@bleedingdev/modern-js-create 3.5.0-ultramodern.3 → 3.5.0-ultramodern.30
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 +21 -17
- package/dist/cjs/ultramodern-tooling/commands.cjs +772 -75
- package/dist/cjs/ultramodern-tooling/config.cjs +149 -8
- package/dist/cjs/ultramodern-workspace/add-vertical.cjs +25 -0
- package/dist/cjs/ultramodern-workspace/api.cjs +44 -0
- package/dist/cjs/ultramodern-workspace/app-files.cjs +8 -11
- package/dist/cjs/ultramodern-workspace/backend-federation.cjs +282 -0
- package/dist/cjs/ultramodern-workspace/contracts.cjs +24 -8
- package/dist/cjs/ultramodern-workspace/delivery-unit-sync.cjs +157 -0
- package/dist/cjs/ultramodern-workspace/delivery-unit.cjs +88 -0
- package/dist/cjs/ultramodern-workspace/descriptors.cjs +24 -0
- package/dist/cjs/ultramodern-workspace/module-federation.cjs +161 -50
- package/dist/cjs/ultramodern-workspace/package-json.cjs +26 -43
- package/dist/cjs/ultramodern-workspace/pnpm-workspace-policy-plan.cjs +166 -0
- package/dist/cjs/ultramodern-workspace/tooling-command-catalog.cjs +153 -0
- package/dist/cjs/ultramodern-workspace/versions.cjs +8 -3
- package/dist/cjs/ultramodern-workspace/workspace-script-plan.cjs +175 -0
- package/dist/cjs/ultramodern-workspace/workspace-scripts.cjs +104 -63
- package/dist/cjs/ultramodern-workspace/workspace-validation-contract.cjs +97 -0
- package/dist/cjs/ultramodern-workspace/write-workspace.cjs +11 -3
- package/dist/cjs/ultramodern-workspace/zerops.cjs +100 -0
- package/dist/esm/ultramodern-tooling/commands.js +775 -78
- package/dist/esm/ultramodern-tooling/config.js +144 -9
- package/dist/esm/ultramodern-workspace/add-vertical.js +26 -1
- package/dist/esm/ultramodern-workspace/api.js +43 -2
- package/dist/esm/ultramodern-workspace/app-files.js +8 -11
- package/dist/esm/ultramodern-workspace/backend-federation.js +217 -0
- package/dist/esm/ultramodern-workspace/contracts.js +24 -8
- package/dist/esm/ultramodern-workspace/delivery-unit-sync.js +108 -0
- package/dist/esm/ultramodern-workspace/delivery-unit.js +31 -0
- package/dist/esm/ultramodern-workspace/descriptors.js +13 -1
- package/dist/esm/ultramodern-workspace/module-federation.js +160 -42
- package/dist/esm/ultramodern-workspace/package-json.js +16 -40
- package/dist/esm/ultramodern-workspace/pnpm-workspace-policy-plan.js +113 -0
- package/dist/esm/ultramodern-workspace/tooling-command-catalog.js +100 -0
- package/dist/esm/ultramodern-workspace/versions.js +6 -4
- package/dist/esm/ultramodern-workspace/workspace-script-plan.js +110 -0
- package/dist/esm/ultramodern-workspace/workspace-scripts.js +88 -65
- package/dist/esm/ultramodern-workspace/workspace-validation-contract.js +59 -0
- package/dist/esm/ultramodern-workspace/write-workspace.js +14 -6
- package/dist/esm/ultramodern-workspace/zerops.js +62 -0
- package/dist/esm-node/ultramodern-tooling/commands.js +775 -78
- package/dist/esm-node/ultramodern-tooling/config.js +144 -9
- package/dist/esm-node/ultramodern-workspace/add-vertical.js +26 -1
- package/dist/esm-node/ultramodern-workspace/api.js +43 -2
- package/dist/esm-node/ultramodern-workspace/app-files.js +8 -11
- package/dist/esm-node/ultramodern-workspace/backend-federation.js +218 -0
- package/dist/esm-node/ultramodern-workspace/contracts.js +24 -8
- package/dist/esm-node/ultramodern-workspace/delivery-unit-sync.js +109 -0
- package/dist/esm-node/ultramodern-workspace/delivery-unit.js +32 -0
- package/dist/esm-node/ultramodern-workspace/descriptors.js +13 -1
- package/dist/esm-node/ultramodern-workspace/module-federation.js +160 -42
- package/dist/esm-node/ultramodern-workspace/package-json.js +16 -40
- package/dist/esm-node/ultramodern-workspace/pnpm-workspace-policy-plan.js +114 -0
- package/dist/esm-node/ultramodern-workspace/tooling-command-catalog.js +101 -0
- package/dist/esm-node/ultramodern-workspace/versions.js +6 -4
- package/dist/esm-node/ultramodern-workspace/workspace-script-plan.js +111 -0
- package/dist/esm-node/ultramodern-workspace/workspace-scripts.js +88 -65
- package/dist/esm-node/ultramodern-workspace/workspace-validation-contract.js +60 -0
- package/dist/esm-node/ultramodern-workspace/write-workspace.js +14 -6
- package/dist/esm-node/ultramodern-workspace/zerops.js +63 -0
- package/dist/types/ultramodern-tooling/config.d.ts +6 -0
- package/dist/types/ultramodern-workspace/api.d.ts +1 -0
- package/dist/types/ultramodern-workspace/backend-federation.d.ts +11 -0
- package/dist/types/ultramodern-workspace/contracts.d.ts +1 -1
- package/dist/types/ultramodern-workspace/delivery-unit-sync.d.ts +6 -0
- package/dist/types/ultramodern-workspace/delivery-unit.d.ts +27 -0
- package/dist/types/ultramodern-workspace/descriptors.d.ts +4 -0
- package/dist/types/ultramodern-workspace/module-federation.d.ts +4 -9
- package/dist/types/ultramodern-workspace/package-json.d.ts +0 -1
- package/dist/types/ultramodern-workspace/pnpm-workspace-policy-plan.d.ts +39 -0
- package/dist/types/ultramodern-workspace/tooling-command-catalog.d.ts +18 -0
- package/dist/types/ultramodern-workspace/versions.d.ts +5 -3
- package/dist/types/ultramodern-workspace/workspace-script-plan.d.ts +72 -0
- package/dist/types/ultramodern-workspace/workspace-scripts.d.ts +13 -0
- package/dist/types/ultramodern-workspace/workspace-validation-contract.d.ts +42 -0
- package/dist/types/ultramodern-workspace/zerops.d.ts +2 -0
- package/package.json +3 -3
- package/template-workspace/.gitignore.handlebars +4 -0
- package/template-workspace/README.md.handlebars +18 -15
- package/template-workspace/patches/@module-federation__bridge-react@2.6.0.patch +140 -0
- package/template-workspace/patches/@module-federation__modern-js-v3@2.6.0.patch +57 -0
- 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 +8 -0
- package/template-workspace/scripts/bootstrap-agent-skills.mjs +11 -3
- package/templates/workspace-scripts/check-ultramodern-api-boundaries.mts +40 -2
- package/templates/workspace-scripts/generate-node-backend-federation.mjs +270 -0
- package/templates/workspace-scripts/materialize-zerops-runtime.mjs +448 -0
- package/templates/workspace-scripts/proof-cloudflare-version.mjs +237 -9
- package/templates/workspace-scripts/proof-node-backend-federation.mjs +729 -0
- package/templates/workspace-scripts/ultramodern-cloudflare-proof.mjs +188 -2
- package/templates/workspace-scripts/validate-ultramodern-workspace.mjs.handlebars +434 -18
|
@@ -3,6 +3,9 @@ import node_path from "node:path";
|
|
|
3
3
|
import { normalizeUltramodernBridgeConfig } from "../ultramodern-workspace/bridge-config.js";
|
|
4
4
|
import { ULTRAMODERN_CONFIG_PATH, createNeutralOwnership, shellApp } from "../ultramodern-workspace/descriptors.js";
|
|
5
5
|
import { toKebabCase } from "../ultramodern-workspace/naming.js";
|
|
6
|
+
const LEGACY_GENERATED_CONTRACT_PATH = '.modernjs/ultramodern-generated-contract.json';
|
|
7
|
+
const LEGACY_PACKAGE_SOURCE_METADATA_PATH = '.modernjs/ultramodern-package-source.json';
|
|
8
|
+
const LEGACY_DEVELOPMENT_OVERLAY_PATH = 'topology/local-overlays/development.json';
|
|
6
9
|
function readJsonObject(filePath) {
|
|
7
10
|
const value = JSON.parse(node_fs.readFileSync(filePath, 'utf-8'));
|
|
8
11
|
if (null === value || 'object' != typeof value || Array.isArray(value)) throw new Error(`UltraModern config must contain a JSON object: ${filePath}`);
|
|
@@ -11,11 +14,39 @@ function readJsonObject(filePath) {
|
|
|
11
14
|
function readOptionalJsonObject(filePath) {
|
|
12
15
|
return node_fs.existsSync(filePath) ? readJsonObject(filePath) : {};
|
|
13
16
|
}
|
|
14
|
-
function packageScopeFromRoot(
|
|
15
|
-
const rootPackage = readOptionalJsonObject(node_path.join(
|
|
16
|
-
return 'string' == typeof rootPackage.name && rootPackage.name.length > 0 ? rootPackage.name : node_path.basename(
|
|
17
|
+
function packageScopeFromRoot(workspaceRoot) {
|
|
18
|
+
const rootPackage = readOptionalJsonObject(node_path.join(workspaceRoot, 'package.json'));
|
|
19
|
+
return 'string' == typeof rootPackage.name && rootPackage.name.length > 0 ? rootPackage.name : node_path.basename(workspaceRoot);
|
|
17
20
|
}
|
|
18
|
-
function
|
|
21
|
+
function packageSourceFromMetadata(workspaceRoot) {
|
|
22
|
+
const metadataPath = node_path.join(workspaceRoot, LEGACY_PACKAGE_SOURCE_METADATA_PATH);
|
|
23
|
+
if (!node_fs.existsSync(metadataPath)) return;
|
|
24
|
+
const metadata = readJsonObject(metadataPath);
|
|
25
|
+
const aliases = metadata.modernPackages?.aliases ?? {};
|
|
26
|
+
const firstAliasEntry = Object.entries(aliases).find((entry)=>'string' == typeof entry[1]);
|
|
27
|
+
const firstPackage = firstAliasEntry?.[0];
|
|
28
|
+
const firstAlias = firstAliasEntry?.[1];
|
|
29
|
+
const aliasScope = firstAlias?.match(/^@([^/]+)\//u)?.[1];
|
|
30
|
+
const unscopedName = firstPackage?.split('/').at(-1) ?? '';
|
|
31
|
+
const aliasUnscopedName = firstAlias?.split('/').at(-1) ?? '';
|
|
32
|
+
const aliasPackageNamePrefix = aliasUnscopedName && unscopedName && aliasUnscopedName.endsWith(unscopedName) ? aliasUnscopedName.slice(0, -unscopedName.length) : void 0;
|
|
33
|
+
return {
|
|
34
|
+
strategy: 'install' === metadata.strategy ? 'install' : 'workspace',
|
|
35
|
+
modernPackageVersion: 'string' == typeof metadata.modernPackages?.specifier ? metadata.modernPackages.specifier : 'workspace:*',
|
|
36
|
+
registry: 'string' == typeof metadata.modernPackages?.registry ? metadata.modernPackages.registry : void 0,
|
|
37
|
+
aliasScope,
|
|
38
|
+
aliasPackageNamePrefix
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function readOverlayPorts(workspaceRoot) {
|
|
42
|
+
const overlayPath = node_path.join(workspaceRoot, LEGACY_DEVELOPMENT_OVERLAY_PATH);
|
|
43
|
+
if (!node_fs.existsSync(overlayPath)) return {};
|
|
44
|
+
const overlay = readJsonObject(overlayPath);
|
|
45
|
+
const ports = overlay.ports;
|
|
46
|
+
if (null === ports || 'object' != typeof ports || Array.isArray(ports)) return {};
|
|
47
|
+
return Object.fromEntries(Object.entries(ports).filter((entry)=>'number' == typeof entry[1]));
|
|
48
|
+
}
|
|
49
|
+
function normalizeCompactConfig(workspaceRoot, sourcePath, config) {
|
|
19
50
|
const packageSource = config.packageSource && 'object' == typeof config.packageSource ? {
|
|
20
51
|
strategy: 'install' === config.packageSource.strategy ? 'install' : 'workspace',
|
|
21
52
|
modernPackageVersion: 'string' == typeof config.packageSource.modernPackageVersion ? config.packageSource.modernPackageVersion : 'workspace:*',
|
|
@@ -68,10 +99,114 @@ function normalizeCompactConfig(sourcePath, config) {
|
|
|
68
99
|
}
|
|
69
100
|
};
|
|
70
101
|
}
|
|
71
|
-
function
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
102
|
+
function normalizeCompactUltramodernConfig(workspaceRoot, compact) {
|
|
103
|
+
return normalizeCompactConfig(workspaceRoot, node_path.join(workspaceRoot, ULTRAMODERN_CONFIG_PATH), compact);
|
|
104
|
+
}
|
|
105
|
+
function synthesizeCompactUltramodernConfig(workspaceRoot) {
|
|
106
|
+
const contractPath = node_path.join(workspaceRoot, LEGACY_GENERATED_CONTRACT_PATH);
|
|
107
|
+
if (!node_fs.existsSync(contractPath)) return;
|
|
108
|
+
const contract = readJsonObject(contractPath);
|
|
109
|
+
const sources = [
|
|
110
|
+
LEGACY_GENERATED_CONTRACT_PATH
|
|
111
|
+
];
|
|
112
|
+
const missing = [];
|
|
113
|
+
const packageSource = packageSourceFromMetadata(workspaceRoot);
|
|
114
|
+
if (packageSource) sources.push(LEGACY_PACKAGE_SOURCE_METADATA_PATH);
|
|
115
|
+
else missing.push(LEGACY_PACKAGE_SOURCE_METADATA_PATH);
|
|
116
|
+
const ports = readOverlayPorts(workspaceRoot);
|
|
117
|
+
if (node_fs.existsSync(node_path.join(workspaceRoot, LEGACY_DEVELOPMENT_OVERLAY_PATH))) sources.push(LEGACY_DEVELOPMENT_OVERLAY_PATH);
|
|
118
|
+
else missing.push(LEGACY_DEVELOPMENT_OVERLAY_PATH);
|
|
119
|
+
const apps = Array.isArray(contract.apps) ? contract.apps : [];
|
|
120
|
+
const shell = apps.find((app)=>app?.id === shellApp.id);
|
|
121
|
+
const compact = {
|
|
122
|
+
schemaVersion: 'number' == typeof contract.schemaVersion ? contract.schemaVersion : 1,
|
|
123
|
+
...'string' == typeof contract.profile ? {
|
|
124
|
+
profile: contract.profile
|
|
125
|
+
} : {},
|
|
126
|
+
workspace: {
|
|
127
|
+
packageScope: packageScopeFromRoot(workspaceRoot)
|
|
128
|
+
},
|
|
129
|
+
...packageSource ? {
|
|
130
|
+
packageSource: {
|
|
131
|
+
strategy: packageSource.strategy,
|
|
132
|
+
modernPackageVersion: packageSource.modernPackageVersion,
|
|
133
|
+
...packageSource.registry ? {
|
|
134
|
+
registry: packageSource.registry
|
|
135
|
+
} : {},
|
|
136
|
+
...packageSource.aliasScope ? {
|
|
137
|
+
aliasScope: packageSource.aliasScope
|
|
138
|
+
} : {},
|
|
139
|
+
...packageSource.aliasPackageNamePrefix ? {
|
|
140
|
+
aliasPackageNamePrefix: packageSource.aliasPackageNamePrefix
|
|
141
|
+
} : {}
|
|
142
|
+
}
|
|
143
|
+
} : {},
|
|
144
|
+
features: {
|
|
145
|
+
tailwind: shell?.styling?.tailwind !== false
|
|
146
|
+
},
|
|
147
|
+
topology: {
|
|
148
|
+
apps: apps.map((app)=>{
|
|
149
|
+
const id = String(app.id);
|
|
150
|
+
const appPath = 'string' == typeof app.path ? app.path : id === shellApp.id ? shellApp.directory : `verticals/${toKebabCase(id)}`;
|
|
151
|
+
const domain = 'string' == typeof app.i18n?.namespace && 'shell' !== app.i18n.namespace ? app.i18n.namespace : appPath.split('/').at(-1);
|
|
152
|
+
const moduleFederation = app.moduleFederation && 'object' == typeof app.moduleFederation ? {
|
|
153
|
+
role: 'vertical' === app.kind ? 'remote' : 'host',
|
|
154
|
+
...'string' == typeof app.moduleFederation.name ? {
|
|
155
|
+
name: app.moduleFederation.name
|
|
156
|
+
} : {},
|
|
157
|
+
...Array.isArray(app.moduleFederation.exposes) ? {
|
|
158
|
+
exposes: app.moduleFederation.exposes.filter((expose)=>'string' == typeof expose)
|
|
159
|
+
} : {},
|
|
160
|
+
...Array.isArray(app.moduleFederation.verticalRefs) ? {
|
|
161
|
+
verticalRefs: app.moduleFederation.verticalRefs.filter((ref)=>'string' == typeof ref)
|
|
162
|
+
} : {}
|
|
163
|
+
} : void 0;
|
|
164
|
+
const api = app.effect && 'object' == typeof app.effect ? {
|
|
165
|
+
stem: 'string' == typeof app.effect.prefix ? app.effect.prefix.split('/').filter(Boolean).at(-1) ?? domain ?? id : domain ?? id,
|
|
166
|
+
prefix: 'string' == typeof app.effect.prefix ? app.effect.prefix : `/${domain ?? id}-api`,
|
|
167
|
+
consumedBy: [
|
|
168
|
+
shellApp.id,
|
|
169
|
+
id
|
|
170
|
+
]
|
|
171
|
+
} : void 0;
|
|
172
|
+
return {
|
|
173
|
+
id,
|
|
174
|
+
kind: 'vertical' === app.kind ? 'vertical' : 'shell',
|
|
175
|
+
path: appPath,
|
|
176
|
+
...'string' == typeof app.package ? {
|
|
177
|
+
package: app.package
|
|
178
|
+
} : {},
|
|
179
|
+
packageSuffix: 'string' == typeof app.package ? app.package.split('/').at(-1) : appPath.split('/').at(-1),
|
|
180
|
+
...id === shellApp.id ? {
|
|
181
|
+
displayName: shellApp.displayName
|
|
182
|
+
} : {},
|
|
183
|
+
...domain ? {
|
|
184
|
+
domain
|
|
185
|
+
} : {},
|
|
186
|
+
...'number' == typeof ports[id] ? {
|
|
187
|
+
port: ports[id]
|
|
188
|
+
} : {},
|
|
189
|
+
...moduleFederation ? {
|
|
190
|
+
moduleFederation
|
|
191
|
+
} : {},
|
|
192
|
+
...api ? {
|
|
193
|
+
api
|
|
194
|
+
} : {}
|
|
195
|
+
};
|
|
196
|
+
})
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
return {
|
|
200
|
+
compact,
|
|
201
|
+
missing,
|
|
202
|
+
sources
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
function readUltramodernConfig(workspaceRoot = process.cwd()) {
|
|
206
|
+
const compactPath = node_path.join(workspaceRoot, ULTRAMODERN_CONFIG_PATH);
|
|
207
|
+
if (node_fs.existsSync(compactPath)) return normalizeCompactConfig(workspaceRoot, compactPath, readJsonObject(compactPath));
|
|
208
|
+
if (node_fs.existsSync(node_path.join(workspaceRoot, LEGACY_GENERATED_CONTRACT_PATH))) throw new Error(`Missing ${ULTRAMODERN_CONFIG_PATH}. Legacy UltraModern metadata detected — run \`modern-js-create ultramodern migrate-strict-effect\` to synthesize it.`);
|
|
209
|
+
throw new Error(`Missing UltraModern config. Expected ${ULTRAMODERN_CONFIG_PATH}. Run \`modern-js-create ultramodern migrate-strict-effect\` if you have legacy UltraModern metadata to migrate.`);
|
|
75
210
|
}
|
|
76
211
|
function workspaceAppsFromToolingConfig(config) {
|
|
77
212
|
return config.topology.apps.map((app)=>{
|
|
@@ -117,4 +252,4 @@ function workspaceAppsFromToolingConfig(config) {
|
|
|
117
252
|
};
|
|
118
253
|
});
|
|
119
254
|
}
|
|
120
|
-
export { readUltramodernConfig, workspaceAppsFromToolingConfig };
|
|
255
|
+
export { normalizeCompactUltramodernConfig, readUltramodernConfig, synthesizeCompactUltramodernConfig, workspaceAppsFromToolingConfig };
|
|
@@ -5,12 +5,14 @@ import { WORKSPACE_PACKAGE_VERSION } from "../ultramodern-package-source.js";
|
|
|
5
5
|
import { readUltramodernConfig } from "../ultramodern-tooling/config.js";
|
|
6
6
|
import { apiTopologyMetadata, createShellApiClient } from "./api.js";
|
|
7
7
|
import { createAppEnvDts, createAppRuntimeConfig, createShellFrameComponent } from "./app-files.js";
|
|
8
|
+
import { createBackendFederationContract, createServerExecutionOverlay } from "./backend-federation.js";
|
|
9
|
+
import { createDeliveryUnitRecord, deliveryUnitContractBlock } from "./delivery-unit.js";
|
|
8
10
|
import { createShellPage, createShellRemoteComponents } from "./demo-components.js";
|
|
9
11
|
import { ULTRAMODERN_CONFIG_PATH, appHasApi, appI18nNamespace, createModuleFederationRemoteContracts, createNeutralOwnership, createRemoteManifestEnv, createShellHost, createVerticalDescriptor, remoteDependencyAlias, resolveApiPrefix, shellApp, zephyrRemoteDependency } from "./descriptors.js";
|
|
10
12
|
import { formatGeneratedWorkspaceFiles, readJsonFile, writeFileReplacing, writeJsonFile } from "./fs-io.js";
|
|
11
13
|
import { createFileSnapshot, createGenerationResult, diffFileSnapshots } from "./generation-result.js";
|
|
12
14
|
import { createAppPublicLocaleMessages } from "./locales.js";
|
|
13
|
-
import { createShellModuleFederationConfig } from "./module-federation.js";
|
|
15
|
+
import { createAppModernConfig, createShellModuleFederationConfig } from "./module-federation.js";
|
|
14
16
|
import { assertUniqueTailwindPrefixes, normalizePath, packageName, toEnvSegment, toKebabCase, toPackageScope, toPascalCase } from "./naming.js";
|
|
15
17
|
import { runCodeSmithOverlays } from "./overlays.js";
|
|
16
18
|
import { createAppMfTypesTsConfig, createAppPackage, createAppTsConfig, createRootPackageJson, createRootTsConfig } from "./package-json.js";
|
|
@@ -20,6 +22,7 @@ import { createPublicWebAppArtifacts, rewriteWorkspaceAssetsForApp } from "./pub
|
|
|
20
22
|
import { isRecord } from "./types.js";
|
|
21
23
|
import { writeGeneratedWorkspaceScripts } from "./workspace-scripts.js";
|
|
22
24
|
import { createCompactUltramodernConfig, writeApp } from "./write-workspace.js";
|
|
25
|
+
import { createZeropsYaml } from "./zerops.js";
|
|
23
26
|
const FIRST_VERTICAL_PORT = 4101;
|
|
24
27
|
const TOPOLOGY_PATH = 'topology/reference-topology.json';
|
|
25
28
|
const OWNERSHIP_PATH = 'topology/ownership.json';
|
|
@@ -73,6 +76,7 @@ function rewriteShellAppFiles(workspaceRoot, scope, packageSource, enableTailwin
|
|
|
73
76
|
writeJsonFile(node_path.join(workspaceRoot, `${shellApp.directory}/tsconfig.json`), createAppTsConfig(shellHost, remotes));
|
|
74
77
|
writeJsonFile(node_path.join(workspaceRoot, `${shellApp.directory}/tsconfig.mf-types.json`), createAppMfTypesTsConfig(shellHost));
|
|
75
78
|
writeFileReplacing(workspaceRoot, `${shellApp.directory}/src/modern-app-env.d.ts`, createAppEnvDts(shellHost, remotes));
|
|
79
|
+
writeFileReplacing(workspaceRoot, `${shellApp.directory}/modern.config.ts`, createAppModernConfig(scope, shellHost, remotes));
|
|
76
80
|
writeFileReplacing(workspaceRoot, publicWeb.jsonLdHelperFile.path, publicWeb.jsonLdHelperFile.content);
|
|
77
81
|
writeFileReplacing(workspaceRoot, publicWeb.routeMetadataFile.path, publicWeb.routeMetadataFile.content);
|
|
78
82
|
writeFileReplacing(workspaceRoot, publicWeb.routeHeadFile.path, publicWeb.routeHeadFile.content);
|
|
@@ -124,6 +128,12 @@ function verticalTopologyEntry(scope, vertical, remotes = []) {
|
|
|
124
128
|
fallbackTelemetryEvent: 'modernjs:mv-runtime-parity',
|
|
125
129
|
sharedContractVersion: 'mf-ssr-contract-v1'
|
|
126
130
|
},
|
|
131
|
+
...createBackendFederationContract(scope, vertical) ? {
|
|
132
|
+
backendFederation: createBackendFederationContract(scope, vertical)
|
|
133
|
+
} : {},
|
|
134
|
+
...vertical.api ? {
|
|
135
|
+
deliveryUnit: deliveryUnitContractBlock(createDeliveryUnitRecord(scope, vertical))
|
|
136
|
+
} : {},
|
|
127
137
|
...apiTopologyMetadata(vertical) ? {
|
|
128
138
|
api: apiTopologyMetadata(vertical)
|
|
129
139
|
} : {},
|
|
@@ -364,6 +374,12 @@ function createDryRunJsonMutations(preflight, manifestUrl) {
|
|
|
364
374
|
pointer: `/apis/${vertical.id}`,
|
|
365
375
|
description: `Add local API URL for ${vertical.id}`,
|
|
366
376
|
value: `http://localhost:${vertical.port}${resolveApiPrefix(vertical)}`
|
|
377
|
+
},
|
|
378
|
+
{
|
|
379
|
+
path: DEVELOPMENT_OVERLAY_PATH,
|
|
380
|
+
pointer: `/serverExecution/${vertical.id}`,
|
|
381
|
+
description: `Add local MicroVertical server execution metadata for ${vertical.id}`,
|
|
382
|
+
value: createServerExecutionOverlay(scope, vertical)
|
|
367
383
|
}
|
|
368
384
|
] : [];
|
|
369
385
|
return [
|
|
@@ -479,6 +495,8 @@ function addUltramodernVertical(options) {
|
|
|
479
495
|
overlay.ports[vertical.id] = vertical.port;
|
|
480
496
|
overlay.manifests ??= {};
|
|
481
497
|
overlay.manifests[vertical.id] = `http://localhost:${vertical.port}/mf-manifest.json`;
|
|
498
|
+
overlay.serverExecution ??= {};
|
|
499
|
+
overlay.serverExecution[vertical.id] = createServerExecutionOverlay(scope, vertical);
|
|
482
500
|
overlay.apis ??= {};
|
|
483
501
|
overlay.apis[vertical.id] = `http://localhost:${vertical.port}${resolveApiPrefix(vertical)}`;
|
|
484
502
|
writeJsonFile(topologyPath, topology);
|
|
@@ -491,6 +509,13 @@ function addUltramodernVertical(options) {
|
|
|
491
509
|
},
|
|
492
510
|
...updatedVerticals
|
|
493
511
|
], enableTailwind, bridge));
|
|
512
|
+
writeFileReplacing(options.workspaceRoot, 'zerops.yaml', `${createZeropsYaml(scope, [
|
|
513
|
+
{
|
|
514
|
+
...shellApp,
|
|
515
|
+
verticalRefs: updatedVerticals.map((vertical)=>vertical.id)
|
|
516
|
+
},
|
|
517
|
+
...updatedVerticals
|
|
518
|
+
])}\n`);
|
|
494
519
|
rewriteShellAppFiles(options.workspaceRoot, scope, packageSource, enableTailwind, updatedVerticals, bridge);
|
|
495
520
|
writeGeneratedWorkspaceScripts(options.workspaceRoot, scope, enableTailwind, updatedVerticals);
|
|
496
521
|
addShellZephyrDependency(options.workspaceRoot, scope, vertical);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BACKEND_FEDERATION_CONTRACT_VERSION, BACKEND_FEDERATION_NODE_ADAPTER_VERSION } from "./backend-federation.js";
|
|
2
|
+
import { appHasApi, createBackendFederationName, resolveApiPrefix, resolveApiStem, verticalApiApps } from "./descriptors.js";
|
|
2
3
|
import { packageName, toCamelCase, toPascalCase } from "./naming.js";
|
|
3
4
|
function verticalApiExport(service) {
|
|
4
5
|
return `${toCamelCase(resolveApiStem(service))}Api`;
|
|
@@ -639,6 +640,46 @@ const apiRuntime: EffectBffDefinition<typeof ${apiExport}, EffectRuntimeLayer> &
|
|
|
639
640
|
layer,
|
|
640
641
|
});
|
|
641
642
|
|
|
643
|
+
export default apiRuntime;
|
|
644
|
+
`;
|
|
645
|
+
}
|
|
646
|
+
function createBackendEffectApiExpose(scope, service) {
|
|
647
|
+
const apiExport = verticalApiExport(service);
|
|
648
|
+
const groupName = verticalApiGroupName(service);
|
|
649
|
+
const apiPrefix = resolveApiPrefix(service);
|
|
650
|
+
const stem = resolveApiStem(service);
|
|
651
|
+
return `import apiRuntime from './index.ts';
|
|
652
|
+
import { ultramodernApiMarker } from '../shared/ultramodern-build.ts';
|
|
653
|
+
import {
|
|
654
|
+
${apiExport},
|
|
655
|
+
${groupName}ApiContract,
|
|
656
|
+
${groupName}OperationContexts,
|
|
657
|
+
} from '../shared/api.ts';
|
|
658
|
+
|
|
659
|
+
export const backendFederationContract = {
|
|
660
|
+
compatibility: {
|
|
661
|
+
build: ultramodernApiMarker.build,
|
|
662
|
+
contractVersion: '${BACKEND_FEDERATION_CONTRACT_VERSION}',
|
|
663
|
+
nodeAdapterVersion: '${BACKEND_FEDERATION_NODE_ADAPTER_VERSION}',
|
|
664
|
+
packageName: '${packageName(scope, service.packageSuffix)}',
|
|
665
|
+
sourceRevision: ultramodernApiMarker.sourceRevision,
|
|
666
|
+
unitId: ultramodernApiMarker.unitId,
|
|
667
|
+
},
|
|
668
|
+
executionSurfaces: ['node-mf-runtime'],
|
|
669
|
+
exposes: ['./effect-api'],
|
|
670
|
+
name: '${createBackendFederationName(service)}',
|
|
671
|
+
openapiPath: '${apiPrefix}/openapi.json',
|
|
672
|
+
readinessPath: '${apiPrefix}/${stem}/readiness',
|
|
673
|
+
role: 'microvertical-server',
|
|
674
|
+
runtimeFramework: 'effect',
|
|
675
|
+
strictEffectApproach: true,
|
|
676
|
+
} as const;
|
|
677
|
+
|
|
678
|
+
export const api: unknown = ${apiExport};
|
|
679
|
+
export const contract = ${groupName}ApiContract;
|
|
680
|
+
export const operationContexts = ${groupName}OperationContexts;
|
|
681
|
+
export const runtime = apiRuntime;
|
|
682
|
+
|
|
642
683
|
export default apiRuntime;
|
|
643
684
|
`;
|
|
644
685
|
}
|
|
@@ -981,4 +1022,4 @@ function createApiOperationContract(target) {
|
|
|
981
1022
|
}
|
|
982
1023
|
};
|
|
983
1024
|
}
|
|
984
|
-
export { apiTopologyMetadata, createApiClient, createApiDomainOperations, createApiOperationContract, createApiReadinessContract, createApiRequestContextContract, createApiServiceEntry, createSharedApi, createSharedApiContract, createSharedApiImports, createShellApiClient, verticalApiCreatePayloadSchemaExport, verticalApiErrorStem, verticalApiExport, verticalApiGroupName, verticalApiMarkerSchemaExport, verticalApiName, verticalApiNotFoundErrorExport, verticalApiNotFoundSchemaExport, verticalApiReadinessSchemaExport, verticalApiSchemaExport };
|
|
1025
|
+
export { apiTopologyMetadata, createApiClient, createApiDomainOperations, createApiOperationContract, createApiReadinessContract, createApiRequestContextContract, createApiServiceEntry, createBackendEffectApiExpose, createSharedApi, createSharedApiContract, createSharedApiImports, createShellApiClient, verticalApiCreatePayloadSchemaExport, verticalApiErrorStem, verticalApiExport, verticalApiGroupName, verticalApiMarkerSchemaExport, verticalApiName, verticalApiNotFoundErrorExport, verticalApiNotFoundSchemaExport, verticalApiReadinessSchemaExport, verticalApiSchemaExport };
|
|
@@ -27,17 +27,14 @@ function createAppEnvDts(app, remotes = []) {
|
|
|
27
27
|
}
|
|
28
28
|
`;
|
|
29
29
|
})).join('\n');
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
declare module '*.css';
|
|
40
|
-
${remoteModuleDeclarations ? `\n${remoteModuleDeclarations}` : ''}`;
|
|
30
|
+
const reactTypeImport = remoteModuleDeclarations ? "import type React from 'react';\n" : '';
|
|
31
|
+
return [
|
|
32
|
+
`import '@modern-js/app-tools/types';\n${reactTypeImport}`.trimEnd(),
|
|
33
|
+
`declare global {
|
|
34
|
+
const ULTRAMODERN_SITE_URL: string;
|
|
35
|
+
}`,
|
|
36
|
+
remoteModuleDeclarations.trimEnd()
|
|
37
|
+
].filter((section)=>section.length > 0).join('\n\n').concat('\n');
|
|
41
38
|
}
|
|
42
39
|
function createAppRuntimeConfig(app, scope, remotes = []) {
|
|
43
40
|
const pluginsConfig = 'shell' === app.kind ? ` plugins: [
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { verticalApiExport, verticalApiGroupName } from "./api.js";
|
|
2
|
+
import { createDeliveryUnitRecord, deliveryUnitContractBlock } from "./delivery-unit.js";
|
|
3
|
+
import { appHasApi, createBackendFederationContainerEntry, createBackendFederationManifestEnv, createBackendFederationManifestUrl, createBackendFederationName, createCloudflarePublicUrlEnv, createCloudflareWorkerName, createRemoteManifestEnv, resolveApiPrefix, resolveApiStem } from "./descriptors.js";
|
|
4
|
+
import { packageName, toEnvSegment } from "./naming.js";
|
|
5
|
+
import { EFFECT_VERSION, MODULE_FEDERATION_VERSION } from "./versions.js";
|
|
6
|
+
const BACKEND_FEDERATION_CONTRACT_VERSION = 'microvertical-server-effect-v1';
|
|
7
|
+
const BACKEND_FEDERATION_NODE_ADAPTER_VERSION = 'backend-mf-effect-v1';
|
|
8
|
+
function createZephyrEnv(app, suffix) {
|
|
9
|
+
return `ZEPHYR_${toEnvSegment(app.domain ?? app.id)}_${suffix}`;
|
|
10
|
+
}
|
|
11
|
+
function createWorkerBindingName(app) {
|
|
12
|
+
return `VERTICAL_${toEnvSegment(app.domain ?? app.id)}_WORKER`;
|
|
13
|
+
}
|
|
14
|
+
function createWorkerBindingEnv(app) {
|
|
15
|
+
return `VERTICAL_${toEnvSegment(app.domain ?? app.id)}_WORKER_BINDING`;
|
|
16
|
+
}
|
|
17
|
+
function createDispatchNamespaceEnv(app) {
|
|
18
|
+
return `VERTICAL_${toEnvSegment(app.domain ?? app.id)}_DISPATCH_NAMESPACE`;
|
|
19
|
+
}
|
|
20
|
+
function createDispatchWorkerNameEnv(app) {
|
|
21
|
+
return `VERTICAL_${toEnvSegment(app.domain ?? app.id)}_WORKER_NAME`;
|
|
22
|
+
}
|
|
23
|
+
function createEffectExpose(app) {
|
|
24
|
+
const apiStem = resolveApiStem(app);
|
|
25
|
+
return {
|
|
26
|
+
contract: `${app.directory}/shared/api.ts`,
|
|
27
|
+
runtime: `${app.directory}/api/index.ts`,
|
|
28
|
+
client: `${app.directory}/src/api/${app.api.stem}-client.ts`,
|
|
29
|
+
openapi: `${app.api.prefix}/openapi.json`,
|
|
30
|
+
readiness: `${app.api.prefix}/${apiStem}/readiness`
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function createCloudflareExecutionSurface(scope, app) {
|
|
34
|
+
return {
|
|
35
|
+
kind: 'cloudflare-worker-snapshot',
|
|
36
|
+
workerName: createCloudflareWorkerName(scope, app),
|
|
37
|
+
publicUrlEnv: createCloudflarePublicUrlEnv(app),
|
|
38
|
+
ssr: {
|
|
39
|
+
workerEntry: '.output/server/index.mjs',
|
|
40
|
+
workerManifest: '.output/server/modern-worker-manifest.json',
|
|
41
|
+
routeManifest: '.output/server/route.json',
|
|
42
|
+
ssrBundle: '.output/worker/index.js',
|
|
43
|
+
effectBffBundle: '.output/worker/__modern_bff_effect.js',
|
|
44
|
+
assetsBinding: 'ASSETS'
|
|
45
|
+
},
|
|
46
|
+
zephyr: {
|
|
47
|
+
runtime: 'ssr-worker',
|
|
48
|
+
integration: 'managed-cloudflare',
|
|
49
|
+
snapshotIdEnv: createZephyrEnv(app, 'SNAPSHOT_ID'),
|
|
50
|
+
versionIdEnv: createZephyrEnv(app, 'VERSION_ID'),
|
|
51
|
+
applicationUidEnv: createZephyrEnv(app, 'APPLICATION_UID')
|
|
52
|
+
},
|
|
53
|
+
workerDispatch: {
|
|
54
|
+
preferred: 'service-binding',
|
|
55
|
+
serviceBinding: createWorkerBindingName(app),
|
|
56
|
+
serviceBindingEnv: createWorkerBindingEnv(app),
|
|
57
|
+
dispatchNamespaceEnv: createDispatchNamespaceEnv(app),
|
|
58
|
+
dispatchWorkerNameEnv: createDispatchWorkerNameEnv(app),
|
|
59
|
+
requestInterface: 'fetch'
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function createNodeExecutionSurface(app) {
|
|
64
|
+
return {
|
|
65
|
+
kind: 'node-mf-runtime',
|
|
66
|
+
adapterVersion: BACKEND_FEDERATION_NODE_ADAPTER_VERSION,
|
|
67
|
+
remoteName: createBackendFederationName(app),
|
|
68
|
+
manifestEnv: createBackendFederationManifestEnv(app),
|
|
69
|
+
manifestUrl: createBackendFederationManifestUrl(app),
|
|
70
|
+
containerEntry: createBackendFederationContainerEntry(app),
|
|
71
|
+
remoteType: 'module',
|
|
72
|
+
expose: './effect-api',
|
|
73
|
+
runtimePackage: '@modern-js/plugin-bff/effect'
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function createServerExecutionOverlay(scope, app) {
|
|
77
|
+
if (!appHasApi(app)) return;
|
|
78
|
+
const deliveryUnit = createDeliveryUnitRecord(scope, app);
|
|
79
|
+
return {
|
|
80
|
+
apiBaseUrl: `http://localhost:${app.port}${resolveApiPrefix(app)}`,
|
|
81
|
+
versionBoundary: 'web-and-api-same-build',
|
|
82
|
+
deliveryUnit: {
|
|
83
|
+
unitId: deliveryUnit.unitId,
|
|
84
|
+
buildMarker: deliveryUnit.buildMarker
|
|
85
|
+
},
|
|
86
|
+
cloudflare: createCloudflareExecutionSurface(scope, app),
|
|
87
|
+
node: createNodeExecutionSurface(app)
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function createBackendFederationContract(scope, app) {
|
|
91
|
+
if (!appHasApi(app)) return;
|
|
92
|
+
const readiness = `${app.api.prefix}/${resolveApiStem(app)}/readiness`;
|
|
93
|
+
const deliveryUnit = createDeliveryUnitRecord(scope, app);
|
|
94
|
+
return {
|
|
95
|
+
role: 'microvertical-server',
|
|
96
|
+
name: createBackendFederationName(app),
|
|
97
|
+
runtimeFramework: 'effect',
|
|
98
|
+
strictEffectApproach: true,
|
|
99
|
+
deliveryUnit: deliveryUnitContractBlock(deliveryUnit),
|
|
100
|
+
exposes: {
|
|
101
|
+
'./effect-api': createEffectExpose(app)
|
|
102
|
+
},
|
|
103
|
+
versionBoundary: {
|
|
104
|
+
invariant: 'web-and-api-same-build',
|
|
105
|
+
identityRoot: 'deliveryUnit',
|
|
106
|
+
packageName: packageName(scope, app.packageSuffix),
|
|
107
|
+
ui: {
|
|
108
|
+
manifestEnv: createRemoteManifestEnv(app),
|
|
109
|
+
manifestUrl: `http://localhost:${app.port}/mf-manifest.json`,
|
|
110
|
+
buildMarker: `${app.directory}/src/routes/ultramodern-route-metadata.ts`
|
|
111
|
+
},
|
|
112
|
+
api: {
|
|
113
|
+
readiness,
|
|
114
|
+
buildMarker: `${app.directory}/shared/ultramodern-build.ts`,
|
|
115
|
+
publicUrlEnv: createCloudflarePublicUrlEnv(app)
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
executionSurfaces: {
|
|
119
|
+
cloudflare: createCloudflareExecutionSurface(scope, app),
|
|
120
|
+
node: createNodeExecutionSurface(app)
|
|
121
|
+
},
|
|
122
|
+
compatibility: {
|
|
123
|
+
contractVersion: BACKEND_FEDERATION_CONTRACT_VERSION,
|
|
124
|
+
packageName: packageName(scope, app.packageSuffix),
|
|
125
|
+
effectVersion: EFFECT_VERSION,
|
|
126
|
+
moduleFederationVersion: MODULE_FEDERATION_VERSION
|
|
127
|
+
},
|
|
128
|
+
cache: {
|
|
129
|
+
cloudflareSnapshot: 'immutable',
|
|
130
|
+
nodeManifest: 'no-store',
|
|
131
|
+
nodeVersionedContainer: 'immutable',
|
|
132
|
+
nodeUnpinnedContainer: 'revalidate'
|
|
133
|
+
},
|
|
134
|
+
fallback: {
|
|
135
|
+
timeoutMs: 1500,
|
|
136
|
+
failureEvent: 'modernjs:microvertical-server-fallback',
|
|
137
|
+
strategy: 'typed-effect-error'
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
function createBackendFederationMetadata(scope, app) {
|
|
142
|
+
if (!appHasApi(app)) return;
|
|
143
|
+
return {
|
|
144
|
+
contractVersion: BACKEND_FEDERATION_CONTRACT_VERSION,
|
|
145
|
+
deliveryUnit: deliveryUnitContractBlock(createDeliveryUnitRecord(scope, app)),
|
|
146
|
+
executionSurfaces: [
|
|
147
|
+
'node-mf-runtime'
|
|
148
|
+
],
|
|
149
|
+
exposes: [
|
|
150
|
+
'./effect-api'
|
|
151
|
+
],
|
|
152
|
+
name: createBackendFederationName(app),
|
|
153
|
+
nodeAdapterVersion: BACKEND_FEDERATION_NODE_ADAPTER_VERSION,
|
|
154
|
+
openapiPath: `${app.api.prefix}/openapi.json`,
|
|
155
|
+
readinessPath: `${app.api.prefix}/${resolveApiStem(app)}/readiness`,
|
|
156
|
+
role: 'microvertical-server',
|
|
157
|
+
runtimeFramework: 'effect',
|
|
158
|
+
strictEffectApproach: true
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
function createBackendFederationContractFile(app) {
|
|
162
|
+
if (!app.api) throw new Error(`App ${app.id} does not define an Effect API.`);
|
|
163
|
+
const apiExport = verticalApiExport(app);
|
|
164
|
+
const groupName = verticalApiGroupName(app);
|
|
165
|
+
const readinessPath = `${app.api.prefix}/${resolveApiStem(app)}/readiness`;
|
|
166
|
+
return `import runtime from './index.ts';
|
|
167
|
+
import { ultramodernApiMarker } from '../shared/ultramodern-build.ts';
|
|
168
|
+
import {
|
|
169
|
+
${apiExport} as api,
|
|
170
|
+
${groupName}ApiContract as contract,
|
|
171
|
+
${groupName}OperationContexts as operationContexts,
|
|
172
|
+
} from '../shared/api.ts';
|
|
173
|
+
|
|
174
|
+
export const backendFederationContract = {
|
|
175
|
+
compatibility: {
|
|
176
|
+
build: ultramodernApiMarker.build,
|
|
177
|
+
contractVersion: '${BACKEND_FEDERATION_CONTRACT_VERSION}',
|
|
178
|
+
nodeAdapterVersion: '${BACKEND_FEDERATION_NODE_ADAPTER_VERSION}',
|
|
179
|
+
packageName: ultramodernApiMarker.packageName,
|
|
180
|
+
sourceRevision: ultramodernApiMarker.sourceRevision,
|
|
181
|
+
unitId: ultramodernApiMarker.unitId,
|
|
182
|
+
},
|
|
183
|
+
contractVersion: '${BACKEND_FEDERATION_CONTRACT_VERSION}',
|
|
184
|
+
executionSurfaces: ['node-mf-runtime'],
|
|
185
|
+
exposes: ['./effect-api'],
|
|
186
|
+
name: '${createBackendFederationName(app)}',
|
|
187
|
+
nodeAdapterVersion: '${BACKEND_FEDERATION_NODE_ADAPTER_VERSION}',
|
|
188
|
+
openapiPath: '${app.api.prefix}/openapi.json',
|
|
189
|
+
readinessPath: '${readinessPath}',
|
|
190
|
+
role: 'microvertical-server',
|
|
191
|
+
runtimeFramework: 'effect',
|
|
192
|
+
strictEffectApproach: true,
|
|
193
|
+
} as const;
|
|
194
|
+
|
|
195
|
+
export { api, contract, operationContexts, runtime };
|
|
196
|
+
|
|
197
|
+
export default runtime;
|
|
198
|
+
`;
|
|
199
|
+
}
|
|
200
|
+
function createBackendFederationSummary(scope, app) {
|
|
201
|
+
if (!appHasApi(app)) return;
|
|
202
|
+
return {
|
|
203
|
+
id: app.id,
|
|
204
|
+
path: app.directory,
|
|
205
|
+
role: 'microvertical-server',
|
|
206
|
+
name: createBackendFederationName(app),
|
|
207
|
+
runtimeFramework: 'effect',
|
|
208
|
+
strictEffectApproach: true,
|
|
209
|
+
contractVersion: BACKEND_FEDERATION_CONTRACT_VERSION,
|
|
210
|
+
deliveryUnit: deliveryUnitContractBlock(createDeliveryUnitRecord(scope, app)),
|
|
211
|
+
executionSurfaces: {
|
|
212
|
+
cloudflare: createCloudflareExecutionSurface(scope, app),
|
|
213
|
+
node: createNodeExecutionSurface(app)
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
export { BACKEND_FEDERATION_CONTRACT_VERSION, BACKEND_FEDERATION_NODE_ADAPTER_VERSION, createBackendFederationContract, createBackendFederationContractFile, createBackendFederationMetadata, createBackendFederationSummary, createDispatchWorkerNameEnv, createServerExecutionOverlay, createWorkerBindingEnv, createWorkerBindingName };
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { apiTopologyMetadata } from "./api.js";
|
|
2
|
+
import { createBackendFederationContract, createBackendFederationSummary, createServerExecutionOverlay } from "./backend-federation.js";
|
|
3
|
+
import { createDeliveryUnitRecord, deliveryUnitContractBlock } from "./delivery-unit.js";
|
|
2
4
|
import { createModuleFederationRemoteContracts, createShellHost, resolveApiPrefix, sharedPackages, shellApp, verticalApiApps } from "./descriptors.js";
|
|
3
5
|
import { packageName } from "./naming.js";
|
|
4
6
|
import { createCloudflareDeployContract } from "./policy.js";
|
|
7
|
+
import { createGeneratedToolingWrapperMap } from "./tooling-command-catalog.js";
|
|
5
8
|
import { CLOUDFLARE_COMPATIBILITY_DATE, NODE_VERSION, PNPM_VERSION } from "./versions.js";
|
|
6
9
|
function createTopology(scope, remotes = []) {
|
|
7
10
|
const shellHost = createShellHost(remotes);
|
|
@@ -44,6 +47,12 @@ function createTopology(scope, remotes = []) {
|
|
|
44
47
|
fallbackTelemetryEvent: 'modernjs:mv-runtime-parity',
|
|
45
48
|
sharedContractVersion: 'mf-ssr-contract-v1'
|
|
46
49
|
},
|
|
50
|
+
...createBackendFederationContract(scope, vertical) ? {
|
|
51
|
+
backendFederation: createBackendFederationContract(scope, vertical)
|
|
52
|
+
} : {},
|
|
53
|
+
...vertical.api ? {
|
|
54
|
+
deliveryUnit: deliveryUnitContractBlock(createDeliveryUnitRecord(scope, vertical))
|
|
55
|
+
} : {},
|
|
47
56
|
...apiTopologyMetadata(vertical) ? {
|
|
48
57
|
api: apiTopologyMetadata(vertical)
|
|
49
58
|
} : {},
|
|
@@ -99,7 +108,7 @@ function createOwnership(scope, remotes = []) {
|
|
|
99
108
|
}))
|
|
100
109
|
};
|
|
101
110
|
}
|
|
102
|
-
function createDevelopmentOverlay(remotes = []) {
|
|
111
|
+
function createDevelopmentOverlay(scope, remotes = []) {
|
|
103
112
|
return {
|
|
104
113
|
schemaVersion: 1,
|
|
105
114
|
environment: 'development',
|
|
@@ -115,6 +124,10 @@ function createDevelopmentOverlay(remotes = []) {
|
|
|
115
124
|
remote.id,
|
|
116
125
|
`http://localhost:${remote.port}/mf-manifest.json`
|
|
117
126
|
])),
|
|
127
|
+
serverExecution: Object.fromEntries(verticalApiApps(remotes).map((app)=>[
|
|
128
|
+
app.id,
|
|
129
|
+
createServerExecutionOverlay(scope, app)
|
|
130
|
+
])),
|
|
118
131
|
apis: Object.fromEntries(verticalApiApps(remotes).map((app)=>[
|
|
119
132
|
app.id,
|
|
120
133
|
`http://localhost:${app.port}${resolveApiPrefix(app)}`
|
|
@@ -191,6 +204,12 @@ function createUltramodernConfig(scope, modernVersion, packageSource, apps = [
|
|
|
191
204
|
tsConfigPath: './tsconfig.mf-types.json'
|
|
192
205
|
}
|
|
193
206
|
},
|
|
207
|
+
...createBackendFederationContract(scope, app) ? {
|
|
208
|
+
backendFederation: createBackendFederationContract(scope, app)
|
|
209
|
+
} : {},
|
|
210
|
+
...app.api ? {
|
|
211
|
+
deliveryUnit: deliveryUnitContractBlock(createDeliveryUnitRecord(scope, app))
|
|
212
|
+
} : {},
|
|
194
213
|
...app.api ? {
|
|
195
214
|
api: {
|
|
196
215
|
stem: app.api.stem,
|
|
@@ -234,6 +253,9 @@ function createUltramodernConfig(scope, modernVersion, packageSource, apps = [
|
|
|
234
253
|
hostOnly: 'shell' === app.kind && 0 === Object.keys(app.exposes ?? {}).length
|
|
235
254
|
}))
|
|
236
255
|
},
|
|
256
|
+
backendFederation: {
|
|
257
|
+
apps: verticalApiApps(remotes).map((app)=>createBackendFederationSummary(scope, app))
|
|
258
|
+
},
|
|
237
259
|
agentSkills: {
|
|
238
260
|
target: 'codex',
|
|
239
261
|
lockfile: './.codex/skills-lock.json',
|
|
@@ -248,13 +270,7 @@ function createUltramodernConfig(scope, modernVersion, packageSource, apps = [
|
|
|
248
270
|
tooling: {
|
|
249
271
|
command: 'modern-js-create ultramodern',
|
|
250
272
|
wrappers: {
|
|
251
|
-
|
|
252
|
-
typecheck: "scripts/ultramodern-typecheck.mts",
|
|
253
|
-
mfTypes: "scripts/assert-mf-types.mts",
|
|
254
|
-
publicSurface: "scripts/generate-public-surface-assets.mts",
|
|
255
|
-
cloudflareProof: "scripts/proof-cloudflare-version.mts",
|
|
256
|
-
performanceReadiness: "scripts/ultramodern-performance-readiness.mts",
|
|
257
|
-
migrateStrictEffect: "scripts/migrate-strict-effect.mts",
|
|
273
|
+
...createGeneratedToolingWrapperMap(),
|
|
258
274
|
apiBoundaries: "scripts/check-ultramodern-api-boundaries.mts",
|
|
259
275
|
skills: "scripts/bootstrap-agent-skills.mts"
|
|
260
276
|
}
|