{"version":3,"sources":["../src/core/types.ts","../src/core/edge-endpoints.ts","../src/constraints/index.ts","../src/utils/tuple-key.ts","../src/store/claims/axis.ts"],"names":["ValidationError","compareStrings","createDataKeyedBag","ConfigurationError","hasOwnKey","readOwnProperty","isPresent","CardinalityError","EndpointError","EndpointPairError","DisjointError"],"mappings":";;;;;;;AAyCO,IAAM,eAAA,GAAkB;AAGxB,IAAM,eAAA,GAAkB;AAQ/B,SAAS,gBAAA,CAAiB,OAAe,IAAA,EAAoB;AAC3D,EAAA,IAAI,KAAA,CAAM,SAAS,CAAA,EAAG;AACpB,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,IAAIA,iCAAA;AAAA,IACR,GAAG,IAAI,CAAA,4BAAA,CAAA;AAAA,IACP;AAAA,MACE,MAAA,EAAQ;AAAA,QACN;AAAA,UACE,IAAA;AAAA,UACA,OAAA,EAAS;AAAA;AACX;AACF,KACF;AAAA,IACA;AAAA,MACE,UAAA,EACE;AAAA;AACJ,GACF;AACF;AA2FO,SAAS,SACd,KAAA,EACW;AACX,EAAA,gBAAA,CAAiB,OAAO,UAAU,CAAA;AAClC,EAAA,OAAO,KAAA;AACT;AAuFO,SAAS,SACd,KAAA,EACW;AACX,EAAA,gBAAA,CAAiB,OAAO,UAAU,CAAA;AAClC,EAAA,OAAO,KAAA;AACT;AA2KO,SAAS,WAAW,KAAA,EAAmC;AAC5D,EAAA,OACE,OAAO,UAAU,QAAA,IACjB,KAAA,KAAU,QACV,eAAA,IAAmB,KAAA,IAClB,KAAA,CAAkC,eAAe,CAAA,KAAM,IAAA;AAE5D;AAKO,SAAS,WAAW,KAAA,EAAsC;AAC/D,EAAA,OACE,OAAO,UAAU,QAAA,IACjB,KAAA,KAAU,QACV,eAAA,IAAmB,KAAA,IAClB,KAAA,CAAkC,eAAe,CAAA,KAAM,IAAA;AAE5D;AAMO,SAAS,wBACd,KAAA,EACgC;AAChC,EAAA,IAAI,CAAC,UAAA,CAAW,KAAK,CAAA,EAAG;AACtB,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,MAAM,SAAA,GAAY,KAAA;AAClB,EAAA,IACE,CAAC,MAAM,OAAA,CAAQ,SAAA,CAAU,MAAM,CAAC,CAAA,IAChC,UAAU,MAAM,CAAA,CAAE,WAAW,CAAA,IAC7B,OAAO,UAAU,IAAI,CAAA,KAAM,YAC3B,SAAA,CAAU,IAAI,MAAM,IAAA,EACpB;AACA,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,OAAO,MAAM,OAAA,CAAQ,SAAA,CAAU,IAAI,CAAC,IAChC,SAAA,CAAU,IAAI,CAAA,CAAE,MAAA,GAAS,IACzB,MAAA,CAAO,IAAA,CAAK,UAAU,IAAI,CAAC,EAAE,MAAA,GAAS,CAAA;AAC5C;;;ACvcO,SAAS,gBAAgB,KAAA,EAAwC;AACtE,EAAA,OACE,OAAO,KAAA,KAAU,QAAA,IACjB,UAAU,IAAA,IACV,CAAC,MAAM,OAAA,CAAQ,KAAK,KACpB,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA,CAAE,MAAA,GAAS,KAC5B,MAAA,CAAO,MAAA,CAAO,KAAK,CAAA,CAAE,KAAA;AAAA,IACnB,CAAC,OAAA,KAAY,KAAA,CAAM,QAAQ,OAAO,CAAA,IAAK,QAAQ,MAAA,GAAS;AAAA,GAC1D;AAEJ;AAKO,SAAS,mBAAmB,EAAA,EAAsC;AACvE,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,EAAA,MAAM,SAAqB,EAAC;AAC5B,EAAA,MAAM,KAAA,GACJ,KAAA,CAAM,OAAA,CAAQ,EAAE,CAAA,GAAI,CAAC,EAAE,CAAA,GAAI,MAAA,CAAO,MAAA,CAAO,EAAE,CAAA;AAC7C,EAAA,KAAA,MAAW,WAAW,KAAA,EAAO;AAC3B,IAAA,KAAA,MAAW,QAAQ,OAAA,EAAS;AAC1B,MAAA,IAAI,CAAC,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,IAAI,CAAA,EAAG;AACxB,QAAA,IAAA,CAAK,GAAA,CAAI,KAAK,IAAI,CAAA;AAClB,QAAA,MAAA,CAAO,KAAK,IAAI,CAAA;AAAA,MAClB;AAAA,IACF;AAAA,EACF;AACA,EAAA,OAAO,MAAA;AACT;AAKO,SAAS,mBAAmB,EAAA,EAAoC;AACrE,EAAA,OAAO,mBAAmB,EAAE,CAAA,CAAE,IAAI,CAAC,IAAA,KAAS,KAAK,IAAI,CAAA;AACvD;AAaO,SAAS,oBAAA,CACd,MACA,EAAA,EACyB;AACzB,EAAA,MAAM,QAAwB,EAAC;AAC/B,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAE7B,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,EAAE,CAAA,EAAG;AACrB,IAAA,MAAM,OAAA,GAA+B,EAAA;AACrC,IAAA,KAAA,MAAW,YAAY,IAAA,EAAM;AAC3B,MAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,QAAA,MAAM,MAAM,CAAA,EAAG,QAAA,CAAS,IAAI,CAAA,EAAA,EAAK,OAAO,IAAI,CAAA,CAAA;AAC5C,QAAA,IAAI,CAAC,IAAA,CAAK,GAAA,CAAI,GAAG,CAAA,EAAG;AAClB,UAAA,IAAA,CAAK,IAAI,GAAG,CAAA;AACZ,UAAA,KAAA,CAAM,IAAA,CAAK,EAAE,IAAA,EAAM,QAAA,CAAS,MAAM,EAAA,EAAI,MAAA,CAAO,MAAM,CAAA;AAAA,QACrD;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAA,MAAO;AACL,IAAA,MAAM,KAAA,GAAuB,EAAA;AAC7B,IAAA,KAAA,MAAW,CAAC,UAAA,EAAY,OAAO,KAAK,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,EAAG;AACzD,MAAA,KAAA,MAAW,cAAc,OAAA,EAAS;AAChC,QAAA,MAAM,GAAA,GAAM,CAAA,EAAG,UAAU,CAAA,EAAA,EAAK,WAAW,IAAI,CAAA,CAAA;AAC7C,QAAA,IAAI,CAAC,IAAA,CAAK,GAAA,CAAI,GAAG,CAAA,EAAG;AAClB,UAAA,IAAA,CAAK,IAAI,GAAG,CAAA;AACZ,UAAA,KAAA,CAAM,KAAK,EAAE,IAAA,EAAM,YAAY,EAAA,EAAI,UAAA,CAAW,MAAM,CAAA;AAAA,QACtD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,KAAA,CAAM,QAAA,CAAS,CAAC,CAAA,EAAG,CAAA,KAAM;AAC9B,IAAA,MAAM,GAAA,GAAMC,gCAAA,CAAe,CAAA,CAAE,IAAA,EAAM,EAAE,IAAI,CAAA;AACzC,IAAA,IAAI,GAAA,KAAQ,GAAG,OAAO,GAAA;AACtB,IAAA,OAAOA,gCAAA,CAAe,CAAA,CAAE,EAAA,EAAI,CAAA,CAAE,EAAE,CAAA;AAAA,EAClC,CAAC,CAAA;AACH;AAKO,SAAS,oBAAoB,KAAA,EAAwC;AAC1E,EAAA,OAAO,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,KAAS,CAAA,CAAA,EAAI,IAAA,CAAK,IAAI,CAAA,IAAA,EAAO,IAAA,CAAK,EAAE,CAAA,CAAA,CAAG,CAAA,CAAE,KAAK,IAAI,CAAA;AACtE;AAKO,SAAS,mBAAmB,EAAA,EAAkC;AACnE,EAAA,MAAM,SAASC,oCAAA,EAAwC;AACvD,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,OAAO,KAAK,MAAA,CAAO,OAAA,CAAQ,EAAE,CAAA,EAAG;AAC/C,IAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,IAAA,MAAM,gBAA4B,EAAC;AACnC,IAAA,KAAA,MAAW,KAAK,OAAA,EAAS;AACvB,MAAA,IAAI,CAAC,IAAA,CAAK,GAAA,CAAI,CAAA,CAAE,IAAI,CAAA,EAAG;AACrB,QAAA,IAAA,CAAK,GAAA,CAAI,EAAE,IAAI,CAAA;AACf,QAAA,aAAA,CAAc,KAAK,CAAC,CAAA;AAAA,MACtB;AAAA,IACF;AACA,IAAA,MAAA,CAAO,GAAG,CAAA,GAAI,MAAA,CAAO,MAAA,CAAO,aAAa,CAAA;AAAA,EAC3C;AACA,EAAA,OAAO,MAAA,CAAO,MAAA,CAAO,EAAE,GAAG,QAAQ,CAAA;AACpC;AAKO,SAAS,wBAAA,CACd,IAAA,EACA,IAAA,EACA,EAAA,EAC6B;AAC7B,EAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,IAAK,IAAA,CAAK,WAAW,CAAA,EAAG;AAC7C,IAAA,MAAM,IAAIC,oCAAA;AAAA,MACR,SAAS,IAAI,CAAA,4EAAA,CAAA;AAAA,MACb,EAAE,UAAU,IAAA,EAAK;AAAA,MACjB;AAAA,QACE,UAAA,EAAY,CAAA,mFAAA;AAAA;AACd,KACF;AAAA,EACF;AAEA,EAAA,IAAI,OAAO,OAAO,QAAA,IAAY,EAAA,KAAO,QAAQ,KAAA,CAAM,OAAA,CAAQ,EAAE,CAAA,EAAG;AAC9D,IAAA,MAAM,IAAIA,oCAAA;AAAA,MACR,SAAS,IAAI,CAAA,sFAAA,CAAA;AAAA,MACb,EAAE,UAAU,IAAA;AAAK,KACnB;AAAA,EACF;AAEA,EAAA,MAAM,sBAAsB,IAAI,GAAA;AAAA,IAC9B,IAAA,CAAK,GAAA,CAAI,CAAC,IAAA,KAA2B,KAAK,IAAI;AAAA,GAChD;AACA,EAAA,MAAM,kBAAA,GAAqB,CAAC,GAAG,mBAAmB,CAAA;AAClD,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,IAAA,CAAK,EAAE,CAAA;AAG9B,EAAA,KAAA,MAAW,cAAc,mBAAA,EAAqB;AAC5C,IAAA,IAAI,CAACC,2BAAA,CAAU,EAAA,EAAyC,UAAU,CAAA,EAAG;AACnE,MAAA,MAAM,IAAID,oCAAA;AAAA,QACR,CAAA,MAAA,EAAS,IAAI,CAAA,sDAAA,EAAyD,UAAU,CAAA,EAAA,CAAA;AAAA,QAChF;AAAA,UACE,QAAA,EAAU,IAAA;AAAA,UACV,UAAA,EAAY,UAAA;AAAA,UACZ,eAAA,EAAiB;AAAA,SACnB;AAAA,QACA;AAAA,UACE,UAAA,EAAY,CAAA,kBAAA,EAAqB,UAAU,CAAA,yBAAA,EAA4B,UAAU,CAAA,UAAA;AAAA;AACnF,OACF;AAAA,IACF;AAAA,EACF;AAGA,EAAA,KAAA,MAAW,OAAO,OAAA,EAAS;AACzB,IAAA,IAAI,CAAC,mBAAA,CAAoB,GAAA,CAAI,GAAG,CAAA,EAAG;AACjC,MAAA,MAAM,IAAIA,oCAAA;AAAA,QACR,CAAA,MAAA,EAAS,IAAI,CAAA,aAAA,EAAgB,GAAG,oDAAoD,kBAAA,CAAmB,IAAA,CAAK,IAAI,CAAC,CAAA,EAAA,CAAA;AAAA,QACjH;AAAA,UACE,QAAA,EAAU,IAAA;AAAA,UACV,QAAA,EAAU,GAAA;AAAA,UACV,eAAA,EAAiB;AAAA,SACnB;AAAA,QACA;AAAA,UACE,UAAA,EAAY,CAAA,QAAA,EAAW,GAAG,CAAA,2CAAA,EAA8C,GAAG,CAAA,2DAAA;AAAA;AAC7E,OACF;AAAA,IACF;AAAA,EACF;AAGA,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,OAAO,KAAK,MAAA,CAAO,OAAA,CAAQ,EAAE,CAAA,EAAG;AAC/C,IAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAA,IAAK,OAAA,CAAQ,WAAW,CAAA,EAAG;AACnD,MAAA,MAAM,IAAIA,oCAAA;AAAA,QACR,CAAA,MAAA,EAAS,IAAI,CAAA,gCAAA,EAAmC,GAAG,CAAA,0CAAA,CAAA;AAAA,QACnD,EAAE,QAAA,EAAU,IAAA,EAAM,UAAA,EAAY,GAAA,EAAI;AAAA,QAClC;AAAA,UACE,UAAA,EAAY,CAAA,uDAAA,EAA0D,GAAG,CAAA,KAAA,EAAQ,GAAG,CAAA,iBAAA;AAAA;AACtF,OACF;AAAA,IACF;AACA,IAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,MAAA,IAAI,CAAC,UAAA,CAAW,MAAM,CAAA,EAAG;AACvB,QAAA,MAAM,IAAIA,oCAAA;AAAA,UACR,CAAA,MAAA,EAAS,IAAI,CAAA,0BAAA,EAA6B,GAAG,CAAA,qCAAA,CAAA;AAAA,UAC7C,EAAE,QAAA,EAAU,IAAA,EAAM,UAAA,EAAY,GAAA,EAAK,eAAe,MAAA,EAAO;AAAA,UACzD;AAAA,YACE,UAAA,EAAY,CAAA,kEAAA;AAAA;AACd,SACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AC7MA,IAAM,oBAAA,GAAuB,GAAA;AAG7B,IAAM,sBAAA,GAAyB,GAAA;AAyCxB,SAAS,gBAAA,CACd,KAAA,EACA,MAAA,EACA,SAAA,EACQ;AACR,EAAA,MAAM,MAAA,GAAS,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,KAAU;AACnC,IAAA,MAAM,KAAA,GAAQE,iCAAA,CAAgB,KAAA,EAAO,KAAK,CAAA;AAC1C,IAAA,IAAI,KAAA,KAAU,MAAA,IAAa,KAAA,KAAU,IAAA,EAAM;AACzC,MAAA,OAAO,sBAAA;AAAA,IACT;AAEA,IAAA,MAAM,cACJ,OAAO,KAAA,KAAU,QAAA,GAAW,KAAA,GAC1B,OAAO,KAAA,KAAU,QAAA,IAAY,OAAO,KAAA,KAAU,YAC9C,KAAA,CAAM,QAAA,EAAS,GACf,IAAA,CAAK,UAAU,KAAK,CAAA;AACxB,IAAA,OAAO,SAAA,KAAc,iBAAA,GACjB,WAAA,CAAY,WAAA,EAAY,GACxB,WAAA;AAAA,EACN,CAAC,CAAA;AACD,EAAA,OAAO,MAAA,CAAO,KAAK,oBAAoB,CAAA;AACzC;AAqBO,SAAS,mBAAA,CACd,YACA,KAAA,EACS;AACT,EAAA,IAAI,CAAC,WAAW,KAAA,EAAO;AACrB,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,SAAA,GAAY,qBAAA,CAAsB,UAAA,CAAW,KAAK,CAAA;AACxD,EAAA,IAAI,cAAc,MAAA,EAAW;AAC3B,IAAA,MAAM,IAAIF,oCAAA;AAAA,MACR,CAAA,mBAAA,EAAsB,WAAW,IAAI,CAAA,4DAAA,CAAA;AAAA,MACrC,EAAE,gBAAgB,UAAA,CAAW,IAAA,EAAM,QAAQ,CAAC,GAAG,UAAA,CAAW,MAAM,CAAA,EAAE;AAAA,MAClE;AAAA,QACE,YAAY,CAAA,2DAAA,EAA8D,UAAA,CAAW,MAAA,CAAO,CAAC,KAAK,WAAW,CAAA,yHAAA;AAAA;AAC/G,KACF;AAAA,EACF;AAEA,EAAA,OAAO,iBAAA,CAAkB,WAAW,KAAK,CAAA;AAC3C;AAyCO,SAAS,sBACd,KAAA,EAC6B;AAC7B,EAAA,MAAM,SAAA,GAAY,KAAA,CAAM,qBAAA,EAAuB,CAAA;AAC/C,EAAA,IACE,OAAO,SAAA,KAAc,QAAA,IACrB,cAAc,IAAA,IACd,EAAE,YAAY,SAAA,CAAA,EACd;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,MAAM,SAAA,GAAY,SAAA;AAKlB,EAAA,IACE,SAAA,CAAU,MAAA,KAAW,kBAAA,IACrB,OAAO,SAAA,CAAU,KAAA,KAAU,QAAA,IAC1B,SAAA,CAAU,EAAA,KAAO,QAAA,IAAY,SAAA,CAAU,EAAA,KAAO,WAAA,EAC/C;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,kBAAA;AAAA,IACR,OAAO,SAAA,CAAU,KAAA;AAAA,IACjB,IAAI,SAAA,CAAU;AAAA,GAChB;AACF;AAqBO,SAAS,wBAAA,CACd,IAAA,EACA,UAAA,EACA,KAAA,EACM;AACN,EAAA,IAAI,CAAC,WAAW,KAAA,EAAO;AAEvB,EAAA,MAAM,SAAA,GAAY,qBAAA,CAAsB,UAAA,CAAW,KAAK,CAAA;AACxD,EAAA,IAAI,cAAc,MAAA,EAAW;AAC3B,IAAA,MAAM,IAAIA,oCAAA;AAAA,MACR,CAAA,mBAAA,EAAsB,UAAA,CAAW,IAAI,CAAA,gBAAA,EAAmB,IAAI,CAAA,4DAAA,CAAA;AAAA,MAC5D,EAAE,IAAA,EAAM,cAAA,EAAgB,UAAA,CAAW,IAAA,EAAK;AAAA,MACxC;AAAA,QACE,UAAA,EAAY,8DAA8D,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA,CAAE,CAAC,KAAK,WAAW,CAAA,eAAA;AAAA;AAChH,KACF;AAAA,EACF;AAEA,EAAA,IAAI,CAACC,2BAAA,CAAU,KAAA,EAAO,SAAA,CAAU,KAAK,CAAA,EAAG;AACtC,IAAA,MAAM,IAAID,oCAAA;AAAA,MACR,sBAAsB,UAAA,CAAW,IAAI,mBAAmB,IAAI,CAAA,mCAAA,EAAsC,UAAU,KAAK,CAAA,8CAAA,CAAA;AAAA,MACjH;AAAA,QACE,IAAA;AAAA,QACA,gBAAgB,UAAA,CAAW,IAAA;AAAA,QAC3B,OAAO,SAAA,CAAU,KAAA;AAAA,QACjB,cAAA,EAAgB,MAAA,CAAO,IAAA,CAAK,KAAK;AAAA,OACnC;AAAA,MACA;AAAA,QACE,UAAA,EAAY,CAAA,uBAAA,EAA0B,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA,UAAA,EAAa,SAAA,CAAU,KAAK,CAAA,gBAAA;AAAA;AACjG,KACF;AAAA,EACF;AACF;AAyCA,SAAS,qBAAA,GAA0C;AACjD,EAAA,OAAO,IAAI,KAAA;AAAA,IACT,EAAC;AAAA,IACD;AAAA,MACE,GAAA,CAAI,SAAS,QAAA,EAAU;AACrB,QAAA,IAAI,OAAO,aAAa,QAAA,EAAU;AAClC,QAAA,OAAO;AAAA,UACL,QAAQ,OAAO;AAAA,YACb,MAAA,EAAQ,kBAAA;AAAA,YACR,KAAA,EAAO,QAAA;AAAA,YACP,EAAA,EAAI;AAAA,WACN,CAAA;AAAA,UACA,WAAW,OAAO;AAAA,YAChB,MAAA,EAAQ,kBAAA;AAAA,YACR,KAAA,EAAO,QAAA;AAAA,YACP,EAAA,EAAI;AAAA,WACN;AAAA,SACF;AAAA,MACF;AAAA;AACF,GACF;AACF;AAYA,SAAS,iBAAA,CACP,MACA,KAAA,EACS;AAKT,EAAA,MAAM,KAAA,GAAQE,iCAAA,CAAgB,KAAA,EAAO,IAAA,CAAK,KAAK,CAAA;AAC/C,EAAA,IAAI,IAAA,CAAK,OAAO,QAAA,EAAU;AACxB,IAAA,OAAO,KAAA,KAAU,QAAQ,KAAA,KAAU,MAAA;AAAA,EACrC;AACA,EAAA,OAAOC,4BAAU,KAAK,CAAA;AACxB;AA8CO,SAAS,iBAAA,CACd,MACA,QAAA,EACmB;AACnB,EAAA,OAAO,QAAA,CAAS,qBAAqB,IAAI,CAAA;AAC3C;AA0DO,SAAS,iBACd,QAAA,EACA,QAAA,EACA,MAAA,EACA,WAAA,EACA,mBACA,aAAA,EAC8B;AAC9B,EAAA,QAAQ,WAAA;AAAa,IACnB,KAAK,MAAA,EAAQ;AAEX,MAAA,OAAO,MAAA;AAAA,IACT;AAAA,IACA,KAAK,KAAA,EAAO;AAEV,MAAA,IAAI,oBAAoB,CAAA,EAAG;AACzB,QAAA,OAAO,IAAIC,kCAAA,CAAiB;AAAA,UAC1B,QAAA;AAAA,UACA,QAAA;AAAA,UACA,MAAA;AAAA,UACA,WAAA,EAAa,KAAA;AAAA,UACb,aAAA,EAAe;AAAA,SAChB,CAAA;AAAA,MACH;AACA,MAAA,OAAO,MAAA;AAAA,IACT;AAAA,IACA,KAAK,QAAA,EAAU;AAEb,MAAA,OAAO,MAAA;AAAA,IACT;AAAA,IACA,KAAK,WAAA,EAAa;AAEhB,MAAA,IAAI,aAAA,EAAe;AACjB,QAAA,OAAO,IAAIA,kCAAA,CAAiB;AAAA,UAC1B,QAAA;AAAA,UACA,QAAA;AAAA,UACA,MAAA;AAAA,UACA,WAAA,EAAa,WAAA;AAAA,UACb,aAAA,EAAe;AAAA,SAChB,CAAA;AAAA,MACH;AACA,MAAA,OAAO,MAAA;AAAA,IACT;AAAA;AAEJ;AAKO,SAAS,gBACd,QAAA,EACA,QAAA,EACA,MAAA,EACA,OAAA,EACA,OACA,aAAA,EAC8B;AAC9B,EAAA,IAAI,gBAAgB,CAAA,EAAG;AACrB,IAAA,OAAO,IAAIA,kCAAA,CAAiB;AAAA,MAC1B,QAAA;AAAA,MACA,QAAA;AAAA,MACA,MAAA;AAAA,MACA,WAAA,EAAa,QAAA;AAAA,MACb;AAAA,KACD,CAAA;AAAA,EACH;AACA,EAAA,OAAO,MAAA;AACT;AASO,SAAS,qBAAA,CACd,QAAA,EACA,QAAA,EACA,MAAA,EACA,cACA,QAAA,EAC+C;AAE/C,EAAA,MAAM,iBAAiB,YAAA,CAAa,IAAA,CAAK,IAAI,CAAC,IAAA,KAAS,KAAK,IAAI,CAAA;AAChE,EAAA,IAAI,CAAC,QAAA,CAAS,iBAAA,CAAkB,QAAA,EAAU,cAAc,CAAA,EAAG;AACzD,IAAA,OAAO,IAAIC,+BAAA,CAAc;AAAA,MACvB,QAAA;AAAA,MACA,QAAA,EAAU,MAAA;AAAA,MACV,UAAA,EAAY,QAAA;AAAA,MACZ,aAAA,EAAe;AAAA,KAChB,CAAA;AAAA,EACH;AAGA,EAAA,IAAI,eAAA,CAAgB,YAAA,CAAa,EAAE,CAAA,EAAG;AACpC,IAAA,MAAM,kBAAA,uBAAyB,GAAA,EAAY;AAC3C,IAAA,KAAA,MAAW,QAAA,IAAY,aAAa,IAAA,EAAM;AACxC,MAAA,IAAI,QAAA,CAAS,cAAA,CAAe,QAAA,EAAU,QAAA,CAAS,IAAI,CAAA,EAAG;AACpD,QAAA,MAAM,UAAU,YAAA,CAAa,EAAA,CAAG,QAAA,CAAS,IAAI,KAAK,EAAC;AACnD,QAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,UAAA,kBAAA,CAAmB,GAAA,CAAI,OAAO,IAAI,CAAA;AAAA,QACpC;AAAA,MACF;AAAA,IACF;AAEA,IAAA,IAAI,CAAC,SAAS,iBAAA,CAAkB,MAAA,EAAQ,CAAC,GAAG,kBAAkB,CAAC,CAAA,EAAG;AAChE,MAAA,OAAO,IAAIC,mCAAA,CAAkB;AAAA,QAC3B,QAAA;AAAA,QACA,QAAA;AAAA,QACA,MAAA;AAAA,QACA,YAAA,EAAc,oBAAA,CAAqB,YAAA,CAAa,IAAA,EAAM,aAAa,EAAE;AAAA,OACtE,CAAA;AAAA,IACH;AAEA,IAAA,OAAO,MAAA;AAAA,EACT;AAGA,EAAA,MAAM,eAAe,YAAA,CAAa,EAAA,CAAG,IAAI,CAAC,IAAA,KAAS,KAAK,IAAI,CAAA;AAC5D,EAAA,IAAI,CAAC,QAAA,CAAS,iBAAA,CAAkB,MAAA,EAAQ,YAAY,CAAA,EAAG;AACrD,IAAA,OAAO,IAAID,+BAAA,CAAc;AAAA,MACvB,QAAA;AAAA,MACA,QAAA,EAAU,IAAA;AAAA,MACV,UAAA,EAAY,MAAA;AAAA,MACZ,aAAA,EAAe;AAAA,KAChB,CAAA;AAAA,EACH;AAEA,EAAA,OAAO,MAAA;AACT;AAeO,SAAS,iBAAA,CACd,MAAA,EACA,QAAA,EACA,aAAA,EACA,QAAA,EAC2B;AAC3B,EAAA,KAAA,MAAW,gBAAgB,aAAA,EAAe;AACxC,IAAA,IAAI,QAAA,CAAS,WAAA,CAAY,QAAA,EAAU,YAAY,CAAA,EAAG;AAChD,MAAA,OAAO,IAAIE,+BAAA,CAAc;AAAA,QACvB,MAAA;AAAA,QACA,aAAA,EAAe,QAAA;AAAA,QACf,eAAA,EAAiB;AAAA,OAClB,CAAA;AAAA,IACH;AAAA,EACF;AACA,EAAA,OAAO,MAAA;AACT;;;ACnlBO,SAAS,eAAe,MAAA,EAAmC;AAChE,EAAA,OAAO,IAAA,CAAK,UAAU,MAAM,CAAA;AAC9B;;;AC6BA,IAAM,cAAA,GAAiB,GAAA;AAGvB,IAAM,oBAAA,GAAuB,CAAA,EAAG,cAAc,CAAA,QAAA,EAAW,cAAc,CAAA,CAAA;AAWhE,IAAM,wBAAA,GAA2B,GAAG,cAAc,CAAA,YAAA;AAgBlD,SAAS,qBAAA,CACd,IAAA,EACA,SAAA,EACA,QAAA,EACQ;AACR,EAAA,OAAO,GAAG,oBAAoB,CAAA,EAAG,SAAS,iBAAA,CAAkB,IAAA,EAAM,SAAS,CAAC,CAAA,CAAA;AAC9E;AAiBO,SAAS,mBAAA,CAAoB,MAAc,OAAA,EAAuB;AACvE,EAAA,IAAI,CAAC,IAAA,CAAK,QAAA,CAAS,cAAc,CAAA,EAAG;AACpC,EAAA,MAAM,IAAIP,oCAAA;AAAA,IACR,GAAG,OAAO,CAAA,MAAA,EAAS,IAAA,CAAK,SAAA,CAAU,IAAI,CAAC,CAAA,0DAAA,CAAA;AAAA,IACvC,EAAE,IAAA,EAAK;AAAA,IACP;AAAA,MACE,UAAA,EAAY,CAAA,0DAAA;AAAA;AACd,GACF;AACF;AAoBA,SAAS,oBAAA,CACP,IAAA,EACA,KAAA,EACA,QAAA,EACmB;AACnB,EAAA,OAAO,UAAU,MAAA,GAAS,CAAC,IAAI,CAAA,GAAI,iBAAA,CAAkB,MAAM,QAAQ,CAAA;AACrE;AAGO,SAAS,qBAAA,CACd,IAAA,EACA,KAAA,EACA,QAAA,EACuB;AACvB,EAAA,MAAM,KAAA,GAAQ,oBAAA,CAAqB,IAAA,EAAM,KAAA,EAAO,QAAQ,CAAA;AACxD,EAAA,OAAO,EAAE,MAAM,KAAA,CAAM,CAAC,KAAK,IAAA,EAAM,SAAA,EAAW,KAAA,CAAM,MAAA,GAAS,CAAA,EAAE;AAC/D;AAYO,SAAS,mBAAA,CACd,IAAA,EACA,KAAA,EACA,QAAA,EACQ;AACR,EAAA,OAAO,qBAAA,CAAsB,IAAA,EAAM,KAAA,EAAO,QAAQ,CAAA,CAAE,IAAA;AACtD;AAkBO,SAAS,oBAAA,CACd,IAAA,EACA,KAAA,EACA,QAAA,EACmB;AACnB,EAAA,MAAM,IAAA,GAAO,mBAAA,CAAoB,IAAA,EAAM,KAAA,EAAO,QAAQ,CAAA;AACtD,EAAA,MAAM,YAAA,GAAe,oBAAA,CAAqB,IAAA,EAAM,KAAA,EAAO,QAAQ,CAAA;AAC/D,EAAA,MAAM,IAAA,GAAO,YAAA,CACV,MAAA,CAAO,CAAC,cAAc,SAAA,KAAc,IAAI,CAAA,CACxC,QAAA,CAAS,CAAC,IAAA,EAAM,KAAA,KAAUF,gCAAA,CAAe,IAAA,EAAM,KAAK,CAAC,CAAA;AACxD,EAAA,OAAO,CAAC,IAAA,EAAM,GAAG,IAAI,CAAA;AACvB;AAYO,SAAS,mBAAA,CACd,aACA,QAAA,EACQ;AACR,EAAA,OAAO,CAAA,EAAG,WAAW,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAA;AACnC;AAoCO,SAAS,mBAAA,CACd,MACA,KAAA,EACQ;AACR,EAAA,OACEA,gCAAA,CAAe,IAAA,CAAK,QAAA,EAAU,KAAA,CAAM,QAAQ,CAAA,IAC5CA,gCAAA,CAAe,IAAA,CAAK,OAAA,EAAS,KAAA,CAAM,OAAO,CAAA,IAC1CA,iCAAe,IAAA,CAAK,IAAA,EAAM,KAAA,CAAM,IAAI,CAAA,IACpCA,gCAAA,CAAe,IAAA,CAAK,cAAA,IAAkB,EAAA,EAAI,KAAA,CAAM,cAAA,IAAkB,EAAE,CAAA,IACpEA,gCAAA,CAAe,IAAA,CAAK,GAAA,EAAK,MAAM,GAAG,CAAA;AAEtC;AAiBO,SAAS,gBAAA,CAAiB,MAAkB,KAAA,EAA4B;AAC7E,EAAA,OACE,KAAK,MAAA,KAAW,KAAA,CAAM,MAAA,IAAU,IAAA,CAAK,iBAAiB,KAAA,CAAM,YAAA;AAEhE;AAaO,SAAS,cAAc,KAAA,EAA2B;AACvD,EAAA,OAAO,eAAe,CAAC,KAAA,CAAM,YAAA,EAAc,KAAA,CAAM,MAAM,CAAC,CAAA;AAC1D;AA6BO,SAAS,oBAAA,CACd,GAAA,EAIA,QAAA,EACA,QAAA,EACA,OAAA,EACa;AACb,EAAA,OAAO,MAAM,QAAA,CAAS,OAAA,CAAQ,MAAM,CAAC,CAAA,GAAA,EAAM,SAAS,OAAA,CAAQ,MAAM,CAAC,CAAA,KAAA,EAAQ,QAAA,CAAS,QAAQ,YAAY,CAAC,MAAM,QAAA,CAAS,OAAA,CAAQ,YAAY,CAAC,CAAA,CAAA;AAC/I","file":"chunk-5ICDVLI3.cjs","sourcesContent":["import { type z } from \"zod\";\n\nimport { ValidationError } from \"../errors\";\n\n// ============================================================\n// Cross-cutting Discriminators\n// ============================================================\n\n/**\n * Which side of the bipartite graph a kind lives on. Used everywhere a\n * function takes \"the entity that owns a kind\" — error metadata,\n * extension classifiers, removal queues, schema diffs.\n */\nexport type KindEntity = \"node\" | \"edge\";\n\n/**\n * Which physical surface an index targets. Vector indexes don't own a\n * kind directly (they back a per-`(kind, field)` typed embedding table\n * owned by the active `VectorStrategy`), but they participate in the same\n * materialization and diff pipelines, so they share this discriminator.\n *\n * `\"system\"` marks TypeGraph's own base-relation indexes\n * (`SYSTEM_INDEX_DECLARATIONS`) — graph-independent, but materialized and\n * status-tracked through the same pipeline; their status rows carry the\n * relation key (e.g. `\"recordedNodes\"`) in the `kind` column.\n */\nexport type IndexEntity = \"node\" | \"edge\" | \"vector\" | \"system\";\n\n/**\n * Field-level null-check operations that round-trip through persisted\n * documents (unique-constraint where clauses, index where clauses,\n * graph-extension where clauses, IsNullPredicate). Consolidated so a\n * single rename or extension touches one site.\n */\nexport type NullCheckOp = \"isNull\" | \"isNotNull\";\n\n// ============================================================\n// Brand Keys for Nominal Typing\n// ============================================================\n\n/** Brand key for NodeType */\nexport const NODE_TYPE_BRAND = \"__nodeType\" as const;\n\n/** Brand key for EdgeType */\nexport const EDGE_TYPE_BRAND = \"__edgeType\" as const;\n\n/** Brand symbol for NodeId */\ndeclare const __nodeId: unique symbol;\n\n/** Brand symbol for EdgeId */\ndeclare const __edgeId: unique symbol;\n\nfunction assertNonEmptyId(value: string, path: string): void {\n  if (value.length > 0) {\n    return;\n  }\n\n  throw new ValidationError(\n    `${path} must be a non-empty string.`,\n    {\n      issues: [\n        {\n          path,\n          message: \"Expected a non-empty string.\",\n        },\n      ],\n    },\n    {\n      suggestion:\n        \"Use a persisted node or edge id value, or let TypeGraph generate an id on create.\",\n    },\n  );\n}\n\n// ============================================================\n// Node Type\n// ============================================================\n\n/** A primitive JSON value, excluding arrays and objects. */\nexport type JsonScalar = null | string | number | boolean;\n\n/**\n * Any JSON-serializable value.\n *\n * Mirrors the JSON wire format: primitives, arrays, and string-keyed objects.\n * `null` is included because the JSON spec requires it for \"no value here\";\n * this is the one place in the public API that uses `null` over `undefined`.\n */\nexport type JsonValue =\n  JsonScalar | readonly JsonValue[] | Readonly<{ [key: string]: JsonValue }>;\n\n/**\n * Consumer-owned per-kind annotations.\n *\n * Stable labels attached to a node or edge kind at definition time — UI hints,\n * audit policy, provenance pointers, tooling annotations.\n *\n * **Consumer-owned, fully.** TypeGraph never reads, validates, or interprets\n * values in this field. Consumers own the entire namespace; there are no\n * reserved keys or extension prefixes. Future library-owned per-kind state,\n * if needed, will use a separate sibling field rather than carving out keys\n * here.\n *\n * **Annotations participate in schema hashing.** Any change to an annotation\n * value (or adding/removing an annotation key) bumps the canonical schema\n * hash and is reported as a `safe`-severity diff by `getSchemaChanges`. If\n * you don't want versioning for a piece of state, do not put it here.\n *\n * Values must be JSON-serializable — `bigint`, `function`, `symbol`, `undefined`,\n * `Date`, and other class instances are rejected at definition time so they can\n * never silently break schema hashing or storage round-trips.\n */\nexport type KindAnnotations = Readonly<Record<string, JsonValue>>;\n\n/**\n * Consumer-owned annotations for a graph as a whole.\n *\n * This is the schema-level counterpart to {@link KindAnnotations}: display\n * names, descriptions, capability declarations, and other JSON metadata that\n * describes the materialization itself rather than one node or edge kind.\n * Values participate in canonical schema hashing and annotation-only changes\n * are safe schema changes.\n */\nexport type GraphAnnotations = Readonly<Record<string, JsonValue>>;\n\n/**\n * A node type definition.\n *\n * Created via `defineNode()`. Represents a type of node in the graph\n * with an associated Zod schema for properties.\n */\nexport type NodeType<\n  K extends string = string,\n  S extends z.ZodObject<z.ZodRawShape> = z.ZodObject<z.ZodRawShape>,\n> = Readonly<{\n  [NODE_TYPE_BRAND]: true;\n  kind: K;\n  schema: S;\n  description: string | undefined;\n  annotations: KindAnnotations | undefined;\n}>;\n\n/**\n * Branded node ID type.\n *\n * Prevents mixing IDs from different node types at compile time.\n */\nexport type NodeId<N extends NodeType> = string &\n  Readonly<{\n    [__nodeId]: N;\n  }>;\n\n/**\n * Brands a non-empty string as a {@link NodeId}.\n *\n * Use this when a persisted node id has round-tripped through untyped storage\n * or an external boundary and must be passed back to read/update/delete\n * surfaces such as `getById`, `getByIds`, `update`, or `delete`.\n * Write surfaces that mint or claim ids, such as `create({ id })` and\n * `upsertById`, intentionally accept plain strings.\n *\n * @throws {ValidationError} when `value` is empty.\n */\nexport function asNodeId<N extends NodeType = NodeType>(\n  value: string,\n): NodeId<N> {\n  assertNonEmptyId(value, \"asNodeId\");\n  return value as NodeId<N>;\n}\n\n/**\n * Infer the props type from a NodeType.\n */\nexport type NodeProps<N extends NodeType> = z.infer<N[\"schema\"]>;\n\n// ============================================================\n// Edge Type\n// ============================================================\n\n/**\n * Target mapping from source kind name to allowed target node types.\n */\nexport type EdgeTargetMap = Readonly<Record<string, readonly NodeType[]>>;\n\n/**\n * Valid edge target definitions: either a Cartesian array of target nodes,\n * or a source-to-target map for source-dependent endpoints.\n */\nexport type EdgeTargets = readonly NodeType[] | EdgeTargetMap;\n\n/**\n * An edge type definition.\n *\n * Created via `defineEdge()`. Represents a type of edge in the graph\n * with an optional Zod schema for properties.\n *\n * Optionally includes `from` and `to` arrays or mappings that define the allowed\n * source and target node types (domain and range constraints).\n */\nexport type EdgeType<\n  K extends string = string,\n  S extends z.ZodObject<z.ZodRawShape> = z.ZodObject<z.ZodRawShape>,\n  From extends readonly NodeType[] | undefined = undefined,\n  To extends EdgeTargets | undefined = undefined,\n> = Readonly<{\n  [EDGE_TYPE_BRAND]: true;\n  kind: K;\n  schema: S;\n  description: string | undefined;\n  annotations: KindAnnotations | undefined;\n  from: From;\n  to: To;\n}>;\n\n/**\n * Base edge type for use in constraints - accepts any from/to configuration.\n */\nexport type AnyEdgeType = EdgeType<\n  string,\n  z.ZodObject<z.ZodRawShape>,\n  readonly NodeType[] | undefined,\n  EdgeTargets | undefined\n>;\n\n/**\n * An edge type that has both from and to constraints defined.\n * Can be used directly in defineGraph without an EdgeRegistration wrapper.\n */\nexport type EdgeTypeWithEndpoints = EdgeType<\n  string,\n  z.ZodObject<z.ZodRawShape>,\n  readonly NodeType[],\n  EdgeTargets\n>;\n\n/**\n * Branded edge ID type.\n *\n * Prevents mixing IDs from different edge types at compile time.\n */\nexport type EdgeId<E extends AnyEdgeType = AnyEdgeType> = string &\n  Readonly<{\n    [__edgeId]: E;\n  }>;\n\n/**\n * Brands a non-empty string as an {@link EdgeId}.\n *\n * Use this when a persisted edge id has round-tripped through untyped storage\n * or an external boundary and must be passed back to read/update/delete\n * surfaces such as `getById`, `getByIds`, `update`, or `delete`.\n * Write surfaces that mint ids intentionally accept plain strings.\n *\n * @throws {ValidationError} when `value` is empty.\n */\nexport function asEdgeId<E extends AnyEdgeType = AnyEdgeType>(\n  value: string,\n): EdgeId<E> {\n  assertNonEmptyId(value, \"asEdgeId\");\n  return value as EdgeId<E>;\n}\n\n/**\n * Infer the props type from an EdgeType.\n */\nexport type EdgeProps<E extends AnyEdgeType> = z.infer<E[\"schema\"]>;\n\n/**\n * The graph-local fields that identify an edge for durable matching.\n */\nexport type EdgeMatchIdentity<E extends AnyEdgeType = AnyEdgeType> = Readonly<{\n  name: string;\n  fields: readonly (keyof z.infer<E[\"schema\"]> & string)[];\n}>;\n\n// ============================================================\n// Configuration Types\n// ============================================================\n\n/**\n * Delete behaviors for nodes.\n */\nexport type DeleteBehavior = \"restrict\" | \"cascade\" | \"disconnect\";\n\n/**\n * Edge cardinality constraints.\n */\nexport type Cardinality =\n  | \"many\" // No constraint (default)\n  | \"one\" // At most one edge of this kind from any source node\n  | \"unique\" // At most one edge of this kind between any (source, target) pair\n  | \"oneActive\"; // At most one edge with valid_to IS NULL from any source\n\n/**\n * Endpoint existence modes for edge validation.\n */\nexport type EndpointExistence =\n  | \"notDeleted\" // Endpoint deleted_at IS NULL (default)\n  | \"currentlyValid\" // Endpoint not deleted AND temporally valid\n  | \"ever\"; // Endpoint exists in any state\n\n/**\n * Temporal query modes.\n */\nexport type TemporalMode =\n  | \"current\" // Valid now AND not deleted\n  | \"asOf\" // Valid at specific date AND not deleted\n  | \"includeEnded\" // All validity periods AND not deleted\n  | \"includeTombstones\"; // Everything including soft-deleted\n\n/**\n * Uniqueness constraint scope.\n */\nexport type UniquenessScope =\n  | \"kind\" // Unique within this exact kind only\n  | \"kindWithSubClasses\"; // Unique across this kind and all subclasses\n\n/**\n * Collation for uniqueness constraints.\n */\nexport type Collation = \"binary\" | \"caseInsensitive\";\n\n// ============================================================\n// Uniqueness Constraint\n// ============================================================\n\n/**\n * Uniqueness constraint definition.\n */\nexport type UniqueConstraint<\n  S extends z.ZodObject<z.ZodRawShape> = z.ZodObject<z.ZodRawShape>,\n> = Readonly<{\n  name: string;\n  fields: readonly (keyof z.infer<S> & string)[];\n  where?: (\n    props: UniqueConstraintPredicateBuilder<S>,\n  ) => UniqueConstraintPredicate;\n  scope: UniquenessScope;\n  collation: Collation;\n}>;\n\n/**\n * Predicate builder for uniqueness constraint where clause.\n * Uses -? to make all fields required in the builder, even if optional in the schema.\n */\ntype UniqueConstraintPredicateBuilder<S extends z.ZodObject<z.ZodRawShape>> =\n  Readonly<{\n    [K in keyof z.infer<S>]-?: UniqueConstraintField;\n  }>;\n\n/**\n * Field operations for uniqueness constraint predicates.\n */\ntype UniqueConstraintField = Readonly<{\n  isNull: () => UniqueConstraintPredicate;\n  isNotNull: () => UniqueConstraintPredicate;\n}>;\n\n/**\n * A uniqueness constraint predicate (internal representation).\n */\ntype UniqueConstraintPredicate = Readonly<{\n  __type: \"unique_predicate\";\n  field: string;\n  op: NullCheckOp;\n}>;\n\n// ============================================================\n// Node Registration\n// ============================================================\n\n/**\n * Node registration in a graph definition.\n */\nexport type NodeRegistration<N extends NodeType = NodeType> = Readonly<{\n  type: N;\n  unique?: readonly UniqueConstraint<N[\"schema\"]>[];\n  onDelete?: DeleteBehavior;\n}>;\n\n// ============================================================\n// Edge Registration\n// ============================================================\n\n/**\n * Edge registration in a graph definition.\n */\nexport type EdgeRegistration<\n  E extends AnyEdgeType = AnyEdgeType,\n  FromTypes extends NodeType = NodeType,\n  ToTypes extends NodeType = NodeType,\n  ToDef extends EdgeTargets = [NodeType] extends [ToTypes] ? EdgeTargets\n  : readonly ToTypes[],\n> = Readonly<{\n  type: E;\n  from: readonly FromTypes[];\n  to: ToDef;\n  cardinality?: Cardinality;\n  endpointExistence?: EndpointExistence;\n  matchIdentity?: EdgeMatchIdentity<E>;\n}>;\n\n/**\n * Base edge registration type for use in constraints - accepts any endpoint configuration.\n */\nexport type AnyEdgeRegistration = EdgeRegistration<\n  AnyEdgeType,\n  NodeType,\n  NodeType,\n  EdgeTargets\n>;\n\n// ============================================================\n// Graph Defaults\n// ============================================================\n\n/**\n * Default settings for a graph.\n */\nexport type GraphDefaults = Readonly<{\n  onNodeDelete?: DeleteBehavior;\n  temporalMode?: TemporalMode;\n}>;\n\n// ============================================================\n// Type Helpers\n// ============================================================\n\n/**\n * Checks if a value is a NodeType.\n */\nexport function isNodeType(value: unknown): value is NodeType {\n  return (\n    typeof value === \"object\" &&\n    value !== null &&\n    NODE_TYPE_BRAND in value &&\n    (value as Record<string, unknown>)[NODE_TYPE_BRAND] === true\n  );\n}\n\n/**\n * Checks if a value is an EdgeType.\n */\nexport function isEdgeType(value: unknown): value is AnyEdgeType {\n  return (\n    typeof value === \"object\" &&\n    value !== null &&\n    EDGE_TYPE_BRAND in value &&\n    (value as Record<string, unknown>)[EDGE_TYPE_BRAND] === true\n  );\n}\n\n/**\n * Checks if a value is an EdgeType with both from and to constraints defined.\n * Such edges can be used directly in defineGraph without an EdgeRegistration wrapper.\n */\nexport function isEdgeTypeWithEndpoints(\n  value: unknown,\n): value is EdgeTypeWithEndpoints {\n  if (!isEdgeType(value)) {\n    return false;\n  }\n  const candidate = value as Record<string, unknown>;\n  if (\n    !Array.isArray(candidate[\"from\"]) ||\n    candidate[\"from\"].length === 0 ||\n    typeof candidate[\"to\"] !== \"object\" ||\n    candidate[\"to\"] === null\n  ) {\n    return false;\n  }\n  return Array.isArray(candidate[\"to\"]) ?\n      candidate[\"to\"].length > 0\n    : Object.keys(candidate[\"to\"]).length > 0;\n}\n","/**\n * Helper utilities for edge endpoint domain and range validation.\n *\n * Supports both Cartesian endpoint declarations (array-valued `to`)\n * and source-dependent target declarations (map-valued `to`).\n */\nimport { ConfigurationError } from \"../errors\";\nimport { compareStrings } from \"../utils/compare\";\nimport { createDataKeyedBag, hasOwnKey } from \"../utils/object\";\nimport {\n  type EdgeTargetMap,\n  type EdgeTargets,\n  isNodeType,\n  type NodeType,\n} from \"./types\";\n\n/**\n * Checks if a value is an EdgeTargetMap.\n */\nexport function isEdgeTargetMap(value: unknown): value is EdgeTargetMap {\n  return (\n    typeof value === \"object\" &&\n    value !== null &&\n    !Array.isArray(value) &&\n    Object.keys(value).length > 0 &&\n    Object.values(value).every(\n      (targets) => Array.isArray(targets) && targets.length > 0,\n    )\n  );\n}\n\n/**\n * Projects all target node types into a deduplicated flat array.\n */\nexport function projectTargetNodes(to: EdgeTargets): readonly NodeType[] {\n  const seen = new Set<string>();\n  const result: NodeType[] = [];\n  const lists: readonly (readonly NodeType[])[] =\n    Array.isArray(to) ? [to] : Object.values(to);\n  for (const targets of lists) {\n    for (const node of targets) {\n      if (!seen.has(node.kind)) {\n        seen.add(node.kind);\n        result.push(node);\n      }\n    }\n  }\n  return result;\n}\n\n/**\n * Projects all target kind names into a deduplicated array.\n */\nexport function projectTargetKinds(to: EdgeTargets): readonly string[] {\n  return projectTargetNodes(to).map((node) => node.kind);\n}\n\n/**\n * Represents a single directed endpoint pair (fromKind -> toKind).\n */\nexport type EndpointPair = Readonly<{\n  from: string;\n  to: string;\n}>;\n\n/**\n * Extracts and canonicalizes (deduplicates and sorts) all valid endpoint pairs for an edge.\n */\nexport function getEdgeEndpointPairs(\n  from: readonly NodeType[],\n  to: EdgeTargets,\n): readonly EndpointPair[] {\n  const pairs: EndpointPair[] = [];\n  const seen = new Set<string>();\n\n  if (Array.isArray(to)) {\n    const toArray: readonly NodeType[] = to;\n    for (const fromNode of from) {\n      for (const toNode of toArray) {\n        const key = `${fromNode.kind}\\0${toNode.kind}`;\n        if (!seen.has(key)) {\n          seen.add(key);\n          pairs.push({ from: fromNode.kind, to: toNode.kind });\n        }\n      }\n    }\n  } else {\n    const toMap: EdgeTargetMap = to as EdgeTargetMap;\n    for (const [sourceKind, targets] of Object.entries(toMap)) {\n      for (const targetNode of targets) {\n        const key = `${sourceKind}\\0${targetNode.kind}`;\n        if (!seen.has(key)) {\n          seen.add(key);\n          pairs.push({ from: sourceKind, to: targetNode.kind });\n        }\n      }\n    }\n  }\n\n  return pairs.toSorted((a, b) => {\n    const cmp = compareStrings(a.from, b.from);\n    if (cmp !== 0) return cmp;\n    return compareStrings(a.to, b.to);\n  });\n}\n\n/**\n * Formats a list of endpoint pairs for human-readable error messages.\n */\nexport function formatEndpointPairs(pairs: readonly EndpointPair[]): string {\n  return pairs.map((pair) => `(${pair.from} -> ${pair.to})`).join(\", \");\n}\n\n/**\n * Normalizes a target map by deduplicating target nodes by kind.\n */\nexport function normalizeTargetMap(to: EdgeTargetMap): EdgeTargetMap {\n  const result = createDataKeyedBag<readonly NodeType[]>();\n  for (const [key, targets] of Object.entries(to)) {\n    const seen = new Set<string>();\n    const uniqueTargets: NodeType[] = [];\n    for (const t of targets) {\n      if (!seen.has(t.kind)) {\n        seen.add(t.kind);\n        uniqueTargets.push(t);\n      }\n    }\n    result[key] = Object.freeze(uniqueTargets);\n  }\n  return Object.freeze({ ...result });\n}\n\n/**\n * Validates map-valued target entries against the declared `from` nodes.\n */\nexport function validateTargetMapEntries(\n  name: string,\n  from: readonly NodeType[] | undefined,\n  to: unknown,\n): asserts to is EdgeTargetMap {\n  if (!Array.isArray(from) || from.length === 0) {\n    throw new ConfigurationError(\n      `Edge \"${name}\" declares source-dependent targets in 'to', but 'from' is missing or empty.`,\n      { edgeName: name },\n      {\n        suggestion: `Declare a non-empty 'from' array of source node types when using a mapping in 'to'.`,\n      },\n    );\n  }\n\n  if (typeof to !== \"object\" || to === null || Array.isArray(to)) {\n    throw new ConfigurationError(\n      `Edge \"${name}\" 'to' mapping must be a plain object mapping source kind names to target node arrays.`,\n      { edgeName: name },\n    );\n  }\n\n  const declaredSourceKinds = new Set<string>(\n    from.map((node: NodeType): string => node.kind),\n  );\n  const declaredSourceList = [...declaredSourceKinds];\n  const mapKeys = Object.keys(to);\n\n  // Check for missing keys\n  for (const sourceKind of declaredSourceKinds) {\n    if (!hasOwnKey(to as Readonly<Record<string, unknown>>, sourceKind)) {\n      throw new ConfigurationError(\n        `Edge \"${name}\" is missing target mapping for declared source kind \"${sourceKind}\".`,\n        {\n          edgeName: name,\n          missingKey: sourceKind,\n          declaredSources: declaredSourceList,\n        },\n        {\n          suggestion: `Add an entry for \"${sourceKind}\" in the 'to' mapping: { ${sourceKind}: [...] }.`,\n        },\n      );\n    }\n  }\n\n  // Check for extra keys\n  for (const key of mapKeys) {\n    if (!declaredSourceKinds.has(key)) {\n      throw new ConfigurationError(\n        `Edge \"${name}\" has entry \"${key}\" in 'to' that is not in declared 'from' kinds: [${declaredSourceList.join(\", \")}].`,\n        {\n          edgeName: name,\n          extraKey: key,\n          declaredSources: declaredSourceList,\n        },\n        {\n          suggestion: `Remove \"${key}\" from 'to', or add a node type with kind \"${key}\" to 'from'. Keys in 'to' must use literal node kind names.`,\n        },\n      );\n    }\n  }\n\n  // Validate target arrays for each key\n  for (const [key, targets] of Object.entries(to)) {\n    if (!Array.isArray(targets) || targets.length === 0) {\n      throw new ConfigurationError(\n        `Edge \"${name}\" target array for source kind \"${key}\" must be a non-empty array of node types.`,\n        { edgeName: name, sourceKind: key },\n        {\n          suggestion: `Provide at least one target node type for source kind \"${key}\": { ${key}: [TargetNode] }.`,\n        },\n      );\n    }\n    for (const target of targets) {\n      if (!isNodeType(target)) {\n        throw new ConfigurationError(\n          `Edge \"${name}\" target for source kind \"${key}\" contains an invalid node reference.`,\n          { edgeName: name, sourceKind: key, invalidTarget: target },\n          {\n            suggestion: `Ensure all targets in 'to' are node types created with defineNode.`,\n          },\n        );\n      }\n    }\n  }\n}\n","/**\n * Constraint validation module.\n *\n * Provides validation functions for enforcing graph constraints:\n * - Uniqueness constraints on node properties\n * - Cardinality constraints on edges\n * - Endpoint type constraints on edges\n * - Disjointness constraints between node kinds\n */\n\n/**\n * Separator used between field values in composite unique keys.\n * Uses ASCII Record Separator (0x1E) — valid UTF-8 and safe for PostgreSQL\n * TEXT columns (unlike \\0 which PostgreSQL rejects).\n */\nconst UNIQUE_KEY_SEPARATOR = \"\\u001E\";\n\n/** Marker for undefined/null field values in unique keys. */\nconst UNIQUE_KEY_NULL_MARKER = \"\\u001F\"; // ASCII Unit Separator\nimport { getEdgeEndpointPairs, isEdgeTargetMap } from \"../core/edge-endpoints\";\nimport {\n  type Cardinality,\n  type Collation,\n  type EdgeRegistration,\n  type NullCheckOp,\n  type UniqueConstraint,\n  type UniquenessScope,\n} from \"../core/types\";\nimport {\n  CardinalityError,\n  ConfigurationError,\n  DisjointError,\n  EndpointError,\n  EndpointPairError,\n  UniquenessError,\n} from \"../errors\";\nimport { type KindRegistry } from \"../registry/kind-registry\";\nimport { hasOwnKey, readOwnProperty } from \"../utils/object\";\nimport { isPresent } from \"../utils/presence\";\n\n// ============================================================\n// Uniqueness Validation\n// ============================================================\n\n/**\n * Computes the unique key for a node's uniqueness constraint.\n *\n * The key is built by concatenating the specified field values,\n * optionally normalized for case-insensitive comparison.\n *\n * Field values are read by declared OWN key ({@link readOwnProperty}): a\n * constraint may name a field that a props bag does not carry (an absent\n * optional field), and a plain `props[field]` read would answer such a field\n * with the inherited `Object.prototype` member when the field is named after\n * one. A constraint over a field named `toString` then keyed on the inherited\n * function — `\"\"` under `binary` (the function stringified and dropped by\n * `JSON.stringify`) and a `TypeError` under `caseInsensitive` — instead of the\n * null marker every other absent value gets.\n */\nexport function computeUniqueKey(\n  props: Record<string, unknown>,\n  fields: readonly string[],\n  collation: Collation,\n): string {\n  const values = fields.map((field) => {\n    const value = readOwnProperty(props, field);\n    if (value === undefined || value === null) {\n      return UNIQUE_KEY_NULL_MARKER;\n    }\n    // Convert to string, handling primitives safely\n    const stringValue =\n      typeof value === \"string\" ? value\n      : typeof value === \"number\" || typeof value === \"boolean\" ?\n        value.toString()\n      : JSON.stringify(value);\n    return collation === \"caseInsensitive\" ?\n        stringValue.toLowerCase()\n      : stringValue;\n  });\n  return values.join(UNIQUE_KEY_SEPARATOR);\n}\n\n/**\n * Checks if a uniqueness constraint's where predicate passes.\n *\n * A `where` callback that does not return a predicate is REFUSED here, not\n * treated as \"the constraint always applies\". The same malformed clause is a\n * hard `ConfigurationError` at definition time ({@link assertWhereFieldDeclared})\n * and at persistence time (`serializeWherePredicate`); a third reading that\n * silently widened a partial constraint to a total one would let the three\n * sites disagree about the same clause — the divergence\n * {@link captureWherePredicate} exists to prevent.\n *\n * The arm SHOULD be unreachable: `defineGraph` refuses a non-predicate callback\n * before any write can evaluate it, `validateGraphExtension` refuses the\n * document form, and a constraint reconstructed from a persisted schema carries\n * a callback this module built itself. It is reachable only by handing the\n * store a constraint object that never passed a definition gate — for which\n * failing loudly is the correct answer, since the alternative is enforcing\n * uniqueness over rows the author meant to exclude.\n */\nexport function checkWherePredicate(\n  constraint: UniqueConstraint,\n  props: Record<string, unknown>,\n): boolean {\n  if (!constraint.where) {\n    return true; // No where clause, always applies\n  }\n\n  const predicate = captureWherePredicate(constraint.where);\n  if (predicate === undefined) {\n    throw new ConfigurationError(\n      `Unique constraint \"${constraint.name}\" has a \\`where\\` callback that does not return a predicate.`,\n      { constraintName: constraint.name, fields: [...constraint.fields] },\n      {\n        suggestion: `Return a field predicate, e.g. \\`where: (fields) => fields.${constraint.fields[0] ?? \"someField\"}.isNotNull()\\`. A constraint built outside \\`defineGraph\\` bypasses the definition-time check that normally reports this.`,\n      },\n    );\n  }\n\n  return evaluatePredicate(predicate, props);\n}\n\ntype UniquePredicate = Readonly<{\n  __type: \"unique_predicate\";\n  field: string;\n  op: NullCheckOp;\n}>;\n\n/**\n * The `where` callback as every caller of {@link captureWherePredicate} sees it:\n * a per-field builder in, whatever the author returned out.\n *\n * Deliberately looser than `UniqueConstraint[\"where\"]`, whose builder type is\n * generic in the kind's schema — the capture is the same operation whether the\n * callback came from a typed `defineGraph` registration, a compiled\n * graph-extension document, or an untyped JavaScript caller.\n */\ntype UniqueWhereCallback = (\n  builder: Readonly<\n    Record<\n      string,\n      Readonly<{\n        isNull: () => UniquePredicate;\n        isNotNull: () => UniquePredicate;\n      }>\n    >\n  >,\n) => unknown;\n\n/**\n * Runs a `where` callback against the shared builder and returns the predicate\n * it named, or `undefined` when the callback returned something that is not a\n * predicate.\n *\n * The single owner of \"what does this `where` clause say\": constraint\n * EVALUATION ({@link checkWherePredicate}), definition-time VALIDATION\n * ({@link assertWhereFieldDeclared}), and persistence-time CAPTURE\n * (`serializeWherePredicate` in src/schema/serializer.ts) all read the clause\n * through this one function, so a persisted `where`, a validated `where`, and\n * an evaluated `where` cannot disagree about which field the author named.\n */\nexport function captureWherePredicate(\n  where: UniqueWhereCallback,\n): UniquePredicate | undefined {\n  const predicate = where(buildPredicateContext());\n  if (\n    typeof predicate !== \"object\" ||\n    predicate === null ||\n    !(\"__type\" in predicate)\n  ) {\n    return undefined;\n  }\n\n  const candidate = predicate as {\n    __type: unknown;\n    field: unknown;\n    op: unknown;\n  };\n  if (\n    candidate.__type !== \"unique_predicate\" ||\n    typeof candidate.field !== \"string\" ||\n    (candidate.op !== \"isNull\" && candidate.op !== \"isNotNull\")\n  ) {\n    return undefined;\n  }\n\n  return {\n    __type: \"unique_predicate\",\n    field: candidate.field,\n    op: candidate.op,\n  };\n}\n\n/**\n * Refuses a uniqueness constraint whose `where` clause names a field the kind\n * does not declare.\n *\n * The runtime half of the builder's guard. {@link buildPredicateContext} is\n * total by design — it must answer for a DECLARED-but-absent field, which is\n * the whole point of a partial constraint — so a typo'd name cannot be caught\n * there, and the type system catches it only for typed callers\n * (`UniqueConstraintPredicateBuilder` declares exactly the schema's fields and\n * has no index signature). An untyped caller naming an undeclared field\n * otherwise gets a predicate that quietly never applies.\n *\n * Called once per constraint at graph-definition time — the single point every\n * constraint passes through before any write can evaluate it — rather than at\n * each of the write paths' `checkWherePredicate` call sites, so the refusal\n * covers every path uniformly and costs nothing per write. Mirrors\n * `validateGraphExtension`'s `UNKNOWN_UNIQUE_WHERE_FIELD` refusal, which\n * already holds the same invariant for kinds declared as JSON documents.\n */\nexport function assertWhereFieldDeclared(\n  kind: string,\n  constraint: UniqueConstraint,\n  shape: Readonly<Record<string, unknown>>,\n): void {\n  if (!constraint.where) return;\n\n  const predicate = captureWherePredicate(constraint.where);\n  if (predicate === undefined) {\n    throw new ConfigurationError(\n      `Unique constraint \"${constraint.name}\" on node kind \"${kind}\" has a \\`where\\` callback that does not return a predicate.`,\n      { kind, constraintName: constraint.name },\n      {\n        suggestion: `Return a field predicate, e.g. \\`where: (fields) => fields.${Object.keys(shape)[0] ?? \"someField\"}.isNotNull()\\`.`,\n      },\n    );\n  }\n\n  if (!hasOwnKey(shape, predicate.field)) {\n    throw new ConfigurationError(\n      `Unique constraint \"${constraint.name}\" on node kind \"${kind}\" has a \\`where\\` clause on field \"${predicate.field}\", which is not declared in the kind's schema.`,\n      {\n        kind,\n        constraintName: constraint.name,\n        field: predicate.field,\n        declaredFields: Object.keys(shape),\n      },\n      {\n        suggestion: `Name a declared field (${Object.keys(shape).join(\", \")}) or add \"${predicate.field}\" to the schema.`,\n      },\n    );\n  }\n}\n\ntype PredicateContext = Readonly<\n  Record<\n    string,\n    Readonly<{\n      isNull: () => UniquePredicate;\n      isNotNull: () => UniquePredicate;\n    }>\n  >\n>;\n\n/**\n * Builds the context a constraint's `where` callback names fields on.\n *\n * EVERY field name gets a member, because the builder type declares every\n * schema field as required (`-?` in `UniqueConstraintPredicateBuilder`) —\n * precisely so a partial constraint can ask whether an OPTIONAL field is\n * present. Populating the context from the props bag's own keys instead left a\n * declared-but-absent field with no member, and the callback's access then hit\n * whatever the context's prototype offered: `Object.prototype.toString` for a\n * field named `toString` (so naming it threw \"isNull is not a function\"), and\n * `undefined` for an ordinary field (so the everyday partial constraint over\n * `externalId` threw — \"Cannot read properties of undefined\", or \"Expected a\n * defined value\" through `requireDefined` — for every node written without it).\n *\n * Answering every name is safe because a name comes from the predicate author\n * (the code), never from data, and the field's VALUE is still read from the\n * props bag by own key when the predicate is evaluated — so an absent field\n * evaluates as null, which is what a partial constraint means by absent. Every\n * reader of a `where` clause goes through {@link captureWherePredicate}, which\n * builds this one context, so a persisted `where`, a validated `where`, and an\n * evaluated `where` cannot see different builders.\n *\n * The guard against a TYPO'D field name is NOT this Proxy — it must stay total\n * or a declared-but-absent field loses its member. It is\n * {@link assertWhereFieldDeclared}, which every constraint passes at\n * graph-definition time: an undeclared name is refused there with a typed\n * `ConfigurationError`, so no `where` clause naming one ever reaches\n * evaluation, from a typed or an untyped caller.\n */\nfunction buildPredicateContext(): PredicateContext {\n  return new Proxy<PredicateContext>(\n    {},\n    {\n      get(_target, property) {\n        if (typeof property === \"symbol\") return;\n        return {\n          isNull: () => ({\n            __type: \"unique_predicate\" as const,\n            field: property,\n            op: \"isNull\" as const,\n          }),\n          isNotNull: () => ({\n            __type: \"unique_predicate\" as const,\n            field: property,\n            op: \"isNotNull\" as const,\n          }),\n        };\n      },\n    },\n  );\n}\n\n/**\n * Evaluates a uniqueness predicate.\n *\n * Takes a CAPTURED predicate, not an `unknown`: the \"is this really a\n * predicate?\" question belongs to {@link captureWherePredicate}, which is its\n * single owner. The defensive `return true` arms this function used to carry\n * were a second, quieter answer to that question — and they answered it the\n * opposite way, widening a partial constraint into a total one where the owner\n * refuses.\n */\nfunction evaluatePredicate(\n  pred: UniquePredicate,\n  props: Record<string, unknown>,\n): boolean {\n  // Own-key read: `pred.field` is a schema field name, and a props bag that\n  // does not carry it must read as absent rather than as the inherited\n  // `Object.prototype` member a field named after one would otherwise find\n  // (which reads as present, inverting both `isNull` and `isNotNull`).\n  const value = readOwnProperty(props, pred.field);\n  if (pred.op === \"isNull\") {\n    return value === null || value === undefined;\n  }\n  return isPresent(value);\n}\n\n/**\n * Gets all kinds that should be checked for a uniqueness constraint.\n *\n * For \"kindWithSubClasses\" scope, includes the entire subclass hierarchy:\n * - The kind itself\n * - All ancestors (parent classes)\n * - All descendants of those ancestors (sibling classes)\n *\n * For \"kind\" scope, only the specific kind.\n */\nexport function getKindsForUniquenessCheck(\n  baseKind: string,\n  scope: UniquenessScope,\n  registry: KindRegistry,\n): readonly string[] {\n  if (scope === \"kind\") {\n    return [baseKind];\n  }\n\n  // Get the entire connected subclass hierarchy by finding the root ancestor\n  const root = findRootAncestor(baseKind, registry);\n\n  // Return the root and all its descendants (which includes baseKind and siblings)\n  return registry.expandSubClasses(root);\n}\n\n/**\n * THE definition of \"which kinds a `kindWithSubClasses` scope covers\": the\n * registry's precomputed connected component of the UNDIRECTED `subClassOf`\n * graph containing `kind`, in code-point order.\n *\n * Kind-independent by construction — every member of a component computes the\n * same set — which is what makes a claim axis folded from it deterministic: two\n * writers of two different kinds in one hierarchy reserve the SAME row, so the\n * uniques primary key fences them against each other.\n *\n * {@link getKindsForUniquenessCheck} is deliberately NOT folded into this: it\n * walks one root's descendants, so on a multi-root hierarchy (`Employee`\n * subclassing both `Alpha` and `Zeta`) it answers differently depending on which\n * member asks, and a fold of a kind-dependent set cannot be a canonical axis.\n * This is the documented intent of that function, so the component is a superset\n * of the set it walks: the fence is never weaker than the probe, and is stronger\n * in exactly the multi-root case where the probe is inconsistent.\n */\nexport function subClassComponent(\n  kind: string,\n  registry: KindRegistry,\n): readonly string[] {\n  return registry.getSubClassComponent(kind);\n}\n\n/**\n * Finds the topmost ancestor of a kind, or the kind itself if it has no ancestors.\n */\nfunction findRootAncestor(kind: string, registry: KindRegistry): string {\n  const ancestors = registry.getAncestors(kind);\n\n  if (ancestors.size === 0) {\n    return kind;\n  }\n\n  // Find an ancestor with no ancestors (the root)\n  for (const ancestor of ancestors) {\n    if (registry.getAncestors(ancestor).size === 0) {\n      return ancestor;\n    }\n  }\n\n  // If all ancestors have ancestors, recurse up\n  const firstAncestor = [...ancestors][0];\n  return firstAncestor ? findRootAncestor(firstAncestor, registry) : kind;\n}\n\n/**\n * Creates a uniqueness error.\n */\nexport function createUniquenessError(\n  constraintName: string,\n  kind: string,\n  existingId: string,\n  newId: string,\n  fields: readonly string[],\n): UniquenessError {\n  return new UniquenessError({\n    constraintName,\n    kind,\n    existingId,\n    newId,\n    fields: [...fields],\n  });\n}\n\n// ============================================================\n// Cardinality Validation\n// ============================================================\n\n/**\n * Checks if adding an edge would violate cardinality constraints.\n *\n * @param edgeKind - The edge kind being added\n * @param fromKind - The source node kind\n * @param fromId - The source node ID\n * @param cardinality - The cardinality constraint\n * @param existingEdgeCount - Number of existing edges of this kind from this source\n * @param hasActiveEdge - Whether there's an active (valid_to IS NULL) edge\n * @returns Error if violation, undefined if valid\n */\nexport function checkCardinality(\n  edgeKind: string,\n  fromKind: string,\n  fromId: string,\n  cardinality: Cardinality,\n  existingEdgeCount: number,\n  hasActiveEdge: boolean,\n): CardinalityError | undefined {\n  switch (cardinality) {\n    case \"many\": {\n      // No constraint\n      return undefined;\n    }\n    case \"one\": {\n      // At most one edge of this kind from any source node\n      if (existingEdgeCount > 0) {\n        return new CardinalityError({\n          edgeKind,\n          fromKind,\n          fromId,\n          cardinality: \"one\",\n          existingCount: existingEdgeCount,\n        });\n      }\n      return undefined;\n    }\n    case \"unique\": {\n      // unique is checked separately per (source, target) pair\n      return undefined;\n    }\n    case \"oneActive\": {\n      // At most one edge with valid_to IS NULL from any source\n      if (hasActiveEdge) {\n        return new CardinalityError({\n          edgeKind,\n          fromKind,\n          fromId,\n          cardinality: \"oneActive\",\n          existingCount: 1,\n        });\n      }\n      return undefined;\n    }\n  }\n}\n\n/**\n * Checks unique edge constraint (at most one edge between any source-target pair).\n */\nexport function checkUniqueEdge(\n  edgeKind: string,\n  fromKind: string,\n  fromId: string,\n  _toKind: string,\n  _toId: string,\n  existingCount: number,\n): CardinalityError | undefined {\n  if (existingCount > 0) {\n    return new CardinalityError({\n      edgeKind,\n      fromKind,\n      fromId,\n      cardinality: \"unique\",\n      existingCount,\n    });\n  }\n  return undefined;\n}\n\n// ============================================================\n// Endpoint Validation\n// ============================================================\n\n/**\n * Validates that an edge's endpoints are valid node kinds.\n */\nexport function validateEdgeEndpoints(\n  edgeKind: string,\n  fromKind: string,\n  toKind: string,\n  registration: EdgeRegistration,\n  registry: KindRegistry,\n): EndpointError | EndpointPairError | undefined {\n  // Check from kinds\n  const validFromKinds = registration.from.map((node) => node.kind);\n  if (!registry.isAssignableToAny(fromKind, validFromKinds)) {\n    return new EndpointError({\n      edgeKind,\n      endpoint: \"from\",\n      actualKind: fromKind,\n      expectedKinds: validFromKinds,\n    });\n  }\n\n  // If to is a map: validate conditional source-dependent targets\n  if (isEdgeTargetMap(registration.to)) {\n    const allowedTargetKinds = new Set<string>();\n    for (const fromNode of registration.from) {\n      if (registry.isAssignableTo(fromKind, fromNode.kind)) {\n        const targets = registration.to[fromNode.kind] ?? [];\n        for (const target of targets) {\n          allowedTargetKinds.add(target.kind);\n        }\n      }\n    }\n\n    if (!registry.isAssignableToAny(toKind, [...allowedTargetKinds])) {\n      return new EndpointPairError({\n        edgeKind,\n        fromKind,\n        toKind,\n        allowedPairs: getEdgeEndpointPairs(registration.from, registration.to),\n      });\n    }\n\n    return undefined;\n  }\n\n  // Check to kinds for Cartesian array\n  const validToKinds = registration.to.map((node) => node.kind);\n  if (!registry.isAssignableToAny(toKind, validToKinds)) {\n    return new EndpointError({\n      edgeKind,\n      endpoint: \"to\",\n      actualKind: toKind,\n      expectedKinds: validToKinds,\n    });\n  }\n\n  return undefined;\n}\n\n// ============================================================\n// Disjointness Validation\n// ============================================================\n\n/**\n * Checks if creating a node would violate disjointness constraints.\n *\n * @param nodeId - The node ID being created\n * @param nodeKind - The kind of the new node\n * @param existingKinds - Kinds of existing nodes with the same ID\n * @param registry - The kind registry for disjointness checks\n * @returns Error if disjoint violation, undefined if valid\n */\nexport function checkDisjointness(\n  nodeId: string,\n  nodeKind: string,\n  existingKinds: readonly string[],\n  registry: KindRegistry,\n): DisjointError | undefined {\n  for (const existingKind of existingKinds) {\n    if (registry.areDisjoint(nodeKind, existingKind)) {\n      return new DisjointError({\n        nodeId,\n        attemptedKind: nodeKind,\n        conflictingKind: existingKind,\n      });\n    }\n  }\n  return undefined;\n}\n\n/**\n * Gets all disjoint kinds for a given kind.\n */\nexport function getDisjointKinds(\n  kind: string,\n  registry: KindRegistry,\n): readonly string[] {\n  return registry.getDisjointKinds(kind);\n}\n","/**\n * Encodes an ordered tuple of strings as an injective map key.\n *\n * Delimiter joins are unsafe because every delimiter is also a legal value\n * character. JSON's string-array grammar preserves both field boundaries and\n * string contents, so distinct tuples cannot collapse onto the same key.\n */\nexport function encodeTupleKey(values: readonly string[]): string {\n  return JSON.stringify(values);\n}\n","/**\n * Claim axis vocabulary.\n *\n * A declared constraint is a CLAIM on an AXIS: the value bound to a claim row's\n * `node_kind` column, which is what the relation's primary key fences on. The\n * axis is not always a kind — it is whatever set of kinds the constraint spans —\n * and deciding it is this module's only job, so no write path spells its own.\n *\n * The other half of a claim row is its OWNER, `(concrete_kind, node_id)`. Ids\n * are unique only per kind, so an id alone cannot answer \"is this row mine?\":\n * `Employee \"X\"` and `Contractor \"X\"` are two rows under the nodes primary key\n * and would read as one owner. The predicate lives here once, in the two\n * renderings the code needs (TypeScript and SQL), so a claim's accept/refuse\n * verdict cannot differ between the layer that probes it and the layer that\n * writes it.\n *\n * The SQL rendering below is generic over the caller's SQL representation and\n * keyed on physical column NAMES rather than a Drizzle `Column` object, so a\n * backend with no column objects at all can call this one owner without an\n * adapter-specific intermediate representation or a re-spelled predicate.\n */\nimport { subClassComponent } from \"../../constraints\";\nimport { type UniquenessScope } from \"../../core/types\";\nimport { ConfigurationError } from \"../../errors\";\nimport { type KindRegistry } from \"../../registry/kind-registry\";\nimport { compareStrings } from \"../../utils/compare\";\nimport { encodeTupleKey } from \"../../utils/tuple-key\";\n\n/**\n * The one code point an axis component may not contain, written as an escape\n * so it can never be mistaken for whitespace in a diff.\n *\n * Axes that are not kinds are built by joining with it — the disjointness pair\n * axis below is the first — so a kind or constraint name containing it could\n * spell a reserved axis and take a claim row the fence assigns to something\n * else. {@link assertClaimAxisSafe} is what makes that unspellable, at\n * graph-definition time.\n */\nconst AXIS_SEPARATOR = \"\\u001E\";\n\n/** The prefix marking an axis as a disjoint PAIR rather than as a kind. */\nconst DISJOINT_AXIS_PREFIX = `${AXIS_SEPARATOR}disjoint${AXIS_SEPARATOR}`;\n\n/**\n * The `constraint_name` every disjointness claim is written under.\n *\n * Reserved rather than derived: it is what tells the claim seam that a refusal\n * on this row is a `DisjointError` and not a `UniquenessError`, and what tells\n * a reader of the relation that this row's `node_kind` is a pair label rather\n * than a kind. {@link assertClaimAxisSafe} is what guarantees no declared\n * constraint can carry the same name.\n */\nexport const DISJOINT_CONSTRAINT_NAME = `${AXIS_SEPARATOR}disjointWith`;\n\n/**\n * THE axis a disjointness claim is written at: the registry's own canonical\n * pair label, prefixed so it cannot collide with a kind.\n *\n * A fold of `KindRegistry.disjointPairLabel` rather than a second\n * normalization of the same pair — the two kinds of one disjoint pair must\n * compute ONE string, or their claims sit on two rows that can never collide\n * and the fence refuses nothing.\n *\n * Pairwise, and deliberately not per component: the registry's disjoint pairs\n * are literal unordered pairs and disjointness is not transitive here, so an\n * axis keyed on a connected component would refuse an `A`/`C` pair under\n * `A⊥B, B⊥C` that the graph never declared disjoint.\n */\nexport function disjointnessClaimAxis(\n  kind: string,\n  otherKind: string,\n  registry: KindRegistry,\n): string {\n  return `${DISJOINT_AXIS_PREFIX}${registry.disjointPairLabel(kind, otherKind)}`;\n}\n\n/**\n * Refuses a kind name or constraint name that could spell a reserved claim\n * axis or the reserved disjointness constraint name.\n *\n * Runs at graph-definition time, the one gate every kind and every declared\n * constraint passes before a claim can be written for it — so the reserved\n * vocabulary is unspellable by construction rather than re-checked at each\n * write, and the claim seam can read \"this refusal is a disjointness refusal\"\n * off the reserved constraint name without a caller being able to forge it. A\n * new refusal, on an input no real schema carries.\n *\n * `subject` names the ROLE (`Node kind`, `Unique constraint`); the name itself\n * is quoted through `JSON.stringify` so the offending code point reads as an\n * escape instead of as an invisible character.\n */\nexport function assertClaimAxisSafe(name: string, subject: string): void {\n  if (!name.includes(AXIS_SEPARATOR)) return;\n  throw new ConfigurationError(\n    `${subject} name ${JSON.stringify(name)} contains U+001E, which TypeGraph reserves for claim axes.`,\n    { name },\n    {\n      suggestion: `Rename it without the U+001E (record separator) character.`,\n    },\n  );\n}\n\n/**\n * WHERE a uniqueness claim for this kind and scope is written, and whether that\n * target spans kinds beyond the writer's own.\n *\n * Both facts come out of one computation on purpose. The axis is the code-point\n * minimum of the set the scope covers, and \"does this site also need the\n * per-graph write lock?\" is that same set having more than one member — so a\n * caller cannot pick up one without the other, and the lock trigger cannot\n * drift away from the claim target. Asking the covered SET rather than the\n * scope token is what keeps a `kindWithSubClasses` constraint on a kind with no\n * hierarchy classified like the `kind` scope it is equivalent to.\n */\nexport type UniquenessClaimTarget = Readonly<{\n  axis: string;\n  crossKind: boolean;\n}>;\n\n/** The kinds one uniqueness claim axis spans, in canonical order. */\nfunction uniquenessClaimKinds(\n  kind: string,\n  scope: UniquenessScope,\n  registry: KindRegistry,\n): readonly string[] {\n  return scope === \"kind\" ? [kind] : subClassComponent(kind, registry);\n}\n\n/** THE decision above — the one owner of both readings. */\nexport function uniquenessClaimTarget(\n  kind: string,\n  scope: UniquenessScope,\n  registry: KindRegistry,\n): UniquenessClaimTarget {\n  const kinds = uniquenessClaimKinds(kind, scope, registry);\n  return { axis: kinds[0] ?? kind, crossKind: kinds.length > 1 };\n}\n\n/**\n * THE axis a uniqueness claim is written at: the kind itself for\n * `scope: \"kind\"`, and the code-point minimum of the subclass component for\n * `scope: \"kindWithSubClasses\"`.\n *\n * The minimum is a fold of a kind-independent set, so every kind in one\n * hierarchy folds to the same axis and their claims collide on the uniques\n * primary key — which is the whole fence. Reserving under each writer's own\n * kind (what this replaces) put sibling kinds in rows that can never collide.\n */\nexport function uniquenessClaimAxis(\n  kind: string,\n  scope: UniquenessScope,\n  registry: KindRegistry,\n): string {\n  return uniquenessClaimTarget(kind, scope, registry).axis;\n}\n\n/**\n * THE order a uniqueness probe reads claim rows in: the axis first, then every\n * remaining kind the scope covers, in code-point order.\n *\n * Two things make this list wider than the axis alone and narrower than\n * arbitrary:\n *\n * - The axis is where this version writes, so it is read first.\n * - Rows written before the axis move sit under their own concrete kind, so the\n *   probe visits the full undirected component, including every root of a\n *   multi-root hierarchy. That is what makes the axis move need no data\n *   migration.\n *\n * The remainder is sorted rather than left in registry-iteration order so two\n * processes reading the same scope read it in the same order.\n */\nexport function uniquenessProbeKinds(\n  kind: string,\n  scope: UniquenessScope,\n  registry: KindRegistry,\n): readonly string[] {\n  const axis = uniquenessClaimAxis(kind, scope, registry);\n  const coveredKinds = uniquenessClaimKinds(kind, scope, registry);\n  const rest = coveredKinds\n    .filter((candidate) => candidate !== axis)\n    .toSorted((left, right) => compareStrings(left, right));\n  return [axis, ...rest];\n}\n\n/**\n * THE axis an edge cardinality claim is written at: the declared cardinality\n * and the edge kind, which together name the population the constraint counts.\n *\n * `one` and `oneActive` on one kind are DIFFERENT axes on purpose — they count\n * different populations (every live edge from a source vs every active one) —\n * so a kind whose declaration changed cannot inherit rows the old declaration\n * wrote. The cardinality tokens contain no `:`, so the pair is injective over\n * arbitrary edge kind names.\n */\nexport function edgeCardinalityAxis(\n  cardinality: string,\n  edgeKind: string,\n): string {\n  return `${cardinality}:${edgeKind}`;\n}\n\n/** The relation a claim row lives in. */\ntype ClaimRelation = \"uniques\" | \"edgeClaims\";\n\n/** A claim row named in full — the row a statement is about to lock. */\nexport type ClaimTarget = Readonly<{\n  relation: ClaimRelation;\n  graphId: string;\n  axis: string;\n  /**\n   * `uniques.constraint_name`. The edge claim relation keys on\n   * `(graph_id, axis, key)` and has no such column, so its targets omit it and\n   * sort as the empty string. Absent means \"this relation does not key on a\n   * constraint name\", never \"not known yet\".\n   */\n  constraintName?: string;\n  key: string;\n}>;\n\n/**\n * THE canonical order claims are acquired in: code-point compare on\n * `(relation, graphId, axis, constraintName, key)`.\n *\n * Two writers that take the same two claim rows in opposite orders deadlock,\n * and PostgreSQL resolves that by aborting one with `40P01` — which would turn\n * an import's per-row recovery into a whole-batch abort. Sorting every claim\n * statement's entries by one comparator removes the commonest cycle, exactly as\n * multi-graph lock acquisition already does (see `recorded-capture.ts`, whose\n * comment states the same rule: every process must acquire in the same order).\n *\n * The order it establishes is per claim SET and per statement, not per\n * transaction: rows and batches inside one import claim in input order, so two\n * concurrent lock-free imports into one graph can still deadlock. That residual\n * is declared out of contract rather than fenced here.\n */\nexport function compareClaimTargets(\n  left: ClaimTarget,\n  right: ClaimTarget,\n): number {\n  return (\n    compareStrings(left.relation, right.relation) ||\n    compareStrings(left.graphId, right.graphId) ||\n    compareStrings(left.axis, right.axis) ||\n    compareStrings(left.constraintName ?? \"\", right.constraintName ?? \"\") ||\n    compareStrings(left.key, right.key)\n  );\n}\n\n/**\n * WHO holds a claim. A node, not an id: ids are unique only per kind, so\n * `(concrete_kind, node_id)` is the smallest thing that identifies a claimant.\n */\nexport type ClaimOwner = Readonly<{ concreteKind: string; nodeId: string }>;\n\n/**\n * THE ownership predicate. Every reader of \"is this claim row mine?\" calls it —\n * the probe, the single-row upsert's verdict, the batch upsert's verdict, and\n * the batch-validation cache's pending answer.\n *\n * Comparing ids alone accepts a claim held by a namesake under another kind,\n * which is precisely the collision `disjointWith` forbids and precisely the one\n * a shared uniqueness scope exists to catch.\n */\nexport function isSameClaimOwner(left: ClaimOwner, right: ClaimOwner): boolean {\n  return (\n    left.nodeId === right.nodeId && left.concreteKind === right.concreteKind\n  );\n}\n\n/**\n * THE Set/Map key rendering of {@link isSameClaimOwner}, for a path that decides\n * ownership against MANY owners at once rather than pairwise.\n *\n * `encodeTupleKey`, not a delimiter join: kind names are constrained but node\n * ids are arbitrary caller data, and a delimiter a value may contain would make\n * two different owners collapse onto one key — which, where this is used, would\n * silently whitelist a foreign owner. Third rendering of one predicate, in the\n * module that owns it and beside {@link claimOwnerMatchesSql}: keys are equal\n * exactly when `isSameClaimOwner` holds and exactly when the SQL matches.\n */\nexport function claimOwnerKey(owner: ClaimOwner): string {\n  return encodeTupleKey([owner.concreteKind, owner.nodeId]);\n}\n\n/**\n * The owner columns of the uniques relation, by PHYSICAL COLUMN NAME.\n *\n * Names, not column objects: every renderer only ever reads `column.name`\n * (the batch builder's is already typed `(column: Readonly<{name: string}>)`),\n * and taking the name is what lets a backend that has no column objects at all\n * call the one owner of this predicate instead of re-spelling it.\n */\nexport type ClaimOwnerColumnNames = Readonly<{\n  nodeId: string;\n  concreteKind: string;\n}>;\n\n/**\n * THE SQL rendering of {@link isSameClaimOwner}, for the three upsert builders.\n *\n * `existing` qualifies a column of the conflicting row the way the dialect\n * requires (PostgreSQL needs the table name, SQLite takes the bare quoted\n * column); `proposed` renders the value being claimed — a bound parameter for\n * the single-row builders, an `excluded.` reference for the batch one. Two\n * renderings, one definition: the arms every builder decides ownership with\n * are this fragment, so a builder cannot quietly compare fewer columns than\n * the TypeScript predicate does. The dialect switch between the qualified and\n * bare forms is the batch builder's own; this function only composes whatever\n * renderer it is handed. The generic tag keeps that composition portable while\n * allowing an adapter to build its native SQL value directly.\n */\nexport function claimOwnerMatchesSql<TExpression>(\n  tag: (\n    strings: TemplateStringsArray,\n    ...expressions: readonly TExpression[]\n  ) => TExpression,\n  existing: (columnName: string) => TExpression,\n  proposed: (columnName: string) => TExpression,\n  columns: ClaimOwnerColumnNames,\n): TExpression {\n  return tag`${existing(columns.nodeId)} = ${proposed(columns.nodeId)} AND ${existing(columns.concreteKind)} = ${proposed(columns.concreteKind)}`;\n}\n"]}