@bleedingdev/modern-js-app-tools 3.2.0-ultramodern.5 → 3.2.0-ultramodern.50

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 (129) hide show
  1. package/dist/cjs/builder/generator/getBuilderEnvironments.js +143 -8
  2. package/dist/cjs/builder/shared/builderPlugins/adapterBasic.js +41 -5
  3. package/dist/cjs/builder/shared/builderPlugins/adapterSSR.js +3 -1
  4. package/dist/cjs/plugins/deploy/index.js +17 -6
  5. package/dist/cjs/plugins/deploy/platforms/cloudflare.js +220 -0
  6. package/dist/cjs/plugins/deploy/platforms/templates/cloudflare-entry.mjs +258 -0
  7. package/dist/cjs/rsbuild.js +3 -0
  8. package/dist/esm/builder/generator/getBuilderEnvironments.mjs +132 -8
  9. package/dist/esm/builder/shared/builderPlugins/adapterBasic.mjs +41 -5
  10. package/dist/esm/builder/shared/builderPlugins/adapterSSR.mjs +3 -1
  11. package/dist/esm/plugins/deploy/index.mjs +10 -4
  12. package/dist/esm/plugins/deploy/platforms/cloudflare.mjs +176 -0
  13. package/dist/esm/plugins/deploy/platforms/templates/cloudflare-entry.mjs +258 -0
  14. package/dist/esm/rsbuild.mjs +5 -2
  15. package/dist/esm-node/builder/generator/getBuilderEnvironments.mjs +134 -9
  16. package/dist/esm-node/builder/shared/builderPlugins/adapterBasic.mjs +41 -5
  17. package/dist/esm-node/builder/shared/builderPlugins/adapterSSR.mjs +3 -1
  18. package/dist/esm-node/plugins/deploy/index.mjs +10 -4
  19. package/dist/esm-node/plugins/deploy/platforms/cloudflare.mjs +177 -0
  20. package/dist/esm-node/plugins/deploy/platforms/templates/cloudflare-entry.mjs +258 -0
  21. package/dist/esm-node/rsbuild.mjs +5 -2
  22. package/dist/types/baseline.d.ts +46 -0
  23. package/dist/types/builder/builder-rspack/index.d.ts +2 -0
  24. package/dist/types/builder/generator/adapterCopy.d.ts +3 -0
  25. package/dist/types/builder/generator/createBuilderProviderConfig.d.ts +3 -0
  26. package/dist/types/builder/generator/createCopyPattern.d.ts +16 -0
  27. package/dist/types/builder/generator/getBuilderEnvironments.d.ts +6 -0
  28. package/dist/types/builder/generator/index.d.ts +8 -0
  29. package/dist/types/builder/index.d.ts +3 -0
  30. package/dist/types/builder/shared/builderPlugins/adapterBasic.d.ts +3 -0
  31. package/dist/types/builder/shared/builderPlugins/adapterHtml.d.ts +3 -0
  32. package/dist/types/builder/shared/builderPlugins/adapterPrecompress.d.ts +3 -0
  33. package/dist/types/builder/shared/builderPlugins/adapterSSR.d.ts +3 -0
  34. package/dist/types/builder/shared/builderPlugins/builderHooks.d.ts +3 -0
  35. package/dist/types/builder/shared/builderPlugins/index.d.ts +5 -0
  36. package/dist/types/builder/shared/bundlerPlugins/HtmlAsyncChunkPlugin.d.ts +7 -0
  37. package/dist/types/builder/shared/bundlerPlugins/HtmlBottomTemplate.d.ts +9 -0
  38. package/dist/types/builder/shared/bundlerPlugins/RouterPlugin.d.ts +32 -0
  39. package/dist/types/builder/shared/bundlerPlugins/index.d.ts +3 -0
  40. package/dist/types/builder/shared/createCopyInfo.d.ts +8 -0
  41. package/dist/types/builder/shared/index.d.ts +3 -0
  42. package/dist/types/builder/shared/loaders/serverModuleLoader.d.ts +3 -0
  43. package/dist/types/builder/shared/types.d.ts +6 -0
  44. package/dist/types/commands/build.d.ts +4 -0
  45. package/dist/types/commands/deploy.d.ts +3 -0
  46. package/dist/types/commands/dev.d.ts +9 -0
  47. package/dist/types/commands/index.d.ts +10 -0
  48. package/dist/types/commands/info.d.ts +18 -0
  49. package/dist/types/commands/inspect.d.ts +4 -0
  50. package/dist/types/commands/runtime.d.ts +11 -0
  51. package/dist/types/commands/serve.d.ts +8 -0
  52. package/dist/types/compat/hooks.d.ts +7 -0
  53. package/dist/types/compat/index.d.ts +2 -0
  54. package/dist/types/compat/utils.d.ts +13 -0
  55. package/dist/types/config/default.d.ts +3 -0
  56. package/dist/types/config/index.d.ts +2 -0
  57. package/dist/types/config/initialize/index.d.ts +3 -0
  58. package/dist/types/config/initialize/inits.d.ts +4 -0
  59. package/dist/types/constants.d.ts +2 -0
  60. package/dist/types/defineConfig.d.ts +11 -0
  61. package/dist/types/esm/register-esm.d.mts +5 -0
  62. package/dist/types/esm/ts-paths-loader.d.mts +6 -0
  63. package/dist/types/exports/server.d.ts +1 -0
  64. package/dist/types/index.d.ts +17 -0
  65. package/dist/types/locale/en.d.ts +44 -0
  66. package/dist/types/locale/index.d.ts +3 -0
  67. package/dist/types/locale/zh.d.ts +44 -0
  68. package/dist/types/plugins/analyze/constants.d.ts +3 -0
  69. package/dist/types/plugins/analyze/getBundleEntry.d.ts +4 -0
  70. package/dist/types/plugins/analyze/getFileSystemEntry.d.ts +7 -0
  71. package/dist/types/plugins/analyze/getHtmlTemplate.d.ts +27 -0
  72. package/dist/types/plugins/analyze/getServerRoutes.d.ts +8 -0
  73. package/dist/types/plugins/analyze/index.d.ts +3 -0
  74. package/dist/types/plugins/analyze/isDefaultExportFunction.d.ts +1 -0
  75. package/dist/types/plugins/analyze/templates.d.ts +5 -0
  76. package/dist/types/plugins/analyze/utils.d.ts +10 -0
  77. package/dist/types/plugins/deploy/index.d.ts +6 -0
  78. package/dist/types/plugins/deploy/platforms/cloudflare.d.ts +2 -0
  79. package/dist/types/plugins/deploy/platforms/gh-pages.d.ts +2 -0
  80. package/dist/types/plugins/deploy/platforms/netlify.d.ts +2 -0
  81. package/dist/types/plugins/deploy/platforms/node.d.ts +2 -0
  82. package/dist/types/plugins/deploy/platforms/platform.d.ts +17 -0
  83. package/dist/types/plugins/deploy/platforms/templates/cloudflare-entry.d.mts +4 -0
  84. package/dist/types/plugins/deploy/platforms/templates/netlify-entry.d.cts +2 -0
  85. package/dist/types/plugins/deploy/platforms/templates/netlify-entry.d.mts +2 -0
  86. package/dist/types/plugins/deploy/platforms/templates/node-entry.d.cts +1 -0
  87. package/dist/types/plugins/deploy/platforms/templates/node-entry.d.mts +1 -0
  88. package/dist/types/plugins/deploy/platforms/templates/vercel-entry.d.cts +2 -0
  89. package/dist/types/plugins/deploy/platforms/templates/vercel-entry.d.mts +2 -0
  90. package/dist/types/plugins/deploy/platforms/vercel.d.ts +2 -0
  91. package/dist/types/plugins/deploy/types.d.ts +3 -0
  92. package/dist/types/plugins/deploy/utils/generator.d.ts +24 -0
  93. package/dist/types/plugins/deploy/utils/index.d.ts +16 -0
  94. package/dist/types/plugins/initialize/index.d.ts +3 -0
  95. package/dist/types/plugins/serverBuild.d.ts +3 -0
  96. package/dist/types/plugins/serverRuntime.d.ts +3 -0
  97. package/dist/types/presetUltramodern.d.ts +6 -0
  98. package/dist/types/rsbuild.d.ts +12 -0
  99. package/dist/types/run/index.d.ts +20 -0
  100. package/dist/types/types/config/deploy.d.ts +46 -0
  101. package/dist/types/types/config/dev.d.ts +55 -0
  102. package/dist/types/types/config/experiments.d.ts +3 -0
  103. package/dist/types/types/config/html.d.ts +3 -0
  104. package/dist/types/types/config/index.d.ts +48 -0
  105. package/dist/types/types/config/output.d.ts +61 -0
  106. package/dist/types/types/config/performance.d.ts +3 -0
  107. package/dist/types/types/config/resolve.d.ts +2 -0
  108. package/dist/types/types/config/security.d.ts +2 -0
  109. package/dist/types/types/config/source.d.ts +61 -0
  110. package/dist/types/types/config/testing.d.ts +8 -0
  111. package/dist/types/types/config/tools.d.ts +21 -0
  112. package/dist/types/types/index.d.ts +10 -0
  113. package/dist/types/types/plugin.d.ts +114 -0
  114. package/dist/types/types/utils.d.ts +1 -0
  115. package/dist/types/ultramodern/designSystem.d.ts +54 -0
  116. package/dist/types/utils/config.d.ts +2 -0
  117. package/dist/types/utils/createServer.d.ts +5 -0
  118. package/dist/types/utils/env.d.ts +2 -0
  119. package/dist/types/utils/generateWatchFiles.d.ts +2 -0
  120. package/dist/types/utils/getConfigFile.d.ts +1 -0
  121. package/dist/types/utils/getSelectedEntries.d.ts +5 -0
  122. package/dist/types/utils/initAppContext.d.ts +31 -0
  123. package/dist/types/utils/loadPlugins.d.ts +13 -0
  124. package/dist/types/utils/printInstructions.d.ts +3 -0
  125. package/dist/types/utils/register.d.ts +19 -0
  126. package/dist/types/utils/restart.d.ts +2 -0
  127. package/dist/types/utils/routes.d.ts +4 -0
  128. package/dist/types/utils/types.d.ts +49 -0
  129. package/package.json +15 -15
@@ -0,0 +1,176 @@
1
+ import node_path from "node:path";
2
+ import { fs } from "@modern-js/utils";
3
+ import { readTemplate } from "../utils/index.mjs";
4
+ const WORKER_ENTRY = 'server/index.mjs';
5
+ const WORKER_MANIFEST = 'server/modern-worker-manifest.json';
6
+ const ASSETS_BINDING = 'ASSETS';
7
+ const ROUTE_SPEC_FILE = 'route.json';
8
+ const ROUTE_SPEC_OUTPUT = `server/${ROUTE_SPEC_FILE}`;
9
+ const LOADABLE_STATS_FILE = 'loadable-stats.json';
10
+ const ROUTE_MANIFEST_FILE = 'routes-manifest.json';
11
+ const PUBLIC_ASSETS_DIRECTORY = 'public';
12
+ const WORKER_BUNDLE_DIRECTORY = 'worker';
13
+ const SERVER_BUNDLE_DIRECTORY = 'bundles';
14
+ const BFF_EFFECT_WORKER_ENTRY = `${WORKER_BUNDLE_DIRECTORY}/__modern_bff_effect.js`;
15
+ const getCompatibilityDate = ()=>new Date().toISOString().slice(0, 10);
16
+ const getWorkerName = (appDirectory)=>{
17
+ const basename = node_path.basename(appDirectory);
18
+ return basename.replace(/[^a-zA-Z0-9-_]/g, '-') || 'modern-cloudflare-worker';
19
+ };
20
+ const getConfiguredWorkerName = (appDirectory, modernConfig)=>{
21
+ const configuredName = modernConfig.deploy?.worker?.name?.trim();
22
+ return configuredName || getWorkerName(appDirectory);
23
+ };
24
+ const readRouteSpec = async (outputDirectory)=>{
25
+ const routeSpecPath = node_path.join(outputDirectory, ROUTE_SPEC_OUTPUT);
26
+ if (!await fs.pathExists(routeSpecPath)) return {
27
+ routes: []
28
+ };
29
+ const routeSpec = await fs.readJSON(routeSpecPath);
30
+ return {
31
+ ...routeSpec,
32
+ routes: Array.isArray(routeSpec.routes) ? routeSpec.routes : []
33
+ };
34
+ };
35
+ const createWorkerManifest = async (outputDirectory, modernConfig)=>{
36
+ const routeSpec = await readRouteSpec(outputDirectory);
37
+ const routes = await Promise.all(routeSpec.routes.map(async (route)=>{
38
+ const worker = 'string' == typeof route.worker ? route.worker : void 0;
39
+ return {
40
+ urlPath: route.urlPath,
41
+ entryName: route.entryName,
42
+ entryPath: route.entryPath,
43
+ isSSR: Boolean(route.isSSR),
44
+ worker,
45
+ workerExists: worker ? await fs.pathExists(node_path.join(outputDirectory, worker)) : false
46
+ };
47
+ }));
48
+ const bffPrefix = modernConfig.bff?.prefix;
49
+ const primaryBffPrefix = Array.isArray(bffPrefix) ? bffPrefix[0] : bffPrefix;
50
+ const isEffectBff = Boolean(modernConfig.bff) && modernConfig.bff?.runtimeFramework !== 'hono';
51
+ const effectBffWorkerExists = await fs.pathExists(node_path.join(outputDirectory, BFF_EFFECT_WORKER_ENTRY));
52
+ return {
53
+ version: 1,
54
+ runtime: {
55
+ type: 'cloudflare-module-worker',
56
+ entry: WORKER_ENTRY,
57
+ fetchExport: true,
58
+ nodeListen: false
59
+ },
60
+ assets: {
61
+ binding: ASSETS_BINDING,
62
+ directory: `./${PUBLIC_ASSETS_DIRECTORY}`,
63
+ runWorkerFirst: true
64
+ },
65
+ routeSpec: {
66
+ file: ROUTE_SPEC_OUTPUT,
67
+ routes
68
+ },
69
+ workerBundles: {
70
+ directory: WORKER_BUNDLE_DIRECTORY,
71
+ format: 'esm',
72
+ importableFromModuleWorker: true,
73
+ requestHandlerExport: 'requestHandler'
74
+ },
75
+ resources: {
76
+ loadableStats: LOADABLE_STATS_FILE,
77
+ routeManifest: ROUTE_MANIFEST_FILE
78
+ },
79
+ bff: isEffectBff && primaryBffPrefix && effectBffWorkerExists ? {
80
+ runtimeFramework: 'effect',
81
+ prefix: primaryBffPrefix,
82
+ worker: BFF_EFFECT_WORKER_ENTRY
83
+ } : void 0
84
+ };
85
+ };
86
+ const createWorkerModuleLoaders = (manifest)=>{
87
+ const imports = new Map();
88
+ for (const route of manifest.routeSpec.routes)if (route.worker && route.workerExists) {
89
+ const importPath = `../${String(route.worker).replace(/^\/+/u, '')}`;
90
+ imports.set(route.worker, `() => import(${JSON.stringify(importPath)})`);
91
+ }
92
+ if (manifest.bff?.worker) {
93
+ const importPath = `../${String(manifest.bff.worker).replace(/^\/+/u, '')}`;
94
+ imports.set(manifest.bff.worker, `() => import(${JSON.stringify(importPath)})`);
95
+ }
96
+ if (0 === imports.size) return '{}';
97
+ const loaders = [
98
+ ...imports.entries()
99
+ ].map(([worker, loader])=>`${JSON.stringify(worker)}: ${loader}`);
100
+ return `{\n${loaders.join(',\n')}\n}`;
101
+ };
102
+ const shouldCopyToPublicAssets = (src, distDirectory)=>{
103
+ const relativePath = node_path.relative(distDirectory, src);
104
+ if (!relativePath) return true;
105
+ const normalizedRelativePath = relativePath.replace(/\\/g, '/');
106
+ const [topLevelDirectory] = normalizedRelativePath.split('/');
107
+ return normalizedRelativePath !== ROUTE_SPEC_FILE && topLevelDirectory !== WORKER_BUNDLE_DIRECTORY && topLevelDirectory !== SERVER_BUNDLE_DIRECTORY;
108
+ };
109
+ const shouldCopyToWorkerBundle = (src, workerBundleDirectory)=>{
110
+ const relativePath = node_path.relative(workerBundleDirectory, src);
111
+ if (!relativePath) return true;
112
+ const normalizedRelativePath = relativePath.replace(/\\/g, '/');
113
+ const basename = node_path.basename(normalizedRelativePath);
114
+ if (basename.startsWith('.') || normalizedRelativePath.includes('/.')) return false;
115
+ return [
116
+ '.cjs',
117
+ '.js',
118
+ '.mjs'
119
+ ].includes(node_path.extname(normalizedRelativePath));
120
+ };
121
+ const createCloudflarePreset = ({ appContext, modernConfig })=>{
122
+ const { appDirectory, distDirectory } = appContext;
123
+ const outputDirectory = node_path.join(appDirectory, '.output');
124
+ const publicDirectory = node_path.join(outputDirectory, PUBLIC_ASSETS_DIRECTORY);
125
+ const workerEntryPath = node_path.join(outputDirectory, WORKER_ENTRY);
126
+ const workerManifestPath = node_path.join(outputDirectory, WORKER_MANIFEST);
127
+ const routeSpecOutputPath = node_path.join(outputDirectory, ROUTE_SPEC_OUTPUT);
128
+ const wranglerConfigPath = node_path.join(outputDirectory, 'wrangler.json');
129
+ const workerName = getConfiguredWorkerName(appDirectory, modernConfig);
130
+ return {
131
+ async prepare () {
132
+ await fs.remove(outputDirectory);
133
+ },
134
+ async writeOutput () {
135
+ await fs.copy(distDirectory, publicDirectory, {
136
+ filter: (src)=>shouldCopyToPublicAssets(src, distDirectory)
137
+ });
138
+ await fs.ensureDir(node_path.dirname(workerEntryPath));
139
+ await fs.ensureDir(node_path.dirname(workerManifestPath));
140
+ const routeSpecSourcePath = node_path.join(distDirectory, ROUTE_SPEC_FILE);
141
+ if (await fs.pathExists(routeSpecSourcePath)) await fs.copy(routeSpecSourcePath, routeSpecOutputPath);
142
+ const workerBundleSourceDirectory = node_path.join(distDirectory, WORKER_BUNDLE_DIRECTORY);
143
+ if (await fs.pathExists(workerBundleSourceDirectory)) await fs.copy(workerBundleSourceDirectory, node_path.join(outputDirectory, WORKER_BUNDLE_DIRECTORY), {
144
+ filter: (src)=>shouldCopyToWorkerBundle(src, workerBundleSourceDirectory)
145
+ });
146
+ await fs.writeJSON(wranglerConfigPath, {
147
+ $schema: 'node_modules/wrangler/config-schema.json',
148
+ name: workerName,
149
+ main: WORKER_ENTRY,
150
+ compatibility_date: getCompatibilityDate(),
151
+ compatibility_flags: [
152
+ 'nodejs_compat'
153
+ ],
154
+ assets: {
155
+ directory: `./${PUBLIC_ASSETS_DIRECTORY}`,
156
+ binding: ASSETS_BINDING,
157
+ run_worker_first: true
158
+ }
159
+ }, {
160
+ spaces: 2
161
+ });
162
+ await fs.writeJSON(workerManifestPath, await createWorkerManifest(outputDirectory, modernConfig), {
163
+ spaces: 2
164
+ });
165
+ await fs.writeJSON(node_path.join(outputDirectory, 'package.json'), {
166
+ type: 'module'
167
+ });
168
+ },
169
+ async genEntry () {
170
+ const template = await readTemplate('cloudflare-entry.mjs');
171
+ const manifest = await fs.readJSON(workerManifestPath);
172
+ await fs.writeFile(workerEntryPath, template.replace('p_workerManifest', JSON.stringify(manifest, null, 2)).replace('p_workerModuleLoaders', createWorkerModuleLoaders(manifest)));
173
+ }
174
+ };
175
+ };
176
+ export { createCloudflarePreset };
@@ -0,0 +1,258 @@
1
+ const ASSETS_BINDING = 'ASSETS';
2
+ const MODERN_WORKER_MANIFEST = p_workerManifest;
3
+ const WORKER_MODULE_LOADERS = p_workerModuleLoaders;
4
+ const workerModulePromises = new Map();
5
+ const CORS_HEADERS = {
6
+ 'access-control-allow-headers': '*',
7
+ 'access-control-allow-methods': 'GET, HEAD, OPTIONS',
8
+ 'access-control-allow-origin': '*'
9
+ };
10
+ globalThis.__dirname ??= '/';
11
+ globalThis.__filename ??= '/index.js';
12
+ function withCorsHeaders(response) {
13
+ const headers = new Headers(response.headers);
14
+ for (const [name, value] of Object.entries(CORS_HEADERS))if (!headers.has(name)) headers.set(name, value);
15
+ return new Response(response.body, {
16
+ headers,
17
+ status: response.status,
18
+ statusText: response.statusText
19
+ });
20
+ }
21
+ function createCorsPreflightResponse(request) {
22
+ if ('OPTIONS' !== request.method) return null;
23
+ return new Response(null, {
24
+ headers: CORS_HEADERS,
25
+ status: 204
26
+ });
27
+ }
28
+ async function fetchAsset(request, env) {
29
+ const assets = env?.[ASSETS_BINDING];
30
+ if (!assets || 'function' != typeof assets.fetch) return null;
31
+ const response = await assets.fetch(request);
32
+ if (404 === response.status) return null;
33
+ return withCorsHeaders(response);
34
+ }
35
+ async function fetchAssetByPath(pathname, request, env) {
36
+ const url = new URL(request.url);
37
+ url.pathname = `/${pathname.replace(/^\/+/u, '')}`;
38
+ return fetchAsset(new Request(url, request), env);
39
+ }
40
+ async function fetchAssetByPathFollowingRedirects(pathname, request, env, visited = new Set()) {
41
+ const normalizedPathname = pathname.startsWith('/') ? pathname : `/${pathname}`;
42
+ if (visited.has(normalizedPathname)) return null;
43
+ visited.add(normalizedPathname);
44
+ const response = await fetchAssetByPath(normalizedPathname, request, env);
45
+ if (response && response.status >= 300 && response.status < 400 && response.headers.has('location')) {
46
+ const location = response.headers.get('location');
47
+ if (location) {
48
+ const nextUrl = new URL(location, request.url);
49
+ const currentUrl = new URL(request.url);
50
+ if (nextUrl.origin === currentUrl.origin) return fetchAssetByPathFollowingRedirects(nextUrl.pathname, request, env, visited);
51
+ }
52
+ }
53
+ return response;
54
+ }
55
+ async function readAssetText(pathname, request, env) {
56
+ const response = await fetchAssetByPathFollowingRedirects(pathname, request, env);
57
+ if (!response || !response.ok) return;
58
+ return response.text();
59
+ }
60
+ async function readAssetJson(pathname, request, env) {
61
+ const text = await readAssetText(pathname, request, env);
62
+ if (!text) return {};
63
+ return JSON.parse(text);
64
+ }
65
+ function normalizeRoutePath(pathname) {
66
+ if ('/' === pathname) return pathname;
67
+ return pathname.replace(/\/+$/u, '');
68
+ }
69
+ function routeMatches(route, pathname) {
70
+ if ('string' != typeof route.urlPath) return false;
71
+ const routePath = normalizeRoutePath(route.urlPath);
72
+ const requestPath = normalizeRoutePath(pathname);
73
+ return routePath === requestPath || '/' === routePath && route.isSSR || requestPath.startsWith(`${routePath}/`);
74
+ }
75
+ function findRoute(request) {
76
+ const { pathname } = new URL(request.url);
77
+ const routes = MODERN_WORKER_MANIFEST.routeSpec.routes;
78
+ return [
79
+ ...routes
80
+ ].sort((left, right)=>{
81
+ const leftLength = left.urlPath?.length || 0;
82
+ const rightLength = right.urlPath?.length || 0;
83
+ return rightLength - leftLength;
84
+ }).find((route)=>routeMatches(route, pathname));
85
+ }
86
+ async function fetchRouteHtml(route, request, env) {
87
+ if (!route?.entryPath) return null;
88
+ return fetchAssetByPath(route.entryPath, request, env);
89
+ }
90
+ function createNoopMonitors() {
91
+ const noop = ()=>{};
92
+ return {
93
+ debug: noop,
94
+ error: noop,
95
+ info: noop,
96
+ warn: noop
97
+ };
98
+ }
99
+ function createRequestHandlerOptions({ route, htmlTemplate, routeManifest, loadableStats }) {
100
+ const monitors = createNoopMonitors();
101
+ return {
102
+ resource: {
103
+ route,
104
+ routeManifest,
105
+ loadableStats,
106
+ htmlTemplate,
107
+ entryName: route.entryName
108
+ },
109
+ params: {},
110
+ loaderContext: {},
111
+ config: {},
112
+ locals: {},
113
+ staticGenerate: false,
114
+ monitors,
115
+ onError (error) {
116
+ monitors.error(error);
117
+ },
118
+ onTiming () {},
119
+ reporter: {
120
+ reportTiming: ()=>{}
121
+ }
122
+ };
123
+ }
124
+ async function getRequestHandlerOptions(route, request, env) {
125
+ const [htmlTemplate, routeManifest, loadableStats] = await Promise.all([
126
+ readAssetText(route.entryPath, request, env),
127
+ readAssetJson(MODERN_WORKER_MANIFEST.resources.routeManifest, request, env),
128
+ readAssetJson(MODERN_WORKER_MANIFEST.resources.loadableStats, request, env)
129
+ ]);
130
+ return createRequestHandlerOptions({
131
+ route,
132
+ htmlTemplate: htmlTemplate || '',
133
+ routeManifest,
134
+ loadableStats
135
+ });
136
+ }
137
+ async function loadWorkerModule(workerPath) {
138
+ const loader = WORKER_MODULE_LOADERS[workerPath];
139
+ if (!loader) return;
140
+ if (!workerModulePromises.has(workerPath)) workerModulePromises.set(workerPath, loader());
141
+ return workerModulePromises.get(workerPath);
142
+ }
143
+ function getFetchHandler(workerModule) {
144
+ const defaultExport = workerModule.default;
145
+ return defaultExport && 'object' == typeof defaultExport && 'function' == typeof defaultExport.fetch && defaultExport.fetch.bind(defaultExport) || 'function' == typeof workerModule.fetch && workerModule.fetch;
146
+ }
147
+ async function getRequestHandler(workerModule) {
148
+ const defaultExport = workerModule.default;
149
+ const defaultRequestHandler = defaultExport && 'object' == typeof defaultExport && 'requestHandler' in defaultExport ? defaultExport.requestHandler : void 0;
150
+ return await workerModule.requestHandler || await defaultRequestHandler || ('function' == typeof defaultExport ? defaultExport : void 0);
151
+ }
152
+ async function dispatchRouteWorker(route, request, env, ctx) {
153
+ const workerPath = route.worker;
154
+ if (!workerPath) return new Response('Worker bundle not configured for SSR route', {
155
+ status: 500,
156
+ headers: {
157
+ 'content-type': 'text/plain; charset=utf-8'
158
+ }
159
+ });
160
+ const workerModule = await loadWorkerModule(workerPath);
161
+ if (!workerModule) return new Response(`Worker bundle not found: ${workerPath}`, {
162
+ status: 500,
163
+ headers: {
164
+ 'content-type': 'text/plain; charset=utf-8',
165
+ 'x-modern-js-route-worker': workerPath
166
+ }
167
+ });
168
+ const fetchHandler = getFetchHandler(workerModule);
169
+ if (fetchHandler) return fetchHandler(request, env, ctx);
170
+ const requestHandler = await getRequestHandler(workerModule);
171
+ if ('function' == typeof requestHandler) {
172
+ const requestHandlerOptions = await getRequestHandlerOptions(route, request, env);
173
+ return requestHandler(request, requestHandlerOptions);
174
+ }
175
+ return new Response(`Worker bundle has no fetch or requestHandler export: ${workerPath}`, {
176
+ status: 500,
177
+ headers: {
178
+ 'content-type': 'text/plain; charset=utf-8',
179
+ 'x-modern-js-route-worker': workerPath
180
+ }
181
+ });
182
+ }
183
+ function matchesPrefix(pathname, prefix) {
184
+ if (!prefix || '/' === prefix) return true;
185
+ const normalized = prefix.endsWith('/') ? prefix.slice(0, -1) : prefix;
186
+ return pathname === normalized || pathname.startsWith(`${normalized}/`);
187
+ }
188
+ function createRequestForMountedPrefix(request, prefix) {
189
+ if (!prefix || '/' === prefix) return request;
190
+ const url = new URL(request.url);
191
+ const normalized = prefix.endsWith('/') ? prefix.slice(0, -1) : prefix;
192
+ if (!matchesPrefix(url.pathname, normalized)) return request;
193
+ const nextPath = url.pathname.slice(normalized.length) || '/';
194
+ url.pathname = nextPath.startsWith('/') ? nextPath : `/${nextPath}`;
195
+ return new Request(url, request);
196
+ }
197
+ function createEffectContext(originalRequest, mountedRequest, env) {
198
+ const url = new URL(originalRequest.url);
199
+ return {
200
+ request: mountedRequest,
201
+ env: env || {},
202
+ path: url.pathname,
203
+ method: originalRequest.method,
204
+ operationContext: {
205
+ request: mountedRequest,
206
+ env: env || {},
207
+ path: url.pathname,
208
+ method: originalRequest.method
209
+ }
210
+ };
211
+ }
212
+ async function dispatchBffRequest(request, env) {
213
+ const bff = MODERN_WORKER_MANIFEST.bff;
214
+ if (!bff?.worker || !matchesPrefix(new URL(request.url).pathname, bff.prefix)) return null;
215
+ const workerModule = await loadWorkerModule(bff.worker);
216
+ if (!workerModule) return new Response(`BFF worker bundle not found: ${bff.worker}`, {
217
+ status: 500,
218
+ headers: {
219
+ 'content-type': 'text/plain; charset=utf-8',
220
+ 'x-modern-js-bff-worker': bff.worker
221
+ }
222
+ });
223
+ const mountedRequest = createRequestForMountedPrefix(request, bff.prefix);
224
+ const effectContext = createEffectContext(request, mountedRequest, env);
225
+ const defaultExport = workerModule.default;
226
+ const runtime = defaultExport && 'object' == typeof defaultExport ? {
227
+ ...workerModule,
228
+ ...defaultExport
229
+ } : workerModule;
230
+ const directHandler = 'function' == typeof runtime.handler && runtime.handler || 'function' == typeof defaultExport && defaultExport;
231
+ const createdHandler = 'function' == typeof runtime.createHandler ? runtime.createHandler().handler : void 0;
232
+ const handler = directHandler || createdHandler;
233
+ if ('function' != typeof handler) return new Response(`BFF worker bundle has no handler export: ${bff.worker}`, {
234
+ status: 500,
235
+ headers: {
236
+ 'content-type': 'text/plain; charset=utf-8',
237
+ 'x-modern-js-bff-worker': bff.worker
238
+ }
239
+ });
240
+ return handler.length > 1 ? handler(mountedRequest, effectContext) : handler(mountedRequest);
241
+ }
242
+ export default {
243
+ async fetch (request, env, ctx) {
244
+ const corsPreflightResponse = createCorsPreflightResponse(request);
245
+ if (corsPreflightResponse) return corsPreflightResponse;
246
+ const assetResponse = await fetchAsset(request, env);
247
+ if (assetResponse) return assetResponse;
248
+ const bffResponse = await dispatchBffRequest(request, env);
249
+ if (bffResponse) return withCorsHeaders(bffResponse);
250
+ const route = findRoute(request);
251
+ if (route?.worker) return withCorsHeaders(await dispatchRouteWorker(route, request, env, ctx));
252
+ const htmlResponse = await fetchRouteHtml(route, request, env);
253
+ if (htmlResponse) return htmlResponse;
254
+ return withCorsHeaders(new Response('Not found', {
255
+ status: 404
256
+ }));
257
+ }
258
+ };
@@ -1,16 +1,18 @@
1
1
  import { parseRspackConfig } from "@modern-js/builder";
2
+ import { INTERNAL_RUNTIME_PLUGINS } from "@modern-js/utils";
2
3
  import { builderPluginAdapterBasic, builderPluginAdapterHooks } from "./builder/shared/builderPlugins/index.mjs";
3
4
  import { DEFAULT_CONFIG_FILE } from "./constants.mjs";
4
5
  import { getConfigFile } from "./utils/getConfigFile.mjs";
6
+ import { loadInternalPlugins } from "./utils/loadPlugins.mjs";
5
7
  import { __webpack_require__ } from "./rslib-runtime.mjs";
6
8
  import * as __rspack_external__modern_js_plugin_cli_caa09fa2 from "@modern-js/plugin/cli";
7
9
  __webpack_require__.add({
8
- "@modern-js/plugin/cli?f956" (module) {
10
+ "@modern-js/plugin/cli?8936" (module) {
9
11
  module.exports = __rspack_external__modern_js_plugin_cli_caa09fa2;
10
12
  }
11
13
  });
12
14
  const MODERN_META_NAME = 'modern-js';
13
- const { createConfigOptions: createConfigOptions } = __webpack_require__("@modern-js/plugin/cli?f956");
15
+ const { createConfigOptions: createConfigOptions } = __webpack_require__("@modern-js/plugin/cli?8936");
14
16
  async function resolveModernRsbuildConfig(options) {
15
17
  const { cwd = process.cwd(), metaName = MODERN_META_NAME } = options;
16
18
  const configFile = options.configPath || getConfigFile(void 0, cwd);
@@ -19,6 +21,7 @@ async function resolveModernRsbuildConfig(options) {
19
21
  command: options.command,
20
22
  cwd,
21
23
  configFile,
24
+ internalPlugins: await loadInternalPlugins(cwd, INTERNAL_RUNTIME_PLUGINS),
22
25
  metaName,
23
26
  modifyModernConfig: options.modifyModernConfig
24
27
  });
@@ -1,6 +1,42 @@
1
- import "node:module";
1
+ import __rslib_shim_module__ from "node:module";
2
+ const require = /*#__PURE__*/ __rslib_shim_module__.createRequire(/*#__PURE__*/ (()=>import.meta.url)());
3
+ import node_fs from "node:fs";
4
+ import node_path from "node:path";
2
5
  import { SERVICE_WORKER_ENVIRONMENT_NAME } from "@modern-js/builder";
3
6
  import { isProd, isSSR, isServiceWorker, isUseRsc, isUseSSRBundle } from "@modern-js/utils";
7
+ const BFF_EFFECT_WORKER_ENTRY_NAME = '__modern_bff_effect';
8
+ const BFF_EFFECT_WORKER_RUNTIME_QUERY = 'modern-bff-runtime';
9
+ const JS_OR_TS_EXTS = [
10
+ '.ts',
11
+ '.tsx',
12
+ '.js',
13
+ '.jsx',
14
+ '.mjs',
15
+ '.cjs'
16
+ ];
17
+ function findExistingFile(candidates) {
18
+ return candidates.find((candidate)=>node_fs.existsSync(candidate));
19
+ }
20
+ function resolvePackageFile(packageName, filePath, paths) {
21
+ try {
22
+ const packageJsonPath = require.resolve(`${packageName}/package.json`, {
23
+ paths
24
+ });
25
+ const packageFile = node_path.join(node_path.dirname(packageJsonPath), filePath);
26
+ return node_fs.existsSync(packageFile) ? node_fs.realpathSync(packageFile) : void 0;
27
+ } catch {
28
+ return;
29
+ }
30
+ }
31
+ function setAliasIfPresent(alias, name, value) {
32
+ if (value) alias.set(name, value);
33
+ }
34
+ function getEffectBffEntry(normalizedConfig, appContext) {
35
+ if (!normalizedConfig.bff || 'hono' === normalizedConfig.bff.runtimeFramework) return;
36
+ const configuredEntry = normalizedConfig.bff.effect?.entry;
37
+ const entryWithoutExtension = configuredEntry ? node_path.isAbsolute(configuredEntry) ? configuredEntry : node_path.resolve(appContext.appDirectory, configuredEntry) : node_path.resolve(appContext.apiDirectory, 'effect', 'index');
38
+ return findExistingFile(JS_OR_TS_EXTS.map((extension)=>`${entryWithoutExtension}${extension}`));
39
+ }
4
40
  function getBuilderEnvironments(normalizedConfig, appContext, tempBuilderConfig) {
5
41
  const entries = {};
6
42
  const { entrypoints = [], checkedEntries } = appContext;
@@ -17,6 +53,11 @@ function getBuilderEnvironments(normalizedConfig, appContext, tempBuilderConfig)
17
53
  const v = entries[entry];
18
54
  serverEntries[entry] = v.map((entry)=>entry.replace('index.jsx', 'index.server.jsx')).map((entry)=>entry.replace('bootstrap.jsx', 'bootstrap.server.jsx'));
19
55
  }
56
+ const cloudflareWorkerServerEntries = {};
57
+ for(const entry in entries){
58
+ const v = entries[entry];
59
+ cloudflareWorkerServerEntries[entry] = v.map((entry)=>entry.replace('index.jsx', 'index.server.jsx')).map((entry)=>entry.replace('bootstrap.jsx', 'index.server.jsx'));
60
+ }
20
61
  const environments = {
21
62
  client: {
22
63
  output: {
@@ -41,14 +82,98 @@ function getBuilderEnvironments(normalizedConfig, appContext, tempBuilderConfig)
41
82
  }
42
83
  };
43
84
  const useWorkerTarget = isServiceWorker(normalizedConfig);
44
- if (useWorkerTarget) environments[SERVICE_WORKER_ENVIRONMENT_NAME] = {
45
- output: {
46
- target: 'web-worker'
47
- },
48
- source: {
49
- entry: serverEntries
50
- }
51
- };
85
+ if (useWorkerTarget) {
86
+ const useCloudflareModuleWorker = normalizedConfig.deploy?.target === 'cloudflare';
87
+ const effectBffEntry = useCloudflareModuleWorker ? getEffectBffEntry(normalizedConfig, appContext) : void 0;
88
+ const tanstackRouterSsrServerFile = useCloudflareModuleWorker ? resolvePackageFile('@tanstack/router-core', 'dist/esm/ssr/ssr-server.js', [
89
+ appContext.appDirectory,
90
+ process.cwd()
91
+ ]) : void 0;
92
+ const runtimeRscWorkerFile = useCloudflareModuleWorker ? resolvePackageFile('@modern-js/runtime', 'dist/esm/rsc/server.worker.mjs', [
93
+ appContext.appDirectory,
94
+ process.cwd()
95
+ ]) : void 0;
96
+ const renderRscWorkerFile = useCloudflareModuleWorker ? resolvePackageFile('@modern-js/render', 'dist/esm/rscWorker.mjs', [
97
+ appContext.appDirectory,
98
+ process.cwd()
99
+ ]) : void 0;
100
+ const reactFile = useCloudflareModuleWorker ? resolvePackageFile('react', 'index.js', [
101
+ appContext.appDirectory,
102
+ process.cwd()
103
+ ]) : void 0;
104
+ const reactJsxRuntimeFile = useCloudflareModuleWorker ? resolvePackageFile('react', 'jsx-runtime.js', [
105
+ appContext.appDirectory,
106
+ process.cwd()
107
+ ]) : void 0;
108
+ const reactJsxDevRuntimeFile = useCloudflareModuleWorker ? resolvePackageFile('react', 'jsx-dev-runtime.js', [
109
+ appContext.appDirectory,
110
+ process.cwd()
111
+ ]) : void 0;
112
+ const reactDomFile = useCloudflareModuleWorker ? resolvePackageFile('react-dom', 'index.js', [
113
+ appContext.appDirectory,
114
+ process.cwd()
115
+ ]) : void 0;
116
+ const reactDomServerEdgeFile = useCloudflareModuleWorker ? resolvePackageFile('react-dom', 'server.edge.js', [
117
+ appContext.appDirectory,
118
+ process.cwd()
119
+ ]) : void 0;
120
+ const baseWorkerEntries = useCloudflareModuleWorker ? cloudflareWorkerServerEntries : serverEntries;
121
+ const workerEntries = effectBffEntry ? {
122
+ ...baseWorkerEntries,
123
+ [BFF_EFFECT_WORKER_ENTRY_NAME]: [
124
+ `${effectBffEntry}?${BFF_EFFECT_WORKER_RUNTIME_QUERY}`
125
+ ]
126
+ } : baseWorkerEntries;
127
+ environments[SERVICE_WORKER_ENVIRONMENT_NAME] = {
128
+ output: {
129
+ target: useCloudflareModuleWorker ? 'web' : 'web-worker',
130
+ ...useCloudflareModuleWorker ? {
131
+ module: true
132
+ } : {}
133
+ },
134
+ source: {
135
+ entry: workerEntries
136
+ },
137
+ tools: {
138
+ htmlPlugin: false,
139
+ ...useCloudflareModuleWorker ? {
140
+ bundlerChain: (chain)=>{
141
+ chain.merge({
142
+ experiments: {
143
+ outputModule: true
144
+ }
145
+ });
146
+ chain.target('webworker');
147
+ chain.plugins.delete('plugin-module-federation');
148
+ if (tanstackRouterSsrServerFile) {
149
+ chain.resolve.alias.set('@tanstack/router-core/ssr/server$', tanstackRouterSsrServerFile);
150
+ chain.resolve.alias.set('@tanstack/router-core/ssr/server', tanstackRouterSsrServerFile);
151
+ }
152
+ if (runtimeRscWorkerFile) {
153
+ chain.resolve.alias.set('@modern-js/runtime/rsc/server$', runtimeRscWorkerFile);
154
+ chain.resolve.alias.set('@modern-js/runtime/rsc/server', runtimeRscWorkerFile);
155
+ }
156
+ if (renderRscWorkerFile) {
157
+ chain.resolve.alias.set('@modern-js/render/rsc$', renderRscWorkerFile);
158
+ chain.resolve.alias.set('@modern-js/render/rsc', renderRscWorkerFile);
159
+ chain.resolve.alias.set('@modern-js/render/rsc-worker$', renderRscWorkerFile);
160
+ }
161
+ setAliasIfPresent(chain.resolve.alias, 'react$', reactFile);
162
+ setAliasIfPresent(chain.resolve.alias, 'react/jsx-runtime$', reactJsxRuntimeFile);
163
+ setAliasIfPresent(chain.resolve.alias, 'react/jsx-dev-runtime$', reactJsxDevRuntimeFile);
164
+ setAliasIfPresent(chain.resolve.alias, 'react-dom$', reactDomFile);
165
+ setAliasIfPresent(chain.resolve.alias, 'react-dom/server.edge$', reactDomServerEdgeFile);
166
+ chain.resolve.alias.set('react-server-dom-rspack/server.node$', 'react-server-dom-rspack/server.edge');
167
+ chain.resolve.alias.set('react-server-dom-rspack/server.node', 'react-server-dom-rspack/server.edge');
168
+ chain.resolve.alias.set('react-server-dom-rspack/client.node$', 'react-server-dom-rspack/client.edge');
169
+ chain.resolve.alias.set('react-server-dom-rspack/client.node', 'react-server-dom-rspack/client.edge');
170
+ chain.resolve.fallback.set('async_hooks', false);
171
+ chain.resolve.fallback.set('node:async_hooks', false);
172
+ }
173
+ } : {}
174
+ }
175
+ };
176
+ }
52
177
  return {
53
178
  environments,
54
179
  builderConfig: tempBuilderConfig