kysely-gen 0.2.2 → 0.3.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/dist/cli.js +335 -112
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -22477,25 +22477,51 @@ function serializeType(node) {
|
|
|
22477
22477
|
return serializeReference(node);
|
|
22478
22478
|
case "raw":
|
|
22479
22479
|
return serializeRaw(node);
|
|
22480
|
+
case "tuple":
|
|
22481
|
+
return serializeTuple(node);
|
|
22482
|
+
case "conditional":
|
|
22483
|
+
return serializeConditional(node);
|
|
22484
|
+
case "keyof":
|
|
22485
|
+
return serializeKeyof(node);
|
|
22486
|
+
case "indexAccess":
|
|
22487
|
+
return serializeIndexAccess(node);
|
|
22488
|
+
case "infer":
|
|
22489
|
+
return serializeInfer(node);
|
|
22480
22490
|
}
|
|
22481
22491
|
}
|
|
22482
22492
|
function serializePrimitive(node) {
|
|
22483
22493
|
return node.value;
|
|
22484
22494
|
}
|
|
22495
|
+
function escapeString(value) {
|
|
22496
|
+
return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
|
|
22497
|
+
}
|
|
22485
22498
|
function serializeLiteral(node) {
|
|
22486
22499
|
if (typeof node.value === "string") {
|
|
22487
|
-
return `'${node.value}'`;
|
|
22500
|
+
return `'${escapeString(node.value)}'`;
|
|
22488
22501
|
}
|
|
22489
22502
|
return String(node.value);
|
|
22490
22503
|
}
|
|
22504
|
+
function needsParens(node, context) {
|
|
22505
|
+
if (context === "union" && node.kind === "intersection")
|
|
22506
|
+
return true;
|
|
22507
|
+
if (context === "intersection" && node.kind === "union")
|
|
22508
|
+
return true;
|
|
22509
|
+
if (context === "array" && (node.kind === "union" || node.kind === "intersection"))
|
|
22510
|
+
return true;
|
|
22511
|
+
return false;
|
|
22512
|
+
}
|
|
22513
|
+
function serializeWithParens(node, context) {
|
|
22514
|
+
const serialized = serializeType(node);
|
|
22515
|
+
return needsParens(node, context) ? `(${serialized})` : serialized;
|
|
22516
|
+
}
|
|
22491
22517
|
function serializeUnion(node) {
|
|
22492
|
-
return node.types.map(
|
|
22518
|
+
return node.types.map((t) => serializeWithParens(t, "union")).join(" | ");
|
|
22493
22519
|
}
|
|
22494
22520
|
function serializeIntersection(node) {
|
|
22495
|
-
return node.types.map(
|
|
22521
|
+
return node.types.map((t) => serializeWithParens(t, "intersection")).join(" & ");
|
|
22496
22522
|
}
|
|
22497
22523
|
function serializeArray(node) {
|
|
22498
|
-
return `${
|
|
22524
|
+
return `${serializeWithParens(node.elementType, "array")}[]`;
|
|
22499
22525
|
}
|
|
22500
22526
|
function serializeGeneric(node) {
|
|
22501
22527
|
const typeArgs = node.typeArguments.map(serializeType).join(", ");
|
|
@@ -22507,10 +22533,103 @@ function serializeReference(node) {
|
|
|
22507
22533
|
function serializeRaw(node) {
|
|
22508
22534
|
return node.value;
|
|
22509
22535
|
}
|
|
22536
|
+
function serializeTuple(node) {
|
|
22537
|
+
return `[${node.elements.map(serializeType).join(", ")}]`;
|
|
22538
|
+
}
|
|
22539
|
+
function serializeConditional(node) {
|
|
22540
|
+
const check = serializeType(node.checkType);
|
|
22541
|
+
const ext = serializeType(node.extendsType);
|
|
22542
|
+
const trueType = serializeType(node.trueType);
|
|
22543
|
+
const falseType = serializeType(node.falseType);
|
|
22544
|
+
return `${check} extends ${ext} ? ${trueType} : ${falseType}`;
|
|
22545
|
+
}
|
|
22546
|
+
function serializeKeyof(node) {
|
|
22547
|
+
return `keyof ${serializeType(node.type)}`;
|
|
22548
|
+
}
|
|
22549
|
+
function serializeIndexAccess(node) {
|
|
22550
|
+
return `${serializeType(node.objectType)}[${serializeType(node.indexType)}]`;
|
|
22551
|
+
}
|
|
22552
|
+
function serializeInfer(node) {
|
|
22553
|
+
return `infer ${node.name}`;
|
|
22554
|
+
}
|
|
22555
|
+
var RESERVED_WORDS = new Set([
|
|
22556
|
+
"break",
|
|
22557
|
+
"case",
|
|
22558
|
+
"catch",
|
|
22559
|
+
"class",
|
|
22560
|
+
"const",
|
|
22561
|
+
"continue",
|
|
22562
|
+
"debugger",
|
|
22563
|
+
"default",
|
|
22564
|
+
"delete",
|
|
22565
|
+
"do",
|
|
22566
|
+
"else",
|
|
22567
|
+
"enum",
|
|
22568
|
+
"export",
|
|
22569
|
+
"extends",
|
|
22570
|
+
"false",
|
|
22571
|
+
"finally",
|
|
22572
|
+
"for",
|
|
22573
|
+
"function",
|
|
22574
|
+
"if",
|
|
22575
|
+
"import",
|
|
22576
|
+
"in",
|
|
22577
|
+
"instanceof",
|
|
22578
|
+
"new",
|
|
22579
|
+
"null",
|
|
22580
|
+
"return",
|
|
22581
|
+
"super",
|
|
22582
|
+
"switch",
|
|
22583
|
+
"this",
|
|
22584
|
+
"throw",
|
|
22585
|
+
"true",
|
|
22586
|
+
"try",
|
|
22587
|
+
"typeof",
|
|
22588
|
+
"var",
|
|
22589
|
+
"void",
|
|
22590
|
+
"while",
|
|
22591
|
+
"with",
|
|
22592
|
+
"yield",
|
|
22593
|
+
"let",
|
|
22594
|
+
"static",
|
|
22595
|
+
"implements",
|
|
22596
|
+
"interface",
|
|
22597
|
+
"package",
|
|
22598
|
+
"private",
|
|
22599
|
+
"protected",
|
|
22600
|
+
"public",
|
|
22601
|
+
"await",
|
|
22602
|
+
"abstract",
|
|
22603
|
+
"as",
|
|
22604
|
+
"async",
|
|
22605
|
+
"declare",
|
|
22606
|
+
"from",
|
|
22607
|
+
"get",
|
|
22608
|
+
"is",
|
|
22609
|
+
"module",
|
|
22610
|
+
"namespace",
|
|
22611
|
+
"of",
|
|
22612
|
+
"require",
|
|
22613
|
+
"set",
|
|
22614
|
+
"type"
|
|
22615
|
+
]);
|
|
22616
|
+
function needsQuotes(name) {
|
|
22617
|
+
if (RESERVED_WORDS.has(name))
|
|
22618
|
+
return true;
|
|
22619
|
+
if (/^\d/.test(name))
|
|
22620
|
+
return true;
|
|
22621
|
+
if (!/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name))
|
|
22622
|
+
return true;
|
|
22623
|
+
return false;
|
|
22624
|
+
}
|
|
22625
|
+
function serializePropertyName(name) {
|
|
22626
|
+
return needsQuotes(name) ? `'${escapeString(name)}'` : name;
|
|
22627
|
+
}
|
|
22510
22628
|
function serializeProperty(node, indent = " ") {
|
|
22511
22629
|
const optional = node.optional ? "?" : "";
|
|
22512
22630
|
const readonly = node.readonly ? "readonly " : "";
|
|
22513
|
-
|
|
22631
|
+
const propName = serializePropertyName(node.name);
|
|
22632
|
+
return `${indent}${readonly}${propName}${optional}: ${serializeType(node.type)};`;
|
|
22514
22633
|
}
|
|
22515
22634
|
function serializeInterface(node) {
|
|
22516
22635
|
const exported = node.exported ? "export " : "";
|
|
@@ -22548,14 +22667,15 @@ function serialize(program2) {
|
|
|
22548
22667
|
|
|
22549
22668
|
// src/introspect/postgres.ts
|
|
22550
22669
|
async function introspectDatabase(db, options) {
|
|
22551
|
-
const [domains, partitions, baseTables, materializedViews, enums] = await Promise.all([
|
|
22670
|
+
const [domains, partitions, baseTables, regularViews, materializedViews, enums] = await Promise.all([
|
|
22552
22671
|
introspectDomains(db),
|
|
22553
22672
|
introspectPartitions(db),
|
|
22554
22673
|
introspectTables(db, options.schemas),
|
|
22674
|
+
introspectViews(db, options.schemas),
|
|
22555
22675
|
introspectMaterializedViews(db, options.schemas),
|
|
22556
22676
|
introspectEnums(db, options.schemas)
|
|
22557
22677
|
]);
|
|
22558
|
-
const tables = [...baseTables, ...materializedViews].map((table) => {
|
|
22678
|
+
const tables = [...baseTables, ...regularViews, ...materializedViews].map((table) => {
|
|
22559
22679
|
const isPartition = partitions.some((partition) => partition.schema === table.schema && partition.name === table.name);
|
|
22560
22680
|
return {
|
|
22561
22681
|
...table,
|
|
@@ -22581,6 +22701,7 @@ async function introspectTables(db, schemas) {
|
|
|
22581
22701
|
c.udt_name,
|
|
22582
22702
|
c.udt_schema,
|
|
22583
22703
|
c.is_nullable,
|
|
22704
|
+
c.is_identity,
|
|
22584
22705
|
c.column_default,
|
|
22585
22706
|
pg_catalog.col_description(
|
|
22586
22707
|
(c.table_schema||'.'||c.table_name)::regclass::oid,
|
|
@@ -22630,6 +22751,67 @@ async function introspectTables(db, schemas) {
|
|
|
22630
22751
|
}
|
|
22631
22752
|
return Array.from(tableMap.values());
|
|
22632
22753
|
}
|
|
22754
|
+
async function introspectViews(db, schemas) {
|
|
22755
|
+
const rawColumns = await sql`
|
|
22756
|
+
SELECT
|
|
22757
|
+
c.table_schema,
|
|
22758
|
+
c.table_name,
|
|
22759
|
+
c.column_name,
|
|
22760
|
+
c.data_type,
|
|
22761
|
+
c.udt_name,
|
|
22762
|
+
c.udt_schema,
|
|
22763
|
+
c.is_nullable,
|
|
22764
|
+
c.is_identity,
|
|
22765
|
+
c.column_default,
|
|
22766
|
+
pg_catalog.col_description(
|
|
22767
|
+
(c.table_schema||'.'||c.table_name)::regclass::oid,
|
|
22768
|
+
c.ordinal_position
|
|
22769
|
+
) as column_comment
|
|
22770
|
+
FROM information_schema.columns c
|
|
22771
|
+
INNER JOIN information_schema.tables t
|
|
22772
|
+
ON c.table_schema = t.table_schema
|
|
22773
|
+
AND c.table_name = t.table_name
|
|
22774
|
+
WHERE t.table_type = 'VIEW'
|
|
22775
|
+
AND c.table_schema = ANY(${schemas})
|
|
22776
|
+
ORDER BY c.table_schema, c.table_name, c.ordinal_position
|
|
22777
|
+
`.execute(db);
|
|
22778
|
+
const tableMap = new Map;
|
|
22779
|
+
for (const row of rawColumns.rows) {
|
|
22780
|
+
const tableKey = `${row.table_schema}.${row.table_name}`;
|
|
22781
|
+
if (!tableMap.has(tableKey)) {
|
|
22782
|
+
tableMap.set(tableKey, {
|
|
22783
|
+
schema: row.table_schema,
|
|
22784
|
+
name: row.table_name,
|
|
22785
|
+
columns: [],
|
|
22786
|
+
isView: true
|
|
22787
|
+
});
|
|
22788
|
+
}
|
|
22789
|
+
const table = tableMap.get(tableKey);
|
|
22790
|
+
if (table) {
|
|
22791
|
+
const isArray = row.data_type === "ARRAY";
|
|
22792
|
+
let dataType = row.udt_name;
|
|
22793
|
+
if (isArray && dataType.startsWith("_")) {
|
|
22794
|
+
dataType = dataType.slice(1);
|
|
22795
|
+
}
|
|
22796
|
+
const columnMetadata = {
|
|
22797
|
+
name: row.column_name,
|
|
22798
|
+
dataType,
|
|
22799
|
+
dataTypeSchema: row.udt_schema,
|
|
22800
|
+
isNullable: row.is_nullable === "YES",
|
|
22801
|
+
isAutoIncrement: false,
|
|
22802
|
+
hasDefaultValue: row.column_default !== null
|
|
22803
|
+
};
|
|
22804
|
+
if (isArray) {
|
|
22805
|
+
columnMetadata.isArray = true;
|
|
22806
|
+
}
|
|
22807
|
+
if (row.column_comment) {
|
|
22808
|
+
columnMetadata.comment = row.column_comment;
|
|
22809
|
+
}
|
|
22810
|
+
table.columns.push(columnMetadata);
|
|
22811
|
+
}
|
|
22812
|
+
}
|
|
22813
|
+
return Array.from(tableMap.values());
|
|
22814
|
+
}
|
|
22633
22815
|
async function introspectMaterializedViews(db, schemas) {
|
|
22634
22816
|
const rawColumns = await sql`
|
|
22635
22817
|
SELECT
|
|
@@ -22642,12 +22824,15 @@ async function introspectMaterializedViews(db, schemas) {
|
|
|
22642
22824
|
t.typname AS data_type,
|
|
22643
22825
|
t.typname AS udt_name,
|
|
22644
22826
|
tn.nspname AS udt_schema,
|
|
22827
|
+
t.typcategory,
|
|
22828
|
+
et.typname AS element_type,
|
|
22645
22829
|
col_description(c.oid, a.attnum) AS column_comment
|
|
22646
22830
|
FROM pg_class c
|
|
22647
22831
|
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
22648
22832
|
JOIN pg_attribute a ON a.attrelid = c.oid
|
|
22649
22833
|
JOIN pg_type t ON t.oid = a.atttypid
|
|
22650
22834
|
JOIN pg_namespace tn ON tn.oid = t.typnamespace
|
|
22835
|
+
LEFT JOIN pg_type et ON t.typelem = et.oid AND t.typcategory = 'A'
|
|
22651
22836
|
LEFT JOIN pg_attrdef ad ON ad.adrelid = c.oid AND ad.adnum = a.attnum
|
|
22652
22837
|
WHERE c.relkind = 'm'
|
|
22653
22838
|
AND a.attnum > 0
|
|
@@ -22668,25 +22853,18 @@ async function introspectMaterializedViews(db, schemas) {
|
|
|
22668
22853
|
}
|
|
22669
22854
|
const table = tableMap.get(tableKey);
|
|
22670
22855
|
if (table) {
|
|
22671
|
-
const isArray = row.
|
|
22672
|
-
|
|
22673
|
-
if (isArray) {
|
|
22674
|
-
dataType = dataType.slice(1);
|
|
22675
|
-
}
|
|
22856
|
+
const isArray = row.typcategory === "A";
|
|
22857
|
+
const dataType = isArray && row.element_type ? row.element_type : row.udt_name;
|
|
22676
22858
|
const columnMetadata = {
|
|
22677
22859
|
name: row.column_name,
|
|
22678
22860
|
dataType,
|
|
22679
22861
|
dataTypeSchema: row.udt_schema,
|
|
22680
22862
|
isNullable: row.is_nullable === "YES",
|
|
22681
22863
|
isAutoIncrement: row.column_default?.includes("nextval") ?? false,
|
|
22682
|
-
hasDefaultValue: row.column_default !== null
|
|
22864
|
+
hasDefaultValue: row.column_default !== null,
|
|
22865
|
+
...isArray && { isArray: true },
|
|
22866
|
+
...row.column_comment && { comment: row.column_comment }
|
|
22683
22867
|
};
|
|
22684
|
-
if (isArray) {
|
|
22685
|
-
columnMetadata.isArray = true;
|
|
22686
|
-
}
|
|
22687
|
-
if (row.column_comment) {
|
|
22688
|
-
columnMetadata.comment = row.column_comment;
|
|
22689
|
-
}
|
|
22690
22868
|
table.columns.push(columnMetadata);
|
|
22691
22869
|
}
|
|
22692
22870
|
}
|
|
@@ -22754,6 +22932,9 @@ async function introspectEnums(db, schemas) {
|
|
|
22754
22932
|
}));
|
|
22755
22933
|
}
|
|
22756
22934
|
function isAutoIncrementColumn(column) {
|
|
22935
|
+
if (column.is_identity === "YES") {
|
|
22936
|
+
return true;
|
|
22937
|
+
}
|
|
22757
22938
|
if (!column.column_default) {
|
|
22758
22939
|
return false;
|
|
22759
22940
|
}
|
|
@@ -22769,51 +22950,8 @@ function parsePostgresArray(value) {
|
|
|
22769
22950
|
return [value];
|
|
22770
22951
|
}
|
|
22771
22952
|
|
|
22772
|
-
// src/transform.ts
|
|
22953
|
+
// src/transform/filter.ts
|
|
22773
22954
|
var import_micromatch = __toESM(require_micromatch(), 1);
|
|
22774
|
-
|
|
22775
|
-
// src/utils/case-converter.ts
|
|
22776
|
-
class CaseConverter extends CamelCasePlugin {
|
|
22777
|
-
toCamelCase(str) {
|
|
22778
|
-
return this.camelCase(str);
|
|
22779
|
-
}
|
|
22780
|
-
}
|
|
22781
|
-
function toCamelCase(str) {
|
|
22782
|
-
return new CaseConverter().toCamelCase(str);
|
|
22783
|
-
}
|
|
22784
|
-
|
|
22785
|
-
// src/transform.ts
|
|
22786
|
-
function transformDatabase(metadata, options) {
|
|
22787
|
-
const declarations = [];
|
|
22788
|
-
declarations.push({
|
|
22789
|
-
kind: "import",
|
|
22790
|
-
imports: ["ColumnType"],
|
|
22791
|
-
from: "kysely",
|
|
22792
|
-
typeOnly: true
|
|
22793
|
-
});
|
|
22794
|
-
declarations.push({
|
|
22795
|
-
kind: "typeAlias",
|
|
22796
|
-
name: "Generated<T>",
|
|
22797
|
-
type: {
|
|
22798
|
-
kind: "raw",
|
|
22799
|
-
value: `T extends ColumnType<infer S, infer I, infer U>
|
|
22800
|
-
? ColumnType<S, I | undefined, U>
|
|
22801
|
-
: ColumnType<T, T | undefined, T>`
|
|
22802
|
-
},
|
|
22803
|
-
exported: true
|
|
22804
|
-
});
|
|
22805
|
-
for (const enumMetadata of metadata.enums) {
|
|
22806
|
-
declarations.push(transformEnum(enumMetadata));
|
|
22807
|
-
}
|
|
22808
|
-
const filteredTables = filterTables(metadata.tables, options);
|
|
22809
|
-
const tableInterfaces = [];
|
|
22810
|
-
for (const table of filteredTables) {
|
|
22811
|
-
tableInterfaces.push(transformTable(table, metadata.enums, options));
|
|
22812
|
-
}
|
|
22813
|
-
declarations.push(...tableInterfaces);
|
|
22814
|
-
declarations.push(createDBInterface(filteredTables, options));
|
|
22815
|
-
return { declarations };
|
|
22816
|
-
}
|
|
22817
22955
|
function filterTables(tables, options) {
|
|
22818
22956
|
if (!options || !options.includePattern && !options.excludePattern) {
|
|
22819
22957
|
return tables;
|
|
@@ -22831,10 +22969,29 @@ function filterTables(tables, options) {
|
|
|
22831
22969
|
return true;
|
|
22832
22970
|
});
|
|
22833
22971
|
}
|
|
22834
|
-
|
|
22972
|
+
|
|
22973
|
+
// src/transform/utils.ts
|
|
22974
|
+
function toPascalCase(str) {
|
|
22975
|
+
return str.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join("");
|
|
22976
|
+
}
|
|
22977
|
+
function singularize(str) {
|
|
22978
|
+
if (str.endsWith("s")) {
|
|
22979
|
+
return str.slice(0, -1);
|
|
22980
|
+
}
|
|
22981
|
+
return str;
|
|
22982
|
+
}
|
|
22983
|
+
|
|
22984
|
+
// src/transform/enum.ts
|
|
22985
|
+
function getEnumTypeName(enumMeta, defaultSchema = "public") {
|
|
22986
|
+
if (enumMeta.schema === defaultSchema) {
|
|
22987
|
+
return toPascalCase(enumMeta.name);
|
|
22988
|
+
}
|
|
22989
|
+
return toPascalCase(enumMeta.schema) + toPascalCase(enumMeta.name);
|
|
22990
|
+
}
|
|
22991
|
+
function transformEnum(enumMetadata, defaultSchema = "public") {
|
|
22835
22992
|
return {
|
|
22836
22993
|
kind: "typeAlias",
|
|
22837
|
-
name:
|
|
22994
|
+
name: getEnumTypeName(enumMetadata, defaultSchema),
|
|
22838
22995
|
type: {
|
|
22839
22996
|
kind: "union",
|
|
22840
22997
|
types: enumMetadata.values.map((value) => ({
|
|
@@ -22845,44 +23002,19 @@ function transformEnum(enumMetadata) {
|
|
|
22845
23002
|
exported: true
|
|
22846
23003
|
};
|
|
22847
23004
|
}
|
|
22848
|
-
|
|
22849
|
-
|
|
22850
|
-
|
|
22851
|
-
|
|
22852
|
-
|
|
22853
|
-
properties,
|
|
22854
|
-
exported: true
|
|
22855
|
-
};
|
|
22856
|
-
}
|
|
22857
|
-
function transformColumn(column, enums, options) {
|
|
22858
|
-
const matchingEnum = enums.find((e) => e.name === column.dataType);
|
|
22859
|
-
let type;
|
|
22860
|
-
if (matchingEnum) {
|
|
22861
|
-
const enumTypeName = toPascalCase(matchingEnum.name);
|
|
22862
|
-
type = { kind: "reference", name: enumTypeName };
|
|
22863
|
-
if (column.isNullable) {
|
|
22864
|
-
type = {
|
|
22865
|
-
kind: "union",
|
|
22866
|
-
types: [type, { kind: "primitive", value: "null" }]
|
|
22867
|
-
};
|
|
22868
|
-
}
|
|
22869
|
-
} else {
|
|
22870
|
-
type = mapPostgresType(column.dataType, column.isNullable, column.isArray);
|
|
22871
|
-
}
|
|
22872
|
-
if (column.isAutoIncrement) {
|
|
22873
|
-
type = {
|
|
22874
|
-
kind: "generic",
|
|
22875
|
-
name: "Generated",
|
|
22876
|
-
typeArguments: [type]
|
|
22877
|
-
};
|
|
23005
|
+
|
|
23006
|
+
// src/utils/case-converter.ts
|
|
23007
|
+
class CaseConverter extends CamelCasePlugin {
|
|
23008
|
+
toCamelCase(str) {
|
|
23009
|
+
return this.camelCase(str);
|
|
22878
23010
|
}
|
|
22879
|
-
const columnName = options?.camelCase ? toCamelCase(column.name) : column.name;
|
|
22880
|
-
return {
|
|
22881
|
-
name: columnName,
|
|
22882
|
-
type,
|
|
22883
|
-
optional: false
|
|
22884
|
-
};
|
|
22885
23011
|
}
|
|
23012
|
+
var caseConverter = new CaseConverter;
|
|
23013
|
+
function toCamelCase(str) {
|
|
23014
|
+
return caseConverter.toCamelCase(str);
|
|
23015
|
+
}
|
|
23016
|
+
|
|
23017
|
+
// src/transform/type-mapper.ts
|
|
22886
23018
|
function createColumnType(selectType, insertType, updateType) {
|
|
22887
23019
|
const typeArguments = [selectType];
|
|
22888
23020
|
if (insertType) {
|
|
@@ -22897,10 +23029,10 @@ function createColumnType(selectType, insertType, updateType) {
|
|
|
22897
23029
|
typeArguments
|
|
22898
23030
|
};
|
|
22899
23031
|
}
|
|
22900
|
-
function mapPostgresType(pgType, isNullable, isArray) {
|
|
23032
|
+
function mapPostgresType(pgType, isNullable, isArray, unknownTypes) {
|
|
22901
23033
|
if (isArray || pgType.endsWith("[]")) {
|
|
22902
23034
|
const baseTypeName = pgType.endsWith("[]") ? pgType.slice(0, -2) : pgType;
|
|
22903
|
-
const elementType = mapPostgresType(baseTypeName, false, false);
|
|
23035
|
+
const elementType = mapPostgresType(baseTypeName, false, false, unknownTypes);
|
|
22904
23036
|
const arrayType = {
|
|
22905
23037
|
kind: "array",
|
|
22906
23038
|
elementType
|
|
@@ -22991,6 +23123,10 @@ function mapPostgresType(pgType, isNullable, isArray) {
|
|
|
22991
23123
|
break;
|
|
22992
23124
|
case "time":
|
|
22993
23125
|
case "timetz":
|
|
23126
|
+
case "interval":
|
|
23127
|
+
baseType = { kind: "primitive", value: "string" };
|
|
23128
|
+
break;
|
|
23129
|
+
case "money":
|
|
22994
23130
|
baseType = { kind: "primitive", value: "string" };
|
|
22995
23131
|
break;
|
|
22996
23132
|
case "json":
|
|
@@ -23000,7 +23136,18 @@ function mapPostgresType(pgType, isNullable, isArray) {
|
|
|
23000
23136
|
case "bytea":
|
|
23001
23137
|
baseType = { kind: "primitive", value: "Buffer" };
|
|
23002
23138
|
break;
|
|
23139
|
+
case "int4range":
|
|
23140
|
+
case "int8range":
|
|
23141
|
+
case "numrange":
|
|
23142
|
+
case "daterange":
|
|
23143
|
+
case "tsrange":
|
|
23144
|
+
case "tstzrange":
|
|
23145
|
+
baseType = { kind: "primitive", value: "string" };
|
|
23146
|
+
break;
|
|
23003
23147
|
default:
|
|
23148
|
+
if (unknownTypes) {
|
|
23149
|
+
unknownTypes.add(pgType);
|
|
23150
|
+
}
|
|
23004
23151
|
baseType = { kind: "primitive", value: "unknown" };
|
|
23005
23152
|
}
|
|
23006
23153
|
if (isNullable) {
|
|
@@ -23011,6 +23158,46 @@ function mapPostgresType(pgType, isNullable, isArray) {
|
|
|
23011
23158
|
}
|
|
23012
23159
|
return baseType;
|
|
23013
23160
|
}
|
|
23161
|
+
|
|
23162
|
+
// src/transform/table.ts
|
|
23163
|
+
function transformTable(table, enums, options, unknownTypes) {
|
|
23164
|
+
const properties = table.columns.map((column) => transformColumn(column, enums, options, unknownTypes));
|
|
23165
|
+
return {
|
|
23166
|
+
kind: "interface",
|
|
23167
|
+
name: toPascalCase(singularize(table.name)),
|
|
23168
|
+
properties,
|
|
23169
|
+
exported: true
|
|
23170
|
+
};
|
|
23171
|
+
}
|
|
23172
|
+
function transformColumn(column, enums, options, unknownTypes) {
|
|
23173
|
+
const matchingEnum = enums.find((e) => e.name === column.dataType && e.schema === (column.dataTypeSchema ?? "public"));
|
|
23174
|
+
let type;
|
|
23175
|
+
if (matchingEnum) {
|
|
23176
|
+
const enumTypeName = getEnumTypeName(matchingEnum);
|
|
23177
|
+
type = { kind: "reference", name: enumTypeName };
|
|
23178
|
+
if (column.isNullable) {
|
|
23179
|
+
type = {
|
|
23180
|
+
kind: "union",
|
|
23181
|
+
types: [type, { kind: "primitive", value: "null" }]
|
|
23182
|
+
};
|
|
23183
|
+
}
|
|
23184
|
+
} else {
|
|
23185
|
+
type = mapPostgresType(column.dataType, column.isNullable, column.isArray, unknownTypes);
|
|
23186
|
+
}
|
|
23187
|
+
if (column.isAutoIncrement) {
|
|
23188
|
+
type = {
|
|
23189
|
+
kind: "generic",
|
|
23190
|
+
name: "Generated",
|
|
23191
|
+
typeArguments: [type]
|
|
23192
|
+
};
|
|
23193
|
+
}
|
|
23194
|
+
const columnName = options?.camelCase ? toCamelCase(column.name) : column.name;
|
|
23195
|
+
return {
|
|
23196
|
+
name: columnName,
|
|
23197
|
+
type,
|
|
23198
|
+
optional: false
|
|
23199
|
+
};
|
|
23200
|
+
}
|
|
23014
23201
|
function createDBInterface(tables, options) {
|
|
23015
23202
|
const properties = tables.map((table) => {
|
|
23016
23203
|
const tableName = options?.camelCase ? toCamelCase(table.name) : table.name;
|
|
@@ -23030,14 +23217,43 @@ function createDBInterface(tables, options) {
|
|
|
23030
23217
|
exported: true
|
|
23031
23218
|
};
|
|
23032
23219
|
}
|
|
23033
|
-
|
|
23034
|
-
|
|
23035
|
-
|
|
23036
|
-
|
|
23037
|
-
|
|
23038
|
-
|
|
23220
|
+
|
|
23221
|
+
// src/transform/index.ts
|
|
23222
|
+
function transformDatabase(metadata, options) {
|
|
23223
|
+
const declarations = [];
|
|
23224
|
+
const unknownTypes = new Set;
|
|
23225
|
+
declarations.push({
|
|
23226
|
+
kind: "import",
|
|
23227
|
+
imports: ["ColumnType"],
|
|
23228
|
+
from: "kysely",
|
|
23229
|
+
typeOnly: true
|
|
23230
|
+
});
|
|
23231
|
+
declarations.push({
|
|
23232
|
+
kind: "typeAlias",
|
|
23233
|
+
name: "Generated<T>",
|
|
23234
|
+
type: {
|
|
23235
|
+
kind: "raw",
|
|
23236
|
+
value: `T extends ColumnType<infer S, infer I, infer U>
|
|
23237
|
+
? ColumnType<S, I | undefined, U>
|
|
23238
|
+
: ColumnType<T, T | undefined, T>`
|
|
23239
|
+
},
|
|
23240
|
+
exported: true
|
|
23241
|
+
});
|
|
23242
|
+
for (const enumMetadata of metadata.enums) {
|
|
23243
|
+
declarations.push(transformEnum(enumMetadata));
|
|
23039
23244
|
}
|
|
23040
|
-
|
|
23245
|
+
const filteredTables = filterTables(metadata.tables, options);
|
|
23246
|
+
const tableInterfaces = [];
|
|
23247
|
+
for (const table of filteredTables) {
|
|
23248
|
+
tableInterfaces.push(transformTable(table, metadata.enums, options, unknownTypes));
|
|
23249
|
+
}
|
|
23250
|
+
declarations.push(...tableInterfaces);
|
|
23251
|
+
declarations.push(createDBInterface(filteredTables, options));
|
|
23252
|
+
const warnings = Array.from(unknownTypes).map((pgType) => ({
|
|
23253
|
+
type: "unknown_type",
|
|
23254
|
+
pgType
|
|
23255
|
+
}));
|
|
23256
|
+
return { program: { declarations }, warnings };
|
|
23041
23257
|
}
|
|
23042
23258
|
|
|
23043
23259
|
// src/cli.ts
|
|
@@ -23103,7 +23319,7 @@ async function generate(options) {
|
|
|
23103
23319
|
}
|
|
23104
23320
|
spinner.succeed(`Found ${source_default.bold(tableCount)} tables and ${source_default.bold(enumCount)} enums`);
|
|
23105
23321
|
spinner.start("Generating TypeScript types...");
|
|
23106
|
-
const program3 = transformDatabase(metadata, {
|
|
23322
|
+
const { program: program3, warnings } = transformDatabase(metadata, {
|
|
23107
23323
|
camelCase: options.camelCase,
|
|
23108
23324
|
includePattern: options.includePattern.length > 0 ? options.includePattern : undefined,
|
|
23109
23325
|
excludePattern: options.excludePattern.length > 0 ? options.excludePattern : undefined
|
|
@@ -23112,9 +23328,16 @@ async function generate(options) {
|
|
|
23112
23328
|
const absolutePath = resolve(outputPath);
|
|
23113
23329
|
await writeFile(absolutePath, code, "utf-8");
|
|
23114
23330
|
spinner.succeed(`Types written to ${source_default.cyan(absolutePath)}`);
|
|
23331
|
+
if (warnings.length > 0) {
|
|
23332
|
+
console.log("");
|
|
23333
|
+
console.log(source_default.yellow("Warnings:"));
|
|
23334
|
+
for (const w of warnings) {
|
|
23335
|
+
console.log(source_default.dim(` Unknown type '${w.pgType}' mapped to 'unknown'`));
|
|
23336
|
+
}
|
|
23337
|
+
}
|
|
23115
23338
|
await db.destroy();
|
|
23116
23339
|
console.log("");
|
|
23117
|
-
console.log(source_default.green("
|
|
23340
|
+
console.log(source_default.green("Done!"));
|
|
23118
23341
|
console.log("");
|
|
23119
23342
|
}
|
|
23120
23343
|
function maskPassword(url) {
|