@temelj/standard-schema 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -43,3 +43,9 @@ import { ss } from "@temelj/standard-schema";
43
43
  const schema = ss.string();
44
44
  const result = schema["~standard"].validate("hello");
45
45
  ```
46
+
47
+ `SchemaFields` names an object's field schemas. `object` validates those fields and strips other keys; `strictObject` rejects extra keys. `looseObject` preserves extra keys at runtime, but its output type exposes only the validated fields.
48
+
49
+ `array()` checks the container and returns `unknown[]`. Pass an element schema, such as `array(string())`, to validate its elements. `fn()` checks that a value is callable; it does not validate the function's parameters or result.
50
+
51
+ `defaulted(schema, value)` uses the supplied value, including function values. Use `defaultedWith(schema, () => value)` to create a default only when the input is `undefined`.
package/dist/mod.d.mts CHANGED
@@ -1,54 +1,130 @@
1
1
  import { StandardSchemaV1 } from "@standard-schema/spec";
2
-
3
2
  //#region src/mod.d.ts
4
- type Schema<TInput = unknown, TOutput = TInput> = StandardSchemaV1<TInput, TOutput>;
5
- type SchemaOutput<TSchema extends Schema> = StandardSchemaV1.InferOutput<TSchema>;
6
- type SchemaResult<TOutput> = StandardSchemaV1.Result<TOutput>;
7
- type SchemaIssue = StandardSchemaV1.Issue;
8
- type SchemaValidator<TOutput> = (value: unknown) => SchemaResult<TOutput>;
9
- type SchemaShape = Record<string, Schema>;
10
- type ObjectOutput<TShape extends SchemaShape> = { readonly [TKey in keyof TShape]: SchemaOutput<TShape[TKey]> };
11
- declare function schema<TInput, TOutput>(validate: SchemaValidator<TOutput>): Schema<TInput, TOutput>;
12
- declare function success<T>(value: T): StandardSchemaV1.SuccessResult<T>;
13
- declare function failure(message: string, path?: ReadonlyArray<PropertyKey>): StandardSchemaV1.FailureResult;
14
- declare class StandardSchemaValidationError extends Error {
3
+ export type Schema<TInput = unknown, TOutput = TInput> = StandardSchemaV1<TInput, TOutput>;
4
+ export type SchemaInput<TSchema extends Schema> = StandardSchemaV1.InferInput<TSchema>;
5
+ export type SchemaOutput<TSchema extends Schema> = StandardSchemaV1.InferOutput<TSchema>;
6
+ export type SchemaResult<TOutput> = StandardSchemaV1.Result<TOutput>;
7
+ export type SchemaIssue = StandardSchemaV1.Issue;
8
+ export type SchemaValidator<TOutput> = (value: unknown) => SchemaResult<TOutput>;
9
+ export type SchemaFields = Record<string, Schema>;
10
+ export type ObjectOutput<TFields extends SchemaFields> = { readonly [TKey in keyof TFields]: SchemaOutput<TFields[TKey]>; };
11
+ export type ObjectInput<TFields extends SchemaFields> = { readonly [TKey in keyof TFields]: SchemaInput<TFields[TKey]>; };
12
+ export type SafeParseResult<T> = {
13
+ readonly success: true;
14
+ readonly value: T;
15
+ } | {
16
+ readonly success: false;
15
17
  readonly issues: ReadonlyArray<SchemaIssue>;
16
- constructor(message: string, issues: ReadonlyArray<SchemaIssue>);
18
+ };
19
+ export interface ObjectOptions {
20
+ readonly unknownKeys?: "strip" | "passthrough" | "strict";
21
+ }
22
+ interface Constructor<T> extends Function {
23
+ readonly prototype: T;
24
+ readonly name: string;
25
+ }
26
+ export declare function schema<TInput, TOutput>(validate: SchemaValidator<TOutput>): Schema<TInput, TOutput>;
27
+ export declare function success<T>(value: T): StandardSchemaV1.SuccessResult<T>;
28
+ export declare function failure(message: string, path?: ReadonlyArray<PropertyKey>): StandardSchemaV1.FailureResult;
29
+ export declare class StandardSchemaValidationError extends Error {
30
+ readonly issues: ReadonlyArray<SchemaIssue>;
31
+ constructor(message: string, issues: ReadonlyArray<SchemaIssue>, context?: Function);
32
+ static failed(this: void, message: string, issues: ReadonlyArray<SchemaIssue>): never;
33
+ }
34
+ export declare class StandardSchemaAsyncValidationError extends Error {
35
+ constructor(message: string, context?: Function);
36
+ static unsupported(this: void): never;
17
37
  }
18
- declare function validateStandardSchema<TSchema extends Schema>(inputSchema: TSchema, value: unknown, message?: string): Promise<SchemaOutput<TSchema>>;
19
- declare function validateStandardSchemaSync<TSchema extends Schema>(inputSchema: TSchema, value: unknown, message?: string): SchemaOutput<TSchema>;
20
- declare function unknown(): Schema<unknown>;
21
- declare function string(message?: string): Schema<unknown, string>;
22
- declare function number(message?: string): Schema<unknown, number>;
23
- declare function boolean(message?: string): Schema<unknown, boolean>;
24
- declare function literal<const TValue extends string | number | boolean | null | undefined>(expected: TValue, message?: string): Schema<unknown, TValue>;
25
- declare function picklist<const TValues extends readonly [unknown, ...unknown[]]>(values: TValues, message?: string): Schema<unknown, TValues[number]>;
26
- declare function union<const TSchemas extends readonly [Schema, ...Schema[]]>(schemas: TSchemas, message?: string): Schema<unknown, SchemaOutput<TSchemas[number]>>;
27
- declare function array<TItem extends Schema = Schema<unknown>>(itemSchema?: TItem, message?: string): Schema<unknown, SchemaOutput<TItem>[]>;
28
- declare function object<TShape extends SchemaShape>(shape: TShape, message?: string): Schema<unknown, ObjectOutput<TShape>>;
29
- declare function record<TValue extends Schema>(valueSchema: TValue, message?: string): Schema<unknown, Record<string, SchemaOutput<TValue>>>;
30
- declare function optional<TSchema extends Schema>(inner: TSchema): Schema<unknown, SchemaOutput<TSchema> | undefined>;
31
- declare function defaulted<TSchema extends Schema>(inner: TSchema, defaultValue: SchemaOutput<TSchema> | (() => SchemaOutput<TSchema>)): Schema<unknown, SchemaOutput<TSchema>>;
32
- declare const ss: {
38
+ export declare function validateStandardSchema<TSchema extends Schema>(inputSchema: TSchema, value: unknown, message?: string): Promise<SchemaOutput<TSchema>>;
39
+ export declare function validateStandardSchemaSync<TSchema extends Schema>(inputSchema: TSchema, value: unknown, message?: string): SchemaOutput<TSchema>;
40
+ export declare function safeParse<TSchema extends Schema>(inputSchema: TSchema, value: SchemaInput<TSchema>): Promise<SafeParseResult<SchemaOutput<TSchema>>>;
41
+ export declare function safeParseSync<TSchema extends Schema>(inputSchema: TSchema, value: SchemaInput<TSchema>): SafeParseResult<SchemaOutput<TSchema>>;
42
+ export declare function parse<TSchema extends Schema>(inputSchema: TSchema, value: SchemaInput<TSchema>, message?: string): Promise<SchemaOutput<TSchema>>;
43
+ export declare function parseSync<TSchema extends Schema>(inputSchema: TSchema, value: SchemaInput<TSchema>, message?: string): SchemaOutput<TSchema>;
44
+ export declare function unknown(): Schema<unknown>;
45
+ export declare function string(message?: string): Schema<unknown, string>;
46
+ export declare function number(message?: string): Schema<unknown, number>;
47
+ export declare function finite(message?: string): Schema<unknown, number>;
48
+ export declare function integer(message?: string): Schema<unknown, number>;
49
+ export declare function safeInteger(message?: string): Schema<unknown, number>;
50
+ export declare function positiveNumber(message?: string): Schema<unknown, number>;
51
+ export declare function nonNegativeNumber(message?: string): Schema<unknown, number>;
52
+ export declare function positiveSafeInteger(message?: string): Schema<unknown, number>;
53
+ export declare function nonNegativeSafeInteger(message?: string): Schema<unknown, number>;
54
+ export declare function min(inner: Schema<unknown, number>, minimum: number, message?: string): Schema<unknown, number>;
55
+ export declare function max(inner: Schema<unknown, number>, maximum: number, message?: string): Schema<unknown, number>;
56
+ export declare function nonEmptyString(message?: string): Schema<unknown, string>;
57
+ export declare function nonBlankString(message?: string): Schema<unknown, string>;
58
+ export declare function boolean(message?: string): Schema<unknown, boolean>;
59
+ export declare function fn(message?: string): Schema<unknown, Function>;
60
+ export declare function instanceOf<T>(constructor: Constructor<T>, message?: string): Schema<unknown, T>;
61
+ export declare function literal<const TValue extends string | number | boolean | null | undefined>(expected: TValue, message?: string): Schema<unknown, TValue>;
62
+ export declare function picklist<const TValues extends readonly [unknown, ...unknown[]]>(values: TValues, message?: string): Schema<unknown, TValues[number]>;
63
+ export declare function union<const TSchemas extends readonly [Schema, ...Schema[]]>(schemas: TSchemas, message?: string): Schema<unknown, SchemaOutput<TSchemas[number]>>;
64
+ export declare function array(): Schema<unknown, unknown[]>;
65
+ export declare function array<TItem extends Schema>(itemSchema: TItem, message?: string): Schema<unknown, SchemaOutput<TItem>[]>;
66
+ export declare function object<TFields extends SchemaFields>(fields: TFields, message?: string, options?: ObjectOptions): Schema<unknown, ObjectOutput<TFields>>;
67
+ export declare function strictObject<TFields extends SchemaFields>(fields: TFields, message?: string): Schema<unknown, ObjectOutput<TFields>>;
68
+ export declare function looseObject<TFields extends SchemaFields>(fields: TFields, message?: string): Schema<unknown, ObjectOutput<TFields>>;
69
+ export declare function record<TValue extends Schema>(valueSchema: TValue, message?: string): Schema<unknown, Record<string, SchemaOutput<TValue>>>;
70
+ export declare function optional<TSchema extends Schema>(inner: TSchema): Schema<unknown, SchemaOutput<TSchema> | undefined>;
71
+ export declare function defaulted<TSchema extends Schema>(inner: TSchema, defaultValue: SchemaOutput<TSchema>): Schema<unknown, SchemaOutput<TSchema>>;
72
+ export declare function defaultedWith<TSchema extends Schema>(inner: TSchema, createDefault: () => SchemaOutput<TSchema>): Schema<unknown, SchemaOutput<TSchema>>;
73
+ export declare function refine<TSchema extends Schema, TOutput extends SchemaOutput<TSchema>>(inner: TSchema, predicate: (value: SchemaOutput<TSchema>) => value is TOutput, message?: string): Schema<SchemaInput<TSchema>, TOutput>;
74
+ export declare function refine<TSchema extends Schema>(inner: TSchema, predicate: (value: SchemaOutput<TSchema>) => boolean, message?: string): Schema<SchemaInput<TSchema>, SchemaOutput<TSchema>>;
75
+ export declare function transform<TSchema extends Schema, TOutput>(inner: TSchema, mapper: (value: SchemaOutput<TSchema>) => TOutput): Schema<SchemaInput<TSchema>, TOutput>;
76
+ export declare function pipe<TLeft extends Schema, TRight extends Schema>(left: TLeft, right: TRight): Schema<SchemaInput<TLeft>, SchemaOutput<TRight>>;
77
+ export declare function extend<TBase extends SchemaFields, TExtension extends SchemaFields>(base: TBase, extension: TExtension): Omit<TBase, keyof TExtension> & TExtension;
78
+ export declare function pick<TFields extends SchemaFields, const TKeys extends readonly (keyof TFields)[]>(fields: TFields, keys: TKeys): Pick<TFields, TKeys[number]>;
79
+ export declare function omit<TFields extends SchemaFields, const TKeys extends readonly (keyof TFields)[]>(fields: TFields, keys: TKeys): Omit<TFields, TKeys[number]>;
80
+ export declare function partial<TFields extends SchemaFields>(fields: TFields): { readonly [TKey in keyof TFields]: Schema<unknown, SchemaOutput<TFields[TKey]> | undefined>; };
81
+ export declare const ss: {
33
82
  schema: typeof schema;
34
83
  success: typeof success;
35
84
  failure: typeof failure;
36
85
  StandardSchemaValidationError: typeof StandardSchemaValidationError;
37
86
  validateStandardSchema: typeof validateStandardSchema;
38
87
  validateStandardSchemaSync: typeof validateStandardSchemaSync;
88
+ safeParse: typeof safeParse;
89
+ safeParseSync: typeof safeParseSync;
90
+ parse: typeof parse;
91
+ parseSync: typeof parseSync;
39
92
  unknown: typeof unknown;
40
93
  string: typeof string;
41
94
  number: typeof number;
95
+ finite: typeof finite;
96
+ integer: typeof integer;
97
+ safeInteger: typeof safeInteger;
98
+ positiveNumber: typeof positiveNumber;
99
+ nonNegativeNumber: typeof nonNegativeNumber;
100
+ positiveSafeInteger: typeof positiveSafeInteger;
101
+ nonNegativeSafeInteger: typeof nonNegativeSafeInteger;
102
+ min: typeof min;
103
+ max: typeof max;
104
+ nonEmptyString: typeof nonEmptyString;
105
+ nonBlankString: typeof nonBlankString;
42
106
  boolean: typeof boolean;
107
+ fn: typeof fn;
108
+ instanceOf: typeof instanceOf;
43
109
  literal: typeof literal;
44
110
  picklist: typeof picklist;
45
111
  union: typeof union;
46
112
  array: typeof array;
47
113
  object: typeof object;
114
+ strictObject: typeof strictObject;
115
+ looseObject: typeof looseObject;
48
116
  record: typeof record;
49
117
  optional: typeof optional;
50
118
  defaulted: typeof defaulted;
119
+ defaultedWith: typeof defaultedWith;
120
+ refine: typeof refine;
121
+ transform: typeof transform;
122
+ pipe: typeof pipe;
123
+ extend: typeof extend;
124
+ pick: typeof pick;
125
+ omit: typeof omit;
126
+ partial: typeof partial;
51
127
  };
52
128
  //#endregion
53
- export { ObjectOutput, Schema, SchemaIssue, SchemaOutput, SchemaResult, SchemaShape, SchemaValidator, StandardSchemaValidationError, array, boolean, defaulted, failure, literal, number, object, optional, picklist, record, schema, ss, string, success, union, unknown, validateStandardSchema, validateStandardSchemaSync };
129
+ export {};
54
130
  //# sourceMappingURL=mod.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mod.d.mts","names":[],"sources":["../src/mod.ts"],"mappings":";;;KAEY,MAAA,6BAAmC,MAAA,IAAU,gBAAA,CAAiB,MAAA,EAAQ,OAAA;AAAA,KAEtE,YAAA,iBAA6B,MAAA,IAAU,gBAAA,CAAiB,WAAA,CAAY,OAAA;AAAA,KAEpE,YAAA,YAAwB,gBAAA,CAAiB,MAAM,CAAC,OAAA;AAAA,KAEhD,WAAA,GAAc,gBAAA,CAAiB,KAAK;AAAA,KAEpC,eAAA,aAA4B,KAAA,cAAmB,YAAY,CAAC,OAAA;AAAA,KAE5D,WAAA,GAAc,MAAM,SAAS,MAAA;AAAA,KAE7B,YAAA,gBAA4B,WAAA,8BACd,MAAA,GAAS,YAAA,CAAa,MAAA,CAAO,IAAA;AAAA,iBAGvC,MAAA,kBACd,QAAA,EAAU,eAAA,CAAgB,OAAA,IACzB,MAAA,CAAO,MAAA,EAAQ,OAAA;AAAA,iBAUF,OAAA,IAAW,KAAA,EAAO,CAAA,GAAI,gBAAA,CAAiB,aAAA,CAAc,CAAA;AAAA,iBAIrD,OAAA,CACd,OAAA,UACA,IAAA,GAAO,aAAA,CAAc,WAAA,IACpB,gBAAA,CAAiB,aAAA;AAAA,cAWP,6BAAA,SAAsC,KAAA;EAAA,SACjC,MAAA,EAAQ,aAAA,CAAc,WAAA;cAE1B,OAAA,UAAiB,MAAA,EAAQ,aAAA,CAAc,WAAA;AAAA;AAAA,iBAO/B,sBAAA,iBAAuC,MAAA,EAC3D,WAAA,EAAa,OAAA,EACb,KAAA,WACA,OAAA,YACC,OAAA,CAAQ,YAAA,CAAa,OAAA;AAAA,iBAQR,0BAAA,iBAA2C,MAAA,EACzD,WAAA,EAAa,OAAA,EACb,KAAA,WACA,OAAA,YACC,YAAA,CAAa,OAAA;AAAA,iBASA,OAAA,IAAW,MAAM;AAAA,iBAIjB,MAAA,CAAO,OAAA,YAAgC,MAAM;AAAA,iBAI7C,MAAA,CAAO,OAAA,YAAgC,MAAM;AAAA,iBAI7C,OAAA,CAAQ,OAAA,YAAiC,MAAM;AAAA,iBAI/C,OAAA,oEACd,QAAA,EAAU,MAAA,EACV,OAAA,YACC,MAAA,UAAgB,MAAA;AAAA,iBAIH,QAAA,yDACd,MAAA,EAAQ,OAAA,EACR,OAAA,YACC,MAAA,UAAgB,OAAA;AAAA,iBAQH,KAAA,kCAAuC,MAAA,KAAW,MAAA,KAChE,OAAA,EAAS,QAAA,EACT,OAAA,YACC,MAAA,UAAgB,YAAA,CAAa,QAAA;AAAA,iBAoBhB,KAAA,eAAoB,MAAA,GAAS,MAAA,WAC3C,UAAA,GAAa,KAAA,EACb,OAAA,YACC,MAAA,UAAgB,YAAA,CAAa,KAAA;AAAA,iBA2BhB,MAAA,gBAAsB,WAAA,EACpC,KAAA,EAAO,MAAA,EACP,OAAA,YACC,MAAA,UAAgB,YAAA,CAAa,MAAA;AAAA,iBA4BhB,MAAA,gBAAsB,MAAA,EACpC,WAAA,EAAa,MAAA,EACb,OAAA,YACC,MAAA,UAAgB,MAAA,SAAe,YAAA,CAAa,MAAA;AAAA,iBAwB/B,QAAA,iBAAyB,MAAA,EACvC,KAAA,EAAO,OAAA,GACN,MAAA,UAAgB,YAAA,CAAa,OAAA;AAAA,iBAYhB,SAAA,iBAA0B,MAAA,EACxC,KAAA,EAAO,OAAA,EACP,YAAA,EAAc,YAAA,CAAa,OAAA,WAAkB,YAAA,CAAa,OAAA,KACzD,MAAA,UAAgB,YAAA,CAAa,OAAA;AAAA,cA6BnB,EAAA"}
1
+ {"version":3,"file":"mod.d.mts","names":[],"sources":["../src/mod.ts"],"mappings":"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"}
package/dist/mod.mjs CHANGED
@@ -1,3 +1,4 @@
1
+ import { isBoolean, isFunction, isNumber, isObject, isString } from "@temelj/value";
1
2
  //#region src/mod.ts
2
3
  function schema(validate) {
3
4
  return { "~standard": {
@@ -12,56 +13,134 @@ function success(value) {
12
13
  function failure(message, path) {
13
14
  return { issues: [{
14
15
  message,
15
- ...path === void 0 ? {} : { path }
16
+ path
16
17
  }] };
17
18
  }
18
- var StandardSchemaValidationError = class extends Error {
19
+ var StandardSchemaValidationError = class StandardSchemaValidationError extends Error {
19
20
  issues;
20
- constructor(message, issues) {
21
+ constructor(message, issues, context) {
21
22
  super(message);
22
23
  this.name = "StandardSchemaValidationError";
23
24
  this.issues = issues;
25
+ if (Error.captureStackTrace !== void 0) Error.captureStackTrace(this, context ?? this.constructor);
26
+ }
27
+ static failed(message, issues) {
28
+ throw new StandardSchemaValidationError(message, issues, StandardSchemaValidationError.failed);
29
+ }
30
+ };
31
+ var StandardSchemaAsyncValidationError = class StandardSchemaAsyncValidationError extends Error {
32
+ constructor(message, context) {
33
+ super(message);
34
+ this.name = "StandardSchemaAsyncValidationError";
35
+ if (Error.captureStackTrace !== void 0) Error.captureStackTrace(this, context ?? this.constructor);
36
+ }
37
+ static unsupported() {
38
+ throw new StandardSchemaAsyncValidationError("Async schema validation is not supported", StandardSchemaAsyncValidationError.unsupported);
24
39
  }
25
40
  };
26
41
  async function validateStandardSchema(inputSchema, value, message = "Schema validation failed") {
27
42
  const result = await inputSchema["~standard"].validate(value);
28
43
  if (!result.issues) return result.value;
29
- throw new StandardSchemaValidationError(message, result.issues);
44
+ StandardSchemaValidationError.failed(message, result.issues);
30
45
  }
31
46
  function validateStandardSchemaSync(inputSchema, value, message = "Schema validation failed") {
32
- const result = inputSchema["~standard"].validate(value);
33
- ensureSynchronous(result);
47
+ const result = evaluate(inputSchema, value);
34
48
  if (!result.issues) return result.value;
35
- throw new StandardSchemaValidationError(message, result.issues);
49
+ StandardSchemaValidationError.failed(message, result.issues);
50
+ }
51
+ async function safeParse(inputSchema, value) {
52
+ const result = await inputSchema["~standard"].validate(value);
53
+ return result.issues ? {
54
+ success: false,
55
+ issues: result.issues
56
+ } : {
57
+ success: true,
58
+ value: result.value
59
+ };
60
+ }
61
+ function safeParseSync(inputSchema, value) {
62
+ const result = evaluate(inputSchema, value);
63
+ return result.issues ? {
64
+ success: false,
65
+ issues: result.issues
66
+ } : {
67
+ success: true,
68
+ value: result.value
69
+ };
70
+ }
71
+ async function parse(inputSchema, value, message) {
72
+ return await validateStandardSchema(inputSchema, value, message);
73
+ }
74
+ function parseSync(inputSchema, value, message) {
75
+ return validateStandardSchemaSync(inputSchema, value, message);
36
76
  }
37
77
  function unknown() {
38
78
  return schema((value) => success(value));
39
79
  }
40
80
  function string(message = "Expected a string") {
41
- return schema((value) => typeof value === "string" ? success(value) : failure(message));
81
+ return schema((value) => isString(value) ? success(value) : failure(message));
42
82
  }
43
83
  function number(message = "Expected a number") {
44
- return schema((value) => typeof value === "number" ? success(value) : failure(message));
84
+ return schema((value) => isNumber(value) ? success(value) : failure(message));
85
+ }
86
+ function finite(message = "Expected a finite number") {
87
+ return refine(number(), Number.isFinite, message);
88
+ }
89
+ function integer(message = "Expected an integer") {
90
+ return refine(number(), Number.isInteger, message);
91
+ }
92
+ function safeInteger(message = "Expected a safe integer") {
93
+ return refine(number(), Number.isSafeInteger, message);
94
+ }
95
+ function positiveNumber(message = "Expected a positive number") {
96
+ return refine(number(), (value) => Number.isFinite(value) && value > 0, message);
97
+ }
98
+ function nonNegativeNumber(message = "Expected a non-negative number") {
99
+ return refine(number(), (value) => Number.isFinite(value) && value >= 0, message);
100
+ }
101
+ function positiveSafeInteger(message = "Expected a positive safe integer") {
102
+ return refine(number(), (value) => Number.isSafeInteger(value) && value > 0, message);
103
+ }
104
+ function nonNegativeSafeInteger(message = "Expected a non-negative safe integer") {
105
+ return refine(number(), (value) => Number.isSafeInteger(value) && value >= 0, message);
106
+ }
107
+ function min(inner, minimum, message = `Expected a number greater than or equal to ${minimum}`) {
108
+ return refine(inner, (value) => value >= minimum, message);
109
+ }
110
+ function max(inner, maximum, message = `Expected a number less than or equal to ${maximum}`) {
111
+ return refine(inner, (value) => value <= maximum, message);
112
+ }
113
+ function nonEmptyString(message = "Expected a non-empty string") {
114
+ return refine(string(), (value) => value.length > 0, message);
115
+ }
116
+ function nonBlankString(message = "Expected a non-blank string") {
117
+ return refine(string(), (value) => value.trim().length > 0, message);
45
118
  }
46
119
  function boolean(message = "Expected a boolean") {
47
- return schema((value) => typeof value === "boolean" ? success(value) : failure(message));
120
+ return schema((value) => isBoolean(value) ? success(value) : failure(message));
121
+ }
122
+ function fn(message = "Expected a function") {
123
+ return schema((value) => isFunction(value) ? success(value) : failure(message));
124
+ }
125
+ function instanceOf(constructor, message = `Expected ${constructor.name}`) {
126
+ return schema((value) => value instanceof constructor ? success(value) : failure(message));
48
127
  }
49
128
  function literal(expected, message = `Expected ${String(expected)}`) {
50
129
  return schema((value) => Object.is(value, expected) ? success(expected) : failure(message));
51
130
  }
52
131
  function picklist(values, message = `Expected one of ${values.map(String).join(", ")}`) {
53
- return schema((value) => values.some((item) => Object.is(item, value)) ? success(value) : failure(message));
132
+ return schema((value) => {
133
+ const match = values.findIndex((item) => Object.is(item, value));
134
+ return match === -1 ? failure(message) : success(values[match]);
135
+ });
54
136
  }
55
137
  function union(schemas, message = "Expected a union match") {
56
138
  return schema((value) => {
57
- const issues = [];
58
139
  for (const itemSchema of schemas) {
59
- const result = itemSchema["~standard"].validate(value);
60
- ensureSynchronous(result);
140
+ const result = evaluate(itemSchema, value);
61
141
  if (!result.issues) return success(result.value);
62
- issues.push(...result.issues);
63
142
  }
64
- return issues.length > 0 ? failure(message) : failure(message);
143
+ return failure(message);
65
144
  });
66
145
  }
67
146
  function array(itemSchema, message = "Expected an array") {
@@ -71,37 +150,62 @@ function array(itemSchema, message = "Expected an array") {
71
150
  const output = [];
72
151
  const issues = [];
73
152
  for (let index = 0; index < value.length; index++) {
74
- const result = itemSchema["~standard"].validate(value[index]);
75
- ensureSynchronous(result);
153
+ const result = evaluate(itemSchema, value[index]);
76
154
  if (result.issues) issues.push(...result.issues.map((issue) => withPath(index, issue)));
77
155
  else output.push(result.value);
78
156
  }
79
157
  return issues.length > 0 ? { issues } : success(output);
80
158
  });
81
159
  }
82
- function object(shape, message = "Expected an object") {
160
+ function object(fields, message = "Expected an object", options = {}) {
83
161
  return schema((value) => {
84
- if (value === null || typeof value !== "object" || Array.isArray(value)) return failure(message);
162
+ if (!isObject(value) || Array.isArray(value)) return failure(message);
85
163
  const input = value;
86
164
  const output = {};
165
+ if (options.unknownKeys === "passthrough") for (const key of Reflect.ownKeys(input)) {
166
+ if (!Object.prototype.propertyIsEnumerable.call(input, key)) continue;
167
+ Object.defineProperty(output, key, {
168
+ value: input[key],
169
+ enumerable: true,
170
+ writable: true,
171
+ configurable: true
172
+ });
173
+ }
87
174
  const issues = [];
88
- for (const key of Object.keys(shape)) {
89
- const result = shape[key]["~standard"].validate(input[key]);
90
- ensureSynchronous(result);
175
+ const fieldKeys = Object.keys(fields);
176
+ if (options.unknownKeys === "strict") {
177
+ for (const key of Object.keys(input)) if (!fieldKeys.includes(key)) issues.push({
178
+ message: "Unexpected key",
179
+ path: [key]
180
+ });
181
+ }
182
+ for (const key of fieldKeys) {
183
+ const hasOwnField = Object.prototype.hasOwnProperty.call(input, key);
184
+ const result = evaluate(fields[key], hasOwnField ? input[key] : void 0);
91
185
  if (result.issues) issues.push(...result.issues.map((issue) => withPath(key, issue)));
92
- else output[key] = result.value;
186
+ else if (hasOwnField || result.value !== void 0) Object.defineProperty(output, key, {
187
+ value: result.value,
188
+ enumerable: true,
189
+ writable: true,
190
+ configurable: true
191
+ });
93
192
  }
94
193
  return issues.length > 0 ? { issues } : success(output);
95
194
  });
96
195
  }
196
+ function strictObject(fields, message = "Expected an object") {
197
+ return object(fields, message, { unknownKeys: "strict" });
198
+ }
199
+ function looseObject(fields, message = "Expected an object") {
200
+ return object(fields, message, { unknownKeys: "passthrough" });
201
+ }
97
202
  function record(valueSchema, message = "Expected an object") {
98
203
  return schema((value) => {
99
- if (value === null || typeof value !== "object" || Array.isArray(value)) return failure(message);
204
+ if (!isObject(value) || Array.isArray(value)) return failure(message);
100
205
  const output = {};
101
206
  const issues = [];
102
207
  for (const [key, item] of Object.entries(value)) {
103
- const result = valueSchema["~standard"].validate(item);
104
- ensureSynchronous(result);
208
+ const result = evaluate(valueSchema, item);
105
209
  if (result.issues) issues.push(...result.issues.map((issue) => withPath(key, issue)));
106
210
  else output[key] = result.value;
107
211
  }
@@ -111,21 +215,66 @@ function record(valueSchema, message = "Expected an object") {
111
215
  function optional(inner) {
112
216
  return schema((value) => {
113
217
  if (value === void 0) return success(void 0);
114
- const result = inner["~standard"].validate(value);
115
- ensureSynchronous(result);
116
- return result;
218
+ return evaluate(inner, value);
117
219
  });
118
220
  }
119
221
  function defaulted(inner, defaultValue) {
120
222
  return schema((value) => {
121
- if (value === void 0) return success(typeof defaultValue === "function" ? defaultValue() : defaultValue);
122
- const result = inner["~standard"].validate(value);
123
- ensureSynchronous(result);
124
- return result;
223
+ if (value === void 0) return success(defaultValue);
224
+ return evaluate(inner, value);
225
+ });
226
+ }
227
+ function defaultedWith(inner, createDefault) {
228
+ return schema((value) => value === void 0 ? success(createDefault()) : evaluate(inner, value));
229
+ }
230
+ function refine(inner, predicate, message = "Invalid value") {
231
+ return schema((value) => {
232
+ const result = evaluate(inner, value);
233
+ if (result.issues) return result;
234
+ return predicate(result.value) ? result : failure(message);
235
+ });
236
+ }
237
+ function transform(inner, mapper) {
238
+ return schema((value) => {
239
+ const result = evaluate(inner, value);
240
+ if (result.issues) return result;
241
+ return success(mapper(result.value));
125
242
  });
126
243
  }
244
+ function pipe(left, right) {
245
+ return schema((value) => {
246
+ const leftResult = evaluate(left, value);
247
+ if (leftResult.issues) return leftResult;
248
+ return evaluate(right, leftResult.value);
249
+ });
250
+ }
251
+ function extend(base, extension) {
252
+ return {
253
+ ...base,
254
+ ...extension
255
+ };
256
+ }
257
+ function pick(fields, keys) {
258
+ return Object.fromEntries(keys.map((key) => [key, fields[key]]));
259
+ }
260
+ function omit(fields, keys) {
261
+ const result = { ...fields };
262
+ for (const key of keys) delete result[key];
263
+ return result;
264
+ }
265
+ function partial(fields) {
266
+ const entries = Reflect.ownKeys(fields).map((key) => {
267
+ return [key, optional(fields[key])];
268
+ });
269
+ return Object.fromEntries(entries);
270
+ }
271
+ function evaluate(inputSchema, value) {
272
+ const result = inputSchema["~standard"].validate(value);
273
+ ensureSynchronous(result);
274
+ return result;
275
+ }
127
276
  function ensureSynchronous(value) {
128
- if (value instanceof Promise) throw new Error("Async schema validation is not supported");
277
+ if (value instanceof Promise) StandardSchemaAsyncValidationError.unsupported();
129
278
  }
130
279
  function withPath(key, issue) {
131
280
  return {
@@ -140,20 +289,47 @@ const ss = {
140
289
  StandardSchemaValidationError,
141
290
  validateStandardSchema,
142
291
  validateStandardSchemaSync,
292
+ safeParse,
293
+ safeParseSync,
294
+ parse,
295
+ parseSync,
143
296
  unknown,
144
297
  string,
145
298
  number,
299
+ finite,
300
+ integer,
301
+ safeInteger,
302
+ positiveNumber,
303
+ nonNegativeNumber,
304
+ positiveSafeInteger,
305
+ nonNegativeSafeInteger,
306
+ min,
307
+ max,
308
+ nonEmptyString,
309
+ nonBlankString,
146
310
  boolean,
311
+ fn,
312
+ instanceOf,
147
313
  literal,
148
314
  picklist,
149
315
  union,
150
316
  array,
151
317
  object,
318
+ strictObject,
319
+ looseObject,
152
320
  record,
153
321
  optional,
154
- defaulted
322
+ defaulted,
323
+ defaultedWith,
324
+ refine,
325
+ transform,
326
+ pipe,
327
+ extend,
328
+ pick,
329
+ omit,
330
+ partial
155
331
  };
156
332
  //#endregion
157
- export { StandardSchemaValidationError, array, boolean, defaulted, failure, literal, number, object, optional, picklist, record, schema, ss, string, success, union, unknown, validateStandardSchema, validateStandardSchemaSync };
333
+ export { StandardSchemaAsyncValidationError, StandardSchemaValidationError, array, boolean, defaulted, defaultedWith, extend, failure, finite, fn, instanceOf, integer, literal, looseObject, max, min, nonBlankString, nonEmptyString, nonNegativeNumber, nonNegativeSafeInteger, number, object, omit, optional, parse, parseSync, partial, pick, picklist, pipe, positiveNumber, positiveSafeInteger, record, refine, safeInteger, safeParse, safeParseSync, schema, ss, strictObject, string, success, transform, union, unknown, validateStandardSchema, validateStandardSchemaSync };
158
334
 
159
335
  //# sourceMappingURL=mod.mjs.map
package/dist/mod.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"mod.mjs","names":[],"sources":["../src/mod.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\nexport type Schema<TInput = unknown, TOutput = TInput> = StandardSchemaV1<TInput, TOutput>;\n\nexport type SchemaOutput<TSchema extends Schema> = StandardSchemaV1.InferOutput<TSchema>;\n\nexport type SchemaResult<TOutput> = StandardSchemaV1.Result<TOutput>;\n\nexport type SchemaIssue = StandardSchemaV1.Issue;\n\nexport type SchemaValidator<TOutput> = (value: unknown) => SchemaResult<TOutput>;\n\nexport type SchemaShape = Record<string, Schema>;\n\nexport type ObjectOutput<TShape extends SchemaShape> = {\n readonly [TKey in keyof TShape]: SchemaOutput<TShape[TKey]>;\n};\n\nexport function schema<TInput, TOutput>(\n validate: SchemaValidator<TOutput>,\n): Schema<TInput, TOutput> {\n return {\n \"~standard\": {\n version: 1,\n vendor: \"@temelj/standard-schema\",\n validate,\n },\n };\n}\n\nexport function success<T>(value: T): StandardSchemaV1.SuccessResult<T> {\n return { value };\n}\n\nexport function failure(\n message: string,\n path?: ReadonlyArray<PropertyKey>,\n): StandardSchemaV1.FailureResult {\n return {\n issues: [\n {\n message,\n ...(path === undefined ? {} : { path }),\n },\n ],\n };\n}\n\nexport class StandardSchemaValidationError extends Error {\n public readonly issues: ReadonlyArray<SchemaIssue>;\n\n constructor(message: string, issues: ReadonlyArray<SchemaIssue>) {\n super(message);\n this.name = \"StandardSchemaValidationError\";\n this.issues = issues;\n }\n}\n\nexport async function validateStandardSchema<TSchema extends Schema>(\n inputSchema: TSchema,\n value: unknown,\n message = \"Schema validation failed\",\n): Promise<SchemaOutput<TSchema>> {\n const result = await inputSchema[\"~standard\"].validate(value);\n if (!result.issues) {\n return result.value as SchemaOutput<TSchema>;\n }\n throw new StandardSchemaValidationError(message, result.issues);\n}\n\nexport function validateStandardSchemaSync<TSchema extends Schema>(\n inputSchema: TSchema,\n value: unknown,\n message = \"Schema validation failed\",\n): SchemaOutput<TSchema> {\n const result = inputSchema[\"~standard\"].validate(value);\n ensureSynchronous(result);\n if (!result.issues) {\n return result.value as SchemaOutput<TSchema>;\n }\n throw new StandardSchemaValidationError(message, result.issues);\n}\n\nexport function unknown(): Schema<unknown> {\n return schema((value) => success(value));\n}\n\nexport function string(message = \"Expected a string\"): Schema<unknown, string> {\n return schema((value) => (typeof value === \"string\" ? success(value) : failure(message)));\n}\n\nexport function number(message = \"Expected a number\"): Schema<unknown, number> {\n return schema((value) => (typeof value === \"number\" ? success(value) : failure(message)));\n}\n\nexport function boolean(message = \"Expected a boolean\"): Schema<unknown, boolean> {\n return schema((value) => (typeof value === \"boolean\" ? success(value) : failure(message)));\n}\n\nexport function literal<const TValue extends string | number | boolean | null | undefined>(\n expected: TValue,\n message = `Expected ${String(expected)}`,\n): Schema<unknown, TValue> {\n return schema((value) => (Object.is(value, expected) ? success(expected) : failure(message)));\n}\n\nexport function picklist<const TValues extends readonly [unknown, ...unknown[]]>(\n values: TValues,\n message = `Expected one of ${values.map(String).join(\", \")}`,\n): Schema<unknown, TValues[number]> {\n return schema((value) =>\n values.some((item) => Object.is(item, value))\n ? success(value as TValues[number])\n : failure(message),\n );\n}\n\nexport function union<const TSchemas extends readonly [Schema, ...Schema[]]>(\n schemas: TSchemas,\n message = \"Expected a union match\",\n): Schema<unknown, SchemaOutput<TSchemas[number]>> {\n return schema((value) => {\n const issues: SchemaIssue[] = [];\n\n for (const itemSchema of schemas) {\n const result:\n | SchemaResult<SchemaOutput<TSchemas[number]>>\n | Promise<SchemaResult<SchemaOutput<TSchemas[number]>>> =\n itemSchema[\"~standard\"].validate(value);\n ensureSynchronous(result);\n if (!result.issues) {\n return success(result.value as SchemaOutput<TSchemas[number]>);\n }\n issues.push(...result.issues);\n }\n\n return issues.length > 0 ? failure(message) : failure(message);\n });\n}\n\nexport function array<TItem extends Schema = Schema<unknown>>(\n itemSchema?: TItem,\n message = \"Expected an array\",\n): Schema<unknown, SchemaOutput<TItem>[]> {\n return schema((value) => {\n if (!Array.isArray(value)) {\n return failure(message);\n }\n\n if (itemSchema === undefined) {\n return success(value as SchemaOutput<TItem>[]);\n }\n\n const output: SchemaOutput<TItem>[] = [];\n const issues: SchemaIssue[] = [];\n for (let index = 0; index < value.length; index++) {\n const result: SchemaResult<SchemaOutput<TItem>> | Promise<SchemaResult<SchemaOutput<TItem>>> =\n itemSchema[\"~standard\"].validate(value[index]);\n ensureSynchronous(result);\n if (result.issues) {\n issues.push(...result.issues.map((issue: SchemaIssue) => withPath(index, issue)));\n } else {\n output.push(result.value as SchemaOutput<TItem>);\n }\n }\n\n return issues.length > 0 ? { issues } : success(output);\n });\n}\n\nexport function object<TShape extends SchemaShape>(\n shape: TShape,\n message = \"Expected an object\",\n): Schema<unknown, ObjectOutput<TShape>> {\n return schema((value) => {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n return failure(message);\n }\n\n const input = value as Record<string, unknown>;\n const output: Partial<ObjectOutput<TShape>> = {};\n const issues: SchemaIssue[] = [];\n\n for (const key of Object.keys(shape) as Array<keyof TShape & string>) {\n const result:\n | SchemaResult<SchemaOutput<TShape[typeof key]>>\n | Promise<SchemaResult<SchemaOutput<TShape[typeof key]>>> = shape[key][\n \"~standard\"\n ].validate(input[key]);\n ensureSynchronous(result);\n if (result.issues) {\n issues.push(...result.issues.map((issue: SchemaIssue) => withPath(key, issue)));\n } else {\n output[key] = result.value as ObjectOutput<TShape>[typeof key];\n }\n }\n\n return issues.length > 0 ? { issues } : success(output as ObjectOutput<TShape>);\n });\n}\n\nexport function record<TValue extends Schema>(\n valueSchema: TValue,\n message = \"Expected an object\",\n): Schema<unknown, Record<string, SchemaOutput<TValue>>> {\n return schema((value) => {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n return failure(message);\n }\n\n const output: Record<string, SchemaOutput<TValue>> = {};\n const issues: SchemaIssue[] = [];\n for (const [key, item] of Object.entries(value)) {\n const result:\n | SchemaResult<SchemaOutput<TValue>>\n | Promise<SchemaResult<SchemaOutput<TValue>>> = valueSchema[\"~standard\"].validate(item);\n ensureSynchronous(result);\n if (result.issues) {\n issues.push(...result.issues.map((issue: SchemaIssue) => withPath(key, issue)));\n } else {\n output[key] = result.value as SchemaOutput<TValue>;\n }\n }\n\n return issues.length > 0 ? { issues } : success(output);\n });\n}\n\nexport function optional<TSchema extends Schema>(\n inner: TSchema,\n): Schema<unknown, SchemaOutput<TSchema> | undefined> {\n return schema((value) => {\n if (value === undefined) {\n return success(undefined);\n }\n\n const result = inner[\"~standard\"].validate(value);\n ensureSynchronous(result);\n return result;\n });\n}\n\nexport function defaulted<TSchema extends Schema>(\n inner: TSchema,\n defaultValue: SchemaOutput<TSchema> | (() => SchemaOutput<TSchema>),\n): Schema<unknown, SchemaOutput<TSchema>> {\n return schema((value) => {\n if (value === undefined) {\n return success(\n typeof defaultValue === \"function\"\n ? (defaultValue as () => SchemaOutput<TSchema>)()\n : defaultValue,\n );\n }\n\n const result = inner[\"~standard\"].validate(value);\n ensureSynchronous(result);\n return result;\n });\n}\n\nfunction ensureSynchronous<T>(value: T | Promise<T>): asserts value is T {\n if (value instanceof Promise) {\n throw new Error(\"Async schema validation is not supported\");\n }\n}\n\nfunction withPath(key: PropertyKey, issue: SchemaIssue): SchemaIssue {\n return {\n ...issue,\n path: [key, ...(issue.path ?? [])],\n };\n}\n\nexport const ss = {\n schema,\n success,\n failure,\n StandardSchemaValidationError,\n validateStandardSchema,\n validateStandardSchemaSync,\n unknown,\n string,\n number,\n boolean,\n literal,\n picklist,\n union,\n array,\n object,\n record,\n optional,\n defaulted,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"mod.mjs","names":[],"sources":["../src/mod.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\nimport { isString, isNumber, isBoolean, isFunction, isObject } from \"@temelj/value\";\n\nexport type Schema<TInput = unknown, TOutput = TInput> = StandardSchemaV1<TInput, TOutput>;\n\nexport type SchemaInput<TSchema extends Schema> = StandardSchemaV1.InferInput<TSchema>;\n\nexport type SchemaOutput<TSchema extends Schema> = StandardSchemaV1.InferOutput<TSchema>;\n\nexport type SchemaResult<TOutput> = StandardSchemaV1.Result<TOutput>;\n\nexport type SchemaIssue = StandardSchemaV1.Issue;\n\n// oxlint-disable-next-line anti-slop/no-unknown-parameters -- Standard Schema validators receive untrusted input before validating it.\nexport type SchemaValidator<TOutput> = (value: unknown) => SchemaResult<TOutput>;\n\nexport type SchemaFields = Record<string, Schema>;\n\nexport type ObjectOutput<TFields extends SchemaFields> = {\n readonly [TKey in keyof TFields]: SchemaOutput<TFields[TKey]>;\n};\n\nexport type ObjectInput<TFields extends SchemaFields> = {\n readonly [TKey in keyof TFields]: SchemaInput<TFields[TKey]>;\n};\n\nexport type SafeParseResult<T> =\n | { readonly success: true; readonly value: T }\n | { readonly success: false; readonly issues: ReadonlyArray<SchemaIssue> };\n\nexport interface ObjectOptions {\n readonly unknownKeys?: \"strip\" | \"passthrough\" | \"strict\";\n}\n\ninterface Constructor<T> extends Function {\n readonly prototype: T;\n readonly name: string;\n}\n\nexport function schema<TInput, TOutput>(\n validate: SchemaValidator<TOutput>,\n): Schema<TInput, TOutput> {\n return {\n \"~standard\": {\n version: 1,\n vendor: \"@temelj/standard-schema\",\n validate,\n },\n };\n}\n\nexport function success<T>(value: T): StandardSchemaV1.SuccessResult<T> {\n return { value };\n}\n\nexport function failure(\n message: string,\n path?: ReadonlyArray<PropertyKey>,\n): StandardSchemaV1.FailureResult {\n return {\n issues: [\n {\n message,\n path,\n },\n ],\n };\n}\n\nexport class StandardSchemaValidationError extends Error {\n public readonly issues: ReadonlyArray<SchemaIssue>;\n\n constructor(message: string, issues: ReadonlyArray<SchemaIssue>, context?: Function) {\n super(message);\n this.name = \"StandardSchemaValidationError\";\n this.issues = issues;\n\n if (Error.captureStackTrace !== undefined) {\n Error.captureStackTrace(this, context ?? this.constructor);\n }\n }\n\n static failed(this: void, message: string, issues: ReadonlyArray<SchemaIssue>): never {\n throw new StandardSchemaValidationError(message, issues, StandardSchemaValidationError.failed);\n }\n}\n\nexport class StandardSchemaAsyncValidationError extends Error {\n constructor(message: string, context?: Function) {\n super(message);\n this.name = \"StandardSchemaAsyncValidationError\";\n\n if (Error.captureStackTrace !== undefined) {\n Error.captureStackTrace(this, context ?? this.constructor);\n }\n }\n\n static unsupported(this: void): never {\n throw new StandardSchemaAsyncValidationError(\n \"Async schema validation is not supported\",\n StandardSchemaAsyncValidationError.unsupported,\n );\n }\n}\n\nexport async function validateStandardSchema<TSchema extends Schema>(\n inputSchema: TSchema,\n // oxlint-disable-next-line anti-slop/no-unknown-parameters -- Schema validation is the boundary that converts untrusted input to its declared output.\n value: unknown,\n message: string = \"Schema validation failed\",\n): Promise<SchemaOutput<TSchema>> {\n const result = await inputSchema[\"~standard\"].validate(value);\n\n if (!result.issues) {\n // SAFETY: this success result was returned by the supplied TSchema validator.\n return result.value as SchemaOutput<TSchema>;\n }\n\n StandardSchemaValidationError.failed(message, result.issues);\n}\n\nexport function validateStandardSchemaSync<TSchema extends Schema>(\n inputSchema: TSchema,\n // oxlint-disable-next-line anti-slop/no-unknown-parameters -- Schema validation is the boundary that converts untrusted input to its declared output.\n value: unknown,\n message: string = \"Schema validation failed\",\n): SchemaOutput<TSchema> {\n const result = evaluate(inputSchema, value);\n\n if (!result.issues) {\n return result.value;\n }\n\n StandardSchemaValidationError.failed(message, result.issues);\n}\n\nexport async function safeParse<TSchema extends Schema>(\n inputSchema: TSchema,\n value: SchemaInput<TSchema>,\n): Promise<SafeParseResult<SchemaOutput<TSchema>>> {\n const result = await inputSchema[\"~standard\"].validate(value);\n\n // SAFETY: the success value was returned by the supplied TSchema validator.\n return result.issues\n ? { success: false, issues: result.issues }\n : { success: true, value: result.value as SchemaOutput<TSchema> };\n}\n\nexport function safeParseSync<TSchema extends Schema>(\n inputSchema: TSchema,\n value: SchemaInput<TSchema>,\n): SafeParseResult<SchemaOutput<TSchema>> {\n const result = evaluate(inputSchema, value);\n\n return result.issues\n ? { success: false, issues: result.issues }\n : { success: true, value: result.value };\n}\n\nexport async function parse<TSchema extends Schema>(\n inputSchema: TSchema,\n value: SchemaInput<TSchema>,\n message?: string,\n): Promise<SchemaOutput<TSchema>> {\n return await validateStandardSchema(inputSchema, value, message);\n}\n\nexport function parseSync<TSchema extends Schema>(\n inputSchema: TSchema,\n value: SchemaInput<TSchema>,\n message?: string,\n): SchemaOutput<TSchema> {\n return validateStandardSchemaSync(inputSchema, value, message);\n}\n\nexport function unknown(): Schema<unknown> {\n return schema((value) => success(value));\n}\n\nexport function string(message: string = \"Expected a string\"): Schema<unknown, string> {\n return schema((value) => (isString(value) ? success(value) : failure(message)));\n}\n\nexport function number(message: string = \"Expected a number\"): Schema<unknown, number> {\n return schema((value) => (isNumber(value) ? success(value) : failure(message)));\n}\n\nexport function finite(message: string = \"Expected a finite number\"): Schema<unknown, number> {\n return refine(number(), Number.isFinite, message);\n}\n\nexport function integer(message: string = \"Expected an integer\"): Schema<unknown, number> {\n return refine(number(), Number.isInteger, message);\n}\n\nexport function safeInteger(message: string = \"Expected a safe integer\"): Schema<unknown, number> {\n return refine(number(), Number.isSafeInteger, message);\n}\n\nexport function positiveNumber(\n message: string = \"Expected a positive number\",\n): Schema<unknown, number> {\n return refine(number(), (value) => Number.isFinite(value) && value > 0, message);\n}\n\nexport function nonNegativeNumber(\n message: string = \"Expected a non-negative number\",\n): Schema<unknown, number> {\n return refine(number(), (value) => Number.isFinite(value) && value >= 0, message);\n}\n\nexport function positiveSafeInteger(\n message: string = \"Expected a positive safe integer\",\n): Schema<unknown, number> {\n return refine(number(), (value) => Number.isSafeInteger(value) && value > 0, message);\n}\n\nexport function nonNegativeSafeInteger(\n message: string = \"Expected a non-negative safe integer\",\n): Schema<unknown, number> {\n return refine(number(), (value) => Number.isSafeInteger(value) && value >= 0, message);\n}\n\nexport function min(\n inner: Schema<unknown, number>,\n minimum: number,\n message: string = `Expected a number greater than or equal to ${minimum}`,\n): Schema<unknown, number> {\n return refine(inner, (value) => value >= minimum, message);\n}\n\nexport function max(\n inner: Schema<unknown, number>,\n maximum: number,\n message: string = `Expected a number less than or equal to ${maximum}`,\n): Schema<unknown, number> {\n return refine(inner, (value) => value <= maximum, message);\n}\n\nexport function nonEmptyString(\n message: string = \"Expected a non-empty string\",\n): Schema<unknown, string> {\n return refine(string(), (value) => value.length > 0, message);\n}\n\nexport function nonBlankString(\n message: string = \"Expected a non-blank string\",\n): Schema<unknown, string> {\n return refine(string(), (value) => value.trim().length > 0, message);\n}\n\nexport function boolean(message: string = \"Expected a boolean\"): Schema<unknown, boolean> {\n return schema((value) => (isBoolean(value) ? success(value) : failure(message)));\n}\n\nexport function fn(message: string = \"Expected a function\"): Schema<unknown, Function> {\n return schema((value) => (isFunction(value) ? success(value) : failure(message)));\n}\n\nexport function instanceOf<T>(\n constructor: Constructor<T>,\n message: string = `Expected ${constructor.name}`,\n): Schema<unknown, T> {\n return schema((value) => (value instanceof constructor ? success(value) : failure(message)));\n}\n\nexport function literal<const TValue extends string | number | boolean | null | undefined>(\n expected: TValue,\n message: string = `Expected ${String(expected)}`,\n): Schema<unknown, TValue> {\n return schema((value) => (Object.is(value, expected) ? success(expected) : failure(message)));\n}\n\nexport function picklist<const TValues extends readonly [unknown, ...unknown[]]>(\n values: TValues,\n message: string = `Expected one of ${values.map(String).join(\", \")}`,\n): Schema<unknown, TValues[number]> {\n return schema((value) => {\n const match = values.findIndex((item) => Object.is(item, value));\n\n return match === -1 ? failure(message) : success(values[match]);\n });\n}\n\nexport function union<const TSchemas extends readonly [Schema, ...Schema[]]>(\n schemas: TSchemas,\n message: string = \"Expected a union match\",\n): Schema<unknown, SchemaOutput<TSchemas[number]>> {\n return schema((value) => {\n for (const itemSchema of schemas) {\n const result = evaluate<TSchemas[number]>(itemSchema, value);\n\n if (!result.issues) {\n return success(result.value);\n }\n }\n\n return failure(message);\n });\n}\n\nexport function array(): Schema<unknown, unknown[]>;\nexport function array<TItem extends Schema>(\n itemSchema: TItem,\n message?: string,\n): Schema<unknown, SchemaOutput<TItem>[]>;\nexport function array<TItem extends Schema>(\n itemSchema?: TItem,\n message: string = \"Expected an array\",\n): Schema<unknown, unknown[]> {\n return schema((value) => {\n if (!Array.isArray(value)) {\n return failure(message);\n }\n\n if (itemSchema === undefined) {\n return success(value);\n }\n\n const output: SchemaOutput<TItem>[] = [];\n const issues: SchemaIssue[] = [];\n\n for (let index = 0; index < value.length; index++) {\n const result: SchemaResult<SchemaOutput<TItem>> = evaluate(itemSchema, value[index]);\n\n if (result.issues) {\n issues.push(...result.issues.map((issue: SchemaIssue) => withPath(index, issue)));\n } else {\n output.push(result.value);\n }\n }\n\n return issues.length > 0 ? { issues } : success(output);\n });\n}\n\nexport function object<TFields extends SchemaFields>(\n fields: TFields,\n message: string = \"Expected an object\",\n options: ObjectOptions = {},\n): Schema<unknown, ObjectOutput<TFields>> {\n return schema((value) => {\n if (!isObject(value) || Array.isArray(value)) {\n return failure(message);\n }\n\n // SAFETY: the object check above establishes key lookup; each field remains unknown until its schema validates it.\n // oxlint-disable-next-line anti-slop/no-unsafe-dictionary-type -- Temporary untrusted object at the schema parsing boundary.\n const input = value as Record<PropertyKey, unknown>;\n\n const output: Partial<{ -readonly [K in keyof TFields]: SchemaOutput<TFields[K]> }> = {};\n\n if (options.unknownKeys === \"passthrough\") {\n for (const key of Reflect.ownKeys(input)) {\n if (!Object.prototype.propertyIsEnumerable.call(input, key)) {\n continue;\n }\n\n Object.defineProperty(output, key, {\n value: input[key],\n enumerable: true,\n writable: true,\n configurable: true,\n });\n }\n }\n\n const issues: SchemaIssue[] = [];\n const fieldKeys = Object.keys(fields);\n\n if (options.unknownKeys === \"strict\") {\n for (const key of Object.keys(input)) {\n if (!fieldKeys.includes(key)) {\n issues.push({ message: \"Unexpected key\", path: [key] });\n }\n }\n }\n\n // SAFETY: these are the enumerable keys of the supplied field schema object.\n for (const key of fieldKeys as Array<keyof TFields & string>) {\n const hasOwnField = Object.prototype.hasOwnProperty.call(input, key);\n const result = evaluate(fields[key], hasOwnField ? input[key] : undefined);\n\n if (result.issues) {\n issues.push(...result.issues.map((issue: SchemaIssue) => withPath(key, issue)));\n } else if (hasOwnField || result.value !== undefined) {\n Object.defineProperty(output, key, {\n value: result.value,\n enumerable: true,\n writable: true,\n configurable: true,\n });\n }\n }\n\n // SAFETY: all schema fields have succeeded; absent optional fields are represented by undefined in ObjectOutput.\n return issues.length > 0 ? { issues } : success(output as ObjectOutput<TFields>);\n });\n}\n\nexport function strictObject<TFields extends SchemaFields>(\n fields: TFields,\n message: string = \"Expected an object\",\n): Schema<unknown, ObjectOutput<TFields>> {\n return object(fields, message, { unknownKeys: \"strict\" });\n}\n\nexport function looseObject<TFields extends SchemaFields>(\n fields: TFields,\n message: string = \"Expected an object\",\n): Schema<unknown, ObjectOutput<TFields>> {\n return object(fields, message, { unknownKeys: \"passthrough\" });\n}\n\nexport function record<TValue extends Schema>(\n valueSchema: TValue,\n message: string = \"Expected an object\",\n): Schema<unknown, Record<string, SchemaOutput<TValue>>> {\n return schema((value) => {\n if (!isObject(value) || Array.isArray(value)) {\n return failure(message);\n }\n\n const output: Record<string, SchemaOutput<TValue>> = {};\n const issues: SchemaIssue[] = [];\n\n for (const [key, item] of Object.entries(value)) {\n const result = evaluate(valueSchema, item);\n\n if (result.issues) {\n issues.push(...result.issues.map((issue: SchemaIssue) => withPath(key, issue)));\n } else {\n output[key] = result.value;\n }\n }\n\n return issues.length > 0 ? { issues } : success(output);\n });\n}\n\nexport function optional<TSchema extends Schema>(\n inner: TSchema,\n): Schema<unknown, SchemaOutput<TSchema> | undefined> {\n return schema((value) => {\n if (value === undefined) {\n return success(undefined);\n }\n\n const result = evaluate(inner, value);\n\n return result;\n });\n}\n\nexport function defaulted<TSchema extends Schema>(\n inner: TSchema,\n defaultValue: SchemaOutput<TSchema>,\n): Schema<unknown, SchemaOutput<TSchema>> {\n return schema((value) => {\n if (value === undefined) {\n return success(defaultValue);\n }\n\n const result = evaluate(inner, value);\n\n return result;\n });\n}\n\nexport function defaultedWith<TSchema extends Schema>(\n inner: TSchema,\n createDefault: () => SchemaOutput<TSchema>,\n): Schema<unknown, SchemaOutput<TSchema>> {\n return schema((value) =>\n value === undefined ? success(createDefault()) : evaluate(inner, value),\n );\n}\n\nexport function refine<TSchema extends Schema, TOutput extends SchemaOutput<TSchema>>(\n inner: TSchema,\n predicate: (value: SchemaOutput<TSchema>) => value is TOutput,\n message?: string,\n): Schema<SchemaInput<TSchema>, TOutput>;\nexport function refine<TSchema extends Schema>(\n inner: TSchema,\n predicate: (value: SchemaOutput<TSchema>) => boolean,\n message?: string,\n): Schema<SchemaInput<TSchema>, SchemaOutput<TSchema>>;\nexport function refine<TSchema extends Schema>(\n inner: TSchema,\n predicate: (value: SchemaOutput<TSchema>) => boolean,\n message: string = \"Invalid value\",\n): Schema<SchemaInput<TSchema>, SchemaOutput<TSchema>> {\n return schema((value) => {\n const result = evaluate(inner, value);\n\n if (result.issues) {\n return result;\n }\n\n return predicate(result.value) ? result : failure(message);\n });\n}\n\nexport function transform<TSchema extends Schema, TOutput>(\n inner: TSchema,\n mapper: (value: SchemaOutput<TSchema>) => TOutput,\n): Schema<SchemaInput<TSchema>, TOutput> {\n return schema((value) => {\n const result = evaluate(inner, value);\n\n if (result.issues) {\n return result;\n }\n\n return success(mapper(result.value));\n });\n}\n\nexport function pipe<TLeft extends Schema, TRight extends Schema>(\n left: TLeft,\n right: TRight,\n): Schema<SchemaInput<TLeft>, SchemaOutput<TRight>> {\n return schema((value) => {\n const leftResult = evaluate(left, value);\n\n if (leftResult.issues) {\n return leftResult;\n }\n\n const rightResult = evaluate(right, leftResult.value);\n\n return rightResult;\n });\n}\n\nexport function extend<TBase extends SchemaFields, TExtension extends SchemaFields>(\n base: TBase,\n extension: TExtension,\n): Omit<TBase, keyof TExtension> & TExtension {\n return { ...base, ...extension };\n}\n\nexport function pick<TFields extends SchemaFields, const TKeys extends readonly (keyof TFields)[]>(\n fields: TFields,\n keys: TKeys,\n): Pick<TFields, TKeys[number]> {\n // SAFETY: each requested key is constrained to TFields and is copied with its corresponding schema.\n return Object.fromEntries(keys.map((key) => [key, fields[key]])) as Pick<TFields, TKeys[number]>;\n}\n\nexport function omit<TFields extends SchemaFields, const TKeys extends readonly (keyof TFields)[]>(\n fields: TFields,\n keys: TKeys,\n): Omit<TFields, TKeys[number]> {\n const result = { ...fields };\n\n for (const key of keys) {\n delete result[key];\n }\n\n return result;\n}\n\nexport function partial<TFields extends SchemaFields>(\n fields: TFields,\n): { readonly [TKey in keyof TFields]: Schema<unknown, SchemaOutput<TFields[TKey]> | undefined> } {\n const entries = Reflect.ownKeys(fields).map((key) => {\n // SAFETY: key is an own key of the supplied field schema object.\n return [key, optional(fields[key as keyof TFields])];\n });\n\n // SAFETY: each own field is preserved under its key and optional retains its output type while adding undefined.\n return Object.fromEntries(entries) as {\n readonly [TKey in keyof TFields]: Schema<unknown, SchemaOutput<TFields[TKey]> | undefined>;\n };\n}\n\nfunction evaluate<TSchema extends Schema>(\n inputSchema: TSchema,\n // oxlint-disable-next-line anti-slop/no-unknown-parameters -- This helper invokes the schema validator on untrusted input.\n value: unknown,\n): SchemaResult<SchemaOutput<TSchema>> {\n const result = inputSchema[\"~standard\"].validate(value);\n ensureSynchronous(result);\n\n // SAFETY: StandardSchemaV1 ties the validator success type to TSchema's declared output.\n return result as SchemaResult<SchemaOutput<TSchema>>;\n}\n\nfunction ensureSynchronous<T>(value: T | Promise<T>): asserts value is T {\n if (value instanceof Promise) {\n StandardSchemaAsyncValidationError.unsupported();\n }\n}\n\nfunction withPath(key: PropertyKey, issue: SchemaIssue): SchemaIssue {\n return {\n ...issue,\n path: [key, ...(issue.path ?? [])],\n };\n}\n\nexport const ss = {\n schema,\n success,\n failure,\n StandardSchemaValidationError,\n validateStandardSchema,\n validateStandardSchemaSync,\n safeParse,\n safeParseSync,\n parse,\n parseSync,\n unknown,\n string,\n number,\n finite,\n integer,\n safeInteger,\n positiveNumber,\n nonNegativeNumber,\n positiveSafeInteger,\n nonNegativeSafeInteger,\n min,\n max,\n nonEmptyString,\n nonBlankString,\n boolean,\n fn,\n instanceOf,\n literal,\n picklist,\n union,\n array,\n object,\n strictObject,\n looseObject,\n record,\n optional,\n defaulted,\n defaultedWith,\n refine,\n transform,\n pipe,\n extend,\n pick,\n omit,\n partial,\n};\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@temelj/standard-schema",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Standard Schema construction utilities.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -19,14 +19,15 @@
19
19
  }
20
20
  },
21
21
  "dependencies": {
22
- "@standard-schema/spec": "^1.1.0"
22
+ "@standard-schema/spec": "^1.1.0",
23
+ "@temelj/value": "0.15.0"
23
24
  },
24
25
  "devDependencies": {
25
- "@types/node": "25.9.2",
26
+ "@types/node": "26.6.5",
26
27
  "shx": "^0.4.0",
27
- "tsdown": "^0.22.2",
28
- "typescript": "^6.0.3",
29
- "vitest": "^4.1.8"
28
+ "tsdown": "^0.23.1",
29
+ "typescript": "^7.0.2",
30
+ "vitest": "^5.0.4"
30
31
  },
31
32
  "scripts": {
32
33
  "build": "tsdown",