surreal-zod 0.0.0-alpha.11 → 0.0.0-alpha.12
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 +262 -0
- package/lib/zod/core.js +10 -0
- package/lib/zod/index.d.ts +2 -0
- package/lib/zod/index.js +2 -0
- package/lib/zod/json-schema.d.ts +89 -0
- package/lib/zod/json-schema.js +629 -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 +2255 -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 +605 -0
- package/src/zod/index.ts +2 -0
- package/src/zod/json-schema.ts +892 -0
- package/src/zod/original.ts +369 -0
- package/src/zod/parse.ts +138 -0
- package/src/zod/schema.ts +7099 -984
- package/src/zod/utils.ts +15 -5
package/lib/surql.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { BoundQuery, escapeIdent, escapeIdPart,
|
|
2
|
-
import * as
|
|
3
|
-
import
|
|
1
|
+
import { BoundQuery, escapeIdent, escapeIdPart, surql, Table, toSurqlString as baseToSurqlString, } from "surrealdb";
|
|
2
|
+
import * as core from "zod/v4/core";
|
|
3
|
+
import * as _schema_ from "./zod/schema";
|
|
4
|
+
import * as _core_ from "./zod/core";
|
|
4
5
|
import dedent from "dedent";
|
|
6
|
+
const OPEN_ISSUE_FOR_SUPPORT = " 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";
|
|
5
7
|
export function tableToSurql(table, statement, options) {
|
|
6
8
|
if (statement === "define") {
|
|
7
9
|
return defineTable(table, options);
|
|
@@ -81,31 +83,45 @@ export function defineTable(schema, options) {
|
|
|
81
83
|
query.append(";\n");
|
|
82
84
|
if (options?.fields) {
|
|
83
85
|
for (const [fieldName, fieldSchema] of Object.entries(def.fields)) {
|
|
86
|
+
let defaultValue;
|
|
87
|
+
let comment;
|
|
88
|
+
let readonly;
|
|
89
|
+
let assert;
|
|
90
|
+
let value;
|
|
91
|
+
if (fieldSchema instanceof _schema_.ZodSurrealField) {
|
|
92
|
+
defaultValue = fieldSchema._zod.def.surreal.field?.default;
|
|
93
|
+
comment = fieldSchema._zod.def.surreal.field?.comment;
|
|
94
|
+
readonly = fieldSchema._zod.def.surreal.field?.readonly;
|
|
95
|
+
assert = fieldSchema._zod.def.surreal.field?.assert;
|
|
96
|
+
value = fieldSchema._zod.def.surreal.field?.value;
|
|
97
|
+
}
|
|
84
98
|
query.append(defineField(fieldName, table.name, fieldName === "id"
|
|
85
99
|
? fieldSchema._zod.def.innerType
|
|
86
100
|
: fieldSchema, {
|
|
87
101
|
exists: options.exists,
|
|
88
102
|
schemafull: surreal.schemafull,
|
|
103
|
+
default: defaultValue,
|
|
104
|
+
comment,
|
|
105
|
+
readonly,
|
|
106
|
+
assert,
|
|
107
|
+
value,
|
|
108
|
+
// @ts-expect-error - @internal
|
|
109
|
+
// We need to add the table schema to the fullParents set to avoid
|
|
110
|
+
// infinite recursion. Child fields keep a separate context from
|
|
111
|
+
// the table or other fields.
|
|
112
|
+
// The resting point for fullParents is in the inferSurrealType function,
|
|
113
|
+
// on the switch case for the "lazy" type.
|
|
114
|
+
fullParents: new Set([schema]),
|
|
89
115
|
}));
|
|
90
116
|
}
|
|
91
117
|
}
|
|
92
118
|
return query;
|
|
93
119
|
}
|
|
94
|
-
export function isNormalTable(table) {
|
|
95
|
-
return table._zod.def.surreal.tableType === "normal";
|
|
96
|
-
}
|
|
97
120
|
export function isRelationTable(table) {
|
|
98
|
-
return table.
|
|
121
|
+
return (table instanceof _schema_.ZodSurrealTable &&
|
|
122
|
+
table._zod.def.surreal.tableType === "relation");
|
|
99
123
|
}
|
|
100
|
-
function defineField(name, table, schema, options) {
|
|
101
|
-
// const context: ZodSurrealTypeContext = {
|
|
102
|
-
// name,
|
|
103
|
-
// table,
|
|
104
|
-
// rootSchema: schema,
|
|
105
|
-
// children: [],
|
|
106
|
-
// asserts: [],
|
|
107
|
-
// transforms: [],
|
|
108
|
-
// };
|
|
124
|
+
export function defineField(name, table, schema, options) {
|
|
109
125
|
const query = surql `DEFINE FIELD`;
|
|
110
126
|
if (options?.exists === "ignore") {
|
|
111
127
|
query.append(" IF NOT EXISTS");
|
|
@@ -117,23 +133,37 @@ function defineField(name, table, schema, options) {
|
|
|
117
133
|
const context = {
|
|
118
134
|
type: new Set(),
|
|
119
135
|
depth: 0,
|
|
136
|
+
parents: new Set(),
|
|
137
|
+
// @ts-expect-error - @internal
|
|
138
|
+
fullParents: options?.fullParents ?? new Set(),
|
|
120
139
|
children: [],
|
|
121
140
|
flexible: false,
|
|
122
141
|
};
|
|
123
|
-
query.append(` TYPE ${inferSurrealType(schema, context)}`);
|
|
142
|
+
query.append(` TYPE ${inferSurrealType(schema, context).type}`);
|
|
124
143
|
if (options?.schemafull && context.flexible) {
|
|
125
144
|
query.append(" FLEXIBLE");
|
|
126
145
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
146
|
+
if (options?.readonly) {
|
|
147
|
+
query.append(" READONLY");
|
|
148
|
+
}
|
|
149
|
+
if (options?.default) {
|
|
150
|
+
query.append(options.default.always
|
|
151
|
+
? ` DEFAULT ALWAYS ${formatQuery(inlineQueryParameters(options.default.value))}`
|
|
152
|
+
: ` DEFAULT ${formatQuery(inlineQueryParameters(options.default.value))}`);
|
|
153
|
+
}
|
|
154
|
+
if (options?.value) {
|
|
155
|
+
query.append(` VALUE ${inlineQueryParameters(options.value)}`);
|
|
156
|
+
}
|
|
157
|
+
if (options?.assert) {
|
|
158
|
+
query.append(` ASSERT ${inlineQueryParameters(options.assert)}`);
|
|
159
|
+
}
|
|
160
|
+
if (options?.comment) {
|
|
161
|
+
query.append(` COMMENT ${JSON.stringify(options.comment)}`);
|
|
162
|
+
}
|
|
133
163
|
// const type =
|
|
134
164
|
// name === "id"
|
|
135
165
|
// ? inferSurrealType(
|
|
136
|
-
// (schema as unknown as
|
|
166
|
+
// (schema as unknown as ZodSurrealRecordId)._zod.def.innerType,
|
|
137
167
|
// [],
|
|
138
168
|
// context,
|
|
139
169
|
// )
|
|
@@ -170,273 +200,639 @@ function defineField(name, table, schema, options) {
|
|
|
170
200
|
// }
|
|
171
201
|
query.append(`;\n`);
|
|
172
202
|
if (context.children.length > 0) {
|
|
203
|
+
context.fullParents.add(schema);
|
|
173
204
|
for (const { name: childName, type: childType } of context.children) {
|
|
174
|
-
query.append(defineField(`${escapeIdent(name)}.${escapeIdent(childName)}`, table, childType, {
|
|
205
|
+
query.append(defineField(`${escapeIdent(name)}.${childName === "*" ? childName : escapeIdent(childName)}`, table, childType, {
|
|
175
206
|
exists: options?.exists,
|
|
207
|
+
// @ts-expect-error - @internal
|
|
208
|
+
fullParents: context.fullParents,
|
|
176
209
|
}));
|
|
177
210
|
}
|
|
178
211
|
}
|
|
179
212
|
return query;
|
|
180
213
|
}
|
|
214
|
+
function createContext(override) {
|
|
215
|
+
return {
|
|
216
|
+
type: new Set(),
|
|
217
|
+
depth: 0,
|
|
218
|
+
parents: new Set(),
|
|
219
|
+
fullParents: new Set(),
|
|
220
|
+
children: [],
|
|
221
|
+
flexible: false,
|
|
222
|
+
...override,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
181
225
|
export function inferSurrealType(type, context) {
|
|
226
|
+
context ??= createContext();
|
|
227
|
+
function enter(type, ctx) {
|
|
228
|
+
context ??= createContext();
|
|
229
|
+
if (context.parents.has(type)) {
|
|
230
|
+
console.warn("Recursive type detected", type._zod.def.type);
|
|
231
|
+
context.type.add("any");
|
|
232
|
+
// throw new Error("Recursive type detected");
|
|
233
|
+
return { type: "any", context };
|
|
234
|
+
}
|
|
235
|
+
const newContext = ctx
|
|
236
|
+
? {
|
|
237
|
+
children: [],
|
|
238
|
+
flexible: false,
|
|
239
|
+
type: new Set(),
|
|
240
|
+
depth: context.depth + 1,
|
|
241
|
+
...(typeof ctx === "object" ? ctx : {}),
|
|
242
|
+
parents: context.parents,
|
|
243
|
+
fullParents: context.fullParents,
|
|
244
|
+
}
|
|
245
|
+
: context;
|
|
246
|
+
context.parents.add(type);
|
|
247
|
+
context.fullParents.add(type);
|
|
248
|
+
const result = inferSurrealType(type, newContext);
|
|
249
|
+
context.fullParents.delete(type);
|
|
250
|
+
context.parents.delete(type);
|
|
251
|
+
return result;
|
|
252
|
+
}
|
|
182
253
|
const schema = type;
|
|
183
254
|
if (!("_zod" in schema)) {
|
|
184
|
-
throw new Error("Invalid schema provided, make sure you are using zod v4
|
|
255
|
+
throw new Error("Invalid schema provided, make sure you are using zod v4+");
|
|
185
256
|
}
|
|
186
|
-
//
|
|
187
|
-
// return schema._zod.def.surreal.type;
|
|
188
|
-
// } else {
|
|
189
|
-
// throw new Error(
|
|
190
|
-
// // @ts-expect-error - zod core not supported
|
|
191
|
-
// `Invalid surreal schema provided. Received ${schema._zod.def.type}`,
|
|
192
|
-
// );
|
|
193
|
-
// }
|
|
257
|
+
// console.log(schema);
|
|
194
258
|
const def = schema._zod.def;
|
|
195
|
-
const childIndent = " ".repeat(context.depth + 1);
|
|
196
259
|
// const checks = getChecks(schema);
|
|
197
260
|
// parseChecks(context.name, checks, context, def.type);
|
|
198
261
|
// console.log(zodToSexpr(type));
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
262
|
+
// console.log(def);
|
|
263
|
+
if (def.surreal.type) {
|
|
264
|
+
context.type.add(def.surreal.type);
|
|
265
|
+
}
|
|
266
|
+
else
|
|
267
|
+
switch ( /* isSurrealZodSchemaDef(def) ? */def.type /*: def.type*/) {
|
|
268
|
+
// case "record_id": {
|
|
269
|
+
// const table = (def as ZodSurrealdRecordId["_zod"]["def"]).table;
|
|
270
|
+
// if (table) {
|
|
271
|
+
// context.type.add(`record<${table.map(escapeIdent).join(" | ")}>`);
|
|
272
|
+
// } else {
|
|
273
|
+
// context.type.add("record");
|
|
274
|
+
// }
|
|
275
|
+
// break;
|
|
276
|
+
// }
|
|
277
|
+
// case "uuid": {
|
|
278
|
+
// context.type.add("uuid");
|
|
279
|
+
// break;
|
|
280
|
+
// }
|
|
281
|
+
// case "table": {
|
|
282
|
+
// throw new Error(
|
|
283
|
+
// `Table type cannot be used as a field type.${OPEN_ISSUE_FOR_SUPPORT}`,
|
|
284
|
+
// );
|
|
285
|
+
// }
|
|
286
|
+
// case "void":
|
|
287
|
+
// case "never":
|
|
288
|
+
// case "undefined": {
|
|
289
|
+
// context.type.add("none");
|
|
290
|
+
// break;
|
|
291
|
+
// }
|
|
292
|
+
case "optional": {
|
|
293
|
+
enter(def.innerType);
|
|
294
|
+
context.type.add("none");
|
|
295
|
+
break;
|
|
219
296
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
//
|
|
251
|
-
//
|
|
252
|
-
//
|
|
253
|
-
// if (Object.keys(shape).length > 0) {
|
|
254
|
-
// type += "\n";
|
|
297
|
+
case "nonoptional": {
|
|
298
|
+
enter(def.innerType);
|
|
299
|
+
if (context.type.size > 1 && context.type.has("none")) {
|
|
300
|
+
context.type.delete("none");
|
|
301
|
+
}
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
case "nullable": {
|
|
305
|
+
enter(def.innerType);
|
|
306
|
+
context.type.add("null");
|
|
307
|
+
break;
|
|
308
|
+
}
|
|
309
|
+
// case "boolean": {
|
|
310
|
+
// context.type.add("bool");
|
|
311
|
+
// break;
|
|
312
|
+
// }
|
|
313
|
+
// case "string": {
|
|
314
|
+
// // Needs override, this will not work with original zod types
|
|
315
|
+
// // if (isStringFormat(def)) {
|
|
316
|
+
// // switch (def.format) {
|
|
317
|
+
// // case "uuid":
|
|
318
|
+
// // case "guid":
|
|
319
|
+
// // context.type.add("uuid");
|
|
320
|
+
// // break TYPE_CHECK;
|
|
321
|
+
// // }
|
|
322
|
+
// // }
|
|
323
|
+
// context.type.add("string");
|
|
324
|
+
// break;
|
|
325
|
+
// }
|
|
326
|
+
// case "bigint": {
|
|
327
|
+
// if (!isBigIntFormat(def as core.$ZodBigIntFormatDef)) {
|
|
328
|
+
// context.type.add("int");
|
|
329
|
+
// break;
|
|
255
330
|
// }
|
|
256
|
-
//
|
|
257
|
-
//
|
|
258
|
-
//
|
|
259
|
-
//
|
|
260
|
-
//
|
|
261
|
-
//
|
|
262
|
-
//
|
|
331
|
+
// switch ((def as core.$ZodBigIntFormatDef).format) {
|
|
332
|
+
// case "int64":
|
|
333
|
+
// case "uint64":
|
|
334
|
+
// context.type.add("int");
|
|
335
|
+
// break;
|
|
336
|
+
// default:
|
|
337
|
+
// throw new Error(
|
|
338
|
+
// `Unsupported bigint format: ${(def as core.$ZodBigIntFormatDef).format}`,
|
|
339
|
+
// );
|
|
263
340
|
// }
|
|
264
|
-
// type += "}";
|
|
265
|
-
// context.type.add(type);
|
|
266
341
|
// break;
|
|
267
342
|
// }
|
|
268
|
-
|
|
269
|
-
if (
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
343
|
+
// case "number": {
|
|
344
|
+
// if (!isNumberFormat(def as core.$ZodNumberDef)) {
|
|
345
|
+
// context.type.add("number");
|
|
346
|
+
// break;
|
|
347
|
+
// }
|
|
348
|
+
// switch ((def as core.$ZodNumberFormatDef).format) {
|
|
349
|
+
// case "uint32":
|
|
350
|
+
// case "safeint":
|
|
351
|
+
// case "int32":
|
|
352
|
+
// context.type.add("int");
|
|
353
|
+
// break;
|
|
354
|
+
// case "float64":
|
|
355
|
+
// case "float32":
|
|
356
|
+
// context.type.add("float");
|
|
357
|
+
// break;
|
|
358
|
+
// default:
|
|
359
|
+
// throw new Error(
|
|
360
|
+
// `Unsupported number format: ${(def as core.$ZodNumberFormatDef).format}. ${OPEN_ISSUE_FOR_SUPPORT}`,
|
|
361
|
+
// );
|
|
362
|
+
// }
|
|
363
|
+
// break;
|
|
364
|
+
// }
|
|
365
|
+
// case "date": {
|
|
366
|
+
// context.type.add("datetime");
|
|
367
|
+
// break;
|
|
368
|
+
// }
|
|
369
|
+
case "object": {
|
|
370
|
+
const shape = def.shape;
|
|
371
|
+
const catchall = def.catchall;
|
|
372
|
+
const isStrict = catchall?._zod.traits.has("$ZodNever");
|
|
373
|
+
const isLoose = catchall?._zod.traits.has("$ZodUnknown");
|
|
374
|
+
// buggy syntax
|
|
375
|
+
// if (isStrict) {
|
|
376
|
+
// let type = "{";
|
|
377
|
+
// if (Object.keys(shape).length > 0) {
|
|
378
|
+
// type += "\n";
|
|
379
|
+
// }
|
|
380
|
+
// for (const [key, value] of Object.entries(shape)) {
|
|
381
|
+
// const childContext: ZodSurrealTypeContext = {
|
|
382
|
+
// type: new Set(),
|
|
383
|
+
// depth: context.depth + 1,
|
|
384
|
+
// children: [],
|
|
385
|
+
// };
|
|
386
|
+
// type += `${childIndent}${escapeIdent(key)}: ${inferSurrealType(value, childContext).inner},\n`;
|
|
387
|
+
// }
|
|
388
|
+
// type += "}";
|
|
389
|
+
// context.type.add(type);
|
|
390
|
+
// break;
|
|
391
|
+
// }
|
|
392
|
+
context.type.add("object");
|
|
393
|
+
if (isLoose)
|
|
394
|
+
context.flexible = true;
|
|
395
|
+
for (const [key, value] of Object.entries(shape)) {
|
|
396
|
+
context.children.push({ name: key, type: value });
|
|
397
|
+
}
|
|
398
|
+
break;
|
|
273
399
|
}
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
400
|
+
case "array": {
|
|
401
|
+
const { type: element } = enter(def.element, true);
|
|
402
|
+
if (element === "any") {
|
|
403
|
+
context.type.add("array");
|
|
404
|
+
break;
|
|
405
|
+
}
|
|
406
|
+
context.type.add(`array<${element}>`);
|
|
407
|
+
break;
|
|
280
408
|
}
|
|
281
|
-
|
|
282
|
-
|
|
409
|
+
case "set": {
|
|
410
|
+
const { type: element } = enter(def.valueType, true);
|
|
411
|
+
if (element === "any") {
|
|
412
|
+
context.type.add("array");
|
|
413
|
+
break;
|
|
414
|
+
}
|
|
415
|
+
context.type.add(`array<${element}>`);
|
|
416
|
+
break;
|
|
417
|
+
}
|
|
418
|
+
case "enum": {
|
|
419
|
+
const values = def.entries;
|
|
420
|
+
for (const key in values) {
|
|
421
|
+
const value = values[key];
|
|
422
|
+
context.type.add(toSurqlString(value));
|
|
423
|
+
}
|
|
424
|
+
break;
|
|
425
|
+
}
|
|
426
|
+
case "union": {
|
|
427
|
+
for (const option of def.options) {
|
|
428
|
+
// context.type.add(inferSurrealType(option, context).inner);
|
|
429
|
+
enter(option);
|
|
430
|
+
}
|
|
431
|
+
break;
|
|
432
|
+
}
|
|
433
|
+
// case "intersection": {
|
|
434
|
+
// // TODO: Find a way to handle intersections
|
|
435
|
+
// // Maybe a new function where we build a new object schema (or primitive one)
|
|
436
|
+
// // And keep track of all the types that are used in the intersection
|
|
437
|
+
// //
|
|
438
|
+
// // const left = def.left;
|
|
439
|
+
// // const right = def.right;
|
|
440
|
+
// // inferSurrealType(left, context);
|
|
441
|
+
// // inferSurrealType(right, context);
|
|
442
|
+
// // inferSurrealType(z.never(), context);
|
|
443
|
+
// // context.type.add("any");
|
|
444
|
+
// context.type.add("any");
|
|
445
|
+
// break;
|
|
446
|
+
// }
|
|
447
|
+
case "tuple": {
|
|
448
|
+
if (def.rest) {
|
|
449
|
+
context.type.add("array");
|
|
450
|
+
break;
|
|
451
|
+
}
|
|
452
|
+
const types = new Set();
|
|
453
|
+
for (const item of def.items) {
|
|
454
|
+
types.add(enter(item, true).type);
|
|
455
|
+
}
|
|
456
|
+
context.type.add(`[${Array.from(types).join(", ")}]`);
|
|
457
|
+
break;
|
|
458
|
+
}
|
|
459
|
+
// case "record": {
|
|
460
|
+
// context.type.add("object");
|
|
461
|
+
// // Currently there is no way to restrict the key type of an object, so we just use *
|
|
462
|
+
// // context.children.push({ name: "*", type: def.keyType });
|
|
463
|
+
// // All commented out code is because of this. Check is only done in JS side.
|
|
464
|
+
// enter((def as core.$ZodRecordDef).keyType, true);
|
|
465
|
+
// /* const isPartial =
|
|
466
|
+
// def.keyType._zod.values === undefined &&
|
|
467
|
+
// !keyContext.type.has("string") &&
|
|
468
|
+
// !keyContext.type.has("number") &&
|
|
469
|
+
// !keyContext.type.has("int") &&
|
|
470
|
+
// !keyContext.type.has("float") &&
|
|
471
|
+
// !keyContext.type.has("decimal"); */
|
|
472
|
+
// context.children.push({
|
|
473
|
+
// name: "*",
|
|
474
|
+
// type: /* isPartial ? z.optional(def.valueType) : */ (
|
|
475
|
+
// def as core.$ZodRecordDef
|
|
476
|
+
// ).valueType,
|
|
477
|
+
// });
|
|
478
|
+
// break;
|
|
479
|
+
// }
|
|
480
|
+
// case "map": {
|
|
481
|
+
// context.type.add("object");
|
|
482
|
+
// // Currently there is no way to restrict the key type of an object, so we just use *
|
|
483
|
+
// // Surreal doesnt have a map type, so we use object instead. We cant really support non PropertyKey values
|
|
484
|
+
// // unless we serialize the keys to strings.
|
|
485
|
+
// const { context: keyContext } = enter(
|
|
486
|
+
// (def as core.$ZodMapDef).keyType,
|
|
487
|
+
// true,
|
|
488
|
+
// );
|
|
489
|
+
// for (const key of keyContext.type) {
|
|
490
|
+
// if (!["string", "number", "float", "int", "decimal"].includes(key)) {
|
|
491
|
+
// throw new Error(`Unsupported key type: ${key}`);
|
|
492
|
+
// }
|
|
493
|
+
// }
|
|
494
|
+
// context.children.push({
|
|
495
|
+
// name: "*",
|
|
496
|
+
// type: (def as core.$ZodMapDef).valueType,
|
|
497
|
+
// });
|
|
498
|
+
// break;
|
|
499
|
+
// }
|
|
500
|
+
case "literal": {
|
|
501
|
+
for (const value of def.values) {
|
|
502
|
+
context.type.add(toSurqlString(value));
|
|
503
|
+
}
|
|
504
|
+
break;
|
|
505
|
+
}
|
|
506
|
+
case "file": {
|
|
507
|
+
throw new Error(`File type cannot be used as a field type.${OPEN_ISSUE_FOR_SUPPORT}`);
|
|
508
|
+
}
|
|
509
|
+
case "transform": {
|
|
510
|
+
break;
|
|
511
|
+
}
|
|
512
|
+
case "readonly":
|
|
513
|
+
case "catch":
|
|
514
|
+
case "prefault":
|
|
515
|
+
case "default": {
|
|
516
|
+
enter(def.innerType);
|
|
517
|
+
break;
|
|
518
|
+
}
|
|
519
|
+
case "success": {
|
|
520
|
+
context.type.add("string");
|
|
521
|
+
break;
|
|
522
|
+
}
|
|
523
|
+
case "nan": {
|
|
524
|
+
context.type.add("number");
|
|
525
|
+
break;
|
|
526
|
+
}
|
|
527
|
+
case "pipe": {
|
|
528
|
+
enter(def.in);
|
|
529
|
+
enter(def.out);
|
|
530
|
+
break;
|
|
531
|
+
}
|
|
532
|
+
case "template_literal": {
|
|
533
|
+
context.type.add("string");
|
|
534
|
+
break;
|
|
535
|
+
}
|
|
536
|
+
case "lazy": {
|
|
537
|
+
const innerType = def.getter();
|
|
538
|
+
// All that cascading to get here, we dont want to keep complex types if
|
|
539
|
+
// recursive.
|
|
540
|
+
if (context.fullParents.has(type) || context.parents.has(type)) {
|
|
541
|
+
context.type.add("any");
|
|
542
|
+
}
|
|
543
|
+
else {
|
|
544
|
+
enter(innerType);
|
|
545
|
+
}
|
|
546
|
+
break;
|
|
547
|
+
}
|
|
548
|
+
case "promise": {
|
|
549
|
+
// We will not support promises for now, this can be uncommented after
|
|
550
|
+
// support is added
|
|
551
|
+
// const { inner: innerType } =
|
|
552
|
+
// enter(def.innerType);
|
|
553
|
+
// context.type.add(innerType);
|
|
554
|
+
throw new Error(`Promise type cannot be used as a field type.${OPEN_ISSUE_FOR_SUPPORT}`);
|
|
555
|
+
}
|
|
556
|
+
case "function": {
|
|
557
|
+
throw new Error(`Function type cannot be used as a field type.${OPEN_ISSUE_FOR_SUPPORT}`);
|
|
558
|
+
}
|
|
559
|
+
case "custom": {
|
|
560
|
+
throw new Error(`Custom type cannot be used as a field type.${OPEN_ISSUE_FOR_SUPPORT}`);
|
|
561
|
+
}
|
|
562
|
+
case "symbol": {
|
|
563
|
+
throw new Error(`Symbol type cannot be used as a field type.${OPEN_ISSUE_FOR_SUPPORT}`);
|
|
283
564
|
}
|
|
284
|
-
break;
|
|
285
|
-
}
|
|
286
|
-
case "table": {
|
|
287
|
-
throw new Error("Table type cannot be used as a field type");
|
|
288
565
|
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
}
|
|
293
|
-
return Array.from(context.type).join(" | ");
|
|
566
|
+
const inner = context.type.has("any") || context.type.size === 0
|
|
567
|
+
? "any"
|
|
568
|
+
: Array.from(context.type).join(" | ");
|
|
569
|
+
return { type: inner, context };
|
|
294
570
|
}
|
|
295
|
-
// function
|
|
296
|
-
//
|
|
297
|
-
//
|
|
298
|
-
//
|
|
299
|
-
// checks.unshift(schema as z4.$ZodCheck);
|
|
300
|
-
// }
|
|
301
|
-
// return checks;
|
|
571
|
+
// function isSurrealZodSchemaDef(
|
|
572
|
+
// def: core.$ZodTypeDef | ZodSurrealTypeDef,
|
|
573
|
+
// ): def is ZodSurrealTypeDef {
|
|
574
|
+
// return "surreal" in def && def.surreal.type !== undefined;
|
|
302
575
|
// }
|
|
303
|
-
// function
|
|
304
|
-
//
|
|
305
|
-
//
|
|
306
|
-
//
|
|
307
|
-
// type: ZodTypeName | SurrealZodTypeName,
|
|
308
|
-
// ) {
|
|
309
|
-
// for (const check of checks) {
|
|
310
|
-
// const { transform, assert } = parseCheck(name, check, type);
|
|
311
|
-
// if (transform) {
|
|
312
|
-
// context.transforms.push(transform);
|
|
313
|
-
// }
|
|
314
|
-
// if (assert) {
|
|
315
|
-
// context.asserts.push(assert);
|
|
316
|
-
// }
|
|
317
|
-
// }
|
|
576
|
+
// function isStringFormat(
|
|
577
|
+
// def: core.$ZodStringDef,
|
|
578
|
+
// ): def is core.$ZodStringFormatTypes["_zod"]["def"] {
|
|
579
|
+
// return def.type === "string" && "format" in def;
|
|
318
580
|
// }
|
|
319
|
-
//
|
|
320
|
-
//
|
|
321
|
-
//
|
|
322
|
-
//
|
|
323
|
-
// min_length(name: string, value: number, type: ZodTypeName) {
|
|
324
|
-
// if (type === "array") {
|
|
325
|
-
// return `$value.len() >= ${value} || { THROW 'Field "${name}" must have at least ${value} ${value === 1 ? "item" : "items"}' };`;
|
|
326
|
-
// }
|
|
327
|
-
// if (type === "string") {
|
|
328
|
-
// return `$value.len() >= ${value} || { THROW 'Field "${name}" must be at least ${value} ${value === 1 ? "character" : "characters"} long' };`;
|
|
329
|
-
// }
|
|
330
|
-
// throw new Error(`Invalid type: ${type}`);
|
|
331
|
-
// },
|
|
332
|
-
// max_length(name: string, value: number, type: ZodTypeName) {
|
|
333
|
-
// if (type === "array") {
|
|
334
|
-
// return `$value.len() <= ${value} || { THROW 'Field "${name}" must have at most ${value} ${value === 1 ? "item" : "items"}' };`;
|
|
335
|
-
// }
|
|
336
|
-
// if (type === "string") {
|
|
337
|
-
// return `$value.len() <= ${value} || { THROW 'Field "${name}" must be at most ${value} ${value === 1 ? "character" : "characters"} long' };`;
|
|
338
|
-
// }
|
|
339
|
-
// throw new Error(`Invalid type: ${type}`);
|
|
340
|
-
// },
|
|
341
|
-
// greater_than(name: string, value: z4.util.Numeric, inclusive: boolean) {
|
|
342
|
-
// return `$value ${inclusive ? ">=" : ">"} ${value} || { THROW 'Field "${name}" must be greater than ${inclusive ? "or equal to" : ""} ${value}' };`;
|
|
343
|
-
// },
|
|
344
|
-
// less_than(name: string, value: z4.util.Numeric, inclusive: boolean) {
|
|
345
|
-
// return `$value ${inclusive ? "<=" : "<"} ${value} || { THROW 'Field "${name}" must be less than ${inclusive ? "or equal to" : ""} ${value}' };`;
|
|
346
|
-
// },
|
|
347
|
-
// length_equals(name: string, value: number, type: ZodTypeName = "string") {
|
|
348
|
-
// if (type === "array") {
|
|
349
|
-
// return `$value.len() == ${value} || { THROW 'Field "${name}" must have exactly ${value} ${value === 1 ? "item" : "items"}' };`;
|
|
350
|
-
// }
|
|
351
|
-
// if (type === "string") {
|
|
352
|
-
// return `$value.len() == ${value} || { THROW 'Field "${name}" must be exactly ${value} ${value === 1 ? "character" : "characters"} long' };`;
|
|
353
|
-
// }
|
|
354
|
-
// throw new Error(`Invalid type: ${type}`);
|
|
355
|
-
// },
|
|
356
|
-
// string_format: {
|
|
357
|
-
// email: (name: string) => {
|
|
358
|
-
// const regex =
|
|
359
|
-
// /^[A-Za-z0-9'_+-]+(?:\.[A-Za-z0-9'_+-]+)*@([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$/;
|
|
360
|
-
// return `string::matches($value, ${regex}) || { THROW "Field '${name}' must be a valid email address" };`;
|
|
361
|
-
// },
|
|
362
|
-
// url: (
|
|
363
|
-
// name: string,
|
|
364
|
-
// def?: Pick<z4.$ZodCheckURLParams, "hostname" | "protocol" | "normalize">,
|
|
365
|
-
// ) => {
|
|
366
|
-
// return dedent`
|
|
367
|
-
// LET $url = {
|
|
368
|
-
// scheme: parse::url::scheme($value),
|
|
369
|
-
// host: parse::url::host($value),
|
|
370
|
-
// domain: parse::url::domain($value),
|
|
371
|
-
// path: parse::url::path($value),
|
|
372
|
-
// port: parse::url::port($value),
|
|
373
|
-
// query: parse::url::query($value),
|
|
374
|
-
// hash: parse::url::fragment($value),
|
|
375
|
-
// };
|
|
376
|
-
// $url.scheme || { THROW "Field '${name}' must be a valid URL" };
|
|
377
|
-
// ${
|
|
378
|
-
// def?.hostname
|
|
379
|
-
// ? `($url.host ?? "").matches(${def.hostname}) || { THROW "Field '${name}' must match hostname ${def.hostname.toString().replace(/\\/g, "\\\\")}" };`
|
|
380
|
-
// : ""
|
|
381
|
-
// }
|
|
382
|
-
// ${
|
|
383
|
-
// def?.protocol
|
|
384
|
-
// ? `($url.scheme ?? "").matches(${def.protocol}) || { THROW "Field '${name}' must match protocol ${def.protocol.toString().replace(/\\/g, "\\\\")}" };`
|
|
385
|
-
// : ""
|
|
386
|
-
// }
|
|
387
|
-
// $url.scheme + "://" + ($url.host ?? "") + (
|
|
388
|
-
// IF $url.port && (
|
|
389
|
-
// ($url.scheme == "http" && $url.port != 80) ||
|
|
390
|
-
// ($url.scheme == "https" && $url.port != 443)
|
|
391
|
-
// ) { ":" + <string>$url.port } ?? ""
|
|
392
|
-
// )
|
|
393
|
-
// + ($url.path ?? "")
|
|
394
|
-
// + (IF $url.query { "?" + $url.query } ?? "")
|
|
395
|
-
// + (IF $url.fragment { "#" + $url.fragment } ?? "");
|
|
396
|
-
// `;
|
|
397
|
-
// },
|
|
398
|
-
// },
|
|
399
|
-
// };
|
|
400
|
-
// function parseCheck(
|
|
401
|
-
// name: string,
|
|
402
|
-
// _check: z4.$ZodCheck,
|
|
403
|
-
// type: ZodTypeName,
|
|
404
|
-
// ): { transform?: string; assert?: string } {
|
|
405
|
-
// const check = _check as z4.$ZodChecks;
|
|
406
|
-
// const def = check._zod.def;
|
|
407
|
-
// switch (def.check) {
|
|
408
|
-
// case "min_length":
|
|
409
|
-
// return { assert: checkMap.min_length(name, def.minimum, type) };
|
|
410
|
-
// case "max_length":
|
|
411
|
-
// return { assert: checkMap.max_length(name, def.maximum, type) };
|
|
412
|
-
// case "greater_than":
|
|
413
|
-
// return { assert: checkMap.greater_than(name, def.value, def.inclusive) };
|
|
414
|
-
// case "less_than":
|
|
415
|
-
// return { assert: checkMap.less_than(name, def.value, def.inclusive) };
|
|
416
|
-
// case "length_equals":
|
|
417
|
-
// return { assert: checkMap.length_equals(name, def.length, type) };
|
|
418
|
-
// case "string_format":
|
|
419
|
-
// return assertionForStringFormat(name, check);
|
|
420
|
-
// default:
|
|
421
|
-
// return { assert: `THROW 'Unknown check: ${def.check}';` };
|
|
422
|
-
// }
|
|
581
|
+
// function isBigIntFormat(
|
|
582
|
+
// def: core.$ZodBigIntDef,
|
|
583
|
+
// ): def is core.$ZodBigIntFormatDef {
|
|
584
|
+
// return def.type === "bigint" && "format" in def;
|
|
423
585
|
// }
|
|
424
|
-
//
|
|
425
|
-
//
|
|
426
|
-
//
|
|
427
|
-
//
|
|
428
|
-
// ): { transform?: string; assert?: string } {
|
|
429
|
-
// const check = _check as z4.$ZodStringFormatChecks;
|
|
430
|
-
// const def = check._zod.def;
|
|
431
|
-
// switch (def.format) {
|
|
432
|
-
// case "email": {
|
|
433
|
-
// return { assert: checkMap.string_format.email(name) };
|
|
434
|
-
// }
|
|
435
|
-
// case "url": {
|
|
436
|
-
// const code = checkMap.string_format.url(name, def);
|
|
437
|
-
// return def.normalize ? { transform: code } : { assert: code };
|
|
438
|
-
// }
|
|
439
|
-
// default:
|
|
440
|
-
// return { assert: `THROW 'Unsupported string format: ${def.format}';` };
|
|
441
|
-
// }
|
|
586
|
+
// function isNumberFormat(
|
|
587
|
+
// def: core.$ZodNumberDef,
|
|
588
|
+
// ): def is core.$ZodNumberFormatDef {
|
|
589
|
+
// return def.type === "number" && "format" in def;
|
|
442
590
|
// }
|
|
591
|
+
// // function getChecks(_schema: z4.$ZodType | SurrealZodType) {
|
|
592
|
+
// // const schema = _schema as z4.$ZodTypes | SurrealZodTypes;
|
|
593
|
+
// // const checks = schema._zod.def.checks ?? [];
|
|
594
|
+
// // if ("check" in schema._zod.def) {
|
|
595
|
+
// // checks.unshift(schema as z4.$ZodCheck);
|
|
596
|
+
// // }
|
|
597
|
+
// // return checks;
|
|
598
|
+
// // }
|
|
599
|
+
// // function parseChecks(
|
|
600
|
+
// // name: string,
|
|
601
|
+
// // checks: z4.$ZodCheck[],
|
|
602
|
+
// // context: ZodSurrealTypeContext,
|
|
603
|
+
// // type: ZodTypeName | SurrealZodTypeName,
|
|
604
|
+
// // ) {
|
|
605
|
+
// // for (const check of checks) {
|
|
606
|
+
// // const { transform, assert } = parseCheck(name, check, type);
|
|
607
|
+
// // if (transform) {
|
|
608
|
+
// // context.transforms.push(transform);
|
|
609
|
+
// // }
|
|
610
|
+
// // if (assert) {
|
|
611
|
+
// // context.asserts.push(assert);
|
|
612
|
+
// // }
|
|
613
|
+
// // }
|
|
614
|
+
// // }
|
|
615
|
+
// // export const checkMap = {
|
|
616
|
+
// // never(name: string) {
|
|
617
|
+
// // return `THROW 'Field "${name}" must never be present'`;
|
|
618
|
+
// // },
|
|
619
|
+
// // min_length(name: string, value: number, type: ZodTypeName) {
|
|
620
|
+
// // if (type === "array") {
|
|
621
|
+
// // return `$value.len() >= ${value} || { THROW 'Field "${name}" must have at least ${value} ${value === 1 ? "item" : "items"}' };`;
|
|
622
|
+
// // }
|
|
623
|
+
// // if (type === "string") {
|
|
624
|
+
// // return `$value.len() >= ${value} || { THROW 'Field "${name}" must be at least ${value} ${value === 1 ? "character" : "characters"} long' };`;
|
|
625
|
+
// // }
|
|
626
|
+
// // throw new Error(`Invalid type: ${type}`);
|
|
627
|
+
// // },
|
|
628
|
+
// // max_length(name: string, value: number, type: ZodTypeName) {
|
|
629
|
+
// // if (type === "array") {
|
|
630
|
+
// // return `$value.len() <= ${value} || { THROW 'Field "${name}" must have at most ${value} ${value === 1 ? "item" : "items"}' };`;
|
|
631
|
+
// // }
|
|
632
|
+
// // if (type === "string") {
|
|
633
|
+
// // return `$value.len() <= ${value} || { THROW 'Field "${name}" must be at most ${value} ${value === 1 ? "character" : "characters"} long' };`;
|
|
634
|
+
// // }
|
|
635
|
+
// // throw new Error(`Invalid type: ${type}`);
|
|
636
|
+
// // },
|
|
637
|
+
// // greater_than(name: string, value: z4.util.Numeric, inclusive: boolean) {
|
|
638
|
+
// // return `$value ${inclusive ? ">=" : ">"} ${value} || { THROW 'Field "${name}" must be greater than ${inclusive ? "or equal to" : ""} ${value}' };`;
|
|
639
|
+
// // },
|
|
640
|
+
// // less_than(name: string, value: z4.util.Numeric, inclusive: boolean) {
|
|
641
|
+
// // return `$value ${inclusive ? "<=" : "<"} ${value} || { THROW 'Field "${name}" must be less than ${inclusive ? "or equal to" : ""} ${value}' };`;
|
|
642
|
+
// // },
|
|
643
|
+
// // length_equals(name: string, value: number, type: ZodTypeName = "string") {
|
|
644
|
+
// // if (type === "array") {
|
|
645
|
+
// // return `$value.len() == ${value} || { THROW 'Field "${name}" must have exactly ${value} ${value === 1 ? "item" : "items"}' };`;
|
|
646
|
+
// // }
|
|
647
|
+
// // if (type === "string") {
|
|
648
|
+
// // return `$value.len() == ${value} || { THROW 'Field "${name}" must be exactly ${value} ${value === 1 ? "character" : "characters"} long' };`;
|
|
649
|
+
// // }
|
|
650
|
+
// // throw new Error(`Invalid type: ${type}`);
|
|
651
|
+
// // },
|
|
652
|
+
// // string_format: {
|
|
653
|
+
// // email: (name: string) => {
|
|
654
|
+
// // const regex =
|
|
655
|
+
// // /^[A-Za-z0-9'_+-]+(?:\.[A-Za-z0-9'_+-]+)*@([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$/;
|
|
656
|
+
// // return `string::matches($value, ${regex}) || { THROW "Field '${name}' must be a valid email address" };`;
|
|
657
|
+
// // },
|
|
658
|
+
// // url: (
|
|
659
|
+
// // name: string,
|
|
660
|
+
// // def?: Pick<z4.$ZodCheckURLParams, "hostname" | "protocol" | "normalize">,
|
|
661
|
+
// // ) => {
|
|
662
|
+
// // return dedent`
|
|
663
|
+
// // LET $url = {
|
|
664
|
+
// // scheme: parse::url::scheme($value),
|
|
665
|
+
// // host: parse::url::host($value),
|
|
666
|
+
// // domain: parse::url::domain($value),
|
|
667
|
+
// // path: parse::url::path($value),
|
|
668
|
+
// // port: parse::url::port($value),
|
|
669
|
+
// // query: parse::url::query($value),
|
|
670
|
+
// // hash: parse::url::fragment($value),
|
|
671
|
+
// // };
|
|
672
|
+
// // $url.scheme || { THROW "Field '${name}' must be a valid URL" };
|
|
673
|
+
// // ${
|
|
674
|
+
// // def?.hostname
|
|
675
|
+
// // ? `($url.host ?? "").matches(${def.hostname}) || { THROW "Field '${name}' must match hostname ${def.hostname.toString().replace(/\\/g, "\\\\")}" };`
|
|
676
|
+
// // : ""
|
|
677
|
+
// // }
|
|
678
|
+
// // ${
|
|
679
|
+
// // def?.protocol
|
|
680
|
+
// // ? `($url.scheme ?? "").matches(${def.protocol}) || { THROW "Field '${name}' must match protocol ${def.protocol.toString().replace(/\\/g, "\\\\")}" };`
|
|
681
|
+
// // : ""
|
|
682
|
+
// // }
|
|
683
|
+
// // $url.scheme + "://" + ($url.host ?? "") + (
|
|
684
|
+
// // IF $url.port && (
|
|
685
|
+
// // ($url.scheme == "http" && $url.port != 80) ||
|
|
686
|
+
// // ($url.scheme == "https" && $url.port != 443)
|
|
687
|
+
// // ) { ":" + <string>$url.port } ?? ""
|
|
688
|
+
// // )
|
|
689
|
+
// // + ($url.path ?? "")
|
|
690
|
+
// // + (IF $url.query { "?" + $url.query } ?? "")
|
|
691
|
+
// // + (IF $url.fragment { "#" + $url.fragment } ?? "");
|
|
692
|
+
// // `;
|
|
693
|
+
// // },
|
|
694
|
+
// // },
|
|
695
|
+
// // };
|
|
696
|
+
// // function parseCheck(
|
|
697
|
+
// // name: string,
|
|
698
|
+
// // _check: z4.$ZodCheck,
|
|
699
|
+
// // type: ZodTypeName,
|
|
700
|
+
// // ): { transform?: string; assert?: string } {
|
|
701
|
+
// // const check = _check as z4.$ZodChecks;
|
|
702
|
+
// // const def = check._zod.def;
|
|
703
|
+
// // switch (def.check) {
|
|
704
|
+
// // case "min_length":
|
|
705
|
+
// // return { assert: checkMap.min_length(name, def.minimum, type) };
|
|
706
|
+
// // case "max_length":
|
|
707
|
+
// // return { assert: checkMap.max_length(name, def.maximum, type) };
|
|
708
|
+
// // case "greater_than":
|
|
709
|
+
// // return { assert: checkMap.greater_than(name, def.value, def.inclusive) };
|
|
710
|
+
// // case "less_than":
|
|
711
|
+
// // return { assert: checkMap.less_than(name, def.value, def.inclusive) };
|
|
712
|
+
// // case "length_equals":
|
|
713
|
+
// // return { assert: checkMap.length_equals(name, def.length, type) };
|
|
714
|
+
// // case "string_format":
|
|
715
|
+
// // return assertionForStringFormat(name, check);
|
|
716
|
+
// // default:
|
|
717
|
+
// // return { assert: `THROW 'Unknown check: ${def.check}';` };
|
|
718
|
+
// // }
|
|
719
|
+
// // }
|
|
720
|
+
// // // Remove look-around, look-behind, and look-ahead as they are not supported by SurrealDB
|
|
721
|
+
// // function assertionForStringFormat(
|
|
722
|
+
// // name: string,
|
|
723
|
+
// // _check: z4.$ZodCheck,
|
|
724
|
+
// // ): { transform?: string; assert?: string } {
|
|
725
|
+
// // const check = _check as z4.$ZodStringFormatChecks;
|
|
726
|
+
// // const def = check._zod.def;
|
|
727
|
+
// // switch (def.format) {
|
|
728
|
+
// // case "email": {
|
|
729
|
+
// // return { assert: checkMap.string_format.email(name) };
|
|
730
|
+
// // }
|
|
731
|
+
// // case "url": {
|
|
732
|
+
// // const code = checkMap.string_format.url(name, def);
|
|
733
|
+
// // return def.normalize ? { transform: code } : { assert: code };
|
|
734
|
+
// // }
|
|
735
|
+
// // default:
|
|
736
|
+
// // return { assert: `THROW 'Unsupported string format: ${def.format}';` };
|
|
737
|
+
// // }
|
|
738
|
+
// // }
|
|
739
|
+
const SurrealQLStatements = [
|
|
740
|
+
"ACCESS",
|
|
741
|
+
"ALTER",
|
|
742
|
+
"BEGIN",
|
|
743
|
+
"BREAK",
|
|
744
|
+
"CANCEL",
|
|
745
|
+
"COMMIT",
|
|
746
|
+
"CONTINUE",
|
|
747
|
+
"CREATE",
|
|
748
|
+
"DEFINE",
|
|
749
|
+
"DELETE",
|
|
750
|
+
"FOR",
|
|
751
|
+
"IF",
|
|
752
|
+
"INFO",
|
|
753
|
+
"INSERT",
|
|
754
|
+
"KILL",
|
|
755
|
+
"LET",
|
|
756
|
+
"LIVE",
|
|
757
|
+
"REBUILD",
|
|
758
|
+
"RELATE",
|
|
759
|
+
"REMOVE",
|
|
760
|
+
"RETURN",
|
|
761
|
+
"SELECT",
|
|
762
|
+
"SHOW",
|
|
763
|
+
"SLEEP",
|
|
764
|
+
"THROW",
|
|
765
|
+
"UPDATE",
|
|
766
|
+
"UPSERT",
|
|
767
|
+
"USE",
|
|
768
|
+
"EXPLAIN",
|
|
769
|
+
"FETCH",
|
|
770
|
+
];
|
|
771
|
+
function hasMultipleStatements(query) {
|
|
772
|
+
let inString = false;
|
|
773
|
+
let escaping = false;
|
|
774
|
+
let statements = 0;
|
|
775
|
+
let buffer = "";
|
|
776
|
+
for (let i = 0; i < query.length; i++) {
|
|
777
|
+
const ch = query[i];
|
|
778
|
+
const nextBuffer = `${buffer}${ch}`;
|
|
779
|
+
if (ch === "\n")
|
|
780
|
+
return true;
|
|
781
|
+
if (inString) {
|
|
782
|
+
if (escaping) {
|
|
783
|
+
escaping = false;
|
|
784
|
+
continue;
|
|
785
|
+
}
|
|
786
|
+
if (ch === "\\") {
|
|
787
|
+
escaping = true;
|
|
788
|
+
continue;
|
|
789
|
+
}
|
|
790
|
+
if (ch === inString) {
|
|
791
|
+
inString = false;
|
|
792
|
+
continue;
|
|
793
|
+
}
|
|
794
|
+
continue;
|
|
795
|
+
}
|
|
796
|
+
if (ch === '"' || ch === "'") {
|
|
797
|
+
inString = ch;
|
|
798
|
+
continue;
|
|
799
|
+
}
|
|
800
|
+
if (ch === " ") {
|
|
801
|
+
if (SurrealQLStatements.includes(buffer.toUpperCase())) {
|
|
802
|
+
return true;
|
|
803
|
+
}
|
|
804
|
+
continue;
|
|
805
|
+
}
|
|
806
|
+
if (ch === ";" ||
|
|
807
|
+
// Single line Comments
|
|
808
|
+
nextBuffer === "--" ||
|
|
809
|
+
nextBuffer === "//" ||
|
|
810
|
+
ch === "#") {
|
|
811
|
+
statements++;
|
|
812
|
+
buffer = "";
|
|
813
|
+
continue;
|
|
814
|
+
}
|
|
815
|
+
buffer = nextBuffer;
|
|
816
|
+
if (statements > 1)
|
|
817
|
+
return true;
|
|
818
|
+
}
|
|
819
|
+
if (statements > 0 && (buffer || inString || escaping))
|
|
820
|
+
return true;
|
|
821
|
+
return statements > 1;
|
|
822
|
+
}
|
|
823
|
+
export function formatQuery(query) {
|
|
824
|
+
if (hasMultipleStatements(query)) {
|
|
825
|
+
return `{\n ${dedent.withOptions({ alignValues: true }) ` ${query.trimStart()}`}\n}`;
|
|
826
|
+
}
|
|
827
|
+
return query.trim();
|
|
828
|
+
}
|
|
829
|
+
export function inlineQueryParameters(query) {
|
|
830
|
+
let value = query.query;
|
|
831
|
+
for (const [paramName, paramValue] of Object.entries(query.bindings ?? {})) {
|
|
832
|
+
value = value.replace(new RegExp(`\\$${paramName}\\b`, "g"), toSurqlString(paramValue));
|
|
833
|
+
}
|
|
834
|
+
return value;
|
|
835
|
+
}
|
|
836
|
+
function toSurqlString(value) {
|
|
837
|
+
return baseToSurqlString(value).replace(/^s"/g, '"');
|
|
838
|
+
}
|