@chrisluyi/daas-cli 1.0.0 → 1.2.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/daas-bin +0 -0
- package/dist/index.js +107 -90
- package/dist/test.js +3 -0
- package/package.json +7 -2
- package/skill.md +21 -2
package/dist/daas-bin
ADDED
|
Binary file
|
package/dist/index.js
CHANGED
|
@@ -2313,57 +2313,7 @@ async function runMain(cmd, opts = {}) {
|
|
|
2313
2313
|
|
|
2314
2314
|
// src/commands/dev.ts
|
|
2315
2315
|
import { createRsbuild } from "@rsbuild/core";
|
|
2316
|
-
|
|
2317
|
-
// ../rsbuild-config/dist/index.js
|
|
2318
|
-
import { mergeRsbuildConfig } from "@rsbuild/core";
|
|
2319
|
-
|
|
2320
|
-
// ../rsbuild-config/dist/defaults.js
|
|
2321
|
-
var SUPPORTED_CONFIG_VERSION = 1;
|
|
2322
|
-
function getDefaults(mode) {
|
|
2323
|
-
return {
|
|
2324
|
-
output: {
|
|
2325
|
-
distPath: { root: "dist" },
|
|
2326
|
-
cleanDistPath: mode === "production"
|
|
2327
|
-
},
|
|
2328
|
-
performance: mode === "production" ? { chunkSplit: { strategy: "split-by-experience" } } : undefined
|
|
2329
|
-
};
|
|
2330
|
-
}
|
|
2331
|
-
|
|
2332
|
-
// ../rsbuild-config/dist/plugins/react.js
|
|
2333
|
-
import { pluginReact } from "@rsbuild/plugin-react";
|
|
2334
|
-
function getReactPlugin() {
|
|
2335
|
-
return pluginReact();
|
|
2336
|
-
}
|
|
2337
|
-
|
|
2338
|
-
// ../rsbuild-config/dist/plugins/mf2.js
|
|
2339
|
-
import { pluginModuleFederation } from "@module-federation/rsbuild-plugin";
|
|
2340
|
-
function getMF2Plugin(manifest, remoteMeta) {
|
|
2341
|
-
return pluginModuleFederation({
|
|
2342
|
-
name: manifest.name,
|
|
2343
|
-
filename: "remoteEntry.js",
|
|
2344
|
-
exposes: manifest.exposes,
|
|
2345
|
-
shared: buildShared(remoteMeta.shared)
|
|
2346
|
-
});
|
|
2347
|
-
}
|
|
2348
|
-
function buildShared(shared) {
|
|
2349
|
-
return Object.fromEntries(Object.entries(shared).map(([pkg, version]) => [
|
|
2350
|
-
pkg,
|
|
2351
|
-
{
|
|
2352
|
-
singleton: true,
|
|
2353
|
-
requiredVersion: version,
|
|
2354
|
-
eager: pkg === "react" || pkg === "react-dom"
|
|
2355
|
-
}
|
|
2356
|
-
]));
|
|
2357
|
-
}
|
|
2358
|
-
|
|
2359
|
-
// ../rsbuild-config/dist/index.js
|
|
2360
|
-
function createConfig(manifest, remoteMeta, options) {
|
|
2361
|
-
const { mode, port } = options;
|
|
2362
|
-
return mergeRsbuildConfig(getDefaults(mode), {
|
|
2363
|
-
server: port ? { port } : undefined,
|
|
2364
|
-
plugins: [getReactPlugin(), getMF2Plugin(manifest, remoteMeta)]
|
|
2365
|
-
});
|
|
2366
|
-
}
|
|
2316
|
+
import { createConfig } from "@chrisluyi/rsbuild-config";
|
|
2367
2317
|
|
|
2368
2318
|
// src/daas-config.ts
|
|
2369
2319
|
import { readFileSync, existsSync } from "fs";
|
|
@@ -2388,7 +2338,8 @@ function readDaasConfig(cwd = process.cwd()) {
|
|
|
2388
2338
|
return {
|
|
2389
2339
|
configUrl: daas.configUrl,
|
|
2390
2340
|
port: daas.port ?? 3000,
|
|
2391
|
-
coverage: daas.coverage
|
|
2341
|
+
coverage: daas.coverage,
|
|
2342
|
+
setupFiles: daas.setupFiles
|
|
2392
2343
|
};
|
|
2393
2344
|
}
|
|
2394
2345
|
|
|
@@ -2435,6 +2386,9 @@ function normalizeManifest(raw, cwd) {
|
|
|
2435
2386
|
function stripScope(name) {
|
|
2436
2387
|
return name.replace(/^@[^/]+\//, "");
|
|
2437
2388
|
}
|
|
2389
|
+
|
|
2390
|
+
// src/remote-config.ts
|
|
2391
|
+
import { SUPPORTED_CONFIG_VERSION } from "@chrisluyi/rsbuild-config";
|
|
2438
2392
|
// src/fallback-config.json
|
|
2439
2393
|
var fallback_config_default = {
|
|
2440
2394
|
version: "1.0.0",
|
|
@@ -2518,6 +2472,42 @@ function meetsMinVersion(current, min) {
|
|
|
2518
2472
|
return cPatch >= mPatch;
|
|
2519
2473
|
}
|
|
2520
2474
|
|
|
2475
|
+
// src/target.ts
|
|
2476
|
+
import { writeFileSync } from "fs";
|
|
2477
|
+
import { resolve as resolve3 } from "path";
|
|
2478
|
+
|
|
2479
|
+
class TargetParseError extends Error {
|
|
2480
|
+
constructor(message) {
|
|
2481
|
+
super(message);
|
|
2482
|
+
this.name = "TargetParseError";
|
|
2483
|
+
}
|
|
2484
|
+
}
|
|
2485
|
+
function parseTarget(str) {
|
|
2486
|
+
const parts = str.split("-");
|
|
2487
|
+
if (parts.length < 4) {
|
|
2488
|
+
throw new TargetParseError(`Invalid target "${str}". Expected format: {region}-{product}-{platform}-{environment} (e.g. sg-foo-mb-dev)`);
|
|
2489
|
+
}
|
|
2490
|
+
const region = parts[0];
|
|
2491
|
+
const environment = parts[parts.length - 1];
|
|
2492
|
+
const platform2 = parts[parts.length - 2];
|
|
2493
|
+
const product = parts.slice(1, parts.length - 2).join("-");
|
|
2494
|
+
return { region, product, platform: platform2, environment };
|
|
2495
|
+
}
|
|
2496
|
+
function generateTsconfigDaas(cwd, target) {
|
|
2497
|
+
const content = {
|
|
2498
|
+
extends: "./tsconfig.json",
|
|
2499
|
+
compilerOptions: {
|
|
2500
|
+
paths: {
|
|
2501
|
+
"@region-config": [`./src/config/regions/${target.region}`],
|
|
2502
|
+
"@platform-config": [`./src/config/platforms/${target.platform}`],
|
|
2503
|
+
"@product-config": [`./src/config/products/${target.product}`]
|
|
2504
|
+
}
|
|
2505
|
+
}
|
|
2506
|
+
};
|
|
2507
|
+
writeFileSync(resolve3(cwd, "tsconfig.daas.json"), JSON.stringify(content, null, 2) + `
|
|
2508
|
+
`);
|
|
2509
|
+
}
|
|
2510
|
+
|
|
2521
2511
|
// src/output.ts
|
|
2522
2512
|
function formatSuccess(command, data) {
|
|
2523
2513
|
return { ok: true, command, cliVersion: getCliVersion(), ...data };
|
|
@@ -2552,6 +2542,7 @@ var EXIT_CODES = {
|
|
|
2552
2542
|
var devCommand = defineCommand({
|
|
2553
2543
|
meta: { name: "dev", description: "Start MFE dev server" },
|
|
2554
2544
|
args: {
|
|
2545
|
+
target: { type: "positional", description: "Build target (e.g. sg-foo-mb-dev)", required: false },
|
|
2555
2546
|
port: { type: "string", description: "Override dev server port" },
|
|
2556
2547
|
json: { type: "boolean", default: false, description: "Machine-readable JSON output" }
|
|
2557
2548
|
},
|
|
@@ -2566,7 +2557,12 @@ var devCommand = defineCommand({
|
|
|
2566
2557
|
consola.warn("Config version mismatch \u2014 update daas-cli for full compatibility");
|
|
2567
2558
|
}
|
|
2568
2559
|
const port = args.port ? Number(args.port) : daasConfig.port;
|
|
2569
|
-
const
|
|
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 });
|
|
2570
2566
|
consola.start(`Starting ${manifest.name} dev server...`);
|
|
2571
2567
|
const rsbuild = await createRsbuild({ rsbuildConfig: config });
|
|
2572
2568
|
const server = await rsbuild.createDevServer();
|
|
@@ -2590,6 +2586,12 @@ function handleError(command, e2, json) {
|
|
|
2590
2586
|
consola.warn(`Remote config unavailable \u2014 using fallback. ${e2.message}`);
|
|
2591
2587
|
process.exit(EXIT_CODES.REMOTE_FETCH_FAILED);
|
|
2592
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
|
+
}
|
|
2593
2595
|
if (e2 instanceof ConfigError || e2 instanceof ManifestError) {
|
|
2594
2596
|
if (json)
|
|
2595
2597
|
writeJsonError(command, EXIT_CODES.CONFIG_ERROR, e2.message, "Run daas init first.");
|
|
@@ -2602,9 +2604,11 @@ function handleError(command, e2, json) {
|
|
|
2602
2604
|
|
|
2603
2605
|
// src/commands/build.ts
|
|
2604
2606
|
import { createRsbuild as createRsbuild2 } from "@rsbuild/core";
|
|
2607
|
+
import { createConfig as createConfig2 } from "@chrisluyi/rsbuild-config";
|
|
2605
2608
|
var buildCommand = defineCommand({
|
|
2606
2609
|
meta: { name: "build", description: "Build MFE for production" },
|
|
2607
2610
|
args: {
|
|
2611
|
+
target: { type: "positional", description: "Build target (e.g. sg-foo-mb-prod)", required: false },
|
|
2608
2612
|
json: { type: "boolean", default: false, description: "Machine-readable JSON output" }
|
|
2609
2613
|
},
|
|
2610
2614
|
async run({ args }) {
|
|
@@ -2617,7 +2621,10 @@ var buildCommand = defineCommand({
|
|
|
2617
2621
|
const remoteMeta = await fetchRemoteConfig(daasConfig.configUrl, true);
|
|
2618
2622
|
checkCliVersion(remoteMeta);
|
|
2619
2623
|
checkConfigVersion(remoteMeta, true);
|
|
2620
|
-
const
|
|
2624
|
+
const target = args.target ? parseTarget(args.target) : undefined;
|
|
2625
|
+
if (target)
|
|
2626
|
+
generateTsconfigDaas(process.cwd(), target);
|
|
2627
|
+
const config = createConfig2(manifest, remoteMeta, { mode: "production", target });
|
|
2621
2628
|
const rsbuild = await createRsbuild2({ rsbuildConfig: config });
|
|
2622
2629
|
await rsbuild.build();
|
|
2623
2630
|
if (json)
|
|
@@ -2642,6 +2649,12 @@ var buildCommand = defineCommand({
|
|
|
2642
2649
|
consola.fatal(e2.message);
|
|
2643
2650
|
process.exit(EXIT_CODES.CONFIG_VERSION_MISMATCH);
|
|
2644
2651
|
}
|
|
2652
|
+
if (e2 instanceof TargetParseError) {
|
|
2653
|
+
if (json)
|
|
2654
|
+
writeJsonError("build", EXIT_CODES.CONFIG_ERROR, e2.message, "Check target format: {region}-{product}-{platform}-{environment}");
|
|
2655
|
+
consola.fatal(e2.message);
|
|
2656
|
+
process.exit(EXIT_CODES.CONFIG_ERROR);
|
|
2657
|
+
}
|
|
2645
2658
|
if (e2 instanceof ConfigError || e2 instanceof ManifestError) {
|
|
2646
2659
|
if (json)
|
|
2647
2660
|
writeJsonError("build", EXIT_CODES.CONFIG_ERROR, e2.message, "Run daas init first.");
|
|
@@ -2656,27 +2669,7 @@ var buildCommand = defineCommand({
|
|
|
2656
2669
|
|
|
2657
2670
|
// src/commands/test.ts
|
|
2658
2671
|
import { startVitest } from "vitest/node";
|
|
2659
|
-
|
|
2660
|
-
// ../rsbuild-config/dist/vitest.js
|
|
2661
|
-
import { resolve as resolve3, dirname } from "path";
|
|
2662
|
-
import { fileURLToPath } from "url";
|
|
2663
|
-
var __dirname2 = dirname(fileURLToPath(import.meta.url));
|
|
2664
|
-
function createVitestConfig(manifest, options = {}) {
|
|
2665
|
-
return {
|
|
2666
|
-
test: {
|
|
2667
|
-
name: manifest.name,
|
|
2668
|
-
environment: "happy-dom",
|
|
2669
|
-
setupFiles: [resolve3(__dirname2, "test-setup.js")],
|
|
2670
|
-
coverage: {
|
|
2671
|
-
provider: "v8",
|
|
2672
|
-
reporter: ["text", "lcov"],
|
|
2673
|
-
thresholds: options.coverage ?? undefined
|
|
2674
|
-
}
|
|
2675
|
-
}
|
|
2676
|
-
};
|
|
2677
|
-
}
|
|
2678
|
-
|
|
2679
|
-
// src/commands/test.ts
|
|
2672
|
+
import { createVitestConfig } from "@chrisluyi/rsbuild-config/vitest";
|
|
2680
2673
|
var testCommand = defineCommand({
|
|
2681
2674
|
meta: { name: "test", description: "Run MFE tests" },
|
|
2682
2675
|
args: {
|
|
@@ -2687,7 +2680,7 @@ var testCommand = defineCommand({
|
|
|
2687
2680
|
try {
|
|
2688
2681
|
const manifest = readManifest();
|
|
2689
2682
|
const daasConfig = readDaasConfig();
|
|
2690
|
-
const config = createVitestConfig(manifest, { coverage: daasConfig.coverage });
|
|
2683
|
+
const config = createVitestConfig(manifest, { coverage: daasConfig.coverage, setupFiles: daasConfig.setupFiles });
|
|
2691
2684
|
const vitest = await startVitest("test", [], config);
|
|
2692
2685
|
const failed = vitest?.state.getFiles().some((f3) => f3.result?.state === "fail") ?? false;
|
|
2693
2686
|
if (json) {
|
|
@@ -2708,11 +2701,11 @@ var testCommand = defineCommand({
|
|
|
2708
2701
|
|
|
2709
2702
|
// src/init/monorepo.ts
|
|
2710
2703
|
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
|
|
2711
|
-
import { resolve as resolve4, dirname
|
|
2704
|
+
import { resolve as resolve4, dirname } from "path";
|
|
2712
2705
|
function detectMonorepo(startDir) {
|
|
2713
2706
|
let dir = startDir;
|
|
2714
2707
|
for (let i2 = 0;i2 < 10; i2++) {
|
|
2715
|
-
const parent =
|
|
2708
|
+
const parent = dirname(dir);
|
|
2716
2709
|
if (parent === dir)
|
|
2717
2710
|
break;
|
|
2718
2711
|
dir = parent;
|
|
@@ -2772,6 +2765,9 @@ var infoCommand = defineCommand({
|
|
|
2772
2765
|
}
|
|
2773
2766
|
});
|
|
2774
2767
|
|
|
2768
|
+
// src/commands/init.ts
|
|
2769
|
+
import { scaffold } from "@chrisluyi/template";
|
|
2770
|
+
|
|
2775
2771
|
// ../../node_modules/.bun/@clack+core@0.3.5/node_modules/@clack/core/dist/index.mjs
|
|
2776
2772
|
var import_sisteransi = __toESM(require_src(), 1);
|
|
2777
2773
|
var import_picocolors = __toESM(require_picocolors(), 1);
|
|
@@ -3263,15 +3259,15 @@ var de = () => {
|
|
|
3263
3259
|
};
|
|
3264
3260
|
|
|
3265
3261
|
// src/commands/init.ts
|
|
3266
|
-
import {
|
|
3262
|
+
import { existsSync as existsSync6, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "fs";
|
|
3267
3263
|
import { resolve as resolve6 } from "path";
|
|
3268
3264
|
|
|
3269
3265
|
// src/init/copy-template.ts
|
|
3270
3266
|
import { existsSync as existsSync4, copyFileSync, mkdirSync, readdirSync } from "fs";
|
|
3271
|
-
import { dirname as
|
|
3272
|
-
import { fileURLToPath
|
|
3273
|
-
var
|
|
3274
|
-
var TEMPLATES_DIR = join(
|
|
3267
|
+
import { dirname as dirname2, join } from "path";
|
|
3268
|
+
import { fileURLToPath } from "url";
|
|
3269
|
+
var __dirname2 = dirname2(fileURLToPath(import.meta.url));
|
|
3270
|
+
var TEMPLATES_DIR = join(__dirname2, "../../templates/mfe");
|
|
3275
3271
|
async function copyTemplate(destDir) {
|
|
3276
3272
|
const files = readdirSync(TEMPLATES_DIR);
|
|
3277
3273
|
const result = { copied: [], skipped: [] };
|
|
@@ -3297,7 +3293,7 @@ async function copyTemplate(destDir) {
|
|
|
3297
3293
|
}
|
|
3298
3294
|
|
|
3299
3295
|
// src/init/package-json.ts
|
|
3300
|
-
import { readFileSync as readFileSync4, writeFileSync, existsSync as existsSync5 } from "fs";
|
|
3296
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, existsSync as existsSync5 } from "fs";
|
|
3301
3297
|
import { resolve as resolve5 } from "path";
|
|
3302
3298
|
function updatePackageJson(cwd, opts) {
|
|
3303
3299
|
const pkgPath = resolve5(cwd, "package.json");
|
|
@@ -3315,24 +3311,27 @@ function updatePackageJson(cwd, opts) {
|
|
|
3315
3311
|
};
|
|
3316
3312
|
}
|
|
3317
3313
|
pkg.daas = { configUrl: opts.configUrl, port: opts.port };
|
|
3318
|
-
|
|
3314
|
+
writeFileSync2(pkgPath, JSON.stringify(pkg, null, 2) + `
|
|
3319
3315
|
`);
|
|
3320
3316
|
}
|
|
3321
3317
|
|
|
3322
3318
|
// src/commands/init.ts
|
|
3319
|
+
var KNOWN_TEMPLATES = ["default"];
|
|
3323
3320
|
var initCommand = defineCommand({
|
|
3324
3321
|
meta: { name: "init", description: "Scaffold a new MFE app" },
|
|
3325
3322
|
args: {
|
|
3326
|
-
template: { type: "string", description: "Template name
|
|
3323
|
+
template: { type: "string", description: "Template name. Use 'default' for the full services/containers/components structure." }
|
|
3327
3324
|
},
|
|
3328
3325
|
async run({ args }) {
|
|
3329
3326
|
if (!process.stdin.isTTY) {
|
|
3330
3327
|
consola.fatal("daas init requires an interactive terminal. Cannot run in non-TTY mode.");
|
|
3331
3328
|
process.exit(EXIT_CODES.CONFIG_ERROR);
|
|
3332
3329
|
}
|
|
3333
|
-
|
|
3334
|
-
|
|
3330
|
+
const templateName = args.template;
|
|
3331
|
+
if (templateName && !KNOWN_TEMPLATES.includes(templateName)) {
|
|
3332
|
+
consola.warn(`Unknown template "${templateName}". Available: ${KNOWN_TEMPLATES.join(", ")}. Falling back to minimal scaffold.`);
|
|
3335
3333
|
}
|
|
3334
|
+
const useFullTemplate = templateName === "default";
|
|
3336
3335
|
oe("daas-cli \u2014 scaffold new MFE");
|
|
3337
3336
|
const configUrl = await te({
|
|
3338
3337
|
message: "Remote config URL?",
|
|
@@ -3358,7 +3357,25 @@ var initCommand = defineCommand({
|
|
|
3358
3357
|
s2.start(`Scaffolding ${appName}...`);
|
|
3359
3358
|
const cwd = process.cwd();
|
|
3360
3359
|
const isMonorepo = detectMonorepo(cwd);
|
|
3361
|
-
|
|
3360
|
+
let copied;
|
|
3361
|
+
let skipped;
|
|
3362
|
+
if (useFullTemplate) {
|
|
3363
|
+
const result = await scaffold(cwd, {
|
|
3364
|
+
appName,
|
|
3365
|
+
onConflict: async (relPath) => {
|
|
3366
|
+
s2.stop("");
|
|
3367
|
+
const overwrite = await se({ message: `${relPath} already exists. Overwrite?` });
|
|
3368
|
+
s2.start(`Scaffolding ${appName}...`);
|
|
3369
|
+
return overwrite;
|
|
3370
|
+
}
|
|
3371
|
+
});
|
|
3372
|
+
copied = result.copied;
|
|
3373
|
+
skipped = result.skipped;
|
|
3374
|
+
} else {
|
|
3375
|
+
const result = await copyTemplate(cwd);
|
|
3376
|
+
copied = result.copied;
|
|
3377
|
+
skipped = result.skipped;
|
|
3378
|
+
}
|
|
3362
3379
|
for (const f4 of copied)
|
|
3363
3380
|
s2.message(`\u2713 Created ${f4}`);
|
|
3364
3381
|
for (const f4 of skipped)
|
|
@@ -3367,7 +3384,7 @@ var initCommand = defineCommand({
|
|
|
3367
3384
|
s2.message("\u2713 Updated package.json");
|
|
3368
3385
|
if (hasExtraExposes) {
|
|
3369
3386
|
const manifest = { name: appName, exposes: { "./App": "./src/App" } };
|
|
3370
|
-
|
|
3387
|
+
writeFileSync3(resolve6(cwd, "mf.manifest.json"), JSON.stringify(manifest, null, 2) + `
|
|
3371
3388
|
`);
|
|
3372
3389
|
s2.message("\u2713 Created mf.manifest.json (add extra exposes as needed)");
|
|
3373
3390
|
}
|
package/dist/test.js
ADDED
package/package.json
CHANGED
|
@@ -1,23 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chrisluyi/daas-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"daas": "./dist/index.js"
|
|
7
7
|
},
|
|
8
8
|
"main": "./dist/index.js",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": "./dist/index.js",
|
|
11
|
+
"./test": "./dist/test.js"
|
|
12
|
+
},
|
|
9
13
|
"files": [
|
|
10
14
|
"dist",
|
|
11
15
|
"templates",
|
|
12
16
|
"skill.md"
|
|
13
17
|
],
|
|
14
18
|
"scripts": {
|
|
15
|
-
"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 && 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",
|
|
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",
|
|
16
20
|
"test": "bun test --ignore 'templates/**'"
|
|
17
21
|
},
|
|
18
22
|
"dependencies": {
|
|
19
23
|
"@clack/prompts": "^0.7.0",
|
|
20
24
|
"@chrisluyi/rsbuild-config": "workspace:*",
|
|
25
|
+
"@chrisluyi/template": "workspace:*",
|
|
21
26
|
"@rsbuild/core": "^1.0.0",
|
|
22
27
|
"citty": "^0.1.6",
|
|
23
28
|
"consola": "^3.2.3",
|
package/skill.md
CHANGED
|
@@ -15,7 +15,8 @@ MFE apps intentionally have NO `rsbuild.config.ts`, NO `vitest.config.ts`. The C
|
|
|
15
15
|
|
|
16
16
|
| Command | Purpose |
|
|
17
17
|
|---|---|
|
|
18
|
-
| `daas init
|
|
18
|
+
| `daas init` | Interactive scaffold (minimal): creates App.tsx, App.test.tsx, tsconfig.json, updates package.json |
|
|
19
|
+
| `daas init --template default` | Full structure scaffold: creates services/containers/components/config layer folders |
|
|
19
20
|
| `daas dev [--port <n>] [--json]` | Start rsbuild dev server |
|
|
20
21
|
| `daas build [--json]` | Production build to ./dist |
|
|
21
22
|
| `daas test [--json]` | Run Vitest tests |
|
|
@@ -83,7 +84,25 @@ Remote URLs are **not configured here** — they are resolved dynamically at run
|
|
|
83
84
|
|
|
84
85
|
`daas-cli` is the only `devDependency` needed. It brings rsbuild, vitest, @testing-library/react, happy-dom, and all tooling as its own dependencies. Do not install these separately.
|
|
85
86
|
|
|
87
|
+
## `--template default` Folder Structure
|
|
88
|
+
|
|
89
|
+
When using `daas init --template default`, the scaffold creates:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
App.tsx ← MF2 entry point (exposes ./App)
|
|
93
|
+
App.test.tsx
|
|
94
|
+
tsconfig.json
|
|
95
|
+
src/
|
|
96
|
+
components/App.tsx ← presentational component
|
|
97
|
+
containers/AppContainer.tsx ← data/business logic wrapper
|
|
98
|
+
services/index.ts ← data fetching / API calls
|
|
99
|
+
config/
|
|
100
|
+
regions/default.ts ← region config layer
|
|
101
|
+
platforms/default.ts ← platform config layer
|
|
102
|
+
products/default.ts ← product config layer
|
|
103
|
+
```
|
|
104
|
+
|
|
86
105
|
## Roadmap (do not suggest these — not yet implemented)
|
|
87
106
|
|
|
88
107
|
- v1.5: `daas dev sg-foo-mb-dev` target strings for multi-region builds
|
|
89
|
-
- v2
|
|
108
|
+
- v2+: `daas lint` — validates project structure against template conventions
|