@lark-apaas/miaoda-cli 0.1.16-alpha.ab80f52 → 0.1.16-alpha.c0b0ae2
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/dist/utils/migrate-rule.js +75 -24
- package/package.json +1 -1
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.applyMigrateRules = applyMigrateRules;
|
|
7
7
|
exports.rewriteViteConfigForFullstack = rewriteViteConfigForFullstack;
|
|
8
|
+
exports.rewriteAliasSrcPaths = rewriteAliasSrcPaths;
|
|
8
9
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
9
10
|
const node_path_1 = __importDefault(require("node:path"));
|
|
10
11
|
const sync_rule_1 = require("./sync-rule");
|
|
@@ -182,75 +183,125 @@ function applyCodemodViteConfigFullstack(rule, opts) {
|
|
|
182
183
|
return { rule, action: 'skipped', path: rel };
|
|
183
184
|
}
|
|
184
185
|
const before = node_fs_1.default.readFileSync(dest, 'utf-8');
|
|
185
|
-
const { text, changed, alreadyDone } = rewriteViteConfigForFullstack(before);
|
|
186
|
-
if (alreadyDone) {
|
|
187
|
-
(0, logger_1.log)(logPrefix, ` ○ ${rel} (fullstack: true already present)`);
|
|
186
|
+
const { text, changed, alreadyDone, aliasRewriteCount } = rewriteViteConfigForFullstack(before);
|
|
187
|
+
if (alreadyDone && aliasRewriteCount === 0) {
|
|
188
|
+
(0, logger_1.log)(logPrefix, ` ○ ${rel} (fullstack: true already present, no alias to rewrite)`);
|
|
188
189
|
return { rule, action: 'noop', path: rel };
|
|
189
190
|
}
|
|
190
|
-
if (!changed) {
|
|
191
|
+
if (!changed && aliasRewriteCount === 0) {
|
|
191
192
|
(0, logger_1.log)(logPrefix, ` ⚠ ${rel} (defineConfig call not found; please add { fullstack: true } manually)`);
|
|
192
193
|
return { rule, action: 'noop', path: rel, detail: 'defineConfig call not found' };
|
|
193
194
|
}
|
|
194
195
|
node_fs_1.default.writeFileSync(dest, text);
|
|
195
|
-
|
|
196
|
-
|
|
196
|
+
const parts = [];
|
|
197
|
+
if (changed && !alreadyDone)
|
|
198
|
+
parts.push('added { fullstack: true }');
|
|
199
|
+
if (aliasRewriteCount > 0)
|
|
200
|
+
parts.push(`rewrote ${aliasRewriteCount.toString()} alias path(s) src → client/src`);
|
|
201
|
+
(0, logger_1.log)(logPrefix, ` ✓ ${rel} (${parts.join(', ')})`);
|
|
202
|
+
return { rule, action: 'patched', path: rel, detail: parts.join('; ') };
|
|
197
203
|
}
|
|
198
204
|
/**
|
|
199
|
-
* 给 vite.config.ts 的 `defineConfig(...)` 调用加上 `{ fullstack: true }`
|
|
205
|
+
* 给 vite.config.ts 的 `defineConfig(...)` 调用加上 `{ fullstack: true }` 第二参,
|
|
206
|
+
* 顺便把 alias 字符串里 `src` 起头的路径重写到 `client/src`。
|
|
200
207
|
*
|
|
201
|
-
*
|
|
208
|
+
* 1) defineConfig 改写支持的形态:
|
|
202
209
|
* defineConfig({ ... }) → defineConfig({ ... }, { fullstack: true })
|
|
203
210
|
* defineConfig({ ... }, { ... }) → 已有第二参,把 fullstack: true 注入对象字面量
|
|
204
211
|
* defineConfig() → defineConfig({}, { fullstack: true })
|
|
212
|
+
* 跨多行 + 嵌套 arrow function / 字符串 / 模板字符串都要保留,所以用括号匹配而非正则。
|
|
213
|
+
* 已经含 `fullstack: true` 字面量则跳过(视为已迁移)。
|
|
205
214
|
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
215
|
+
* 2) alias 路径重写:vite-react 时代 user 业务代码在 `src/`,迁移后搬到 `client/src/`,
|
|
216
|
+
* vite.config 里的 alias(典型如 `'@': path.resolve(__dirname, 'src')`)必须同步改:
|
|
217
|
+
* path.resolve(<args>, 'src') → 'src' 替换为 'client/src'
|
|
218
|
+
* path.resolve(<args>, 'src/<rest>') → 同上
|
|
219
|
+
* path.join(<args>, 'src') → 同上
|
|
220
|
+
* './src' / './src/<rest>' 字符串 → './client/src' / './client/src/<rest>'
|
|
221
|
+
* 边界:仅匹配整段 'src' 起头(避免 'sub/src' 误改),保留单/双引号原样。
|
|
208
222
|
*/
|
|
209
223
|
function rewriteViteConfigForFullstack(source) {
|
|
224
|
+
// ── Step 1: 先处理 alias 路径(在 defineConfig 改写之前做,避免位置串行扰乱) ──
|
|
225
|
+
const { text: afterAlias, count: aliasRewriteCount } = rewriteAliasSrcPaths(source);
|
|
226
|
+
// ── Step 2: 加 fullstack: true ──
|
|
210
227
|
const callRe = /defineConfig\s*\(/g;
|
|
211
|
-
const m = callRe.exec(
|
|
228
|
+
const m = callRe.exec(afterAlias);
|
|
212
229
|
if (m === null) {
|
|
213
|
-
return { text:
|
|
230
|
+
return { text: afterAlias, changed: false, alreadyDone: false, aliasRewriteCount };
|
|
214
231
|
}
|
|
215
232
|
const openIdx = m.index + m[0].length - 1; // 指向 '('
|
|
216
|
-
const closeIdx = findMatchingParen(
|
|
233
|
+
const closeIdx = findMatchingParen(afterAlias, openIdx);
|
|
217
234
|
if (closeIdx < 0) {
|
|
218
|
-
return { text:
|
|
235
|
+
return { text: afterAlias, changed: false, alreadyDone: false, aliasRewriteCount };
|
|
219
236
|
}
|
|
220
|
-
const argsRaw =
|
|
237
|
+
const argsRaw = afterAlias.slice(openIdx + 1, closeIdx);
|
|
221
238
|
if (/fullstack\s*:\s*true/.test(argsRaw)) {
|
|
222
|
-
return { text:
|
|
239
|
+
return { text: afterAlias, changed: false, alreadyDone: true, aliasRewriteCount };
|
|
223
240
|
}
|
|
224
|
-
const { firstArgEnd, secondArgRange } = splitFirstTwoArgs(
|
|
241
|
+
const { firstArgEnd, secondArgRange } = splitFirstTwoArgs(afterAlias, openIdx + 1, closeIdx);
|
|
225
242
|
if (secondArgRange === null) {
|
|
226
243
|
// 单参 / 无参:在第一参之后插 ", { fullstack: true }"
|
|
227
244
|
const insertAt = firstArgEnd ?? openIdx + 1;
|
|
228
|
-
const head =
|
|
229
|
-
const tail =
|
|
245
|
+
const head = afterAlias.slice(0, insertAt);
|
|
246
|
+
const tail = afterAlias.slice(insertAt, closeIdx);
|
|
230
247
|
// 第一参是否非空(去空白)
|
|
231
|
-
const arg1 =
|
|
248
|
+
const arg1 = afterAlias.slice(openIdx + 1, insertAt).trim();
|
|
232
249
|
const sep = arg1.length === 0 ? '{}, { fullstack: true }' : ', { fullstack: true }';
|
|
233
250
|
return {
|
|
234
|
-
text: head +
|
|
251
|
+
text: head + sep + tail + afterAlias.slice(closeIdx),
|
|
235
252
|
changed: true,
|
|
236
253
|
alreadyDone: false,
|
|
254
|
+
aliasRewriteCount,
|
|
237
255
|
};
|
|
238
256
|
}
|
|
239
257
|
// 双参:在第二参对象 `{` 之后插 ` fullstack: true,`
|
|
240
|
-
const arg2 =
|
|
258
|
+
const arg2 = afterAlias.slice(secondArgRange.start, secondArgRange.end);
|
|
241
259
|
const objOpen = arg2.indexOf('{');
|
|
242
260
|
if (objOpen < 0) {
|
|
243
261
|
// 第二参不是对象字面量(罕见),保守跳过
|
|
244
|
-
return { text:
|
|
262
|
+
return { text: afterAlias, changed: false, alreadyDone: false, aliasRewriteCount };
|
|
245
263
|
}
|
|
246
264
|
const absObjOpen = secondArgRange.start + objOpen;
|
|
247
265
|
const inserted = '\n fullstack: true,';
|
|
248
266
|
return {
|
|
249
|
-
text:
|
|
267
|
+
text: afterAlias.slice(0, absObjOpen + 1) + inserted + afterAlias.slice(absObjOpen + 1),
|
|
250
268
|
changed: true,
|
|
251
269
|
alreadyDone: false,
|
|
270
|
+
aliasRewriteCount,
|
|
252
271
|
};
|
|
253
272
|
}
|
|
273
|
+
/**
|
|
274
|
+
* vite.config 里 alias 路径重写:`src` 起头的路径加 `client/` 前缀。
|
|
275
|
+
*
|
|
276
|
+
* 匹配的形态(不限制在 resolve.alias 块内 —— vite.config 顶层很少出现非 alias 用的
|
|
277
|
+
* `src` 字符串,业务 import 走 `@/...`,所以全文匹配是安全的):
|
|
278
|
+
*
|
|
279
|
+
* path.resolve(<args>, 'src') → path.resolve(<args>, 'client/src')
|
|
280
|
+
* path.resolve(<args>, 'src/<rest>') → path.resolve(<args>, 'client/src/<rest>')
|
|
281
|
+
* path.join(<args>, 'src') → 同上
|
|
282
|
+
* './src' / './src/<rest>'(独立字符串) → './client/src' / './client/src/<rest>'
|
|
283
|
+
*
|
|
284
|
+
* 已含 `client/src` 的不动(视为已迁移),`sub/src` 之类(src 不在词首)不动。
|
|
285
|
+
*/
|
|
286
|
+
function rewriteAliasSrcPaths(source) {
|
|
287
|
+
let count = 0;
|
|
288
|
+
// path.resolve(...) / path.join(...) 的最后一个参数是 'src' 或 'src/...' 起头
|
|
289
|
+
// 匹配 ['"]src[/'"],保留引号
|
|
290
|
+
const pathCallRe = /(\bpath\s*\.\s*(?:resolve|join)\s*\([^)]*?,\s*)(['"`])(src)(\/[^'"`]*)?(['"`])/g;
|
|
291
|
+
let next = source.replace(pathCallRe, (_match, prefix, q1, _src, rest, q2) => {
|
|
292
|
+
count++;
|
|
293
|
+
return `${prefix}${q1}client/src${rest ?? ''}${q2}`;
|
|
294
|
+
});
|
|
295
|
+
// 独立的相对路径字符串字面量 './src' 或 './src/...'(不在 path.resolve 参数里)
|
|
296
|
+
// 注意:path.resolve / join 已被上一步处理,这里只匹配剩下的 './src...' 字面量。
|
|
297
|
+
// 这种用法在 vite.config 较少(典型是直接给 alias 字符串值),但兜底处理。
|
|
298
|
+
const relativeRe = /(['"`])\.\/(src)(\/[^'"`]*)?(['"`])/g;
|
|
299
|
+
next = next.replace(relativeRe, (_match, q1, _src, rest, q2) => {
|
|
300
|
+
count++;
|
|
301
|
+
return `${q1}./client/src${rest ?? ''}${q2}`;
|
|
302
|
+
});
|
|
303
|
+
return { text: next, count };
|
|
304
|
+
}
|
|
254
305
|
/**
|
|
255
306
|
* 从 openIdx(指向 `(`)开始扫到匹配的 `)`,跳过 string / template / 括号嵌套。
|
|
256
307
|
* 找不到匹配返回 -1。
|