@bleedingdev/modern-js-create 3.5.0-ultramodern.0 → 3.5.0-ultramodern.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -0
- package/dist/cjs/ultramodern-tooling/commands.cjs +399 -0
- package/dist/cjs/ultramodern-workspace/contracts.cjs +1 -0
- package/dist/cjs/ultramodern-workspace/module-federation.cjs +6 -0
- package/dist/cjs/ultramodern-workspace/package-json.cjs +2 -1
- package/dist/cjs/ultramodern-workspace/versions.cjs +12 -2
- package/dist/cjs/ultramodern-workspace/workspace-scripts.cjs +1 -0
- package/dist/cjs/ultramodern-workspace/write-workspace.cjs +2 -0
- package/dist/esm/ultramodern-tooling/commands.js +399 -0
- package/dist/esm/ultramodern-workspace/contracts.js +1 -0
- package/dist/esm/ultramodern-workspace/module-federation.js +6 -0
- package/dist/esm/ultramodern-workspace/package-json.js +2 -1
- package/dist/esm/ultramodern-workspace/versions.js +7 -3
- package/dist/esm/ultramodern-workspace/workspace-scripts.js +1 -0
- package/dist/esm/ultramodern-workspace/write-workspace.js +3 -1
- package/dist/esm-node/ultramodern-tooling/commands.js +399 -0
- package/dist/esm-node/ultramodern-workspace/contracts.js +1 -0
- package/dist/esm-node/ultramodern-workspace/module-federation.js +6 -0
- package/dist/esm-node/ultramodern-workspace/package-json.js +2 -1
- package/dist/esm-node/ultramodern-workspace/versions.js +7 -3
- package/dist/esm-node/ultramodern-workspace/workspace-scripts.js +1 -0
- package/dist/esm-node/ultramodern-workspace/write-workspace.js +3 -1
- package/dist/types/ultramodern-workspace/versions.d.ts +6 -2
- package/package.json +6 -6
- package/template-workspace/README.md.handlebars +44 -1
- package/template-workspace/pnpm-workspace.yaml.handlebars +8 -0
- package/templates/workspace-scripts/check-ultramodern-api-boundaries.mts +30 -8
- package/templates/workspace-scripts/validate-ultramodern-workspace.mjs.handlebars +23 -0
|
@@ -8,6 +8,8 @@ minimumReleaseAgeStrict: true
|
|
|
8
8
|
minimumReleaseAgeIgnoreMissingTime: false
|
|
9
9
|
minimumReleaseAgeExclude:
|
|
10
10
|
- '@bleedingdev/modern-js-*'
|
|
11
|
+
- 'effect@{{effectVersion}}'
|
|
12
|
+
- '@effect/opentelemetry@{{effectVersion}}'
|
|
11
13
|
- '@tanstack/react-router'
|
|
12
14
|
- '@tanstack/router-core'
|
|
13
15
|
- 'typescript'
|
|
@@ -24,6 +26,9 @@ minimumReleaseAgeExclude:
|
|
|
24
26
|
- 'ts-checker-rspack-plugin'
|
|
25
27
|
trustPolicy: no-downgrade
|
|
26
28
|
trustPolicyIgnoreAfter: 1440
|
|
29
|
+
trustPolicyExclude:
|
|
30
|
+
- 'effect@{{effectVersion}}'
|
|
31
|
+
- '@effect/opentelemetry@{{effectVersion}}'
|
|
27
32
|
blockExoticSubdeps: true
|
|
28
33
|
engineStrict: true
|
|
29
34
|
pmOnFail: error
|
|
@@ -37,11 +42,14 @@ peerDependencyRules:
|
|
|
37
42
|
'@module-federation/enhanced>typescript': '{{typescriptVersion}}'
|
|
38
43
|
'@module-federation/modern-js-v3>typescript': '{{typescriptVersion}}'
|
|
39
44
|
'@module-federation/rspack>typescript': '{{typescriptVersion}}'
|
|
45
|
+
'@effect/vitest>effect': '{{effectVersion}}'
|
|
40
46
|
'i18next>typescript': '{{typescriptVersion}}'
|
|
41
47
|
|
|
42
48
|
overrides:
|
|
43
49
|
'@tanstack/react-router': {{tanstackRouterVersion}}
|
|
44
50
|
'@tanstack/router-core': {{tanstackRouterCoreVersion}}
|
|
51
|
+
'@effect/vitest': {{effectVitestVersion}}
|
|
52
|
+
effect: {{effectVersion}}
|
|
45
53
|
node-fetch: '{{nodeFetchVersion}}'
|
|
46
54
|
|
|
47
55
|
allowBuilds:
|
|
@@ -97,7 +97,12 @@ function assertNotContains(relativePath, content, pattern, message) {
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
for (const forbiddenPath of [
|
|
100
|
-
'apps
|
|
100
|
+
...listDirectories('apps').flatMap(appPath => [
|
|
101
|
+
`${appPath}/api/effect`,
|
|
102
|
+
`${appPath}/api/lambda`,
|
|
103
|
+
`${appPath}/shared/effect`,
|
|
104
|
+
`${appPath}/src/effect`,
|
|
105
|
+
]),
|
|
101
106
|
...listDirectories('verticals').flatMap(verticalPath => [
|
|
102
107
|
`${verticalPath}/api/effect`,
|
|
103
108
|
`${verticalPath}/api/lambda`,
|
|
@@ -148,6 +153,12 @@ for (const file of textFiles) {
|
|
|
148
153
|
/\bcreateHandler\s*[:=]\s*(?!defineEffectBff\b)/u,
|
|
149
154
|
'API modules must not define unbranded handler factories; use defineEffectBff(...).',
|
|
150
155
|
);
|
|
156
|
+
assertNotContains(
|
|
157
|
+
file,
|
|
158
|
+
content,
|
|
159
|
+
/\bSchema\.(?:UnknownFromJsonString|Unknown|Any)\b/u,
|
|
160
|
+
'API modules must use concrete request, response and error schemas; Schema.UnknownFromJsonString, Schema.Unknown and Schema.Any are forbidden in UltraModern API code.',
|
|
161
|
+
);
|
|
151
162
|
}
|
|
152
163
|
|
|
153
164
|
assertNotContains(
|
|
@@ -170,17 +181,18 @@ for (const file of textFiles) {
|
|
|
170
181
|
);
|
|
171
182
|
}
|
|
172
183
|
|
|
184
|
+
const verticalDirectories = listDirectories('verticals');
|
|
173
185
|
const shellClient = 'apps/shell-super-app/src/api/vertical-clients.ts';
|
|
174
|
-
if (exists('apps/shell-super-app')) {
|
|
186
|
+
if (exists('apps/shell-super-app') && verticalDirectories.length > 0) {
|
|
175
187
|
assert(exists(shellClient), `${shellClient} must aggregate vertical API clients.`);
|
|
176
188
|
}
|
|
177
189
|
|
|
178
|
-
|
|
179
|
-
const apiEntry = `${
|
|
180
|
-
const sharedApi = `${
|
|
181
|
-
const srcApiDirectory = `${
|
|
182
|
-
const modernConfig = `${
|
|
183
|
-
const packageJsonPath = `${
|
|
190
|
+
function assertApiSurface(appPath) {
|
|
191
|
+
const apiEntry = `${appPath}/api/index.ts`;
|
|
192
|
+
const sharedApi = `${appPath}/shared/api.ts`;
|
|
193
|
+
const srcApiDirectory = `${appPath}/src/api`;
|
|
194
|
+
const modernConfig = `${appPath}/modern.config.ts`;
|
|
195
|
+
const packageJsonPath = `${appPath}/package.json`;
|
|
184
196
|
|
|
185
197
|
assert(exists(apiEntry), `${apiEntry} is required.`);
|
|
186
198
|
assert(exists(sharedApi), `${sharedApi} is required.`);
|
|
@@ -288,6 +300,16 @@ for (const verticalPath of listDirectories('verticals')) {
|
|
|
288
300
|
}
|
|
289
301
|
}
|
|
290
302
|
|
|
303
|
+
for (const appPath of listDirectories('apps')) {
|
|
304
|
+
if (exists(`${appPath}/api/index.ts`) || exists(`${appPath}/shared/api.ts`)) {
|
|
305
|
+
assertApiSurface(appPath);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
for (const verticalPath of verticalDirectories) {
|
|
310
|
+
assertApiSurface(verticalPath);
|
|
311
|
+
}
|
|
312
|
+
|
|
291
313
|
if (exists('apps/shell-super-app/package.json')) {
|
|
292
314
|
const shellPackageJson = JSON.parse(
|
|
293
315
|
readText('apps/shell-super-app/package.json'),
|
|
@@ -1349,6 +1349,22 @@ const extractAssetPrefixExpression = modernConfig => {
|
|
|
1349
1349
|
assert(match?.groups?.expression, 'modern.config.ts must assign assetPrefix');
|
|
1350
1350
|
return match.groups.expression;
|
|
1351
1351
|
};
|
|
1352
|
+
const assertBuildCacheBase = (appId, modernConfig) => {
|
|
1353
|
+
assert(
|
|
1354
|
+
modernConfig.includes("const buildCacheTarget = cloudflareDeployEnabled ? 'cloudflare' : 'web';") &&
|
|
1355
|
+
modernConfig.includes('const buildCacheDirectory = `node_modules/.cache/rspack-${appId}-${buildCacheTarget}`;') &&
|
|
1356
|
+
modernConfig.includes('cacheDirectory: buildCacheDirectory,'),
|
|
1357
|
+
`${appId} must provide a per-app/per-target Rspack cache base directory`,
|
|
1358
|
+
);
|
|
1359
|
+
};
|
|
1360
|
+
const assertCloudflareBuildSkipsDeployRebuild = (appId, packageJson) => {
|
|
1361
|
+
assert(
|
|
1362
|
+
packageJson.scripts?.['cloudflare:build']?.includes(
|
|
1363
|
+
'ULTRAMODERN_ZEPHYR=false MODERNJS_DEPLOY=cloudflare modern deploy --skip-build',
|
|
1364
|
+
),
|
|
1365
|
+
`${appId} cloudflare:build must deploy with --skip-build after the explicit Cloudflare build`,
|
|
1366
|
+
);
|
|
1367
|
+
};
|
|
1352
1368
|
const stripYamlInlineComment = value => {
|
|
1353
1369
|
let quote = undefined;
|
|
1354
1370
|
for (let index = 0; index < value.length; index += 1) {
|
|
@@ -1701,6 +1717,7 @@ assert(
|
|
|
1701
1717
|
assert(rootPackage.scripts?.['mf:types'] === 'node ./scripts/assert-mf-types.mts', 'Root must expose mf:types');
|
|
1702
1718
|
assert(rootPackage.scripts?.['cloudflare:deploy'] === expectedCloudflareDeployScript, 'Root must expose cloudflare:deploy');
|
|
1703
1719
|
assert(rootPackage.scripts?.['cloudflare:proof'] === 'node ./scripts/proof-cloudflare-version.mts --out .codex/reports/cloudflare-version-proof/public-url-proof.json', 'Root must expose cloudflare:proof');
|
|
1720
|
+
assert(rootPackage.scripts?.['migrate:strict-effect'] === 'node ./scripts/migrate-strict-effect.mts', 'Root must expose migrate:strict-effect');
|
|
1704
1721
|
assert(rootPackage.scripts?.['skills:install'] === 'node ./scripts/bootstrap-agent-skills.mts', 'Root must expose skills:install');
|
|
1705
1722
|
assert(rootPackage.scripts?.['skills:check'] === 'node ./scripts/bootstrap-agent-skills.mts --check', 'Root must expose skills:check');
|
|
1706
1723
|
assert(rootPackage.scripts?.postinstall === "oxfmt . '!repos/**' && node ./scripts/bootstrap-agent-skills.mts --postinstall", 'Root postinstall must format, run the default-on Codex skills bootstrap, and leave reference repository installs explicit');
|
|
@@ -1709,6 +1726,7 @@ const agentSkillsBootstrap = readText('scripts/bootstrap-agent-skills.mts');
|
|
|
1709
1726
|
assertToolWrapper('scripts/assert-mf-types.mts', 'mf-types');
|
|
1710
1727
|
assertToolWrapper('scripts/generate-public-surface-assets.mts', 'public-surface');
|
|
1711
1728
|
assertToolWrapper('scripts/proof-cloudflare-version.mts', 'cloudflare-proof');
|
|
1729
|
+
assertToolWrapper('scripts/migrate-strict-effect.mts', 'migrate-strict-effect');
|
|
1712
1730
|
assertToolWrapper('scripts/bootstrap-agent-skills.mts', 'skills');
|
|
1713
1731
|
assert(!agentSkillsBootstrap.includes("run('brew'") && !agentSkillsBootstrap.includes('runShell('), 'Agent skills bootstrap must never invoke system package managers');
|
|
1714
1732
|
const agentReferenceRepoSetup = readText('scripts/setup-agent-reference-repos.mts');
|
|
@@ -1769,6 +1787,9 @@ assert(shellPackage.dependencies?.['@modern-js/plugin-bff'] === expectedModernPa
|
|
|
1769
1787
|
assert(shellPackage.dependencies?.['@modern-js/plugin-i18n'] === expectedModernPackageSpecifier('@modern-js/plugin-i18n'), 'Shell plugin-i18n dependency must match package source metadata');
|
|
1770
1788
|
assert(shellPackage.dependencies?.['@modern-js/plugin-tanstack'] === expectedModernPackageSpecifier('@modern-js/plugin-tanstack'), 'Shell plugin-tanstack dependency must match package source metadata');
|
|
1771
1789
|
assert(shellPackage.dependencies?.['@modern-js/runtime'] === expectedModernPackageSpecifier('@modern-js/runtime'), 'Shell runtime dependency must match package source metadata');
|
|
1790
|
+
assert(shellPackage.scripts?.['cloudflare:deploy'] === 'ULTRAMODERN_CLOUDFLARE_REQUIRE_PUBLIC_URLS=true pnpm run cloudflare:build && wrangler deploy --config .output/wrangler.json', 'Shell must expose cloudflare:deploy');
|
|
1791
|
+
assertBuildCacheBase('shell-super-app', shellModernConfig);
|
|
1792
|
+
assertCloudflareBuildSkipsDeployRebuild('shell-super-app', shellPackage);
|
|
1772
1793
|
const shellContract = generatedContract.apps?.find(app => app.id === 'shell-super-app');
|
|
1773
1794
|
assert(shellContract?.deploy?.cloudflare?.workerName === expectedWorkerName('shell-super-app'), 'Shell Cloudflare workerName is incorrect');
|
|
1774
1795
|
assert(shellContract?.deploy?.cloudflare?.publicUrlEnv === 'ULTRAMODERN_PUBLIC_URL_SHELL_SUPER_APP', 'Shell Cloudflare public URL env is incorrect');
|
|
@@ -1845,6 +1866,8 @@ for (const vertical of fullStackVerticals) {
|
|
|
1845
1866
|
assert(routeMetadata.includes("authoring: 'colocated-route-meta'"), `${vertical.id} route metadata manifest must advertise colocated authoring`);
|
|
1846
1867
|
assert(packageJson.name === vertical.packageName, `${vertical.id} package name is incorrect`);
|
|
1847
1868
|
assert(packageJson.scripts?.['cloudflare:deploy'] === 'ULTRAMODERN_CLOUDFLARE_REQUIRE_PUBLIC_URLS=true pnpm run cloudflare:build && wrangler deploy --config .output/wrangler.json', `${vertical.id} must expose cloudflare:deploy`);
|
|
1869
|
+
assertBuildCacheBase(vertical.id, modernConfig);
|
|
1870
|
+
assertCloudflareBuildSkipsDeployRebuild(vertical.id, packageJson);
|
|
1848
1871
|
assert(packageJson.scripts?.['cloudflare:proof']?.includes(`--app ${vertical.id}`), `${vertical.id} must expose cloudflare:proof`);
|
|
1849
1872
|
assert(packageJson.devDependencies?.['@modern-js/app-tools'] === expectedModernPackageSpecifier('@modern-js/app-tools'), `${vertical.id} app-tools dependency must match package source metadata`);
|
|
1850
1873
|
assert(packageJson.dependencies?.['@modern-js/plugin-bff'] === expectedModernPackageSpecifier('@modern-js/plugin-bff'), `${vertical.id} plugin-bff dependency must match package source metadata`);
|