@econ-v1/domain 6.7.0 → 6.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/errors/index.d.ts +96 -25
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/events/index.d.ts +127 -20
- package/dist/events/index.d.ts.map +1 -1
- package/dist/index.d.ts +250 -47
- package/dist/index.d.ts.map +1 -1
- package/dist/models/agent.d.ts +25 -4
- package/dist/models/agent.d.ts.map +1 -1
- package/dist/models/app-data.d.ts +84 -0
- package/dist/models/app-data.d.ts.map +1 -0
- package/dist/models/conversation.d.ts +12 -2
- package/dist/models/conversation.d.ts.map +1 -1
- package/dist/models/delegation.d.ts +12 -3
- package/dist/models/delegation.d.ts.map +1 -1
- package/dist/models/device-boot-state.d.ts +12 -0
- package/dist/models/device-boot-state.d.ts.map +1 -0
- package/dist/models/device-identity.d.ts +11 -3
- package/dist/models/device-identity.d.ts.map +1 -1
- package/dist/models/graph.d.ts +26 -3
- package/dist/models/graph.d.ts.map +1 -1
- package/dist/models/index.d.ts +82 -14
- package/dist/models/index.d.ts.map +1 -1
- package/dist/models/json.d.ts +5 -5
- package/dist/models/json.d.ts.map +1 -1
- package/dist/models/l402.d.ts +4 -5
- package/dist/models/l402.d.ts.map +1 -1
- package/dist/models/live-query-definition.d.ts +15 -16
- package/dist/models/live-query-definition.d.ts.map +1 -1
- package/dist/models/node-app-memory.d.ts +107 -0
- package/dist/models/node-app-memory.d.ts.map +1 -0
- package/dist/models/outbox-intent.d.ts +3 -3
- package/dist/models/outbox-intent.d.ts.map +1 -1
- package/dist/models/outbox.d.ts +67 -15
- package/dist/models/outbox.d.ts.map +1 -1
- package/dist/models/owner-views.d.ts +28 -28
- package/dist/models/owner-views.d.ts.map +1 -1
- package/dist/models/payment.d.ts +28 -9
- package/dist/models/payment.d.ts.map +1 -1
- package/dist/models/query-diff.d.ts +2 -2
- package/dist/models/query-diff.d.ts.map +1 -1
- package/dist/models/release-manifest.d.ts +32 -47
- package/dist/models/release-manifest.d.ts.map +1 -1
- package/dist/models/repository-write.d.ts +3 -3
- package/dist/models/repository-write.d.ts.map +1 -1
- package/dist/models/revisioned-commands.d.ts +66 -13
- package/dist/models/revisioned-commands.d.ts.map +1 -1
- package/dist/models/revisioned.d.ts +50 -10
- package/dist/models/revisioned.d.ts.map +1 -1
- package/dist/models/settings.d.ts +2 -2
- package/dist/models/settings.d.ts.map +1 -1
- package/dist/models/sync.d.ts +18 -18
- package/dist/models/sync.d.ts.map +1 -1
- package/dist/models/wallet.d.ts +16 -16
- package/dist/models/wallet.d.ts.map +1 -1
- package/dist/queries/certificate-trust.d.ts +13 -0
- package/dist/queries/certificate-trust.d.ts.map +1 -0
- package/dist/queries/conversations.d.ts +38 -7
- package/dist/queries/conversations.d.ts.map +1 -1
- package/dist/queries/discovery.d.ts +10 -10
- package/dist/queries/discovery.d.ts.map +1 -1
- package/dist/queries/notifications.d.ts +24 -4
- package/dist/queries/notifications.d.ts.map +1 -1
- package/dist/queries/onboarding-flow.d.ts +25 -0
- package/dist/queries/onboarding-flow.d.ts.map +1 -0
- package/dist/queries/onboarding-lcd-screen.d.ts +56 -0
- package/dist/queries/onboarding-lcd-screen.d.ts.map +1 -0
- package/dist/queries/onboarding-status.d.ts +10 -10
- package/dist/queries/onboarding-status.d.ts.map +1 -1
- package/dist/queries/revisioned.d.ts +47 -13
- package/dist/queries/revisioned.d.ts.map +1 -1
- package/dist/queries/wallet.d.ts +40 -10
- package/dist/queries/wallet.d.ts.map +1 -1
- package/dist/services/abort-signal.d.ts +54 -0
- package/dist/services/abort-signal.d.ts.map +1 -0
- package/dist/services/certificate-trust-service.d.ts +42 -0
- package/dist/services/certificate-trust-service.d.ts.map +1 -0
- package/dist/services/conversation-service.d.ts +103 -15
- package/dist/services/conversation-service.d.ts.map +1 -1
- package/dist/services/conversation-sync.d.ts +9 -5
- package/dist/services/conversation-sync.d.ts.map +1 -1
- package/dist/services/device-boot-state-service.d.ts +17 -0
- package/dist/services/device-boot-state-service.d.ts.map +1 -0
- package/dist/services/device-cleanup-service.d.ts +47 -0
- package/dist/services/device-cleanup-service.d.ts.map +1 -0
- package/dist/services/discovery-probe-service.d.ts +37 -46
- package/dist/services/discovery-probe-service.d.ts.map +1 -1
- package/dist/services/gossip-service.d.ts +28 -13
- package/dist/services/gossip-service.d.ts.map +1 -1
- package/dist/services/invite-redemption-service.d.ts +43 -0
- package/dist/services/invite-redemption-service.d.ts.map +1 -0
- package/dist/services/lan-candidate-refresh-service.d.ts +22 -7
- package/dist/services/lan-candidate-refresh-service.d.ts.map +1 -1
- package/dist/services/lcd-decision-service.d.ts +58 -0
- package/dist/services/lcd-decision-service.d.ts.map +1 -0
- package/dist/services/onboarding-checkpoint-store.d.ts +54 -0
- package/dist/services/onboarding-checkpoint-store.d.ts.map +1 -0
- package/dist/services/onboarding-flow-service.d.ts +180 -0
- package/dist/services/onboarding-flow-service.d.ts.map +1 -0
- package/dist/services/onboarding-status-service.d.ts +21 -38
- package/dist/services/onboarding-status-service.d.ts.map +1 -1
- package/dist/services/outbox-service.d.ts +105 -29
- package/dist/services/outbox-service.d.ts.map +1 -1
- package/dist/services/owner-claim-service.d.ts +187 -0
- package/dist/services/owner-claim-service.d.ts.map +1 -0
- package/dist/services/owner-view-refresh-service.d.ts +40 -0
- package/dist/services/owner-view-refresh-service.d.ts.map +1 -0
- package/dist/services/owner-view-service.d.ts +49 -4
- package/dist/services/owner-view-service.d.ts.map +1 -1
- package/dist/services/peer-directory-service.d.ts +53 -17
- package/dist/services/peer-directory-service.d.ts.map +1 -1
- package/dist/services/release-manifest-verifier.d.ts +18 -20
- package/dist/services/release-manifest-verifier.d.ts.map +1 -1
- package/dist/services/revisioned-domain-service.d.ts +50 -17
- package/dist/services/revisioned-domain-service.d.ts.map +1 -1
- package/dist/services/runtime-globals.d.ts +39 -0
- package/dist/services/runtime-globals.d.ts.map +1 -0
- package/dist/services/session-service.d.ts +23 -3
- package/dist/services/session-service.d.ts.map +1 -1
- package/dist/services/sync/authoritative-mirror.d.ts +88 -15
- package/dist/services/sync/authoritative-mirror.d.ts.map +1 -1
- package/dist/services/sync/index.d.ts +17 -5
- package/dist/services/sync/index.d.ts.map +1 -1
- package/dist/services/sync/log-sync.d.ts +42 -8
- package/dist/services/sync/log-sync.d.ts.map +1 -1
- package/dist/services/sync/revision-merge.d.ts +80 -13
- package/dist/services/sync/revision-merge.d.ts.map +1 -1
- package/dist/services/sync/strategy.d.ts +11 -1
- package/dist/services/sync/strategy.d.ts.map +1 -1
- package/dist/services/transport-manager.d.ts +84 -29
- package/dist/services/transport-manager.d.ts.map +1 -1
- package/dist/services/wallet-mirror-service.d.ts +81 -18
- package/dist/services/wallet-mirror-service.d.ts.map +1 -1
- package/dist/services/wifi-provisioning-service.d.ts +146 -0
- package/dist/services/wifi-provisioning-service.d.ts.map +1 -0
- package/package.json +18 -12
- package/src/errors/index.js +126 -0
- package/src/events/index.js +124 -0
- package/src/index.js +566 -0
- package/src/models/agent.js +43 -0
- package/src/models/app-data.js +122 -0
- package/src/models/conversation.js +36 -0
- package/{dist → src}/models/delegation.js +18 -1
- package/src/models/device-boot-state.js +3 -0
- package/{dist → src}/models/device-identity.js +18 -2
- package/{dist → src}/models/graph.js +30 -3
- package/src/models/index.js +175 -0
- package/src/models/json.js +18 -0
- package/src/models/l402.js +9 -0
- package/src/models/live-query-definition.js +30 -0
- package/src/models/node-app-memory.js +130 -0
- package/src/models/outbox-intent.js +12 -0
- package/{dist → src}/models/outbox.js +102 -3
- package/src/models/owner-views.js +59 -0
- package/src/models/payment.js +24 -0
- package/src/models/query-diff.js +7 -0
- package/src/models/release-manifest.js +160 -0
- package/src/models/repository-write.js +10 -0
- package/src/models/revisioned-commands.js +92 -0
- package/src/models/revisioned.js +41 -0
- package/src/models/settings.js +16 -0
- package/src/models/sync.js +44 -0
- package/src/models/wallet.js +40 -0
- package/src/queries/certificate-trust.js +31 -0
- package/{dist → src}/queries/conversations.js +54 -3
- package/src/queries/discovery.js +34 -0
- package/{dist → src}/queries/notifications.js +25 -2
- package/src/queries/onboarding-flow.js +48 -0
- package/src/queries/onboarding-lcd-screen.js +100 -0
- package/src/queries/onboarding-status.js +34 -0
- package/src/queries/revisioned.js +128 -0
- package/{dist → src}/queries/wallet.js +35 -1
- package/src/services/abort-signal.js +69 -0
- package/src/services/certificate-trust-service.js +119 -0
- package/{dist → src}/services/conversation-service.js +108 -1
- package/src/services/conversation-sync.js +28 -0
- package/src/services/device-boot-state-service.js +45 -0
- package/src/services/device-cleanup-service.js +112 -0
- package/src/services/discovery-probe-service.js +196 -0
- package/{dist → src}/services/gossip-service.js +54 -4
- package/src/services/invite-redemption-service.js +64 -0
- package/src/services/lan-candidate-refresh-service.js +164 -0
- package/src/services/lcd-decision-service.js +93 -0
- package/src/services/onboarding-checkpoint-store.js +155 -0
- package/src/services/onboarding-flow-service.js +1096 -0
- package/src/services/onboarding-status-service.js +64 -0
- package/{dist → src}/services/outbox-service.js +132 -1
- package/src/services/owner-claim-service.js +347 -0
- package/src/services/owner-view-refresh-service.js +208 -0
- package/src/services/owner-view-service.js +87 -0
- package/{dist → src}/services/peer-directory-service.js +72 -3
- package/src/services/release-manifest-verifier.js +108 -0
- package/{dist → src}/services/revisioned-domain-service.js +189 -9
- package/src/services/runtime-globals.js +174 -0
- package/src/services/session-service.js +50 -0
- package/{dist → src}/services/sync/authoritative-mirror.js +90 -1
- package/src/services/sync/index.js +67 -0
- package/src/services/sync/log-sync.js +60 -0
- package/src/services/sync/revision-merge.js +119 -0
- package/src/services/sync/strategy.js +44 -0
- package/src/services/transport-manager.js +478 -0
- package/{dist → src}/services/wallet-mirror-service.js +226 -6
- package/src/services/wifi-provisioning-service.js +278 -0
- package/dist/errors/index.js +0 -45
- package/dist/errors/index.js.map +0 -1
- package/dist/events/index.js +0 -17
- package/dist/events/index.js.map +0 -1
- package/dist/index.js +0 -31
- package/dist/index.js.map +0 -1
- package/dist/models/agent.js +0 -17
- package/dist/models/agent.js.map +0 -1
- package/dist/models/conversation.js +0 -2
- package/dist/models/conversation.js.map +0 -1
- package/dist/models/delegation.js.map +0 -1
- package/dist/models/device-identity.js.map +0 -1
- package/dist/models/graph.js.map +0 -1
- package/dist/models/index.js +0 -8
- package/dist/models/index.js.map +0 -1
- package/dist/models/json.js +0 -2
- package/dist/models/json.js.map +0 -1
- package/dist/models/l402.js +0 -2
- package/dist/models/l402.js.map +0 -1
- package/dist/models/live-query-definition.js +0 -2
- package/dist/models/live-query-definition.js.map +0 -1
- package/dist/models/outbox-intent.js +0 -2
- package/dist/models/outbox-intent.js.map +0 -1
- package/dist/models/outbox.js.map +0 -1
- package/dist/models/owner-views.js +0 -7
- package/dist/models/owner-views.js.map +0 -1
- package/dist/models/payment.js +0 -3
- package/dist/models/payment.js.map +0 -1
- package/dist/models/query-diff.js +0 -2
- package/dist/models/query-diff.js.map +0 -1
- package/dist/models/release-manifest.js +0 -147
- package/dist/models/release-manifest.js.map +0 -1
- package/dist/models/repository-write.js +0 -2
- package/dist/models/repository-write.js.map +0 -1
- package/dist/models/revisioned-commands.js +0 -35
- package/dist/models/revisioned-commands.js.map +0 -1
- package/dist/models/revisioned.js +0 -2
- package/dist/models/revisioned.js.map +0 -1
- package/dist/models/settings.js +0 -2
- package/dist/models/settings.js.map +0 -1
- package/dist/models/sync.js +0 -2
- package/dist/models/sync.js.map +0 -1
- package/dist/models/wallet.js +0 -2
- package/dist/models/wallet.js.map +0 -1
- package/dist/queries/conversations.js.map +0 -1
- package/dist/queries/discovery.js +0 -27
- package/dist/queries/discovery.js.map +0 -1
- package/dist/queries/notifications.js.map +0 -1
- package/dist/queries/onboarding-status.js +0 -27
- package/dist/queries/onboarding-status.js.map +0 -1
- package/dist/queries/revisioned.js +0 -58
- package/dist/queries/revisioned.js.map +0 -1
- package/dist/queries/wallet.js.map +0 -1
- package/dist/services/conversation-service.js.map +0 -1
- package/dist/services/conversation-sync.js +0 -9
- package/dist/services/conversation-sync.js.map +0 -1
- package/dist/services/discovery-probe-service.js +0 -129
- package/dist/services/discovery-probe-service.js.map +0 -1
- package/dist/services/gossip-service.js.map +0 -1
- package/dist/services/lan-candidate-refresh-service.js +0 -79
- package/dist/services/lan-candidate-refresh-service.js.map +0 -1
- package/dist/services/onboarding-status-service.js +0 -32
- package/dist/services/onboarding-status-service.js.map +0 -1
- package/dist/services/outbox-service.js.map +0 -1
- package/dist/services/owner-view-service.js +0 -21
- package/dist/services/owner-view-service.js.map +0 -1
- package/dist/services/peer-directory-service.js.map +0 -1
- package/dist/services/release-manifest-verifier.js +0 -84
- package/dist/services/release-manifest-verifier.js.map +0 -1
- package/dist/services/revisioned-domain-service.js.map +0 -1
- package/dist/services/session-service.js +0 -20
- package/dist/services/session-service.js.map +0 -1
- package/dist/services/sync/authoritative-mirror.js.map +0 -1
- package/dist/services/sync/index.js +0 -4
- package/dist/services/sync/index.js.map +0 -1
- package/dist/services/sync/log-sync.js +0 -20
- package/dist/services/sync/log-sync.js.map +0 -1
- package/dist/services/sync/revision-merge.js +0 -46
- package/dist/services/sync/revision-merge.js.map +0 -1
- package/dist/services/sync/strategy.js +0 -2
- package/dist/services/sync/strategy.js.map +0 -1
- package/dist/services/transport-manager.js +0 -234
- package/dist/services/transport-manager.js.map +0 -1
- package/dist/services/wallet-mirror-service.js.map +0 -1
|
@@ -1,4 +1,42 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {import("./json.js").JsonValue} JsonValue
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {(typeof OUTBOX_STATES)[number]} OutboxState
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* @typedef {"acknowledged" | "replaying"} LegacyOutboxState
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* @typedef {OutboxState | LegacyOutboxState} OutboxIntentState
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* @typedef {"authoritative" | "eventual"} OutboxAuthority
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* @typedef {{ readonly expiresAt: string; readonly owner: string; }} OutboxLease
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* @typedef {{ readonly authority?: OutboxAuthority; readonly attemptCount?: number; readonly conflictReason?: string; readonly createdAt?: string; readonly domain: string; readonly id: string; readonly idempotencyKey: string; readonly lease?: OutboxLease; readonly maxAttempts?: number; readonly payload: JsonValue; readonly state: OutboxIntentState; readonly terminalReason?: string; readonly updatedAt?: string; }} OutboxIntent
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* @typedef {Omit<OutboxIntent, "attemptCount" | "createdAt" | "maxAttempts" | "state" | "updatedAt"> & { readonly attemptCount?: number; readonly createdAt?: string; readonly maxAttempts?: number; readonly state?: OutboxIntentState; readonly updatedAt?: string; }} OutboxIntentInput
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* @typedef {OutboxIntent & { readonly authority: OutboxAuthority; readonly attemptCount: number; readonly createdAt: string; readonly maxAttempts: number; readonly state: OutboxState; readonly updatedAt: string; }} OutboxEntry
|
|
29
|
+
*/
|
|
30
|
+
/**
|
|
31
|
+
* @typedef {{ readonly maxAttempts?: number; readonly now?: string; }} OutboxIntentOptions
|
|
32
|
+
*/
|
|
33
|
+
/** @type {readonly ["pending", "inflight", "acked", "failed", "conflict"]} */
|
|
1
34
|
export const OUTBOX_STATES = ["pending", "inflight", "acked", "failed", "conflict"];
|
|
35
|
+
/**
|
|
36
|
+
* @param {OutboxIntentInput} input
|
|
37
|
+
* @param {OutboxIntentOptions} [options]
|
|
38
|
+
* @returns {OutboxEntry}
|
|
39
|
+
*/
|
|
2
40
|
export function createOutboxIntent(input, options = {}) {
|
|
3
41
|
const now = options.now ?? input.updatedAt ?? input.createdAt ?? new Date().toISOString();
|
|
4
42
|
return validateOutboxIntent({
|
|
@@ -9,6 +47,10 @@ export function createOutboxIntent(input, options = {}) {
|
|
|
9
47
|
updatedAt: input.updatedAt ?? now,
|
|
10
48
|
});
|
|
11
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* @param {unknown} value
|
|
52
|
+
* @returns {OutboxEntry}
|
|
53
|
+
*/
|
|
12
54
|
export function validateOutboxIntent(value) {
|
|
13
55
|
if (!isRecord(value))
|
|
14
56
|
throw invalid("outbox intent must be an object");
|
|
@@ -49,15 +91,23 @@ export function validateOutboxIntent(value) {
|
|
|
49
91
|
updatedAt,
|
|
50
92
|
});
|
|
51
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* @param {unknown} state
|
|
96
|
+
* @returns {OutboxState}
|
|
97
|
+
*/
|
|
52
98
|
export function fromPublicOutboxState(state) {
|
|
53
99
|
if (state === "replaying")
|
|
54
100
|
return "inflight";
|
|
55
101
|
if (state === "acknowledged")
|
|
56
102
|
return "acked";
|
|
57
|
-
if (
|
|
103
|
+
if (isOutboxState(state))
|
|
58
104
|
return state;
|
|
59
105
|
throw invalid("outbox state");
|
|
60
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* @param {OutboxState} state
|
|
109
|
+
* @returns {Exclude<OutboxIntentState, OutboxState> | OutboxState}
|
|
110
|
+
*/
|
|
61
111
|
export function toPublicOutboxState(state) {
|
|
62
112
|
if (state === "inflight")
|
|
63
113
|
return "replaying";
|
|
@@ -67,14 +117,22 @@ export function toPublicOutboxState(state) {
|
|
|
67
117
|
return "failed";
|
|
68
118
|
return state;
|
|
69
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* @param {JsonValue} value
|
|
122
|
+
* @returns {string}
|
|
123
|
+
*/
|
|
70
124
|
export function canonicalOutboxPayload(value) {
|
|
71
125
|
if (Array.isArray(value))
|
|
72
126
|
return `[${value.map(canonicalOutboxPayload).join(",")}]`;
|
|
73
127
|
if (value !== null && typeof value === "object") {
|
|
74
|
-
return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonicalOutboxPayload(value[key])}`).join(",")}}`;
|
|
128
|
+
return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonicalOutboxPayload(/** @type {JsonValue} */ (value[key]))}`).join(",")}}`;
|
|
75
129
|
}
|
|
76
130
|
return JSON.stringify(value);
|
|
77
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* @param {JsonValue} value
|
|
134
|
+
* @returns {JsonValue}
|
|
135
|
+
*/
|
|
78
136
|
function cloneJson(value) {
|
|
79
137
|
if (Array.isArray(value))
|
|
80
138
|
return value.map(cloneJson);
|
|
@@ -83,6 +141,11 @@ function cloneJson(value) {
|
|
|
83
141
|
}
|
|
84
142
|
return value;
|
|
85
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* @template T
|
|
146
|
+
* @param {T} value
|
|
147
|
+
* @returns {T}
|
|
148
|
+
*/
|
|
86
149
|
function deepFreeze(value) {
|
|
87
150
|
if (value !== null && typeof value === "object" && !Object.isFrozen(value)) {
|
|
88
151
|
Object.freeze(value);
|
|
@@ -91,6 +154,10 @@ function deepFreeze(value) {
|
|
|
91
154
|
}
|
|
92
155
|
return value;
|
|
93
156
|
}
|
|
157
|
+
/**
|
|
158
|
+
* @param {unknown} value
|
|
159
|
+
* @returns {value is JsonValue}
|
|
160
|
+
*/
|
|
94
161
|
function isJsonValue(value) {
|
|
95
162
|
if (value === null || typeof value === "boolean" || typeof value === "string")
|
|
96
163
|
return true;
|
|
@@ -102,26 +169,59 @@ function isJsonValue(value) {
|
|
|
102
169
|
return false;
|
|
103
170
|
return Object.values(value).every(isJsonValue);
|
|
104
171
|
}
|
|
172
|
+
/**
|
|
173
|
+
* @param {unknown} value
|
|
174
|
+
* @returns {value is OutboxState}
|
|
175
|
+
*/
|
|
176
|
+
function isOutboxState(value) {
|
|
177
|
+
return typeof value === "string" && OUTBOX_STATES.includes(/** @type {OutboxState} */ (value));
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* @param {unknown} value
|
|
181
|
+
* @returns {value is number}
|
|
182
|
+
*/
|
|
105
183
|
function isNonNegativeInteger(value) {
|
|
106
184
|
return typeof value === "number" && Number.isInteger(value) && value >= 0;
|
|
107
185
|
}
|
|
186
|
+
/**
|
|
187
|
+
* @param {unknown} value
|
|
188
|
+
* @returns {value is Record<string, unknown>}
|
|
189
|
+
*/
|
|
108
190
|
function isRecord(value) {
|
|
109
191
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
110
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* @param {string} message
|
|
195
|
+
* @returns {TypeError}
|
|
196
|
+
*/
|
|
111
197
|
function invalid(message) {
|
|
112
198
|
return new TypeError(message);
|
|
113
199
|
}
|
|
200
|
+
/**
|
|
201
|
+
* @param {unknown} value
|
|
202
|
+
* @param {string} label
|
|
203
|
+
* @returns {string}
|
|
204
|
+
*/
|
|
114
205
|
function requiredString(value, label) {
|
|
115
206
|
if (typeof value !== "string" || value.trim() === "")
|
|
116
207
|
throw invalid(`${label} must be a non-empty string`);
|
|
117
208
|
return value;
|
|
118
209
|
}
|
|
210
|
+
/**
|
|
211
|
+
* @param {unknown} value
|
|
212
|
+
* @param {string} label
|
|
213
|
+
* @returns {string}
|
|
214
|
+
*/
|
|
119
215
|
function requiredTimestamp(value, label) {
|
|
120
216
|
const timestamp = requiredString(value, label);
|
|
121
217
|
if (!Number.isFinite(Date.parse(timestamp)))
|
|
122
218
|
throw invalid(`${label} must be an ISO timestamp`);
|
|
123
219
|
return timestamp;
|
|
124
220
|
}
|
|
221
|
+
/**
|
|
222
|
+
* @param {unknown} value
|
|
223
|
+
* @returns {OutboxLease}
|
|
224
|
+
*/
|
|
125
225
|
function validateLease(value) {
|
|
126
226
|
if (!isRecord(value))
|
|
127
227
|
throw invalid("outbox lease");
|
|
@@ -130,4 +230,3 @@ function validateLease(value) {
|
|
|
130
230
|
owner: requiredString(value.owner, "outbox lease owner"),
|
|
131
231
|
});
|
|
132
232
|
}
|
|
133
|
-
//# sourceMappingURL=outbox.js.map
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {(typeof OWNER_VIEW_SYNC_STRATEGIES)[keyof typeof OWNER_VIEW_SYNC_STRATEGIES]} OwnerViewSyncStrategy
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {"offline" | "online" | "unknown"} HomeStatus
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* @typedef {{ readonly cachedAt?: string; readonly displayName: string; readonly homeNodeId: string; readonly lastSyncedAt?: string; readonly status: HomeStatus; }} HomeSummary
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* @typedef {"offline" | "online" | "unknown"} PeerStatus
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* @typedef {{ readonly displayName: string; readonly id: string; readonly lastSeenAt?: string; readonly status: PeerStatus; }} PeerDirectoryEntry
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* @typedef {{ readonly limit?: number; readonly status?: PeerStatus; }} PeerDirectoryQuery
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* @typedef {"activity" | "message" | "system"} FeedItemKind
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* @typedef {{ readonly body: string; readonly createdAt: string; readonly id: string; readonly kind: FeedItemKind; readonly read: boolean; readonly title: string; }} FeedItem
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* @typedef {{ readonly before?: string; readonly limit?: number; readonly unreadOnly?: boolean; }} FeedQuery
|
|
29
|
+
*/
|
|
30
|
+
/**
|
|
31
|
+
* @typedef {"blocked" | "ready" | "recovering"} StorageStatus
|
|
32
|
+
*/
|
|
33
|
+
/**
|
|
34
|
+
* @typedef {"current" | "stale" | "syncing"} SyncStatus
|
|
35
|
+
*/
|
|
36
|
+
/**
|
|
37
|
+
* @typedef {"iroh-relay" | "lan-direct" | "lan-webtransport" | "offline" | "wan-direct" | "webrtc-direct"} OperationalTransport
|
|
38
|
+
*/
|
|
39
|
+
/**
|
|
40
|
+
* @typedef {{ readonly cachedAt?: string; readonly outboxDepth: number; readonly storage: StorageStatus; readonly sync: SyncStatus; readonly transport: OperationalTransport; }} OperationalSummary
|
|
41
|
+
*/
|
|
42
|
+
/**
|
|
43
|
+
* Owner-facing read views projected from the home node.
|
|
44
|
+
*
|
|
45
|
+
* Implementations MUST NOT depend on the durable, OPFS-backed local SQLite
|
|
46
|
+
* cache. This port models what the home node currently reports, so every
|
|
47
|
+
* method resolves from in-memory state or a home-node round trip. The kernel
|
|
48
|
+
* relies on that prohibition to keep owner-view live queries available in
|
|
49
|
+
* degraded mode when a browser cannot provide OPFS. A storage-backed
|
|
50
|
+
* projection belongs behind its own repository port instead.
|
|
51
|
+
*
|
|
52
|
+
* @typedef {{ listFeed(params: FeedQuery): Promise<readonly FeedItem[]>; listPeers(params: PeerDirectoryQuery): Promise<readonly PeerDirectoryEntry[]>; readHomeSummary(): Promise<HomeSummary | undefined>; readOperationalSummary(): Promise<OperationalSummary | undefined>; }} OwnerViewRepository
|
|
53
|
+
*/
|
|
54
|
+
export const OWNER_VIEW_SYNC_STRATEGIES = {
|
|
55
|
+
feeds: "log",
|
|
56
|
+
home: "authoritative",
|
|
57
|
+
operations: "authoritative",
|
|
58
|
+
peers: "log",
|
|
59
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {(typeof PAYMENT_DIRECTIONS)[number]} PaymentDirection
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {(typeof PAYMENT_STATUSES)[number]} PaymentStatus
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* @typedef {{ readonly amountMsat: number; readonly createdAt: string; readonly direction: PaymentDirection; readonly failureCode?: string; readonly id: string; readonly paymentHash?: string; readonly status: PaymentStatus; readonly updatedAt: string; }} PaymentRecord
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* @typedef {{ readonly amountMsat: number; readonly invoiceId: string; readonly kind: "invoice-created"; readonly paymentHash?: string; readonly paymentRequest: string; readonly status: "created"; }} InvoiceCreatedResult
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* @typedef {{ readonly amountMsat: number; readonly kind: "payment-submitted"; readonly paymentHash?: string; readonly paymentId: string; readonly status: Exclude<PaymentStatus, "expired">; }} PaymentSubmittedResult
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* @typedef {InvoiceCreatedResult | PaymentSubmittedResult} WalletCommandResult
|
|
20
|
+
*/
|
|
21
|
+
/** @type {readonly ["incoming", "outgoing"]} */
|
|
22
|
+
export const PAYMENT_DIRECTIONS = ["incoming", "outgoing"];
|
|
23
|
+
/** @type {readonly ["pending", "succeeded", "failed", "expired"]} */
|
|
24
|
+
export const PAYMENT_STATUSES = ["pending", "succeeded", "failed", "expired"];
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
/** @typedef {import("./json.js").JsonObject} JsonObject */
|
|
4
|
+
|
|
5
|
+
export const RELEASE_MANIFEST_VERSION = 1;
|
|
6
|
+
|
|
7
|
+
export const RELEASE_MANIFEST_LIMITS = {
|
|
8
|
+
maxBuildIdLength: 128,
|
|
9
|
+
maxChannelLength: 64,
|
|
10
|
+
maxShellAssetUrlLength: 2048,
|
|
11
|
+
maxShellAssets: 4096,
|
|
12
|
+
maxShellVersionLength: 64,
|
|
13
|
+
maxSigningKeyIdLength: 128,
|
|
14
|
+
maxVersionValue: 1_000_000,
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/** @typedef {{ readonly sha256: string, readonly url: string }} ReleaseManifestAsset */
|
|
18
|
+
/** @typedef {{ readonly max: number, readonly min: number }} ReleaseManifestVersionRange */
|
|
19
|
+
/** @typedef {{ readonly buildId: string, readonly channel: string, readonly issuedAtMs: number, readonly manifestVersion: 1, readonly protocolCompatibility: ReleaseManifestVersionRange, readonly shellAssets: readonly ReleaseManifestAsset[], readonly shellVersion: string, readonly signingKeyId: string, readonly storageSchemaCompatibility: ReleaseManifestVersionRange }} UnsignedReleaseManifest */
|
|
20
|
+
/** @typedef {UnsignedReleaseManifest & { readonly signature: string }} SignedReleaseManifest */
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @param {UnsignedReleaseManifest} manifest
|
|
24
|
+
* @returns {JsonObject}
|
|
25
|
+
*/
|
|
26
|
+
export function unsignedReleaseManifestToJson(manifest) {
|
|
27
|
+
return {
|
|
28
|
+
buildId: manifest.buildId,
|
|
29
|
+
channel: manifest.channel,
|
|
30
|
+
issuedAtMs: manifest.issuedAtMs,
|
|
31
|
+
manifestVersion: manifest.manifestVersion,
|
|
32
|
+
protocolCompatibility: {
|
|
33
|
+
max: manifest.protocolCompatibility.max,
|
|
34
|
+
min: manifest.protocolCompatibility.min,
|
|
35
|
+
},
|
|
36
|
+
shellAssets: manifest.shellAssets.map((asset) => ({ sha256: asset.sha256, url: asset.url })),
|
|
37
|
+
shellVersion: manifest.shellVersion,
|
|
38
|
+
signingKeyId: manifest.signingKeyId,
|
|
39
|
+
storageSchemaCompatibility: {
|
|
40
|
+
max: manifest.storageSchemaCompatibility.max,
|
|
41
|
+
min: manifest.storageSchemaCompatibility.min,
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const HEX_64_BYTES = /^[0-9a-f]{128}$/u;
|
|
47
|
+
const SHA256_HEX = /^[0-9a-f]{64}$/u;
|
|
48
|
+
const CHANNEL_PATTERN = /^[a-z][a-z0-9-]{0,63}$/u;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @param {unknown} candidate
|
|
52
|
+
* @returns {SignedReleaseManifest | undefined}
|
|
53
|
+
*/
|
|
54
|
+
export function parseSignedReleaseManifest(candidate) {
|
|
55
|
+
if (typeof candidate !== "object" || candidate === null || Array.isArray(candidate)) return undefined;
|
|
56
|
+
const value = /** @type {Record<string, unknown>} */ (candidate);
|
|
57
|
+
|
|
58
|
+
if (value.manifestVersion !== RELEASE_MANIFEST_VERSION) return undefined;
|
|
59
|
+
|
|
60
|
+
const buildId = boundedString(value.buildId, 1, RELEASE_MANIFEST_LIMITS.maxBuildIdLength);
|
|
61
|
+
if (buildId === undefined) return undefined;
|
|
62
|
+
|
|
63
|
+
const channel = typeof value.channel === "string" && CHANNEL_PATTERN.test(value.channel)
|
|
64
|
+
? value.channel
|
|
65
|
+
: undefined;
|
|
66
|
+
if (channel === undefined || channel.length > RELEASE_MANIFEST_LIMITS.maxChannelLength) return undefined;
|
|
67
|
+
|
|
68
|
+
if (!isSafeNonNegativeInteger(value.issuedAtMs)) return undefined;
|
|
69
|
+
|
|
70
|
+
const signingKeyId = boundedString(value.signingKeyId, 1, RELEASE_MANIFEST_LIMITS.maxSigningKeyIdLength);
|
|
71
|
+
if (signingKeyId === undefined) return undefined;
|
|
72
|
+
|
|
73
|
+
const shellVersion = boundedString(value.shellVersion, 1, RELEASE_MANIFEST_LIMITS.maxShellVersionLength);
|
|
74
|
+
if (shellVersion === undefined) return undefined;
|
|
75
|
+
|
|
76
|
+
const signature = typeof value.signature === "string" && HEX_64_BYTES.test(value.signature)
|
|
77
|
+
? value.signature
|
|
78
|
+
: undefined;
|
|
79
|
+
if (signature === undefined) return undefined;
|
|
80
|
+
|
|
81
|
+
const protocolCompatibility = parseVersionRange(value.protocolCompatibility);
|
|
82
|
+
if (protocolCompatibility === undefined) return undefined;
|
|
83
|
+
|
|
84
|
+
const storageSchemaCompatibility = parseVersionRange(value.storageSchemaCompatibility);
|
|
85
|
+
if (storageSchemaCompatibility === undefined) return undefined;
|
|
86
|
+
|
|
87
|
+
const shellAssets = parseShellAssets(value.shellAssets);
|
|
88
|
+
if (shellAssets === undefined) return undefined;
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
buildId,
|
|
92
|
+
channel,
|
|
93
|
+
issuedAtMs: value.issuedAtMs,
|
|
94
|
+
manifestVersion: RELEASE_MANIFEST_VERSION,
|
|
95
|
+
protocolCompatibility,
|
|
96
|
+
shellAssets,
|
|
97
|
+
shellVersion,
|
|
98
|
+
signature,
|
|
99
|
+
signingKeyId,
|
|
100
|
+
storageSchemaCompatibility,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* @param {unknown} candidate
|
|
106
|
+
* @returns {ReleaseManifestVersionRange | undefined}
|
|
107
|
+
*/
|
|
108
|
+
function parseVersionRange(candidate) {
|
|
109
|
+
if (typeof candidate !== "object" || candidate === null || Array.isArray(candidate)) return undefined;
|
|
110
|
+
const value = /** @type {Record<string, unknown>} */ (candidate);
|
|
111
|
+
const { maxVersionValue } = RELEASE_MANIFEST_LIMITS;
|
|
112
|
+
if (
|
|
113
|
+
!isSafeNonNegativeInteger(value.min) ||
|
|
114
|
+
!isSafeNonNegativeInteger(value.max) ||
|
|
115
|
+
value.min > maxVersionValue ||
|
|
116
|
+
value.max > maxVersionValue ||
|
|
117
|
+
value.min > value.max
|
|
118
|
+
) return undefined;
|
|
119
|
+
return { max: value.max, min: value.min };
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* @param {unknown} candidate
|
|
124
|
+
* @returns {readonly ReleaseManifestAsset[] | undefined}
|
|
125
|
+
*/
|
|
126
|
+
function parseShellAssets(candidate) {
|
|
127
|
+
if (!Array.isArray(candidate) || candidate.length < 1) return undefined;
|
|
128
|
+
if (candidate.length > RELEASE_MANIFEST_LIMITS.maxShellAssets) return undefined;
|
|
129
|
+
/** @type {ReleaseManifestAsset[]} */
|
|
130
|
+
const assets = [];
|
|
131
|
+
for (const entry of candidate) {
|
|
132
|
+
if (typeof entry !== "object" || entry === null || Array.isArray(entry)) return undefined;
|
|
133
|
+
const record = /** @type {Record<string, unknown>} */ (entry);
|
|
134
|
+
const url = boundedString(record.url, 1, RELEASE_MANIFEST_LIMITS.maxShellAssetUrlLength);
|
|
135
|
+
if (url === undefined) return undefined;
|
|
136
|
+
if (typeof record.sha256 !== "string" || !SHA256_HEX.test(record.sha256)) return undefined;
|
|
137
|
+
assets.push({ sha256: record.sha256, url });
|
|
138
|
+
}
|
|
139
|
+
return assets;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* @param {unknown} value
|
|
144
|
+
* @param {number} minLength
|
|
145
|
+
* @param {number} maxLength
|
|
146
|
+
* @returns {string | undefined}
|
|
147
|
+
*/
|
|
148
|
+
function boundedString(value, minLength, maxLength) {
|
|
149
|
+
return typeof value === "string" && value.length >= minLength && value.length <= maxLength
|
|
150
|
+
? value
|
|
151
|
+
: undefined;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* @param {unknown} value
|
|
156
|
+
* @returns {value is number}
|
|
157
|
+
*/
|
|
158
|
+
function isSafeNonNegativeInteger(value) {
|
|
159
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
160
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {import("./agent.js").AgentValue} AgentValue
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {import("./graph.js").GraphValue} GraphValue
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* @typedef {import("./json.js").JsonValue} JsonValue
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* @template {JsonValue} TValue
|
|
14
|
+
* @typedef {import("./revisioned.js").RevisionCommand<TValue>} RevisionCommand
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* @typedef {import("./revisioned.js").RevisionResolution} RevisionResolution
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* @typedef {import("./revisioned.js").RevisionedDomain} RevisionedDomain
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* @typedef {(typeof REVISIONED_COMMAND_NAMES)[number]} RevisionedCommandName
|
|
24
|
+
*/
|
|
25
|
+
/**
|
|
26
|
+
* @typedef {Exclude<RevisionedCommandName, "sync.revision-conflict.resolve.v1">} RevisionUpdateCommandName
|
|
27
|
+
*/
|
|
28
|
+
/**
|
|
29
|
+
* @template {JsonValue} [TValue=import("./json.js").JsonValue]
|
|
30
|
+
* @typedef {{ readonly name: RevisionUpdateCommandName; readonly payload: RevisionCommand<TValue>; }} RevisionUpdateCommand
|
|
31
|
+
*/
|
|
32
|
+
/**
|
|
33
|
+
* @typedef {{ readonly name: "sync.revision-conflict.resolve.v1"; readonly payload: { readonly conflictId: string; readonly idempotencyKey: string; readonly resolution: RevisionResolution; }; }} ResolveRevisionConflictCommand
|
|
34
|
+
*/
|
|
35
|
+
/** @type {readonly ["agents.update.v1", "graphs.update.v1", "settings.update.v1", "sync.revision-conflict.resolve.v1"]} */
|
|
36
|
+
export const REVISIONED_COMMAND_NAMES = [
|
|
37
|
+
"agents.update.v1",
|
|
38
|
+
"graphs.update.v1",
|
|
39
|
+
"settings.update.v1",
|
|
40
|
+
"sync.revision-conflict.resolve.v1",
|
|
41
|
+
];
|
|
42
|
+
/**
|
|
43
|
+
* @template {JsonValue} TValue
|
|
44
|
+
* @param {RevisionedDomain} domain
|
|
45
|
+
* @param {RevisionCommand<TValue>} payload
|
|
46
|
+
* @returns {RevisionUpdateCommand<TValue>}
|
|
47
|
+
*/
|
|
48
|
+
export function createRevisionedUpdateCommand(domain, payload) {
|
|
49
|
+
return {
|
|
50
|
+
name: updateCommandName(domain),
|
|
51
|
+
payload,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* @param {RevisionCommand<AgentValue>} payload
|
|
56
|
+
* @returns {RevisionUpdateCommand<AgentValue>}
|
|
57
|
+
*/
|
|
58
|
+
export function createAgentUpdateCommand(payload) {
|
|
59
|
+
return createRevisionedUpdateCommand("agent", payload);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* @param {RevisionCommand<GraphValue>} payload
|
|
63
|
+
* @returns {RevisionUpdateCommand<GraphValue>}
|
|
64
|
+
*/
|
|
65
|
+
export function createGraphUpdateCommand(payload) {
|
|
66
|
+
return createRevisionedUpdateCommand("graph", payload);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* @param {ResolveRevisionConflictCommand["payload"]} payload
|
|
70
|
+
* @returns {ResolveRevisionConflictCommand}
|
|
71
|
+
*/
|
|
72
|
+
export function createResolveRevisionConflictCommand(payload) {
|
|
73
|
+
if (payload.conflictId.trim() === "" || payload.idempotencyKey.trim() === "") {
|
|
74
|
+
throw new TypeError("Revision conflict resolution requires identifiers");
|
|
75
|
+
}
|
|
76
|
+
if (payload.resolution !== "mine" && payload.resolution !== "theirs") {
|
|
77
|
+
throw new TypeError("Invalid revision conflict resolution");
|
|
78
|
+
}
|
|
79
|
+
return { name: "sync.revision-conflict.resolve.v1", payload };
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* @param {RevisionedDomain} domain
|
|
83
|
+
* @returns {RevisionUpdateCommandName}
|
|
84
|
+
*/
|
|
85
|
+
function updateCommandName(domain) {
|
|
86
|
+
switch (domain) {
|
|
87
|
+
case "agent": return "agents.update.v1";
|
|
88
|
+
case "graph": return "graphs.update.v1";
|
|
89
|
+
case "settings": return "settings.update.v1";
|
|
90
|
+
}
|
|
91
|
+
throw new TypeError("Unsupported revisioned domain");
|
|
92
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {import("./json.js").JsonValue} JsonValue
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* @template TValue
|
|
8
|
+
* @typedef {import("./sync.js").RevisionConflict<TValue>} RevisionConflict
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* @template TValue
|
|
12
|
+
* @typedef {import("./sync.js").RevisionIntent<TValue>} RevisionIntent
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* @typedef {(typeof REVISIONED_DOMAINS)[number]} RevisionedDomain
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* @template {JsonValue} TValue
|
|
19
|
+
* @typedef {RevisionIntent<TValue> & { readonly idempotencyKey: string; }} RevisionCommand
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* @template {JsonValue} TValue
|
|
23
|
+
* @typedef {RevisionConflict<TValue> & { readonly conflictId: string; readonly createdAt: string; readonly domain: RevisionedDomain; readonly idempotencyKey: string; }} RevisionConflictRecord
|
|
24
|
+
*/
|
|
25
|
+
/**
|
|
26
|
+
* @template {JsonValue} TValue
|
|
27
|
+
* @typedef {RevisionConflictRecord<TValue> & { readonly kind: "revision-conflict.v1"; }} RevisionConflictPayload
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* @typedef {"mine" | "theirs"} RevisionResolution
|
|
31
|
+
*/
|
|
32
|
+
/**
|
|
33
|
+
* @template TValue
|
|
34
|
+
* @typedef {import("./sync.js").RevisionCommandResult<TValue>} RevisionCommandResult
|
|
35
|
+
*/
|
|
36
|
+
/**
|
|
37
|
+
* @template TValue
|
|
38
|
+
* @typedef {import("./sync.js").RevisionEntity<TValue>} RevisionEntity
|
|
39
|
+
*/
|
|
40
|
+
/** @type {readonly ["agent", "settings", "graph"]} */
|
|
41
|
+
export const REVISIONED_DOMAINS = ["agent", "settings", "graph"];
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {import("./json.js").JsonValue} JsonValue
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* @template TValue
|
|
8
|
+
* @typedef {import("./sync.js").RevisionEntity<TValue>} RevisionEntity
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* @typedef {JsonValue} SettingValue
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* @typedef {RevisionEntity<SettingValue>} RevisionedSetting
|
|
15
|
+
*/
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {"authoritative-mirror" | "log" | "revision-merge"} SyncStrategyKind
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* @template TPayload
|
|
8
|
+
* @typedef {{ readonly cursor: string; readonly id: string; readonly payload: TPayload; }} SyncDelta
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* @typedef {{ readonly domain: string; readonly now: string; }} SyncDeltaContext
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* @typedef {{ readonly applied: boolean; }} SyncApplyResult
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* @template TPayload
|
|
18
|
+
* @typedef {{ readonly kind: SyncStrategyKind; applyDelta(delta: SyncDelta<TPayload>, context: SyncDeltaContext): Promise<SyncApplyResult>; }} SyncStrategy
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* @template TValue
|
|
22
|
+
* @typedef {{ readonly id: string; readonly rev: number; readonly value: TValue; }} RevisionEntity
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* @template TValue
|
|
26
|
+
* @typedef {{ readonly baseRev: number; readonly id: string; readonly value: TValue; }} RevisionIntent
|
|
27
|
+
*/
|
|
28
|
+
/**
|
|
29
|
+
* @template TValue
|
|
30
|
+
* @typedef {{ readonly baseRev: number; readonly id: string; readonly mine: TValue; readonly theirs: RevisionEntity<TValue>; }} RevisionConflict
|
|
31
|
+
*/
|
|
32
|
+
/**
|
|
33
|
+
* @template TValue
|
|
34
|
+
* @typedef {| { readonly entity: RevisionEntity<TValue>; readonly status: "accepted" } | { readonly status: "conflict"; readonly theirs: RevisionEntity<TValue> }} RevisionCommandResult
|
|
35
|
+
*/
|
|
36
|
+
/**
|
|
37
|
+
* @template TValue
|
|
38
|
+
* @typedef {{ readonly observedAt: string; readonly staleAt: string; readonly value: TValue; }} AuthoritativeSnapshot
|
|
39
|
+
*/
|
|
40
|
+
/**
|
|
41
|
+
* @template TPayload
|
|
42
|
+
* @typedef {{ readonly idempotencyKey: string; readonly payload: TPayload; }} AuthoritativeCommand
|
|
43
|
+
*/
|
|
44
|
+
export {};
|