@bleedingdev/modern-js-ultramodern-create 3.9.3-ultramodern.1 → 3.9.3-ultramodern.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/dist/cjs/ultramodern-workspace/add-vertical/shell-files.cjs +2 -7
  2. package/dist/cjs/ultramodern-workspace/api/client.cjs +2 -37
  3. package/dist/cjs/ultramodern-workspace/api.cjs +0 -3
  4. package/dist/cjs/ultramodern-workspace/native-app.cjs +0 -2
  5. package/dist/cjs/ultramodern-workspace/package-json.cjs +1 -3
  6. package/dist/cjs/ultramodern-workspace/validation/architecture.cjs +24 -11
  7. package/dist/cjs/ultramodern-workspace/validation/native-shell-runtime.cjs +134 -0
  8. package/dist/cjs/ultramodern-workspace/write-app.cjs +1 -3
  9. package/dist/esm/ultramodern-workspace/add-vertical/shell-files.js +3 -8
  10. package/dist/esm/ultramodern-workspace/api/client.js +4 -36
  11. package/dist/esm/ultramodern-workspace/api.js +1 -1
  12. package/dist/esm/ultramodern-workspace/native-app.js +0 -2
  13. package/dist/esm/ultramodern-workspace/package-json.js +1 -3
  14. package/dist/esm/ultramodern-workspace/validation/architecture.js +24 -11
  15. package/dist/esm/ultramodern-workspace/validation/native-shell-runtime.js +96 -0
  16. package/dist/esm/ultramodern-workspace/write-app.js +1 -3
  17. package/dist/esm-node/ultramodern-workspace/add-vertical/shell-files.js +3 -8
  18. package/dist/esm-node/ultramodern-workspace/api/client.js +4 -36
  19. package/dist/esm-node/ultramodern-workspace/api.js +1 -1
  20. package/dist/esm-node/ultramodern-workspace/native-app.js +0 -2
  21. package/dist/esm-node/ultramodern-workspace/package-json.js +1 -3
  22. package/dist/esm-node/ultramodern-workspace/validation/architecture.js +24 -11
  23. package/dist/esm-node/ultramodern-workspace/validation/native-shell-runtime.js +97 -0
  24. package/dist/esm-node/ultramodern-workspace/write-app.js +1 -3
  25. package/dist/types/ultramodern-workspace/api/client.d.ts +1 -2
  26. package/dist/types/ultramodern-workspace/api.d.ts +1 -1
  27. package/dist/types/ultramodern-workspace/validation/native-shell-runtime.d.ts +19 -0
  28. package/package.json +18 -18
  29. package/release-cohort.json +51 -51
  30. package/templates/workspace-scripts/proof-workerd-ssr.mjs +371 -38
@@ -45,7 +45,6 @@ const external_node_fs_namespaceObject = require("node:fs");
45
45
  var external_node_fs_default = /*#__PURE__*/ __webpack_require__.n(external_node_fs_namespaceObject);
46
46
  const external_node_path_namespaceObject = require("node:path");
47
47
  var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
48
- const external_api_cjs_namespaceObject = require("../api.cjs");
49
48
  const external_app_files_cjs_namespaceObject = require("../app-files.cjs");
50
49
  const external_demo_components_cjs_namespaceObject = require("../demo-components.cjs");
51
50
  const external_descriptors_cjs_namespaceObject = require("../descriptors.cjs");
@@ -85,10 +84,7 @@ function shellAppArtifacts(scope, packageSource, enableTailwind, remotes, bridge
85
84
  ...Object.fromEntries((0, external_native_federation_cjs_namespaceObject.createNativeFederationArtifacts)(scope, shellHost, remotes).map((artifact)=>[
86
85
  `${shellHost.directory}/${artifact.path}`,
87
86
  artifact.content
88
- ])),
89
- ...remotes.some(external_descriptors_cjs_namespaceObject.appHasApi) ? {
90
- [`${shellHost.directory}/src/api/vertical-clients.ts`]: (0, external_api_cjs_namespaceObject.createShellApiClient)(scope, remotes)
91
- } : {}
87
+ ]))
92
88
  };
93
89
  return {
94
90
  shellHost,
@@ -128,8 +124,7 @@ function shellAppArtifacts(scope, packageSource, enableTailwind, remotes, bridge
128
124
  [`${shellHost.directory}/src/routes/[lang]/page.tsx`]: (0, external_demo_components_cjs_namespaceObject.createShellPage)(shellHost, uiRemotes),
129
125
  [`${shellHost.directory}/src/routes/vertical-components.tsx`]: (0, external_demo_components_cjs_namespaceObject.createShellRemoteComponents)(shellHost, uiRemotes),
130
126
  [`${shellHost.directory}/src/routes/vertical-components.worker.tsx`]: (0, external_demo_components_cjs_namespaceObject.createShellWorkerRemoteComponents)(shellHost, uiRemotes),
131
- [`${shellHost.directory}/src/routes/shell-frame.tsx`]: (0, external_app_files_cjs_namespaceObject.createShellFrameComponent)(shellHost),
132
- [`${shellHost.directory}/src/api/vertical-clients.ts`]: (0, external_api_cjs_namespaceObject.createShellApiClient)(scope, remotes)
127
+ [`${shellHost.directory}/src/routes/shell-frame.tsx`]: (0, external_app_files_cjs_namespaceObject.createShellFrameComponent)(shellHost)
133
128
  };
134
129
  return {
135
130
  shellHost,
@@ -28,8 +28,7 @@ var __webpack_require__ = {};
28
28
  var __webpack_exports__ = {};
29
29
  __webpack_require__.r(__webpack_exports__);
30
30
  __webpack_require__.d(__webpack_exports__, {
31
- createApiClient: ()=>createApiClient,
32
- createShellApiClient: ()=>createShellApiClient
31
+ createApiClient: ()=>createApiClient
33
32
  });
34
33
  const external_descriptors_cjs_namespaceObject = require("../descriptors.cjs");
35
34
  const external_naming_cjs_namespaceObject = require("../naming.cjs");
@@ -181,43 +180,9 @@ export const ${createName} = (
181
180
  );${checkoutCartClientExports}
182
181
  `;
183
182
  }
184
- function createShellApiClient(scope, remotes = []) {
185
- const exports1 = (0, external_descriptors_cjs_namespaceObject.verticalApiApps)(remotes).map((remote)=>{
186
- const stem = (0, external_descriptors_cjs_namespaceObject.resolveApiStem)(remote);
187
- const pascalStem = (0, external_naming_cjs_namespaceObject.toPascalCase)(stem);
188
- const rpc = 'rpc' === (0, external_descriptors_cjs_namespaceObject.resolveApiProtocol)(remote);
189
- const pascalSingular = (0, external_naming_cjs_namespaceObject.toPascalCase)((0, external_names_cjs_namespaceObject.verticalApiErrorStem)(remote));
190
- const checkoutCartExports = !rpc && (0, external_checkout_cart_cjs_namespaceObject.serviceHasCheckoutCartState)(remote) ? ` addCheckoutCartItem,
191
- clearCheckoutCart,
192
- getCheckoutCart,
193
- removeCheckoutCartItem,
194
- type CheckoutAddCartItemInput,
195
- type CheckoutCart,
196
- type CheckoutCartLine,
197
- ` : '';
198
- if (rpc) return `export {
199
- get${pascalStem}Rpc,
200
- list${pascalStem}Rpc,
201
- make${pascalStem}RpcClient,
202
- type ${pascalStem}RpcClientOptions,
203
- } from '${(0, external_naming_cjs_namespaceObject.packageName)(scope, remote.packageSuffix)}/api/rpc-client';`;
204
- return `export {
205
- ${checkoutCartExports} create${pascalSingular},
206
- create${pascalStem}Client,
207
- get${pascalSingular},
208
- get${pascalStem}Readiness,
209
- list${pascalStem},
210
- type ${pascalStem}ClientOptions,
211
- } from '${(0, external_naming_cjs_namespaceObject.packageName)(scope, remote.packageSuffix)}/api/client';`;
212
- }).join('\n\n');
213
- return exports1 ? `${exports1}\n` : `export const ultramodernVerticalClients = [] as const;
214
- `;
215
- }
216
183
  exports.createApiClient = __webpack_exports__.createApiClient;
217
- exports.createShellApiClient = __webpack_exports__.createShellApiClient;
218
184
  for(var __rspack_i in __webpack_exports__)if (-1 === [
219
- "createApiClient",
220
- "createShellApiClient"
185
+ "createApiClient"
221
186
  ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
222
187
  Object.defineProperty(exports, '__esModule', {
223
188
  value: true
@@ -36,7 +36,6 @@ __webpack_require__.d(__webpack_exports__, {
36
36
  createRpcClientFile: ()=>rpc_cjs_namespaceObject.createRpcClientFile,
37
37
  createRpcContractFile: ()=>rpc_cjs_namespaceObject.createRpcContractFile,
38
38
  createSharedApi: ()=>shared_cjs_namespaceObject.createSharedApi,
39
- createShellApiClient: ()=>client_cjs_namespaceObject.createShellApiClient,
40
39
  rpcPath: ()=>rpc_cjs_namespaceObject.rpcPath,
41
40
  verticalApiCreatePayloadSchemaExport: ()=>names_cjs_namespaceObject.verticalApiCreatePayloadSchemaExport,
42
41
  verticalApiErrorStem: ()=>names_cjs_namespaceObject.verticalApiErrorStem,
@@ -65,7 +64,6 @@ exports.createRpcApiServiceEntry = __webpack_exports__.createRpcApiServiceEntry;
65
64
  exports.createRpcClientFile = __webpack_exports__.createRpcClientFile;
66
65
  exports.createRpcContractFile = __webpack_exports__.createRpcContractFile;
67
66
  exports.createSharedApi = __webpack_exports__.createSharedApi;
68
- exports.createShellApiClient = __webpack_exports__.createShellApiClient;
69
67
  exports.rpcPath = __webpack_exports__.rpcPath;
70
68
  exports.verticalApiCreatePayloadSchemaExport = __webpack_exports__.verticalApiCreatePayloadSchemaExport;
71
69
  exports.verticalApiErrorStem = __webpack_exports__.verticalApiErrorStem;
@@ -88,7 +86,6 @@ for(var __rspack_i in __webpack_exports__)if (-1 === [
88
86
  "createRpcClientFile",
89
87
  "createRpcContractFile",
90
88
  "createSharedApi",
91
- "createShellApiClient",
92
89
  "rpcPath",
93
90
  "verticalApiCreatePayloadSchemaExport",
94
91
  "verticalApiErrorStem",
@@ -30,7 +30,6 @@ __webpack_require__.r(__webpack_exports__);
30
30
  __webpack_require__.d(__webpack_exports__, {
31
31
  writeNativeApp: ()=>writeNativeApp
32
32
  });
33
- const external_api_cjs_namespaceObject = require("./api.cjs");
34
33
  const write_app_api_cjs_namespaceObject = require("./api/write-app-api.cjs");
35
34
  const external_app_files_cjs_namespaceObject = require("./app-files.cjs");
36
35
  const external_descriptors_cjs_namespaceObject = require("./descriptors.cjs");
@@ -93,7 +92,6 @@ function writeNativeApp(targetDir, scope, app, packageSource, enableTailwind, re
93
92
  resolvedApp: app,
94
93
  emitsUi: true
95
94
  });
96
- if ('shell' === app.kind && remotes.some(external_descriptors_cjs_namespaceObject.appHasApi)) write('src/api/vertical-clients.ts', (0, external_api_cjs_namespaceObject.createShellApiClient)(scope, remotes));
97
95
  }
98
96
  exports.writeNativeApp = __webpack_exports__.writeNativeApp;
99
97
  for(var __rspack_i in __webpack_exports__)if (-1 === [
@@ -312,9 +312,7 @@ function createAppPackage(scope, app, packageSource, enableTailwind, remotes = [
312
312
  './api': './shared/api.ts',
313
313
  './api/client': `./${clientDirectory}/${app.api.stem}-client.ts`
314
314
  });
315
- } else if ('shell' === app.kind && ('react' === (0, external_renderer_profile_cjs_namespaceObject.resolveWorkspaceRenderer)(app) || (0, external_descriptors_cjs_namespaceObject.verticalApiApps)(remotes).length > 0)) Object.assign(packageExports, {
316
- './api/clients': './src/api/vertical-clients.ts'
317
- });
315
+ }
318
316
  if (Object.keys(packageExports).length > 0) packageJson.exports = packageExports;
319
317
  return packageJson;
320
318
  }
@@ -47,6 +47,7 @@ var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_no
47
47
  const external_renderer_generations_cjs_namespaceObject = require("../renderer-generations.cjs");
48
48
  const external_renderer_profile_cjs_namespaceObject = require("../renderer-profile.cjs");
49
49
  const external_assertions_cjs_namespaceObject = require("./assertions.cjs");
50
+ const external_native_shell_runtime_cjs_namespaceObject = require("./native-shell-runtime.cjs");
50
51
  const external_renderer_cjs_namespaceObject = require("./renderer.cjs");
51
52
  function assertCompilerArchitecture(root, workspaceValidationContract) {
52
53
  const fullStackVerticals = workspaceValidationContract.apps.filter((app)=>'shell' !== app.kind);
@@ -105,12 +106,16 @@ function assertCompilerArchitecture(root, workspaceValidationContract) {
105
106
  ]
106
107
  });
107
108
  };
108
- const parseCompilerInput = (absolutePath)=>{
109
+ const compilerInput = (absolutePath)=>{
109
110
  const project = compilerSnapshot?.getDefaultProjectForFile(absolutePath);
110
111
  const sourceFile = project?.program.getSourceFile(absolutePath);
111
- (0, external_assertions_cjs_namespaceObject.assert)(void 0 !== sourceFile, `Native TypeScript compiler could not parse ${external_node_path_default().relative(root, absolutePath)}`);
112
- return sourceFile;
112
+ (0, external_assertions_cjs_namespaceObject.assert)(void 0 !== project && void 0 !== sourceFile, `Native TypeScript compiler could not parse ${external_node_path_default().relative(root, absolutePath)}`);
113
+ return {
114
+ checker: project.checker,
115
+ sourceFile
116
+ };
113
117
  };
118
+ const parseCompilerInput = (absolutePath)=>compilerInput(absolutePath).sourceFile;
114
119
  const nodeName = (node)=>{
115
120
  if (!node) return;
116
121
  if (typescript.isIdentifier(node) || typescript.isPrivateIdentifier(node) || typescript.isStringLiteralLikeNode(node) || typescript.isNumericLiteral(node)) return node.text;
@@ -198,6 +203,12 @@ function assertCompilerArchitecture(root, workspaceValidationContract) {
198
203
  const accessPath = propertyAccessPath(node.expression);
199
204
  return void 0 !== accessPath && names.has(accessPath.at(-1));
200
205
  };
206
+ const calleeName = (node)=>{
207
+ let callee = node.expression;
208
+ while(typescript.isParenthesizedExpression(callee) || typescript.isNonNullExpression(callee) || typescript.isAsExpression(callee))callee = callee.expression;
209
+ if (typescript.isIdentifier(callee)) return callee.text;
210
+ if (typescript.isPropertyAccessExpression(callee)) return callee.name.text;
211
+ };
201
212
  const objectLiteralProperty = (objectLiteral, name)=>objectLiteral.properties.find((property)=>typescript.isPropertyAssignment(property) && nodeName(property.name) === name);
202
213
  const moduleFederationConfigArgument = (sourceFile)=>{
203
214
  let argument;
@@ -345,11 +356,12 @@ function assertCompilerArchitecture(root, workspaceValidationContract) {
345
356
  ...configFiles.map((relativePath)=>external_node_path_default().join(root, relativePath)).filter((absolutePath)=>external_node_fs_default().existsSync(absolutePath))
346
357
  ]);
347
358
  for (const absolutePath of checkedFiles){
348
- const sourceFile = parseCompilerInput(absolutePath);
359
+ const { checker, sourceFile } = compilerInput(absolutePath);
349
360
  const isShellRoute = shellRouteDirectories.some((relativeDirectory)=>{
350
361
  const absoluteDirectory = external_node_path_default().join(root, relativeDirectory);
351
362
  return absolutePath.startsWith(absoluteDirectory + external_node_path_default().sep);
352
363
  });
364
+ const shellRuntime = isShellRoute ? (0, external_native_shell_runtime_cjs_namespaceObject.createNativeShellRuntimeEvidence)(typescript, typescriptApi, checker, sourceFile) : void 0;
353
365
  const moduleFederationAppPath = moduleFederationConfigAppPaths.get(absolutePath);
354
366
  const nativeFederation = void 0 === moduleFederationAppPath ? void 0 : nativeModuleFederationApps.get(moduleFederationAppPath);
355
367
  const tailwindFactories = new Set();
@@ -372,6 +384,12 @@ function assertCompilerArchitecture(root, workspaceValidationContract) {
372
384
  ].includes(imported)) presetFactories.add(binding.name.text);
373
385
  }
374
386
  }
387
+ const manualLoadingCallees = new Set([
388
+ 'hydrateRoot',
389
+ 'loadRemote',
390
+ 'loadShare',
391
+ ...nativeRemoteLoaders
392
+ ]);
375
393
  const modernConfigApp = workspaceValidationContract.apps.find((app)=>absolutePath === external_node_path_default().join(root, app.path, 'modern.config.ts'));
376
394
  let insideDefaultExport = false;
377
395
  const visit = (node)=>{
@@ -399,7 +417,7 @@ function assertCompilerArchitecture(root, workspaceValidationContract) {
399
417
  if ((0, external_assertions_cjs_namespaceObject.sameJson)(accessPath, [
400
418
  'process',
401
419
  'env'
402
- ])) compilerFailure(sourceFile, node, 'framework config API direct-process-env-access', 'Generated config must use the framework config environment API instead of process.env.', 'use getBuildConfigEnvironment');
420
+ ]) && !shellRuntime?.isBuildTargetCondition(node)) compilerFailure(sourceFile, node, 'framework config API direct-process-env-access', 'Generated config must use the framework config environment API instead of process.env.', 'use getBuildConfigEnvironment');
403
421
  if (typescript.isIdentifier(node) && 'ULTRAMODERN_ZEPHYR' === node.text) compilerFailure(sourceFile, node, 'zephyr gating ultramodern-zephyr-environment-gate', 'Generated Zephyr integration must not be gated through ULTRAMODERN_ZEPHYR.', 'use Zephyr native deploy-token behavior');
404
422
  if (typescript.isPropertyAssignment(node) || typescript.isShorthandPropertyAssignment(node)) {
405
423
  const property = nodeName(node.name);
@@ -407,12 +425,7 @@ function assertCompilerArchitecture(root, workspaceValidationContract) {
407
425
  }
408
426
  if (isShellRoute) {
409
427
  if (typescript.isJsxOpeningElement(node) && 'a' === jsxTagName(node.tagName) && void 0 !== jsxAttribute(node.attributes, 'onClick')) compilerFailure(sourceFile, node, 'shell routing synthetic-anchor-click-interception', 'Shell routing must not intercept anchor clicks synthetically.', 'use the router Link primitive');
410
- if (isCallNamed(node, new Set([
411
- 'hydrateRoot',
412
- 'loadRemote',
413
- 'loadShare',
414
- ...nativeRemoteLoaders
415
- ])) && !nativeLoaderCalls.has(node)) compilerFailure(sourceFile, node, 'module federation native loading', 'Shell routing must use framework Module Federation loading primitives.', 'remove manual hydration or remote-loading wrappers');
428
+ if (typescript.isCallExpression(node) && manualLoadingCallees.has(calleeName(node) ?? '') && !nativeLoaderCalls.has(node) && !shellRuntime?.isBrowserFederationMemberLoad(node)) compilerFailure(sourceFile, node, 'module federation native loading', 'Shell routing must use framework Module Federation loading primitives.', 'remove manual hydration or remote-loading wrappers');
416
429
  if (typescript.isBinaryExpression(node) && node.operatorToken.kind === typescript.SyntaxKind.EqualsToken && propertyAccessPath(node.left)?.slice(0, 2).join('.') === 'window.location' || typescript.isCallExpression(node) && propertyAccessPath(node.expression)?.slice(0, 2).join('.') === 'window.location') compilerFailure(sourceFile, node, 'shell routing window-location-navigation', 'Shell routing must use router navigation instead of window.location.', 'use the router navigation primitive');
417
430
  }
418
431
  node.forEachChild(visit);
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, getters, values)=>{
5
+ var define = (defs, kind)=>{
6
+ for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
7
+ enumerable: true,
8
+ [kind]: defs[key]
9
+ });
10
+ };
11
+ define(getters, "get");
12
+ define(values, "value");
13
+ };
14
+ })();
15
+ (()=>{
16
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
17
+ })();
18
+ (()=>{
19
+ __webpack_require__.r = (exports1)=>{
20
+ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
21
+ value: 'Module'
22
+ });
23
+ Object.defineProperty(exports1, '__esModule', {
24
+ value: true
25
+ });
26
+ };
27
+ })();
28
+ var __webpack_exports__ = {};
29
+ __webpack_require__.r(__webpack_exports__);
30
+ const FEDERATION_RUNTIME = '@module-federation/modern-js-v3/runtime';
31
+ const FEDERATION_MEMBER_LOADERS = new Set([
32
+ 'loadRemote',
33
+ 'loadShare'
34
+ ]);
35
+ const DECLARATION_FILE = /\.d\.[cm]?ts$/u;
36
+ function createNativeShellRuntimeEvidence(typescript, typescriptApi, checker, sourceFile) {
37
+ const unwrapParentheses = (node)=>{
38
+ while(typescript.isParenthesizedExpression(node))node = node.expression;
39
+ return node;
40
+ };
41
+ const isAmbientProcess = (node)=>{
42
+ if (!typescript.isIdentifier(node) || 'process' !== node.text) return false;
43
+ const symbol = checker.getSymbolAtLocation(node);
44
+ return void 0 === symbol || symbol.declarations.every((declaration)=>DECLARATION_FILE.test(declaration.path));
45
+ };
46
+ const isBuildTargetAccess = (node)=>typescript.isPropertyAccessExpression(node) && void 0 === node.questionDotToken && 'MODERN_TARGET' === node.name.text && typescript.isPropertyAccessExpression(node.expression) && void 0 === node.expression.questionDotToken && 'env' === node.expression.name.text && isAmbientProcess(node.expression.expression);
47
+ const isBuildTargetLiteral = (node)=>typescript.isStringLiteral(node) && ('browser' === node.text || 'node' === node.text);
48
+ const buildTargetComparison = (node)=>{
49
+ node = unwrapParentheses(node);
50
+ if (!typescript.isBinaryExpression(node) || node.operatorToken.kind !== typescript.SyntaxKind.EqualsEqualsEqualsToken) return;
51
+ const literal = isBuildTargetAccess(node.left) ? node.right : isBuildTargetAccess(node.right) ? node.left : void 0;
52
+ return void 0 !== literal && isBuildTargetLiteral(literal) ? literal.text : void 0;
53
+ };
54
+ const isConditionOf = (node)=>{
55
+ let condition = node;
56
+ for(;;){
57
+ const parent = condition.parent;
58
+ if (typescript.isParenthesizedExpression(parent) || typescript.isPrefixUnaryExpression(parent) && parent.operator === typescript.SyntaxKind.ExclamationToken || typescript.isBinaryExpression(parent) && (parent.operatorToken.kind === typescript.SyntaxKind.AmpersandAmpersandToken || parent.operatorToken.kind === typescript.SyntaxKind.BarBarToken)) {
59
+ condition = parent;
60
+ continue;
61
+ }
62
+ return typescript.isIfStatement(parent) && parent.expression === condition || typescript.isConditionalExpression(parent) && parent.condition === condition;
63
+ }
64
+ };
65
+ const isBuildTargetCondition = (node)=>{
66
+ const access = node.parent;
67
+ if (!isBuildTargetAccess(access) || access.expression !== node) return false;
68
+ const comparison = access.parent;
69
+ return void 0 !== buildTargetComparison(comparison) && isConditionOf(comparison);
70
+ };
71
+ const conjuncts = (node)=>{
72
+ node = unwrapParentheses(node);
73
+ return typescript.isBinaryExpression(node) && node.operatorToken.kind === typescript.SyntaxKind.AmpersandAmpersandToken ? [
74
+ ...conjuncts(node.left),
75
+ ...conjuncts(node.right)
76
+ ] : [
77
+ node
78
+ ];
79
+ };
80
+ const requiresBrowserTarget = (condition)=>conjuncts(condition).some((conjunct)=>'browser' === buildTargetComparison(conjunct));
81
+ const isBrowserGuarded = (node)=>{
82
+ for(let child = node; void 0 !== child.parent; child = child.parent){
83
+ const parent = child.parent;
84
+ if (typescript.isIfStatement(parent) && parent.thenStatement === child && requiresBrowserTarget(parent.expression)) return true;
85
+ if (typescript.isConditionalExpression(parent) && parent.whenTrue === child && requiresBrowserTarget(parent.condition)) return true;
86
+ }
87
+ return false;
88
+ };
89
+ let federationInstanceTypeIds;
90
+ const federationInstanceTypes = ()=>{
91
+ if (void 0 !== federationInstanceTypeIds) return federationInstanceTypeIds;
92
+ const typeIds = new Set();
93
+ const recordRuntime = (specifier)=>{
94
+ const runtime = checker.getSymbolAtLocation(specifier);
95
+ const getInstance = void 0 === runtime ? void 0 : checker.getMemberInModuleExports(runtime, 'getInstance');
96
+ const getInstanceType = void 0 === getInstance ? void 0 : checker.getTypeOfSymbol(getInstance);
97
+ if (void 0 === getInstanceType) return;
98
+ for (const signature of checker.getSignaturesOfType(getInstanceType, typescriptApi.SignatureKind.Call)){
99
+ const returnType = checker.getReturnTypeOfSignature(signature);
100
+ const instanceType = void 0 === returnType ? void 0 : checker.getNonNullableType(returnType);
101
+ if (void 0 !== instanceType && instanceType.getSymbol()?.name === 'ModuleFederation') typeIds.add(instanceType.id);
102
+ }
103
+ };
104
+ const visit = (node)=>{
105
+ if (typescript.isImportDeclaration(node) && typescript.isStringLiteralLikeNode(node.moduleSpecifier) && node.moduleSpecifier.text === FEDERATION_RUNTIME && node.importClause?.phaseModifier !== typescript.SyntaxKind.TypeKeyword) recordRuntime(node.moduleSpecifier);
106
+ else if (typescript.isCallExpression(node) && node.expression.kind === typescript.SyntaxKind.ImportKeyword && 1 === node.arguments.length && typescript.isStringLiteralLikeNode(node.arguments[0]) && node.arguments[0].text === FEDERATION_RUNTIME) recordRuntime(node.arguments[0]);
107
+ node.forEachChild(visit);
108
+ };
109
+ visit(sourceFile);
110
+ federationInstanceTypeIds = typeIds;
111
+ return typeIds;
112
+ };
113
+ const isBrowserFederationMemberLoad = (node)=>{
114
+ if (!typescript.isCallExpression(node)) return false;
115
+ const callee = unwrapParentheses(node.expression);
116
+ if (!typescript.isPropertyAccessExpression(callee) || !FEDERATION_MEMBER_LOADERS.has(callee.name.text)) return false;
117
+ const receiverType = checker.getTypeAtLocation(callee.expression);
118
+ return void 0 !== receiverType && federationInstanceTypes().has(receiverType.id) && isBrowserGuarded(node);
119
+ };
120
+ return {
121
+ isBrowserFederationMemberLoad,
122
+ isBuildTargetCondition
123
+ };
124
+ }
125
+ __webpack_require__.d(__webpack_exports__, {
126
+ createNativeShellRuntimeEvidence: ()=>createNativeShellRuntimeEvidence
127
+ });
128
+ exports.createNativeShellRuntimeEvidence = __webpack_exports__.createNativeShellRuntimeEvidence;
129
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
130
+ "createNativeShellRuntimeEvidence"
131
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
132
+ Object.defineProperty(exports, '__esModule', {
133
+ value: true
134
+ });
@@ -30,7 +30,6 @@ __webpack_require__.r(__webpack_exports__);
30
30
  __webpack_require__.d(__webpack_exports__, {
31
31
  writeApp: ()=>writeApp
32
32
  });
33
- const external_api_cjs_namespaceObject = require("./api.cjs");
34
33
  const write_app_api_cjs_namespaceObject = require("./api/write-app-api.cjs");
35
34
  const external_app_files_cjs_namespaceObject = require("./app-files.cjs");
36
35
  const external_demo_components_cjs_namespaceObject = require("./demo-components.cjs");
@@ -110,7 +109,7 @@ function writeAppFederationConfigFiles({ targetDir, scope, resolvedApp, emitsUi,
110
109
  if (emitsUi) (0, external_fs_io_cjs_namespaceObject.writeFile)(targetDir, `${resolvedApp.directory}/module-federation.config.ts`, 'shell' === resolvedApp.kind ? (0, external_module_federation_cjs_namespaceObject.createShellModuleFederationConfig)(scope, resolvedApp, remotes) : (0, external_module_federation_cjs_namespaceObject.createRemoteModuleFederationConfig)(scope, resolvedApp, remotes));
111
110
  if ((0, external_descriptors_cjs_namespaceObject.appHasApi)(resolvedApp)) (0, external_fs_io_cjs_namespaceObject.writeFile)(targetDir, `${resolvedApp.directory}/backend-federation.config.ts`, (0, external_module_federation_cjs_namespaceObject.createBackendModuleFederationConfig)(resolvedApp));
112
111
  }
113
- function writeAppRouteAndShellFiles({ targetDir, scope, resolvedApp, emitsUi, remotes, availableRemotes, publicWeb, writeAppFile }) {
112
+ function writeAppRouteAndShellFiles({ targetDir, scope, resolvedApp, emitsUi, remotes, publicWeb, writeAppFile }) {
114
113
  if (!emitsUi) return;
115
114
  if ((resolvedApp.verticalRefs?.length ?? 0) > 0) {
116
115
  writeAppFile('src/federated-components.tsx', (0, external_demo_components_cjs_namespaceObject.createFederatedComponentsRegistry)(scope, resolvedApp, remotes));
@@ -124,7 +123,6 @@ function writeAppRouteAndShellFiles({ targetDir, scope, resolvedApp, emitsUi, re
124
123
  writeAppFile('src/routes/vertical-components.tsx', (0, external_demo_components_cjs_namespaceObject.createShellRemoteComponents)(resolvedApp, remotes.filter(external_descriptors_cjs_namespaceObject.appEmitsBrowserUi)));
125
124
  writeAppFile('src/routes/vertical-components.worker.tsx', (0, external_demo_components_cjs_namespaceObject.createShellWorkerRemoteComponents)(resolvedApp, remotes.filter(external_descriptors_cjs_namespaceObject.appEmitsBrowserUi)));
126
125
  writeAppFile('src/routes/shell-frame.tsx', (0, external_app_files_cjs_namespaceObject.createShellFrameComponent)(resolvedApp));
127
- (0, external_fs_io_cjs_namespaceObject.writeFile)(targetDir, `${resolvedApp.directory}/src/api/vertical-clients.ts`, (0, external_api_cjs_namespaceObject.createShellApiClient)(scope, availableRemotes));
128
126
  } else for (const expose of (0, external_descriptors_cjs_namespaceObject.distributedSsrExposes)(resolvedApp))writeAppFile(`src/routes/[lang]/_mf/fragment/${(0, external_descriptors_cjs_namespaceObject.distributedSsrFragmentSlug)(expose)}/page.tsx`, (0, external_demo_components_cjs_namespaceObject.createRemoteExposeFragmentPage)(resolvedApp, expose));
129
127
  }
130
128
  function writeAppRemoteExposeFiles({ resolvedApp, emitsUi, writeAppFile }) {
@@ -1,9 +1,8 @@
1
1
  import node_fs from "node:fs";
2
2
  import node_path from "node:path";
3
- import { createShellApiClient } from "../api.js";
4
3
  import { createAppEnvDts, createAppRuntimeConfig, createShellFrameComponent } from "../app-files.js";
5
4
  import { createShellPage, createShellRemoteComponents, createShellWorkerRemoteComponents } from "../demo-components.js";
6
- import { appEmitsBrowserUi, appHasApi, appI18nNamespace, resolveRemoteRefs, shellApp } from "../descriptors.js";
5
+ import { appEmitsBrowserUi, appI18nNamespace, resolveRemoteRefs, shellApp } from "../descriptors.js";
7
6
  import { readJsonFile, writeJsonFile } from "../fs-io.js";
8
7
  import { createAppPublicLocaleMessages } from "../locales.js";
9
8
  import { createAppModernConfig, createShellModuleFederationConfig } from "../module-federation.js";
@@ -40,10 +39,7 @@ function shellAppArtifacts(scope, packageSource, enableTailwind, remotes, bridge
40
39
  ...Object.fromEntries(createNativeFederationArtifacts(scope, shellHost, remotes).map((artifact)=>[
41
40
  `${shellHost.directory}/${artifact.path}`,
42
41
  artifact.content
43
- ])),
44
- ...remotes.some(appHasApi) ? {
45
- [`${shellHost.directory}/src/api/vertical-clients.ts`]: createShellApiClient(scope, remotes)
46
- } : {}
42
+ ]))
47
43
  };
48
44
  return {
49
45
  shellHost,
@@ -83,8 +79,7 @@ function shellAppArtifacts(scope, packageSource, enableTailwind, remotes, bridge
83
79
  [`${shellHost.directory}/src/routes/[lang]/page.tsx`]: createShellPage(shellHost, uiRemotes),
84
80
  [`${shellHost.directory}/src/routes/vertical-components.tsx`]: createShellRemoteComponents(shellHost, uiRemotes),
85
81
  [`${shellHost.directory}/src/routes/vertical-components.worker.tsx`]: createShellWorkerRemoteComponents(shellHost, uiRemotes),
86
- [`${shellHost.directory}/src/routes/shell-frame.tsx`]: createShellFrameComponent(shellHost),
87
- [`${shellHost.directory}/src/api/vertical-clients.ts`]: createShellApiClient(scope, remotes)
82
+ [`${shellHost.directory}/src/routes/shell-frame.tsx`]: createShellFrameComponent(shellHost)
88
83
  };
89
84
  return {
90
85
  shellHost,
@@ -1,6 +1,6 @@
1
- import { resolveApiProtocol, resolveApiStem, verticalApiApps } from "../descriptors.js";
2
- import { packageName, toPascalCase } from "../naming.js";
3
- import { createCheckoutCartClientExports, serviceHasCheckoutCartState } from "./checkout-cart.js";
1
+ import { resolveApiStem } from "../descriptors.js";
2
+ import { toPascalCase } from "../naming.js";
3
+ import { createCheckoutCartClientExports } from "./checkout-cart.js";
4
4
  import { verticalApiErrorStem, verticalApiExport, verticalApiGroupName, verticalApiNotFoundErrorExport } from "./names.js";
5
5
  function createApiClient(service, contractImportPath, options) {
6
6
  const apiExport = verticalApiExport(service);
@@ -148,36 +148,4 @@ export const ${createName} = (
148
148
  );${checkoutCartClientExports}
149
149
  `;
150
150
  }
151
- function createShellApiClient(scope, remotes = []) {
152
- const exports = verticalApiApps(remotes).map((remote)=>{
153
- const stem = resolveApiStem(remote);
154
- const pascalStem = toPascalCase(stem);
155
- const rpc = 'rpc' === resolveApiProtocol(remote);
156
- const pascalSingular = toPascalCase(verticalApiErrorStem(remote));
157
- const checkoutCartExports = !rpc && serviceHasCheckoutCartState(remote) ? ` addCheckoutCartItem,
158
- clearCheckoutCart,
159
- getCheckoutCart,
160
- removeCheckoutCartItem,
161
- type CheckoutAddCartItemInput,
162
- type CheckoutCart,
163
- type CheckoutCartLine,
164
- ` : '';
165
- if (rpc) return `export {
166
- get${pascalStem}Rpc,
167
- list${pascalStem}Rpc,
168
- make${pascalStem}RpcClient,
169
- type ${pascalStem}RpcClientOptions,
170
- } from '${packageName(scope, remote.packageSuffix)}/api/rpc-client';`;
171
- return `export {
172
- ${checkoutCartExports} create${pascalSingular},
173
- create${pascalStem}Client,
174
- get${pascalSingular},
175
- get${pascalStem}Readiness,
176
- list${pascalStem},
177
- type ${pascalStem}ClientOptions,
178
- } from '${packageName(scope, remote.packageSuffix)}/api/client';`;
179
- }).join('\n\n');
180
- return exports ? `${exports}\n` : `export const ultramodernVerticalClients = [] as const;
181
- `;
182
- }
183
- export { createApiClient, createShellApiClient };
151
+ export { createApiClient };
@@ -1,4 +1,4 @@
1
- export { createApiClient, createShellApiClient } from "./api/client.js";
1
+ export { createApiClient } from "./api/client.js";
2
2
  export { apiTopologyMetadata } from "./api/contracts.js";
3
3
  export { verticalApiCreatePayloadSchemaExport, verticalApiErrorStem, verticalApiExport, verticalApiGroupName, verticalApiMarkerSchemaExport, verticalApiName, verticalApiNotFoundErrorExport, verticalApiNotFoundSchemaExport, verticalApiReadinessSchemaExport, verticalApiSchemaExport } from "./api/names.js";
4
4
  export { createRpcApiServiceEntry, createRpcClientFile, createRpcContractFile, rpcPath, verticalRpcContractExport, verticalRpcGroupExport } from "./api/rpc.js";
@@ -1,4 +1,3 @@
1
- import { createShellApiClient } from "./api.js";
2
1
  import { writeAppApiFiles } from "./api/write-app-api.js";
3
2
  import { createAppStyles, createTailwindConfig } from "./app-files.js";
4
3
  import { appHasApi } from "./descriptors.js";
@@ -61,6 +60,5 @@ function writeNativeApp(targetDir, scope, app, packageSource, enableTailwind, re
61
60
  resolvedApp: app,
62
61
  emitsUi: true
63
62
  });
64
- if ('shell' === app.kind && remotes.some(appHasApi)) write('src/api/vertical-clients.ts', createShellApiClient(scope, remotes));
65
63
  }
66
64
  export { writeNativeApp };
@@ -269,9 +269,7 @@ function createAppPackage(scope, app, packageSource, enableTailwind, remotes = [
269
269
  './api': './shared/api.ts',
270
270
  './api/client': `./${clientDirectory}/${app.api.stem}-client.ts`
271
271
  });
272
- } else if ('shell' === app.kind && ('react' === resolveWorkspaceRenderer(app) || verticalApiApps(remotes).length > 0)) Object.assign(packageExports, {
273
- './api/clients': './src/api/vertical-clients.ts'
274
- });
272
+ }
275
273
  if (Object.keys(packageExports).length > 0) packageJson.exports = packageExports;
276
274
  return packageJson;
277
275
  }
@@ -4,6 +4,7 @@ import node_path from "node:path";
4
4
  import { hasNativeAppGeneration } from "../renderer-generations.js";
5
5
  import { getRendererGenerationProfile, isApplicationRenderer } from "../renderer-profile.js";
6
6
  import { assert, sameJson, selfCheckFailure } from "./assertions.js";
7
+ import { createNativeShellRuntimeEvidence } from "./native-shell-runtime.js";
7
8
  import { isForeignRendererPackage } from "./renderer.js";
8
9
  function assertCompilerArchitecture(root, workspaceValidationContract) {
9
10
  const fullStackVerticals = workspaceValidationContract.apps.filter((app)=>'shell' !== app.kind);
@@ -62,12 +63,16 @@ function assertCompilerArchitecture(root, workspaceValidationContract) {
62
63
  ]
63
64
  });
64
65
  };
65
- const parseCompilerInput = (absolutePath)=>{
66
+ const compilerInput = (absolutePath)=>{
66
67
  const project = compilerSnapshot?.getDefaultProjectForFile(absolutePath);
67
68
  const sourceFile = project?.program.getSourceFile(absolutePath);
68
- assert(void 0 !== sourceFile, `Native TypeScript compiler could not parse ${node_path.relative(root, absolutePath)}`);
69
- return sourceFile;
69
+ assert(void 0 !== project && void 0 !== sourceFile, `Native TypeScript compiler could not parse ${node_path.relative(root, absolutePath)}`);
70
+ return {
71
+ checker: project.checker,
72
+ sourceFile
73
+ };
70
74
  };
75
+ const parseCompilerInput = (absolutePath)=>compilerInput(absolutePath).sourceFile;
71
76
  const nodeName = (node)=>{
72
77
  if (!node) return;
73
78
  if (typescript.isIdentifier(node) || typescript.isPrivateIdentifier(node) || typescript.isStringLiteralLikeNode(node) || typescript.isNumericLiteral(node)) return node.text;
@@ -155,6 +160,12 @@ function assertCompilerArchitecture(root, workspaceValidationContract) {
155
160
  const accessPath = propertyAccessPath(node.expression);
156
161
  return void 0 !== accessPath && names.has(accessPath.at(-1));
157
162
  };
163
+ const calleeName = (node)=>{
164
+ let callee = node.expression;
165
+ while(typescript.isParenthesizedExpression(callee) || typescript.isNonNullExpression(callee) || typescript.isAsExpression(callee))callee = callee.expression;
166
+ if (typescript.isIdentifier(callee)) return callee.text;
167
+ if (typescript.isPropertyAccessExpression(callee)) return callee.name.text;
168
+ };
158
169
  const objectLiteralProperty = (objectLiteral, name)=>objectLiteral.properties.find((property)=>typescript.isPropertyAssignment(property) && nodeName(property.name) === name);
159
170
  const moduleFederationConfigArgument = (sourceFile)=>{
160
171
  let argument;
@@ -302,11 +313,12 @@ function assertCompilerArchitecture(root, workspaceValidationContract) {
302
313
  ...configFiles.map((relativePath)=>node_path.join(root, relativePath)).filter((absolutePath)=>node_fs.existsSync(absolutePath))
303
314
  ]);
304
315
  for (const absolutePath of checkedFiles){
305
- const sourceFile = parseCompilerInput(absolutePath);
316
+ const { checker, sourceFile } = compilerInput(absolutePath);
306
317
  const isShellRoute = shellRouteDirectories.some((relativeDirectory)=>{
307
318
  const absoluteDirectory = node_path.join(root, relativeDirectory);
308
319
  return absolutePath.startsWith(absoluteDirectory + node_path.sep);
309
320
  });
321
+ const shellRuntime = isShellRoute ? createNativeShellRuntimeEvidence(typescript, typescriptApi, checker, sourceFile) : void 0;
310
322
  const moduleFederationAppPath = moduleFederationConfigAppPaths.get(absolutePath);
311
323
  const nativeFederation = void 0 === moduleFederationAppPath ? void 0 : nativeModuleFederationApps.get(moduleFederationAppPath);
312
324
  const tailwindFactories = new Set();
@@ -329,6 +341,12 @@ function assertCompilerArchitecture(root, workspaceValidationContract) {
329
341
  ].includes(imported)) presetFactories.add(binding.name.text);
330
342
  }
331
343
  }
344
+ const manualLoadingCallees = new Set([
345
+ 'hydrateRoot',
346
+ 'loadRemote',
347
+ 'loadShare',
348
+ ...nativeRemoteLoaders
349
+ ]);
332
350
  const modernConfigApp = workspaceValidationContract.apps.find((app)=>absolutePath === node_path.join(root, app.path, 'modern.config.ts'));
333
351
  let insideDefaultExport = false;
334
352
  const visit = (node)=>{
@@ -356,7 +374,7 @@ function assertCompilerArchitecture(root, workspaceValidationContract) {
356
374
  if (sameJson(accessPath, [
357
375
  'process',
358
376
  'env'
359
- ])) compilerFailure(sourceFile, node, 'framework config API direct-process-env-access', 'Generated config must use the framework config environment API instead of process.env.', 'use getBuildConfigEnvironment');
377
+ ]) && !shellRuntime?.isBuildTargetCondition(node)) compilerFailure(sourceFile, node, 'framework config API direct-process-env-access', 'Generated config must use the framework config environment API instead of process.env.', 'use getBuildConfigEnvironment');
360
378
  if (typescript.isIdentifier(node) && 'ULTRAMODERN_ZEPHYR' === node.text) compilerFailure(sourceFile, node, 'zephyr gating ultramodern-zephyr-environment-gate', 'Generated Zephyr integration must not be gated through ULTRAMODERN_ZEPHYR.', 'use Zephyr native deploy-token behavior');
361
379
  if (typescript.isPropertyAssignment(node) || typescript.isShorthandPropertyAssignment(node)) {
362
380
  const property = nodeName(node.name);
@@ -364,12 +382,7 @@ function assertCompilerArchitecture(root, workspaceValidationContract) {
364
382
  }
365
383
  if (isShellRoute) {
366
384
  if (typescript.isJsxOpeningElement(node) && 'a' === jsxTagName(node.tagName) && void 0 !== jsxAttribute(node.attributes, 'onClick')) compilerFailure(sourceFile, node, 'shell routing synthetic-anchor-click-interception', 'Shell routing must not intercept anchor clicks synthetically.', 'use the router Link primitive');
367
- if (isCallNamed(node, new Set([
368
- 'hydrateRoot',
369
- 'loadRemote',
370
- 'loadShare',
371
- ...nativeRemoteLoaders
372
- ])) && !nativeLoaderCalls.has(node)) compilerFailure(sourceFile, node, 'module federation native loading', 'Shell routing must use framework Module Federation loading primitives.', 'remove manual hydration or remote-loading wrappers');
385
+ if (typescript.isCallExpression(node) && manualLoadingCallees.has(calleeName(node) ?? '') && !nativeLoaderCalls.has(node) && !shellRuntime?.isBrowserFederationMemberLoad(node)) compilerFailure(sourceFile, node, 'module federation native loading', 'Shell routing must use framework Module Federation loading primitives.', 'remove manual hydration or remote-loading wrappers');
373
386
  if (typescript.isBinaryExpression(node) && node.operatorToken.kind === typescript.SyntaxKind.EqualsToken && propertyAccessPath(node.left)?.slice(0, 2).join('.') === 'window.location' || typescript.isCallExpression(node) && propertyAccessPath(node.expression)?.slice(0, 2).join('.') === 'window.location') compilerFailure(sourceFile, node, 'shell routing window-location-navigation', 'Shell routing must use router navigation instead of window.location.', 'use the router navigation primitive');
374
387
  }
375
388
  node.forEachChild(visit);