@bleedingdev/modern-js-create 3.4.0-ultramodern.19 → 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.
- package/dist/cjs/index.cjs +1 -1
- package/dist/cjs/locale/en.cjs +2 -2
- package/dist/cjs/locale/zh.cjs +2 -2
- package/dist/cjs/ultramodern-tooling/config.cjs +9 -91
- package/dist/cjs/ultramodern-workspace/add-vertical.cjs +13 -40
- package/dist/cjs/ultramodern-workspace/contracts.cjs +2 -0
- package/dist/cjs/ultramodern-workspace/demo-components.cjs +12 -12
- package/dist/cjs/ultramodern-workspace/descriptors.cjs +0 -4
- package/dist/cjs/ultramodern-workspace/effect-api.cjs +74 -75
- package/dist/cjs/ultramodern-workspace/mf-validation.cjs +1 -2
- package/dist/cjs/ultramodern-workspace/module-federation.cjs +3 -2
- package/dist/cjs/ultramodern-workspace/package-json.cjs +6 -5
- package/dist/cjs/ultramodern-workspace/policy.cjs +1 -1
- package/dist/cjs/ultramodern-workspace/workspace-scripts.cjs +7 -0
- package/dist/cjs/ultramodern-workspace/write-workspace.cjs +4 -4
- package/dist/esm/index.js +1 -1
- package/dist/esm/locale/en.js +2 -2
- package/dist/esm/locale/zh.js +2 -2
- package/dist/esm/ultramodern-tooling/config.js +10 -92
- package/dist/esm/ultramodern-workspace/add-vertical.js +14 -41
- package/dist/esm/ultramodern-workspace/contracts.js +2 -0
- package/dist/esm/ultramodern-workspace/demo-components.js +12 -12
- package/dist/esm/ultramodern-workspace/descriptors.js +1 -2
- package/dist/esm/ultramodern-workspace/effect-api.js +74 -75
- package/dist/esm/ultramodern-workspace/mf-validation.js +1 -2
- package/dist/esm/ultramodern-workspace/module-federation.js +3 -2
- package/dist/esm/ultramodern-workspace/package-json.js +6 -5
- package/dist/esm/ultramodern-workspace/policy.js +1 -1
- package/dist/esm/ultramodern-workspace/workspace-scripts.js +5 -1
- package/dist/esm/ultramodern-workspace/write-workspace.js +4 -4
- package/dist/esm-node/index.js +1 -1
- package/dist/esm-node/locale/en.js +2 -2
- package/dist/esm-node/locale/zh.js +2 -2
- package/dist/esm-node/ultramodern-tooling/config.js +10 -92
- package/dist/esm-node/ultramodern-workspace/add-vertical.js +14 -41
- package/dist/esm-node/ultramodern-workspace/contracts.js +2 -0
- package/dist/esm-node/ultramodern-workspace/demo-components.js +12 -12
- package/dist/esm-node/ultramodern-workspace/descriptors.js +1 -2
- package/dist/esm-node/ultramodern-workspace/effect-api.js +74 -75
- package/dist/esm-node/ultramodern-workspace/mf-validation.js +1 -2
- package/dist/esm-node/ultramodern-workspace/module-federation.js +3 -2
- package/dist/esm-node/ultramodern-workspace/package-json.js +6 -5
- package/dist/esm-node/ultramodern-workspace/policy.js +1 -1
- package/dist/esm-node/ultramodern-workspace/workspace-scripts.js +5 -1
- package/dist/esm-node/ultramodern-workspace/write-workspace.js +4 -4
- package/dist/types/ultramodern-tooling/config.d.ts +1 -2
- package/dist/types/ultramodern-workspace/descriptors.d.ts +0 -1
- package/dist/types/ultramodern-workspace/workspace-scripts.d.ts +1 -0
- package/package.json +3 -3
- package/templates/workspace-scripts/assert-mf-types.mjs.handlebars +1 -11
- package/templates/workspace-scripts/check-ultramodern-api-boundaries.mjs +339 -0
- package/templates/workspace-scripts/generate-public-surface-assets.mjs +14 -12
- package/templates/workspace-scripts/proof-cloudflare-version.mjs +3 -13
- package/templates/workspace-scripts/ultramodern-cloudflare-proof.mjs +3 -3
- package/templates/workspace-scripts/ultramodern-performance-readiness.mjs +1 -9
- package/templates/workspace-scripts/validate-ultramodern-workspace.mjs.handlebars +82 -86
|
@@ -2,13 +2,13 @@ import "node:module";
|
|
|
2
2
|
import { appHasEffectApi, effectApiPrefix, effectApiStem, verticalEffectApps } from "./descriptors.js";
|
|
3
3
|
import { packageName, toCamelCase, toPascalCase } from "./naming.js";
|
|
4
4
|
function verticalEffectApiExport(service) {
|
|
5
|
-
return `${toCamelCase(effectApiStem(service))}
|
|
5
|
+
return `${toCamelCase(effectApiStem(service))}Api`;
|
|
6
6
|
}
|
|
7
7
|
function verticalEffectGroupName(service) {
|
|
8
8
|
return toCamelCase(effectApiStem(service));
|
|
9
9
|
}
|
|
10
10
|
function verticalEffectApiName(service) {
|
|
11
|
-
return `${toPascalCase(effectApiStem(service))}
|
|
11
|
+
return `${toPascalCase(effectApiStem(service))}Api`;
|
|
12
12
|
}
|
|
13
13
|
function verticalEffectSchemaExport(service) {
|
|
14
14
|
return `${toCamelCase(effectApiStem(service))}ItemSchema`;
|
|
@@ -90,24 +90,24 @@ function createCheckoutCartEndpointDefinitions(service) {
|
|
|
90
90
|
if (!serviceHasCheckoutCartState(service)) return '';
|
|
91
91
|
return `
|
|
92
92
|
.add(
|
|
93
|
-
HttpApiEndpoint.get('getCart', '/
|
|
93
|
+
HttpApiEndpoint.get('getCart', '/checkout/cart', {
|
|
94
94
|
success: checkoutCartSchema,
|
|
95
95
|
}),
|
|
96
96
|
)
|
|
97
97
|
.add(
|
|
98
|
-
HttpApiEndpoint.post('addCartItem', '/
|
|
98
|
+
HttpApiEndpoint.post('addCartItem', '/checkout/cart/items', {
|
|
99
99
|
payload: checkoutAddCartItemPayloadSchema,
|
|
100
100
|
success: checkoutCartSchema,
|
|
101
101
|
}),
|
|
102
102
|
)
|
|
103
103
|
.add(
|
|
104
|
-
HttpApiEndpoint.post('removeCartItem', '/
|
|
104
|
+
HttpApiEndpoint.post('removeCartItem', '/checkout/cart/remove', {
|
|
105
105
|
payload: checkoutRemoveCartItemPayloadSchema,
|
|
106
106
|
success: checkoutCartSchema,
|
|
107
107
|
}),
|
|
108
108
|
)
|
|
109
109
|
.add(
|
|
110
|
-
HttpApiEndpoint.post('clearCart', '/
|
|
110
|
+
HttpApiEndpoint.post('clearCart', '/checkout/cart/clear', {
|
|
111
111
|
success: checkoutCartSchema,
|
|
112
112
|
}),
|
|
113
113
|
)`;
|
|
@@ -120,31 +120,31 @@ function createCheckoutCartOperationContexts(service) {
|
|
|
120
120
|
addCartItem: {
|
|
121
121
|
method: 'POST',
|
|
122
122
|
operationId: '${apiName}:${groupName}:addCartItem',
|
|
123
|
-
routePath: '/
|
|
123
|
+
routePath: '/checkout/cart/items',
|
|
124
124
|
source: 'generated-client',
|
|
125
125
|
},
|
|
126
126
|
clearCart: {
|
|
127
127
|
method: 'POST',
|
|
128
128
|
operationId: '${apiName}:${groupName}:clearCart',
|
|
129
|
-
routePath: '/
|
|
129
|
+
routePath: '/checkout/cart/clear',
|
|
130
130
|
source: 'generated-client',
|
|
131
131
|
},
|
|
132
132
|
getCart: {
|
|
133
133
|
method: 'GET',
|
|
134
134
|
operationId: '${apiName}:${groupName}:getCart',
|
|
135
|
-
routePath: '/
|
|
135
|
+
routePath: '/checkout/cart',
|
|
136
136
|
source: 'generated-client',
|
|
137
137
|
},
|
|
138
138
|
removeCartItem: {
|
|
139
139
|
method: 'POST',
|
|
140
140
|
operationId: '${apiName}:${groupName}:removeCartItem',
|
|
141
|
-
routePath: '/
|
|
141
|
+
routePath: '/checkout/cart/remove',
|
|
142
142
|
source: 'generated-client',
|
|
143
143
|
},`;
|
|
144
144
|
}
|
|
145
145
|
function createCheckoutCartApiContractFields(service) {
|
|
146
146
|
if (!serviceHasCheckoutCartState(service)) return '';
|
|
147
|
-
return ` checkoutCartPath: '${effectApiPrefix(service)}/
|
|
147
|
+
return ` checkoutCartPath: '${effectApiPrefix(service)}/checkout/cart',
|
|
148
148
|
`;
|
|
149
149
|
}
|
|
150
150
|
function createCheckoutCartServerState(service) {
|
|
@@ -180,7 +180,7 @@ function createCheckoutCartServerHandlers(service) {
|
|
|
180
180
|
return `
|
|
181
181
|
.handle('getCart', () =>
|
|
182
182
|
Effect.sync(() => createCheckoutCartSnapshot()).pipe(
|
|
183
|
-
Effect.withSpan('ultramodern.
|
|
183
|
+
Effect.withSpan('ultramodern.api.${groupName}.checkout.getCart', {
|
|
184
184
|
attributes: operationAttributes(${groupName}OperationContexts.getCart),
|
|
185
185
|
kind: 'server',
|
|
186
186
|
}),
|
|
@@ -198,7 +198,7 @@ function createCheckoutCartServerHandlers(service) {
|
|
|
198
198
|
});
|
|
199
199
|
return createCheckoutCartSnapshot();
|
|
200
200
|
}).pipe(
|
|
201
|
-
Effect.withSpan('ultramodern.
|
|
201
|
+
Effect.withSpan('ultramodern.api.${groupName}.checkout.addCartItem', {
|
|
202
202
|
attributes: operationAttributes(${groupName}OperationContexts.addCartItem),
|
|
203
203
|
kind: 'server',
|
|
204
204
|
}),
|
|
@@ -209,7 +209,7 @@ function createCheckoutCartServerHandlers(service) {
|
|
|
209
209
|
checkoutCartLines.delete(payload.sku);
|
|
210
210
|
return createCheckoutCartSnapshot();
|
|
211
211
|
}).pipe(
|
|
212
|
-
Effect.withSpan('ultramodern.
|
|
212
|
+
Effect.withSpan('ultramodern.api.${groupName}.checkout.removeCartItem', {
|
|
213
213
|
attributes: operationAttributes(${groupName}OperationContexts.removeCartItem),
|
|
214
214
|
kind: 'server',
|
|
215
215
|
}),
|
|
@@ -220,7 +220,7 @@ function createCheckoutCartServerHandlers(service) {
|
|
|
220
220
|
checkoutCartLines.clear();
|
|
221
221
|
return createCheckoutCartSnapshot();
|
|
222
222
|
}).pipe(
|
|
223
|
-
Effect.withSpan('ultramodern.
|
|
223
|
+
Effect.withSpan('ultramodern.api.${groupName}.checkout.clearCart', {
|
|
224
224
|
attributes: operationAttributes(${groupName}OperationContexts.clearCart),
|
|
225
225
|
kind: 'server',
|
|
226
226
|
}),
|
|
@@ -357,7 +357,7 @@ export interface ${itemType} {
|
|
|
357
357
|
|
|
358
358
|
export interface ${readinessType} {
|
|
359
359
|
readonly checks: {
|
|
360
|
-
readonly
|
|
360
|
+
readonly api: 'ready';
|
|
361
361
|
readonly moduleFederation: 'ready';
|
|
362
362
|
readonly ssr: 'ready';
|
|
363
363
|
readonly translations: 'ready';
|
|
@@ -401,7 +401,7 @@ export const ${schemaExport}: Schema.Codec<${itemType}> = Schema.Struct({
|
|
|
401
401
|
|
|
402
402
|
export const ${readinessSchemaExport}: Schema.Codec<${readinessType}> = Schema.Struct({
|
|
403
403
|
checks: Schema.Struct({
|
|
404
|
-
|
|
404
|
+
api: Schema.Literal('ready'),
|
|
405
405
|
moduleFederation: Schema.Literal('ready'),
|
|
406
406
|
ssr: Schema.Literal('ready'),
|
|
407
407
|
translations: Schema.Literal('ready'),
|
|
@@ -438,7 +438,7 @@ export interface OperationContext {
|
|
|
438
438
|
export const ${apiExport} = HttpApi.make('${apiName}').add(
|
|
439
439
|
HttpApiGroup.make('${groupName}')
|
|
440
440
|
.add(
|
|
441
|
-
HttpApiEndpoint.get('list', '
|
|
441
|
+
HttpApiEndpoint.get('list', '/${stem}', {
|
|
442
442
|
query: {
|
|
443
443
|
limit: Schema.optional(Schema.FiniteFromString),
|
|
444
444
|
},
|
|
@@ -448,12 +448,12 @@ export const ${apiExport} = HttpApi.make('${apiName}').add(
|
|
|
448
448
|
}),
|
|
449
449
|
)
|
|
450
450
|
.add(
|
|
451
|
-
HttpApiEndpoint.get('readiness', '
|
|
451
|
+
HttpApiEndpoint.get('readiness', '/${stem}/readiness', {
|
|
452
452
|
success: ${readinessSchemaExport},
|
|
453
453
|
}),
|
|
454
454
|
)
|
|
455
455
|
.add(
|
|
456
|
-
HttpApiEndpoint.get('get', '
|
|
456
|
+
HttpApiEndpoint.get('get', '/${stem}/:id', {
|
|
457
457
|
error: ${notFoundSchemaExport},
|
|
458
458
|
params: {
|
|
459
459
|
id: Schema.String,
|
|
@@ -462,7 +462,7 @@ export const ${apiExport} = HttpApi.make('${apiName}').add(
|
|
|
462
462
|
}),
|
|
463
463
|
)
|
|
464
464
|
.add(
|
|
465
|
-
HttpApiEndpoint.post('create', '
|
|
465
|
+
HttpApiEndpoint.post('create', '/${stem}', {
|
|
466
466
|
payload: ${createPayloadSchemaExport},
|
|
467
467
|
success: Schema.Struct({
|
|
468
468
|
item: ${schemaExport},
|
|
@@ -475,34 +475,34 @@ export const ${groupName}OperationContexts = {
|
|
|
475
475
|
${checkoutCartOperationContextEntries} create: {
|
|
476
476
|
method: 'POST',
|
|
477
477
|
operationId: '${apiName}:${groupName}:create',
|
|
478
|
-
routePath: '
|
|
478
|
+
routePath: '/${stem}',
|
|
479
479
|
source: 'generated-client',
|
|
480
480
|
},
|
|
481
481
|
get: {
|
|
482
482
|
method: 'GET',
|
|
483
483
|
operationId: '${apiName}:${groupName}:get',
|
|
484
|
-
routePath: '
|
|
484
|
+
routePath: '/${stem}/:id',
|
|
485
485
|
source: 'generated-client',
|
|
486
486
|
},
|
|
487
487
|
list: {
|
|
488
488
|
method: 'GET',
|
|
489
489
|
operationId: '${apiName}:${groupName}:list',
|
|
490
|
-
routePath: '
|
|
490
|
+
routePath: '/${stem}',
|
|
491
491
|
source: 'generated-client',
|
|
492
492
|
},
|
|
493
493
|
readiness: {
|
|
494
494
|
method: 'GET',
|
|
495
495
|
operationId: '${apiName}:${groupName}:readiness',
|
|
496
|
-
routePath: '
|
|
496
|
+
routePath: '/${stem}/readiness',
|
|
497
497
|
source: 'generated-client',
|
|
498
498
|
},
|
|
499
499
|
} satisfies Record<string, OperationContext>;
|
|
500
500
|
|
|
501
501
|
export const ${groupName}ApiContract = {
|
|
502
502
|
apiPrefix: '${apiPrefix}',
|
|
503
|
-
basePath: '${apiPrefix}
|
|
503
|
+
basePath: '${apiPrefix}/${stem}',
|
|
504
504
|
${createCheckoutCartApiContractFields(service)} ownerId: '${service.id}',
|
|
505
|
-
readinessPath: '${apiPrefix}
|
|
505
|
+
readinessPath: '${apiPrefix}/${stem}/readiness',
|
|
506
506
|
} as const;
|
|
507
507
|
`;
|
|
508
508
|
}
|
|
@@ -526,7 +526,7 @@ import type {
|
|
|
526
526
|
EffectBffRuntime,
|
|
527
527
|
EffectRuntimeLayer,
|
|
528
528
|
} from '@modern-js/plugin-bff/effect-edge';
|
|
529
|
-
import { ultramodernApiMarker } from '
|
|
529
|
+
import { ultramodernApiMarker } from '../shared/ultramodern-build.ts';
|
|
530
530
|
import {
|
|
531
531
|
${apiExport},
|
|
532
532
|
${groupName}OperationContexts,
|
|
@@ -567,7 +567,7 @@ const ${groupName}Layer = HttpApiBuilder.group(
|
|
|
567
567
|
? ${groupName}Items.slice(0, query.limit)
|
|
568
568
|
: ${groupName}Items,
|
|
569
569
|
}).pipe(
|
|
570
|
-
Effect.withSpan('ultramodern.
|
|
570
|
+
Effect.withSpan('ultramodern.api.${groupName}.list', {
|
|
571
571
|
attributes: operationAttributes(${groupName}OperationContexts.list),
|
|
572
572
|
kind: 'server',
|
|
573
573
|
}),
|
|
@@ -576,7 +576,7 @@ const ${groupName}Layer = HttpApiBuilder.group(
|
|
|
576
576
|
.handle('readiness', () =>
|
|
577
577
|
Effect.succeed({
|
|
578
578
|
checks: {
|
|
579
|
-
|
|
579
|
+
api: 'ready' as const,
|
|
580
580
|
moduleFederation: 'ready' as const,
|
|
581
581
|
ssr: 'ready' as const,
|
|
582
582
|
translations: 'ready' as const,
|
|
@@ -585,7 +585,7 @@ const ${groupName}Layer = HttpApiBuilder.group(
|
|
|
585
585
|
status: 'ready' as const,
|
|
586
586
|
versionSkew: 'none' as const,
|
|
587
587
|
}).pipe(
|
|
588
|
-
Effect.withSpan('ultramodern.
|
|
588
|
+
Effect.withSpan('ultramodern.api.${groupName}.readiness', {
|
|
589
589
|
attributes: operationAttributes(${groupName}OperationContexts.readiness),
|
|
590
590
|
kind: 'server',
|
|
591
591
|
}),
|
|
@@ -605,7 +605,7 @@ const ${groupName}Layer = HttpApiBuilder.group(
|
|
|
605
605
|
: Effect.succeed(matchedItem);
|
|
606
606
|
|
|
607
607
|
return result.pipe(
|
|
608
|
-
Effect.withSpan('ultramodern.
|
|
608
|
+
Effect.withSpan('ultramodern.api.${groupName}.get', {
|
|
609
609
|
attributes: operationAttributes(${groupName}OperationContexts.get),
|
|
610
610
|
kind: 'server',
|
|
611
611
|
}),
|
|
@@ -622,7 +622,7 @@ const ${groupName}Layer = HttpApiBuilder.group(
|
|
|
622
622
|
title: payload.title,
|
|
623
623
|
},
|
|
624
624
|
}).pipe(
|
|
625
|
-
Effect.withSpan('ultramodern.
|
|
625
|
+
Effect.withSpan('ultramodern.api.${groupName}.create', {
|
|
626
626
|
attributes: operationAttributes(${groupName}OperationContexts.create),
|
|
627
627
|
kind: 'server',
|
|
628
628
|
}),
|
|
@@ -634,13 +634,13 @@ const layer = HttpApiBuilder.layer(${apiExport}).pipe(
|
|
|
634
634
|
Layer.provide(${groupName}Layer),
|
|
635
635
|
) satisfies EffectRuntimeLayer;
|
|
636
636
|
|
|
637
|
-
const
|
|
637
|
+
const apiRuntime: EffectBffDefinition<typeof ${apiExport}, EffectRuntimeLayer> &
|
|
638
638
|
EffectBffRuntime<typeof ${apiExport}, EffectRuntimeLayer> = defineEffectBff({
|
|
639
639
|
api: ${apiExport},
|
|
640
640
|
layer,
|
|
641
641
|
});
|
|
642
642
|
|
|
643
|
-
export default
|
|
643
|
+
export default apiRuntime;
|
|
644
644
|
`;
|
|
645
645
|
}
|
|
646
646
|
function createEffectClient(service, contractImportPath) {
|
|
@@ -692,7 +692,7 @@ import type {
|
|
|
692
692
|
|
|
693
693
|
export { Effect, runEffectRequest };
|
|
694
694
|
|
|
695
|
-
type ${pascalStem}
|
|
695
|
+
type ${pascalStem}ApiGroups = typeof ${apiExport} extends HttpApi.HttpApi<
|
|
696
696
|
infer _ApiId,
|
|
697
697
|
infer Groups
|
|
698
698
|
>
|
|
@@ -700,7 +700,7 @@ type ${pascalStem}EffectGroups = typeof ${apiExport} extends HttpApi.HttpApi<
|
|
|
700
700
|
: never;
|
|
701
701
|
|
|
702
702
|
export type ${clientTypeName} = HttpApiClient.Client<
|
|
703
|
-
Extract<${pascalStem}
|
|
703
|
+
Extract<${pascalStem}ApiGroups, HttpApiGroup.Any>,
|
|
704
704
|
never,
|
|
705
705
|
never
|
|
706
706
|
>;
|
|
@@ -810,7 +810,7 @@ ${checkoutCartExports} create${pascalSingular},
|
|
|
810
810
|
get${pascalStem}Readiness,
|
|
811
811
|
list${pascalStem},
|
|
812
812
|
type ${pascalStem}ClientOptions,
|
|
813
|
-
} from '${packageName(scope, remote.packageSuffix)}/
|
|
813
|
+
} from '${packageName(scope, remote.packageSuffix)}/api/client';`;
|
|
814
814
|
}).join('\n\n');
|
|
815
815
|
return exports ? `${exports}\n` : `export const ultramodernVerticalClients = [] as const;
|
|
816
816
|
`;
|
|
@@ -818,7 +818,7 @@ ${checkoutCartExports} create${pascalSingular},
|
|
|
818
818
|
function createEffectReadinessContract(app) {
|
|
819
819
|
const stem = effectApiStem(app);
|
|
820
820
|
return {
|
|
821
|
-
endpoint:
|
|
821
|
+
endpoint: `/${stem}/readiness`,
|
|
822
822
|
marker: {
|
|
823
823
|
ui: 'ultramodernUiMarker',
|
|
824
824
|
api: 'ultramodernApiMarker',
|
|
@@ -828,7 +828,7 @@ function createEffectReadinessContract(app) {
|
|
|
828
828
|
'moduleFederation',
|
|
829
829
|
'ssr',
|
|
830
830
|
'translations',
|
|
831
|
-
'
|
|
831
|
+
'api'
|
|
832
832
|
]
|
|
833
833
|
};
|
|
834
834
|
}
|
|
@@ -843,39 +843,39 @@ function createEffectRequestContextContract() {
|
|
|
843
843
|
'x-ultramodern-env',
|
|
844
844
|
'x-vertical-version-id'
|
|
845
845
|
],
|
|
846
|
-
source: 'shell-to-vertical-
|
|
846
|
+
source: 'shell-to-vertical-api-client'
|
|
847
847
|
};
|
|
848
848
|
}
|
|
849
849
|
function createEffectDomainOperations(app) {
|
|
850
850
|
const stem = effectApiStem(app);
|
|
851
851
|
const group = verticalEffectGroupName(app);
|
|
852
|
-
const basePath =
|
|
852
|
+
const basePath = `/${stem}`;
|
|
853
853
|
const checkoutCartOperations = serviceHasCheckoutCartState(app) ? {
|
|
854
854
|
checkoutCartAddItem: {
|
|
855
855
|
client: 'addCheckoutCartItem',
|
|
856
856
|
method: 'POST',
|
|
857
|
-
path: '/
|
|
857
|
+
path: '/checkout/cart/items',
|
|
858
858
|
resource: 'checkout-cart',
|
|
859
859
|
owner: app.id
|
|
860
860
|
},
|
|
861
861
|
checkoutCartClear: {
|
|
862
862
|
client: 'clearCheckoutCart',
|
|
863
863
|
method: 'POST',
|
|
864
|
-
path: '/
|
|
864
|
+
path: '/checkout/cart/clear',
|
|
865
865
|
resource: 'checkout-cart',
|
|
866
866
|
owner: app.id
|
|
867
867
|
},
|
|
868
868
|
checkoutCartRead: {
|
|
869
869
|
client: 'getCheckoutCart',
|
|
870
870
|
method: 'GET',
|
|
871
|
-
path: '/
|
|
871
|
+
path: '/checkout/cart',
|
|
872
872
|
resource: 'checkout-cart',
|
|
873
873
|
owner: app.id
|
|
874
874
|
},
|
|
875
875
|
checkoutCartRemoveItem: {
|
|
876
876
|
client: 'removeCheckoutCartItem',
|
|
877
877
|
method: 'POST',
|
|
878
|
-
path: '/
|
|
878
|
+
path: '/checkout/cart/remove',
|
|
879
879
|
resource: 'checkout-cart',
|
|
880
880
|
owner: app.id
|
|
881
881
|
}
|
|
@@ -908,27 +908,26 @@ function createEffectDomainOperations(app) {
|
|
|
908
908
|
function effectApiTopologyMetadata(app) {
|
|
909
909
|
if (!appHasEffectApi(app)) return;
|
|
910
910
|
return {
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
}
|
|
911
|
+
runtime: 'effect',
|
|
912
|
+
bff: {
|
|
913
|
+
prefix: app.effectApi.prefix,
|
|
914
|
+
openapi: '/openapi.json',
|
|
915
|
+
strictEffectApproach: true
|
|
916
|
+
},
|
|
917
|
+
contract: {
|
|
918
|
+
export: './api',
|
|
919
|
+
path: `${app.directory}/shared/api.ts`
|
|
920
|
+
},
|
|
921
|
+
client: {
|
|
922
|
+
export: './api/client',
|
|
923
|
+
path: `${app.directory}/src/api/${app.effectApi.stem}-client.ts`
|
|
924
|
+
},
|
|
925
|
+
serverEntry: `${app.directory}/api/index.ts`,
|
|
926
|
+
basePath: `${app.effectApi.prefix}/${app.effectApi.stem}`,
|
|
927
|
+
consumedBy: app.effectApi.consumedBy,
|
|
928
|
+
readiness: createEffectReadinessContract(app),
|
|
929
|
+
requestContext: createEffectRequestContextContract(),
|
|
930
|
+
domainOperations: createEffectDomainOperations(app)
|
|
932
931
|
};
|
|
933
932
|
}
|
|
934
933
|
function createEffectOperationContract(target) {
|
|
@@ -936,22 +935,22 @@ function createEffectOperationContract(target) {
|
|
|
936
935
|
const checkoutCartOperations = serviceHasCheckoutCartState(target) ? {
|
|
937
936
|
addCartItem: {
|
|
938
937
|
method: 'POST',
|
|
939
|
-
path: '/
|
|
938
|
+
path: '/checkout/cart/items',
|
|
940
939
|
source: 'generated-client'
|
|
941
940
|
},
|
|
942
941
|
clearCart: {
|
|
943
942
|
method: 'POST',
|
|
944
|
-
path: '/
|
|
943
|
+
path: '/checkout/cart/clear',
|
|
945
944
|
source: 'generated-client'
|
|
946
945
|
},
|
|
947
946
|
getCart: {
|
|
948
947
|
method: 'GET',
|
|
949
|
-
path: '/
|
|
948
|
+
path: '/checkout/cart',
|
|
950
949
|
source: 'generated-client'
|
|
951
950
|
},
|
|
952
951
|
removeCartItem: {
|
|
953
952
|
method: 'POST',
|
|
954
|
-
path: '/
|
|
953
|
+
path: '/checkout/cart/remove',
|
|
955
954
|
source: 'generated-client'
|
|
956
955
|
}
|
|
957
956
|
} : {};
|
|
@@ -962,22 +961,22 @@ function createEffectOperationContract(target) {
|
|
|
962
961
|
...checkoutCartOperations,
|
|
963
962
|
list: {
|
|
964
963
|
method: 'GET',
|
|
965
|
-
path:
|
|
964
|
+
path: `/${stem}`,
|
|
966
965
|
source: 'generated-client'
|
|
967
966
|
},
|
|
968
967
|
readiness: {
|
|
969
968
|
method: 'GET',
|
|
970
|
-
path:
|
|
969
|
+
path: `/${stem}/readiness`,
|
|
971
970
|
source: 'generated-client'
|
|
972
971
|
},
|
|
973
972
|
get: {
|
|
974
973
|
method: 'GET',
|
|
975
|
-
path:
|
|
974
|
+
path: `/${stem}/:id`,
|
|
976
975
|
source: 'generated-client'
|
|
977
976
|
},
|
|
978
977
|
create: {
|
|
979
978
|
method: 'POST',
|
|
980
|
-
path:
|
|
979
|
+
path: `/${stem}`,
|
|
981
980
|
source: 'generated-client'
|
|
982
981
|
}
|
|
983
982
|
}
|
|
@@ -4,8 +4,7 @@ import node_path from "node:path";
|
|
|
4
4
|
const moduleFederationConfigFile = 'module-federation.config.ts';
|
|
5
5
|
const mfTypesArchive = 'dist/@mf-types.zip';
|
|
6
6
|
const generatedMetadataPaths = [
|
|
7
|
-
'.modernjs/ultramodern.json'
|
|
8
|
-
'.modernjs/ultramodern-generated-contract.json'
|
|
7
|
+
'.modernjs/ultramodern.json'
|
|
9
8
|
];
|
|
10
9
|
const defaultAppRootDirs = [
|
|
11
10
|
'apps',
|
|
@@ -9,10 +9,11 @@ function createAppModernConfig(scope, app) {
|
|
|
9
9
|
const bffImport = appHasEffectApi(app) ? "import { bffPlugin } from '@modern-js/plugin-bff';\n" : '';
|
|
10
10
|
const bffConfig = appHasEffectApi(app) ? ` bff: {
|
|
11
11
|
effect: {
|
|
12
|
-
entry: './api/
|
|
12
|
+
entry: './api/index',
|
|
13
13
|
openapi: {
|
|
14
14
|
path: '/openapi.json',
|
|
15
15
|
},
|
|
16
|
+
strictEffectApproach: true,
|
|
16
17
|
},
|
|
17
18
|
prefix: '${effectApiPrefix(app)}',
|
|
18
19
|
runtimeFramework: 'effect',
|
|
@@ -396,7 +397,7 @@ export const ultramodernUiMarker = {
|
|
|
396
397
|
|
|
397
398
|
export const ultramodernApiMarker = {
|
|
398
399
|
...ultramodernVerticalIdentity,
|
|
399
|
-
surface: '
|
|
400
|
+
surface: 'api',
|
|
400
401
|
} as const;
|
|
401
402
|
`;
|
|
402
403
|
}
|
|
@@ -180,10 +180,11 @@ function createRootPackageJson(scope, packageSource, remotes = [], bridge) {
|
|
|
180
180
|
'mf:types': "node ./scripts/assert-mf-types.mjs",
|
|
181
181
|
'performance:readiness': "node ./scripts/ultramodern-performance-readiness.mjs",
|
|
182
182
|
'contract:check': "node ./scripts/validate-ultramodern-workspace.mjs",
|
|
183
|
+
'api:check': "node ./scripts/check-ultramodern-api-boundaries.mjs",
|
|
183
184
|
'i18n:boundaries': "node ./scripts/check-ultramodern-i18n-boundaries.mjs",
|
|
184
185
|
...bridgeScripts,
|
|
185
186
|
postinstall: "oxfmt . '!repos/**' && node ./scripts/bootstrap-agent-skills.mjs --postinstall",
|
|
186
|
-
check: `pnpm format:check && pnpm lint && pnpm typecheck && pnpm skills:check && pnpm i18n:boundaries && pnpm contract:check && pnpm performance:readiness${bridgeCheck}`
|
|
187
|
+
check: `pnpm format:check && pnpm lint && pnpm typecheck && pnpm skills:check && pnpm i18n:boundaries && pnpm api:check && pnpm contract:check && pnpm performance:readiness${bridgeCheck}`
|
|
187
188
|
},
|
|
188
189
|
engines: {
|
|
189
190
|
node: '>=26',
|
|
@@ -383,7 +384,7 @@ function createAppPackage(scope, app, packageSource, enableTailwind, remotes = [
|
|
|
383
384
|
appId: app.id,
|
|
384
385
|
topology: `${relativeRootFor(app.directory)}/topology/reference-topology.json`,
|
|
385
386
|
...appHasEffectApi(app) ? {
|
|
386
|
-
apiRuntime: 'effect
|
|
387
|
+
apiRuntime: 'effect'
|
|
387
388
|
} : {}
|
|
388
389
|
},
|
|
389
390
|
'zephyr:dependencies': createZephyrDependencies(scope, app, remotes),
|
|
@@ -391,11 +392,11 @@ function createAppPackage(scope, app, packageSource, enableTailwind, remotes = [
|
|
|
391
392
|
devDependencies: appDevDependencies(packageSource, enableTailwind)
|
|
392
393
|
};
|
|
393
394
|
if (appHasEffectApi(app)) Object.assign(packageExports, {
|
|
394
|
-
'./
|
|
395
|
-
'./
|
|
395
|
+
'./api': './shared/api.ts',
|
|
396
|
+
'./api/client': `./src/api/${app.effectApi.stem}-client.ts`
|
|
396
397
|
});
|
|
397
398
|
else if ('shell' === app.kind) Object.assign(packageExports, {
|
|
398
|
-
'./
|
|
399
|
+
'./api/clients': './src/api/vertical-clients.ts'
|
|
399
400
|
});
|
|
400
401
|
if (Object.keys(packageExports).length > 0) packageJson.exports = packageExports;
|
|
401
402
|
return packageJson;
|
|
@@ -17,7 +17,7 @@ function createCloudflareProofRoute(app) {
|
|
|
17
17
|
mfManifest: '/mf-manifest.json',
|
|
18
18
|
locale: `/locales/en/${appI18nNamespace(app)}.json`,
|
|
19
19
|
...appHasEffectApi(app) ? {
|
|
20
|
-
|
|
20
|
+
apiReadiness: `${effectApiPrefix(app)}/${effectApiStem(app)}/readiness`
|
|
21
21
|
} : {}
|
|
22
22
|
};
|
|
23
23
|
}
|
|
@@ -128,6 +128,9 @@ function createWorkspaceValidationScript(scope, enableTailwind, remotes = []) {
|
|
|
128
128
|
function createWorkspaceI18nBoundaryValidationScript() {
|
|
129
129
|
return readFileTemplate("workspace-scripts/check-ultramodern-i18n-boundaries.mjs");
|
|
130
130
|
}
|
|
131
|
+
function createWorkspaceApiBoundaryValidationScript() {
|
|
132
|
+
return readFileTemplate("workspace-scripts/check-ultramodern-api-boundaries.mjs");
|
|
133
|
+
}
|
|
131
134
|
function createPerformanceReadinessConfigScript() {
|
|
132
135
|
return readFileTemplate("workspace-scripts/ultramodern-performance-readiness.config.mjs");
|
|
133
136
|
}
|
|
@@ -135,6 +138,7 @@ function writeGeneratedWorkspaceScripts(targetDir, _scope, _enableTailwind, _rem
|
|
|
135
138
|
writeFileReplacing(targetDir, "scripts/assert-mf-types.mjs", createToolWrapperScript('mf-types'));
|
|
136
139
|
writeFileReplacing(targetDir, "scripts/validate-ultramodern-workspace.mjs", createToolWrapperScript('validate'));
|
|
137
140
|
writeFileReplacing(targetDir, "scripts/check-ultramodern-i18n-boundaries.mjs", createWorkspaceI18nBoundaryValidationScript());
|
|
141
|
+
writeFileReplacing(targetDir, "scripts/check-ultramodern-api-boundaries.mjs", createWorkspaceApiBoundaryValidationScript());
|
|
138
142
|
writeFileReplacing(targetDir, "scripts/generate-public-surface-assets.mjs", createToolWrapperScript('public-surface'));
|
|
139
143
|
writeFileReplacing(targetDir, "scripts/proof-cloudflare-version.mjs", createToolWrapperScript('cloudflare-proof'));
|
|
140
144
|
writeFileReplacing(targetDir, "scripts/ultramodern-performance-readiness.config.mjs", createPerformanceReadinessConfigScript());
|
|
@@ -142,4 +146,4 @@ function writeGeneratedWorkspaceScripts(targetDir, _scope, _enableTailwind, _rem
|
|
|
142
146
|
writeFileReplacing(targetDir, "scripts/ultramodern-typecheck.mjs", createToolWrapperScript('typecheck'));
|
|
143
147
|
writeFileReplacing(targetDir, "scripts/bootstrap-agent-skills.mjs", createSkillsToolWrapperScript());
|
|
144
148
|
}
|
|
145
|
-
export { createPerformanceReadinessConfigScript, createWorkspaceI18nBoundaryValidationScript, createWorkspaceValidationScript, writeGeneratedWorkspaceScripts };
|
|
149
|
+
export { createPerformanceReadinessConfigScript, createWorkspaceApiBoundaryValidationScript, createWorkspaceI18nBoundaryValidationScript, createWorkspaceValidationScript, writeGeneratedWorkspaceScripts };
|
|
@@ -51,12 +51,12 @@ function writeApp(targetDir, scope, app, packageSource, enableTailwind, remotes
|
|
|
51
51
|
if ('shell' === resolvedApp.kind) {
|
|
52
52
|
writeAppFile('src/routes/vertical-components.tsx', createShellRemoteComponents(scope, remotes));
|
|
53
53
|
writeAppFile('src/routes/shell-frame.tsx', createShellFrameComponent());
|
|
54
|
-
writeFile(targetDir, `${resolvedApp.directory}/src/
|
|
54
|
+
writeFile(targetDir, `${resolvedApp.directory}/src/api/vertical-clients.ts`, createShellEffectClient(scope, remotes));
|
|
55
55
|
}
|
|
56
56
|
if (appHasEffectApi(resolvedApp)) {
|
|
57
|
-
writeFile(targetDir, `${resolvedApp.directory}/shared/
|
|
58
|
-
writeFile(targetDir, `${resolvedApp.directory}/api/
|
|
59
|
-
writeFile(targetDir, `${resolvedApp.directory}/src/
|
|
57
|
+
writeFile(targetDir, `${resolvedApp.directory}/shared/api.ts`, createEffectSharedApi(resolvedApp));
|
|
58
|
+
writeFile(targetDir, `${resolvedApp.directory}/api/index.ts`, createEffectServiceEntry(resolvedApp, '../shared/api.ts'));
|
|
59
|
+
writeFile(targetDir, `${resolvedApp.directory}/src/api/${resolvedApp.effectApi.stem}-client.ts`, createEffectClient(resolvedApp, '../../shared/api'));
|
|
60
60
|
}
|
|
61
61
|
if ('vertical' === resolvedApp.kind) {
|
|
62
62
|
writeAppFile('src/federation-entry.tsx', createRemoteEntry(resolvedApp));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type UltramodernBridgeConfig } from '../ultramodern-workspace/bridge-config';
|
|
2
2
|
import type { ResolvedPackageSource, WorkspaceApp, WorkspaceEffectApi } from '../ultramodern-workspace/types';
|
|
3
|
-
export type UltramodernToolingConfigSource = 'compact'
|
|
3
|
+
export type UltramodernToolingConfigSource = 'compact';
|
|
4
4
|
export type UltramodernToolingConfigApp = {
|
|
5
5
|
id: string;
|
|
6
6
|
kind: WorkspaceApp['kind'];
|
|
@@ -38,7 +38,6 @@ export type UltramodernToolingConfig = {
|
|
|
38
38
|
topology: {
|
|
39
39
|
apps: UltramodernToolingConfigApp[];
|
|
40
40
|
};
|
|
41
|
-
legacyContract?: Record<string, any>;
|
|
42
41
|
};
|
|
43
42
|
export declare function readUltramodernConfig(workspaceRoot?: any): UltramodernToolingConfig;
|
|
44
43
|
export declare function workspaceAppsFromToolingConfig(config: UltramodernToolingConfig): WorkspaceApp[];
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { Ownership, WorkspaceApp, WorkspaceEffectApi } from './types';
|
|
2
|
-
export declare const GENERATED_CONTRACT_PATH = ".modernjs/ultramodern-generated-contract.json";
|
|
3
2
|
export declare const ULTRAMODERN_CONFIG_PATH = ".modernjs/ultramodern.json";
|
|
4
3
|
export declare const shellApp: WorkspaceApp;
|
|
5
4
|
export declare function createShellHost(remotes?: WorkspaceApp[]): WorkspaceApp;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { WorkspaceApp } from './types';
|
|
2
2
|
export declare function createWorkspaceValidationScript(scope: string, enableTailwind: boolean, remotes?: WorkspaceApp[]): string;
|
|
3
3
|
export declare function createWorkspaceI18nBoundaryValidationScript(): string;
|
|
4
|
+
export declare function createWorkspaceApiBoundaryValidationScript(): string;
|
|
4
5
|
export declare function createPerformanceReadinessConfigScript(): string;
|
|
5
6
|
export declare function writeGeneratedWorkspaceScripts(targetDir: string, _scope: string, _enableTailwind: boolean, _remotes?: WorkspaceApp[]): void;
|
package/package.json
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"engines": {
|
|
22
22
|
"node": ">=20"
|
|
23
23
|
},
|
|
24
|
-
"version": "3.4.0-ultramodern.
|
|
24
|
+
"version": "3.4.0-ultramodern.20",
|
|
25
25
|
"types": "./dist/types/index.d.ts",
|
|
26
26
|
"main": "./dist/esm-node/index.js",
|
|
27
27
|
"bin": {
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
"@modern-js/codesmith": "2.6.9",
|
|
78
78
|
"oxfmt": "0.55.0",
|
|
79
79
|
"ultracite": "7.8.3",
|
|
80
|
-
"@modern-js/i18n-utils": "npm:@bleedingdev/modern-js-i18n-utils@3.4.0-ultramodern.
|
|
80
|
+
"@modern-js/i18n-utils": "npm:@bleedingdev/modern-js-i18n-utils@3.4.0-ultramodern.20"
|
|
81
81
|
},
|
|
82
82
|
"devDependencies": {
|
|
83
83
|
"@rslib/core": "0.23.0",
|
|
@@ -99,6 +99,6 @@
|
|
|
99
99
|
"test": "rm -rf dist && rslib build -c rslibconfig.mts && rstest --passWithNoTests"
|
|
100
100
|
},
|
|
101
101
|
"ultramodern": {
|
|
102
|
-
"frameworkVersion": "3.4.0-ultramodern.
|
|
102
|
+
"frameworkVersion": "3.4.0-ultramodern.20"
|
|
103
103
|
}
|
|
104
104
|
}
|