@bleedingdev/modern-js-create 3.5.0-ultramodern.1 → 3.5.0-ultramodern.11
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 +10 -6
- package/dist/cjs/ultramodern-tooling/commands.cjs +271 -3
- package/dist/cjs/ultramodern-workspace/app-files.cjs +8 -11
- package/dist/cjs/ultramodern-workspace/package-json.cjs +15 -7
- package/dist/cjs/ultramodern-workspace/versions.cjs +9 -4
- package/dist/cjs/ultramodern-workspace/workspace-scripts.cjs +1 -0
- package/dist/cjs/ultramodern-workspace/write-workspace.cjs +1 -0
- package/dist/esm/ultramodern-tooling/commands.js +271 -3
- package/dist/esm/ultramodern-workspace/app-files.js +8 -11
- package/dist/esm/ultramodern-workspace/package-json.js +5 -7
- package/dist/esm/ultramodern-workspace/versions.js +7 -5
- package/dist/esm/ultramodern-workspace/workspace-scripts.js +2 -1
- package/dist/esm/ultramodern-workspace/write-workspace.js +2 -1
- package/dist/esm-node/ultramodern-tooling/commands.js +271 -3
- package/dist/esm-node/ultramodern-workspace/app-files.js +8 -11
- package/dist/esm-node/ultramodern-workspace/package-json.js +5 -7
- package/dist/esm-node/ultramodern-workspace/versions.js +7 -5
- package/dist/esm-node/ultramodern-workspace/workspace-scripts.js +2 -1
- package/dist/esm-node/ultramodern-workspace/write-workspace.js +2 -1
- package/dist/types/ultramodern-workspace/versions.d.ts +6 -4
- package/package.json +6 -6
- package/template-workspace/.gitignore.handlebars +2 -0
- package/template-workspace/README.md.handlebars +8 -4
- 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 +7 -0
- package/templates/workspace-scripts/validate-ultramodern-workspace.mjs.handlebars +58 -2
|
@@ -6,7 +6,10 @@ import node_path from "node:path";
|
|
|
6
6
|
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
|
+
import { createAppEnvDts } from "../ultramodern-workspace/app-files.js";
|
|
9
10
|
import { validateModuleFederationTypes } from "../ultramodern-workspace/mf-validation.js";
|
|
11
|
+
import { createAppMfTypesTsConfig, createAppTsConfig, createSharedPackageTsConfig, createTsConfigBase } from "../ultramodern-workspace/package-json.js";
|
|
12
|
+
import { DRIZZLE_ORM_VERSION, 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
13
|
import { createWorkspaceValidationScript } from "../ultramodern-workspace/workspace-scripts.js";
|
|
11
14
|
import { readUltramodernConfig, workspaceAppsFromToolingConfig } from "./config.js";
|
|
12
15
|
const commands_dirname = node_path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -152,6 +155,82 @@ function updateModernDependencies(packageJson, packageSource) {
|
|
|
152
155
|
}
|
|
153
156
|
return changed;
|
|
154
157
|
}
|
|
158
|
+
const generatedToolingDependencyPins = new Map([
|
|
159
|
+
[
|
|
160
|
+
'@effect/tsgo',
|
|
161
|
+
EFFECT_TSGO_VERSION
|
|
162
|
+
],
|
|
163
|
+
[
|
|
164
|
+
"@typescript/native-preview",
|
|
165
|
+
TYPESCRIPT_NATIVE_PREVIEW_VERSION
|
|
166
|
+
],
|
|
167
|
+
[
|
|
168
|
+
'oxfmt',
|
|
169
|
+
OXFMT_VERSION
|
|
170
|
+
],
|
|
171
|
+
[
|
|
172
|
+
'oxlint',
|
|
173
|
+
OXLINT_VERSION
|
|
174
|
+
],
|
|
175
|
+
[
|
|
176
|
+
'wrangler',
|
|
177
|
+
WRANGLER_VERSION
|
|
178
|
+
],
|
|
179
|
+
[
|
|
180
|
+
'zephyr-agent',
|
|
181
|
+
ZEPHYR_AGENT_VERSION
|
|
182
|
+
],
|
|
183
|
+
[
|
|
184
|
+
'zephyr-rspack-plugin',
|
|
185
|
+
ZEPHYR_RSPACK_PLUGIN_VERSION
|
|
186
|
+
]
|
|
187
|
+
]);
|
|
188
|
+
const strictEffectPackageVersionPolicyExclusions = [
|
|
189
|
+
`effect@${EFFECT_VERSION}`,
|
|
190
|
+
`@effect/opentelemetry@${EFFECT_VERSION}`
|
|
191
|
+
];
|
|
192
|
+
const effectDeclarationPatchPath = 'patches/effect-schema-error-type-id.patch';
|
|
193
|
+
const effectDeclarationPatchSourcePath = node_path.join(createPackageRoot, 'template-workspace', effectDeclarationPatchPath);
|
|
194
|
+
const drizzleOrmDeclarationPatchPath = 'patches/drizzle-orm-ts7-strict-declarations.patch';
|
|
195
|
+
const drizzleOrmDeclarationPatchSourcePath = node_path.join(createPackageRoot, 'template-workspace', drizzleOrmDeclarationPatchPath);
|
|
196
|
+
function updateGeneratedToolingDependencies(packageJson) {
|
|
197
|
+
let changed = false;
|
|
198
|
+
for (const section of [
|
|
199
|
+
'dependencies',
|
|
200
|
+
'devDependencies',
|
|
201
|
+
'peerDependencies',
|
|
202
|
+
'optionalDependencies'
|
|
203
|
+
]){
|
|
204
|
+
const dependencies = packageJson[section];
|
|
205
|
+
if (!(!dependencies || 'object' != typeof dependencies || Array.isArray(dependencies))) {
|
|
206
|
+
for (const [packageName, version] of generatedToolingDependencyPins)if (Object.prototype.hasOwnProperty.call(dependencies, packageName) && dependencies[packageName] !== version) {
|
|
207
|
+
dependencies[packageName] = version;
|
|
208
|
+
changed = true;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return changed;
|
|
213
|
+
}
|
|
214
|
+
const cloudflareModernDeployCommand = 'ULTRAMODERN_ZEPHYR=false MODERNJS_DEPLOY=cloudflare modern deploy';
|
|
215
|
+
const cloudflareModernDeploySkipBuildCommand = `${cloudflareModernDeployCommand} --skip-build`;
|
|
216
|
+
const cloudflareWranglerDeployCommand = 'wrangler deploy --config .output/wrangler.json';
|
|
217
|
+
const cloudflareWranglerDeployInvalidSkipBuildCommand = `${cloudflareWranglerDeployCommand} --skip-build`;
|
|
218
|
+
function updateGeneratedPackageScripts(packageJson) {
|
|
219
|
+
const scripts = packageJson.scripts;
|
|
220
|
+
if (!scripts || 'object' != typeof scripts || Array.isArray(scripts)) return false;
|
|
221
|
+
let changed = false;
|
|
222
|
+
const cloudflareBuild = scripts['cloudflare:build'];
|
|
223
|
+
if ('string' == typeof cloudflareBuild && cloudflareBuild.includes(cloudflareModernDeployCommand) && !cloudflareBuild.includes(cloudflareModernDeploySkipBuildCommand)) {
|
|
224
|
+
scripts['cloudflare:build'] = cloudflareBuild.replace(cloudflareModernDeployCommand, cloudflareModernDeploySkipBuildCommand);
|
|
225
|
+
changed = true;
|
|
226
|
+
}
|
|
227
|
+
const cloudflareDeploy = scripts['cloudflare:deploy'];
|
|
228
|
+
if ('string' == typeof cloudflareDeploy && cloudflareDeploy.includes(cloudflareWranglerDeployInvalidSkipBuildCommand)) {
|
|
229
|
+
scripts['cloudflare:deploy'] = cloudflareDeploy.replace(cloudflareWranglerDeployInvalidSkipBuildCommand, cloudflareWranglerDeployCommand);
|
|
230
|
+
changed = true;
|
|
231
|
+
}
|
|
232
|
+
return changed;
|
|
233
|
+
}
|
|
155
234
|
function normalizeStrictEffectApiMetadata(value) {
|
|
156
235
|
const api = value.api;
|
|
157
236
|
if (!api || 'object' != typeof api || Array.isArray(api)) return false;
|
|
@@ -217,6 +296,135 @@ function normalizeStrictEffectApiMetadata(value) {
|
|
|
217
296
|
}
|
|
218
297
|
return changed;
|
|
219
298
|
}
|
|
299
|
+
function replaceYamlLine(source, pattern, replacement) {
|
|
300
|
+
const updated = source.replace(pattern, replacement);
|
|
301
|
+
return {
|
|
302
|
+
source: updated,
|
|
303
|
+
changed: updated !== source
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
function ensureYamlListItem(source, key, item) {
|
|
307
|
+
const itemLine = ` - '${item}'`;
|
|
308
|
+
const headerPattern = new RegExp(`^${key}:\\n(?:(?: - .+\\n)*)`, 'mu');
|
|
309
|
+
const header = source.match(headerPattern);
|
|
310
|
+
if (header) {
|
|
311
|
+
if (header[0].split('\n').includes(itemLine)) return {
|
|
312
|
+
source,
|
|
313
|
+
changed: false
|
|
314
|
+
};
|
|
315
|
+
return {
|
|
316
|
+
source: source.replace(headerPattern, `${header[0]}${itemLine}\n`),
|
|
317
|
+
changed: true
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
const block = `${key}:\n${itemLine}\n`;
|
|
321
|
+
const afterTrustPolicyIgnore = source.replace(/^(trustPolicyIgnoreAfter: .+\n)/mu, `$1${block}`);
|
|
322
|
+
if (afterTrustPolicyIgnore !== source) return {
|
|
323
|
+
source: afterTrustPolicyIgnore,
|
|
324
|
+
changed: true
|
|
325
|
+
};
|
|
326
|
+
return {
|
|
327
|
+
source: `${source.trimEnd()}\n${block}`,
|
|
328
|
+
changed: true
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
function ensureYamlMapEntry(source, key, entryKey, value) {
|
|
332
|
+
const entryLine = ` '${entryKey}': ${value}`;
|
|
333
|
+
const packageName = entryKey.includes('@') ? entryKey.slice(0, entryKey.lastIndexOf('@')) : entryKey;
|
|
334
|
+
const escapedPackageName = packageName.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&');
|
|
335
|
+
const currentEntryPattern = new RegExp(`^ {2}'${escapedPackageName}@[^']+': .+$`, 'mu');
|
|
336
|
+
const currentEntry = source.match(currentEntryPattern);
|
|
337
|
+
if (currentEntry) {
|
|
338
|
+
if (currentEntry[0] === entryLine) return {
|
|
339
|
+
source,
|
|
340
|
+
changed: false
|
|
341
|
+
};
|
|
342
|
+
return {
|
|
343
|
+
source: source.replace(currentEntryPattern, entryLine),
|
|
344
|
+
changed: true
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
const headerPattern = new RegExp(`^${key}:\\n(?:(?: .+\\n)*)`, 'mu');
|
|
348
|
+
const header = source.match(headerPattern);
|
|
349
|
+
if (header) {
|
|
350
|
+
if (header[0].split('\n').includes(entryLine)) return {
|
|
351
|
+
source,
|
|
352
|
+
changed: false
|
|
353
|
+
};
|
|
354
|
+
return {
|
|
355
|
+
source: source.replace(headerPattern, `${header[0]}${entryLine}\n`),
|
|
356
|
+
changed: true
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
return {
|
|
360
|
+
source: `${source.trimEnd()}\n${key}:\n${entryLine}\n`,
|
|
361
|
+
changed: true
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
function ensureGeneratedPatchFile(workspaceRoot, relativePatchPath, sourcePatchPath) {
|
|
365
|
+
const targetPath = node_path.join(workspaceRoot, relativePatchPath);
|
|
366
|
+
const patch = node_fs.readFileSync(sourcePatchPath, 'utf-8');
|
|
367
|
+
if (node_fs.existsSync(targetPath) && node_fs.readFileSync(targetPath, 'utf-8') === patch) return false;
|
|
368
|
+
node_fs.mkdirSync(node_path.dirname(targetPath), {
|
|
369
|
+
recursive: true
|
|
370
|
+
});
|
|
371
|
+
node_fs.writeFileSync(targetPath, patch, 'utf-8');
|
|
372
|
+
return true;
|
|
373
|
+
}
|
|
374
|
+
function ensureGeneratedDeclarationPatches(workspaceRoot) {
|
|
375
|
+
let changed = false;
|
|
376
|
+
changed = ensureGeneratedPatchFile(workspaceRoot, effectDeclarationPatchPath, effectDeclarationPatchSourcePath) || changed;
|
|
377
|
+
changed = ensureGeneratedPatchFile(workspaceRoot, drizzleOrmDeclarationPatchPath, drizzleOrmDeclarationPatchSourcePath) || changed;
|
|
378
|
+
return changed;
|
|
379
|
+
}
|
|
380
|
+
function updateGeneratedPnpmWorkspacePolicy(workspaceRoot) {
|
|
381
|
+
const workspaceFile = node_path.join(workspaceRoot, 'pnpm-workspace.yaml');
|
|
382
|
+
if (!node_fs.existsSync(workspaceFile)) return false;
|
|
383
|
+
let source = node_fs.readFileSync(workspaceFile, 'utf-8');
|
|
384
|
+
let changed = false;
|
|
385
|
+
const replacements = [
|
|
386
|
+
[
|
|
387
|
+
/^ {4}'@effect\/vitest>effect': .+$/mu,
|
|
388
|
+
` '@effect/vitest>effect': '${EFFECT_VERSION}'`
|
|
389
|
+
],
|
|
390
|
+
[
|
|
391
|
+
/^ {2}'@effect\/vitest': .+$/mu,
|
|
392
|
+
` '@effect/vitest': ${EFFECT_VITEST_VERSION}`
|
|
393
|
+
],
|
|
394
|
+
[
|
|
395
|
+
/^ {2}effect: .+$/mu,
|
|
396
|
+
` effect: ${EFFECT_VERSION}`
|
|
397
|
+
]
|
|
398
|
+
];
|
|
399
|
+
for (const [pattern, replacement] of replacements){
|
|
400
|
+
const result = replaceYamlLine(source, pattern, replacement);
|
|
401
|
+
source = result.source;
|
|
402
|
+
changed = result.changed || changed;
|
|
403
|
+
}
|
|
404
|
+
for (const item of strictEffectPackageVersionPolicyExclusions){
|
|
405
|
+
const packageName = item.slice(0, item.lastIndexOf('@'));
|
|
406
|
+
const escapedPackageName = packageName.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&');
|
|
407
|
+
const currentVersion = replaceYamlLine(source, new RegExp(`^ {2}- '${escapedPackageName}@[^']+'$`, 'gmu'), ` - '${item}'`);
|
|
408
|
+
source = currentVersion.source;
|
|
409
|
+
changed = currentVersion.changed || changed;
|
|
410
|
+
for (const policyKey of [
|
|
411
|
+
'minimumReleaseAgeExclude',
|
|
412
|
+
'trustPolicyExclude'
|
|
413
|
+
]){
|
|
414
|
+
const policyExclude = ensureYamlListItem(source, policyKey, item);
|
|
415
|
+
source = policyExclude.source;
|
|
416
|
+
changed = policyExclude.changed || changed;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
const effectPatch = ensureYamlMapEntry(source, 'patchedDependencies', `effect@${EFFECT_VERSION}`, effectDeclarationPatchPath);
|
|
420
|
+
source = effectPatch.source;
|
|
421
|
+
changed = effectPatch.changed || changed;
|
|
422
|
+
const drizzleOrmPatch = ensureYamlMapEntry(source, 'patchedDependencies', `drizzle-orm@${DRIZZLE_ORM_VERSION}`, drizzleOrmDeclarationPatchPath);
|
|
423
|
+
source = drizzleOrmPatch.source;
|
|
424
|
+
changed = drizzleOrmPatch.changed || changed;
|
|
425
|
+
if (changed) node_fs.writeFileSync(workspaceFile, source, 'utf-8');
|
|
426
|
+
return changed;
|
|
427
|
+
}
|
|
220
428
|
function updateUltramodernConfig(workspaceRoot, packageSource) {
|
|
221
429
|
const configPath = node_path.join(workspaceRoot, '.modernjs/ultramodern.json');
|
|
222
430
|
const config = readJsonFile(configPath);
|
|
@@ -236,6 +444,57 @@ function updateUltramodernConfig(workspaceRoot, packageSource) {
|
|
|
236
444
|
for (const app of config.topology?.apps ?? [])if (app && 'object' == typeof app && !Array.isArray(app)) normalizeStrictEffectApiMetadata(app);
|
|
237
445
|
writeJsonFile(configPath, config);
|
|
238
446
|
}
|
|
447
|
+
function writeJsonIfChanged(filePath, value) {
|
|
448
|
+
const next = `${JSON.stringify(value, null, 2)}\n`;
|
|
449
|
+
if (node_fs.existsSync(filePath) && node_fs.readFileSync(filePath, 'utf-8') === next) return false;
|
|
450
|
+
node_fs.mkdirSync(node_path.dirname(filePath), {
|
|
451
|
+
recursive: true
|
|
452
|
+
});
|
|
453
|
+
node_fs.writeFileSync(filePath, next, 'utf-8');
|
|
454
|
+
return true;
|
|
455
|
+
}
|
|
456
|
+
function writeTextIfChanged(filePath, value) {
|
|
457
|
+
if (node_fs.existsSync(filePath) && node_fs.readFileSync(filePath, 'utf-8') === value) return false;
|
|
458
|
+
node_fs.mkdirSync(node_path.dirname(filePath), {
|
|
459
|
+
recursive: true
|
|
460
|
+
});
|
|
461
|
+
node_fs.writeFileSync(filePath, value, 'utf-8');
|
|
462
|
+
return true;
|
|
463
|
+
}
|
|
464
|
+
function ensureGeneratedIgnoreRules(workspaceRoot) {
|
|
465
|
+
const gitignorePath = node_path.join(workspaceRoot, '.gitignore');
|
|
466
|
+
const existing = node_fs.existsSync(gitignorePath) ? node_fs.readFileSync(gitignorePath, 'utf-8') : '';
|
|
467
|
+
const lines = 0 === existing.trimEnd().length ? [] : existing.trimEnd().split(/\r?\n/u);
|
|
468
|
+
let changed = false;
|
|
469
|
+
for (const rule of [
|
|
470
|
+
'.mf/',
|
|
471
|
+
'**/.mf/'
|
|
472
|
+
])if (!lines.includes(rule)) {
|
|
473
|
+
lines.push(rule);
|
|
474
|
+
changed = true;
|
|
475
|
+
}
|
|
476
|
+
if (!changed) return false;
|
|
477
|
+
const next = `${lines.join('\n')}\n`;
|
|
478
|
+
node_fs.writeFileSync(gitignorePath, next, 'utf-8');
|
|
479
|
+
return true;
|
|
480
|
+
}
|
|
481
|
+
function updateGeneratedTypeScriptSurfaces(workspaceRoot, config) {
|
|
482
|
+
let changed = false;
|
|
483
|
+
const apps = workspaceAppsFromToolingConfig(config);
|
|
484
|
+
const remotes = apps.filter((app)=>'shell' !== app.kind);
|
|
485
|
+
changed = writeJsonIfChanged(node_path.join(workspaceRoot, 'tsconfig.base.json'), createTsConfigBase()) || changed;
|
|
486
|
+
changed = ensureGeneratedIgnoreRules(workspaceRoot) || changed;
|
|
487
|
+
for (const sharedPackage of [
|
|
488
|
+
'packages/shared-contracts',
|
|
489
|
+
'packages/shared-design-tokens'
|
|
490
|
+
])changed = writeJsonIfChanged(node_path.join(workspaceRoot, sharedPackage, 'tsconfig.json'), createSharedPackageTsConfig(sharedPackage)) || changed;
|
|
491
|
+
for (const app of apps){
|
|
492
|
+
changed = writeJsonIfChanged(node_path.join(workspaceRoot, app.directory, 'tsconfig.json'), createAppTsConfig(app, remotes)) || changed;
|
|
493
|
+
changed = writeJsonIfChanged(node_path.join(workspaceRoot, app.directory, 'tsconfig.mf-types.json'), createAppMfTypesTsConfig(app)) || changed;
|
|
494
|
+
changed = writeTextIfChanged(node_path.join(workspaceRoot, app.directory, 'src/modern-app-env.d.ts'), createAppEnvDts(app, remotes)) || changed;
|
|
495
|
+
}
|
|
496
|
+
return changed;
|
|
497
|
+
}
|
|
239
498
|
function updateReferenceTopology(workspaceRoot) {
|
|
240
499
|
const topologyPath = node_path.join(workspaceRoot, 'topology/reference-topology.json');
|
|
241
500
|
if (!node_fs.existsSync(topologyPath)) return false;
|
|
@@ -298,8 +557,10 @@ function runMigrateStrictEffect(args, context) {
|
|
|
298
557
|
modern-js-create ultramodern migrate-strict-effect --version <version> [--skip-install]
|
|
299
558
|
|
|
300
559
|
Updates generated UltraModern package-source metadata, Modern package aliases,
|
|
301
|
-
direct Effect API topology metadata,
|
|
302
|
-
|
|
560
|
+
framework-owned toolchain pins, direct Effect API topology metadata, strict
|
|
561
|
+
Effect pnpm overrides/trust policy, framework-owned TypeScript config
|
|
562
|
+
surfaces, and the pnpm lockfile. Source code still has to pass pnpm api:check
|
|
563
|
+
and pnpm contract:check.
|
|
303
564
|
`);
|
|
304
565
|
return 0;
|
|
305
566
|
}
|
|
@@ -307,6 +568,7 @@ workspaces. Source code still has to pass pnpm api:check and pnpm contract:check
|
|
|
307
568
|
const packageSource = createMigrationPackageSource(args, current);
|
|
308
569
|
updateUltramodernConfig(context.workspaceRoot, packageSource);
|
|
309
570
|
updateReferenceTopology(context.workspaceRoot);
|
|
571
|
+
updateGeneratedTypeScriptSurfaces(context.workspaceRoot, current);
|
|
310
572
|
for (const relativePackageFile of listWorkspacePackageFiles(context.workspaceRoot)){
|
|
311
573
|
const packageFile = node_path.join(context.workspaceRoot, relativePackageFile);
|
|
312
574
|
const packageJson = readJsonFile(packageFile);
|
|
@@ -317,9 +579,15 @@ workspaces. Source code still has to pass pnpm api:check and pnpm contract:check
|
|
|
317
579
|
config: './.modernjs/ultramodern.json'
|
|
318
580
|
};
|
|
319
581
|
}
|
|
320
|
-
|
|
582
|
+
const modernDependenciesChanged = updateModernDependencies(packageJson, packageSource);
|
|
583
|
+
const toolingDependenciesChanged = updateGeneratedToolingDependencies(packageJson);
|
|
584
|
+
const generatedScriptsChanged = updateGeneratedPackageScripts(packageJson);
|
|
585
|
+
const changed = modernDependenciesChanged || toolingDependenciesChanged || generatedScriptsChanged;
|
|
586
|
+
if (changed) writeJsonFile(packageFile, packageJson);
|
|
321
587
|
else if ('package.json' === relativePackageFile) writeJsonFile(packageFile, packageJson);
|
|
322
588
|
}
|
|
589
|
+
updateGeneratedPnpmWorkspacePolicy(context.workspaceRoot);
|
|
590
|
+
ensureGeneratedDeclarationPatches(context.workspaceRoot);
|
|
323
591
|
if (!hasFlag(args, '--skip-install')) {
|
|
324
592
|
const status = runPnpmLockfileRefresh(context);
|
|
325
593
|
if (0 !== status) return status;
|
|
@@ -28,17 +28,14 @@ function createAppEnvDts(app, remotes = []) {
|
|
|
28
28
|
}
|
|
29
29
|
`;
|
|
30
30
|
})).join('\n');
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
declare module '*.css';
|
|
41
|
-
${remoteModuleDeclarations ? `\n${remoteModuleDeclarations}` : ''}`;
|
|
31
|
+
const reactTypeImport = remoteModuleDeclarations ? "import type React from 'react';\n" : '';
|
|
32
|
+
return [
|
|
33
|
+
`import '@modern-js/app-tools/types';\n${reactTypeImport}`.trimEnd(),
|
|
34
|
+
`declare global {
|
|
35
|
+
const ULTRAMODERN_SITE_URL: string;
|
|
36
|
+
}`,
|
|
37
|
+
remoteModuleDeclarations.trimEnd()
|
|
38
|
+
].filter((section)=>section.length > 0).join('\n\n').concat('\n');
|
|
42
39
|
}
|
|
43
40
|
function createAppRuntimeConfig(app, scope, remotes = []) {
|
|
44
41
|
const pluginsConfig = 'shell' === app.kind ? ` plugins: [
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import "node:module";
|
|
2
|
+
import node_path from "node:path";
|
|
2
3
|
import { WORKSPACE_PACKAGE_VERSION, modernPackageSpecifier } from "../ultramodern-package-source.js";
|
|
3
4
|
import { appHasApi, remoteDependencyAlias, resolveRemoteRefs, sharedPackages, shellApp, verticalApiApps, zephyrRemoteDependency } from "./descriptors.js";
|
|
4
5
|
import { readFileTemplate } from "./fs-io.js";
|
|
@@ -249,7 +250,6 @@ function createTsConfigBase() {
|
|
|
249
250
|
noFallthroughCasesInSwitch: true,
|
|
250
251
|
noPropertyAccessFromIndexSignature: true,
|
|
251
252
|
noImplicitReturns: true,
|
|
252
|
-
skipLibCheck: true,
|
|
253
253
|
resolveJsonModule: true,
|
|
254
254
|
plugins: [
|
|
255
255
|
{
|
|
@@ -281,7 +281,7 @@ function createReferences(packageDir, references) {
|
|
|
281
281
|
return [
|
|
282
282
|
...new Set(references)
|
|
283
283
|
].filter((reference)=>reference !== packageDir).map((reference)=>({
|
|
284
|
-
path:
|
|
284
|
+
path: node_path.relative(packageDir, reference).split(node_path.sep).join('/')
|
|
285
285
|
}));
|
|
286
286
|
}
|
|
287
287
|
function createPackageTsConfig(packageDir, options = {}) {
|
|
@@ -291,8 +291,6 @@ function createPackageTsConfig(packageDir, options = {}) {
|
|
|
291
291
|
const include = resolvedOptions.include ?? [
|
|
292
292
|
'src',
|
|
293
293
|
'locales/**/*.json',
|
|
294
|
-
'modern.config.ts',
|
|
295
|
-
'module-federation.config.ts',
|
|
296
294
|
'package.json',
|
|
297
295
|
'shared'
|
|
298
296
|
];
|
|
@@ -326,9 +324,9 @@ function createAppTsConfig(app, remotes = []) {
|
|
|
326
324
|
});
|
|
327
325
|
}
|
|
328
326
|
function createAppMfTypesTsConfig(app) {
|
|
329
|
-
const exposedFiles = Object.
|
|
327
|
+
const exposedFiles = Object.entries(app.exposes ?? {}).sort(([left], [right])=>'./Route' === left ? -1 : './Route' === right ? 1 : 0).map(([, exposePath])=>exposePath.replace(/^\.\//u, ''));
|
|
330
328
|
return {
|
|
331
|
-
extends:
|
|
329
|
+
extends: `${relativeRootFor(app.directory)}/tsconfig.base.json`,
|
|
332
330
|
include: [
|
|
333
331
|
...new Set([
|
|
334
332
|
...exposedFiles,
|
|
@@ -372,7 +370,7 @@ function createAppPackage(scope, app, packageSource, enableTailwind, remotes = [
|
|
|
372
370
|
scripts: {
|
|
373
371
|
dev: 'modern dev',
|
|
374
372
|
build: app.exposes ? `ULTRAMODERN_ZEPHYR=false modern build && ${publicSurfaceBuildCommand} && node ${relativeRootFor(app.directory)}/scripts/assert-mf-types.mts` : `ULTRAMODERN_ZEPHYR=false modern build && ${publicSurfaceBuildCommand}`,
|
|
375
|
-
'cloudflare:build': `ULTRAMODERN_ZEPHYR=false MODERNJS_DEPLOY=cloudflare modern build && ${publicSurfaceCloudflareBuildCommand} && ULTRAMODERN_ZEPHYR=false MODERNJS_DEPLOY=cloudflare modern deploy && ${publicSurfaceCloudflareOutputCommand}`,
|
|
373
|
+
'cloudflare:build': `ULTRAMODERN_ZEPHYR=false MODERNJS_DEPLOY=cloudflare modern build && ${publicSurfaceCloudflareBuildCommand} && ULTRAMODERN_ZEPHYR=false MODERNJS_DEPLOY=cloudflare modern deploy --skip-build && ${publicSurfaceCloudflareOutputCommand}`,
|
|
376
374
|
'cloudflare:deploy': 'ULTRAMODERN_CLOUDFLARE_REQUIRE_PUBLIC_URLS=true pnpm run cloudflare:build && wrangler deploy --config .output/wrangler.json',
|
|
377
375
|
'cloudflare:preview': 'pnpm run cloudflare:build && wrangler dev --config .output/wrangler.json',
|
|
378
376
|
'cloudflare:proof': `node ${relativeRootFor(app.directory)}/scripts/proof-cloudflare-version.mts --app ${app.id}`,
|
|
@@ -9,14 +9,15 @@ const CLOUDFLARE_COMPATIBILITY_DATE = '2026-06-02';
|
|
|
9
9
|
const TAILWIND_VERSION = '4.3.1';
|
|
10
10
|
const TAILWIND_POSTCSS_VERSION = '4.3.1';
|
|
11
11
|
const POSTCSS_VERSION = '8.5.15';
|
|
12
|
-
const EFFECT_VERSION = '4.0.0-beta.
|
|
13
|
-
const EFFECT_VITEST_VERSION = '4.0.0-beta.
|
|
12
|
+
const EFFECT_VERSION = '4.0.0-beta.91';
|
|
13
|
+
const EFFECT_VITEST_VERSION = '4.0.0-beta.91';
|
|
14
14
|
const EFFECT_TSGO_VERSION = '0.14.6';
|
|
15
|
+
const DRIZZLE_ORM_VERSION = '1.0.0-rc.4';
|
|
15
16
|
const TYPESCRIPT_STABLE_VERSION = '6.0.3';
|
|
16
|
-
const TYPESCRIPT_NATIVE_PREVIEW_VERSION = '7.0.0-dev.
|
|
17
|
+
const TYPESCRIPT_NATIVE_PREVIEW_VERSION = '7.0.0-dev.20260628.1';
|
|
17
18
|
const TYPESCRIPT_VERSION = TYPESCRIPT_STABLE_VERSION;
|
|
18
19
|
const OXLINT_VERSION = '1.71.0';
|
|
19
|
-
const OXFMT_VERSION = '0.
|
|
20
|
+
const OXFMT_VERSION = '0.56.0';
|
|
20
21
|
const ULTRACITE_VERSION = '7.8.3';
|
|
21
22
|
const LEFTHOOK_VERSION = '^2.1.9';
|
|
22
23
|
const I18NEXT_VERSION = '26.3.1';
|
|
@@ -36,7 +37,8 @@ const ultramodernWorkspaceVersions = {
|
|
|
36
37
|
moduleFederation: MODULE_FEDERATION_VERSION,
|
|
37
38
|
effect: EFFECT_VERSION,
|
|
38
39
|
effectVitest: EFFECT_VITEST_VERSION,
|
|
40
|
+
drizzleOrm: DRIZZLE_ORM_VERSION,
|
|
39
41
|
tailwind: TAILWIND_VERSION,
|
|
40
42
|
tailwindPostcss: TAILWIND_POSTCSS_VERSION
|
|
41
43
|
};
|
|
42
|
-
export { CLOUDFLARE_COMPATIBILITY_DATE, EFFECT_TSGO_VERSION, EFFECT_VERSION, EFFECT_VITEST_VERSION, I18NEXT_VERSION, LEFTHOOK_VERSION, MODULE_FEDERATION_AGENT_SKILLS_COMMIT, MODULE_FEDERATION_VERSION, NODE_FETCH_VERSION, NODE_VERSION, OXFMT_VERSION, OXLINT_VERSION, PNPM_VERSION, POSTCSS_VERSION, REACT_DOM_VERSION, REACT_ROUTER_VERSION, REACT_VERSION, RSTACK_AGENT_SKILLS_COMMIT, TAILWIND_POSTCSS_VERSION, TAILWIND_VERSION, TANSTACK_ROUTER_CORE_VERSION, TANSTACK_ROUTER_VERSION, TYPESCRIPT_NATIVE_PREVIEW_VERSION, TYPESCRIPT_STABLE_VERSION, TYPESCRIPT_VERSION, TYPES_REACT_DOM_VERSION, TYPES_REACT_VERSION, ULTRACITE_VERSION, WRANGLER_VERSION, ZEPHYR_AGENT_VERSION, ZEPHYR_RSPACK_PLUGIN_VERSION, ultramodernWorkspaceVersions };
|
|
44
|
+
export { CLOUDFLARE_COMPATIBILITY_DATE, DRIZZLE_ORM_VERSION, EFFECT_TSGO_VERSION, EFFECT_VERSION, EFFECT_VITEST_VERSION, I18NEXT_VERSION, LEFTHOOK_VERSION, MODULE_FEDERATION_AGENT_SKILLS_COMMIT, MODULE_FEDERATION_VERSION, NODE_FETCH_VERSION, NODE_VERSION, OXFMT_VERSION, OXLINT_VERSION, PNPM_VERSION, POSTCSS_VERSION, REACT_DOM_VERSION, REACT_ROUTER_VERSION, REACT_VERSION, RSTACK_AGENT_SKILLS_COMMIT, TAILWIND_POSTCSS_VERSION, TAILWIND_VERSION, TANSTACK_ROUTER_CORE_VERSION, TANSTACK_ROUTER_VERSION, TYPESCRIPT_NATIVE_PREVIEW_VERSION, TYPESCRIPT_STABLE_VERSION, TYPESCRIPT_VERSION, TYPES_REACT_DOM_VERSION, TYPES_REACT_VERSION, ULTRACITE_VERSION, WRANGLER_VERSION, ZEPHYR_AGENT_VERSION, ZEPHYR_RSPACK_PLUGIN_VERSION, ultramodernWorkspaceVersions };
|
|
@@ -9,7 +9,7 @@ import { packageName, tailwindPrefixForApp } from "./naming.js";
|
|
|
9
9
|
import { createCloudflareSecurityContract } from "./policy.js";
|
|
10
10
|
import { publicSurfaceManagedSourceAssetPaths } from "./public-surface.js";
|
|
11
11
|
import { createLocalisedUrlsMap, createRouteMetaFilePath, createRouteOwnedI18nPaths, createRoutePageFilePath } from "./routes.js";
|
|
12
|
-
import { CLOUDFLARE_COMPATIBILITY_DATE, NODE_VERSION, PNPM_VERSION } from "./versions.js";
|
|
12
|
+
import { CLOUDFLARE_COMPATIBILITY_DATE, EFFECT_VERSION, NODE_VERSION, PNPM_VERSION } from "./versions.js";
|
|
13
13
|
function createToolWrapperScript(command, extraArgs = []) {
|
|
14
14
|
const commandJson = JSON.stringify(command);
|
|
15
15
|
const extraArgsJson = JSON.stringify(extraArgs);
|
|
@@ -128,6 +128,7 @@ function createWorkspaceValidationScript(scope, enableTailwind, remotes = []) {
|
|
|
128
128
|
const expectedCloudflareSecurity = createCloudflareSecurityContract();
|
|
129
129
|
return renderFileTemplate("workspace-scripts/validate-ultramodern-workspace.mjs", {
|
|
130
130
|
packageScope: scope,
|
|
131
|
+
effectVersion: EFFECT_VERSION,
|
|
131
132
|
nodeVersion: NODE_VERSION,
|
|
132
133
|
pnpmVersion: PNPM_VERSION,
|
|
133
134
|
tailwindEnabledJson: JSON.stringify(enableTailwind),
|
|
@@ -15,7 +15,7 @@ import { runCodeSmithOverlays } from "./overlays.js";
|
|
|
15
15
|
import { createAppMfTypesTsConfig, createAppPackage, createAppTsConfig, createRootPackageJson, createRootTsConfig, createSharedContractsIndex, createSharedPackage, createSharedPackageTsConfig, createTsConfigBase } from "./package-json.js";
|
|
16
16
|
import { resolvePackageSource } from "./package-source.js";
|
|
17
17
|
import { createPublicWebAppArtifacts } from "./public-surface.js";
|
|
18
|
-
import { EFFECT_VERSION, EFFECT_VITEST_VERSION, NODE_FETCH_VERSION, NODE_VERSION, PNPM_VERSION, TANSTACK_ROUTER_CORE_VERSION, TANSTACK_ROUTER_VERSION, TYPESCRIPT_VERSION } from "./versions.js";
|
|
18
|
+
import { DRIZZLE_ORM_VERSION, EFFECT_VERSION, EFFECT_VITEST_VERSION, NODE_FETCH_VERSION, NODE_VERSION, PNPM_VERSION, TANSTACK_ROUTER_CORE_VERSION, TANSTACK_ROUTER_VERSION, TYPESCRIPT_VERSION } from "./versions.js";
|
|
19
19
|
import { writeGeneratedWorkspaceScripts } from "./workspace-scripts.js";
|
|
20
20
|
function writeApp(targetDir, scope, app, packageSource, enableTailwind, remotes = [], bridge) {
|
|
21
21
|
const resolvedApp = 'shell' === app.kind ? createShellHost(remotes) : app;
|
|
@@ -131,6 +131,7 @@ function generateUltramodernWorkspace(options) {
|
|
|
131
131
|
nodeVersion: NODE_VERSION,
|
|
132
132
|
pnpmVersion: PNPM_VERSION,
|
|
133
133
|
nodeFetchVersion: NODE_FETCH_VERSION,
|
|
134
|
+
drizzleOrmVersion: DRIZZLE_ORM_VERSION,
|
|
134
135
|
effectVersion: EFFECT_VERSION,
|
|
135
136
|
effectVitestVersion: EFFECT_VITEST_VERSION,
|
|
136
137
|
tanstackRouterCoreVersion: TANSTACK_ROUTER_CORE_VERSION,
|
|
@@ -13,14 +13,15 @@ export declare const CLOUDFLARE_COMPATIBILITY_DATE = "2026-06-02";
|
|
|
13
13
|
export declare const TAILWIND_VERSION = "4.3.1";
|
|
14
14
|
export declare const TAILWIND_POSTCSS_VERSION = "4.3.1";
|
|
15
15
|
export declare const POSTCSS_VERSION = "8.5.15";
|
|
16
|
-
export declare const EFFECT_VERSION = "4.0.0-beta.
|
|
17
|
-
export declare const EFFECT_VITEST_VERSION = "4.0.0-beta.
|
|
16
|
+
export declare const EFFECT_VERSION = "4.0.0-beta.91";
|
|
17
|
+
export declare const EFFECT_VITEST_VERSION = "4.0.0-beta.91";
|
|
18
18
|
export declare const EFFECT_TSGO_VERSION = "0.14.6";
|
|
19
|
+
export declare const DRIZZLE_ORM_VERSION = "1.0.0-rc.4";
|
|
19
20
|
export declare const TYPESCRIPT_STABLE_VERSION = "6.0.3";
|
|
20
|
-
export declare const TYPESCRIPT_NATIVE_PREVIEW_VERSION = "7.0.0-dev.
|
|
21
|
+
export declare const TYPESCRIPT_NATIVE_PREVIEW_VERSION = "7.0.0-dev.20260628.1";
|
|
21
22
|
export declare const TYPESCRIPT_VERSION = "6.0.3";
|
|
22
23
|
export declare const OXLINT_VERSION = "1.71.0";
|
|
23
|
-
export declare const OXFMT_VERSION = "0.
|
|
24
|
+
export declare const OXFMT_VERSION = "0.56.0";
|
|
24
25
|
export declare const ULTRACITE_VERSION = "7.8.3";
|
|
25
26
|
export declare const LEFTHOOK_VERSION = "^2.1.9";
|
|
26
27
|
export declare const I18NEXT_VERSION = "26.3.1";
|
|
@@ -40,6 +41,7 @@ export declare const ultramodernWorkspaceVersions: {
|
|
|
40
41
|
moduleFederation: string;
|
|
41
42
|
effect: string;
|
|
42
43
|
effectVitest: string;
|
|
44
|
+
drizzleOrm: string;
|
|
43
45
|
tailwind: string;
|
|
44
46
|
tailwindPostcss: string;
|
|
45
47
|
};
|
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.11",
|
|
25
25
|
"types": "./dist/types/index.d.ts",
|
|
26
26
|
"main": "./dist/esm-node/index.js",
|
|
27
27
|
"bin": {
|
|
@@ -75,14 +75,14 @@
|
|
|
75
75
|
],
|
|
76
76
|
"dependencies": {
|
|
77
77
|
"@modern-js/codesmith": "2.6.9",
|
|
78
|
-
"oxfmt": "0.
|
|
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.11"
|
|
81
81
|
},
|
|
82
82
|
"devDependencies": {
|
|
83
|
-
"@rslib/core": "0.23.
|
|
83
|
+
"@rslib/core": "0.23.1",
|
|
84
84
|
"@types/node": "^26.0.1",
|
|
85
|
-
"@typescript/native-preview": "7.0.0-dev.
|
|
85
|
+
"@typescript/native-preview": "7.0.0-dev.20260628.1",
|
|
86
86
|
"tsx": "^4.22.4",
|
|
87
87
|
"typescript": "^6.0.3",
|
|
88
88
|
"@scripts/rstest-config": "2.66.0"
|
|
@@ -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.11"
|
|
103
103
|
}
|
|
104
104
|
}
|
|
@@ -169,19 +169,23 @@ 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 policy intentionally excludes the matching
|
|
173
|
+
`effect` and `@effect/opentelemetry` cohort versions from the
|
|
174
|
+
minimum-release-age and no-downgrade checks while Effect's beta publishes move
|
|
175
|
+
from trusted-publisher metadata to provenance attestations.
|
|
173
176
|
|
|
174
177
|
For older generated workspaces, run the framework migration command first:
|
|
175
178
|
|
|
176
179
|
```bash
|
|
177
|
-
pnpm dlx @bleedingdev/modern-js-create@3.5.0-ultramodern.
|
|
178
|
-
migrate-strict-effect --version 3.5.0-ultramodern.
|
|
180
|
+
pnpm dlx @bleedingdev/modern-js-create@3.5.0-ultramodern.10 ultramodern \
|
|
181
|
+
migrate-strict-effect --version 3.5.0-ultramodern.10
|
|
179
182
|
pnpm api:check
|
|
180
183
|
pnpm contract:check
|
|
181
184
|
```
|
|
182
185
|
|
|
183
186
|
The command updates generated package-source metadata, Modern package aliases,
|
|
184
|
-
direct API topology metadata,
|
|
187
|
+
framework-owned toolchain pins, direct API topology metadata, strict Effect pnpm
|
|
188
|
+
overrides/trust policy, and the lockfile. Remaining failures are source
|
|
185
189
|
migration work; fix the owning API files instead of adding compatibility shims.
|
|
186
190
|
|
|
187
191
|
## Troubleshooting
|