dinou 6.1.1 ā 7.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +106 -0
- package/README.md +9352 -1081
- package/cli.js +314 -91
- package/dinou/adapters/bun.js +62 -0
- package/dinou/adapters/cloudflare.js +65 -0
- package/dinou/adapters/deno.js +48 -0
- package/dinou/adapters/netlify.js +85 -0
- package/dinou/adapters/node.mjs +31 -0
- package/dinou/bun/build.mjs +1077 -0
- package/dinou/cloudflare/build.mjs +1121 -0
- package/dinou/cloudflare/shims/child_process.js +14 -0
- package/dinou/cloudflare/shims/empty.js +2 -0
- package/dinou/cloudflare/shims/fs.js +99 -0
- package/dinou/cloudflare/shims/os.js +29 -0
- package/dinou/config.js +1 -0
- package/dinou/config.mjs +2 -0
- package/dinou/constants.js +29 -4
- package/dinou/core/babel-esm-loader.js +66 -37
- package/dinou/core/bailout-proxy.js +61 -0
- package/dinou/core/build-static-pages.js +322 -165
- package/dinou/core/cache-revalidate.js +471 -144
- package/dinou/core/cache-slot.js +387 -0
- package/dinou/core/client-redirect.jsx +12 -7
- package/dinou/core/client-webpack.jsx +457 -82
- package/dinou/core/client.jsx +452 -82
- package/dinou/core/config.js +11 -0
- package/dinou/core/dinou-paths.js +52 -0
- package/dinou/core/edge-ssr.js +122 -0
- package/dinou/core/export-static.mjs +64 -0
- package/dinou/core/generate-route-types.js +252 -0
- package/dinou/core/generate-static-page.js +55 -94
- package/dinou/core/generate-static-rsc.js +47 -15
- package/dinou/core/generate-static.js +212 -10
- package/dinou/core/generating-isg.js +5 -0
- package/dinou/core/get-asset-from-manifest.js +9 -3
- package/dinou/core/get-error-jsx.js +221 -41
- package/dinou/core/get-file-path-and-dynamic-params.js +9 -13
- package/dinou/core/get-jsx.js +175 -96
- package/dinou/core/handler.js +2303 -0
- package/dinou/core/http-adapter.js +115 -0
- package/dinou/core/import-module.js +83 -53
- package/dinou/core/layout-functions.js +183 -0
- package/dinou/core/link.jsx +18 -6
- package/dinou/core/load-dinou-config.js +60 -0
- package/dinou/core/manifest-provider.js +261 -0
- package/dinou/core/navigation-utils.js +4 -0
- package/dinou/core/navigation.js +50 -39
- package/dinou/core/parse-exports.js +252 -2
- package/dinou/core/ppr-context.js +105 -0
- package/dinou/core/ppr-runtime.js +263 -0
- package/dinou/core/redirect.jsx +20 -19
- package/dinou/core/render-jsx-to-client-jsx.js +91 -87
- package/dinou/core/request-context.js +47 -13
- package/dinou/core/resolve-module-ppr.js +34 -0
- package/dinou/core/revalidating.js +28 -9
- package/dinou/core/route-generator.js +107 -0
- package/dinou/core/rsc-renderer.js +90 -0
- package/dinou/core/run-ssg.js +19 -0
- package/dinou/core/scan-dependency-components.js +218 -0
- package/dinou/core/server-function-proxy-webpack.js +3 -0
- package/dinou/core/server-function-proxy.js +3 -0
- package/dinou/core/slot.js +302 -0
- package/dinou/core/status-manifest.js +41 -1
- package/dinou/core/storage-adapter.js +522 -0
- package/dinou/core/url-resolver.js +16 -16
- package/dinou/core/vfs.js +139 -68
- package/dinou/deno/build.mjs +1112 -0
- package/dinou/deno/seed-kv.js +115 -0
- package/dinou/esbuild/build.mjs +51 -1
- package/dinou/esbuild/dev.mjs +290 -224
- package/dinou/esbuild/helpers-esbuild/get-config-esbuild-prod.mjs +3 -2
- package/dinou/esbuild/helpers-esbuild/get-config-esbuild.mjs +104 -16
- package/dinou/esbuild/helpers-esbuild/get-esbuild-entries.mjs +31 -19
- package/dinou/esbuild/helpers-esbuild/strip-namespace.mjs +9 -0
- package/dinou/esbuild/helpers-esbuild/swc-disk-cache.mjs +225 -0
- package/dinou/esbuild/helpers-esbuild/update-manifest-for-module.mjs +7 -0
- package/dinou/esbuild/helpers-esbuild/write.mjs +111 -2
- package/dinou/esbuild/plugins-esbuild/assets-plugin.mjs +236 -161
- package/dinou/esbuild/plugins-esbuild/css-processor-plugin.mjs +101 -5
- package/dinou/esbuild/plugins-esbuild/react-client-manifest-plugin.mjs +63 -24
- package/dinou/esbuild/plugins-esbuild/server-functions-plugin.mjs +177 -56
- package/dinou/esbuild/plugins-esbuild/skip-missing-entry-points-plugin.mjs +3 -0
- package/dinou/esbuild/plugins-esbuild/stable-chunk-names-and-maps-plugin.mjs +182 -137
- package/dinou/esbuild/plugins-postcss/postcss-extract-plugin.js +38 -11
- package/dinou/esbuild/react-refresh/esm-hmr/client.mjs +55 -8
- package/dinou/esbuild/react-refresh/esm-hmr/server.js +1 -1
- package/dinou/esbuild/react-refresh/esm-hmr-plugin.mjs +238 -101
- package/dinou/esbuild/react-refresh/is-react-refresh-boundary.mjs +18 -4
- package/dinou/index.d.ts +315 -11
- package/dinou/index.js +12 -6
- package/dinou/index.mjs +9 -0
- package/dinou/node/build.mjs +195 -0
- package/dinou/node/bundle-dual-engine.mjs +1012 -0
- package/dinou/node/dev.mjs +2589 -0
- package/dinou/node/port-selector.mjs +164 -0
- package/dinou/node/terminal-status.mjs +345 -0
- package/dinou/package.json +16 -14
- package/dinou/rollup/react-refresh/esm-hmr/client.js +66 -10
- package/dinou/rollup/react-refresh/esm-hmr/server.js +1 -1
- package/dinou/rollup/react-refresh/is-react-refresh-boundary.js +24 -5
- package/dinou/rollup/react-refresh/react-refresh-runtime.js +13 -6
- package/dinou/rollup/react-refresh/react-refresh-wrap-modules.js +56 -11
- package/dinou/rollup/react-refresh/rollup-plugin-esm-hmr.js +176 -48
- package/dinou/rollup/rollup-plugins/dinou-asset-plugin.js +9 -5
- package/dinou/rollup/rollup-plugins/rollup-plugin-memory.js +66 -0
- package/dinou/rollup/rollup-plugins/rollup-plugin-react-client-manifest.js +468 -123
- package/dinou/rollup/rollup-plugins/rollup-plugin-server-functions.js +44 -12
- package/dinou/rollup/rollup-plugins/rollup-plugin-swc.js +100 -0
- package/dinou/rollup/rollup.config.js +155 -43
- package/dinou/server.d.ts +114 -12
- package/dinou/server.js +35 -10
- package/dinou/server.mjs +30 -9
- package/dinou/webpack/helpers/get-webpack-entries.js +14 -19
- package/dinou/webpack/loaders/server-functions-loader.js +22 -1
- package/dinou/webpack/loaders/swc-loader.js +76 -0
- package/dinou/webpack/plugins/manifest-generator-plugin.js +1 -0
- package/dinou/webpack/plugins/server-functions-plugin.js +75 -19
- package/dinou/webpack/plugins/webpack-memory-plugin.js +66 -0
- package/dinou/webpack/webpack.config.js +227 -29
- package/eject.js +113 -34
- package/package.json +18 -16
- package/dinou/core/asset-require-hook.js +0 -58
- package/dinou/core/client-error-webpack.jsx +0 -432
- package/dinou/core/client-error.jsx +0 -432
- package/dinou/core/concurrency-manager.js +0 -48
- package/dinou/core/context-proxy.js +0 -68
- package/dinou/core/generate-static-pages.js +0 -130
- package/dinou/core/generate-static-rscs.js +0 -151
- package/dinou/core/get-ssg-metadata.js +0 -31
- package/dinou/core/register-loader.mjs +0 -11
- package/dinou/core/register-paths.js +0 -27
- package/dinou/core/render-app-to-html.js +0 -430
- package/dinou/core/render-html.js +0 -407
- package/dinou/core/server.js +0 -1542
- package/dinou/esbuild/plugins-esbuild/write-metafile-plugin.mjs +0 -16
|
@@ -0,0 +1,1112 @@
|
|
|
1
|
+
// dinou/deno/build.mjs
|
|
2
|
+
// Dual-Bundle Build script for packaging Dinou v7 for Deno Deploy & Edge.
|
|
3
|
+
// Pass A: RSC Engine (conditions: ["deno", "worker", "react-server"])
|
|
4
|
+
// Pass B: Native Streaming HTML SSR Engine (conditions: ["deno", "worker", "browser"])
|
|
5
|
+
// Pass C: Main Deno Orchestrator (main.js)
|
|
6
|
+
|
|
7
|
+
import fs from "node:fs";
|
|
8
|
+
import path from "node:path";
|
|
9
|
+
import esbuild from "esbuild";
|
|
10
|
+
import { createRequire } from "node:module";
|
|
11
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
12
|
+
|
|
13
|
+
const require = createRequire(import.meta.url);
|
|
14
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
15
|
+
const { generateRouteModulesCode, generateRouteTypes } = require("../core/route-generator.js");
|
|
16
|
+
const parseExports = require("../core/parse-exports.js");
|
|
17
|
+
const { useClientRegex, useServerRegex } = require("../constants.js");
|
|
18
|
+
const {
|
|
19
|
+
isSupportedClientModule,
|
|
20
|
+
scanProjectDependenciesForClientComponents,
|
|
21
|
+
} = require("../core/scan-dependency-components.js");
|
|
22
|
+
|
|
23
|
+
const projectRoot = process.cwd();
|
|
24
|
+
const denoDir = path.resolve(projectRoot, ".dinou/deno");
|
|
25
|
+
fs.mkdirSync(denoDir, { recursive: true });
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
generateRouteTypes(projectRoot);
|
|
29
|
+
} catch (e) {}
|
|
30
|
+
|
|
31
|
+
// Locate dinou root: ejected in project or in package directory
|
|
32
|
+
const dinouDir = fs.existsSync(path.resolve(projectRoot, "dinou"))
|
|
33
|
+
? path.resolve(projectRoot, "dinou")
|
|
34
|
+
: path.resolve(__dirname, "..");
|
|
35
|
+
const dinouDirSlash = dinouDir.replace(/\\/g, "/");
|
|
36
|
+
|
|
37
|
+
const candidateDinouRoots = [
|
|
38
|
+
dinouDir,
|
|
39
|
+
path.resolve(projectRoot, "dinou"),
|
|
40
|
+
path.resolve(projectRoot, "node_modules/dinou/dinou"),
|
|
41
|
+
path.resolve(projectRoot, "node_modules/dinou"),
|
|
42
|
+
path.resolve(__dirname, ".."),
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
const candidateLinkPaths = new Set();
|
|
46
|
+
const candidateRedirectPaths = new Set();
|
|
47
|
+
const candidateSlotPaths = new Set();
|
|
48
|
+
|
|
49
|
+
for (const r of candidateDinouRoots) {
|
|
50
|
+
candidateLinkPaths.add(path.resolve(r, "core/link.jsx"));
|
|
51
|
+
candidateRedirectPaths.add(path.resolve(r, "core/client-redirect.jsx"));
|
|
52
|
+
candidateSlotPaths.add(path.resolve(r, "core/slot.js"));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function copyRecursive(src, dest) {
|
|
56
|
+
if (!fs.existsSync(src)) return 0;
|
|
57
|
+
let count = 0;
|
|
58
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
59
|
+
for (const entry of entries) {
|
|
60
|
+
const srcPath = path.join(src, entry.name);
|
|
61
|
+
const destPath = path.join(dest, entry.name);
|
|
62
|
+
if (entry.isDirectory()) {
|
|
63
|
+
fs.mkdirSync(destPath, { recursive: true });
|
|
64
|
+
count += copyRecursive(srcPath, destPath);
|
|
65
|
+
} else {
|
|
66
|
+
fs.mkdirSync(path.dirname(destPath), { recursive: true });
|
|
67
|
+
fs.copyFileSync(srcPath, destPath);
|
|
68
|
+
count++;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return count;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const isWebpackBuild = process.env.DINOU_BUILD_TOOL === "webpack";
|
|
75
|
+
const bundlerName = isWebpackBuild ? "webpack" : (process.env.DINOU_BUILD_TOOL || "esbuild");
|
|
76
|
+
|
|
77
|
+
const dist2Dir = path.resolve(projectRoot, ".dinou/dist2");
|
|
78
|
+
const dist3Dir = path.resolve(projectRoot, ".dinou/dist3");
|
|
79
|
+
console.log(`\nš¦ Dinou v7 (Deno ⢠${bundlerName})`);
|
|
80
|
+
if (fs.existsSync(dist2Dir)) {
|
|
81
|
+
const copiedCount = copyRecursive(dist2Dir, dist3Dir);
|
|
82
|
+
console.log(` š Synchronized ${copiedCount} pre-rendered static route(s) to .dinou/dist3`);
|
|
83
|
+
}
|
|
84
|
+
console.log(" ā” Generating route modules & manifests...");
|
|
85
|
+
const routeModulesCode = generateRouteModulesCode(projectRoot, "../..");
|
|
86
|
+
const routeModulesPath = path.join(denoDir, "route-modules.js");
|
|
87
|
+
fs.writeFileSync(routeModulesPath, routeModulesCode, "utf8");
|
|
88
|
+
|
|
89
|
+
function findManifest(filename, fallbackFolder) {
|
|
90
|
+
const candidates = isWebpackBuild
|
|
91
|
+
? [
|
|
92
|
+
path.resolve(projectRoot, ".dinou/dist3", filename),
|
|
93
|
+
path.resolve(projectRoot, ".dinou/public", filename),
|
|
94
|
+
path.resolve(projectRoot, ".dinou", fallbackFolder, filename),
|
|
95
|
+
]
|
|
96
|
+
: [
|
|
97
|
+
path.resolve(projectRoot, ".dinou", fallbackFolder, filename),
|
|
98
|
+
path.resolve(projectRoot, ".dinou/dist3", filename),
|
|
99
|
+
path.resolve(projectRoot, ".dinou/public", filename),
|
|
100
|
+
];
|
|
101
|
+
for (const c of candidates) {
|
|
102
|
+
if (fs.existsSync(c)) return c;
|
|
103
|
+
}
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const clientManifestPath = findManifest("react-client-manifest.json", "react_client_manifest");
|
|
108
|
+
const sfManifestPath = findManifest("server-functions-manifest.json", "server_functions_manifest");
|
|
109
|
+
|
|
110
|
+
let parsedClientManifest = {};
|
|
111
|
+
if (clientManifestPath && fs.existsSync(clientManifestPath)) {
|
|
112
|
+
try {
|
|
113
|
+
parsedClientManifest = JSON.parse(fs.readFileSync(clientManifestPath, "utf8"));
|
|
114
|
+
} catch (e) {}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
let parsedServerFunctionsManifest = {};
|
|
118
|
+
if (sfManifestPath && fs.existsSync(sfManifestPath)) {
|
|
119
|
+
try {
|
|
120
|
+
parsedServerFunctionsManifest = JSON.parse(fs.readFileSync(sfManifestPath, "utf8"));
|
|
121
|
+
} catch (e) {}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// ====================================================================
|
|
125
|
+
// Discovery of Client Components for SSR Engine & RSC Manifest
|
|
126
|
+
// ====================================================================
|
|
127
|
+
if (process.env.DINOU_DEBUG) {
|
|
128
|
+
console.log("š [Dinou Deno] Discovering client components for SSR Engine...");
|
|
129
|
+
}
|
|
130
|
+
const srcDir = path.resolve(projectRoot, "src");
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
function findClientComponents() {
|
|
134
|
+
const clientFiles = new Set();
|
|
135
|
+
function walk(dir) {
|
|
136
|
+
if (!fs.existsSync(dir)) return;
|
|
137
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
138
|
+
for (const entry of entries) {
|
|
139
|
+
const full = path.join(dir, entry.name);
|
|
140
|
+
if (entry.isDirectory()) {
|
|
141
|
+
walk(full);
|
|
142
|
+
} else if (/\.[jt]sx?$/.test(entry.name)) {
|
|
143
|
+
try {
|
|
144
|
+
const content = fs.readFileSync(full, "utf8");
|
|
145
|
+
if (useClientRegex.test(content.trim()) && isSupportedClientModule(full, content)) {
|
|
146
|
+
clientFiles.add(path.resolve(full));
|
|
147
|
+
}
|
|
148
|
+
} catch (e) {}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
walk(srcDir);
|
|
153
|
+
|
|
154
|
+
const coreCandidates = [
|
|
155
|
+
...Array.from(candidateLinkPaths),
|
|
156
|
+
...Array.from(candidateRedirectPaths),
|
|
157
|
+
];
|
|
158
|
+
for (const f of coreCandidates) {
|
|
159
|
+
if (fs.existsSync(f)) {
|
|
160
|
+
clientFiles.add(path.resolve(f));
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
scanProjectDependenciesForClientComponents(projectRoot, clientFiles, useClientRegex);
|
|
165
|
+
|
|
166
|
+
for (const k of Object.keys(parsedClientManifest)) {
|
|
167
|
+
const fileUrl = k.split("#")[0];
|
|
168
|
+
if (fileUrl.startsWith("file:///")) {
|
|
169
|
+
try {
|
|
170
|
+
const filePath = fileURLToPath(fileUrl);
|
|
171
|
+
const baseName = path.basename(filePath);
|
|
172
|
+
if (baseName === "client.jsx" || baseName === "client-webpack.jsx") {
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
if (fs.existsSync(filePath) && isSupportedClientModule(filePath)) {
|
|
176
|
+
clientFiles.add(path.resolve(filePath));
|
|
177
|
+
}
|
|
178
|
+
} catch (e) {}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return Array.from(clientFiles);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const clientComponents = findClientComponents();
|
|
186
|
+
if (process.env.DINOU_DEBUG) {
|
|
187
|
+
console.log(` Found ${clientComponents.length} client component(s) for Native SSR.`);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
let manifestInlines = "";
|
|
191
|
+
const normalizedManifest = { ...parsedClientManifest };
|
|
192
|
+
for (const [k, v] of Object.entries(parsedClientManifest)) {
|
|
193
|
+
if (k.startsWith("file:///c:/")) {
|
|
194
|
+
normalizedManifest["file:///C:/" + k.slice(11)] = v;
|
|
195
|
+
} else if (k.startsWith("file:///C:/")) {
|
|
196
|
+
normalizedManifest["file:///c:/" + k.slice(11)] = v;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function generateAllUrlVariants(absPath) {
|
|
201
|
+
const norm = absPath.replace(/\\/g, "/");
|
|
202
|
+
const fileUrl = pathToFileURL(absPath).href;
|
|
203
|
+
const urls = new Set([fileUrl]);
|
|
204
|
+
urls.add(fileUrl.replace(/file:\/\/\/([a-zA-Z]):/, (m, d) => 'file:///' + d.toLowerCase() + ':'));
|
|
205
|
+
urls.add(fileUrl.replace(/file:\/\/\/([a-zA-Z]):/, (m, d) => 'file:///' + d.toUpperCase() + ':'));
|
|
206
|
+
urls.add("file:///" + norm);
|
|
207
|
+
urls.add("file://" + norm);
|
|
208
|
+
return Array.from(urls);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
let linkChunkId = null;
|
|
213
|
+
let redirectChunkId = null;
|
|
214
|
+
let slotChunkId = null;
|
|
215
|
+
let linkEntry = null;
|
|
216
|
+
let redirectEntry = null;
|
|
217
|
+
let slotEntry = null;
|
|
218
|
+
|
|
219
|
+
for (const [k, v] of Object.entries(parsedClientManifest)) {
|
|
220
|
+
if (k.includes("/core/link.jsx") || k.includes("dinouLink")) {
|
|
221
|
+
if (v && v.id) {
|
|
222
|
+
linkChunkId = v.id;
|
|
223
|
+
linkEntry = v;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (k.includes("/core/client-redirect.jsx") || k.includes("dinouClientRedirect")) {
|
|
227
|
+
if (v && v.id) {
|
|
228
|
+
redirectChunkId = v.id;
|
|
229
|
+
redirectEntry = v;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
if (k.includes("/core/slot.") || k.includes("dinouSlot")) {
|
|
233
|
+
if (v && v.id) {
|
|
234
|
+
slotChunkId = v.id;
|
|
235
|
+
slotEntry = v;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (linkChunkId) {
|
|
241
|
+
const linkChunks = isWebpackBuild
|
|
242
|
+
? (linkEntry?.chunks || [linkChunkId])
|
|
243
|
+
: "Link";
|
|
244
|
+
const linkDefaultChunks = isWebpackBuild
|
|
245
|
+
? (linkEntry?.chunks || [linkChunkId])
|
|
246
|
+
: "default";
|
|
247
|
+
|
|
248
|
+
for (const lp of candidateLinkPaths) {
|
|
249
|
+
for (const url of generateAllUrlVariants(lp)) {
|
|
250
|
+
normalizedManifest[`${url}#Link`] = { id: linkChunkId, chunks: linkChunks, name: "Link" };
|
|
251
|
+
normalizedManifest[`${url}#default`] = { id: linkChunkId, chunks: linkDefaultChunks, name: "default" };
|
|
252
|
+
normalizedManifest[url] = { id: linkChunkId, chunks: linkDefaultChunks, name: "default" };
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (redirectChunkId) {
|
|
258
|
+
const redirectChunks = isWebpackBuild
|
|
259
|
+
? (redirectEntry?.chunks || [redirectChunkId])
|
|
260
|
+
: "ClientRedirect";
|
|
261
|
+
const redirectDefaultChunks = isWebpackBuild
|
|
262
|
+
? (redirectEntry?.chunks || [redirectChunkId])
|
|
263
|
+
: "default";
|
|
264
|
+
|
|
265
|
+
for (const rp of candidateRedirectPaths) {
|
|
266
|
+
for (const url of generateAllUrlVariants(rp)) {
|
|
267
|
+
normalizedManifest[`${url}#ClientRedirect`] = { id: redirectChunkId, chunks: redirectChunks, name: "ClientRedirect" };
|
|
268
|
+
normalizedManifest[`${url}#default`] = { id: redirectChunkId, chunks: redirectDefaultChunks, name: "default" };
|
|
269
|
+
normalizedManifest[url] = { id: redirectChunkId, chunks: redirectDefaultChunks, name: "default" };
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (slotChunkId) {
|
|
275
|
+
const slotChunks = isWebpackBuild
|
|
276
|
+
? (slotEntry?.chunks || [slotChunkId])
|
|
277
|
+
: "DinouPageSlot";
|
|
278
|
+
const slotBoundaryChunks = isWebpackBuild
|
|
279
|
+
? (slotEntry?.chunks || [slotChunkId])
|
|
280
|
+
: "DinouCacheSlotBoundary";
|
|
281
|
+
const slotDefaultChunks = isWebpackBuild
|
|
282
|
+
? (slotEntry?.chunks || [slotChunkId])
|
|
283
|
+
: "default";
|
|
284
|
+
|
|
285
|
+
for (const sp of candidateSlotPaths) {
|
|
286
|
+
for (const url of generateAllUrlVariants(sp)) {
|
|
287
|
+
normalizedManifest[`${url}#DinouPageSlot`] = { id: slotChunkId, chunks: slotChunks, name: "DinouPageSlot" };
|
|
288
|
+
normalizedManifest[`${url}#DinouCacheSlotBoundary`] = { id: slotChunkId, chunks: slotBoundaryChunks, name: "DinouCacheSlotBoundary" };
|
|
289
|
+
normalizedManifest[`${url}#default`] = { id: slotChunkId, chunks: slotDefaultChunks, name: "default" };
|
|
290
|
+
normalizedManifest[url] = { id: slotChunkId, chunks: slotDefaultChunks, name: "default" };
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
for (const comp of clientComponents) {
|
|
296
|
+
const fileUrl = pathToFileURL(comp).href;
|
|
297
|
+
const fileUrlLower = fileUrl.replace(/file:\/\/\/([a-zA-Z]):/, (m, d) => 'file:///' + d.toLowerCase() + ':');
|
|
298
|
+
const fileUrlUpper = fileUrl.replace(/file:\/\/\/([a-zA-Z]):/, (m, d) => 'file:///' + d.toUpperCase() + ':');
|
|
299
|
+
const compResolved = path.resolve(comp);
|
|
300
|
+
const isCoreLink = candidateLinkPaths.has(compResolved);
|
|
301
|
+
const isCoreRedirect = candidateRedirectPaths.has(compResolved);
|
|
302
|
+
const isCoreSlot = candidateSlotPaths.has(compResolved);
|
|
303
|
+
|
|
304
|
+
if (!normalizedManifest[fileUrlLower]) {
|
|
305
|
+
if (isCoreLink && linkChunkId) {
|
|
306
|
+
normalizedManifest[fileUrlLower] = {
|
|
307
|
+
id: linkChunkId,
|
|
308
|
+
chunks: isWebpackBuild ? (linkEntry?.chunks || [linkChunkId]) : "default",
|
|
309
|
+
name: "default",
|
|
310
|
+
};
|
|
311
|
+
} else if (isCoreRedirect && redirectChunkId) {
|
|
312
|
+
normalizedManifest[fileUrlLower] = {
|
|
313
|
+
id: redirectChunkId,
|
|
314
|
+
chunks: isWebpackBuild ? (redirectEntry?.chunks || [redirectChunkId]) : "default",
|
|
315
|
+
name: "default",
|
|
316
|
+
};
|
|
317
|
+
} else if (isCoreSlot && slotChunkId) {
|
|
318
|
+
normalizedManifest[fileUrlLower] = {
|
|
319
|
+
id: slotChunkId,
|
|
320
|
+
chunks: isWebpackBuild ? (slotEntry?.chunks || [slotChunkId]) : "default",
|
|
321
|
+
name: "default",
|
|
322
|
+
};
|
|
323
|
+
} else {
|
|
324
|
+
normalizedManifest[fileUrlLower] = { id: fileUrlLower, chunks: [], name: "*" };
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
if (!normalizedManifest[fileUrlUpper]) {
|
|
328
|
+
if (isCoreLink && linkChunkId) {
|
|
329
|
+
normalizedManifest[fileUrlUpper] = {
|
|
330
|
+
id: linkChunkId,
|
|
331
|
+
chunks: isWebpackBuild ? (linkEntry?.chunks || [linkChunkId]) : "default",
|
|
332
|
+
name: "default",
|
|
333
|
+
};
|
|
334
|
+
} else if (isCoreRedirect && redirectChunkId) {
|
|
335
|
+
normalizedManifest[fileUrlUpper] = {
|
|
336
|
+
id: redirectChunkId,
|
|
337
|
+
chunks: isWebpackBuild ? (redirectEntry?.chunks || [redirectChunkId]) : "default",
|
|
338
|
+
name: "default",
|
|
339
|
+
};
|
|
340
|
+
} else if (isCoreSlot && slotChunkId) {
|
|
341
|
+
normalizedManifest[fileUrlUpper] = {
|
|
342
|
+
id: slotChunkId,
|
|
343
|
+
chunks: isWebpackBuild ? (slotEntry?.chunks || [slotChunkId]) : "default",
|
|
344
|
+
name: "default",
|
|
345
|
+
};
|
|
346
|
+
} else {
|
|
347
|
+
normalizedManifest[fileUrlUpper] = { id: fileUrlLower, chunks: [], name: "*" };
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
manifestInlines += `\nglobalThis.__DINOU_CLIENT_MANIFEST__ = ${JSON.stringify(normalizedManifest)};\n`;
|
|
353
|
+
|
|
354
|
+
if (sfManifestPath && fs.existsSync(sfManifestPath)) {
|
|
355
|
+
const content = fs.readFileSync(sfManifestPath, "utf8");
|
|
356
|
+
manifestInlines += `\nglobalThis.__DINOU_SERVER_FUNCTIONS_MANIFEST__ = ${content};\n`;
|
|
357
|
+
} else {
|
|
358
|
+
manifestInlines += `\nglobalThis.__DINOU_SERVER_FUNCTIONS_MANIFEST__ = {};\n`;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
const assetManifestPath = findManifest("manifest.json", "dist3");
|
|
362
|
+
if (assetManifestPath && fs.existsSync(assetManifestPath)) {
|
|
363
|
+
const content = fs.readFileSync(assetManifestPath, "utf8");
|
|
364
|
+
manifestInlines += `\nglobalThis.__DINOU_ASSET_MANIFEST__ = ${content};\n`;
|
|
365
|
+
} else {
|
|
366
|
+
manifestInlines += `\nglobalThis.__DINOU_ASSET_MANIFEST__ = {};\n`;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
let importMapHtml = "";
|
|
370
|
+
if (!isWebpackBuild && Object.keys(parsedClientManifest).length > 0) {
|
|
371
|
+
const imports = {};
|
|
372
|
+
const moduleBasePath = pathToFileURL(projectRoot).href + "/";
|
|
373
|
+
|
|
374
|
+
for (const [key, val] of Object.entries(parsedClientManifest)) {
|
|
375
|
+
let specifier = key;
|
|
376
|
+
if (specifier.startsWith(moduleBasePath)) {
|
|
377
|
+
specifier = specifier.slice(moduleBasePath.length);
|
|
378
|
+
}
|
|
379
|
+
const hashIdx = specifier.indexOf("#");
|
|
380
|
+
if (hashIdx !== -1) {
|
|
381
|
+
specifier = specifier.slice(0, hashIdx);
|
|
382
|
+
}
|
|
383
|
+
imports[specifier] = val.id;
|
|
384
|
+
|
|
385
|
+
const srcIdx = key.indexOf("/src/");
|
|
386
|
+
if (srcIdx !== -1) {
|
|
387
|
+
const srcRel = "src/" + key.slice(srcIdx + 5).split("#")[0];
|
|
388
|
+
imports[srcRel] = val.id;
|
|
389
|
+
imports["/" + srcRel] = val.id;
|
|
390
|
+
imports["./" + srcRel] = val.id;
|
|
391
|
+
}
|
|
392
|
+
const dinouIdx = key.lastIndexOf("/dinou/");
|
|
393
|
+
if (dinouIdx !== -1) {
|
|
394
|
+
const dinouRel = "dinou/" + key.slice(dinouIdx + 7).split("#")[0];
|
|
395
|
+
imports[dinouRel] = val.id;
|
|
396
|
+
imports["/" + dinouRel] = val.id;
|
|
397
|
+
imports["./" + dinouRel] = val.id;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
if (linkChunkId) {
|
|
402
|
+
imports["dinou/core/link.jsx"] = linkChunkId;
|
|
403
|
+
imports["dinou/core/link"] = linkChunkId;
|
|
404
|
+
imports["/dinou/core/link.jsx"] = linkChunkId;
|
|
405
|
+
imports["./dinou/core/link.jsx"] = linkChunkId;
|
|
406
|
+
for (const lp of candidateLinkPaths) {
|
|
407
|
+
for (const u of generateAllUrlVariants(lp)) {
|
|
408
|
+
imports[u] = linkChunkId;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
if (redirectChunkId) {
|
|
413
|
+
imports["dinou/core/client-redirect.jsx"] = redirectChunkId;
|
|
414
|
+
imports["dinou/core/client-redirect"] = redirectChunkId;
|
|
415
|
+
imports["/dinou/core/client-redirect.jsx"] = redirectChunkId;
|
|
416
|
+
imports["./dinou/core/client-redirect.jsx"] = redirectChunkId;
|
|
417
|
+
for (const rp of candidateRedirectPaths) {
|
|
418
|
+
for (const u of generateAllUrlVariants(rp)) {
|
|
419
|
+
imports[u] = redirectChunkId;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
importMapHtml = `<script type="importmap">{"imports":${JSON.stringify(imports)}}</script>`;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
manifestInlines += `\nglobalThis.__DINOU_IMPORT_MAP_HTML__ = ${JSON.stringify(importMapHtml)};\n`;
|
|
428
|
+
|
|
429
|
+
const discoveredLayouts = [];
|
|
430
|
+
function findLayoutRoutes(dir, rel = "") {
|
|
431
|
+
if (!fs.existsSync(dir)) return;
|
|
432
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
433
|
+
for (const entry of entries) {
|
|
434
|
+
if (entry.isDirectory()) {
|
|
435
|
+
findLayoutRoutes(path.join(dir, entry.name), rel ? `${rel}/${entry.name}` : entry.name);
|
|
436
|
+
} else if (/^layout\.[jt]sx?$/.test(entry.name)) {
|
|
437
|
+
discoveredLayouts.push(rel);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
findLayoutRoutes(srcDir);
|
|
442
|
+
manifestInlines += `\nglobalThis.__DINOU_LAYOUTS__ = ${JSON.stringify(discoveredLayouts)};\n`;
|
|
443
|
+
|
|
444
|
+
if (process.env.DINOU_DEBUG) {
|
|
445
|
+
|
|
446
|
+
console.log("ā” [Dinou Deno] Building in-memory VFS for Edge routing...");
|
|
447
|
+
}
|
|
448
|
+
const vfsSnapshot = {};
|
|
449
|
+
function walkVfs(dir) {
|
|
450
|
+
if (!fs.existsSync(dir)) return;
|
|
451
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
452
|
+
const children = [];
|
|
453
|
+
for (const entry of entries) {
|
|
454
|
+
const isDir = entry.isDirectory();
|
|
455
|
+
children.push({ name: entry.name, isDirectory: isDir });
|
|
456
|
+
const fullPath = path.join(dir, entry.name);
|
|
457
|
+
const relFromSrc = path.relative(srcDir, fullPath).replace(/\\/g, "/");
|
|
458
|
+
const edgePath = "/src/" + relFromSrc;
|
|
459
|
+
const slashPath = fullPath.replace(/\\/g, "/");
|
|
460
|
+
if (isDir) {
|
|
461
|
+
walkVfs(fullPath);
|
|
462
|
+
} else {
|
|
463
|
+
vfsSnapshot[edgePath] = { type: "file" };
|
|
464
|
+
vfsSnapshot[slashPath] = { type: "file" };
|
|
465
|
+
if (slashPath.length > 2 && slashPath[1] === ":") {
|
|
466
|
+
vfsSnapshot[slashPath.slice(2)] = { type: "file" };
|
|
467
|
+
}
|
|
468
|
+
vfsSnapshot["src/" + relFromSrc] = { type: "file" };
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
const dirRel = path.relative(srcDir, dir).replace(/\\/g, "/");
|
|
472
|
+
const edgeDir = dirRel ? "/src/" + dirRel : "/src";
|
|
473
|
+
const dirSlash = dir.replace(/\\/g, "/");
|
|
474
|
+
vfsSnapshot[edgeDir] = { type: "directory", children };
|
|
475
|
+
vfsSnapshot[dirSlash] = { type: "directory", children };
|
|
476
|
+
if (dirSlash.length > 2 && dirSlash[1] === ":") {
|
|
477
|
+
vfsSnapshot[dirSlash.slice(2)] = { type: "directory", children };
|
|
478
|
+
}
|
|
479
|
+
vfsSnapshot[dirRel ? "src/" + dirRel : "src"] = { type: "directory", children };
|
|
480
|
+
}
|
|
481
|
+
walkVfs(srcDir);
|
|
482
|
+
|
|
483
|
+
const envSetupContent = `// Auto-generated environment setup
|
|
484
|
+
if (typeof globalThis.__webpack_require__ === 'undefined') {
|
|
485
|
+
globalThis.__webpack_require__ = function(id) {
|
|
486
|
+
if (globalThis.__webpack_modules__ && globalThis.__webpack_modules__[id]) {
|
|
487
|
+
return globalThis.__webpack_modules__[id];
|
|
488
|
+
}
|
|
489
|
+
return {};
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
if (typeof globalThis.__webpack_require__.u === 'undefined') {
|
|
493
|
+
globalThis.__webpack_require__.u = function(chunkId) { return '' + chunkId + '.js'; };
|
|
494
|
+
}
|
|
495
|
+
if (typeof globalThis.__webpack_chunk_load__ === 'undefined') {
|
|
496
|
+
globalThis.__webpack_chunk_load__ = () => Promise.resolve();
|
|
497
|
+
}
|
|
498
|
+
${manifestInlines}
|
|
499
|
+
globalThis.__DINOU_VFS__ = ${JSON.stringify(vfsSnapshot)};
|
|
500
|
+
`;
|
|
501
|
+
const envSetupPath = path.join(denoDir, "env-setup.js");
|
|
502
|
+
fs.writeFileSync(envSetupPath, envSetupContent, "utf8");
|
|
503
|
+
|
|
504
|
+
// Generate ssr-client-manifest.js
|
|
505
|
+
let ssrManifestCode = `// Auto-generated client modules registry for Native Edge SSR\n`;
|
|
506
|
+
clientComponents.forEach((compPath, index) => {
|
|
507
|
+
const normPath = compPath.replace(/\\/g, "/");
|
|
508
|
+
ssrManifestCode += `import * as mod_${index} from ${JSON.stringify(normPath)};\n`;
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
const serverFunctionFiles = Object.keys(parsedServerFunctionsManifest);
|
|
512
|
+
serverFunctionFiles.forEach((relPath, index) => {
|
|
513
|
+
const absPath = path.resolve(projectRoot, relPath).replace(/\\/g, "/");
|
|
514
|
+
ssrManifestCode += `import * as sf_${index} from ${JSON.stringify(absPath)};\n`;
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
ssrManifestCode += `\nexport const clientModules = {\n`;
|
|
518
|
+
const emittedClientModules = new Set();
|
|
519
|
+
function addClientModule(key, valueExpr) {
|
|
520
|
+
if (!emittedClientModules.has(key)) {
|
|
521
|
+
emittedClientModules.add(key);
|
|
522
|
+
ssrManifestCode += ` ${JSON.stringify(key)}: ${valueExpr},\n`;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
clientComponents.forEach((compPath, index) => {
|
|
527
|
+
const fileUrl = pathToFileURL(compPath).href;
|
|
528
|
+
const altFileUrl = fileUrl.replace(/file:\/\/\/([a-zA-Z]):/, (m, d) => 'file:///' + (d === d.toLowerCase() ? d.toUpperCase() : d.toLowerCase()) + ':');
|
|
529
|
+
addClientModule(fileUrl, `mod_${index}`);
|
|
530
|
+
if (altFileUrl !== fileUrl) {
|
|
531
|
+
addClientModule(altFileUrl, `mod_${index}`);
|
|
532
|
+
}
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
for (const [k, v] of Object.entries(parsedClientManifest)) {
|
|
536
|
+
const fileUrl = k.split("#")[0];
|
|
537
|
+
if (fileUrl.startsWith("file:///")) {
|
|
538
|
+
try {
|
|
539
|
+
const filePath = fileURLToPath(fileUrl);
|
|
540
|
+
if (fs.existsSync(filePath) && !isSupportedClientModule(filePath)) continue;
|
|
541
|
+
} catch (e) {}
|
|
542
|
+
}
|
|
543
|
+
const compIndex = clientComponents.findIndex(
|
|
544
|
+
(c) => pathToFileURL(c).href === fileUrl || pathToFileURL(c).href.toLowerCase() === fileUrl.toLowerCase()
|
|
545
|
+
);
|
|
546
|
+
if (compIndex !== -1) {
|
|
547
|
+
if (v && v.id) addClientModule(v.id, `mod_${compIndex}`);
|
|
548
|
+
addClientModule(fileUrl, `mod_${compIndex}`);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
if (linkChunkId) {
|
|
553
|
+
const linkCompIndex = clientComponents.findIndex((c) => candidateLinkPaths.has(path.resolve(c)));
|
|
554
|
+
if (linkCompIndex !== -1) {
|
|
555
|
+
addClientModule(linkChunkId, `mod_${linkCompIndex}`);
|
|
556
|
+
for (const lp of candidateLinkPaths) {
|
|
557
|
+
for (const u of generateAllUrlVariants(lp)) {
|
|
558
|
+
addClientModule(u, `mod_${linkCompIndex}`);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
if (redirectChunkId) {
|
|
564
|
+
const redirectCompIndex = clientComponents.findIndex((c) => candidateRedirectPaths.has(path.resolve(c)));
|
|
565
|
+
if (redirectCompIndex !== -1) {
|
|
566
|
+
addClientModule(redirectChunkId, `mod_${redirectCompIndex}`);
|
|
567
|
+
for (const rp of candidateRedirectPaths) {
|
|
568
|
+
for (const u of generateAllUrlVariants(rp)) {
|
|
569
|
+
addClientModule(u, `mod_${redirectCompIndex}`);
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
serverFunctionFiles.forEach((relPath, index) => {
|
|
576
|
+
const normRel = relPath.replace(/\\/g, "/");
|
|
577
|
+
const relFileUrl = "file:///" + normRel;
|
|
578
|
+
const absPath = path.resolve(projectRoot, relPath);
|
|
579
|
+
const fullFileUrl = pathToFileURL(absPath).href;
|
|
580
|
+
const altFullFileUrl = fullFileUrl.replace(/file:\/\/\/([a-zA-Z]):/, (m, d) => 'file:///' + (d === d.toLowerCase() ? d.toUpperCase() : d.toLowerCase()) + ':');
|
|
581
|
+
|
|
582
|
+
addClientModule(relFileUrl, `sf_${index}`);
|
|
583
|
+
addClientModule(fullFileUrl, `sf_${index}`);
|
|
584
|
+
if (altFullFileUrl !== fullFileUrl) {
|
|
585
|
+
addClientModule(altFullFileUrl, `sf_${index}`);
|
|
586
|
+
}
|
|
587
|
+
});
|
|
588
|
+
ssrManifestCode += `};\n\n`;
|
|
589
|
+
|
|
590
|
+
ssrManifestCode += `export const ssrConsumerManifest = {\n moduleMap: {\n`;
|
|
591
|
+
const emittedModuleMap = new Set();
|
|
592
|
+
function addModuleMap(key, valueObjStr) {
|
|
593
|
+
if (!emittedModuleMap.has(key)) {
|
|
594
|
+
emittedModuleMap.add(key);
|
|
595
|
+
ssrManifestCode += ` ${JSON.stringify(key)}: ${valueObjStr},\n`;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
clientComponents.forEach((compPath) => {
|
|
600
|
+
const fileUrl = pathToFileURL(compPath).href;
|
|
601
|
+
const altFileUrl = fileUrl.replace(/file:\/\/\/([a-zA-Z]):/, (m, d) => 'file:///' + (d === d.toLowerCase() ? d.toUpperCase() : d.toLowerCase()) + ':');
|
|
602
|
+
addModuleMap(fileUrl, `{ "*": { id: ${JSON.stringify(fileUrl)}, chunks: [], name: "*" } }`);
|
|
603
|
+
if (altFileUrl !== fileUrl) {
|
|
604
|
+
addModuleMap(altFileUrl, `{ "*": { id: ${JSON.stringify(fileUrl)}, chunks: [], name: "*" } }`);
|
|
605
|
+
}
|
|
606
|
+
});
|
|
607
|
+
|
|
608
|
+
for (const [k, v] of Object.entries(parsedClientManifest)) {
|
|
609
|
+
const fileUrl = k.split("#")[0];
|
|
610
|
+
if (fileUrl.startsWith("file:///")) {
|
|
611
|
+
try {
|
|
612
|
+
const filePath = fileURLToPath(fileUrl);
|
|
613
|
+
if (fs.existsSync(filePath) && !isSupportedClientModule(filePath)) continue;
|
|
614
|
+
} catch (e) {}
|
|
615
|
+
}
|
|
616
|
+
if (v && v.id) {
|
|
617
|
+
addModuleMap(v.id, `{ "*": { id: ${JSON.stringify(fileUrl)}, chunks: [], name: "*" } }`);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
if (linkChunkId) {
|
|
622
|
+
const linkCompIndex = clientComponents.findIndex((c) => candidateLinkPaths.has(path.resolve(c)));
|
|
623
|
+
if (linkCompIndex !== -1) {
|
|
624
|
+
const fileUrl = pathToFileURL(clientComponents[linkCompIndex]).href;
|
|
625
|
+
addModuleMap(linkChunkId, `{ "*": { id: ${JSON.stringify(fileUrl)}, chunks: [], name: "*" } }`);
|
|
626
|
+
for (const lp of candidateLinkPaths) {
|
|
627
|
+
for (const u of generateAllUrlVariants(lp)) {
|
|
628
|
+
addModuleMap(u, `{ "*": { id: ${JSON.stringify(fileUrl)}, chunks: [], name: "*" } }`);
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
if (redirectChunkId) {
|
|
634
|
+
const redirectCompIndex = clientComponents.findIndex((c) => candidateRedirectPaths.has(path.resolve(c)));
|
|
635
|
+
if (redirectCompIndex !== -1) {
|
|
636
|
+
const fileUrl = pathToFileURL(clientComponents[redirectCompIndex]).href;
|
|
637
|
+
addModuleMap(redirectChunkId, `{ "*": { id: ${JSON.stringify(fileUrl)}, chunks: [], name: "*" } }`);
|
|
638
|
+
for (const rp of candidateRedirectPaths) {
|
|
639
|
+
for (const u of generateAllUrlVariants(rp)) {
|
|
640
|
+
addModuleMap(u, `{ "*": { id: ${JSON.stringify(fileUrl)}, chunks: [], name: "*" } }`);
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
ssrManifestCode += ` },\n serverModuleMap: {\n`;
|
|
646
|
+
|
|
647
|
+
const emittedServerModuleMap = new Set();
|
|
648
|
+
function addServerModuleMap(key, valueObjStr) {
|
|
649
|
+
if (!emittedServerModuleMap.has(key)) {
|
|
650
|
+
emittedServerModuleMap.add(key);
|
|
651
|
+
ssrManifestCode += ` ${JSON.stringify(key)}: ${valueObjStr},\n`;
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
serverFunctionFiles.forEach((relPath) => {
|
|
656
|
+
const normRel = relPath.replace(/\\/g, "/");
|
|
657
|
+
const relFileUrl = "file:///" + normRel;
|
|
658
|
+
const absPath = path.resolve(projectRoot, relPath);
|
|
659
|
+
const fullFileUrl = pathToFileURL(absPath).href;
|
|
660
|
+
const altFullFileUrl = fullFileUrl.replace(/file:\/\/\/([a-zA-Z]):/, (m, d) => 'file:///' + (d === d.toLowerCase() ? d.toUpperCase() : d.toLowerCase()) + ':');
|
|
661
|
+
|
|
662
|
+
addServerModuleMap(relFileUrl, `{ id: ${JSON.stringify(relFileUrl)}, chunks: [], name: "*" }`);
|
|
663
|
+
addServerModuleMap(fullFileUrl, `{ id: ${JSON.stringify(relFileUrl)}, chunks: [], name: "*" }`);
|
|
664
|
+
if (altFullFileUrl !== fullFileUrl) {
|
|
665
|
+
addServerModuleMap(altFullFileUrl, `{ id: ${JSON.stringify(relFileUrl)}, chunks: [], name: "*" }`);
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
const fns = parsedServerFunctionsManifest[relPath] || [];
|
|
669
|
+
for (const fn of fns) {
|
|
670
|
+
addServerModuleMap(relFileUrl + "#" + fn, `{ id: ${JSON.stringify(relFileUrl)}, chunks: [], name: ${JSON.stringify(fn)} }`);
|
|
671
|
+
addServerModuleMap(fullFileUrl + "#" + fn, `{ id: ${JSON.stringify(relFileUrl)}, chunks: [], name: ${JSON.stringify(fn)} }`);
|
|
672
|
+
if (altFullFileUrl !== fullFileUrl) {
|
|
673
|
+
addServerModuleMap(altFullFileUrl + "#" + fn, `{ id: ${JSON.stringify(relFileUrl)}, chunks: [], name: ${JSON.stringify(fn)} }`);
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
});
|
|
677
|
+
|
|
678
|
+
ssrManifestCode += ` },\n moduleLoading: null,\n};\n`;
|
|
679
|
+
|
|
680
|
+
const ssrClientManifestPath = path.join(denoDir, "ssr-client-manifest.js");
|
|
681
|
+
fs.writeFileSync(ssrClientManifestPath, ssrManifestCode, "utf8");
|
|
682
|
+
|
|
683
|
+
// ====================================================================
|
|
684
|
+
// Entry Files Generation
|
|
685
|
+
// ====================================================================
|
|
686
|
+
// 1. RSC Engine Entry
|
|
687
|
+
const rscEntryContent = `// Auto-generated RSC Engine entry for Deno Deploy / Edge
|
|
688
|
+
import "./env-setup.js";
|
|
689
|
+
import "./route-modules.js";
|
|
690
|
+
export { handleRequest } from "${dinouDirSlash}/core/handler.js";
|
|
691
|
+
`;
|
|
692
|
+
const rscEntryPath = path.join(denoDir, "rsc-entry.js");
|
|
693
|
+
fs.writeFileSync(rscEntryPath, rscEntryContent, "utf8");
|
|
694
|
+
|
|
695
|
+
// 2. SSR Engine Entry
|
|
696
|
+
const ssrEntryContent = `// Auto-generated SSR Engine entry for Deno Deploy / Edge
|
|
697
|
+
import { renderRscStreamToHtmlStream } from "${dinouDirSlash}/core/edge-ssr.js";
|
|
698
|
+
import { clientModules, ssrConsumerManifest } from "./ssr-client-manifest.js";
|
|
699
|
+
|
|
700
|
+
const lowerMap = new Map();
|
|
701
|
+
globalThis.__webpack_require__ = (id) => {
|
|
702
|
+
if (clientModules[id]) return clientModules[id];
|
|
703
|
+
if (typeof id === "string") {
|
|
704
|
+
if (lowerMap.size === 0) {
|
|
705
|
+
for (const k of Object.keys(clientModules)) lowerMap.set(k.toLowerCase(), clientModules[k]);
|
|
706
|
+
}
|
|
707
|
+
const lowerVal = lowerMap.get(id.toLowerCase());
|
|
708
|
+
if (lowerVal) return lowerVal;
|
|
709
|
+
}
|
|
710
|
+
console.error("[SSR Engine] Module not found in __webpack_require__:", id);
|
|
711
|
+
return {};
|
|
712
|
+
};
|
|
713
|
+
globalThis.__webpack_require__.u = (chunkId) => "" + chunkId + ".js";
|
|
714
|
+
globalThis.__webpack_chunk_load__ = () => Promise.resolve();
|
|
715
|
+
|
|
716
|
+
export async function renderHtml(rscStream, options = {}) {
|
|
717
|
+
return renderRscStreamToHtmlStream(rscStream, ssrConsumerManifest, options);
|
|
718
|
+
}
|
|
719
|
+
`;
|
|
720
|
+
const ssrEntryPath = path.join(denoDir, "ssr-entry.js");
|
|
721
|
+
fs.writeFileSync(ssrEntryPath, ssrEntryContent, "utf8");
|
|
722
|
+
|
|
723
|
+
// 3. Deno Orchestrator Entry
|
|
724
|
+
const denoEntryContent = `// Auto-generated main entry for Deno Deploy / Edge (Dual-Bundle)
|
|
725
|
+
import { handleRequest } from "./rsc-engine.js";
|
|
726
|
+
import { renderHtml } from "./ssr-engine.js";
|
|
727
|
+
import {
|
|
728
|
+
getStorageAdapter,
|
|
729
|
+
setStorageAdapter,
|
|
730
|
+
DenoKVStorage,
|
|
731
|
+
MemoryStorage,
|
|
732
|
+
} from "${dinouDirSlash}/core/storage-adapter.js";
|
|
733
|
+
import * as path from "node:path";
|
|
734
|
+
import * as fs from "node:fs";
|
|
735
|
+
|
|
736
|
+
if (typeof globalThis !== "undefined") {
|
|
737
|
+
globalThis.__DINOU_RUNTIME__ = "deno-edge";
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
let storageInitialized = false;
|
|
741
|
+
|
|
742
|
+
export async function fetch(req) {
|
|
743
|
+
if (!storageInitialized) {
|
|
744
|
+
if (typeof Deno !== "undefined" && typeof Deno.openKv === "function") {
|
|
745
|
+
try {
|
|
746
|
+
const kvUrl = Deno.env.get("DENO_KV_URL");
|
|
747
|
+
let kvInstance;
|
|
748
|
+
if (kvUrl) {
|
|
749
|
+
kvInstance = await Deno.openKv(kvUrl);
|
|
750
|
+
} else if (Deno.env.get("DENO_DEPLOYMENT_ID")) {
|
|
751
|
+
kvInstance = await Deno.openKv();
|
|
752
|
+
} else {
|
|
753
|
+
const cwd = typeof Deno.cwd === "function" ? Deno.cwd() : process.cwd();
|
|
754
|
+
const kvPath = Deno.env.get("DENO_KV_PATH") || path.resolve(cwd, ".dinou/kv.db");
|
|
755
|
+
kvInstance = await Deno.openKv(kvPath);
|
|
756
|
+
}
|
|
757
|
+
setStorageAdapter(new DenoKVStorage(kvInstance));
|
|
758
|
+
} catch (e) {
|
|
759
|
+
setStorageAdapter(new MemoryStorage());
|
|
760
|
+
}
|
|
761
|
+
} else {
|
|
762
|
+
setStorageAdapter(new MemoryStorage());
|
|
763
|
+
}
|
|
764
|
+
storageInitialized = true;
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
const url = new URL(req.url);
|
|
768
|
+
const pathname = url.pathname;
|
|
769
|
+
|
|
770
|
+
// Static assets delivery (if running with local disk access)
|
|
771
|
+
if (pathname !== "/" && typeof Deno !== "undefined" && typeof Deno.readFile === "function") {
|
|
772
|
+
try {
|
|
773
|
+
const cwd = typeof Deno.cwd === "function" ? Deno.cwd() : process.cwd();
|
|
774
|
+
const dist3Dir = path.resolve(cwd, ".dinou/dist3");
|
|
775
|
+
const filePath = path.join(dist3Dir, pathname);
|
|
776
|
+
if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) {
|
|
777
|
+
const content = await Deno.readFile(filePath);
|
|
778
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
779
|
+
const headers = {};
|
|
780
|
+
if (ext === ".js" || ext === ".mjs") headers["content-type"] = "application/javascript; charset=utf-8";
|
|
781
|
+
else if (ext === ".css") headers["content-type"] = "text/css; charset=utf-8";
|
|
782
|
+
else if (ext === ".json") headers["content-type"] = "application/json";
|
|
783
|
+
else if (ext === ".svg") headers["content-type"] = "image/svg+xml";
|
|
784
|
+
else if (ext === ".png") headers["content-type"] = "image/png";
|
|
785
|
+
else if (ext === ".ico") headers["content-type"] = "image/x-icon";
|
|
786
|
+
return new Response(content, { headers });
|
|
787
|
+
}
|
|
788
|
+
} catch (e) {
|
|
789
|
+
// Fallback to Dinou handler
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
return handleRequest(req, {
|
|
794
|
+
runtime: "deno-edge",
|
|
795
|
+
renderHtmlStream: renderHtml,
|
|
796
|
+
});
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
if (typeof Deno !== "undefined" && typeof Deno.serve === "function" && import.meta.main) {
|
|
800
|
+
const port = Number(Deno.env.get("PORT") || 3000);
|
|
801
|
+
Deno.serve({ port }, fetch);
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
export default { fetch };
|
|
805
|
+
`;
|
|
806
|
+
const denoEntryPath = path.join(denoDir, "deno-entry.js");
|
|
807
|
+
fs.writeFileSync(denoEntryPath, denoEntryContent, "utf8");
|
|
808
|
+
|
|
809
|
+
// ====================================================================
|
|
810
|
+
// Build Configuration
|
|
811
|
+
// ====================================================================
|
|
812
|
+
const nodeBuiltins = [
|
|
813
|
+
"assert", "async_hooks", "buffer", "child_process", "cluster", "console",
|
|
814
|
+
"constants", "crypto", "dgram", "diagnostics_channel", "dns", "domain",
|
|
815
|
+
"events", "fs", "fs/promises", "http", "http2", "https", "inspector",
|
|
816
|
+
"module", "net", "os", "path", "path/posix", "path/win32", "perf_hooks",
|
|
817
|
+
"process", "punycode", "querystring", "readline", "repl", "stream",
|
|
818
|
+
"stream/consumers", "stream/promises", "stream/web", "string_decoder",
|
|
819
|
+
"timers", "timers/promises", "tls", "trace_events", "tty", "url",
|
|
820
|
+
"util", "util/types", "v8", "vm", "wasi", "worker_threads", "zlib"
|
|
821
|
+
];
|
|
822
|
+
|
|
823
|
+
const externalList = [
|
|
824
|
+
"npm:*",
|
|
825
|
+
"jsr:*",
|
|
826
|
+
...nodeBuiltins,
|
|
827
|
+
...nodeBuiltins.map((b) => "node:" + b),
|
|
828
|
+
];
|
|
829
|
+
|
|
830
|
+
const commonAlias = {
|
|
831
|
+
"@": path.resolve(projectRoot, "src"),
|
|
832
|
+
"dinou/config": path.resolve(dinouDir, "core/config.js"),
|
|
833
|
+
dinou: dinouDir,
|
|
834
|
+
};
|
|
835
|
+
|
|
836
|
+
const commonLoader = {
|
|
837
|
+
".js": "jsx",
|
|
838
|
+
".jsx": "jsx",
|
|
839
|
+
".ts": "ts",
|
|
840
|
+
".tsx": "tsx",
|
|
841
|
+
".json": "json",
|
|
842
|
+
".css": "empty",
|
|
843
|
+
".svg": "dataurl",
|
|
844
|
+
".png": "dataurl",
|
|
845
|
+
".jpg": "dataurl",
|
|
846
|
+
".jpeg": "dataurl",
|
|
847
|
+
".webp": "dataurl",
|
|
848
|
+
".ico": "dataurl",
|
|
849
|
+
};
|
|
850
|
+
|
|
851
|
+
const banner = {
|
|
852
|
+
js: `import { createRequire as ___createRequire } from 'node:module';
|
|
853
|
+
import { AsyncLocalStorage as ___AsyncLocalStorage } from 'node:async_hooks';
|
|
854
|
+
const require = ___createRequire(import.meta.url || 'file:///main.js');
|
|
855
|
+
const __dirname = '';
|
|
856
|
+
const __filename = '';
|
|
857
|
+
globalThis.__dinou_require__ = require;
|
|
858
|
+
if (typeof globalThis.AsyncLocalStorage === 'undefined' && typeof ___AsyncLocalStorage !== 'undefined') {
|
|
859
|
+
globalThis.AsyncLocalStorage = ___AsyncLocalStorage;
|
|
860
|
+
}
|
|
861
|
+
if (typeof globalThis.__webpack_require__ === 'undefined') {
|
|
862
|
+
globalThis.__webpack_require__ = function(id) {
|
|
863
|
+
if (globalThis.__webpack_modules__ && globalThis.__webpack_modules__[id]) {
|
|
864
|
+
return globalThis.__webpack_modules__[id];
|
|
865
|
+
}
|
|
866
|
+
return {};
|
|
867
|
+
};
|
|
868
|
+
}
|
|
869
|
+
if (typeof globalThis.__webpack_require__.u === 'undefined') {
|
|
870
|
+
globalThis.__webpack_require__.u = function(chunkId) { return '' + chunkId + '.js'; };
|
|
871
|
+
}
|
|
872
|
+
if (typeof globalThis.__webpack_chunk_load__ === 'undefined') {
|
|
873
|
+
globalThis.__webpack_chunk_load__ = () => Promise.resolve();
|
|
874
|
+
}
|
|
875
|
+
var __webpack_require__ = function(id) {
|
|
876
|
+
return globalThis.__webpack_require__ ? globalThis.__webpack_require__(id) : {};
|
|
877
|
+
};
|
|
878
|
+
__webpack_require__.u = function(chunkId) {
|
|
879
|
+
return (globalThis.__webpack_require__ && globalThis.__webpack_require__.u)
|
|
880
|
+
? globalThis.__webpack_require__.u(chunkId)
|
|
881
|
+
: '' + chunkId + '.js';
|
|
882
|
+
};
|
|
883
|
+
var __webpack_chunk_load__ = function(chunkId) {
|
|
884
|
+
return globalThis.__webpack_chunk_load__ ? globalThis.__webpack_chunk_load__(chunkId) : Promise.resolve();
|
|
885
|
+
};
|
|
886
|
+
`,
|
|
887
|
+
};
|
|
888
|
+
|
|
889
|
+
// Plugins for RSC Engine
|
|
890
|
+
const clientReferencesPlugin = {
|
|
891
|
+
name: "dinou-client-references",
|
|
892
|
+
setup(build) {
|
|
893
|
+
build.onLoad({ filter: /\.[jt]sx?$/ }, async (args) => {
|
|
894
|
+
if (args.path.includes("node_modules")) {
|
|
895
|
+
if (
|
|
896
|
+
args.path.includes("react-server-dom") ||
|
|
897
|
+
args.path.includes("@roggc/react-server-dom-esm") ||
|
|
898
|
+
args.path.includes("node_modules/react/") ||
|
|
899
|
+
args.path.includes("node_modules\\react\\") ||
|
|
900
|
+
args.path.includes("node_modules/react-dom/") ||
|
|
901
|
+
args.path.includes("node_modules\\react-dom\\")
|
|
902
|
+
) {
|
|
903
|
+
return null;
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
const normalizedPath = args.path.replace(/\\/g, "/");
|
|
907
|
+
if (normalizedPath.includes("dinou/core/navigation")) return null;
|
|
908
|
+
|
|
909
|
+
let code;
|
|
910
|
+
try {
|
|
911
|
+
code = fs.readFileSync(args.path, "utf8");
|
|
912
|
+
} catch (e) {
|
|
913
|
+
return null;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
if (!isSupportedClientModule(args.path, code)) return null;
|
|
917
|
+
if (!useClientRegex.test(code.trim())) return null;
|
|
918
|
+
|
|
919
|
+
const exports = parseExports(code);
|
|
920
|
+
const absPath = path.resolve(args.path);
|
|
921
|
+
const fileUrl = pathToFileURL(absPath).href;
|
|
922
|
+
|
|
923
|
+
let proxyCode = `import { createClientModuleProxy } from "react-server-dom-webpack/server.edge";\n`;
|
|
924
|
+
proxyCode += `const proxy = createClientModuleProxy(${JSON.stringify(fileUrl)});\n`;
|
|
925
|
+
|
|
926
|
+
for (const name of exports) {
|
|
927
|
+
if (name === "default") {
|
|
928
|
+
proxyCode += `export default proxy.default;\n`;
|
|
929
|
+
} else {
|
|
930
|
+
proxyCode += `export const ${name} = proxy[${JSON.stringify(name)}];\n`;
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
if (!exports.includes("default")) {
|
|
935
|
+
proxyCode += `export default proxy.default;\n`;
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
return {
|
|
939
|
+
contents: proxyCode,
|
|
940
|
+
loader: "js",
|
|
941
|
+
};
|
|
942
|
+
});
|
|
943
|
+
},
|
|
944
|
+
};
|
|
945
|
+
|
|
946
|
+
const serverReferencesPlugin = {
|
|
947
|
+
name: "dinou-server-references",
|
|
948
|
+
setup(build) {
|
|
949
|
+
build.onLoad({ filter: /\.[jt]sx?$/ }, async (args) => {
|
|
950
|
+
if (args.path.includes("node_modules")) return null;
|
|
951
|
+
|
|
952
|
+
let code;
|
|
953
|
+
try {
|
|
954
|
+
code = fs.readFileSync(args.path, "utf8");
|
|
955
|
+
} catch (e) {
|
|
956
|
+
return null;
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
if (!useServerRegex.test(code.trim())) return null;
|
|
960
|
+
|
|
961
|
+
const exports = parseExports(code);
|
|
962
|
+
const absPath = path.resolve(args.path);
|
|
963
|
+
const relPath = path.relative(projectRoot, absPath).replace(/\\/g, "/");
|
|
964
|
+
const relativeFileUrl = "file:///" + relPath;
|
|
965
|
+
|
|
966
|
+
let transformed = code + "\n\n";
|
|
967
|
+
transformed += `import { registerServerReference } from "react-server-dom-webpack/server.edge";\n`;
|
|
968
|
+
|
|
969
|
+
for (const name of exports) {
|
|
970
|
+
if (name !== "default") {
|
|
971
|
+
transformed += `registerServerReference(${name}, ${JSON.stringify(relativeFileUrl)}, ${JSON.stringify(name)});\n`;
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
const ext = path.extname(args.path);
|
|
976
|
+
const loader = ext === ".ts" ? "ts" : ext === ".tsx" ? "tsx" : ext === ".jsx" ? "jsx" : "js";
|
|
977
|
+
|
|
978
|
+
return {
|
|
979
|
+
contents: transformed,
|
|
980
|
+
loader,
|
|
981
|
+
};
|
|
982
|
+
});
|
|
983
|
+
},
|
|
984
|
+
};
|
|
985
|
+
|
|
986
|
+
// Plugin for SSR Engine (Register server functions with client.edge)
|
|
987
|
+
const serverReferencesPluginSsr = {
|
|
988
|
+
name: "dinou-server-references-ssr",
|
|
989
|
+
setup(build) {
|
|
990
|
+
build.onLoad({ filter: /\.[jt]sx?$/ }, async (args) => {
|
|
991
|
+
if (args.path.includes("node_modules")) return null;
|
|
992
|
+
|
|
993
|
+
let code;
|
|
994
|
+
try {
|
|
995
|
+
code = fs.readFileSync(args.path, "utf8");
|
|
996
|
+
} catch (e) {
|
|
997
|
+
return null;
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
if (!useServerRegex.test(code.trim())) return null;
|
|
1001
|
+
|
|
1002
|
+
const exports = parseExports(code);
|
|
1003
|
+
const absPath = path.resolve(args.path);
|
|
1004
|
+
const relPath = path.relative(projectRoot, absPath).replace(/\\/g, "/");
|
|
1005
|
+
const relativeFileUrl = "file:///" + relPath;
|
|
1006
|
+
|
|
1007
|
+
let transformed = code + "\n\n";
|
|
1008
|
+
transformed += `import { registerServerReference } from "react-server-dom-webpack/client.edge";\n`;
|
|
1009
|
+
|
|
1010
|
+
for (const name of exports) {
|
|
1011
|
+
if (name !== "default") {
|
|
1012
|
+
transformed += `registerServerReference(${name}, ${JSON.stringify(relativeFileUrl + "#" + name)});\n`;
|
|
1013
|
+
transformed += `registerServerReference(${name}, ${JSON.stringify(pathToFileURL(absPath).href + "#" + name)});\n`;
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
const ext = path.extname(args.path);
|
|
1018
|
+
const loader = ext === ".ts" ? "ts" : ext === ".tsx" ? "tsx" : ext === ".jsx" ? "jsx" : "js";
|
|
1019
|
+
|
|
1020
|
+
return {
|
|
1021
|
+
contents: transformed,
|
|
1022
|
+
loader,
|
|
1023
|
+
};
|
|
1024
|
+
});
|
|
1025
|
+
},
|
|
1026
|
+
};
|
|
1027
|
+
|
|
1028
|
+
const rscOutfile = path.join(denoDir, "rsc-engine.js");
|
|
1029
|
+
const ssrOutfile = path.join(denoDir, "ssr-engine.js");
|
|
1030
|
+
const finalOutfile = path.join(denoDir, "main.js");
|
|
1031
|
+
|
|
1032
|
+
try {
|
|
1033
|
+
// Pass A: RSC Engine
|
|
1034
|
+
console.log(" ā” Bundling Pass A (RSC deno) & Pass B (SSR deno)...");
|
|
1035
|
+
await esbuild.build({
|
|
1036
|
+
entryPoints: [rscEntryPath],
|
|
1037
|
+
outfile: rscOutfile,
|
|
1038
|
+
bundle: true,
|
|
1039
|
+
format: "esm",
|
|
1040
|
+
target: "es2022",
|
|
1041
|
+
platform: "neutral",
|
|
1042
|
+
mainFields: ["module", "main"],
|
|
1043
|
+
conditions: ["deno", "worker", "react-server"],
|
|
1044
|
+
external: externalList,
|
|
1045
|
+
plugins: [clientReferencesPlugin, serverReferencesPlugin],
|
|
1046
|
+
alias: commonAlias,
|
|
1047
|
+
loader: commonLoader,
|
|
1048
|
+
jsx: "automatic",
|
|
1049
|
+
define: {
|
|
1050
|
+
"process.env.NODE_ENV": '"production"',
|
|
1051
|
+
"process.env.DINOU_RUNTIME": '"deno-edge"',
|
|
1052
|
+
"process.env.DINOU_BUILD_TOOL": JSON.stringify(isWebpackBuild ? "webpack" : (process.env.DINOU_BUILD_TOOL || "esbuild")),
|
|
1053
|
+
},
|
|
1054
|
+
logLevel: "warning",
|
|
1055
|
+
});
|
|
1056
|
+
|
|
1057
|
+
// Pass B: SSR Engine
|
|
1058
|
+
await esbuild.build({
|
|
1059
|
+
entryPoints: [ssrEntryPath],
|
|
1060
|
+
outfile: ssrOutfile,
|
|
1061
|
+
bundle: true,
|
|
1062
|
+
format: "esm",
|
|
1063
|
+
target: "es2022",
|
|
1064
|
+
platform: "neutral",
|
|
1065
|
+
mainFields: ["module", "main"],
|
|
1066
|
+
conditions: ["deno", "worker", "browser"],
|
|
1067
|
+
external: externalList,
|
|
1068
|
+
plugins: [serverReferencesPluginSsr],
|
|
1069
|
+
alias: commonAlias,
|
|
1070
|
+
loader: commonLoader,
|
|
1071
|
+
jsx: "automatic",
|
|
1072
|
+
define: {
|
|
1073
|
+
"process.env.NODE_ENV": '"production"',
|
|
1074
|
+
"process.env.DINOU_RUNTIME": '"deno-edge"',
|
|
1075
|
+
"process.env.DINOU_BUILD_TOOL": JSON.stringify(isWebpackBuild ? "webpack" : (process.env.DINOU_BUILD_TOOL || "esbuild")),
|
|
1076
|
+
},
|
|
1077
|
+
logLevel: "warning",
|
|
1078
|
+
});
|
|
1079
|
+
|
|
1080
|
+
// Pass C: Final Deno Orchestrator
|
|
1081
|
+
console.log(" š Bundling Pass C: Deno Orchestrator (.dinou/deno/main.js)...");
|
|
1082
|
+
await esbuild.build({
|
|
1083
|
+
entryPoints: [denoEntryPath],
|
|
1084
|
+
outfile: finalOutfile,
|
|
1085
|
+
bundle: true,
|
|
1086
|
+
format: "esm",
|
|
1087
|
+
target: "es2022",
|
|
1088
|
+
platform: "neutral",
|
|
1089
|
+
mainFields: ["module", "main"],
|
|
1090
|
+
conditions: ["deno", "worker", "browser"],
|
|
1091
|
+
external: externalList,
|
|
1092
|
+
banner,
|
|
1093
|
+
alias: commonAlias,
|
|
1094
|
+
loader: commonLoader,
|
|
1095
|
+
define: {
|
|
1096
|
+
"process.env.NODE_ENV": '"production"',
|
|
1097
|
+
"process.env.DINOU_RUNTIME": '"deno-edge"',
|
|
1098
|
+
"process.env.DINOU_BUILD_TOOL": JSON.stringify(isWebpackBuild ? "webpack" : (process.env.DINOU_BUILD_TOOL || "esbuild")),
|
|
1099
|
+
},
|
|
1100
|
+
logLevel: "warning",
|
|
1101
|
+
});
|
|
1102
|
+
|
|
1103
|
+
const relOutfile = path.relative(projectRoot, finalOutfile).replace(/\\/g, "/");
|
|
1104
|
+
console.log(`\nā Deno build complete!`);
|
|
1105
|
+
console.log(` Output: ${relOutfile}`);
|
|
1106
|
+
console.log(` š Run locally: deno run --unstable-kv -A ${relOutfile}`);
|
|
1107
|
+
console.log(` š Deploy to edge: deno deploy --project=<your-project> ${relOutfile}`);
|
|
1108
|
+
console.log(` š Compile binary: npm run build:deno:compile\n`);
|
|
1109
|
+
} catch (err) {
|
|
1110
|
+
console.error("ā [Dinou Deno] Build failed:", err);
|
|
1111
|
+
process.exit(1);
|
|
1112
|
+
}
|