@tstdl/base 0.93.48 → 0.93.49

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 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/openapi-converter.js';
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: 2500,
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) && isError(error) && (error.message.includes('429 Too Many Requests') || error.message.includes('503 Service Unavailable'))) {
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/openapi-converter.js';
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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tstdl/base",
3
- "version": "0.93.48",
3
+ "version": "0.93.49",
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.56",
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.47"
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/array.js';
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 : undefined,
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,3 @@
1
+ import * as z from 'zod/mini';
2
+ import type { SchemaTestable } from '../schema.js';
3
+ export declare function convertToZodSchema<O, I = unknown>(testable: SchemaTestable<O>): z.ZodMiniType<O, I>;
@@ -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
+ }
@@ -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
- throw new Error(`A maximum of ${this.maximum} items are allowed.`);
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
- throw new Error(`A minimum of ${this.minimum} items are required.`);
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++) {
@@ -1,10 +1,13 @@
1
- import { type SchemaPropertyDecorator, type SchemaDecoratorOptions } from '../decorators/index.js';
1
+ import { type SchemaDecoratorOptions, type SchemaPropertyDecorator } from '../decorators/index.js';
2
2
  import { SimpleSchema, type SimpleSchemaOptions } from './simple.js';
3
- export type DateSchemaOptions = SimpleSchemaOptions<globalThis.Date> & {
4
- integer?: boolean;
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<globalThis.Date> {
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;
@@ -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 globalThis.Date(value);
12
- return globalThis.Number.isNaN(result.getTime())
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 globalThis.Date(value), valid: false })
18
+ number: (value) => ({ success: true, value: new Date(value), valid: false }),
17
19
  },
18
20
  constraints: [
19
- (options?.integer == true) ? (value) => globalThis.Number.isInteger(value) ? ({ success: true }) : ({ success: false, error: 'value is not an integer.' }) : null
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 SchemaPropertyDecorator, type SchemaDecoratorOptions } from '../decorators/index.js';
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>;
@@ -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 SchemaPropertyDecorator, type SchemaDecoratorOptions } from '../decorators/index.js';
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> {
@@ -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 SchemaPropertyDecorator, type SchemaDecoratorOptions } from '../decorators/index.js';
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 { isDefined, isUint8Array } from '../../utils/type-guards.js';
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(`invalid hex string at position ${i}`);
65
+ throw new AssertionError(`Invalid hex string at position ${i}.`);
66
66
  }
67
67
  bytes[i / 2] = byte;
68
68
  }
@@ -1,3 +1,3 @@
1
1
  import type { BinaryData } from '../types/index.js';
2
2
  export declare function zBase32Encode(buffer: BinaryData): string;
3
- export declare function zBase32Decode(input: string): Uint8Array;
3
+ export declare function zBase32Decode(input: string): Uint8Array<ArrayBuffer>;
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 Error(`invalid character at index ${i}`);
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';