@lunora/values 1.0.0-alpha.12 → 1.0.0-alpha.14
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/dist/index.d.mts
CHANGED
|
@@ -96,7 +96,15 @@ interface Validator<T = unknown> extends StandardSchemaV1<T, T> {
|
|
|
96
96
|
*
|
|
97
97
|
* Works in any context — argument validators, column validators, or
|
|
98
98
|
* standalone — so it can encode invariants like
|
|
99
|
-
* `v.number().check(n => n >= 0)
|
|
99
|
+
* `v.number().check(n => n >= 0)`.
|
|
100
|
+
*
|
|
101
|
+
* For the common length/format/range cases, prefer the named shortcuts
|
|
102
|
+
* (`v.string().min(1)`, `.max(n)`, `.length(n)`, `.pattern(re)`, `.email()`,
|
|
103
|
+
* `.url()`; `v.number().min(n)`, `.max(n)`, `.int()`, `.positive()`;
|
|
104
|
+
* `v.array(...).min(n)`, `.max(n)`) — each is sugar over this same
|
|
105
|
+
* `.check(predicate, { schema })` path, so the predicate and the JSON Schema
|
|
106
|
+
* keyword are set together and can never drift apart. `.check()` remains the
|
|
107
|
+
* escape hatch for anything the shortcuts don't cover, e.g.
|
|
100
108
|
* `v.string().check(s => s.length > 0, { message: "non-empty", schema: { minLength: 1 } })`.
|
|
101
109
|
*/
|
|
102
110
|
check: (predicate: (value: T) => boolean, options?: CheckOptions | string) => Validator<T>;
|
|
@@ -211,6 +219,67 @@ interface TimestampColumnValidator extends ColumnValidator<number, number> {
|
|
|
211
219
|
/** Default to the current epoch-ms (`Date.now()`) at insert time; field becomes optional on insert. */
|
|
212
220
|
defaultNow: () => ColumnValidator<number, number | undefined>;
|
|
213
221
|
}
|
|
222
|
+
/**
|
|
223
|
+
* A {@link ColumnValidator} for `v.string()` with ergonomic refinement
|
|
224
|
+
* shortcuts. Each method is sugar over `.check(predicate, { schema })` — it
|
|
225
|
+
* sets the runtime predicate AND the matching JSON Schema keyword in one call
|
|
226
|
+
* so the two can never drift (see the module-level `.check()` docstring for
|
|
227
|
+
* the underlying two-part mechanism). Chainable among each other; `.check()`/
|
|
228
|
+
* `.meta()` compose after them but the return narrows to the base
|
|
229
|
+
* {@link ColumnValidator} (no further refinement shortcuts after that point).
|
|
230
|
+
*/
|
|
231
|
+
interface StringColumnValidator extends ColumnValidator<string, string> {
|
|
232
|
+
/** Require a valid email address (`format: "email"`). Uses a pragmatic (non-RFC-5322-exhaustive) pattern. */
|
|
233
|
+
email: () => StringColumnValidator;
|
|
234
|
+
/** Require exactly `length` characters (`minLength`/`maxLength` both set to `length`). */
|
|
235
|
+
length: (length: number) => StringColumnValidator;
|
|
236
|
+
/** Require at most `max` characters (`maxLength`). */
|
|
237
|
+
max: (max: number) => StringColumnValidator;
|
|
238
|
+
/** Require at least `min` characters (`minLength`). */
|
|
239
|
+
min: (min: number) => StringColumnValidator;
|
|
240
|
+
/**
|
|
241
|
+
* Require the value to match `pattern` (JSON Schema `pattern` set from
|
|
242
|
+
* `pattern.source`; emitted `pattern` does not encode `pattern.flags` — a
|
|
243
|
+
* case-insensitive `/i` regex, for instance, emits a flag-less JSON Schema
|
|
244
|
+
* pattern). A `g`/`y`-flagged `pattern` is tested statelessly (its
|
|
245
|
+
* `lastIndex` is never consulted or advanced), so a single validator
|
|
246
|
+
* instance gives the same answer for the same input on every call.
|
|
247
|
+
*/
|
|
248
|
+
pattern: (pattern: RegExp) => StringColumnValidator;
|
|
249
|
+
/**
|
|
250
|
+
* Require a valid `http:`/`https:` URL (`format: "uri"`). Parseable by the
|
|
251
|
+
* WHATWG `URL` constructor is necessary but not sufficient — schemes such as
|
|
252
|
+
* `javascript:`, `data:`, `file:`, and `vbscript:` all parse successfully but
|
|
253
|
+
* are rejected here, since accepting them lets a validated "link" field carry
|
|
254
|
+
* an XSS payload straight into an anchor's `href` or `window.location` at
|
|
255
|
+
* render time.
|
|
256
|
+
*/
|
|
257
|
+
url: () => StringColumnValidator;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* A {@link ColumnValidator} for `v.number()` with ergonomic refinement
|
|
261
|
+
* shortcuts — see {@link StringColumnValidator} for the delegation pattern.
|
|
262
|
+
*/
|
|
263
|
+
interface NumberColumnValidator extends ColumnValidator<number, number> {
|
|
264
|
+
/** Require an integer value (`Number.isInteger`); JSON Schema `type` narrows to `"integer"`. */
|
|
265
|
+
int: () => NumberColumnValidator;
|
|
266
|
+
/** Require at most `max` (`maximum`). */
|
|
267
|
+
max: (max: number) => NumberColumnValidator;
|
|
268
|
+
/** Require at least `min` (`minimum`). */
|
|
269
|
+
min: (min: number) => NumberColumnValidator;
|
|
270
|
+
/** Require a value strictly greater than zero (`exclusiveMinimum: 0`). */
|
|
271
|
+
positive: () => NumberColumnValidator;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* A {@link ColumnValidator} for `v.array(...)` with ergonomic length-refinement
|
|
275
|
+
* shortcuts — see {@link StringColumnValidator} for the delegation pattern.
|
|
276
|
+
*/
|
|
277
|
+
interface ArrayColumnValidator<TItem> extends ColumnValidator<TItem[], TItem[]> {
|
|
278
|
+
/** Require at most `max` items (`maxItems`). */
|
|
279
|
+
max: (max: number) => ArrayColumnValidator<TItem>;
|
|
280
|
+
/** Require at least `min` items (`minItems`). */
|
|
281
|
+
min: (min: number) => ArrayColumnValidator<TItem>;
|
|
282
|
+
}
|
|
214
283
|
/** The type a validator/column presents on **select** (reads). */
|
|
215
284
|
type InferSelect<V> = V extends Validator<infer T> ? T : never;
|
|
216
285
|
/** The type a validator/column accepts on **insert** (writes). */
|
|
@@ -223,8 +292,8 @@ type SelectShape<S extends Record<string, Validator>> = { [K in keyof S]: InferS
|
|
|
223
292
|
* become optional keys.
|
|
224
293
|
*/
|
|
225
294
|
type InsertShape<S extends Record<string, Validator>> = { [K in keyof S as undefined extends InferInsert<S[K]> ? K : never]?: Exclude<InferInsert<S[K]>, undefined>; } & { [K in keyof S as undefined extends InferInsert<S[K]> ? never : K]: InferInsert<S[K]>; };
|
|
226
|
-
declare const string: () =>
|
|
227
|
-
declare const number: () =>
|
|
295
|
+
declare const string: () => StringColumnValidator;
|
|
296
|
+
declare const number: () => NumberColumnValidator;
|
|
228
297
|
/** Epoch-millisecond timestamp (`number`). Pair with `.defaultNow()` for an insert-time clock. */
|
|
229
298
|
declare const timestamp: () => TimestampColumnValidator;
|
|
230
299
|
/** Calendar date stored as an epoch-millisecond `number`. Pair with `.defaultNow()` for an insert-time clock. */
|
|
@@ -265,7 +334,7 @@ interface GeoPoint {
|
|
|
265
334
|
*/
|
|
266
335
|
declare const geoPoint: () => ColumnValidator<GeoPoint, GeoPoint>;
|
|
267
336
|
declare const literal: <T extends bigint | boolean | number | string | null>(literalValue: T) => ColumnValidator<T, T>;
|
|
268
|
-
declare const array: <V extends Validator>(inner: V) =>
|
|
337
|
+
declare const array: <V extends Validator>(inner: V) => ArrayColumnValidator<Infer<V>>;
|
|
269
338
|
/**
|
|
270
339
|
* Split a value-type map into optional + required keys: any member whose value
|
|
271
340
|
* type includes `undefined` becomes an optional key. The single optionality rule
|
|
@@ -505,4 +574,4 @@ declare const installCompiledValidatorMap: (validators: object, compiled: Compil
|
|
|
505
574
|
* which case the interpreted loop below runs and owns the result (and any error).
|
|
506
575
|
*/
|
|
507
576
|
declare const parseValidatorMap: (validators: ValidatorMap, source: Record<string, unknown>, label: string) => Record<string, unknown>;
|
|
508
|
-
export { type CheckOptions, type Column, type ColumnMeta, type ColumnValidator, type CompiledValidatorMap, DEFER_VALIDATION, type GeoPoint, type Id, type Infer, type InferInsert, type InferSelect, type InferStandardOutput, type InferValidatorMap, type InsertShape, type JsonSchema, type JsonSchemaFragment, type MetaOptions, type SchemaNodeReader, type SelectShape, type ServerDefaultContext, type TimestampColumnValidator, ValidationError, type ValidationPath, type Validator, type ValidatorKind, type ValidatorMap, argsToJsonSchema, describeValue, formatPath, installCompiledValidatorMap, isOrWrapsFromValidator, jsonSchemaFromNode, objectSchemaFromNodes, optionalInner, parseValidatorMap, toJsonSchema, v };
|
|
577
|
+
export { type ArrayColumnValidator, type CheckOptions, type Column, type ColumnMeta, type ColumnValidator, type CompiledValidatorMap, DEFER_VALIDATION, type GeoPoint, type Id, type Infer, type InferInsert, type InferSelect, type InferStandardOutput, type InferValidatorMap, type InsertShape, type JsonSchema, type JsonSchemaFragment, type MetaOptions, type NumberColumnValidator, type SchemaNodeReader, type SelectShape, type ServerDefaultContext, type StringColumnValidator, type TimestampColumnValidator, ValidationError, type ValidationPath, type Validator, type ValidatorKind, type ValidatorMap, argsToJsonSchema, describeValue, formatPath, installCompiledValidatorMap, isOrWrapsFromValidator, jsonSchemaFromNode, objectSchemaFromNodes, optionalInner, parseValidatorMap, toJsonSchema, v };
|
package/dist/index.d.ts
CHANGED
|
@@ -96,7 +96,15 @@ interface Validator<T = unknown> extends StandardSchemaV1<T, T> {
|
|
|
96
96
|
*
|
|
97
97
|
* Works in any context — argument validators, column validators, or
|
|
98
98
|
* standalone — so it can encode invariants like
|
|
99
|
-
* `v.number().check(n => n >= 0)
|
|
99
|
+
* `v.number().check(n => n >= 0)`.
|
|
100
|
+
*
|
|
101
|
+
* For the common length/format/range cases, prefer the named shortcuts
|
|
102
|
+
* (`v.string().min(1)`, `.max(n)`, `.length(n)`, `.pattern(re)`, `.email()`,
|
|
103
|
+
* `.url()`; `v.number().min(n)`, `.max(n)`, `.int()`, `.positive()`;
|
|
104
|
+
* `v.array(...).min(n)`, `.max(n)`) — each is sugar over this same
|
|
105
|
+
* `.check(predicate, { schema })` path, so the predicate and the JSON Schema
|
|
106
|
+
* keyword are set together and can never drift apart. `.check()` remains the
|
|
107
|
+
* escape hatch for anything the shortcuts don't cover, e.g.
|
|
100
108
|
* `v.string().check(s => s.length > 0, { message: "non-empty", schema: { minLength: 1 } })`.
|
|
101
109
|
*/
|
|
102
110
|
check: (predicate: (value: T) => boolean, options?: CheckOptions | string) => Validator<T>;
|
|
@@ -211,6 +219,67 @@ interface TimestampColumnValidator extends ColumnValidator<number, number> {
|
|
|
211
219
|
/** Default to the current epoch-ms (`Date.now()`) at insert time; field becomes optional on insert. */
|
|
212
220
|
defaultNow: () => ColumnValidator<number, number | undefined>;
|
|
213
221
|
}
|
|
222
|
+
/**
|
|
223
|
+
* A {@link ColumnValidator} for `v.string()` with ergonomic refinement
|
|
224
|
+
* shortcuts. Each method is sugar over `.check(predicate, { schema })` — it
|
|
225
|
+
* sets the runtime predicate AND the matching JSON Schema keyword in one call
|
|
226
|
+
* so the two can never drift (see the module-level `.check()` docstring for
|
|
227
|
+
* the underlying two-part mechanism). Chainable among each other; `.check()`/
|
|
228
|
+
* `.meta()` compose after them but the return narrows to the base
|
|
229
|
+
* {@link ColumnValidator} (no further refinement shortcuts after that point).
|
|
230
|
+
*/
|
|
231
|
+
interface StringColumnValidator extends ColumnValidator<string, string> {
|
|
232
|
+
/** Require a valid email address (`format: "email"`). Uses a pragmatic (non-RFC-5322-exhaustive) pattern. */
|
|
233
|
+
email: () => StringColumnValidator;
|
|
234
|
+
/** Require exactly `length` characters (`minLength`/`maxLength` both set to `length`). */
|
|
235
|
+
length: (length: number) => StringColumnValidator;
|
|
236
|
+
/** Require at most `max` characters (`maxLength`). */
|
|
237
|
+
max: (max: number) => StringColumnValidator;
|
|
238
|
+
/** Require at least `min` characters (`minLength`). */
|
|
239
|
+
min: (min: number) => StringColumnValidator;
|
|
240
|
+
/**
|
|
241
|
+
* Require the value to match `pattern` (JSON Schema `pattern` set from
|
|
242
|
+
* `pattern.source`; emitted `pattern` does not encode `pattern.flags` — a
|
|
243
|
+
* case-insensitive `/i` regex, for instance, emits a flag-less JSON Schema
|
|
244
|
+
* pattern). A `g`/`y`-flagged `pattern` is tested statelessly (its
|
|
245
|
+
* `lastIndex` is never consulted or advanced), so a single validator
|
|
246
|
+
* instance gives the same answer for the same input on every call.
|
|
247
|
+
*/
|
|
248
|
+
pattern: (pattern: RegExp) => StringColumnValidator;
|
|
249
|
+
/**
|
|
250
|
+
* Require a valid `http:`/`https:` URL (`format: "uri"`). Parseable by the
|
|
251
|
+
* WHATWG `URL` constructor is necessary but not sufficient — schemes such as
|
|
252
|
+
* `javascript:`, `data:`, `file:`, and `vbscript:` all parse successfully but
|
|
253
|
+
* are rejected here, since accepting them lets a validated "link" field carry
|
|
254
|
+
* an XSS payload straight into an anchor's `href` or `window.location` at
|
|
255
|
+
* render time.
|
|
256
|
+
*/
|
|
257
|
+
url: () => StringColumnValidator;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* A {@link ColumnValidator} for `v.number()` with ergonomic refinement
|
|
261
|
+
* shortcuts — see {@link StringColumnValidator} for the delegation pattern.
|
|
262
|
+
*/
|
|
263
|
+
interface NumberColumnValidator extends ColumnValidator<number, number> {
|
|
264
|
+
/** Require an integer value (`Number.isInteger`); JSON Schema `type` narrows to `"integer"`. */
|
|
265
|
+
int: () => NumberColumnValidator;
|
|
266
|
+
/** Require at most `max` (`maximum`). */
|
|
267
|
+
max: (max: number) => NumberColumnValidator;
|
|
268
|
+
/** Require at least `min` (`minimum`). */
|
|
269
|
+
min: (min: number) => NumberColumnValidator;
|
|
270
|
+
/** Require a value strictly greater than zero (`exclusiveMinimum: 0`). */
|
|
271
|
+
positive: () => NumberColumnValidator;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* A {@link ColumnValidator} for `v.array(...)` with ergonomic length-refinement
|
|
275
|
+
* shortcuts — see {@link StringColumnValidator} for the delegation pattern.
|
|
276
|
+
*/
|
|
277
|
+
interface ArrayColumnValidator<TItem> extends ColumnValidator<TItem[], TItem[]> {
|
|
278
|
+
/** Require at most `max` items (`maxItems`). */
|
|
279
|
+
max: (max: number) => ArrayColumnValidator<TItem>;
|
|
280
|
+
/** Require at least `min` items (`minItems`). */
|
|
281
|
+
min: (min: number) => ArrayColumnValidator<TItem>;
|
|
282
|
+
}
|
|
214
283
|
/** The type a validator/column presents on **select** (reads). */
|
|
215
284
|
type InferSelect<V> = V extends Validator<infer T> ? T : never;
|
|
216
285
|
/** The type a validator/column accepts on **insert** (writes). */
|
|
@@ -223,8 +292,8 @@ type SelectShape<S extends Record<string, Validator>> = { [K in keyof S]: InferS
|
|
|
223
292
|
* become optional keys.
|
|
224
293
|
*/
|
|
225
294
|
type InsertShape<S extends Record<string, Validator>> = { [K in keyof S as undefined extends InferInsert<S[K]> ? K : never]?: Exclude<InferInsert<S[K]>, undefined>; } & { [K in keyof S as undefined extends InferInsert<S[K]> ? never : K]: InferInsert<S[K]>; };
|
|
226
|
-
declare const string: () =>
|
|
227
|
-
declare const number: () =>
|
|
295
|
+
declare const string: () => StringColumnValidator;
|
|
296
|
+
declare const number: () => NumberColumnValidator;
|
|
228
297
|
/** Epoch-millisecond timestamp (`number`). Pair with `.defaultNow()` for an insert-time clock. */
|
|
229
298
|
declare const timestamp: () => TimestampColumnValidator;
|
|
230
299
|
/** Calendar date stored as an epoch-millisecond `number`. Pair with `.defaultNow()` for an insert-time clock. */
|
|
@@ -265,7 +334,7 @@ interface GeoPoint {
|
|
|
265
334
|
*/
|
|
266
335
|
declare const geoPoint: () => ColumnValidator<GeoPoint, GeoPoint>;
|
|
267
336
|
declare const literal: <T extends bigint | boolean | number | string | null>(literalValue: T) => ColumnValidator<T, T>;
|
|
268
|
-
declare const array: <V extends Validator>(inner: V) =>
|
|
337
|
+
declare const array: <V extends Validator>(inner: V) => ArrayColumnValidator<Infer<V>>;
|
|
269
338
|
/**
|
|
270
339
|
* Split a value-type map into optional + required keys: any member whose value
|
|
271
340
|
* type includes `undefined` becomes an optional key. The single optionality rule
|
|
@@ -505,4 +574,4 @@ declare const installCompiledValidatorMap: (validators: object, compiled: Compil
|
|
|
505
574
|
* which case the interpreted loop below runs and owns the result (and any error).
|
|
506
575
|
*/
|
|
507
576
|
declare const parseValidatorMap: (validators: ValidatorMap, source: Record<string, unknown>, label: string) => Record<string, unknown>;
|
|
508
|
-
export { type CheckOptions, type Column, type ColumnMeta, type ColumnValidator, type CompiledValidatorMap, DEFER_VALIDATION, type GeoPoint, type Id, type Infer, type InferInsert, type InferSelect, type InferStandardOutput, type InferValidatorMap, type InsertShape, type JsonSchema, type JsonSchemaFragment, type MetaOptions, type SchemaNodeReader, type SelectShape, type ServerDefaultContext, type TimestampColumnValidator, ValidationError, type ValidationPath, type Validator, type ValidatorKind, type ValidatorMap, argsToJsonSchema, describeValue, formatPath, installCompiledValidatorMap, isOrWrapsFromValidator, jsonSchemaFromNode, objectSchemaFromNodes, optionalInner, parseValidatorMap, toJsonSchema, v };
|
|
577
|
+
export { type ArrayColumnValidator, type CheckOptions, type Column, type ColumnMeta, type ColumnValidator, type CompiledValidatorMap, DEFER_VALIDATION, type GeoPoint, type Id, type Infer, type InferInsert, type InferSelect, type InferStandardOutput, type InferValidatorMap, type InsertShape, type JsonSchema, type JsonSchemaFragment, type MetaOptions, type NumberColumnValidator, type SchemaNodeReader, type SelectShape, type ServerDefaultContext, type StringColumnValidator, type TimestampColumnValidator, ValidationError, type ValidationPath, type Validator, type ValidatorKind, type ValidatorMap, argsToJsonSchema, describeValue, formatPath, installCompiledValidatorMap, isOrWrapsFromValidator, jsonSchemaFromNode, objectSchemaFromNodes, optionalInner, parseValidatorMap, toJsonSchema, v };
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ValidationError as a,describeValue as e,formatPath as t}from"./packem_shared/ValidationError-5sbiLWie.mjs";import{jsonSchemaFromNode as p,objectSchemaFromNodes as i}from"./packem_shared/jsonSchemaFromNode-k28QmNzA.mjs";import{argsToJsonSchema as l,toJsonSchema as d}from"./packem_shared/argsToJsonSchema-C4oyUJUg.mjs";import{isOrWrapsFromValidator as c,optionalInner as f,v as V}from"./packem_shared/isOrWrapsFromValidator-
|
|
1
|
+
import{ValidationError as a,describeValue as e,formatPath as t}from"./packem_shared/ValidationError-5sbiLWie.mjs";import{jsonSchemaFromNode as p,objectSchemaFromNodes as i}from"./packem_shared/jsonSchemaFromNode-k28QmNzA.mjs";import{argsToJsonSchema as l,toJsonSchema as d}from"./packem_shared/argsToJsonSchema-C4oyUJUg.mjs";import{isOrWrapsFromValidator as c,optionalInner as f,v as V}from"./packem_shared/isOrWrapsFromValidator-s_IOX_qQ.mjs";import{DEFER_VALIDATION as x,installCompiledValidatorMap as F,parseValidatorMap as S}from"./packem_shared/DEFER_VALIDATION-CNrZDGXy.mjs";export{x as DEFER_VALIDATION,a as ValidationError,l as argsToJsonSchema,e as describeValue,t as formatPath,F as installCompiledValidatorMap,c as isOrWrapsFromValidator,p as jsonSchemaFromNode,i as objectSchemaFromNodes,f as optionalInner,S as parseValidatorMap,d as toJsonSchema,V as v};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{LunoraError as v}from"@lunora/errors";import{ValidationError as h,formatPath as x,describeValue as y}from"./ValidationError-5sbiLWie.mjs";const j=/^[^\s@]+@[^\s@.]+(?:\.[^\s@.]+)+$/u,$=e=>{if(!URL.canParse(e))return!1;const{protocol:r}=new URL(e);return r==="http:"||r==="https:"};function p(e,r,n,o){const s=[...e.path],i=y(n,{literal:!o?.redactValue});throw new h(`Expected ${r} at ${x(s)}, received ${i}`,{expected:r,path:s,received:i})}const k=(e,r)=>{if(r===void 0)return e;const n=e?.constraints;return{...e,constraints:{...n,...r}}},l=(e,r,n)=>{const o=n?.column??{notNull:!0},s={__type:void 0,"~standard":{validate(a){const t=s.safeParse(a);return t.ok?{value:t.value}:{issues:[{message:t.error.message,path:t.error.path}]}},vendor:"lunora",version:1},_meta:{...n,column:o},_parse(a,t){return r(a,t)},kind:e,parse(a){return r(a,{path:[]})},safeParse(a){try{return{ok:!0,value:r(a,{path:[]})}}catch(t){if(t instanceof h)return{error:t,ok:!1};throw t}}},i=a=>l(e,r,{...n,column:{...o,...a}});switch(s.default=a=>i({defaultValue:a}),s.defaultNow=()=>i({defaultFn:()=>Date.now()}),s.unique=()=>i({unique:!0}),s.$defaultFn=a=>i({defaultFn:a}),s.$onUpdateFn=a=>i({onUpdateFn:a}),s.serverDefault=a=>i({serverDefault:a}),s.$type=(()=>i({})),s.nullable=()=>l(e,(a,t)=>a===null?null:r(a,t),{...n,column:{...o,notNull:!1}}),s.check=(a,t)=>{const c=typeof t=="string"?t:t?.message,u=typeof t=="string"?void 0:t?.schema;return l(e,(d,g)=>{const b=r(d,g);return a(b)||p(g,c??"value matching refinement",b,{redactValue:!0}),b},k(n,u))},s.meta=a=>{const t=a.description===void 0?a.schema:{description:a.description,...a.schema};return l(e,r,k(n,t))},e){case"array":{const a=s;a.min=t=>a.check(c=>c.length>=t,{message:`expected array length >= ${String(t)}`,schema:{minItems:t}}),a.max=t=>a.check(c=>c.length<=t,{message:`expected array length <= ${String(t)}`,schema:{maxItems:t}});break}case"number":{const a=s;a.min=t=>a.check(c=>c>=t,{message:`expected number >= ${String(t)}`,schema:{minimum:t}}),a.max=t=>a.check(c=>c<=t,{message:`expected number <= ${String(t)}`,schema:{maximum:t}}),a.int=()=>a.check(t=>Number.isInteger(t),{message:"expected an integer",schema:{type:"integer"}}),a.positive=()=>a.check(t=>t>0,{message:"expected a positive number",schema:{exclusiveMinimum:0}});break}case"string":{const a=s;a.min=t=>a.check(c=>c.length>=t,{message:`expected string length >= ${String(t)}`,schema:{minLength:t}}),a.max=t=>a.check(c=>c.length<=t,{message:`expected string length <= ${String(t)}`,schema:{maxLength:t}}),a.length=t=>a.check(c=>c.length===t,{message:`expected string length === ${String(t)}`,schema:{maxLength:t,minLength:t}}),a.pattern=t=>{const c=t.global||t.sticky?new RegExp(t.source,t.flags.replaceAll(/[gy]/gu,"")):t;return a.check(u=>c.test(u),{message:`expected string matching ${t.toString()}`,schema:{pattern:t.source}})},a.email=()=>a.check(t=>j.test(t),{message:"expected a valid email address",schema:{format:"email"}}),a.url=()=>a.check(t=>$(t),{message:"expected a valid URL",schema:{format:"uri"}});break}}return s},f=e=>e,m=e=>e,S=e=>e,_=e=>e,A=e=>e,N=()=>S(l("string",(e,r)=>(typeof e!="string"&&p(r,"string",e),e))),L=()=>_(l("number",(e,r)=>((typeof e!="number"||!Number.isFinite(e))&&p(r,"number",e),e))),w=(e,r)=>((typeof e!="number"||!Number.isFinite(e))&&p(r,"number",e),e),F=()=>l("timestamp",w),O=()=>l("date",w),V=()=>m(l("boolean",(e,r)=>(typeof e!="boolean"&&p(r,"boolean",e),e))),P=()=>m(l("bigint",(e,r)=>(typeof e!="bigint"&&p(r,"bigint",e),e))),I=()=>m(l("null",(e,r)=>(e!==null&&p(r,"null",e),e))),E=()=>m(l("bytes",(e,r)=>(e instanceof ArrayBuffer||p(r,"ArrayBuffer",e),e))),R=e=>m(l("id",(r,n)=>(typeof r!="string"&&p(n,`Id<"${e}">`,r),r),{tableName:e})),U=e=>m(l("storage",(r,n)=>(typeof r!="string"&&p(n,"storage object key (string)",r),r),e===void 0?void 0:{bucket:e})),q=()=>m(l("geoPoint",(e,r)=>{(typeof e!="object"||e===null||Array.isArray(e))&&p(r,"geoPoint { lat, lng }",e);const n=e,{lat:o,lng:s}=n;return(typeof o!="number"||!Number.isFinite(o)||o<-90||o>90)&&(r.path.push("lat"),p(r,"latitude in [-90, 90]",o)),(typeof s!="number"||!Number.isFinite(s)||s<-180||s>180)&&(r.path.push("lng"),p(r,"longitude in [-180, 180]",s)),{lat:o,lng:s}})),D=e=>m(l("literal",(r,n)=>(r!==e&&p(n,`literal(${String(e)})`,r),r),{value:e})),T=e=>{const r=f(e);return A(l("array",(n,o)=>{Array.isArray(n)||p(o,"array",n);const{length:s}=n,i=[],{path:a}=o;for(let t=0;t<s;t+=1)a.push(t),i.push(r._parse(n[t],o)),a.pop();return i},{inner:e}))},B=e=>{const r=Object.keys(e).map(n=>{const o=f(e[n]);return{child:o,isOptional:o.kind==="optional",key:n}});if(r.some(({key:n})=>n==="__proto__"))throw new v("INTERNAL",'v.object: "__proto__" cannot be a declared field name — it collides with the Object.prototype accessor');return m(l("object",(n,o)=>{(typeof n!="object"||n===null||Array.isArray(n))&&p(o,"object",n);const s=n,i={},{path:a}=o;for(const{child:t,isOptional:c,key:u}of r){const d=Object.hasOwn(s,u)?s[u]:void 0;d===void 0&&c||(a.push(u),i[u]=t._parse(d,o),a.pop())}return i},{shape:e}))},M=(e,r)=>{const n=f(e),o=f(r);return m(l("record",(s,i)=>{(typeof s!="object"||s===null||Array.isArray(s))&&p(i,"record",s);const a=s,t=Object.create(null),{path:c}=i;for(const u of Object.keys(a)){c.push(u);const d=n._parse(u,i),g=o._parse(a[u],i);c.pop(),t[d]=g}return t},{keyValidator:e,valueValidator:r}))},W=(...e)=>{if(e.length===0)throw new v("INTERNAL","v.union requires at least one member");const r=e.map(n=>f(n));return m(l("union",(n,o)=>{let s;const{path:i}=o,a=i.length;for(const c of r)try{return c._parse(n,o)}catch(u){if(!(u instanceof h))throw u;i.length=a,(s===void 0||u.path.length>s.path.length)&&(s=u)}if(r.length===1&&s!==void 0)throw s;const t=s===void 0?"":` (closest: expected ${s.expected} at ${x(s.path)})`;return p(o,`union of ${String(e.length)} member(s)${t}`,n)},{members:e}))},z=e=>{const r=f(e);return m(l("optional",(n,o)=>n===void 0?void 0:r._parse(n,o),{inner:e}))},G=()=>m(l("any",e=>e)),H=e=>{const r=[];if(!e)return r;for(const n of e){const o=typeof n=="object"&&n!==null&&"key"in n?n.key:n;(typeof o=="string"||typeof o=="number")&&r.push(o)}return r},J=e=>{const r=e["~standard"];if(r?.version!==1||typeof r.validate!="function")throw new v("INTERNAL",'@lunora/values: v.from() expects a Standard Schema v1 object (missing or invalid "~standard")');const n=r.validate;return m(l("from",(o,s)=>{const i=n(o);if(i instanceof Promise||typeof i?.then=="function")throw new h("v.from(): async Standard Schema validators are not supported in args",{expected:"sync Standard Schema result",path:[...s.path],received:"Promise"});const a=i;if(a===null||typeof a!="object")throw new h("v.from(): Standard Schema validator returned a non-object result",{expected:"Standard Schema result object",path:[...s.path],received:y(a)});const t=i;if("issues"in t&&t.issues!==void 0&&t.issues.length>0){const c=t.issues[0],u=c?.message??"Standard Schema validation failed";throw new h(u,{expected:"valid value",path:[...s.path,...H(c?.path)],received:y(o)})}return t.value}))},K=e=>{if(e.kind==="from")return!0;const r=e._meta;if(!r)return!1;const n=[r.inner,r.keyValidator,r.valueValidator];Array.isArray(r.members)&&n.push(...r.members),r.shape!==null&&typeof r.shape=="object"&&n.push(...Object.values(r.shape));for(const o of n)if(o!==null&&typeof o=="object"&&"kind"in o&&K(o))return!0;return!1},C=e=>{if(e.kind==="optional")return e._meta?.inner},Y={any:G,array:T,bigint:P,boolean:V,bytes:E,date:O,from:J,geoPoint:q,id:R,literal:D,null:I,number:L,object:B,optional:z,record:M,storage:U,string:N,timestamp:F,union:W};export{K as isOrWrapsFromValidator,C as optionalInner,Y as v};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/values",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.14",
|
|
4
4
|
"description": "Validators for Lunora: the v.* validator suite with end-to-end return-type inference",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"access": "public"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@lunora/errors": "1.0.0-alpha.
|
|
49
|
+
"@lunora/errors": "1.0.0-alpha.11"
|
|
50
50
|
},
|
|
51
51
|
"engines": {
|
|
52
52
|
"node": "^22.15.0 || >=24.11.0"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{LunoraError as j}from"@lunora/errors";import{ValidationError as h,describeValue as v,formatPath as k}from"./ValidationError-5sbiLWie.mjs";function l(e,t,r,a){const o=[...e.path],i=v(r,{literal:!a?.redactValue});throw new h(`Expected ${t} at ${k(o)}, received ${i}`,{expected:t,path:o,received:i})}const g=(e,t)=>{if(t===void 0)return e;const r=e?.constraints;return{...e,constraints:{...r,...t}}},u=(e,t,r)=>{const a=r?.column??{notNull:!0},o={__type:void 0,"~standard":{validate(n){const s=o.safeParse(n);return s.ok?{value:s.value}:{issues:[{message:s.error.message,path:s.error.path}]}},vendor:"lunora",version:1},_meta:{...r,column:a},_parse(n,s){return t(n,s)},kind:e,parse(n){return t(n,{path:[]})},safeParse(n){try{return{ok:!0,value:t(n,{path:[]})}}catch(s){if(s instanceof h)return{error:s,ok:!1};throw s}}},i=n=>u(e,t,{...r,column:{...a,...n}});return o.default=n=>i({defaultValue:n}),o.defaultNow=()=>i({defaultFn:()=>Date.now()}),o.unique=()=>i({unique:!0}),o.$defaultFn=n=>i({defaultFn:n}),o.$onUpdateFn=n=>i({onUpdateFn:n}),o.serverDefault=n=>i({serverDefault:n}),o.$type=(()=>i({})),o.nullable=()=>u(e,(n,s)=>n===null?null:t(n,s),{...r,column:{...a,notNull:!1}}),o.check=(n,s)=>{const d=typeof s=="string"?s:s?.message,c=typeof s=="string"?void 0:s?.schema;return u(e,(f,y)=>{const b=t(f,y);return n(b)||l(y,d??"value matching refinement",b,{redactValue:!0}),b},g(r,c))},o.meta=n=>{const s=n.description===void 0?n.schema:{description:n.description,...n.schema};return u(e,t,g(r,s))},o},m=e=>e,p=e=>e,A=()=>p(u("string",(e,t)=>(typeof e!="string"&&l(t,"string",e),e))),N=()=>p(u("number",(e,t)=>((typeof e!="number"||!Number.isFinite(e))&&l(t,"number",e),e))),w=(e,t)=>((typeof e!="number"||!Number.isFinite(e))&&l(t,"number",e),e),S=()=>u("timestamp",w),_=()=>u("date",w),$=()=>p(u("boolean",(e,t)=>(typeof e!="boolean"&&l(t,"boolean",e),e))),F=()=>p(u("bigint",(e,t)=>(typeof e!="bigint"&&l(t,"bigint",e),e))),V=()=>p(u("null",(e,t)=>(e!==null&&l(t,"null",e),e))),x=()=>p(u("bytes",(e,t)=>(e instanceof ArrayBuffer||l(t,"ArrayBuffer",e),e))),O=e=>p(u("id",(t,r)=>(typeof t!="string"&&l(r,`Id<"${e}">`,t),t),{tableName:e})),P=e=>p(u("storage",(t,r)=>(typeof t!="string"&&l(r,"storage object key (string)",t),t),e===void 0?void 0:{bucket:e})),E=()=>p(u("geoPoint",(e,t)=>{(typeof e!="object"||e===null||Array.isArray(e))&&l(t,"geoPoint { lat, lng }",e);const r=e,{lat:a,lng:o}=r;return(typeof a!="number"||!Number.isFinite(a)||a<-90||a>90)&&(t.path.push("lat"),l(t,"latitude in [-90, 90]",a)),(typeof o!="number"||!Number.isFinite(o)||o<-180||o>180)&&(t.path.push("lng"),l(t,"longitude in [-180, 180]",o)),{lat:a,lng:o}})),q=e=>p(u("literal",(t,r)=>(t!==e&&l(r,`literal(${String(e)})`,t),t),{value:e})),D=e=>{const t=m(e);return p(u("array",(r,a)=>{Array.isArray(r)||l(a,"array",r);const{length:o}=r,i=[],{path:n}=a;for(let s=0;s<o;s+=1)n.push(s),i.push(t._parse(r[s],a)),n.pop();return i},{inner:e}))},I=e=>{const t=Object.keys(e).map(r=>{const a=m(e[r]);return{child:a,isOptional:a.kind==="optional",key:r}});return p(u("object",(r,a)=>{(typeof r!="object"||r===null||Array.isArray(r))&&l(a,"object",r);const o=r,i={},{path:n}=a;for(const{child:s,isOptional:d,key:c}of t){const f=Object.hasOwn(o,c)?o[c]:void 0;f===void 0&&d||(n.push(c),i[c]=s._parse(f,a),n.pop())}return i},{shape:e}))},B=(e,t)=>{const r=m(e),a=m(t);return p(u("record",(o,i)=>{(typeof o!="object"||o===null||Array.isArray(o))&&l(i,"record",o);const n=o,s=Object.create(null),{path:d}=i;for(const c of Object.keys(n)){d.push(c);const f=r._parse(c,i),y=a._parse(n[c],i);d.pop(),s[f]=y}return s},{keyValidator:e,valueValidator:t}))},L=(...e)=>{if(e.length===0)throw new j("INTERNAL","v.union requires at least one member");const t=e.map(r=>m(r));return p(u("union",(r,a)=>{let o;const{path:i}=a,n=i.length;for(const d of t)try{return d._parse(r,a)}catch(c){if(!(c instanceof h))throw c;i.length=n,(o===void 0||c.path.length>o.path.length)&&(o=c)}if(t.length===1&&o!==void 0)throw o;const s=o===void 0?"":` (closest: expected ${o.expected} at ${k(o.path)})`;return l(a,`union of ${String(e.length)} member(s)${s}`,r)},{members:e}))},R=e=>{const t=m(e);return p(u("optional",(r,a)=>r===void 0?void 0:t._parse(r,a),{inner:e}))},T=()=>p(u("any",e=>e)),U=e=>{const t=[];if(!e)return t;for(const r of e){const a=typeof r=="object"&&r!==null&&"key"in r?r.key:r;(typeof a=="string"||typeof a=="number")&&t.push(a)}return t},z=e=>{const t=e["~standard"];if(t?.version!==1||typeof t.validate!="function")throw new j("INTERNAL",'@lunora/values: v.from() expects a Standard Schema v1 object (missing or invalid "~standard")');const r=t.validate;return p(u("from",(a,o)=>{const i=r(a);if(i instanceof Promise||typeof i?.then=="function")throw new h("v.from(): async Standard Schema validators are not supported in args",{expected:"sync Standard Schema result",path:[...o.path],received:"Promise"});const n=i;if(n===null||typeof n!="object")throw new h("v.from(): Standard Schema validator returned a non-object result",{expected:"Standard Schema result object",path:[...o.path],received:v(n)});const s=i;if("issues"in s&&s.issues!==void 0&&s.issues.length>0){const d=s.issues[0],c=d?.message??"Standard Schema validation failed";throw new h(c,{expected:"valid value",path:[...o.path,...U(d?.path)],received:v(a)})}return s.value}))},C=e=>{if(e.kind==="from")return!0;const t=e._meta;if(!t)return!1;const r=[t.inner,t.keyValidator,t.valueValidator];Array.isArray(t.members)&&r.push(...t.members),t.shape!==null&&typeof t.shape=="object"&&r.push(...Object.values(t.shape));for(const a of r)if(a!==null&&typeof a=="object"&&"kind"in a&&C(a))return!0;return!1},K=e=>{if(e.kind==="optional")return e._meta?.inner},M={any:T,array:D,bigint:F,boolean:$,bytes:x,date:_,from:z,geoPoint:E,id:O,literal:q,null:V,number:N,object:I,optional:R,record:B,storage:P,string:A,timestamp:S,union:L};export{C as isOrWrapsFromValidator,K as optionalInner,M as v};
|