@bleedingdev/modern-js-ultramodern-create 3.9.0-ultramodern.2 → 3.9.0-ultramodern.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-typescript.cjs +1 -0
  2. package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/package-cohort.cjs +2 -0
  3. package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/shared-api-infrastructure.cjs +99 -0
  4. package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/toolchain-pins.cjs +1 -0
  5. package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect.cjs +2 -0
  6. package/dist/cjs/ultramodern-workspace/api/client.cjs +2 -2
  7. package/dist/cjs/ultramodern-workspace/api/service.cjs +45 -16
  8. package/dist/cjs/ultramodern-workspace/api/shared.cjs +26 -16
  9. package/dist/cjs/ultramodern-workspace/mf-validation/inspect.cjs +6 -2
  10. package/dist/cjs/ultramodern-workspace/module-federation/reexport-module.cjs +0 -5
  11. package/dist/cjs/ultramodern-workspace/package-json.cjs +12 -1
  12. package/dist/cjs/ultramodern-workspace/policy.cjs +1 -0
  13. package/dist/cjs/ultramodern-workspace/tsconfigs.cjs +3 -0
  14. package/dist/cjs/ultramodern-workspace/workspace-script-plan.cjs +1 -1
  15. package/dist/cjs/ultramodern-workspace/workspace-scripts.cjs +5 -0
  16. package/dist/cjs/ultramodern-workspace/write-app.cjs +9 -3
  17. package/dist/cjs/ultramodern-workspace/write-workspace.cjs +5 -3
  18. package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-typescript.js +1 -0
  19. package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/package-cohort.js +2 -0
  20. package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/shared-api-infrastructure.js +50 -0
  21. package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/toolchain-pins.js +1 -0
  22. package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect.js +2 -0
  23. package/dist/esm/ultramodern-workspace/api/client.js +2 -2
  24. package/dist/esm/ultramodern-workspace/api/service.js +45 -16
  25. package/dist/esm/ultramodern-workspace/api/shared.js +27 -17
  26. package/dist/esm/ultramodern-workspace/mf-validation/inspect.js +6 -2
  27. package/dist/esm/ultramodern-workspace/module-federation/reexport-module.js +0 -5
  28. package/dist/esm/ultramodern-workspace/package-json.js +12 -1
  29. package/dist/esm/ultramodern-workspace/policy.js +1 -0
  30. package/dist/esm/ultramodern-workspace/tsconfigs.js +3 -0
  31. package/dist/esm/ultramodern-workspace/workspace-script-plan.js +1 -1
  32. package/dist/esm/ultramodern-workspace/workspace-scripts.js +5 -0
  33. package/dist/esm/ultramodern-workspace/write-app.js +9 -3
  34. package/dist/esm/ultramodern-workspace/write-workspace.js +6 -4
  35. package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-typescript.js +1 -0
  36. package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/package-cohort.js +2 -0
  37. package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/shared-api-infrastructure.js +51 -0
  38. package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/toolchain-pins.js +1 -0
  39. package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect.js +2 -0
  40. package/dist/esm-node/ultramodern-workspace/api/client.js +2 -2
  41. package/dist/esm-node/ultramodern-workspace/api/service.js +45 -16
  42. package/dist/esm-node/ultramodern-workspace/api/shared.js +27 -17
  43. package/dist/esm-node/ultramodern-workspace/mf-validation/inspect.js +6 -2
  44. package/dist/esm-node/ultramodern-workspace/module-federation/reexport-module.js +0 -5
  45. package/dist/esm-node/ultramodern-workspace/package-json.js +12 -1
  46. package/dist/esm-node/ultramodern-workspace/policy.js +1 -0
  47. package/dist/esm-node/ultramodern-workspace/tsconfigs.js +3 -0
  48. package/dist/esm-node/ultramodern-workspace/workspace-script-plan.js +1 -1
  49. package/dist/esm-node/ultramodern-workspace/workspace-scripts.js +5 -0
  50. package/dist/esm-node/ultramodern-workspace/write-app.js +9 -3
  51. package/dist/esm-node/ultramodern-workspace/write-workspace.js +6 -4
  52. package/dist/types/ultramodern-tooling/commands/migrate-strict-effect/shared-api-infrastructure.d.ts +4 -0
  53. package/dist/types/ultramodern-workspace/api/client.d.ts +3 -1
  54. package/dist/types/ultramodern-workspace/api/service.d.ts +3 -1
  55. package/dist/types/ultramodern-workspace/api/shared.d.ts +2 -0
  56. package/dist/types/ultramodern-workspace/package-json.d.ts +1 -1
  57. package/dist/types/ultramodern-workspace/policy.d.ts +2 -0
  58. package/package.json +4 -4
  59. package/template-workspace/.modernjs/release-cohort.json +40 -40
  60. package/templates/packages/effect-bff-runtime.ts +50 -0
  61. package/templates/packages/microvertical-api-baseline.ts +102 -0
  62. package/templates/workspace-scripts/check-ultramodern-api-boundaries.mts +49 -28
  63. package/templates/workspace-scripts/microvertical-api-baseline-boundary.mts +944 -0
  64. package/templates/workspace-scripts/ultramodern-cloudflare-proof.mjs +25 -7
  65. package/templates/workspace-scripts/validate-ultramodern-workspace.mjs.handlebars +1 -1
@@ -3,7 +3,7 @@ import { resolveApiProtocol, resolveApiStem, verticalApiApps } from "../descript
3
3
  import { packageName, toPascalCase } from "../naming.js";
4
4
  import { createCheckoutCartClientExports, serviceHasCheckoutCartState } from "./checkout-cart.js";
5
5
  import { verticalApiErrorStem, verticalApiExport, verticalApiGroupName, verticalApiNotFoundErrorExport } from "./names.js";
6
- function createApiClient(service, contractImportPath) {
6
+ function createApiClient(service, contractImportPath, options) {
7
7
  const apiExport = verticalApiExport(service);
8
8
  const contractExport = verticalApiGroupName(service);
9
9
  const stem = resolveApiStem(service);
@@ -119,7 +119,7 @@ export const ${readinessName} = (
119
119
  operationContext:
120
120
  options.operationContext ?? ${groupName}OperationContexts.readiness,
121
121
  }).pipe(
122
- Effect.flatMap(client => client.${groupName}.readiness({})),
122
+ Effect.flatMap(client => client.${options ? 'foundation' : groupName}.readiness({})),
123
123
  );
124
124
 
125
125
  export const ${getName} = (
@@ -5,23 +5,22 @@ import { packageName } from "../naming.js";
5
5
  import { createCheckoutCartServerHandlers, createCheckoutCartServerState } from "./checkout-cart.js";
6
6
  import { verticalApiExport, verticalApiGroupName, verticalApiNotFoundErrorExport } from "./names.js";
7
7
  import { createRpcApiServiceEntry, rpcPath, verticalRpcContractExport, verticalRpcGroupExport } from "./rpc.js";
8
- function createApiServiceEntry(service, contractImportPath) {
8
+ function createApiServiceEntry(service, contractImportPath, options) {
9
9
  if ((service.api?.protocol ?? 'rest') === 'rpc') return createRpcApiServiceEntry(service);
10
10
  const apiExport = verticalApiExport(service);
11
11
  const groupName = verticalApiGroupName(service);
12
12
  const notFoundErrorExport = verticalApiNotFoundErrorExport(service);
13
13
  const stem = resolveApiStem(service);
14
- return `import {
15
- defineEffectBff,
14
+ const assemblyImport = options ? `import { assembleEffectBffRuntime } from '${packageName(options.scope, 'shared-contracts')}/server/effect-bff-runtime';\n` : '';
15
+ return `${assemblyImport}import {
16
+ ${options ? '' : 'defineEffectBff,'}
16
17
  Effect,
17
18
  HttpApiBuilder,
18
19
  Layer,
19
20
  } from '@modern-js/plugin-bff/effect-edge';
20
- import type {
21
- EffectBffDefinition,
22
- EffectBffRuntime,
21
+ ${options ? '' : `import type {
23
22
  EffectRuntimeLayer,
24
- } from '@modern-js/plugin-bff/effect-edge';
23
+ } from '@modern-js/plugin-bff/effect-edge';`}
25
24
  import { ultramodernApiMarker } from '../shared/ultramodern-build.ts';
26
25
  import {
27
26
  ${apiExport},
@@ -51,6 +50,31 @@ const operationAttributes = (operationContext: OperationContext) => ({
51
50
  : {}),
52
51
  });
53
52
 
53
+ ${options ? `const ${groupName}ReadinessLayer = HttpApiBuilder.group(
54
+ ${apiExport},
55
+ 'foundation',
56
+ handlers => handlers
57
+ .handle('readiness', () =>
58
+ Effect.succeed({
59
+ checks: {
60
+ api: 'ready' as const,
61
+ moduleFederation: 'ready' as const,
62
+ ssr: 'ready' as const,
63
+ translations: 'ready' as const,
64
+ },
65
+ marker: ultramodernApiMarker,
66
+ status: 'ready' as const,
67
+ versionSkew: 'none' as const,
68
+ }).pipe(
69
+ Effect.withSpan('ultramodern.api.${groupName}.readiness', {
70
+ attributes: operationAttributes(${groupName}OperationContexts.readiness),
71
+ kind: 'server',
72
+ }),
73
+ ),
74
+ )
75
+ ,
76
+ );` : ''}
77
+
54
78
  const ${groupName}Layer = HttpApiBuilder.group(
55
79
  ${apiExport},
56
80
  '${groupName}',
@@ -69,7 +93,7 @@ const ${groupName}Layer = HttpApiBuilder.group(
69
93
  }),
70
94
  ),
71
95
  )
72
- .handle('readiness', () =>
96
+ ${options ? '' : ` .handle('readiness', () =>
73
97
  Effect.succeed({
74
98
  checks: {
75
99
  api: 'ready' as const,
@@ -87,6 +111,7 @@ const ${groupName}Layer = HttpApiBuilder.group(
87
111
  }),
88
112
  ),
89
113
  )
114
+ `}
90
115
  .handle('get', ({ params }) => {
91
116
  const matchedItem = ${groupName}Items.find(
92
117
  candidate => candidate.id === params.id,
@@ -126,14 +151,18 @@ const ${groupName}Layer = HttpApiBuilder.group(
126
151
  )${createCheckoutCartServerHandlers(service)},
127
152
  );
128
153
 
129
- const layer = HttpApiBuilder.layer(${apiExport}).pipe(
130
- Layer.provide(${groupName}Layer),
131
- ) satisfies EffectRuntimeLayer;
132
- const apiRuntime: EffectBffDefinition<typeof ${apiExport}, EffectRuntimeLayer> &
133
- EffectBffRuntime<typeof ${apiExport}, EffectRuntimeLayer> = defineEffectBff({
134
- api: ${apiExport},
135
- layer,
136
- });
154
+ ${options ? `const apiHandlersLive = Layer.mergeAll(${groupName}Layer, ${groupName}ReadinessLayer);
155
+ export const make${apiExport[0].toUpperCase()}${apiExport.slice(1)}Runtime = () =>
156
+ assembleEffectBffRuntime({
157
+ api: ${apiExport},
158
+ handlers: apiHandlersLive,
159
+ });` : `export const make${apiExport[0].toUpperCase()}${apiExport.slice(1)}Runtime = () => {
160
+ const layer = HttpApiBuilder.layer(${apiExport}).pipe(
161
+ Layer.provide(${groupName}Layer),
162
+ ) satisfies EffectRuntimeLayer;
163
+ return defineEffectBff({ api: ${apiExport}, layer });
164
+ };`}
165
+ const apiRuntime = make${apiExport[0].toUpperCase()}${apiExport.slice(1)}Runtime();
137
166
 
138
167
  export default apiRuntime;
139
168
  `;
@@ -1,7 +1,7 @@
1
1
  import "node:module";
2
2
  import { resolveApiPrefix, resolveApiStem } from "../descriptors.js";
3
3
  import { renderTemplate } from "../fs-io.js";
4
- import { toPascalCase } from "../naming.js";
4
+ import { packageName, toPascalCase } from "../naming.js";
5
5
  import { createCheckoutCartApiContractFields, createCheckoutCartEndpointDefinitions, createCheckoutCartOperationContexts, createCheckoutCartSharedSchemas } from "./checkout-cart.js";
6
6
  import { verticalApiCreatePayloadSchemaExport, verticalApiExport, verticalApiGroupName, verticalApiMarkerSchemaExport, verticalApiName, verticalApiNotFoundErrorExport, verticalApiNotFoundSchemaExport, verticalApiReadinessSchemaExport, verticalApiSchemaExport } from "./names.js";
7
7
  function createSharedApiImports() {
@@ -14,7 +14,7 @@ function createSharedApiImports() {
14
14
  } from '@modern-js/plugin-bff/effect-client';
15
15
  `;
16
16
  }
17
- function createSharedApiContract(service) {
17
+ function createSharedApiContract(service, shared = false) {
18
18
  const schemaExport = verticalApiSchemaExport(service);
19
19
  const markerSchemaExport = verticalApiMarkerSchemaExport(service);
20
20
  const readinessSchemaExport = verticalApiReadinessSchemaExport(service);
@@ -71,7 +71,7 @@ function createSharedApiContract(service) {
71
71
  listOperationContext,
72
72
  readinessOperationContext
73
73
  }).trim();
74
- return `export interface ${markerType} {
74
+ return `${shared ? `export type ${markerType} = MicroVerticalBuildMarker;` : `export interface ${markerType} {
75
75
  readonly appId: string;
76
76
  readonly build: string;
77
77
  readonly buildMarker: string;
@@ -81,7 +81,7 @@ function createSharedApiContract(service) {
81
81
  readonly surface: string;
82
82
  readonly unitId: string;
83
83
  readonly version: string;
84
- }
84
+ }`}
85
85
 
86
86
  export interface ${itemType} {
87
87
  readonly id: string;
@@ -89,7 +89,7 @@ export interface ${itemType} {
89
89
  readonly title: string;
90
90
  }
91
91
 
92
- export interface ${readinessType} {
92
+ ${shared ? `export type ${readinessType} = MicroVerticalReadiness;` : `export interface ${readinessType} {
93
93
  readonly checks: {
94
94
  readonly api: 'ready';
95
95
  readonly moduleFederation: 'ready';
@@ -99,7 +99,7 @@ export interface ${readinessType} {
99
99
  readonly marker: ${markerType};
100
100
  readonly status: 'ready';
101
101
  readonly versionSkew: 'none';
102
- }
102
+ }`}
103
103
 
104
104
  export interface ${createPayloadType} {
105
105
  readonly title: string;
@@ -118,7 +118,7 @@ export interface ${notFoundErrorExport} {
118
118
  readonly id: string;
119
119
  }
120
120
 
121
- export const ${markerSchemaExport}: Schema.Codec<${markerType}> = Schema.Struct({
121
+ ${shared ? `export const ${markerSchemaExport}: Schema.Codec<${markerType}> = MicroVerticalBuildMarkerSchema;` : `export const ${markerSchemaExport}: Schema.Codec<${markerType}> = Schema.Struct({
122
122
  appId: Schema.String,
123
123
  build: Schema.String,
124
124
  buildMarker: Schema.String,
@@ -128,7 +128,7 @@ export const ${markerSchemaExport}: Schema.Codec<${markerType}> = Schema.Struct(
128
128
  surface: Schema.String,
129
129
  unitId: Schema.String,
130
130
  version: Schema.String,
131
- });
131
+ });`}
132
132
 
133
133
  export const ${schemaExport}: Schema.Codec<${itemType}> = Schema.Struct({
134
134
  id: Schema.String,
@@ -136,7 +136,7 @@ export const ${schemaExport}: Schema.Codec<${itemType}> = Schema.Struct({
136
136
  title: Schema.String,
137
137
  });
138
138
 
139
- export const ${readinessSchemaExport}: Schema.Codec<${readinessType}> = Schema.Struct({
139
+ ${shared ? `export const ${readinessSchemaExport}: Schema.Codec<${readinessType}> = MicroVerticalReadinessSchema;` : `export const ${readinessSchemaExport}: Schema.Codec<${readinessType}> = Schema.Struct({
140
140
  checks: Schema.Struct({
141
141
  api: Schema.Literal('ready'),
142
142
  moduleFederation: Schema.Literal('ready'),
@@ -146,7 +146,7 @@ export const ${readinessSchemaExport}: Schema.Codec<${readinessType}> = Schema.S
146
146
  marker: ${markerSchemaExport},
147
147
  status: Schema.Literal('ready'),
148
148
  versionSkew: Schema.Literal('none'),
149
- });
149
+ });`}
150
150
 
151
151
  export const ${createPayloadSchemaExport}: Schema.Codec<${createPayloadType}> = Schema.Struct({
152
152
  title: Schema.String,
@@ -158,7 +158,7 @@ ${checkoutCartSharedSchemaSection}export const ${notFoundSchemaExport}: Schema.C
158
158
  HttpApiSchema.status(404),
159
159
  );
160
160
 
161
- export interface OperationContext {
161
+ ${shared ? 'export type OperationContext = MicroVerticalOperationContext;' : `export interface OperationContext {
162
162
  method: string;
163
163
  operationId: string;
164
164
  routePath: string;
@@ -170,9 +170,14 @@ export interface OperationContext {
170
170
  | 'data-platform'
171
171
  | 'unknown';
172
172
  traceId?: string;
173
- }
173
+ }`}
174
174
 
175
- export const ${apiExport} = HttpApi.make('${apiName}').add(
175
+ ${shared ? `export const ${groupName}FoundationApi = HttpApi.make('${apiName}Foundation').add(
176
+ HttpApiGroup.make('foundation').add(
177
+ HttpApiEndpoint.get('readiness', '/${stem}/readiness', { success: ${readinessSchemaExport} }),
178
+ ),
179
+ );` : ''}
180
+ export const ${apiExport} = HttpApi.make('${apiName}')${shared ? `.addHttpApi(${groupName}FoundationApi)` : ''}.add(
176
181
  HttpApiGroup.make('${groupName}')
177
182
  .add(
178
183
  HttpApiEndpoint.get('list', '/${stem}', {
@@ -184,11 +189,12 @@ export const ${apiExport} = HttpApi.make('${apiName}').add(
184
189
  }),
185
190
  }),
186
191
  )
187
- .add(
192
+ ${shared ? '' : ` .add(
188
193
  HttpApiEndpoint.get('readiness', '/${stem}/readiness', {
189
194
  success: ${readinessSchemaExport},
190
195
  }),
191
196
  )
197
+ `}
192
198
  .add(
193
199
  HttpApiEndpoint.get('get', '/${stem}/:id', {
194
200
  error: ${notFoundSchemaExport},
@@ -209,7 +215,7 @@ export const ${apiExport} = HttpApi.make('${apiName}').add(
209
215
  );
210
216
 
211
217
  export const ${groupName}OperationContexts = {
212
- ${operationContextEntries}
218
+ ${shared ? operationContextEntries.replaceAll(/(\w+: )\{([\s\S]*?)\},/gu, (_, key, fields)=>`${key}createMicroVerticalOperationContext({${fields.replace(/\n\s*source: 'generated-client',/u, '')}}),`) : operationContextEntries}
213
219
  } satisfies Record<string, OperationContext>;
214
220
 
215
221
  export const ${groupName}ApiContract = {
@@ -220,8 +226,12 @@ ${createCheckoutCartApiContractFields(service)} ownerId: '${service.id}',
220
226
  } as const;
221
227
  `;
222
228
  }
223
- function createSharedApi(service) {
229
+ function createSharedApi(service, options) {
230
+ const imports = options ? `import { MicroVerticalBuildMarkerSchema, MicroVerticalReadinessSchema, createMicroVerticalOperationContext } from '${packageName(options.scope, 'shared-contracts')}/microvertical-api-baseline';
231
+ import type { MicroVerticalBuildMarker, MicroVerticalReadiness, MicroVerticalOperationContext } from '${packageName(options.scope, 'shared-contracts')}/microvertical-api-baseline';
232
+ ` : '';
224
233
  return `${createSharedApiImports()}
225
- ${createSharedApiContract(service)}`;
234
+ ${imports}
235
+ ${createSharedApiContract(service, void 0 !== options)}`;
226
236
  }
227
237
  export { createSharedApi };
@@ -12,7 +12,11 @@ function extractExposes(configPath, value) {
12
12
  if (array) return array.sort();
13
13
  throw new Error(`Cannot statically extract Module Federation exposes from ${configPath}; use a literal exposes object or string array.`);
14
14
  }
15
- function extractDtsSettings(configPath, value) {
15
+ function extractDtsSettings(configPath, value, exposes) {
16
+ if ('false' === value) {
17
+ if (exposes.length > 0) throw new Error(`Module Federation DTS cannot be disabled for exposed app ${configPath}.`);
18
+ return {};
19
+ }
16
20
  if (void 0 === value) return {};
17
21
  const dts = parseObjectLiteral(value);
18
22
  if (!dts || dts.hasSpread) throw new Error(`Cannot statically extract Module Federation DTS settings from ${configPath}; use a literal dts object.`);
@@ -39,7 +43,7 @@ function inspectModuleFederationConfigSource(source, appDir, configPath) {
39
43
  return {
40
44
  appDir,
41
45
  configPath,
42
- dts: extractDtsSettings(configPath, properties.properties.get('dts')),
46
+ dts: extractDtsSettings(configPath, properties.properties.get('dts'), exposes),
43
47
  exposes,
44
48
  hostOnlyNoExposes
45
49
  };
@@ -46,22 +46,17 @@ const ultramodernBuildArtifact = {
46
46
  },
47
47
  } as const;
48
48
 
49
- export { ultramodernBuildArtifact };
50
-
51
49
  export const ultramodernDeliveryUnit =
52
50
  ultramodernBuildArtifact.deliveryUnit;
53
- export const ultramodernVerticalIdentity = ultramodernDeliveryUnit;
54
51
  export const ultramodernUiMarker = ultramodernBuildArtifact.surfaces.ui;
55
52
  export const ultramodernApiMarker = ultramodernBuildArtifact.surfaces.api;
56
53
  `;
57
54
  }
58
55
  function createUltramodernBuildReexportModule() {
59
56
  return `export {
60
- ultramodernBuildArtifact,
61
57
  ultramodernApiMarker,
62
58
  ultramodernDeliveryUnit,
63
59
  ultramodernUiMarker,
64
- ultramodernVerticalIdentity,
65
60
  } from '../shared/ultramodern-build';
66
61
  `;
67
62
  }
@@ -172,7 +172,7 @@ function createAppPackage(scope, app, packageSource, enableTailwind, remotes = [
172
172
  if (Object.keys(packageExports).length > 0) packageJson.exports = packageExports;
173
173
  return packageJson;
174
174
  }
175
- function createSharedPackage(scope, id, description) {
175
+ function createSharedPackage(scope, id, description, packageSource) {
176
176
  const packageJson = {
177
177
  private: true,
178
178
  name: packageName(scope, id),
@@ -189,6 +189,17 @@ function createSharedPackage(scope, id, description) {
189
189
  '@effect/tsgo': ULTRAMODERN_PACKAGE_PINS.appDevDependencies["@effect/tsgo"]
190
190
  }
191
191
  };
192
+ if ('shared-contracts' === id) {
193
+ packageJson.exports = {
194
+ '.': './src/index.ts',
195
+ './microvertical-api-baseline': './src/microvertical-api-baseline.ts',
196
+ './server/effect-bff-runtime': './src/effect-bff-runtime.ts'
197
+ };
198
+ packageJson.dependencies = {
199
+ ...ULTRAMODERN_PACKAGE_PINS.bffEffectDependencies,
200
+ '@modern-js/plugin-bff': packageSource ? modernPackageSpecifier('@modern-js/plugin-bff', packageSource) : WORKSPACE_PACKAGE_VERSION
201
+ };
202
+ }
192
203
  if ('shared-design-tokens' === id) packageJson.exports = {
193
204
  ...packageJson.exports,
194
205
  './tokens.css': './src/tokens.css'
@@ -250,6 +250,7 @@ const ULTRAMODERN_PACKAGE_PINS = {
250
250
  rootDevDependencies: {
251
251
  '@effect/tsgo': EFFECT_TSGO_VERSION,
252
252
  "@typescript/native": `npm:typescript@${TYPESCRIPT_VERSION}`,
253
+ '@types/node': TYPES_NODE_VERSION,
253
254
  'cross-env': CROSS_ENV_VERSION,
254
255
  lefthook: LEFTHOOK_VERSION,
255
256
  miniflare: MINIFLARE_VERSION,
@@ -7,6 +7,9 @@ function createTsConfigBase() {
7
7
  return {
8
8
  compilerOptions: {
9
9
  target: 'ESNext',
10
+ types: [
11
+ 'node'
12
+ ],
10
13
  lib: [
11
14
  'ESNext',
12
15
  'DOM',
@@ -140,7 +140,7 @@ function createWorkspaceRootScriptPlan(remotes = [], options = {}) {
140
140
  migrateStrictEffect: rootToolingWrapperCommand('migrateStrictEffect'),
141
141
  zeropsMaterialize: "node ./scripts/materialize-zerops-runtime.mjs",
142
142
  contractCheck: rootToolingWrapperCommand('validate'),
143
- typecheck: options.typecheck ?? `${rootToolingWrapperCommand('typecheck')} --project tsconfig.json`,
143
+ typecheck: options.typecheck ?? `${rootToolingWrapperCommand('typecheck')} --build tsconfig.json`,
144
144
  check: `pnpm format:check && pnpm lint && pnpm typecheck && pnpm skills:check && pnpm i18n:boundaries && pnpm api:check && pnpm contract:check && pnpm performance:readiness${bridgeCheck}`
145
145
  };
146
146
  }
@@ -130,6 +130,7 @@ function writeGeneratedWorkspaceScripts(targetDir, scope, enableTailwind, remote
130
130
  const hasBackendSurface = remotes.some(appHasApi);
131
131
  writeWorkspaceOwnedMtsScript(targetDir, 'check-ultramodern-i18n-boundaries', createWorkspaceI18nBoundaryValidationScript());
132
132
  writeWorkspaceOwnedMtsScript(targetDir, 'check-ultramodern-api-boundaries', createWorkspaceApiBoundaryValidationScript());
133
+ writeWorkspaceOwnedMtsScript(targetDir, 'microvertical-api-baseline-boundary', external_fs_io_js_readFileTemplate("workspace-scripts/microvertical-api-baseline-boundary.mts"));
133
134
  if (!shellOnly) {
134
135
  writeFileReplacing(targetDir, "scripts/materialize-zerops-runtime.mjs", createZeropsRuntimeMaterializationScript());
135
136
  writeWorkspaceOwnedMtsScript(targetDir, 'proof-workerd-ssr', createWorkerdSsrProofScript());
@@ -157,6 +158,10 @@ function migratedWorkspaceScriptArtifacts(options) {
157
158
  content: createWorkspaceI18nBoundaryValidationScript(),
158
159
  legacyPath: "scripts/check-ultramodern-i18n-boundaries.mjs"
159
160
  },
161
+ {
162
+ relativePath: "scripts/microvertical-api-baseline-boundary.mts",
163
+ content: external_fs_io_js_readFileTemplate("workspace-scripts/microvertical-api-baseline-boundary.mts")
164
+ },
160
165
  {
161
166
  relativePath: "scripts/check-ultramodern-api-boundaries.mts",
162
167
  content: createWorkspaceApiBoundaryValidationScript(),
@@ -89,11 +89,17 @@ function writeAppRouteAndShellFiles({ targetDir, scope, resolvedApp, emitsUi, re
89
89
  function writeAppApiAndRemoteExposeFiles({ targetDir, scope, resolvedApp, emitsUi, writeAppFile }) {
90
90
  if (appHasApi(resolvedApp)) {
91
91
  const rpcProtocol = 'rpc' === resolveApiProtocol(resolvedApp);
92
- rpcProtocol ? writeFile(targetDir, `${resolvedApp.directory}/shared/rpc.ts`, createRpcContractFile(resolvedApp)) : writeFile(targetDir, `${resolvedApp.directory}/shared/api.ts`, createSharedApi(resolvedApp));
93
- writeFile(targetDir, `${resolvedApp.directory}/api/index.ts`, createApiServiceEntry(resolvedApp, rpcProtocol ? '../shared/rpc.ts' : '../shared/api.ts'));
92
+ rpcProtocol ? writeFile(targetDir, `${resolvedApp.directory}/shared/rpc.ts`, createRpcContractFile(resolvedApp)) : writeFile(targetDir, `${resolvedApp.directory}/shared/api.ts`, createSharedApi(resolvedApp, {
93
+ scope
94
+ }));
95
+ writeFile(targetDir, `${resolvedApp.directory}/api/index.ts`, createApiServiceEntry(resolvedApp, rpcProtocol ? '../shared/rpc.ts' : '../shared/api.ts', {
96
+ scope
97
+ }));
94
98
  writeFile(targetDir, `${resolvedApp.directory}/api/backend-federation.ts`, createBackendFederationContractFile(resolvedApp));
95
99
  writeFile(targetDir, `${resolvedApp.directory}/api/effect-api.ts`, createBackendEffectApiExpose(scope, resolvedApp));
96
- rpcProtocol ? writeFile(targetDir, `${resolvedApp.directory}/src/api/${resolvedApp.api.stem}-rpc-client.ts`, createRpcClientFile(resolvedApp)) : writeFile(targetDir, `${resolvedApp.directory}/src/api/${resolvedApp.api.stem}-client.ts`, createApiClient(resolvedApp, '../../shared/api'));
100
+ rpcProtocol ? writeFile(targetDir, `${resolvedApp.directory}/src/api/${resolvedApp.api.stem}-rpc-client.ts`, createRpcClientFile(resolvedApp)) : writeFile(targetDir, `${resolvedApp.directory}/src/api/${resolvedApp.api.stem}-client.ts`, createApiClient(resolvedApp, '../../shared/api', {
101
+ scope
102
+ }));
97
103
  }
98
104
  if ('vertical' === resolvedApp.kind && emitsUi) {
99
105
  writeAppFile('src/federation-entry.tsx', createRemoteEntry(resolvedApp));
@@ -6,7 +6,7 @@ import { createSharedDesignTokensCss } from "./app-files.js";
6
6
  import { normalizeUltramodernBridgeConfig } from "./bridge-config.js";
7
7
  import { createDevelopmentOverlay, createOwnership, createTopology, createUltramodernConfig } from "./contracts.js";
8
8
  import { ULTRAMODERN_CONFIG_PATH, createShellHost, sharedPackages, shellApp } from "./descriptors.js";
9
- import { copyRootTemplate, formatGeneratedWorkspaceFiles, writeFile, writeFileReplacing, writeJson } from "./fs-io.js";
9
+ import { copyRootTemplate, formatGeneratedWorkspaceFiles, readFileTemplate, writeFile, writeFileReplacing, writeJson } from "./fs-io.js";
10
10
  import { createFileSnapshot, createGenerationResult, diffFileSnapshots } from "./generation-result.js";
11
11
  import { assertUniqueTailwindPrefixes, toPackageScope } from "./naming.js";
12
12
  import { runCodeSmithOverlays } from "./overlays.js";
@@ -20,12 +20,14 @@ import { createZeropsYaml } from "./zerops.js";
20
20
  function hasExplicitInstallRequest(options) {
21
21
  return void 0 !== options.packageSource && 'workspace' !== options.packageSource.strategy;
22
22
  }
23
- function writeSharedPackages(targetDir, scope) {
23
+ function writeSharedPackages(targetDir, scope, packageSource) {
24
24
  for (const sharedPackage of sharedPackages){
25
- writeJson(targetDir, `${sharedPackage.directory}/package.json`, createSharedPackage(scope, sharedPackage.id, sharedPackage.description));
25
+ writeJson(targetDir, `${sharedPackage.directory}/package.json`, createSharedPackage(scope, sharedPackage.id, sharedPackage.description, packageSource));
26
26
  writeJson(targetDir, `${sharedPackage.directory}/tsconfig.json`, createSharedPackageTsConfig(sharedPackage.directory));
27
27
  }
28
28
  writeFile(targetDir, 'packages/shared-contracts/src/index.ts', createSharedContractsIndex());
29
+ writeFile(targetDir, 'packages/shared-contracts/src/microvertical-api-baseline.ts', readFileTemplate('packages/microvertical-api-baseline.ts'));
30
+ writeFile(targetDir, 'packages/shared-contracts/src/effect-bff-runtime.ts', readFileTemplate('packages/effect-bff-runtime.ts'));
29
31
  writeFile(targetDir, 'packages/shared-design-tokens/src/index.ts', `export const sharedDesignTokens = {
30
32
  color: {
31
33
  accent: '#2f8f68',
@@ -145,7 +147,7 @@ function generateUltramodernWorkspaceInPlace(options, logicalWorkspaceRoot = opt
145
147
  writeJson(options.targetDir, ULTRAMODERN_CONFIG_PATH, createCompactUltramodernConfig(scope, options.modernVersion, packageSource, createdApps, enableTailwind, bridge));
146
148
  writeApp(options.targetDir, scope, shellApp, packageSource, enableTailwind, initialVerticals, bridge);
147
149
  for (const remote of initialVerticals)writeApp(options.targetDir, scope, remote, packageSource, enableTailwind, initialVerticals, bridge);
148
- writeSharedPackages(options.targetDir, scope);
150
+ writeSharedPackages(options.targetDir, scope, packageSource);
149
151
  writeGeneratedWorkspaceScripts(options.targetDir, scope, enableTailwind, initialVerticals, releaseCohort);
150
152
  const preliminaryAfterFiles = createFileSnapshot(options.targetDir);
151
153
  const preliminaryDiff = diffFileSnapshots(beforeFiles, preliminaryAfterFiles);
@@ -0,0 +1,4 @@
1
+ import type { ResolvedPackageSource } from '../../../ultramodern-workspace/types.js';
2
+ import { type MigrationIo } from './io.js';
3
+ /** Add infrastructure only: existing contracts and business handlers stay owned by the consumer. */
4
+ export declare function ensureSharedApiInfrastructure(io: MigrationIo, scope: string, packageSource: ResolvedPackageSource): void;
@@ -2,5 +2,7 @@ import type { WorkspaceApi, WorkspaceApp } from '../types.js';
2
2
  export declare function createApiClient(service: {
3
3
  id: string;
4
4
  api?: WorkspaceApi;
5
- }, contractImportPath: string): string;
5
+ }, contractImportPath: string, options?: {
6
+ readonly scope: string;
7
+ }): string;
6
8
  export declare function createShellApiClient(scope: string, remotes?: WorkspaceApp[]): string;
@@ -2,5 +2,7 @@ import type { WorkspaceApi, WorkspaceApp } from '../types.js';
2
2
  export declare function createApiServiceEntry(service: {
3
3
  id: string;
4
4
  api?: WorkspaceApi;
5
- }, contractImportPath: string): string;
5
+ }, contractImportPath: string, options?: {
6
+ readonly scope: string;
7
+ }): string;
6
8
  export declare function createBackendEffectApiExpose(scope: string, service: WorkspaceApp): string;
@@ -2,4 +2,6 @@ import type { WorkspaceApi } from '../types.js';
2
2
  export declare function createSharedApi(service: {
3
3
  id: string;
4
4
  api?: WorkspaceApi;
5
+ }, options?: {
6
+ readonly scope: string;
5
7
  }): string;
@@ -4,5 +4,5 @@ export declare function appDependencies(scope: string, packageSource: ResolvedPa
4
4
  export declare function createRootPackageJson(scope: string, packageSource: ResolvedPackageSource, remotes?: WorkspaceApp[], bridge?: UltramodernBridgeConfig, additionalShells?: WorkspaceApp[]): JsonValue;
5
5
  export { createAppMfTypesTsConfig, createAppTsConfig, createPackageTsConfig, createRootTsConfig, createSharedPackageTsConfig, createTsConfigBase, } from './tsconfigs.js';
6
6
  export declare function createAppPackage(scope: string, app: WorkspaceApp, packageSource: ResolvedPackageSource, enableTailwind: boolean, remotes?: WorkspaceApp[], bridge?: UltramodernBridgeConfig): JsonValue;
7
- export declare function createSharedPackage(scope: string, id: string, description: string): JsonValue;
7
+ export declare function createSharedPackage(scope: string, id: string, description: string, packageSource?: ResolvedPackageSource): JsonValue;
8
8
  export declare function createSharedContractsIndex(): string;
@@ -82,6 +82,7 @@ export declare const ULTRAMODERN_PACKAGE_PINS: {
82
82
  readonly rootDevDependencies: {
83
83
  readonly '@effect/tsgo': "0.41.0";
84
84
  readonly '@typescript/native': "npm:typescript@7.0.2";
85
+ readonly '@types/node': "^26.4.1";
85
86
  readonly 'cross-env': "10.1.0";
86
87
  readonly lefthook: "^2.1.10";
87
88
  readonly miniflare: "4.20260730.0";
@@ -134,6 +135,7 @@ export declare const ULTRAMODERN_WORKSPACE_POLICY: {
134
135
  readonly rootDevDependencies: {
135
136
  readonly '@effect/tsgo': "0.41.0";
136
137
  readonly '@typescript/native': "npm:typescript@7.0.2";
138
+ readonly '@types/node': "^26.4.1";
137
139
  readonly 'cross-env': "10.1.0";
138
140
  readonly lefthook: "^2.1.10";
139
141
  readonly miniflare: "4.20260730.0";
package/package.json CHANGED
@@ -26,7 +26,7 @@
26
26
  "engines": {
27
27
  "node": ">=26.7.0"
28
28
  },
29
- "version": "3.9.0-ultramodern.2",
29
+ "version": "3.9.0-ultramodern.3",
30
30
  "types": "./dist/types/index.d.ts",
31
31
  "main": "./dist/esm-node/index.js",
32
32
  "bin": {
@@ -82,8 +82,8 @@
82
82
  ],
83
83
  "dependencies": {
84
84
  "@modern-js/codesmith": "2.6.9",
85
- "@modern-js/i18n-utils": "npm:@bleedingdev/modern-js-i18n-utils@3.9.0-ultramodern.2",
86
- "@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.9.0-ultramodern.2",
85
+ "@modern-js/i18n-utils": "npm:@bleedingdev/modern-js-i18n-utils@3.9.0-ultramodern.3",
86
+ "@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.9.0-ultramodern.3",
87
87
  "esbuild": "^0.28.2",
88
88
  "oxfmt": "0.66.0",
89
89
  "ultracite": "7.11.0"
@@ -110,6 +110,6 @@
110
110
  "type-check": "tsgo --noEmit -p tsconfig.json"
111
111
  },
112
112
  "ultramodern": {
113
- "frameworkVersion": "3.9.0-ultramodern.2"
113
+ "frameworkVersion": "3.9.0-ultramodern.3"
114
114
  }
115
115
  }