@kanonak-protocol/sdk 3.70.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-EOMKFFKU.js → chunk-ATH6636H.js} +1 -1
- package/dist/{chunk-N224PFBI.js → chunk-BGQKZBNE.js} +1 -1
- package/dist/chunk-CRKSKIAL.js +1 -0
- package/dist/{chunk-W4LPC6VM.js → chunk-F5ANO7MJ.js} +1 -1
- package/dist/{chunk-2OXZDBHX.js → chunk-FX7JDGL6.js} +1 -1
- package/dist/chunk-G2DKKSZ4.js +1 -0
- package/dist/{chunk-6T2XFOMU.js → chunk-GN2XODVC.js} +1 -1
- package/dist/chunk-IOMNZBK4.js +1 -0
- package/dist/chunk-LKBG2MK6.js +2 -0
- package/dist/{chunk-C5NKFT7W.js → chunk-MCU5IAMS.js} +24 -24
- package/dist/chunk-RRODBYIK.js +74 -0
- package/dist/chunk-TJPQETHV.js +1 -0
- package/dist/{chunk-7ZCFYITD.js → chunk-Y7TGQ7UF.js} +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +26 -26
- package/dist/parsing/index.js +1 -1
- 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/reasoning/index.js +1 -1
- 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/resolution/index.js +1 -1
- package/dist/search/index.js +1 -1
- package/dist/server/assembleModel.d.ts +2 -0
- package/dist/server/index.js +2 -2
- package/dist/server/types.d.ts +9 -0
- package/dist/transformations/index.js +1 -1
- package/dist/uri-helpers/UriHelpers.d.ts +18 -0
- package/dist/uri-helpers/index.d.ts +1 -1
- package/dist/uri-helpers/index.js +1 -1
- package/dist/validation/TxExpressionPathChecker.d.ts +39 -0
- package/dist/validation/index.d.ts +1 -1
- package/dist/validation/index.js +1 -1
- package/dist/validation/rules/repository/LookSemanticSvgPathRule.d.ts +13 -23
- package/dist/validation/rules/repository/TxExpressionPathRule.d.ts +28 -0
- package/dist/validation/rules/repository/index.d.ts +1 -0
- package/dist/view/ViewMaterializer.d.ts +65 -0
- package/dist/view/index.d.ts +2 -0
- package/package.json +2 -2
- package/dist/chunk-64TVBQFR.js +0 -1
- package/dist/chunk-ORFSMEMM.js +0 -1
- package/dist/chunk-PODBS4IU.js +0 -1
- package/dist/chunk-Q4DKP5DO.js +0 -1
- package/dist/chunk-U75VPNYW.js +0 -2
- package/dist/chunk-XEFBKQY5.js +0 -64
|
@@ -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';
|
package/dist/reasoning/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as g,b as h,c as i,d as j,e as k}from"../chunk-
|
|
1
|
+
import{a as g,b as h,c as i,d as j,e as k}from"../chunk-FX7JDGL6.js";import"../chunk-G2DKKSZ4.js";import"../chunk-TJPQETHV.js";import{d as a,e as b,f as c,h as d,i as e,j as f}from"../chunk-IOMNZBK4.js";import"../chunk-W6T7MOKY.js";import"../chunk-FUUTGGJS.js";import"../chunk-2ACBWC7K.js";export{f as KanonakVocabulary,i as OWL_RL_CLASSIFICATION_RULES,h as RDFS_RULES,k as Reasoner,j as ReasoningResult,g as TripleStore,e as canonicalizeBuiltinUri,b as makeUriKey,c as tripleKey,a as uriKey,d as uriTriple};
|
|
@@ -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};
|
package/dist/resolution/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as p,b as x}from"../chunk-PEUTCG3B.js";import{a as s}from"../chunk-PEJALHXK.js";import{a as k}from"../chunk-SC5M74NM.js";import{a as o,b as q,c as r,d as t,e as u,f as v,g as w}from"../chunk-
|
|
1
|
+
import{a as p,b as x}from"../chunk-PEUTCG3B.js";import{a as s}from"../chunk-PEJALHXK.js";import{a as k}from"../chunk-SC5M74NM.js";import{a as o,b as q,c as r,d as t,e as u,f as v,g as w}from"../chunk-BGQKZBNE.js";import"../chunk-CRKSKIAL.js";import{b as m,c as n}from"../chunk-IOMNZBK4.js";import"../chunk-W6T7MOKY.js";import{a as l}from"../chunk-FUUTGGJS.js";import{a,b,c,d,e,f,g,h,i,j}from"../chunk-2ACBWC7K.js";export{l as KanonakUri,p as KanonakUriBuilder,s as KanonakUrlResolver,m as ResourceResolver,o as ResourceTypeClassifier,n as TypeResolver,k as assertPackageIdentity,c as compareVersions,w as contextTypesOf,f as createVersion,x as findInstancesByType,r as formatKanonakAddress,e as formatVersion,h as isCompatibleVersion,i as isMajorCompatible,q as parseKanonakAddress,g as parseVersionString,j as pickHighestDocument,u as propertiesInScope,v as resolvePropertyStep,t as subjectUri,a as versionOperatorFromChar,b as versionOperatorToChar,d as versionsEqual};
|
package/dist/search/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as g}from"../chunk-
|
|
1
|
+
import{a as g}from"../chunk-MCU5IAMS.js";import"../chunk-QHABFCRC.js";import"../chunk-4NO7MHS7.js";import"../chunk-PEUTCG3B.js";import"../chunk-PEJALHXK.js";import"../chunk-SC5M74NM.js";import"../chunk-SHDHMKMJ.js";import"../chunk-G2DKKSZ4.js";import"../chunk-TJPQETHV.js";import{d as m,g as S}from"../chunk-BGQKZBNE.js";import{a as p,f as E}from"../chunk-CRKSKIAL.js";import"../chunk-IOMNZBK4.js";import{c as v}from"../chunk-W6T7MOKY.js";import"../chunk-FUUTGGJS.js";import{c as x}from"../chunk-2ACBWC7K.js";import{homedir as P}from"os";import{join as d}from"path";import{existsSync as M,mkdirSync as D,readFileSync as j,writeFileSync as O}from"fs";import{createHash as C}from"crypto";import{pathToFileURL as B}from"url";var h="Xenova/all-MiniLM-L6-v2",w="q8",b=32;async function F(r){let{pipeline:e,env:t}=r.transformers;t.cacheDir=r.modelCacheDir??d(P(),".kanonak","models");let n=await e("feature-extraction",h,{dtype:w});return async s=>(await n(s,{pooling:"mean",normalize:!0})).tolist()}async function z(r){let e=d(r,"node_modules","@huggingface","transformers"),t=JSON.parse(j(d(e,"package.json"),"utf-8")),n=I(t);if(!n)throw new Error(`@huggingface/transformers at ${e} exposes no resolvable ESM entry.`);let s=await import(B(d(e,n)).href);return typeof s.pipeline=="function"?s:s.default}function I(r){let e=r.exports,t=n=>typeof n=="string"?n:n?.default;return typeof e=="string"?e:t(e?.node?.import)??t(e?.import)??t(e?.default)??r.module??r.main}var y=null;async function U(){return y||(y=(async()=>{let r;try{r=await import("@huggingface/transformers")}catch(e){throw new Error(`Semantic search requires the embedding runtime, which is an optional dependency.
|
|
2
2
|
Install it with:
|
|
3
3
|
npm install @huggingface/transformers
|
|
4
4
|
(underlying import error: ${e.message})`)}return F({transformers:r})})()),y}function H(r,e){let t=0;for(let n=0;n<r.length;n++)t+=r[n]*e[n];return t}function R(r,e){return e?r.version?e.version?x(r.version,e.version)>0:!0:!1:!0}function K(r,e){let t=g(r,e),n=[t.label],s=S(e);if(s.length>0){let i=E(r,s[0]),a=i?g(r,i).label:s[0].name;a&&n.push(`\u2014 a ${a}.`)}return t.summary&&n.push(t.summary),n.join(" ")}function q(r){let e=new Map;for(let t of r){if(!(t instanceof v))continue;let n=m(t);if(!n)continue;let s=p(n),i=e.get(s);(!i||R(n,m(i)))&&e.set(s,t)}return[...e.values()].sort((t,n)=>{let s=m(t)?p(m(t)):t.name,i=m(n)?p(m(n)):n.name;return s.localeCompare(i)})}var k=class{entries=[];embedder;constructor(e={}){this.embedder=e.embedder}resolveEmbedder(){return this.embedder?Promise.resolve(this.embedder):U()}get size(){return this.entries.length}async build(e,t={}){let n=q(e);if(t.include&&(n=n.filter(t.include)),n.length===0)return this.entries=[],{size:0,cached:!1};let s=n.map(o=>K(e,o)),i=t.cacheDir,a;if(i){let o=C("sha256").update(h+"|"+w+`
|
|
@@ -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 {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{b as Y,c as An,d as Sn,e as ce,f as Te,g as O,h as wn,i as X,j as q}from"../chunk-
|
|
1
|
+
import{b as Y,c as An,d as Sn,e as ce,f as Te,g as O,h as wn,i as X,j as q}from"../chunk-MCU5IAMS.js";import{a as se}from"../chunk-F5ANO7MJ.js";import"../chunk-QHABFCRC.js";import"../chunk-4NO7MHS7.js";import"../chunk-GN2XODVC.js";import"../chunk-PEJALHXK.js";import{a as kn,b as bn,c as hn,d as Dn}from"../chunk-SHDHMKMJ.js";import{f as ie}from"../chunk-G2DKKSZ4.js";import{a as ae}from"../chunk-TJPQETHV.js";import{b as L,c as A,f as S}from"../chunk-CRKSKIAL.js";import"../chunk-IOMNZBK4.js";import{b as N,c as D,d as K,g as M,h as P,i as F,j as W,l as H}from"../chunk-W6T7MOKY.js";import"../chunk-FUUTGGJS.js";import{g as oe}from"../chunk-2ACBWC7K.js";var $e="kanonak.org",Ue="document-ast",i=e=>({publisher:$e,package_:Ue,name:e}),m={Document:i("Document"),Block:i("Block"),Inline:i("Inline"),StructuredValue:i("StructuredValue"),Heading:i("Heading"),Paragraph:i("Paragraph"),RawBlock:i("RawBlock"),Text:i("Text"),StructuredMap:i("StructuredMap"),StructuredEntry:i("StructuredEntry"),StructuredList:i("StructuredList"),StringScalar:i("StringScalar"),IntegerScalar:i("IntegerScalar"),EscapeHint:i("EscapeHint"),MediaType:i("MediaType"),metadata:i("metadata"),children:i("children"),level:i("level"),inlines:i("inlines"),text:i("text"),entries:i("entries"),key:i("key"),value:i("value"),escapeHint:i("escapeHint"),items:i("items"),stringValue:i("stringValue"),integerValue:i("integerValue"),rawContent:i("rawContent"),mediaType:i("mediaType"),mimeType:i("mimeType"),ESC_RAW:i("esc-raw"),ESC_YAML_SAFE:i("esc-yaml-safe"),ESC_TOML_STRING:i("esc-toml-string"),ESC_TOML_MULTILINE:i("esc-toml-multiline"),ESC_JSON:i("esc-json"),ESC_DYNAMODB_BOOL:i("esc-dynamodb-bool"),ESC_DYNAMODB_NUMBER:i("esc-dynamodb-number"),ESC_DYNAMODB_NULL:i("esc-dynamodb-null"),TEXT_PLAIN:i("text-plain"),TEXT_MARKDOWN:i("text-markdown"),TEXT_HTML:i("text-html"),TEXT_CSS:i("text-css"),APPLICATION_JSON:i("application-json"),TEXT_YAML:i("text-yaml"),IMAGE_SVG_XML:i("image-svg-xml"),ResourceLink:i("ResourceLink"),target:i("target"),linkLabel:i("linkLabel"),PropertyList:i("PropertyList"),propertyEntries:i("propertyEntries"),PropertyEntry:i("PropertyEntry"),propertyKey:i("propertyKey"),propertyValue:i("propertyValue"),Table:i("Table"),tableColumnLabels:i("tableColumnLabels"),tableRows:i("tableRows"),TableRow:i("TableRow"),tableCells:i("tableCells")};function ue(e,n){return e.publisher===n.publisher&&e.package_===n.package_&&e.name===n.name}var j=class{backendUri="kanonak.org/transformations/markdown-with-frontmatter";render(n,t){let r=xe(n.metadata,t),o=Le(n.children),s=["---",...r,"---","",o].join(`
|
|
2
2
|
`);return t?.trailingNewline&&(s.endsWith(`
|
|
3
3
|
`)||(s+=`
|
|
4
4
|
`)),s}};function xe(e,n){if(!e)return[];let t=new Map;for(let c of e.entries)t.set(I(c.key),c);let r=new Map;if(n?.metadataRenames)for(let[c,u]of n.metadataRenames)r.set(I(c),u);let a=(n?.metadataKeys??e.entries.map(c=>c.key)).map(I),s=[];for(let c of a){let u=t.get(c);if(!u)continue;let f=r.get(c),l=I(f??c),d=me(u.value,u.escapeHint);d!==void 0&&s.push(`${l}: ${d}`)}return s}function I(e){let n=e.lastIndexOf(".");return n===-1?e:e.substring(n+1)||e}function me(e,n){switch(e.kind){case"StringScalar":return Ve(e.stringValue,n);case"IntegerScalar":return String(e.integerValue);case"StructuredList":{let t=[];for(let r of e.items){let o=me(r,n);o!==void 0&&t.push(o)}return t.join(", ")}case"StructuredMap":return;default:return}}function Ve(e,n){return!n||ue(n,m.ESC_RAW)?e:ue(n,m.ESC_YAML_SAFE)?ve(e):e}function ve(e){return e.includes(`
|
|
@@ -86,6 +86,24 @@ export declare function findSubjectsByType(kanonaks: Kanonak[], target: EntityUr
|
|
|
86
86
|
* bare-name references in single-version workspaces, etc).
|
|
87
87
|
*/
|
|
88
88
|
export declare function findSubjectByUri(kanonaks: Kanonak[], uri: KanonakUri): SubjectKanonak | undefined;
|
|
89
|
+
/**
|
|
90
|
+
* Every version of a subject present in the catalog, matched by canonical
|
|
91
|
+
* URI (publisher/package/name, version-agnostic), HIGHEST VERSION FIRST.
|
|
92
|
+
*
|
|
93
|
+
* This is THE single place the "newest wins" multi-version rule lives, so
|
|
94
|
+
* every cascade that takes the first match (semanticSvg, tokens, the type
|
|
95
|
+
* chain, path/traversal resolution) resolves to the newest version's
|
|
96
|
+
* open-world augmentation — an archived older version can never shadow the
|
|
97
|
+
* current one — and all environments (serve, publish, validate, the VS Code
|
|
98
|
+
* server, the transformation engine) render identically without each
|
|
99
|
+
* reimplementing (or forgetting) the load-order sort. Do not duplicate this:
|
|
100
|
+
* import it.
|
|
101
|
+
*/
|
|
102
|
+
export declare function findAllResourcesByCanonicalUri(catalog: Kanonak[], uri: {
|
|
103
|
+
publisher: string;
|
|
104
|
+
package_: string;
|
|
105
|
+
name: string;
|
|
106
|
+
}): SubjectKanonak[];
|
|
89
107
|
/**
|
|
90
108
|
* Read a datatype property value (string, number, boolean) off a defined
|
|
91
109
|
* kanonak, by property URI. Returns `undefined` when the property is not
|