dinou 7.1.0 → 7.3.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 +26 -0
- package/README.md +1 -1
- package/cli.js +85 -0
- package/dinou/adapters/netlify.js +3 -15
- package/dinou/bun/build.mjs +11 -0
- package/dinou/cloudflare/build.mjs +12 -0
- package/dinou/core/load-dinou-config.js +35 -3
- package/dinou/core/resolve-setup-files.js +69 -0
- package/dinou/core/server-function-proxy-webpack.js +20 -1
- package/dinou/core/server-function-proxy.js +20 -1
- package/dinou/deno/build.mjs +11 -0
- package/dinou/index.d.ts +34 -0
- package/dinou/node/build.mjs +54 -7
- package/dinou/node/bundle-dual-engine.mjs +11 -0
- package/dinou/node/dev.mjs +66 -1
- package/dinou/package.json +1 -1
- package/eject.js +45 -1
- package/package.json +1 -1
- package/dinou/core/babel-esm-loader.js +0 -267
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,32 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
7
7
|
|
|
8
|
+
## [7.3.0]
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **Universal Setup Files & Environment Polyfills**:
|
|
12
|
+
- Early-stage execution guarantee: Setup scripts are injected at Line 1 of all compilation bundles before any module imports or engine code run, enabling browser/canvas polyfills (`DOMMatrix`, `ImageData`, `Path2D`) and APM/telemetry agents without ejecting.
|
|
13
|
+
- Unified configuration hierarchy: `plugin.setupFiles` (plugins run first) -> explicit `setupFiles: [...]` in `dinou.config.*` (strict source of truth; replaces convention) -> zero-config root convention `./dinou.setup.(mjs|js|ts)`.
|
|
14
|
+
- Comprehensive multi-platform support: Injected uniformly across Node.js (`Pass A`, `Pass B`, `Pass C`), Bun native AOT, Cloudflare Workers, Deno / Deno Deploy, Static Site Generation (SSG), and Hot-Reload Dev Server.
|
|
15
|
+
- Added TypeScript definitions for `setupFiles?: string[]` in both `DinouConfig` and `DinouPlugin`.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
- **Bun Standalone Compilation Port Collision (`EADDRINUSE`)**:
|
|
19
|
+
- Resolved port binding conflict when compiling the Node.js orchestrator into a standalone executable using `bun build --compile`.
|
|
20
|
+
- Separated exports in `.dinou/node/server.mjs`: `fetch` is now exported exclusively as a named export (`export { fetch }`), while `export default` exposes `{ port, startServer }`, preventing Bun's runtime from launching a duplicate background `Bun.serve` instance over Node's `http.createServer()`.
|
|
21
|
+
- Robust `isMain` execution detection supporting both Node.js (`process.argv[1]`) and compiled Bun binaries (`import.meta.main`).
|
|
22
|
+
|
|
23
|
+
## [7.2.0]
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
- **Plugin Hook `configureServer`**: Attach WebSockets (Socket.IO, WS) and native Node.js HTTP middlewares before server startup without ejecting.
|
|
27
|
+
- **Node Standalone Binary Compilation**: Added `dinou build:node:compile` and cross-compilation matrix (`:linux`, `:linux_arm`, `:mac`, `:win`).
|
|
28
|
+
- **Client-Side Server Function Auth Hooks**: Added `window.__DINOU_SERVER_FUNCTION_HEADERS__` and `window.__DINOU_GET_AUTH_TOKEN__` to inject dynamic JWT/Bearer authorization headers into `"use server"` calls.
|
|
29
|
+
- **Esbuild-Powered Config Loader**: `dinou.config.*` is automatically pre-bundled with Esbuild, enabling native `tsconfig.json` path aliases (`@/*`) and TypeScript configuration files out of the box.
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
- Removed legacy `babel-esm-loader.js` and cleaned up residual loader registrations.
|
|
33
|
+
|
|
8
34
|
## [7.1.0] - 2026-10-16
|
|
9
35
|
|
|
10
36
|
### Added
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# **Dinou**
|
|
2
2
|
|
|
3
|
-
[](https://dinou.dev) [](https://dinou.dev) [](https://www.npmjs.com/package/dinou)
|
|
4
4
|
|
|
5
5
|
### **Full-Stack React 19 Framework**
|
|
6
6
|
|
package/cli.js
CHANGED
|
@@ -121,6 +121,91 @@ program
|
|
|
121
121
|
runCommand(`cross-env NODE_ENV=production DINOU_BUILD_TOOL=webpack node ${p("adapters/node.mjs")}`);
|
|
122
122
|
});
|
|
123
123
|
|
|
124
|
+
// --- NODE (COMPILE VIA BUN) ---
|
|
125
|
+
|
|
126
|
+
const nodeTargets = [
|
|
127
|
+
{ name: "", flags: "", outfile: "dist/server" },
|
|
128
|
+
{ name: ":linux", flags: "--target=bun-linux-x64 ", outfile: "dist/server-linux" },
|
|
129
|
+
{ name: ":linux_arm", flags: "--target=bun-linux-arm64 ", outfile: "dist/server-linux-arm" },
|
|
130
|
+
{ name: ":mac", flags: "--target=bun-darwin-arm64 ", outfile: "dist/server-mac" },
|
|
131
|
+
{ name: ":win", flags: "--target=bun-windows-x64 ", outfile: "dist/server-win" },
|
|
132
|
+
];
|
|
133
|
+
|
|
134
|
+
const runNodeBuild = (bundler) => {
|
|
135
|
+
const bundlerCmd = bundler === "rollup"
|
|
136
|
+
? `cross-env NODE_ENV=production npx rollup -c ${p("rollup/rollup.config.js")}`
|
|
137
|
+
: bundler === "webpack"
|
|
138
|
+
? `cross-env NODE_ENV=production npx webpack --config ${p("webpack/webpack.config.js")}`
|
|
139
|
+
: `cross-env NODE_ENV=production node ${p("esbuild/build.mjs")}`;
|
|
140
|
+
|
|
141
|
+
const envPrefix = bundler === "webpack" ? "cross-env DINOU_BUILD_TOOL=webpack " : "";
|
|
142
|
+
return `${bundlerCmd} && ${envPrefix}node ${p("node/build.mjs")}`;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
for (const t of nodeTargets) {
|
|
146
|
+
for (const b of ["esbuild", "rollup", "webpack"]) {
|
|
147
|
+
const cmdNames = b === "esbuild"
|
|
148
|
+
? [`build:node:compile${t.name}`, `build:node:compile${t.name}:esbuild`]
|
|
149
|
+
: [`build:node:compile${t.name}:${b}`];
|
|
150
|
+
for (const cmdName of cmdNames) {
|
|
151
|
+
program
|
|
152
|
+
.command(cmdName)
|
|
153
|
+
.description(`Compile standalone Node.js server executable with Bun (${t.name || "host"}, ${b})`)
|
|
154
|
+
.action(() => {
|
|
155
|
+
runCommand(`${runNodeBuild(b)} && bun build --compile ${t.flags}.dinou/node/server.mjs --outfile ${t.outfile}`);
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// --- NODE (PURE BUN RUNNER COMPILE) ---
|
|
162
|
+
|
|
163
|
+
const runNodePureBuild = (bundler) => {
|
|
164
|
+
if (bundler === "rollup") {
|
|
165
|
+
return `cross-env NODE_ENV=production npx rollup -c ${p("rollup/rollup.config.js")} && bun ${p("node/build.mjs")}`;
|
|
166
|
+
}
|
|
167
|
+
if (bundler === "webpack") {
|
|
168
|
+
return `cross-env NODE_ENV=production npx webpack --config ${p("webpack/webpack.config.js")} && cross-env DINOU_BUILD_TOOL=webpack bun ${p("node/build.mjs")}`;
|
|
169
|
+
}
|
|
170
|
+
return `cross-env NODE_ENV=production bun ${p("esbuild/build.mjs")} && bun ${p("node/build.mjs")}`;
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
program
|
|
174
|
+
.command("build:node:pure")
|
|
175
|
+
.description("Build the app for Node.js with 100% Bun (using esbuild)")
|
|
176
|
+
.action(() => { runCommand(runNodePureBuild("esbuild")); });
|
|
177
|
+
|
|
178
|
+
program
|
|
179
|
+
.command("build:node:pure:esbuild")
|
|
180
|
+
.description("Build the app for Node.js with 100% Bun (Esbuild)")
|
|
181
|
+
.action(() => { runCommand(runNodePureBuild("esbuild")); });
|
|
182
|
+
|
|
183
|
+
program
|
|
184
|
+
.command("build:node:pure:rollup")
|
|
185
|
+
.description("Build the app for Node.js with 100% Bun (Rollup)")
|
|
186
|
+
.action(() => { runCommand(runNodePureBuild("rollup")); });
|
|
187
|
+
|
|
188
|
+
program
|
|
189
|
+
.command("build:node:pure:webpack")
|
|
190
|
+
.description("Build the app for Node.js with 100% Bun (Webpack)")
|
|
191
|
+
.action(() => { runCommand(runNodePureBuild("webpack")); });
|
|
192
|
+
|
|
193
|
+
for (const t of nodeTargets) {
|
|
194
|
+
for (const b of ["esbuild", "rollup", "webpack"]) {
|
|
195
|
+
const cmdNames = b === "esbuild"
|
|
196
|
+
? [`build:node:pure:compile${t.name}`, `build:node:pure:compile${t.name}:esbuild`]
|
|
197
|
+
: [`build:node:pure:compile${t.name}:${b}`];
|
|
198
|
+
for (const cmdName of cmdNames) {
|
|
199
|
+
program
|
|
200
|
+
.command(cmdName)
|
|
201
|
+
.description(`Compile standalone Node.js server executable with 100% Bun (${t.name || "host"}, ${b})`)
|
|
202
|
+
.action(() => {
|
|
203
|
+
runCommand(`${runNodePureBuild(b)} && bun build --compile ${t.flags}.dinou/node/server.mjs --outfile ${t.outfile}`);
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
124
209
|
// --- CLOUDFLARE WORKERS ---
|
|
125
210
|
|
|
126
211
|
program
|
|
@@ -3,21 +3,9 @@
|
|
|
3
3
|
// Automatically routes all requests to Dinou's universal Web Standards handler.
|
|
4
4
|
Object.assign(process.env, { NODE_ENV: "production" });
|
|
5
5
|
|
|
6
|
-
import { register } from "node:module";
|
|
7
|
-
import { pathToFileURL } from "node:url";
|
|
8
6
|
import path from "node:path";
|
|
9
7
|
import Module from "node:module";
|
|
10
8
|
|
|
11
|
-
import { dinouCoreDir } from "../core/dinou-paths.js";
|
|
12
|
-
|
|
13
|
-
if (typeof register === "function") {
|
|
14
|
-
try {
|
|
15
|
-
const loaderPath = path.join(dinouCoreDir, "babel-esm-loader.js");
|
|
16
|
-
register(pathToFileURL(loaderPath).href, pathToFileURL("./"));
|
|
17
|
-
} catch (e) {
|
|
18
|
-
console.error("[Dinou Adapter] Loader registration failed:", e);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
9
|
|
|
22
10
|
let reactServerPath, reactDomServerPath, reactJsxRuntimePath, reactJsxDevRuntimePath;
|
|
23
11
|
let roggcServerNodePath, webpackServerNodePath;
|
|
@@ -30,17 +18,17 @@ try {
|
|
|
30
18
|
|
|
31
19
|
const reactDomPkgJson = require.resolve("react-dom/package.json");
|
|
32
20
|
reactDomServerPath = path.join(path.dirname(reactDomPkgJson), "react-dom.react-server.js");
|
|
33
|
-
} catch (e) {}
|
|
21
|
+
} catch (e) { }
|
|
34
22
|
|
|
35
23
|
try {
|
|
36
24
|
const roggcPkgJson = require.resolve("@roggc/react-server-dom-esm/package.json");
|
|
37
25
|
roggcServerNodePath = path.join(path.dirname(roggcPkgJson), "server.node.js");
|
|
38
|
-
} catch (e) {}
|
|
26
|
+
} catch (e) { }
|
|
39
27
|
|
|
40
28
|
try {
|
|
41
29
|
const webpackPkgJson = require.resolve("react-server-dom-webpack/package.json");
|
|
42
30
|
webpackServerNodePath = path.join(path.dirname(webpackPkgJson), "server.node.js");
|
|
43
|
-
} catch (e) {}
|
|
31
|
+
} catch (e) { }
|
|
44
32
|
|
|
45
33
|
if (Module && Module._resolveFilename) {
|
|
46
34
|
const originalResolveFilename = Module._resolveFilename;
|
package/dinou/bun/build.mjs
CHANGED
|
@@ -19,11 +19,19 @@ const {
|
|
|
19
19
|
isSupportedClientModule,
|
|
20
20
|
scanProjectDependenciesForClientComponents,
|
|
21
21
|
} = require("../core/scan-dependency-components.js");
|
|
22
|
+
const { getDinouConfig } = require("../core/load-dinou-config.js");
|
|
23
|
+
const { resolveSetupFiles } = require("../core/resolve-setup-files.js");
|
|
22
24
|
|
|
23
25
|
const projectRoot = process.cwd();
|
|
24
26
|
const bunDir = path.resolve(projectRoot, ".dinou/bun");
|
|
25
27
|
fs.mkdirSync(bunDir, { recursive: true });
|
|
26
28
|
|
|
29
|
+
const dinouConfig = await getDinouConfig(projectRoot);
|
|
30
|
+
const setupFiles = resolveSetupFiles(projectRoot, dinouConfig);
|
|
31
|
+
if (setupFiles.length > 0) {
|
|
32
|
+
console.log(` 🔌 [Dinou Setup] Active setup files (${setupFiles.length}): ${setupFiles.map((f) => path.basename(f)).join(", ")}`);
|
|
33
|
+
}
|
|
34
|
+
|
|
27
35
|
try {
|
|
28
36
|
generateRouteTypes(projectRoot);
|
|
29
37
|
} catch (e) {}
|
|
@@ -1012,6 +1020,7 @@ try {
|
|
|
1012
1020
|
alias: commonAlias,
|
|
1013
1021
|
loader: commonLoader,
|
|
1014
1022
|
jsx: "automatic",
|
|
1023
|
+
inject: setupFiles.length > 0 ? setupFiles : undefined,
|
|
1015
1024
|
define: {
|
|
1016
1025
|
"process.env.NODE_ENV": '"production"',
|
|
1017
1026
|
"process.env.DINOU_RUNTIME": '"bun-bundle"',
|
|
@@ -1035,6 +1044,7 @@ try {
|
|
|
1035
1044
|
alias: commonAlias,
|
|
1036
1045
|
loader: commonLoader,
|
|
1037
1046
|
jsx: "automatic",
|
|
1047
|
+
inject: setupFiles.length > 0 ? setupFiles : undefined,
|
|
1038
1048
|
define: {
|
|
1039
1049
|
"process.env.NODE_ENV": '"production"',
|
|
1040
1050
|
"process.env.DINOU_RUNTIME": '"bun-bundle"',
|
|
@@ -1056,6 +1066,7 @@ try {
|
|
|
1056
1066
|
conditions: ["bun", "worker", "browser"],
|
|
1057
1067
|
external: externalList,
|
|
1058
1068
|
banner,
|
|
1069
|
+
inject: setupFiles.length > 0 ? setupFiles : undefined,
|
|
1059
1070
|
alias: commonAlias,
|
|
1060
1071
|
loader: commonLoader,
|
|
1061
1072
|
define: {
|
|
@@ -19,11 +19,19 @@ const {
|
|
|
19
19
|
isSupportedClientModule,
|
|
20
20
|
scanProjectDependenciesForClientComponents,
|
|
21
21
|
} = require("../core/scan-dependency-components.js");
|
|
22
|
+
const { getDinouConfig } = require("../core/load-dinou-config.js");
|
|
23
|
+
const { resolveSetupFiles } = require("../core/resolve-setup-files.js");
|
|
22
24
|
|
|
23
25
|
const projectRoot = process.cwd();
|
|
24
26
|
const cloudflareDir = path.resolve(projectRoot, ".dinou/cloudflare");
|
|
25
27
|
fs.mkdirSync(cloudflareDir, { recursive: true });
|
|
26
28
|
|
|
29
|
+
const dinouConfig = await getDinouConfig(projectRoot);
|
|
30
|
+
const setupFiles = resolveSetupFiles(projectRoot, dinouConfig);
|
|
31
|
+
if (setupFiles.length > 0) {
|
|
32
|
+
console.log(` 🔌 [Dinou Setup] Active setup files (${setupFiles.length}): ${setupFiles.map((f) => path.basename(f)).join(", ")}`);
|
|
33
|
+
}
|
|
34
|
+
|
|
27
35
|
try {
|
|
28
36
|
generateRouteTypes(projectRoot);
|
|
29
37
|
} catch (e) {}
|
|
@@ -819,6 +827,7 @@ const commonAlias = {
|
|
|
819
827
|
"@": path.resolve(projectRoot, "src"),
|
|
820
828
|
"dinou/config": path.resolve(dinouDir, "core/config.js"),
|
|
821
829
|
dinou: dinouDir,
|
|
830
|
+
esbuild: path.resolve(shimsDir, "empty.js"),
|
|
822
831
|
fs: path.resolve(shimsDir, "fs.js"),
|
|
823
832
|
"node:fs": path.resolve(shimsDir, "fs.js"),
|
|
824
833
|
"fs/promises": path.resolve(shimsDir, "fs.js"),
|
|
@@ -1056,6 +1065,7 @@ try {
|
|
|
1056
1065
|
alias: commonAlias,
|
|
1057
1066
|
loader: commonLoader,
|
|
1058
1067
|
jsx: "automatic",
|
|
1068
|
+
inject: setupFiles.length > 0 ? setupFiles : undefined,
|
|
1059
1069
|
define: {
|
|
1060
1070
|
"process.env.NODE_ENV": '"production"',
|
|
1061
1071
|
"process.env.DINOU_RUNTIME": '"edge"',
|
|
@@ -1079,6 +1089,7 @@ try {
|
|
|
1079
1089
|
alias: commonAlias,
|
|
1080
1090
|
loader: commonLoader,
|
|
1081
1091
|
jsx: "automatic",
|
|
1092
|
+
inject: setupFiles.length > 0 ? setupFiles : undefined,
|
|
1082
1093
|
define: {
|
|
1083
1094
|
"process.env.NODE_ENV": '"production"',
|
|
1084
1095
|
"process.env.DINOU_RUNTIME": '"edge"',
|
|
@@ -1100,6 +1111,7 @@ try {
|
|
|
1100
1111
|
conditions: ["workerd", "worker", "browser"],
|
|
1101
1112
|
external: externalList,
|
|
1102
1113
|
banner,
|
|
1114
|
+
inject: setupFiles.length > 0 ? setupFiles : undefined,
|
|
1103
1115
|
alias: commonAlias,
|
|
1104
1116
|
loader: commonLoader,
|
|
1105
1117
|
define: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const path = require("path");
|
|
2
|
-
const { existsSync } = require("fs");
|
|
2
|
+
const { existsSync, mkdirSync } = require("fs");
|
|
3
3
|
const { pathToFileURL } = require("url");
|
|
4
4
|
|
|
5
5
|
let dinouConfig = { plugins: [] };
|
|
@@ -12,13 +12,45 @@ async function getDinouConfig() {
|
|
|
12
12
|
if (dinouConfigPromise) return dinouConfigPromise;
|
|
13
13
|
dinouConfigPromise = (async () => {
|
|
14
14
|
const cwd = typeof process !== "undefined" && typeof process.cwd === "function" ? process.cwd() : ".";
|
|
15
|
-
for (const filename of ["dinou.config.
|
|
15
|
+
for (const filename of ["dinou.config.ts", "dinou.config.mjs", "dinou.config.js", "dinou.config.cjs"]) {
|
|
16
16
|
const p = path.resolve(cwd, filename);
|
|
17
17
|
if (existsSync(p)) {
|
|
18
18
|
try {
|
|
19
19
|
let loaded;
|
|
20
20
|
const isDev = process.env.NODE_ENV !== "production";
|
|
21
|
-
|
|
21
|
+
let esbuild;
|
|
22
|
+
if (
|
|
23
|
+
typeof process !== "undefined" &&
|
|
24
|
+
process.versions &&
|
|
25
|
+
process.versions.node &&
|
|
26
|
+
process.env.DINOU_RUNTIME !== "edge"
|
|
27
|
+
) {
|
|
28
|
+
try {
|
|
29
|
+
const req = typeof require === "function" ? require : null;
|
|
30
|
+
const esbuildPkg = "esbuild";
|
|
31
|
+
if (req) {
|
|
32
|
+
esbuild = req(esbuildPkg);
|
|
33
|
+
}
|
|
34
|
+
} catch (e) {}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (esbuild && typeof esbuild.build === "function") {
|
|
38
|
+
const outDir = path.resolve(cwd, ".dinou");
|
|
39
|
+
if (!existsSync(outDir)) {
|
|
40
|
+
mkdirSync(outDir, { recursive: true });
|
|
41
|
+
}
|
|
42
|
+
const bundledPath = path.resolve(outDir, "dinou.config.bundled.mjs");
|
|
43
|
+
await esbuild.build({
|
|
44
|
+
entryPoints: [p],
|
|
45
|
+
outfile: bundledPath,
|
|
46
|
+
bundle: true,
|
|
47
|
+
format: "esm",
|
|
48
|
+
platform: "node",
|
|
49
|
+
packages: "external",
|
|
50
|
+
sourcemap: "inline",
|
|
51
|
+
});
|
|
52
|
+
loaded = await import(pathToFileURL(bundledPath).href + (isDev ? `?t=${Date.now()}` : ""));
|
|
53
|
+
} else if (p.endsWith(".mjs")) {
|
|
22
54
|
loaded = await import(pathToFileURL(p).href + (isDev ? `?t=${Date.now()}` : ""));
|
|
23
55
|
} else {
|
|
24
56
|
const nodeReq =
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// dinou/core/resolve-setup-files.js
|
|
2
|
+
const fs = require("node:fs");
|
|
3
|
+
const path = require("node:path");
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Resolves setup files according to Dinou's configuration hierarchy:
|
|
7
|
+
* 1. Plugin setup files (plugin.setupFiles) always execute first.
|
|
8
|
+
* 2. User setup files:
|
|
9
|
+
* - If config.setupFiles is explicitly provided in dinou.config.mjs, it is the sole source of truth.
|
|
10
|
+
* - Otherwise, falls back to checking the project root for dinou.setup.mjs, dinou.setup.js, or dinou.setup.ts.
|
|
11
|
+
*
|
|
12
|
+
* @param {string} projectRoot
|
|
13
|
+
* @param {object} config - Dinou config object
|
|
14
|
+
* @returns {string[]} Array of absolute file paths to inject/execute
|
|
15
|
+
*/
|
|
16
|
+
function resolveSetupFiles(projectRoot, config = {}) {
|
|
17
|
+
const pluginSetupFiles = [];
|
|
18
|
+
if (config.plugins && Array.isArray(config.plugins)) {
|
|
19
|
+
for (const plugin of config.plugins) {
|
|
20
|
+
if (plugin && Array.isArray(plugin.setupFiles)) {
|
|
21
|
+
for (const file of plugin.setupFiles) {
|
|
22
|
+
const resolved = path.isAbsolute(file)
|
|
23
|
+
? file
|
|
24
|
+
: path.resolve(projectRoot, file);
|
|
25
|
+
if (fs.existsSync(resolved)) {
|
|
26
|
+
pluginSetupFiles.push(resolved);
|
|
27
|
+
} else {
|
|
28
|
+
console.warn(
|
|
29
|
+
`⚠️ [Dinou] Plugin "${plugin.name || "unnamed"}" specified setup file not found: ${file}`,
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
let userSetupFiles = [];
|
|
38
|
+
if (Array.isArray(config.setupFiles)) {
|
|
39
|
+
// Explicit configuration takes precedence over convention
|
|
40
|
+
for (const file of config.setupFiles) {
|
|
41
|
+
const resolved = path.isAbsolute(file)
|
|
42
|
+
? file
|
|
43
|
+
: path.resolve(projectRoot, file);
|
|
44
|
+
if (fs.existsSync(resolved)) {
|
|
45
|
+
userSetupFiles.push(resolved);
|
|
46
|
+
} else {
|
|
47
|
+
console.warn(`⚠️ [Dinou] Configured setupFile not found: ${file}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
} else {
|
|
51
|
+
// Convention: check ONLY project root
|
|
52
|
+
const rootCandidates = [
|
|
53
|
+
"dinou.setup.mjs",
|
|
54
|
+
"dinou.setup.js",
|
|
55
|
+
"dinou.setup.ts",
|
|
56
|
+
];
|
|
57
|
+
for (const name of rootCandidates) {
|
|
58
|
+
const fullPath = path.resolve(projectRoot, name);
|
|
59
|
+
if (fs.existsSync(fullPath)) {
|
|
60
|
+
userSetupFiles.push(fullPath);
|
|
61
|
+
break; // Only pick the highest priority extension match
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return [...new Set([...pluginSetupFiles, ...userSetupFiles])];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
module.exports = { resolveSetupFiles };
|
|
@@ -17,14 +17,33 @@ function executeRedirect(url) {
|
|
|
17
17
|
function createServerFunctionProxy(id) {
|
|
18
18
|
return new Proxy(() => { }, {
|
|
19
19
|
apply: async (_target, _thisArg, args) => {
|
|
20
|
-
let
|
|
20
|
+
let customHeaders = {};
|
|
21
|
+
if (typeof window !== "undefined") {
|
|
22
|
+
if (typeof window.__DINOU_SERVER_FUNCTION_HEADERS__ === "function") {
|
|
23
|
+
try {
|
|
24
|
+
customHeaders = window.__DINOU_SERVER_FUNCTION_HEADERS__() || {};
|
|
25
|
+
} catch (e) {
|
|
26
|
+
console.error("[Dinou] Error getting custom headers for server function:", e);
|
|
27
|
+
}
|
|
28
|
+
} else if (typeof window.__DINOU_GET_AUTH_TOKEN__ === "function") {
|
|
29
|
+
try {
|
|
30
|
+
const token = window.__DINOU_GET_AUTH_TOKEN__();
|
|
31
|
+
if (token) customHeaders = { Authorization: `Bearer ${token}` };
|
|
32
|
+
} catch (e) {
|
|
33
|
+
console.error("[Dinou] Error getting auth token for server function:", e);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
21
38
|
const headers = {
|
|
22
39
|
"x-server-function-call": "1",
|
|
40
|
+
...customHeaders,
|
|
23
41
|
};
|
|
24
42
|
if (typeof window !== "undefined" && window.location) {
|
|
25
43
|
headers["x-dinou-current-path"] = window.location.pathname;
|
|
26
44
|
}
|
|
27
45
|
|
|
46
|
+
let body;
|
|
28
47
|
const formDataIndex = args.findIndex((arg) => arg instanceof FormData);
|
|
29
48
|
|
|
30
49
|
if (formDataIndex !== -1) {
|
|
@@ -17,14 +17,33 @@ function executeRedirect(url) {
|
|
|
17
17
|
export function createServerFunctionProxy(id) {
|
|
18
18
|
return new Proxy(() => { }, {
|
|
19
19
|
apply: async (_target, _thisArg, args) => {
|
|
20
|
-
let
|
|
20
|
+
let customHeaders = {};
|
|
21
|
+
if (typeof window !== "undefined") {
|
|
22
|
+
if (typeof window.__DINOU_SERVER_FUNCTION_HEADERS__ === "function") {
|
|
23
|
+
try {
|
|
24
|
+
customHeaders = window.__DINOU_SERVER_FUNCTION_HEADERS__() || {};
|
|
25
|
+
} catch (e) {
|
|
26
|
+
console.error("[Dinou] Error getting custom headers for server function:", e);
|
|
27
|
+
}
|
|
28
|
+
} else if (typeof window.__DINOU_GET_AUTH_TOKEN__ === "function") {
|
|
29
|
+
try {
|
|
30
|
+
const token = window.__DINOU_GET_AUTH_TOKEN__();
|
|
31
|
+
if (token) customHeaders = { Authorization: `Bearer ${token}` };
|
|
32
|
+
} catch (e) {
|
|
33
|
+
console.error("[Dinou] Error getting auth token for server function:", e);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
21
38
|
const headers = {
|
|
22
39
|
"x-server-function-call": "1",
|
|
40
|
+
...customHeaders,
|
|
23
41
|
};
|
|
24
42
|
if (typeof window !== "undefined" && window.location) {
|
|
25
43
|
headers["x-dinou-current-path"] = window.location.pathname;
|
|
26
44
|
}
|
|
27
45
|
|
|
46
|
+
let body;
|
|
28
47
|
const formDataIndex = args.findIndex((arg) => arg instanceof FormData);
|
|
29
48
|
|
|
30
49
|
if (formDataIndex !== -1) {
|
package/dinou/deno/build.mjs
CHANGED
|
@@ -19,11 +19,19 @@ const {
|
|
|
19
19
|
isSupportedClientModule,
|
|
20
20
|
scanProjectDependenciesForClientComponents,
|
|
21
21
|
} = require("../core/scan-dependency-components.js");
|
|
22
|
+
const { getDinouConfig } = require("../core/load-dinou-config.js");
|
|
23
|
+
const { resolveSetupFiles } = require("../core/resolve-setup-files.js");
|
|
22
24
|
|
|
23
25
|
const projectRoot = process.cwd();
|
|
24
26
|
const denoDir = path.resolve(projectRoot, ".dinou/deno");
|
|
25
27
|
fs.mkdirSync(denoDir, { recursive: true });
|
|
26
28
|
|
|
29
|
+
const dinouConfig = await getDinouConfig(projectRoot);
|
|
30
|
+
const setupFiles = resolveSetupFiles(projectRoot, dinouConfig);
|
|
31
|
+
if (setupFiles.length > 0) {
|
|
32
|
+
console.log(` 🔌 [Dinou Setup] Active setup files (${setupFiles.length}): ${setupFiles.map((f) => path.basename(f)).join(", ")}`);
|
|
33
|
+
}
|
|
34
|
+
|
|
27
35
|
try {
|
|
28
36
|
generateRouteTypes(projectRoot);
|
|
29
37
|
} catch (e) {}
|
|
@@ -1046,6 +1054,7 @@ try {
|
|
|
1046
1054
|
alias: commonAlias,
|
|
1047
1055
|
loader: commonLoader,
|
|
1048
1056
|
jsx: "automatic",
|
|
1057
|
+
inject: setupFiles.length > 0 ? setupFiles : undefined,
|
|
1049
1058
|
define: {
|
|
1050
1059
|
"process.env.NODE_ENV": '"production"',
|
|
1051
1060
|
"process.env.DINOU_RUNTIME": '"deno-edge"',
|
|
@@ -1069,6 +1078,7 @@ try {
|
|
|
1069
1078
|
alias: commonAlias,
|
|
1070
1079
|
loader: commonLoader,
|
|
1071
1080
|
jsx: "automatic",
|
|
1081
|
+
inject: setupFiles.length > 0 ? setupFiles : undefined,
|
|
1072
1082
|
define: {
|
|
1073
1083
|
"process.env.NODE_ENV": '"production"',
|
|
1074
1084
|
"process.env.DINOU_RUNTIME": '"deno-edge"',
|
|
@@ -1090,6 +1100,7 @@ try {
|
|
|
1090
1100
|
conditions: ["deno", "worker", "browser"],
|
|
1091
1101
|
external: externalList,
|
|
1092
1102
|
banner,
|
|
1103
|
+
inject: setupFiles.length > 0 ? setupFiles : undefined,
|
|
1093
1104
|
alias: commonAlias,
|
|
1094
1105
|
loader: commonLoader,
|
|
1095
1106
|
define: {
|
package/dinou/index.d.ts
CHANGED
|
@@ -120,8 +120,35 @@ export interface RequestContextStore {
|
|
|
120
120
|
// DINOU CONFIGURATION & PLUGIN INTERFACES
|
|
121
121
|
// ====================================================================
|
|
122
122
|
|
|
123
|
+
export type NodeMiddleware = (
|
|
124
|
+
req: import("node:http").IncomingMessage,
|
|
125
|
+
res: import("node:http").ServerResponse,
|
|
126
|
+
next: () => void
|
|
127
|
+
) => void | Promise<void>;
|
|
128
|
+
|
|
129
|
+
export interface ServerHookContext {
|
|
130
|
+
/** The underlying Node.js http.Server instance */
|
|
131
|
+
server: import("node:http").Server;
|
|
132
|
+
/** Whether the server is running in development mode */
|
|
133
|
+
isDev: boolean;
|
|
134
|
+
/** Register a raw Node.js middleware (req, res, next) executed before Dinou routes */
|
|
135
|
+
use(middleware: NodeMiddleware): void;
|
|
136
|
+
}
|
|
137
|
+
|
|
123
138
|
export interface DinouPlugin {
|
|
124
139
|
name?: string;
|
|
140
|
+
/**
|
|
141
|
+
* Hook invoked when the Node.js HTTP server is instantiated,
|
|
142
|
+
* allowing plugins to attach WebSockets (Socket.IO, ws), listeners, or raw Node middlewares.
|
|
143
|
+
*/
|
|
144
|
+
configureServer?(context: ServerHookContext): Promise<void> | void;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Array of setup/polyfill file paths to be executed at the earliest stage
|
|
148
|
+
* and injected into all bundled engines before any modules are loaded.
|
|
149
|
+
*/
|
|
150
|
+
setupFiles?: string[];
|
|
151
|
+
|
|
125
152
|
/**
|
|
126
153
|
* Universal Web Standards middleware and webhook handler.
|
|
127
154
|
* Runs on every incoming HTTP request before React rendering.
|
|
@@ -161,6 +188,13 @@ export interface DinouConfig {
|
|
|
161
188
|
*/
|
|
162
189
|
storage?: any;
|
|
163
190
|
|
|
191
|
+
/**
|
|
192
|
+
* Array of setup/polyfill file paths to be executed at the earliest stage
|
|
193
|
+
* before any server or client components are imported.
|
|
194
|
+
* If provided, overrides the root `dinou.setup.(mjs|js|ts)` convention.
|
|
195
|
+
*/
|
|
196
|
+
setupFiles?: string[];
|
|
197
|
+
|
|
164
198
|
/**
|
|
165
199
|
* Array of Dinou plugins.
|
|
166
200
|
*/
|
package/dinou/node/build.mjs
CHANGED
|
@@ -23,7 +23,7 @@ try {
|
|
|
23
23
|
outDir: ".dinou/node",
|
|
24
24
|
});
|
|
25
25
|
|
|
26
|
-
const { dinouDirSlash, externalList, banner, commonAlias, commonLoader, isWebpackBuild } = engineResult;
|
|
26
|
+
const { dinouDirSlash, externalList, banner, commonAlias, commonLoader, isWebpackBuild, setupFiles } = engineResult;
|
|
27
27
|
|
|
28
28
|
// Pass C: Node Orchestrator Entry
|
|
29
29
|
const nodeEntryContent = `// Auto-generated main entry for Node.js (Dual-Bundle)
|
|
@@ -119,12 +119,32 @@ export async function fetch(req) {
|
|
|
119
119
|
|
|
120
120
|
const PORT = Number(process.env.PORT || 3000);
|
|
121
121
|
|
|
122
|
-
|
|
122
|
+
const nodeMiddlewares = [];
|
|
123
|
+
|
|
124
|
+
export async function startServer(port = PORT, host = "0.0.0.0") {
|
|
123
125
|
const server = http.createServer(async (req, res) => {
|
|
124
126
|
try {
|
|
127
|
+
if (res.writableEnded || res.headersSent) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (nodeMiddlewares.length > 0) {
|
|
132
|
+
for (const mw of nodeMiddlewares) {
|
|
133
|
+
let continued = false;
|
|
134
|
+
await mw(req, res, () => {
|
|
135
|
+
continued = true;
|
|
136
|
+
});
|
|
137
|
+
if (!continued || res.writableEnded || res.headersSent) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
125
143
|
const webReq = nodeToWebRequest(req);
|
|
126
144
|
const webRes = await fetch(webReq);
|
|
127
|
-
|
|
145
|
+
if (!res.writableEnded && !res.headersSent) {
|
|
146
|
+
await sendWebResponseToNode(webRes, res);
|
|
147
|
+
}
|
|
128
148
|
} catch (err) {
|
|
129
149
|
console.error("[Dinou Node Server] Request error:", err);
|
|
130
150
|
if (!res.headersSent) {
|
|
@@ -135,6 +155,29 @@ export function startServer(port = PORT, host = "0.0.0.0") {
|
|
|
135
155
|
}
|
|
136
156
|
});
|
|
137
157
|
|
|
158
|
+
try {
|
|
159
|
+
const { getDinouConfig } = await import("${dinouDirSlash}/core/load-dinou-config.js");
|
|
160
|
+
const cfg = await getDinouConfig();
|
|
161
|
+
if (cfg.plugins && Array.isArray(cfg.plugins)) {
|
|
162
|
+
const serverContext = {
|
|
163
|
+
server,
|
|
164
|
+
isDev: false,
|
|
165
|
+
use(middleware) {
|
|
166
|
+
if (typeof middleware === "function") {
|
|
167
|
+
nodeMiddlewares.push(middleware);
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
for (const plugin of cfg.plugins) {
|
|
172
|
+
if (typeof plugin.configureServer === "function") {
|
|
173
|
+
await plugin.configureServer(serverContext);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
} catch (err) {
|
|
178
|
+
console.error("❌ [Dinou Node Server] Error running configureServer plugins:", err);
|
|
179
|
+
}
|
|
180
|
+
|
|
138
181
|
return new Promise((resolve, reject) => {
|
|
139
182
|
server.on("error", reject);
|
|
140
183
|
server.listen(port, () => {
|
|
@@ -146,17 +189,20 @@ export function startServer(port = PORT, host = "0.0.0.0") {
|
|
|
146
189
|
|
|
147
190
|
export default {
|
|
148
191
|
port: PORT,
|
|
149
|
-
fetch,
|
|
150
192
|
startServer,
|
|
151
193
|
};
|
|
152
194
|
|
|
153
|
-
const isMain =
|
|
154
|
-
|
|
155
|
-
(
|
|
195
|
+
const isMain = Boolean(
|
|
196
|
+
(typeof import.meta !== "undefined" && import.meta.main) ||
|
|
197
|
+
(typeof process !== "undefined" &&
|
|
198
|
+
process.argv[1] &&
|
|
199
|
+
(path.resolve(process.argv[1]) === path.resolve(fileURLToPath(import.meta.url))))
|
|
200
|
+
);
|
|
156
201
|
|
|
157
202
|
if (isMain) {
|
|
158
203
|
startServer(PORT);
|
|
159
204
|
}
|
|
205
|
+
|
|
160
206
|
`;
|
|
161
207
|
const nodeEntryPath = path.join(nodeDir, "node-entry.mjs");
|
|
162
208
|
fs.writeFileSync(nodeEntryPath, nodeEntryContent, "utf8");
|
|
@@ -175,6 +221,7 @@ if (isMain) {
|
|
|
175
221
|
conditions: ["node", "worker", "browser"],
|
|
176
222
|
external: [...externalList, "./rsc-engine.mjs", "./ssr-engine.mjs"],
|
|
177
223
|
banner,
|
|
224
|
+
inject: setupFiles,
|
|
178
225
|
alias: commonAlias,
|
|
179
226
|
loader: commonLoader,
|
|
180
227
|
define: {
|
|
@@ -20,6 +20,8 @@ const {
|
|
|
20
20
|
isSupportedClientModule,
|
|
21
21
|
scanProjectDependenciesForClientComponents,
|
|
22
22
|
} = require("../core/scan-dependency-components.js");
|
|
23
|
+
const { getDinouConfig } = require("../core/load-dinou-config.js");
|
|
24
|
+
const { resolveSetupFiles } = require("../core/resolve-setup-files.js");
|
|
23
25
|
|
|
24
26
|
export async function bundleDualEngine(options = {}) {
|
|
25
27
|
const isDev = Boolean(options.isDev);
|
|
@@ -27,6 +29,12 @@ export async function bundleDualEngine(options = {}) {
|
|
|
27
29
|
const nodeDir = path.resolve(projectRoot, options.outDir || ".dinou/node");
|
|
28
30
|
fs.mkdirSync(nodeDir, { recursive: true });
|
|
29
31
|
|
|
32
|
+
const dinouConfig = await getDinouConfig();
|
|
33
|
+
const setupFiles = resolveSetupFiles(projectRoot, dinouConfig);
|
|
34
|
+
if (setupFiles.length > 0) {
|
|
35
|
+
console.log(` 🔌 [Dinou Setup] Active setup files (${setupFiles.length}):`, setupFiles.map((f) => path.relative(projectRoot, f)).join(", "));
|
|
36
|
+
}
|
|
37
|
+
|
|
30
38
|
try {
|
|
31
39
|
generateRouteTypes(projectRoot);
|
|
32
40
|
} catch (e) {}
|
|
@@ -956,6 +964,7 @@ var __webpack_chunk_load__ = function(chunkId) {
|
|
|
956
964
|
conditions: ["node", "worker", "react-server"],
|
|
957
965
|
external: externalList,
|
|
958
966
|
banner,
|
|
967
|
+
inject: setupFiles,
|
|
959
968
|
plugins: [clientReferencesPlugin, serverReferencesPlugin, serverAssetPlugin],
|
|
960
969
|
alias: commonAlias,
|
|
961
970
|
loader: commonLoader,
|
|
@@ -980,6 +989,7 @@ var __webpack_chunk_load__ = function(chunkId) {
|
|
|
980
989
|
conditions: ["node", "worker", "browser"],
|
|
981
990
|
external: externalList,
|
|
982
991
|
banner,
|
|
992
|
+
inject: setupFiles,
|
|
983
993
|
plugins: [serverReferencesPluginSsr, serverAssetPlugin],
|
|
984
994
|
alias: commonAlias,
|
|
985
995
|
loader: commonLoader,
|
|
@@ -1006,6 +1016,7 @@ var __webpack_chunk_load__ = function(chunkId) {
|
|
|
1006
1016
|
commonAlias,
|
|
1007
1017
|
commonLoader,
|
|
1008
1018
|
isWebpackBuild,
|
|
1019
|
+
setupFiles,
|
|
1009
1020
|
};
|
|
1010
1021
|
}
|
|
1011
1022
|
|
package/dinou/node/dev.mjs
CHANGED
|
@@ -76,6 +76,22 @@ const dinouDir = fs.existsSync(path.resolve(projectRoot, "dinou"))
|
|
|
76
76
|
: path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
77
77
|
const dinouDirSlash = dinouDir.replace(/\\/g, "/");
|
|
78
78
|
|
|
79
|
+
// Resolve and execute setupFiles immediately before any compilation
|
|
80
|
+
const { getDinouConfig } = require(path.join(dinouDir, "core/load-dinou-config.js"));
|
|
81
|
+
const { resolveSetupFiles } = require(path.join(dinouDir, "core/resolve-setup-files.js"));
|
|
82
|
+
const dinouConfig = await getDinouConfig();
|
|
83
|
+
const setupFiles = resolveSetupFiles(projectRoot, dinouConfig);
|
|
84
|
+
if (setupFiles.length > 0) {
|
|
85
|
+
console.log(` 🔌 [Dinou Setup] Executing setup files (${setupFiles.length}):`, setupFiles.map((f) => path.relative(projectRoot, f)).join(", "));
|
|
86
|
+
for (const f of setupFiles) {
|
|
87
|
+
try {
|
|
88
|
+
await dynamicImportWithRetry(pathToFileURL(f).href);
|
|
89
|
+
} catch (e) {
|
|
90
|
+
console.error(`❌ [Dinou Dev] Error executing setupFile "${f}":`, e);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
79
95
|
function getFallbackChunkId(absPath) {
|
|
80
96
|
const norm = absPath.replace(/\\/g, "/");
|
|
81
97
|
const name = path.basename(absPath, path.extname(absPath));
|
|
@@ -1463,6 +1479,7 @@ const ctxA = await esbuild.context({
|
|
|
1463
1479
|
conditions: ["node", "worker", "react-server"],
|
|
1464
1480
|
external: externalList,
|
|
1465
1481
|
banner,
|
|
1482
|
+
inject: setupFiles,
|
|
1466
1483
|
plugins: [clientReferencesPlugin, serverReferencesPlugin, serverAssetPlugin, createDevExternalPackagesPlugin(true)],
|
|
1467
1484
|
alias: commonAlias,
|
|
1468
1485
|
loader: commonLoader,
|
|
@@ -1490,6 +1507,7 @@ const ctxB = await esbuild.context({
|
|
|
1490
1507
|
conditions: ["node", "worker", "browser"],
|
|
1491
1508
|
external: externalList,
|
|
1492
1509
|
banner,
|
|
1510
|
+
inject: setupFiles,
|
|
1493
1511
|
plugins: [serverReferencesPluginSsr, serverAssetPlugin, createDevExternalPackagesPlugin(false)],
|
|
1494
1512
|
alias: commonAlias,
|
|
1495
1513
|
loader: commonLoader,
|
|
@@ -2302,9 +2320,52 @@ async function startClientBundler(tool) {
|
|
|
2302
2320
|
throw new Error(`Unsupported DINOU_BUILD_TOOL: ${tool}`);
|
|
2303
2321
|
}
|
|
2304
2322
|
|
|
2323
|
+
// Node.js Middlewares registered by plugins via configureServer
|
|
2324
|
+
const nodeMiddlewares = [];
|
|
2325
|
+
|
|
2326
|
+
async function applyServerPlugins(serverInstance) {
|
|
2327
|
+
try {
|
|
2328
|
+
const { getDinouConfig } = require(path.join(dinouDir, "core/load-dinou-config.js"));
|
|
2329
|
+
const config = await getDinouConfig();
|
|
2330
|
+
if (config.plugins && Array.isArray(config.plugins)) {
|
|
2331
|
+
const serverContext = {
|
|
2332
|
+
server: serverInstance,
|
|
2333
|
+
isDev: true,
|
|
2334
|
+
use(middleware) {
|
|
2335
|
+
if (typeof middleware === "function") {
|
|
2336
|
+
nodeMiddlewares.push(middleware);
|
|
2337
|
+
}
|
|
2338
|
+
},
|
|
2339
|
+
};
|
|
2340
|
+
for (const plugin of config.plugins) {
|
|
2341
|
+
if (typeof plugin.configureServer === "function") {
|
|
2342
|
+
await plugin.configureServer(serverContext);
|
|
2343
|
+
}
|
|
2344
|
+
}
|
|
2345
|
+
}
|
|
2346
|
+
} catch (err) {
|
|
2347
|
+
console.error("❌ [Dinou Dev] Error applying plugin configureServer hooks:", err);
|
|
2348
|
+
}
|
|
2349
|
+
}
|
|
2350
|
+
|
|
2305
2351
|
// HTTP Server
|
|
2306
2352
|
const server = http.createServer(async (req, res) => {
|
|
2307
2353
|
try {
|
|
2354
|
+
if (res.writableEnded || res.headersSent) {
|
|
2355
|
+
return;
|
|
2356
|
+
}
|
|
2357
|
+
|
|
2358
|
+
if (nodeMiddlewares.length > 0) {
|
|
2359
|
+
for (const mw of nodeMiddlewares) {
|
|
2360
|
+
let continued = false;
|
|
2361
|
+
await mw(req, res, () => {
|
|
2362
|
+
continued = true;
|
|
2363
|
+
});
|
|
2364
|
+
if (!continued || res.writableEnded || res.headersSent) {
|
|
2365
|
+
return;
|
|
2366
|
+
}
|
|
2367
|
+
}
|
|
2368
|
+
}
|
|
2308
2369
|
if (clientBundlerPromise) {
|
|
2309
2370
|
await clientBundlerPromise;
|
|
2310
2371
|
}
|
|
@@ -2493,7 +2554,9 @@ const server = http.createServer(async (req, res) => {
|
|
|
2493
2554
|
console.log(`[DEV 404] ${req.method} ${pathname}`);
|
|
2494
2555
|
}
|
|
2495
2556
|
|
|
2496
|
-
|
|
2557
|
+
if (!res.writableEnded && !res.headersSent) {
|
|
2558
|
+
await sendWebResponseToNode(webRes, res);
|
|
2559
|
+
}
|
|
2497
2560
|
} catch (err) {
|
|
2498
2561
|
console.error("[Dinou Dev Server] Request error:", err);
|
|
2499
2562
|
if (!res.headersSent) {
|
|
@@ -2515,6 +2578,8 @@ server.on("error", (err) => {
|
|
|
2515
2578
|
process.exit(1);
|
|
2516
2579
|
});
|
|
2517
2580
|
|
|
2581
|
+
await applyServerPlugins(server);
|
|
2582
|
+
|
|
2518
2583
|
server.listen(PORT, async () => {
|
|
2519
2584
|
const buildTool = isWebpackBuild ? "webpack" : (process.env.DINOU_BUILD_TOOL || "esbuild");
|
|
2520
2585
|
|
package/dinou/package.json
CHANGED
package/eject.js
CHANGED
|
@@ -28,6 +28,50 @@ const ejectedScripts = {
|
|
|
28
28
|
"build:node:esbuild": "npm run build:node",
|
|
29
29
|
"build:node:rollup": "npm run build:client:rollup && node ./dinou/node/build.mjs",
|
|
30
30
|
"build:node:webpack": "npm run build:client:webpack && cross-env DINOU_BUILD_TOOL=webpack node ./dinou/node/build.mjs",
|
|
31
|
+
"build:node:compile": "npm run build:node:compile:esbuild",
|
|
32
|
+
"build:node:compile:esbuild": "npm run build:node:esbuild && bun build --compile .dinou/node/server.mjs --outfile dist/server",
|
|
33
|
+
"build:node:compile:rollup": "npm run build:node:rollup && bun build --compile .dinou/node/server.mjs --outfile dist/server",
|
|
34
|
+
"build:node:compile:webpack": "npm run build:node:webpack && bun build --compile .dinou/node/server.mjs --outfile dist/server",
|
|
35
|
+
"build:node:compile:linux": "npm run build:node:compile:linux:esbuild",
|
|
36
|
+
"build:node:compile:linux:esbuild": "npm run build:node:esbuild && bun build --compile --target=bun-linux-x64 .dinou/node/server.mjs --outfile dist/server-linux",
|
|
37
|
+
"build:node:compile:linux:rollup": "npm run build:node:rollup && bun build --compile --target=bun-linux-x64 .dinou/node/server.mjs --outfile dist/server-linux",
|
|
38
|
+
"build:node:compile:linux:webpack": "npm run build:node:webpack && bun build --compile --target=bun-linux-x64 .dinou/node/server.mjs --outfile dist/server-linux",
|
|
39
|
+
"build:node:compile:linux_arm": "npm run build:node:compile:linux_arm:esbuild",
|
|
40
|
+
"build:node:compile:linux_arm:esbuild": "npm run build:node:esbuild && bun build --compile --target=bun-linux-arm64 .dinou/node/server.mjs --outfile dist/server-linux-arm",
|
|
41
|
+
"build:node:compile:linux_arm:rollup": "npm run build:node:rollup && bun build --compile --target=bun-linux-arm64 .dinou/node/server.mjs --outfile dist/server-linux-arm",
|
|
42
|
+
"build:node:compile:linux_arm:webpack": "npm run build:node:webpack && bun build --compile --target=bun-linux-arm64 .dinou/node/server.mjs --outfile dist/server-linux-arm",
|
|
43
|
+
"build:node:compile:mac": "npm run build:node:compile:mac:esbuild",
|
|
44
|
+
"build:node:compile:mac:esbuild": "npm run build:node:esbuild && bun build --compile --target=bun-darwin-arm64 .dinou/node/server.mjs --outfile dist/server-mac",
|
|
45
|
+
"build:node:compile:mac:rollup": "npm run build:node:rollup && bun build --compile --target=bun-darwin-arm64 .dinou/node/server.mjs --outfile dist/server-mac",
|
|
46
|
+
"build:node:compile:mac:webpack": "npm run build:node:webpack && bun build --compile --target=bun-darwin-arm64 .dinou/node/server.mjs --outfile dist/server-mac",
|
|
47
|
+
"build:node:compile:win": "npm run build:node:compile:win:esbuild",
|
|
48
|
+
"build:node:compile:win:esbuild": "npm run build:node:esbuild && bun build --compile --target=bun-windows-x64 .dinou/node/server.mjs --outfile dist/server-win",
|
|
49
|
+
"build:node:compile:win:rollup": "npm run build:node:rollup && bun build --compile --target=bun-windows-x64 .dinou/node/server.mjs --outfile dist/server-win",
|
|
50
|
+
"build:node:compile:win:webpack": "npm run build:node:webpack && bun build --compile --target=bun-windows-x64 .dinou/node/server.mjs --outfile dist/server-win",
|
|
51
|
+
"build:node:pure": "npm run build:node:pure:esbuild",
|
|
52
|
+
"build:node:pure:esbuild": "cross-env NODE_ENV=production bun dinou/esbuild/build.mjs && bun ./dinou/node/build.mjs",
|
|
53
|
+
"build:node:pure:rollup": "cross-env NODE_ENV=production rollup -c ./dinou/rollup/rollup.config.js && bun ./dinou/node/build.mjs",
|
|
54
|
+
"build:node:pure:webpack": "cross-env NODE_ENV=production webpack --config dinou/webpack/webpack.config.js && cross-env DINOU_BUILD_TOOL=webpack bun ./dinou/node/build.mjs",
|
|
55
|
+
"build:node:pure:compile": "npm run build:node:pure:compile:esbuild",
|
|
56
|
+
"build:node:pure:compile:esbuild": "cross-env NODE_ENV=production bun dinou/esbuild/build.mjs && bun ./dinou/node/build.mjs && bun build --compile .dinou/node/server.mjs --outfile dist/server",
|
|
57
|
+
"build:node:pure:compile:rollup": "cross-env NODE_ENV=production rollup -c ./dinou/rollup/rollup.config.js && bun ./dinou/node/build.mjs && bun build --compile .dinou/node/server.mjs --outfile dist/server",
|
|
58
|
+
"build:node:pure:compile:webpack": "cross-env NODE_ENV=production webpack --config dinou/webpack/webpack.config.js && cross-env DINOU_BUILD_TOOL=webpack bun ./dinou/node/build.mjs && bun build --compile .dinou/node/server.mjs --outfile dist/server",
|
|
59
|
+
"build:node:pure:compile:linux": "npm run build:node:pure:compile:linux:esbuild",
|
|
60
|
+
"build:node:pure:compile:linux:esbuild": "cross-env NODE_ENV=production bun dinou/esbuild/build.mjs && bun ./dinou/node/build.mjs && bun build --compile --target=bun-linux-x64 .dinou/node/server.mjs --outfile dist/server-linux",
|
|
61
|
+
"build:node:pure:compile:linux:rollup": "cross-env NODE_ENV=production rollup -c ./dinou/rollup/rollup.config.js && bun ./dinou/node/build.mjs && bun build --compile --target=bun-linux-x64 .dinou/node/server.mjs --outfile dist/server-linux",
|
|
62
|
+
"build:node:pure:compile:linux:webpack": "cross-env NODE_ENV=production webpack --config dinou/webpack/webpack.config.js && cross-env DINOU_BUILD_TOOL=webpack bun ./dinou/node/build.mjs && bun build --compile --target=bun-linux-x64 .dinou/node/server.mjs --outfile dist/server-linux",
|
|
63
|
+
"build:node:pure:compile:linux_arm": "npm run build:node:pure:compile:linux_arm:esbuild",
|
|
64
|
+
"build:node:pure:compile:linux_arm:esbuild": "cross-env NODE_ENV=production bun dinou/esbuild/build.mjs && bun ./dinou/node/build.mjs && bun build --compile --target=bun-linux-arm64 .dinou/node/server.mjs --outfile dist/server-linux-arm",
|
|
65
|
+
"build:node:pure:compile:linux_arm:rollup": "cross-env NODE_ENV=production rollup -c ./dinou/rollup/rollup.config.js && bun ./dinou/node/build.mjs && bun build --compile --target=bun-linux-arm64 .dinou/node/server.mjs --outfile dist/server-linux-arm",
|
|
66
|
+
"build:node:pure:compile:linux_arm:webpack": "cross-env NODE_ENV=production webpack --config dinou/webpack/webpack.config.js && cross-env DINOU_BUILD_TOOL=webpack bun ./dinou/node/build.mjs && bun build --compile --target=bun-linux-arm64 .dinou/node/server.mjs --outfile dist/server-linux-arm",
|
|
67
|
+
"build:node:pure:compile:mac": "npm run build:node:pure:compile:mac:esbuild",
|
|
68
|
+
"build:node:pure:compile:mac:esbuild": "cross-env NODE_ENV=production bun dinou/esbuild/build.mjs && bun ./dinou/node/build.mjs && bun build --compile --target=bun-darwin-arm64 .dinou/node/server.mjs --outfile dist/server-mac",
|
|
69
|
+
"build:node:pure:compile:mac:rollup": "cross-env NODE_ENV=production rollup -c ./dinou/rollup/rollup.config.js && bun ./dinou/node/build.mjs && bun build --compile --target=bun-darwin-arm64 .dinou/node/server.mjs --outfile dist/server-mac",
|
|
70
|
+
"build:node:pure:compile:mac:webpack": "cross-env NODE_ENV=production webpack --config dinou/webpack/webpack.config.js && cross-env DINOU_BUILD_TOOL=webpack bun ./dinou/node/build.mjs && bun build --compile --target=bun-darwin-arm64 .dinou/node/server.mjs --outfile dist/server-mac",
|
|
71
|
+
"build:node:pure:compile:win": "npm run build:node:pure:compile:win:esbuild",
|
|
72
|
+
"build:node:pure:compile:win:esbuild": "cross-env NODE_ENV=production bun dinou/esbuild/build.mjs && bun ./dinou/node/build.mjs && bun build --compile --target=bun-windows-x64 .dinou/node/server.mjs --outfile dist/server-win",
|
|
73
|
+
"build:node:pure:compile:win:rollup": "cross-env NODE_ENV=production rollup -c ./dinou/rollup/rollup.config.js && bun ./dinou/node/build.mjs && bun build --compile --target=bun-windows-x64 .dinou/node/server.mjs --outfile dist/server-win",
|
|
74
|
+
"build:node:pure:compile:win:webpack": "cross-env NODE_ENV=production webpack --config dinou/webpack/webpack.config.js && cross-env DINOU_BUILD_TOOL=webpack bun ./dinou/node/build.mjs && bun build --compile --target=bun-windows-x64 .dinou/node/server.mjs --outfile dist/server-win",
|
|
31
75
|
"start:node": "cross-env NODE_ENV=production node dinou/adapters/node.mjs",
|
|
32
76
|
"start:node:esbuild": "npm run start:node",
|
|
33
77
|
"start:node:rollup": "npm run start:node",
|
|
@@ -146,7 +190,7 @@ function detectPackageManager() {
|
|
|
146
190
|
|
|
147
191
|
if (fs.existsSync(path.join(projectRoot, "yarn.lock"))) return "yarn";
|
|
148
192
|
if (fs.existsSync(path.join(projectRoot, "pnpm-lock.yaml"))) return "pnpm";
|
|
149
|
-
if (fs.existsSync(path.join(projectRoot, "bun.lockb"))) return "bun";
|
|
193
|
+
if (fs.existsSync(path.join(projectRoot, "bun.lockb")) || fs.existsSync(path.join(projectRoot, "bun.lock"))) return "bun";
|
|
150
194
|
if (fs.existsSync(path.join(projectRoot, "package-lock.json"))) return "npm";
|
|
151
195
|
|
|
152
196
|
return "npm";
|
package/package.json
CHANGED
|
@@ -1,267 +0,0 @@
|
|
|
1
|
-
const fs = require("fs");
|
|
2
|
-
const path = require("path");
|
|
3
|
-
const { transformAsync } = require("@babel/core");
|
|
4
|
-
const { fileURLToPath, pathToFileURL } = require("url");
|
|
5
|
-
const createScopedName = require("./createScopedName");
|
|
6
|
-
const { extensionsWithDot } = require("./asset-extensions.js");
|
|
7
|
-
const { getAbsPathWithExt } = require("./get-abs-path-with-ext.js");
|
|
8
|
-
|
|
9
|
-
const { normalizePathCase } = require("./path-utils.js");
|
|
10
|
-
|
|
11
|
-
const Module = require("module");
|
|
12
|
-
const originalResolveFilename = Module._resolveFilename;
|
|
13
|
-
const isWebpack = process.env.DINOU_BUILD_TOOL === "webpack";
|
|
14
|
-
|
|
15
|
-
let reactServerPath, reactDomServerPath, reactJsxRuntimePath, reactJsxDevRuntimePath;
|
|
16
|
-
|
|
17
|
-
const reactPkgJson = require.resolve("react/package.json");
|
|
18
|
-
reactServerPath = path.join(path.dirname(reactPkgJson), "react.react-server.js");
|
|
19
|
-
reactJsxRuntimePath = path.join(path.dirname(reactPkgJson), "jsx-runtime.react-server.js");
|
|
20
|
-
reactJsxDevRuntimePath = path.join(path.dirname(reactPkgJson), "jsx-dev-runtime.react-server.js");
|
|
21
|
-
|
|
22
|
-
const reactDomPkgJson = require.resolve("react-dom/package.json");
|
|
23
|
-
reactDomServerPath = path.join(path.dirname(reactDomPkgJson), "react-dom.react-server.js");
|
|
24
|
-
|
|
25
|
-
let roggcServerNodePath, webpackServerNodePath;
|
|
26
|
-
try {
|
|
27
|
-
const roggcPkg = require.resolve("@roggc/react-server-dom-esm/package.json");
|
|
28
|
-
roggcServerNodePath = path.join(path.dirname(roggcPkg), "server.node.js");
|
|
29
|
-
} catch (e) {}
|
|
30
|
-
|
|
31
|
-
try {
|
|
32
|
-
const wpPkg = require.resolve("react-server-dom-webpack/package.json");
|
|
33
|
-
webpackServerNodePath = path.join(path.dirname(wpPkg), "server.node.js");
|
|
34
|
-
} catch (e) {}
|
|
35
|
-
|
|
36
|
-
Module._resolveFilename = function (request, parent, isMain, options) {
|
|
37
|
-
if (request === "react") {
|
|
38
|
-
return reactServerPath;
|
|
39
|
-
} else if (request === "react-dom") {
|
|
40
|
-
return reactDomServerPath;
|
|
41
|
-
} else if (request === "react/jsx-runtime") {
|
|
42
|
-
return reactJsxRuntimePath;
|
|
43
|
-
} else if (request === "react/jsx-dev-runtime") {
|
|
44
|
-
return reactJsxDevRuntimePath;
|
|
45
|
-
} else if (request === "@roggc/react-server-dom-esm/server" && roggcServerNodePath) {
|
|
46
|
-
return roggcServerNodePath;
|
|
47
|
-
} else if (request === "react-server-dom-webpack/server" && webpackServerNodePath) {
|
|
48
|
-
return webpackServerNodePath;
|
|
49
|
-
}
|
|
50
|
-
return originalResolveFilename.call(this, request, parent, isMain, options);
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
require("./css-require-hook.js")();
|
|
54
|
-
|
|
55
|
-
function getMtimeParam(absPath) {
|
|
56
|
-
try {
|
|
57
|
-
const stats = fs.statSync(absPath);
|
|
58
|
-
return Math.round(stats.mtimeMs);
|
|
59
|
-
} catch (e) {
|
|
60
|
-
return Date.now();
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
exports.resolve = async function resolve(specifier, context, defaultResolve) {
|
|
65
|
-
if (process.env.DINOU_PROCESS !== "ssr-html") {
|
|
66
|
-
if (specifier === "react") {
|
|
67
|
-
return { url: pathToFileURL(reactServerPath).href, shortCircuit: true };
|
|
68
|
-
}
|
|
69
|
-
if (specifier === "react/jsx-runtime") {
|
|
70
|
-
return { url: pathToFileURL(reactJsxRuntimePath).href, shortCircuit: true };
|
|
71
|
-
}
|
|
72
|
-
if (specifier === "react/jsx-dev-runtime") {
|
|
73
|
-
return { url: pathToFileURL(reactJsxDevRuntimePath).href, shortCircuit: true };
|
|
74
|
-
}
|
|
75
|
-
if (specifier === "react-dom") {
|
|
76
|
-
return { url: pathToFileURL(reactDomServerPath).href, shortCircuit: true };
|
|
77
|
-
}
|
|
78
|
-
if (specifier === "@roggc/react-server-dom-esm/server" && roggcServerNodePath) {
|
|
79
|
-
return { url: pathToFileURL(roggcServerNodePath).href, shortCircuit: true };
|
|
80
|
-
}
|
|
81
|
-
if (specifier === "react-server-dom-webpack/server" && webpackServerNodePath) {
|
|
82
|
-
return { url: pathToFileURL(webpackServerNodePath).href, shortCircuit: true };
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const absPathWithExt = getAbsPathWithExt(specifier, context);
|
|
87
|
-
if (absPathWithExt) {
|
|
88
|
-
let url = pathToFileURL(absPathWithExt).href;
|
|
89
|
-
if (process.env.NODE_ENV !== "production") {
|
|
90
|
-
url += `?mtime=${getMtimeParam(absPathWithExt)}`;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return {
|
|
94
|
-
url,
|
|
95
|
-
shortCircuit: true,
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Fallback to default resolver
|
|
100
|
-
return defaultResolve(specifier, context, defaultResolve);
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
exports.load = async function load(url, context, defaultLoad) {
|
|
104
|
-
// --- 🟢 Handle non-JS assets (png, jpg, etc.)
|
|
105
|
-
const assetExts = extensionsWithDot;
|
|
106
|
-
const ext = path.extname(url.split("?")[0]); // remove search params if any
|
|
107
|
-
|
|
108
|
-
if (assetExts.includes(ext)) {
|
|
109
|
-
// Return a tiny stub that mimics what asset-require-hook would do
|
|
110
|
-
const filepath = fileURLToPath(url.split("?")[0]);
|
|
111
|
-
const localName = path.basename(filepath, ext);
|
|
112
|
-
const hashedName = createScopedName(localName, filepath);
|
|
113
|
-
const virtualExport = `export default "/assets/${hashedName}${ext}";`;
|
|
114
|
-
|
|
115
|
-
return {
|
|
116
|
-
format: "module",
|
|
117
|
-
source: virtualExport,
|
|
118
|
-
shortCircuit: true,
|
|
119
|
-
url,
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (ext === ".css") {
|
|
124
|
-
const mod = require(fileURLToPath(url.split("?")[0]));
|
|
125
|
-
const source = `export default ${JSON.stringify(mod)};`;
|
|
126
|
-
return { format: "module", source, shortCircuit: true, url };
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
const cleanUrl = url.split("?")[0];
|
|
130
|
-
if (/\.(jsx|tsx|ts|js)$/.test(cleanUrl)) {
|
|
131
|
-
let filename;
|
|
132
|
-
try {
|
|
133
|
-
filename = fileURLToPath(
|
|
134
|
-
cleanUrl.startsWith("file://") ? cleanUrl : pathToFileURL(cleanUrl).href
|
|
135
|
-
);
|
|
136
|
-
} catch (e) {
|
|
137
|
-
throw e;
|
|
138
|
-
}
|
|
139
|
-
const rel = path.relative(
|
|
140
|
-
normalizePathCase(process.cwd()),
|
|
141
|
-
normalizePathCase(filename)
|
|
142
|
-
);
|
|
143
|
-
const source = fs.readFileSync(filename, "utf-8");
|
|
144
|
-
const urlToReturn = pathToFileURL(filename).href;
|
|
145
|
-
|
|
146
|
-
const useClientRegex =
|
|
147
|
-
/^\s*(?:(?:\/\/[^\n]*\n\s*)|(?:\/\*[\s\S]*?\*\/\s*))*['"]use client['"]/;
|
|
148
|
-
const hasUseClient = useClientRegex.test(source);
|
|
149
|
-
|
|
150
|
-
const esmSyntaxRegex = /^(?:import|export)\b/m;
|
|
151
|
-
const hasESMSyntax = esmSyntaxRegex.test(source);
|
|
152
|
-
|
|
153
|
-
if (ext === ".js" && !rel.startsWith("src" + path.sep) && !hasESMSyntax) {
|
|
154
|
-
return defaultLoad(url, context, defaultLoad);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const isReactServer = process.env.DINOU_PROCESS !== "ssr-html";
|
|
158
|
-
if (isReactServer && hasUseClient) {
|
|
159
|
-
const parseExports = require("./parse-exports.js");
|
|
160
|
-
const exports = parseExports(source);
|
|
161
|
-
const clientPkgPath = isWebpack
|
|
162
|
-
? require.resolve("react-server-dom-webpack/package.json")
|
|
163
|
-
: require.resolve("@roggc/react-server-dom-esm/package.json");
|
|
164
|
-
const clientServerNodePath = path.join(path.dirname(clientPkgPath), "server.node.js");
|
|
165
|
-
const clientServerNodeUrl = pathToFileURL(clientServerNodePath).href;
|
|
166
|
-
let newSrc = `import pkg from ${JSON.stringify(clientServerNodeUrl)};\n`;
|
|
167
|
-
newSrc += 'const {registerClientReference} = pkg;\n';
|
|
168
|
-
for (const name of exports) {
|
|
169
|
-
if (name === 'default') {
|
|
170
|
-
newSrc += 'export default ';
|
|
171
|
-
newSrc += 'registerClientReference(function() {';
|
|
172
|
-
newSrc += 'throw new Error(' + JSON.stringify("Attempted to call the default export of " + urlToReturn + " from the server but it's on the client.") + ');';
|
|
173
|
-
newSrc += '},';
|
|
174
|
-
newSrc += JSON.stringify(urlToReturn) + ',';
|
|
175
|
-
newSrc += JSON.stringify(name) + ');\n';
|
|
176
|
-
} else {
|
|
177
|
-
newSrc += 'export const ' + name + ' = ';
|
|
178
|
-
newSrc += 'registerClientReference(function() {';
|
|
179
|
-
newSrc += 'throw new Error(' + JSON.stringify("Attempted to call " + name + "() from the server but " + name + " is on the client.") + ');';
|
|
180
|
-
newSrc += '},';
|
|
181
|
-
newSrc += JSON.stringify(urlToReturn) + ',';
|
|
182
|
-
newSrc += JSON.stringify(name) + ');\n';
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
return {
|
|
186
|
-
format: "module",
|
|
187
|
-
source: newSrc,
|
|
188
|
-
shortCircuit: true,
|
|
189
|
-
url,
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const { useServerRegex } = require("../constants.js");
|
|
194
|
-
const hasUseServer = useServerRegex.test(source);
|
|
195
|
-
|
|
196
|
-
if (isReactServer && hasUseServer) {
|
|
197
|
-
const parseExports = require("./parse-exports.js");
|
|
198
|
-
const exports = parseExports(source);
|
|
199
|
-
|
|
200
|
-
const { code } = await transformAsync(source, {
|
|
201
|
-
filename,
|
|
202
|
-
presets: [
|
|
203
|
-
["@babel/preset-react", { runtime: "automatic" }],
|
|
204
|
-
"@babel/preset-typescript",
|
|
205
|
-
],
|
|
206
|
-
sourceMaps: "inline",
|
|
207
|
-
ast: false,
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
let newSrc = code + "\n\n";
|
|
211
|
-
|
|
212
|
-
const serverPkgPath = isWebpack
|
|
213
|
-
? require.resolve("react-server-dom-webpack/package.json")
|
|
214
|
-
: require.resolve("@roggc/react-server-dom-esm/package.json");
|
|
215
|
-
const serverNodePath = path.join(path.dirname(serverPkgPath), "server.node.js");
|
|
216
|
-
const serverNodeUrl = pathToFileURL(serverNodePath).href;
|
|
217
|
-
newSrc += `import pkgServer from ${JSON.stringify(serverNodeUrl)};\n`;
|
|
218
|
-
newSrc += 'const {registerServerReference} = pkgServer;\n';
|
|
219
|
-
|
|
220
|
-
const relativeFileUrl = "file:///" + rel.replace(/\\/g, "/");
|
|
221
|
-
for (const name of exports) {
|
|
222
|
-
if (name !== 'default') {
|
|
223
|
-
newSrc += `registerServerReference(${name}, ${JSON.stringify(relativeFileUrl)}, ${JSON.stringify(name)});\n`;
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
return {
|
|
228
|
-
format: "module",
|
|
229
|
-
source: newSrc,
|
|
230
|
-
shortCircuit: true,
|
|
231
|
-
url,
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
if (ext === ".js") {
|
|
236
|
-
return {
|
|
237
|
-
format: "module",
|
|
238
|
-
source,
|
|
239
|
-
shortCircuit: true,
|
|
240
|
-
url,
|
|
241
|
-
};
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
const { code } = await transformAsync(source, {
|
|
245
|
-
filename,
|
|
246
|
-
presets: [
|
|
247
|
-
["@babel/preset-react", { runtime: "automatic" }],
|
|
248
|
-
"@babel/preset-typescript",
|
|
249
|
-
],
|
|
250
|
-
sourceMaps: "inline",
|
|
251
|
-
ast: false,
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
// const urlToReturn = pathToFileURL(filename).href;
|
|
255
|
-
|
|
256
|
-
return {
|
|
257
|
-
format: "module",
|
|
258
|
-
source: code,
|
|
259
|
-
shortCircuit: true,
|
|
260
|
-
url,
|
|
261
|
-
};
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
if (url) {
|
|
265
|
-
return defaultLoad(url, context, defaultLoad);
|
|
266
|
-
}
|
|
267
|
-
};
|