@adhd/apigen-base-logical 0.1.0 โ†’ 0.1.1

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/CHANGELOG.md CHANGED
@@ -1,3 +1,25 @@
1
+ ## 0.1.1 (2026-08-07)
2
+
3
+
4
+ ### ๐Ÿš€ Features
5
+
6
+ - **apigen:** schema-driven worked examples for MCP tool descriptions + validation errors
7
+
8
+ - **apigen-base-logical:** fill JAVA_COLUMN codec expressions (FEAT-APIGEN-001 1/3)
9
+
10
+
11
+ ### ๐Ÿฉน Fixes
12
+
13
+ - **apigen-java:** mirror PYTHON_MATRIX_SCRIPT's decode+invariant-diff negative-control algorithm exactly (FEAT-APIGEN-001 review)
14
+
15
+ - **apigen-cli:** restore 2768 files mass-deleted by 0117eb22 (BUG-APIGEN-052)
16
+
17
+
18
+ ### โค๏ธ Thank You
19
+
20
+ - parity-harness-self-test
21
+ - pseudosky
22
+
1
23
  ## 0.0.6 (2026-07-25)
2
24
 
3
25
 
package/README.md CHANGED
@@ -34,3 +34,39 @@ The `x-apigen-*` descriptor keys are **optional** dispatch accelerators โ€”
34
34
  structure (`format`/`$ref`/`oneOf`) is authoritative. `logicalKindOf` and
35
35
  `codecIdOf` therefore return `undefined` (never throw) when a key is absent or
36
36
  malformed; correctness must never depend on a hint being present.
37
+
38
+ ## Schema example synthesis (shipped, unlike the contract-spine surface above)
39
+
40
+ `synthesizeExample(schema)` / `renderExampleNote(schema)` โ€” generates a
41
+ concrete, plausible example value from any JSON Schema: walks `properties`/
42
+ `required`, resolves `$ref` against the schema's own `definitions`/`$defs`,
43
+ picks a `oneOf`/`anyOf` branch, merges `allOf`, and produces format-aware
44
+ placeholders (`date-time`, `uuid`, `email`, `decimal`, `int64`, `byte`, etc.)
45
+ that satisfy `ajv-formats`. Every synthesized shape round-trips through real
46
+ AJV validation in this package's own tests.
47
+
48
+ This exists to solve a concrete discoverability problem: an apigen-mounted
49
+ MCP tool's description/error used to only describe the *shape* of a valid
50
+ call ("all domain parameters go inside a `data` envelope"), never a *worked
51
+ example* with real field names โ€” so callers repeatedly got the call shape
52
+ wrong on the first try. `renderExampleNote` is consumed by:
53
+
54
+ - `@adhd/apigen-engine-runtime`'s `buildToolDescription` โ€” appends a
55
+ synthesized example to every apigen-mounted tool's description.
56
+ - `@adhd/apigen-engine-runtime`'s validate-Layer โ€” appends the same
57
+ synthesized example to AJV validation-failure error messages, so a
58
+ rejected call comes back with both what was wrong *and* a working example.
59
+
60
+ Because synthesis is schema-driven (not hand-written per tool), it covers
61
+ every current and future apigen-mounted MCP tool automatically, including
62
+ mount-derived tools (e.g. `apigen-plugin-batch`'s `_batch/<kind>` mounts)
63
+ whose top-level shape differs from the `{data:{...}}` envelope regular
64
+ extracted operations use โ€” the synthesized example always reflects each
65
+ tool's own real, advertised schema, never an assumed universal convention.
66
+
67
+ ```ts
68
+ import { renderExampleNote } from '@adhd/apigen-base-logical';
69
+
70
+ renderExampleNote(someOperation.input);
71
+ // โ†’ 'Example: {"data":{"input":{"family":"<string>","title":"<string>","body":"<string>","repo":"<string>"}}}'
72
+ ```
package/index.d.ts CHANGED
@@ -6,5 +6,7 @@ export { X_APIGEN_LOGICAL, X_APIGEN_CODEC, X_APIGEN_CTOR, X_APIGEN_TOJSON, LOGIC
6
6
  export { buildTranscoder, tryRegister, validateSchemaRefs } from './lib/runmode';
7
7
  export { dateTimeCodec, int64Codec, decimalCodec, makeDecimal, byteCodec, uuidCodec, numberSpecialCodec, registerWellKnown, } from './lib/codecs/index';
8
8
  export type { DecimalString } from './lib/codecs/index';
9
+ export { synthesizeExample, renderExampleNote } from './lib/example';
10
+ export type { JsonSchemaLike } from './lib/example';
9
11
  export { CANONICAL_LOGICAL_TYPE_IDS, TEMPLATE_CELLS, cellsFor, depsForLogicalTypes, tsDepMap, assertNoEmptyCells, } from './lib/hints';
10
12
  export type { CanonicalLogicalTypeId, HostLanguage, LanguageTable, } from './lib/hints';
package/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l="$apigen";class C extends Error{constructor(o){super(o),this.code="E_DUP_CODEC",this.name="CodecRegistryError"}}function P(e){e==null||e.wellKnown;const o=new Map;return{register(n,r){if(o.has(n.id)&&!(r!=null&&r.override))throw new C(`E_DUP_CODEC: a codec is already registered for id "${n.id}"`);o.set(n.id,n)},resolve(n){for(const r of o.values())if(r.matches(n))return r},get(n){return o.get(n)},ids(){return[...o.keys()]},freeze(){const n=new Map(o),r={register(){throw new C("E_DUP_CODEC: registry is frozen and cannot accept new codecs")},resolve(d){for(const a of n.values())if(a.matches(d))return a},get(d){return n.get(d)},ids(){return[...n.keys()]},freeze(){return r}};return r}}}const $="x-apigen-logical",v="x-apigen-codec",j="x-apigen-ctor",M="x-apigen-tojson",R="0.1.0",G=["scalar","nominal","union","map","set"];function w(e){const o=e[$];return typeof o=="string"&&G.includes(o)?o:void 0}function B(e){const o=e[v];return typeof o=="string"?o:void 0}function T(e,o){return{registry:e,resolve:t=>{throw new Error(`[apigen-logical] $ref "${t}" cannot be resolved in run-mode without a descriptor root. Supply a resolve() in the ctx override to handle $ref.`)},seen:new WeakSet,path:"",mode:"strict",...o}}function p(e,o,t){const n=t.registry.resolve(o);if(n)return n.encode(e,o,t);const r=o.$ref;if(typeof r=="string"){const i=t.resolve(r);return p(e,i,t)}const d=o.oneOf;if(Array.isArray(d)){const i=U(e,d,o);return p(e,i,t)}const a=o.type;if(a==="array"){if(!Array.isArray(e))return D(e,o,t);const i=o.items;if(!i)return e.map(c=>u(c));const f=t.path;return Array.isArray(i)?e.map((c,_)=>{const s=i[_];return s===void 0?u(c):p(c,s,{...t,path:`${f}/${_}`})}):e.map((c,_)=>p(c,i,{...t,path:`${f}/${_}`}))}if(a==="object"){if(e===null||typeof e!="object"||Array.isArray(e))return D(e,o,t);const i=o.properties;if(!i)return u(e);const f=t.path,c={};for(const[_,s]of Object.entries(i)){const m=e[_];m!==void 0&&(c[_]=p(m,s,{...t,path:`${f}/${_}`}))}return c}return a==null?D(e,o,t):u(e)}function E(e,o,t){const n=t.registry.resolve(o);if(n)return n.decode(e,o,t);const r=o.$ref;if(typeof r=="string"){const i=t.resolve(r);return E(e,i,t)}const d=o.oneOf;if(Array.isArray(d)){const i=U(e,d,o);return E(e,i,t)}const a=o.type;if(a==="array"){if(!Array.isArray(e))return e;const i=o.items;if(!i)return e;const f=t.path;return Array.isArray(i)?e.map((c,_)=>{const s=i[_];return s===void 0?c:E(c,s,{...t,path:`${f}/${_}`})}):e.map((c,_)=>E(c,i,{...t,path:`${f}/${_}`}))}if(a==="object"){if(e===null||typeof e!="object"||Array.isArray(e))return e;const i=o.properties;if(!i)return e;const f=t.path,c={};for(const[_,s]of Object.entries(i)){const m=e[_];m!==void 0&&(c[_]=E(m,s,{...t,path:`${f}/${_}`}))}return c}return a==null?k(e,t):e}function U(e,o,t,n){const r=t.discriminator;if(r!=null&&r.propertyName){const d=e!==null&&typeof e=="object"?e[r.propertyName]:void 0;if(typeof d=="string"&&r.mapping){const a=r.mapping[d];if(a){const i=o.find(f=>f.$ref===a);if(i)return i}}}return o[0]??{}}function D(e,o,t){for(const n of t.registry.ids()){const r=t.registry.get(n);if(r)try{const d=r.encode(e,r.schema,t);return{[l]:n,v:d}}catch{}}return u(e)}function k(e,o){if(e!==null&&typeof e=="object"&&!Array.isArray(e)&&l in e){const t=e,n=t[l],r=o.registry.get(n);if(r)return r.decode(t.v,r.schema,o)}return e}function u(e){if(e===null||typeof e=="string"||typeof e=="number"||typeof e=="boolean")return e;if(Array.isArray(e))return e.map(u);if(typeof e=="object"){const o={};for(const[t,n]of Object.entries(e))n!==void 0&&(o[t]=u(n));return o}return null}function J(e,o){const t=new Set,n=[e];for(;n.length>0;){const r=n.pop();if(!r||t.has(r))continue;t.add(r);const d=r.$ref;if(typeof d=="string"){if(o){const s=o[d];if(!s){const m=Object.keys(o).join(", ")||"(none)";throw new Error(`[apigen-logical] $ref "${d}" cannot be resolved. Available $defs: ${m}`)}n.push(s)}continue}const a=r.oneOf;if(Array.isArray(a))for(const s of a)typeof s=="object"&&s!==null&&n.push(s);const i=r.properties;if(i)for(const s of Object.values(i))n.push(s);const f=r.items;if(Array.isArray(f))for(const s of f)typeof s=="object"&&s!==null&&n.push(s);else typeof f=="object"&&f!==null&&n.push(f);const c=r.additionalProperties;typeof c=="object"&&c!==null&&n.push(c);const _=r.propertyNames;typeof _=="object"&&_!==null&&n.push(_)}}function V(e){return{encode(o,t,n){const r=T(e,n);return p(o,t,r)},decode(o,t,n){const r=T(e,n);return E(o,t,r)}}}function Y(e,o,t){try{const n=t();e.register(n)}catch(n){if(K(n))return;throw n}}function K(e){return e===null||typeof e!="object"?!1:e.code==="MODULE_NOT_FOUND"}const h={id:"date-time",kind:"scalar",schema:{type:"string",format:"date-time"},matches(e){return e.type==="string"&&e.format==="date-time"},encode(e,o,t){return e.toISOString()},decode(e,o,t){if(typeof e!="string"){if(t.mode==="strict")throw new TypeError(`[date-time] expected a string on the wire at "${t.path}", got ${typeof e}`);return new Date(String(e))}if(t.mode==="strict"&&Number.isNaN(new Date(e).getTime()))throw new TypeError(`[date-time] invalid date-time string at "${t.path}": ${JSON.stringify(e)}`);return new Date(e)}},S={id:"int64",kind:"scalar",schema:{type:"string",format:"int64"},matches(e){return e.type==="string"&&e.format==="int64"},encode(e,o,t){return String(e)},decode(e,o,t){if(typeof e!="string"){if(t.mode==="strict")throw new TypeError(`[int64] expected a string on the wire at "${t.path}", got ${typeof e}`);try{return BigInt(Math.trunc(Number(e)))}catch{return BigInt(0)}}if(t.mode==="strict")return BigInt(e);if(/^-?\d+$/.test(e))try{return BigInt(e)}catch{return BigInt(0)}return BigInt(0)}};function W(e){return e}const N={id:"decimal",kind:"scalar",schema:{type:"string",format:"decimal"},matches(e){return e.type==="string"&&e.format==="decimal"},encode(e,o,t){return e},decode(e,o,t){if(typeof e!="string"){if(t.mode==="strict")throw new TypeError(`[decimal] expected a string on the wire at "${t.path}", got ${typeof e}`);return String(e)}if(t.mode==="strict"&&!/^-?\d+(\.\d+)?$/.test(e))throw new TypeError(`[decimal] wire value "${e}" at "${t.path}" is not a valid decimal string`);return e}},b={id:"byte",kind:"scalar",schema:{type:"string",format:"byte"},matches(e){return e.type==="string"&&e.format==="byte"},encode(e,o,t){return Buffer.from(e).toString("base64")},decode(e,o,t){if(typeof e!="string"){if(t.mode==="strict")throw new TypeError(`[byte] expected a base64 string on the wire at "${t.path}", got ${typeof e}`);return new Uint8Array(0)}if(t.mode==="strict"&&!/^[A-Za-z0-9+/]*={0,2}$/.test(e))throw new TypeError(`[byte] wire value at "${t.path}" is not standard base64 (format:byte): "${e}"`);return new Uint8Array(Buffer.from(e,"base64"))}},z=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,L={id:"uuid",kind:"scalar",schema:{type:"string",format:"uuid"},matches(e){return e.type==="string"&&e.format==="uuid"},encode(e,o,t){return e.toLowerCase()},decode(e,o,t){if(typeof e!="string"){if(t.mode==="strict")throw new TypeError(`[uuid] expected a string on the wire at "${t.path}", got ${typeof e}`);return String(e).toLowerCase()}if(t.mode==="strict"&&!z.test(e))throw new TypeError(`[uuid] wire value "${e}" at "${t.path}" is not a lowercase-hyphenated RFC 4122 UUID`);return e}},O="NaN",A="Infinity",g="-Infinity",X=new Set([O,A,g]),F={id:"number-special",kind:"scalar",schema:{type:"number"},matches(e){return e.type==="number"&&e.format===void 0},encode(e,o,t){return Number.isNaN(e)?O:e===1/0?A:e===-1/0?g:e},decode(e,o,t){if(typeof e=="number")return e;if(typeof e=="string"){if(e===O)return NaN;if(e===A)return 1/0;if(e===g)return-1/0;const n=Number(e);if(!Number.isNaN(n))return n}if(t.mode==="strict")throw new TypeError(`[number-special] unrecognized wire value at "${t.path}": ${JSON.stringify(e)}. Expected a number or one of ${[...X].join(", ")}.`);return NaN}},H=[h,S,N,b,L,F];function Z(e,o={}){for(const t of H)e.register(t,{override:o.override??!1})}const I=[h.id,S.id,N.id,b.id,L.id,F.id],q={"date-time":{encode:"$.toISOString()",decode:"new Date($)",mode:"native"},int64:{encode:"String($)",decode:"BigInt($)",mode:"native"},decimal:{encode:"$.toString()",decode:"new Decimal($)",imports:[],dep:{name:"decimal.js",version:"^10"},mode:"branded"},byte:{encode:"Buffer.from($).toString('base64')",decode:"new Uint8Array(Buffer.from($, 'base64'))",mode:"native"},uuid:{encode:"$.toLowerCase()",decode:"$",mode:"native"},"number-special":{encode:"numToWire($)",decode:"wireToNum($)",mode:"native"}},Q={"date-time":{encode:"$.isoformat()",decode:"datetime.fromisoformat($)",imports:["from datetime import datetime"],mode:"native"},int64:{encode:"str($)",decode:"int($)",mode:"native"},decimal:{encode:"str($)",decode:"Decimal($)",imports:["from decimal import Decimal"],mode:"native"},byte:{encode:"b64encode($).decode()",decode:"b64decode($)",imports:["from base64 import b64encode, b64decode"],mode:"native"},uuid:{encode:"str($)",decode:"UUID($)",imports:["from uuid import UUID"],mode:"native"},"number-special":{encode:"num_to_wire($)",decode:"wire_to_num($)",mode:"native"}},x={"date-time":{encode:"__SCAFFOLD_RUST_DATETIME_ENCODE__",decode:"__SCAFFOLD_RUST_DATETIME_DECODE__",imports:["use chrono::{DateTime, Utc};"],dep:{name:"chrono",version:"^0.4"},mode:"lib"},int64:{encode:"__SCAFFOLD_RUST_INT64_ENCODE__",decode:"__SCAFFOLD_RUST_INT64_DECODE__",imports:["use serde_with::DisplayFromStr;"],dep:{name:"serde_with",version:"^3"},mode:"lib"},decimal:{encode:"__SCAFFOLD_RUST_DECIMAL_ENCODE__",decode:"__SCAFFOLD_RUST_DECIMAL_DECODE__",imports:["use rust_decimal::Decimal;"],dep:{name:"rust_decimal",version:"^1"},mode:"lib"},byte:{encode:"__SCAFFOLD_RUST_BYTE_ENCODE__",decode:"__SCAFFOLD_RUST_BYTE_DECODE__",imports:["use serde_with::base64::Base64;"],dep:{name:"serde_with",version:"^3"},mode:"lib"},uuid:{encode:"__SCAFFOLD_RUST_UUID_ENCODE__",decode:"__SCAFFOLD_RUST_UUID_DECODE__",imports:["use uuid::Uuid;"],dep:{name:"uuid",version:"^1"},mode:"lib"},"number-special":{encode:"__SCAFFOLD_RUST_NUMSPECIAL_ENCODE__",decode:"__SCAFFOLD_RUST_NUMSPECIAL_DECODE__",mode:"native"}},ee={"date-time":{encode:"__SCAFFOLD_GO_DATETIME_ENCODE__",decode:"__SCAFFOLD_GO_DATETIME_DECODE__",imports:['"time"'],mode:"native"},int64:{encode:"__SCAFFOLD_GO_INT64_ENCODE__",decode:"__SCAFFOLD_GO_INT64_DECODE__",imports:['"strconv"'],mode:"native"},decimal:{encode:"__SCAFFOLD_GO_DECIMAL_ENCODE__",decode:"__SCAFFOLD_GO_DECIMAL_DECODE__",imports:['"github.com/shopspring/decimal"'],dep:{name:"github.com/shopspring/decimal",version:"v1"},mode:"lib"},byte:{encode:"__SCAFFOLD_GO_BYTE_ENCODE__",decode:"__SCAFFOLD_GO_BYTE_DECODE__",imports:['"encoding/base64"'],mode:"native"},uuid:{encode:"__SCAFFOLD_GO_UUID_ENCODE__",decode:"__SCAFFOLD_GO_UUID_DECODE__",imports:['"github.com/google/uuid"'],dep:{name:"github.com/google/uuid",version:"v1"},mode:"lib"},"number-special":{encode:"__SCAFFOLD_GO_NUMSPECIAL_ENCODE__",decode:"__SCAFFOLD_GO_NUMSPECIAL_DECODE__",mode:"native"}},te={"date-time":{encode:"__SCAFFOLD_JAVA_DATETIME_ENCODE__",decode:"__SCAFFOLD_JAVA_DATETIME_DECODE__",imports:["import java.time.Instant;"],dep:{name:"jackson-datatype-jsr310",version:"2.x"},mode:"lib"},int64:{encode:"__SCAFFOLD_JAVA_INT64_ENCODE__",decode:"__SCAFFOLD_JAVA_INT64_DECODE__",imports:["import com.fasterxml.jackson.annotation.JsonFormat;"],mode:"native"},decimal:{encode:"__SCAFFOLD_JAVA_DECIMAL_ENCODE__",decode:"__SCAFFOLD_JAVA_DECIMAL_DECODE__",imports:["import java.math.BigDecimal;"],mode:"native"},byte:{encode:"__SCAFFOLD_JAVA_BYTE_ENCODE__",decode:"__SCAFFOLD_JAVA_BYTE_DECODE__",mode:"native"},uuid:{encode:"__SCAFFOLD_JAVA_UUID_ENCODE__",decode:"__SCAFFOLD_JAVA_UUID_DECODE__",imports:["import java.util.UUID;"],mode:"native"},"number-special":{encode:"__SCAFFOLD_JAVA_NUMSPECIAL_ENCODE__",decode:"__SCAFFOLD_JAVA_NUMSPECIAL_DECODE__",mode:"native"}},y=Object.freeze({typescript:q,python:Q,rust:x,go:ee,java:te});function oe(e){return y[e]}function ne(e,o){const t=y[o],n=[];for(const r of e){const d=t[r];d!=null&&d.dep&&n.push({id:r,dep:d.dep})}return n}function re(){const e=y.typescript,o={};for(const t of I){const n=e[t].dep;n&&(o[t]=n)}return Object.freeze(o)}function ie(e,o){const t=o??y[e],n=[];for(const r of I)t[r]||n.push(r);if(n.length>0)throw new Error(`[hints] assertNoEmptyCells: language "${e}" is missing cells for: ${n.join(", ")}`)}exports.CANONICAL_LOGICAL_TYPE_IDS=I;exports.CodecRegistryError=C;exports.ENVELOPE_KEY=l;exports.LOGICAL_TYPE_VERSION=R;exports.TEMPLATE_CELLS=y;exports.X_APIGEN_CODEC=v;exports.X_APIGEN_CTOR=j;exports.X_APIGEN_LOGICAL=$;exports.X_APIGEN_TOJSON=M;exports.assertNoEmptyCells=ie;exports.buildTranscoder=V;exports.byteCodec=b;exports.cellsFor=oe;exports.codecIdOf=B;exports.createRegistry=P;exports.dateTimeCodec=h;exports.decimalCodec=N;exports.depsForLogicalTypes=ne;exports.int64Codec=S;exports.logicalKindOf=w;exports.makeDecimal=W;exports.numberSpecialCodec=F;exports.registerWellKnown=Z;exports.tryRegister=Y;exports.tsDepMap=re;exports.uuidCodec=L;exports.validateSchemaRefs=J;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const g="$apigen";class C extends Error{constructor(r){super(r),this.code="E_DUP_CODEC",this.name="CodecRegistryError"}}function G(e){e==null||e.wellKnown;const r=new Map;return{register(n,o){if(r.has(n.id)&&!(o!=null&&o.override))throw new C(`E_DUP_CODEC: a codec is already registered for id "${n.id}"`);r.set(n.id,n)},resolve(n){for(const o of r.values())if(o.matches(n))return o},get(n){return r.get(n)},ids(){return[...r.keys()]},freeze(){const n=new Map(r),o={register(){throw new C("E_DUP_CODEC: registry is frozen and cannot accept new codecs")},resolve(i){for(const c of n.values())if(c.matches(i))return c},get(i){return n.get(i)},ids(){return[...n.keys()]},freeze(){return o}};return o}}}const j="x-apigen-logical",R="x-apigen-codec",M="x-apigen-ctor",k="x-apigen-tojson",w="0.1.0",z=["scalar","nominal","union","map","set"];function B(e){const r=e[j];return typeof r=="string"&&z.includes(r)?r:void 0}function J(e){const r=e[R];return typeof r=="string"?r:void 0}function L(e,r){return{registry:e,resolve:t=>{throw new Error(`[apigen-logical] $ref "${t}" cannot be resolved in run-mode without a descriptor root. Supply a resolve() in the ctx override to handle $ref.`)},seen:new WeakSet,path:"",mode:"strict",...r}}function m(e,r,t){const n=t.registry.resolve(r);if(n)return n.encode(e,r,t);const o=r.$ref;if(typeof o=="string"){const s=t.resolve(o);return m(e,s,t)}const i=r.oneOf;if(Array.isArray(i)){const s=P(e,i,r);return m(e,s,t)}const c=r.type;if(c==="array"){if(!Array.isArray(e))return O(e,r,t);const s=r.items;if(!s)return e.map(a=>_(a));const u=t.path;return Array.isArray(s)?e.map((a,f)=>{const d=s[f];return d===void 0?_(a):m(a,d,{...t,path:`${u}/${f}`})}):e.map((a,f)=>m(a,s,{...t,path:`${u}/${f}`}))}if(c==="object"){if(e===null||typeof e!="object"||Array.isArray(e))return O(e,r,t);const s=r.properties;if(!s)return _(e);const u=t.path,a={};for(const[f,d]of Object.entries(s)){const p=e[f];p!==void 0&&(a[f]=m(p,d,{...t,path:`${u}/${f}`}))}return a}return c==null?O(e,r,t):_(e)}function l(e,r,t){const n=t.registry.resolve(r);if(n)return n.decode(e,r,t);const o=r.$ref;if(typeof o=="string"){const s=t.resolve(o);return l(e,s,t)}const i=r.oneOf;if(Array.isArray(i)){const s=P(e,i,r);return l(e,s,t)}const c=r.type;if(c==="array"){if(!Array.isArray(e))return e;const s=r.items;if(!s)return e;const u=t.path;return Array.isArray(s)?e.map((a,f)=>{const d=s[f];return d===void 0?a:l(a,d,{...t,path:`${u}/${f}`})}):e.map((a,f)=>l(a,s,{...t,path:`${u}/${f}`}))}if(c==="object"){if(e===null||typeof e!="object"||Array.isArray(e))return e;const s=r.properties;if(!s)return e;const u=t.path,a={};for(const[f,d]of Object.entries(s)){const p=e[f];p!==void 0&&(a[f]=l(p,d,{...t,path:`${u}/${f}`}))}return a}return c==null?Y(e,t):e}function P(e,r,t,n){const o=t.discriminator;if(o!=null&&o.propertyName){const i=e!==null&&typeof e=="object"?e[o.propertyName]:void 0;if(typeof i=="string"&&o.mapping){const c=o.mapping[i];if(c){const s=r.find(u=>u.$ref===c);if(s)return s}}}return r[0]??{}}function O(e,r,t){for(const n of t.registry.ids()){const o=t.registry.get(n);if(o)try{const i=o.encode(e,o.schema,t);return{[g]:n,v:i}}catch{}}return _(e)}function Y(e,r){if(e!==null&&typeof e=="object"&&!Array.isArray(e)&&g in e){const t=e,n=t[g],o=r.registry.get(n);if(o)return o.decode(t.v,o.schema,r)}return e}function _(e){if(e===null||typeof e=="string"||typeof e=="number"||typeof e=="boolean")return e;if(Array.isArray(e))return e.map(_);if(typeof e=="object"){const r={};for(const[t,n]of Object.entries(e))n!==void 0&&(r[t]=_(n));return r}return null}function K(e,r){const t=new Set,n=[e];for(;n.length>0;){const o=n.pop();if(!o||t.has(o))continue;t.add(o);const i=o.$ref;if(typeof i=="string"){if(r){const d=r[i];if(!d){const p=Object.keys(r).join(", ")||"(none)";throw new Error(`[apigen-logical] $ref "${i}" cannot be resolved. Available $defs: ${p}`)}n.push(d)}continue}const c=o.oneOf;if(Array.isArray(c))for(const d of c)typeof d=="object"&&d!==null&&n.push(d);const s=o.properties;if(s)for(const d of Object.values(s))n.push(d);const u=o.items;if(Array.isArray(u))for(const d of u)typeof d=="object"&&d!==null&&n.push(d);else typeof u=="object"&&u!==null&&n.push(u);const a=o.additionalProperties;typeof a=="object"&&a!==null&&n.push(a);const f=o.propertyNames;typeof f=="object"&&f!==null&&n.push(f)}}function W(e){return{encode(r,t,n){const o=L(e,n);return m(r,t,o)},decode(r,t,n){const o=L(e,n);return l(r,t,o)}}}function X(e,r,t){try{const n=t();e.register(n)}catch(n){if(q(n))return;throw n}}function q(e){return e===null||typeof e!="object"?!1:e.code==="MODULE_NOT_FOUND"}const A={id:"date-time",kind:"scalar",schema:{type:"string",format:"date-time"},matches(e){return e.type==="string"&&e.format==="date-time"},encode(e,r,t){return e.toISOString()},decode(e,r,t){if(typeof e!="string"){if(t.mode==="strict")throw new TypeError(`[date-time] expected a string on the wire at "${t.path}", got ${typeof e}`);return new Date(String(e))}if(t.mode==="strict"&&Number.isNaN(new Date(e).getTime()))throw new TypeError(`[date-time] invalid date-time string at "${t.path}": ${JSON.stringify(e)}`);return new Date(e)}},h={id:"int64",kind:"scalar",schema:{type:"string",format:"int64"},matches(e){return e.type==="string"&&e.format==="int64"},encode(e,r,t){return String(e)},decode(e,r,t){if(typeof e!="string"){if(t.mode==="strict")throw new TypeError(`[int64] expected a string on the wire at "${t.path}", got ${typeof e}`);try{return BigInt(Math.trunc(Number(e)))}catch{return BigInt(0)}}if(t.mode==="strict")return BigInt(e);if(/^-?\d+$/.test(e))try{return BigInt(e)}catch{return BigInt(0)}return BigInt(0)}};function V(e){return e}const N={id:"decimal",kind:"scalar",schema:{type:"string",format:"decimal"},matches(e){return e.type==="string"&&e.format==="decimal"},encode(e,r,t){return e},decode(e,r,t){if(typeof e!="string"){if(t.mode==="strict")throw new TypeError(`[decimal] expected a string on the wire at "${t.path}", got ${typeof e}`);return String(e)}if(t.mode==="strict"&&!/^-?\d+(\.\d+)?$/.test(e))throw new TypeError(`[decimal] wire value "${e}" at "${t.path}" is not a valid decimal string`);return e}},$={id:"byte",kind:"scalar",schema:{type:"string",format:"byte"},matches(e){return e.type==="string"&&e.format==="byte"},encode(e,r,t){return Buffer.from(e).toString("base64")},decode(e,r,t){if(typeof e!="string"){if(t.mode==="strict")throw new TypeError(`[byte] expected a base64 string on the wire at "${t.path}", got ${typeof e}`);return new Uint8Array(0)}if(t.mode==="strict"&&!/^[A-Za-z0-9+/]*={0,2}$/.test(e))throw new TypeError(`[byte] wire value at "${t.path}" is not standard base64 (format:byte): "${e}"`);return new Uint8Array(Buffer.from(e,"base64"))}},Z=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,I={id:"uuid",kind:"scalar",schema:{type:"string",format:"uuid"},matches(e){return e.type==="string"&&e.format==="uuid"},encode(e,r,t){return e.toLowerCase()},decode(e,r,t){if(typeof e!="string"){if(t.mode==="strict")throw new TypeError(`[uuid] expected a string on the wire at "${t.path}", got ${typeof e}`);return String(e).toLowerCase()}if(t.mode==="strict"&&!Z.test(e))throw new TypeError(`[uuid] wire value "${e}" at "${t.path}" is not a lowercase-hyphenated RFC 4122 UUID`);return e}},D="NaN",b="Infinity",S="-Infinity",H=new Set([D,b,S]),T={id:"number-special",kind:"scalar",schema:{type:"number"},matches(e){return e.type==="number"&&e.format===void 0},encode(e,r,t){return Number.isNaN(e)?D:e===1/0?b:e===-1/0?S:e},decode(e,r,t){if(typeof e=="number")return e;if(typeof e=="string"){if(e===D)return NaN;if(e===b)return 1/0;if(e===S)return-1/0;const n=Number(e);if(!Number.isNaN(n))return n}if(t.mode==="strict")throw new TypeError(`[number-special] unrecognized wire value at "${t.path}": ${JSON.stringify(e)}. Expected a number or one of ${[...H].join(", ")}.`);return NaN}},Q=[A,h,N,$,I,T];function x(e,r={}){for(const t of Q)e.register(t,{override:r.override??!1})}const ee=12;function te(e,r){const t=/^#\/(definitions|\$defs)\/(.+)$/.exec(e);if(!t)return;const[,n,o]=t,i=n==="$defs"?r.$defs:r.definitions;return i==null?void 0:i[decodeURIComponent(o)]}function F(e){return Array.isArray(e)&&e.length>0?e[0]:void 0}function re(e){if(Array.isArray(e.type))return e.type.find(r=>r!=="null")??e.type[0];if(typeof e.type=="string")return e.type;if(e.properties)return"object"}function ne(e){switch(e.format){case"date-time":return"1970-01-01T00:00:00.000Z";case"date":return"1970-01-01";case"time":return"00:00:00Z";case"uuid":return"00000000-0000-0000-0000-000000000000";case"email":return"user@example.com";case"uri":case"url":case"uri-reference":return"https://example.com";case"hostname":return"example.com";case"ipv4":return"127.0.0.1";case"ipv6":return"::1";case"decimal":return"0";case"int64":return"0";case"byte":return"";default:return"<string>"}}function U(e,r,t){const n=e.properties??{},o=e.required??[],i={};for(const c of o){const s=n[c];i[c]=s!==void 0?y(s,r,t+1):`<${c}>`}return i}function oe(e,r,t){const n=Array.isArray(e.items)?e.items[0]:e.items;return n?[y(n,r,t+1)]:[]}function y(e,r=e??{},t=0){if(!e||t>ee)return null;if(typeof e.$ref=="string"){const i=te(e.$ref,r);return i!==void 0?y(i,r,t+1):null}if(e.const!==void 0)return e.const;if(Array.isArray(e.enum)&&e.enum.length>0)return e.enum[0];if(Array.isArray(e.allOf)&&e.allOf.length>0){const i={},c=[];for(const s of e.allOf){Object.assign(i,s.properties??{});for(const u of s.required??[])c.includes(u)||c.push(u)}return U({...e,properties:i,required:c},r,t)}const n=F(e.oneOf)??F(e.anyOf);if(n)return y(n,r,t+1);switch(re(e)){case"object":return U(e,r,t);case"array":return oe(e,r,t);case"string":return ne(e);case"integer":case"number":return 0;case"boolean":return!1;case"null":return null;default:return null}}function ie(e){if(!e)return;const r=y(e);return`Example: ${JSON.stringify(r)}`}const v=[A.id,h.id,N.id,$.id,I.id,T.id],se={"date-time":{encode:"$.toISOString()",decode:"new Date($)",mode:"native"},int64:{encode:"String($)",decode:"BigInt($)",mode:"native"},decimal:{encode:"$.toString()",decode:"new Decimal($)",imports:[],dep:{name:"decimal.js",version:"^10"},mode:"branded"},byte:{encode:"Buffer.from($).toString('base64')",decode:"new Uint8Array(Buffer.from($, 'base64'))",mode:"native"},uuid:{encode:"$.toLowerCase()",decode:"$",mode:"native"},"number-special":{encode:"numToWire($)",decode:"wireToNum($)",mode:"native"}},ce={"date-time":{encode:"$.isoformat()",decode:"datetime.fromisoformat($)",imports:["from datetime import datetime"],mode:"native"},int64:{encode:"str($)",decode:"int($)",mode:"native"},decimal:{encode:"str($)",decode:"Decimal($)",imports:["from decimal import Decimal"],mode:"native"},byte:{encode:"b64encode($).decode()",decode:"b64decode($)",imports:["from base64 import b64encode, b64decode"],mode:"native"},uuid:{encode:"str($)",decode:"UUID($)",imports:["from uuid import UUID"],mode:"native"},"number-special":{encode:"num_to_wire($)",decode:"wire_to_num($)",mode:"native"}},de={"date-time":{encode:"__SCAFFOLD_RUST_DATETIME_ENCODE__",decode:"__SCAFFOLD_RUST_DATETIME_DECODE__",imports:["use chrono::{DateTime, Utc};"],dep:{name:"chrono",version:"^0.4"},mode:"lib"},int64:{encode:"__SCAFFOLD_RUST_INT64_ENCODE__",decode:"__SCAFFOLD_RUST_INT64_DECODE__",imports:["use serde_with::DisplayFromStr;"],dep:{name:"serde_with",version:"^3"},mode:"lib"},decimal:{encode:"__SCAFFOLD_RUST_DECIMAL_ENCODE__",decode:"__SCAFFOLD_RUST_DECIMAL_DECODE__",imports:["use rust_decimal::Decimal;"],dep:{name:"rust_decimal",version:"^1"},mode:"lib"},byte:{encode:"__SCAFFOLD_RUST_BYTE_ENCODE__",decode:"__SCAFFOLD_RUST_BYTE_DECODE__",imports:["use serde_with::base64::Base64;"],dep:{name:"serde_with",version:"^3"},mode:"lib"},uuid:{encode:"__SCAFFOLD_RUST_UUID_ENCODE__",decode:"__SCAFFOLD_RUST_UUID_DECODE__",imports:["use uuid::Uuid;"],dep:{name:"uuid",version:"^1"},mode:"lib"},"number-special":{encode:"__SCAFFOLD_RUST_NUMSPECIAL_ENCODE__",decode:"__SCAFFOLD_RUST_NUMSPECIAL_DECODE__",mode:"native"}},ae={"date-time":{encode:"__SCAFFOLD_GO_DATETIME_ENCODE__",decode:"__SCAFFOLD_GO_DATETIME_DECODE__",imports:['"time"'],mode:"native"},int64:{encode:"__SCAFFOLD_GO_INT64_ENCODE__",decode:"__SCAFFOLD_GO_INT64_DECODE__",imports:['"strconv"'],mode:"native"},decimal:{encode:"__SCAFFOLD_GO_DECIMAL_ENCODE__",decode:"__SCAFFOLD_GO_DECIMAL_DECODE__",imports:['"github.com/shopspring/decimal"'],dep:{name:"github.com/shopspring/decimal",version:"v1"},mode:"lib"},byte:{encode:"__SCAFFOLD_GO_BYTE_ENCODE__",decode:"__SCAFFOLD_GO_BYTE_DECODE__",imports:['"encoding/base64"'],mode:"native"},uuid:{encode:"__SCAFFOLD_GO_UUID_ENCODE__",decode:"__SCAFFOLD_GO_UUID_DECODE__",imports:['"github.com/google/uuid"'],dep:{name:"github.com/google/uuid",version:"v1"},mode:"lib"},"number-special":{encode:"__SCAFFOLD_GO_NUMSPECIAL_ENCODE__",decode:"__SCAFFOLD_GO_NUMSPECIAL_DECODE__",mode:"native"}},fe={"date-time":{encode:"$.toString()",decode:"Instant.parse($)",imports:["import java.time.Instant;"],dep:{name:"jackson-datatype-jsr310",version:"2.x"},mode:"lib"},int64:{encode:"@JsonFormat(shape = JsonFormat.Shape.STRING)",decode:"@JsonFormat(shape = JsonFormat.Shape.STRING)",imports:["import com.fasterxml.jackson.annotation.JsonFormat;"],mode:"native"},decimal:{encode:"@JsonSerialize(using = ToStringSerializer.class)",decode:"new BigDecimal($)",imports:["import java.math.BigDecimal;","import com.fasterxml.jackson.databind.annotation.JsonSerialize;","import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;"],mode:"native"},byte:{encode:"$",decode:"$",mode:"native"},uuid:{encode:"$.toString()",decode:"UUID.fromString($)",imports:["import java.util.UUID;"],mode:"native"},"number-special":{encode:"@JsonSerialize(using = NumberSpecialSerializer.class)",decode:"@JsonDeserialize(using = NumberSpecialDeserializer.class)",imports:["import com.fasterxml.jackson.databind.annotation.JsonSerialize;","import com.fasterxml.jackson.databind.annotation.JsonDeserialize;"],mode:"native"}},E=Object.freeze({typescript:se,python:ce,rust:de,go:ae,java:fe});function ue(e){return E[e]}function pe(e,r){const t=E[r],n=[];for(const o of e){const i=t[o];i!=null&&i.dep&&n.push({id:o,dep:i.dep})}return n}function _e(){const e=E.typescript,r={};for(const t of v){const n=e[t].dep;n&&(r[t]=n)}return Object.freeze(r)}function me(e,r){const t=r??E[e],n=[];for(const o of v)t[o]||n.push(o);if(n.length>0)throw new Error(`[hints] assertNoEmptyCells: language "${e}" is missing cells for: ${n.join(", ")}`)}exports.CANONICAL_LOGICAL_TYPE_IDS=v;exports.CodecRegistryError=C;exports.ENVELOPE_KEY=g;exports.LOGICAL_TYPE_VERSION=w;exports.TEMPLATE_CELLS=E;exports.X_APIGEN_CODEC=R;exports.X_APIGEN_CTOR=M;exports.X_APIGEN_LOGICAL=j;exports.X_APIGEN_TOJSON=k;exports.assertNoEmptyCells=me;exports.buildTranscoder=W;exports.byteCodec=$;exports.cellsFor=ue;exports.codecIdOf=J;exports.createRegistry=G;exports.dateTimeCodec=A;exports.decimalCodec=N;exports.depsForLogicalTypes=pe;exports.int64Codec=h;exports.logicalKindOf=B;exports.makeDecimal=V;exports.numberSpecialCodec=T;exports.registerWellKnown=x;exports.renderExampleNote=ie;exports.synthesizeExample=y;exports.tryRegister=X;exports.tsDepMap=_e;exports.uuidCodec=I;exports.validateSchemaRefs=K;
package/index.mjs CHANGED
@@ -1,73 +1,73 @@
1
- const l = "$apigen";
2
- class g extends Error {
3
- constructor(o) {
4
- super(o), this.code = "E_DUP_CODEC", this.name = "CodecRegistryError";
1
+ const D = "$apigen";
2
+ class C extends Error {
3
+ constructor(r) {
4
+ super(r), this.code = "E_DUP_CODEC", this.name = "CodecRegistryError";
5
5
  }
6
6
  }
7
- function z(e) {
7
+ function x(e) {
8
8
  e == null || e.wellKnown;
9
- const o = /* @__PURE__ */ new Map();
9
+ const r = /* @__PURE__ */ new Map();
10
10
  return {
11
- register(n, r) {
12
- if (o.has(n.id) && !(r != null && r.override))
13
- throw new g(
11
+ register(n, o) {
12
+ if (r.has(n.id) && !(o != null && o.override))
13
+ throw new C(
14
14
  `E_DUP_CODEC: a codec is already registered for id "${n.id}"`
15
15
  );
16
- o.set(n.id, n);
16
+ r.set(n.id, n);
17
17
  },
18
18
  resolve(n) {
19
- for (const r of o.values())
20
- if (r.matches(n))
21
- return r;
19
+ for (const o of r.values())
20
+ if (o.matches(n))
21
+ return o;
22
22
  },
23
23
  get(n) {
24
- return o.get(n);
24
+ return r.get(n);
25
25
  },
26
26
  ids() {
27
- return [...o.keys()];
27
+ return [...r.keys()];
28
28
  },
29
29
  freeze() {
30
- const n = new Map(o), r = {
30
+ const n = new Map(r), o = {
31
31
  register() {
32
- throw new g(
32
+ throw new C(
33
33
  "E_DUP_CODEC: registry is frozen and cannot accept new codecs"
34
34
  );
35
35
  },
36
- resolve(d) {
37
- for (const a of n.values())
38
- if (a.matches(d))
39
- return a;
36
+ resolve(i) {
37
+ for (const c of n.values())
38
+ if (c.matches(i))
39
+ return c;
40
40
  },
41
- get(d) {
42
- return n.get(d);
41
+ get(i) {
42
+ return n.get(i);
43
43
  },
44
44
  ids() {
45
45
  return [...n.keys()];
46
46
  },
47
47
  freeze() {
48
- return r;
48
+ return o;
49
49
  }
50
50
  };
51
- return r;
51
+ return o;
52
52
  }
53
53
  };
54
54
  }
55
- const v = "x-apigen-logical", U = "x-apigen-codec", W = "x-apigen-ctor", K = "x-apigen-tojson", X = "0.1.0", j = [
55
+ const R = "x-apigen-logical", P = "x-apigen-codec", ee = "x-apigen-ctor", te = "x-apigen-tojson", re = "0.1.0", M = [
56
56
  "scalar",
57
57
  "nominal",
58
58
  "union",
59
59
  "map",
60
60
  "set"
61
61
  ];
62
- function H(e) {
63
- const o = e[v];
64
- return typeof o == "string" && j.includes(o) ? o : void 0;
62
+ function ne(e) {
63
+ const r = e[R];
64
+ return typeof r == "string" && M.includes(r) ? r : void 0;
65
65
  }
66
- function Z(e) {
67
- const o = e[U];
68
- return typeof o == "string" ? o : void 0;
66
+ function oe(e) {
67
+ const r = e[P];
68
+ return typeof r == "string" ? r : void 0;
69
69
  }
70
- function h(e, o) {
70
+ function h(e, r) {
71
71
  return {
72
72
  registry: e,
73
73
  resolve: (t) => {
@@ -78,228 +78,228 @@ function h(e, o) {
78
78
  seen: /* @__PURE__ */ new WeakSet(),
79
79
  path: "",
80
80
  mode: "strict",
81
- ...o
81
+ ...r
82
82
  };
83
83
  }
84
- function p(e, o, t) {
85
- const n = t.registry.resolve(o);
84
+ function _(e, r, t) {
85
+ const n = t.registry.resolve(r);
86
86
  if (n)
87
- return n.encode(e, o, t);
88
- const r = o.$ref;
89
- if (typeof r == "string") {
90
- const i = t.resolve(r);
91
- return p(e, i, t);
92
- }
93
- const d = o.oneOf;
94
- if (Array.isArray(d)) {
95
- const i = S(e, d, o);
96
- return p(e, i, t);
97
- }
98
- const a = o.type;
99
- if (a === "array") {
87
+ return n.encode(e, r, t);
88
+ const o = r.$ref;
89
+ if (typeof o == "string") {
90
+ const s = t.resolve(o);
91
+ return _(e, s, t);
92
+ }
93
+ const i = r.oneOf;
94
+ if (Array.isArray(i)) {
95
+ const s = N(e, i, r);
96
+ return _(e, s, t);
97
+ }
98
+ const c = r.type;
99
+ if (c === "array") {
100
100
  if (!Array.isArray(e))
101
- return D(e, o, t);
102
- const i = o.items;
103
- if (!i)
104
- return e.map((c) => u(c));
105
- const f = t.path;
106
- return Array.isArray(i) ? e.map((c, _) => {
107
- const s = i[_];
108
- return s === void 0 ? u(c) : p(c, s, { ...t, path: `${f}/${_}` });
101
+ return E(e, r, t);
102
+ const s = r.items;
103
+ if (!s)
104
+ return e.map((a) => m(a));
105
+ const u = t.path;
106
+ return Array.isArray(s) ? e.map((a, f) => {
107
+ const d = s[f];
108
+ return d === void 0 ? m(a) : _(a, d, { ...t, path: `${u}/${f}` });
109
109
  }) : e.map(
110
- (c, _) => p(c, i, { ...t, path: `${f}/${_}` })
110
+ (a, f) => _(a, s, { ...t, path: `${u}/${f}` })
111
111
  );
112
112
  }
113
- if (a === "object") {
113
+ if (c === "object") {
114
114
  if (e === null || typeof e != "object" || Array.isArray(e))
115
- return D(e, o, t);
116
- const i = o.properties;
117
- if (!i)
118
- return u(e);
119
- const f = t.path, c = {};
120
- for (const [_, s] of Object.entries(i)) {
121
- const m = e[_];
122
- m !== void 0 && (c[_] = p(m, s, {
115
+ return E(e, r, t);
116
+ const s = r.properties;
117
+ if (!s)
118
+ return m(e);
119
+ const u = t.path, a = {};
120
+ for (const [f, d] of Object.entries(s)) {
121
+ const p = e[f];
122
+ p !== void 0 && (a[f] = _(p, d, {
123
123
  ...t,
124
- path: `${f}/${_}`
124
+ path: `${u}/${f}`
125
125
  }));
126
126
  }
127
- return c;
127
+ return a;
128
128
  }
129
- return a == null ? D(e, o, t) : u(e);
129
+ return c == null ? E(e, r, t) : m(e);
130
130
  }
131
- function E(e, o, t) {
132
- const n = t.registry.resolve(o);
131
+ function l(e, r, t) {
132
+ const n = t.registry.resolve(r);
133
133
  if (n)
134
- return n.decode(e, o, t);
135
- const r = o.$ref;
136
- if (typeof r == "string") {
137
- const i = t.resolve(r);
138
- return E(e, i, t);
139
- }
140
- const d = o.oneOf;
141
- if (Array.isArray(d)) {
142
- const i = S(e, d, o);
143
- return E(e, i, t);
144
- }
145
- const a = o.type;
146
- if (a === "array") {
134
+ return n.decode(e, r, t);
135
+ const o = r.$ref;
136
+ if (typeof o == "string") {
137
+ const s = t.resolve(o);
138
+ return l(e, s, t);
139
+ }
140
+ const i = r.oneOf;
141
+ if (Array.isArray(i)) {
142
+ const s = N(e, i, r);
143
+ return l(e, s, t);
144
+ }
145
+ const c = r.type;
146
+ if (c === "array") {
147
147
  if (!Array.isArray(e))
148
148
  return e;
149
- const i = o.items;
150
- if (!i)
149
+ const s = r.items;
150
+ if (!s)
151
151
  return e;
152
- const f = t.path;
153
- return Array.isArray(i) ? e.map((c, _) => {
154
- const s = i[_];
155
- return s === void 0 ? c : E(c, s, { ...t, path: `${f}/${_}` });
152
+ const u = t.path;
153
+ return Array.isArray(s) ? e.map((a, f) => {
154
+ const d = s[f];
155
+ return d === void 0 ? a : l(a, d, { ...t, path: `${u}/${f}` });
156
156
  }) : e.map(
157
- (c, _) => E(c, i, { ...t, path: `${f}/${_}` })
157
+ (a, f) => l(a, s, { ...t, path: `${u}/${f}` })
158
158
  );
159
159
  }
160
- if (a === "object") {
160
+ if (c === "object") {
161
161
  if (e === null || typeof e != "object" || Array.isArray(e))
162
162
  return e;
163
- const i = o.properties;
164
- if (!i)
163
+ const s = r.properties;
164
+ if (!s)
165
165
  return e;
166
- const f = t.path, c = {};
167
- for (const [_, s] of Object.entries(i)) {
168
- const m = e[_];
169
- m !== void 0 && (c[_] = E(m, s, {
166
+ const u = t.path, a = {};
167
+ for (const [f, d] of Object.entries(s)) {
168
+ const p = e[f];
169
+ p !== void 0 && (a[f] = l(p, d, {
170
170
  ...t,
171
- path: `${f}/${_}`
171
+ path: `${u}/${f}`
172
172
  }));
173
173
  }
174
- return c;
174
+ return a;
175
175
  }
176
- return a == null ? M(e, t) : e;
176
+ return c == null ? k(e, t) : e;
177
177
  }
178
- function S(e, o, t, n) {
179
- const r = t.discriminator;
180
- if (r != null && r.propertyName) {
181
- const d = e !== null && typeof e == "object" ? e[r.propertyName] : void 0;
182
- if (typeof d == "string" && r.mapping) {
183
- const a = r.mapping[d];
184
- if (a) {
185
- const i = o.find((f) => f.$ref === a);
186
- if (i)
187
- return i;
178
+ function N(e, r, t, n) {
179
+ const o = t.discriminator;
180
+ if (o != null && o.propertyName) {
181
+ const i = e !== null && typeof e == "object" ? e[o.propertyName] : void 0;
182
+ if (typeof i == "string" && o.mapping) {
183
+ const c = o.mapping[i];
184
+ if (c) {
185
+ const s = r.find((u) => u.$ref === c);
186
+ if (s)
187
+ return s;
188
188
  }
189
189
  }
190
190
  }
191
- return o[0] ?? {};
191
+ return r[0] ?? {};
192
192
  }
193
- function D(e, o, t) {
193
+ function E(e, r, t) {
194
194
  for (const n of t.registry.ids()) {
195
- const r = t.registry.get(n);
196
- if (r)
195
+ const o = t.registry.get(n);
196
+ if (o)
197
197
  try {
198
- const d = r.encode(e, r.schema, t);
199
- return { [l]: n, v: d };
198
+ const i = o.encode(e, o.schema, t);
199
+ return { [D]: n, v: i };
200
200
  } catch {
201
201
  }
202
202
  }
203
- return u(e);
203
+ return m(e);
204
204
  }
205
- function M(e, o) {
206
- if (e !== null && typeof e == "object" && !Array.isArray(e) && l in e) {
207
- const t = e, n = t[l], r = o.registry.get(n);
208
- if (r)
209
- return r.decode(t.v, r.schema, o);
205
+ function k(e, r) {
206
+ if (e !== null && typeof e == "object" && !Array.isArray(e) && D in e) {
207
+ const t = e, n = t[D], o = r.registry.get(n);
208
+ if (o)
209
+ return o.decode(t.v, o.schema, r);
210
210
  }
211
211
  return e;
212
212
  }
213
- function u(e) {
213
+ function m(e) {
214
214
  if (e === null || typeof e == "string" || typeof e == "number" || typeof e == "boolean")
215
215
  return e;
216
216
  if (Array.isArray(e))
217
- return e.map(u);
217
+ return e.map(m);
218
218
  if (typeof e == "object") {
219
- const o = {};
219
+ const r = {};
220
220
  for (const [t, n] of Object.entries(e))
221
- n !== void 0 && (o[t] = u(n));
222
- return o;
221
+ n !== void 0 && (r[t] = m(n));
222
+ return r;
223
223
  }
224
224
  return null;
225
225
  }
226
- function q(e, o) {
226
+ function ie(e, r) {
227
227
  const t = /* @__PURE__ */ new Set(), n = [e];
228
228
  for (; n.length > 0; ) {
229
- const r = n.pop();
230
- if (!r || t.has(r))
229
+ const o = n.pop();
230
+ if (!o || t.has(o))
231
231
  continue;
232
- t.add(r);
233
- const d = r.$ref;
234
- if (typeof d == "string") {
235
- if (o) {
236
- const s = o[d];
237
- if (!s) {
238
- const m = Object.keys(o).join(", ") || "(none)";
232
+ t.add(o);
233
+ const i = o.$ref;
234
+ if (typeof i == "string") {
235
+ if (r) {
236
+ const d = r[i];
237
+ if (!d) {
238
+ const p = Object.keys(r).join(", ") || "(none)";
239
239
  throw new Error(
240
- `[apigen-logical] $ref "${d}" cannot be resolved. Available $defs: ${m}`
240
+ `[apigen-logical] $ref "${i}" cannot be resolved. Available $defs: ${p}`
241
241
  );
242
242
  }
243
- n.push(s);
243
+ n.push(d);
244
244
  }
245
245
  continue;
246
246
  }
247
- const a = r.oneOf;
248
- if (Array.isArray(a))
249
- for (const s of a)
250
- typeof s == "object" && s !== null && n.push(s);
251
- const i = r.properties;
252
- if (i)
253
- for (const s of Object.values(i))
254
- n.push(s);
255
- const f = r.items;
256
- if (Array.isArray(f))
257
- for (const s of f)
258
- typeof s == "object" && s !== null && n.push(s);
247
+ const c = o.oneOf;
248
+ if (Array.isArray(c))
249
+ for (const d of c)
250
+ typeof d == "object" && d !== null && n.push(d);
251
+ const s = o.properties;
252
+ if (s)
253
+ for (const d of Object.values(s))
254
+ n.push(d);
255
+ const u = o.items;
256
+ if (Array.isArray(u))
257
+ for (const d of u)
258
+ typeof d == "object" && d !== null && n.push(d);
259
259
  else
260
- typeof f == "object" && f !== null && n.push(f);
261
- const c = r.additionalProperties;
262
- typeof c == "object" && c !== null && n.push(c);
263
- const _ = r.propertyNames;
264
- typeof _ == "object" && _ !== null && n.push(_);
260
+ typeof u == "object" && u !== null && n.push(u);
261
+ const a = o.additionalProperties;
262
+ typeof a == "object" && a !== null && n.push(a);
263
+ const f = o.propertyNames;
264
+ typeof f == "object" && f !== null && n.push(f);
265
265
  }
266
266
  }
267
- function Q(e) {
267
+ function se(e) {
268
268
  return {
269
- encode(o, t, n) {
270
- const r = h(e, n);
271
- return p(o, t, r);
269
+ encode(r, t, n) {
270
+ const o = h(e, n);
271
+ return _(r, t, o);
272
272
  },
273
- decode(o, t, n) {
274
- const r = h(e, n);
275
- return E(o, t, r);
273
+ decode(r, t, n) {
274
+ const o = h(e, n);
275
+ return l(r, t, o);
276
276
  }
277
277
  };
278
278
  }
279
- function x(e, o, t) {
279
+ function ce(e, r, t) {
280
280
  try {
281
281
  const n = t();
282
282
  e.register(n);
283
283
  } catch (n) {
284
- if (P(n))
284
+ if (G(n))
285
285
  return;
286
286
  throw n;
287
287
  }
288
288
  }
289
- function P(e) {
289
+ function G(e) {
290
290
  return e === null || typeof e != "object" ? !1 : e.code === "MODULE_NOT_FOUND";
291
291
  }
292
- const b = {
292
+ const v = {
293
293
  id: "date-time",
294
294
  kind: "scalar",
295
295
  schema: { type: "string", format: "date-time" },
296
296
  matches(e) {
297
297
  return e.type === "string" && e.format === "date-time";
298
298
  },
299
- encode(e, o, t) {
299
+ encode(e, r, t) {
300
300
  return e.toISOString();
301
301
  },
302
- decode(e, o, t) {
302
+ decode(e, r, t) {
303
303
  if (typeof e != "string") {
304
304
  if (t.mode === "strict")
305
305
  throw new TypeError(
@@ -313,17 +313,17 @@ const b = {
313
313
  );
314
314
  return new Date(e);
315
315
  }
316
- }, N = {
316
+ }, I = {
317
317
  id: "int64",
318
318
  kind: "scalar",
319
319
  schema: { type: "string", format: "int64" },
320
320
  matches(e) {
321
321
  return e.type === "string" && e.format === "int64";
322
322
  },
323
- encode(e, o, t) {
323
+ encode(e, r, t) {
324
324
  return String(e);
325
325
  },
326
- decode(e, o, t) {
326
+ decode(e, r, t) {
327
327
  if (typeof e != "string") {
328
328
  if (t.mode === "strict")
329
329
  throw new TypeError(
@@ -346,20 +346,20 @@ const b = {
346
346
  return BigInt(0);
347
347
  }
348
348
  };
349
- function ee(e) {
349
+ function de(e) {
350
350
  return e;
351
351
  }
352
- const F = {
352
+ const T = {
353
353
  id: "decimal",
354
354
  kind: "scalar",
355
355
  schema: { type: "string", format: "decimal" },
356
356
  matches(e) {
357
357
  return e.type === "string" && e.format === "decimal";
358
358
  },
359
- encode(e, o, t) {
359
+ encode(e, r, t) {
360
360
  return e;
361
361
  },
362
- decode(e, o, t) {
362
+ decode(e, r, t) {
363
363
  if (typeof e != "string") {
364
364
  if (t.mode === "strict")
365
365
  throw new TypeError(
@@ -373,17 +373,17 @@ const F = {
373
373
  );
374
374
  return e;
375
375
  }
376
- }, $ = {
376
+ }, F = {
377
377
  id: "byte",
378
378
  kind: "scalar",
379
379
  schema: { type: "string", format: "byte" },
380
380
  matches(e) {
381
381
  return e.type === "string" && e.format === "byte";
382
382
  },
383
- encode(e, o, t) {
383
+ encode(e, r, t) {
384
384
  return Buffer.from(e).toString("base64");
385
385
  },
386
- decode(e, o, t) {
386
+ decode(e, r, t) {
387
387
  if (typeof e != "string") {
388
388
  if (t.mode === "strict")
389
389
  throw new TypeError(
@@ -397,17 +397,17 @@ const F = {
397
397
  );
398
398
  return new Uint8Array(Buffer.from(e, "base64"));
399
399
  }
400
- }, R = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/, L = {
400
+ }, w = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/, L = {
401
401
  id: "uuid",
402
402
  kind: "scalar",
403
403
  schema: { type: "string", format: "uuid" },
404
404
  matches(e) {
405
405
  return e.type === "string" && e.format === "uuid";
406
406
  },
407
- encode(e, o, t) {
407
+ encode(e, r, t) {
408
408
  return e.toLowerCase();
409
409
  },
410
- decode(e, o, t) {
410
+ decode(e, r, t) {
411
411
  if (typeof e != "string") {
412
412
  if (t.mode === "strict")
413
413
  throw new TypeError(
@@ -415,35 +415,35 @@ const F = {
415
415
  );
416
416
  return String(e).toLowerCase();
417
417
  }
418
- if (t.mode === "strict" && !R.test(e))
418
+ if (t.mode === "strict" && !w.test(e))
419
419
  throw new TypeError(
420
420
  `[uuid] wire value "${e}" at "${t.path}" is not a lowercase-hyphenated RFC 4122 UUID`
421
421
  );
422
422
  return e;
423
423
  }
424
- }, O = "NaN", C = "Infinity", A = "-Infinity", G = /* @__PURE__ */ new Set([
424
+ }, O = "NaN", b = "Infinity", S = "-Infinity", z = /* @__PURE__ */ new Set([
425
425
  O,
426
- C,
427
- A
428
- ]), I = {
426
+ b,
427
+ S
428
+ ]), U = {
429
429
  id: "number-special",
430
430
  kind: "scalar",
431
431
  schema: { type: "number" },
432
432
  matches(e) {
433
433
  return e.type === "number" && e.format === void 0;
434
434
  },
435
- encode(e, o, t) {
436
- return Number.isNaN(e) ? O : e === 1 / 0 ? C : e === -1 / 0 ? A : e;
435
+ encode(e, r, t) {
436
+ return Number.isNaN(e) ? O : e === 1 / 0 ? b : e === -1 / 0 ? S : e;
437
437
  },
438
- decode(e, o, t) {
438
+ decode(e, r, t) {
439
439
  if (typeof e == "number")
440
440
  return e;
441
441
  if (typeof e == "string") {
442
442
  if (e === O)
443
443
  return NaN;
444
- if (e === C)
444
+ if (e === b)
445
445
  return 1 / 0;
446
- if (e === A)
446
+ if (e === S)
447
447
  return -1 / 0;
448
448
  const n = Number(e);
449
449
  if (!Number.isNaN(n))
@@ -451,36 +451,150 @@ const F = {
451
451
  }
452
452
  if (t.mode === "strict")
453
453
  throw new TypeError(
454
- `[number-special] unrecognized wire value at "${t.path}": ${JSON.stringify(e)}. Expected a number or one of ${[...G].join(", ")}.`
454
+ `[number-special] unrecognized wire value at "${t.path}": ${JSON.stringify(e)}. Expected a number or one of ${[...z].join(", ")}.`
455
455
  );
456
456
  return NaN;
457
457
  }
458
- }, w = [
459
- b,
460
- N,
458
+ }, B = [
459
+ v,
460
+ I,
461
+ T,
461
462
  F,
462
- $,
463
463
  L,
464
- I
464
+ U
465
465
  ];
466
- function te(e, o = {}) {
467
- for (const t of w)
468
- e.register(t, { override: o.override ?? !1 });
466
+ function ae(e, r = {}) {
467
+ for (const t of B)
468
+ e.register(t, { override: r.override ?? !1 });
469
+ }
470
+ const J = 12;
471
+ function Y(e, r) {
472
+ const t = /^#\/(definitions|\$defs)\/(.+)$/.exec(e);
473
+ if (!t)
474
+ return;
475
+ const [, n, o] = t, i = n === "$defs" ? r.$defs : r.definitions;
476
+ return i == null ? void 0 : i[decodeURIComponent(o)];
469
477
  }
470
- const T = [
471
- b.id,
478
+ function A(e) {
479
+ return Array.isArray(e) && e.length > 0 ? e[0] : void 0;
480
+ }
481
+ function W(e) {
482
+ if (Array.isArray(e.type))
483
+ return e.type.find((r) => r !== "null") ?? e.type[0];
484
+ if (typeof e.type == "string")
485
+ return e.type;
486
+ if (e.properties)
487
+ return "object";
488
+ }
489
+ function K(e) {
490
+ switch (e.format) {
491
+ case "date-time":
492
+ return "1970-01-01T00:00:00.000Z";
493
+ case "date":
494
+ return "1970-01-01";
495
+ case "time":
496
+ return "00:00:00Z";
497
+ case "uuid":
498
+ return "00000000-0000-0000-0000-000000000000";
499
+ case "email":
500
+ return "user@example.com";
501
+ case "uri":
502
+ case "url":
503
+ case "uri-reference":
504
+ return "https://example.com";
505
+ case "hostname":
506
+ return "example.com";
507
+ case "ipv4":
508
+ return "127.0.0.1";
509
+ case "ipv6":
510
+ return "::1";
511
+ case "decimal":
512
+ return "0";
513
+ case "int64":
514
+ return "0";
515
+ case "byte":
516
+ return "";
517
+ default:
518
+ return "<string>";
519
+ }
520
+ }
521
+ function $(e, r, t) {
522
+ const n = e.properties ?? {}, o = e.required ?? [], i = {};
523
+ for (const c of o) {
524
+ const s = n[c];
525
+ i[c] = s !== void 0 ? y(s, r, t + 1) : `<${c}>`;
526
+ }
527
+ return i;
528
+ }
529
+ function q(e, r, t) {
530
+ const n = Array.isArray(e.items) ? e.items[0] : e.items;
531
+ return n ? [y(n, r, t + 1)] : [];
532
+ }
533
+ function y(e, r = e ?? {}, t = 0) {
534
+ if (!e || t > J)
535
+ return null;
536
+ if (typeof e.$ref == "string") {
537
+ const i = Y(e.$ref, r);
538
+ return i !== void 0 ? y(i, r, t + 1) : null;
539
+ }
540
+ if (e.const !== void 0)
541
+ return e.const;
542
+ if (Array.isArray(e.enum) && e.enum.length > 0)
543
+ return e.enum[0];
544
+ if (Array.isArray(e.allOf) && e.allOf.length > 0) {
545
+ const i = {}, c = [];
546
+ for (const s of e.allOf) {
547
+ Object.assign(i, s.properties ?? {});
548
+ for (const u of s.required ?? [])
549
+ c.includes(u) || c.push(u);
550
+ }
551
+ return $(
552
+ { ...e, properties: i, required: c },
553
+ r,
554
+ t
555
+ );
556
+ }
557
+ const n = A(e.oneOf) ?? A(e.anyOf);
558
+ if (n)
559
+ return y(n, r, t + 1);
560
+ switch (W(e)) {
561
+ case "object":
562
+ return $(e, r, t);
563
+ case "array":
564
+ return q(e, r, t);
565
+ case "string":
566
+ return K(e);
567
+ case "integer":
568
+ case "number":
569
+ return 0;
570
+ case "boolean":
571
+ return !1;
572
+ case "null":
573
+ return null;
574
+ default:
575
+ return null;
576
+ }
577
+ }
578
+ function fe(e) {
579
+ if (!e)
580
+ return;
581
+ const r = y(e);
582
+ return `Example: ${JSON.stringify(r)}`;
583
+ }
584
+ const j = [
585
+ v.id,
472
586
  // 'date-time'
473
- N.id,
587
+ I.id,
474
588
  // 'int64'
475
- F.id,
589
+ T.id,
476
590
  // 'decimal'
477
- $.id,
591
+ F.id,
478
592
  // 'byte'
479
593
  L.id,
480
594
  // 'uuid'
481
- I.id
595
+ U.id
482
596
  // 'number-special'
483
- ], B = {
597
+ ], X = {
484
598
  "date-time": {
485
599
  encode: "$.toISOString()",
486
600
  decode: "new Date($)",
@@ -519,7 +633,7 @@ const T = [
519
633
  decode: "wireToNum($)",
520
634
  mode: "native"
521
635
  }
522
- }, k = {
636
+ }, V = {
523
637
  "date-time": {
524
638
  encode: "$.isoformat()",
525
639
  decode: "datetime.fromisoformat($)",
@@ -556,7 +670,7 @@ const T = [
556
670
  decode: "wire_to_num($)",
557
671
  mode: "native"
558
672
  }
559
- }, J = {
673
+ }, Z = {
560
674
  "date-time": {
561
675
  // chrono::DateTime<Utc> serialises as RFC3339 via serde.
562
676
  encode: "__SCAFFOLD_RUST_DATETIME_ENCODE__",
@@ -600,7 +714,7 @@ const T = [
600
714
  decode: "__SCAFFOLD_RUST_NUMSPECIAL_DECODE__",
601
715
  mode: "native"
602
716
  }
603
- }, V = {
717
+ }, H = {
604
718
  "date-time": {
605
719
  // time.Time serialises as RFC3339Nano via MarshalJSON.
606
720
  encode: "__SCAFFOLD_GO_DATETIME_ENCODE__",
@@ -641,78 +755,104 @@ const T = [
641
755
  decode: "__SCAFFOLD_GO_NUMSPECIAL_DECODE__",
642
756
  mode: "native"
643
757
  }
644
- }, Y = {
758
+ }, Q = {
645
759
  "date-time": {
646
- // Instant.toString() / Instant.parse() via jackson-datatype-jsr310.
647
- encode: "__SCAFFOLD_JAVA_DATETIME_ENCODE__",
648
- decode: "__SCAFFOLD_JAVA_DATETIME_DECODE__",
760
+ // Instant.toString() (RFC-3339/ISO-8601, UTC) / Instant.parse($) โ€” the
761
+ // jackson-datatype-jsr310 module is registered on the shared ObjectMapper
762
+ // so java.time.Instant fields round-trip automatically, but the
763
+ // dispatcher-woven glue (which builds/reads JsonNode by hand rather than
764
+ // going through a field-annotated POJO) uses these expressions directly.
765
+ encode: "$.toString()",
766
+ decode: "Instant.parse($)",
649
767
  imports: ["import java.time.Instant;"],
650
768
  dep: { name: "jackson-datatype-jsr310", version: "2.x" },
651
769
  mode: "lib"
652
770
  },
653
771
  int64: {
654
- // @JsonFormat(shape=STRING) on Long / BigInteger โ€” stdlib Jackson.
655
- encode: "__SCAFFOLD_JAVA_INT64_ENCODE__",
656
- decode: "__SCAFFOLD_JAVA_INT64_DECODE__",
772
+ // Declarative, not expression-shaped: Jackson field annotation forces
773
+ // Long/long to serialise as a JSON string (avoids precision loss in
774
+ // JS/JSON-number consumers). mode:'native' โ€” the "encode"/"decode"
775
+ // values below ARE the annotation text (identical on both sides; Jackson
776
+ // applies it symmetrically), not a `$`-substituted call expression.
777
+ encode: "@JsonFormat(shape = JsonFormat.Shape.STRING)",
778
+ decode: "@JsonFormat(shape = JsonFormat.Shape.STRING)",
657
779
  imports: ["import com.fasterxml.jackson.annotation.JsonFormat;"],
658
780
  mode: "native"
659
781
  },
660
782
  decimal: {
661
- // @JsonSerialize(using=ToStringSerializer) on BigDecimal โ€” stdlib Jackson.
662
- encode: "__SCAFFOLD_JAVA_DECIMAL_ENCODE__",
663
- decode: "__SCAFFOLD_JAVA_DECIMAL_DECODE__",
664
- imports: ["import java.math.BigDecimal;"],
783
+ // Encode is declarative (field annotation forces BigDecimal -> JSON
784
+ // string via Jackson's stdlib ToStringSerializer, so scale/precision
785
+ // survive the wire); decode is a plain expression since BigDecimal has
786
+ // no matching stdlib deserializer-by-annotation for "parse from string".
787
+ encode: "@JsonSerialize(using = ToStringSerializer.class)",
788
+ decode: "new BigDecimal($)",
789
+ imports: [
790
+ "import java.math.BigDecimal;",
791
+ "import com.fasterxml.jackson.databind.annotation.JsonSerialize;",
792
+ "import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;"
793
+ ],
665
794
  mode: "native"
666
795
  },
667
796
  byte: {
668
- // byte[] serialises as base64 by default in Jackson.
669
- encode: "__SCAFFOLD_JAVA_BYTE_ENCODE__",
670
- decode: "__SCAFFOLD_JAVA_BYTE_DECODE__",
797
+ // byte[] <-> base64 String is Jackson's built-in default codec โ€” no
798
+ // annotation, no wrapping expression. The dispatcher glue passes the
799
+ // value through unchanged; Jackson's ObjectMapper performs the base64
800
+ // transcoding when the JsonNode tree is built/read.
801
+ encode: "$",
802
+ decode: "$",
671
803
  mode: "native"
672
804
  },
673
805
  uuid: {
674
- // UUID.toString() / UUID.fromString() โ€” stdlib Java.
675
- encode: "__SCAFFOLD_JAVA_UUID_ENCODE__",
676
- decode: "__SCAFFOLD_JAVA_UUID_DECODE__",
806
+ // UUID.toString() / UUID.fromString($) โ€” stdlib Java, no Jackson module.
807
+ encode: "$.toString()",
808
+ decode: "UUID.fromString($)",
677
809
  imports: ["import java.util.UUID;"],
678
810
  mode: "native"
679
811
  },
680
812
  "number-special": {
681
- // Custom StdSerializer โ€” stdlib Jackson.
682
- encode: "__SCAFFOLD_JAVA_NUMSPECIAL_ENCODE__",
683
- decode: "__SCAFFOLD_JAVA_NUMSPECIAL_DECODE__",
813
+ // NaN/Infinity/-Infinity have no native JSON representation; mirrors the
814
+ // TS numToWire/wireToNum inline helpers with a small custom Jackson
815
+ // StdSerializer/StdDeserializer pair, generated inline by
816
+ // renderDispatcherJava (class names below are the fixed contract the
817
+ // generator emits โ€” apigen-plugin-java-javalin/src/lib/dispatcher-template.ts).
818
+ encode: "@JsonSerialize(using = NumberSpecialSerializer.class)",
819
+ decode: "@JsonDeserialize(using = NumberSpecialDeserializer.class)",
820
+ imports: [
821
+ "import com.fasterxml.jackson.databind.annotation.JsonSerialize;",
822
+ "import com.fasterxml.jackson.databind.annotation.JsonDeserialize;"
823
+ ],
684
824
  mode: "native"
685
825
  }
686
- }, y = Object.freeze({
687
- typescript: B,
688
- python: k,
689
- rust: J,
690
- go: V,
691
- java: Y
826
+ }, g = Object.freeze({
827
+ typescript: X,
828
+ python: V,
829
+ rust: Z,
830
+ go: H,
831
+ java: Q
692
832
  });
693
- function oe(e) {
694
- return y[e];
833
+ function ue(e) {
834
+ return g[e];
695
835
  }
696
- function ne(e, o) {
697
- const t = y[o], n = [];
698
- for (const r of e) {
699
- const d = t[r];
700
- d != null && d.dep && n.push({ id: r, dep: d.dep });
836
+ function pe(e, r) {
837
+ const t = g[r], n = [];
838
+ for (const o of e) {
839
+ const i = t[o];
840
+ i != null && i.dep && n.push({ id: o, dep: i.dep });
701
841
  }
702
842
  return n;
703
843
  }
704
- function re() {
705
- const e = y.typescript, o = {};
706
- for (const t of T) {
844
+ function me() {
845
+ const e = g.typescript, r = {};
846
+ for (const t of j) {
707
847
  const n = e[t].dep;
708
- n && (o[t] = n);
848
+ n && (r[t] = n);
709
849
  }
710
- return Object.freeze(o);
850
+ return Object.freeze(r);
711
851
  }
712
- function ie(e, o) {
713
- const t = o ?? y[e], n = [];
714
- for (const r of T)
715
- t[r] || n.push(r);
852
+ function _e(e, r) {
853
+ const t = r ?? g[e], n = [];
854
+ for (const o of j)
855
+ t[o] || n.push(o);
716
856
  if (n.length > 0)
717
857
  throw new Error(
718
858
  `[hints] assertNoEmptyCells: language "${e}" is missing cells for: ${n.join(
@@ -721,31 +861,33 @@ function ie(e, o) {
721
861
  );
722
862
  }
723
863
  export {
724
- T as CANONICAL_LOGICAL_TYPE_IDS,
725
- g as CodecRegistryError,
726
- l as ENVELOPE_KEY,
727
- X as LOGICAL_TYPE_VERSION,
728
- y as TEMPLATE_CELLS,
729
- U as X_APIGEN_CODEC,
730
- W as X_APIGEN_CTOR,
731
- v as X_APIGEN_LOGICAL,
732
- K as X_APIGEN_TOJSON,
733
- ie as assertNoEmptyCells,
734
- Q as buildTranscoder,
735
- $ as byteCodec,
736
- oe as cellsFor,
737
- Z as codecIdOf,
738
- z as createRegistry,
739
- b as dateTimeCodec,
740
- F as decimalCodec,
741
- ne as depsForLogicalTypes,
742
- N as int64Codec,
743
- H as logicalKindOf,
744
- ee as makeDecimal,
745
- I as numberSpecialCodec,
746
- te as registerWellKnown,
747
- x as tryRegister,
748
- re as tsDepMap,
864
+ j as CANONICAL_LOGICAL_TYPE_IDS,
865
+ C as CodecRegistryError,
866
+ D as ENVELOPE_KEY,
867
+ re as LOGICAL_TYPE_VERSION,
868
+ g as TEMPLATE_CELLS,
869
+ P as X_APIGEN_CODEC,
870
+ ee as X_APIGEN_CTOR,
871
+ R as X_APIGEN_LOGICAL,
872
+ te as X_APIGEN_TOJSON,
873
+ _e as assertNoEmptyCells,
874
+ se as buildTranscoder,
875
+ F as byteCodec,
876
+ ue as cellsFor,
877
+ oe as codecIdOf,
878
+ x as createRegistry,
879
+ v as dateTimeCodec,
880
+ T as decimalCodec,
881
+ pe as depsForLogicalTypes,
882
+ I as int64Codec,
883
+ ne as logicalKindOf,
884
+ de as makeDecimal,
885
+ U as numberSpecialCodec,
886
+ ae as registerWellKnown,
887
+ fe as renderExampleNote,
888
+ y as synthesizeExample,
889
+ ce as tryRegister,
890
+ me as tsDepMap,
749
891
  L as uuidCodec,
750
- q as validateSchemaRefs
892
+ ie as validateSchemaRefs
751
893
  };
@@ -0,0 +1,35 @@
1
+ /** The minimal JSON-Schema-shaped structure this module reads. */
2
+ export interface JsonSchemaLike {
3
+ type?: string | string[];
4
+ properties?: Record<string, JsonSchemaLike>;
5
+ required?: string[];
6
+ items?: JsonSchemaLike | JsonSchemaLike[];
7
+ enum?: unknown[];
8
+ const?: unknown;
9
+ format?: string;
10
+ oneOf?: JsonSchemaLike[];
11
+ anyOf?: JsonSchemaLike[];
12
+ allOf?: JsonSchemaLike[];
13
+ $ref?: string;
14
+ definitions?: Record<string, JsonSchemaLike>;
15
+ $defs?: Record<string, JsonSchemaLike>;
16
+ [key: string]: unknown;
17
+ }
18
+ /**
19
+ * Synthesize a minimal, AJV-plausible example value for `schema`.
20
+ *
21
+ * @param schema - The schema fragment to synthesize a value for.
22
+ * @param root - The document root `$ref`s in `schema` (and its descendants)
23
+ * resolve against. Defaults to `schema` itself โ€” correct for the common
24
+ * case where `schema` IS the whole self-contained document (apigen always
25
+ * composes schemas this way; see module doc).
26
+ * @param depth - Internal recursion guard; callers never need to pass this.
27
+ */
28
+ export declare function synthesizeExample(schema: JsonSchemaLike | undefined, root?: JsonSchemaLike, depth?: number): unknown;
29
+ /**
30
+ * Render `schema`'s synthesized example as a compact `Example: {...}` note,
31
+ * or `undefined` if there's nothing meaningful to show (schema absent).
32
+ * Shared rendering so every call site (tool descriptions, validation error
33
+ * messages) produces byte-identical example text for the same schema.
34
+ */
35
+ export declare function renderExampleNote(schema: JsonSchemaLike | undefined): string | undefined;
package/lib/hints.d.ts CHANGED
@@ -15,18 +15,22 @@ export type CanonicalLogicalTypeId = (typeof CANONICAL_LOGICAL_TYPE_IDS)[number]
15
15
  export type LanguageTable = Record<CanonicalLogicalTypeId, TemplateCell>;
16
16
  /**
17
17
  * @stable The host languages for which a template column exists in
18
- * {@link TEMPLATE_CELLS}. `'typescript'` and `'python'` are fully filled
19
- * (ยง13.2 values verbatim). `'rust'`, `'go'`, and `'java'` are scaffolded โ€”
20
- * structure complete, expressions use stable placeholders pending the
21
- * `lt-host-*` states.
18
+ * {@link TEMPLATE_CELLS}. `'typescript'`, `'python'`, and `'java'` (FEAT-APIGEN-001
19
+ * slice 1/3, 2026-08-06) are fully filled (ยง13.2 values verbatim / real
20
+ * Jackson expressions โ€” see the `JAVA_COLUMN` doc comments below).
21
+ * `'rust'` and `'go'` remain scaffolded โ€” structure complete, expressions
22
+ * use stable placeholders pending the `lt-host-*` states.
22
23
  */
23
24
  export type HostLanguage = 'typescript' | 'python' | 'rust' | 'go' | 'java';
24
25
  /**
25
26
  * @stable The template-cell registry: `[language][logicalTypeId] โ†’ TemplateCell`.
26
27
  *
27
- * TypeScript and Python columns are fully filled per DESIGN ยง13.2 (verbatim
28
- * expressions). Rust, Go, and Java columns are scaffolded โ€” structure complete,
29
- * expressions use `__SCAFFOLD_*__` placeholders pending `lt-host-*` states.
28
+ * TypeScript, Python, and Java columns are fully filled (TypeScript/Python
29
+ * per DESIGN ยง13.2 verbatim expressions; Java per FEAT-APIGEN-001 slice 1/3 โ€”
30
+ * real Jackson annotation/expression glue, no `__SCAFFOLD_*__` left โ€” see
31
+ * `JAVA_COLUMN` above). Rust and Go columns remain scaffolded โ€” structure
32
+ * complete, expressions use `__SCAFFOLD_*__` placeholders pending `lt-host-*`
33
+ * states.
30
34
  *
31
35
  * Keyed by {@link HostLanguage}, then by the canonical {@link CanonicalLogicalTypeId}.
32
36
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhd/apigen-base-logical",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "main": "./index.js",
5
5
  "module": "./index.mjs",
6
6
  "typings": "./index.d.ts"