@heathenjs/taro-router-generator 1.0.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.
@@ -0,0 +1,33 @@
1
+ import { Page } from './type';
2
+ type PackageConfig = {
3
+ /** 包名 */
4
+ name: string;
5
+ /** 包页面根路径 */
6
+ pagePath: string;
7
+ };
8
+ type GeneratorOptions = {
9
+ /** 排除的文件 */
10
+ ignore: string[];
11
+ /** 包配置 */
12
+ packages: [PackageConfig & {
13
+ isMainPackage: true;
14
+ }, ...(PackageConfig & {
15
+ isMainPackage?: false;
16
+ })[]];
17
+ };
18
+ export declare class Generator {
19
+ private pages;
20
+ private mainPackageName;
21
+ private tsProject;
22
+ constructor({ ignore, packages }: GeneratorOptions);
23
+ /** 生成路由方法 */
24
+ private generateRouterNavigateMethod;
25
+ /** 生成页面对象的集合 */
26
+ private generateGetPagesMethod;
27
+ private createRouterSourceFile;
28
+ private overrideRouter;
29
+ generateRouter(): void;
30
+ getPages(): Page[];
31
+ getMainPackageName(): string;
32
+ }
33
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,191 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Generator = void 0;
7
+ const package_json_1 = __importDefault(require("@heathen/taro-router/package.json"));
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const ignore_1 = __importDefault(require("ignore"));
10
+ const normalize_path_1 = __importDefault(require("normalize-path"));
11
+ const path_1 = __importDefault(require("path"));
12
+ const ts_morph_1 = require("ts-morph");
13
+ const utils_1 = require("./utils");
14
+ const TARGET_MODULE_PATH = path_1.default.resolve('node_modules', package_json_1.default.name);
15
+ const ACCEPTS_INDEX_FILE = ['index.js', 'index.jsx', 'index.jsx', 'index.tsx'];
16
+ const CURRENT_PATH = process.cwd();
17
+ const SOURCE_PATH = path_1.default.resolve(CURRENT_PATH, './src');
18
+ class Generator {
19
+ constructor({ ignore, packages }) {
20
+ var _a;
21
+ this.pages = [];
22
+ this.tsProject = new ts_morph_1.Project({
23
+ tsConfigFilePath: path_1.default.resolve(TARGET_MODULE_PATH, 'tsconfig.json'),
24
+ });
25
+ const mainPackages = packages.filter((pkg) => pkg.isMainPackage);
26
+ if (!mainPackages.length) {
27
+ console.warn('[Generator]: 没有检测到主包,请确认配置');
28
+ throw new Error('[Generator]: 没有检测到主包,请确认配置');
29
+ }
30
+ else if (mainPackages.length > 1) {
31
+ console.warn('[Generator]: 存在多个配置的主包,将使用首个主包');
32
+ }
33
+ this.mainPackageName = (_a = mainPackages[0]) === null || _a === void 0 ? void 0 : _a.name;
34
+ const ignoreFilter = (0, ignore_1.default)().add(ignore).createFilter();
35
+ for (const pkg of packages) {
36
+ const pkgPagePath = path_1.default.resolve(CURRENT_PATH, pkg.pagePath);
37
+ const routeConfigSourceFiles = this.tsProject.addSourceFilesAtPaths(path_1.default.join(pkgPagePath, '/**/route.config.ts'));
38
+ const pageDirNames = fs_1.default
39
+ .readdirSync(pkgPagePath, { recursive: true, encoding: 'utf-8' })
40
+ /** 仅保留包含index的目录 */
41
+ .filter((pageDirName) => {
42
+ return (fs_1.default.statSync(path_1.default.resolve(pkgPagePath, pageDirName)).isDirectory() &&
43
+ ACCEPTS_INDEX_FILE.some((filename) => fs_1.default.existsSync(path_1.default.resolve(pkgPagePath, pageDirName, filename))));
44
+ })
45
+ // ignore配置
46
+ .filter(ignoreFilter);
47
+ for (const pageDirName of pageDirNames) {
48
+ const indexFileName = fs_1.default
49
+ .readdirSync(path_1.default.resolve(pkgPagePath, pageDirName), { encoding: 'utf8' })
50
+ .filter((filename) => ACCEPTS_INDEX_FILE.some((_filename) => filename === _filename))[0];
51
+ const configPath = path_1.default.resolve(pkgPagePath, pageDirName, 'route.config.ts');
52
+ const configSourceFile = routeConfigSourceFiles.find((_sourceFile) => {
53
+ return path_1.default.normalize(_sourceFile.compilerNode.fileName) === configPath;
54
+ });
55
+ configSourceFile === null || configSourceFile === void 0 ? void 0 : configSourceFile.refreshFromFileSystemSync();
56
+ const dirPath = path_1.default.resolve(pkgPagePath, pageDirName);
57
+ const dirName = (0, normalize_path_1.default)(pageDirName);
58
+ this.pages.push({
59
+ packageName: pkg.name,
60
+ dirName,
61
+ dirPath,
62
+ // 生成跳转路径
63
+ path: (0, normalize_path_1.default)(path_1.default.join(pkgPagePath.replace(SOURCE_PATH, ''), pageDirName, 'index')),
64
+ pageFileName: indexFileName,
65
+ routeConfig: configSourceFile
66
+ ? Array.from(configSourceFile.getExportedDeclarations().entries()).reduce((_routeConfig, [name, declarations]) => {
67
+ if (declarations.length > 1)
68
+ return _routeConfig;
69
+ const declaration = declarations[0];
70
+ switch (name) {
71
+ case 'Params':
72
+ _routeConfig.params = `import('${path_1.default.resolve(dirPath, 'route.config').replace(/\\/g, '/')}').Params`;
73
+ break;
74
+ case 'BackData':
75
+ _routeConfig.backData = `import('${path_1.default.resolve(dirPath, 'route.config').replace(/\\/g, '/')}').BackData`;
76
+ break;
77
+ case 'Ext':
78
+ _routeConfig.ext = (0, utils_1.extractValue)({
79
+ name,
80
+ declaration,
81
+ });
82
+ break;
83
+ }
84
+ return _routeConfig;
85
+ }, {})
86
+ : undefined,
87
+ });
88
+ // Logger.log(
89
+ // LOG_TYPE.GENERATE,
90
+ // `Router.${pkg.name === MAIN_PACKAGE_NAME ? '' : `${pkg.name}.`}to${formatPageDir(dirName)}`,
91
+ // );
92
+ }
93
+ }
94
+ }
95
+ /** 生成路由方法 */
96
+ generateRouterNavigateMethod() {
97
+ const packageMethodConfigs = this.pages.reduce((store, page) => {
98
+ var _a, _b, _c, _d, _e, _f;
99
+ const methodPath = [page.packageName, ...page.dirName.split('/')];
100
+ const methodName = 'to' + (0, utils_1.formatPageDir)(page.dirName);
101
+ const methodComment = `/** [View page component](${page.dirPath}/${page.pageFileName}) */`;
102
+ const methodReturnType = (_b = (_a = page.routeConfig) === null || _a === void 0 ? void 0 : _a.backData) !== null && _b !== void 0 ? _b : 'any';
103
+ const methodType = ((_c = page.routeConfig) === null || _c === void 0 ? void 0 : _c.params)
104
+ ? `<TBackData = ${methodReturnType}, TParams = ${(_e = (_d = page.routeConfig) === null || _d === void 0 ? void 0 : _d.params) !== null && _e !== void 0 ? _e : 'unknown'}>` +
105
+ '(...options: RequiredKeys<NavigateOptions & Params<NoInfer<TParams>>> extends never ' +
106
+ '? [options?: NavigateOptions & Params<NoInfer<TParams>>] : [options: NavigateOptions & Params<NoInfer<TParams>>]) => Promise<TBackData>'
107
+ : `<TBackData = ${methodReturnType}, TParams = unknown>` +
108
+ '(options?: NavigateOptions & Params<NoInfer<TParams>>) => Promise<TBackData>';
109
+ const methodBody = `function (options) {return Router.navigate({ url: "${page.path}"${((_f = page.routeConfig) === null || _f === void 0 ? void 0 : _f.ext) ? ', ext: ' + page.routeConfig.ext : ''} }, options)}`;
110
+ let methodConfigs = store.get(page.packageName);
111
+ if (!methodConfigs) {
112
+ methodConfigs = [];
113
+ store.set(page.packageName, methodConfigs);
114
+ }
115
+ methodConfigs.push({
116
+ path: methodPath,
117
+ name: methodName,
118
+ comment: methodComment,
119
+ type: methodType,
120
+ body: methodBody,
121
+ });
122
+ return store;
123
+ }, new Map());
124
+ let methodText = '';
125
+ for (const packageName of packageMethodConfigs.keys()) {
126
+ const methodConfigs = packageMethodConfigs.get(packageName);
127
+ if (packageName === this.mainPackageName) {
128
+ methodText += methodConfigs === null || methodConfigs === void 0 ? void 0 : methodConfigs.map((methodConfig) => {
129
+ return `${methodConfig.comment}\nstatic ${methodConfig.name}: ${methodConfig.type} = ${methodConfig.body}`;
130
+ }).join('\n\n');
131
+ }
132
+ else {
133
+ methodText += `
134
+ static ${packageName}: {
135
+ ${methodConfigs === null || methodConfigs === void 0 ? void 0 : methodConfigs.map((methodConfig) => {
136
+ return `${methodConfig.comment}\n${methodConfig.name}: ${methodConfig.type}`;
137
+ }).join(';\n')}
138
+ } = {
139
+ ${methodConfigs === null || methodConfigs === void 0 ? void 0 : methodConfigs.map((methodConfig) => {
140
+ return `${methodConfig.name}: ${methodConfig.body}`;
141
+ }).join(',\n')}
142
+ }
143
+ `;
144
+ }
145
+ }
146
+ return methodText;
147
+ }
148
+ /** 生成页面对象的集合 */
149
+ generateGetPagesMethod() {
150
+ return `private static _pages = ${JSON.stringify(this.pages)}
151
+ static getPages = () => { return Router._pages };`;
152
+ }
153
+ createRouterSourceFile() {
154
+ return this.tsProject.createSourceFile('temp.ts', (writer) => {
155
+ writer.writeLine('type NoInfer<T> = T extends infer U ? U : never;');
156
+ writer.writeLine('type RequiredKeys<T> = { [K in keyof T]-?: {} extends Pick<T, K> ? never : K }[keyof T]');
157
+ writer.writeLine('type Data<Q> = RequiredKeys<Q> extends never ? { data?: Q } : { data: Q }');
158
+ writer.writeLine('type Params<P> = RequiredKeys<P> extends never ? { params?: P } : { params: P }');
159
+ writer.writeLine('class Router {');
160
+ writer.write(this.generateRouterNavigateMethod());
161
+ writer.write(this.generateGetPagesMethod());
162
+ writer.writeLine('}');
163
+ });
164
+ }
165
+ overrideRouter(sourceFile) {
166
+ // 删除原有的router文件
167
+ fs_1.default.rmSync(path_1.default.resolve(TARGET_MODULE_PATH, './dist/router/index.js'), { recursive: true, force: true });
168
+ fs_1.default.rmSync(path_1.default.resolve(TARGET_MODULE_PATH, './dist/router/index.js.map'), { recursive: true, force: true });
169
+ fs_1.default.rmSync(path_1.default.resolve(TARGET_MODULE_PATH, './dist/router/index.d.ts'), { recursive: true, force: true });
170
+ const routerSourceFile = this.tsProject.addSourceFileAtPath(path_1.default.resolve(TARGET_MODULE_PATH, './src/router/index.ts'));
171
+ routerSourceFile.refreshFromFileSystemSync();
172
+ const routerClass = routerSourceFile.getClass('Router');
173
+ const staticMembers = sourceFile.getClass('Router').getStaticMembers();
174
+ routerSourceFile.addTypeAliases(sourceFile.getTypeAliases().map((m) => m.getStructure()));
175
+ routerClass.addMembers(staticMembers.map((m) => m.getStructure()));
176
+ routerSourceFile.emitSync();
177
+ }
178
+ generateRouter() {
179
+ const sourceFile = this.createRouterSourceFile();
180
+ this.overrideRouter(sourceFile);
181
+ sourceFile.delete();
182
+ }
183
+ getPages() {
184
+ return this.pages;
185
+ }
186
+ getMainPackageName() {
187
+ return this.mainPackageName;
188
+ }
189
+ }
190
+ exports.Generator = Generator;
191
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/type.d.ts ADDED
@@ -0,0 +1,19 @@
1
+ export type Page = {
2
+ dirName: string;
3
+ dirPath: string;
4
+ path: string;
5
+ pageFileName: string;
6
+ packageName: string;
7
+ routeConfig?: {
8
+ params?: string;
9
+ backData?: string;
10
+ ext?: string;
11
+ };
12
+ };
13
+ export type RouterNavigateMethodConfig = {
14
+ path: string[];
15
+ name: string;
16
+ comment: string;
17
+ type: string;
18
+ body: string;
19
+ };
package/dist/type.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=type.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type.js","sourceRoot":"","sources":["../src/type.ts"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ import { VariableDeclaration } from 'ts-morph';
2
+ export declare function extractValue(options: {
3
+ name: string;
4
+ declaration: VariableDeclaration;
5
+ }): string;
6
+ export declare function formatPageDir(dirName: string): string;
7
+ export declare function isNil(val: any): boolean;
package/dist/utils.js ADDED
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.extractValue = extractValue;
7
+ exports.formatPageDir = formatPageDir;
8
+ exports.isNil = isNil;
9
+ const path_1 = __importDefault(require("path"));
10
+ const ts_morph_1 = require("ts-morph");
11
+ function extractValue(options) {
12
+ const { name, declaration } = options;
13
+ if (!ts_morph_1.VariableDeclaration.is(declaration.getKind()))
14
+ throw Error(`${name} 应该导出变量类型`);
15
+ const text = declaration.getFullText();
16
+ return text.split('=', 2)[1].trim();
17
+ }
18
+ function formatPageDir(dirName) {
19
+ return dirName
20
+ .replace(new RegExp(`(\\-|\\${path_1.default.sep})`, 'g'), '_')
21
+ .replace(/\_(\w)/g, (_, letter) => {
22
+ return letter.toUpperCase();
23
+ })
24
+ .replace(/^\S/, (s) => s.toUpperCase());
25
+ }
26
+ function isNil(val) {
27
+ return val === undefined || val === null;
28
+ }
29
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";;;;;AAGA,oCAQC;AAED,sCAOC;AAED,sBAEC;AAxBD,gDAAwB;AACxB,uCAA+C;AAE/C,SAAgB,YAAY,CAAC,OAA2D;IACtF,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC;IAEtC,IAAI,CAAC,8BAAmB,CAAC,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;QAAE,MAAM,KAAK,CAAC,GAAG,IAAI,WAAW,CAAC,CAAC;IAEpF,MAAM,IAAI,GAAG,WAAW,CAAC,WAAW,EAAE,CAAC;IAEvC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AACtC,CAAC;AAED,SAAgB,aAAa,CAAC,OAAe;IAC3C,OAAO,OAAO;SACX,OAAO,CAAC,IAAI,MAAM,CAAC,UAAU,cAAI,CAAC,GAAG,GAAG,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC;SACpD,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;QAChC,OAAO,MAAM,CAAC,WAAW,EAAE,CAAC;IAC9B,CAAC,CAAC;SACD,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AAC5C,CAAC;AAED,SAAgB,KAAK,CAAC,GAAQ;IAC5B,OAAO,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,IAAI,CAAC;AAC3C,CAAC"}
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@heathenjs/taro-router-generator",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "scripts": {
8
+ "prod": "tsc -p ./tsconfig.json",
9
+ "clean": "rimraf dist",
10
+ "build": "pnpm run clean && pnpm run prod",
11
+ "tsc": "tsc -p ./tsconfig.json --noEmit",
12
+ "lint": "eslint --ext .ts --max-warnings 0 \"./src\" "
13
+ },
14
+ "keywords": [],
15
+ "author": "",
16
+ "license": "ISC",
17
+ "peerDependencies": {
18
+ "@tarojs/service": "^3.6.35",
19
+ "@tarojs/taro": "^3.6.35"
20
+ },
21
+ "dependencies": {
22
+ "normalize-path": "^3.0.0",
23
+ "query-string": "^7.0.0",
24
+ "ts-morph": "^21.0.1"
25
+ },
26
+ "devDependencies": {
27
+ "@types/normalize-path": "^3.0.0",
28
+ "@heathenjs/taro-router": "workspace:*"
29
+ }
30
+ }
package/src/index.ts ADDED
@@ -0,0 +1,240 @@
1
+ import routerModulePkgJson from '@heathenjs/taro-router/package.json';
2
+ import fs from 'fs';
3
+ import createIgnore from 'ignore';
4
+ import normalize from 'normalize-path';
5
+ import path from 'path';
6
+ import { Project, SourceFile } from 'ts-morph';
7
+ import { Page, RouterNavigateMethodConfig } from './type';
8
+ import { extractValue, formatPageDir } from './utils';
9
+
10
+ const TARGET_MODULE_PATH = path.resolve('node_modules', routerModulePkgJson.name);
11
+ const ACCEPTS_INDEX_FILE = ['index.js', 'index.jsx', 'index.jsx', 'index.tsx'];
12
+ const CURRENT_PATH = process.cwd();
13
+ const SOURCE_PATH = path.resolve(CURRENT_PATH, './src');
14
+
15
+ type PackageConfig = {
16
+ /** 包名 */
17
+ name: string;
18
+ /** 包页面根路径 */
19
+ pagePath: string;
20
+ };
21
+
22
+ type GeneratorOptions = {
23
+ /** 排除的文件 */
24
+ ignore: string[];
25
+ /** 包配置 */
26
+ packages: [PackageConfig & { isMainPackage: true }, ...(PackageConfig & { isMainPackage?: false })[]];
27
+ };
28
+
29
+ export class Generator {
30
+ private pages: Page[] = [];
31
+ private mainPackageName: string;
32
+ private tsProject = new Project({
33
+ tsConfigFilePath: path.resolve(TARGET_MODULE_PATH, 'tsconfig.json'),
34
+ });
35
+
36
+ constructor({ ignore, packages }: GeneratorOptions) {
37
+ const mainPackages = packages.filter((pkg) => pkg.isMainPackage);
38
+ if (!mainPackages.length) {
39
+ console.warn('[Generator]: 没有检测到主包,请确认配置');
40
+ throw new Error('[Generator]: 没有检测到主包,请确认配置');
41
+ } else if (mainPackages.length > 1) {
42
+ console.warn('[Generator]: 存在多个配置的主包,将使用首个主包');
43
+ }
44
+ this.mainPackageName = mainPackages[0]?.name;
45
+
46
+ const ignoreFilter = createIgnore().add(ignore).createFilter();
47
+
48
+ for (const pkg of packages) {
49
+ const pkgPagePath = path.resolve(CURRENT_PATH, pkg.pagePath);
50
+ const routeConfigSourceFiles = this.tsProject.addSourceFilesAtPaths(
51
+ path.join(pkgPagePath, '/**/route.config.ts'),
52
+ );
53
+ const pageDirNames = fs
54
+ .readdirSync(pkgPagePath, { recursive: true, encoding: 'utf-8' })
55
+ /** 仅保留包含index的目录 */
56
+ .filter((pageDirName) => {
57
+ return (
58
+ fs.statSync(path.resolve(pkgPagePath, pageDirName)).isDirectory() &&
59
+ ACCEPTS_INDEX_FILE.some((filename) => fs.existsSync(path.resolve(pkgPagePath, pageDirName, filename)))
60
+ );
61
+ })
62
+ // ignore配置
63
+ .filter(ignoreFilter);
64
+
65
+ for (const pageDirName of pageDirNames) {
66
+ const indexFileName = fs
67
+ .readdirSync(path.resolve(pkgPagePath, pageDirName), { encoding: 'utf8' })
68
+ .filter((filename) => ACCEPTS_INDEX_FILE.some((_filename) => filename === _filename))[0];
69
+
70
+ const configPath = path.resolve(pkgPagePath, pageDirName, 'route.config.ts');
71
+ const configSourceFile = routeConfigSourceFiles.find((_sourceFile) => {
72
+ return path.normalize(_sourceFile.compilerNode.fileName) === configPath;
73
+ });
74
+ configSourceFile?.refreshFromFileSystemSync();
75
+
76
+ const dirPath = path.resolve(pkgPagePath, pageDirName);
77
+ const dirName = normalize(pageDirName);
78
+
79
+ this.pages.push({
80
+ packageName: pkg.name,
81
+ dirName,
82
+ dirPath,
83
+ // 生成跳转路径
84
+ path: normalize(path.join(pkgPagePath.replace(SOURCE_PATH, ''), pageDirName, 'index')),
85
+ pageFileName: indexFileName,
86
+ routeConfig: configSourceFile
87
+ ? Array.from(configSourceFile.getExportedDeclarations().entries()).reduce(
88
+ (_routeConfig, [name, declarations]) => {
89
+ if (declarations.length > 1) return _routeConfig;
90
+
91
+ const declaration = declarations[0] as any;
92
+ switch (name) {
93
+ case 'Params':
94
+ _routeConfig.params = `import('${path.resolve(dirPath, 'route.config').replace(/\\/g, '/')}').Params`;
95
+ break;
96
+ case 'BackData':
97
+ _routeConfig.backData = `import('${path.resolve(dirPath, 'route.config').replace(/\\/g, '/')}').BackData`;
98
+ break;
99
+ case 'Ext':
100
+ _routeConfig.ext = extractValue({
101
+ name,
102
+ declaration,
103
+ });
104
+ break;
105
+ }
106
+ return _routeConfig;
107
+ },
108
+ {} as NonNullable<Page['routeConfig']>,
109
+ )
110
+ : undefined,
111
+ });
112
+
113
+ // Logger.log(
114
+ // LOG_TYPE.GENERATE,
115
+ // `Router.${pkg.name === MAIN_PACKAGE_NAME ? '' : `${pkg.name}.`}to${formatPageDir(dirName)}`,
116
+ // );
117
+ }
118
+ }
119
+ }
120
+
121
+ /** 生成路由方法 */
122
+ private generateRouterNavigateMethod() {
123
+ const packageMethodConfigs = this.pages.reduce((store, page) => {
124
+ const methodPath = [page.packageName, ...page.dirName.split('/')];
125
+ const methodName = 'to' + formatPageDir(page.dirName);
126
+ const methodComment = `/** [View page component](${page.dirPath}/${page.pageFileName}) */`;
127
+ const methodReturnType = page.routeConfig?.backData ?? 'any';
128
+ const methodType = page.routeConfig?.params
129
+ ? `<TBackData = ${methodReturnType}, TParams = ${page.routeConfig?.params ?? 'unknown'}>` +
130
+ '(...options: RequiredKeys<NavigateOptions & Params<NoInfer<TParams>>> extends never ' +
131
+ '? [options?: NavigateOptions & Params<NoInfer<TParams>>] : [options: NavigateOptions & Params<NoInfer<TParams>>]) => Promise<TBackData>'
132
+ : `<TBackData = ${methodReturnType}, TParams = unknown>` +
133
+ '(options?: NavigateOptions & Params<NoInfer<TParams>>) => Promise<TBackData>';
134
+ const methodBody = `function (options) {return Router.navigate({ url: "${page.path}"${
135
+ page.routeConfig?.ext ? ', ext: ' + page.routeConfig.ext : ''
136
+ } }, options)}`;
137
+
138
+ let methodConfigs = store.get(page.packageName);
139
+ if (!methodConfigs) {
140
+ methodConfigs = [];
141
+ store.set(page.packageName, methodConfigs);
142
+ }
143
+ methodConfigs.push({
144
+ path: methodPath,
145
+ name: methodName,
146
+ comment: methodComment,
147
+ type: methodType,
148
+ body: methodBody,
149
+ });
150
+ return store;
151
+ }, new Map<string, RouterNavigateMethodConfig[]>());
152
+
153
+ let methodText = '';
154
+ for (const packageName of packageMethodConfigs.keys()) {
155
+ const methodConfigs = packageMethodConfigs.get(packageName);
156
+ if (packageName === this.mainPackageName) {
157
+ methodText += methodConfigs
158
+ ?.map((methodConfig) => {
159
+ return `${methodConfig.comment}\nstatic ${methodConfig.name}: ${methodConfig.type} = ${methodConfig.body}`;
160
+ })
161
+ .join('\n\n');
162
+ } else {
163
+ methodText += `
164
+ static ${packageName}: {
165
+ ${methodConfigs
166
+ ?.map((methodConfig) => {
167
+ return `${methodConfig.comment}\n${methodConfig.name}: ${methodConfig.type}`;
168
+ })
169
+ .join(';\n')}
170
+ } = {
171
+ ${methodConfigs
172
+ ?.map((methodConfig) => {
173
+ return `${methodConfig.name}: ${methodConfig.body}`;
174
+ })
175
+ .join(',\n')}
176
+ }
177
+ `;
178
+ }
179
+ }
180
+
181
+ return methodText;
182
+ }
183
+
184
+ /** 生成页面对象的集合 */
185
+ private generateGetPagesMethod() {
186
+ return `private static _pages = ${JSON.stringify(this.pages)}
187
+ static getPages = () => { return Router._pages };`;
188
+ }
189
+
190
+ private createRouterSourceFile() {
191
+ return this.tsProject.createSourceFile('temp.ts', (writer) => {
192
+ writer.writeLine('type NoInfer<T> = T extends infer U ? U : never;');
193
+ writer.writeLine('type RequiredKeys<T> = { [K in keyof T]-?: {} extends Pick<T, K> ? never : K }[keyof T]');
194
+ writer.writeLine('type Data<Q> = RequiredKeys<Q> extends never ? { data?: Q } : { data: Q }');
195
+ writer.writeLine('type Params<P> = RequiredKeys<P> extends never ? { params?: P } : { params: P }');
196
+ writer.writeLine('class Router {');
197
+
198
+ writer.write(this.generateRouterNavigateMethod());
199
+ writer.write(this.generateGetPagesMethod());
200
+
201
+ writer.writeLine('}');
202
+ });
203
+ }
204
+
205
+ private overrideRouter(sourceFile: SourceFile) {
206
+ // 删除原有的router文件
207
+ fs.rmSync(path.resolve(TARGET_MODULE_PATH, './dist/router/index.js'), { recursive: true, force: true });
208
+ fs.rmSync(path.resolve(TARGET_MODULE_PATH, './dist/router/index.js.map'), { recursive: true, force: true });
209
+ fs.rmSync(path.resolve(TARGET_MODULE_PATH, './dist/router/index.d.ts'), { recursive: true, force: true });
210
+
211
+ const routerSourceFile = this.tsProject.addSourceFileAtPath(
212
+ path.resolve(TARGET_MODULE_PATH, './src/router/index.ts'),
213
+ );
214
+
215
+ routerSourceFile.refreshFromFileSystemSync();
216
+
217
+ const routerClass = routerSourceFile.getClass('Router')!;
218
+ const staticMembers = sourceFile.getClass('Router')!.getStaticMembers();
219
+ routerSourceFile.addTypeAliases(sourceFile.getTypeAliases().map((m) => m.getStructure()));
220
+ routerClass.addMembers(staticMembers.map((m) => m.getStructure() as any));
221
+
222
+ routerSourceFile.emitSync();
223
+ }
224
+
225
+ public generateRouter() {
226
+ const sourceFile = this.createRouterSourceFile();
227
+
228
+ this.overrideRouter(sourceFile);
229
+
230
+ sourceFile.delete();
231
+ }
232
+
233
+ public getPages() {
234
+ return this.pages;
235
+ }
236
+
237
+ public getMainPackageName() {
238
+ return this.mainPackageName;
239
+ }
240
+ }
package/src/type.ts ADDED
@@ -0,0 +1,20 @@
1
+ export type Page = {
2
+ dirName: string;
3
+ dirPath: string;
4
+ path: string;
5
+ pageFileName: string;
6
+ packageName: string;
7
+ routeConfig?: {
8
+ params?: string;
9
+ backData?: string;
10
+ ext?: string;
11
+ };
12
+ };
13
+
14
+ export type RouterNavigateMethodConfig = {
15
+ path: string[];
16
+ name: string;
17
+ comment: string;
18
+ type: string;
19
+ body: string;
20
+ };
package/src/utils.ts ADDED
@@ -0,0 +1,25 @@
1
+ import path from 'path';
2
+ import { VariableDeclaration } from 'ts-morph';
3
+
4
+ export function extractValue(options: { name: string; declaration: VariableDeclaration }) {
5
+ const { name, declaration } = options;
6
+
7
+ if (!VariableDeclaration.is(declaration.getKind())) throw Error(`${name} 应该导出变量类型`);
8
+
9
+ const text = declaration.getFullText();
10
+
11
+ return text.split('=', 2)[1].trim();
12
+ }
13
+
14
+ export function formatPageDir(dirName: string) {
15
+ return dirName
16
+ .replace(new RegExp(`(\\-|\\${path.sep})`, 'g'), '_')
17
+ .replace(/\_(\w)/g, (_, letter) => {
18
+ return letter.toUpperCase();
19
+ })
20
+ .replace(/^\S/, (s) => s.toUpperCase());
21
+ }
22
+
23
+ export function isNil(val: any) {
24
+ return val === undefined || val === null;
25
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "extends": "../../tsconfig",
3
+ "compilerOptions": {
4
+ "module": "CommonJS",
5
+ "removeComments": false,
6
+ "moduleResolution": "node",
7
+ "experimentalDecorators": false,
8
+ "noImplicitAny": false,
9
+ "allowSyntheticDefaultImports": true,
10
+ "esModuleInterop": true,
11
+ "noUnusedLocals": false,
12
+ "noUnusedParameters": false,
13
+ "strictNullChecks": true,
14
+ "resolveJsonModule": true,
15
+ "sourceMap": true,
16
+ "skipLibCheck": true,
17
+ "target": "es2015",
18
+ "outDir": "dist",
19
+ "rootDir": "./src",
20
+ "declaration": true,
21
+ "noEmit": false
22
+ },
23
+ "include": ["./**/*.ts", "./**/*.tsx", "src/index.ts"],
24
+ "exclude": ["node_modules", "dist"]
25
+ }