postgresdk 0.19.2 → 0.19.3
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 +32 -8
- package/dist/index.js +32 -8
- package/dist/rel-classify.d.ts +2 -0
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -583,7 +583,8 @@ function buildReturnType(baseTable, path, isMany, targets, graph) {
|
|
|
583
583
|
continue;
|
|
584
584
|
const targetType = `Select${pascal(target)}`;
|
|
585
585
|
if (i === 0) {
|
|
586
|
-
|
|
586
|
+
const edgeNull = !isMany[i] && graph[baseTable]?.[key]?.nullable ? " | null" : "";
|
|
587
|
+
parts.push(`${key}: ${isMany[i] ? `${targetType}[]` : `${targetType}${edgeNull}`}`);
|
|
587
588
|
} else {
|
|
588
589
|
let nestedType = targetType;
|
|
589
590
|
for (let j = i;j < path.length; j++) {
|
|
@@ -593,13 +594,26 @@ function buildReturnType(baseTable, path, isMany, targets, graph) {
|
|
|
593
594
|
if (!nestedKey || !nestedTarget)
|
|
594
595
|
continue;
|
|
595
596
|
const nestedTargetType = `Select${pascal(nestedTarget)}`;
|
|
596
|
-
|
|
597
|
+
const nestedSource = targets[j - 1];
|
|
598
|
+
const nestedNull = !isMany[j] && graph[nestedSource]?.[nestedKey]?.nullable ? " | null" : "";
|
|
599
|
+
nestedType = `${nestedType} & { ${nestedKey}: ${isMany[j] ? `${nestedTargetType}[]` : `${nestedTargetType}${nestedNull}`} }`;
|
|
597
600
|
}
|
|
598
601
|
}
|
|
599
602
|
const prevKey = path[i - 1];
|
|
600
603
|
const prevTarget = targets[i - 1];
|
|
601
604
|
if (prevKey && prevTarget) {
|
|
602
|
-
|
|
605
|
+
const prevSource = i - 1 === 0 ? baseTable : targets[i - 2];
|
|
606
|
+
const innerNull = !isMany[i] && graph[prevTarget]?.[key]?.nullable ? " | null" : "";
|
|
607
|
+
const prevNullable = !isMany[i - 1] && graph[prevSource]?.[prevKey]?.nullable;
|
|
608
|
+
const inner = isMany[i] ? `${targetType}[]` : `${targetType}${innerNull}`;
|
|
609
|
+
const composite = `Select${pascal(prevTarget)} & { ${key}: ${inner} }`;
|
|
610
|
+
if (isMany[i - 1]) {
|
|
611
|
+
parts[parts.length - 1] = `${prevKey}: (${composite})[]`;
|
|
612
|
+
} else if (prevNullable) {
|
|
613
|
+
parts[parts.length - 1] = `${prevKey}: (${composite}) | null`;
|
|
614
|
+
} else {
|
|
615
|
+
parts[parts.length - 1] = `${prevKey}: ${composite}`;
|
|
616
|
+
}
|
|
603
617
|
}
|
|
604
618
|
break;
|
|
605
619
|
}
|
|
@@ -689,8 +703,10 @@ function generateIncludeMethods(table, graph, opts, allTables) {
|
|
|
689
703
|
}
|
|
690
704
|
const combinedPath = [key1, key2];
|
|
691
705
|
const combinedSuffix = `With${pascal(key1)}And${pascal(key2)}`;
|
|
692
|
-
const
|
|
693
|
-
const
|
|
706
|
+
const null1 = edge1.kind === "one" && edge1.nullable ? " | null" : "";
|
|
707
|
+
const null2 = edge2.kind === "one" && edge2.nullable ? " | null" : "";
|
|
708
|
+
const type1 = `${key1}: ${edge1.kind === "many" ? `Select${pascal(edge1.target)}[]` : `Select${pascal(edge1.target)}${null1}`}`;
|
|
709
|
+
const type2 = `${key2}: ${edge2.kind === "many" ? `Select${pascal(edge2.target)}[]` : `Select${pascal(edge2.target)}${null2}`}`;
|
|
694
710
|
const combinedBaseType = `Select${pascal(baseTableName)} & { ${type1}; ${type2} }`;
|
|
695
711
|
const combinedTypeName = `Select${pascal(baseTableName)}${combinedSuffix}`;
|
|
696
712
|
methods.push({
|
|
@@ -2639,7 +2655,14 @@ function buildGraph(model) {
|
|
|
2639
2655
|
const upKey = singular(parent.name);
|
|
2640
2656
|
const downKey = plural(child.name);
|
|
2641
2657
|
if (!(upKey in childNode)) {
|
|
2642
|
-
|
|
2658
|
+
const fkNullable = fk.from.some((colName) => child.columns.find((c) => c.name === colName)?.nullable);
|
|
2659
|
+
childNode[upKey] = {
|
|
2660
|
+
from: child.name,
|
|
2661
|
+
key: upKey,
|
|
2662
|
+
kind: "one",
|
|
2663
|
+
target: parent.name,
|
|
2664
|
+
...fkNullable && { nullable: true }
|
|
2665
|
+
};
|
|
2643
2666
|
}
|
|
2644
2667
|
if (!(downKey in parentNode)) {
|
|
2645
2668
|
parentNode[downKey] = { from: parent.name, key: downKey, kind: "many", target: child.name };
|
|
@@ -2757,10 +2780,11 @@ function emitIncludeResolver(graph, useJsExtensions) {
|
|
|
2757
2780
|
: Select${targetType}[]
|
|
2758
2781
|
)`;
|
|
2759
2782
|
} else {
|
|
2783
|
+
const nullSuffix = edge.nullable ? " | null" : "";
|
|
2760
2784
|
out += `(
|
|
2761
2785
|
TInclude[K] extends { include: infer U extends ${targetType}IncludeSpec }
|
|
2762
|
-
? ${targetType}WithIncludes<U
|
|
2763
|
-
: Select${targetType}
|
|
2786
|
+
? ${targetType}WithIncludes<U>${nullSuffix}
|
|
2787
|
+
: Select${targetType}${nullSuffix}
|
|
2764
2788
|
)`;
|
|
2765
2789
|
}
|
|
2766
2790
|
out += ` :${isLast ? `
|
package/dist/index.js
CHANGED
|
@@ -582,7 +582,8 @@ function buildReturnType(baseTable, path, isMany, targets, graph) {
|
|
|
582
582
|
continue;
|
|
583
583
|
const targetType = `Select${pascal(target)}`;
|
|
584
584
|
if (i === 0) {
|
|
585
|
-
|
|
585
|
+
const edgeNull = !isMany[i] && graph[baseTable]?.[key]?.nullable ? " | null" : "";
|
|
586
|
+
parts.push(`${key}: ${isMany[i] ? `${targetType}[]` : `${targetType}${edgeNull}`}`);
|
|
586
587
|
} else {
|
|
587
588
|
let nestedType = targetType;
|
|
588
589
|
for (let j = i;j < path.length; j++) {
|
|
@@ -592,13 +593,26 @@ function buildReturnType(baseTable, path, isMany, targets, graph) {
|
|
|
592
593
|
if (!nestedKey || !nestedTarget)
|
|
593
594
|
continue;
|
|
594
595
|
const nestedTargetType = `Select${pascal(nestedTarget)}`;
|
|
595
|
-
|
|
596
|
+
const nestedSource = targets[j - 1];
|
|
597
|
+
const nestedNull = !isMany[j] && graph[nestedSource]?.[nestedKey]?.nullable ? " | null" : "";
|
|
598
|
+
nestedType = `${nestedType} & { ${nestedKey}: ${isMany[j] ? `${nestedTargetType}[]` : `${nestedTargetType}${nestedNull}`} }`;
|
|
596
599
|
}
|
|
597
600
|
}
|
|
598
601
|
const prevKey = path[i - 1];
|
|
599
602
|
const prevTarget = targets[i - 1];
|
|
600
603
|
if (prevKey && prevTarget) {
|
|
601
|
-
|
|
604
|
+
const prevSource = i - 1 === 0 ? baseTable : targets[i - 2];
|
|
605
|
+
const innerNull = !isMany[i] && graph[prevTarget]?.[key]?.nullable ? " | null" : "";
|
|
606
|
+
const prevNullable = !isMany[i - 1] && graph[prevSource]?.[prevKey]?.nullable;
|
|
607
|
+
const inner = isMany[i] ? `${targetType}[]` : `${targetType}${innerNull}`;
|
|
608
|
+
const composite = `Select${pascal(prevTarget)} & { ${key}: ${inner} }`;
|
|
609
|
+
if (isMany[i - 1]) {
|
|
610
|
+
parts[parts.length - 1] = `${prevKey}: (${composite})[]`;
|
|
611
|
+
} else if (prevNullable) {
|
|
612
|
+
parts[parts.length - 1] = `${prevKey}: (${composite}) | null`;
|
|
613
|
+
} else {
|
|
614
|
+
parts[parts.length - 1] = `${prevKey}: ${composite}`;
|
|
615
|
+
}
|
|
602
616
|
}
|
|
603
617
|
break;
|
|
604
618
|
}
|
|
@@ -688,8 +702,10 @@ function generateIncludeMethods(table, graph, opts, allTables) {
|
|
|
688
702
|
}
|
|
689
703
|
const combinedPath = [key1, key2];
|
|
690
704
|
const combinedSuffix = `With${pascal(key1)}And${pascal(key2)}`;
|
|
691
|
-
const
|
|
692
|
-
const
|
|
705
|
+
const null1 = edge1.kind === "one" && edge1.nullable ? " | null" : "";
|
|
706
|
+
const null2 = edge2.kind === "one" && edge2.nullable ? " | null" : "";
|
|
707
|
+
const type1 = `${key1}: ${edge1.kind === "many" ? `Select${pascal(edge1.target)}[]` : `Select${pascal(edge1.target)}${null1}`}`;
|
|
708
|
+
const type2 = `${key2}: ${edge2.kind === "many" ? `Select${pascal(edge2.target)}[]` : `Select${pascal(edge2.target)}${null2}`}`;
|
|
693
709
|
const combinedBaseType = `Select${pascal(baseTableName)} & { ${type1}; ${type2} }`;
|
|
694
710
|
const combinedTypeName = `Select${pascal(baseTableName)}${combinedSuffix}`;
|
|
695
711
|
methods.push({
|
|
@@ -1679,7 +1695,14 @@ function buildGraph(model) {
|
|
|
1679
1695
|
const upKey = singular(parent.name);
|
|
1680
1696
|
const downKey = plural(child.name);
|
|
1681
1697
|
if (!(upKey in childNode)) {
|
|
1682
|
-
|
|
1698
|
+
const fkNullable = fk.from.some((colName) => child.columns.find((c) => c.name === colName)?.nullable);
|
|
1699
|
+
childNode[upKey] = {
|
|
1700
|
+
from: child.name,
|
|
1701
|
+
key: upKey,
|
|
1702
|
+
kind: "one",
|
|
1703
|
+
target: parent.name,
|
|
1704
|
+
...fkNullable && { nullable: true }
|
|
1705
|
+
};
|
|
1683
1706
|
}
|
|
1684
1707
|
if (!(downKey in parentNode)) {
|
|
1685
1708
|
parentNode[downKey] = { from: parent.name, key: downKey, kind: "many", target: child.name };
|
|
@@ -1797,10 +1820,11 @@ function emitIncludeResolver(graph, useJsExtensions) {
|
|
|
1797
1820
|
: Select${targetType}[]
|
|
1798
1821
|
)`;
|
|
1799
1822
|
} else {
|
|
1823
|
+
const nullSuffix = edge.nullable ? " | null" : "";
|
|
1800
1824
|
out += `(
|
|
1801
1825
|
TInclude[K] extends { include: infer U extends ${targetType}IncludeSpec }
|
|
1802
|
-
? ${targetType}WithIncludes<U
|
|
1803
|
-
: Select${targetType}
|
|
1826
|
+
? ${targetType}WithIncludes<U>${nullSuffix}
|
|
1827
|
+
: Select${targetType}${nullSuffix}
|
|
1804
1828
|
)`;
|
|
1805
1829
|
}
|
|
1806
1830
|
out += ` :${isLast ? `
|
package/dist/rel-classify.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ export type Edge = {
|
|
|
5
5
|
kind: "one" | "many";
|
|
6
6
|
target: string;
|
|
7
7
|
via?: string;
|
|
8
|
+
/** True when the FK column(s) are nullable (belongs-to may return null). */
|
|
9
|
+
nullable?: boolean;
|
|
8
10
|
};
|
|
9
11
|
export type Graph = Record<string, Record<string, Edge>>;
|
|
10
12
|
export declare function buildGraph(model: Model): Graph;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "postgresdk",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.3",
|
|
4
4
|
"description": "Generate a typed server/client SDK from a Postgres schema (includes, Zod, Hono).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
},
|
|
23
23
|
"scripts": {
|
|
24
24
|
"build": "bun build src/cli.ts src/index.ts --outdir dist --target node --format esm --external=pg --external=zod --external=hono --external=prompts --external=node:* && tsc -p tsconfig.build.json --emitDeclarationOnly",
|
|
25
|
-
"test": "bun test:write-files && bun test:init && bun test:gen && bun test test/test-where-clause.test.ts && bun test test/test-where-or-and.test.ts && bun test test/test-nested-include-options.test.ts && bun test test/test-include-methods-with-options.test.ts && bun test:gen-with-tests && bun test:pull && bun test:enums && bun test:typecheck && bun test:drizzle-e2e && bun test test/test-numeric-mode-integration.test.ts && bun test test/test-jsonb-array-serialization.test.ts && bun test test/test-trigram-search.test.ts && bun test test/test-soft-delete-config.test.ts && bun test test/test-soft-delete-include-loader.test.ts && bun test test/test-soft-delete-nested-include.test.ts && bun test test/test-transaction.test.ts",
|
|
25
|
+
"test": "bun test:write-files && bun test:init && bun test:gen && bun test test/test-where-clause.test.ts && bun test test/test-where-or-and.test.ts && bun test test/test-nested-include-options.test.ts && bun test test/test-include-methods-with-options.test.ts && bun test:gen-with-tests && bun test:pull && bun test:enums && bun test:typecheck && bun test:drizzle-e2e && bun test test/test-numeric-mode-integration.test.ts && bun test test/test-jsonb-array-serialization.test.ts && bun test test/test-trigram-search.test.ts && bun test test/test-soft-delete-config.test.ts && bun test test/test-soft-delete-include-loader.test.ts && bun test test/test-soft-delete-nested-include.test.ts && bun test test/test-transaction.test.ts && bun test test/test-nullable-belongs-to.test.ts",
|
|
26
26
|
"test:write-files": "bun test/test-write-files-if-changed.ts",
|
|
27
27
|
"test:init": "bun test/test-init.ts",
|
|
28
28
|
"test:gen": "bun test/test-gen.ts",
|