@bleedingdev/modern-js-create 3.5.0-ultramodern.3 → 3.5.0-ultramodern.30
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 +21 -17
- package/dist/cjs/ultramodern-tooling/commands.cjs +772 -75
- package/dist/cjs/ultramodern-tooling/config.cjs +149 -8
- package/dist/cjs/ultramodern-workspace/add-vertical.cjs +25 -0
- package/dist/cjs/ultramodern-workspace/api.cjs +44 -0
- package/dist/cjs/ultramodern-workspace/app-files.cjs +8 -11
- package/dist/cjs/ultramodern-workspace/backend-federation.cjs +282 -0
- package/dist/cjs/ultramodern-workspace/contracts.cjs +24 -8
- package/dist/cjs/ultramodern-workspace/delivery-unit-sync.cjs +157 -0
- package/dist/cjs/ultramodern-workspace/delivery-unit.cjs +88 -0
- package/dist/cjs/ultramodern-workspace/descriptors.cjs +24 -0
- package/dist/cjs/ultramodern-workspace/module-federation.cjs +161 -50
- package/dist/cjs/ultramodern-workspace/package-json.cjs +26 -43
- package/dist/cjs/ultramodern-workspace/pnpm-workspace-policy-plan.cjs +166 -0
- package/dist/cjs/ultramodern-workspace/tooling-command-catalog.cjs +153 -0
- package/dist/cjs/ultramodern-workspace/versions.cjs +8 -3
- package/dist/cjs/ultramodern-workspace/workspace-script-plan.cjs +175 -0
- package/dist/cjs/ultramodern-workspace/workspace-scripts.cjs +104 -63
- package/dist/cjs/ultramodern-workspace/workspace-validation-contract.cjs +97 -0
- package/dist/cjs/ultramodern-workspace/write-workspace.cjs +11 -3
- package/dist/cjs/ultramodern-workspace/zerops.cjs +100 -0
- package/dist/esm/ultramodern-tooling/commands.js +775 -78
- package/dist/esm/ultramodern-tooling/config.js +144 -9
- package/dist/esm/ultramodern-workspace/add-vertical.js +26 -1
- package/dist/esm/ultramodern-workspace/api.js +43 -2
- package/dist/esm/ultramodern-workspace/app-files.js +8 -11
- package/dist/esm/ultramodern-workspace/backend-federation.js +217 -0
- package/dist/esm/ultramodern-workspace/contracts.js +24 -8
- package/dist/esm/ultramodern-workspace/delivery-unit-sync.js +108 -0
- package/dist/esm/ultramodern-workspace/delivery-unit.js +31 -0
- package/dist/esm/ultramodern-workspace/descriptors.js +13 -1
- package/dist/esm/ultramodern-workspace/module-federation.js +160 -42
- package/dist/esm/ultramodern-workspace/package-json.js +16 -40
- package/dist/esm/ultramodern-workspace/pnpm-workspace-policy-plan.js +113 -0
- package/dist/esm/ultramodern-workspace/tooling-command-catalog.js +100 -0
- package/dist/esm/ultramodern-workspace/versions.js +6 -4
- package/dist/esm/ultramodern-workspace/workspace-script-plan.js +110 -0
- package/dist/esm/ultramodern-workspace/workspace-scripts.js +88 -65
- package/dist/esm/ultramodern-workspace/workspace-validation-contract.js +59 -0
- package/dist/esm/ultramodern-workspace/write-workspace.js +14 -6
- package/dist/esm/ultramodern-workspace/zerops.js +62 -0
- package/dist/esm-node/ultramodern-tooling/commands.js +775 -78
- package/dist/esm-node/ultramodern-tooling/config.js +144 -9
- package/dist/esm-node/ultramodern-workspace/add-vertical.js +26 -1
- package/dist/esm-node/ultramodern-workspace/api.js +43 -2
- package/dist/esm-node/ultramodern-workspace/app-files.js +8 -11
- package/dist/esm-node/ultramodern-workspace/backend-federation.js +218 -0
- package/dist/esm-node/ultramodern-workspace/contracts.js +24 -8
- package/dist/esm-node/ultramodern-workspace/delivery-unit-sync.js +109 -0
- package/dist/esm-node/ultramodern-workspace/delivery-unit.js +32 -0
- package/dist/esm-node/ultramodern-workspace/descriptors.js +13 -1
- package/dist/esm-node/ultramodern-workspace/module-federation.js +160 -42
- package/dist/esm-node/ultramodern-workspace/package-json.js +16 -40
- package/dist/esm-node/ultramodern-workspace/pnpm-workspace-policy-plan.js +114 -0
- package/dist/esm-node/ultramodern-workspace/tooling-command-catalog.js +101 -0
- package/dist/esm-node/ultramodern-workspace/versions.js +6 -4
- package/dist/esm-node/ultramodern-workspace/workspace-script-plan.js +111 -0
- package/dist/esm-node/ultramodern-workspace/workspace-scripts.js +88 -65
- package/dist/esm-node/ultramodern-workspace/workspace-validation-contract.js +60 -0
- package/dist/esm-node/ultramodern-workspace/write-workspace.js +14 -6
- package/dist/esm-node/ultramodern-workspace/zerops.js +63 -0
- package/dist/types/ultramodern-tooling/config.d.ts +6 -0
- package/dist/types/ultramodern-workspace/api.d.ts +1 -0
- package/dist/types/ultramodern-workspace/backend-federation.d.ts +11 -0
- package/dist/types/ultramodern-workspace/contracts.d.ts +1 -1
- package/dist/types/ultramodern-workspace/delivery-unit-sync.d.ts +6 -0
- package/dist/types/ultramodern-workspace/delivery-unit.d.ts +27 -0
- package/dist/types/ultramodern-workspace/descriptors.d.ts +4 -0
- package/dist/types/ultramodern-workspace/module-federation.d.ts +4 -9
- package/dist/types/ultramodern-workspace/package-json.d.ts +0 -1
- package/dist/types/ultramodern-workspace/pnpm-workspace-policy-plan.d.ts +39 -0
- package/dist/types/ultramodern-workspace/tooling-command-catalog.d.ts +18 -0
- package/dist/types/ultramodern-workspace/versions.d.ts +5 -3
- package/dist/types/ultramodern-workspace/workspace-script-plan.d.ts +72 -0
- package/dist/types/ultramodern-workspace/workspace-scripts.d.ts +13 -0
- package/dist/types/ultramodern-workspace/workspace-validation-contract.d.ts +42 -0
- package/dist/types/ultramodern-workspace/zerops.d.ts +2 -0
- package/package.json +3 -3
- package/template-workspace/.gitignore.handlebars +4 -0
- package/template-workspace/README.md.handlebars +18 -15
- package/template-workspace/patches/@module-federation__bridge-react@2.6.0.patch +140 -0
- package/template-workspace/patches/@module-federation__modern-js-v3@2.6.0.patch +57 -0
- package/template-workspace/patches/drizzle-orm-ts7-strict-declarations.patch +452 -0
- package/template-workspace/patches/effect-schema-error-type-id.patch +18 -0
- package/template-workspace/pnpm-workspace.yaml.handlebars +8 -0
- package/template-workspace/scripts/bootstrap-agent-skills.mjs +11 -3
- package/templates/workspace-scripts/check-ultramodern-api-boundaries.mts +40 -2
- package/templates/workspace-scripts/generate-node-backend-federation.mjs +270 -0
- package/templates/workspace-scripts/materialize-zerops-runtime.mjs +448 -0
- package/templates/workspace-scripts/proof-cloudflare-version.mjs +237 -9
- package/templates/workspace-scripts/proof-node-backend-federation.mjs +729 -0
- package/templates/workspace-scripts/ultramodern-cloudflare-proof.mjs +188 -2
- package/templates/workspace-scripts/validate-ultramodern-workspace.mjs.handlebars +434 -18
|
@@ -52,26 +52,31 @@ var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_no
|
|
|
52
52
|
const external_node_url_namespaceObject = require("node:url");
|
|
53
53
|
const external_create_package_root_cjs_namespaceObject = require("../create-package-root.cjs");
|
|
54
54
|
const external_ultramodern_package_source_cjs_namespaceObject = require("../ultramodern-package-source.cjs");
|
|
55
|
+
const app_files_cjs_namespaceObject = require("../ultramodern-workspace/app-files.cjs");
|
|
56
|
+
const backend_federation_cjs_namespaceObject = require("../ultramodern-workspace/backend-federation.cjs");
|
|
57
|
+
const delivery_unit_sync_cjs_namespaceObject = require("../ultramodern-workspace/delivery-unit-sync.cjs");
|
|
55
58
|
const mf_validation_cjs_namespaceObject = require("../ultramodern-workspace/mf-validation.cjs");
|
|
59
|
+
const module_federation_cjs_namespaceObject = require("../ultramodern-workspace/module-federation.cjs");
|
|
60
|
+
const package_json_cjs_namespaceObject = require("../ultramodern-workspace/package-json.cjs");
|
|
61
|
+
const tooling_command_catalog_cjs_namespaceObject = require("../ultramodern-workspace/tooling-command-catalog.cjs");
|
|
56
62
|
const versions_cjs_namespaceObject = require("../ultramodern-workspace/versions.cjs");
|
|
63
|
+
const workspace_script_plan_cjs_namespaceObject = require("../ultramodern-workspace/workspace-script-plan.cjs");
|
|
57
64
|
const workspace_scripts_cjs_namespaceObject = require("../ultramodern-workspace/workspace-scripts.cjs");
|
|
65
|
+
const zerops_cjs_namespaceObject = require("../ultramodern-workspace/zerops.cjs");
|
|
58
66
|
const external_config_cjs_namespaceObject = require("./config.cjs");
|
|
59
67
|
const commands_dirname = external_node_path_default().dirname((0, external_node_url_namespaceObject.fileURLToPath)(__rslib_import_meta_url__));
|
|
60
68
|
const createPackageRoot = (0, external_create_package_root_cjs_namespaceObject.resolveCreatePackageRoot)(commands_dirname);
|
|
61
69
|
function printHelp() {
|
|
70
|
+
const commands = [
|
|
71
|
+
...(0, tooling_command_catalog_cjs_namespaceObject.generatedToolingCommandList)().map((command)=>` ${command}`),
|
|
72
|
+
' skills install',
|
|
73
|
+
' skills check'
|
|
74
|
+
].join('\n');
|
|
62
75
|
process.stdout.write(`Usage:
|
|
63
76
|
modern-js-create ultramodern <command> [args]
|
|
64
77
|
|
|
65
78
|
Commands:
|
|
66
|
-
|
|
67
|
-
typecheck
|
|
68
|
-
mf-types
|
|
69
|
-
migrate-strict-effect
|
|
70
|
-
public-surface
|
|
71
|
-
cloudflare-proof
|
|
72
|
-
performance-readiness
|
|
73
|
-
skills install
|
|
74
|
-
skills check
|
|
79
|
+
${commands}
|
|
75
80
|
`);
|
|
76
81
|
}
|
|
77
82
|
function spawnNodeScript(relativeScriptPath, args, context, options = {}) {
|
|
@@ -90,6 +95,13 @@ function spawnNodeScript(relativeScriptPath, args, context, options = {}) {
|
|
|
90
95
|
if (result.error) throw result.error;
|
|
91
96
|
return result.status ?? 1;
|
|
92
97
|
}
|
|
98
|
+
function runTemplateBackedToolingCommand(command, args, context) {
|
|
99
|
+
const toolingCommand = tooling_command_catalog_cjs_namespaceObject.generatedToolingCommands.find((candidate)=>candidate.command === command);
|
|
100
|
+
if (!toolingCommand?.templatePath) return;
|
|
101
|
+
return spawnNodeScript(toolingCommand.templatePath, args, context, {
|
|
102
|
+
cwd: 'invocation' === toolingCommand.cwd ? context.invocationCwd : context.workspaceRoot
|
|
103
|
+
});
|
|
104
|
+
}
|
|
93
105
|
function runRenderedModule(source, context) {
|
|
94
106
|
const tempDir = external_node_fs_default().mkdtempSync(external_node_path_default().join(external_node_os_default().tmpdir(), 'ultramodern-tool-'));
|
|
95
107
|
const tempFile = external_node_path_default().join(tempDir, 'command.mjs');
|
|
@@ -136,11 +148,45 @@ const modernPackageNames = new Set([
|
|
|
136
148
|
...external_ultramodern_package_source_cjs_namespaceObject.ULTRAMODERN_SINGLE_APP_MODERN_PACKAGES,
|
|
137
149
|
...external_ultramodern_package_source_cjs_namespaceObject.ULTRAMODERN_WORKSPACE_MODERN_PACKAGES
|
|
138
150
|
]);
|
|
151
|
+
function createMigrationIo(workspaceRoot, dryRun) {
|
|
152
|
+
const plan = [];
|
|
153
|
+
const rel = (p)=>(external_node_path_default().relative(workspaceRoot, p) || external_node_path_default().basename(p)).split(external_node_path_default().sep).join('/');
|
|
154
|
+
return {
|
|
155
|
+
workspaceRoot,
|
|
156
|
+
dryRun,
|
|
157
|
+
plan,
|
|
158
|
+
write (filePath, content) {
|
|
159
|
+
if (external_node_fs_default().existsSync(filePath) && external_node_fs_default().readFileSync(filePath, 'utf-8') === content) return false;
|
|
160
|
+
if (dryRun) {
|
|
161
|
+
plan.push(`[dry-run] would write ${rel(filePath)}`);
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
external_node_fs_default().mkdirSync(external_node_path_default().dirname(filePath), {
|
|
165
|
+
recursive: true
|
|
166
|
+
});
|
|
167
|
+
external_node_fs_default().writeFileSync(filePath, content, 'utf-8');
|
|
168
|
+
return true;
|
|
169
|
+
},
|
|
170
|
+
remove (filePath) {
|
|
171
|
+
if (!external_node_fs_default().existsSync(filePath)) return false;
|
|
172
|
+
if (dryRun) {
|
|
173
|
+
plan.push(`[dry-run] would delete ${rel(filePath)}`);
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
176
|
+
external_node_fs_default().rmSync(filePath);
|
|
177
|
+
return true;
|
|
178
|
+
},
|
|
179
|
+
log (message) {
|
|
180
|
+
if (dryRun) plan.push(`[dry-run] ${message}`);
|
|
181
|
+
else process.stdout.write(`[ultramodern] ${message}\n`);
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
}
|
|
139
185
|
function readJsonFile(filePath) {
|
|
140
186
|
return JSON.parse(external_node_fs_default().readFileSync(filePath, 'utf-8'));
|
|
141
187
|
}
|
|
142
|
-
function writeJsonFile(filePath, value) {
|
|
143
|
-
|
|
188
|
+
function writeJsonFile(io, filePath, value) {
|
|
189
|
+
return io.write(filePath, `${JSON.stringify(value, null, 2)}\n`);
|
|
144
190
|
}
|
|
145
191
|
function readOption(args, name) {
|
|
146
192
|
const prefix = `${name}=`;
|
|
@@ -173,7 +219,7 @@ function listWorkspacePackageFiles(workspaceRoot) {
|
|
|
173
219
|
withFileTypes: true
|
|
174
220
|
})){
|
|
175
221
|
if (!entry.isDirectory()) continue;
|
|
176
|
-
const packageFile =
|
|
222
|
+
const packageFile = `${directory}/${entry.name}/package.json`;
|
|
177
223
|
if (external_node_fs_default().existsSync(external_node_path_default().join(workspaceRoot, packageFile))) packageFiles.push(packageFile);
|
|
178
224
|
}
|
|
179
225
|
}
|
|
@@ -229,6 +275,18 @@ const generatedToolingDependencyPins = new Map([
|
|
|
229
275
|
versions_cjs_namespaceObject.ZEPHYR_RSPACK_PLUGIN_VERSION
|
|
230
276
|
]
|
|
231
277
|
]);
|
|
278
|
+
const strictEffectPackageVersionPolicyExclusions = [
|
|
279
|
+
`effect@${versions_cjs_namespaceObject.EFFECT_VERSION}`,
|
|
280
|
+
`@effect/opentelemetry@${versions_cjs_namespaceObject.EFFECT_VERSION}`
|
|
281
|
+
];
|
|
282
|
+
const moduleFederationModernJsPatchPath = `patches/@module-federation__modern-js-v3@${versions_cjs_namespaceObject.MODULE_FEDERATION_VERSION}.patch`;
|
|
283
|
+
const moduleFederationModernJsPatchSourcePath = external_node_path_default().join(createPackageRoot, 'template-workspace', moduleFederationModernJsPatchPath);
|
|
284
|
+
const moduleFederationBridgeReactPatchPath = `patches/@module-federation__bridge-react@${versions_cjs_namespaceObject.MODULE_FEDERATION_VERSION}.patch`;
|
|
285
|
+
const moduleFederationBridgeReactPatchSourcePath = external_node_path_default().join(createPackageRoot, 'template-workspace', moduleFederationBridgeReactPatchPath);
|
|
286
|
+
const effectDeclarationPatchPath = 'patches/effect-schema-error-type-id.patch';
|
|
287
|
+
const effectDeclarationPatchSourcePath = external_node_path_default().join(createPackageRoot, 'template-workspace', effectDeclarationPatchPath);
|
|
288
|
+
const drizzleOrmDeclarationPatchPath = 'patches/drizzle-orm-ts7-strict-declarations.patch';
|
|
289
|
+
const drizzleOrmDeclarationPatchSourcePath = external_node_path_default().join(createPackageRoot, 'template-workspace', drizzleOrmDeclarationPatchPath);
|
|
232
290
|
function updateGeneratedToolingDependencies(packageJson) {
|
|
233
291
|
let changed = false;
|
|
234
292
|
for (const section of [
|
|
@@ -247,10 +305,117 @@ function updateGeneratedToolingDependencies(packageJson) {
|
|
|
247
305
|
}
|
|
248
306
|
return changed;
|
|
249
307
|
}
|
|
308
|
+
const cloudflareModernDeployCommand = 'ULTRAMODERN_ZEPHYR=false MODERNJS_DEPLOY=cloudflare modern deploy';
|
|
309
|
+
const cloudflareModernDeploySkipBuildCommand = `${cloudflareModernDeployCommand} --skip-build`;
|
|
310
|
+
const cloudflareWranglerDeployCommand = 'wrangler deploy --config .output/wrangler.json';
|
|
311
|
+
const cloudflareWranglerDeployInvalidSkipBuildCommand = `${cloudflareWranglerDeployCommand} --skip-build`;
|
|
312
|
+
function removeStaleBackendFederationCommandSegments(command) {
|
|
313
|
+
return command.replace(/\s+&&\s+node\s+\S*scripts\/generate-node-backend-federation\.m[ct]s(?:\s+--app\s+\S+)?(?:\s+--target\s+\S+)?(?=\s+&&|$)/gu, '');
|
|
314
|
+
}
|
|
315
|
+
const SHELL_ONLY_OMITTED_ROOT_SCRIPTS = [
|
|
316
|
+
'node:backend-federation:generate',
|
|
317
|
+
'node:proof',
|
|
318
|
+
'zerops:materialize'
|
|
319
|
+
];
|
|
320
|
+
const splitScriptSegments = (command)=>command.split('&&').map((segment)=>segment.trim()).filter((segment)=>segment.length > 0);
|
|
321
|
+
const scriptSegmentTarget = (segment)=>segment.replace(/^pnpm\s+/u, '').split(/\s+/u)[0] ?? segment;
|
|
322
|
+
const FRAMEWORK_CHECK_TARGETS = new Set([
|
|
323
|
+
'format:check',
|
|
324
|
+
'lint',
|
|
325
|
+
'typecheck',
|
|
326
|
+
'skills:check',
|
|
327
|
+
'i18n:boundaries',
|
|
328
|
+
'api:check',
|
|
329
|
+
'contract:check',
|
|
330
|
+
'node:backend-federation:generate',
|
|
331
|
+
'node:proof',
|
|
332
|
+
'performance:readiness',
|
|
333
|
+
'bridge:check'
|
|
334
|
+
]);
|
|
335
|
+
function mergeAggregateCheckScript(consumer, framework) {
|
|
336
|
+
const frameworkSegments = splitScriptSegments(framework);
|
|
337
|
+
const consumerExtras = splitScriptSegments(consumer).filter((segment)=>!FRAMEWORK_CHECK_TARGETS.has(scriptSegmentTarget(segment)));
|
|
338
|
+
return [
|
|
339
|
+
...consumerExtras,
|
|
340
|
+
...frameworkSegments
|
|
341
|
+
].join(' && ');
|
|
342
|
+
}
|
|
343
|
+
function rewriteMigratedScriptReferences(scripts) {
|
|
344
|
+
let changed = false;
|
|
345
|
+
const pattern = new RegExp(`(scripts/(?:${workspace_scripts_cjs_namespaceObject.migratedWorkspaceScriptBasenames.join('|')}))\\.mjs`, 'gu');
|
|
346
|
+
for (const [name, value] of Object.entries(scripts)){
|
|
347
|
+
if ('string' != typeof value) continue;
|
|
348
|
+
const next = value.replace(pattern, '$1.mts');
|
|
349
|
+
if (next !== value) {
|
|
350
|
+
scripts[name] = next;
|
|
351
|
+
changed = true;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
return changed;
|
|
355
|
+
}
|
|
356
|
+
function updateGeneratedPackageScripts(packageJson, options = {}) {
|
|
357
|
+
const scripts = packageJson.scripts;
|
|
358
|
+
if (!scripts || 'object' != typeof scripts || Array.isArray(scripts)) return false;
|
|
359
|
+
let changed = false;
|
|
360
|
+
const apps = options.apps ?? [];
|
|
361
|
+
const shellOnly = options.shellOnly ?? false;
|
|
362
|
+
const app = apps.find((candidate)=>`${candidate.directory}/package.json` === options.relativePackageFile);
|
|
363
|
+
const isRootPackage = 'package.json' === options.relativePackageFile;
|
|
364
|
+
const expectedScripts = isRootPackage ? (0, workspace_script_plan_cjs_namespaceObject.createWorkspaceRootPackageScripts)(apps.filter((candidate)=>'shell' !== candidate.kind)) : app ? (0, workspace_script_plan_cjs_namespaceObject.createWorkspaceAppPackageScripts)(app) : void 0;
|
|
365
|
+
if (expectedScripts) for (const [name, value] of Object.entries(expectedScripts)){
|
|
366
|
+
if (isRootPackage && shellOnly && SHELL_ONLY_OMITTED_ROOT_SCRIPTS.includes(name)) {
|
|
367
|
+
if (name in scripts) {
|
|
368
|
+
delete scripts[name];
|
|
369
|
+
changed = true;
|
|
370
|
+
}
|
|
371
|
+
continue;
|
|
372
|
+
}
|
|
373
|
+
const nextValue = 'check' === name && 'string' == typeof scripts[name] ? mergeAggregateCheckScript(scripts[name], value) : value;
|
|
374
|
+
if (scripts[name] !== nextValue) {
|
|
375
|
+
scripts[name] = nextValue;
|
|
376
|
+
changed = true;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
if (rewriteMigratedScriptReferences(scripts)) changed = true;
|
|
380
|
+
const build = scripts.build;
|
|
381
|
+
if ('string' == typeof build) {
|
|
382
|
+
const nextBuild = removeStaleBackendFederationCommandSegments(build);
|
|
383
|
+
if (nextBuild !== build) {
|
|
384
|
+
scripts.build = nextBuild;
|
|
385
|
+
changed = true;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
const cloudflareBuild = scripts['cloudflare:build'];
|
|
389
|
+
if ('string' == typeof cloudflareBuild) {
|
|
390
|
+
let nextCloudflareBuild = removeStaleBackendFederationCommandSegments(cloudflareBuild);
|
|
391
|
+
if (nextCloudflareBuild.includes(cloudflareModernDeployCommand) && !nextCloudflareBuild.includes(cloudflareModernDeploySkipBuildCommand)) nextCloudflareBuild = nextCloudflareBuild.replace(cloudflareModernDeployCommand, cloudflareModernDeploySkipBuildCommand);
|
|
392
|
+
nextCloudflareBuild = nextCloudflareBuild.replace(/ && node \S*scripts\/generate-public-surface-assets\.m[ct]s --app [^&]+ --target dist(?= && ULTRAMODERN_ZEPHYR=false MODERNJS_DEPLOY=cloudflare modern deploy --skip-build)/u, '');
|
|
393
|
+
nextCloudflareBuild = nextCloudflareBuild.replace(/ && node \S*scripts\/verify-cloudflare-output\.m[ct]s(?: --app [^&]+)?/u, '');
|
|
394
|
+
if (nextCloudflareBuild !== cloudflareBuild) {
|
|
395
|
+
scripts['cloudflare:build'] = nextCloudflareBuild;
|
|
396
|
+
changed = true;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
const cloudflareDeploy = scripts['cloudflare:deploy'];
|
|
400
|
+
if ('string' == typeof cloudflareDeploy && cloudflareDeploy.includes(cloudflareWranglerDeployInvalidSkipBuildCommand)) {
|
|
401
|
+
scripts['cloudflare:deploy'] = cloudflareDeploy.replace(cloudflareWranglerDeployInvalidSkipBuildCommand, cloudflareWranglerDeployCommand);
|
|
402
|
+
changed = true;
|
|
403
|
+
}
|
|
404
|
+
return changed;
|
|
405
|
+
}
|
|
250
406
|
function normalizeStrictEffectApiMetadata(value) {
|
|
251
|
-
const api = value.api;
|
|
252
|
-
if (!api || 'object' != typeof api || Array.isArray(api)) return false;
|
|
253
407
|
let changed = false;
|
|
408
|
+
const backendFederation = value.backendFederation;
|
|
409
|
+
if (backendFederation && 'object' == typeof backendFederation && !Array.isArray(backendFederation) && Object.hasOwn(backendFederation, 'entry')) {
|
|
410
|
+
delete backendFederation.entry;
|
|
411
|
+
changed = true;
|
|
412
|
+
}
|
|
413
|
+
const api = value.api;
|
|
414
|
+
if (!api || 'object' != typeof api || Array.isArray(api)) return changed;
|
|
415
|
+
if (void 0 !== api.backendFederation) {
|
|
416
|
+
delete api.backendFederation;
|
|
417
|
+
changed = true;
|
|
418
|
+
}
|
|
254
419
|
const oldEffect = api.effect;
|
|
255
420
|
if (oldEffect && 'object' == typeof oldEffect && !Array.isArray(oldEffect)) {
|
|
256
421
|
if (void 0 === api.stem && 'string' == typeof oldEffect.stem) {
|
|
@@ -312,6 +477,38 @@ function normalizeStrictEffectApiMetadata(value) {
|
|
|
312
477
|
}
|
|
313
478
|
return changed;
|
|
314
479
|
}
|
|
480
|
+
function removeGeneratedFileIfExists(io, relativePath) {
|
|
481
|
+
return io.remove(external_node_path_default().join(io.workspaceRoot, relativePath));
|
|
482
|
+
}
|
|
483
|
+
function removeStaleBackendFederationArtifacts(io, config) {
|
|
484
|
+
let changed = false;
|
|
485
|
+
for (const relativePath of [
|
|
486
|
+
"scripts/generate-node-backend-federation.mts",
|
|
487
|
+
"scripts/proof-node-backend-federation.mts",
|
|
488
|
+
"scripts/verify-cloudflare-output.mts"
|
|
489
|
+
])changed = removeGeneratedFileIfExists(io, relativePath) || changed;
|
|
490
|
+
for (const app of (0, external_config_cjs_namespaceObject.workspaceAppsFromToolingConfig)(config))changed = removeGeneratedFileIfExists(io, external_node_path_default().join(app.directory, 'api/backend-federation.ts')) || changed;
|
|
491
|
+
return changed;
|
|
492
|
+
}
|
|
493
|
+
function updateGeneratedZeropsArtifacts(io, config) {
|
|
494
|
+
const apps = (0, external_config_cjs_namespaceObject.workspaceAppsFromToolingConfig)(config);
|
|
495
|
+
let changed = writeTextIfChanged(io, external_node_path_default().join(io.workspaceRoot, 'zerops.yaml'), `${(0, zerops_cjs_namespaceObject.createZeropsYaml)(config.workspace.packageScope, apps)}\n`);
|
|
496
|
+
changed = writeTextIfChanged(io, external_node_path_default().join(io.workspaceRoot, "scripts/materialize-zerops-runtime.mjs"), (0, workspace_scripts_cjs_namespaceObject.createZeropsRuntimeMaterializationScript)()) || changed;
|
|
497
|
+
return changed;
|
|
498
|
+
}
|
|
499
|
+
function updateGeneratedBuildIdentityModules(io, config) {
|
|
500
|
+
let changed = false;
|
|
501
|
+
for (const app of (0, external_config_cjs_namespaceObject.workspaceAppsFromToolingConfig)(config)){
|
|
502
|
+
changed = writeTextIfChanged(io, external_node_path_default().join(io.workspaceRoot, app.directory, 'src/ultramodern-build.ts'), (0, module_federation_cjs_namespaceObject.createUltramodernBuildReexportModule)()) || changed;
|
|
503
|
+
changed = writeTextIfChanged(io, external_node_path_default().join(io.workspaceRoot, app.directory, 'shared/ultramodern-build.ts'), (0, module_federation_cjs_namespaceObject.createUltramodernBuildModule)(config.workspace.packageScope, app)) || changed;
|
|
504
|
+
}
|
|
505
|
+
return changed;
|
|
506
|
+
}
|
|
507
|
+
function updateGeneratedBackendFederationContractFiles(io, config) {
|
|
508
|
+
let changed = false;
|
|
509
|
+
for (const app of (0, external_config_cjs_namespaceObject.workspaceAppsFromToolingConfig)(config))if (app.api) changed = writeTextIfChanged(io, external_node_path_default().join(io.workspaceRoot, app.directory, 'api/backend-federation.ts'), (0, backend_federation_cjs_namespaceObject.createBackendFederationContractFile)(app)) || changed;
|
|
510
|
+
return changed;
|
|
511
|
+
}
|
|
315
512
|
function replaceYamlLine(source, pattern, replacement) {
|
|
316
513
|
const updated = source.replace(pattern, replacement);
|
|
317
514
|
return {
|
|
@@ -322,16 +519,17 @@ function replaceYamlLine(source, pattern, replacement) {
|
|
|
322
519
|
function ensureYamlListItem(source, key, item) {
|
|
323
520
|
const itemLine = ` - '${item}'`;
|
|
324
521
|
const headerPattern = new RegExp(`^${key}:\\n(?:(?: - .+\\n)*)`, 'mu');
|
|
325
|
-
const existingItemPattern = new RegExp(`^ - '${item.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&')}'$`, 'mu');
|
|
326
|
-
if (existingItemPattern.test(source)) return {
|
|
327
|
-
source,
|
|
328
|
-
changed: false
|
|
329
|
-
};
|
|
330
522
|
const header = source.match(headerPattern);
|
|
331
|
-
if (header)
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
523
|
+
if (header) {
|
|
524
|
+
if (header[0].split('\n').includes(itemLine)) return {
|
|
525
|
+
source,
|
|
526
|
+
changed: false
|
|
527
|
+
};
|
|
528
|
+
return {
|
|
529
|
+
source: source.replace(headerPattern, `${header[0]}${itemLine}\n`),
|
|
530
|
+
changed: true
|
|
531
|
+
};
|
|
532
|
+
}
|
|
335
533
|
const block = `${key}:\n${itemLine}\n`;
|
|
336
534
|
const afterTrustPolicyIgnore = source.replace(/^(trustPolicyIgnoreAfter: .+\n)/mu, `$1${block}`);
|
|
337
535
|
if (afterTrustPolicyIgnore !== source) return {
|
|
@@ -343,43 +541,203 @@ function ensureYamlListItem(source, key, item) {
|
|
|
343
541
|
changed: true
|
|
344
542
|
};
|
|
345
543
|
}
|
|
346
|
-
function
|
|
347
|
-
const
|
|
544
|
+
function yamlEntryPattern(entryKey, scalar = false) {
|
|
545
|
+
const bareKey = entryKey.replace(/^['"]|['"]$/gu, '');
|
|
546
|
+
if (scalar) {
|
|
547
|
+
const esc = bareKey.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&');
|
|
548
|
+
return new RegExp(`^ {2}(?:'${esc}'|"${esc}"|${esc}): .+$`, 'gmu');
|
|
549
|
+
}
|
|
550
|
+
const packageName = bareKey.includes('@') ? bareKey.slice(0, bareKey.lastIndexOf('@')) : bareKey;
|
|
551
|
+
const esc = packageName.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&');
|
|
552
|
+
return new RegExp(`^ {2}(?:'${esc}@[^']+'|"${esc}@[^"]+"|${esc}@[^:'"\\s]+): .+$`, 'gmu');
|
|
553
|
+
}
|
|
554
|
+
function upsertYamlEntry(source, key, entryLine, pattern) {
|
|
555
|
+
const linePattern = new RegExp(pattern.source, 'u');
|
|
556
|
+
const lines = source.split('\n');
|
|
557
|
+
let seen = false;
|
|
558
|
+
let changed = false;
|
|
559
|
+
const out = [];
|
|
560
|
+
for (const line of lines)if (linePattern.test(line)) {
|
|
561
|
+
if (seen) {
|
|
562
|
+
changed = true;
|
|
563
|
+
continue;
|
|
564
|
+
}
|
|
565
|
+
seen = true;
|
|
566
|
+
if (line !== entryLine) changed = true;
|
|
567
|
+
out.push(entryLine);
|
|
568
|
+
} else out.push(line);
|
|
569
|
+
if (seen) return {
|
|
570
|
+
source: out.join('\n'),
|
|
571
|
+
changed
|
|
572
|
+
};
|
|
573
|
+
const headerPattern = new RegExp(`^${key}:\\n(?:(?: .+\\n)*)`, 'mu');
|
|
574
|
+
const header = source.match(headerPattern);
|
|
575
|
+
if (header) {
|
|
576
|
+
if (header[0].split('\n').includes(entryLine)) return {
|
|
577
|
+
source,
|
|
578
|
+
changed: false
|
|
579
|
+
};
|
|
580
|
+
return {
|
|
581
|
+
source: source.replace(headerPattern, `${header[0]}${entryLine}\n`),
|
|
582
|
+
changed: true
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
return {
|
|
586
|
+
source: `${source.trimEnd()}\n${key}:\n${entryLine}\n`,
|
|
587
|
+
changed: true
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
function ensureYamlMapEntry(source, key, entryKey, value) {
|
|
591
|
+
return upsertYamlEntry(source, key, ` '${entryKey}': ${value}`, yamlEntryPattern(entryKey));
|
|
592
|
+
}
|
|
593
|
+
function ensureYamlScalarMapEntry(source, key, entryKey, value) {
|
|
594
|
+
return upsertYamlEntry(source, key, ` ${entryKey}: ${value}`, yamlEntryPattern(entryKey, true));
|
|
595
|
+
}
|
|
596
|
+
function removeYamlMapEntry(source, entryKey) {
|
|
597
|
+
const linePattern = new RegExp(yamlEntryPattern(entryKey).source, 'u');
|
|
598
|
+
const lines = source.split('\n');
|
|
599
|
+
let changed = false;
|
|
600
|
+
const out = [];
|
|
601
|
+
for (const line of lines){
|
|
602
|
+
if (linePattern.test(line)) {
|
|
603
|
+
changed = true;
|
|
604
|
+
continue;
|
|
605
|
+
}
|
|
606
|
+
out.push(line);
|
|
607
|
+
}
|
|
608
|
+
return changed ? {
|
|
609
|
+
source: out.join('\n'),
|
|
610
|
+
changed
|
|
611
|
+
} : {
|
|
612
|
+
source,
|
|
613
|
+
changed
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
function ensureGeneratedPatchFile(io, relativePatchPath, sourcePatchPath) {
|
|
617
|
+
const targetPath = external_node_path_default().join(io.workspaceRoot, relativePatchPath);
|
|
618
|
+
const patch = external_node_fs_default().readFileSync(sourcePatchPath, 'utf-8');
|
|
619
|
+
return io.write(targetPath, patch);
|
|
620
|
+
}
|
|
621
|
+
function removeGeneratedPatchFileIfUnchanged(io, relativePatchPath, sourcePatchPath) {
|
|
622
|
+
const targetPath = external_node_path_default().join(io.workspaceRoot, relativePatchPath);
|
|
623
|
+
if (!external_node_fs_default().existsSync(targetPath)) return false;
|
|
624
|
+
const patch = external_node_fs_default().readFileSync(sourcePatchPath, 'utf-8');
|
|
625
|
+
if (external_node_fs_default().readFileSync(targetPath, 'utf-8') !== patch) return false;
|
|
626
|
+
return io.remove(targetPath);
|
|
627
|
+
}
|
|
628
|
+
function workspaceUsesDependency(workspaceRoot, packageName) {
|
|
629
|
+
const packageJsonPaths = [
|
|
630
|
+
external_node_path_default().join(workspaceRoot, 'package.json')
|
|
631
|
+
];
|
|
632
|
+
for (const workspaceDir of [
|
|
633
|
+
'apps',
|
|
634
|
+
'verticals',
|
|
635
|
+
'packages'
|
|
636
|
+
]){
|
|
637
|
+
const absoluteWorkspaceDir = external_node_path_default().join(workspaceRoot, workspaceDir);
|
|
638
|
+
if (external_node_fs_default().existsSync(absoluteWorkspaceDir)) for (const entry of external_node_fs_default().readdirSync(absoluteWorkspaceDir, {
|
|
639
|
+
withFileTypes: true
|
|
640
|
+
})){
|
|
641
|
+
if (!entry.isDirectory()) continue;
|
|
642
|
+
const packageJsonPath = external_node_path_default().join(absoluteWorkspaceDir, entry.name, 'package.json');
|
|
643
|
+
if (external_node_fs_default().existsSync(packageJsonPath)) packageJsonPaths.push(packageJsonPath);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
for (const packageJsonPath of packageJsonPaths){
|
|
647
|
+
const packageJson = JSON.parse(external_node_fs_default().readFileSync(packageJsonPath, 'utf-8'));
|
|
648
|
+
for (const field of [
|
|
649
|
+
'dependencies',
|
|
650
|
+
'devDependencies',
|
|
651
|
+
'peerDependencies',
|
|
652
|
+
'optionalDependencies'
|
|
653
|
+
]){
|
|
654
|
+
const dependencies = packageJson[field];
|
|
655
|
+
if (dependencies && 'object' == typeof dependencies) {
|
|
656
|
+
if (Object.prototype.hasOwnProperty.call(dependencies, packageName)) return true;
|
|
657
|
+
for (const specifier of Object.values(dependencies))if ('string' == typeof specifier && specifier.startsWith(`npm:${packageName}@`)) return true;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
return false;
|
|
662
|
+
}
|
|
663
|
+
function ensureGeneratedDeclarationPatches(io, options) {
|
|
664
|
+
let changed = false;
|
|
665
|
+
changed = ensureGeneratedPatchFile(io, moduleFederationModernJsPatchPath, moduleFederationModernJsPatchSourcePath) || changed;
|
|
666
|
+
changed = ensureGeneratedPatchFile(io, moduleFederationBridgeReactPatchPath, moduleFederationBridgeReactPatchSourcePath) || changed;
|
|
667
|
+
changed = ensureGeneratedPatchFile(io, effectDeclarationPatchPath, effectDeclarationPatchSourcePath) || changed;
|
|
668
|
+
changed = options.includeDrizzleOrmPatch ? ensureGeneratedPatchFile(io, drizzleOrmDeclarationPatchPath, drizzleOrmDeclarationPatchSourcePath) || changed : removeGeneratedPatchFileIfUnchanged(io, drizzleOrmDeclarationPatchPath, drizzleOrmDeclarationPatchSourcePath) || changed;
|
|
669
|
+
return changed;
|
|
670
|
+
}
|
|
671
|
+
function updateGeneratedPnpmWorkspacePolicy(io) {
|
|
672
|
+
const workspaceFile = external_node_path_default().join(io.workspaceRoot, 'pnpm-workspace.yaml');
|
|
348
673
|
if (!external_node_fs_default().existsSync(workspaceFile)) return false;
|
|
349
674
|
let source = external_node_fs_default().readFileSync(workspaceFile, 'utf-8');
|
|
350
675
|
let changed = false;
|
|
676
|
+
const usesDrizzleOrm = workspaceUsesDependency(io.workspaceRoot, 'drizzle-orm');
|
|
351
677
|
const replacements = [
|
|
352
678
|
[
|
|
353
679
|
/^ {4}'@effect\/vitest>effect': .+$/mu,
|
|
354
680
|
` '@effect/vitest>effect': '${versions_cjs_namespaceObject.EFFECT_VERSION}'`
|
|
355
|
-
]
|
|
681
|
+
]
|
|
682
|
+
];
|
|
683
|
+
for (const [pattern, replacement] of replacements){
|
|
684
|
+
const result = replaceYamlLine(source, pattern, replacement);
|
|
685
|
+
source = result.source;
|
|
686
|
+
changed = result.changed || changed;
|
|
687
|
+
}
|
|
688
|
+
for (const [entryKey, version] of [
|
|
356
689
|
[
|
|
357
|
-
|
|
358
|
-
|
|
690
|
+
"'@effect/opentelemetry'",
|
|
691
|
+
versions_cjs_namespaceObject.EFFECT_VERSION
|
|
359
692
|
],
|
|
360
693
|
[
|
|
361
|
-
|
|
362
|
-
|
|
694
|
+
"'@effect/vitest'",
|
|
695
|
+
versions_cjs_namespaceObject.EFFECT_VITEST_VERSION
|
|
363
696
|
],
|
|
364
697
|
[
|
|
365
|
-
|
|
366
|
-
|
|
698
|
+
'effect',
|
|
699
|
+
versions_cjs_namespaceObject.EFFECT_VERSION
|
|
367
700
|
]
|
|
368
|
-
]
|
|
369
|
-
|
|
370
|
-
const result = replaceYamlLine(source, pattern, replacement);
|
|
701
|
+
]){
|
|
702
|
+
const result = ensureYamlScalarMapEntry(source, 'overrides', entryKey, version);
|
|
371
703
|
source = result.source;
|
|
372
704
|
changed = result.changed || changed;
|
|
373
705
|
}
|
|
374
|
-
const
|
|
375
|
-
source =
|
|
376
|
-
changed =
|
|
377
|
-
|
|
706
|
+
const parcelWatcherBuildPolicy = ensureYamlScalarMapEntry(source, 'allowBuilds', "'@parcel/watcher'", 'true');
|
|
707
|
+
source = parcelWatcherBuildPolicy.source;
|
|
708
|
+
changed = parcelWatcherBuildPolicy.changed || changed;
|
|
709
|
+
for (const item of strictEffectPackageVersionPolicyExclusions){
|
|
710
|
+
const packageName = item.slice(0, item.lastIndexOf('@'));
|
|
711
|
+
const escapedPackageName = packageName.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&');
|
|
712
|
+
const currentVersion = replaceYamlLine(source, new RegExp(`^ {2}- '${escapedPackageName}@[^']+'$`, 'gmu'), ` - '${item}'`);
|
|
713
|
+
source = currentVersion.source;
|
|
714
|
+
changed = currentVersion.changed || changed;
|
|
715
|
+
for (const policyKey of [
|
|
716
|
+
'minimumReleaseAgeExclude',
|
|
717
|
+
'trustPolicyExclude'
|
|
718
|
+
]){
|
|
719
|
+
const policyExclude = ensureYamlListItem(source, policyKey, item);
|
|
720
|
+
source = policyExclude.source;
|
|
721
|
+
changed = policyExclude.changed || changed;
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
const effectPatch = ensureYamlMapEntry(source, 'patchedDependencies', `effect@${versions_cjs_namespaceObject.EFFECT_VERSION}`, effectDeclarationPatchPath);
|
|
725
|
+
source = effectPatch.source;
|
|
726
|
+
changed = effectPatch.changed || changed;
|
|
727
|
+
const moduleFederationModernJsPatch = ensureYamlMapEntry(source, 'patchedDependencies', `@module-federation/modern-js-v3@${versions_cjs_namespaceObject.MODULE_FEDERATION_VERSION}`, moduleFederationModernJsPatchPath);
|
|
728
|
+
source = moduleFederationModernJsPatch.source;
|
|
729
|
+
changed = moduleFederationModernJsPatch.changed || changed;
|
|
730
|
+
const moduleFederationBridgeReactPatch = ensureYamlMapEntry(source, 'patchedDependencies', `@module-federation/bridge-react@${versions_cjs_namespaceObject.MODULE_FEDERATION_VERSION}`, moduleFederationBridgeReactPatchPath);
|
|
731
|
+
source = moduleFederationBridgeReactPatch.source;
|
|
732
|
+
changed = moduleFederationBridgeReactPatch.changed || changed;
|
|
733
|
+
const drizzleOrmPatch = usesDrizzleOrm ? ensureYamlMapEntry(source, 'patchedDependencies', `drizzle-orm@${versions_cjs_namespaceObject.DRIZZLE_ORM_VERSION}`, drizzleOrmDeclarationPatchPath) : removeYamlMapEntry(source, `drizzle-orm@${versions_cjs_namespaceObject.DRIZZLE_ORM_VERSION}`);
|
|
734
|
+
source = drizzleOrmPatch.source;
|
|
735
|
+
changed = drizzleOrmPatch.changed || changed;
|
|
736
|
+
if (changed) io.write(workspaceFile, source);
|
|
378
737
|
return changed;
|
|
379
738
|
}
|
|
380
|
-
function updateUltramodernConfig(
|
|
381
|
-
const configPath = external_node_path_default().join(workspaceRoot, '.modernjs/ultramodern.json');
|
|
382
|
-
const config = readJsonFile(configPath);
|
|
739
|
+
function updateUltramodernConfig(io, config, packageSource) {
|
|
740
|
+
const configPath = external_node_path_default().join(io.workspaceRoot, '.modernjs/ultramodern.json');
|
|
383
741
|
config.packageSource = {
|
|
384
742
|
strategy: packageSource.strategy,
|
|
385
743
|
modernPackageVersion: packageSource.modernPackageVersion,
|
|
@@ -393,16 +751,147 @@ function updateUltramodernConfig(workspaceRoot, packageSource) {
|
|
|
393
751
|
aliasPackageNamePrefix: packageSource.aliasPackageNamePrefix
|
|
394
752
|
} : {}
|
|
395
753
|
};
|
|
754
|
+
if (config.generator && 'object' == typeof config.generator && !Array.isArray(config.generator) && 'string' == typeof config.generator.version) config.generator.version = packageSource.modernPackageVersion;
|
|
396
755
|
for (const app of config.topology?.apps ?? [])if (app && 'object' == typeof app && !Array.isArray(app)) normalizeStrictEffectApiMetadata(app);
|
|
397
|
-
writeJsonFile(configPath, config);
|
|
756
|
+
writeJsonFile(io, configPath, config);
|
|
757
|
+
}
|
|
758
|
+
function writeJsonIfChanged(io, filePath, value) {
|
|
759
|
+
return io.write(filePath, `${JSON.stringify(value, null, 2)}\n`);
|
|
760
|
+
}
|
|
761
|
+
function writeTextIfChanged(io, filePath, value) {
|
|
762
|
+
return io.write(filePath, value);
|
|
398
763
|
}
|
|
399
|
-
function
|
|
400
|
-
const
|
|
764
|
+
function ensureGeneratedIgnoreRules(io) {
|
|
765
|
+
const gitignorePath = external_node_path_default().join(io.workspaceRoot, '.gitignore');
|
|
766
|
+
const existing = external_node_fs_default().existsSync(gitignorePath) ? external_node_fs_default().readFileSync(gitignorePath, 'utf-8') : '';
|
|
767
|
+
const lines = 0 === existing.trimEnd().length ? [] : existing.trimEnd().split(/\r?\n/u);
|
|
768
|
+
let changed = false;
|
|
769
|
+
for (const rule of [
|
|
770
|
+
'.mf/',
|
|
771
|
+
'**/.mf/',
|
|
772
|
+
'dist-cloudflare/',
|
|
773
|
+
'.output/',
|
|
774
|
+
'**/.output/',
|
|
775
|
+
'.modern-js/',
|
|
776
|
+
'**/.modern-js/'
|
|
777
|
+
])if (!lines.includes(rule)) {
|
|
778
|
+
lines.push(rule);
|
|
779
|
+
changed = true;
|
|
780
|
+
}
|
|
781
|
+
if (!changed) return false;
|
|
782
|
+
return io.write(gitignorePath, `${lines.join('\n')}\n`);
|
|
783
|
+
}
|
|
784
|
+
function updateGeneratedTypeScriptSurfaces(io, config) {
|
|
785
|
+
let changed = false;
|
|
786
|
+
const apps = (0, external_config_cjs_namespaceObject.workspaceAppsFromToolingConfig)(config);
|
|
787
|
+
const remotes = apps.filter((app)=>'shell' !== app.kind);
|
|
788
|
+
changed = writeJsonIfChanged(io, external_node_path_default().join(io.workspaceRoot, 'tsconfig.base.json'), (0, package_json_cjs_namespaceObject.createTsConfigBase)()) || changed;
|
|
789
|
+
changed = ensureGeneratedIgnoreRules(io) || changed;
|
|
790
|
+
for (const sharedPackage of [
|
|
791
|
+
'packages/shared-contracts',
|
|
792
|
+
'packages/shared-design-tokens'
|
|
793
|
+
])changed = writeJsonIfChanged(io, external_node_path_default().join(io.workspaceRoot, sharedPackage, 'tsconfig.json'), (0, package_json_cjs_namespaceObject.createSharedPackageTsConfig)(sharedPackage)) || changed;
|
|
794
|
+
for (const app of apps){
|
|
795
|
+
changed = writeJsonIfChanged(io, external_node_path_default().join(io.workspaceRoot, app.directory, 'tsconfig.json'), (0, package_json_cjs_namespaceObject.createAppTsConfig)(app, remotes)) || changed;
|
|
796
|
+
changed = writeJsonIfChanged(io, external_node_path_default().join(io.workspaceRoot, app.directory, 'tsconfig.mf-types.json'), (0, package_json_cjs_namespaceObject.createAppMfTypesTsConfig)(app)) || changed;
|
|
797
|
+
changed = writeTextIfChanged(io, external_node_path_default().join(io.workspaceRoot, app.directory, 'src/modern-app-env.d.ts'), (0, app_files_cjs_namespaceObject.createAppEnvDts)(app, remotes)) || changed;
|
|
798
|
+
}
|
|
799
|
+
return changed;
|
|
800
|
+
}
|
|
801
|
+
function updateGeneratedModernConfigs(io, config) {
|
|
802
|
+
let changed = false;
|
|
803
|
+
const apps = (0, external_config_cjs_namespaceObject.workspaceAppsFromToolingConfig)(config);
|
|
804
|
+
const remotes = apps.filter((app)=>'shell' !== app.kind);
|
|
805
|
+
for (const app of apps)changed = writeTextIfChanged(io, external_node_path_default().join(io.workspaceRoot, app.directory, 'modern.config.ts'), (0, module_federation_cjs_namespaceObject.createAppModernConfig)(config.workspace.packageScope, app, remotes)) || changed;
|
|
806
|
+
return changed;
|
|
807
|
+
}
|
|
808
|
+
function ensureGeneratedOxfmtIgnorePatterns(io) {
|
|
809
|
+
const configPath = external_node_path_default().join(io.workspaceRoot, 'oxfmt.config.ts');
|
|
810
|
+
if (!external_node_fs_default().existsSync(configPath)) return false;
|
|
811
|
+
const source = external_node_fs_default().readFileSync(configPath, 'utf-8');
|
|
812
|
+
const requiredPatterns = [
|
|
813
|
+
'.modernjs',
|
|
814
|
+
'.output',
|
|
815
|
+
'**/modern-tanstack/**',
|
|
816
|
+
'**/routeTree.gen.*'
|
|
817
|
+
];
|
|
818
|
+
const warnUnparseable = ()=>{
|
|
819
|
+
const message = `Could not update oxfmt.config.ts ignorePatterns automatically; add these entries manually: ${requiredPatterns.join(', ')}.`;
|
|
820
|
+
if (io.dryRun) io.log(message);
|
|
821
|
+
else process.stderr.write(`[ultramodern] ${message}\n`);
|
|
822
|
+
};
|
|
823
|
+
const anchor = source.indexOf('ignorePatterns:');
|
|
824
|
+
if (-1 === anchor) {
|
|
825
|
+
warnUnparseable();
|
|
826
|
+
return false;
|
|
827
|
+
}
|
|
828
|
+
const openBracket = source.indexOf('[', anchor);
|
|
829
|
+
if (-1 === openBracket) {
|
|
830
|
+
warnUnparseable();
|
|
831
|
+
return false;
|
|
832
|
+
}
|
|
833
|
+
let depth = 0;
|
|
834
|
+
let closeBracket = -1;
|
|
835
|
+
let stringQuote;
|
|
836
|
+
for(let index = openBracket; index < source.length; index += 1){
|
|
837
|
+
const char = source[index];
|
|
838
|
+
if (stringQuote) {
|
|
839
|
+
if ('\\' === char) index += 1;
|
|
840
|
+
else if (char === stringQuote) stringQuote = void 0;
|
|
841
|
+
continue;
|
|
842
|
+
}
|
|
843
|
+
if ("'" === char || '"' === char || '`' === char) stringQuote = char;
|
|
844
|
+
else if ('[' === char) depth += 1;
|
|
845
|
+
else if (']' === char) {
|
|
846
|
+
depth -= 1;
|
|
847
|
+
if (0 === depth) {
|
|
848
|
+
closeBracket = index;
|
|
849
|
+
break;
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
if (-1 === closeBracket) {
|
|
854
|
+
warnUnparseable();
|
|
855
|
+
return false;
|
|
856
|
+
}
|
|
857
|
+
const body = source.slice(openBracket + 1, closeBracket);
|
|
858
|
+
if (body.includes('...')) {
|
|
859
|
+
warnUnparseable();
|
|
860
|
+
return false;
|
|
861
|
+
}
|
|
862
|
+
const literalPattern = /(['"`])((?:\\.|(?!\1).)*)\1/g;
|
|
863
|
+
const existing = new Set();
|
|
864
|
+
for (const match of body.matchAll(literalPattern))existing.add(match[2]);
|
|
865
|
+
const missing = requiredPatterns.filter((pattern)=>!existing.has(pattern));
|
|
866
|
+
if (0 === missing.length) return false;
|
|
867
|
+
const bodyLines = body.split('\n');
|
|
868
|
+
let indent = ' ';
|
|
869
|
+
let quote = "'";
|
|
870
|
+
for(let index = bodyLines.length - 1; index >= 0; index -= 1){
|
|
871
|
+
const literal = bodyLines[index].match(/^(\s*)(['"`])/u);
|
|
872
|
+
if (literal) {
|
|
873
|
+
indent = literal[1];
|
|
874
|
+
quote = literal[2];
|
|
875
|
+
break;
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
const head = source.slice(0, closeBracket);
|
|
879
|
+
const rest = source.slice(closeBracket);
|
|
880
|
+
const tailMatch = head.match(/(\r?\n[ \t]*)$/u);
|
|
881
|
+
const tail = tailMatch ? tailMatch[1] : '\n';
|
|
882
|
+
let bodyContent = tailMatch ? head.slice(0, head.length - tail.length) : head;
|
|
883
|
+
if (!/[[,]\s*$/u.test(bodyContent)) bodyContent = `${bodyContent},`;
|
|
884
|
+
const insertionLines = missing.map((pattern)=>`${indent}${quote}${pattern}${quote},`).join('\n');
|
|
885
|
+
const nextSource = `${bodyContent}\n${insertionLines}${tail}${rest}`;
|
|
886
|
+
return io.write(configPath, nextSource);
|
|
887
|
+
}
|
|
888
|
+
function updateReferenceTopology(io) {
|
|
889
|
+
const topologyPath = external_node_path_default().join(io.workspaceRoot, 'topology/reference-topology.json');
|
|
401
890
|
if (!external_node_fs_default().existsSync(topologyPath)) return false;
|
|
402
891
|
const topology = readJsonFile(topologyPath);
|
|
403
892
|
let changed = false;
|
|
404
893
|
for (const vertical of topology.verticals ?? [])if (vertical && 'object' == typeof vertical && !Array.isArray(vertical)) changed = normalizeStrictEffectApiMetadata(vertical) || changed;
|
|
405
|
-
if (changed) writeJsonFile(topologyPath, topology);
|
|
894
|
+
if (changed) writeJsonFile(io, topologyPath, topology);
|
|
406
895
|
return changed;
|
|
407
896
|
}
|
|
408
897
|
function createMigrationPackageSource(args, current) {
|
|
@@ -455,21 +944,69 @@ function runPnpmLockfileRefresh(context) {
|
|
|
455
944
|
function runMigrateStrictEffect(args, context) {
|
|
456
945
|
if (args.includes('--help') || args.includes('-h')) {
|
|
457
946
|
process.stdout.write(`Usage:
|
|
458
|
-
modern-js-create ultramodern migrate-strict-effect --version <version> [--skip-install]
|
|
947
|
+
modern-js-create ultramodern migrate-strict-effect --version <version> [--dry-run] [--skip-install]
|
|
459
948
|
|
|
460
949
|
Updates generated UltraModern package-source metadata, Modern package aliases,
|
|
461
950
|
framework-owned toolchain pins, direct Effect API topology metadata, strict
|
|
462
|
-
Effect pnpm overrides/trust policy,
|
|
463
|
-
has to pass pnpm api:check
|
|
951
|
+
Effect pnpm overrides/trust policy, framework-owned TypeScript config
|
|
952
|
+
surfaces, and the pnpm lockfile. Source code still has to pass pnpm api:check
|
|
953
|
+
and pnpm contract:check.
|
|
954
|
+
|
|
955
|
+
When the compact config is absent but legacy UltraModern 3.2 metadata is
|
|
956
|
+
present, the compact config is synthesized from it first. Shell-only
|
|
957
|
+
workspaces skip the backend-federation and Zerops runtime stages. Pass
|
|
958
|
+
--dry-run to print the planned filesystem changes without writing anything
|
|
959
|
+
(implies --skip-install).
|
|
464
960
|
`);
|
|
465
961
|
return 0;
|
|
466
962
|
}
|
|
467
|
-
const
|
|
963
|
+
const dryRun = hasFlag(args, '--dry-run');
|
|
964
|
+
const skipInstall = dryRun || hasFlag(args, '--skip-install');
|
|
965
|
+
const io = createMigrationIo(context.workspaceRoot, dryRun);
|
|
966
|
+
const compactPath = external_node_path_default().join(io.workspaceRoot, '.modernjs/ultramodern.json');
|
|
967
|
+
let raw;
|
|
968
|
+
if (external_node_fs_default().existsSync(compactPath)) raw = readJsonFile(compactPath);
|
|
969
|
+
else {
|
|
970
|
+
const synthesized = (0, external_config_cjs_namespaceObject.synthesizeCompactUltramodernConfig)(io.workspaceRoot);
|
|
971
|
+
if (!synthesized) throw new Error("Missing .modernjs/ultramodern.json and no legacy UltraModern metadata (.modernjs/ultramodern-generated-contract.json) was found to synthesize it from.");
|
|
972
|
+
raw = synthesized.compact;
|
|
973
|
+
io.write(compactPath, `${JSON.stringify(raw, null, 2)}\n`);
|
|
974
|
+
io.log(`Synthesized .modernjs/ultramodern.json from legacy metadata: ${synthesized.sources.join(', ')}.`);
|
|
975
|
+
if (synthesized.missing.length > 0) io.log(`Legacy metadata not found (using defaults): ${synthesized.missing.join(', ')}.`);
|
|
976
|
+
}
|
|
977
|
+
const current = (0, external_config_cjs_namespaceObject.normalizeCompactUltramodernConfig)(io.workspaceRoot, raw);
|
|
468
978
|
const packageSource = createMigrationPackageSource(args, current);
|
|
469
|
-
updateUltramodernConfig(
|
|
470
|
-
updateReferenceTopology(
|
|
471
|
-
|
|
472
|
-
|
|
979
|
+
updateUltramodernConfig(io, raw, packageSource);
|
|
980
|
+
updateReferenceTopology(io);
|
|
981
|
+
const migrated = (0, external_config_cjs_namespaceObject.normalizeCompactUltramodernConfig)(io.workspaceRoot, raw);
|
|
982
|
+
const migratedApps = (0, external_config_cjs_namespaceObject.workspaceAppsFromToolingConfig)(migrated);
|
|
983
|
+
const shellOnly = !migrated.topology.apps.some((app)=>app.api);
|
|
984
|
+
if (shellOnly) {
|
|
985
|
+
io.log('Shell-only workspace: skipping backend-federation and Zerops runtime stages.');
|
|
986
|
+
for (const relativePath of [
|
|
987
|
+
"scripts/generate-node-backend-federation.mts",
|
|
988
|
+
"scripts/generate-node-backend-federation.mjs",
|
|
989
|
+
"scripts/proof-node-backend-federation.mts",
|
|
990
|
+
"scripts/proof-node-backend-federation.mjs",
|
|
991
|
+
"scripts/materialize-zerops-runtime.mjs",
|
|
992
|
+
'zerops.yaml'
|
|
993
|
+
])removeGeneratedFileIfExists(io, relativePath);
|
|
994
|
+
} else {
|
|
995
|
+
removeStaleBackendFederationArtifacts(io, migrated);
|
|
996
|
+
updateGeneratedZeropsArtifacts(io, migrated);
|
|
997
|
+
updateGeneratedBackendFederationContractFiles(io, migrated);
|
|
998
|
+
}
|
|
999
|
+
for (const artifact of (0, workspace_scripts_cjs_namespaceObject.migratedWorkspaceScriptArtifacts)({
|
|
1000
|
+
shellOnly
|
|
1001
|
+
})){
|
|
1002
|
+
if (artifact.legacyPath) io.remove(external_node_path_default().join(io.workspaceRoot, artifact.legacyPath));
|
|
1003
|
+
io.write(external_node_path_default().join(io.workspaceRoot, artifact.relativePath), artifact.content);
|
|
1004
|
+
}
|
|
1005
|
+
updateGeneratedBuildIdentityModules(io, migrated);
|
|
1006
|
+
updateGeneratedTypeScriptSurfaces(io, migrated);
|
|
1007
|
+
updateGeneratedModernConfigs(io, migrated);
|
|
1008
|
+
for (const relativePackageFile of listWorkspacePackageFiles(io.workspaceRoot)){
|
|
1009
|
+
const packageFile = external_node_path_default().join(io.workspaceRoot, relativePackageFile);
|
|
473
1010
|
const packageJson = readJsonFile(packageFile);
|
|
474
1011
|
if ('package.json' === relativePackageFile) {
|
|
475
1012
|
packageJson.modernjs ??= {};
|
|
@@ -478,17 +1015,29 @@ has to pass pnpm api:check and pnpm contract:check.
|
|
|
478
1015
|
config: './.modernjs/ultramodern.json'
|
|
479
1016
|
};
|
|
480
1017
|
}
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
1018
|
+
updateModernDependencies(packageJson, packageSource);
|
|
1019
|
+
updateGeneratedToolingDependencies(packageJson);
|
|
1020
|
+
updateGeneratedPackageScripts(packageJson, {
|
|
1021
|
+
relativePackageFile,
|
|
1022
|
+
apps: migratedApps,
|
|
1023
|
+
shellOnly
|
|
1024
|
+
});
|
|
1025
|
+
writeJsonFile(io, packageFile, packageJson);
|
|
1026
|
+
}
|
|
1027
|
+
updateGeneratedPnpmWorkspacePolicy(io);
|
|
1028
|
+
ensureGeneratedDeclarationPatches(io, {
|
|
1029
|
+
includeDrizzleOrmPatch: workspaceUsesDependency(io.workspaceRoot, 'drizzle-orm')
|
|
1030
|
+
});
|
|
1031
|
+
ensureGeneratedOxfmtIgnorePatterns(io);
|
|
1032
|
+
if (!skipInstall) {
|
|
489
1033
|
const status = runPnpmLockfileRefresh(context);
|
|
490
1034
|
if (0 !== status) return status;
|
|
491
1035
|
}
|
|
1036
|
+
if (dryRun) {
|
|
1037
|
+
for (const line of io.plan)process.stdout.write(`${line}\n`);
|
|
1038
|
+
process.stdout.write(`[dry-run] migrate-strict-effect would migrate UltraModern strict Effect metadata to ${packageSource.modernPackageVersion}.\n`);
|
|
1039
|
+
return 0;
|
|
1040
|
+
}
|
|
492
1041
|
process.stdout.write(`UltraModern strict Effect metadata migrated to ${packageSource.modernPackageVersion}. Run pnpm api:check && pnpm contract:check next.\n`);
|
|
493
1042
|
return 0;
|
|
494
1043
|
}
|
|
@@ -501,6 +1050,154 @@ function runSkills(args, context) {
|
|
|
501
1050
|
], context);
|
|
502
1051
|
throw new Error('Usage: modern-js-create ultramodern skills <install|check>');
|
|
503
1052
|
}
|
|
1053
|
+
const resolveCloudflareOutputVerifyTargets = (args, context)=>{
|
|
1054
|
+
const outputDirectory = readOption(args, '--output');
|
|
1055
|
+
const appId = readOption(args, '--app');
|
|
1056
|
+
if (outputDirectory && appId) throw new Error('Use either --app or --output, not both.');
|
|
1057
|
+
const targets = outputDirectory ? [
|
|
1058
|
+
{
|
|
1059
|
+
label: outputDirectory,
|
|
1060
|
+
outputDirectory: external_node_path_default().resolve(context.invocationCwd, outputDirectory)
|
|
1061
|
+
}
|
|
1062
|
+
] : (0, external_config_cjs_namespaceObject.workspaceAppsFromToolingConfig)((0, external_config_cjs_namespaceObject.readUltramodernConfig)(context.workspaceRoot)).filter((app)=>!appId || app.id === appId).map((app)=>({
|
|
1063
|
+
label: app.id,
|
|
1064
|
+
outputDirectory: external_node_path_default().join(context.workspaceRoot, app.directory, '.output')
|
|
1065
|
+
}));
|
|
1066
|
+
if (0 === targets.length) throw new Error(`No generated UltraModern app matched ${appId}.`);
|
|
1067
|
+
return targets;
|
|
1068
|
+
};
|
|
1069
|
+
const renderCloudflareOutputVerifyModule = ({ workspaceRoot, targets, scanRoots, importWorker })=>`
|
|
1070
|
+
import { createRequire } from 'node:module';
|
|
1071
|
+
import path from 'node:path';
|
|
1072
|
+
|
|
1073
|
+
const workspaceRoot = ${JSON.stringify(workspaceRoot)};
|
|
1074
|
+
const targets = ${JSON.stringify(targets, null, 2)};
|
|
1075
|
+
const scanRoots = ${JSON.stringify(scanRoots)};
|
|
1076
|
+
const verifierRequire = createRequire(path.join(workspaceRoot, 'package.json'));
|
|
1077
|
+
const {
|
|
1078
|
+
verifyCloudflareOutput,
|
|
1079
|
+
verifyCloudflareOutputMutationPolicy,
|
|
1080
|
+
} = verifierRequire('@modern-js/app-tools/cloudflare-output-verifier');
|
|
1081
|
+
|
|
1082
|
+
let failed = false;
|
|
1083
|
+
for (const target of targets) {
|
|
1084
|
+
const result = await verifyCloudflareOutput({
|
|
1085
|
+
outputDirectory: target.outputDirectory,
|
|
1086
|
+
importWorker: ${JSON.stringify(importWorker)},
|
|
1087
|
+
});
|
|
1088
|
+
if (result.ok) {
|
|
1089
|
+
console.log(\`[ultramodern] Cloudflare output verified: \${target.label}\`);
|
|
1090
|
+
} else {
|
|
1091
|
+
failed = true;
|
|
1092
|
+
console.error(\`[ultramodern] Cloudflare output failed: \${target.label}\`);
|
|
1093
|
+
for (const issue of result.issues) {
|
|
1094
|
+
console.error(\`- \${issue.code}: \${issue.message}\${issue.path ? \` (\${issue.path})\` : ''}\`);
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
if (scanRoots.length > 0) {
|
|
1100
|
+
const policyResult = await verifyCloudflareOutputMutationPolicy({ scanRoots });
|
|
1101
|
+
if (!policyResult.ok) {
|
|
1102
|
+
failed = true;
|
|
1103
|
+
console.error('[ultramodern] generated-output mutation policy failed');
|
|
1104
|
+
for (const issue of policyResult.issues) {
|
|
1105
|
+
console.error(\`- \${issue.code}: \${issue.message}\${issue.path ? \` (\${issue.path})\` : ''}\`);
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
process.exit(failed ? 1 : 0);
|
|
1111
|
+
`;
|
|
1112
|
+
function runCloudflareOutputVerify(args, context) {
|
|
1113
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
1114
|
+
process.stdout.write(`Usage:
|
|
1115
|
+
modern-js-create ultramodern cloudflare-output-verify [--app <id> | --output <dir>] [--no-import-worker] [--no-source-scan]
|
|
1116
|
+
|
|
1117
|
+
Verifies generated Cloudflare output against the UltraModern worker contract.
|
|
1118
|
+
Without --app or --output, every generated workspace app is verified.
|
|
1119
|
+
`);
|
|
1120
|
+
return 0;
|
|
1121
|
+
}
|
|
1122
|
+
const source = renderCloudflareOutputVerifyModule({
|
|
1123
|
+
workspaceRoot: context.workspaceRoot,
|
|
1124
|
+
targets: resolveCloudflareOutputVerifyTargets(args, context),
|
|
1125
|
+
scanRoots: hasFlag(args, '--no-source-scan') ? [] : [
|
|
1126
|
+
context.workspaceRoot
|
|
1127
|
+
],
|
|
1128
|
+
importWorker: !hasFlag(args, '--no-import-worker')
|
|
1129
|
+
});
|
|
1130
|
+
return runRenderedModule(source, context);
|
|
1131
|
+
}
|
|
1132
|
+
const resolveRoutesGenerateTargets = (args, context)=>{
|
|
1133
|
+
const appId = readOption(args, '--app');
|
|
1134
|
+
const targets = (0, external_config_cjs_namespaceObject.workspaceAppsFromToolingConfig)((0, external_config_cjs_namespaceObject.readUltramodernConfig)(context.workspaceRoot)).filter((app)=>!appId || app.id === appId).map((app)=>({
|
|
1135
|
+
label: app.id,
|
|
1136
|
+
appDirectory: external_node_path_default().join(context.workspaceRoot, app.directory)
|
|
1137
|
+
}));
|
|
1138
|
+
if (0 === targets.length) throw new Error(`No generated UltraModern app matched ${appId ?? '<any>'}.`);
|
|
1139
|
+
return targets;
|
|
1140
|
+
};
|
|
1141
|
+
const renderRoutesGenerateModule = ({ workspaceRoot, targets })=>`
|
|
1142
|
+
import { createRequire } from 'node:module';
|
|
1143
|
+
import path from 'node:path';
|
|
1144
|
+
import { pathToFileURL } from 'node:url';
|
|
1145
|
+
|
|
1146
|
+
const workspaceRoot = ${JSON.stringify(workspaceRoot)};
|
|
1147
|
+
const targets = ${JSON.stringify(targets, null, 2)};
|
|
1148
|
+
const appRequire = createRequire(path.join(workspaceRoot, 'package.json'));
|
|
1149
|
+
const pluginUrl = pathToFileURL(
|
|
1150
|
+
appRequire.resolve('@modern-js/plugin-tanstack'),
|
|
1151
|
+
).href;
|
|
1152
|
+
const { generateTanstackRouteArtifacts } = await import(pluginUrl);
|
|
1153
|
+
|
|
1154
|
+
let failed = false;
|
|
1155
|
+
// Sequential — the app-tools cli singleton is not re-entrant.
|
|
1156
|
+
for (const target of targets) {
|
|
1157
|
+
try {
|
|
1158
|
+
await generateTanstackRouteArtifacts({ appDirectory: target.appDirectory });
|
|
1159
|
+
console.log(\`[ultramodern] TanStack route artifacts generated: \${target.label}\`);
|
|
1160
|
+
} catch (error) {
|
|
1161
|
+
failed = true;
|
|
1162
|
+
console.error(\`[ultramodern] TanStack route generation failed: \${target.label}\`);
|
|
1163
|
+
// Print the full underlying failure, including the cause chain. The
|
|
1164
|
+
// route-generate crash is often an opaque node error thrown deep inside
|
|
1165
|
+
// app-tools/plugin (e.g. a path TypeError), so surfacing only
|
|
1166
|
+
// \`error.message\` swallows the stack that points at the real culprit.
|
|
1167
|
+
let current = error;
|
|
1168
|
+
let depth = 0;
|
|
1169
|
+
while (current) {
|
|
1170
|
+
const label = depth === 0 ? '-' : ' caused by:';
|
|
1171
|
+
const detail =
|
|
1172
|
+
current instanceof Error
|
|
1173
|
+
? current.stack ?? \`\${current.name}: \${current.message}\`
|
|
1174
|
+
: String(current);
|
|
1175
|
+
console.error(\`\${label} \${detail}\`);
|
|
1176
|
+
current = current instanceof Error ? current.cause : undefined;
|
|
1177
|
+
depth += 1;
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
process.exit(failed ? 1 : 0);
|
|
1183
|
+
`;
|
|
1184
|
+
function runRoutesGenerate(args, context) {
|
|
1185
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
1186
|
+
process.stdout.write(`Usage:
|
|
1187
|
+
modern-js-create ultramodern routes-generate [--app <id>]
|
|
1188
|
+
|
|
1189
|
+
Regenerates TanStack route artifacts (router.gen.ts, register.gen.d.ts) for
|
|
1190
|
+
generated UltraModern apps without running dev or build. Without --app, every
|
|
1191
|
+
generated workspace app is regenerated.
|
|
1192
|
+
`);
|
|
1193
|
+
return 0;
|
|
1194
|
+
}
|
|
1195
|
+
const source = renderRoutesGenerateModule({
|
|
1196
|
+
workspaceRoot: context.workspaceRoot,
|
|
1197
|
+
targets: resolveRoutesGenerateTargets(args, context)
|
|
1198
|
+
});
|
|
1199
|
+
return runRenderedModule(source, context);
|
|
1200
|
+
}
|
|
504
1201
|
async function runUltramodernToolingCli(args, workspaceRoot = process.env.ULTRAMODERN_WORKSPACE_ROOT ?? process.cwd()) {
|
|
505
1202
|
try {
|
|
506
1203
|
const [command, ...rest] = args;
|
|
@@ -514,25 +1211,25 @@ async function runUltramodernToolingCli(args, workspaceRoot = process.env.ULTRAM
|
|
|
514
1211
|
case '-h':
|
|
515
1212
|
printHelp();
|
|
516
1213
|
return 0;
|
|
517
|
-
case
|
|
1214
|
+
case tooling_command_catalog_cjs_namespaceObject.GENERATED_TOOLING_COMMANDS.validate.command:
|
|
518
1215
|
return runValidate(context);
|
|
519
|
-
case
|
|
520
|
-
return spawnNodeScript("templates/workspace-scripts/ultramodern-typecheck.mjs", rest, context, {
|
|
521
|
-
cwd: context.invocationCwd
|
|
522
|
-
});
|
|
523
|
-
case 'mf-types':
|
|
1216
|
+
case tooling_command_catalog_cjs_namespaceObject.GENERATED_TOOLING_COMMANDS.mfTypes.command:
|
|
524
1217
|
return runMfTypes(rest, context);
|
|
525
|
-
case
|
|
1218
|
+
case tooling_command_catalog_cjs_namespaceObject.GENERATED_TOOLING_COMMANDS.migrateStrictEffect.command:
|
|
526
1219
|
return runMigrateStrictEffect(rest, context);
|
|
527
|
-
case
|
|
528
|
-
return
|
|
529
|
-
case
|
|
530
|
-
return
|
|
531
|
-
case '
|
|
532
|
-
return
|
|
1220
|
+
case tooling_command_catalog_cjs_namespaceObject.GENERATED_TOOLING_COMMANDS.cloudflareOutputVerify.command:
|
|
1221
|
+
return runCloudflareOutputVerify(rest, context);
|
|
1222
|
+
case tooling_command_catalog_cjs_namespaceObject.GENERATED_TOOLING_COMMANDS.routesGenerate.command:
|
|
1223
|
+
return runRoutesGenerate(rest, context);
|
|
1224
|
+
case 'sync-delivery-unit':
|
|
1225
|
+
return (0, delivery_unit_sync_cjs_namespaceObject.runSyncDeliveryUnit)(rest, context);
|
|
533
1226
|
case 'skills':
|
|
534
1227
|
return runSkills(rest, context);
|
|
535
1228
|
default:
|
|
1229
|
+
{
|
|
1230
|
+
const templateBackedStatus = runTemplateBackedToolingCommand(command ?? '', rest, context);
|
|
1231
|
+
if (void 0 !== templateBackedStatus) return templateBackedStatus;
|
|
1232
|
+
}
|
|
536
1233
|
throw new Error(`Unknown UltraModern command: ${command}`);
|
|
537
1234
|
}
|
|
538
1235
|
} catch (error) {
|