@lark-apaas/fullstack-cli 1.1.22-alpha.1 → 1.1.22-alpha.11

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.
Files changed (2) hide show
  1. package/dist/index.js +784 -259
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // src/index.ts
2
- import fs22 from "fs";
3
- import path18 from "path";
4
- import { fileURLToPath as fileURLToPath4 } from "url";
2
+ import fs25 from "fs";
3
+ import path21 from "path";
4
+ import { fileURLToPath as fileURLToPath5 } from "url";
5
5
  import { config as dotenvConfig } from "dotenv";
6
6
 
7
7
  // src/cli.ts
@@ -1041,6 +1041,8 @@ async function fetchColumnComments(connectionString, options = {}) {
1041
1041
  const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
1042
1042
  const url = new URL(connectionString);
1043
1043
  const schemaName = url.searchParams.get("schema") ?? "public";
1044
+ const start = Date.now();
1045
+ console.log(`[fetchColumnComments] \u2192 Querying pg_description for schema=${schemaName} (timeout=${timeoutMs}ms)`);
1044
1046
  const sql = postgres(connectionString, {
1045
1047
  connect_timeout: Math.ceil(timeoutMs / 1e3),
1046
1048
  idle_timeout: Math.ceil(timeoutMs / 1e3)
@@ -1069,6 +1071,7 @@ async function fetchColumnComments(connectionString, options = {}) {
1069
1071
  const key = `${row.tableName}.${row.columnName}`;
1070
1072
  commentMap.set(key, row.comment);
1071
1073
  }
1074
+ console.log(`[fetchColumnComments] \u2190 Fetched ${commentMap.size} column comments (${Date.now() - start}ms)`);
1072
1075
  return commentMap;
1073
1076
  } finally {
1074
1077
  await sql.end().catch(() => {
@@ -1167,6 +1170,79 @@ function addJsonbTypeComments(source, columnComments) {
1167
1170
  return { text: result.join("\n"), added };
1168
1171
  }
1169
1172
 
1173
+ // src/commands/db/gen-dbschema/transforms/text/synced-table-comments.ts
1174
+ var TABLE_COMMENT = "Synced table: data is auto-synced from external source. Do not rename or delete this table.";
1175
+ var FIELD_COMMENT = "Synced field: auto-synced, do not modify or delete";
1176
+ var TABLE_DEF_REGEX = /^(export const\s+\w+\s*=\s*(?:pgTable|pgView|pgMaterializedView)\(\s*["'`])([^"'`]+)(["'`])/;
1177
+ var FIELD_WITH_NAME_REGEX = /^\s*[\w"']+\s*:\s*\w+\(\s*["'`]([^"'`]+)["'`]/;
1178
+ var FIELD_PROP_NAME_REGEX = /^\s*([\w]+)\s*:/;
1179
+ function addSyncedTableComments(source, syncedTableMap) {
1180
+ if (!syncedTableMap || syncedTableMap.size === 0) {
1181
+ return { text: source, added: 0 };
1182
+ }
1183
+ const lines = source.split("\n");
1184
+ const result = [];
1185
+ let added = 0;
1186
+ let currentSyncedFields = null;
1187
+ let insideTableBody = false;
1188
+ let braceDepth = 0;
1189
+ for (let i = 0; i < lines.length; i++) {
1190
+ const line = lines[i];
1191
+ const tableMatch = line.match(TABLE_DEF_REGEX);
1192
+ if (tableMatch) {
1193
+ const tableName = tableMatch[2];
1194
+ const syncedFields = syncedTableMap.get(tableName);
1195
+ if (syncedFields) {
1196
+ currentSyncedFields = syncedFields;
1197
+ insideTableBody = true;
1198
+ braceDepth = 0;
1199
+ const prevLine = result[result.length - 1]?.trim() ?? "";
1200
+ if (!prevLine.includes("Synced table")) {
1201
+ const indentMatch = line.match(/^\s*/);
1202
+ const indent = indentMatch ? indentMatch[0] : "";
1203
+ result.push(`${indent}// ${TABLE_COMMENT}`);
1204
+ added++;
1205
+ }
1206
+ }
1207
+ }
1208
+ if (insideTableBody) {
1209
+ for (const ch of line) {
1210
+ if (ch === "{") braceDepth++;
1211
+ if (ch === "}") braceDepth--;
1212
+ }
1213
+ if (braceDepth <= 0) {
1214
+ insideTableBody = false;
1215
+ currentSyncedFields = null;
1216
+ }
1217
+ if (currentSyncedFields && braceDepth >= 1 && !tableMatch) {
1218
+ const columnName = extractColumnName2(line);
1219
+ if (columnName && currentSyncedFields.has(columnName)) {
1220
+ const prevLine = result[result.length - 1]?.trim() ?? "";
1221
+ if (!prevLine.includes("Synced field")) {
1222
+ const indentMatch = line.match(/^\s*/);
1223
+ const indent = indentMatch ? indentMatch[0] : "";
1224
+ result.push(`${indent}// ${FIELD_COMMENT}`);
1225
+ added++;
1226
+ }
1227
+ }
1228
+ }
1229
+ }
1230
+ result.push(line);
1231
+ }
1232
+ return { text: result.join("\n"), added };
1233
+ }
1234
+ function extractColumnName2(line) {
1235
+ const withNameMatch = line.match(FIELD_WITH_NAME_REGEX);
1236
+ if (withNameMatch) {
1237
+ return withNameMatch[1];
1238
+ }
1239
+ const propMatch = line.match(FIELD_PROP_NAME_REGEX);
1240
+ if (propMatch) {
1241
+ return propMatch[1];
1242
+ }
1243
+ return null;
1244
+ }
1245
+
1170
1246
  // src/commands/db/gen-dbschema/transforms/text/table-aliases.ts
1171
1247
  var TABLE_ALIAS_MARKER = "// table aliases";
1172
1248
  function generateTableAliases(source) {
@@ -1215,13 +1291,16 @@ function postprocessSchema(rawSource, options = {}) {
1215
1291
  source = inlineCustomTypes(source);
1216
1292
  const jsonbCommentsResult = addJsonbTypeComments(source, options.columnComments);
1217
1293
  source = jsonbCommentsResult.text;
1294
+ const syncedCommentsResult = addSyncedTableComments(source, options.syncedTableMap);
1295
+ source = syncedCommentsResult.text;
1218
1296
  source = generateTableAliases(source);
1219
1297
  source = formatSource(source);
1220
1298
  return {
1221
1299
  source,
1222
1300
  astStats,
1223
1301
  patchedDefects: patchResult.fixed,
1224
- addedJsonbComments: jsonbCommentsResult.added
1302
+ addedJsonbComments: jsonbCommentsResult.added,
1303
+ addedSyncedComments: syncedCommentsResult.added
1225
1304
  };
1226
1305
  }
1227
1306
  function logStats(result, prefix = "[postprocess]") {
@@ -1271,6 +1350,9 @@ function logStats(result, prefix = "[postprocess]") {
1271
1350
  if (result.addedJsonbComments > 0) {
1272
1351
  console.info(`${prefix} Added ${result.addedJsonbComments} JSDoc comments for jsonb fields`);
1273
1352
  }
1353
+ if (result.addedSyncedComments > 0) {
1354
+ console.info(`${prefix} Added ${result.addedSyncedComments} comments for synced tables/fields`);
1355
+ }
1274
1356
  }
1275
1357
 
1276
1358
  // src/commands/db/gen-dbschema/index.ts
@@ -1281,7 +1363,10 @@ async function postprocessDrizzleSchema(targetPath, options = {}) {
1281
1363
  return void 0;
1282
1364
  }
1283
1365
  const rawSource = fs3.readFileSync(resolvedPath, "utf8");
1284
- const result = postprocessSchema(rawSource, { columnComments: options.columnComments });
1366
+ const result = postprocessSchema(rawSource, {
1367
+ columnComments: options.columnComments,
1368
+ syncedTableMap: options.syncedTableMap
1369
+ });
1285
1370
  fs3.writeFileSync(resolvedPath, result.source, "utf8");
1286
1371
  logStats(result, "[postprocess-drizzle-schema]");
1287
1372
  return {
@@ -1291,10 +1376,82 @@ async function postprocessDrizzleSchema(targetPath, options = {}) {
1291
1376
  patchedDefects: result.patchedDefects,
1292
1377
  replacedTimestamps: result.astStats.replacedTimestamp,
1293
1378
  replacedDefaultNow: result.astStats.replacedDefaultNow,
1294
- addedJsonbComments: result.addedJsonbComments
1379
+ addedJsonbComments: result.addedJsonbComments,
1380
+ addedSyncedComments: result.addedSyncedComments
1295
1381
  };
1296
1382
  }
1297
1383
 
1384
+ // src/utils/http-client.ts
1385
+ import { HttpClient } from "@lark-apaas/http-client";
1386
+ var clientInstance = null;
1387
+ function getHttpClient() {
1388
+ if (!clientInstance) {
1389
+ clientInstance = new HttpClient({
1390
+ timeout: 3e4,
1391
+ platform: {
1392
+ enabled: true
1393
+ }
1394
+ });
1395
+ const canaryEnv = process.env.FORCE_FRAMEWORK_CLI_CANARY_ENV;
1396
+ if (canaryEnv) {
1397
+ clientInstance.interceptors.request.use((req) => {
1398
+ req.headers["x-tt-env"] = canaryEnv;
1399
+ return req;
1400
+ });
1401
+ }
1402
+ }
1403
+ return clientInstance;
1404
+ }
1405
+
1406
+ // src/commands/db/gen-dbschema/utils/fetch-synced-tables.ts
1407
+ async function fetchSyncedTables(appId, workspace) {
1408
+ const client = getHttpClient();
1409
+ const start = Date.now();
1410
+ console.log(
1411
+ `[fetchSyncedTables] \u2192 GET listTableView (dbBranch=main) appId=${appId} workspace=${workspace}`,
1412
+ process.env.FORCE_AUTHN_ACCESS_SECRET
1413
+ );
1414
+ const response = await client.get(
1415
+ `/api/v1/dataloom/inner/app/${appId}/workspaces/${workspace}/listTableView`
1416
+ );
1417
+ console.log(`[fetchSyncedTables] \u2190 listTableView response: ${response.status} ${response.statusText} (${Date.now() - start}ms)`);
1418
+ const responseXHeaders = Array.from(response.headers.entries()).filter(([key]) => key.toLowerCase().startsWith("x-")).reduce((acc, [key, value]) => {
1419
+ acc[key] = value;
1420
+ return acc;
1421
+ }, {});
1422
+ console.log("[fetchSyncedTables] x-* response headers:", responseXHeaders);
1423
+ if (!response.ok) {
1424
+ throw new Error(`listTableView API failed: ${response.status} ${response.statusText}`);
1425
+ }
1426
+ const json = await response.json();
1427
+ const tableView = json?.data?.data;
1428
+ console.log("[fetchSyncedTables] listTableView raw response:", JSON.stringify(json, null, 2));
1429
+ if (!tableView) {
1430
+ console.warn("[fetchSyncedTables] \u26A0 listTableView response missing data.data, returning empty map");
1431
+ return /* @__PURE__ */ new Map();
1432
+ }
1433
+ const syncedMap = extractSyncedTableMap(tableView);
1434
+ const totalCount = (tableView.table?.data?.length ?? 0) + (tableView.view?.data?.length ?? 0) + (tableView.materializedView?.data?.length ?? 0);
1435
+ console.log(
1436
+ `[fetchSyncedTables] \u2713 Extracted synced tables: ${syncedMap.size}/${totalCount} (elapsed ${Date.now() - start}ms)`
1437
+ );
1438
+ return syncedMap;
1439
+ }
1440
+ function extractSyncedTableMap(tableView) {
1441
+ const syncedMap = /* @__PURE__ */ new Map();
1442
+ const allTables = [
1443
+ ...tableView.table?.data ?? [],
1444
+ ...tableView.view?.data ?? [],
1445
+ ...tableView.materializedView?.data ?? []
1446
+ ];
1447
+ for (const table of allTables) {
1448
+ if (table.bitableSyncTask && table.bitableSyncTask.fieldApiNameList?.length > 0) {
1449
+ syncedMap.set(table.tableName, new Set(table.bitableSyncTask.fieldApiNameList));
1450
+ }
1451
+ }
1452
+ return syncedMap;
1453
+ }
1454
+
1298
1455
  // src/commands/db/gen-nest-resource/generator.ts
1299
1456
  import { pluralize } from "inflection";
1300
1457
 
@@ -2017,15 +2174,52 @@ async function run(options = {}) {
2017
2174
  throw new Error("Unable to locate drizzle-kit package root");
2018
2175
  };
2019
2176
  let columnComments;
2020
- try {
2021
- columnComments = await fetchColumnComments(databaseUrl, { timeoutMs: 1e4 });
2022
- console.log(`[gen-db-schema] \u2713 Fetched ${columnComments.size} column comments`);
2023
- } catch (err) {
2177
+ let syncedTableMap;
2178
+ const appId = process.env.app_id;
2179
+ const workspace = process.env.suda_workspace_id;
2180
+ console.log(
2181
+ `[gen-db-schema] Pre-fetch info: columnComments=enabled, syncedTables=${Boolean(appId && workspace) ? "enabled" : "skipped"} (app_id=${appId ? "set" : "unset"}, suda_workspace_id=${workspace ? "set" : "unset"})`
2182
+ );
2183
+ const columnCommentsTask = (async () => {
2184
+ const start = Date.now();
2185
+ console.log("[gen-db-schema] \u2192 Fetching column comments...");
2186
+ const res = await fetchColumnComments(databaseUrl, { timeoutMs: 1e4 });
2187
+ console.log(`[gen-db-schema] \u2190 Fetched column comments: ${res.size} items (${Date.now() - start}ms)`);
2188
+ return res;
2189
+ })();
2190
+ const syncedTablesTask = appId && workspace ? (async () => {
2191
+ const start = Date.now();
2192
+ console.log("[gen-db-schema] \u2192 Fetching synced tables from listTableView...");
2193
+ const res = await fetchSyncedTables(appId, workspace);
2194
+ console.log(`[gen-db-schema] \u2190 Fetched synced tables: ${res.size} tables (${Date.now() - start}ms)`);
2195
+ return res;
2196
+ })() : void 0;
2197
+ const fetchTasks = await Promise.allSettled([
2198
+ columnCommentsTask,
2199
+ ...syncedTablesTask ? [syncedTablesTask] : []
2200
+ ]);
2201
+ if (fetchTasks[0].status === "fulfilled") {
2202
+ columnComments = fetchTasks[0].value;
2203
+ console.log(`[gen-db-schema] \u2713 Column comments ready: ${columnComments.size}`);
2204
+ } else {
2024
2205
  console.warn(
2025
2206
  "[gen-db-schema] \u26A0 Failed to fetch column comments (skipping):",
2026
- err instanceof Error ? err.message : String(err)
2207
+ fetchTasks[0].reason instanceof Error ? fetchTasks[0].reason.message : String(fetchTasks[0].reason)
2027
2208
  );
2028
2209
  }
2210
+ if (appId && workspace) {
2211
+ if (fetchTasks[1]?.status === "fulfilled") {
2212
+ syncedTableMap = fetchTasks[1].value;
2213
+ console.log(`[gen-db-schema] \u2713 Synced tables ready: ${syncedTableMap.size}`);
2214
+ } else if (fetchTasks[1]?.status === "rejected") {
2215
+ console.warn(
2216
+ "[gen-db-schema] \u26A0 Failed to fetch synced tables (skipping):",
2217
+ fetchTasks[1].reason instanceof Error ? fetchTasks[1].reason.message : String(fetchTasks[1].reason)
2218
+ );
2219
+ }
2220
+ } else {
2221
+ console.info("[gen-db-schema] \u2139 Skipping synced table detection (app_id or suda_workspace_id not set)");
2222
+ }
2029
2223
  try {
2030
2224
  const env = {
2031
2225
  ...process.env,
@@ -2050,7 +2244,8 @@ async function run(options = {}) {
2050
2244
  throw new Error("drizzle-kit introspect failed to generate schema.ts");
2051
2245
  }
2052
2246
  const stats = await postprocessDrizzleSchema(generatedSchema, {
2053
- columnComments
2247
+ columnComments,
2248
+ syncedTableMap
2054
2249
  });
2055
2250
  if (stats?.unmatchedUnknown?.length) {
2056
2251
  console.warn("[gen-db-schema] Unmatched custom types detected:", stats.unmatchedUnknown);
@@ -2419,10 +2614,379 @@ var syncCommand = {
2419
2614
  }
2420
2615
  };
2421
2616
 
2422
- // src/commands/action-plugin/utils.ts
2617
+ // src/utils/telemetry.ts
2618
+ async function reportEvents(events) {
2619
+ if (events.length === 0) {
2620
+ return true;
2621
+ }
2622
+ try {
2623
+ const client = getHttpClient();
2624
+ const response = await client.post("/api/v1/studio/innerapi/resource_events", { events });
2625
+ if (!response.ok) {
2626
+ console.warn(`[telemetry] Failed to report events: ${response.status} ${response.statusText}`);
2627
+ return false;
2628
+ }
2629
+ const result = await response.json();
2630
+ if (result.status_code !== "0") {
2631
+ console.warn(`[telemetry] API error: ${result.message}`);
2632
+ return false;
2633
+ }
2634
+ return true;
2635
+ } catch (error) {
2636
+ console.warn(`[telemetry] Failed to report events: ${error instanceof Error ? error.message : error}`);
2637
+ return false;
2638
+ }
2639
+ }
2640
+ async function reportInstallEvent(pluginKey, version) {
2641
+ await reportEvents([
2642
+ {
2643
+ resourceType: "plugin",
2644
+ resourceKey: pluginKey,
2645
+ eventType: "install",
2646
+ details: { version }
2647
+ }
2648
+ ]);
2649
+ }
2650
+ async function reportCreateInstanceEvent(pluginKey, version) {
2651
+ await reportEvents([
2652
+ {
2653
+ resourceType: "plugin",
2654
+ resourceKey: pluginKey,
2655
+ eventType: "create_instance",
2656
+ details: { version }
2657
+ }
2658
+ ]);
2659
+ }
2660
+
2661
+ // src/utils/git.ts
2662
+ import { execSync, spawnSync as spawnSync2 } from "child_process";
2423
2663
  import fs7 from "fs";
2424
2664
  import path5 from "path";
2425
- import { spawnSync as spawnSync2, execSync } from "child_process";
2665
+ function isGitRepository(cwd = process.cwd()) {
2666
+ try {
2667
+ const gitDir = path5.join(cwd, ".git");
2668
+ if (fs7.existsSync(gitDir)) {
2669
+ return true;
2670
+ }
2671
+ const result = spawnSync2("git", ["rev-parse", "--git-dir"], {
2672
+ cwd,
2673
+ stdio: "pipe",
2674
+ encoding: "utf-8"
2675
+ });
2676
+ return result.status === 0;
2677
+ } catch {
2678
+ return false;
2679
+ }
2680
+ }
2681
+ function getChangedFiles(cwd = process.cwd()) {
2682
+ try {
2683
+ const output = execSync("git status --porcelain", {
2684
+ cwd,
2685
+ stdio: "pipe",
2686
+ encoding: "utf-8"
2687
+ });
2688
+ return output.split("\n").filter((line) => line.trim()).map((line) => line.substring(3));
2689
+ } catch (error) {
2690
+ const message = error instanceof Error ? error.message : String(error);
2691
+ throw new Error(`Failed to get changed files: ${message}`);
2692
+ }
2693
+ }
2694
+ function gitAddUpgradeFiles(cwd = process.cwd(), filesToStage) {
2695
+ const filteredFiles = [];
2696
+ for (const filePath of filesToStage) {
2697
+ if (fs7.existsSync(path5.join(cwd, filePath))) {
2698
+ filteredFiles.push(filePath);
2699
+ continue;
2700
+ }
2701
+ const tracked = spawnSync2("git", ["ls-files", "--error-unmatch", "--", filePath], {
2702
+ cwd,
2703
+ stdio: "pipe",
2704
+ encoding: "utf-8"
2705
+ });
2706
+ if (tracked.status === 0) {
2707
+ filteredFiles.push(filePath);
2708
+ }
2709
+ }
2710
+ if (filteredFiles.length === 0) {
2711
+ return;
2712
+ }
2713
+ const result = spawnSync2("git", ["add", "--", ...filteredFiles], {
2714
+ cwd,
2715
+ stdio: "pipe",
2716
+ encoding: "utf-8"
2717
+ });
2718
+ if (result.error || result.status !== 0) {
2719
+ const errorMsg = result.stderr || result.error?.message || "Unknown error";
2720
+ throw new Error(`git add failed: ${errorMsg}`);
2721
+ }
2722
+ }
2723
+ function gitCommit(message, cwd = process.cwd()) {
2724
+ const result = spawnSync2("git", ["commit", "-m", message], {
2725
+ cwd,
2726
+ stdio: "pipe",
2727
+ encoding: "utf-8"
2728
+ });
2729
+ if (result.error || result.status !== 0) {
2730
+ const errorMsg = result.stderr || result.error?.message || "Unknown error";
2731
+ throw new Error(`git commit failed: ${errorMsg}`);
2732
+ }
2733
+ }
2734
+ function autoCommitUpgradeChanges(version, cwd, filesToStage, commitMessage) {
2735
+ if (!isGitRepository(cwd)) {
2736
+ console.log("[fullstack-cli] \u26A0 Not a git repository, skipping auto-commit");
2737
+ return false;
2738
+ }
2739
+ const changedFiles = getChangedFiles(cwd);
2740
+ if (changedFiles.length === 0) {
2741
+ console.log("[fullstack-cli] No changes to commit");
2742
+ return false;
2743
+ }
2744
+ try {
2745
+ gitAddUpgradeFiles(cwd, filesToStage);
2746
+ const message = commitMessage || `chore(upgrade): auto-upgrade by fullstack-cli
2747
+
2748
+ - Sync template files
2749
+ - Cleanup package.json config
2750
+ - Upgrade @lark-apaas dependencies (if any)
2751
+
2752
+ Auto-committed by fullstack-cli v${version}`;
2753
+ gitCommit(message, cwd);
2754
+ console.log(`[fullstack-cli] \u2713 Auto-committed ${changedFiles.length} changed file(s)`);
2755
+ return true;
2756
+ } catch (error) {
2757
+ const message = error instanceof Error ? error.message : String(error);
2758
+ throw new Error(`Failed to auto-commit changes: ${message}`);
2759
+ }
2760
+ }
2761
+
2762
+ // src/utils/package-json.ts
2763
+ import fs8 from "fs";
2764
+ import path6 from "path";
2765
+ function readPackageJson(cwd = process.cwd()) {
2766
+ const pkgPath = path6.join(cwd, "package.json");
2767
+ if (!fs8.existsSync(pkgPath)) {
2768
+ throw new Error(`package.json not found at ${pkgPath}`);
2769
+ }
2770
+ const content = fs8.readFileSync(pkgPath, "utf-8");
2771
+ return JSON.parse(content);
2772
+ }
2773
+ function writePackageJson(pkg2, cwd = process.cwd()) {
2774
+ const pkgPath = path6.join(cwd, "package.json");
2775
+ const content = JSON.stringify(pkg2, null, 2) + "\n";
2776
+ fs8.writeFileSync(pkgPath, content, "utf-8");
2777
+ }
2778
+ function removeUpgradeScript(pkg2) {
2779
+ if (!pkg2.scripts?.upgrade) {
2780
+ return false;
2781
+ }
2782
+ delete pkg2.scripts.upgrade;
2783
+ return true;
2784
+ }
2785
+ function cleanDevScript(pkg2) {
2786
+ if (!pkg2.scripts?.dev) {
2787
+ return false;
2788
+ }
2789
+ const originalDev = pkg2.scripts.dev;
2790
+ const cleanedDev = originalDev.replace(/npm\s+run\s+upgrade\s*&&\s*/g, "").replace(/npm\s+run\s+upgrade\s*$/g, "").trim();
2791
+ if (cleanedDev !== originalDev) {
2792
+ pkg2.scripts.dev = cleanedDev;
2793
+ return true;
2794
+ }
2795
+ return false;
2796
+ }
2797
+ function cleanupPackageJson(cwd = process.cwd()) {
2798
+ try {
2799
+ const pkg2 = readPackageJson(cwd);
2800
+ let changed = false;
2801
+ if (removeUpgradeScript(pkg2)) {
2802
+ console.log("[fullstack-cli] \u2713 Removed scripts.upgrade");
2803
+ changed = true;
2804
+ }
2805
+ if (cleanDevScript(pkg2)) {
2806
+ console.log("[fullstack-cli] \u2713 Cleaned scripts.dev (removed npm run upgrade)");
2807
+ changed = true;
2808
+ }
2809
+ if (changed) {
2810
+ writePackageJson(pkg2, cwd);
2811
+ }
2812
+ return changed;
2813
+ } catch (error) {
2814
+ const message = error instanceof Error ? error.message : String(error);
2815
+ console.log(`[fullstack-cli] \u26A0 Could not cleanup package.json: ${message}`);
2816
+ return false;
2817
+ }
2818
+ }
2819
+
2820
+ // src/commands/upgrade/shared/utils.ts
2821
+ import path7 from "path";
2822
+ import fs9 from "fs";
2823
+ import { fileURLToPath as fileURLToPath4 } from "url";
2824
+ function getCliVersion() {
2825
+ try {
2826
+ const __filename = fileURLToPath4(import.meta.url);
2827
+ const __dirname2 = path7.dirname(__filename);
2828
+ const pkgPath = path7.resolve(__dirname2, "../../../package.json");
2829
+ const pkgContent = fs9.readFileSync(pkgPath, "utf-8");
2830
+ const pkg2 = JSON.parse(pkgContent);
2831
+ return pkg2.version || "unknown";
2832
+ } catch {
2833
+ return "unknown";
2834
+ }
2835
+ }
2836
+
2837
+ // src/commands/upgrade/get-upgrade-files.ts
2838
+ function getUpgradeFilesToStage(disableGenOpenapi = true) {
2839
+ const syncConfig2 = genSyncConfig({ disableGenOpenapi });
2840
+ const filesToStage = /* @__PURE__ */ new Set();
2841
+ syncConfig2.sync.forEach((rule) => {
2842
+ if (rule.type === "file" || rule.type === "directory") {
2843
+ filesToStage.add(rule.to);
2844
+ } else if (rule.type === "remove-line" || rule.type === "add-line") {
2845
+ filesToStage.add(rule.to);
2846
+ } else if (rule.type === "add-script") {
2847
+ filesToStage.add("package.json");
2848
+ } else if (rule.type === "delete-file" || rule.type === "delete-directory") {
2849
+ filesToStage.add(rule.to);
2850
+ }
2851
+ });
2852
+ filesToStage.add("package.json");
2853
+ filesToStage.add("package-lock.json");
2854
+ return Array.from(filesToStage);
2855
+ }
2856
+
2857
+ // src/commands/upgrade/run.handler.ts
2858
+ async function run3(options = {}) {
2859
+ const userProjectRoot = process.env.INIT_CWD || process.cwd();
2860
+ console.log("[fullstack-cli] Starting upgrade...");
2861
+ try {
2862
+ console.log("[fullstack-cli] Step 1/3: Syncing template files...");
2863
+ await run2({ disableGenOpenapi: options.disableGenOpenapi ?? true });
2864
+ console.log("[fullstack-cli] Step 2/3: Cleaning up package.json...");
2865
+ const cleaned = cleanupPackageJson(userProjectRoot);
2866
+ if (!cleaned) {
2867
+ console.log("[fullstack-cli] \u25CB No cleanup needed");
2868
+ }
2869
+ const shouldCommit = options.commit ?? true;
2870
+ if (shouldCommit) {
2871
+ console.log("[fullstack-cli] Step 3/3: Committing changes...");
2872
+ const version = getCliVersion();
2873
+ const filesToStage = getUpgradeFilesToStage(options.disableGenOpenapi ?? true);
2874
+ autoCommitUpgradeChanges(version, userProjectRoot, filesToStage);
2875
+ } else {
2876
+ console.log("[fullstack-cli] Step 3/3: Skipping commit (--no-commit flag)");
2877
+ }
2878
+ console.log("[fullstack-cli] Upgrade completed successfully \u2705");
2879
+ } catch (error) {
2880
+ const message = error instanceof Error ? error.message : String(error);
2881
+ console.error("[fullstack-cli] Failed to upgrade:", message);
2882
+ process.exit(1);
2883
+ }
2884
+ }
2885
+
2886
+ // src/commands/upgrade/deps/run.handler.ts
2887
+ import { spawnSync as spawnSync3 } from "child_process";
2888
+ function findLarkAapaasPackages(cwd, filterPackages) {
2889
+ const pkg2 = readPackageJson(cwd);
2890
+ const allPackages = /* @__PURE__ */ new Set();
2891
+ if (pkg2.dependencies) {
2892
+ Object.keys(pkg2.dependencies).forEach((name) => {
2893
+ if (name.startsWith("@lark-apaas/")) {
2894
+ allPackages.add(name);
2895
+ }
2896
+ });
2897
+ }
2898
+ if (pkg2.devDependencies) {
2899
+ Object.keys(pkg2.devDependencies).forEach((name) => {
2900
+ if (name.startsWith("@lark-apaas/")) {
2901
+ allPackages.add(name);
2902
+ }
2903
+ });
2904
+ }
2905
+ const packages = Array.from(allPackages);
2906
+ if (filterPackages) {
2907
+ const filter = new Set(filterPackages.split(",").map((p) => p.trim()));
2908
+ return packages.filter((p) => filter.has(p));
2909
+ }
2910
+ return packages;
2911
+ }
2912
+ function upgradePackages(packages, version, cwd) {
2913
+ if (version) {
2914
+ console.log(`[fullstack-cli] Upgrading to version ${version}...`);
2915
+ packages.forEach((pkg2) => {
2916
+ const target = `${pkg2}@${version}`;
2917
+ console.log(`[fullstack-cli] Installing ${target}...`);
2918
+ const result = spawnSync3("npm", ["install", target], {
2919
+ cwd,
2920
+ stdio: "inherit"
2921
+ });
2922
+ if (result.error || result.status !== 0) {
2923
+ throw new Error(`Failed to install ${target}`);
2924
+ }
2925
+ });
2926
+ } else {
2927
+ console.log("[fullstack-cli] Upgrading to latest compatible versions...");
2928
+ packages.forEach((pkg2) => {
2929
+ console.log(`[fullstack-cli] Updating ${pkg2}...`);
2930
+ const result = spawnSync3("npm", ["update", pkg2], {
2931
+ cwd,
2932
+ stdio: "inherit"
2933
+ });
2934
+ if (result.error || result.status !== 0) {
2935
+ throw new Error(`Failed to update ${pkg2}`);
2936
+ }
2937
+ });
2938
+ }
2939
+ }
2940
+ async function run4(options = {}) {
2941
+ const cwd = process.env.INIT_CWD || process.cwd();
2942
+ console.log("[fullstack-cli] Starting dependencies upgrade...");
2943
+ try {
2944
+ console.log("[fullstack-cli] Step 1/2: Scanning @lark-apaas dependencies...");
2945
+ const packages = findLarkAapaasPackages(cwd, options.packages);
2946
+ if (packages.length === 0) {
2947
+ console.log("[fullstack-cli] No @lark-apaas packages found");
2948
+ return;
2949
+ }
2950
+ console.log(`[fullstack-cli] Found ${packages.length} @lark-apaas package(s):`);
2951
+ packages.forEach((p) => console.log(` - ${p}`));
2952
+ console.log("[fullstack-cli] Step 2/2: Upgrading packages...");
2953
+ upgradePackages(packages, options.version, cwd);
2954
+ console.log(`[fullstack-cli] \u2713 Successfully upgraded ${packages.length} package(s)`);
2955
+ console.log("[fullstack-cli] Dependencies upgrade completed successfully \u2705");
2956
+ } catch (error) {
2957
+ const message = error instanceof Error ? error.message : String(error);
2958
+ console.error("[fullstack-cli] Failed to upgrade dependencies:", message);
2959
+ process.exit(1);
2960
+ }
2961
+ }
2962
+
2963
+ // src/commands/upgrade/deps/index.ts
2964
+ var depsCommand = {
2965
+ name: "deps",
2966
+ description: "Upgrade @lark-apaas dependencies",
2967
+ register(parentCommand) {
2968
+ parentCommand.command(this.name).description(this.description).option("--version <version>", "Upgrade to specific version").option("--packages <packages>", "Only upgrade specific packages (comma-separated)").action(async (options) => {
2969
+ await run4(options);
2970
+ });
2971
+ }
2972
+ };
2973
+
2974
+ // src/commands/upgrade/index.ts
2975
+ var upgradeCommand = {
2976
+ name: "upgrade",
2977
+ description: "Upgrade template files and auto-commit changes",
2978
+ register(program) {
2979
+ const upgradeCmd = program.command(this.name).description(this.description).option("--disable-gen-openapi", "Disable generating openapi.ts").option("--no-commit", "Skip auto-commit changes").action(async (options) => {
2980
+ await run3(options);
2981
+ });
2982
+ depsCommand.register(upgradeCmd);
2983
+ }
2984
+ };
2985
+
2986
+ // src/commands/action-plugin/utils.ts
2987
+ import fs10 from "fs";
2988
+ import path8 from "path";
2989
+ import { spawnSync as spawnSync4, execSync as execSync2 } from "child_process";
2426
2990
  function parsePluginName(input) {
2427
2991
  const match = input.match(/^(@[^/]+\/[^@]+)(?:@(.+))?$/);
2428
2992
  if (!match) {
@@ -2439,35 +3003,35 @@ function getProjectRoot() {
2439
3003
  return process.cwd();
2440
3004
  }
2441
3005
  function getPackageJsonPath() {
2442
- return path5.join(getProjectRoot(), "package.json");
3006
+ return path8.join(getProjectRoot(), "package.json");
2443
3007
  }
2444
3008
  function getPluginPath(pluginName) {
2445
- return path5.join(getProjectRoot(), "node_modules", pluginName);
3009
+ return path8.join(getProjectRoot(), "node_modules", pluginName);
2446
3010
  }
2447
- function readPackageJson() {
3011
+ function readPackageJson2() {
2448
3012
  const pkgPath = getPackageJsonPath();
2449
- if (!fs7.existsSync(pkgPath)) {
3013
+ if (!fs10.existsSync(pkgPath)) {
2450
3014
  throw new Error("package.json not found in current directory");
2451
3015
  }
2452
3016
  try {
2453
- const content = fs7.readFileSync(pkgPath, "utf-8");
3017
+ const content = fs10.readFileSync(pkgPath, "utf-8");
2454
3018
  return JSON.parse(content);
2455
3019
  } catch {
2456
3020
  throw new Error("Failed to parse package.json");
2457
3021
  }
2458
3022
  }
2459
- function writePackageJson(pkg2) {
3023
+ function writePackageJson2(pkg2) {
2460
3024
  const pkgPath = getPackageJsonPath();
2461
- fs7.writeFileSync(pkgPath, JSON.stringify(pkg2, null, 2) + "\n", "utf-8");
3025
+ fs10.writeFileSync(pkgPath, JSON.stringify(pkg2, null, 2) + "\n", "utf-8");
2462
3026
  }
2463
3027
  function readActionPlugins() {
2464
- const pkg2 = readPackageJson();
3028
+ const pkg2 = readPackageJson2();
2465
3029
  return pkg2.actionPlugins || {};
2466
3030
  }
2467
3031
  function writeActionPlugins(plugins) {
2468
- const pkg2 = readPackageJson();
3032
+ const pkg2 = readPackageJson2();
2469
3033
  pkg2.actionPlugins = plugins;
2470
- writePackageJson(pkg2);
3034
+ writePackageJson2(pkg2);
2471
3035
  }
2472
3036
  function isPluginInstalled(pluginName) {
2473
3037
  const plugins = readActionPlugins();
@@ -2479,7 +3043,7 @@ function getInstalledPluginVersion(pluginName) {
2479
3043
  }
2480
3044
  function npmInstall(tgzPath) {
2481
3045
  console.log(`[action-plugin] Running npm install ${tgzPath}...`);
2482
- const result = spawnSync2("npm", ["install", tgzPath, "--no-save", "--no-package-lock", "--ignore-scripts"], {
3046
+ const result = spawnSync4("npm", ["install", tgzPath, "--no-save", "--no-package-lock", "--ignore-scripts"], {
2483
3047
  cwd: getProjectRoot(),
2484
3048
  stdio: "inherit"
2485
3049
  });
@@ -2491,12 +3055,12 @@ function npmInstall(tgzPath) {
2491
3055
  }
2492
3056
  }
2493
3057
  function getPackageVersion(pluginName) {
2494
- const pkgJsonPath = path5.join(getPluginPath(pluginName), "package.json");
2495
- if (!fs7.existsSync(pkgJsonPath)) {
3058
+ const pkgJsonPath = path8.join(getPluginPath(pluginName), "package.json");
3059
+ if (!fs10.existsSync(pkgJsonPath)) {
2496
3060
  return null;
2497
3061
  }
2498
3062
  try {
2499
- const content = fs7.readFileSync(pkgJsonPath, "utf-8");
3063
+ const content = fs10.readFileSync(pkgJsonPath, "utf-8");
2500
3064
  const pkg2 = JSON.parse(content);
2501
3065
  return pkg2.version || null;
2502
3066
  } catch {
@@ -2504,49 +3068,49 @@ function getPackageVersion(pluginName) {
2504
3068
  }
2505
3069
  }
2506
3070
  function readPluginPackageJson(pluginPath) {
2507
- const pkgJsonPath = path5.join(pluginPath, "package.json");
2508
- if (!fs7.existsSync(pkgJsonPath)) {
3071
+ const pkgJsonPath = path8.join(pluginPath, "package.json");
3072
+ if (!fs10.existsSync(pkgJsonPath)) {
2509
3073
  return null;
2510
3074
  }
2511
3075
  try {
2512
- const content = fs7.readFileSync(pkgJsonPath, "utf-8");
3076
+ const content = fs10.readFileSync(pkgJsonPath, "utf-8");
2513
3077
  return JSON.parse(content);
2514
3078
  } catch {
2515
3079
  return null;
2516
3080
  }
2517
3081
  }
2518
3082
  function extractTgzToNodeModules(tgzPath, pluginName) {
2519
- const nodeModulesPath = path5.join(getProjectRoot(), "node_modules");
2520
- const targetDir = path5.join(nodeModulesPath, pluginName);
2521
- const scopeDir = path5.dirname(targetDir);
2522
- if (!fs7.existsSync(scopeDir)) {
2523
- fs7.mkdirSync(scopeDir, { recursive: true });
3083
+ const nodeModulesPath = path8.join(getProjectRoot(), "node_modules");
3084
+ const targetDir = path8.join(nodeModulesPath, pluginName);
3085
+ const scopeDir = path8.dirname(targetDir);
3086
+ if (!fs10.existsSync(scopeDir)) {
3087
+ fs10.mkdirSync(scopeDir, { recursive: true });
2524
3088
  }
2525
- if (fs7.existsSync(targetDir)) {
2526
- fs7.rmSync(targetDir, { recursive: true });
3089
+ if (fs10.existsSync(targetDir)) {
3090
+ fs10.rmSync(targetDir, { recursive: true });
2527
3091
  }
2528
- const tempDir = path5.join(nodeModulesPath, ".cache", "fullstack-cli", "extract-temp");
2529
- if (fs7.existsSync(tempDir)) {
2530
- fs7.rmSync(tempDir, { recursive: true });
3092
+ const tempDir = path8.join(nodeModulesPath, ".cache", "fullstack-cli", "extract-temp");
3093
+ if (fs10.existsSync(tempDir)) {
3094
+ fs10.rmSync(tempDir, { recursive: true });
2531
3095
  }
2532
- fs7.mkdirSync(tempDir, { recursive: true });
3096
+ fs10.mkdirSync(tempDir, { recursive: true });
2533
3097
  try {
2534
- execSync(`tar -xzf "${tgzPath}" -C "${tempDir}"`, { stdio: "pipe" });
2535
- const extractedDir = path5.join(tempDir, "package");
2536
- if (fs7.existsSync(extractedDir)) {
2537
- fs7.renameSync(extractedDir, targetDir);
3098
+ execSync2(`tar -xzf "${tgzPath}" -C "${tempDir}"`, { stdio: "pipe" });
3099
+ const extractedDir = path8.join(tempDir, "package");
3100
+ if (fs10.existsSync(extractedDir)) {
3101
+ fs10.renameSync(extractedDir, targetDir);
2538
3102
  } else {
2539
- const files = fs7.readdirSync(tempDir);
3103
+ const files = fs10.readdirSync(tempDir);
2540
3104
  if (files.length === 1) {
2541
- fs7.renameSync(path5.join(tempDir, files[0]), targetDir);
3105
+ fs10.renameSync(path8.join(tempDir, files[0]), targetDir);
2542
3106
  } else {
2543
3107
  throw new Error("Unexpected tgz structure");
2544
3108
  }
2545
3109
  }
2546
3110
  return targetDir;
2547
3111
  } finally {
2548
- if (fs7.existsSync(tempDir)) {
2549
- fs7.rmSync(tempDir, { recursive: true });
3112
+ if (fs10.existsSync(tempDir)) {
3113
+ fs10.rmSync(tempDir, { recursive: true });
2550
3114
  }
2551
3115
  }
2552
3116
  }
@@ -2555,10 +3119,10 @@ function checkMissingPeerDeps(peerDeps) {
2555
3119
  return [];
2556
3120
  }
2557
3121
  const missing = [];
2558
- const nodeModulesPath = path5.join(getProjectRoot(), "node_modules");
3122
+ const nodeModulesPath = path8.join(getProjectRoot(), "node_modules");
2559
3123
  for (const [depName, _version] of Object.entries(peerDeps)) {
2560
- const depPath = path5.join(nodeModulesPath, depName);
2561
- if (!fs7.existsSync(depPath)) {
3124
+ const depPath = path8.join(nodeModulesPath, depName);
3125
+ if (!fs10.existsSync(depPath)) {
2562
3126
  missing.push(depName);
2563
3127
  }
2564
3128
  }
@@ -2569,7 +3133,7 @@ function installMissingDeps(deps) {
2569
3133
  return;
2570
3134
  }
2571
3135
  console.log(`[action-plugin] Installing missing dependencies: ${deps.join(", ")}`);
2572
- const result = spawnSync2("npm", ["install", ...deps, "--no-save", "--no-package-lock"], {
3136
+ const result = spawnSync4("npm", ["install", ...deps, "--no-save", "--no-package-lock"], {
2573
3137
  cwd: getProjectRoot(),
2574
3138
  stdio: "inherit"
2575
3139
  });
@@ -2582,76 +3146,16 @@ function installMissingDeps(deps) {
2582
3146
  }
2583
3147
  function removePluginDirectory(pluginName) {
2584
3148
  const pluginPath = getPluginPath(pluginName);
2585
- if (fs7.existsSync(pluginPath)) {
2586
- fs7.rmSync(pluginPath, { recursive: true });
3149
+ if (fs10.existsSync(pluginPath)) {
3150
+ fs10.rmSync(pluginPath, { recursive: true });
2587
3151
  console.log(`[action-plugin] Removed ${pluginName}`);
2588
3152
  }
2589
3153
  }
2590
3154
 
2591
3155
  // src/commands/action-plugin/api-client.ts
2592
3156
  import { HttpClient as HttpClient2 } from "@lark-apaas/http-client";
2593
- import fs8 from "fs";
2594
- import path6 from "path";
2595
-
2596
- // src/utils/http-client.ts
2597
- import { HttpClient } from "@lark-apaas/http-client";
2598
- var clientInstance = null;
2599
- function getHttpClient() {
2600
- if (!clientInstance) {
2601
- clientInstance = new HttpClient({
2602
- timeout: 3e4,
2603
- platform: {
2604
- enabled: true
2605
- }
2606
- });
2607
- const canaryEnv = process.env.FORCE_FRAMEWORK_CLI_CANARY_ENV;
2608
- if (canaryEnv) {
2609
- clientInstance.interceptors.request.use((req) => {
2610
- req.headers["x-tt-env"] = canaryEnv;
2611
- return req;
2612
- });
2613
- }
2614
- }
2615
- return clientInstance;
2616
- }
2617
-
2618
- // src/utils/telemetry.ts
2619
- async function reportEvents(events) {
2620
- if (events.length === 0) {
2621
- return true;
2622
- }
2623
- try {
2624
- const client = getHttpClient();
2625
- const response = await client.post("/resource_events", {
2626
- body: JSON.stringify({ events })
2627
- });
2628
- if (!response.ok) {
2629
- console.warn(`[telemetry] Failed to report events: ${response.status} ${response.statusText}`);
2630
- return false;
2631
- }
2632
- const result = await response.json();
2633
- if (result.status_code !== "0") {
2634
- console.warn(`[telemetry] API error: ${result.message}`);
2635
- return false;
2636
- }
2637
- return true;
2638
- } catch (error) {
2639
- console.warn(`[telemetry] Failed to report events: ${error instanceof Error ? error.message : error}`);
2640
- return false;
2641
- }
2642
- }
2643
- async function reportInstallEvent(pluginKey, version) {
2644
- await reportEvents([
2645
- {
2646
- resourceType: "plugin",
2647
- resourceKey: pluginKey,
2648
- eventType: "install",
2649
- details: { version }
2650
- }
2651
- ]);
2652
- }
2653
-
2654
- // src/commands/action-plugin/api-client.ts
3157
+ import fs11 from "fs";
3158
+ import path9 from "path";
2655
3159
  var PLUGIN_CACHE_DIR = "node_modules/.cache/fullstack-cli/plugins";
2656
3160
  async function getPluginVersions(keys, latestOnly = true) {
2657
3161
  const client = getHttpClient();
@@ -2715,19 +3219,19 @@ async function downloadFromPublic(downloadURL) {
2715
3219
  return Buffer.from(arrayBuffer);
2716
3220
  }
2717
3221
  function getPluginCacheDir() {
2718
- return path6.join(process.cwd(), PLUGIN_CACHE_DIR);
3222
+ return path9.join(process.cwd(), PLUGIN_CACHE_DIR);
2719
3223
  }
2720
3224
  function ensureCacheDir() {
2721
3225
  const cacheDir = getPluginCacheDir();
2722
- if (!fs8.existsSync(cacheDir)) {
2723
- fs8.mkdirSync(cacheDir, { recursive: true });
3226
+ if (!fs11.existsSync(cacheDir)) {
3227
+ fs11.mkdirSync(cacheDir, { recursive: true });
2724
3228
  }
2725
3229
  }
2726
3230
  function getTempFilePath(pluginKey, version) {
2727
3231
  ensureCacheDir();
2728
3232
  const safeKey = pluginKey.replace(/[/@]/g, "_");
2729
3233
  const filename = `${safeKey}@${version}.tgz`;
2730
- return path6.join(getPluginCacheDir(), filename);
3234
+ return path9.join(getPluginCacheDir(), filename);
2731
3235
  }
2732
3236
  var MAX_RETRIES = 2;
2733
3237
  async function withRetry(operation, description, maxRetries = MAX_RETRIES) {
@@ -2764,7 +3268,7 @@ async function downloadPlugin(pluginKey, requestedVersion) {
2764
3268
  );
2765
3269
  }
2766
3270
  const tgzPath = getTempFilePath(pluginKey, pluginInfo.version);
2767
- fs8.writeFileSync(tgzPath, tgzBuffer);
3271
+ fs11.writeFileSync(tgzPath, tgzBuffer);
2768
3272
  console.log(`[action-plugin] Downloaded to ${tgzPath} (${(tgzBuffer.length / 1024).toFixed(2)} KB)`);
2769
3273
  return {
2770
3274
  tgzPath,
@@ -2778,18 +3282,18 @@ function getCachePath(pluginKey, version) {
2778
3282
  ensureCacheDir();
2779
3283
  const safeKey = pluginKey.replace(/[/@]/g, "_");
2780
3284
  const filename = `${safeKey}@${version}.tgz`;
2781
- return path6.join(getPluginCacheDir(), filename);
3285
+ return path9.join(getPluginCacheDir(), filename);
2782
3286
  }
2783
3287
  function hasCachedPlugin(pluginKey, version) {
2784
3288
  const cachePath = getCachePath(pluginKey, version);
2785
- return fs8.existsSync(cachePath);
3289
+ return fs11.existsSync(cachePath);
2786
3290
  }
2787
3291
  function listCachedPlugins() {
2788
3292
  const cacheDir = getPluginCacheDir();
2789
- if (!fs8.existsSync(cacheDir)) {
3293
+ if (!fs11.existsSync(cacheDir)) {
2790
3294
  return [];
2791
3295
  }
2792
- const files = fs8.readdirSync(cacheDir);
3296
+ const files = fs11.readdirSync(cacheDir);
2793
3297
  const result = [];
2794
3298
  for (const file of files) {
2795
3299
  if (!file.endsWith(".tgz")) continue;
@@ -2797,8 +3301,8 @@ function listCachedPlugins() {
2797
3301
  if (!match) continue;
2798
3302
  const [, rawName, version] = match;
2799
3303
  const name = rawName.replace(/^_/, "@").replace(/_/, "/");
2800
- const filePath = path6.join(cacheDir, file);
2801
- const stat = fs8.statSync(filePath);
3304
+ const filePath = path9.join(cacheDir, file);
3305
+ const stat = fs11.statSync(filePath);
2802
3306
  result.push({
2803
3307
  name,
2804
3308
  version,
@@ -2811,14 +3315,14 @@ function listCachedPlugins() {
2811
3315
  }
2812
3316
  function cleanAllCache() {
2813
3317
  const cacheDir = getPluginCacheDir();
2814
- if (!fs8.existsSync(cacheDir)) {
3318
+ if (!fs11.existsSync(cacheDir)) {
2815
3319
  return 0;
2816
3320
  }
2817
- const files = fs8.readdirSync(cacheDir);
3321
+ const files = fs11.readdirSync(cacheDir);
2818
3322
  let count = 0;
2819
3323
  for (const file of files) {
2820
3324
  if (file.endsWith(".tgz")) {
2821
- fs8.unlinkSync(path6.join(cacheDir, file));
3325
+ fs11.unlinkSync(path9.join(cacheDir, file));
2822
3326
  count++;
2823
3327
  }
2824
3328
  }
@@ -2826,21 +3330,21 @@ function cleanAllCache() {
2826
3330
  }
2827
3331
  function cleanPluginCache(pluginKey, version) {
2828
3332
  const cacheDir = getPluginCacheDir();
2829
- if (!fs8.existsSync(cacheDir)) {
3333
+ if (!fs11.existsSync(cacheDir)) {
2830
3334
  return 0;
2831
3335
  }
2832
3336
  const safeKey = pluginKey.replace(/[/@]/g, "_");
2833
- const files = fs8.readdirSync(cacheDir);
3337
+ const files = fs11.readdirSync(cacheDir);
2834
3338
  let count = 0;
2835
3339
  for (const file of files) {
2836
3340
  if (version) {
2837
3341
  if (file === `${safeKey}@${version}.tgz`) {
2838
- fs8.unlinkSync(path6.join(cacheDir, file));
3342
+ fs11.unlinkSync(path9.join(cacheDir, file));
2839
3343
  count++;
2840
3344
  }
2841
3345
  } else {
2842
3346
  if (file.startsWith(`${safeKey}@`) && file.endsWith(".tgz")) {
2843
- fs8.unlinkSync(path6.join(cacheDir, file));
3347
+ fs11.unlinkSync(path9.join(cacheDir, file));
2844
3348
  count++;
2845
3349
  }
2846
3350
  }
@@ -2934,6 +3438,8 @@ async function installOne(nameWithVersion) {
2934
3438
  if (actualVersion === requestedVersion) {
2935
3439
  console.log(`[action-plugin] Plugin ${name}@${requestedVersion} is already installed`);
2936
3440
  syncActionPluginsRecord(name, actualVersion);
3441
+ reportCreateInstanceEvent(name, actualVersion).catch(() => {
3442
+ });
2937
3443
  return { name, version: actualVersion, success: true, skipped: true };
2938
3444
  }
2939
3445
  }
@@ -2944,6 +3450,8 @@ async function installOne(nameWithVersion) {
2944
3450
  if (actualVersion === targetVersion) {
2945
3451
  console.log(`[action-plugin] Plugin ${name} is already up to date (version: ${actualVersion})`);
2946
3452
  syncActionPluginsRecord(name, actualVersion);
3453
+ reportCreateInstanceEvent(name, actualVersion).catch(() => {
3454
+ });
2947
3455
  return { name, version: actualVersion, success: true, skipped: true };
2948
3456
  }
2949
3457
  console.log(`[action-plugin] Found newer version: ${targetVersion} (installed: ${actualVersion || "none"})`);
@@ -2976,6 +3484,8 @@ async function installOne(nameWithVersion) {
2976
3484
  console.log(`[action-plugin] Successfully installed ${name}@${installedVersion} (${source})`);
2977
3485
  reportInstallEvent(name, installedVersion).catch(() => {
2978
3486
  });
3487
+ reportCreateInstanceEvent(name, installedVersion).catch(() => {
3488
+ });
2979
3489
  return { name, version: installedVersion, success: true };
2980
3490
  } catch (error) {
2981
3491
  const message = error instanceof Error ? error.message : String(error);
@@ -3261,40 +3771,40 @@ var actionPluginCommandGroup = {
3261
3771
  };
3262
3772
 
3263
3773
  // src/commands/capability/utils.ts
3264
- import fs9 from "fs";
3774
+ import fs12 from "fs";
3265
3775
  import { createRequire as createRequire2 } from "module";
3266
- import path7 from "path";
3776
+ import path10 from "path";
3267
3777
  var CAPABILITIES_DIR = "server/capabilities";
3268
3778
  function getProjectRoot2() {
3269
3779
  return process.cwd();
3270
3780
  }
3271
3781
  function getCapabilitiesDir() {
3272
- return path7.join(getProjectRoot2(), CAPABILITIES_DIR);
3782
+ return path10.join(getProjectRoot2(), CAPABILITIES_DIR);
3273
3783
  }
3274
3784
  function getCapabilityPath(id) {
3275
- return path7.join(getCapabilitiesDir(), `${id}.json`);
3785
+ return path10.join(getCapabilitiesDir(), `${id}.json`);
3276
3786
  }
3277
3787
  function getPluginManifestPath(pluginKey) {
3278
- return path7.join(getProjectRoot2(), "node_modules", pluginKey, "manifest.json");
3788
+ return path10.join(getProjectRoot2(), "node_modules", pluginKey, "manifest.json");
3279
3789
  }
3280
3790
  function capabilitiesDirExists() {
3281
- return fs9.existsSync(getCapabilitiesDir());
3791
+ return fs12.existsSync(getCapabilitiesDir());
3282
3792
  }
3283
3793
  function listCapabilityIds() {
3284
3794
  const dir = getCapabilitiesDir();
3285
- if (!fs9.existsSync(dir)) {
3795
+ if (!fs12.existsSync(dir)) {
3286
3796
  return [];
3287
3797
  }
3288
- const files = fs9.readdirSync(dir);
3798
+ const files = fs12.readdirSync(dir);
3289
3799
  return files.filter((f) => f.endsWith(".json") && f !== "capabilities.json").map((f) => f.replace(/\.json$/, ""));
3290
3800
  }
3291
3801
  function readCapability(id) {
3292
3802
  const filePath = getCapabilityPath(id);
3293
- if (!fs9.existsSync(filePath)) {
3803
+ if (!fs12.existsSync(filePath)) {
3294
3804
  throw new Error(`Capability not found: ${id}`);
3295
3805
  }
3296
3806
  try {
3297
- const content = fs9.readFileSync(filePath, "utf-8");
3807
+ const content = fs12.readFileSync(filePath, "utf-8");
3298
3808
  return JSON.parse(content);
3299
3809
  } catch (error) {
3300
3810
  if (error instanceof SyntaxError) {
@@ -3321,11 +3831,11 @@ function readAllCapabilities() {
3321
3831
  }
3322
3832
  function readPluginManifest(pluginKey) {
3323
3833
  const manifestPath = getPluginManifestPath(pluginKey);
3324
- if (!fs9.existsSync(manifestPath)) {
3834
+ if (!fs12.existsSync(manifestPath)) {
3325
3835
  throw new Error(`Plugin not installed: ${pluginKey} (manifest.json not found)`);
3326
3836
  }
3327
3837
  try {
3328
- const content = fs9.readFileSync(manifestPath, "utf-8");
3838
+ const content = fs12.readFileSync(manifestPath, "utf-8");
3329
3839
  return JSON.parse(content);
3330
3840
  } catch (error) {
3331
3841
  if (error instanceof SyntaxError) {
@@ -3342,7 +3852,7 @@ function hasValidParamsSchema(paramsSchema) {
3342
3852
  }
3343
3853
  async function loadPlugin(pluginKey) {
3344
3854
  try {
3345
- const userRequire = createRequire2(path7.join(getProjectRoot2(), "package.json"));
3855
+ const userRequire = createRequire2(path10.join(getProjectRoot2(), "package.json"));
3346
3856
  const resolvedPath = userRequire.resolve(pluginKey);
3347
3857
  const pluginModule = await import(resolvedPath);
3348
3858
  const pluginPackage = pluginModule.default ?? pluginModule;
@@ -3501,9 +4011,12 @@ var capabilityCommandGroup = {
3501
4011
  commands: [listCommand2]
3502
4012
  };
3503
4013
 
4014
+ // src/commands/component/add.handler.ts
4015
+ import { execFile } from "child_process";
4016
+
3504
4017
  // src/commands/component/registry-preparer.ts
3505
- import fs10 from "fs";
3506
- import path8 from "path";
4018
+ import fs13 from "fs";
4019
+ import path11 from "path";
3507
4020
  import os from "os";
3508
4021
 
3509
4022
  // src/commands/component/service.ts
@@ -3559,7 +4072,7 @@ async function sendInstallEvent(key) {
3559
4072
  }
3560
4073
 
3561
4074
  // src/commands/component/registry-preparer.ts
3562
- var REGISTRY_TEMP_DIR = path8.join(os.tmpdir(), "miaoda-registry");
4075
+ var REGISTRY_TEMP_DIR = path11.join(os.tmpdir(), "miaoda-registry");
3563
4076
  function parseComponentKey(key) {
3564
4077
  const match = key.match(/^@([^/]+)\/(.+)$/);
3565
4078
  if (!match) {
@@ -3571,11 +4084,11 @@ function parseComponentKey(key) {
3571
4084
  }
3572
4085
  function getLocalRegistryPath(key) {
3573
4086
  const { scope, name } = parseComponentKey(key);
3574
- return path8.join(REGISTRY_TEMP_DIR, scope, `${name}.json`);
4087
+ return path11.join(REGISTRY_TEMP_DIR, scope, `${name}.json`);
3575
4088
  }
3576
4089
  function ensureDir(dirPath) {
3577
- if (!fs10.existsSync(dirPath)) {
3578
- fs10.mkdirSync(dirPath, { recursive: true });
4090
+ if (!fs13.existsSync(dirPath)) {
4091
+ fs13.mkdirSync(dirPath, { recursive: true });
3579
4092
  }
3580
4093
  }
3581
4094
  async function prepareRecursive(key, visited) {
@@ -3608,8 +4121,8 @@ async function prepareRecursive(key, visited) {
3608
4121
  registryDependencies: deps.map((dep) => getLocalRegistryPath(dep))
3609
4122
  };
3610
4123
  const localPath = getLocalRegistryPath(key);
3611
- ensureDir(path8.dirname(localPath));
3612
- fs10.writeFileSync(localPath, JSON.stringify(rewrittenItem, null, 2), "utf-8");
4124
+ ensureDir(path11.dirname(localPath));
4125
+ fs13.writeFileSync(localPath, JSON.stringify(rewrittenItem, null, 2), "utf-8");
3613
4126
  debug("\u4FDD\u5B58\u5230: %s", localPath);
3614
4127
  }
3615
4128
  async function prepareComponentRegistryItems(id) {
@@ -3619,18 +4132,18 @@ async function prepareComponentRegistryItems(id) {
3619
4132
  }
3620
4133
  function cleanupTempDir() {
3621
4134
  try {
3622
- if (fs10.existsSync(REGISTRY_TEMP_DIR)) {
3623
- fs10.rmSync(REGISTRY_TEMP_DIR, { recursive: true, force: true });
4135
+ if (fs13.existsSync(REGISTRY_TEMP_DIR)) {
4136
+ fs13.rmSync(REGISTRY_TEMP_DIR, { recursive: true, force: true });
3624
4137
  }
3625
4138
  } catch {
3626
4139
  }
3627
4140
  }
3628
4141
  function getDownloadedRegistryItem(itemId) {
3629
4142
  const localPath = getLocalRegistryPath(itemId);
3630
- if (!fs10.existsSync(localPath)) {
4143
+ if (!fs13.existsSync(localPath)) {
3631
4144
  return null;
3632
4145
  }
3633
- const content = fs10.readFileSync(localPath, "utf-8");
4146
+ const content = fs13.readFileSync(localPath, "utf-8");
3634
4147
  return JSON.parse(content);
3635
4148
  }
3636
4149
 
@@ -3730,6 +4243,16 @@ async function executeShadcnAdd(registryItemPath) {
3730
4243
  }
3731
4244
 
3732
4245
  // src/commands/component/add.handler.ts
4246
+ function runActionPluginInit() {
4247
+ return new Promise((resolve) => {
4248
+ execFile("fullstack-cli", ["action-plugin", "init"], { cwd: process.cwd(), stdio: "ignore" }, (error) => {
4249
+ if (error) {
4250
+ debug("action-plugin init \u5931\u8D25: %s", error.message);
4251
+ }
4252
+ resolve();
4253
+ });
4254
+ });
4255
+ }
3733
4256
  function printResult(result) {
3734
4257
  console.log(JSON.stringify(result, null, 2));
3735
4258
  }
@@ -3766,6 +4289,7 @@ async function add(key) {
3766
4289
  errors: [{ message: errorMessage }]
3767
4290
  });
3768
4291
  } finally {
4292
+ await runActionPluginInit();
3769
4293
  cleanupTempDir();
3770
4294
  }
3771
4295
  }
@@ -3787,58 +4311,58 @@ var componentCommandGroup = {
3787
4311
  };
3788
4312
 
3789
4313
  // src/commands/migration/version-manager.ts
3790
- import fs11 from "fs";
3791
- import path9 from "path";
4314
+ import fs14 from "fs";
4315
+ import path12 from "path";
3792
4316
  var PACKAGE_JSON = "package.json";
3793
4317
  var VERSION_FIELD = "migrationVersion";
3794
4318
  function getPackageJsonPath2() {
3795
- return path9.join(process.cwd(), PACKAGE_JSON);
4319
+ return path12.join(process.cwd(), PACKAGE_JSON);
3796
4320
  }
3797
4321
  function getCurrentVersion() {
3798
4322
  const pkgPath = getPackageJsonPath2();
3799
- if (!fs11.existsSync(pkgPath)) {
4323
+ if (!fs14.existsSync(pkgPath)) {
3800
4324
  throw new Error("package.json not found");
3801
4325
  }
3802
- const pkg2 = JSON.parse(fs11.readFileSync(pkgPath, "utf-8"));
4326
+ const pkg2 = JSON.parse(fs14.readFileSync(pkgPath, "utf-8"));
3803
4327
  return pkg2[VERSION_FIELD] ?? 0;
3804
4328
  }
3805
4329
  function setCurrentVersion(version) {
3806
4330
  const pkgPath = getPackageJsonPath2();
3807
- const pkg2 = JSON.parse(fs11.readFileSync(pkgPath, "utf-8"));
4331
+ const pkg2 = JSON.parse(fs14.readFileSync(pkgPath, "utf-8"));
3808
4332
  pkg2[VERSION_FIELD] = version;
3809
- fs11.writeFileSync(pkgPath, JSON.stringify(pkg2, null, 2) + "\n", "utf-8");
4333
+ fs14.writeFileSync(pkgPath, JSON.stringify(pkg2, null, 2) + "\n", "utf-8");
3810
4334
  }
3811
4335
 
3812
4336
  // src/commands/migration/versions/v001_capability/json-migrator/detector.ts
3813
- import fs13 from "fs";
3814
- import path11 from "path";
4337
+ import fs16 from "fs";
4338
+ import path14 from "path";
3815
4339
 
3816
4340
  // src/commands/migration/versions/v001_capability/utils.ts
3817
- import fs12 from "fs";
3818
- import path10 from "path";
4341
+ import fs15 from "fs";
4342
+ import path13 from "path";
3819
4343
  var CAPABILITIES_DIR2 = "server/capabilities";
3820
4344
  function getProjectRoot3() {
3821
4345
  return process.cwd();
3822
4346
  }
3823
4347
  function getCapabilitiesDir2() {
3824
- return path10.join(getProjectRoot3(), CAPABILITIES_DIR2);
4348
+ return path13.join(getProjectRoot3(), CAPABILITIES_DIR2);
3825
4349
  }
3826
4350
  function getPluginManifestPath2(pluginKey) {
3827
- return path10.join(getProjectRoot3(), "node_modules", pluginKey, "manifest.json");
4351
+ return path13.join(getProjectRoot3(), "node_modules", pluginKey, "manifest.json");
3828
4352
  }
3829
4353
 
3830
4354
  // src/commands/migration/versions/v001_capability/json-migrator/detector.ts
3831
4355
  function detectJsonMigration() {
3832
4356
  const capabilitiesDir = getCapabilitiesDir2();
3833
- const oldFilePath = path11.join(capabilitiesDir, "capabilities.json");
3834
- if (!fs13.existsSync(oldFilePath)) {
4357
+ const oldFilePath = path14.join(capabilitiesDir, "capabilities.json");
4358
+ if (!fs16.existsSync(oldFilePath)) {
3835
4359
  return {
3836
4360
  needsMigration: false,
3837
4361
  reason: "capabilities.json not found"
3838
4362
  };
3839
4363
  }
3840
4364
  try {
3841
- const content = fs13.readFileSync(oldFilePath, "utf-8");
4365
+ const content = fs16.readFileSync(oldFilePath, "utf-8");
3842
4366
  const parsed = JSON.parse(content);
3843
4367
  if (!Array.isArray(parsed)) {
3844
4368
  return {
@@ -3889,8 +4413,8 @@ async function check(options) {
3889
4413
  }
3890
4414
 
3891
4415
  // src/commands/migration/versions/v001_capability/json-migrator/index.ts
3892
- import fs14 from "fs";
3893
- import path12 from "path";
4416
+ import fs17 from "fs";
4417
+ import path15 from "path";
3894
4418
 
3895
4419
  // src/commands/migration/versions/v001_capability/mapping.ts
3896
4420
  var DEFAULT_PLUGIN_VERSION = "1.0.0";
@@ -4120,18 +4644,18 @@ function transformCapabilities(oldCapabilities) {
4120
4644
  // src/commands/migration/versions/v001_capability/json-migrator/index.ts
4121
4645
  function loadExistingCapabilities() {
4122
4646
  const capabilitiesDir = getCapabilitiesDir2();
4123
- if (!fs14.existsSync(capabilitiesDir)) {
4647
+ if (!fs17.existsSync(capabilitiesDir)) {
4124
4648
  return [];
4125
4649
  }
4126
- const files = fs14.readdirSync(capabilitiesDir);
4650
+ const files = fs17.readdirSync(capabilitiesDir);
4127
4651
  const capabilities = [];
4128
4652
  for (const file of files) {
4129
4653
  if (file === "capabilities.json" || !file.endsWith(".json")) {
4130
4654
  continue;
4131
4655
  }
4132
4656
  try {
4133
- const filePath = path12.join(capabilitiesDir, file);
4134
- const content = fs14.readFileSync(filePath, "utf-8");
4657
+ const filePath = path15.join(capabilitiesDir, file);
4658
+ const content = fs17.readFileSync(filePath, "utf-8");
4135
4659
  const capability = JSON.parse(content);
4136
4660
  if (capability.id && capability.pluginKey) {
4137
4661
  capabilities.push(capability);
@@ -4189,9 +4713,9 @@ async function migrateJsonFiles(options) {
4189
4713
  }
4190
4714
  const capabilitiesDir = getCapabilitiesDir2();
4191
4715
  for (const cap of newCapabilities) {
4192
- const filePath = path12.join(capabilitiesDir, `${cap.id}.json`);
4716
+ const filePath = path15.join(capabilitiesDir, `${cap.id}.json`);
4193
4717
  const content = JSON.stringify(cap, null, 2);
4194
- fs14.writeFileSync(filePath, content, "utf-8");
4718
+ fs17.writeFileSync(filePath, content, "utf-8");
4195
4719
  console.log(` \u2713 Created: ${cap.id}.json`);
4196
4720
  }
4197
4721
  return {
@@ -4203,11 +4727,11 @@ async function migrateJsonFiles(options) {
4203
4727
  }
4204
4728
 
4205
4729
  // src/commands/migration/versions/v001_capability/plugin-installer/detector.ts
4206
- import fs15 from "fs";
4730
+ import fs18 from "fs";
4207
4731
  function isPluginInstalled2(pluginKey) {
4208
4732
  const actionPlugins = readActionPlugins();
4209
4733
  const manifestPath = getPluginManifestPath2(pluginKey);
4210
- return fs15.existsSync(manifestPath) && !!actionPlugins[pluginKey];
4734
+ return fs18.existsSync(manifestPath) && !!actionPlugins[pluginKey];
4211
4735
  }
4212
4736
  function detectPluginsToInstall(capabilities) {
4213
4737
  const pluginKeys = /* @__PURE__ */ new Set();
@@ -4283,12 +4807,12 @@ async function installPlugins(capabilities, options) {
4283
4807
  }
4284
4808
 
4285
4809
  // src/commands/migration/versions/v001_capability/code-migrator/index.ts
4286
- import path14 from "path";
4810
+ import path17 from "path";
4287
4811
  import { Project as Project3 } from "ts-morph";
4288
4812
 
4289
4813
  // src/commands/migration/versions/v001_capability/code-migrator/scanner.ts
4290
- import fs16 from "fs";
4291
- import path13 from "path";
4814
+ import fs19 from "fs";
4815
+ import path16 from "path";
4292
4816
  var EXCLUDED_DIRS = [
4293
4817
  "node_modules",
4294
4818
  "dist",
@@ -4303,9 +4827,9 @@ var EXCLUDED_PATTERNS = [
4303
4827
  /\.d\.ts$/
4304
4828
  ];
4305
4829
  function scanDirectory(dir, files = []) {
4306
- const entries = fs16.readdirSync(dir, { withFileTypes: true });
4830
+ const entries = fs19.readdirSync(dir, { withFileTypes: true });
4307
4831
  for (const entry of entries) {
4308
- const fullPath = path13.join(dir, entry.name);
4832
+ const fullPath = path16.join(dir, entry.name);
4309
4833
  if (entry.isDirectory()) {
4310
4834
  if (EXCLUDED_DIRS.includes(entry.name)) {
4311
4835
  continue;
@@ -4321,14 +4845,14 @@ function scanDirectory(dir, files = []) {
4321
4845
  return files;
4322
4846
  }
4323
4847
  function scanServerFiles() {
4324
- const serverDir = path13.join(getProjectRoot3(), "server");
4325
- if (!fs16.existsSync(serverDir)) {
4848
+ const serverDir = path16.join(getProjectRoot3(), "server");
4849
+ if (!fs19.existsSync(serverDir)) {
4326
4850
  return [];
4327
4851
  }
4328
4852
  return scanDirectory(serverDir);
4329
4853
  }
4330
4854
  function hasCapabilityImport(filePath) {
4331
- const content = fs16.readFileSync(filePath, "utf-8");
4855
+ const content = fs19.readFileSync(filePath, "utf-8");
4332
4856
  return /import\s+.*from\s+['"][^'"]*capabilities[^'"]*['"]/.test(content);
4333
4857
  }
4334
4858
  function scanFilesToMigrate() {
@@ -4705,7 +5229,7 @@ function analyzeFile(project, filePath, actionNameMap) {
4705
5229
  const callSites = analyzeCallSites(sourceFile, imports);
4706
5230
  const classInfo = analyzeClass(sourceFile);
4707
5231
  const { canMigrate, reason } = canAutoMigrate(classInfo);
4708
- const relativePath = path14.relative(getProjectRoot3(), filePath);
5232
+ const relativePath = path17.relative(getProjectRoot3(), filePath);
4709
5233
  return {
4710
5234
  filePath: relativePath,
4711
5235
  imports,
@@ -4716,7 +5240,7 @@ function analyzeFile(project, filePath, actionNameMap) {
4716
5240
  };
4717
5241
  }
4718
5242
  function migrateFile(project, analysis, dryRun) {
4719
- const absolutePath = path14.join(getProjectRoot3(), analysis.filePath);
5243
+ const absolutePath = path17.join(getProjectRoot3(), analysis.filePath);
4720
5244
  if (!analysis.canAutoMigrate) {
4721
5245
  return {
4722
5246
  filePath: analysis.filePath,
@@ -4819,17 +5343,17 @@ function getSuggestion(analysis) {
4819
5343
  }
4820
5344
 
4821
5345
  // src/commands/migration/versions/v001_capability/cleanup.ts
4822
- import fs17 from "fs";
4823
- import path15 from "path";
5346
+ import fs20 from "fs";
5347
+ import path18 from "path";
4824
5348
  function cleanupOldFiles(capabilities, dryRun) {
4825
5349
  const deletedFiles = [];
4826
5350
  const errors = [];
4827
5351
  const capabilitiesDir = getCapabilitiesDir2();
4828
- const oldJsonPath = path15.join(capabilitiesDir, "capabilities.json");
4829
- if (fs17.existsSync(oldJsonPath)) {
5352
+ const oldJsonPath = path18.join(capabilitiesDir, "capabilities.json");
5353
+ if (fs20.existsSync(oldJsonPath)) {
4830
5354
  try {
4831
5355
  if (!dryRun) {
4832
- fs17.unlinkSync(oldJsonPath);
5356
+ fs20.unlinkSync(oldJsonPath);
4833
5357
  }
4834
5358
  deletedFiles.push("capabilities.json");
4835
5359
  } catch (error) {
@@ -4837,11 +5361,11 @@ function cleanupOldFiles(capabilities, dryRun) {
4837
5361
  }
4838
5362
  }
4839
5363
  for (const cap of capabilities) {
4840
- const tsFilePath = path15.join(capabilitiesDir, `${cap.id}.ts`);
4841
- if (fs17.existsSync(tsFilePath)) {
5364
+ const tsFilePath = path18.join(capabilitiesDir, `${cap.id}.ts`);
5365
+ if (fs20.existsSync(tsFilePath)) {
4842
5366
  try {
4843
5367
  if (!dryRun) {
4844
- fs17.unlinkSync(tsFilePath);
5368
+ fs20.unlinkSync(tsFilePath);
4845
5369
  }
4846
5370
  deletedFiles.push(`${cap.id}.ts`);
4847
5371
  } catch (error) {
@@ -4857,8 +5381,8 @@ function cleanupOldFiles(capabilities, dryRun) {
4857
5381
  }
4858
5382
 
4859
5383
  // src/commands/migration/versions/v001_capability/report-generator.ts
4860
- import fs18 from "fs";
4861
- import path16 from "path";
5384
+ import fs21 from "fs";
5385
+ import path19 from "path";
4862
5386
  var REPORT_FILE = "capability-migration-report.md";
4863
5387
  function printSummary(result) {
4864
5388
  const { jsonMigration, pluginInstallation, codeMigration, cleanup } = result;
@@ -5021,15 +5545,15 @@ async function generateReport(result) {
5021
5545
  }
5022
5546
  lines.push("");
5023
5547
  const logDir = process.env.LOG_DIR || "logs";
5024
- if (!fs18.existsSync(logDir)) {
5548
+ if (!fs21.existsSync(logDir)) {
5025
5549
  return;
5026
5550
  }
5027
- const reportDir = path16.join(logDir, "migration");
5028
- if (!fs18.existsSync(reportDir)) {
5029
- fs18.mkdirSync(reportDir, { recursive: true });
5551
+ const reportDir = path19.join(logDir, "migration");
5552
+ if (!fs21.existsSync(reportDir)) {
5553
+ fs21.mkdirSync(reportDir, { recursive: true });
5030
5554
  }
5031
- const reportPath = path16.join(reportDir, REPORT_FILE);
5032
- fs18.writeFileSync(reportPath, lines.join("\n"), "utf-8");
5555
+ const reportPath = path19.join(reportDir, REPORT_FILE);
5556
+ fs21.writeFileSync(reportPath, lines.join("\n"), "utf-8");
5033
5557
  console.log(`\u{1F4C4} Report generated: ${reportPath}`);
5034
5558
  }
5035
5559
 
@@ -5206,7 +5730,7 @@ function buildResult(jsonMigration, pluginInstallation, codeMigration, cleanup)
5206
5730
  }
5207
5731
 
5208
5732
  // src/commands/migration/versions/v001_capability/run.ts
5209
- async function run3(options) {
5733
+ async function run5(options) {
5210
5734
  try {
5211
5735
  const migrationOptions = {
5212
5736
  dryRun: options.dryRun ?? false
@@ -5271,7 +5795,7 @@ var v001CapabilityMigration = {
5271
5795
  name: "capability",
5272
5796
  description: "Migrate capability configurations from old format (capabilities.json array) to new format (individual JSON files)",
5273
5797
  check,
5274
- run: run3
5798
+ run: run5
5275
5799
  };
5276
5800
 
5277
5801
  // src/commands/migration/versions/index.ts
@@ -5561,10 +6085,10 @@ var migrationCommand = {
5561
6085
  };
5562
6086
 
5563
6087
  // src/commands/read-logs/index.ts
5564
- import path17 from "path";
6088
+ import path20 from "path";
5565
6089
 
5566
6090
  // src/commands/read-logs/std-utils.ts
5567
- import fs19 from "fs";
6091
+ import fs22 from "fs";
5568
6092
  function formatStdPrefixTime(localTime) {
5569
6093
  const match = localTime.match(/^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/);
5570
6094
  if (!match) return localTime;
@@ -5594,11 +6118,11 @@ function stripPrefixFromStdLine(line) {
5594
6118
  return `[${time}] ${content}`;
5595
6119
  }
5596
6120
  function readStdLinesTailFromLastMarkerPaged(filePath, maxLines, offset, isMarker) {
5597
- const stat = fs19.statSync(filePath);
6121
+ const stat = fs22.statSync(filePath);
5598
6122
  if (stat.size === 0) {
5599
6123
  return { lines: [], markerFound: false, totalLinesCount: 0 };
5600
6124
  }
5601
- const fd = fs19.openSync(filePath, "r");
6125
+ const fd = fs22.openSync(filePath, "r");
5602
6126
  const chunkSize = 64 * 1024;
5603
6127
  let position = stat.size;
5604
6128
  let remainder = "";
@@ -5612,7 +6136,7 @@ function readStdLinesTailFromLastMarkerPaged(filePath, maxLines, offset, isMarke
5612
6136
  const length = Math.min(chunkSize, position);
5613
6137
  position -= length;
5614
6138
  const buffer = Buffer.alloc(length);
5615
- fs19.readSync(fd, buffer, 0, length, position);
6139
+ fs22.readSync(fd, buffer, 0, length, position);
5616
6140
  let chunk = buffer.toString("utf8");
5617
6141
  if (remainder) {
5618
6142
  chunk += remainder;
@@ -5654,7 +6178,7 @@ function readStdLinesTailFromLastMarkerPaged(filePath, maxLines, offset, isMarke
5654
6178
  }
5655
6179
  }
5656
6180
  } finally {
5657
- fs19.closeSync(fd);
6181
+ fs22.closeSync(fd);
5658
6182
  }
5659
6183
  return { lines: collected.reverse(), markerFound, totalLinesCount };
5660
6184
  }
@@ -5675,21 +6199,21 @@ function readServerStdSegment(filePath, maxLines, offset) {
5675
6199
  }
5676
6200
 
5677
6201
  // src/commands/read-logs/tail.ts
5678
- import fs20 from "fs";
6202
+ import fs23 from "fs";
5679
6203
  function fileExists(filePath) {
5680
6204
  try {
5681
- fs20.accessSync(filePath, fs20.constants.F_OK | fs20.constants.R_OK);
6205
+ fs23.accessSync(filePath, fs23.constants.F_OK | fs23.constants.R_OK);
5682
6206
  return true;
5683
6207
  } catch {
5684
6208
  return false;
5685
6209
  }
5686
6210
  }
5687
6211
  function readFileTailLines(filePath, maxLines) {
5688
- const stat = fs20.statSync(filePath);
6212
+ const stat = fs23.statSync(filePath);
5689
6213
  if (stat.size === 0) {
5690
6214
  return [];
5691
6215
  }
5692
- const fd = fs20.openSync(filePath, "r");
6216
+ const fd = fs23.openSync(filePath, "r");
5693
6217
  const chunkSize = 64 * 1024;
5694
6218
  const chunks = [];
5695
6219
  let position = stat.size;
@@ -5699,13 +6223,13 @@ function readFileTailLines(filePath, maxLines) {
5699
6223
  const length = Math.min(chunkSize, position);
5700
6224
  position -= length;
5701
6225
  const buffer = Buffer.alloc(length);
5702
- fs20.readSync(fd, buffer, 0, length, position);
6226
+ fs23.readSync(fd, buffer, 0, length, position);
5703
6227
  chunks.unshift(buffer.toString("utf8"));
5704
6228
  const chunkLines = buffer.toString("utf8").split("\n").length - 1;
5705
6229
  collectedLines += chunkLines;
5706
6230
  }
5707
6231
  } finally {
5708
- fs20.closeSync(fd);
6232
+ fs23.closeSync(fd);
5709
6233
  }
5710
6234
  const content = chunks.join("");
5711
6235
  const allLines = content.split("\n");
@@ -5721,11 +6245,11 @@ function readFileTailLines(filePath, maxLines) {
5721
6245
  return allLines.slice(allLines.length - maxLines);
5722
6246
  }
5723
6247
  function readFileTailNonEmptyLinesWithOffset(filePath, maxLines, offset) {
5724
- const stat = fs20.statSync(filePath);
6248
+ const stat = fs23.statSync(filePath);
5725
6249
  if (stat.size === 0) {
5726
6250
  return { lines: [], totalLinesCount: 0 };
5727
6251
  }
5728
- const fd = fs20.openSync(filePath, "r");
6252
+ const fd = fs23.openSync(filePath, "r");
5729
6253
  const chunkSize = 64 * 1024;
5730
6254
  let position = stat.size;
5731
6255
  let remainder = "";
@@ -5737,7 +6261,7 @@ function readFileTailNonEmptyLinesWithOffset(filePath, maxLines, offset) {
5737
6261
  const length = Math.min(chunkSize, position);
5738
6262
  position -= length;
5739
6263
  const buffer = Buffer.alloc(length);
5740
- fs20.readSync(fd, buffer, 0, length, position);
6264
+ fs23.readSync(fd, buffer, 0, length, position);
5741
6265
  let chunk = buffer.toString("utf8");
5742
6266
  if (remainder) {
5743
6267
  chunk += remainder;
@@ -5768,7 +6292,7 @@ function readFileTailNonEmptyLinesWithOffset(filePath, maxLines, offset) {
5768
6292
  }
5769
6293
  }
5770
6294
  } finally {
5771
- fs20.closeSync(fd);
6295
+ fs23.closeSync(fd);
5772
6296
  }
5773
6297
  return { lines: collected.reverse(), totalLinesCount };
5774
6298
  }
@@ -5910,7 +6434,7 @@ function readDevStdSegment(filePath, maxLines, offset) {
5910
6434
  }
5911
6435
 
5912
6436
  // src/commands/read-logs/json-lines.ts
5913
- import fs21 from "fs";
6437
+ import fs24 from "fs";
5914
6438
  function normalizePid(value) {
5915
6439
  if (typeof value === "number") {
5916
6440
  return String(value);
@@ -5961,11 +6485,11 @@ function buildWantedLevelSet(levels) {
5961
6485
  return set.size > 0 ? set : null;
5962
6486
  }
5963
6487
  function readJsonLinesLastPid(filePath, maxLines, offset, levels) {
5964
- const stat = fs21.statSync(filePath);
6488
+ const stat = fs24.statSync(filePath);
5965
6489
  if (stat.size === 0) {
5966
6490
  return { lines: [], totalLinesCount: 0 };
5967
6491
  }
5968
- const fd = fs21.openSync(filePath, "r");
6492
+ const fd = fs24.openSync(filePath, "r");
5969
6493
  const chunkSize = 64 * 1024;
5970
6494
  let position = stat.size;
5971
6495
  let remainder = "";
@@ -5980,7 +6504,7 @@ function readJsonLinesLastPid(filePath, maxLines, offset, levels) {
5980
6504
  const length = Math.min(chunkSize, position);
5981
6505
  position -= length;
5982
6506
  const buffer = Buffer.alloc(length);
5983
- fs21.readSync(fd, buffer, 0, length, position);
6507
+ fs24.readSync(fd, buffer, 0, length, position);
5984
6508
  let chunk = buffer.toString("utf8");
5985
6509
  if (remainder) {
5986
6510
  chunk += remainder;
@@ -6042,7 +6566,7 @@ function readJsonLinesLastPid(filePath, maxLines, offset, levels) {
6042
6566
  }
6043
6567
  }
6044
6568
  } finally {
6045
- fs21.closeSync(fd);
6569
+ fs24.closeSync(fd);
6046
6570
  }
6047
6571
  return { lines: collected.reverse(), totalLinesCount };
6048
6572
  }
@@ -6085,11 +6609,11 @@ function extractTraceId(obj) {
6085
6609
  function readJsonLinesByTraceId(filePath, traceId, maxLines, offset, levels) {
6086
6610
  const wanted = traceId.trim();
6087
6611
  if (!wanted) return { lines: [], totalLinesCount: 0 };
6088
- const stat = fs21.statSync(filePath);
6612
+ const stat = fs24.statSync(filePath);
6089
6613
  if (stat.size === 0) {
6090
6614
  return { lines: [], totalLinesCount: 0 };
6091
6615
  }
6092
- const fd = fs21.openSync(filePath, "r");
6616
+ const fd = fs24.openSync(filePath, "r");
6093
6617
  const chunkSize = 64 * 1024;
6094
6618
  let position = stat.size;
6095
6619
  let remainder = "";
@@ -6102,7 +6626,7 @@ function readJsonLinesByTraceId(filePath, traceId, maxLines, offset, levels) {
6102
6626
  const length = Math.min(chunkSize, position);
6103
6627
  position -= length;
6104
6628
  const buffer = Buffer.alloc(length);
6105
- fs21.readSync(fd, buffer, 0, length, position);
6629
+ fs24.readSync(fd, buffer, 0, length, position);
6106
6630
  let chunk = buffer.toString("utf8");
6107
6631
  if (remainder) {
6108
6632
  chunk += remainder;
@@ -6155,7 +6679,7 @@ function readJsonLinesByTraceId(filePath, traceId, maxLines, offset, levels) {
6155
6679
  }
6156
6680
  }
6157
6681
  } finally {
6158
- fs21.closeSync(fd);
6682
+ fs24.closeSync(fd);
6159
6683
  }
6160
6684
  return { lines: collected.reverse(), totalLinesCount };
6161
6685
  }
@@ -6164,11 +6688,11 @@ function readJsonLinesTailByLevel(filePath, maxLines, offset, levels) {
6164
6688
  if (!wantedLevelSet) {
6165
6689
  return { lines: [], totalLinesCount: 0 };
6166
6690
  }
6167
- const stat = fs21.statSync(filePath);
6691
+ const stat = fs24.statSync(filePath);
6168
6692
  if (stat.size === 0) {
6169
6693
  return { lines: [], totalLinesCount: 0 };
6170
6694
  }
6171
- const fd = fs21.openSync(filePath, "r");
6695
+ const fd = fs24.openSync(filePath, "r");
6172
6696
  const chunkSize = 64 * 1024;
6173
6697
  let position = stat.size;
6174
6698
  let remainder = "";
@@ -6180,7 +6704,7 @@ function readJsonLinesTailByLevel(filePath, maxLines, offset, levels) {
6180
6704
  const length = Math.min(chunkSize, position);
6181
6705
  position -= length;
6182
6706
  const buffer = Buffer.alloc(length);
6183
- fs21.readSync(fd, buffer, 0, length, position);
6707
+ fs24.readSync(fd, buffer, 0, length, position);
6184
6708
  let chunk = buffer.toString("utf8");
6185
6709
  if (remainder) {
6186
6710
  chunk += remainder;
@@ -6227,7 +6751,7 @@ function readJsonLinesTailByLevel(filePath, maxLines, offset, levels) {
6227
6751
  }
6228
6752
  }
6229
6753
  } finally {
6230
- fs21.closeSync(fd);
6754
+ fs24.closeSync(fd);
6231
6755
  }
6232
6756
  return { lines: collected.reverse(), totalLinesCount };
6233
6757
  }
@@ -6461,34 +6985,34 @@ async function readLogsJsonResult(options) {
6461
6985
  };
6462
6986
  }
6463
6987
  function resolveLogFilePath(logDir, type) {
6464
- const base = path17.isAbsolute(logDir) ? logDir : path17.join(process.cwd(), logDir);
6988
+ const base = path20.isAbsolute(logDir) ? logDir : path20.join(process.cwd(), logDir);
6465
6989
  if (type === "server") {
6466
- return path17.join(base, "server.log");
6990
+ return path20.join(base, "server.log");
6467
6991
  }
6468
6992
  if (type === "trace") {
6469
- return path17.join(base, "trace.log");
6993
+ return path20.join(base, "trace.log");
6470
6994
  }
6471
6995
  if (type === "server-std") {
6472
- return path17.join(base, "server.std.log");
6996
+ return path20.join(base, "server.std.log");
6473
6997
  }
6474
6998
  if (type === "client-std") {
6475
- return path17.join(base, "client.std.log");
6999
+ return path20.join(base, "client.std.log");
6476
7000
  }
6477
7001
  if (type === "dev") {
6478
- return path17.join(base, "dev.log");
7002
+ return path20.join(base, "dev.log");
6479
7003
  }
6480
7004
  if (type === "dev-std") {
6481
- return path17.join(base, "dev.std.log");
7005
+ return path20.join(base, "dev.std.log");
6482
7006
  }
6483
7007
  if (type === "install-dep-std") {
6484
- return path17.join(base, "install-dep.std.log");
7008
+ return path20.join(base, "install-dep.std.log");
6485
7009
  }
6486
7010
  if (type === "browser") {
6487
- return path17.join(base, "browser.log");
7011
+ return path20.join(base, "browser.log");
6488
7012
  }
6489
7013
  throw new Error(`Unsupported log type: ${type}`);
6490
7014
  }
6491
- async function run4(options) {
7015
+ async function run6(options) {
6492
7016
  const result = await readLogsJsonResult(options);
6493
7017
  process.stdout.write(JSON.stringify(result) + "\n");
6494
7018
  }
@@ -6530,7 +7054,7 @@ var readLogsCommand = {
6530
7054
  const offset = parseNonNegativeInt(rawOptions.offset, "--offset");
6531
7055
  const traceId = typeof rawOptions.traceId === "string" ? rawOptions.traceId : void 0;
6532
7056
  const levels = parseCommaSeparatedList(rawOptions.level);
6533
- await run4({ logDir, type, maxLines, offset, traceId, levels });
7057
+ await run6({ logDir, type, maxLines, offset, traceId, levels });
6534
7058
  } catch (error) {
6535
7059
  const message = error instanceof Error ? error.message : String(error);
6536
7060
  process.stderr.write(message + "\n");
@@ -6619,6 +7143,7 @@ var buildCommandGroup = {
6619
7143
  var commands = [
6620
7144
  genDbSchemaCommand,
6621
7145
  syncCommand,
7146
+ upgradeCommand,
6622
7147
  actionPluginCommandGroup,
6623
7148
  capabilityCommandGroup,
6624
7149
  componentCommandGroup,
@@ -6628,12 +7153,12 @@ var commands = [
6628
7153
  ];
6629
7154
 
6630
7155
  // src/index.ts
6631
- var envPath = path18.join(process.cwd(), ".env");
6632
- if (fs22.existsSync(envPath)) {
7156
+ var envPath = path21.join(process.cwd(), ".env");
7157
+ if (fs25.existsSync(envPath)) {
6633
7158
  dotenvConfig({ path: envPath });
6634
7159
  }
6635
- var __dirname = path18.dirname(fileURLToPath4(import.meta.url));
6636
- var pkg = JSON.parse(fs22.readFileSync(path18.join(__dirname, "../package.json"), "utf-8"));
7160
+ var __dirname = path21.dirname(fileURLToPath5(import.meta.url));
7161
+ var pkg = JSON.parse(fs25.readFileSync(path21.join(__dirname, "../package.json"), "utf-8"));
6637
7162
  var cli = new FullstackCLI(pkg.version);
6638
7163
  cli.useAll(commands);
6639
7164
  cli.run();