@lark-apaas/fullstack-cli 1.1.16-beta.2 → 1.1.16-beta.4
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 +41 -3
- package/dist/index.js +1023 -214
- package/package.json +6 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import { fileURLToPath as
|
|
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
|
|
@@ -481,6 +481,7 @@ var replaceUnknownTransform = {
|
|
|
481
481
|
transform(ctx) {
|
|
482
482
|
const { sourceFile, stats } = ctx;
|
|
483
483
|
const fullText = sourceFile.getFullText();
|
|
484
|
+
const replacements = [];
|
|
484
485
|
sourceFile.forEachDescendant((node) => {
|
|
485
486
|
if (!Node5.isCallExpression(node)) {
|
|
486
487
|
return;
|
|
@@ -511,13 +512,23 @@ var replaceUnknownTransform = {
|
|
|
511
512
|
break;
|
|
512
513
|
}
|
|
513
514
|
}
|
|
515
|
+
replacements.push({
|
|
516
|
+
expression,
|
|
517
|
+
factoryName,
|
|
518
|
+
foundKnownType,
|
|
519
|
+
isArrayType,
|
|
520
|
+
node
|
|
521
|
+
});
|
|
522
|
+
});
|
|
523
|
+
for (const { expression, factoryName, foundKnownType, isArrayType, node } of replacements) {
|
|
514
524
|
expression.replaceWithText(factoryName);
|
|
515
525
|
if (isArrayType && foundKnownType) {
|
|
516
526
|
const parent = node.getParent();
|
|
517
527
|
if (Node5.isPropertyAccessExpression(parent) && parent.getName() === "array") {
|
|
518
528
|
const grandParent = parent.getParent();
|
|
519
529
|
if (Node5.isCallExpression(grandParent)) {
|
|
520
|
-
|
|
530
|
+
const nodeText = node.getText();
|
|
531
|
+
grandParent.replaceWithText(nodeText);
|
|
521
532
|
}
|
|
522
533
|
}
|
|
523
534
|
}
|
|
@@ -526,7 +537,7 @@ var replaceUnknownTransform = {
|
|
|
526
537
|
} else {
|
|
527
538
|
stats.fallbackToText++;
|
|
528
539
|
}
|
|
529
|
-
}
|
|
540
|
+
}
|
|
530
541
|
const todoCommentRegex = /\/\/ TODO: failed to parse database type '[^']+'\s*\n/g;
|
|
531
542
|
const currentText = sourceFile.getFullText();
|
|
532
543
|
const cleanedText = currentText.replace(todoCommentRegex, "");
|
|
@@ -2408,10 +2419,420 @@ var syncCommand = {
|
|
|
2408
2419
|
}
|
|
2409
2420
|
};
|
|
2410
2421
|
|
|
2411
|
-
// src/
|
|
2422
|
+
// src/utils/http-client.ts
|
|
2423
|
+
import { HttpClient } from "@lark-apaas/http-client";
|
|
2424
|
+
var clientInstance = null;
|
|
2425
|
+
function getHttpClient() {
|
|
2426
|
+
if (!clientInstance) {
|
|
2427
|
+
clientInstance = new HttpClient({
|
|
2428
|
+
timeout: 3e4,
|
|
2429
|
+
platform: {
|
|
2430
|
+
enabled: true
|
|
2431
|
+
}
|
|
2432
|
+
});
|
|
2433
|
+
const canaryEnv = process.env.FORCE_FRAMEWORK_CLI_CANARY_ENV;
|
|
2434
|
+
if (canaryEnv) {
|
|
2435
|
+
clientInstance.interceptors.request.use((req) => {
|
|
2436
|
+
req.headers["x-tt-env"] = canaryEnv;
|
|
2437
|
+
return req;
|
|
2438
|
+
});
|
|
2439
|
+
}
|
|
2440
|
+
}
|
|
2441
|
+
return clientInstance;
|
|
2442
|
+
}
|
|
2443
|
+
|
|
2444
|
+
// src/utils/telemetry.ts
|
|
2445
|
+
async function reportEvents(events) {
|
|
2446
|
+
if (events.length === 0) {
|
|
2447
|
+
return true;
|
|
2448
|
+
}
|
|
2449
|
+
try {
|
|
2450
|
+
const client = getHttpClient();
|
|
2451
|
+
const response = await client.post("/api/v1/studio/innerapi/resource_events", { events });
|
|
2452
|
+
if (!response.ok) {
|
|
2453
|
+
console.warn(`[telemetry] Failed to report events: ${response.status} ${response.statusText}`);
|
|
2454
|
+
return false;
|
|
2455
|
+
}
|
|
2456
|
+
const result = await response.json();
|
|
2457
|
+
if (result.status_code !== "0") {
|
|
2458
|
+
console.warn(`[telemetry] API error: ${result.message}`);
|
|
2459
|
+
return false;
|
|
2460
|
+
}
|
|
2461
|
+
return true;
|
|
2462
|
+
} catch (error) {
|
|
2463
|
+
console.warn(`[telemetry] Failed to report events: ${error instanceof Error ? error.message : error}`);
|
|
2464
|
+
return false;
|
|
2465
|
+
}
|
|
2466
|
+
}
|
|
2467
|
+
async function reportInstallEvent(pluginKey, version) {
|
|
2468
|
+
await reportEvents([
|
|
2469
|
+
{
|
|
2470
|
+
resourceType: "plugin",
|
|
2471
|
+
resourceKey: pluginKey,
|
|
2472
|
+
eventType: "install",
|
|
2473
|
+
details: { version }
|
|
2474
|
+
}
|
|
2475
|
+
]);
|
|
2476
|
+
}
|
|
2477
|
+
async function reportCreateInstanceEvent(pluginKey, version) {
|
|
2478
|
+
await reportEvents([
|
|
2479
|
+
{
|
|
2480
|
+
resourceType: "plugin",
|
|
2481
|
+
resourceKey: pluginKey,
|
|
2482
|
+
eventType: "create_instance",
|
|
2483
|
+
details: { version }
|
|
2484
|
+
}
|
|
2485
|
+
]);
|
|
2486
|
+
}
|
|
2487
|
+
|
|
2488
|
+
// src/utils/git.ts
|
|
2489
|
+
import { execSync, spawnSync as spawnSync2 } from "child_process";
|
|
2412
2490
|
import fs7 from "fs";
|
|
2413
2491
|
import path5 from "path";
|
|
2414
|
-
|
|
2492
|
+
function isGitRepository(cwd = process.cwd()) {
|
|
2493
|
+
try {
|
|
2494
|
+
const gitDir = path5.join(cwd, ".git");
|
|
2495
|
+
if (fs7.existsSync(gitDir)) {
|
|
2496
|
+
return true;
|
|
2497
|
+
}
|
|
2498
|
+
const result = spawnSync2("git", ["rev-parse", "--git-dir"], {
|
|
2499
|
+
cwd,
|
|
2500
|
+
stdio: "pipe",
|
|
2501
|
+
encoding: "utf-8"
|
|
2502
|
+
});
|
|
2503
|
+
return result.status === 0;
|
|
2504
|
+
} catch {
|
|
2505
|
+
return false;
|
|
2506
|
+
}
|
|
2507
|
+
}
|
|
2508
|
+
function getChangedFiles(cwd = process.cwd()) {
|
|
2509
|
+
try {
|
|
2510
|
+
const output = execSync("git status --porcelain", {
|
|
2511
|
+
cwd,
|
|
2512
|
+
stdio: "pipe",
|
|
2513
|
+
encoding: "utf-8"
|
|
2514
|
+
});
|
|
2515
|
+
return output.split("\n").filter((line) => line.trim()).map((line) => line.substring(3));
|
|
2516
|
+
} catch (error) {
|
|
2517
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2518
|
+
throw new Error(`Failed to get changed files: ${message}`);
|
|
2519
|
+
}
|
|
2520
|
+
}
|
|
2521
|
+
function gitAddUpgradeFiles(cwd = process.cwd(), filesToStage) {
|
|
2522
|
+
const filteredFiles = [];
|
|
2523
|
+
for (const filePath of filesToStage) {
|
|
2524
|
+
if (fs7.existsSync(path5.join(cwd, filePath))) {
|
|
2525
|
+
filteredFiles.push(filePath);
|
|
2526
|
+
continue;
|
|
2527
|
+
}
|
|
2528
|
+
const tracked = spawnSync2("git", ["ls-files", "--error-unmatch", "--", filePath], {
|
|
2529
|
+
cwd,
|
|
2530
|
+
stdio: "pipe",
|
|
2531
|
+
encoding: "utf-8"
|
|
2532
|
+
});
|
|
2533
|
+
if (tracked.status === 0) {
|
|
2534
|
+
filteredFiles.push(filePath);
|
|
2535
|
+
}
|
|
2536
|
+
}
|
|
2537
|
+
if (filteredFiles.length === 0) {
|
|
2538
|
+
return;
|
|
2539
|
+
}
|
|
2540
|
+
const result = spawnSync2("git", ["add", "--", ...filteredFiles], {
|
|
2541
|
+
cwd,
|
|
2542
|
+
stdio: "pipe",
|
|
2543
|
+
encoding: "utf-8"
|
|
2544
|
+
});
|
|
2545
|
+
if (result.error || result.status !== 0) {
|
|
2546
|
+
const errorMsg = result.stderr || result.error?.message || "Unknown error";
|
|
2547
|
+
throw new Error(`git add failed: ${errorMsg}`);
|
|
2548
|
+
}
|
|
2549
|
+
}
|
|
2550
|
+
function hasStagedChanges(cwd = process.cwd()) {
|
|
2551
|
+
const result = spawnSync2("git", ["diff", "--cached", "--quiet"], {
|
|
2552
|
+
cwd,
|
|
2553
|
+
stdio: "pipe",
|
|
2554
|
+
encoding: "utf-8"
|
|
2555
|
+
});
|
|
2556
|
+
if (result.status === 0) {
|
|
2557
|
+
return false;
|
|
2558
|
+
}
|
|
2559
|
+
if (result.status === 1) {
|
|
2560
|
+
return true;
|
|
2561
|
+
}
|
|
2562
|
+
const errorMsg = result.stderr || result.error?.message || "Unknown error";
|
|
2563
|
+
throw new Error(`Failed to check staged changes: ${errorMsg}`);
|
|
2564
|
+
}
|
|
2565
|
+
function gitCommit(message, cwd = process.cwd()) {
|
|
2566
|
+
const result = spawnSync2("git", ["commit", "-m", message], {
|
|
2567
|
+
cwd,
|
|
2568
|
+
stdio: "pipe",
|
|
2569
|
+
encoding: "utf-8"
|
|
2570
|
+
});
|
|
2571
|
+
if (result.error || result.status !== 0) {
|
|
2572
|
+
const errorMsg = result.stderr || result.error?.message || "Unknown error";
|
|
2573
|
+
throw new Error(`git commit failed: ${errorMsg}`);
|
|
2574
|
+
}
|
|
2575
|
+
}
|
|
2576
|
+
function autoCommitUpgradeChanges(version, cwd, filesToStage, commitMessage) {
|
|
2577
|
+
if (!isGitRepository(cwd)) {
|
|
2578
|
+
console.log("[fullstack-cli] \u26A0 Not a git repository, skipping auto-commit");
|
|
2579
|
+
return false;
|
|
2580
|
+
}
|
|
2581
|
+
const changedFiles = getChangedFiles(cwd);
|
|
2582
|
+
if (changedFiles.length === 0) {
|
|
2583
|
+
console.log("[fullstack-cli] No changes to commit");
|
|
2584
|
+
return false;
|
|
2585
|
+
}
|
|
2586
|
+
try {
|
|
2587
|
+
gitAddUpgradeFiles(cwd, filesToStage);
|
|
2588
|
+
if (!hasStagedChanges(cwd)) {
|
|
2589
|
+
console.log("[fullstack-cli] No upgrade changes to commit");
|
|
2590
|
+
return false;
|
|
2591
|
+
}
|
|
2592
|
+
const message = commitMessage || `chore(upgrade): auto-upgrade by fullstack-cli
|
|
2593
|
+
|
|
2594
|
+
- Sync template files
|
|
2595
|
+
- Cleanup package.json config
|
|
2596
|
+
- Upgrade @lark-apaas dependencies (if any)
|
|
2597
|
+
|
|
2598
|
+
Auto-committed by fullstack-cli v${version}`;
|
|
2599
|
+
gitCommit(message, cwd);
|
|
2600
|
+
console.log(`[fullstack-cli] \u2713 Auto-committed ${changedFiles.length} changed file(s)`);
|
|
2601
|
+
return true;
|
|
2602
|
+
} catch (error) {
|
|
2603
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2604
|
+
throw new Error(`Failed to auto-commit changes: ${message}`);
|
|
2605
|
+
}
|
|
2606
|
+
}
|
|
2607
|
+
|
|
2608
|
+
// src/utils/package-json.ts
|
|
2609
|
+
import fs8 from "fs";
|
|
2610
|
+
import path6 from "path";
|
|
2611
|
+
function readPackageJson(cwd = process.cwd()) {
|
|
2612
|
+
const pkgPath = path6.join(cwd, "package.json");
|
|
2613
|
+
if (!fs8.existsSync(pkgPath)) {
|
|
2614
|
+
throw new Error(`package.json not found at ${pkgPath}`);
|
|
2615
|
+
}
|
|
2616
|
+
const content = fs8.readFileSync(pkgPath, "utf-8");
|
|
2617
|
+
return JSON.parse(content);
|
|
2618
|
+
}
|
|
2619
|
+
function writePackageJson(pkg2, cwd = process.cwd()) {
|
|
2620
|
+
const pkgPath = path6.join(cwd, "package.json");
|
|
2621
|
+
const content = JSON.stringify(pkg2, null, 2) + "\n";
|
|
2622
|
+
fs8.writeFileSync(pkgPath, content, "utf-8");
|
|
2623
|
+
}
|
|
2624
|
+
function removeUpgradeScript(pkg2) {
|
|
2625
|
+
if (!pkg2.scripts?.upgrade) {
|
|
2626
|
+
return false;
|
|
2627
|
+
}
|
|
2628
|
+
delete pkg2.scripts.upgrade;
|
|
2629
|
+
return true;
|
|
2630
|
+
}
|
|
2631
|
+
function cleanDevScript(pkg2) {
|
|
2632
|
+
if (!pkg2.scripts?.dev) {
|
|
2633
|
+
return false;
|
|
2634
|
+
}
|
|
2635
|
+
const originalDev = pkg2.scripts.dev;
|
|
2636
|
+
const cleanedDev = originalDev.replace(/npm\s+run\s+upgrade\s*&&\s*/g, "").replace(/npm\s+run\s+upgrade\s*$/g, "").trim();
|
|
2637
|
+
if (cleanedDev !== originalDev) {
|
|
2638
|
+
pkg2.scripts.dev = cleanedDev;
|
|
2639
|
+
return true;
|
|
2640
|
+
}
|
|
2641
|
+
return false;
|
|
2642
|
+
}
|
|
2643
|
+
function cleanupPackageJson(cwd = process.cwd()) {
|
|
2644
|
+
try {
|
|
2645
|
+
const pkg2 = readPackageJson(cwd);
|
|
2646
|
+
let changed = false;
|
|
2647
|
+
if (removeUpgradeScript(pkg2)) {
|
|
2648
|
+
console.log("[fullstack-cli] \u2713 Removed scripts.upgrade");
|
|
2649
|
+
changed = true;
|
|
2650
|
+
}
|
|
2651
|
+
if (cleanDevScript(pkg2)) {
|
|
2652
|
+
console.log("[fullstack-cli] \u2713 Cleaned scripts.dev (removed npm run upgrade)");
|
|
2653
|
+
changed = true;
|
|
2654
|
+
}
|
|
2655
|
+
if (changed) {
|
|
2656
|
+
writePackageJson(pkg2, cwd);
|
|
2657
|
+
}
|
|
2658
|
+
return changed;
|
|
2659
|
+
} catch (error) {
|
|
2660
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2661
|
+
console.log(`[fullstack-cli] \u26A0 Could not cleanup package.json: ${message}`);
|
|
2662
|
+
return false;
|
|
2663
|
+
}
|
|
2664
|
+
}
|
|
2665
|
+
|
|
2666
|
+
// src/commands/upgrade/shared/utils.ts
|
|
2667
|
+
import path7 from "path";
|
|
2668
|
+
import fs9 from "fs";
|
|
2669
|
+
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
2670
|
+
function getCliVersion() {
|
|
2671
|
+
try {
|
|
2672
|
+
const __filename = fileURLToPath4(import.meta.url);
|
|
2673
|
+
const __dirname2 = path7.dirname(__filename);
|
|
2674
|
+
const pkgPath = path7.resolve(__dirname2, "../../../package.json");
|
|
2675
|
+
const pkgContent = fs9.readFileSync(pkgPath, "utf-8");
|
|
2676
|
+
const pkg2 = JSON.parse(pkgContent);
|
|
2677
|
+
return pkg2.version || "unknown";
|
|
2678
|
+
} catch {
|
|
2679
|
+
return "unknown";
|
|
2680
|
+
}
|
|
2681
|
+
}
|
|
2682
|
+
|
|
2683
|
+
// src/commands/upgrade/get-upgrade-files.ts
|
|
2684
|
+
function getUpgradeFilesToStage(disableGenOpenapi = true) {
|
|
2685
|
+
const syncConfig2 = genSyncConfig({ disableGenOpenapi });
|
|
2686
|
+
const filesToStage = /* @__PURE__ */ new Set();
|
|
2687
|
+
syncConfig2.sync.forEach((rule) => {
|
|
2688
|
+
if (rule.type === "file" || rule.type === "directory") {
|
|
2689
|
+
filesToStage.add(rule.to);
|
|
2690
|
+
} else if (rule.type === "remove-line" || rule.type === "add-line") {
|
|
2691
|
+
filesToStage.add(rule.to);
|
|
2692
|
+
} else if (rule.type === "add-script") {
|
|
2693
|
+
filesToStage.add("package.json");
|
|
2694
|
+
} else if (rule.type === "delete-file" || rule.type === "delete-directory") {
|
|
2695
|
+
filesToStage.add(rule.to);
|
|
2696
|
+
}
|
|
2697
|
+
});
|
|
2698
|
+
filesToStage.add("package.json");
|
|
2699
|
+
filesToStage.add("package-lock.json");
|
|
2700
|
+
return Array.from(filesToStage);
|
|
2701
|
+
}
|
|
2702
|
+
|
|
2703
|
+
// src/commands/upgrade/run.handler.ts
|
|
2704
|
+
async function run3(options = {}) {
|
|
2705
|
+
const userProjectRoot = process.env.INIT_CWD || process.cwd();
|
|
2706
|
+
console.log("[fullstack-cli] Starting upgrade...");
|
|
2707
|
+
try {
|
|
2708
|
+
console.log("[fullstack-cli] Step 1/3: Syncing template files...");
|
|
2709
|
+
await run2({ disableGenOpenapi: options.disableGenOpenapi ?? true });
|
|
2710
|
+
console.log("[fullstack-cli] Step 2/3: Cleaning up package.json...");
|
|
2711
|
+
const cleaned = cleanupPackageJson(userProjectRoot);
|
|
2712
|
+
if (!cleaned) {
|
|
2713
|
+
console.log("[fullstack-cli] \u25CB No cleanup needed");
|
|
2714
|
+
}
|
|
2715
|
+
const shouldCommit = options.commit ?? true;
|
|
2716
|
+
if (shouldCommit) {
|
|
2717
|
+
console.log("[fullstack-cli] Step 3/3: Committing changes...");
|
|
2718
|
+
const version = getCliVersion();
|
|
2719
|
+
const filesToStage = getUpgradeFilesToStage(options.disableGenOpenapi ?? true);
|
|
2720
|
+
autoCommitUpgradeChanges(version, userProjectRoot, filesToStage);
|
|
2721
|
+
} else {
|
|
2722
|
+
console.log("[fullstack-cli] Step 3/3: Skipping commit (--no-commit flag)");
|
|
2723
|
+
}
|
|
2724
|
+
console.log("[fullstack-cli] Upgrade completed successfully \u2705");
|
|
2725
|
+
} catch (error) {
|
|
2726
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2727
|
+
console.error("[fullstack-cli] Failed to upgrade:", message);
|
|
2728
|
+
process.exit(1);
|
|
2729
|
+
}
|
|
2730
|
+
}
|
|
2731
|
+
|
|
2732
|
+
// src/commands/upgrade/deps/run.handler.ts
|
|
2733
|
+
import { spawnSync as spawnSync3 } from "child_process";
|
|
2734
|
+
function findLarkAapaasPackages(cwd, filterPackages) {
|
|
2735
|
+
const pkg2 = readPackageJson(cwd);
|
|
2736
|
+
const allPackages = /* @__PURE__ */ new Set();
|
|
2737
|
+
if (pkg2.dependencies) {
|
|
2738
|
+
Object.keys(pkg2.dependencies).forEach((name) => {
|
|
2739
|
+
if (name.startsWith("@lark-apaas/")) {
|
|
2740
|
+
allPackages.add(name);
|
|
2741
|
+
}
|
|
2742
|
+
});
|
|
2743
|
+
}
|
|
2744
|
+
if (pkg2.devDependencies) {
|
|
2745
|
+
Object.keys(pkg2.devDependencies).forEach((name) => {
|
|
2746
|
+
if (name.startsWith("@lark-apaas/")) {
|
|
2747
|
+
allPackages.add(name);
|
|
2748
|
+
}
|
|
2749
|
+
});
|
|
2750
|
+
}
|
|
2751
|
+
const packages = Array.from(allPackages);
|
|
2752
|
+
if (filterPackages) {
|
|
2753
|
+
const filter = new Set(filterPackages.split(",").map((p) => p.trim()));
|
|
2754
|
+
return packages.filter((p) => filter.has(p));
|
|
2755
|
+
}
|
|
2756
|
+
return packages;
|
|
2757
|
+
}
|
|
2758
|
+
function upgradePackages(packages, version, cwd) {
|
|
2759
|
+
if (version) {
|
|
2760
|
+
console.log(`[fullstack-cli] Upgrading to version ${version}...`);
|
|
2761
|
+
packages.forEach((pkg2) => {
|
|
2762
|
+
const target = `${pkg2}@${version}`;
|
|
2763
|
+
console.log(`[fullstack-cli] Installing ${target}...`);
|
|
2764
|
+
const result = spawnSync3("npm", ["install", target], {
|
|
2765
|
+
cwd,
|
|
2766
|
+
stdio: "inherit"
|
|
2767
|
+
});
|
|
2768
|
+
if (result.error || result.status !== 0) {
|
|
2769
|
+
throw new Error(`Failed to install ${target}`);
|
|
2770
|
+
}
|
|
2771
|
+
});
|
|
2772
|
+
} else {
|
|
2773
|
+
console.log("[fullstack-cli] Upgrading to latest compatible versions...");
|
|
2774
|
+
packages.forEach((pkg2) => {
|
|
2775
|
+
console.log(`[fullstack-cli] Updating ${pkg2}...`);
|
|
2776
|
+
const result = spawnSync3("npm", ["update", pkg2], {
|
|
2777
|
+
cwd,
|
|
2778
|
+
stdio: "inherit"
|
|
2779
|
+
});
|
|
2780
|
+
if (result.error || result.status !== 0) {
|
|
2781
|
+
throw new Error(`Failed to update ${pkg2}`);
|
|
2782
|
+
}
|
|
2783
|
+
});
|
|
2784
|
+
}
|
|
2785
|
+
}
|
|
2786
|
+
async function run4(options = {}) {
|
|
2787
|
+
const cwd = process.env.INIT_CWD || process.cwd();
|
|
2788
|
+
console.log("[fullstack-cli] Starting dependencies upgrade...");
|
|
2789
|
+
try {
|
|
2790
|
+
console.log("[fullstack-cli] Step 1/2: Scanning @lark-apaas dependencies...");
|
|
2791
|
+
const packages = findLarkAapaasPackages(cwd, options.packages);
|
|
2792
|
+
if (packages.length === 0) {
|
|
2793
|
+
console.log("[fullstack-cli] No @lark-apaas packages found");
|
|
2794
|
+
return;
|
|
2795
|
+
}
|
|
2796
|
+
console.log(`[fullstack-cli] Found ${packages.length} @lark-apaas package(s):`);
|
|
2797
|
+
packages.forEach((p) => console.log(` - ${p}`));
|
|
2798
|
+
console.log("[fullstack-cli] Step 2/2: Upgrading packages...");
|
|
2799
|
+
upgradePackages(packages, options.version, cwd);
|
|
2800
|
+
console.log(`[fullstack-cli] \u2713 Successfully upgraded ${packages.length} package(s)`);
|
|
2801
|
+
console.log("[fullstack-cli] Dependencies upgrade completed successfully \u2705");
|
|
2802
|
+
} catch (error) {
|
|
2803
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2804
|
+
console.error("[fullstack-cli] Failed to upgrade dependencies:", message);
|
|
2805
|
+
process.exit(1);
|
|
2806
|
+
}
|
|
2807
|
+
}
|
|
2808
|
+
|
|
2809
|
+
// src/commands/upgrade/deps/index.ts
|
|
2810
|
+
var depsCommand = {
|
|
2811
|
+
name: "deps",
|
|
2812
|
+
description: "Upgrade @lark-apaas dependencies",
|
|
2813
|
+
register(parentCommand) {
|
|
2814
|
+
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) => {
|
|
2815
|
+
await run4(options);
|
|
2816
|
+
});
|
|
2817
|
+
}
|
|
2818
|
+
};
|
|
2819
|
+
|
|
2820
|
+
// src/commands/upgrade/index.ts
|
|
2821
|
+
var upgradeCommand = {
|
|
2822
|
+
name: "upgrade",
|
|
2823
|
+
description: "Upgrade template files and auto-commit changes",
|
|
2824
|
+
register(program) {
|
|
2825
|
+
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) => {
|
|
2826
|
+
await run3(options);
|
|
2827
|
+
});
|
|
2828
|
+
depsCommand.register(upgradeCmd);
|
|
2829
|
+
}
|
|
2830
|
+
};
|
|
2831
|
+
|
|
2832
|
+
// src/commands/action-plugin/utils.ts
|
|
2833
|
+
import fs10 from "fs";
|
|
2834
|
+
import path8 from "path";
|
|
2835
|
+
import { spawnSync as spawnSync4, execSync as execSync2 } from "child_process";
|
|
2415
2836
|
function parsePluginName(input) {
|
|
2416
2837
|
const match = input.match(/^(@[^/]+\/[^@]+)(?:@(.+))?$/);
|
|
2417
2838
|
if (!match) {
|
|
@@ -2428,35 +2849,35 @@ function getProjectRoot() {
|
|
|
2428
2849
|
return process.cwd();
|
|
2429
2850
|
}
|
|
2430
2851
|
function getPackageJsonPath() {
|
|
2431
|
-
return
|
|
2852
|
+
return path8.join(getProjectRoot(), "package.json");
|
|
2432
2853
|
}
|
|
2433
2854
|
function getPluginPath(pluginName) {
|
|
2434
|
-
return
|
|
2855
|
+
return path8.join(getProjectRoot(), "node_modules", pluginName);
|
|
2435
2856
|
}
|
|
2436
|
-
function
|
|
2857
|
+
function readPackageJson2() {
|
|
2437
2858
|
const pkgPath = getPackageJsonPath();
|
|
2438
|
-
if (!
|
|
2859
|
+
if (!fs10.existsSync(pkgPath)) {
|
|
2439
2860
|
throw new Error("package.json not found in current directory");
|
|
2440
2861
|
}
|
|
2441
2862
|
try {
|
|
2442
|
-
const content =
|
|
2863
|
+
const content = fs10.readFileSync(pkgPath, "utf-8");
|
|
2443
2864
|
return JSON.parse(content);
|
|
2444
2865
|
} catch {
|
|
2445
2866
|
throw new Error("Failed to parse package.json");
|
|
2446
2867
|
}
|
|
2447
2868
|
}
|
|
2448
|
-
function
|
|
2869
|
+
function writePackageJson2(pkg2) {
|
|
2449
2870
|
const pkgPath = getPackageJsonPath();
|
|
2450
|
-
|
|
2871
|
+
fs10.writeFileSync(pkgPath, JSON.stringify(pkg2, null, 2) + "\n", "utf-8");
|
|
2451
2872
|
}
|
|
2452
2873
|
function readActionPlugins() {
|
|
2453
|
-
const pkg2 =
|
|
2874
|
+
const pkg2 = readPackageJson2();
|
|
2454
2875
|
return pkg2.actionPlugins || {};
|
|
2455
2876
|
}
|
|
2456
2877
|
function writeActionPlugins(plugins) {
|
|
2457
|
-
const pkg2 =
|
|
2878
|
+
const pkg2 = readPackageJson2();
|
|
2458
2879
|
pkg2.actionPlugins = plugins;
|
|
2459
|
-
|
|
2880
|
+
writePackageJson2(pkg2);
|
|
2460
2881
|
}
|
|
2461
2882
|
function isPluginInstalled(pluginName) {
|
|
2462
2883
|
const plugins = readActionPlugins();
|
|
@@ -2468,7 +2889,7 @@ function getInstalledPluginVersion(pluginName) {
|
|
|
2468
2889
|
}
|
|
2469
2890
|
function npmInstall(tgzPath) {
|
|
2470
2891
|
console.log(`[action-plugin] Running npm install ${tgzPath}...`);
|
|
2471
|
-
const result =
|
|
2892
|
+
const result = spawnSync4("npm", ["install", tgzPath, "--no-save", "--no-package-lock", "--ignore-scripts"], {
|
|
2472
2893
|
cwd: getProjectRoot(),
|
|
2473
2894
|
stdio: "inherit"
|
|
2474
2895
|
});
|
|
@@ -2480,12 +2901,12 @@ function npmInstall(tgzPath) {
|
|
|
2480
2901
|
}
|
|
2481
2902
|
}
|
|
2482
2903
|
function getPackageVersion(pluginName) {
|
|
2483
|
-
const pkgJsonPath =
|
|
2484
|
-
if (!
|
|
2904
|
+
const pkgJsonPath = path8.join(getPluginPath(pluginName), "package.json");
|
|
2905
|
+
if (!fs10.existsSync(pkgJsonPath)) {
|
|
2485
2906
|
return null;
|
|
2486
2907
|
}
|
|
2487
2908
|
try {
|
|
2488
|
-
const content =
|
|
2909
|
+
const content = fs10.readFileSync(pkgJsonPath, "utf-8");
|
|
2489
2910
|
const pkg2 = JSON.parse(content);
|
|
2490
2911
|
return pkg2.version || null;
|
|
2491
2912
|
} catch {
|
|
@@ -2493,49 +2914,49 @@ function getPackageVersion(pluginName) {
|
|
|
2493
2914
|
}
|
|
2494
2915
|
}
|
|
2495
2916
|
function readPluginPackageJson(pluginPath) {
|
|
2496
|
-
const pkgJsonPath =
|
|
2497
|
-
if (!
|
|
2917
|
+
const pkgJsonPath = path8.join(pluginPath, "package.json");
|
|
2918
|
+
if (!fs10.existsSync(pkgJsonPath)) {
|
|
2498
2919
|
return null;
|
|
2499
2920
|
}
|
|
2500
2921
|
try {
|
|
2501
|
-
const content =
|
|
2922
|
+
const content = fs10.readFileSync(pkgJsonPath, "utf-8");
|
|
2502
2923
|
return JSON.parse(content);
|
|
2503
2924
|
} catch {
|
|
2504
2925
|
return null;
|
|
2505
2926
|
}
|
|
2506
2927
|
}
|
|
2507
2928
|
function extractTgzToNodeModules(tgzPath, pluginName) {
|
|
2508
|
-
const nodeModulesPath =
|
|
2509
|
-
const targetDir =
|
|
2510
|
-
const scopeDir =
|
|
2511
|
-
if (!
|
|
2512
|
-
|
|
2929
|
+
const nodeModulesPath = path8.join(getProjectRoot(), "node_modules");
|
|
2930
|
+
const targetDir = path8.join(nodeModulesPath, pluginName);
|
|
2931
|
+
const scopeDir = path8.dirname(targetDir);
|
|
2932
|
+
if (!fs10.existsSync(scopeDir)) {
|
|
2933
|
+
fs10.mkdirSync(scopeDir, { recursive: true });
|
|
2513
2934
|
}
|
|
2514
|
-
if (
|
|
2515
|
-
|
|
2935
|
+
if (fs10.existsSync(targetDir)) {
|
|
2936
|
+
fs10.rmSync(targetDir, { recursive: true });
|
|
2516
2937
|
}
|
|
2517
|
-
const tempDir =
|
|
2518
|
-
if (
|
|
2519
|
-
|
|
2938
|
+
const tempDir = path8.join(nodeModulesPath, ".cache", "fullstack-cli", "extract-temp");
|
|
2939
|
+
if (fs10.existsSync(tempDir)) {
|
|
2940
|
+
fs10.rmSync(tempDir, { recursive: true });
|
|
2520
2941
|
}
|
|
2521
|
-
|
|
2942
|
+
fs10.mkdirSync(tempDir, { recursive: true });
|
|
2522
2943
|
try {
|
|
2523
|
-
|
|
2524
|
-
const extractedDir =
|
|
2525
|
-
if (
|
|
2526
|
-
|
|
2944
|
+
execSync2(`tar -xzf "${tgzPath}" -C "${tempDir}"`, { stdio: "pipe" });
|
|
2945
|
+
const extractedDir = path8.join(tempDir, "package");
|
|
2946
|
+
if (fs10.existsSync(extractedDir)) {
|
|
2947
|
+
fs10.renameSync(extractedDir, targetDir);
|
|
2527
2948
|
} else {
|
|
2528
|
-
const files =
|
|
2949
|
+
const files = fs10.readdirSync(tempDir);
|
|
2529
2950
|
if (files.length === 1) {
|
|
2530
|
-
|
|
2951
|
+
fs10.renameSync(path8.join(tempDir, files[0]), targetDir);
|
|
2531
2952
|
} else {
|
|
2532
2953
|
throw new Error("Unexpected tgz structure");
|
|
2533
2954
|
}
|
|
2534
2955
|
}
|
|
2535
2956
|
return targetDir;
|
|
2536
2957
|
} finally {
|
|
2537
|
-
if (
|
|
2538
|
-
|
|
2958
|
+
if (fs10.existsSync(tempDir)) {
|
|
2959
|
+
fs10.rmSync(tempDir, { recursive: true });
|
|
2539
2960
|
}
|
|
2540
2961
|
}
|
|
2541
2962
|
}
|
|
@@ -2544,10 +2965,10 @@ function checkMissingPeerDeps(peerDeps) {
|
|
|
2544
2965
|
return [];
|
|
2545
2966
|
}
|
|
2546
2967
|
const missing = [];
|
|
2547
|
-
const nodeModulesPath =
|
|
2968
|
+
const nodeModulesPath = path8.join(getProjectRoot(), "node_modules");
|
|
2548
2969
|
for (const [depName, _version] of Object.entries(peerDeps)) {
|
|
2549
|
-
const depPath =
|
|
2550
|
-
if (!
|
|
2970
|
+
const depPath = path8.join(nodeModulesPath, depName);
|
|
2971
|
+
if (!fs10.existsSync(depPath)) {
|
|
2551
2972
|
missing.push(depName);
|
|
2552
2973
|
}
|
|
2553
2974
|
}
|
|
@@ -2558,7 +2979,7 @@ function installMissingDeps(deps) {
|
|
|
2558
2979
|
return;
|
|
2559
2980
|
}
|
|
2560
2981
|
console.log(`[action-plugin] Installing missing dependencies: ${deps.join(", ")}`);
|
|
2561
|
-
const result =
|
|
2982
|
+
const result = spawnSync4("npm", ["install", ...deps, "--no-save", "--no-package-lock"], {
|
|
2562
2983
|
cwd: getProjectRoot(),
|
|
2563
2984
|
stdio: "inherit"
|
|
2564
2985
|
});
|
|
@@ -2571,40 +2992,16 @@ function installMissingDeps(deps) {
|
|
|
2571
2992
|
}
|
|
2572
2993
|
function removePluginDirectory(pluginName) {
|
|
2573
2994
|
const pluginPath = getPluginPath(pluginName);
|
|
2574
|
-
if (
|
|
2575
|
-
|
|
2995
|
+
if (fs10.existsSync(pluginPath)) {
|
|
2996
|
+
fs10.rmSync(pluginPath, { recursive: true });
|
|
2576
2997
|
console.log(`[action-plugin] Removed ${pluginName}`);
|
|
2577
2998
|
}
|
|
2578
2999
|
}
|
|
2579
3000
|
|
|
2580
3001
|
// src/commands/action-plugin/api-client.ts
|
|
2581
3002
|
import { HttpClient as HttpClient2 } from "@lark-apaas/http-client";
|
|
2582
|
-
import
|
|
2583
|
-
import
|
|
2584
|
-
|
|
2585
|
-
// src/utils/http-client.ts
|
|
2586
|
-
import { HttpClient } from "@lark-apaas/http-client";
|
|
2587
|
-
var clientInstance = null;
|
|
2588
|
-
function getHttpClient() {
|
|
2589
|
-
if (!clientInstance) {
|
|
2590
|
-
clientInstance = new HttpClient({
|
|
2591
|
-
timeout: 3e4,
|
|
2592
|
-
platform: {
|
|
2593
|
-
enabled: true
|
|
2594
|
-
}
|
|
2595
|
-
});
|
|
2596
|
-
const canaryEnv = process.env.FORCE_FRAMEWORK_CLI_CANARY_ENV;
|
|
2597
|
-
if (canaryEnv) {
|
|
2598
|
-
clientInstance.interceptors.request.use((req) => {
|
|
2599
|
-
req.headers["x-tt-env"] = canaryEnv;
|
|
2600
|
-
return req;
|
|
2601
|
-
});
|
|
2602
|
-
}
|
|
2603
|
-
}
|
|
2604
|
-
return clientInstance;
|
|
2605
|
-
}
|
|
2606
|
-
|
|
2607
|
-
// src/commands/action-plugin/api-client.ts
|
|
3003
|
+
import fs11 from "fs";
|
|
3004
|
+
import path9 from "path";
|
|
2608
3005
|
var PLUGIN_CACHE_DIR = "node_modules/.cache/fullstack-cli/plugins";
|
|
2609
3006
|
async function getPluginVersions(keys, latestOnly = true) {
|
|
2610
3007
|
const client = getHttpClient();
|
|
@@ -2668,19 +3065,19 @@ async function downloadFromPublic(downloadURL) {
|
|
|
2668
3065
|
return Buffer.from(arrayBuffer);
|
|
2669
3066
|
}
|
|
2670
3067
|
function getPluginCacheDir() {
|
|
2671
|
-
return
|
|
3068
|
+
return path9.join(process.cwd(), PLUGIN_CACHE_DIR);
|
|
2672
3069
|
}
|
|
2673
3070
|
function ensureCacheDir() {
|
|
2674
3071
|
const cacheDir = getPluginCacheDir();
|
|
2675
|
-
if (!
|
|
2676
|
-
|
|
3072
|
+
if (!fs11.existsSync(cacheDir)) {
|
|
3073
|
+
fs11.mkdirSync(cacheDir, { recursive: true });
|
|
2677
3074
|
}
|
|
2678
3075
|
}
|
|
2679
3076
|
function getTempFilePath(pluginKey, version) {
|
|
2680
3077
|
ensureCacheDir();
|
|
2681
3078
|
const safeKey = pluginKey.replace(/[/@]/g, "_");
|
|
2682
3079
|
const filename = `${safeKey}@${version}.tgz`;
|
|
2683
|
-
return
|
|
3080
|
+
return path9.join(getPluginCacheDir(), filename);
|
|
2684
3081
|
}
|
|
2685
3082
|
var MAX_RETRIES = 2;
|
|
2686
3083
|
async function withRetry(operation, description, maxRetries = MAX_RETRIES) {
|
|
@@ -2717,7 +3114,7 @@ async function downloadPlugin(pluginKey, requestedVersion) {
|
|
|
2717
3114
|
);
|
|
2718
3115
|
}
|
|
2719
3116
|
const tgzPath = getTempFilePath(pluginKey, pluginInfo.version);
|
|
2720
|
-
|
|
3117
|
+
fs11.writeFileSync(tgzPath, tgzBuffer);
|
|
2721
3118
|
console.log(`[action-plugin] Downloaded to ${tgzPath} (${(tgzBuffer.length / 1024).toFixed(2)} KB)`);
|
|
2722
3119
|
return {
|
|
2723
3120
|
tgzPath,
|
|
@@ -2731,18 +3128,18 @@ function getCachePath(pluginKey, version) {
|
|
|
2731
3128
|
ensureCacheDir();
|
|
2732
3129
|
const safeKey = pluginKey.replace(/[/@]/g, "_");
|
|
2733
3130
|
const filename = `${safeKey}@${version}.tgz`;
|
|
2734
|
-
return
|
|
3131
|
+
return path9.join(getPluginCacheDir(), filename);
|
|
2735
3132
|
}
|
|
2736
3133
|
function hasCachedPlugin(pluginKey, version) {
|
|
2737
3134
|
const cachePath = getCachePath(pluginKey, version);
|
|
2738
|
-
return
|
|
3135
|
+
return fs11.existsSync(cachePath);
|
|
2739
3136
|
}
|
|
2740
3137
|
function listCachedPlugins() {
|
|
2741
3138
|
const cacheDir = getPluginCacheDir();
|
|
2742
|
-
if (!
|
|
3139
|
+
if (!fs11.existsSync(cacheDir)) {
|
|
2743
3140
|
return [];
|
|
2744
3141
|
}
|
|
2745
|
-
const files =
|
|
3142
|
+
const files = fs11.readdirSync(cacheDir);
|
|
2746
3143
|
const result = [];
|
|
2747
3144
|
for (const file of files) {
|
|
2748
3145
|
if (!file.endsWith(".tgz")) continue;
|
|
@@ -2750,8 +3147,8 @@ function listCachedPlugins() {
|
|
|
2750
3147
|
if (!match) continue;
|
|
2751
3148
|
const [, rawName, version] = match;
|
|
2752
3149
|
const name = rawName.replace(/^_/, "@").replace(/_/, "/");
|
|
2753
|
-
const filePath =
|
|
2754
|
-
const stat =
|
|
3150
|
+
const filePath = path9.join(cacheDir, file);
|
|
3151
|
+
const stat = fs11.statSync(filePath);
|
|
2755
3152
|
result.push({
|
|
2756
3153
|
name,
|
|
2757
3154
|
version,
|
|
@@ -2764,14 +3161,14 @@ function listCachedPlugins() {
|
|
|
2764
3161
|
}
|
|
2765
3162
|
function cleanAllCache() {
|
|
2766
3163
|
const cacheDir = getPluginCacheDir();
|
|
2767
|
-
if (!
|
|
3164
|
+
if (!fs11.existsSync(cacheDir)) {
|
|
2768
3165
|
return 0;
|
|
2769
3166
|
}
|
|
2770
|
-
const files =
|
|
3167
|
+
const files = fs11.readdirSync(cacheDir);
|
|
2771
3168
|
let count = 0;
|
|
2772
3169
|
for (const file of files) {
|
|
2773
3170
|
if (file.endsWith(".tgz")) {
|
|
2774
|
-
|
|
3171
|
+
fs11.unlinkSync(path9.join(cacheDir, file));
|
|
2775
3172
|
count++;
|
|
2776
3173
|
}
|
|
2777
3174
|
}
|
|
@@ -2779,21 +3176,21 @@ function cleanAllCache() {
|
|
|
2779
3176
|
}
|
|
2780
3177
|
function cleanPluginCache(pluginKey, version) {
|
|
2781
3178
|
const cacheDir = getPluginCacheDir();
|
|
2782
|
-
if (!
|
|
3179
|
+
if (!fs11.existsSync(cacheDir)) {
|
|
2783
3180
|
return 0;
|
|
2784
3181
|
}
|
|
2785
3182
|
const safeKey = pluginKey.replace(/[/@]/g, "_");
|
|
2786
|
-
const files =
|
|
3183
|
+
const files = fs11.readdirSync(cacheDir);
|
|
2787
3184
|
let count = 0;
|
|
2788
3185
|
for (const file of files) {
|
|
2789
3186
|
if (version) {
|
|
2790
3187
|
if (file === `${safeKey}@${version}.tgz`) {
|
|
2791
|
-
|
|
3188
|
+
fs11.unlinkSync(path9.join(cacheDir, file));
|
|
2792
3189
|
count++;
|
|
2793
3190
|
}
|
|
2794
3191
|
} else {
|
|
2795
3192
|
if (file.startsWith(`${safeKey}@`) && file.endsWith(".tgz")) {
|
|
2796
|
-
|
|
3193
|
+
fs11.unlinkSync(path9.join(cacheDir, file));
|
|
2797
3194
|
count++;
|
|
2798
3195
|
}
|
|
2799
3196
|
}
|
|
@@ -2887,6 +3284,8 @@ async function installOne(nameWithVersion) {
|
|
|
2887
3284
|
if (actualVersion === requestedVersion) {
|
|
2888
3285
|
console.log(`[action-plugin] Plugin ${name}@${requestedVersion} is already installed`);
|
|
2889
3286
|
syncActionPluginsRecord(name, actualVersion);
|
|
3287
|
+
reportCreateInstanceEvent(name, actualVersion).catch(() => {
|
|
3288
|
+
});
|
|
2890
3289
|
return { name, version: actualVersion, success: true, skipped: true };
|
|
2891
3290
|
}
|
|
2892
3291
|
}
|
|
@@ -2897,6 +3296,8 @@ async function installOne(nameWithVersion) {
|
|
|
2897
3296
|
if (actualVersion === targetVersion) {
|
|
2898
3297
|
console.log(`[action-plugin] Plugin ${name} is already up to date (version: ${actualVersion})`);
|
|
2899
3298
|
syncActionPluginsRecord(name, actualVersion);
|
|
3299
|
+
reportCreateInstanceEvent(name, actualVersion).catch(() => {
|
|
3300
|
+
});
|
|
2900
3301
|
return { name, version: actualVersion, success: true, skipped: true };
|
|
2901
3302
|
}
|
|
2902
3303
|
console.log(`[action-plugin] Found newer version: ${targetVersion} (installed: ${actualVersion || "none"})`);
|
|
@@ -2927,6 +3328,10 @@ async function installOne(nameWithVersion) {
|
|
|
2927
3328
|
writeActionPlugins(plugins);
|
|
2928
3329
|
const source = fromCache ? "from cache" : "downloaded";
|
|
2929
3330
|
console.log(`[action-plugin] Successfully installed ${name}@${installedVersion} (${source})`);
|
|
3331
|
+
reportInstallEvent(name, installedVersion).catch(() => {
|
|
3332
|
+
});
|
|
3333
|
+
reportCreateInstanceEvent(name, installedVersion).catch(() => {
|
|
3334
|
+
});
|
|
2930
3335
|
return { name, version: installedVersion, success: true };
|
|
2931
3336
|
} catch (error) {
|
|
2932
3337
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -3212,40 +3617,40 @@ var actionPluginCommandGroup = {
|
|
|
3212
3617
|
};
|
|
3213
3618
|
|
|
3214
3619
|
// src/commands/capability/utils.ts
|
|
3215
|
-
import
|
|
3620
|
+
import fs12 from "fs";
|
|
3216
3621
|
import { createRequire as createRequire2 } from "module";
|
|
3217
|
-
import
|
|
3622
|
+
import path10 from "path";
|
|
3218
3623
|
var CAPABILITIES_DIR = "server/capabilities";
|
|
3219
3624
|
function getProjectRoot2() {
|
|
3220
3625
|
return process.cwd();
|
|
3221
3626
|
}
|
|
3222
3627
|
function getCapabilitiesDir() {
|
|
3223
|
-
return
|
|
3628
|
+
return path10.join(getProjectRoot2(), CAPABILITIES_DIR);
|
|
3224
3629
|
}
|
|
3225
3630
|
function getCapabilityPath(id) {
|
|
3226
|
-
return
|
|
3631
|
+
return path10.join(getCapabilitiesDir(), `${id}.json`);
|
|
3227
3632
|
}
|
|
3228
3633
|
function getPluginManifestPath(pluginKey) {
|
|
3229
|
-
return
|
|
3634
|
+
return path10.join(getProjectRoot2(), "node_modules", pluginKey, "manifest.json");
|
|
3230
3635
|
}
|
|
3231
3636
|
function capabilitiesDirExists() {
|
|
3232
|
-
return
|
|
3637
|
+
return fs12.existsSync(getCapabilitiesDir());
|
|
3233
3638
|
}
|
|
3234
3639
|
function listCapabilityIds() {
|
|
3235
3640
|
const dir = getCapabilitiesDir();
|
|
3236
|
-
if (!
|
|
3641
|
+
if (!fs12.existsSync(dir)) {
|
|
3237
3642
|
return [];
|
|
3238
3643
|
}
|
|
3239
|
-
const files =
|
|
3644
|
+
const files = fs12.readdirSync(dir);
|
|
3240
3645
|
return files.filter((f) => f.endsWith(".json") && f !== "capabilities.json").map((f) => f.replace(/\.json$/, ""));
|
|
3241
3646
|
}
|
|
3242
3647
|
function readCapability(id) {
|
|
3243
3648
|
const filePath = getCapabilityPath(id);
|
|
3244
|
-
if (!
|
|
3649
|
+
if (!fs12.existsSync(filePath)) {
|
|
3245
3650
|
throw new Error(`Capability not found: ${id}`);
|
|
3246
3651
|
}
|
|
3247
3652
|
try {
|
|
3248
|
-
const content =
|
|
3653
|
+
const content = fs12.readFileSync(filePath, "utf-8");
|
|
3249
3654
|
return JSON.parse(content);
|
|
3250
3655
|
} catch (error) {
|
|
3251
3656
|
if (error instanceof SyntaxError) {
|
|
@@ -3272,11 +3677,11 @@ function readAllCapabilities() {
|
|
|
3272
3677
|
}
|
|
3273
3678
|
function readPluginManifest(pluginKey) {
|
|
3274
3679
|
const manifestPath = getPluginManifestPath(pluginKey);
|
|
3275
|
-
if (!
|
|
3680
|
+
if (!fs12.existsSync(manifestPath)) {
|
|
3276
3681
|
throw new Error(`Plugin not installed: ${pluginKey} (manifest.json not found)`);
|
|
3277
3682
|
}
|
|
3278
3683
|
try {
|
|
3279
|
-
const content =
|
|
3684
|
+
const content = fs12.readFileSync(manifestPath, "utf-8");
|
|
3280
3685
|
return JSON.parse(content);
|
|
3281
3686
|
} catch (error) {
|
|
3282
3687
|
if (error instanceof SyntaxError) {
|
|
@@ -3293,7 +3698,7 @@ function hasValidParamsSchema(paramsSchema) {
|
|
|
3293
3698
|
}
|
|
3294
3699
|
async function loadPlugin(pluginKey) {
|
|
3295
3700
|
try {
|
|
3296
|
-
const userRequire = createRequire2(
|
|
3701
|
+
const userRequire = createRequire2(path10.join(getProjectRoot2(), "package.json"));
|
|
3297
3702
|
const resolvedPath = userRequire.resolve(pluginKey);
|
|
3298
3703
|
const pluginModule = await import(resolvedPath);
|
|
3299
3704
|
const pluginPackage = pluginModule.default ?? pluginModule;
|
|
@@ -3452,59 +3857,358 @@ var capabilityCommandGroup = {
|
|
|
3452
3857
|
commands: [listCommand2]
|
|
3453
3858
|
};
|
|
3454
3859
|
|
|
3860
|
+
// src/commands/component/add.handler.ts
|
|
3861
|
+
import { execFile } from "child_process";
|
|
3862
|
+
|
|
3863
|
+
// src/commands/component/registry-preparer.ts
|
|
3864
|
+
import fs13 from "fs";
|
|
3865
|
+
import path11 from "path";
|
|
3866
|
+
import os from "os";
|
|
3867
|
+
|
|
3868
|
+
// src/commands/component/service.ts
|
|
3869
|
+
import { mapValues } from "es-toolkit";
|
|
3870
|
+
|
|
3871
|
+
// src/commands/component/utils.ts
|
|
3872
|
+
import createDebug from "debug";
|
|
3873
|
+
var debug = createDebug("component");
|
|
3874
|
+
|
|
3875
|
+
// src/commands/component/service.ts
|
|
3876
|
+
async function getComponents(keys) {
|
|
3877
|
+
const client = getHttpClient();
|
|
3878
|
+
debug("\u8C03\u7528 /components/batch_get %o", keys);
|
|
3879
|
+
const response = await client.post(
|
|
3880
|
+
`/api/v1/studio/innerapi/components/batch_get?keys=${keys.join(",")}`
|
|
3881
|
+
);
|
|
3882
|
+
if (response.status !== 200) {
|
|
3883
|
+
throw new Error(
|
|
3884
|
+
`\u83B7\u53D6\u7EC4\u4EF6\u4FE1\u606F\u5931\u8D25\uFF1A${response.status} ${response.statusText}`
|
|
3885
|
+
);
|
|
3886
|
+
}
|
|
3887
|
+
const result = await response.json();
|
|
3888
|
+
if (result.status_code !== "0") {
|
|
3889
|
+
debug("\u63A5\u53E3\u8FD4\u56DE\u9519\u8BEF\uFF1A%o", result);
|
|
3890
|
+
throw new Error(`\u83B7\u53D6\u7EC4\u4EF6\u4FE1\u606F\u5931\u8D25\uFF1A${result.error_msg}`);
|
|
3891
|
+
}
|
|
3892
|
+
return mapValues(result.data.components, ([component]) => component);
|
|
3893
|
+
}
|
|
3894
|
+
async function getRegistryItem(url) {
|
|
3895
|
+
const client = getHttpClient();
|
|
3896
|
+
debug("\u4E0B\u8F7D registry-item.json\uFF1A%s", url);
|
|
3897
|
+
const response = await client.get(url);
|
|
3898
|
+
if (!response.ok) {
|
|
3899
|
+
throw new Error(
|
|
3900
|
+
`\u4E0B\u8F7D registry-item.json \u5931\u8D25\uFF1A${response.status} ${response.statusText}`
|
|
3901
|
+
);
|
|
3902
|
+
}
|
|
3903
|
+
const item = await response.json();
|
|
3904
|
+
return item;
|
|
3905
|
+
}
|
|
3906
|
+
async function sendInstallEvent(key) {
|
|
3907
|
+
const client = getHttpClient();
|
|
3908
|
+
await client.post("/api/v1/studio/innerapi/resource_events", {
|
|
3909
|
+
events: [
|
|
3910
|
+
{
|
|
3911
|
+
resourceType: "component",
|
|
3912
|
+
resourceKey: key,
|
|
3913
|
+
eventType: "install",
|
|
3914
|
+
details: {}
|
|
3915
|
+
}
|
|
3916
|
+
]
|
|
3917
|
+
});
|
|
3918
|
+
}
|
|
3919
|
+
|
|
3920
|
+
// src/commands/component/registry-preparer.ts
|
|
3921
|
+
var REGISTRY_TEMP_DIR = path11.join(os.tmpdir(), "miaoda-registry");
|
|
3922
|
+
function parseComponentKey(key) {
|
|
3923
|
+
const match = key.match(/^@([^/]+)\/(.+)$/);
|
|
3924
|
+
if (!match) {
|
|
3925
|
+
throw new Error(
|
|
3926
|
+
`Invalid component key format: ${key}. Expected format: @scope/name`
|
|
3927
|
+
);
|
|
3928
|
+
}
|
|
3929
|
+
return { scope: match[1], name: match[2] };
|
|
3930
|
+
}
|
|
3931
|
+
function getLocalRegistryPath(key) {
|
|
3932
|
+
const { scope, name } = parseComponentKey(key);
|
|
3933
|
+
return path11.join(REGISTRY_TEMP_DIR, scope, `${name}.json`);
|
|
3934
|
+
}
|
|
3935
|
+
function ensureDir(dirPath) {
|
|
3936
|
+
if (!fs13.existsSync(dirPath)) {
|
|
3937
|
+
fs13.mkdirSync(dirPath, { recursive: true });
|
|
3938
|
+
}
|
|
3939
|
+
}
|
|
3940
|
+
async function prepareRecursive(key, visited) {
|
|
3941
|
+
if (visited.has(key)) {
|
|
3942
|
+
debug("\u8DF3\u8FC7\u5DF2\u5904\u7406\u7684\u7EC4\u4EF6: %s", key);
|
|
3943
|
+
return;
|
|
3944
|
+
}
|
|
3945
|
+
visited.add(key);
|
|
3946
|
+
debug("\u5904\u7406\u7EC4\u4EF6: %s", key);
|
|
3947
|
+
debug("\u83B7\u53D6\u7EC4\u4EF6\u4E0B\u8F7D\u4FE1\u606F...");
|
|
3948
|
+
const infoMap = await getComponents([key]);
|
|
3949
|
+
const info = infoMap[key];
|
|
3950
|
+
debug("\u7EC4\u4EF6\u4FE1\u606F: %o", info);
|
|
3951
|
+
if (!info) {
|
|
3952
|
+
throw new Error(`Component not found: ${key}`);
|
|
3953
|
+
}
|
|
3954
|
+
if (info.status !== "active") {
|
|
3955
|
+
throw new Error(`Component is not active: ${key}`);
|
|
3956
|
+
}
|
|
3957
|
+
debug("\u4E0B\u8F7D registry item: %s", info.downloadURL);
|
|
3958
|
+
const registryItem = await getRegistryItem(info.downloadURL);
|
|
3959
|
+
debug("registry item \u5185\u5BB9: %o", registryItem);
|
|
3960
|
+
const deps = registryItem.registryDependencies || [];
|
|
3961
|
+
debug("\u4F9D\u8D56\u5217\u8868: %o", deps);
|
|
3962
|
+
for (const dep of deps) {
|
|
3963
|
+
await prepareRecursive(dep, visited);
|
|
3964
|
+
}
|
|
3965
|
+
const rewrittenItem = {
|
|
3966
|
+
...registryItem,
|
|
3967
|
+
registryDependencies: deps.map((dep) => getLocalRegistryPath(dep))
|
|
3968
|
+
};
|
|
3969
|
+
const localPath = getLocalRegistryPath(key);
|
|
3970
|
+
ensureDir(path11.dirname(localPath));
|
|
3971
|
+
fs13.writeFileSync(localPath, JSON.stringify(rewrittenItem, null, 2), "utf-8");
|
|
3972
|
+
debug("\u4FDD\u5B58\u5230: %s", localPath);
|
|
3973
|
+
}
|
|
3974
|
+
async function prepareComponentRegistryItems(id) {
|
|
3975
|
+
const visited = /* @__PURE__ */ new Set();
|
|
3976
|
+
await prepareRecursive(id, visited);
|
|
3977
|
+
return getLocalRegistryPath(id);
|
|
3978
|
+
}
|
|
3979
|
+
function cleanupTempDir() {
|
|
3980
|
+
try {
|
|
3981
|
+
if (fs13.existsSync(REGISTRY_TEMP_DIR)) {
|
|
3982
|
+
fs13.rmSync(REGISTRY_TEMP_DIR, { recursive: true, force: true });
|
|
3983
|
+
}
|
|
3984
|
+
} catch {
|
|
3985
|
+
}
|
|
3986
|
+
}
|
|
3987
|
+
function getDownloadedRegistryItem(itemId) {
|
|
3988
|
+
const localPath = getLocalRegistryPath(itemId);
|
|
3989
|
+
if (!fs13.existsSync(localPath)) {
|
|
3990
|
+
return null;
|
|
3991
|
+
}
|
|
3992
|
+
const content = fs13.readFileSync(localPath, "utf-8");
|
|
3993
|
+
return JSON.parse(content);
|
|
3994
|
+
}
|
|
3995
|
+
|
|
3996
|
+
// src/commands/component/shadcn-executor.ts
|
|
3997
|
+
import * as pty from "@lydell/node-pty";
|
|
3998
|
+
function parseOutput(output) {
|
|
3999
|
+
const state = {
|
|
4000
|
+
currentSection: null,
|
|
4001
|
+
files: /* @__PURE__ */ new Set()
|
|
4002
|
+
};
|
|
4003
|
+
const lines = output.split("\n");
|
|
4004
|
+
for (const line of lines) {
|
|
4005
|
+
const trimmedLine = line.trim();
|
|
4006
|
+
if (/Created \d+ files?:/.test(trimmedLine)) {
|
|
4007
|
+
state.currentSection = "created";
|
|
4008
|
+
continue;
|
|
4009
|
+
}
|
|
4010
|
+
if (/Updated \d+ files?:/.test(trimmedLine)) {
|
|
4011
|
+
state.currentSection = "updated";
|
|
4012
|
+
continue;
|
|
4013
|
+
}
|
|
4014
|
+
if (/Skipped \d+ files?:/.test(trimmedLine)) {
|
|
4015
|
+
state.currentSection = "skipped";
|
|
4016
|
+
continue;
|
|
4017
|
+
}
|
|
4018
|
+
if (state.currentSection && trimmedLine.startsWith("- ")) {
|
|
4019
|
+
const filePath = trimmedLine.slice(2).trim();
|
|
4020
|
+
if (filePath && filePath.includes("/")) {
|
|
4021
|
+
state.files.add(filePath);
|
|
4022
|
+
}
|
|
4023
|
+
}
|
|
4024
|
+
if (state.currentSection && trimmedLine.length > 1 && !trimmedLine.startsWith("- ")) {
|
|
4025
|
+
state.currentSection = null;
|
|
4026
|
+
}
|
|
4027
|
+
}
|
|
4028
|
+
return Array.from(state.files);
|
|
4029
|
+
}
|
|
4030
|
+
function toFileInfo(filePath) {
|
|
4031
|
+
const name = filePath.split("/").pop() || filePath;
|
|
4032
|
+
return { name, path: filePath };
|
|
4033
|
+
}
|
|
4034
|
+
var PROMPT_PATTERNS = [
|
|
4035
|
+
// 文件覆盖确认 - 回答 n(不覆盖)
|
|
4036
|
+
{ pattern: /overwrite/i, answer: "n\n" },
|
|
4037
|
+
// 主题/样式选择 - 回答 n(不安装额外主题)
|
|
4038
|
+
{ pattern: /theme/i, answer: "n\n" },
|
|
4039
|
+
{ pattern: /style/i, answer: "n\n" },
|
|
4040
|
+
// 继续确认 - 回答 y
|
|
4041
|
+
{ pattern: /continue\?/i, answer: "y\n" },
|
|
4042
|
+
{ pattern: /proceed\?/i, answer: "y\n" }
|
|
4043
|
+
];
|
|
4044
|
+
async function executeShadcnAdd(registryItemPath) {
|
|
4045
|
+
return new Promise((resolve) => {
|
|
4046
|
+
let output = "";
|
|
4047
|
+
const args = ["--yes", "shadcn@3.8.2", "add", registryItemPath];
|
|
4048
|
+
const ptyProcess = pty.spawn("npx", args, {
|
|
4049
|
+
name: "xterm-color",
|
|
4050
|
+
cols: 120,
|
|
4051
|
+
rows: 30,
|
|
4052
|
+
cwd: process.cwd(),
|
|
4053
|
+
env: {
|
|
4054
|
+
...process.env,
|
|
4055
|
+
// 禁用颜色输出以便解析
|
|
4056
|
+
NO_COLOR: "1",
|
|
4057
|
+
FORCE_COLOR: "0"
|
|
4058
|
+
}
|
|
4059
|
+
});
|
|
4060
|
+
ptyProcess.onData((data) => {
|
|
4061
|
+
output += data;
|
|
4062
|
+
for (const { pattern, answer } of PROMPT_PATTERNS) {
|
|
4063
|
+
if (pattern.test(data)) {
|
|
4064
|
+
ptyProcess.write(answer);
|
|
4065
|
+
return;
|
|
4066
|
+
}
|
|
4067
|
+
}
|
|
4068
|
+
});
|
|
4069
|
+
const timeoutId = setTimeout(() => {
|
|
4070
|
+
ptyProcess.kill();
|
|
4071
|
+
resolve({
|
|
4072
|
+
success: false,
|
|
4073
|
+
files: [],
|
|
4074
|
+
error: "\u6267\u884C\u8D85\u65F6"
|
|
4075
|
+
});
|
|
4076
|
+
}, 3 * 60 * 1e3);
|
|
4077
|
+
ptyProcess.onExit(({ exitCode }) => {
|
|
4078
|
+
clearTimeout(timeoutId);
|
|
4079
|
+
const success = exitCode === 0;
|
|
4080
|
+
const filePaths = parseOutput(output);
|
|
4081
|
+
const files = filePaths.map(toFileInfo);
|
|
4082
|
+
resolve({
|
|
4083
|
+
success,
|
|
4084
|
+
files,
|
|
4085
|
+
error: success ? void 0 : output || `Process exited with code ${exitCode}`
|
|
4086
|
+
});
|
|
4087
|
+
});
|
|
4088
|
+
});
|
|
4089
|
+
}
|
|
4090
|
+
|
|
4091
|
+
// src/commands/component/add.handler.ts
|
|
4092
|
+
function runActionPluginInit() {
|
|
4093
|
+
return new Promise((resolve) => {
|
|
4094
|
+
execFile("fullstack-cli", ["action-plugin", "init"], { cwd: process.cwd(), stdio: "ignore" }, (error) => {
|
|
4095
|
+
if (error) {
|
|
4096
|
+
debug("action-plugin init \u5931\u8D25: %s", error.message);
|
|
4097
|
+
}
|
|
4098
|
+
resolve();
|
|
4099
|
+
});
|
|
4100
|
+
});
|
|
4101
|
+
}
|
|
4102
|
+
function printResult(result) {
|
|
4103
|
+
console.log(JSON.stringify(result, null, 2));
|
|
4104
|
+
}
|
|
4105
|
+
async function addComponent(key) {
|
|
4106
|
+
debug("\u5F00\u59CB\u5B89\u88C5\u7EC4\u4EF6: %s", key);
|
|
4107
|
+
debug("\u51C6\u5907 registry items...");
|
|
4108
|
+
const registryItemPath = await prepareComponentRegistryItems(key);
|
|
4109
|
+
debug("registry item \u8DEF\u5F84: %s", registryItemPath);
|
|
4110
|
+
const registryItem = getDownloadedRegistryItem(key);
|
|
4111
|
+
debug("\u83B7\u53D6\u5230 registry item: %o", registryItem);
|
|
4112
|
+
debug("\u6267\u884C shadcn add...");
|
|
4113
|
+
const executeResult = await executeShadcnAdd(registryItemPath);
|
|
4114
|
+
debug("shadcn \u6267\u884C\u7ED3\u679C: %o", executeResult);
|
|
4115
|
+
if (!executeResult.success) {
|
|
4116
|
+
throw new Error(executeResult.error || "\u5B89\u88C5\u5931\u8D25\uFF0C\u672A\u77E5\u539F\u56E0");
|
|
4117
|
+
}
|
|
4118
|
+
return {
|
|
4119
|
+
success: true,
|
|
4120
|
+
name: key,
|
|
4121
|
+
description: registryItem?.description || "",
|
|
4122
|
+
files: executeResult.files,
|
|
4123
|
+
docs: registryItem?.docs || ""
|
|
4124
|
+
};
|
|
4125
|
+
}
|
|
4126
|
+
async function add(key) {
|
|
4127
|
+
try {
|
|
4128
|
+
const result = await addComponent(key);
|
|
4129
|
+
printResult(result);
|
|
4130
|
+
void sendInstallEvent(key);
|
|
4131
|
+
} catch (error) {
|
|
4132
|
+
const errorMessage = error instanceof Error ? error.message : "\u5B89\u88C5\u5931\u8D25\uFF0C\u539F\u56E0\u672A\u77E5";
|
|
4133
|
+
printResult({
|
|
4134
|
+
success: false,
|
|
4135
|
+
errors: [{ message: errorMessage }]
|
|
4136
|
+
});
|
|
4137
|
+
} finally {
|
|
4138
|
+
await runActionPluginInit();
|
|
4139
|
+
cleanupTempDir();
|
|
4140
|
+
}
|
|
4141
|
+
}
|
|
4142
|
+
|
|
4143
|
+
// src/commands/component/index.ts
|
|
4144
|
+
var addCommand = {
|
|
4145
|
+
name: "add",
|
|
4146
|
+
description: "\u5B89\u88C5\u5999\u642D\u7EC4\u4EF6\u5E02\u573A\u4E2D\u7684\u7EC4\u4EF6",
|
|
4147
|
+
register(program) {
|
|
4148
|
+
program.command(this.name).description(this.description).argument("<component>", "\u7EC4\u4EF6 ID (\u4F8B\u5982 @miaoda/button)").action(async (component) => {
|
|
4149
|
+
await add(component);
|
|
4150
|
+
});
|
|
4151
|
+
}
|
|
4152
|
+
};
|
|
4153
|
+
var componentCommandGroup = {
|
|
4154
|
+
name: "component",
|
|
4155
|
+
description: "\u7EC4\u4EF6\u76F8\u5173\u547D\u4EE4",
|
|
4156
|
+
commands: [addCommand]
|
|
4157
|
+
};
|
|
4158
|
+
|
|
3455
4159
|
// src/commands/migration/version-manager.ts
|
|
3456
|
-
import
|
|
3457
|
-
import
|
|
4160
|
+
import fs14 from "fs";
|
|
4161
|
+
import path12 from "path";
|
|
3458
4162
|
var PACKAGE_JSON = "package.json";
|
|
3459
4163
|
var VERSION_FIELD = "migrationVersion";
|
|
3460
4164
|
function getPackageJsonPath2() {
|
|
3461
|
-
return
|
|
4165
|
+
return path12.join(process.cwd(), PACKAGE_JSON);
|
|
3462
4166
|
}
|
|
3463
4167
|
function getCurrentVersion() {
|
|
3464
4168
|
const pkgPath = getPackageJsonPath2();
|
|
3465
|
-
if (!
|
|
4169
|
+
if (!fs14.existsSync(pkgPath)) {
|
|
3466
4170
|
throw new Error("package.json not found");
|
|
3467
4171
|
}
|
|
3468
|
-
const pkg2 = JSON.parse(
|
|
4172
|
+
const pkg2 = JSON.parse(fs14.readFileSync(pkgPath, "utf-8"));
|
|
3469
4173
|
return pkg2[VERSION_FIELD] ?? 0;
|
|
3470
4174
|
}
|
|
3471
4175
|
function setCurrentVersion(version) {
|
|
3472
4176
|
const pkgPath = getPackageJsonPath2();
|
|
3473
|
-
const pkg2 = JSON.parse(
|
|
4177
|
+
const pkg2 = JSON.parse(fs14.readFileSync(pkgPath, "utf-8"));
|
|
3474
4178
|
pkg2[VERSION_FIELD] = version;
|
|
3475
|
-
|
|
4179
|
+
fs14.writeFileSync(pkgPath, JSON.stringify(pkg2, null, 2) + "\n", "utf-8");
|
|
3476
4180
|
}
|
|
3477
4181
|
|
|
3478
4182
|
// src/commands/migration/versions/v001_capability/json-migrator/detector.ts
|
|
3479
|
-
import
|
|
3480
|
-
import
|
|
4183
|
+
import fs16 from "fs";
|
|
4184
|
+
import path14 from "path";
|
|
3481
4185
|
|
|
3482
4186
|
// src/commands/migration/versions/v001_capability/utils.ts
|
|
3483
|
-
import
|
|
3484
|
-
import
|
|
4187
|
+
import fs15 from "fs";
|
|
4188
|
+
import path13 from "path";
|
|
3485
4189
|
var CAPABILITIES_DIR2 = "server/capabilities";
|
|
3486
4190
|
function getProjectRoot3() {
|
|
3487
4191
|
return process.cwd();
|
|
3488
4192
|
}
|
|
3489
4193
|
function getCapabilitiesDir2() {
|
|
3490
|
-
return
|
|
4194
|
+
return path13.join(getProjectRoot3(), CAPABILITIES_DIR2);
|
|
3491
4195
|
}
|
|
3492
4196
|
function getPluginManifestPath2(pluginKey) {
|
|
3493
|
-
return
|
|
4197
|
+
return path13.join(getProjectRoot3(), "node_modules", pluginKey, "manifest.json");
|
|
3494
4198
|
}
|
|
3495
4199
|
|
|
3496
4200
|
// src/commands/migration/versions/v001_capability/json-migrator/detector.ts
|
|
3497
4201
|
function detectJsonMigration() {
|
|
3498
4202
|
const capabilitiesDir = getCapabilitiesDir2();
|
|
3499
|
-
const oldFilePath =
|
|
3500
|
-
if (!
|
|
4203
|
+
const oldFilePath = path14.join(capabilitiesDir, "capabilities.json");
|
|
4204
|
+
if (!fs16.existsSync(oldFilePath)) {
|
|
3501
4205
|
return {
|
|
3502
4206
|
needsMigration: false,
|
|
3503
4207
|
reason: "capabilities.json not found"
|
|
3504
4208
|
};
|
|
3505
4209
|
}
|
|
3506
4210
|
try {
|
|
3507
|
-
const content =
|
|
4211
|
+
const content = fs16.readFileSync(oldFilePath, "utf-8");
|
|
3508
4212
|
const parsed = JSON.parse(content);
|
|
3509
4213
|
if (!Array.isArray(parsed)) {
|
|
3510
4214
|
return {
|
|
@@ -3555,8 +4259,8 @@ async function check(options) {
|
|
|
3555
4259
|
}
|
|
3556
4260
|
|
|
3557
4261
|
// src/commands/migration/versions/v001_capability/json-migrator/index.ts
|
|
3558
|
-
import
|
|
3559
|
-
import
|
|
4262
|
+
import fs17 from "fs";
|
|
4263
|
+
import path15 from "path";
|
|
3560
4264
|
|
|
3561
4265
|
// src/commands/migration/versions/v001_capability/mapping.ts
|
|
3562
4266
|
var DEFAULT_PLUGIN_VERSION = "1.0.0";
|
|
@@ -3786,18 +4490,18 @@ function transformCapabilities(oldCapabilities) {
|
|
|
3786
4490
|
// src/commands/migration/versions/v001_capability/json-migrator/index.ts
|
|
3787
4491
|
function loadExistingCapabilities() {
|
|
3788
4492
|
const capabilitiesDir = getCapabilitiesDir2();
|
|
3789
|
-
if (!
|
|
4493
|
+
if (!fs17.existsSync(capabilitiesDir)) {
|
|
3790
4494
|
return [];
|
|
3791
4495
|
}
|
|
3792
|
-
const files =
|
|
4496
|
+
const files = fs17.readdirSync(capabilitiesDir);
|
|
3793
4497
|
const capabilities = [];
|
|
3794
4498
|
for (const file of files) {
|
|
3795
4499
|
if (file === "capabilities.json" || !file.endsWith(".json")) {
|
|
3796
4500
|
continue;
|
|
3797
4501
|
}
|
|
3798
4502
|
try {
|
|
3799
|
-
const filePath =
|
|
3800
|
-
const content =
|
|
4503
|
+
const filePath = path15.join(capabilitiesDir, file);
|
|
4504
|
+
const content = fs17.readFileSync(filePath, "utf-8");
|
|
3801
4505
|
const capability = JSON.parse(content);
|
|
3802
4506
|
if (capability.id && capability.pluginKey) {
|
|
3803
4507
|
capabilities.push(capability);
|
|
@@ -3855,9 +4559,9 @@ async function migrateJsonFiles(options) {
|
|
|
3855
4559
|
}
|
|
3856
4560
|
const capabilitiesDir = getCapabilitiesDir2();
|
|
3857
4561
|
for (const cap of newCapabilities) {
|
|
3858
|
-
const filePath =
|
|
4562
|
+
const filePath = path15.join(capabilitiesDir, `${cap.id}.json`);
|
|
3859
4563
|
const content = JSON.stringify(cap, null, 2);
|
|
3860
|
-
|
|
4564
|
+
fs17.writeFileSync(filePath, content, "utf-8");
|
|
3861
4565
|
console.log(` \u2713 Created: ${cap.id}.json`);
|
|
3862
4566
|
}
|
|
3863
4567
|
return {
|
|
@@ -3869,11 +4573,11 @@ async function migrateJsonFiles(options) {
|
|
|
3869
4573
|
}
|
|
3870
4574
|
|
|
3871
4575
|
// src/commands/migration/versions/v001_capability/plugin-installer/detector.ts
|
|
3872
|
-
import
|
|
4576
|
+
import fs18 from "fs";
|
|
3873
4577
|
function isPluginInstalled2(pluginKey) {
|
|
3874
4578
|
const actionPlugins = readActionPlugins();
|
|
3875
4579
|
const manifestPath = getPluginManifestPath2(pluginKey);
|
|
3876
|
-
return
|
|
4580
|
+
return fs18.existsSync(manifestPath) && !!actionPlugins[pluginKey];
|
|
3877
4581
|
}
|
|
3878
4582
|
function detectPluginsToInstall(capabilities) {
|
|
3879
4583
|
const pluginKeys = /* @__PURE__ */ new Set();
|
|
@@ -3949,12 +4653,12 @@ async function installPlugins(capabilities, options) {
|
|
|
3949
4653
|
}
|
|
3950
4654
|
|
|
3951
4655
|
// src/commands/migration/versions/v001_capability/code-migrator/index.ts
|
|
3952
|
-
import
|
|
4656
|
+
import path17 from "path";
|
|
3953
4657
|
import { Project as Project3 } from "ts-morph";
|
|
3954
4658
|
|
|
3955
4659
|
// src/commands/migration/versions/v001_capability/code-migrator/scanner.ts
|
|
3956
|
-
import
|
|
3957
|
-
import
|
|
4660
|
+
import fs19 from "fs";
|
|
4661
|
+
import path16 from "path";
|
|
3958
4662
|
var EXCLUDED_DIRS = [
|
|
3959
4663
|
"node_modules",
|
|
3960
4664
|
"dist",
|
|
@@ -3969,9 +4673,9 @@ var EXCLUDED_PATTERNS = [
|
|
|
3969
4673
|
/\.d\.ts$/
|
|
3970
4674
|
];
|
|
3971
4675
|
function scanDirectory(dir, files = []) {
|
|
3972
|
-
const entries =
|
|
4676
|
+
const entries = fs19.readdirSync(dir, { withFileTypes: true });
|
|
3973
4677
|
for (const entry of entries) {
|
|
3974
|
-
const fullPath =
|
|
4678
|
+
const fullPath = path16.join(dir, entry.name);
|
|
3975
4679
|
if (entry.isDirectory()) {
|
|
3976
4680
|
if (EXCLUDED_DIRS.includes(entry.name)) {
|
|
3977
4681
|
continue;
|
|
@@ -3987,14 +4691,14 @@ function scanDirectory(dir, files = []) {
|
|
|
3987
4691
|
return files;
|
|
3988
4692
|
}
|
|
3989
4693
|
function scanServerFiles() {
|
|
3990
|
-
const serverDir =
|
|
3991
|
-
if (!
|
|
4694
|
+
const serverDir = path16.join(getProjectRoot3(), "server");
|
|
4695
|
+
if (!fs19.existsSync(serverDir)) {
|
|
3992
4696
|
return [];
|
|
3993
4697
|
}
|
|
3994
4698
|
return scanDirectory(serverDir);
|
|
3995
4699
|
}
|
|
3996
4700
|
function hasCapabilityImport(filePath) {
|
|
3997
|
-
const content =
|
|
4701
|
+
const content = fs19.readFileSync(filePath, "utf-8");
|
|
3998
4702
|
return /import\s+.*from\s+['"][^'"]*capabilities[^'"]*['"]/.test(content);
|
|
3999
4703
|
}
|
|
4000
4704
|
function scanFilesToMigrate() {
|
|
@@ -4371,7 +5075,7 @@ function analyzeFile(project, filePath, actionNameMap) {
|
|
|
4371
5075
|
const callSites = analyzeCallSites(sourceFile, imports);
|
|
4372
5076
|
const classInfo = analyzeClass(sourceFile);
|
|
4373
5077
|
const { canMigrate, reason } = canAutoMigrate(classInfo);
|
|
4374
|
-
const relativePath =
|
|
5078
|
+
const relativePath = path17.relative(getProjectRoot3(), filePath);
|
|
4375
5079
|
return {
|
|
4376
5080
|
filePath: relativePath,
|
|
4377
5081
|
imports,
|
|
@@ -4382,7 +5086,7 @@ function analyzeFile(project, filePath, actionNameMap) {
|
|
|
4382
5086
|
};
|
|
4383
5087
|
}
|
|
4384
5088
|
function migrateFile(project, analysis, dryRun) {
|
|
4385
|
-
const absolutePath =
|
|
5089
|
+
const absolutePath = path17.join(getProjectRoot3(), analysis.filePath);
|
|
4386
5090
|
if (!analysis.canAutoMigrate) {
|
|
4387
5091
|
return {
|
|
4388
5092
|
filePath: analysis.filePath,
|
|
@@ -4485,17 +5189,17 @@ function getSuggestion(analysis) {
|
|
|
4485
5189
|
}
|
|
4486
5190
|
|
|
4487
5191
|
// src/commands/migration/versions/v001_capability/cleanup.ts
|
|
4488
|
-
import
|
|
4489
|
-
import
|
|
5192
|
+
import fs20 from "fs";
|
|
5193
|
+
import path18 from "path";
|
|
4490
5194
|
function cleanupOldFiles(capabilities, dryRun) {
|
|
4491
5195
|
const deletedFiles = [];
|
|
4492
5196
|
const errors = [];
|
|
4493
5197
|
const capabilitiesDir = getCapabilitiesDir2();
|
|
4494
|
-
const oldJsonPath =
|
|
4495
|
-
if (
|
|
5198
|
+
const oldJsonPath = path18.join(capabilitiesDir, "capabilities.json");
|
|
5199
|
+
if (fs20.existsSync(oldJsonPath)) {
|
|
4496
5200
|
try {
|
|
4497
5201
|
if (!dryRun) {
|
|
4498
|
-
|
|
5202
|
+
fs20.unlinkSync(oldJsonPath);
|
|
4499
5203
|
}
|
|
4500
5204
|
deletedFiles.push("capabilities.json");
|
|
4501
5205
|
} catch (error) {
|
|
@@ -4503,11 +5207,11 @@ function cleanupOldFiles(capabilities, dryRun) {
|
|
|
4503
5207
|
}
|
|
4504
5208
|
}
|
|
4505
5209
|
for (const cap of capabilities) {
|
|
4506
|
-
const tsFilePath =
|
|
4507
|
-
if (
|
|
5210
|
+
const tsFilePath = path18.join(capabilitiesDir, `${cap.id}.ts`);
|
|
5211
|
+
if (fs20.existsSync(tsFilePath)) {
|
|
4508
5212
|
try {
|
|
4509
5213
|
if (!dryRun) {
|
|
4510
|
-
|
|
5214
|
+
fs20.unlinkSync(tsFilePath);
|
|
4511
5215
|
}
|
|
4512
5216
|
deletedFiles.push(`${cap.id}.ts`);
|
|
4513
5217
|
} catch (error) {
|
|
@@ -4523,8 +5227,8 @@ function cleanupOldFiles(capabilities, dryRun) {
|
|
|
4523
5227
|
}
|
|
4524
5228
|
|
|
4525
5229
|
// src/commands/migration/versions/v001_capability/report-generator.ts
|
|
4526
|
-
import
|
|
4527
|
-
import
|
|
5230
|
+
import fs21 from "fs";
|
|
5231
|
+
import path19 from "path";
|
|
4528
5232
|
var REPORT_FILE = "capability-migration-report.md";
|
|
4529
5233
|
function printSummary(result) {
|
|
4530
5234
|
const { jsonMigration, pluginInstallation, codeMigration, cleanup } = result;
|
|
@@ -4687,15 +5391,15 @@ async function generateReport(result) {
|
|
|
4687
5391
|
}
|
|
4688
5392
|
lines.push("");
|
|
4689
5393
|
const logDir = process.env.LOG_DIR || "logs";
|
|
4690
|
-
if (!
|
|
5394
|
+
if (!fs21.existsSync(logDir)) {
|
|
4691
5395
|
return;
|
|
4692
5396
|
}
|
|
4693
|
-
const reportDir =
|
|
4694
|
-
if (!
|
|
4695
|
-
|
|
5397
|
+
const reportDir = path19.join(logDir, "migration");
|
|
5398
|
+
if (!fs21.existsSync(reportDir)) {
|
|
5399
|
+
fs21.mkdirSync(reportDir, { recursive: true });
|
|
4696
5400
|
}
|
|
4697
|
-
const reportPath =
|
|
4698
|
-
|
|
5401
|
+
const reportPath = path19.join(reportDir, REPORT_FILE);
|
|
5402
|
+
fs21.writeFileSync(reportPath, lines.join("\n"), "utf-8");
|
|
4699
5403
|
console.log(`\u{1F4C4} Report generated: ${reportPath}`);
|
|
4700
5404
|
}
|
|
4701
5405
|
|
|
@@ -4872,7 +5576,7 @@ function buildResult(jsonMigration, pluginInstallation, codeMigration, cleanup)
|
|
|
4872
5576
|
}
|
|
4873
5577
|
|
|
4874
5578
|
// src/commands/migration/versions/v001_capability/run.ts
|
|
4875
|
-
async function
|
|
5579
|
+
async function run5(options) {
|
|
4876
5580
|
try {
|
|
4877
5581
|
const migrationOptions = {
|
|
4878
5582
|
dryRun: options.dryRun ?? false
|
|
@@ -4937,7 +5641,7 @@ var v001CapabilityMigration = {
|
|
|
4937
5641
|
name: "capability",
|
|
4938
5642
|
description: "Migrate capability configurations from old format (capabilities.json array) to new format (individual JSON files)",
|
|
4939
5643
|
check,
|
|
4940
|
-
run:
|
|
5644
|
+
run: run5
|
|
4941
5645
|
};
|
|
4942
5646
|
|
|
4943
5647
|
// src/commands/migration/versions/index.ts
|
|
@@ -5227,10 +5931,10 @@ var migrationCommand = {
|
|
|
5227
5931
|
};
|
|
5228
5932
|
|
|
5229
5933
|
// src/commands/read-logs/index.ts
|
|
5230
|
-
import
|
|
5934
|
+
import path20 from "path";
|
|
5231
5935
|
|
|
5232
5936
|
// src/commands/read-logs/std-utils.ts
|
|
5233
|
-
import
|
|
5937
|
+
import fs22 from "fs";
|
|
5234
5938
|
function formatStdPrefixTime(localTime) {
|
|
5235
5939
|
const match = localTime.match(/^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/);
|
|
5236
5940
|
if (!match) return localTime;
|
|
@@ -5260,11 +5964,11 @@ function stripPrefixFromStdLine(line) {
|
|
|
5260
5964
|
return `[${time}] ${content}`;
|
|
5261
5965
|
}
|
|
5262
5966
|
function readStdLinesTailFromLastMarkerPaged(filePath, maxLines, offset, isMarker) {
|
|
5263
|
-
const stat =
|
|
5967
|
+
const stat = fs22.statSync(filePath);
|
|
5264
5968
|
if (stat.size === 0) {
|
|
5265
5969
|
return { lines: [], markerFound: false, totalLinesCount: 0 };
|
|
5266
5970
|
}
|
|
5267
|
-
const fd =
|
|
5971
|
+
const fd = fs22.openSync(filePath, "r");
|
|
5268
5972
|
const chunkSize = 64 * 1024;
|
|
5269
5973
|
let position = stat.size;
|
|
5270
5974
|
let remainder = "";
|
|
@@ -5278,7 +5982,7 @@ function readStdLinesTailFromLastMarkerPaged(filePath, maxLines, offset, isMarke
|
|
|
5278
5982
|
const length = Math.min(chunkSize, position);
|
|
5279
5983
|
position -= length;
|
|
5280
5984
|
const buffer = Buffer.alloc(length);
|
|
5281
|
-
|
|
5985
|
+
fs22.readSync(fd, buffer, 0, length, position);
|
|
5282
5986
|
let chunk = buffer.toString("utf8");
|
|
5283
5987
|
if (remainder) {
|
|
5284
5988
|
chunk += remainder;
|
|
@@ -5320,7 +6024,7 @@ function readStdLinesTailFromLastMarkerPaged(filePath, maxLines, offset, isMarke
|
|
|
5320
6024
|
}
|
|
5321
6025
|
}
|
|
5322
6026
|
} finally {
|
|
5323
|
-
|
|
6027
|
+
fs22.closeSync(fd);
|
|
5324
6028
|
}
|
|
5325
6029
|
return { lines: collected.reverse(), markerFound, totalLinesCount };
|
|
5326
6030
|
}
|
|
@@ -5341,21 +6045,21 @@ function readServerStdSegment(filePath, maxLines, offset) {
|
|
|
5341
6045
|
}
|
|
5342
6046
|
|
|
5343
6047
|
// src/commands/read-logs/tail.ts
|
|
5344
|
-
import
|
|
6048
|
+
import fs23 from "fs";
|
|
5345
6049
|
function fileExists(filePath) {
|
|
5346
6050
|
try {
|
|
5347
|
-
|
|
6051
|
+
fs23.accessSync(filePath, fs23.constants.F_OK | fs23.constants.R_OK);
|
|
5348
6052
|
return true;
|
|
5349
6053
|
} catch {
|
|
5350
6054
|
return false;
|
|
5351
6055
|
}
|
|
5352
6056
|
}
|
|
5353
6057
|
function readFileTailLines(filePath, maxLines) {
|
|
5354
|
-
const stat =
|
|
6058
|
+
const stat = fs23.statSync(filePath);
|
|
5355
6059
|
if (stat.size === 0) {
|
|
5356
6060
|
return [];
|
|
5357
6061
|
}
|
|
5358
|
-
const fd =
|
|
6062
|
+
const fd = fs23.openSync(filePath, "r");
|
|
5359
6063
|
const chunkSize = 64 * 1024;
|
|
5360
6064
|
const chunks = [];
|
|
5361
6065
|
let position = stat.size;
|
|
@@ -5365,13 +6069,13 @@ function readFileTailLines(filePath, maxLines) {
|
|
|
5365
6069
|
const length = Math.min(chunkSize, position);
|
|
5366
6070
|
position -= length;
|
|
5367
6071
|
const buffer = Buffer.alloc(length);
|
|
5368
|
-
|
|
6072
|
+
fs23.readSync(fd, buffer, 0, length, position);
|
|
5369
6073
|
chunks.unshift(buffer.toString("utf8"));
|
|
5370
6074
|
const chunkLines = buffer.toString("utf8").split("\n").length - 1;
|
|
5371
6075
|
collectedLines += chunkLines;
|
|
5372
6076
|
}
|
|
5373
6077
|
} finally {
|
|
5374
|
-
|
|
6078
|
+
fs23.closeSync(fd);
|
|
5375
6079
|
}
|
|
5376
6080
|
const content = chunks.join("");
|
|
5377
6081
|
const allLines = content.split("\n");
|
|
@@ -5387,11 +6091,11 @@ function readFileTailLines(filePath, maxLines) {
|
|
|
5387
6091
|
return allLines.slice(allLines.length - maxLines);
|
|
5388
6092
|
}
|
|
5389
6093
|
function readFileTailNonEmptyLinesWithOffset(filePath, maxLines, offset) {
|
|
5390
|
-
const stat =
|
|
6094
|
+
const stat = fs23.statSync(filePath);
|
|
5391
6095
|
if (stat.size === 0) {
|
|
5392
6096
|
return { lines: [], totalLinesCount: 0 };
|
|
5393
6097
|
}
|
|
5394
|
-
const fd =
|
|
6098
|
+
const fd = fs23.openSync(filePath, "r");
|
|
5395
6099
|
const chunkSize = 64 * 1024;
|
|
5396
6100
|
let position = stat.size;
|
|
5397
6101
|
let remainder = "";
|
|
@@ -5403,7 +6107,7 @@ function readFileTailNonEmptyLinesWithOffset(filePath, maxLines, offset) {
|
|
|
5403
6107
|
const length = Math.min(chunkSize, position);
|
|
5404
6108
|
position -= length;
|
|
5405
6109
|
const buffer = Buffer.alloc(length);
|
|
5406
|
-
|
|
6110
|
+
fs23.readSync(fd, buffer, 0, length, position);
|
|
5407
6111
|
let chunk = buffer.toString("utf8");
|
|
5408
6112
|
if (remainder) {
|
|
5409
6113
|
chunk += remainder;
|
|
@@ -5434,7 +6138,7 @@ function readFileTailNonEmptyLinesWithOffset(filePath, maxLines, offset) {
|
|
|
5434
6138
|
}
|
|
5435
6139
|
}
|
|
5436
6140
|
} finally {
|
|
5437
|
-
|
|
6141
|
+
fs23.closeSync(fd);
|
|
5438
6142
|
}
|
|
5439
6143
|
return { lines: collected.reverse(), totalLinesCount };
|
|
5440
6144
|
}
|
|
@@ -5447,13 +6151,19 @@ function readClientStdSegment(filePath, maxLines, offset) {
|
|
|
5447
6151
|
function extractClientStdSegment(lines, maxLines, offset) {
|
|
5448
6152
|
const bodyLines = lines.map(stripPrefixFromStdLine);
|
|
5449
6153
|
const hotStartMarkers = [
|
|
6154
|
+
// Webpack markers
|
|
5450
6155
|
/file change detected\..*incremental compilation/i,
|
|
5451
6156
|
/starting incremental compilation/i,
|
|
5452
6157
|
/starting compilation/i,
|
|
5453
6158
|
/\bcompiling\b/i,
|
|
5454
|
-
/\brecompil/i
|
|
6159
|
+
/\brecompil/i,
|
|
6160
|
+
// Vite markers - format: "3:11:46 PM [vite] (client) hmr update ..."
|
|
6161
|
+
/VITE v[\d.]+.*ready/i,
|
|
6162
|
+
/\[vite\].*page reload/i,
|
|
6163
|
+
/\[vite\].*hmr update/i
|
|
5455
6164
|
];
|
|
5456
6165
|
const hotEndMarkers = [
|
|
6166
|
+
// Webpack markers
|
|
5457
6167
|
/file change detected\..*incremental compilation/i,
|
|
5458
6168
|
/\bwebpack compiled\b/i,
|
|
5459
6169
|
/compiled successfully/i,
|
|
@@ -5464,14 +6174,25 @@ function extractClientStdSegment(lines, maxLines, offset) {
|
|
|
5464
6174
|
/\bhmr\b/i,
|
|
5465
6175
|
/hot update/i,
|
|
5466
6176
|
/\bhot reload\b/i,
|
|
5467
|
-
/\bhmr update\b/i
|
|
6177
|
+
/\bhmr update\b/i,
|
|
6178
|
+
// Vite markers
|
|
6179
|
+
/VITE v[\d.]+.*ready/i,
|
|
6180
|
+
/\[vite\].*page reload/i,
|
|
6181
|
+
/\[vite\].*hmr update/i,
|
|
6182
|
+
/\[vite\].*hmr invalidate/i,
|
|
6183
|
+
/\[vite\].*internal server error/i,
|
|
6184
|
+
/\[vite\].*pre-transform error/i
|
|
5468
6185
|
];
|
|
5469
6186
|
const compiledMarkers = [
|
|
6187
|
+
// Webpack markers
|
|
5470
6188
|
/\bwebpack compiled\b/i,
|
|
5471
6189
|
/compiled successfully/i,
|
|
5472
6190
|
/compiled with warnings/i,
|
|
5473
6191
|
/compiled with errors/i,
|
|
5474
|
-
/failed to compile/i
|
|
6192
|
+
/failed to compile/i,
|
|
6193
|
+
// Vite markers
|
|
6194
|
+
/VITE v[\d.]+.*ready/i,
|
|
6195
|
+
/\[vite\].*hmr update/i
|
|
5475
6196
|
];
|
|
5476
6197
|
let startIndex = -1;
|
|
5477
6198
|
for (let i = bodyLines.length - 1; i >= 0; i -= 1) {
|
|
@@ -5524,14 +6245,15 @@ function extractClientStdSegment(lines, maxLines, offset) {
|
|
|
5524
6245
|
}
|
|
5525
6246
|
const segment = startIndex === -1 ? bodyLines : bodyLines.slice(startIndex);
|
|
5526
6247
|
if (segment.length === 0) {
|
|
5527
|
-
return { lines: [], totalLinesCount: 0 };
|
|
6248
|
+
return { lines: [], totalLinesCount: 0, allLines: [] };
|
|
5528
6249
|
}
|
|
5529
6250
|
const totalLinesCount = segment.length;
|
|
5530
6251
|
const endExclusive = Math.max(0, segment.length - offset);
|
|
5531
6252
|
const start = Math.max(0, endExclusive - maxLines);
|
|
5532
6253
|
return {
|
|
5533
6254
|
lines: segment.slice(start, endExclusive),
|
|
5534
|
-
totalLinesCount
|
|
6255
|
+
totalLinesCount,
|
|
6256
|
+
allLines: segment
|
|
5535
6257
|
};
|
|
5536
6258
|
}
|
|
5537
6259
|
|
|
@@ -5558,7 +6280,7 @@ function readDevStdSegment(filePath, maxLines, offset) {
|
|
|
5558
6280
|
}
|
|
5559
6281
|
|
|
5560
6282
|
// src/commands/read-logs/json-lines.ts
|
|
5561
|
-
import
|
|
6283
|
+
import fs24 from "fs";
|
|
5562
6284
|
function normalizePid(value) {
|
|
5563
6285
|
if (typeof value === "number") {
|
|
5564
6286
|
return String(value);
|
|
@@ -5609,11 +6331,11 @@ function buildWantedLevelSet(levels) {
|
|
|
5609
6331
|
return set.size > 0 ? set : null;
|
|
5610
6332
|
}
|
|
5611
6333
|
function readJsonLinesLastPid(filePath, maxLines, offset, levels) {
|
|
5612
|
-
const stat =
|
|
6334
|
+
const stat = fs24.statSync(filePath);
|
|
5613
6335
|
if (stat.size === 0) {
|
|
5614
6336
|
return { lines: [], totalLinesCount: 0 };
|
|
5615
6337
|
}
|
|
5616
|
-
const fd =
|
|
6338
|
+
const fd = fs24.openSync(filePath, "r");
|
|
5617
6339
|
const chunkSize = 64 * 1024;
|
|
5618
6340
|
let position = stat.size;
|
|
5619
6341
|
let remainder = "";
|
|
@@ -5628,7 +6350,7 @@ function readJsonLinesLastPid(filePath, maxLines, offset, levels) {
|
|
|
5628
6350
|
const length = Math.min(chunkSize, position);
|
|
5629
6351
|
position -= length;
|
|
5630
6352
|
const buffer = Buffer.alloc(length);
|
|
5631
|
-
|
|
6353
|
+
fs24.readSync(fd, buffer, 0, length, position);
|
|
5632
6354
|
let chunk = buffer.toString("utf8");
|
|
5633
6355
|
if (remainder) {
|
|
5634
6356
|
chunk += remainder;
|
|
@@ -5690,7 +6412,7 @@ function readJsonLinesLastPid(filePath, maxLines, offset, levels) {
|
|
|
5690
6412
|
}
|
|
5691
6413
|
}
|
|
5692
6414
|
} finally {
|
|
5693
|
-
|
|
6415
|
+
fs24.closeSync(fd);
|
|
5694
6416
|
}
|
|
5695
6417
|
return { lines: collected.reverse(), totalLinesCount };
|
|
5696
6418
|
}
|
|
@@ -5733,11 +6455,11 @@ function extractTraceId(obj) {
|
|
|
5733
6455
|
function readJsonLinesByTraceId(filePath, traceId, maxLines, offset, levels) {
|
|
5734
6456
|
const wanted = traceId.trim();
|
|
5735
6457
|
if (!wanted) return { lines: [], totalLinesCount: 0 };
|
|
5736
|
-
const stat =
|
|
6458
|
+
const stat = fs24.statSync(filePath);
|
|
5737
6459
|
if (stat.size === 0) {
|
|
5738
6460
|
return { lines: [], totalLinesCount: 0 };
|
|
5739
6461
|
}
|
|
5740
|
-
const fd =
|
|
6462
|
+
const fd = fs24.openSync(filePath, "r");
|
|
5741
6463
|
const chunkSize = 64 * 1024;
|
|
5742
6464
|
let position = stat.size;
|
|
5743
6465
|
let remainder = "";
|
|
@@ -5750,7 +6472,7 @@ function readJsonLinesByTraceId(filePath, traceId, maxLines, offset, levels) {
|
|
|
5750
6472
|
const length = Math.min(chunkSize, position);
|
|
5751
6473
|
position -= length;
|
|
5752
6474
|
const buffer = Buffer.alloc(length);
|
|
5753
|
-
|
|
6475
|
+
fs24.readSync(fd, buffer, 0, length, position);
|
|
5754
6476
|
let chunk = buffer.toString("utf8");
|
|
5755
6477
|
if (remainder) {
|
|
5756
6478
|
chunk += remainder;
|
|
@@ -5803,7 +6525,7 @@ function readJsonLinesByTraceId(filePath, traceId, maxLines, offset, levels) {
|
|
|
5803
6525
|
}
|
|
5804
6526
|
}
|
|
5805
6527
|
} finally {
|
|
5806
|
-
|
|
6528
|
+
fs24.closeSync(fd);
|
|
5807
6529
|
}
|
|
5808
6530
|
return { lines: collected.reverse(), totalLinesCount };
|
|
5809
6531
|
}
|
|
@@ -5812,11 +6534,11 @@ function readJsonLinesTailByLevel(filePath, maxLines, offset, levels) {
|
|
|
5812
6534
|
if (!wantedLevelSet) {
|
|
5813
6535
|
return { lines: [], totalLinesCount: 0 };
|
|
5814
6536
|
}
|
|
5815
|
-
const stat =
|
|
6537
|
+
const stat = fs24.statSync(filePath);
|
|
5816
6538
|
if (stat.size === 0) {
|
|
5817
6539
|
return { lines: [], totalLinesCount: 0 };
|
|
5818
6540
|
}
|
|
5819
|
-
const fd =
|
|
6541
|
+
const fd = fs24.openSync(filePath, "r");
|
|
5820
6542
|
const chunkSize = 64 * 1024;
|
|
5821
6543
|
let position = stat.size;
|
|
5822
6544
|
let remainder = "";
|
|
@@ -5828,7 +6550,7 @@ function readJsonLinesTailByLevel(filePath, maxLines, offset, levels) {
|
|
|
5828
6550
|
const length = Math.min(chunkSize, position);
|
|
5829
6551
|
position -= length;
|
|
5830
6552
|
const buffer = Buffer.alloc(length);
|
|
5831
|
-
|
|
6553
|
+
fs24.readSync(fd, buffer, 0, length, position);
|
|
5832
6554
|
let chunk = buffer.toString("utf8");
|
|
5833
6555
|
if (remainder) {
|
|
5834
6556
|
chunk += remainder;
|
|
@@ -5875,7 +6597,7 @@ function readJsonLinesTailByLevel(filePath, maxLines, offset, levels) {
|
|
|
5875
6597
|
}
|
|
5876
6598
|
}
|
|
5877
6599
|
} finally {
|
|
5878
|
-
|
|
6600
|
+
fs24.closeSync(fd);
|
|
5879
6601
|
}
|
|
5880
6602
|
return { lines: collected.reverse(), totalLinesCount };
|
|
5881
6603
|
}
|
|
@@ -6068,12 +6790,21 @@ async function readLatestLogLinesMeta(options) {
|
|
|
6068
6790
|
return { lines: [], totalLinesCount: 0 };
|
|
6069
6791
|
}
|
|
6070
6792
|
async function readLogsJsonResult(options) {
|
|
6071
|
-
const { lines, totalLinesCount } = await readLatestLogLinesMeta(options);
|
|
6793
|
+
const { lines, totalLinesCount, allLines } = await readLatestLogLinesMeta(options);
|
|
6072
6794
|
if (options.type === "server-std" || options.type === "client-std" || options.type === "dev" || options.type === "dev-std" || options.type === "install-dep-std") {
|
|
6795
|
+
const linesForErrorCheck = allLines ?? lines;
|
|
6796
|
+
const stackTracePattern = /\bat\s+\S+\s+\([^)]+:\d+:\d+\)/;
|
|
6797
|
+
const linesToFilter = allLines ?? lines;
|
|
6798
|
+
const filteredLines = linesToFilter.filter((line) => !stackTracePattern.test(line));
|
|
6799
|
+
const maxLines = options.maxLines ?? 30;
|
|
6800
|
+
const offset = options.offset ?? 0;
|
|
6801
|
+
const endExclusive = Math.max(0, filteredLines.length - offset);
|
|
6802
|
+
const start = Math.max(0, endExclusive - maxLines);
|
|
6803
|
+
const paginatedLogs = filteredLines.slice(start, endExclusive);
|
|
6073
6804
|
return {
|
|
6074
|
-
hasError: hasErrorInStdLines(
|
|
6075
|
-
totalLinesCount,
|
|
6076
|
-
logs:
|
|
6805
|
+
hasError: hasErrorInStdLines(linesForErrorCheck),
|
|
6806
|
+
totalLinesCount: filteredLines.length,
|
|
6807
|
+
logs: paginatedLogs
|
|
6077
6808
|
};
|
|
6078
6809
|
}
|
|
6079
6810
|
const logs = [];
|
|
@@ -6100,34 +6831,34 @@ async function readLogsJsonResult(options) {
|
|
|
6100
6831
|
};
|
|
6101
6832
|
}
|
|
6102
6833
|
function resolveLogFilePath(logDir, type) {
|
|
6103
|
-
const base =
|
|
6834
|
+
const base = path20.isAbsolute(logDir) ? logDir : path20.join(process.cwd(), logDir);
|
|
6104
6835
|
if (type === "server") {
|
|
6105
|
-
return
|
|
6836
|
+
return path20.join(base, "server.log");
|
|
6106
6837
|
}
|
|
6107
6838
|
if (type === "trace") {
|
|
6108
|
-
return
|
|
6839
|
+
return path20.join(base, "trace.log");
|
|
6109
6840
|
}
|
|
6110
6841
|
if (type === "server-std") {
|
|
6111
|
-
return
|
|
6842
|
+
return path20.join(base, "server.std.log");
|
|
6112
6843
|
}
|
|
6113
6844
|
if (type === "client-std") {
|
|
6114
|
-
return
|
|
6845
|
+
return path20.join(base, "client.std.log");
|
|
6115
6846
|
}
|
|
6116
6847
|
if (type === "dev") {
|
|
6117
|
-
return
|
|
6848
|
+
return path20.join(base, "dev.log");
|
|
6118
6849
|
}
|
|
6119
6850
|
if (type === "dev-std") {
|
|
6120
|
-
return
|
|
6851
|
+
return path20.join(base, "dev.std.log");
|
|
6121
6852
|
}
|
|
6122
6853
|
if (type === "install-dep-std") {
|
|
6123
|
-
return
|
|
6854
|
+
return path20.join(base, "install-dep.std.log");
|
|
6124
6855
|
}
|
|
6125
6856
|
if (type === "browser") {
|
|
6126
|
-
return
|
|
6857
|
+
return path20.join(base, "browser.log");
|
|
6127
6858
|
}
|
|
6128
6859
|
throw new Error(`Unsupported log type: ${type}`);
|
|
6129
6860
|
}
|
|
6130
|
-
async function
|
|
6861
|
+
async function run6(options) {
|
|
6131
6862
|
const result = await readLogsJsonResult(options);
|
|
6132
6863
|
process.stdout.write(JSON.stringify(result) + "\n");
|
|
6133
6864
|
}
|
|
@@ -6169,7 +6900,7 @@ var readLogsCommand = {
|
|
|
6169
6900
|
const offset = parseNonNegativeInt(rawOptions.offset, "--offset");
|
|
6170
6901
|
const traceId = typeof rawOptions.traceId === "string" ? rawOptions.traceId : void 0;
|
|
6171
6902
|
const levels = parseCommaSeparatedList(rawOptions.level);
|
|
6172
|
-
await
|
|
6903
|
+
await run6({ logDir, type, maxLines, offset, traceId, levels });
|
|
6173
6904
|
} catch (error) {
|
|
6174
6905
|
const message = error instanceof Error ? error.message : String(error);
|
|
6175
6906
|
process.stderr.write(message + "\n");
|
|
@@ -6179,23 +6910,101 @@ var readLogsCommand = {
|
|
|
6179
6910
|
}
|
|
6180
6911
|
};
|
|
6181
6912
|
|
|
6913
|
+
// src/commands/build/types.ts
|
|
6914
|
+
var SCENE_CONFIGS = {
|
|
6915
|
+
pipeline: {
|
|
6916
|
+
name: "pipeline",
|
|
6917
|
+
requiredOptions: ["commitId"],
|
|
6918
|
+
buildRequestBody: (opts) => ({ commitID: opts.commitId })
|
|
6919
|
+
},
|
|
6920
|
+
static: {
|
|
6921
|
+
name: "static",
|
|
6922
|
+
requiredOptions: [],
|
|
6923
|
+
buildRequestBody: () => ({ commitID: "" })
|
|
6924
|
+
}
|
|
6925
|
+
};
|
|
6926
|
+
|
|
6927
|
+
// src/commands/build/api-client.ts
|
|
6928
|
+
async function genArtifactUploadCredential(appId, body) {
|
|
6929
|
+
const client = getHttpClient();
|
|
6930
|
+
const url = `/v1/app/${appId}/pipeline/gen_artifact_upload_credential`;
|
|
6931
|
+
const response = await client.post(url, body);
|
|
6932
|
+
if (!response.ok || response.status !== 200) {
|
|
6933
|
+
throw new Error(
|
|
6934
|
+
`API request failed: ${response.status} ${response.statusText}`
|
|
6935
|
+
);
|
|
6936
|
+
}
|
|
6937
|
+
return response.json();
|
|
6938
|
+
}
|
|
6939
|
+
|
|
6940
|
+
// src/commands/build/get-token.handler.ts
|
|
6941
|
+
async function getToken(options) {
|
|
6942
|
+
try {
|
|
6943
|
+
const sceneConfig = SCENE_CONFIGS[options.scene];
|
|
6944
|
+
if (!sceneConfig) {
|
|
6945
|
+
const available = Object.keys(SCENE_CONFIGS).join(", ");
|
|
6946
|
+
console.error(
|
|
6947
|
+
`[build] Error: invalid scene "${options.scene}". Available scenes: ${available}`
|
|
6948
|
+
);
|
|
6949
|
+
process.exit(1);
|
|
6950
|
+
}
|
|
6951
|
+
for (const key of sceneConfig.requiredOptions) {
|
|
6952
|
+
if (!options[key]) {
|
|
6953
|
+
console.error(
|
|
6954
|
+
`[build] Error: --${camelToKebab(key)} is required for scene "${options.scene}"`
|
|
6955
|
+
);
|
|
6956
|
+
process.exit(1);
|
|
6957
|
+
}
|
|
6958
|
+
}
|
|
6959
|
+
const body = sceneConfig.buildRequestBody(options);
|
|
6960
|
+
const response = await genArtifactUploadCredential(options.appId, body);
|
|
6961
|
+
console.log(JSON.stringify(response));
|
|
6962
|
+
} catch (error) {
|
|
6963
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
6964
|
+
console.error(`[build] Error: ${message}`);
|
|
6965
|
+
process.exit(1);
|
|
6966
|
+
}
|
|
6967
|
+
}
|
|
6968
|
+
function camelToKebab(str) {
|
|
6969
|
+
return str.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
6970
|
+
}
|
|
6971
|
+
|
|
6972
|
+
// src/commands/build/index.ts
|
|
6973
|
+
var getTokenCommand = {
|
|
6974
|
+
name: "get-token",
|
|
6975
|
+
description: "Get artifact upload credential (STI token)",
|
|
6976
|
+
register(program) {
|
|
6977
|
+
program.command(this.name).description(this.description).requiredOption("--app-id <id>", "Application ID").requiredOption("--scene <scene>", "Build scene (pipeline, static)").option("--commit-id <id>", "Git commit ID (required for pipeline scene)").action(async (options) => {
|
|
6978
|
+
await getToken(options);
|
|
6979
|
+
});
|
|
6980
|
+
}
|
|
6981
|
+
};
|
|
6982
|
+
var buildCommandGroup = {
|
|
6983
|
+
name: "build",
|
|
6984
|
+
description: "Build related commands",
|
|
6985
|
+
commands: [getTokenCommand]
|
|
6986
|
+
};
|
|
6987
|
+
|
|
6182
6988
|
// src/commands/index.ts
|
|
6183
6989
|
var commands = [
|
|
6184
6990
|
genDbSchemaCommand,
|
|
6185
6991
|
syncCommand,
|
|
6992
|
+
upgradeCommand,
|
|
6186
6993
|
actionPluginCommandGroup,
|
|
6187
6994
|
capabilityCommandGroup,
|
|
6995
|
+
componentCommandGroup,
|
|
6188
6996
|
migrationCommand,
|
|
6189
|
-
readLogsCommand
|
|
6997
|
+
readLogsCommand,
|
|
6998
|
+
buildCommandGroup
|
|
6190
6999
|
];
|
|
6191
7000
|
|
|
6192
7001
|
// src/index.ts
|
|
6193
|
-
var envPath =
|
|
6194
|
-
if (
|
|
7002
|
+
var envPath = path21.join(process.cwd(), ".env");
|
|
7003
|
+
if (fs25.existsSync(envPath)) {
|
|
6195
7004
|
dotenvConfig({ path: envPath });
|
|
6196
7005
|
}
|
|
6197
|
-
var __dirname =
|
|
6198
|
-
var pkg = JSON.parse(
|
|
7006
|
+
var __dirname = path21.dirname(fileURLToPath5(import.meta.url));
|
|
7007
|
+
var pkg = JSON.parse(fs25.readFileSync(path21.join(__dirname, "../package.json"), "utf-8"));
|
|
6199
7008
|
var cli = new FullstackCLI(pkg.version);
|
|
6200
7009
|
cli.useAll(commands);
|
|
6201
7010
|
cli.run();
|