dinou 4.0.0 → 4.0.2

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.2]
9
+
10
+ ### Fixed
11
+
12
+ - Export dinou as ESM too.
13
+
14
+ ## [4.0.1]
15
+
16
+ ### Fixed
17
+
18
+ - Starting sequence of the server (generate static pages on background).
19
+
8
20
  ## [4.0.0]
9
21
 
10
22
  ### 🚀 Major Release
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # **Dinou**
2
2
 
3
+ [![Documentation](https://img.shields.io/badge/docs-dinou.dev-blue?style=flat-square)](https://dinou.dev)
4
+
3
5
  ### **Full-Stack React 19 Framework**
4
6
 
5
7
  ---
@@ -1314,7 +1316,7 @@ Netlify is currently incompatible because it does not support passing custom Nod
1314
1316
  Ensure your platform allows customization of the start command. Your start command should look like:
1315
1317
 
1316
1318
  ```bash
1317
- node --conditions react-server dist3/index.js
1319
+ node --conditions react-server ...
1318
1320
  ```
1319
1321
 
1320
1322
  _(Or use `npm start` if your package.json scripts are configured correctly)._
@@ -119,10 +119,10 @@ function formatErrorHtmlProduction(error) {
119
119
 
120
120
  function writeErrorOutput(error, isProd) {
121
121
  process.stdout.write(
122
- isProd ? formatErrorHtmlProduction(error) : formatErrorHtml(error)
122
+ isProd ? formatErrorHtmlProduction(error) : formatErrorHtml(error),
123
123
  );
124
124
  process.stderr.write(
125
- JSON.stringify({ error: error.message, stack: error.stack })
125
+ JSON.stringify({ error: error.message, stack: error.stack }),
126
126
  );
127
127
  }
128
128
 
@@ -132,7 +132,7 @@ async function renderToStream(
132
132
  serializedBox,
133
133
  isDynamic,
134
134
  hasJsxJson,
135
- jsxJson
135
+ jsxJson,
136
136
  ) {
137
137
  const context = {
138
138
  req: serializedBox.req,
@@ -146,12 +146,12 @@ async function renderToStream(
146
146
  isDynamic ||
147
147
  !hasJsxJson
148
148
  ? renderJSXToClientJSX(
149
- await getJSX(reqPath, query, isNotFound, isDevelopment)
149
+ await getJSX(reqPath, query, isNotFound, isDevelopment),
150
150
  )
151
- : (await getSSGJSX(jsxJson)) ??
151
+ : ((await getSSGJSX(jsxJson)) ??
152
152
  renderJSXToClientJSX(
153
- await getJSX(reqPath, query, isNotFound, isDevelopment)
154
- );
153
+ await getJSX(reqPath, query, isNotFound, isDevelopment),
154
+ ));
155
155
  if (isNotFound.value) {
156
156
  context.res.status(404);
157
157
  }
@@ -171,7 +171,7 @@ async function renderToStream(
171
171
  reqPath,
172
172
  query,
173
173
  error,
174
- isDevelopment
174
+ isDevelopment,
175
175
  );
176
176
 
177
177
  if (!context.res.headersSent) context.res.status(500);
@@ -200,11 +200,11 @@ async function renderToStream(
200
200
  ].filter(Boolean)
201
201
  : [getAssetFromManifest("error.js")],
202
202
  bootstrapScriptContent: `window.__DINOU_ERROR_MESSAGE__=${JSON.stringify(
203
- error.message || "Unknown error"
203
+ error.message || "Unknown error",
204
204
  )};window.__DINOU_ERROR_NAME__=${JSON.stringify(error.name)};${
205
205
  isDevelopment
206
206
  ? `window.__DINOU_ERROR_STACK__=${JSON.stringify(
207
- error.stack || "No stack trace available"
207
+ error.stack || "No stack trace available",
208
208
  )};`
209
209
  : ""
210
210
  }${
@@ -244,19 +244,19 @@ async function renderToStream(
244
244
  JSON.stringify({
245
245
  error: error.message,
246
246
  stack: error.stack,
247
- })
247
+ }),
248
248
  );
249
249
  process.exit(1);
250
250
  }
251
251
  });
252
252
  }
253
253
 
254
- const reqPath = process.argv[2];
255
- const query = JSON.parse(process.argv[3]);
254
+ const reqPath = process.argv[2] || "/";
255
+ const query = JSON.parse(process.argv[3] || "{}");
256
256
  const serializedBox = JSON.parse(process.argv[4] || "{}");
257
257
  const isDynamic = process.argv[5] === "true";
258
258
  const hasJsxJson = process.argv[6] === "true";
259
- const jsxJson = JSON.parse(process.argv[7]);
259
+ const jsxJson = JSON.parse(process.argv[7] || "{}");
260
260
 
261
261
  process.on("uncaughtException", (error) => {
262
262
  process.stdout.write(formatErrorHtml(error));
@@ -264,7 +264,7 @@ process.on("uncaughtException", (error) => {
264
264
  JSON.stringify({
265
265
  error: error.message,
266
266
  stack: error.stack,
267
- })
267
+ }),
268
268
  );
269
269
  process.exit(1);
270
270
  });
@@ -276,7 +276,7 @@ process.on("unhandledRejection", (reason) => {
276
276
  JSON.stringify({
277
277
  error: error.message,
278
278
  stack: error.stack,
279
- })
279
+ }),
280
280
  );
281
281
  process.exit(1);
282
282
  });
@@ -287,7 +287,7 @@ renderToStream(
287
287
  serializedBox,
288
288
  isDynamic,
289
289
  hasJsxJson,
290
- jsxJson
290
+ jsxJson,
291
291
  ).catch((err) => {
292
292
  console.error("❌ Fatal error starting render stream:", err);
293
293
  process.exit(1);
@@ -436,42 +436,14 @@ function getContextForServerFunctionEndpoint(req, res) {
436
436
 
437
437
  app.use(express.static(path.resolve(process.cwd(), outputFolder)));
438
438
 
439
- // app.use((req, res, next) => {
440
- // // Make sure NOT to return 200 if what is requested is a .js that doesn't exist
441
- // if (
442
- // req.path.endsWith(".js") ||
443
- // req.path.endsWith(".css") ||
444
- // req.path.endsWith(".png") ||
445
- // req.path.endsWith(".jpg") ||
446
- // req.path.endsWith(".svg") ||
447
- // req.path.endsWith(".webp") ||
448
- // req.path.endsWith(".ico") ||
449
- // req.path.endsWith(".json")
450
- // ) {
451
- // return res.status(404).send("Not found");
452
- // }
453
- // next();
454
- // // ... Dinou rendering ...
455
- // });
456
-
457
439
  let isReady = isDevelopment; // In dev we are always ready (or almost)
458
440
 
459
- // 1. "Blocking" Middleware (Put BEFORE your Dinou routes, but AFTER express.static)
460
- // Ideal order:
461
- // app.use(express.static(...));
462
- // app.use(404AssetsMiddlewareWeMadeBefore);
463
-
464
- app.use((req, res, next) => {
465
- // If we are in PROD and generateStatic hasn't finished yet...
466
- if (!isReady) {
467
- // Optional: Allow health-checks or assets if you want
468
- // if (req.path.endsWith('.js')) return next();
469
-
470
- // Return 503 (Service Unavailable)
471
- // Playwright understands that 503 means "Keep waiting"
472
- return res.status(503).send("Server warming up (generating static)...");
473
- }
474
- next();
441
+ app.get("/__DINOU_STATUS_PLAYWRIGHT__", (req, res) => {
442
+ res.json({
443
+ status: "ok",
444
+ isReady,
445
+ mode: isDevelopment ? "development" : "production",
446
+ });
475
447
  });
476
448
 
477
449
  app.get("/.well-known/appspecific/com.chrome.devtools.json", (req, res) => {
@@ -759,8 +731,8 @@ app.get(/^\/.*\/?$/, (req, res) => {
759
731
  if (
760
732
  !isDevelopment &&
761
733
  res.statusCode === 200 && // Only if success
762
- req.method === "GET" // Only GET requests
763
- /*Object.keys({ ...req.query }).length === 0*/ // No query params (avoid infinite duplicates)
734
+ req.method === "GET" && // Only GET requests
735
+ isReady
764
736
  ) {
765
737
  generatingISG(reqPath, dynamicState);
766
738
  }
@@ -983,70 +955,54 @@ const port = process.env.PORT || 3000;
983
955
 
984
956
  const http = require("http");
985
957
 
986
- // Wrap the entire startup in an async IIFE to use await cleanly
958
+ // ============================================================
959
+ // STARTUP SEQUENCE
960
+ // ============================================================
987
961
  (async () => {
988
962
  try {
989
- // ============================================================
990
- // PHASE 1: STATIC GENERATION (Build Time)
991
- // ============================================================
992
- // We do this BEFORE creating the server. This way, if generateStatic
993
- // performs aggressive memory cleanups, it doesn't kill the HTTP server.
994
- if (!isDevelopment) {
995
- console.log("🏗️ [Startup] Starting static generation (SSG/ISR)...");
996
- try {
997
- await generateStatic();
998
- console.log("✅ [Startup] Static generation finished successfully.");
999
- } catch (buildError) {
1000
- console.error("❌ [Startup] Static generation failed:", buildError);
1001
- // Depending on your policy, you could exit (process.exit(1)) or continue
1002
- // If you decide to continue, the server will start but files might be missing.
1003
- process.exit(1);
1004
- }
1005
- } else {
1006
- console.log(
1007
- "⚙️ [Startup] Running in Development Mode (Dynamic Rendering)"
1008
- );
1009
- }
1010
-
1011
- // ============================================================
1012
- // PHASE 2: SERVER CREATION
1013
- // ============================================================
1014
963
  console.log("👉 [Startup] Initializing HTTP Server...");
1015
-
1016
- // We pass 'app' to createServer. This decouples Express from the network.
1017
964
  const server = http.createServer(app);
1018
965
 
1019
- // ============================================================
1020
- // PHASE 3: ERROR HANDLING (Anti-Zombies)
1021
- // ============================================================
1022
- // This captures errors like EADDRINUSE before they silently crash the process
966
+ // 2. ERROR HANDLING (Anti-Zombies)
1023
967
  server.on("error", (error) => {
1024
968
  if (error.code === "EADDRINUSE") {
1025
969
  console.error(`\n❌ FATAL ERROR: Port ${port} is already in use!`);
1026
- console.error(
1027
- ` Cause: A previous instance, a zombie test runner, or another app is holding the port.`
1028
- );
1029
- console.error(
1030
- ` Action: Run 'netstat -ano | findstr :${port}' (Win) or 'lsof -i :${port}' to find the PID and kill it.\n`
1031
- );
1032
970
  } else {
1033
971
  console.error("❌ [Server Error]:", error);
1034
972
  }
1035
- process.exit(1); // Explicitly exit with error code
973
+ process.exit(1);
1036
974
  });
1037
975
 
1038
- // ============================================================
1039
- // PHASE 4: STARTUP (Listen)
1040
- // ============================================================
1041
- server.listen(port, () => {
1042
- isReady = true;
1043
- console.log(
1044
- `\n🚀 Dinou Server is ready and listening on http://localhost:${port}`
1045
- );
1046
- console.log(
1047
- ` Environment: ${isDevelopment ? "Development" : "Production"}\n`
1048
- );
976
+ await new Promise((resolve) => {
977
+ server.listen(port, () => {
978
+ console.log(
979
+ `\n🚀 Dinou Server is ready and listening on http://localhost:${port}`
980
+ );
981
+ console.log(
982
+ ` Environment: ${isDevelopment ? "Development" : "Production"}`
983
+ );
984
+ resolve();
985
+ });
1049
986
  });
987
+
988
+ if (!isDevelopment) {
989
+ console.log("🏗️ [Background] Starting static generation (SSG)...");
990
+
991
+ generateStatic()
992
+ .then(() => {
993
+ console.log("✅ [Background] Static generation finished.");
994
+ isReady = true;
995
+ })
996
+ .catch((err) => {
997
+ console.error(
998
+ "❌ [Background] Static generation failed (App continues in Dynamic Mode):",
999
+ err
1000
+ );
1001
+ isReady = true;
1002
+ });
1003
+ } else {
1004
+ console.log("⚙️ [Startup] Running in Development Mode");
1005
+ }
1050
1006
  } catch (error) {
1051
1007
  console.error("💥 [Fatal Startup Error]:", error);
1052
1008
  process.exit(1);
@@ -0,0 +1,13 @@
1
+ // dinou/index.mjs
2
+ import dinou from "./index.js";
3
+
4
+ export const getContext = dinou.getContext;
5
+ export const usePathname = dinou.usePathname;
6
+ export const useSearchParams = dinou.useSearchParams;
7
+ export const useRouter = dinou.useRouter;
8
+ export const useNavigationLoading = dinou.useNavigationLoading;
9
+ export const redirect = dinou.redirect;
10
+ export const ClientRedirect = dinou.ClientRedirect;
11
+ export const Link = dinou.Link;
12
+
13
+ export default dinou;
@@ -0,0 +1,74 @@
1
+ {
2
+ "name": "dinou",
3
+ "version": "4.0.1",
4
+ "main": "index.js",
5
+ "private": true,
6
+ "exports": {
7
+ ".": {
8
+ "import": "./index.mjs",
9
+ "require": "./index.js"
10
+ }
11
+ },
12
+ "types": "./index.d.ts",
13
+ "scripts": {
14
+ "test": "echo \"Error: no test specified\" && exit 1"
15
+ },
16
+ "dependencies": {
17
+ "@babel/core": "^7.27.4",
18
+ "@babel/parser": "^7.28.3",
19
+ "@babel/plugin-syntax-import-meta": "^7.10.4",
20
+ "@babel/plugin-transform-modules-commonjs": "^7.27.1",
21
+ "@babel/preset-react": "^7.27.1",
22
+ "@babel/preset-typescript": "^7.27.1",
23
+ "@babel/register": "^7.27.1",
24
+ "@babel/traverse": "^7.28.3",
25
+ "@esbuild-plugins/tsconfig-paths": "^0.1.2",
26
+ "@pmmmwh/react-refresh-webpack-plugin": "^0.6.2",
27
+ "@roggc/react-server-dom-esm": "^0.0.0-b061b597-20251212",
28
+ "@rollup/plugin-babel": "^6.0.4",
29
+ "@rollup/plugin-commonjs": "^28.0.6",
30
+ "@rollup/plugin-json": "^6.1.0",
31
+ "@rollup/plugin-node-resolve": "^16.0.1",
32
+ "@rollup/plugin-replace": "^6.0.2",
33
+ "@tailwindcss/postcss": "^4.1.10",
34
+ "autoprefixer": "^10.4.21",
35
+ "babel-loader": "^10.0.0",
36
+ "chokidar": "^4.0.3",
37
+ "commander": "^14.0.0",
38
+ "concurrently": "^9.2.0",
39
+ "cookie-parser": "^1.4.7",
40
+ "copy-webpack-plugin": "^13.0.1",
41
+ "cross-env": "^7.0.3",
42
+ "css-loader": "^7.1.2",
43
+ "css-modules-require-hook": "^4.2.3",
44
+ "dotenv": "^16.5.0",
45
+ "esbuild": "^0.27.0",
46
+ "esbuild-copy-static-files": "^0.1.0",
47
+ "express": "^5.1.0",
48
+ "generic-names": "^4.0.0",
49
+ "loader-utils": "^3.3.1",
50
+ "mini-css-extract-plugin": "^2.9.4",
51
+ "postcss": "^8.5.5",
52
+ "postcss-import": "^16.1.1",
53
+ "postcss-loader": "^8.2.0",
54
+ "postcss-modules": "^6.0.1",
55
+ "react-refresh": "^0.17.0",
56
+ "react-server-dom-webpack": "^19.2.3",
57
+ "rollup": "^4.46.2",
58
+ "rollup-plugin-copy": "^3.5.0",
59
+ "rollup-plugin-delete": "^3.0.1",
60
+ "rollup-plugin-postcss": "^4.0.2",
61
+ "rollup-plugin-tsconfig-paths": "^1.5.2",
62
+ "tailwindcss": "^4.1.10",
63
+ "tsconfig-paths": "^4.2.0",
64
+ "tsconfig-paths-webpack-plugin": "^4.2.0",
65
+ "webpack": "^5.103.0",
66
+ "webpack-cli": "^6.0.1",
67
+ "webpack-dev-server": "^5.2.2",
68
+ "ws": "^8.18.3"
69
+ },
70
+ "peerDependencies": {
71
+ "react": ">=19.2.3",
72
+ "react-dom": ">=19.2.3"
73
+ }
74
+ }
@@ -20,7 +20,7 @@ const manifestGeneratorPlugin = require("./rollup-plugins/manifest-generator-plu
20
20
  const isDevelopment = process.env.NODE_ENV !== "production";
21
21
  const outputDirectory = isDevelopment ? "public" : "dist3";
22
22
 
23
- const localDinouPath = path.resolve(process.cwd(), "dinou/index.js");
23
+ const localDinouPath = path.resolve(process.cwd(), "dinou");
24
24
  // const localNavigationPath = path.resolve(
25
25
  // process.cwd(),
26
26
  // "dinou/core/navigation.js"
@@ -30,7 +30,7 @@ const isEjected = fs.existsSync(localDinouPath);
30
30
  console.log(
31
31
  isEjected
32
32
  ? "🚀 [Dinou] Ejected Mode detected (Using local code)"
33
- : "📦 [Dinou] Library Mode detected (Using node_modules)"
33
+ : "📦 [Dinou] Library Mode detected (Using node_modules)",
34
34
  );
35
35
 
36
36
  // ----------------------------------------------------------------------
@@ -60,21 +60,21 @@ module.exports = async function () {
60
60
  ? {
61
61
  runtime: path.resolve(
62
62
  __dirname,
63
- "react-refresh/react-refresh-runtime.js"
63
+ "react-refresh/react-refresh-runtime.js",
64
64
  ),
65
65
  refresh: path.resolve(
66
66
  __dirname,
67
- "react-refresh/react-refresh-entry.js"
67
+ "react-refresh/react-refresh-entry.js",
68
68
  ),
69
69
  main: path.resolve(__dirname, "../core/client.jsx"),
70
70
  error: path.resolve(__dirname, "../core/client-error.jsx"),
71
71
  serverFunctionProxy: path.resolve(
72
72
  __dirname,
73
- "../core/server-function-proxy.js"
73
+ "../core/server-function-proxy.js",
74
74
  ),
75
75
  dinouClientRedirect: path.resolve(
76
76
  __dirname,
77
- "../core/client-redirect.jsx"
77
+ "../core/client-redirect.jsx",
78
78
  ),
79
79
  }
80
80
  : {
@@ -82,11 +82,11 @@ module.exports = async function () {
82
82
  error: path.resolve(__dirname, "../core/client-error.jsx"),
83
83
  serverFunctionProxy: path.resolve(
84
84
  __dirname,
85
- "../core/server-function-proxy.js"
85
+ "../core/server-function-proxy.js",
86
86
  ),
87
87
  dinouClientRedirect: path.resolve(
88
88
  __dirname,
89
- "../core/client-redirect.jsx"
89
+ "../core/client-redirect.jsx",
90
90
  ),
91
91
  },
92
92
  output: {
@@ -110,7 +110,7 @@ module.exports = async function () {
110
110
  // "dinou",
111
111
  ],
112
112
  plugins: [
113
- isEjected && localDinouAlias(),
113
+ // isEjected && localDinouAlias(),
114
114
  del({
115
115
  targets: [
116
116
  `${outputDirectory}/*`,
@@ -124,7 +124,7 @@ module.exports = async function () {
124
124
  replace({
125
125
  preventAssignment: true,
126
126
  "process.env.NODE_ENV": JSON.stringify(
127
- isDevelopment ? "development" : "production"
127
+ isDevelopment ? "development" : "production",
128
128
  ),
129
129
  }),
130
130
  json(),
@@ -176,7 +176,7 @@ module.exports = async function () {
176
176
  reactClientManifest({
177
177
  manifestPath: path.join(
178
178
  "react_client_manifest",
179
- "react-client-manifest.json"
179
+ "react-client-manifest.json",
180
180
  ),
181
181
  }),
182
182
  isDevelopment && reactRefreshWrapModules(),
@@ -199,10 +199,10 @@ module.exports = async function () {
199
199
  }
200
200
  if (
201
201
  warning.message.includes(
202
- 'Module level directives cause errors when bundled, "use client"'
202
+ 'Module level directives cause errors when bundled, "use client"',
203
203
  ) ||
204
204
  warning.message.includes(
205
- 'Module level directives cause errors when bundled, "use server"'
205
+ 'Module level directives cause errors when bundled, "use server"',
206
206
  )
207
207
  ) {
208
208
  return;
@@ -28,33 +28,38 @@ function getConfigFileIfExists() {
28
28
 
29
29
  const configFile = getConfigFileIfExists();
30
30
 
31
- const localDinouPath = path.resolve(process.cwd(), "dinou/index.js");
31
+ const localDinouPath = path.resolve(process.cwd(), "dinou");
32
32
  const isEjected = fs.existsSync(localDinouPath);
33
33
 
34
34
  console.log(
35
35
  isEjected
36
36
  ? "🚀 [Dinou] Ejected Mode detected (Webpack: Using local code)"
37
- : "📦 [Dinou] Library Mode detected (Webpack: Using node_modules)"
37
+ : "📦 [Dinou] Library Mode detected (Webpack: Using node_modules)",
38
38
  );
39
39
 
40
40
  module.exports = async () => {
41
41
  const [cssEntries] = await getCSSEntries();
42
42
  return {
43
+ performance: {
44
+ hints: isDevelopment ? false : "warning",
45
+ maxEntrypointSize: 512000,
46
+ maxAssetSize: 512000,
47
+ },
43
48
  mode: isDevelopment ? "development" : "production",
44
49
  entry: {
45
50
  main: [path.resolve(__dirname, "../core/client-webpack.jsx")].filter(
46
- Boolean
51
+ Boolean,
47
52
  ),
48
53
  error: [
49
54
  path.resolve(__dirname, "../core/client-error-webpack.jsx"),
50
55
  ].filter(Boolean),
51
56
  serverFunctionProxy: path.resolve(
52
57
  __dirname,
53
- "../core/server-function-proxy-webpack.js"
58
+ "../core/server-function-proxy-webpack.js",
54
59
  ),
55
60
  dinouClientRedirect: path.resolve(
56
61
  __dirname,
57
- "../core/client-redirect.jsx"
62
+ "../core/client-redirect.jsx",
58
63
  ),
59
64
  dinouLink: path.resolve(__dirname, "../core/link.jsx"),
60
65
  ...[...cssEntries].reduce(
@@ -62,7 +67,7 @@ module.exports = async () => {
62
67
  ...acc,
63
68
  [cssEntry.outfileName]: cssEntry.absPath,
64
69
  }),
65
- {}
70
+ {},
66
71
  ),
67
72
  },
68
73
  experiments: {
@@ -95,12 +100,12 @@ module.exports = async () => {
95
100
 
96
101
  {
97
102
  test: /\.(js|jsx|ts|tsx)$/,
98
- include: [
99
- path.resolve(process.cwd(), "src"),
100
- path.resolve(__dirname, "../core"),
101
- path.resolve(process.cwd(), "node_modules/dinou"),
102
- isEjected && path.resolve(process.cwd(), "dinou"),
103
- ].filter(Boolean),
103
+ // include: [
104
+ // path.resolve(process.cwd(), "src"),
105
+ // path.resolve(__dirname, "../core"),
106
+ // path.resolve(process.cwd(), "node_modules/dinou"),
107
+ // isEjected && path.resolve(process.cwd(), "dinou"),
108
+ // ].filter(Boolean),
104
109
  use: {
105
110
  loader: "babel-loader",
106
111
  options: {
@@ -127,7 +132,7 @@ module.exports = async () => {
127
132
  {
128
133
  loader: path.resolve(
129
134
  __dirname,
130
- "./loaders/server-functions-loader.js"
135
+ "./loaders/server-functions-loader.js",
131
136
  ),
132
137
  },
133
138
  ],
@@ -182,7 +187,7 @@ module.exports = async () => {
182
187
 
183
188
  const base = path.basename(
184
189
  resourcePath,
185
- path.extname(resourcePath)
190
+ path.extname(resourcePath),
186
191
  );
187
192
  const scoped = createScopedName(base, resourcePath);
188
193
 
@@ -218,6 +223,10 @@ module.exports = async () => {
218
223
  resolve: {
219
224
  extensions: [".js", ".jsx", ".ts", ".tsx"],
220
225
  modules: ["src", "node_modules"],
226
+ extensionAlias: {
227
+ ".js": [".js", ".ts", ".tsx"],
228
+ ".jsx": [".jsx", ".tsx"],
229
+ },
221
230
  // 🎯 ADD THIS:
222
231
  alias: {
223
232
  ...(isEjected ? { dinou: localDinouPath } : {}),
package/eject.js CHANGED
@@ -1,14 +1,20 @@
1
1
  const fs = require("fs");
2
2
  const path = require("path");
3
+ const { execSync } = require("child_process");
3
4
 
4
5
  const dinouPath = path.resolve(__dirname, "dinou");
5
6
  const projectRoot = process.cwd();
6
7
 
8
+ console.log("🚀 Starting Dinou ejecting process...");
9
+
7
10
  fs.cpSync(dinouPath, path.join(projectRoot, "dinou"), {
8
11
  recursive: true,
9
12
  });
13
+ console.log("✅ Files copyed to ./dinou");
14
+
15
+ const pkgPath = path.join(projectRoot, "package.json");
16
+ const pkg = require(pkgPath);
10
17
 
11
- const pkg = require(path.join(projectRoot, "package.json"));
12
18
  pkg.scripts["dev:express"] =
13
19
  "node --conditions react-server --import ./dinou/core/register-loader.mjs ./dinou/core/server.js";
14
20
  pkg.scripts["dev_rollup"] = "rollup -c ./dinou/rollup/rollup.config.js -w";
@@ -39,9 +45,50 @@ pkg.scripts["start:webpack"] =
39
45
  "cross-env NODE_ENV=production DINOU_BUILD_TOOL=webpack node --conditions react-server --import ./dinou/core/register-loader.mjs ./dinou/core/server.js";
40
46
  pkg.scripts.start = "npm run start:esbuild";
41
47
  delete pkg.scripts.eject;
42
- fs.writeFileSync(
43
- path.join(projectRoot, "package.json"),
44
- JSON.stringify(pkg, null, 2)
45
- );
46
48
 
47
- console.log("Eject completed. Now you can customize the files in /dinou.");
49
+ if (!pkg.dependencies) {
50
+ pkg.dependencies = {};
51
+ }
52
+
53
+ pkg.dependencies["dinou"] = "file:./dinou";
54
+
55
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
56
+
57
+ function detectPackageManager() {
58
+ const userAgent = process.env.npm_config_user_agent;
59
+
60
+ if (userAgent) {
61
+ if (userAgent.startsWith("yarn")) return "yarn";
62
+ if (userAgent.startsWith("pnpm")) return "pnpm";
63
+ if (userAgent.startsWith("bun")) return "bun";
64
+ if (userAgent.startsWith("npm")) return "npm";
65
+ }
66
+
67
+ if (fs.existsSync(path.join(projectRoot, "yarn.lock"))) return "yarn";
68
+ if (fs.existsSync(path.join(projectRoot, "pnpm-lock.yaml"))) return "pnpm";
69
+ if (fs.existsSync(path.join(projectRoot, "bun.lockb"))) return "bun";
70
+ if (fs.existsSync(path.join(projectRoot, "package-lock.json"))) return "npm";
71
+
72
+ return "npm";
73
+ }
74
+
75
+ const pm = detectPackageManager();
76
+ console.log(`🕵️ Package manager detected: ${pm}`);
77
+
78
+ // const installCommand = pm === "yarn" ? "yarn" : `${pm} install`;
79
+ const installCommand = `${pm} install`;
80
+
81
+ console.log(`📦 Executing '${installCommand}' to link dependencies...`);
82
+
83
+ try {
84
+ execSync(installCommand, { stdio: "inherit", cwd: projectRoot });
85
+ console.log("✅ Dependencies updated successfully");
86
+ } catch (error) {
87
+ console.error(
88
+ `❌ Error on executing ${installCommand}. Please, install dependencies manually`,
89
+ );
90
+ }
91
+
92
+ console.log(
93
+ "🎉 Eject completed successfully! Dinou is now running from local source.",
94
+ );
package/package.json CHANGED
@@ -1,13 +1,16 @@
1
1
  {
2
2
  "name": "dinou",
3
- "version": "4.0.0",
3
+ "version": "4.0.2",
4
4
  "description": "Modern Full-Stack React 19 framework with React Server Components, Server Functions, and Streaming SSR.",
5
5
  "main": "index.js",
6
6
  "bin": {
7
7
  "dinou": "./cli.js"
8
8
  },
9
9
  "exports": {
10
- ".": "./dinou/index.js"
10
+ ".": {
11
+ "import": "./dinou/index.mjs",
12
+ "require": "./dinou/index.js"
13
+ }
11
14
  },
12
15
  "types": "./dinou/index.d.ts",
13
16
  "scripts": {