nuxt-typed-router 3.3.2 → 3.4.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
@@ -60,8 +60,6 @@ Demo repo 🧪 : [nuxt-typed-router-demo](https://github.com/victorgarciaesgi/nu
60
60
  # Compatibility:
61
61
 
62
62
  - Nuxt 3
63
- - Nuxt 2 (via [`nuxt2` branch](https://github.com/victorgarciaesgi/nuxt-typed-router/tree/nuxt2))
64
-
65
63
 
66
64
 
67
65
  # Quick start
@@ -76,16 +74,6 @@ npm install -D nuxt-typed-router
76
74
  pnpm install -D nuxt-typed-router
77
75
  ```
78
76
 
79
- ### Nuxt 2 legacy (not maintained)
80
-
81
- Nuxt 2 version is no longer maintained, but still available in [`nuxt2` branch](https://github.com/victorgarciaesgi/nuxt-typed-router/tree/nuxt2)
82
- It only has route name autocomplete functionnality
83
-
84
- ```bash
85
- yarn add -D nuxt-typed-router@legacy
86
- # or
87
- npm install -D nuxt-typed-router@legacy
88
- ```
89
77
 
90
78
  # Configuration
91
79
  Register the module in the `nuxt.config.ts`, done!
package/dist/module.d.mts CHANGED
@@ -27,14 +27,14 @@ interface ModuleOptions {
27
27
  * Remove Nuxt definitions to avoid conflicts
28
28
  * @default true
29
29
  */
30
- experimentalRemoveNuxtDefs?: boolean;
30
+ removeNuxtDefs?: boolean;
31
31
  /**
32
32
  * ⚠️ Experimental
33
33
  *
34
34
  * Exclude certain routes from being included into the generated types
35
35
  * Ex: 404 routes or catchAll routes
36
36
  */
37
- experimentalIgnoreRoutes?: string[];
37
+ ignoreRoutes?: string[];
38
38
  }
39
39
  interface StrictOptions {
40
40
  NuxtLink?: StrictParamsOptions;
package/dist/module.d.ts CHANGED
@@ -27,14 +27,14 @@ interface ModuleOptions {
27
27
  * Remove Nuxt definitions to avoid conflicts
28
28
  * @default true
29
29
  */
30
- experimentalRemoveNuxtDefs?: boolean;
30
+ removeNuxtDefs?: boolean;
31
31
  /**
32
32
  * ⚠️ Experimental
33
33
  *
34
34
  * Exclude certain routes from being included into the generated types
35
35
  * Ex: 404 routes or catchAll routes
36
36
  */
37
- experimentalIgnoreRoutes?: string[];
37
+ ignoreRoutes?: string[];
38
38
  }
39
39
  interface StrictOptions {
40
40
  NuxtLink?: StrictParamsOptions;
package/dist/module.json CHANGED
@@ -5,5 +5,5 @@
5
5
  "nuxt": "^3.0.0",
6
6
  "bridge": false
7
7
  },
8
- "version": "3.3.2"
8
+ "version": "3.4.0"
9
9
  }
package/dist/module.mjs CHANGED
@@ -12,27 +12,19 @@ import { mkdirp } from 'mkdirp';
12
12
  import { camelCase } from 'lodash-es';
13
13
  import { readFile } from 'fs/promises';
14
14
 
15
- var __defProp = Object.defineProperty;
16
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
17
- var __publicField = (obj, key, value) => {
18
- __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
19
- return value;
20
- };
21
15
  class ModuleOptionsStore {
22
- constructor() {
23
- __publicField(this, "plugin", false);
24
- __publicField(this, "strict", false);
25
- __publicField(this, "pathCheck", true);
26
- __publicField(this, "autoImport", false);
27
- __publicField(this, "rootDir", "");
28
- __publicField(this, "buildDir", "");
29
- __publicField(this, "srcDir", "");
30
- __publicField(this, "pagesDir", "");
31
- __publicField(this, "i18n", false);
32
- __publicField(this, "i18nOptions", null);
33
- __publicField(this, "i18nLocales", []);
34
- __publicField(this, "experimentalIgnoreRoutes", []);
35
- }
16
+ plugin = false;
17
+ strict = false;
18
+ pathCheck = true;
19
+ autoImport = false;
20
+ rootDir = "";
21
+ buildDir = "";
22
+ srcDir = "";
23
+ pagesDir = "";
24
+ i18n = false;
25
+ i18nOptions = null;
26
+ i18nLocales = [];
27
+ ignoreRoutes = [];
36
28
  updateOptions(options) {
37
29
  if (options.plugin != null)
38
30
  this.plugin = options.plugin;
@@ -66,12 +58,12 @@ class ModuleOptionsStore {
66
58
  if (options.pathCheck != null) {
67
59
  this.pathCheck = options.pathCheck;
68
60
  }
69
- if (options.experimentalIgnoreRoutes) {
70
- this.experimentalIgnoreRoutes = options.experimentalIgnoreRoutes;
61
+ if (options.ignoreRoutes) {
62
+ this.ignoreRoutes = options.ignoreRoutes;
71
63
  }
72
64
  }
73
65
  get resolvedIgnoredRoutes() {
74
- return this.experimentalIgnoreRoutes.map((file) => path.join(this.pagesDir, file));
66
+ return this.ignoreRoutes.map((file) => path.join(this.pagesDir, file));
75
67
  }
76
68
  getResolvedStrictOptions() {
77
69
  let resolved;
@@ -220,7 +212,7 @@ function createLocaleRoutePathSchema(routePaths) {
220
212
  ${routePaths.filter((f) => !!f.path && !f.isLocale).map((route) => `"${route.path}"`).join("|")}
221
213
  `;
222
214
  }
223
- function createValidatePathTypes(pathElements, withLocale = false) {
215
+ function createValidatePathTypes(pathElements, routesList, withLocale = false) {
224
216
  let pathConditions = pathElements.map(createTypeValidatePathCondition).filter((f) => {
225
217
  if (withLocale) {
226
218
  return !f.isLocale;
@@ -243,14 +235,14 @@ function createValidatePathTypes(pathElements, withLocale = false) {
243
235
  : ${pathConditions.length ? `\`Error: \${${pathConditions.map((t) => `${t.typeName}<T>`).join("|")}}\`` : "never"}
244
236
  : never;
245
237
 
246
-
238
+ // RouteNameFromPath, RouteNameFromLocalePath
247
239
  export type RouteNameFrom${returnIfTrue(
248
240
  withLocale,
249
241
  "Locale"
250
242
  )}Path<T extends string> = T extends string
251
243
  ? T extends '/'
252
244
  ? "index"
253
- ${pathConditions.length ? `: ${pathConditions.map((t) => `${t.typeName}<T> extends true ? "${t.routeName}"`).join(": ")} : never` : ": never"}
245
+ ${pathConditions.length ? `: ${pathConditions.filter((f) => routesList.includes(f.routeName)).map((t) => `${t.typeName}<T> extends true ? "${t.routeName}"`).join(": ")} : never` : ": never"}
254
246
  : never;
255
247
 
256
248
  `;
@@ -366,6 +358,19 @@ function createTypedRouterFile() {
366
358
 
367
359
  // - Routes location for navigation types (ex: router.push or navigateTo)
368
360
 
361
+
362
+ export type NuxtRoute<T extends RoutesNamesList, P extends string, E extends boolean = false> =
363
+ | TypedRouteLocationRawFromName<T, P>
364
+ ${returnIfTrue(!pathCheck && !strictOptions.NuxtLink.strictToArgument, ` | string`)}
365
+ ${returnIfTrue(
366
+ pathCheck && strictOptions.NuxtLink.strictToArgument,
367
+ ` | (E extends true ? string : never)`
368
+ )}
369
+ ${returnIfTrue(
370
+ pathCheck && !strictOptions.NuxtLink.strictToArgument,
371
+ ` | (E extends true ? string : TypedPathParameter<P>)`
372
+ )}
373
+
369
374
  /**
370
375
  * RouteLocationRaw with discrimanated name and params properties
371
376
  * {@link RouteLocationRaw}
@@ -468,22 +473,14 @@ function createTypedRouterFile() {
468
473
  *
469
474
  * @param to - Route location to navigate to
470
475
  */
471
- push<T extends RoutesNamesList, P extends string>(to: TypedRouteLocationRawFromName<T, P>): Promise<NavigationFailure | void | undefined>;
472
- ${returnIfTrue(
473
- pathCheck && !strictOptions.router.strictToArgument,
474
- `push<T extends string>(to: TypedPathParameter<T>): Promise<NavigationFailure | void | undefined>;`
475
- )}
476
+ push<T extends RoutesNamesList, P extends string>(to: NuxtRoute<T, P>): Promise<NavigationFailure | void | undefined>;
476
477
  /**
477
478
  * Programmatically navigate to a new URL by replacing the current entry in
478
479
  * the history stack.
479
480
  *
480
481
  * @param to - Route location to navigate to
481
482
  */
482
- replace<T extends RoutesNamesList, P extends string>(to: TypedRouteLocationRawFromName<T, P>): Promise<NavigationFailure | void | undefined>;
483
- ${returnIfTrue(
484
- pathCheck && !strictOptions.router.strictToArgument,
485
- `replace<T extends string>(to: TypedPathParameter<T>): Promise<NavigationFailure | void | undefined>;`
486
- )}
483
+ replace<T extends RoutesNamesList, P extends string>(to: NuxtRoute<T, P>): Promise<NavigationFailure | void | undefined>;
487
484
  }
488
485
 
489
486
 
@@ -528,23 +525,25 @@ function createTypedRouterFile() {
528
525
  }
529
526
 
530
527
  function createTypedRouterDefinitionFile() {
531
- const strictOptions = moduleOptionStore.getResolvedStrictOptions();
528
+ moduleOptionStore.getResolvedStrictOptions();
532
529
  const { plugin, autoImport, i18n, pathCheck } = moduleOptionStore;
533
530
  return (
534
531
  /* typescript */
535
532
  `
536
533
 
537
- import type { NuxtLinkProps, PageMeta } from '#app';
534
+ import type { NuxtLinkProps, PageMeta } from 'nuxt/app';
538
535
  import NuxtLink from 'nuxt/dist/app/components/nuxt-link';
539
536
  import type { RouteLocationRaw, RouteLocationPathRaw } from 'vue-router';
540
537
  import type { RoutesNamedLocations, RoutesNamesListRecord, RoutesNamesList } from './__routes';
541
- import type {TypedRouter, TypedRoute, TypedRouteLocationRawFromName, TypedLocationAsRelativeRaw} from './__router';
538
+ import type {TypedRouter, TypedRoute, TypedRouteLocationRawFromName, TypedLocationAsRelativeRaw, NuxtRoute} from './__router';
542
539
  import { useRoute as _useRoute } from './__useTypedRoute';
543
540
  import { useRouter as _useRouter } from './__useTypedRouter';
541
+ import { useLink as _useLink } from './__useTypedLink';
544
542
  import { navigateTo as _navigateTo } from './__navigateTo';
545
543
  ${returnIfTrue(
546
544
  i18n,
547
- `import { useLocalePath as _useLocalePath, useLocaleRoute as _useLocaleRoute} from './__i18n-router';`
545
+ `import { useLocalePath as _useLocalePath, useLocaleRoute as _useLocaleRoute} from './__i18n-router';
546
+ import type {TypedNuxtLinkLocale} from './__NuxtLinkLocale'`
548
547
  )}
549
548
 
550
549
  import {definePageMeta as _definePageMeta} from './__definePageMeta';
@@ -560,6 +559,7 @@ function createTypedRouterDefinitionFile() {
560
559
  `
561
560
  const useRoute: typeof _useRoute;
562
561
  const useRouter: typeof _useRouter;
562
+ const useLink: typeof _useLink;
563
563
  const navigateTo: typeof _navigateTo;
564
564
  const definePageMeta: typeof _definePageMeta;
565
565
 
@@ -575,40 +575,28 @@ function createTypedRouterDefinitionFile() {
575
575
  )}
576
576
  }
577
577
 
578
- type TypedNuxtLinkProps<T extends string, E extends boolean = false> = Omit<NuxtLinkProps, 'to' | 'external'> &
578
+ type TypedNuxtLinkProps<
579
+ T extends RoutesNamesList,
580
+ P extends string,
581
+ E extends boolean = false> = Omit<NuxtLinkProps, 'to' | 'external'> &
579
582
  {
580
- to:
581
- | Omit<Exclude<RouteLocationRaw, string>, 'name' | 'params'> & RoutesNamedLocations
582
- | Omit<RouteLocationPathRaw, 'path'>
583
- ${returnIfTrue(
584
- pathCheck && !strictOptions.NuxtLink.strictRouteLocation,
585
- `& {path?: (E extends true ? string : TypedPathParameter<T>)}`
586
- )}
587
- ${returnIfTrue(!pathCheck && !strictOptions.NuxtLink.strictToArgument, ` | string`)}
588
- ${returnIfTrue(
589
- pathCheck && strictOptions.NuxtLink.strictToArgument,
590
- ` | (E extends true ? string : void)`
591
- )}
592
- ${returnIfTrue(
593
- pathCheck && !strictOptions.NuxtLink.strictToArgument,
594
- ` | (E extends true ? string : TypedPathParameter<T>)`
595
- )},
583
+ to: NuxtRoute<T, P, E>,
596
584
  external?: E
597
585
  }
598
586
 
599
587
 
600
588
 
601
- export type TypedNuxtLink = new <P extends string, E extends boolean = false>(props: TypedNuxtLinkProps<P, E>) => Omit<
589
+ export type TypedNuxtLink = new <T extends RoutesNamesList, P extends string, E extends boolean = false>(props: TypedNuxtLinkProps<T, P, E>) => Omit<
602
590
  typeof NuxtLink,
603
591
  '$props'
604
592
  > & {
605
- $props: TypedNuxtLinkProps<P, E>;
593
+ $props: TypedNuxtLinkProps<T, P, E>;
606
594
  };
607
595
 
608
- // Declare runtime-core instead of vue for compatibility issues with pnpm
609
596
  declare module 'vue' {
610
597
  interface GlobalComponents {
611
598
  NuxtLink: TypedNuxtLink;
599
+ ${returnIfTrue(i18n, ` NuxtLinkLocale: TypedNuxtLinkLocale;`)}
612
600
  }
613
601
  }
614
602
 
@@ -650,6 +638,7 @@ function createIndexFile() {
650
638
  TypedRouteLocationRaw,
651
639
  TypedRouteLocationRawFromName,
652
640
  TypedRouter,
641
+ NuxtRoute
653
642
  } from './__router';
654
643
  export { routesNames } from './__routes';
655
644
  export type {
@@ -661,6 +650,7 @@ function createIndexFile() {
661
650
  } from './__routes';
662
651
  export { useRoute } from './__useTypedRoute';
663
652
  export { useRouter } from './__useTypedRouter';
653
+ export { useLink } from './__useTypedLink';
664
654
  export { navigateTo } from './__navigateTo';
665
655
  export { definePageMeta } from './__definePageMeta';
666
656
  export { helpers } from './__helpers';
@@ -688,7 +678,7 @@ function createPluginFile() {
688
678
  /* typescript */
689
679
  `
690
680
 
691
- import { defineNuxtPlugin, useRouter, useRoute } from '#app';
681
+ import { defineNuxtPlugin, useRouter, useRoute } from '#imports';
692
682
  import {TypedRouter, TypedRoute, routesNames} from '@typed-router';
693
683
 
694
684
  export default defineNuxtPlugin(() => {
@@ -711,7 +701,7 @@ function createUseTypedRouteFile() {
711
701
  return (
712
702
  /* typescript */
713
703
  `
714
- import { useRoute as defaultRoute } from '#app';
704
+ import { useRoute as defaultRoute } from '#imports';
715
705
  import type { RoutesNamesList } from './__routes';
716
706
  import type {TypedRoute, TypedRouteFromName} from './__router'
717
707
 
@@ -752,7 +742,7 @@ function createUseTypedRouterFile() {
752
742
  /* typescript */
753
743
  `
754
744
 
755
- import { useRouter as defaultRouter } from '#app';
745
+ import { useRouter as defaultRouter } from '#imports';
756
746
  import type { TypedRouter } from './__router';
757
747
 
758
748
  /**
@@ -774,13 +764,76 @@ function createUseTypedRouterFile() {
774
764
  );
775
765
  }
776
766
 
767
+ function createUseTypedLinkFile() {
768
+ const strictOptions = moduleOptionStore.getResolvedStrictOptions();
769
+ const { pathCheck } = moduleOptionStore;
770
+ return (
771
+ /* typescript */
772
+ `
773
+
774
+ import { useLink as defaultLink } from '#imports';
775
+ import type {MaybeRef} from 'vue';
776
+ import type { NavigateToOptions } from 'nuxt/dist/app/composables/router';
777
+ import type { NavigationFailure } from 'vue-router';
778
+ import type { TypedRouteLocationRawFromName, TypedRouteFromName, TypedRoute } from './__router';
779
+ import type { RoutesNamesList } from './__routes';
780
+ ${returnIfTrue(
781
+ pathCheck,
782
+ `import type {TypedPathParameter, RouteNameFromPath} from './__paths';`
783
+ )}
784
+
785
+
786
+ type LinkedRoute<T extends RoutesNamesList> = {
787
+ route: ComputedRef<TypedRouteFromName<T> & {
788
+ href: string;
789
+ }>;
790
+ href: ComputedRef<string>;
791
+ isActive: ComputedRef<boolean>;
792
+ isExactActive: ComputedRef<boolean>;
793
+ navigate: (e?: MouseEvent) => Promise<void | NavigationFailure>;
794
+ };
795
+
796
+
797
+ interface UseLinkFunction {
798
+ <T extends RoutesNamesList, P extends string>(
799
+ props: {
800
+ to: MaybeRef<TypedRouteLocationRawFromName<T, P>>,
801
+ replace?: MaybeRef<boolean>
802
+ }
803
+ ) : LinkedRoute<T>
804
+ ${returnIfTrue(
805
+ pathCheck && !strictOptions.router.strictToArgument,
806
+ `<T extends string>(
807
+ props: {
808
+ to: MaybeRef<TypedPathParameter<T>>,
809
+ replace?: MaybeRef<boolean>
810
+ }
811
+ ) : LinkedRoute<RouteNameFromPath<T>>`
812
+ )}
813
+ }
814
+
815
+ /**
816
+ * Typed clone of \`useLink\`
817
+ *
818
+ * @exemple
819
+ *
820
+ * \`\`\`ts
821
+ * const router = useLink(props);
822
+ * \`\`\`
823
+ */
824
+ export const useLink: UseLinkFunction = defaultLink as any;
825
+
826
+ `
827
+ );
828
+ }
829
+
777
830
  function createNavigateToFile() {
778
831
  const { router } = moduleOptionStore.getResolvedStrictOptions();
779
832
  const { pathCheck } = moduleOptionStore;
780
833
  return (
781
834
  /* typescript */
782
835
  `
783
- import { navigateTo as defaultNavigateTo } from '#app';
836
+ import { navigateTo as defaultNavigateTo } from '#imports';
784
837
  import type { NavigateToOptions } from 'nuxt/dist/app/composables/router';
785
838
  import type { NavigationFailure } from 'vue-router';
786
839
  import type { TypedRouteLocationRawFromName, TypedRouteFromName, TypedRoute } from './__router';
@@ -818,7 +871,8 @@ function createNavigateToFile() {
818
871
  ) : Promise<void | NavigationFailure | TypedRouteFromName<RouteNameFromPath<T>>>`
819
872
  )}
820
873
  }
821
- export const navigateTo: NavigateToFunction = defaultNavigateTo as any;
874
+
875
+ export const navigateTo: NavigateToFunction = defaultNavigateTo as any;
822
876
 
823
877
  `
824
878
  );
@@ -849,7 +903,7 @@ function createTypeUtilsRuntimeFile() {
849
903
  }
850
904
 
851
905
  function createi18nRouterFile() {
852
- const { router } = moduleOptionStore.getResolvedStrictOptions();
906
+ const { router, NuxtLink } = moduleOptionStore.getResolvedStrictOptions();
853
907
  const { i18nOptions, pathCheck, i18nLocales } = moduleOptionStore;
854
908
  const LocalePathType = i18nOptions?.strategy === "no_prefix" ? "TypedPathParameter" : "TypedLocalePathParameter";
855
909
  return (
@@ -866,6 +920,16 @@ function createi18nRouterFile() {
866
920
 
867
921
  export type I18nLocales = ${i18nLocales?.length ? i18nLocales.map((loc) => `"${loc}"`).join("|") : "string"};
868
922
 
923
+
924
+ export type NuxtLocaleRoute<T extends RoutesNamesList, P extends string, E extends boolean = false> =
925
+ | TypedRouteLocationRawFromName<T, P>
926
+ ${returnIfTrue(!pathCheck && !NuxtLink.strictToArgument, ` | string`)}
927
+ ${returnIfTrue(pathCheck && NuxtLink.strictToArgument, ` | (E extends true ? string : never)`)}
928
+ ${returnIfTrue(
929
+ pathCheck && !NuxtLink.strictToArgument,
930
+ ` | (E extends true ? string : ${LocalePathType}<P>)`
931
+ )}
932
+
869
933
  export interface TypedToLocalePath {
870
934
  <T extends RoutesNamesList, P extends string>(
871
935
  to: TypedRouteLocationRawFromName<T, P>,
@@ -1000,7 +1064,7 @@ function extractPathElements(partOfPath, route) {
1000
1064
  return { pathElements, strippedPath };
1001
1065
  }
1002
1066
 
1003
- function createPathsFiles({ routesPaths }) {
1067
+ function createPathsFiles({ routesPaths, routesList }) {
1004
1068
  const { i18n, i18nOptions } = moduleOptionStore;
1005
1069
  const hasPrefixStrategy = i18n && i18nOptions?.strategy !== "no_prefix";
1006
1070
  const filteredRoutesPaths = routesPaths.filter((route) => !routesPaths.find((r) => `${route.path}/` === r.path)).map((route) => ({
@@ -1048,8 +1112,8 @@ function createPathsFiles({ routesPaths }) {
1048
1112
  const pathElements = filteredRoutesPaths.filter((f) => f.path && f.path !== "/").map((route) => {
1049
1113
  return route.path.split("/").filter((f) => f.length).map((m) => destructurePath(m, route));
1050
1114
  }).filter((f) => f.length);
1051
- const validatePathTypes = createValidatePathTypes(pathElements);
1052
- const validateLocalePathTypes = createValidatePathTypes(pathElements, true);
1115
+ const validatePathTypes = createValidatePathTypes(pathElements, routesList);
1116
+ const validateLocalePathTypes = createValidatePathTypes(pathElements, routesList, true);
1053
1117
  return (
1054
1118
  /* typescript */
1055
1119
  `
@@ -1122,7 +1186,7 @@ function createDefinePageMetaFile() {
1122
1186
  `
1123
1187
 
1124
1188
  import { definePageMeta as defaultDefinePageMeta } from '#imports';
1125
- import type {PageMeta, NuxtError} from '#app'
1189
+ import type {PageMeta, NuxtError} from 'nuxt/app'
1126
1190
  import type {TypedRouteFromName, TypedRoute, TypedRouteLocationRawFromName, TypedRouteLocationRaw} from './__router';
1127
1191
  import type {RoutesNamesList} from './__routes';
1128
1192
  ${returnIfTrue(pathCheck, `import type {TypedPathParameter} from './__paths';`)}
@@ -1242,6 +1306,40 @@ export const helpers = {
1242
1306
  );
1243
1307
  }
1244
1308
 
1309
+ function createNuxtLinkLocaleDefinitionFile() {
1310
+ moduleOptionStore.getResolvedStrictOptions();
1311
+ return (
1312
+ /* typescript */
1313
+ `
1314
+
1315
+ import type { NuxtLinkProps, PageMeta } from 'nuxt/app';
1316
+ import NuxtLink from 'nuxt/dist/app/components/nuxt-link';
1317
+ import type { RoutesNamedLocations, RoutesNamesListRecord, RoutesNamesList } from './__routes';
1318
+ import type {TypedRouter, TypedRoute, TypedRouteLocationRawFromName, TypedLocationAsRelativeRaw} from './__router';
1319
+ import type {NuxtLocaleRoute, I18nLocales} from './__i18n-router';
1320
+
1321
+
1322
+ type TypedNuxtLinkLocaleProps<
1323
+ T extends RoutesNamesList,
1324
+ P extends string,
1325
+ E extends boolean = false> = Omit<NuxtLinkProps, 'to' | 'external'> &
1326
+ {
1327
+ to: NuxtLocaleRoute<T, P, E>,
1328
+ external?: E,
1329
+ locale?: E extends true ? never : I18nLocales
1330
+ }
1331
+
1332
+ export type TypedNuxtLinkLocale = new <T extends RoutesNamesList, P extends string, E extends boolean = false>(props: TypedNuxtLinkLocaleProps<T, P, E>) => Omit<
1333
+ typeof NuxtLink,
1334
+ '$props'
1335
+ > & {
1336
+ $props: TypedNuxtLinkLocaleProps<T, P, E>;
1337
+ };
1338
+
1339
+ `
1340
+ );
1341
+ }
1342
+
1245
1343
  async function handleAddPlugin() {
1246
1344
  const pluginName = "__typed-router.plugin.ts";
1247
1345
  addPluginTemplate({
@@ -1307,6 +1405,10 @@ async function saveGeneratedFiles({ outputData }) {
1307
1405
  fileName: "__useTypedRoute.ts",
1308
1406
  content: createUseTypedRouteFile()
1309
1407
  },
1408
+ {
1409
+ fileName: "__useTypedLink.ts",
1410
+ content: createUseTypedLinkFile()
1411
+ },
1310
1412
  {
1311
1413
  fileName: "__paths.d.ts",
1312
1414
  content: createPathsFiles(outputData)
@@ -1349,6 +1451,10 @@ async function saveGeneratedFiles({ outputData }) {
1349
1451
  fileName: "__i18n-router.ts",
1350
1452
  content: createi18nRouterFile()
1351
1453
  });
1454
+ filesMap.push({
1455
+ fileName: "__NuxtLinkLocale.ts",
1456
+ content: createNuxtLinkLocaleDefinitionFile()
1457
+ });
1352
1458
  }
1353
1459
  await Promise.all(
1354
1460
  filesMap.map(({ content, fileName }) => {
@@ -1451,7 +1557,7 @@ function walkThoughRoutes({
1451
1557
  return;
1452
1558
  }
1453
1559
  const newPath = `${parent?.path ?? ""}${route.path.startsWith("/") || parent?.path === "/" ? route.path : `/${route.path}`}`;
1454
- if (parent?.path !== "/") {
1560
+ if (parent?.path !== "/" || newPath !== parent?.path) {
1455
1561
  output.routesPaths.push({
1456
1562
  name: route.name,
1457
1563
  path: newPath,
@@ -1604,7 +1710,7 @@ async function removeNuxtDefinitions({
1604
1710
  encoding: "utf8"
1605
1711
  });
1606
1712
  const replacedNuxtLink = componentDefinitions.replace(
1607
- /'NuxtLink': typeof import\(".*"\)\['default'\]/gm,
1713
+ /'NuxtLink': typeof import\(".*"\)\['default'\]|'NuxtLinkLocale': typeof import\(".*"\)\['default'\]/gm,
1608
1714
  ""
1609
1715
  );
1610
1716
  processPathAndWriteFile({
@@ -1649,8 +1755,8 @@ const module = defineNuxtModule({
1649
1755
  plugin: false,
1650
1756
  strict: false,
1651
1757
  pathCheck: true,
1652
- experimentalRemoveNuxtDefs: true,
1653
- experimentalIgnoreRoutes: []
1758
+ removeNuxtDefs: true,
1759
+ ignoreRoutes: []
1654
1760
  },
1655
1761
  setup(moduleOptions, nuxt) {
1656
1762
  const { resolve } = createResolver(import.meta.url);
@@ -1689,7 +1795,7 @@ const module = defineNuxtModule({
1689
1795
  experimentalRfc436: true
1690
1796
  };
1691
1797
  }
1692
- if (moduleOptions.experimentalRemoveNuxtDefs) {
1798
+ if (moduleOptions.removeNuxtDefs) {
1693
1799
  removeNuxtDefinitions({
1694
1800
  autoImport: nuxt.options.imports.autoImport ?? true,
1695
1801
  buildDir: nuxt.options.buildDir
@@ -1697,7 +1803,7 @@ const module = defineNuxtModule({
1697
1803
  }
1698
1804
  });
1699
1805
  nuxt.hook("build:done", () => {
1700
- if (moduleOptions.experimentalRemoveNuxtDefs) {
1806
+ if (moduleOptions.removeNuxtDefs) {
1701
1807
  removeNuxtDefinitions({
1702
1808
  autoImport: nuxt.options.imports.autoImport ?? true,
1703
1809
  buildDir: nuxt.options.buildDir
package/dist/types.d.mts CHANGED
@@ -1,5 +1,6 @@
1
1
 
2
- import { ModuleOptions } from './module'
2
+ import type { ModuleOptions } from './module'
3
+
3
4
 
4
5
  declare module '@nuxt/schema' {
5
6
  interface NuxtConfig { ['nuxtTypedRouter']?: Partial<ModuleOptions> }
@@ -12,4 +13,4 @@ declare module 'nuxt/schema' {
12
13
  }
13
14
 
14
15
 
15
- export { ModuleOptions, default } from './module'
16
+ export type { ModuleOptions, default } from './module'
package/dist/types.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
 
2
- import { ModuleOptions } from './module'
2
+ import type { ModuleOptions } from './module'
3
+
3
4
 
4
5
  declare module '@nuxt/schema' {
5
6
  interface NuxtConfig { ['nuxtTypedRouter']?: Partial<ModuleOptions> }
@@ -12,4 +13,4 @@ declare module 'nuxt/schema' {
12
13
  }
13
14
 
14
15
 
15
- export { ModuleOptions, default } from './module'
16
+ export type { ModuleOptions, default } from './module'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-typed-router",
3
- "version": "3.3.2",
3
+ "version": "3.4.0",
4
4
  "description": "Provide autocompletion for routes paths, names and params in Nuxt apps",
5
5
  "type": "module",
6
6
  "main": "./dist/module.cjs",
@@ -60,44 +60,44 @@
60
60
  "url": "https://github.com/victorgarciaesgi/nuxt-typed-router/issues"
61
61
  },
62
62
  "dependencies": {
63
- "@nuxt/kit": "^3.8.0",
64
- "chalk": "^5.3.0",
65
- "defu": "^6.1.2",
66
- "lodash-es": "^4.17.21",
67
- "log-symbols": "^5.1.0",
68
- "mkdirp": "^3.0.1",
69
- "nanoid": "^5.0.2",
63
+ "@nuxt/kit": "3.8.2",
64
+ "chalk": "5.3.0",
65
+ "defu": "6.1.3",
66
+ "lodash-es": "4.17.21",
67
+ "log-symbols": "6.0.0",
68
+ "mkdirp": "3.0.1",
69
+ "nanoid": "5.0.3",
70
70
  "pathe": "1.1.1"
71
71
  },
72
72
  "devDependencies": {
73
- "@nuxt/devtools": "^1.0.0",
74
- "@nuxt/module-builder": "^0.5.2",
75
- "@nuxt/test-utils": "^3.8.0",
76
- "@nuxt/types": "^2.17.1",
77
- "@nuxtjs/eslint-config-typescript": "^12.1.0",
78
- "@nuxtjs/i18n": "8.0.0-beta.10",
79
- "@nuxtjs/web-vitals": "^0.2.6",
80
- "@types/lodash-es": "^4.17.10",
81
- "@types/node": "^20.8.7",
82
- "@types/prettier": "^3.0.0",
83
- "@typescript-eslint/eslint-plugin": "^6.8.0",
84
- "@typescript-eslint/parser": "^6.8.0",
85
- "@vue/test-utils": "^2.4.1",
73
+ "@nuxt/devtools": "1.0.3",
74
+ "@nuxt/module-builder": "0.5.4",
75
+ "@nuxt/test-utils": "3.8.1",
76
+ "@nuxt/types": "2.17.2",
77
+ "@nuxtjs/eslint-config-typescript": "12.1.0",
78
+ "@nuxtjs/i18n": "8.0.0-rc.5",
79
+ "@nuxtjs/web-vitals": "0.2.6",
80
+ "@types/lodash-es": "4.17.12",
81
+ "@types/node": "20.10.0",
82
+ "@types/prettier": "3.0.0",
83
+ "@typescript-eslint/eslint-plugin": "6.12.0",
84
+ "@typescript-eslint/parser": "6.12.0",
85
+ "@vue/test-utils": "2.4.2",
86
86
  "bumpp": "9.2.0",
87
- "changelogithub": "0.13.1",
88
- "cross-env": "^7.0.3",
89
- "eslint": "8.51.0",
90
- "eslint-config-prettier": "^9.0.0",
91
- "eslint-plugin-vue": "^9.17.0",
92
- "nuxt": "3.8.0",
87
+ "changelogithub": "0.13.2",
88
+ "cross-env": "7.0.3",
89
+ "eslint": "8.54.0",
90
+ "eslint-config-prettier": "9.0.0",
91
+ "eslint-plugin-vue": "9.18.1",
92
+ "nuxt": "3.8.2",
93
93
  "nuxt-seo-kit": "1.3.13",
94
- "playwright": "1.39.0",
95
- "prettier": "3.0.3",
96
- "tsd": "^0.29.0",
97
- "typescript": "^5.2.2",
98
- "vitest": "^0.34.6",
99
- "vue-eslint-parser": "^9.3.2",
100
- "vue-router": "^4.2.5",
101
- "vue-tsc": "^1.8.19"
94
+ "playwright": "1.37.0",
95
+ "prettier": "3.1.0",
96
+ "tsd": "0.29.0",
97
+ "typescript": "5.3.2",
98
+ "vitest": "0.34.6",
99
+ "vue-eslint-parser": "9.3.2",
100
+ "vue-router": "4.2.5",
101
+ "vue-tsc": "1.8.22"
102
102
  }
103
103
  }