nuxt-typed-router 2.2.0 → 2.2.2-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 +1 -0
- package/dist/module.d.ts +24 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +138 -33
- package/package.json +8 -4
package/README.md
CHANGED
package/dist/module.d.ts
CHANGED
|
@@ -6,6 +6,30 @@ interface ModuleOptions {
|
|
|
6
6
|
* @default false
|
|
7
7
|
*/
|
|
8
8
|
plugin?: boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Prevent passing a string path to `router` or `<NuxtLink/>`
|
|
11
|
+
* Ex:
|
|
12
|
+
*
|
|
13
|
+
* ```ts
|
|
14
|
+
* router.push('/login'); // Error ❌
|
|
15
|
+
* ```
|
|
16
|
+
* @default false
|
|
17
|
+
*/
|
|
18
|
+
strict?: boolean | StrictOptions;
|
|
19
|
+
}
|
|
20
|
+
interface StrictOptions {
|
|
21
|
+
NuxtLink: StrictParamsOptions;
|
|
22
|
+
router: StrictParamsOptions;
|
|
23
|
+
}
|
|
24
|
+
interface StrictParamsOptions {
|
|
25
|
+
/**
|
|
26
|
+
* @default false
|
|
27
|
+
*/
|
|
28
|
+
strictToArgument?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* @default false
|
|
31
|
+
*/
|
|
32
|
+
strictRouteLocation?: boolean;
|
|
9
33
|
}
|
|
10
34
|
|
|
11
35
|
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions>;
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { addPluginTemplate, extendPages, defineNuxtModule, createResolver } from '@nuxt/kit';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import logSymbols from 'log-symbols';
|
|
4
|
+
import { defu } from 'defu';
|
|
4
5
|
import prettier from 'prettier';
|
|
5
6
|
import fs from 'fs';
|
|
6
7
|
import { fileURLToPath } from 'url';
|
|
@@ -8,6 +9,66 @@ import { dirname, resolve } from 'pathe';
|
|
|
8
9
|
import mkdirp from 'mkdirp';
|
|
9
10
|
import { camelCase } from 'lodash-es';
|
|
10
11
|
|
|
12
|
+
class ModuleOptionsStore {
|
|
13
|
+
constructor() {
|
|
14
|
+
this.plugin = false;
|
|
15
|
+
this.strict = false;
|
|
16
|
+
this.autoImport = false;
|
|
17
|
+
this.rootDir = "";
|
|
18
|
+
}
|
|
19
|
+
updateOptions(options) {
|
|
20
|
+
if (options.plugin != null)
|
|
21
|
+
this.plugin = options.plugin;
|
|
22
|
+
if (options.strict != null)
|
|
23
|
+
this.strict = options.strict;
|
|
24
|
+
if (options.autoImport != null)
|
|
25
|
+
this.autoImport = options.autoImport;
|
|
26
|
+
if (options.rootDir != null)
|
|
27
|
+
this.rootDir = options.rootDir;
|
|
28
|
+
}
|
|
29
|
+
getResolvedStrictOptions() {
|
|
30
|
+
let resolved;
|
|
31
|
+
if (typeof this.strict === "boolean") {
|
|
32
|
+
if (this.strict) {
|
|
33
|
+
resolved = {
|
|
34
|
+
NuxtLink: {
|
|
35
|
+
strictRouteLocation: true,
|
|
36
|
+
strictToArgument: true
|
|
37
|
+
},
|
|
38
|
+
router: {
|
|
39
|
+
strictRouteLocation: true,
|
|
40
|
+
strictToArgument: true
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
} else {
|
|
44
|
+
resolved = {
|
|
45
|
+
NuxtLink: {
|
|
46
|
+
strictRouteLocation: false,
|
|
47
|
+
strictToArgument: false
|
|
48
|
+
},
|
|
49
|
+
router: {
|
|
50
|
+
strictRouteLocation: false,
|
|
51
|
+
strictToArgument: false
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
} else {
|
|
56
|
+
resolved = defu(this.strict, {
|
|
57
|
+
NuxtLink: {
|
|
58
|
+
strictRouteLocation: false,
|
|
59
|
+
strictToArgument: false
|
|
60
|
+
},
|
|
61
|
+
router: {
|
|
62
|
+
strictRouteLocation: false,
|
|
63
|
+
strictToArgument: false
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
return resolved;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const moduleOptionStore = new ModuleOptionsStore();
|
|
71
|
+
|
|
11
72
|
function createRoutesNamesListExport(routesList) {
|
|
12
73
|
return `
|
|
13
74
|
/**
|
|
@@ -74,6 +135,23 @@ function createRoutesNamedLocationsResolvedExport(routesParams) {
|
|
|
74
135
|
`;
|
|
75
136
|
}
|
|
76
137
|
|
|
138
|
+
function createRoutesParamsRecordResolvedExport(routesParams) {
|
|
139
|
+
return `
|
|
140
|
+
/**
|
|
141
|
+
* Record resolved used for resolved routes
|
|
142
|
+
*
|
|
143
|
+
* */
|
|
144
|
+
export type RoutesParamsRecordResolved = {
|
|
145
|
+
${routesParams.map(
|
|
146
|
+
({ name, params }) => `"${name}": ${params.length ? `{
|
|
147
|
+
${params.map(
|
|
148
|
+
({ key, notRequiredOnPage, catchAll }) => `"${key}"${notRequiredOnPage ? "?" : ""}: string${catchAll ? "[]" : ""}`
|
|
149
|
+
).join(",\n")}
|
|
150
|
+
}` : "never"}`
|
|
151
|
+
).join(",\n")}
|
|
152
|
+
}`;
|
|
153
|
+
}
|
|
154
|
+
|
|
77
155
|
function createRoutesTypesFile({
|
|
78
156
|
routesList,
|
|
79
157
|
routesObjectTemplate,
|
|
@@ -86,6 +164,8 @@ function createRoutesTypesFile({
|
|
|
86
164
|
${createRoutesNamesListExport(routesList)}
|
|
87
165
|
|
|
88
166
|
${createRoutesParamsRecordExport(routesParams)}
|
|
167
|
+
|
|
168
|
+
${createRoutesParamsRecordResolvedExport(routesParams)}
|
|
89
169
|
|
|
90
170
|
${createRoutesNamedLocationsExport(routesParams)}
|
|
91
171
|
|
|
@@ -100,7 +180,24 @@ function createRoutesTypesFile({
|
|
|
100
180
|
);
|
|
101
181
|
}
|
|
102
182
|
|
|
183
|
+
function isItemLast(array, index) {
|
|
184
|
+
return array ? index === array.length - 1 : false;
|
|
185
|
+
}
|
|
186
|
+
function returnIfTrue(condition, template, otherwise) {
|
|
187
|
+
if (condition) {
|
|
188
|
+
return template;
|
|
189
|
+
}
|
|
190
|
+
return otherwise ?? "";
|
|
191
|
+
}
|
|
192
|
+
function returnIfFalse(condition, template, otherwise) {
|
|
193
|
+
if (!condition) {
|
|
194
|
+
return template;
|
|
195
|
+
}
|
|
196
|
+
return otherwise ?? "";
|
|
197
|
+
}
|
|
198
|
+
|
|
103
199
|
function createTypedRouterFile() {
|
|
200
|
+
const strictOptions = moduleOptionStore.getResolvedStrictOptions();
|
|
104
201
|
return (
|
|
105
202
|
/* typescript */
|
|
106
203
|
`
|
|
@@ -118,6 +215,7 @@ function createTypedRouterFile() {
|
|
|
118
215
|
RoutesNamedLocationsResolved,
|
|
119
216
|
RoutesNamesList,
|
|
120
217
|
RoutesParamsRecord,
|
|
218
|
+
RoutesParamsRecordResolved
|
|
121
219
|
} from './__routes';
|
|
122
220
|
import type { HasOneRequiredParameter } from './__types_utils';
|
|
123
221
|
|
|
@@ -129,15 +227,22 @@ function createTypedRouterFile() {
|
|
|
129
227
|
* {@link RouteLocationRaw}
|
|
130
228
|
* */
|
|
131
229
|
export type TypedRouteLocationRaw =
|
|
132
|
-
| (Omit<Exclude<RouteLocationRaw, string>, 'name' | 'params'
|
|
133
|
-
|
|
230
|
+
| (Omit<Exclude<RouteLocationRaw, string>, 'name' | 'params' ${returnIfTrue(
|
|
231
|
+
strictOptions.NuxtLink.strictRouteLocation,
|
|
232
|
+
`| 'path'`
|
|
233
|
+
)}> & RoutesNamedLocations)
|
|
234
|
+
${returnIfFalse(strictOptions.NuxtLink.strictToArgument, "| string")};
|
|
235
|
+
|
|
134
236
|
|
|
135
237
|
/**
|
|
136
238
|
* Alternative version of {@link TypedRouteLocationRaw} but with a name generic
|
|
137
239
|
*/
|
|
138
240
|
export type TypedRouteLocationRawFromName<T extends RoutesNamesList> =
|
|
139
|
-
| (Omit<Exclude<RouteLocationRaw, string>, 'name' | 'params'
|
|
140
|
-
|
|
241
|
+
| (Omit<Exclude<RouteLocationRaw, string>, 'name' | 'params' ${returnIfTrue(
|
|
242
|
+
strictOptions.NuxtLink.strictRouteLocation,
|
|
243
|
+
`| 'path'`
|
|
244
|
+
)}> & TypedLocationAsRelativeRaw<T>)
|
|
245
|
+
${returnIfFalse(strictOptions.NuxtLink.strictToArgument, "| string")};
|
|
141
246
|
|
|
142
247
|
/**
|
|
143
248
|
* Generic providing inference and dynamic inclusion of \`params\` property
|
|
@@ -226,7 +331,7 @@ function createTypedRouterFile() {
|
|
|
226
331
|
* */
|
|
227
332
|
export type TypedResolvedMatcherLocation<T extends RoutesNamesList> = {
|
|
228
333
|
name: T;
|
|
229
|
-
} & ([
|
|
334
|
+
} & ([RoutesParamsRecordResolved[T]] extends [never] ? {} : { params: RoutesParamsRecordResolved[T] });
|
|
230
335
|
|
|
231
336
|
|
|
232
337
|
/**
|
|
@@ -238,7 +343,9 @@ function createTypedRouterFile() {
|
|
|
238
343
|
);
|
|
239
344
|
}
|
|
240
345
|
|
|
241
|
-
function createTypedRouterDefinitionFile(
|
|
346
|
+
function createTypedRouterDefinitionFile() {
|
|
347
|
+
const { plugin, autoImport } = moduleOptionStore;
|
|
348
|
+
const strictOptions = moduleOptionStore.getResolvedStrictOptions();
|
|
242
349
|
return (
|
|
243
350
|
/* typescript */
|
|
244
351
|
`
|
|
@@ -254,17 +361,24 @@ function createTypedRouterDefinitionFile({ autoImport, plugin }) {
|
|
|
254
361
|
|
|
255
362
|
declare global {
|
|
256
363
|
|
|
257
|
-
${
|
|
364
|
+
${returnIfTrue(
|
|
365
|
+
autoImport,
|
|
258
366
|
/* typescript */
|
|
259
367
|
`
|
|
260
368
|
const useRoute: typeof _useRoute;
|
|
261
369
|
const useRouter: typeof _useRouter;
|
|
262
370
|
const navigateTo: typeof _navigateTo;`
|
|
263
|
-
)
|
|
371
|
+
)}
|
|
264
372
|
}
|
|
265
373
|
|
|
266
374
|
type TypedNuxtLinkProps = Omit<NuxtLinkProps, 'to'> & {
|
|
267
|
-
to:
|
|
375
|
+
to: ${returnIfFalse(
|
|
376
|
+
strictOptions.NuxtLink.strictToArgument,
|
|
377
|
+
"string |"
|
|
378
|
+
)} Omit<Exclude<RouteLocationRaw, string>, 'name' | 'params' ${returnIfTrue(
|
|
379
|
+
strictOptions.NuxtLink.strictRouteLocation,
|
|
380
|
+
`| 'path'`
|
|
381
|
+
)}> & RoutesNamedLocations;
|
|
268
382
|
};
|
|
269
383
|
|
|
270
384
|
export type TypedNuxtLink = DefineComponent<
|
|
@@ -290,7 +404,8 @@ function createTypedRouterDefinitionFile({ autoImport, plugin }) {
|
|
|
290
404
|
}
|
|
291
405
|
}
|
|
292
406
|
|
|
293
|
-
${
|
|
407
|
+
${returnIfTrue(
|
|
408
|
+
plugin,
|
|
294
409
|
/* typescript */
|
|
295
410
|
`
|
|
296
411
|
interface CustomPluginProperties {
|
|
@@ -305,7 +420,7 @@ function createTypedRouterDefinitionFile({ autoImport, plugin }) {
|
|
|
305
420
|
interface ComponentCustomProperties extends CustomPluginProperties {}
|
|
306
421
|
}
|
|
307
422
|
`
|
|
308
|
-
)
|
|
423
|
+
)}
|
|
309
424
|
`
|
|
310
425
|
);
|
|
311
426
|
}
|
|
@@ -523,10 +638,10 @@ dirname(fileURLToPath(import.meta.url));
|
|
|
523
638
|
async function processPathAndWriteFile({
|
|
524
639
|
content,
|
|
525
640
|
fileName,
|
|
526
|
-
rootDir,
|
|
527
641
|
outDir
|
|
528
642
|
}) {
|
|
529
643
|
try {
|
|
644
|
+
const { rootDir } = moduleOptionStore;
|
|
530
645
|
const finalOutDir = outDir ?? `.nuxt/typed-router`;
|
|
531
646
|
const processedOutDir = resolve(rootDir, finalOutDir);
|
|
532
647
|
const outputFile = resolve(process.cwd(), `${processedOutDir}/${fileName}`);
|
|
@@ -566,9 +681,6 @@ const watermarkTemplate = `
|
|
|
566
681
|
|
|
567
682
|
let previousGeneratedRoutes = "";
|
|
568
683
|
async function saveGeneratedFiles({
|
|
569
|
-
rootDir,
|
|
570
|
-
autoImport,
|
|
571
|
-
plugin,
|
|
572
684
|
outputData: { routesDeclTemplate, routesList, routesObjectTemplate, routesParams }
|
|
573
685
|
}) {
|
|
574
686
|
const filesMap = [
|
|
@@ -603,7 +715,7 @@ async function saveGeneratedFiles({
|
|
|
603
715
|
},
|
|
604
716
|
{
|
|
605
717
|
fileName: `typed-router.d.ts`,
|
|
606
|
-
content: createTypedRouterDefinitionFile(
|
|
718
|
+
content: createTypedRouterDefinitionFile()
|
|
607
719
|
},
|
|
608
720
|
{
|
|
609
721
|
fileName: "index.ts",
|
|
@@ -617,7 +729,7 @@ async function saveGeneratedFiles({
|
|
|
617
729
|
|
|
618
730
|
${content}
|
|
619
731
|
`;
|
|
620
|
-
return processPathAndWriteFile({
|
|
732
|
+
return processPathAndWriteFile({ content: waterMakeredContent, fileName });
|
|
621
733
|
})
|
|
622
734
|
);
|
|
623
735
|
if (previousGeneratedRoutes !== routesList.join(",")) {
|
|
@@ -626,10 +738,6 @@ async function saveGeneratedFiles({
|
|
|
626
738
|
}
|
|
627
739
|
}
|
|
628
740
|
|
|
629
|
-
function isItemLast(array, index) {
|
|
630
|
-
return array ? index === array.length - 1 : false;
|
|
631
|
-
}
|
|
632
|
-
|
|
633
741
|
const routeParamExtractRegxp = /(:(\w+)(\(.+\)[*+]?)?(\?)?)+/g;
|
|
634
742
|
function extractRouteParamsFromPath(path, isIndexFileForRouting, previousParams) {
|
|
635
743
|
let params = [];
|
|
@@ -785,7 +893,6 @@ function startGenerator({ output, routesConfig }) {
|
|
|
785
893
|
let hasLoggedNoPages = false;
|
|
786
894
|
let hasRoutesDefined = false;
|
|
787
895
|
async function createTypedRouter({
|
|
788
|
-
plugin,
|
|
789
896
|
nuxt,
|
|
790
897
|
routesConfig,
|
|
791
898
|
isHookCall = false
|
|
@@ -793,18 +900,19 @@ async function createTypedRouter({
|
|
|
793
900
|
try {
|
|
794
901
|
const rootDir = nuxt.options.rootDir;
|
|
795
902
|
const autoImport = nuxt.options.imports.autoImport ?? true;
|
|
903
|
+
moduleOptionStore.updateOptions({ rootDir, autoImport });
|
|
796
904
|
if (!isHookCall) {
|
|
797
905
|
if (routesConfig) {
|
|
798
906
|
await nuxt.callHook("pages:extend", routesConfig);
|
|
799
907
|
return;
|
|
800
908
|
}
|
|
801
909
|
nuxt.hook("pages:extend", (routesConfig2) => {
|
|
802
|
-
createTypedRouter({ nuxt,
|
|
910
|
+
createTypedRouter({ nuxt, routesConfig: routesConfig2, isHookCall: true });
|
|
803
911
|
});
|
|
804
912
|
nuxt.hook("modules:done", () => {
|
|
805
|
-
createTypedRouter({ nuxt,
|
|
913
|
+
createTypedRouter({ nuxt, isHookCall: true });
|
|
806
914
|
});
|
|
807
|
-
if (plugin) {
|
|
915
|
+
if (moduleOptionStore.plugin) {
|
|
808
916
|
await handleAddPlugin();
|
|
809
917
|
}
|
|
810
918
|
return;
|
|
@@ -813,10 +921,7 @@ async function createTypedRouter({
|
|
|
813
921
|
hasRoutesDefined = true;
|
|
814
922
|
const outputData = constructRouteMap(routes);
|
|
815
923
|
await saveGeneratedFiles({
|
|
816
|
-
|
|
817
|
-
rootDir,
|
|
818
|
-
outputData,
|
|
819
|
-
plugin
|
|
924
|
+
outputData
|
|
820
925
|
});
|
|
821
926
|
});
|
|
822
927
|
setTimeout(() => {
|
|
@@ -844,11 +949,12 @@ const module = defineNuxtModule({
|
|
|
844
949
|
compatibility: { nuxt: "^3.0.0-rc.1", bridge: false }
|
|
845
950
|
},
|
|
846
951
|
defaults: {
|
|
847
|
-
plugin: false
|
|
952
|
+
plugin: false,
|
|
953
|
+
strict: false
|
|
848
954
|
},
|
|
849
955
|
setup(moduleOptions, nuxt) {
|
|
850
956
|
const rootDir = nuxt.options.rootDir;
|
|
851
|
-
|
|
957
|
+
moduleOptionStore.updateOptions(moduleOptions);
|
|
852
958
|
const { resolve } = createResolver(import.meta.url);
|
|
853
959
|
nuxt.options.alias = {
|
|
854
960
|
...nuxt.options.alias,
|
|
@@ -857,8 +963,7 @@ const module = defineNuxtModule({
|
|
|
857
963
|
nuxt.options.typescript.tsConfig = {
|
|
858
964
|
include: ["./typed-router/typed-router.d.ts"]
|
|
859
965
|
};
|
|
860
|
-
|
|
861
|
-
createTypedRouter({ ...typedRouterOptions });
|
|
966
|
+
createTypedRouter({ nuxt });
|
|
862
967
|
}
|
|
863
968
|
});
|
|
864
969
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-typed-router",
|
|
3
|
-
"version": "2.2.0",
|
|
3
|
+
"version": "2.2.2-beta.0",
|
|
4
4
|
"description": "Provide autocompletion for pages route names generated by Nuxt router",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/module.cjs",
|
|
@@ -63,7 +63,8 @@
|
|
|
63
63
|
"log-symbols": "^5.1.0",
|
|
64
64
|
"mkdirp": "^1.0.4",
|
|
65
65
|
"pathe": "1.1.0",
|
|
66
|
-
"prettier": "2.8.3"
|
|
66
|
+
"prettier": "2.8.3",
|
|
67
|
+
"defu": "^6.1.2"
|
|
67
68
|
},
|
|
68
69
|
"devDependencies": {
|
|
69
70
|
"@nuxt/module-builder": "^0.2.1",
|
|
@@ -74,14 +75,17 @@
|
|
|
74
75
|
"@types/mkdirp": "^1.0.2",
|
|
75
76
|
"@types/node": "^17.0.23",
|
|
76
77
|
"@types/prettier": "^2.7.2",
|
|
78
|
+
"@typescript-eslint/eslint-plugin": "^5.49.0",
|
|
79
|
+
"@typescript-eslint/parser": "^5.49.0",
|
|
77
80
|
"cross-env": "^7.0.3",
|
|
78
|
-
"eslint": "8.
|
|
81
|
+
"eslint": "8.33.0",
|
|
79
82
|
"eslint-config-prettier": "^8.6.0",
|
|
80
83
|
"eslint-plugin-vue": "^9.9.0",
|
|
81
84
|
"nuxt": "3.1.1",
|
|
82
85
|
"playwright": "1.30.0",
|
|
83
86
|
"typescript": "^4.9.4",
|
|
84
|
-
"vitest": "^0.28.
|
|
87
|
+
"vitest": "^0.28.3",
|
|
88
|
+
"vue-eslint-parser": "^9.1.0",
|
|
85
89
|
"vue-router": "^4.1.6",
|
|
86
90
|
"vue-tsc": "^1.0.24"
|
|
87
91
|
}
|