@nitronjs/framework 0.3.3 → 0.3.4
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/cli/njs.js +1 -1
- package/lib/Build/CssBuilder.js +152 -136
- package/lib/Build/FileAnalyzer.js +52 -35
- package/lib/Build/Manager.js +144 -41
- package/lib/Build/ModuleGraph.js +84 -0
- package/lib/Build/PropUsageAnalyzer.js +2 -2
- package/lib/Build/plugins.js +35 -0
- package/lib/Console/Commands/DevCommand.js +301 -258
- package/lib/HMR/Server.js +93 -170
- package/lib/Runtime/Entry.js +3 -0
- package/lib/View/Client/hmr-client.js +217 -219
- package/lib/View/Client/refresh-entry.cjs +1 -0
- package/lib/View/View.js +7 -2
- package/package.json +8 -6
|
@@ -1,219 +1,217 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
if (
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
if (
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
.
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
function escapeHtml(str) {
|
|
204
|
-
return String(str || "")
|
|
205
|
-
.replace(/&/g, "&")
|
|
206
|
-
.replace(/</g, "<")
|
|
207
|
-
.replace(/>/g, ">");
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
})();
|
|
1
|
+
(function() {
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
var RSC_ENDPOINT = "/__nitron/rsc";
|
|
5
|
+
var ws = null;
|
|
6
|
+
var reconnectTimer = null;
|
|
7
|
+
|
|
8
|
+
function connect() {
|
|
9
|
+
if (ws) return;
|
|
10
|
+
|
|
11
|
+
var protocol = location.protocol === "https:" ? "wss:" : "ws:";
|
|
12
|
+
var url = protocol + "//" + location.host + "/__nitron_hmr";
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
ws = new WebSocket(url);
|
|
16
|
+
}
|
|
17
|
+
catch (e) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
ws.onopen = function() {
|
|
22
|
+
window.__nitron_hmr_connected__ = true;
|
|
23
|
+
hideErrorOverlay();
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
ws.onclose = function() {
|
|
27
|
+
window.__nitron_hmr_connected__ = false;
|
|
28
|
+
ws = null;
|
|
29
|
+
|
|
30
|
+
clearTimeout(reconnectTimer);
|
|
31
|
+
reconnectTimer = setTimeout(connect, 1000);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
ws.onerror = function() {
|
|
35
|
+
window.__nitron_hmr_connected__ = false;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
ws.onmessage = function(event) {
|
|
39
|
+
var msg;
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
msg = JSON.parse(event.data);
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (msg.type === "change") {
|
|
49
|
+
hideErrorOverlay();
|
|
50
|
+
|
|
51
|
+
if (msg.changeType === "css") {
|
|
52
|
+
refreshCss();
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
refetchRSC(msg.cssChanged);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (msg.type === "fast-refresh") {
|
|
60
|
+
hideErrorOverlay();
|
|
61
|
+
handleFastRefresh(msg);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (msg.type === "reload") {
|
|
65
|
+
location.reload();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (msg.type === "error") {
|
|
69
|
+
showErrorOverlay(msg.message || "Unknown error", msg.file);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function parseLengthPrefixed(text) {
|
|
75
|
+
var nl = text.indexOf("\n");
|
|
76
|
+
if (nl === -1) return null;
|
|
77
|
+
|
|
78
|
+
var len = parseInt(text.substring(0, nl), 10);
|
|
79
|
+
if (isNaN(len) || len < 0) return null;
|
|
80
|
+
|
|
81
|
+
var flight = text.substring(nl + 1, nl + 1 + len);
|
|
82
|
+
var jsonStr = text.substring(nl + 1 + len);
|
|
83
|
+
var data;
|
|
84
|
+
|
|
85
|
+
try { data = JSON.parse(jsonStr); }
|
|
86
|
+
catch (e) { return null; }
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
payload: flight,
|
|
90
|
+
meta: data.meta || null,
|
|
91
|
+
css: data.css || null,
|
|
92
|
+
translations: data.translations || null
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function refetchRSC(cssChanged) {
|
|
97
|
+
var rsc = window.__NITRON_RSC__;
|
|
98
|
+
|
|
99
|
+
if (!rsc || !rsc.root) {
|
|
100
|
+
location.reload();
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
var url = location.pathname + location.search;
|
|
105
|
+
|
|
106
|
+
fetch(RSC_ENDPOINT + "?url=" + encodeURIComponent(url), {
|
|
107
|
+
headers: { "X-Nitron-SPA": "1" },
|
|
108
|
+
credentials: "same-origin"
|
|
109
|
+
})
|
|
110
|
+
.then(function(r) {
|
|
111
|
+
if (!r.ok) throw new Error("HTTP " + r.status);
|
|
112
|
+
|
|
113
|
+
return r.text().then(function(text) {
|
|
114
|
+
return parseLengthPrefixed(text);
|
|
115
|
+
});
|
|
116
|
+
})
|
|
117
|
+
.then(function(d) {
|
|
118
|
+
if (!d || !d.payload) {
|
|
119
|
+
location.reload();
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (d.translations) {
|
|
124
|
+
var prev = window.__NITRON_TRANSLATIONS__;
|
|
125
|
+
|
|
126
|
+
window.__NITRON_TRANSLATIONS__ = prev
|
|
127
|
+
? Object.assign({}, prev, d.translations)
|
|
128
|
+
: d.translations;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
rsc.navigate(d.payload);
|
|
132
|
+
|
|
133
|
+
if (d.meta && d.meta.title) document.title = d.meta.title;
|
|
134
|
+
|
|
135
|
+
if (cssChanged) refreshCss();
|
|
136
|
+
})
|
|
137
|
+
.catch(function() {
|
|
138
|
+
location.reload();
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function refreshCss() {
|
|
143
|
+
var links = document.querySelectorAll('link[rel="stylesheet"]');
|
|
144
|
+
var timestamp = Date.now();
|
|
145
|
+
|
|
146
|
+
for (var i = 0; i < links.length; i++) {
|
|
147
|
+
var href = (links[i].href || "").split("?")[0];
|
|
148
|
+
links[i].href = href + "?t=" + timestamp;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function showErrorOverlay(message, file) {
|
|
153
|
+
hideErrorOverlay();
|
|
154
|
+
|
|
155
|
+
var overlay = document.createElement("div");
|
|
156
|
+
overlay.id = "__nitron_error__";
|
|
157
|
+
overlay.innerHTML =
|
|
158
|
+
'<div style="position:fixed;inset:0;background:rgba(0,0,0,.95);color:#ff4444;padding:32px;font-family:monospace;z-index:999999;overflow:auto">' +
|
|
159
|
+
'<div style="font-size:24px;font-weight:bold;margin-bottom:16px">Build Error</div>' +
|
|
160
|
+
'<div style="color:#888;margin-bottom:16px">' + escapeHtml(file || "") + '</div>' +
|
|
161
|
+
'<pre style="white-space:pre-wrap;background:#1a1a2e;padding:16px;border-radius:8px">' + escapeHtml(message) + '</pre>' +
|
|
162
|
+
'<button onclick="this.parentNode.parentNode.remove()" style="position:absolute;top:16px;right:16px;background:#333;color:#fff;border:none;padding:8px 16px;cursor:pointer;border-radius:4px">Close</button>' +
|
|
163
|
+
'</div>';
|
|
164
|
+
|
|
165
|
+
document.body.appendChild(overlay);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function hideErrorOverlay() {
|
|
169
|
+
var el = document.getElementById("__nitron_error__");
|
|
170
|
+
|
|
171
|
+
if (el) {
|
|
172
|
+
el.remove();
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function handleFastRefresh(msg) {
|
|
177
|
+
const chunks = msg.chunks || [];
|
|
178
|
+
const timestamp = msg.timestamp || Date.now();
|
|
179
|
+
const cssChanged = msg.cssChanged || false;
|
|
180
|
+
|
|
181
|
+
const promises = chunks.map(function(chunk) {
|
|
182
|
+
if (chunk.includes("..") || chunk.includes("://")) return Promise.resolve();
|
|
183
|
+
|
|
184
|
+
return import("/storage/" + chunk + "?t=" + timestamp);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
Promise.all(promises)
|
|
188
|
+
.then(function() {
|
|
189
|
+
if (window.$RefreshRuntime$) {
|
|
190
|
+
window.$RefreshRuntime$.performReactRefresh();
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (cssChanged) {
|
|
194
|
+
refreshCss();
|
|
195
|
+
}
|
|
196
|
+
})
|
|
197
|
+
.catch(function(err) {
|
|
198
|
+
console.warn("[HMR] Fast Refresh failed, full reload:", err.message);
|
|
199
|
+
location.reload();
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function escapeHtml(str) {
|
|
204
|
+
return String(str || "")
|
|
205
|
+
.replace(/&/g, "&")
|
|
206
|
+
.replace(/</g, "<")
|
|
207
|
+
.replace(/>/g, ">");
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (document.readyState === "loading") {
|
|
211
|
+
document.addEventListener("DOMContentLoaded", connect);
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
connect();
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
})();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require("react-refresh/runtime");
|
package/lib/View/View.js
CHANGED
|
@@ -735,10 +735,15 @@ class View {
|
|
|
735
735
|
runtimeScript += `<script${nonceAttr}>window.__NITRON_FLIGHT__=${JSON.stringify(escapedPayload)};</script>`;
|
|
736
736
|
}
|
|
737
737
|
|
|
738
|
+
const refreshScript = this.#isDev
|
|
739
|
+
? `<script src="/storage/js/react-refresh-runtime.js"${nonceAttr}></script>`
|
|
740
|
+
+ `<script${nonceAttr}>$RefreshRuntime$.injectIntoGlobalHook(window);window.$RefreshReg$=function(t,i){$RefreshRuntime$.register(t,"__mod__ "+i)};window.$RefreshSig$=function(){return $RefreshRuntime$.createSignatureFunctionForTransform()};</script>`
|
|
741
|
+
: "";
|
|
742
|
+
|
|
738
743
|
const vendorScript = `<script src="/storage/js/vendor.js"${nonceAttr}></script>`;
|
|
739
744
|
|
|
740
745
|
const hmrScript = this.#isDev
|
|
741
|
-
? `<script src="/
|
|
746
|
+
? `<script src="/storage/js/hmr.js"${nonceAttr}></script>`
|
|
742
747
|
: "";
|
|
743
748
|
|
|
744
749
|
const consumerScript = hasFlightPayload
|
|
@@ -757,7 +762,7 @@ ${this.#generateHead(meta, css)}
|
|
|
757
762
|
<body>
|
|
758
763
|
<div id="app">${html}</div>
|
|
759
764
|
${runtimeScript}
|
|
760
|
-
${vendorScript}${hmrScript}${consumerScript}${spaScript}${devIndicator}
|
|
765
|
+
${refreshScript}${vendorScript}${hmrScript}${consumerScript}${spaScript}${devIndicator}
|
|
761
766
|
</body>
|
|
762
767
|
</html>`;
|
|
763
768
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nitronjs/framework",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.4",
|
|
4
4
|
"description": "NitronJS is a modern and extensible Node.js MVC framework built on Fastify. It focuses on clean architecture, modular structure, and developer productivity, offering built-in routing, middleware, configuration management, CLI tooling, and native React integration for scalable full-stack applications.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"njs": "./cli/njs.js"
|
|
@@ -21,11 +21,11 @@
|
|
|
21
21
|
"@fastify/helmet": "^13.0.2",
|
|
22
22
|
"@fastify/multipart": "^9.3.0",
|
|
23
23
|
"@fastify/static": "^8.3.0",
|
|
24
|
-
"@
|
|
24
|
+
"@parcel/watcher": "^2.5.6",
|
|
25
|
+
"@tailwindcss/node": "^4.2.2",
|
|
25
26
|
"@types/react": "^19.2.7",
|
|
26
27
|
"@types/react-dom": "^19.2.3",
|
|
27
28
|
"bcrypt": "^5.1.1",
|
|
28
|
-
"chokidar": "^5.0.0",
|
|
29
29
|
"dotenv": "^17.2.3",
|
|
30
30
|
"es-module-lexer": "^2.0.0",
|
|
31
31
|
"esbuild": "^0.27.2",
|
|
@@ -33,15 +33,17 @@
|
|
|
33
33
|
"mysql2": "^3.16.0",
|
|
34
34
|
"nodemailer": "^7.0.11",
|
|
35
35
|
"otpauth": "^9.5.0",
|
|
36
|
-
"
|
|
36
|
+
"oxc-parser": "^0.121.0",
|
|
37
|
+
"oxc-transform": "^0.121.0",
|
|
37
38
|
"qrcode": "^1.5.4",
|
|
38
39
|
"react": "^19.2.3",
|
|
39
40
|
"react-dom": "^19.2.3",
|
|
41
|
+
"react-refresh": "^0.18.0",
|
|
40
42
|
"react-server-dom-webpack": "^19.2.4",
|
|
41
43
|
"redis": "^5.6.0",
|
|
42
|
-
"socket.io": "^4.8.1",
|
|
43
44
|
"tailwindcss": "^4.1.18",
|
|
44
|
-
"typescript": "^5.9.3"
|
|
45
|
+
"typescript": "^5.9.3",
|
|
46
|
+
"ws": "^8.18.3"
|
|
45
47
|
},
|
|
46
48
|
"keywords": [
|
|
47
49
|
"nitronjs",
|