dinou 6.1.1 → 7.0.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.
Files changed (135) hide show
  1. package/CHANGELOG.md +94 -0
  2. package/README.md +9461 -1080
  3. package/cli.js +392 -169
  4. package/dinou/adapters/bun.js +62 -0
  5. package/dinou/adapters/cloudflare.js +65 -0
  6. package/dinou/adapters/deno.js +48 -0
  7. package/dinou/adapters/netlify.js +85 -0
  8. package/dinou/adapters/node.mjs +31 -0
  9. package/dinou/bun/build.mjs +1077 -0
  10. package/dinou/cloudflare/build.mjs +1121 -0
  11. package/dinou/cloudflare/shims/child_process.js +14 -0
  12. package/dinou/cloudflare/shims/empty.js +2 -0
  13. package/dinou/cloudflare/shims/fs.js +99 -0
  14. package/dinou/cloudflare/shims/os.js +29 -0
  15. package/dinou/config.js +1 -0
  16. package/dinou/config.mjs +2 -0
  17. package/dinou/constants.js +29 -4
  18. package/dinou/core/babel-esm-loader.js +66 -37
  19. package/dinou/core/bailout-proxy.js +61 -0
  20. package/dinou/core/build-static-pages.js +309 -157
  21. package/dinou/core/cache-revalidate.js +471 -144
  22. package/dinou/core/cache-slot.js +387 -0
  23. package/dinou/core/client-redirect.jsx +12 -7
  24. package/dinou/core/client-webpack.jsx +457 -82
  25. package/dinou/core/client.jsx +452 -82
  26. package/dinou/core/config.js +11 -0
  27. package/dinou/core/dinou-paths.js +52 -0
  28. package/dinou/core/edge-ssr.js +122 -0
  29. package/dinou/core/export-static.mjs +64 -0
  30. package/dinou/core/generate-route-types.js +252 -0
  31. package/dinou/core/generate-static-page.js +55 -94
  32. package/dinou/core/generate-static-rsc.js +47 -15
  33. package/dinou/core/generate-static.js +212 -10
  34. package/dinou/core/generating-isg.js +5 -0
  35. package/dinou/core/get-asset-from-manifest.js +9 -3
  36. package/dinou/core/get-error-jsx.js +221 -41
  37. package/dinou/core/get-file-path-and-dynamic-params.js +9 -13
  38. package/dinou/core/get-jsx.js +172 -95
  39. package/dinou/core/handler.js +2296 -0
  40. package/dinou/core/http-adapter.js +115 -0
  41. package/dinou/core/import-module.js +83 -53
  42. package/dinou/core/layout-functions.js +181 -0
  43. package/dinou/core/link.jsx +18 -6
  44. package/dinou/core/load-dinou-config.js +60 -0
  45. package/dinou/core/manifest-provider.js +261 -0
  46. package/dinou/core/navigation-utils.js +4 -0
  47. package/dinou/core/navigation.js +50 -39
  48. package/dinou/core/parse-exports.js +207 -2
  49. package/dinou/core/ppr-context.js +105 -0
  50. package/dinou/core/ppr-runtime.js +263 -0
  51. package/dinou/core/redirect.jsx +20 -19
  52. package/dinou/core/render-jsx-to-client-jsx.js +133 -15
  53. package/dinou/core/request-context.js +47 -13
  54. package/dinou/core/resolve-module-ppr.js +32 -0
  55. package/dinou/core/revalidating.js +28 -9
  56. package/dinou/core/route-generator.js +107 -0
  57. package/dinou/core/rsc-renderer.js +90 -0
  58. package/dinou/core/run-ssg.js +19 -0
  59. package/dinou/core/scan-dependency-components.js +218 -0
  60. package/dinou/core/server-function-proxy-webpack.js +3 -0
  61. package/dinou/core/server-function-proxy.js +3 -0
  62. package/dinou/core/slot.js +302 -0
  63. package/dinou/core/status-manifest.js +41 -1
  64. package/dinou/core/storage-adapter.js +522 -0
  65. package/dinou/core/url-resolver.js +16 -16
  66. package/dinou/core/vfs.js +139 -68
  67. package/dinou/deno/build.mjs +1112 -0
  68. package/dinou/deno/seed-kv.js +115 -0
  69. package/dinou/esbuild/build.mjs +51 -1
  70. package/dinou/esbuild/dev.mjs +290 -224
  71. package/dinou/esbuild/helpers-esbuild/get-config-esbuild-prod.mjs +3 -2
  72. package/dinou/esbuild/helpers-esbuild/get-config-esbuild.mjs +104 -16
  73. package/dinou/esbuild/helpers-esbuild/get-esbuild-entries.mjs +31 -19
  74. package/dinou/esbuild/helpers-esbuild/strip-namespace.mjs +9 -0
  75. package/dinou/esbuild/helpers-esbuild/swc-disk-cache.mjs +225 -0
  76. package/dinou/esbuild/helpers-esbuild/update-manifest-for-module.mjs +7 -0
  77. package/dinou/esbuild/helpers-esbuild/write.mjs +111 -2
  78. package/dinou/esbuild/plugins-esbuild/assets-plugin.mjs +236 -161
  79. package/dinou/esbuild/plugins-esbuild/css-processor-plugin.mjs +101 -5
  80. package/dinou/esbuild/plugins-esbuild/react-client-manifest-plugin.mjs +63 -24
  81. package/dinou/esbuild/plugins-esbuild/server-functions-plugin.mjs +177 -56
  82. package/dinou/esbuild/plugins-esbuild/skip-missing-entry-points-plugin.mjs +3 -0
  83. package/dinou/esbuild/plugins-esbuild/stable-chunk-names-and-maps-plugin.mjs +182 -137
  84. package/dinou/esbuild/plugins-postcss/postcss-extract-plugin.js +38 -11
  85. package/dinou/esbuild/react-refresh/esm-hmr/client.mjs +55 -8
  86. package/dinou/esbuild/react-refresh/esm-hmr/server.js +1 -1
  87. package/dinou/esbuild/react-refresh/esm-hmr-plugin.mjs +238 -101
  88. package/dinou/esbuild/react-refresh/is-react-refresh-boundary.mjs +18 -4
  89. package/dinou/index.d.ts +315 -11
  90. package/dinou/index.js +12 -6
  91. package/dinou/index.mjs +9 -0
  92. package/dinou/node/build.mjs +195 -0
  93. package/dinou/node/bundle-dual-engine.mjs +1012 -0
  94. package/dinou/node/dev.mjs +2589 -0
  95. package/dinou/node/port-selector.mjs +164 -0
  96. package/dinou/node/terminal-status.mjs +345 -0
  97. package/dinou/package.json +16 -14
  98. package/dinou/rollup/react-refresh/esm-hmr/client.js +66 -10
  99. package/dinou/rollup/react-refresh/esm-hmr/server.js +1 -1
  100. package/dinou/rollup/react-refresh/is-react-refresh-boundary.js +24 -5
  101. package/dinou/rollup/react-refresh/react-refresh-runtime.js +13 -6
  102. package/dinou/rollup/react-refresh/react-refresh-wrap-modules.js +56 -11
  103. package/dinou/rollup/react-refresh/rollup-plugin-esm-hmr.js +176 -48
  104. package/dinou/rollup/rollup-plugins/dinou-asset-plugin.js +9 -5
  105. package/dinou/rollup/rollup-plugins/rollup-plugin-memory.js +66 -0
  106. package/dinou/rollup/rollup-plugins/rollup-plugin-react-client-manifest.js +468 -123
  107. package/dinou/rollup/rollup-plugins/rollup-plugin-server-functions.js +44 -12
  108. package/dinou/rollup/rollup-plugins/rollup-plugin-swc.js +100 -0
  109. package/dinou/rollup/rollup.config.js +155 -43
  110. package/dinou/server.d.ts +114 -12
  111. package/dinou/server.js +35 -10
  112. package/dinou/server.mjs +30 -9
  113. package/dinou/webpack/helpers/get-webpack-entries.js +14 -19
  114. package/dinou/webpack/loaders/server-functions-loader.js +22 -1
  115. package/dinou/webpack/loaders/swc-loader.js +76 -0
  116. package/dinou/webpack/plugins/manifest-generator-plugin.js +1 -0
  117. package/dinou/webpack/plugins/server-functions-plugin.js +75 -19
  118. package/dinou/webpack/plugins/webpack-memory-plugin.js +66 -0
  119. package/dinou/webpack/webpack.config.js +227 -29
  120. package/eject.js +173 -94
  121. package/package.json +110 -108
  122. package/dinou/core/asset-require-hook.js +0 -58
  123. package/dinou/core/client-error-webpack.jsx +0 -432
  124. package/dinou/core/client-error.jsx +0 -432
  125. package/dinou/core/concurrency-manager.js +0 -48
  126. package/dinou/core/context-proxy.js +0 -68
  127. package/dinou/core/generate-static-pages.js +0 -130
  128. package/dinou/core/generate-static-rscs.js +0 -151
  129. package/dinou/core/get-ssg-metadata.js +0 -31
  130. package/dinou/core/register-loader.mjs +0 -11
  131. package/dinou/core/register-paths.js +0 -27
  132. package/dinou/core/render-app-to-html.js +0 -430
  133. package/dinou/core/render-html.js +0 -407
  134. package/dinou/core/server.js +0 -1542
  135. package/dinou/esbuild/plugins-esbuild/write-metafile-plugin.mjs +0 -16
@@ -0,0 +1,164 @@
1
+ // dinou/node/port-selector.mjs
2
+ // Interactive development port detection and fallback for Dinou.
3
+ // Ensures dual consecutive free ports (HTTP server + HMR / WebSocket server)
4
+ // across all supported bundlers (esbuild, rollup, webpack).
5
+
6
+ import net from "node:net";
7
+ import readline from "node:readline";
8
+
9
+ const C_RESET = "\x1b[0m";
10
+ const C_BOLD = "\x1b[1m";
11
+ const C_DIM = "\x1b[90m";
12
+ const C_CYAN = "\x1b[36m";
13
+ const C_GREEN = "\x1b[32m";
14
+ const C_YELLOW = "\x1b[33m";
15
+ const C_RED = "\x1b[31m";
16
+
17
+ /**
18
+ * Checks if a TCP port is currently free on both default and IPv4 loopback.
19
+ * @param {number} port
20
+ * @returns {Promise<boolean>}
21
+ */
22
+ export function isPortAvailable(port) {
23
+ return new Promise((resolve) => {
24
+ // 1. Try active connection to 127.0.0.1
25
+ const client = net.connect({ port, host: "127.0.0.1" });
26
+ client.once("connect", () => {
27
+ client.destroy();
28
+ resolve(false);
29
+ });
30
+ client.once("error", () => {
31
+ client.destroy();
32
+ // 2. Try listening on default host
33
+ const s1 = net.createServer();
34
+ s1.unref();
35
+ s1.once("error", () => resolve(false));
36
+ s1.once("listening", () => {
37
+ s1.close(() => {
38
+ // 3. Try listening specifically on 127.0.0.1
39
+ const s2 = net.createServer();
40
+ s2.unref();
41
+ s2.once("error", () => resolve(false));
42
+ s2.once("listening", () => {
43
+ s2.close(() => resolve(true));
44
+ });
45
+ s2.listen(port, "127.0.0.1");
46
+ });
47
+ });
48
+ s1.listen(port);
49
+ });
50
+ });
51
+ }
52
+
53
+ /**
54
+ * Checks if both server port and companion HMR port are available.
55
+ * @param {number} serverPort
56
+ * @param {number} hmrPort
57
+ * @returns {Promise<boolean>}
58
+ */
59
+ export async function arePortsAvailable(serverPort, hmrPort) {
60
+ const isServerFree = await isPortAvailable(serverPort);
61
+ if (!isServerFree) return false;
62
+ const isHmrFree = await isPortAvailable(hmrPort);
63
+ return isHmrFree;
64
+ }
65
+
66
+ /**
67
+ * Finds the next available pair of consecutive ports [P, P+1].
68
+ * Keeps even/odd parity so HTTP servers remain on even ports.
69
+ * @param {number} startPort
70
+ * @returns {Promise<number>}
71
+ */
72
+ export async function findAvailablePortPair(startPort = 3000) {
73
+ let current = startPort;
74
+ while (current < 65534) {
75
+ if (await arePortsAvailable(current, current + 1)) {
76
+ return current;
77
+ }
78
+ current += current % 2 === 0 ? 2 : 1;
79
+ }
80
+ throw new Error("No available port pair found");
81
+ }
82
+
83
+ /**
84
+ * Prompts the user interactively in the terminal via readline.
85
+ * @param {string} question
86
+ * @returns {Promise<boolean>}
87
+ */
88
+ function promptUser(question) {
89
+ return new Promise((resolve) => {
90
+ const rl = readline.createInterface({
91
+ input: process.stdin,
92
+ output: process.stdout,
93
+ });
94
+
95
+ rl.on("SIGINT", () => {
96
+ rl.close();
97
+ console.log(`\n\n ${C_RED}❌ Server startup aborted by user.${C_RESET}\n`);
98
+ process.exit(0);
99
+ });
100
+
101
+ rl.question(question, (answer) => {
102
+ rl.close();
103
+ const trimmed = answer.trim().toLowerCase();
104
+ if (trimmed === "" || trimmed === "y" || trimmed === "yes") {
105
+ resolve(true);
106
+ } else {
107
+ resolve(false);
108
+ }
109
+ });
110
+ });
111
+ }
112
+
113
+ /**
114
+ * Resolves dev server ports.
115
+ * In development, if the target port (or HMR port) is in use:
116
+ * - In interactive TTY: prompts the user to switch to the next consecutive free port pair.
117
+ * - In non-interactive environments (CI, scripts): exits immediately with an error.
118
+ * @returns {Promise<{ port: number, hmrPort: number }>}
119
+ */
120
+ export async function resolveDevPorts() {
121
+ const requestedPort = Number(process.env.PORT || 3000);
122
+ const requestedHmrPort = Number(process.env.HMR_PORT || (requestedPort + 1));
123
+
124
+ const isServerFree = await isPortAvailable(requestedPort);
125
+ const isHmrFree = await isPortAvailable(requestedHmrPort);
126
+
127
+ if (isServerFree && isHmrFree) {
128
+ process.env.PORT = String(requestedPort);
129
+ process.env.HMR_PORT = String(requestedHmrPort);
130
+ return { port: requestedPort, hmrPort: requestedHmrPort };
131
+ }
132
+
133
+ const busyPort = !isServerFree ? requestedPort : requestedHmrPort;
134
+
135
+ // Non-interactive environments (CI, pipes) cannot prompt user
136
+ const isInteractive = Boolean(
137
+ (process.stdout.isTTY || process.env.DINOU_FORCE_INTERACTIVE === "true") &&
138
+ !process.env.CI &&
139
+ process.env.TERM !== "dumb"
140
+ );
141
+
142
+ if (!isInteractive) {
143
+ console.error(`\n❌ FATAL ERROR: Port ${busyPort} is already in use!\n`);
144
+ process.exit(1);
145
+ }
146
+
147
+ // Find next consecutive pair (e.g. 3002 & 3003)
148
+ const fallbackPort = await findAvailablePortPair(requestedPort + 2);
149
+ const fallbackHmrPort = fallbackPort + 1;
150
+
151
+ const confirmed = await promptUser(
152
+ `\n ${C_YELLOW}⚠️ Port ${busyPort} is in use.${C_RESET}\n ${C_BOLD}? Would you like to use port ${fallbackPort} instead?${C_RESET} ${C_DIM}(Y/n)${C_RESET} `
153
+ );
154
+
155
+ if (!confirmed) {
156
+ console.log(`\n ${C_RED}❌ Server startup aborted by user.${C_RESET}\n`);
157
+ process.exit(0);
158
+ }
159
+
160
+ console.log(`\n ${C_GREEN}➜${C_RESET} ${C_BOLD}Using port:${C_RESET} ${C_CYAN}${fallbackPort}${C_RESET} ${C_DIM}(HMR: ${fallbackHmrPort})${C_RESET}\n`);
161
+ process.env.PORT = String(fallbackPort);
162
+ process.env.HMR_PORT = String(fallbackHmrPort);
163
+ return { port: fallbackPort, hmrPort: fallbackHmrPort };
164
+ }
@@ -0,0 +1,345 @@
1
+ // dinou/node/terminal-status.mjs
2
+ // Lightweight terminal status & animated spinner for Dinou Development Server.
3
+ // Zero external dependencies. Fully TTY-aware and safe for CI/Playwright.
4
+
5
+ import readline from "node:readline";
6
+
7
+ export const isTTY = Boolean(
8
+ process.stdout.isTTY && !process.env.CI && process.env.TERM !== "dumb"
9
+ );
10
+
11
+ const FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
12
+ const C_RESET = "\x1b[0m";
13
+ const C_BOLD = "\x1b[1m";
14
+ const C_DIM = "\x1b[90m";
15
+ const C_CYAN = "\x1b[36m";
16
+ const C_GREEN = "\x1b[32m";
17
+ const C_YELLOW = "\x1b[33m";
18
+ const C_MAGENTA = "\x1b[35m";
19
+
20
+ export function getTerminalCols() {
21
+ if (process.stdout.isTTY) {
22
+ if (typeof process.stdout._refreshSize === "function") {
23
+ try {
24
+ process.stdout._refreshSize();
25
+ } catch (e) {}
26
+ }
27
+ if (typeof process.stdout.getWindowSize === "function") {
28
+ try {
29
+ const [w] = process.stdout.getWindowSize();
30
+ if (w > 0) return w;
31
+ } catch (e) {}
32
+ }
33
+ return process.stdout.columns || 80;
34
+ }
35
+ return 80;
36
+ }
37
+
38
+ let active = false;
39
+ let frameIdx = 0;
40
+ let currentText = "";
41
+ let timer = null;
42
+ let isWatching = false;
43
+
44
+ // Intercept stdout/stderr writes so normal logs don't collide with the spinner line
45
+ let hooked = false;
46
+ const originalStdoutWrite = process.stdout.write.bind(process.stdout);
47
+ const originalStderrWrite = process.stderr.write.bind(process.stderr);
48
+
49
+ function hookStreams() {
50
+ if (hooked || !isTTY) return;
51
+ hooked = true;
52
+
53
+ process.stdout.write = function (chunk, encoding, callback) {
54
+ if (active) {
55
+ originalStdoutWrite("\r\x1b[2K");
56
+ }
57
+ const result = originalStdoutWrite(chunk, encoding, callback);
58
+ if (active) {
59
+ render();
60
+ }
61
+ return result;
62
+ };
63
+
64
+ process.stderr.write = function (chunk, encoding, callback) {
65
+ if (active) {
66
+ originalStdoutWrite("\r\x1b[2K");
67
+ }
68
+ const result = originalStderrWrite(chunk, encoding, callback);
69
+ if (active) {
70
+ render();
71
+ }
72
+ return result;
73
+ };
74
+ }
75
+
76
+ function render() {
77
+ if (!active || !isTTY) return;
78
+ const cols = getTerminalCols();
79
+ if (cols <= 0) return;
80
+ if (cols < 8) {
81
+ const frame = FRAMES[frameIdx];
82
+ originalStdoutWrite(`\r\x1b[2K${frame}\x1b[K\x1b[J`);
83
+ return;
84
+ }
85
+ const maxTextLen = Math.max(1, cols - 6);
86
+ let text = currentText;
87
+ if (text.length > maxTextLen) {
88
+ text = text.slice(0, Math.max(1, maxTextLen - 3)) + "...";
89
+ }
90
+ const frame = FRAMES[frameIdx];
91
+ const line = `\r\x1b[2K ${C_CYAN}${C_BOLD}${frame}${C_RESET} ${text}\x1b[K\x1b[J`;
92
+ originalStdoutWrite(line);
93
+ }
94
+
95
+ export function startSpinner(text) {
96
+ if (!isTTY) return;
97
+ hookStreams();
98
+ currentText = text;
99
+ active = true;
100
+ frameIdx = 0;
101
+ if (!timer) {
102
+ timer = setInterval(() => {
103
+ frameIdx = (frameIdx + 1) % FRAMES.length;
104
+ render();
105
+ }, 80);
106
+ timer.unref();
107
+ }
108
+ render();
109
+ }
110
+
111
+ export function updateSpinner(text) {
112
+ currentText = text;
113
+ if (isTTY && active) {
114
+ render();
115
+ }
116
+ }
117
+
118
+ export function stopSpinner() {
119
+ active = false;
120
+ if (timer) {
121
+ clearInterval(timer);
122
+ timer = null;
123
+ }
124
+ if (isTTY) {
125
+ originalStdoutWrite("\r\x1b[2K\x1b[J\r");
126
+ }
127
+ }
128
+
129
+ let buildFrameIdx = 0;
130
+ let buildTimer = null;
131
+ let currentBuildText = "";
132
+ let isBuildActive = false;
133
+
134
+ function smartTruncate(text, maxLen) {
135
+ if (text.length <= maxLen) return text;
136
+ const m = text.match(/^(\[SSG\].*?:\s+)(.*)$/);
137
+ if (m) {
138
+ const prefix = m[1];
139
+ const route = m[2];
140
+ const avail = maxLen - prefix.length;
141
+ if (avail > 10) {
142
+ const half = Math.floor((avail - 3) / 2);
143
+ return prefix + route.slice(0, half) + "..." + route.slice(route.length - (avail - 3 - half));
144
+ }
145
+ }
146
+ if (maxLen <= 3) {
147
+ return text.slice(0, maxLen);
148
+ }
149
+ return text.slice(0, maxLen - 3) + "...";
150
+ }
151
+
152
+ let lastBuildLineLen = 0;
153
+ let lastBuildCols = 0;
154
+
155
+ function renderBuildProgress() {
156
+ if (!isBuildActive || !isTTY) return;
157
+ const cols = getTerminalCols();
158
+ if (cols <= 0) return;
159
+
160
+ // Ultra-narrow terminal (< 8 cols): render just the spinner frame to guarantee 0 wrapping
161
+ if (cols < 8) {
162
+ const frame = FRAMES[buildFrameIdx];
163
+ buildFrameIdx = (buildFrameIdx + 1) % FRAMES.length;
164
+ lastBuildLineLen = 1;
165
+ lastBuildCols = cols;
166
+ process.stdout.write(`\r\x1b[2K${frame}\x1b[K\x1b[J`);
167
+ return;
168
+ }
169
+
170
+ // If terminal narrowed since last render, the previous line reflowed across multiple physical rows.
171
+ // Move up linesOccupied - 1 rows and clear each one to stay on a single line!
172
+ if (lastBuildLineLen > 0 && lastBuildCols > cols) {
173
+ const linesOccupied = Math.min(3, Math.ceil(lastBuildLineLen / Math.max(1, cols)));
174
+ if (linesOccupied > 1) {
175
+ for (let i = 0; i < linesOccupied - 1; i++) {
176
+ process.stdout.write("\x1b[1A\r\x1b[2K");
177
+ }
178
+ }
179
+ }
180
+
181
+ // Dynamically adapt to full terminal width with a 2-column margin against auto-wrap
182
+ const maxLineLen = Math.max(4, cols - 2);
183
+ const maxTextLen = Math.max(1, maxLineLen - 4);
184
+
185
+ const safeText = smartTruncate(currentBuildText, maxTextLen);
186
+
187
+ const frame = FRAMES[buildFrameIdx];
188
+ buildFrameIdx = (buildFrameIdx + 1) % FRAMES.length;
189
+
190
+ lastBuildLineLen = safeText.length + 4;
191
+ lastBuildCols = cols;
192
+
193
+ // \r (carriage return) + \x1b[2K (clear line) + text + \x1b[K (clear trailing) + \x1b[J (clear all lines below)
194
+ process.stdout.write(`\r\x1b[2K ${C_CYAN}${C_BOLD}${frame}${C_RESET} ${safeText}\x1b[K\x1b[J`);
195
+ }
196
+
197
+ export function updateBuildProgress(text) {
198
+ if (!isTTY) return;
199
+ currentBuildText = text;
200
+ if (!isBuildActive) {
201
+ isBuildActive = true;
202
+ buildFrameIdx = 0;
203
+ lastBuildLineLen = 0;
204
+ lastBuildCols = 0;
205
+ // Hide cursor for smooth, flicker-free rendering
206
+ process.stdout.write("\x1b[?25l");
207
+ renderBuildProgress();
208
+ if (!buildTimer) {
209
+ buildTimer = setInterval(renderBuildProgress, 80);
210
+ if (buildTimer.unref) buildTimer.unref();
211
+ }
212
+ }
213
+ }
214
+
215
+ export function clearBuildProgress() {
216
+ if (!isTTY) return;
217
+ isBuildActive = false;
218
+ lastBuildLineLen = 0;
219
+ lastBuildCols = 0;
220
+ if (buildTimer) {
221
+ clearInterval(buildTimer);
222
+ buildTimer = null;
223
+ }
224
+ // Clear the line, clear any lines below, and restore cursor visibility
225
+ process.stdout.write("\r\x1b[2K\x1b[J\x1b[?25h");
226
+ }
227
+
228
+ // Debounce terminal resize events so mouse dragging does not flood stdout
229
+ let resizeTimer = null;
230
+ if (typeof process.stdout.on === "function") {
231
+ process.stdout.on("resize", () => {
232
+ if (isBuildActive && isTTY) {
233
+ if (!resizeTimer) {
234
+ resizeTimer = setTimeout(() => {
235
+ resizeTimer = null;
236
+ renderBuildProgress();
237
+ }, 40);
238
+ if (resizeTimer.unref) resizeTimer.unref();
239
+ }
240
+ }
241
+ });
242
+ }
243
+
244
+ // Ensure cursor is always restored on process exit
245
+ process.on("exit", () => {
246
+ if (isTTY) {
247
+ try {
248
+ process.stdout.write("\x1b[?25h");
249
+ } catch (e) {}
250
+ }
251
+ });
252
+
253
+ export function logSuccess(text) {
254
+ stopSpinner();
255
+ console.log(` ${C_GREEN}✓${C_RESET} ${text}`);
256
+ if (isWatching) {
257
+ showIdleStatus();
258
+ }
259
+ }
260
+
261
+ export function logInfo(text) {
262
+ stopSpinner();
263
+ console.log(` ${C_CYAN}ℹ${C_RESET} ${text}`);
264
+ if (isWatching) {
265
+ showIdleStatus();
266
+ }
267
+ }
268
+
269
+ export function showIdleStatus() {
270
+ if (!isTTY) return;
271
+ startSpinner(`${C_DIM}watching for file changes...${C_RESET}`);
272
+ }
273
+
274
+ export function printReadyBanner({ port, tool, durationMs, timings }) {
275
+ stopSpinner();
276
+ isWatching = true;
277
+
278
+ const durationStr = durationMs ? `${durationMs}ms` : "";
279
+ const timeBadge = durationStr ? ` ${C_DIM}in ${C_BOLD}${durationStr}${C_RESET}` : "";
280
+
281
+ console.log("");
282
+ console.log(` ${C_CYAN}${C_BOLD}🦖 Dinou v7${C_RESET} ${C_GREEN}(Dual-Bundle, 0-fork)${C_RESET}${timeBadge}`);
283
+ console.log("");
284
+ console.log(` ${C_GREEN}➜${C_RESET} ${C_BOLD}Local:${C_RESET} ${C_CYAN}http://localhost:${port}/${C_RESET}`);
285
+ console.log(` ${C_GREEN}➜${C_RESET} ${C_BOLD}Bundler:${C_RESET} ${tool}`);
286
+ const isDebug =
287
+ process.env.DINOU_DEBUG === "true" ||
288
+ process.env.DINOU_DEBUG === "1" ||
289
+ process.env.DEBUG === "true" ||
290
+ process.env.DEBUG === "1";
291
+
292
+ if (timings && isDebug) {
293
+ console.log("");
294
+ console.log(` ${C_BOLD}⚡ Startup Breakdown:${C_RESET}`);
295
+ if (timings.discovery != null) {
296
+ console.log(` ${C_DIM}├─ Discovery & Routing:${C_RESET} ${C_CYAN}${timings.discovery}ms${C_RESET}`);
297
+ }
298
+ if (timings.engineBuild != null) {
299
+ console.log(` ${C_DIM}├─ Dual-Engine (RSC+SSR):${C_RESET} ${C_CYAN}${timings.engineBuild}ms${C_RESET}`);
300
+ }
301
+ if (timings.engineImport != null) {
302
+ console.log(` ${C_DIM}├─ Engine V8 Evaluation:${C_RESET} ${C_CYAN}${timings.engineImport}ms${C_RESET}`);
303
+ }
304
+ if (timings.clientEntriesBabel != null) {
305
+ console.log(` ${C_DIM}├─ Client Babel AST Scan:${C_RESET} ${C_CYAN}${timings.clientEntriesBabel}ms${C_RESET}`);
306
+ }
307
+ if (timings.clientBuild != null) {
308
+ console.log(` ${C_DIM}├─ Client Bundling (esbuild):${C_RESET} ${C_CYAN}${timings.clientBuild}ms${C_RESET}`);
309
+ const subParts = [];
310
+ if (timings.postCss) subParts.push(`PostCSS: ${timings.postCss}ms (${timings.postCssCount || 0} css)`);
311
+ if (timings.swc) subParts.push(`SWC Refresh: ${timings.swc}ms (${timings.swcCount || 0} files)`);
312
+ if (timings.sf) subParts.push(`Server Actions: ${timings.sf}ms (${timings.sfCount || 0} files)`);
313
+ if (timings.rcm) subParts.push(`Client Manifest: ${timings.rcm}ms`);
314
+ if (timings.stable) subParts.push(`Stable Chunks: ${timings.stable}ms`);
315
+ if (timings.writeDisk != null) {
316
+ if (timings.writeDisk === 0) {
317
+ subParts.push("Memory: 0ms (disk skipped)");
318
+ } else {
319
+ subParts.push(`Disk Write: ${timings.writeDisk}ms`);
320
+ }
321
+ }
322
+ if (subParts.length > 0) {
323
+ console.log(` ${C_DIM}│ └─ [${subParts.join(" | ")}]${C_RESET}`);
324
+ }
325
+ } else if (timings.clientBundlerTotal != null) {
326
+ console.log(` ${C_DIM}├─ Client Bundler Total:${C_RESET} ${C_CYAN}${timings.clientBundlerTotal}ms${C_RESET}`);
327
+ }
328
+ console.log(` ${C_DIM}└─ Total Startup Time:${C_RESET} ${C_GREEN}${C_BOLD}${durationMs}ms${C_RESET}`);
329
+ }
330
+
331
+ console.log("");
332
+ showIdleStatus();
333
+ }
334
+
335
+ export default {
336
+ startSpinner,
337
+ updateSpinner,
338
+ stopSpinner,
339
+ updateBuildProgress,
340
+ clearBuildProgress,
341
+ logSuccess,
342
+ logInfo,
343
+ showIdleStatus,
344
+ printReadyBanner,
345
+ };
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dinou-ejected",
3
- "version": "6.1.1",
3
+ "version": "7.0.0",
4
4
  "main": "index.js",
5
5
  "private": true,
6
6
  "exports": {
@@ -16,7 +16,17 @@
16
16
  "types": "./server.d.ts",
17
17
  "import": "./server.mjs",
18
18
  "require": "./server.js"
19
- }
19
+ },
20
+ "./config": {
21
+ "types": "./index.d.ts",
22
+ "import": "./core/config.js",
23
+ "require": "./core/config.js"
24
+ },
25
+ "./adapters/node": "./adapters/node.mjs",
26
+ "./adapters/bun": "./adapters/bun.js",
27
+ "./adapters/deno": "./adapters/deno.js",
28
+ "./adapters/cloudflare": "./adapters/cloudflare.js",
29
+ "./adapters/netlify": "./adapters/netlify.js"
20
30
  },
21
31
  "types": "./index.d.ts",
22
32
  "scripts": {
@@ -26,13 +36,11 @@
26
36
  "@babel/core": "^7.27.4",
27
37
  "@babel/parser": "^7.28.3",
28
38
  "@babel/plugin-syntax-import-meta": "^7.10.4",
29
- "@babel/plugin-transform-modules-commonjs": "^7.27.1",
30
39
  "@babel/preset-react": "^7.27.1",
31
40
  "@babel/preset-typescript": "^7.27.1",
32
- "@babel/register": "^7.27.1",
33
41
  "@babel/traverse": "^7.28.3",
34
42
  "@esbuild-plugins/tsconfig-paths": "^0.1.2",
35
- "@roggc/react-server-dom-esm": "^0.0.0-b061b597-20251212",
43
+ "@roggc/react-server-dom-esm": "^19.3.0",
36
44
  "@rollup/plugin-babel": "^6.0.4",
37
45
  "@rollup/plugin-commonjs": "^28.0.6",
38
46
  "@rollup/plugin-json": "^6.1.0",
@@ -45,32 +53,26 @@
45
53
  "babel-plugin-react-compiler": "^1.0.0",
46
54
  "chokidar": "^4.0.3",
47
55
  "commander": "^14.0.0",
48
- "concurrently": "^10.0.3",
49
- "cookie-parser": "^1.4.7",
50
56
  "copy-webpack-plugin": "^14.0.0",
51
57
  "cross-env": "^7.0.3",
52
58
  "css-loader": "^7.1.2",
53
59
  "dotenv": "^16.5.0",
54
60
  "esbuild": "^0.27.0",
55
61
  "esbuild-copy-static-files": "^0.1.0",
56
- "express": "^5.1.0",
57
62
  "generic-names": "^4.0.0",
58
- "loader-utils": "^3.3.1",
59
63
  "mini-css-extract-plugin": "^2.9.4",
60
- "multer": "^2.0.2",
61
64
  "postcss": "^8.5.5",
62
65
  "postcss-import": "^16.1.1",
63
66
  "postcss-loader": "^8.2.0",
64
67
  "postcss-modules": "^6.0.1",
65
68
  "react-refresh": "^0.17.0",
66
- "react-server-dom-webpack": "^19.2.3",
69
+ "react-server-dom-webpack": "^19.3.0",
67
70
  "rollup": "^4.46.2",
68
71
  "rollup-plugin-copy": "^3.5.0",
69
72
  "rollup-plugin-delete": "^3.0.1",
70
73
  "rollup-plugin-postcss": "^4.0.2",
71
74
  "rollup-plugin-tsconfig-paths": "^1.5.2",
72
75
  "tailwindcss": "^4.1.10",
73
- "tsconfig-paths": "^4.2.0",
74
76
  "tsconfig-paths-webpack-plugin": "^4.2.0",
75
77
  "webpack": "^5.103.0",
76
78
  "webpack-cli": "^6.0.1",
@@ -78,7 +80,7 @@
78
80
  "ws": "^8.18.3"
79
81
  },
80
82
  "peerDependencies": {
81
- "react": ">=19.2.3",
82
- "react-dom": ">=19.2.3"
83
+ "react": ">=19.3.0",
84
+ "react-dom": ">=19.3.0"
83
85
  }
84
86
  }