surreal-zod 0.0.0-alpha.11 → 0.0.0-alpha.13
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.d.ts +4 -3
- package/lib/index.js +4 -3
- package/lib/registries.d.ts +7 -0
- package/lib/registries.js +5 -0
- package/lib/surql.d.ts +34 -17
- package/lib/surql.js +661 -265
- package/lib/zod/core.d.ts +257 -0
- package/lib/zod/core.js +10 -0
- package/lib/zod/external.d.ts +2 -0
- package/lib/zod/external.js +2 -0
- package/lib/zod/index.d.ts +3 -0
- package/lib/zod/index.js +3 -0
- package/lib/zod/json-schema.d.ts +89 -0
- package/lib/zod/json-schema.js +628 -0
- package/lib/zod/original.d.ts +2 -0
- package/lib/zod/original.js +177 -0
- package/lib/zod/parse.d.ts +71 -0
- package/lib/zod/parse.js +17 -0
- package/lib/zod/schema.d.ts +1798 -233
- package/lib/zod/schema.js +2254 -278
- package/lib/zod/utils.d.ts +3 -2
- package/lib/zod/utils.js +0 -2
- package/package.json +6 -8
- package/src/index.ts +4 -3
- package/src/registries.ts +9 -0
- package/src/surql.ts +768 -324
- package/src/zod/core.ts +596 -0
- package/src/zod/external.ts +8 -0
- package/src/zod/index.ts +3 -0
- package/src/zod/json-schema.ts +891 -0
- package/src/zod/original.ts +369 -0
- package/src/zod/parse.ts +138 -0
- package/src/zod/schema.ts +7098 -984
- package/src/zod/utils.ts +15 -5
package/src/surql.ts
CHANGED
|
@@ -2,28 +2,17 @@ import {
|
|
|
2
2
|
BoundQuery,
|
|
3
3
|
escapeIdent,
|
|
4
4
|
escapeIdPart,
|
|
5
|
-
RecordId,
|
|
6
5
|
surql,
|
|
7
6
|
Table,
|
|
7
|
+
toSurqlString as baseToSurqlString,
|
|
8
8
|
} from "surrealdb";
|
|
9
|
-
import * as
|
|
10
|
-
import
|
|
9
|
+
import * as core from "zod/v4/core";
|
|
10
|
+
import * as _schema_ from "./zod/schema";
|
|
11
|
+
import * as _core_ from "./zod/core";
|
|
11
12
|
import dedent from "dedent";
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
SurrealZodObject,
|
|
16
|
-
SurrealZodOptional,
|
|
17
|
-
SurrealZodRecordId,
|
|
18
|
-
SurrealZodTable,
|
|
19
|
-
SurrealZodTableNormal,
|
|
20
|
-
SurrealZodTableRelation,
|
|
21
|
-
SurrealZodType,
|
|
22
|
-
SurrealZodTypes,
|
|
23
|
-
} from "./zod/schema";
|
|
24
|
-
|
|
25
|
-
export type ZodTypeName = z4.$ZodType["_zod"]["def"]["type"];
|
|
26
|
-
export type SurrealZodTypeName = SurrealZodType["_zod"]["def"]["type"];
|
|
13
|
+
|
|
14
|
+
const OPEN_ISSUE_FOR_SUPPORT =
|
|
15
|
+
" If you need this, please open an issue on the repository so we can look into your use case and possible implementation. https://github.com/msanchezdev/surreal-zod/issues";
|
|
27
16
|
|
|
28
17
|
/////////////////////////////////////
|
|
29
18
|
/////////////////////////////////////
|
|
@@ -34,25 +23,25 @@ export type SurrealZodTypeName = SurrealZodType["_zod"]["def"]["type"];
|
|
|
34
23
|
/////////////////////////////////////
|
|
35
24
|
|
|
36
25
|
export function tableToSurql(
|
|
37
|
-
table:
|
|
26
|
+
table: _schema_.ZodSurrealTable,
|
|
38
27
|
statement: "define",
|
|
39
28
|
defineOptions?: DefineTableOptions,
|
|
40
29
|
): BoundQuery<[undefined]>;
|
|
41
30
|
export function tableToSurql(
|
|
42
|
-
table:
|
|
31
|
+
table: _schema_.ZodSurrealTable,
|
|
43
32
|
statement: "remove",
|
|
44
33
|
removeOptions?: RemoveTableOptions,
|
|
45
34
|
): BoundQuery<[undefined]>;
|
|
46
35
|
export function tableToSurql(
|
|
47
|
-
table:
|
|
36
|
+
table: _schema_.ZodSurrealTable,
|
|
48
37
|
statement: "info",
|
|
49
38
|
): BoundQuery<[TableInfo]>;
|
|
50
39
|
export function tableToSurql(
|
|
51
|
-
table:
|
|
40
|
+
table: _schema_.ZodSurrealTable,
|
|
52
41
|
statement: "structure",
|
|
53
42
|
): BoundQuery<[TableStructure]>;
|
|
54
43
|
export function tableToSurql(
|
|
55
|
-
table:
|
|
44
|
+
table: _schema_.ZodSurrealTable,
|
|
56
45
|
statement: "define" | "info" | "structure" | "remove",
|
|
57
46
|
options?: DefineTableOptions | RemoveTableOptions,
|
|
58
47
|
): BoundQuery<[TableInfo | TableStructure]> {
|
|
@@ -82,7 +71,7 @@ export type RemoveTableOptions = {
|
|
|
82
71
|
};
|
|
83
72
|
|
|
84
73
|
export function removeTable(
|
|
85
|
-
table:
|
|
74
|
+
table: _schema_.ZodSurrealTable,
|
|
86
75
|
options?: RemoveTableOptions,
|
|
87
76
|
): BoundQuery<[undefined]> {
|
|
88
77
|
const name = table._zod.def.name;
|
|
@@ -104,7 +93,9 @@ export interface TableInfo {
|
|
|
104
93
|
tables: Record<string, string>;
|
|
105
94
|
}
|
|
106
95
|
|
|
107
|
-
export function infoTable(
|
|
96
|
+
export function infoTable(
|
|
97
|
+
table: _schema_.ZodSurrealTable,
|
|
98
|
+
): BoundQuery<[TableInfo]> {
|
|
108
99
|
const name = table._zod.def.name;
|
|
109
100
|
const query = surql`INFO FOR TABLE`;
|
|
110
101
|
query.append(` ${escapeIdent(name)}`);
|
|
@@ -133,7 +124,7 @@ export interface FieldStructure {
|
|
|
133
124
|
}
|
|
134
125
|
|
|
135
126
|
export function structureTable(
|
|
136
|
-
table:
|
|
127
|
+
table: _schema_.ZodSurrealTable,
|
|
137
128
|
): BoundQuery<[TableStructure]> {
|
|
138
129
|
const name = table._zod.def.name;
|
|
139
130
|
const query = surql`INFO FOR TABLE`;
|
|
@@ -148,7 +139,7 @@ export type DefineTableOptions = {
|
|
|
148
139
|
};
|
|
149
140
|
|
|
150
141
|
export function defineTable(
|
|
151
|
-
schema:
|
|
142
|
+
schema: _schema_.ZodSurrealTable,
|
|
152
143
|
options?: DefineTableOptions,
|
|
153
144
|
): BoundQuery<[undefined, ...undefined[]]> {
|
|
154
145
|
const def = schema._zod.def;
|
|
@@ -194,17 +185,45 @@ export function defineTable(
|
|
|
194
185
|
query.append(";\n");
|
|
195
186
|
|
|
196
187
|
if (options?.fields) {
|
|
197
|
-
for (const [fieldName, fieldSchema] of Object.entries(def.fields)
|
|
188
|
+
for (const [fieldName, fieldSchema] of Object.entries(def.fields) as [
|
|
189
|
+
string,
|
|
190
|
+
_core_.$ZodSurrealType,
|
|
191
|
+
][]) {
|
|
192
|
+
let defaultValue: DefineFieldOptions["default"];
|
|
193
|
+
let comment: DefineFieldOptions["comment"];
|
|
194
|
+
let readonly: DefineFieldOptions["readonly"];
|
|
195
|
+
let assert: DefineFieldOptions["assert"];
|
|
196
|
+
let value: DefineFieldOptions["value"];
|
|
197
|
+
if (fieldSchema instanceof _schema_.ZodSurrealField) {
|
|
198
|
+
defaultValue = fieldSchema._zod.def.surreal.field?.default;
|
|
199
|
+
comment = fieldSchema._zod.def.surreal.field?.comment;
|
|
200
|
+
readonly = fieldSchema._zod.def.surreal.field?.readonly;
|
|
201
|
+
assert = fieldSchema._zod.def.surreal.field?.assert;
|
|
202
|
+
value = fieldSchema._zod.def.surreal.field?.value;
|
|
203
|
+
}
|
|
204
|
+
|
|
198
205
|
query.append(
|
|
199
206
|
defineField(
|
|
200
207
|
fieldName,
|
|
201
208
|
table.name,
|
|
202
209
|
fieldName === "id"
|
|
203
|
-
? (fieldSchema as
|
|
210
|
+
? (fieldSchema as _schema_.ZodSurrealdRecordId)._zod.def.innerType
|
|
204
211
|
: fieldSchema,
|
|
205
212
|
{
|
|
206
213
|
exists: options.exists,
|
|
207
214
|
schemafull: surreal.schemafull,
|
|
215
|
+
default: defaultValue,
|
|
216
|
+
comment,
|
|
217
|
+
readonly,
|
|
218
|
+
assert,
|
|
219
|
+
value,
|
|
220
|
+
// @ts-expect-error - @internal
|
|
221
|
+
// We need to add the table schema to the fullParents set to avoid
|
|
222
|
+
// infinite recursion. Child fields keep a separate context from
|
|
223
|
+
// the table or other fields.
|
|
224
|
+
// The resting point for fullParents is in the inferSurrealType function,
|
|
225
|
+
// on the switch case for the "lazy" type.
|
|
226
|
+
fullParents: new Set([schema]),
|
|
208
227
|
},
|
|
209
228
|
),
|
|
210
229
|
);
|
|
@@ -214,19 +233,23 @@ export function defineTable(
|
|
|
214
233
|
return query;
|
|
215
234
|
}
|
|
216
235
|
|
|
217
|
-
export function isNormalTable(
|
|
218
|
-
table: SurrealZodTable,
|
|
219
|
-
): table is SurrealZodTableNormal {
|
|
220
|
-
return table._zod.def.surreal.tableType === "normal";
|
|
221
|
-
}
|
|
222
|
-
|
|
223
236
|
export function isRelationTable(
|
|
224
|
-
table:
|
|
225
|
-
): table is
|
|
226
|
-
|
|
237
|
+
table: unknown,
|
|
238
|
+
): table is _schema_.ZodSurrealTable<
|
|
239
|
+
string,
|
|
240
|
+
{
|
|
241
|
+
[K in "in" | "out" | "id"]: _schema_.ZodSurrealdRecordId;
|
|
242
|
+
},
|
|
243
|
+
_schema_.SurrealZodTableConfig,
|
|
244
|
+
"relation"
|
|
245
|
+
> {
|
|
246
|
+
return (
|
|
247
|
+
table instanceof _schema_.ZodSurrealTable &&
|
|
248
|
+
table._zod.def.surreal.tableType === "relation"
|
|
249
|
+
);
|
|
227
250
|
}
|
|
228
251
|
|
|
229
|
-
export interface ZodToSurqlOptions<S extends
|
|
252
|
+
export interface ZodToSurqlOptions<S extends _schema_.ZodSurrealObject> {
|
|
230
253
|
table: string | Table;
|
|
231
254
|
schemafull?: boolean;
|
|
232
255
|
exists?: "ignore" | "error" | "overwrite";
|
|
@@ -238,22 +261,25 @@ export interface ZodToSurqlOptions<S extends z4.$ZodObject> {
|
|
|
238
261
|
export type DefineFieldOptions = {
|
|
239
262
|
exists?: "ignore" | "error" | "overwrite";
|
|
240
263
|
schemafull?: boolean;
|
|
264
|
+
default?: {
|
|
265
|
+
value: BoundQuery;
|
|
266
|
+
always?: boolean;
|
|
267
|
+
prase?: boolean;
|
|
268
|
+
};
|
|
269
|
+
comment?: string;
|
|
270
|
+
readonly?: boolean;
|
|
271
|
+
assert?: BoundQuery;
|
|
272
|
+
value?: BoundQuery;
|
|
273
|
+
// @internal
|
|
274
|
+
// fullParents?: Set<core.$ZodType>;
|
|
241
275
|
};
|
|
242
276
|
|
|
243
|
-
function defineField(
|
|
277
|
+
export function defineField(
|
|
244
278
|
name: string,
|
|
245
279
|
table: string,
|
|
246
|
-
schema:
|
|
280
|
+
schema: _core_.$ZodSurrealType,
|
|
247
281
|
options?: DefineFieldOptions,
|
|
248
282
|
) {
|
|
249
|
-
// const context: ZodSurrealTypeContext = {
|
|
250
|
-
// name,
|
|
251
|
-
// table,
|
|
252
|
-
// rootSchema: schema,
|
|
253
|
-
// children: [],
|
|
254
|
-
// asserts: [],
|
|
255
|
-
// transforms: [],
|
|
256
|
-
// };
|
|
257
283
|
const query = surql`DEFINE FIELD`;
|
|
258
284
|
|
|
259
285
|
if (options?.exists === "ignore") {
|
|
@@ -267,26 +293,45 @@ function defineField(
|
|
|
267
293
|
const context: ZodSurrealTypeContext = {
|
|
268
294
|
type: new Set(),
|
|
269
295
|
depth: 0,
|
|
296
|
+
parents: new Set(),
|
|
297
|
+
// @ts-expect-error - @internal
|
|
298
|
+
fullParents: options?.fullParents ?? new Set(),
|
|
270
299
|
children: [],
|
|
271
300
|
flexible: false,
|
|
272
301
|
};
|
|
273
|
-
query.append(` TYPE ${inferSurrealType(schema, context)}`);
|
|
302
|
+
query.append(` TYPE ${inferSurrealType(schema, context).type}`);
|
|
274
303
|
if (options?.schemafull && context.flexible) {
|
|
275
304
|
query.append(" FLEXIBLE");
|
|
276
305
|
}
|
|
277
306
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
// query.append(" OVERWRITE");
|
|
282
|
-
// }
|
|
307
|
+
if (options?.readonly) {
|
|
308
|
+
query.append(" READONLY");
|
|
309
|
+
}
|
|
283
310
|
|
|
284
|
-
|
|
311
|
+
if (options?.default) {
|
|
312
|
+
query.append(
|
|
313
|
+
options.default.always
|
|
314
|
+
? ` DEFAULT ALWAYS ${formatQuery(inlineQueryParameters(options.default.value))}`
|
|
315
|
+
: ` DEFAULT ${formatQuery(inlineQueryParameters(options.default.value))}`,
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
if (options?.value) {
|
|
320
|
+
query.append(` VALUE ${inlineQueryParameters(options.value)}`);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
if (options?.assert) {
|
|
324
|
+
query.append(` ASSERT ${inlineQueryParameters(options.assert)}`);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
if (options?.comment) {
|
|
328
|
+
query.append(` COMMENT ${JSON.stringify(options.comment)}`);
|
|
329
|
+
}
|
|
285
330
|
|
|
286
331
|
// const type =
|
|
287
332
|
// name === "id"
|
|
288
333
|
// ? inferSurrealType(
|
|
289
|
-
// (schema as unknown as
|
|
334
|
+
// (schema as unknown as ZodSurrealRecordId)._zod.def.innerType,
|
|
290
335
|
// [],
|
|
291
336
|
// context,
|
|
292
337
|
// )
|
|
@@ -329,14 +374,17 @@ function defineField(
|
|
|
329
374
|
query.append(`;\n`);
|
|
330
375
|
|
|
331
376
|
if (context.children.length > 0) {
|
|
377
|
+
context.fullParents.add(schema);
|
|
332
378
|
for (const { name: childName, type: childType } of context.children) {
|
|
333
379
|
query.append(
|
|
334
380
|
defineField(
|
|
335
|
-
`${escapeIdent(name)}.${escapeIdent(childName)}`,
|
|
381
|
+
`${escapeIdent(name)}.${childName === "*" ? childName : escapeIdent(childName)}`,
|
|
336
382
|
table,
|
|
337
|
-
childType as
|
|
383
|
+
childType as _core_.$ZodSurrealType,
|
|
338
384
|
{
|
|
339
385
|
exists: options?.exists,
|
|
386
|
+
// @ts-expect-error - @internal
|
|
387
|
+
fullParents: context.fullParents,
|
|
340
388
|
},
|
|
341
389
|
),
|
|
342
390
|
);
|
|
@@ -355,304 +403,700 @@ type ZodSurrealTypeContext = {
|
|
|
355
403
|
// transforms: string[];
|
|
356
404
|
// default?: { value: any; always: boolean };
|
|
357
405
|
type: Set<string>;
|
|
406
|
+
parents: Set<_core_.$ZodSurrealType>;
|
|
407
|
+
fullParents: Set<_core_.$ZodSurrealType>;
|
|
358
408
|
depth: number;
|
|
359
409
|
children: ZodSurrealChildType[];
|
|
360
410
|
flexible: boolean;
|
|
361
411
|
};
|
|
362
|
-
type ZodSurrealChildType = { name: string; type:
|
|
412
|
+
type ZodSurrealChildType = { name: string; type: core.$ZodType };
|
|
413
|
+
|
|
414
|
+
function createContext(
|
|
415
|
+
override?: Partial<ZodSurrealTypeContext>,
|
|
416
|
+
): ZodSurrealTypeContext {
|
|
417
|
+
return {
|
|
418
|
+
type: new Set<string>(),
|
|
419
|
+
depth: 0,
|
|
420
|
+
parents: new Set<_core_.$ZodSurrealType>(),
|
|
421
|
+
fullParents: new Set<_core_.$ZodSurrealType>(),
|
|
422
|
+
children: [],
|
|
423
|
+
flexible: false,
|
|
424
|
+
...override,
|
|
425
|
+
};
|
|
426
|
+
}
|
|
363
427
|
|
|
364
428
|
export function inferSurrealType(
|
|
365
|
-
type:
|
|
366
|
-
context
|
|
367
|
-
): string {
|
|
368
|
-
|
|
429
|
+
type: _core_.$ZodSurrealType,
|
|
430
|
+
context?: ZodSurrealTypeContext,
|
|
431
|
+
): { type: string; context: ZodSurrealTypeContext } {
|
|
432
|
+
context ??= createContext();
|
|
433
|
+
|
|
434
|
+
function enter(
|
|
435
|
+
type: _core_.$ZodSurrealType,
|
|
436
|
+
ctx?: Omit<Partial<ZodSurrealTypeContext>, "parents"> | true,
|
|
437
|
+
) {
|
|
438
|
+
context ??= createContext();
|
|
439
|
+
if (context.parents.has(type)) {
|
|
440
|
+
console.warn("Recursive type detected", type._zod.def.type);
|
|
441
|
+
context.type.add("any");
|
|
442
|
+
// throw new Error("Recursive type detected");
|
|
443
|
+
return { type: "any", context };
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
const newContext = ctx
|
|
447
|
+
? {
|
|
448
|
+
children: [],
|
|
449
|
+
flexible: false,
|
|
450
|
+
type: new Set<string>(),
|
|
451
|
+
depth: context.depth + 1,
|
|
452
|
+
...(typeof ctx === "object" ? ctx : {}),
|
|
453
|
+
parents: context.parents,
|
|
454
|
+
fullParents: context.fullParents,
|
|
455
|
+
}
|
|
456
|
+
: context;
|
|
457
|
+
context.parents.add(type);
|
|
458
|
+
context.fullParents.add(type);
|
|
459
|
+
const result = inferSurrealType(type, newContext);
|
|
460
|
+
context.fullParents.delete(type);
|
|
461
|
+
context.parents.delete(type);
|
|
462
|
+
return result;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
const schema = type as _schema_.ZodSurrealTypes;
|
|
369
466
|
if (!("_zod" in schema)) {
|
|
370
|
-
throw new Error(
|
|
371
|
-
"Invalid schema provided, make sure you are using zod v4 as zod v3 is currently not supported.",
|
|
372
|
-
);
|
|
467
|
+
throw new Error("Invalid schema provided, make sure you are using zod v4+");
|
|
373
468
|
}
|
|
374
469
|
|
|
375
|
-
//
|
|
376
|
-
// return schema._zod.def.surreal.type;
|
|
377
|
-
// } else {
|
|
378
|
-
// throw new Error(
|
|
379
|
-
// // @ts-expect-error - zod core not supported
|
|
380
|
-
// `Invalid surreal schema provided. Received ${schema._zod.def.type}`,
|
|
381
|
-
// );
|
|
382
|
-
// }
|
|
470
|
+
// console.log(schema);
|
|
383
471
|
|
|
384
472
|
const def = schema._zod.def;
|
|
385
|
-
const childIndent = " ".repeat(context.depth + 1);
|
|
386
473
|
// const checks = getChecks(schema);
|
|
387
474
|
// parseChecks(context.name, checks, context, def.type);
|
|
388
475
|
// console.log(zodToSexpr(type));
|
|
476
|
+
// console.log(def);
|
|
477
|
+
if (def.surreal.type) {
|
|
478
|
+
context.type.add(def.surreal.type);
|
|
479
|
+
} else
|
|
480
|
+
switch (/* isSurrealZodSchemaDef(def) ? */ def.type /*: def.type*/) {
|
|
481
|
+
// case "record_id": {
|
|
482
|
+
// const table = (def as ZodSurrealdRecordId["_zod"]["def"]).table;
|
|
483
|
+
// if (table) {
|
|
484
|
+
// context.type.add(`record<${table.map(escapeIdent).join(" | ")}>`);
|
|
485
|
+
// } else {
|
|
486
|
+
// context.type.add("record");
|
|
487
|
+
// }
|
|
488
|
+
// break;
|
|
489
|
+
// }
|
|
490
|
+
// case "uuid": {
|
|
491
|
+
// context.type.add("uuid");
|
|
492
|
+
// break;
|
|
493
|
+
// }
|
|
494
|
+
// case "table": {
|
|
495
|
+
// throw new Error(
|
|
496
|
+
// `Table type cannot be used as a field type.${OPEN_ISSUE_FOR_SUPPORT}`,
|
|
497
|
+
// );
|
|
498
|
+
// }
|
|
389
499
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
context.type.add("
|
|
394
|
-
break;
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
(type as SurrealZodOptional)._zod.def.innerType,
|
|
404
|
-
context,
|
|
405
|
-
);
|
|
406
|
-
context.type.add("none");
|
|
407
|
-
break;
|
|
408
|
-
}
|
|
409
|
-
case "nonoptional": {
|
|
410
|
-
inferSurrealType(
|
|
411
|
-
(type as SurrealZodNonOptional)._zod.def.innerType,
|
|
412
|
-
context,
|
|
413
|
-
);
|
|
500
|
+
// case "void":
|
|
501
|
+
// case "never":
|
|
502
|
+
// case "undefined": {
|
|
503
|
+
// context.type.add("none");
|
|
504
|
+
// break;
|
|
505
|
+
// }
|
|
506
|
+
case "optional": {
|
|
507
|
+
enter(def.innerType);
|
|
508
|
+
context.type.add("none");
|
|
509
|
+
break;
|
|
510
|
+
}
|
|
511
|
+
case "nonoptional": {
|
|
512
|
+
enter(def.innerType);
|
|
414
513
|
|
|
415
|
-
|
|
416
|
-
|
|
514
|
+
if (context.type.size > 1 && context.type.has("none")) {
|
|
515
|
+
context.type.delete("none");
|
|
516
|
+
}
|
|
517
|
+
break;
|
|
417
518
|
}
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
context.type.add("
|
|
434
|
-
break;
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
case "object": {
|
|
446
|
-
const _schema = schema as SurrealZodObject;
|
|
447
|
-
const shape = _schema._zod.def.shape;
|
|
448
|
-
const catchall = _schema._zod.def.catchall;
|
|
449
|
-
const isStrict = catchall?._zod.traits.has("$ZodNever");
|
|
450
|
-
const isLoose = catchall?._zod.traits.has("$ZodUnknown");
|
|
451
|
-
|
|
452
|
-
// buggy syntax
|
|
453
|
-
// if (isStrict) {
|
|
454
|
-
// let type = "{";
|
|
455
|
-
// if (Object.keys(shape).length > 0) {
|
|
456
|
-
// type += "\n";
|
|
519
|
+
case "nullable": {
|
|
520
|
+
enter(def.innerType);
|
|
521
|
+
context.type.add("null");
|
|
522
|
+
break;
|
|
523
|
+
}
|
|
524
|
+
// case "boolean": {
|
|
525
|
+
// context.type.add("bool");
|
|
526
|
+
// break;
|
|
527
|
+
// }
|
|
528
|
+
// case "string": {
|
|
529
|
+
// // Needs override, this will not work with original zod types
|
|
530
|
+
// // if (isStringFormat(def)) {
|
|
531
|
+
// // switch (def.format) {
|
|
532
|
+
// // case "uuid":
|
|
533
|
+
// // case "guid":
|
|
534
|
+
// // context.type.add("uuid");
|
|
535
|
+
// // break TYPE_CHECK;
|
|
536
|
+
// // }
|
|
537
|
+
// // }
|
|
538
|
+
|
|
539
|
+
// context.type.add("string");
|
|
540
|
+
// break;
|
|
541
|
+
// }
|
|
542
|
+
// case "bigint": {
|
|
543
|
+
// if (!isBigIntFormat(def as core.$ZodBigIntFormatDef)) {
|
|
544
|
+
// context.type.add("int");
|
|
545
|
+
// break;
|
|
457
546
|
// }
|
|
458
|
-
|
|
459
|
-
//
|
|
460
|
-
//
|
|
461
|
-
//
|
|
462
|
-
//
|
|
463
|
-
//
|
|
464
|
-
//
|
|
547
|
+
|
|
548
|
+
// switch ((def as core.$ZodBigIntFormatDef).format) {
|
|
549
|
+
// case "int64":
|
|
550
|
+
// case "uint64":
|
|
551
|
+
// context.type.add("int");
|
|
552
|
+
// break;
|
|
553
|
+
// default:
|
|
554
|
+
// throw new Error(
|
|
555
|
+
// `Unsupported bigint format: ${(def as core.$ZodBigIntFormatDef).format}`,
|
|
556
|
+
// );
|
|
465
557
|
// }
|
|
466
|
-
// type += "}";
|
|
467
|
-
// context.type.add(type);
|
|
468
558
|
// break;
|
|
469
559
|
// }
|
|
560
|
+
// case "number": {
|
|
561
|
+
// if (!isNumberFormat(def as core.$ZodNumberDef)) {
|
|
562
|
+
// context.type.add("number");
|
|
563
|
+
// break;
|
|
564
|
+
// }
|
|
470
565
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
566
|
+
// switch ((def as core.$ZodNumberFormatDef).format) {
|
|
567
|
+
// case "uint32":
|
|
568
|
+
// case "safeint":
|
|
569
|
+
// case "int32":
|
|
570
|
+
// context.type.add("int");
|
|
571
|
+
// break;
|
|
572
|
+
// case "float64":
|
|
573
|
+
// case "float32":
|
|
574
|
+
// context.type.add("float");
|
|
575
|
+
// break;
|
|
576
|
+
// default:
|
|
577
|
+
// throw new Error(
|
|
578
|
+
// `Unsupported number format: ${(def as core.$ZodNumberFormatDef).format}. ${OPEN_ISSUE_FOR_SUPPORT}`,
|
|
579
|
+
// );
|
|
580
|
+
// }
|
|
581
|
+
// break;
|
|
582
|
+
// }
|
|
583
|
+
// case "date": {
|
|
584
|
+
// context.type.add("datetime");
|
|
585
|
+
// break;
|
|
586
|
+
// }
|
|
587
|
+
case "object": {
|
|
588
|
+
const shape = (def as core.$ZodObjectDef).shape;
|
|
589
|
+
const catchall = (def as core.$ZodObjectDef).catchall;
|
|
590
|
+
const isStrict = catchall?._zod.traits.has("$ZodNever");
|
|
591
|
+
const isLoose = catchall?._zod.traits.has("$ZodUnknown");
|
|
592
|
+
|
|
593
|
+
// buggy syntax
|
|
594
|
+
// if (isStrict) {
|
|
595
|
+
// let type = "{";
|
|
596
|
+
// if (Object.keys(shape).length > 0) {
|
|
597
|
+
// type += "\n";
|
|
598
|
+
// }
|
|
599
|
+
// for (const [key, value] of Object.entries(shape)) {
|
|
600
|
+
// const childContext: ZodSurrealTypeContext = {
|
|
601
|
+
// type: new Set(),
|
|
602
|
+
// depth: context.depth + 1,
|
|
603
|
+
// children: [],
|
|
604
|
+
// };
|
|
605
|
+
// type += `${childIndent}${escapeIdent(key)}: ${inferSurrealType(value, childContext).inner},\n`;
|
|
606
|
+
// }
|
|
607
|
+
// type += "}";
|
|
608
|
+
// context.type.add(type);
|
|
609
|
+
// break;
|
|
610
|
+
// }
|
|
611
|
+
|
|
612
|
+
context.type.add("object");
|
|
613
|
+
if (isLoose) context.flexible = true;
|
|
614
|
+
for (const [key, value] of Object.entries(shape)) {
|
|
615
|
+
context.children.push({ name: key, type: value as core.$ZodType });
|
|
616
|
+
}
|
|
617
|
+
break;
|
|
475
618
|
}
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
context.type.add(
|
|
619
|
+
case "array": {
|
|
620
|
+
const { type: element } = enter(def.element, true);
|
|
621
|
+
if (element === "any") {
|
|
622
|
+
context.type.add("array");
|
|
623
|
+
break;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
context.type.add(`array<${element}>`);
|
|
627
|
+
break;
|
|
628
|
+
}
|
|
629
|
+
case "set": {
|
|
630
|
+
const { type: element } = enter(def.valueType, true);
|
|
631
|
+
if (element === "any") {
|
|
632
|
+
context.type.add("array");
|
|
633
|
+
break;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
context.type.add(`array<${element}>`);
|
|
637
|
+
break;
|
|
638
|
+
}
|
|
639
|
+
case "enum": {
|
|
640
|
+
const values = def.entries;
|
|
641
|
+
for (const key in values) {
|
|
642
|
+
const value = values[key];
|
|
643
|
+
context.type.add(toSurqlString(value));
|
|
644
|
+
}
|
|
645
|
+
break;
|
|
646
|
+
}
|
|
647
|
+
case "union": {
|
|
648
|
+
for (const option of def.options) {
|
|
649
|
+
// context.type.add(inferSurrealType(option, context).inner);
|
|
650
|
+
enter(option);
|
|
651
|
+
}
|
|
652
|
+
break;
|
|
653
|
+
}
|
|
654
|
+
// case "intersection": {
|
|
655
|
+
// // TODO: Find a way to handle intersections
|
|
656
|
+
// // Maybe a new function where we build a new object schema (or primitive one)
|
|
657
|
+
// // And keep track of all the types that are used in the intersection
|
|
658
|
+
// //
|
|
659
|
+
// // const left = def.left;
|
|
660
|
+
// // const right = def.right;
|
|
661
|
+
// // inferSurrealType(left, context);
|
|
662
|
+
// // inferSurrealType(right, context);
|
|
663
|
+
// // inferSurrealType(z.never(), context);
|
|
664
|
+
// // context.type.add("any");
|
|
665
|
+
// context.type.add("any");
|
|
666
|
+
// break;
|
|
667
|
+
// }
|
|
668
|
+
case "tuple": {
|
|
669
|
+
if (def.rest) {
|
|
670
|
+
context.type.add("array");
|
|
671
|
+
break;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
const types = new Set<string>();
|
|
675
|
+
for (const item of def.items) {
|
|
676
|
+
types.add(enter(item, true).type);
|
|
677
|
+
}
|
|
678
|
+
context.type.add(`[${Array.from(types).join(", ")}]`);
|
|
679
|
+
break;
|
|
680
|
+
}
|
|
681
|
+
// case "record": {
|
|
682
|
+
// context.type.add("object");
|
|
683
|
+
// // Currently there is no way to restrict the key type of an object, so we just use *
|
|
684
|
+
// // context.children.push({ name: "*", type: def.keyType });
|
|
685
|
+
// // All commented out code is because of this. Check is only done in JS side.
|
|
686
|
+
// enter((def as core.$ZodRecordDef).keyType, true);
|
|
687
|
+
// /* const isPartial =
|
|
688
|
+
// def.keyType._zod.values === undefined &&
|
|
689
|
+
// !keyContext.type.has("string") &&
|
|
690
|
+
// !keyContext.type.has("number") &&
|
|
691
|
+
// !keyContext.type.has("int") &&
|
|
692
|
+
// !keyContext.type.has("float") &&
|
|
693
|
+
// !keyContext.type.has("decimal"); */
|
|
694
|
+
// context.children.push({
|
|
695
|
+
// name: "*",
|
|
696
|
+
// type: /* isPartial ? z.optional(def.valueType) : */ (
|
|
697
|
+
// def as core.$ZodRecordDef
|
|
698
|
+
// ).valueType,
|
|
699
|
+
// });
|
|
700
|
+
// break;
|
|
701
|
+
// }
|
|
702
|
+
// case "map": {
|
|
703
|
+
// context.type.add("object");
|
|
704
|
+
// // Currently there is no way to restrict the key type of an object, so we just use *
|
|
705
|
+
// // Surreal doesnt have a map type, so we use object instead. We cant really support non PropertyKey values
|
|
706
|
+
// // unless we serialize the keys to strings.
|
|
707
|
+
// const { context: keyContext } = enter(
|
|
708
|
+
// (def as core.$ZodMapDef).keyType,
|
|
709
|
+
// true,
|
|
710
|
+
// );
|
|
711
|
+
// for (const key of keyContext.type) {
|
|
712
|
+
// if (!["string", "number", "float", "int", "decimal"].includes(key)) {
|
|
713
|
+
// throw new Error(`Unsupported key type: ${key}`);
|
|
714
|
+
// }
|
|
715
|
+
// }
|
|
716
|
+
// context.children.push({
|
|
717
|
+
// name: "*",
|
|
718
|
+
// type: (def as core.$ZodMapDef).valueType,
|
|
719
|
+
// });
|
|
720
|
+
// break;
|
|
721
|
+
// }
|
|
722
|
+
case "literal": {
|
|
723
|
+
for (const value of (def as core.$ZodLiteralDef<any>).values) {
|
|
724
|
+
context.type.add(toSurqlString(value));
|
|
725
|
+
}
|
|
726
|
+
break;
|
|
727
|
+
}
|
|
728
|
+
case "file": {
|
|
729
|
+
throw new Error(
|
|
730
|
+
`File type cannot be used as a field type.${OPEN_ISSUE_FOR_SUPPORT}`,
|
|
731
|
+
);
|
|
732
|
+
}
|
|
733
|
+
case "transform": {
|
|
734
|
+
break;
|
|
735
|
+
}
|
|
736
|
+
case "readonly":
|
|
737
|
+
case "catch":
|
|
738
|
+
case "prefault":
|
|
739
|
+
case "default": {
|
|
740
|
+
enter(def.innerType);
|
|
741
|
+
break;
|
|
742
|
+
}
|
|
743
|
+
case "success": {
|
|
744
|
+
context.type.add("string");
|
|
745
|
+
break;
|
|
746
|
+
}
|
|
747
|
+
case "nan": {
|
|
748
|
+
context.type.add("number");
|
|
749
|
+
break;
|
|
750
|
+
}
|
|
751
|
+
case "pipe": {
|
|
752
|
+
enter(def.in);
|
|
753
|
+
enter(def.out);
|
|
754
|
+
break;
|
|
755
|
+
}
|
|
756
|
+
case "template_literal": {
|
|
757
|
+
context.type.add("string");
|
|
758
|
+
break;
|
|
759
|
+
}
|
|
760
|
+
case "lazy": {
|
|
761
|
+
const innerType = def.getter();
|
|
762
|
+
// All that cascading to get here, we dont want to keep complex types if
|
|
763
|
+
// recursive.
|
|
764
|
+
if (context.fullParents.has(type) || context.parents.has(type)) {
|
|
765
|
+
context.type.add("any");
|
|
766
|
+
} else {
|
|
767
|
+
enter(innerType);
|
|
768
|
+
}
|
|
769
|
+
break;
|
|
770
|
+
}
|
|
771
|
+
case "promise": {
|
|
772
|
+
// We will not support promises for now, this can be uncommented after
|
|
773
|
+
// support is added
|
|
774
|
+
// const { inner: innerType } =
|
|
775
|
+
// enter(def.innerType);
|
|
776
|
+
// context.type.add(innerType);
|
|
777
|
+
throw new Error(
|
|
778
|
+
`Promise type cannot be used as a field type.${OPEN_ISSUE_FOR_SUPPORT}`,
|
|
779
|
+
);
|
|
780
|
+
}
|
|
781
|
+
case "function": {
|
|
782
|
+
throw new Error(
|
|
783
|
+
`Function type cannot be used as a field type.${OPEN_ISSUE_FOR_SUPPORT}`,
|
|
784
|
+
);
|
|
785
|
+
}
|
|
786
|
+
case "custom": {
|
|
787
|
+
throw new Error(
|
|
788
|
+
`Custom type cannot be used as a field type.${OPEN_ISSUE_FOR_SUPPORT}`,
|
|
789
|
+
);
|
|
790
|
+
}
|
|
791
|
+
case "symbol": {
|
|
792
|
+
throw new Error(
|
|
793
|
+
`Symbol type cannot be used as a field type.${OPEN_ISSUE_FOR_SUPPORT}`,
|
|
794
|
+
);
|
|
484
795
|
}
|
|
485
|
-
break;
|
|
486
|
-
}
|
|
487
|
-
case "table": {
|
|
488
|
-
throw new Error("Table type cannot be used as a field type");
|
|
489
796
|
}
|
|
490
|
-
}
|
|
491
797
|
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
798
|
+
const inner =
|
|
799
|
+
context.type.has("any") || context.type.size === 0
|
|
800
|
+
? "any"
|
|
801
|
+
: Array.from(context.type).join(" | ");
|
|
495
802
|
|
|
496
|
-
return
|
|
803
|
+
return { type: inner, context };
|
|
497
804
|
}
|
|
498
805
|
|
|
499
|
-
// function
|
|
500
|
-
//
|
|
501
|
-
//
|
|
502
|
-
//
|
|
503
|
-
// checks.unshift(schema as z4.$ZodCheck);
|
|
504
|
-
// }
|
|
505
|
-
// return checks;
|
|
806
|
+
// function isSurrealZodSchemaDef(
|
|
807
|
+
// def: core.$ZodTypeDef | ZodSurrealTypeDef,
|
|
808
|
+
// ): def is ZodSurrealTypeDef {
|
|
809
|
+
// return "surreal" in def && def.surreal.type !== undefined;
|
|
506
810
|
// }
|
|
507
811
|
|
|
508
|
-
// function
|
|
509
|
-
//
|
|
510
|
-
//
|
|
511
|
-
//
|
|
512
|
-
// type: ZodTypeName | SurrealZodTypeName,
|
|
513
|
-
// ) {
|
|
514
|
-
// for (const check of checks) {
|
|
515
|
-
// const { transform, assert } = parseCheck(name, check, type);
|
|
516
|
-
// if (transform) {
|
|
517
|
-
// context.transforms.push(transform);
|
|
518
|
-
// }
|
|
519
|
-
// if (assert) {
|
|
520
|
-
// context.asserts.push(assert);
|
|
521
|
-
// }
|
|
522
|
-
// }
|
|
812
|
+
// function isStringFormat(
|
|
813
|
+
// def: core.$ZodStringDef,
|
|
814
|
+
// ): def is core.$ZodStringFormatTypes["_zod"]["def"] {
|
|
815
|
+
// return def.type === "string" && "format" in def;
|
|
523
816
|
// }
|
|
524
817
|
|
|
525
|
-
//
|
|
526
|
-
//
|
|
527
|
-
//
|
|
528
|
-
//
|
|
529
|
-
// min_length(name: string, value: number, type: ZodTypeName) {
|
|
530
|
-
// if (type === "array") {
|
|
531
|
-
// return `$value.len() >= ${value} || { THROW 'Field "${name}" must have at least ${value} ${value === 1 ? "item" : "items"}' };`;
|
|
532
|
-
// }
|
|
533
|
-
|
|
534
|
-
// if (type === "string") {
|
|
535
|
-
// return `$value.len() >= ${value} || { THROW 'Field "${name}" must be at least ${value} ${value === 1 ? "character" : "characters"} long' };`;
|
|
536
|
-
// }
|
|
537
|
-
|
|
538
|
-
// throw new Error(`Invalid type: ${type}`);
|
|
539
|
-
// },
|
|
540
|
-
// max_length(name: string, value: number, type: ZodTypeName) {
|
|
541
|
-
// if (type === "array") {
|
|
542
|
-
// return `$value.len() <= ${value} || { THROW 'Field "${name}" must have at most ${value} ${value === 1 ? "item" : "items"}' };`;
|
|
543
|
-
// }
|
|
544
|
-
|
|
545
|
-
// if (type === "string") {
|
|
546
|
-
// return `$value.len() <= ${value} || { THROW 'Field "${name}" must be at most ${value} ${value === 1 ? "character" : "characters"} long' };`;
|
|
547
|
-
// }
|
|
548
|
-
|
|
549
|
-
// throw new Error(`Invalid type: ${type}`);
|
|
550
|
-
// },
|
|
551
|
-
// greater_than(name: string, value: z4.util.Numeric, inclusive: boolean) {
|
|
552
|
-
// return `$value ${inclusive ? ">=" : ">"} ${value} || { THROW 'Field "${name}" must be greater than ${inclusive ? "or equal to" : ""} ${value}' };`;
|
|
553
|
-
// },
|
|
554
|
-
// less_than(name: string, value: z4.util.Numeric, inclusive: boolean) {
|
|
555
|
-
// return `$value ${inclusive ? "<=" : "<"} ${value} || { THROW 'Field "${name}" must be less than ${inclusive ? "or equal to" : ""} ${value}' };`;
|
|
556
|
-
// },
|
|
557
|
-
// length_equals(name: string, value: number, type: ZodTypeName = "string") {
|
|
558
|
-
// if (type === "array") {
|
|
559
|
-
// return `$value.len() == ${value} || { THROW 'Field "${name}" must have exactly ${value} ${value === 1 ? "item" : "items"}' };`;
|
|
560
|
-
// }
|
|
561
|
-
|
|
562
|
-
// if (type === "string") {
|
|
563
|
-
// return `$value.len() == ${value} || { THROW 'Field "${name}" must be exactly ${value} ${value === 1 ? "character" : "characters"} long' };`;
|
|
564
|
-
// }
|
|
565
|
-
|
|
566
|
-
// throw new Error(`Invalid type: ${type}`);
|
|
567
|
-
// },
|
|
568
|
-
|
|
569
|
-
// string_format: {
|
|
570
|
-
// email: (name: string) => {
|
|
571
|
-
// const regex =
|
|
572
|
-
// /^[A-Za-z0-9'_+-]+(?:\.[A-Za-z0-9'_+-]+)*@([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$/;
|
|
573
|
-
// return `string::matches($value, ${regex}) || { THROW "Field '${name}' must be a valid email address" };`;
|
|
574
|
-
// },
|
|
575
|
-
// url: (
|
|
576
|
-
// name: string,
|
|
577
|
-
// def?: Pick<z4.$ZodCheckURLParams, "hostname" | "protocol" | "normalize">,
|
|
578
|
-
// ) => {
|
|
579
|
-
// return dedent`
|
|
580
|
-
// LET $url = {
|
|
581
|
-
// scheme: parse::url::scheme($value),
|
|
582
|
-
// host: parse::url::host($value),
|
|
583
|
-
// domain: parse::url::domain($value),
|
|
584
|
-
// path: parse::url::path($value),
|
|
585
|
-
// port: parse::url::port($value),
|
|
586
|
-
// query: parse::url::query($value),
|
|
587
|
-
// hash: parse::url::fragment($value),
|
|
588
|
-
// };
|
|
589
|
-
// $url.scheme || { THROW "Field '${name}' must be a valid URL" };
|
|
590
|
-
// ${
|
|
591
|
-
// def?.hostname
|
|
592
|
-
// ? `($url.host ?? "").matches(${def.hostname}) || { THROW "Field '${name}' must match hostname ${def.hostname.toString().replace(/\\/g, "\\\\")}" };`
|
|
593
|
-
// : ""
|
|
594
|
-
// }
|
|
595
|
-
// ${
|
|
596
|
-
// def?.protocol
|
|
597
|
-
// ? `($url.scheme ?? "").matches(${def.protocol}) || { THROW "Field '${name}' must match protocol ${def.protocol.toString().replace(/\\/g, "\\\\")}" };`
|
|
598
|
-
// : ""
|
|
599
|
-
// }
|
|
600
|
-
// $url.scheme + "://" + ($url.host ?? "") + (
|
|
601
|
-
// IF $url.port && (
|
|
602
|
-
// ($url.scheme == "http" && $url.port != 80) ||
|
|
603
|
-
// ($url.scheme == "https" && $url.port != 443)
|
|
604
|
-
// ) { ":" + <string>$url.port } ?? ""
|
|
605
|
-
// )
|
|
606
|
-
// + ($url.path ?? "")
|
|
607
|
-
// + (IF $url.query { "?" + $url.query } ?? "")
|
|
608
|
-
// + (IF $url.fragment { "#" + $url.fragment } ?? "");
|
|
609
|
-
// `;
|
|
610
|
-
// },
|
|
611
|
-
// },
|
|
612
|
-
// };
|
|
613
|
-
|
|
614
|
-
// function parseCheck(
|
|
615
|
-
// name: string,
|
|
616
|
-
// _check: z4.$ZodCheck,
|
|
617
|
-
// type: ZodTypeName,
|
|
618
|
-
// ): { transform?: string; assert?: string } {
|
|
619
|
-
// const check = _check as z4.$ZodChecks;
|
|
620
|
-
// const def = check._zod.def;
|
|
621
|
-
// switch (def.check) {
|
|
622
|
-
// case "min_length":
|
|
623
|
-
// return { assert: checkMap.min_length(name, def.minimum, type) };
|
|
624
|
-
// case "max_length":
|
|
625
|
-
// return { assert: checkMap.max_length(name, def.maximum, type) };
|
|
626
|
-
// case "greater_than":
|
|
627
|
-
// return { assert: checkMap.greater_than(name, def.value, def.inclusive) };
|
|
628
|
-
// case "less_than":
|
|
629
|
-
// return { assert: checkMap.less_than(name, def.value, def.inclusive) };
|
|
630
|
-
// case "length_equals":
|
|
631
|
-
// return { assert: checkMap.length_equals(name, def.length, type) };
|
|
632
|
-
// case "string_format":
|
|
633
|
-
// return assertionForStringFormat(name, check);
|
|
634
|
-
// default:
|
|
635
|
-
// return { assert: `THROW 'Unknown check: ${def.check}';` };
|
|
636
|
-
// }
|
|
818
|
+
// function isBigIntFormat(
|
|
819
|
+
// def: core.$ZodBigIntDef,
|
|
820
|
+
// ): def is core.$ZodBigIntFormatDef {
|
|
821
|
+
// return def.type === "bigint" && "format" in def;
|
|
637
822
|
// }
|
|
638
823
|
|
|
639
|
-
//
|
|
640
|
-
//
|
|
641
|
-
//
|
|
642
|
-
//
|
|
643
|
-
// ): { transform?: string; assert?: string } {
|
|
644
|
-
// const check = _check as z4.$ZodStringFormatChecks;
|
|
645
|
-
// const def = check._zod.def;
|
|
646
|
-
|
|
647
|
-
// switch (def.format) {
|
|
648
|
-
// case "email": {
|
|
649
|
-
// return { assert: checkMap.string_format.email(name) };
|
|
650
|
-
// }
|
|
651
|
-
// case "url": {
|
|
652
|
-
// const code = checkMap.string_format.url(name, def);
|
|
653
|
-
// return def.normalize ? { transform: code } : { assert: code };
|
|
654
|
-
// }
|
|
655
|
-
// default:
|
|
656
|
-
// return { assert: `THROW 'Unsupported string format: ${def.format}';` };
|
|
657
|
-
// }
|
|
824
|
+
// function isNumberFormat(
|
|
825
|
+
// def: core.$ZodNumberDef,
|
|
826
|
+
// ): def is core.$ZodNumberFormatDef {
|
|
827
|
+
// return def.type === "number" && "format" in def;
|
|
658
828
|
// }
|
|
829
|
+
|
|
830
|
+
// // function getChecks(_schema: z4.$ZodType | SurrealZodType) {
|
|
831
|
+
// // const schema = _schema as z4.$ZodTypes | SurrealZodTypes;
|
|
832
|
+
// // const checks = schema._zod.def.checks ?? [];
|
|
833
|
+
// // if ("check" in schema._zod.def) {
|
|
834
|
+
// // checks.unshift(schema as z4.$ZodCheck);
|
|
835
|
+
// // }
|
|
836
|
+
// // return checks;
|
|
837
|
+
// // }
|
|
838
|
+
|
|
839
|
+
// // function parseChecks(
|
|
840
|
+
// // name: string,
|
|
841
|
+
// // checks: z4.$ZodCheck[],
|
|
842
|
+
// // context: ZodSurrealTypeContext,
|
|
843
|
+
// // type: ZodTypeName | SurrealZodTypeName,
|
|
844
|
+
// // ) {
|
|
845
|
+
// // for (const check of checks) {
|
|
846
|
+
// // const { transform, assert } = parseCheck(name, check, type);
|
|
847
|
+
// // if (transform) {
|
|
848
|
+
// // context.transforms.push(transform);
|
|
849
|
+
// // }
|
|
850
|
+
// // if (assert) {
|
|
851
|
+
// // context.asserts.push(assert);
|
|
852
|
+
// // }
|
|
853
|
+
// // }
|
|
854
|
+
// // }
|
|
855
|
+
|
|
856
|
+
// // export const checkMap = {
|
|
857
|
+
// // never(name: string) {
|
|
858
|
+
// // return `THROW 'Field "${name}" must never be present'`;
|
|
859
|
+
// // },
|
|
860
|
+
// // min_length(name: string, value: number, type: ZodTypeName) {
|
|
861
|
+
// // if (type === "array") {
|
|
862
|
+
// // return `$value.len() >= ${value} || { THROW 'Field "${name}" must have at least ${value} ${value === 1 ? "item" : "items"}' };`;
|
|
863
|
+
// // }
|
|
864
|
+
|
|
865
|
+
// // if (type === "string") {
|
|
866
|
+
// // return `$value.len() >= ${value} || { THROW 'Field "${name}" must be at least ${value} ${value === 1 ? "character" : "characters"} long' };`;
|
|
867
|
+
// // }
|
|
868
|
+
|
|
869
|
+
// // throw new Error(`Invalid type: ${type}`);
|
|
870
|
+
// // },
|
|
871
|
+
// // max_length(name: string, value: number, type: ZodTypeName) {
|
|
872
|
+
// // if (type === "array") {
|
|
873
|
+
// // return `$value.len() <= ${value} || { THROW 'Field "${name}" must have at most ${value} ${value === 1 ? "item" : "items"}' };`;
|
|
874
|
+
// // }
|
|
875
|
+
|
|
876
|
+
// // if (type === "string") {
|
|
877
|
+
// // return `$value.len() <= ${value} || { THROW 'Field "${name}" must be at most ${value} ${value === 1 ? "character" : "characters"} long' };`;
|
|
878
|
+
// // }
|
|
879
|
+
|
|
880
|
+
// // throw new Error(`Invalid type: ${type}`);
|
|
881
|
+
// // },
|
|
882
|
+
// // greater_than(name: string, value: z4.util.Numeric, inclusive: boolean) {
|
|
883
|
+
// // return `$value ${inclusive ? ">=" : ">"} ${value} || { THROW 'Field "${name}" must be greater than ${inclusive ? "or equal to" : ""} ${value}' };`;
|
|
884
|
+
// // },
|
|
885
|
+
// // less_than(name: string, value: z4.util.Numeric, inclusive: boolean) {
|
|
886
|
+
// // return `$value ${inclusive ? "<=" : "<"} ${value} || { THROW 'Field "${name}" must be less than ${inclusive ? "or equal to" : ""} ${value}' };`;
|
|
887
|
+
// // },
|
|
888
|
+
// // length_equals(name: string, value: number, type: ZodTypeName = "string") {
|
|
889
|
+
// // if (type === "array") {
|
|
890
|
+
// // return `$value.len() == ${value} || { THROW 'Field "${name}" must have exactly ${value} ${value === 1 ? "item" : "items"}' };`;
|
|
891
|
+
// // }
|
|
892
|
+
|
|
893
|
+
// // if (type === "string") {
|
|
894
|
+
// // return `$value.len() == ${value} || { THROW 'Field "${name}" must be exactly ${value} ${value === 1 ? "character" : "characters"} long' };`;
|
|
895
|
+
// // }
|
|
896
|
+
|
|
897
|
+
// // throw new Error(`Invalid type: ${type}`);
|
|
898
|
+
// // },
|
|
899
|
+
|
|
900
|
+
// // string_format: {
|
|
901
|
+
// // email: (name: string) => {
|
|
902
|
+
// // const regex =
|
|
903
|
+
// // /^[A-Za-z0-9'_+-]+(?:\.[A-Za-z0-9'_+-]+)*@([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$/;
|
|
904
|
+
// // return `string::matches($value, ${regex}) || { THROW "Field '${name}' must be a valid email address" };`;
|
|
905
|
+
// // },
|
|
906
|
+
// // url: (
|
|
907
|
+
// // name: string,
|
|
908
|
+
// // def?: Pick<z4.$ZodCheckURLParams, "hostname" | "protocol" | "normalize">,
|
|
909
|
+
// // ) => {
|
|
910
|
+
// // return dedent`
|
|
911
|
+
// // LET $url = {
|
|
912
|
+
// // scheme: parse::url::scheme($value),
|
|
913
|
+
// // host: parse::url::host($value),
|
|
914
|
+
// // domain: parse::url::domain($value),
|
|
915
|
+
// // path: parse::url::path($value),
|
|
916
|
+
// // port: parse::url::port($value),
|
|
917
|
+
// // query: parse::url::query($value),
|
|
918
|
+
// // hash: parse::url::fragment($value),
|
|
919
|
+
// // };
|
|
920
|
+
// // $url.scheme || { THROW "Field '${name}' must be a valid URL" };
|
|
921
|
+
// // ${
|
|
922
|
+
// // def?.hostname
|
|
923
|
+
// // ? `($url.host ?? "").matches(${def.hostname}) || { THROW "Field '${name}' must match hostname ${def.hostname.toString().replace(/\\/g, "\\\\")}" };`
|
|
924
|
+
// // : ""
|
|
925
|
+
// // }
|
|
926
|
+
// // ${
|
|
927
|
+
// // def?.protocol
|
|
928
|
+
// // ? `($url.scheme ?? "").matches(${def.protocol}) || { THROW "Field '${name}' must match protocol ${def.protocol.toString().replace(/\\/g, "\\\\")}" };`
|
|
929
|
+
// // : ""
|
|
930
|
+
// // }
|
|
931
|
+
// // $url.scheme + "://" + ($url.host ?? "") + (
|
|
932
|
+
// // IF $url.port && (
|
|
933
|
+
// // ($url.scheme == "http" && $url.port != 80) ||
|
|
934
|
+
// // ($url.scheme == "https" && $url.port != 443)
|
|
935
|
+
// // ) { ":" + <string>$url.port } ?? ""
|
|
936
|
+
// // )
|
|
937
|
+
// // + ($url.path ?? "")
|
|
938
|
+
// // + (IF $url.query { "?" + $url.query } ?? "")
|
|
939
|
+
// // + (IF $url.fragment { "#" + $url.fragment } ?? "");
|
|
940
|
+
// // `;
|
|
941
|
+
// // },
|
|
942
|
+
// // },
|
|
943
|
+
// // };
|
|
944
|
+
|
|
945
|
+
// // function parseCheck(
|
|
946
|
+
// // name: string,
|
|
947
|
+
// // _check: z4.$ZodCheck,
|
|
948
|
+
// // type: ZodTypeName,
|
|
949
|
+
// // ): { transform?: string; assert?: string } {
|
|
950
|
+
// // const check = _check as z4.$ZodChecks;
|
|
951
|
+
// // const def = check._zod.def;
|
|
952
|
+
// // switch (def.check) {
|
|
953
|
+
// // case "min_length":
|
|
954
|
+
// // return { assert: checkMap.min_length(name, def.minimum, type) };
|
|
955
|
+
// // case "max_length":
|
|
956
|
+
// // return { assert: checkMap.max_length(name, def.maximum, type) };
|
|
957
|
+
// // case "greater_than":
|
|
958
|
+
// // return { assert: checkMap.greater_than(name, def.value, def.inclusive) };
|
|
959
|
+
// // case "less_than":
|
|
960
|
+
// // return { assert: checkMap.less_than(name, def.value, def.inclusive) };
|
|
961
|
+
// // case "length_equals":
|
|
962
|
+
// // return { assert: checkMap.length_equals(name, def.length, type) };
|
|
963
|
+
// // case "string_format":
|
|
964
|
+
// // return assertionForStringFormat(name, check);
|
|
965
|
+
// // default:
|
|
966
|
+
// // return { assert: `THROW 'Unknown check: ${def.check}';` };
|
|
967
|
+
// // }
|
|
968
|
+
// // }
|
|
969
|
+
|
|
970
|
+
// // // Remove look-around, look-behind, and look-ahead as they are not supported by SurrealDB
|
|
971
|
+
// // function assertionForStringFormat(
|
|
972
|
+
// // name: string,
|
|
973
|
+
// // _check: z4.$ZodCheck,
|
|
974
|
+
// // ): { transform?: string; assert?: string } {
|
|
975
|
+
// // const check = _check as z4.$ZodStringFormatChecks;
|
|
976
|
+
// // const def = check._zod.def;
|
|
977
|
+
|
|
978
|
+
// // switch (def.format) {
|
|
979
|
+
// // case "email": {
|
|
980
|
+
// // return { assert: checkMap.string_format.email(name) };
|
|
981
|
+
// // }
|
|
982
|
+
// // case "url": {
|
|
983
|
+
// // const code = checkMap.string_format.url(name, def);
|
|
984
|
+
// // return def.normalize ? { transform: code } : { assert: code };
|
|
985
|
+
// // }
|
|
986
|
+
// // default:
|
|
987
|
+
// // return { assert: `THROW 'Unsupported string format: ${def.format}';` };
|
|
988
|
+
// // }
|
|
989
|
+
// // }
|
|
990
|
+
|
|
991
|
+
const SurrealQLStatements = [
|
|
992
|
+
"ACCESS",
|
|
993
|
+
"ALTER",
|
|
994
|
+
"BEGIN",
|
|
995
|
+
"BREAK",
|
|
996
|
+
"CANCEL",
|
|
997
|
+
"COMMIT",
|
|
998
|
+
"CONTINUE",
|
|
999
|
+
"CREATE",
|
|
1000
|
+
"DEFINE",
|
|
1001
|
+
"DELETE",
|
|
1002
|
+
"FOR",
|
|
1003
|
+
"IF",
|
|
1004
|
+
"INFO",
|
|
1005
|
+
"INSERT",
|
|
1006
|
+
"KILL",
|
|
1007
|
+
"LET",
|
|
1008
|
+
"LIVE",
|
|
1009
|
+
"REBUILD",
|
|
1010
|
+
"RELATE",
|
|
1011
|
+
"REMOVE",
|
|
1012
|
+
"RETURN",
|
|
1013
|
+
"SELECT",
|
|
1014
|
+
"SHOW",
|
|
1015
|
+
"SLEEP",
|
|
1016
|
+
"THROW",
|
|
1017
|
+
"UPDATE",
|
|
1018
|
+
"UPSERT",
|
|
1019
|
+
"USE",
|
|
1020
|
+
"EXPLAIN",
|
|
1021
|
+
"FETCH",
|
|
1022
|
+
];
|
|
1023
|
+
|
|
1024
|
+
function hasMultipleStatements(query: string): boolean {
|
|
1025
|
+
let inString: false | "'" | '"' = false;
|
|
1026
|
+
let escaping = false;
|
|
1027
|
+
let statements = 0;
|
|
1028
|
+
let buffer = "";
|
|
1029
|
+
|
|
1030
|
+
for (let i = 0; i < query.length; i++) {
|
|
1031
|
+
const ch = query[i];
|
|
1032
|
+
const nextBuffer = `${buffer}${ch}`;
|
|
1033
|
+
|
|
1034
|
+
if (ch === "\n") return true;
|
|
1035
|
+
if (inString) {
|
|
1036
|
+
if (escaping) {
|
|
1037
|
+
escaping = false;
|
|
1038
|
+
continue;
|
|
1039
|
+
}
|
|
1040
|
+
if (ch === "\\") {
|
|
1041
|
+
escaping = true;
|
|
1042
|
+
continue;
|
|
1043
|
+
}
|
|
1044
|
+
if (ch === inString) {
|
|
1045
|
+
inString = false;
|
|
1046
|
+
continue;
|
|
1047
|
+
}
|
|
1048
|
+
continue;
|
|
1049
|
+
}
|
|
1050
|
+
if (ch === '"' || ch === "'") {
|
|
1051
|
+
inString = ch;
|
|
1052
|
+
continue;
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
if (ch === " ") {
|
|
1056
|
+
if (SurrealQLStatements.includes(buffer.toUpperCase())) {
|
|
1057
|
+
return true;
|
|
1058
|
+
}
|
|
1059
|
+
continue;
|
|
1060
|
+
}
|
|
1061
|
+
if (
|
|
1062
|
+
ch === ";" ||
|
|
1063
|
+
// Single line Comments
|
|
1064
|
+
nextBuffer === "--" ||
|
|
1065
|
+
nextBuffer === "//" ||
|
|
1066
|
+
ch === "#"
|
|
1067
|
+
) {
|
|
1068
|
+
statements++;
|
|
1069
|
+
buffer = "";
|
|
1070
|
+
continue;
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
buffer = nextBuffer;
|
|
1074
|
+
|
|
1075
|
+
if (statements > 1) return true;
|
|
1076
|
+
}
|
|
1077
|
+
if (statements > 0 && (buffer || inString || escaping)) return true;
|
|
1078
|
+
return statements > 1;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
export function formatQuery(query: string) {
|
|
1082
|
+
if (hasMultipleStatements(query)) {
|
|
1083
|
+
return `{\n ${dedent.withOptions({ alignValues: true })` ${query.trimStart()}`}\n}`;
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
return query.trim();
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
export function inlineQueryParameters(query: BoundQuery): string {
|
|
1090
|
+
let value = query.query;
|
|
1091
|
+
for (const [paramName, paramValue] of Object.entries(query.bindings ?? {})) {
|
|
1092
|
+
value = value.replace(
|
|
1093
|
+
new RegExp(`\\$${paramName}\\b`, "g"),
|
|
1094
|
+
toSurqlString(paramValue),
|
|
1095
|
+
);
|
|
1096
|
+
}
|
|
1097
|
+
return value;
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
function toSurqlString(value: unknown): string {
|
|
1101
|
+
return baseToSurqlString(value).replace(/^s"/g, '"');
|
|
1102
|
+
}
|