nuxt-typed-router 0.2.22 → 1.0.0-alpha-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/lib/hook.js +9 -0
- package/lib/module.js +189 -35
- package/lib/save.js +2 -2
- package/lib/templates/typed-router.js +9 -0
- package/lib/utils.js +8 -7
- package/package.json +22 -9
- package/types/types.d.ts +8 -0
- package/types/vue.d.ts +1 -1
package/lib/hook.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useTypedRouter = void 0;
|
|
4
|
+
const vue_router_1 = require("vue-router");
|
|
5
|
+
const useTypedRouter = () => {
|
|
6
|
+
const router = (0, vue_router_1.useRouter)();
|
|
7
|
+
return router;
|
|
8
|
+
};
|
|
9
|
+
exports.useTypedRouter = useTypedRouter;
|
package/lib/module.js
CHANGED
|
@@ -7,50 +7,204 @@ const lodash_1 = require("lodash");
|
|
|
7
7
|
const chalk_1 = __importDefault(require("chalk"));
|
|
8
8
|
const save_1 = require("./save");
|
|
9
9
|
const utils_1 = require("./utils");
|
|
10
|
+
const path_1 = require("path");
|
|
11
|
+
const paramRegxp = /:(\w+)/;
|
|
10
12
|
const typedRouterModule = function (moduleOptions) {
|
|
11
|
-
const { filePath = `${this.options.srcDir}/__routes.
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
13
|
+
const { filePath = `${this.options.srcDir}/__routes.ts`, routesObjectName = 'routerPagesNames', stripAtFromName = false, } = { ...this.options.typedRouter, ...moduleOptions };
|
|
14
|
+
const folderPathes = filePath.split('/');
|
|
15
|
+
folderPathes.splice(folderPathes.length - 1, 1);
|
|
16
|
+
const definitionFilePath = folderPathes.join('/') + `/typed-router.d.ts`;
|
|
17
|
+
this.addPlugin({
|
|
18
|
+
src: (0, path_1.resolve)(__dirname, './templates/typed-router.js'),
|
|
19
|
+
fileName: 'typed-router.js',
|
|
20
|
+
});
|
|
21
|
+
this.nuxt.hook('build:before', () => routeHook.call(this, filePath, routesObjectName, stripAtFromName, definitionFilePath));
|
|
22
|
+
this.nuxt.hook('build:extendRoutes', () => routeHook.call(this, filePath, routesObjectName, stripAtFromName, definitionFilePath));
|
|
23
|
+
};
|
|
24
|
+
function routeHook(filePath, routesObjectName, stripAtFromName, definitionFilePath) {
|
|
25
|
+
try {
|
|
26
|
+
this.extendRoutes(async (routes) => {
|
|
27
|
+
(0, utils_1.transformRouteNames)(routes, stripAtFromName);
|
|
28
|
+
let routesObjectString = '{';
|
|
29
|
+
let routesObjectDecl = '{';
|
|
30
|
+
let routesList = [];
|
|
31
|
+
let routesParams = [];
|
|
32
|
+
let routeObjectJs = {};
|
|
33
|
+
const recursiveTypedRoutes = (route, level, routeObject, siblings, parentName, previousParams) => {
|
|
34
|
+
var _a, _b, _c, _d, _e, _f;
|
|
35
|
+
const matchingSiblings = (0, utils_1.extractMatchingSiblings)(route, siblings);
|
|
36
|
+
const haveMatchingSiblings = !!(matchingSiblings === null || matchingSiblings === void 0 ? void 0 : matchingSiblings.length) && route.path !== '/';
|
|
37
|
+
const chunkArray = (_b = (_a = route.file) === null || _a === void 0 ? void 0 : _a.split('/')) !== null && _b !== void 0 ? _b : [];
|
|
38
|
+
const lastChunkArray = chunkArray[(chunkArray === null || chunkArray === void 0 ? void 0 : chunkArray.length) - 1].split('.vue')[0];
|
|
39
|
+
const isRootSibling = lastChunkArray === 'index';
|
|
40
|
+
if ((((_c = route.children) === null || _c === void 0 ? void 0 : _c.length) && !haveMatchingSiblings) ||
|
|
41
|
+
(!((_d = route.children) === null || _d === void 0 ? void 0 : _d.length) && haveMatchingSiblings && isRootSibling)) {
|
|
42
|
+
let childrenChunks = haveMatchingSiblings ? matchingSiblings : route.children;
|
|
43
|
+
const splittedPaths = route.path.split('/');
|
|
44
|
+
const parentPath = splittedPaths[splittedPaths.length - 1];
|
|
45
|
+
const nameKey = (0, lodash_1.camelCase)(parentPath || 'index');
|
|
46
|
+
routesObjectString += `${nameKey}:{`;
|
|
47
|
+
routesObjectDecl += `${nameKey}:{`;
|
|
48
|
+
routeObject[nameKey] = {};
|
|
49
|
+
const params = (_e = route.path.match(paramRegxp)) !== null && _e !== void 0 ? _e : [];
|
|
50
|
+
params === null || params === void 0 ? void 0 : params.shift();
|
|
51
|
+
let allMergedParams = params.map((m) => ({ key: m, type: 'string | number' }));
|
|
52
|
+
if (previousParams === null || previousParams === void 0 ? void 0 : previousParams.length) {
|
|
53
|
+
allMergedParams = allMergedParams.concat(previousParams);
|
|
32
54
|
}
|
|
33
|
-
|
|
34
|
-
|
|
55
|
+
childrenChunks === null || childrenChunks === void 0 ? void 0 : childrenChunks.map((r) => recursiveTypedRoutes(r, level + 1, routeObject[nameKey], (0, utils_1.extractUnMatchingSiblings)(route, siblings), nameKey, allMergedParams));
|
|
56
|
+
routesObjectString += '},';
|
|
57
|
+
routesObjectDecl += '},';
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
if (route.name) {
|
|
61
|
+
let splitted = [];
|
|
62
|
+
splitted = route.name.split('-');
|
|
35
63
|
splitted = splitted.slice(level, splitted.length);
|
|
36
64
|
if (splitted[0] === parentName) {
|
|
37
65
|
splitted.splice(0, 1);
|
|
38
66
|
}
|
|
39
67
|
const keyName = route.path === '' ? 'index' : (0, lodash_1.camelCase)(splitted.join('-')) || 'index';
|
|
40
|
-
routesObjectString += `'${keyName}': '${
|
|
41
|
-
|
|
68
|
+
routesObjectString += `'${keyName}': '${route.name}' as const,`;
|
|
69
|
+
routesObjectDecl += `'${keyName}': '${route.name}',`;
|
|
70
|
+
routesList.push(route.name);
|
|
71
|
+
const params = (_f = route.path.match(paramRegxp)) !== null && _f !== void 0 ? _f : [];
|
|
72
|
+
params === null || params === void 0 ? void 0 : params.shift();
|
|
73
|
+
let allMergedParams = params === null || params === void 0 ? void 0 : params.map((m) => ({ key: m, type: 'string | number' }));
|
|
74
|
+
if (previousParams === null || previousParams === void 0 ? void 0 : previousParams.length) {
|
|
75
|
+
allMergedParams = allMergedParams.concat(previousParams);
|
|
76
|
+
}
|
|
77
|
+
routesParams.push({
|
|
78
|
+
name: route.name,
|
|
79
|
+
params: allMergedParams,
|
|
80
|
+
});
|
|
81
|
+
routeObject[keyName] = route.name;
|
|
42
82
|
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
routes.map((r) => recursiveTypedRoutes(r, 0, routeObjectJs, routes === null || routes === void 0 ? void 0 : routes.filter((f) => f.path !== r.path)));
|
|
86
|
+
routesObjectString += '}';
|
|
87
|
+
routesObjectDecl += '}';
|
|
88
|
+
const signature = `/**
|
|
89
|
+
* Generated by nuxt-typed-router. Do not modify
|
|
90
|
+
* */`;
|
|
91
|
+
const typedRouteListExport = `export type TypedRouteList = ${routesList
|
|
92
|
+
.map((m) => `'${m}'`)
|
|
93
|
+
.join('|\n')}`;
|
|
94
|
+
const typedRouteParamsExport = `export type TypedRouteParams = {
|
|
95
|
+
${routesParams
|
|
96
|
+
.map(({ name, params }) => `"${name}": ${params.length
|
|
97
|
+
? `{
|
|
98
|
+
${params.map((p) => `"${p.key}"?: ${p.type}`).join(',\n')}
|
|
99
|
+
}`
|
|
100
|
+
: 'never'}`)
|
|
101
|
+
.join(',\n')}
|
|
102
|
+
}`;
|
|
103
|
+
const templateRoutesRuntime = `
|
|
104
|
+
${signature}
|
|
105
|
+
|
|
106
|
+
export const ${routesObjectName} = ${routesObjectString};
|
|
107
|
+
|
|
108
|
+
${typedRouteListExport}
|
|
109
|
+
|
|
110
|
+
${typedRouteParamsExport}
|
|
111
|
+
`;
|
|
112
|
+
const templateRoutesDeclaration = `
|
|
113
|
+
${signature}
|
|
114
|
+
import type {
|
|
115
|
+
NavigationFailure,
|
|
116
|
+
RouteLocation,
|
|
117
|
+
RouteLocationNormalized,
|
|
118
|
+
RouteLocationNormalizedLoaded,
|
|
119
|
+
RouteLocationOptions,
|
|
120
|
+
RouteQueryAndHash,
|
|
121
|
+
Router,
|
|
122
|
+
} from 'vue-router';
|
|
123
|
+
|
|
124
|
+
${typedRouteListExport}
|
|
125
|
+
|
|
126
|
+
${typedRouteParamsExport}
|
|
127
|
+
|
|
128
|
+
type TypedRouteParamsStructure = {
|
|
129
|
+
[K in TypedRouteList]: Record<string, string | number> | never;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
type TypedLocationAsRelativeRaw<T extends TypedRouteList> = {
|
|
133
|
+
name?: T;
|
|
134
|
+
params?: TypedRouteParams[T];
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
type TypedRouteLocationRaw<T extends TypedRouteList> = RouteQueryAndHash &
|
|
138
|
+
TypedLocationAsRelativeRaw<T> &
|
|
139
|
+
RouteLocationOptions;
|
|
140
|
+
|
|
141
|
+
interface TypedRouter {
|
|
142
|
+
/**
|
|
143
|
+
* Remove an existing route by its name.
|
|
144
|
+
*
|
|
145
|
+
* @param name - Name of the route to remove
|
|
146
|
+
*/
|
|
147
|
+
removeRoute(name: TypedRouteList): void;
|
|
148
|
+
/**
|
|
149
|
+
* Checks if a route with a given name exists
|
|
150
|
+
*
|
|
151
|
+
* @param name - Name of the route to check
|
|
152
|
+
*/
|
|
153
|
+
hasRoute(name: TypedRouteList): boolean;
|
|
154
|
+
/**
|
|
155
|
+
* Returns the {@link RouteLocation | normalized version} of a
|
|
156
|
+
* {@link RouteLocationRaw | route location}. Also includes an \`href\` property
|
|
157
|
+
* that includes any existing \`base\`. By default the \`currentLocation\` used is
|
|
158
|
+
* \`route.currentRoute\` and should only be overriden in advanced use cases.
|
|
159
|
+
*
|
|
160
|
+
* @param to - Raw route location to resolve
|
|
161
|
+
* @param currentLocation - Optional current location to resolve against
|
|
162
|
+
*/
|
|
163
|
+
resolve<T extends TypedRouteList>(
|
|
164
|
+
to: TypedRouteLocationRaw<T>,
|
|
165
|
+
currentLocation?: RouteLocationNormalizedLoaded
|
|
166
|
+
): RouteLocation & {
|
|
167
|
+
href: string;
|
|
168
|
+
};
|
|
169
|
+
/**
|
|
170
|
+
* Programmatically navigate to a new URL by pushing an entry in the history
|
|
171
|
+
* stack.
|
|
172
|
+
*
|
|
173
|
+
* @param to - Route location to navigate to
|
|
174
|
+
*/
|
|
175
|
+
push<T extends TypedRouteList>(
|
|
176
|
+
to: TypedRouteLocationRaw<T>
|
|
177
|
+
): Promise<NavigationFailure | void | undefined>;
|
|
178
|
+
/**
|
|
179
|
+
* Programmatically navigate to a new URL by replacing the current entry in
|
|
180
|
+
* the history stack.
|
|
181
|
+
*
|
|
182
|
+
* @param to - Route location to navigate to
|
|
183
|
+
*/
|
|
184
|
+
replace<T extends TypedRouteList>(
|
|
185
|
+
to: TypedRouteLocationRaw<T>
|
|
186
|
+
): Promise<NavigationFailure | void | undefined>;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
declare module '#app' {
|
|
190
|
+
interface NuxtApp {
|
|
191
|
+
$typedRouter: TypedRouter
|
|
49
192
|
}
|
|
50
|
-
|
|
51
|
-
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
declare module '@vue/runtime-core' {
|
|
196
|
+
interface ComponentCustomProperties {
|
|
197
|
+
$typedRouter: TypedRouter
|
|
52
198
|
}
|
|
53
|
-
|
|
54
|
-
|
|
199
|
+
}
|
|
200
|
+
`;
|
|
201
|
+
await (0, save_1.saveRoutesFiles)(filePath, templateRoutesRuntime);
|
|
202
|
+
await (0, save_1.saveRoutesFiles)(definitionFilePath, templateRoutesDeclaration, 'declaration');
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
catch (e) {
|
|
206
|
+
console.error(chalk_1.default.red('Error while generating routes definitions model'), '\n' + e);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
55
209
|
module.exports = typedRouterModule;
|
|
56
210
|
module.exports.meta = require('../package.json');
|
package/lib/save.js
CHANGED
|
@@ -37,7 +37,7 @@ const defaultPrettierOptions = {
|
|
|
37
37
|
bracketSpacing: true,
|
|
38
38
|
htmlWhitespaceSensitivity: 'strict',
|
|
39
39
|
};
|
|
40
|
-
async function saveRoutesFiles(filePath, templateRoutes) {
|
|
40
|
+
async function saveRoutesFiles(filePath, templateRoutes, title = 'object') {
|
|
41
41
|
try {
|
|
42
42
|
let prettierFoundOptions = await prettier.resolveConfig(process.cwd());
|
|
43
43
|
if (!prettierFoundOptions) {
|
|
@@ -49,7 +49,7 @@ async function saveRoutesFiles(filePath, templateRoutes) {
|
|
|
49
49
|
});
|
|
50
50
|
const savePath = path_1.default.resolve(process.cwd(), filePath);
|
|
51
51
|
fs_1.default.writeFileSync(savePath, formatedModelsFile);
|
|
52
|
-
console.log(log_symbols_1.default.success, `Route
|
|
52
|
+
console.log(log_symbols_1.default.success, `Route ${title} file generated at ${chalk_1.default.blue(savePath)}`);
|
|
53
53
|
}
|
|
54
54
|
catch (e) {
|
|
55
55
|
console.error(chalk_1.default.red('Error while saving route definitions file'), '\n' + e);
|
package/lib/utils.js
CHANGED
|
@@ -44,20 +44,21 @@ function transformRouteNames(existingRoutes, stripAtFromName) {
|
|
|
44
44
|
}
|
|
45
45
|
exports.transformRouteNames = transformRouteNames;
|
|
46
46
|
function extractChunkMain(chunkName) {
|
|
47
|
+
var _a;
|
|
47
48
|
let chunkArray = chunkName === null || chunkName === void 0 ? void 0 : chunkName.split('/');
|
|
48
|
-
chunkArray === null || chunkArray === void 0 ? void 0 : chunkArray.pop();
|
|
49
|
+
(_a = chunkArray === null || chunkArray === void 0 ? void 0 : chunkArray.pop()) === null || _a === void 0 ? void 0 : _a.split('.vue')[0];
|
|
49
50
|
return chunkArray === null || chunkArray === void 0 ? void 0 : chunkArray.join('/');
|
|
50
51
|
}
|
|
51
52
|
exports.extractChunkMain = extractChunkMain;
|
|
52
53
|
function extractChunkRouteName(chunkName) {
|
|
53
|
-
return chunkName === null || chunkName === void 0 ? void 0 : chunkName.split('/')[chunkName.length - 1];
|
|
54
|
+
return chunkName === null || chunkName === void 0 ? void 0 : chunkName.split('/')[chunkName.length - 1].split('.vue')[0];
|
|
54
55
|
}
|
|
55
56
|
exports.extractChunkRouteName = extractChunkRouteName;
|
|
56
57
|
function extractMatchingSiblings(mainRoute, siblingRoutes) {
|
|
57
58
|
return siblingRoutes === null || siblingRoutes === void 0 ? void 0 : siblingRoutes.filter((s) => {
|
|
58
|
-
const chunkName = extractChunkMain(mainRoute.
|
|
59
|
-
if (chunkName) {
|
|
60
|
-
const siblingChunkName = extractChunkMain(s.
|
|
59
|
+
const chunkName = extractChunkMain(mainRoute.file);
|
|
60
|
+
if (chunkName && s.name) {
|
|
61
|
+
const siblingChunkName = extractChunkMain(s.file);
|
|
61
62
|
if (!siblingChunkName)
|
|
62
63
|
return false;
|
|
63
64
|
return chunkName === siblingChunkName;
|
|
@@ -68,9 +69,9 @@ function extractMatchingSiblings(mainRoute, siblingRoutes) {
|
|
|
68
69
|
exports.extractMatchingSiblings = extractMatchingSiblings;
|
|
69
70
|
function extractUnMatchingSiblings(mainRoute, siblingRoutes) {
|
|
70
71
|
return siblingRoutes === null || siblingRoutes === void 0 ? void 0 : siblingRoutes.filter((s) => {
|
|
71
|
-
const chunkName = extractChunkMain(mainRoute.
|
|
72
|
+
const chunkName = extractChunkMain(mainRoute.file);
|
|
72
73
|
if (chunkName) {
|
|
73
|
-
const siblingChunkName = extractChunkMain(s.
|
|
74
|
+
const siblingChunkName = extractChunkMain(s.file);
|
|
74
75
|
if (!siblingChunkName)
|
|
75
76
|
return false;
|
|
76
77
|
return chunkName !== siblingChunkName;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-typed-router",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0-alpha-0",
|
|
4
4
|
"description": "Provide autocompletion for pages route names generated by Nuxt router",
|
|
5
5
|
"main": "lib/module.js",
|
|
6
6
|
"keywords": [
|
|
@@ -15,7 +15,9 @@
|
|
|
15
15
|
"dev": "tsc -p ./tsconfig.json --pretty --watch",
|
|
16
16
|
"build": "rimraf lib && rimraf types && tsc -p ./tsconfig.json --pretty",
|
|
17
17
|
"copy-files": "copyfiles -u 1 ./src/**/*.js ./lib",
|
|
18
|
-
"prepublish": "yarn build"
|
|
18
|
+
"prepublish": "yarn build",
|
|
19
|
+
"test": "jest",
|
|
20
|
+
"test:reset": "yarn test --updateSnapshot"
|
|
19
21
|
},
|
|
20
22
|
"publishConfig": {
|
|
21
23
|
"access": "public"
|
|
@@ -41,18 +43,29 @@
|
|
|
41
43
|
"typings": "types/index.d.ts",
|
|
42
44
|
"dependencies": {
|
|
43
45
|
"chalk": "^4.1.2",
|
|
46
|
+
"jest": "^27.4.3",
|
|
44
47
|
"lodash": "^4.17.21",
|
|
45
|
-
"log-symbols": "^5.
|
|
46
|
-
"prettier": "^2.
|
|
48
|
+
"log-symbols": "^5.1.0",
|
|
49
|
+
"prettier": "^2.5.1"
|
|
47
50
|
},
|
|
48
51
|
"devDependencies": {
|
|
52
|
+
"@babel/plugin-transform-runtime": "^7.16.4",
|
|
53
|
+
"@babel/preset-env": "^7.16.4",
|
|
54
|
+
"@nuxt/kit": "^0.8.1-edge",
|
|
55
|
+
"@nuxt/test-utils": "^0.2.2",
|
|
49
56
|
"@nuxt/types": "^2.15.8",
|
|
50
|
-
"@types/
|
|
51
|
-
"@types/
|
|
52
|
-
"@types/
|
|
57
|
+
"@types/jest": "^27.0.3",
|
|
58
|
+
"@types/lodash": "^4.14.178",
|
|
59
|
+
"@types/node": "^16.11.12",
|
|
60
|
+
"@types/prettier": "^2.4.2",
|
|
61
|
+
"babel-jest": "^27.4.2",
|
|
53
62
|
"copyfiles": "^2.4.0",
|
|
63
|
+
"core-js": "^3.19.3",
|
|
64
|
+
"nuxt": "^2.15.8",
|
|
65
|
+
"playwright": "^1.17.1",
|
|
54
66
|
"rimraf": "^3.0.2",
|
|
55
|
-
"
|
|
56
|
-
"
|
|
67
|
+
"ts-jest": "^27.1.1",
|
|
68
|
+
"typescript": "^4.5.2",
|
|
69
|
+
"vue-router": "^4.0.12"
|
|
57
70
|
}
|
|
58
71
|
}
|
package/types/types.d.ts
CHANGED
|
@@ -3,3 +3,11 @@ export interface NuxtTypedRouterOptions {
|
|
|
3
3
|
routesObjectName?: string;
|
|
4
4
|
stripAtFromName?: boolean;
|
|
5
5
|
}
|
|
6
|
+
export declare type ParamDecl = {
|
|
7
|
+
key: string;
|
|
8
|
+
type: string;
|
|
9
|
+
};
|
|
10
|
+
export declare type RouteParamsDecl = {
|
|
11
|
+
name: string;
|
|
12
|
+
params: ParamDecl[];
|
|
13
|
+
};
|
package/types/vue.d.ts
CHANGED