@nitronjs/framework 0.2.7 → 0.2.9
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/lib/Build/jsxRuntime.js +14 -4
- package/lib/Database/QueryBuilder.js +19 -5
- package/lib/HMR/Server.js +12 -39
- package/package.json +1 -1
package/lib/Build/jsxRuntime.js
CHANGED
|
@@ -96,18 +96,28 @@ function getWrappedComponent(Component) {
|
|
|
96
96
|
return componentCache.get(Component);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
function extractKey(props, key) {
|
|
100
|
+
if (props == null || !('key' in props)) {
|
|
101
|
+
return [props, key];
|
|
102
|
+
}
|
|
103
|
+
const { key: propKey, ...rest } = props;
|
|
104
|
+
return [rest, key ?? propKey];
|
|
105
|
+
}
|
|
106
|
+
|
|
99
107
|
export function jsx(type, props, key) {
|
|
108
|
+
const [cleanProps, finalKey] = extractKey(props, key);
|
|
100
109
|
if (typeof type === 'function' && type[MARK]) {
|
|
101
|
-
return OriginalJsx.jsx(getWrappedComponent(type),
|
|
110
|
+
return OriginalJsx.jsx(getWrappedComponent(type), cleanProps, finalKey);
|
|
102
111
|
}
|
|
103
|
-
return OriginalJsx.jsx(type,
|
|
112
|
+
return OriginalJsx.jsx(type, cleanProps, finalKey);
|
|
104
113
|
}
|
|
105
114
|
|
|
106
115
|
export function jsxs(type, props, key) {
|
|
116
|
+
const [cleanProps, finalKey] = extractKey(props, key);
|
|
107
117
|
if (typeof type === 'function' && type[MARK]) {
|
|
108
|
-
return OriginalJsx.jsx(getWrappedComponent(type),
|
|
118
|
+
return OriginalJsx.jsx(getWrappedComponent(type), cleanProps, finalKey);
|
|
109
119
|
}
|
|
110
|
-
return OriginalJsx.jsxs(type,
|
|
120
|
+
return OriginalJsx.jsxs(type, cleanProps, finalKey);
|
|
111
121
|
}
|
|
112
122
|
|
|
113
123
|
export const Fragment = OriginalJsx.Fragment;
|
|
@@ -59,6 +59,20 @@ class QueryBuilder {
|
|
|
59
59
|
return validateIdentifier(identifier);
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Quotes an identifier (table/column name) to handle reserved keywords.
|
|
64
|
+
* Uses backticks for MySQL compatibility.
|
|
65
|
+
* @param {string} identifier
|
|
66
|
+
* @returns {string}
|
|
67
|
+
*/
|
|
68
|
+
#quoteIdentifier(identifier) {
|
|
69
|
+
// Handle table.column format
|
|
70
|
+
if (identifier.includes('.')) {
|
|
71
|
+
return identifier.split('.').map(part => `\`${part}\``).join('.');
|
|
72
|
+
}
|
|
73
|
+
return `\`${identifier}\``;
|
|
74
|
+
}
|
|
75
|
+
|
|
62
76
|
#validateWhereOperator(operator) {
|
|
63
77
|
return validateWhereOperator(operator);
|
|
64
78
|
}
|
|
@@ -543,12 +557,12 @@ class QueryBuilder {
|
|
|
543
557
|
}
|
|
544
558
|
|
|
545
559
|
const columns = Object.keys(rows[0]);
|
|
546
|
-
columns.
|
|
560
|
+
const validatedColumns = columns.map(col => this.#validateIdentifier(col));
|
|
547
561
|
|
|
548
562
|
const placeholders = rows.map(() => `(${columns.map(() => '?').join(', ')})`).join(', ');
|
|
549
563
|
const values = rows.flatMap(row => columns.map(col => row[col]));
|
|
550
564
|
|
|
551
|
-
const sql = `INSERT INTO ${this.#table} (${
|
|
565
|
+
const sql = `INSERT INTO ${this.#quoteIdentifier(this.#table)} (${validatedColumns.join(', ')}) VALUES ${placeholders}`;
|
|
552
566
|
const [result] = await connection.query(sql, values);
|
|
553
567
|
|
|
554
568
|
|
|
@@ -584,7 +598,7 @@ class QueryBuilder {
|
|
|
584
598
|
}
|
|
585
599
|
}
|
|
586
600
|
|
|
587
|
-
const sql = `UPDATE ${this.#table} SET ${sets.join(', ')}${this.#compileWheres()}`;
|
|
601
|
+
const sql = `UPDATE ${this.#quoteIdentifier(this.#table)} SET ${sets.join(', ')}${this.#compileWheres()}`;
|
|
588
602
|
const [result] = await connection.query(sql, [...values, ...this.#bindings]);
|
|
589
603
|
|
|
590
604
|
return result.affectedRows;
|
|
@@ -602,7 +616,7 @@ class QueryBuilder {
|
|
|
602
616
|
async delete() {
|
|
603
617
|
const connection = await this.#getConnection();
|
|
604
618
|
try {
|
|
605
|
-
const sql = `DELETE FROM ${this.#table}${this.#compileWheres()}`;
|
|
619
|
+
const sql = `DELETE FROM ${this.#quoteIdentifier(this.#table)}${this.#compileWheres()}`;
|
|
606
620
|
const [result] = await connection.query(sql, this.#bindings);
|
|
607
621
|
|
|
608
622
|
return result.affectedRows;
|
|
@@ -630,7 +644,7 @@ class QueryBuilder {
|
|
|
630
644
|
const orders = this.#compileOrders();
|
|
631
645
|
const limit = this.#compileLimit();
|
|
632
646
|
|
|
633
|
-
return `SELECT ${distinct}${columns} FROM ${this.#table}${joins}${wheres}${groups}${havings}${orders}${limit}`;
|
|
647
|
+
return `SELECT ${distinct}${columns} FROM ${this.#quoteIdentifier(this.#table)}${joins}${wheres}${groups}${havings}${orders}${limit}`;
|
|
634
648
|
}
|
|
635
649
|
|
|
636
650
|
#compileJoins() {
|
package/lib/HMR/Server.js
CHANGED
|
@@ -34,16 +34,13 @@ class HMRServer {
|
|
|
34
34
|
registerRoutes(fastify) {
|
|
35
35
|
this.#clientScript = this.#findSocketIoClient();
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
fastify.get("/__nitron_client/socket.io.js", (req, reply) => {
|
|
38
38
|
if (!this.#clientScript) {
|
|
39
39
|
return reply.code(503).send("// HMR disabled: socket.io client not found");
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
reply.type("application/javascript").send(fs.readFileSync(this.#clientScript, "utf-8"));
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
// Support both paths for cache compatibility
|
|
46
|
-
fastify.get("/__nitron_client/socket.io.js", handler);
|
|
43
|
+
});
|
|
47
44
|
}
|
|
48
45
|
|
|
49
46
|
/**
|
|
@@ -160,57 +157,33 @@ class HMRServer {
|
|
|
160
157
|
// Private Methods
|
|
161
158
|
|
|
162
159
|
/**
|
|
163
|
-
* Finds socket.io client script
|
|
164
|
-
* Searches
|
|
165
|
-
* parent directories, and monorepo root.
|
|
160
|
+
* Finds socket.io client script.
|
|
161
|
+
* Searches framework node_modules and walks up directory tree for monorepo support.
|
|
166
162
|
* @returns {string|null} Path to socket.io.min.js or null if not found
|
|
167
163
|
*/
|
|
168
164
|
#findSocketIoClient() {
|
|
169
165
|
const clientFile = "client-dist/socket.io.min.js";
|
|
170
|
-
const possiblePaths = [];
|
|
171
166
|
|
|
172
|
-
// 1. Try resolving from framework package location
|
|
167
|
+
// 1. Try resolving from framework package location (most common case)
|
|
173
168
|
try {
|
|
174
169
|
const frameworkRequire = createRequire(import.meta.url);
|
|
175
170
|
const socketIoDir = path.dirname(frameworkRequire.resolve("socket.io/package.json"));
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
catch {}
|
|
179
|
-
|
|
180
|
-
// 2. Try resolving from project's node_modules
|
|
181
|
-
try {
|
|
182
|
-
const projectRequire = createRequire(path.join(process.cwd(), "package.json"));
|
|
183
|
-
const socketIoDir = path.dirname(projectRequire.resolve("socket.io/package.json"));
|
|
184
|
-
possiblePaths.push(path.join(socketIoDir, clientFile));
|
|
171
|
+
const clientPath = path.join(socketIoDir, clientFile);
|
|
172
|
+
if (fs.existsSync(clientPath)) return clientPath;
|
|
185
173
|
}
|
|
186
174
|
catch {}
|
|
187
175
|
|
|
188
|
-
//
|
|
189
|
-
let currentDir =
|
|
176
|
+
// 2. Walk up from framework location for monorepo setups
|
|
177
|
+
let currentDir = __dirname;
|
|
190
178
|
for (let i = 0; i < 5; i++) {
|
|
191
|
-
|
|
179
|
+
const clientPath = path.join(currentDir, "node_modules", "socket.io", clientFile);
|
|
180
|
+
if (fs.existsSync(clientPath)) return clientPath;
|
|
181
|
+
|
|
192
182
|
const parentDir = path.dirname(currentDir);
|
|
193
183
|
if (parentDir === currentDir) break;
|
|
194
184
|
currentDir = parentDir;
|
|
195
185
|
}
|
|
196
186
|
|
|
197
|
-
// 4. Walk up from framework package location
|
|
198
|
-
currentDir = __dirname;
|
|
199
|
-
for (let i = 0; i < 5; i++) {
|
|
200
|
-
possiblePaths.push(path.join(currentDir, "node_modules", "socket.io", clientFile));
|
|
201
|
-
const parentDir = path.dirname(currentDir);
|
|
202
|
-
if (parentDir === currentDir) break;
|
|
203
|
-
currentDir = parentDir;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// Find first existing path
|
|
207
|
-
for (const p of possiblePaths) {
|
|
208
|
-
if (fs.existsSync(p)) {
|
|
209
|
-
return p;
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
console.warn("[HMR] socket.io client not found. Searched paths:", possiblePaths);
|
|
214
187
|
return null;
|
|
215
188
|
}
|
|
216
189
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nitronjs/framework",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.9",
|
|
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"
|