@lark-apaas/fullstack-cli 1.1.6-alpha.7 → 1.1.6-alpha.9
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/README.md +0 -3
- package/dist/index.js +821 -216
- package/package.json +1 -1
- package/templates/scripts/dev.sh +1 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import
|
|
3
|
-
import
|
|
2
|
+
import fs15 from "fs";
|
|
3
|
+
import path14 from "path";
|
|
4
4
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
5
5
|
import { config as dotenvConfig } from "dotenv";
|
|
6
6
|
|
|
@@ -1271,117 +1271,289 @@ async function listAll(summary) {
|
|
|
1271
1271
|
}
|
|
1272
1272
|
}
|
|
1273
1273
|
|
|
1274
|
-
// src/commands/capability/
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
// AI 相关
|
|
1284
|
-
"ai/generate_text": "@official_ai/text_generation",
|
|
1285
|
-
"ai/chat_completion": "@official_ai/chat_completion"
|
|
1286
|
-
// 其他
|
|
1287
|
-
// 根据实际需要添加更多映射
|
|
1288
|
-
};
|
|
1289
|
-
function mergeMapping(customMapping) {
|
|
1290
|
-
if (!customMapping) {
|
|
1291
|
-
return { ...DEFAULT_MAPPING };
|
|
1274
|
+
// src/commands/capability/index.ts
|
|
1275
|
+
var listCommand2 = {
|
|
1276
|
+
name: "list",
|
|
1277
|
+
description: "List capability configurations",
|
|
1278
|
+
aliases: ["ls"],
|
|
1279
|
+
register(program) {
|
|
1280
|
+
program.command(this.name).alias("ls").description(this.description).option("--summary", "Return raw capability config (without hydration)").option("--id <id>", "Specify capability ID").action(async (options) => {
|
|
1281
|
+
await list2(options);
|
|
1282
|
+
});
|
|
1292
1283
|
}
|
|
1293
|
-
|
|
1284
|
+
};
|
|
1285
|
+
var capabilityCommandGroup = {
|
|
1286
|
+
name: "capability",
|
|
1287
|
+
description: "Manage capability configurations",
|
|
1288
|
+
commands: [listCommand2]
|
|
1289
|
+
};
|
|
1290
|
+
|
|
1291
|
+
// src/commands/migration/version-manager.ts
|
|
1292
|
+
import fs6 from "fs";
|
|
1293
|
+
import path6 from "path";
|
|
1294
|
+
var PACKAGE_JSON = "package.json";
|
|
1295
|
+
var VERSION_FIELD = "migrationVersion";
|
|
1296
|
+
function getPackageJsonPath2() {
|
|
1297
|
+
return path6.join(process.cwd(), PACKAGE_JSON);
|
|
1294
1298
|
}
|
|
1295
|
-
function
|
|
1296
|
-
const
|
|
1297
|
-
if (!
|
|
1298
|
-
throw new Error(
|
|
1299
|
-
`Unknown sourceActionID: "${sourceActionID}". Please provide mapping via --mapping option or add to default mapping.`
|
|
1300
|
-
);
|
|
1299
|
+
function getCurrentVersion() {
|
|
1300
|
+
const pkgPath = getPackageJsonPath2();
|
|
1301
|
+
if (!fs6.existsSync(pkgPath)) {
|
|
1302
|
+
throw new Error("package.json not found");
|
|
1301
1303
|
}
|
|
1302
|
-
|
|
1304
|
+
const pkg2 = JSON.parse(fs6.readFileSync(pkgPath, "utf-8"));
|
|
1305
|
+
return pkg2[VERSION_FIELD] ?? 0;
|
|
1306
|
+
}
|
|
1307
|
+
function setCurrentVersion(version) {
|
|
1308
|
+
const pkgPath = getPackageJsonPath2();
|
|
1309
|
+
const pkg2 = JSON.parse(fs6.readFileSync(pkgPath, "utf-8"));
|
|
1310
|
+
pkg2[VERSION_FIELD] = version;
|
|
1311
|
+
fs6.writeFileSync(pkgPath, JSON.stringify(pkg2, null, 2) + "\n", "utf-8");
|
|
1303
1312
|
}
|
|
1304
1313
|
|
|
1305
|
-
// src/commands/
|
|
1314
|
+
// src/commands/migration/versions/v001_capability/json-migrator/detector.ts
|
|
1315
|
+
import fs8 from "fs";
|
|
1316
|
+
import path8 from "path";
|
|
1317
|
+
|
|
1318
|
+
// src/commands/migration/versions/v001_capability/utils.ts
|
|
1306
1319
|
import fs7 from "fs";
|
|
1307
1320
|
import path7 from "path";
|
|
1321
|
+
var CAPABILITIES_DIR2 = "server/capabilities";
|
|
1322
|
+
function getProjectRoot3() {
|
|
1323
|
+
return process.cwd();
|
|
1324
|
+
}
|
|
1325
|
+
function getCapabilitiesDir2() {
|
|
1326
|
+
return path7.join(getProjectRoot3(), CAPABILITIES_DIR2);
|
|
1327
|
+
}
|
|
1328
|
+
function getPluginManifestPath2(pluginKey) {
|
|
1329
|
+
return path7.join(getProjectRoot3(), "node_modules", pluginKey, "manifest.json");
|
|
1330
|
+
}
|
|
1308
1331
|
|
|
1309
|
-
// src/commands/
|
|
1310
|
-
import fs6 from "fs";
|
|
1311
|
-
import path6 from "path";
|
|
1332
|
+
// src/commands/migration/versions/v001_capability/json-migrator/detector.ts
|
|
1312
1333
|
function detectJsonMigration() {
|
|
1313
|
-
const capabilitiesDir =
|
|
1314
|
-
const oldFilePath =
|
|
1315
|
-
if (!
|
|
1316
|
-
return {
|
|
1317
|
-
needsMigration: false,
|
|
1318
|
-
reason: "capabilities directory does not exist"
|
|
1319
|
-
};
|
|
1320
|
-
}
|
|
1321
|
-
if (!fs6.existsSync(oldFilePath)) {
|
|
1334
|
+
const capabilitiesDir = getCapabilitiesDir2();
|
|
1335
|
+
const oldFilePath = path8.join(capabilitiesDir, "capabilities.json");
|
|
1336
|
+
if (!fs8.existsSync(oldFilePath)) {
|
|
1322
1337
|
return {
|
|
1323
1338
|
needsMigration: false,
|
|
1324
|
-
reason: "capabilities.json not found
|
|
1339
|
+
reason: "capabilities.json not found"
|
|
1325
1340
|
};
|
|
1326
1341
|
}
|
|
1327
1342
|
try {
|
|
1328
|
-
const content =
|
|
1343
|
+
const content = fs8.readFileSync(oldFilePath, "utf-8");
|
|
1329
1344
|
const parsed = JSON.parse(content);
|
|
1330
|
-
|
|
1331
|
-
return {
|
|
1332
|
-
needsMigration: false,
|
|
1333
|
-
reason: "capabilities.json is not array format"
|
|
1334
|
-
};
|
|
1335
|
-
}
|
|
1336
|
-
if (parsed.length === 0) {
|
|
1337
|
-
return {
|
|
1338
|
-
needsMigration: false,
|
|
1339
|
-
reason: "capabilities.json is empty array"
|
|
1340
|
-
};
|
|
1341
|
-
}
|
|
1342
|
-
const firstItem = parsed[0];
|
|
1343
|
-
if (!firstItem.sourceActionID) {
|
|
1344
|
-
return {
|
|
1345
|
-
needsMigration: false,
|
|
1346
|
-
reason: "capabilities.json does not contain old format (missing sourceActionID)"
|
|
1347
|
-
};
|
|
1348
|
-
}
|
|
1345
|
+
const capabilities = Array.isArray(parsed) ? parsed : [];
|
|
1349
1346
|
return {
|
|
1350
1347
|
needsMigration: true,
|
|
1351
|
-
oldCapabilities:
|
|
1348
|
+
oldCapabilities: capabilities,
|
|
1352
1349
|
oldFilePath
|
|
1353
1350
|
};
|
|
1354
1351
|
} catch (error) {
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1352
|
+
return {
|
|
1353
|
+
needsMigration: true,
|
|
1354
|
+
oldCapabilities: [],
|
|
1355
|
+
oldFilePath
|
|
1356
|
+
};
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
// src/commands/migration/versions/v001_capability/check.ts
|
|
1361
|
+
async function check(options) {
|
|
1362
|
+
const detection = detectJsonMigration();
|
|
1363
|
+
if (!detection.needsMigration) {
|
|
1364
|
+
return {
|
|
1365
|
+
needsMigration: false,
|
|
1366
|
+
message: detection.reason || "No migration needed"
|
|
1367
|
+
};
|
|
1368
|
+
}
|
|
1369
|
+
const capabilityCount = detection.oldCapabilities?.length || 0;
|
|
1370
|
+
return {
|
|
1371
|
+
needsMigration: true,
|
|
1372
|
+
message: `found ${capabilityCount} capabilities to migrate`,
|
|
1373
|
+
items: [
|
|
1374
|
+
`server/capabilities/capabilities.json \u2192 server/capabilities/*.json`,
|
|
1375
|
+
`${capabilityCount} capabilities will be converted to new format`
|
|
1376
|
+
]
|
|
1377
|
+
};
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
// src/commands/migration/versions/v001_capability/json-migrator/index.ts
|
|
1381
|
+
import fs9 from "fs";
|
|
1382
|
+
import path9 from "path";
|
|
1383
|
+
|
|
1384
|
+
// src/commands/migration/versions/v001_capability/mapping.ts
|
|
1385
|
+
var DEFAULT_PLUGIN_VERSION = "1.0.0";
|
|
1386
|
+
var PLUGIN_MAPPING = {
|
|
1387
|
+
// 飞书相关
|
|
1388
|
+
"official_feishu/send_message": {
|
|
1389
|
+
pluginKey: "@official-plugins/send-feishu-message",
|
|
1390
|
+
pluginVersion: "1.0.0"
|
|
1391
|
+
},
|
|
1392
|
+
"official_feishu/create_group": {
|
|
1393
|
+
pluginKey: "@official-plugins/feishu-group-create",
|
|
1394
|
+
pluginVersion: "1.0.0"
|
|
1395
|
+
},
|
|
1396
|
+
// AI 相关
|
|
1397
|
+
"official_ai/text_generate": {
|
|
1398
|
+
pluginKey: "@official-plugins/ai-text-generate",
|
|
1399
|
+
pluginVersion: "1.0.0"
|
|
1400
|
+
},
|
|
1401
|
+
"official_ai/image_understanding": {
|
|
1402
|
+
pluginKey: "@official-plugins/ai-image-understanding",
|
|
1403
|
+
pluginVersion: "1.0.0"
|
|
1404
|
+
},
|
|
1405
|
+
"official_ai/image_generate": {
|
|
1406
|
+
pluginKey: "@official-plugins/ai-text-to-image",
|
|
1407
|
+
pluginVersion: "1.0.0"
|
|
1408
|
+
}
|
|
1409
|
+
};
|
|
1410
|
+
function getPluginInfo(sourceActionID) {
|
|
1411
|
+
const item = PLUGIN_MAPPING[sourceActionID];
|
|
1412
|
+
if (!item) {
|
|
1413
|
+
throw new Error(
|
|
1414
|
+
`Unknown sourceActionID: "${sourceActionID}". This sourceActionID is not in the built-in mapping. Please contact the developer to add it.`
|
|
1415
|
+
);
|
|
1416
|
+
}
|
|
1417
|
+
return {
|
|
1418
|
+
pluginKey: item.pluginKey,
|
|
1419
|
+
pluginVersion: item.pluginVersion ?? DEFAULT_PLUGIN_VERSION
|
|
1420
|
+
};
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1423
|
+
// src/commands/migration/versions/v001_capability/json-migrator/form-value-transformers/send-feishu-message.ts
|
|
1424
|
+
function transformSendFeishuMessage(input) {
|
|
1425
|
+
const actionInput = input;
|
|
1426
|
+
const cardContent = actionInput.card_content;
|
|
1427
|
+
const header = cardContent?.header;
|
|
1428
|
+
const bodyElements = cardContent?.body?.elements;
|
|
1429
|
+
const title = {
|
|
1430
|
+
title: header?.title?.content ?? "",
|
|
1431
|
+
titleColor: header?.template
|
|
1432
|
+
};
|
|
1433
|
+
const markdownElement = bodyElements?.find((el) => el.tag === "markdown");
|
|
1434
|
+
const content = markdownElement?.content ?? "";
|
|
1435
|
+
const columnSet = bodyElements?.find((el) => el.tag === "column_set");
|
|
1436
|
+
const buttons = columnSet?.columns?.flatMap(
|
|
1437
|
+
(column) => column.elements?.filter((el) => el.tag === "button").map((btn) => ({
|
|
1438
|
+
style: btn.type,
|
|
1439
|
+
text: btn.text?.content,
|
|
1440
|
+
url: btn.behaviors?.[0]?.default_url
|
|
1441
|
+
})) ?? []
|
|
1442
|
+
) ?? [];
|
|
1443
|
+
return {
|
|
1444
|
+
sender: "bot",
|
|
1445
|
+
receiverUserList: actionInput.receiver_user_list ?? [],
|
|
1446
|
+
receiverGroupList: actionInput.receiver_group_list ?? [],
|
|
1447
|
+
title,
|
|
1448
|
+
content,
|
|
1449
|
+
buttons
|
|
1450
|
+
};
|
|
1451
|
+
}
|
|
1452
|
+
|
|
1453
|
+
// src/commands/migration/versions/v001_capability/json-migrator/form-value-transformers/feishu-group-create.ts
|
|
1454
|
+
function transformFeishuGroupCreate(input) {
|
|
1455
|
+
const actionInput = input;
|
|
1456
|
+
return {
|
|
1457
|
+
owner: actionInput.owner,
|
|
1458
|
+
members: actionInput.members ?? [],
|
|
1459
|
+
groupName: actionInput.group_name ?? "",
|
|
1460
|
+
groupDescription: actionInput.group_description ?? "",
|
|
1461
|
+
welcomeMessage: actionInput.welcome_message ?? ""
|
|
1462
|
+
};
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
// src/commands/migration/versions/v001_capability/json-migrator/form-value-transformers/utils.ts
|
|
1466
|
+
function convertToNumber(value, defaultValue) {
|
|
1467
|
+
if (value === void 0 || value === "") {
|
|
1468
|
+
return defaultValue;
|
|
1469
|
+
}
|
|
1470
|
+
const num = Number(value);
|
|
1471
|
+
return isNaN(num) ? defaultValue : num;
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
// src/commands/migration/versions/v001_capability/json-migrator/form-value-transformers/ai-text-generate.ts
|
|
1475
|
+
var DEFAULT_MODEL_ID = "87";
|
|
1476
|
+
var DEFAULT_MAX_TOKENS = 8192;
|
|
1477
|
+
var DEFAULT_TEMPERATURE = 0.7;
|
|
1478
|
+
function transformAITextGenerate(input) {
|
|
1479
|
+
const actionInput = input;
|
|
1480
|
+
return {
|
|
1481
|
+
modelID: actionInput.model_id ?? DEFAULT_MODEL_ID,
|
|
1482
|
+
prompt: actionInput.prompt ?? "",
|
|
1483
|
+
modelParams: {
|
|
1484
|
+
maxTokens: convertToNumber(actionInput.max_tokens, DEFAULT_MAX_TOKENS),
|
|
1485
|
+
temperature: convertToNumber(actionInput.temperature, DEFAULT_TEMPERATURE)
|
|
1360
1486
|
}
|
|
1361
|
-
|
|
1487
|
+
};
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1490
|
+
// src/commands/migration/versions/v001_capability/json-migrator/form-value-transformers/ai-image-understanding.ts
|
|
1491
|
+
var DEFAULT_MODEL_ID2 = "87";
|
|
1492
|
+
var DEFAULT_MAX_TOKENS2 = 8192;
|
|
1493
|
+
var DEFAULT_TEMPERATURE2 = 0.7;
|
|
1494
|
+
function transformAIImageUnderstanding(input) {
|
|
1495
|
+
const actionInput = input;
|
|
1496
|
+
return {
|
|
1497
|
+
modelID: actionInput.model_id ?? DEFAULT_MODEL_ID2,
|
|
1498
|
+
prompt: actionInput.prompt ?? "",
|
|
1499
|
+
modelParams: {
|
|
1500
|
+
maxTokens: convertToNumber(actionInput.max_tokens, DEFAULT_MAX_TOKENS2),
|
|
1501
|
+
temperature: convertToNumber(actionInput.temperature, DEFAULT_TEMPERATURE2)
|
|
1502
|
+
}
|
|
1503
|
+
};
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1506
|
+
// src/commands/migration/versions/v001_capability/json-migrator/form-value-transformers/ai-text-to-image.ts
|
|
1507
|
+
var DEFAULT_RATIO = "1:1";
|
|
1508
|
+
var DEFAULT_WATERMARK = true;
|
|
1509
|
+
function transformAITextToImage(input) {
|
|
1510
|
+
const actionInput = input;
|
|
1511
|
+
return {
|
|
1512
|
+
prompt: actionInput.prompt ?? "",
|
|
1513
|
+
ratio: actionInput.image_ratio ?? DEFAULT_RATIO,
|
|
1514
|
+
watermark: actionInput.watermark ?? DEFAULT_WATERMARK
|
|
1515
|
+
};
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1518
|
+
// src/commands/migration/versions/v001_capability/json-migrator/form-value-transformers/index.ts
|
|
1519
|
+
var TRANSFORMER_MAP = {
|
|
1520
|
+
"official_feishu/send_message": transformSendFeishuMessage,
|
|
1521
|
+
"official_feishu/create_group": transformFeishuGroupCreate,
|
|
1522
|
+
"official_ai/text_generate": transformAITextGenerate,
|
|
1523
|
+
"official_ai/image_understanding": transformAIImageUnderstanding,
|
|
1524
|
+
"official_ai/image_generate": transformAITextToImage
|
|
1525
|
+
};
|
|
1526
|
+
function transformFormValue(sourceActionID, actionInput) {
|
|
1527
|
+
const transformer = TRANSFORMER_MAP[sourceActionID];
|
|
1528
|
+
if (!transformer) {
|
|
1529
|
+
throw new Error(
|
|
1530
|
+
`No formValue transformer found for sourceActionID: "${sourceActionID}". Please implement the transformer and add it to TRANSFORMER_MAP.`
|
|
1531
|
+
);
|
|
1362
1532
|
}
|
|
1533
|
+
return transformer(actionInput);
|
|
1363
1534
|
}
|
|
1364
1535
|
|
|
1365
|
-
// src/commands/
|
|
1366
|
-
function transformCapability(old
|
|
1367
|
-
const pluginKey =
|
|
1536
|
+
// src/commands/migration/versions/v001_capability/json-migrator/transformer.ts
|
|
1537
|
+
function transformCapability(old) {
|
|
1538
|
+
const { pluginKey, pluginVersion } = getPluginInfo(old.sourceActionID);
|
|
1539
|
+
const formValue = transformFormValue(old.sourceActionID, old.actionInput);
|
|
1368
1540
|
return {
|
|
1369
1541
|
id: old.id,
|
|
1370
1542
|
pluginKey,
|
|
1371
|
-
pluginVersion
|
|
1543
|
+
pluginVersion,
|
|
1372
1544
|
name: old.name,
|
|
1373
1545
|
description: old.desc,
|
|
1374
1546
|
paramsSchema: old.inputSchema,
|
|
1375
|
-
formValue
|
|
1547
|
+
formValue,
|
|
1376
1548
|
createdAt: old.createdAt,
|
|
1377
1549
|
updatedAt: old.updatedAt
|
|
1378
1550
|
};
|
|
1379
1551
|
}
|
|
1380
|
-
function transformCapabilities(oldCapabilities
|
|
1381
|
-
return oldCapabilities.map((old) => transformCapability(old
|
|
1552
|
+
function transformCapabilities(oldCapabilities) {
|
|
1553
|
+
return oldCapabilities.map((old) => transformCapability(old));
|
|
1382
1554
|
}
|
|
1383
1555
|
|
|
1384
|
-
// src/commands/
|
|
1556
|
+
// src/commands/migration/versions/v001_capability/json-migrator/index.ts
|
|
1385
1557
|
async function migrateJsonFiles(options) {
|
|
1386
1558
|
const detection = detectJsonMigration();
|
|
1387
1559
|
if (!detection.needsMigration) {
|
|
@@ -1405,7 +1577,7 @@ async function migrateJsonFiles(options) {
|
|
|
1405
1577
|
}
|
|
1406
1578
|
let newCapabilities;
|
|
1407
1579
|
try {
|
|
1408
|
-
newCapabilities = transformCapabilities(oldCapabilities
|
|
1580
|
+
newCapabilities = transformCapabilities(oldCapabilities);
|
|
1409
1581
|
} catch (error) {
|
|
1410
1582
|
return {
|
|
1411
1583
|
success: false,
|
|
@@ -1427,29 +1599,26 @@ async function migrateJsonFiles(options) {
|
|
|
1427
1599
|
capabilities: newCapabilities
|
|
1428
1600
|
};
|
|
1429
1601
|
}
|
|
1430
|
-
const capabilitiesDir =
|
|
1602
|
+
const capabilitiesDir = getCapabilitiesDir2();
|
|
1431
1603
|
for (const cap of newCapabilities) {
|
|
1432
|
-
const filePath =
|
|
1604
|
+
const filePath = path9.join(capabilitiesDir, `${cap.id}.json`);
|
|
1433
1605
|
const content = JSON.stringify(cap, null, 2);
|
|
1434
|
-
|
|
1606
|
+
fs9.writeFileSync(filePath, content, "utf-8");
|
|
1435
1607
|
console.log(` \u2713 Created: ${cap.id}.json`);
|
|
1436
1608
|
}
|
|
1437
|
-
const backupPath = oldFilePath + ".backup";
|
|
1438
|
-
fs7.renameSync(oldFilePath, backupPath);
|
|
1439
1609
|
return {
|
|
1440
1610
|
success: true,
|
|
1441
1611
|
skipped: false,
|
|
1442
1612
|
count: newCapabilities.length,
|
|
1443
|
-
capabilities: newCapabilities
|
|
1444
|
-
backupPath
|
|
1613
|
+
capabilities: newCapabilities
|
|
1445
1614
|
};
|
|
1446
1615
|
}
|
|
1447
1616
|
|
|
1448
|
-
// src/commands/
|
|
1449
|
-
import
|
|
1617
|
+
// src/commands/migration/versions/v001_capability/plugin-installer/detector.ts
|
|
1618
|
+
import fs10 from "fs";
|
|
1450
1619
|
function isPluginInstalled2(pluginKey) {
|
|
1451
|
-
const manifestPath =
|
|
1452
|
-
return
|
|
1620
|
+
const manifestPath = getPluginManifestPath2(pluginKey);
|
|
1621
|
+
return fs10.existsSync(manifestPath);
|
|
1453
1622
|
}
|
|
1454
1623
|
function detectPluginsToInstall(capabilities) {
|
|
1455
1624
|
const pluginKeys = /* @__PURE__ */ new Set();
|
|
@@ -1468,7 +1637,7 @@ function detectPluginsToInstall(capabilities) {
|
|
|
1468
1637
|
return { toInstall, alreadyInstalled };
|
|
1469
1638
|
}
|
|
1470
1639
|
|
|
1471
|
-
// src/commands/
|
|
1640
|
+
// src/commands/migration/versions/v001_capability/plugin-installer/index.ts
|
|
1472
1641
|
async function installPlugins(capabilities, options) {
|
|
1473
1642
|
const detection = detectPluginsToInstall(capabilities);
|
|
1474
1643
|
const result = {
|
|
@@ -1524,14 +1693,14 @@ async function installPlugins(capabilities, options) {
|
|
|
1524
1693
|
return result;
|
|
1525
1694
|
}
|
|
1526
1695
|
|
|
1527
|
-
// src/commands/
|
|
1528
|
-
import
|
|
1529
|
-
import
|
|
1696
|
+
// src/commands/migration/versions/v001_capability/code-migrator/index.ts
|
|
1697
|
+
import fs12 from "fs";
|
|
1698
|
+
import path11 from "path";
|
|
1530
1699
|
import * as ts4 from "typescript";
|
|
1531
1700
|
|
|
1532
|
-
// src/commands/
|
|
1533
|
-
import
|
|
1534
|
-
import
|
|
1701
|
+
// src/commands/migration/versions/v001_capability/code-migrator/scanner.ts
|
|
1702
|
+
import fs11 from "fs";
|
|
1703
|
+
import path10 from "path";
|
|
1535
1704
|
var EXCLUDED_DIRS = [
|
|
1536
1705
|
"node_modules",
|
|
1537
1706
|
"dist",
|
|
@@ -1546,9 +1715,9 @@ var EXCLUDED_PATTERNS = [
|
|
|
1546
1715
|
/\.d\.ts$/
|
|
1547
1716
|
];
|
|
1548
1717
|
function scanDirectory(dir, files = []) {
|
|
1549
|
-
const entries =
|
|
1718
|
+
const entries = fs11.readdirSync(dir, { withFileTypes: true });
|
|
1550
1719
|
for (const entry of entries) {
|
|
1551
|
-
const fullPath =
|
|
1720
|
+
const fullPath = path10.join(dir, entry.name);
|
|
1552
1721
|
if (entry.isDirectory()) {
|
|
1553
1722
|
if (EXCLUDED_DIRS.includes(entry.name)) {
|
|
1554
1723
|
continue;
|
|
@@ -1564,14 +1733,14 @@ function scanDirectory(dir, files = []) {
|
|
|
1564
1733
|
return files;
|
|
1565
1734
|
}
|
|
1566
1735
|
function scanServerFiles() {
|
|
1567
|
-
const serverDir =
|
|
1568
|
-
if (!
|
|
1736
|
+
const serverDir = path10.join(getProjectRoot3(), "server");
|
|
1737
|
+
if (!fs11.existsSync(serverDir)) {
|
|
1569
1738
|
return [];
|
|
1570
1739
|
}
|
|
1571
1740
|
return scanDirectory(serverDir);
|
|
1572
1741
|
}
|
|
1573
1742
|
function hasCapabilityImport(filePath) {
|
|
1574
|
-
const content =
|
|
1743
|
+
const content = fs11.readFileSync(filePath, "utf-8");
|
|
1575
1744
|
return /import\s+.*from\s+['"][^'"]*capabilities[^'"]*['"]/.test(content);
|
|
1576
1745
|
}
|
|
1577
1746
|
function scanFilesToMigrate() {
|
|
@@ -1579,7 +1748,7 @@ function scanFilesToMigrate() {
|
|
|
1579
1748
|
return allFiles.filter(hasCapabilityImport);
|
|
1580
1749
|
}
|
|
1581
1750
|
|
|
1582
|
-
// src/commands/
|
|
1751
|
+
// src/commands/migration/versions/v001_capability/code-migrator/analyzers/import-analyzer.ts
|
|
1583
1752
|
import * as ts from "typescript";
|
|
1584
1753
|
function extractCapabilityId(importPath) {
|
|
1585
1754
|
const match = importPath.match(/capabilities\/([^/]+)$/);
|
|
@@ -1643,7 +1812,7 @@ function analyzeImports(sourceFile) {
|
|
|
1643
1812
|
return imports;
|
|
1644
1813
|
}
|
|
1645
1814
|
|
|
1646
|
-
// src/commands/
|
|
1815
|
+
// src/commands/migration/versions/v001_capability/code-migrator/analyzers/call-site-analyzer.ts
|
|
1647
1816
|
import * as ts2 from "typescript";
|
|
1648
1817
|
function analyzeCallSites(sourceFile, imports) {
|
|
1649
1818
|
const callSites = [];
|
|
@@ -1693,7 +1862,7 @@ function analyzeCallSites(sourceFile, imports) {
|
|
|
1693
1862
|
return callSites;
|
|
1694
1863
|
}
|
|
1695
1864
|
|
|
1696
|
-
// src/commands/
|
|
1865
|
+
// src/commands/migration/versions/v001_capability/code-migrator/analyzers/class-analyzer.ts
|
|
1697
1866
|
import * as ts3 from "typescript";
|
|
1698
1867
|
function hasDecorator(node, decoratorName) {
|
|
1699
1868
|
const decorators = ts3.getDecorators(node);
|
|
@@ -1769,10 +1938,14 @@ function canAutoMigrate(classInfo) {
|
|
|
1769
1938
|
return { canMigrate: true };
|
|
1770
1939
|
}
|
|
1771
1940
|
|
|
1772
|
-
// src/commands/
|
|
1773
|
-
var CAPABILITY_SERVICE_IMPORT = `import { CapabilityService } from '@lark-apaas/nestjs-core';`;
|
|
1941
|
+
// src/commands/migration/versions/v001_capability/code-migrator/transformers/import-transformer.ts
|
|
1942
|
+
var CAPABILITY_SERVICE_IMPORT = `import { CapabilityService, migrationAdaptor } from '@lark-apaas/fullstack-nestjs-core';`;
|
|
1943
|
+
var INJECT_IMPORT = `import { Inject } from '@nestjs/common';`;
|
|
1774
1944
|
function hasCapabilityServiceImport(content) {
|
|
1775
|
-
return /import\s+.*CapabilityService.*from\s+['"]@lark-apaas\/nestjs-core['"]/.test(content);
|
|
1945
|
+
return /import\s+.*CapabilityService.*from\s+['"]@lark-apaas\/fullstack-nestjs-core['"]/.test(content);
|
|
1946
|
+
}
|
|
1947
|
+
function hasInjectImport(content) {
|
|
1948
|
+
return /import\s+.*\bInject\b.*from\s+['"]@nestjs\/common['"]/.test(content);
|
|
1776
1949
|
}
|
|
1777
1950
|
function findImportInsertPosition(content) {
|
|
1778
1951
|
const importRegex = /^import\s+.*?from\s+['"][^'"]+['"];?\s*$/gm;
|
|
@@ -1805,11 +1978,20 @@ function transformImports(content, imports) {
|
|
|
1805
1978
|
}
|
|
1806
1979
|
importAdded = true;
|
|
1807
1980
|
}
|
|
1981
|
+
if (!hasInjectImport(result)) {
|
|
1982
|
+
const insertPos = findImportInsertPosition(result);
|
|
1983
|
+
if (insertPos > 0) {
|
|
1984
|
+
result = result.substring(0, insertPos) + "\n" + INJECT_IMPORT + result.substring(insertPos);
|
|
1985
|
+
} else {
|
|
1986
|
+
result = INJECT_IMPORT + "\n" + result;
|
|
1987
|
+
}
|
|
1988
|
+
importAdded = true;
|
|
1989
|
+
}
|
|
1808
1990
|
return { content: result, importAdded };
|
|
1809
1991
|
}
|
|
1810
1992
|
|
|
1811
|
-
// src/commands/
|
|
1812
|
-
var INJECTION_PARAM = "private readonly capabilityService: CapabilityService";
|
|
1993
|
+
// src/commands/migration/versions/v001_capability/code-migrator/transformers/injection-transformer.ts
|
|
1994
|
+
var INJECTION_PARAM = "@Inject() private readonly capabilityService: CapabilityService";
|
|
1813
1995
|
function hasCapabilityServiceInjection(content) {
|
|
1814
1996
|
return /capabilityService\s*:\s*CapabilityService/.test(content);
|
|
1815
1997
|
}
|
|
@@ -1838,7 +2020,7 @@ function addInjection(content, classInfo) {
|
|
|
1838
2020
|
return { content: result, injectionAdded: result !== content };
|
|
1839
2021
|
}
|
|
1840
2022
|
|
|
1841
|
-
// src/commands/
|
|
2023
|
+
// src/commands/migration/versions/v001_capability/code-migrator/transformers/call-site-transformer.ts
|
|
1842
2024
|
function generateNewCall(capabilityId, originalCall) {
|
|
1843
2025
|
const parenIndex = originalCall.indexOf("(");
|
|
1844
2026
|
if (parenIndex === -1) {
|
|
@@ -1846,14 +2028,14 @@ function generateNewCall(capabilityId, originalCall) {
|
|
|
1846
2028
|
}
|
|
1847
2029
|
const argsStart = parenIndex + 1;
|
|
1848
2030
|
const argsEnd = originalCall.lastIndexOf(")");
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
2031
|
+
let args = "{}";
|
|
2032
|
+
if (argsEnd !== -1 && argsEnd > argsStart) {
|
|
2033
|
+
const extractedArgs = originalCall.substring(argsStart, argsEnd).trim();
|
|
2034
|
+
if (extractedArgs) {
|
|
2035
|
+
args = extractedArgs;
|
|
2036
|
+
}
|
|
1855
2037
|
}
|
|
1856
|
-
return `this.capabilityService.load('${capabilityId}').call('run', ${args})`;
|
|
2038
|
+
return `migrationAdaptor(this.capabilityService.load('${capabilityId}').call('run', ${args}))`;
|
|
1857
2039
|
}
|
|
1858
2040
|
function transformCallSites(content, callSites) {
|
|
1859
2041
|
const sortedCallSites = [...callSites].sort((a, b) => b.start - a.start);
|
|
@@ -1869,9 +2051,9 @@ function transformCallSites(content, callSites) {
|
|
|
1869
2051
|
return { content: result, replacedCount };
|
|
1870
2052
|
}
|
|
1871
2053
|
|
|
1872
|
-
// src/commands/
|
|
2054
|
+
// src/commands/migration/versions/v001_capability/code-migrator/index.ts
|
|
1873
2055
|
function analyzeFile(filePath) {
|
|
1874
|
-
const content =
|
|
2056
|
+
const content = fs12.readFileSync(filePath, "utf-8");
|
|
1875
2057
|
const sourceFile = ts4.createSourceFile(
|
|
1876
2058
|
filePath,
|
|
1877
2059
|
content,
|
|
@@ -1882,7 +2064,7 @@ function analyzeFile(filePath) {
|
|
|
1882
2064
|
const callSites = analyzeCallSites(sourceFile, imports);
|
|
1883
2065
|
const classInfo = analyzeClass(sourceFile);
|
|
1884
2066
|
const { canMigrate, reason } = canAutoMigrate(classInfo);
|
|
1885
|
-
const relativePath =
|
|
2067
|
+
const relativePath = path11.relative(getProjectRoot3(), filePath);
|
|
1886
2068
|
return {
|
|
1887
2069
|
filePath: relativePath,
|
|
1888
2070
|
imports,
|
|
@@ -1893,7 +2075,7 @@ function analyzeFile(filePath) {
|
|
|
1893
2075
|
};
|
|
1894
2076
|
}
|
|
1895
2077
|
function migrateFile(analysis, dryRun) {
|
|
1896
|
-
const absolutePath =
|
|
2078
|
+
const absolutePath = path11.join(getProjectRoot3(), analysis.filePath);
|
|
1897
2079
|
if (!analysis.canAutoMigrate) {
|
|
1898
2080
|
return {
|
|
1899
2081
|
filePath: analysis.filePath,
|
|
@@ -1905,7 +2087,7 @@ function migrateFile(analysis, dryRun) {
|
|
|
1905
2087
|
};
|
|
1906
2088
|
}
|
|
1907
2089
|
try {
|
|
1908
|
-
let content =
|
|
2090
|
+
let content = fs12.readFileSync(absolutePath, "utf-8");
|
|
1909
2091
|
const callResult = transformCallSites(content, analysis.callSites);
|
|
1910
2092
|
content = callResult.content;
|
|
1911
2093
|
const sourceFile = ts4.createSourceFile(
|
|
@@ -1933,7 +2115,7 @@ function migrateFile(analysis, dryRun) {
|
|
|
1933
2115
|
}
|
|
1934
2116
|
}
|
|
1935
2117
|
if (!dryRun) {
|
|
1936
|
-
|
|
2118
|
+
fs12.writeFileSync(absolutePath, content, "utf-8");
|
|
1937
2119
|
}
|
|
1938
2120
|
return {
|
|
1939
2121
|
filePath: analysis.filePath,
|
|
@@ -1999,12 +2181,50 @@ function getSuggestion(analysis) {
|
|
|
1999
2181
|
return "Manual review required";
|
|
2000
2182
|
}
|
|
2001
2183
|
|
|
2002
|
-
// src/commands/
|
|
2003
|
-
import
|
|
2004
|
-
import
|
|
2184
|
+
// src/commands/migration/versions/v001_capability/cleanup.ts
|
|
2185
|
+
import fs13 from "fs";
|
|
2186
|
+
import path12 from "path";
|
|
2187
|
+
function cleanupOldFiles(capabilities, dryRun) {
|
|
2188
|
+
const deletedFiles = [];
|
|
2189
|
+
const errors = [];
|
|
2190
|
+
const capabilitiesDir = getCapabilitiesDir2();
|
|
2191
|
+
const oldJsonPath = path12.join(capabilitiesDir, "capabilities.json");
|
|
2192
|
+
if (fs13.existsSync(oldJsonPath)) {
|
|
2193
|
+
try {
|
|
2194
|
+
if (!dryRun) {
|
|
2195
|
+
fs13.unlinkSync(oldJsonPath);
|
|
2196
|
+
}
|
|
2197
|
+
deletedFiles.push("capabilities.json");
|
|
2198
|
+
} catch (error) {
|
|
2199
|
+
errors.push(`Failed to delete capabilities.json: ${error instanceof Error ? error.message : String(error)}`);
|
|
2200
|
+
}
|
|
2201
|
+
}
|
|
2202
|
+
for (const cap of capabilities) {
|
|
2203
|
+
const tsFilePath = path12.join(capabilitiesDir, `${cap.id}.ts`);
|
|
2204
|
+
if (fs13.existsSync(tsFilePath)) {
|
|
2205
|
+
try {
|
|
2206
|
+
if (!dryRun) {
|
|
2207
|
+
fs13.unlinkSync(tsFilePath);
|
|
2208
|
+
}
|
|
2209
|
+
deletedFiles.push(`${cap.id}.ts`);
|
|
2210
|
+
} catch (error) {
|
|
2211
|
+
errors.push(`Failed to delete ${cap.id}.ts: ${error instanceof Error ? error.message : String(error)}`);
|
|
2212
|
+
}
|
|
2213
|
+
}
|
|
2214
|
+
}
|
|
2215
|
+
return {
|
|
2216
|
+
success: errors.length === 0,
|
|
2217
|
+
deletedFiles,
|
|
2218
|
+
errors
|
|
2219
|
+
};
|
|
2220
|
+
}
|
|
2221
|
+
|
|
2222
|
+
// src/commands/migration/versions/v001_capability/report-generator.ts
|
|
2223
|
+
import fs14 from "fs";
|
|
2224
|
+
import path13 from "path";
|
|
2005
2225
|
var REPORT_FILE = "capability-migration-report.md";
|
|
2006
2226
|
function printSummary(result) {
|
|
2007
|
-
const { jsonMigration, pluginInstallation, codeMigration } = result;
|
|
2227
|
+
const { jsonMigration, pluginInstallation, codeMigration, cleanup } = result;
|
|
2008
2228
|
console.log("\u{1F4CA} Migration Summary");
|
|
2009
2229
|
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
2010
2230
|
if (!jsonMigration.skipped) {
|
|
@@ -2029,6 +2249,9 @@ function printSummary(result) {
|
|
|
2029
2249
|
console.log(` Files need manual work: ${codeMigration.manualRequired.length}`);
|
|
2030
2250
|
}
|
|
2031
2251
|
console.log(` Total call sites fixed: ${totalCallSites}`);
|
|
2252
|
+
if (cleanup.deletedFiles.length > 0) {
|
|
2253
|
+
console.log(` Old files cleaned up: ${cleanup.deletedFiles.length}`);
|
|
2254
|
+
}
|
|
2032
2255
|
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n");
|
|
2033
2256
|
const hasErrors = pluginInstallation.failed.length > 0 || failedMigrations.length > 0;
|
|
2034
2257
|
const hasManual = codeMigration.manualRequired.length > 0;
|
|
@@ -2049,7 +2272,7 @@ function printSummary(result) {
|
|
|
2049
2272
|
console.log("");
|
|
2050
2273
|
}
|
|
2051
2274
|
async function generateReport(result) {
|
|
2052
|
-
const { jsonMigration, pluginInstallation, codeMigration } = result;
|
|
2275
|
+
const { jsonMigration, pluginInstallation, codeMigration, cleanup } = result;
|
|
2053
2276
|
const lines = [];
|
|
2054
2277
|
lines.push("# Capability \u8FC1\u79FB\u62A5\u544A");
|
|
2055
2278
|
lines.push("");
|
|
@@ -2068,12 +2291,6 @@ async function generateReport(result) {
|
|
|
2068
2291
|
lines.push(`| ${cap.id} | ${cap.pluginKey} |`);
|
|
2069
2292
|
}
|
|
2070
2293
|
lines.push("");
|
|
2071
|
-
if (jsonMigration.backupPath) {
|
|
2072
|
-
lines.push("### 1.2 \u5907\u4EFD\u6587\u4EF6");
|
|
2073
|
-
lines.push("");
|
|
2074
|
-
lines.push(`- \`${jsonMigration.backupPath}\``);
|
|
2075
|
-
lines.push("");
|
|
2076
|
-
}
|
|
2077
2294
|
}
|
|
2078
2295
|
lines.push("## 2. \u63D2\u4EF6\u5B89\u88C5");
|
|
2079
2296
|
lines.push("");
|
|
@@ -2134,7 +2351,30 @@ async function generateReport(result) {
|
|
|
2134
2351
|
lines.push("");
|
|
2135
2352
|
}
|
|
2136
2353
|
}
|
|
2137
|
-
lines.push("## 4. \
|
|
2354
|
+
lines.push("## 4. \u6E05\u7406\u8001\u6587\u4EF6");
|
|
2355
|
+
lines.push("");
|
|
2356
|
+
if (cleanup.deletedFiles.length === 0 && cleanup.errors.length === 0) {
|
|
2357
|
+
lines.push("\u65E0\u6587\u4EF6\u9700\u8981\u6E05\u7406\u3002");
|
|
2358
|
+
} else {
|
|
2359
|
+
if (cleanup.deletedFiles.length > 0) {
|
|
2360
|
+
lines.push("### 4.1 \u5DF2\u5220\u9664\u7684\u6587\u4EF6");
|
|
2361
|
+
lines.push("");
|
|
2362
|
+
for (const file of cleanup.deletedFiles) {
|
|
2363
|
+
lines.push(`- \`${file}\``);
|
|
2364
|
+
}
|
|
2365
|
+
lines.push("");
|
|
2366
|
+
}
|
|
2367
|
+
if (cleanup.errors.length > 0) {
|
|
2368
|
+
lines.push("### 4.2 \u6E05\u7406\u5931\u8D25");
|
|
2369
|
+
lines.push("");
|
|
2370
|
+
for (const err of cleanup.errors) {
|
|
2371
|
+
lines.push(`- \u274C ${err}`);
|
|
2372
|
+
}
|
|
2373
|
+
lines.push("");
|
|
2374
|
+
}
|
|
2375
|
+
}
|
|
2376
|
+
lines.push("");
|
|
2377
|
+
lines.push("## 5. \u9A8C\u8BC1\u6E05\u5355");
|
|
2138
2378
|
lines.push("");
|
|
2139
2379
|
lines.push("- [ ] \u8FD0\u884C `git diff` \u68C0\u67E5\u4EE3\u7801\u53D8\u66F4");
|
|
2140
2380
|
lines.push("- [ ] \u8FD0\u884C `npm run typecheck` \u68C0\u67E5\u7C7B\u578B");
|
|
@@ -2142,40 +2382,74 @@ async function generateReport(result) {
|
|
|
2142
2382
|
if (codeMigration.manualRequired.length > 0) {
|
|
2143
2383
|
lines.push("- [ ] \u5904\u7406\u624B\u52A8\u8FC1\u79FB\u9879");
|
|
2144
2384
|
}
|
|
2145
|
-
lines.push("- [ ] \u5220\u9664\u5907\u4EFD\u6587\u4EF6\uFF08\u786E\u8BA4\u65E0\u8BEF\u540E\uFF09");
|
|
2146
2385
|
lines.push("");
|
|
2147
|
-
const reportPath =
|
|
2148
|
-
|
|
2386
|
+
const reportPath = path13.join(getProjectRoot3(), REPORT_FILE);
|
|
2387
|
+
fs14.writeFileSync(reportPath, lines.join("\n"), "utf-8");
|
|
2149
2388
|
console.log(`\u{1F4C4} Report generated: ${REPORT_FILE}`);
|
|
2150
2389
|
}
|
|
2151
2390
|
|
|
2152
|
-
// src/commands/
|
|
2153
|
-
async function
|
|
2391
|
+
// src/commands/migration/versions/v001_capability/migration-runner.ts
|
|
2392
|
+
async function runCapabilityMigration(options = {}) {
|
|
2154
2393
|
const fullOptions = {
|
|
2155
|
-
dryRun: options.dryRun ?? false
|
|
2156
|
-
skipInstall: options.skipInstall ?? false,
|
|
2157
|
-
skipCode: options.skipCode ?? false,
|
|
2158
|
-
mapping: mergeMapping(options.mapping)
|
|
2394
|
+
dryRun: options.dryRun ?? false
|
|
2159
2395
|
};
|
|
2160
2396
|
console.log("\u{1F50D} Analyzing project...\n");
|
|
2161
2397
|
if (fullOptions.dryRun) {
|
|
2162
2398
|
console.log("\u{1F4CB} Running in dry-run mode (no files will be modified)\n");
|
|
2163
2399
|
}
|
|
2400
|
+
let jsonResult = {
|
|
2401
|
+
success: false,
|
|
2402
|
+
skipped: true,
|
|
2403
|
+
reason: "Not executed",
|
|
2404
|
+
count: 0,
|
|
2405
|
+
capabilities: []
|
|
2406
|
+
};
|
|
2407
|
+
let pluginResult = {
|
|
2408
|
+
installed: [],
|
|
2409
|
+
alreadyInstalled: [],
|
|
2410
|
+
failed: []
|
|
2411
|
+
};
|
|
2412
|
+
let codeResult = {
|
|
2413
|
+
autoMigrated: [],
|
|
2414
|
+
manualRequired: []
|
|
2415
|
+
};
|
|
2416
|
+
let cleanupResult = {
|
|
2417
|
+
success: true,
|
|
2418
|
+
deletedFiles: [],
|
|
2419
|
+
errors: []
|
|
2420
|
+
};
|
|
2164
2421
|
console.log("\u{1F4C1} Step 1: JSON File Migration");
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2422
|
+
try {
|
|
2423
|
+
jsonResult = await migrateJsonFiles(fullOptions);
|
|
2424
|
+
if (jsonResult.skipped) {
|
|
2425
|
+
console.log(` \u25CB Skipped: ${jsonResult.reason}
|
|
2426
|
+
`);
|
|
2427
|
+
} else if (jsonResult.success) {
|
|
2428
|
+
console.log(` \u2713 Created ${jsonResult.count} capability files
|
|
2429
|
+
`);
|
|
2430
|
+
} else {
|
|
2431
|
+
console.log(` \u2717 Failed: ${jsonResult.reason}
|
|
2168
2432
|
`);
|
|
2169
|
-
|
|
2170
|
-
console.log(` \u2713 Migrated ${jsonResult.count} capabilities`);
|
|
2171
|
-
if (jsonResult.backupPath) {
|
|
2172
|
-
console.log(` \u2713 Backed up: capabilities.json \u2192 capabilities.json.backup`);
|
|
2433
|
+
return buildResult(jsonResult, pluginResult, codeResult, cleanupResult);
|
|
2173
2434
|
}
|
|
2174
|
-
|
|
2435
|
+
} catch (error) {
|
|
2436
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
2437
|
+
console.log(` \u2717 Error: ${errorMsg}
|
|
2438
|
+
`);
|
|
2439
|
+
jsonResult = {
|
|
2440
|
+
success: false,
|
|
2441
|
+
skipped: false,
|
|
2442
|
+
reason: errorMsg,
|
|
2443
|
+
count: 0,
|
|
2444
|
+
capabilities: []
|
|
2445
|
+
};
|
|
2446
|
+
return buildResult(jsonResult, pluginResult, codeResult, cleanupResult);
|
|
2175
2447
|
}
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2448
|
+
if (jsonResult.skipped) {
|
|
2449
|
+
return buildResult(jsonResult, pluginResult, codeResult, cleanupResult);
|
|
2450
|
+
}
|
|
2451
|
+
console.log("\u{1F4E6} Step 2: Plugin Installation");
|
|
2452
|
+
try {
|
|
2179
2453
|
pluginResult = await installPlugins(jsonResult.capabilities, fullOptions);
|
|
2180
2454
|
if (pluginResult.alreadyInstalled.length > 0) {
|
|
2181
2455
|
console.log(` \u2713 Already installed: ${pluginResult.alreadyInstalled.join(", ")}`);
|
|
@@ -2184,18 +2458,27 @@ async function runMigration(options = {}) {
|
|
|
2184
2458
|
console.log(` \u2713 Installed: ${pluginResult.installed.join(", ")}`);
|
|
2185
2459
|
}
|
|
2186
2460
|
if (pluginResult.failed.length > 0) {
|
|
2187
|
-
console.log(` \
|
|
2461
|
+
console.log(` \u26A0 Failed (will continue): ${pluginResult.failed.map((f) => f.pluginKey).join(", ")}`);
|
|
2462
|
+
for (const f of pluginResult.failed) {
|
|
2463
|
+
console.log(` - ${f.pluginKey}: ${f.error}`);
|
|
2464
|
+
}
|
|
2188
2465
|
}
|
|
2189
2466
|
console.log("");
|
|
2190
|
-
}
|
|
2191
|
-
|
|
2192
|
-
console.log(
|
|
2467
|
+
} catch (error) {
|
|
2468
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
2469
|
+
console.log(` \u26A0 Error (will continue): ${errorMsg}
|
|
2470
|
+
`);
|
|
2471
|
+
pluginResult = {
|
|
2472
|
+
installed: [],
|
|
2473
|
+
alreadyInstalled: [],
|
|
2474
|
+
failed: [{ pluginKey: "unknown", error: errorMsg }]
|
|
2475
|
+
};
|
|
2193
2476
|
}
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
console.log(" Scanning server/ directory...\n");
|
|
2477
|
+
console.log("\u{1F527} Step 3: Code Migration");
|
|
2478
|
+
console.log(" Scanning server/ directory...\n");
|
|
2479
|
+
try {
|
|
2198
2480
|
codeResult = await migrateCode(fullOptions);
|
|
2481
|
+
let hasCodeError = false;
|
|
2199
2482
|
for (const file of codeResult.autoMigrated) {
|
|
2200
2483
|
if (file.success) {
|
|
2201
2484
|
console.log(` \u2713 ${file.filePath}`);
|
|
@@ -2206,6 +2489,7 @@ async function runMigration(options = {}) {
|
|
|
2206
2489
|
console.log(` - Replaced ${file.callSitesReplaced} call sites`);
|
|
2207
2490
|
} else {
|
|
2208
2491
|
console.log(` \u2717 ${file.filePath}: ${file.error}`);
|
|
2492
|
+
hasCodeError = true;
|
|
2209
2493
|
}
|
|
2210
2494
|
}
|
|
2211
2495
|
if (codeResult.manualRequired.length > 0) {
|
|
@@ -2216,93 +2500,414 @@ async function runMigration(options = {}) {
|
|
|
2216
2500
|
}
|
|
2217
2501
|
}
|
|
2218
2502
|
console.log("");
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2503
|
+
if (hasCodeError) {
|
|
2504
|
+
console.log(" \u2717 Code migration failed, aborting...\n");
|
|
2505
|
+
return buildResult(jsonResult, pluginResult, codeResult, cleanupResult);
|
|
2506
|
+
}
|
|
2507
|
+
} catch (error) {
|
|
2508
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
2509
|
+
console.log(` \u2717 Error: ${errorMsg}
|
|
2510
|
+
`);
|
|
2511
|
+
codeResult = {
|
|
2512
|
+
autoMigrated: [],
|
|
2513
|
+
manualRequired: []
|
|
2514
|
+
};
|
|
2515
|
+
return buildResult(jsonResult, pluginResult, codeResult, cleanupResult);
|
|
2222
2516
|
}
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2517
|
+
console.log("\u{1F9F9} Step 4: Cleanup Old Files");
|
|
2518
|
+
try {
|
|
2519
|
+
cleanupResult = cleanupOldFiles(jsonResult.capabilities, fullOptions.dryRun);
|
|
2520
|
+
if (cleanupResult.deletedFiles.length > 0) {
|
|
2521
|
+
for (const file of cleanupResult.deletedFiles) {
|
|
2522
|
+
console.log(` \u2713 Deleted: ${file}`);
|
|
2523
|
+
}
|
|
2524
|
+
} else {
|
|
2525
|
+
console.log(" \u25CB No files to clean up");
|
|
2526
|
+
}
|
|
2527
|
+
if (cleanupResult.errors.length > 0) {
|
|
2528
|
+
for (const err of cleanupResult.errors) {
|
|
2529
|
+
console.log(` \u26A0 ${err}`);
|
|
2530
|
+
}
|
|
2531
|
+
}
|
|
2532
|
+
console.log("");
|
|
2533
|
+
} catch (error) {
|
|
2534
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
2535
|
+
console.log(` \u26A0 Error: ${errorMsg}
|
|
2536
|
+
`);
|
|
2537
|
+
cleanupResult = {
|
|
2538
|
+
success: false,
|
|
2539
|
+
deletedFiles: [],
|
|
2540
|
+
errors: [errorMsg]
|
|
2541
|
+
};
|
|
2542
|
+
}
|
|
2543
|
+
const result = buildResult(jsonResult, pluginResult, codeResult, cleanupResult);
|
|
2228
2544
|
printSummary(result);
|
|
2229
2545
|
if (!fullOptions.dryRun) {
|
|
2230
2546
|
await generateReport(result);
|
|
2231
2547
|
}
|
|
2232
2548
|
return result;
|
|
2233
2549
|
}
|
|
2550
|
+
function buildResult(jsonMigration, pluginInstallation, codeMigration, cleanup) {
|
|
2551
|
+
return {
|
|
2552
|
+
jsonMigration,
|
|
2553
|
+
pluginInstallation,
|
|
2554
|
+
codeMigration,
|
|
2555
|
+
cleanup
|
|
2556
|
+
};
|
|
2557
|
+
}
|
|
2234
2558
|
|
|
2235
|
-
// src/commands/
|
|
2236
|
-
async function
|
|
2559
|
+
// src/commands/migration/versions/v001_capability/run.ts
|
|
2560
|
+
async function run3(options) {
|
|
2237
2561
|
try {
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2562
|
+
const migrationOptions = {
|
|
2563
|
+
dryRun: options.dryRun ?? false
|
|
2564
|
+
};
|
|
2565
|
+
const result = await runCapabilityMigration(migrationOptions);
|
|
2566
|
+
const { jsonMigration, pluginInstallation, codeMigration, cleanup } = result;
|
|
2567
|
+
const jsonFailed = !jsonMigration.success && !jsonMigration.skipped;
|
|
2568
|
+
const codeFailed = codeMigration.autoMigrated.some((f) => !f.success);
|
|
2569
|
+
if (jsonFailed) {
|
|
2570
|
+
return {
|
|
2571
|
+
success: false,
|
|
2572
|
+
message: jsonMigration.reason || "JSON migration failed",
|
|
2573
|
+
error: new Error(jsonMigration.reason || "Unknown error")
|
|
2574
|
+
};
|
|
2575
|
+
}
|
|
2576
|
+
if (codeFailed) {
|
|
2577
|
+
return {
|
|
2578
|
+
success: false,
|
|
2579
|
+
message: "Code migration failed",
|
|
2580
|
+
error: new Error("Some files failed to migrate")
|
|
2581
|
+
};
|
|
2582
|
+
}
|
|
2583
|
+
const messages = [];
|
|
2584
|
+
if (jsonMigration.success) {
|
|
2585
|
+
messages.push(`${jsonMigration.count} capabilities migrated`);
|
|
2586
|
+
}
|
|
2587
|
+
if (pluginInstallation.installed.length > 0) {
|
|
2588
|
+
messages.push(`${pluginInstallation.installed.length} plugins installed`);
|
|
2589
|
+
}
|
|
2590
|
+
if (codeMigration.autoMigrated.length > 0) {
|
|
2591
|
+
const successCount = codeMigration.autoMigrated.filter((f) => f.success).length;
|
|
2592
|
+
if (successCount > 0) {
|
|
2593
|
+
messages.push(`${successCount} files auto-migrated`);
|
|
2250
2594
|
}
|
|
2251
2595
|
}
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2596
|
+
if (cleanup.deletedFiles.length > 0) {
|
|
2597
|
+
messages.push(`${cleanup.deletedFiles.length} old files cleaned up`);
|
|
2598
|
+
}
|
|
2599
|
+
if (codeMigration.manualRequired.length > 0) {
|
|
2600
|
+
messages.push(`${codeMigration.manualRequired.length} files need manual migration`);
|
|
2601
|
+
}
|
|
2602
|
+
if (pluginInstallation.failed.length > 0) {
|
|
2603
|
+
messages.push(`${pluginInstallation.failed.length} plugins failed to install`);
|
|
2604
|
+
}
|
|
2605
|
+
return {
|
|
2606
|
+
success: true,
|
|
2607
|
+
message: messages.join(", ") || "No migration needed"
|
|
2257
2608
|
};
|
|
2258
|
-
await runMigration(migrationOptions);
|
|
2259
2609
|
} catch (error) {
|
|
2260
|
-
|
|
2261
|
-
|
|
2610
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
2611
|
+
return {
|
|
2612
|
+
success: false,
|
|
2613
|
+
message: err.message,
|
|
2614
|
+
error: err
|
|
2615
|
+
};
|
|
2262
2616
|
}
|
|
2263
2617
|
}
|
|
2264
2618
|
|
|
2265
|
-
// src/commands/
|
|
2266
|
-
var
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
await list2(options);
|
|
2273
|
-
});
|
|
2274
|
-
}
|
|
2619
|
+
// src/commands/migration/versions/v001_capability/index.ts
|
|
2620
|
+
var v001CapabilityMigration = {
|
|
2621
|
+
version: 1,
|
|
2622
|
+
name: "capability",
|
|
2623
|
+
description: "Migrate capability configurations from old format (capabilities.json array) to new format (individual JSON files)",
|
|
2624
|
+
check,
|
|
2625
|
+
run: run3
|
|
2275
2626
|
};
|
|
2627
|
+
|
|
2628
|
+
// src/commands/migration/versions/index.ts
|
|
2629
|
+
var versionedMigrations = [
|
|
2630
|
+
v001CapabilityMigration
|
|
2631
|
+
// 未来新增的迁移脚本在此添加,如:
|
|
2632
|
+
// v002ConfigMigration,
|
|
2633
|
+
// v003RoutesMigration,
|
|
2634
|
+
];
|
|
2635
|
+
function getPendingMigrations(currentVersion) {
|
|
2636
|
+
return versionedMigrations.filter((m) => m.version > currentVersion).sort((a, b) => a.version - b.version);
|
|
2637
|
+
}
|
|
2638
|
+
function getLatestVersion() {
|
|
2639
|
+
if (versionedMigrations.length === 0) return 0;
|
|
2640
|
+
return Math.max(...versionedMigrations.map((m) => m.version));
|
|
2641
|
+
}
|
|
2642
|
+
|
|
2643
|
+
// src/commands/migration/runner.ts
|
|
2644
|
+
function log(message) {
|
|
2645
|
+
console.log(`[migration] ${message}`);
|
|
2646
|
+
}
|
|
2647
|
+
async function executeSingle(migration, options) {
|
|
2648
|
+
const { version, name } = migration;
|
|
2649
|
+
const versionTag = `v${version}`;
|
|
2650
|
+
try {
|
|
2651
|
+
log(`Checking [${versionTag}] ${name}...`);
|
|
2652
|
+
const checkResult = await migration.check(options);
|
|
2653
|
+
if (!checkResult.needsMigration) {
|
|
2654
|
+
log(`[${versionTag}] ${name}: no migration needed`);
|
|
2655
|
+
return {
|
|
2656
|
+
name,
|
|
2657
|
+
status: "skipped",
|
|
2658
|
+
message: checkResult.message || "No migration needed"
|
|
2659
|
+
};
|
|
2660
|
+
}
|
|
2661
|
+
log(`[${versionTag}] ${name}: needs migration (${checkResult.message})`);
|
|
2662
|
+
if (checkResult.items && checkResult.items.length > 0) {
|
|
2663
|
+
for (const item of checkResult.items) {
|
|
2664
|
+
console.log(` - ${item}`);
|
|
2665
|
+
}
|
|
2666
|
+
}
|
|
2667
|
+
if (options.dryRun) {
|
|
2668
|
+
return {
|
|
2669
|
+
name,
|
|
2670
|
+
status: "skipped",
|
|
2671
|
+
message: `Dry-run: ${checkResult.message}`
|
|
2672
|
+
};
|
|
2673
|
+
}
|
|
2674
|
+
log(`Running [${versionTag}] ${name} migration...`);
|
|
2675
|
+
const runResult = await migration.run(options);
|
|
2676
|
+
if (runResult.success) {
|
|
2677
|
+
log(`\u2713 [${versionTag}] ${name}: completed (${runResult.message})`);
|
|
2678
|
+
return {
|
|
2679
|
+
name,
|
|
2680
|
+
status: "completed",
|
|
2681
|
+
message: runResult.message
|
|
2682
|
+
};
|
|
2683
|
+
} else {
|
|
2684
|
+
log(`\u2717 [${versionTag}] ${name}: failed`);
|
|
2685
|
+
if (runResult.error) {
|
|
2686
|
+
console.log(` Error: ${runResult.error.message}`);
|
|
2687
|
+
}
|
|
2688
|
+
return {
|
|
2689
|
+
name,
|
|
2690
|
+
status: "failed",
|
|
2691
|
+
message: runResult.message,
|
|
2692
|
+
error: runResult.error
|
|
2693
|
+
};
|
|
2694
|
+
}
|
|
2695
|
+
} catch (error) {
|
|
2696
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
2697
|
+
log(`\u2717 [${versionTag}] ${name}: failed`);
|
|
2698
|
+
console.log(` Error: ${err.message}`);
|
|
2699
|
+
return {
|
|
2700
|
+
name,
|
|
2701
|
+
status: "failed",
|
|
2702
|
+
message: err.message,
|
|
2703
|
+
error: err
|
|
2704
|
+
};
|
|
2705
|
+
}
|
|
2706
|
+
}
|
|
2707
|
+
function printSummary2(summary, dryRun) {
|
|
2708
|
+
console.log("");
|
|
2709
|
+
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
2710
|
+
console.log(dryRun ? "Dry-run Summary:" : "Migration Summary:");
|
|
2711
|
+
if (dryRun) {
|
|
2712
|
+
const needsMigration = summary.skipped.filter((s) => s.message.startsWith("Dry-run:")).length;
|
|
2713
|
+
const noAction = summary.skipped.filter((s) => !s.message.startsWith("Dry-run:")).length;
|
|
2714
|
+
console.log(` Needs migration: ${needsMigration}`);
|
|
2715
|
+
console.log(` No action needed: ${noAction}`);
|
|
2716
|
+
} else {
|
|
2717
|
+
console.log(` \u2713 Completed: ${summary.completed.length}`);
|
|
2718
|
+
console.log(` \u25CB Skipped: ${summary.skipped.length} (no migration needed)`);
|
|
2719
|
+
console.log(` \u2717 Failed: ${summary.failed.length}`);
|
|
2720
|
+
}
|
|
2721
|
+
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
2722
|
+
}
|
|
2723
|
+
async function runMigrations(options) {
|
|
2724
|
+
const currentVersion = getCurrentVersion();
|
|
2725
|
+
const latestVersion = getLatestVersion();
|
|
2726
|
+
console.log("");
|
|
2727
|
+
log(`Current version: ${currentVersion || "0 (not set)"}`);
|
|
2728
|
+
if (currentVersion >= latestVersion) {
|
|
2729
|
+
log("All migrations are up to date.");
|
|
2730
|
+
return {
|
|
2731
|
+
needsMigration: false,
|
|
2732
|
+
completed: [],
|
|
2733
|
+
skipped: [],
|
|
2734
|
+
failed: []
|
|
2735
|
+
};
|
|
2736
|
+
}
|
|
2737
|
+
const pendingMigrations = getPendingMigrations(currentVersion);
|
|
2738
|
+
if (options.dryRun) {
|
|
2739
|
+
log("Dry-run mode enabled, no changes will be made.");
|
|
2740
|
+
} else {
|
|
2741
|
+
log("Applying migrations...");
|
|
2742
|
+
}
|
|
2743
|
+
console.log("");
|
|
2744
|
+
const summary = {
|
|
2745
|
+
needsMigration: false,
|
|
2746
|
+
completed: [],
|
|
2747
|
+
skipped: [],
|
|
2748
|
+
failed: []
|
|
2749
|
+
};
|
|
2750
|
+
let hasAnyMigration = false;
|
|
2751
|
+
for (const migration of pendingMigrations) {
|
|
2752
|
+
const result = await executeSingle(migration, options);
|
|
2753
|
+
switch (result.status) {
|
|
2754
|
+
case "completed":
|
|
2755
|
+
summary.completed.push(result);
|
|
2756
|
+
hasAnyMigration = true;
|
|
2757
|
+
if (!options.dryRun) {
|
|
2758
|
+
setCurrentVersion(migration.version);
|
|
2759
|
+
}
|
|
2760
|
+
break;
|
|
2761
|
+
case "skipped":
|
|
2762
|
+
summary.skipped.push(result);
|
|
2763
|
+
if (result.message.startsWith("Dry-run:")) {
|
|
2764
|
+
hasAnyMigration = true;
|
|
2765
|
+
}
|
|
2766
|
+
break;
|
|
2767
|
+
case "failed":
|
|
2768
|
+
summary.failed.push(result);
|
|
2769
|
+
hasAnyMigration = true;
|
|
2770
|
+
log("Migration aborted due to failure.");
|
|
2771
|
+
printSummary2(summary, !!options.dryRun);
|
|
2772
|
+
return summary;
|
|
2773
|
+
}
|
|
2774
|
+
console.log("");
|
|
2775
|
+
}
|
|
2776
|
+
summary.needsMigration = hasAnyMigration;
|
|
2777
|
+
if (currentVersion === 0 && !hasAnyMigration && !options.dryRun) {
|
|
2778
|
+
log(`All migrations skipped. Project is up to date.`);
|
|
2779
|
+
log(`Updated migrationVersion to ${latestVersion}.`);
|
|
2780
|
+
setCurrentVersion(latestVersion);
|
|
2781
|
+
} else if (!options.dryRun && summary.completed.length > 0) {
|
|
2782
|
+
log(`Migration complete. Updated to version ${getCurrentVersion()}.`);
|
|
2783
|
+
}
|
|
2784
|
+
printSummary2(summary, !!options.dryRun);
|
|
2785
|
+
return summary;
|
|
2786
|
+
}
|
|
2787
|
+
async function checkMigrations(options) {
|
|
2788
|
+
const currentVersion = getCurrentVersion();
|
|
2789
|
+
const latestVersion = getLatestVersion();
|
|
2790
|
+
console.log("");
|
|
2791
|
+
log(`Current version: ${currentVersion || "0 (not set)"}`);
|
|
2792
|
+
if (currentVersion >= latestVersion) {
|
|
2793
|
+
log("All migrations are up to date.");
|
|
2794
|
+
return {
|
|
2795
|
+
needsMigration: false,
|
|
2796
|
+
completed: [],
|
|
2797
|
+
skipped: [],
|
|
2798
|
+
failed: []
|
|
2799
|
+
};
|
|
2800
|
+
}
|
|
2801
|
+
log("Checking pending migrations...");
|
|
2802
|
+
console.log("");
|
|
2803
|
+
const pendingMigrations = getPendingMigrations(currentVersion);
|
|
2804
|
+
const summary = {
|
|
2805
|
+
needsMigration: false,
|
|
2806
|
+
completed: [],
|
|
2807
|
+
skipped: [],
|
|
2808
|
+
failed: []
|
|
2809
|
+
};
|
|
2810
|
+
let needsCount = 0;
|
|
2811
|
+
let noActionCount = 0;
|
|
2812
|
+
for (const migration of pendingMigrations) {
|
|
2813
|
+
const { version, name } = migration;
|
|
2814
|
+
const versionTag = `v${version}`;
|
|
2815
|
+
try {
|
|
2816
|
+
const checkResult = await migration.check(options);
|
|
2817
|
+
if (checkResult.needsMigration) {
|
|
2818
|
+
needsCount++;
|
|
2819
|
+
console.log(` ${versionTag} (${name}): needs migration`);
|
|
2820
|
+
if (checkResult.items && checkResult.items.length > 0) {
|
|
2821
|
+
for (const item of checkResult.items) {
|
|
2822
|
+
console.log(` - ${item}`);
|
|
2823
|
+
}
|
|
2824
|
+
}
|
|
2825
|
+
summary.skipped.push({
|
|
2826
|
+
name,
|
|
2827
|
+
status: "skipped",
|
|
2828
|
+
message: `Needs migration: ${checkResult.message}`
|
|
2829
|
+
});
|
|
2830
|
+
} else {
|
|
2831
|
+
noActionCount++;
|
|
2832
|
+
console.log(` ${versionTag} (${name}): no migration needed`);
|
|
2833
|
+
summary.skipped.push({
|
|
2834
|
+
name,
|
|
2835
|
+
status: "skipped",
|
|
2836
|
+
message: checkResult.message || "No migration needed"
|
|
2837
|
+
});
|
|
2838
|
+
}
|
|
2839
|
+
} catch (error) {
|
|
2840
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
2841
|
+
console.log(` ${versionTag} (${name}): check failed`);
|
|
2842
|
+
console.log(` Error: ${err.message}`);
|
|
2843
|
+
summary.failed.push({
|
|
2844
|
+
name,
|
|
2845
|
+
status: "failed",
|
|
2846
|
+
message: err.message,
|
|
2847
|
+
error: err
|
|
2848
|
+
});
|
|
2849
|
+
}
|
|
2850
|
+
}
|
|
2851
|
+
console.log("");
|
|
2852
|
+
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
2853
|
+
console.log("Check Summary:");
|
|
2854
|
+
console.log(` Needs migration: ${needsCount}`);
|
|
2855
|
+
console.log(` No action needed: ${noActionCount}`);
|
|
2856
|
+
if (summary.failed.length > 0) {
|
|
2857
|
+
console.log(` Check failed: ${summary.failed.length}`);
|
|
2858
|
+
}
|
|
2859
|
+
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
2860
|
+
if (needsCount > 0) {
|
|
2861
|
+
console.log("");
|
|
2862
|
+
log("Run 'fullstack-cli migration' to apply.");
|
|
2863
|
+
}
|
|
2864
|
+
summary.needsMigration = needsCount > 0;
|
|
2865
|
+
if (needsCount === 0 && summary.failed.length === 0) {
|
|
2866
|
+
setCurrentVersion(latestVersion);
|
|
2867
|
+
console.log("");
|
|
2868
|
+
log(`Updated migrationVersion to ${latestVersion}.`);
|
|
2869
|
+
}
|
|
2870
|
+
return summary;
|
|
2871
|
+
}
|
|
2872
|
+
|
|
2873
|
+
// src/commands/migration/index.ts
|
|
2276
2874
|
var migrationCommand = {
|
|
2277
2875
|
name: "migration",
|
|
2278
|
-
description: "
|
|
2876
|
+
description: "Run versioned migration scripts",
|
|
2279
2877
|
register(program) {
|
|
2280
|
-
program.command(this.name).description(
|
|
2281
|
-
await
|
|
2878
|
+
const migrationCmd = program.command(this.name).description("Run all pending migrations based on current migrationVersion").option("--dry-run", "Preview mode, only run check() without executing run()").action(async (options) => {
|
|
2879
|
+
const summary = await runMigrations(options);
|
|
2880
|
+
if (summary.failed.length > 0) {
|
|
2881
|
+
process.exit(1);
|
|
2882
|
+
}
|
|
2883
|
+
});
|
|
2884
|
+
migrationCmd.command("check").description("Check pending migrations without applying them").action(async () => {
|
|
2885
|
+
const summary = await checkMigrations({});
|
|
2886
|
+
if (summary.failed.length > 0) {
|
|
2887
|
+
process.exit(2);
|
|
2888
|
+
} else if (summary.needsMigration) {
|
|
2889
|
+
process.exit(1);
|
|
2890
|
+
}
|
|
2282
2891
|
});
|
|
2283
2892
|
}
|
|
2284
2893
|
};
|
|
2285
|
-
var capabilityCommandGroup = {
|
|
2286
|
-
name: "capability",
|
|
2287
|
-
description: "Manage capability configurations",
|
|
2288
|
-
commands: [listCommand2, migrationCommand]
|
|
2289
|
-
};
|
|
2290
2894
|
|
|
2291
2895
|
// src/commands/index.ts
|
|
2292
2896
|
var commands = [
|
|
2293
2897
|
genDbSchemaCommand,
|
|
2294
2898
|
syncCommand,
|
|
2295
2899
|
actionPluginCommandGroup,
|
|
2296
|
-
capabilityCommandGroup
|
|
2900
|
+
capabilityCommandGroup,
|
|
2901
|
+
migrationCommand
|
|
2297
2902
|
];
|
|
2298
2903
|
|
|
2299
2904
|
// src/index.ts
|
|
2300
|
-
var envPath =
|
|
2301
|
-
if (
|
|
2905
|
+
var envPath = path14.join(process.cwd(), ".env");
|
|
2906
|
+
if (fs15.existsSync(envPath)) {
|
|
2302
2907
|
dotenvConfig({ path: envPath });
|
|
2303
2908
|
}
|
|
2304
|
-
var __dirname =
|
|
2305
|
-
var pkg = JSON.parse(
|
|
2909
|
+
var __dirname = path14.dirname(fileURLToPath3(import.meta.url));
|
|
2910
|
+
var pkg = JSON.parse(fs15.readFileSync(path14.join(__dirname, "../package.json"), "utf-8"));
|
|
2306
2911
|
var cli = new FullstackCLI(pkg.version);
|
|
2307
2912
|
cli.useAll(commands);
|
|
2308
2913
|
cli.run();
|