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 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.js`, routesObjectName = 'routerPagesNames', stripAtFromName = false, } = { ...this.options.typedRouter, ...moduleOptions };
12
- this.nuxt.hook('build:extendRoutes', async (existingRoutes) => {
13
- try {
14
- this.extendRoutes(async (routes) => {
15
- (0, utils_1.transformRouteNames)(routes, stripAtFromName);
16
- let routesObjectString = '{';
17
- let routeObjectJs = {};
18
- const recursiveTypedRoutes = (route, level, routeObject, siblings, parentName, hadMatching) => {
19
- const routeName = route.name;
20
- const matchingSiblings = (0, utils_1.extractMatchingSiblings)(route, siblings);
21
- const haveMatchingSiblings = !!(matchingSiblings === null || matchingSiblings === void 0 ? void 0 : matchingSiblings.length);
22
- if ((route.children && !haveMatchingSiblings) ||
23
- (!route.children && haveMatchingSiblings)) {
24
- let childrenChunks = haveMatchingSiblings ? matchingSiblings : route.children;
25
- const splittedPaths = route.path.split('/');
26
- const parentPath = splittedPaths[splittedPaths.length - 1];
27
- const nameKey = (0, lodash_1.camelCase)(parentPath || 'index');
28
- routesObjectString += `${nameKey}:{`;
29
- routeObject[nameKey] = {};
30
- childrenChunks === null || childrenChunks === void 0 ? void 0 : childrenChunks.map((r) => recursiveTypedRoutes(r, level + 1, routeObject[nameKey], (0, utils_1.extractUnMatchingSiblings)(route, siblings), nameKey, haveMatchingSiblings));
31
- routesObjectString += '},';
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
- else if (routeName) {
34
- let splitted = routeName.split('-');
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}': '${routeName}',`;
41
- routeObject[keyName] = routeName;
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
- routes.map((r) => recursiveTypedRoutes(r, 0, routeObjectJs, routes === null || routes === void 0 ? void 0 : routes.filter((f) => f.path !== r.path)));
45
- routesObjectString += '}';
46
- const templateRoutes = `export const ${routesObjectName} = ${routesObjectString};`;
47
- await (0, save_1.saveRoutesFiles)(filePath, templateRoutes);
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
- catch (e) {
51
- console.error(chalk_1.default.red('Error while generating routes definitions model'), '\n' + e);
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 definition file generated at ${chalk_1.default.blue(savePath)}`);
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);
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = ({ app }, inject) => {
4
+ return {
5
+ provide: {
6
+ typedRouter: app.router,
7
+ },
8
+ };
9
+ };
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.chunkName);
59
- if (chunkName) {
60
- const siblingChunkName = extractChunkMain(s.chunkName);
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.chunkName);
72
+ const chunkName = extractChunkMain(mainRoute.file);
72
73
  if (chunkName) {
73
- const siblingChunkName = extractChunkMain(s.chunkName);
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.2.22",
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.0.0",
46
- "prettier": "^2.4.1"
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/lodash": "^4.14.173",
51
- "@types/node": "^15.12.4",
52
- "@types/prettier": "^2.3.2",
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
- "typescript": "^4.4.3",
56
- "vue-router": "^3.5.2"
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
@@ -1,5 +1,5 @@
1
1
  import { NuxtTypedRouterOptions } from './types';
2
- declare module '@nuxt/types' {
2
+ declare module '@nuxt/schema' {
3
3
  interface NuxtConfig {
4
4
  typedRouter?: NuxtTypedRouterOptions;
5
5
  }