prostgles-types 4.0.281 → 4.0.283

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/lib/index.ts CHANGED
@@ -117,6 +117,8 @@ export type DBTableSchema = {
117
117
  * fields that are nullable or with a default value are be optional
118
118
  */
119
119
  columns: AnyObject;
120
+ /** Client insert input; omitted on schemas that use the database column defaults. */
121
+ insertColumns?: AnyObject;
120
122
  /**
121
123
  * TODO: extract references and update InsertDataWithNested type to allow nested inserts based on the references
122
124
  * Table names and their columns that reference the current table through foreign keys.
@@ -582,7 +584,7 @@ type InclusiveSelect = true | 1 | FunctionSelect | JoinSelect;
582
584
  type SelectWithFunctions<T extends AnyObject = AnyObject, IsTyped = false> =
583
585
  | ({ [K in keyof Partial<T>]: InclusiveSelect } & Record<
584
586
  string,
585
- IsTyped extends true ? FunctionFull : InclusiveSelect
587
+ IsTyped extends true ? FunctionFull | DetailedJoinSelect : InclusiveSelect
586
588
  >)
587
589
  | FunctionAliasedSelect
588
590
  | { [K in keyof Partial<T>]: true | 1 | string }
@@ -757,31 +759,61 @@ export type NormalizedRow<T extends Record<string, unknown>> = Required<{
757
759
  [K in keyof T]: CollapseNumberIfStringPresent<T[K]>;
758
760
  }>;
759
761
 
762
+ type JoinTarget<P> =
763
+ P extends string ? P
764
+ : P extends readonly [...unknown[], infer Last] ?
765
+ Last extends string ? Last
766
+ : Last extends { table: infer T } ? T
767
+ : never
768
+ : never;
769
+
770
+ type ExplicitJoinResult<J, S extends DBSchema | void, P> =
771
+ [JoinTarget<P>] extends [never] ? any[]
772
+ : S extends DBSchema ?
773
+ JoinTarget<P> extends infer T extends keyof S ?
774
+ J extends { select: infer Sel extends Select } ?
775
+ SelectDataType<S, { select: Sel }, S[T]["columns"]>[]
776
+ : any[]
777
+ : any[]
778
+ : any[];
779
+
760
780
  type JoinedSelect = Record<string, Select>;
761
781
  export type SelectFunction = Record<string, any[]>;
762
782
  type ParseSelect<
763
783
  Select extends SelectParams<TD>["select"],
764
784
  TD extends AnyObject,
785
+ S extends DBSchema | void,
765
786
  > = (Select extends { "*": 1 } ? NormalizedRow<TD> : {}) & {
766
- [Key in keyof Omit<Select, "*"> & string]: Select[Key] extends 1 ? NormalizedRow<TD>[Key]
787
+ [Key in keyof Omit<Select, "*"> & string]: Select[Key] extends 1 | true ? NormalizedRow<TD>[Key]
788
+ : Select[Key] extends (
789
+ {
790
+ $leftJoin: infer P extends RawJoinPath;
791
+ select: unknown;
792
+ }
793
+ ) ?
794
+ ExplicitJoinResult<Select[Key], S, P>
795
+ : Select[Key] extends (
796
+ {
797
+ $innerJoin: infer P extends RawJoinPath;
798
+ select: unknown;
799
+ }
800
+ ) ?
801
+ ExplicitJoinResult<Select[Key], S, P>
767
802
  : Select[Key] extends SelectFunction ? any
768
803
  : Select[Key] extends JoinedSelect ? any[]
769
804
  : any;
770
805
  };
771
806
 
772
- type SelectDataType<
773
- S extends DBSchema | void,
774
- O extends SelectParams<TD, S>,
775
- TD extends AnyObject,
776
- > =
807
+ type SelectDataType<S extends DBSchema | void, O, TD extends AnyObject> =
777
808
  O extends { returnType: "value" } ? any
778
809
  : O extends { returnType: "values"; select: Record<string, 1> } ?
779
810
  ValueOf<Pick<NormalizedRow<TD>, keyof O["select"]>>
780
811
  : O extends { returnType: "values" } ? any
781
812
  : O extends { select: "*" } ? NormalizedRow<TD>
782
813
  : O extends { select: "" } ? Record<string, never>
783
- : O extends { select: Record<string, 0> } ? Omit<NormalizedRow<TD>, keyof O["select"]>
784
- : O extends { select: Record<string, any> } ? ParseSelect<O["select"], NormalizedRow<TD>>
814
+ : O extends { select: readonly (keyof TD)[] } ? Pick<NormalizedRow<TD>, O["select"][number]>
815
+ : O extends { select: Record<string, 0 | false> } ? Omit<NormalizedRow<TD>, keyof O["select"]>
816
+ : O extends { select: Record<string, any> } ? ParseSelect<O["select"], NormalizedRow<TD>, S>
785
817
  : NormalizedRow<TD>;
786
818
 
787
819
  export type SelectReturnType<
@@ -901,7 +933,7 @@ export type InsertDataWithNested<
901
933
  TD extends AnyObject,
902
934
  S extends DBSchema | void,
903
935
  TName extends PropertyKey = never,
904
- > = InsertColumnsWithReferences<TD, S, TName> &
936
+ > = InsertColumnsWithReferences<GetInsertColumns<TD, S, TName>, S, TName> &
905
937
  (S extends DBSchema ?
906
938
  string extends keyof S ?
907
939
  {} // collapse to void-like behavior for untyped/dynamic schema
@@ -910,6 +942,11 @@ export type InsertDataWithNested<
910
942
  }
911
943
  : {});
912
944
 
945
+ type GetInsertColumns<TD extends AnyObject, S, TName extends PropertyKey> =
946
+ [TName] extends [never] ? TD
947
+ : S extends Record<TName, { insertColumns: infer Columns extends AnyObject }> ? Columns
948
+ : TD;
949
+
913
950
  /**
914
951
  * Methods for interacting with a table/view
915
952
  * - On client-side some methods are restricted (and undefined) based on publish rules on the server
@@ -20,13 +20,19 @@ export type InsertColumnsWithReferences<
20
20
  }
21
21
  : never;
22
22
 
23
- type ColumnReferences<S extends DBSchema | void, TName extends PropertyKey> = {
24
- [F in keyof S]: S[F] extends (
25
- {
26
- columns: infer Data extends AnyObject;
23
+ // Compute the reference-bearing tables once per schema, independently of the insert target.
24
+ type SchemaReferences<S> = {
25
+ [F in keyof S]: S[F] extends {
26
+ columns: infer Data extends AnyObject;
27
+ referencedBy: infer References;
28
+ } ? { name: F; data: Data; referencedBy: References } : never;
29
+ }[keyof S];
30
+
31
+ type ColumnReferences<S extends DBSchema | void, TName extends PropertyKey> =
32
+ SchemaReferences<S> extends infer Table ?
33
+ Table extends {
34
+ name: infer F extends PropertyKey;
35
+ data: infer Data extends AnyObject;
27
36
  referencedBy: Record<TName, infer Columns>;
28
- }
29
- ) ?
30
- { columns: Columns; data: InsertDataWithNested<Data, S, F> }
37
+ } ? { columns: Columns; data: InsertDataWithNested<Data, S, F> } : never
31
38
  : never;
32
- }[keyof S];
@@ -1,6 +1,9 @@
1
- import type { AnyObject, JoinMaker } from "./index";
1
+ import type { AnyObject, DetailedJoinSelect, JoinMaker } from "./index";
2
2
  import { omitKeys } from "./util";
3
3
 
4
+ /** Preserve literal table names and selections for joined return type inference. */
5
+ export const defineJoin = <const J extends DetailedJoinSelect>(join: J): J => join;
6
+
4
7
  const getJoinFunc = (joinType: "$leftJoin" | "$innerJoin" = "$leftJoin") => {
5
8
  const joinMaker: JoinMaker = (
6
9
  tableName: Parameters<JoinMaker<AnyObject>>[0],
package/package.json CHANGED
@@ -1,16 +1,22 @@
1
1
  {
2
2
  "name": "prostgles-types",
3
- "version": "4.0.281",
3
+ "version": "4.0.283",
4
4
  "description": "",
5
5
  "main": "dist/index_umd.js",
6
6
  "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist",
9
+ "lib",
10
+ "!**/*.spec.*"
11
+ ],
7
12
  "directories": {},
8
13
  "scripts": {
9
14
  "start": "tsc --watch",
10
15
  "test": "npm run build && npm run test:type-instantiations && node --test dist/*.spec.js dist/**/*.spec.js",
11
16
  "test:type-instantiations": "node scripts/check-type-instantiations.mjs",
12
- "build": "npm i && rm -rf ./dist/* && tsc && webpack --config webpack.prod.js",
17
+ "build": "rm -rf ./dist/* && tsc && webpack --config webpack.prod.js",
13
18
  "prebuild": "tsc --noEmit -p tsconfig.browser.json",
19
+ "prepack": "npm run build",
14
20
  "perf": "tsc --extendedDiagnostics 2>&1 | grep -E \"Instantiations|Check time\"",
15
21
  "pushpublish": "npm version patch --git-tag-version false && git push && npm publish"
16
22
  },
@@ -1,12 +0,0 @@
1
- {
2
- "typescript.tsdk": "node_modules/typescript/lib",
3
- "editor.formatOnSave": true,
4
- "prettier.experimentalTernaries": true,
5
- "[javascript]": {
6
- "editor.defaultFormatter": "esbenp.prettier-vscode"
7
- },
8
- "[typescript]": {
9
- "editor.defaultFormatter": "esbenp.prettier-vscode"
10
- },
11
- "prettier.printWidth": 100
12
- }
@@ -1,40 +0,0 @@
1
- import { spawnSync } from "node:child_process";
2
- import { fileURLToPath } from "node:url";
3
-
4
- // Baseline: 108,997. The small margin avoids hiding meaningful inference regressions.
5
- const MAX_INSTANTIATIONS = 105_000;
6
- const tscPath = fileURLToPath(new URL("../node_modules/typescript/bin/tsc", import.meta.url));
7
- const result = spawnSync(
8
- process.execPath,
9
- [tscPath, "--noEmit", "--extendedDiagnostics", "--pretty", "false"],
10
- { encoding: "utf8" },
11
- );
12
-
13
- if (result.error) {
14
- throw result.error;
15
- }
16
-
17
- if (result.status !== 0) {
18
- process.stdout.write(result.stdout);
19
- process.stderr.write(result.stderr);
20
- process.exit(result.status ?? 1);
21
- }
22
-
23
- const output = result.stdout + result.stderr;
24
- const label = "Instantiations:";
25
- const line = output.split("\n").find((outputLine) => outputLine.startsWith(label));
26
- const instantiations = Number(line?.slice(label.length).trim());
27
-
28
- if (!Number.isFinite(instantiations)) {
29
- throw new Error(`Could not read type instantiations from tsc output:\n${output}`);
30
- }
31
-
32
- if (instantiations > MAX_INSTANTIATIONS) {
33
- throw new Error(
34
- `Type instantiations increased to ${instantiations.toLocaleString()} (maximum: ${MAX_INSTANTIATIONS.toLocaleString()}).`,
35
- );
36
- }
37
-
38
- console.log(
39
- `Type instantiations: ${instantiations.toLocaleString()} / ${MAX_INSTANTIATIONS.toLocaleString()}`,
40
- );