postgresdk 0.1.1-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 +15 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +5833 -0
- package/dist/cli.js.map +1 -0
- package/dist/emit-client.d.ts +3 -0
- package/dist/emit-client.d.ts.map +1 -0
- package/dist/emit-client.js +114 -0
- package/dist/emit-client.js.map +1 -0
- package/dist/emit-include-builder.d.ts +2 -0
- package/dist/emit-include-builder.d.ts.map +1 -0
- package/dist/emit-include-builder.js +30 -0
- package/dist/emit-include-builder.js.map +1 -0
- package/dist/emit-include-loader.d.ts +9 -0
- package/dist/emit-include-loader.d.ts.map +1 -0
- package/dist/emit-include-loader.js +299 -0
- package/dist/emit-include-loader.js.map +1 -0
- package/dist/emit-include-spec.d.ts +2 -0
- package/dist/emit-include-spec.d.ts.map +1 -0
- package/dist/emit-include-spec.js +26 -0
- package/dist/emit-include-spec.js.map +1 -0
- package/dist/emit-logger.d.ts +1 -0
- package/dist/emit-logger.d.ts.map +1 -0
- package/dist/emit-logger.js +35 -0
- package/dist/emit-logger.js.map +1 -0
- package/dist/emit-routes.d.ts +20 -0
- package/dist/emit-routes.d.ts.map +1 -0
- package/dist/emit-routes.js +208 -0
- package/dist/emit-routes.js.map +1 -0
- package/dist/emit-types.d.ts +5 -0
- package/dist/emit-types.d.ts.map +1 -0
- package/dist/emit-types.js +51 -0
- package/dist/emit-types.js.map +1 -0
- package/dist/emit-zod.d.ts +5 -0
- package/dist/emit-zod.d.ts.map +1 -0
- package/dist/emit-zod.js +43 -0
- package/dist/emit-zod.js.map +1 -0
- package/dist/gen.config.d.ts +10 -0
- package/dist/gen.config.js +10 -0
- package/dist/gen.config.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5793 -0
- package/dist/index.js.map +1 -0
- package/dist/introspect.d.ts +26 -0
- package/dist/introspect.d.ts.map +1 -0
- package/dist/introspect.js +132 -0
- package/dist/introspect.js.map +1 -0
- package/dist/rel-classify.d.ts +10 -0
- package/dist/rel-classify.d.ts.map +1 -0
- package/dist/rel-classify.js +52 -0
- package/dist/rel-classify.js.map +1 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.js +39 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/emit-client.d.ts +3 -0
- package/dist/src/emit-client.js +114 -0
- package/dist/src/emit-client.js.map +1 -0
- package/dist/src/emit-include-builder.d.ts +2 -0
- package/dist/src/emit-include-builder.js +30 -0
- package/dist/src/emit-include-builder.js.map +1 -0
- package/dist/src/emit-include-loader.d.ts +9 -0
- package/dist/src/emit-include-loader.js +299 -0
- package/dist/src/emit-include-loader.js.map +1 -0
- package/dist/src/emit-include-spec.d.ts +2 -0
- package/dist/src/emit-include-spec.js +26 -0
- package/dist/src/emit-include-spec.js.map +1 -0
- package/dist/src/emit-logger.d.ts +1 -0
- package/dist/src/emit-logger.js +35 -0
- package/dist/src/emit-logger.js.map +1 -0
- package/dist/src/emit-routes.d.ts +20 -0
- package/dist/src/emit-routes.js +208 -0
- package/dist/src/emit-routes.js.map +1 -0
- package/dist/src/emit-types.d.ts +5 -0
- package/dist/src/emit-types.js +51 -0
- package/dist/src/emit-types.js.map +1 -0
- package/dist/src/emit-zod.d.ts +5 -0
- package/dist/src/emit-zod.js +43 -0
- package/dist/src/emit-zod.js.map +1 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +83 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/introspect.d.ts +26 -0
- package/dist/src/introspect.js +132 -0
- package/dist/src/introspect.js.map +1 -0
- package/dist/src/rel-classify.d.ts +10 -0
- package/dist/src/rel-classify.js +52 -0
- package/dist/src/rel-classify.js.map +1 -0
- package/dist/src/utils.d.ts +6 -0
- package/dist/src/utils.js +17 -0
- package/dist/src/utils.js.map +1 -0
- package/dist/utils.d.ts +6 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +17 -0
- package/dist/utils.js.map +1 -0
- package/package.json +49 -0
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAEjD,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,UAAkB;IAC/C,cAAc;IACd,MAAM,SAAS,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC;IACjD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;IACvC,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC;IAErC,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,gBAAgB,EAAE,GAAG,CAAC,MAAM,IAAI,QAAQ,CAAC,CAAC;IAE7E,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAEhC,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,IAAI,oBAAoB,CAAC;IACxD,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,IAAI,oBAAoB,CAAC;IACxD,MAAM,YAAY,GAAG,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC;IAEnE,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IAC1C,MAAM,UAAU,CAAC;QACf,SAAS;QACT,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC;QACxB,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC;QACtB,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC;QACzB,SAAS;QACT,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC;KACzB,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,EAAE,CAAC;IAEjB,wBAAwB;IACxB,MAAM,WAAW,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IAC3C,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;IAC/E,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;IAE/E,2BAA2B;IAC3B,KAAK,CAAC,IAAI,CAAC;QACT,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,oBAAoB,CAAC;QAC3C,OAAO,EAAE,kBAAkB,CAAC,KAAK,EAAE,GAAG,CAAC,iBAAiB,IAAI,CAAC,CAAC;KAC/D,CAAC,CAAC;IAEH,0BAA0B;IAC1B,KAAK,CAAC,IAAI,CAAC;QACT,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,mBAAmB,CAAC;QAC1C,OAAO,EAAE,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,CAAC,iBAAiB,IAAI,CAAC,CAAC;KACrE,CAAC,CAAC;IAEH,kBAAkB;IAClB,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC;IAE1E,oBAAoB;IACpB,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;QAChD,0BAA0B;QAC1B,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC,CAAC;QACrF,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC,IAAI,KAAK,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;QACtF,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC,IAAI,KAAK,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;QAEtF,MAAM;QACN,KAAK,CAAC,IAAI,CAAC;YACT,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC,IAAI,KAAK,CAAC;YAChD,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC;SAC3E,CAAC,CAAC;QAEH,SAAS;QACT,KAAK,CAAC,IAAI,CAAC;YACT,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC,IAAI,KAAK,CAAC;YACnD,OAAO,EAAE,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE;gBAChC,gBAAgB,EAAE,GAAG,CAAC,gBAAgB,IAAI,IAAI;gBAC9C,iBAAiB,EAAE,GAAG,CAAC,iBAAiB,IAAI,CAAC;aAC9C,CAAC;SACH,CAAC,CAAC;QAEH,SAAS;QACT,KAAK,CAAC,IAAI,CAAC;YACT,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,GAAG,KAAK,CAAC,IAAI,KAAK,CAAC;YACzC,OAAO,EAAE,UAAU,CAAC,KAAK,CAAC;SAC3B,CAAC,CAAC;IACL,CAAC;IAED,qBAAqB;IACrB,KAAK,CAAC,IAAI,CAAC;QACT,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC;QACjC,OAAO,EAAE,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;KACtD,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IACpC,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC;IAExB,OAAO,CAAC,GAAG,CAAC,eAAe,KAAK,CAAC,MAAM,QAAQ,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,aAAa,SAAS,EAAE,CAAC,CAAC;IACtC,OAAO,CAAC,GAAG,CAAC,aAAa,SAAS,EAAE,CAAC,CAAC;AACxC,CAAC"}
|
@@ -0,0 +1,26 @@
|
|
1
|
+
export type Column = {
|
2
|
+
name: string;
|
3
|
+
pgType: string;
|
4
|
+
nullable: boolean;
|
5
|
+
hasDefault: boolean;
|
6
|
+
};
|
7
|
+
export type ForeignKey = {
|
8
|
+
from: string[];
|
9
|
+
toTable: string;
|
10
|
+
to: string[];
|
11
|
+
onDelete: "cascade" | "restrict" | "set null" | "no action";
|
12
|
+
onUpdate: "cascade" | "restrict" | "set null" | "no action";
|
13
|
+
};
|
14
|
+
export type Table = {
|
15
|
+
name: string;
|
16
|
+
columns: Column[];
|
17
|
+
pk: string[];
|
18
|
+
uniques: string[][];
|
19
|
+
fks: ForeignKey[];
|
20
|
+
};
|
21
|
+
export type Model = {
|
22
|
+
schema: string;
|
23
|
+
tables: Record<string, Table>;
|
24
|
+
enums: Record<string, string[]>;
|
25
|
+
};
|
26
|
+
export declare function introspect(connectionString: string, schema: string): Promise<Model>;
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"introspect.d.ts","sourceRoot":"","sources":["../src/introspect.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,MAAM,GAAG;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,EAAE,CAAC;IACb,QAAQ,EAAE,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,WAAW,CAAC;IAC5D,QAAQ,EAAE,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,WAAW,CAAC;CAC7D,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,EAAE,EAAE,MAAM,EAAE,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC;IACpB,GAAG,EAAE,UAAU,EAAE,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CACjC,CAAC;AAoBF,wBAAsB,UAAU,CAAC,gBAAgB,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAqJzF"}
|
@@ -0,0 +1,132 @@
|
|
1
|
+
import { Client } from "pg";
|
2
|
+
function ensureTable(tables, name) {
|
3
|
+
if (!tables[name])
|
4
|
+
tables[name] = { name, columns: [], pk: [], uniques: [], fks: [] };
|
5
|
+
return tables[name];
|
6
|
+
}
|
7
|
+
function decodeAction(ch) {
|
8
|
+
switch (ch) {
|
9
|
+
case "c":
|
10
|
+
return "cascade";
|
11
|
+
case "r":
|
12
|
+
return "restrict";
|
13
|
+
case "n":
|
14
|
+
return "set null";
|
15
|
+
default:
|
16
|
+
return "no action";
|
17
|
+
}
|
18
|
+
}
|
19
|
+
export async function introspect(connectionString, schema) {
|
20
|
+
const pg = new Client({ connectionString });
|
21
|
+
await pg.connect();
|
22
|
+
const tables = {};
|
23
|
+
const enums = {};
|
24
|
+
try {
|
25
|
+
const tablesRows = await pg.query(`
|
26
|
+
SELECT c.oid, c.relname AS table
|
27
|
+
FROM pg_class c
|
28
|
+
JOIN pg_namespace n ON n.oid = c.relnamespace
|
29
|
+
WHERE c.relkind = 'r' AND n.nspname = $1
|
30
|
+
ORDER BY c.relname
|
31
|
+
`, [schema]);
|
32
|
+
for (const r of tablesRows.rows)
|
33
|
+
ensureTable(tables, r.table);
|
34
|
+
const colsRows = await pg.query(`
|
35
|
+
SELECT table_name, column_name, is_nullable, udt_name, data_type, column_default
|
36
|
+
FROM information_schema.columns
|
37
|
+
WHERE table_schema = $1
|
38
|
+
ORDER BY table_name, ordinal_position
|
39
|
+
`, [schema]);
|
40
|
+
for (const r of colsRows.rows) {
|
41
|
+
const t = ensureTable(tables, r.table_name);
|
42
|
+
t.columns.push({
|
43
|
+
name: r.column_name,
|
44
|
+
pgType: (r.udt_name ?? r.data_type).toLowerCase(),
|
45
|
+
nullable: r.is_nullable === "YES",
|
46
|
+
hasDefault: r.column_default != null,
|
47
|
+
});
|
48
|
+
}
|
49
|
+
const pkRows = await pg.query(`
|
50
|
+
SELECT
|
51
|
+
tc.table_name,
|
52
|
+
COALESCE(json_agg(kcu.column_name ORDER BY kcu.ordinal_position), '[]'::json) AS cols
|
53
|
+
FROM information_schema.table_constraints tc
|
54
|
+
JOIN information_schema.key_column_usage kcu
|
55
|
+
ON tc.constraint_name = kcu.constraint_name
|
56
|
+
AND tc.table_schema = kcu.table_schema
|
57
|
+
WHERE tc.constraint_type = 'PRIMARY KEY'
|
58
|
+
AND tc.table_schema = $1
|
59
|
+
GROUP BY tc.table_name
|
60
|
+
`, [schema]);
|
61
|
+
for (const r of pkRows.rows) {
|
62
|
+
const t = ensureTable(tables, r.table_name);
|
63
|
+
t.pk = (r.cols ?? []).slice();
|
64
|
+
}
|
65
|
+
const uniqRows = await pg.query(`
|
66
|
+
SELECT
|
67
|
+
tc.table_name,
|
68
|
+
COALESCE(json_agg(kcu.column_name ORDER BY kcu.ordinal_position), '[]'::json) AS cols
|
69
|
+
FROM information_schema.table_constraints tc
|
70
|
+
JOIN information_schema.key_column_usage kcu
|
71
|
+
ON tc.constraint_name = kcu.constraint_name
|
72
|
+
AND tc.table_schema = kcu.table_schema
|
73
|
+
WHERE tc.constraint_type = 'UNIQUE'
|
74
|
+
AND tc.table_schema = $1
|
75
|
+
GROUP BY tc.table_name, tc.constraint_name
|
76
|
+
`, [schema]);
|
77
|
+
for (const r of uniqRows.rows) {
|
78
|
+
const t = ensureTable(tables, r.table_name);
|
79
|
+
if (r.cols && r.cols.length)
|
80
|
+
t.uniques.push(r.cols);
|
81
|
+
}
|
82
|
+
const fkRows = await pg.query(`
|
83
|
+
SELECT
|
84
|
+
con.oid AS con_oid,
|
85
|
+
src.relname AS src_table,
|
86
|
+
tgt.relname AS tgt_table,
|
87
|
+
con.confdeltype,
|
88
|
+
con.confupdtype,
|
89
|
+
COALESCE(json_agg(src_att.attname ORDER BY ord.n), '[]'::json) AS src_cols,
|
90
|
+
COALESCE(json_agg(tgt_att.attname ORDER BY ord.n), '[]'::json) AS tgt_cols
|
91
|
+
FROM pg_constraint con
|
92
|
+
JOIN pg_class src ON src.oid = con.conrelid
|
93
|
+
JOIN pg_class tgt ON tgt.oid = con.confrelid
|
94
|
+
JOIN LATERAL generate_subscripts(con.conkey, 1) ord(n) ON true
|
95
|
+
JOIN pg_attribute src_att ON src_att.attrelid = src.oid AND src_att.attnum = con.conkey[ord.n]
|
96
|
+
JOIN pg_attribute tgt_att ON tgt_att.attrelid = tgt.oid AND tgt_att.attnum = con.confkey[ord.n]
|
97
|
+
JOIN pg_namespace ns ON ns.oid = src.relnamespace
|
98
|
+
WHERE con.contype = 'f'
|
99
|
+
AND ns.nspname = $1
|
100
|
+
GROUP BY con.oid, src.relname, tgt.relname, con.confdeltype, con.confupdtype
|
101
|
+
ORDER BY src.relname, con.oid
|
102
|
+
`, [schema]);
|
103
|
+
for (const r of fkRows.rows) {
|
104
|
+
const t = ensureTable(tables, r.src_table);
|
105
|
+
t.fks.push({
|
106
|
+
from: (r.src_cols ?? []).slice(),
|
107
|
+
toTable: r.tgt_table,
|
108
|
+
to: (r.tgt_cols ?? []).slice(),
|
109
|
+
onDelete: decodeAction(r.confdeltype),
|
110
|
+
onUpdate: decodeAction(r.confupdtype),
|
111
|
+
});
|
112
|
+
}
|
113
|
+
const enumRows = await pg.query(`
|
114
|
+
SELECT t.typname AS enum_name, e.enumlabel
|
115
|
+
FROM pg_type t
|
116
|
+
JOIN pg_enum e ON e.enumtypid = t.oid
|
117
|
+
JOIN pg_namespace n ON n.oid = t.typnamespace
|
118
|
+
WHERE n.nspname = $1
|
119
|
+
ORDER BY t.typname, e.enumsortorder
|
120
|
+
`, [schema]);
|
121
|
+
for (const r of enumRows.rows) {
|
122
|
+
if (!enums[r.enum_name])
|
123
|
+
enums[r.enum_name] = [];
|
124
|
+
enums[r.enum_name].push(r.enumlabel);
|
125
|
+
}
|
126
|
+
}
|
127
|
+
finally {
|
128
|
+
await pg.end();
|
129
|
+
}
|
130
|
+
return { schema, tables, enums };
|
131
|
+
}
|
132
|
+
//# sourceMappingURL=introspect.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"introspect.js","sourceRoot":"","sources":["../src/introspect.ts"],"names":[],"mappings":"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"}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
import type { Model } from "./introspect";
|
2
|
+
export type Edge = {
|
3
|
+
from: string;
|
4
|
+
key: string;
|
5
|
+
kind: "one" | "many";
|
6
|
+
target: string;
|
7
|
+
via?: string;
|
8
|
+
};
|
9
|
+
export type Graph = Record<string, Record<string, Edge>>;
|
10
|
+
export declare function buildGraph(model: Model): Graph;
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"rel-classify.d.ts","sourceRoot":"","sources":["../src/rel-classify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAS,MAAM,cAAc,CAAC;AAEjD,MAAM,MAAM,IAAI,GAAG;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,KAAK,GAAG,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;AAKzD,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAsD9C"}
|
@@ -0,0 +1,52 @@
|
|
1
|
+
const singular = (s) => (s.endsWith("s") ? s.slice(0, -1) : s);
|
2
|
+
const plural = (s) => (s.endsWith("s") ? s : s + "s");
|
3
|
+
export function buildGraph(model) {
|
4
|
+
const graph = {};
|
5
|
+
const tables = Object.values(model.tables);
|
6
|
+
// init nodes
|
7
|
+
for (const t of tables)
|
8
|
+
graph[t.name] = graph[t.name] ?? {};
|
9
|
+
// 1) 1:N & 1:1 from FKs
|
10
|
+
for (const child of tables) {
|
11
|
+
for (const fk of child.fks) {
|
12
|
+
const parent = tables.find((t) => t.name === fk.toTable);
|
13
|
+
if (!parent)
|
14
|
+
continue;
|
15
|
+
// cache nodes so TS knows they're not undefined
|
16
|
+
const childNode = (graph[child.name] ??= {});
|
17
|
+
const parentNode = (graph[parent.name] ??= {});
|
18
|
+
const upKey = singular(parent.name);
|
19
|
+
const downKey = plural(child.name);
|
20
|
+
if (!(upKey in childNode)) {
|
21
|
+
childNode[upKey] = { from: child.name, key: upKey, kind: "one", target: parent.name };
|
22
|
+
}
|
23
|
+
if (!(downKey in parentNode)) {
|
24
|
+
parentNode[downKey] = { from: parent.name, key: downKey, kind: "many", target: child.name };
|
25
|
+
}
|
26
|
+
}
|
27
|
+
}
|
28
|
+
// 2) M:N via junction (two FKs)
|
29
|
+
for (const j of tables) {
|
30
|
+
if ((j.fks?.length ?? 0) !== 2)
|
31
|
+
continue;
|
32
|
+
const [fkA, fkB] = j.fks;
|
33
|
+
if (!fkA || !fkB)
|
34
|
+
continue;
|
35
|
+
const A = fkA.toTable;
|
36
|
+
const B = fkB.toTable;
|
37
|
+
if (!A || !B || A === B)
|
38
|
+
continue;
|
39
|
+
const aNode = (graph[A] ??= {});
|
40
|
+
const bNode = (graph[B] ??= {});
|
41
|
+
const aKey = plural(B);
|
42
|
+
const bKey = plural(A);
|
43
|
+
if (!(aKey in aNode)) {
|
44
|
+
aNode[aKey] = { from: A, key: aKey, kind: "many", target: B, via: j.name };
|
45
|
+
}
|
46
|
+
if (!(bKey in bNode)) {
|
47
|
+
bNode[bKey] = { from: B, key: bKey, kind: "many", target: A, via: j.name };
|
48
|
+
}
|
49
|
+
}
|
50
|
+
return graph;
|
51
|
+
}
|
52
|
+
//# sourceMappingURL=rel-classify.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"rel-classify.js","sourceRoot":"","sources":["../src/rel-classify.ts"],"names":[],"mappings":"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"}
|
package/dist/src/cli.js
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/usr/bin/env node
|
2
|
+
import { resolve } from "node:path";
|
3
|
+
import { generate } from "./index.js";
|
4
|
+
const args = process.argv.slice(2);
|
5
|
+
// Handle --version
|
6
|
+
if (args.includes("--version") || args.includes("-v")) {
|
7
|
+
console.log("postgresdk v0.1.0");
|
8
|
+
process.exit(0);
|
9
|
+
}
|
10
|
+
// Handle --help
|
11
|
+
if (args.includes("--help") || args.includes("-h")) {
|
12
|
+
console.log(`
|
13
|
+
postgresdk - Generate typed SDK from PostgreSQL
|
14
|
+
|
15
|
+
Usage:
|
16
|
+
postgresdk [options]
|
17
|
+
|
18
|
+
Options:
|
19
|
+
-c, --config <path> Path to config file (default: postgresdk.config.ts)
|
20
|
+
-v, --version Show version
|
21
|
+
-h, --help Show help
|
22
|
+
`);
|
23
|
+
process.exit(0);
|
24
|
+
}
|
25
|
+
// Get config path
|
26
|
+
let configPath = "postgresdk.config.ts";
|
27
|
+
const configIndex = args.findIndex(a => a === "-c" || a === "--config");
|
28
|
+
if (configIndex !== -1 && args[configIndex + 1]) {
|
29
|
+
configPath = args[configIndex + 1];
|
30
|
+
}
|
31
|
+
// Run generator
|
32
|
+
try {
|
33
|
+
await generate(resolve(process.cwd(), configPath));
|
34
|
+
}
|
35
|
+
catch (err) {
|
36
|
+
console.error("❌ Generation failed:", err);
|
37
|
+
process.exit(1);
|
38
|
+
}
|
39
|
+
//# sourceMappingURL=cli.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEnC,mBAAmB;AACnB,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;IACtD,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IACjC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,gBAAgB;AAChB,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;IACnD,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;CAUb,CAAC,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,kBAAkB;AAClB,IAAI,UAAU,GAAG,sBAAsB,CAAC;AACxC,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,UAAU,CAAC,CAAC;AACxE,IAAI,WAAW,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,EAAE,CAAC;IAChD,UAAU,GAAG,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;AACrC,CAAC;AAED,gBAAgB;AAChB,IAAI,CAAC;IACH,MAAM,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,CAAC,CAAC,CAAC;AACrD,CAAC;AAAC,OAAO,GAAG,EAAE,CAAC;IACb,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,GAAG,CAAC,CAAC;IAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC"}
|
@@ -0,0 +1,114 @@
|
|
1
|
+
import { pascal } from "./utils";
|
2
|
+
export function emitClient(table) {
|
3
|
+
const Type = pascal(table.name);
|
4
|
+
// Normalize PKs
|
5
|
+
const pkCols = Array.isArray(table.pk)
|
6
|
+
? table.pk
|
7
|
+
: table.pk
|
8
|
+
? [table.pk]
|
9
|
+
: [];
|
10
|
+
const safePk = pkCols.length ? pkCols : ["id"];
|
11
|
+
const hasCompositePk = safePk.length > 1;
|
12
|
+
const pkType = hasCompositePk ? `{ ${safePk.map((c) => `${c}: string`).join("; ")} }` : `string`;
|
13
|
+
const pkPathExpr = hasCompositePk ? safePk.map((c) => `pk.${c}`).join(` + "/" + `) : `pk`;
|
14
|
+
return `/* Generated. Do not edit. */
|
15
|
+
import type { ${Type}IncludeSpec } from "./include-spec";
|
16
|
+
import type { Insert${Type}, Update${Type}, Select${Type} } from "./types/${table.name}";
|
17
|
+
|
18
|
+
export class ${Type}Client {
|
19
|
+
constructor(
|
20
|
+
private baseUrl: string,
|
21
|
+
private fetchFn: typeof fetch = fetch,
|
22
|
+
private auth?: () => Promise<Record<string,string>>
|
23
|
+
) {}
|
24
|
+
|
25
|
+
private async headers(json = false) {
|
26
|
+
const extra = (await this.auth?.()) ?? {};
|
27
|
+
return json ? { "Content-Type": "application/json", ...extra } : extra;
|
28
|
+
}
|
29
|
+
|
30
|
+
private async okOrThrow(res: Response, action: string) {
|
31
|
+
if (!res.ok) {
|
32
|
+
let detail = "";
|
33
|
+
try { detail = await res.text(); } catch {}
|
34
|
+
throw new Error(\`\${action} ${table.name} failed: \${res.status} \${detail}\`);
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
async create(data: Insert${Type}): Promise<Select${Type}> {
|
39
|
+
const res = await this.fetchFn(\`\${this.baseUrl}/v1/${table.name}\`, {
|
40
|
+
method: "POST",
|
41
|
+
headers: await this.headers(true),
|
42
|
+
body: JSON.stringify(data),
|
43
|
+
});
|
44
|
+
await this.okOrThrow(res, "create");
|
45
|
+
return (await res.json()) as Select${Type};
|
46
|
+
}
|
47
|
+
|
48
|
+
async getByPk(pk: ${pkType}): Promise<Select${Type} | null> {
|
49
|
+
const path = ${pkPathExpr};
|
50
|
+
const res = await this.fetchFn(\`\${this.baseUrl}/v1/${table.name}/\${path}\`, {
|
51
|
+
headers: await this.headers(),
|
52
|
+
});
|
53
|
+
if (res.status === 404) return null;
|
54
|
+
await this.okOrThrow(res, "get");
|
55
|
+
return (await res.json()) as Select${Type};
|
56
|
+
}
|
57
|
+
|
58
|
+
async list(params?: { include?: ${Type}IncludeSpec; limit?: number; offset?: number }): Promise<Select${Type}[]> {
|
59
|
+
const res = await this.fetchFn(\`\${this.baseUrl}/v1/${table.name}/list\`, {
|
60
|
+
method: "POST",
|
61
|
+
headers: await this.headers(true),
|
62
|
+
body: JSON.stringify(params ?? {}),
|
63
|
+
});
|
64
|
+
await this.okOrThrow(res, "list");
|
65
|
+
return (await res.json()) as Select${Type}[];
|
66
|
+
}
|
67
|
+
|
68
|
+
async update(pk: ${pkType}, patch: Update${Type}): Promise<Select${Type} | null> {
|
69
|
+
const path = ${pkPathExpr};
|
70
|
+
const res = await this.fetchFn(\`\${this.baseUrl}/v1/${table.name}/\${path}\`, {
|
71
|
+
method: "PATCH",
|
72
|
+
headers: await this.headers(true),
|
73
|
+
body: JSON.stringify(patch),
|
74
|
+
});
|
75
|
+
if (res.status === 404) return null;
|
76
|
+
await this.okOrThrow(res, "update");
|
77
|
+
return (await res.json()) as Select${Type};
|
78
|
+
}
|
79
|
+
|
80
|
+
async delete(pk: ${pkType}): Promise<Select${Type} | null> {
|
81
|
+
const path = ${pkPathExpr};
|
82
|
+
const res = await this.fetchFn(\`\${this.baseUrl}/v1/${table.name}/\${path}\`, {
|
83
|
+
method: "DELETE",
|
84
|
+
headers: await this.headers(),
|
85
|
+
});
|
86
|
+
if (res.status === 404) return null;
|
87
|
+
await this.okOrThrow(res, "delete");
|
88
|
+
return (await res.json()) as Select${Type};
|
89
|
+
}
|
90
|
+
}
|
91
|
+
`;
|
92
|
+
}
|
93
|
+
export function emitClientIndex(tables) {
|
94
|
+
let out = `/* Generated. Do not edit. */\n`;
|
95
|
+
for (const t of tables) {
|
96
|
+
out += `import { ${pascal(t.name)}Client } from "./${t.name}";\n`;
|
97
|
+
}
|
98
|
+
out += `\nexport class SDK {\n`;
|
99
|
+
for (const t of tables) {
|
100
|
+
out += ` public ${t.name}: ${pascal(t.name)}Client;\n`;
|
101
|
+
}
|
102
|
+
out += `\n constructor(cfg: { baseUrl: string; fetch?: typeof fetch; auth?: () => Promise<Record<string,string>> }) {\n`;
|
103
|
+
out += ` const f = cfg.fetch ?? fetch;\n`;
|
104
|
+
for (const t of tables) {
|
105
|
+
out += ` this.${t.name} = new ${pascal(t.name)}Client(cfg.baseUrl, f, cfg.auth);\n`;
|
106
|
+
}
|
107
|
+
out += ` }\n`;
|
108
|
+
out += `}\n`;
|
109
|
+
for (const t of tables)
|
110
|
+
out += `export { ${pascal(t.name)}Client } from "./${t.name}";\n`;
|
111
|
+
out += `export * from "./include-spec";\n`;
|
112
|
+
return out;
|
113
|
+
}
|
114
|
+
//# sourceMappingURL=emit-client.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"emit-client.js","sourceRoot":"","sources":["../../src/emit-client.ts"],"names":[],"mappings":"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"}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
export function emitIncludeBuilder(graph, maxDepth) {
|
2
|
+
return `// Generated. Do not edit.
|
3
|
+
export const RELATION_GRAPH = ${JSON.stringify(graph, null, 2)} as const;
|
4
|
+
type TableName = keyof typeof RELATION_GRAPH;
|
5
|
+
|
6
|
+
export function buildWith(root: TableName, spec: any, maxDepth = ${maxDepth}) {
|
7
|
+
return walk(root as string, spec, 0);
|
8
|
+
function walk(table: string, s: any, depth: number): any {
|
9
|
+
if (!s || depth >= maxDepth) return undefined;
|
10
|
+
const rels: any = (RELATION_GRAPH as any)[table] || {};
|
11
|
+
const out: any = {};
|
12
|
+
for (const key of Object.keys(s)) {
|
13
|
+
const rel = rels[key];
|
14
|
+
if (!rel) throw new Error(\`Unknown include key '\${key}' on table '\${table}'\`);
|
15
|
+
const v = s[key];
|
16
|
+
if (v === true) out[key] = true;
|
17
|
+
else if (v && typeof v === "object") {
|
18
|
+
const child = "include" in v ? walk(rel.target, v.include, depth + 1) : undefined;
|
19
|
+
out[key] = child ? { with: child } : true;
|
20
|
+
}
|
21
|
+
}
|
22
|
+
return Object.keys(out).length ? out : undefined;
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
export const buildWithFor = (t: TableName) =>
|
27
|
+
(spec?: any, depth = ${maxDepth}) => (spec ? buildWith(t, spec, depth) : undefined);
|
28
|
+
`;
|
29
|
+
}
|
30
|
+
//# sourceMappingURL=emit-include-builder.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"emit-include-builder.js","sourceRoot":"","sources":["../../src/emit-include-builder.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,kBAAkB,CAAC,KAAY,EAAE,QAAgB;IAC/D,OAAO;gCACuB,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;;;mEAGK,QAAQ;;;;;;;;;;;;;;;;;;;;;yBAqBlD,QAAQ;CAChC,CAAC;AACF,CAAC"}
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import type { Graph } from "./rel-classify";
|
2
|
+
import type { Model } from "./introspect";
|
3
|
+
/**
|
4
|
+
* Emit a generic include loader that:
|
5
|
+
* - Walks the include spec
|
6
|
+
* - Loads children in batches per edge kind
|
7
|
+
* - Stitches onto parent rows (mutates copies)
|
8
|
+
*/
|
9
|
+
export declare function emitIncludeLoader(graph: Graph, model: Model, maxDepth: number): string;
|