@casekit/orm2-schema 0.0.0-20250331202540 → 0.0.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.
Files changed (86) hide show
  1. package/package.json +15 -16
  2. package/{build/Config.d.ts → src/Config.ts} +9 -2
  3. package/{build/definition/FieldDefinition.d.ts → src/definition/FieldDefinition.ts} +19 -6
  4. package/{build/definition/ModelDefinition.d.ts → src/definition/ModelDefinition.ts} +7 -0
  5. package/{build/definition/ModelDefinitions.d.ts → src/definition/ModelDefinitions.ts} +1 -0
  6. package/{build/definition/OperatorDefinitions.d.ts → src/definition/OperatorDefinitions.ts} +1 -0
  7. package/{build/definition/PostgresDataTypes.d.ts → src/definition/PostgresDataTypes.ts} +3 -0
  8. package/{build/definition/RelationDefinition.d.ts → src/definition/RelationDefinition.ts} +7 -1
  9. package/{build/definition/RelationDefinitions.d.ts → src/definition/RelationDefinitions.ts} +1 -0
  10. package/{build/definition/UniqueConstraintDefinition.d.ts → src/definition/UniqueConstraintDefinition.ts} +1 -0
  11. package/src/definition/WhereOperator.ts +6 -0
  12. package/src/helper/DefaultFieldType.test-d.ts +60 -0
  13. package/src/helper/DefaultFieldType.ts +99 -0
  14. package/{build/helper/FieldName.test-d.js → src/helper/FieldName.test-d.ts} +9 -2
  15. package/{build/helper/FieldName.d.ts → src/helper/FieldName.ts} +1 -0
  16. package/src/helper/FieldType.test-d.ts +81 -0
  17. package/src/helper/FieldType.ts +16 -0
  18. package/{build/helper/FieldWithDefault.test-d.js → src/helper/FieldWithDefault.test-d.ts} +17 -6
  19. package/{build/helper/FieldWithDefault.d.ts → src/helper/FieldWithDefault.ts} +6 -1
  20. package/{build/helper/ModelName.test-d.js → src/helper/ModelName.test-d.ts} +9 -2
  21. package/{build/helper/ModelName.d.ts → src/helper/ModelName.ts} +5 -1
  22. package/{build/helper/ModelType.test-d.js → src/helper/ModelType.test-d.ts} +18 -3
  23. package/{build/helper/ModelType.d.ts → src/helper/ModelType.ts} +2 -0
  24. package/{build/helper/NullableField.test-d.js → src/helper/NullableField.test-d.ts} +17 -6
  25. package/{build/helper/NullableField.d.ts → src/helper/NullableField.ts} +4 -1
  26. package/{build/helper/OptionalField.test-d.js → src/helper/OptionalField.test-d.ts} +21 -6
  27. package/{build/helper/OptionalField.d.ts → src/helper/OptionalField.ts} +5 -1
  28. package/{build/helper/ProvidedField.test-d.js → src/helper/ProvidedField.test-d.ts} +17 -6
  29. package/{build/helper/ProvidedField.d.ts → src/helper/ProvidedField.ts} +4 -1
  30. package/{build/helper/RelationModel.test-d.js → src/helper/RelationModel.test-d.ts} +27 -6
  31. package/src/helper/RelationModel.ts +9 -0
  32. package/{build/helper/RelationName.test-d.js → src/helper/RelationName.test-d.ts} +14 -4
  33. package/src/helper/RelationName.ts +4 -0
  34. package/{build/helper/RequiredField.test-d.js → src/helper/RequiredField.test-d.ts} +19 -6
  35. package/{build/helper/RequiredField.d.ts → src/helper/RequiredField.ts} +8 -1
  36. package/{build/helper/SerialField.test-d.js → src/helper/SerialField.test-d.ts} +23 -8
  37. package/{build/helper/SerialField.d.ts → src/helper/SerialField.ts} +7 -1
  38. package/{build/index.d.ts → src/index.ts} +8 -1
  39. package/build/Config.js +0 -1
  40. package/build/Logger.js +0 -1
  41. package/build/definition/FieldDefinition.js +0 -1
  42. package/build/definition/ForeignKeyDefinition.js +0 -1
  43. package/build/definition/ModelDefinition.js +0 -1
  44. package/build/definition/ModelDefinitions.js +0 -1
  45. package/build/definition/OperatorDefinitions.js +0 -1
  46. package/build/definition/PostgresDataTypes.js +0 -1
  47. package/build/definition/RelationDefinition.js +0 -1
  48. package/build/definition/RelationDefinitions.js +0 -1
  49. package/build/definition/UniqueConstraintDefinition.js +0 -1
  50. package/build/definition/WhereOperator.d.ts +0 -5
  51. package/build/definition/WhereOperator.js +0 -1
  52. package/build/helper/DefaultFieldType.d.ts +0 -7
  53. package/build/helper/DefaultFieldType.js +0 -1
  54. package/build/helper/DefaultFieldType.test-d.d.ts +0 -1
  55. package/build/helper/DefaultFieldType.test-d.js +0 -57
  56. package/build/helper/FieldName.js +0 -1
  57. package/build/helper/FieldName.test-d.d.ts +0 -1
  58. package/build/helper/FieldType.d.ts +0 -5
  59. package/build/helper/FieldType.js +0 -1
  60. package/build/helper/FieldType.test-d.d.ts +0 -1
  61. package/build/helper/FieldType.test-d.js +0 -45
  62. package/build/helper/FieldWithDefault.js +0 -1
  63. package/build/helper/FieldWithDefault.test-d.d.ts +0 -1
  64. package/build/helper/ModelName.js +0 -1
  65. package/build/helper/ModelName.test-d.d.ts +0 -1
  66. package/build/helper/ModelType.js +0 -1
  67. package/build/helper/ModelType.test-d.d.ts +0 -1
  68. package/build/helper/NullableField.js +0 -1
  69. package/build/helper/NullableField.test-d.d.ts +0 -1
  70. package/build/helper/OptionalField.js +0 -1
  71. package/build/helper/OptionalField.test-d.d.ts +0 -1
  72. package/build/helper/ProvidedField.js +0 -1
  73. package/build/helper/ProvidedField.test-d.d.ts +0 -1
  74. package/build/helper/RelationModel.d.ts +0 -4
  75. package/build/helper/RelationModel.js +0 -1
  76. package/build/helper/RelationModel.test-d.d.ts +0 -1
  77. package/build/helper/RelationName.d.ts +0 -2
  78. package/build/helper/RelationName.js +0 -1
  79. package/build/helper/RelationName.test-d.d.ts +0 -1
  80. package/build/helper/RequiredField.js +0 -1
  81. package/build/helper/RequiredField.test-d.d.ts +0 -1
  82. package/build/helper/SerialField.js +0 -1
  83. package/build/helper/SerialField.test-d.d.ts +0 -1
  84. package/build/index.js +0 -1
  85. /package/{build/Logger.d.ts → src/Logger.ts} +0 -0
  86. /package/{build/definition/ForeignKeyDefinition.d.ts → src/definition/ForeignKeyDefinition.ts} +0 -0
package/package.json CHANGED
@@ -1,41 +1,40 @@
1
1
  {
2
2
  "name": "@casekit/orm2-schema",
3
3
  "description": "",
4
- "version": "0.0.0-20250331202540",
4
+ "version": "0.0.0",
5
5
  "author": "",
6
6
  "dependencies": {
7
- "@casekit/sql": "0.0.0-20250331202540",
8
- "@casekit/toolbox": "0.0.0-20250331202540"
7
+ "@casekit/toolbox": "0.0.0",
8
+ "@casekit/sql": "0.0.0"
9
9
  },
10
10
  "devDependencies": {
11
11
  "@trivago/prettier-plugin-sort-imports": "^5.2.2",
12
- "@types/node": "^22.13.13",
13
- "@types/pg": "^8.11.11",
12
+ "@types/node": "^24.0.3",
13
+ "@types/pg": "^8.15.4",
14
14
  "@types/uuid": "^10.0.0",
15
15
  "prettier": "^3.5.3",
16
- "ts-essentials": "^10.0.4",
17
- "typescript": "^5.8.2",
18
- "typescript-eslint": "^8.28.0",
16
+ "ts-essentials": "^10.1.1",
17
+ "typescript": "^5.8.3",
18
+ "typescript-eslint": "^8.34.1",
19
19
  "vite-tsconfig-paths": "^5.1.4",
20
- "vitest": "^3.0.9",
21
- "@casekit/tsconfig": "0.0.0-20250331202540",
22
- "@casekit/prettier-config": "0.0.0-20250331202540"
20
+ "vitest": "^3.2.4",
21
+ "@casekit/prettier-config": "0.0.0",
22
+ "@casekit/tsconfig": "0.0.0"
23
23
  },
24
24
  "exports": {
25
- ".": "./build/index.js"
25
+ ".": "./src/index.ts"
26
26
  },
27
27
  "files": [
28
- "/build"
28
+ "/src"
29
29
  ],
30
30
  "imports": {
31
- "#*": "./build/*"
31
+ "#*": "./src/*"
32
32
  },
33
33
  "keywords": [],
34
34
  "license": "ISC",
35
- "main": "index.js",
36
35
  "peerDependencies": {
37
36
  "pg": "^8.13.1",
38
- "zod": "^3.24.2"
37
+ "zod": "^4.0.17"
39
38
  },
40
39
  "prettier": "@casekit/prettier-config",
41
40
  "type": "module",
@@ -1,12 +1,19 @@
1
1
  import pg from "pg";
2
- import { ModelDefinitions, OperatorDefinitions } from "@casekit/orm2-schema";
2
+
3
3
  import { Logger } from "./Logger.js";
4
+ import { ModelDefinitions } from "./definition/ModelDefinitions.js";
5
+ import { OperatorDefinitions } from "./definition/OperatorDefinitions.js";
6
+
4
7
  export interface Config {
5
8
  readonly schema?: string;
6
9
  readonly models: ModelDefinitions;
7
10
  readonly operators?: OperatorDefinitions;
8
11
  readonly extensions?: readonly string[];
9
- readonly connection?: pg.ConnectionConfig | pg.PoolConfig | pg.PoolOptions | null;
12
+ readonly connection?:
13
+ | pg.ConnectionConfig
14
+ | pg.PoolConfig
15
+ | pg.PoolOptions
16
+ | null;
10
17
  readonly pool?: boolean;
11
18
  readonly logger?: Logger;
12
19
  readonly naming?: {
@@ -1,6 +1,9 @@
1
1
  import { z } from "zod";
2
+
2
3
  import { SQLStatement } from "@casekit/sql";
4
+
3
5
  import { PostgresDataTypes } from "./PostgresDataTypes.js";
6
+
4
7
  export interface FieldDefinition {
5
8
  /**
6
9
  * The name of the column in the database. If not specified,
@@ -9,10 +12,14 @@ export interface FieldDefinition {
9
12
  * in the config applied.
10
13
  */
11
14
  column?: string;
15
+
12
16
  /**
13
17
  * The postgresql datatype of the column.
14
18
  */
15
- type: `${PostgresDataTypes[keyof PostgresDataTypes]}${string}` | `${Uppercase<PostgresDataTypes[keyof PostgresDataTypes]>}${string}`;
19
+ type:
20
+ | `${PostgresDataTypes[keyof PostgresDataTypes]}${string}` // the string at the end allows for arrays
21
+ | `${Uppercase<PostgresDataTypes[keyof PostgresDataTypes]>}${string}`;
22
+
16
23
  /**
17
24
  * A Zod schema used to infer the type of the column and to
18
25
  * validate/transform data coming from the database.
@@ -21,11 +28,13 @@ export interface FieldDefinition {
21
28
  * allows to you configure more sophisticated parsing, validation,
22
29
  * and transformations.
23
30
  */
24
- zodSchema?: z.ZodType<unknown>;
31
+ zodSchema?: z.ZodType;
32
+
25
33
  /**
26
34
  * Are null values allowed in this column?
27
35
  */
28
36
  nullable?: boolean;
37
+
29
38
  /**
30
39
  * The default value for this column, if it has one. This can be either a value such
31
40
  * as a number or string, or if you want to specify a SQL function for the default,
@@ -42,19 +51,21 @@ export interface FieldDefinition {
42
51
  * default: sql`uuid_generate_v4()`,
43
52
  */
44
53
  default?: unknown;
54
+
45
55
  /**
46
56
  * Is this column unique? If so, you can specify a where clause to
47
57
  * specify a partial unique index, and whether nulls should be considered
48
58
  * distinct.
49
59
  */
50
- unique?: boolean | {
51
- where?: SQLStatement | null;
52
- nullsNotDistinct?: boolean;
53
- };
60
+ unique?:
61
+ | boolean
62
+ | { where?: SQLStatement | null; nullsNotDistinct?: boolean };
63
+
54
64
  /**
55
65
  * Is this column a single-column primary key?
56
66
  */
57
67
  primaryKey?: boolean;
68
+
58
69
  /**
59
70
  * Is this column a foreign key? If so, you can specify the table and column it references,
60
71
  * and what should happen on update or delete.
@@ -66,9 +77,11 @@ export interface FieldDefinition {
66
77
  onUpdate?: "RESTRICT" | "CASCADE" | "SET NULL" | "SET DEFAULT" | null;
67
78
  onDelete?: "RESTRICT" | "CASCADE" | "SET NULL" | "SET DEFAULT" | null;
68
79
  } | null;
80
+
69
81
  /**
70
82
  * Is this column provided by middleware? If so, it will not be included in
71
83
  * the set of required columns for inserts and updates.
72
84
  */
85
+
73
86
  provided?: boolean;
74
87
  }
@@ -2,6 +2,7 @@ import { FieldDefinition } from "./FieldDefinition.js";
2
2
  import { ForeignKeyDefinition } from "./ForeignKeyDefinition.js";
3
3
  import { RelationDefinitions } from "./RelationDefinitions.js";
4
4
  import { UniqueConstraintDefinition } from "./UniqueConstraintDefinition.js";
5
+
5
6
  /**
6
7
  * Configuration object for a database model.
7
8
  */
@@ -12,32 +13,38 @@ export interface ModelDefinition {
12
13
  * config applied.
13
14
  */
14
15
  table?: string;
16
+
15
17
  /**
16
18
  * The schema in which the model sits. If not specified, will use the
17
19
  * schema specified in the global config; if no schema is specified in
18
20
  * the global config, will be set to `public`.
19
21
  */
20
22
  schema?: string;
23
+
21
24
  /**
22
25
  * The model's fields - a map of field name to field
23
26
  * definitions. The keys of this map will be used in generated functions
24
27
  * and object fields, so must be valid Javascript identifiers.
25
28
  */
26
29
  fields: Record<string, FieldDefinition>;
30
+
27
31
  /**
28
32
  * If the table's primary key contains multiple columns, specify them here.
29
33
  * If the primary key is on a single column, you can specify it here or in the column definition.
30
34
  */
31
35
  primaryKey?: string[] | null;
36
+
32
37
  /**
33
38
  * If the table has unique constraints that span multiple columns, you must specify them here.
34
39
  * If the unique constraint is on a single column, you can specify it here or in the column definition.
35
40
  */
36
41
  uniqueConstraints?: UniqueConstraintDefinition[];
42
+
37
43
  /**
38
44
  * If the table has foreign keys, you must specify them here. If the foreign key is on a single column,
39
45
  * you can specify it here or in the column definition.
40
46
  */
41
47
  foreignKeys?: ForeignKeyDefinition[];
48
+
42
49
  relations?: RelationDefinitions;
43
50
  }
@@ -1,2 +1,3 @@
1
1
  import { ModelDefinition } from "./ModelDefinition.js";
2
+
2
3
  export type ModelDefinitions = Record<string, ModelDefinition>;
@@ -1,4 +1,5 @@
1
1
  import { WhereOperatorDefinition } from "./WhereOperator.js";
2
+
2
3
  export type OperatorDefinitions = {
3
4
  where: Record<symbol, WhereOperatorDefinition>;
4
5
  };
@@ -14,6 +14,7 @@ export interface PostgresDataTypes {
14
14
  character_varying: `character varying`;
15
15
  character_varying_n: `character varying (${number})`;
16
16
  cidr: "cidr";
17
+ // circle: "circle";
17
18
  date: "date";
18
19
  daterange: "daterange";
19
20
  double_precision: "double precision";
@@ -22,6 +23,7 @@ export interface PostgresDataTypes {
22
23
  int4range: "int4range";
23
24
  int8range: "int8range";
24
25
  integer: "integer";
26
+ // interval: `interval`;
25
27
  json: "json";
26
28
  jsonb: "jsonb";
27
29
  line: "line";
@@ -35,6 +37,7 @@ export interface PostgresDataTypes {
35
37
  oid: "oid";
36
38
  path: "path";
37
39
  pg_lsn: "pg_lsn";
40
+ // point: "point";
38
41
  polygon: "polygon";
39
42
  real: "real";
40
43
  regclass: "regclass";
@@ -4,6 +4,7 @@ export interface OneToManyRelationDefinition {
4
4
  fromField: string | string[];
5
5
  toField: string | string[];
6
6
  }
7
+
7
8
  export interface ManyToOneRelationDefinition {
8
9
  type: "N:1";
9
10
  model: string;
@@ -11,6 +12,7 @@ export interface ManyToOneRelationDefinition {
11
12
  toField: string | string[];
12
13
  optional?: boolean | null;
13
14
  }
15
+
14
16
  export interface ManyToManyRelationDefinition {
15
17
  type: "N:N";
16
18
  model: string;
@@ -20,4 +22,8 @@ export interface ManyToManyRelationDefinition {
20
22
  toRelation: string;
21
23
  };
22
24
  }
23
- export type RelationDefinition = OneToManyRelationDefinition | ManyToOneRelationDefinition | ManyToManyRelationDefinition;
25
+
26
+ export type RelationDefinition =
27
+ | OneToManyRelationDefinition
28
+ | ManyToOneRelationDefinition
29
+ | ManyToManyRelationDefinition;
@@ -1,2 +1,3 @@
1
1
  import { RelationDefinition } from "./RelationDefinition.js";
2
+
2
3
  export type RelationDefinitions = Record<string, RelationDefinition>;
@@ -1,4 +1,5 @@
1
1
  import { SQLStatement } from "@casekit/sql";
2
+
2
3
  export interface UniqueConstraintDefinition {
3
4
  name?: string;
4
5
  fields: string[];
@@ -0,0 +1,6 @@
1
+ import { SQLStatement } from "@casekit/sql";
2
+
3
+ export type WhereOperatorDefinition = (
4
+ meta: { table: SQLStatement; column: SQLStatement },
5
+ value: unknown,
6
+ ) => SQLStatement;
@@ -0,0 +1,60 @@
1
+ import { expectTypeOf, test } from "vitest";
2
+
3
+ import { DefaultFieldType } from "./DefaultFieldType.js";
4
+
5
+ test("DefaultFieldType", () => {
6
+ expectTypeOf<DefaultFieldType<"bigint">>().toBeBigInt();
7
+ expectTypeOf<DefaultFieldType<"integer">>().toBeNumber();
8
+ expectTypeOf<DefaultFieldType<"double precision">>().toBeNumber();
9
+ expectTypeOf<DefaultFieldType<"oid">>().toBeNumber();
10
+ expectTypeOf<DefaultFieldType<"real">>().toBeNumber();
11
+ expectTypeOf<DefaultFieldType<"smallint">>().toBeNumber();
12
+ expectTypeOf<DefaultFieldType<"smallserial">>().toBeNumber();
13
+ expectTypeOf<DefaultFieldType<"serial">>().toBeNumber();
14
+ expectTypeOf<DefaultFieldType<"text">>().toBeString();
15
+ expectTypeOf<DefaultFieldType<"uuid">>().toBeString();
16
+ expectTypeOf<DefaultFieldType<"bytea">>().toEqualTypeOf<Buffer>();
17
+ // expectTypeOf<DefaultFieldType<"circle">>().toEqualTypeOf<{
18
+ // x: number;
19
+ // y: number;
20
+ // radius: number;
21
+ // }>();
22
+ // expectTypeOf<DefaultFieldType<"point">>().toEqualTypeOf<{
23
+ // x: number;
24
+ // y: number;
25
+ // }>();
26
+ expectTypeOf<DefaultFieldType<"json">>().toBeUnknown();
27
+ expectTypeOf<DefaultFieldType<"jsonb">>().toBeUnknown();
28
+ expectTypeOf<DefaultFieldType<"boolean">>().toBeBoolean();
29
+ expectTypeOf<DefaultFieldType<"date">>().toEqualTypeOf<Date>();
30
+ expectTypeOf<DefaultFieldType<"timestamp">>().toEqualTypeOf<Date>();
31
+ // expectTypeOf<DefaultFieldType<"interval">>().toEqualTypeOf<{
32
+ // years?: number;
33
+ // months?: number;
34
+ // days?: number;
35
+ // hours?: number;
36
+ // minutes?: number;
37
+ // seconds?: number;
38
+ // milliseconds?: number;
39
+ // }>();
40
+ expectTypeOf<DefaultFieldType<"time">>().toEqualTypeOf<string>();
41
+ expectTypeOf<DefaultFieldType<"timetz">>().toEqualTypeOf<string>();
42
+ expectTypeOf<DefaultFieldType<"timestamptz">>().toEqualTypeOf<Date>();
43
+ expectTypeOf<DefaultFieldType<"varchar">>().toBeString();
44
+ expectTypeOf<DefaultFieldType<"char">>().toBeString();
45
+ expectTypeOf<DefaultFieldType<"numeric">>().toBeString();
46
+ expectTypeOf<DefaultFieldType<"decimal">>().toBeString();
47
+ expectTypeOf<DefaultFieldType<"money">>().toBeString();
48
+ expectTypeOf<DefaultFieldType<"bit">>().toBeString();
49
+ expectTypeOf<DefaultFieldType<"box">>().toBeString();
50
+ expectTypeOf<DefaultFieldType<"line">>().toBeString();
51
+ expectTypeOf<DefaultFieldType<"lseg">>().toBeString();
52
+ expectTypeOf<DefaultFieldType<"path">>().toBeString();
53
+ expectTypeOf<DefaultFieldType<"polygon">>().toBeString();
54
+ expectTypeOf<DefaultFieldType<"cidr">>().toBeString();
55
+ expectTypeOf<DefaultFieldType<"inet">>().toBeString();
56
+ expectTypeOf<DefaultFieldType<"macaddr">>().toBeString();
57
+ expectTypeOf<DefaultFieldType<"tsquery">>().toBeString();
58
+ expectTypeOf<DefaultFieldType<"tsvector">>().toBeString();
59
+ expectTypeOf<DefaultFieldType<"xml">>().toBeString();
60
+ });
@@ -0,0 +1,99 @@
1
+ /**
2
+ * WARNING!!! The types in this file must be kept in sync
3
+ * with the zod schemas in packages/orm/src/config/defaultZodSchema.ts.
4
+ * If you make a change here, make sure to update the
5
+ * corresponding zod schema.
6
+ */
7
+ export type DefaultFieldType<DataType extends string> =
8
+ DataType extends `${infer T extends string}[]`
9
+ ? DefaultFieldType<T>[]
10
+ : Uppercase<DataType> extends "BIGINT" | "BIGSERIAL"
11
+ ? bigint
12
+ : Uppercase<DataType> extends
13
+ | "DOUBLE PRECISION"
14
+ | "INTEGER"
15
+ | "OID"
16
+ | "REAL"
17
+ | "SMALLINT"
18
+ | "SMALLSERIAL"
19
+ | "SERIAL"
20
+ ? number
21
+ : Uppercase<DataType> extends
22
+ | "BPCHAR"
23
+ | "BIT"
24
+ | "BOX"
25
+ | "CIDR"
26
+ | "CHAR"
27
+ | "DATERANGE"
28
+ | "DECIMAL"
29
+ | "INET"
30
+ | "INT4RANGE"
31
+ | "INT8RANGE"
32
+ | "INT2VECTOR"
33
+ | "PG_LSN"
34
+ | "REGCLASS"
35
+ | "REGCONFIG"
36
+ | "REGDICTIONARY"
37
+ | "REGNAMESPACE"
38
+ | "REGOPER"
39
+ | "REGOPERATOR"
40
+ | "REGPROC"
41
+ | "REGPROCEDURE"
42
+ | "REGROLE"
43
+ | "REGTYPE"
44
+ | "TID"
45
+ | "XID"
46
+ | "NUMRANGE"
47
+ | "TSRANGE"
48
+ | "TSTZRANGE"
49
+ | "LINE"
50
+ | "LSEG"
51
+ | "MACADDR"
52
+ | "MACADDR8"
53
+ | "MONEY"
54
+ | "PATH"
55
+ | "POLYGON"
56
+ | "TEXT"
57
+ | "TIME"
58
+ | "TIMETZ"
59
+ | "TSQUERY"
60
+ | "TSVECTOR"
61
+ | "TXID_SNAPSHOT"
62
+ | "XML"
63
+ | `BIT${string}`
64
+ | `CHARACTER${string}`
65
+ | `NUMERIC${string}`
66
+ | `TIME ${string}`
67
+ | `TIME(${string})`
68
+ | `VARCHAR`
69
+ | `VARCHAR ${string}`
70
+ ? string
71
+ : Uppercase<DataType> extends "BYTEA"
72
+ ? Buffer
73
+ : // : Uppercase<DataType> extends "CIRCLE"
74
+ // ? { x: number; y: number; radius: number }
75
+ // : Uppercase<DataType> extends "POINT"
76
+ // ? { x: number; y: number }
77
+ Uppercase<DataType> extends "JSON" | "JSONB"
78
+ ? unknown
79
+ : Uppercase<DataType> extends "UUID"
80
+ ? string
81
+ : Uppercase<DataType> extends "BOOLEAN"
82
+ ? boolean
83
+ : Uppercase<DataType> extends
84
+ | "DATE"
85
+ | "TIMESTAMP"
86
+ | "TIMESTAMPTZ"
87
+ | `TIMESTAMP${string}`
88
+ ? Date
89
+ : // : Uppercase<DataType> extends "INTERVAL"
90
+ // ? {
91
+ // years?: number;
92
+ // months?: number;
93
+ // days?: number;
94
+ // hours?: number;
95
+ // minutes?: number;
96
+ // seconds?: number;
97
+ // milliseconds?: number;
98
+ // }
99
+ unknown;
@@ -1,4 +1,8 @@
1
1
  import { describe, expectTypeOf, test } from "vitest";
2
+
3
+ import { ModelDefinition } from "#definition/ModelDefinition.js";
4
+ import { FieldName } from "./FieldName.js";
5
+
2
6
  describe("FieldName", () => {
3
7
  test("it evaluates to a string union of the model's column names", () => {
4
8
  const model = {
@@ -10,7 +14,10 @@ describe("FieldName", () => {
10
14
  email: { type: "text" },
11
15
  type: { type: "text" },
12
16
  },
13
- };
14
- expectTypeOf().toEqualTypeOf();
17
+ } as const satisfies ModelDefinition;
18
+
19
+ expectTypeOf<FieldName<typeof model>>().toEqualTypeOf<
20
+ "id" | "name" | "createdAt" | "dateOfBirth" | "email" | "type"
21
+ >();
15
22
  });
16
23
  });
@@ -1,2 +1,3 @@
1
1
  import { ModelDefinition } from "#definition/ModelDefinition.js";
2
+
2
3
  export type FieldName<Model extends ModelDefinition> = keyof Model["fields"];
@@ -0,0 +1,81 @@
1
+ import { describe, expectTypeOf } from "vitest";
2
+ import { z } from "zod";
3
+
4
+ import type { ModelDefinition } from "#definition/ModelDefinition.js";
5
+ import type { FieldType } from "./FieldType.js";
6
+
7
+ const user = {
8
+ fields: {
9
+ email: {
10
+ type: "text",
11
+ zodSchema: z.email(),
12
+ },
13
+ id: {
14
+ type: "serial",
15
+ },
16
+ age: {
17
+ type: "integer",
18
+ zodSchema: z.number().min(0).max(150),
19
+ },
20
+ tags: {
21
+ type: "text[]",
22
+ zodSchema: z.array(z.string()),
23
+ },
24
+ status: {
25
+ type: "text",
26
+ zodSchema: z.enum(["active", "inactive", "pending"]),
27
+ },
28
+ createdAt: {
29
+ type: "timestamp with time zone",
30
+ },
31
+ deletedAt: {
32
+ type: "timestamp with time zone",
33
+ zodSchema: z.date().nullable(),
34
+ },
35
+ metadata: {
36
+ type: "jsonb",
37
+ default: "{}",
38
+ zodSchema: z.object({
39
+ foo: z.enum(["a", "b", "c"]),
40
+ bar: z.array(
41
+ z.object({
42
+ baz: z.enum(["good", "bad", "indifferent"]),
43
+ quux: z.boolean(),
44
+ }),
45
+ ),
46
+ }),
47
+ },
48
+ },
49
+ } as const satisfies ModelDefinition;
50
+
51
+ type UserModel = typeof user;
52
+
53
+ describe("FieldType", () => {
54
+ describe("json field", () => {
55
+ expectTypeOf<FieldType<UserModel, "metadata">>().toEqualTypeOf<{
56
+ foo: "a" | "b" | "c";
57
+ bar: { baz: "good" | "bad" | "indifferent"; quux: boolean }[];
58
+ }>();
59
+ });
60
+
61
+ describe("fields with Zod schemas", () => {
62
+ expectTypeOf<FieldType<UserModel, "email">>().toBeString();
63
+
64
+ expectTypeOf<FieldType<UserModel, "age">>().toBeNumber();
65
+
66
+ expectTypeOf<FieldType<UserModel, "tags">>().toEqualTypeOf<string[]>();
67
+
68
+ expectTypeOf<FieldType<UserModel, "status">>().toEqualTypeOf<
69
+ "active" | "inactive" | "pending"
70
+ >();
71
+
72
+ expectTypeOf<
73
+ FieldType<UserModel, "deletedAt">
74
+ >().toEqualTypeOf<Date | null>();
75
+ });
76
+
77
+ describe("fields without Zod schemas (using DefaultFieldType)", () => {
78
+ expectTypeOf<FieldType<UserModel, "id">>().toBeNumber();
79
+ expectTypeOf<FieldType<UserModel, "createdAt">>().toEqualTypeOf<Date>();
80
+ });
81
+ });
@@ -0,0 +1,16 @@
1
+ import { z } from "zod";
2
+
3
+ import { ModelDefinition } from "#definition/ModelDefinition.js";
4
+ import { DefaultFieldType } from "./DefaultFieldType.js";
5
+ import { FieldName } from "./FieldName.js";
6
+
7
+ export type FieldType<
8
+ Model extends ModelDefinition,
9
+ C extends FieldName<Model>,
10
+ > = Model["fields"][C]["zodSchema"] extends z.ZodType
11
+ ?
12
+ | z.infer<Model["fields"][C]["zodSchema"]>
13
+ | (Model["fields"][C]["nullable"] extends true ? null : never)
14
+ :
15
+ | DefaultFieldType<Model["fields"][C]["type"]>
16
+ | (Model["fields"][C]["nullable"] extends true ? null : never);
@@ -1,4 +1,8 @@
1
1
  import { describe, expectTypeOf, test } from "vitest";
2
+
3
+ import type { ModelDefinition } from "../definition/ModelDefinition.js";
4
+ import type { FieldWithDefault } from "./FieldWithDefault.js";
5
+
2
6
  describe("FieldWithDefault", () => {
3
7
  test("extracts just the fields with a default value from the model", () => {
4
8
  const user = {
@@ -8,9 +12,13 @@ describe("FieldWithDefault", () => {
8
12
  age: { type: "integer", default: 18 },
9
13
  email: { type: "text", default: null },
10
14
  },
11
- };
12
- expectTypeOf().toEqualTypeOf();
15
+ } as const satisfies ModelDefinition;
16
+
17
+ expectTypeOf<FieldWithDefault<typeof user>>().toEqualTypeOf<
18
+ "name" | "age"
19
+ >();
13
20
  });
21
+
14
22
  test("returns never if there are no fields with defaults", () => {
15
23
  const user = {
16
24
  fields: {
@@ -18,9 +26,11 @@ describe("FieldWithDefault", () => {
18
26
  name: { type: "text" },
19
27
  age: { type: "integer" },
20
28
  },
21
- };
22
- expectTypeOf().toEqualTypeOf();
29
+ } as const satisfies ModelDefinition;
30
+
31
+ expectTypeOf<FieldWithDefault<typeof user>>().toEqualTypeOf<never>();
23
32
  });
33
+
24
34
  test("excludes fields with null or undefined defaults", () => {
25
35
  const user = {
26
36
  fields: {
@@ -29,7 +39,8 @@ describe("FieldWithDefault", () => {
29
39
  email: { type: "text", default: null },
30
40
  phone: { type: "text", default: undefined },
31
41
  },
32
- };
33
- expectTypeOf().toEqualTypeOf();
42
+ } as const satisfies ModelDefinition;
43
+
44
+ expectTypeOf<FieldWithDefault<typeof user>>().toEqualTypeOf<"name">();
34
45
  });
35
46
  });
@@ -1,4 +1,9 @@
1
1
  import { ModelDefinition } from "../definition/ModelDefinition.js";
2
+
2
3
  export type FieldWithDefault<Model extends ModelDefinition> = {
3
- [K in keyof Model["fields"]]: Model["fields"][K]["default"] extends NonNullable<Model["fields"][K]["default"]> ? K : never;
4
+ [K in keyof Model["fields"]]: Model["fields"][K]["default"] extends NonNullable<
5
+ Model["fields"][K]["default"]
6
+ >
7
+ ? K
8
+ : never;
4
9
  }[keyof Model["fields"]];
@@ -1,4 +1,8 @@
1
1
  import { describe, expectTypeOf, test } from "vitest";
2
+
3
+ import { ModelDefinitions } from "../definition/ModelDefinitions.js";
4
+ import { ModelName } from "./ModelName.js";
5
+
2
6
  describe("ModelName", () => {
3
7
  test("it evaluates to a string union of the names of the models", () => {
4
8
  const models = {
@@ -8,7 +12,10 @@ describe("ModelName", () => {
8
12
  comment: { fields: {} },
9
13
  mention: { fields: {} },
10
14
  color: { fields: {} },
11
- };
12
- expectTypeOf().toEqualTypeOf();
15
+ } as const satisfies ModelDefinitions;
16
+
17
+ expectTypeOf<ModelName<typeof models>>().toEqualTypeOf<
18
+ "user" | "post" | "like" | "comment" | "mention" | "color"
19
+ >();
13
20
  });
14
21
  });