@lunora/values 1.0.0-alpha.40 → 1.0.0-alpha.42

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
@@ -521,7 +521,7 @@ interface JsonSchema {
521
521
  * no runtime metadata — so `constraints`/`isNullable` may be inert there).
522
522
  *
523
523
  * A reader normalizes a `TNode` to the small set of children/leaves the mapper
524
- * recurses over. Composite accessors (`inner`/`shape`/`members`/`valueChild`)
524
+ * recurses over. Composite accessors (`inner`/`shape`/`members`/`keyChild`/`valueChild`)
525
525
  * return the same `TNode` type so the mapper can recurse uniformly; leaf concerns
526
526
  * that differ between the two sources — how a literal's `const` is computed,
527
527
  * whether a `.check()`/`.meta()` constraint fragment exists, whether `.nullable()`
@@ -539,6 +539,12 @@ interface SchemaNodeReader<TNode> {
539
539
  inner: (node: TNode) => TNode | undefined;
540
540
  /** Whether `.nullable()` was applied (runtime: `_meta.column.notNull === false`). */
541
541
  isNullable: (node: TNode) => boolean;
542
+ /**
543
+ * Key-child of a `record` node, mapped to `propertyNames`. May be absent on
544
+ * the IR side (and on a `v.record(v.string(), …)` whose key validator adds
545
+ * no constraint beyond `type: "string"` it is merely redundant, not wrong).
546
+ */
547
+ keyChild: (node: TNode) => TNode | undefined;
542
548
  /** Discriminating validator kind. */
543
549
  kind: (node: TNode) => ValidatorKind;
544
550
  /**
@@ -563,10 +569,13 @@ interface SchemaNodeReader<TNode> {
563
569
  * so nested objects/arrays/unions/records are fully expanded (never collapsed to
564
570
  * one level).
565
571
  *
566
- * `date`/`timestamp` are epoch-millisecond numbers in Lunora (not ISO strings),
567
- * so they schema as integers; `bigint` schemas as an int64 (JSON has no bigint
568
- * type, so `format: int64` is the conventional OpenAPI carrier); `bytes` is an
569
- * `ArrayBuffer`, surfaced as base64 per JSON Schema 2020-12 content encoding.
572
+ * Each node names the JSON CARRIER, not the decoded JS type — the transport
573
+ * decodes before the parser sees a value, so describing the JS type would
574
+ * advertise shapes no JSON body can hold. `date`/`timestamp` are
575
+ * epoch-millisecond numbers in Lunora (not ISO strings), so they schema as
576
+ * integers; `bigint` rides as an int64 decimal string, the same carrier the
577
+ * wire codec and `v.literal(5n)` use; `bytes` is an `ArrayBuffer`, surfaced as
578
+ * base64 per JSON Schema 2020-12 content encoding.
570
579
  *
571
580
  * A `.check()`/`.meta()` JSON Schema fragment (when the reader exposes one) is
572
581
  * shallow-merged onto the node — constraint keys win on conflict. A `.nullable()`
@@ -575,9 +584,16 @@ interface SchemaNodeReader<TNode> {
575
584
  */
576
585
  declare const jsonSchemaFromNode: <TNode>(node: TNode, reader: SchemaNodeReader<TNode>) => JsonSchema;
577
586
  /**
578
- * Build `{ type: "object", properties, required, additionalProperties: false }`
579
- * from a node shape. A `v.optional(...)` property is the only thing that drops
580
- * out of `required`; every other property is required.
587
+ * Build `{ type: "object", properties, required }` from a node shape.
588
+ *
589
+ * Deliberately NOT `additionalProperties: false`: `v.object` STRIPS an
590
+ * undeclared key rather than refusing it (only `.output()`'s
591
+ * `rejectUnknownKeys` mode refuses one, and it is not what this schema
592
+ * describes), so closing the object had a spec-validating client reject bodies
593
+ * the server accepts. Absent means allowed, which is what the parser does.
594
+ *
595
+ * `required` lists every key whose field cannot be absent — see
596
+ * {@link acceptsAbsent}.
581
597
  */
582
598
  declare const objectSchemaFromNodes: <TNode>(shape: Record<string, TNode>, reader: SchemaNodeReader<TNode>) => JsonSchema;
583
599
  /**
package/dist/index.d.ts CHANGED
@@ -521,7 +521,7 @@ interface JsonSchema {
521
521
  * no runtime metadata — so `constraints`/`isNullable` may be inert there).
522
522
  *
523
523
  * A reader normalizes a `TNode` to the small set of children/leaves the mapper
524
- * recurses over. Composite accessors (`inner`/`shape`/`members`/`valueChild`)
524
+ * recurses over. Composite accessors (`inner`/`shape`/`members`/`keyChild`/`valueChild`)
525
525
  * return the same `TNode` type so the mapper can recurse uniformly; leaf concerns
526
526
  * that differ between the two sources — how a literal's `const` is computed,
527
527
  * whether a `.check()`/`.meta()` constraint fragment exists, whether `.nullable()`
@@ -539,6 +539,12 @@ interface SchemaNodeReader<TNode> {
539
539
  inner: (node: TNode) => TNode | undefined;
540
540
  /** Whether `.nullable()` was applied (runtime: `_meta.column.notNull === false`). */
541
541
  isNullable: (node: TNode) => boolean;
542
+ /**
543
+ * Key-child of a `record` node, mapped to `propertyNames`. May be absent on
544
+ * the IR side (and on a `v.record(v.string(), …)` whose key validator adds
545
+ * no constraint beyond `type: "string"` it is merely redundant, not wrong).
546
+ */
547
+ keyChild: (node: TNode) => TNode | undefined;
542
548
  /** Discriminating validator kind. */
543
549
  kind: (node: TNode) => ValidatorKind;
544
550
  /**
@@ -563,10 +569,13 @@ interface SchemaNodeReader<TNode> {
563
569
  * so nested objects/arrays/unions/records are fully expanded (never collapsed to
564
570
  * one level).
565
571
  *
566
- * `date`/`timestamp` are epoch-millisecond numbers in Lunora (not ISO strings),
567
- * so they schema as integers; `bigint` schemas as an int64 (JSON has no bigint
568
- * type, so `format: int64` is the conventional OpenAPI carrier); `bytes` is an
569
- * `ArrayBuffer`, surfaced as base64 per JSON Schema 2020-12 content encoding.
572
+ * Each node names the JSON CARRIER, not the decoded JS type — the transport
573
+ * decodes before the parser sees a value, so describing the JS type would
574
+ * advertise shapes no JSON body can hold. `date`/`timestamp` are
575
+ * epoch-millisecond numbers in Lunora (not ISO strings), so they schema as
576
+ * integers; `bigint` rides as an int64 decimal string, the same carrier the
577
+ * wire codec and `v.literal(5n)` use; `bytes` is an `ArrayBuffer`, surfaced as
578
+ * base64 per JSON Schema 2020-12 content encoding.
570
579
  *
571
580
  * A `.check()`/`.meta()` JSON Schema fragment (when the reader exposes one) is
572
581
  * shallow-merged onto the node — constraint keys win on conflict. A `.nullable()`
@@ -575,9 +584,16 @@ interface SchemaNodeReader<TNode> {
575
584
  */
576
585
  declare const jsonSchemaFromNode: <TNode>(node: TNode, reader: SchemaNodeReader<TNode>) => JsonSchema;
577
586
  /**
578
- * Build `{ type: "object", properties, required, additionalProperties: false }`
579
- * from a node shape. A `v.optional(...)` property is the only thing that drops
580
- * out of `required`; every other property is required.
587
+ * Build `{ type: "object", properties, required }` from a node shape.
588
+ *
589
+ * Deliberately NOT `additionalProperties: false`: `v.object` STRIPS an
590
+ * undeclared key rather than refusing it (only `.output()`'s
591
+ * `rejectUnknownKeys` mode refuses one, and it is not what this schema
592
+ * describes), so closing the object had a spec-validating client reject bodies
593
+ * the server accepts. Absent means allowed, which is what the parser does.
594
+ *
595
+ * `required` lists every key whose field cannot be absent — see
596
+ * {@link acceptsAbsent}.
581
597
  */
582
598
  declare const objectSchemaFromNodes: <TNode>(shape: Record<string, TNode>, reader: SchemaNodeReader<TNode>) => JsonSchema;
583
599
  /**
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{jsonSchemaFromNode as p,objectSchemaFromNodes as i}from"./packem_shared/jsonSchemaFromNode-DtU81nPr.mjs";import{argsToJsonSchema as l,toJsonSchema as d}from"./packem_shared/argsToJsonSchema-ujumcrdC.mjs";import{isOrWrapsFromValidator as c,optionalInner as f,v as V}from"./packem_shared/isOrWrapsFromValidator-Drhf5Ake.mjs";import{DEFER_VALIDATION as x,installCompiledValidatorMap as F,parseValidatorMap as S}from"./packem_shared/DEFER_VALIDATION-C0nIiPG-.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};
1
+ import{ValidationError as a,describeValue as e,formatPath as t}from"./packem_shared/ValidationError-BdVoGndu.mjs";import{jsonSchemaFromNode as p,objectSchemaFromNodes as i}from"./packem_shared/jsonSchemaFromNode-BSWBXSLL.mjs";import{argsToJsonSchema as l,toJsonSchema as d}from"./packem_shared/argsToJsonSchema-BN05tFLL.mjs";import{isOrWrapsFromValidator as c,optionalInner as f,v as V}from"./packem_shared/isOrWrapsFromValidator-Drhf5Ake.mjs";import{DEFER_VALIDATION as x,installCompiledValidatorMap as F,parseValidatorMap as S}from"./packem_shared/DEFER_VALIDATION-C0nIiPG-.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{objectSchemaFromNodes as n,jsonSchemaFromNode as s}from"./jsonSchemaFromNode-BSWBXSLL.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};
@@ -0,0 +1 @@
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{r as jsonSchemaFromNode,u as objectSchemaFromNodes};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/values",
3
- "version": "1.0.0-alpha.40",
3
+ "version": "1.0.0-alpha.42",
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.32",
49
+ "@lunora/errors": "1.0.0-alpha.34",
50
50
  "@standard-schema/spec": "1.1.0"
51
51
  },
52
52
  "engines": {
@@ -1 +0,0 @@
1
- import{objectSchemaFromNodes as a,jsonSchemaFromNode as s}from"./jsonSchemaFromNode-DtU81nPr.mjs";const r=e=>e,t=e=>r(e)._meta??{},n={constraints:e=>t(e).constraints,inner:e=>t(e).inner,isNullable:e=>t(e).column?.notNull===!1,kind:e=>e.kind,literalSchema:e=>{const{value:o}=t(e);return typeof o=="bigint"?{const:o.toString(),type:"string"}:{const:o}},members:e=>t(e).members,shape:e=>t(e).shape,tableName:e=>t(e).tableName,valueChild:e=>t(e).valueValidator},m=e=>s(e,n),i=e=>a(e,n);export{i as argsToJsonSchema,m as toJsonSchema};
@@ -1 +0,0 @@
1
- const o=(e,t)=>{const i=(()=>{switch(t.kind(e)){case"any":return{};case"array":{const n=t.inner(e);return{items:n===void 0?{}:o(n,t),type:"array"}}case"bigint":return{format:"int64",type:"integer"};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 c(t.shape(e),t);case"optional":{const n=t.inner(e);return n===void 0?{}:o(n,t)}case"record":{const n=t.valueChild(e);return{additionalProperties:n===void 0?{}:o(n,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=>o(n,t))};default:return{}}})(),r=t.constraints(e),s=r===void 0?i:{...i,...r};return t.isNullable(e)?{anyOf:[s,{type:"null"}]}:s},c=(e,t)=>{const i={},r=[];for(const[s,n]of Object.entries(e))i[s]=o(n,t),t.kind(n)!=="optional"&&r.push(s);return{additionalProperties:!1,properties:i,required:r,type:"object"}};export{o as jsonSchemaFromNode,c as objectSchemaFromNodes};