@superbee/core 0.2.0-pre.6 → 0.2.0-pre.8

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.
Files changed (117) hide show
  1. package/README.md +89 -0
  2. package/dist/bundle-ops.d.ts +1 -1
  3. package/dist/bundle-ops.d.ts.map +1 -1
  4. package/dist/bundle-ops.js +2 -2
  5. package/dist/bundle-ops.js.map +1 -1
  6. package/dist/engine.d.ts +1 -1
  7. package/dist/engine.d.ts.map +1 -1
  8. package/dist/engine.js +4 -3
  9. package/dist/engine.js.map +1 -1
  10. package/dist/file-journaled-backend-internal.d.ts +19 -0
  11. package/dist/file-journaled-backend-internal.d.ts.map +1 -0
  12. package/dist/file-journaled-backend-internal.js +10 -0
  13. package/dist/file-journaled-backend-internal.js.map +1 -0
  14. package/dist/file-journaled-backend.d.ts +162 -0
  15. package/dist/file-journaled-backend.d.ts.map +1 -0
  16. package/dist/file-journaled-backend.js +1113 -0
  17. package/dist/file-journaled-backend.js.map +1 -0
  18. package/dist/filesystem-lock.d.ts +10 -0
  19. package/dist/filesystem-lock.d.ts.map +1 -1
  20. package/dist/filesystem-lock.js +133 -8
  21. package/dist/filesystem-lock.js.map +1 -1
  22. package/dist/filesystem-push-role.d.ts +77 -0
  23. package/dist/filesystem-push-role.d.ts.map +1 -0
  24. package/dist/filesystem-push-role.js +165 -0
  25. package/dist/filesystem-push-role.js.map +1 -0
  26. package/dist/governed-body-write.d.ts +8 -1
  27. package/dist/governed-body-write.d.ts.map +1 -1
  28. package/dist/governed-body-write.js +9 -2
  29. package/dist/governed-body-write.js.map +1 -1
  30. package/dist/host-text.d.ts +31 -0
  31. package/dist/host-text.d.ts.map +1 -0
  32. package/dist/host-text.js +77 -0
  33. package/dist/host-text.js.map +1 -0
  34. package/dist/hosted-transport/answer-rows.d.ts +216 -0
  35. package/dist/hosted-transport/answer-rows.d.ts.map +1 -0
  36. package/dist/hosted-transport/answer-rows.js +396 -0
  37. package/dist/hosted-transport/answer-rows.js.map +1 -0
  38. package/dist/hosted-transport/carrier.d.ts +142 -0
  39. package/dist/hosted-transport/carrier.d.ts.map +1 -0
  40. package/dist/hosted-transport/carrier.js +241 -0
  41. package/dist/hosted-transport/carrier.js.map +1 -0
  42. package/dist/hosted-transport/history-pages.d.ts +55 -0
  43. package/dist/hosted-transport/history-pages.d.ts.map +1 -0
  44. package/dist/hosted-transport/history-pages.js +69 -0
  45. package/dist/hosted-transport/history-pages.js.map +1 -0
  46. package/dist/hosted-transport/index.d.ts +18 -0
  47. package/dist/hosted-transport/index.d.ts.map +1 -0
  48. package/dist/hosted-transport/index.js +18 -0
  49. package/dist/hosted-transport/index.js.map +1 -0
  50. package/dist/hosted-transport/operations.d.ts +85 -0
  51. package/dist/hosted-transport/operations.d.ts.map +1 -0
  52. package/dist/hosted-transport/operations.js +128 -0
  53. package/dist/hosted-transport/operations.js.map +1 -0
  54. package/dist/hosted-transport/paged-reads.d.ts +87 -0
  55. package/dist/hosted-transport/paged-reads.d.ts.map +1 -0
  56. package/dist/hosted-transport/paged-reads.js +238 -0
  57. package/dist/hosted-transport/paged-reads.js.map +1 -0
  58. package/dist/hosted-transport/read-adapter.d.ts +250 -0
  59. package/dist/hosted-transport/read-adapter.d.ts.map +1 -0
  60. package/dist/hosted-transport/read-adapter.js +557 -0
  61. package/dist/hosted-transport/read-adapter.js.map +1 -0
  62. package/dist/hosted-transport/root-write.d.ts +114 -0
  63. package/dist/hosted-transport/root-write.d.ts.map +1 -0
  64. package/dist/hosted-transport/root-write.js +171 -0
  65. package/dist/hosted-transport/root-write.js.map +1 -0
  66. package/dist/hosted-transport/whole-document-transport.d.ts +174 -0
  67. package/dist/hosted-transport/whole-document-transport.d.ts.map +1 -0
  68. package/dist/hosted-transport/whole-document-transport.js +411 -0
  69. package/dist/hosted-transport/whole-document-transport.js.map +1 -0
  70. package/dist/index.d.ts +5 -3
  71. package/dist/index.d.ts.map +1 -1
  72. package/dist/index.js +5 -2
  73. package/dist/index.js.map +1 -1
  74. package/dist/indexeddb-backend.d.ts +6 -1
  75. package/dist/indexeddb-backend.d.ts.map +1 -1
  76. package/dist/indexeddb-backend.js +77 -6
  77. package/dist/indexeddb-backend.js.map +1 -1
  78. package/dist/journaled-backend.d.ts +73 -5
  79. package/dist/journaled-backend.d.ts.map +1 -1
  80. package/dist/journaled-backend.js +55 -1
  81. package/dist/journaled-backend.js.map +1 -1
  82. package/dist/kinds.d.ts +25 -1
  83. package/dist/kinds.d.ts.map +1 -1
  84. package/dist/kinds.js +52 -4
  85. package/dist/kinds.js.map +1 -1
  86. package/dist/links.d.ts +1 -1
  87. package/dist/links.d.ts.map +1 -1
  88. package/dist/links.js +5 -10
  89. package/dist/links.js.map +1 -1
  90. package/dist/platform.d.ts +9 -2
  91. package/dist/platform.d.ts.map +1 -1
  92. package/dist/platform.js.map +1 -1
  93. package/dist/query-order.d.ts +22 -0
  94. package/dist/query-order.d.ts.map +1 -0
  95. package/dist/query-order.js +42 -0
  96. package/dist/query-order.js.map +1 -0
  97. package/dist/remote-backend.d.ts +56 -11
  98. package/dist/remote-backend.d.ts.map +1 -1
  99. package/dist/remote-backend.js +154 -27
  100. package/dist/remote-backend.js.map +1 -1
  101. package/dist/remote-error.d.ts +17 -1
  102. package/dist/remote-error.d.ts.map +1 -1
  103. package/dist/remote-error.js +32 -2
  104. package/dist/remote-error.js.map +1 -1
  105. package/dist/remote-operations.d.ts +5 -4
  106. package/dist/remote-operations.d.ts.map +1 -1
  107. package/dist/remote-operations.js +16 -6
  108. package/dist/remote-operations.js.map +1 -1
  109. package/dist/remote-parsers.d.ts +1 -1
  110. package/dist/remote-parsers.js +1 -1
  111. package/dist/types.d.ts +9 -4
  112. package/dist/types.d.ts.map +1 -1
  113. package/dist/uncertain-write.d.ts +45 -11
  114. package/dist/uncertain-write.d.ts.map +1 -1
  115. package/dist/uncertain-write.js +30 -9
  116. package/dist/uncertain-write.js.map +1 -1
  117. package/package.json +17 -1
@@ -0,0 +1,114 @@
1
+ /**
2
+ * The bundle's front page: one write that replaces the root `index.md` (`bundles.root.replace.v1`,
3
+ * `POST <sync prefix>/root`), compare-and-swap on the root's version or on its absence.
4
+ *
5
+ * It is not an identified write. It carries no `X-Superbee-Write-Request`, the host keeps no
6
+ * receipt of it, and there is no outcome lookup. A root version is the SHA-256 of its exact UTF-8
7
+ * bytes, so a client that lost the answer re-reads the root's version from the capabilities answer
8
+ * instead ({@link rootLanding}): the digest of what it sent means the write landed, its base means
9
+ * it did not, and anything else is a conflict. The window this leaves (the root returning to the
10
+ * same old bytes in between) is accepted for a front page.
11
+ *
12
+ * The refusal envelope is the write schema's, read by the same parser as a document write's; only
13
+ * the success differs, since it names the bundle and no document.
14
+ */
15
+ import { type AuthorizationCode } from "./answer-rows.js";
16
+ import { type HostedAnswer, type HostedCarrier } from "./carrier.js";
17
+ export declare const ROOT_OPERATION_ID = "bundles.root.replace.v1";
18
+ /** What a capabilities answer says about replacing the bundle's root `index.md`; absent reads as `"refused"`. */
19
+ export type HostedRootWrites = "allowed" | "refused";
20
+ export declare const ROOT_WRITE_BOUNDS: Readonly<{
21
+ /** The request ceiling, measured on the encoded JSON body: the same bound as every sync write. */
22
+ payloadBytes: 65536;
23
+ /** The answer is a bounded result envelope. */
24
+ answerBytes: 65536;
25
+ }>;
26
+ /** The root's version as the host computes it: `sha256:` and the hex SHA-256 of the UTF-8 bytes. */
27
+ export declare function rootVersionOf(content: string): string;
28
+ /** The body one root write sends: against `expectedVersion`, or creating a root that is absent. */
29
+ export type RootWritePayload = {
30
+ readonly bundleId: string;
31
+ readonly content: string;
32
+ readonly expectedVersion: string;
33
+ } | {
34
+ readonly bundleId: string;
35
+ readonly content: string;
36
+ readonly expectAbsent: true;
37
+ };
38
+ /** A root the transport will not send, and why: over the request bound, or content the host refuses outright. */
39
+ export declare class RootWriteInputError extends Error {
40
+ readonly name = "RootWriteInputError";
41
+ readonly code: "too_large" | "invalid_input";
42
+ constructor(code: "too_large" | "invalid_input", message: string);
43
+ }
44
+ /**
45
+ * The request a root write sends, and its encoded body, refused before anything leaves when the
46
+ * host could only refuse it: a leading byte-order mark or text that is not well formed (the host's
47
+ * version and the client's digest of it could then differ), or a body over the request bound.
48
+ */
49
+ export declare function rootWriteRequest(bundleId: string, content: string, base: string | null): {
50
+ payload: RootWritePayload;
51
+ body: string;
52
+ bytes: number;
53
+ };
54
+ /**
55
+ * One root write's outcome. `committed` names the version stored (the digest of the bytes sent).
56
+ * `conflict` is a stale base (`version_conflict`, or `document_exists` for a create that found a
57
+ * root), with the host's version when it said. `refused` applied nothing and is final;
58
+ * `authorization` is set when the refusal is about the caller, not the content. `unknown` may
59
+ * have landed: resolve it with {@link rootLanding}.
60
+ */
61
+ export type RootWriteOutcome = {
62
+ readonly kind: "committed";
63
+ readonly version: string;
64
+ readonly changed: boolean;
65
+ } | {
66
+ readonly kind: "conflict";
67
+ readonly current?: string;
68
+ } | {
69
+ readonly kind: "refused";
70
+ readonly code: string;
71
+ readonly message: string;
72
+ readonly authorization?: AuthorizationCode;
73
+ /** The host refused the request itself as malformed (`400`): nothing about the content. */
74
+ readonly malformed?: true;
75
+ } | {
76
+ readonly kind: "unknown";
77
+ };
78
+ /**
79
+ * The outcome one root write's answer stands for. The refusal rows are the identified writes'
80
+ * ({@link updateRow}), read without an identity: a refusal that says `not_applied` is final, and
81
+ * anything the host may have applied without saying so is unknown.
82
+ */
83
+ export declare function classifyRootAnswer(answer: Pick<HostedAnswer, "status" | "body">, expected: {
84
+ bundleId: string;
85
+ sent: string;
86
+ }): RootWriteOutcome;
87
+ /** The refusal codes of a root write that say only that the host was busy: the next sync sends it again. */
88
+ export declare const ROOT_BUSY_CODES: ReadonlySet<string>;
89
+ export interface RootWriteOptions {
90
+ carrier: HostedCarrier;
91
+ /** The root route, e.g. `/sync/v1/root`. */
92
+ route: string;
93
+ bundleId: string;
94
+ /** The checkout's binding (`X-Superbee-Checkout`). */
95
+ binding: string;
96
+ /** The agent the client runs under (`X-Superbee-Via`); a token {@link isAgentLabelVia} admits. */
97
+ via?: string;
98
+ content: string;
99
+ /** The root version the content replaces, or null to create a root the bundle lacks. */
100
+ base: string | null;
101
+ signal?: AbortSignal;
102
+ }
103
+ /**
104
+ * Send one root write and classify its answer. Content the host would refuse outright is refused
105
+ * here without sending ({@link rootWriteRequest}). Never sends a request identity.
106
+ */
107
+ export declare function sendRootWrite(options: RootWriteOptions): Promise<RootWriteOutcome>;
108
+ /**
109
+ * Whether a root write whose answer was lost landed, from the root version the host serves now
110
+ * (`null`: no root): the digest of the bytes sent means it landed, its base means it did not, and
111
+ * anything else is a conflict (another write moved the root).
112
+ */
113
+ export declare function rootLanding(current: string | null, sent: string, base: string | null): "landed" | "not_landed" | "conflict";
114
+ //# sourceMappingURL=root-write.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"root-write.d.ts","sourceRoot":"","sources":["../../src/hosted-transport/root-write.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,171 @@
1
+ /**
2
+ * The bundle's front page: one write that replaces the root `index.md` (`bundles.root.replace.v1`,
3
+ * `POST <sync prefix>/root`), compare-and-swap on the root's version or on its absence.
4
+ *
5
+ * It is not an identified write. It carries no `X-Superbee-Write-Request`, the host keeps no
6
+ * receipt of it, and there is no outcome lookup. A root version is the SHA-256 of its exact UTF-8
7
+ * bytes, so a client that lost the answer re-reads the root's version from the capabilities answer
8
+ * instead ({@link rootLanding}): the digest of what it sent means the write landed, its base means
9
+ * it did not, and anything else is a conflict. The window this leaves (the root returning to the
10
+ * same old bytes in between) is accepted for a front page.
11
+ *
12
+ * The refusal envelope is the write schema's, read by the same parser as a document write's; only
13
+ * the success differs, since it names the bundle and no document.
14
+ */
15
+ import { sha256HexOfUtf8 } from "../sha256.js";
16
+ import { isContentVersion } from "../version-transport.js";
17
+ import { parseWriteResult, updateRow } from "./answer-rows.js";
18
+ import { HostedCarrierError, isAgentLabelVia } from "./carrier.js";
19
+ import { WHOLE_DOCUMENT_BOUNDS } from "./whole-document-transport.js";
20
+ export const ROOT_OPERATION_ID = "bundles.root.replace.v1";
21
+ export const ROOT_WRITE_BOUNDS = Object.freeze({
22
+ /** The request ceiling, measured on the encoded JSON body: the same bound as every sync write. */
23
+ payloadBytes: WHOLE_DOCUMENT_BOUNDS.payloadBytes,
24
+ /** The answer is a bounded result envelope. */
25
+ answerBytes: WHOLE_DOCUMENT_BOUNDS.answerBytes,
26
+ });
27
+ /** The root's version as the host computes it: `sha256:` and the hex SHA-256 of the UTF-8 bytes. */
28
+ export function rootVersionOf(content) {
29
+ return `sha256:${sha256HexOfUtf8(content)}`;
30
+ }
31
+ /** A root the transport will not send, and why: over the request bound, or content the host refuses outright. */
32
+ export class RootWriteInputError extends Error {
33
+ name = "RootWriteInputError";
34
+ code;
35
+ constructor(code, message) {
36
+ super(message);
37
+ this.code = code;
38
+ }
39
+ }
40
+ const LONE_SURROGATE = /[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/;
41
+ const encoder = new TextEncoder();
42
+ /**
43
+ * The request a root write sends, and its encoded body, refused before anything leaves when the
44
+ * host could only refuse it: a leading byte-order mark or text that is not well formed (the host's
45
+ * version and the client's digest of it could then differ), or a body over the request bound.
46
+ */
47
+ export function rootWriteRequest(bundleId, content, base) {
48
+ if (base !== null && !isContentVersion(base))
49
+ throw new RootWriteInputError("invalid_input", "the root's base is not a version");
50
+ if (content.startsWith(""))
51
+ throw new RootWriteInputError("invalid_input", "the root index starts with a byte-order mark, which the host refuses");
52
+ if (LONE_SURROGATE.test(content))
53
+ throw new RootWriteInputError("invalid_input", "the root index is not well-formed text");
54
+ const payload = base === null ? { bundleId, content, expectAbsent: true } : { bundleId, content, expectedVersion: base };
55
+ const body = JSON.stringify(payload);
56
+ const bytes = encoder.encode(body).byteLength;
57
+ if (bytes > ROOT_WRITE_BOUNDS.payloadBytes)
58
+ throw new RootWriteInputError("too_large", `the root index is over the ${ROOT_WRITE_BOUNDS.payloadBytes / 1024} KiB a sync write carries (${bytes} bytes as a request)`);
59
+ return { payload, body, bytes };
60
+ }
61
+ const UNKNOWN = Object.freeze({ kind: "unknown" });
62
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
63
+ /** A root write's `200` success, admitted only for this bundle, a content version and a boolean `changed`. */
64
+ function rootSuccess(body, bundleId) {
65
+ if (!isRecord(body) || body.ok !== true || body.operationId !== ROOT_OPERATION_ID || body.error !== undefined)
66
+ return null;
67
+ const data = body.data;
68
+ if (!isRecord(data) || !Object.keys(data).every((key) => key === "bundleId" || key === "version" || key === "changed"))
69
+ return null;
70
+ if (data.bundleId !== bundleId || !isContentVersion(data.version) || typeof data.changed !== "boolean")
71
+ return null;
72
+ return { version: data.version, changed: data.changed };
73
+ }
74
+ /** The authorization code the identified writes' row for a `200` refusal carries, if any. */
75
+ function authorizationOf(code) {
76
+ try {
77
+ return updateRow(`200 ${code}`).code;
78
+ }
79
+ catch {
80
+ return undefined;
81
+ }
82
+ }
83
+ /**
84
+ * The outcome one root write's answer stands for. The refusal rows are the identified writes'
85
+ * ({@link updateRow}), read without an identity: a refusal that says `not_applied` is final, and
86
+ * anything the host may have applied without saying so is unknown.
87
+ */
88
+ export function classifyRootAnswer(answer, expected) {
89
+ const { status, body } = answer;
90
+ const error = isRecord(body) && isRecord(body.error) ? body.error : undefined;
91
+ const notApplied = error?.writeState === "not_applied";
92
+ if (status === 200) {
93
+ if (isRecord(body) && body.ok === true) {
94
+ const success = rootSuccess(body, expected.bundleId);
95
+ // A success naming other bytes than those sent is not evidence about this request.
96
+ return success && success.version === expected.sent ? { kind: "committed", ...success } : UNKNOWN;
97
+ }
98
+ let failure;
99
+ try {
100
+ failure = parseWriteResult(body, { operationIds: [ROOT_OPERATION_ID], documentId: "index.md", bundleId: expected.bundleId });
101
+ }
102
+ catch {
103
+ return UNKNOWN;
104
+ }
105
+ if (failure.ok || failure.error.writeState !== "not_applied")
106
+ return UNKNOWN;
107
+ const { code, message, currentVersion } = failure.error;
108
+ if (code === "version_conflict" || code === "document_exists")
109
+ return { kind: "conflict", ...(currentVersion !== undefined ? { current: currentVersion } : {}) };
110
+ const authorization = authorizationOf(code);
111
+ return { kind: "refused", code, message, ...(authorization ? { authorization } : {}) };
112
+ }
113
+ // A malformed binding or body: the host read nothing, and the same request can only repeat it.
114
+ if (status === 400)
115
+ return { kind: "refused", code: typeof error?.code === "string" ? error.code : "invalid_input", message: typeof error?.message === "string" ? error.message : "The host refused the request as malformed; nothing was written.", malformed: true };
116
+ if (status === 401)
117
+ return notApplied ? { kind: "refused", code: "AUTH_REQUIRED", message: "The hosted session ended; the front page was not sent.", authorization: "AUTH_REQUIRED" } : UNKNOWN;
118
+ // As the identified writes' `403` row: access withdrawn, which signing in again cannot fix.
119
+ if (status === 403)
120
+ return { kind: "refused", code: "access_withdrawn", message: "The host denied access to this bundle.", authorization: "AUTH_REQUIRED" };
121
+ if (status === 503 && notApplied)
122
+ return { kind: "refused", code: typeof error?.code === "string" ? error.code : "backend_unavailable", message: typeof error?.message === "string" ? error.message : "The host was unavailable; nothing was written." };
123
+ return UNKNOWN;
124
+ }
125
+ /** The refusal codes of a root write that say only that the host was busy: the next sync sends it again. */
126
+ export const ROOT_BUSY_CODES = new Set(["backend_unavailable", "concurrent_change", "internal_error", "deadline_exceeded", "cancelled"]);
127
+ /**
128
+ * Send one root write and classify its answer. Content the host would refuse outright is refused
129
+ * here without sending ({@link rootWriteRequest}). Never sends a request identity.
130
+ */
131
+ export async function sendRootWrite(options) {
132
+ if (options.via !== undefined && !isAgentLabelVia(options.via))
133
+ throw new TypeError("the via token is not one the host admits");
134
+ let request;
135
+ try {
136
+ request = rootWriteRequest(options.bundleId, options.content, options.base);
137
+ }
138
+ catch (error) {
139
+ if (error instanceof RootWriteInputError)
140
+ return { kind: "refused", code: error.code, message: `${error.message}; it was not sent.` };
141
+ throw error;
142
+ }
143
+ let answer;
144
+ try {
145
+ answer = await options.carrier.json(options.route, request.payload, options.signal ?? new AbortController().signal, {
146
+ maximum: ROOT_WRITE_BOUNDS.answerBytes,
147
+ binding: options.binding,
148
+ ...(options.via !== undefined ? { via: options.via } : {}),
149
+ });
150
+ }
151
+ catch (error) {
152
+ // A credential that was already gone sent nothing; anything else may have left.
153
+ if (error instanceof HostedCarrierError && error.code === "denied")
154
+ return { kind: "refused", code: "AUTH_REQUIRED", message: "No credential was available; the front page was not sent.", authorization: "AUTH_REQUIRED" };
155
+ return UNKNOWN;
156
+ }
157
+ return classifyRootAnswer(answer, { bundleId: options.bundleId, sent: rootVersionOf(options.content) });
158
+ }
159
+ /**
160
+ * Whether a root write whose answer was lost landed, from the root version the host serves now
161
+ * (`null`: no root): the digest of the bytes sent means it landed, its base means it did not, and
162
+ * anything else is a conflict (another write moved the root).
163
+ */
164
+ export function rootLanding(current, sent, base) {
165
+ if (current === sent)
166
+ return "landed";
167
+ if (current === base)
168
+ return "not_landed";
169
+ return "conflict";
170
+ }
171
+ //# sourceMappingURL=root-write.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"root-write.js","sourceRoot":"","sources":["../../src/hosted-transport/root-write.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,174 @@
1
+ /**
2
+ * The sync delivery side: an {@link OperationTransport} that pushes one whole document per
3
+ * request. The intent's kind names the operation and its base must agree with it
4
+ * ({@link WHOLE_DOCUMENT_INTENT_KINDS}): a create (`documents.create.v1`, create-only) has no
5
+ * base, a replace (`documents.replace.v1`) is against exactly the intent's base, and a delete
6
+ * (`documents.delete.v1`) removes the document at exactly the intent's base, so the host's
7
+ * compare-and-swap decides every concurrent change to one document and never merges it. Any other
8
+ * kind (a body update) or a kind its base contradicts is refused before anything is sent, and
9
+ * never mapped to another operation. The managed fields the host owns are stripped before
10
+ * sending; the host carries them from the stored document.
11
+ *
12
+ * A deleted document leaves a tombstone on the host. A create of that id is refused as a
13
+ * `version_conflict` naming the tombstone unless it acknowledges exactly the id's latest one
14
+ * (`X-Superbee-Recreate`), and the refusal comes back as the "deleted remotely" conflict carrying
15
+ * the tombstone (`{ kind: "conflict", actual: null, tombstone }`). The acknowledgement is sent
16
+ * only when the intent says so ({@link OperationIntent.recreates}); a stale one is refused again
17
+ * and comes back as a fresh conflict naming the newer tombstone, never as last-writer-wins.
18
+ *
19
+ * Every answer is mapped by the shared rows in `answer-rows.ts`, with one difference a
20
+ * create-only write needs: `document_exists` is a conflict against the served head, because a
21
+ * create that finds the document is exactly a compare-and-swap mismatch on absence.
22
+ *
23
+ * The committed version comes from the host's recorded result, and the host stores its own
24
+ * serialization (with managed fields), so a committed version is not the intent's `local`
25
+ * version. Deliver with `settlement: "recorded-only"` ({@link WHOLE_DOCUMENT_SETTLEMENT}) so a
26
+ * conflict is never read as a commit by comparing versions.
27
+ *
28
+ * `OperationTransport.lookup` names only a request identity, and the host's outcome route takes
29
+ * the same body as the write it identifies, so the transport reads the intent back from the
30
+ * journal (`intentFor`) to rebuild it.
31
+ */
32
+ import type { Frontmatter, Version } from "../types.js";
33
+ import type { OperationIntent, OperationTransport, UncertainWriteOptions } from "../uncertain-write.js";
34
+ import { DELETE_OPERATION_ID } from "./answer-rows.js";
35
+ import { type HostedCarrier } from "./carrier.js";
36
+ import { type HostedReadAdapter } from "./read-adapter.js";
37
+ /** Frontmatter the host owns; no caller may set it, and the host carries it from the stored document. */
38
+ export declare const HOSTED_MANAGED_FIELDS: ReadonlySet<string>;
39
+ /** The most frontmatter fields the kernel accepts on a create or replace. */
40
+ export declare const FRONTMATTER_KEY_LIMIT = 32;
41
+ /** The settlement mode a whole-document delivery must use. */
42
+ export declare const WHOLE_DOCUMENT_SETTLEMENT: NonNullable<UncertainWriteOptions["settlement"]>;
43
+ export declare const WHOLE_DOCUMENT_BOUNDS: Readonly<{
44
+ /**
45
+ * The write routes' request ceiling on a host that states none (`limits.documentInputBytes`); a
46
+ * larger payload is refused here before it leaves. A host that states its bound is held to that.
47
+ */
48
+ payloadBytes: 65536;
49
+ /** A write answer is a bounded result envelope. */
50
+ answerBytes: 65536;
51
+ /** An outcome answer carries the committed document as base64 under this envelope ceiling. */
52
+ outcomeAnswerBytes: number;
53
+ }>;
54
+ /**
55
+ * The whole-document write bound current hosts state (`limits.documentInputBytes`, 983,040 bytes:
56
+ * 1 MiB less a 64 KiB margin). A client plans against it only before it has asked the host, and
57
+ * holds a request to what the host actually states.
58
+ */
59
+ export declare const CURRENT_HOST_DOCUMENT_INPUT_BYTES = 983040;
60
+ export interface WholeDocumentRoutes {
61
+ create: string;
62
+ replace: string;
63
+ delete: string;
64
+ outcome: string;
65
+ }
66
+ export declare const SYNC_WRITE_ROUTES: WholeDocumentRoutes;
67
+ /**
68
+ * The exact kernel input one intent becomes, and the route and operation it goes to. A create
69
+ * that re-creates a deleted document carries the tombstone it acknowledges in `recreates`, which
70
+ * rides the `X-Superbee-Recreate` header, never the body.
71
+ */
72
+ export type WholeDocumentRequest = {
73
+ kind: "create";
74
+ operationId: "documents.create.v1";
75
+ payload: {
76
+ bundleId: string;
77
+ documentId: string;
78
+ expectAbsent: true;
79
+ frontmatter: Frontmatter;
80
+ body: string;
81
+ };
82
+ recreates?: Version;
83
+ } | {
84
+ kind: "replace";
85
+ operationId: "documents.replace.v1";
86
+ payload: {
87
+ bundleId: string;
88
+ documentId: string;
89
+ expectedVersion: Version;
90
+ frontmatter: Frontmatter;
91
+ body: string;
92
+ };
93
+ } | {
94
+ kind: "delete";
95
+ operationId: typeof DELETE_OPERATION_ID;
96
+ payload: {
97
+ bundleId: string;
98
+ documentId: string;
99
+ expectedVersion: Version;
100
+ };
101
+ };
102
+ /**
103
+ * The intent kinds this transport sends, each with the base it requires. `document.write` is the
104
+ * working-copy engine's whole-document write, a create exactly when it has no base.
105
+ * `document.delete` removes the document at exactly its base, so it requires one. Every other
106
+ * kind is unsupported: it is refused without sending, never routed by its base.
107
+ */
108
+ export declare const WHOLE_DOCUMENT_INTENT_KINDS: Readonly<Record<string, "create" | "replace" | "delete" | "by-base">>;
109
+ /**
110
+ * An intent the transport will not send, and why: the answer a `refused` outcome carries.
111
+ * `unsupported_operation` is an intent kind this transport does not send, or one its base
112
+ * contradicts; `invalid_input` is a document the host would refuse.
113
+ */
114
+ export declare class WholeDocumentInputError extends Error {
115
+ readonly name = "WholeDocumentInputError";
116
+ readonly code: "invalid_input" | "unsupported_operation";
117
+ constructor(message: string, code?: "invalid_input" | "unsupported_operation");
118
+ }
119
+ /**
120
+ * The request an intent becomes: the serialized document parsed under the bundle's edition,
121
+ * managed fields removed, a create or a replace against `base` as its kind names. The kind is
122
+ * checked first, so an unsupported kind is refused before its content is read. A document
123
+ * whose frontmatter is not plain JSON (a date object, say) is refused here, because sending it
124
+ * would change what it says.
125
+ */
126
+ export declare function wholeDocumentRequest(bundleId: string, intent: Pick<OperationIntent, "kind" | "target" | "base" | "content" | "recreates">, okfVersion?: string): WholeDocumentRequest;
127
+ export interface WholeDocumentTransportOptions {
128
+ carrier: HostedCarrier;
129
+ bundleId: string;
130
+ /** The checkout's binding, pinned on every write and lookup; the outcome answer must name it. */
131
+ binding: string;
132
+ /** The intent a request identity names, from the journal; the lookup rebuilds its request from it. */
133
+ intentFor(requestId: string): Promise<OperationIntent | undefined>;
134
+ /** The served head after a conflict without a current version, and the retention window. */
135
+ remote: Pick<HostedReadAdapter, "read" | "operationsRetentionMs">;
136
+ routes?: WholeDocumentRoutes;
137
+ /** The bundle's edition, for parsing an intent's serialized frontmatter. */
138
+ okfVersion?: string;
139
+ /** Ends every request in flight. */
140
+ signal?: AbortSignal;
141
+ now?: () => number;
142
+ /**
143
+ * The agent the client runs under (`X-Superbee-Via`), sent on every write and its lookup. It
144
+ * must be a token {@link isAgentLabelVia} admits: the transport refuses to be built otherwise.
145
+ */
146
+ via?: string;
147
+ /**
148
+ * The person's typed acknowledgment of the host's mass-delete hold (`X-Superbee-Accept-Deletes`),
149
+ * sent on every delete write of this transport and on nothing else. Set it only after the person
150
+ * confirmed that many deletions in their own terminal; never from an agent's decision.
151
+ */
152
+ acceptDeletes?: number;
153
+ /**
154
+ * The host's whole-document write bound as its capabilities answer states it
155
+ * (`documentInputBytes`), in bytes of the request's JSON. Absent or null: the host states none,
156
+ * and {@link WHOLE_DOCUMENT_BOUNDS}`.payloadBytes` applies.
157
+ */
158
+ documentInputBytes?: number | null;
159
+ /**
160
+ * Told of each delete the host's mass-delete hold refused (`428 deletions_held`), with the
161
+ * bundle's counts. The intent is settled `refused` with {@link DELETIONS_HELD_REFUSAL_CODE},
162
+ * which never pauses the store: it stays until a person accepts or restores it.
163
+ */
164
+ onDeletionsHeld?: (held: {
165
+ requestId: string;
166
+ target: string;
167
+ deletions: number;
168
+ baseline: number;
169
+ }) => void;
170
+ }
171
+ export declare function createWholeDocumentTransport(options: WholeDocumentTransportOptions): OperationTransport & {
172
+ readonly settlement: typeof WHOLE_DOCUMENT_SETTLEMENT;
173
+ };
174
+ //# sourceMappingURL=whole-document-transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whole-document-transport.d.ts","sourceRoot":"","sources":["../../src/hosted-transport/whole-document-transport.ts"],"names":[],"mappings":"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"}