@bleedingdev/modern-js-create 3.5.0-ultramodern.2 → 3.5.0-ultramodern.3
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 +8 -5
- package/dist/cjs/ultramodern-tooling/commands.cjs +122 -3
- package/dist/esm/ultramodern-tooling/commands.js +122 -3
- package/dist/esm-node/ultramodern-tooling/commands.js +122 -3
- package/package.json +3 -3
- package/template-workspace/README.md.handlebars +7 -4
- package/template-workspace/pnpm-workspace.yaml.handlebars +2 -0
package/README.md
CHANGED
|
@@ -193,8 +193,8 @@ For strict Effect API migrations, update generated package metadata and Modern
|
|
|
193
193
|
package aliases through the framework command before hand-editing app code:
|
|
194
194
|
|
|
195
195
|
```bash
|
|
196
|
-
pnpm dlx @bleedingdev/modern-js-create@3.5.0-ultramodern.
|
|
197
|
-
migrate-strict-effect --version 3.5.0-ultramodern.
|
|
196
|
+
pnpm dlx @bleedingdev/modern-js-create@3.5.0-ultramodern.3 ultramodern \
|
|
197
|
+
migrate-strict-effect --version 3.5.0-ultramodern.3
|
|
198
198
|
pnpm api:check
|
|
199
199
|
pnpm contract:check
|
|
200
200
|
pnpm check
|
|
@@ -202,7 +202,8 @@ pnpm build
|
|
|
202
202
|
```
|
|
203
203
|
|
|
204
204
|
The command updates `.modernjs/ultramodern.json`, root `modernjs.packageSource`,
|
|
205
|
-
generated Modern package aliases,
|
|
205
|
+
generated Modern package aliases, framework-owned toolchain pins, old direct
|
|
206
|
+
topology metadata, strict Effect pnpm overrides/trust policy, and the pnpm
|
|
206
207
|
lockfile. It does not invent compatibility shims or move business code behind
|
|
207
208
|
your back. If `pnpm api:check` still fails, migrate the source to
|
|
208
209
|
`shared/api.ts`, `api/index.ts`, and `src/api/*-client.ts` and delete
|
|
@@ -210,8 +211,10 @@ your back. If `pnpm api:check` still fails, migrate the source to
|
|
|
210
211
|
|
|
211
212
|
Generated strict Effect workspaces pin the compatible Effect cohort through
|
|
212
213
|
`pnpm-workspace.yaml` overrides: `effect@4.0.0-beta.91` and
|
|
213
|
-
`@effect/vitest@4.0.0-beta.91`.
|
|
214
|
-
|
|
214
|
+
`@effect/vitest@4.0.0-beta.91`. The generated pnpm policy also excludes the
|
|
215
|
+
known `@effect/opentelemetry@4.0.0-beta.91` trusted-publisher to provenance
|
|
216
|
+
transition from no-downgrade checks. Do not override those in app packages;
|
|
217
|
+
update the framework cohort when the runtime moves.
|
|
215
218
|
|
|
216
219
|
Use `--ultramodern-package-source=install` for published cohort proof and pin a
|
|
217
220
|
specific release with `--ultramodern-package-version` when CI must prove an
|
|
@@ -53,6 +53,7 @@ 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
55
|
const mf_validation_cjs_namespaceObject = require("../ultramodern-workspace/mf-validation.cjs");
|
|
56
|
+
const versions_cjs_namespaceObject = require("../ultramodern-workspace/versions.cjs");
|
|
56
57
|
const workspace_scripts_cjs_namespaceObject = require("../ultramodern-workspace/workspace-scripts.cjs");
|
|
57
58
|
const external_config_cjs_namespaceObject = require("./config.cjs");
|
|
58
59
|
const commands_dirname = external_node_path_default().dirname((0, external_node_url_namespaceObject.fileURLToPath)(__rslib_import_meta_url__));
|
|
@@ -198,6 +199,54 @@ function updateModernDependencies(packageJson, packageSource) {
|
|
|
198
199
|
}
|
|
199
200
|
return changed;
|
|
200
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
|
+
function updateGeneratedToolingDependencies(packageJson) {
|
|
233
|
+
let changed = false;
|
|
234
|
+
for (const section of [
|
|
235
|
+
'dependencies',
|
|
236
|
+
'devDependencies',
|
|
237
|
+
'peerDependencies',
|
|
238
|
+
'optionalDependencies'
|
|
239
|
+
]){
|
|
240
|
+
const dependencies = packageJson[section];
|
|
241
|
+
if (!(!dependencies || 'object' != typeof dependencies || Array.isArray(dependencies))) {
|
|
242
|
+
for (const [packageName, version] of generatedToolingDependencyPins)if (Object.prototype.hasOwnProperty.call(dependencies, packageName) && dependencies[packageName] !== version) {
|
|
243
|
+
dependencies[packageName] = version;
|
|
244
|
+
changed = true;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
return changed;
|
|
249
|
+
}
|
|
201
250
|
function normalizeStrictEffectApiMetadata(value) {
|
|
202
251
|
const api = value.api;
|
|
203
252
|
if (!api || 'object' != typeof api || Array.isArray(api)) return false;
|
|
@@ -263,6 +312,71 @@ function normalizeStrictEffectApiMetadata(value) {
|
|
|
263
312
|
}
|
|
264
313
|
return changed;
|
|
265
314
|
}
|
|
315
|
+
function replaceYamlLine(source, pattern, replacement) {
|
|
316
|
+
const updated = source.replace(pattern, replacement);
|
|
317
|
+
return {
|
|
318
|
+
source: updated,
|
|
319
|
+
changed: updated !== source
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
function ensureYamlListItem(source, key, item) {
|
|
323
|
+
const itemLine = ` - '${item}'`;
|
|
324
|
+
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
|
+
const header = source.match(headerPattern);
|
|
331
|
+
if (header) return {
|
|
332
|
+
source: source.replace(headerPattern, `${header[0]}${itemLine}\n`),
|
|
333
|
+
changed: true
|
|
334
|
+
};
|
|
335
|
+
const block = `${key}:\n${itemLine}\n`;
|
|
336
|
+
const afterTrustPolicyIgnore = source.replace(/^(trustPolicyIgnoreAfter: .+\n)/mu, `$1${block}`);
|
|
337
|
+
if (afterTrustPolicyIgnore !== source) return {
|
|
338
|
+
source: afterTrustPolicyIgnore,
|
|
339
|
+
changed: true
|
|
340
|
+
};
|
|
341
|
+
return {
|
|
342
|
+
source: `${source.trimEnd()}\n${block}`,
|
|
343
|
+
changed: true
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
function updateGeneratedPnpmWorkspacePolicy(workspaceRoot) {
|
|
347
|
+
const workspaceFile = external_node_path_default().join(workspaceRoot, 'pnpm-workspace.yaml');
|
|
348
|
+
if (!external_node_fs_default().existsSync(workspaceFile)) return false;
|
|
349
|
+
let source = external_node_fs_default().readFileSync(workspaceFile, 'utf-8');
|
|
350
|
+
let changed = false;
|
|
351
|
+
const replacements = [
|
|
352
|
+
[
|
|
353
|
+
/^ {4}'@effect\/vitest>effect': .+$/mu,
|
|
354
|
+
` '@effect/vitest>effect': '${versions_cjs_namespaceObject.EFFECT_VERSION}'`
|
|
355
|
+
],
|
|
356
|
+
[
|
|
357
|
+
/^ {2}'@effect\/vitest': .+$/mu,
|
|
358
|
+
` '@effect/vitest': ${versions_cjs_namespaceObject.EFFECT_VITEST_VERSION}`
|
|
359
|
+
],
|
|
360
|
+
[
|
|
361
|
+
/^ {2}effect: .+$/mu,
|
|
362
|
+
` effect: ${versions_cjs_namespaceObject.EFFECT_VERSION}`
|
|
363
|
+
],
|
|
364
|
+
[
|
|
365
|
+
/^ {2}- '@effect\/opentelemetry@[^']+'$/mu,
|
|
366
|
+
` - '@effect/opentelemetry@${versions_cjs_namespaceObject.EFFECT_VERSION}'`
|
|
367
|
+
]
|
|
368
|
+
];
|
|
369
|
+
for (const [pattern, replacement] of replacements){
|
|
370
|
+
const result = replaceYamlLine(source, pattern, replacement);
|
|
371
|
+
source = result.source;
|
|
372
|
+
changed = result.changed || changed;
|
|
373
|
+
}
|
|
374
|
+
const trustPolicyExclude = ensureYamlListItem(source, 'trustPolicyExclude', `@effect/opentelemetry@${versions_cjs_namespaceObject.EFFECT_VERSION}`);
|
|
375
|
+
source = trustPolicyExclude.source;
|
|
376
|
+
changed = trustPolicyExclude.changed || changed;
|
|
377
|
+
if (changed) external_node_fs_default().writeFileSync(workspaceFile, source, 'utf-8');
|
|
378
|
+
return changed;
|
|
379
|
+
}
|
|
266
380
|
function updateUltramodernConfig(workspaceRoot, packageSource) {
|
|
267
381
|
const configPath = external_node_path_default().join(workspaceRoot, '.modernjs/ultramodern.json');
|
|
268
382
|
const config = readJsonFile(configPath);
|
|
@@ -344,8 +458,9 @@ function runMigrateStrictEffect(args, context) {
|
|
|
344
458
|
modern-js-create ultramodern migrate-strict-effect --version <version> [--skip-install]
|
|
345
459
|
|
|
346
460
|
Updates generated UltraModern package-source metadata, Modern package aliases,
|
|
347
|
-
direct Effect API topology metadata,
|
|
348
|
-
|
|
461
|
+
framework-owned toolchain pins, direct Effect API topology metadata, strict
|
|
462
|
+
Effect pnpm overrides/trust policy, and the pnpm lockfile. Source code still
|
|
463
|
+
has to pass pnpm api:check and pnpm contract:check.
|
|
349
464
|
`);
|
|
350
465
|
return 0;
|
|
351
466
|
}
|
|
@@ -363,9 +478,13 @@ workspaces. Source code still has to pass pnpm api:check and pnpm contract:check
|
|
|
363
478
|
config: './.modernjs/ultramodern.json'
|
|
364
479
|
};
|
|
365
480
|
}
|
|
366
|
-
|
|
481
|
+
const modernDependenciesChanged = updateModernDependencies(packageJson, packageSource);
|
|
482
|
+
const toolingDependenciesChanged = updateGeneratedToolingDependencies(packageJson);
|
|
483
|
+
const changed = modernDependenciesChanged || toolingDependenciesChanged;
|
|
484
|
+
if (changed) writeJsonFile(packageFile, packageJson);
|
|
367
485
|
else if ('package.json' === relativePackageFile) writeJsonFile(packageFile, packageJson);
|
|
368
486
|
}
|
|
487
|
+
updateGeneratedPnpmWorkspacePolicy(context.workspaceRoot);
|
|
369
488
|
if (!hasFlag(args, '--skip-install')) {
|
|
370
489
|
const status = runPnpmLockfileRefresh(context);
|
|
371
490
|
if (0 !== status) return status;
|
|
@@ -6,6 +6,7 @@ import { fileURLToPath } from "node:url";
|
|
|
6
6
|
import { resolveCreatePackageRoot } from "../create-package-root.js";
|
|
7
7
|
import { BLEEDINGDEV_PACKAGE_NAME_PREFIX, BLEEDINGDEV_PACKAGE_SCOPE, ULTRAMODERN_SINGLE_APP_MODERN_PACKAGES, ULTRAMODERN_WORKSPACE_MODERN_PACKAGES, WORKSPACE_PACKAGE_VERSION, modernPackageSpecifier } from "../ultramodern-package-source.js";
|
|
8
8
|
import { validateModuleFederationTypes } from "../ultramodern-workspace/mf-validation.js";
|
|
9
|
+
import { EFFECT_TSGO_VERSION, EFFECT_VERSION, EFFECT_VITEST_VERSION, OXFMT_VERSION, OXLINT_VERSION, TYPESCRIPT_NATIVE_PREVIEW_VERSION, WRANGLER_VERSION, ZEPHYR_AGENT_VERSION, ZEPHYR_RSPACK_PLUGIN_VERSION } from "../ultramodern-workspace/versions.js";
|
|
9
10
|
import { createWorkspaceValidationScript } from "../ultramodern-workspace/workspace-scripts.js";
|
|
10
11
|
import { readUltramodernConfig, workspaceAppsFromToolingConfig } from "./config.js";
|
|
11
12
|
const commands_dirname = node_path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -151,6 +152,54 @@ function updateModernDependencies(packageJson, packageSource) {
|
|
|
151
152
|
}
|
|
152
153
|
return changed;
|
|
153
154
|
}
|
|
155
|
+
const generatedToolingDependencyPins = new Map([
|
|
156
|
+
[
|
|
157
|
+
'@effect/tsgo',
|
|
158
|
+
EFFECT_TSGO_VERSION
|
|
159
|
+
],
|
|
160
|
+
[
|
|
161
|
+
"@typescript/native-preview",
|
|
162
|
+
TYPESCRIPT_NATIVE_PREVIEW_VERSION
|
|
163
|
+
],
|
|
164
|
+
[
|
|
165
|
+
'oxfmt',
|
|
166
|
+
OXFMT_VERSION
|
|
167
|
+
],
|
|
168
|
+
[
|
|
169
|
+
'oxlint',
|
|
170
|
+
OXLINT_VERSION
|
|
171
|
+
],
|
|
172
|
+
[
|
|
173
|
+
'wrangler',
|
|
174
|
+
WRANGLER_VERSION
|
|
175
|
+
],
|
|
176
|
+
[
|
|
177
|
+
'zephyr-agent',
|
|
178
|
+
ZEPHYR_AGENT_VERSION
|
|
179
|
+
],
|
|
180
|
+
[
|
|
181
|
+
'zephyr-rspack-plugin',
|
|
182
|
+
ZEPHYR_RSPACK_PLUGIN_VERSION
|
|
183
|
+
]
|
|
184
|
+
]);
|
|
185
|
+
function updateGeneratedToolingDependencies(packageJson) {
|
|
186
|
+
let changed = false;
|
|
187
|
+
for (const section of [
|
|
188
|
+
'dependencies',
|
|
189
|
+
'devDependencies',
|
|
190
|
+
'peerDependencies',
|
|
191
|
+
'optionalDependencies'
|
|
192
|
+
]){
|
|
193
|
+
const dependencies = packageJson[section];
|
|
194
|
+
if (!(!dependencies || 'object' != typeof dependencies || Array.isArray(dependencies))) {
|
|
195
|
+
for (const [packageName, version] of generatedToolingDependencyPins)if (Object.prototype.hasOwnProperty.call(dependencies, packageName) && dependencies[packageName] !== version) {
|
|
196
|
+
dependencies[packageName] = version;
|
|
197
|
+
changed = true;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return changed;
|
|
202
|
+
}
|
|
154
203
|
function normalizeStrictEffectApiMetadata(value) {
|
|
155
204
|
const api = value.api;
|
|
156
205
|
if (!api || 'object' != typeof api || Array.isArray(api)) return false;
|
|
@@ -216,6 +265,71 @@ function normalizeStrictEffectApiMetadata(value) {
|
|
|
216
265
|
}
|
|
217
266
|
return changed;
|
|
218
267
|
}
|
|
268
|
+
function replaceYamlLine(source, pattern, replacement) {
|
|
269
|
+
const updated = source.replace(pattern, replacement);
|
|
270
|
+
return {
|
|
271
|
+
source: updated,
|
|
272
|
+
changed: updated !== source
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
function ensureYamlListItem(source, key, item) {
|
|
276
|
+
const itemLine = ` - '${item}'`;
|
|
277
|
+
const headerPattern = new RegExp(`^${key}:\\n(?:(?: - .+\\n)*)`, 'mu');
|
|
278
|
+
const existingItemPattern = new RegExp(`^ - '${item.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&')}'$`, 'mu');
|
|
279
|
+
if (existingItemPattern.test(source)) return {
|
|
280
|
+
source,
|
|
281
|
+
changed: false
|
|
282
|
+
};
|
|
283
|
+
const header = source.match(headerPattern);
|
|
284
|
+
if (header) return {
|
|
285
|
+
source: source.replace(headerPattern, `${header[0]}${itemLine}\n`),
|
|
286
|
+
changed: true
|
|
287
|
+
};
|
|
288
|
+
const block = `${key}:\n${itemLine}\n`;
|
|
289
|
+
const afterTrustPolicyIgnore = source.replace(/^(trustPolicyIgnoreAfter: .+\n)/mu, `$1${block}`);
|
|
290
|
+
if (afterTrustPolicyIgnore !== source) return {
|
|
291
|
+
source: afterTrustPolicyIgnore,
|
|
292
|
+
changed: true
|
|
293
|
+
};
|
|
294
|
+
return {
|
|
295
|
+
source: `${source.trimEnd()}\n${block}`,
|
|
296
|
+
changed: true
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
function updateGeneratedPnpmWorkspacePolicy(workspaceRoot) {
|
|
300
|
+
const workspaceFile = node_path.join(workspaceRoot, 'pnpm-workspace.yaml');
|
|
301
|
+
if (!node_fs.existsSync(workspaceFile)) return false;
|
|
302
|
+
let source = node_fs.readFileSync(workspaceFile, 'utf-8');
|
|
303
|
+
let changed = false;
|
|
304
|
+
const replacements = [
|
|
305
|
+
[
|
|
306
|
+
/^ {4}'@effect\/vitest>effect': .+$/mu,
|
|
307
|
+
` '@effect/vitest>effect': '${EFFECT_VERSION}'`
|
|
308
|
+
],
|
|
309
|
+
[
|
|
310
|
+
/^ {2}'@effect\/vitest': .+$/mu,
|
|
311
|
+
` '@effect/vitest': ${EFFECT_VITEST_VERSION}`
|
|
312
|
+
],
|
|
313
|
+
[
|
|
314
|
+
/^ {2}effect: .+$/mu,
|
|
315
|
+
` effect: ${EFFECT_VERSION}`
|
|
316
|
+
],
|
|
317
|
+
[
|
|
318
|
+
/^ {2}- '@effect\/opentelemetry@[^']+'$/mu,
|
|
319
|
+
` - '@effect/opentelemetry@${EFFECT_VERSION}'`
|
|
320
|
+
]
|
|
321
|
+
];
|
|
322
|
+
for (const [pattern, replacement] of replacements){
|
|
323
|
+
const result = replaceYamlLine(source, pattern, replacement);
|
|
324
|
+
source = result.source;
|
|
325
|
+
changed = result.changed || changed;
|
|
326
|
+
}
|
|
327
|
+
const trustPolicyExclude = ensureYamlListItem(source, 'trustPolicyExclude', `@effect/opentelemetry@${EFFECT_VERSION}`);
|
|
328
|
+
source = trustPolicyExclude.source;
|
|
329
|
+
changed = trustPolicyExclude.changed || changed;
|
|
330
|
+
if (changed) node_fs.writeFileSync(workspaceFile, source, 'utf-8');
|
|
331
|
+
return changed;
|
|
332
|
+
}
|
|
219
333
|
function updateUltramodernConfig(workspaceRoot, packageSource) {
|
|
220
334
|
const configPath = node_path.join(workspaceRoot, '.modernjs/ultramodern.json');
|
|
221
335
|
const config = readJsonFile(configPath);
|
|
@@ -297,8 +411,9 @@ function runMigrateStrictEffect(args, context) {
|
|
|
297
411
|
modern-js-create ultramodern migrate-strict-effect --version <version> [--skip-install]
|
|
298
412
|
|
|
299
413
|
Updates generated UltraModern package-source metadata, Modern package aliases,
|
|
300
|
-
direct Effect API topology metadata,
|
|
301
|
-
|
|
414
|
+
framework-owned toolchain pins, direct Effect API topology metadata, strict
|
|
415
|
+
Effect pnpm overrides/trust policy, and the pnpm lockfile. Source code still
|
|
416
|
+
has to pass pnpm api:check and pnpm contract:check.
|
|
302
417
|
`);
|
|
303
418
|
return 0;
|
|
304
419
|
}
|
|
@@ -316,9 +431,13 @@ workspaces. Source code still has to pass pnpm api:check and pnpm contract:check
|
|
|
316
431
|
config: './.modernjs/ultramodern.json'
|
|
317
432
|
};
|
|
318
433
|
}
|
|
319
|
-
|
|
434
|
+
const modernDependenciesChanged = updateModernDependencies(packageJson, packageSource);
|
|
435
|
+
const toolingDependenciesChanged = updateGeneratedToolingDependencies(packageJson);
|
|
436
|
+
const changed = modernDependenciesChanged || toolingDependenciesChanged;
|
|
437
|
+
if (changed) writeJsonFile(packageFile, packageJson);
|
|
320
438
|
else if ('package.json' === relativePackageFile) writeJsonFile(packageFile, packageJson);
|
|
321
439
|
}
|
|
440
|
+
updateGeneratedPnpmWorkspacePolicy(context.workspaceRoot);
|
|
322
441
|
if (!hasFlag(args, '--skip-install')) {
|
|
323
442
|
const status = runPnpmLockfileRefresh(context);
|
|
324
443
|
if (0 !== status) return status;
|
|
@@ -7,6 +7,7 @@ import { fileURLToPath } from "node:url";
|
|
|
7
7
|
import { resolveCreatePackageRoot } from "../create-package-root.js";
|
|
8
8
|
import { BLEEDINGDEV_PACKAGE_NAME_PREFIX, BLEEDINGDEV_PACKAGE_SCOPE, ULTRAMODERN_SINGLE_APP_MODERN_PACKAGES, ULTRAMODERN_WORKSPACE_MODERN_PACKAGES, WORKSPACE_PACKAGE_VERSION, modernPackageSpecifier } from "../ultramodern-package-source.js";
|
|
9
9
|
import { validateModuleFederationTypes } from "../ultramodern-workspace/mf-validation.js";
|
|
10
|
+
import { EFFECT_TSGO_VERSION, EFFECT_VERSION, EFFECT_VITEST_VERSION, OXFMT_VERSION, OXLINT_VERSION, TYPESCRIPT_NATIVE_PREVIEW_VERSION, WRANGLER_VERSION, ZEPHYR_AGENT_VERSION, ZEPHYR_RSPACK_PLUGIN_VERSION } from "../ultramodern-workspace/versions.js";
|
|
10
11
|
import { createWorkspaceValidationScript } from "../ultramodern-workspace/workspace-scripts.js";
|
|
11
12
|
import { readUltramodernConfig, workspaceAppsFromToolingConfig } from "./config.js";
|
|
12
13
|
const commands_dirname = node_path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -152,6 +153,54 @@ function updateModernDependencies(packageJson, packageSource) {
|
|
|
152
153
|
}
|
|
153
154
|
return changed;
|
|
154
155
|
}
|
|
156
|
+
const generatedToolingDependencyPins = new Map([
|
|
157
|
+
[
|
|
158
|
+
'@effect/tsgo',
|
|
159
|
+
EFFECT_TSGO_VERSION
|
|
160
|
+
],
|
|
161
|
+
[
|
|
162
|
+
"@typescript/native-preview",
|
|
163
|
+
TYPESCRIPT_NATIVE_PREVIEW_VERSION
|
|
164
|
+
],
|
|
165
|
+
[
|
|
166
|
+
'oxfmt',
|
|
167
|
+
OXFMT_VERSION
|
|
168
|
+
],
|
|
169
|
+
[
|
|
170
|
+
'oxlint',
|
|
171
|
+
OXLINT_VERSION
|
|
172
|
+
],
|
|
173
|
+
[
|
|
174
|
+
'wrangler',
|
|
175
|
+
WRANGLER_VERSION
|
|
176
|
+
],
|
|
177
|
+
[
|
|
178
|
+
'zephyr-agent',
|
|
179
|
+
ZEPHYR_AGENT_VERSION
|
|
180
|
+
],
|
|
181
|
+
[
|
|
182
|
+
'zephyr-rspack-plugin',
|
|
183
|
+
ZEPHYR_RSPACK_PLUGIN_VERSION
|
|
184
|
+
]
|
|
185
|
+
]);
|
|
186
|
+
function updateGeneratedToolingDependencies(packageJson) {
|
|
187
|
+
let changed = false;
|
|
188
|
+
for (const section of [
|
|
189
|
+
'dependencies',
|
|
190
|
+
'devDependencies',
|
|
191
|
+
'peerDependencies',
|
|
192
|
+
'optionalDependencies'
|
|
193
|
+
]){
|
|
194
|
+
const dependencies = packageJson[section];
|
|
195
|
+
if (!(!dependencies || 'object' != typeof dependencies || Array.isArray(dependencies))) {
|
|
196
|
+
for (const [packageName, version] of generatedToolingDependencyPins)if (Object.prototype.hasOwnProperty.call(dependencies, packageName) && dependencies[packageName] !== version) {
|
|
197
|
+
dependencies[packageName] = version;
|
|
198
|
+
changed = true;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return changed;
|
|
203
|
+
}
|
|
155
204
|
function normalizeStrictEffectApiMetadata(value) {
|
|
156
205
|
const api = value.api;
|
|
157
206
|
if (!api || 'object' != typeof api || Array.isArray(api)) return false;
|
|
@@ -217,6 +266,71 @@ function normalizeStrictEffectApiMetadata(value) {
|
|
|
217
266
|
}
|
|
218
267
|
return changed;
|
|
219
268
|
}
|
|
269
|
+
function replaceYamlLine(source, pattern, replacement) {
|
|
270
|
+
const updated = source.replace(pattern, replacement);
|
|
271
|
+
return {
|
|
272
|
+
source: updated,
|
|
273
|
+
changed: updated !== source
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
function ensureYamlListItem(source, key, item) {
|
|
277
|
+
const itemLine = ` - '${item}'`;
|
|
278
|
+
const headerPattern = new RegExp(`^${key}:\\n(?:(?: - .+\\n)*)`, 'mu');
|
|
279
|
+
const existingItemPattern = new RegExp(`^ - '${item.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&')}'$`, 'mu');
|
|
280
|
+
if (existingItemPattern.test(source)) return {
|
|
281
|
+
source,
|
|
282
|
+
changed: false
|
|
283
|
+
};
|
|
284
|
+
const header = source.match(headerPattern);
|
|
285
|
+
if (header) return {
|
|
286
|
+
source: source.replace(headerPattern, `${header[0]}${itemLine}\n`),
|
|
287
|
+
changed: true
|
|
288
|
+
};
|
|
289
|
+
const block = `${key}:\n${itemLine}\n`;
|
|
290
|
+
const afterTrustPolicyIgnore = source.replace(/^(trustPolicyIgnoreAfter: .+\n)/mu, `$1${block}`);
|
|
291
|
+
if (afterTrustPolicyIgnore !== source) return {
|
|
292
|
+
source: afterTrustPolicyIgnore,
|
|
293
|
+
changed: true
|
|
294
|
+
};
|
|
295
|
+
return {
|
|
296
|
+
source: `${source.trimEnd()}\n${block}`,
|
|
297
|
+
changed: true
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
function updateGeneratedPnpmWorkspacePolicy(workspaceRoot) {
|
|
301
|
+
const workspaceFile = node_path.join(workspaceRoot, 'pnpm-workspace.yaml');
|
|
302
|
+
if (!node_fs.existsSync(workspaceFile)) return false;
|
|
303
|
+
let source = node_fs.readFileSync(workspaceFile, 'utf-8');
|
|
304
|
+
let changed = false;
|
|
305
|
+
const replacements = [
|
|
306
|
+
[
|
|
307
|
+
/^ {4}'@effect\/vitest>effect': .+$/mu,
|
|
308
|
+
` '@effect/vitest>effect': '${EFFECT_VERSION}'`
|
|
309
|
+
],
|
|
310
|
+
[
|
|
311
|
+
/^ {2}'@effect\/vitest': .+$/mu,
|
|
312
|
+
` '@effect/vitest': ${EFFECT_VITEST_VERSION}`
|
|
313
|
+
],
|
|
314
|
+
[
|
|
315
|
+
/^ {2}effect: .+$/mu,
|
|
316
|
+
` effect: ${EFFECT_VERSION}`
|
|
317
|
+
],
|
|
318
|
+
[
|
|
319
|
+
/^ {2}- '@effect\/opentelemetry@[^']+'$/mu,
|
|
320
|
+
` - '@effect/opentelemetry@${EFFECT_VERSION}'`
|
|
321
|
+
]
|
|
322
|
+
];
|
|
323
|
+
for (const [pattern, replacement] of replacements){
|
|
324
|
+
const result = replaceYamlLine(source, pattern, replacement);
|
|
325
|
+
source = result.source;
|
|
326
|
+
changed = result.changed || changed;
|
|
327
|
+
}
|
|
328
|
+
const trustPolicyExclude = ensureYamlListItem(source, 'trustPolicyExclude', `@effect/opentelemetry@${EFFECT_VERSION}`);
|
|
329
|
+
source = trustPolicyExclude.source;
|
|
330
|
+
changed = trustPolicyExclude.changed || changed;
|
|
331
|
+
if (changed) node_fs.writeFileSync(workspaceFile, source, 'utf-8');
|
|
332
|
+
return changed;
|
|
333
|
+
}
|
|
220
334
|
function updateUltramodernConfig(workspaceRoot, packageSource) {
|
|
221
335
|
const configPath = node_path.join(workspaceRoot, '.modernjs/ultramodern.json');
|
|
222
336
|
const config = readJsonFile(configPath);
|
|
@@ -298,8 +412,9 @@ function runMigrateStrictEffect(args, context) {
|
|
|
298
412
|
modern-js-create ultramodern migrate-strict-effect --version <version> [--skip-install]
|
|
299
413
|
|
|
300
414
|
Updates generated UltraModern package-source metadata, Modern package aliases,
|
|
301
|
-
direct Effect API topology metadata,
|
|
302
|
-
|
|
415
|
+
framework-owned toolchain pins, direct Effect API topology metadata, strict
|
|
416
|
+
Effect pnpm overrides/trust policy, and the pnpm lockfile. Source code still
|
|
417
|
+
has to pass pnpm api:check and pnpm contract:check.
|
|
303
418
|
`);
|
|
304
419
|
return 0;
|
|
305
420
|
}
|
|
@@ -317,9 +432,13 @@ workspaces. Source code still has to pass pnpm api:check and pnpm contract:check
|
|
|
317
432
|
config: './.modernjs/ultramodern.json'
|
|
318
433
|
};
|
|
319
434
|
}
|
|
320
|
-
|
|
435
|
+
const modernDependenciesChanged = updateModernDependencies(packageJson, packageSource);
|
|
436
|
+
const toolingDependenciesChanged = updateGeneratedToolingDependencies(packageJson);
|
|
437
|
+
const changed = modernDependenciesChanged || toolingDependenciesChanged;
|
|
438
|
+
if (changed) writeJsonFile(packageFile, packageJson);
|
|
321
439
|
else if ('package.json' === relativePackageFile) writeJsonFile(packageFile, packageJson);
|
|
322
440
|
}
|
|
441
|
+
updateGeneratedPnpmWorkspacePolicy(context.workspaceRoot);
|
|
323
442
|
if (!hasFlag(args, '--skip-install')) {
|
|
324
443
|
const status = runPnpmLockfileRefresh(context);
|
|
325
444
|
if (0 !== status) return status;
|
package/package.json
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"engines": {
|
|
22
22
|
"node": ">=20"
|
|
23
23
|
},
|
|
24
|
-
"version": "3.5.0-ultramodern.
|
|
24
|
+
"version": "3.5.0-ultramodern.3",
|
|
25
25
|
"types": "./dist/types/index.d.ts",
|
|
26
26
|
"main": "./dist/esm-node/index.js",
|
|
27
27
|
"bin": {
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
"@modern-js/codesmith": "2.6.9",
|
|
78
78
|
"oxfmt": "0.56.0",
|
|
79
79
|
"ultracite": "7.8.3",
|
|
80
|
-
"@modern-js/i18n-utils": "npm:@bleedingdev/modern-js-i18n-utils@3.5.0-ultramodern.
|
|
80
|
+
"@modern-js/i18n-utils": "npm:@bleedingdev/modern-js-i18n-utils@3.5.0-ultramodern.3"
|
|
81
81
|
},
|
|
82
82
|
"devDependencies": {
|
|
83
83
|
"@rslib/core": "0.23.1",
|
|
@@ -99,6 +99,6 @@
|
|
|
99
99
|
"test": "rm -rf dist && rslib build -c rslibconfig.mts && rstest --passWithNoTests"
|
|
100
100
|
},
|
|
101
101
|
"ultramodern": {
|
|
102
|
-
"frameworkVersion": "3.5.0-ultramodern.
|
|
102
|
+
"frameworkVersion": "3.5.0-ultramodern.3"
|
|
103
103
|
}
|
|
104
104
|
}
|
|
@@ -169,19 +169,22 @@ in API modules.
|
|
|
169
169
|
Generated pnpm overrides pin the framework-compatible Effect cohort. Keep
|
|
170
170
|
`effect` and `@effect/vitest` aligned with `pnpm-workspace.yaml`; do not add
|
|
171
171
|
new direct package-level Effect versions unless the whole UltraModern cohort is
|
|
172
|
-
upgraded.
|
|
172
|
+
upgraded. The generated pnpm trust policy intentionally excludes the matching
|
|
173
|
+
`@effect/opentelemetry` cohort package from no-downgrade checks while Effect's
|
|
174
|
+
beta publishes move from trusted-publisher metadata to provenance attestations.
|
|
173
175
|
|
|
174
176
|
For older generated workspaces, run the framework migration command first:
|
|
175
177
|
|
|
176
178
|
```bash
|
|
177
|
-
pnpm dlx @bleedingdev/modern-js-create@3.5.0-ultramodern.
|
|
178
|
-
migrate-strict-effect --version 3.5.0-ultramodern.
|
|
179
|
+
pnpm dlx @bleedingdev/modern-js-create@3.5.0-ultramodern.3 ultramodern \
|
|
180
|
+
migrate-strict-effect --version 3.5.0-ultramodern.3
|
|
179
181
|
pnpm api:check
|
|
180
182
|
pnpm contract:check
|
|
181
183
|
```
|
|
182
184
|
|
|
183
185
|
The command updates generated package-source metadata, Modern package aliases,
|
|
184
|
-
direct API topology metadata,
|
|
186
|
+
framework-owned toolchain pins, direct API topology metadata, strict Effect pnpm
|
|
187
|
+
overrides/trust policy, and the lockfile. Remaining failures are source
|
|
185
188
|
migration work; fix the owning API files instead of adding compatibility shims.
|
|
186
189
|
|
|
187
190
|
## Troubleshooting
|