@noego/proper 0.0.8 → 0.1.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/bin/index.d.mts CHANGED
@@ -1,4 +1,5 @@
1
1
  import mysql from 'mysql2/promise';
2
+ import * as sqlite from 'sqlite';
2
3
 
3
4
  interface MigrationConfig {
4
5
  config_file?: string;
@@ -15,6 +16,20 @@ interface MigrationConfig {
15
16
  sqlite?: {
16
17
  database: string;
17
18
  };
19
+ /**
20
+ * PostgreSQL. Either a single `connectionString` (also readable from
21
+ * `process.env.DATABASE_URL` when omitted) or discrete fields.
22
+ * `password` falls back to `process.env.PG_PASSWORD`.
23
+ */
24
+ pg?: {
25
+ connectionString?: string;
26
+ host?: string;
27
+ user?: string;
28
+ database?: string;
29
+ password?: string;
30
+ port?: number;
31
+ ssl?: boolean | Record<string, unknown>;
32
+ };
18
33
  seeds?: {
19
34
  migrationsDir?: string;
20
35
  dataDir?: string;
@@ -31,6 +46,92 @@ interface ISQLRunner {
31
46
  execute(sql: string, params?: any[]): Promise<any>;
32
47
  end(): Promise<void>;
33
48
  }
49
+ /**
50
+ * Base class that implements the common contract and helper utilities that are
51
+ * shared between the different dialect runners. The concrete subclasses only
52
+ * need to implement the three primitive methods `_query`, `_execute` and
53
+ * `_end` that perform the actual driver-specific interaction. Everything else
54
+ * – such as ensuring a uniform return shape – is handled here once.
55
+ */
56
+ declare abstract class BaseSQLRunner implements ISQLRunner {
57
+ abstract _query(sql: string, params?: any[]): Promise<any>;
58
+ abstract _execute(sql: string, params?: any[]): Promise<any>;
59
+ abstract _end(): Promise<void>;
60
+ /**
61
+ * Ensures that both MySQL and SQLite return the same tuple shape that callers
62
+ * expect: `[rowsOrResult, extra]`. For SQLite there is no `extra` metadata
63
+ * comparable to MySQL's `FieldPacket[]`, so we just use `undefined`.
64
+ */
65
+ query(sql: string, params?: any[]): Promise<any>;
66
+ execute(sql: string, params?: any[]): Promise<any>;
67
+ end(): Promise<void>;
68
+ }
69
+ declare class SQLRunner extends BaseSQLRunner {
70
+ private connection;
71
+ constructor(connection: mysql.Connection);
72
+ _query(sql: string, params?: any[]): Promise<[mysql.OkPacket | mysql.RowDataPacket[] | mysql.ResultSetHeader[] | mysql.RowDataPacket[][] | mysql.OkPacket[] | mysql.ProcedureCallPacket, mysql.FieldPacket[]]>;
73
+ _execute(sql: string, params?: any[]): Promise<[mysql.OkPacket | mysql.RowDataPacket[] | mysql.ResultSetHeader[] | mysql.RowDataPacket[][] | mysql.OkPacket[] | mysql.ProcedureCallPacket, mysql.FieldPacket[]]>;
74
+ _end(): Promise<void>;
75
+ }
76
+ declare class SQLiteRunner extends BaseSQLRunner {
77
+ private connection;
78
+ constructor(connection: sqlite.Database | any);
79
+ private prepareStatement;
80
+ private finalizeStatement;
81
+ private statementAll;
82
+ private statementRun;
83
+ _query(sql: string, params?: any[]): Promise<any>;
84
+ _execute(sql: string, params?: any[]): Promise<any>;
85
+ /**
86
+ * Checks if SQL is empty or contains only comments/whitespace.
87
+ * Returns true if there is no actual SQL to execute.
88
+ */
89
+ private isEmptySQL;
90
+ private isMultiStatement;
91
+ private executeMultiStatement;
92
+ private removeComments;
93
+ _end(): Promise<void>;
94
+ }
95
+ /**
96
+ * Minimal structural type for a `pg` Client or Pool (or anything shaped like
97
+ * one, e.g. a Hyperdrive/Neon client). We only rely on `query()` and `end()`.
98
+ */
99
+ interface PgQueryable {
100
+ query(text: string, values?: any[]): Promise<{
101
+ rows: any[];
102
+ rowCount: number | null;
103
+ }>;
104
+ end?(): Promise<void>;
105
+ }
106
+ /**
107
+ * PostgreSQL runner.
108
+ *
109
+ * Proper's internal bookkeeping statements use MySQL-style `?` placeholders;
110
+ * Postgres wants `$1..$n`, so parameterised statements are rewritten here.
111
+ * Migration files themselves are executed verbatim with no parameters — a
112
+ * parameter-less `query()` goes through the simple protocol, which allows
113
+ * multiple `;`-separated statements in one call, so no client-side splitting
114
+ * (as SQLite needs) is required.
115
+ */
116
+ declare class PgRunner extends BaseSQLRunner {
117
+ private connection;
118
+ constructor(connection: PgQueryable);
119
+ /** `?` -> `$1`, `$2`, ... outside of string literals / comments. */
120
+ static toPositional(sql: string): string;
121
+ private run;
122
+ _query(sql: string, params?: any[]): Promise<(any[] | {
123
+ rows: any[];
124
+ rowCount: number | null;
125
+ })[]>;
126
+ _execute(sql: string, params?: any[]): Promise<({
127
+ rows: any[];
128
+ rowCount: number | null;
129
+ } | {
130
+ changes: number;
131
+ lastID: undefined;
132
+ })[]>;
133
+ _end(): Promise<void>;
134
+ }
34
135
 
35
136
  declare abstract class MigrationNode {
36
137
  name: string;
@@ -76,10 +177,11 @@ declare class MigrationDirectoryReader {
76
177
  private read_strategy;
77
178
  private sqlrunner;
78
179
  private dialect;
79
- constructor(directory: string, read_strategy: any, sqlrunner: ISQLRunner, dialect?: 'sql' | 'sqlite');
180
+ constructor(directory: string, read_strategy: any, sqlrunner: ISQLRunner, dialect?: 'sql' | 'sqlite' | 'pg');
80
181
  /**
81
182
  * Resolves the appropriate file for a migration based on dialect.
82
183
  * Priority: dialect-specific file > generic file
184
+ * File extensions: `.mysql.up.sql`, `.sqlite.up.sql`, `.pg.up.sql`.
83
185
  */
84
186
  private resolveFile;
85
187
  /**
@@ -176,4 +278,4 @@ type SeedFactory = {
176
278
  };
177
279
  declare function createSeedFactory(options: SeedFactoryOptions): SeedFactory;
178
280
 
179
- export { type MigrationConfig, MySQLMigrationRunner as MigrationRunner, MigrationRunnerFactory, type SeedContext, type SeedFactory, type SeedFactoryOptions, createSeedFactory, loadMigrationConfig, runSeedsWithRunner };
281
+ export { type ISQLRunner, type MigrationConfig, MySQLMigrationRunner as MigrationRunner, MigrationRunnerFactory, type PgQueryable, PgRunner, SQLRunner, SQLiteRunner, type SeedContext, type SeedFactory, type SeedFactoryOptions, createSeedFactory, loadMigrationConfig, runSeedsWithRunner };
package/bin/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import mysql from 'mysql2/promise';
2
+ import * as sqlite from 'sqlite';
2
3
 
3
4
  interface MigrationConfig {
4
5
  config_file?: string;
@@ -15,6 +16,20 @@ interface MigrationConfig {
15
16
  sqlite?: {
16
17
  database: string;
17
18
  };
19
+ /**
20
+ * PostgreSQL. Either a single `connectionString` (also readable from
21
+ * `process.env.DATABASE_URL` when omitted) or discrete fields.
22
+ * `password` falls back to `process.env.PG_PASSWORD`.
23
+ */
24
+ pg?: {
25
+ connectionString?: string;
26
+ host?: string;
27
+ user?: string;
28
+ database?: string;
29
+ password?: string;
30
+ port?: number;
31
+ ssl?: boolean | Record<string, unknown>;
32
+ };
18
33
  seeds?: {
19
34
  migrationsDir?: string;
20
35
  dataDir?: string;
@@ -31,6 +46,92 @@ interface ISQLRunner {
31
46
  execute(sql: string, params?: any[]): Promise<any>;
32
47
  end(): Promise<void>;
33
48
  }
49
+ /**
50
+ * Base class that implements the common contract and helper utilities that are
51
+ * shared between the different dialect runners. The concrete subclasses only
52
+ * need to implement the three primitive methods `_query`, `_execute` and
53
+ * `_end` that perform the actual driver-specific interaction. Everything else
54
+ * – such as ensuring a uniform return shape – is handled here once.
55
+ */
56
+ declare abstract class BaseSQLRunner implements ISQLRunner {
57
+ abstract _query(sql: string, params?: any[]): Promise<any>;
58
+ abstract _execute(sql: string, params?: any[]): Promise<any>;
59
+ abstract _end(): Promise<void>;
60
+ /**
61
+ * Ensures that both MySQL and SQLite return the same tuple shape that callers
62
+ * expect: `[rowsOrResult, extra]`. For SQLite there is no `extra` metadata
63
+ * comparable to MySQL's `FieldPacket[]`, so we just use `undefined`.
64
+ */
65
+ query(sql: string, params?: any[]): Promise<any>;
66
+ execute(sql: string, params?: any[]): Promise<any>;
67
+ end(): Promise<void>;
68
+ }
69
+ declare class SQLRunner extends BaseSQLRunner {
70
+ private connection;
71
+ constructor(connection: mysql.Connection);
72
+ _query(sql: string, params?: any[]): Promise<[mysql.OkPacket | mysql.RowDataPacket[] | mysql.ResultSetHeader[] | mysql.RowDataPacket[][] | mysql.OkPacket[] | mysql.ProcedureCallPacket, mysql.FieldPacket[]]>;
73
+ _execute(sql: string, params?: any[]): Promise<[mysql.OkPacket | mysql.RowDataPacket[] | mysql.ResultSetHeader[] | mysql.RowDataPacket[][] | mysql.OkPacket[] | mysql.ProcedureCallPacket, mysql.FieldPacket[]]>;
74
+ _end(): Promise<void>;
75
+ }
76
+ declare class SQLiteRunner extends BaseSQLRunner {
77
+ private connection;
78
+ constructor(connection: sqlite.Database | any);
79
+ private prepareStatement;
80
+ private finalizeStatement;
81
+ private statementAll;
82
+ private statementRun;
83
+ _query(sql: string, params?: any[]): Promise<any>;
84
+ _execute(sql: string, params?: any[]): Promise<any>;
85
+ /**
86
+ * Checks if SQL is empty or contains only comments/whitespace.
87
+ * Returns true if there is no actual SQL to execute.
88
+ */
89
+ private isEmptySQL;
90
+ private isMultiStatement;
91
+ private executeMultiStatement;
92
+ private removeComments;
93
+ _end(): Promise<void>;
94
+ }
95
+ /**
96
+ * Minimal structural type for a `pg` Client or Pool (or anything shaped like
97
+ * one, e.g. a Hyperdrive/Neon client). We only rely on `query()` and `end()`.
98
+ */
99
+ interface PgQueryable {
100
+ query(text: string, values?: any[]): Promise<{
101
+ rows: any[];
102
+ rowCount: number | null;
103
+ }>;
104
+ end?(): Promise<void>;
105
+ }
106
+ /**
107
+ * PostgreSQL runner.
108
+ *
109
+ * Proper's internal bookkeeping statements use MySQL-style `?` placeholders;
110
+ * Postgres wants `$1..$n`, so parameterised statements are rewritten here.
111
+ * Migration files themselves are executed verbatim with no parameters — a
112
+ * parameter-less `query()` goes through the simple protocol, which allows
113
+ * multiple `;`-separated statements in one call, so no client-side splitting
114
+ * (as SQLite needs) is required.
115
+ */
116
+ declare class PgRunner extends BaseSQLRunner {
117
+ private connection;
118
+ constructor(connection: PgQueryable);
119
+ /** `?` -> `$1`, `$2`, ... outside of string literals / comments. */
120
+ static toPositional(sql: string): string;
121
+ private run;
122
+ _query(sql: string, params?: any[]): Promise<(any[] | {
123
+ rows: any[];
124
+ rowCount: number | null;
125
+ })[]>;
126
+ _execute(sql: string, params?: any[]): Promise<({
127
+ rows: any[];
128
+ rowCount: number | null;
129
+ } | {
130
+ changes: number;
131
+ lastID: undefined;
132
+ })[]>;
133
+ _end(): Promise<void>;
134
+ }
34
135
 
35
136
  declare abstract class MigrationNode {
36
137
  name: string;
@@ -76,10 +177,11 @@ declare class MigrationDirectoryReader {
76
177
  private read_strategy;
77
178
  private sqlrunner;
78
179
  private dialect;
79
- constructor(directory: string, read_strategy: any, sqlrunner: ISQLRunner, dialect?: 'sql' | 'sqlite');
180
+ constructor(directory: string, read_strategy: any, sqlrunner: ISQLRunner, dialect?: 'sql' | 'sqlite' | 'pg');
80
181
  /**
81
182
  * Resolves the appropriate file for a migration based on dialect.
82
183
  * Priority: dialect-specific file > generic file
184
+ * File extensions: `.mysql.up.sql`, `.sqlite.up.sql`, `.pg.up.sql`.
83
185
  */
84
186
  private resolveFile;
85
187
  /**
@@ -176,4 +278,4 @@ type SeedFactory = {
176
278
  };
177
279
  declare function createSeedFactory(options: SeedFactoryOptions): SeedFactory;
178
280
 
179
- export { type MigrationConfig, MySQLMigrationRunner as MigrationRunner, MigrationRunnerFactory, type SeedContext, type SeedFactory, type SeedFactoryOptions, createSeedFactory, loadMigrationConfig, runSeedsWithRunner };
281
+ export { type ISQLRunner, type MigrationConfig, MySQLMigrationRunner as MigrationRunner, MigrationRunnerFactory, type PgQueryable, PgRunner, SQLRunner, SQLiteRunner, type SeedContext, type SeedFactory, type SeedFactoryOptions, createSeedFactory, loadMigrationConfig, runSeedsWithRunner };
package/bin/index.js CHANGED
@@ -68,6 +68,9 @@ var index_exports = {};
68
68
  __export(index_exports, {
69
69
  MigrationRunner: () => MySQLMigrationRunner,
70
70
  MigrationRunnerFactory: () => MigrationRunnerFactory,
71
+ PgRunner: () => PgRunner,
72
+ SQLRunner: () => SQLRunner,
73
+ SQLiteRunner: () => SQLiteRunner,
71
74
  createSeedFactory: () => createSeedFactory,
72
75
  loadMigrationConfig: () => loadMigrationConfig,
73
76
  runSeedsWithRunner: () => runSeedsWithRunner
@@ -76,9 +79,6 @@ module.exports = __toCommonJS(index_exports);
76
79
 
77
80
  // framework/MigrationRunner.ts
78
81
  var import_fs3 = __toESM(require("fs"));
79
- var import_promise = __toESM(require("mysql2/promise"));
80
- var sqlite = __toESM(require("sqlite"));
81
- var sqlite3 = __toESM(require("sqlite3"));
82
82
 
83
83
  // framework/MigrationDirectoryReader.ts
84
84
  var import_fs = __toESM(require("fs"));
@@ -370,9 +370,10 @@ var MigrationDirectoryReader = class {
370
370
  /**
371
371
  * Resolves the appropriate file for a migration based on dialect.
372
372
  * Priority: dialect-specific file > generic file
373
+ * File extensions: `.mysql.up.sql`, `.sqlite.up.sql`, `.pg.up.sql`.
373
374
  */
374
375
  resolveFile(baseName, direction) {
375
- const dialectExt = this.dialect === "sql" ? "mysql" : "sqlite";
376
+ const dialectExt = this.dialect === "sql" ? "mysql" : this.dialect;
376
377
  const dialectFile = import_path.default.join(this.directory, `${baseName}.${dialectExt}.${direction}.sql`);
377
378
  if (import_fs.default.existsSync(dialectFile)) return dialectFile;
378
379
  const genericFile = import_path.default.join(this.directory, `${baseName}.${direction}.sql`);
@@ -383,14 +384,14 @@ var MigrationDirectoryReader = class {
383
384
  * Checks if a file path is dialect-specific (contains .mysql. or .sqlite. in the name)
384
385
  */
385
386
  isDialectSpecific(filePath) {
386
- return /\.(mysql|sqlite)\.(up|down)\.sql$/i.test(filePath);
387
+ return /\.(mysql|sqlite|pg)\.(up|down)\.sql$/i.test(filePath);
387
388
  }
388
389
  loadMigrations(table, connection) {
389
390
  import_fs.default.existsSync(this.directory) || import_fs.default.mkdirSync(this.directory);
390
391
  const dir_content = import_fs.default.readdirSync(this.directory, { withFileTypes: true }).filter((file) => file.isFile()).map((file) => file.name);
391
392
  const uniqueKeys = /* @__PURE__ */ new Set();
392
393
  dir_content.forEach((file) => {
393
- const key = file.replace(/(?:\.(mysql|sqlite))?\.(up|down)\.(sql|js)/i, "").toLowerCase();
394
+ const key = file.replace(/(?:\.(mysql|sqlite|pg))?\.(up|down)\.(sql|js)/i, "").toLowerCase();
394
395
  uniqueKeys.add(key);
395
396
  });
396
397
  const migration_sorter = {};
@@ -462,6 +463,12 @@ var MigrationSetup = class {
462
463
  up TEXT,
463
464
  down TEXT,
464
465
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
466
+ )` : this.config.database === "pg" ? `CREATE TABLE IF NOT EXISTS ${tableName} (
467
+ id SERIAL PRIMARY KEY,
468
+ migration_key TEXT,
469
+ up TEXT,
470
+ down TEXT,
471
+ created_at TIMESTAMPTZ DEFAULT now()
465
472
  )` : `CREATE TABLE IF NOT EXISTS ${tableName} (
466
473
  id INT AUTO_INCREMENT PRIMARY KEY,
467
474
  migration_key VARCHAR(255),
@@ -521,31 +528,35 @@ function MySqlDialectParser(sql) {
521
528
  }
522
529
  return result;
523
530
  }
524
- function SqliteDialectParser(sql) {
525
- const lines = sql.split("\n");
526
- let result = "";
527
- let isInSqliteBlock = true;
528
- const startSqliteRegex = /^\s*--\s*\[\s*sqlite\s*\]\s*$/i;
531
+ function markerDialectParser(names) {
532
+ const startRegex = new RegExp(`^\\s*--\\s*\\[\\s*(${names.join("|")})\\s*\\]\\s*$`, "i");
529
533
  const anyDialectRegex = /^\s*--\s*\[\s*\w+\s*\]\s*$/i;
530
- for (const line of lines) {
531
- const trimmed = line.trim();
532
- if (startSqliteRegex.test(trimmed)) {
533
- isInSqliteBlock = true;
534
- result += line + "\n";
535
- continue;
536
- } else if (anyDialectRegex.test(trimmed) && !startSqliteRegex.test(trimmed)) {
537
- isInSqliteBlock = false;
538
- continue;
539
- }
540
- if (!isInSqliteBlock && line.toLowerCase().includes("create index")) {
541
- isInSqliteBlock = true;
542
- }
543
- if (isInSqliteBlock) {
544
- result += line + "\n";
534
+ return function(sql) {
535
+ const lines = sql.split("\n");
536
+ let result = "";
537
+ let capturing = true;
538
+ for (const line of lines) {
539
+ const trimmed = line.trim();
540
+ if (startRegex.test(trimmed)) {
541
+ capturing = true;
542
+ result += line + "\n";
543
+ continue;
544
+ } else if (anyDialectRegex.test(trimmed)) {
545
+ capturing = false;
546
+ continue;
547
+ }
548
+ if (!capturing && line.toLowerCase().includes("create index")) {
549
+ capturing = true;
550
+ }
551
+ if (capturing) {
552
+ result += line + "\n";
553
+ }
545
554
  }
546
- }
547
- return result;
555
+ return result;
556
+ };
548
557
  }
558
+ var SqliteDialectParser = markerDialectParser(["sqlite"]);
559
+ var PgDialectParser = markerDialectParser(["pg", "postgres", "postgresql"]);
549
560
 
550
561
  // framework/SQLRunner.ts
551
562
  var BaseSQLRunner = class {
@@ -761,12 +772,122 @@ ${sql}
761
772
  });
762
773
  }
763
774
  };
775
+ var PgRunner = class _PgRunner extends BaseSQLRunner {
776
+ constructor(connection) {
777
+ super();
778
+ this.connection = connection;
779
+ }
780
+ /** `?` -> `$1`, `$2`, ... outside of string literals / comments. */
781
+ static toPositional(sql) {
782
+ let out = "";
783
+ let n = 0;
784
+ let inSingle = false;
785
+ let inDouble = false;
786
+ let inLineComment = false;
787
+ let inBlockComment = false;
788
+ for (let i = 0; i < sql.length; i++) {
789
+ const ch = sql[i];
790
+ const next = sql[i + 1];
791
+ if (inLineComment) {
792
+ out += ch;
793
+ if (ch === "\n") inLineComment = false;
794
+ continue;
795
+ }
796
+ if (inBlockComment) {
797
+ out += ch;
798
+ if (ch === "*" && next === "/") {
799
+ out += next;
800
+ i++;
801
+ inBlockComment = false;
802
+ }
803
+ continue;
804
+ }
805
+ if (inSingle) {
806
+ out += ch;
807
+ if (ch === "'") inSingle = false;
808
+ continue;
809
+ }
810
+ if (inDouble) {
811
+ out += ch;
812
+ if (ch === '"') inDouble = false;
813
+ continue;
814
+ }
815
+ if (ch === "-" && next === "-") {
816
+ out += ch;
817
+ inLineComment = true;
818
+ continue;
819
+ }
820
+ if (ch === "/" && next === "*") {
821
+ out += ch + next;
822
+ i++;
823
+ inBlockComment = true;
824
+ continue;
825
+ }
826
+ if (ch === "'") {
827
+ out += ch;
828
+ inSingle = true;
829
+ continue;
830
+ }
831
+ if (ch === '"') {
832
+ out += ch;
833
+ inDouble = true;
834
+ continue;
835
+ }
836
+ if (ch === "?") {
837
+ out += `$${++n}`;
838
+ continue;
839
+ }
840
+ out += ch;
841
+ }
842
+ return out;
843
+ }
844
+ run(sql, params) {
845
+ return __async(this, null, function* () {
846
+ if (params.length > 0) {
847
+ return yield this.connection.query(_PgRunner.toPositional(sql), params);
848
+ }
849
+ return yield this.connection.query(sql);
850
+ });
851
+ }
852
+ _query(_0) {
853
+ return __async(this, arguments, function* (sql, params = []) {
854
+ const result = yield this.run(sql, params);
855
+ return [result.rows, result];
856
+ });
857
+ }
858
+ _execute(_0) {
859
+ return __async(this, arguments, function* (sql, params = []) {
860
+ var _a;
861
+ const result = yield this.run(sql, params);
862
+ return [{ changes: (_a = result.rowCount) != null ? _a : 0, lastID: void 0 }, result];
863
+ });
864
+ }
865
+ _end() {
866
+ return __async(this, null, function* () {
867
+ if (this.connection && typeof this.connection.end === "function") {
868
+ yield this.connection.end();
869
+ }
870
+ });
871
+ }
872
+ };
764
873
 
765
874
  // framework/MigrationRunner.ts
766
875
  function toError(error) {
767
876
  if (error instanceof Error) return error;
768
877
  return new Error(String(error));
769
878
  }
879
+ function makeRunner(database, conn) {
880
+ switch (database) {
881
+ case "sql":
882
+ return new SQLRunner(conn);
883
+ case "sqlite":
884
+ return new SQLiteRunner(conn);
885
+ case "pg":
886
+ return new PgRunner(conn);
887
+ default:
888
+ throw ConfigurationError.unknownDatabaseType(database);
889
+ }
890
+ }
770
891
  function loadMigrationConfig(configFile) {
771
892
  const reader = new FileMigrationConfigReader(configFile);
772
893
  return reader.loadFile();
@@ -787,6 +908,7 @@ var MigrationRunnerFactory = class _MigrationRunnerFactory {
787
908
  }
788
909
  static createConnection(config) {
789
910
  return __async(this, null, function* () {
911
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
790
912
  let conn = null;
791
913
  switch (config.database) {
792
914
  case "sql":
@@ -797,7 +919,8 @@ var MigrationRunnerFactory = class _MigrationRunnerFactory {
797
919
  password: process.env.SQL_PASSWORD
798
920
  }, config.sql);
799
921
  try {
800
- conn = yield import_promise.default.createConnection(settings);
922
+ const mysql = yield import("mysql2/promise");
923
+ conn = yield ((_b = (_a = mysql.default) == null ? void 0 : _a.createConnection) != null ? _b : mysql.createConnection)(settings);
801
924
  return conn;
802
925
  } catch (error) {
803
926
  throw DatabaseConnectionError.connectionFailed("sql", toError(error).message);
@@ -807,14 +930,32 @@ var MigrationRunnerFactory = class _MigrationRunnerFactory {
807
930
  throw ConfigurationError.missingDatabaseConfiguration("sqlite");
808
931
  }
809
932
  try {
810
- conn = yield sqlite.open({
933
+ const sqlite = yield import("sqlite");
934
+ const sqlite3 = yield import("sqlite3");
935
+ conn = yield ((_d = (_c = sqlite.default) == null ? void 0 : _c.open) != null ? _d : sqlite.open)({
811
936
  filename: config.sqlite.database,
812
- driver: sqlite3.Database
937
+ driver: (_f = (_e = sqlite3.default) == null ? void 0 : _e.Database) != null ? _f : sqlite3.Database
813
938
  });
814
939
  return conn;
815
940
  } catch (error) {
816
941
  throw DatabaseConnectionError.connectionFailed("sqlite", toError(error).message);
817
942
  }
943
+ case "pg":
944
+ if (!config.pg && !process.env.DATABASE_URL) {
945
+ throw ConfigurationError.missingDatabaseConfiguration("pg");
946
+ }
947
+ try {
948
+ const pgcfg = (_g = config.pg) != null ? _g : {};
949
+ const connectionString = (_h = pgcfg.connectionString) != null ? _h : process.env.DATABASE_URL;
950
+ const settings2 = connectionString ? { connectionString, ssl: pgcfg.ssl } : __spreadProps(__spreadValues({}, pgcfg), { password: (_i = pgcfg.password) != null ? _i : process.env.PG_PASSWORD });
951
+ const pg = yield import("pg");
952
+ const Client = (_k = (_j = pg.default) == null ? void 0 : _j.Client) != null ? _k : pg.Client;
953
+ conn = new Client(settings2);
954
+ yield conn.connect();
955
+ return conn;
956
+ } catch (error) {
957
+ throw DatabaseConnectionError.connectionFailed("pg", toError(error).message);
958
+ }
818
959
  default:
819
960
  throw ConfigurationError.unknownDatabaseType(config.database);
820
961
  }
@@ -835,16 +976,7 @@ var MigrationRunnerFactory = class _MigrationRunnerFactory {
835
976
  sqlrunner = conn;
836
977
  driverConnection = null;
837
978
  } else {
838
- switch (config.database) {
839
- case "sql":
840
- sqlrunner = new SQLRunner(conn);
841
- break;
842
- case "sqlite":
843
- sqlrunner = new SQLiteRunner(conn);
844
- break;
845
- default:
846
- throw ConfigurationError.unknownDatabaseType(config.database);
847
- }
979
+ sqlrunner = makeRunner(config.database, conn);
848
980
  }
849
981
  const setup = new MigrationSetup(sqlrunner, config);
850
982
  const read_strategy = this.getReadStategy(config);
@@ -856,17 +988,7 @@ var MigrationRunnerFactory = class _MigrationRunnerFactory {
856
988
  createEmpty(config) {
857
989
  return __async(this, null, function* () {
858
990
  const conn = null;
859
- let sqlrunner;
860
- switch (config.database) {
861
- case "sql":
862
- sqlrunner = new SQLRunner(conn);
863
- break;
864
- case "sqlite":
865
- sqlrunner = new SQLiteRunner(conn);
866
- break;
867
- default:
868
- throw ConfigurationError.unknownDatabaseType(config.database);
869
- }
991
+ const sqlrunner = makeRunner(config.database, conn);
870
992
  const setup = new MigrationSetup(sqlrunner, config);
871
993
  const read_strategy = this.getReadStategy(config);
872
994
  const migration_files = new MigrationDirectoryReader(config.migration_folder, read_strategy, sqlrunner, config.database);
@@ -879,6 +1001,8 @@ var MigrationRunnerFactory = class _MigrationRunnerFactory {
879
1001
  return MySqlDialectParser;
880
1002
  case "sqlite":
881
1003
  return SqliteDialectParser;
1004
+ case "pg":
1005
+ return PgDialectParser;
882
1006
  default:
883
1007
  throw ConfigurationError.unknownDatabaseType(config.database);
884
1008
  }
@@ -1065,6 +1189,8 @@ var FileMigrationConfigReader = class {
1065
1189
  config.database = "sql";
1066
1190
  } else if (config.sqlite) {
1067
1191
  config.database = "sqlite";
1192
+ } else if (config.pg) {
1193
+ config.database = "pg";
1068
1194
  } else {
1069
1195
  throw ConfigurationError.missingRequiredProperty("database");
1070
1196
  }
@@ -1118,8 +1244,10 @@ var MigrationCreator = class {
1118
1244
  // framework/SeedRunner.ts
1119
1245
  var import_fs4 = __toESM(require("fs"));
1120
1246
  var import_path2 = __toESM(require("path"));
1247
+ var import_url = require("url");
1121
1248
  var import_ajv = __toESM(require("ajv"));
1122
1249
  var import_ajv_formats = __toESM(require("ajv-formats"));
1250
+ var import_api = require("tsx/esm/api");
1123
1251
  function resolveAlias(name, aliasMap) {
1124
1252
  var _a;
1125
1253
  if (!aliasMap) return name;
@@ -1256,6 +1384,10 @@ function runSqlSeed(runner, resolved, direction) {
1256
1384
  function loadSeedModule(modulePath) {
1257
1385
  return __async(this, null, function* () {
1258
1386
  const resolved = import_path2.default.resolve(modulePath);
1387
+ if (resolved.endsWith(".ts")) {
1388
+ const fileUrl = (0, import_url.pathToFileURL)(resolved).href;
1389
+ return (0, import_api.tsImport)(fileUrl, fileUrl);
1390
+ }
1259
1391
  return import(resolved);
1260
1392
  });
1261
1393
  }
@@ -1374,6 +1506,9 @@ function createSeedFactory(options) {
1374
1506
  0 && (module.exports = {
1375
1507
  MigrationRunner,
1376
1508
  MigrationRunnerFactory,
1509
+ PgRunner,
1510
+ SQLRunner,
1511
+ SQLiteRunner,
1377
1512
  createSeedFactory,
1378
1513
  loadMigrationConfig,
1379
1514
  runSeedsWithRunner