@kanonak-protocol/sdk 3.71.0 → 3.72.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-LKBG2MK6.js +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +26 -26
- 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/server/assembleModel.d.ts +2 -0
- package/dist/server/index.js +2 -2
- package/dist/server/types.d.ts +9 -0
- package/dist/view/ViewMaterializer.d.ts +1 -7
- package/package.json +2 -2
- package/dist/chunk-HAR3BNTB.js +0 -2
package/dist/browser.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as ge,b as fe,c as me,d as C,e as E,f as d}from"./chunk-Y7TGQ7UF.js";import{a as Qe}from"./chunk-F5ANO7MJ.js";import"./chunk-QHABFCRC.js";import{b as L,c as W,d as F}from"./chunk-
|
|
1
|
+
import{a as ge,b as fe,c as me,d as C,e as E,f as d}from"./chunk-Y7TGQ7UF.js";import{a as Qe}from"./chunk-F5ANO7MJ.js";import"./chunk-QHABFCRC.js";import{b as L,c as W,d as F}from"./chunk-LKBG2MK6.js";import{a as H}from"./chunk-4NO7MHS7.js";import{a as Pe,b as we,c as he}from"./chunk-GN2XODVC.js";import{a as ke,b as be}from"./chunk-PEUTCG3B.js";import"./chunk-PEJALHXK.js";import"./chunk-SC5M74NM.js";import{A as We,B as Fe,C as Ge,G as Xe,a as Ke,b as xe,c as Se,d as Re,f as De,g as Be,h as Ce,i as Ee,j as je,k as ve,l as _e,m as Ie,n as Ae,o as Te,p as Oe,q as Ve,r as $e,s as Ue,t as ze,u as Me,v as Ne,w as Je,x as He,y as qe,z as Le}from"./chunk-RRODBYIK.js";import"./chunk-SHDHMKMJ.js";import{a as Y,c as le,f as pe}from"./chunk-G2DKKSZ4.js";import{a as q}from"./chunk-TJPQETHV.js";import{a as ye}from"./chunk-BGQKZBNE.js";import"./chunk-CRKSKIAL.js";import{b as ue,c as de}from"./chunk-IOMNZBK4.js";import{a as G,b as X,c as Q,d as ee,e as re,f as te,g as ne,h as oe,i as se,j as ie,k as ae,l as ce}from"./chunk-W6T7MOKY.js";import{a as Z}from"./chunk-FUUTGGJS.js";import{c as O,d as V,e as $,f as U,g as z,h as M,i as N,j as J}from"./chunk-2ACBWC7K.js";var j="kanonak-credentials",u="credentials",Ye=1,f=class{async get(r){let e=d(r),t=await h();return new Promise((o,a)=>{let s=t.transaction(u,"readonly"),i=s.objectStore(u).get(e);i.onsuccess=()=>o(i.result??null),i.onerror=()=>a(new Error(`IndexedDB read failed for '${e}': ${i.error?.message}`)),s.oncomplete=()=>t.close()})}async store(r,e){let t=d(r),o=await h();return new Promise((a,s)=>{let l=o.transaction(u,"readwrite"),c=l.objectStore(u).put(e,t);c.onsuccess=()=>a(),c.onerror=()=>s(new Error(`IndexedDB write failed for '${t}': ${c.error?.message}`)),l.oncomplete=()=>o.close()})}async remove(r){let e=d(r),t=await h();return new Promise((o,a)=>{let s=t.transaction(u,"readwrite"),i=s.objectStore(u).delete(e);i.onsuccess=()=>o(),i.onerror=()=>a(new Error(`IndexedDB delete failed for '${e}': ${i.error?.message}`)),s.oncomplete=()=>t.close()})}async list(){let r=await h();return new Promise((e,t)=>{let o=r.transaction(u,"readonly"),s=o.objectStore(u).getAllKeys();s.onsuccess=()=>e(s.result??[]),s.onerror=()=>t(new Error(`IndexedDB list failed: ${s.error?.message}`)),o.oncomplete=()=>r.close()})}};function h(){return new Promise((n,r)=>{let e=indexedDB.open(j,Ye);e.onupgradeneeded=()=>{let t=e.result;t.objectStoreNames.contains(u)||t.createObjectStore(u)},e.onsuccess=()=>n(e.result),e.onerror=()=>r(new Error(`Failed to open IndexedDB '${j}': ${e.error?.message}
|
|
2
2
|
Credential storage requires IndexedDB support in your browser.`))})}async function _(){let n=await crypto.subtle.generateKey({name:"ECDSA",namedCurve:"P-256"},!1,["sign"]),r=await crypto.subtle.exportKey("jwk",n.publicKey);return{signingKey:n.privateKey,publicKeyJwk:r}}async function k(){let n=await crypto.subtle.generateKey({name:"ECDSA",namedCurve:"P-256"},!0,["sign"]),r=await crypto.subtle.exportKey("jwk",n.publicKey),e=await crypto.subtle.exportKey("jwk",n.privateKey);return{keys:{signingKey:n.privateKey,publicKeyJwk:r},dpopKeyPair:{publicKey:r,privateKey:e}}}async function b(n){return{signingKey:await crypto.subtle.importKey("jwk",n.privateKey,{name:"ECDSA",namedCurve:"P-256"},!1,["sign"]),publicKeyJwk:n.publicKey}}async function K(n,r,e,t,o){let a={alg:"ES256",typ:"dpop+jwt",jwk:{kty:n.publicKeyJwk.kty,crv:n.publicKeyJwk.crv,x:n.publicKeyJwk.x,y:n.publicKeyJwk.y}},s={jti:crypto.randomUUID(),htm:r.toUpperCase(),htu:e,iat:Math.floor(Date.now()/1e3)};return t&&(s.ath=await er(t)),o&&(s.nonce=o),await Ze(a,s,n.signingKey)}function x(n){return!n||n.length===0?!1:n.some(r=>r.toUpperCase()==="ES256")}async function Ze(n,r,e){let t=v(JSON.stringify(n)),o=v(JSON.stringify(r)),a=new TextEncoder().encode(`${t}.${o}`),s=await crypto.subtle.sign({name:"ECDSA",hash:"SHA-256"},e,a),l=D(s);return`${t}.${o}.${l}`}async function er(n){let r=new TextEncoder().encode(n),e=await crypto.subtle.digest("SHA-256",r);return D(e)}function v(n){let r=new TextEncoder().encode(n);return D(r.buffer)}function D(n){let r=new Uint8Array(n),e="";for(let t=0;t<r.length;t++)e+=String.fromCharCode(r[t]);return btoa(e).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}var rr=300*1e3,S=class{credentialBackend;callbackUrl;constructor(r){this.credentialBackend=new f,this.callbackUrl=r??`${window.location.origin}/browser/callback.html`}async authorize(r){let e=d(r),t=await this.discover(e);if(!t)return{success:!1,error:`No OAuth discovery endpoint found for '${e}'.`};if(!t.authorizationEndpoint||!t.tokenEndpoint)return{success:!1,error:`OAuth metadata incomplete for '${e}'.`};let o=x(t.dpopSigningAlgValuesSupported),a=null,s=null;if(o){let g=await k();a=g.keys,s=g.dpopKeyPair}let l=await this.credentialBackend.get(e),i=l?.clientId??null,c=l?.clientSecret??null;if(!i&&t.registrationEndpoint){let g=await this.registerClient(t.registrationEndpoint);if(!g)return{success:!1,error:`Dynamic client registration failed for '${e}'.`};i=g.clientId,c=g.clientSecret??null}if(!i)return{success:!1,error:`No OAuth client credentials for '${e}'.`};let m=tr(),p=await nr(m),R=or(),A=sr(t.authorizationEndpoint,i,this.callbackUrl,R,p),y=await this.openAuthPopup(A,R);if(!y)return{success:!1,error:"Authorization timed out or was cancelled."};if(y.error)return{success:!1,error:`Authorization failed: ${y.error}`};if(!y.code)return{success:!1,error:"No authorization code received."};if(y.state!==R)return{success:!1,error:"State mismatch \u2014 possible CSRF attack."};let P=await this.exchangeCode(t.tokenEndpoint,i,c,y.code,this.callbackUrl,m,a);if(!P)return{success:!1,error:"Token exchange failed."};let T={clientId:i,clientSecret:c,accessToken:P.accessToken??null,refreshToken:P.refreshToken??null,expiresAt:P.expiresIn?new Date(Date.now()+P.expiresIn*1e3).toISOString():null,tokenEndpoint:t.tokenEndpoint,dpopKeyPair:s};return await this.credentialBackend.store(e,T),{success:!0,host:e}}async getCredentialWithKeys(r){let e=await this.credentialBackend.get(r);if(!e)return null;let t=null;return e.dpopKeyPair&&(t=await b(e.dpopKeyPair)),{credential:e,dpopKeys:t}}async logout(r){let e=d(r);return await this.credentialBackend.remove(e),{success:!0,host:e}}async listAuthenticated(){return this.credentialBackend.list()}async discover(r){for(let e of[`https://${r}/.well-known/oauth-authorization-server`,`https://${r}/.well-known/openid-configuration`])try{let t=await fetch(e);if(!t.ok)continue;let o=await t.json();return{issuer:w(o.issuer),authorizationEndpoint:w(o.authorization_endpoint),tokenEndpoint:w(o.token_endpoint),registrationEndpoint:w(o.registration_endpoint),revocationEndpoint:w(o.revocation_endpoint),dpopSigningAlgValuesSupported:I(o.dpop_signing_alg_values_supported),codeChallengeMethodsSupported:I(o.code_challenge_methods_supported)}}catch{continue}return null}async registerClient(r){try{let e=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({client_name:"Kanonak Browser",redirect_uris:[this.callbackUrl],grant_types:["authorization_code","refresh_token"],response_types:["code"],token_endpoint_auth_method:"none"})});if(!e.ok)return null;let t=await e.json(),o=t.client_id;return o?{clientId:o,clientSecret:t.client_secret}:null}catch{return null}}openAuthPopup(r,e){return new Promise(t=>{let o=window.open(r,"kanonak-auth","width=500,height=700,menubar=no,toolbar=no,location=yes,status=no");if(!o){t(null);return}let a=setTimeout(()=>{i(),t(null)},rr),s=c=>{c.origin===window.location.origin&&(!c.data||c.data.type!=="kanonak-auth-callback"||(i(),t({code:c.data.code??void 0,state:c.data.state??void 0,error:c.data.error??void 0})))},l=setInterval(()=>{o.closed&&(i(),t(null))},500),i=()=>{clearTimeout(a),clearInterval(l),window.removeEventListener("message",s);try{o.close()}catch{}};window.addEventListener("message",s)})}async exchangeCode(r,e,t,o,a,s,l){let i=new URLSearchParams({grant_type:"authorization_code",client_id:e,code:o,redirect_uri:a,code_verifier:s});t&&i.set("client_secret",t);let c={"Content-Type":"application/x-www-form-urlencoded"};l&&(c.DPoP=await K(l,"POST",r));try{let m=await fetch(r,{method:"POST",headers:c,body:i.toString()});if(!m.ok)return null;let p=await m.json();return{accessToken:p.access_token,refreshToken:p.refresh_token,expiresIn:typeof p.expires_in=="number"?p.expires_in:void 0}}catch{return null}}};function tr(){let n=new Uint8Array(32);return crypto.getRandomValues(n),B(n.buffer)}async function nr(n){let r=new TextEncoder().encode(n),e=await crypto.subtle.digest("SHA-256",r);return B(e)}function or(){let n=new Uint8Array(16);return crypto.getRandomValues(n),B(n.buffer)}function sr(n,r,e,t,o){let a=new URLSearchParams({client_id:r,response_type:"code",redirect_uri:e,state:t,code_challenge:o,code_challenge_method:"S256"});return`${n}?${a}`}function B(n){let r=new Uint8Array(n),e="";for(let t=0;t<r.length;t++)e+=String.fromCharCode(r[t]);return btoa(e).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function w(n){return typeof n=="string"?n:null}function I(n){return Array.isArray(n)?n.filter(r=>typeof r=="string"):null}export{Ne as AmbiguousReferenceRule,se as BooleanStatement,f as BrowserCredentialBackend,S as BrowserOAuthFlow,Fe as ClassDefinitionRule,Ie as ClassHierarchyCycleRule,X as DefinedKanonak,ze as DefinitionPropertyReferenceRule,fe as EdgeType,Y as EmbeddedKanonak,je as EmbeddedKanonakTypeRule,ae as EmbeddedStatement,me as GraphBuilder,F as HttpKanonakDocumentRepository,ve as ImportExistenceRule,H as InMemoryKanonakDocumentRepository,Ue as InstancePropertyReferenceRule,G as Kanonak,we as KanonakDocumentPositions,pe as KanonakObjectParser,Xe as KanonakObjectValidator,q as KanonakParser,Z as KanonakUri,ke as KanonakUriBuilder,ce as ListStatement,Ge as MarkdownLinkRule,le as MarkdownStatement,$e as NamespaceImportCycleRule,De as NamespacePrefixRule,ge as NodeType,oe as NumberStatement,He as ObjectPropertyImportRule,qe as ObjectPropertyValueValidationRule,Se as OntologyValidationError,Ke as OntologyValidationResult,Le as PropertyDomainRule,Ae as PropertyHierarchyCycleRule,Pe as PropertyMetadata,Je as PropertyRangeReferenceRule,Te as PropertyRangeRequiredRule,Ce as PropertyTypeSpecificityRule,We as PropertyValueTypeRule,L as PublisherConfigResolver,W as PublisherIndex,ee as ReferenceKanonak,ie as ReferenceStatement,Be as ResourceNamingRule,ue as ResourceResolver,ye as ResourceTypeClassifier,te as ScalarStatement,re as Statement,ne as StringStatement,Oe as SubClassOfReferenceRule,Ve as SubPropertyOfReferenceRule,Q as SubjectKanonak,Ee as SubjectKanonakTypeRequiredRule,de as TypeResolver,_e as UnresolvedReferenceRule,Re as ValidationContext,xe as ValidationSeverity,Me as XsdImportRule,x as browserServerSupportsDPoP,O as compareVersions,K as createBrowserDPoPProof,U as createVersion,Qe as findDerivation,be as findInstancesByType,$ as formatVersion,k as generateBrowserDPoPKeyPair,_ as generateBrowserDPoPKeys,E as hasValidToken,b as importDPoPKeys,M as isCompatibleVersion,C as isExpired,N as isMajorCompatible,d as normalizeHost,z as parseVersionString,he as parseWithPositions,J as pickHighestDocument,V as versionsEqual};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{d as v}from"./chunk-HAR3BNTB.js";import{a as A}from"./chunk-4NO7MHS7.js";import{a as f}from"./chunk-TJPQETHV.js";import{c as w,d as I,h as R,i as F}from"./chunk-2ACBWC7K.js";import*as i from"fs/promises";import*as c from"path";import{pathToFileURL as b}from"url";import{VersionOperator as P}from"@kanonak-protocol/types/document/models/enums";var y=class{rootPath;recursive;parser;documentCache;filePathsByIdentifier;cacheInitialized=!1;cacheInitPromise=null;parsingErrors=new Map;constructor(e,t=!0,n){if(!e||e.trim().length===0)throw new Error("Root path cannot be null or empty");this.rootPath=c.resolve(e),this.recursive=t,this.parser=n??new f,this.documentCache=new Map,this.filePathsByIdentifier=new Map}async getAllDocumentsAsync(){await this.ensureCacheInitialized();let e=new Set(this.documentCache.values());return Array.from(e)}async getDocumentAsync(e){await this.ensureCacheInitialized();let t=this.documentCache.get(e);if(t)return t;let n=c.join(this.rootPath,e);if(t=this.documentCache.get(n),t)return t;for(let o of[".kan.yml",".yml",".yaml"])if(!e.endsWith(o)){let s=e+o;if(t=this.documentCache.get(s),t)return t;let a=c.join(this.rootPath,s);if(t=this.documentCache.get(a),t)return t}return null}async getDocumentsByNamespaceAsync(e,t){await this.ensureCacheInitialized();let n=new Set(this.documentCache.values());return Array.from(n).filter(o=>o.metadata.namespace_?.publisher===e&&o.metadata.namespace_?.package_===t)}async getHighestCompatibleVersionAsync(e,t){await this.ensureCacheInitialized();let n=new Set(this.documentCache.values()),o=Array.from(n).filter(a=>a.metadata?.namespace_?.publisher===e&&a.metadata?.namespace_?.package_===t.packageName&&a.metadata?.namespace_?.version!==void 0);if(o.length===0)return null;let s=o.filter(a=>{let r=a.metadata.namespace_.version;switch(t.versionOperator){case P.Exact:return I(r,t.version);case P.Compatible:return R(r,t.version);case P.Major:return F(r,t.version);case P.Any:return w(r,t.minVersion)>=0;default:return!1}});return s.length===0?null:(s.sort((a,r)=>{let m=a.metadata.namespace_.version,l=r.metadata.namespace_.version;return w(l,m)}),s[0])}async saveDocumentAsync(e,t){let n,o=e.metadata.namespace_?.toString();if(o&&o.includes("@")&&o.includes("/")){let m=o.split("/"),l=m[0],p=m[1].replace("@","@")+".kan.yml";n=c.join(this.rootPath,l,p)}else n=c.join(this.rootPath,t),!n.endsWith(".yml")&&!n.endsWith(".yaml")&&!n.endsWith(".kan.yml")&&(n+=".kan.yml");let s=c.dirname(n);await i.mkdir(s,{recursive:!0});let a=this.parser.save(e);await i.writeFile(n,a,"utf8"),o&&this.documentCache.set(o,e),this.documentCache.set(n,e);let r=c.relative(this.rootPath,n);this.documentCache.set(r,e)}async deleteDocumentAsync(e){let t=await this.getDocumentAsync(e);if(!t)return;let n=this.filePathsByIdentifier.get(e);if(!n)return;try{await i.unlink(n)}catch{}let o=t.metadata.namespace_?.toString();o&&this.documentCache.delete(o),this.documentCache.delete(e),this.documentCache.delete(n);let s=c.relative(this.rootPath,n);this.documentCache.delete(s)}async clearNamespaceAsync(e,t){await this.ensureCacheInitialized();let n=[];for(let[s,a]of this.documentCache.entries()){let r=a.metadata.namespace_?.toString()||"";r.includes(e)&&r.includes(t)&&n.push([s,a])}let o=c.join(this.rootPath,e);try{let s=await i.readdir(o);for(let a of s)a.includes(t)&&a.endsWith(".kan.yml")&&await i.unlink(c.join(o,a))}catch{}for(let[s]of n)this.documentCache.delete(s)}async getAllDocumentReferencesAsync(){await this.ensureCacheInitialized();let e=new Set(this.filePathsByIdentifier.values()),t=[];for(let n of e){let o=b(n).toString(),s;for(let[m,l]of this.documentCache.entries())if(this.filePathsByIdentifier.get(m)===n&&l.metadata.namespace_){s=l.metadata.namespace_.toString();break}let a=s??c.relative(this.rootPath,n),r=this.parsingErrors.has(n);t.push({identifier:a,uri:o,hasParseError:r})}return t}async getDocumentContentAsync(e){await this.ensureCacheInitialized();let t=this.filePathsByIdentifier.get(e);if(!t)try{await i.access(e),t=e}catch{let n=c.join(this.rootPath,e);try{await i.access(n),t=n}catch{return null}}try{return await i.readFile(t,"utf8")}catch{return null}}async getDocumentUriAsync(e){await this.ensureCacheInitialized();let t=this.filePathsByIdentifier.get(e);if(!t)try{await i.access(e),t=e}catch{let n=c.join(this.rootPath,e);try{await i.access(n),t=n}catch{return null}}return b(t).toString()}async refreshAsync(){this.documentCache.clear(),this.filePathsByIdentifier.clear(),this.parsingErrors.clear(),this.cacheInitialized=!1,this.cacheInitPromise=null,await this.ensureCacheInitialized()}async ensureCacheInitialized(){if(!this.cacheInitialized){if(this.cacheInitPromise){await this.cacheInitPromise;return}this.cacheInitPromise=this.loadDocuments(),await this.cacheInitPromise,this.cacheInitialized=!0}}async loadDocuments(){try{await i.mkdir(this.rootPath,{recursive:!0})}catch{}let t=(await this.findYamlFiles(this.rootPath,this.recursive)).map(async o=>{try{let s=await i.readFile(o,"utf8"),a=this.parser.parse(s);return{filePath:o,document:a,error:null}}catch(s){return{filePath:o,document:null,error:s instanceof Error?s.message:String(s)}}}),n=await Promise.all(t);for(let{filePath:o,document:s,error:a}of n){let r=c.relative(this.rootPath,o);if(s&&s.metadata.namespace_){let m=s.metadata.namespace_.toString();this.documentCache.set(m,s),this.documentCache.set(o,s),this.documentCache.set(r,s),this.filePathsByIdentifier.set(m,o),this.filePathsByIdentifier.set(o,o),this.filePathsByIdentifier.set(r,o)}else this.filePathsByIdentifier.set(o,o),this.filePathsByIdentifier.set(r,o);a&&this.parsingErrors.set(o,a)}}async findYamlFiles(e,t){let n=[];try{let o=await i.readdir(e,{withFileTypes:!0});for(let s of o){let a=c.join(e,s.name);if(s.isDirectory()&&t){let r=await this.findYamlFiles(a,t);n.push(...r)}else s.isFile()&&s.name.endsWith(".kan.yml")&&n.push(a)}}catch{}return n}};import*as d from"fs";var S=(n=>(n.NotFound="NotFound",n.Workspace="Workspace",n.Cache="Cache",n))(S||{}),k=class{cache;workspace;constructor(e,t,n){let o=n??new f;d.existsSync(e)||d.mkdirSync(e,{recursive:!0}),d.existsSync(t)||d.mkdirSync(t,{recursive:!0}),this.cache=new y(e,!0,o),this.workspace=new y(t,!0,o)}getCache(){return this.cache}getWorkspace(){return this.workspace}async getAllDocumentsAsync(){let e=await this.workspace.getAllDocumentsAsync(),t=await this.cache.getAllDocumentsAsync(),n=new Map;for(let o of t)if(o.metadata.namespace_){let s=o.metadata.namespace_.toString();n.set(s,o)}for(let o of e)if(o.metadata.namespace_){let s=o.metadata.namespace_.toString();n.set(s,o)}return Array.from(n.values())}async getDocumentAsync(e){let t=await this.workspace.getDocumentAsync(e);return t||await this.cache.getDocumentAsync(e)}async getDocumentsByNamespaceAsync(e,t){let n=await this.workspace.getDocumentsByNamespaceAsync(e,t),o=await this.cache.getDocumentsByNamespaceAsync(e,t),s=new Map;for(let a of o)if(a.metadata.namespace_?.version){let r=a.metadata.namespace_.version.toString();s.set(r,a)}for(let a of n)if(a.metadata.namespace_?.version){let r=a.metadata.namespace_.version.toString();s.set(r,a)}return Array.from(s.values())}async getHighestCompatibleVersionAsync(e,t){let n=await this.workspace.getHighestCompatibleVersionAsync(e,t);return n||await this.cache.getHighestCompatibleVersionAsync(e,t)}async saveDocumentAsync(e,t){await this.workspace.saveDocumentAsync(e,t)}async saveToCacheAsync(e,t){await this.cache.saveDocumentAsync(e,t)}async deleteDocumentAsync(e){await this.workspace.deleteDocumentAsync(e)}async clearNamespaceAsync(e,t){await this.workspace.clearNamespaceAsync(e,t)}async getAllDocumentReferencesAsync(){let e=await this.workspace.getAllDocumentReferencesAsync(),t=await this.cache.getAllDocumentReferencesAsync(),n=[];return n.push(...e),n.push(...t),n}async getDocumentContentAsync(e){let t=await this.workspace.getDocumentContentAsync(e);return t||await this.cache.getDocumentContentAsync(e)}async getDocumentUriAsync(e){let t=await this.workspace.getDocumentUriAsync(e);return t||await this.cache.getDocumentUriAsync(e)}async getDocumentLocationAsync(e){return await this.workspace.getDocumentAsync(e)?"Workspace":await this.cache.getDocumentAsync(e)?"Cache":"NotFound"}};import{homedir as _}from"os";import{join as N}from"path";function g(){let u=process.env.KANONAK_PACKAGE_CACHE;return u||N(_(),".kanonak","packages")}var C=class u{static createComposite(e,t,n){let o=e??g(),s=t??".";return new k(o,s,n)}static createFromEnvironment(e){let t=g(),n=process.env.KANONAK_WORKSPACE_PATH??".";return u.createComposite(t,n,e)}};var D=class{repos;constructor(...e){this.repos=e}async getHighestCompatibleVersionAsync(e,t){for(let n of this.repos)try{let o=await n.getHighestCompatibleVersionAsync(e,t);if(o)return o}catch{}return null}async getAllDocumentsAsync(){let e=[],t=new Set;for(let n of this.repos)try{for(let o of await n.getAllDocumentsAsync()){let s=o.metadata?.namespace_,a=s?s.version?`${s.publisher}/${s.package_}@${s.version.major}.${s.version.minor}.${s.version.patch}`:`${s.publisher}/${s.package_}`:void 0;if(a!==void 0){if(t.has(a))continue;t.add(a)}e.push(o)}}catch{}return e}async getDocumentAsync(e){for(let t of this.repos)try{let n=await t.getDocumentAsync(e);if(n)return n}catch{}return null}async getDocumentsByNamespaceAsync(e,t){for(let n of this.repos)try{let o=await n.getDocumentsByNamespaceAsync(e,t);if(o.length>0)return o}catch{}return[]}async saveDocumentAsync(e,t){await this.repos[0].saveDocumentAsync(e,t)}async deleteDocumentAsync(e){await this.repos[0].deleteDocumentAsync(e)}async clearNamespaceAsync(e,t){await this.repos[0].clearNamespaceAsync(e,t)}async getAllDocumentReferencesAsync(){return this.repos[0].getAllDocumentReferencesAsync()}async getDocumentContentAsync(e){for(let t of this.repos)try{let n=await t.getDocumentContentAsync(e);if(n)return n}catch{}return null}async getDocumentUriAsync(e){for(let t of this.repos)try{let n=await t.getDocumentUriAsync(e);if(n)return n}catch{}return null}};import{readFileSync as B,readdirSync as H}from"fs";import{join as x}from"path";var $=new Set(["node_modules",".kanonak",".git","_site","build",".stage"]);function K(u,e=[]){for(let t of H(u,{withFileTypes:!0}))t.isDirectory()?$.has(t.name)||K(x(u,t.name),e):t.name.endsWith(".kan.yml")&&e.push(x(u,t.name));return e}async function j(u,e=new f,t={}){let n=new A(e);for(let m of K(u))try{let l=e.parse(B(m,"utf-8")),h=l.metadata?.namespace_,p=h?.version;h&&p&&await n.saveDocumentAsync(l,`${h.publisher}/${h.package_}@${p.major}.${p.minor}.${p.patch}`)}catch{}let o=new y(g(),!0,e),s=new Map,a=t.httpCache??{getFromCache:(m,l,h)=>s.get(`${m}|${l}|${h}`)??null,onFetch:(m,l,h,p)=>{s.set(`${m}|${l}|${h}`,p)}},r=new v({getFromCache:a.getFromCache,onFetch:a.onFetch});return new D(n,o,r)}export{y as a,S as b,k as c,g as d,C as e,D as f,K as g,j as h};
|
|
1
|
+
import{d as v}from"./chunk-LKBG2MK6.js";import{a as A}from"./chunk-4NO7MHS7.js";import{a as f}from"./chunk-TJPQETHV.js";import{c as w,d as I,h as R,i as F}from"./chunk-2ACBWC7K.js";import*as i from"fs/promises";import*as c from"path";import{pathToFileURL as b}from"url";import{VersionOperator as P}from"@kanonak-protocol/types/document/models/enums";var y=class{rootPath;recursive;parser;documentCache;filePathsByIdentifier;cacheInitialized=!1;cacheInitPromise=null;parsingErrors=new Map;constructor(e,t=!0,n){if(!e||e.trim().length===0)throw new Error("Root path cannot be null or empty");this.rootPath=c.resolve(e),this.recursive=t,this.parser=n??new f,this.documentCache=new Map,this.filePathsByIdentifier=new Map}async getAllDocumentsAsync(){await this.ensureCacheInitialized();let e=new Set(this.documentCache.values());return Array.from(e)}async getDocumentAsync(e){await this.ensureCacheInitialized();let t=this.documentCache.get(e);if(t)return t;let n=c.join(this.rootPath,e);if(t=this.documentCache.get(n),t)return t;for(let o of[".kan.yml",".yml",".yaml"])if(!e.endsWith(o)){let s=e+o;if(t=this.documentCache.get(s),t)return t;let a=c.join(this.rootPath,s);if(t=this.documentCache.get(a),t)return t}return null}async getDocumentsByNamespaceAsync(e,t){await this.ensureCacheInitialized();let n=new Set(this.documentCache.values());return Array.from(n).filter(o=>o.metadata.namespace_?.publisher===e&&o.metadata.namespace_?.package_===t)}async getHighestCompatibleVersionAsync(e,t){await this.ensureCacheInitialized();let n=new Set(this.documentCache.values()),o=Array.from(n).filter(a=>a.metadata?.namespace_?.publisher===e&&a.metadata?.namespace_?.package_===t.packageName&&a.metadata?.namespace_?.version!==void 0);if(o.length===0)return null;let s=o.filter(a=>{let r=a.metadata.namespace_.version;switch(t.versionOperator){case P.Exact:return I(r,t.version);case P.Compatible:return R(r,t.version);case P.Major:return F(r,t.version);case P.Any:return w(r,t.minVersion)>=0;default:return!1}});return s.length===0?null:(s.sort((a,r)=>{let m=a.metadata.namespace_.version,l=r.metadata.namespace_.version;return w(l,m)}),s[0])}async saveDocumentAsync(e,t){let n,o=e.metadata.namespace_?.toString();if(o&&o.includes("@")&&o.includes("/")){let m=o.split("/"),l=m[0],p=m[1].replace("@","@")+".kan.yml";n=c.join(this.rootPath,l,p)}else n=c.join(this.rootPath,t),!n.endsWith(".yml")&&!n.endsWith(".yaml")&&!n.endsWith(".kan.yml")&&(n+=".kan.yml");let s=c.dirname(n);await i.mkdir(s,{recursive:!0});let a=this.parser.save(e);await i.writeFile(n,a,"utf8"),o&&this.documentCache.set(o,e),this.documentCache.set(n,e);let r=c.relative(this.rootPath,n);this.documentCache.set(r,e)}async deleteDocumentAsync(e){let t=await this.getDocumentAsync(e);if(!t)return;let n=this.filePathsByIdentifier.get(e);if(!n)return;try{await i.unlink(n)}catch{}let o=t.metadata.namespace_?.toString();o&&this.documentCache.delete(o),this.documentCache.delete(e),this.documentCache.delete(n);let s=c.relative(this.rootPath,n);this.documentCache.delete(s)}async clearNamespaceAsync(e,t){await this.ensureCacheInitialized();let n=[];for(let[s,a]of this.documentCache.entries()){let r=a.metadata.namespace_?.toString()||"";r.includes(e)&&r.includes(t)&&n.push([s,a])}let o=c.join(this.rootPath,e);try{let s=await i.readdir(o);for(let a of s)a.includes(t)&&a.endsWith(".kan.yml")&&await i.unlink(c.join(o,a))}catch{}for(let[s]of n)this.documentCache.delete(s)}async getAllDocumentReferencesAsync(){await this.ensureCacheInitialized();let e=new Set(this.filePathsByIdentifier.values()),t=[];for(let n of e){let o=b(n).toString(),s;for(let[m,l]of this.documentCache.entries())if(this.filePathsByIdentifier.get(m)===n&&l.metadata.namespace_){s=l.metadata.namespace_.toString();break}let a=s??c.relative(this.rootPath,n),r=this.parsingErrors.has(n);t.push({identifier:a,uri:o,hasParseError:r})}return t}async getDocumentContentAsync(e){await this.ensureCacheInitialized();let t=this.filePathsByIdentifier.get(e);if(!t)try{await i.access(e),t=e}catch{let n=c.join(this.rootPath,e);try{await i.access(n),t=n}catch{return null}}try{return await i.readFile(t,"utf8")}catch{return null}}async getDocumentUriAsync(e){await this.ensureCacheInitialized();let t=this.filePathsByIdentifier.get(e);if(!t)try{await i.access(e),t=e}catch{let n=c.join(this.rootPath,e);try{await i.access(n),t=n}catch{return null}}return b(t).toString()}async refreshAsync(){this.documentCache.clear(),this.filePathsByIdentifier.clear(),this.parsingErrors.clear(),this.cacheInitialized=!1,this.cacheInitPromise=null,await this.ensureCacheInitialized()}async ensureCacheInitialized(){if(!this.cacheInitialized){if(this.cacheInitPromise){await this.cacheInitPromise;return}this.cacheInitPromise=this.loadDocuments(),await this.cacheInitPromise,this.cacheInitialized=!0}}async loadDocuments(){try{await i.mkdir(this.rootPath,{recursive:!0})}catch{}let t=(await this.findYamlFiles(this.rootPath,this.recursive)).map(async o=>{try{let s=await i.readFile(o,"utf8"),a=this.parser.parse(s);return{filePath:o,document:a,error:null}}catch(s){return{filePath:o,document:null,error:s instanceof Error?s.message:String(s)}}}),n=await Promise.all(t);for(let{filePath:o,document:s,error:a}of n){let r=c.relative(this.rootPath,o);if(s&&s.metadata.namespace_){let m=s.metadata.namespace_.toString();this.documentCache.set(m,s),this.documentCache.set(o,s),this.documentCache.set(r,s),this.filePathsByIdentifier.set(m,o),this.filePathsByIdentifier.set(o,o),this.filePathsByIdentifier.set(r,o)}else this.filePathsByIdentifier.set(o,o),this.filePathsByIdentifier.set(r,o);a&&this.parsingErrors.set(o,a)}}async findYamlFiles(e,t){let n=[];try{let o=await i.readdir(e,{withFileTypes:!0});for(let s of o){let a=c.join(e,s.name);if(s.isDirectory()&&t){let r=await this.findYamlFiles(a,t);n.push(...r)}else s.isFile()&&s.name.endsWith(".kan.yml")&&n.push(a)}}catch{}return n}};import*as d from"fs";var S=(n=>(n.NotFound="NotFound",n.Workspace="Workspace",n.Cache="Cache",n))(S||{}),k=class{cache;workspace;constructor(e,t,n){let o=n??new f;d.existsSync(e)||d.mkdirSync(e,{recursive:!0}),d.existsSync(t)||d.mkdirSync(t,{recursive:!0}),this.cache=new y(e,!0,o),this.workspace=new y(t,!0,o)}getCache(){return this.cache}getWorkspace(){return this.workspace}async getAllDocumentsAsync(){let e=await this.workspace.getAllDocumentsAsync(),t=await this.cache.getAllDocumentsAsync(),n=new Map;for(let o of t)if(o.metadata.namespace_){let s=o.metadata.namespace_.toString();n.set(s,o)}for(let o of e)if(o.metadata.namespace_){let s=o.metadata.namespace_.toString();n.set(s,o)}return Array.from(n.values())}async getDocumentAsync(e){let t=await this.workspace.getDocumentAsync(e);return t||await this.cache.getDocumentAsync(e)}async getDocumentsByNamespaceAsync(e,t){let n=await this.workspace.getDocumentsByNamespaceAsync(e,t),o=await this.cache.getDocumentsByNamespaceAsync(e,t),s=new Map;for(let a of o)if(a.metadata.namespace_?.version){let r=a.metadata.namespace_.version.toString();s.set(r,a)}for(let a of n)if(a.metadata.namespace_?.version){let r=a.metadata.namespace_.version.toString();s.set(r,a)}return Array.from(s.values())}async getHighestCompatibleVersionAsync(e,t){let n=await this.workspace.getHighestCompatibleVersionAsync(e,t);return n||await this.cache.getHighestCompatibleVersionAsync(e,t)}async saveDocumentAsync(e,t){await this.workspace.saveDocumentAsync(e,t)}async saveToCacheAsync(e,t){await this.cache.saveDocumentAsync(e,t)}async deleteDocumentAsync(e){await this.workspace.deleteDocumentAsync(e)}async clearNamespaceAsync(e,t){await this.workspace.clearNamespaceAsync(e,t)}async getAllDocumentReferencesAsync(){let e=await this.workspace.getAllDocumentReferencesAsync(),t=await this.cache.getAllDocumentReferencesAsync(),n=[];return n.push(...e),n.push(...t),n}async getDocumentContentAsync(e){let t=await this.workspace.getDocumentContentAsync(e);return t||await this.cache.getDocumentContentAsync(e)}async getDocumentUriAsync(e){let t=await this.workspace.getDocumentUriAsync(e);return t||await this.cache.getDocumentUriAsync(e)}async getDocumentLocationAsync(e){return await this.workspace.getDocumentAsync(e)?"Workspace":await this.cache.getDocumentAsync(e)?"Cache":"NotFound"}};import{homedir as _}from"os";import{join as N}from"path";function g(){let u=process.env.KANONAK_PACKAGE_CACHE;return u||N(_(),".kanonak","packages")}var C=class u{static createComposite(e,t,n){let o=e??g(),s=t??".";return new k(o,s,n)}static createFromEnvironment(e){let t=g(),n=process.env.KANONAK_WORKSPACE_PATH??".";return u.createComposite(t,n,e)}};var D=class{repos;constructor(...e){this.repos=e}async getHighestCompatibleVersionAsync(e,t){for(let n of this.repos)try{let o=await n.getHighestCompatibleVersionAsync(e,t);if(o)return o}catch{}return null}async getAllDocumentsAsync(){let e=[],t=new Set;for(let n of this.repos)try{for(let o of await n.getAllDocumentsAsync()){let s=o.metadata?.namespace_,a=s?s.version?`${s.publisher}/${s.package_}@${s.version.major}.${s.version.minor}.${s.version.patch}`:`${s.publisher}/${s.package_}`:void 0;if(a!==void 0){if(t.has(a))continue;t.add(a)}e.push(o)}}catch{}return e}async getDocumentAsync(e){for(let t of this.repos)try{let n=await t.getDocumentAsync(e);if(n)return n}catch{}return null}async getDocumentsByNamespaceAsync(e,t){for(let n of this.repos)try{let o=await n.getDocumentsByNamespaceAsync(e,t);if(o.length>0)return o}catch{}return[]}async saveDocumentAsync(e,t){await this.repos[0].saveDocumentAsync(e,t)}async deleteDocumentAsync(e){await this.repos[0].deleteDocumentAsync(e)}async clearNamespaceAsync(e,t){await this.repos[0].clearNamespaceAsync(e,t)}async getAllDocumentReferencesAsync(){return this.repos[0].getAllDocumentReferencesAsync()}async getDocumentContentAsync(e){for(let t of this.repos)try{let n=await t.getDocumentContentAsync(e);if(n)return n}catch{}return null}async getDocumentUriAsync(e){for(let t of this.repos)try{let n=await t.getDocumentUriAsync(e);if(n)return n}catch{}return null}};import{readFileSync as B,readdirSync as H}from"fs";import{join as x}from"path";var $=new Set(["node_modules",".kanonak",".git","_site","build",".stage"]);function K(u,e=[]){for(let t of H(u,{withFileTypes:!0}))t.isDirectory()?$.has(t.name)||K(x(u,t.name),e):t.name.endsWith(".kan.yml")&&e.push(x(u,t.name));return e}async function j(u,e=new f,t={}){let n=new A(e);for(let m of K(u))try{let l=e.parse(B(m,"utf-8")),h=l.metadata?.namespace_,p=h?.version;h&&p&&await n.saveDocumentAsync(l,`${h.publisher}/${h.package_}@${p.major}.${p.minor}.${p.patch}`)}catch{}let o=new y(g(),!0,e),s=new Map,a=t.httpCache??{getFromCache:(m,l,h)=>s.get(`${m}|${l}|${h}`)??null,onFetch:(m,l,h,p)=>{s.set(`${m}|${l}|${h}`,p)}},r=new v({getFromCache:a.getFromCache,onFetch:a.onFetch});return new D(n,o,r)}export{y as a,S as b,k as c,g as d,C as e,D as f,K as g,j as h};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{a as u}from"./chunk-SC5M74NM.js";import{a as y}from"./chunk-TJPQETHV.js";import{e as v}from"./chunk-2ACBWC7K.js";var x="https://{publisher}/index.txt",P="https://{publisher}/{package}/{version}.kan.yml",k={version:1};function A(c){return{version:1,index:x.replaceAll("{publisher}",c),package:P.replaceAll("{publisher}",c),auth:"none"}}var f=class{cache=new Map;getConfig(t){let n=this.cache.get(t);return n||(n=this.fetchConfig(t),this.cache.set(t,n),n.catch(()=>{this.cache.get(t)===n&&this.cache.delete(t)})),n}async fetchConfig(t){let n=`https://${t}/.well-known/kanonak.json`,r;try{r=await fetch(n)}catch{return k}if(r.status===404)return k;if(!r.ok)throw new Error(`Failed to fetch publisher config: ${n} (${r.status} ${r.statusText})`);let e=await r.json();if(typeof e.version!="number")throw new Error(`Invalid publisher config at ${n}: missing or invalid "version" field`);let s={version:e.version};return typeof e.index=="string"&&(s.index=e.index),typeof e.package=="string"&&(s.package=e.package),(e.auth==="none"||e.auth==="oauth"||e.auth==="bearer")&&(s.auth=e.auth),Array.isArray(e.render)&&e.render.every(i=>typeof i=="string")&&(s.render=e.render),typeof e.resolveByRedirect=="boolean"&&(s.resolveByRedirect=e.resolveByRedirect),s}resolveIndexUrl(t,n){let r=n.index??x;return w(r,{publisher:t})}resolvePackageUrl(t,n,r,e){let s=e.package??P;return w(s,{publisher:t,package:n,version:r})}};function w(c,t){let n=c;for(let[e,s]of Object.entries(t))n=n.replaceAll(`{${e}}`,s);let r=n.match(/\{[a-z]+\}/);if(r)throw new Error(`Unresolved variable ${r[0]} in URL template: ${c}`);return n}import{VersionOperator as m}from"@kanonak-protocol/types/document/models/enums";var l=class c{indexCache=new Map;configResolver;fetchFn;constructor(t){this.configResolver=t?.configResolver??new f,this.fetchFn=t?.fetchFn}async resolveVersion(t,n){let r=await this.getPackageVersions(t,n.packageName);if(r.length===0)return null;let e=r.filter(s=>this.isVersionCompatible(s,n.version,n.versionOperator));return e.length===0?null:(e.sort((s,i)=>this.compareVersionStrings(i,s)),e[0])}async getHighestVersion(t,n){let r=await this.getPackageVersions(t,n);return r.length===0?null:[...r].sort((s,i)=>this.compareVersionStrings(i,s))[0]}async listLatestPackages(t){let n=await this.getIndex(t),r=[];for(let[e,s]of n){if(s.length===0)continue;let i=[...s].sort((o,a)=>this.compareVersionStrings(a,o));r.push({packageName:e,version:i[0]})}return r.sort((e,s)=>e.packageName.localeCompare(s.packageName)),r}async getPackageUrl(t,n,r){let e=await this.configResolver.getConfig(t);return this.configResolver.resolvePackageUrl(t,n,r,e)}getConfig(t){return this.configResolver.getConfig(t)}async getPackageVersions(t,n){return(await this.getIndex(t)).get(n)??[]}getIndex(t){let n=this.indexCache.get(t);return n||(n=this.fetchIndex(t),this.indexCache.set(t,n),n.catch(()=>{this.indexCache.get(t)===n&&this.indexCache.delete(t)})),n}async fetchIndex(t){let n=await this.configResolver.getConfig(t),r=this.configResolver.resolveIndexUrl(t,n),e=this.fetchFn?await this.fetchFn(r,t):await fetch(r);if(!e.ok)throw new Error(`Failed to fetch publisher index: ${r} (${e.status} ${e.statusText})`);let s=await e.text();return c.parseIndex(s)}static parseIndex(t){let n=new Map;for(let r of t.split(`
|
|
2
|
+
`)){let e=r.trim();if(!e||e.startsWith("#"))continue;let s=e.indexOf("/");if(s===-1)continue;let i=e.substring(0,s),o=e.substring(s+1);if(!i||!o)continue;let a=n.get(i);a?a.push(o):n.set(i,[o])}return n}isVersionCompatible(t,n,r){let e=c.parseVersion(t);if(!e)return!1;switch(r){case m.Any:return!0;case m.Exact:return e.major===n.major&&e.minor===n.minor&&e.patch===n.patch;case m.Compatible:return e.major===n.major&&e.minor===n.minor&&e.patch>=n.patch;case m.Major:return e.major!==n.major?!1:e.minor>n.minor?!0:e.minor===n.minor?e.patch>=n.patch:!1;default:return!1}}static parseVersion(t){let n=t.split(".");if(n.length<2)return null;let r=parseInt(n[0],10),e=parseInt(n[1],10),s=n.length>=3?parseInt(n[2],10):0;return isNaN(r)||isNaN(e)||isNaN(s)?null:{major:r,minor:e,patch:s}}compareVersionStrings(t,n){let r=c.parseVersion(t),e=c.parseVersion(n);return!r&&!e?0:r?e?r.major!==e.major?r.major-e.major:r.minor!==e.minor?r.minor-e.minor:r.patch-e.patch:1:-1}};import{VersionOperator as C}from"@kanonak-protocol/types/document/models/enums";var F=class{parser=new y;publisherIndex;documents=new Map;contentCache=new Map;fetchFn;onFetch;getFromCache;constructor(t){this.onFetch=t?.onFetch,this.getFromCache=t?.getFromCache,this.fetchFn=t?.fetchFn,this.publisherIndex=t?.fetchFn?new l({fetchFn:t.fetchFn}):new l}async getHighestCompatibleVersionAsync(t,n){if((await this.publisherIndex.getConfig(t)).resolveByRedirect)return this.resolveByRedirect(t,n);let e=await this.publisherIndex.resolveVersion(t,n);if(!e)return null;let s=`${t}/${n.packageName}@${e}`,i=this.documents.get(s);if(i)return i;if(this.getFromCache){let p=this.getFromCache(t,n.packageName,e);if(p){let d=this.parser.parse(p);return u(d,t,n.packageName,e),this.documents.set(s,d),this.contentCache.set(s,p),d}}let o=await this.publisherIndex.getPackageUrl(t,n.packageName,e),a=this.fetchFn?await this.fetchFn(o,t):await fetch(o);if(!a.ok)throw new Error(`Failed to fetch Kanonak package: ${o} (${a.status} ${a.statusText})`);let g=await a.text(),h=this.parser.parse(g);return u(h,t,n.packageName,e),this.onFetch&&this.onFetch(t,n.packageName,e,g),this.documents.set(s,h),this.contentCache.set(s,g),h}async resolveByRedirect(t,n){let r=n.packageName,s=n.versionOperator===C.Exact?await this.publisherIndex.getPackageUrl(t,r,v(n.version)):`https://${t}/${r}.kan.yml`,i=await this.fetchFollowing(s,t);if(!i)return null;let o=this.parser.parse(i.content),a=o.metadata.namespace_;if(!a||!a.version)throw new Error(`Producer origin returned a package with no namespace/version for ${t}/${r}`);let g=v(a.version);u(o,t,r,g);let h=`${t}/${r}@${g}`;return this.onFetch&&this.onFetch(t,r,g,i.content),this.documents.set(h,o),this.contentCache.set(h,i.content),o}async fetchFollowing(t,n,r=4){let e=t;for(let s=0;s<r;s++){let i=this.fetchFn?await this.fetchFn(e,n):await fetch(e,{redirect:"manual"});if(i.status===301||i.status===302){let o=i.headers.get("location");if(!o)throw new Error(`Redirect with no Location header from ${e}`);e=new URL(o,e).toString();continue}if(i.status===404)return null;if(!i.ok)throw new Error(`Failed to fetch Kanonak package: ${e} (${i.status} ${i.statusText})`);return{url:e,content:await i.text()}}throw new Error(`Too many redirects resolving ${t}`)}async getAllDocumentsAsync(){return Array.from(this.documents.values())}async getDocumentAsync(t){return this.documents.get(t)??null}async getDocumentsByNamespaceAsync(t,n){return Array.from(this.documents.values()).filter(r=>{let e=r.metadata.namespace_;return e&&e.publisher===t&&e.package_===n})}async saveDocumentAsync(t,n){throw new Error("HttpKanonakDocumentRepository is read-only")}async deleteDocumentAsync(t){throw new Error("HttpKanonakDocumentRepository is read-only")}async clearNamespaceAsync(t,n){throw new Error("HttpKanonakDocumentRepository is read-only")}async getAllDocumentReferencesAsync(){return[]}async getDocumentContentAsync(t){return this.contentCache.get(t)??null}async getDocumentUriAsync(t){let n=t.match(/^(.+?)\/(.+?)@(.+)$/);if(!n)return null;let[,r,e,s]=n;return this.publisherIndex.getPackageUrl(r,e,s)}};export{A as a,f as b,l as c,F as d};
|
package/dist/index.d.ts
CHANGED
|
@@ -31,4 +31,6 @@ export { LookRenderer, resolveDisplayValue } from './look/index.js';
|
|
|
31
31
|
export type { ResolvedLook, DisplayValue } from './look/index.js';
|
|
32
32
|
export { ViewMaterializer } from './view/index.js';
|
|
33
33
|
export type { MaterializeOptions, MaterializeResult } from './view/index.js';
|
|
34
|
+
export { PackageBuilder, ImportBook, contentAddressedName, sanitizeName, ProducerRepository, EntitlementProducer, EntitlementDeniedError, allowAllPolicy, noopMeter, } from './producer/index.js';
|
|
35
|
+
export type { BuiltPackage, ImportEntry, IPackageProducer, ProduceResult, VersionRange, IEntitlementPolicy, IMeter, ProduceContext, PackageAddress, EntitlementDecision, RequestPrincipal, } from './producer/index.js';
|
|
34
36
|
export { canonicalForm, canonicalHash } from './canonical/index.js';
|
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-MCU5IAMS.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-RRODBYIK.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};
|
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { PackageBuilder, ImportBook, contentAddressedName, sanitizeName } from './PackageBuilder.js';
|
|
2
|
+
export type { BuiltPackage, ImportEntry } from './PackageBuilder.js';
|
|
3
|
+
export { ProducerRepository } from './ProducerRepository.js';
|
|
4
|
+
export type { IPackageProducer, ProduceResult, VersionRange } from './IPackageProducer.js';
|
|
5
|
+
export { EntitlementProducer, EntitlementDeniedError, allowAllPolicy, noopMeter, } from './Entitlement.js';
|
|
6
|
+
export type { IEntitlementPolicy, IMeter, ProduceContext, PackageAddress, EntitlementDecision, RequestPrincipal, } from './Entitlement.js';
|
|
@@ -15,6 +15,26 @@ export declare class HttpKanonakDocumentRepository implements IKanonakDocumentRe
|
|
|
15
15
|
fetchFn?: AuthenticatedFetchFn;
|
|
16
16
|
});
|
|
17
17
|
getHighestCompatibleVersionAsync(publisher: string, import_: Import): Promise<KanonakDocument | null>;
|
|
18
|
+
/**
|
|
19
|
+
* Resolve against a live producer origin (`config.resolveByRedirect`): fetch
|
|
20
|
+
* the package source and follow the latest→pinned redirect, instead of
|
|
21
|
+
* downloading and filtering an index. An exact pin fetches the pinned URL;
|
|
22
|
+
* any range fetches the bare-name "latest" pointer (`/{package}.kan.yml`),
|
|
23
|
+
* which the origin 302s to the resolved pinned source. The resolved version
|
|
24
|
+
* is read from the returned document.
|
|
25
|
+
*
|
|
26
|
+
* A range resolves to the origin's LATEST — correct for a snapshot feed,
|
|
27
|
+
* where `^`/`~` are inert on the time axis; range-constrained resolution
|
|
28
|
+
* over redirect would need the range encoded in the request (future work).
|
|
29
|
+
*/
|
|
30
|
+
private resolveByRedirect;
|
|
31
|
+
/**
|
|
32
|
+
* Fetch a URL following 301/302 redirects explicitly — so an authenticated
|
|
33
|
+
* `fetchFn` re-signs each hop (and plain fetch doesn't transparently swallow
|
|
34
|
+
* the redirect). Returns null on 404; throws on other non-OK statuses or a
|
|
35
|
+
* redirect loop.
|
|
36
|
+
*/
|
|
37
|
+
private fetchFollowing;
|
|
18
38
|
getAllDocumentsAsync(): Promise<KanonakDocument[]>;
|
|
19
39
|
getDocumentAsync(identifier: string): Promise<KanonakDocument | null>;
|
|
20
40
|
getDocumentsByNamespaceAsync(publisher: string, package_: string): Promise<KanonakDocument[]>;
|
|
@@ -14,6 +14,16 @@ export interface PublisherConfig {
|
|
|
14
14
|
* through `parseKanonakAddress`, not string-matched.
|
|
15
15
|
*/
|
|
16
16
|
render?: string[];
|
|
17
|
+
/**
|
|
18
|
+
* When true, this is a LIVE producer origin: it resolves version ranges
|
|
19
|
+
* server-side and 302-redirects a "latest" request to the pinned source,
|
|
20
|
+
* rather than publishing an enumerable `index.txt`. A consumer then resolves
|
|
21
|
+
* by fetching the package URL and following the redirect, instead of
|
|
22
|
+
* downloading and filtering the index — essential for a snapshot feed whose
|
|
23
|
+
* version history is unbounded. ABSENT/false means an ordinary static
|
|
24
|
+
* publisher (resolve via `index.txt`), which is the unchanged default.
|
|
25
|
+
*/
|
|
26
|
+
resolveByRedirect?: boolean;
|
|
17
27
|
}
|
|
18
28
|
/**
|
|
19
29
|
* The explicit, self-describing config a publisher advertises at
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Import } from '@kanonak-protocol/types/document/models/types';
|
|
2
|
-
import { PublisherConfigResolver } from './PublisherConfig.js';
|
|
2
|
+
import { PublisherConfigResolver, type PublisherConfig } from './PublisherConfig.js';
|
|
3
3
|
import type { AuthenticatedFetchFn } from '../auth/index.js';
|
|
4
4
|
export declare class PublisherIndex {
|
|
5
5
|
private readonly indexCache;
|
|
@@ -24,6 +24,8 @@ export declare class PublisherIndex {
|
|
|
24
24
|
version: string;
|
|
25
25
|
}[]>;
|
|
26
26
|
getPackageUrl(publisher: string, packageName: string, version: string): Promise<string>;
|
|
27
|
+
/** The publisher's `.well-known` config — e.g. to check `resolveByRedirect`. */
|
|
28
|
+
getConfig(publisher: string): Promise<PublisherConfig>;
|
|
27
29
|
private getPackageVersions;
|
|
28
30
|
/**
|
|
29
31
|
* Resolve the publisher's index, de-duplicating concurrent fetches by
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{b as e,c as r,d as n}from"../chunk-
|
|
1
|
+
import{b as e,c as r,d as n}from"../chunk-LKBG2MK6.js";import{a as o}from"../chunk-4NO7MHS7.js";import"../chunk-SC5M74NM.js";import"../chunk-TJPQETHV.js";import"../chunk-2ACBWC7K.js";export{n as HttpKanonakDocumentRepository,o as InMemoryKanonakDocumentRepository,e as PublisherConfigResolver,r as PublisherIndex};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as b,b as c,c as d,d as e,e as f,f as k,g as l,h as m}from"../chunk-
|
|
1
|
+
import{a as b,b as c,c as d,d as e,e as f,f as k,g as l,h as m}from"../chunk-ATH6636H.js";import{a as g,b as h,c as i,d as j}from"../chunk-LKBG2MK6.js";import{a}from"../chunk-4NO7MHS7.js";import"../chunk-SC5M74NM.js";import"../chunk-TJPQETHV.js";import"../chunk-2ACBWC7K.js";export{d as CompositeKanonakDocumentRepository,c as DocumentLocation,b as FileSystemKanonakDocumentRepository,j as HttpKanonakDocumentRepository,a as InMemoryKanonakDocumentRepository,k as LocalFirstRepository,h as PublisherConfigResolver,i as PublisherIndex,f as RepositoryFactory,m as buildLocalFirstRepository,l as collectKanonakFiles,g as defaultPublisherConfig,e as getGlobalCachePath};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Kanonak } from '../kanonaks/index.js';
|
|
2
2
|
import type { LookRenderer } from '../look/index.js';
|
|
3
|
+
import type { IPackageProducer } from '../producer/index.js';
|
|
3
4
|
import type { ServerModel } from './types.js';
|
|
4
5
|
/**
|
|
5
6
|
* Build the route-facing indexes for a {@link ServerModel} from an already-built
|
|
@@ -18,4 +19,5 @@ export declare function assembleServerModel(params: {
|
|
|
18
19
|
lookRenderer: LookRenderer;
|
|
19
20
|
localNamespaces: Set<string>;
|
|
20
21
|
rawByNsKey: Map<string, string>;
|
|
22
|
+
producers?: readonly IPackageProducer[];
|
|
21
23
|
}): ServerModel;
|
package/dist/server/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{j as
|
|
1
|
+
import{j as E}from"../chunk-MCU5IAMS.js";import"../chunk-QHABFCRC.js";import{a as Z,d as A,f as te,g as N}from"../chunk-ATH6636H.js";import{a as ee,b as re,c as V,d as I}from"../chunk-LKBG2MK6.js";import{a as X}from"../chunk-4NO7MHS7.js";import"../chunk-PEUTCG3B.js";import{a as oe}from"../chunk-PEJALHXK.js";import"../chunk-SC5M74NM.js";import"../chunk-SHDHMKMJ.js";import{f as L}from"../chunk-G2DKKSZ4.js";import{a as D}from"../chunk-TJPQETHV.js";import{b as O}from"../chunk-BGQKZBNE.js";import"../chunk-CRKSKIAL.js";import"../chunk-IOMNZBK4.js";import{c as ne}from"../chunk-W6T7MOKY.js";import"../chunk-FUUTGGJS.js";import{c as F,e as z,f as K,g as Q}from"../chunk-2ACBWC7K.js";import{readFileSync as ue,existsSync as de,readdirSync as me,writeFileSync as ge,mkdirSync as fe}from"fs";import{join as q}from"path";function se(n){let e=n.metadata?.namespace_;return e?`${e.publisher}/${e.package_}`:void 0}async function M(n,e){let t=new Set,r=[...n];for(;r.length>0;){let o=r.shift(),a=se(o);if(!a||t.has(a))continue;t.add(a);let d=o.metadata?.imports;if(d)for(let[c,f]of Object.entries(d))for(let g of f)try{let l=await e.getHighestCompatibleVersionAsync(c,g);l&&r.push(l)}catch{}}return t}var j=class{constructor(e,t){this.inner=e;this.scope=t}inner;scope;async getAllDocumentsAsync(){return(await this.inner.getAllDocumentsAsync()).filter(t=>{let r=se(t);return r!==void 0&&this.scope.has(r)})}getDocumentAsync(e){return this.inner.getDocumentAsync(e)}getDocumentsByNamespaceAsync(e,t){return this.inner.getDocumentsByNamespaceAsync(e,t)}getHighestCompatibleVersionAsync(e,t){return this.inner.getHighestCompatibleVersionAsync(e,t)}saveDocumentAsync(e,t){return this.inner.saveDocumentAsync(e,t)}deleteDocumentAsync(e){return this.inner.deleteDocumentAsync(e)}clearNamespaceAsync(e,t){return this.inner.clearNamespaceAsync(e,t)}getAllDocumentReferencesAsync(){return this.inner.getAllDocumentReferencesAsync()}getDocumentContentAsync(e){return this.inner.getDocumentContentAsync(e)}getDocumentUriAsync(e){return this.inner.getDocumentUriAsync(e)}};var ie=[{publisher:"kanonak.org",package_:"core-kanonak"},{publisher:"kanonak.org",package_:"site"},{publisher:"kanonak.org",package_:"link"},{publisher:"kanonak.org",package_:"look-tokens"},{publisher:"kanonak.org",package_:"look-styles"},{publisher:"kanonak.org",package_:"look"},{publisher:"kanonak.org",package_:"universal-look"}];function C(n){let e=n?.render;if(e&&e.length>0){let t=[];for(let r of e)try{let o=O(r);o.kind==="package"?t.push({publisher:o.publisher,package_:o.package_}):o.kind==="resource"&&t.push({publisher:o.uri.publisher,package_:o.uri.package_})}catch{}if(t.length>0)return t}return ie}function H(n){return`${n.publisher}/${n.package_}`}function B(n){let{publisher:e,availablePublishers:t,catalog:r,lookRenderer:o,localNamespaces:a,rawByNsKey:d,producers:c}=n,f=new Map,g=new Map,l=new Map,i=new Set;for(let m of r){if(!(m instanceof ne))continue;let y=m.namespace||"";if(!a.has(y))continue;f.set(`${y}/${m.name}`,m);let v=y.split("/")[1]??"",[x,p]=v.split("@");if(!x||!p)continue;let b=Q(p);b&&(i.has(v)||(i.add(v),g.has(x)||g.set(x,[]),g.get(x).push({verStr:p,version:b})),m.name===x&&l.set(v,m))}for(let m of g.values())m.sort((y,v)=>F(v.version,y.version));return{publisher:e,availablePublishers:t,catalog:r,lookRenderer:o,localNamespaces:a,rawByNsKey:d,bySubject:f,pkgVersions:g,pkgSelfByVer:l,...c?{producers:c}:{}}}async function T(n,e={}){let t=new D,r=new X(t),o=[],a=[];for(let p of N(n)){let b;try{b=ue(p,"utf-8")}catch{continue}let S;try{S=t.parse(b).metadata?.namespace_}catch{continue}if(!S?.version)continue;let $=S.version;a.push({publisher:S.publisher,package_:S.package_,verStr:`${$.major}.${$.minor}.${$.patch}`,version:$,source:b})}a.sort((p,b)=>F(b.version,p.version));for(let p of a)await r.saveDocumentAsync(t.parse(p.source),`${p.publisher}/${p.package_}@${p.verStr}`),o.push({publisher:p.publisher,package_:p.package_,verStr:p.verStr,source:p.source});let d=[...new Set(o.map(p=>p.publisher))].sort(),c=e.publisher;if(c){if(!d.includes(c))throw new Error(`Publisher "${c}" not found in workspace. Available: ${d.join(", ")||"(none)"}`)}else if(d.length===1)c=d[0];else throw d.length===0?new Error(`No Kanonak packages found under ${n}`):new Error(`Workspace has multiple publishers (${d.join(", ")}). Pass --publisher <domain> to choose which one to serve.`);let f=new Set,g=new Map;for(let p of o)p.publisher===c&&(f.add(`${p.publisher}/${p.package_}@${p.verStr}`),g.set(`${p.package_}@${p.verStr}`,p.source));let l=new Z(A(),!0,t),i=e.repository??new te(r,l,new I(e.httpCache?{getFromCache:e.httpCache.getFromCache,onFetch:e.httpCache.onFetch}:void 0)),m=C(void 0);if(!e.repository){let p=A(),b=s=>{let h=q(p,s);return de(h)?new Set(me(h).filter(k=>k.endsWith(".kan.yml")).map(k=>k.split("@")[0])):new Set},S=(s,h)=>o.some(k=>k.publisher===s&&k.package_===h),$=new V,u=new Map;for(let s of m)if(u.has(s.publisher)||u.set(s.publisher,b(s.publisher)),!(u.get(s.publisher).has(s.package_)||S(s.publisher,s.package_)))try{let h=await $.getHighestVersion(s.publisher,s.package_);if(!h)continue;let k=await $.getPackageUrl(s.publisher,s.package_,h),_=await fetch(k);if(!_.ok)continue;let le=await _.text(),J=q(p,s.publisher);fe(J,{recursive:!0}),ge(q(J,`${s.package_}@${h}.kan.yml`),le,"utf-8")}catch{}}let y=i;if(!e.repository){let p=(await r.getAllDocumentsAsync()).filter(S=>S.metadata.namespace_?.publisher===c),b=await M(p,i);for(let S of m)b.add(H(S));y=new j(i,b)}let v=await new L(t).parseKanonaks(y),x=new E(v);return B({publisher:c,availablePublishers:d,catalog:v,lookRenderer:x,localNamespaces:f,rawByNsKey:g})}import{existsSync as he,readFileSync as ke,writeFileSync as ye,mkdirSync as ve}from"fs";import{join as ae}from"path";async function U(n,e={}){let t=new D,r=O(n),o=r.kind==="resource"?r.uri.publisher:r.publisher,a=e.cacheRoot??A(),d=(u,s,h)=>ae(a,u,`${s}@${h}.kan.yml`),c=new I({getFromCache:(u,s,h)=>{let k=d(u,s,h);return he(k)?ke(k,"utf-8"):null},onFetch:(u,s,h,k)=>{let _=ae(a,u);ve(_,{recursive:!0}),ye(d(u,s,h),k,"utf-8")},...e.fetchFn?{fetchFn:e.fetchFn}:{}}),f=new V(e.fetchFn?{fetchFn:e.fetchFn}:void 0),g;if(r.kind==="resource"){let u=r.uri.version;g=[u?{package_:r.uri.package_,version:`${u.major}.${u.minor}.${u.patch}`}:{package_:r.uri.package_}]}else if(r.kind==="package"){let u=r.version;g=[u?{package_:r.package_,version:`${u.major}.${u.minor}.${u.patch}`}:{package_:r.package_}]}else g=(await f.listLatestPackages(o)).map(s=>({package_:s.packageName}));let l=async(u,s,h)=>{try{let k=h?t.buildImport(s,"=",h,u):t.buildImport(s,"*","0.0.0",u);return await c.getHighestCompatibleVersionAsync(u,k)}catch{return null}},i=[];for(let u of g){let s=await l(o,u.package_,u.version);s&&i.push(s)}if(i.length===0)throw new Error(`Could not fetch any package for address "${n}" from publisher "${o}".`);let m=await new re().getConfig(o).catch(()=>{}),y=[];for(let u of C(m)){let s=await l(u.publisher,u.package_,void 0);s&&y.push(s)}let v=await M([...i,...y],c),x=new j(c,v),p=await new L(t).parseKanonaks(x),b=new E(p),S=new Set,$=new Map;for(let u of await c.getAllDocumentsAsync()){let s=u.metadata.namespace_;if(!s||s.publisher!==o)continue;let h=`${s.version.major}.${s.version.minor}.${s.version.patch}`,k=`${s.publisher}/${s.package_}@${h}`;S.add(k);let _=await c.getDocumentContentAsync(k);_!==null&&$.set(`${s.package_}@${h}`,_)}return B({publisher:o,availablePublishers:[o],catalog:p,lookRenderer:b,localNamespaces:S,rawByNsKey:$})}import{VersionOperator as W}from"@kanonak-protocol/types/document/models/enums";var w={".html":"text/html; charset=utf-8",".css":"text/css; charset=utf-8",".svg":"image/svg+xml",".md":"text/markdown; charset=utf-8",".kan.yml":"application/yaml; charset=utf-8",".txt":"text/plain; charset=utf-8",".json":"application/json; charset=utf-8"},R=(n,e,t,r)=>({status:n,headers:{"Content-Type":e,...r||{}},body:t}),P=n=>R(404,w[".html"],`<!doctype html><meta charset=utf-8><title>404</title><h1>404</h1><p>Not found: ${n}</p>`),be=n=>({status:301,headers:{Location:n},body:""}),Se=n=>({status:302,headers:{Location:n},body:""});function we(n){switch(n.kind){case"exact":return{operator:W.Exact,version:K(n.major,n.minor,n.patch)};case"minor-pin":return{operator:W.Compatible,version:K(n.major,n.minor,0)};case"major-pin":return{operator:W.Major,version:K(n.major,0,0)};default:return{operator:W.Any,version:K(0,0,0)}}}async function Re(n,e,t,r){if(!r)return null;let o=n.producers?.find(f=>f.canProduce(n.publisher,e));if(!o)return null;let a=await o.resolveVersion(n.publisher,e,we(t));if(!a)return null;let d=z(a);if(t.kind!=="exact")return Se(`/${e}/${d}.kan.yml`);let{source:c}=await o.produce(n.publisher,e,a);return R(200,w[".kan.yml"],c)}function ce(n,e,t){let r=n.pkgVersions.get(e);if(!r||r.length===0)return null;switch(t.kind){case"any":return r[0].verStr;case"major-pin":return r.find(o=>o.version.major===t.major)?.verStr??null;case"minor-pin":return r.find(o=>o.version.major===t.major&&o.version.minor===t.minor)?.verStr??null;case"exact":return r.find(o=>o.version.major===t.major&&o.version.minor===t.minor&&o.version.patch===t.patch)?.verStr??null;default:return null}}async function G(n,e,t=""){let{lookRenderer:r,publisher:o}=n;if(e==="/.well-known/kanonak.json"){let i=ee(o);return n.producers&&n.producers.length>0&&(i.resolveByRedirect=!0),R(200,w[".json"],JSON.stringify(i,null,2))}if(e==="/index.txt"){let i=[...n.localNamespaces].map(m=>m.split("/")[1].replace("@","/")).sort();return R(200,w[".txt"],i.join(`
|
|
2
2
|
`)+`
|
|
3
|
-
`)}if(e==="/"||e==="/index.html"||e==="/index.css"){let
|
|
3
|
+
`)}if(e==="/"||e==="/index.html"||e==="/index.css"){let i=r.publisherSubject(o);return e==="/index.css"?R(200,w[".css"],r.renderStylesheet(i)):R(200,w[".html"],r.renderDocument(i,{rootIndex:!0}))}let a=".html",d=!1,c=e;for(let i of[".kan.yml",".css",".svg",".md",".html"])if(e.endsWith(i)){a=i,d=!0,c=e.slice(0,-i.length);break}let f=!d&&/application\/yaml|text\/yaml/i.test(t),g=c.endsWith("/");g&&c!=="/"&&(c=c.slice(0,-1));let l=oe.parse(c,o);if(!l)return P(e);if(l.kind==="package"){let i=ce(n,l.package_,l.versionSpec);if(!i)return await Re(n,l.package_,l.versionSpec,a===".kan.yml"||f)??P(e);if(a===".kan.yml"||f){let v=n.rawByNsKey.get(`${l.package_}@${i}`);return v!==void 0?R(200,w[".kan.yml"],v):P(e)}let m=n.pkgSelfByVer.get(`${l.package_}@${i}`);if(!m)return P(e);if(a===".css")return R(200,w[".css"],r.renderStylesheet(m));if(!g)return be(c+"/");let y=l.versionSpec.kind==="any";if(y&&!r.hasDeclaredView(m)){let v=(n.pkgVersions.get(l.package_)||[]).map(x=>x.verStr);return R(200,w[".html"],r.renderPackageVersionList(l.package_,v,m))}return R(200,w[".html"],r.renderDocument(m,y?{bareOverview:!0}:void 0))}if(l.kind==="resource"){let i=ce(n,l.package_,l.versionSpec);if(!i)return P(e);let m=n.bySubject.get(`${o}/${l.package_}@${i}/${l.name}`);if(!m)return P(e);switch(a){case".css":return R(200,w[".css"],r.renderStylesheet(m));case".svg":return R(200,w[".svg"],await r.renderSvg(m));case".md":{let y=r.renderRawMarkdown(m);return y===void 0?P(e):R(200,w[".md"],y)}default:return R(200,w[".html"],r.renderDocument(m))}}return P(e)}import{readFileSync as xe}from"fs";var Y=class{constructor(e={}){this.options=e}options;models=new Map;workspaceIndex;clearCache(){this.models.clear(),this.workspaceIndex=void 0}getWorkspaceIndex(){if(this.workspaceIndex)return this.workspaceIndex;let e=new Set,t=new Set;if(this.options.root!==void 0){let r=new D;for(let o of N(this.options.root))try{let a=r.parse(xe(o,"utf-8")).metadata?.namespace_;if(!a?.version)continue;let d=a.version;e.add(`${a.publisher}/${a.package_}@${d.major}.${d.minor}.${d.patch}`),t.add(`${a.publisher}/${a.package_}`)}catch{}}return this.workspaceIndex={exact:e,pkgs:t},this.workspaceIndex}async modelFor(e,t,r){let o=this.getWorkspaceIndex(),a=this.options.fetchFn?{fetchFn:this.options.fetchFn}:{},d=t?r?o.exact.has(`${e}/${t}@${r}`):o.pkgs.has(`${e}/${t}`):[...o.pkgs].some(i=>i.startsWith(`${e}/`)),c,f;if(d&&this.options.root!==void 0){let i=this.options.root;c=`ws:${e}`,f=()=>T(i,{publisher:e})}else{let i=t?r?`${e}/${t}@${r}`:`${e}/${t}`:e;c=`rm:${i}`,f=()=>U(i,a)}let g=this.models.get(c);if(g)return g;let l=await f();return l.lookRenderer.setLinkMode("open-world"),this.models.set(c,l),l}async handle(e,t=""){let r=e.split("/").filter(Boolean);if(r.length===0)return{status:200,headers:{"Content-Type":"text/html; charset=utf-8"},body:pe()};let o=r[0];if(!o.includes("."))return{status:404,headers:{"Content-Type":"text/html; charset=utf-8"},body:"<!doctype html><meta charset=utf-8><title>404</title><h1>404</h1><p>Expected a publisher domain as the first path segment: <code>/{publisher}/{package}/{version}/{resource}</code></p>"};let a=r.length>=2&&(r[1]==="index.html"||r[1]==="index.css"||r[1]==="index.txt"||r[1]===".well-known"),d=!a&&r.length>=2?r[1]:void 0,c=!a&&r.length>=3&&/^\d+\.\d+\.\d+$/.test(r[2])?r[2]:void 0,f=await this.modelFor(o,d,c),g=e.endsWith("/")&&r.length>1?"/":"",l="/"+r.slice(1).join("/")+g,i=await G(f,l,t);return i.headers.Location?{...i,headers:{...i.headers,Location:`/${o}${i.headers.Location}`}}:i}};function pe(){return'<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Kanonak origin</title></head><body style="font-family:system-ui;max-width:40rem;margin:4rem auto;padding:0 1rem"><h1>Kanonak request-driven origin</h1><p>Open a resource by its address:</p><p><code>/{publisher}/{package}/{version}/{resource}</code></p><p>e.g. <code>/kanonak.org/capabilities/2.0.0/Capability</code></p></body></html>'}export{j as ClosureScopedRepository,Y as RequestRouter,ie as UNIVERSAL_RENDER_BASE,M as deriveImportClosure,pe as landingPage,U as loadResourceModel,T as loadServerModel,H as renderRefKey,C as resolveRenderContract,G as route};
|
package/dist/server/types.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type { Kanonak } from '../kanonaks/index.js';
|
|
|
4
4
|
import { SubjectKanonak } from '../kanonaks/index.js';
|
|
5
5
|
import type { LookRenderer } from '../look/index.js';
|
|
6
6
|
import type { HttpCacheHooks } from '../repositories/index.js';
|
|
7
|
+
import type { IPackageProducer } from '../producer/index.js';
|
|
7
8
|
/** A package version present in the served workspace. */
|
|
8
9
|
export interface PackageVersion {
|
|
9
10
|
/** "major.minor.patch" string form. */
|
|
@@ -36,6 +37,14 @@ export interface ServerModel {
|
|
|
36
37
|
readonly pkgVersions: Map<string, PackageVersion[]>;
|
|
37
38
|
/** `pkg@ver` → the package self-resource subject. */
|
|
38
39
|
readonly pkgSelfByVer: Map<string, SubjectKanonak>;
|
|
40
|
+
/**
|
|
41
|
+
* Package producers this origin hosts (optional). When a requested package
|
|
42
|
+
* is not preloaded but a producer claims it, `route` generates the package
|
|
43
|
+
* on demand: a range request 302-redirects to the resolved pinned source,
|
|
44
|
+
* an exact `.kan.yml` request is produced and served. Compose
|
|
45
|
+
* `EntitlementProducer` here for a gated origin.
|
|
46
|
+
*/
|
|
47
|
+
readonly producers?: readonly IPackageProducer[];
|
|
39
48
|
}
|
|
40
49
|
/** A routed response. `body` is always a string (HTML/CSS/SVG/MD/YAML/JSON). */
|
|
41
50
|
export interface RouteResponse {
|
|
@@ -52,6 +52,7 @@ export declare class ViewMaterializer {
|
|
|
52
52
|
private readonly repository;
|
|
53
53
|
private readonly parser;
|
|
54
54
|
private readonly objectParser;
|
|
55
|
+
private readonly builder;
|
|
55
56
|
constructor(repository: IKanonakDocumentRepository, parser?: KanonakParser);
|
|
56
57
|
materialize(viewRef: EntityUri, opts?: MaterializeOptions): Promise<MaterializeResult>;
|
|
57
58
|
private resolveView;
|
|
@@ -61,11 +62,4 @@ export declare class ViewMaterializer {
|
|
|
61
62
|
private passesWhere;
|
|
62
63
|
private evaluateValue;
|
|
63
64
|
private rowName;
|
|
64
|
-
/**
|
|
65
|
-
* Content hash of the body, independent of the EphemeralPackage's own
|
|
66
|
-
* (not-yet-assigned) name. Parses the rows under a fixed probe header,
|
|
67
|
-
* neutralizes each body subject's namespace to a constant, and hashes —
|
|
68
|
-
* so the same projected data always yields the same `sha256:`.
|
|
69
|
-
*/
|
|
70
|
-
private hashBody;
|
|
71
65
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kanonak-protocol/sdk",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.72.0",
|
|
4
4
|
"description": "TypeScript SDK for the Kanonak Protocol — parse, resolve, validate, reason over, and render .kan.yml packages.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -122,7 +122,7 @@
|
|
|
122
122
|
"yaml-parser"
|
|
123
123
|
],
|
|
124
124
|
"dependencies": {
|
|
125
|
-
"@kanonak-protocol/types": "^3.
|
|
125
|
+
"@kanonak-protocol/types": "^3.72.0",
|
|
126
126
|
"ignore": "^7.0.5",
|
|
127
127
|
"js-yaml": "^4.1.0",
|
|
128
128
|
"yaml": "^2.7.0"
|
package/dist/chunk-HAR3BNTB.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{a as f}from"./chunk-SC5M74NM.js";import{a as d}from"./chunk-TJPQETHV.js";var k="https://{publisher}/index.txt",x="https://{publisher}/{package}/{version}.kan.yml",v={version:1};function F(a){return{version:1,index:k.replaceAll("{publisher}",a),package:x.replaceAll("{publisher}",a),auth:"none"}}var h=class{cache=new Map;getConfig(n){let e=this.cache.get(n);return e||(e=this.fetchConfig(n),this.cache.set(n,e),e.catch(()=>{this.cache.get(n)===e&&this.cache.delete(n)})),e}async fetchConfig(n){let e=`https://${n}/.well-known/kanonak.json`,r;try{r=await fetch(e)}catch{return v}if(r.status===404)return v;if(!r.ok)throw new Error(`Failed to fetch publisher config: ${e} (${r.status} ${r.statusText})`);let t=await r.json();if(typeof t.version!="number")throw new Error(`Invalid publisher config at ${e}: missing or invalid "version" field`);let s={version:t.version};return typeof t.index=="string"&&(s.index=t.index),typeof t.package=="string"&&(s.package=t.package),(t.auth==="none"||t.auth==="oauth"||t.auth==="bearer")&&(s.auth=t.auth),Array.isArray(t.render)&&t.render.every(i=>typeof i=="string")&&(s.render=t.render),s}resolveIndexUrl(n,e){let r=e.index??k;return y(r,{publisher:n})}resolvePackageUrl(n,e,r,t){let s=t.package??x;return y(s,{publisher:n,package:e,version:r})}};function y(a,n){let e=a;for(let[t,s]of Object.entries(n))e=e.replaceAll(`{${t}}`,s);let r=e.match(/\{[a-z]+\}/);if(r)throw new Error(`Unresolved variable ${r[0]} in URL template: ${a}`);return e}import{VersionOperator as l}from"@kanonak-protocol/types/document/models/enums";var g=class a{indexCache=new Map;configResolver;fetchFn;constructor(n){this.configResolver=n?.configResolver??new h,this.fetchFn=n?.fetchFn}async resolveVersion(n,e){let r=await this.getPackageVersions(n,e.packageName);if(r.length===0)return null;let t=r.filter(s=>this.isVersionCompatible(s,e.version,e.versionOperator));return t.length===0?null:(t.sort((s,i)=>this.compareVersionStrings(i,s)),t[0])}async getHighestVersion(n,e){let r=await this.getPackageVersions(n,e);return r.length===0?null:[...r].sort((s,i)=>this.compareVersionStrings(i,s))[0]}async listLatestPackages(n){let e=await this.getIndex(n),r=[];for(let[t,s]of e){if(s.length===0)continue;let i=[...s].sort((o,c)=>this.compareVersionStrings(c,o));r.push({packageName:t,version:i[0]})}return r.sort((t,s)=>t.packageName.localeCompare(s.packageName)),r}async getPackageUrl(n,e,r){let t=await this.configResolver.getConfig(n);return this.configResolver.resolvePackageUrl(n,e,r,t)}async getPackageVersions(n,e){return(await this.getIndex(n)).get(e)??[]}getIndex(n){let e=this.indexCache.get(n);return e||(e=this.fetchIndex(n),this.indexCache.set(n,e),e.catch(()=>{this.indexCache.get(n)===e&&this.indexCache.delete(n)})),e}async fetchIndex(n){let e=await this.configResolver.getConfig(n),r=this.configResolver.resolveIndexUrl(n,e),t=this.fetchFn?await this.fetchFn(r,n):await fetch(r);if(!t.ok)throw new Error(`Failed to fetch publisher index: ${r} (${t.status} ${t.statusText})`);let s=await t.text();return a.parseIndex(s)}static parseIndex(n){let e=new Map;for(let r of n.split(`
|
|
2
|
-
`)){let t=r.trim();if(!t||t.startsWith("#"))continue;let s=t.indexOf("/");if(s===-1)continue;let i=t.substring(0,s),o=t.substring(s+1);if(!i||!o)continue;let c=e.get(i);c?c.push(o):e.set(i,[o])}return e}isVersionCompatible(n,e,r){let t=a.parseVersion(n);if(!t)return!1;switch(r){case l.Any:return!0;case l.Exact:return t.major===e.major&&t.minor===e.minor&&t.patch===e.patch;case l.Compatible:return t.major===e.major&&t.minor===e.minor&&t.patch>=e.patch;case l.Major:return t.major!==e.major?!1:t.minor>e.minor?!0:t.minor===e.minor?t.patch>=e.patch:!1;default:return!1}}static parseVersion(n){let e=n.split(".");if(e.length<2)return null;let r=parseInt(e[0],10),t=parseInt(e[1],10),s=e.length>=3?parseInt(e[2],10):0;return isNaN(r)||isNaN(t)||isNaN(s)?null:{major:r,minor:t,patch:s}}compareVersionStrings(n,e){let r=a.parseVersion(n),t=a.parseVersion(e);return!r&&!t?0:r?t?r.major!==t.major?r.major-t.major:r.minor!==t.minor?r.minor-t.minor:r.patch-t.patch:1:-1}};var P=class{parser=new d;publisherIndex;documents=new Map;contentCache=new Map;fetchFn;onFetch;getFromCache;constructor(n){this.onFetch=n?.onFetch,this.getFromCache=n?.getFromCache,this.fetchFn=n?.fetchFn,this.publisherIndex=n?.fetchFn?new g({fetchFn:n.fetchFn}):new g}async getHighestCompatibleVersionAsync(n,e){let r=await this.publisherIndex.resolveVersion(n,e);if(!r)return null;let t=`${n}/${e.packageName}@${r}`,s=this.documents.get(t);if(s)return s;if(this.getFromCache){let m=this.getFromCache(n,e.packageName,r);if(m){let p=this.parser.parse(m);return f(p,n,e.packageName,r),this.documents.set(t,p),this.contentCache.set(t,m),p}}let i=await this.publisherIndex.getPackageUrl(n,e.packageName,r),o=this.fetchFn?await this.fetchFn(i,n):await fetch(i);if(!o.ok)throw new Error(`Failed to fetch Kanonak package: ${i} (${o.status} ${o.statusText})`);let c=await o.text(),u=this.parser.parse(c);return f(u,n,e.packageName,r),this.onFetch&&this.onFetch(n,e.packageName,r,c),this.documents.set(t,u),this.contentCache.set(t,c),u}async getAllDocumentsAsync(){return Array.from(this.documents.values())}async getDocumentAsync(n){return this.documents.get(n)??null}async getDocumentsByNamespaceAsync(n,e){return Array.from(this.documents.values()).filter(r=>{let t=r.metadata.namespace_;return t&&t.publisher===n&&t.package_===e})}async saveDocumentAsync(n,e){throw new Error("HttpKanonakDocumentRepository is read-only")}async deleteDocumentAsync(n){throw new Error("HttpKanonakDocumentRepository is read-only")}async clearNamespaceAsync(n,e){throw new Error("HttpKanonakDocumentRepository is read-only")}async getAllDocumentReferencesAsync(){return[]}async getDocumentContentAsync(n){return this.contentCache.get(n)??null}async getDocumentUriAsync(n){let e=n.match(/^(.+?)\/(.+?)@(.+)$/);if(!e)return null;let[,r,t,s]=e;return this.publisherIndex.getPackageUrl(r,t,s)}};export{F as a,h as b,g as c,P as d};
|