@rfjs/pg-toolkit 0.0.6 → 0.0.8-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/package.json +4 -5
- package/dist/admin/index.d.mts +0 -33
- package/dist/admin/index.d.mts.map +0 -1
- package/dist/admin/index.d.ts +0 -33
- package/dist/admin/index.d.ts.map +0 -1
- package/dist/admin/index.js +0 -87
- package/dist/admin/index.js.map +0 -1
- package/dist/admin/index.mjs +0 -83
- package/dist/admin/index.mjs.map +0 -1
- package/dist/index.d.mts +0 -19
- package/dist/index.d.mts.map +0 -1
- package/dist/index.d.ts +0 -19
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -51
- package/dist/index.js.map +0 -1
- package/dist/index.mjs +0 -50
- package/dist/index.mjs.map +0 -1
- package/dist/package.json +0 -28
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rfjs/pg-toolkit",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8-alpha.0",
|
|
4
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",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
}
|
|
39
39
|
},
|
|
40
40
|
"keywords": [],
|
|
41
|
-
"author": "
|
|
41
|
+
"author": "Roy Chuang",
|
|
42
42
|
"license": "ISC",
|
|
43
43
|
"engines": {
|
|
44
44
|
"node": ">=18",
|
|
@@ -59,7 +59,6 @@
|
|
|
59
59
|
"eslint": "^9.20.1",
|
|
60
60
|
"eslint-config-prettier": "^10.0.1",
|
|
61
61
|
"husky": "^9.1.7",
|
|
62
|
-
"inquirer": "9",
|
|
63
62
|
"lint-staged": "^15.4.3",
|
|
64
63
|
"prettier": "^3.5.1",
|
|
65
64
|
"rimraf": "^6.0.1",
|
|
@@ -77,10 +76,10 @@
|
|
|
77
76
|
"tslib": "^2.8.1"
|
|
78
77
|
},
|
|
79
78
|
"scripts": {
|
|
80
|
-
"clean": "pnpm
|
|
79
|
+
"clean": "pnpm --filter . --parallel clean:dist clean:types",
|
|
81
80
|
"clean:types": "pnpm exec rimraf ./types",
|
|
82
81
|
"clean:dist": "pnpm exec rimraf ./dist",
|
|
83
|
-
"dev": "pnpm
|
|
82
|
+
"dev": "pnpm --filter . --parallel dev:tsdown typecheck:watch",
|
|
84
83
|
"dev:tsdown": "npm run clean && tsdown --config-loader unrun --watch",
|
|
85
84
|
"build": "npm run build:tsdown",
|
|
86
85
|
"build:tsdown": "npm run clean && tsdown --config-loader unrun",
|
package/dist/admin/index.d.mts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { Client, Pool } from "pg";
|
|
2
|
-
|
|
3
|
-
//#region src/admin/ensure-db.d.ts
|
|
4
|
-
declare function checkAndCreateDB(connectionString: string): Promise<void>;
|
|
5
|
-
//#endregion
|
|
6
|
-
//#region src/admin/ensure-schema.d.ts
|
|
7
|
-
declare function checkAndCreateSchema(connectionString: string, schemas: string[]): Promise<void>;
|
|
8
|
-
//#endregion
|
|
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 };
|
|
33
|
-
//# sourceMappingURL=index.d.mts.map
|
|
@@ -1 +0,0 @@
|
|
|
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"}
|
package/dist/admin/index.d.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { Client, Pool } from "pg";
|
|
2
|
-
|
|
3
|
-
//#region src/admin/ensure-db.d.ts
|
|
4
|
-
declare function checkAndCreateDB(connectionString: string): Promise<void>;
|
|
5
|
-
//#endregion
|
|
6
|
-
//#region src/admin/ensure-schema.d.ts
|
|
7
|
-
declare function checkAndCreateSchema(connectionString: string, schemas: string[]): Promise<void>;
|
|
8
|
-
//#endregion
|
|
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 };
|
|
33
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
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"}
|
package/dist/admin/index.js
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
let pg_connection_string = require("pg-connection-string");
|
|
2
|
-
let pg = require("pg");
|
|
3
|
-
|
|
4
|
-
//#region src/admin/ensure-db.ts
|
|
5
|
-
async function checkAndCreateDB(connectionString) {
|
|
6
|
-
const { user, password, host, port, database } = (0, pg_connection_string.parse)(connectionString);
|
|
7
|
-
const adminConnectionString = `postgres://${user}:${password}@${host}:${port}/postgres`;
|
|
8
|
-
const targetDb = database ?? "orm";
|
|
9
|
-
const client = new pg.Client({ connectionString: adminConnectionString });
|
|
10
|
-
let isConnected = false;
|
|
11
|
-
try {
|
|
12
|
-
await client.connect();
|
|
13
|
-
isConnected = true;
|
|
14
|
-
if ((await client.query(`SELECT 1 FROM pg_database WHERE datname = $1`, [targetDb])).rowCount === 0) {
|
|
15
|
-
console.log(`Database "${targetDb}" does not exist. Creating...`);
|
|
16
|
-
await client.query(`CREATE DATABASE "${targetDb}"`);
|
|
17
|
-
console.log(`Database "${targetDb}" created successfully.`);
|
|
18
|
-
}
|
|
19
|
-
} catch (error) {
|
|
20
|
-
console.error(`Failed to ensure database exists: ${error}`);
|
|
21
|
-
throw error;
|
|
22
|
-
} finally {
|
|
23
|
-
if (isConnected) await client.end();
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
//#endregion
|
|
28
|
-
//#region src/admin/ensure-schema.ts
|
|
29
|
-
async function checkAndCreateSchema(connectionString, schemas) {
|
|
30
|
-
const client = new pg.Client(connectionString);
|
|
31
|
-
let isConnected = false;
|
|
32
|
-
try {
|
|
33
|
-
await client.connect();
|
|
34
|
-
isConnected = true;
|
|
35
|
-
for (const schema of schemas) await client.query(`CREATE SCHEMA IF NOT EXISTS "${schema}"`);
|
|
36
|
-
} catch (error) {
|
|
37
|
-
console.error(`Failed to ensure schema exists: ${error}`);
|
|
38
|
-
throw error;
|
|
39
|
-
} finally {
|
|
40
|
-
if (isConnected) await client.end();
|
|
41
|
-
}
|
|
42
|
-
}
|
|
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
|
-
|
|
81
|
-
//#endregion
|
|
82
|
-
exports.checkAndCreateDB = checkAndCreateDB;
|
|
83
|
-
exports.checkAndCreateSchema = checkAndCreateSchema;
|
|
84
|
-
exports.checkSeedExecuted = checkSeedExecuted;
|
|
85
|
-
exports.ensureSeedHistoryTable = ensureSeedHistoryTable;
|
|
86
|
-
exports.recordSeedExecution = recordSeedExecution;
|
|
87
|
-
//# sourceMappingURL=index.js.map
|
package/dist/admin/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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"}
|
package/dist/admin/index.mjs
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { parse } from "pg-connection-string";
|
|
2
|
-
import { Client } from "pg";
|
|
3
|
-
|
|
4
|
-
//#region src/admin/ensure-db.ts
|
|
5
|
-
async function checkAndCreateDB(connectionString) {
|
|
6
|
-
const { user, password, host, port, database } = parse(connectionString);
|
|
7
|
-
const adminConnectionString = `postgres://${user}:${password}@${host}:${port}/postgres`;
|
|
8
|
-
const targetDb = database ?? "orm";
|
|
9
|
-
const client = new Client({ connectionString: adminConnectionString });
|
|
10
|
-
let isConnected = false;
|
|
11
|
-
try {
|
|
12
|
-
await client.connect();
|
|
13
|
-
isConnected = true;
|
|
14
|
-
if ((await client.query(`SELECT 1 FROM pg_database WHERE datname = $1`, [targetDb])).rowCount === 0) {
|
|
15
|
-
console.log(`Database "${targetDb}" does not exist. Creating...`);
|
|
16
|
-
await client.query(`CREATE DATABASE "${targetDb}"`);
|
|
17
|
-
console.log(`Database "${targetDb}" created successfully.`);
|
|
18
|
-
}
|
|
19
|
-
} catch (error) {
|
|
20
|
-
console.error(`Failed to ensure database exists: ${error}`);
|
|
21
|
-
throw error;
|
|
22
|
-
} finally {
|
|
23
|
-
if (isConnected) await client.end();
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
//#endregion
|
|
28
|
-
//#region src/admin/ensure-schema.ts
|
|
29
|
-
async function checkAndCreateSchema(connectionString, schemas) {
|
|
30
|
-
const client = new Client(connectionString);
|
|
31
|
-
let isConnected = false;
|
|
32
|
-
try {
|
|
33
|
-
await client.connect();
|
|
34
|
-
isConnected = true;
|
|
35
|
-
for (const schema of schemas) await client.query(`CREATE SCHEMA IF NOT EXISTS "${schema}"`);
|
|
36
|
-
} catch (error) {
|
|
37
|
-
console.error(`Failed to ensure schema exists: ${error}`);
|
|
38
|
-
throw error;
|
|
39
|
-
} finally {
|
|
40
|
-
if (isConnected) await client.end();
|
|
41
|
-
}
|
|
42
|
-
}
|
|
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
|
-
|
|
81
|
-
//#endregion
|
|
82
|
-
export { checkAndCreateDB, checkAndCreateSchema, checkSeedExecuted, ensureSeedHistoryTable, recordSeedExecution };
|
|
83
|
-
//# sourceMappingURL=index.mjs.map
|
package/dist/admin/index.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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.d.mts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
//#region src/pure/options.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* 從 options 解析 search_path
|
|
4
|
-
* 支援:
|
|
5
|
-
* -c search_path=a,b
|
|
6
|
-
* -csearch_path=a,b (防呆,但會 normalize)
|
|
7
|
-
*/
|
|
8
|
-
declare function getOptionsSchemas(options?: string): string[];
|
|
9
|
-
//#endregion
|
|
10
|
-
//#region src/pure/connection-string.d.ts
|
|
11
|
-
declare function getConnectionStringInfo(connectionString: string, targetSchema?: string): {
|
|
12
|
-
finalConnectionString: string;
|
|
13
|
-
finalSchema: string;
|
|
14
|
-
optionsSchemas: string[];
|
|
15
|
-
hasSearchPath: boolean;
|
|
16
|
-
};
|
|
17
|
-
//#endregion
|
|
18
|
-
export { getConnectionStringInfo, getOptionsSchemas };
|
|
19
|
-
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/pure/options.ts","../src/pure/connection-string.ts"],"sourcesContent":[],"mappings":";;AAMA;;;;ACQA;iBDRgB,iBAAA;;;iBCQA,uBAAA;EDRhB,qBAAgB,EAAA,MAAA;;;;ACQhB,CAAA"}
|
package/dist/index.d.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
//#region src/pure/options.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* 從 options 解析 search_path
|
|
4
|
-
* 支援:
|
|
5
|
-
* -c search_path=a,b
|
|
6
|
-
* -csearch_path=a,b (防呆,但會 normalize)
|
|
7
|
-
*/
|
|
8
|
-
declare function getOptionsSchemas(options?: string): string[];
|
|
9
|
-
//#endregion
|
|
10
|
-
//#region src/pure/connection-string.d.ts
|
|
11
|
-
declare function getConnectionStringInfo(connectionString: string, targetSchema?: string): {
|
|
12
|
-
finalConnectionString: string;
|
|
13
|
-
finalSchema: string;
|
|
14
|
-
optionsSchemas: string[];
|
|
15
|
-
hasSearchPath: boolean;
|
|
16
|
-
};
|
|
17
|
-
//#endregion
|
|
18
|
-
export { getConnectionStringInfo, getOptionsSchemas };
|
|
19
|
-
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/pure/options.ts","../src/pure/connection-string.ts"],"sourcesContent":[],"mappings":";;AAMA;;;;ACQA;iBDRgB,iBAAA;;;iBCQA,uBAAA;EDRhB,qBAAgB,EAAA,MAAA;;;;ACQhB,CAAA"}
|
package/dist/index.js
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
let pg_connection_string = require("pg-connection-string");
|
|
2
|
-
|
|
3
|
-
//#region src/pure/options.ts
|
|
4
|
-
/**
|
|
5
|
-
* 從 options 解析 search_path
|
|
6
|
-
* 支援:
|
|
7
|
-
* -c search_path=a,b
|
|
8
|
-
* -csearch_path=a,b (防呆,但會 normalize)
|
|
9
|
-
*/
|
|
10
|
-
function getOptionsSchemas(options) {
|
|
11
|
-
if (!options) return [];
|
|
12
|
-
const m = options.replace(/-csearch_path=/g, "-c search_path=").match(/(?:^|\s)search_path=([^\s]+)/);
|
|
13
|
-
if (!m) return [];
|
|
14
|
-
return m[1].split(",").map((s) => s.trim()).filter(Boolean);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
//#endregion
|
|
18
|
-
//#region src/pure/connection-string.ts
|
|
19
|
-
function buildSearchPathOption(schema) {
|
|
20
|
-
return `-c search_path=${schema}`;
|
|
21
|
-
}
|
|
22
|
-
function mergeOptions(existing, schema) {
|
|
23
|
-
if (getOptionsSchemas(existing).length > 0) return existing ?? "";
|
|
24
|
-
const add = buildSearchPathOption(schema);
|
|
25
|
-
return existing && existing.trim() ? `${existing.trim()} ${add}` : add;
|
|
26
|
-
}
|
|
27
|
-
function getConnectionStringInfo(connectionString, targetSchema) {
|
|
28
|
-
const config = (0, pg_connection_string.parse)(connectionString);
|
|
29
|
-
const url = new URL(connectionString);
|
|
30
|
-
const options = url.searchParams.get("options") ?? config.options ?? void 0;
|
|
31
|
-
const optionsSchemas = getOptionsSchemas(options);
|
|
32
|
-
const hasSearchPath = optionsSchemas.length > 0;
|
|
33
|
-
const schemaParam = url.searchParams.get("schema") ?? void 0;
|
|
34
|
-
const finalSchema = optionsSchemas[0] ?? schemaParam ?? targetSchema ?? "public";
|
|
35
|
-
if (!hasSearchPath && finalSchema !== "public") {
|
|
36
|
-
const merged = mergeOptions(options, finalSchema);
|
|
37
|
-
url.searchParams.set("options", merged);
|
|
38
|
-
}
|
|
39
|
-
if (!schemaParam && optionsSchemas.length > 0) url.searchParams.set("schema", optionsSchemas[0]);
|
|
40
|
-
return {
|
|
41
|
-
optionsSchemas,
|
|
42
|
-
finalSchema,
|
|
43
|
-
finalConnectionString: url.toString(),
|
|
44
|
-
hasSearchPath
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
//#endregion
|
|
49
|
-
exports.getConnectionStringInfo = getConnectionStringInfo;
|
|
50
|
-
exports.getOptionsSchemas = getOptionsSchemas;
|
|
51
|
-
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { parse } from "pg-connection-string";
|
|
2
|
-
|
|
3
|
-
//#region src/pure/options.ts
|
|
4
|
-
/**
|
|
5
|
-
* 從 options 解析 search_path
|
|
6
|
-
* 支援:
|
|
7
|
-
* -c search_path=a,b
|
|
8
|
-
* -csearch_path=a,b (防呆,但會 normalize)
|
|
9
|
-
*/
|
|
10
|
-
function getOptionsSchemas(options) {
|
|
11
|
-
if (!options) return [];
|
|
12
|
-
const m = options.replace(/-csearch_path=/g, "-c search_path=").match(/(?:^|\s)search_path=([^\s]+)/);
|
|
13
|
-
if (!m) return [];
|
|
14
|
-
return m[1].split(",").map((s) => s.trim()).filter(Boolean);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
//#endregion
|
|
18
|
-
//#region src/pure/connection-string.ts
|
|
19
|
-
function buildSearchPathOption(schema) {
|
|
20
|
-
return `-c search_path=${schema}`;
|
|
21
|
-
}
|
|
22
|
-
function mergeOptions(existing, schema) {
|
|
23
|
-
if (getOptionsSchemas(existing).length > 0) return existing ?? "";
|
|
24
|
-
const add = buildSearchPathOption(schema);
|
|
25
|
-
return existing && existing.trim() ? `${existing.trim()} ${add}` : add;
|
|
26
|
-
}
|
|
27
|
-
function getConnectionStringInfo(connectionString, targetSchema) {
|
|
28
|
-
const config = parse(connectionString);
|
|
29
|
-
const url = new URL(connectionString);
|
|
30
|
-
const options = url.searchParams.get("options") ?? config.options ?? void 0;
|
|
31
|
-
const optionsSchemas = getOptionsSchemas(options);
|
|
32
|
-
const hasSearchPath = optionsSchemas.length > 0;
|
|
33
|
-
const schemaParam = url.searchParams.get("schema") ?? void 0;
|
|
34
|
-
const finalSchema = optionsSchemas[0] ?? schemaParam ?? targetSchema ?? "public";
|
|
35
|
-
if (!hasSearchPath && finalSchema !== "public") {
|
|
36
|
-
const merged = mergeOptions(options, finalSchema);
|
|
37
|
-
url.searchParams.set("options", merged);
|
|
38
|
-
}
|
|
39
|
-
if (!schemaParam && optionsSchemas.length > 0) url.searchParams.set("schema", optionsSchemas[0]);
|
|
40
|
-
return {
|
|
41
|
-
optionsSchemas,
|
|
42
|
-
finalSchema,
|
|
43
|
-
finalConnectionString: url.toString(),
|
|
44
|
-
hasSearchPath
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
//#endregion
|
|
49
|
-
export { getConnectionStringInfo, getOptionsSchemas };
|
|
50
|
-
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","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,SAAS,MAAM,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/package.json
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@rfjs/pg-toolkit",
|
|
3
|
-
"version": "0.0.6",
|
|
4
|
-
"description": "Shared PostgreSQL utilities and management scripts for Drizzle, Prisma, Kysely, and TypeORM",
|
|
5
|
-
"files": [
|
|
6
|
-
"dist",
|
|
7
|
-
"README.md",
|
|
8
|
-
"LICENSE"
|
|
9
|
-
],
|
|
10
|
-
"publishConfig": {
|
|
11
|
-
"access": "public"
|
|
12
|
-
},
|
|
13
|
-
"keywords": [],
|
|
14
|
-
"author": "royfuwei",
|
|
15
|
-
"license": "ISC",
|
|
16
|
-
"engines": {
|
|
17
|
-
"node": ">=18",
|
|
18
|
-
"pnpm": ">=10.24.0 <11.0.0"
|
|
19
|
-
},
|
|
20
|
-
"dependencies": {
|
|
21
|
-
"pg": "^8.16.3",
|
|
22
|
-
"pg-connection-string": "^2.9.1",
|
|
23
|
-
"tslib": "^2.8.1"
|
|
24
|
-
},
|
|
25
|
-
"main": "index.js",
|
|
26
|
-
"module": "index.mjs",
|
|
27
|
-
"types": "index.d.ts"
|
|
28
|
-
}
|