@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.
Files changed (49) hide show
  1. package/README.md +7 -7
  2. package/dist/cjs/ultramodern-workspace/add-vertical.cjs +24 -0
  3. package/dist/cjs/ultramodern-workspace/contracts.cjs +8 -4
  4. package/dist/cjs/ultramodern-workspace/demo-components.cjs +14 -21
  5. package/dist/cjs/ultramodern-workspace/descriptors.cjs +2 -2
  6. package/dist/cjs/ultramodern-workspace/effect-api.cjs +162 -31
  7. package/dist/cjs/ultramodern-workspace/module-federation.cjs +29 -10
  8. package/dist/cjs/ultramodern-workspace/package-json.cjs +102 -14
  9. package/dist/cjs/ultramodern-workspace/versions.cjs +1 -5
  10. package/dist/cjs/ultramodern-workspace/workspace-scripts.cjs +7 -0
  11. package/dist/cjs/ultramodern-workspace/write-workspace.cjs +6 -8
  12. package/dist/esm/ultramodern-workspace/add-vertical.js +25 -1
  13. package/dist/esm/ultramodern-workspace/contracts.js +9 -5
  14. package/dist/esm/ultramodern-workspace/demo-components.js +14 -21
  15. package/dist/esm/ultramodern-workspace/descriptors.js +2 -2
  16. package/dist/esm/ultramodern-workspace/effect-api.js +162 -31
  17. package/dist/esm/ultramodern-workspace/module-federation.js +27 -11
  18. package/dist/esm/ultramodern-workspace/package-json.js +87 -11
  19. package/dist/esm/ultramodern-workspace/versions.js +2 -3
  20. package/dist/esm/ultramodern-workspace/workspace-scripts.js +5 -1
  21. package/dist/esm/ultramodern-workspace/write-workspace.js +9 -11
  22. package/dist/esm-node/ultramodern-workspace/add-vertical.js +25 -1
  23. package/dist/esm-node/ultramodern-workspace/contracts.js +9 -5
  24. package/dist/esm-node/ultramodern-workspace/demo-components.js +14 -21
  25. package/dist/esm-node/ultramodern-workspace/descriptors.js +2 -2
  26. package/dist/esm-node/ultramodern-workspace/effect-api.js +162 -31
  27. package/dist/esm-node/ultramodern-workspace/module-federation.js +27 -11
  28. package/dist/esm-node/ultramodern-workspace/package-json.js +87 -11
  29. package/dist/esm-node/ultramodern-workspace/versions.js +2 -3
  30. package/dist/esm-node/ultramodern-workspace/workspace-scripts.js +5 -1
  31. package/dist/esm-node/ultramodern-workspace/write-workspace.js +9 -11
  32. package/dist/types/ultramodern-workspace/module-federation.d.ts +1 -0
  33. package/dist/types/ultramodern-workspace/package-json.d.ts +12 -2
  34. package/dist/types/ultramodern-workspace/versions.d.ts +1 -2
  35. package/dist/types/ultramodern-workspace/workspace-scripts.d.ts +1 -0
  36. package/package.json +4 -4
  37. package/template-workspace/AGENTS.md.handlebars +2 -1
  38. package/template-workspace/README.md.handlebars +7 -0
  39. package/template-workspace/oxfmt.config.ts +3 -1
  40. package/template-workspace/oxlint.config.ts +3 -1
  41. package/template-workspace/patches/@tanstack__router-core@1.171.13.patch +51 -0
  42. package/template-workspace/pnpm-workspace.yaml.handlebars +11 -0
  43. package/template-workspace/scripts/bootstrap-agent-skills.mjs +42 -10
  44. package/templates/app/shell-frame.tsx +1 -2
  45. package/templates/app/ultramodern-route-head.tsx.handlebars +22 -11
  46. package/templates/packages/shared-contracts-index.ts +206 -272
  47. package/templates/workspace-scripts/assert-mf-types.mjs.handlebars +9 -0
  48. package/templates/workspace-scripts/ultramodern-typecheck.mjs +197 -0
  49. 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 const checkoutCartLineSchema = Schema.Struct({
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 const ${markerSchemaExport} = Schema.Struct({
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 class ${notFoundErrorExport} extends Schema.TaggedErrorClass<${notFoundErrorExport}>()(
343
- '${notFoundErrorExport}',
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 { ultramodernApiMarker } from '../../src/ultramodern-build.ts';
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(new ${notFoundErrorExport}({ id: params.id }))
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
- export default defineEffectBff({
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 { OperationContext } from '${contractImportPath}';
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: true,
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
- export default createModuleFederationConfig({
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
- export default createModuleFederationConfig({
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 effectTsgoTypecheckCommand = "node -e \"const fs = require('node:fs'); const { execFileSync, spawnSync } = require('node:child_process'); const bin = execFileSync('effect-tsgo', ['get-exe-path'], { encoding: 'utf8' }).trim(); if (process.platform !== 'win32') fs.chmodSync(bin, 0o755); const result = spawnSync(bin, ['--noEmit', '-p', 'tsconfig.json'], { stdio: 'inherit' }); process.exit(result.status ?? 1);\"";
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: `pnpm -r --filter "@${scope}/*" 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 createPackageTsConfig(packageDir, includeApi = false) {
256
- const include = [
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', 'shared');
262
- return {
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: effectTsgoTypecheckCommand
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: effectTsgoTypecheckCommand
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, effectTsgoTypecheckCommand };
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, TYPESCRIPT_7_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 };
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 };