@nitronjs/framework 0.2.7 → 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.
@@ -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.forEach(col => this.#validateIdentifier(col));
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} (${columns.join(', ')}) VALUES ${placeholders}`;
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
- const handler = (req, reply) => {
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 from multiple possible locations.
164
- * Searches in order: createRequire resolution, cwd node_modules,
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
- possiblePaths.push(path.join(socketIoDir, clientFile));
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
- // 3. Walk up from cwd looking for node_modules/socket.io
189
- let currentDir = process.cwd();
176
+ // 2. Walk up from framework location for monorepo setups
177
+ let currentDir = __dirname;
190
178
  for (let i = 0; i < 5; i++) {
191
- possiblePaths.push(path.join(currentDir, "node_modules", "socket.io", clientFile));
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.7",
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"