@lark-apaas/fullstack-rspack-preset 1.0.32-alpha.37 → 1.0.32-alpha.39

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.
@@ -1,3 +1,4 @@
1
+ export { normalizeBasePath, parseRoutesFromFile } from '@lark-apaas/devtool-kits';
1
2
  interface RouteParserPluginOptions {
2
3
  appPath?: string;
3
4
  outputPath?: string;
@@ -8,24 +9,7 @@ declare class RouteParserPlugin {
8
9
  private lastAppPathHash;
9
10
  private cachedRoutes;
10
11
  constructor(options?: RouteParserPluginOptions);
11
- private normalizeBasePath;
12
- private log;
13
12
  apply(compiler: any): void;
14
13
  private shouldRegenerateRoutes;
15
- private calculateFileHash;
16
- private parseRoutes;
17
- private isRouteComponent;
18
- private extractRouteInfo;
19
- private buildFullPath;
20
- private evaluateTemplateLiteral;
21
14
  }
22
- export declare function normalizeBasePath(basePath: string): string;
23
- /**
24
- * Parse routes from the app file at build time.
25
- * @param appPath - Path to app.tsx (relative to cwd or absolute)
26
- * @param basePath - Base path prefix for routes (e.g., '/my_plugin')
27
- */
28
- export declare function parseRoutesFromFile(appPath: string, basePath: string): Array<{
29
- path: string;
30
- }>;
31
15
  export default RouteParserPlugin;
@@ -32,70 +32,33 @@ var __importStar = (this && this.__importStar) || (function () {
32
32
  return result;
33
33
  };
34
34
  })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
35
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.normalizeBasePath = normalizeBasePath;
40
- exports.parseRoutesFromFile = parseRoutesFromFile;
36
+ exports.parseRoutesFromFile = exports.normalizeBasePath = void 0;
41
37
  const fs = __importStar(require("fs"));
42
38
  const path = __importStar(require("path"));
43
- const crypto = __importStar(require("crypto"));
44
- const parser_1 = require("@babel/parser");
45
- const traverse_1 = __importDefault(require("@babel/traverse"));
46
- const t = __importStar(require("@babel/types"));
39
+ const devtool_kits_1 = require("@lark-apaas/devtool-kits");
40
+ // Re-export for backward compatibility
41
+ var devtool_kits_2 = require("@lark-apaas/devtool-kits");
42
+ Object.defineProperty(exports, "normalizeBasePath", { enumerable: true, get: function () { return devtool_kits_2.normalizeBasePath; } });
43
+ Object.defineProperty(exports, "parseRoutesFromFile", { enumerable: true, get: function () { return devtool_kits_2.parseRoutesFromFile; } });
47
44
  class RouteParserPlugin {
48
45
  constructor(options = {}) {
49
46
  this.lastAppPathHash = null;
50
47
  this.cachedRoutes = null;
51
- // 从环境变量读取 basePath,并规范化(确保以 / 开头,不以 / 结尾)
52
48
  const envBasePath = process.env.CLIENT_BASE_PATH || '';
53
- const normalizedBasePath = this.normalizeBasePath(options.basePath ?? envBasePath);
49
+ const normalizedBasePath = (0, devtool_kits_1.normalizeBasePath)(options.basePath ?? envBasePath);
54
50
  this.options = {
55
51
  appPath: options.appPath || './client/src/app.tsx',
56
52
  outputPath: options.outputPath || './dist/client/routes.json',
57
53
  basePath: normalizedBasePath,
58
54
  };
59
55
  }
60
- normalizeBasePath(basePath) {
61
- if (!basePath || basePath === '/') {
62
- return '';
63
- }
64
- // 确保以 / 开头
65
- let normalized = basePath.startsWith('/') ? basePath : `/${basePath}`;
66
- // 确保不以 / 结尾
67
- if (normalized.endsWith('/')) {
68
- normalized = normalized.slice(0, -1);
69
- }
70
- return normalized;
71
- }
72
- log(level, message, ...args) {
73
- const prefix = '[route-parser]';
74
- const logMessage = `${prefix} ${message}`;
75
- switch (level) {
76
- case 'log':
77
- console.log(logMessage, ...args);
78
- break;
79
- case 'warn':
80
- console.warn(logMessage, ...args);
81
- break;
82
- case 'error':
83
- console.error(logMessage, ...args);
84
- break;
85
- case 'info':
86
- console.info(logMessage, ...args);
87
- break;
88
- default:
89
- console.log(logMessage, ...args);
90
- }
91
- }
92
56
  apply(compiler) {
93
57
  const pluginName = 'RouteParserPlugin';
94
58
  compiler.hooks.emit.tapAsync(pluginName, (compilation, callback) => {
95
59
  try {
96
60
  if (this.shouldRegenerateRoutes()) {
97
- const routes = this.parseRoutes();
98
- this.cachedRoutes = routes;
61
+ this.cachedRoutes = (0, devtool_kits_1.parseRoutesFromFile)(this.options.appPath, this.options.basePath);
99
62
  }
100
63
  const routesJson = JSON.stringify(this.cachedRoutes, null, 2);
101
64
  compilation.assets['routes.json'] = {
@@ -105,7 +68,7 @@ class RouteParserPlugin {
105
68
  callback();
106
69
  }
107
70
  catch (error) {
108
- this.log('warn', '⚠️ 路由解析失败,使用默认路由:', error.message);
71
+ (0, devtool_kits_1.routeParserLog)('warn', '⚠️ 路由解析失败,使用默认路由:', error.message);
109
72
  const { basePath } = this.options;
110
73
  const defaultPath = basePath ? `${basePath}/` : '/';
111
74
  const defaultRoutes = [{ path: defaultPath }];
@@ -122,10 +85,10 @@ class RouteParserPlugin {
122
85
  try {
123
86
  const appFilePath = path.resolve(process.cwd(), this.options.appPath);
124
87
  if (!fs.existsSync(appFilePath)) {
125
- this.log('warn', `⚠️ App.tsx 文件不存在: ${appFilePath}`);
88
+ (0, devtool_kits_1.routeParserLog)('warn', `⚠️ App.tsx 文件不存在: ${appFilePath}`);
126
89
  return false;
127
90
  }
128
- const currentHash = this.calculateFileHash(appFilePath);
91
+ const currentHash = (0, devtool_kits_1.calculateFileHash)(appFilePath);
129
92
  if (this.lastAppPathHash === currentHash && this.cachedRoutes) {
130
93
  return false;
131
94
  }
@@ -133,321 +96,9 @@ class RouteParserPlugin {
133
96
  return true;
134
97
  }
135
98
  catch (error) {
136
- this.log('warn', '⚠️ 检查文件变更时出错:', error.message);
99
+ (0, devtool_kits_1.routeParserLog)('warn', '⚠️ 检查文件变更时出错:', error.message);
137
100
  return true;
138
101
  }
139
102
  }
140
- calculateFileHash(filePath) {
141
- try {
142
- const content = fs.readFileSync(filePath, 'utf-8');
143
- return crypto.createHash('md5').update(content).digest('hex');
144
- }
145
- catch (error) {
146
- this.log('warn', '⚠️ 计算文件哈希失败:', error.message);
147
- return null;
148
- }
149
- }
150
- parseRoutes() {
151
- try {
152
- const appFilePath = path.resolve(process.cwd(), this.options.appPath);
153
- if (!fs.existsSync(appFilePath)) {
154
- throw new Error(`App.tsx 文件不存在: ${appFilePath}`);
155
- }
156
- const sourceCode = fs.readFileSync(appFilePath, 'utf-8');
157
- const ast = (0, parser_1.parse)(sourceCode, {
158
- sourceType: 'module',
159
- plugins: [
160
- 'jsx',
161
- 'typescript',
162
- 'decorators-legacy',
163
- 'classProperties',
164
- 'objectRestSpread',
165
- 'functionBind',
166
- 'exportDefaultFrom',
167
- 'exportNamespaceFrom',
168
- 'dynamicImport',
169
- 'nullishCoalescingOperator',
170
- 'optionalChaining'
171
- ]
172
- });
173
- const routeSet = new Set();
174
- const routeStack = [];
175
- const self = this;
176
- (0, traverse_1.default)(ast, {
177
- JSXElement: {
178
- enter(path) {
179
- const { openingElement } = path.node;
180
- if (self.isRouteComponent(openingElement)) {
181
- const routeInfo = self.extractRouteInfo(openingElement);
182
- routeStack.push(routeInfo);
183
- }
184
- },
185
- exit(path) {
186
- const { openingElement } = path.node;
187
- if (self.isRouteComponent(openingElement)) {
188
- const currentRoute = routeStack.pop();
189
- if (currentRoute && currentRoute.path === '*') {
190
- return;
191
- }
192
- if (currentRoute && (currentRoute.path || currentRoute.index)) {
193
- const fullPath = self.buildFullPath(routeStack, currentRoute);
194
- if (fullPath) {
195
- routeSet.add(fullPath);
196
- }
197
- }
198
- }
199
- }
200
- }
201
- });
202
- const { basePath } = this.options;
203
- const routes = Array.from(routeSet).map(routePath => ({
204
- path: basePath ? `${basePath}${routePath}` : routePath,
205
- }));
206
- // 默认路由也需要加上 basePath
207
- const defaultPath = basePath ? `${basePath}/` : '/';
208
- return routes.length > 0 ? routes : [{ path: defaultPath }];
209
- }
210
- catch (error) {
211
- this.log('warn', '⚠️ 路由解析失败,使用默认路由:', error.message);
212
- const { basePath } = this.options;
213
- const defaultPath = basePath ? `${basePath}/` : '/';
214
- return [{ path: defaultPath }];
215
- }
216
- }
217
- isRouteComponent(openingElement) {
218
- return (t.isJSXIdentifier(openingElement.name) &&
219
- openingElement.name.name === 'Route');
220
- }
221
- extractRouteInfo(openingElement) {
222
- const routeInfo = {};
223
- openingElement.attributes.forEach((attr) => {
224
- if (t.isJSXAttribute(attr)) {
225
- const name = attr.name.name;
226
- let value;
227
- if (attr.value) {
228
- if (t.isStringLiteral(attr.value)) {
229
- value = attr.value.value;
230
- }
231
- else if (t.isJSXExpressionContainer(attr.value)) {
232
- const expression = attr.value.expression;
233
- if (t.isStringLiteral(expression)) {
234
- value = expression.value;
235
- }
236
- else if (t.isTemplateLiteral(expression)) {
237
- value = this.evaluateTemplateLiteral(expression);
238
- }
239
- else {
240
- value = true;
241
- }
242
- }
243
- }
244
- else {
245
- value = true;
246
- }
247
- routeInfo[name] = value;
248
- }
249
- });
250
- return routeInfo;
251
- }
252
- buildFullPath(routeStack, currentRoute) {
253
- let fullPath = '';
254
- for (let i = 0; i < routeStack.length; i++) {
255
- if (routeStack[i].path) {
256
- let parentPath = routeStack[i].path;
257
- if (!parentPath.startsWith('/'))
258
- parentPath = `/${parentPath}`;
259
- if (parentPath.endsWith('/') && parentPath !== '/') {
260
- parentPath = parentPath.slice(0, -1);
261
- }
262
- fullPath += parentPath === '/' ? '' : parentPath;
263
- }
264
- }
265
- if (currentRoute.index) {
266
- return fullPath || '/';
267
- }
268
- else if (currentRoute.path) {
269
- const routePath = currentRoute.path;
270
- if (routePath === '*') {
271
- return null;
272
- }
273
- if (!routePath.startsWith('/')) {
274
- fullPath = `${fullPath}/${routePath}`;
275
- }
276
- else {
277
- fullPath = routePath;
278
- }
279
- if (fullPath === '')
280
- fullPath = '/';
281
- if (!fullPath.startsWith('/'))
282
- fullPath = `/${fullPath}`;
283
- return fullPath;
284
- }
285
- return null;
286
- }
287
- evaluateTemplateLiteral(templateLiteral) {
288
- const quasis = templateLiteral.quasis;
289
- const expressions = templateLiteral.expressions;
290
- if (quasis.length === 1 && expressions.length === 0) {
291
- return quasis[0].value.raw;
292
- }
293
- return quasis.map((q) => q.value.raw).join('');
294
- }
295
- }
296
- // Standalone module-level helpers (mirroring private class methods) for external callers
297
- function normalizeBasePath(basePath) {
298
- if (!basePath || basePath === '/') {
299
- return '';
300
- }
301
- let normalized = basePath.startsWith('/') ? basePath : `/${basePath}`;
302
- if (normalized.endsWith('/')) {
303
- normalized = normalized.slice(0, -1);
304
- }
305
- return normalized;
306
- }
307
- function _isRouteComponent(openingElement) {
308
- return (t.isJSXIdentifier(openingElement.name) &&
309
- openingElement.name.name === 'Route');
310
- }
311
- function _evaluateTemplateLiteral(templateLiteral) {
312
- const quasis = templateLiteral.quasis;
313
- const expressions = templateLiteral.expressions;
314
- if (quasis.length === 1 && expressions.length === 0) {
315
- return quasis[0].value.raw;
316
- }
317
- return quasis.map((q) => q.value.raw).join('');
318
- }
319
- function _extractRouteInfo(openingElement) {
320
- const routeInfo = {};
321
- openingElement.attributes.forEach((attr) => {
322
- if (t.isJSXAttribute(attr)) {
323
- const name = attr.name.name;
324
- let value;
325
- if (attr.value) {
326
- if (t.isStringLiteral(attr.value)) {
327
- value = attr.value.value;
328
- }
329
- else if (t.isJSXExpressionContainer(attr.value)) {
330
- const expression = attr.value.expression;
331
- if (t.isStringLiteral(expression)) {
332
- value = expression.value;
333
- }
334
- else if (t.isTemplateLiteral(expression)) {
335
- value = _evaluateTemplateLiteral(expression);
336
- }
337
- else {
338
- value = true;
339
- }
340
- }
341
- }
342
- else {
343
- value = true;
344
- }
345
- routeInfo[name] = value;
346
- }
347
- });
348
- return routeInfo;
349
- }
350
- function _buildFullPath(routeStack, currentRoute) {
351
- let fullPath = '';
352
- for (let i = 0; i < routeStack.length; i++) {
353
- if (routeStack[i].path) {
354
- let parentPath = routeStack[i].path;
355
- if (!parentPath.startsWith('/'))
356
- parentPath = `/${parentPath}`;
357
- if (parentPath.endsWith('/') && parentPath !== '/') {
358
- parentPath = parentPath.slice(0, -1);
359
- }
360
- fullPath += parentPath === '/' ? '' : parentPath;
361
- }
362
- }
363
- if (currentRoute.index) {
364
- return fullPath || '/';
365
- }
366
- else if (currentRoute.path) {
367
- const routePath = currentRoute.path;
368
- if (routePath === '*') {
369
- return null;
370
- }
371
- if (!routePath.startsWith('/')) {
372
- fullPath = `${fullPath}/${routePath}`;
373
- }
374
- else {
375
- fullPath = routePath;
376
- }
377
- if (fullPath === '')
378
- fullPath = '/';
379
- if (!fullPath.startsWith('/'))
380
- fullPath = `/${fullPath}`;
381
- return fullPath;
382
- }
383
- return null;
384
- }
385
- /**
386
- * Parse routes from the app file at build time.
387
- * @param appPath - Path to app.tsx (relative to cwd or absolute)
388
- * @param basePath - Base path prefix for routes (e.g., '/my_plugin')
389
- */
390
- function parseRoutesFromFile(appPath, basePath) {
391
- const prefix = '[route-parser]';
392
- const defaultPath = basePath ? `${basePath}/` : '/';
393
- try {
394
- const appFilePath = path.resolve(process.cwd(), appPath);
395
- if (!fs.existsSync(appFilePath)) {
396
- throw new Error(`App.tsx file does not exist: ${appFilePath}`);
397
- }
398
- const sourceCode = fs.readFileSync(appFilePath, 'utf-8');
399
- const ast = (0, parser_1.parse)(sourceCode, {
400
- sourceType: 'module',
401
- plugins: [
402
- 'jsx',
403
- 'typescript',
404
- 'decorators-legacy',
405
- 'classProperties',
406
- 'objectRestSpread',
407
- 'functionBind',
408
- 'exportDefaultFrom',
409
- 'exportNamespaceFrom',
410
- 'dynamicImport',
411
- 'nullishCoalescingOperator',
412
- 'optionalChaining'
413
- ]
414
- });
415
- const routeSet = new Set();
416
- const routeStack = [];
417
- (0, traverse_1.default)(ast, {
418
- JSXElement: {
419
- enter(nodePath) {
420
- const { openingElement } = nodePath.node;
421
- if (_isRouteComponent(openingElement)) {
422
- const routeInfo = _extractRouteInfo(openingElement);
423
- routeStack.push(routeInfo);
424
- }
425
- },
426
- exit(nodePath) {
427
- const { openingElement } = nodePath.node;
428
- if (_isRouteComponent(openingElement)) {
429
- const currentRoute = routeStack.pop();
430
- if (currentRoute && currentRoute.path === '*') {
431
- return;
432
- }
433
- if (currentRoute && (currentRoute.path || currentRoute.index)) {
434
- const fullPath = _buildFullPath(routeStack, currentRoute);
435
- if (fullPath) {
436
- routeSet.add(fullPath);
437
- }
438
- }
439
- }
440
- }
441
- }
442
- });
443
- const routes = Array.from(routeSet).map(routePath => ({
444
- path: basePath ? `${basePath}${routePath}` : routePath,
445
- }));
446
- return routes.length > 0 ? routes : [{ path: defaultPath }];
447
- }
448
- catch (error) {
449
- console.warn(`${prefix} Route parsing failed, using default routes:`, error.message);
450
- return [{ path: defaultPath }];
451
- }
452
103
  }
453
104
  exports.default = RouteParserPlugin;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-apaas/fullstack-rspack-preset",
3
- "version": "1.0.32-alpha.37",
3
+ "version": "1.0.32-alpha.39",
4
4
  "files": [
5
5
  "lib",
6
6
  "patches",
@@ -31,7 +31,7 @@
31
31
  "@babel/parser": "^7.28.0",
32
32
  "@babel/traverse": "^7.28.0",
33
33
  "@babel/types": "^7.28.2",
34
- "@lark-apaas/devtool-kits": "1.2.17-alpha.50",
34
+ "@lark-apaas/devtool-kits": "1.2.17-alpha.52",
35
35
  "@lark-apaas/miaoda-inspector-babel-plugin": "^1.0.2",
36
36
  "@lark-apaas/styled-jsx": "^1.0.1",
37
37
  "@rspack/plugin-react-refresh": "^1.5.1",