@bleedingdev/modern-js-create 3.5.0-ultramodern.0 → 3.5.0-ultramodern.10
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 +28 -0
- package/dist/cjs/ultramodern-tooling/commands.cjs +399 -0
- package/dist/cjs/ultramodern-workspace/contracts.cjs +1 -0
- package/dist/cjs/ultramodern-workspace/module-federation.cjs +6 -0
- package/dist/cjs/ultramodern-workspace/package-json.cjs +2 -1
- package/dist/cjs/ultramodern-workspace/versions.cjs +12 -2
- package/dist/cjs/ultramodern-workspace/workspace-scripts.cjs +1 -0
- package/dist/cjs/ultramodern-workspace/write-workspace.cjs +2 -0
- package/dist/esm/ultramodern-tooling/commands.js +399 -0
- package/dist/esm/ultramodern-workspace/contracts.js +1 -0
- package/dist/esm/ultramodern-workspace/module-federation.js +6 -0
- package/dist/esm/ultramodern-workspace/package-json.js +2 -1
- package/dist/esm/ultramodern-workspace/versions.js +7 -3
- package/dist/esm/ultramodern-workspace/workspace-scripts.js +1 -0
- package/dist/esm/ultramodern-workspace/write-workspace.js +3 -1
- package/dist/esm-node/ultramodern-tooling/commands.js +399 -0
- package/dist/esm-node/ultramodern-workspace/contracts.js +1 -0
- package/dist/esm-node/ultramodern-workspace/module-federation.js +6 -0
- package/dist/esm-node/ultramodern-workspace/package-json.js +2 -1
- package/dist/esm-node/ultramodern-workspace/versions.js +7 -3
- package/dist/esm-node/ultramodern-workspace/workspace-scripts.js +1 -0
- package/dist/esm-node/ultramodern-workspace/write-workspace.js +3 -1
- package/dist/types/ultramodern-workspace/versions.d.ts +6 -2
- package/package.json +6 -6
- package/template-workspace/README.md.handlebars +44 -1
- package/template-workspace/pnpm-workspace.yaml.handlebars +8 -0
- package/templates/workspace-scripts/check-ultramodern-api-boundaries.mts +30 -8
- package/templates/workspace-scripts/validate-ultramodern-workspace.mjs.handlebars +23 -0
package/README.md
CHANGED
|
@@ -189,6 +189,34 @@ mise exec -- pnpm check
|
|
|
189
189
|
mise exec -- pnpm build
|
|
190
190
|
```
|
|
191
191
|
|
|
192
|
+
For strict Effect API migrations, update generated package metadata and Modern
|
|
193
|
+
package aliases through the framework command before hand-editing app code:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
pnpm dlx @bleedingdev/modern-js-create@3.5.0-ultramodern.10 ultramodern \
|
|
197
|
+
migrate-strict-effect --version 3.5.0-ultramodern.10
|
|
198
|
+
pnpm api:check
|
|
199
|
+
pnpm contract:check
|
|
200
|
+
pnpm check
|
|
201
|
+
pnpm build
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
The command updates `.modernjs/ultramodern.json`, root `modernjs.packageSource`,
|
|
205
|
+
generated Modern package aliases, framework-owned toolchain pins, old direct
|
|
206
|
+
topology metadata, strict Effect pnpm overrides/trust policy, and the pnpm
|
|
207
|
+
lockfile. It does not invent compatibility shims or move business code behind
|
|
208
|
+
your back. If `pnpm api:check` still fails, migrate the source to
|
|
209
|
+
`shared/api.ts`, `api/index.ts`, and `src/api/*-client.ts` and delete
|
|
210
|
+
`api/effect`, `api/lambda`, `shared/effect`, and `src/effect` paths.
|
|
211
|
+
|
|
212
|
+
Generated strict Effect workspaces pin the compatible Effect cohort through
|
|
213
|
+
`pnpm-workspace.yaml` overrides: `effect@4.0.0-beta.91` and
|
|
214
|
+
`@effect/vitest@4.0.0-beta.91`. The generated pnpm policy also excludes the
|
|
215
|
+
known `effect@4.0.0-beta.91` and `@effect/opentelemetry@4.0.0-beta.91`
|
|
216
|
+
versions from the 24-hour minimum-release-age gate and their trusted-publisher
|
|
217
|
+
to provenance transitions from no-downgrade checks. Do not override those in
|
|
218
|
+
app packages; update the framework cohort when the runtime moves.
|
|
219
|
+
|
|
192
220
|
Use `--ultramodern-package-source=install` for published cohort proof and pin a
|
|
193
221
|
specific release with `--ultramodern-package-version` when CI must prove an
|
|
194
222
|
exact framework version. Keep `--workspace` only for local monorepo testing
|
|
@@ -51,7 +51,9 @@ const external_node_path_namespaceObject = require("node:path");
|
|
|
51
51
|
var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
|
|
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
|
+
const external_ultramodern_package_source_cjs_namespaceObject = require("../ultramodern-package-source.cjs");
|
|
54
55
|
const mf_validation_cjs_namespaceObject = require("../ultramodern-workspace/mf-validation.cjs");
|
|
56
|
+
const versions_cjs_namespaceObject = require("../ultramodern-workspace/versions.cjs");
|
|
55
57
|
const workspace_scripts_cjs_namespaceObject = require("../ultramodern-workspace/workspace-scripts.cjs");
|
|
56
58
|
const external_config_cjs_namespaceObject = require("./config.cjs");
|
|
57
59
|
const commands_dirname = external_node_path_default().dirname((0, external_node_url_namespaceObject.fileURLToPath)(__rslib_import_meta_url__));
|
|
@@ -64,6 +66,7 @@ Commands:
|
|
|
64
66
|
validate
|
|
65
67
|
typecheck
|
|
66
68
|
mf-types
|
|
69
|
+
migrate-strict-effect
|
|
67
70
|
public-surface
|
|
68
71
|
cloudflare-proof
|
|
69
72
|
performance-readiness
|
|
@@ -129,6 +132,400 @@ Checks real Module Federation config files and DTS archives for exposed apps.
|
|
|
129
132
|
});
|
|
130
133
|
return 0;
|
|
131
134
|
}
|
|
135
|
+
const modernPackageNames = new Set([
|
|
136
|
+
...external_ultramodern_package_source_cjs_namespaceObject.ULTRAMODERN_SINGLE_APP_MODERN_PACKAGES,
|
|
137
|
+
...external_ultramodern_package_source_cjs_namespaceObject.ULTRAMODERN_WORKSPACE_MODERN_PACKAGES
|
|
138
|
+
]);
|
|
139
|
+
function readJsonFile(filePath) {
|
|
140
|
+
return JSON.parse(external_node_fs_default().readFileSync(filePath, 'utf-8'));
|
|
141
|
+
}
|
|
142
|
+
function writeJsonFile(filePath, value) {
|
|
143
|
+
external_node_fs_default().writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`, 'utf-8');
|
|
144
|
+
}
|
|
145
|
+
function readOption(args, name) {
|
|
146
|
+
const prefix = `${name}=`;
|
|
147
|
+
const inline = args.find((arg)=>arg.startsWith(prefix));
|
|
148
|
+
if (inline) {
|
|
149
|
+
const value = inline.slice(prefix.length);
|
|
150
|
+
if (!value) throw new Error(`${name} needs a value.`);
|
|
151
|
+
return value;
|
|
152
|
+
}
|
|
153
|
+
const index = args.indexOf(name);
|
|
154
|
+
if (-1 === index) return;
|
|
155
|
+
const value = args[index + 1];
|
|
156
|
+
if (!value || value.startsWith('--')) throw new Error(`${name} needs a value.`);
|
|
157
|
+
return value;
|
|
158
|
+
}
|
|
159
|
+
function hasFlag(args, name) {
|
|
160
|
+
return args.includes(name);
|
|
161
|
+
}
|
|
162
|
+
function listWorkspacePackageFiles(workspaceRoot) {
|
|
163
|
+
const packageFiles = [
|
|
164
|
+
'package.json'
|
|
165
|
+
];
|
|
166
|
+
for (const directory of [
|
|
167
|
+
'apps',
|
|
168
|
+
'verticals',
|
|
169
|
+
'packages'
|
|
170
|
+
]){
|
|
171
|
+
const absoluteDirectory = external_node_path_default().join(workspaceRoot, directory);
|
|
172
|
+
if (external_node_fs_default().existsSync(absoluteDirectory)) for (const entry of external_node_fs_default().readdirSync(absoluteDirectory, {
|
|
173
|
+
withFileTypes: true
|
|
174
|
+
})){
|
|
175
|
+
if (!entry.isDirectory()) continue;
|
|
176
|
+
const packageFile = external_node_path_default().join(directory, entry.name, 'package.json');
|
|
177
|
+
if (external_node_fs_default().existsSync(external_node_path_default().join(workspaceRoot, packageFile))) packageFiles.push(packageFile);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return packageFiles;
|
|
181
|
+
}
|
|
182
|
+
function updateModernDependencies(packageJson, packageSource) {
|
|
183
|
+
let changed = false;
|
|
184
|
+
for (const section of [
|
|
185
|
+
'dependencies',
|
|
186
|
+
'devDependencies',
|
|
187
|
+
'peerDependencies',
|
|
188
|
+
'optionalDependencies'
|
|
189
|
+
]){
|
|
190
|
+
const dependencies = packageJson[section];
|
|
191
|
+
if (!(!dependencies || 'object' != typeof dependencies || Array.isArray(dependencies))) for (const packageName of Object.keys(dependencies)){
|
|
192
|
+
if (!modernPackageNames.has(packageName)) continue;
|
|
193
|
+
const nextSpecifier = (0, external_ultramodern_package_source_cjs_namespaceObject.modernPackageSpecifier)(packageName, packageSource);
|
|
194
|
+
if (dependencies[packageName] !== nextSpecifier) {
|
|
195
|
+
dependencies[packageName] = nextSpecifier;
|
|
196
|
+
changed = true;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return changed;
|
|
201
|
+
}
|
|
202
|
+
const generatedToolingDependencyPins = new Map([
|
|
203
|
+
[
|
|
204
|
+
'@effect/tsgo',
|
|
205
|
+
versions_cjs_namespaceObject.EFFECT_TSGO_VERSION
|
|
206
|
+
],
|
|
207
|
+
[
|
|
208
|
+
"@typescript/native-preview",
|
|
209
|
+
versions_cjs_namespaceObject.TYPESCRIPT_NATIVE_PREVIEW_VERSION
|
|
210
|
+
],
|
|
211
|
+
[
|
|
212
|
+
'oxfmt',
|
|
213
|
+
versions_cjs_namespaceObject.OXFMT_VERSION
|
|
214
|
+
],
|
|
215
|
+
[
|
|
216
|
+
'oxlint',
|
|
217
|
+
versions_cjs_namespaceObject.OXLINT_VERSION
|
|
218
|
+
],
|
|
219
|
+
[
|
|
220
|
+
'wrangler',
|
|
221
|
+
versions_cjs_namespaceObject.WRANGLER_VERSION
|
|
222
|
+
],
|
|
223
|
+
[
|
|
224
|
+
'zephyr-agent',
|
|
225
|
+
versions_cjs_namespaceObject.ZEPHYR_AGENT_VERSION
|
|
226
|
+
],
|
|
227
|
+
[
|
|
228
|
+
'zephyr-rspack-plugin',
|
|
229
|
+
versions_cjs_namespaceObject.ZEPHYR_RSPACK_PLUGIN_VERSION
|
|
230
|
+
]
|
|
231
|
+
]);
|
|
232
|
+
const strictEffectPackageVersionPolicyExclusions = [
|
|
233
|
+
`effect@${versions_cjs_namespaceObject.EFFECT_VERSION}`,
|
|
234
|
+
`@effect/opentelemetry@${versions_cjs_namespaceObject.EFFECT_VERSION}`
|
|
235
|
+
];
|
|
236
|
+
function updateGeneratedToolingDependencies(packageJson) {
|
|
237
|
+
let changed = false;
|
|
238
|
+
for (const section of [
|
|
239
|
+
'dependencies',
|
|
240
|
+
'devDependencies',
|
|
241
|
+
'peerDependencies',
|
|
242
|
+
'optionalDependencies'
|
|
243
|
+
]){
|
|
244
|
+
const dependencies = packageJson[section];
|
|
245
|
+
if (!(!dependencies || 'object' != typeof dependencies || Array.isArray(dependencies))) {
|
|
246
|
+
for (const [packageName, version] of generatedToolingDependencyPins)if (Object.prototype.hasOwnProperty.call(dependencies, packageName) && dependencies[packageName] !== version) {
|
|
247
|
+
dependencies[packageName] = version;
|
|
248
|
+
changed = true;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return changed;
|
|
253
|
+
}
|
|
254
|
+
const cloudflareModernDeployCommand = 'ULTRAMODERN_ZEPHYR=false MODERNJS_DEPLOY=cloudflare modern deploy';
|
|
255
|
+
const cloudflareModernDeploySkipBuildCommand = `${cloudflareModernDeployCommand} --skip-build`;
|
|
256
|
+
const cloudflareWranglerDeployCommand = 'wrangler deploy --config .output/wrangler.json';
|
|
257
|
+
const cloudflareWranglerDeployInvalidSkipBuildCommand = `${cloudflareWranglerDeployCommand} --skip-build`;
|
|
258
|
+
function updateGeneratedPackageScripts(packageJson) {
|
|
259
|
+
const scripts = packageJson.scripts;
|
|
260
|
+
if (!scripts || 'object' != typeof scripts || Array.isArray(scripts)) return false;
|
|
261
|
+
let changed = false;
|
|
262
|
+
const cloudflareBuild = scripts['cloudflare:build'];
|
|
263
|
+
if ('string' == typeof cloudflareBuild && cloudflareBuild.includes(cloudflareModernDeployCommand) && !cloudflareBuild.includes(cloudflareModernDeploySkipBuildCommand)) {
|
|
264
|
+
scripts['cloudflare:build'] = cloudflareBuild.replace(cloudflareModernDeployCommand, cloudflareModernDeploySkipBuildCommand);
|
|
265
|
+
changed = true;
|
|
266
|
+
}
|
|
267
|
+
const cloudflareDeploy = scripts['cloudflare:deploy'];
|
|
268
|
+
if ('string' == typeof cloudflareDeploy && cloudflareDeploy.includes(cloudflareWranglerDeployInvalidSkipBuildCommand)) {
|
|
269
|
+
scripts['cloudflare:deploy'] = cloudflareDeploy.replace(cloudflareWranglerDeployInvalidSkipBuildCommand, cloudflareWranglerDeployCommand);
|
|
270
|
+
changed = true;
|
|
271
|
+
}
|
|
272
|
+
return changed;
|
|
273
|
+
}
|
|
274
|
+
function normalizeStrictEffectApiMetadata(value) {
|
|
275
|
+
const api = value.api;
|
|
276
|
+
if (!api || 'object' != typeof api || Array.isArray(api)) return false;
|
|
277
|
+
let changed = false;
|
|
278
|
+
const oldEffect = api.effect;
|
|
279
|
+
if (oldEffect && 'object' == typeof oldEffect && !Array.isArray(oldEffect)) {
|
|
280
|
+
if (void 0 === api.stem && 'string' == typeof oldEffect.stem) {
|
|
281
|
+
api.stem = oldEffect.stem;
|
|
282
|
+
changed = true;
|
|
283
|
+
}
|
|
284
|
+
if (void 0 === api.prefix && 'string' == typeof oldEffect.prefix) {
|
|
285
|
+
api.prefix = oldEffect.prefix;
|
|
286
|
+
changed = true;
|
|
287
|
+
}
|
|
288
|
+
if (void 0 === api.consumedBy && Array.isArray(oldEffect.consumedBy)) {
|
|
289
|
+
api.consumedBy = oldEffect.consumedBy;
|
|
290
|
+
changed = true;
|
|
291
|
+
}
|
|
292
|
+
delete api.effect;
|
|
293
|
+
changed = true;
|
|
294
|
+
}
|
|
295
|
+
if (void 0 !== api.runtime && 'effect' !== api.runtime) {
|
|
296
|
+
api.runtime = 'effect';
|
|
297
|
+
changed = true;
|
|
298
|
+
}
|
|
299
|
+
if (api.bff && 'object' == typeof api.bff && !Array.isArray(api.bff)) {
|
|
300
|
+
if (true !== api.bff.strictEffectApproach) {
|
|
301
|
+
api.bff.strictEffectApproach = true;
|
|
302
|
+
changed = true;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
if ('string' == typeof value.path) {
|
|
306
|
+
const directServerEntry = `${value.path}/api/index.ts`;
|
|
307
|
+
if ('string' == typeof api.serverEntry && /\/api\/effect\/index\.[cm]?[jt]sx?$/u.test(api.serverEntry)) {
|
|
308
|
+
api.serverEntry = directServerEntry;
|
|
309
|
+
changed = true;
|
|
310
|
+
}
|
|
311
|
+
if (api.contract && 'object' == typeof api.contract && !Array.isArray(api.contract)) {
|
|
312
|
+
if ('./shared/effect/api' === api.contract.export) {
|
|
313
|
+
api.contract.export = './api';
|
|
314
|
+
changed = true;
|
|
315
|
+
}
|
|
316
|
+
if ('string' == typeof api.contract.path && /\/shared\/effect\/api\.[cm]?[jt]sx?$/u.test(api.contract.path)) {
|
|
317
|
+
api.contract.path = `${value.path}/shared/api.ts`;
|
|
318
|
+
changed = true;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
if (api.client && 'object' == typeof api.client && !Array.isArray(api.client)) {
|
|
322
|
+
if ('./effect/client' === api.client.export) {
|
|
323
|
+
api.client.export = './api/client';
|
|
324
|
+
changed = true;
|
|
325
|
+
}
|
|
326
|
+
if ('string' == typeof api.client.path && /\/src\/effect\/[^/]+-client\.[cm]?ts$/u.test(api.client.path)) {
|
|
327
|
+
const basename = external_node_path_default().basename(api.client.path);
|
|
328
|
+
api.client.path = `${value.path}/src/api/${basename}`;
|
|
329
|
+
changed = true;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
if (void 0 === api.serverEntry && 'effect' === api.runtime) {
|
|
333
|
+
api.serverEntry = directServerEntry;
|
|
334
|
+
changed = true;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
return changed;
|
|
338
|
+
}
|
|
339
|
+
function replaceYamlLine(source, pattern, replacement) {
|
|
340
|
+
const updated = source.replace(pattern, replacement);
|
|
341
|
+
return {
|
|
342
|
+
source: updated,
|
|
343
|
+
changed: updated !== source
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
function ensureYamlListItem(source, key, item) {
|
|
347
|
+
const itemLine = ` - '${item}'`;
|
|
348
|
+
const headerPattern = new RegExp(`^${key}:\\n(?:(?: - .+\\n)*)`, 'mu');
|
|
349
|
+
const header = source.match(headerPattern);
|
|
350
|
+
if (header) {
|
|
351
|
+
if (header[0].split('\n').includes(itemLine)) return {
|
|
352
|
+
source,
|
|
353
|
+
changed: false
|
|
354
|
+
};
|
|
355
|
+
return {
|
|
356
|
+
source: source.replace(headerPattern, `${header[0]}${itemLine}\n`),
|
|
357
|
+
changed: true
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
const block = `${key}:\n${itemLine}\n`;
|
|
361
|
+
const afterTrustPolicyIgnore = source.replace(/^(trustPolicyIgnoreAfter: .+\n)/mu, `$1${block}`);
|
|
362
|
+
if (afterTrustPolicyIgnore !== source) return {
|
|
363
|
+
source: afterTrustPolicyIgnore,
|
|
364
|
+
changed: true
|
|
365
|
+
};
|
|
366
|
+
return {
|
|
367
|
+
source: `${source.trimEnd()}\n${block}`,
|
|
368
|
+
changed: true
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
function updateGeneratedPnpmWorkspacePolicy(workspaceRoot) {
|
|
372
|
+
const workspaceFile = external_node_path_default().join(workspaceRoot, 'pnpm-workspace.yaml');
|
|
373
|
+
if (!external_node_fs_default().existsSync(workspaceFile)) return false;
|
|
374
|
+
let source = external_node_fs_default().readFileSync(workspaceFile, 'utf-8');
|
|
375
|
+
let changed = false;
|
|
376
|
+
const replacements = [
|
|
377
|
+
[
|
|
378
|
+
/^ {4}'@effect\/vitest>effect': .+$/mu,
|
|
379
|
+
` '@effect/vitest>effect': '${versions_cjs_namespaceObject.EFFECT_VERSION}'`
|
|
380
|
+
],
|
|
381
|
+
[
|
|
382
|
+
/^ {2}'@effect\/vitest': .+$/mu,
|
|
383
|
+
` '@effect/vitest': ${versions_cjs_namespaceObject.EFFECT_VITEST_VERSION}`
|
|
384
|
+
],
|
|
385
|
+
[
|
|
386
|
+
/^ {2}effect: .+$/mu,
|
|
387
|
+
` effect: ${versions_cjs_namespaceObject.EFFECT_VERSION}`
|
|
388
|
+
]
|
|
389
|
+
];
|
|
390
|
+
for (const [pattern, replacement] of replacements){
|
|
391
|
+
const result = replaceYamlLine(source, pattern, replacement);
|
|
392
|
+
source = result.source;
|
|
393
|
+
changed = result.changed || changed;
|
|
394
|
+
}
|
|
395
|
+
for (const item of strictEffectPackageVersionPolicyExclusions){
|
|
396
|
+
const packageName = item.slice(0, item.lastIndexOf('@'));
|
|
397
|
+
const escapedPackageName = packageName.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&');
|
|
398
|
+
const currentVersion = replaceYamlLine(source, new RegExp(`^ {2}- '${escapedPackageName}@[^']+'$`, 'gmu'), ` - '${item}'`);
|
|
399
|
+
source = currentVersion.source;
|
|
400
|
+
changed = currentVersion.changed || changed;
|
|
401
|
+
for (const policyKey of [
|
|
402
|
+
'minimumReleaseAgeExclude',
|
|
403
|
+
'trustPolicyExclude'
|
|
404
|
+
]){
|
|
405
|
+
const policyExclude = ensureYamlListItem(source, policyKey, item);
|
|
406
|
+
source = policyExclude.source;
|
|
407
|
+
changed = policyExclude.changed || changed;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
if (changed) external_node_fs_default().writeFileSync(workspaceFile, source, 'utf-8');
|
|
411
|
+
return changed;
|
|
412
|
+
}
|
|
413
|
+
function updateUltramodernConfig(workspaceRoot, packageSource) {
|
|
414
|
+
const configPath = external_node_path_default().join(workspaceRoot, '.modernjs/ultramodern.json');
|
|
415
|
+
const config = readJsonFile(configPath);
|
|
416
|
+
config.packageSource = {
|
|
417
|
+
strategy: packageSource.strategy,
|
|
418
|
+
modernPackageVersion: packageSource.modernPackageVersion,
|
|
419
|
+
...packageSource.registry ? {
|
|
420
|
+
registry: packageSource.registry
|
|
421
|
+
} : {},
|
|
422
|
+
...packageSource.aliasScope ? {
|
|
423
|
+
aliasScope: packageSource.aliasScope
|
|
424
|
+
} : {},
|
|
425
|
+
...packageSource.aliasPackageNamePrefix ? {
|
|
426
|
+
aliasPackageNamePrefix: packageSource.aliasPackageNamePrefix
|
|
427
|
+
} : {}
|
|
428
|
+
};
|
|
429
|
+
for (const app of config.topology?.apps ?? [])if (app && 'object' == typeof app && !Array.isArray(app)) normalizeStrictEffectApiMetadata(app);
|
|
430
|
+
writeJsonFile(configPath, config);
|
|
431
|
+
}
|
|
432
|
+
function updateReferenceTopology(workspaceRoot) {
|
|
433
|
+
const topologyPath = external_node_path_default().join(workspaceRoot, 'topology/reference-topology.json');
|
|
434
|
+
if (!external_node_fs_default().existsSync(topologyPath)) return false;
|
|
435
|
+
const topology = readJsonFile(topologyPath);
|
|
436
|
+
let changed = false;
|
|
437
|
+
for (const vertical of topology.verticals ?? [])if (vertical && 'object' == typeof vertical && !Array.isArray(vertical)) changed = normalizeStrictEffectApiMetadata(vertical) || changed;
|
|
438
|
+
if (changed) writeJsonFile(topologyPath, topology);
|
|
439
|
+
return changed;
|
|
440
|
+
}
|
|
441
|
+
function createMigrationPackageSource(args, current) {
|
|
442
|
+
const strategy = hasFlag(args, '--workspace') ? 'workspace' : 'install';
|
|
443
|
+
const registry = readOption(args, '--registry') ?? readOption(args, '--ultramodern-package-registry');
|
|
444
|
+
const explicitAliasScope = readOption(args, '--alias-scope') ?? readOption(args, '--ultramodern-package-scope');
|
|
445
|
+
const aliasScope = explicitAliasScope ?? ('install' === strategy && void 0 === registry ? current.packageSource?.aliasScope ?? external_ultramodern_package_source_cjs_namespaceObject.BLEEDINGDEV_PACKAGE_SCOPE : current.packageSource?.aliasScope);
|
|
446
|
+
const aliasPackageNamePrefix = readOption(args, '--alias-package-name-prefix') ?? readOption(args, '--ultramodern-package-name-prefix') ?? current.packageSource?.aliasPackageNamePrefix ?? (aliasScope ? external_ultramodern_package_source_cjs_namespaceObject.BLEEDINGDEV_PACKAGE_NAME_PREFIX : void 0);
|
|
447
|
+
if ('workspace' === strategy) return {
|
|
448
|
+
strategy,
|
|
449
|
+
modernPackageVersion: external_ultramodern_package_source_cjs_namespaceObject.WORKSPACE_PACKAGE_VERSION,
|
|
450
|
+
...registry ? {
|
|
451
|
+
registry
|
|
452
|
+
} : {},
|
|
453
|
+
...aliasScope ? {
|
|
454
|
+
aliasScope
|
|
455
|
+
} : {},
|
|
456
|
+
...aliasPackageNamePrefix ? {
|
|
457
|
+
aliasPackageNamePrefix
|
|
458
|
+
} : {}
|
|
459
|
+
};
|
|
460
|
+
const version = readOption(args, '--version') ?? readOption(args, '--ultramodern-package-version') ?? current.packageSource?.modernPackageVersion;
|
|
461
|
+
if (!version || version === external_ultramodern_package_source_cjs_namespaceObject.WORKSPACE_PACKAGE_VERSION) throw new Error('migrate-strict-effect needs --version <published-ultramodern-version> for install package source.');
|
|
462
|
+
return {
|
|
463
|
+
strategy,
|
|
464
|
+
modernPackageVersion: version,
|
|
465
|
+
...registry ? {
|
|
466
|
+
registry
|
|
467
|
+
} : {},
|
|
468
|
+
...aliasScope ? {
|
|
469
|
+
aliasScope
|
|
470
|
+
} : {},
|
|
471
|
+
...aliasPackageNamePrefix ? {
|
|
472
|
+
aliasPackageNamePrefix
|
|
473
|
+
} : {}
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
function runPnpmLockfileRefresh(context) {
|
|
477
|
+
const result = (0, external_node_child_process_namespaceObject.spawnSync)('pnpm', [
|
|
478
|
+
'install',
|
|
479
|
+
'--lockfile-only',
|
|
480
|
+
"--ignore-scripts"
|
|
481
|
+
], {
|
|
482
|
+
cwd: context.workspaceRoot,
|
|
483
|
+
stdio: 'inherit'
|
|
484
|
+
});
|
|
485
|
+
if (result.error) throw result.error;
|
|
486
|
+
return result.status ?? 1;
|
|
487
|
+
}
|
|
488
|
+
function runMigrateStrictEffect(args, context) {
|
|
489
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
490
|
+
process.stdout.write(`Usage:
|
|
491
|
+
modern-js-create ultramodern migrate-strict-effect --version <version> [--skip-install]
|
|
492
|
+
|
|
493
|
+
Updates generated UltraModern package-source metadata, Modern package aliases,
|
|
494
|
+
framework-owned toolchain pins, direct Effect API topology metadata, strict
|
|
495
|
+
Effect pnpm overrides/trust policy, and the pnpm lockfile. Source code still
|
|
496
|
+
has to pass pnpm api:check and pnpm contract:check.
|
|
497
|
+
`);
|
|
498
|
+
return 0;
|
|
499
|
+
}
|
|
500
|
+
const current = (0, external_config_cjs_namespaceObject.readUltramodernConfig)(context.workspaceRoot);
|
|
501
|
+
const packageSource = createMigrationPackageSource(args, current);
|
|
502
|
+
updateUltramodernConfig(context.workspaceRoot, packageSource);
|
|
503
|
+
updateReferenceTopology(context.workspaceRoot);
|
|
504
|
+
for (const relativePackageFile of listWorkspacePackageFiles(context.workspaceRoot)){
|
|
505
|
+
const packageFile = external_node_path_default().join(context.workspaceRoot, relativePackageFile);
|
|
506
|
+
const packageJson = readJsonFile(packageFile);
|
|
507
|
+
if ('package.json' === relativePackageFile) {
|
|
508
|
+
packageJson.modernjs ??= {};
|
|
509
|
+
packageJson.modernjs.packageSource = {
|
|
510
|
+
strategy: packageSource.strategy,
|
|
511
|
+
config: './.modernjs/ultramodern.json'
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
const modernDependenciesChanged = updateModernDependencies(packageJson, packageSource);
|
|
515
|
+
const toolingDependenciesChanged = updateGeneratedToolingDependencies(packageJson);
|
|
516
|
+
const generatedScriptsChanged = updateGeneratedPackageScripts(packageJson);
|
|
517
|
+
const changed = modernDependenciesChanged || toolingDependenciesChanged || generatedScriptsChanged;
|
|
518
|
+
if (changed) writeJsonFile(packageFile, packageJson);
|
|
519
|
+
else if ('package.json' === relativePackageFile) writeJsonFile(packageFile, packageJson);
|
|
520
|
+
}
|
|
521
|
+
updateGeneratedPnpmWorkspacePolicy(context.workspaceRoot);
|
|
522
|
+
if (!hasFlag(args, '--skip-install')) {
|
|
523
|
+
const status = runPnpmLockfileRefresh(context);
|
|
524
|
+
if (0 !== status) return status;
|
|
525
|
+
}
|
|
526
|
+
process.stdout.write(`UltraModern strict Effect metadata migrated to ${packageSource.modernPackageVersion}. Run pnpm api:check && pnpm contract:check next.\n`);
|
|
527
|
+
return 0;
|
|
528
|
+
}
|
|
132
529
|
function runSkills(args, context) {
|
|
133
530
|
const [subcommand, ...rest] = args;
|
|
134
531
|
if ('install' === subcommand) return spawnNodeScript("template-workspace/scripts/bootstrap-agent-skills.mjs", rest, context);
|
|
@@ -159,6 +556,8 @@ async function runUltramodernToolingCli(args, workspaceRoot = process.env.ULTRAM
|
|
|
159
556
|
});
|
|
160
557
|
case 'mf-types':
|
|
161
558
|
return runMfTypes(rest, context);
|
|
559
|
+
case 'migrate-strict-effect':
|
|
560
|
+
return runMigrateStrictEffect(rest, context);
|
|
162
561
|
case 'public-surface':
|
|
163
562
|
return spawnNodeScript("templates/workspace-scripts/generate-public-surface-assets.mjs", rest, context);
|
|
164
563
|
case 'cloudflare-proof':
|
|
@@ -289,6 +289,7 @@ function createUltramodernConfig(scope, modernVersion, packageSource, apps = [
|
|
|
289
289
|
publicSurface: "scripts/generate-public-surface-assets.mts",
|
|
290
290
|
cloudflareProof: "scripts/proof-cloudflare-version.mts",
|
|
291
291
|
performanceReadiness: "scripts/ultramodern-performance-readiness.mts",
|
|
292
|
+
migrateStrictEffect: "scripts/migrate-strict-effect.mts",
|
|
292
293
|
apiBoundaries: "scripts/check-ultramodern-api-boundaries.mts",
|
|
293
294
|
skills: "scripts/bootstrap-agent-skills.mts"
|
|
294
295
|
}
|
|
@@ -144,6 +144,8 @@ ${defaultAssetPrefixSource}
|
|
|
144
144
|
// load remoteEntry.js and exposed chunks from the remote origin, not the host.
|
|
145
145
|
const assetPrefix =
|
|
146
146
|
configuredModernAssetPrefix || configuredUltramodernAssetPrefix || defaultAssetPrefix;
|
|
147
|
+
const buildCacheTarget = cloudflareDeployEnabled ? 'cloudflare' : 'web';
|
|
148
|
+
const buildCacheDirectory = \`node_modules/.cache/rspack-\${appId}-\${buildCacheTarget}\`;
|
|
147
149
|
|
|
148
150
|
if (
|
|
149
151
|
cloudflareDeployEnabled &&
|
|
@@ -190,6 +192,10 @@ ${bffConfig} ...(cloudflareDeployEnabled
|
|
|
190
192
|
splitRouteChunks: true,
|
|
191
193
|
},
|
|
192
194
|
performance: {
|
|
195
|
+
buildCache: {
|
|
196
|
+
cacheDigest: [appId, buildCacheTarget],
|
|
197
|
+
cacheDirectory: buildCacheDirectory,
|
|
198
|
+
},
|
|
193
199
|
rsdoctor: {
|
|
194
200
|
disableClientServer: true,
|
|
195
201
|
enabled: process.env['ULTRAMODERN_RSDOCTOR'] === 'true',
|
|
@@ -224,6 +224,7 @@ function createRootPackageJson(scope, packageSource, remotes = [], bridge) {
|
|
|
224
224
|
'agents:refs:check': "node ./scripts/setup-agent-reference-repos.mts --check",
|
|
225
225
|
'mf:types': "node ./scripts/assert-mf-types.mts",
|
|
226
226
|
'performance:readiness': "node ./scripts/ultramodern-performance-readiness.mts",
|
|
227
|
+
'migrate:strict-effect': "node ./scripts/migrate-strict-effect.mts",
|
|
227
228
|
'contract:check': "node ./scripts/validate-ultramodern-workspace.mts",
|
|
228
229
|
'api:check': "node ./scripts/check-ultramodern-api-boundaries.mts",
|
|
229
230
|
'i18n:boundaries': "node ./scripts/check-ultramodern-i18n-boundaries.mts",
|
|
@@ -416,7 +417,7 @@ function createAppPackage(scope, app, packageSource, enableTailwind, remotes = [
|
|
|
416
417
|
scripts: {
|
|
417
418
|
dev: 'modern dev',
|
|
418
419
|
build: app.exposes ? `ULTRAMODERN_ZEPHYR=false modern build && ${publicSurfaceBuildCommand} && node ${(0, external_naming_cjs_namespaceObject.relativeRootFor)(app.directory)}/scripts/assert-mf-types.mts` : `ULTRAMODERN_ZEPHYR=false modern build && ${publicSurfaceBuildCommand}`,
|
|
419
|
-
'cloudflare:build': `ULTRAMODERN_ZEPHYR=false MODERNJS_DEPLOY=cloudflare modern build && ${publicSurfaceCloudflareBuildCommand} && ULTRAMODERN_ZEPHYR=false MODERNJS_DEPLOY=cloudflare modern deploy && ${publicSurfaceCloudflareOutputCommand}`,
|
|
420
|
+
'cloudflare:build': `ULTRAMODERN_ZEPHYR=false MODERNJS_DEPLOY=cloudflare modern build && ${publicSurfaceCloudflareBuildCommand} && ULTRAMODERN_ZEPHYR=false MODERNJS_DEPLOY=cloudflare modern deploy --skip-build && ${publicSurfaceCloudflareOutputCommand}`,
|
|
420
421
|
'cloudflare:deploy': 'ULTRAMODERN_CLOUDFLARE_REQUIRE_PUBLIC_URLS=true pnpm run cloudflare:build && wrangler deploy --config .output/wrangler.json',
|
|
421
422
|
'cloudflare:preview': 'pnpm run cloudflare:build && wrangler dev --config .output/wrangler.json',
|
|
422
423
|
'cloudflare:proof': `node ${(0, external_naming_cjs_namespaceObject.relativeRootFor)(app.directory)}/scripts/proof-cloudflare-version.mts --app ${app.id}`,
|
|
@@ -37,12 +37,14 @@ const CLOUDFLARE_COMPATIBILITY_DATE = '2026-06-02';
|
|
|
37
37
|
const TAILWIND_VERSION = '4.3.1';
|
|
38
38
|
const TAILWIND_POSTCSS_VERSION = '4.3.1';
|
|
39
39
|
const POSTCSS_VERSION = '8.5.15';
|
|
40
|
+
const EFFECT_VERSION = '4.0.0-beta.91';
|
|
41
|
+
const EFFECT_VITEST_VERSION = '4.0.0-beta.91';
|
|
40
42
|
const EFFECT_TSGO_VERSION = '0.14.6';
|
|
41
43
|
const TYPESCRIPT_STABLE_VERSION = '6.0.3';
|
|
42
|
-
const TYPESCRIPT_NATIVE_PREVIEW_VERSION = '7.0.0-dev.
|
|
44
|
+
const TYPESCRIPT_NATIVE_PREVIEW_VERSION = '7.0.0-dev.20260628.1';
|
|
43
45
|
const TYPESCRIPT_VERSION = TYPESCRIPT_STABLE_VERSION;
|
|
44
46
|
const OXLINT_VERSION = '1.71.0';
|
|
45
|
-
const OXFMT_VERSION = '0.
|
|
47
|
+
const OXFMT_VERSION = '0.56.0';
|
|
46
48
|
const ULTRACITE_VERSION = '7.8.3';
|
|
47
49
|
const LEFTHOOK_VERSION = '^2.1.9';
|
|
48
50
|
const I18NEXT_VERSION = '26.3.1';
|
|
@@ -60,12 +62,16 @@ const ultramodernWorkspaceVersions = {
|
|
|
60
62
|
tanstackRouter: TANSTACK_ROUTER_VERSION,
|
|
61
63
|
tanstackRouterCore: TANSTACK_ROUTER_CORE_VERSION,
|
|
62
64
|
moduleFederation: MODULE_FEDERATION_VERSION,
|
|
65
|
+
effect: EFFECT_VERSION,
|
|
66
|
+
effectVitest: EFFECT_VITEST_VERSION,
|
|
63
67
|
tailwind: TAILWIND_VERSION,
|
|
64
68
|
tailwindPostcss: TAILWIND_POSTCSS_VERSION
|
|
65
69
|
};
|
|
66
70
|
__webpack_require__.d(__webpack_exports__, {}, {
|
|
67
71
|
CLOUDFLARE_COMPATIBILITY_DATE: CLOUDFLARE_COMPATIBILITY_DATE,
|
|
68
72
|
EFFECT_TSGO_VERSION: EFFECT_TSGO_VERSION,
|
|
73
|
+
EFFECT_VERSION: EFFECT_VERSION,
|
|
74
|
+
EFFECT_VITEST_VERSION: EFFECT_VITEST_VERSION,
|
|
69
75
|
I18NEXT_VERSION: I18NEXT_VERSION,
|
|
70
76
|
LEFTHOOK_VERSION: LEFTHOOK_VERSION,
|
|
71
77
|
MODULE_FEDERATION_AGENT_SKILLS_COMMIT: MODULE_FEDERATION_AGENT_SKILLS_COMMIT,
|
|
@@ -97,6 +103,8 @@ __webpack_require__.d(__webpack_exports__, {}, {
|
|
|
97
103
|
});
|
|
98
104
|
exports.CLOUDFLARE_COMPATIBILITY_DATE = __webpack_exports__.CLOUDFLARE_COMPATIBILITY_DATE;
|
|
99
105
|
exports.EFFECT_TSGO_VERSION = __webpack_exports__.EFFECT_TSGO_VERSION;
|
|
106
|
+
exports.EFFECT_VERSION = __webpack_exports__.EFFECT_VERSION;
|
|
107
|
+
exports.EFFECT_VITEST_VERSION = __webpack_exports__.EFFECT_VITEST_VERSION;
|
|
100
108
|
exports.I18NEXT_VERSION = __webpack_exports__.I18NEXT_VERSION;
|
|
101
109
|
exports.LEFTHOOK_VERSION = __webpack_exports__.LEFTHOOK_VERSION;
|
|
102
110
|
exports.MODULE_FEDERATION_AGENT_SKILLS_COMMIT = __webpack_exports__.MODULE_FEDERATION_AGENT_SKILLS_COMMIT;
|
|
@@ -128,6 +136,8 @@ exports.ultramodernWorkspaceVersions = __webpack_exports__.ultramodernWorkspaceV
|
|
|
128
136
|
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
129
137
|
"CLOUDFLARE_COMPATIBILITY_DATE",
|
|
130
138
|
"EFFECT_TSGO_VERSION",
|
|
139
|
+
"EFFECT_VERSION",
|
|
140
|
+
"EFFECT_VITEST_VERSION",
|
|
131
141
|
"I18NEXT_VERSION",
|
|
132
142
|
"LEFTHOOK_VERSION",
|
|
133
143
|
"MODULE_FEDERATION_AGENT_SKILLS_COMMIT",
|
|
@@ -209,6 +209,7 @@ function writeGeneratedWorkspaceScripts(targetDir, _scope, _enableTailwind, _rem
|
|
|
209
209
|
writeWorkspaceOwnedMtsScript(targetDir, 'proof-cloudflare-version', createToolWrapperScript('cloudflare-proof'));
|
|
210
210
|
(0, external_fs_io_cjs_namespaceObject.writeFileReplacing)(targetDir, "scripts/ultramodern-performance-readiness.config.mjs", createPerformanceReadinessConfigScript());
|
|
211
211
|
writeWorkspaceOwnedMtsScript(targetDir, 'ultramodern-performance-readiness', createToolWrapperScript('performance-readiness'));
|
|
212
|
+
writeWorkspaceOwnedMtsScript(targetDir, 'migrate-strict-effect', createToolWrapperScript('migrate-strict-effect'));
|
|
212
213
|
writeWorkspaceOwnedMtsScript(targetDir, 'ultramodern-typecheck', createToolWrapperScript('typecheck'));
|
|
213
214
|
writeWorkspaceOwnedMtsScript(targetDir, 'bootstrap-agent-skills', createSkillsToolWrapperScript());
|
|
214
215
|
migrateCopiedWorkspaceScriptToMts(targetDir, 'setup-agent-reference-repos');
|
|
@@ -175,6 +175,8 @@ function generateUltramodernWorkspace(options) {
|
|
|
175
175
|
nodeVersion: external_versions_cjs_namespaceObject.NODE_VERSION,
|
|
176
176
|
pnpmVersion: external_versions_cjs_namespaceObject.PNPM_VERSION,
|
|
177
177
|
nodeFetchVersion: external_versions_cjs_namespaceObject.NODE_FETCH_VERSION,
|
|
178
|
+
effectVersion: external_versions_cjs_namespaceObject.EFFECT_VERSION,
|
|
179
|
+
effectVitestVersion: external_versions_cjs_namespaceObject.EFFECT_VITEST_VERSION,
|
|
178
180
|
tanstackRouterCoreVersion: external_versions_cjs_namespaceObject.TANSTACK_ROUTER_CORE_VERSION,
|
|
179
181
|
tanstackRouterVersion: external_versions_cjs_namespaceObject.TANSTACK_ROUTER_VERSION,
|
|
180
182
|
typescriptVersion: external_versions_cjs_namespaceObject.TYPESCRIPT_VERSION,
|