@multisystemsuite/create-mf-app 1.0.14 → 1.0.15
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 +18 -0
- package/dist/index.js +88 -46
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -303,9 +303,25 @@ npx create-mf-app <project-name> [options]
|
|
|
303
303
|
| `--federation=true\|false` | Module Federation (default: `true`) |
|
|
304
304
|
| `--control-plane` | Workflow Designer & Monitoring preset (6 apps + corelib, control-plane API, mf-* packages) |
|
|
305
305
|
| `--federation-os` | Full Enterprise Federation OS preset (10 apps + corelib, runtime, observability stack) |
|
|
306
|
+
| `--lite` | **Faster install** — skip ESLint/Vitest/Husky stack and optional SDK packages |
|
|
306
307
|
| `-y`, `--yes` | Non-interactive (use defaults where applicable) |
|
|
307
308
|
| `-h`, `--help` | Show help |
|
|
308
309
|
|
|
310
|
+
**Faster install (`--lite`):**
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
npx create-mf-app my-platform --type=parent --children=billing,orders --shared=corelib --lite -y
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
Skips ESLint, Prettier, Stylelint, Vitest, Husky, commitlint, and optional SDK packages (`api-client`, `sdk-core`, `websocket-sdk`). Federation, apps, `corelib`, and `query-client` are still included — typical install drops from ~850 to ~400 packages.
|
|
317
|
+
|
|
318
|
+
**Other ways to speed up install:**
|
|
319
|
+
|
|
320
|
+
- Exclude the project folder from Windows Defender real-time scan
|
|
321
|
+
- Second `npm install` is much faster (npm cache)
|
|
322
|
+
- Use `HUSKY=0 npm install` to skip git hooks on any scaffold
|
|
323
|
+
- Fewer `--children` = fewer apps = less to resolve
|
|
324
|
+
|
|
309
325
|
### Add a child to an existing parent workspace
|
|
310
326
|
|
|
311
327
|
```bash
|
|
@@ -1431,6 +1447,8 @@ Node 18 will fail on Vite 7 commands.
|
|
|
1431
1447
|
| `Cannot find module 'billing/App'` | Add federation `.d.ts` declarations in host |
|
|
1432
1448
|
| `Task not found: live-reload` | Root `"live-reload": "node live-reload.js"` |
|
|
1433
1449
|
| Vite binary missing after install | Clean reinstall (see below) |
|
|
1450
|
+
| **`npm install` very slow (~2 min+)** | Use `--lite` for faster scaffold; exclude project from antivirus scan; second install uses npm cache |
|
|
1451
|
+
| **`npm run local` fails on `api-client` build** | Update to latest CLI (smart-build skips source-only packages) or patch `smart-build.js` |
|
|
1434
1452
|
| Sidebar overlaps main content | Use generated flex sidebar in corelib |
|
|
1435
1453
|
| **Text invisible on dark header/sidebar** | Clear `localStorage` key `mf-enterprise-config`; hard refresh |
|
|
1436
1454
|
| `provider support react(undefined)` / `useState` null | Rebuild all apps after federation config change; host uses exact `version: "19.0.0"`, remotes use `requiredVersion: "^19.0.0"` |
|
package/dist/index.js
CHANGED
|
@@ -365,6 +365,17 @@ function writeCache(projectId, hash) {
|
|
|
365
365
|
fs.writeFileSync(cachePath(projectId), JSON.stringify({ hash, mode, at: Date.now() }, null, 2));
|
|
366
366
|
}
|
|
367
367
|
|
|
368
|
+
function hasBuildScript(projectRoot) {
|
|
369
|
+
const pkgPath = path.join(projectRoot, "package.json");
|
|
370
|
+
if (!fs.existsSync(pkgPath)) return false;
|
|
371
|
+
try {
|
|
372
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
373
|
+
return typeof pkg.scripts?.build === "string" && pkg.scripts.build.trim().length > 0;
|
|
374
|
+
} catch {
|
|
375
|
+
return false;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
368
379
|
function runBuild(projectId, root) {
|
|
369
380
|
return new Promise((resolve) => {
|
|
370
381
|
const npm = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
@@ -392,6 +403,12 @@ async function main() {
|
|
|
392
403
|
let order = topoSort(graph, onlyProjects);
|
|
393
404
|
if (!order.length) order = Object.keys(config.projects ?? {});
|
|
394
405
|
|
|
406
|
+
order = order.filter((projectId) => {
|
|
407
|
+
const meta = config.projects[projectId];
|
|
408
|
+
if (!meta?.root) return false;
|
|
409
|
+
return hasBuildScript(path.join(cwd, meta.root));
|
|
410
|
+
});
|
|
411
|
+
|
|
395
412
|
console.log("[smart-build] mode=" + mode + " projects=" + order.join(", "));
|
|
396
413
|
|
|
397
414
|
const waves = [];
|
|
@@ -414,6 +431,10 @@ async function main() {
|
|
|
414
431
|
const meta = config.projects[projectId];
|
|
415
432
|
if (!meta?.root) return;
|
|
416
433
|
const projectRoot = path.join(cwd, meta.root);
|
|
434
|
+
if (!hasBuildScript(projectRoot)) {
|
|
435
|
+
console.log("[skip] " + projectId + " (no build script \u2014 source-only workspace package)");
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
417
438
|
const hash = hashProject(projectRoot);
|
|
418
439
|
if (skipUnchanged) {
|
|
419
440
|
const cached = readCache(projectId);
|
|
@@ -3521,28 +3542,12 @@ function mergeAppTsconfigForQuality(existing) {
|
|
|
3521
3542
|
`;
|
|
3522
3543
|
}
|
|
3523
3544
|
var APP_QUALITY_DEV_DEPS = {
|
|
3524
|
-
vitest: "^3.0.5",
|
|
3525
|
-
"@vitest/coverage-v8": "^3.0.5",
|
|
3526
|
-
jsdom: "^25.0.1",
|
|
3527
|
-
"@testing-library/react": "^16.2.0",
|
|
3528
|
-
"@testing-library/jest-dom": "^6.6.3",
|
|
3529
|
-
"@testing-library/user-event": "^14.5.2",
|
|
3530
3545
|
"cross-env": "^7.0.3",
|
|
3531
3546
|
"rollup-plugin-visualizer": "^5.14.0",
|
|
3532
3547
|
"vite-plugin-compression": "^0.5.1"
|
|
3533
3548
|
};
|
|
3534
3549
|
var APP_QUALITY_SCRIPTS = {
|
|
3535
|
-
lint: "eslint src --ext .ts,.tsx --max-warnings 0",
|
|
3536
|
-
"lint:fix": "eslint src --ext .ts,.tsx --fix",
|
|
3537
|
-
format: 'prettier --write "src/**/*.{ts,tsx,css,json}"',
|
|
3538
|
-
"format:check": 'prettier --check "src/**/*.{ts,tsx,css,json}"',
|
|
3539
3550
|
"type-check": "tsc --noEmit -p tsconfig.json",
|
|
3540
|
-
test: "vitest",
|
|
3541
|
-
"test:ci": "vitest run",
|
|
3542
|
-
coverage: "vitest run --coverage",
|
|
3543
|
-
cleanup: "npm run lint:fix && npm run cleanup:imports && npm run type-check",
|
|
3544
|
-
"cleanup:imports": "npm run lint:fix",
|
|
3545
|
-
"cleanup:deadcode": "node ../../scripts/deadcode-scan-placeholder.js",
|
|
3546
3551
|
"build:prod": "tsc -b && vite build --mode prod",
|
|
3547
3552
|
analyze: "cross-env VITE_ANALYZE=1 tsc -b && vite build --mode prod"
|
|
3548
3553
|
};
|
|
@@ -14250,16 +14255,35 @@ export function invalidateCache(cwd) {
|
|
|
14250
14255
|
if (fs.existsSync(dir)) fs.rmSync(dir, { recursive: true, force: true });
|
|
14251
14256
|
}
|
|
14252
14257
|
`;
|
|
14253
|
-
var ORCHESTRATOR = `import
|
|
14258
|
+
var ORCHESTRATOR = `import fs from "node:fs";
|
|
14259
|
+
import path from "node:path";
|
|
14260
|
+
import { spawn } from "node:child_process";
|
|
14254
14261
|
import { readCache, writeCache, hashInputs } from "./cache-engine.js";
|
|
14255
14262
|
import { loadMfConfig } from "../tools/project-graph/graph-engine.js";
|
|
14256
14263
|
|
|
14264
|
+
function hasWorkspaceScript(projectRoot, script) {
|
|
14265
|
+
const pkgPath = path.join(projectRoot, "package.json");
|
|
14266
|
+
if (!fs.existsSync(pkgPath)) return false;
|
|
14267
|
+
try {
|
|
14268
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
14269
|
+
return typeof pkg.scripts?.[script] === "string" && pkg.scripts[script].trim().length > 0;
|
|
14270
|
+
} catch {
|
|
14271
|
+
return false;
|
|
14272
|
+
}
|
|
14273
|
+
}
|
|
14274
|
+
|
|
14257
14275
|
export async function runTarget(projectId, target, options = {}) {
|
|
14258
14276
|
const cwd = options.cwd ?? process.cwd();
|
|
14259
14277
|
const config = loadMfConfig(cwd);
|
|
14260
14278
|
const project = config.projects?.[projectId];
|
|
14261
14279
|
if (!project) throw new Error("Unknown project: " + projectId);
|
|
14262
14280
|
|
|
14281
|
+
const projectRoot = path.join(cwd, project.root);
|
|
14282
|
+
if (!hasWorkspaceScript(projectRoot, target)) {
|
|
14283
|
+
console.log("[skip] " + projectId + ":" + target + " (no script in " + project.root + ")");
|
|
14284
|
+
return { success: true, code: 0, projectId, target, skipped: true };
|
|
14285
|
+
}
|
|
14286
|
+
|
|
14263
14287
|
const cacheKey = hashInputs({ projectId, target, root: project.root });
|
|
14264
14288
|
if (options.cache !== false && config.cache?.enabled !== false) {
|
|
14265
14289
|
const cached = readCache(projectId + ":" + target + ":" + cacheKey, cwd);
|
|
@@ -14838,24 +14862,25 @@ export * from "./branding.js";
|
|
|
14838
14862
|
|
|
14839
14863
|
// src/generators/platformFramework/index.ts
|
|
14840
14864
|
init_developerExperience();
|
|
14841
|
-
function getPlatformFrameworkFiles(projectName, allApps, sharedApp, npmScope) {
|
|
14865
|
+
function getPlatformFrameworkFiles(projectName, allApps, sharedApp, npmScope, options) {
|
|
14866
|
+
const lite = options?.lite ?? false;
|
|
14842
14867
|
return {
|
|
14843
14868
|
"mf.json": getMfJson(projectName, allApps, sharedApp),
|
|
14844
14869
|
...getMfCliFiles(),
|
|
14845
14870
|
...getProjectGraphFiles(),
|
|
14846
14871
|
...getTaskRunnerFiles(),
|
|
14847
14872
|
...getPlatformPluginFiles(),
|
|
14848
|
-
...getDevtoolsFiles(),
|
|
14849
|
-
...getCicdAndGovernanceFiles(projectName),
|
|
14850
|
-
...getTemplateMarketplaceFiles(),
|
|
14851
|
-
...getAiPlatformFiles(),
|
|
14852
|
-
...getExtendedSharedPackages(npmScope),
|
|
14873
|
+
...lite ? {} : getDevtoolsFiles(),
|
|
14874
|
+
...lite ? {} : getCicdAndGovernanceFiles(projectName),
|
|
14875
|
+
...lite ? {} : getTemplateMarketplaceFiles(),
|
|
14876
|
+
...lite ? {} : getAiPlatformFiles(),
|
|
14877
|
+
...lite ? {} : getExtendedSharedPackages(npmScope),
|
|
14853
14878
|
...getRuntimeConfigFiles(),
|
|
14854
14879
|
...getArchitectureProtectionFiles(projectName, sharedApp, npmScope),
|
|
14855
14880
|
...getDeveloperExperiencePlatformFiles(projectName, allApps),
|
|
14856
14881
|
"tools/mf-cli/schemas/mf.schema.json": getMfSchema(),
|
|
14857
14882
|
"docs/PLATFORM_ARCHITECTURE.md": getPlatformArchitectureDoc(projectName),
|
|
14858
|
-
".vscode/mf.code-snippets": VSCODE_SNIPPETS
|
|
14883
|
+
...lite ? {} : { ".vscode/mf.code-snippets": VSCODE_SNIPPETS }
|
|
14859
14884
|
};
|
|
14860
14885
|
}
|
|
14861
14886
|
var VSCODE_SNIPPETS = `{
|
|
@@ -15154,6 +15179,7 @@ function buildConfigFromArgs(argv) {
|
|
|
15154
15179
|
}
|
|
15155
15180
|
const federationOs = toBoolean(options["federation-os"] ?? options.federationOs, false);
|
|
15156
15181
|
const controlPlane = toBoolean(options["control-plane"] ?? options.controlPlane, false);
|
|
15182
|
+
const lite = toBoolean(options.lite, false);
|
|
15157
15183
|
let config = {
|
|
15158
15184
|
projectName: resolvedProjectName,
|
|
15159
15185
|
port,
|
|
@@ -15165,7 +15191,8 @@ function buildConfigFromArgs(argv) {
|
|
|
15165
15191
|
shared: resolveShared(options),
|
|
15166
15192
|
features: resolveEnterpriseFeatures(options),
|
|
15167
15193
|
federationOs,
|
|
15168
|
-
controlPlane
|
|
15194
|
+
controlPlane,
|
|
15195
|
+
lite
|
|
15169
15196
|
};
|
|
15170
15197
|
if (controlPlane) {
|
|
15171
15198
|
config = applyControlPlanePreset(config);
|
|
@@ -19787,6 +19814,13 @@ export function buildFederation() {
|
|
|
19787
19814
|
// src/generators/project.ts
|
|
19788
19815
|
var FEDERATION_SHARED_IMPORT = "../../../../packages/shared-config/src/federationShared.js";
|
|
19789
19816
|
var FEDERATION_REMOTES_IMPORT = "../../../../packages/shared-config/src/federationRemotes.js";
|
|
19817
|
+
function getNpmrcContent() {
|
|
19818
|
+
return `install-strategy=hoisted
|
|
19819
|
+
fund=false
|
|
19820
|
+
audit=false
|
|
19821
|
+
prefer-offline=true
|
|
19822
|
+
`;
|
|
19823
|
+
}
|
|
19790
19824
|
function getDockerfile(port) {
|
|
19791
19825
|
return `FROM node:22-alpine
|
|
19792
19826
|
|
|
@@ -19896,13 +19930,11 @@ async function generateParentWorkspace(projectRoot, config) {
|
|
|
19896
19930
|
Object.entries(getWorkspacePackageFiles(npmScope)).map(([filePath, content]) => writeFile(projectRoot, filePath, content))
|
|
19897
19931
|
);
|
|
19898
19932
|
if (isEnterpriseParent) {
|
|
19899
|
-
const sdkIds = ["sdk-core", "api-client", "query-client", "websocket-sdk", ...enterpriseFlags.auth ? ["auth-sdk"] : []];
|
|
19933
|
+
const sdkIds = config.lite ? ["query-client"] : ["sdk-core", "api-client", "query-client", "websocket-sdk", ...enterpriseFlags.auth ? ["auth-sdk"] : []];
|
|
19900
19934
|
await Promise.all(sdkIds.map((pkg2) => import_fs_extra3.default.ensureDir(import_node_path4.default.join(projectRoot, `packages/${pkg2}/src`))));
|
|
19901
|
-
|
|
19902
|
-
|
|
19903
|
-
|
|
19904
|
-
)
|
|
19905
|
-
);
|
|
19935
|
+
const sdkFiles = getSdkWorkspacePackageFiles(npmScope, enterpriseFlags);
|
|
19936
|
+
const sdkEntries = config.lite ? Object.entries(sdkFiles).filter(([filePath]) => filePath.startsWith("packages/query-client/")) : Object.entries(sdkFiles);
|
|
19937
|
+
await Promise.all(sdkEntries.map(([filePath, content]) => writeFile(projectRoot, filePath, content)));
|
|
19906
19938
|
}
|
|
19907
19939
|
}
|
|
19908
19940
|
await Promise.all(
|
|
@@ -19955,13 +19987,15 @@ async function generateParentWorkspace(projectRoot, config) {
|
|
|
19955
19987
|
sharedApps[0] ?? "corelib",
|
|
19956
19988
|
config.template === "tsx",
|
|
19957
19989
|
includeWorkspacePackages,
|
|
19958
|
-
includeWorkspacePackages && isEnterpriseParent
|
|
19990
|
+
includeWorkspacePackages && isEnterpriseParent && !config.lite,
|
|
19991
|
+
includeWorkspacePackages && isEnterpriseParent && !config.lite ? enterpriseFlags : void 0,
|
|
19959
19992
|
federationOs,
|
|
19960
19993
|
controlPlane,
|
|
19961
|
-
config.appType === "parent" && config.federation
|
|
19994
|
+
config.appType === "parent" && config.federation,
|
|
19995
|
+
config.lite
|
|
19962
19996
|
)
|
|
19963
19997
|
);
|
|
19964
|
-
await writeFile(projectRoot, ".npmrc",
|
|
19998
|
+
await writeFile(projectRoot, ".npmrc", getNpmrcContent());
|
|
19965
19999
|
await writeFile(
|
|
19966
20000
|
projectRoot,
|
|
19967
20001
|
"README.md",
|
|
@@ -19994,20 +20028,27 @@ async function generateParentWorkspace(projectRoot, config) {
|
|
|
19994
20028
|
await writeFile(projectRoot, "scripts/security-scan-placeholder.js", getSecurityScanPlaceholderScript());
|
|
19995
20029
|
if (config.template === "tsx" || config.template === "jsx" && isEnterpriseParent) {
|
|
19996
20030
|
if (config.template === "tsx") {
|
|
19997
|
-
|
|
19998
|
-
|
|
19999
|
-
|
|
20031
|
+
if (config.lite) {
|
|
20032
|
+
await writeFile(projectRoot, "tsconfig.base.json", getTsconfigBaseJson());
|
|
20033
|
+
await augmentWorkspacePackagesTsconfig(projectRoot);
|
|
20034
|
+
} else {
|
|
20035
|
+
await writeEnterpriseQualityRootFiles(projectRoot, config.projectName, allApps, true);
|
|
20036
|
+
await augmentWorkspacePackagesTsconfig(projectRoot);
|
|
20037
|
+
await Promise.all(allApps.map((appName) => augmentWorkspaceAppWithQuality(import_node_path4.default.join(projectRoot, "apps", appName))));
|
|
20038
|
+
}
|
|
20000
20039
|
}
|
|
20001
20040
|
if (isEnterpriseParent) {
|
|
20002
20041
|
await augmentWorkspacePackagesForProjectReferences(projectRoot);
|
|
20003
|
-
|
|
20004
|
-
|
|
20005
|
-
(
|
|
20006
|
-
|
|
20007
|
-
|
|
20042
|
+
if (!config.lite) {
|
|
20043
|
+
await Promise.all(
|
|
20044
|
+
Object.entries(getEnterprisePlatformRootFiles(config.projectName, enterpriseFlags)).map(
|
|
20045
|
+
([filePath, content]) => writeFile(projectRoot, filePath, content)
|
|
20046
|
+
)
|
|
20047
|
+
);
|
|
20048
|
+
}
|
|
20008
20049
|
const sharedAppName = sharedApps[0] ?? "corelib";
|
|
20009
20050
|
await Promise.all(
|
|
20010
|
-
Object.entries(getPlatformFrameworkFiles(config.projectName, allApps, sharedAppName, npmScope)).map(
|
|
20051
|
+
Object.entries(getPlatformFrameworkFiles(config.projectName, allApps, sharedAppName, npmScope, { lite: config.lite })).map(
|
|
20011
20052
|
([filePath, content]) => writeFile(projectRoot, filePath, content)
|
|
20012
20053
|
)
|
|
20013
20054
|
);
|
|
@@ -21628,7 +21669,7 @@ ${getFederationSharedBlockJs(enterprise, "host", platformPreset)}
|
|
|
21628
21669
|
}
|
|
21629
21670
|
`;
|
|
21630
21671
|
}
|
|
21631
|
-
function getWorkspacePackageJson(projectName, allApps, remotes, sharedApp, includeWorkspacePackages, includeEnterpriseQuality, enterpriseFlags, federationOs = false, controlPlane = false, includeInfraScripts = false) {
|
|
21672
|
+
function getWorkspacePackageJson(projectName, allApps, remotes, sharedApp, includeWorkspacePackages, includeEnterpriseQuality, enterpriseFlags, federationOs = false, controlPlane = false, includeInfraScripts = false, lite = false) {
|
|
21632
21673
|
const envs = ["dev", "staging", "uat", "production"];
|
|
21633
21674
|
const hostApp = allApps[0];
|
|
21634
21675
|
const scripts = {
|
|
@@ -21700,7 +21741,7 @@ function getWorkspacePackageJson(projectName, allApps, remotes, sharedApp, inclu
|
|
|
21700
21741
|
remotes
|
|
21701
21742
|
}
|
|
21702
21743
|
};
|
|
21703
|
-
if (includeEnterpriseQuality) {
|
|
21744
|
+
if (includeEnterpriseQuality && !lite) {
|
|
21704
21745
|
applyEnterpriseQualityRootPackageJson(packageJson.scripts, packageJson.devDependencies, allApps);
|
|
21705
21746
|
packageJson.overrides = getWorkspaceNpmOverrides();
|
|
21706
21747
|
}
|
|
@@ -21897,7 +21938,7 @@ async function resolveWorkspaceContext(workspaceRoot) {
|
|
|
21897
21938
|
const controlPlane = !federationOs && await import_fs_extra3.default.pathExists(import_node_path4.default.join(workspaceRoot, "apps/workflow-monitor-app"));
|
|
21898
21939
|
const includeWorkspacePackages = await import_fs_extra3.default.pathExists(import_node_path4.default.join(workspaceRoot, "packages/shared-ui"));
|
|
21899
21940
|
const includeInfraScripts = await import_fs_extra3.default.pathExists(import_node_path4.default.join(workspaceRoot, "infrastructure/nginx"));
|
|
21900
|
-
const includeEnterpriseQuality = template === "tsx" && (enterprise || includeWorkspacePackages);
|
|
21941
|
+
const includeEnterpriseQuality = template === "tsx" && (enterprise || includeWorkspacePackages) && await import_fs_extra3.default.pathExists(import_node_path4.default.join(workspaceRoot, ".eslintrc.cjs"));
|
|
21901
21942
|
return {
|
|
21902
21943
|
workspaceRoot,
|
|
21903
21944
|
projectName: mf.name ?? import_node_path4.default.basename(workspaceRoot),
|
|
@@ -22094,6 +22135,7 @@ function printHelp() {
|
|
|
22094
22135
|
console.log(" --shared=sharedlib");
|
|
22095
22136
|
console.log(" --docker=true|false (default: true)");
|
|
22096
22137
|
console.log(" --federation=true|false");
|
|
22138
|
+
console.log(" --lite Faster npm install (skip ESLint/Vitest/Husky + optional SDK packages)");
|
|
22097
22139
|
console.log("");
|
|
22098
22140
|
console.log("Enterprise platform flags (parent monorepo):");
|
|
22099
22141
|
console.log(" --auth OAuth/OIDC auth foundation");
|
package/package.json
CHANGED