@rfjs/pg-toolkit 0.0.3 → 0.0.5-alpha.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/README.md CHANGED
@@ -1,38 +1,46 @@
1
- pg-bootstrap
2
- ===
1
+ # @packages/pg-toolkit
3
2
 
4
- This project is a `royfuwei/start-ts-templates#main/templates/lib-tsdown` template for creating a new project using the [start-ts-by](https://www.npmjs.com/package/start-ts-by) CLI.
3
+ A utility toolkit for PostgreSQL, designed to share common functionality and management scripts across different ORMs (Drizzle, Prisma, Kysely, TypeORM).
5
4
 
6
- ## Getting Started
5
+ ## Features
7
6
 
8
- ```bash
9
- # 1. Install dependencies
10
- npm install
11
- ## or pnpm
12
- pnpm install
13
- # 2. Run the project
14
- npm run dev
15
- # 3. Build the project
16
- npm run build
17
- # 4. Run tests
18
- npm run test
19
- # 5. Run lint
20
- npm run lint
21
- ```
7
+ ### Admin
8
+ Provides database-level management functions, useful for CI/CD or environment initialization.
9
+ - `ensureSeedHistoryTable`: Creates and manages a seed execution history table (`__seed_history`).
10
+ - `checkSeedExecuted`: Checks if a specific seed has already been executed.
11
+ - `recordSeedExecution`: Records the execution status of a seed.
12
+ - `checkAndCreateDB`: Checks and automatically creates the database.
13
+ - `checkAndCreateSchema`: Checks and automatically creates Schemas.
14
+
15
+ ### Pure
16
+ Utility functions that do not depend on database connections.
17
+ - `getConnectionStringInfo`: Parses Connection Strings, handling logic for `schema` parameters and merging `search_path` options.
18
+
19
+ ## Installation
22
20
 
23
- ## Release
24
21
  ```bash
25
- # 1. Release the project
26
- npx standard-version
27
- ## or
28
- npm run release
29
- # dry run
30
- npm run release -- --dry-run
31
-
32
- # 2. Release the project with version
33
- npm run release -- --version 1.0.0
22
+ npm install @rfjs/pg-toolkit
23
+ # or
24
+ pnpm add @rfjs/pg-toolkit
34
25
  ```
35
26
 
36
- ## Reference
37
- - [Original README](./START_BY_README.md)
38
-
27
+ ## Usage Example
28
+
29
+ ### Managing Seed History
30
+
31
+ ```typescript
32
+ import { ensureSeedHistoryTable, checkSeedExecuted, recordSeedExecution } from '@rfjs/pg-toolkit/admin';
33
+ import { Client } from 'pg';
34
+
35
+ const client = new Client(process.env.DATABASE_URL);
36
+ await client.connect();
37
+
38
+ // Ensure history table exists
39
+ await ensureSeedHistoryTable(client);
40
+
41
+ // Check and execute
42
+ if (!await checkSeedExecuted(client, 'init_data')) {
43
+ // await runMySeed();
44
+ await recordSeedExecution(client, 'init_data');
45
+ }
46
+ ```
@@ -0,0 +1,46 @@
1
+ # @packages/pg-toolkit
2
+
3
+ PostgreSQL 工具庫,提供跨 ORM (Drizzle, Prisma, Kysely, TypeORM) 共用的基礎功能與管理腳本。
4
+
5
+ ## 功能特色
6
+
7
+ ### Admin (管理工具)
8
+ 提供資料庫層級的管理功能,通常用於 CI/CD 或開發環境初始化。
9
+ - `ensureSeedHistoryTable`: 建立並管理種子資料執行紀錄表 (`__seed_history`)。
10
+ - `checkSeedExecuted`: 檢查特定種子資料是否已執行。
11
+ - `recordSeedExecution`: 紀錄種子資料執行狀態。
12
+ - `checkAndCreateDB`: 檢查並自動建立資料庫。
13
+ - `checkAndCreateSchema`: 檢查並自動建立 Schema。
14
+
15
+ ### Pure (純函數)
16
+ 不依賴資料庫連線的工具函數。
17
+ - `getConnectionStringInfo`: 解析 Connection String,處理 `schema` 參數與 `search_path` options 的合併邏輯。
18
+
19
+ ## 安裝
20
+
21
+ ```bash
22
+ npm install @rfjs/pg-toolkit
23
+ # 或
24
+ pnpm add @rfjs/pg-toolkit
25
+ ```
26
+
27
+ ## 使用範例
28
+
29
+ ### 管理種子紀錄
30
+
31
+ ```typescript
32
+ import { ensureSeedHistoryTable, checkSeedExecuted, recordSeedExecution } from '@rfjs/pg-toolkit/admin';
33
+ import { Client } from 'pg';
34
+
35
+ const client = new Client(process.env.DATABASE_URL);
36
+ await client.connect();
37
+
38
+ // 確保紀錄表存在
39
+ await ensureSeedHistoryTable(client);
40
+
41
+ // 檢查並執行
42
+ if (!await checkSeedExecuted(client, 'init_data')) {
43
+ // await runMySeed();
44
+ await recordSeedExecution(client, 'init_data');
45
+ }
46
+ ```
@@ -1,8 +1,33 @@
1
+ import { Client, Pool } from "pg";
2
+
1
3
  //#region src/admin/ensure-db.d.ts
2
4
  declare function checkAndCreateDB(connectionString: string): Promise<void>;
3
5
  //#endregion
4
6
  //#region src/admin/ensure-schema.d.ts
5
7
  declare function checkAndCreateSchema(connectionString: string, schemas: string[]): Promise<void>;
6
8
  //#endregion
7
- export { checkAndCreateDB, checkAndCreateSchema };
9
+ //#region src/admin/seed-history.d.ts
10
+ /**
11
+ * 確保種子資料歷史紀錄表存在
12
+ * @param client PG Client 或 Pool
13
+ * @param tableName 資料表名稱 (預設: __seed_history)
14
+ */
15
+ declare function ensureSeedHistoryTable(client: Client | Pool, tableName?: string): Promise<void>;
16
+ /**
17
+ * 檢查種子資料是否已執行過
18
+ * @param client PG Client 或 Pool
19
+ * @param name 種子資料名稱
20
+ * @param tableName 資料表名稱 (預設: __seed_history)
21
+ * @returns 是否已執行
22
+ */
23
+ declare function checkSeedExecuted(client: Client | Pool, name: string, tableName?: string): Promise<boolean>;
24
+ /**
25
+ * 紀錄種子資料執行紀錄
26
+ * @param client PG Client 或 Pool
27
+ * @param name 種子資料名稱
28
+ * @param tableName 資料表名稱 (預設: __seed_history)
29
+ */
30
+ declare function recordSeedExecution(client: Client | Pool, name: string, tableName?: string): Promise<void>;
31
+ //#endregion
32
+ export { checkAndCreateDB, checkAndCreateSchema, checkSeedExecuted, ensureSeedHistoryTable, recordSeedExecution };
8
33
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/admin/ensure-db.ts","../../src/admin/ensure-schema.ts"],"sourcesContent":[],"mappings":";iBAGsB,gBAAA,4BAA4C;;;iBCD5C,oBAAA,+CAGnB"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/admin/ensure-db.ts","../../src/admin/ensure-schema.ts","../../src/admin/seed-history.ts"],"sourcesContent":[],"mappings":";;;iBAGsB,gBAAA,4BAA4C;;;iBCD5C,oBAAA,+CAGnB;;;;;ADFH;;;iBEMsB,sBAAA,SACZ,SAAS,2BAEhB;ADVH;;;;ACOA;;;AAGG,iBAiBmB,iBAAA,CAjBnB,MAAA,EAkBO,MAlBP,GAkBgB,IAlBhB,EAAA,IAAA,EAAA,MAAA,EAAA,SAAA,CAAA,EAAA,MAAA,CAAA,EAqBA,OArBA,CAAA,OAAA,CAAA;;AAiBH;;;;;AAiBsB,iBAAA,mBAAA,CAAA,MAAA,EACZ,MADY,GACH,IADG,EAAA,IAAA,EAAA,MAAA,EAAA,SAAA,CAAA,EAAA,MAAA,CAAA,EAInB,OAJmB,CAAA,IAAA,CAAA"}
@@ -1,8 +1,33 @@
1
+ import { Client, Pool } from "pg";
2
+
1
3
  //#region src/admin/ensure-db.d.ts
2
4
  declare function checkAndCreateDB(connectionString: string): Promise<void>;
3
5
  //#endregion
4
6
  //#region src/admin/ensure-schema.d.ts
5
7
  declare function checkAndCreateSchema(connectionString: string, schemas: string[]): Promise<void>;
6
8
  //#endregion
7
- export { checkAndCreateDB, checkAndCreateSchema };
9
+ //#region src/admin/seed-history.d.ts
10
+ /**
11
+ * 確保種子資料歷史紀錄表存在
12
+ * @param client PG Client 或 Pool
13
+ * @param tableName 資料表名稱 (預設: __seed_history)
14
+ */
15
+ declare function ensureSeedHistoryTable(client: Client | Pool, tableName?: string): Promise<void>;
16
+ /**
17
+ * 檢查種子資料是否已執行過
18
+ * @param client PG Client 或 Pool
19
+ * @param name 種子資料名稱
20
+ * @param tableName 資料表名稱 (預設: __seed_history)
21
+ * @returns 是否已執行
22
+ */
23
+ declare function checkSeedExecuted(client: Client | Pool, name: string, tableName?: string): Promise<boolean>;
24
+ /**
25
+ * 紀錄種子資料執行紀錄
26
+ * @param client PG Client 或 Pool
27
+ * @param name 種子資料名稱
28
+ * @param tableName 資料表名稱 (預設: __seed_history)
29
+ */
30
+ declare function recordSeedExecution(client: Client | Pool, name: string, tableName?: string): Promise<void>;
31
+ //#endregion
32
+ export { checkAndCreateDB, checkAndCreateSchema, checkSeedExecuted, ensureSeedHistoryTable, recordSeedExecution };
8
33
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/admin/ensure-db.ts","../../src/admin/ensure-schema.ts"],"sourcesContent":[],"mappings":";iBAGsB,gBAAA,4BAA4C;;;iBCD5C,oBAAA,+CAGnB"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/admin/ensure-db.ts","../../src/admin/ensure-schema.ts","../../src/admin/seed-history.ts"],"sourcesContent":[],"mappings":";;;iBAGsB,gBAAA,4BAA4C;;;iBCD5C,oBAAA,+CAGnB;;;;;ADFH;;;iBEMsB,sBAAA,SACZ,SAAS,2BAEhB;ADVH;;;;ACOA;;;AAGG,iBAiBmB,iBAAA,CAjBnB,MAAA,EAkBO,MAlBP,GAkBgB,IAlBhB,EAAA,IAAA,EAAA,MAAA,EAAA,SAAA,CAAA,EAAA,MAAA,CAAA,EAqBA,OArBA,CAAA,OAAA,CAAA;;AAiBH;;;;;AAiBsB,iBAAA,mBAAA,CAAA,MAAA,EACZ,MADY,GACH,IADG,EAAA,IAAA,EAAA,MAAA,EAAA,SAAA,CAAA,EAAA,MAAA,CAAA,EAInB,OAJmB,CAAA,IAAA,CAAA"}
@@ -1,9 +1,9 @@
1
- const require_esm = require('../esm-9QNtbaRS.js');
1
+ let pg_connection_string = require("pg-connection-string");
2
2
  let pg = require("pg");
3
3
 
4
4
  //#region src/admin/ensure-db.ts
5
5
  async function checkAndCreateDB(connectionString) {
6
- const { user, password, host, port, database } = require_esm.parse(connectionString);
6
+ const { user, password, host, port, database } = (0, pg_connection_string.parse)(connectionString);
7
7
  const adminConnectionString = `postgres://${user}:${password}@${host}:${port}/postgres`;
8
8
  const targetDb = database ?? "orm";
9
9
  const client = new pg.Client({ connectionString: adminConnectionString });
@@ -41,7 +41,47 @@ async function checkAndCreateSchema(connectionString, schemas) {
41
41
  }
42
42
  }
43
43
 
44
+ //#endregion
45
+ //#region src/admin/seed-history.ts
46
+ const DEFAULT_TABLE_NAME = "__seed_history";
47
+ /**
48
+ * 確保種子資料歷史紀錄表存在
49
+ * @param client PG Client 或 Pool
50
+ * @param tableName 資料表名稱 (預設: __seed_history)
51
+ */
52
+ async function ensureSeedHistoryTable(client, tableName = DEFAULT_TABLE_NAME) {
53
+ await client.query(`
54
+ CREATE TABLE IF NOT EXISTS "${tableName}" (
55
+ "id" SERIAL PRIMARY KEY,
56
+ "name" VARCHAR(255) NOT NULL UNIQUE,
57
+ "executed_at" TIMESTAMPTZ DEFAULT NOW()
58
+ );
59
+ `);
60
+ }
61
+ /**
62
+ * 檢查種子資料是否已執行過
63
+ * @param client PG Client 或 Pool
64
+ * @param name 種子資料名稱
65
+ * @param tableName 資料表名稱 (預設: __seed_history)
66
+ * @returns 是否已執行
67
+ */
68
+ async function checkSeedExecuted(client, name, tableName = DEFAULT_TABLE_NAME) {
69
+ return ((await client.query(`SELECT 1 FROM "${tableName}" WHERE "name" = $1`, [name])).rowCount ?? 0) > 0;
70
+ }
71
+ /**
72
+ * 紀錄種子資料執行紀錄
73
+ * @param client PG Client 或 Pool
74
+ * @param name 種子資料名稱
75
+ * @param tableName 資料表名稱 (預設: __seed_history)
76
+ */
77
+ async function recordSeedExecution(client, name, tableName = DEFAULT_TABLE_NAME) {
78
+ await client.query(`INSERT INTO "${tableName}" ("name") VALUES ($1)`, [name]);
79
+ }
80
+
44
81
  //#endregion
45
82
  exports.checkAndCreateDB = checkAndCreateDB;
46
83
  exports.checkAndCreateSchema = checkAndCreateSchema;
84
+ exports.checkSeedExecuted = checkSeedExecuted;
85
+ exports.ensureSeedHistoryTable = ensureSeedHistoryTable;
86
+ exports.recordSeedExecution = recordSeedExecution;
47
87
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["parse","Client","Client"],"sources":["../../src/admin/ensure-db.ts","../../src/admin/ensure-schema.ts"],"sourcesContent":["import { Client } from 'pg';\nimport { parse } from 'pg-connection-string';\n\nexport async function checkAndCreateDB(connectionString: string): Promise<void> {\n // Use pg-connection-string for more robust parsing and to generate admin connection string\n // Default fallback\n const config = parse(connectionString);\n const { user, password, host, port, database } = config;\n const adminConnectionString = `postgres://${user}:${password}@${host}:${port}/postgres`;\n const targetDb = database ?? 'orm';\n const client = new Client({\n connectionString: adminConnectionString,\n });\n let isConnected = false;\n\n try {\n await client.connect();\n isConnected = true;\n const res = await client.query(`SELECT 1 FROM pg_database WHERE datname = $1`, [\n targetDb,\n ]);\n\n if (res.rowCount === 0) {\n console.log(`Database \"${targetDb}\" does not exist. Creating...`);\n await client.query(`CREATE DATABASE \"${targetDb}\"`);\n console.log(`Database \"${targetDb}\" created successfully.`);\n }\n } catch (error) {\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n console.error(`Failed to ensure database exists: ${error}`);\n throw error;\n } finally {\n if (isConnected) {\n await client.end();\n }\n }\n}\n","import { Client } from 'pg';\n\nexport async function checkAndCreateSchema(\n connectionString: string,\n schemas: string[],\n): Promise<void> {\n const client = new Client(connectionString);\n let isConnected = false;\n\n try {\n await client.connect();\n isConnected = true;\n for (const schema of schemas) {\n await client.query(`CREATE SCHEMA IF NOT EXISTS \"${schema}\"`);\n }\n } catch (error) {\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n console.error(`Failed to ensure schema exists: ${error}`);\n throw error;\n } finally {\n if (isConnected) {\n await client.end();\n }\n }\n}\n"],"mappings":";;;;AAGA,eAAsB,iBAAiB,kBAAyC;CAI9E,MAAM,EAAE,MAAM,UAAU,MAAM,MAAM,aADrBA,kBAAM,iBAAiB;CAEtC,MAAM,wBAAwB,cAAc,KAAK,GAAG,SAAS,GAAG,KAAK,GAAG,KAAK;CAC7E,MAAM,WAAW,YAAY;CAC7B,MAAM,SAAS,IAAIC,UAAO,EACxB,kBAAkB,uBACnB,CAAC;CACF,IAAI,cAAc;AAElB,KAAI;AACF,QAAM,OAAO,SAAS;AACtB,gBAAc;AAKd,OAJY,MAAM,OAAO,MAAM,gDAAgD,CAC7E,SACD,CAAC,EAEM,aAAa,GAAG;AACtB,WAAQ,IAAI,aAAa,SAAS,+BAA+B;AACjE,SAAM,OAAO,MAAM,oBAAoB,SAAS,GAAG;AACnD,WAAQ,IAAI,aAAa,SAAS,yBAAyB;;UAEtD,OAAO;AAEd,UAAQ,MAAM,qCAAqC,QAAQ;AAC3D,QAAM;WACE;AACR,MAAI,YACF,OAAM,OAAO,KAAK;;;;;;AC/BxB,eAAsB,qBACpB,kBACA,SACe;CACf,MAAM,SAAS,IAAIC,UAAO,iBAAiB;CAC3C,IAAI,cAAc;AAElB,KAAI;AACF,QAAM,OAAO,SAAS;AACtB,gBAAc;AACd,OAAK,MAAM,UAAU,QACnB,OAAM,OAAO,MAAM,gCAAgC,OAAO,GAAG;UAExD,OAAO;AAEd,UAAQ,MAAM,mCAAmC,QAAQ;AACzD,QAAM;WACE;AACR,MAAI,YACF,OAAM,OAAO,KAAK"}
1
+ {"version":3,"file":"index.js","names":["Client","Client"],"sources":["../../src/admin/ensure-db.ts","../../src/admin/ensure-schema.ts","../../src/admin/seed-history.ts"],"sourcesContent":["import { Client } from 'pg';\nimport { parse } from 'pg-connection-string';\n\nexport async function checkAndCreateDB(connectionString: string): Promise<void> {\n // Use pg-connection-string for more robust parsing and to generate admin connection string\n // Default fallback\n const config = parse(connectionString);\n const { user, password, host, port, database } = config;\n const adminConnectionString = `postgres://${user}:${password}@${host}:${port}/postgres`;\n const targetDb = database ?? 'orm';\n const client = new Client({\n connectionString: adminConnectionString,\n });\n let isConnected = false;\n\n try {\n await client.connect();\n isConnected = true;\n const res = await client.query(`SELECT 1 FROM pg_database WHERE datname = $1`, [\n targetDb,\n ]);\n\n if (res.rowCount === 0) {\n console.log(`Database \"${targetDb}\" does not exist. Creating...`);\n await client.query(`CREATE DATABASE \"${targetDb}\"`);\n console.log(`Database \"${targetDb}\" created successfully.`);\n }\n } catch (error) {\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n console.error(`Failed to ensure database exists: ${error}`);\n throw error;\n } finally {\n if (isConnected) {\n await client.end();\n }\n }\n}\n","import { Client } from 'pg';\n\nexport async function checkAndCreateSchema(\n connectionString: string,\n schemas: string[],\n): Promise<void> {\n const client = new Client(connectionString);\n let isConnected = false;\n\n try {\n await client.connect();\n isConnected = true;\n for (const schema of schemas) {\n await client.query(`CREATE SCHEMA IF NOT EXISTS \"${schema}\"`);\n }\n } catch (error) {\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n console.error(`Failed to ensure schema exists: ${error}`);\n throw error;\n } finally {\n if (isConnected) {\n await client.end();\n }\n }\n}\n","import { Client, Pool } from 'pg';\n\nconst DEFAULT_TABLE_NAME = '__seed_history';\n\n/**\n * 確保種子資料歷史紀錄表存在\n * @param client PG Client 或 Pool\n * @param tableName 資料表名稱 (預設: __seed_history)\n */\nexport async function ensureSeedHistoryTable(\n client: Client | Pool,\n tableName: string = DEFAULT_TABLE_NAME,\n): Promise<void> {\n await client.query(`\n CREATE TABLE IF NOT EXISTS \"${tableName}\" (\n \"id\" SERIAL PRIMARY KEY,\n \"name\" VARCHAR(255) NOT NULL UNIQUE,\n \"executed_at\" TIMESTAMPTZ DEFAULT NOW()\n );\n `);\n}\n\n/**\n * 檢查種子資料是否已執行過\n * @param client PG Client 或 Pool\n * @param name 種子資料名稱\n * @param tableName 資料表名稱 (預設: __seed_history)\n * @returns 是否已執行\n */\nexport async function checkSeedExecuted(\n client: Client | Pool,\n name: string,\n tableName: string = DEFAULT_TABLE_NAME,\n): Promise<boolean> {\n const res = await client.query(`SELECT 1 FROM \"${tableName}\" WHERE \"name\" = $1`, [\n name,\n ]);\n return (res.rowCount ?? 0) > 0;\n}\n\n/**\n * 紀錄種子資料執行紀錄\n * @param client PG Client 或 Pool\n * @param name 種子資料名稱\n * @param tableName 資料表名稱 (預設: __seed_history)\n */\nexport async function recordSeedExecution(\n client: Client | Pool,\n name: string,\n tableName: string = DEFAULT_TABLE_NAME,\n): Promise<void> {\n await client.query(`INSERT INTO \"${tableName}\" (\"name\") VALUES ($1)`, [name]);\n}\n"],"mappings":";;;;AAGA,eAAsB,iBAAiB,kBAAyC;CAI9E,MAAM,EAAE,MAAM,UAAU,MAAM,MAAM,6CADf,iBAAiB;CAEtC,MAAM,wBAAwB,cAAc,KAAK,GAAG,SAAS,GAAG,KAAK,GAAG,KAAK;CAC7E,MAAM,WAAW,YAAY;CAC7B,MAAM,SAAS,IAAIA,UAAO,EACxB,kBAAkB,uBACnB,CAAC;CACF,IAAI,cAAc;AAElB,KAAI;AACF,QAAM,OAAO,SAAS;AACtB,gBAAc;AAKd,OAJY,MAAM,OAAO,MAAM,gDAAgD,CAC7E,SACD,CAAC,EAEM,aAAa,GAAG;AACtB,WAAQ,IAAI,aAAa,SAAS,+BAA+B;AACjE,SAAM,OAAO,MAAM,oBAAoB,SAAS,GAAG;AACnD,WAAQ,IAAI,aAAa,SAAS,yBAAyB;;UAEtD,OAAO;AAEd,UAAQ,MAAM,qCAAqC,QAAQ;AAC3D,QAAM;WACE;AACR,MAAI,YACF,OAAM,OAAO,KAAK;;;;;;AC/BxB,eAAsB,qBACpB,kBACA,SACe;CACf,MAAM,SAAS,IAAIC,UAAO,iBAAiB;CAC3C,IAAI,cAAc;AAElB,KAAI;AACF,QAAM,OAAO,SAAS;AACtB,gBAAc;AACd,OAAK,MAAM,UAAU,QACnB,OAAM,OAAO,MAAM,gCAAgC,OAAO,GAAG;UAExD,OAAO;AAEd,UAAQ,MAAM,mCAAmC,QAAQ;AACzD,QAAM;WACE;AACR,MAAI,YACF,OAAM,OAAO,KAAK;;;;;;ACnBxB,MAAM,qBAAqB;;;;;;AAO3B,eAAsB,uBACpB,QACA,YAAoB,oBACL;AACf,OAAM,OAAO,MAAM;kCACa,UAAU;;;;;IAKxC;;;;;;;;;AAUJ,eAAsB,kBACpB,QACA,MACA,YAAoB,oBACF;AAIlB,UAHY,MAAM,OAAO,MAAM,kBAAkB,UAAU,sBAAsB,CAC/E,KACD,CAAC,EACU,YAAY,KAAK;;;;;;;;AAS/B,eAAsB,oBACpB,QACA,MACA,YAAoB,oBACL;AACf,OAAM,OAAO,MAAM,gBAAgB,UAAU,yBAAyB,CAAC,KAAK,CAAC"}
@@ -1,4 +1,4 @@
1
- import { t as parse } from "../esm-v1isYkCK.mjs";
1
+ import { parse } from "pg-connection-string";
2
2
  import { Client } from "pg";
3
3
 
4
4
  //#region src/admin/ensure-db.ts
@@ -42,5 +42,42 @@ async function checkAndCreateSchema(connectionString, schemas) {
42
42
  }
43
43
 
44
44
  //#endregion
45
- export { checkAndCreateDB, checkAndCreateSchema };
45
+ //#region src/admin/seed-history.ts
46
+ const DEFAULT_TABLE_NAME = "__seed_history";
47
+ /**
48
+ * 確保種子資料歷史紀錄表存在
49
+ * @param client PG Client 或 Pool
50
+ * @param tableName 資料表名稱 (預設: __seed_history)
51
+ */
52
+ async function ensureSeedHistoryTable(client, tableName = DEFAULT_TABLE_NAME) {
53
+ await client.query(`
54
+ CREATE TABLE IF NOT EXISTS "${tableName}" (
55
+ "id" SERIAL PRIMARY KEY,
56
+ "name" VARCHAR(255) NOT NULL UNIQUE,
57
+ "executed_at" TIMESTAMPTZ DEFAULT NOW()
58
+ );
59
+ `);
60
+ }
61
+ /**
62
+ * 檢查種子資料是否已執行過
63
+ * @param client PG Client 或 Pool
64
+ * @param name 種子資料名稱
65
+ * @param tableName 資料表名稱 (預設: __seed_history)
66
+ * @returns 是否已執行
67
+ */
68
+ async function checkSeedExecuted(client, name, tableName = DEFAULT_TABLE_NAME) {
69
+ return ((await client.query(`SELECT 1 FROM "${tableName}" WHERE "name" = $1`, [name])).rowCount ?? 0) > 0;
70
+ }
71
+ /**
72
+ * 紀錄種子資料執行紀錄
73
+ * @param client PG Client 或 Pool
74
+ * @param name 種子資料名稱
75
+ * @param tableName 資料表名稱 (預設: __seed_history)
76
+ */
77
+ async function recordSeedExecution(client, name, tableName = DEFAULT_TABLE_NAME) {
78
+ await client.query(`INSERT INTO "${tableName}" ("name") VALUES ($1)`, [name]);
79
+ }
80
+
81
+ //#endregion
82
+ export { checkAndCreateDB, checkAndCreateSchema, checkSeedExecuted, ensureSeedHistoryTable, recordSeedExecution };
46
83
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/admin/ensure-db.ts","../../src/admin/ensure-schema.ts"],"sourcesContent":["import { Client } from 'pg';\nimport { parse } from 'pg-connection-string';\n\nexport async function checkAndCreateDB(connectionString: string): Promise<void> {\n // Use pg-connection-string for more robust parsing and to generate admin connection string\n // Default fallback\n const config = parse(connectionString);\n const { user, password, host, port, database } = config;\n const adminConnectionString = `postgres://${user}:${password}@${host}:${port}/postgres`;\n const targetDb = database ?? 'orm';\n const client = new Client({\n connectionString: adminConnectionString,\n });\n let isConnected = false;\n\n try {\n await client.connect();\n isConnected = true;\n const res = await client.query(`SELECT 1 FROM pg_database WHERE datname = $1`, [\n targetDb,\n ]);\n\n if (res.rowCount === 0) {\n console.log(`Database \"${targetDb}\" does not exist. Creating...`);\n await client.query(`CREATE DATABASE \"${targetDb}\"`);\n console.log(`Database \"${targetDb}\" created successfully.`);\n }\n } catch (error) {\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n console.error(`Failed to ensure database exists: ${error}`);\n throw error;\n } finally {\n if (isConnected) {\n await client.end();\n }\n }\n}\n","import { Client } from 'pg';\n\nexport async function checkAndCreateSchema(\n connectionString: string,\n schemas: string[],\n): Promise<void> {\n const client = new Client(connectionString);\n let isConnected = false;\n\n try {\n await client.connect();\n isConnected = true;\n for (const schema of schemas) {\n await client.query(`CREATE SCHEMA IF NOT EXISTS \"${schema}\"`);\n }\n } catch (error) {\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n console.error(`Failed to ensure schema exists: ${error}`);\n throw error;\n } finally {\n if (isConnected) {\n await client.end();\n }\n }\n}\n"],"mappings":";;;;AAGA,eAAsB,iBAAiB,kBAAyC;CAI9E,MAAM,EAAE,MAAM,UAAU,MAAM,MAAM,aADrB,MAAM,iBAAiB;CAEtC,MAAM,wBAAwB,cAAc,KAAK,GAAG,SAAS,GAAG,KAAK,GAAG,KAAK;CAC7E,MAAM,WAAW,YAAY;CAC7B,MAAM,SAAS,IAAI,OAAO,EACxB,kBAAkB,uBACnB,CAAC;CACF,IAAI,cAAc;AAElB,KAAI;AACF,QAAM,OAAO,SAAS;AACtB,gBAAc;AAKd,OAJY,MAAM,OAAO,MAAM,gDAAgD,CAC7E,SACD,CAAC,EAEM,aAAa,GAAG;AACtB,WAAQ,IAAI,aAAa,SAAS,+BAA+B;AACjE,SAAM,OAAO,MAAM,oBAAoB,SAAS,GAAG;AACnD,WAAQ,IAAI,aAAa,SAAS,yBAAyB;;UAEtD,OAAO;AAEd,UAAQ,MAAM,qCAAqC,QAAQ;AAC3D,QAAM;WACE;AACR,MAAI,YACF,OAAM,OAAO,KAAK;;;;;;AC/BxB,eAAsB,qBACpB,kBACA,SACe;CACf,MAAM,SAAS,IAAI,OAAO,iBAAiB;CAC3C,IAAI,cAAc;AAElB,KAAI;AACF,QAAM,OAAO,SAAS;AACtB,gBAAc;AACd,OAAK,MAAM,UAAU,QACnB,OAAM,OAAO,MAAM,gCAAgC,OAAO,GAAG;UAExD,OAAO;AAEd,UAAQ,MAAM,mCAAmC,QAAQ;AACzD,QAAM;WACE;AACR,MAAI,YACF,OAAM,OAAO,KAAK"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/admin/ensure-db.ts","../../src/admin/ensure-schema.ts","../../src/admin/seed-history.ts"],"sourcesContent":["import { Client } from 'pg';\nimport { parse } from 'pg-connection-string';\n\nexport async function checkAndCreateDB(connectionString: string): Promise<void> {\n // Use pg-connection-string for more robust parsing and to generate admin connection string\n // Default fallback\n const config = parse(connectionString);\n const { user, password, host, port, database } = config;\n const adminConnectionString = `postgres://${user}:${password}@${host}:${port}/postgres`;\n const targetDb = database ?? 'orm';\n const client = new Client({\n connectionString: adminConnectionString,\n });\n let isConnected = false;\n\n try {\n await client.connect();\n isConnected = true;\n const res = await client.query(`SELECT 1 FROM pg_database WHERE datname = $1`, [\n targetDb,\n ]);\n\n if (res.rowCount === 0) {\n console.log(`Database \"${targetDb}\" does not exist. Creating...`);\n await client.query(`CREATE DATABASE \"${targetDb}\"`);\n console.log(`Database \"${targetDb}\" created successfully.`);\n }\n } catch (error) {\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n console.error(`Failed to ensure database exists: ${error}`);\n throw error;\n } finally {\n if (isConnected) {\n await client.end();\n }\n }\n}\n","import { Client } from 'pg';\n\nexport async function checkAndCreateSchema(\n connectionString: string,\n schemas: string[],\n): Promise<void> {\n const client = new Client(connectionString);\n let isConnected = false;\n\n try {\n await client.connect();\n isConnected = true;\n for (const schema of schemas) {\n await client.query(`CREATE SCHEMA IF NOT EXISTS \"${schema}\"`);\n }\n } catch (error) {\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n console.error(`Failed to ensure schema exists: ${error}`);\n throw error;\n } finally {\n if (isConnected) {\n await client.end();\n }\n }\n}\n","import { Client, Pool } from 'pg';\n\nconst DEFAULT_TABLE_NAME = '__seed_history';\n\n/**\n * 確保種子資料歷史紀錄表存在\n * @param client PG Client 或 Pool\n * @param tableName 資料表名稱 (預設: __seed_history)\n */\nexport async function ensureSeedHistoryTable(\n client: Client | Pool,\n tableName: string = DEFAULT_TABLE_NAME,\n): Promise<void> {\n await client.query(`\n CREATE TABLE IF NOT EXISTS \"${tableName}\" (\n \"id\" SERIAL PRIMARY KEY,\n \"name\" VARCHAR(255) NOT NULL UNIQUE,\n \"executed_at\" TIMESTAMPTZ DEFAULT NOW()\n );\n `);\n}\n\n/**\n * 檢查種子資料是否已執行過\n * @param client PG Client 或 Pool\n * @param name 種子資料名稱\n * @param tableName 資料表名稱 (預設: __seed_history)\n * @returns 是否已執行\n */\nexport async function checkSeedExecuted(\n client: Client | Pool,\n name: string,\n tableName: string = DEFAULT_TABLE_NAME,\n): Promise<boolean> {\n const res = await client.query(`SELECT 1 FROM \"${tableName}\" WHERE \"name\" = $1`, [\n name,\n ]);\n return (res.rowCount ?? 0) > 0;\n}\n\n/**\n * 紀錄種子資料執行紀錄\n * @param client PG Client 或 Pool\n * @param name 種子資料名稱\n * @param tableName 資料表名稱 (預設: __seed_history)\n */\nexport async function recordSeedExecution(\n client: Client | Pool,\n name: string,\n tableName: string = DEFAULT_TABLE_NAME,\n): Promise<void> {\n await client.query(`INSERT INTO \"${tableName}\" (\"name\") VALUES ($1)`, [name]);\n}\n"],"mappings":";;;;AAGA,eAAsB,iBAAiB,kBAAyC;CAI9E,MAAM,EAAE,MAAM,UAAU,MAAM,MAAM,aADrB,MAAM,iBAAiB;CAEtC,MAAM,wBAAwB,cAAc,KAAK,GAAG,SAAS,GAAG,KAAK,GAAG,KAAK;CAC7E,MAAM,WAAW,YAAY;CAC7B,MAAM,SAAS,IAAI,OAAO,EACxB,kBAAkB,uBACnB,CAAC;CACF,IAAI,cAAc;AAElB,KAAI;AACF,QAAM,OAAO,SAAS;AACtB,gBAAc;AAKd,OAJY,MAAM,OAAO,MAAM,gDAAgD,CAC7E,SACD,CAAC,EAEM,aAAa,GAAG;AACtB,WAAQ,IAAI,aAAa,SAAS,+BAA+B;AACjE,SAAM,OAAO,MAAM,oBAAoB,SAAS,GAAG;AACnD,WAAQ,IAAI,aAAa,SAAS,yBAAyB;;UAEtD,OAAO;AAEd,UAAQ,MAAM,qCAAqC,QAAQ;AAC3D,QAAM;WACE;AACR,MAAI,YACF,OAAM,OAAO,KAAK;;;;;;AC/BxB,eAAsB,qBACpB,kBACA,SACe;CACf,MAAM,SAAS,IAAI,OAAO,iBAAiB;CAC3C,IAAI,cAAc;AAElB,KAAI;AACF,QAAM,OAAO,SAAS;AACtB,gBAAc;AACd,OAAK,MAAM,UAAU,QACnB,OAAM,OAAO,MAAM,gCAAgC,OAAO,GAAG;UAExD,OAAO;AAEd,UAAQ,MAAM,mCAAmC,QAAQ;AACzD,QAAM;WACE;AACR,MAAI,YACF,OAAM,OAAO,KAAK;;;;;;ACnBxB,MAAM,qBAAqB;;;;;;AAO3B,eAAsB,uBACpB,QACA,YAAoB,oBACL;AACf,OAAM,OAAO,MAAM;kCACa,UAAU;;;;;IAKxC;;;;;;;;;AAUJ,eAAsB,kBACpB,QACA,MACA,YAAoB,oBACF;AAIlB,UAHY,MAAM,OAAO,MAAM,kBAAkB,UAAU,sBAAsB,CAC/E,KACD,CAAC,EACU,YAAY,KAAK;;;;;;;;AAS/B,eAAsB,oBACpB,QACA,MACA,YAAoB,oBACL;AACf,OAAM,OAAO,MAAM,gBAAgB,UAAU,yBAAyB,CAAC,KAAK,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- const require_esm = require('./esm-9QNtbaRS.js');
1
+ let pg_connection_string = require("pg-connection-string");
2
2
 
3
3
  //#region src/pure/options.ts
4
4
  /**
@@ -25,7 +25,7 @@ function mergeOptions(existing, schema) {
25
25
  return existing && existing.trim() ? `${existing.trim()} ${add}` : add;
26
26
  }
27
27
  function getConnectionStringInfo(connectionString, targetSchema) {
28
- const config = require_esm.parse(connectionString);
28
+ const config = (0, pg_connection_string.parse)(connectionString);
29
29
  const url = new URL(connectionString);
30
30
  const options = url.searchParams.get("options") ?? config.options ?? void 0;
31
31
  const optionsSchemas = getOptionsSchemas(options);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["parse"],"sources":["../src/pure/options.ts","../src/pure/connection-string.ts"],"sourcesContent":["/**\n * 從 options 解析 search_path\n * 支援:\n * -c search_path=a,b\n * -csearch_path=a,b (防呆,但會 normalize)\n */\nexport function getOptionsSchemas(options?: string): string[] {\n if (!options) return [];\n\n // normalize: -csearch_path -> -c search_path\n const normalized = options.replace(/-csearch_path=/g, '-c search_path=');\n\n // match: search_path=a,b (到空白結束)\n const m = normalized.match(/(?:^|\\s)search_path=([^\\s]+)/);\n if (!m) return [];\n\n return m[1]\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n}\n","import { parse } from 'pg-connection-string';\nimport { getOptionsSchemas } from './options';\n\nfunction buildSearchPathOption(schema: string): string {\n return `-c search_path=${schema}`;\n}\n\nfunction mergeOptions(existing: string | undefined, schema: string): string {\n const schemas = getOptionsSchemas(existing);\n if (schemas.length > 0) return existing ?? '';\n const add = buildSearchPathOption(schema);\n return existing && existing.trim() ? `${existing.trim()} ${add}` : add;\n}\n\nexport function getConnectionStringInfo(\n connectionString: string,\n targetSchema?: string,\n): {\n finalConnectionString: string;\n finalSchema: string;\n optionsSchemas: string[];\n hasSearchPath: boolean;\n} {\n const config = parse(connectionString);\n const url = new URL(connectionString);\n\n // 這裡拿到的 options **是 decode 後的字串**(例如 \"-c search_path=prisma_test\")\n const options = url.searchParams.get('options') ?? config.options ?? undefined;\n\n const optionsSchemas = getOptionsSchemas(options);\n const hasSearchPath = optionsSchemas.length > 0;\n\n const schemaParam = url.searchParams.get('schema') ?? undefined;\n\n // options search_path > schema param > targetSchema > public\n const finalSchema = optionsSchemas[0] ?? schemaParam ?? targetSchema ?? 'public';\n\n // (1) 有 schema,沒 search_path → 補 options\n if (!hasSearchPath && finalSchema !== 'public') {\n const merged = mergeOptions(options, finalSchema);\n // ✅ 不要 encodeURIComponent,URLSearchParams 會自動處理\n url.searchParams.set('options', merged);\n }\n\n // (2) 有 search_path,沒 schema → 補 schema\n if (!schemaParam && optionsSchemas.length > 0) {\n url.searchParams.set('schema', optionsSchemas[0]);\n }\n\n const finalConnectionString = url.toString();\n\n return {\n optionsSchemas,\n finalSchema,\n finalConnectionString,\n hasSearchPath,\n };\n}\n"],"mappings":";;;;;;;;;AAMA,SAAgB,kBAAkB,SAA4B;AAC5D,KAAI,CAAC,QAAS,QAAO,EAAE;CAMvB,MAAM,IAHa,QAAQ,QAAQ,mBAAmB,kBAAkB,CAGnD,MAAM,+BAA+B;AAC1D,KAAI,CAAC,EAAG,QAAO,EAAE;AAEjB,QAAO,EAAE,GACN,MAAM,IAAI,CACV,KAAK,MAAM,EAAE,MAAM,CAAC,CACpB,OAAO,QAAQ;;;;;AChBpB,SAAS,sBAAsB,QAAwB;AACrD,QAAO,kBAAkB;;AAG3B,SAAS,aAAa,UAA8B,QAAwB;AAE1E,KADgB,kBAAkB,SAAS,CAC/B,SAAS,EAAG,QAAO,YAAY;CAC3C,MAAM,MAAM,sBAAsB,OAAO;AACzC,QAAO,YAAY,SAAS,MAAM,GAAG,GAAG,SAAS,MAAM,CAAC,GAAG,QAAQ;;AAGrE,SAAgB,wBACd,kBACA,cAMA;CACA,MAAM,SAASA,kBAAM,iBAAiB;CACtC,MAAM,MAAM,IAAI,IAAI,iBAAiB;CAGrC,MAAM,UAAU,IAAI,aAAa,IAAI,UAAU,IAAI,OAAO,WAAW;CAErE,MAAM,iBAAiB,kBAAkB,QAAQ;CACjD,MAAM,gBAAgB,eAAe,SAAS;CAE9C,MAAM,cAAc,IAAI,aAAa,IAAI,SAAS,IAAI;CAGtD,MAAM,cAAc,eAAe,MAAM,eAAe,gBAAgB;AAGxE,KAAI,CAAC,iBAAiB,gBAAgB,UAAU;EAC9C,MAAM,SAAS,aAAa,SAAS,YAAY;AAEjD,MAAI,aAAa,IAAI,WAAW,OAAO;;AAIzC,KAAI,CAAC,eAAe,eAAe,SAAS,EAC1C,KAAI,aAAa,IAAI,UAAU,eAAe,GAAG;AAKnD,QAAO;EACL;EACA;EACA,uBAL4B,IAAI,UAAU;EAM1C;EACD"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/pure/options.ts","../src/pure/connection-string.ts"],"sourcesContent":["/**\n * 從 options 解析 search_path\n * 支援:\n * -c search_path=a,b\n * -csearch_path=a,b (防呆,但會 normalize)\n */\nexport function getOptionsSchemas(options?: string): string[] {\n if (!options) return [];\n\n // normalize: -csearch_path -> -c search_path\n const normalized = options.replace(/-csearch_path=/g, '-c search_path=');\n\n // match: search_path=a,b (到空白結束)\n const m = normalized.match(/(?:^|\\s)search_path=([^\\s]+)/);\n if (!m) return [];\n\n return m[1]\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n}\n","import { parse } from 'pg-connection-string';\nimport { getOptionsSchemas } from './options';\n\nfunction buildSearchPathOption(schema: string): string {\n return `-c search_path=${schema}`;\n}\n\nfunction mergeOptions(existing: string | undefined, schema: string): string {\n const schemas = getOptionsSchemas(existing);\n if (schemas.length > 0) return existing ?? '';\n const add = buildSearchPathOption(schema);\n return existing && existing.trim() ? `${existing.trim()} ${add}` : add;\n}\n\nexport function getConnectionStringInfo(\n connectionString: string,\n targetSchema?: string,\n): {\n finalConnectionString: string;\n finalSchema: string;\n optionsSchemas: string[];\n hasSearchPath: boolean;\n} {\n const config = parse(connectionString);\n const url = new URL(connectionString);\n\n // 這裡拿到的 options **是 decode 後的字串**(例如 \"-c search_path=prisma_test\")\n const options = url.searchParams.get('options') ?? config.options ?? undefined;\n\n const optionsSchemas = getOptionsSchemas(options);\n const hasSearchPath = optionsSchemas.length > 0;\n\n const schemaParam = url.searchParams.get('schema') ?? undefined;\n\n // options search_path > schema param > targetSchema > public\n const finalSchema = optionsSchemas[0] ?? schemaParam ?? targetSchema ?? 'public';\n\n // (1) 有 schema,沒 search_path → 補 options\n if (!hasSearchPath && finalSchema !== 'public') {\n const merged = mergeOptions(options, finalSchema);\n // ✅ 不要 encodeURIComponent,URLSearchParams 會自動處理\n url.searchParams.set('options', merged);\n }\n\n // (2) 有 search_path,沒 schema → 補 schema\n if (!schemaParam && optionsSchemas.length > 0) {\n url.searchParams.set('schema', optionsSchemas[0]);\n }\n\n const finalConnectionString = url.toString();\n\n return {\n optionsSchemas,\n finalSchema,\n finalConnectionString,\n hasSearchPath,\n };\n}\n"],"mappings":";;;;;;;;;AAMA,SAAgB,kBAAkB,SAA4B;AAC5D,KAAI,CAAC,QAAS,QAAO,EAAE;CAMvB,MAAM,IAHa,QAAQ,QAAQ,mBAAmB,kBAAkB,CAGnD,MAAM,+BAA+B;AAC1D,KAAI,CAAC,EAAG,QAAO,EAAE;AAEjB,QAAO,EAAE,GACN,MAAM,IAAI,CACV,KAAK,MAAM,EAAE,MAAM,CAAC,CACpB,OAAO,QAAQ;;;;;AChBpB,SAAS,sBAAsB,QAAwB;AACrD,QAAO,kBAAkB;;AAG3B,SAAS,aAAa,UAA8B,QAAwB;AAE1E,KADgB,kBAAkB,SAAS,CAC/B,SAAS,EAAG,QAAO,YAAY;CAC3C,MAAM,MAAM,sBAAsB,OAAO;AACzC,QAAO,YAAY,SAAS,MAAM,GAAG,GAAG,SAAS,MAAM,CAAC,GAAG,QAAQ;;AAGrE,SAAgB,wBACd,kBACA,cAMA;CACA,MAAM,yCAAe,iBAAiB;CACtC,MAAM,MAAM,IAAI,IAAI,iBAAiB;CAGrC,MAAM,UAAU,IAAI,aAAa,IAAI,UAAU,IAAI,OAAO,WAAW;CAErE,MAAM,iBAAiB,kBAAkB,QAAQ;CACjD,MAAM,gBAAgB,eAAe,SAAS;CAE9C,MAAM,cAAc,IAAI,aAAa,IAAI,SAAS,IAAI;CAGtD,MAAM,cAAc,eAAe,MAAM,eAAe,gBAAgB;AAGxE,KAAI,CAAC,iBAAiB,gBAAgB,UAAU;EAC9C,MAAM,SAAS,aAAa,SAAS,YAAY;AAEjD,MAAI,aAAa,IAAI,WAAW,OAAO;;AAIzC,KAAI,CAAC,eAAe,eAAe,SAAS,EAC1C,KAAI,aAAa,IAAI,UAAU,eAAe,GAAG;AAKnD,QAAO;EACL;EACA;EACA,uBAL4B,IAAI,UAAU;EAM1C;EACD"}
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { t as parse } from "./esm-v1isYkCK.mjs";
1
+ import { parse } from "pg-connection-string";
2
2
 
3
3
  //#region src/pure/options.ts
4
4
  /**
package/dist/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rfjs/pg-toolkit",
3
- "version": "0.0.3",
4
- "description": "A project created by lib-tsdown",
3
+ "version": "0.0.5-alpha.0",
4
+ "description": "Shared PostgreSQL utilities and management scripts for Drizzle, Prisma, Kysely, and TypeORM",
5
5
  "files": [
6
6
  "dist",
7
7
  "README.md",
@@ -19,6 +19,7 @@
19
19
  },
20
20
  "dependencies": {
21
21
  "pg": "^8.16.3",
22
+ "pg-connection-string": "^2.9.1",
22
23
  "tslib": "^2.8.1"
23
24
  },
24
25
  "main": "index.js",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rfjs/pg-toolkit",
3
- "version": "0.0.3",
4
- "description": "A project created by lib-tsdown",
3
+ "version": "0.0.5-alpha.0",
4
+ "description": "Shared PostgreSQL utilities and management scripts for Drizzle, Prisma, Kysely, and TypeORM",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
7
7
  "types": "dist/index.d.ts",
@@ -27,9 +27,9 @@
27
27
  },
28
28
  "lint-staged": {
29
29
  "*.ts": [
30
- "npx vitest related --run",
31
- "npx prettier --write",
32
- "npx eslint --fix"
30
+ "pnpm exec vitest related --run",
31
+ "pnpm exec prettier --write",
32
+ "pnpm exec eslint --fix"
33
33
  ]
34
34
  },
35
35
  "config": {
@@ -61,7 +61,6 @@
61
61
  "husky": "^9.1.7",
62
62
  "inquirer": "9",
63
63
  "lint-staged": "^15.4.3",
64
- "pg-connection-string": "^2.9.1",
65
64
  "prettier": "^3.5.1",
66
65
  "rimraf": "^6.0.1",
67
66
  "supertest": "^7.0.0",
@@ -74,19 +73,20 @@
74
73
  },
75
74
  "dependencies": {
76
75
  "pg": "^8.16.3",
76
+ "pg-connection-string": "^2.9.1",
77
77
  "tslib": "^2.8.1"
78
78
  },
79
79
  "scripts": {
80
- "clean": "npx npm-run-all --parallel clean:dist clean:types",
81
- "clean:types": "npx rimraf ./types",
82
- "clean:dist": "npx rimraf ./dist",
83
- "dev": "npx npm-run-all --parallel dev:tsdown typecheck:watch",
80
+ "clean": "pnpm -r --parallel clean:dist clean:types",
81
+ "clean:types": "pnpm exec rimraf ./types",
82
+ "clean:dist": "pnpm exec rimraf ./dist",
83
+ "dev": "pnpm -r --parallel dev:tsdown typecheck:watch",
84
84
  "dev:tsdown": "npm run clean && tsdown --config-loader unrun --watch",
85
85
  "build": "npm run build:tsdown",
86
86
  "build:tsdown": "npm run clean && tsdown --config-loader unrun",
87
87
  "typecheck": "tsc --noEmit",
88
88
  "typecheck:watch": "tsc --noEmit --watch",
89
- "lint-staged": "npx lint-staged",
89
+ "lint-staged": "pnpm exec lint-staged",
90
90
  "lint": "eslint \"{src,apps,libs,test}/**/*.ts\"",
91
91
  "lint:fix": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
92
92
  "test": "npm run vitest:run",
@@ -95,9 +95,8 @@
95
95
  "vitest:ui": "vitest --passWithNoTests --ui",
96
96
  "vitest:e2e": "vitest --config vitest.config.e2e.mts --passWithNoTests",
97
97
  "vitest:e2e:ui": "vitest --config vitest.config.e2e.mts --passWithNoTests --ui",
98
- "release": "npx standard-version",
99
- "commit": "npx cz",
100
- "preinstall": "npx -y only-allow pnpm",
98
+ "release": "pnpm exec standard-version",
99
+ "commit": "pnpm exec cz",
101
100
  "docs:dev": "vitepress dev docs",
102
101
  "docs:build": "vitepress build docs",
103
102
  "docs:preview": "vitepress preview docs"
@@ -1,160 +0,0 @@
1
- //#region rolldown:runtime
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
9
- var __copyProps = (to, from, except, desc) => {
10
- if (from && typeof from === "object" || typeof from === "function") {
11
- for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
12
- key = keys[i];
13
- if (!__hasOwnProp.call(to, key) && key !== except) {
14
- __defProp(to, key, {
15
- get: ((k) => from[k]).bind(null, key),
16
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
17
- });
18
- }
19
- }
20
- }
21
- return to;
22
- };
23
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
24
- value: mod,
25
- enumerable: true
26
- }) : target, mod));
27
-
28
- //#endregion
29
-
30
- //#region ../../node_modules/.pnpm/pg-connection-string@2.9.1/node_modules/pg-connection-string/index.js
31
- var require_pg_connection_string = /* @__PURE__ */ __commonJSMin(((exports, module) => {
32
- function parse$1(str, options = {}) {
33
- if (str.charAt(0) === "/") {
34
- const config$1 = str.split(" ");
35
- return {
36
- host: config$1[0],
37
- database: config$1[1]
38
- };
39
- }
40
- const config = {};
41
- let result;
42
- let dummyHost = false;
43
- if (/ |%[^a-f0-9]|%[a-f0-9][^a-f0-9]/i.test(str)) str = encodeURI(str).replace(/%25(\d\d)/g, "%$1");
44
- try {
45
- try {
46
- result = new URL(str, "postgres://base");
47
- } catch (e) {
48
- result = new URL(str.replace("@/", "@___DUMMY___/"), "postgres://base");
49
- dummyHost = true;
50
- }
51
- } catch (err) {
52
- err.input && (err.input = "*****REDACTED*****");
53
- }
54
- for (const entry of result.searchParams.entries()) config[entry[0]] = entry[1];
55
- config.user = config.user || decodeURIComponent(result.username);
56
- config.password = config.password || decodeURIComponent(result.password);
57
- if (result.protocol == "socket:") {
58
- config.host = decodeURI(result.pathname);
59
- config.database = result.searchParams.get("db");
60
- config.client_encoding = result.searchParams.get("encoding");
61
- return config;
62
- }
63
- const hostname = dummyHost ? "" : result.hostname;
64
- if (!config.host) config.host = decodeURIComponent(hostname);
65
- else if (hostname && /^%2f/i.test(hostname)) result.pathname = hostname + result.pathname;
66
- if (!config.port) config.port = result.port;
67
- const pathname = result.pathname.slice(1) || null;
68
- config.database = pathname ? decodeURI(pathname) : null;
69
- if (config.ssl === "true" || config.ssl === "1") config.ssl = true;
70
- if (config.ssl === "0") config.ssl = false;
71
- if (config.sslcert || config.sslkey || config.sslrootcert || config.sslmode) config.ssl = {};
72
- const fs = config.sslcert || config.sslkey || config.sslrootcert ? require("fs") : null;
73
- if (config.sslcert) config.ssl.cert = fs.readFileSync(config.sslcert).toString();
74
- if (config.sslkey) config.ssl.key = fs.readFileSync(config.sslkey).toString();
75
- if (config.sslrootcert) config.ssl.ca = fs.readFileSync(config.sslrootcert).toString();
76
- if (options.useLibpqCompat && config.uselibpqcompat) throw new Error("Both useLibpqCompat and uselibpqcompat are set. Please use only one of them.");
77
- if (config.uselibpqcompat === "true" || options.useLibpqCompat) switch (config.sslmode) {
78
- case "disable":
79
- config.ssl = false;
80
- break;
81
- case "prefer":
82
- config.ssl.rejectUnauthorized = false;
83
- break;
84
- case "require":
85
- if (config.sslrootcert) config.ssl.checkServerIdentity = function() {};
86
- else config.ssl.rejectUnauthorized = false;
87
- break;
88
- case "verify-ca":
89
- if (!config.ssl.ca) throw new Error("SECURITY WARNING: Using sslmode=verify-ca requires specifying a CA with sslrootcert. If a public CA is used, verify-ca allows connections to a server that somebody else may have registered with the CA, making you vulnerable to Man-in-the-Middle attacks. Either specify a custom CA certificate with sslrootcert parameter or use sslmode=verify-full for proper security.");
90
- config.ssl.checkServerIdentity = function() {};
91
- break;
92
- case "verify-full": break;
93
- }
94
- else switch (config.sslmode) {
95
- case "disable":
96
- config.ssl = false;
97
- break;
98
- case "prefer":
99
- case "require":
100
- case "verify-ca":
101
- case "verify-full": break;
102
- case "no-verify":
103
- config.ssl.rejectUnauthorized = false;
104
- break;
105
- }
106
- return config;
107
- }
108
- function toConnectionOptions(sslConfig) {
109
- return Object.entries(sslConfig).reduce((c, [key, value]) => {
110
- if (value !== void 0 && value !== null) c[key] = value;
111
- return c;
112
- }, {});
113
- }
114
- function toClientConfig$1(config) {
115
- return Object.entries(config).reduce((c, [key, value]) => {
116
- if (key === "ssl") {
117
- const sslConfig = value;
118
- if (typeof sslConfig === "boolean") c[key] = sslConfig;
119
- if (typeof sslConfig === "object") c[key] = toConnectionOptions(sslConfig);
120
- } else if (value !== void 0 && value !== null) if (key === "port") {
121
- if (value !== "") {
122
- const v = parseInt(value, 10);
123
- if (isNaN(v)) throw new Error(`Invalid ${key}: ${value}`);
124
- c[key] = v;
125
- }
126
- } else c[key] = value;
127
- return c;
128
- }, {});
129
- }
130
- function parseIntoClientConfig$1(str) {
131
- return toClientConfig$1(parse$1(str));
132
- }
133
- module.exports = parse$1;
134
- parse$1.parse = parse$1;
135
- parse$1.toClientConfig = toClientConfig$1;
136
- parse$1.parseIntoClientConfig = parseIntoClientConfig$1;
137
- }));
138
-
139
- //#endregion
140
- //#region ../../node_modules/.pnpm/pg-connection-string@2.9.1/node_modules/pg-connection-string/esm/index.mjs
141
- var import_pg_connection_string = /* @__PURE__ */ __toESM(require_pg_connection_string(), 1);
142
- var esm_default = import_pg_connection_string.default.parse;
143
- const parse = import_pg_connection_string.default.parse;
144
- const toClientConfig = import_pg_connection_string.default.toClientConfig;
145
- const parseIntoClientConfig = import_pg_connection_string.default.parseIntoClientConfig;
146
-
147
- //#endregion
148
- Object.defineProperty(exports, '__toESM', {
149
- enumerable: true,
150
- get: function () {
151
- return __toESM;
152
- }
153
- });
154
- Object.defineProperty(exports, 'parse', {
155
- enumerable: true,
156
- get: function () {
157
- return parse;
158
- }
159
- });
160
- //# sourceMappingURL=esm-9QNtbaRS.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"esm-9QNtbaRS.js","names":["parse","config","toClientConfig","parseIntoClientConfig","connectionString"],"sources":["../../../node_modules/.pnpm/pg-connection-string@2.9.1/node_modules/pg-connection-string/index.js","../../../node_modules/.pnpm/pg-connection-string@2.9.1/node_modules/pg-connection-string/esm/index.mjs"],"sourcesContent":["'use strict'\n\n//Parse method copied from https://github.com/brianc/node-postgres\n//Copyright (c) 2010-2014 Brian Carlson (brian.m.carlson@gmail.com)\n//MIT License\n\n//parses a connection string\nfunction parse(str, options = {}) {\n //unix socket\n if (str.charAt(0) === '/') {\n const config = str.split(' ')\n return { host: config[0], database: config[1] }\n }\n\n // Check for empty host in URL\n\n const config = {}\n let result\n let dummyHost = false\n if (/ |%[^a-f0-9]|%[a-f0-9][^a-f0-9]/i.test(str)) {\n // Ensure spaces are encoded as %20\n str = encodeURI(str).replace(/%25(\\d\\d)/g, '%$1')\n }\n\n try {\n try {\n result = new URL(str, 'postgres://base')\n } catch (e) {\n // The URL is invalid so try again with a dummy host\n result = new URL(str.replace('@/', '@___DUMMY___/'), 'postgres://base')\n dummyHost = true\n }\n } catch (err) {\n // Remove the input from the error message to avoid leaking sensitive information\n err.input && (err.input = '*****REDACTED*****')\n }\n\n // We'd like to use Object.fromEntries() here but Node.js 10 does not support it\n for (const entry of result.searchParams.entries()) {\n config[entry[0]] = entry[1]\n }\n\n config.user = config.user || decodeURIComponent(result.username)\n config.password = config.password || decodeURIComponent(result.password)\n\n if (result.protocol == 'socket:') {\n config.host = decodeURI(result.pathname)\n config.database = result.searchParams.get('db')\n config.client_encoding = result.searchParams.get('encoding')\n return config\n }\n const hostname = dummyHost ? '' : result.hostname\n if (!config.host) {\n // Only set the host if there is no equivalent query param.\n config.host = decodeURIComponent(hostname)\n } else if (hostname && /^%2f/i.test(hostname)) {\n // Only prepend the hostname to the pathname if it is not a URL encoded Unix socket host.\n result.pathname = hostname + result.pathname\n }\n if (!config.port) {\n // Only set the port if there is no equivalent query param.\n config.port = result.port\n }\n\n const pathname = result.pathname.slice(1) || null\n config.database = pathname ? decodeURI(pathname) : null\n\n if (config.ssl === 'true' || config.ssl === '1') {\n config.ssl = true\n }\n\n if (config.ssl === '0') {\n config.ssl = false\n }\n\n if (config.sslcert || config.sslkey || config.sslrootcert || config.sslmode) {\n config.ssl = {}\n }\n\n // Only try to load fs if we expect to read from the disk\n const fs = config.sslcert || config.sslkey || config.sslrootcert ? require('fs') : null\n\n if (config.sslcert) {\n config.ssl.cert = fs.readFileSync(config.sslcert).toString()\n }\n\n if (config.sslkey) {\n config.ssl.key = fs.readFileSync(config.sslkey).toString()\n }\n\n if (config.sslrootcert) {\n config.ssl.ca = fs.readFileSync(config.sslrootcert).toString()\n }\n\n if (options.useLibpqCompat && config.uselibpqcompat) {\n throw new Error('Both useLibpqCompat and uselibpqcompat are set. Please use only one of them.')\n }\n\n if (config.uselibpqcompat === 'true' || options.useLibpqCompat) {\n switch (config.sslmode) {\n case 'disable': {\n config.ssl = false\n break\n }\n case 'prefer': {\n config.ssl.rejectUnauthorized = false\n break\n }\n case 'require': {\n if (config.sslrootcert) {\n // If a root CA is specified, behavior of `sslmode=require` will be the same as that of `verify-ca`\n config.ssl.checkServerIdentity = function () {}\n } else {\n config.ssl.rejectUnauthorized = false\n }\n break\n }\n case 'verify-ca': {\n if (!config.ssl.ca) {\n throw new Error(\n 'SECURITY WARNING: Using sslmode=verify-ca requires specifying a CA with sslrootcert. If a public CA is used, verify-ca allows connections to a server that somebody else may have registered with the CA, making you vulnerable to Man-in-the-Middle attacks. Either specify a custom CA certificate with sslrootcert parameter or use sslmode=verify-full for proper security.'\n )\n }\n config.ssl.checkServerIdentity = function () {}\n break\n }\n case 'verify-full': {\n break\n }\n }\n } else {\n switch (config.sslmode) {\n case 'disable': {\n config.ssl = false\n break\n }\n case 'prefer':\n case 'require':\n case 'verify-ca':\n case 'verify-full': {\n break\n }\n case 'no-verify': {\n config.ssl.rejectUnauthorized = false\n break\n }\n }\n }\n\n return config\n}\n\n// convert pg-connection-string ssl config to a ClientConfig.ConnectionOptions\nfunction toConnectionOptions(sslConfig) {\n const connectionOptions = Object.entries(sslConfig).reduce((c, [key, value]) => {\n // we explicitly check for undefined and null instead of `if (value)` because some\n // options accept falsy values. Example: `ssl.rejectUnauthorized = false`\n if (value !== undefined && value !== null) {\n c[key] = value\n }\n\n return c\n }, {})\n\n return connectionOptions\n}\n\n// convert pg-connection-string config to a ClientConfig\nfunction toClientConfig(config) {\n const poolConfig = Object.entries(config).reduce((c, [key, value]) => {\n if (key === 'ssl') {\n const sslConfig = value\n\n if (typeof sslConfig === 'boolean') {\n c[key] = sslConfig\n }\n\n if (typeof sslConfig === 'object') {\n c[key] = toConnectionOptions(sslConfig)\n }\n } else if (value !== undefined && value !== null) {\n if (key === 'port') {\n // when port is not specified, it is converted into an empty string\n // we want to avoid NaN or empty string as a values in ClientConfig\n if (value !== '') {\n const v = parseInt(value, 10)\n if (isNaN(v)) {\n throw new Error(`Invalid ${key}: ${value}`)\n }\n\n c[key] = v\n }\n } else {\n c[key] = value\n }\n }\n\n return c\n }, {})\n\n return poolConfig\n}\n\n// parses a connection string into ClientConfig\nfunction parseIntoClientConfig(str) {\n return toClientConfig(parse(str))\n}\n\nmodule.exports = parse\n\nparse.parse = parse\nparse.toClientConfig = toClientConfig\nparse.parseIntoClientConfig = parseIntoClientConfig\n","// ESM wrapper for pg-connection-string\nimport connectionString from '../index.js'\n\n// Re-export the parse function\nexport default connectionString.parse\nexport const parse = connectionString.parse\nexport const toClientConfig = connectionString.toClientConfig\nexport const parseIntoClientConfig = connectionString.parseIntoClientConfig\n"],"x_google_ignoreList":[0,1],"mappings":"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"}
@@ -1,151 +0,0 @@
1
- import { createRequire } from "node:module";
2
-
3
- //#region rolldown:runtime
4
- var __create = Object.create;
5
- var __defProp = Object.defineProperty;
6
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
- var __getOwnPropNames = Object.getOwnPropertyNames;
8
- var __getProtoOf = Object.getPrototypeOf;
9
- var __hasOwnProp = Object.prototype.hasOwnProperty;
10
- var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
11
- var __copyProps = (to, from, except, desc) => {
12
- if (from && typeof from === "object" || typeof from === "function") {
13
- for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
14
- key = keys[i];
15
- if (!__hasOwnProp.call(to, key) && key !== except) {
16
- __defProp(to, key, {
17
- get: ((k) => from[k]).bind(null, key),
18
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
19
- });
20
- }
21
- }
22
- }
23
- return to;
24
- };
25
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
26
- value: mod,
27
- enumerable: true
28
- }) : target, mod));
29
- var __require = /* @__PURE__ */ createRequire(import.meta.url);
30
-
31
- //#endregion
32
- //#region ../../node_modules/.pnpm/pg-connection-string@2.9.1/node_modules/pg-connection-string/index.js
33
- var require_pg_connection_string = /* @__PURE__ */ __commonJSMin(((exports, module) => {
34
- function parse$1(str, options = {}) {
35
- if (str.charAt(0) === "/") {
36
- const config$1 = str.split(" ");
37
- return {
38
- host: config$1[0],
39
- database: config$1[1]
40
- };
41
- }
42
- const config = {};
43
- let result;
44
- let dummyHost = false;
45
- if (/ |%[^a-f0-9]|%[a-f0-9][^a-f0-9]/i.test(str)) str = encodeURI(str).replace(/%25(\d\d)/g, "%$1");
46
- try {
47
- try {
48
- result = new URL(str, "postgres://base");
49
- } catch (e) {
50
- result = new URL(str.replace("@/", "@___DUMMY___/"), "postgres://base");
51
- dummyHost = true;
52
- }
53
- } catch (err) {
54
- err.input && (err.input = "*****REDACTED*****");
55
- }
56
- for (const entry of result.searchParams.entries()) config[entry[0]] = entry[1];
57
- config.user = config.user || decodeURIComponent(result.username);
58
- config.password = config.password || decodeURIComponent(result.password);
59
- if (result.protocol == "socket:") {
60
- config.host = decodeURI(result.pathname);
61
- config.database = result.searchParams.get("db");
62
- config.client_encoding = result.searchParams.get("encoding");
63
- return config;
64
- }
65
- const hostname = dummyHost ? "" : result.hostname;
66
- if (!config.host) config.host = decodeURIComponent(hostname);
67
- else if (hostname && /^%2f/i.test(hostname)) result.pathname = hostname + result.pathname;
68
- if (!config.port) config.port = result.port;
69
- const pathname = result.pathname.slice(1) || null;
70
- config.database = pathname ? decodeURI(pathname) : null;
71
- if (config.ssl === "true" || config.ssl === "1") config.ssl = true;
72
- if (config.ssl === "0") config.ssl = false;
73
- if (config.sslcert || config.sslkey || config.sslrootcert || config.sslmode) config.ssl = {};
74
- const fs = config.sslcert || config.sslkey || config.sslrootcert ? __require("fs") : null;
75
- if (config.sslcert) config.ssl.cert = fs.readFileSync(config.sslcert).toString();
76
- if (config.sslkey) config.ssl.key = fs.readFileSync(config.sslkey).toString();
77
- if (config.sslrootcert) config.ssl.ca = fs.readFileSync(config.sslrootcert).toString();
78
- if (options.useLibpqCompat && config.uselibpqcompat) throw new Error("Both useLibpqCompat and uselibpqcompat are set. Please use only one of them.");
79
- if (config.uselibpqcompat === "true" || options.useLibpqCompat) switch (config.sslmode) {
80
- case "disable":
81
- config.ssl = false;
82
- break;
83
- case "prefer":
84
- config.ssl.rejectUnauthorized = false;
85
- break;
86
- case "require":
87
- if (config.sslrootcert) config.ssl.checkServerIdentity = function() {};
88
- else config.ssl.rejectUnauthorized = false;
89
- break;
90
- case "verify-ca":
91
- if (!config.ssl.ca) throw new Error("SECURITY WARNING: Using sslmode=verify-ca requires specifying a CA with sslrootcert. If a public CA is used, verify-ca allows connections to a server that somebody else may have registered with the CA, making you vulnerable to Man-in-the-Middle attacks. Either specify a custom CA certificate with sslrootcert parameter or use sslmode=verify-full for proper security.");
92
- config.ssl.checkServerIdentity = function() {};
93
- break;
94
- case "verify-full": break;
95
- }
96
- else switch (config.sslmode) {
97
- case "disable":
98
- config.ssl = false;
99
- break;
100
- case "prefer":
101
- case "require":
102
- case "verify-ca":
103
- case "verify-full": break;
104
- case "no-verify":
105
- config.ssl.rejectUnauthorized = false;
106
- break;
107
- }
108
- return config;
109
- }
110
- function toConnectionOptions(sslConfig) {
111
- return Object.entries(sslConfig).reduce((c, [key, value]) => {
112
- if (value !== void 0 && value !== null) c[key] = value;
113
- return c;
114
- }, {});
115
- }
116
- function toClientConfig$1(config) {
117
- return Object.entries(config).reduce((c, [key, value]) => {
118
- if (key === "ssl") {
119
- const sslConfig = value;
120
- if (typeof sslConfig === "boolean") c[key] = sslConfig;
121
- if (typeof sslConfig === "object") c[key] = toConnectionOptions(sslConfig);
122
- } else if (value !== void 0 && value !== null) if (key === "port") {
123
- if (value !== "") {
124
- const v = parseInt(value, 10);
125
- if (isNaN(v)) throw new Error(`Invalid ${key}: ${value}`);
126
- c[key] = v;
127
- }
128
- } else c[key] = value;
129
- return c;
130
- }, {});
131
- }
132
- function parseIntoClientConfig$1(str) {
133
- return toClientConfig$1(parse$1(str));
134
- }
135
- module.exports = parse$1;
136
- parse$1.parse = parse$1;
137
- parse$1.toClientConfig = toClientConfig$1;
138
- parse$1.parseIntoClientConfig = parseIntoClientConfig$1;
139
- }));
140
-
141
- //#endregion
142
- //#region ../../node_modules/.pnpm/pg-connection-string@2.9.1/node_modules/pg-connection-string/esm/index.mjs
143
- var import_pg_connection_string = /* @__PURE__ */ __toESM(require_pg_connection_string(), 1);
144
- var esm_default = import_pg_connection_string.default.parse;
145
- const parse = import_pg_connection_string.default.parse;
146
- const toClientConfig = import_pg_connection_string.default.toClientConfig;
147
- const parseIntoClientConfig = import_pg_connection_string.default.parseIntoClientConfig;
148
-
149
- //#endregion
150
- export { parse as t };
151
- //# sourceMappingURL=esm-v1isYkCK.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"esm-v1isYkCK.mjs","names":["parse","config","toClientConfig","parseIntoClientConfig","connectionString"],"sources":["../../../node_modules/.pnpm/pg-connection-string@2.9.1/node_modules/pg-connection-string/index.js","../../../node_modules/.pnpm/pg-connection-string@2.9.1/node_modules/pg-connection-string/esm/index.mjs"],"sourcesContent":["'use strict'\n\n//Parse method copied from https://github.com/brianc/node-postgres\n//Copyright (c) 2010-2014 Brian Carlson (brian.m.carlson@gmail.com)\n//MIT License\n\n//parses a connection string\nfunction parse(str, options = {}) {\n //unix socket\n if (str.charAt(0) === '/') {\n const config = str.split(' ')\n return { host: config[0], database: config[1] }\n }\n\n // Check for empty host in URL\n\n const config = {}\n let result\n let dummyHost = false\n if (/ |%[^a-f0-9]|%[a-f0-9][^a-f0-9]/i.test(str)) {\n // Ensure spaces are encoded as %20\n str = encodeURI(str).replace(/%25(\\d\\d)/g, '%$1')\n }\n\n try {\n try {\n result = new URL(str, 'postgres://base')\n } catch (e) {\n // The URL is invalid so try again with a dummy host\n result = new URL(str.replace('@/', '@___DUMMY___/'), 'postgres://base')\n dummyHost = true\n }\n } catch (err) {\n // Remove the input from the error message to avoid leaking sensitive information\n err.input && (err.input = '*****REDACTED*****')\n }\n\n // We'd like to use Object.fromEntries() here but Node.js 10 does not support it\n for (const entry of result.searchParams.entries()) {\n config[entry[0]] = entry[1]\n }\n\n config.user = config.user || decodeURIComponent(result.username)\n config.password = config.password || decodeURIComponent(result.password)\n\n if (result.protocol == 'socket:') {\n config.host = decodeURI(result.pathname)\n config.database = result.searchParams.get('db')\n config.client_encoding = result.searchParams.get('encoding')\n return config\n }\n const hostname = dummyHost ? '' : result.hostname\n if (!config.host) {\n // Only set the host if there is no equivalent query param.\n config.host = decodeURIComponent(hostname)\n } else if (hostname && /^%2f/i.test(hostname)) {\n // Only prepend the hostname to the pathname if it is not a URL encoded Unix socket host.\n result.pathname = hostname + result.pathname\n }\n if (!config.port) {\n // Only set the port if there is no equivalent query param.\n config.port = result.port\n }\n\n const pathname = result.pathname.slice(1) || null\n config.database = pathname ? decodeURI(pathname) : null\n\n if (config.ssl === 'true' || config.ssl === '1') {\n config.ssl = true\n }\n\n if (config.ssl === '0') {\n config.ssl = false\n }\n\n if (config.sslcert || config.sslkey || config.sslrootcert || config.sslmode) {\n config.ssl = {}\n }\n\n // Only try to load fs if we expect to read from the disk\n const fs = config.sslcert || config.sslkey || config.sslrootcert ? require('fs') : null\n\n if (config.sslcert) {\n config.ssl.cert = fs.readFileSync(config.sslcert).toString()\n }\n\n if (config.sslkey) {\n config.ssl.key = fs.readFileSync(config.sslkey).toString()\n }\n\n if (config.sslrootcert) {\n config.ssl.ca = fs.readFileSync(config.sslrootcert).toString()\n }\n\n if (options.useLibpqCompat && config.uselibpqcompat) {\n throw new Error('Both useLibpqCompat and uselibpqcompat are set. Please use only one of them.')\n }\n\n if (config.uselibpqcompat === 'true' || options.useLibpqCompat) {\n switch (config.sslmode) {\n case 'disable': {\n config.ssl = false\n break\n }\n case 'prefer': {\n config.ssl.rejectUnauthorized = false\n break\n }\n case 'require': {\n if (config.sslrootcert) {\n // If a root CA is specified, behavior of `sslmode=require` will be the same as that of `verify-ca`\n config.ssl.checkServerIdentity = function () {}\n } else {\n config.ssl.rejectUnauthorized = false\n }\n break\n }\n case 'verify-ca': {\n if (!config.ssl.ca) {\n throw new Error(\n 'SECURITY WARNING: Using sslmode=verify-ca requires specifying a CA with sslrootcert. If a public CA is used, verify-ca allows connections to a server that somebody else may have registered with the CA, making you vulnerable to Man-in-the-Middle attacks. Either specify a custom CA certificate with sslrootcert parameter or use sslmode=verify-full for proper security.'\n )\n }\n config.ssl.checkServerIdentity = function () {}\n break\n }\n case 'verify-full': {\n break\n }\n }\n } else {\n switch (config.sslmode) {\n case 'disable': {\n config.ssl = false\n break\n }\n case 'prefer':\n case 'require':\n case 'verify-ca':\n case 'verify-full': {\n break\n }\n case 'no-verify': {\n config.ssl.rejectUnauthorized = false\n break\n }\n }\n }\n\n return config\n}\n\n// convert pg-connection-string ssl config to a ClientConfig.ConnectionOptions\nfunction toConnectionOptions(sslConfig) {\n const connectionOptions = Object.entries(sslConfig).reduce((c, [key, value]) => {\n // we explicitly check for undefined and null instead of `if (value)` because some\n // options accept falsy values. Example: `ssl.rejectUnauthorized = false`\n if (value !== undefined && value !== null) {\n c[key] = value\n }\n\n return c\n }, {})\n\n return connectionOptions\n}\n\n// convert pg-connection-string config to a ClientConfig\nfunction toClientConfig(config) {\n const poolConfig = Object.entries(config).reduce((c, [key, value]) => {\n if (key === 'ssl') {\n const sslConfig = value\n\n if (typeof sslConfig === 'boolean') {\n c[key] = sslConfig\n }\n\n if (typeof sslConfig === 'object') {\n c[key] = toConnectionOptions(sslConfig)\n }\n } else if (value !== undefined && value !== null) {\n if (key === 'port') {\n // when port is not specified, it is converted into an empty string\n // we want to avoid NaN or empty string as a values in ClientConfig\n if (value !== '') {\n const v = parseInt(value, 10)\n if (isNaN(v)) {\n throw new Error(`Invalid ${key}: ${value}`)\n }\n\n c[key] = v\n }\n } else {\n c[key] = value\n }\n }\n\n return c\n }, {})\n\n return poolConfig\n}\n\n// parses a connection string into ClientConfig\nfunction parseIntoClientConfig(str) {\n return toClientConfig(parse(str))\n}\n\nmodule.exports = parse\n\nparse.parse = parse\nparse.toClientConfig = toClientConfig\nparse.parseIntoClientConfig = parseIntoClientConfig\n","// ESM wrapper for pg-connection-string\nimport connectionString from '../index.js'\n\n// Re-export the parse function\nexport default connectionString.parse\nexport const parse = connectionString.parse\nexport const toClientConfig = connectionString.toClientConfig\nexport const parseIntoClientConfig = connectionString.parseIntoClientConfig\n"],"x_google_ignoreList":[0,1],"mappings":"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"}