nuxt-typed-router 1.0.2 → 1.1.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -77,16 +77,22 @@ interface ModuleOptions {
77
77
 
78
78
  # Generated files
79
79
 
80
- The module will create 2 files:
80
+ The module will generate 4 files each time you modify the `pages` folder :
81
81
 
82
- - `__routes.ts` with the global object of the route names inside.
83
- - `typed-router.d.ts` containing the global typecript definitions and exports
82
+ - `~/<outDir>/__routes.ts` with the global object of the route names inside.
83
+ - `~/<outDir>/__useTypedRouter` Composable tu simply access your typed routes
84
+ - `~/<outDir>/typed-router.d.ts` containing the global typecript definitions and exports
85
+ - `~/plugins/__typed_router.ts` Plugin that will inject `$typedRouter` and `$routesList` (`@nuxt/kit` has problems registering plugin templates so this is a workaround)
84
86
 
85
87
  # Usage in Vue/Nuxt
86
88
 
89
+ ## Check out this demo and clone it! [nuxt-typed-router-demo](https://github.com/victorgarciaesgi/nuxt-typed-router-demo)
90
+
91
+ <br/>
92
+
87
93
  ### **_Requirements_**
88
94
 
89
- You have to specify the output dir of the generated files in your configuration
95
+ You can specify the output dir of the generated files in your configuration. It defaults to `<srcDir>/generated`
90
96
 
91
97
  ```ts
92
98
  import TypedRouter from 'nuxt-typed-router';
@@ -146,13 +152,16 @@ export type TypedRouteList =
146
152
  | 'index-user';
147
153
  ```
148
154
 
155
+ > nuxt-typed-router will also create a plugin in your `<srcDir>/plugins` folder with the injected `$typedRouter` and `$routesList` helpers
156
+
149
157
  # Usage with `useTypedRouter` hook
150
158
 
151
159
  `useTypedRouter` is an exported composable from nuxt-typed-router. It contains a clone of `vue-router` but with stritly typed route names and params type-check
152
160
 
153
161
  ```vue
154
162
  <script lang="ts">
155
- import { useTypedRouter } from 'nuxt-typed-router/hook';
163
+ // The path here is `~/generated` because I set `outDir: './generated'` in my module options
164
+ import { useTypedRouter } from '~/generated';
156
165
 
157
166
  export default defineComponent({
158
167
  setup() {
@@ -171,7 +180,7 @@ export default defineComponent({
171
180
  </script>
172
181
  ```
173
182
 
174
- # Usage with `$typedRouter` injected method
183
+ # Usage with `$typedRouter` and `$routesList` injected helpers
175
184
 
176
185
  `$typedRouter` is an injected clone of vue-router `$router`, but fully typed with all your routes.
177
186
  It's available anywhere you have access to Nuxt context
@@ -183,10 +192,10 @@ import { defineComponent } from 'vue';
183
192
  export default defineComponent({
184
193
  name: 'Index',
185
194
  setup() {
186
- const { $typedRouter } = useNuxtApp();
195
+ const { $typedRouter, $routesList } = useNuxtApp();
187
196
 
188
197
  function navigate() {
189
- $typedRouter.push({ name: 'activate' });
198
+ $typedRouter.push({ name: $routesList.activate });
190
199
  }
191
200
 
192
201
  return {
@@ -197,6 +206,25 @@ export default defineComponent({
197
206
  </script>
198
207
  ```
199
208
 
209
+ # Usage outside Vue component
210
+
211
+ You can import the `useTypedRouter` composable from where it's generated.
212
+ Exemple with `pinia` store here
213
+
214
+ ```ts
215
+ import pinia from 'pinia';
216
+ import { useTypedRouter } from '~/generated';
217
+
218
+ export const useFooStore = defineStore('foo', {
219
+ actions: {
220
+ bar() {
221
+ const { router, routes } = useTypedRouter();
222
+ router.push({ name: routes.index.user, params: { user: 2 } });
223
+ },
224
+ },
225
+ });
226
+ ```
227
+
200
228
  ## Development
201
229
 
202
230
  1. Clone this repository
package/dist/module.json CHANGED
@@ -5,5 +5,5 @@
5
5
  "nuxt": "^3.0.0",
6
6
  "bridge": false
7
7
  },
8
- "version": "1.0.2"
8
+ "version": "1.1.0-beta.0"
9
9
  }
package/dist/module.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { extendPages, addPluginTemplate, defineNuxtModule } from '@nuxt/kit';
1
+ import { extendPages, defineNuxtModule } from '@nuxt/kit';
2
2
  import { fileURLToPath } from 'url';
3
3
  import chalk from 'chalk';
4
4
  import logSymbols from 'log-symbols';
@@ -192,8 +192,12 @@ function walkThoughRoutes({
192
192
  }
193
193
 
194
194
  const signatureTemplate = `/**
195
- * Generated by nuxt-typed-router. Do not modify
196
- * */`;
195
+ * ---------------------
196
+ * \u{1F697}\u{1F6A6} Generated by nuxt-typed-router. Do not modify !
197
+ * ---------------------
198
+ * */
199
+
200
+ `;
197
201
  const staticDeclImports = `
198
202
  import type {
199
203
  NavigationFailure,
@@ -288,18 +292,11 @@ const staticDeclarations = `
288
292
  $routesList: RouteListDecl;
289
293
  }
290
294
  }
291
- declare module 'nuxt-typed-router/hook' {
292
- declare const useTypedRouter: () => {
293
- /** Export of $router with type check */
294
- router: TypedRouter,
295
- /** Contains a typed dictionnary of all your route names (for syntax sugar) */
296
- routes: RouteListDecl
297
- };
298
- }
299
295
  `;
300
296
 
301
297
  function createRuntimePluginFile(routesDeclTemplate) {
302
298
  return `
299
+ ${signatureTemplate}
303
300
  import { defineNuxtPlugin } from '#app';
304
301
 
305
302
  export default defineNuxtPlugin((nuxtApp) => {
@@ -307,7 +304,7 @@ function createRuntimePluginFile(routesDeclTemplate) {
307
304
 
308
305
  return {
309
306
  provide: {
310
- typedRouter: nuxtApp.vueApp.$router,
307
+ typedRouter: nuxtApp.$router,
311
308
  routesList,
312
309
  },
313
310
  };
@@ -316,17 +313,22 @@ function createRuntimePluginFile(routesDeclTemplate) {
316
313
  }
317
314
  function createRuntimeHookFile(routesDeclTemplate) {
318
315
  return `
316
+ ${signatureTemplate}
319
317
  import { getCurrentInstance } from 'vue';
318
+ import { useNuxtApp } from '#app';
320
319
 
321
- function useNuxtApp() {
322
- const vm = getCurrentInstance();
323
- if (!vm) {
324
- throw new Error('nuxt instance unavailable');
325
- }
326
- return vm.appContext.app.$nuxt;
327
- }
328
-
329
- export const useTypedRouter = () => {
320
+ /** Returns instances of $typedRouter and $routesList fully typed to use in your components or your Vuex/Pinia store
321
+ *
322
+ * @exemple
323
+ *
324
+ * const { router, routes } = useTypedRouter();
325
+ */
326
+ export const useTypedRouter = (): {
327
+ /** Export of $router with type check */
328
+ router: TypedRouter,
329
+ /** Contains a typed dictionnary of all your route names (for syntax sugar) */
330
+ routes: RouteListDecl
331
+ } => {
330
332
  const { $router } = useNuxtApp();
331
333
 
332
334
  const routesList = ${routesDeclTemplate};
@@ -334,11 +336,18 @@ function createRuntimeHookFile(routesDeclTemplate) {
334
336
  return {
335
337
  router: $router,
336
338
  routes: routesList,
337
- };
339
+ } as any;
338
340
  };
339
341
 
340
342
  `;
341
343
  }
344
+ function createRuntimeIndexFile() {
345
+ return `
346
+ ${signatureTemplate}
347
+ export * from './__routes';
348
+ export * from './__useTypedRouter';
349
+ `;
350
+ }
342
351
  function createRuntimeRoutesFile({
343
352
  routesList,
344
353
  routesObjectTemplate,
@@ -380,27 +389,28 @@ function createTypedRouteParamsExport(routesParams) {
380
389
  }
381
390
 
382
391
  const __dirname = dirname(fileURLToPath(import.meta.url));
383
- function routeHook(outDir, routesObjectName) {
392
+ function routeHook(outDir, routesObjectName, srcDir, nuxt) {
384
393
  try {
385
394
  extendPages(async (routes) => {
386
- const { routesDeclTemplate, routesList, routesObjectTemplate, routesParams } = constructRouteMap(routes);
387
- const pluginName = "typed-router.mjs";
388
- const runtimeDir = resolve(__dirname, process.env.NUXT_BUILD_TYPE === "stub" ? "../../dist/runtime" : "./runtime");
389
- const pluginPath = resolve(runtimeDir, pluginName);
390
- await Promise.all([
391
- saveRouteFiles(runtimeDir, "useTypedRouter.mjs", createRuntimeHookFile(routesDeclTemplate)),
392
- saveRouteFiles(runtimeDir, pluginName, createRuntimePluginFile(routesDeclTemplate))
393
- ]);
394
- addPluginTemplate({
395
- src: pluginPath,
396
- filename: pluginName,
397
- options: {
398
- routesList: "test"
399
- }
400
- });
401
- await saveRouteFiles(outDir, `__routes.ts`, createRuntimeRoutesFile({ routesList, routesObjectTemplate, routesObjectName }));
402
- await saveRouteFiles(outDir, `typed-router.d.ts`, createDeclarationRoutesFile({ routesDeclTemplate, routesList, routesParams }));
403
- console.log(logSymbols.success, `[typed-router] Routes definitions generated`);
395
+ if (routes.length) {
396
+ const { routesDeclTemplate, routesList, routesObjectTemplate, routesParams } = constructRouteMap(routes);
397
+ const pluginName = "__typed-router.ts";
398
+ const runtimeDir = resolve(__dirname, process.env.NUXT_BUILD_TYPE === "stub" ? "../../dist/runtime" : "./runtime");
399
+ const pluginPath = resolve(runtimeDir, pluginName);
400
+ nuxt.hook("build:done", async () => {
401
+ const pluginFolder = `${srcDir}/plugins`;
402
+ await saveRouteFiles(pluginFolder, pluginName, createRuntimePluginFile(routesDeclTemplate));
403
+ });
404
+ await Promise.all([
405
+ saveRouteFiles(outDir, "__useTypedRouter.ts", createRuntimeHookFile(routesDeclTemplate)),
406
+ saveRouteFiles(outDir, `__routes.ts`, createRuntimeRoutesFile({ routesList, routesObjectTemplate, routesObjectName })),
407
+ saveRouteFiles(outDir, `typed-router.d.ts`, createDeclarationRoutesFile({ routesDeclTemplate, routesList, routesParams })),
408
+ saveRouteFiles(outDir, "index.ts", createRuntimeIndexFile())
409
+ ]);
410
+ console.log(logSymbols.success, `[typed-router] Routes definitions generated`);
411
+ } else {
412
+ console.log(logSymbols.warning, chalk.yellow(`[typed-router] No routes defined. Check if your ${chalk.underline(chalk.bold("pages"))} folder exists and remove ${chalk.underline(chalk.bold("app.vue"))}`));
413
+ }
404
414
  });
405
415
  } catch (e) {
406
416
  console.error(chalk.red("Error while generating routes definitions model"), "\n" + e);
@@ -418,10 +428,10 @@ const module = defineNuxtModule({
418
428
  stripAtFromName: false
419
429
  },
420
430
  setup(moduleOptions, nuxt) {
421
- const { outDir = `${nuxt.options.srcDir}/generated`, routesObjectName } = moduleOptions;
422
- nuxt.hook("pages:extend", () => routeHook(outDir, routesObjectName));
423
- nuxt.hook("build:extendRoutes", () => routeHook(outDir, routesObjectName));
424
- routeHook(outDir, routesObjectName);
431
+ const srcDir = nuxt.options.srcDir;
432
+ const { outDir = `${srcDir}/generated`, routesObjectName } = moduleOptions;
433
+ nuxt.hook("pages:extend", () => routeHook(outDir, routesObjectName, srcDir, nuxt));
434
+ routeHook(outDir, routesObjectName, srcDir, nuxt);
425
435
  }
426
436
  });
427
437
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-typed-router",
3
- "version": "1.0.2",
3
+ "version": "1.1.0-beta.0",
4
4
  "description": "Provide autocompletion for pages route names generated by Nuxt router",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -17,18 +17,13 @@
17
17
  ".": {
18
18
  "import": "./dist/module.mjs",
19
19
  "require": "./dist/module.cjs"
20
- },
21
- "./hook": {
22
- "import": "./hook.mjs"
23
20
  }
24
21
  },
25
22
  "main": "./dist/module.cjs",
26
23
  "types": "./main.d.ts",
27
24
  "files": [
28
25
  "dist",
29
- "main.d.ts",
30
- "hook.mjs",
31
- "hook.d.ts"
26
+ "main.d.ts"
32
27
  ],
33
28
  "publishConfig": {
34
29
  "access": "public"
@@ -1 +0,0 @@
1
- export { useTypedRouter } from './useTypedRouter';
@@ -1 +0,0 @@
1
- export { useTypedRouter } from "./useTypedRouter.mjs";
@@ -1,34 +0,0 @@
1
- import { defineNuxtPlugin } from '#app';
2
-
3
- export default defineNuxtPlugin((nuxtApp) => {
4
- const routesList = {
5
- activate: 'activate',
6
- index: 'index',
7
- childOne: {
8
- childOneChildOneSubOne: 'parent-child-one-child-one-sub-one',
9
- user: { index: 'parent-child-one-child-one-sub-one-user' },
10
- childOneChildOneSubTwo: 'parent-child-one-child-one-sub-two',
11
- index: 'parent-child-one',
12
- },
13
- childTwo: {
14
- childTwoId: 'parent-child-two-id',
15
- childTwoChildOneSubOne: 'parent-child-two-child-one-sub-one',
16
- index: 'parent-child-two',
17
- profile: {
18
- id: {
19
- slug: { index: 'parent-child-two-profile-id-slug' },
20
- index: 'parent-child-two-profile-id',
21
- },
22
- index: 'parent-child-two-profile',
23
- },
24
- },
25
- rootPage: 'rootPage',
26
- };
27
-
28
- return {
29
- provide: {
30
- typedRouter: nuxtApp.vueApp.$router,
31
- routesList,
32
- },
33
- };
34
- });
@@ -1,34 +0,0 @@
1
- import { defineNuxtPlugin } from '#app';
2
-
3
- export default defineNuxtPlugin((nuxtApp) => {
4
- const routesList = {
5
- activate: 'activate',
6
- index: 'index',
7
- childOne: {
8
- childOneChildOneSubOne: 'parent-child-one-child-one-sub-one',
9
- user: { index: 'parent-child-one-child-one-sub-one-user' },
10
- childOneChildOneSubTwo: 'parent-child-one-child-one-sub-two',
11
- index: 'parent-child-one',
12
- },
13
- childTwo: {
14
- childTwoId: 'parent-child-two-id',
15
- childTwoChildOneSubOne: 'parent-child-two-child-one-sub-one',
16
- index: 'parent-child-two',
17
- profile: {
18
- id: {
19
- slug: { index: 'parent-child-two-profile-id-slug' },
20
- index: 'parent-child-two-profile-id',
21
- },
22
- index: 'parent-child-two-profile',
23
- },
24
- },
25
- rootPage: 'rootPage',
26
- };
27
-
28
- return {
29
- provide: {
30
- typedRouter: nuxtApp.vueApp.$router,
31
- routesList,
32
- },
33
- };
34
- });
@@ -1,42 +0,0 @@
1
- import { getCurrentInstance } from 'vue';
2
-
3
- function useNuxtApp() {
4
- const vm = getCurrentInstance();
5
- if (!vm) {
6
- throw new Error('nuxt instance unavailable');
7
- }
8
- return vm.appContext.app.$nuxt;
9
- }
10
-
11
- export const useTypedRouter = () => {
12
- const { $router } = useNuxtApp();
13
-
14
- const routesList = {
15
- activate: 'activate',
16
- index: 'index',
17
- childOne: {
18
- childOneChildOneSubOne: 'parent-child-one-child-one-sub-one',
19
- user: { index: 'parent-child-one-child-one-sub-one-user' },
20
- childOneChildOneSubTwo: 'parent-child-one-child-one-sub-two',
21
- index: 'parent-child-one',
22
- },
23
- childTwo: {
24
- childTwoId: 'parent-child-two-id',
25
- childTwoChildOneSubOne: 'parent-child-two-child-one-sub-one',
26
- index: 'parent-child-two',
27
- profile: {
28
- id: {
29
- slug: { index: 'parent-child-two-profile-id-slug' },
30
- index: 'parent-child-two-profile-id',
31
- },
32
- index: 'parent-child-two-profile',
33
- },
34
- },
35
- rootPage: 'rootPage',
36
- };
37
-
38
- return {
39
- router: $router,
40
- routes: routesList,
41
- };
42
- };
@@ -1,42 +0,0 @@
1
- import { getCurrentInstance } from 'vue';
2
-
3
- function useNuxtApp() {
4
- const vm = getCurrentInstance();
5
- if (!vm) {
6
- throw new Error('nuxt instance unavailable');
7
- }
8
- return vm.appContext.app.$nuxt;
9
- }
10
-
11
- export const useTypedRouter = () => {
12
- const { $router } = useNuxtApp();
13
-
14
- const routesList = {
15
- activate: 'activate',
16
- index: 'index',
17
- childOne: {
18
- childOneChildOneSubOne: 'parent-child-one-child-one-sub-one',
19
- user: { index: 'parent-child-one-child-one-sub-one-user' },
20
- childOneChildOneSubTwo: 'parent-child-one-child-one-sub-two',
21
- index: 'parent-child-one',
22
- },
23
- childTwo: {
24
- childTwoId: 'parent-child-two-id',
25
- childTwoChildOneSubOne: 'parent-child-two-child-one-sub-one',
26
- index: 'parent-child-two',
27
- profile: {
28
- id: {
29
- slug: { index: 'parent-child-two-profile-id-slug' },
30
- index: 'parent-child-two-profile-id',
31
- },
32
- index: 'parent-child-two-profile',
33
- },
34
- },
35
- rootPage: 'rootPage',
36
- };
37
-
38
- return {
39
- router: $router,
40
- routes: routesList,
41
- };
42
- };
package/hook.d.ts DELETED
@@ -1,4 +0,0 @@
1
- /** @deprecated Do not import or use. Dummy export to fool Typescript into thinking it's a module */
2
- declare const doNotImportItsToFoolTypescript = 'foo';
3
-
4
- export { doNotImportItsToFoolTypescript };
package/hook.mjs DELETED
@@ -1 +0,0 @@
1
- export { useTypedRouter } from './dist/runtime/useTypedRouter.mjs';