@chrisluyi/daas-cli 1.2.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +242 -133
- package/package.json +8 -2
- package/skill.md +48 -1
package/dist/index.js
CHANGED
|
@@ -2311,12 +2311,36 @@ async function runMain(cmd, opts = {}) {
|
|
|
2311
2311
|
}
|
|
2312
2312
|
}
|
|
2313
2313
|
|
|
2314
|
-
// src/
|
|
2315
|
-
import {
|
|
2314
|
+
// src/index.ts
|
|
2315
|
+
import { createLogger as createLogger5, setLogger as setLogger5 } from "@chrisluyi/logger";
|
|
2316
|
+
|
|
2317
|
+
// src/logger/consolaTransport.ts
|
|
2318
|
+
function consolaTransport() {
|
|
2319
|
+
return (entry) => {
|
|
2320
|
+
switch (entry.level) {
|
|
2321
|
+
case "debug":
|
|
2322
|
+
consola.debug(entry.message, entry.context ?? "");
|
|
2323
|
+
break;
|
|
2324
|
+
case "info":
|
|
2325
|
+
consola.info(entry.message);
|
|
2326
|
+
break;
|
|
2327
|
+
case "warn":
|
|
2328
|
+
consola.warn(entry.message);
|
|
2329
|
+
break;
|
|
2330
|
+
case "error":
|
|
2331
|
+
consola.fatal(entry.message);
|
|
2332
|
+
break;
|
|
2333
|
+
}
|
|
2334
|
+
};
|
|
2335
|
+
}
|
|
2336
|
+
|
|
2337
|
+
// src/commands/build.ts
|
|
2316
2338
|
import { createConfig } from "@chrisluyi/rsbuild-config";
|
|
2339
|
+
import { createLogger, setLogger, apiTransport } from "@chrisluyi/logger";
|
|
2340
|
+
import { createRsbuild } from "@rsbuild/core";
|
|
2317
2341
|
|
|
2318
2342
|
// src/daas-config.ts
|
|
2319
|
-
import {
|
|
2343
|
+
import { existsSync, readFileSync } from "fs";
|
|
2320
2344
|
import { resolve } from "path";
|
|
2321
2345
|
|
|
2322
2346
|
class ConfigError extends Error {
|
|
@@ -2339,12 +2363,13 @@ function readDaasConfig(cwd = process.cwd()) {
|
|
|
2339
2363
|
configUrl: daas.configUrl,
|
|
2340
2364
|
port: daas.port ?? 3000,
|
|
2341
2365
|
coverage: daas.coverage,
|
|
2342
|
-
setupFiles: daas.setupFiles
|
|
2366
|
+
setupFiles: daas.setupFiles,
|
|
2367
|
+
logUrl: daas.logUrl
|
|
2343
2368
|
};
|
|
2344
2369
|
}
|
|
2345
2370
|
|
|
2346
2371
|
// src/manifest.ts
|
|
2347
|
-
import {
|
|
2372
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
2348
2373
|
import { resolve as resolve2 } from "path";
|
|
2349
2374
|
|
|
2350
2375
|
class ManifestError extends Error {
|
|
@@ -2387,6 +2412,33 @@ function stripScope(name) {
|
|
|
2387
2412
|
return name.replace(/^@[^/]+\//, "");
|
|
2388
2413
|
}
|
|
2389
2414
|
|
|
2415
|
+
// src/output.ts
|
|
2416
|
+
function formatSuccess(command, data) {
|
|
2417
|
+
return { ok: true, command, cliVersion: getCliVersion(), ...data };
|
|
2418
|
+
}
|
|
2419
|
+
function formatError(command, exitCode, error, suggestion) {
|
|
2420
|
+
return {
|
|
2421
|
+
ok: false,
|
|
2422
|
+
command,
|
|
2423
|
+
exitCode,
|
|
2424
|
+
error,
|
|
2425
|
+
suggestion,
|
|
2426
|
+
cliVersion: getCliVersion()
|
|
2427
|
+
};
|
|
2428
|
+
}
|
|
2429
|
+
function writeJsonSuccess(command, data) {
|
|
2430
|
+
process.stdout.write(`${JSON.stringify(formatSuccess(command, data))}
|
|
2431
|
+
`);
|
|
2432
|
+
}
|
|
2433
|
+
function writeJsonError(command, exitCode, error, suggestion) {
|
|
2434
|
+
process.stdout.write(`${JSON.stringify(formatError(command, exitCode, error, suggestion))}
|
|
2435
|
+
`);
|
|
2436
|
+
process.exit(exitCode);
|
|
2437
|
+
}
|
|
2438
|
+
function getCliVersion() {
|
|
2439
|
+
return process.env.DAAS_CLI_VERSION ?? "0.0.0";
|
|
2440
|
+
}
|
|
2441
|
+
|
|
2390
2442
|
// src/remote-config.ts
|
|
2391
2443
|
import { SUPPORTED_CONFIG_VERSION } from "@chrisluyi/rsbuild-config";
|
|
2392
2444
|
// src/fallback-config.json
|
|
@@ -2498,36 +2550,17 @@ function generateTsconfigDaas(cwd, target) {
|
|
|
2498
2550
|
extends: "./tsconfig.json",
|
|
2499
2551
|
compilerOptions: {
|
|
2500
2552
|
paths: {
|
|
2501
|
-
"@region-config": [`./src/config/regions/${target.region}`],
|
|
2553
|
+
"@region-config": [`./src/config/regions/${target.region}/config`],
|
|
2502
2554
|
"@platform-config": [`./src/config/platforms/${target.platform}`],
|
|
2503
|
-
"@product-config": [`./src/config/products/${target.product}`]
|
|
2555
|
+
"@product-config": [`./src/config/products/${target.product}`],
|
|
2556
|
+
"@regional": [`./src/config/regions/${target.region}/index`]
|
|
2504
2557
|
}
|
|
2505
2558
|
}
|
|
2506
2559
|
};
|
|
2507
|
-
writeFileSync(resolve3(cwd, "tsconfig.daas.json"), JSON.stringify(content, null, 2)
|
|
2560
|
+
writeFileSync(resolve3(cwd, "tsconfig.daas.json"), `${JSON.stringify(content, null, 2)}
|
|
2508
2561
|
`);
|
|
2509
2562
|
}
|
|
2510
2563
|
|
|
2511
|
-
// src/output.ts
|
|
2512
|
-
function formatSuccess(command, data) {
|
|
2513
|
-
return { ok: true, command, cliVersion: getCliVersion(), ...data };
|
|
2514
|
-
}
|
|
2515
|
-
function formatError(command, exitCode, error, suggestion) {
|
|
2516
|
-
return { ok: false, command, exitCode, error, suggestion, cliVersion: getCliVersion() };
|
|
2517
|
-
}
|
|
2518
|
-
function writeJsonSuccess(command, data) {
|
|
2519
|
-
process.stdout.write(JSON.stringify(formatSuccess(command, data)) + `
|
|
2520
|
-
`);
|
|
2521
|
-
}
|
|
2522
|
-
function writeJsonError(command, exitCode, error, suggestion) {
|
|
2523
|
-
process.stdout.write(JSON.stringify(formatError(command, exitCode, error, suggestion)) + `
|
|
2524
|
-
`);
|
|
2525
|
-
process.exit(exitCode);
|
|
2526
|
-
}
|
|
2527
|
-
function getCliVersion() {
|
|
2528
|
-
return process.env.DAAS_CLI_VERSION ?? "0.0.0";
|
|
2529
|
-
}
|
|
2530
|
-
|
|
2531
2564
|
// src/types.ts
|
|
2532
2565
|
var EXIT_CODES = {
|
|
2533
2566
|
SUCCESS: 0,
|
|
@@ -2538,83 +2571,26 @@ var EXIT_CODES = {
|
|
|
2538
2571
|
CONFIG_VERSION_MISMATCH: 5
|
|
2539
2572
|
};
|
|
2540
2573
|
|
|
2541
|
-
// src/commands/dev.ts
|
|
2542
|
-
var devCommand = defineCommand({
|
|
2543
|
-
meta: { name: "dev", description: "Start MFE dev server" },
|
|
2544
|
-
args: {
|
|
2545
|
-
target: { type: "positional", description: "Build target (e.g. sg-foo-mb-dev)", required: false },
|
|
2546
|
-
port: { type: "string", description: "Override dev server port" },
|
|
2547
|
-
json: { type: "boolean", default: false, description: "Machine-readable JSON output" }
|
|
2548
|
-
},
|
|
2549
|
-
async run({ args }) {
|
|
2550
|
-
try {
|
|
2551
|
-
const daasConfig = readDaasConfig();
|
|
2552
|
-
const manifest = readManifest();
|
|
2553
|
-
const remoteMeta = await fetchRemoteConfig(daasConfig.configUrl, false);
|
|
2554
|
-
checkCliVersion(remoteMeta);
|
|
2555
|
-
const versionOk = checkConfigVersion(remoteMeta, false);
|
|
2556
|
-
if (!versionOk) {
|
|
2557
|
-
consola.warn("Config version mismatch \u2014 update daas-cli for full compatibility");
|
|
2558
|
-
}
|
|
2559
|
-
const port = args.port ? Number(args.port) : daasConfig.port;
|
|
2560
|
-
const target = args.target ? parseTarget(args.target) : undefined;
|
|
2561
|
-
if (target) {
|
|
2562
|
-
generateTsconfigDaas(process.cwd(), target);
|
|
2563
|
-
consola.info(`Target: ${args.target} (region=${target.region}, product=${target.product}, platform=${target.platform}, env=${target.environment})`);
|
|
2564
|
-
}
|
|
2565
|
-
const config = createConfig(manifest, remoteMeta, { mode: "development", port, target });
|
|
2566
|
-
consola.start(`Starting ${manifest.name} dev server...`);
|
|
2567
|
-
const rsbuild = await createRsbuild({ rsbuildConfig: config });
|
|
2568
|
-
const server = await rsbuild.createDevServer();
|
|
2569
|
-
await server.listen();
|
|
2570
|
-
consola.success(`Ready on http://localhost:${port}`);
|
|
2571
|
-
} catch (e2) {
|
|
2572
|
-
handleError("dev", e2, args.json);
|
|
2573
|
-
}
|
|
2574
|
-
}
|
|
2575
|
-
});
|
|
2576
|
-
function handleError(command, e2, json) {
|
|
2577
|
-
if (e2 instanceof CliVersionError) {
|
|
2578
|
-
if (json)
|
|
2579
|
-
writeJsonError(command, EXIT_CODES.CLI_TOO_OLD, e2.message, "Update daas-cli to the required version.");
|
|
2580
|
-
consola.fatal(e2.message);
|
|
2581
|
-
process.exit(EXIT_CODES.CLI_TOO_OLD);
|
|
2582
|
-
}
|
|
2583
|
-
if (e2 instanceof FetchError) {
|
|
2584
|
-
if (json)
|
|
2585
|
-
writeJsonError(command, EXIT_CODES.REMOTE_FETCH_FAILED, e2.message, "Check network or VPN.");
|
|
2586
|
-
consola.warn(`Remote config unavailable \u2014 using fallback. ${e2.message}`);
|
|
2587
|
-
process.exit(EXIT_CODES.REMOTE_FETCH_FAILED);
|
|
2588
|
-
}
|
|
2589
|
-
if (e2 instanceof TargetParseError) {
|
|
2590
|
-
if (json)
|
|
2591
|
-
writeJsonError(command, EXIT_CODES.CONFIG_ERROR, e2.message, "Check target format: {region}-{product}-{platform}-{environment}");
|
|
2592
|
-
consola.fatal(e2.message);
|
|
2593
|
-
process.exit(EXIT_CODES.CONFIG_ERROR);
|
|
2594
|
-
}
|
|
2595
|
-
if (e2 instanceof ConfigError || e2 instanceof ManifestError) {
|
|
2596
|
-
if (json)
|
|
2597
|
-
writeJsonError(command, EXIT_CODES.CONFIG_ERROR, e2.message, "Run daas init first.");
|
|
2598
|
-
consola.fatal(e2.message);
|
|
2599
|
-
process.exit(EXIT_CODES.CONFIG_ERROR);
|
|
2600
|
-
}
|
|
2601
|
-
consola.fatal(e2);
|
|
2602
|
-
process.exit(EXIT_CODES.GENERAL_ERROR);
|
|
2603
|
-
}
|
|
2604
|
-
|
|
2605
2574
|
// src/commands/build.ts
|
|
2606
|
-
import { createRsbuild as createRsbuild2 } from "@rsbuild/core";
|
|
2607
|
-
import { createConfig as createConfig2 } from "@chrisluyi/rsbuild-config";
|
|
2608
2575
|
var buildCommand = defineCommand({
|
|
2609
2576
|
meta: { name: "build", description: "Build MFE for production" },
|
|
2610
2577
|
args: {
|
|
2611
|
-
target: {
|
|
2612
|
-
|
|
2578
|
+
target: {
|
|
2579
|
+
type: "positional",
|
|
2580
|
+
description: "Build target (e.g. sg-foo-mb-prod)",
|
|
2581
|
+
required: false
|
|
2582
|
+
},
|
|
2583
|
+
json: {
|
|
2584
|
+
type: "boolean",
|
|
2585
|
+
default: false,
|
|
2586
|
+
description: "Machine-readable JSON output"
|
|
2587
|
+
}
|
|
2613
2588
|
},
|
|
2614
2589
|
async run({ args }) {
|
|
2615
2590
|
const json = args.json;
|
|
2616
2591
|
try {
|
|
2617
2592
|
const daasConfig = readDaasConfig();
|
|
2593
|
+
setLogger(createLogger([consolaTransport(), apiTransport(daasConfig.logUrl)]));
|
|
2618
2594
|
const manifest = readManifest();
|
|
2619
2595
|
if (!json)
|
|
2620
2596
|
consola.start(`Building ${manifest.name}...`);
|
|
@@ -2624,8 +2600,11 @@ var buildCommand = defineCommand({
|
|
|
2624
2600
|
const target = args.target ? parseTarget(args.target) : undefined;
|
|
2625
2601
|
if (target)
|
|
2626
2602
|
generateTsconfigDaas(process.cwd(), target);
|
|
2627
|
-
const config =
|
|
2628
|
-
|
|
2603
|
+
const config = createConfig(manifest, remoteMeta, {
|
|
2604
|
+
mode: "production",
|
|
2605
|
+
target
|
|
2606
|
+
});
|
|
2607
|
+
const rsbuild = await createRsbuild({ rsbuildConfig: config });
|
|
2629
2608
|
await rsbuild.build();
|
|
2630
2609
|
if (json)
|
|
2631
2610
|
writeJsonSuccess("build", { appName: manifest.name, output: "./dist" });
|
|
@@ -2667,41 +2646,92 @@ var buildCommand = defineCommand({
|
|
|
2667
2646
|
}
|
|
2668
2647
|
});
|
|
2669
2648
|
|
|
2670
|
-
// src/commands/
|
|
2671
|
-
import {
|
|
2672
|
-
import {
|
|
2673
|
-
|
|
2674
|
-
|
|
2649
|
+
// src/commands/dev.ts
|
|
2650
|
+
import { createConfig as createConfig2 } from "@chrisluyi/rsbuild-config";
|
|
2651
|
+
import { createLogger as createLogger2, setLogger as setLogger2, apiTransport as apiTransport2 } from "@chrisluyi/logger";
|
|
2652
|
+
import { createRsbuild as createRsbuild2 } from "@rsbuild/core";
|
|
2653
|
+
var devCommand = defineCommand({
|
|
2654
|
+
meta: { name: "dev", description: "Start MFE dev server" },
|
|
2675
2655
|
args: {
|
|
2676
|
-
|
|
2656
|
+
target: {
|
|
2657
|
+
type: "positional",
|
|
2658
|
+
description: "Build target (e.g. sg-foo-mb-dev)",
|
|
2659
|
+
required: false
|
|
2660
|
+
},
|
|
2661
|
+
port: { type: "string", description: "Override dev server port" },
|
|
2662
|
+
json: {
|
|
2663
|
+
type: "boolean",
|
|
2664
|
+
default: false,
|
|
2665
|
+
description: "Machine-readable JSON output"
|
|
2666
|
+
}
|
|
2677
2667
|
},
|
|
2678
2668
|
async run({ args }) {
|
|
2679
|
-
const json = args.json;
|
|
2680
2669
|
try {
|
|
2681
|
-
const manifest = readManifest();
|
|
2682
2670
|
const daasConfig = readDaasConfig();
|
|
2683
|
-
|
|
2684
|
-
const
|
|
2685
|
-
const
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2671
|
+
setLogger2(createLogger2([consolaTransport(), apiTransport2(daasConfig.logUrl)]));
|
|
2672
|
+
const manifest = readManifest();
|
|
2673
|
+
const remoteMeta = await fetchRemoteConfig(daasConfig.configUrl, false);
|
|
2674
|
+
checkCliVersion(remoteMeta);
|
|
2675
|
+
const versionOk = checkConfigVersion(remoteMeta, false);
|
|
2676
|
+
if (!versionOk) {
|
|
2677
|
+
consola.warn("Config version mismatch \u2014 update daas-cli for full compatibility");
|
|
2690
2678
|
}
|
|
2691
|
-
|
|
2692
|
-
|
|
2679
|
+
const port = args.port ? Number(args.port) : daasConfig.port;
|
|
2680
|
+
const target = args.target ? parseTarget(args.target) : undefined;
|
|
2681
|
+
if (target) {
|
|
2682
|
+
generateTsconfigDaas(process.cwd(), target);
|
|
2683
|
+
consola.info(`Target: ${args.target} (region=${target.region}, product=${target.product}, platform=${target.platform}, env=${target.environment})`);
|
|
2684
|
+
}
|
|
2685
|
+
const config = createConfig2(manifest, remoteMeta, {
|
|
2686
|
+
mode: "development",
|
|
2687
|
+
port,
|
|
2688
|
+
target
|
|
2689
|
+
});
|
|
2690
|
+
consola.start(`Starting ${manifest.name} dev server...`);
|
|
2691
|
+
const rsbuild = await createRsbuild2({ rsbuildConfig: config });
|
|
2692
|
+
const server = await rsbuild.createDevServer();
|
|
2693
|
+
await server.listen();
|
|
2694
|
+
consola.success(`Ready on http://localhost:${port}`);
|
|
2693
2695
|
} catch (e2) {
|
|
2694
|
-
|
|
2695
|
-
writeJsonError("test", EXIT_CODES.GENERAL_ERROR, e2.message, "Check test configuration");
|
|
2696
|
-
consola.fatal(e2);
|
|
2697
|
-
process.exit(EXIT_CODES.GENERAL_ERROR);
|
|
2696
|
+
handleError("dev", e2, args.json);
|
|
2698
2697
|
}
|
|
2699
2698
|
}
|
|
2700
2699
|
});
|
|
2700
|
+
function handleError(command, e2, json) {
|
|
2701
|
+
if (e2 instanceof CliVersionError) {
|
|
2702
|
+
if (json)
|
|
2703
|
+
writeJsonError(command, EXIT_CODES.CLI_TOO_OLD, e2.message, "Update daas-cli to the required version.");
|
|
2704
|
+
consola.fatal(e2.message);
|
|
2705
|
+
process.exit(EXIT_CODES.CLI_TOO_OLD);
|
|
2706
|
+
}
|
|
2707
|
+
if (e2 instanceof FetchError) {
|
|
2708
|
+
if (json)
|
|
2709
|
+
writeJsonError(command, EXIT_CODES.REMOTE_FETCH_FAILED, e2.message, "Check network or VPN.");
|
|
2710
|
+
consola.warn(`Remote config unavailable \u2014 using fallback. ${e2.message}`);
|
|
2711
|
+
process.exit(EXIT_CODES.REMOTE_FETCH_FAILED);
|
|
2712
|
+
}
|
|
2713
|
+
if (e2 instanceof TargetParseError) {
|
|
2714
|
+
if (json)
|
|
2715
|
+
writeJsonError(command, EXIT_CODES.CONFIG_ERROR, e2.message, "Check target format: {region}-{product}-{platform}-{environment}");
|
|
2716
|
+
consola.fatal(e2.message);
|
|
2717
|
+
process.exit(EXIT_CODES.CONFIG_ERROR);
|
|
2718
|
+
}
|
|
2719
|
+
if (e2 instanceof ConfigError || e2 instanceof ManifestError) {
|
|
2720
|
+
if (json)
|
|
2721
|
+
writeJsonError(command, EXIT_CODES.CONFIG_ERROR, e2.message, "Run daas init first.");
|
|
2722
|
+
consola.fatal(e2.message);
|
|
2723
|
+
process.exit(EXIT_CODES.CONFIG_ERROR);
|
|
2724
|
+
}
|
|
2725
|
+
consola.fatal(e2);
|
|
2726
|
+
process.exit(EXIT_CODES.GENERAL_ERROR);
|
|
2727
|
+
}
|
|
2728
|
+
|
|
2729
|
+
// src/commands/info.ts
|
|
2730
|
+
import { createLogger as createLogger3, setLogger as setLogger3, apiTransport as apiTransport3 } from "@chrisluyi/logger";
|
|
2701
2731
|
|
|
2702
2732
|
// src/init/monorepo.ts
|
|
2703
2733
|
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
|
|
2704
|
-
import { resolve as resolve4
|
|
2734
|
+
import { dirname, resolve as resolve4 } from "path";
|
|
2705
2735
|
function detectMonorepo(startDir) {
|
|
2706
2736
|
let dir = startDir;
|
|
2707
2737
|
for (let i2 = 0;i2 < 10; i2++) {
|
|
@@ -2727,7 +2757,11 @@ function detectMonorepo(startDir) {
|
|
|
2727
2757
|
var infoCommand = defineCommand({
|
|
2728
2758
|
meta: { name: "info", description: "Show resolved MFE project state" },
|
|
2729
2759
|
args: {
|
|
2730
|
-
json: {
|
|
2760
|
+
json: {
|
|
2761
|
+
type: "boolean",
|
|
2762
|
+
default: false,
|
|
2763
|
+
description: "Machine-readable JSON output"
|
|
2764
|
+
}
|
|
2731
2765
|
},
|
|
2732
2766
|
async run({ args }) {
|
|
2733
2767
|
const json = args.json;
|
|
@@ -2735,6 +2769,7 @@ var infoCommand = defineCommand({
|
|
|
2735
2769
|
let manifest;
|
|
2736
2770
|
try {
|
|
2737
2771
|
daasConfig = readDaasConfig();
|
|
2772
|
+
setLogger3(createLogger3([consolaTransport(), apiTransport3(daasConfig.logUrl)]));
|
|
2738
2773
|
manifest = readManifest();
|
|
2739
2774
|
} catch (e2) {
|
|
2740
2775
|
if (json)
|
|
@@ -2766,6 +2801,9 @@ var infoCommand = defineCommand({
|
|
|
2766
2801
|
});
|
|
2767
2802
|
|
|
2768
2803
|
// src/commands/init.ts
|
|
2804
|
+
import { existsSync as existsSync6, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "fs";
|
|
2805
|
+
import { createRequire } from "module";
|
|
2806
|
+
import { resolve as resolve6 } from "path";
|
|
2769
2807
|
import { scaffold } from "@chrisluyi/template";
|
|
2770
2808
|
|
|
2771
2809
|
// ../../node_modules/.bun/@clack+core@0.3.5/node_modules/@clack/core/dist/index.mjs
|
|
@@ -3258,12 +3296,8 @@ var de = () => {
|
|
|
3258
3296
|
return process.on("uncaughtExceptionMonitor", () => $2(2)), process.on("unhandledRejection", () => $2(2)), process.on("SIGINT", () => $2(1)), process.on("SIGTERM", () => $2(1)), process.on("exit", $2), { start: l3, stop: u3, message: m3 };
|
|
3259
3297
|
};
|
|
3260
3298
|
|
|
3261
|
-
// src/commands/init.ts
|
|
3262
|
-
import { existsSync as existsSync6, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "fs";
|
|
3263
|
-
import { resolve as resolve6 } from "path";
|
|
3264
|
-
|
|
3265
3299
|
// src/init/copy-template.ts
|
|
3266
|
-
import { existsSync as existsSync4,
|
|
3300
|
+
import { copyFileSync, existsSync as existsSync4, mkdirSync, readdirSync } from "fs";
|
|
3267
3301
|
import { dirname as dirname2, join } from "path";
|
|
3268
3302
|
import { fileURLToPath } from "url";
|
|
3269
3303
|
var __dirname2 = dirname2(fileURLToPath(import.meta.url));
|
|
@@ -3280,7 +3314,9 @@ async function copyTemplate(destDir) {
|
|
|
3280
3314
|
mkdirSync(join(destDir, "src"), { recursive: true });
|
|
3281
3315
|
}
|
|
3282
3316
|
if (existsSync4(dest)) {
|
|
3283
|
-
const overwrite = await se({
|
|
3317
|
+
const overwrite = await se({
|
|
3318
|
+
message: `${destFile} already exists. Overwrite?`
|
|
3319
|
+
});
|
|
3284
3320
|
if (!overwrite) {
|
|
3285
3321
|
result.skipped.push(destFile);
|
|
3286
3322
|
continue;
|
|
@@ -3293,7 +3329,7 @@ async function copyTemplate(destDir) {
|
|
|
3293
3329
|
}
|
|
3294
3330
|
|
|
3295
3331
|
// src/init/package-json.ts
|
|
3296
|
-
import {
|
|
3332
|
+
import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
|
|
3297
3333
|
import { resolve as resolve5 } from "path";
|
|
3298
3334
|
function updatePackageJson(cwd, opts) {
|
|
3299
3335
|
const pkgPath = resolve5(cwd, "package.json");
|
|
@@ -3304,6 +3340,17 @@ function updatePackageJson(cwd, opts) {
|
|
|
3304
3340
|
build: "daas build",
|
|
3305
3341
|
test: "daas test"
|
|
3306
3342
|
};
|
|
3343
|
+
pkg.dependencies = {
|
|
3344
|
+
...pkg.dependencies ?? {},
|
|
3345
|
+
"@radix-ui/react-tabs": "^1.1.0",
|
|
3346
|
+
...opts.isFullTemplate ? {
|
|
3347
|
+
"@chrisluyi/template": `^${opts.templateVersion ?? opts.cliVersion ?? "1.0.0"}`,
|
|
3348
|
+
"@tanstack/react-query": "^5.0.0",
|
|
3349
|
+
zustand: "^5.0.0",
|
|
3350
|
+
immer: "^10.0.0",
|
|
3351
|
+
zod: "^3.23.0"
|
|
3352
|
+
} : {}
|
|
3353
|
+
};
|
|
3307
3354
|
if (!opts.isMonorepo) {
|
|
3308
3355
|
pkg.devDependencies = {
|
|
3309
3356
|
...pkg.devDependencies ?? {},
|
|
@@ -3311,7 +3358,7 @@ function updatePackageJson(cwd, opts) {
|
|
|
3311
3358
|
};
|
|
3312
3359
|
}
|
|
3313
3360
|
pkg.daas = { configUrl: opts.configUrl, port: opts.port };
|
|
3314
|
-
writeFileSync2(pkgPath, JSON.stringify(pkg, null, 2)
|
|
3361
|
+
writeFileSync2(pkgPath, `${JSON.stringify(pkg, null, 2)}
|
|
3315
3362
|
`);
|
|
3316
3363
|
}
|
|
3317
3364
|
|
|
@@ -3320,7 +3367,10 @@ var KNOWN_TEMPLATES = ["default"];
|
|
|
3320
3367
|
var initCommand = defineCommand({
|
|
3321
3368
|
meta: { name: "init", description: "Scaffold a new MFE app" },
|
|
3322
3369
|
args: {
|
|
3323
|
-
template: {
|
|
3370
|
+
template: {
|
|
3371
|
+
type: "string",
|
|
3372
|
+
description: "Template name. Use 'default' for the full services/containers/components structure."
|
|
3373
|
+
}
|
|
3324
3374
|
},
|
|
3325
3375
|
async run({ args }) {
|
|
3326
3376
|
if (!process.stdin.isTTY) {
|
|
@@ -3364,7 +3414,9 @@ var initCommand = defineCommand({
|
|
|
3364
3414
|
appName,
|
|
3365
3415
|
onConflict: async (relPath) => {
|
|
3366
3416
|
s2.stop("");
|
|
3367
|
-
const overwrite = await se({
|
|
3417
|
+
const overwrite = await se({
|
|
3418
|
+
message: `${relPath} already exists. Overwrite?`
|
|
3419
|
+
});
|
|
3368
3420
|
s2.start(`Scaffolding ${appName}...`);
|
|
3369
3421
|
return overwrite;
|
|
3370
3422
|
}
|
|
@@ -3380,11 +3432,17 @@ var initCommand = defineCommand({
|
|
|
3380
3432
|
s2.message(`\u2713 Created ${f4}`);
|
|
3381
3433
|
for (const f4 of skipped)
|
|
3382
3434
|
s2.message(`\u2014 Skipped ${f4} (kept existing)`);
|
|
3383
|
-
updatePackageJson(cwd, {
|
|
3435
|
+
updatePackageJson(cwd, {
|
|
3436
|
+
configUrl,
|
|
3437
|
+
port,
|
|
3438
|
+
isMonorepo,
|
|
3439
|
+
isFullTemplate: useFullTemplate,
|
|
3440
|
+
templateVersion: getTemplateVersion()
|
|
3441
|
+
});
|
|
3384
3442
|
s2.message("\u2713 Updated package.json");
|
|
3385
3443
|
if (hasExtraExposes) {
|
|
3386
3444
|
const manifest = { name: appName, exposes: { "./App": "./src/App" } };
|
|
3387
|
-
writeFileSync3(resolve6(cwd, "mf.manifest.json"), JSON.stringify(manifest, null, 2)
|
|
3445
|
+
writeFileSync3(resolve6(cwd, "mf.manifest.json"), `${JSON.stringify(manifest, null, 2)}
|
|
3388
3446
|
`);
|
|
3389
3447
|
s2.message("\u2713 Created mf.manifest.json (add extra exposes as needed)");
|
|
3390
3448
|
}
|
|
@@ -3392,6 +3450,15 @@ var initCommand = defineCommand({
|
|
|
3392
3450
|
$e(isMonorepo ? "Run: daas dev" : "Run: bun install && daas dev");
|
|
3393
3451
|
}
|
|
3394
3452
|
});
|
|
3453
|
+
function getTemplateVersion() {
|
|
3454
|
+
try {
|
|
3455
|
+
const req = createRequire(import.meta.url);
|
|
3456
|
+
const pkg = req("@chrisluyi/template/package.json");
|
|
3457
|
+
return pkg.version ?? "1.0.0";
|
|
3458
|
+
} catch {
|
|
3459
|
+
return "1.0.0";
|
|
3460
|
+
}
|
|
3461
|
+
}
|
|
3395
3462
|
function getPackageName(cwd) {
|
|
3396
3463
|
const pkgPath = resolve6(cwd, "package.json");
|
|
3397
3464
|
if (!existsSync6(pkgPath))
|
|
@@ -3404,7 +3471,49 @@ function getPackageName(cwd) {
|
|
|
3404
3471
|
}
|
|
3405
3472
|
}
|
|
3406
3473
|
|
|
3474
|
+
// src/commands/test.ts
|
|
3475
|
+
import { createVitestConfig } from "@chrisluyi/rsbuild-config/vitest";
|
|
3476
|
+
import { createLogger as createLogger4, setLogger as setLogger4, apiTransport as apiTransport4 } from "@chrisluyi/logger";
|
|
3477
|
+
import { startVitest } from "vitest/node";
|
|
3478
|
+
var testCommand = defineCommand({
|
|
3479
|
+
meta: { name: "test", description: "Run MFE tests" },
|
|
3480
|
+
args: {
|
|
3481
|
+
json: {
|
|
3482
|
+
type: "boolean",
|
|
3483
|
+
default: false,
|
|
3484
|
+
description: "Machine-readable JSON output"
|
|
3485
|
+
}
|
|
3486
|
+
},
|
|
3487
|
+
async run({ args }) {
|
|
3488
|
+
const json = args.json;
|
|
3489
|
+
try {
|
|
3490
|
+
const manifest = readManifest();
|
|
3491
|
+
const daasConfig = readDaasConfig();
|
|
3492
|
+
setLogger4(createLogger4([consolaTransport(), apiTransport4(daasConfig.logUrl)]));
|
|
3493
|
+
const config = createVitestConfig(manifest, {
|
|
3494
|
+
coverage: daasConfig.coverage,
|
|
3495
|
+
setupFiles: daasConfig.setupFiles
|
|
3496
|
+
});
|
|
3497
|
+
const vitest = await startVitest("test", [], config);
|
|
3498
|
+
const failed = vitest?.state.getFiles().some((f4) => f4.result?.state === "fail") ?? false;
|
|
3499
|
+
if (json) {
|
|
3500
|
+
if (failed)
|
|
3501
|
+
writeJsonError("test", EXIT_CODES.GENERAL_ERROR, "Tests failed", "Check test output above");
|
|
3502
|
+
writeJsonSuccess("test", { appName: manifest.name, passed: !failed });
|
|
3503
|
+
}
|
|
3504
|
+
if (failed)
|
|
3505
|
+
process.exit(EXIT_CODES.GENERAL_ERROR);
|
|
3506
|
+
} catch (e3) {
|
|
3507
|
+
if (json)
|
|
3508
|
+
writeJsonError("test", EXIT_CODES.GENERAL_ERROR, e3.message, "Check test configuration");
|
|
3509
|
+
consola.fatal(e3);
|
|
3510
|
+
process.exit(EXIT_CODES.GENERAL_ERROR);
|
|
3511
|
+
}
|
|
3512
|
+
}
|
|
3513
|
+
});
|
|
3514
|
+
|
|
3407
3515
|
// src/index.ts
|
|
3516
|
+
setLogger5(createLogger5([consolaTransport()]));
|
|
3408
3517
|
var main = defineCommand({
|
|
3409
3518
|
meta: {
|
|
3410
3519
|
name: "daas",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chrisluyi/daas-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"daas": "./dist/index.js"
|
|
@@ -16,11 +16,12 @@
|
|
|
16
16
|
"skill.md"
|
|
17
17
|
],
|
|
18
18
|
"scripts": {
|
|
19
|
-
"build": "bun build src/index.ts --outfile dist/index.js.tmp --target bun --external @rspack/core --external @rspack/lite-tapable --external @rsbuild/core --external @rsbuild/plugin-react --external @module-federation/rsbuild-plugin --external vitest --external @vitest/browser --external @vitest/ui --external tapable --external react-router-dom --external lightningcss --external @chrisluyi/template --external @chrisluyi/rsbuild-config && printf '%s\\n' '#!/usr/bin/env bun' | cat - dist/index.js.tmp > dist/index.js && rm dist/index.js.tmp && chmod +x dist/index.js && bun build src/test.ts --outfile dist/test.js --target bun --external vitest --external @testing-library/react --external @testing-library/user-event --external @chrisluyi/rsbuild-config",
|
|
19
|
+
"build": "bun build src/index.ts --outfile dist/index.js.tmp --target bun --external @rspack/core --external @rspack/lite-tapable --external @rsbuild/core --external @rsbuild/plugin-react --external @module-federation/rsbuild-plugin --external vitest --external @vitest/browser --external @vitest/ui --external tapable --external react-router-dom --external lightningcss --external @chrisluyi/template --external @chrisluyi/logger --external @chrisluyi/rsbuild-config && printf '%s\\n' '#!/usr/bin/env bun' | cat - dist/index.js.tmp > dist/index.js && rm dist/index.js.tmp && chmod +x dist/index.js && bun build src/test.ts --outfile dist/test.js --target bun --external vitest --external @testing-library/react --external @testing-library/user-event --external @chrisluyi/rsbuild-config",
|
|
20
20
|
"test": "bun test --ignore 'templates/**'"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@clack/prompts": "^0.7.0",
|
|
24
|
+
"@chrisluyi/logger": "workspace:*",
|
|
24
25
|
"@chrisluyi/rsbuild-config": "workspace:*",
|
|
25
26
|
"@chrisluyi/template": "workspace:*",
|
|
26
27
|
"@rsbuild/core": "^1.0.0",
|
|
@@ -31,6 +32,11 @@
|
|
|
31
32
|
"devDependencies": {
|
|
32
33
|
"typescript": "^5.5.0"
|
|
33
34
|
},
|
|
35
|
+
"repository": {
|
|
36
|
+
"type": "git",
|
|
37
|
+
"url": "https://github.com/Chris-LuYi/daas-cli",
|
|
38
|
+
"directory": "packages/cli"
|
|
39
|
+
},
|
|
34
40
|
"publishConfig": {
|
|
35
41
|
"access": "public"
|
|
36
42
|
}
|
package/skill.md
CHANGED
|
@@ -96,13 +96,60 @@ src/
|
|
|
96
96
|
components/App.tsx ← presentational component
|
|
97
97
|
containers/AppContainer.tsx ← data/business logic wrapper
|
|
98
98
|
services/index.ts ← data fetching / API calls
|
|
99
|
+
flows/ ← multi-step flows (optional — add when needed)
|
|
100
|
+
<name>/
|
|
101
|
+
types.ts ← TData interface
|
|
102
|
+
index.ts ← createFlow<TData>(...)
|
|
103
|
+
steps/ ← step components (useFlowData / useFlowActions)
|
|
99
104
|
config/
|
|
100
105
|
regions/default.ts ← region config layer
|
|
101
106
|
platforms/default.ts ← platform config layer
|
|
102
107
|
products/default.ts ← product config layer
|
|
103
108
|
```
|
|
104
109
|
|
|
110
|
+
## Template Runtime (`@chrisluyi/template/runtime`)
|
|
111
|
+
|
|
112
|
+
Key utilities available in MFE components:
|
|
113
|
+
|
|
114
|
+
| Export | Purpose |
|
|
115
|
+
|---|---|
|
|
116
|
+
| `createApiClient` | Region-aware HTTP client (auto-injects X-Region-Id, X-Locale headers) |
|
|
117
|
+
| `createService` | React Query data fetching with Zod validation |
|
|
118
|
+
| `createStore` | Zustand UI state (per-module singleton) |
|
|
119
|
+
| `createForm` | Zod-validated form with regional widget injection |
|
|
120
|
+
| `createFlow` | Router-agnostic multi-step flow engine |
|
|
121
|
+
| `FlowEngine` | Component wrapper — renders current step automatically |
|
|
122
|
+
| `useFlow` | Hook — use when you need a custom layout (progress bar etc.) |
|
|
123
|
+
| `useFlowData` | Step hook — read/write the shared typed data bag |
|
|
124
|
+
| `useFlowActions` | Step hook — `next()`, `back()`, `isFirst`, `isLast` |
|
|
125
|
+
| `useRegional` | Access the full `RegionalRegistry` from any component |
|
|
126
|
+
|
|
127
|
+
### Flow SDK quick reference
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
// Define
|
|
131
|
+
const myFlow = createFlow<MyData>({
|
|
132
|
+
id: "MyFlow",
|
|
133
|
+
steps: [{ id: "step1", component: Step1 }, { id: "step2", component: Step2 }],
|
|
134
|
+
initialData: {},
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
// Mount
|
|
138
|
+
const registry = useRegional()
|
|
139
|
+
return <FlowEngine flow={myFlow} registry={registry} />
|
|
140
|
+
|
|
141
|
+
// Inside a step — no props needed
|
|
142
|
+
const { data, setData } = useFlowData<MyData>()
|
|
143
|
+
const { next, back, isLast } = useFlowActions()
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Regional step injection via `RegionalRegistry.flows?`:
|
|
147
|
+
```ts
|
|
148
|
+
createRegistry(defaultRegistry, {
|
|
149
|
+
flows: { MyFlow: { extraSteps: [{ after: "step1", id: "extra", component: ExtraStep }] } }
|
|
150
|
+
})
|
|
151
|
+
```
|
|
152
|
+
|
|
105
153
|
## Roadmap (do not suggest these — not yet implemented)
|
|
106
154
|
|
|
107
|
-
- v1.5: `daas dev sg-foo-mb-dev` target strings for multi-region builds
|
|
108
155
|
- v2+: `daas lint` — validates project structure against template conventions
|