@superbee/core 0.2.0-pre.1 → 0.2.0-pre.10
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/README.md +127 -0
- package/dist/artifact-contract.d.ts +90 -0
- package/dist/artifact-contract.d.ts.map +1 -0
- package/dist/artifact-contract.js +205 -0
- package/dist/artifact-contract.js.map +1 -0
- package/dist/backend.d.ts +16 -1
- package/dist/backend.d.ts.map +1 -1
- package/dist/backend.js +85 -42
- package/dist/backend.js.map +1 -1
- package/dist/bundle-ops.d.ts +1 -1
- package/dist/bundle-ops.d.ts.map +1 -1
- package/dist/bundle-ops.js +2 -2
- package/dist/bundle-ops.js.map +1 -1
- package/dist/bundle.d.ts +2 -1
- package/dist/bundle.d.ts.map +1 -1
- package/dist/bundle.js +3 -3
- package/dist/bundle.js.map +1 -1
- package/dist/document-codec.d.ts +6 -1
- package/dist/document-codec.d.ts.map +1 -1
- package/dist/document-codec.js +8 -4
- package/dist/document-codec.js.map +1 -1
- package/dist/document-field-actions.d.ts +13 -1
- package/dist/document-field-actions.d.ts.map +1 -1
- package/dist/document-field-actions.js +47 -6
- package/dist/document-field-actions.js.map +1 -1
- package/dist/document-mutation.d.ts +15 -1
- package/dist/document-mutation.d.ts.map +1 -1
- package/dist/document-mutation.js +42 -11
- package/dist/document-mutation.js.map +1 -1
- package/dist/document-write-policy.d.ts.map +1 -1
- package/dist/document-write-policy.js +4 -2
- package/dist/document-write-policy.js.map +1 -1
- package/dist/engine.d.ts +1 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +4 -3
- package/dist/engine.js.map +1 -1
- package/dist/file-journaled-backend-internal.d.ts +19 -0
- package/dist/file-journaled-backend-internal.d.ts.map +1 -0
- package/dist/file-journaled-backend-internal.js +10 -0
- package/dist/file-journaled-backend-internal.js.map +1 -0
- package/dist/file-journaled-backend.d.ts +162 -0
- package/dist/file-journaled-backend.d.ts.map +1 -0
- package/dist/file-journaled-backend.js +1113 -0
- package/dist/file-journaled-backend.js.map +1 -0
- package/dist/filesystem-host.d.ts +15 -0
- package/dist/filesystem-host.d.ts.map +1 -0
- package/dist/filesystem-host.js +20 -0
- package/dist/filesystem-host.js.map +1 -0
- package/dist/filesystem-identity.d.ts +86 -4
- package/dist/filesystem-identity.d.ts.map +1 -1
- package/dist/filesystem-identity.js +338 -102
- package/dist/filesystem-identity.js.map +1 -1
- package/dist/filesystem-lock.d.ts +16 -3
- package/dist/filesystem-lock.d.ts.map +1 -1
- package/dist/filesystem-lock.js +323 -77
- package/dist/filesystem-lock.js.map +1 -1
- package/dist/filesystem-push-role.d.ts +77 -0
- package/dist/filesystem-push-role.d.ts.map +1 -0
- package/dist/filesystem-push-role.js +165 -0
- package/dist/filesystem-push-role.js.map +1 -0
- package/dist/filesystem.d.ts +17 -0
- package/dist/filesystem.d.ts.map +1 -0
- package/dist/filesystem.js +18 -0
- package/dist/filesystem.js.map +1 -0
- package/dist/frontmatter.d.ts +8 -0
- package/dist/frontmatter.d.ts.map +1 -1
- package/dist/frontmatter.js +14 -4
- package/dist/frontmatter.js.map +1 -1
- package/dist/governed-body-write.d.ts +106 -0
- package/dist/governed-body-write.d.ts.map +1 -0
- package/dist/governed-body-write.js +251 -0
- package/dist/governed-body-write.js.map +1 -0
- package/dist/heads-digest.d.ts +32 -0
- package/dist/heads-digest.d.ts.map +1 -0
- package/dist/heads-digest.js +37 -0
- package/dist/heads-digest.js.map +1 -0
- package/dist/host-policy-snapshot.d.ts +9 -0
- package/dist/host-policy-snapshot.d.ts.map +1 -0
- package/dist/host-policy-snapshot.js +33 -0
- package/dist/host-policy-snapshot.js.map +1 -0
- package/dist/host-text.d.ts +31 -0
- package/dist/host-text.d.ts.map +1 -0
- package/dist/host-text.js +77 -0
- package/dist/host-text.js.map +1 -0
- package/dist/hosted-transport/answer-rows.d.ts +216 -0
- package/dist/hosted-transport/answer-rows.d.ts.map +1 -0
- package/dist/hosted-transport/answer-rows.js +396 -0
- package/dist/hosted-transport/answer-rows.js.map +1 -0
- package/dist/hosted-transport/carrier.d.ts +142 -0
- package/dist/hosted-transport/carrier.d.ts.map +1 -0
- package/dist/hosted-transport/carrier.js +241 -0
- package/dist/hosted-transport/carrier.js.map +1 -0
- package/dist/hosted-transport/history-pages.d.ts +55 -0
- package/dist/hosted-transport/history-pages.d.ts.map +1 -0
- package/dist/hosted-transport/history-pages.js +69 -0
- package/dist/hosted-transport/history-pages.js.map +1 -0
- package/dist/hosted-transport/index.d.ts +18 -0
- package/dist/hosted-transport/index.d.ts.map +1 -0
- package/dist/hosted-transport/index.js +18 -0
- package/dist/hosted-transport/index.js.map +1 -0
- package/dist/hosted-transport/operations.d.ts +85 -0
- package/dist/hosted-transport/operations.d.ts.map +1 -0
- package/dist/hosted-transport/operations.js +128 -0
- package/dist/hosted-transport/operations.js.map +1 -0
- package/dist/hosted-transport/paged-reads.d.ts +87 -0
- package/dist/hosted-transport/paged-reads.d.ts.map +1 -0
- package/dist/hosted-transport/paged-reads.js +238 -0
- package/dist/hosted-transport/paged-reads.js.map +1 -0
- package/dist/hosted-transport/read-adapter.d.ts +250 -0
- package/dist/hosted-transport/read-adapter.d.ts.map +1 -0
- package/dist/hosted-transport/read-adapter.js +557 -0
- package/dist/hosted-transport/read-adapter.js.map +1 -0
- package/dist/hosted-transport/root-write.d.ts +114 -0
- package/dist/hosted-transport/root-write.d.ts.map +1 -0
- package/dist/hosted-transport/root-write.js +171 -0
- package/dist/hosted-transport/root-write.js.map +1 -0
- package/dist/hosted-transport/whole-document-transport.d.ts +174 -0
- package/dist/hosted-transport/whole-document-transport.d.ts.map +1 -0
- package/dist/hosted-transport/whole-document-transport.js +411 -0
- package/dist/hosted-transport/whole-document-transport.js.map +1 -0
- package/dist/index.d.ts +22 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -5
- package/dist/index.js.map +1 -1
- package/dist/indexeddb-backend.d.ts +38 -6
- package/dist/indexeddb-backend.d.ts.map +1 -1
- package/dist/indexeddb-backend.js +511 -46
- package/dist/indexeddb-backend.js.map +1 -1
- package/dist/journaled-backend.d.ts +296 -7
- package/dist/journaled-backend.d.ts.map +1 -1
- package/dist/journaled-backend.js +312 -0
- package/dist/journaled-backend.js.map +1 -1
- package/dist/kind-coverage.d.ts +99 -0
- package/dist/kind-coverage.d.ts.map +1 -0
- package/dist/kind-coverage.js +186 -0
- package/dist/kind-coverage.js.map +1 -0
- package/dist/kinds.d.ts +31 -1
- package/dist/kinds.d.ts.map +1 -1
- package/dist/kinds.js +83 -16
- package/dist/kinds.js.map +1 -1
- package/dist/links.d.ts +1 -1
- package/dist/links.d.ts.map +1 -1
- package/dist/links.js +5 -10
- package/dist/links.js.map +1 -1
- package/dist/managed-document-metadata.d.ts +2 -0
- package/dist/managed-document-metadata.d.ts.map +1 -0
- package/dist/managed-document-metadata.js +9 -0
- package/dist/managed-document-metadata.js.map +1 -0
- package/dist/memory-backend.d.ts +2 -2
- package/dist/memory-backend.d.ts.map +1 -1
- package/dist/memory-backend.js +32 -16
- package/dist/memory-backend.js.map +1 -1
- package/dist/paths.d.ts +6 -2
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +35 -33
- package/dist/paths.js.map +1 -1
- package/dist/platform.d.ts +84 -6
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +9 -4
- package/dist/platform.js.map +1 -1
- package/dist/portable-export.d.ts +119 -0
- package/dist/portable-export.d.ts.map +1 -0
- package/dist/portable-export.js +501 -0
- package/dist/portable-export.js.map +1 -0
- package/dist/publication-filesystem.d.ts +1 -1
- package/dist/publication-filesystem.d.ts.map +1 -1
- package/dist/publication-filesystem.js +1 -1
- package/dist/publication-filesystem.js.map +1 -1
- package/dist/query-filter.d.ts +7 -2
- package/dist/query-filter.d.ts.map +1 -1
- package/dist/query-filter.js +24 -1
- package/dist/query-filter.js.map +1 -1
- package/dist/query-order.d.ts +22 -0
- package/dist/query-order.d.ts.map +1 -0
- package/dist/query-order.js +42 -0
- package/dist/query-order.js.map +1 -0
- package/dist/remote-backend.d.ts +91 -27
- package/dist/remote-backend.d.ts.map +1 -1
- package/dist/remote-backend.js +217 -49
- package/dist/remote-backend.js.map +1 -1
- package/dist/remote-document-codec.d.ts +15 -0
- package/dist/remote-document-codec.d.ts.map +1 -0
- package/dist/remote-document-codec.js +103 -0
- package/dist/remote-document-codec.js.map +1 -0
- package/dist/remote-error.d.ts +38 -0
- package/dist/remote-error.d.ts.map +1 -0
- package/dist/remote-error.js +59 -0
- package/dist/remote-error.js.map +1 -0
- package/dist/remote-operations.d.ts +6 -3
- package/dist/remote-operations.d.ts.map +1 -1
- package/dist/remote-operations.js +20 -5
- package/dist/remote-operations.js.map +1 -1
- package/dist/remote-parsers.d.ts +86 -0
- package/dist/remote-parsers.d.ts.map +1 -0
- package/dist/remote-parsers.js +181 -0
- package/dist/remote-parsers.js.map +1 -0
- package/dist/remote.d.ts +7 -2
- package/dist/remote.d.ts.map +1 -1
- package/dist/remote.js +6 -1
- package/dist/remote.js.map +1 -1
- package/dist/storage.d.ts +4 -2
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +4 -1
- package/dist/storage.js.map +1 -1
- package/dist/types.d.ts +28 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/uncertain-write.d.ts +49 -13
- package/dist/uncertain-write.d.ts.map +1 -1
- package/dist/uncertain-write.js +36 -12
- package/dist/uncertain-write.js.map +1 -1
- package/dist/versioning.d.ts +9 -4
- package/dist/versioning.d.ts.map +1 -1
- package/dist/versioning.js +9 -4
- package/dist/versioning.js.map +1 -1
- package/package.json +34 -2
package/dist/memory-backend.js
CHANGED
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
* - per-write ACTOR attribution recorded on every revision;
|
|
13
13
|
* - a real batch {@link MemoryBackend.readMany}.
|
|
14
14
|
*
|
|
15
|
-
* It touches NO filesystem and
|
|
16
|
-
*
|
|
15
|
+
* It touches NO filesystem — bodies and YAML metadata snapshots are held in memory,
|
|
16
|
+
* keyed by concept id — so running the
|
|
17
17
|
* core operations over it exercises exactly the parts of the engine that must be
|
|
18
18
|
* backend-neutral. Version tokens are still content-addressed via {@link contentVersion},
|
|
19
19
|
* so an engine-written document carries the SAME token here as on disk.
|
|
@@ -25,12 +25,10 @@
|
|
|
25
25
|
* the dual-backend / wire-protocol contract tests diverge.
|
|
26
26
|
*/
|
|
27
27
|
import { resolveContentType } from "./content-type.js";
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
return structuredClone(value);
|
|
33
|
-
}
|
|
28
|
+
import { readBundleOkfVersion } from "./engine.js";
|
|
29
|
+
import { MalformedDocumentError, normalizeDocumentBodyForStorage, parseFrontmatter, stringifyFrontmatter, stringifyWithSerializedFrontmatter } from "./frontmatter.js";
|
|
30
|
+
import { assertSafeBlobKey, assertSafeConceptId, assertSafeReservedDir, assertSafeReservedFilename, compareStorageKeys } from "./paths.js";
|
|
31
|
+
import { blobVersion, defaultActor, VersionConflict, versionOfBytes } from "./versioning.js";
|
|
34
32
|
/** An ENOENT-shaped rejection so missing-document handling matches {@link FilesystemBackend}. */
|
|
35
33
|
function notFound(id) {
|
|
36
34
|
const err = new Error(`no concept document '${id}'`);
|
|
@@ -39,8 +37,7 @@ function notFound(id) {
|
|
|
39
37
|
}
|
|
40
38
|
/** Bundle-relative key for a reserved file (`""` = bundle root), mirroring the fs adapter's layout. */
|
|
41
39
|
function reservedKey(dir, name) {
|
|
42
|
-
|
|
43
|
-
return d === "" ? name : `${d}/${name}`;
|
|
40
|
+
return dir === "" ? name : `${dir}/${name}`;
|
|
44
41
|
}
|
|
45
42
|
/**
|
|
46
43
|
* A fully in-memory OKF store implementing the {@link StorageBackend} contract for
|
|
@@ -61,7 +58,18 @@ export class MemoryBackend {
|
|
|
61
58
|
const head = this.chains.get(id)?.[0];
|
|
62
59
|
if (!head)
|
|
63
60
|
throw notFound(id);
|
|
64
|
-
|
|
61
|
+
let okfVersion;
|
|
62
|
+
try {
|
|
63
|
+
okfVersion = await readBundleOkfVersion(this);
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
if (!(error instanceof MalformedDocumentError))
|
|
67
|
+
throw error;
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
doc: { ...head.doc, frontmatter: parseFrontmatter(head.frontmatterSource, id, { okfVersion }) },
|
|
71
|
+
version: head.version,
|
|
72
|
+
};
|
|
65
73
|
}
|
|
66
74
|
async readMany(ids) {
|
|
67
75
|
// Validate every id up front (same contract as FilesystemBackend.readMany), then a
|
|
@@ -81,8 +89,13 @@ export class MemoryBackend {
|
|
|
81
89
|
// The seam's `id` argument owns identity. Filesystem and wire adapters reconstruct/attach
|
|
82
90
|
// that route id on reads because document bytes do not serialize `doc.id`; mirror them here
|
|
83
91
|
// instead of retaining a mismatched caller-supplied `doc.id` in the in-memory snapshot.
|
|
84
|
-
|
|
85
|
-
|
|
92
|
+
// The body is likewise stored in its SERIALIZED shape: byte-storing adapters re-parse what
|
|
93
|
+
// they wrote, so their reads always carry the serializer's trailing-newline form. Mirroring
|
|
94
|
+
// that normalization keeps a read-built mutation's candidate identical on every adapter, as
|
|
95
|
+
// `frontmatterSource` does for metadata.
|
|
96
|
+
const storedDoc = { ...doc, id, body: normalizeDocumentBodyForStorage(doc.body ?? "") };
|
|
97
|
+
const frontmatterSource = stringifyFrontmatter(storedDoc.frontmatter);
|
|
98
|
+
const version = versionOfBytes(stringifyWithSerializedFrontmatter(frontmatterSource, storedDoc.body));
|
|
86
99
|
// Idempotent: re-writing byte-identical content is a no-op that does not grow the
|
|
87
100
|
// chain (the content address is unchanged). A genuine content change appends a revision.
|
|
88
101
|
if (current === version)
|
|
@@ -93,7 +106,8 @@ export class MemoryBackend {
|
|
|
93
106
|
timestamp: new Date().toISOString(),
|
|
94
107
|
// Unlike `actor`, an unattested agent is simply absent — no default is applied.
|
|
95
108
|
agent: options.agent?.trim() || undefined,
|
|
96
|
-
|
|
109
|
+
frontmatterSource,
|
|
110
|
+
doc: { id, body: storedDoc.body },
|
|
97
111
|
};
|
|
98
112
|
this.chains.set(id, chain ? [revision, ...chain] : [revision]);
|
|
99
113
|
return version;
|
|
@@ -120,7 +134,7 @@ export class MemoryBackend {
|
|
|
120
134
|
}
|
|
121
135
|
async list(prefix) {
|
|
122
136
|
const ids = [...this.chains.keys()].filter((id) => !prefix || id.startsWith(prefix));
|
|
123
|
-
ids.sort(
|
|
137
|
+
ids.sort(compareStorageKeys);
|
|
124
138
|
return ids;
|
|
125
139
|
}
|
|
126
140
|
async versions(id) {
|
|
@@ -133,6 +147,7 @@ export class MemoryBackend {
|
|
|
133
147
|
}
|
|
134
148
|
async readReserved(dir, name) {
|
|
135
149
|
assertSafeReservedDir(dir);
|
|
150
|
+
assertSafeReservedFilename(name);
|
|
136
151
|
const content = this.reserved.get(reservedKey(dir, name));
|
|
137
152
|
if (content === undefined)
|
|
138
153
|
return null;
|
|
@@ -141,6 +156,7 @@ export class MemoryBackend {
|
|
|
141
156
|
}
|
|
142
157
|
async writeReserved(dir, name, content, options = {}) {
|
|
143
158
|
assertSafeReservedDir(dir);
|
|
159
|
+
assertSafeReservedFilename(name);
|
|
144
160
|
const key = reservedKey(dir, name);
|
|
145
161
|
const existing = this.reserved.get(key);
|
|
146
162
|
const current = existing === undefined ? null : versionOfBytes(existing);
|
|
@@ -207,7 +223,7 @@ export class MemoryBackend {
|
|
|
207
223
|
}
|
|
208
224
|
async listBlobs(prefix) {
|
|
209
225
|
const keys = [...this.blobs.keys()].filter((k) => !prefix || k.startsWith(prefix));
|
|
210
|
-
keys.sort(
|
|
226
|
+
keys.sort(compareStorageKeys);
|
|
211
227
|
return keys;
|
|
212
228
|
}
|
|
213
229
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-backend.js","sourceRoot":"","sources":["../src/memory-backend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"memory-backend.js","sourceRoot":"","sources":["../src/memory-backend.ts"],"names":[],"mappings":"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"}
|
package/dist/paths.d.ts
CHANGED
|
@@ -11,6 +11,10 @@
|
|
|
11
11
|
import type { ConceptId } from "./types.js";
|
|
12
12
|
/** The two OKF reserved filenames, valid at any directory level (§3.1). */
|
|
13
13
|
export declare const RESERVED_FILENAMES: readonly ["index.md", "log.md"];
|
|
14
|
+
/** Keep locale ordering, but never let distinct spellings depend on insertion order. */
|
|
15
|
+
export declare function compareStorageKeys(a: string, b: string): number;
|
|
16
|
+
/** Runtime callers must obey the same finite reserved-name type as TypeScript callers. */
|
|
17
|
+
export declare function assertSafeReservedFilename(name: unknown): asserts name is typeof RESERVED_FILENAMES[number];
|
|
14
18
|
/** Normalize any separators to forward slashes and collapse duplicate slashes. */
|
|
15
19
|
export declare function toPosix(p: string): string;
|
|
16
20
|
/**
|
|
@@ -71,8 +75,8 @@ export declare function assertSafeBlobKey(key: string): void;
|
|
|
71
75
|
* Guard a reserved-file directory (the `dir` argument to `readReserved`/`writeReserved`,
|
|
72
76
|
* where `""` denotes the bundle root) against path traversal / absolute escape before it
|
|
73
77
|
* is joined onto the bundle root. Unlike {@link assertSafeConceptId}, an empty string IS
|
|
74
|
-
* valid here (it means "the bundle root itself").
|
|
75
|
-
*
|
|
78
|
+
* valid here (it means "the bundle root itself"). Other spellings must be canonical;
|
|
79
|
+
* aliases are rejected rather than silently normalized.
|
|
76
80
|
*/
|
|
77
81
|
export declare function assertSafeReservedDir(dir: string): void;
|
|
78
82
|
//# sourceMappingURL=paths.d.ts.map
|
package/dist/paths.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG5C,2EAA2E;AAC3E,eAAO,MAAM,kBAAkB,iCAAkC,CAAC;AAElE,kFAAkF;AAClF,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEzC;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAGvD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAO5D;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,SAAS,GAAG,MAAM,CAGvD;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,SAAS,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG5C,2EAA2E;AAC3E,eAAO,MAAM,kBAAkB,iCAAkC,CAAC;AAElE,wFAAwF;AACxF,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAS/D;AAYD,0FAA0F;AAC1F,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,IAAI,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAI3G;AAED,kFAAkF;AAClF,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEzC;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAGvD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAO5D;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,SAAS,GAAG,MAAM,CAGvD;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,SAAS,GAAG,IAAI,CAWvD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAgBnD;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAKvD"}
|
package/dist/paths.js
CHANGED
|
@@ -11,6 +11,34 @@
|
|
|
11
11
|
import { InvalidInputError } from "./errors.js";
|
|
12
12
|
/** The two OKF reserved filenames, valid at any directory level (§3.1). */
|
|
13
13
|
export const RESERVED_FILENAMES = ["index.md", "log.md"];
|
|
14
|
+
/** Keep locale ordering, but never let distinct spellings depend on insertion order. */
|
|
15
|
+
export function compareStorageKeys(a, b) {
|
|
16
|
+
const primary = a.localeCompare(b);
|
|
17
|
+
if (primary !== 0 || a === b)
|
|
18
|
+
return primary;
|
|
19
|
+
const left = Array.from(a, (character) => character.codePointAt(0));
|
|
20
|
+
const right = Array.from(b, (character) => character.codePointAt(0));
|
|
21
|
+
for (let i = 0; i < Math.min(left.length, right.length); i++) {
|
|
22
|
+
if (left[i] !== right[i])
|
|
23
|
+
return left[i] - right[i];
|
|
24
|
+
}
|
|
25
|
+
return left.length - right.length;
|
|
26
|
+
}
|
|
27
|
+
/** Reject spellings that cannot remain the same key across storage and wire adapters. */
|
|
28
|
+
function assertPortablePath(value, label) {
|
|
29
|
+
if (/[\u0000-\u001f\u007f]/u.test(value) || /^[a-z]:/i.test(value)) {
|
|
30
|
+
throw new InvalidInputError(`${label} must not contain controls or start with a drive prefix.`);
|
|
31
|
+
}
|
|
32
|
+
if (value.includes("\\") || value.split("/").some((segment) => segment === "" || segment === "." || segment === "..")) {
|
|
33
|
+
throw new InvalidInputError(`${label} must be canonical and bundle-relative.`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/** Runtime callers must obey the same finite reserved-name type as TypeScript callers. */
|
|
37
|
+
export function assertSafeReservedFilename(name) {
|
|
38
|
+
if (!RESERVED_FILENAMES.includes(name)) {
|
|
39
|
+
throw new InvalidInputError("Reserved filename must be index.md or log.md.");
|
|
40
|
+
}
|
|
41
|
+
}
|
|
14
42
|
/** Normalize any separators to forward slashes and collapse duplicate slashes. */
|
|
15
43
|
export function toPosix(p) {
|
|
16
44
|
return p.replace(/\\/g, "/").replace(/\/{2,}/g, "/");
|
|
@@ -58,19 +86,8 @@ export function assertSafeConceptId(id) {
|
|
|
58
86
|
if (typeof id !== "string" || id.trim() === "") {
|
|
59
87
|
throw new InvalidInputError("Concept id must be a non-empty string.");
|
|
60
88
|
}
|
|
61
|
-
|
|
62
|
-
throw new InvalidInputError(`Concept id must be bundle-relative, got absolute '${id}'.`);
|
|
63
|
-
}
|
|
64
|
-
if (id.includes("\\")) {
|
|
65
|
-
throw new InvalidInputError(`Concept id must use forward slashes: '${id}'.`);
|
|
66
|
-
}
|
|
89
|
+
assertPortablePath(id, "Concept id");
|
|
67
90
|
const segments = id.split("/");
|
|
68
|
-
if (segments.some((seg) => seg === "..")) {
|
|
69
|
-
throw new InvalidInputError(`Concept id must not contain '..' segments: '${id}'.`);
|
|
70
|
-
}
|
|
71
|
-
if (segments.some((seg) => seg === "." || seg === "")) {
|
|
72
|
-
throw new InvalidInputError(`Concept id must be canonical (no '.', duplicate-slash, leading './', or trailing-slash segments): '${id}'.`);
|
|
73
|
-
}
|
|
74
91
|
if (segments.slice(0, -1).some((seg) => seg.toLowerCase().endsWith(".md"))) {
|
|
75
92
|
throw new InvalidInputError(`Concept id must not contain a non-final segment ending in '.md': '${id}' (it collides with a concept file at that path).`);
|
|
76
93
|
}
|
|
@@ -105,21 +122,11 @@ export function assertSafeBlobKey(key) {
|
|
|
105
122
|
if (typeof key !== "string" || key.trim() === "") {
|
|
106
123
|
throw new InvalidInputError("Blob key must be a non-empty string.");
|
|
107
124
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
throw new InvalidInputError(`Blob key must be bundle-relative, got absolute '${key}'.`);
|
|
111
|
-
}
|
|
112
|
-
const segments = norm.split("/");
|
|
113
|
-
if (segments.some((seg) => seg === "..")) {
|
|
114
|
-
throw new InvalidInputError(`Blob key must not contain '..' segments: '${key}'.`);
|
|
115
|
-
}
|
|
125
|
+
assertPortablePath(key, "Blob key");
|
|
126
|
+
const segments = key.split("/");
|
|
116
127
|
if (segments.some((seg) => seg.startsWith("."))) {
|
|
117
128
|
throw new InvalidInputError(`Blob key must not contain dot-prefixed segments: '${key}'.`);
|
|
118
129
|
}
|
|
119
|
-
const last = segments[segments.length - 1] ?? "";
|
|
120
|
-
if (last === "") {
|
|
121
|
-
throw new InvalidInputError(`Blob key must name a file, not end with '/': '${key}'.`);
|
|
122
|
-
}
|
|
123
130
|
if (segments.some((seg) => seg.toLowerCase().endsWith(".md"))) {
|
|
124
131
|
throw new InvalidInputError(`Blob key '${key}' has a path segment ending in '.md' (checked case-insensitively, at ` +
|
|
125
132
|
`any depth), which collides with the concept-document namespace — write it as a doc ` +
|
|
@@ -130,19 +137,14 @@ export function assertSafeBlobKey(key) {
|
|
|
130
137
|
* Guard a reserved-file directory (the `dir` argument to `readReserved`/`writeReserved`,
|
|
131
138
|
* where `""` denotes the bundle root) against path traversal / absolute escape before it
|
|
132
139
|
* is joined onto the bundle root. Unlike {@link assertSafeConceptId}, an empty string IS
|
|
133
|
-
* valid here (it means "the bundle root itself").
|
|
134
|
-
*
|
|
140
|
+
* valid here (it means "the bundle root itself"). Other spellings must be canonical;
|
|
141
|
+
* aliases are rejected rather than silently normalized.
|
|
135
142
|
*/
|
|
136
143
|
export function assertSafeReservedDir(dir) {
|
|
137
144
|
if (typeof dir !== "string") {
|
|
138
145
|
throw new InvalidInputError("Reserved-file directory must be a string.");
|
|
139
146
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
throw new InvalidInputError(`Reserved-file directory must be bundle-relative, got absolute '${dir}'.`);
|
|
143
|
-
}
|
|
144
|
-
if (norm.split("/").some((seg) => seg === "..")) {
|
|
145
|
-
throw new InvalidInputError(`Reserved-file directory must not contain '..' segments: '${dir}'.`);
|
|
146
|
-
}
|
|
147
|
+
if (dir !== "")
|
|
148
|
+
assertPortablePath(dir, "Reserved-file directory");
|
|
147
149
|
}
|
|
148
150
|
//# sourceMappingURL=paths.js.map
|
package/dist/paths.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD,2EAA2E;AAC3E,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAU,CAAC;AAElE,
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"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"}
|
package/dist/platform.d.ts
CHANGED
|
@@ -17,10 +17,15 @@
|
|
|
17
17
|
* presentation can report shared confirmation without an acknowledgement. It says nothing
|
|
18
18
|
* about what the authority holds now: request-driven's last exchange is the request itself,
|
|
19
19
|
* browser-local's is its last sync, and the authority may have moved (or deleted the document)
|
|
20
|
-
* since.
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
20
|
+
* since. A document the authority deleted disappears from a browser-local working copy at
|
|
21
|
+
* its next sync (pull reconciles deletions against the authority's heads) unless a local
|
|
22
|
+
* edit holds it, in which case pull retains the local content and rewrites its base to an
|
|
23
|
+
* absent shared version, and the document reads `local-pending` until push delivers the edit
|
|
24
|
+
* and settles the authority's conflict answer (a 412 whose actual version is `null`) as a
|
|
25
|
+
* conflict against an absent remote, from which point it reads `local-conflict` with
|
|
26
|
+
* `remote: null`; request-driven answers absence directly. Between syncs a deleted document
|
|
27
|
+
* still reads `shared-confirmed` at its last served version, so a presentation must not read
|
|
28
|
+
* `shared-confirmed` as proof of present existence.
|
|
24
29
|
* - `local-pending`: the working copy holds a local edit the authority has not accepted;
|
|
25
30
|
* `requestId` names the journaled intent that will deliver it and `base` the shared version
|
|
26
31
|
* the edit was made against.
|
|
@@ -111,6 +116,69 @@ export interface PlatformCommit {
|
|
|
111
116
|
changed: boolean;
|
|
112
117
|
provenance: Provenance;
|
|
113
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* Why a browser-local sync applied none of the deletions a verified listing implied:
|
|
121
|
+
* `empty-listing` names no document while the working copy holds some, `over-half` names so
|
|
122
|
+
* few that more than half of the working copy would go. Only a listing that would remove at
|
|
123
|
+
* least eight documents is bounded; fewer are applied on the authority's word.
|
|
124
|
+
*/
|
|
125
|
+
export type RefusedDeletionsReason = "empty-listing" | "over-half";
|
|
126
|
+
/**
|
|
127
|
+
* The deletions a browser-local sync refused to apply, exactly as recorded on its last pull.
|
|
128
|
+
* `digest` names the listing that implied them; a caller that has judged the shrink genuine
|
|
129
|
+
* passes the record back as {@link PlatformSyncOptions.acceptRefusedDeletions}.
|
|
130
|
+
*/
|
|
131
|
+
export interface RefusedDeletions {
|
|
132
|
+
/** How many documents the listing would have removed from the working copy. */
|
|
133
|
+
deletions: number;
|
|
134
|
+
reason: RefusedDeletionsReason;
|
|
135
|
+
/** The heads digest of the listing that was refused. */
|
|
136
|
+
digest: string;
|
|
137
|
+
}
|
|
138
|
+
/** How the runtime's last sync ended; see {@link PlatformSyncStatus.lastSync}. */
|
|
139
|
+
export interface PlatformSyncOutcome {
|
|
140
|
+
/** False when the sync rejected (a carrier failure, or an authority answer the runtime could not apply). */
|
|
141
|
+
ok: boolean;
|
|
142
|
+
/** The rejection's `name: message` when `ok` is false. */
|
|
143
|
+
error?: string;
|
|
144
|
+
/** The deletions the last completed pull refused; present until a pull applies or clears them. */
|
|
145
|
+
refusedDeletions?: RefusedDeletions;
|
|
146
|
+
}
|
|
147
|
+
export interface PlatformSyncOptions {
|
|
148
|
+
/**
|
|
149
|
+
* The refusal the last sync reported (`lastSync.refusedDeletions`), passed back to say the
|
|
150
|
+
* shrink it describes is genuine. Browser-local applies the deletions only when the
|
|
151
|
+
* authority's current listing still carries the same digest, count and reason; a listing
|
|
152
|
+
* that has moved since is refused afresh. When another realm holds the push role, a sync
|
|
153
|
+
* passing it applies nothing, records `lastSync.ok` false and rejects, so the caller can retry.
|
|
154
|
+
* One whose pull another realm supersedes twice also records `lastSync.ok` false and rejects,
|
|
155
|
+
* possibly with some deletions applied, and reports a refusal in `lastSync.refusedDeletions`
|
|
156
|
+
* for the retry to pass back: a fresh one when the listing moved, not necessarily the one
|
|
157
|
+
* passed. It is shown only while the superseding pull's marker is unfinished, and is held in
|
|
158
|
+
* memory only, so a page reload loses it; a later plain pull that refuses records it on its
|
|
159
|
+
* marker again.
|
|
160
|
+
* Request-driven ignores it: nothing is ever refused there.
|
|
161
|
+
*/
|
|
162
|
+
acceptRefusedDeletions?: RefusedDeletions;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* The runtime's relation to the authority as of its last exchange. `online` reports the
|
|
166
|
+
* carrier: it turns false only when a request could not reach the authority, never on an
|
|
167
|
+
* answer the authority gave. `lastSync` reports the sync verb itself, and is the field a
|
|
168
|
+
* presentation must show to distinguish "synchronized" from "tried and failed": `ok` is false
|
|
169
|
+
* whenever `sync` rejected, whatever the cause, with the rejection's text in `error`.
|
|
170
|
+
*
|
|
171
|
+
* Browser-local applies a verified heads listing on the authority's word, including the
|
|
172
|
+
* documents it no longer names, with one bound: a listing that would remove at least eight
|
|
173
|
+
* documents and more than half of the working copy (or every document) is refused as a whole.
|
|
174
|
+
* The refreshes in that sync still apply, nothing is removed, `lastSync.ok` stays true, and
|
|
175
|
+
* `lastSync.refusedDeletions` carries the refusal until a later pull applies or clears it. A
|
|
176
|
+
* genuine shrink of that size therefore never reconciles on its own; the recovery path is to
|
|
177
|
+
* pass the recorded refusal back as `sync({ acceptRefusedDeletions })`, which applies the
|
|
178
|
+
* deletions if the authority still lists the same state and refuses afresh if it has moved.
|
|
179
|
+
* Request-driven has no working copy and leaves `lastSync` undefined: the status is the answer
|
|
180
|
+
* to the request that produced it.
|
|
181
|
+
*/
|
|
114
182
|
export interface PlatformSyncStatus {
|
|
115
183
|
mode: ExecutionMode;
|
|
116
184
|
/** Whether the last request to the authority succeeded; `null` before any was made. */
|
|
@@ -131,6 +199,12 @@ export interface PlatformSyncStatus {
|
|
|
131
199
|
pausedReason?: string;
|
|
132
200
|
/** The runtime's working set is complete: the authority's for request-driven, a finished bootstrap for browser-local. */
|
|
133
201
|
complete: boolean;
|
|
202
|
+
/**
|
|
203
|
+
* How the last sync ended, and any deletions its pull refused. Browser-local fills it from
|
|
204
|
+
* the sync's own outcome and the pull marker (so a refusal recorded before this runtime was
|
|
205
|
+
* created still shows); request-driven leaves it undefined. Absent before any sync.
|
|
206
|
+
*/
|
|
207
|
+
lastSync?: PlatformSyncOutcome;
|
|
134
208
|
}
|
|
135
209
|
export interface PlatformRuntime {
|
|
136
210
|
capabilities(): PlatformCapabilities;
|
|
@@ -141,8 +215,12 @@ export interface PlatformRuntime {
|
|
|
141
215
|
validate(id: ConceptId): Promise<PlatformValidation>;
|
|
142
216
|
commit(id: ConceptId, edit: PlatformEdit): Promise<PlatformCommit>;
|
|
143
217
|
syncStatus(): Promise<PlatformSyncStatus>;
|
|
144
|
-
/**
|
|
145
|
-
|
|
218
|
+
/**
|
|
219
|
+
* Push pending work and pull the authority's changes; a no-op returning the status in
|
|
220
|
+
* request-driven mode. `options` carries the recovery path for refused deletions; see
|
|
221
|
+
* {@link PlatformSyncOptions}.
|
|
222
|
+
*/
|
|
223
|
+
sync(options?: PlatformSyncOptions): Promise<PlatformSyncStatus>;
|
|
146
224
|
}
|
|
147
225
|
/** The word a presentation shows for a provenance. */
|
|
148
226
|
export declare function provenanceLabel(provenance: Provenance): ProvenanceLabel;
|
package/dist/platform.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"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"}
|
package/dist/platform.js
CHANGED
|
@@ -17,10 +17,15 @@
|
|
|
17
17
|
* presentation can report shared confirmation without an acknowledgement. It says nothing
|
|
18
18
|
* about what the authority holds now: request-driven's last exchange is the request itself,
|
|
19
19
|
* browser-local's is its last sync, and the authority may have moved (or deleted the document)
|
|
20
|
-
* since.
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
20
|
+
* since. A document the authority deleted disappears from a browser-local working copy at
|
|
21
|
+
* its next sync (pull reconciles deletions against the authority's heads) unless a local
|
|
22
|
+
* edit holds it, in which case pull retains the local content and rewrites its base to an
|
|
23
|
+
* absent shared version, and the document reads `local-pending` until push delivers the edit
|
|
24
|
+
* and settles the authority's conflict answer (a 412 whose actual version is `null`) as a
|
|
25
|
+
* conflict against an absent remote, from which point it reads `local-conflict` with
|
|
26
|
+
* `remote: null`; request-driven answers absence directly. Between syncs a deleted document
|
|
27
|
+
* still reads `shared-confirmed` at its last served version, so a presentation must not read
|
|
28
|
+
* `shared-confirmed` as proof of present existence.
|
|
24
29
|
* - `local-pending`: the working copy holds a local edit the authority has not accepted;
|
|
25
30
|
* `requestId` names the journaled intent that will deliver it and `base` the shared version
|
|
26
31
|
* the edit was made against.
|
package/dist/platform.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform.js","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"platform.js","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AAkLH,sDAAsD;AACtD,MAAM,UAAU,eAAe,CAAC,UAAsB;IACpD,QAAQ,UAAU,CAAC,KAAK,EAAE,CAAC;QACzB,KAAK,kBAAkB;YACrB,OAAO,QAAQ,CAAC;QAClB,KAAK,eAAe;YAClB,OAAO,SAAS,CAAC;QACnB,KAAK,gBAAgB;YACnB,OAAO,UAAU,CAAC;IACtB,CAAC;AACH,CAAC;AAED,+GAA+G;AAC/G,MAAM,UAAU,iBAAiB,CAAC,UAAsB;IACtD,OAAO,UAAU,CAAC,KAAK,KAAK,kBAAkB,CAAC;AACjD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,OAAgB,EAAE,eAAwB,OAAO;IAC/E,OAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,OAAgB,EAAE,IAAoB,EAAE,SAAiB;IACpF,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAAgB,EAAE,IAAoB,EAAE,MAAsB,EAAE,SAAiB;IAC7G,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;AACvE,CAAC"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
export declare const EXPORT_MANIFEST = "superbee-export.json";
|
|
2
|
+
export declare const EXPORT_FORMAT = "superbee-export/1";
|
|
3
|
+
/** The host's own bounds (20,000 objects, 64 MiB stored), plus room for headers and the manifest. */
|
|
4
|
+
export declare const MAX_EXPORT_ENTRIES = 20001;
|
|
5
|
+
export declare const MAX_EXPORT_BYTES: number;
|
|
6
|
+
/** Why an archive was refused: `incomplete` is an export the host stopped; the rest are contract failures. */
|
|
7
|
+
export type ArchiveProblem = "incomplete" | "malformed" | "unsafe_path" | "manifest_mismatch" | "wrong_bundle" | "unsupported_format";
|
|
8
|
+
export declare class ExportArchiveError extends Error {
|
|
9
|
+
readonly name = "ExportArchiveError";
|
|
10
|
+
readonly problem: ArchiveProblem;
|
|
11
|
+
constructor(problem: ArchiveProblem, message: string);
|
|
12
|
+
}
|
|
13
|
+
export type EntryKind = "document" | "reserved" | "blob";
|
|
14
|
+
export interface ArchiveEntry {
|
|
15
|
+
/** The bundle-relative path the entry is placed at. */
|
|
16
|
+
readonly path: string;
|
|
17
|
+
readonly kind: EntryKind;
|
|
18
|
+
readonly bytes: Uint8Array;
|
|
19
|
+
}
|
|
20
|
+
export interface ExportSource {
|
|
21
|
+
readonly tenantId: string;
|
|
22
|
+
readonly bundleId: string;
|
|
23
|
+
readonly revision: number;
|
|
24
|
+
readonly okfEdition: string | null;
|
|
25
|
+
}
|
|
26
|
+
export interface VerifiedExport {
|
|
27
|
+
readonly source: ExportSource;
|
|
28
|
+
readonly exportedAt: string;
|
|
29
|
+
readonly counts: {
|
|
30
|
+
readonly documents: number;
|
|
31
|
+
readonly reserved: number;
|
|
32
|
+
readonly blobs: number;
|
|
33
|
+
};
|
|
34
|
+
/** Every entry but the manifest, in archive order. */
|
|
35
|
+
readonly entries: readonly ArchiveEntry[];
|
|
36
|
+
/** Stored bytes, the manifest excluded. */
|
|
37
|
+
readonly bytes: number;
|
|
38
|
+
/** A paged export's page; absent on the whole archive (and on pages once joined). */
|
|
39
|
+
readonly page?: ExportPage;
|
|
40
|
+
}
|
|
41
|
+
/** What one page of a paged export states (`page` in its manifest). */
|
|
42
|
+
export interface ExportPage {
|
|
43
|
+
/** The inventory position of the page's first object. */
|
|
44
|
+
readonly from: number;
|
|
45
|
+
/** Objects the page carries. */
|
|
46
|
+
readonly count: number;
|
|
47
|
+
/** Objects in the whole bundle. */
|
|
48
|
+
readonly total: number;
|
|
49
|
+
/** The cursor of the next page; absent on the last. */
|
|
50
|
+
readonly next?: string;
|
|
51
|
+
/** The whole bundle's counts, as every page's manifest states them. */
|
|
52
|
+
readonly counts: VerifiedExport["counts"];
|
|
53
|
+
}
|
|
54
|
+
export declare function crc32(bytes: Uint8Array): number;
|
|
55
|
+
interface RawEntry {
|
|
56
|
+
readonly name: string;
|
|
57
|
+
readonly data: Uint8Array;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* The entries of a store-only zip, strictly: one end record at the very end, a central directory
|
|
61
|
+
* that ends where it starts it, and local records laid end to end from offset zero, each stored,
|
|
62
|
+
* uncompressed, with no data descriptor and a matching CRC.
|
|
63
|
+
*/
|
|
64
|
+
export declare function readStoredZip(archive: Uint8Array): RawEntry[];
|
|
65
|
+
/** What an archive path is in a bundle, or an `unsafe_path` refusal. The core guards decide. */
|
|
66
|
+
export declare function classifyEntryPath(entryPath: string): EntryKind;
|
|
67
|
+
/**
|
|
68
|
+
* The first two paths that one folder cannot hold apart: the same file under folding, a file where
|
|
69
|
+
* a folder must be, or one folder spelled two ways (a case-insensitive disk would merge them, and
|
|
70
|
+
* the files in it would no longer be at the paths their ids name).
|
|
71
|
+
*/
|
|
72
|
+
export declare function findEntryCollision(paths: readonly string[]): readonly [string, string] | null;
|
|
73
|
+
/**
|
|
74
|
+
* Verify a whole export archive for `bundleId` and return its entries. Any failure is an
|
|
75
|
+
* {@link ExportArchiveError}; nothing is returned for an archive that is not complete and exact.
|
|
76
|
+
*/
|
|
77
|
+
export declare function verifyExport(archive: Uint8Array, bundleId: string, options?: {
|
|
78
|
+
readonly paged?: boolean;
|
|
79
|
+
}): VerifiedExport;
|
|
80
|
+
/**
|
|
81
|
+
* The pages of one paged export, checked as each arrives and joined once the last has: every page
|
|
82
|
+
* must name the first page's source (one revision, one edition), state the same whole (its total,
|
|
83
|
+
* at most an export's entries, and its counts), start where the one before ended, and only the
|
|
84
|
+
* last may name no next page. So a host that repeats or skips a page is refused at that page, and
|
|
85
|
+
* a run of pages is at most `total` long. Joined, the pages must hold every object once, add up to
|
|
86
|
+
* the bundle's counts, and keep every path apart from the others in one folder.
|
|
87
|
+
*/
|
|
88
|
+
export declare class ExportPageChain {
|
|
89
|
+
#private;
|
|
90
|
+
/** Adds the next page; answers its next cursor, or undefined once the export is whole. */
|
|
91
|
+
add(verified: VerifiedExport): string | undefined;
|
|
92
|
+
/** The whole bundle, as one archive would have carried it. */
|
|
93
|
+
joined(): VerifiedExport;
|
|
94
|
+
}
|
|
95
|
+
/** Join the verified pages of one paged export ({@link ExportPageChain}). */
|
|
96
|
+
export declare function joinExportPages(pages: readonly VerifiedExport[]): VerifiedExport;
|
|
97
|
+
/** Exact transport evidence, kept outside any materialized OKF bundle. */
|
|
98
|
+
export interface ExportProvenance {
|
|
99
|
+
readonly source: ExportSource;
|
|
100
|
+
readonly exportedAt: string;
|
|
101
|
+
/** SHA-256 and byte length of each accepted raw manifest, in page order. */
|
|
102
|
+
readonly manifests: readonly {
|
|
103
|
+
readonly sha256: string;
|
|
104
|
+
readonly bytes: number;
|
|
105
|
+
}[];
|
|
106
|
+
/** SHA-256 of UTF-8 JSON for path-sorted {path,kind,bytes,sha256} inventory rows. */
|
|
107
|
+
readonly inventorySha256: string;
|
|
108
|
+
}
|
|
109
|
+
/** Evidence for an accepted handle; refuses forged or subsequently mutated values. */
|
|
110
|
+
export declare function exportProvenance(verified: VerifiedExport): ExportProvenance;
|
|
111
|
+
/**
|
|
112
|
+
* Materialize a complete verified export in a fresh private child of an existing caller-owned
|
|
113
|
+
* parent. Returns only after every file is written. The caller owns cleanup of the returned
|
|
114
|
+
* directory and must keep that parent private while using the result. No target is overwritten,
|
|
115
|
+
* no transport metadata is written, and failure removes only this call's newly created child.
|
|
116
|
+
*/
|
|
117
|
+
export declare function materializeExport(verified: VerifiedExport, parentDirectory: string): Promise<string>;
|
|
118
|
+
export {};
|
|
119
|
+
//# sourceMappingURL=portable-export.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portable-export.d.ts","sourceRoot":"","sources":["../src/portable-export.ts"],"names":[],"mappings":"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"}
|