@bleedingdev/modern-js-create 3.5.0-ultramodern.0 → 3.5.0-ultramodern.2
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 +24 -0
- package/dist/cjs/ultramodern-tooling/commands.cjs +246 -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 +1 -0
- 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 +246 -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 +1 -0
- 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 +246 -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 +1 -0
- 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 +40 -1
- package/template-workspace/pnpm-workspace.yaml.handlebars +3 -0
- package/templates/workspace-scripts/check-ultramodern-api-boundaries.mts +30 -8
- package/templates/workspace-scripts/validate-ultramodern-workspace.mjs.handlebars +2 -0
|
@@ -4,6 +4,7 @@ import node_os from "node:os";
|
|
|
4
4
|
import node_path from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { resolveCreatePackageRoot } from "../create-package-root.js";
|
|
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";
|
|
7
8
|
import { validateModuleFederationTypes } from "../ultramodern-workspace/mf-validation.js";
|
|
8
9
|
import { createWorkspaceValidationScript } from "../ultramodern-workspace/workspace-scripts.js";
|
|
9
10
|
import { readUltramodernConfig, workspaceAppsFromToolingConfig } from "./config.js";
|
|
@@ -17,6 +18,7 @@ Commands:
|
|
|
17
18
|
validate
|
|
18
19
|
typecheck
|
|
19
20
|
mf-types
|
|
21
|
+
migrate-strict-effect
|
|
20
22
|
public-surface
|
|
21
23
|
cloudflare-proof
|
|
22
24
|
performance-readiness
|
|
@@ -82,6 +84,248 @@ Checks real Module Federation config files and DTS archives for exposed apps.
|
|
|
82
84
|
});
|
|
83
85
|
return 0;
|
|
84
86
|
}
|
|
87
|
+
const modernPackageNames = new Set([
|
|
88
|
+
...ULTRAMODERN_SINGLE_APP_MODERN_PACKAGES,
|
|
89
|
+
...ULTRAMODERN_WORKSPACE_MODERN_PACKAGES
|
|
90
|
+
]);
|
|
91
|
+
function readJsonFile(filePath) {
|
|
92
|
+
return JSON.parse(node_fs.readFileSync(filePath, 'utf-8'));
|
|
93
|
+
}
|
|
94
|
+
function writeJsonFile(filePath, value) {
|
|
95
|
+
node_fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`, 'utf-8');
|
|
96
|
+
}
|
|
97
|
+
function readOption(args, name) {
|
|
98
|
+
const prefix = `${name}=`;
|
|
99
|
+
const inline = args.find((arg)=>arg.startsWith(prefix));
|
|
100
|
+
if (inline) {
|
|
101
|
+
const value = inline.slice(prefix.length);
|
|
102
|
+
if (!value) throw new Error(`${name} needs a value.`);
|
|
103
|
+
return value;
|
|
104
|
+
}
|
|
105
|
+
const index = args.indexOf(name);
|
|
106
|
+
if (-1 === index) return;
|
|
107
|
+
const value = args[index + 1];
|
|
108
|
+
if (!value || value.startsWith('--')) throw new Error(`${name} needs a value.`);
|
|
109
|
+
return value;
|
|
110
|
+
}
|
|
111
|
+
function hasFlag(args, name) {
|
|
112
|
+
return args.includes(name);
|
|
113
|
+
}
|
|
114
|
+
function listWorkspacePackageFiles(workspaceRoot) {
|
|
115
|
+
const packageFiles = [
|
|
116
|
+
'package.json'
|
|
117
|
+
];
|
|
118
|
+
for (const directory of [
|
|
119
|
+
'apps',
|
|
120
|
+
'verticals',
|
|
121
|
+
'packages'
|
|
122
|
+
]){
|
|
123
|
+
const absoluteDirectory = node_path.join(workspaceRoot, directory);
|
|
124
|
+
if (node_fs.existsSync(absoluteDirectory)) for (const entry of node_fs.readdirSync(absoluteDirectory, {
|
|
125
|
+
withFileTypes: true
|
|
126
|
+
})){
|
|
127
|
+
if (!entry.isDirectory()) continue;
|
|
128
|
+
const packageFile = node_path.join(directory, entry.name, 'package.json');
|
|
129
|
+
if (node_fs.existsSync(node_path.join(workspaceRoot, packageFile))) packageFiles.push(packageFile);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return packageFiles;
|
|
133
|
+
}
|
|
134
|
+
function updateModernDependencies(packageJson, packageSource) {
|
|
135
|
+
let changed = false;
|
|
136
|
+
for (const section of [
|
|
137
|
+
'dependencies',
|
|
138
|
+
'devDependencies',
|
|
139
|
+
'peerDependencies',
|
|
140
|
+
'optionalDependencies'
|
|
141
|
+
]){
|
|
142
|
+
const dependencies = packageJson[section];
|
|
143
|
+
if (!(!dependencies || 'object' != typeof dependencies || Array.isArray(dependencies))) for (const packageName of Object.keys(dependencies)){
|
|
144
|
+
if (!modernPackageNames.has(packageName)) continue;
|
|
145
|
+
const nextSpecifier = modernPackageSpecifier(packageName, packageSource);
|
|
146
|
+
if (dependencies[packageName] !== nextSpecifier) {
|
|
147
|
+
dependencies[packageName] = nextSpecifier;
|
|
148
|
+
changed = true;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return changed;
|
|
153
|
+
}
|
|
154
|
+
function normalizeStrictEffectApiMetadata(value) {
|
|
155
|
+
const api = value.api;
|
|
156
|
+
if (!api || 'object' != typeof api || Array.isArray(api)) return false;
|
|
157
|
+
let changed = false;
|
|
158
|
+
const oldEffect = api.effect;
|
|
159
|
+
if (oldEffect && 'object' == typeof oldEffect && !Array.isArray(oldEffect)) {
|
|
160
|
+
if (void 0 === api.stem && 'string' == typeof oldEffect.stem) {
|
|
161
|
+
api.stem = oldEffect.stem;
|
|
162
|
+
changed = true;
|
|
163
|
+
}
|
|
164
|
+
if (void 0 === api.prefix && 'string' == typeof oldEffect.prefix) {
|
|
165
|
+
api.prefix = oldEffect.prefix;
|
|
166
|
+
changed = true;
|
|
167
|
+
}
|
|
168
|
+
if (void 0 === api.consumedBy && Array.isArray(oldEffect.consumedBy)) {
|
|
169
|
+
api.consumedBy = oldEffect.consumedBy;
|
|
170
|
+
changed = true;
|
|
171
|
+
}
|
|
172
|
+
delete api.effect;
|
|
173
|
+
changed = true;
|
|
174
|
+
}
|
|
175
|
+
if (void 0 !== api.runtime && 'effect' !== api.runtime) {
|
|
176
|
+
api.runtime = 'effect';
|
|
177
|
+
changed = true;
|
|
178
|
+
}
|
|
179
|
+
if (api.bff && 'object' == typeof api.bff && !Array.isArray(api.bff)) {
|
|
180
|
+
if (true !== api.bff.strictEffectApproach) {
|
|
181
|
+
api.bff.strictEffectApproach = true;
|
|
182
|
+
changed = true;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
if ('string' == typeof value.path) {
|
|
186
|
+
const directServerEntry = `${value.path}/api/index.ts`;
|
|
187
|
+
if ('string' == typeof api.serverEntry && /\/api\/effect\/index\.[cm]?[jt]sx?$/u.test(api.serverEntry)) {
|
|
188
|
+
api.serverEntry = directServerEntry;
|
|
189
|
+
changed = true;
|
|
190
|
+
}
|
|
191
|
+
if (api.contract && 'object' == typeof api.contract && !Array.isArray(api.contract)) {
|
|
192
|
+
if ('./shared/effect/api' === api.contract.export) {
|
|
193
|
+
api.contract.export = './api';
|
|
194
|
+
changed = true;
|
|
195
|
+
}
|
|
196
|
+
if ('string' == typeof api.contract.path && /\/shared\/effect\/api\.[cm]?[jt]sx?$/u.test(api.contract.path)) {
|
|
197
|
+
api.contract.path = `${value.path}/shared/api.ts`;
|
|
198
|
+
changed = true;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
if (api.client && 'object' == typeof api.client && !Array.isArray(api.client)) {
|
|
202
|
+
if ('./effect/client' === api.client.export) {
|
|
203
|
+
api.client.export = './api/client';
|
|
204
|
+
changed = true;
|
|
205
|
+
}
|
|
206
|
+
if ('string' == typeof api.client.path && /\/src\/effect\/[^/]+-client\.[cm]?ts$/u.test(api.client.path)) {
|
|
207
|
+
const basename = node_path.basename(api.client.path);
|
|
208
|
+
api.client.path = `${value.path}/src/api/${basename}`;
|
|
209
|
+
changed = true;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
if (void 0 === api.serverEntry && 'effect' === api.runtime) {
|
|
213
|
+
api.serverEntry = directServerEntry;
|
|
214
|
+
changed = true;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return changed;
|
|
218
|
+
}
|
|
219
|
+
function updateUltramodernConfig(workspaceRoot, packageSource) {
|
|
220
|
+
const configPath = node_path.join(workspaceRoot, '.modernjs/ultramodern.json');
|
|
221
|
+
const config = readJsonFile(configPath);
|
|
222
|
+
config.packageSource = {
|
|
223
|
+
strategy: packageSource.strategy,
|
|
224
|
+
modernPackageVersion: packageSource.modernPackageVersion,
|
|
225
|
+
...packageSource.registry ? {
|
|
226
|
+
registry: packageSource.registry
|
|
227
|
+
} : {},
|
|
228
|
+
...packageSource.aliasScope ? {
|
|
229
|
+
aliasScope: packageSource.aliasScope
|
|
230
|
+
} : {},
|
|
231
|
+
...packageSource.aliasPackageNamePrefix ? {
|
|
232
|
+
aliasPackageNamePrefix: packageSource.aliasPackageNamePrefix
|
|
233
|
+
} : {}
|
|
234
|
+
};
|
|
235
|
+
for (const app of config.topology?.apps ?? [])if (app && 'object' == typeof app && !Array.isArray(app)) normalizeStrictEffectApiMetadata(app);
|
|
236
|
+
writeJsonFile(configPath, config);
|
|
237
|
+
}
|
|
238
|
+
function updateReferenceTopology(workspaceRoot) {
|
|
239
|
+
const topologyPath = node_path.join(workspaceRoot, 'topology/reference-topology.json');
|
|
240
|
+
if (!node_fs.existsSync(topologyPath)) return false;
|
|
241
|
+
const topology = readJsonFile(topologyPath);
|
|
242
|
+
let changed = false;
|
|
243
|
+
for (const vertical of topology.verticals ?? [])if (vertical && 'object' == typeof vertical && !Array.isArray(vertical)) changed = normalizeStrictEffectApiMetadata(vertical) || changed;
|
|
244
|
+
if (changed) writeJsonFile(topologyPath, topology);
|
|
245
|
+
return changed;
|
|
246
|
+
}
|
|
247
|
+
function createMigrationPackageSource(args, current) {
|
|
248
|
+
const strategy = hasFlag(args, '--workspace') ? 'workspace' : 'install';
|
|
249
|
+
const registry = readOption(args, '--registry') ?? readOption(args, '--ultramodern-package-registry');
|
|
250
|
+
const explicitAliasScope = readOption(args, '--alias-scope') ?? readOption(args, '--ultramodern-package-scope');
|
|
251
|
+
const aliasScope = explicitAliasScope ?? ('install' === strategy && void 0 === registry ? current.packageSource?.aliasScope ?? BLEEDINGDEV_PACKAGE_SCOPE : current.packageSource?.aliasScope);
|
|
252
|
+
const aliasPackageNamePrefix = readOption(args, '--alias-package-name-prefix') ?? readOption(args, '--ultramodern-package-name-prefix') ?? current.packageSource?.aliasPackageNamePrefix ?? (aliasScope ? BLEEDINGDEV_PACKAGE_NAME_PREFIX : void 0);
|
|
253
|
+
if ('workspace' === strategy) return {
|
|
254
|
+
strategy,
|
|
255
|
+
modernPackageVersion: WORKSPACE_PACKAGE_VERSION,
|
|
256
|
+
...registry ? {
|
|
257
|
+
registry
|
|
258
|
+
} : {},
|
|
259
|
+
...aliasScope ? {
|
|
260
|
+
aliasScope
|
|
261
|
+
} : {},
|
|
262
|
+
...aliasPackageNamePrefix ? {
|
|
263
|
+
aliasPackageNamePrefix
|
|
264
|
+
} : {}
|
|
265
|
+
};
|
|
266
|
+
const version = readOption(args, '--version') ?? readOption(args, '--ultramodern-package-version') ?? current.packageSource?.modernPackageVersion;
|
|
267
|
+
if (!version || version === WORKSPACE_PACKAGE_VERSION) throw new Error('migrate-strict-effect needs --version <published-ultramodern-version> for install package source.');
|
|
268
|
+
return {
|
|
269
|
+
strategy,
|
|
270
|
+
modernPackageVersion: version,
|
|
271
|
+
...registry ? {
|
|
272
|
+
registry
|
|
273
|
+
} : {},
|
|
274
|
+
...aliasScope ? {
|
|
275
|
+
aliasScope
|
|
276
|
+
} : {},
|
|
277
|
+
...aliasPackageNamePrefix ? {
|
|
278
|
+
aliasPackageNamePrefix
|
|
279
|
+
} : {}
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
function runPnpmLockfileRefresh(context) {
|
|
283
|
+
const result = spawnSync('pnpm', [
|
|
284
|
+
'install',
|
|
285
|
+
'--lockfile-only',
|
|
286
|
+
"--ignore-scripts"
|
|
287
|
+
], {
|
|
288
|
+
cwd: context.workspaceRoot,
|
|
289
|
+
stdio: 'inherit'
|
|
290
|
+
});
|
|
291
|
+
if (result.error) throw result.error;
|
|
292
|
+
return result.status ?? 1;
|
|
293
|
+
}
|
|
294
|
+
function runMigrateStrictEffect(args, context) {
|
|
295
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
296
|
+
process.stdout.write(`Usage:
|
|
297
|
+
modern-js-create ultramodern migrate-strict-effect --version <version> [--skip-install]
|
|
298
|
+
|
|
299
|
+
Updates generated UltraModern package-source metadata, Modern package aliases,
|
|
300
|
+
direct Effect API topology metadata, and the pnpm lockfile for strict Effect
|
|
301
|
+
workspaces. Source code still has to pass pnpm api:check and pnpm contract:check.
|
|
302
|
+
`);
|
|
303
|
+
return 0;
|
|
304
|
+
}
|
|
305
|
+
const current = readUltramodernConfig(context.workspaceRoot);
|
|
306
|
+
const packageSource = createMigrationPackageSource(args, current);
|
|
307
|
+
updateUltramodernConfig(context.workspaceRoot, packageSource);
|
|
308
|
+
updateReferenceTopology(context.workspaceRoot);
|
|
309
|
+
for (const relativePackageFile of listWorkspacePackageFiles(context.workspaceRoot)){
|
|
310
|
+
const packageFile = node_path.join(context.workspaceRoot, relativePackageFile);
|
|
311
|
+
const packageJson = readJsonFile(packageFile);
|
|
312
|
+
if ('package.json' === relativePackageFile) {
|
|
313
|
+
packageJson.modernjs ??= {};
|
|
314
|
+
packageJson.modernjs.packageSource = {
|
|
315
|
+
strategy: packageSource.strategy,
|
|
316
|
+
config: './.modernjs/ultramodern.json'
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
if (updateModernDependencies(packageJson, packageSource)) writeJsonFile(packageFile, packageJson);
|
|
320
|
+
else if ('package.json' === relativePackageFile) writeJsonFile(packageFile, packageJson);
|
|
321
|
+
}
|
|
322
|
+
if (!hasFlag(args, '--skip-install')) {
|
|
323
|
+
const status = runPnpmLockfileRefresh(context);
|
|
324
|
+
if (0 !== status) return status;
|
|
325
|
+
}
|
|
326
|
+
process.stdout.write(`UltraModern strict Effect metadata migrated to ${packageSource.modernPackageVersion}. Run pnpm api:check && pnpm contract:check next.\n`);
|
|
327
|
+
return 0;
|
|
328
|
+
}
|
|
85
329
|
function runSkills(args, context) {
|
|
86
330
|
const [subcommand, ...rest] = args;
|
|
87
331
|
if ('install' === subcommand) return spawnNodeScript("template-workspace/scripts/bootstrap-agent-skills.mjs", rest, context);
|
|
@@ -112,6 +356,8 @@ async function runUltramodernToolingCli(args, workspaceRoot = process.env.ULTRAM
|
|
|
112
356
|
});
|
|
113
357
|
case 'mf-types':
|
|
114
358
|
return runMfTypes(rest, context);
|
|
359
|
+
case 'migrate-strict-effect':
|
|
360
|
+
return runMigrateStrictEffect(rest, context);
|
|
115
361
|
case 'public-surface':
|
|
116
362
|
return spawnNodeScript("templates/workspace-scripts/generate-public-surface-assets.mjs", rest, context);
|
|
117
363
|
case 'cloudflare-proof':
|
|
@@ -254,6 +254,7 @@ function createUltramodernConfig(scope, modernVersion, packageSource, apps = [
|
|
|
254
254
|
publicSurface: "scripts/generate-public-surface-assets.mts",
|
|
255
255
|
cloudflareProof: "scripts/proof-cloudflare-version.mts",
|
|
256
256
|
performanceReadiness: "scripts/ultramodern-performance-readiness.mts",
|
|
257
|
+
migrateStrictEffect: "scripts/migrate-strict-effect.mts",
|
|
257
258
|
apiBoundaries: "scripts/check-ultramodern-api-boundaries.mts",
|
|
258
259
|
skills: "scripts/bootstrap-agent-skills.mts"
|
|
259
260
|
}
|
|
@@ -93,6 +93,8 @@ ${defaultAssetPrefixSource}
|
|
|
93
93
|
// load remoteEntry.js and exposed chunks from the remote origin, not the host.
|
|
94
94
|
const assetPrefix =
|
|
95
95
|
configuredModernAssetPrefix || configuredUltramodernAssetPrefix || defaultAssetPrefix;
|
|
96
|
+
const buildCacheTarget = cloudflareDeployEnabled ? 'cloudflare' : 'web';
|
|
97
|
+
const buildCacheDirectory = \`node_modules/.cache/rspack-\${appId}-\${buildCacheTarget}\`;
|
|
96
98
|
|
|
97
99
|
if (
|
|
98
100
|
cloudflareDeployEnabled &&
|
|
@@ -139,6 +141,10 @@ ${bffConfig} ...(cloudflareDeployEnabled
|
|
|
139
141
|
splitRouteChunks: true,
|
|
140
142
|
},
|
|
141
143
|
performance: {
|
|
144
|
+
buildCache: {
|
|
145
|
+
cacheDigest: [appId, buildCacheTarget],
|
|
146
|
+
cacheDirectory: buildCacheDirectory,
|
|
147
|
+
},
|
|
142
148
|
rsdoctor: {
|
|
143
149
|
disableClientServer: true,
|
|
144
150
|
enabled: process.env['ULTRAMODERN_RSDOCTOR'] === 'true',
|
|
@@ -178,6 +178,7 @@ function createRootPackageJson(scope, packageSource, remotes = [], bridge) {
|
|
|
178
178
|
'agents:refs:check': "node ./scripts/setup-agent-reference-repos.mts --check",
|
|
179
179
|
'mf:types': "node ./scripts/assert-mf-types.mts",
|
|
180
180
|
'performance:readiness': "node ./scripts/ultramodern-performance-readiness.mts",
|
|
181
|
+
'migrate:strict-effect': "node ./scripts/migrate-strict-effect.mts",
|
|
181
182
|
'contract:check': "node ./scripts/validate-ultramodern-workspace.mts",
|
|
182
183
|
'api:check': "node ./scripts/check-ultramodern-api-boundaries.mts",
|
|
183
184
|
'i18n:boundaries': "node ./scripts/check-ultramodern-i18n-boundaries.mts",
|
|
@@ -8,12 +8,14 @@ const CLOUDFLARE_COMPATIBILITY_DATE = '2026-06-02';
|
|
|
8
8
|
const TAILWIND_VERSION = '4.3.1';
|
|
9
9
|
const TAILWIND_POSTCSS_VERSION = '4.3.1';
|
|
10
10
|
const POSTCSS_VERSION = '8.5.15';
|
|
11
|
+
const EFFECT_VERSION = '4.0.0-beta.91';
|
|
12
|
+
const EFFECT_VITEST_VERSION = '4.0.0-beta.91';
|
|
11
13
|
const EFFECT_TSGO_VERSION = '0.14.6';
|
|
12
14
|
const TYPESCRIPT_STABLE_VERSION = '6.0.3';
|
|
13
|
-
const TYPESCRIPT_NATIVE_PREVIEW_VERSION = '7.0.0-dev.
|
|
15
|
+
const TYPESCRIPT_NATIVE_PREVIEW_VERSION = '7.0.0-dev.20260628.1';
|
|
14
16
|
const TYPESCRIPT_VERSION = TYPESCRIPT_STABLE_VERSION;
|
|
15
17
|
const OXLINT_VERSION = '1.71.0';
|
|
16
|
-
const OXFMT_VERSION = '0.
|
|
18
|
+
const OXFMT_VERSION = '0.56.0';
|
|
17
19
|
const ULTRACITE_VERSION = '7.8.3';
|
|
18
20
|
const LEFTHOOK_VERSION = '^2.1.9';
|
|
19
21
|
const I18NEXT_VERSION = '26.3.1';
|
|
@@ -31,7 +33,9 @@ const ultramodernWorkspaceVersions = {
|
|
|
31
33
|
tanstackRouter: TANSTACK_ROUTER_VERSION,
|
|
32
34
|
tanstackRouterCore: TANSTACK_ROUTER_CORE_VERSION,
|
|
33
35
|
moduleFederation: MODULE_FEDERATION_VERSION,
|
|
36
|
+
effect: EFFECT_VERSION,
|
|
37
|
+
effectVitest: EFFECT_VITEST_VERSION,
|
|
34
38
|
tailwind: TAILWIND_VERSION,
|
|
35
39
|
tailwindPostcss: TAILWIND_POSTCSS_VERSION
|
|
36
40
|
};
|
|
37
|
-
export { CLOUDFLARE_COMPATIBILITY_DATE, EFFECT_TSGO_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 };
|
|
41
|
+
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 };
|
|
@@ -162,6 +162,7 @@ function writeGeneratedWorkspaceScripts(targetDir, _scope, _enableTailwind, _rem
|
|
|
162
162
|
writeWorkspaceOwnedMtsScript(targetDir, 'proof-cloudflare-version', createToolWrapperScript('cloudflare-proof'));
|
|
163
163
|
writeFileReplacing(targetDir, "scripts/ultramodern-performance-readiness.config.mjs", createPerformanceReadinessConfigScript());
|
|
164
164
|
writeWorkspaceOwnedMtsScript(targetDir, 'ultramodern-performance-readiness', createToolWrapperScript('performance-readiness'));
|
|
165
|
+
writeWorkspaceOwnedMtsScript(targetDir, 'migrate-strict-effect', createToolWrapperScript('migrate-strict-effect'));
|
|
165
166
|
writeWorkspaceOwnedMtsScript(targetDir, 'ultramodern-typecheck', createToolWrapperScript('typecheck'));
|
|
166
167
|
writeWorkspaceOwnedMtsScript(targetDir, 'bootstrap-agent-skills', createSkillsToolWrapperScript());
|
|
167
168
|
migrateCopiedWorkspaceScriptToMts(targetDir, 'setup-agent-reference-repos');
|
|
@@ -14,7 +14,7 @@ import { runCodeSmithOverlays } from "./overlays.js";
|
|
|
14
14
|
import { createAppMfTypesTsConfig, createAppPackage, createAppTsConfig, createRootPackageJson, createRootTsConfig, createSharedContractsIndex, createSharedPackage, createSharedPackageTsConfig, createTsConfigBase } from "./package-json.js";
|
|
15
15
|
import { resolvePackageSource } from "./package-source.js";
|
|
16
16
|
import { createPublicWebAppArtifacts } from "./public-surface.js";
|
|
17
|
-
import { NODE_FETCH_VERSION, NODE_VERSION, PNPM_VERSION, TANSTACK_ROUTER_CORE_VERSION, TANSTACK_ROUTER_VERSION, TYPESCRIPT_VERSION } from "./versions.js";
|
|
17
|
+
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
18
|
import { writeGeneratedWorkspaceScripts } from "./workspace-scripts.js";
|
|
19
19
|
function writeApp(targetDir, scope, app, packageSource, enableTailwind, remotes = [], bridge) {
|
|
20
20
|
const resolvedApp = 'shell' === app.kind ? createShellHost(remotes) : app;
|
|
@@ -130,6 +130,8 @@ function generateUltramodernWorkspace(options) {
|
|
|
130
130
|
nodeVersion: NODE_VERSION,
|
|
131
131
|
pnpmVersion: PNPM_VERSION,
|
|
132
132
|
nodeFetchVersion: NODE_FETCH_VERSION,
|
|
133
|
+
effectVersion: EFFECT_VERSION,
|
|
134
|
+
effectVitestVersion: EFFECT_VITEST_VERSION,
|
|
133
135
|
tanstackRouterCoreVersion: TANSTACK_ROUTER_CORE_VERSION,
|
|
134
136
|
tanstackRouterVersion: TANSTACK_ROUTER_VERSION,
|
|
135
137
|
typescriptVersion: TYPESCRIPT_VERSION,
|
|
@@ -5,6 +5,7 @@ import node_os from "node:os";
|
|
|
5
5
|
import node_path from "node:path";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
7
|
import { resolveCreatePackageRoot } from "../create-package-root.js";
|
|
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";
|
|
8
9
|
import { validateModuleFederationTypes } from "../ultramodern-workspace/mf-validation.js";
|
|
9
10
|
import { createWorkspaceValidationScript } from "../ultramodern-workspace/workspace-scripts.js";
|
|
10
11
|
import { readUltramodernConfig, workspaceAppsFromToolingConfig } from "./config.js";
|
|
@@ -18,6 +19,7 @@ Commands:
|
|
|
18
19
|
validate
|
|
19
20
|
typecheck
|
|
20
21
|
mf-types
|
|
22
|
+
migrate-strict-effect
|
|
21
23
|
public-surface
|
|
22
24
|
cloudflare-proof
|
|
23
25
|
performance-readiness
|
|
@@ -83,6 +85,248 @@ Checks real Module Federation config files and DTS archives for exposed apps.
|
|
|
83
85
|
});
|
|
84
86
|
return 0;
|
|
85
87
|
}
|
|
88
|
+
const modernPackageNames = new Set([
|
|
89
|
+
...ULTRAMODERN_SINGLE_APP_MODERN_PACKAGES,
|
|
90
|
+
...ULTRAMODERN_WORKSPACE_MODERN_PACKAGES
|
|
91
|
+
]);
|
|
92
|
+
function readJsonFile(filePath) {
|
|
93
|
+
return JSON.parse(node_fs.readFileSync(filePath, 'utf-8'));
|
|
94
|
+
}
|
|
95
|
+
function writeJsonFile(filePath, value) {
|
|
96
|
+
node_fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`, 'utf-8');
|
|
97
|
+
}
|
|
98
|
+
function readOption(args, name) {
|
|
99
|
+
const prefix = `${name}=`;
|
|
100
|
+
const inline = args.find((arg)=>arg.startsWith(prefix));
|
|
101
|
+
if (inline) {
|
|
102
|
+
const value = inline.slice(prefix.length);
|
|
103
|
+
if (!value) throw new Error(`${name} needs a value.`);
|
|
104
|
+
return value;
|
|
105
|
+
}
|
|
106
|
+
const index = args.indexOf(name);
|
|
107
|
+
if (-1 === index) return;
|
|
108
|
+
const value = args[index + 1];
|
|
109
|
+
if (!value || value.startsWith('--')) throw new Error(`${name} needs a value.`);
|
|
110
|
+
return value;
|
|
111
|
+
}
|
|
112
|
+
function hasFlag(args, name) {
|
|
113
|
+
return args.includes(name);
|
|
114
|
+
}
|
|
115
|
+
function listWorkspacePackageFiles(workspaceRoot) {
|
|
116
|
+
const packageFiles = [
|
|
117
|
+
'package.json'
|
|
118
|
+
];
|
|
119
|
+
for (const directory of [
|
|
120
|
+
'apps',
|
|
121
|
+
'verticals',
|
|
122
|
+
'packages'
|
|
123
|
+
]){
|
|
124
|
+
const absoluteDirectory = node_path.join(workspaceRoot, directory);
|
|
125
|
+
if (node_fs.existsSync(absoluteDirectory)) for (const entry of node_fs.readdirSync(absoluteDirectory, {
|
|
126
|
+
withFileTypes: true
|
|
127
|
+
})){
|
|
128
|
+
if (!entry.isDirectory()) continue;
|
|
129
|
+
const packageFile = node_path.join(directory, entry.name, 'package.json');
|
|
130
|
+
if (node_fs.existsSync(node_path.join(workspaceRoot, packageFile))) packageFiles.push(packageFile);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return packageFiles;
|
|
134
|
+
}
|
|
135
|
+
function updateModernDependencies(packageJson, packageSource) {
|
|
136
|
+
let changed = false;
|
|
137
|
+
for (const section of [
|
|
138
|
+
'dependencies',
|
|
139
|
+
'devDependencies',
|
|
140
|
+
'peerDependencies',
|
|
141
|
+
'optionalDependencies'
|
|
142
|
+
]){
|
|
143
|
+
const dependencies = packageJson[section];
|
|
144
|
+
if (!(!dependencies || 'object' != typeof dependencies || Array.isArray(dependencies))) for (const packageName of Object.keys(dependencies)){
|
|
145
|
+
if (!modernPackageNames.has(packageName)) continue;
|
|
146
|
+
const nextSpecifier = modernPackageSpecifier(packageName, packageSource);
|
|
147
|
+
if (dependencies[packageName] !== nextSpecifier) {
|
|
148
|
+
dependencies[packageName] = nextSpecifier;
|
|
149
|
+
changed = true;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return changed;
|
|
154
|
+
}
|
|
155
|
+
function normalizeStrictEffectApiMetadata(value) {
|
|
156
|
+
const api = value.api;
|
|
157
|
+
if (!api || 'object' != typeof api || Array.isArray(api)) return false;
|
|
158
|
+
let changed = false;
|
|
159
|
+
const oldEffect = api.effect;
|
|
160
|
+
if (oldEffect && 'object' == typeof oldEffect && !Array.isArray(oldEffect)) {
|
|
161
|
+
if (void 0 === api.stem && 'string' == typeof oldEffect.stem) {
|
|
162
|
+
api.stem = oldEffect.stem;
|
|
163
|
+
changed = true;
|
|
164
|
+
}
|
|
165
|
+
if (void 0 === api.prefix && 'string' == typeof oldEffect.prefix) {
|
|
166
|
+
api.prefix = oldEffect.prefix;
|
|
167
|
+
changed = true;
|
|
168
|
+
}
|
|
169
|
+
if (void 0 === api.consumedBy && Array.isArray(oldEffect.consumedBy)) {
|
|
170
|
+
api.consumedBy = oldEffect.consumedBy;
|
|
171
|
+
changed = true;
|
|
172
|
+
}
|
|
173
|
+
delete api.effect;
|
|
174
|
+
changed = true;
|
|
175
|
+
}
|
|
176
|
+
if (void 0 !== api.runtime && 'effect' !== api.runtime) {
|
|
177
|
+
api.runtime = 'effect';
|
|
178
|
+
changed = true;
|
|
179
|
+
}
|
|
180
|
+
if (api.bff && 'object' == typeof api.bff && !Array.isArray(api.bff)) {
|
|
181
|
+
if (true !== api.bff.strictEffectApproach) {
|
|
182
|
+
api.bff.strictEffectApproach = true;
|
|
183
|
+
changed = true;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
if ('string' == typeof value.path) {
|
|
187
|
+
const directServerEntry = `${value.path}/api/index.ts`;
|
|
188
|
+
if ('string' == typeof api.serverEntry && /\/api\/effect\/index\.[cm]?[jt]sx?$/u.test(api.serverEntry)) {
|
|
189
|
+
api.serverEntry = directServerEntry;
|
|
190
|
+
changed = true;
|
|
191
|
+
}
|
|
192
|
+
if (api.contract && 'object' == typeof api.contract && !Array.isArray(api.contract)) {
|
|
193
|
+
if ('./shared/effect/api' === api.contract.export) {
|
|
194
|
+
api.contract.export = './api';
|
|
195
|
+
changed = true;
|
|
196
|
+
}
|
|
197
|
+
if ('string' == typeof api.contract.path && /\/shared\/effect\/api\.[cm]?[jt]sx?$/u.test(api.contract.path)) {
|
|
198
|
+
api.contract.path = `${value.path}/shared/api.ts`;
|
|
199
|
+
changed = true;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
if (api.client && 'object' == typeof api.client && !Array.isArray(api.client)) {
|
|
203
|
+
if ('./effect/client' === api.client.export) {
|
|
204
|
+
api.client.export = './api/client';
|
|
205
|
+
changed = true;
|
|
206
|
+
}
|
|
207
|
+
if ('string' == typeof api.client.path && /\/src\/effect\/[^/]+-client\.[cm]?ts$/u.test(api.client.path)) {
|
|
208
|
+
const basename = node_path.basename(api.client.path);
|
|
209
|
+
api.client.path = `${value.path}/src/api/${basename}`;
|
|
210
|
+
changed = true;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
if (void 0 === api.serverEntry && 'effect' === api.runtime) {
|
|
214
|
+
api.serverEntry = directServerEntry;
|
|
215
|
+
changed = true;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return changed;
|
|
219
|
+
}
|
|
220
|
+
function updateUltramodernConfig(workspaceRoot, packageSource) {
|
|
221
|
+
const configPath = node_path.join(workspaceRoot, '.modernjs/ultramodern.json');
|
|
222
|
+
const config = readJsonFile(configPath);
|
|
223
|
+
config.packageSource = {
|
|
224
|
+
strategy: packageSource.strategy,
|
|
225
|
+
modernPackageVersion: packageSource.modernPackageVersion,
|
|
226
|
+
...packageSource.registry ? {
|
|
227
|
+
registry: packageSource.registry
|
|
228
|
+
} : {},
|
|
229
|
+
...packageSource.aliasScope ? {
|
|
230
|
+
aliasScope: packageSource.aliasScope
|
|
231
|
+
} : {},
|
|
232
|
+
...packageSource.aliasPackageNamePrefix ? {
|
|
233
|
+
aliasPackageNamePrefix: packageSource.aliasPackageNamePrefix
|
|
234
|
+
} : {}
|
|
235
|
+
};
|
|
236
|
+
for (const app of config.topology?.apps ?? [])if (app && 'object' == typeof app && !Array.isArray(app)) normalizeStrictEffectApiMetadata(app);
|
|
237
|
+
writeJsonFile(configPath, config);
|
|
238
|
+
}
|
|
239
|
+
function updateReferenceTopology(workspaceRoot) {
|
|
240
|
+
const topologyPath = node_path.join(workspaceRoot, 'topology/reference-topology.json');
|
|
241
|
+
if (!node_fs.existsSync(topologyPath)) return false;
|
|
242
|
+
const topology = readJsonFile(topologyPath);
|
|
243
|
+
let changed = false;
|
|
244
|
+
for (const vertical of topology.verticals ?? [])if (vertical && 'object' == typeof vertical && !Array.isArray(vertical)) changed = normalizeStrictEffectApiMetadata(vertical) || changed;
|
|
245
|
+
if (changed) writeJsonFile(topologyPath, topology);
|
|
246
|
+
return changed;
|
|
247
|
+
}
|
|
248
|
+
function createMigrationPackageSource(args, current) {
|
|
249
|
+
const strategy = hasFlag(args, '--workspace') ? 'workspace' : 'install';
|
|
250
|
+
const registry = readOption(args, '--registry') ?? readOption(args, '--ultramodern-package-registry');
|
|
251
|
+
const explicitAliasScope = readOption(args, '--alias-scope') ?? readOption(args, '--ultramodern-package-scope');
|
|
252
|
+
const aliasScope = explicitAliasScope ?? ('install' === strategy && void 0 === registry ? current.packageSource?.aliasScope ?? BLEEDINGDEV_PACKAGE_SCOPE : current.packageSource?.aliasScope);
|
|
253
|
+
const aliasPackageNamePrefix = readOption(args, '--alias-package-name-prefix') ?? readOption(args, '--ultramodern-package-name-prefix') ?? current.packageSource?.aliasPackageNamePrefix ?? (aliasScope ? BLEEDINGDEV_PACKAGE_NAME_PREFIX : void 0);
|
|
254
|
+
if ('workspace' === strategy) return {
|
|
255
|
+
strategy,
|
|
256
|
+
modernPackageVersion: WORKSPACE_PACKAGE_VERSION,
|
|
257
|
+
...registry ? {
|
|
258
|
+
registry
|
|
259
|
+
} : {},
|
|
260
|
+
...aliasScope ? {
|
|
261
|
+
aliasScope
|
|
262
|
+
} : {},
|
|
263
|
+
...aliasPackageNamePrefix ? {
|
|
264
|
+
aliasPackageNamePrefix
|
|
265
|
+
} : {}
|
|
266
|
+
};
|
|
267
|
+
const version = readOption(args, '--version') ?? readOption(args, '--ultramodern-package-version') ?? current.packageSource?.modernPackageVersion;
|
|
268
|
+
if (!version || version === WORKSPACE_PACKAGE_VERSION) throw new Error('migrate-strict-effect needs --version <published-ultramodern-version> for install package source.');
|
|
269
|
+
return {
|
|
270
|
+
strategy,
|
|
271
|
+
modernPackageVersion: version,
|
|
272
|
+
...registry ? {
|
|
273
|
+
registry
|
|
274
|
+
} : {},
|
|
275
|
+
...aliasScope ? {
|
|
276
|
+
aliasScope
|
|
277
|
+
} : {},
|
|
278
|
+
...aliasPackageNamePrefix ? {
|
|
279
|
+
aliasPackageNamePrefix
|
|
280
|
+
} : {}
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
function runPnpmLockfileRefresh(context) {
|
|
284
|
+
const result = spawnSync('pnpm', [
|
|
285
|
+
'install',
|
|
286
|
+
'--lockfile-only',
|
|
287
|
+
"--ignore-scripts"
|
|
288
|
+
], {
|
|
289
|
+
cwd: context.workspaceRoot,
|
|
290
|
+
stdio: 'inherit'
|
|
291
|
+
});
|
|
292
|
+
if (result.error) throw result.error;
|
|
293
|
+
return result.status ?? 1;
|
|
294
|
+
}
|
|
295
|
+
function runMigrateStrictEffect(args, context) {
|
|
296
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
297
|
+
process.stdout.write(`Usage:
|
|
298
|
+
modern-js-create ultramodern migrate-strict-effect --version <version> [--skip-install]
|
|
299
|
+
|
|
300
|
+
Updates generated UltraModern package-source metadata, Modern package aliases,
|
|
301
|
+
direct Effect API topology metadata, and the pnpm lockfile for strict Effect
|
|
302
|
+
workspaces. Source code still has to pass pnpm api:check and pnpm contract:check.
|
|
303
|
+
`);
|
|
304
|
+
return 0;
|
|
305
|
+
}
|
|
306
|
+
const current = readUltramodernConfig(context.workspaceRoot);
|
|
307
|
+
const packageSource = createMigrationPackageSource(args, current);
|
|
308
|
+
updateUltramodernConfig(context.workspaceRoot, packageSource);
|
|
309
|
+
updateReferenceTopology(context.workspaceRoot);
|
|
310
|
+
for (const relativePackageFile of listWorkspacePackageFiles(context.workspaceRoot)){
|
|
311
|
+
const packageFile = node_path.join(context.workspaceRoot, relativePackageFile);
|
|
312
|
+
const packageJson = readJsonFile(packageFile);
|
|
313
|
+
if ('package.json' === relativePackageFile) {
|
|
314
|
+
packageJson.modernjs ??= {};
|
|
315
|
+
packageJson.modernjs.packageSource = {
|
|
316
|
+
strategy: packageSource.strategy,
|
|
317
|
+
config: './.modernjs/ultramodern.json'
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
if (updateModernDependencies(packageJson, packageSource)) writeJsonFile(packageFile, packageJson);
|
|
321
|
+
else if ('package.json' === relativePackageFile) writeJsonFile(packageFile, packageJson);
|
|
322
|
+
}
|
|
323
|
+
if (!hasFlag(args, '--skip-install')) {
|
|
324
|
+
const status = runPnpmLockfileRefresh(context);
|
|
325
|
+
if (0 !== status) return status;
|
|
326
|
+
}
|
|
327
|
+
process.stdout.write(`UltraModern strict Effect metadata migrated to ${packageSource.modernPackageVersion}. Run pnpm api:check && pnpm contract:check next.\n`);
|
|
328
|
+
return 0;
|
|
329
|
+
}
|
|
86
330
|
function runSkills(args, context) {
|
|
87
331
|
const [subcommand, ...rest] = args;
|
|
88
332
|
if ('install' === subcommand) return spawnNodeScript("template-workspace/scripts/bootstrap-agent-skills.mjs", rest, context);
|
|
@@ -113,6 +357,8 @@ async function runUltramodernToolingCli(args, workspaceRoot = process.env.ULTRAM
|
|
|
113
357
|
});
|
|
114
358
|
case 'mf-types':
|
|
115
359
|
return runMfTypes(rest, context);
|
|
360
|
+
case 'migrate-strict-effect':
|
|
361
|
+
return runMigrateStrictEffect(rest, context);
|
|
116
362
|
case 'public-surface':
|
|
117
363
|
return spawnNodeScript("templates/workspace-scripts/generate-public-surface-assets.mjs", rest, context);
|
|
118
364
|
case 'cloudflare-proof':
|
|
@@ -255,6 +255,7 @@ function createUltramodernConfig(scope, modernVersion, packageSource, apps = [
|
|
|
255
255
|
publicSurface: "scripts/generate-public-surface-assets.mts",
|
|
256
256
|
cloudflareProof: "scripts/proof-cloudflare-version.mts",
|
|
257
257
|
performanceReadiness: "scripts/ultramodern-performance-readiness.mts",
|
|
258
|
+
migrateStrictEffect: "scripts/migrate-strict-effect.mts",
|
|
258
259
|
apiBoundaries: "scripts/check-ultramodern-api-boundaries.mts",
|
|
259
260
|
skills: "scripts/bootstrap-agent-skills.mts"
|
|
260
261
|
}
|
|
@@ -94,6 +94,8 @@ ${defaultAssetPrefixSource}
|
|
|
94
94
|
// load remoteEntry.js and exposed chunks from the remote origin, not the host.
|
|
95
95
|
const assetPrefix =
|
|
96
96
|
configuredModernAssetPrefix || configuredUltramodernAssetPrefix || defaultAssetPrefix;
|
|
97
|
+
const buildCacheTarget = cloudflareDeployEnabled ? 'cloudflare' : 'web';
|
|
98
|
+
const buildCacheDirectory = \`node_modules/.cache/rspack-\${appId}-\${buildCacheTarget}\`;
|
|
97
99
|
|
|
98
100
|
if (
|
|
99
101
|
cloudflareDeployEnabled &&
|
|
@@ -140,6 +142,10 @@ ${bffConfig} ...(cloudflareDeployEnabled
|
|
|
140
142
|
splitRouteChunks: true,
|
|
141
143
|
},
|
|
142
144
|
performance: {
|
|
145
|
+
buildCache: {
|
|
146
|
+
cacheDigest: [appId, buildCacheTarget],
|
|
147
|
+
cacheDirectory: buildCacheDirectory,
|
|
148
|
+
},
|
|
143
149
|
rsdoctor: {
|
|
144
150
|
disableClientServer: true,
|
|
145
151
|
enabled: process.env['ULTRAMODERN_RSDOCTOR'] === 'true',
|