@lunora/values 1.0.0-alpha.75 → 1.0.0-alpha.77

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
@@ -367,6 +367,13 @@ interface GeoPoint {
367
367
  */
368
368
  declare const geoPoint: () => ColumnValidator<GeoPoint, GeoPoint>;
369
369
  declare const literal: <T extends bigint | boolean | number | string | null>(literalValue: T) => ColumnValidator<T, T>;
370
+ /**
371
+ * True when `validator` is marked with {@link sensitive} or wraps a marked
372
+ * validator anywhere in its tree. Coarse on purpose: an argument whose tree holds
373
+ * any secret is treated as a secret as a whole, which fails closed where a
374
+ * per-field walk over wire-encoded values would not.
375
+ */
376
+ declare const containsSensitive: (validator: Validator) => boolean;
370
377
  declare const array: <V extends Validator>(inner: V) => ArrayColumnValidator<Infer<V>>;
371
378
  /**
372
379
  * Split a value-type map into optional + required keys: any member whose value
@@ -389,6 +396,23 @@ type OptionalizeShape<M> = { [K in keyof M as undefined extends M[K] ? K : never
389
396
  type ObjectShape = Record<string, Validator>;
390
397
  type ObjectShapeType<S extends ObjectShape> = OptionalizeShape<{ [K in keyof S]: Infer<S[K]>; }>;
391
398
  declare const objectValidator: <S extends ObjectShape>(shape: S, stripUnknown?: boolean) => ObjectColumnValidator<ObjectShapeType<S>>;
399
+ /**
400
+ * Mark a validator's value as sensitive. Parsing and the accepted set are
401
+ * unchanged. A failed parse withholds the value from `received` and the message
402
+ * (see {@link ParseContext.redact}); the JSON Schema node is `writeOnly`, with
403
+ * `format: "password"` on a plain string; and the request log, the MCP proposal
404
+ * and the offline queue treat the argument as a secret (see
405
+ * {@link containsSensitive}). In a recorded string the value is masked wherever it
406
+ * appears if it is four or more characters, as a whole word or number if it is
407
+ * three, and only as the whole string if it is shorter. A string of four or more
408
+ * characters is also matched in its JSON-escaped spelling, since a handler that
409
+ * serializes its arguments writes that form.
410
+ *
411
+ * A marker is a meta flag on the same kind rather than a kind of its own, so
412
+ * every `switch (kind)` and `kind === "optional"` test keeps its meaning and
413
+ * `v.sensitive(v.optional(x))` stays optional.
414
+ */
415
+ declare const sensitive: <V extends Validator>(validator: V) => V;
392
416
  declare const record: <K extends Validator<string>, V extends Validator>(keyValidator: K, valueValidator: V) => ColumnValidator<Record<Infer<K>, Infer<V>>, Record<Infer<K>, Infer<V>>>;
393
417
  declare const union: <Vs extends ReadonlyArray<Validator>>(...members: Vs) => ColumnValidator<Infer<Vs[number]>, Infer<Vs[number]>>;
394
418
  declare const optional: <V extends Validator>(inner: V) => ColumnValidator<Infer<V> | undefined, Infer<V> | undefined>;
@@ -491,6 +515,11 @@ declare const from: <S extends StandardSchemaV1>(schema: S) => ColumnValidator<I
491
515
  * and stores JSON, see {@link from}.
492
516
  */
493
517
  declare const isOrWrapsFromValidator: (validator: Validator) => boolean;
518
+ /**
519
+ * The names of a function's arguments that carry a {@link sensitive} marker.
520
+ * Memoised per args object: the request log asks on every dispatch.
521
+ */
522
+ declare const sensitiveArgumentNames: (args: Readonly<Record<string, unknown>>) => ReadonlySet<string>;
494
523
  /**
495
524
  * The inner validator wrapped by `v.optional(inner)`, or `undefined` for any
496
525
  * other validator. The nested child lives on the validator's internal `_meta`
@@ -531,6 +560,7 @@ declare const v: {
531
560
  optional: typeof optional;
532
561
  partial: typeof partial;
533
562
  record: typeof record;
563
+ sensitive: typeof sensitive;
534
564
  storage: typeof storage;
535
565
  string: typeof string;
536
566
  timestamp: typeof timestamp;
@@ -587,6 +617,11 @@ interface SchemaNodeReader<TNode> {
587
617
  literalSchema: (node: TNode) => JsonSchema;
588
618
  /** Member nodes of a `union`. */
589
619
  members: (node: TNode) => ReadonlyArray<TNode>;
620
+ /**
621
+ * Whether the node is marked sensitive (`v.sensitive`). A sensitive node is
622
+ * emitted `writeOnly`, and a plain string also gets `format: "password"`.
623
+ */
624
+ sensitive: (node: TNode) => boolean;
590
625
  /** Property nodes of an `object`, keyed by property name. */
591
626
  shape: (node: TNode) => Record<string, TNode>;
592
627
  /** Target table name of an `id` node. */
@@ -728,4 +763,4 @@ declare const installCompiledValidatorMap: (validators: object, compiled: Compil
728
763
  * which case the interpreted loop below runs and owns the result (and any error).
729
764
  */
730
765
  declare const parseValidatorMap: (validators: ValidatorMap, source: Record<string, unknown>, label: string) => Record<string, unknown>;
731
- 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 InferStandardInput, type InferStandardOutput, type InferValidatorMap, type InsertShape, type JsonSchema, type JsonSchemaFragment, type MetaOptions, type NumberColumnValidator, type ObjectColumnValidator, type ParseOptions, type SchemaNodeReader, type SelectShape, type ServerDefaultContext, type StringColumnValidator, type TimestampColumnValidator, ValidationError, type ValidationPath, type Validator, type ValidatorKind, type ValidatorMap, acceptsAbsent, argsToJsonSchema, cyrb53, describeValue, formatPath, installCompiledValidatorMap, isOrWrapsFromValidator, isStringValidator, jsonSchemaFromNode, objectSchemaFromNodes, optionalInner, parseValidatorMap, toJsonSchema, v };
766
+ 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 InferStandardInput, type InferStandardOutput, type InferValidatorMap, type InsertShape, type JsonSchema, type JsonSchemaFragment, type MetaOptions, type NumberColumnValidator, type ObjectColumnValidator, type ParseOptions, type SchemaNodeReader, type SelectShape, type ServerDefaultContext, type StringColumnValidator, type TimestampColumnValidator, ValidationError, type ValidationPath, type Validator, type ValidatorKind, type ValidatorMap, acceptsAbsent, argsToJsonSchema, containsSensitive, cyrb53, describeValue, formatPath, installCompiledValidatorMap, isOrWrapsFromValidator, isStringValidator, jsonSchemaFromNode, objectSchemaFromNodes, optionalInner, parseValidatorMap, sensitiveArgumentNames, toJsonSchema, v };
package/dist/index.d.ts CHANGED
@@ -367,6 +367,13 @@ interface GeoPoint {
367
367
  */
368
368
  declare const geoPoint: () => ColumnValidator<GeoPoint, GeoPoint>;
369
369
  declare const literal: <T extends bigint | boolean | number | string | null>(literalValue: T) => ColumnValidator<T, T>;
370
+ /**
371
+ * True when `validator` is marked with {@link sensitive} or wraps a marked
372
+ * validator anywhere in its tree. Coarse on purpose: an argument whose tree holds
373
+ * any secret is treated as a secret as a whole, which fails closed where a
374
+ * per-field walk over wire-encoded values would not.
375
+ */
376
+ declare const containsSensitive: (validator: Validator) => boolean;
370
377
  declare const array: <V extends Validator>(inner: V) => ArrayColumnValidator<Infer<V>>;
371
378
  /**
372
379
  * Split a value-type map into optional + required keys: any member whose value
@@ -389,6 +396,23 @@ type OptionalizeShape<M> = { [K in keyof M as undefined extends M[K] ? K : never
389
396
  type ObjectShape = Record<string, Validator>;
390
397
  type ObjectShapeType<S extends ObjectShape> = OptionalizeShape<{ [K in keyof S]: Infer<S[K]>; }>;
391
398
  declare const objectValidator: <S extends ObjectShape>(shape: S, stripUnknown?: boolean) => ObjectColumnValidator<ObjectShapeType<S>>;
399
+ /**
400
+ * Mark a validator's value as sensitive. Parsing and the accepted set are
401
+ * unchanged. A failed parse withholds the value from `received` and the message
402
+ * (see {@link ParseContext.redact}); the JSON Schema node is `writeOnly`, with
403
+ * `format: "password"` on a plain string; and the request log, the MCP proposal
404
+ * and the offline queue treat the argument as a secret (see
405
+ * {@link containsSensitive}). In a recorded string the value is masked wherever it
406
+ * appears if it is four or more characters, as a whole word or number if it is
407
+ * three, and only as the whole string if it is shorter. A string of four or more
408
+ * characters is also matched in its JSON-escaped spelling, since a handler that
409
+ * serializes its arguments writes that form.
410
+ *
411
+ * A marker is a meta flag on the same kind rather than a kind of its own, so
412
+ * every `switch (kind)` and `kind === "optional"` test keeps its meaning and
413
+ * `v.sensitive(v.optional(x))` stays optional.
414
+ */
415
+ declare const sensitive: <V extends Validator>(validator: V) => V;
392
416
  declare const record: <K extends Validator<string>, V extends Validator>(keyValidator: K, valueValidator: V) => ColumnValidator<Record<Infer<K>, Infer<V>>, Record<Infer<K>, Infer<V>>>;
393
417
  declare const union: <Vs extends ReadonlyArray<Validator>>(...members: Vs) => ColumnValidator<Infer<Vs[number]>, Infer<Vs[number]>>;
394
418
  declare const optional: <V extends Validator>(inner: V) => ColumnValidator<Infer<V> | undefined, Infer<V> | undefined>;
@@ -491,6 +515,11 @@ declare const from: <S extends StandardSchemaV1>(schema: S) => ColumnValidator<I
491
515
  * and stores JSON, see {@link from}.
492
516
  */
493
517
  declare const isOrWrapsFromValidator: (validator: Validator) => boolean;
518
+ /**
519
+ * The names of a function's arguments that carry a {@link sensitive} marker.
520
+ * Memoised per args object: the request log asks on every dispatch.
521
+ */
522
+ declare const sensitiveArgumentNames: (args: Readonly<Record<string, unknown>>) => ReadonlySet<string>;
494
523
  /**
495
524
  * The inner validator wrapped by `v.optional(inner)`, or `undefined` for any
496
525
  * other validator. The nested child lives on the validator's internal `_meta`
@@ -531,6 +560,7 @@ declare const v: {
531
560
  optional: typeof optional;
532
561
  partial: typeof partial;
533
562
  record: typeof record;
563
+ sensitive: typeof sensitive;
534
564
  storage: typeof storage;
535
565
  string: typeof string;
536
566
  timestamp: typeof timestamp;
@@ -587,6 +617,11 @@ interface SchemaNodeReader<TNode> {
587
617
  literalSchema: (node: TNode) => JsonSchema;
588
618
  /** Member nodes of a `union`. */
589
619
  members: (node: TNode) => ReadonlyArray<TNode>;
620
+ /**
621
+ * Whether the node is marked sensitive (`v.sensitive`). A sensitive node is
622
+ * emitted `writeOnly`, and a plain string also gets `format: "password"`.
623
+ */
624
+ sensitive: (node: TNode) => boolean;
590
625
  /** Property nodes of an `object`, keyed by property name. */
591
626
  shape: (node: TNode) => Record<string, TNode>;
592
627
  /** Target table name of an `id` node. */
@@ -728,4 +763,4 @@ declare const installCompiledValidatorMap: (validators: object, compiled: Compil
728
763
  * which case the interpreted loop below runs and owns the result (and any error).
729
764
  */
730
765
  declare const parseValidatorMap: (validators: ValidatorMap, source: Record<string, unknown>, label: string) => Record<string, unknown>;
731
- 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 InferStandardInput, type InferStandardOutput, type InferValidatorMap, type InsertShape, type JsonSchema, type JsonSchemaFragment, type MetaOptions, type NumberColumnValidator, type ObjectColumnValidator, type ParseOptions, type SchemaNodeReader, type SelectShape, type ServerDefaultContext, type StringColumnValidator, type TimestampColumnValidator, ValidationError, type ValidationPath, type Validator, type ValidatorKind, type ValidatorMap, acceptsAbsent, argsToJsonSchema, cyrb53, describeValue, formatPath, installCompiledValidatorMap, isOrWrapsFromValidator, isStringValidator, jsonSchemaFromNode, objectSchemaFromNodes, optionalInner, parseValidatorMap, toJsonSchema, v };
766
+ 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 InferStandardInput, type InferStandardOutput, type InferValidatorMap, type InsertShape, type JsonSchema, type JsonSchemaFragment, type MetaOptions, type NumberColumnValidator, type ObjectColumnValidator, type ParseOptions, type SchemaNodeReader, type SelectShape, type ServerDefaultContext, type StringColumnValidator, type TimestampColumnValidator, ValidationError, type ValidationPath, type Validator, type ValidatorKind, type ValidatorMap, acceptsAbsent, argsToJsonSchema, containsSensitive, cyrb53, describeValue, formatPath, installCompiledValidatorMap, isOrWrapsFromValidator, isStringValidator, jsonSchemaFromNode, objectSchemaFromNodes, optionalInner, parseValidatorMap, sensitiveArgumentNames, toJsonSchema, v };
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{ValidationError as a,describeValue as e,formatPath as t}from"./packem_shared/ValidationError-BdVoGndu.mjs";import{cyrb53 as i}from"./packem_shared/cyrb53-CFiior4X.mjs";import{acceptsAbsent as s,jsonSchemaFromNode as l,objectSchemaFromNodes as n}from"./packem_shared/acceptsAbsent-Biqy6mRN.mjs";import{argsToJsonSchema as d,toJsonSchema as f}from"./packem_shared/argsToJsonSchema-ATrQFtr_.mjs";import{isOrWrapsFromValidator as x,isStringValidator as h,optionalInner as S,v as b}from"./packem_shared/isOrWrapsFromValidator-CpKb4P21.mjs";import{DEFER_VALIDATION as A,installCompiledValidatorMap as E,parseValidatorMap as I}from"./packem_shared/DEFER_VALIDATION-C0nIiPG-.mjs";export{A as DEFER_VALIDATION,a as ValidationError,s as acceptsAbsent,d as argsToJsonSchema,i as cyrb53,e as describeValue,t as formatPath,E as installCompiledValidatorMap,x as isOrWrapsFromValidator,h as isStringValidator,l as jsonSchemaFromNode,n as objectSchemaFromNodes,S as optionalInner,I as parseValidatorMap,f as toJsonSchema,b as v};
1
+ import{ValidationError as a,describeValue as e,formatPath as t}from"./packem_shared/ValidationError-BdVoGndu.mjs";import{cyrb53 as s}from"./packem_shared/cyrb53-CFiior4X.mjs";import{acceptsAbsent as n,jsonSchemaFromNode as p,objectSchemaFromNodes as c}from"./packem_shared/acceptsAbsent-DgAiqnEt.mjs";import{argsToJsonSchema as d,toJsonSchema as f}from"./packem_shared/argsToJsonSchema-DCmyUTsd.mjs";import{containsSensitive as x,isOrWrapsFromValidator as S,isStringValidator as h,optionalInner as b,sensitiveArgumentNames as A,v as F}from"./packem_shared/containsSensitive-CwYDLFoi.mjs";import{DEFER_VALIDATION as g,installCompiledValidatorMap as v,parseValidatorMap as E}from"./packem_shared/DEFER_VALIDATION-C0nIiPG-.mjs";export{g as DEFER_VALIDATION,a as ValidationError,n as acceptsAbsent,d as argsToJsonSchema,x as containsSensitive,s as cyrb53,e as describeValue,t as formatPath,v as installCompiledValidatorMap,S as isOrWrapsFromValidator,h as isStringValidator,p as jsonSchemaFromNode,c as objectSchemaFromNodes,b as optionalInner,E as parseValidatorMap,A as sensitiveArgumentNames,f as toJsonSchema,F as v};
@@ -0,0 +1 @@
1
+ const m=n=>n===null?"null":typeof n=="number"?"number":typeof n=="string"||typeof n=="boolean"?typeof n:void 0,p=n=>{const{const:t,anyOf:e,...i}=n,s=t===void 0?i:{...i,type:i.type??m(t)},o=Array.isArray(e)?{anyOf:e.map(a=>p(a))}:{},r=s.type==="string"&&s.format===void 0;return{...s,...o,writeOnly:!0,...r?{format:"password"}:{}}},c=(n,t)=>{const e=(()=>{switch(t.kind(n)){case"any":return{};case"array":{const r=t.inner(n);return{items:r===void 0?{}:c(r,t),type:"array"}}case"bigint":return{format:"int64",type:"string"};case"boolean":return{type:"boolean"};case"bytes":return{contentEncoding:"base64",description:"binary (ArrayBuffer)",type:"string"};case"date":return{description:"epoch milliseconds (date)",type:"integer"};case"geoPoint":return{description:"geographic point (WGS84 decimal degrees)",properties:{lat:{maximum:90,minimum:-90,type:"number"},lng:{maximum:180,minimum:-180,type:"number"}},required:["lat","lng"],type:"object"};case"id":return{description:`Id<"${String(t.tableName(n))}">`,type:"string","x-lunora-table":t.tableName(n)};case"literal":return t.literalSchema(n);case"null":return{type:"null"};case"number":return{type:"number"};case"object":return l(t.shape(n),t);case"optional":{const r=t.inner(n);return r===void 0?{}:c(r,t)}case"record":{const r=t.valueChild(n),a=t.keyChild(n);return{additionalProperties:r===void 0?{}:c(r,t),...a===void 0?{}:{propertyNames:c(a,t)},type:"object"}}case"storage":return{description:"storage object key",type:"string","x-lunora-storage":!0};case"string":return{type:"string"};case"timestamp":return{description:"epoch milliseconds (timestamp)",type:"integer"};case"union":return{anyOf:t.members(n).map(r=>c(r,t))};default:return{}}})(),i=t.constraints(n),s=i===void 0?e:{...e,...i},o=t.sensitive(n)?p(s):s;return t.isNullable(n)?{anyOf:[o,{type:"null"}]}:o},u=(n,t)=>{const e=t.kind(n);return e==="any"||e==="optional"?!0:e==="union"&&t.members(n).some(i=>u(i,t))},l=(n,t)=>{const e={},i=[];for(const[s,o]of Object.entries(n))e[s]=c(o,t),u(o,t)||i.push(s);return{properties:e,required:i,type:"object"}};export{u as acceptsAbsent,c as jsonSchemaFromNode,l as objectSchemaFromNodes};
@@ -0,0 +1 @@
1
+ import{objectSchemaFromNodes as a,jsonSchemaFromNode as s}from"./acceptsAbsent-DgAiqnEt.mjs";const i=e=>e,t=e=>i(e)._meta??{},n={constraints:e=>t(e).constraints,inner:e=>t(e).inner,isNullable:e=>t(e).column?.notNull===!1,keyChild:e=>t(e).keyValidator,kind:e=>e.kind,literalSchema:e=>{const{value:o}=t(e);return typeof o=="bigint"?{const:o.toString(),format:"int64",type:"string"}:{const:o}},members:e=>t(e).members,sensitive:e=>t(e).sensitive===!0,shape:e=>t(e).shape,tableName:e=>t(e).tableName,valueChild:e=>t(e).valueValidator},l=e=>s(e,n),m=e=>a(e,n);export{m as argsToJsonSchema,l as toJsonSchema};
@@ -0,0 +1 @@
1
+ import{LunoraError as _}from"@lunora/errors";import{ValidationError as g,describeValue as S,formatPath as E}from"./ValidationError-BdVoGndu.mjs";const V=/^[^\s@]+@[^\s@.]+(?:\.[^\s@.]+)+$/u,F=e=>{if(!URL.canParse(e))return!1;const{protocol:t}=new URL(e);return t==="http:"||t==="https:"},P=new g("union branch probe miss (internal)",{expected:"",path:[],received:""}),j=e=>typeof e=="object"&&e!==null&&!Array.isArray(e)&&!(e instanceof ArrayBuffer)?"object":S(e,{literal:!1}),k=(e,t)=>t?{...e,redact:!0}:e;function d(e,t,s,i){if(e.probe===!0)throw P;const o=[...e.path],a=e.redact===!0?j(s):S(s,{literal:!i?.redactValue});throw new g(`Expected ${t} at ${E(o)}, received ${a}`,{expected:t,path:o,received:a})}const $=(e,t)=>{if(t===void 0)return e;const s=e?.constraints;return{...e,constraints:{...s,...t}}},u=(e,t,s)=>{const i=s?.column??{notNull:!0},o={__type:void 0,"~standard":{validate(r){const n=o.safeParse(r);return n.ok?{value:n.value}:{issues:[{message:n.error.message,path:n.error.path}]}},vendor:"lunora",version:1},_meta:{...s,column:i},_parse(r,n){return t(r,n)},kind:e,parse(r,n){return t(r,{path:[],...n})},safeParse(r,n){try{return{ok:!0,value:t(r,{path:[],...n})}}catch(c){if(c instanceof g)return{error:c,ok:!1};throw c}}},a=r=>u(e,t,{...s,column:{...i,...r}});switch(o.default=r=>a({defaultValue:r}),o.defaultNow=()=>a({defaultFn:()=>Date.now()}),o.unique=()=>a({unique:!0}),o.$defaultFn=r=>a({defaultFn:r}),o.$onUpdateFn=r=>a({onUpdateFn:r}),o.serverDefault=r=>a({serverDefault:r}),o.$type=(()=>a({})),o.nullable=()=>u(e,(n,c)=>n===null?null:t(n,c),{...s,column:{...i,notNull:!1}}),o.check=(r,n)=>{const c=typeof n=="string"?n:n?.message,l=typeof n=="string"?void 0:n?.schema;return u(e,(p,f)=>{const y=t(p,f);return r(y)||d(k(f,s?.sensitive===!0),c??"value matching refinement",y,{redactValue:!0}),y},$(s,l))},o.meta=r=>{const n=r.description===void 0?r.schema:{description:r.description,...r.schema};return u(e,t,$(s,n))},e){case"array":{const r=o;r.min=n=>r.check(c=>c.length>=n,{message:`expected array length >= ${String(n)}`,schema:{minItems:n}}),r.max=n=>r.check(c=>c.length<=n,{message:`expected array length <= ${String(n)}`,schema:{maxItems:n}});break}case"number":{const r=o;r.min=n=>r.check(c=>c>=n,{message:`expected number >= ${String(n)}`,schema:{minimum:n}}),r.max=n=>r.check(c=>c<=n,{message:`expected number <= ${String(n)}`,schema:{maximum:n}}),r.int=()=>r.check(n=>Number.isInteger(n),{message:"expected an integer",schema:{type:"integer"}}),r.positive=()=>r.check(n=>n>0,{message:"expected a positive number",schema:{exclusiveMinimum:0}});break}case"string":{const r=o;r.min=n=>r.check(c=>c.length>=n,{message:`expected string length >= ${String(n)}`,schema:{minLength:n}}),r.max=n=>r.check(c=>c.length<=n,{message:`expected string length <= ${String(n)}`,schema:{maxLength:n}}),r.length=n=>r.check(c=>c.length===n,{message:`expected string length === ${String(n)}`,schema:{maxLength:n,minLength:n}}),r.pattern=n=>{const c=n.global||n.sticky?new RegExp(n.source,n.flags.replaceAll(/[gy]/gu,"")):n;return r.check(l=>c.test(l),{message:`expected string matching ${n.toString()}`,schema:{pattern:n.source}})},r.email=()=>r.check(n=>V.test(n),{message:"expected a valid email address",schema:{format:"email"}}),r.url=()=>r.check(n=>F(n),{message:"expected a valid URL",schema:{format:"uri"}});break}}return o},b=e=>e,h=e=>e,C=e=>e,U=e=>e,D=e=>e,T=()=>C(u("string",(e,t)=>(typeof e!="string"&&d(t,"string",e),e))),A=(e,t)=>((typeof e!="number"||!Number.isFinite(e))&&d(t,"number",e),e),M=()=>U(u("number",A)),B=()=>u("timestamp",A),q=()=>u("date",A),K=()=>h(u("boolean",(e,t)=>(typeof e!="boolean"&&d(t,"boolean",e),e))),W=()=>h(u("bigint",(e,t)=>(typeof e!="bigint"&&d(t,"bigint",e),e))),G=()=>h(u("null",(e,t)=>(e!==null&&d(t,"null",e),e))),H=()=>h(u("bytes",(e,t)=>ArrayBuffer.isView(e)?e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength):(e instanceof ArrayBuffer||d(t,"ArrayBuffer",e),e))),Y=e=>h(u("id",(t,s)=>(typeof t!="string"&&d(s,`Id<"${e}">`,t),t),{tableName:e})),z=e=>h(u("storage",(t,s)=>(typeof t!="string"&&d(s,"storage object key (string)",t),t),e===void 0?void 0:{bucket:e})),J=()=>h(u("geoPoint",(e,t)=>{(typeof e!="object"||e===null||Array.isArray(e))&&d(t,"geoPoint { lat, lng }",e);const s=e,{lat:i,lng:o}=s;return(typeof i!="number"||!Number.isFinite(i)||i<-90||i>90)&&(t.path.push("lat"),d(t,"latitude in [-90, 90]",i)),(typeof o!="number"||!Number.isFinite(o)||o<-180||o>180)&&(t.path.push("lng"),d(t,"longitude in [-180, 180]",o)),{lat:i,lng:o}})),Q=e=>h(u("literal",(t,s)=>(t!==e&&d(s,s.redact===!0?"literal":`literal(${String(e)})`,t),t),{value:e})),I=e=>{const t=e._meta;if(!t)return[];const s=[t.inner,t.keyValidator,t.valueValidator];return Array.isArray(t.members)&&s.push(...t.members),t.shape!==null&&typeof t.shape=="object"&&s.push(...Object.values(t.shape)),s.filter(i=>i!==null&&typeof i=="object"&&"kind"in i)},w=e=>e._meta?.sensitive===!0||I(e).some(t=>w(t)),X=e=>{const t=b(e),s=w(e);return D(u("array",(i,o)=>{Array.isArray(i)||d(k(o,s),"array",i);const{length:a}=i,r=[],{path:n}=o;for(let c=0;c<a;c+=1)n.push(c),r.push(t._parse(i[c],o)),n.pop();return r},{inner:e}))},N=(e,t)=>{const s=Object.keys(e).map(a=>{const r=b(e[a]);return{child:r,isOptional:r.kind==="optional",key:a}});if(s.some(({key:a})=>a==="__proto__"))throw new _("INTERNAL",'v.object: "__proto__" cannot be a declared field name — it collides with the Object.prototype accessor');const i=Object.values(e).some(a=>w(a)),o=h(u("object",(a,r)=>{(typeof a!="object"||a===null||Array.isArray(a))&&d(k(r,i),"object",a);const n=a,c={},{path:l}=r;if(r.rejectUnknownKeys===!0&&t!==!0){const m=new Set(s.map(({key:f})=>f)),p=Object.keys(n).filter(f=>!m.has(f));if(p.length>0){const f=r.redact===!0||i?"[redacted]":p.join(", ");throw new g(`object has ${String(p.length)} undeclared key(s): ${f}. Add them to the validator, or call .strip() on it to drop them on purpose.`,{expected:`only the declared keys (${s.map(({key:y})=>y).join(", ")})`,path:[...l],received:f})}}for(const{child:m,isOptional:p,key:f}of s){const y=Object.hasOwn(n,f)?n[f]:void 0;y===void 0&&p||(l.push(f),c[f]=m._parse(y,r),l.pop())}return c},{shape:e}));return o.strip=()=>N(e,!0),o},v=e=>{const t=b(e),s=u(t.kind,(o,a)=>{const r=a.redact;a.redact=!0;try{return t._parse(o,a)}finally{a.redact=r}},{...t._meta,sensitive:!0}),{strip:i}=t;return typeof i=="function"&&(s.strip=()=>v(i())),s},R="<key>",Z=(e,t)=>{const s=w(e)||w(t),i=b(s?v(e):e),o=b(t);return h(u("record",(a,r)=>{(typeof a!="object"||a===null||Array.isArray(a))&&d(k(r,s),"record",a);const n=a,c=Object.create(null),{path:l}=r;for(const m of Object.keys(n)){l.push(s?R:m);const p=i._parse(m,r),f=o._parse(n[m],r);l.pop(),c[p]=f}return c},{keyValidator:e,valueValidator:t}))},x=(e,t,s,i,o)=>{const{path:a}=s;let r;const n=S(t,{literal:!1});let c=!1;for(const m of e)try{m._parse(t,s)}catch(p){if(!(p instanceof g))throw p;a.length=i,c||=p.received===n,(r===void 0||p.path.length>r.path.length)&&(r=p)}if(e.length===1&&r!==void 0)throw r;const l=r===void 0?"":` (closest: expected ${r.expected} at ${E(r.path)})`;return d(k(s,o),`union of ${String(e.length)} member(s)${l}`,t,{redactValue:c})},ee=(...e)=>{if(e.length===0)throw new _("INTERNAL","v.union requires at least one member");const t=e.map(i=>b(i)),s=e.some(i=>w(i));return h(u("union",(i,o)=>{const{path:a}=o,r=a.length,n=o.probe===!0;o.probe=!0;try{for(const c of t)try{return c._parse(i,o)}catch(l){if(!(l instanceof g))throw l;a.length=r}}finally{o.probe=n}if(n)throw P;return x(t,i,o,r,s)},{members:e}))},L=e=>{const t=b(e);return h(u("optional",(s,i)=>s===void 0?void 0:t._parse(s,i),{inner:e}))},te=e=>Object.fromEntries(Object.entries(e).map(([t,s])=>[t,b(s).kind==="optional"?s:L(s)])),re=()=>h(u("any",e=>e)),ne=e=>{const t=[];if(!e)return t;for(const s of e){const i=typeof s=="object"&&s!==null&&"key"in s?s.key:s;(typeof i=="string"||typeof i=="number")&&t.push(i)}return t},se=e=>{const t=e["~standard"];if(t?.version!==1||typeof t.validate!="function")throw new _("INTERNAL",'@lunora/values: v.from() expects a Standard Schema v1 object (missing or invalid "~standard")');const s=t.validate;return h(u("from",(i,o)=>{const a=(()=>{try{return s(i)}catch(c){throw o.redact===!0?new g("Standard Schema validation failed",{expected:"valid value",path:[...o.path],received:j(i)}):c}})();if(a instanceof Promise||typeof a?.then=="function")throw new g("v.from(): async Standard Schema validators are not supported in args",{expected:"sync Standard Schema result",path:[...o.path],received:"Promise"});const r=a;if(r===null||typeof r!="object")throw new g("v.from(): Standard Schema validator returned a non-object result",{expected:"Standard Schema result object",path:[...o.path],received:o.redact===!0?j(r):S(r)});const n=a;if(n.issues!==void 0){const c=n.issues[0],l=o.redact===!0?"Standard Schema validation failed":c?.message??"Standard Schema validation failed";throw new g(l,{expected:"valid value",path:[...o.path,...ne(c?.path).map(m=>o.redact===!0&&typeof m=="string"?R:m)],received:o.redact===!0?j(i):S(i)})}return n.value}))},oe=e=>e.kind==="from"?!0:I(e).some(t=>oe(t)),O=new WeakMap,ue=e=>{const t=O.get(e);if(t!==void 0)return t;const s=new Set(Object.keys(e).filter(i=>typeof e[i]=="object"&&e[i]!==null&&w(e[i])));return O.set(e,s),s},le=e=>{if(e.kind==="optional")return e._meta?.inner},ie=e=>{switch(e.kind){case"id":case"storage":case"string":return!0;case"literal":return typeof e._meta?.value=="string";case"union":return e._meta?.members?.every(s=>ie(s))??!1;default:return!1}},de={any:re,array:X,bigint:W,boolean:K,bytes:H,date:q,from:se,geoPoint:J,id:Y,literal:Q,null:G,number:M,object:N,optional:L,partial:te,record:Z,sensitive:v,storage:z,string:T,timestamp:B,union:ee};export{w as containsSensitive,oe as isOrWrapsFromValidator,ie as isStringValidator,le as optionalInner,ue as sensitiveArgumentNames,de as v};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/values",
3
- "version": "1.0.0-alpha.75",
3
+ "version": "1.0.0-alpha.77",
4
4
  "description": "Validators for Lunora: the v.* validator suite with end-to-end return-type inference",
5
5
  "keywords": [
6
6
  "cloudflare",
@@ -1 +0,0 @@
1
- const r=(e,t)=>{const i=(()=>{switch(t.kind(e)){case"any":return{};case"array":{const n=t.inner(e);return{items:n===void 0?{}:r(n,t),type:"array"}}case"bigint":return{format:"int64",type:"string"};case"boolean":return{type:"boolean"};case"bytes":return{contentEncoding:"base64",description:"binary (ArrayBuffer)",type:"string"};case"date":return{description:"epoch milliseconds (date)",type:"integer"};case"geoPoint":return{description:"geographic point (WGS84 decimal degrees)",properties:{lat:{maximum:90,minimum:-90,type:"number"},lng:{maximum:180,minimum:-180,type:"number"}},required:["lat","lng"],type:"object"};case"id":return{description:`Id<"${String(t.tableName(e))}">`,type:"string","x-lunora-table":t.tableName(e)};case"literal":return t.literalSchema(e);case"null":return{type:"null"};case"number":return{type:"number"};case"object":return u(t.shape(e),t);case"optional":{const n=t.inner(e);return n===void 0?{}:r(n,t)}case"record":{const n=t.valueChild(e),o=t.keyChild(e);return{additionalProperties:n===void 0?{}:r(n,t),...o===void 0?{}:{propertyNames:r(o,t)},type:"object"}}case"storage":return{description:"storage object key",type:"string","x-lunora-storage":!0};case"string":return{type:"string"};case"timestamp":return{description:"epoch milliseconds (timestamp)",type:"integer"};case"union":return{anyOf:t.members(e).map(n=>r(n,t))};default:return{}}})(),s=t.constraints(e),c=s===void 0?i:{...i,...s};return t.isNullable(e)?{anyOf:[c,{type:"null"}]}:c},a=(e,t)=>{const i=t.kind(e);return i==="any"||i==="optional"?!0:i==="union"&&t.members(e).some(s=>a(s,t))},u=(e,t)=>{const i={},s=[];for(const[c,n]of Object.entries(e))i[c]=r(n,t),a(n,t)||s.push(c);return{properties:i,required:s,type:"object"}};export{a as acceptsAbsent,r as jsonSchemaFromNode,u as objectSchemaFromNodes};
@@ -1 +0,0 @@
1
- import{objectSchemaFromNodes as n,jsonSchemaFromNode as s}from"./acceptsAbsent-Biqy6mRN.mjs";const r=e=>e,t=e=>r(e)._meta??{},a={constraints:e=>t(e).constraints,inner:e=>t(e).inner,isNullable:e=>t(e).column?.notNull===!1,keyChild:e=>t(e).keyValidator,kind:e=>e.kind,literalSchema:e=>{const{value:o}=t(e);return typeof o=="bigint"?{const:o.toString(),format:"int64",type:"string"}:{const:o}},members:e=>t(e).members,shape:e=>t(e).shape,tableName:e=>t(e).tableName,valueChild:e=>t(e).valueValidator},l=e=>s(e,a),m=e=>n(e,a);export{m as argsToJsonSchema,l as toJsonSchema};
@@ -1 +0,0 @@
1
- import{LunoraError as k}from"@lunora/errors";import{ValidationError as m,describeValue as y,formatPath as _}from"./ValidationError-BdVoGndu.mjs";const v=/^[^\s@]+@[^\s@.]+(?:\.[^\s@.]+)+$/u,O=e=>{if(!URL.canParse(e))return!1;const{protocol:r}=new URL(e);return r==="http:"||r==="https:"},$=new m("union branch probe miss (internal)",{expected:"",path:[],received:""});function u(e,r,s,i){if(e.probe===!0)throw $;const o=[...e.path],a=y(s,{literal:!i?.redactValue});throw new m(`Expected ${r} at ${_(o)}, received ${a}`,{expected:r,path:o,received:a})}const S=(e,r)=>{if(r===void 0)return e;const s=e?.constraints;return{...e,constraints:{...s,...r}}},l=(e,r,s)=>{const i=s?.column??{notNull:!0},o={__type:void 0,"~standard":{validate(n){const t=o.safeParse(n);return t.ok?{value:t.value}:{issues:[{message:t.error.message,path:t.error.path}]}},vendor:"lunora",version:1},_meta:{...s,column:i},_parse(n,t){return r(n,t)},kind:e,parse(n,t){return r(n,{path:[],...t})},safeParse(n,t){try{return{ok:!0,value:r(n,{path:[],...t})}}catch(c){if(c instanceof m)return{error:c,ok:!1};throw c}}},a=n=>l(e,r,{...s,column:{...i,...n}});switch(o.default=n=>a({defaultValue:n}),o.defaultNow=()=>a({defaultFn:()=>Date.now()}),o.unique=()=>a({unique:!0}),o.$defaultFn=n=>a({defaultFn:n}),o.$onUpdateFn=n=>a({onUpdateFn:n}),o.serverDefault=n=>a({serverDefault:n}),o.$type=(()=>a({})),o.nullable=()=>l(e,(t,c)=>t===null?null:r(t,c),{...s,column:{...i,notNull:!1}}),o.check=(n,t)=>{const c=typeof t=="string"?t:t?.message,f=typeof t=="string"?void 0:t?.schema;return l(e,(p,b)=>{const w=r(p,b);return n(w)||u(b,c??"value matching refinement",w,{redactValue:!0}),w},S(s,f))},o.meta=n=>{const t=n.description===void 0?n.schema:{description:n.description,...n.schema};return l(e,r,S(s,t))},e){case"array":{const n=o;n.min=t=>n.check(c=>c.length>=t,{message:`expected array length >= ${String(t)}`,schema:{minItems:t}}),n.max=t=>n.check(c=>c.length<=t,{message:`expected array length <= ${String(t)}`,schema:{maxItems:t}});break}case"number":{const n=o;n.min=t=>n.check(c=>c>=t,{message:`expected number >= ${String(t)}`,schema:{minimum:t}}),n.max=t=>n.check(c=>c<=t,{message:`expected number <= ${String(t)}`,schema:{maximum:t}}),n.int=()=>n.check(t=>Number.isInteger(t),{message:"expected an integer",schema:{type:"integer"}}),n.positive=()=>n.check(t=>t>0,{message:"expected a positive number",schema:{exclusiveMinimum:0}});break}case"string":{const n=o;n.min=t=>n.check(c=>c.length>=t,{message:`expected string length >= ${String(t)}`,schema:{minLength:t}}),n.max=t=>n.check(c=>c.length<=t,{message:`expected string length <= ${String(t)}`,schema:{maxLength:t}}),n.length=t=>n.check(c=>c.length===t,{message:`expected string length === ${String(t)}`,schema:{maxLength:t,minLength:t}}),n.pattern=t=>{const c=t.global||t.sticky?new RegExp(t.source,t.flags.replaceAll(/[gy]/gu,"")):t;return n.check(f=>c.test(f),{message:`expected string matching ${t.toString()}`,schema:{pattern:t.source}})},n.email=()=>n.check(t=>v.test(t),{message:"expected a valid email address",schema:{format:"email"}}),n.url=()=>n.check(t=>O(t),{message:"expected a valid URL",schema:{format:"uri"}});break}}return o},g=e=>e,h=e=>e,I=e=>e,N=e=>e,V=e=>e,L=()=>I(l("string",(e,r)=>(typeof e!="string"&&u(r,"string",e),e))),j=(e,r)=>((typeof e!="number"||!Number.isFinite(e))&&u(r,"number",e),e),E=()=>N(l("number",j)),R=()=>l("timestamp",j),F=()=>l("date",j),U=()=>h(l("boolean",(e,r)=>(typeof e!="boolean"&&u(r,"boolean",e),e))),T=()=>h(l("bigint",(e,r)=>(typeof e!="bigint"&&u(r,"bigint",e),e))),C=()=>h(l("null",(e,r)=>(e!==null&&u(r,"null",e),e))),D=()=>h(l("bytes",(e,r)=>ArrayBuffer.isView(e)?e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength):(e instanceof ArrayBuffer||u(r,"ArrayBuffer",e),e))),B=e=>h(l("id",(r,s)=>(typeof r!="string"&&u(s,`Id<"${e}">`,r),r),{tableName:e})),q=e=>h(l("storage",(r,s)=>(typeof r!="string"&&u(s,"storage object key (string)",r),r),e===void 0?void 0:{bucket:e})),M=()=>h(l("geoPoint",(e,r)=>{(typeof e!="object"||e===null||Array.isArray(e))&&u(r,"geoPoint { lat, lng }",e);const s=e,{lat:i,lng:o}=s;return(typeof i!="number"||!Number.isFinite(i)||i<-90||i>90)&&(r.path.push("lat"),u(r,"latitude in [-90, 90]",i)),(typeof o!="number"||!Number.isFinite(o)||o<-180||o>180)&&(r.path.push("lng"),u(r,"longitude in [-180, 180]",o)),{lat:i,lng:o}})),x=e=>h(l("literal",(r,s)=>(r!==e&&u(s,`literal(${String(e)})`,r),r),{value:e})),K=e=>{const r=g(e);return V(l("array",(s,i)=>{Array.isArray(s)||u(i,"array",s);const{length:o}=s,a=[],{path:n}=i;for(let t=0;t<o;t+=1)n.push(t),a.push(r._parse(s[t],i)),n.pop();return a},{inner:e}))},A=(e,r)=>{const s=Object.keys(e).map(o=>{const a=g(e[o]);return{child:a,isOptional:a.kind==="optional",key:o}});if(s.some(({key:o})=>o==="__proto__"))throw new k("INTERNAL",'v.object: "__proto__" cannot be a declared field name — it collides with the Object.prototype accessor');const i=h(l("object",(o,a)=>{(typeof o!="object"||o===null||Array.isArray(o))&&u(a,"object",o);const n=o,t={},{path:c}=a;if(a.rejectUnknownKeys===!0&&r!==!0){const f=new Set(s.map(({key:p})=>p)),d=Object.keys(n).filter(p=>!f.has(p));if(d.length>0)throw new m(`object has ${String(d.length)} undeclared key(s): ${d.join(", ")}. Add them to the validator, or call .strip() on it to drop them on purpose.`,{expected:`only the declared keys (${s.map(({key:p})=>p).join(", ")})`,path:[...c],received:d.join(", ")})}for(const{child:f,isOptional:d,key:p}of s){const b=Object.hasOwn(n,p)?n[p]:void 0;b===void 0&&d||(c.push(p),t[p]=f._parse(b,a),c.pop())}return t},{shape:e}));return i.strip=()=>A(e,!0),i},W=(e,r)=>{const s=g(e),i=g(r);return h(l("record",(o,a)=>{(typeof o!="object"||o===null||Array.isArray(o))&&u(a,"record",o);const n=o,t=Object.create(null),{path:c}=a;for(const f of Object.keys(n)){c.push(f);const d=s._parse(f,a),p=i._parse(n[f],a);c.pop(),t[d]=p}return t},{keyValidator:e,valueValidator:r}))},z=(e,r,s,i)=>{const{path:o}=s;let a;const n=y(r,{literal:!1});let t=!1;for(const f of e)try{f._parse(r,s)}catch(d){if(!(d instanceof m))throw d;o.length=i,t||=d.received===n,(a===void 0||d.path.length>a.path.length)&&(a=d)}if(e.length===1&&a!==void 0)throw a;const c=a===void 0?"":` (closest: expected ${a.expected} at ${_(a.path)})`;return u(s,`union of ${String(e.length)} member(s)${c}`,r,{redactValue:t})},G=(...e)=>{if(e.length===0)throw new k("INTERNAL","v.union requires at least one member");const r=e.map(s=>g(s));return h(l("union",(s,i)=>{const{path:o}=i,a=o.length,n=i.probe===!0;i.probe=!0;try{for(const t of r)try{return t._parse(s,i)}catch(c){if(!(c instanceof m))throw c;o.length=a}}finally{i.probe=n}if(n)throw $;return z(r,s,i,a)},{members:e}))},P=e=>{const r=g(e);return h(l("optional",(s,i)=>s===void 0?void 0:r._parse(s,i),{inner:e}))},H=e=>Object.fromEntries(Object.entries(e).map(([r,s])=>[r,g(s).kind==="optional"?s:P(s)])),J=()=>h(l("any",e=>e)),Q=e=>{const r=[];if(!e)return r;for(const s of e){const i=typeof s=="object"&&s!==null&&"key"in s?s.key:s;(typeof i=="string"||typeof i=="number")&&r.push(i)}return r},X=e=>{const r=e["~standard"];if(r?.version!==1||typeof r.validate!="function")throw new k("INTERNAL",'@lunora/values: v.from() expects a Standard Schema v1 object (missing or invalid "~standard")');const s=r.validate;return h(l("from",(i,o)=>{const a=s(i);if(a instanceof Promise||typeof a?.then=="function")throw new m("v.from(): async Standard Schema validators are not supported in args",{expected:"sync Standard Schema result",path:[...o.path],received:"Promise"});const n=a;if(n===null||typeof n!="object")throw new m("v.from(): Standard Schema validator returned a non-object result",{expected:"Standard Schema result object",path:[...o.path],received:y(n)});const t=a;if(t.issues!==void 0){const c=t.issues[0],f=c?.message??"Standard Schema validation failed";throw new m(f,{expected:"valid value",path:[...o.path,...Q(c?.path)],received:y(i)})}return t.value}))},Y=e=>{if(e.kind==="from")return!0;const r=e._meta;if(!r)return!1;const s=[r.inner,r.keyValidator,r.valueValidator];Array.isArray(r.members)&&s.push(...r.members),r.shape!==null&&typeof r.shape=="object"&&s.push(...Object.values(r.shape));for(const i of s)if(i!==null&&typeof i=="object"&&"kind"in i&&Y(i))return!0;return!1},re=e=>{if(e.kind==="optional")return e._meta?.inner},Z=e=>{switch(e.kind){case"id":case"storage":case"string":return!0;case"literal":return typeof e._meta?.value=="string";case"union":return e._meta?.members?.every(s=>Z(s))??!1;default:return!1}},ne={any:J,array:K,bigint:T,boolean:U,bytes:D,date:F,from:X,geoPoint:M,id:B,literal:x,null:C,number:E,object:A,optional:P,partial:H,record:W,storage:q,string:L,timestamp:R,union:G};export{Y as isOrWrapsFromValidator,Z as isStringValidator,re as optionalInner,ne as v};