tempest-db-js 0.2.0 → 0.3.0

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/dist/index.cjs CHANGED
@@ -288,7 +288,9 @@ var DIALECT_ALIASES = {
288
288
  sqlite3: "sqlite",
289
289
  postgresql: "postgresql",
290
290
  postgres: "postgresql",
291
- pg: "postgresql"
291
+ pg: "postgresql",
292
+ mysql: "mysql",
293
+ mariadb: "mysql"
292
294
  };
293
295
  function splitScheme(scheme) {
294
296
  const plus = scheme.indexOf("+");
@@ -328,10 +330,10 @@ function parseSqlite(raw, driver, rest) {
328
330
  raw
329
331
  };
330
332
  }
331
- function parsePostgres(raw, driver, rest) {
333
+ function parseNetworkUrl(raw, driver, rest, dialect) {
332
334
  let parsed;
333
335
  try {
334
- parsed = new URL(`postgresql:${rest}`);
336
+ parsed = new URL(`${dialect}:${rest}`);
335
337
  } catch {
336
338
  throw new InvalidDatabaseUrl(raw, "could not parse host/credentials");
337
339
  }
@@ -339,7 +341,7 @@ function parsePostgres(raw, driver, rest) {
339
341
  const options = {};
340
342
  for (const [key, value] of parsed.searchParams) options[key] = value;
341
343
  return {
342
- dialect: "postgresql",
344
+ dialect,
343
345
  driver,
344
346
  host: parsed.hostname || null,
345
347
  port: parsed.port ? Number(parsed.port) : null,
@@ -364,7 +366,8 @@ function parseDatabaseUrl(url) {
364
366
  throw new InvalidDatabaseUrl(url, `unknown dialect ${JSON.stringify(base)}`);
365
367
  }
366
368
  const rest = url.slice(schemeEnd + 1);
367
- return dialect === "sqlite" ? parseSqlite(url, driver, rest) : parsePostgres(url, driver, rest);
369
+ if (dialect === "sqlite") return parseSqlite(url, driver, rest);
370
+ return parseNetworkUrl(url, driver, rest, dialect);
368
371
  }
369
372
  function detectDialect(url) {
370
373
  return parseDatabaseUrl(url).dialect;
@@ -663,18 +666,30 @@ var BaseDialect = class _BaseDialect {
663
666
  const rowsSql = node.values.map(() => `(${columns.map(() => this.placeholder(++position)).join(", ")})`).join(", ");
664
667
  let sql2 = `INSERT INTO ${this.quoteId(node.table)} (${colSql}) VALUES ${rowsSql}`;
665
668
  if (node.onConflict) {
666
- const target = node.onConflict.target.map((c) => this.quoteId(c)).join(", ");
667
- if (node.onConflict.update === "nothing") {
668
- sql2 += ` ON CONFLICT (${target}) DO NOTHING`;
669
- } else {
670
- const assignments = conflictCols.map((c) => `${this.quoteId(c)} = ${this.placeholder(++position)}`).join(", ");
671
- sql2 += ` ON CONFLICT (${target}) DO UPDATE SET ${assignments}`;
672
- }
669
+ sql2 += this.renderConflict(
670
+ node.onConflict,
671
+ conflictCols,
672
+ () => this.placeholder(++position)
673
+ );
673
674
  }
674
675
  sql2 += this.compileReturning(node.returning);
675
676
  _BaseDialect.insertTemplates.set(key, sql2);
676
677
  return sql2;
677
678
  }
679
+ /**
680
+ * Render the conflict-handling clause. Standard SQL (SQLite/PostgreSQL) uses
681
+ * `ON CONFLICT (...) DO NOTHING | DO UPDATE SET ...`; MySQL overrides this.
682
+ *
683
+ * @param onConflict The conflict clause from the node.
684
+ * @param conflictCols The columns to overwrite on `DO UPDATE` (empty for nothing).
685
+ * @param nextPlaceholder Yields the next positional placeholder (advances the count).
686
+ */
687
+ renderConflict(onConflict, conflictCols, nextPlaceholder) {
688
+ const target = onConflict.target.map((c) => this.quoteId(c)).join(", ");
689
+ if (onConflict.update === "nothing") return ` ON CONFLICT (${target}) DO NOTHING`;
690
+ const assignments = conflictCols.map((c) => `${this.quoteId(c)} = ${nextPlaceholder()}`).join(", ");
691
+ return ` ON CONFLICT (${target}) DO UPDATE SET ${assignments}`;
692
+ }
678
693
  compileUpdate(node, params) {
679
694
  const sets = Object.entries(node.set).map(([col, value]) => `${this.quoteId(col)} = ${params.bind(value)}`).join(", ");
680
695
  let sql2 = `UPDATE ${this.quoteId(node.table)} SET ${sets}`;
@@ -812,8 +827,46 @@ var PostgresDialect = class extends BaseDialect {
812
827
  return `${column2} ILIKE ${param}`;
813
828
  }
814
829
  };
830
+ var mysqlQuotedIds = /* @__PURE__ */ new Map();
831
+ var MysqlDialect = class extends BaseDialect {
832
+ name = "mysql";
833
+ placeholder() {
834
+ return "?";
835
+ }
836
+ ilike(column2, param) {
837
+ return `${column2} LIKE ${param}`;
838
+ }
839
+ quoteId(name) {
840
+ const cached = mysqlQuotedIds.get(name);
841
+ if (cached !== void 0) return cached;
842
+ const quoted = `\`${name.replace(/`/g, "``")}\``;
843
+ mysqlQuotedIds.set(name, quoted);
844
+ return quoted;
845
+ }
846
+ renderConflict(onConflict, conflictCols, nextPlaceholder) {
847
+ if (onConflict.update === "nothing") {
848
+ const col = this.quoteId(onConflict.target[0] ?? "id");
849
+ return ` ON DUPLICATE KEY UPDATE ${col} = ${col}`;
850
+ }
851
+ const assignments = conflictCols.map((c) => `${this.quoteId(c)} = ${nextPlaceholder()}`).join(", ");
852
+ return ` ON DUPLICATE KEY UPDATE ${assignments}`;
853
+ }
854
+ compileReturning(returning) {
855
+ if (returning === null) return "";
856
+ throw new Error(
857
+ "RETURNING is not supported on MySQL \u2014 insert, then SELECT by key (e.g. LAST_INSERT_ID())."
858
+ );
859
+ }
860
+ };
815
861
  function getDialect(name) {
816
- return name === "sqlite" ? new SqliteDialect() : new PostgresDialect();
862
+ switch (name) {
863
+ case "sqlite":
864
+ return new SqliteDialect();
865
+ case "postgresql":
866
+ return new PostgresDialect();
867
+ case "mysql":
868
+ return new MysqlDialect();
869
+ }
817
870
  }
818
871
 
819
872
  // src/join.ts
@@ -1576,12 +1629,76 @@ function createEngine(url, options) {
1576
1629
  options?.onQuery
1577
1630
  );
1578
1631
  }
1632
+ if (parsed.dialect === "mysql") {
1633
+ return new AsyncEngine(
1634
+ createMysqlDriver(parsed.raw, options?.pool),
1635
+ "mysql",
1636
+ options?.onQuery
1637
+ );
1638
+ }
1579
1639
  return new AsyncEngine(
1580
1640
  createPostgresDriver(parsed.raw, options?.pool),
1581
1641
  "postgresql",
1582
1642
  options?.onQuery
1583
1643
  );
1584
1644
  }
1645
+ function encodeMysqlParam(value) {
1646
+ if (value === void 0 || value === null) return null;
1647
+ if (typeof value === "boolean") return value ? 1 : 0;
1648
+ if (value instanceof Uint8Array) return value;
1649
+ if (value instanceof Date) return value;
1650
+ if (typeof value === "object") return JSON.stringify(value);
1651
+ return value;
1652
+ }
1653
+ function toMysqlResult(rows) {
1654
+ if (Array.isArray(rows)) {
1655
+ return { rows, changes: 0 };
1656
+ }
1657
+ const header = rows;
1658
+ return { rows: [], changes: header.affectedRows ?? 0 };
1659
+ }
1660
+ function createMysqlDriver(url, pool) {
1661
+ let poolHandle;
1662
+ const ensure = async () => {
1663
+ if (poolHandle) return;
1664
+ const moduleName = "mysql2/promise";
1665
+ const mod = await import(
1666
+ /* @vite-ignore */
1667
+ moduleName
1668
+ );
1669
+ const opts = { uri: url };
1670
+ if (pool?.size !== void 0) opts.connectionLimit = pool.size;
1671
+ if (pool?.idleTimeoutMs !== void 0) opts.idleTimeout = pool.idleTimeoutMs;
1672
+ if (pool?.connectTimeoutMs !== void 0) opts.connectTimeout = pool.connectTimeoutMs;
1673
+ poolHandle = mod.createPool(opts);
1674
+ };
1675
+ const runOn = async (queryable, sql2, params) => {
1676
+ const [rows] = await queryable.query(sql2, params.map(encodeMysqlParam));
1677
+ return toMysqlResult(rows);
1678
+ };
1679
+ return {
1680
+ async execute(sql2, params) {
1681
+ await ensure();
1682
+ return runOn(poolHandle, sql2, params);
1683
+ },
1684
+ async reserve() {
1685
+ await ensure();
1686
+ const conn = await poolHandle.getConnection();
1687
+ return {
1688
+ execute: (sql2, params) => runOn(conn, sql2, params),
1689
+ async release() {
1690
+ conn.release();
1691
+ },
1692
+ async close() {
1693
+ conn.release();
1694
+ }
1695
+ };
1696
+ },
1697
+ async close() {
1698
+ if (poolHandle) await poolHandle.end();
1699
+ }
1700
+ };
1701
+ }
1585
1702
  function toPostgresResult(rows) {
1586
1703
  const arr = rows;
1587
1704
  return { rows: Array.from(arr), changes: arr.count ?? arr.length };
@@ -1785,6 +1902,7 @@ exports.InsertBuilder = InsertBuilder;
1785
1902
  exports.InvalidDatabaseUrl = InvalidDatabaseUrl;
1786
1903
  exports.JoinBuilder = JoinBuilder;
1787
1904
  exports.Model = Model;
1905
+ exports.MysqlDialect = MysqlDialect;
1788
1906
  exports.NoResultError = NoResultError;
1789
1907
  exports.NodeSqliteDriver = NodeSqliteDriver;
1790
1908
  exports.OPERATORS = OPERATORS;