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.
Files changed (135) hide show
  1. package/CHANGELOG.md +106 -0
  2. package/README.md +9352 -1081
  3. package/cli.js +314 -91
  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 +322 -165
  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 +175 -96
  39. package/dinou/core/handler.js +2303 -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 +183 -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 +252 -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 +91 -87
  53. package/dinou/core/request-context.js +47 -13
  54. package/dinou/core/resolve-module-ppr.js +34 -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 +113 -34
  121. package/package.json +18 -16
  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
@@ -9,14 +9,30 @@ import { useClientRegex } from "../../constants.js";
9
9
  export default function reactClientManifestPlugin({
10
10
  manifestPath = ".dinou/react_client_manifest/react-client-manifest.json",
11
11
  manifest = {},
12
+ onManifestUpdated,
12
13
  } = {}) {
13
14
  return {
14
15
  name: "react-client-manifest",
15
16
  setup(build) {
17
+ let lastSerialized = "";
16
18
  build.onEnd(async (result) => {
19
+ const tRcm0 = Date.now();
20
+ let manifestChanged = false;
17
21
  try {
18
22
  const meta = result.metafile;
19
23
  if (meta && meta.outputs) {
24
+ // Group manifest keys by base file URL for O(1) matching (case-insensitive for Windows)
25
+ const manifestPrefixMap = new Map();
26
+ for (const key of Object.keys(manifest)) {
27
+ const base = key.split("#")[0].toLowerCase();
28
+ let list = manifestPrefixMap.get(base);
29
+ if (!list) {
30
+ list = [];
31
+ manifestPrefixMap.set(base, list);
32
+ }
33
+ list.push(key);
34
+ }
35
+
20
36
  for (const [outFile, outInfo] of Object.entries(meta.outputs)) {
21
37
  const fileName = outFile.replace(/\\/g, "/").split(/[/\\]/).pop();
22
38
  const outUrl = "/" + fileName;
@@ -25,39 +41,62 @@ export default function reactClientManifestPlugin({
25
41
  continue;
26
42
  }
27
43
  const absModulePath = path.resolve(modulePath);
28
- const baseFileUrl = pathToFileURL(absModulePath).href;
29
- const code = readFileSync(absModulePath, "utf8");
30
- const isClientModule = useClientRegex.test(code.trim());
31
- if (!isClientModule) {
32
- // console.log(
33
- // `[react-client-manifest] Skipping non-client module: ${baseFileUrl}`
34
- // );
35
- continue;
44
+ let baseFileUrl = pathToFileURL(absModulePath).href;
45
+
46
+ // If entry point was loaded from .dinou/swc, map to original file URL
47
+ if (absModulePath.includes(".dinou/swc") || absModulePath.includes(".dinou\\swc")) {
48
+ const norm = absModulePath.replace(/\\/g, "/");
49
+ const rel = norm.replace(/^.*\.dinou\/swc\//, "");
50
+ const base = path.resolve(process.cwd(), rel.replace(/\.js$/, ""));
51
+ for (const ext of [".tsx", ".ts", ".jsx", ".js"]) {
52
+ const candidate = base + ext;
53
+ const candidateUrl = pathToFileURL(candidate).href;
54
+ if (manifestPrefixMap.has(candidateUrl.toLowerCase())) {
55
+ baseFileUrl = candidateUrl;
56
+ break;
57
+ }
58
+ }
36
59
  }
37
- const exports = parseExports(code);
38
- for (const expName of exports) {
39
- const manifestKey =
40
- expName === "default"
41
- ? baseFileUrl
42
- : `${baseFileUrl}#${expName}`;
43
- if (manifest[manifestKey]) {
44
- manifest[manifestKey].id = outUrl;
60
+
61
+ const relatedKeys = manifestPrefixMap.get(baseFileUrl.toLowerCase());
62
+ if (relatedKeys) {
63
+ for (const key of relatedKeys) {
64
+ manifest[key].id = outUrl;
45
65
  }
46
66
  }
47
67
  }
48
68
  }
49
69
 
50
- // Ensure directory exists
51
- await fs.mkdir(path.dirname(manifestPath), { recursive: true });
70
+ // Write merged manifest only if changed
71
+ const serialized = JSON.stringify(manifest, null, 2);
72
+ if (typeof globalThis !== "undefined") {
73
+ globalThis.__DINOU_RAW_CLIENT_MANIFEST__ = { ...manifest };
74
+ }
75
+
76
+ const isDev = process.env.DINOU_DEV === "true" || process.env.NODE_ENV === "development";
77
+ const shouldWriteToDisk = process.env.DINOU_WRITE_TO_DISK === "true" || !isDev;
78
+
79
+ if (lastSerialized !== serialized) {
80
+ manifestChanged = true;
81
+ lastSerialized = serialized;
82
+ }
52
83
 
53
- // Write merged manifest
54
- await fs.writeFile(
55
- manifestPath,
56
- JSON.stringify(manifest, null, 2),
57
- "utf8"
58
- );
84
+ if (shouldWriteToDisk && manifestChanged) {
85
+ await fs.mkdir(path.dirname(manifestPath), { recursive: true });
86
+ await fs.writeFile(
87
+ manifestPath,
88
+ serialized,
89
+ "utf8"
90
+ );
91
+ }
59
92
  } catch (err) {
60
93
  console.warn("[react-client-manifest] onEnd error:", err.message);
94
+ } finally {
95
+ globalThis.__DINOU_RCM_TIME__ = Date.now() - tRcm0;
96
+ }
97
+
98
+ if (manifestChanged && onManifestUpdated) {
99
+ await onManifestUpdated();
61
100
  }
62
101
  });
63
102
  }, // end setup
@@ -3,88 +3,209 @@ import fs from "node:fs/promises";
3
3
  import parseExports from "../../core/parse-exports.js";
4
4
  import { useServerRegex } from "../../constants.js";
5
5
 
6
- export default function serverFunctionsPlugin(manifestData = {}) {
6
+ export default function serverFunctionsPlugin(manifestData = {}, options = {}) {
7
+ const opts =
8
+ typeof manifestData === "object" && manifestData !== null && ("onManifestUpdated" in manifestData || "serverFiles" in manifestData)
9
+ ? manifestData
10
+ : options;
11
+ const manifestMap = opts.manifestData || (manifestData.onManifestUpdated ? {} : manifestData) || {};
12
+ const onManifestUpdated = opts.onManifestUpdated;
13
+ const serverFiles = opts.serverFiles || manifestData.serverFiles || options.serverFiles || null;
14
+ const normalizeNormPath = (p) => {
15
+ let s = path.resolve(p).replace(/\\/g, "/");
16
+ if (process.platform === "win32") {
17
+ s = s.replace(/^([a-zA-Z]):/, (_, d) => d.toLowerCase() + ":");
18
+ }
19
+ return s;
20
+ };
21
+ const serverFilesSet = serverFiles
22
+ ? new Set(Array.from(serverFiles).map((f) => normalizeNormPath(f)))
23
+ : null;
24
+
7
25
  return {
8
26
  name: "server-functions-proxy",
9
27
  setup(build) {
28
+ if (serverFilesSet && serverFilesSet.size === 0) {
29
+ return;
30
+ }
31
+ const escapeRegExp = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
32
+ const sfFilter = serverFilesSet && serverFilesSet.size > 0
33
+ ? new RegExp(Array.from(serverFilesSet).map((f) => escapeRegExp(path.basename(f))).join("|"))
34
+ : /\.[jt]sx?$/;
10
35
  const root = process.cwd();
11
36
  const serverFunctions = new Map(); // Collect server functions here: Map<relativePath, Set<exports>>
37
+ const sfCache = new Map(); // Cache by path: { mtimeMs, isServer, relativePath, exportsSet, proxyCode }
38
+ let sfTime = 0;
39
+ let sfCount = 0;
40
+
41
+ build.onStart(() => {
42
+ sfTime = 0;
43
+ sfCount = 0;
44
+ });
12
45
 
13
46
  // 1. TRANSFORM FILES DURING BUILD
14
- build.onLoad({ filter: /\.[jt]sx?$/ }, async (args) => {
15
- const code = await fs.readFile(args.path, "utf8");
47
+ build.onLoad({ filter: sfFilter }, async (args) => {
48
+ const normPath = args.path.replace(/\\/g, "/");
49
+ if (normPath.includes("/node_modules/") || normPath.includes("/.dinou/")) return null;
50
+
51
+ if (serverFilesSet) {
52
+ const absNorm = normalizeNormPath(args.path);
53
+ if (!serverFilesSet.has(absNorm)) {
54
+ return null;
55
+ }
56
+ }
57
+
58
+ const t0 = Date.now();
59
+ try {
60
+ let stat;
61
+ try {
62
+ stat = await fs.stat(args.path);
63
+ } catch (e) {
64
+ return null;
65
+ }
66
+
67
+ const cached = sfCache.get(args.path);
68
+ if (cached && cached.mtimeMs === stat.mtimeMs) {
69
+ if (!cached.isServer) return null;
70
+ serverFunctions.set(cached.relativePath, cached.exportsSet);
71
+ return { contents: cached.proxyCode, loader: "js", watchFiles: [args.path] };
72
+ }
73
+
74
+ const code = await fs.readFile(args.path, "utf8");
16
75
 
17
- if (!useServerRegex.test(code.trim())) return null;
76
+ if (!useServerRegex.test(code.trim())) {
77
+ sfCache.set(args.path, { mtimeMs: stat.mtimeMs, isServer: false });
78
+ return null;
79
+ }
18
80
 
19
- const exports = parseExports(code);
20
- if (exports.length === 0) return null;
81
+ const exports = parseExports(code);
82
+ if (exports.length === 0) {
83
+ sfCache.set(args.path, { mtimeMs: stat.mtimeMs, isServer: false });
84
+ return null;
85
+ }
21
86
 
22
- const relativePath = path.relative(root, args.path).replace(/\\/g, "/");
23
- serverFunctions.set(relativePath, new Set(exports)); // Save exports as a Set to guarantee uniqueness
87
+ const relativePath = path.relative(root, args.path).replace(/\\/g, "/");
88
+ const exportsSet = new Set(exports);
89
+ serverFunctions.set(relativePath, exportsSet); // Save exports as a Set to guarantee uniqueness
24
90
 
25
- const fileUrl = `file:///${relativePath}`;
91
+ const fileUrl = `file:///${relativePath}`;
26
92
 
27
- // Generate proxy code that forwards calls to the server instead of executing the actual code
28
- let proxyCode = `
29
- import { createServerFunctionProxy } from "/__SERVER_FUNCTION_PROXY__";
30
- `;
93
+ // Generate proxy code that forwards calls to the server instead of executing the actual code
94
+ let proxyCode = `
95
+ import { createServerFunctionProxy } from "/__SERVER_FUNCTION_PROXY__";
96
+ `;
31
97
 
32
- for (const exp of exports) {
33
- const key =
34
- exp === "default" ? `${fileUrl}#default` : `${fileUrl}#${exp}`;
98
+ for (const exp of exports) {
99
+ const key =
100
+ exp === "default" ? `${fileUrl}#default` : `${fileUrl}#${exp}`;
35
101
 
36
- if (exp === "default") {
37
- proxyCode += `export default createServerFunctionProxy(${JSON.stringify(
38
- key
39
- )});\n`;
40
- } else {
41
- proxyCode += `export const ${exp} = createServerFunctionProxy(${JSON.stringify(
42
- key
43
- )});\n`;
102
+ if (exp === "default") {
103
+ proxyCode += `export default createServerFunctionProxy(${JSON.stringify(
104
+ key
105
+ )});\n`;
106
+ } else {
107
+ proxyCode += `export const ${exp} = createServerFunctionProxy(${JSON.stringify(
108
+ key
109
+ )});\n`;
110
+ }
44
111
  }
45
- }
46
112
 
47
- return {
48
- contents: proxyCode,
49
- loader: "js",
50
- };
113
+ sfCache.set(args.path, {
114
+ mtimeMs: stat.mtimeMs,
115
+ isServer: true,
116
+ relativePath,
117
+ exportsSet,
118
+ proxyCode,
119
+ });
120
+
121
+ return {
122
+ contents: proxyCode,
123
+ loader: "js",
124
+ watchFiles: [args.path],
125
+ };
126
+ } finally {
127
+ sfTime += Date.now() - t0;
128
+ sfCount++;
129
+ globalThis.__DINOU_SF_TIME__ = sfTime;
130
+ globalThis.__DINOU_SF_COUNT__ = sfCount;
131
+ }
51
132
  });
52
133
 
53
134
  // 2. REPLACE PLACEHOLDER AND GENERATE MANIFEST AFTER BUILD
54
135
  build.onEnd(async (result) => {
55
- const hashedProxy =
136
+ const tEnd0 = Date.now();
137
+ try {
138
+ if (serverFunctions.size === 0) {
139
+ if (typeof globalThis !== "undefined") {
140
+ globalThis.__DINOU_RAW_SERVER_FUNCTIONS_MANIFEST__ = {};
141
+ }
142
+ return;
143
+ }
144
+ const hashedProxy =
56
145
  "/" +
57
- (manifestData["serverFunctionProxy.js"] || "serverFunctionProxy.js");
146
+ (manifestMap["serverFunctionProxy.js"] || "serverFunctionProxy.js");
58
147
 
59
- for (const outputFile of Object.values(result.outputFiles)) {
60
- const fileCode = new TextDecoder().decode(outputFile.contents);
148
+ const serverFnNormalized = new Set();
149
+ for (const relPath of serverFunctions.keys()) {
150
+ serverFnNormalized.add(path.resolve(root, relPath).replace(/\\/g, "/").toLowerCase());
151
+ }
61
152
 
62
- if (!fileCode) continue;
63
- if (fileCode.includes("/__SERVER_FUNCTION_PROXY__")) {
64
- const newCode = fileCode.replace(
65
- /\/__SERVER_FUNCTION_PROXY__/g,
66
- hashedProxy
67
- );
68
- outputFile.contents = new TextEncoder().encode(newCode);
153
+ let targetOutputFiles = Object.values(result.outputFiles || {});
154
+ if (result.metafile && result.metafile.outputs) {
155
+ const allowedOutputs = new Set();
156
+ for (const [outPath, outMeta] of Object.entries(result.metafile.outputs)) {
157
+ const hasSf = Object.keys(outMeta.inputs || {}).some((inPath) => {
158
+ const norm = path.resolve(root, inPath).replace(/\\/g, "/").toLowerCase();
159
+ return serverFnNormalized.has(norm);
160
+ });
161
+ if (hasSf) {
162
+ allowedOutputs.add(path.resolve(root, outPath).replace(/\\/g, "/").toLowerCase());
163
+ }
164
+ }
165
+ targetOutputFiles = targetOutputFiles.filter((outputFile) => {
166
+ const norm = path.resolve(outputFile.path).replace(/\\/g, "/").toLowerCase();
167
+ return allowedOutputs.has(norm);
168
+ });
69
169
  }
70
- }
71
170
 
72
- // Generate the final manifest by converting the Map to a plain object
73
- const manifestObj = {};
74
- for (const [path, exportsSet] of serverFunctions.entries()) {
75
- manifestObj[path] = Array.from(exportsSet);
76
- }
171
+ for (const outputFile of targetOutputFiles) {
172
+ const fileCode = new TextDecoder().decode(outputFile.contents);
173
+
174
+ if (!fileCode) continue;
175
+ if (fileCode.includes("/__SERVER_FUNCTION_PROXY__")) {
176
+ const newCode = fileCode.replace(
177
+ /\/__SERVER_FUNCTION_PROXY__/g,
178
+ hashedProxy
179
+ );
180
+ outputFile.contents = new TextEncoder().encode(newCode);
181
+ }
182
+ }
77
183
 
78
- // Write the server functions manifest JSON file to the output directory
79
- const manifestPath = path.join(
80
- ".dinou/server_functions_manifest",
81
- "server-functions-manifest.json"
82
- );
83
- await fs.mkdir(path.dirname(manifestPath), { recursive: true });
84
- await fs.writeFile(manifestPath, JSON.stringify(manifestObj, null, 2));
85
- // console.log(
86
- // `[server-functions-proxy] Generated manifest at ${manifestPath}`
87
- // );
184
+ // Generate the final manifest by converting the Map to a plain object
185
+ const manifestObj = {};
186
+ for (const [path, exportsSet] of serverFunctions.entries()) {
187
+ manifestObj[path] = Array.from(exportsSet);
188
+ }
189
+
190
+ if (typeof globalThis !== "undefined") {
191
+ globalThis.__DINOU_RAW_SERVER_FUNCTIONS_MANIFEST__ = manifestObj;
192
+ }
193
+
194
+ const isDev = process.env.DINOU_DEV === "true" || process.env.NODE_ENV === "development";
195
+ const shouldWriteToDisk = process.env.DINOU_WRITE_TO_DISK === "true" || !isDev;
196
+
197
+ if (shouldWriteToDisk) {
198
+ // Write the server functions manifest JSON file to the output directory
199
+ const manifestPath = path.join(
200
+ ".dinou/server_functions_manifest",
201
+ "server-functions-manifest.json"
202
+ );
203
+ await fs.mkdir(path.dirname(manifestPath), { recursive: true });
204
+ await fs.writeFile(manifestPath, JSON.stringify(manifestObj, null, 2));
205
+ }
206
+ } finally {
207
+ globalThis.__DINOU_SF_END_TIME__ = Date.now() - tEnd0;
208
+ }
88
209
  });
89
210
  },
90
211
  };
@@ -1,10 +1,13 @@
1
1
  import { existsSync } from "node:fs";
2
2
 
3
3
  export default function skipMissingEntryPointsPlugin() {
4
+ let checkedOnce = false;
4
5
  return {
5
6
  name: "skip-missing-entry-points",
6
7
  setup(build) {
7
8
  build.onStart(async () => {
9
+ if (checkedOnce) return;
10
+ checkedOnce = true;
8
11
  const entryPoints = build.initialOptions.entryPoints;
9
12
  if (!entryPoints || typeof entryPoints === "string") return;
10
13