@zeno-lib/schema 0.2.1 → 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/index.d.mts +4 -2
- package/package.json +15 -15
- package/src/index.test-d.ts +28 -4
- package/src/index.test.ts +19 -0
- package/src/index.ts +42 -5
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { InferInsertModel, InferSelectModel, Table } from "drizzle-orm";
|
|
1
|
+
import { Column, InferInsertModel, InferSelectModel, Table } from "drizzle-orm";
|
|
2
2
|
import { BuildRefine, BuildSchema, CoerceOptions, CreateSchemaFactoryOptions, NoUnknownKeys, createInsertSchema, createSchemaFactory, createSelectSchema, createUpdateSchema } from "drizzle-orm/zod";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
//#region src/index.d.ts
|
|
@@ -21,8 +21,10 @@ type DefineTableSchemaOptions<TTable extends Table, TCoerce extends CoerceOption
|
|
|
21
21
|
};
|
|
22
22
|
type RefineFromOptions<TOptions, TKey extends string> = TKey extends keyof TOptions ? NonNullable<TOptions[TKey]> extends Record<string, unknown> ? NonNullable<TOptions[TKey]> : undefined : undefined;
|
|
23
23
|
type OmitKeys<TSchema, TKeys extends PropertyKey> = TSchema extends z.ZodObject<infer TShape, infer TConfig> ? z.ZodObject<{ [K in keyof TShape as K extends TKeys ? never : K]: TShape[K]; }, TConfig> : never;
|
|
24
|
+
type IsInsertOptional<TColumn> = TColumn extends Column ? TColumn["_"]["notNull"] extends true ? TColumn["_"]["hasDefault"] extends true ? true : false : true : false;
|
|
25
|
+
type OptionalRefinedInsert<TSchema, TTable extends Table, TRefine> = TSchema extends z.ZodObject<infer TShape, infer TConfig> ? z.ZodObject<{ [K in keyof TShape]: K extends keyof TRefine ? TRefine[K] extends ((schema: never) => unknown) ? (K extends keyof TableColumns<TTable> ? IsInsertOptional<TableColumns<TTable>[K]> : false) extends true ? TShape[K] extends z.ZodOptional ? TShape[K] : z.ZodOptional<TShape[K]> : TShape[K] : TShape[K] : TShape[K]; }, TConfig> : never;
|
|
24
26
|
type DefineTableSchemaResult<TTable extends Table, TCoerce extends CoerceOptions, TOptions> = {
|
|
25
|
-
insert: OmitKeys<BuildSchema<"insert", TableColumns<TTable>, RefineFromOptions<TOptions, "insert">, TCoerce>, AuditKeys<TTable>>;
|
|
27
|
+
insert: OmitKeys<OptionalRefinedInsert<BuildSchema<"insert", TableColumns<TTable>, RefineFromOptions<TOptions, "insert">, TCoerce>, TTable, RefineFromOptions<TOptions, "insert">>, AuditKeys<TTable>>;
|
|
26
28
|
select: BuildSchema<"select", TableColumns<TTable>, RefineFromOptions<TOptions, "select">, TCoerce>;
|
|
27
29
|
update: OmitKeys<BuildSchema<"update", TableColumns<TTable>, RefineFromOptions<TOptions, "update">, TCoerce>, AuditKeys<TTable>>;
|
|
28
30
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zeno-lib/schema",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"repository": {
|
|
5
|
+
"url": "https://github.com/zeno-lib/zeno.git",
|
|
6
|
+
"directory": "packages/schema"
|
|
7
|
+
},
|
|
4
8
|
"type": "module",
|
|
5
9
|
"exports": {
|
|
6
10
|
".": {
|
|
@@ -13,24 +17,20 @@
|
|
|
13
17
|
"dist",
|
|
14
18
|
"src"
|
|
15
19
|
],
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
"
|
|
21
|
-
"
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@zeno-lib/typescript": "^1.1.0",
|
|
22
|
+
"drizzle-orm": "1.0.0-rc.5-5935859",
|
|
23
|
+
"tsdown": "^0.23.0",
|
|
24
|
+
"typescript": "7.0.2",
|
|
25
|
+
"vitest": "5.0.3",
|
|
26
|
+
"zod": "^4.6.5"
|
|
22
27
|
},
|
|
23
28
|
"peerDependencies": {
|
|
24
|
-
"drizzle-orm": "1.0.0-rc.
|
|
29
|
+
"drizzle-orm": "1.0.0-rc.5-5935859",
|
|
25
30
|
"zod": ">=4"
|
|
26
31
|
},
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"tsdown": "^0.22.14",
|
|
30
|
-
"typescript": "7.0.2",
|
|
31
|
-
"vitest": "4.1.11",
|
|
32
|
-
"zod": "^4.4.3",
|
|
33
|
-
"@zeno-lib/typescript": "^1.1.0"
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public"
|
|
34
34
|
},
|
|
35
35
|
"scripts": {
|
|
36
36
|
"build": "tsdown",
|
package/src/index.test-d.ts
CHANGED
|
@@ -12,11 +12,9 @@ type StandardSchema<T> = {
|
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
function acceptsFormsSchema<TFormData>(
|
|
15
|
+
declare function acceptsFormsSchema<TFormData>(
|
|
16
16
|
_schema: StandardSchema<TFormData>
|
|
17
|
-
): void
|
|
18
|
-
return
|
|
19
|
-
}
|
|
17
|
+
): void
|
|
20
18
|
|
|
21
19
|
const posts = pgTable("posts", {
|
|
22
20
|
id: integer("id").primaryKey().generatedAlwaysAsIdentity(),
|
|
@@ -80,3 +78,29 @@ test("defaulted audit columns leave the insert and update types", () => {
|
|
|
80
78
|
insert: { createdBy: (schema) => schema },
|
|
81
79
|
})
|
|
82
80
|
})
|
|
81
|
+
|
|
82
|
+
test("a function refinement keeps a nullable or defaulted insert column optional", () => {
|
|
83
|
+
const drafts = pgTable("drafts", {
|
|
84
|
+
note: text("note"),
|
|
85
|
+
status: text("status").notNull().default("open"),
|
|
86
|
+
title: text("title").notNull(),
|
|
87
|
+
})
|
|
88
|
+
const schemas = defineTableSchema(drafts, {
|
|
89
|
+
insert: {
|
|
90
|
+
note: (schema) => schema.min(1),
|
|
91
|
+
status: (schema) => schema.min(1),
|
|
92
|
+
title: (schema) => schema.min(1),
|
|
93
|
+
},
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
expectTypeOf<z.infer<typeof schemas.insert>>().toEqualTypeOf<{
|
|
97
|
+
note?: string | null | undefined
|
|
98
|
+
status?: string | undefined
|
|
99
|
+
title: string
|
|
100
|
+
}>()
|
|
101
|
+
expectTypeOf<z.input<typeof schemas.insert>>().toEqualTypeOf<{
|
|
102
|
+
note?: string | null | undefined
|
|
103
|
+
status?: string | undefined
|
|
104
|
+
title: string
|
|
105
|
+
}>()
|
|
106
|
+
})
|
package/src/index.test.ts
CHANGED
|
@@ -210,4 +210,23 @@ describe("defineTableSchema", () => {
|
|
|
210
210
|
expect(schemas.insert.safeParse({ id: 11 }).success).toBe(false)
|
|
211
211
|
expect(schemas.insert.safeParse({ id: 5 }).success).toBe(true)
|
|
212
212
|
})
|
|
213
|
+
|
|
214
|
+
it("keeps a function-refined nullable insert column optional", () => {
|
|
215
|
+
const drafts = pgTable("drafts", {
|
|
216
|
+
note: text("note"),
|
|
217
|
+
title: text("title").notNull(),
|
|
218
|
+
})
|
|
219
|
+
const schemas = defineTableSchema(drafts, {
|
|
220
|
+
insert: { note: (schema) => schema.min(1) },
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
expect(schemas.insert.parse({ title: "x" })).toEqual({ title: "x" })
|
|
224
|
+
expect(schemas.insert.parse({ note: null, title: "x" })).toEqual({
|
|
225
|
+
note: null,
|
|
226
|
+
title: "x",
|
|
227
|
+
})
|
|
228
|
+
expect(schemas.insert.safeParse({ note: "", title: "x" }).success).toBe(
|
|
229
|
+
false
|
|
230
|
+
)
|
|
231
|
+
})
|
|
213
232
|
})
|
package/src/index.ts
CHANGED
|
@@ -99,17 +99,54 @@ type OmitKeys<TSchema, TKeys extends PropertyKey> =
|
|
|
99
99
|
>
|
|
100
100
|
: never
|
|
101
101
|
|
|
102
|
+
// Drizzle types a function refinement on an insert column as required, even
|
|
103
|
+
// when the column is nullable or defaulted and the runtime wraps it in
|
|
104
|
+
// `.optional()`. This puts the wrapper back into the type.
|
|
105
|
+
type IsInsertOptional<TColumn> = TColumn extends Column
|
|
106
|
+
? TColumn["_"]["notNull"] extends true
|
|
107
|
+
? TColumn["_"]["hasDefault"] extends true
|
|
108
|
+
? true
|
|
109
|
+
: false
|
|
110
|
+
: true
|
|
111
|
+
: false
|
|
112
|
+
|
|
113
|
+
type OptionalRefinedInsert<TSchema, TTable extends Table, TRefine> =
|
|
114
|
+
TSchema extends z.ZodObject<infer TShape, infer TConfig>
|
|
115
|
+
? z.ZodObject<
|
|
116
|
+
{
|
|
117
|
+
[K in keyof TShape]: K extends keyof TRefine
|
|
118
|
+
? TRefine[K] extends (schema: never) => unknown
|
|
119
|
+
? (
|
|
120
|
+
K extends keyof TableColumns<TTable>
|
|
121
|
+
? IsInsertOptional<TableColumns<TTable>[K]>
|
|
122
|
+
: false
|
|
123
|
+
) extends true
|
|
124
|
+
? TShape[K] extends z.ZodOptional
|
|
125
|
+
? TShape[K]
|
|
126
|
+
: z.ZodOptional<TShape[K]>
|
|
127
|
+
: TShape[K]
|
|
128
|
+
: TShape[K]
|
|
129
|
+
: TShape[K]
|
|
130
|
+
},
|
|
131
|
+
TConfig
|
|
132
|
+
>
|
|
133
|
+
: never
|
|
134
|
+
|
|
102
135
|
type DefineTableSchemaResult<
|
|
103
136
|
TTable extends Table,
|
|
104
137
|
TCoerce extends CoerceOptions,
|
|
105
138
|
TOptions,
|
|
106
139
|
> = {
|
|
107
140
|
insert: OmitKeys<
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
141
|
+
OptionalRefinedInsert<
|
|
142
|
+
BuildSchema<
|
|
143
|
+
"insert",
|
|
144
|
+
TableColumns<TTable>,
|
|
145
|
+
RefineFromOptions<TOptions, "insert">,
|
|
146
|
+
TCoerce
|
|
147
|
+
>,
|
|
148
|
+
TTable,
|
|
149
|
+
RefineFromOptions<TOptions, "insert">
|
|
113
150
|
>,
|
|
114
151
|
AuditKeys<TTable>
|
|
115
152
|
>
|