@bleedingdev/modern-js-app-tools-extensions 3.9.0-ultramodern.2 → 3.9.0-ultramodern.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (213) hide show
  1. package/dist/cjs/backend-federation-build/codegen.js +267 -0
  2. package/dist/cjs/backend-federation-build/config.js +239 -0
  3. package/dist/cjs/backend-federation-build/emit.js +154 -0
  4. package/dist/cjs/backend-federation-build/index.js +53 -0
  5. package/dist/cjs/build-config/build-environment.js +129 -0
  6. package/dist/cjs/build-config/precompress/plugin.js +124 -0
  7. package/dist/cjs/build-config/precompress/types.js +18 -0
  8. package/dist/cjs/build-config/public.js +43 -0
  9. package/dist/cjs/build-config/remote-address.js +58 -0
  10. package/dist/cjs/cloudflare/artifacts.js +8 -19
  11. package/dist/cjs/cloudflare/constants.js +1 -1
  12. package/dist/cjs/cloudflare/delivery-unit.js +23 -42
  13. package/dist/cjs/cloudflare/index.js +10 -2
  14. package/dist/cjs/cloudflare/worker-manifest.js +13 -4
  15. package/dist/cjs/cloudflare/wrangler-config.js +35 -7
  16. package/dist/cjs/cloudflare-builder.js +251 -75
  17. package/dist/cjs/cloudflare-output-contract.js +69 -3
  18. package/dist/cjs/cloudflare-output-verifier/identity.js +29 -27
  19. package/dist/cjs/cloudflare-output-verifier/index.js +10 -0
  20. package/dist/cjs/cloudflare-output-verifier/manifest.js +46 -0
  21. package/dist/cjs/cloudflare-output-verifier/mutation-policy.js +7 -1
  22. package/dist/cjs/cloudflare-output-verifier/worker-bundles.js +14 -6
  23. package/dist/cjs/config.js +34 -1
  24. package/dist/cjs/deploy-output/npmAliases.js +251 -0
  25. package/dist/cjs/deploy-output/plugin.js +97 -0
  26. package/dist/cjs/deploy-output/public-assets.js +146 -0
  27. package/dist/cjs/deploy-output/target.js +104 -0
  28. package/dist/cjs/deploy-output/trace-files.js +90 -0
  29. package/dist/cjs/native-type-checker.js +193 -0
  30. package/dist/cjs/policy-defaults.js +101 -0
  31. package/dist/cjs/release-envelope/framework-output.js +153 -79
  32. package/dist/cjs/release-envelope/index.js +10 -4
  33. package/dist/cjs/release-envelope/plugin.js +18 -13
  34. package/dist/cjs/release-identity.js +5 -6
  35. package/dist/cjs/runtime-package-resolution.js +118 -0
  36. package/dist/cjs/templates/cloudflare-entry.002-assets-routes.mjs +1 -1
  37. package/dist/cjs/templates/cloudflare-entry.004-rendering-css.mjs +5 -1
  38. package/dist/cjs/templates/cloudflare-entry.005-worker-dispatch.mjs +98 -10
  39. package/dist/cjs/templates/cloudflare-entry.006-fetch-handler.mjs +9 -2
  40. package/dist/cjs/templates/cloudflare-worker-route-data.mjs +1069 -0
  41. package/dist/esm/backend-federation-build/codegen.mjs +216 -0
  42. package/dist/esm/backend-federation-build/config.mjs +163 -0
  43. package/dist/esm/backend-federation-build/emit.mjs +103 -0
  44. package/dist/esm/backend-federation-build/index.mjs +1 -0
  45. package/dist/esm/build-config/build-environment.mjs +88 -0
  46. package/dist/esm/build-config/precompress/plugin.mjs +76 -0
  47. package/dist/esm/build-config/precompress/types.mjs +0 -0
  48. package/dist/esm/build-config/public.mjs +1 -0
  49. package/dist/esm/build-config/remote-address.mjs +20 -0
  50. package/dist/esm/cloudflare/artifacts.mjs +8 -19
  51. package/dist/esm/cloudflare/constants.mjs +1 -1
  52. package/dist/esm/cloudflare/delivery-unit.mjs +17 -36
  53. package/dist/esm/cloudflare/index.mjs +10 -2
  54. package/dist/esm/cloudflare/worker-manifest.mjs +13 -4
  55. package/dist/esm/cloudflare/wrangler-config.mjs +35 -7
  56. package/dist/esm/cloudflare-builder.mjs +245 -75
  57. package/dist/esm/cloudflare-output-contract.mjs +59 -2
  58. package/dist/esm/cloudflare-output-verifier/identity.mjs +27 -25
  59. package/dist/esm/cloudflare-output-verifier/index.mjs +10 -0
  60. package/dist/esm/cloudflare-output-verifier/manifest.mjs +46 -0
  61. package/dist/esm/cloudflare-output-verifier/mutation-policy.mjs +7 -1
  62. package/dist/esm/cloudflare-output-verifier/worker-bundles.mjs +15 -7
  63. package/dist/esm/config.mjs +3 -0
  64. package/dist/esm/deploy-output/npmAliases.mjs +199 -0
  65. package/dist/esm/deploy-output/plugin.mjs +46 -0
  66. package/dist/esm/deploy-output/public-assets.mjs +82 -0
  67. package/dist/esm/deploy-output/target.mjs +57 -0
  68. package/dist/esm/deploy-output/trace-files.mjs +38 -0
  69. package/dist/esm/native-type-checker.mjs +142 -0
  70. package/dist/esm/policy-defaults.mjs +45 -0
  71. package/dist/esm/release-envelope/framework-output.mjs +130 -56
  72. package/dist/esm/release-envelope/index.mjs +10 -4
  73. package/dist/esm/release-envelope/plugin.mjs +18 -13
  74. package/dist/esm/release-identity.mjs +5 -6
  75. package/dist/esm/runtime-package-resolution.mjs +60 -0
  76. package/dist/esm/templates/cloudflare-entry.002-assets-routes.mjs +1 -1
  77. package/dist/esm/templates/cloudflare-entry.004-rendering-css.mjs +5 -1
  78. package/dist/esm/templates/cloudflare-entry.005-worker-dispatch.mjs +98 -10
  79. package/dist/esm/templates/cloudflare-entry.006-fetch-handler.mjs +9 -2
  80. package/dist/esm/templates/cloudflare-worker-route-data.mjs +1069 -0
  81. package/dist/esm-node/backend-federation-build/codegen.mjs +217 -0
  82. package/dist/esm-node/backend-federation-build/config.mjs +164 -0
  83. package/dist/esm-node/backend-federation-build/emit.mjs +104 -0
  84. package/dist/esm-node/backend-federation-build/index.mjs +2 -0
  85. package/dist/esm-node/build-config/build-environment.mjs +89 -0
  86. package/dist/esm-node/build-config/precompress/plugin.mjs +77 -0
  87. package/dist/esm-node/build-config/precompress/types.mjs +1 -0
  88. package/dist/esm-node/build-config/public.mjs +2 -0
  89. package/dist/esm-node/build-config/remote-address.mjs +21 -0
  90. package/dist/esm-node/cloudflare/artifacts.mjs +8 -19
  91. package/dist/esm-node/cloudflare/constants.mjs +1 -1
  92. package/dist/esm-node/cloudflare/delivery-unit.mjs +17 -36
  93. package/dist/esm-node/cloudflare/index.mjs +10 -2
  94. package/dist/esm-node/cloudflare/worker-manifest.mjs +13 -4
  95. package/dist/esm-node/cloudflare/wrangler-config.mjs +35 -7
  96. package/dist/esm-node/cloudflare-builder.mjs +245 -75
  97. package/dist/esm-node/cloudflare-output-contract.mjs +59 -2
  98. package/dist/esm-node/cloudflare-output-verifier/identity.mjs +27 -25
  99. package/dist/esm-node/cloudflare-output-verifier/index.mjs +10 -0
  100. package/dist/esm-node/cloudflare-output-verifier/manifest.mjs +46 -0
  101. package/dist/esm-node/cloudflare-output-verifier/mutation-policy.mjs +7 -1
  102. package/dist/esm-node/cloudflare-output-verifier/worker-bundles.mjs +15 -7
  103. package/dist/esm-node/config.mjs +3 -0
  104. package/dist/esm-node/deploy-output/npmAliases.mjs +200 -0
  105. package/dist/esm-node/deploy-output/plugin.mjs +49 -0
  106. package/dist/esm-node/deploy-output/public-assets.mjs +83 -0
  107. package/dist/esm-node/deploy-output/target.mjs +58 -0
  108. package/dist/esm-node/deploy-output/trace-files.mjs +39 -0
  109. package/dist/esm-node/native-type-checker.mjs +143 -0
  110. package/dist/esm-node/policy-defaults.mjs +46 -0
  111. package/dist/esm-node/release-envelope/framework-output.mjs +130 -56
  112. package/dist/esm-node/release-envelope/index.mjs +10 -4
  113. package/dist/esm-node/release-envelope/plugin.mjs +18 -13
  114. package/dist/esm-node/release-identity.mjs +5 -6
  115. package/dist/esm-node/runtime-package-resolution.mjs +61 -0
  116. package/dist/esm-node/templates/cloudflare-entry.002-assets-routes.mjs +1 -1
  117. package/dist/esm-node/templates/cloudflare-entry.004-rendering-css.mjs +5 -1
  118. package/dist/esm-node/templates/cloudflare-entry.005-worker-dispatch.mjs +98 -10
  119. package/dist/esm-node/templates/cloudflare-entry.006-fetch-handler.mjs +9 -2
  120. package/dist/esm-node/templates/cloudflare-worker-route-data.mjs +1069 -0
  121. package/dist/types/backend-federation-build/codegen.d.ts +116 -0
  122. package/dist/types/backend-federation-build/config.d.ts +121 -0
  123. package/dist/types/backend-federation-build/emit.d.ts +21 -0
  124. package/dist/types/backend-federation-build/index.d.ts +2 -0
  125. package/dist/types/build-config/build-environment.d.ts +14 -0
  126. package/dist/types/build-config/precompress/plugin.d.ts +4 -0
  127. package/dist/types/build-config/precompress/types.d.ts +19 -0
  128. package/dist/types/build-config/public.d.ts +2 -0
  129. package/dist/types/build-config/remote-address.d.ts +3 -0
  130. package/dist/types/cloudflare/artifacts.d.ts +7 -6
  131. package/dist/types/cloudflare/constants.d.ts +1 -1
  132. package/dist/types/cloudflare/delivery-unit.d.ts +3 -3
  133. package/dist/types/cloudflare/worker-manifest.d.ts +2 -2
  134. package/dist/types/cloudflare/wrangler-config.d.ts +6 -0
  135. package/dist/types/cloudflare-builder.d.ts +49 -9
  136. package/dist/types/cloudflare-output-contract.d.ts +4 -1
  137. package/dist/types/cloudflare-output-verifier/identity.d.ts +1 -1
  138. package/dist/types/cloudflare-output-verifier/worker-bundles.d.ts +2 -2
  139. package/dist/types/config.d.ts +29 -1
  140. package/dist/types/deploy-output/npmAliases.d.ts +14 -0
  141. package/dist/types/deploy-output/plugin.d.ts +35 -0
  142. package/dist/types/deploy-output/public-assets.d.ts +51 -0
  143. package/dist/types/deploy-output/target.d.ts +29 -0
  144. package/dist/types/deploy-output/trace-files.d.ts +17 -0
  145. package/dist/types/native-type-checker.d.ts +15 -0
  146. package/dist/types/policy-defaults.d.ts +46 -0
  147. package/dist/types/precompress/LICENSE +20 -0
  148. package/dist/types/precompress/index.d.ts +76 -0
  149. package/dist/types/release-envelope/framework-output.d.ts +8 -3
  150. package/dist/types/release-envelope/plugin.d.ts +7 -7
  151. package/dist/types/runtime-package-resolution.d.ts +28 -0
  152. package/dist/types/templates/cloudflare-worker-route-data.d.mts +14 -0
  153. package/package.json +97 -15
  154. package/src/backend-federation-build/codegen.ts +254 -0
  155. package/src/backend-federation-build/config.ts +492 -0
  156. package/src/backend-federation-build/emit.ts +213 -0
  157. package/src/backend-federation-build/index.ts +2 -0
  158. package/src/build-config/build-environment.ts +160 -0
  159. package/src/build-config/precompress/plugin.ts +140 -0
  160. package/src/build-config/precompress/types.ts +26 -0
  161. package/src/build-config/public.ts +5 -0
  162. package/src/build-config/remote-address.ts +33 -0
  163. package/src/cloudflare/artifacts.ts +22 -43
  164. package/src/cloudflare/constants.ts +1 -1
  165. package/src/cloudflare/delivery-unit.ts +42 -53
  166. package/src/cloudflare/index.ts +24 -11
  167. package/src/cloudflare/worker-manifest.ts +20 -3
  168. package/src/cloudflare/wrangler-config.ts +86 -10
  169. package/src/cloudflare-builder.ts +472 -151
  170. package/src/cloudflare-output-contract.ts +70 -0
  171. package/src/cloudflare-output-verifier/identity.ts +5 -1
  172. package/src/cloudflare-output-verifier/index.ts +20 -0
  173. package/src/cloudflare-output-verifier/manifest.ts +77 -0
  174. package/src/cloudflare-output-verifier/mutation-policy.ts +11 -1
  175. package/src/cloudflare-output-verifier/worker-bundles.ts +32 -14
  176. package/src/config.ts +34 -6
  177. package/src/deploy-output/npmAliases.ts +382 -0
  178. package/src/deploy-output/plugin.ts +86 -0
  179. package/src/deploy-output/public-assets.ts +224 -0
  180. package/src/deploy-output/target.ts +106 -0
  181. package/src/deploy-output/trace-files.ts +67 -0
  182. package/src/native-type-checker.ts +183 -0
  183. package/src/policy-defaults.ts +127 -0
  184. package/src/release-envelope/framework-output.ts +346 -94
  185. package/src/release-envelope/index.ts +26 -5
  186. package/src/release-envelope/plugin.ts +43 -40
  187. package/src/release-identity.ts +13 -2
  188. package/src/runtime-package-resolution.ts +115 -0
  189. package/src/templates/cloudflare-entry.002-assets-routes.mjs +1 -1
  190. package/src/templates/cloudflare-entry.004-rendering-css.mjs +5 -1
  191. package/src/templates/cloudflare-entry.005-worker-dispatch.mjs +98 -10
  192. package/src/templates/cloudflare-entry.006-fetch-handler.mjs +9 -2
  193. package/src/templates/cloudflare-worker-route-data.mjs +1069 -0
  194. package/dist/cjs/templates/cloudflare-worker-fs-promises.mjs +0 -11
  195. package/dist/cjs/templates/cloudflare-worker-loadable-server.mjs +0 -281
  196. package/dist/cjs/templates/cloudflare-worker-mf-ssr-runtime-plugin.mjs +0 -14
  197. package/dist/cjs/templates/cloudflare-worker-path.mjs +0 -98
  198. package/dist/esm/templates/cloudflare-worker-fs-promises.mjs +0 -11
  199. package/dist/esm/templates/cloudflare-worker-loadable-server.mjs +0 -281
  200. package/dist/esm/templates/cloudflare-worker-mf-ssr-runtime-plugin.mjs +0 -14
  201. package/dist/esm/templates/cloudflare-worker-path.mjs +0 -98
  202. package/dist/esm-node/templates/cloudflare-worker-fs-promises.mjs +0 -11
  203. package/dist/esm-node/templates/cloudflare-worker-loadable-server.mjs +0 -281
  204. package/dist/esm-node/templates/cloudflare-worker-mf-ssr-runtime-plugin.mjs +0 -14
  205. package/dist/esm-node/templates/cloudflare-worker-path.mjs +0 -98
  206. package/dist/types/templates/cloudflare-worker-fs-promises.d.mts +0 -5
  207. package/dist/types/templates/cloudflare-worker-loadable-server.d.mts +0 -48
  208. package/dist/types/templates/cloudflare-worker-mf-ssr-runtime-plugin.d.mts +0 -13
  209. package/dist/types/templates/cloudflare-worker-path.d.mts +0 -21
  210. package/src/templates/cloudflare-worker-fs-promises.mjs +0 -11
  211. package/src/templates/cloudflare-worker-loadable-server.mjs +0 -281
  212. package/src/templates/cloudflare-worker-mf-ssr-runtime-plugin.mjs +0 -14
  213. package/src/templates/cloudflare-worker-path.mjs +0 -98
@@ -4,9 +4,9 @@ import { pathToFileURL } from "node:url";
4
4
  import { isDeepStrictEqual } from "node:util";
5
5
  import { parse } from "@babel/parser";
6
6
  import traverse from "@babel/traverse";
7
- import { CLOUDFLARE_WORKER_BUNDLE_DIRECTORY, CLOUDFLARE_WORKER_NODE_BUILTINS } from "../cloudflare-output-contract.mjs";
7
+ import { CLOUDFLARE_ROUTE_DATA_HANDLER_EXPORT, CLOUDFLARE_WORKER_BUNDLE_DIRECTORY, CLOUDFLARE_WORKER_NODE_BUILTINS, CLOUDFLARE_WORKER_PLATFORM_MODULES } from "../cloudflare-output-contract.mjs";
8
8
  import { addIssue } from "./issues.mjs";
9
- const getReferencedRouteWorkers = (manifest)=>Array.isArray(manifest?.routeSpec?.routes) ? manifest.routeSpec.routes.map((route)=>'string' == typeof route?.worker && route.worker.length > 0 ? route.worker : void 0).filter((worker)=>'string' == typeof worker) : [];
9
+ const getReferencedRouteWorkers = (manifest, field)=>Array.isArray(manifest?.routeSpec?.routes) ? manifest.routeSpec.routes.map((route)=>'string' == typeof route?.[field] && route[field].length > 0 ? route[field] : void 0).filter((worker)=>'string' == typeof worker) : [];
10
10
  const getEffectBffWorker = (manifest)=>manifest?.bff?.runtimeFramework === 'effect' && 'string' == typeof manifest.bff.worker ? manifest.bff.worker : void 0;
11
11
  const getWorkerBundleReferences = (manifest)=>{
12
12
  const effectBffWorker = getEffectBffWorker(manifest);
@@ -18,9 +18,14 @@ const getWorkerBundleReferences = (manifest)=>{
18
18
  reference: effectBffWorker
19
19
  }
20
20
  ] : [],
21
- ...getReferencedRouteWorkers(manifest).map((reference)=>({
21
+ ...getReferencedRouteWorkers(manifest, 'worker').map((reference)=>({
22
22
  kind: 'route',
23
23
  reference
24
+ })),
25
+ ...getReferencedRouteWorkers(manifest, 'routeDataWorker').map((reference)=>({
26
+ dispatcherExport: CLOUDFLARE_ROUTE_DATA_HANDLER_EXPORT,
27
+ kind: 'route-data',
28
+ reference
24
29
  }))
25
30
  ];
26
31
  };
@@ -41,7 +46,7 @@ const resolveWorkerBundleReference = (issues, outputDirectory, reference, manife
41
46
  path: workerPath
42
47
  };
43
48
  };
44
- const missingWorkerBundleMessage = (reference)=>'effect-bff' === reference.kind ? 'Cloudflare Effect BFF manifest points to a missing worker bundle.' : 'Cloudflare route worker manifest points to a missing worker bundle.';
49
+ const missingWorkerBundleMessage = (reference)=>'effect-bff' === reference.kind ? 'Cloudflare Effect BFF manifest points to a missing worker bundle.' : 'route-data' === reference.kind ? 'Cloudflare route data worker manifest points to a missing worker bundle.' : 'Cloudflare route worker manifest points to a missing worker bundle.';
45
50
  const isAstNode = (value)=>null !== value && 'object' == typeof value && 'type' in value && 'string' == typeof value.type;
46
51
  const getNodeName = (node)=>{
47
52
  if (!isAstNode(node)) return;
@@ -174,7 +179,10 @@ const analyzeWorkerModule = (source)=>{
174
179
  };
175
180
  };
176
181
  const getPackageName = (specifier)=>specifier.startsWith('@') ? specifier.split('/').slice(0, 2).join('/') : specifier.split('/')[0];
177
- const CLOUDFLARE_WORKER_NODE_BUILTIN_SPECIFIERS = new Set(CLOUDFLARE_WORKER_NODE_BUILTINS.map((builtin)=>`node:${builtin}`));
182
+ const CLOUDFLARE_WORKER_NODE_BUILTIN_SPECIFIERS = new Set([
183
+ ...CLOUDFLARE_WORKER_NODE_BUILTINS.map((builtin)=>`node:${builtin}`),
184
+ ...CLOUDFLARE_WORKER_PLATFORM_MODULES
185
+ ]);
178
186
  const isInsideDirectory = (directory, filePath)=>{
179
187
  const relative = node_path.relative(directory, filePath);
180
188
  return 0 === relative.length || !relative.startsWith('..') && !node_path.isAbsolute(relative);
@@ -282,9 +290,9 @@ const verifyWorkerModuleClosure = async (issues, entryPath, entrySource, contrac
282
290
  };
283
291
  const verifyWorkerBundleReferences = async (issues, worker, source, contract)=>{
284
292
  const entryAnalysis = await verifyWorkerModuleClosure(issues, worker.path, source, contract);
285
- if ('effect-bff' === worker.kind && 'string' == typeof worker.dispatcherExport && !entryAnalysis?.exports.has(worker.dispatcherExport)) addIssue(issues, {
293
+ if ('string' == typeof worker.dispatcherExport && !entryAnalysis?.exports.has(worker.dispatcherExport)) addIssue(issues, {
286
294
  code: 'invalid-worker-bundle',
287
- message: 'Cloudflare Effect BFF worker bundle must expose its manifest dispatcherExport.',
295
+ message: 'route-data' === worker.kind ? `Cloudflare route data worker bundle must expose ${worker.dispatcherExport}.` : 'Cloudflare Effect BFF worker bundle must expose its manifest dispatcherExport.',
288
296
  path: worker.path
289
297
  });
290
298
  };
@@ -0,0 +1,3 @@
1
+ export { getBuildConfigEnvironment, resolveEffectTsgoCompiler } from "./build-config/public.mjs";
2
+ export { createRemoteManifestUrl } from "./build-config/remote-address.mjs";
3
+ export { resolveDeployTarget } from "./deploy-output/target.mjs";
@@ -0,0 +1,199 @@
1
+ import promises from "node:fs/promises";
2
+ import node_path from "node:path";
3
+ const dependencyKeys = [
4
+ 'dependencies',
5
+ 'optionalDependencies'
6
+ ];
7
+ const rootDependencyKeys = [
8
+ ...dependencyKeys,
9
+ 'devDependencies'
10
+ ];
11
+ const exactVersionPattern = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/u;
12
+ async function readPackageJson(filePath) {
13
+ return JSON.parse(await promises.readFile(filePath, 'utf8'));
14
+ }
15
+ function parseNpmAlias(aliasName, specifier) {
16
+ if (!specifier.startsWith('npm:')) return;
17
+ const target = specifier.slice(4);
18
+ const versionSeparator = target.lastIndexOf('@');
19
+ if (versionSeparator <= 0 || versionSeparator === target.length - 1) throw new Error(`Invalid npm alias specifier for ${aliasName}: ${specifier}`);
20
+ return {
21
+ aliasName,
22
+ targetName: target.slice(0, versionSeparator),
23
+ targetVersion: target.slice(versionSeparator + 1)
24
+ };
25
+ }
26
+ function aliasesFromPackageJson(packageJson, keys = dependencyKeys) {
27
+ const aliases = [];
28
+ for (const dependencyKey of keys)for (const [aliasName, specifier] of Object.entries(packageJson[dependencyKey] ?? {})){
29
+ const alias = parseNpmAlias(aliasName, specifier);
30
+ if (alias) aliases.push(alias);
31
+ }
32
+ return aliases;
33
+ }
34
+ async function catalogAliasesFromInstalledPackages(appDirectory, packageJson) {
35
+ const aliases = [];
36
+ for (const dependencyKey of rootDependencyKeys)for (const [aliasName, specifier] of Object.entries(packageJson[dependencyKey] ?? {})){
37
+ if (!specifier.startsWith('catalog:')) continue;
38
+ let installedPackage;
39
+ try {
40
+ installedPackage = await readPackageJson(node_path.join(appDirectory, 'node_modules', aliasName, 'package.json'));
41
+ } catch (error) {
42
+ if ('ENOENT' === error.code) continue;
43
+ throw error;
44
+ }
45
+ if (!installedPackage.name || !installedPackage.version) throw new Error(`Installed catalog package ${aliasName} has no identity`);
46
+ if (installedPackage.name !== aliasName) aliases.push({
47
+ aliasName,
48
+ targetName: installedPackage.name,
49
+ targetVersion: installedPackage.version
50
+ });
51
+ }
52
+ return aliases;
53
+ }
54
+ async function collectPackageRecords(nodeModulesDirectory) {
55
+ const records = [];
56
+ const visitedNodeModules = new Set();
57
+ const visitPackage = async (directory)=>{
58
+ const packageJsonPath = node_path.join(directory, 'package.json');
59
+ try {
60
+ const packageJson = await readPackageJson(packageJsonPath);
61
+ if (packageJson.name && packageJson.version) records.push({
62
+ directory,
63
+ packageJson
64
+ });
65
+ } catch (error) {
66
+ if ('ENOENT' !== error.code) throw error;
67
+ }
68
+ await visitNodeModules(node_path.join(directory, 'node_modules'));
69
+ };
70
+ const visitScope = async (scopeDirectory)=>{
71
+ const entries = await promises.readdir(scopeDirectory, {
72
+ withFileTypes: true
73
+ });
74
+ for (const entry of entries)if (entry.isDirectory()) await visitPackage(node_path.join(scopeDirectory, entry.name));
75
+ };
76
+ const visitNdepeStore = async (storeDirectory)=>{
77
+ const entries = await promises.readdir(storeDirectory, {
78
+ withFileTypes: true
79
+ });
80
+ for (const entry of entries)if (entry.isDirectory()) {
81
+ const entryPath = node_path.join(storeDirectory, entry.name);
82
+ if (entry.name.startsWith('@')) await visitScope(entryPath);
83
+ else await visitNodeModules(node_path.join(entryPath, 'node_modules'));
84
+ }
85
+ };
86
+ const visitNodeModules = async (directory)=>{
87
+ const resolvedDirectory = node_path.resolve(directory);
88
+ if (visitedNodeModules.has(resolvedDirectory)) return;
89
+ visitedNodeModules.add(resolvedDirectory);
90
+ let entries;
91
+ try {
92
+ entries = await promises.readdir(directory, {
93
+ withFileTypes: true
94
+ });
95
+ } catch (error) {
96
+ if ('ENOENT' === error.code) return;
97
+ throw error;
98
+ }
99
+ for (const entry of entries){
100
+ if (!entry.isDirectory()) continue;
101
+ const entryPath = node_path.join(directory, entry.name);
102
+ if ('.ndepe' === entry.name) await visitNdepeStore(entryPath);
103
+ else if (entry.name.startsWith('@')) await visitScope(entryPath);
104
+ else await visitPackage(entryPath);
105
+ }
106
+ };
107
+ await visitNodeModules(nodeModulesDirectory);
108
+ return records;
109
+ }
110
+ async function resolveAliasTarget(ownerDirectory, alias, outputDirectory) {
111
+ let directory = ownerDirectory;
112
+ const outputRoot = node_path.resolve(outputDirectory);
113
+ const resolvedOutputRoot = await promises.realpath(outputRoot);
114
+ while(directory === outputRoot || directory.startsWith(`${outputRoot}${node_path.sep}`)){
115
+ const candidate = node_path.join(directory, 'node_modules', alias.targetName);
116
+ try {
117
+ const resolvedCandidate = await promises.realpath(candidate);
118
+ if (resolvedCandidate !== resolvedOutputRoot && !resolvedCandidate.startsWith(`${resolvedOutputRoot}${node_path.sep}`)) throw new Error(`Cannot preserve npm alias ${alias.aliasName}: emitted target ${candidate} resolves outside deployment output to ${resolvedCandidate}`);
119
+ const packageJson = await readPackageJson(node_path.join(candidate, 'package.json'));
120
+ if (packageJson.name !== alias.targetName || !packageJson.version) throw new Error(`npm alias ${alias.aliasName} resolved ${candidate} to unexpected package ${String(packageJson.name)}`);
121
+ if (exactVersionPattern.test(alias.targetVersion) && packageJson.version !== alias.targetVersion) return;
122
+ return {
123
+ directory: candidate,
124
+ packageJson
125
+ };
126
+ } catch (error) {
127
+ if ('ENOENT' !== error.code) throw error;
128
+ }
129
+ if (directory === outputRoot) break;
130
+ directory = node_path.dirname(directory);
131
+ }
132
+ }
133
+ async function ensureAliasLink(ownerDirectory, alias, target) {
134
+ const aliasPath = node_path.join(ownerDirectory, 'node_modules', alias.aliasName);
135
+ await promises.mkdir(node_path.dirname(aliasPath), {
136
+ recursive: true
137
+ });
138
+ try {
139
+ const [existing, expected] = await Promise.all([
140
+ promises.realpath(aliasPath),
141
+ promises.realpath(target.directory)
142
+ ]);
143
+ if (existing === expected) return;
144
+ throw new Error(`Cannot preserve npm alias ${alias.aliasName}: ${aliasPath} already resolves to ${existing}, expected ${expected}`);
145
+ } catch (error) {
146
+ if ('ENOENT' !== error.code) throw error;
147
+ }
148
+ const linkTarget = node_path.relative(node_path.dirname(aliasPath), target.directory);
149
+ await promises.symlink(linkTarget, aliasPath, 'dir');
150
+ }
151
+ function aliasSpecifier(alias) {
152
+ return `npm:${alias.targetName}@${alias.targetVersion}`;
153
+ }
154
+ async function readPackageIdentity(entryPath) {
155
+ let directory = node_path.dirname(entryPath);
156
+ const root = node_path.parse(directory).root;
157
+ while(directory !== root){
158
+ try {
159
+ const packageJson = await readPackageJson(node_path.join(directory, 'package.json'));
160
+ if (packageJson.name && packageJson.version) return {
161
+ name: packageJson.name,
162
+ version: packageJson.version
163
+ };
164
+ } catch (error) {
165
+ if ('ENOENT' !== error.code) throw error;
166
+ }
167
+ directory = node_path.dirname(directory);
168
+ }
169
+ throw new Error(`Cannot find owning package for deployment entry ${entryPath}`);
170
+ }
171
+ async function preserveNpmAliases({ appDirectory, outputDirectory, implicitAliases = [] }) {
172
+ const records = await collectPackageRecords(node_path.join(outputDirectory, 'node_modules'));
173
+ const appPackageJson = await readPackageJson(node_path.join(appDirectory, 'package.json'));
174
+ const rootAliases = [
175
+ ...aliasesFromPackageJson(appPackageJson, rootDependencyKeys),
176
+ ...await catalogAliasesFromInstalledPackages(appDirectory, appPackageJson),
177
+ ...implicitAliases
178
+ ].filter((alias)=>alias.aliasName !== alias.targetName);
179
+ const emittedRootAliases = [];
180
+ for (const alias of rootAliases){
181
+ const target = await resolveAliasTarget(outputDirectory, alias, outputDirectory);
182
+ if (!target) {
183
+ if (implicitAliases.includes(alias)) throw new Error(`Cannot preserve implicit npm alias ${alias.aliasName}: emitted target ${alias.targetName}@${alias.targetVersion} is missing`);
184
+ continue;
185
+ }
186
+ await ensureAliasLink(outputDirectory, alias, target);
187
+ emittedRootAliases.push(alias);
188
+ }
189
+ for (const record of records)for (const alias of aliasesFromPackageJson(record.packageJson).filter((candidate)=>candidate.aliasName !== candidate.targetName)){
190
+ const target = await resolveAliasTarget(record.directory, alias, outputDirectory);
191
+ if (target) await ensureAliasLink(record.directory, alias, target);
192
+ }
193
+ const outputPackageJsonPath = node_path.join(outputDirectory, 'package.json');
194
+ const outputPackageJson = await readPackageJson(outputPackageJsonPath);
195
+ outputPackageJson.dependencies ??= {};
196
+ for (const alias of emittedRootAliases)outputPackageJson.dependencies[alias.aliasName] = aliasSpecifier(alias);
197
+ await promises.writeFile(outputPackageJsonPath, `${JSON.stringify(outputPackageJson, null, 2)}\n`);
198
+ }
199
+ export { preserveNpmAliases, readPackageIdentity };
@@ -0,0 +1,46 @@
1
+ import { createRequire } from "node:module";
2
+ import node_path from "node:path";
3
+ import { preserveNpmAliases, readPackageIdentity } from "./npmAliases.mjs";
4
+ import { NODE_PUBLIC_ASSET_SCOPE, normalizeDeclaredPublicAssets, stageDeclaredPublicAssets } from "./public-assets.mjs";
5
+ import { getDeployingTarget } from "./target.mjs";
6
+ const createDeployOutputAliasesPlugin = ()=>({
7
+ name: '@modern-js/deploy-output-aliases',
8
+ setup (api) {
9
+ api.onAfterDeploy(async ()=>{
10
+ const appContext = api.getAppContext();
11
+ if ('node' !== getDeployingTarget(appContext)) return;
12
+ const { appDirectory } = appContext;
13
+ const entry = createRequire(__filename).resolve('@modern-js/prod-server');
14
+ const identity = await readPackageIdentity(entry);
15
+ await preserveNpmAliases({
16
+ appDirectory,
17
+ outputDirectory: node_path.join(appDirectory, '.output'),
18
+ implicitAliases: [
19
+ {
20
+ aliasName: '@modern-js/prod-server',
21
+ targetName: identity.name,
22
+ targetVersion: identity.version
23
+ }
24
+ ]
25
+ });
26
+ });
27
+ }
28
+ });
29
+ const createDeployOutputPublicAssetsPlugin = ()=>({
30
+ name: '@modern-js/deploy-output-public-assets',
31
+ setup (api) {
32
+ api.onAfterDeploy(async ()=>{
33
+ const appContext = api.getAppContext();
34
+ if ('node' !== getDeployingTarget(appContext)) return;
35
+ const { appDirectory } = appContext;
36
+ const config = api.getNormalizedConfig();
37
+ await stageDeclaredPublicAssets({
38
+ appDirectory,
39
+ outputDirectory: node_path.join(appDirectory, '.output'),
40
+ assets: normalizeDeclaredPublicAssets(config.deploy?.node?.publicAssets, NODE_PUBLIC_ASSET_SCOPE),
41
+ scope: NODE_PUBLIC_ASSET_SCOPE
42
+ });
43
+ });
44
+ }
45
+ });
46
+ export { createDeployOutputAliasesPlugin, createDeployOutputPublicAssetsPlugin };
@@ -0,0 +1,82 @@
1
+ import promises from "node:fs/promises";
2
+ import node_path from "node:path";
3
+ import { normalizeRelativePath } from "../cloudflare/utils.mjs";
4
+ const DECLARED_PUBLIC_ASSET_DIRECTORY = 'public';
5
+ const CLOUDFLARE_PUBLIC_ASSET_SCOPE = {
6
+ label: 'deploy.worker.publicAssets',
7
+ output: 'Cloudflare public output'
8
+ };
9
+ const NODE_PUBLIC_ASSET_SCOPE = {
10
+ label: 'deploy.node.publicAssets',
11
+ output: 'Node public output'
12
+ };
13
+ const normalizeDeclaredPublicAssets = (assets, scope)=>(assets ?? []).map((asset, index)=>({
14
+ from: normalizeRelativePath(asset?.from, `${scope.label}[${index}].from`, 'app root'),
15
+ to: normalizeRelativePath(asset?.to, `${scope.label}[${index}].to`, scope.output, {
16
+ allowRoot: true
17
+ }),
18
+ index
19
+ }));
20
+ const isMissingPathError = (error)=>error instanceof Error && 'code' in error && 'ENOENT' === error.code;
21
+ const pathExists = async (filePath)=>{
22
+ try {
23
+ await promises.lstat(filePath);
24
+ return true;
25
+ } catch (error) {
26
+ if (isMissingPathError(error)) return false;
27
+ throw error;
28
+ }
29
+ };
30
+ const listDeclaredPublicAssetFiles = async (appDirectory, assets, scope)=>{
31
+ const files = [];
32
+ const owners = new Map();
33
+ const add = (index, logicalPath)=>{
34
+ const owner = owners.get(logicalPath);
35
+ if (void 0 !== owner) throw new Error(`${scope.label}[${index}] and ${scope.label}[${owner}] both stage ${JSON.stringify(logicalPath)}.`);
36
+ owners.set(logicalPath, index);
37
+ files.push({
38
+ index,
39
+ logicalPath
40
+ });
41
+ };
42
+ const visit = async (asset, sourcePath, destination)=>{
43
+ const stat = await promises.lstat(sourcePath);
44
+ if (stat.isSymbolicLink()) throw new Error(`${scope.label}[${asset.index}].from must not contain symbolic links: ${node_path.relative(appDirectory, sourcePath).replace(/\\/gu, '/')}`);
45
+ if (stat.isFile()) {
46
+ if (destination === DECLARED_PUBLIC_ASSET_DIRECTORY) throw new Error(`${scope.label}[${asset.index}].to must name a file when ${scope.label}[${asset.index}].from is a file.`);
47
+ add(asset.index, destination);
48
+ return;
49
+ }
50
+ if (!stat.isDirectory()) throw new Error(`${scope.label}[${asset.index}].from must contain only files and directories: ${node_path.relative(appDirectory, sourcePath).replace(/\\/gu, '/')}`);
51
+ const entries = (await promises.readdir(sourcePath)).sort();
52
+ for (const entry of entries)await visit(asset, node_path.join(sourcePath, entry), node_path.posix.join(destination, entry));
53
+ };
54
+ for (const asset of assets){
55
+ const sourcePath = node_path.join(appDirectory, asset.from);
56
+ if (!await pathExists(sourcePath)) throw new Error(`${scope.label}[${asset.index}].from does not exist: ${asset.from}`);
57
+ await visit(asset, sourcePath, node_path.posix.join(DECLARED_PUBLIC_ASSET_DIRECTORY, asset.to));
58
+ }
59
+ return files;
60
+ };
61
+ const resolveAddedDeclaredPublicAssetPaths = async ({ appDirectory, assets, generatedRoot, scope })=>{
62
+ const added = [];
63
+ for (const file of (await listDeclaredPublicAssetFiles(appDirectory, assets, scope)))if (!await pathExists(node_path.join(generatedRoot, file.logicalPath))) added.push(file.logicalPath);
64
+ return added.sort();
65
+ };
66
+ const stageDeclaredPublicAssets = async ({ appDirectory, outputDirectory, assets, scope })=>{
67
+ const files = await listDeclaredPublicAssetFiles(appDirectory, assets, scope);
68
+ const added = [];
69
+ for (const file of files){
70
+ const asset = assets.find((candidate)=>candidate.index === file.index);
71
+ const relativePath = node_path.posix.relative(node_path.posix.join(DECLARED_PUBLIC_ASSET_DIRECTORY, asset.to), file.logicalPath);
72
+ const destination = node_path.join(outputDirectory, file.logicalPath);
73
+ const replacesGeneratedFile = await pathExists(destination);
74
+ await promises.mkdir(node_path.dirname(destination), {
75
+ recursive: true
76
+ });
77
+ await promises.copyFile(node_path.join(appDirectory, asset.from, relativePath), destination);
78
+ if (!replacesGeneratedFile) added.push(file.logicalPath);
79
+ }
80
+ return added.sort();
81
+ };
82
+ export { CLOUDFLARE_PUBLIC_ASSET_SCOPE, DECLARED_PUBLIC_ASSET_DIRECTORY, NODE_PUBLIC_ASSET_SCOPE, normalizeDeclaredPublicAssets, resolveAddedDeclaredPublicAssetPaths, stageDeclaredPublicAssets };
@@ -0,0 +1,57 @@
1
+ import { getArgv } from "@modern-js/utils";
2
+ import { provider as external_std_env_provider } from "std-env";
3
+ const DEPLOY_TARGETS = [
4
+ 'node',
5
+ 'vercel',
6
+ 'netlify',
7
+ 'ghPages',
8
+ 'cloudflare'
9
+ ];
10
+ const DEPLOY_TARGET_FLAG = '--deploy-target';
11
+ const providerDeployTargets = {
12
+ vercel: 'vercel',
13
+ netlify: 'netlify',
14
+ cloudflare: 'cloudflare',
15
+ cloudflare_pages: 'cloudflare',
16
+ cloudflare_workers: 'cloudflare'
17
+ };
18
+ const readDeployTargetFlag = (argv)=>{
19
+ for (const [index, arg] of argv.entries()){
20
+ if (arg === DEPLOY_TARGET_FLAG) {
21
+ const value = argv[index + 1];
22
+ if (void 0 === value || value.startsWith('-')) throw new Error(`${DEPLOY_TARGET_FLAG} needs a value.`);
23
+ return value;
24
+ }
25
+ if (arg.startsWith(`${DEPLOY_TARGET_FLAG}=`)) return arg.slice(DEPLOY_TARGET_FLAG.length + 1);
26
+ }
27
+ };
28
+ const assertDeployTarget = (target, source)=>{
29
+ if (!DEPLOY_TARGETS.includes(target)) throw new Error(`Unknown deploy target '${target}' from ${source}. Use one of: ${DEPLOY_TARGETS.join(', ')}.`);
30
+ return target;
31
+ };
32
+ const resolveDeployTarget = ({ argv = getArgv(), configTarget, env = process.env.MODERNJS_DEPLOY, provider = external_std_env_provider } = {})=>{
33
+ const explicit = [
34
+ [
35
+ readDeployTargetFlag(argv),
36
+ DEPLOY_TARGET_FLAG
37
+ ],
38
+ [
39
+ configTarget,
40
+ 'deploy.target'
41
+ ],
42
+ [
43
+ env,
44
+ 'MODERNJS_DEPLOY'
45
+ ]
46
+ ].find(([target])=>target);
47
+ if (explicit?.[0]) return {
48
+ target: assertDeployTarget(explicit[0], explicit[1]),
49
+ explicit: true
50
+ };
51
+ return {
52
+ target: provider && providerDeployTargets[provider] || 'node',
53
+ explicit: false
54
+ };
55
+ };
56
+ const getDeployingTarget = ({ deployTarget, metaName })=>deployTarget && ('modern-js' === metaName || deployTarget.explicit) ? deployTarget.target : void 0;
57
+ export { DEPLOY_TARGETS, DEPLOY_TARGET_FLAG, getDeployingTarget, resolveDeployTarget };
@@ -0,0 +1,38 @@
1
+ import node_os from "node:os";
2
+ import node_path from "node:path";
3
+ import { nodeFileTrace } from "@vercel/nft";
4
+ const SYSTEM_ROOTS = 'win32' === process.platform ? [] : [
5
+ '/dev',
6
+ '/etc',
7
+ '/proc',
8
+ '/run',
9
+ '/sys',
10
+ '/var/run'
11
+ ];
12
+ const GLOB_SEGMENT = /[*?[{]/;
13
+ const isInside = (parent, child)=>child === parent || child.startsWith(`${parent}${node_path.sep}`);
14
+ const globRoot = (absolutePattern)=>{
15
+ const { root } = node_path.parse(absolutePattern);
16
+ const segments = absolutePattern.slice(root.length).split(node_path.sep);
17
+ const index = segments.findIndex((segment)=>GLOB_SEGMENT.test(segment));
18
+ return -1 === index ? void 0 : node_path.join(root, ...segments.slice(0, index));
19
+ };
20
+ const createBuildHostIgnore = (base)=>{
21
+ const wholeDirectories = new Set([
22
+ node_path.parse(node_path.resolve(base)).root,
23
+ node_path.resolve(node_os.homedir()),
24
+ node_path.resolve(node_os.tmpdir())
25
+ ]);
26
+ return (relativePath)=>{
27
+ const absolutePath = node_path.resolve(base, relativePath);
28
+ if (SYSTEM_ROOTS.some((root)=>isInside(root, absolutePath))) return true;
29
+ const root = globRoot(absolutePath);
30
+ return void 0 !== root && wholeDirectories.has(root);
31
+ };
32
+ };
33
+ const traceDeployFiles = ({ entryFiles, sourceDir, base = '/' })=>nodeFileTrace(entryFiles, {
34
+ base,
35
+ processCwd: sourceDir,
36
+ ignore: createBuildHostIgnore(base)
37
+ });
38
+ export { createBuildHostIgnore, traceDeployFiles };
@@ -0,0 +1,142 @@
1
+ import { execFile } from "node:child_process";
2
+ import { existsSync, realpathSync } from "node:fs";
3
+ import node_path from "node:path";
4
+ import { promisify } from "node:util";
5
+ import { refreshTsgoCheckerConfig } from "@modern-js/builder";
6
+ const execute = promisify(execFile);
7
+ const native_type_checker_name = 'UltramodernNativeTypeChecker';
8
+ const watchDependencyPath = (file)=>{
9
+ if ('win32' !== process.platform) return file;
10
+ try {
11
+ return realpathSync.native(file);
12
+ } catch {
13
+ return file;
14
+ }
15
+ };
16
+ class UltramodernNativeTypeChecker {
17
+ async check() {
18
+ const { configFile, build } = this.options;
19
+ if (!build) {
20
+ const config = JSON.parse(await this.run([
21
+ '--showConfig',
22
+ '--project',
23
+ configFile
24
+ ]));
25
+ if (config.references?.length) await this.run([
26
+ '--build',
27
+ ...config.references.map((reference)=>node_path.resolve(node_path.dirname(configFile), reference.path)),
28
+ '--stopBuildOnErrors',
29
+ '--pretty',
30
+ 'false'
31
+ ]);
32
+ }
33
+ const args = build ? [
34
+ '--build',
35
+ configFile,
36
+ '--stopBuildOnErrors'
37
+ ] : [
38
+ '--project',
39
+ configFile,
40
+ '--noEmit'
41
+ ];
42
+ await this.run([
43
+ ...args,
44
+ '--pretty',
45
+ 'false'
46
+ ]);
47
+ }
48
+ async run(args) {
49
+ try {
50
+ const result = await execute(this.options.compiler(), args, {
51
+ cwd: node_path.dirname(this.options.configFile),
52
+ maxBuffer: 16777216
53
+ });
54
+ return result.stdout;
55
+ } catch (cause) {
56
+ const output = cause;
57
+ const diagnostics = `${output.stdout ?? ''}${output.stderr ?? ''}`;
58
+ throw new Error(`${native_type_checker_name} failed:\n${diagnostics || (cause instanceof Error ? cause.message : String(cause))}`, {
59
+ cause
60
+ });
61
+ }
62
+ }
63
+ async watchInputs() {
64
+ const inputs = new Set();
65
+ const missing = new Set();
66
+ const projects = [
67
+ this.options.configFile
68
+ ];
69
+ const visited = new Set();
70
+ for (const configFile of projects){
71
+ if (visited.has(configFile)) continue;
72
+ visited.add(configFile);
73
+ inputs.add(configFile);
74
+ if (!existsSync(configFile)) {
75
+ missing.add(configFile);
76
+ continue;
77
+ }
78
+ let config;
79
+ try {
80
+ config = JSON.parse(await this.run([
81
+ '--showConfig',
82
+ '--project',
83
+ configFile
84
+ ]));
85
+ } catch {
86
+ continue;
87
+ }
88
+ const directory = node_path.dirname(configFile);
89
+ for (const file of config.files ?? [])inputs.add(node_path.resolve(directory, file));
90
+ for (const reference of config.references ?? []){
91
+ const target = node_path.resolve(directory, reference.path);
92
+ projects.push('.json' === node_path.extname(target) ? target : node_path.join(target, 'tsconfig.json'));
93
+ }
94
+ }
95
+ return {
96
+ inputs,
97
+ missing
98
+ };
99
+ }
100
+ apply(compiler) {
101
+ compiler.hooks.thisCompilation.tap(native_type_checker_name, (compilation)=>{
102
+ compilation.hooks.processAssets.tapPromise(native_type_checker_name, async ()=>{
103
+ try {
104
+ compilation.fileDependencies.add(watchDependencyPath(this.options.configFile));
105
+ const projectConfigFile = refreshTsgoCheckerConfig(this.options.configFile);
106
+ if (projectConfigFile) {
107
+ const watched = watchDependencyPath(projectConfigFile);
108
+ compilation.fileDependencies.add(watched);
109
+ if (!existsSync(projectConfigFile)) compilation.missingDependencies.add(watched);
110
+ }
111
+ const { inputs, missing } = await this.watchInputs();
112
+ for (const file of inputs)compilation.fileDependencies.add(watchDependencyPath(file));
113
+ for (const file of missing)compilation.missingDependencies.add(watchDependencyPath(file));
114
+ await this.check();
115
+ } catch (cause) {
116
+ compilation.errors.push(new Error(cause instanceof Error ? cause.message : String(cause), {
117
+ cause
118
+ }));
119
+ }
120
+ });
121
+ });
122
+ }
123
+ constructor(options){
124
+ this.options = options;
125
+ }
126
+ }
127
+ function configureUltramodernTypeChecker(chain, pluginId, resolveCompiler) {
128
+ if (!chain.plugins.has(pluginId)) return;
129
+ const options = chain.plugin(pluginId).get('args')?.[0];
130
+ const typescript = options?.typescript;
131
+ if (typescript?.tsgo === false) return;
132
+ if (!typescript?.configFile) throw new Error(`${native_type_checker_name} requires the configured TypeScript project.`);
133
+ const configFile = node_path.resolve(typescript.configFile);
134
+ chain.plugin(pluginId).use(UltramodernNativeTypeChecker, [
135
+ {
136
+ build: true === typescript.build,
137
+ compiler: ()=>resolveCompiler(configFile),
138
+ configFile
139
+ }
140
+ ]);
141
+ }
142
+ export { UltramodernNativeTypeChecker, configureUltramodernTypeChecker };