@kanonak-protocol/sdk 4.11.0 → 4.13.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/auth/CredentialBackend.d.ts +15 -6
- package/dist/auth/CredentialHelperBackend.d.ts +4 -4
- package/dist/auth/DeviceCertificateStore.d.ts +52 -0
- package/dist/auth/EncryptedFileBackend.d.ts +11 -7
- package/dist/auth/KeychainBackend.d.ts +10 -6
- package/dist/auth/SecretServiceBackend.d.ts +8 -6
- package/dist/auth/WinCredBackend.d.ts +13 -9
- package/dist/auth/index.d.ts +3 -1
- package/dist/browser.js +1 -1
- package/dist/canonical/CanonicalHash.d.ts +13 -17
- package/dist/canonical/Datatypes.d.ts +19 -93
- package/dist/canonical/InputModel.d.ts +9 -46
- package/dist/chunk-BKVPSPG4.js +1 -0
- package/dist/{chunk-QIMJSVIM.js → chunk-CR55WXIN.js} +1 -1
- package/dist/{chunk-WED776KZ.js → chunk-NUXUITUC.js} +2 -2
- package/dist/{chunk-MMJ7GO7J.js → chunk-RGOBWOBB.js} +1 -1
- package/dist/{chunk-55DXTCGV.js → chunk-UBBZWWRB.js} +1 -1
- package/dist/{chunk-E2FCKRB4.js → chunk-V72IVYR4.js} +1 -1
- package/dist/{chunk-47RLRYV2.js → chunk-VWS25JH4.js} +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +26 -26
- package/dist/parsing/index.js +1 -1
- package/dist/reasoning/index.js +1 -1
- package/dist/search/index.js +1 -1
- package/dist/server/index.js +1 -1
- package/dist/transformations/index.js +1 -1
- package/dist/validation/index.js +1 -1
- package/package.json +3 -2
- package/dist/chunk-MFNVQSBW.js +0 -1
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Pluggable
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Pluggable secure-storage backend: JSON values of type `T` keyed by a
|
|
3
|
+
* normalized host, in a platform-specific secure store (OS keychain, encrypted
|
|
4
|
+
* file, enterprise vault). The same backend implementations serve different
|
|
5
|
+
* record types under different namespaces — OAuth credentials
|
|
6
|
+
* ({@link StoredCredential}) and device enrollments — so the storage mechanism
|
|
7
|
+
* is written once and reused.
|
|
5
8
|
*/
|
|
6
|
-
export interface
|
|
7
|
-
get(publisher: string): Promise<
|
|
8
|
-
store(publisher: string,
|
|
9
|
+
export interface SecretBackend<T> {
|
|
10
|
+
get(publisher: string): Promise<T | null>;
|
|
11
|
+
store(publisher: string, value: T): Promise<void>;
|
|
9
12
|
remove(publisher: string): Promise<void>;
|
|
10
13
|
list(): Promise<string[]>;
|
|
11
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* The OAuth credential storage backend — a {@link SecretBackend} whose records
|
|
17
|
+
* are {@link StoredCredential}. Kept as a named alias so existing consumers and
|
|
18
|
+
* the `CredentialStore` are unchanged.
|
|
19
|
+
*/
|
|
20
|
+
export type CredentialBackend = SecretBackend<StoredCredential>;
|
|
12
21
|
/**
|
|
13
22
|
* OAuth credential stored per publisher host.
|
|
14
23
|
* Matches the OAuthCredentialStore types from @kanonak-protocol/types.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { SecretBackend, StoredCredential } from './CredentialBackend.js';
|
|
2
2
|
/**
|
|
3
3
|
* External credential helper backend.
|
|
4
4
|
* Delegates to an enterprise-configured binary using a stdin/stdout JSON protocol.
|
|
@@ -6,11 +6,11 @@ import type { CredentialBackend, StoredCredential } from './CredentialBackend.js
|
|
|
6
6
|
* Configure in ~/.kanonak/config.json:
|
|
7
7
|
* { "credentialHelper": "/usr/local/bin/kanonak-credential-vault" }
|
|
8
8
|
*/
|
|
9
|
-
export declare class CredentialHelperBackend implements
|
|
9
|
+
export declare class CredentialHelperBackend<T = StoredCredential> implements SecretBackend<T> {
|
|
10
10
|
private readonly helperPath;
|
|
11
11
|
constructor(helperPath: string);
|
|
12
|
-
get(publisher: string): Promise<
|
|
13
|
-
store(publisher: string,
|
|
12
|
+
get(publisher: string): Promise<T | null>;
|
|
13
|
+
store(publisher: string, value: T): Promise<void>;
|
|
14
14
|
remove(publisher: string): Promise<void>;
|
|
15
15
|
list(): Promise<string[]>;
|
|
16
16
|
private runHelper;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { SecretBackend } from './CredentialBackend.js';
|
|
2
|
+
import { normalizeHost } from './CredentialBackend.js';
|
|
3
|
+
/**
|
|
4
|
+
* A device certificate enrollment, persisted per registry host (issue #67).
|
|
5
|
+
*
|
|
6
|
+
* The record holds the device-held key material, the CA-signed certificate, and
|
|
7
|
+
* the consent context. In v1 the key is a software key (its private JWK lives in
|
|
8
|
+
* `keyMaterial`); a future hardware {@link KeyProvider} stores an opaque handle
|
|
9
|
+
* here instead, so the secure store never holds an exportable key. Either way the
|
|
10
|
+
* record is opaque JSON to the storage backend.
|
|
11
|
+
*/
|
|
12
|
+
export interface DeviceEnrollmentRecord {
|
|
13
|
+
/** Software provider: the private key JWK. Hardware provider: an opaque key handle. */
|
|
14
|
+
keyMaterial: Record<string, unknown>;
|
|
15
|
+
/** RFC 7638 JWK SHA-256 thumbprint of the device public key — the consent-bound identity. */
|
|
16
|
+
thumbprint: string;
|
|
17
|
+
/** The CA-signed leaf certificate (PEM). */
|
|
18
|
+
certificatePem: string;
|
|
19
|
+
/** The issuing chain (PEM, possibly empty). */
|
|
20
|
+
chainPem: string;
|
|
21
|
+
/** ISO timestamp the certificate was issued/installed. */
|
|
22
|
+
issuedAt: string;
|
|
23
|
+
/** ISO timestamp the certificate expires, or null if unknown. */
|
|
24
|
+
expiresAt: string | null;
|
|
25
|
+
/** The scopes consented at enrollment. */
|
|
26
|
+
scopes: string[];
|
|
27
|
+
/** A human-facing device label shown on the consent screen. */
|
|
28
|
+
deviceName?: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Persists {@link DeviceEnrollmentRecord}s in the same platform-secure stores as
|
|
32
|
+
* OAuth credentials, but under a separate `kanonak-device` namespace so the two
|
|
33
|
+
* never collide (separate Keychain service / Credential Manager target prefix /
|
|
34
|
+
* Secret Service attribute / encrypted file). Mirrors {@link CredentialStore}'s
|
|
35
|
+
* backend selection; the external credential-helper backend is intentionally not
|
|
36
|
+
* used for device certs in v1 (device enrollment is a first-party flow).
|
|
37
|
+
*
|
|
38
|
+
* This is a Node-only module (it reaches OS keystores) and is deliberately not
|
|
39
|
+
* exported from the SDK browser entry.
|
|
40
|
+
*/
|
|
41
|
+
export declare class DeviceCertificateStore {
|
|
42
|
+
private backend;
|
|
43
|
+
private backendReady;
|
|
44
|
+
getBackend(): Promise<SecretBackend<DeviceEnrollmentRecord>>;
|
|
45
|
+
get(host: string): Promise<DeviceEnrollmentRecord | null>;
|
|
46
|
+
store(host: string, record: DeviceEnrollmentRecord): Promise<void>;
|
|
47
|
+
remove(host: string): Promise<void>;
|
|
48
|
+
list(): Promise<string[]>;
|
|
49
|
+
private resolveBackend;
|
|
50
|
+
}
|
|
51
|
+
/** Re-exported for callers that namespace device records themselves. */
|
|
52
|
+
export { normalizeHost };
|
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { SecretBackend, StoredCredential } from './CredentialBackend.js';
|
|
2
2
|
/**
|
|
3
|
-
* Encrypted file
|
|
3
|
+
* Encrypted file secret backend.
|
|
4
4
|
* Fallback for headless Linux, containers, and CI environments
|
|
5
|
-
* where no OS keyring is available.
|
|
5
|
+
* where no OS keyring is available. The secrets file is namespaced (OAuth
|
|
6
|
+
* credentials in `credentials.enc`, device enrollments in `device-credentials.enc`)
|
|
7
|
+
* so the two stores never collide; both are sealed with the same per-user key.
|
|
6
8
|
*
|
|
7
9
|
* - Key: ~/.config/kanonak/keyring.key (random 32 bytes, mode 0600)
|
|
8
|
-
* - Secrets:
|
|
10
|
+
* - Secrets: a per-namespace AES-256-GCM encrypted JSON file
|
|
9
11
|
*/
|
|
10
|
-
export declare class EncryptedFileBackend implements
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
export declare class EncryptedFileBackend<T = StoredCredential> implements SecretBackend<T> {
|
|
13
|
+
private readonly secretsFile;
|
|
14
|
+
constructor(secretsFile?: string);
|
|
15
|
+
get(publisher: string): Promise<T | null>;
|
|
16
|
+
store(publisher: string, value: T): Promise<void>;
|
|
13
17
|
remove(publisher: string): Promise<void>;
|
|
14
18
|
list(): Promise<string[]>;
|
|
15
19
|
private loadStore;
|
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { SecretBackend, StoredCredential } from './CredentialBackend.js';
|
|
2
2
|
/**
|
|
3
|
-
* macOS Keychain
|
|
4
|
-
* Stores
|
|
3
|
+
* macOS Keychain secret backend.
|
|
4
|
+
* Stores records via the `security` CLI tool (no native modules). The Keychain
|
|
5
|
+
* `service` namespaces the store, so OAuth credentials (`kanonak`) and device
|
|
6
|
+
* enrollments (`kanonak-device`) live side by side without colliding.
|
|
5
7
|
*/
|
|
6
|
-
export declare class KeychainBackend implements
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
export declare class KeychainBackend<T = StoredCredential> implements SecretBackend<T> {
|
|
9
|
+
private readonly service;
|
|
10
|
+
constructor(service?: string);
|
|
11
|
+
get(publisher: string): Promise<T | null>;
|
|
12
|
+
store(publisher: string, value: T): Promise<void>;
|
|
9
13
|
remove(publisher: string): Promise<void>;
|
|
10
14
|
list(): Promise<string[]>;
|
|
11
15
|
}
|
|
@@ -1,19 +1,21 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { SecretBackend, StoredCredential } from './CredentialBackend.js';
|
|
2
2
|
/**
|
|
3
3
|
* Linux Secret Service backend (GNOME Keyring / KDE Wallet).
|
|
4
4
|
* Uses the `secret-tool` CLI from libsecret-tools.
|
|
5
5
|
*
|
|
6
|
-
* Each
|
|
7
|
-
* service = "kanonak"
|
|
6
|
+
* Each record is stored with attributes:
|
|
7
|
+
* service = the namespace ("kanonak" for OAuth, "kanonak-device" for device certs)
|
|
8
8
|
* publisher = normalized publisher host
|
|
9
9
|
*
|
|
10
10
|
* All interactions use execFile (no shell) to prevent command injection.
|
|
11
11
|
* The store() method uses spawn with stdin piping since secret-tool
|
|
12
12
|
* reads the secret value from stdin.
|
|
13
13
|
*/
|
|
14
|
-
export declare class SecretServiceBackend implements
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
export declare class SecretServiceBackend<T = StoredCredential> implements SecretBackend<T> {
|
|
15
|
+
private readonly service;
|
|
16
|
+
constructor(service?: string);
|
|
17
|
+
get(publisher: string): Promise<T | null>;
|
|
18
|
+
store(publisher: string, value: T): Promise<void>;
|
|
17
19
|
remove(publisher: string): Promise<void>;
|
|
18
20
|
list(): Promise<string[]>;
|
|
19
21
|
}
|
|
@@ -1,19 +1,23 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { SecretBackend, StoredCredential } from './CredentialBackend.js';
|
|
2
2
|
/**
|
|
3
3
|
* Windows Credential Manager backend.
|
|
4
4
|
* Uses PowerShell P/Invoke to Advapi32.dll for CredRead/CredWrite/CredDelete.
|
|
5
5
|
* cmdkey cannot read passwords back, so P/Invoke is required.
|
|
6
6
|
*
|
|
7
|
-
* Each
|
|
8
|
-
* target = "
|
|
9
|
-
* credential blob = JSON-serialized
|
|
7
|
+
* Each record is stored as a generic credential with:
|
|
8
|
+
* target = "{prefix}{normalized_publisher}"
|
|
9
|
+
* credential blob = JSON-serialized record (UTF-16)
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
11
|
+
* The `target` prefix namespaces the store, so OAuth credentials (`kanonak:`)
|
|
12
|
+
* and device enrollments (`kanonak-device:`) do not collide. Data is passed to
|
|
13
|
+
* PowerShell via stdin to prevent injection attacks; no user-supplied values
|
|
14
|
+
* are interpolated into PowerShell code.
|
|
13
15
|
*/
|
|
14
|
-
export declare class WinCredBackend implements
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
export declare class WinCredBackend<T = StoredCredential> implements SecretBackend<T> {
|
|
17
|
+
private readonly targetPrefix;
|
|
18
|
+
constructor(targetPrefix?: string);
|
|
19
|
+
get(publisher: string): Promise<T | null>;
|
|
20
|
+
store(publisher: string, value: T): Promise<void>;
|
|
17
21
|
remove(publisher: string): Promise<void>;
|
|
18
22
|
list(): Promise<string[]>;
|
|
19
23
|
}
|
package/dist/auth/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
export type { CredentialBackend, StoredCredential, DPoPKeyPair } from './CredentialBackend.js';
|
|
1
|
+
export type { SecretBackend, CredentialBackend, StoredCredential, DPoPKeyPair } from './CredentialBackend.js';
|
|
2
2
|
export { isExpired, hasValidToken, normalizeHost } from './CredentialBackend.js';
|
|
3
3
|
export { CredentialStore } from './CredentialStore.js';
|
|
4
|
+
export { DeviceCertificateStore } from './DeviceCertificateStore.js';
|
|
5
|
+
export type { DeviceEnrollmentRecord } from './DeviceCertificateStore.js';
|
|
4
6
|
export type { AuthenticatedFetchFn } from './AuthenticatedFetch.js';
|
|
5
7
|
export { createAuthenticatedFetch } from './AuthenticatedFetch.js';
|
|
6
8
|
export { generateDPoPKeyPair, createDPoPProof, serverSupportsDPoP } from './DPoP.js';
|
package/dist/browser.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as we,b as ke,c as he,d as E,e as _,f as d,g as tr}from"./chunk-
|
|
1
|
+
import{a as we,b as ke,c as he,d as E,e as _,f as d,g as tr}from"./chunk-NUXUITUC.js";import{a as rr}from"./chunk-VWS25JH4.js";import"./chunk-QHABFCRC.js";import{a as F,b as W,c as G,d as w,f as X,g as Q,h as Y}from"./chunk-JYBKSBB5.js";import{a as q}from"./chunk-4NO7MHS7.js";import{a as Ke,b as be,c as xe}from"./chunk-RGOBWOBB.js";import{a as Se,b as Re}from"./chunk-PEUTCG3B.js";import"./chunk-PEJALHXK.js";import"./chunk-SC5M74NM.js";import{A as Xe,B as Qe,C as Ye,D as Ze,M as er,a as De,b as Be,c as Ce,d as Ee,f as _e,g as je,h as ve,i as Ae,k as Te,l as Ie,m as Oe,n as Ue,o as Ve,p as $e,q as Me,r as Ne,s as ze,t as Je,u as He,v as qe,w as Le,x as Fe,y as We,z as Ge}from"./chunk-UBBZWWRB.js";import"./chunk-SHDHMKMJ.js";import{a as te,c as ye,h as me}from"./chunk-BKVPSPG4.js";import{a as L}from"./chunk-NJ3AZYQD.js";import{a as Pe}from"./chunk-IEOSSSB5.js";import"./chunk-7TKJHKC2.js";import{b as ge,c as fe}from"./chunk-7HRKWTBB.js";import{a as Z,b as ee,c as re,d as oe,e as se,f as ie,g as ae,h as ce,i as le,j as ue,k as de,l as pe}from"./chunk-4UT2CLAT.js";import{a as ne}from"./chunk-FUUTGGJS.js";import{c as U,d as V,e as $,f as M,g as N,h as z,i as J,j as H}from"./chunk-2ACBWC7K.js";var j="kanonak-credentials",u="credentials",nr=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,nr);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 A(){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 x(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 sr(t)),o&&(s.nonce=o),await or(a,s,n.signingKey)}function S(n){return!n||n.length===0?!1:n.some(r=>r.toUpperCase()==="ES256")}async function or(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=B(s);return`${t}.${o}.${l}`}async function sr(n){let r=new TextEncoder().encode(n),e=await crypto.subtle.digest("SHA-256",r);return B(e)}function v(n){let r=new TextEncoder().encode(n);return B(r.buffer)}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(/=+$/,"")}var ir=300*1e3,R=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=S(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=ar(),p=await cr(m),D=lr(),I=ur(t.authorizationEndpoint,i,this.callbackUrl,D,p),y=await this.openAuthPopup(I,D);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!==D)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 O={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,O),{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 w(e);if(!t.ok)continue;let o=await t.json();return{issuer:k(o.issuer),authorizationEndpoint:k(o.authorization_endpoint),tokenEndpoint:k(o.token_endpoint),registrationEndpoint:k(o.registration_endpoint),revocationEndpoint:k(o.revocation_endpoint),dpopSigningAlgValuesSupported:T(o.dpop_signing_alg_values_supported),codeChallengeMethodsSupported:T(o.code_challenge_methods_supported)}}catch{continue}return null}async registerClient(r){try{let e=await w(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)},ir),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 x(l,"POST",r));try{let m=await w(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 ar(){let n=new Uint8Array(32);return crypto.getRandomValues(n),C(n.buffer)}async function cr(n){let r=new TextEncoder().encode(n),e=await crypto.subtle.digest("SHA-256",r);return C(e)}function lr(){let n=new Uint8Array(16);return crypto.getRandomValues(n),C(n.buffer)}function ur(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 C(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 k(n){return typeof n=="string"?n:null}function T(n){return Array.isArray(n)?n.filter(r=>typeof r=="string"):null}export{Le as AmbiguousReferenceRule,le as BooleanStatement,f as BrowserCredentialBackend,R as BrowserOAuthFlow,Ye as ClassDefinitionRule,Ue as ClassHierarchyCycleRule,ee as DefinedKanonak,He as DefinitionPropertyReferenceRule,ke as EdgeType,te as EmbeddedKanonak,Te as EmbeddedKanonakTypeRule,de as EmbeddedStatement,he as GraphBuilder,Y as HttpKanonakDocumentRepository,Ie as ImportExistenceRule,q as InMemoryKanonakDocumentRepository,F as KANONAK_USER_AGENT,Z as Kanonak,be as KanonakDocumentPositions,me as KanonakObjectParser,er as KanonakObjectValidator,L as KanonakParser,ne as KanonakUri,Se as KanonakUriBuilder,pe as ListStatement,Ze as MarkdownLinkRule,ye as MarkdownStatement,ze as NamespaceImportCycleRule,_e as NamespacePrefixRule,we as NodeType,ce as NumberStatement,We as ObjectPropertyImportRule,Ge as ObjectPropertyValueValidationRule,Ce as OntologyValidationError,De as OntologyValidationResult,Xe as PropertyDomainRule,Ve as PropertyHierarchyCycleRule,Ke as PropertyMetadata,Fe as PropertyRangeReferenceRule,$e as PropertyRangeRequiredRule,ve as PropertyTypeSpecificityRule,Qe as PropertyValueTypeRule,X as PublisherConfigResolver,Q as PublisherIndex,oe as ReferenceKanonak,ue as ReferenceStatement,je as ResourceNamingRule,ge as ResourceResolver,Pe as ResourceTypeClassifier,ie as ScalarStatement,se as Statement,ae as StringStatement,Me as SubClassOfReferenceRule,Ne as SubPropertyOfReferenceRule,re as SubjectKanonak,Ae as SubjectKanonakTypeRequiredRule,fe as TypeResolver,Je as UnresolvedPredicateRule,Oe as UnresolvedReferenceRule,Ee as ValidationContext,Be as ValidationSeverity,qe as XsdImportRule,S as browserServerSupportsDPoP,tr as buildOntologyModel,U as compareVersions,x as createBrowserDPoPProof,M as createVersion,rr as findDerivation,Re as findInstancesByType,$ as formatVersion,K as generateBrowserDPoPKeyPair,A as generateBrowserDPoPKeys,G as getKanonakUserAgent,_ as hasValidToken,b as importDPoPKeys,z as isCompatibleVersion,E as isExpired,J as isMajorCompatible,w as kanonakFetch,d as normalizeHost,N as parseVersionString,xe as parseWithPositions,H as pickHighestDocument,W as setKanonakUserAgent,V as versionsEqual};
|
|
@@ -1,24 +1,20 @@
|
|
|
1
1
|
import { type Kanonak } from '../kanonaks/index.js';
|
|
2
2
|
import { type CanonicalInput } from './InputModel.js';
|
|
3
3
|
/**
|
|
4
|
-
* The frozen canonical-form version
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* and lets a consumer record which form produced an address.
|
|
4
|
+
* The frozen canonical-form version, re-exported from the library so the SDK
|
|
5
|
+
* surface is unchanged. It is NOT part of the hashed bytes; it stamps the
|
|
6
|
+
* golden-vector fixtures and lets a consumer record which form produced an
|
|
7
|
+
* address.
|
|
9
8
|
*/
|
|
10
|
-
export
|
|
9
|
+
export { CANONICAL_FORM_VERSION } from '@kanonak-protocol/canonical';
|
|
11
10
|
/**
|
|
12
11
|
* Render a parsed kanonak collection into its canonical JSON form.
|
|
13
12
|
*
|
|
14
|
-
* `kanonaks` should be the `SubjectKanonak` instances from a single
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* Returns the JSON string (no trailing newline). Identical inputs
|
|
21
|
-
* always produce byte-identical output.
|
|
13
|
+
* `kanonaks` should be the `SubjectKanonak` instances from a single package —
|
|
14
|
+
* typically the result of `KanonakObjectParser.parseKanonaks` over a
|
|
15
|
+
* `SingleDocumentRepository`. Embedded, reference, and literal kanonaks are
|
|
16
|
+
* walked through subjects' statement trees; they don't count as top-level
|
|
17
|
+
* subjects. Identical inputs always produce byte-identical output.
|
|
22
18
|
*/
|
|
23
19
|
export declare function canonicalForm(kanonaks: Kanonak[]): string;
|
|
24
20
|
/**
|
|
@@ -28,9 +24,9 @@ export declare function canonicalForm(kanonaks: Kanonak[]): string;
|
|
|
28
24
|
*/
|
|
29
25
|
export declare function canonicalForm(input: CanonicalInput): string;
|
|
30
26
|
/**
|
|
31
|
-
* SHA-256 of the canonical form, prefixed `sha256:`. The output is
|
|
32
|
-
*
|
|
33
|
-
*
|
|
27
|
+
* SHA-256 of the canonical form, prefixed `sha256:`. The output is 71 characters
|
|
28
|
+
* (`sha256:` + 64 hex digits) and matches the convention used by `kanonak.lock`
|
|
29
|
+
* integrity entries.
|
|
34
30
|
*/
|
|
35
31
|
export declare function canonicalHash(kanonaks: Kanonak[]): string;
|
|
36
32
|
/** SHA-256 of the canonical form of a {@link CanonicalInput} model (issue #56). */
|
|
@@ -1,98 +1,24 @@
|
|
|
1
|
-
import type { EntityUri } from '../uri-helpers/index.js';
|
|
2
1
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* SDK adapter over `@kanonak-protocol/canonical`'s datatype layer.
|
|
3
|
+
*
|
|
4
|
+
* The frozen carrier routing and the per-carrier canonical lexical forms — the
|
|
5
|
+
* normative heart of `canonicalFormVersion "1"` — now live in exactly one place,
|
|
6
|
+
* the published `@kanonak-protocol/canonical` library, verified byte-for-byte
|
|
7
|
+
* against the shared golden vectors. This module no longer carries a copy; it
|
|
8
|
+
* only re-exposes `Carrier` on the SDK surface and adds the SDK-shaped
|
|
9
|
+
* `carrierOf` that classifies a datatype given as an {@link EntityUri} object
|
|
10
|
+
* (the form the parser and resolver carry) by delegating to the library's
|
|
11
|
+
* string-keyed `carrierOf`.
|
|
6
12
|
*/
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
Double = "double",
|
|
11
|
-
Float = "float",
|
|
12
|
-
Boolean = "boolean",
|
|
13
|
-
String = "string",
|
|
14
|
-
AnyUri = "anyURI",
|
|
15
|
-
LangString = "langString",
|
|
16
|
-
DateTime = "dateTime",
|
|
17
|
-
Date = "date",
|
|
18
|
-
Time = "time",
|
|
19
|
-
HexBinary = "hexBinary",
|
|
20
|
-
Base64Binary = "base64Binary"
|
|
21
|
-
}
|
|
13
|
+
import type { EntityUri } from '../uri-helpers/index.js';
|
|
14
|
+
import { Carrier } from '@kanonak-protocol/canonical';
|
|
15
|
+
export { Carrier };
|
|
22
16
|
/**
|
|
23
|
-
* The carrier for a datatype, or `undefined`
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* carrier.
|
|
17
|
+
* The carrier for a datatype identified by an {@link EntityUri}, or `undefined`
|
|
18
|
+
* if it is outside the canonicalized set. Builds the `publisher/package/name`
|
|
19
|
+
* key the library classifies on — a datatype's version never affects its
|
|
20
|
+
* carrier identity, so it is omitted. The routing itself (the whole integer
|
|
21
|
+
* tree → {@link Carrier.Integer}, `normalizedString`/`token` → {@link
|
|
22
|
+
* Carrier.String}, etc.) is the library's frozen contract.
|
|
27
23
|
*/
|
|
28
24
|
export declare function carrierOf(datatype: EntityUri): Carrier | undefined;
|
|
29
|
-
/**
|
|
30
|
-
* Canonical `xsd:integer` (and every derived integer): optional `-`, digits
|
|
31
|
-
* with no leading zeros, `0` for zero, never `-0`, never a leading `+`.
|
|
32
|
-
* Backed by `BigInt` so values beyond 2^53 (e.g. epoch-nanoseconds) are exact.
|
|
33
|
-
*/
|
|
34
|
-
export declare function canonicalInteger(raw: string): string;
|
|
35
|
-
/**
|
|
36
|
-
* Canonical `xsd:decimal`: value-based minimal form. Optional `-`, integer part
|
|
37
|
-
* with no leading zeros (`0` if zero), then `.`+fraction only when the fraction
|
|
38
|
-
* is non-zero, with no trailing zeros. `1.10 → 1.1`, `1.00 → 1`, `0.10 → 0.1`,
|
|
39
|
-
* `-0 → 0`, `-0.00 → 0`. Pure string arithmetic — never parsed to a double.
|
|
40
|
-
*/
|
|
41
|
-
export declare function canonicalDecimal(raw: string): string;
|
|
42
|
-
/** Canonical `xsd:double` — shortest round-tripping decimal; INF / -INF / NaN. */
|
|
43
|
-
export declare function canonicalDouble(raw: string): string;
|
|
44
|
-
/**
|
|
45
|
-
* Canonical `xsd:float` — like {@link canonicalDouble} but the value is first
|
|
46
|
-
* rounded to IEEE single precision (`Math.fround`). NOTE: exact cross-language
|
|
47
|
-
* agreement on shortest-float32 strings is a known sharp edge to lock against
|
|
48
|
-
* the golden vectors; representative values agree.
|
|
49
|
-
*/
|
|
50
|
-
export declare function canonicalFloat(raw: string): string;
|
|
51
|
-
/** Canonical `xsd:boolean`: `true` / `false`. Accepts the `1`/`0` lexicals. */
|
|
52
|
-
export declare function canonicalBoolean(raw: string): string;
|
|
53
|
-
/** Canonical string value: Unicode NFC. No whitespace collapse (that's a facet). */
|
|
54
|
-
export declare function canonicalString(raw: string): string;
|
|
55
|
-
/** Canonical `xsd:anyURI`: NFC (distinct carrier/tag from string, same lexical rule). */
|
|
56
|
-
export declare function canonicalAnyUri(raw: string): string;
|
|
57
|
-
/**
|
|
58
|
-
* Canonical `rdf:langString`: NFC value + BCP 47 canonical-CASE language tag
|
|
59
|
-
* (language lowercase, script titlecase, region uppercase) — `"hi"@EN-us`
|
|
60
|
-
* becomes `("hi", "en-US")`. Case only; no IANA registry / preferred-value
|
|
61
|
-
* substitution. Returns the pair; the canonical form serializes both.
|
|
62
|
-
*/
|
|
63
|
-
export declare function canonicalLangString(value: string, lang: string): {
|
|
64
|
-
value: string;
|
|
65
|
-
lang: string;
|
|
66
|
-
};
|
|
67
|
-
/** BCP 47 canonical case by subtag position. */
|
|
68
|
-
export declare function canonicalLanguageTag(tag: string): string;
|
|
69
|
-
/** Canonical `xsd:hexBinary`: uppercase hex digits, even length. */
|
|
70
|
-
export declare function canonicalHexBinary(raw: string): string;
|
|
71
|
-
/**
|
|
72
|
-
* Canonical `xsd:base64Binary`: RFC 4648 standard alphabet, canonical padding,
|
|
73
|
-
* no line breaks. Decodes (tolerating XSD-permitted internal whitespace) then
|
|
74
|
-
* re-encodes, so any padding/line-wrap variant of the same bytes collapses.
|
|
75
|
-
*/
|
|
76
|
-
export declare function canonicalBase64(raw: string): string;
|
|
77
|
-
/**
|
|
78
|
-
* Canonical `xsd:dateTime`. Offset-bearing → shifted to UTC `Z` (instant
|
|
79
|
-
* equality, so `13:00:00+01:00` and `12:00:00Z` collide). Timezone-less →
|
|
80
|
-
* floating: canonical lexical form, no `Z`, distinct from any zoned instant.
|
|
81
|
-
* Fractional seconds are preserved at arbitrary precision (only trailing zeros
|
|
82
|
-
* trimmed) and never participate in the offset shift.
|
|
83
|
-
*/
|
|
84
|
-
export declare function canonicalDateTime(raw: string): string;
|
|
85
|
-
/**
|
|
86
|
-
* Canonical `xsd:date`: lexical only — canonical year width + canonical
|
|
87
|
-
* timezone spelling, NO UTC shift (a date is not an instant; shifting could
|
|
88
|
-
* cross midnight). Timezone-less stays distinct from a zoned date.
|
|
89
|
-
*/
|
|
90
|
-
export declare function canonicalDate(raw: string): string;
|
|
91
|
-
/**
|
|
92
|
-
* Canonical `xsd:time`: lexical only — arbitrary-precision fractional seconds,
|
|
93
|
-
* canonical timezone spelling, NO UTC shift. `24:00:00` normalizes to
|
|
94
|
-
* `00:00:00` (XSD value-space equivalence within a day).
|
|
95
|
-
*/
|
|
96
|
-
export declare function canonicalTime(raw: string): string;
|
|
97
|
-
/** Canonical lexical form of a raw token under a carrier. Throws on malformed input. */
|
|
98
|
-
export declare function canonicalScalarLexical(carrier: Carrier, raw: string): string;
|
|
@@ -1,54 +1,17 @@
|
|
|
1
|
-
import type { Kanonak } from '../kanonaks/Kanonak.js';
|
|
2
1
|
/**
|
|
3
2
|
* The language-neutral canonical INPUT model (issue #56) — the one
|
|
4
3
|
* cross-language contract a codec builds to content-address a typed object,
|
|
5
4
|
* carrying datatypes explicitly so canonicalization needs no parser. It is
|
|
6
5
|
* exactly the shape `full-form-vectors.json` is defined over and `kanonak hash
|
|
7
|
-
* -v` emits.
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
* -v` emits.
|
|
7
|
+
*
|
|
8
|
+
* The types are re-exported from `@kanonak-protocol/canonical`, the single home
|
|
9
|
+
* of the frozen canonical form, so the SDK surface is unchanged for existing
|
|
10
|
+
* consumers while the definition lives in exactly one place. The SDK keeps the
|
|
11
|
+
* {@link isCanonicalInput} discriminator the public `canonicalForm` /
|
|
12
|
+
* `canonicalHash` overloads use to tell a `CanonicalInput` from a `Kanonak[]`.
|
|
10
13
|
*/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
export interface CanonicalInputSubject {
|
|
15
|
-
/** The subject's canonical URI, e.g. `publisher/package@1.0.0/Name`. */
|
|
16
|
-
uri: string;
|
|
17
|
-
statements: CanonicalInputStatement[];
|
|
18
|
-
}
|
|
19
|
-
export interface CanonicalInputStatement {
|
|
20
|
-
/** The predicate's canonical URI. */
|
|
21
|
-
predicate: string;
|
|
22
|
-
value: CanonicalInputValue;
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* A value: a typed scalar (`lit` + its `datatype` URI), an untyped/open-world
|
|
26
|
-
* scalar (`raw` token, no carrier), a reference, an embedded node, or a list.
|
|
27
|
-
*/
|
|
28
|
-
export type CanonicalInputValue = {
|
|
29
|
-
lit: string;
|
|
30
|
-
datatype: string;
|
|
31
|
-
} | {
|
|
32
|
-
raw: string;
|
|
33
|
-
} | {
|
|
34
|
-
ref: string;
|
|
35
|
-
} | {
|
|
36
|
-
embed: {
|
|
37
|
-
name?: string;
|
|
38
|
-
statements: CanonicalInputStatement[];
|
|
39
|
-
};
|
|
40
|
-
} | {
|
|
41
|
-
list: CanonicalInputValue[];
|
|
42
|
-
};
|
|
14
|
+
import type { CanonicalInput } from '@kanonak-protocol/canonical';
|
|
15
|
+
export type { CanonicalInput, CanonicalInputSubject, CanonicalInputStatement, CanonicalInputValue, } from '@kanonak-protocol/canonical';
|
|
43
16
|
/** Discriminate a `CanonicalInput` from a `Kanonak[]` (for the public overload). */
|
|
44
17
|
export declare function isCanonicalInput(arg: unknown): arg is CanonicalInput;
|
|
45
|
-
/**
|
|
46
|
-
* Build the SDK object model the canonical form consumes from a `CanonicalInput`.
|
|
47
|
-
* Datatypes are classified by their URI via {@link carrierOf} (the same routing
|
|
48
|
-
* the parser uses); predicate/reference URIs resolve through the canonical URI
|
|
49
|
-
* parser; a typed scalar carries `(carrier, lexical)`, an untyped one its raw
|
|
50
|
-
* token. The canonical form reads `(carrier, lexical)` off any scalar statement,
|
|
51
|
-
* so a single `StringStatement` faithfully represents every scalar carrier —
|
|
52
|
-
* producing bytes identical to the parsed-model path for equivalent content.
|
|
53
|
-
*/
|
|
54
|
-
export declare function buildModelFromInput(input: CanonicalInput): Kanonak[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as N}from"./chunk-NJ3AZYQD.js";import{b as V,c as C,i as B,j as M}from"./chunk-7HRKWTBB.js";import{a as _,b as U,c as S,d as k,g as P,h as x,i as O,j as I,k as R,l as v}from"./chunk-4UT2CLAT.js";import{j as $}from"./chunk-2ACBWC7K.js";var w=class extends U{name};var K=class extends _{value;carrier;lexical};var D=class extends P{links=[]};import{Carrier as j,carrierOf as F}from"@kanonak-protocol/canonical";function T(p){return F(`${p.publisher}/${p.package_}/${p.name}`)}var Y=/\[\[([^\[\]\n]+)\]\]/g,G=/\[\[/g,z=/```[\s\S]*?```|`[^`\n]*`/g;function q(p){let e=[];for(let t of p.matchAll(z))e.push([t.index,t.index+t[0].length]);return e}function ae(p){if(!p||!p.includes("[["))return[];let e=q(p),t=s=>e.some(([r,i])=>s>=r&&s<i),a=new Set(E(p).map(s=>s.startOffset)),n=[];for(let s of p.matchAll(G)){let r=s.index;if(t(r)||a.has(r))continue;let i=p.slice(r,r+48).replace(/\s+/g," ").trim();n.push({startOffset:r,snippet:i})}return n}function E(p){if(!p||!p.includes("[["))return[];let e=[];for(let n of p.matchAll(z))e.push([n.index,n.index+n[0].length]);let t=n=>e.some(([s,r])=>n>=s&&n<r),a=[];for(let n of p.matchAll(Y)){let s=n.index;if(t(s))continue;let r=n[1],i=r.indexOf("|"),c=(i===-1?r:r.slice(0,i)).trim();if(c.length===0)continue;let f=i===-1?"":r.slice(i+1).trim(),g={reference:c,startOffset:s,endOffset:s+n[0].length};f.length>0&&(g.displayText=f),a.push(g)}return a}var X=class{constructor(e){}async parseKanonaks(e){let t=[],a=await e.getAllDocumentsAsync(),n=new V(e),s=new C(n);for(let o of a){let m=o.metadata.namespace_?.toString()??"";for(let[u,y]of Object.entries(o.body)){let d=new S,b=this.resolveCanonicalEntity(u,o,m);d.namespace=b.namespace,d.name=b.name,d.statement=[];let h=await this.parseStatements(y,o,n,s,e);d.statement.push(...h.statements),d.unresolvedPredicates=h.unresolved,t.push(d)}}let r=new Map,i=new Map,c=[];for(let o of t)if(o instanceof S){let m=`${o.namespace}/${o.name}`,u=r.get(m);if(u){let y=i.get(m);for(let d of o.statement){let b=L(d);y.has(b)||(y.add(b),u.statement.push(d))}for(let d of o.unresolvedPredicates)u.unresolvedPredicates.some(b=>b.key===d.key&&b.sourceDoc===d.sourceDoc)||u.unresolvedPredicates.push(d)}else{let y=new Set,d=[];for(let b of o.statement){let h=L(b);y.has(h)||(y.add(h),d.push(b))}o.statement=d,i.set(m,y),r.set(m,o),c.push(o)}}else c.push(o);let f=new Set;for(let o of c)if(o instanceof S){let m=o.namespace||"",u=m.indexOf("/"),y=u>=0?m.slice(0,u):"",d=u>=0?m.slice(u+1):"",b=d.indexOf("@"),h=b>=0?d.slice(0,b):d;f.add(`${y}/${h}/${o.name}`)}let g=o=>f.has(`${o.publisher}/${o.package_}/${o.name}`),l=new Map;for(let o of["core-rdf","core-owl","core-kanonak"]){let m=await e.getDocumentsByNamespaceAsync("kanonak.org",o);l.set(o,$(m).chosen?.metadata.namespace_?.version??void 0)}for(let o of c)o instanceof S&&this.canonicalizeStatementBuiltins(o.statement,g,l);return c}canonicalizeStatementBuiltins(e,t,a){for(let n of e){let s=n.predicate?.subject;if(M(s,t,a),n instanceof I)n.object instanceof k&&M(n.object.subject,t,a);else if(n instanceof R)n.object&&this.canonicalizeStatementBuiltins(n.object.statement,t,a);else if(n instanceof v)for(let r of n.object??[])r instanceof k?M(r.subject,t,a):r instanceof w&&this.canonicalizeStatementBuiltins(r.statement,t,a)}}resolveCanonicalEntity(e,t,a){if(!e.includes(".")||!t.metadata?.imports)return{namespace:a,name:e};let n=e.indexOf("."),s=e.substring(0,n),r=e.substring(n+1);for(let[i,c]of Object.entries(t.metadata.imports))for(let f of c)if((f.alias??f.packageName)===s){let l=f.version;return{namespace:`${i}/${f.packageName}@${l.major}.${l.minor}.${l.patch}`,name:r}}return{namespace:a,name:e}}async parseStatements(e,t,a,n,s){let r=[],i=[];if(typeof e!="object"||e===null||Array.isArray(e))return{statements:r,unresolved:i};let c=t.metadata.namespace_?.toString()??"";for(let[f,g]of Object.entries(e))try{let l=await this.getPropertyMetadata(f,t,a,s,n);if(!l){let m=f.includes(".")?f.slice(f.lastIndexOf(".")+1):f;B(m)||i.push({key:f,sourceDoc:c});continue}let o=await this.parsePropertyValue(f,g,l,t,a,n,s);o&&r.push(o)}catch(l){throw new Error(`Failed to parse property '${f}': ${l.message}`,{cause:l})}return{statements:r,unresolved:i}}async getPropertyMetadata(e,t,a,n,s){let r=await a.resolveEntityAsync(e,t);if(!r)return;let i=r.entity,c=i.type?.toString()??"",f=c.includes(".")?c.substring(c.lastIndexOf(".")+1):c;if(!new Set(["Property","DatatypeProperty","ObjectProperty","AnnotationProperty"]).has(f))return;let l=s.getPropertyTypeClassification(c),o=i.range?.toString(),m;if(l==="ObjectProperty")m="ObjectProperty";else if(l==="DatatypeProperty")m="DatatypeProperty";else{let d=o&&o.includes(".")?o.substring(o.lastIndexOf(".")+1):o??"";(o?s.isKnownXsdDatatypeName(o):!1)||d==="Literal"?m="DatatypeProperty":m="ObjectProperty"}let u;if(o){let d=t;if(r.isImported&&r.definedInNamespace){if(typeof n.getDocumentAsync!="function")throw new Error(`Cannot resolve the range of imported property '${e}': the parse repository cannot fetch defining document '${r.definedInNamespace}'. Thread the real repository through to embedded-object parsing \u2014 no stub, no fallback.`);let h=await n.getDocumentAsync(r.definedInNamespace);if(!h)throw new Error(`Cannot resolve the range of imported property '${e}': defining document '${r.definedInNamespace}' was not found in the repository.`);d=h}u=(await a.resolveEntityAsync(o,d))?.uri}return{propertyUri:r.uri.toString(),propertyType:m,range:o,rangeUri:u,isImported:r.isImported,definedInNamespace:r.definedInNamespace}}async parsePropertyValue(e,t,a,n,s,r,i){let c=a.propertyUri;if(t!=null){if(Array.isArray(t))return this.parseListValue(c,t,a,n,s,r,i);if(a.propertyType==="DatatypeProperty")return this.parseDatatypeValue(c,t,a,n,s,r);if(a.propertyType==="ObjectProperty")return this.parseObjectValue(c,t,a,n,s,r,i)}}async parseDatatypeValue(e,t,a,n,s,r){let i;if(typeof t=="string"){if(r.isSubstitutableDatatype(a.rangeUri))return await this.parseSubstitutableValue(e,t,n,s);i=t}else if(typeof t=="number"||typeof t=="boolean")i=String(t);else return;return this.typedScalarStatement(e,i,a)}typedScalarStatement(e,t,a){let n=k.parse(e),s=a.rangeUri?T(a.rangeUri):void 0;if(s===j.Boolean){let i=new O;return i.predicate=n,i.object=t==="true"||t==="1",i.carrier=s,i.lexical=t,i}if(s===j.Integer||s===j.Decimal||s===j.Double||s===j.Float){let i=new x;return i.predicate=n,i.object=Number(t),i.carrier=s,i.lexical=t,i}let r=P.parse(e,t);return s&&(r.carrier=s,r.lexical=t),r}typedListLiteral(e,t){let a=new K,n=t.rangeUri?T(t.rangeUri):void 0;return n===j.Boolean?a.value=e==="true"||e==="1":n===j.Integer||n===j.Decimal||n===j.Double||n===j.Float?a.value=Number(e):a.value=e,n&&(a.carrier=n,a.lexical=e),a}async parseSubstitutableValue(e,t,a,n){let s=new D;s.predicate=k.parse(e),s.object=t;for(let r of E(t)){let i=await n.resolveEntityAsync(r.reference,a),c;i&&(c=new k,c.subject=i.uri);let f={reference:r.reference,startOffset:r.startOffset,endOffset:r.endOffset};r.displayText!==void 0&&(f.displayText=r.displayText),c!==void 0&&(f.target=c),s.links.push(f)}return s}async parseObjectValue(e,t,a,n,s,r,i){if(typeof t=="string"){let c=await this.resolveReference(t,n,s);if(!c)return;let f=new I;return f.predicate=k.parse(e),f.object=c,f}if(typeof t=="object"&&!Array.isArray(t)){let c=await this.parseStatements(t,n,s,r,i);if(c.statements.length>0){let l=new w;l.statement=c.statements,l.unresolvedPredicates=c.unresolved;let o=new R;return o.predicate=k.parse(e),o.object=l,o}let f=[];for(let[l,o]of Object.entries(t))if(typeof o=="object"&&o!==null&&!Array.isArray(o)){let m=new w;m.name=l;let u=await this.parseStatements(o,n,s,r,i);m.statement=u.statements,m.unresolvedPredicates=u.unresolved,f.push(m)}else if(typeof o=="string"){let m=await this.resolveReference(o,n,s);m&&f.push(m)}if(f.length>0){let l=new v;return l.predicate=k.parse(e),l.object=f,l}let g=new R;return g.predicate=k.parse(e),g.object=new w,g}}async parseListValue(e,t,a,n,s,r,i){let c=[],f=a.propertyType==="DatatypeProperty",g=a.rangeUri?.publisher==="kanonak.org"&&a.rangeUri?.package_==="core-rdf"&&a.rangeUri?.name==="List"||!a.rangeUri&&(a.range?.includes(".")?a.range.substring(a.range.lastIndexOf(".")+1):a.range)==="List";for(let o of t){let m=typeof o=="string"||typeof o=="number"||typeof o=="boolean";if(f&&m){let u=typeof o=="string"?o:String(o);c.push(this.typedListLiteral(u,a));continue}if(g&&m){if(typeof o=="string"){let u=await s.resolveEntityAsync(o,n);if(u){let y=new k;y.subject=u.uri,c.push(y)}else{let y=new K;y.value=o,c.push(y)}}else{let u=new K;u.value=o,c.push(u)}continue}if(typeof o=="string"){let u=await this.resolveReference(o,n,s);u&&c.push(u)}else if(typeof o=="object"&&o!==null&&!Array.isArray(o)){let u=new w,y=await this.parseStatements(o,n,s,r,i);u.statement=y.statements,u.unresolvedPredicates=y.unresolved,c.push(u)}}let l=new v;return l.predicate=k.parse(e),l.object=c,l}async resolveReference(e,t,a){let n=await a.resolveEntityAsync(e,t);if(n){let r=new k;return r.subject=n.uri,r}let s=t.metadata?.namespace_;if(s){let{KanonakUri:r}=await import("./KanonakUri-4VJGV3FN.js");if(e.includes(".")){let c=e.indexOf("."),f=e.substring(0,c),g=e.substring(c+1);if(t.metadata?.imports){for(let[l,o]of Object.entries(t.metadata.imports))for(let m of o)if((m.alias??m.packageName)===f){let y=new k;return y.subject=new r(l,m.packageName,g,m.version),y}}}let i=new k;return i.subject=new r(s.publisher,s.package_,e,s.version??void 0),i}return null}async saveKanonaks(e,t){let a=new Map;for(let n of e)n instanceof S&&n.namespace&&(a.has(n.namespace)||a.set(n.namespace,[]),a.get(n.namespace).push(n));for(let[n,s]of a){let r=await this.convertKanonaksToDocument(n,s),i=`${n.split("@")[0]}.yml`;await t.saveDocumentAsync(r,i)}}async serializeToYaml(e,t){let a=e.filter(r=>r instanceof S&&r.namespace===t);if(a.length===0)throw new Error(`No kanonaks found with namespace '${t}'`);let n=await this.convertKanonaksToDocument(t,a);return new N().save(n)}async convertKanonaksToDocument(e,t){let n={metadata:{namespace_:e,get allImports(){if(!this.imports)return[];let r=[];for(let i of Object.values(this.imports))r.push(...i);return r}},body:{}},s=new Map;for(let r of t){let i={};for(let c of r.statement){let[f,g]=this.convertStatementToProperty(c);f&&g!==null&&g!==void 0&&(i[f]=g),this.collectImportsFromStatement(c,e,s)}n.body[r.name]=i}return n}convertStatementToProperty(e){if(e instanceof P)return[e.predicate.subject.name,e.object];if(e instanceof x)return[e.predicate.subject.name,e.object];if(e instanceof O)return[e.predicate.subject.name,e.object];if(e instanceof I)return[e.predicate.subject.name,e.object.subject.name];if(e instanceof v){let t=this.convertKanonakListToValue(e.object);return[e.predicate.subject.name,t]}else if(e instanceof R){let t=this.convertEmbeddedKanonakToValue(e.object);return[e.predicate.subject.name,t]}return[null,null]}convertKanonakListToValue(e){let t=[];for(let a of e)a instanceof k?t.push(a.subject.name):a instanceof w&&t.push(this.convertEmbeddedKanonakToValue(a));return t}convertEmbeddedKanonakToValue(e){let t={};for(let a of e.statement){let[n,s]=this.convertStatementToProperty(a);n&&s!==null&&s!==void 0&&(t[n]=s)}return t}collectImportsFromStatement(e,t,a){}};function L(p){let e=p.predicate?.subject;return(e?`${e.publisher}/${e.package_}/${e.name}`:"?")+"="+H(p)}function H(p){return p instanceof D?"m:"+String(p.object):p instanceof P?"s:"+String(p.object):p instanceof x?"n:"+String(p.object):p instanceof O?"b:"+String(p.object):p instanceof I?"r:"+A(p.object):p instanceof R?"e:"+A(p.object):p instanceof v?"l:["+(p.object??[]).map(A).join("|")+"]":"x"}function A(p){if(!p)return"";if(p instanceof k){let e=p.subject;return"R("+(e?`${e.publisher}/${e.package_}/${e.name}`:"")+")"}return p instanceof w?"E("+(p.statement??[]).map(L).join(";")+")":p instanceof K?"L("+String(p.value)+")":"N"}export{w as a,K as b,D as c,j as d,T as e,ae as f,E as g,X as h};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as j,b as x,
|
|
1
|
+
import{a as j,b as x,h as _}from"./chunk-BKVPSPG4.js";import{d as l,e as u,f as b,g as $,h as s,k as h}from"./chunk-7HRKWTBB.js";import{c as S,d as O,g as I,h as T,i as g,j as v,k as L,l as q}from"./chunk-4UT2CLAT.js";var d=class{all=new Set;byPIdx=new Map;bySPIdx=new Map;byPOIdx=new Map;tripleList=[];add(e){let t=b(e);return this.all.has(t)?!1:(this.all.add(t),this.tripleList.push(e),P(this.byPIdx,e.p,e),P(this.bySPIdx,`${e.s}|${e.p}`,e),e.o.kind==="uri"&&P(this.byPOIdx,`${e.p}|${e.o.key}`,e),!0)}has(e){return this.all.has(b(e))}size(){return this.tripleList.length}snapshot(){return this.tripleList.slice()}byPredicate(e){let t=this.byPIdx.get(e);return t?t.slice():[]}bySubjectPredicate(e,t){let r=this.bySPIdx.get(`${e}|${t}`);return r?r.slice():[]}byPredicateObject(e,t){let r=this.byPOIdx.get(`${e}|${t}`);return r?r.slice():[]}subjectsWithPredicateObject(e,t){let r=this.byPOIdx.get(`${e}|${t}`);if(!r)return[];let n=new Set;for(let a of r)n.add(a.s);return Array.from(n)}uriObjectsOf(e,t){let r=this.bySPIdx.get(`${e}|${t}`);if(!r)return[];let n=new Set;for(let a of r)a.o.kind==="uri"&&n.add(a.o.key);return Array.from(n)}hasUri(e,t,r){return this.all.has(`${e}|${t}|u:${r}`)}hasTriple(e,t,r){return this.all.has(`${e}|${t}|${$(r)}`)}};function P(o,e,t){let r=o.get(e);r?r.push(t):o.set(e,[t])}var w={name:"rdfs2",apply(o,e){let t=!1;for(let r of o.byPredicate(e.domain)){if(r.o.kind!=="uri")continue;let n=r.s,a=r.o.key;for(let i of o.byPredicate(n))o.add(s(i.s,e.type,a))&&(t=!0)}return t}},C={name:"rdfs3",apply(o,e){let t=!1;for(let r of o.byPredicate(e.range)){if(r.o.kind!=="uri")continue;let n=r.s,a=r.o.key;for(let i of o.byPredicate(n))i.o.kind==="uri"&&o.add(s(i.o.key,e.type,a))&&(t=!0)}return t}},A={name:"rdfs5",apply(o,e){let t=!1;for(let r of o.byPredicate(e.subPropertyOf)){if(r.o.kind!=="uri")continue;let n=r.s,a=r.o.key;for(let i of o.bySubjectPredicate(a,e.subPropertyOf))i.o.kind==="uri"&&o.add(s(n,e.subPropertyOf,i.o.key))&&(t=!0)}return t}},V={name:"rdfs7",apply(o,e){let t=!1;for(let r of o.byPredicate(e.subPropertyOf)){if(r.o.kind!=="uri")continue;let n=r.s,a=r.o.key;if(n!==a)for(let i of o.byPredicate(n)){let f={s:i.s,p:a,o:i.o};o.add(f)&&(t=!0)}}return t}},W={name:"rdfs9",apply(o,e){let t=!1;for(let r of o.byPredicate(e.subClassOf)){if(r.o.kind!=="uri")continue;let n=r.s,a=r.o.key;if(n!==a)for(let i of o.byPredicateObject(e.type,n))o.add(s(i.s,e.type,a))&&(t=!0)}return t}},F={name:"rdfs11",apply(o,e){let t=!1;for(let r of o.byPredicate(e.subClassOf)){if(r.o.kind!=="uri")continue;let n=r.s,a=r.o.key;for(let i of o.bySubjectPredicate(a,e.subClassOf))i.o.kind==="uri"&&o.add(s(n,e.subClassOf,i.o.key))&&(t=!0)}return t}},k=[w,C,A,V,W,F];var N={name:"prp-trp",apply(o,e){let t=!1,r=o.subjectsWithPredicateObject(e.type,e.transitiveProperty);for(let n of r){let a=o.byPredicate(n);for(let i of a){if(i.o.kind!=="uri")continue;let f=i.o.key;for(let c of o.bySubjectPredicate(f,n))c.o.kind==="uri"&&i.s!==c.o.key&&o.add(s(i.s,n,c.o.key))&&(t=!0)}}return t}},D={name:"prp-symp",apply(o,e){let t=!1,r=o.subjectsWithPredicateObject(e.type,e.symmetricProperty);for(let n of r)for(let a of o.byPredicate(n))a.o.kind==="uri"&&o.add(s(a.o.key,n,a.s))&&(t=!0);return t}},z={name:"prp-inv1",apply(o,e){let t=!1;for(let r of o.byPredicate(e.inverseOf)){if(r.o.kind!=="uri")continue;let n=r.s,a=r.o.key;for(let i of o.byPredicate(n))i.o.kind==="uri"&&o.add(s(i.o.key,a,i.s))&&(t=!0)}return t}},B={name:"prp-inv2",apply(o,e){let t=!1;for(let r of o.byPredicate(e.inverseOf)){if(r.o.kind!=="uri")continue;let n=r.s,a=r.o.key;for(let i of o.byPredicate(a))i.o.kind==="uri"&&o.add(s(i.o.key,n,i.s))&&(t=!0)}return t}},M={name:"prp-eqp1",apply(o,e){let t=!1;for(let r of o.byPredicate(e.equivalentProperty)){if(r.o.kind!=="uri")continue;let n=r.s,a=r.o.key;if(n!==a)for(let i of o.byPredicate(n))o.add({s:i.s,p:a,o:i.o})&&(t=!0)}return t}},G={name:"prp-eqp2",apply(o,e){let t=!1;for(let r of o.byPredicate(e.equivalentProperty)){if(r.o.kind!=="uri")continue;let n=r.s,a=r.o.key;if(n!==a)for(let i of o.byPredicate(a))o.add({s:i.s,p:n,o:i.o})&&(t=!0)}return t}},H={name:"cax-eqc1",apply(o,e){let t=!1;for(let r of o.byPredicate(e.equivalentClass)){if(r.o.kind!=="uri")continue;let n=r.s,a=r.o.key;if(n!==a)for(let i of o.byPredicateObject(e.type,n))o.add(s(i.s,e.type,a))&&(t=!0)}return t}},J={name:"cax-eqc2",apply(o,e){let t=!1;for(let r of o.byPredicate(e.equivalentClass)){if(r.o.kind!=="uri")continue;let n=r.s,a=r.o.key;if(n!==a)for(let i of o.byPredicateObject(e.type,a))o.add(s(i.s,e.type,n))&&(t=!0)}return t}},Q={name:"eq-rep-s",apply(o,e){let t=!1;for(let r of o.byPredicate(e.sameAs)){if(r.o.kind!=="uri")continue;let n=r.s,a=r.o.key;if(n!==a){for(let i of o.snapshot())i.s===n&&o.add({s:a,p:i.p,o:i.o})&&(t=!0);for(let i of o.snapshot())i.s===a&&o.add({s:n,p:i.p,o:i.o})&&(t=!0)}}return t}},X={name:"eq-rep-o",apply(o,e){let t=!1;for(let r of o.byPredicate(e.sameAs)){if(r.o.kind!=="uri")continue;let n=r.s,a=r.o.key;if(n!==a)for(let i of o.snapshot())i.o.kind==="uri"&&(i.o.key===n?o.add(s(i.s,i.p,a))&&(t=!0):i.o.key===a&&o.add(s(i.s,i.p,n))&&(t=!0))}return t}},K=[N,D,z,B,M,G,H,J,Q,X];var y=class{constructor(e,t){this.store=e;this.vocabulary=t}store;vocabulary;getInstancesOfClass(e){let t=p(e);return this.store.subjectsWithPredicateObject(this.vocabulary.type,t)}getSubclasses(e){let t=p(e);return this.store.subjectsWithPredicateObject(this.vocabulary.subClassOf,t).filter(n=>n!==t)}getSuperclasses(e){let t=p(e);return this.store.uriObjectsOf(t,this.vocabulary.subClassOf).filter(r=>r!==t)}getTypesOfIndividual(e){return this.store.uriObjectsOf(p(e),this.vocabulary.type)}isInstanceOf(e,t){return this.store.hasUri(p(e),this.vocabulary.type,p(t))}triples(){return this.store.snapshot()}size(){return this.store.size()}};function p(o){return typeof o=="string"?o:u(o.publisher,o.package_,o.name)}var R=class{vocabulary;profile;maxIterations;constructor(e={}){this.vocabulary=e.vocabulary??new h,this.profile=e.profile??"owl-rl-classification",this.maxIterations=e.maxIterations??100}async reason(e){let t=new d,n=await new _().parseKanonaks(e),a=new U;for(let c of n)if(c instanceof S){let m=Y(c);if(!m)continue;for(let E of c.statement)this.emitStatement(m,E,t,a)}let i=[...k];this.profile==="owl-rl-classification"&&i.push(...K);let f=0;for(;f<this.maxIterations;){let c=!1;for(let m of i)m.apply(t,this.vocabulary)&&(c=!0);if(!c)break;f++}return new y(t,this.vocabulary)}emitStatement(e,t,r,n){let a=Z(t);if(a){if(t instanceof I){r.add({s:e,p:a,o:{kind:"literal",lexical:t.object,datatype:"string"}});return}if(t instanceof T){r.add({s:e,p:a,o:{kind:"literal",lexical:String(t.object),datatype:"number"}});return}if(t instanceof g){r.add({s:e,p:a,o:{kind:"literal",lexical:String(t.object),datatype:"boolean"}});return}if(t instanceof v){let i=l(t.object.subject);r.add(s(e,a,i));return}if(t instanceof L){let i=n.next();r.add({s:e,p:a,o:{kind:"blank",id:i}}),this.emitEmbedded(i,t.object,r,n);return}if(t instanceof q){for(let i of t.object??[])this.emitListItem(e,a,i,r,n);return}}}emitListItem(e,t,r,n,a){if(r instanceof O)n.add(s(e,t,l(r.subject)));else if(r instanceof j){let i=a.next();n.add({s:e,p:t,o:{kind:"blank",id:i}}),this.emitEmbedded(i,r,n,a)}else if(r instanceof x){let i=typeof r.value=="number"?"number":typeof r.value=="boolean"?"boolean":"string";n.add({s:e,p:t,o:{kind:"literal",lexical:String(r.value),datatype:i}})}}emitEmbedded(e,t,r,n){let a=`_:${e}`;for(let i of t.statement)this.emitStatement(a,i,r,n)}},U=class{counter=0;next(){return`b${this.counter++}`}};function Y(o){let e=o.namespace??"",t=e.indexOf("@"),r=t===-1?e:e.substring(0,t),n=r.indexOf("/");if(n===-1)return null;let a=r.substring(0,n),i=r.substring(n+1);return!a||!i||!o.name?null:u(a,i,o.name)}function Z(o){let e=o.predicate;return e?.subject?l(e.subject):null}export{d as a,k as b,K as c,y as d,R as e};
|