@bleedingdev/modern-js-create 3.4.0-ultramodern.2 → 3.4.0-ultramodern.20

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 (128) hide show
  1. package/README.md +13 -11
  2. package/dist/cjs/index.cjs +37 -4
  3. package/dist/cjs/locale/en.cjs +12 -2
  4. package/dist/cjs/locale/zh.cjs +12 -2
  5. package/dist/cjs/ultramodern-tooling/commands.cjs +185 -0
  6. package/dist/cjs/ultramodern-tooling/config.cjs +172 -0
  7. package/dist/cjs/ultramodern-workspace/add-vertical.cjs +79 -61
  8. package/dist/cjs/ultramodern-workspace/bridge-config.cjs +327 -0
  9. package/dist/cjs/ultramodern-workspace/codesmith.cjs +1 -0
  10. package/dist/cjs/ultramodern-workspace/contracts.cjs +121 -648
  11. package/dist/cjs/ultramodern-workspace/demo-components.cjs +26 -33
  12. package/dist/cjs/ultramodern-workspace/descriptors.cjs +4 -4
  13. package/dist/cjs/ultramodern-workspace/effect-api.cjs +230 -100
  14. package/dist/cjs/ultramodern-workspace/fs-io.cjs +117 -0
  15. package/dist/cjs/ultramodern-workspace/generation-result.cjs +1 -1
  16. package/dist/cjs/ultramodern-workspace/index.cjs +4 -0
  17. package/dist/cjs/ultramodern-workspace/mf-validation.cjs +571 -0
  18. package/dist/cjs/ultramodern-workspace/module-federation.cjs +51 -20
  19. package/dist/cjs/ultramodern-workspace/package-json.cjs +62 -19
  20. package/dist/cjs/ultramodern-workspace/policy.cjs +2 -2
  21. package/dist/cjs/ultramodern-workspace/public-api.cjs +4 -0
  22. package/dist/cjs/ultramodern-workspace/versions.cjs +5 -0
  23. package/dist/cjs/ultramodern-workspace/workspace-scripts.cjs +80 -43
  24. package/dist/cjs/ultramodern-workspace/write-workspace.cjs +63 -20
  25. package/dist/esm/index.js +37 -4
  26. package/dist/esm/locale/en.js +12 -2
  27. package/dist/esm/locale/zh.js +12 -2
  28. package/dist/esm/ultramodern-tooling/commands.js +132 -0
  29. package/dist/esm/ultramodern-tooling/config.js +120 -0
  30. package/dist/esm/ultramodern-workspace/add-vertical.js +81 -66
  31. package/dist/esm/ultramodern-workspace/bridge-config.js +270 -0
  32. package/dist/esm/ultramodern-workspace/codesmith.js +1 -0
  33. package/dist/esm/ultramodern-workspace/contracts.js +124 -603
  34. package/dist/esm/ultramodern-workspace/demo-components.js +26 -33
  35. package/dist/esm/ultramodern-workspace/descriptors.js +2 -2
  36. package/dist/esm/ultramodern-workspace/effect-api.js +230 -100
  37. package/dist/esm/ultramodern-workspace/fs-io.js +116 -2
  38. package/dist/esm/ultramodern-workspace/generation-result.js +2 -2
  39. package/dist/esm/ultramodern-workspace/index.js +1 -0
  40. package/dist/esm/ultramodern-workspace/mf-validation.js +516 -0
  41. package/dist/esm/ultramodern-workspace/module-federation.js +49 -21
  42. package/dist/esm/ultramodern-workspace/package-json.js +60 -20
  43. package/dist/esm/ultramodern-workspace/policy.js +2 -2
  44. package/dist/esm/ultramodern-workspace/public-api.js +1 -0
  45. package/dist/esm/ultramodern-workspace/versions.js +3 -1
  46. package/dist/esm/ultramodern-workspace/workspace-scripts.js +78 -26
  47. package/dist/esm/ultramodern-workspace/write-workspace.js +67 -27
  48. package/dist/esm-node/index.js +37 -4
  49. package/dist/esm-node/locale/en.js +12 -2
  50. package/dist/esm-node/locale/zh.js +12 -2
  51. package/dist/esm-node/ultramodern-tooling/commands.js +133 -0
  52. package/dist/esm-node/ultramodern-tooling/config.js +121 -0
  53. package/dist/esm-node/ultramodern-workspace/add-vertical.js +81 -66
  54. package/dist/esm-node/ultramodern-workspace/bridge-config.js +271 -0
  55. package/dist/esm-node/ultramodern-workspace/codesmith.js +1 -0
  56. package/dist/esm-node/ultramodern-workspace/contracts.js +124 -603
  57. package/dist/esm-node/ultramodern-workspace/demo-components.js +26 -33
  58. package/dist/esm-node/ultramodern-workspace/descriptors.js +2 -2
  59. package/dist/esm-node/ultramodern-workspace/effect-api.js +230 -100
  60. package/dist/esm-node/ultramodern-workspace/fs-io.js +116 -2
  61. package/dist/esm-node/ultramodern-workspace/generation-result.js +2 -2
  62. package/dist/esm-node/ultramodern-workspace/index.js +1 -0
  63. package/dist/esm-node/ultramodern-workspace/mf-validation.js +517 -0
  64. package/dist/esm-node/ultramodern-workspace/module-federation.js +49 -21
  65. package/dist/esm-node/ultramodern-workspace/package-json.js +60 -20
  66. package/dist/esm-node/ultramodern-workspace/policy.js +2 -2
  67. package/dist/esm-node/ultramodern-workspace/public-api.js +1 -0
  68. package/dist/esm-node/ultramodern-workspace/versions.js +3 -1
  69. package/dist/esm-node/ultramodern-workspace/workspace-scripts.js +78 -26
  70. package/dist/esm-node/ultramodern-workspace/write-workspace.js +67 -27
  71. package/dist/types/locale/en.d.ts +10 -0
  72. package/dist/types/locale/index.d.ts +20 -0
  73. package/dist/types/locale/zh.d.ts +10 -0
  74. package/dist/types/ultramodern-tooling/commands.d.ts +1 -0
  75. package/dist/types/ultramodern-tooling/config.d.ts +43 -0
  76. package/dist/types/ultramodern-workspace/add-vertical.d.ts +5 -2
  77. package/dist/types/ultramodern-workspace/bridge-config.d.ts +64 -0
  78. package/dist/types/ultramodern-workspace/codesmith.d.ts +1 -0
  79. package/dist/types/ultramodern-workspace/contracts.d.ts +2 -17
  80. package/dist/types/ultramodern-workspace/descriptors.d.ts +1 -1
  81. package/dist/types/ultramodern-workspace/fs-io.d.ts +1 -0
  82. package/dist/types/ultramodern-workspace/index.d.ts +2 -0
  83. package/dist/types/ultramodern-workspace/mf-validation.d.ts +27 -0
  84. package/dist/types/ultramodern-workspace/module-federation.d.ts +1 -0
  85. package/dist/types/ultramodern-workspace/package-json.d.ts +5 -3
  86. package/dist/types/ultramodern-workspace/public-api.d.ts +2 -0
  87. package/dist/types/ultramodern-workspace/types.d.ts +2 -0
  88. package/dist/types/ultramodern-workspace/versions.d.ts +2 -0
  89. package/dist/types/ultramodern-workspace/workspace-scripts.d.ts +2 -7
  90. package/dist/types/ultramodern-workspace/write-workspace.d.ts +4 -2
  91. package/package.json +5 -3
  92. package/template-workspace/{.agents → .codex}/skills-lock.json +12 -12
  93. package/template-workspace/.gitignore.handlebars +3 -0
  94. package/template-workspace/AGENTS.md.handlebars +11 -5
  95. package/template-workspace/README.md.handlebars +15 -12
  96. package/template-workspace/oxfmt.config.ts +1 -0
  97. package/template-workspace/oxlint.config.ts +1 -0
  98. package/template-workspace/patches/@tanstack__router-core@1.171.13.patch +51 -0
  99. package/template-workspace/pnpm-workspace.yaml.handlebars +12 -0
  100. package/template-workspace/scripts/bootstrap-agent-skills.mjs +96 -69
  101. package/templates/app/shell-frame.tsx +1 -2
  102. package/templates/app/ultramodern-route-head.tsx.handlebars +5 -6
  103. package/templates/workspace-scripts/assert-mf-types.mjs.handlebars +59 -7
  104. package/templates/workspace-scripts/check-ultramodern-api-boundaries.mjs +339 -0
  105. package/templates/workspace-scripts/generate-public-surface-assets.mjs +245 -8
  106. package/templates/workspace-scripts/proof-cloudflare-version.mjs +276 -8
  107. package/templates/workspace-scripts/ultramodern-cloudflare-proof.mjs +35 -10
  108. package/templates/workspace-scripts/ultramodern-performance-readiness.mjs +164 -1
  109. package/templates/workspace-scripts/ultramodern-typecheck.mjs +4 -2
  110. package/templates/workspace-scripts/validate-ultramodern-workspace.mjs.handlebars +949 -63
  111. /package/template-workspace/{.agents → .codex}/rstackjs-agent-skills-LICENSE +0 -0
  112. /package/template-workspace/{.agents → .codex}/skills/rsbuild-best-practices/SKILL.md +0 -0
  113. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/SKILL.md +0 -0
  114. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/command-map.md +0 -0
  115. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/common-analysis-patterns.md +0 -0
  116. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/install-rsdoctor-common.md +0 -0
  117. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/install-rsdoctor-rspack.md +0 -0
  118. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/install-rsdoctor-webpack.md +0 -0
  119. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/install-rsdoctor.md +0 -0
  120. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/rsdoctor-data-types.md +0 -0
  121. /package/template-workspace/{.agents → .codex}/skills/rslib-best-practices/SKILL.md +0 -0
  122. /package/template-workspace/{.agents → .codex}/skills/rslib-modern-package/SKILL.md +0 -0
  123. /package/template-workspace/{.agents → .codex}/skills/rspack-best-practices/SKILL.md +0 -0
  124. /package/template-workspace/{.agents → .codex}/skills/rspack-tracing/SKILL.md +0 -0
  125. /package/template-workspace/{.agents → .codex}/skills/rspack-tracing/references/bottlenecks.md +0 -0
  126. /package/template-workspace/{.agents → .codex}/skills/rspack-tracing/references/tracing-guide.md +0 -0
  127. /package/template-workspace/{.agents → .codex}/skills/rspack-tracing/scripts/analyze_trace.js +0 -0
  128. /package/template-workspace/{.agents → .codex}/skills/rstest-best-practices/SKILL.md +0 -0
@@ -53,13 +53,13 @@ __webpack_require__.d(__webpack_exports__, {
53
53
  const external_descriptors_cjs_namespaceObject = require("./descriptors.cjs");
54
54
  const external_naming_cjs_namespaceObject = require("./naming.cjs");
55
55
  function verticalEffectApiExport(service) {
56
- return `${(0, external_naming_cjs_namespaceObject.toCamelCase)((0, external_descriptors_cjs_namespaceObject.effectApiStem)(service))}EffectApi`;
56
+ return `${(0, external_naming_cjs_namespaceObject.toCamelCase)((0, external_descriptors_cjs_namespaceObject.effectApiStem)(service))}Api`;
57
57
  }
58
58
  function verticalEffectGroupName(service) {
59
59
  return (0, external_naming_cjs_namespaceObject.toCamelCase)((0, external_descriptors_cjs_namespaceObject.effectApiStem)(service));
60
60
  }
61
61
  function verticalEffectApiName(service) {
62
- return `${(0, external_naming_cjs_namespaceObject.toPascalCase)((0, external_descriptors_cjs_namespaceObject.effectApiStem)(service))}EffectApi`;
62
+ return `${(0, external_naming_cjs_namespaceObject.toPascalCase)((0, external_descriptors_cjs_namespaceObject.effectApiStem)(service))}Api`;
63
63
  }
64
64
  function verticalEffectSchemaExport(service) {
65
65
  return `${(0, external_naming_cjs_namespaceObject.toCamelCase)((0, external_descriptors_cjs_namespaceObject.effectApiStem)(service))}ItemSchema`;
@@ -88,27 +88,51 @@ function serviceHasCheckoutCartState(service) {
88
88
  function createCheckoutCartSharedSchemas(service) {
89
89
  if (!serviceHasCheckoutCartState(service)) return '';
90
90
  return `
91
- export const checkoutCartLineSchema = Schema.Struct({
91
+ export interface CheckoutCartLine {
92
+ readonly sku: string;
93
+ readonly name: string;
94
+ readonly quantity: number;
95
+ readonly unitPriceCents: number;
96
+ }
97
+
98
+ export interface CheckoutCart {
99
+ readonly lines: readonly CheckoutCartLine[];
100
+ readonly subtotalCents: number;
101
+ readonly totalQuantity: number;
102
+ }
103
+
104
+ export interface CheckoutAddCartItemPayload {
105
+ readonly sku: string;
106
+ readonly name?: string;
107
+ readonly quantity: number;
108
+ readonly unitPriceCents?: number;
109
+ }
110
+
111
+ export interface CheckoutRemoveCartItemPayload {
112
+ readonly sku: string;
113
+ }
114
+
115
+ export const checkoutCartLineSchema: Schema.Codec<CheckoutCartLine> = Schema.Struct({
92
116
  sku: Schema.String,
93
117
  name: Schema.String,
94
118
  quantity: Schema.Finite,
95
119
  unitPriceCents: Schema.Finite,
96
120
  });
97
121
 
98
- export const checkoutCartSchema = Schema.Struct({
122
+ export const checkoutCartSchema: Schema.Codec<CheckoutCart> = Schema.Struct({
99
123
  lines: Schema.Array(checkoutCartLineSchema),
100
124
  subtotalCents: Schema.Finite,
101
125
  totalQuantity: Schema.Finite,
102
126
  });
103
127
 
104
- export const checkoutAddCartItemPayloadSchema = Schema.Struct({
128
+ export const checkoutAddCartItemPayloadSchema: Schema.Codec<CheckoutAddCartItemPayload> = Schema.Struct({
105
129
  sku: Schema.String,
106
130
  name: Schema.optional(Schema.String),
107
131
  quantity: Schema.Finite,
108
132
  unitPriceCents: Schema.optional(Schema.Finite),
109
133
  });
110
134
 
111
- export const checkoutRemoveCartItemPayloadSchema = Schema.Struct({
135
+ export const checkoutRemoveCartItemPayloadSchema: Schema.Codec<CheckoutRemoveCartItemPayload> = Schema.Struct({
112
136
  sku: Schema.String,
113
137
  });
114
138
  `;
@@ -117,24 +141,24 @@ function createCheckoutCartEndpointDefinitions(service) {
117
141
  if (!serviceHasCheckoutCartState(service)) return '';
118
142
  return `
119
143
  .add(
120
- HttpApiEndpoint.get('getCart', '/effect/checkout/cart', {
144
+ HttpApiEndpoint.get('getCart', '/checkout/cart', {
121
145
  success: checkoutCartSchema,
122
146
  }),
123
147
  )
124
148
  .add(
125
- HttpApiEndpoint.post('addCartItem', '/effect/checkout/cart/items', {
149
+ HttpApiEndpoint.post('addCartItem', '/checkout/cart/items', {
126
150
  payload: checkoutAddCartItemPayloadSchema,
127
151
  success: checkoutCartSchema,
128
152
  }),
129
153
  )
130
154
  .add(
131
- HttpApiEndpoint.post('removeCartItem', '/effect/checkout/cart/remove', {
155
+ HttpApiEndpoint.post('removeCartItem', '/checkout/cart/remove', {
132
156
  payload: checkoutRemoveCartItemPayloadSchema,
133
157
  success: checkoutCartSchema,
134
158
  }),
135
159
  )
136
160
  .add(
137
- HttpApiEndpoint.post('clearCart', '/effect/checkout/cart/clear', {
161
+ HttpApiEndpoint.post('clearCart', '/checkout/cart/clear', {
138
162
  success: checkoutCartSchema,
139
163
  }),
140
164
  )`;
@@ -147,31 +171,31 @@ function createCheckoutCartOperationContexts(service) {
147
171
  addCartItem: {
148
172
  method: 'POST',
149
173
  operationId: '${apiName}:${groupName}:addCartItem',
150
- routePath: '/effect/checkout/cart/items',
174
+ routePath: '/checkout/cart/items',
151
175
  source: 'generated-client',
152
176
  },
153
177
  clearCart: {
154
178
  method: 'POST',
155
179
  operationId: '${apiName}:${groupName}:clearCart',
156
- routePath: '/effect/checkout/cart/clear',
180
+ routePath: '/checkout/cart/clear',
157
181
  source: 'generated-client',
158
182
  },
159
183
  getCart: {
160
184
  method: 'GET',
161
185
  operationId: '${apiName}:${groupName}:getCart',
162
- routePath: '/effect/checkout/cart',
186
+ routePath: '/checkout/cart',
163
187
  source: 'generated-client',
164
188
  },
165
189
  removeCartItem: {
166
190
  method: 'POST',
167
191
  operationId: '${apiName}:${groupName}:removeCartItem',
168
- routePath: '/effect/checkout/cart/remove',
192
+ routePath: '/checkout/cart/remove',
169
193
  source: 'generated-client',
170
194
  },`;
171
195
  }
172
196
  function createCheckoutCartApiContractFields(service) {
173
197
  if (!serviceHasCheckoutCartState(service)) return '';
174
- return ` checkoutCartPath: '${(0, external_descriptors_cjs_namespaceObject.effectApiPrefix)(service)}/effect/checkout/cart',
198
+ return ` checkoutCartPath: '${(0, external_descriptors_cjs_namespaceObject.effectApiPrefix)(service)}/checkout/cart',
175
199
  `;
176
200
  }
177
201
  function createCheckoutCartServerState(service) {
@@ -207,7 +231,7 @@ function createCheckoutCartServerHandlers(service) {
207
231
  return `
208
232
  .handle('getCart', () =>
209
233
  Effect.sync(() => createCheckoutCartSnapshot()).pipe(
210
- Effect.withSpan('ultramodern.effect.${groupName}.checkout.getCart', {
234
+ Effect.withSpan('ultramodern.api.${groupName}.checkout.getCart', {
211
235
  attributes: operationAttributes(${groupName}OperationContexts.getCart),
212
236
  kind: 'server',
213
237
  }),
@@ -225,7 +249,7 @@ function createCheckoutCartServerHandlers(service) {
225
249
  });
226
250
  return createCheckoutCartSnapshot();
227
251
  }).pipe(
228
- Effect.withSpan('ultramodern.effect.${groupName}.checkout.addCartItem', {
252
+ Effect.withSpan('ultramodern.api.${groupName}.checkout.addCartItem', {
229
253
  attributes: operationAttributes(${groupName}OperationContexts.addCartItem),
230
254
  kind: 'server',
231
255
  }),
@@ -236,7 +260,7 @@ function createCheckoutCartServerHandlers(service) {
236
260
  checkoutCartLines.delete(payload.sku);
237
261
  return createCheckoutCartSnapshot();
238
262
  }).pipe(
239
- Effect.withSpan('ultramodern.effect.${groupName}.checkout.removeCartItem', {
263
+ Effect.withSpan('ultramodern.api.${groupName}.checkout.removeCartItem', {
240
264
  attributes: operationAttributes(${groupName}OperationContexts.removeCartItem),
241
265
  kind: 'server',
242
266
  }),
@@ -247,7 +271,7 @@ function createCheckoutCartServerHandlers(service) {
247
271
  checkoutCartLines.clear();
248
272
  return createCheckoutCartSnapshot();
249
273
  }).pipe(
250
- Effect.withSpan('ultramodern.effect.${groupName}.checkout.clearCart', {
274
+ Effect.withSpan('ultramodern.api.${groupName}.checkout.clearCart', {
251
275
  attributes: operationAttributes(${groupName}OperationContexts.clearCart),
252
276
  kind: 'server',
253
277
  }),
@@ -261,6 +285,7 @@ function createCheckoutCartClientExports(service) {
261
285
  const pascalStem = (0, external_naming_cjs_namespaceObject.toPascalCase)(stem);
262
286
  const clientOptionsName = `${pascalStem}ClientOptions`;
263
287
  const createClientName = `create${pascalStem}Client`;
288
+ const clientEffectTypeName = `${pascalStem}ClientEffect`;
264
289
  return `
265
290
  export interface CheckoutCartLine {
266
291
  sku: string;
@@ -284,7 +309,7 @@ export interface CheckoutAddCartItemInput {
284
309
 
285
310
  export const getCheckoutCart = (
286
311
  options: ${clientOptionsName} = {},
287
- ) =>
312
+ ): ${clientEffectTypeName}<CheckoutCart> =>
288
313
  ${createClientName}({
289
314
  ...options,
290
315
  operationContext:
@@ -296,7 +321,7 @@ export const getCheckoutCart = (
296
321
  export const addCheckoutCartItem = (
297
322
  payload: CheckoutAddCartItemInput,
298
323
  options: ${clientOptionsName} = {},
299
- ) =>
324
+ ): ${clientEffectTypeName}<CheckoutCart> =>
300
325
  ${createClientName}({
301
326
  ...options,
302
327
  operationContext:
@@ -310,7 +335,7 @@ export const addCheckoutCartItem = (
310
335
  export const removeCheckoutCartItem = (
311
336
  sku: string,
312
337
  options: ${clientOptionsName} = {},
313
- ) =>
338
+ ): ${clientEffectTypeName}<CheckoutCart> =>
314
339
  ${createClientName}({
315
340
  ...options,
316
341
  operationContext:
@@ -323,7 +348,7 @@ export const removeCheckoutCartItem = (
323
348
 
324
349
  export const clearCheckoutCart = (
325
350
  options: ${clientOptionsName} = {},
326
- ) =>
351
+ ): ${clientEffectTypeName}<CheckoutCart> =>
327
352
  ${createClientName}({
328
353
  ...options,
329
354
  operationContext:
@@ -354,12 +379,63 @@ function createEffectSharedApiContract(service) {
354
379
  const apiName = verticalEffectApiName(service);
355
380
  const groupName = verticalEffectGroupName(service);
356
381
  const stem = (0, external_descriptors_cjs_namespaceObject.effectApiStem)(service);
382
+ const pascalStem = (0, external_naming_cjs_namespaceObject.toPascalCase)(stem);
383
+ const markerType = `${pascalStem}Marker`;
384
+ const itemType = `${pascalStem}Item`;
385
+ const readinessType = `${pascalStem}Readiness`;
386
+ const createPayloadType = `${pascalStem}CreatePayload`;
387
+ const createResponseType = `${pascalStem}CreateResponse`;
388
+ const listResponseType = `${pascalStem}ListResponse`;
357
389
  const apiPrefix = (0, external_descriptors_cjs_namespaceObject.effectApiPrefix)(service);
358
390
  const checkoutCartSharedSchemas = createCheckoutCartSharedSchemas(service);
359
391
  const checkoutCartSharedSchemaSection = '' === checkoutCartSharedSchemas ? '' : `${checkoutCartSharedSchemas}\n`;
360
392
  const checkoutCartOperationContexts = createCheckoutCartOperationContexts(service).trimStart();
361
393
  const checkoutCartOperationContextEntries = '' === checkoutCartOperationContexts ? '' : `${checkoutCartOperationContexts}\n`;
362
- return `export const ${markerSchemaExport} = Schema.Struct({
394
+ return `export interface ${markerType} {
395
+ readonly appId: string;
396
+ readonly build: string;
397
+ readonly deployProfile: string;
398
+ readonly packageName: string;
399
+ readonly surface: string;
400
+ readonly version: string;
401
+ }
402
+
403
+ export interface ${itemType} {
404
+ readonly id: string;
405
+ readonly marker: ${markerType};
406
+ readonly title: string;
407
+ }
408
+
409
+ export interface ${readinessType} {
410
+ readonly checks: {
411
+ readonly api: 'ready';
412
+ readonly moduleFederation: 'ready';
413
+ readonly ssr: 'ready';
414
+ readonly translations: 'ready';
415
+ };
416
+ readonly marker: ${markerType};
417
+ readonly status: 'ready';
418
+ readonly versionSkew: 'none';
419
+ }
420
+
421
+ export interface ${createPayloadType} {
422
+ readonly title: string;
423
+ }
424
+
425
+ export interface ${listResponseType} {
426
+ readonly items: readonly ${itemType}[];
427
+ }
428
+
429
+ export interface ${createResponseType} {
430
+ readonly item: ${itemType};
431
+ }
432
+
433
+ export interface ${notFoundErrorExport} {
434
+ readonly _tag: '${notFoundErrorExport}';
435
+ readonly id: string;
436
+ }
437
+
438
+ export const ${markerSchemaExport}: Schema.Codec<${markerType}> = Schema.Struct({
363
439
  appId: Schema.String,
364
440
  build: Schema.String,
365
441
  deployProfile: Schema.String,
@@ -368,15 +444,15 @@ function createEffectSharedApiContract(service) {
368
444
  version: Schema.String,
369
445
  });
370
446
 
371
- export const ${schemaExport} = Schema.Struct({
447
+ export const ${schemaExport}: Schema.Codec<${itemType}> = Schema.Struct({
372
448
  id: Schema.String,
373
449
  marker: ${markerSchemaExport},
374
450
  title: Schema.String,
375
451
  });
376
452
 
377
- export const ${readinessSchemaExport} = Schema.Struct({
453
+ export const ${readinessSchemaExport}: Schema.Codec<${readinessType}> = Schema.Struct({
378
454
  checks: Schema.Struct({
379
- effectBff: Schema.Literal('ready'),
455
+ api: Schema.Literal('ready'),
380
456
  moduleFederation: Schema.Literal('ready'),
381
457
  ssr: Schema.Literal('ready'),
382
458
  translations: Schema.Literal('ready'),
@@ -386,18 +462,13 @@ export const ${readinessSchemaExport} = Schema.Struct({
386
462
  versionSkew: Schema.Literal('none'),
387
463
  });
388
464
 
389
- export const ${createPayloadSchemaExport} = Schema.Struct({
465
+ export const ${createPayloadSchemaExport}: Schema.Codec<${createPayloadType}> = Schema.Struct({
390
466
  title: Schema.String,
391
467
  });
392
468
 
393
- ${checkoutCartSharedSchemaSection}export class ${notFoundErrorExport} extends Schema.TaggedErrorClass<${notFoundErrorExport}>()(
394
- '${notFoundErrorExport}',
395
- {
396
- id: Schema.String,
397
- },
398
- ) {}
399
-
400
- export const ${notFoundSchemaExport} = ${notFoundErrorExport}.pipe(
469
+ ${checkoutCartSharedSchemaSection}export const ${notFoundSchemaExport}: Schema.Codec<${notFoundErrorExport}> = Schema.TaggedStruct('${notFoundErrorExport}', {
470
+ id: Schema.String,
471
+ }).pipe(
401
472
  HttpApiSchema.status(404),
402
473
  );
403
474
 
@@ -418,7 +489,7 @@ export interface OperationContext {
418
489
  export const ${apiExport} = HttpApi.make('${apiName}').add(
419
490
  HttpApiGroup.make('${groupName}')
420
491
  .add(
421
- HttpApiEndpoint.get('list', '/effect/${stem}', {
492
+ HttpApiEndpoint.get('list', '/${stem}', {
422
493
  query: {
423
494
  limit: Schema.optional(Schema.FiniteFromString),
424
495
  },
@@ -428,12 +499,12 @@ export const ${apiExport} = HttpApi.make('${apiName}').add(
428
499
  }),
429
500
  )
430
501
  .add(
431
- HttpApiEndpoint.get('readiness', '/effect/${stem}/readiness', {
502
+ HttpApiEndpoint.get('readiness', '/${stem}/readiness', {
432
503
  success: ${readinessSchemaExport},
433
504
  }),
434
505
  )
435
506
  .add(
436
- HttpApiEndpoint.get('get', '/effect/${stem}/:id', {
507
+ HttpApiEndpoint.get('get', '/${stem}/:id', {
437
508
  error: ${notFoundSchemaExport},
438
509
  params: {
439
510
  id: Schema.String,
@@ -442,7 +513,7 @@ export const ${apiExport} = HttpApi.make('${apiName}').add(
442
513
  }),
443
514
  )
444
515
  .add(
445
- HttpApiEndpoint.post('create', '/effect/${stem}', {
516
+ HttpApiEndpoint.post('create', '/${stem}', {
446
517
  payload: ${createPayloadSchemaExport},
447
518
  success: Schema.Struct({
448
519
  item: ${schemaExport},
@@ -455,34 +526,34 @@ export const ${groupName}OperationContexts = {
455
526
  ${checkoutCartOperationContextEntries} create: {
456
527
  method: 'POST',
457
528
  operationId: '${apiName}:${groupName}:create',
458
- routePath: '/effect/${stem}',
529
+ routePath: '/${stem}',
459
530
  source: 'generated-client',
460
531
  },
461
532
  get: {
462
533
  method: 'GET',
463
534
  operationId: '${apiName}:${groupName}:get',
464
- routePath: '/effect/${stem}/:id',
535
+ routePath: '/${stem}/:id',
465
536
  source: 'generated-client',
466
537
  },
467
538
  list: {
468
539
  method: 'GET',
469
540
  operationId: '${apiName}:${groupName}:list',
470
- routePath: '/effect/${stem}',
541
+ routePath: '/${stem}',
471
542
  source: 'generated-client',
472
543
  },
473
544
  readiness: {
474
545
  method: 'GET',
475
546
  operationId: '${apiName}:${groupName}:readiness',
476
- routePath: '/effect/${stem}/readiness',
547
+ routePath: '/${stem}/readiness',
477
548
  source: 'generated-client',
478
549
  },
479
550
  } satisfies Record<string, OperationContext>;
480
551
 
481
552
  export const ${groupName}ApiContract = {
482
553
  apiPrefix: '${apiPrefix}',
483
- basePath: '${apiPrefix}/effect/${stem}',
554
+ basePath: '${apiPrefix}/${stem}',
484
555
  ${createCheckoutCartApiContractFields(service)} ownerId: '${service.id}',
485
- readinessPath: '${apiPrefix}/effect/${stem}/readiness',
556
+ readinessPath: '${apiPrefix}/${stem}/readiness',
486
557
  } as const;
487
558
  `;
488
559
  }
@@ -501,13 +572,20 @@ function createEffectServiceEntry(service, contractImportPath) {
501
572
  HttpApiBuilder,
502
573
  Layer,
503
574
  } from '@modern-js/plugin-bff/effect-edge';
504
- import { ultramodernApiMarker } from '../../src/ultramodern-build.ts';
575
+ import type {
576
+ EffectBffDefinition,
577
+ EffectBffRuntime,
578
+ EffectRuntimeLayer,
579
+ } from '@modern-js/plugin-bff/effect-edge';
580
+ import { ultramodernApiMarker } from '../shared/ultramodern-build.ts';
505
581
  import {
506
582
  ${apiExport},
507
583
  ${groupName}OperationContexts,
584
+ } from '${contractImportPath}';
585
+ import type {
508
586
  ${notFoundErrorExport},
587
+ OperationContext,
509
588
  } from '${contractImportPath}';
510
- import type { OperationContext } from '${contractImportPath}';
511
589
 
512
590
  const ${groupName}Items = [
513
591
  {
@@ -540,7 +618,7 @@ const ${groupName}Layer = HttpApiBuilder.group(
540
618
  ? ${groupName}Items.slice(0, query.limit)
541
619
  : ${groupName}Items,
542
620
  }).pipe(
543
- Effect.withSpan('ultramodern.effect.${groupName}.list', {
621
+ Effect.withSpan('ultramodern.api.${groupName}.list', {
544
622
  attributes: operationAttributes(${groupName}OperationContexts.list),
545
623
  kind: 'server',
546
624
  }),
@@ -549,7 +627,7 @@ const ${groupName}Layer = HttpApiBuilder.group(
549
627
  .handle('readiness', () =>
550
628
  Effect.succeed({
551
629
  checks: {
552
- effectBff: 'ready' as const,
630
+ api: 'ready' as const,
553
631
  moduleFederation: 'ready' as const,
554
632
  ssr: 'ready' as const,
555
633
  translations: 'ready' as const,
@@ -558,7 +636,7 @@ const ${groupName}Layer = HttpApiBuilder.group(
558
636
  status: 'ready' as const,
559
637
  versionSkew: 'none' as const,
560
638
  }).pipe(
561
- Effect.withSpan('ultramodern.effect.${groupName}.readiness', {
639
+ Effect.withSpan('ultramodern.api.${groupName}.readiness', {
562
640
  attributes: operationAttributes(${groupName}OperationContexts.readiness),
563
641
  kind: 'server',
564
642
  }),
@@ -568,13 +646,17 @@ const ${groupName}Layer = HttpApiBuilder.group(
568
646
  const matchedItem = ${groupName}Items.find(
569
647
  candidate => candidate.id === params.id,
570
648
  );
649
+ const notFound: ${notFoundErrorExport} = {
650
+ _tag: '${notFoundErrorExport}',
651
+ id: params.id,
652
+ };
571
653
  const result =
572
654
  matchedItem === undefined
573
- ? Effect.fail(new ${notFoundErrorExport}({ id: params.id }))
655
+ ? Effect.fail(notFound)
574
656
  : Effect.succeed(matchedItem);
575
657
 
576
658
  return result.pipe(
577
- Effect.withSpan('ultramodern.effect.${groupName}.get', {
659
+ Effect.withSpan('ultramodern.api.${groupName}.get', {
578
660
  attributes: operationAttributes(${groupName}OperationContexts.get),
579
661
  kind: 'server',
580
662
  }),
@@ -591,7 +673,7 @@ const ${groupName}Layer = HttpApiBuilder.group(
591
673
  title: payload.title,
592
674
  },
593
675
  }).pipe(
594
- Effect.withSpan('ultramodern.effect.${groupName}.create', {
676
+ Effect.withSpan('ultramodern.api.${groupName}.create', {
595
677
  attributes: operationAttributes(${groupName}OperationContexts.create),
596
678
  kind: 'server',
597
679
  }),
@@ -601,12 +683,15 @@ const ${groupName}Layer = HttpApiBuilder.group(
601
683
 
602
684
  const layer = HttpApiBuilder.layer(${apiExport}).pipe(
603
685
  Layer.provide(${groupName}Layer),
604
- );
686
+ ) satisfies EffectRuntimeLayer;
605
687
 
606
- export default defineEffectBff({
688
+ const apiRuntime: EffectBffDefinition<typeof ${apiExport}, EffectRuntimeLayer> &
689
+ EffectBffRuntime<typeof ${apiExport}, EffectRuntimeLayer> = defineEffectBff({
607
690
  api: ${apiExport},
608
691
  layer,
609
692
  });
693
+
694
+ export default apiRuntime;
610
695
  `;
611
696
  }
612
697
  function createEffectClient(service, contractImportPath) {
@@ -617,25 +702,71 @@ function createEffectClient(service, contractImportPath) {
617
702
  const singular = verticalEffectErrorStem(service);
618
703
  const clientOptionsName = `${(0, external_naming_cjs_namespaceObject.toPascalCase)(stem)}ClientOptions`;
619
704
  const createClientName = `create${(0, external_naming_cjs_namespaceObject.toPascalCase)(stem)}Client`;
705
+ const clientTypeName = `${(0, external_naming_cjs_namespaceObject.toPascalCase)(stem)}Client`;
706
+ const clientEffectTypeName = `${(0, external_naming_cjs_namespaceObject.toPascalCase)(stem)}ClientEffect`;
620
707
  const listName = `list${(0, external_naming_cjs_namespaceObject.toPascalCase)(stem)}`;
621
708
  const readinessName = `get${(0, external_naming_cjs_namespaceObject.toPascalCase)(stem)}Readiness`;
622
709
  const getName = `get${(0, external_naming_cjs_namespaceObject.toPascalCase)(singular)}`;
623
710
  const createName = `create${(0, external_naming_cjs_namespaceObject.toPascalCase)(singular)}`;
711
+ const notFoundErrorExport = verticalEffectNotFoundErrorExport(service);
712
+ const pascalStem = (0, external_naming_cjs_namespaceObject.toPascalCase)(stem);
713
+ const itemType = `${pascalStem}Item`;
714
+ const readinessType = `${pascalStem}Readiness`;
715
+ const createResponseType = `${pascalStem}CreateResponse`;
716
+ const listResponseType = `${pascalStem}ListResponse`;
624
717
  const checkoutCartClientExports = createCheckoutCartClientExports(service);
625
718
  return `import {
626
719
  Effect,
627
720
  makeEffectHttpApiClient,
628
721
  runEffectRequest,
629
722
  } from '@modern-js/plugin-bff/effect-client';
723
+ import type {
724
+ HttpClientError,
725
+ HttpApi,
726
+ HttpApiClient,
727
+ HttpApiGroup,
728
+ Schema,
729
+ } from '@modern-js/plugin-bff/effect-client';
630
730
  import {
631
731
  ${contractExport}ApiContract,
632
732
  ${apiExport},
633
733
  ${groupName}OperationContexts,
634
734
  } from '${contractImportPath}';
635
- import type { OperationContext } from '${contractImportPath}';
735
+ import type {
736
+ ${createResponseType},
737
+ ${itemType},
738
+ ${listResponseType},
739
+ ${notFoundErrorExport},
740
+ OperationContext,
741
+ ${readinessType},
742
+ } from '${contractImportPath}';
636
743
 
637
744
  export { Effect, runEffectRequest };
638
745
 
746
+ type ${pascalStem}ApiGroups = typeof ${apiExport} extends HttpApi.HttpApi<
747
+ infer _ApiId,
748
+ infer Groups
749
+ >
750
+ ? Groups
751
+ : never;
752
+
753
+ export type ${clientTypeName} = HttpApiClient.Client<
754
+ Extract<${pascalStem}ApiGroups, HttpApiGroup.Any>,
755
+ never,
756
+ never
757
+ >;
758
+
759
+ export type ${pascalStem}ClientError =
760
+ | ${notFoundErrorExport}
761
+ | HttpClientError.HttpClientError
762
+ | Schema.SchemaError;
763
+
764
+ export type ${clientEffectTypeName}<Success> = Effect.Effect<
765
+ Success,
766
+ ${pascalStem}ClientError,
767
+ never
768
+ >;
769
+
639
770
  export interface ${clientOptionsName} {
640
771
  baseUrl?: string | URL;
641
772
  locale?: string;
@@ -645,7 +776,7 @@ export interface ${clientOptionsName} {
645
776
 
646
777
  export const ${createClientName} = (
647
778
  options: ${clientOptionsName} = {},
648
- ) =>
779
+ ): ${clientEffectTypeName}<${clientTypeName}> =>
649
780
  makeEffectHttpApiClient(${apiExport}, {
650
781
  baseUrl: options.baseUrl ?? ${contractExport}ApiContract.apiPrefix,
651
782
  requestContext: {
@@ -661,7 +792,7 @@ export const ${createClientName} = (
661
792
 
662
793
  export const ${listName} = (
663
794
  options: ${clientOptionsName} & { limit?: number } = {},
664
- ) =>
795
+ ): ${clientEffectTypeName}<${listResponseType}> =>
665
796
  ${createClientName}({
666
797
  ...options,
667
798
  operationContext:
@@ -674,7 +805,7 @@ export const ${listName} = (
674
805
 
675
806
  export const ${readinessName} = (
676
807
  options: ${clientOptionsName} = {},
677
- ) =>
808
+ ): ${clientEffectTypeName}<${readinessType}> =>
678
809
  ${createClientName}({
679
810
  ...options,
680
811
  operationContext:
@@ -686,7 +817,7 @@ export const ${readinessName} = (
686
817
  export const ${getName} = (
687
818
  id: string,
688
819
  options: ${clientOptionsName} = {},
689
- ) =>
820
+ ): ${clientEffectTypeName}<${itemType}> =>
690
821
  ${createClientName}({
691
822
  ...options,
692
823
  operationContext:
@@ -698,7 +829,7 @@ export const ${getName} = (
698
829
  export const ${createName} = (
699
830
  title: string,
700
831
  options: ${clientOptionsName} = {},
701
- ) =>
832
+ ): ${clientEffectTypeName}<${createResponseType}> =>
702
833
  ${createClientName}({
703
834
  ...options,
704
835
  operationContext:
@@ -730,7 +861,7 @@ ${checkoutCartExports} create${pascalSingular},
730
861
  get${pascalStem}Readiness,
731
862
  list${pascalStem},
732
863
  type ${pascalStem}ClientOptions,
733
- } from '${(0, external_naming_cjs_namespaceObject.packageName)(scope, remote.packageSuffix)}/effect/client';`;
864
+ } from '${(0, external_naming_cjs_namespaceObject.packageName)(scope, remote.packageSuffix)}/api/client';`;
734
865
  }).join('\n\n');
735
866
  return exports1 ? `${exports1}\n` : `export const ultramodernVerticalClients = [] as const;
736
867
  `;
@@ -738,7 +869,7 @@ ${checkoutCartExports} create${pascalSingular},
738
869
  function createEffectReadinessContract(app) {
739
870
  const stem = (0, external_descriptors_cjs_namespaceObject.effectApiStem)(app);
740
871
  return {
741
- endpoint: `/effect/${stem}/readiness`,
872
+ endpoint: `/${stem}/readiness`,
742
873
  marker: {
743
874
  ui: 'ultramodernUiMarker',
744
875
  api: 'ultramodernApiMarker',
@@ -748,7 +879,7 @@ function createEffectReadinessContract(app) {
748
879
  'moduleFederation',
749
880
  'ssr',
750
881
  'translations',
751
- 'effectBff'
882
+ 'api'
752
883
  ]
753
884
  };
754
885
  }
@@ -763,39 +894,39 @@ function createEffectRequestContextContract() {
763
894
  'x-ultramodern-env',
764
895
  'x-vertical-version-id'
765
896
  ],
766
- source: 'shell-to-vertical-effect-client'
897
+ source: 'shell-to-vertical-api-client'
767
898
  };
768
899
  }
769
900
  function createEffectDomainOperations(app) {
770
901
  const stem = (0, external_descriptors_cjs_namespaceObject.effectApiStem)(app);
771
902
  const group = verticalEffectGroupName(app);
772
- const basePath = `/effect/${stem}`;
903
+ const basePath = `/${stem}`;
773
904
  const checkoutCartOperations = serviceHasCheckoutCartState(app) ? {
774
905
  checkoutCartAddItem: {
775
906
  client: 'addCheckoutCartItem',
776
907
  method: 'POST',
777
- path: '/effect/checkout/cart/items',
908
+ path: '/checkout/cart/items',
778
909
  resource: 'checkout-cart',
779
910
  owner: app.id
780
911
  },
781
912
  checkoutCartClear: {
782
913
  client: 'clearCheckoutCart',
783
914
  method: 'POST',
784
- path: '/effect/checkout/cart/clear',
915
+ path: '/checkout/cart/clear',
785
916
  resource: 'checkout-cart',
786
917
  owner: app.id
787
918
  },
788
919
  checkoutCartRead: {
789
920
  client: 'getCheckoutCart',
790
921
  method: 'GET',
791
- path: '/effect/checkout/cart',
922
+ path: '/checkout/cart',
792
923
  resource: 'checkout-cart',
793
924
  owner: app.id
794
925
  },
795
926
  checkoutCartRemoveItem: {
796
927
  client: 'removeCheckoutCartItem',
797
928
  method: 'POST',
798
- path: '/effect/checkout/cart/remove',
929
+ path: '/checkout/cart/remove',
799
930
  resource: 'checkout-cart',
800
931
  owner: app.id
801
932
  }
@@ -828,27 +959,26 @@ function createEffectDomainOperations(app) {
828
959
  function effectApiTopologyMetadata(app) {
829
960
  if (!(0, external_descriptors_cjs_namespaceObject.appHasEffectApi)(app)) return;
830
961
  return {
831
- effect: {
832
- runtime: 'effect',
833
- bff: {
834
- prefix: app.effectApi.prefix,
835
- openapi: '/openapi.json'
836
- },
837
- contract: {
838
- export: './shared/effect/api',
839
- path: `${app.directory}/shared/effect/api.ts`
840
- },
841
- client: {
842
- export: './effect/client',
843
- path: `${app.directory}/src/effect/${app.effectApi.stem}-client.ts`
844
- },
845
- serverEntry: `${app.directory}/api/effect/index.ts`,
846
- basePath: `${app.effectApi.prefix}/effect/${app.effectApi.stem}`,
847
- consumedBy: app.effectApi.consumedBy,
848
- readiness: createEffectReadinessContract(app),
849
- requestContext: createEffectRequestContextContract(),
850
- domainOperations: createEffectDomainOperations(app)
851
- }
962
+ runtime: 'effect',
963
+ bff: {
964
+ prefix: app.effectApi.prefix,
965
+ openapi: '/openapi.json',
966
+ strictEffectApproach: true
967
+ },
968
+ contract: {
969
+ export: './api',
970
+ path: `${app.directory}/shared/api.ts`
971
+ },
972
+ client: {
973
+ export: './api/client',
974
+ path: `${app.directory}/src/api/${app.effectApi.stem}-client.ts`
975
+ },
976
+ serverEntry: `${app.directory}/api/index.ts`,
977
+ basePath: `${app.effectApi.prefix}/${app.effectApi.stem}`,
978
+ consumedBy: app.effectApi.consumedBy,
979
+ readiness: createEffectReadinessContract(app),
980
+ requestContext: createEffectRequestContextContract(),
981
+ domainOperations: createEffectDomainOperations(app)
852
982
  };
853
983
  }
854
984
  function createEffectOperationContract(target) {
@@ -856,22 +986,22 @@ function createEffectOperationContract(target) {
856
986
  const checkoutCartOperations = serviceHasCheckoutCartState(target) ? {
857
987
  addCartItem: {
858
988
  method: 'POST',
859
- path: '/effect/checkout/cart/items',
989
+ path: '/checkout/cart/items',
860
990
  source: 'generated-client'
861
991
  },
862
992
  clearCart: {
863
993
  method: 'POST',
864
- path: '/effect/checkout/cart/clear',
994
+ path: '/checkout/cart/clear',
865
995
  source: 'generated-client'
866
996
  },
867
997
  getCart: {
868
998
  method: 'GET',
869
- path: '/effect/checkout/cart',
999
+ path: '/checkout/cart',
870
1000
  source: 'generated-client'
871
1001
  },
872
1002
  removeCartItem: {
873
1003
  method: 'POST',
874
- path: '/effect/checkout/cart/remove',
1004
+ path: '/checkout/cart/remove',
875
1005
  source: 'generated-client'
876
1006
  }
877
1007
  } : {};
@@ -882,22 +1012,22 @@ function createEffectOperationContract(target) {
882
1012
  ...checkoutCartOperations,
883
1013
  list: {
884
1014
  method: 'GET',
885
- path: `/effect/${stem}`,
1015
+ path: `/${stem}`,
886
1016
  source: 'generated-client'
887
1017
  },
888
1018
  readiness: {
889
1019
  method: 'GET',
890
- path: `/effect/${stem}/readiness`,
1020
+ path: `/${stem}/readiness`,
891
1021
  source: 'generated-client'
892
1022
  },
893
1023
  get: {
894
1024
  method: 'GET',
895
- path: `/effect/${stem}/:id`,
1025
+ path: `/${stem}/:id`,
896
1026
  source: 'generated-client'
897
1027
  },
898
1028
  create: {
899
1029
  method: 'POST',
900
- path: `/effect/${stem}`,
1030
+ path: `/${stem}`,
901
1031
  source: 'generated-client'
902
1032
  }
903
1033
  }