tina4-nodejs 3.13.139 → 3.13.141

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.
@@ -5760,15 +5760,15 @@ function findOutsideQuotes(expr, needle) {
5760
5760
  }
5761
5761
  return -1;
5762
5762
  }
5763
- function splitOutsideQuotes(expr, sep8) {
5764
- if (!expr.includes(sep8)) return [expr];
5763
+ function splitOutsideQuotes(expr, sep9) {
5764
+ if (!expr.includes(sep9)) return [expr];
5765
5765
  const parts = [];
5766
5766
  let currentStart = 0;
5767
5767
  let inQuote = null;
5768
5768
  let depth = 0;
5769
5769
  let bracketDepth = 0;
5770
5770
  let i = 0;
5771
- const sepLen = sep8.length;
5771
+ const sepLen = sep9.length;
5772
5772
  const lastStart = expr.length - sepLen;
5773
5773
  while (i <= lastStart) {
5774
5774
  const ch = expr[i];
@@ -5789,7 +5789,7 @@ function splitOutsideQuotes(expr, sep8) {
5789
5789
  else if (ch === ")") depth--;
5790
5790
  else if (ch === "[") bracketDepth++;
5791
5791
  else if (ch === "]") bracketDepth--;
5792
- if (depth === 0 && bracketDepth === 0 && expr.startsWith(sep8, i)) {
5792
+ if (depth === 0 && bracketDepth === 0 && expr.startsWith(sep9, i)) {
5793
5793
  parts.push(expr.slice(currentStart, i));
5794
5794
  i += sepLen;
5795
5795
  currentStart = i;
@@ -6742,8 +6742,8 @@ var init_engine = __esm({
6742
6742
  },
6743
6743
  first: (v) => Array.isArray(v) ? v[0] ?? null : null,
6744
6744
  last: (v) => Array.isArray(v) ? v[v.length - 1] ?? null : null,
6745
- join: (v, sep8) => Array.isArray(v) ? v.map(String).join(sep8 !== void 0 ? String(sep8) : ", ") : String(v),
6746
- split: (v, sep8) => String(v).split(sep8 !== void 0 ? String(sep8) : " "),
6745
+ join: (v, sep9) => Array.isArray(v) ? v.map(String).join(sep9 !== void 0 ? String(sep9) : ", ") : String(v),
6746
+ split: (v, sep9) => String(v).split(sep9 !== void 0 ? String(sep9) : " "),
6747
6747
  replace: (v, from, to) => {
6748
6748
  const s = String(v);
6749
6749
  if (from !== void 0 && typeof from === "object" && from !== null && !Array.isArray(from)) {
@@ -13730,12 +13730,6 @@ function printResolution() {
13730
13730
  lines.push("");
13731
13731
  process.stderr.write(lines.join("\n"));
13732
13732
  }
13733
- function toPlural(name) {
13734
- const lower = name.toLowerCase();
13735
- if (lower.endsWith("s")) return lower;
13736
- if (lower.endsWith("y") && !/[aeiou]y$/i.test(lower)) return lower.slice(0, -1) + "ies";
13737
- return lower + "s";
13738
- }
13739
13733
  function toCamel(name) {
13740
13734
  return name.charAt(0).toLowerCase() + name.slice(1);
13741
13735
  }
@@ -14168,7 +14162,7 @@ ${aiFill(`delete_${singular}`, {
14168
14162
  }
14169
14163
  function generateCrud(name, flags) {
14170
14164
  const table2 = resolveTable(name, flags, { announce: false });
14171
- const routeName = toPlural(table2);
14165
+ const routeName = pluralizeReserved(toSnake(name));
14172
14166
  const isPublic = Boolean(flags.public);
14173
14167
  if (!__resolution.jsonMode) console.log(`
14174
14168
  Generating CRUD for ${name}...
@@ -14422,7 +14416,7 @@ void test${titleName};
14422
14416
  function generateForm(name, flags) {
14423
14417
  const fields = fieldsOrDefault(flags.fields || "");
14424
14418
  const table2 = resolveTable(name, flags, { announce: false });
14425
- const routeName = toPlural(table2);
14419
+ const routeName = pluralizeReserved(toSnake(name));
14426
14420
  const inputTypes = {
14427
14421
  string: "text",
14428
14422
  str: "text",
@@ -14488,7 +14482,7 @@ function generateForm(name, flags) {
14488
14482
  function generateView(name, flags) {
14489
14483
  const fields = fieldsOrDefault(flags.fields || "");
14490
14484
  const table2 = resolveTable(name, flags, { announce: false });
14491
- const routeName = toPlural(table2);
14485
+ const routeName = pluralizeReserved(toSnake(name));
14492
14486
  const cols = fields.map(([f]) => f);
14493
14487
  const dir = resolve6("src/templates/pages");
14494
14488
  ensureDir(dir);
@@ -15500,7 +15494,7 @@ var init_generate = __esm({
15500
15494
  crud: ({ name, table: table2 }) => [
15501
15495
  `Apply the migration: npx tina4nodejs migrate`,
15502
15496
  `Serve and try: npx tina4nodejs serve -> visit /swagger`,
15503
- `Run the gate test: npx tsx tests/${toPlural(table2)}.test.ts`,
15497
+ `Run the gate test: npx tsx tests/${pluralizeReserved(toSnake(name))}.test.ts`,
15504
15498
  `Change fields: edit src/models/${name}.ts then re-run generate crud`
15505
15499
  ],
15506
15500
  migration: () => [
@@ -15518,10 +15512,10 @@ var init_generate = __esm({
15518
15512
  ],
15519
15513
  form: ({ name, table: table2 }) => [
15520
15514
  `Render from a route: res.render("forms/${table2}.twig", { item })`,
15521
- `Add the POST route: npx tina4nodejs generate route ${toPlural(table2)} --model ${name}`
15515
+ `Add the POST route: npx tina4nodejs generate route ${pluralizeReserved(toSnake(name))} --model ${name}`
15522
15516
  ],
15523
- view: ({ table: table2 }) => [
15524
- `Wire routes to render list -> ${toPlural(table2)}.twig, detail -> ${table2}.twig`,
15517
+ view: ({ name, table: table2 }) => [
15518
+ `Wire routes to render list -> ${pluralizeReserved(toSnake(name))}.twig, detail -> ${table2}.twig`,
15525
15519
  `Customize the templates in src/templates/pages/`
15526
15520
  ],
15527
15521
  auth: () => [
@@ -27805,8 +27799,8 @@ function writeMcpDiscovery(projectRoot3, port) {
27805
27799
  const lines = contents.split(/\r?\n/);
27806
27800
  const already = lines.some((l) => l.trim() === GITIGNORE_LINE || l.trim() === ".tina4");
27807
27801
  if (!already) {
27808
- const sep8 = contents.endsWith("\n") || contents === "" ? "" : "\n";
27809
- fs9.writeFileSync(gitignorePath, `${contents}${sep8}${GITIGNORE_LINE}
27802
+ const sep9 = contents.endsWith("\n") || contents === "" ? "" : "\n";
27803
+ fs9.writeFileSync(gitignorePath, `${contents}${sep9}${GITIGNORE_LINE}
27810
27804
  `, "utf-8");
27811
27805
  }
27812
27806
  }
@@ -38134,14 +38128,72 @@ var init_cachedDatabase = __esm({
38134
38128
  }
38135
38129
  });
38136
38130
 
38131
+ // src/adapters/sqlCrud.ts
38132
+ function buildInsertRow(dialect, table2, data, suffix = "", options = {}) {
38133
+ const keys = Object.keys(data);
38134
+ const sql = buildInsert(dialect, table2, keys, suffix, options.startAt ?? 1);
38135
+ return { sql, values: Object.values(data) };
38136
+ }
38137
+ function buildInsertRows(dialect, table2, rows) {
38138
+ if (rows.length === 0) return null;
38139
+ const keys = Object.keys(rows[0]);
38140
+ const sql = buildInsert(dialect, table2, keys);
38141
+ const paramsList = rows.map((row) => keys.map((k) => row[k]));
38142
+ return { sql, paramsList };
38143
+ }
38144
+ function buildUpdate(dialect, table2, data, filter, params, options = {}) {
38145
+ const startAt = options.startAt ?? 1;
38146
+ const convertFragment = options.convertFragment ?? identityFragment;
38147
+ const dataKeys = Object.keys(data);
38148
+ const setClauses = buildSetClause(dialect, dataKeys, startAt);
38149
+ const whereStart = startAt + dataKeys.length;
38150
+ if (typeof filter === "string") {
38151
+ const where = filter ? ` WHERE ${convertFragment(filter, whereStart)}` : "";
38152
+ return {
38153
+ sql: `UPDATE ${dialect.quote(table2)} SET ${setClauses}${where}`,
38154
+ values: [...Object.values(data), ...params ?? []]
38155
+ };
38156
+ }
38157
+ const whereClauses = buildWhereClause(dialect, Object.keys(filter), whereStart);
38158
+ return {
38159
+ sql: `UPDATE ${dialect.quote(table2)} SET ${setClauses} WHERE ${whereClauses}`,
38160
+ values: [...Object.values(data), ...Object.values(filter)]
38161
+ };
38162
+ }
38163
+ function buildDelete(dialect, table2, filter, params, options = {}) {
38164
+ const startAt = options.startAt ?? 1;
38165
+ const convertFragment = options.convertFragment ?? identityFragment;
38166
+ if (typeof filter === "string") {
38167
+ const where = filter ? ` WHERE ${convertFragment(filter, startAt)}` : "";
38168
+ return {
38169
+ sql: `DELETE FROM ${dialect.quote(table2)}${where}`,
38170
+ values: params ?? []
38171
+ };
38172
+ }
38173
+ const whereClauses = buildWhereClause(dialect, Object.keys(filter), startAt);
38174
+ return {
38175
+ sql: `DELETE FROM ${dialect.quote(table2)} WHERE ${whereClauses}`,
38176
+ values: Object.values(filter)
38177
+ };
38178
+ }
38179
+ var identityFragment;
38180
+ var init_sqlCrud = __esm({
38181
+ "src/adapters/sqlCrud.ts"() {
38182
+ "use strict";
38183
+ init_sqlDialect();
38184
+ identityFragment = (fragment) => fragment;
38185
+ }
38186
+ });
38187
+
38137
38188
  // src/adapters/sqlite.ts
38138
38189
  var sqlite_exports = {};
38139
38190
  __export(sqlite_exports, {
38140
- SQLiteAdapter: () => SQLiteAdapter
38191
+ SQLiteAdapter: () => SQLiteAdapter,
38192
+ resolveSqlitePath: () => resolveSqlitePath
38141
38193
  });
38142
38194
  import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
38143
38195
  import { mkdirSync as mkdirSync18 } from "node:fs";
38144
- import { dirname as dirname13, isAbsolute as isAbsolute5, join as join29, resolve as resolve18 } from "node:path";
38196
+ import { dirname as dirname13, isAbsolute as isAbsolute5, join as join29, resolve as resolve18, sep as sep7 } from "node:path";
38145
38197
  function isIdentifier(str) {
38146
38198
  return /^[A-Za-z_][A-Za-z0-9_]*$/.test(str);
38147
38199
  }
@@ -38172,17 +38224,20 @@ function sqliteVersionAtLeast(major, minor, patch2) {
38172
38224
  }
38173
38225
  function resolveSqlitePath(dbPath) {
38174
38226
  if (dbPath === ":memory:") return dbPath;
38175
- let path10 = dbPath;
38176
- if (!isAbsolute5(path10)) {
38177
- path10 = join29(process.cwd(), path10);
38178
- mkdirSync18(dirname13(path10), { recursive: true });
38179
- } else {
38180
- const cwd = resolve18(process.cwd());
38181
- const abs = resolve18(path10);
38182
- if (abs.startsWith(cwd + "/") || abs === cwd) {
38183
- mkdirSync18(dirname13(abs), { recursive: true });
38184
- }
38227
+ const isWindowsAbs = /^[A-Za-z]:[\\/]/.test(dbPath);
38228
+ if (isAbsolute5(dbPath) || isWindowsAbs) {
38229
+ return dbPath;
38230
+ }
38231
+ const cwd = resolve18(process.cwd());
38232
+ const path10 = join29(cwd, dbPath);
38233
+ const parent = dirname13(path10);
38234
+ const absParent = resolve18(parent);
38235
+ if (absParent !== cwd && !absParent.startsWith(cwd + sep7)) {
38236
+ throw new Error(
38237
+ `SQLite path "${dbPath}" resolves outside the project directory: "${absParent}" is not within "${cwd}". Tina4 refuses to create directories outside the project (ADR-0086). Use an absolute path for a database that lives outside the project.`
38238
+ );
38185
38239
  }
38240
+ mkdirSync18(parent, { recursive: true, mode: 509 });
38186
38241
  return path10;
38187
38242
  }
38188
38243
  function fieldTypeToSQLite(def) {
@@ -38218,6 +38273,7 @@ var init_sqlite = __esm({
38218
38273
  "src/adapters/sqlite.ts"() {
38219
38274
  "use strict";
38220
38275
  init_sqlDialect();
38276
+ init_sqlCrud();
38221
38277
  init_sqlTranslator();
38222
38278
  _sqliteVersionInfo = null;
38223
38279
  SQLiteAdapter = class {
@@ -38338,16 +38394,12 @@ var init_sqlite = __esm({
38338
38394
  }
38339
38395
  insert(table2, data) {
38340
38396
  if (Array.isArray(data)) {
38341
- if (data.length === 0) return { success: true, affectedRows: 0 };
38342
- const keys2 = Object.keys(data[0]);
38343
- const sql2 = buildInsert(ANSI_DIALECT, table2, keys2);
38344
- const paramsList = data.map((row) => keys2.map((k) => row[k]));
38345
- const result = this.executeMany(sql2, paramsList);
38397
+ const batch = buildInsertRows(ANSI_DIALECT, table2, data);
38398
+ if (!batch) return { success: true, affectedRows: 0 };
38399
+ const result = this.executeMany(batch.sql, batch.paramsList);
38346
38400
  return { success: true, affectedRows: result.affectedRows, lastId: result.lastId };
38347
38401
  }
38348
- const keys = Object.keys(data);
38349
- const sql = buildInsert(ANSI_DIALECT, table2, keys);
38350
- const values = Object.values(data);
38402
+ const { sql, values } = buildInsertRow(ANSI_DIALECT, table2, data);
38351
38403
  try {
38352
38404
  const result = this.db.prepare(sql).run(...toSqlParams(values));
38353
38405
  this._lastInsertId = result.lastInsertRowid;
@@ -38357,21 +38409,7 @@ var init_sqlite = __esm({
38357
38409
  }
38358
38410
  }
38359
38411
  update(table2, data, filter, params) {
38360
- const setClauses = buildSetClause(ANSI_DIALECT, Object.keys(data));
38361
- if (typeof filter === "string") {
38362
- const where = filter ? ` WHERE ${filter}` : "";
38363
- const sql2 = `UPDATE ${ANSI_DIALECT.quote(table2)} SET ${setClauses}${where}`;
38364
- const values2 = [...Object.values(data), ...params ?? []];
38365
- try {
38366
- const result = this.db.prepare(sql2).run(...toSqlParams(values2));
38367
- return { success: true, affectedRows: Number(result.changes) };
38368
- } catch (e) {
38369
- return { success: false, affectedRows: 0, error: e.message };
38370
- }
38371
- }
38372
- const whereClauses = buildWhereClause(ANSI_DIALECT, Object.keys(filter));
38373
- const sql = `UPDATE ${ANSI_DIALECT.quote(table2)} SET ${setClauses} WHERE ${whereClauses}`;
38374
- const values = [...Object.values(data), ...Object.values(filter)];
38412
+ const { sql, values } = buildUpdate(ANSI_DIALECT, table2, data, filter, params);
38375
38413
  try {
38376
38414
  const result = this.db.prepare(sql).run(...toSqlParams(values));
38377
38415
  return { success: true, affectedRows: Number(result.changes) };
@@ -38388,18 +38426,7 @@ var init_sqlite = __esm({
38388
38426
  }
38389
38427
  return { success: true, affectedRows: totalAffected };
38390
38428
  }
38391
- if (typeof filter === "string") {
38392
- const sql2 = filter ? `DELETE FROM "${table2}" WHERE ${filter}` : `DELETE FROM "${table2}"`;
38393
- try {
38394
- const result = this.db.prepare(sql2).run(...toSqlParams(params ?? []));
38395
- return { success: true, affectedRows: Number(result.changes) };
38396
- } catch (e) {
38397
- return { success: false, affectedRows: 0, error: e.message };
38398
- }
38399
- }
38400
- const whereClauses = buildWhereClause(ANSI_DIALECT, Object.keys(filter));
38401
- const sql = `DELETE FROM ${ANSI_DIALECT.quote(table2)} WHERE ${whereClauses}`;
38402
- const values = Object.values(filter);
38429
+ const { sql, values } = buildDelete(ANSI_DIALECT, table2, filter, params);
38403
38430
  try {
38404
38431
  const result = this.db.prepare(sql).run(...toSqlParams(values));
38405
38432
  return { success: true, affectedRows: Number(result.changes) };
@@ -38691,6 +38718,7 @@ var init_postgres = __esm({
38691
38718
  "src/adapters/postgres.ts"() {
38692
38719
  "use strict";
38693
38720
  init_sqlDialect();
38721
+ init_sqlCrud();
38694
38722
  init_sqlTranslator();
38695
38723
  init_connectTimeout();
38696
38724
  pg = null;
@@ -38892,21 +38920,17 @@ var init_postgres = __esm({
38892
38920
  async insertAsync(table2, data) {
38893
38921
  this.ensureConnected();
38894
38922
  if (Array.isArray(data)) {
38895
- if (data.length === 0) return { success: true, affectedRows: 0 };
38896
- const keys2 = Object.keys(data[0]);
38897
- const sql2 = buildInsert(ANSI_DIALECT, table2, keys2);
38898
- const paramsList = data.map((row) => keys2.map((k) => row[k]));
38923
+ const batch = buildInsertRows(ANSI_DIALECT, table2, data);
38924
+ if (!batch) return { success: true, affectedRows: 0 };
38899
38925
  try {
38900
- const result = await this.executeManyAsync(sql2, paramsList);
38926
+ const result = await this.executeManyAsync(batch.sql, batch.paramsList);
38901
38927
  if (result.lastId !== void 0) this._lastInsertId = result.lastId;
38902
38928
  return { success: true, affectedRows: result.totalAffected, lastId: result.lastId };
38903
38929
  } catch (e) {
38904
38930
  return { success: false, affectedRows: 0, error: e.message };
38905
38931
  }
38906
38932
  }
38907
- const keys = Object.keys(data);
38908
- const sql = buildInsert(POSTGRES_DIALECT, table2, keys, " RETURNING *");
38909
- const values = Object.values(data);
38933
+ const { sql, values } = buildInsertRow(POSTGRES_DIALECT, table2, data, " RETURNING *");
38910
38934
  try {
38911
38935
  const result = await this.client.query(sql, values);
38912
38936
  const insertedRow = result.rows[0];
@@ -38926,26 +38950,10 @@ var init_postgres = __esm({
38926
38950
  }
38927
38951
  async updateAsync(table2, data, filter, params) {
38928
38952
  this.ensureConnected();
38929
- const dataKeys = Object.keys(data);
38930
- let paramIndex = 1;
38931
- const setClauses = buildSetClause(POSTGRES_DIALECT, dataKeys, paramIndex);
38932
- paramIndex += dataKeys.length;
38933
- if (typeof filter === "string") {
38934
- const where = filter ? ` WHERE ${this.convertPlaceholders(filter, paramIndex)}` : "";
38935
- const sql2 = `UPDATE ${POSTGRES_DIALECT.quote(table2)} SET ${setClauses}${where}`;
38936
- const values2 = [...Object.values(data), ...params ?? []];
38937
- try {
38938
- const result = await this.client.query(sql2, values2);
38939
- return { success: true, affectedRows: result.rowCount ?? 0 };
38940
- } catch (e) {
38941
- return { success: false, affectedRows: 0, error: e.message };
38942
- }
38943
- }
38944
- const filterKeys = Object.keys(filter);
38945
- const whereClauses = buildWhereClause(POSTGRES_DIALECT, filterKeys, paramIndex);
38946
- paramIndex += filterKeys.length;
38947
- const sql = `UPDATE ${POSTGRES_DIALECT.quote(table2)} SET ${setClauses} WHERE ${whereClauses}`;
38948
- const values = [...Object.values(data), ...Object.values(filter)];
38953
+ const { sql, values } = buildUpdate(POSTGRES_DIALECT, table2, data, filter, params, {
38954
+ startAt: 1,
38955
+ convertFragment: (fragment, startAt) => this.convertPlaceholders(fragment, startAt)
38956
+ });
38949
38957
  try {
38950
38958
  const result = await this.client.query(sql, values);
38951
38959
  return { success: true, affectedRows: result.rowCount ?? 0 };
@@ -38958,21 +38966,10 @@ var init_postgres = __esm({
38958
38966
  }
38959
38967
  async deleteAsync(table2, filter, params) {
38960
38968
  this.ensureConnected();
38961
- if (typeof filter === "string") {
38962
- const sql2 = filter ? `DELETE FROM "${table2}" WHERE ${this.bindable(filter, params)}` : `DELETE FROM "${table2}"`;
38963
- try {
38964
- const result = await this.client.query(sql2, params ?? []);
38965
- return { success: true, affectedRows: result.rowCount ?? 0 };
38966
- } catch (e) {
38967
- return { success: false, affectedRows: 0, error: e.message };
38968
- }
38969
- }
38970
- const filterKeys = Object.keys(filter);
38971
- let paramIndex = 1;
38972
- const whereClauses = buildWhereClause(POSTGRES_DIALECT, filterKeys, paramIndex);
38973
- paramIndex += filterKeys.length;
38974
- const sql = `DELETE FROM ${POSTGRES_DIALECT.quote(table2)} WHERE ${whereClauses}`;
38975
- const values = Object.values(filter);
38969
+ const { sql, values } = buildDelete(POSTGRES_DIALECT, table2, filter, params, {
38970
+ startAt: 1,
38971
+ convertFragment: (fragment) => this.bindable(fragment, params)
38972
+ });
38976
38973
  try {
38977
38974
  const result = await this.client.query(sql, values);
38978
38975
  return { success: true, affectedRows: result.rowCount ?? 0 };
@@ -39146,6 +39143,7 @@ var init_mysql = __esm({
39146
39143
  "src/adapters/mysql.ts"() {
39147
39144
  "use strict";
39148
39145
  init_sqlDialect();
39146
+ init_sqlCrud();
39149
39147
  init_sqlTranslator();
39150
39148
  init_connectTimeout();
39151
39149
  mysql2 = null;
@@ -39327,21 +39325,17 @@ var init_mysql = __esm({
39327
39325
  async insertAsync(table2, data) {
39328
39326
  this.ensureConnected();
39329
39327
  if (Array.isArray(data)) {
39330
- if (data.length === 0) return { success: true, affectedRows: 0 };
39331
- const keys2 = Object.keys(data[0]);
39332
- const sql2 = buildInsert(MYSQL_DIALECT, table2, keys2);
39333
- const paramsList = data.map((row) => keys2.map((k) => row[k]));
39328
+ const batch = buildInsertRows(MYSQL_DIALECT, table2, data);
39329
+ if (!batch) return { success: true, affectedRows: 0 };
39334
39330
  try {
39335
- const result = await this.executeManyAsync(sql2, paramsList);
39331
+ const result = await this.executeManyAsync(batch.sql, batch.paramsList);
39336
39332
  if (result.lastId !== void 0) this._lastInsertId = result.lastId;
39337
39333
  return { success: true, affectedRows: result.totalAffected, lastId: result.lastId };
39338
39334
  } catch (e) {
39339
39335
  return { success: false, affectedRows: 0, error: e.message };
39340
39336
  }
39341
39337
  }
39342
- const keys = Object.keys(data);
39343
- const sql = buildInsert(MYSQL_DIALECT, table2, keys);
39344
- const values = Object.values(data);
39338
+ const { sql, values } = buildInsertRow(MYSQL_DIALECT, table2, data);
39345
39339
  try {
39346
39340
  const result = await this.queryPromise(sql, values);
39347
39341
  this._lastInsertId = result.insertId ?? null;
@@ -39359,21 +39353,7 @@ var init_mysql = __esm({
39359
39353
  }
39360
39354
  async updateAsync(table2, data, filter, params) {
39361
39355
  this.ensureConnected();
39362
- const setClauses = buildSetClause(MYSQL_DIALECT, Object.keys(data));
39363
- if (typeof filter === "string") {
39364
- const where = filter ? ` WHERE ${filter}` : "";
39365
- const sql2 = `UPDATE ${MYSQL_DIALECT.quote(table2)} SET ${setClauses}${where}`;
39366
- const values2 = [...Object.values(data), ...params ?? []];
39367
- try {
39368
- const result = await this.queryPromise(sql2, values2);
39369
- return { success: true, affectedRows: result.affectedRows ?? 0 };
39370
- } catch (e) {
39371
- return { success: false, affectedRows: 0, error: e.message };
39372
- }
39373
- }
39374
- const whereClauses = buildWhereClause(MYSQL_DIALECT, Object.keys(filter));
39375
- const sql = `UPDATE ${MYSQL_DIALECT.quote(table2)} SET ${setClauses} WHERE ${whereClauses}`;
39376
- const values = [...Object.values(data), ...Object.values(filter)];
39356
+ const { sql, values } = buildUpdate(MYSQL_DIALECT, table2, data, filter, params);
39377
39357
  try {
39378
39358
  const result = await this.queryPromise(sql, values);
39379
39359
  return { success: true, affectedRows: result.affectedRows ?? 0 };
@@ -39386,18 +39366,7 @@ var init_mysql = __esm({
39386
39366
  }
39387
39367
  async deleteAsync(table2, filter, params) {
39388
39368
  this.ensureConnected();
39389
- if (typeof filter === "string") {
39390
- const sql2 = filter ? `DELETE FROM \`${table2}\` WHERE ${filter}` : `DELETE FROM \`${table2}\``;
39391
- try {
39392
- const result = await this.queryPromise(sql2, params ?? []);
39393
- return { success: true, affectedRows: result.affectedRows ?? 0 };
39394
- } catch (e) {
39395
- return { success: false, affectedRows: 0, error: e.message };
39396
- }
39397
- }
39398
- const whereClauses = buildWhereClause(MYSQL_DIALECT, Object.keys(filter));
39399
- const sql = `DELETE FROM ${MYSQL_DIALECT.quote(table2)} WHERE ${whereClauses}`;
39400
- const values = Object.values(filter);
39369
+ const { sql, values } = buildDelete(MYSQL_DIALECT, table2, filter, params);
39401
39370
  try {
39402
39371
  const result = await this.queryPromise(sql, values);
39403
39372
  return { success: true, affectedRows: result.affectedRows ?? 0 };
@@ -39549,6 +39518,7 @@ var init_mssql = __esm({
39549
39518
  "src/adapters/mssql.ts"() {
39550
39519
  "use strict";
39551
39520
  init_sqlDialect();
39521
+ init_sqlCrud();
39552
39522
  init_sqlTranslator();
39553
39523
  init_connectTimeout();
39554
39524
  tedious = null;
@@ -39805,21 +39775,17 @@ var init_mssql = __esm({
39805
39775
  async insertAsync(table2, data) {
39806
39776
  this.ensureConnected();
39807
39777
  if (Array.isArray(data)) {
39808
- if (data.length === 0) return { success: true, affectedRows: 0 };
39809
- const keys2 = Object.keys(data[0]);
39810
- const sql2 = buildInsert({ quote: MSSQL_DIALECT.quote, marker: ANSI_DIALECT.marker }, table2, keys2);
39811
- const paramsList = data.map((row) => keys2.map((k) => row[k]));
39778
+ const batch = buildInsertRows({ quote: MSSQL_DIALECT.quote, marker: ANSI_DIALECT.marker }, table2, data);
39779
+ if (!batch) return { success: true, affectedRows: 0 };
39812
39780
  try {
39813
- const result = await this.executeManyAsync(sql2, paramsList);
39781
+ const result = await this.executeManyAsync(batch.sql, batch.paramsList);
39814
39782
  if (result.lastId !== void 0) this._lastInsertId = result.lastId;
39815
39783
  return { success: true, affectedRows: result.totalAffected, lastId: result.lastId };
39816
39784
  } catch (e) {
39817
39785
  return { success: false, affectedRows: 0, error: e.message };
39818
39786
  }
39819
39787
  }
39820
- const keys = Object.keys(data);
39821
- const sql = buildInsert(MSSQL_DIALECT, table2, keys, "; SELECT SCOPE_IDENTITY() AS id", 0);
39822
- const values = Object.values(data);
39788
+ const { sql, values } = buildInsertRow(MSSQL_DIALECT, table2, data, "; SELECT SCOPE_IDENTITY() AS id", { startAt: 0 });
39823
39789
  try {
39824
39790
  const result = await this.execSqlPromise(sql, values);
39825
39791
  const id = result.rows[0]?.id ?? null;
@@ -39842,26 +39808,10 @@ var init_mssql = __esm({
39842
39808
  }
39843
39809
  async updateAsync(table2, data, filter, params) {
39844
39810
  this.ensureConnected();
39845
- const dataKeys = Object.keys(data);
39846
- let paramIndex = 0;
39847
- const setClauses = buildSetClause(MSSQL_DIALECT, dataKeys, paramIndex);
39848
- paramIndex += dataKeys.length;
39849
- if (typeof filter === "string") {
39850
- const where = filter ? ` WHERE ${this.convertPlaceholders(filter, paramIndex)}` : "";
39851
- const sql2 = `UPDATE ${MSSQL_DIALECT.quote(table2)} SET ${setClauses}${where}`;
39852
- const values2 = [...Object.values(data), ...params ?? []];
39853
- try {
39854
- const result = await this.execSqlPromise(sql2, values2);
39855
- return { success: true, affectedRows: result.rowCount };
39856
- } catch (e) {
39857
- return { success: false, affectedRows: 0, error: e.message };
39858
- }
39859
- }
39860
- const filterKeys = Object.keys(filter);
39861
- const whereClauses = buildWhereClause(MSSQL_DIALECT, filterKeys, paramIndex);
39862
- paramIndex += filterKeys.length;
39863
- const sql = `UPDATE ${MSSQL_DIALECT.quote(table2)} SET ${setClauses} WHERE ${whereClauses}`;
39864
- const values = [...Object.values(data), ...Object.values(filter)];
39811
+ const { sql, values } = buildUpdate(MSSQL_DIALECT, table2, data, filter, params, {
39812
+ startAt: 0,
39813
+ convertFragment: (fragment, startAt) => this.convertPlaceholders(fragment, startAt)
39814
+ });
39865
39815
  try {
39866
39816
  const result = await this.execSqlPromise(sql, values);
39867
39817
  return { success: true, affectedRows: result.rowCount };
@@ -39874,21 +39824,10 @@ var init_mssql = __esm({
39874
39824
  }
39875
39825
  async deleteAsync(table2, filter, params) {
39876
39826
  this.ensureConnected();
39877
- if (typeof filter === "string") {
39878
- const sql2 = filter ? `DELETE FROM [${table2}] WHERE ${this.bindable(filter, params)}` : `DELETE FROM [${table2}]`;
39879
- try {
39880
- const result = await this.execSqlPromise(sql2, params ?? []);
39881
- return { success: true, affectedRows: result.rowCount };
39882
- } catch (e) {
39883
- return { success: false, affectedRows: 0, error: e.message };
39884
- }
39885
- }
39886
- const filterKeys = Object.keys(filter);
39887
- let paramIndex = 0;
39888
- const whereClauses = buildWhereClause(MSSQL_DIALECT, filterKeys, paramIndex);
39889
- paramIndex += filterKeys.length;
39890
- const sql = `DELETE FROM ${MSSQL_DIALECT.quote(table2)} WHERE ${whereClauses}`;
39891
- const values = Object.values(filter);
39827
+ const { sql, values } = buildDelete(MSSQL_DIALECT, table2, filter, params, {
39828
+ startAt: 0,
39829
+ convertFragment: (fragment) => this.bindable(fragment, params)
39830
+ });
39892
39831
  try {
39893
39832
  const result = await this.execSqlPromise(sql, values);
39894
39833
  return { success: true, affectedRows: result.rowCount };
@@ -40141,6 +40080,7 @@ var init_firebird = __esm({
40141
40080
  "src/adapters/firebird.ts"() {
40142
40081
  "use strict";
40143
40082
  init_sqlDialect();
40083
+ init_sqlCrud();
40144
40084
  init_sqlTranslator();
40145
40085
  init_connectTimeout();
40146
40086
  firebird = null;
@@ -40511,17 +40451,13 @@ var init_firebird = __esm({
40511
40451
  async insertAsync(table2, data) {
40512
40452
  this.ensureConnected();
40513
40453
  if (Array.isArray(data)) {
40514
- if (data.length === 0) return { success: true, affectedRows: 0 };
40515
- const keys2 = Object.keys(data[0]);
40516
- const sql2 = buildInsert(FB_DIALECT, table2, keys2);
40517
- const paramsList = data.map((row) => keys2.map((k) => row[k]));
40518
- const result = await this.executeManyAsync(sql2, paramsList);
40454
+ const batch = buildInsertRows(FB_DIALECT, table2, data);
40455
+ if (!batch) return { success: true, affectedRows: 0 };
40456
+ const result = await this.executeManyAsync(batch.sql, batch.paramsList);
40519
40457
  const lastId2 = await this.readGeneratorId(table2) ?? result.lastId;
40520
40458
  return { success: true, affectedRows: result.totalAffected, lastId: lastId2 ?? void 0 };
40521
40459
  }
40522
- const keys = Object.keys(data);
40523
- const sql = buildInsert(FB_DIALECT, table2, keys);
40524
- const values = Object.values(data);
40460
+ const { sql, values } = buildInsertRow(FB_DIALECT, table2, data);
40525
40461
  await this.executePromise(sql, values);
40526
40462
  const lastId = await this.readGeneratorId(table2);
40527
40463
  return { success: true, affectedRows: 1, lastId: lastId ?? void 0 };
@@ -40531,18 +40467,7 @@ var init_firebird = __esm({
40531
40467
  }
40532
40468
  async updateAsync(table2, data, filter, params) {
40533
40469
  this.ensureConnected();
40534
- const setClauses = buildSetClause(FB_DIALECT, Object.keys(data));
40535
- if (typeof filter === "string") {
40536
- const where = filter ? ` WHERE ${filter}` : "";
40537
- const affected2 = await this.executeReturningCount(
40538
- `UPDATE ${fbQuote(table2)} SET ${setClauses}${where}`,
40539
- [...Object.values(data), ...params ?? []]
40540
- );
40541
- return { success: true, affectedRows: affected2 };
40542
- }
40543
- const whereClauses = buildWhereClause(FB_DIALECT, Object.keys(filter));
40544
- const sql = `UPDATE ${FB_DIALECT.quote(table2)} SET ${setClauses} WHERE ${whereClauses}`;
40545
- const values = [...Object.values(data), ...Object.values(filter)];
40470
+ const { sql, values } = buildUpdate(FB_DIALECT, table2, data, filter, params);
40546
40471
  const affected = await this.executeReturningCount(sql, values);
40547
40472
  return { success: true, affectedRows: affected };
40548
40473
  }
@@ -40551,14 +40476,7 @@ var init_firebird = __esm({
40551
40476
  }
40552
40477
  async deleteAsync(table2, filter, params) {
40553
40478
  this.ensureConnected();
40554
- if (typeof filter === "string") {
40555
- const where = filter ? ` WHERE ${filter}` : "";
40556
- const affected2 = await this.executeReturningCount(`DELETE FROM ${fbQuote(table2)}${where}`, params ?? []);
40557
- return { success: true, affectedRows: affected2 };
40558
- }
40559
- const whereClauses = buildWhereClause(FB_DIALECT, Object.keys(filter));
40560
- const sql = `DELETE FROM ${FB_DIALECT.quote(table2)} WHERE ${whereClauses}`;
40561
- const values = Object.values(filter);
40479
+ const { sql, values } = buildDelete(FB_DIALECT, table2, filter, params);
40562
40480
  const affected = await this.executeReturningCount(sql, values);
40563
40481
  return { success: true, affectedRows: affected };
40564
40482
  }
@@ -41390,6 +41308,7 @@ var init_odbc = __esm({
41390
41308
  "src/adapters/odbc.ts"() {
41391
41309
  "use strict";
41392
41310
  init_sqlDialect();
41311
+ init_sqlCrud();
41393
41312
  init_sqlTranslator();
41394
41313
  init_connectTimeout();
41395
41314
  odbcModule = null;
@@ -41589,16 +41508,12 @@ var init_odbc = __esm({
41589
41508
  async insertAsync(table2, data) {
41590
41509
  this.ensureConnected();
41591
41510
  if (Array.isArray(data)) {
41592
- if (data.length === 0) return { success: true, affectedRows: 0 };
41593
- const keys2 = Object.keys(data[0]);
41594
- const sql2 = buildInsert(ANSI_DIALECT, table2, keys2);
41595
- const paramsList = data.map((row) => keys2.map((k) => row[k]));
41596
- const { totalAffected } = await this.executeManyAsync(sql2, paramsList);
41511
+ const batch = buildInsertRows(ANSI_DIALECT, table2, data);
41512
+ if (!batch) return { success: true, affectedRows: 0 };
41513
+ const { totalAffected } = await this.executeManyAsync(batch.sql, batch.paramsList);
41597
41514
  return { success: true, affectedRows: totalAffected };
41598
41515
  }
41599
- const keys = Object.keys(data);
41600
- const sql = buildInsert(ANSI_DIALECT, table2, keys);
41601
- const values = Object.values(data);
41516
+ const { sql, values } = buildInsertRow(ANSI_DIALECT, table2, data);
41602
41517
  try {
41603
41518
  const result = await this.connection.query(sql, values);
41604
41519
  return { success: true, affectedRows: this.affectedCount(result), lastId: this._lastInsertId ?? void 0 };
@@ -41609,17 +41524,7 @@ var init_odbc = __esm({
41609
41524
  /** Update rows in a table matching filter. */
41610
41525
  async updateAsync(table2, data, filter, params) {
41611
41526
  this.ensureConnected();
41612
- const setClauses = buildSetClause(ANSI_DIALECT, Object.keys(data));
41613
- let whereSql;
41614
- let values;
41615
- if (typeof filter === "string") {
41616
- whereSql = filter;
41617
- values = [...Object.values(data), ...params ?? []];
41618
- } else {
41619
- whereSql = buildWhereClause(ANSI_DIALECT, Object.keys(filter));
41620
- values = [...Object.values(data), ...Object.values(filter)];
41621
- }
41622
- const sql = `UPDATE ${ANSI_DIALECT.quote(table2)} SET ${setClauses} WHERE ${whereSql}`;
41527
+ const { sql, values } = buildUpdate(ANSI_DIALECT, table2, data, filter, params);
41623
41528
  try {
41624
41529
  const result = await this.connection.query(sql, values);
41625
41530
  return { success: true, affectedRows: this.affectedCount(result) };
@@ -41638,18 +41543,7 @@ var init_odbc = __esm({
41638
41543
  }
41639
41544
  return { success: true, affectedRows: totalAffected };
41640
41545
  }
41641
- if (typeof filter === "string") {
41642
- const sql2 = filter ? `DELETE FROM "${table2}" WHERE ${filter}` : `DELETE FROM "${table2}"`;
41643
- try {
41644
- const result = await this.connection.query(sql2, params ?? []);
41645
- return { success: true, affectedRows: this.affectedCount(result) };
41646
- } catch (e) {
41647
- return { success: false, affectedRows: 0, error: e.message };
41648
- }
41649
- }
41650
- const whereClauses = buildWhereClause(ANSI_DIALECT, Object.keys(filter));
41651
- const sql = `DELETE FROM ${ANSI_DIALECT.quote(table2)} WHERE ${whereClauses}`;
41652
- const values = Object.values(filter);
41546
+ const { sql, values } = buildDelete(ANSI_DIALECT, table2, filter, params);
41653
41547
  try {
41654
41548
  const result = await this.connection.query(sql, values);
41655
41549
  return { success: true, affectedRows: this.affectedCount(result) };
@@ -48529,7 +48423,7 @@ var init_attachment = __esm({
48529
48423
  // src/realtime/storage.ts
48530
48424
  import { randomBytes as randomBytes11 } from "node:crypto";
48531
48425
  import { mkdirSync as mkdirSync21, readFileSync as readFileSync26, writeFileSync as writeFileSync18, unlinkSync as unlinkSync8, statSync as statSync19 } from "node:fs";
48532
- import { resolve as resolve20, sep as sep7 } from "node:path";
48426
+ import { resolve as resolve20, sep as sep8 } from "node:path";
48533
48427
  import { createRequire as createRequire8 } from "node:module";
48534
48428
  function loadAwsSdk(packageName) {
48535
48429
  try {
@@ -48582,7 +48476,7 @@ var init_storage = __esm({
48582
48476
  // Resolve inside the root and reject any traversal attempt.
48583
48477
  pathFor(key) {
48584
48478
  const target = resolve20(this.directory, key);
48585
- if (target !== this.directory && !target.startsWith(this.directory + sep7)) {
48479
+ if (target !== this.directory && !target.startsWith(this.directory + sep8)) {
48586
48480
  throw new Error(`unsafe storage key: ${JSON.stringify(key)}`);
48587
48481
  }
48588
48482
  return target;
@@ -49099,6 +48993,7 @@ __export(index_exports, {
49099
48993
  resolveDbPool: () => resolveDbPool,
49100
48994
  resolveFirebirdCharset: () => resolveFirebirdCharset,
49101
48995
  resolveGraphConnectTimeout: () => resolveGraphConnectTimeout,
48996
+ resolveSqlitePath: () => resolveSqlitePath,
49102
48997
  rollback: () => rollback,
49103
48998
  seedModels: () => seedModels,
49104
48999
  seedOrm: () => seedOrm,
@@ -49265,6 +49160,7 @@ export {
49265
49160
  resolveDbPool,
49266
49161
  resolveFirebirdCharset,
49267
49162
  resolveGraphConnectTimeout,
49163
+ resolveSqlitePath,
49268
49164
  rollback,
49269
49165
  seedModels,
49270
49166
  seedOrm,