dinou 4.0.5 → 4.0.7

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 CHANGED
@@ -5,6 +5,18 @@ 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
+ ## [4.0.7]
9
+
10
+ ### Fixed
11
+
12
+ - env vars in getProps and json files in esbuild.
13
+
14
+ ## [4.0.6]
15
+
16
+ ### Fixed
17
+
18
+ - Execute page_functions on not_found page too in getJSX.
19
+
8
20
  ## [4.0.5]
9
21
 
10
22
  ### Fixed
@@ -11,7 +11,7 @@ async function getJSX(
11
11
  reqPath,
12
12
  query,
13
13
  isNotFound = null,
14
- isDevelopment = false
14
+ isDevelopment = false,
15
15
  ) {
16
16
  const srcFolder = path.resolve(process.cwd(), "src");
17
17
  const reqSegments = reqPath.split("/").filter(Boolean);
@@ -43,7 +43,7 @@ async function getJSX(
43
43
  const [filePath, dParams] = getFilePathAndDynamicParams(
44
44
  reqSegments,
45
45
  query,
46
- srcFolder
46
+ srcFolder,
47
47
  );
48
48
  pagePath = filePath;
49
49
  dynamicParams = dParams ?? {};
@@ -60,26 +60,43 @@ async function getJSX(
60
60
  srcFolder,
61
61
  "not_found",
62
62
  true,
63
- false
63
+ false,
64
64
  );
65
65
  if (!notFoundPath) {
66
66
  jsx = React.createElement(
67
67
  "div",
68
68
  null,
69
- `Page not found: no "page" file found for "${reqPath}"`
69
+ `Page not found: no "page" file found for "${reqPath}"`,
70
70
  );
71
71
  } else {
72
72
  const pageModule = await importModule(notFoundPath);
73
73
  const Page = pageModule.default ?? pageModule;
74
- jsx = React.createElement(Page, {
74
+ let props = {
75
75
  params: dParams ?? {},
76
- // searchParams: query,
77
- });
78
-
76
+ };
79
77
  const notFoundDir = path.dirname(notFoundPath);
78
+
79
+ const [pageFunctionsPath] = getFilePathAndDynamicParams(
80
+ reqSegments,
81
+ query,
82
+ notFoundDir,
83
+ "page_functions",
84
+ true,
85
+ true,
86
+ undefined,
87
+ reqSegments.length,
88
+ );
89
+ if (pageFunctionsPath) {
90
+ const pageFunctionsModule = await importModule(pageFunctionsPath);
91
+ const getProps = pageFunctionsModule.getProps;
92
+ pageFunctionsProps = await getProps?.(dParams ?? {});
93
+ props = { ...props, ...(pageFunctionsProps?.page ?? {}) };
94
+ }
95
+
96
+ jsx = React.createElement(Page, props);
80
97
  const noLayoutNotFoundPath = path.join(
81
98
  notFoundDir,
82
- `no_layout_not_found`
99
+ `no_layout_not_found`,
83
100
  );
84
101
  if (existsSync(noLayoutNotFoundPath)) {
85
102
  return jsx;
@@ -104,7 +121,7 @@ async function getJSX(
104
121
  true,
105
122
  true,
106
123
  undefined,
107
- reqSegments.length
124
+ reqSegments.length,
108
125
  );
109
126
  if (pageFunctionsPath) {
110
127
  const pageFunctionsModule = await importModule(pageFunctionsPath);
@@ -122,7 +139,7 @@ async function getJSX(
122
139
  query,
123
140
  srcFolder,
124
141
  "no_layout",
125
- false
142
+ false,
126
143
  )[0]
127
144
  ) {
128
145
  return jsx;
@@ -138,7 +155,7 @@ async function getJSX(
138
155
  undefined,
139
156
  0,
140
157
  {},
141
- true
158
+ true,
142
159
  );
143
160
 
144
161
  if (layouts && Array.isArray(layouts)) {
@@ -151,7 +168,7 @@ async function getJSX(
151
168
  {},
152
169
  layoutFolderPath,
153
170
  "reset_layout",
154
- false
171
+ false,
155
172
  )[0];
156
173
  const Layout = layoutModule.default ?? layoutModule;
157
174
  const updatedSlots = {};
@@ -175,7 +192,7 @@ async function getJSX(
175
192
  true, // withExtension
176
193
  true, // finalDestination
177
194
  undefined, // lastFound
178
- reqSegments.length
195
+ reqSegments.length,
179
196
  );
180
197
 
181
198
  if (slotErrorPath) {
@@ -196,13 +213,13 @@ async function getJSX(
196
213
  });
197
214
  } else {
198
215
  console.warn(
199
- `[Dinou] Slot @${slotName} failed and does not have error.tsx`
216
+ `[Dinou] Slot @${slotName} failed and does not have error.tsx`,
200
217
  );
201
218
  updatedSlotElement = null;
202
219
  }
203
220
  } else {
204
221
  console.error(
205
- `[Dinou] Could not locate the path of the slot @${slotName}`
222
+ `[Dinou] Could not locate the path of the slot @${slotName}`,
206
223
  );
207
224
  updatedSlotElement = null;
208
225
  }
@@ -9,7 +9,7 @@ function toFileUrl(p) {
9
9
  }
10
10
 
11
11
  const registerLoaderPath = toFileUrl(
12
- path.join(__dirname, "register-loader.mjs")
12
+ path.join(__dirname, "register-loader.mjs"),
13
13
  );
14
14
  const renderHtmlPath = path.resolve(__dirname, "render-html.js");
15
15
 
@@ -33,7 +33,7 @@ function renderAppToHtml(
33
33
  contextForChild,
34
34
  res,
35
35
  capturedStatus = null,
36
- isDynamic = false
36
+ isDynamic = false,
37
37
  ) {
38
38
  const jsxJson = getJSXJSON(reqPath);
39
39
  const hasJsxJson = hasJSXJSON(reqPath);
@@ -52,15 +52,15 @@ function renderAppToHtml(
52
52
  renderHtmlPath, // ⬅️ CHANGE 2: The script (path) is the first argument of fork (no need for "node")
53
53
  scriptArgs, // Positional arguments for the script (process.argv)
54
54
  {
55
- env: {
56
- NODE_ENV: process.env.NODE_ENV,
57
- DINOU_BUILD_TOOL: process.env.DINOU_BUILD_TOOL,
58
- }, // You can pass other environment variables if necessary
55
+ // env: {
56
+ // NODE_ENV: process.env.NODE_ENV,
57
+ // DINOU_BUILD_TOOL: process.env.DINOU_BUILD_TOOL,
58
+ // }, // You can pass other environment variables if necessary
59
59
  // ⬅️ CHANGE 3: Apply Whitelist to execArgv, resetting inherited options
60
60
  execArgv: childExecArgv,
61
61
  // ⬅️ CHANGE 4: stdio needs 'ipc' for fork to work and for the future communication channel
62
62
  stdio: ["ignore", "pipe", "pipe", "ipc"], // stdin, stdout, stderr, ipc
63
- }
63
+ },
64
64
  );
65
65
 
66
66
  // 💡 on('message') Implementation (IPC Channel)
@@ -88,7 +88,7 @@ function renderAppToHtml(
88
88
  if (command === "redirect") {
89
89
  const url = args.length === 1 ? args[0] : args[1];
90
90
  console.log(
91
- `[Dinou] Streaming active. Redirecting via JavaScript to: ${url}`
91
+ `[Dinou] Streaming active. Redirecting via JavaScript to: ${url}`,
92
92
  );
93
93
  const safeUrl = JSON.stringify(url);
94
94
  res.write(`<script>window.location.href = ${safeUrl};</script>`);
@@ -99,7 +99,7 @@ function renderAppToHtml(
99
99
  // --- STATUS (Warning) ---
100
100
  if (command === "status") {
101
101
  console.warn(
102
- `[Dinou Warning] HTTP status '${args[0]}' ignored because streaming started.`
102
+ `[Dinou Warning] HTTP status '${args[0]}' ignored because streaming started.`,
103
103
  );
104
104
  if (capturedStatus) capturedStatus.value = args[0];
105
105
  return;
@@ -110,12 +110,12 @@ function renderAppToHtml(
110
110
  const [name, options] = args;
111
111
  const path = options && options.path ? options.path : "/";
112
112
  console.log(
113
- `[Dinou] Streaming active. Clearing cookie '${name}' via JS.`
113
+ `[Dinou] Streaming active. Clearing cookie '${name}' via JS.`,
114
114
  );
115
115
  const safeName = JSON.stringify(name);
116
116
  const safePath = JSON.stringify(path);
117
117
  res.write(
118
- `<script>document.cookie = ${safeName} + "=; Max-Age=0; path=" + ${safePath} + ";";</script>`
118
+ `<script>document.cookie = ${safeName} + "=; Max-Age=0; path=" + ${safePath} + ";";</script>`,
119
119
  );
120
120
  return;
121
121
  }
@@ -129,13 +129,13 @@ function renderAppToHtml(
129
129
  if (options && options.httpOnly) {
130
130
  console.error(
131
131
  `[Dinou Error] Cannot set HttpOnly cookie '${name}' because streaming has already started. ` +
132
- `Headers are sent, and document.cookie cannot write HttpOnly cookies.`
132
+ `Headers are sent, and document.cookie cannot write HttpOnly cookies.`,
133
133
  );
134
134
  return; // We do nothing because it would fail silently in the browser
135
135
  }
136
136
 
137
137
  console.log(
138
- `[Dinou] Streaming active. Setting cookie '${name}' via JS.`
138
+ `[Dinou] Streaming active. Setting cookie '${name}' via JS.`,
139
139
  );
140
140
 
141
141
  // We build the cookie string manually for JS
@@ -148,7 +148,7 @@ function renderAppToHtml(
148
148
  if (options.maxAge) cookieStr += `; max-age=${options.maxAge}`;
149
149
  if (options.expires)
150
150
  cookieStr += `; expires=${new Date(
151
- options.expires
151
+ options.expires,
152
152
  ).toUTCString()}`;
153
153
  if (options.secure) cookieStr += `; secure`;
154
154
  if (options.sameSite)
@@ -164,7 +164,7 @@ function renderAppToHtml(
164
164
  // --- SET HEADER (Warning) ---
165
165
  if (command === "setHeader") {
166
166
  console.warn(
167
- `[Dinou Warning] Cannot set header '${args[0]}' because streaming started.`
167
+ `[Dinou Warning] Cannot set header '${args[0]}' because streaming started.`,
168
168
  );
169
169
  return;
170
170
  }
@@ -202,7 +202,7 @@ function renderAppToHtml(
202
202
  finalUrl = rawUrl;
203
203
  } else {
204
204
  console.warn(
205
- `[Dinou Security] Blocked unsafe redirect to: ${rawUrl}`
205
+ `[Dinou Security] Blocked unsafe redirect to: ${rawUrl}`,
206
206
  );
207
207
  // finalUrl remains "/"
208
208
  }
@@ -33,7 +33,7 @@ export default async function getEsbuildEntries({
33
33
  code,
34
34
  baseFilePath,
35
35
  visited = new Set(),
36
- isTopLevelClientComponent = false
36
+ isTopLevelClientComponent = false,
37
37
  ) {
38
38
  if (visited.has(baseFilePath)) {
39
39
  return { imports: [], assets: [], csss: [] };
@@ -75,7 +75,7 @@ export default async function getEsbuildEntries({
75
75
  } catch (err) {
76
76
  console.warn(
77
77
  `[get-esbuild-entries] Could not read import: ${absImportPathWithExt}`,
78
- err.message
78
+ err.message,
79
79
  );
80
80
  continue;
81
81
  }
@@ -111,6 +111,12 @@ export default async function getEsbuildEntries({
111
111
  continue;
112
112
  }
113
113
 
114
+ // 🚨 LA SOLUCIÓN: Si es un JSON, lo añadimos pero NO lo parseamos con Babel
115
+ if (absImportPathWithExt.endsWith(".json")) {
116
+ imports.add(absImportPathWithExt);
117
+ continue; // Esto evita que pase a la recursividad de Babel
118
+ }
119
+
114
120
  imports.add(absImportPathWithExt);
115
121
 
116
122
  // Procesar imports recursivamente para módulos no-client
@@ -119,7 +125,7 @@ export default async function getEsbuildEntries({
119
125
  importedCode,
120
126
  absImportPathWithExt,
121
127
  visited,
122
- isTopLevelClientComponent
128
+ isTopLevelClientComponent,
123
129
  );
124
130
  nested.imports.forEach((p) => imports.add(p));
125
131
  nested.assets.forEach((p) => assets.add(p));
@@ -127,7 +133,7 @@ export default async function getEsbuildEntries({
127
133
  } catch (err) {
128
134
  console.warn(
129
135
  `[get-esbuild-entries] Could not process imports of: ${absImportPathWithExt}`,
130
- err.message
136
+ err.message,
131
137
  );
132
138
  }
133
139
  }
@@ -203,7 +209,7 @@ export default async function getEsbuildEntries({
203
209
  code,
204
210
  absPath,
205
211
  new Set(),
206
- true
212
+ true,
207
213
  );
208
214
  const clientComponentRegex = /\.(js|jsx|ts|tsx)$/i;
209
215
  imports.forEach((imp) => {
@@ -218,14 +224,14 @@ export default async function getEsbuildEntries({
218
224
  } else if (isPageOrLayout(absPath)) {
219
225
  if (!isAsyncDefaultExport(code)) {
220
226
  console.warn(
221
- `[react-client-manifest] The file ${normalizedPath} is a page or layout without "use client" directive, but its default export is not an async function.`
227
+ `[react-client-manifest] The file ${normalizedPath} is a page or layout without "use client" directive, but its default export is not an async function.`,
222
228
  );
223
229
  }
224
230
  serverModules.add(normalizedPath);
225
231
  try {
226
232
  const { imports, assets, csss } = await getImportsAndAssetsAndCsss(
227
233
  code,
228
- absPath
234
+ absPath,
229
235
  );
230
236
 
231
237
  if (csss.length > 0) {
@@ -233,7 +239,7 @@ export default async function getEsbuildEntries({
233
239
  ...csss.map((cssPath) => ({
234
240
  absPath: normalizePath(cssPath),
235
241
  name: path.basename(cssPath, path.extname(cssPath)),
236
- }))
242
+ })),
237
243
  );
238
244
  }
239
245
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dinou-ejected",
3
- "version": "4.0.5",
3
+ "version": "4.0.7",
4
4
  "main": "index.js",
5
5
  "private": true,
6
6
  "exports": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dinou",
3
- "version": "4.0.5",
3
+ "version": "4.0.7",
4
4
  "description": "Full-Stack React 19 framework with React Server Components, Server Functions, and Streaming SSR.",
5
5
  "main": "index.js",
6
6
  "bin": {