@stroc/compose 0.0.0-stage → 0.1.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/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright 2026 Got Choices Foundation
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,17 @@
1
- # Temporary Holding Version
1
+ # @stroc/compose
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Fetches a document and everything it includes, verifies each against its CID, and composes them:
4
+ numbering, references resolved, parameters gathered. Includes an HTTP resolver for the IPFS
5
+ trustless-gateway layout (`/ipfs/<cid>`), catalog reading and author-domain checks.
6
+
7
+ ```js
8
+ import { compose, HttpResolver, MemoryStore, firstOf } from '@stroc/compose'
9
+
10
+ const resolver = firstOf(localStore, new HttpResolver('https://mychips.org'))
11
+ const composed = await compose(cid, resolver)
12
+ ```
13
+
14
+ Part of [Stroc](https://github.com/gotchoices/stroc), a format for structured legal documents
15
+ identified by content (IPLD CIDs). The format is specified in
16
+ [docs/Specification.md](https://github.com/gotchoices/stroc/blob/main/docs/Specification.md).
17
+ MIT license.
@@ -0,0 +1,57 @@
1
+ import type { CID } from 'multiformats/cid';
2
+ import { type StrocDocument } from '@stroc/core';
3
+ import type { Resolver } from './index.js';
4
+ type Fetch = typeof globalThis.fetch;
5
+ export declare class HttpResolver implements Resolver {
6
+ readonly base: string;
7
+ private readonly fetchFn;
8
+ constructor(base: string, options?: {
9
+ fetch?: Fetch;
10
+ });
11
+ get(cid: CID): Promise<Uint8Array | undefined>;
12
+ }
13
+ export declare const CATALOG_PATH = "/.well-known/stroc/catalog.json";
14
+ export type CatalogRole = 'author' | 'endorse' | 'mirror';
15
+ export type CatalogStatus = 'current' | 'superseded' | 'withdrawn';
16
+ export interface CatalogEntry {
17
+ cid: string;
18
+ title?: string;
19
+ role: CatalogRole;
20
+ status: CatalogStatus;
21
+ published?: string;
22
+ replaces?: string[];
23
+ }
24
+ export interface Catalog {
25
+ 'stroc-catalog': string;
26
+ domain: string;
27
+ entries: CatalogEntry[];
28
+ }
29
+ export declare function parseCatalog(value: unknown): {
30
+ catalog?: Catalog;
31
+ error?: string;
32
+ };
33
+ export type AuthorCheckStatus = 'confirmed' | 'endorsed' | 'mirrored' | 'not-listed' | 'unreachable' | 'not-a-domain';
34
+ export interface AuthorCheck {
35
+ status: AuthorCheckStatus;
36
+ author?: string;
37
+ domain?: string;
38
+ entry?: CatalogEntry;
39
+ reason?: string;
40
+ checked: string;
41
+ }
42
+ export interface AuthorCheckOptions {
43
+ fetch?: Fetch;
44
+ catalogUrl?: (domain: string) => string;
45
+ now?: () => Date;
46
+ }
47
+ export declare class AuthorChecker {
48
+ private readonly fetchFn;
49
+ private readonly catalogUrl;
50
+ private readonly now;
51
+ private readonly catalogs;
52
+ constructor(options?: AuthorCheckOptions);
53
+ private catalog;
54
+ check(document: StrocDocument, cid: CID | string): Promise<AuthorCheck>;
55
+ }
56
+ export {};
57
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/http.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,EAAY,KAAK,aAAa,EAAE,MAAM,aAAa,CAAA;AAC1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAE1C,KAAK,KAAK,GAAG,OAAO,UAAU,CAAC,KAAK,CAAA;AAKpC,qBAAa,YAAa,YAAW,QAAQ;IAC3C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAO;gBAEnB,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,KAAK,CAAA;KAAO;IAKnD,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;CAWrD;AAKD,eAAO,MAAM,YAAY,oCAAoC,CAAA;AAE7D,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAA;AACzD,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,YAAY,GAAG,WAAW,CAAA;AAElE,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,WAAW,CAAA;IACjB,MAAM,EAAE,aAAa,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CACpB;AAED,MAAM,WAAW,OAAO;IACtB,eAAe,EAAE,MAAM,CAAA;IACvB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,YAAY,EAAE,CAAA;CACxB;AAMD,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAYlF;AAKD,MAAM,MAAM,iBAAiB,GACzB,WAAW,GACX,UAAU,GACV,UAAU,GACV,YAAY,GACZ,aAAa,GACb,cAAc,CAAA;AAElB,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,iBAAiB,CAAA;IACzB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,YAAY,CAAA;IACpB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,KAAK,CAAA;IAGb,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAA;IACvC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAA;CACjB;AAGD,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAO;IAC/B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA4B;IACvD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAY;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoE;gBAEjF,OAAO,GAAE,kBAAuB;IAM5C,OAAO,CAAC,OAAO;IAqBT,KAAK,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,EAAE,GAAG,GAAG,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;CAW9E"}
@@ -0,0 +1,97 @@
1
+ // HTTP access to published documents (Specification: Published Sets and Catalogs).
2
+ //
3
+ // Uses only the standard `fetch`, so it runs in browsers, Node and React Native. Nothing fetched is
4
+ // trusted: documents are verified against their CIDs by `compose`, and catalogs only ever confirm
5
+ // claims about a domain they were fetched from.
6
+ import { isDomain } from '@stroc/core';
7
+ // Reads documents from a Stroc server, a static host or an IPFS gateway, using the trustless
8
+ // gateway convention: GET <base>/ipfs/<cid>?format=raw. Returns undefined for anything other than
9
+ // a successful response (the caller reports the document as missing).
10
+ export class HttpResolver {
11
+ constructor(base, options = {}) {
12
+ this.base = base.replace(/\/+$/, '');
13
+ this.fetchFn = options.fetch ?? globalThis.fetch.bind(globalThis);
14
+ }
15
+ async get(cid) {
16
+ try {
17
+ const res = await this.fetchFn(`${this.base}/ipfs/${cid}?format=raw`, {
18
+ headers: { Accept: 'application/vnd.ipld.raw, application/vnd.ipld.dag-json;q=0.9, */*;q=0.1' },
19
+ });
20
+ if (!res.ok)
21
+ return undefined;
22
+ return new Uint8Array(await res.arrayBuffer());
23
+ }
24
+ catch {
25
+ return undefined;
26
+ }
27
+ }
28
+ }
29
+ // ---------------------------------------------------------------------------------------------
30
+ // Catalogs
31
+ export const CATALOG_PATH = '/.well-known/stroc/catalog.json';
32
+ const ROLES = new Set(['author', 'endorse', 'mirror']);
33
+ const STATUSES = new Set(['current', 'superseded', 'withdrawn']);
34
+ // Check the shape of a fetched catalog. Returns undefined (with a reason) if it is not one.
35
+ export function parseCatalog(value) {
36
+ if (typeof value !== 'object' || value === null)
37
+ return { error: 'not a JSON object' };
38
+ const c = value;
39
+ if (typeof c['stroc-catalog'] !== 'string')
40
+ return { error: 'missing "stroc-catalog" version' };
41
+ if (typeof c.domain !== 'string')
42
+ return { error: 'missing "domain"' };
43
+ if (!Array.isArray(c.entries))
44
+ return { error: '"entries" must be an array' };
45
+ for (const e of c.entries) {
46
+ if (typeof e?.cid !== 'string' || !ROLES.has(e.role) || !STATUSES.has(e.status)) {
47
+ return { error: 'an entry lacks a valid cid, role or status' };
48
+ }
49
+ }
50
+ return { catalog: value };
51
+ }
52
+ // Checks documents' `author` claims, fetching each domain's catalog once.
53
+ export class AuthorChecker {
54
+ constructor(options = {}) {
55
+ this.catalogs = new Map();
56
+ this.fetchFn = options.fetch ?? globalThis.fetch.bind(globalThis);
57
+ this.catalogUrl = options.catalogUrl ?? (d => `https://${d}${CATALOG_PATH}`);
58
+ this.now = options.now ?? (() => new Date());
59
+ }
60
+ catalog(domain) {
61
+ let pending = this.catalogs.get(domain);
62
+ if (!pending) {
63
+ pending = (async () => {
64
+ try {
65
+ const res = await this.fetchFn(this.catalogUrl(domain), { headers: { Accept: 'application/json' } });
66
+ if (!res.ok)
67
+ return { error: `HTTP ${res.status}` };
68
+ const parsed = parseCatalog(await res.json());
69
+ if (parsed.catalog && parsed.catalog.domain !== domain) {
70
+ return { error: `the catalog speaks for "${parsed.catalog.domain}", not "${domain}"` };
71
+ }
72
+ return parsed;
73
+ }
74
+ catch (err) {
75
+ return { error: err.message };
76
+ }
77
+ })();
78
+ this.catalogs.set(domain, pending);
79
+ }
80
+ return pending;
81
+ }
82
+ async check(document, cid) {
83
+ const checked = this.now().toISOString();
84
+ const author = document.author;
85
+ if (!author || !isDomain(author))
86
+ return { status: 'not-a-domain', ...(author ? { author } : {}), checked };
87
+ const { catalog, error } = await this.catalog(author);
88
+ if (!catalog)
89
+ return { status: 'unreachable', author, domain: author, reason: error, checked };
90
+ const entry = catalog.entries.find(e => e.cid === cid.toString());
91
+ if (!entry)
92
+ return { status: 'not-listed', author, domain: author, checked };
93
+ const status = entry.role === 'author' ? 'confirmed' : entry.role === 'endorse' ? 'endorsed' : 'mirrored';
94
+ return { status, author, domain: author, entry, checked };
95
+ }
96
+ }
97
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/http.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ import { CID } from 'multiformats/cid';
2
+ import { type Problem, type StrocDocument, type Parameter } from '@stroc/core';
3
+ export interface Resolver {
4
+ get(cid: CID): Promise<Uint8Array | undefined>;
5
+ }
6
+ export declare class MemoryStore implements Resolver {
7
+ private blocks;
8
+ get(cid: CID): Promise<Uint8Array | undefined>;
9
+ has(cid: CID): boolean;
10
+ put(bytes: Uint8Array): Promise<CID>;
11
+ putDocument(doc: unknown): Promise<CID>;
12
+ get size(): number;
13
+ }
14
+ export declare function firstOf(...resolvers: Resolver[]): Resolver;
15
+ export declare function findMissing(root: CID, resolver: Resolver): Promise<CID[]>;
16
+ export type ComposedInline = {
17
+ type: 'text';
18
+ value: string;
19
+ } | {
20
+ type: 'emphasis';
21
+ tag: 'b' | 'i' | 'u';
22
+ children: ComposedInline[];
23
+ } | {
24
+ type: 'ref';
25
+ path: string[];
26
+ target?: number[];
27
+ } | {
28
+ type: 'param';
29
+ path: string;
30
+ };
31
+ export interface ComposedSection {
32
+ number: number[];
33
+ id?: string;
34
+ title?: string;
35
+ text?: ComposedInline[];
36
+ sections: ComposedSection[];
37
+ include?: {
38
+ cid: CID;
39
+ document: StrocDocument;
40
+ };
41
+ }
42
+ export interface ParameterGroup {
43
+ section?: {
44
+ number: number[];
45
+ title: string;
46
+ };
47
+ prefix: string[];
48
+ parameters: Parameter[];
49
+ }
50
+ export interface Composed {
51
+ cid: CID;
52
+ document?: StrocDocument;
53
+ title: string;
54
+ language: string;
55
+ text?: ComposedInline[];
56
+ sections: ComposedSection[];
57
+ parameters: ParameterGroup[];
58
+ problems: Problem[];
59
+ }
60
+ export declare function compose(root: CID | string, resolver: Resolver): Promise<Composed>;
61
+ export declare function formatNumber(number: number[]): string;
62
+ export * from './http.js';
63
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AACtC,OAAO,EAEY,KAAK,OAAO,EAAE,KAAK,aAAa,EAAqB,KAAK,SAAS,EACrF,MAAM,aAAa,CAAA;AAKpB,MAAM,WAAW,QAAQ;IAEvB,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAA;CAC/C;AAGD,qBAAa,WAAY,YAAW,QAAQ;IAC1C,OAAO,CAAC,MAAM,CAAgC;IAExC,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAIpD,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO;IAKhB,GAAG,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC;IAOpC,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC;IAI7C,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF;AAGD,wBAAgB,OAAO,CAAC,GAAG,SAAS,EAAE,QAAQ,EAAE,GAAG,QAAQ,CAU1D;AAID,wBAAsB,WAAW,CAAC,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAa/E;AAeD,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;IAAC,QAAQ,EAAE,cAAc,EAAE,CAAA;CAAE,GACtE;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GAClD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAEnC,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,cAAc,EAAE,CAAA;IACvB,QAAQ,EAAE,eAAe,EAAE,CAAA;IAC3B,OAAO,CAAC,EAAE;QACR,GAAG,EAAE,GAAG,CAAA;QACR,QAAQ,EAAE,aAAa,CAAA;KACxB,CAAA;CACF;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IAC7C,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,UAAU,EAAE,SAAS,EAAE,CAAA;CACxB;AAED,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,GAAG,CAAA;IACR,QAAQ,CAAC,EAAE,aAAa,CAAA;IACxB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,cAAc,EAAE,CAAA;IACvB,QAAQ,EAAE,eAAe,EAAE,CAAA;IAC3B,UAAU,EAAE,cAAc,EAAE,CAAA;IAC5B,QAAQ,EAAE,OAAO,EAAE,CAAA;CACpB;AAiBD,wBAAsB,OAAO,CAAC,IAAI,EAAE,GAAG,GAAG,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CA4FvF;AA4BD,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAErD;AAED,cAAc,WAAW,CAAA"}
@@ -0,0 +1,215 @@
1
+ // Composition: fetch and verify a document and everything it includes, number the whole tree,
2
+ // resolve cross-references and gather parameters (Specification: Composition, Cross-References,
3
+ // Parameters, Document Resolution and Verification).
4
+ //
5
+ // Where bytes come from is the app's business: it supplies a Resolver. Every fetched document is
6
+ // verified against its CID before use.
7
+ import { CID } from 'multiformats/cid';
8
+ import { verifyDocument, computeCid, encodeDagJson, parseMarkup, } from '@stroc/core';
9
+ // An in-memory content-addressed store. Documents are keyed by the CID of their bytes.
10
+ export class MemoryStore {
11
+ constructor() {
12
+ this.blocks = new Map();
13
+ }
14
+ async get(cid) {
15
+ return this.blocks.get(cid.toString());
16
+ }
17
+ has(cid) {
18
+ return this.blocks.has(cid.toString());
19
+ }
20
+ // Store bytes under their CID and return it. (Bytes are verified when read, not here.)
21
+ async put(bytes) {
22
+ const cid = await computeCid(bytes);
23
+ this.blocks.set(cid.toString(), bytes);
24
+ return cid;
25
+ }
26
+ // Store a document from the data model in its canonical encoding.
27
+ async putDocument(doc) {
28
+ return this.put(encodeDagJson(doc));
29
+ }
30
+ get size() {
31
+ return this.blocks.size;
32
+ }
33
+ }
34
+ // Try several resolvers in order (for example a local store, then a peer, then a publisher).
35
+ export function firstOf(...resolvers) {
36
+ return {
37
+ async get(cid) {
38
+ for (const r of resolvers) {
39
+ const bytes = await r.get(cid);
40
+ if (bytes)
41
+ return bytes;
42
+ }
43
+ return undefined;
44
+ },
45
+ };
46
+ }
47
+ // The CIDs reachable from root that the resolver cannot supply. Documents that are present are
48
+ // verified and followed; an empty result means the whole composition is available.
49
+ export async function findMissing(root, resolver) {
50
+ const missing = [];
51
+ const seen = new Set();
52
+ const visit = async (cid) => {
53
+ if (seen.has(cid.toString()))
54
+ return;
55
+ seen.add(cid.toString());
56
+ const bytes = await resolver.get(cid);
57
+ if (!bytes) {
58
+ missing.push(cid);
59
+ return;
60
+ }
61
+ const v = await verifyDocument(bytes, cid);
62
+ if (v.document)
63
+ for (const link of includeLinks(v.document.sections))
64
+ await visit(link);
65
+ };
66
+ await visit(root);
67
+ return missing;
68
+ }
69
+ function includeLinks(sections) {
70
+ const out = [];
71
+ for (const s of sections ?? []) {
72
+ if ('source' in s)
73
+ out.push(s.source);
74
+ else
75
+ out.push(...includeLinks(s.sections));
76
+ }
77
+ return out;
78
+ }
79
+ const MAX_DEPTH = 64;
80
+ // Compose a document by CID. Never throws: anything missing, invalid or unresolved is reported in
81
+ // `problems`, and the parts that could not be composed are left out.
82
+ export async function compose(root, resolver) {
83
+ const rootCid = typeof root === 'string' ? CID.parse(root) : root;
84
+ const problems = [];
85
+ const pending = [];
86
+ const parameters = [];
87
+ const cache = new Map();
88
+ const load = async (cid, at) => {
89
+ const key = cid.toString();
90
+ if (cache.has(key))
91
+ return cache.get(key) ?? undefined;
92
+ const bytes = await resolver.get(cid);
93
+ if (!bytes) {
94
+ problems.push({ path: [], code: 'missing-document', message: `${at}: document ${key} is not available` });
95
+ cache.set(key, null);
96
+ return undefined;
97
+ }
98
+ const v = await verifyDocument(bytes, cid);
99
+ if (!v.ok || !v.document) {
100
+ const why = v.problems.map(p => `${p.path.join('.') || 'document'}: ${p.message}`).join('; ');
101
+ problems.push({ path: [], code: 'invalid-document', message: `${at}: document ${key} failed verification: ${why}` });
102
+ cache.set(key, null);
103
+ return undefined;
104
+ }
105
+ cache.set(key, v.document);
106
+ return v.document;
107
+ };
108
+ const convertText = (text, scope, at, prefix) => {
109
+ const convert = (nodes) => nodes.map(n => n.type === 'text' ? { type: 'text', value: n.value } :
110
+ n.type === 'ref' ? { type: 'ref', path: n.path } :
111
+ n.type === 'param' ? { type: 'param', path: [...prefix, n.key].join('/') } :
112
+ { type: 'emphasis', tag: n.tag, children: convert(n.children) });
113
+ const nodes = convert(parseMarkup(text).nodes);
114
+ pending.push({ nodes, scope, at });
115
+ return nodes;
116
+ };
117
+ // Compose a document's sections under a parent number, in the document's own id scope.
118
+ const composeSections = async (sections, parent, scope, prefix, depth, at) => {
119
+ const out = [];
120
+ let n = 0;
121
+ for (const sec of sections ?? []) {
122
+ n++;
123
+ const number = [...parent, n];
124
+ if ('source' in sec) {
125
+ const placeholder = { number, id: sec.id, sections: [] };
126
+ scope.ids.set(sec.id, placeholder);
127
+ out.push(placeholder);
128
+ if (depth >= MAX_DEPTH) {
129
+ problems.push({ path: [], code: 'too-deep', message: `${at}: includes nested more than ${MAX_DEPTH} deep` });
130
+ continue;
131
+ }
132
+ const doc = await load(sec.source, `${at} > ${sec.id}`);
133
+ if (!doc)
134
+ continue;
135
+ const inner = { ids: new Map(), includes: new Map() };
136
+ scope.includes.set(sec.id, inner);
137
+ const innerPrefix = [...prefix, sec.id];
138
+ placeholder.title = doc.title;
139
+ placeholder.include = { cid: sec.source, document: doc };
140
+ if (doc.parameters)
141
+ parameters.push({ section: { number, title: doc.title }, prefix: innerPrefix, parameters: doc.parameters });
142
+ if (doc.text)
143
+ placeholder.text = convertText(doc.text, inner, `${at} > ${sec.id}`, innerPrefix);
144
+ placeholder.sections = await composeSections(doc.sections, number, inner, innerPrefix, depth + 1, `${at} > ${sec.id}`);
145
+ }
146
+ else {
147
+ const section = { number, sections: [] };
148
+ if (sec.id) {
149
+ section.id = sec.id;
150
+ scope.ids.set(sec.id, section);
151
+ }
152
+ if (sec.title)
153
+ section.title = sec.title;
154
+ if (sec.text)
155
+ section.text = convertText(sec.text, scope, at, prefix);
156
+ section.sections = await composeSections(sec.sections, number, scope, prefix, depth, at);
157
+ out.push(section);
158
+ }
159
+ }
160
+ return out;
161
+ };
162
+ const document = await load(rootCid, 'root');
163
+ if (!document) {
164
+ return { cid: rootCid, title: '', language: '', sections: [], parameters: [], problems };
165
+ }
166
+ const rootScope = { ids: new Map(), includes: new Map() };
167
+ if (document.parameters)
168
+ parameters.unshift({ prefix: [], parameters: document.parameters });
169
+ const text = document.text ? convertText(document.text, rootScope, 'root', []) : undefined;
170
+ const sections = await composeSections(document.sections, [], rootScope, [], 0, 'root');
171
+ // Root parameters first, then included documents' in document order.
172
+ parameters.sort((a, b) => compareNumbers(a.section?.number ?? [], b.section?.number ?? []));
173
+ // Resolve references now that every scope is complete.
174
+ for (const p of pending)
175
+ resolveRefs(p.nodes, p.scope, p.at, problems);
176
+ return { cid: rootCid, document, title: document.title, language: document.language, text, sections, parameters, problems };
177
+ }
178
+ function resolveRefs(nodes, scope, at, problems) {
179
+ for (const node of nodes) {
180
+ if (node.type === 'emphasis')
181
+ resolveRefs(node.children, scope, at, problems);
182
+ if (node.type !== 'ref')
183
+ continue;
184
+ let current = scope;
185
+ let target;
186
+ for (let i = 0; i < node.path.length && current; i++) {
187
+ target = current.ids.get(node.path[i]);
188
+ if (!target)
189
+ break;
190
+ current = i < node.path.length - 1 ? current.includes.get(node.path[i]) : undefined;
191
+ if (i < node.path.length - 1 && !current) {
192
+ target = undefined;
193
+ break;
194
+ }
195
+ }
196
+ if (target)
197
+ node.target = target.number;
198
+ else
199
+ problems.push({ path: [], code: 'unresolved-ref', message: `${at}: <ref:${node.path.join('/')}> does not resolve in the composed document` });
200
+ }
201
+ }
202
+ function compareNumbers(a, b) {
203
+ for (let i = 0; i < Math.max(a.length, b.length); i++) {
204
+ const d = (a[i] ?? 0) - (b[i] ?? 0);
205
+ if (d)
206
+ return d;
207
+ }
208
+ return 0;
209
+ }
210
+ // "3.1" for [3, 1].
211
+ export function formatNumber(number) {
212
+ return number.join('.');
213
+ }
214
+ export * from './http.js';
215
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,51 @@
1
1
  {
2
2
  "name": "@stroc/compose",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.1.0",
4
+ "description": "Fetch, verify and compose Stroc documents and their includes; HTTP resolver and catalogs",
5
+ "keywords": [
6
+ "stroc",
7
+ "structured-documents",
8
+ "ipfs",
9
+ "trustless-gateway"
10
+ ],
11
+ "license": "MIT",
12
+ "author": "Got Choices Foundation",
13
+ "homepage": "https://github.com/gotchoices/stroc/tree/main/packages/compose#readme",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "https://github.com/gotchoices/stroc.git",
17
+ "directory": "packages/compose"
18
+ },
19
+ "bugs": "https://github.com/gotchoices/stroc/issues",
20
+ "engines": {
21
+ "node": ">=20.19"
22
+ },
23
+ "type": "module",
24
+ "sideEffects": false,
25
+ "main": "dist/src/index.js",
26
+ "types": "dist/src/index.d.ts",
27
+ "exports": {
28
+ ".": {
29
+ "types": "./dist/src/index.d.ts",
30
+ "import": "./dist/src/index.js"
31
+ }
32
+ },
33
+ "files": [
34
+ "dist/src/**/*"
35
+ ],
36
+ "scripts": {
37
+ "build": "tsc -b",
38
+ "test": "vitest run"
39
+ },
40
+ "dependencies": {
41
+ "@stroc/core": "0.1.0",
42
+ "multiformats": "^13.4 || ^14"
43
+ },
44
+ "devDependencies": {
45
+ "typescript": "^5.4.0",
46
+ "vitest": "^3"
47
+ },
48
+ "publishConfig": {
49
+ "access": "public"
50
+ }
6
51
  }