@bleedingdev/modern-js-create 3.4.0-ultramodern.12 → 3.4.0-ultramodern.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/README.md +13 -11
  2. package/dist/cjs/index.cjs +36 -3
  3. package/dist/cjs/locale/en.cjs +10 -0
  4. package/dist/cjs/locale/zh.cjs +10 -0
  5. package/dist/cjs/ultramodern-tooling/commands.cjs +185 -0
  6. package/dist/cjs/ultramodern-tooling/config.cjs +248 -0
  7. package/dist/cjs/ultramodern-workspace/add-vertical.cjs +64 -25
  8. package/dist/cjs/ultramodern-workspace/bridge-config.cjs +327 -0
  9. package/dist/cjs/ultramodern-workspace/codesmith.cjs +1 -0
  10. package/dist/cjs/ultramodern-workspace/contracts.cjs +119 -653
  11. package/dist/cjs/ultramodern-workspace/descriptors.cjs +4 -0
  12. package/dist/cjs/ultramodern-workspace/fs-io.cjs +117 -0
  13. package/dist/cjs/ultramodern-workspace/generation-result.cjs +1 -1
  14. package/dist/cjs/ultramodern-workspace/index.cjs +4 -0
  15. package/dist/cjs/ultramodern-workspace/mf-validation.cjs +572 -0
  16. package/dist/cjs/ultramodern-workspace/module-federation.cjs +14 -0
  17. package/dist/cjs/ultramodern-workspace/package-json.cjs +26 -12
  18. package/dist/cjs/ultramodern-workspace/public-api.cjs +4 -0
  19. package/dist/cjs/ultramodern-workspace/workspace-scripts.cjs +74 -44
  20. package/dist/cjs/ultramodern-workspace/write-workspace.cjs +55 -15
  21. package/dist/esm/index.js +36 -3
  22. package/dist/esm/locale/en.js +10 -0
  23. package/dist/esm/locale/zh.js +10 -0
  24. package/dist/esm/ultramodern-tooling/commands.js +132 -0
  25. package/dist/esm/ultramodern-tooling/config.js +196 -0
  26. package/dist/esm/ultramodern-workspace/add-vertical.js +65 -29
  27. package/dist/esm/ultramodern-workspace/bridge-config.js +270 -0
  28. package/dist/esm/ultramodern-workspace/codesmith.js +1 -0
  29. package/dist/esm/ultramodern-workspace/contracts.js +122 -608
  30. package/dist/esm/ultramodern-workspace/descriptors.js +2 -1
  31. package/dist/esm/ultramodern-workspace/fs-io.js +116 -2
  32. package/dist/esm/ultramodern-workspace/generation-result.js +2 -2
  33. package/dist/esm/ultramodern-workspace/index.js +1 -0
  34. package/dist/esm/ultramodern-workspace/mf-validation.js +517 -0
  35. package/dist/esm/ultramodern-workspace/module-federation.js +14 -0
  36. package/dist/esm/ultramodern-workspace/package-json.js +26 -12
  37. package/dist/esm/ultramodern-workspace/public-api.js +1 -0
  38. package/dist/esm/ultramodern-workspace/workspace-scripts.js +75 -27
  39. package/dist/esm/ultramodern-workspace/write-workspace.js +56 -19
  40. package/dist/esm-node/index.js +36 -3
  41. package/dist/esm-node/locale/en.js +10 -0
  42. package/dist/esm-node/locale/zh.js +10 -0
  43. package/dist/esm-node/ultramodern-tooling/commands.js +133 -0
  44. package/dist/esm-node/ultramodern-tooling/config.js +197 -0
  45. package/dist/esm-node/ultramodern-workspace/add-vertical.js +65 -29
  46. package/dist/esm-node/ultramodern-workspace/bridge-config.js +271 -0
  47. package/dist/esm-node/ultramodern-workspace/codesmith.js +1 -0
  48. package/dist/esm-node/ultramodern-workspace/contracts.js +122 -608
  49. package/dist/esm-node/ultramodern-workspace/descriptors.js +2 -1
  50. package/dist/esm-node/ultramodern-workspace/fs-io.js +116 -2
  51. package/dist/esm-node/ultramodern-workspace/generation-result.js +2 -2
  52. package/dist/esm-node/ultramodern-workspace/index.js +1 -0
  53. package/dist/esm-node/ultramodern-workspace/mf-validation.js +518 -0
  54. package/dist/esm-node/ultramodern-workspace/module-federation.js +14 -0
  55. package/dist/esm-node/ultramodern-workspace/package-json.js +26 -12
  56. package/dist/esm-node/ultramodern-workspace/public-api.js +1 -0
  57. package/dist/esm-node/ultramodern-workspace/workspace-scripts.js +75 -27
  58. package/dist/esm-node/ultramodern-workspace/write-workspace.js +56 -19
  59. package/dist/types/locale/en.d.ts +10 -0
  60. package/dist/types/locale/index.d.ts +20 -0
  61. package/dist/types/locale/zh.d.ts +10 -0
  62. package/dist/types/ultramodern-tooling/commands.d.ts +1 -0
  63. package/dist/types/ultramodern-tooling/config.d.ts +43 -0
  64. package/dist/types/ultramodern-workspace/add-vertical.d.ts +5 -2
  65. package/dist/types/ultramodern-workspace/bridge-config.d.ts +64 -0
  66. package/dist/types/ultramodern-workspace/codesmith.d.ts +1 -0
  67. package/dist/types/ultramodern-workspace/contracts.d.ts +2 -17
  68. package/dist/types/ultramodern-workspace/descriptors.d.ts +1 -0
  69. package/dist/types/ultramodern-workspace/fs-io.d.ts +1 -0
  70. package/dist/types/ultramodern-workspace/index.d.ts +2 -0
  71. package/dist/types/ultramodern-workspace/mf-validation.d.ts +27 -0
  72. package/dist/types/ultramodern-workspace/package-json.d.ts +4 -3
  73. package/dist/types/ultramodern-workspace/public-api.d.ts +2 -0
  74. package/dist/types/ultramodern-workspace/types.d.ts +2 -0
  75. package/dist/types/ultramodern-workspace/workspace-scripts.d.ts +1 -7
  76. package/dist/types/ultramodern-workspace/write-workspace.d.ts +4 -2
  77. package/package.json +5 -3
  78. package/template-workspace/{.agents → .codex}/skills-lock.json +12 -12
  79. package/template-workspace/.gitignore.handlebars +3 -0
  80. package/template-workspace/AGENTS.md.handlebars +11 -5
  81. package/template-workspace/README.md.handlebars +15 -12
  82. package/template-workspace/oxfmt.config.ts +1 -0
  83. package/template-workspace/oxlint.config.ts +1 -0
  84. package/template-workspace/scripts/bootstrap-agent-skills.mjs +77 -67
  85. package/templates/workspace-scripts/assert-mf-types.mjs.handlebars +56 -3
  86. package/templates/workspace-scripts/generate-public-surface-assets.mjs +239 -4
  87. package/templates/workspace-scripts/proof-cloudflare-version.mjs +282 -4
  88. package/templates/workspace-scripts/ultramodern-performance-readiness.mjs +172 -1
  89. package/templates/workspace-scripts/ultramodern-typecheck.mjs +4 -2
  90. package/templates/workspace-scripts/validate-ultramodern-workspace.mjs.handlebars +783 -26
  91. /package/template-workspace/{.agents → .codex}/rstackjs-agent-skills-LICENSE +0 -0
  92. /package/template-workspace/{.agents → .codex}/skills/rsbuild-best-practices/SKILL.md +0 -0
  93. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/SKILL.md +0 -0
  94. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/command-map.md +0 -0
  95. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/common-analysis-patterns.md +0 -0
  96. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/install-rsdoctor-common.md +0 -0
  97. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/install-rsdoctor-rspack.md +0 -0
  98. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/install-rsdoctor-webpack.md +0 -0
  99. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/install-rsdoctor.md +0 -0
  100. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/rsdoctor-data-types.md +0 -0
  101. /package/template-workspace/{.agents → .codex}/skills/rslib-best-practices/SKILL.md +0 -0
  102. /package/template-workspace/{.agents → .codex}/skills/rslib-modern-package/SKILL.md +0 -0
  103. /package/template-workspace/{.agents → .codex}/skills/rspack-best-practices/SKILL.md +0 -0
  104. /package/template-workspace/{.agents → .codex}/skills/rspack-tracing/SKILL.md +0 -0
  105. /package/template-workspace/{.agents → .codex}/skills/rspack-tracing/references/bottlenecks.md +0 -0
  106. /package/template-workspace/{.agents → .codex}/skills/rspack-tracing/references/tracing-guide.md +0 -0
  107. /package/template-workspace/{.agents → .codex}/skills/rspack-tracing/scripts/analyze_trace.js +0 -0
  108. /package/template-workspace/{.agents → .codex}/skills/rstest-best-practices/SKILL.md +0 -0
@@ -7,10 +7,73 @@ import { createCloudflareSecurityContract } from "./policy.js";
7
7
  import { publicSurfaceManagedSourceAssetPaths } from "./public-surface.js";
8
8
  import { createLocalisedUrlsMap, createRouteMetaFilePath, createRouteOwnedI18nPaths, createRoutePageFilePath } from "./routes.js";
9
9
  import { CLOUDFLARE_COMPATIBILITY_DATE, NODE_VERSION, PNPM_VERSION } from "./versions.js";
10
- function createAssertMfTypesScript(remotes = []) {
11
- return renderFileTemplate("workspace-scripts/assert-mf-types.mjs", {
12
- defaultAppDirsJson: JSON.stringify(remotes.map((remote)=>remote.directory), null, 2)
10
+ function createToolWrapperScript(command, extraArgs = []) {
11
+ const commandJson = JSON.stringify(command);
12
+ const extraArgsJson = JSON.stringify(extraArgs);
13
+ return `#!/usr/bin/env node
14
+ import { spawnSync } from 'node:child_process';
15
+ import path from 'node:path';
16
+ import { fileURLToPath } from 'node:url';
17
+
18
+ const createBin = process.env.ULTRAMODERN_CREATE_BIN;
19
+ const forwardedArgs = process.argv.slice(2);
20
+ const workspaceRoot =
21
+ process.env.ULTRAMODERN_WORKSPACE_ROOT ??
22
+ path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
23
+ const ultramodernArgs = ['ultramodern', ${commandJson}, ...${extraArgsJson}, ...forwardedArgs];
24
+ const result = createBin
25
+ ? spawnSync(process.execPath, [createBin, ...ultramodernArgs], {
26
+ env: { ...process.env, ULTRAMODERN_WORKSPACE_ROOT: workspaceRoot },
27
+ stdio: 'inherit',
28
+ })
29
+ : spawnSync('modern-js-create', ultramodernArgs, {
30
+ env: { ...process.env, ULTRAMODERN_WORKSPACE_ROOT: workspaceRoot },
31
+ shell: process.platform === 'win32',
32
+ stdio: 'inherit',
13
33
  });
34
+
35
+ if (result.error) {
36
+ console.error(result.error.message);
37
+ process.exit(1);
38
+ }
39
+
40
+ process.exit(result.status ?? 1);
41
+ `;
42
+ }
43
+ function createSkillsToolWrapperScript() {
44
+ return `#!/usr/bin/env node
45
+ import { spawnSync } from 'node:child_process';
46
+ import path from 'node:path';
47
+ import { fileURLToPath } from 'node:url';
48
+
49
+ const createBin = process.env.ULTRAMODERN_CREATE_BIN;
50
+ const forwardedArgs = process.argv.slice(2);
51
+ const workspaceRoot =
52
+ process.env.ULTRAMODERN_WORKSPACE_ROOT ??
53
+ path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
54
+ const checkOnly = forwardedArgs.includes('--check');
55
+ const skillArgs = checkOnly
56
+ ? ['skills', 'check', ...forwardedArgs.filter(arg => arg !== '--check')]
57
+ : ['skills', 'install', ...forwardedArgs];
58
+ const ultramodernArgs = ['ultramodern', ...skillArgs];
59
+ const result = createBin
60
+ ? spawnSync(process.execPath, [createBin, ...ultramodernArgs], {
61
+ env: { ...process.env, ULTRAMODERN_WORKSPACE_ROOT: workspaceRoot },
62
+ stdio: 'inherit',
63
+ })
64
+ : spawnSync('modern-js-create', ultramodernArgs, {
65
+ env: { ...process.env, ULTRAMODERN_WORKSPACE_ROOT: workspaceRoot },
66
+ shell: process.platform === 'win32',
67
+ stdio: 'inherit',
68
+ });
69
+
70
+ if (result.error) {
71
+ console.error(result.error.message);
72
+ process.exit(1);
73
+ }
74
+
75
+ process.exit(result.status ?? 1);
76
+ `;
14
77
  }
15
78
  function createWorkspaceValidationScript(scope, enableTailwind, remotes = []) {
16
79
  const verticals = remotes.filter(appHasEffectApi).map((remote)=>({
@@ -64,33 +127,18 @@ function createWorkspaceValidationScript(scope, enableTailwind, remotes = []) {
64
127
  function createWorkspaceI18nBoundaryValidationScript() {
65
128
  return readFileTemplate("workspace-scripts/check-ultramodern-i18n-boundaries.mjs");
66
129
  }
67
- function createPublicSurfaceAssetsScript() {
68
- return readFileTemplate("workspace-scripts/generate-public-surface-assets.mjs");
69
- }
70
- function createCloudflareProofHelperScript() {
71
- return readFileTemplate("workspace-scripts/ultramodern-cloudflare-proof.mjs");
72
- }
73
- function createCloudflareVersionProofScript() {
74
- return readFileTemplate("workspace-scripts/proof-cloudflare-version.mjs");
75
- }
76
130
  function createPerformanceReadinessConfigScript() {
77
131
  return readFileTemplate("workspace-scripts/ultramodern-performance-readiness.config.mjs");
78
132
  }
79
- function createPerformanceReadinessScript() {
80
- return readFileTemplate("workspace-scripts/ultramodern-performance-readiness.mjs");
81
- }
82
- function createUltramodernTypecheckScript() {
83
- return readFileTemplate("workspace-scripts/ultramodern-typecheck.mjs");
84
- }
85
- function writeGeneratedWorkspaceScripts(targetDir, scope, enableTailwind, remotes = []) {
86
- writeFileReplacing(targetDir, "scripts/assert-mf-types.mjs", createAssertMfTypesScript(remotes));
87
- writeFileReplacing(targetDir, "scripts/validate-ultramodern-workspace.mjs", createWorkspaceValidationScript(scope, enableTailwind, remotes));
133
+ function writeGeneratedWorkspaceScripts(targetDir, _scope, _enableTailwind, _remotes = []) {
134
+ writeFileReplacing(targetDir, "scripts/assert-mf-types.mjs", createToolWrapperScript('mf-types'));
135
+ writeFileReplacing(targetDir, "scripts/validate-ultramodern-workspace.mjs", createToolWrapperScript('validate'));
88
136
  writeFileReplacing(targetDir, "scripts/check-ultramodern-i18n-boundaries.mjs", createWorkspaceI18nBoundaryValidationScript());
89
- writeFileReplacing(targetDir, "scripts/generate-public-surface-assets.mjs", createPublicSurfaceAssetsScript());
90
- writeFileReplacing(targetDir, "scripts/ultramodern-cloudflare-proof.mjs", createCloudflareProofHelperScript());
91
- writeFileReplacing(targetDir, "scripts/proof-cloudflare-version.mjs", createCloudflareVersionProofScript());
137
+ writeFileReplacing(targetDir, "scripts/generate-public-surface-assets.mjs", createToolWrapperScript('public-surface'));
138
+ writeFileReplacing(targetDir, "scripts/proof-cloudflare-version.mjs", createToolWrapperScript('cloudflare-proof'));
92
139
  writeFileReplacing(targetDir, "scripts/ultramodern-performance-readiness.config.mjs", createPerformanceReadinessConfigScript());
93
- writeFileReplacing(targetDir, "scripts/ultramodern-performance-readiness.mjs", createPerformanceReadinessScript());
94
- writeFileReplacing(targetDir, "scripts/ultramodern-typecheck.mjs", createUltramodernTypecheckScript());
140
+ writeFileReplacing(targetDir, "scripts/ultramodern-performance-readiness.mjs", createToolWrapperScript('performance-readiness'));
141
+ writeFileReplacing(targetDir, "scripts/ultramodern-typecheck.mjs", createToolWrapperScript('typecheck'));
142
+ writeFileReplacing(targetDir, "scripts/bootstrap-agent-skills.mjs", createSkillsToolWrapperScript());
95
143
  }
96
- export { createAssertMfTypesScript, createCloudflareProofHelperScript, createCloudflareVersionProofScript, createPerformanceReadinessConfigScript, createPerformanceReadinessScript, createPublicSurfaceAssetsScript, createUltramodernTypecheckScript, createWorkspaceI18nBoundaryValidationScript, createWorkspaceValidationScript, writeGeneratedWorkspaceScripts };
144
+ export { createPerformanceReadinessConfigScript, createWorkspaceI18nBoundaryValidationScript, createWorkspaceValidationScript, writeGeneratedWorkspaceScripts };
@@ -1,10 +1,11 @@
1
1
  import node_fs from "node:fs";
2
2
  import { createAppEnvDts, createAppRuntimeConfig, createAppStyles, createPostcssConfig, createSharedDesignTokensCss, createShellFrameComponent, createTailwindConfig } from "./app-files.js";
3
- import { createDevelopmentOverlay, createGeneratedContract, createOwnership, createPackageSourceMetadata, createTemplateManifest, createTopology } from "./contracts.js";
3
+ import { normalizeUltramodernBridgeConfig } from "./bridge-config.js";
4
+ import { createDevelopmentOverlay, createOwnership, createTopology, createUltramodernConfig } from "./contracts.js";
4
5
  import { createLayout, createRemoteEntry, createRemoteExposeComponent, createRemotePage, createShellPage, createShellRemoteComponents, remoteComponentOutputPath } from "./demo-components.js";
5
- import { GENERATED_CONTRACT_PATH, appHasEffectApi, appI18nNamespace, createShellHost, sharedPackages, shellApp } from "./descriptors.js";
6
+ import { ULTRAMODERN_CONFIG_PATH, appHasEffectApi, appI18nNamespace, createShellHost, sharedPackages, shellApp } from "./descriptors.js";
6
7
  import { createEffectClient, createEffectServiceEntry, createEffectSharedApi, createShellEffectClient } from "./effect-api.js";
7
- import { copyRootTemplate, writeFile, writeJson } from "./fs-io.js";
8
+ import { copyRootTemplate, formatGeneratedWorkspaceFiles, writeFile, writeFileReplacing, writeJson } from "./fs-io.js";
8
9
  import { createFileSnapshot, createGenerationResult, diffFileSnapshots } from "./generation-result.js";
9
10
  import { createAppPublicLocaleMessages } from "./locales.js";
10
11
  import { createAppModernConfig, createRemoteModuleFederationConfig, createShellModuleFederationConfig, createUltramodernBuildModule, createUltramodernBuildReexportModule } from "./module-federation.js";
@@ -15,13 +16,13 @@ import { resolvePackageSource } from "./package-source.js";
15
16
  import { createPublicWebAppArtifacts } from "./public-surface.js";
16
17
  import { NODE_FETCH_VERSION, NODE_VERSION, PNPM_VERSION, TANSTACK_ROUTER_CORE_VERSION, TANSTACK_ROUTER_VERSION, TYPESCRIPT_VERSION } from "./versions.js";
17
18
  import { writeGeneratedWorkspaceScripts } from "./workspace-scripts.js";
18
- function writeApp(targetDir, scope, app, packageSource, enableTailwind, remotes = []) {
19
+ function writeApp(targetDir, scope, app, packageSource, enableTailwind, remotes = [], bridge) {
19
20
  const resolvedApp = 'shell' === app.kind ? createShellHost(remotes) : app;
20
21
  const publicWeb = createPublicWebAppArtifacts(resolvedApp);
21
22
  const writeAppFile = (relativePath, content)=>{
22
23
  writeFile(targetDir, `${resolvedApp.directory}/${relativePath}`, content);
23
24
  };
24
- writeJson(targetDir, `${resolvedApp.directory}/package.json`, createAppPackage(scope, resolvedApp, packageSource, enableTailwind, remotes));
25
+ writeJson(targetDir, `${resolvedApp.directory}/package.json`, createAppPackage(scope, resolvedApp, packageSource, enableTailwind, remotes, bridge));
25
26
  writeJson(targetDir, `${resolvedApp.directory}/tsconfig.json`, createAppTsConfig(resolvedApp, remotes));
26
27
  writeJson(targetDir, `${resolvedApp.directory}/tsconfig.mf-types.json`, createAppMfTypesTsConfig(resolvedApp));
27
28
  writeFile(targetDir, `${resolvedApp.directory}/src/modern-app-env.d.ts`, createAppEnvDts(resolvedApp, remotes));
@@ -80,10 +81,36 @@ function writeSharedPackages(targetDir, scope) {
80
81
  `);
81
82
  writeFile(targetDir, 'packages/shared-design-tokens/src/tokens.css', createSharedDesignTokensCss());
82
83
  }
84
+ function createCompactRootPackageJson(scope, packageSource, remotes, bridge) {
85
+ const rootPackage = createRootPackageJson(scope, packageSource, remotes, bridge);
86
+ if (rootPackage.modernjs?.packageSource && 'object' == typeof rootPackage.modernjs.packageSource) rootPackage.modernjs.packageSource.config = `./${ULTRAMODERN_CONFIG_PATH}`;
87
+ return rootPackage;
88
+ }
89
+ function createCompactUltramodernConfig(scope, modernVersion, packageSource, apps = [
90
+ createShellHost()
91
+ ], enableTailwind = true, bridge) {
92
+ const config = createUltramodernConfig(scope, modernVersion, packageSource, apps, enableTailwind, bridge);
93
+ if (config.packageSource && 'object' == typeof config.packageSource && !Array.isArray(config.packageSource)) delete config.packageSource.metadata;
94
+ return config;
95
+ }
96
+ function writePnpmWorkspacePackages(targetDir, bridge) {
97
+ if (!bridge) return;
98
+ const pnpmWorkspacePath = `${targetDir}/pnpm-workspace.yaml`;
99
+ const pnpmWorkspace = node_fs.readFileSync(pnpmWorkspacePath, 'utf-8');
100
+ const packages = [
101
+ 'apps/*',
102
+ 'verticals/*',
103
+ 'packages/*',
104
+ ...bridge.workspacePackages.map((entry)=>entry.pattern)
105
+ ];
106
+ const renderedPackages = packages.map((pattern)=>` - ${pattern}`).join('\n');
107
+ writeFileReplacing(targetDir, 'pnpm-workspace.yaml', pnpmWorkspace.replace(/^packages:\n(?: {2}- .+\n)+/u, `packages:\n${renderedPackages}\n`));
108
+ }
83
109
  function generateUltramodernWorkspace(options) {
84
110
  const beforeFiles = createFileSnapshot(options.targetDir);
85
111
  const scope = toPackageScope(options.packageName);
86
112
  const packageSource = resolvePackageSource(options);
113
+ const bridge = normalizeUltramodernBridgeConfig(options.bridge);
87
114
  const enableTailwind = false !== options.enableTailwind;
88
115
  const initialVerticals = [];
89
116
  const createdApps = [
@@ -108,35 +135,45 @@ function generateUltramodernWorkspace(options) {
108
135
  typescriptVersion: TYPESCRIPT_VERSION,
109
136
  tailwindEnabled: String(enableTailwind)
110
137
  });
111
- writeJson(options.targetDir, 'package.json', createRootPackageJson(scope, packageSource, initialVerticals));
138
+ writePnpmWorkspacePackages(options.targetDir, bridge);
139
+ writeJson(options.targetDir, 'package.json', createCompactRootPackageJson(scope, packageSource, initialVerticals, bridge));
112
140
  writeJson(options.targetDir, 'tsconfig.base.json', createTsConfigBase());
113
141
  writeJson(options.targetDir, 'tsconfig.json', createRootTsConfig(createdApps));
114
142
  writeJson(options.targetDir, 'topology/reference-topology.json', createTopology(scope, initialVerticals));
115
143
  writeJson(options.targetDir, 'topology/ownership.json', createOwnership(scope, initialVerticals));
116
144
  writeJson(options.targetDir, 'topology/local-overlays/development.json', createDevelopmentOverlay(initialVerticals));
117
- writeJson(options.targetDir, '.modernjs/ultramodern-workspace-template-manifest.json', createTemplateManifest(options.modernVersion, packageSource));
118
- writeJson(options.targetDir, '.modernjs/ultramodern-package-source.json', createPackageSourceMetadata(scope, packageSource));
119
- writeJson(options.targetDir, GENERATED_CONTRACT_PATH, createGeneratedContract(scope, createdApps, enableTailwind));
120
- writeApp(options.targetDir, scope, shellApp, packageSource, enableTailwind, initialVerticals);
121
- for (const remote of initialVerticals)writeApp(options.targetDir, scope, remote, packageSource, enableTailwind, initialVerticals);
145
+ writeJson(options.targetDir, ULTRAMODERN_CONFIG_PATH, createCompactUltramodernConfig(scope, options.modernVersion, packageSource, createdApps, enableTailwind, bridge));
146
+ writeApp(options.targetDir, scope, shellApp, packageSource, enableTailwind, initialVerticals, bridge);
147
+ for (const remote of initialVerticals)writeApp(options.targetDir, scope, remote, packageSource, enableTailwind, initialVerticals, bridge);
122
148
  writeSharedPackages(options.targetDir, scope);
123
149
  writeGeneratedWorkspaceScripts(options.targetDir, scope, enableTailwind, initialVerticals);
124
- const afterFiles = createFileSnapshot(options.targetDir);
125
- const { createdPaths, rewrittenPaths } = diffFileSnapshots(beforeFiles, afterFiles);
126
- const result = createGenerationResult({
150
+ const preliminaryAfterFiles = createFileSnapshot(options.targetDir);
151
+ const preliminaryDiff = diffFileSnapshots(beforeFiles, preliminaryAfterFiles);
152
+ const preliminaryResult = createGenerationResult({
127
153
  operation: 'workspace',
128
154
  workspaceRoot: options.targetDir,
129
155
  packageScope: scope,
130
156
  packageSource,
131
157
  createdApps,
132
- createdPaths,
133
- rewrittenPaths
158
+ createdPaths: preliminaryDiff.createdPaths,
159
+ rewrittenPaths: preliminaryDiff.rewrittenPaths
134
160
  });
135
161
  runCodeSmithOverlays({
136
162
  workspaceRoot: options.targetDir,
137
163
  overlays: options.overlays,
138
- result
164
+ result: preliminaryResult
165
+ });
166
+ formatGeneratedWorkspaceFiles(options.targetDir);
167
+ const afterFiles = createFileSnapshot(options.targetDir);
168
+ const { createdPaths, rewrittenPaths } = diffFileSnapshots(beforeFiles, afterFiles);
169
+ return createGenerationResult({
170
+ operation: 'workspace',
171
+ workspaceRoot: options.targetDir,
172
+ packageScope: scope,
173
+ packageSource,
174
+ createdApps,
175
+ createdPaths,
176
+ rewrittenPaths
139
177
  });
140
- return result;
141
178
  }
142
- export { generateUltramodernWorkspace, writeApp, writeSharedPackages };
179
+ export { createCompactUltramodernConfig, generateUltramodernWorkspace, writeApp, writeSharedPackages };
@@ -7,7 +7,9 @@ import { fileURLToPath } from "node:url";
7
7
  import { resolveCreatePackageRoot } from "./create-package-root.js";
8
8
  import { i18n, localeKeys } from "./locale/index.js";
9
9
  import { BLEEDINGDEV_CREATE_PACKAGE, BLEEDINGDEV_FRAMEWORK_VERSION_ENV, BLEEDINGDEV_PACKAGE_NAME_PREFIX, BLEEDINGDEV_PACKAGE_SCOPE, WORKSPACE_PACKAGE_VERSION } from "./ultramodern-package-source.js";
10
+ import { runUltramodernToolingCli } from "./ultramodern-tooling/commands.js";
10
11
  import { addUltramodernVertical, generateUltramodernWorkspace, planUltramodernVertical } from "./ultramodern-workspace/index.js";
12
+ import { hasUltramodernBridgeCliOptions, parseUltramodernBridgeCliOptions, ultramodernBridgeCliBooleanFlags, ultramodernBridgeCliValueFlags } from "./ultramodern-workspace/bridge-config.js";
11
13
  const src_dirname = node_path.dirname(fileURLToPath(import.meta.url));
12
14
  const createPackageRoot = resolveCreatePackageRoot(src_dirname);
13
15
  const semverPattern = /^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
@@ -85,6 +87,16 @@ function showHelp() {
85
87
  console.log(i18n.t(localeKeys.help.optionUltramodernPackageRegistry));
86
88
  console.log(i18n.t(localeKeys.help.optionUltramodernPackageScope));
87
89
  console.log(i18n.t(localeKeys.help.optionUltramodernPackageNamePrefix));
90
+ console.log(i18n.t(localeKeys.help.optionBridge));
91
+ console.log(i18n.t(localeKeys.help.optionBridgeParentRoot));
92
+ console.log(i18n.t(localeKeys.help.optionBridgeWorkspacePackage));
93
+ console.log(i18n.t(localeKeys.help.optionBridgeWorkspacePackageName));
94
+ console.log(i18n.t(localeKeys.help.optionBridgeTestAlias));
95
+ console.log(i18n.t(localeKeys.help.optionBridgeDependency));
96
+ console.log(i18n.t(localeKeys.help.optionBridgeLockfilePolicy));
97
+ console.log(i18n.t(localeKeys.help.optionBridgeGate));
98
+ console.log(i18n.t(localeKeys.help.optionBridgeGateCwd));
99
+ console.log(i18n.t(localeKeys.help.optionBridgeReactSingleton));
88
100
  console.log(i18n.t(localeKeys.help.optionVertical));
89
101
  console.log(i18n.t(localeKeys.help.optionVerticalName));
90
102
  console.log(i18n.t(localeKeys.help.optionDryRun));
@@ -198,7 +210,8 @@ function collectPositionalArgs(args) {
198
210
  '--ultramodern-package-scope',
199
211
  '--ultramodern-package-name-prefix',
200
212
  VERTICAL_NAME_FLAG,
201
- CODESMITH_OVERLAY_FLAG
213
+ CODESMITH_OVERLAY_FLAG,
214
+ ...ultramodernBridgeCliValueFlags
202
215
  ]);
203
216
  const optionWithoutValue = new Set([
204
217
  '--help',
@@ -211,7 +224,8 @@ function collectPositionalArgs(args) {
211
224
  WORKSPACE_PROTOCOL_FLAG,
212
225
  DRY_RUN_FLAG,
213
226
  VERTICAL_FLAG,
214
- LEGACY_MODERN_JS_FLAG
227
+ LEGACY_MODERN_JS_FLAG,
228
+ ...ultramodernBridgeCliBooleanFlags
215
229
  ]);
216
230
  const positionalArgs = [];
217
231
  for(let i = 0; i < args.length; i++){
@@ -221,7 +235,7 @@ function collectPositionalArgs(args) {
221
235
  i += 1;
222
236
  continue;
223
237
  }
224
- if (!(arg.startsWith('--lang=') || arg.startsWith(`${BFF_RUNTIME_OPTION}=`) || arg.startsWith('--ultramodern-package-source=') || arg.startsWith('--ultramodern-package-version=') || arg.startsWith('--ultramodern-package-registry=') || arg.startsWith('--ultramodern-package-scope=') || arg.startsWith('--ultramodern-package-name-prefix=') || arg.startsWith(`${VERTICAL_FLAG}=`) || arg.startsWith(`${VERTICAL_NAME_FLAG}=`) || arg.startsWith(`${CODESMITH_OVERLAY_FLAG}=`))) positionalArgs.push(arg);
238
+ if (!(arg.startsWith('--lang=') || arg.startsWith(`${BFF_RUNTIME_OPTION}=`) || arg.startsWith('--ultramodern-package-source=') || arg.startsWith('--ultramodern-package-version=') || arg.startsWith('--ultramodern-package-registry=') || arg.startsWith('--ultramodern-package-scope=') || arg.startsWith('--ultramodern-package-name-prefix=') || arg.startsWith(`${VERTICAL_FLAG}=`) || arg.startsWith(`${VERTICAL_NAME_FLAG}=`) || arg.startsWith(`${CODESMITH_OVERLAY_FLAG}=`) || ultramodernBridgeCliBooleanFlags.some((flag)=>arg.startsWith(`${flag}=`)) || ultramodernBridgeCliValueFlags.some((flag)=>arg.startsWith(`${flag}=`)))) positionalArgs.push(arg);
225
239
  }
226
240
  }
227
241
  return positionalArgs;
@@ -337,6 +351,14 @@ function detectCodeSmithOverlays(args) {
337
351
  }
338
352
  return overlays.length > 0 ? overlays : void 0;
339
353
  }
354
+ function readBridgeCliOptions(args) {
355
+ try {
356
+ return parseUltramodernBridgeCliOptions(args);
357
+ } catch (error) {
358
+ console.error(error instanceof Error ? error.message : String(error));
359
+ process.exit(1);
360
+ }
361
+ }
340
362
  function detectUltramodernPackageSource(args, defaultPackageVersion, createPackage) {
341
363
  const bleedingDevDefaults = isBleedingDevCreatePackage(createPackage);
342
364
  const strategy = getOptionValue(args, [
@@ -546,6 +568,10 @@ async function getProjectName() {
546
568
  }
547
569
  async function main() {
548
570
  const args = process.argv.slice(2);
571
+ if ('ultramodern' === args[0]) {
572
+ process.exitCode = await runUltramodernToolingCli(args.slice(1));
573
+ return;
574
+ }
549
575
  if (args.includes('--help') || args.includes('-h')) return void showHelp();
550
576
  if (args.includes('--version') || args.includes('-v')) return void showVersion();
551
577
  if (detectLegacyModernJsFlag(args)) {
@@ -557,10 +583,16 @@ async function main() {
557
583
  const dryRun = detectDryRunFlag(args);
558
584
  const verticalInput = resolveVerticalCliInput(args);
559
585
  const overlays = detectCodeSmithOverlays(args);
586
+ const bridgeRequested = hasUltramodernBridgeCliOptions(args);
560
587
  if (dryRun && !verticalInput.addVertical) {
561
588
  console.error(`${DRY_RUN_FLAG} is currently supported only with ${VERTICAL_FLAG}`);
562
589
  process.exit(1);
563
590
  }
591
+ if (verticalInput.addVertical && bridgeRequested) {
592
+ console.error('Bridge options are supported only when creating a new UltraModern workspace.');
593
+ process.exit(1);
594
+ }
595
+ const bridge = readBridgeCliOptions(args);
564
596
  if (!dryRun) console.log(`\n${i18n.t(localeKeys.message.welcome)}\n`);
565
597
  const createPackage = readCreatePackageJson();
566
598
  const version = createPackage.version || 'latest';
@@ -601,6 +633,7 @@ async function main() {
601
633
  packageName: generatedPackageName,
602
634
  modernVersion: version,
603
635
  enableTailwind: detectTailwindFlag(),
636
+ bridge,
604
637
  overlays,
605
638
  packageSource
606
639
  });
@@ -39,6 +39,16 @@ const EN_LOCALE = {
39
39
  optionUltramodernPackageRegistry: ' --ultramodern-package-registry npm registry URL used for install package sources',
40
40
  optionUltramodernPackageScope: ' --ultramodern-package-scope Publish scope for npm alias installs (for example bleedingdev)',
41
41
  optionUltramodernPackageNamePrefix: ' --ultramodern-package-name-prefix Prefix for npm alias package names (default: modern-js-)',
42
+ optionBridge: ' --bridge Enable explicit nested parent-monorepo bridge mode for new workspaces',
43
+ optionBridgeParentRoot: ' --bridge-parent-root <path> Parent monorepo root for bridge mode',
44
+ optionBridgeWorkspacePackage: ' --bridge-workspace-package <glob> Parent workspace package glob consumed by generated apps',
45
+ optionBridgeWorkspacePackageName: ' --bridge-workspace-package-name <glob=package[,package]> Package names covered by a bridge workspace glob',
46
+ optionBridgeTestAlias: ' --bridge-test-alias <glob:alias=target> Test/source alias for a bridge workspace package glob',
47
+ optionBridgeDependency: ' --bridge-dependency <package[,package]> Explicit parent package dependency consumed by generated apps',
48
+ optionBridgeLockfilePolicy: ' --bridge-lockfile-policy <nested|parent> Bridge lockfile ownership policy (default: nested)',
49
+ optionBridgeGate: ' --bridge-gate <name=command> Delegated parent workspace gate command for bridge packages',
50
+ optionBridgeGateCwd: ' --bridge-gate-cwd <name=cwd> Working directory for a named bridge gate',
51
+ optionBridgeReactSingleton: ' --bridge-react-singleton <package[,package]> React singleton package expectation (default: react,react-dom)',
42
52
  optionVertical: ' --vertical[=<name>] Mutate the current existing UltraModern workspace and wire a MicroVertical',
43
53
  optionVerticalName: ' --vertical-name <name> Explicit MicroVertical name for automation-friendly workspace mutation',
44
54
  optionDryRun: ' --dry-run Preview a MicroVertical mutation plan without writing files (supported with --vertical)',
@@ -39,6 +39,16 @@ const ZH_LOCALE = {
39
39
  optionUltramodernPackageRegistry: ' --ultramodern-package-registry install 依赖来源使用的 npm registry 地址',
40
40
  optionUltramodernPackageScope: ' --ultramodern-package-scope npm alias 安装使用的发布 scope(例如 bleedingdev)',
41
41
  optionUltramodernPackageNamePrefix: ' --ultramodern-package-name-prefix npm alias 包名前缀(默认:modern-js-)',
42
+ optionBridge: ' --bridge 为新工作区启用显式的嵌套父 monorepo 桥接模式',
43
+ optionBridgeParentRoot: ' --bridge-parent-root <路径> 桥接模式使用的父 monorepo 根目录',
44
+ optionBridgeWorkspacePackage: ' --bridge-workspace-package <glob> 生成应用消费的父工作区包 glob',
45
+ optionBridgeWorkspacePackageName: ' --bridge-workspace-package-name <glob=包名[,包名]> 桥接工作区 glob 覆盖的包名',
46
+ optionBridgeTestAlias: ' --bridge-test-alias <glob:别名=目标> 桥接工作区包 glob 的测试/源码 alias',
47
+ optionBridgeDependency: ' --bridge-dependency <包名[,包名]> 生成应用显式消费的父包依赖',
48
+ optionBridgeLockfilePolicy: ' --bridge-lockfile-policy <nested|parent> 桥接 lockfile 归属策略(默认:nested)',
49
+ optionBridgeGate: ' --bridge-gate <名称=命令> 桥接包委托给父工作区执行的 gate 命令',
50
+ optionBridgeGateCwd: ' --bridge-gate-cwd <名称=目录> 指定桥接 gate 的工作目录',
51
+ optionBridgeReactSingleton: ' --bridge-react-singleton <包名[,包名]> React 单例包预期(默认:react,react-dom)',
42
52
  optionVertical: ' --vertical[=<名称>] 修改当前已有的 UltraModern 工作区,并接入 MicroVertical',
43
53
  optionVerticalName: ' --vertical-name <名称> 为自动化工作流显式指定 MicroVertical 名称',
44
54
  optionDryRun: ' --dry-run 预览 MicroVertical 修改计划但不写入文件(与 --vertical 一起使用)',
@@ -0,0 +1,133 @@
1
+ import "node:module";
2
+ import { spawnSync } from "node:child_process";
3
+ import node_fs from "node:fs";
4
+ import node_os from "node:os";
5
+ import node_path from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+ import { resolveCreatePackageRoot } from "../create-package-root.js";
8
+ import { validateModuleFederationTypes } from "../ultramodern-workspace/mf-validation.js";
9
+ import { createWorkspaceValidationScript } from "../ultramodern-workspace/workspace-scripts.js";
10
+ import { readUltramodernConfig, workspaceAppsFromToolingConfig } from "./config.js";
11
+ const commands_dirname = node_path.dirname(fileURLToPath(import.meta.url));
12
+ const createPackageRoot = resolveCreatePackageRoot(commands_dirname);
13
+ function printHelp() {
14
+ process.stdout.write(`Usage:
15
+ modern-js-create ultramodern <command> [args]
16
+
17
+ Commands:
18
+ validate
19
+ typecheck
20
+ mf-types
21
+ public-surface
22
+ cloudflare-proof
23
+ performance-readiness
24
+ skills install
25
+ skills check
26
+ `);
27
+ }
28
+ function spawnNodeScript(relativeScriptPath, args, context, options = {}) {
29
+ const scriptPath = node_path.join(createPackageRoot, relativeScriptPath);
30
+ const result = spawnSync(process.execPath, [
31
+ scriptPath,
32
+ ...args
33
+ ], {
34
+ cwd: options.cwd ?? context.workspaceRoot,
35
+ env: {
36
+ ...process.env,
37
+ ULTRAMODERN_WORKSPACE_ROOT: context.workspaceRoot
38
+ },
39
+ stdio: 'inherit'
40
+ });
41
+ if (result.error) throw result.error;
42
+ return result.status ?? 1;
43
+ }
44
+ function runRenderedModule(source, context) {
45
+ const tempDir = node_fs.mkdtempSync(node_path.join(node_os.tmpdir(), 'ultramodern-tool-'));
46
+ const tempFile = node_path.join(tempDir, 'command.mjs');
47
+ try {
48
+ node_fs.writeFileSync(tempFile, source, 'utf-8');
49
+ const result = spawnSync(process.execPath, [
50
+ tempFile
51
+ ], {
52
+ cwd: context.workspaceRoot,
53
+ stdio: 'inherit'
54
+ });
55
+ if (result.error) throw result.error;
56
+ return result.status ?? 1;
57
+ } finally{
58
+ node_fs.rmSync(tempDir, {
59
+ force: true,
60
+ recursive: true
61
+ });
62
+ }
63
+ }
64
+ function runValidate(context) {
65
+ const config = readUltramodernConfig(context.workspaceRoot);
66
+ const apps = workspaceAppsFromToolingConfig(config);
67
+ const remotes = apps.filter((app)=>'shell' !== app.kind);
68
+ const source = createWorkspaceValidationScript(config.workspace.packageScope, config.features.tailwind, remotes);
69
+ return runRenderedModule(source, context);
70
+ }
71
+ function runMfTypes(args, context) {
72
+ if (args.includes('--help') || args.includes('-h')) {
73
+ process.stdout.write(`Usage:
74
+ modern-js-create ultramodern mf-types [app-dir...]
75
+
76
+ Checks real Module Federation config files and DTS archives for exposed apps.
77
+ `);
78
+ return 0;
79
+ }
80
+ validateModuleFederationTypes({
81
+ workspaceRoot: context.workspaceRoot,
82
+ appDirs: args.length > 0 ? args : void 0
83
+ });
84
+ return 0;
85
+ }
86
+ function runSkills(args, context) {
87
+ const [subcommand, ...rest] = args;
88
+ if ('install' === subcommand) return spawnNodeScript("template-workspace/scripts/bootstrap-agent-skills.mjs", rest, context);
89
+ if ('check' === subcommand) return spawnNodeScript("template-workspace/scripts/bootstrap-agent-skills.mjs", [
90
+ '--check',
91
+ ...rest
92
+ ], context);
93
+ throw new Error('Usage: modern-js-create ultramodern skills <install|check>');
94
+ }
95
+ async function runUltramodernToolingCli(args, workspaceRoot = process.env.ULTRAMODERN_WORKSPACE_ROOT ?? process.cwd()) {
96
+ try {
97
+ const [command, ...rest] = args;
98
+ const context = {
99
+ workspaceRoot: node_path.resolve(workspaceRoot),
100
+ invocationCwd: process.cwd()
101
+ };
102
+ switch(command){
103
+ case void 0:
104
+ case '--help':
105
+ case '-h':
106
+ printHelp();
107
+ return 0;
108
+ case 'validate':
109
+ return runValidate(context);
110
+ case 'typecheck':
111
+ return spawnNodeScript("templates/workspace-scripts/ultramodern-typecheck.mjs", rest, context, {
112
+ cwd: context.invocationCwd
113
+ });
114
+ case 'mf-types':
115
+ return runMfTypes(rest, context);
116
+ case 'public-surface':
117
+ return spawnNodeScript("templates/workspace-scripts/generate-public-surface-assets.mjs", rest, context);
118
+ case 'cloudflare-proof':
119
+ return spawnNodeScript("templates/workspace-scripts/proof-cloudflare-version.mjs", rest, context);
120
+ case 'performance-readiness':
121
+ return spawnNodeScript("templates/workspace-scripts/ultramodern-performance-readiness.mjs", rest, context);
122
+ case 'skills':
123
+ return runSkills(rest, context);
124
+ default:
125
+ throw new Error(`Unknown UltraModern command: ${command}`);
126
+ }
127
+ } catch (error) {
128
+ const message = error instanceof Error ? error.message : String(error);
129
+ process.stderr.write(`[ultramodern] ${message}\n`);
130
+ return 1;
131
+ }
132
+ }
133
+ export { runUltramodernToolingCli };