@bleedingdev/modern-js-create 3.4.0-ultramodern.0 → 3.4.0-ultramodern.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -7
- package/dist/cjs/ultramodern-workspace/add-vertical.cjs +24 -0
- package/dist/cjs/ultramodern-workspace/contracts.cjs +8 -4
- package/dist/cjs/ultramodern-workspace/demo-components.cjs +14 -21
- package/dist/cjs/ultramodern-workspace/descriptors.cjs +2 -2
- package/dist/cjs/ultramodern-workspace/effect-api.cjs +162 -31
- package/dist/cjs/ultramodern-workspace/module-federation.cjs +29 -10
- package/dist/cjs/ultramodern-workspace/package-json.cjs +102 -14
- package/dist/cjs/ultramodern-workspace/versions.cjs +1 -5
- package/dist/cjs/ultramodern-workspace/workspace-scripts.cjs +7 -0
- package/dist/cjs/ultramodern-workspace/write-workspace.cjs +6 -8
- package/dist/esm/ultramodern-workspace/add-vertical.js +25 -1
- package/dist/esm/ultramodern-workspace/contracts.js +9 -5
- package/dist/esm/ultramodern-workspace/demo-components.js +14 -21
- package/dist/esm/ultramodern-workspace/descriptors.js +2 -2
- package/dist/esm/ultramodern-workspace/effect-api.js +162 -31
- package/dist/esm/ultramodern-workspace/module-federation.js +27 -11
- package/dist/esm/ultramodern-workspace/package-json.js +87 -11
- package/dist/esm/ultramodern-workspace/versions.js +2 -3
- package/dist/esm/ultramodern-workspace/workspace-scripts.js +5 -1
- package/dist/esm/ultramodern-workspace/write-workspace.js +9 -11
- package/dist/esm-node/ultramodern-workspace/add-vertical.js +25 -1
- package/dist/esm-node/ultramodern-workspace/contracts.js +9 -5
- package/dist/esm-node/ultramodern-workspace/demo-components.js +14 -21
- package/dist/esm-node/ultramodern-workspace/descriptors.js +2 -2
- package/dist/esm-node/ultramodern-workspace/effect-api.js +162 -31
- package/dist/esm-node/ultramodern-workspace/module-federation.js +27 -11
- package/dist/esm-node/ultramodern-workspace/package-json.js +87 -11
- package/dist/esm-node/ultramodern-workspace/versions.js +2 -3
- package/dist/esm-node/ultramodern-workspace/workspace-scripts.js +5 -1
- package/dist/esm-node/ultramodern-workspace/write-workspace.js +9 -11
- package/dist/types/ultramodern-workspace/module-federation.d.ts +1 -0
- package/dist/types/ultramodern-workspace/package-json.d.ts +12 -2
- package/dist/types/ultramodern-workspace/versions.d.ts +1 -2
- package/dist/types/ultramodern-workspace/workspace-scripts.d.ts +1 -0
- package/package.json +4 -4
- package/template-workspace/AGENTS.md.handlebars +2 -1
- package/template-workspace/README.md.handlebars +7 -0
- package/template-workspace/oxfmt.config.ts +3 -1
- package/template-workspace/oxlint.config.ts +3 -1
- package/template-workspace/patches/@tanstack__router-core@1.171.13.patch +51 -0
- package/template-workspace/pnpm-workspace.yaml.handlebars +11 -0
- package/template-workspace/scripts/bootstrap-agent-skills.mjs +42 -10
- package/templates/app/shell-frame.tsx +1 -2
- package/templates/app/ultramodern-route-head.tsx.handlebars +22 -11
- package/templates/packages/shared-contracts-index.ts +206 -272
- package/templates/workspace-scripts/assert-mf-types.mjs.handlebars +9 -0
- package/templates/workspace-scripts/ultramodern-typecheck.mjs +197 -0
- package/templates/workspace-scripts/validate-ultramodern-workspace.mjs.handlebars +234 -2
|
@@ -37,27 +37,51 @@ function serviceHasCheckoutCartState(service) {
|
|
|
37
37
|
function createCheckoutCartSharedSchemas(service) {
|
|
38
38
|
if (!serviceHasCheckoutCartState(service)) return '';
|
|
39
39
|
return `
|
|
40
|
-
export
|
|
40
|
+
export interface CheckoutCartLine {
|
|
41
|
+
readonly sku: string;
|
|
42
|
+
readonly name: string;
|
|
43
|
+
readonly quantity: number;
|
|
44
|
+
readonly unitPriceCents: number;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface CheckoutCart {
|
|
48
|
+
readonly lines: readonly CheckoutCartLine[];
|
|
49
|
+
readonly subtotalCents: number;
|
|
50
|
+
readonly totalQuantity: number;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface CheckoutAddCartItemPayload {
|
|
54
|
+
readonly sku: string;
|
|
55
|
+
readonly name?: string;
|
|
56
|
+
readonly quantity: number;
|
|
57
|
+
readonly unitPriceCents?: number;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface CheckoutRemoveCartItemPayload {
|
|
61
|
+
readonly sku: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export const checkoutCartLineSchema: Schema.Codec<CheckoutCartLine> = Schema.Struct({
|
|
41
65
|
sku: Schema.String,
|
|
42
66
|
name: Schema.String,
|
|
43
67
|
quantity: Schema.Finite,
|
|
44
68
|
unitPriceCents: Schema.Finite,
|
|
45
69
|
});
|
|
46
70
|
|
|
47
|
-
export const checkoutCartSchema = Schema.Struct({
|
|
71
|
+
export const checkoutCartSchema: Schema.Codec<CheckoutCart> = Schema.Struct({
|
|
48
72
|
lines: Schema.Array(checkoutCartLineSchema),
|
|
49
73
|
subtotalCents: Schema.Finite,
|
|
50
74
|
totalQuantity: Schema.Finite,
|
|
51
75
|
});
|
|
52
76
|
|
|
53
|
-
export const checkoutAddCartItemPayloadSchema = Schema.Struct({
|
|
77
|
+
export const checkoutAddCartItemPayloadSchema: Schema.Codec<CheckoutAddCartItemPayload> = Schema.Struct({
|
|
54
78
|
sku: Schema.String,
|
|
55
79
|
name: Schema.optional(Schema.String),
|
|
56
80
|
quantity: Schema.Finite,
|
|
57
81
|
unitPriceCents: Schema.optional(Schema.Finite),
|
|
58
82
|
});
|
|
59
83
|
|
|
60
|
-
export const checkoutRemoveCartItemPayloadSchema = Schema.Struct({
|
|
84
|
+
export const checkoutRemoveCartItemPayloadSchema: Schema.Codec<CheckoutRemoveCartItemPayload> = Schema.Struct({
|
|
61
85
|
sku: Schema.String,
|
|
62
86
|
});
|
|
63
87
|
`;
|
|
@@ -210,6 +234,7 @@ function createCheckoutCartClientExports(service) {
|
|
|
210
234
|
const pascalStem = toPascalCase(stem);
|
|
211
235
|
const clientOptionsName = `${pascalStem}ClientOptions`;
|
|
212
236
|
const createClientName = `create${pascalStem}Client`;
|
|
237
|
+
const clientEffectTypeName = `${pascalStem}ClientEffect`;
|
|
213
238
|
return `
|
|
214
239
|
export interface CheckoutCartLine {
|
|
215
240
|
sku: string;
|
|
@@ -233,7 +258,7 @@ export interface CheckoutAddCartItemInput {
|
|
|
233
258
|
|
|
234
259
|
export const getCheckoutCart = (
|
|
235
260
|
options: ${clientOptionsName} = {},
|
|
236
|
-
) =>
|
|
261
|
+
): ${clientEffectTypeName}<CheckoutCart> =>
|
|
237
262
|
${createClientName}({
|
|
238
263
|
...options,
|
|
239
264
|
operationContext:
|
|
@@ -245,7 +270,7 @@ export const getCheckoutCart = (
|
|
|
245
270
|
export const addCheckoutCartItem = (
|
|
246
271
|
payload: CheckoutAddCartItemInput,
|
|
247
272
|
options: ${clientOptionsName} = {},
|
|
248
|
-
) =>
|
|
273
|
+
): ${clientEffectTypeName}<CheckoutCart> =>
|
|
249
274
|
${createClientName}({
|
|
250
275
|
...options,
|
|
251
276
|
operationContext:
|
|
@@ -259,7 +284,7 @@ export const addCheckoutCartItem = (
|
|
|
259
284
|
export const removeCheckoutCartItem = (
|
|
260
285
|
sku: string,
|
|
261
286
|
options: ${clientOptionsName} = {},
|
|
262
|
-
) =>
|
|
287
|
+
): ${clientEffectTypeName}<CheckoutCart> =>
|
|
263
288
|
${createClientName}({
|
|
264
289
|
...options,
|
|
265
290
|
operationContext:
|
|
@@ -272,7 +297,7 @@ export const removeCheckoutCartItem = (
|
|
|
272
297
|
|
|
273
298
|
export const clearCheckoutCart = (
|
|
274
299
|
options: ${clientOptionsName} = {},
|
|
275
|
-
) =>
|
|
300
|
+
): ${clientEffectTypeName}<CheckoutCart> =>
|
|
276
301
|
${createClientName}({
|
|
277
302
|
...options,
|
|
278
303
|
operationContext:
|
|
@@ -303,12 +328,63 @@ function createEffectSharedApiContract(service) {
|
|
|
303
328
|
const apiName = verticalEffectApiName(service);
|
|
304
329
|
const groupName = verticalEffectGroupName(service);
|
|
305
330
|
const stem = effectApiStem(service);
|
|
331
|
+
const pascalStem = toPascalCase(stem);
|
|
332
|
+
const markerType = `${pascalStem}Marker`;
|
|
333
|
+
const itemType = `${pascalStem}Item`;
|
|
334
|
+
const readinessType = `${pascalStem}Readiness`;
|
|
335
|
+
const createPayloadType = `${pascalStem}CreatePayload`;
|
|
336
|
+
const createResponseType = `${pascalStem}CreateResponse`;
|
|
337
|
+
const listResponseType = `${pascalStem}ListResponse`;
|
|
306
338
|
const apiPrefix = effectApiPrefix(service);
|
|
307
339
|
const checkoutCartSharedSchemas = createCheckoutCartSharedSchemas(service);
|
|
308
340
|
const checkoutCartSharedSchemaSection = '' === checkoutCartSharedSchemas ? '' : `${checkoutCartSharedSchemas}\n`;
|
|
309
341
|
const checkoutCartOperationContexts = createCheckoutCartOperationContexts(service).trimStart();
|
|
310
342
|
const checkoutCartOperationContextEntries = '' === checkoutCartOperationContexts ? '' : `${checkoutCartOperationContexts}\n`;
|
|
311
|
-
return `export
|
|
343
|
+
return `export interface ${markerType} {
|
|
344
|
+
readonly appId: string;
|
|
345
|
+
readonly build: string;
|
|
346
|
+
readonly deployProfile: string;
|
|
347
|
+
readonly packageName: string;
|
|
348
|
+
readonly surface: string;
|
|
349
|
+
readonly version: string;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
export interface ${itemType} {
|
|
353
|
+
readonly id: string;
|
|
354
|
+
readonly marker: ${markerType};
|
|
355
|
+
readonly title: string;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
export interface ${readinessType} {
|
|
359
|
+
readonly checks: {
|
|
360
|
+
readonly effectBff: 'ready';
|
|
361
|
+
readonly moduleFederation: 'ready';
|
|
362
|
+
readonly ssr: 'ready';
|
|
363
|
+
readonly translations: 'ready';
|
|
364
|
+
};
|
|
365
|
+
readonly marker: ${markerType};
|
|
366
|
+
readonly status: 'ready';
|
|
367
|
+
readonly versionSkew: 'none';
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
export interface ${createPayloadType} {
|
|
371
|
+
readonly title: string;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
export interface ${listResponseType} {
|
|
375
|
+
readonly items: readonly ${itemType}[];
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
export interface ${createResponseType} {
|
|
379
|
+
readonly item: ${itemType};
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
export interface ${notFoundErrorExport} {
|
|
383
|
+
readonly _tag: '${notFoundErrorExport}';
|
|
384
|
+
readonly id: string;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
export const ${markerSchemaExport}: Schema.Codec<${markerType}> = Schema.Struct({
|
|
312
388
|
appId: Schema.String,
|
|
313
389
|
build: Schema.String,
|
|
314
390
|
deployProfile: Schema.String,
|
|
@@ -317,13 +393,13 @@ function createEffectSharedApiContract(service) {
|
|
|
317
393
|
version: Schema.String,
|
|
318
394
|
});
|
|
319
395
|
|
|
320
|
-
export const ${schemaExport} = Schema.Struct({
|
|
396
|
+
export const ${schemaExport}: Schema.Codec<${itemType}> = Schema.Struct({
|
|
321
397
|
id: Schema.String,
|
|
322
398
|
marker: ${markerSchemaExport},
|
|
323
399
|
title: Schema.String,
|
|
324
400
|
});
|
|
325
401
|
|
|
326
|
-
export const ${readinessSchemaExport} = Schema.Struct({
|
|
402
|
+
export const ${readinessSchemaExport}: Schema.Codec<${readinessType}> = Schema.Struct({
|
|
327
403
|
checks: Schema.Struct({
|
|
328
404
|
effectBff: Schema.Literal('ready'),
|
|
329
405
|
moduleFederation: Schema.Literal('ready'),
|
|
@@ -335,18 +411,13 @@ export const ${readinessSchemaExport} = Schema.Struct({
|
|
|
335
411
|
versionSkew: Schema.Literal('none'),
|
|
336
412
|
});
|
|
337
413
|
|
|
338
|
-
export const ${createPayloadSchemaExport} = Schema.Struct({
|
|
414
|
+
export const ${createPayloadSchemaExport}: Schema.Codec<${createPayloadType}> = Schema.Struct({
|
|
339
415
|
title: Schema.String,
|
|
340
416
|
});
|
|
341
417
|
|
|
342
|
-
${checkoutCartSharedSchemaSection}export
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
id: Schema.String,
|
|
346
|
-
},
|
|
347
|
-
) {}
|
|
348
|
-
|
|
349
|
-
export const ${notFoundSchemaExport} = ${notFoundErrorExport}.pipe(
|
|
418
|
+
${checkoutCartSharedSchemaSection}export const ${notFoundSchemaExport}: Schema.Codec<${notFoundErrorExport}> = Schema.TaggedStruct('${notFoundErrorExport}', {
|
|
419
|
+
id: Schema.String,
|
|
420
|
+
}).pipe(
|
|
350
421
|
HttpApiSchema.status(404),
|
|
351
422
|
);
|
|
352
423
|
|
|
@@ -450,13 +521,20 @@ function createEffectServiceEntry(service, contractImportPath) {
|
|
|
450
521
|
HttpApiBuilder,
|
|
451
522
|
Layer,
|
|
452
523
|
} from '@modern-js/plugin-bff/effect-edge';
|
|
453
|
-
import {
|
|
524
|
+
import type {
|
|
525
|
+
EffectBffDefinition,
|
|
526
|
+
EffectBffRuntime,
|
|
527
|
+
EffectRuntimeLayer,
|
|
528
|
+
} from '@modern-js/plugin-bff/effect-edge';
|
|
529
|
+
import { ultramodernApiMarker } from '../../shared/ultramodern-build.ts';
|
|
454
530
|
import {
|
|
455
531
|
${apiExport},
|
|
456
532
|
${groupName}OperationContexts,
|
|
533
|
+
} from '${contractImportPath}';
|
|
534
|
+
import type {
|
|
457
535
|
${notFoundErrorExport},
|
|
536
|
+
OperationContext,
|
|
458
537
|
} from '${contractImportPath}';
|
|
459
|
-
import type { OperationContext } from '${contractImportPath}';
|
|
460
538
|
|
|
461
539
|
const ${groupName}Items = [
|
|
462
540
|
{
|
|
@@ -517,9 +595,13 @@ const ${groupName}Layer = HttpApiBuilder.group(
|
|
|
517
595
|
const matchedItem = ${groupName}Items.find(
|
|
518
596
|
candidate => candidate.id === params.id,
|
|
519
597
|
);
|
|
598
|
+
const notFound: ${notFoundErrorExport} = {
|
|
599
|
+
_tag: '${notFoundErrorExport}',
|
|
600
|
+
id: params.id,
|
|
601
|
+
};
|
|
520
602
|
const result =
|
|
521
603
|
matchedItem === undefined
|
|
522
|
-
? Effect.fail(
|
|
604
|
+
? Effect.fail(notFound)
|
|
523
605
|
: Effect.succeed(matchedItem);
|
|
524
606
|
|
|
525
607
|
return result.pipe(
|
|
@@ -550,12 +632,15 @@ const ${groupName}Layer = HttpApiBuilder.group(
|
|
|
550
632
|
|
|
551
633
|
const layer = HttpApiBuilder.layer(${apiExport}).pipe(
|
|
552
634
|
Layer.provide(${groupName}Layer),
|
|
553
|
-
);
|
|
635
|
+
) satisfies EffectRuntimeLayer;
|
|
554
636
|
|
|
555
|
-
|
|
637
|
+
const effectBff: EffectBffDefinition<typeof ${apiExport}, EffectRuntimeLayer> &
|
|
638
|
+
EffectBffRuntime<typeof ${apiExport}, EffectRuntimeLayer> = defineEffectBff({
|
|
556
639
|
api: ${apiExport},
|
|
557
640
|
layer,
|
|
558
641
|
});
|
|
642
|
+
|
|
643
|
+
export default effectBff;
|
|
559
644
|
`;
|
|
560
645
|
}
|
|
561
646
|
function createEffectClient(service, contractImportPath) {
|
|
@@ -566,25 +651,71 @@ function createEffectClient(service, contractImportPath) {
|
|
|
566
651
|
const singular = verticalEffectErrorStem(service);
|
|
567
652
|
const clientOptionsName = `${toPascalCase(stem)}ClientOptions`;
|
|
568
653
|
const createClientName = `create${toPascalCase(stem)}Client`;
|
|
654
|
+
const clientTypeName = `${toPascalCase(stem)}Client`;
|
|
655
|
+
const clientEffectTypeName = `${toPascalCase(stem)}ClientEffect`;
|
|
569
656
|
const listName = `list${toPascalCase(stem)}`;
|
|
570
657
|
const readinessName = `get${toPascalCase(stem)}Readiness`;
|
|
571
658
|
const getName = `get${toPascalCase(singular)}`;
|
|
572
659
|
const createName = `create${toPascalCase(singular)}`;
|
|
660
|
+
const notFoundErrorExport = verticalEffectNotFoundErrorExport(service);
|
|
661
|
+
const pascalStem = toPascalCase(stem);
|
|
662
|
+
const itemType = `${pascalStem}Item`;
|
|
663
|
+
const readinessType = `${pascalStem}Readiness`;
|
|
664
|
+
const createResponseType = `${pascalStem}CreateResponse`;
|
|
665
|
+
const listResponseType = `${pascalStem}ListResponse`;
|
|
573
666
|
const checkoutCartClientExports = createCheckoutCartClientExports(service);
|
|
574
667
|
return `import {
|
|
575
668
|
Effect,
|
|
576
669
|
makeEffectHttpApiClient,
|
|
577
670
|
runEffectRequest,
|
|
578
671
|
} from '@modern-js/plugin-bff/effect-client';
|
|
672
|
+
import type {
|
|
673
|
+
HttpClientError,
|
|
674
|
+
HttpApi,
|
|
675
|
+
HttpApiClient,
|
|
676
|
+
HttpApiGroup,
|
|
677
|
+
Schema,
|
|
678
|
+
} from '@modern-js/plugin-bff/effect-client';
|
|
579
679
|
import {
|
|
580
680
|
${contractExport}ApiContract,
|
|
581
681
|
${apiExport},
|
|
582
682
|
${groupName}OperationContexts,
|
|
583
683
|
} from '${contractImportPath}';
|
|
584
|
-
import type {
|
|
684
|
+
import type {
|
|
685
|
+
${createResponseType},
|
|
686
|
+
${itemType},
|
|
687
|
+
${listResponseType},
|
|
688
|
+
${notFoundErrorExport},
|
|
689
|
+
OperationContext,
|
|
690
|
+
${readinessType},
|
|
691
|
+
} from '${contractImportPath}';
|
|
585
692
|
|
|
586
693
|
export { Effect, runEffectRequest };
|
|
587
694
|
|
|
695
|
+
type ${pascalStem}EffectGroups = typeof ${apiExport} extends HttpApi.HttpApi<
|
|
696
|
+
infer _ApiId,
|
|
697
|
+
infer Groups
|
|
698
|
+
>
|
|
699
|
+
? Groups
|
|
700
|
+
: never;
|
|
701
|
+
|
|
702
|
+
export type ${clientTypeName} = HttpApiClient.Client<
|
|
703
|
+
Extract<${pascalStem}EffectGroups, HttpApiGroup.Any>,
|
|
704
|
+
never,
|
|
705
|
+
never
|
|
706
|
+
>;
|
|
707
|
+
|
|
708
|
+
export type ${pascalStem}ClientError =
|
|
709
|
+
| ${notFoundErrorExport}
|
|
710
|
+
| HttpClientError.HttpClientError
|
|
711
|
+
| Schema.SchemaError;
|
|
712
|
+
|
|
713
|
+
export type ${clientEffectTypeName}<Success> = Effect.Effect<
|
|
714
|
+
Success,
|
|
715
|
+
${pascalStem}ClientError,
|
|
716
|
+
never
|
|
717
|
+
>;
|
|
718
|
+
|
|
588
719
|
export interface ${clientOptionsName} {
|
|
589
720
|
baseUrl?: string | URL;
|
|
590
721
|
locale?: string;
|
|
@@ -594,7 +725,7 @@ export interface ${clientOptionsName} {
|
|
|
594
725
|
|
|
595
726
|
export const ${createClientName} = (
|
|
596
727
|
options: ${clientOptionsName} = {},
|
|
597
|
-
) =>
|
|
728
|
+
): ${clientEffectTypeName}<${clientTypeName}> =>
|
|
598
729
|
makeEffectHttpApiClient(${apiExport}, {
|
|
599
730
|
baseUrl: options.baseUrl ?? ${contractExport}ApiContract.apiPrefix,
|
|
600
731
|
requestContext: {
|
|
@@ -610,7 +741,7 @@ export const ${createClientName} = (
|
|
|
610
741
|
|
|
611
742
|
export const ${listName} = (
|
|
612
743
|
options: ${clientOptionsName} & { limit?: number } = {},
|
|
613
|
-
) =>
|
|
744
|
+
): ${clientEffectTypeName}<${listResponseType}> =>
|
|
614
745
|
${createClientName}({
|
|
615
746
|
...options,
|
|
616
747
|
operationContext:
|
|
@@ -623,7 +754,7 @@ export const ${listName} = (
|
|
|
623
754
|
|
|
624
755
|
export const ${readinessName} = (
|
|
625
756
|
options: ${clientOptionsName} = {},
|
|
626
|
-
) =>
|
|
757
|
+
): ${clientEffectTypeName}<${readinessType}> =>
|
|
627
758
|
${createClientName}({
|
|
628
759
|
...options,
|
|
629
760
|
operationContext:
|
|
@@ -635,7 +766,7 @@ export const ${readinessName} = (
|
|
|
635
766
|
export const ${getName} = (
|
|
636
767
|
id: string,
|
|
637
768
|
options: ${clientOptionsName} = {},
|
|
638
|
-
) =>
|
|
769
|
+
): ${clientEffectTypeName}<${itemType}> =>
|
|
639
770
|
${createClientName}({
|
|
640
771
|
...options,
|
|
641
772
|
operationContext:
|
|
@@ -647,7 +778,7 @@ export const ${getName} = (
|
|
|
647
778
|
export const ${createName} = (
|
|
648
779
|
title: string,
|
|
649
780
|
options: ${clientOptionsName} = {},
|
|
650
|
-
) =>
|
|
781
|
+
): ${clientEffectTypeName}<${createResponseType}> =>
|
|
651
782
|
${createClientName}({
|
|
652
783
|
...options,
|
|
653
784
|
operationContext:
|
|
@@ -123,7 +123,7 @@ ${bffConfig} ...(cloudflareDeployEnabled
|
|
|
123
123
|
},
|
|
124
124
|
output: {
|
|
125
125
|
assetPrefix,
|
|
126
|
-
disableTsChecker:
|
|
126
|
+
disableTsChecker: false,
|
|
127
127
|
distPath: {
|
|
128
128
|
html: './',
|
|
129
129
|
},
|
|
@@ -179,6 +179,10 @@ ${bffPluginEntry} moduleFederationPlugin(),
|
|
|
179
179
|
},
|
|
180
180
|
},
|
|
181
181
|
source: {
|
|
182
|
+
alias: {
|
|
183
|
+
'@modern-js/plugin-i18n/runtime':
|
|
184
|
+
'@modern-js/plugin-i18n/runtime/no-react-i18next',
|
|
185
|
+
},
|
|
182
186
|
globalVars: {
|
|
183
187
|
ULTRAMODERN_SITE_URL: siteUrl,
|
|
184
188
|
},
|
|
@@ -192,12 +196,6 @@ ${bffPluginEntry} moduleFederationPlugin(),
|
|
|
192
196
|
chain.output
|
|
193
197
|
.uniqueName('${createRspackUniqueName(app)}')
|
|
194
198
|
.chunkLoadingGlobal('${createRspackChunkLoadingGlobal(app)}');
|
|
195
|
-
chain.ignoreWarnings([
|
|
196
|
-
{
|
|
197
|
-
message: /the request of a dependency is an expression/u,
|
|
198
|
-
module: /modern-js-plugin-i18n/u,
|
|
199
|
-
},
|
|
200
|
-
]);
|
|
201
199
|
},
|
|
202
200
|
},
|
|
203
201
|
},
|
|
@@ -214,7 +212,7 @@ ${bffPluginEntry} moduleFederationPlugin(),
|
|
|
214
212
|
}
|
|
215
213
|
function createSharedModuleFederationConfig() {
|
|
216
214
|
return ` shared: {
|
|
217
|
-
'@modern-js/plugin-i18n/runtime': {
|
|
215
|
+
'@modern-js/plugin-i18n/runtime/no-react-i18next': {
|
|
218
216
|
requiredVersion: pluginI18nVersion,
|
|
219
217
|
singleton: true,
|
|
220
218
|
treeShaking: false,
|
|
@@ -334,7 +332,9 @@ const reactVersion = (require('react/package.json') as { version: string }).vers
|
|
|
334
332
|
const reactDomVersion = (require('react-dom/package.json') as { version: string }).version;
|
|
335
333
|
|
|
336
334
|
${createModuleFederationRemoteUrlHelpers(shellHost, remotes)}
|
|
337
|
-
|
|
335
|
+
const moduleFederationConfig: Parameters<
|
|
336
|
+
typeof createModuleFederationConfig
|
|
337
|
+
>[0] = createModuleFederationConfig({
|
|
338
338
|
bridge: {
|
|
339
339
|
enableBridgeRouter: false,
|
|
340
340
|
},
|
|
@@ -346,12 +346,15 @@ export default createModuleFederationConfig({
|
|
|
346
346
|
generateTypes: {
|
|
347
347
|
compilerInstance: 'tsgo',
|
|
348
348
|
},
|
|
349
|
+
tsConfigPath: './tsconfig.mf-types.json',
|
|
349
350
|
},
|
|
350
351
|
filename: 'remoteEntry.js',
|
|
351
352
|
name: '${shellApp.mfName}',
|
|
352
353
|
${createModuleFederationRemotesConfig(scope, shellHost, remotes)}${createSharedModuleFederationConfig()},
|
|
353
354
|
treeShakingSharedExcludePlugins: ['RspackModuleFederationPlugin'],
|
|
354
355
|
});
|
|
356
|
+
|
|
357
|
+
export default moduleFederationConfig;
|
|
355
358
|
`;
|
|
356
359
|
}
|
|
357
360
|
function createBuildMarker(scope, app) {
|
|
@@ -377,6 +380,14 @@ export const ultramodernApiMarker = {
|
|
|
377
380
|
} as const;
|
|
378
381
|
`;
|
|
379
382
|
}
|
|
383
|
+
function createUltramodernBuildReexportModule() {
|
|
384
|
+
return `export {
|
|
385
|
+
ultramodernApiMarker,
|
|
386
|
+
ultramodernUiMarker,
|
|
387
|
+
ultramodernVerticalIdentity,
|
|
388
|
+
} from '../shared/ultramodern-build';
|
|
389
|
+
`;
|
|
390
|
+
}
|
|
380
391
|
function createRemoteModuleFederationConfig(scope, app, remotes = []) {
|
|
381
392
|
const exposes = formatTsObjectLiteral(app.exposes ?? {});
|
|
382
393
|
return `// @effect-diagnostics nodeBuiltinImport:off
|
|
@@ -392,7 +403,9 @@ const reactVersion = (require('react/package.json') as { version: string }).vers
|
|
|
392
403
|
const reactDomVersion = (require('react-dom/package.json') as { version: string }).version;
|
|
393
404
|
|
|
394
405
|
${createModuleFederationRemoteUrlHelpers(app, remotes)}
|
|
395
|
-
|
|
406
|
+
const moduleFederationConfig: Parameters<
|
|
407
|
+
typeof createModuleFederationConfig
|
|
408
|
+
>[0] = createModuleFederationConfig({
|
|
396
409
|
bridge: {
|
|
397
410
|
enableBridgeRouter: false,
|
|
398
411
|
},
|
|
@@ -404,6 +417,7 @@ export default createModuleFederationConfig({
|
|
|
404
417
|
generateTypes: {
|
|
405
418
|
compilerInstance: 'tsgo',
|
|
406
419
|
},
|
|
420
|
+
tsConfigPath: './tsconfig.mf-types.json',
|
|
407
421
|
},
|
|
408
422
|
exposes: ${exposes},
|
|
409
423
|
filename: 'remoteEntry.js',
|
|
@@ -411,6 +425,8 @@ export default createModuleFederationConfig({
|
|
|
411
425
|
${createModuleFederationRemotesConfig(scope, app, remotes)}${createSharedModuleFederationConfig()},
|
|
412
426
|
treeShakingSharedExcludePlugins: ['RspackModuleFederationPlugin'],
|
|
413
427
|
});
|
|
428
|
+
|
|
429
|
+
export default moduleFederationConfig;
|
|
414
430
|
`;
|
|
415
431
|
}
|
|
416
|
-
export { createAppModernConfig, createBuildMarker, createModuleFederationRemoteUrlHelpers, createModuleFederationRemotesConfig, createRemoteModuleFederationConfig, createSharedModuleFederationConfig, createShellModuleFederationConfig, createUltramodernBuildModule, formatTsObjectLiteral };
|
|
432
|
+
export { createAppModernConfig, createBuildMarker, createModuleFederationRemoteUrlHelpers, createModuleFederationRemotesConfig, createRemoteModuleFederationConfig, createSharedModuleFederationConfig, createShellModuleFederationConfig, createUltramodernBuildModule, createUltramodernBuildReexportModule, formatTsObjectLiteral };
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import "node:module";
|
|
2
2
|
import { WORKSPACE_PACKAGE_VERSION, modernPackageSpecifier } from "../ultramodern-package-source.js";
|
|
3
|
-
import { appHasEffectApi, remoteDependencyAlias, resolveRemoteRefs, shellApp, verticalEffectApps, zephyrRemoteDependency } from "./descriptors.js";
|
|
3
|
+
import { appHasEffectApi, remoteDependencyAlias, resolveRemoteRefs, sharedPackages, shellApp, verticalEffectApps, zephyrRemoteDependency } from "./descriptors.js";
|
|
4
4
|
import { readFileTemplate } from "./fs-io.js";
|
|
5
5
|
import { packageName, relativeRootFor } from "./naming.js";
|
|
6
6
|
import { createPublicSurfaceGenerationCommand } from "./public-surface.js";
|
|
7
7
|
import { EFFECT_TSGO_VERSION, I18NEXT_VERSION, LEFTHOOK_VERSION, MODULE_FEDERATION_VERSION, NODE_FETCH_VERSION, OXFMT_VERSION, OXLINT_VERSION, PNPM_VERSION, POSTCSS_VERSION, REACT_DOM_VERSION, REACT_ROUTER_VERSION, REACT_VERSION, TAILWIND_POSTCSS_VERSION, TAILWIND_VERSION, TANSTACK_ROUTER_VERSION, TYPESCRIPT_NATIVE_PREVIEW_VERSION, TYPESCRIPT_VERSION, TYPES_REACT_DOM_VERSION, TYPES_REACT_VERSION, ULTRACITE_VERSION, WRANGLER_VERSION, ZEPHYR_AGENT_VERSION, ZEPHYR_RSPACK_PLUGIN_VERSION } from "./versions.js";
|
|
8
|
-
const
|
|
8
|
+
const createEffectTsgoTypecheckCommand = (packageDir)=>`node ${relativeRootFor(packageDir)}/scripts/ultramodern-typecheck.mjs --project tsconfig.json`;
|
|
9
9
|
const effectDiagnostics = [
|
|
10
10
|
'anyUnknownInErrorContext',
|
|
11
11
|
'classSelfMismatch',
|
|
@@ -151,7 +151,7 @@ function createRootPackageJson(scope, packageSource, remotes = []) {
|
|
|
151
151
|
'format:check': "oxfmt --check . '!repos/**'",
|
|
152
152
|
lint: 'oxlint apps verticals packages',
|
|
153
153
|
'lint:fix': 'oxlint apps verticals packages --fix',
|
|
154
|
-
typecheck:
|
|
154
|
+
typecheck: "node ./scripts/ultramodern-typecheck.mjs --build tsconfig.json",
|
|
155
155
|
'cloudflare:build': `${remoteCloudflareBuildPrefix}pnpm --filter "./apps/shell-super-app" run cloudflare:build && pnpm mf:types`,
|
|
156
156
|
'cloudflare:deploy': `${remoteCloudflareDeployPrefix}pnpm --filter "./apps/shell-super-app" run cloudflare:deploy`,
|
|
157
157
|
'cloudflare:proof': "node ./scripts/proof-cloudflare-version.mjs --out .codex/reports/cloudflare-version-proof/public-url-proof.json",
|
|
@@ -252,17 +252,93 @@ function createTsConfigBase() {
|
|
|
252
252
|
}
|
|
253
253
|
};
|
|
254
254
|
}
|
|
255
|
-
function
|
|
256
|
-
const
|
|
255
|
+
function createTsBuildInfoFile(packageDir) {
|
|
256
|
+
const cacheKey = packageDir.replace(/[^a-zA-Z0-9._-]+/gu, '__');
|
|
257
|
+
return `${relativeRootFor(packageDir)}/node_modules/.cache/tsgo/${cacheKey}.tsbuildinfo`;
|
|
258
|
+
}
|
|
259
|
+
function createTsDeclarationOutDir(packageDir) {
|
|
260
|
+
const cacheKey = packageDir.replace(/[^a-zA-Z0-9._-]+/gu, '__');
|
|
261
|
+
return `${relativeRootFor(packageDir)}/node_modules/.cache/tsgo/declarations/${cacheKey}`;
|
|
262
|
+
}
|
|
263
|
+
function createReferences(packageDir, references) {
|
|
264
|
+
return [
|
|
265
|
+
...new Set(references)
|
|
266
|
+
].filter((reference)=>reference !== packageDir).map((reference)=>({
|
|
267
|
+
path: `${relativeRootFor(packageDir)}/${reference}`
|
|
268
|
+
}));
|
|
269
|
+
}
|
|
270
|
+
function createPackageTsConfig(packageDir, options = {}) {
|
|
271
|
+
const resolvedOptions = 'boolean' == typeof options ? {
|
|
272
|
+
includeApi: options
|
|
273
|
+
} : options;
|
|
274
|
+
const include = resolvedOptions.include ?? [
|
|
257
275
|
'src',
|
|
276
|
+
'locales/**/*.json',
|
|
258
277
|
'modern.config.ts',
|
|
259
|
-
'module-federation.config.ts'
|
|
278
|
+
'module-federation.config.ts',
|
|
279
|
+
'package.json',
|
|
280
|
+
'shared'
|
|
260
281
|
];
|
|
261
|
-
if (includeApi) include.push('api'
|
|
262
|
-
|
|
282
|
+
if (resolvedOptions.includeApi) include.push('api');
|
|
283
|
+
const references = createReferences(packageDir, resolvedOptions.references ?? []);
|
|
284
|
+
const tsconfig = {
|
|
263
285
|
extends: `${relativeRootFor(packageDir)}/tsconfig.base.json`,
|
|
286
|
+
compilerOptions: {
|
|
287
|
+
composite: true,
|
|
288
|
+
declaration: true,
|
|
289
|
+
declarationMap: false,
|
|
290
|
+
emitDeclarationOnly: true,
|
|
291
|
+
incremental: true,
|
|
292
|
+
noEmit: false,
|
|
293
|
+
outDir: createTsDeclarationOutDir(packageDir),
|
|
294
|
+
tsBuildInfoFile: createTsBuildInfoFile(packageDir)
|
|
295
|
+
},
|
|
264
296
|
include
|
|
265
297
|
};
|
|
298
|
+
if (references.length > 0) tsconfig.references = references;
|
|
299
|
+
return tsconfig;
|
|
300
|
+
}
|
|
301
|
+
function createAppTsConfig(app, remotes = []) {
|
|
302
|
+
const references = [
|
|
303
|
+
...sharedPackages.map((sharedPackage)=>sharedPackage.directory),
|
|
304
|
+
...'shell' === app.kind ? verticalEffectApps(remotes).map((remote)=>remote.directory) : resolveRemoteRefs(app, remotes).map((remote)=>remote.directory)
|
|
305
|
+
];
|
|
306
|
+
return createPackageTsConfig(app.directory, {
|
|
307
|
+
includeApi: appHasEffectApi(app),
|
|
308
|
+
references
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
function createAppMfTypesTsConfig(app) {
|
|
312
|
+
const exposedFiles = Object.values(app.exposes ?? {}).map((exposePath)=>exposePath.replace(/^\.\//u, ''));
|
|
313
|
+
return {
|
|
314
|
+
extends: './tsconfig.json',
|
|
315
|
+
include: [
|
|
316
|
+
...new Set([
|
|
317
|
+
...exposedFiles,
|
|
318
|
+
'src/modern-app-env.d.ts'
|
|
319
|
+
])
|
|
320
|
+
]
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
function createSharedPackageTsConfig(packageDir) {
|
|
324
|
+
return createPackageTsConfig(packageDir, {
|
|
325
|
+
include: [
|
|
326
|
+
'src'
|
|
327
|
+
]
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
function createRootTsConfig(apps = []) {
|
|
331
|
+
return {
|
|
332
|
+
files: [],
|
|
333
|
+
references: [
|
|
334
|
+
...sharedPackages.map((sharedPackage)=>({
|
|
335
|
+
path: sharedPackage.directory
|
|
336
|
+
})),
|
|
337
|
+
...apps.map((app)=>({
|
|
338
|
+
path: app.directory
|
|
339
|
+
}))
|
|
340
|
+
]
|
|
341
|
+
};
|
|
266
342
|
}
|
|
267
343
|
function createAppPackage(scope, app, packageSource, enableTailwind, remotes = []) {
|
|
268
344
|
const publicSurfaceBuildCommand = createPublicSurfaceGenerationCommand(app, 'dist');
|
|
@@ -284,7 +360,7 @@ function createAppPackage(scope, app, packageSource, enableTailwind, remotes = [
|
|
|
284
360
|
'cloudflare:preview': 'pnpm run cloudflare:build && wrangler dev --config .output/wrangler.json',
|
|
285
361
|
'cloudflare:proof': `node ${relativeRootFor(app.directory)}/scripts/proof-cloudflare-version.mjs --app ${app.id}`,
|
|
286
362
|
serve: 'modern serve',
|
|
287
|
-
typecheck:
|
|
363
|
+
typecheck: createEffectTsgoTypecheckCommand(app.directory)
|
|
288
364
|
},
|
|
289
365
|
modernjs: {
|
|
290
366
|
preset: 'presetUltramodern',
|
|
@@ -320,7 +396,7 @@ function createSharedPackage(scope, id, description) {
|
|
|
320
396
|
'.': './src/index.ts'
|
|
321
397
|
},
|
|
322
398
|
scripts: {
|
|
323
|
-
typecheck:
|
|
399
|
+
typecheck: createEffectTsgoTypecheckCommand(`packages/${id}`)
|
|
324
400
|
},
|
|
325
401
|
devDependencies: {
|
|
326
402
|
'@effect/tsgo': EFFECT_TSGO_VERSION,
|
|
@@ -336,4 +412,4 @@ function createSharedPackage(scope, id, description) {
|
|
|
336
412
|
function createSharedContractsIndex() {
|
|
337
413
|
return readFileTemplate('packages/shared-contracts-index.ts');
|
|
338
414
|
}
|
|
339
|
-
export { appDependencies, appDevDependencies, createAppPackage, createPackageTsConfig, createRootPackageJson, createSharedContractsIndex, createSharedPackage, createTsConfigBase, createZephyrDependencies, effectDiagnostics
|
|
415
|
+
export { appDependencies, appDevDependencies, createAppMfTypesTsConfig, createAppPackage, createAppTsConfig, createEffectTsgoTypecheckCommand, createPackageTsConfig, createRootPackageJson, createRootTsConfig, createSharedContractsIndex, createSharedPackage, createSharedPackageTsConfig, createTsConfigBase, createZephyrDependencies, effectDiagnostics };
|
|
@@ -10,9 +10,8 @@ const TAILWIND_POSTCSS_VERSION = '4.3.1';
|
|
|
10
10
|
const POSTCSS_VERSION = '8.5.15';
|
|
11
11
|
const EFFECT_TSGO_VERSION = '0.14.6';
|
|
12
12
|
const TYPESCRIPT_STABLE_VERSION = '6.0.3';
|
|
13
|
-
const TYPESCRIPT_7_VERSION = '7.0.1-rc';
|
|
14
|
-
const TYPESCRIPT_VERSION = TYPESCRIPT_7_VERSION;
|
|
15
13
|
const TYPESCRIPT_NATIVE_PREVIEW_VERSION = '7.0.0-dev.20260624.1';
|
|
14
|
+
const TYPESCRIPT_VERSION = TYPESCRIPT_STABLE_VERSION;
|
|
16
15
|
const OXLINT_VERSION = '1.71.0';
|
|
17
16
|
const OXFMT_VERSION = '0.55.0';
|
|
18
17
|
const ULTRACITE_VERSION = '7.8.3';
|
|
@@ -34,4 +33,4 @@ const ultramodernWorkspaceVersions = {
|
|
|
34
33
|
tailwind: TAILWIND_VERSION,
|
|
35
34
|
tailwindPostcss: TAILWIND_POSTCSS_VERSION
|
|
36
35
|
};
|
|
37
|
-
export { CLOUDFLARE_COMPATIBILITY_DATE, EFFECT_TSGO_VERSION, I18NEXT_VERSION, LEFTHOOK_VERSION, MODULE_FEDERATION_AGENT_SKILLS_COMMIT, MODULE_FEDERATION_VERSION, NODE_FETCH_VERSION, NODE_VERSION, OXFMT_VERSION, OXLINT_VERSION, PNPM_VERSION, POSTCSS_VERSION, REACT_DOM_VERSION, REACT_ROUTER_VERSION, REACT_VERSION, RSTACK_AGENT_SKILLS_COMMIT, TAILWIND_POSTCSS_VERSION, TAILWIND_VERSION, TANSTACK_ROUTER_VERSION,
|
|
36
|
+
export { CLOUDFLARE_COMPATIBILITY_DATE, EFFECT_TSGO_VERSION, I18NEXT_VERSION, LEFTHOOK_VERSION, MODULE_FEDERATION_AGENT_SKILLS_COMMIT, MODULE_FEDERATION_VERSION, NODE_FETCH_VERSION, NODE_VERSION, OXFMT_VERSION, OXLINT_VERSION, PNPM_VERSION, POSTCSS_VERSION, REACT_DOM_VERSION, REACT_ROUTER_VERSION, REACT_VERSION, RSTACK_AGENT_SKILLS_COMMIT, TAILWIND_POSTCSS_VERSION, TAILWIND_VERSION, TANSTACK_ROUTER_VERSION, TYPESCRIPT_NATIVE_PREVIEW_VERSION, TYPESCRIPT_STABLE_VERSION, TYPESCRIPT_VERSION, TYPES_REACT_DOM_VERSION, TYPES_REACT_VERSION, ULTRACITE_VERSION, WRANGLER_VERSION, ZEPHYR_AGENT_VERSION, ZEPHYR_RSPACK_PLUGIN_VERSION, ultramodernWorkspaceVersions };
|
|
@@ -80,6 +80,9 @@ function createPerformanceReadinessConfigScript() {
|
|
|
80
80
|
function createPerformanceReadinessScript() {
|
|
81
81
|
return readFileTemplate("workspace-scripts/ultramodern-performance-readiness.mjs");
|
|
82
82
|
}
|
|
83
|
+
function createUltramodernTypecheckScript() {
|
|
84
|
+
return readFileTemplate("workspace-scripts/ultramodern-typecheck.mjs");
|
|
85
|
+
}
|
|
83
86
|
function writeGeneratedWorkspaceScripts(targetDir, scope, enableTailwind, remotes = []) {
|
|
84
87
|
writeFileReplacing(targetDir, "scripts/assert-mf-types.mjs", createAssertMfTypesScript(remotes));
|
|
85
88
|
writeFileReplacing(targetDir, "scripts/validate-ultramodern-workspace.mjs", createWorkspaceValidationScript(scope, enableTailwind, remotes));
|
|
@@ -89,5 +92,6 @@ function writeGeneratedWorkspaceScripts(targetDir, scope, enableTailwind, remote
|
|
|
89
92
|
writeFileReplacing(targetDir, "scripts/proof-cloudflare-version.mjs", createCloudflareVersionProofScript());
|
|
90
93
|
writeFileReplacing(targetDir, "scripts/ultramodern-performance-readiness.config.mjs", createPerformanceReadinessConfigScript());
|
|
91
94
|
writeFileReplacing(targetDir, "scripts/ultramodern-performance-readiness.mjs", createPerformanceReadinessScript());
|
|
95
|
+
writeFileReplacing(targetDir, "scripts/ultramodern-typecheck.mjs", createUltramodernTypecheckScript());
|
|
92
96
|
}
|
|
93
|
-
export { createAssertMfTypesScript, createCloudflareProofHelperScript, createCloudflareVersionProofScript, createPerformanceReadinessConfigScript, createPerformanceReadinessScript, createPublicSurfaceAssetsScript, createWorkspaceI18nBoundaryValidationScript, createWorkspaceValidationScript, writeGeneratedWorkspaceScripts };
|
|
97
|
+
export { createAssertMfTypesScript, createCloudflareProofHelperScript, createCloudflareVersionProofScript, createPerformanceReadinessConfigScript, createPerformanceReadinessScript, createPublicSurfaceAssetsScript, createUltramodernTypecheckScript, createWorkspaceI18nBoundaryValidationScript, createWorkspaceValidationScript, writeGeneratedWorkspaceScripts };
|