durcno 1.0.0-alpha.2 → 1.0.0-alpha.3

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.
Files changed (67) hide show
  1. package/dist/bin.cjs +34 -33
  2. package/dist/src/columns/common.d.mts +1 -1
  3. package/dist/src/connectors/bun.d.mts +2 -2
  4. package/dist/src/connectors/bun.mjs +15 -15
  5. package/dist/src/connectors/common.d.mts +86 -25
  6. package/dist/src/connectors/common.mjs +76 -28
  7. package/dist/src/connectors/pg.d.mts +3 -2
  8. package/dist/src/connectors/pg.mjs +18 -15
  9. package/dist/src/connectors/pglite.d.mts +4 -4
  10. package/dist/src/connectors/pglite.mjs +19 -19
  11. package/dist/src/connectors/postgres.d.mts +3 -2
  12. package/dist/src/connectors/postgres.mjs +17 -14
  13. package/dist/src/db.d.mts +7 -8
  14. package/dist/src/db.mjs +30 -39
  15. package/dist/src/filters/array.d.mts +2 -2
  16. package/dist/src/filters/custom.d.mts +1 -1
  17. package/dist/src/filters/index.d.mts +3 -3
  18. package/dist/src/index.d.mts +25 -50
  19. package/dist/src/index.mjs +14 -15
  20. package/dist/src/logger.d.mts +32 -0
  21. package/dist/src/logger.mjs +57 -0
  22. package/dist/src/query-builders/aggregates.d.mts +3 -4
  23. package/dist/src/query-builders/aggregates.mjs +2 -4
  24. package/dist/src/query-builders/count.d.mts +3 -4
  25. package/dist/src/query-builders/count.mjs +2 -4
  26. package/dist/src/query-builders/delete.d.mts +3 -4
  27. package/dist/src/query-builders/delete.mjs +4 -6
  28. package/dist/src/query-builders/distinct.d.mts +3 -4
  29. package/dist/src/query-builders/distinct.mjs +2 -4
  30. package/dist/src/query-builders/exists.d.mts +3 -4
  31. package/dist/src/query-builders/exists.mjs +2 -4
  32. package/dist/src/query-builders/first.d.mts +3 -4
  33. package/dist/src/query-builders/first.mjs +2 -4
  34. package/dist/src/query-builders/insert-returning.d.mts +4 -5
  35. package/dist/src/query-builders/insert-returning.mjs +3 -5
  36. package/dist/src/query-builders/insert.d.mts +4 -5
  37. package/dist/src/query-builders/insert.mjs +5 -9
  38. package/dist/src/query-builders/pre.d.mts +3 -5
  39. package/dist/src/query-builders/pre.mjs +3 -5
  40. package/dist/src/query-builders/query.d.mts +6 -4
  41. package/dist/src/query-builders/query.mjs +5 -0
  42. package/dist/src/query-builders/raw.d.mts +1 -1
  43. package/dist/src/query-builders/rq.d.mts +4 -5
  44. package/dist/src/query-builders/rq.mjs +10 -15
  45. package/dist/src/query-builders/select.d.mts +4 -5
  46. package/dist/src/query-builders/select.mjs +10 -14
  47. package/dist/src/query-builders/update.d.mts +4 -5
  48. package/dist/src/query-builders/update.mjs +6 -10
  49. package/dist/src/sql.d.mts +1 -1
  50. package/dist/src/table.d.mts +0 -2
  51. package/dist/src/wkx/binarywriter.mjs +103 -108
  52. package/dist/src/wkx/geometry.mjs +88 -95
  53. package/dist/src/wkx/geometrycollection.mjs +3 -6
  54. package/dist/src/wkx/index.mjs +1 -4
  55. package/dist/src/wkx/linestring.mjs +4 -8
  56. package/dist/src/wkx/multilinestring.mjs +4 -8
  57. package/dist/src/wkx/multipoint.mjs +4 -8
  58. package/dist/src/wkx/multipolygon.mjs +4 -8
  59. package/dist/src/wkx/parser.mjs +4 -8
  60. package/dist/src/wkx/point.mjs +147 -157
  61. package/dist/src/wkx/polygon.mjs +4 -8
  62. package/dist/src/wkx/types.mjs +30 -35
  63. package/dist/src/wkx/wktparser.mjs +2 -5
  64. package/dist/src/wkx/zigzag.mjs +5 -10
  65. package/package.json +5 -2
  66. package/dist/src/_virtual/_rolldown/runtime.mjs +0 -28
  67. package/dist/src/cli/helpers.mjs +0 -16
package/dist/bin.cjs CHANGED
@@ -8903,19 +8903,17 @@ function resolveConfigPath(argPath) {
8903
8903
  }
8904
8904
  return (0, import_node_path2.resolve)(process.cwd(), DURCNO_CONFIG_NAME);
8905
8905
  }
8906
- async function getSetup(argPath) {
8907
- const absPath = resolveConfigPath(argPath);
8906
+ async function loadConfig(absPath) {
8908
8907
  const mod = await import(absPath);
8909
- const { default: setup } = mod;
8910
- return setup;
8908
+ return mod.default;
8911
8909
  }
8912
8910
 
8913
8911
  // src/cli/commands/down.ts
8914
8912
  var { bgGreen, dim, cyan: cyan2, yellow: yellow2, red: red2 } = source_default;
8915
8913
  async function down(m, options) {
8916
8914
  const configPath = resolveConfigPath(options.config);
8917
- const { connector, config: config2 } = await getSetup(configPath);
8918
- config2.pool = { ...config2.pool, max: 1 };
8915
+ const config2 = await loadConfig(configPath);
8916
+ const { connector } = config2;
8919
8917
  const migrationsDir = (0, import_node_path3.resolve)(
8920
8918
  (0, import_node_path3.dirname)(configPath),
8921
8919
  config2.out || DEFAULT_MIGRATIONS_DIR
@@ -8925,7 +8923,7 @@ async function down(m, options) {
8925
8923
  const client = connector.getClient();
8926
8924
  await client.connect();
8927
8925
  if (await migrationsTableExists(client)) {
8928
- const db = (0, import_durcno2.database)({ Migrations: import_durcno2.Migrations }, { connector, config: config2 });
8926
+ const db = (0, import_durcno2.database)({ Migrations: import_durcno2.Migrations }, config2);
8929
8927
  const migrations = await db.from(import_durcno2.Migrations).select();
8930
8928
  const migrationDirsReversed = migrationDirNames.sort().reverse();
8931
8929
  for (let i = 0; i < migrationDirsReversed.length; i++) {
@@ -8939,7 +8937,7 @@ async function down(m, options) {
8939
8937
  migrationDirName,
8940
8938
  isFirstMigration,
8941
8939
  migrationsDir,
8942
- { connector, config: config2 },
8940
+ config2,
8943
8941
  client
8944
8942
  );
8945
8943
  if (migration.name === m) {
@@ -8954,7 +8952,7 @@ async function down(m, options) {
8954
8952
  await client.close();
8955
8953
  process.exit(0);
8956
8954
  }
8957
- async function runDownMigration(migrationDirName, isFirstMigration, migrationsDirPath, setup, client) {
8955
+ async function runDownMigration(migrationDirName, isFirstMigration, migrationsDirPath, config2, client) {
8958
8956
  const migrationName = (0, import_node_path3.basename)(migrationDirName);
8959
8957
  const downPath = (0, import_node_path3.join)(migrationsDirPath, migrationName, "down.ts");
8960
8958
  try {
@@ -8987,7 +8985,9 @@ async function runDownMigration(migrationDirName, isFirstMigration, migrationsDi
8987
8985
  throw e;
8988
8986
  }
8989
8987
  if (!isFirstMigration) {
8990
- const db = (0, import_durcno2.database)({ Migrations: import_durcno2.Migrations }, setup);
8988
+ config2.connector.pool = { ...config2.connector.pool, max: 1 };
8989
+ config2.connector.logger = void 0;
8990
+ const db = (0, import_durcno2.database)({ Migrations: import_durcno2.Migrations }, config2);
8991
8991
  await db.delete(import_durcno2.Migrations).where((0, import_durcno2.eq)(import_durcno2.Migrations.name, migrationName));
8992
8992
  await db.close();
8993
8993
  }
@@ -12234,7 +12234,7 @@ async function promptColumnRenames(prev, curr, renamedTables) {
12234
12234
  }
12235
12235
  async function generate(options) {
12236
12236
  const configPath = resolveConfigPath(options.config);
12237
- const { config: config2 } = await getSetup(configPath);
12237
+ const config2 = await loadConfig(configPath);
12238
12238
  const migrationsDir = (0, import_node_path4.resolve)(
12239
12239
  (0, import_node_path4.dirname)(configPath),
12240
12240
  config2.out || DEFAULT_MIGRATIONS_DIR
@@ -12803,12 +12803,14 @@ function generateConfigFile(config2) {
12803
12803
  return `${envLoader}import { defineConfig } from "durcno";
12804
12804
  import { ${funcName} } from "durcno/connectors/${connector}";
12805
12805
 
12806
- export default defineConfig(${funcName}(), {
12806
+ export default defineConfig({
12807
12807
  schema: "${schemaPath}",
12808
12808
  out: "${migrationsDir}",
12809
- dbCredentials: {
12810
- url: ${urlValue},
12811
- },
12809
+ connector: ${funcName}({
12810
+ dbCredentials: {
12811
+ url: ${urlValue},
12812
+ },
12813
+ }),
12812
12814
  });
12813
12815
  `;
12814
12816
  }
@@ -12830,9 +12832,9 @@ function generateIndexFile(schemaPath) {
12830
12832
  const schemaImport = schemaPath.replace(/^db\//, "./");
12831
12833
  return `import { database } from "durcno";
12832
12834
  import * as schema from "${schemaImport}";
12833
- import setup from "../durcno.config.ts";
12835
+ import config from "../durcno.config.ts";
12834
12836
 
12835
- export const db = database(schema, setup);
12837
+ export const db = database(schema, config);
12836
12838
  `;
12837
12839
  }
12838
12840
  async function promptConfig() {
@@ -13001,8 +13003,8 @@ var import_durcno3 = require("durcno");
13001
13003
  var { bgGreen: bgGreen3, bgYellow, dim: dim3, gray: gray4, yellow: yellow5, green: green2, cyan: cyan5 } = source_default;
13002
13004
  async function migrate(options) {
13003
13005
  const configPath = resolveConfigPath(options.config);
13004
- const { connector, config: config2 } = await getSetup(configPath);
13005
- config2.pool = { ...config2.pool, max: 1 };
13006
+ const config2 = await loadConfig(configPath);
13007
+ const { connector } = config2;
13006
13008
  const migrationsDir = (0, import_node_path6.resolve)(
13007
13009
  (0, import_node_path6.dirname)(configPath),
13008
13010
  config2.out || DEFAULT_MIGRATIONS_DIR
@@ -13015,16 +13017,13 @@ async function migrate(options) {
13015
13017
  try {
13016
13018
  let previouslyApplied = [];
13017
13019
  if (await migrationsTableExists(client)) {
13018
- const db = (0, import_durcno3.database)({ Migrations: import_durcno3.Migrations }, { connector, config: config2 });
13020
+ const db = (0, import_durcno3.database)({ Migrations: import_durcno3.Migrations }, config2);
13019
13021
  const records = await db.from(import_durcno3.Migrations).select();
13020
13022
  previouslyApplied = records.map((r) => r.name);
13021
13023
  }
13022
13024
  for (const migrationDirName of migrationDirNames.sort()) {
13023
13025
  if (!previouslyApplied.includes(migrationDirName)) {
13024
- await runUpMigration(migrationDirName, migrationsDir, client, {
13025
- connector,
13026
- config: config2
13027
- });
13026
+ await runUpMigration(migrationDirName, migrationsDir, client, config2);
13028
13027
  appliedMigrations.push(migrationDirName);
13029
13028
  }
13030
13029
  }
@@ -13040,7 +13039,7 @@ async function migrate(options) {
13040
13039
  migrationFolder,
13041
13040
  isFirstMigration,
13042
13041
  migrationsDir,
13043
- { connector, config: config2 },
13042
+ config2,
13044
13043
  client
13045
13044
  );
13046
13045
  }
@@ -13054,7 +13053,7 @@ async function migrate(options) {
13054
13053
  await client.close();
13055
13054
  process.exit(0);
13056
13055
  }
13057
- async function runUpMigration(migrationDirName, migrationsDir, client, setup) {
13056
+ async function runUpMigration(migrationDirName, migrationsDir, client, config2) {
13058
13057
  const upPath = (0, import_node_path6.join)(migrationsDir, migrationDirName, "up.ts");
13059
13058
  const migrationModule = await import(upPath);
13060
13059
  const statements = migrationModule.statements;
@@ -13081,7 +13080,9 @@ async function runUpMigration(migrationDirName, migrationsDir, client, setup) {
13081
13080
  console.log(
13082
13081
  bgGreen3.white.bold("[APPLIED]") + " " + green2(`Migration ${cyan5(migrationDirName)}`) + dim3(".")
13083
13082
  );
13084
- const db = (0, import_durcno3.database)({ Migrations: import_durcno3.Migrations }, setup);
13083
+ config2.connector.pool = { ...config2.connector.pool, max: 1 };
13084
+ config2.connector.logger = void 0;
13085
+ const db = (0, import_durcno3.database)({ Migrations: import_durcno3.Migrations }, config2);
13085
13086
  await db.insert(import_durcno3.Migrations).values({
13086
13087
  name: migrationDirName,
13087
13088
  createdAt: /* @__PURE__ */ new Date()
@@ -13106,7 +13107,7 @@ var import_node_readline = require("node:readline");
13106
13107
  var { cyan: cyan6, green: green3, red: red4, yellow: yellow6, gray: gray5, bgCyan, bold: bold2 } = source_default;
13107
13108
  async function shell(options) {
13108
13109
  const configPath = resolveConfigPath(options.config);
13109
- const { connector } = await getSetup(configPath);
13110
+ const { connector } = await loadConfig(configPath);
13110
13111
  const client = connector.getClient();
13111
13112
  console.log(gray5("Connecting to database..."));
13112
13113
  await client.connect();
@@ -13352,7 +13353,7 @@ var import_migration3 = require("durcno/migration");
13352
13353
  var { bgGreen: bgGreen4, bgRed: bgRed2, yellow: yellow7, red: red5, green: green4, cyan: cyan7, gray: gray6 } = source_default;
13353
13354
  async function squash(start, end, options) {
13354
13355
  const configPath = resolveConfigPath(options.config);
13355
- const { config: config2 } = await getSetup(configPath);
13356
+ const config2 = await loadConfig(configPath);
13356
13357
  const migrationsDir = (0, import_node_path7.resolve)(
13357
13358
  (0, import_node_path7.dirname)(configPath),
13358
13359
  config2.out || DEFAULT_MIGRATIONS_DIR
@@ -13459,8 +13460,8 @@ var import_durcno4 = require("durcno");
13459
13460
  var { dim: dim4, cyan: cyan8, yellow: yellow8, green: green5 } = source_default;
13460
13461
  async function status(options) {
13461
13462
  const configPath = resolveConfigPath(options.config);
13462
- const { connector, config: config2 } = await getSetup(configPath);
13463
- config2.pool = { ...config2.pool, max: 1 };
13463
+ const config2 = await loadConfig(configPath);
13464
+ const { connector } = config2;
13464
13465
  const migrationsDir = (0, import_node_path8.resolve)(
13465
13466
  (0, import_node_path8.dirname)(configPath),
13466
13467
  config2.out || DEFAULT_MIGRATIONS_DIR
@@ -13471,7 +13472,7 @@ async function status(options) {
13471
13472
  console.log(source_default.yellow("No migrations found."));
13472
13473
  process.exit(0);
13473
13474
  }
13474
- const db = (0, import_durcno4.database)({ Migrations: import_durcno4.Migrations }, { connector, config: config2 });
13475
+ const db = (0, import_durcno4.database)({ Migrations: import_durcno4.Migrations }, config2);
13475
13476
  const migrationsQuery = db.from(import_durcno4.Migrations).select();
13476
13477
  let migrations;
13477
13478
  const client = connector.getClient();
@@ -13504,7 +13505,7 @@ async function status(options) {
13504
13505
  }
13505
13506
 
13506
13507
  // src/cli/index.ts
13507
- program.version("1.0.0-alpha.1");
13508
+ program.version("1.0.0-alpha.2");
13508
13509
  var Options = {
13509
13510
  config: ["--config <path>", "Path to the config file"]
13510
13511
  };
@@ -1,7 +1,7 @@
1
1
  import { Sql } from "../sql.mjs";
2
2
  import { entityType } from "../symbols.mjs";
3
- import { Arg } from "../query-builders/pre.mjs";
4
3
  import { StdTableColumn, TableColumn } from "../table.mjs";
4
+ import { Arg } from "../query-builders/pre.mjs";
5
5
  import * as z from "zod";
6
6
 
7
7
  //#region src/columns/common.d.ts
@@ -1,4 +1,4 @@
1
- import { Connector } from "./common.mjs";
1
+ import { Connector, ConnectorOptions } from "./common.mjs";
2
2
 
3
3
  //#region src/connectors/bun.d.ts
4
4
  /**
@@ -15,6 +15,6 @@ declare class BunConnector extends Connector {
15
15
  getPool(): BunPool;
16
16
  }
17
17
  /** Creates a Bun SQL connector instance. */
18
- declare function bun(): BunConnector;
18
+ declare function bun(options: ConnectorOptions): BunConnector;
19
19
  //#endregion
20
20
  export { BunConnector, bun };
@@ -1,5 +1,5 @@
1
- import { $Client, $Pool, Connector } from "./common.mjs";
2
- import { SQL } from "bun";
1
+ import { $Client, $Pool, Connector, getUrlFromDbCredentials } from "./common.mjs";
2
+ import Bun from "bun";
3
3
  //#region src/connectors/bun.ts
4
4
  /**
5
5
  * Connector implementation for the Bun built-in SQL client.
@@ -12,15 +12,15 @@ import { SQL } from "bun";
12
12
  */
13
13
  var BunConnector = class extends Connector {
14
14
  getClient() {
15
- return new BunClient(this.url);
15
+ return new BunClient(this.options);
16
16
  }
17
17
  getPool() {
18
- return new BunPool(this.url, this.config.pool);
18
+ return new BunPool(this.options);
19
19
  }
20
20
  };
21
21
  /** Creates a Bun SQL connector instance. */
22
- function bun() {
23
- return new BunConnector();
22
+ function bun(options) {
23
+ return new BunConnector(options);
24
24
  }
25
25
  /**
26
26
  * Single-connection client wrapper for Bun's SQL API.
@@ -32,9 +32,9 @@ function bun() {
32
32
  */
33
33
  var BunClient = class extends $Client {
34
34
  #client;
35
- constructor(connectionString) {
36
- super();
37
- this.#client = new SQL(connectionString, { max: 1 });
35
+ constructor(options) {
36
+ super(options);
37
+ this.#client = new Bun.SQL(getUrlFromDbCredentials(options.dbCredentials), { max: 1 });
38
38
  this.query = this.#client.unsafe.bind(this.#client);
39
39
  }
40
40
  async connect() {
@@ -57,9 +57,9 @@ var BunClient = class extends $Client {
57
57
  */
58
58
  var BunPool = class extends $Pool {
59
59
  #pool;
60
- constructor(connectionString, pool) {
61
- super();
62
- this.#pool = new SQL(connectionString, { max: pool?.max ?? 10 });
60
+ constructor(options) {
61
+ super(options);
62
+ this.#pool = new Bun.SQL(getUrlFromDbCredentials(options.dbCredentials), { max: options.pool?.max ?? 10 });
63
63
  this.query = this.#pool.unsafe.bind(this.#pool);
64
64
  }
65
65
  async connect() {
@@ -72,7 +72,7 @@ var BunPool = class extends $Pool {
72
72
  await this.#pool.end();
73
73
  }
74
74
  async acquireClient() {
75
- return new BunPoolClient(await this.#pool.reserve());
75
+ return new BunPoolClient(await this.#pool.reserve(), this.options);
76
76
  }
77
77
  };
78
78
  /**
@@ -84,8 +84,8 @@ var BunPool = class extends $Pool {
84
84
  */
85
85
  var BunPoolClient = class extends $Client {
86
86
  #sql;
87
- constructor(sql) {
88
- super();
87
+ constructor(sql, options) {
88
+ super(options);
89
89
  this.#sql = sql;
90
90
  this.query = this.#sql.unsafe.bind(this.#sql);
91
91
  }
@@ -1,6 +1,49 @@
1
- import { Config } from "../index.mjs";
1
+ import { DurcnoLogger } from "../logger.mjs";
2
+ import { Query } from "../query-builders/query.mjs";
3
+ import { ConnectionOptions } from "node:tls";
2
4
 
3
5
  //#region src/connectors/common.d.ts
6
+ /**
7
+ * Options passed to connector constructors containing database connection
8
+ * credentials, pool settings, and an optional logger.
9
+ *
10
+ * These options were previously part of the top-level `Config` type and are
11
+ * now scoped to the connector so that `Config` only contains schema/migration
12
+ * settings.
13
+ */
14
+ type ConnectorOptions = {
15
+ /**
16
+ * Database connection credentials — either a connection URL or individual
17
+ * host/user/password/database fields.
18
+ */
19
+ dbCredentials: ({
20
+ host: string;
21
+ port?: number;
22
+ user: string;
23
+ password?: string;
24
+ database: string;
25
+ ssl?: boolean | "require" | "allow" | "prefer" | "verify-full" | ConnectionOptions;
26
+ } & {}) | {
27
+ url: string;
28
+ };
29
+ /**
30
+ * Connection pool configuration.
31
+ */
32
+ pool?: {
33
+ /**
34
+ * Maximum number of connections in the pool.
35
+ * @default 10
36
+ */
37
+ max?: number;
38
+ };
39
+ /**
40
+ * Optional logger instance for query logging.
41
+ * Pass a Winston logger or any object with a compatible `info()` method.
42
+ * When set, all executed queries will be logged at the `info` level with
43
+ * structured `{ sql, arguments }` metadata.
44
+ */
45
+ logger?: DurcnoLogger;
46
+ };
4
47
  /**
5
48
  * Abstract base class for all database connectors.
6
49
  *
@@ -12,12 +55,18 @@ import { Config } from "../index.mjs";
12
55
  * @abstract
13
56
  */
14
57
  declare abstract class Connector {
15
- /** The configuration object containing file paths, database credentials, client configs etc. */
16
- config: Config;
17
- /** The PostgreSQL connection URL derived from the configuration. */
18
- url: string;
19
- /** Injects the configuration and derives the connection URL. Called by `defineConfig`. */
20
- _init(config: Config): void;
58
+ /**
59
+ * The original options passed to the connector constructor.
60
+ * Provides full access to `dbCredentials`, `pool`, and `logger`.
61
+ * Note: `pool` and `logger` may be mutated on the connector instance after
62
+ * construction (e.g. by CLI commands); use the instance fields for current values.
63
+ */
64
+ options: ConnectorOptions;
65
+ /** Connection pool size override (can be mutated by CLI commands before `getPool()` is called). */
66
+ pool?: ConnectorOptions["pool"];
67
+ /** Optional logger instance for query logging. */
68
+ logger?: DurcnoLogger;
69
+ constructor(options: ConnectorOptions);
21
70
  /**
22
71
  * Creates a single-connection client.
23
72
  *
@@ -38,15 +87,19 @@ declare abstract class Connector {
38
87
  abstract getPool(): $Pool;
39
88
  }
40
89
  /**
41
- * Abstract base class for single-connection database clients.
90
+ * Abstract base class shared by {@link $Client} and {@link $Pool}.
42
91
  *
43
- * Implementations wrap specific PostgreSQL client libraries to provide
44
- * a unified interface for query execution, connection management, and
45
- * result parsing.
92
+ * Holds the common `options`, `logger`, `query`, and `execQuery` members so
93
+ * they only need to be defined once.
46
94
  *
47
95
  * @abstract
48
96
  */
49
- declare abstract class $Client {
97
+ declare abstract class $QueryExecutor {
98
+ /** The connector options used to create this executor. */
99
+ options: ConnectorOptions;
100
+ /** Optional logger instance for query logging. */
101
+ logger?: DurcnoLogger;
102
+ constructor(options: ConnectorOptions);
50
103
  /**
51
104
  * Executes a SQL query with optional parameterized arguments.
52
105
  *
@@ -55,6 +108,25 @@ declare abstract class $Client {
55
108
  * @returns A promise that resolves with the query result.
56
109
  */
57
110
  query: (query: string, args?: (string | number | null)[]) => Promise<unknown>;
111
+ /**
112
+ * Executes a {@link Query} object by forwarding its sql and arguments to {@link query}.
113
+ * When a logger is configured, logs the SQL, arguments, and query duration after execution.
114
+ *
115
+ * @param q - The {@link Query} object to execute.
116
+ * @returns A promise that resolves with the raw query result.
117
+ */
118
+ execQuery(q: Query<any>): Promise<unknown>;
119
+ }
120
+ /**
121
+ * Abstract base class for single-connection database clients.
122
+ *
123
+ * Implementations wrap specific PostgreSQL client libraries to provide
124
+ * a unified interface for query execution, connection management, and
125
+ * result parsing.
126
+ *
127
+ * @abstract
128
+ */
129
+ declare abstract class $Client extends $QueryExecutor {
58
130
  /**
59
131
  * Establishes a connection to the database.
60
132
  *
@@ -87,18 +159,7 @@ declare abstract class $Client {
87
159
  *
88
160
  * @abstract
89
161
  */
90
- declare abstract class $Pool {
91
- /**
92
- * Executes a SQL query with optional parameterized arguments.
93
- *
94
- * The pool automatically acquires a connection, executes the query,
95
- * and returns the connection to the pool.
96
- *
97
- * @param query - The SQL query string to execute.
98
- * @param args - Optional array of parameter values for parameterized queries.
99
- * @returns A promise that resolves with the query result.
100
- */
101
- query: (query: string, args?: (string | number | null)[]) => Promise<unknown>;
162
+ declare abstract class $Pool extends $QueryExecutor {
102
163
  /**
103
164
  * Initializes the connection pool.
104
165
  *
@@ -146,4 +207,4 @@ declare abstract class $Pool {
146
207
  */
147
208
  type QueryExecutor = $Client | $Pool;
148
209
  //#endregion
149
- export { $Pool, Connector, QueryExecutor };
210
+ export { $Pool, Connector, ConnectorOptions, QueryExecutor };
@@ -1,6 +1,25 @@
1
- import { getUrlFromDbCredentials } from "../cli/helpers.mjs";
2
1
  //#region src/connectors/common.ts
3
2
  /**
3
+ * Derives a PostgreSQL connection URL string from `ConnectorOptions.dbCredentials`.
4
+ *
5
+ * Accepts either a plain `{ url }` object or an expanded
6
+ * `{ host, port, user, password, database, ssl }` object and builds a
7
+ * properly-encoded `postgresql://` URL.
8
+ */
9
+ function getUrlFromDbCredentials(dbCredentials) {
10
+ if ("url" in dbCredentials) return dbCredentials.url;
11
+ const { host, port, user, password, database, ssl } = dbCredentials;
12
+ const url = `postgresql://${encodeURIComponent(user) + (password ? `:${encodeURIComponent(password)}` : "")}@${port !== void 0 ? `${host}:${port}` : host}/${encodeURIComponent(database)}`;
13
+ const params = {};
14
+ if (ssl !== void 0) {
15
+ if (typeof ssl === "boolean") {
16
+ if (ssl) params.ssl = "true";
17
+ } else if (typeof ssl === "string") params.sslmode = ssl;
18
+ else if (typeof ssl === "object") throw new Error("Cannot convert 'ssl' ConnectionOptions object into a URL. Provide dbCredentials.url or use a boolean/string ssl value (e.g. 'require').");
19
+ }
20
+ return `${url}${Object.keys(params).length ? `?${Object.entries(params).map(([k, v]) => `${k}=${encodeURIComponent(v)}`).join("&")}` : ""}`;
21
+ }
22
+ /**
4
23
  * Abstract base class for all database connectors.
5
24
  *
6
25
  * Connectors provide a unified interface for creating database clients
@@ -11,26 +30,40 @@ import { getUrlFromDbCredentials } from "../cli/helpers.mjs";
11
30
  * @abstract
12
31
  */
13
32
  var Connector = class {
14
- /** The configuration object containing file paths, database credentials, client configs etc. */
15
- config;
16
- /** The PostgreSQL connection URL derived from the configuration. */
17
- url;
18
- /** Injects the configuration and derives the connection URL. Called by `defineConfig`. */
19
- _init(config) {
20
- this.config = config;
21
- this.url = getUrlFromDbCredentials(config.dbCredentials);
33
+ /**
34
+ * The original options passed to the connector constructor.
35
+ * Provides full access to `dbCredentials`, `pool`, and `logger`.
36
+ * Note: `pool` and `logger` may be mutated on the connector instance after
37
+ * construction (e.g. by CLI commands); use the instance fields for current values.
38
+ */
39
+ options;
40
+ /** Connection pool size override (can be mutated by CLI commands before `getPool()` is called). */
41
+ pool;
42
+ /** Optional logger instance for query logging. */
43
+ logger;
44
+ constructor(options) {
45
+ this.options = options;
46
+ this.pool = options.pool;
47
+ this.logger = options.logger;
22
48
  }
23
49
  };
24
50
  /**
25
- * Abstract base class for single-connection database clients.
51
+ * Abstract base class shared by {@link $Client} and {@link $Pool}.
26
52
  *
27
- * Implementations wrap specific PostgreSQL client libraries to provide
28
- * a unified interface for query execution, connection management, and
29
- * result parsing.
53
+ * Holds the common `options`, `logger`, `query`, and `execQuery` members so
54
+ * they only need to be defined once.
30
55
  *
31
56
  * @abstract
32
57
  */
33
- var $Client = class {
58
+ var $QueryExecutor = class {
59
+ /** The connector options used to create this executor. */
60
+ options;
61
+ /** Optional logger instance for query logging. */
62
+ logger;
63
+ constructor(options) {
64
+ this.options = options;
65
+ this.logger = options.logger;
66
+ }
34
67
  /**
35
68
  * Executes a SQL query with optional parameterized arguments.
36
69
  *
@@ -39,8 +72,35 @@ var $Client = class {
39
72
  * @returns A promise that resolves with the query result.
40
73
  */
41
74
  query;
75
+ /**
76
+ * Executes a {@link Query} object by forwarding its sql and arguments to {@link query}.
77
+ * When a logger is configured, logs the SQL, arguments, and query duration after execution.
78
+ *
79
+ * @param q - The {@link Query} object to execute.
80
+ * @returns A promise that resolves with the raw query result.
81
+ */
82
+ async execQuery(q) {
83
+ const start = performance.now();
84
+ const result = await this.query(q.sql, q.arguments);
85
+ if (this.logger) this.logger.info("Query", {
86
+ sql: q.sql,
87
+ arguments: q.arguments,
88
+ durationMs: performance.now() - start
89
+ });
90
+ return result;
91
+ }
42
92
  };
43
93
  /**
94
+ * Abstract base class for single-connection database clients.
95
+ *
96
+ * Implementations wrap specific PostgreSQL client libraries to provide
97
+ * a unified interface for query execution, connection management, and
98
+ * result parsing.
99
+ *
100
+ * @abstract
101
+ */
102
+ var $Client = class extends $QueryExecutor {};
103
+ /**
44
104
  * Abstract base class for database connection pools.
45
105
  *
46
106
  * Connection pools manage multiple reusable connections to improve
@@ -49,18 +109,6 @@ var $Client = class {
49
109
  *
50
110
  * @abstract
51
111
  */
52
- var $Pool = class {
53
- /**
54
- * Executes a SQL query with optional parameterized arguments.
55
- *
56
- * The pool automatically acquires a connection, executes the query,
57
- * and returns the connection to the pool.
58
- *
59
- * @param query - The SQL query string to execute.
60
- * @param args - Optional array of parameter values for parameterized queries.
61
- * @returns A promise that resolves with the query result.
62
- */
63
- query;
64
- };
112
+ var $Pool = class extends $QueryExecutor {};
65
113
  //#endregion
66
- export { $Client, $Pool, Connector };
114
+ export { $Client, $Pool, Connector, getUrlFromDbCredentials };
@@ -1,4 +1,4 @@
1
- import { Connector } from "./common.mjs";
1
+ import { Connector, ConnectorOptions } from "./common.mjs";
2
2
 
3
3
  //#region src/connectors/pg.d.ts
4
4
  /**
@@ -11,10 +11,11 @@ import { Connector } from "./common.mjs";
11
11
  * @see https://www.npmjs.com/package/pg
12
12
  */
13
13
  declare class PgConnector extends Connector {
14
+ constructor(options: ConnectorOptions);
14
15
  getClient(): PgClient;
15
16
  getPool(): PgPool;
16
17
  }
17
18
  /** Creates a pg (node-postgres) connector instance. */
18
- declare function pg(): PgConnector;
19
+ declare function pg(options: ConnectorOptions): PgConnector;
19
20
  //#endregion
20
21
  export { PgConnector, pg };