@kanonak-protocol/sdk 3.71.0 → 3.73.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.js +1 -1
- package/dist/{chunk-OFSARZX6.js → chunk-ATH6636H.js} +1 -1
- package/dist/chunk-C7RZIMEH.js +80 -0
- package/dist/chunk-LKBG2MK6.js +2 -0
- package/dist/chunk-X5TYWQRA.js +148 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +26 -26
- package/dist/look/LookRenderer.d.ts +21 -50
- package/dist/producer/Entitlement.d.ts +75 -0
- package/dist/producer/IPackageProducer.d.ts +59 -0
- package/dist/producer/PackageBuilder.d.ts +130 -0
- package/dist/producer/ProducerRepository.d.ts +44 -0
- package/dist/producer/index.d.ts +6 -0
- package/dist/repositories/HttpKanonakDocumentRepository.d.ts +20 -0
- package/dist/repositories/PublisherConfig.d.ts +10 -0
- package/dist/repositories/PublisherIndex.d.ts +3 -1
- package/dist/repositories/browser.js +1 -1
- package/dist/repositories/index.js +1 -1
- package/dist/search/index.js +1 -1
- package/dist/server/assembleModel.d.ts +2 -0
- package/dist/server/index.js +2 -2
- package/dist/server/types.d.ts +9 -0
- package/dist/transformations/index.js +2 -2
- package/dist/validation/index.js +1 -1
- package/dist/validation/rules/repository/LookBandPathRule.d.ts +38 -0
- package/dist/validation/rules/repository/index.d.ts +1 -0
- package/dist/view/ViewMaterializer.d.ts +1 -7
- package/package.json +2 -2
- package/dist/chunk-HAR3BNTB.js +0 -2
- package/dist/chunk-MCU5IAMS.js +0 -148
- package/dist/chunk-RRODBYIK.js +0 -74
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import{a as
|
|
2
|
-
Run 'kanonak logout ${
|
|
1
|
+
import{a as ir,b as sr,c as cr,d as lr,e as fe}from"./chunk-FX7JDGL6.js";import{a as Qr,c as ke,e as Te,h as Ne,i as Oe,j as en}from"./chunk-X5TYWQRA.js";import{a as nr,b as or,c as ar,d as U,e as _,f as c}from"./chunk-Y7TGQ7UF.js";import{a as Xr}from"./chunk-F5ANO7MJ.js";import"./chunk-QHABFCRC.js";import{a as jt,b as Bt,c as At,d as Vt,e as Dt,f as _t,g as Lt,h as Ft}from"./chunk-ATH6636H.js";import{b as Tt,c as Nt,d as Ut}from"./chunk-LKBG2MK6.js";import{a as It}from"./chunk-4NO7MHS7.js";import{a as dr,b as pr,c as mr,d as fr}from"./chunk-GN2XODVC.js";import{a as yr,b as wr}from"./chunk-PEUTCG3B.js";import{a as hr}from"./chunk-PEJALHXK.js";import{a as Ot}from"./chunk-SC5M74NM.js";import{A as Jr,B as qr,C as Yr,G as Zr,a as Sr,b as Rr,c as vr,d as Er,e as Cr,f as xr,g as Kr,h as $r,i as Ir,j as jr,k as Br,l as Ar,m as Vr,n as Dr,o as Tr,p as Nr,q as Or,r as Ur,s as _r,t as Lr,u as Fr,v as Mr,w as Hr,x as zr,y as Wr,z as Gr}from"./chunk-C7RZIMEH.js";import"./chunk-SHDHMKMJ.js";import{a as y,b as se,c as Gt,d as er,e as tr,f as v}from"./chunk-G2DKKSZ4.js";import{a as S}from"./chunk-TJPQETHV.js";import{a as rr,b as ye,c as gr,d as g,e as kr,f as br,g as Pr}from"./chunk-BGQKZBNE.js";import{f as O,j as E,k as ge,l as he,m as De}from"./chunk-CRKSKIAL.js";import{b as Jt,c as qt,d as R,e as Yt,f as Zt,h as Xt,j as Qt}from"./chunk-IOMNZBK4.js";import{a as Mt,b as ie,c as f,d as k,e as zt,f as Wt,g as ce,h as le,i as ue,j as de,k as pe,l as me}from"./chunk-W6T7MOKY.js";import{a as Ht}from"./chunk-FUUTGGJS.js";import{a as St,b as Rt,c as N,d as vt,e as h,f as Et,g as Ct,h as xt,i as Kt,j as $t}from"./chunk-2ACBWC7K.js";import{a as ur}from"./chunk-ODIECDN7.js";import{VersionOperator as ni}from"@kanonak-protocol/types/document/models/enums";import{existsSync as bn,readFileSync as Pn}from"fs";import{homedir as wn}from"os";import{join as Sn}from"path";import{execFile as tn}from"child_process";import{promisify as rn}from"util";var L=rn(tn),F="kanonak",M="/usr/bin/security",C=class{async get(e){let t=c(e);try{let{stdout:n}=await L(M,["find-generic-password","-s",F,"-a",t,"-w"],{timeout:1e4});try{return JSON.parse(n.trim())}catch{throw new Error(`Stored credential for '${t}' is corrupted (not valid JSON).
|
|
2
|
+
Run 'kanonak logout ${t}' then 'kanonak login ${t}' to fix.`)}}catch(n){if(Ue(n,44))return null;throw new Error(`macOS Keychain read failed for '${t}': ${H(n)}
|
|
3
3
|
The Keychain may be locked or inaccessible.
|
|
4
|
-
Try unlocking it via Keychain Access.app or running 'security unlock-keychain'.`)}}async store(e,
|
|
4
|
+
Try unlocking it via Keychain Access.app or running 'security unlock-keychain'.`)}}async store(e,t){let n=c(e),o=JSON.stringify(t);try{await L(M,["add-generic-password","-s",F,"-a",n,"-U","-w",o],{timeout:1e4})}catch(a){throw new Error(`macOS Keychain write failed for '${n}': ${H(a)}
|
|
5
5
|
Ensure the Keychain is unlocked and the CLI has write permission.
|
|
6
|
-
On managed devices, your IT policy may block credential storage.`)}}async remove(e){let
|
|
7
|
-
The credential may not have been fully removed.`)}}async list(){try{let{stdout:e}=await
|
|
8
|
-
`))if(o.includes(`"svce"<blob>="${
|
|
9
|
-
${
|
|
6
|
+
On managed devices, your IT policy may block credential storage.`)}}async remove(e){let t=c(e);try{await L(M,["delete-generic-password","-s",F,"-a",t],{timeout:1e4})}catch(n){if(Ue(n,44))return;console.warn(` Warning: macOS Keychain delete failed for '${t}': ${H(n)}
|
|
7
|
+
The credential may not have been fully removed.`)}}async list(){try{let{stdout:e}=await L(M,["dump-keychain"],{timeout:1e4}),t=[],n=!1;for(let o of e.split(`
|
|
8
|
+
`))if(o.includes(`"svce"<blob>="${F}"`)&&(n=!0),n&&o.includes('"acct"<blob>=')){let a=o.match(/"acct"<blob>="([^"]+)"/);a&&t.push(a[1]),n=!1}return t}catch(e){return console.warn(` Warning: Could not enumerate Keychain entries: ${H(e)}`),[]}}};function Ue(r,e){return typeof r=="object"&&r!==null&&"code"in r&&r.code===e}function H(r){return r instanceof Error?r.message:String(r)}import{execFile as nn}from"child_process";import{promisify as on}from"util";var an=on(nn),z="kanonak:",x=class{async get(e){let t=z+c(e),n=`
|
|
9
|
+
${G}
|
|
10
10
|
$target = [Console]::In.ReadLine()
|
|
11
11
|
$ptr = [IntPtr]::Zero
|
|
12
12
|
$result = [CredMan]::CredRead($target, 1, 0, [ref]$ptr)
|
|
@@ -18,8 +18,8 @@ try {
|
|
|
18
18
|
[System.Text.Encoding]::Unicode.GetString($bytes)
|
|
19
19
|
} finally {
|
|
20
20
|
[CredMan]::CredFree($ptr)
|
|
21
|
-
}`;try{let{stdout:o}=await
|
|
22
|
-
${
|
|
21
|
+
}`;try{let{stdout:o}=await W(n,t),a=o.trim();return a?JSON.parse(a):null}catch{return null}}async store(e,t){let n=z+c(e),o=JSON.stringify(t),a=`
|
|
22
|
+
${G}
|
|
23
23
|
$target = [Console]::In.ReadLine()
|
|
24
24
|
$json = [Console]::In.ReadLine()
|
|
25
25
|
$bytes = [System.Text.Encoding]::Unicode.GetBytes($json)
|
|
@@ -35,13 +35,13 @@ try {
|
|
|
35
35
|
if (-not $result) { throw "CredWrite failed" }
|
|
36
36
|
} finally {
|
|
37
37
|
[System.Runtime.InteropServices.Marshal]::FreeHGlobal($cred.CredentialBlob)
|
|
38
|
-
}`;try{await
|
|
39
|
-
${o}`)}catch(i){throw new Error(`Windows Credential Manager write failed: ${String(i)}`)}}async remove(e){let
|
|
40
|
-
${
|
|
38
|
+
}`;try{await W(a,`${n}
|
|
39
|
+
${o}`)}catch(i){throw new Error(`Windows Credential Manager write failed: ${String(i)}`)}}async remove(e){let t=z+c(e),n=`
|
|
40
|
+
${G}
|
|
41
41
|
$target = [Console]::In.ReadLine()
|
|
42
|
-
[CredMan]::CredDelete($target, 1, 0) | Out-Null`;try{await
|
|
43
|
-
${
|
|
44
|
-
${
|
|
42
|
+
[CredMan]::CredDelete($target, 1, 0) | Out-Null`;try{await W(n,t)}catch{}}async list(){let e=`
|
|
43
|
+
${G}
|
|
44
|
+
${sn}
|
|
45
45
|
$prefix = [Console]::In.ReadLine()
|
|
46
46
|
$count = 0
|
|
47
47
|
$pCreds = [IntPtr]::Zero
|
|
@@ -55,8 +55,8 @@ if ([CredMan]::CredEnumerate($null, 0, [ref]$count, [ref]$pCreds)) {
|
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
[CredMan]::CredFree($pCreds)
|
|
58
|
-
}`;try{let{stdout:
|
|
59
|
-
`).map(
|
|
58
|
+
}`;try{let{stdout:t}=await W(e,z);return t.trim().split(`
|
|
59
|
+
`).map(n=>n.trim()).filter(Boolean)}catch{return[]}}};async function W(r,e){for(let t of["pwsh","powershell"])try{return await an(t,["-NoProfile","-NonInteractive","-Command",r],{timeout:15e3,...e!==void 0&&{input:e}})}catch(n){if(t==="powershell")throw n}throw new Error("Neither pwsh nor powershell found")}var G=`
|
|
60
60
|
Add-Type -TypeDefinition @"
|
|
61
61
|
using System;
|
|
62
62
|
using System.Runtime.InteropServices;
|
|
@@ -87,13 +87,13 @@ public class CredMan {
|
|
|
87
87
|
[DllImport("Advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
|
88
88
|
public static extern bool CredEnumerate(string filter, int flags, out int count, out IntPtr credentials);
|
|
89
89
|
}
|
|
90
|
-
"@`,
|
|
91
|
-
`)){let o=
|
|
90
|
+
"@`,sn="";import{execFile as cn,spawn as ln}from"child_process";import{promisify as un}from"util";var q=un(cn),J="kanonak",K=class{async get(e){let t=c(e);try{let{stdout:n}=await q("secret-tool",["lookup","service",J,"publisher",t],{timeout:1e4}),o=n.trim();return o?JSON.parse(o):null}catch{return null}}async store(e,t){let n=c(e),o=JSON.stringify(t);await new Promise((a,i)=>{let s=ln("secret-tool",["store","--label",`Kanonak: ${n}`,"service",J,"publisher",n],{stdio:["pipe","ignore","ignore"],timeout:1e4});s.stdin.write(o),s.stdin.end(),s.on("close",l=>{l===0?a():i(new Error(`secret-tool store exited with code ${l}`))}),s.on("error",i)})}async remove(e){let t=c(e);try{await q("secret-tool",["clear","service",J,"publisher",t],{timeout:1e4})}catch{}}async list(){try{let{stdout:e}=await q("secret-tool",["search","service",J],{timeout:1e4}),t=[];for(let n of e.split(`
|
|
91
|
+
`)){let o=n.match(/attribute\.publisher\s*=\s*(.+)/);o&&t.push(o[1].trim())}return t}catch{return[]}}};async function be(){try{return await q("sh",["-c","command -v secret-tool"],{timeout:5e3}),!0}catch{return!1}}import{existsSync as _e,mkdirSync as Le,readFileSync as Fe,writeFileSync as Me}from"fs";import{createCipheriv as dn,createDecipheriv as pn,randomBytes as He}from"crypto";import{homedir as mn}from"os";import{join as Se,dirname as ze}from"path";var Ge=Se(mn(),".config","kanonak"),$=Se(Ge,"keyring.key"),Y=Se(Ge,"credentials.enc"),We="aes-256-gcm",Pe=32,b=12,we=16,I=class{async get(e){let t=this.loadStore(),n=c(e);return t[n]??null}async store(e,t){let n=this.loadStore(),o=c(e);n[o]=t,this.saveStore(n)}async remove(e){let t=this.loadStore(),n=c(e);delete t[n],this.saveStore(t)}async list(){let e=this.loadStore();return Object.keys(e)}loadStore(){if(!_e(Y))return{};try{let e=this.getOrCreateKey(),t=Fe(Y);if(t.length<b+we)return{};let n=t.subarray(0,b),o=t.subarray(b,b+we),a=t.subarray(b+we),i=pn(We,e,n);i.setAuthTag(o);let s=Buffer.concat([i.update(a),i.final()]);return JSON.parse(s.toString("utf-8"))}catch{return{}}}saveStore(e){let t=this.getOrCreateKey(),n=He(b),o=dn(We,t,n),a=Buffer.from(JSON.stringify(e),"utf-8"),i=Buffer.concat([o.update(a),o.final()]),s=o.getAuthTag(),l=Buffer.concat([n,s,i]);Le(ze(Y),{recursive:!0}),Me(Y,l,{mode:384})}getOrCreateKey(){if(_e($)){let t=Fe($);if(t.length!==Pe)throw new Error(`Credential keyring key is corrupted (expected ${Pe} bytes, got ${t.length}). Delete ${$} and re-authenticate.`);return t}let e=He(Pe);return Le(ze($),{recursive:!0}),Me($,e,{mode:384}),e}};import{execFile as fn}from"child_process";import{promisify as yn}from"util";var gn=yn(fn),Je=3e4,j=class{constructor(e){this.helperPath=e}helperPath;async get(e){let t=c(e);try{let o=(await this.runHelper("get",{publisher:t})).trim();return o?JSON.parse(o):null}catch(n){throw new Error(`Credential helper '${this.helperPath}' failed to read credential for '${t}': ${Z(n)}
|
|
92
92
|
Verify the helper binary exists, is executable, and implements the Kanonak credential helper protocol.
|
|
93
|
-
Check the 'credentialHelper' path in ~/.kanonak/config.json.`)}}async store(e,
|
|
94
|
-
Verify the helper binary supports the 'store' action.`)}}async remove(e){let
|
|
95
|
-
Check the 'credentialHelper' path in ~/.kanonak/config.json.`):
|
|
96
|
-
The helper may be waiting for authentication to an external vault.`):
|
|
97
|
-
Using default credential backend. Fix the JSON syntax or delete the file.`),{}}}import{createHash as
|
|
98
|
-
The stored key pair may be corrupted. Run 'kanonak login ${
|
|
99
|
-
`;function Je(t=Ge){if(!$r(t))return null;let e=Rr(t,"utf-8"),n=We.load(e);return!n||typeof n!="object"||n.version!=="1"?null:{version:"1",lastUpdated:n.lastUpdated??new Date().toISOString(),packages:n.packages??{}}}function qe(t,e=Ge){t.lastUpdated=new Date().toISOString();let n={};for(let o of Object.keys(t.packages).sort())n[o]=t.packages[o];t.packages=n;let r=We.dump(t,{lineWidth:-1,sortKeys:!1,quotingType:'"'});vr(e,xr+r,"utf-8")}function Ye(t){return`sha256:${Kr("sha256").update(t).digest("hex")}`}import*as Se from"js-yaml";import{createHash as Ir}from"crypto";function ke(t){let e=[];for(let r of t)r instanceof y&&e.push(jr(r));return e.sort((r,o)=>r.uri<o.uri?-1:r.uri>o.uri?1:0),JSON.stringify({subjects:e})}function G(t){let e=ke(t);return`sha256:${Ir("sha256").update(e,"utf8").digest("hex")}`}function jr(t){let e=Lr(t),n=be(t.statement);return{uri:e,statements:n}}function be(t){let e=[];for(let n of t){let r=Br(n);r&&e.push(r)}return e.sort((n,r)=>n.predicate<r.predicate?-1:n.predicate>r.predicate?1:0),e}function Br(t){let e=Or(t);if(!e)return;let n=Tr(t);if(n)return Ur(e,n)}function Tr(t){if(t instanceof ne)return{type:"string",value:t.object};if(t instanceof re)return{type:"number",value:et(t.object)};if(t instanceof oe)return{type:"boolean",value:t.object};if(t instanceof ae)return{type:"ref",value:Xe(t.object)};if(t instanceof ie){let e=t.object;return Ze(e)}if(t instanceof se)return{type:"list",items:t.object.map(Vr)}}function Ze(t){let e=be(t.statement);return t.name&&t.name.length>0?{type:"embedded",name:t.name,statements:e}:{type:"embedded",statements:e}}function Vr(t){if(t instanceof h)return{type:"ref",value:Xe(t)};if(t instanceof g)return Ze(t);if(t instanceof te){let e=t.value;if(typeof e=="string")return{type:"string",value:e};if(typeof e=="number")return{type:"number",value:et(e)};if(typeof e=="boolean")return{type:"boolean",value:e}}if(t instanceof ee)return{type:"embedded",statements:be(t.statement)};throw new Error(`canonicalForm: list item of unrecognized kind (${t.constructor?.name??typeof t}); add canonicalization support before hashing data that contains it`)}function Ur(t,e){switch(e.type){case"string":return{predicate:t,type:"string",value:e.value};case"number":return{predicate:t,type:"number",value:e.value};case"boolean":return{predicate:t,type:"boolean",value:e.value};case"ref":return{predicate:t,type:"ref",value:e.value};case"embedded":return e.name!==void 0?{predicate:t,type:"embedded",name:e.name,statements:e.statements}:{predicate:t,type:"embedded",statements:e.statements};case"list":return{predicate:t,type:"list",items:e.items}}}function Or(t){let e=t.predicate;if(e)return Qe(e.subject)}function Lr(t){let e=t.namespace??"",n=t.name??"";return`${e}/${n}`}function Xe(t){return Qe(t.subject)}function Qe(t){let e=t.version;return e&&typeof e.major=="number"?`${t.publisher}/${t.package_}@${e.major}.${e.minor}.${e.patch}/${t.name}`:`${t.publisher}/${t.package_}/${t.name}`}function et(t){if(Number.isNaN(t))throw new Error("canonicalForm: NaN cannot be canonicalized");if(!Number.isFinite(t))throw new Error("canonicalForm: \xB1Infinity cannot be canonicalized");return Object.is(t,-0)?"0":String(t)}var p="kanonak.org",m="view",tt="core-kanonak",Nr={publisher:p,package_:m,name:"rootView"},_r={publisher:p,package_:m,name:"bind"},Ar={publisher:p,package_:m,name:"produces"},Dr={publisher:p,package_:m,name:"projections"},Fr={publisher:p,package_:m,name:"where"},Mr={publisher:p,package_:m,name:"value"},Hr={publisher:p,package_:m,name:"as"},nt="__view_probe__",J=class{constructor(e,n=new Q){this.repository=e;this.parser=n;this.objectParser=new ce(this.parser)}repository;parser;objectParser;async materialize(e,n={}){let r=await this.objectParser.parseKanonaks(this.repository),o=this.resolveView(r,e),a=S(o,_r);if(!a)throw new Error(`View ${o.namespace}/${o.name} declares no view.bind; cannot materialize.`);let i=S(o,Ar);if(!i)throw new Error(`View ${o.namespace}/${o.name} is a selection view (no view.produces). In-graph materialization of selection views is not yet supported \u2014 declare a view.produces output class to reshape the result.`);let s=zr(o),l=rt(r,p,tt),u=rt(r,p,m),d=new we,q=d.ensure(p,tt,l,"ck"),it=d.ensure(p,m,u,"v"),st=d.ref(i),ct=new je(this.repository,this.parser,this.objectParser),Pe=new xe(ct,r),lt=this.readProjections(r,o),ut=Jr(o,Fr),dt=this.findInstances(r,a,await this.reason(n)),K={},pt=new Set;for(let x of dt){if(!await this.passesWhere(Pe,r,ut,x))continue;let X={type:st};for(let ve of lt){let ft=await this.evaluateValue(Pe,r,ve.value,x),$e=ot(ft,d);$e!==void 0&&(X[d.ref(ve.as)]=$e)}let Re=f(x);Re&&(X[`${it}.derivedFrom`]=d.ref(Re)),K[this.rowName(x,pt)]=X}let Ce=d.toImports(),Y=await this.hashBody(s,Ce,K),Ee=`q-${Y.slice(7,23)}`,Z={type:"EphemeralPackage",publisher:s,imports:Ce,[`${q}.contentHash`]:Y};n.resolvedAt&&(Z[`${q}.resolvedAt`]=n.resolvedAt),n.invocationId&&(Z[`${q}.id`]=n.invocationId);let mt={[Ee]:Z,...K};return{yaml:Se.dump(mt,{lineWidth:-1}),contentHash:Y,packageName:Ee,publisher:s,rowCount:Object.keys(K).length}}resolveView(e,n){let r=B(e,n);if(!r)throw new Error(`View ${n.publisher}/${n.package_}/${n.name} not found in the catalog.`);let o=S(r,Nr);if(o){let a=B(e,o);if(!a)throw new Error(`ViewPackage ${n.name} names rootView ${o.name}, which is not in the catalog.`);return a}return r}readProjections(e,n){let r=[];for(let o of de(n,Dr)){let a=o instanceof g?o:o instanceof h?B(e,o.subject):void 0;if(!a)continue;let i=ue(a,Mr),s=S(a,Hr);i&&s&&r.push({value:i,as:s})}return r}async reason(e){return new le({profile:e.reasoningProfile??"owl-rl-classification"}).reason(this.repository)}findInstances(e,n,r){let o=Gr(e),a=[],i=new Set;for(let s of r.getInstancesOfClass(n)){if(i.has(s))continue;i.add(s);let l=o.get(s);l&&a.push(l)}return a.sort((s,l)=>{let u=b(f(s)),d=b(f(l));return u<d?-1:u>d?1:0}),a}async passesWhere(e,n,r,o){for(let a of r){let i=await this.evaluateValue(e,n,a,o);if(!qr(i))return!1}return!0}async evaluateValue(e,n,r,o){let a=Ie(r,"view-projection",{catalog:n,depth:0}),i=new Map([["input",o]]);return e.evaluate(a,i)}rowName(e,n){let r=at(e.name)||"row",o=r,a=2;for(;n.has(o);)o=`${r}-${a++}`;return n.add(o),o}async hashBody(e,n,r){let o={[nt]:{type:"EphemeralPackage",publisher:e,imports:n},...r},a=this.parser.parse(Se.dump(o,{lineWidth:-1})),i=a.metadata.namespace_?.toString(),l=(await this.objectParser.parseKanonaks(new Ke(a,this.repository))).filter(u=>u instanceof y&&u.namespace===i&&u.name!==nt);for(let u of l)u.namespace="ephemeral";return G(l)}},we=class{byKey=new Map;aliases=new Set;ensure(e,n,r,o){let a=`${e}/${n}@${r}`,i=this.byKey.get(a);if(i)return i.alias;let s=this.uniqueAlias(o);return this.byKey.set(a,{publisher:e,package_:n,version:r,alias:s}),s}ref(e){if(!e.version||typeof e.version.major!="number")throw new Error(`Cannot serialize a reference to ${e.publisher}/${e.package_}/${e.name} without a version.`);return`${this.ensure(e.publisher,e.package_,j(e.version),e.package_)}.${e.name}`}toImports(){let e=new Map;for(let r of this.byKey.values()){let o=e.get(r.publisher)??[];o.push(r),e.set(r.publisher,o)}return[...e.keys()].sort().map(r=>({publisher:r,packages:e.get(r).sort((o,a)=>o.package_<a.package_?-1:1).map(o=>({package:o.package_,match:"^",version:o.version,alias:o.alias}))}))}uniqueAlias(e){let n=at(e)||"pkg",r=n,o=2;for(;this.aliases.has(r);)r=`${n}${o++}`;return this.aliases.add(r),r}};function ot(t,e){if(t!=null){if(typeof t=="string"||typeof t=="number"||typeof t=="boolean")return t;if(pe(t))return t.value;if(t instanceof h)return e.ref(t.subject);if(Array.isArray(t)){let n=t.map(r=>ot(r,e)).filter(r=>r!==void 0);return n.length>0?n:void 0}if(t instanceof g)throw new Error("Embedded projection values are not yet supported by the in-graph materializer. Project a literal or a reference, or compose the embedded shape into the produces class.");if(Yr(t))throw new Error(`Projection produced a bare URI without a version (${t.publisher}/${t.package_}/${t.name}); cannot serialize it as a reference.`)}}function zr(t){let e=f(t);if(!e)throw new Error(`Could not derive a publisher from view ${t.namespace}/${t.name}.`);return e.publisher}function rt(t,e,n){let r=Wr(t,e,n);if(!r)throw new Error(`Package ${e}/${n} is not in the catalog; it must be importable to materialize a view.`);return r}function Wr(t,e,n){let r;for(let o of t){if(!(o instanceof y))continue;let a=f(o);!a||a.publisher!==e||a.package_!==n||!a.version||(!r||I(a.version,r)>0)&&(r=a.version)}return r?j(r):void 0}function Gr(t){let e=new Map,n=new Map;for(let r of t){if(!(r instanceof y))continue;let o=f(r);if(!o||!o.version)continue;let a=b(o),i=n.get(a);(!i||I(o.version,i)>0)&&(n.set(a,o.version),e.set(a,r))}return e}function Jr(t,e){let n=ue(t,e);return n?[n]:de(t,e).filter(r=>r instanceof g)}function at(t){return t.replace(/[^A-Za-z0-9-]/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")}function qr(t){return t===!0?!0:t===!1||t===void 0||t===null?!1:typeof t=="string"?t.length>0:typeof t=="number"?t!==0:pe(t)?t.value.length>0:Array.isArray(t)?t.length>0:!!t}function Yr(t){return typeof t=="object"&&t!==null&&typeof t.publisher=="string"&&typeof t.package_=="string"&&typeof t.name=="string"}export{Nn as AmbiguousReferenceRule,oe as BooleanStatement,Hn as ClassDefinitionRule,xn as ClassHierarchyCycleRule,vt as CompositeKanonakDocumentRepository,W as CredentialStore,ee as DefinedKanonak,On as DefinitionPropertyReferenceRule,Rt as DocumentLocation,Zt as EdgeType,g as EmbeddedKanonak,vn as EmbeddedKanonakTypeRule,ie as EmbeddedStatement,Et as FileSystemKanonakDocumentRepository,rn as GitIgnoreFilter,Xt as GraphBuilder,Bt as HttpKanonakDocumentRepository,$n as ImportExistenceRule,Ct as InMemoryKanonakDocumentRepository,Un as InstancePropertyReferenceRule,Ot as Kanonak,an as KanonakDocumentPositions,ce as KanonakObjectParser,Wn as KanonakObjectValidator,Q as KanonakParser,Lt as KanonakUri,ln as KanonakUriBuilder,pn as KanonakUrlResolver,Wt as KanonakVocabulary,se as ListStatement,te as LiteralKanonak,Tt as LocalFirstRepository,qn as LookRenderer,zn as MarkdownLinkRule,At as MarkdownStatement,Vn as NamespaceImportCycleRule,Pn as NamespacePrefixRule,Yt as NodeType,re as NumberStatement,tn as OWL_RL_CLASSIFICATION_RULES,An as ObjectPropertyImportRule,Dn as ObjectPropertyValueValidationRule,bn as OntologyValidationError,hn as OntologyValidationResult,Fn as PropertyDomainRule,In as PropertyHierarchyCycleRule,on as PropertyMetadata,_n as PropertyRangeReferenceRule,jn as PropertyRangeRequiredRule,En as PropertyTypeSpecificityRule,Mn as PropertyValueTypeRule,xt as PublisherConfigResolver,It as PublisherIndex,en as RDFS_RULES,le as Reasoner,nn as ReasoningResult,h as ReferenceKanonak,ae as ReferenceStatement,Kt as RepositoryFactory,Cn as ResourceNamingRule,Dt as ResourceResolver,qt as ResourceTypeClassifier,_t as ScalarStatement,Nt as Statement,ne as StringStatement,Bn as SubClassOfReferenceRule,Tn as SubPropertyOfReferenceRule,y as SubjectKanonak,Rn as SubjectKanonakTypeRequiredRule,Qt as TripleStore,Ft as TypeResolver,Kn as UnresolvedReferenceRule,wn as ValidationCache,Sn as ValidationContext,kn as ValidationSeverity,Ua as VersionOperator,J as ViewMaterializer,Ln as XsdImportRule,jt as assertPackageIdentity,Ut as buildLocalFirstRepository,ke as canonicalForm,G as canonicalHash,Vt as collectKanonakFiles,I as compareVersions,Ye as computeIntegrity,yn as contextTypesOf,ze as createAuthenticatedFetch,$ as createDPoPProof,kt as createVersion,Jt as extractMarkdownLinks,Gn as findDerivation,gn as findInstancesByType,Gt as findMalformedReferences,cn as findMarkdownLinkAt,dn as formatKanonakAddress,j as formatVersion,Me as generateDPoPKeyPair,$t as getGlobalCachePath,V as hasValidToken,St as isCompatibleVersion,T as isExpired,wt as isMajorCompatible,Je as loadLockFile,Mt as makeUriKey,c as normalizeHost,un as parseKanonakAddress,bt as parseVersionString,sn as parseWithPositions,Pt as pickHighestDocument,mn as propertiesInScope,Jn as resolveDisplayValue,fn as resolvePropertyStep,qe as saveLockFile,He as serverSupportsDPoP,f as subjectUri,Ht as tripleKey,b as uriKey,zt as uriTriple,yt as versionOperatorFromChar,gt as versionOperatorToChar,ht as versionsEqual};
|
|
93
|
+
Check the 'credentialHelper' path in ~/.kanonak/config.json.`)}}async store(e,t){let n=c(e);try{await this.runHelper("store",{publisher:n,credential:t})}catch(o){throw new Error(`Credential helper '${this.helperPath}' failed to store credential for '${n}': ${Z(o)}
|
|
94
|
+
Verify the helper binary supports the 'store' action.`)}}async remove(e){let t=c(e);try{await this.runHelper("erase",{publisher:t})}catch(n){console.warn(` Warning: Credential helper '${this.helperPath}' failed to erase credential for '${t}': ${Z(n)}`)}}async list(){try{let e=await this.runHelper("list",void 0);return JSON.parse(e.trim())}catch(e){return console.warn(` Warning: Credential helper '${this.helperPath}' failed to list credentials: ${Z(e)}`),[]}}async runHelper(e,t){try{let{stdout:n}=await gn(this.helperPath,[e],{...t&&{input:JSON.stringify(t)},timeout:Je});return n}catch(n){throw hn(n)?new Error(`Credential helper not found at '${this.helperPath}'.
|
|
95
|
+
Check the 'credentialHelper' path in ~/.kanonak/config.json.`):kn(n)?new Error(`Credential helper '${this.helperPath}' timed out after ${Je/1e3}s on '${e}'.
|
|
96
|
+
The helper may be waiting for authentication to an external vault.`):n}}};function Z(r){return r instanceof Error?r.message:String(r)}function hn(r){return r instanceof Error&&"code"in r&&r.code==="ENOENT"}function kn(r){return r instanceof Error&&"killed"in r&&r.killed}var Re=Sn(wn(),".kanonak","config.json"),X=class{backend=null;backendReady=null;async getBackend(){if(this.backend)return this.backend;if(this.backendReady)return this.backendReady;this.backendReady=this.resolveBackend();try{return this.backend=await this.backendReady,this.backend}catch(e){throw this.backendReady=null,e}}async getToken(e){let t=Rn(e);if(t)return t;let o=await(await this.getBackend()).get(e);return!o||!_(o)?null:o.accessToken??null}async getCredential(e){return(await this.getBackend()).get(e)}async store(e,t){return(await this.getBackend()).store(e,t)}async remove(e){return(await this.getBackend()).remove(e)}async list(){return(await this.getBackend()).list()}async resolveBackend(){let e=vn();return e.credentialHelper?new j(e.credentialHelper):process.platform==="darwin"?new C:process.platform==="win32"?new x:await be()?new K:new I}};function Rn(r){let t="KANONAK_TOKEN_"+c(r).replace(/[.\-]/g,"_").toUpperCase();return process.env[t]??null}function vn(){if(!bn(Re))return{};try{return JSON.parse(Pn(Re,"utf-8"))}catch(r){let e=r instanceof Error?r.message:String(r);return console.warn(` Warning: Failed to parse ${Re}: ${e}
|
|
97
|
+
Using default credential backend. Fix the JSON syntax or delete the file.`),{}}}import{createHash as En,createPrivateKey as Cn,generateKeyPairSync as xn,randomUUID as Kn,sign as $n}from"crypto";function Ye(){let{publicKey:r,privateKey:e}=xn("ec",{namedCurve:"P-256"});return{publicKey:r.export({format:"jwk"}),privateKey:e.export({format:"jwk"})}}function B(r,e,t,n,o,a){let i={alg:"ES256",typ:"dpop+jwt",jwk:{kty:e.kty,crv:e.crv,x:e.x,y:e.y}},s={jti:Kn(),htm:t.toUpperCase(),htu:n,iat:Math.floor(Date.now()/1e3)};return o&&(s.ath=En("sha256").update(o).digest("base64url")),a&&(s.nonce=a),In(i,s,r)}function Ze(r){return!r||r.length===0?!1:r.some(e=>e.toUpperCase()==="ES256")}function In(r,e,t){let n=qe(JSON.stringify(r)),o=qe(JSON.stringify(e)),a=`${n}.${o}`,i=Cn({key:t,format:"jwk"}),l=$n("SHA256",Buffer.from(a),{key:i,dsaEncoding:"ieee-p1363"}).toString("base64url");return`${a}.${l}`}function qe(r){return Buffer.from(r,"utf-8").toString("base64url")}function Xe(r){let e=new Map;return async(t,n,o="GET")=>{if(!r)return fetch(t,{method:o});let a=await r.getCredential(n);if(!a?.accessToken)return fetch(t,{method:o});U(a)&&console.warn(` Warning: Access token for '${n}' is expired. Run 'kanonak login ${n}' to re-authenticate.`);let i={};if(a.dpopKeyPair){let l=e.get(n);try{let u=B(a.dpopKeyPair.privateKey,a.dpopKeyPair.publicKey,o,t,a.accessToken,l);i.Authorization=`DPoP ${a.accessToken}`,i.DPoP=u}catch(u){let d=u instanceof Error?u.message:String(u);console.error(` Error: Failed to create DPoP proof for '${n}': ${d}
|
|
98
|
+
The stored key pair may be corrupted. Run 'kanonak login ${n}' to re-authenticate.`),i.Authorization=`Bearer ${a.accessToken}`}}else i.Authorization=`Bearer ${a.accessToken}`;let s=await fetch(t,{method:o,headers:i});if(s.status===401&&a.dpopKeyPair){let l=s.headers.get("DPoP-Nonce");if(l){e.set(n,l);try{let u=B(a.dpopKeyPair.privateKey,a.dpopKeyPair.publicKey,o,t,a.accessToken,l);i.DPoP=u,s=await fetch(t,{method:o,headers:i})}catch{}}}return s}}import{readFileSync as jn,writeFileSync as Bn,existsSync as An}from"fs";import{createHash as Vn}from"crypto";import Qe from"js-yaml";var et="kanonak.lock",Dn=`# This file is generated by Kanonak CLI. Do not edit manually.
|
|
99
|
+
`;function tt(r=et){if(!An(r))return null;let e=jn(r,"utf-8"),t=Qe.load(e);return!t||typeof t!="object"||t.version!=="1"?null:{version:"1",lastUpdated:t.lastUpdated??new Date().toISOString(),packages:t.packages??{}}}function rt(r,e=et){r.lastUpdated=new Date().toISOString();let t={};for(let o of Object.keys(r.packages).sort())t[o]=r.packages[o];r.packages=t;let n=Qe.dump(r,{lineWidth:-1,sortKeys:!1,quotingType:'"'});Bn(e,Dn+n,"utf-8")}function nt(r){return`sha256:${Vn("sha256").update(r).digest("hex")}`}import*as Ce from"js-yaml";import{createHash as Tn}from"crypto";function ve(r){let e=[];for(let n of r)n instanceof f&&e.push(Nn(n));return e.sort((n,o)=>n.uri<o.uri?-1:n.uri>o.uri?1:0),JSON.stringify({subjects:e})}function Q(r){let e=ve(r);return`sha256:${Tn("sha256").update(e,"utf8").digest("hex")}`}function Nn(r){let e=Mn(r),t=Ee(r.statement);return{uri:e,statements:t}}function Ee(r){let e=[];for(let t of r){let n=On(t);n&&e.push(n)}return e.sort((t,n)=>t.predicate<n.predicate?-1:t.predicate>n.predicate?1:0),e}function On(r){let e=Fn(r);if(!e)return;let t=Un(r);if(t)return Ln(e,t)}function Un(r){if(r instanceof ce)return{type:"string",value:r.object};if(r instanceof le)return{type:"number",value:st(r.object)};if(r instanceof ue)return{type:"boolean",value:r.object};if(r instanceof de)return{type:"ref",value:at(r.object)};if(r instanceof pe){let e=r.object;return ot(e)}if(r instanceof me)return{type:"list",items:r.object.map(_n)}}function ot(r){let e=Ee(r.statement);return r.name&&r.name.length>0?{type:"embedded",name:r.name,statements:e}:{type:"embedded",statements:e}}function _n(r){if(r instanceof k)return{type:"ref",value:at(r)};if(r instanceof y)return ot(r);if(r instanceof se){let e=r.value;if(typeof e=="string")return{type:"string",value:e};if(typeof e=="number")return{type:"number",value:st(e)};if(typeof e=="boolean")return{type:"boolean",value:e}}if(r instanceof ie)return{type:"embedded",statements:Ee(r.statement)};throw new Error(`canonicalForm: list item of unrecognized kind (${r.constructor?.name??typeof r}); add canonicalization support before hashing data that contains it`)}function Ln(r,e){switch(e.type){case"string":return{predicate:r,type:"string",value:e.value};case"number":return{predicate:r,type:"number",value:e.value};case"boolean":return{predicate:r,type:"boolean",value:e.value};case"ref":return{predicate:r,type:"ref",value:e.value};case"embedded":return e.name!==void 0?{predicate:r,type:"embedded",name:e.name,statements:e.statements}:{predicate:r,type:"embedded",statements:e.statements};case"list":return{predicate:r,type:"list",items:e.items}}}function Fn(r){let e=r.predicate;if(e)return it(e.subject)}function Mn(r){let e=r.namespace??"",t=r.name??"";return`${e}/${t}`}function at(r){return it(r.subject)}function it(r){let e=r.version;return e&&typeof e.major=="number"?`${r.publisher}/${r.package_}@${e.major}.${e.minor}.${e.patch}/${r.name}`:`${r.publisher}/${r.package_}/${r.name}`}function st(r){if(Number.isNaN(r))throw new Error("canonicalForm: NaN cannot be canonicalized");if(!Number.isFinite(r))throw new Error("canonicalForm: \xB1Infinity cannot be canonicalized");return Object.is(r,-0)?"0":String(r)}var P=class{constructor(e,t=new S,n){this.repository=e;this.parser=t;this.objectParser=n??new v(this.parser)}repository;parser;objectParser;imports(){return new A}serializeValue(e,t){return ut(e,t)}async buildContentAddressed(e){let t=e.book.toImports(),n=await this.hashBody(e.publisher,t,e.body),o=xe(n),a={type:"EphemeralPackage",publisher:e.publisher,imports:t};e.contentHashProperty&&(a[e.contentHashProperty]=n),Object.assign(a,e.header??{});let i={[o]:a,...e.body},s=this.dump(i);return{yaml:s,byteCount:lt(s),contentHash:n,packageName:o,publisher:e.publisher,resourceCount:Object.keys(e.body).length}}async buildNamed(e){let t=e.book.toImports(),n={type:e.type??"Package",publisher:e.publisher,version:e.version,imports:t},o;e.contentHashProperty&&(o=await this.hashBody(e.publisher,t,e.body),n[e.contentHashProperty]=o),Object.assign(n,e.header??{});let a={[e.name]:n,...e.body},i=this.dump(a),s={yaml:i,byteCount:lt(i),packageName:e.name,publisher:e.publisher,resourceCount:Object.keys(e.body).length};return o!==void 0&&(s.contentHash=o),s}dump(e){return Ce.dump(e,{lineWidth:-1})}async hashBody(e,t,n){let o={[ct]:{type:"EphemeralPackage",publisher:e,imports:t},...n},a=this.parser.parse(Ce.dump(o,{lineWidth:-1})),i=a.metadata.namespace_?.toString(),l=(await this.objectParser.parseKanonaks(new De(a,this.repository))).filter(u=>u instanceof f&&u.namespace===i&&u.name!==ct);for(let u of l)u.namespace="ephemeral";return Q(l)}},ct="__pkgbuilder_probe__";function lt(r){return new TextEncoder().encode(r).length}function xe(r){let e="sha256:",t=r.startsWith(e)?e.length:0;return`q-${r.slice(t,t+16)}`}var A=class{byKey=new Map;aliases=new Set;ensure(e,t,n,o){let a=`${e}/${t}@${n}`,i=this.byKey.get(a);if(i)return i.alias;let s=this.uniqueAlias(o);return this.byKey.set(a,{publisher:e,package_:t,version:n,alias:s}),s}ref(e){if(!e.version||typeof e.version.major!="number")throw new Error(`Cannot serialize a reference to ${e.publisher}/${e.package_}/${e.name} without a version.`);return`${this.ensure(e.publisher,e.package_,h(e.version),e.package_)}.${e.name}`}toImports(){let e=new Map;for(let n of this.byKey.values()){let o=e.get(n.publisher)??[];o.push(n),e.set(n.publisher,o)}return[...e.keys()].sort().map(n=>({publisher:n,packages:e.get(n).sort((o,a)=>o.package_<a.package_?-1:1).map(o=>({package:o.package_,match:"^",version:o.version,alias:o.alias}))}))}uniqueAlias(e){let t=V(e)||"pkg",n=t,o=2;for(;this.aliases.has(n);)n=`${t}${o++}`;return this.aliases.add(n),n}};function ut(r,e){if(r!=null){if(typeof r=="string"||typeof r=="number"||typeof r=="boolean")return r;if(r instanceof k)return e.ref(r.subject);if(Array.isArray(r)){let t=r.map(n=>ut(n,e)).filter(n=>n!==void 0);return t.length>0?t:void 0}if(r instanceof y)throw new Error("Embedded values are not yet supported by PackageBuilder. Produce a literal or a reference, or compose the embedded shape into the output class.");if(Hn(r))throw new Error(`Value produced a bare URI without a version (${r.publisher}/${r.package_}/${r.name}); cannot serialize it as a reference.`)}}function V(r){return r.replace(/[^A-Za-z0-9-]/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")}function Hn(r){return typeof r=="object"&&r!==null&&typeof r.publisher=="string"&&typeof r.package_=="string"&&typeof r.name=="string"}var ee=class{constructor(e){this.producers=e}producers;produced=new Map;producerFor(e,t){return this.producers.find(n=>n.canProduce(e,t))}async produceCached(e,t,n,o){let a=`${t}/${n}@${h(o)}`,i=this.produced.get(a);if(i)return i;let{document:s}=await e.produce(t,n,o);return this.produced.set(a,s),s}async getHighestCompatibleVersionAsync(e,t){let n=this.producerFor(e,t.packageName);if(!n)return null;let o={operator:t.versionOperator,version:t.version},a=await n.resolveVersion(e,t.packageName,o);return a?this.produceCached(n,e,t.packageName,a):null}async getDocumentAsync(e){let t;try{t=ye(e)}catch{return null}if(t.kind!=="package"||!t.version)return null;let n=this.producerFor(t.publisher,t.package_);return n?this.produceCached(n,t.publisher,t.package_,t.version):null}async getDocumentsByNamespaceAsync(e,t){return Array.from(this.produced.values()).filter(n=>{let o=n.metadata.namespace_;return o!=null&&o.publisher===e&&o.package_===t})}async getAllDocumentsAsync(){return Array.from(this.produced.values())}async saveDocumentAsync(e,t){throw new Error("ProducerRepository is read-only: a producer is a source, not a store.")}async deleteDocumentAsync(e){throw new Error("ProducerRepository is read-only: a producer is a source, not a store.")}async clearNamespaceAsync(e,t){throw new Error("ProducerRepository is read-only: a producer is a source, not a store.")}async getAllDocumentReferencesAsync(){return[]}async getDocumentContentAsync(e){return null}async getDocumentUriAsync(e){return null}};var Ke={async authorize(){return{allowed:!0}}},$e={async record(){}},D=class extends Error{constructor(t,n){let o=`${t.publisher}/${t.package_}${t.version?`@${t.version.major}.${t.version.minor}.${t.version.patch}`:""}`;super(`Not entitled to produce ${o}${n?`: ${n}`:""}`);this.address=t;this.reason=n;this.name="EntitlementDeniedError"}address;reason},te=class{inner;ctx;policy;meter;constructor(e,t,n=Ke,o=$e){this.inner=e,this.ctx=t,this.policy=n,this.meter=o}canProduce(e,t){return this.inner.canProduce(e,t)}async resolveVersion(e,t,n){return await this.assertAllowed({publisher:e,package_:t,version:n.version}),this.inner.resolveVersion(e,t,n)}async produce(e,t,n){let o={publisher:e,package_:t,version:n};await this.assertAllowed(o);let a=await this.inner.produce(e,t,n);return await this.meter.record(this.ctx,o,a),a}async assertAllowed(e){let t=await this.policy.authorize(this.ctx,e);if(!t.allowed)throw new D(e,t.reason)}};var p="kanonak.org",m="view",dt="core-kanonak",zn={publisher:p,package_:m,name:"rootView"},Wn={publisher:p,package_:m,name:"bind"},Gn={publisher:p,package_:m,name:"produces"},Jn={publisher:p,package_:m,name:"projections"},qn={publisher:p,package_:m,name:"where"},Yn={publisher:p,package_:m,name:"value"},Zn={publisher:p,package_:m,name:"as"},re=class{constructor(e,t=new S){this.repository=e;this.parser=t;this.objectParser=new v(this.parser),this.builder=new P(this.repository,this.parser,this.objectParser)}repository;parser;objectParser;builder;async materialize(e,t={}){let n=await this.objectParser.parseKanonaks(this.repository),o=this.resolveView(n,e),a=E(o,Wn);if(!a)throw new Error(`View ${o.namespace}/${o.name} declares no view.bind; cannot materialize.`);let i=E(o,Gn);if(!i)throw new Error(`View ${o.namespace}/${o.name} is a selection view (no view.produces). In-graph materialization of selection views is not yet supported \u2014 declare a view.produces output class to reshape the result.`);let s=Xn(o),l=pt(n,p,dt),u=pt(n,p,m),d=this.builder.imports(),ne=d.ensure(p,dt,l,"ck"),ft=d.ensure(p,m,u,"v"),yt=d.ref(i),gt=new Oe(this.repository,this.parser,this.objectParser),Ie=new Te(gt,n),ht=this.readProjections(n,o),kt=to(o,qn),bt=this.findInstances(n,a,await this.reason(t)),je={},Pt=new Set;for(let T of bt){if(!await this.passesWhere(Ie,n,kt,T))continue;let ae={type:yt};for(let Ae of ht){let wt=await this.evaluateValue(Ie,n,Ae.value,T),Ve=this.builder.serializeValue(mt(wt),d);Ve!==void 0&&(ae[d.ref(Ae.as)]=Ve)}let Be=g(T);Be&&(ae[`${ft}.derivedFrom`]=d.ref(Be)),je[this.rowName(T,Pt)]=ae}let oe={};t.resolvedAt&&(oe[`${ne}.resolvedAt`]=t.resolvedAt),t.invocationId&&(oe[`${ne}.id`]=t.invocationId);let w=await this.builder.buildContentAddressed({publisher:s,book:d,body:je,contentHashProperty:`${ne}.contentHash`,header:oe});return{yaml:w.yaml,contentHash:w.contentHash,packageName:w.packageName,publisher:w.publisher,rowCount:w.resourceCount}}resolveView(e,t){let n=O(e,t);if(!n)throw new Error(`View ${t.publisher}/${t.package_}/${t.name} not found in the catalog.`);let o=E(n,zn);if(o){let a=O(e,o);if(!a)throw new Error(`ViewPackage ${t.name} names rootView ${o.name}, which is not in the catalog.`);return a}return n}readProjections(e,t){let n=[];for(let o of he(t,Jn)){let a=o instanceof y?o:o instanceof k?O(e,o.subject):void 0;if(!a)continue;let i=ge(a,Yn),s=E(a,Zn);i&&s&&n.push({value:i,as:s})}return n}async reason(e){return new fe({profile:e.reasoningProfile??"owl-rl-classification"}).reason(this.repository)}findInstances(e,t,n){let o=eo(e),a=[],i=new Set;for(let s of n.getInstancesOfClass(t)){if(i.has(s))continue;i.add(s);let l=o.get(s);l&&a.push(l)}return a.sort((s,l)=>{let u=R(g(s)),d=R(g(l));return u<d?-1:u>d?1:0}),a}async passesWhere(e,t,n,o){for(let a of n){let i=await this.evaluateValue(e,t,a,o);if(!ro(i))return!1}return!0}async evaluateValue(e,t,n,o){let a=Ne(n,"view-projection",{catalog:t,depth:0}),i=new Map([["input",o]]);return e.evaluate(a,i)}rowName(e,t){let n=V(e.name)||"row",o=n,a=2;for(;t.has(o);)o=`${n}-${a++}`;return t.add(o),o}};function mt(r){return ke(r)?r.value:Array.isArray(r)?r.map(mt):r}function Xn(r){let e=g(r);if(!e)throw new Error(`Could not derive a publisher from view ${r.namespace}/${r.name}.`);return e.publisher}function pt(r,e,t){let n=Qn(r,e,t);if(!n)throw new Error(`Package ${e}/${t} is not in the catalog; it must be importable to materialize a view.`);return n}function Qn(r,e,t){let n;for(let o of r){if(!(o instanceof f))continue;let a=g(o);!a||a.publisher!==e||a.package_!==t||!a.version||(!n||N(a.version,n)>0)&&(n=a.version)}return n?h(n):void 0}function eo(r){let e=new Map,t=new Map;for(let n of r){if(!(n instanceof f))continue;let o=g(n);if(!o||!o.version)continue;let a=R(o),i=t.get(a);(!i||N(o.version,i)>0)&&(t.set(a,o.version),e.set(a,n))}return e}function to(r,e){let t=ge(r,e);return t?[t]:he(r,e).filter(n=>n instanceof y)}function ro(r){return r===!0?!0:r===!1||r===void 0||r===null?!1:typeof r=="string"?r.length>0:typeof r=="number"?r!==0:ke(r)?r.value.length>0:Array.isArray(r)?r.length>0:!!r}export{Mr as AmbiguousReferenceRule,ue as BooleanStatement,qr as ClassDefinitionRule,Vr as ClassHierarchyCycleRule,At as CompositeKanonakDocumentRepository,X as CredentialStore,ie as DefinedKanonak,Lr as DefinitionPropertyReferenceRule,Bt as DocumentLocation,or as EdgeType,y as EmbeddedKanonak,jr as EmbeddedKanonakTypeRule,pe as EmbeddedStatement,D as EntitlementDeniedError,te as EntitlementProducer,jt as FileSystemKanonakDocumentRepository,ur as GitIgnoreFilter,ar as GraphBuilder,Ut as HttpKanonakDocumentRepository,A as ImportBook,Br as ImportExistenceRule,It as InMemoryKanonakDocumentRepository,_r as InstancePropertyReferenceRule,Mt as Kanonak,pr as KanonakDocumentPositions,v as KanonakObjectParser,Zr as KanonakObjectValidator,S as KanonakParser,Ht as KanonakUri,yr as KanonakUriBuilder,hr as KanonakUrlResolver,Qt as KanonakVocabulary,me as ListStatement,se as LiteralKanonak,_t as LocalFirstRepository,en as LookRenderer,Yr as MarkdownLinkRule,Gt as MarkdownStatement,Ur as NamespaceImportCycleRule,xr as NamespacePrefixRule,nr as NodeType,le as NumberStatement,cr as OWL_RL_CLASSIFICATION_RULES,zr as ObjectPropertyImportRule,Wr as ObjectPropertyValueValidationRule,vr as OntologyValidationError,Sr as OntologyValidationResult,P as PackageBuilder,ee as ProducerRepository,Gr as PropertyDomainRule,Dr as PropertyHierarchyCycleRule,dr as PropertyMetadata,Hr as PropertyRangeReferenceRule,Tr as PropertyRangeRequiredRule,$r as PropertyTypeSpecificityRule,Jr as PropertyValueTypeRule,Tt as PublisherConfigResolver,Nt as PublisherIndex,sr as RDFS_RULES,fe as Reasoner,lr as ReasoningResult,k as ReferenceKanonak,de as ReferenceStatement,Dt as RepositoryFactory,Kr as ResourceNamingRule,Jt as ResourceResolver,rr as ResourceTypeClassifier,Wt as ScalarStatement,zt as Statement,ce as StringStatement,Nr as SubClassOfReferenceRule,Or as SubPropertyOfReferenceRule,f as SubjectKanonak,Ir as SubjectKanonakTypeRequiredRule,ir as TripleStore,qt as TypeResolver,Ar as UnresolvedReferenceRule,Cr as ValidationCache,Er as ValidationContext,Rr as ValidationSeverity,ni as VersionOperator,re as ViewMaterializer,Fr as XsdImportRule,Ke as allowAllPolicy,Ot as assertPackageIdentity,Ft as buildLocalFirstRepository,ve as canonicalForm,Q as canonicalHash,Lt as collectKanonakFiles,N as compareVersions,nt as computeIntegrity,xe as contentAddressedName,Pr as contextTypesOf,Xe as createAuthenticatedFetch,B as createDPoPProof,Et as createVersion,tr as extractMarkdownLinks,Xr as findDerivation,wr as findInstancesByType,er as findMalformedReferences,fr as findMarkdownLinkAt,gr as formatKanonakAddress,h as formatVersion,Ye as generateDPoPKeyPair,Vt as getGlobalCachePath,_ as hasValidToken,xt as isCompatibleVersion,U as isExpired,Kt as isMajorCompatible,tt as loadLockFile,Yt as makeUriKey,$e as noopMeter,c as normalizeHost,ye as parseKanonakAddress,Ct as parseVersionString,mr as parseWithPositions,$t as pickHighestDocument,kr as propertiesInScope,Qr as resolveDisplayValue,br as resolvePropertyStep,V as sanitizeName,rt as saveLockFile,Ze as serverSupportsDPoP,g as subjectUri,Zt as tripleKey,R as uriKey,Xt as uriTriple,St as versionOperatorFromChar,Rt as versionOperatorToChar,vt as versionsEqual};
|
|
@@ -165,55 +165,26 @@ export declare class LookRenderer {
|
|
|
165
165
|
*/
|
|
166
166
|
private evaluateTier;
|
|
167
167
|
/**
|
|
168
|
-
*
|
|
168
|
+
* Evaluate a band path carrier — a `tx.Expression` (e.g. `metricPath`,
|
|
169
|
+
* `statPath`, `labelPath`) — against `node`, which is bound to the
|
|
170
|
+
* `input` variable. Returns the scalar text result, or undefined when
|
|
171
|
+
* the carrier is absent or evaluates to nothing. This is the structured,
|
|
172
|
+
* object-model-resolved replacement for the old `/`-separated path DSL:
|
|
173
|
+
* every property reference inside the expression resolves through the
|
|
174
|
+
* import closure and validates at `kanonak validate` time.
|
|
169
175
|
*
|
|
170
|
-
*
|
|
171
|
-
* `
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
*
|
|
180
|
-
*
|
|
181
|
-
|
|
182
|
-
private applyPlaceholders;
|
|
183
|
-
/**
|
|
184
|
-
* Whether a placeholder expression resolves to a non-empty value — the
|
|
185
|
-
* condition for an optional `{{#expr}}…{{/expr}}` section. Uses the same
|
|
186
|
-
* resolution as inline substitution (specials, delta/svg functions, property
|
|
187
|
-
* paths), so a section guards exactly what its inner `{{expr}}` would print.
|
|
188
|
-
*/
|
|
189
|
-
private placeholderResolves;
|
|
190
|
-
/**
|
|
191
|
-
* The change in a `/`-path metric vs the previous version of THIS
|
|
192
|
-
* resource (highest version below the current). Undefined when there is
|
|
193
|
-
* no prior version or the metric doesn't resolve on both.
|
|
194
|
-
*/
|
|
195
|
-
private metricDelta;
|
|
196
|
-
/**
|
|
197
|
-
* Resolve a `/`-separated property path starting from `instance`. Each
|
|
198
|
-
* step matches a statement by predicate local name (alias prefix in
|
|
199
|
-
* the step is ignored for readability — `wv.confidence` and
|
|
200
|
-
* `confidence` both match). Returns the final value as a string, or
|
|
201
|
-
* undefined when the path doesn't resolve.
|
|
202
|
-
*/
|
|
203
|
-
private resolvePath;
|
|
204
|
-
/**
|
|
205
|
-
* Walk a `/`-separated property path from `current`. At a reference step
|
|
206
|
-
* the target may carry the remaining property via an open-world
|
|
207
|
-
* augmentation merged onto a *specific* parsed version, so we try every
|
|
208
|
-
* version of the referenced resource and return the first that yields a
|
|
209
|
-
* value — same multi-version tolerance the look/SVG cascades use. Picking
|
|
210
|
-
* a single version (findResourceByUri) can land on an un-augmented copy.
|
|
211
|
-
*/
|
|
212
|
-
private resolvePathSteps;
|
|
213
|
-
/** All text values of a final-step statement: a reference → its display
|
|
214
|
-
* label; a literal → its value; a list → each member's text; an embedded →
|
|
215
|
-
* none (not text). Version-tolerant on reference labels. */
|
|
216
|
-
private finalStatementTexts;
|
|
176
|
+
* `fragment` is read off the band/spec/channel subject with
|
|
177
|
+
* `readEmbeddedCarrier`. A single field is a `tx.PropertyRead`; a
|
|
178
|
+
* reference step composes `tx.Traverse` with a nested `tx.PropertyRead`.
|
|
179
|
+
* Multi-valued properties join with ", " (matching the old DSL).
|
|
180
|
+
*/
|
|
181
|
+
private evaluateCarrier;
|
|
182
|
+
/** Numeric form of `evaluateCarrier` — NaN when absent or non-numeric. */
|
|
183
|
+
private evaluateCarrierNum;
|
|
184
|
+
/** Read a band path carrier (an embedded `tx.Expression`) off a subject
|
|
185
|
+
* by its property URI, or undefined when the property is absent or not
|
|
186
|
+
* an embedded value. */
|
|
187
|
+
private readEmbeddedCarrier;
|
|
217
188
|
/** A reference's display label, tolerant of open-world augmentations landing
|
|
218
189
|
* on a specific parsed version (tries every version, falls back to the URI
|
|
219
190
|
* name). */
|
|
@@ -238,7 +209,7 @@ export declare class LookRenderer {
|
|
|
238
209
|
/**
|
|
239
210
|
* Render the instance as body-only HTML using its cascaded look.
|
|
240
211
|
*/
|
|
241
|
-
renderHtml(instance: SubjectKanonak): string
|
|
212
|
+
renderHtml(instance: SubjectKanonak): Promise<string>;
|
|
242
213
|
/**
|
|
243
214
|
* Wrap a band's HTML in a float container when it declares `look.placement`
|
|
244
215
|
* (floatLeft / floatRight) so the FOLLOWING band's prose flows around it —
|
|
@@ -294,7 +265,7 @@ export declare class LookRenderer {
|
|
|
294
265
|
renderDocument(instance: SubjectKanonak, opts?: {
|
|
295
266
|
bareOverview?: boolean;
|
|
296
267
|
rootIndex?: boolean;
|
|
297
|
-
}): string
|
|
268
|
+
}): Promise<string>;
|
|
298
269
|
/**
|
|
299
270
|
* True if the instance's class chain declares a `derivation.derivations`
|
|
300
271
|
* binding whose `derivation.format` is `kanonak.org/formats/svg`. Used by
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { Version } from '@kanonak-protocol/types/document/models/types';
|
|
2
|
+
import type { IPackageProducer, ProduceResult, VersionRange } from './IPackageProducer.js';
|
|
3
|
+
/**
|
|
4
|
+
* The entitlement + metering seam for package producers. The SDK ships the
|
|
5
|
+
* *wrapper* and these *interfaces* with no-op defaults; the platform supplies
|
|
6
|
+
* the *policy* (e.g. Cedar/IAM), the *meter* (billing), and the credential /
|
|
7
|
+
* egress layer — none of which appear in the SDK. Composing
|
|
8
|
+
* {@link EntitlementProducer} around an {@link IPackageProducer} gates access
|
|
9
|
+
* to a produced package without changing the bare producer contract, so an
|
|
10
|
+
* in-process producer needs none of this.
|
|
11
|
+
*
|
|
12
|
+
* Invariant the wrapper preserves: it gates *access to* a deterministic
|
|
13
|
+
* artifact — it never parameterizes the artifact. The produced body stays a
|
|
14
|
+
* pure function of the address; the principal must not leak into the body or
|
|
15
|
+
* its content hash.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* The authenticated caller, resolved by the host from the inbound request's
|
|
19
|
+
* credential. Opaque to the SDK — the platform resolves it to its own
|
|
20
|
+
* principal model. `null` is an anonymous / unauthenticated caller.
|
|
21
|
+
*/
|
|
22
|
+
export type RequestPrincipal = Record<string, unknown>;
|
|
23
|
+
/** The request context threaded to the entitlement layer. */
|
|
24
|
+
export interface ProduceContext {
|
|
25
|
+
readonly principal: RequestPrincipal | null;
|
|
26
|
+
}
|
|
27
|
+
/** The address an entitlement decision is made about. `version` is absent at version-resolution time. */
|
|
28
|
+
export interface PackageAddress {
|
|
29
|
+
readonly publisher: string;
|
|
30
|
+
readonly package_: string;
|
|
31
|
+
readonly version?: Version;
|
|
32
|
+
}
|
|
33
|
+
/** A policy's verdict. A deny is fail-closed; `reason` is for diagnostics/audit. */
|
|
34
|
+
export interface EntitlementDecision {
|
|
35
|
+
readonly allowed: boolean;
|
|
36
|
+
readonly reason?: string;
|
|
37
|
+
}
|
|
38
|
+
/** Authorizes a caller for an address. The platform implements this (Cedar/IAM/…). */
|
|
39
|
+
export interface IEntitlementPolicy {
|
|
40
|
+
authorize(ctx: ProduceContext, address: PackageAddress): Promise<EntitlementDecision>;
|
|
41
|
+
}
|
|
42
|
+
/** Records a usage event for a produced package. The platform implements this (billing). */
|
|
43
|
+
export interface IMeter {
|
|
44
|
+
record(ctx: ProduceContext, address: PackageAddress, result: ProduceResult): Promise<void>;
|
|
45
|
+
}
|
|
46
|
+
/** Allow-all policy — the default when a host wires no entitlement. */
|
|
47
|
+
export declare const allowAllPolicy: IEntitlementPolicy;
|
|
48
|
+
/** No-op meter — the default when a host wires no metering. */
|
|
49
|
+
export declare const noopMeter: IMeter;
|
|
50
|
+
/** Thrown when a policy denies a caller. The origin maps this to 403 (or 404 to avoid disclosure). */
|
|
51
|
+
export declare class EntitlementDeniedError extends Error {
|
|
52
|
+
readonly address: PackageAddress;
|
|
53
|
+
readonly reason?: string | undefined;
|
|
54
|
+
constructor(address: PackageAddress, reason?: string | undefined);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Decorates an {@link IPackageProducer} so each `resolveVersion` / `produce`
|
|
58
|
+
* is authorized for the bound caller before the inner producer runs, and each
|
|
59
|
+
* `produce` is metered after. A denied call throws {@link EntitlementDeniedError}
|
|
60
|
+
* and never invokes the inner producer (fail-closed). One instance is bound to
|
|
61
|
+
* one request's {@link ProduceContext} — the host constructs it per request
|
|
62
|
+
* after resolving the caller's principal — so the principal stays out of the
|
|
63
|
+
* producer signature and out of the produced bytes.
|
|
64
|
+
*/
|
|
65
|
+
export declare class EntitlementProducer implements IPackageProducer {
|
|
66
|
+
private readonly inner;
|
|
67
|
+
private readonly ctx;
|
|
68
|
+
private readonly policy;
|
|
69
|
+
private readonly meter;
|
|
70
|
+
constructor(inner: IPackageProducer, ctx: ProduceContext, policy?: IEntitlementPolicy, meter?: IMeter);
|
|
71
|
+
canProduce(publisher: string, package_: string): boolean;
|
|
72
|
+
resolveVersion(publisher: string, package_: string, range: VersionRange): Promise<Version | null>;
|
|
73
|
+
produce(publisher: string, package_: string, version: Version): Promise<ProduceResult>;
|
|
74
|
+
private assertAllowed;
|
|
75
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { KanonakDocument } from '@kanonak-protocol/types/document/models/types';
|
|
2
|
+
import type { Version } from '@kanonak-protocol/types/document/models/types';
|
|
3
|
+
import type { VersionOperator } from '@kanonak-protocol/types/document/models/enums';
|
|
4
|
+
/**
|
|
5
|
+
* A version request a producer resolves: an operator and the version it
|
|
6
|
+
* qualifies (`= 1.2.0`, `^ 1.0.0`, `~ 1.1.0`, or `*` where the version is
|
|
7
|
+
* ignored). Deliberately minimal — decoupled from the parser's full `Import`
|
|
8
|
+
* — so a producer interprets only what it needs.
|
|
9
|
+
*/
|
|
10
|
+
export interface VersionRange {
|
|
11
|
+
operator: VersionOperator;
|
|
12
|
+
version: Version;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* What a producer hands back for one produced package: the parsed document,
|
|
16
|
+
* its canonical `.kan.yml` source text, and the source's UTF-8 byte size.
|
|
17
|
+
* `source` is what an HTTP origin serves verbatim (so a consumer that fetches
|
|
18
|
+
* raw YAML gets byte-identical content); `document` is what the resolution
|
|
19
|
+
* layer consumes; `byteCount` is captured here so a meter bills per-byte
|
|
20
|
+
* without re-serializing.
|
|
21
|
+
*/
|
|
22
|
+
export interface ProduceResult {
|
|
23
|
+
document: KanonakDocument;
|
|
24
|
+
source: string;
|
|
25
|
+
byteCount: number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* A package producer generates a valid Kanonak Package on demand for a URI it
|
|
29
|
+
* is authoritative for, instead of serving an authored, on-disk `.kan.yml`.
|
|
30
|
+
* It is the seam a data adapter (market data, DynamoDB, a SQL warehouse)
|
|
31
|
+
* implements: the SDK resolves a package through {@link IPackageProducer}
|
|
32
|
+
* exactly as it would through any repository, and the producer projects its
|
|
33
|
+
* external store into Kanonak form.
|
|
34
|
+
*
|
|
35
|
+
* Resolution is two steps so a range never forces enumeration of every
|
|
36
|
+
* version: {@link resolveVersion} answers "which concrete version does this
|
|
37
|
+
* range mean" (consulting the backend — e.g. the latest `updated_at` ordinal
|
|
38
|
+
* for `*`), and {@link produce} generates only that one. A producer typically
|
|
39
|
+
* builds its document with `PackageBuilder`.
|
|
40
|
+
*
|
|
41
|
+
* The contract carries no auth: entitlement and metering are layered as an
|
|
42
|
+
* injected decorator around a producer (see the package-producer design),
|
|
43
|
+
* so an in-process producer needs none. The produced body MUST be a pure
|
|
44
|
+
* function of `(publisher, package, version)` — the requesting principal may
|
|
45
|
+
* gate access and may appear in the address, but must never shape the bytes,
|
|
46
|
+
* or content-addressing, lockfiles, and caching break.
|
|
47
|
+
*/
|
|
48
|
+
export interface IPackageProducer {
|
|
49
|
+
/** Whether this producer is authoritative for `publisher/package`. */
|
|
50
|
+
canProduce(publisher: string, package_: string): boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Resolve a version range to the concrete version this producer would serve
|
|
53
|
+
* — the latest snapshot ordinal for `*`, an exact pin verbatim, the highest
|
|
54
|
+
* in range for `^`/`~`. Returns `null` when nothing satisfies the range.
|
|
55
|
+
*/
|
|
56
|
+
resolveVersion(publisher: string, package_: string, range: VersionRange): Promise<Version | null>;
|
|
57
|
+
/** Generate the package for a concrete, already-resolved version. */
|
|
58
|
+
produce(publisher: string, package_: string, version: Version): Promise<ProduceResult>;
|
|
59
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import type { IKanonakDocumentRepository } from '@kanonak-protocol/types/document/models';
|
|
2
|
+
import { KanonakParser } from '../parsing/KanonakParser.js';
|
|
3
|
+
import { KanonakObjectParser } from '../parsing/KanonakObjectParser.js';
|
|
4
|
+
import type { KanonakUri } from '../resolution/KanonakUri.js';
|
|
5
|
+
/**
|
|
6
|
+
* The producer-side toolkit for constructing a valid, canonical Kanonak
|
|
7
|
+
* Package document from data — the surface a package producer (an in-graph
|
|
8
|
+
* materializer, or an external data adapter) builds on instead of hand-
|
|
9
|
+
* rolling YAML and re-implementing the object model.
|
|
10
|
+
*
|
|
11
|
+
* It owns the four pieces every producer needs and must get right
|
|
12
|
+
* identically: import/alias bookkeeping ({@link ImportBook}), value
|
|
13
|
+
* serialization (literals vs. `alias.name` references, fail-loud on the
|
|
14
|
+
* unrepresentable), content-hash identity over the canonical (parsed) body,
|
|
15
|
+
* and a deterministic YAML dump. `ViewMaterializer` is its first client.
|
|
16
|
+
*
|
|
17
|
+
* Two assembly modes:
|
|
18
|
+
* - {@link buildContentAddressed} — a versionless, content-hashed package
|
|
19
|
+
* whose name is derived from the hash (`q-<hex16>`). For per-invocation /
|
|
20
|
+
* deterministic-query output.
|
|
21
|
+
* - {@link buildNamed} — an ordinary named, versioned package (e.g. a data
|
|
22
|
+
* adapter's `quotes-aapl@<epoch>.0.0` snapshot), optionally recording a
|
|
23
|
+
* `contentHash` for dedup.
|
|
24
|
+
*
|
|
25
|
+
* The SDK never reads the clock or invents identity; the caller supplies any
|
|
26
|
+
* provenance (`resolvedAt`, `id`) via `header`, and it lives outside the
|
|
27
|
+
* hashed body so two identical productions share a content hash.
|
|
28
|
+
*/
|
|
29
|
+
export declare class PackageBuilder {
|
|
30
|
+
private readonly repository;
|
|
31
|
+
private readonly parser;
|
|
32
|
+
private readonly objectParser;
|
|
33
|
+
/**
|
|
34
|
+
* @param repository resolution context for the body's import closure —
|
|
35
|
+
* the same role it plays for any parse; used to canonicalize the body
|
|
36
|
+
* when content-hashing.
|
|
37
|
+
* @param parser the shared Kanonak parser.
|
|
38
|
+
* @param objectParser optional reuse of an existing object parser.
|
|
39
|
+
*/
|
|
40
|
+
constructor(repository: IKanonakDocumentRepository, parser?: KanonakParser, objectParser?: KanonakObjectParser);
|
|
41
|
+
/** A fresh import/alias ledger to allocate references against while building the body. */
|
|
42
|
+
imports(): ImportBook;
|
|
43
|
+
/**
|
|
44
|
+
* Serialize one body value: primitives pass through; a `ReferenceKanonak`
|
|
45
|
+
* becomes an `alias.name` string (allocating the import via `book`); a list
|
|
46
|
+
* recurses. An embedded object or a bare unversioned URI is unrepresentable
|
|
47
|
+
* here and throws rather than silently dropping or guessing.
|
|
48
|
+
*/
|
|
49
|
+
serializeValue(value: unknown, book: ImportBook): unknown;
|
|
50
|
+
/**
|
|
51
|
+
* Assemble a versionless, content-addressed package. The body is hashed in
|
|
52
|
+
* canonical form (name-independent), the package name is derived from the
|
|
53
|
+
* hash, and `header` carries any out-of-body provenance.
|
|
54
|
+
*/
|
|
55
|
+
buildContentAddressed(args: {
|
|
56
|
+
publisher: string;
|
|
57
|
+
book: ImportBook;
|
|
58
|
+
body: Record<string, unknown>;
|
|
59
|
+
/** Extra header fields (e.g. `ck.contentHash`, `ck.resolvedAt`, `ck.id`). */
|
|
60
|
+
header?: Record<string, unknown>;
|
|
61
|
+
/** Property key under which to record the content hash (e.g. `ck.contentHash`). */
|
|
62
|
+
contentHashProperty?: string;
|
|
63
|
+
}): Promise<BuiltPackage>;
|
|
64
|
+
/**
|
|
65
|
+
* Assemble an ordinary named, versioned package — the mode a data adapter
|
|
66
|
+
* uses for a stable or snapshot-versioned artifact (`quotes-aapl@<epoch>.0.0`).
|
|
67
|
+
* Optionally records a `contentHash` for dedup; the package's identity is
|
|
68
|
+
* its `name@version`, not the hash.
|
|
69
|
+
*/
|
|
70
|
+
buildNamed(args: {
|
|
71
|
+
publisher: string;
|
|
72
|
+
name: string;
|
|
73
|
+
/** Version string, e.g. `1.0.0` or an epoch ordinal `1717000000000.0.0`. */
|
|
74
|
+
version: string;
|
|
75
|
+
book: ImportBook;
|
|
76
|
+
body: Record<string, unknown>;
|
|
77
|
+
type?: string;
|
|
78
|
+
header?: Record<string, unknown>;
|
|
79
|
+
/** Property key under which to record the content hash, if any. */
|
|
80
|
+
contentHashProperty?: string;
|
|
81
|
+
}): Promise<BuiltPackage>;
|
|
82
|
+
/** Deterministic YAML serialization of an assembled document. */
|
|
83
|
+
dump(doc: Record<string, unknown>): string;
|
|
84
|
+
/**
|
|
85
|
+
* Content hash of the body, independent of the package's own (possibly
|
|
86
|
+
* not-yet-assigned) name. Parses the body under a fixed probe header,
|
|
87
|
+
* neutralizes each body subject's namespace to a constant, and hashes the
|
|
88
|
+
* canonical form — so the same projected data always yields the same
|
|
89
|
+
* `sha256:` regardless of which package name it ends up under.
|
|
90
|
+
*/
|
|
91
|
+
hashBody(publisher: string, imports: unknown[], body: Record<string, unknown>): Promise<string>;
|
|
92
|
+
}
|
|
93
|
+
/** The result of assembling a package: the `.kan.yml` text plus its identity. */
|
|
94
|
+
export interface BuiltPackage {
|
|
95
|
+
/** The package as `.kan.yml` text. */
|
|
96
|
+
yaml: string;
|
|
97
|
+
/** UTF-8 byte length of `yaml` — the on-the-wire size, for metering. */
|
|
98
|
+
byteCount: number;
|
|
99
|
+
/** `sha256:` content hash of the body, when one was computed. */
|
|
100
|
+
contentHash?: string;
|
|
101
|
+
/** The package name (content-addressed `q-<hex16>` or the caller's name). */
|
|
102
|
+
packageName: string;
|
|
103
|
+
/** Publisher the package is minted under. */
|
|
104
|
+
publisher: string;
|
|
105
|
+
/** Number of body resources produced. */
|
|
106
|
+
resourceCount: number;
|
|
107
|
+
}
|
|
108
|
+
/** Address-safe package name (`q-<hex16>`) derived from a `sha256:` content hash. */
|
|
109
|
+
export declare function contentAddressedName(contentHash: string): string;
|
|
110
|
+
export interface ImportEntry {
|
|
111
|
+
publisher: string;
|
|
112
|
+
package_: string;
|
|
113
|
+
version: string;
|
|
114
|
+
alias: string;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Allocates import aliases and emits the package's `imports` block. Aliases
|
|
118
|
+
* are unique within the package; the same `publisher/package@version` reuses
|
|
119
|
+
* its alias. Holding this while building the body lets value serialization
|
|
120
|
+
* mint `alias.name` references that the emitted `imports` exactly covers.
|
|
121
|
+
*/
|
|
122
|
+
export declare class ImportBook {
|
|
123
|
+
private readonly byKey;
|
|
124
|
+
private readonly aliases;
|
|
125
|
+
ensure(publisher: string, package_: string, version: string, preferred: string): string;
|
|
126
|
+
ref(uri: KanonakUri): string;
|
|
127
|
+
toImports(): unknown[];
|
|
128
|
+
private uniqueAlias;
|
|
129
|
+
}
|
|
130
|
+
export declare function sanitizeName(raw: string): string;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { IKanonakDocumentRepository } from '@kanonak-protocol/types/document/models';
|
|
2
|
+
import type { KanonakDocument, Import, DocumentReference } from '@kanonak-protocol/types/document/models/types';
|
|
3
|
+
import type { IPackageProducer } from './IPackageProducer.js';
|
|
4
|
+
/**
|
|
5
|
+
* Composes one or more {@link IPackageProducer}s into the resolution chain as
|
|
6
|
+
* an ordinary read-only `IKanonakDocumentRepository` — the same shape
|
|
7
|
+
* `HttpKanonakDocumentRepository` realizes, so a producer drops into a
|
|
8
|
+
* `CompositeKanonakDocumentRepository`, `kanonak serve`, or any consumer
|
|
9
|
+
* without special-casing. `getHighestCompatibleVersionAsync` is
|
|
10
|
+
* `resolveVersion` then `produce`; writes throw (a producer is a source, not
|
|
11
|
+
* a store).
|
|
12
|
+
*
|
|
13
|
+
* Producers are tried in registration order; the first whose `canProduce`
|
|
14
|
+
* matches wins (explicit registration — a host wires its producers up front).
|
|
15
|
+
* Produced documents are deterministic per `(publisher, package, version)`,
|
|
16
|
+
* so they are cached by that key and never re-produced. The repository never
|
|
17
|
+
* enumerates a producer's version history (it would be unbounded for a
|
|
18
|
+
* snapshot feed): namespace/all-document queries return only what has already
|
|
19
|
+
* been produced this session.
|
|
20
|
+
*/
|
|
21
|
+
export declare class ProducerRepository implements IKanonakDocumentRepository {
|
|
22
|
+
private readonly producers;
|
|
23
|
+
private readonly produced;
|
|
24
|
+
constructor(producers: IPackageProducer[]);
|
|
25
|
+
private producerFor;
|
|
26
|
+
private produceCached;
|
|
27
|
+
getHighestCompatibleVersionAsync(publisher: string, import_: Import): Promise<KanonakDocument | null>;
|
|
28
|
+
/**
|
|
29
|
+
* Produce a specific package by identifier. A producer must be told which
|
|
30
|
+
* snapshot to make, so the identifier must carry a version
|
|
31
|
+
* (`publisher/package@version`); a versionless or non-package identifier
|
|
32
|
+
* returns `null` — callers resolve ranges through
|
|
33
|
+
* {@link getHighestCompatibleVersionAsync}, not here.
|
|
34
|
+
*/
|
|
35
|
+
getDocumentAsync(identifier: string): Promise<KanonakDocument | null>;
|
|
36
|
+
getDocumentsByNamespaceAsync(publisher: string, package_: string): Promise<KanonakDocument[]>;
|
|
37
|
+
getAllDocumentsAsync(): Promise<KanonakDocument[]>;
|
|
38
|
+
saveDocumentAsync(_document: KanonakDocument, _identifier: string): Promise<void>;
|
|
39
|
+
deleteDocumentAsync(_identifier: string): Promise<void>;
|
|
40
|
+
clearNamespaceAsync(_publisher: string, _package: string): Promise<void>;
|
|
41
|
+
getAllDocumentReferencesAsync(): Promise<DocumentReference[]>;
|
|
42
|
+
getDocumentContentAsync(_identifier: string): Promise<string | null>;
|
|
43
|
+
getDocumentUriAsync(_identifier: string): Promise<string | null>;
|
|
44
|
+
}
|