@tstdl/base 0.93.48 → 0.93.50
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/ai/ai.service.js +7 -7
- package/ai/functions.js +1 -1
- package/orm/server/repository.js +8 -9
- package/package.json +7 -4
- package/schema/converters/{openapi-converter.js → open-api-converter.js} +19 -12
- package/schema/converters/zod-converter.d.ts +3 -0
- package/schema/converters/zod-converter.js +172 -0
- package/schema/schemas/array.js +2 -2
- package/schema/schemas/date.d.ts +7 -4
- package/schema/schemas/date.js +11 -6
- package/schema/schemas/function.js +2 -2
- package/schema/schemas/instance.d.ts +1 -1
- package/schema/schemas/instance.js +1 -1
- package/schema/schemas/object.d.ts +5 -0
- package/schema/schemas/object.js +12 -0
- package/schema/schemas/regexp.d.ts +1 -1
- package/schema/schemas/regexp.js +2 -2
- package/schema/schemas/uint8-array.d.ts +4 -1
- package/schema/schemas/uint8-array.js +32 -3
- package/utils/encoding.js +1 -1
- package/utils/z-base32.d.ts +1 -1
- package/utils/z-base32.js +2 -1
- package/schema/converters/index.d.ts +0 -1
- package/schema/converters/index.js +0 -1
- /package/schema/converters/{openapi-converter.d.ts → open-api-converter.d.ts} +0 -0
package/ai/ai.service.js
CHANGED
|
@@ -6,7 +6,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
6
6
|
};
|
|
7
7
|
var _a;
|
|
8
8
|
var AiService_1;
|
|
9
|
-
import { FinishReason, FunctionCallingConfigMode as GoogleFunctionCallingMode, GoogleGenAI } from '@google/genai';
|
|
9
|
+
import { ApiError, FinishReason, FunctionCallingConfigMode as GoogleFunctionCallingMode, GoogleGenAI } from '@google/genai';
|
|
10
10
|
import { match } from 'ts-pattern';
|
|
11
11
|
import { CancellationSignal } from '../cancellation/index.js';
|
|
12
12
|
import { NotSupportedError } from '../errors/not-supported.error.js';
|
|
@@ -15,7 +15,7 @@ import { inject, injectArgument } from '../injector/inject.js';
|
|
|
15
15
|
import { Logger } from '../logger/logger.js';
|
|
16
16
|
import { DeferredPromise } from '../promise/deferred-promise.js';
|
|
17
17
|
import { LazyPromise } from '../promise/lazy-promise.js';
|
|
18
|
-
import { convertToOpenApiSchema } from '../schema/converters/
|
|
18
|
+
import { convertToOpenApiSchema } from '../schema/converters/open-api-converter.js';
|
|
19
19
|
import { Schema } from '../schema/index.js';
|
|
20
20
|
import { toArray } from '../utils/array/array.js';
|
|
21
21
|
import { mapAsync } from '../utils/async-iterable-helpers/map.js';
|
|
@@ -23,7 +23,7 @@ import { toArrayAsync } from '../utils/async-iterable-helpers/to-array.js';
|
|
|
23
23
|
import { backoffGenerator } from '../utils/backoff.js';
|
|
24
24
|
import { lazyObject } from '../utils/object/lazy-property.js';
|
|
25
25
|
import { hasOwnProperty, objectEntries } from '../utils/object/object.js';
|
|
26
|
-
import { assertDefinedPass, isDefined, isError, isNotNull, isNull, isUndefined } from '../utils/type-guards.js';
|
|
26
|
+
import { assertDefinedPass, isDefined, isError, isInstanceOf, isNotNull, isNull, isUndefined } from '../utils/type-guards.js';
|
|
27
27
|
import { resolveValueOrAsyncProvider } from '../utils/value-or-provider.js';
|
|
28
28
|
import { AiFileService } from './ai-file.service.js';
|
|
29
29
|
import { AiSession } from './ai-session.js';
|
|
@@ -57,7 +57,7 @@ let AiService = AiService_1 = class AiService {
|
|
|
57
57
|
#backoffOptions = {
|
|
58
58
|
cancellationSignal: this.#cancellationSignal,
|
|
59
59
|
strategy: 'exponential',
|
|
60
|
-
initialDelay:
|
|
60
|
+
initialDelay: 5000,
|
|
61
61
|
increase: 1.5,
|
|
62
62
|
jitter: 0.2,
|
|
63
63
|
maximumDelay: 30000,
|
|
@@ -215,7 +215,7 @@ let AiService = AiService_1 = class AiService {
|
|
|
215
215
|
}
|
|
216
216
|
catch (error) {
|
|
217
217
|
triesLeft -= 1;
|
|
218
|
-
if ((triesLeft > 0) &&
|
|
218
|
+
if ((triesLeft > 0) && isInstanceOf(error, ApiError) && ((error.status == 429) || (error.status == 503))) {
|
|
219
219
|
this.#logger.verbose(`Retrying after transient error: ${error.message}`);
|
|
220
220
|
backoff();
|
|
221
221
|
continue;
|
|
@@ -304,7 +304,7 @@ let AiService = AiService_1 = class AiService {
|
|
|
304
304
|
for (const call of generation.functionCalls) {
|
|
305
305
|
const fn = assertDefinedPass(options.functions[call.name], 'Function in response not declared.');
|
|
306
306
|
const parametersSchema = await resolveValueOrAsyncProvider(fn.parameters);
|
|
307
|
-
const parameters = isDefined(parametersSchema) ? parametersSchema.parse(call.parameters) : call.parameters;
|
|
307
|
+
const parameters = isDefined(parametersSchema) ? parametersSchema.parse(call.parameters, { coerce: true }) : call.parameters;
|
|
308
308
|
const handlerResult = isSchemaFunctionDeclarationWithHandler(fn) ? await fn.handler(parameters) : undefined;
|
|
309
309
|
yield {
|
|
310
310
|
functionName: call.name,
|
|
@@ -470,7 +470,7 @@ export function mergeGenerationStreamItems(items, schema) {
|
|
|
470
470
|
catch (error) {
|
|
471
471
|
throw new Error(`Failed to parse model output as JSON. Raw text: "${this.text}"`, { cause: error });
|
|
472
472
|
}
|
|
473
|
-
return Schema.parse(schema, parsed);
|
|
473
|
+
return Schema.parse(schema, parsed, { coerce: true });
|
|
474
474
|
},
|
|
475
475
|
functionCalls() {
|
|
476
476
|
return parts.filter((part) => hasOwnProperty(part, 'functionCall')).map((part) => part.functionCall);
|
package/ai/functions.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { convertToOpenApiSchema } from '../schema/converters/
|
|
1
|
+
import { convertToOpenApiSchema } from '../schema/converters/open-api-converter.js';
|
|
2
2
|
import { FunctionSchema, getObjectSchema, object } from '../schema/index.js';
|
|
3
3
|
import { fromEntries, objectEntries } from '../utils/object/object.js';
|
|
4
4
|
import { isNotNull, isNull, isString } from '../utils/type-guards.js';
|
package/orm/server/repository.js
CHANGED
|
@@ -457,9 +457,12 @@ let EntityRepository = class EntityRepository extends Transactional {
|
|
|
457
457
|
*/
|
|
458
458
|
async hasByQuery(query) {
|
|
459
459
|
const sqlQuery = this.convertQuery(query);
|
|
460
|
-
const result = await this.session
|
|
461
|
-
|
|
462
|
-
|
|
460
|
+
const result = await this.session
|
|
461
|
+
.select({ value: sql `1` })
|
|
462
|
+
.from(this.#table)
|
|
463
|
+
.where(sqlQuery)
|
|
464
|
+
.limit(1);
|
|
465
|
+
return result.length > 0;
|
|
463
466
|
}
|
|
464
467
|
/**
|
|
465
468
|
* Checks if all entities with the given IDs exist.
|
|
@@ -471,12 +474,8 @@ let EntityRepository = class EntityRepository extends Transactional {
|
|
|
471
474
|
if (uniqueIds.length === 0) {
|
|
472
475
|
return false;
|
|
473
476
|
}
|
|
474
|
-
const
|
|
475
|
-
|
|
476
|
-
.from(this.#table)
|
|
477
|
-
.where(inArray(this.#table.id, uniqueIds));
|
|
478
|
-
const foundCount = result[0]?.count ?? 0;
|
|
479
|
-
return foundCount == uniqueIds.length;
|
|
477
|
+
const count = await this.countByQuery(inArray(this.#table.id, uniqueIds));
|
|
478
|
+
return count == uniqueIds.length;
|
|
480
479
|
}
|
|
481
480
|
/**
|
|
482
481
|
* Tries to insert using ON CONFLICT DO NOTHING
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tstdl/base",
|
|
3
|
-
"version": "0.93.
|
|
3
|
+
"version": "0.93.50",
|
|
4
4
|
"author": "Patrick Hein",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -101,6 +101,8 @@
|
|
|
101
101
|
"./rxjs-utils": "./rxjs-utils/index.js",
|
|
102
102
|
"./schema": "./schema/index.js",
|
|
103
103
|
"./schema/converters": "./schema/converters/index.js",
|
|
104
|
+
"./schema/converters/open-api": "./schema/converters/open-api-converter.js",
|
|
105
|
+
"./schema/converters/zod": "./schema/converters/zod-converter.js",
|
|
104
106
|
"./serializer": "./serializer/index.js",
|
|
105
107
|
"./serializer/handlers": "./serializer/handlers/index.js",
|
|
106
108
|
"./signals": "./signals/index.js",
|
|
@@ -149,12 +151,13 @@
|
|
|
149
151
|
"mjml": "^4.17",
|
|
150
152
|
"nodemailer": "^7.0",
|
|
151
153
|
"pg": "^8.16",
|
|
152
|
-
"playwright": "^1.
|
|
154
|
+
"playwright": "^1.57",
|
|
153
155
|
"preact": "^10.27",
|
|
154
156
|
"preact-render-to-string": "^6.6",
|
|
155
157
|
"sharp": "^0.34",
|
|
156
158
|
"undici": "^7.16",
|
|
157
|
-
"urlpattern-polyfill": "^10.1"
|
|
159
|
+
"urlpattern-polyfill": "^10.1",
|
|
160
|
+
"zod": "^4.1"
|
|
158
161
|
},
|
|
159
162
|
"peerDependenciesMeta": {
|
|
160
163
|
"@tstdl/angular": {
|
|
@@ -178,7 +181,7 @@
|
|
|
178
181
|
"typedoc-plugin-markdown": "4.9",
|
|
179
182
|
"typedoc-plugin-missing-exports": "4.1",
|
|
180
183
|
"typescript": "5.9",
|
|
181
|
-
"typescript-eslint": "8.
|
|
184
|
+
"typescript-eslint": "8.48"
|
|
182
185
|
},
|
|
183
186
|
"overrides": {
|
|
184
187
|
"drizzle-kit": {
|
|
@@ -1,17 +1,7 @@
|
|
|
1
1
|
import { NotSupportedError } from '../../errors/not-supported.error.js';
|
|
2
2
|
import { filterUndefinedObjectProperties, fromEntries, hasOwnProperty, objectEntries } from '../../utils/object/object.js';
|
|
3
3
|
import { isDefined, isNotNull, isNumber, isString } from '../../utils/type-guards.js';
|
|
4
|
-
import { ArraySchema } from '../schemas/
|
|
5
|
-
import { BooleanSchema } from '../schemas/boolean.js';
|
|
6
|
-
import { DateSchema } from '../schemas/date.js';
|
|
7
|
-
import { EnumerationSchema } from '../schemas/enumeration.js';
|
|
8
|
-
import { LiteralSchema } from '../schemas/literal.js';
|
|
9
|
-
import { nullable, NullableSchema } from '../schemas/nullable.js';
|
|
10
|
-
import { NumberSchema } from '../schemas/number.js';
|
|
11
|
-
import { ObjectSchema } from '../schemas/object.js';
|
|
12
|
-
import { OptionalSchema } from '../schemas/optional.js';
|
|
13
|
-
import { StringSchema } from '../schemas/string.js';
|
|
14
|
-
import { UnionSchema } from '../schemas/union.js';
|
|
4
|
+
import { ArraySchema, BooleanSchema, DateSchema, DefaultSchema, EnumerationSchema, LiteralSchema, nullable, NullableSchema, NumberSchema, ObjectSchema, OptionalSchema, StringSchema, TransformSchema, Uint8ArraySchema, UnionSchema } from '../schemas/index.js';
|
|
15
5
|
import { schemaTestableToSchema } from '../testable.js';
|
|
16
6
|
export function convertToOpenApiSchema(testable) {
|
|
17
7
|
const schema = schemaTestableToSchema(testable);
|
|
@@ -39,12 +29,21 @@ function convertToOpenApiSchemaBase(schema) {
|
|
|
39
29
|
maxProperties: isNumber(schema.maximumPropertiesCount) ? schema.maximumPropertiesCount : undefined,
|
|
40
30
|
});
|
|
41
31
|
}
|
|
32
|
+
if (schema instanceof DefaultSchema) { // You'd need to import DefaultedSchema
|
|
33
|
+
return {
|
|
34
|
+
...convertToOpenApiSchema(schema.schema),
|
|
35
|
+
default: schema.defaultValue,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
if (schema instanceof TransformSchema) { // You'd need to import TransformSchema
|
|
39
|
+
return convertToOpenApiSchema(schema.schema);
|
|
40
|
+
}
|
|
42
41
|
if (schema instanceof StringSchema) {
|
|
43
42
|
return filterUndefinedObjectProperties({
|
|
44
43
|
type: 'string',
|
|
45
44
|
minLength: isNumber(schema.minimumLength) ? schema.minimumLength : undefined,
|
|
46
45
|
maxLength: isNumber(schema.maximumLength) ? schema.maximumLength : undefined,
|
|
47
|
-
pattern: isString(schema.pattern) ? schema.pattern :
|
|
46
|
+
pattern: isString(schema.pattern) ? schema.pattern : schema.pattern?.source,
|
|
48
47
|
});
|
|
49
48
|
}
|
|
50
49
|
if (schema instanceof DateSchema) {
|
|
@@ -79,6 +78,14 @@ function convertToOpenApiSchemaBase(schema) {
|
|
|
79
78
|
maxItems: isNumber(schema.maximum) ? schema.maximum : undefined,
|
|
80
79
|
});
|
|
81
80
|
}
|
|
81
|
+
if ((schema instanceof Uint8ArraySchema) && (schema.coerceType == 'base64')) {
|
|
82
|
+
return filterUndefinedObjectProperties({
|
|
83
|
+
type: 'string',
|
|
84
|
+
format: 'byte',
|
|
85
|
+
minLength: isNumber(schema.minimumLength) ? schema.minimumLength : undefined,
|
|
86
|
+
maxLength: isNumber(schema.maximumLength) ? schema.maximumLength : undefined,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
82
89
|
if (schema instanceof EnumerationSchema) {
|
|
83
90
|
const hasString = schema.allowedValues.some(isString);
|
|
84
91
|
const hasNumber = schema.allowedValues.some(isNumber);
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import * as z from 'zod/mini';
|
|
2
|
+
import { NotSupportedError } from '../../errors/not-supported.error.js';
|
|
3
|
+
import { objectEntries, objectKeys } from '../../utils/object/object.js';
|
|
4
|
+
import { isArray, isNotNull, isNumber, isString } from '../../utils/type-guards.js';
|
|
5
|
+
import { any, AnySchema, ArraySchema, BigIntSchema, BooleanSchema, DateSchema, DefaultSchema, DeferredSchema, EnumerationSchema, InstanceSchema, LiteralSchema, NeverSchema, NullableSchema, NumberSchema, ObjectSchema, OneOrManySchema, OptionalSchema, ReadableStreamSchema, RegExpSchema, StringSchema, SymbolSchema, TransformSchema, Uint8ArraySchema, UnionSchema, UnknownSchema } from '../schemas/index.js';
|
|
6
|
+
import { schemaTestableToSchema } from '../testable.js';
|
|
7
|
+
export function convertToZodSchema(testable) {
|
|
8
|
+
const schema = schemaTestableToSchema(testable);
|
|
9
|
+
return convertToZodSchemaBase(schema);
|
|
10
|
+
}
|
|
11
|
+
function convertToZodSchemaBase(schema) {
|
|
12
|
+
if (schema instanceof AnySchema) {
|
|
13
|
+
return z.any();
|
|
14
|
+
}
|
|
15
|
+
if (schema instanceof UnknownSchema) {
|
|
16
|
+
return z.unknown();
|
|
17
|
+
}
|
|
18
|
+
if (schema instanceof NeverSchema) {
|
|
19
|
+
return z.never();
|
|
20
|
+
}
|
|
21
|
+
if (schema instanceof NullableSchema) {
|
|
22
|
+
return z.nullable(convertToZodSchema(schema.schema));
|
|
23
|
+
}
|
|
24
|
+
if (schema instanceof OptionalSchema) {
|
|
25
|
+
return z.optional(convertToZodSchema(schema.schema));
|
|
26
|
+
}
|
|
27
|
+
if (schema instanceof OneOrManySchema) {
|
|
28
|
+
return convertToZodSchema(schema.schema);
|
|
29
|
+
}
|
|
30
|
+
if (schema instanceof StringSchema) {
|
|
31
|
+
const checks = [];
|
|
32
|
+
if (isNumber(schema.minimumLength)) {
|
|
33
|
+
checks.push(z.minLength(schema.minimumLength));
|
|
34
|
+
}
|
|
35
|
+
if (isNumber(schema.maximumLength)) {
|
|
36
|
+
checks.push(z.maxLength(schema.maximumLength));
|
|
37
|
+
}
|
|
38
|
+
if (isNotNull(schema.pattern)) {
|
|
39
|
+
checks.push(z.regex(isString(schema.pattern) ? new RegExp(schema.pattern) : schema.pattern));
|
|
40
|
+
}
|
|
41
|
+
if (schema.lowercase) {
|
|
42
|
+
checks.push(z.toLowerCase());
|
|
43
|
+
}
|
|
44
|
+
const zodSchema = z.string();
|
|
45
|
+
return (checks.length > 0) ? zodSchema.check(...checks) : zodSchema;
|
|
46
|
+
}
|
|
47
|
+
if (schema instanceof NumberSchema) {
|
|
48
|
+
const checks = [];
|
|
49
|
+
if (isNumber(schema.minimum)) {
|
|
50
|
+
checks.push(z.gte(schema.minimum));
|
|
51
|
+
}
|
|
52
|
+
if (isNumber(schema.maximum)) {
|
|
53
|
+
checks.push(z.lte(schema.maximum));
|
|
54
|
+
}
|
|
55
|
+
const zodSchema = (schema.integer) ? z.int() : z.number();
|
|
56
|
+
return (checks.length > 0) ? zodSchema.check(...checks) : zodSchema;
|
|
57
|
+
}
|
|
58
|
+
if (schema instanceof BooleanSchema) {
|
|
59
|
+
return z.boolean();
|
|
60
|
+
}
|
|
61
|
+
if (schema instanceof BigIntSchema) {
|
|
62
|
+
return z.bigint();
|
|
63
|
+
}
|
|
64
|
+
if (schema instanceof SymbolSchema) {
|
|
65
|
+
return z.symbol();
|
|
66
|
+
}
|
|
67
|
+
if (schema instanceof DateSchema) {
|
|
68
|
+
const checks = [];
|
|
69
|
+
if (isNotNull(schema.minimum)) {
|
|
70
|
+
checks.push(z.gte(schema.minimum));
|
|
71
|
+
}
|
|
72
|
+
if (isNotNull(schema.maximum)) {
|
|
73
|
+
checks.push(z.lte(schema.maximum));
|
|
74
|
+
}
|
|
75
|
+
const zodSchema = z.date();
|
|
76
|
+
return (checks.length > 0) ? zodSchema.check(...checks) : zodSchema;
|
|
77
|
+
}
|
|
78
|
+
if (schema instanceof LiteralSchema) {
|
|
79
|
+
return z.literal(schema.value);
|
|
80
|
+
}
|
|
81
|
+
if (schema instanceof ArraySchema) {
|
|
82
|
+
const itemSchema = convertToZodSchema(schema.itemSchema);
|
|
83
|
+
const checks = [];
|
|
84
|
+
if (isNumber(schema.minimum)) {
|
|
85
|
+
checks.push(z.minSize(schema.minimum));
|
|
86
|
+
}
|
|
87
|
+
if (isNumber(schema.maximum)) {
|
|
88
|
+
checks.push(z.maxSize(schema.maximum));
|
|
89
|
+
}
|
|
90
|
+
const zodSchema = z.array(itemSchema);
|
|
91
|
+
return (checks.length > 0) ? zodSchema.check(...checks) : zodSchema;
|
|
92
|
+
}
|
|
93
|
+
if (schema instanceof ObjectSchema) {
|
|
94
|
+
const propertyEntries = objectEntries(schema.properties);
|
|
95
|
+
if ((propertyEntries.length == 0) && (isNotNull(schema.unknownPropertiesKey) || isNotNull(schema.unknownProperties))) {
|
|
96
|
+
return z.record(convertToZodSchema(schema.unknownPropertiesKey ?? any()), convertToZodSchema(schema.unknownProperties ?? any()));
|
|
97
|
+
}
|
|
98
|
+
const shape = {};
|
|
99
|
+
for (const [key, propertySchema] of propertyEntries) {
|
|
100
|
+
shape[key] = convertToZodSchema(propertySchema);
|
|
101
|
+
}
|
|
102
|
+
const loose = isNotNull(schema.unknownPropertiesKey) || isNotNull(schema.unknownProperties);
|
|
103
|
+
const zodSchema = loose
|
|
104
|
+
? z.looseObject(shape)
|
|
105
|
+
: schema.mask
|
|
106
|
+
? z.object(shape)
|
|
107
|
+
: z.strictObject(shape);
|
|
108
|
+
if (loose) {
|
|
109
|
+
const propertiesSchema = convertToZodSchema(schema.unknownProperties ?? any());
|
|
110
|
+
const propertiesKeySchema = convertToZodSchema(schema.unknownPropertiesKey ?? any());
|
|
111
|
+
const knownPropertyKeys = new Set(objectKeys(shape));
|
|
112
|
+
return zodSchema.check(z.superRefine((record, context) => {
|
|
113
|
+
for (const [key, value] of objectEntries(record)) {
|
|
114
|
+
if (knownPropertyKeys.has(key)) {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
const keyParseResult = propertiesKeySchema.safeParse(key);
|
|
118
|
+
const valueParseResult = propertiesSchema.safeParse(value);
|
|
119
|
+
if (!keyParseResult.success) {
|
|
120
|
+
context.addIssue({
|
|
121
|
+
code: 'invalid_key',
|
|
122
|
+
origin: 'record',
|
|
123
|
+
issues: keyParseResult.error.issues,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
if (!valueParseResult.success) {
|
|
127
|
+
context.addIssue({
|
|
128
|
+
code: 'custom',
|
|
129
|
+
input: value,
|
|
130
|
+
path: [key],
|
|
131
|
+
message: valueParseResult.error.message,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}));
|
|
136
|
+
}
|
|
137
|
+
return zodSchema;
|
|
138
|
+
}
|
|
139
|
+
if (schema instanceof UnionSchema) {
|
|
140
|
+
const schemas = schema.schemas.map((s) => convertToZodSchema(s));
|
|
141
|
+
return z.union(schemas);
|
|
142
|
+
}
|
|
143
|
+
if (schema instanceof EnumerationSchema) {
|
|
144
|
+
if (isArray(schema.enumeration) && schema.enumeration.some((v) => isNumber(v))) {
|
|
145
|
+
const types = schema.allowedValues.map((value) => z.literal(value));
|
|
146
|
+
return z.union(types);
|
|
147
|
+
}
|
|
148
|
+
return z.enum(schema.enumeration);
|
|
149
|
+
}
|
|
150
|
+
if (schema instanceof DefaultSchema) {
|
|
151
|
+
return z._default(convertToZodSchema(schema.schema), schema.defaultValue);
|
|
152
|
+
}
|
|
153
|
+
if (schema instanceof TransformSchema) {
|
|
154
|
+
return z.transform((input) => schema.transformFn(input));
|
|
155
|
+
}
|
|
156
|
+
if (schema instanceof DeferredSchema) {
|
|
157
|
+
return z.lazy(() => convertToZodSchema(schema.schema));
|
|
158
|
+
}
|
|
159
|
+
if (schema instanceof Uint8ArraySchema) {
|
|
160
|
+
return z.instanceof(Uint8Array);
|
|
161
|
+
}
|
|
162
|
+
if (schema instanceof ReadableStreamSchema) {
|
|
163
|
+
return z.instanceof(ReadableStream);
|
|
164
|
+
}
|
|
165
|
+
if (schema instanceof RegExpSchema) {
|
|
166
|
+
return z.instanceof(RegExp);
|
|
167
|
+
}
|
|
168
|
+
if (schema instanceof InstanceSchema) {
|
|
169
|
+
return z.instanceof(schema.type);
|
|
170
|
+
}
|
|
171
|
+
throw new NotSupportedError(`Schema "${schema.name}" cannot be converted to Zod schema.`);
|
|
172
|
+
}
|
package/schema/schemas/array.js
CHANGED
|
@@ -27,10 +27,10 @@ export class ArraySchema extends Schema {
|
|
|
27
27
|
return { valid: false, error: SchemaError.expectedButGot('array', typeOf(value), path) };
|
|
28
28
|
}
|
|
29
29
|
if (isNotNull(this.maximum) && (value.length > this.maximum)) {
|
|
30
|
-
|
|
30
|
+
return { valid: false, error: new SchemaError(`A maximum of ${this.maximum} items are allowed.`, { path, fast: options.fastErrors }) };
|
|
31
31
|
}
|
|
32
32
|
if (isNotNull(this.minimum) && (value.length < this.minimum)) {
|
|
33
|
-
|
|
33
|
+
return { valid: false, error: new SchemaError(`A minimum of ${this.minimum} items are required.`, { path, fast: options.fastErrors }) };
|
|
34
34
|
}
|
|
35
35
|
const values = [];
|
|
36
36
|
for (let i = 0; i < value.length; i++) {
|
package/schema/schemas/date.d.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type SchemaDecoratorOptions, type SchemaPropertyDecorator } from '../decorators/index.js';
|
|
2
2
|
import { SimpleSchema, type SimpleSchemaOptions } from './simple.js';
|
|
3
|
-
export type DateSchemaOptions = SimpleSchemaOptions<
|
|
4
|
-
|
|
3
|
+
export type DateSchemaOptions = SimpleSchemaOptions<Date> & {
|
|
4
|
+
minimum?: Date | number | null;
|
|
5
|
+
maximum?: Date | number | null;
|
|
5
6
|
};
|
|
6
|
-
export declare class DateSchema extends SimpleSchema<
|
|
7
|
+
export declare class DateSchema extends SimpleSchema<Date> {
|
|
7
8
|
readonly name = "date";
|
|
9
|
+
readonly minimum: Date | null;
|
|
10
|
+
readonly maximum: Date | null;
|
|
8
11
|
constructor(options?: DateSchemaOptions);
|
|
9
12
|
}
|
|
10
13
|
export declare function date(options?: DateSchemaOptions): DateSchema;
|
package/schema/schemas/date.js
CHANGED
|
@@ -1,24 +1,29 @@
|
|
|
1
|
-
import { isValidDate } from '../../utils/type-guards.js';
|
|
1
|
+
import { isNotNullOrUndefined, isValidDate } from '../../utils/type-guards.js';
|
|
2
2
|
import { PropertySchema } from '../decorators/index.js';
|
|
3
3
|
import { SchemaError } from '../schema.error.js';
|
|
4
4
|
import { SimpleSchema } from './simple.js';
|
|
5
5
|
export class DateSchema extends SimpleSchema {
|
|
6
6
|
name = 'date';
|
|
7
|
+
minimum;
|
|
8
|
+
maximum;
|
|
7
9
|
constructor(options) {
|
|
8
10
|
super('date', isValidDate, options, {
|
|
9
11
|
coercers: {
|
|
10
12
|
string: (value, path, options) => {
|
|
11
|
-
const result = new
|
|
12
|
-
return
|
|
13
|
+
const result = new Date(value);
|
|
14
|
+
return Number.isNaN(result.getTime())
|
|
13
15
|
? { success: false, error: SchemaError.couldNotCoerce('date', 'string', path, { fast: options.fastErrors }) }
|
|
14
16
|
: { success: true, value: result, valid: true };
|
|
15
17
|
},
|
|
16
|
-
number: (value) => ({ success: true, value: new
|
|
18
|
+
number: (value) => ({ success: true, value: new Date(value), valid: false }),
|
|
17
19
|
},
|
|
18
20
|
constraints: [
|
|
19
|
-
(options?.
|
|
20
|
-
|
|
21
|
+
isNotNullOrUndefined(options?.minimum) ? (value) => (value >= this.minimum) ? ({ success: true }) : ({ success: false, error: `Value ${value.toDateString()} is less than minimum ${this.minimum.toDateString()}` }) : null,
|
|
22
|
+
isNotNullOrUndefined(options?.maximum) ? (value) => (value <= this.maximum) ? ({ success: true }) : ({ success: false, error: `Value ${value.toDateString()} is greater than maximum ${this.maximum.toDateString()}` }) : null,
|
|
23
|
+
],
|
|
21
24
|
});
|
|
25
|
+
this.minimum = isNotNullOrUndefined(options?.minimum) ? new Date(options.minimum) : null;
|
|
26
|
+
this.maximum = isNotNullOrUndefined(options?.maximum) ? new Date(options.maximum) : null;
|
|
22
27
|
}
|
|
23
28
|
}
|
|
24
29
|
export function date(options) {
|
|
@@ -27,14 +27,14 @@ export function Method(parameterSchemasOrOptions, returnValueSchema, optionsOrNo
|
|
|
27
27
|
if (isArray(parameterSchemasOrOptions) || isNull(parameterSchemasOrOptions)) {
|
|
28
28
|
return Property({
|
|
29
29
|
...optionsOrNothing,
|
|
30
|
-
schema: (data) => func(parameterSchemasOrOptions, returnValueSchema, { description: data.description, example: data.example, ...optionsOrNothing })
|
|
30
|
+
schema: (data) => func(parameterSchemasOrOptions, returnValueSchema, { description: data.description, example: data.example, ...optionsOrNothing }),
|
|
31
31
|
});
|
|
32
32
|
}
|
|
33
33
|
return createMethodDecorator({
|
|
34
34
|
handler: (data, _metdata, originalArguments) => {
|
|
35
35
|
createSchemaDecorator(parameterSchemasOrOptions)(...originalArguments);
|
|
36
36
|
Property(getFunctionSchemaFromReflection(data.constructor, data.methodKey), parameterSchemasOrOptions);
|
|
37
|
-
}
|
|
37
|
+
},
|
|
38
38
|
});
|
|
39
39
|
}
|
|
40
40
|
export function getFunctionSchemaFromReflection(type, method) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { JsonPath } from '../../json-path/json-path.js';
|
|
2
2
|
import type { AbstractConstructor } from '../../types/index.js';
|
|
3
|
-
import { type
|
|
3
|
+
import { type SchemaDecoratorOptions, type SchemaPropertyDecorator } from '../decorators/index.js';
|
|
4
4
|
import { Schema, type SchemaOptions, type SchemaTestOptions, type SchemaTestResult } from '../schema.js';
|
|
5
5
|
export type InstanceSchemaOptions<T extends AbstractConstructor> = SchemaOptions<InstanceType<T>>;
|
|
6
6
|
export declare class InstanceSchema<T extends AbstractConstructor> extends Schema<InstanceType<T>> {
|
|
@@ -17,7 +17,7 @@ export class InstanceSchema extends Schema {
|
|
|
17
17
|
}
|
|
18
18
|
return {
|
|
19
19
|
valid: false,
|
|
20
|
-
error: SchemaError.expectedButGot(typeOf(this.type), typeOf(value), path, { fast: options.fastErrors })
|
|
20
|
+
error: SchemaError.expectedButGot(typeOf(this.type), typeOf(value), path, { fast: options.fastErrors }),
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
23
|
}
|
|
@@ -47,6 +47,11 @@ export declare class ObjectSchema<T extends Record = Record> extends Schema<T> {
|
|
|
47
47
|
readonly factory: ObjectSchemaFactory<T> | null;
|
|
48
48
|
constructor(properties: ObjectSchemaProperties<T>, options?: ObjectSchemaOptions<T>);
|
|
49
49
|
_test(value: any, path: JsonPath, options: SchemaTestOptions): SchemaTestResult<T>;
|
|
50
|
+
pick<const K extends keyof T>(keys: OneOrMany<K>): ObjectSchema<SimplifyObject<Pick<T, K>>>;
|
|
51
|
+
omit<const K extends keyof T>(keys: OneOrMany<K>): ObjectSchema<SimplifyObject<Omit<T, K>>>;
|
|
52
|
+
partial(): ObjectSchema<Partial<T>>;
|
|
53
|
+
partial<const K extends keyof T>(keys: OneOrMany<K>): ObjectSchema<PartialProperty<T, K>>;
|
|
54
|
+
assign<T extends Record>(other: ObjectSchemaOrType<T>): ObjectSchema<Merge<T, T>>;
|
|
50
55
|
}
|
|
51
56
|
export declare function object<const K extends PropertyKey, const V>(properties: Record<never>, options: ObjectSchemaOptions<Record<K, V>> & {
|
|
52
57
|
unknownProperties: SchemaTestable<V>;
|
package/schema/schemas/object.js
CHANGED
|
@@ -81,6 +81,18 @@ export class ObjectSchema extends Schema {
|
|
|
81
81
|
const testResultValue = isFunction(this.factory) ? this.factory(resultValue) : resultValue;
|
|
82
82
|
return { valid: true, value: testResultValue };
|
|
83
83
|
}
|
|
84
|
+
pick(keys) {
|
|
85
|
+
return pick(this, keys);
|
|
86
|
+
}
|
|
87
|
+
omit(keys) {
|
|
88
|
+
return omit(this, keys);
|
|
89
|
+
}
|
|
90
|
+
partial(keys) {
|
|
91
|
+
return partial(this, keys);
|
|
92
|
+
}
|
|
93
|
+
assign(other) {
|
|
94
|
+
return assign(this, other);
|
|
95
|
+
}
|
|
84
96
|
}
|
|
85
97
|
export function object(properties, options) {
|
|
86
98
|
return new ObjectSchema(properties, options);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type SchemaDecoratorOptions, type SchemaPropertyDecorator } from '../decorators/index.js';
|
|
2
2
|
import { SimpleSchema, type SimpleSchemaOptions } from './simple.js';
|
|
3
3
|
export type RegExpSchemaOptions = SimpleSchemaOptions<RegExp>;
|
|
4
4
|
export declare class RegExpSchema extends SimpleSchema<RegExp> {
|
package/schema/schemas/regexp.js
CHANGED
|
@@ -15,8 +15,8 @@ export class RegExpSchema extends SimpleSchema {
|
|
|
15
15
|
catch (error) {
|
|
16
16
|
return { success: false, error: SchemaError.couldNotCoerce(globalThis.RegExp, 'string', path, { fast: options.fastErrors, customMessage: error.message }) };
|
|
17
17
|
}
|
|
18
|
-
}
|
|
19
|
-
}
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
20
|
});
|
|
21
21
|
}
|
|
22
22
|
}
|
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type SchemaDecoratorOptions, type SchemaPropertyDecorator } from '../decorators/index.js';
|
|
2
2
|
import { SimpleSchema, type SimpleSchemaOptions } from './simple.js';
|
|
3
3
|
export type Uint8ArraySchemaOptions = SimpleSchemaOptions<Uint8Array> & {
|
|
4
4
|
/** Minimum byte length */
|
|
5
5
|
minimumLength?: number;
|
|
6
6
|
/** Maximum byte length */
|
|
7
7
|
maximumLength?: number;
|
|
8
|
+
/** Type to coerce from string */
|
|
9
|
+
coerceType?: Uint8ArraySchema['coerceType'];
|
|
8
10
|
};
|
|
9
11
|
export declare class Uint8ArraySchema extends SimpleSchema<Uint8Array> {
|
|
10
12
|
readonly name = "Uint8Array";
|
|
11
13
|
readonly minimumLength: number | null;
|
|
12
14
|
readonly maximumLength: number | null;
|
|
15
|
+
readonly coerceType: 'base64' | 'base64url' | 'zbase32' | 'hex' | null;
|
|
13
16
|
constructor(options?: Uint8ArraySchemaOptions);
|
|
14
17
|
}
|
|
15
18
|
export declare function uint8Array(options?: Uint8ArraySchemaOptions): Uint8ArraySchema;
|
|
@@ -1,19 +1,48 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { match } from 'ts-pattern';
|
|
2
|
+
import { AssertionError } from '../../errors/index.js';
|
|
3
|
+
import { decodeBase64, decodeBase64Url } from '../../utils/base64.js';
|
|
4
|
+
import { decodeHex } from '../../utils/encoding.js';
|
|
5
|
+
import { isDefined, isInstanceOf, isUint8Array } from '../../utils/type-guards.js';
|
|
6
|
+
import { zBase32Decode } from '../../utils/z-base32.js';
|
|
2
7
|
import { PropertySchema } from '../decorators/index.js';
|
|
8
|
+
import { SchemaError } from '../schema.error.js';
|
|
3
9
|
import { SimpleSchema } from './simple.js';
|
|
4
10
|
export class Uint8ArraySchema extends SimpleSchema {
|
|
5
11
|
name = 'Uint8Array';
|
|
6
12
|
minimumLength;
|
|
7
13
|
maximumLength;
|
|
14
|
+
coerceType;
|
|
8
15
|
constructor(options) {
|
|
9
16
|
super('Uint8Array', isUint8Array, options, {
|
|
17
|
+
coercers: {
|
|
18
|
+
string: isDefined(options?.coerceType)
|
|
19
|
+
? (value, path, options) => {
|
|
20
|
+
try {
|
|
21
|
+
const coerced = match(this.coerceType)
|
|
22
|
+
.with('base64', () => decodeBase64(value))
|
|
23
|
+
.with('base64url', () => decodeBase64Url(value))
|
|
24
|
+
.with('zbase32', () => zBase32Decode(value))
|
|
25
|
+
.with('hex', () => decodeHex(value))
|
|
26
|
+
.exhaustive();
|
|
27
|
+
return { success: true, valid: true, value: coerced };
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
if (isInstanceOf(error, AssertionError)) {
|
|
31
|
+
return { success: false, error: SchemaError.couldNotCoerce(`${this.coerceType} formatted string`, 'string', path, { fast: options.fastErrors, customMessage: error.message }) };
|
|
32
|
+
}
|
|
33
|
+
throw error;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
: undefined,
|
|
37
|
+
},
|
|
10
38
|
constraints: [
|
|
11
39
|
isDefined(options?.minimumLength) ? (value) => (value.byteLength >= this.minimumLength) ? ({ success: true }) : ({ success: false, error: `Size must be at least ${this.minimumLength} bytes.` }) : null,
|
|
12
|
-
isDefined(options?.maximumLength) ? (value) => (value.byteLength <= this.maximumLength) ? ({ success: true }) : ({ success: false, error: `Size must be at most ${this.maximumLength} bytes.` }) : null
|
|
13
|
-
]
|
|
40
|
+
isDefined(options?.maximumLength) ? (value) => (value.byteLength <= this.maximumLength) ? ({ success: true }) : ({ success: false, error: `Size must be at most ${this.maximumLength} bytes.` }) : null,
|
|
41
|
+
],
|
|
14
42
|
});
|
|
15
43
|
this.minimumLength = options?.minimumLength ?? null;
|
|
16
44
|
this.maximumLength = options?.maximumLength ?? null;
|
|
45
|
+
this.coerceType = options?.coerceType ?? null;
|
|
17
46
|
}
|
|
18
47
|
}
|
|
19
48
|
export function uint8Array(options) {
|
package/utils/encoding.js
CHANGED
|
@@ -62,7 +62,7 @@ export function decodeHex(hex) {
|
|
|
62
62
|
const hexPart = hex.substring(i, i + 2);
|
|
63
63
|
const byte = hexToByte.get(hexPart);
|
|
64
64
|
if (isUndefined(byte)) {
|
|
65
|
-
throw new AssertionError(`
|
|
65
|
+
throw new AssertionError(`Invalid hex string at position ${i}.`);
|
|
66
66
|
}
|
|
67
67
|
bytes[i / 2] = byte;
|
|
68
68
|
}
|
package/utils/z-base32.d.ts
CHANGED
package/utils/z-base32.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { AssertionError } from '../errors/index.js';
|
|
1
2
|
import { Alphabet } from './alphabet.js';
|
|
2
3
|
import { toUint8Array } from './binary.js';
|
|
3
4
|
const alphabet = Alphabet.ZBase32;
|
|
@@ -30,7 +31,7 @@ export function zBase32Decode(input) {
|
|
|
30
31
|
const char = input[i];
|
|
31
32
|
const charValue = charValueMap.get(char);
|
|
32
33
|
if (charValue == undefined) {
|
|
33
|
-
throw new
|
|
34
|
+
throw new AssertionError(`Invalid character at index ${i}.`);
|
|
34
35
|
}
|
|
35
36
|
value = (value << 5) | charValue;
|
|
36
37
|
bits += 5;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './openapi-converter.js';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './openapi-converter.js';
|
|
File without changes
|