All Projects → aspida → Pathpida

aspida / Pathpida

Licence: mit
TypeScript friendly internal link client for Next.js, Nuxt.js and Sapper.

Programming Languages

typescript
32286 projects

Projects that are alternatives of or similar to Pathpida

Mordred
[Experimental] Source data from anywhere, for Next.js, Nuxt.js, Eleventy and many more.
Stars: ✭ 208 (+63.78%)
Mutual labels:  nextjs, nuxtjs
Graphcms Examples
Example projects to help you get started with GraphCMS
Stars: ✭ 295 (+132.28%)
Mutual labels:  nextjs, nuxtjs
Firebase Gcp Examples
🔥 Firebase app architectures, languages, tools & some GCP things! React w Next.js, Svelte w Sapper, Cloud Functions, Cloud Run.
Stars: ✭ 470 (+270.08%)
Mutual labels:  nextjs, nuxtjs
Amazon Next
A simple mock and re-concept of Amazon - built with Next.js, Firebase, and Framer Motion
Stars: ✭ 112 (-11.81%)
Mutual labels:  nextjs
Next Sanity
Sanity.io toolkit for Next.js
Stars: ✭ 115 (-9.45%)
Mutual labels:  nextjs
Next Optimized Images
🌅 next-optimized-images automatically optimizes images used in next.js projects (jpeg, png, svg, webp and gif).
Stars: ✭ 1,870 (+1372.44%)
Mutual labels:  nextjs
Nuxt Helmet
👷 Helmet for Nuxt
Stars: ✭ 126 (-0.79%)
Mutual labels:  nuxtjs
Next Cms Ghost
Publish flaring fast blogs with Next.js and Ghost CMS
Stars: ✭ 107 (-15.75%)
Mutual labels:  nextjs
Nuxt Svg Loader
SVGs as components, also on the server side!
Stars: ✭ 125 (-1.57%)
Mutual labels:  nuxtjs
Mdx Embed
Embed 3rd party media content in MDX - no import required 🧽
Stars: ✭ 119 (-6.3%)
Mutual labels:  nextjs
Nuxt Dev To Clone
Build DEV.TO clone with Nuxt.js and new `fetch` hook
Stars: ✭ 118 (-7.09%)
Mutual labels:  nuxtjs
Zendea
A free, open-source, self-hosted forum software written in Go 官方QQ群:656868
Stars: ✭ 116 (-8.66%)
Mutual labels:  nuxtjs
Gank
🦅 Gank api base △ next.js (react&ssr)
Stars: ✭ 122 (-3.94%)
Mutual labels:  nextjs
Bitwave
Front end for [bitwave.tv] - an open platform live video streaming service
Stars: ✭ 113 (-11.02%)
Mutual labels:  nuxtjs
Contenta vue nuxt
Start in minutes a Drupal 8 with JSON API and Vue.js : a Nuxt.js ( Vue.js SSR ) consumer for Contenta CMS
Stars: ✭ 125 (-1.57%)
Mutual labels:  nuxtjs
Nextjs Headless Wordpress
🔥 Nextjs Headless WordPress
Stars: ✭ 110 (-13.39%)
Mutual labels:  nextjs
Nextjs Pwa Graphql Sql Boilerplate
Next.js serverless PWA with GraphQL (Apollo) + Postgres SQL boilerplate
Stars: ✭ 125 (-1.57%)
Mutual labels:  nextjs
Next Todos
200 lines realtime todos app powered by next.js, preact, jet, redux and now
Stars: ✭ 117 (-7.87%)
Mutual labels:  nextjs
Create Ueno App
The easiest and fastest way to create new web projects with next, gatsby, create-react-app and mobile projects with react-native.
Stars: ✭ 116 (-8.66%)
Mutual labels:  nextjs
Next Redux Wrapper
Redux wrapper for Next.js
Stars: ✭ 1,901 (+1396.85%)
Mutual labels:  nextjs

pathpida


pathpida

TypeScript friendly internal link client for Next.js, Nuxt.js and Sapper.



Features

  • Type safety. Automatically generate type definition files for manipulating internal links in Next.js/Nuxt.js/Sapper.
  • Zero configuration. No configuration required can be used immediately after installation.
  • Zero runtime. Lightweight because runtime code is not included in the bundle.
  • Support for static files. Static files in public/ are also supported, so static assets can be safely referenced.

Table of Contents

Install

  • Using npm:

    $ npm install pathpida npm-run-all --save-dev
    
  • Using Yarn:

    $ yarn add pathpida npm-run-all --dev
    

Setup - Next.js

package.json

{
  "scripts": {
    "dev": "run-p dev:*",
    "dev:next": "next dev",
    "dev:path": "pathpida --watch",
    "build": "pathpida && next build"
  }
}

Usage - Next.js

pages/index.tsx
pages/post/create.tsx
pages/post/[pid].tsx
pages/post/[...slug].tsx

lib/$path.ts or utils/$path.ts // Generated automatically by pathpida

or

src/pages/index.tsx
src/pages/post/create.tsx
src/pages/post/[pid].tsx
src/pages/post/[...slug].tsx

src/lib/$path.ts or src/utils/$path.ts // Generated automatically by pathpida

pages/index.tsx

import Link from 'next/link'
import { pagesPath } from '../lib/$path'

console.log(pagesPath.post.create.$url()) // { pathname: '/post/create' }
console.log(pagesPath.post._pid(1).$url()) // { pathname: '/post/[pid]', query: { pid: 1 }}
console.log(pagesPath.post._slug(['a', 'b', 'c']).$url()) // { pathname: '/post//[...slug]', query: { slug: ['a', 'b', 'c'] }}

export default () => {
  const onClick = useCallback(() => {
    router.push(pagesPath.post._pid(1).$url())
  }, [])

  return <>
    <Link href={pagesPath.post._slug(['a', 'b', 'c']).$url()} />
    <div onClick={onClick} />
  </>
}

Define query - Next.js

pages/post/create.tsx

export type Query = {
  userId: number
  name?: string
}

export default () => <div />

pages/post/[pid].tsx

export type OptionalQuery = {
  limit: number
  label?: string
}

export default () => <div />

pages/index.tsx

import Link from 'next/link'
import { pagesPath } from '../lib/$path'

console.log(pagesPath.post.create.$url({ query: { userId: 1 }})) // { pathname: '/post/create', query: { userId: 1 }}
console.log(pagesPath.post.create.$url()) // type error
console.log(pagesPath.post._pid(1).$url()) // { pathname: '/post/[pid]', query: { pid: 1 }}
console.log(pagesPath.post._pid(1).$url({ query: { limit: 10 }, hash: 'sample' })) // { pathname: '/post/[pid]', query: { pid: 1, limit: 10 }, hash: 'sample' }

export default () => {
  const onClick = useCallback(() => {
    router.push(pagesPath.post._pid(1).$url())
  }, [])

  return <>
    <Link href={pagesPath.post._slug(['a', 'b', 'c']).$url()} />
    <div onClick={onClick} />
  </>
}

Generate static files path - Next.js

package.json

{
  "scripts": {
    "dev": "run-p dev:*",
    "dev:next": "next dev",
    "dev:path": "pathpida --enableStatic --watch",
    "build": "pathpida --enableStatic && next build"
  }
}
pages/index.tsx
pages/post/create.tsx
pages/post/[pid].tsx
pages/post/[...slug].tsx

public/aa.json
public/bb/cc.png

lib/$path.ts or utils/$path.ts // Generated automatically by pathpida

or

src/pages/index.tsx
src/pages/post/create.tsx
src/pages/post/[pid].tsx
src/pages/post/[...slug].tsx

public/aa.json
public/bb/cc.png

src/lib/$path.ts or src/utils/$path.ts // Generated automatically by pathpida

pages/index.tsx

import Link from 'next/link'
import { pagesPath, staticPath } from '../lib/$path'

console.log(staticPath.aa_json) // /aa.json

export default () => {
  return <>
    <Link href={pagesPath.post._slug(['a', 'b', 'c']).$url()} />
    <img src={staticPath.bb.cc_png} />
  </>
}

Setup - Nuxt.js

package.json

{
  "scripts": {
    "dev": "run-p dev:*",
    "dev:nuxt": "nuxt-ts",
    "dev:path": "pathpida --watch",
    "build": "pathpida && nuxt-ts build"
  }
}

nuxt.config.js or nuxt.config.ts

{
  plugins: ['~/plugins/$path'],
  srcDir: 'client', // optional
  router: {
    trailingSlash: true // optional
  }
}

Usage - Nuxt.js

pages/index.vue
pages/post/create.vue
pages/post/_pid.tsx

plugins/$path.ts // Generated automatically by pathpida

pages/index.vue

<template>
  <div>
    <nuxt-link :to="$pagesPath.post._pid(1).$url()" />
    <div @click="onClick" />
  </div>
</template>

<script lang="ts">
import Vue from 'vue'

export default Vue.extend({
  methods: {
    onClick() {
      this.$router.push(this.$pagesPath.post._pid(1).$url())
    }
  }
})
</script>

Define query - Nuxt.js

pages/post/create.vue

<script lang="ts">
import Vue from 'vue'

export type Query = {
  userId: number
  name?: string
}

export default Vue.extend({
})
</script>

pages/post/_pid.vue

<script lang="ts">
import Vue from 'vue'

export type OptionalQuery = {
  limit: number
  label?: string
}

export default Vue.extend({
})
</script>

pages/index.vue

<template>
  <div>
    <nuxt-link :to="$pagesPath.post.create.$url({ query: { userId: 1 }})" />
    <div @click="onClick" />
  </div>
</template>

<script lang="ts">
import Vue from 'vue'

export default Vue.extend({
  methods: {
    onClick() {
      this.$router.push(this.$pagesPath.post._pid(1).$url())
      this.$router.push(this.$pagesPath.post._pid(1).$url({ query: { limit: 10 }, hash: 'sample' }))
    }
  }
})
</script>

⚠️ In the case of .vue file, Query/OptionalQuery type must not contain any reference types.

This is because due to typescript restrictions, types exported from .vue files cannot be imported in plugins/$path.ts. If you want to import types from other files, please use import types with absolute paths.

types/users.ts

export type UserId = number

pages/post/create.vue

<script lang="ts">
import Vue from 'vue'

export type Query = {
  userId: import('~/types/users').UserId
  name?: string
}

export default Vue.extend({
})
</script>

Generate static files path - Nuxt.js

package.json

{
  "scripts": {
    "dev": "run-p dev:*",
    "dev:nuxt": "nuxt-ts",
    "dev:path": "pathpida --enableStatic --watch",
    "build": "pathpida --enableStatic && nuxt-ts build"
  }
}
pages/index.vue
pages/post/create.vue
pages/post/_pid.vue

static/aa.json
static/bb/cc.png

plugins/$path.ts // Generated automatically by pathpida

pages/index.vue

<template>
  <div>
    <nuxt-link :to="$pagesPath.post.create.$url({ query: { userId: 1 }})" />
    <img :src="$staticPath.bb.cc_png" />
  </div>
</template>

<script lang="ts">
import Vue from 'vue'

export default Vue.extend({})
</script>

Setup - Sapper

package.json

{
  "scripts": {
    "dev": "run-p dev:*",
    "dev:sapper": "sapper dev",
    "dev:path": "pathpida --watch",
    "build": "pathpida && sapper build --legacy",
    "export": "pathpida && sapper export --legacy"
  }
}

Usage - Sapper

src/routes/blog/[slug].json.ts
src/routes/blog/[slug].svelte
src/routes/blog/index.json.js
src/routes/blog/index.svelte

src/node_modules/$path.ts // Generated automatically by pathpida

src/routes/blog/index.svelte

<script context="module" lang="ts">
  import { pagesPath } from '$path'

  export function preload() {
    return this.fetch(pagesPath.blog_json.$url()).then((r: { json: () => any; }) => r.json()).then((posts: { slug: string; title: string, html: any }[]) => {
      return { posts };
    });
  }
</script>

<script lang="ts">
  export let posts: { slug: string; title: string, html: any }[];
</script>

<ul>
  {#each posts as post}
    <li><a rel="prefetch" href="{pagesPath.blog._slug(post.slug).$url()}">{post.title}</a></li>
  {/each}
</ul>

Define query - Sapper

src/routes/blog/[slug].json.ts

import posts from './_posts.js';

export type Query = { // or OptionalQuery
  id: number
}

const lookup = new Map();
posts.forEach(post => {
  lookup.set(post.slug, JSON.stringify(post));
});

src/routes/blog/[slug].svelte

<script context="module" lang="ts">
  import { pagesPath } from '$path'

  export async function preload({ params }) {
    const res = await this.fetch(pagesPath.blog._slug_json(params.slug).$url({ query: { id: 1 }}));
    const data = await res.json();

    if (res.status === 200) {
      return { post: data };
    } else {
      this.error(res.status, data.message);
    }
  }
</script>

⚠️ In the case of .svelte file, Query/OptionalQuery type must not contain any reference types.

This is because due to typescript restrictions, types exported from .svelte files cannot be imported in src/node_modules/$path.ts. If you want to import types from other files, please use import types with absolute paths.

src/node_modules/types/users.ts

export type UserId = number

src/routes/blog/[slug].json.ts

import posts from './_posts.js';

export type Query = {
  id: import('types/users').UserId
}

const lookup = new Map();
posts.forEach(post => {
  lookup.set(post.slug, JSON.stringify(post));
});

Generate static files path - Sapper

package.json

{
  "scripts": {
    "dev": "run-p dev:*",
    "dev:sapper": "sapper dev",
    "dev:path": "pathpida --enableStatic --watch",
    "build": "pathpida --enableStatic && sapper build --legacy",
    "export": "pathpida --enableStatic && sapper export --legacy"
  }
}
src/routes/index.svelte
static/logo-512.png

src/node_modules/$path.ts // Generated automatically by pathpida

src/routes/index.svelte

<script>
  import { staticPath } from '$path';
</script>

<figure>
  <img alt="Logo" src="{staticPath.logo_512_png}">
</figure>

License

pathpida is licensed under a MIT License.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].