@nitronjs/framework 0.2.6 → 0.2.8
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/Database/QueryBuilder.js +19 -5
- package/lib/HMR/Server.js +11 -35
- package/lib/View/View.js +1 -1
- package/package.json +1 -1
|
@@ -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,7 +34,7 @@ class HMRServer {
|
|
|
34
34
|
registerRoutes(fastify) {
|
|
35
35
|
this.#clientScript = this.#findSocketIoClient();
|
|
36
36
|
|
|
37
|
-
fastify.get("/
|
|
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
|
}
|
|
@@ -157,57 +157,33 @@ class HMRServer {
|
|
|
157
157
|
// Private Methods
|
|
158
158
|
|
|
159
159
|
/**
|
|
160
|
-
* Finds socket.io client script
|
|
161
|
-
* Searches
|
|
162
|
-
* parent directories, and monorepo root.
|
|
160
|
+
* Finds socket.io client script.
|
|
161
|
+
* Searches framework node_modules and walks up directory tree for monorepo support.
|
|
163
162
|
* @returns {string|null} Path to socket.io.min.js or null if not found
|
|
164
163
|
*/
|
|
165
164
|
#findSocketIoClient() {
|
|
166
165
|
const clientFile = "client-dist/socket.io.min.js";
|
|
167
|
-
const possiblePaths = [];
|
|
168
166
|
|
|
169
|
-
// 1. Try resolving from framework package location
|
|
167
|
+
// 1. Try resolving from framework package location (most common case)
|
|
170
168
|
try {
|
|
171
169
|
const frameworkRequire = createRequire(import.meta.url);
|
|
172
170
|
const socketIoDir = path.dirname(frameworkRequire.resolve("socket.io/package.json"));
|
|
173
|
-
|
|
171
|
+
const clientPath = path.join(socketIoDir, clientFile);
|
|
172
|
+
if (fs.existsSync(clientPath)) return clientPath;
|
|
174
173
|
}
|
|
175
174
|
catch {}
|
|
176
175
|
|
|
177
|
-
// 2.
|
|
178
|
-
|
|
179
|
-
const projectRequire = createRequire(path.join(process.cwd(), "package.json"));
|
|
180
|
-
const socketIoDir = path.dirname(projectRequire.resolve("socket.io/package.json"));
|
|
181
|
-
possiblePaths.push(path.join(socketIoDir, clientFile));
|
|
182
|
-
}
|
|
183
|
-
catch {}
|
|
184
|
-
|
|
185
|
-
// 3. Walk up from cwd looking for node_modules/socket.io
|
|
186
|
-
let currentDir = process.cwd();
|
|
176
|
+
// 2. Walk up from framework location for monorepo setups
|
|
177
|
+
let currentDir = __dirname;
|
|
187
178
|
for (let i = 0; i < 5; i++) {
|
|
188
|
-
|
|
179
|
+
const clientPath = path.join(currentDir, "node_modules", "socket.io", clientFile);
|
|
180
|
+
if (fs.existsSync(clientPath)) return clientPath;
|
|
181
|
+
|
|
189
182
|
const parentDir = path.dirname(currentDir);
|
|
190
183
|
if (parentDir === currentDir) break;
|
|
191
184
|
currentDir = parentDir;
|
|
192
185
|
}
|
|
193
186
|
|
|
194
|
-
// 4. Walk up from framework package location
|
|
195
|
-
currentDir = __dirname;
|
|
196
|
-
for (let i = 0; i < 5; i++) {
|
|
197
|
-
possiblePaths.push(path.join(currentDir, "node_modules", "socket.io", clientFile));
|
|
198
|
-
const parentDir = path.dirname(currentDir);
|
|
199
|
-
if (parentDir === currentDir) break;
|
|
200
|
-
currentDir = parentDir;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// Find first existing path
|
|
204
|
-
for (const p of possiblePaths) {
|
|
205
|
-
if (fs.existsSync(p)) {
|
|
206
|
-
return p;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
console.warn("[HMR] socket.io client not found. Searched paths:", possiblePaths);
|
|
211
187
|
return null;
|
|
212
188
|
}
|
|
213
189
|
}
|
package/lib/View/View.js
CHANGED
|
@@ -689,7 +689,7 @@ class View {
|
|
|
689
689
|
: "";
|
|
690
690
|
|
|
691
691
|
const hmrScript = this.#isDev
|
|
692
|
-
? `<script src="/
|
|
692
|
+
? `<script src="/__nitron_client/socket.io.js"${nonceAttr}></script><script src="/storage/js/hmr.js"${nonceAttr}></script>`
|
|
693
693
|
: "";
|
|
694
694
|
|
|
695
695
|
const hydrateScript = hasHydration
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nitronjs/framework",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8",
|
|
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"
|