@abloatai/ablo 0.3.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/CHANGELOG.md +208 -0
- package/LICENSE +201 -0
- package/NOTICE +12 -0
- package/README.md +230 -0
- package/dist/BaseSyncedStore.d.ts +709 -0
- package/dist/BaseSyncedStore.js +1843 -0
- package/dist/Database.d.ts +344 -0
- package/dist/Database.js +1259 -0
- package/dist/LazyReferenceCollection.d.ts +181 -0
- package/dist/LazyReferenceCollection.js +460 -0
- package/dist/Model.d.ts +339 -0
- package/dist/Model.js +715 -0
- package/dist/ModelRegistry.d.ts +200 -0
- package/dist/ModelRegistry.js +535 -0
- package/dist/NetworkMonitor.d.ts +27 -0
- package/dist/NetworkMonitor.js +73 -0
- package/dist/ObjectPool.d.ts +202 -0
- package/dist/ObjectPool.js +1106 -0
- package/dist/SyncClient.d.ts +489 -0
- package/dist/SyncClient.js +1555 -0
- package/dist/SyncEngineContext.d.ts +46 -0
- package/dist/SyncEngineContext.js +74 -0
- package/dist/adapters/alwaysOnline.d.ts +16 -0
- package/dist/adapters/alwaysOnline.js +19 -0
- package/dist/adapters/inMemoryStorage.d.ts +30 -0
- package/dist/adapters/inMemoryStorage.js +94 -0
- package/dist/agent/Agent.d.ts +358 -0
- package/dist/agent/Agent.js +500 -0
- package/dist/agent/index.d.ts +115 -0
- package/dist/agent/index.js +128 -0
- package/dist/agent/session.d.ts +90 -0
- package/dist/agent/session.js +156 -0
- package/dist/agent/types.d.ts +73 -0
- package/dist/agent/types.js +10 -0
- package/dist/ai-sdk/coordination-context.d.ts +51 -0
- package/dist/ai-sdk/coordination-context.js +107 -0
- package/dist/ai-sdk/index.d.ts +68 -0
- package/dist/ai-sdk/index.js +68 -0
- package/dist/ai-sdk/intent-broadcast.d.ts +77 -0
- package/dist/ai-sdk/intent-broadcast.js +72 -0
- package/dist/ai-sdk/wrap.d.ts +67 -0
- package/dist/ai-sdk/wrap.js +45 -0
- package/dist/api/index.d.ts +10 -0
- package/dist/api/index.js +9 -0
- package/dist/auth/index.d.ts +137 -0
- package/dist/auth/index.js +246 -0
- package/dist/client/Ablo.d.ts +835 -0
- package/dist/client/Ablo.js +1440 -0
- package/dist/client/ApiClient.d.ts +200 -0
- package/dist/client/ApiClient.js +659 -0
- package/dist/client/auth.d.ts +79 -0
- package/dist/client/auth.js +81 -0
- package/dist/client/createInternalComponents.d.ts +44 -0
- package/dist/client/createInternalComponents.js +88 -0
- package/dist/client/createModelProxy.d.ts +152 -0
- package/dist/client/createModelProxy.js +199 -0
- package/dist/client/identity.d.ts +63 -0
- package/dist/client/identity.js +156 -0
- package/dist/client/index.d.ts +36 -0
- package/dist/client/index.js +33 -0
- package/dist/client/persistence.d.ts +7 -0
- package/dist/client/persistence.js +11 -0
- package/dist/client/validateAbloOptions.d.ts +42 -0
- package/dist/client/validateAbloOptions.js +43 -0
- package/dist/config/index.d.ts +10 -0
- package/dist/config/index.js +12 -0
- package/dist/context.d.ts +27 -0
- package/dist/context.js +58 -0
- package/dist/core/DatabaseManager.d.ts +108 -0
- package/dist/core/DatabaseManager.js +361 -0
- package/dist/core/QueryProcessor.d.ts +77 -0
- package/dist/core/QueryProcessor.js +262 -0
- package/dist/core/QueryView.d.ts +64 -0
- package/dist/core/QueryView.js +219 -0
- package/dist/core/StoreManager.d.ts +131 -0
- package/dist/core/StoreManager.js +334 -0
- package/dist/core/ViewRegistry.d.ts +20 -0
- package/dist/core/ViewRegistry.js +55 -0
- package/dist/core/index.d.ts +34 -0
- package/dist/core/index.js +59 -0
- package/dist/core/openIDBWithTimeout.d.ts +27 -0
- package/dist/core/openIDBWithTimeout.js +63 -0
- package/dist/core/query-utils.d.ts +37 -0
- package/dist/core/query-utils.js +60 -0
- package/dist/errors.d.ts +235 -0
- package/dist/errors.js +243 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.js +82 -0
- package/dist/interfaces/headless.d.ts +95 -0
- package/dist/interfaces/headless.js +41 -0
- package/dist/interfaces/index.d.ts +321 -0
- package/dist/interfaces/index.js +8 -0
- package/dist/mutators/RecordingTransaction.d.ts +36 -0
- package/dist/mutators/RecordingTransaction.js +216 -0
- package/dist/mutators/Transaction.d.ts +48 -0
- package/dist/mutators/Transaction.js +64 -0
- package/dist/mutators/UndoManager.d.ts +114 -0
- package/dist/mutators/UndoManager.js +143 -0
- package/dist/mutators/defineMutators.d.ts +55 -0
- package/dist/mutators/defineMutators.js +28 -0
- package/dist/policy/index.d.ts +19 -0
- package/dist/policy/index.js +18 -0
- package/dist/policy/types.d.ts +74 -0
- package/dist/policy/types.js +17 -0
- package/dist/principal.d.ts +44 -0
- package/dist/principal.js +49 -0
- package/dist/query/client.d.ts +43 -0
- package/dist/query/client.js +84 -0
- package/dist/query/index.d.ts +6 -0
- package/dist/query/index.js +5 -0
- package/dist/query/types.d.ts +143 -0
- package/dist/query/types.js +36 -0
- package/dist/react/AbloProvider.d.ts +205 -0
- package/dist/react/AbloProvider.js +398 -0
- package/dist/react/ClientSideSuspense.d.ts +36 -0
- package/dist/react/ClientSideSuspense.js +17 -0
- package/dist/react/DefaultFallback.d.ts +24 -0
- package/dist/react/DefaultFallback.js +43 -0
- package/dist/react/SyncGroupProvider.d.ts +19 -0
- package/dist/react/SyncGroupProvider.js +44 -0
- package/dist/react/context.d.ts +161 -0
- package/dist/react/context.js +35 -0
- package/dist/react/index.d.ts +64 -0
- package/dist/react/index.js +73 -0
- package/dist/react/internalContext.d.ts +35 -0
- package/dist/react/internalContext.js +3 -0
- package/dist/react/useAblo.d.ts +72 -0
- package/dist/react/useAblo.js +63 -0
- package/dist/react/useCurrentUserId.d.ts +21 -0
- package/dist/react/useCurrentUserId.js +33 -0
- package/dist/react/useErrorListener.d.ts +20 -0
- package/dist/react/useErrorListener.js +39 -0
- package/dist/react/useIntent.d.ts +29 -0
- package/dist/react/useIntent.js +42 -0
- package/dist/react/useMutate.d.ts +83 -0
- package/dist/react/useMutate.js +122 -0
- package/dist/react/useMutationFailureListener.d.ts +26 -0
- package/dist/react/useMutationFailureListener.js +38 -0
- package/dist/react/useMutators.d.ts +56 -0
- package/dist/react/useMutators.js +66 -0
- package/dist/react/usePresence.d.ts +32 -0
- package/dist/react/usePresence.js +41 -0
- package/dist/react/useQuery.d.ts +123 -0
- package/dist/react/useQuery.js +145 -0
- package/dist/react/useReactive.d.ts +35 -0
- package/dist/react/useReactive.js +111 -0
- package/dist/react/useReader.d.ts +69 -0
- package/dist/react/useReader.js +73 -0
- package/dist/react/useSyncStatus.d.ts +61 -0
- package/dist/react/useSyncStatus.js +76 -0
- package/dist/react/useUndoScope.d.ts +36 -0
- package/dist/react/useUndoScope.js +73 -0
- package/dist/realtime/index.d.ts +10 -0
- package/dist/realtime/index.js +9 -0
- package/dist/schema/field.d.ts +134 -0
- package/dist/schema/field.js +264 -0
- package/dist/schema/index.d.ts +29 -0
- package/dist/schema/index.js +38 -0
- package/dist/schema/model.d.ts +326 -0
- package/dist/schema/model.js +89 -0
- package/dist/schema/queries.d.ts +203 -0
- package/dist/schema/queries.js +145 -0
- package/dist/schema/relation.d.ts +172 -0
- package/dist/schema/relation.js +104 -0
- package/dist/schema/schema.d.ts +259 -0
- package/dist/schema/schema.js +188 -0
- package/dist/schema/sugar.d.ts +129 -0
- package/dist/schema/sugar.js +94 -0
- package/dist/source/index.d.ts +423 -0
- package/dist/source/index.js +320 -0
- package/dist/source/pushQueue.d.ts +112 -0
- package/dist/source/pushQueue.js +249 -0
- package/dist/stores/ObjectStore.d.ts +103 -0
- package/dist/stores/ObjectStore.js +371 -0
- package/dist/stores/ObjectStoreContract.d.ts +39 -0
- package/dist/stores/ObjectStoreContract.js +1 -0
- package/dist/stores/SyncActionStore.d.ts +101 -0
- package/dist/stores/SyncActionStore.js +481 -0
- package/dist/sync/BootstrapHelper.d.ts +127 -0
- package/dist/sync/BootstrapHelper.js +434 -0
- package/dist/sync/ConnectionManager.d.ts +136 -0
- package/dist/sync/ConnectionManager.js +465 -0
- package/dist/sync/HydrationCoordinator.d.ts +137 -0
- package/dist/sync/HydrationCoordinator.js +468 -0
- package/dist/sync/NetworkProbe.d.ts +43 -0
- package/dist/sync/NetworkProbe.js +113 -0
- package/dist/sync/OfflineFlush.d.ts +9 -0
- package/dist/sync/OfflineFlush.js +22 -0
- package/dist/sync/OfflineTransactionStore.d.ts +37 -0
- package/dist/sync/OfflineTransactionStore.js +263 -0
- package/dist/sync/SyncWebSocket.d.ts +663 -0
- package/dist/sync/SyncWebSocket.js +1336 -0
- package/dist/sync/createIntentStream.d.ts +33 -0
- package/dist/sync/createIntentStream.js +243 -0
- package/dist/sync/createPresenceStream.d.ts +46 -0
- package/dist/sync/createPresenceStream.js +192 -0
- package/dist/sync/createSnapshot.d.ts +33 -0
- package/dist/sync/createSnapshot.js +124 -0
- package/dist/sync/participants.d.ts +114 -0
- package/dist/sync/participants.js +336 -0
- package/dist/sync/schemas.d.ts +79 -0
- package/dist/sync/schemas.js +78 -0
- package/dist/testing/fixtures/bootstrap.d.ts +45 -0
- package/dist/testing/fixtures/bootstrap.js +53 -0
- package/dist/testing/fixtures/deltas.d.ts +86 -0
- package/dist/testing/fixtures/deltas.js +139 -0
- package/dist/testing/fixtures/models.d.ts +82 -0
- package/dist/testing/fixtures/models.js +270 -0
- package/dist/testing/helpers/react-wrapper.d.ts +66 -0
- package/dist/testing/helpers/react-wrapper.js +64 -0
- package/dist/testing/helpers/sync-engine-harness.d.ts +55 -0
- package/dist/testing/helpers/sync-engine-harness.js +70 -0
- package/dist/testing/helpers/wait.d.ts +25 -0
- package/dist/testing/helpers/wait.js +44 -0
- package/dist/testing/index.d.ts +21 -0
- package/dist/testing/index.js +32 -0
- package/dist/testing/mocks/MockMutationExecutor.d.ts +65 -0
- package/dist/testing/mocks/MockMutationExecutor.js +139 -0
- package/dist/testing/mocks/MockNetworkMonitor.d.ts +20 -0
- package/dist/testing/mocks/MockNetworkMonitor.js +46 -0
- package/dist/testing/mocks/MockSyncContext.d.ts +64 -0
- package/dist/testing/mocks/MockSyncContext.js +100 -0
- package/dist/testing/mocks/MockSyncStore.d.ts +88 -0
- package/dist/testing/mocks/MockSyncStore.js +171 -0
- package/dist/testing/mocks/MockWebSocket.d.ts +66 -0
- package/dist/testing/mocks/MockWebSocket.js +117 -0
- package/dist/transactions/OptimisticEchoTracker.d.ts +82 -0
- package/dist/transactions/OptimisticEchoTracker.js +104 -0
- package/dist/transactions/TransactionQueue.d.ts +499 -0
- package/dist/transactions/TransactionQueue.js +1895 -0
- package/dist/transactions/index.d.ts +16 -0
- package/dist/transactions/index.js +7 -0
- package/dist/transactions/mutation-error-handler.d.ts +5 -0
- package/dist/transactions/mutation-error-handler.js +39 -0
- package/dist/types/global.d.ts +107 -0
- package/dist/types/global.js +38 -0
- package/dist/types/index.d.ts +241 -0
- package/dist/types/index.js +70 -0
- package/dist/types/streams.d.ts +495 -0
- package/dist/types/streams.js +11 -0
- package/dist/utils/asyncIterator.d.ts +41 -0
- package/dist/utils/asyncIterator.js +142 -0
- package/dist/utils/duration.d.ts +28 -0
- package/dist/utils/duration.js +47 -0
- package/dist/utils/mobx-setup.d.ts +42 -0
- package/dist/utils/mobx-setup.js +381 -0
- package/docs/api-keys.md +24 -0
- package/docs/api.md +230 -0
- package/docs/audit.md +81 -0
- package/docs/capabilities.md +163 -0
- package/docs/client-behavior.md +202 -0
- package/docs/data-sources.md +214 -0
- package/docs/examples/agent-human.md +84 -0
- package/docs/examples/ai-sdk-tool.md +92 -0
- package/docs/examples/existing-python-backend.md +249 -0
- package/docs/examples/nextjs.md +88 -0
- package/docs/examples/server-agent.md +86 -0
- package/docs/guarantees.md +148 -0
- package/docs/index.md +97 -0
- package/docs/integration-guide.md +493 -0
- package/docs/interaction-model.md +140 -0
- package/docs/mcp/claude-code.md +43 -0
- package/docs/mcp/cursor.md +53 -0
- package/docs/mcp/windsurf.md +46 -0
- package/docs/mcp.md +59 -0
- package/docs/quickstart.md +152 -0
- package/docs/react.md +115 -0
- package/docs/roadmap.md +45 -0
- package/examples/README.md +54 -0
- package/examples/data-source/README.md +102 -0
- package/examples/data-source/ablo-driver.ts +89 -0
- package/examples/data-source/customer-server.ts +208 -0
- package/examples/data-source/run.ts +101 -0
- package/examples/data-source/schema.ts +25 -0
- package/examples/quickstart.ts +54 -0
- package/examples/tsconfig.json +16 -0
- package/llms.txt +143 -0
- package/package.json +147 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* query-utils — Pure query helpers shared between QueryView (MobX) and
|
|
3
|
+
* AgentQueryView (headless). One source of truth for sort, filter, and
|
|
4
|
+
* binary insertion logic.
|
|
5
|
+
*
|
|
6
|
+
* No MobX, no ObjectPool, no Model — just arrays and values.
|
|
7
|
+
*/
|
|
8
|
+
/** Compare two values for sorting, null-safe. Returns -1 | 0 | 1. */
|
|
9
|
+
export function compareValues(a, b, dir) {
|
|
10
|
+
if (a === b)
|
|
11
|
+
return 0;
|
|
12
|
+
if (a == null)
|
|
13
|
+
return 1;
|
|
14
|
+
if (b == null)
|
|
15
|
+
return -1;
|
|
16
|
+
return (a < b ? -1 : 1) * dir;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Binary search for the correct insertion index in a sorted array.
|
|
20
|
+
* Returns the index at which `item` should be inserted.
|
|
21
|
+
*/
|
|
22
|
+
export function binaryInsertionIndex(arr, item, sortKey, dir) {
|
|
23
|
+
let lo = 0;
|
|
24
|
+
let hi = arr.length;
|
|
25
|
+
const itemVal = item[sortKey];
|
|
26
|
+
while (lo < hi) {
|
|
27
|
+
const mid = (lo + hi) >>> 1;
|
|
28
|
+
const midVal = arr[mid][sortKey];
|
|
29
|
+
if (compareValues(midVal, itemVal, dir) <= 0) {
|
|
30
|
+
lo = mid + 1;
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
hi = mid;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return lo;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Check whether an entity matches a declarative `where` clause.
|
|
40
|
+
* Every key in `where` must exactly match the entity's value.
|
|
41
|
+
*/
|
|
42
|
+
export function matchesWhere(entity, where) {
|
|
43
|
+
for (const [key, value] of Object.entries(where)) {
|
|
44
|
+
if (value === undefined)
|
|
45
|
+
continue;
|
|
46
|
+
if (entity[key] !== value)
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Find the index of an entity by id in an array. Returns -1 if not found.
|
|
53
|
+
*/
|
|
54
|
+
export function findIndexById(arr, id) {
|
|
55
|
+
for (let i = 0; i < arr.length; i++) {
|
|
56
|
+
if (arr[i]['id'] === id)
|
|
57
|
+
return i;
|
|
58
|
+
}
|
|
59
|
+
return -1;
|
|
60
|
+
}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed error hierarchy for `@ablo/sync-engine`.
|
|
3
|
+
*
|
|
4
|
+
* Inlined directly so the publishable dist is self-contained. The public
|
|
5
|
+
* package should never reference an unpublished internal package from emitted
|
|
6
|
+
* JS; strict bundlers surface that immediately.
|
|
7
|
+
*
|
|
8
|
+
* ### Two patterns for consumers
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* // Stripe-style instanceof
|
|
12
|
+
* if (err instanceof AbloRateLimitError) backoff(err.retryAfterSeconds);
|
|
13
|
+
*
|
|
14
|
+
* // Discriminator-string (for cross-boundary cases where the class
|
|
15
|
+
* // identity gets lost, e.g. across a web worker postMessage)
|
|
16
|
+
* if (err.type === 'AbloRateLimitError') { ... }
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* Both work on every subclass.
|
|
20
|
+
*/
|
|
21
|
+
/** Common shape for all errors thrown by this SDK. */
|
|
22
|
+
export declare class AbloError extends Error {
|
|
23
|
+
/** Discriminator string — matches the class name. Lets consumers
|
|
24
|
+
* switch on `e.type` without `instanceof` checks across package
|
|
25
|
+
* boundaries (matches Stripe's `err.type` pattern). */
|
|
26
|
+
readonly type: string;
|
|
27
|
+
/** Stable short identifier for logs + metrics.
|
|
28
|
+
* E.g. `'apikey_invalid'`, `'capability_scope_denied'`. */
|
|
29
|
+
readonly code?: string;
|
|
30
|
+
/** HTTP status code when the error originated from an HTTP response. */
|
|
31
|
+
readonly httpStatus?: number;
|
|
32
|
+
/** Correlation id for ops — present when the server sent one on
|
|
33
|
+
* `x-request-id`. Include in support tickets. */
|
|
34
|
+
readonly requestId?: string;
|
|
35
|
+
constructor(message: string, options?: {
|
|
36
|
+
code?: string;
|
|
37
|
+
httpStatus?: number;
|
|
38
|
+
requestId?: string;
|
|
39
|
+
cause?: unknown;
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
/** 401 — invalid/missing/expired credentials. */
|
|
43
|
+
export declare class AbloAuthenticationError extends AbloError {
|
|
44
|
+
readonly type: "AbloAuthenticationError";
|
|
45
|
+
}
|
|
46
|
+
/** 403 — credentials were valid but the action is forbidden (scope
|
|
47
|
+
* denial, revoked capability, role not authorized). */
|
|
48
|
+
export declare class AbloPermissionError extends AbloError {
|
|
49
|
+
readonly type: "AbloPermissionError";
|
|
50
|
+
}
|
|
51
|
+
/** 429 — rate limit exceeded. Consumers should back off before retry. */
|
|
52
|
+
export declare class AbloRateLimitError extends AbloError {
|
|
53
|
+
readonly type: "AbloRateLimitError";
|
|
54
|
+
readonly retryAfterSeconds?: number;
|
|
55
|
+
constructor(message: string, options?: {
|
|
56
|
+
code?: string;
|
|
57
|
+
httpStatus?: number;
|
|
58
|
+
requestId?: string;
|
|
59
|
+
cause?: unknown;
|
|
60
|
+
retryAfterSeconds?: number;
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
/** 409 — same `Idempotency-Key` reused with a different request body. */
|
|
64
|
+
export declare class AbloIdempotencyError extends AbloError {
|
|
65
|
+
readonly type: "AbloIdempotencyError";
|
|
66
|
+
}
|
|
67
|
+
/** Network / transport failure — TCP reset, DNS, timeout, abort. */
|
|
68
|
+
export declare class AbloConnectionError extends AbloError {
|
|
69
|
+
readonly type: "AbloConnectionError";
|
|
70
|
+
}
|
|
71
|
+
/** 400 / 422 — request payload was invalid. */
|
|
72
|
+
export declare class AbloValidationError extends AbloError {
|
|
73
|
+
readonly type: "AbloValidationError";
|
|
74
|
+
}
|
|
75
|
+
/** 5xx — server-side error. Usually retryable with backoff. */
|
|
76
|
+
export declare class AbloServerError extends AbloError {
|
|
77
|
+
readonly type: "AbloServerError";
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* 409 — a write carried `readAt: N` but the target entity has received
|
|
81
|
+
* deltas since `N`. The caller's reasoning snapshot is stale; the safe
|
|
82
|
+
* response is to re-read (or re-capture a watermark) and regenerate.
|
|
83
|
+
*
|
|
84
|
+
* Carries `conflicts` so callers can inspect which specific (model, id)
|
|
85
|
+
* pairs moved during the generation window — useful for metrics
|
|
86
|
+
* ("72% of stale rejects were on slide titles") and for selective
|
|
87
|
+
* regeneration (only re-think the slides that changed, not the whole
|
|
88
|
+
* deck).
|
|
89
|
+
*/
|
|
90
|
+
export declare class AbloStaleContextError extends AbloError {
|
|
91
|
+
readonly type: "AbloStaleContextError";
|
|
92
|
+
/** Sync id at the caller's `readAt` when the write was attempted. */
|
|
93
|
+
readonly readAt?: number;
|
|
94
|
+
/** Entities that received deltas between `readAt` and the write. */
|
|
95
|
+
readonly conflicts?: ReadonlyArray<{
|
|
96
|
+
readonly model: string;
|
|
97
|
+
readonly id: string;
|
|
98
|
+
readonly observedSyncId: number;
|
|
99
|
+
}>;
|
|
100
|
+
constructor(message: string, options?: {
|
|
101
|
+
code?: string;
|
|
102
|
+
httpStatus?: number;
|
|
103
|
+
requestId?: string;
|
|
104
|
+
cause?: unknown;
|
|
105
|
+
readAt?: number;
|
|
106
|
+
conflicts?: ReadonlyArray<{
|
|
107
|
+
readonly model: string;
|
|
108
|
+
readonly id: string;
|
|
109
|
+
readonly observedSyncId: number;
|
|
110
|
+
}>;
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* The target entity currently has an active intent held by another
|
|
115
|
+
* participant and the caller asked the SDK not to return immediately.
|
|
116
|
+
*
|
|
117
|
+
* Use `ifBusy: 'wait'` to wait for the intent stream to clear, or
|
|
118
|
+
* `ifBusy: 'return'` to inspect the active intents yourself.
|
|
119
|
+
*/
|
|
120
|
+
export declare class AbloBusyError extends AbloError {
|
|
121
|
+
readonly type: "AbloBusyError";
|
|
122
|
+
readonly intents?: ReadonlyArray<unknown>;
|
|
123
|
+
constructor(message: string, options?: {
|
|
124
|
+
code?: string;
|
|
125
|
+
httpStatus?: number;
|
|
126
|
+
requestId?: string;
|
|
127
|
+
cause?: unknown;
|
|
128
|
+
intents?: ReadonlyArray<unknown>;
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Structured description of the capability an agent would need to
|
|
133
|
+
* satisfy a denied request. Mirrors the x402 `paymentRequirements`
|
|
134
|
+
* shape: the server emits enough information for the client to
|
|
135
|
+
* attenuate (or request) a capability that would pass on retry.
|
|
136
|
+
*/
|
|
137
|
+
export interface RequiredCapability {
|
|
138
|
+
/** Operation or capability scope identifier (e.g. `"slide.update"`,
|
|
139
|
+
* `"subscribe"`). */
|
|
140
|
+
readonly scope: string;
|
|
141
|
+
/** Concrete constraints the capability must satisfy. Keys map to
|
|
142
|
+
* Datalog fact families — e.g. `{ syncGroup: ["org_abc"] }` for a
|
|
143
|
+
* rejected subscription. Forward-compatible: ignore unknown keys. */
|
|
144
|
+
readonly constraints?: Readonly<Record<string, readonly string[] | string>>;
|
|
145
|
+
/** Issuer hint — public-key fingerprint or well-known URL fragment. */
|
|
146
|
+
readonly issuer?: string;
|
|
147
|
+
/** Server-suggested maximum TTL for the attenuated capability. */
|
|
148
|
+
readonly ttlSeconds?: number;
|
|
149
|
+
/** Single-use nonce to embed in the retry's capability facts; binds
|
|
150
|
+
* retry → denial and prevents replay of a stale attenuation. */
|
|
151
|
+
readonly nonce?: string;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Canonical receipt returned by every successful or rejected commit,
|
|
155
|
+
* regardless of transport (WebSocket `mutation_result` payload, HTTP
|
|
156
|
+
* `/v1/commits` response body, or `AgentJob.result.receipt`). One
|
|
157
|
+
* shape across all three surfaces.
|
|
158
|
+
*
|
|
159
|
+
* Linear-style correlation receipt — no cryptographic signature
|
|
160
|
+
* (single-tenant trust boundary). A Hub signature is a forward-
|
|
161
|
+
* compatible extension when cross-org agent crossings arrive.
|
|
162
|
+
*/
|
|
163
|
+
export interface CommitReceipt {
|
|
164
|
+
readonly object: 'commit_receipt';
|
|
165
|
+
/** Client-issued idempotency handle. Echoed verbatim. */
|
|
166
|
+
readonly clientTxId: string;
|
|
167
|
+
/** Server-issued opaque commit id — typically `String(lastSyncId)`. */
|
|
168
|
+
readonly serverTxId: string;
|
|
169
|
+
/** Convenience boolean. `status === 'confirmed'`. */
|
|
170
|
+
readonly success: boolean;
|
|
171
|
+
/** `'confirmed'` on apply, `'rejected'` on any failure. */
|
|
172
|
+
readonly status: 'confirmed' | 'rejected';
|
|
173
|
+
/** Last syncId visible after this commit (or high-water mark on
|
|
174
|
+
* rejection). */
|
|
175
|
+
readonly lastSyncId?: number;
|
|
176
|
+
/** Number of operations metered. Reported on both success and
|
|
177
|
+
* rejection so quota systems see attempted work. */
|
|
178
|
+
readonly ops?: number;
|
|
179
|
+
/** Populated on rejection. `requiredCapability` (when present)
|
|
180
|
+
* carries the x402-style structured retry hint. */
|
|
181
|
+
readonly error?: {
|
|
182
|
+
readonly code: string;
|
|
183
|
+
readonly message: string;
|
|
184
|
+
readonly field?: string;
|
|
185
|
+
readonly requiredCapability?: RequiredCapability;
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Biscuit capability token failed verification — either it's
|
|
190
|
+
* malformed / unknown / revoked (`capability_invalid`), or its
|
|
191
|
+
* caveats deny the attempted action (`capability_scope_denied`).
|
|
192
|
+
*
|
|
193
|
+
* Extends `AbloPermissionError` so existing `instanceof CapabilityError`
|
|
194
|
+
* checks keep working AND broader `instanceof AbloPermissionError`
|
|
195
|
+
* matches for consumers who don't care about the Biscuit specifics.
|
|
196
|
+
*
|
|
197
|
+
* `requiredCapability` (when present) describes what an attenuated
|
|
198
|
+
* capability must satisfy for the request to succeed on retry.
|
|
199
|
+
*/
|
|
200
|
+
export declare class CapabilityError extends AbloPermissionError {
|
|
201
|
+
readonly requiredCapability?: RequiredCapability;
|
|
202
|
+
constructor(code: 'capability_scope_denied' | 'capability_invalid', message: string, requiredCapability?: RequiredCapability);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* SyncSessionError — Thrown when authentication/session is invalid or expired.
|
|
206
|
+
* Signals that the user should be redirected to sign in
|
|
207
|
+
* rather than showing a generic retry option.
|
|
208
|
+
*
|
|
209
|
+
* Extends `AbloAuthenticationError` so existing
|
|
210
|
+
* `SyncSessionError.isSessionError(...)` duck-type callers keep
|
|
211
|
+
* working, AND downstream code that only catches the typed hierarchy
|
|
212
|
+
* (`instanceof AbloAuthenticationError` / `e.type === 'AbloAuthenticationError'`)
|
|
213
|
+
* now sees session failures too.
|
|
214
|
+
*/
|
|
215
|
+
export declare class SyncSessionError extends AbloAuthenticationError {
|
|
216
|
+
readonly isSessionError = true;
|
|
217
|
+
readonly statusCode: number;
|
|
218
|
+
constructor(message: string, statusCode?: number);
|
|
219
|
+
/**
|
|
220
|
+
* Check if an error is a session error (duck-type check)
|
|
221
|
+
*/
|
|
222
|
+
static isSessionError(error: unknown): error is SyncSessionError;
|
|
223
|
+
/**
|
|
224
|
+
* Check if an HTTP response status indicates a session error
|
|
225
|
+
*/
|
|
226
|
+
static isSessionErrorResponse(status: number, body?: string): boolean;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Translate an HTTP response into the appropriate typed error.
|
|
230
|
+
*
|
|
231
|
+
* Single source of truth for status-code → class mapping — every SDK
|
|
232
|
+
* fetch path that sees a non-2xx response should route through here
|
|
233
|
+
* so the customer-visible error is always the right subclass.
|
|
234
|
+
*/
|
|
235
|
+
export declare function translateHttpError(status: number, body: unknown, requestId?: string): AbloError;
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed error hierarchy for `@ablo/sync-engine`.
|
|
3
|
+
*
|
|
4
|
+
* Inlined directly so the publishable dist is self-contained. The public
|
|
5
|
+
* package should never reference an unpublished internal package from emitted
|
|
6
|
+
* JS; strict bundlers surface that immediately.
|
|
7
|
+
*
|
|
8
|
+
* ### Two patterns for consumers
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* // Stripe-style instanceof
|
|
12
|
+
* if (err instanceof AbloRateLimitError) backoff(err.retryAfterSeconds);
|
|
13
|
+
*
|
|
14
|
+
* // Discriminator-string (for cross-boundary cases where the class
|
|
15
|
+
* // identity gets lost, e.g. across a web worker postMessage)
|
|
16
|
+
* if (err.type === 'AbloRateLimitError') { ... }
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* Both work on every subclass.
|
|
20
|
+
*/
|
|
21
|
+
// ── AbloError hierarchy — the typed error surface ────────────────────
|
|
22
|
+
/** Common shape for all errors thrown by this SDK. */
|
|
23
|
+
export class AbloError extends Error {
|
|
24
|
+
/** Discriminator string — matches the class name. Lets consumers
|
|
25
|
+
* switch on `e.type` without `instanceof` checks across package
|
|
26
|
+
* boundaries (matches Stripe's `err.type` pattern). */
|
|
27
|
+
type = 'AbloError';
|
|
28
|
+
/** Stable short identifier for logs + metrics.
|
|
29
|
+
* E.g. `'apikey_invalid'`, `'capability_scope_denied'`. */
|
|
30
|
+
code;
|
|
31
|
+
/** HTTP status code when the error originated from an HTTP response. */
|
|
32
|
+
httpStatus;
|
|
33
|
+
/** Correlation id for ops — present when the server sent one on
|
|
34
|
+
* `x-request-id`. Include in support tickets. */
|
|
35
|
+
requestId;
|
|
36
|
+
constructor(message, options) {
|
|
37
|
+
super(message);
|
|
38
|
+
this.name = this.constructor.name;
|
|
39
|
+
if (options?.code !== undefined)
|
|
40
|
+
this.code = options.code;
|
|
41
|
+
if (options?.httpStatus !== undefined)
|
|
42
|
+
this.httpStatus = options.httpStatus;
|
|
43
|
+
if (options?.requestId !== undefined)
|
|
44
|
+
this.requestId = options.requestId;
|
|
45
|
+
if (options?.cause !== undefined) {
|
|
46
|
+
Object.defineProperty(this, 'cause', { value: options.cause, enumerable: false });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/** 401 — invalid/missing/expired credentials. */
|
|
51
|
+
export class AbloAuthenticationError extends AbloError {
|
|
52
|
+
type = 'AbloAuthenticationError';
|
|
53
|
+
}
|
|
54
|
+
/** 403 — credentials were valid but the action is forbidden (scope
|
|
55
|
+
* denial, revoked capability, role not authorized). */
|
|
56
|
+
export class AbloPermissionError extends AbloError {
|
|
57
|
+
type = 'AbloPermissionError';
|
|
58
|
+
}
|
|
59
|
+
/** 429 — rate limit exceeded. Consumers should back off before retry. */
|
|
60
|
+
export class AbloRateLimitError extends AbloError {
|
|
61
|
+
type = 'AbloRateLimitError';
|
|
62
|
+
retryAfterSeconds;
|
|
63
|
+
constructor(message, options) {
|
|
64
|
+
super(message, options);
|
|
65
|
+
if (options?.retryAfterSeconds !== undefined) {
|
|
66
|
+
this.retryAfterSeconds = options.retryAfterSeconds;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/** 409 — same `Idempotency-Key` reused with a different request body. */
|
|
71
|
+
export class AbloIdempotencyError extends AbloError {
|
|
72
|
+
type = 'AbloIdempotencyError';
|
|
73
|
+
}
|
|
74
|
+
/** Network / transport failure — TCP reset, DNS, timeout, abort. */
|
|
75
|
+
export class AbloConnectionError extends AbloError {
|
|
76
|
+
type = 'AbloConnectionError';
|
|
77
|
+
}
|
|
78
|
+
/** 400 / 422 — request payload was invalid. */
|
|
79
|
+
export class AbloValidationError extends AbloError {
|
|
80
|
+
type = 'AbloValidationError';
|
|
81
|
+
}
|
|
82
|
+
/** 5xx — server-side error. Usually retryable with backoff. */
|
|
83
|
+
export class AbloServerError extends AbloError {
|
|
84
|
+
type = 'AbloServerError';
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* 409 — a write carried `readAt: N` but the target entity has received
|
|
88
|
+
* deltas since `N`. The caller's reasoning snapshot is stale; the safe
|
|
89
|
+
* response is to re-read (or re-capture a watermark) and regenerate.
|
|
90
|
+
*
|
|
91
|
+
* Carries `conflicts` so callers can inspect which specific (model, id)
|
|
92
|
+
* pairs moved during the generation window — useful for metrics
|
|
93
|
+
* ("72% of stale rejects were on slide titles") and for selective
|
|
94
|
+
* regeneration (only re-think the slides that changed, not the whole
|
|
95
|
+
* deck).
|
|
96
|
+
*/
|
|
97
|
+
export class AbloStaleContextError extends AbloError {
|
|
98
|
+
type = 'AbloStaleContextError';
|
|
99
|
+
/** Sync id at the caller's `readAt` when the write was attempted. */
|
|
100
|
+
readAt;
|
|
101
|
+
/** Entities that received deltas between `readAt` and the write. */
|
|
102
|
+
conflicts;
|
|
103
|
+
constructor(message, options) {
|
|
104
|
+
super(message, options);
|
|
105
|
+
if (options?.readAt !== undefined)
|
|
106
|
+
this.readAt = options.readAt;
|
|
107
|
+
if (options?.conflicts !== undefined)
|
|
108
|
+
this.conflicts = options.conflicts;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* The target entity currently has an active intent held by another
|
|
113
|
+
* participant and the caller asked the SDK not to return immediately.
|
|
114
|
+
*
|
|
115
|
+
* Use `ifBusy: 'wait'` to wait for the intent stream to clear, or
|
|
116
|
+
* `ifBusy: 'return'` to inspect the active intents yourself.
|
|
117
|
+
*/
|
|
118
|
+
export class AbloBusyError extends AbloError {
|
|
119
|
+
type = 'AbloBusyError';
|
|
120
|
+
intents;
|
|
121
|
+
constructor(message, options) {
|
|
122
|
+
super(message, options);
|
|
123
|
+
if (options?.intents !== undefined)
|
|
124
|
+
this.intents = options.intents;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Biscuit capability token failed verification — either it's
|
|
129
|
+
* malformed / unknown / revoked (`capability_invalid`), or its
|
|
130
|
+
* caveats deny the attempted action (`capability_scope_denied`).
|
|
131
|
+
*
|
|
132
|
+
* Extends `AbloPermissionError` so existing `instanceof CapabilityError`
|
|
133
|
+
* checks keep working AND broader `instanceof AbloPermissionError`
|
|
134
|
+
* matches for consumers who don't care about the Biscuit specifics.
|
|
135
|
+
*
|
|
136
|
+
* `requiredCapability` (when present) describes what an attenuated
|
|
137
|
+
* capability must satisfy for the request to succeed on retry.
|
|
138
|
+
*/
|
|
139
|
+
export class CapabilityError extends AbloPermissionError {
|
|
140
|
+
requiredCapability;
|
|
141
|
+
constructor(code, message, requiredCapability) {
|
|
142
|
+
super(`${code}: ${message}`, { code });
|
|
143
|
+
this.name = 'CapabilityError';
|
|
144
|
+
if (requiredCapability !== undefined) {
|
|
145
|
+
this.requiredCapability = requiredCapability;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// ── Legacy session error (now part of the typed hierarchy) ───────────
|
|
150
|
+
/**
|
|
151
|
+
* SyncSessionError — Thrown when authentication/session is invalid or expired.
|
|
152
|
+
* Signals that the user should be redirected to sign in
|
|
153
|
+
* rather than showing a generic retry option.
|
|
154
|
+
*
|
|
155
|
+
* Extends `AbloAuthenticationError` so existing
|
|
156
|
+
* `SyncSessionError.isSessionError(...)` duck-type callers keep
|
|
157
|
+
* working, AND downstream code that only catches the typed hierarchy
|
|
158
|
+
* (`instanceof AbloAuthenticationError` / `e.type === 'AbloAuthenticationError'`)
|
|
159
|
+
* now sees session failures too.
|
|
160
|
+
*/
|
|
161
|
+
export class SyncSessionError extends AbloAuthenticationError {
|
|
162
|
+
isSessionError = true;
|
|
163
|
+
statusCode;
|
|
164
|
+
constructor(message, statusCode = 401) {
|
|
165
|
+
super(message, { httpStatus: statusCode, code: 'session_expired' });
|
|
166
|
+
this.name = 'SyncSessionError';
|
|
167
|
+
this.statusCode = statusCode;
|
|
168
|
+
if (Error.captureStackTrace) {
|
|
169
|
+
Error.captureStackTrace(this, SyncSessionError);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Check if an error is a session error (duck-type check)
|
|
174
|
+
*/
|
|
175
|
+
static isSessionError(error) {
|
|
176
|
+
if (error instanceof SyncSessionError) {
|
|
177
|
+
return true;
|
|
178
|
+
}
|
|
179
|
+
if (error && typeof error === 'object' && 'isSessionError' in error) {
|
|
180
|
+
return error.isSessionError === true;
|
|
181
|
+
}
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Check if an HTTP response status indicates a session error
|
|
186
|
+
*/
|
|
187
|
+
static isSessionErrorResponse(status, body) {
|
|
188
|
+
if (status === 401)
|
|
189
|
+
return true;
|
|
190
|
+
if (status === 403) {
|
|
191
|
+
if (body) {
|
|
192
|
+
const lowerBody = body.toLowerCase();
|
|
193
|
+
if (lowerBody.includes('session') ||
|
|
194
|
+
lowerBody.includes('unauthorized') ||
|
|
195
|
+
lowerBody.includes('not authenticated') ||
|
|
196
|
+
lowerBody.includes('token')) {
|
|
197
|
+
return true;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return true;
|
|
201
|
+
}
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Translate an HTTP response into the appropriate typed error.
|
|
207
|
+
*
|
|
208
|
+
* Single source of truth for status-code → class mapping — every SDK
|
|
209
|
+
* fetch path that sees a non-2xx response should route through here
|
|
210
|
+
* so the customer-visible error is always the right subclass.
|
|
211
|
+
*/
|
|
212
|
+
export function translateHttpError(status, body, requestId) {
|
|
213
|
+
const parsed = typeof body === 'object' && body !== null ? body : {};
|
|
214
|
+
const nested = parsed.error != null && typeof parsed.error === 'object'
|
|
215
|
+
? parsed.error
|
|
216
|
+
: undefined;
|
|
217
|
+
const flatError = typeof parsed.error === 'string' ? parsed.error : undefined;
|
|
218
|
+
const code = parsed.code ?? nested?.code ?? flatError;
|
|
219
|
+
const message = nested?.message ??
|
|
220
|
+
parsed.reason ??
|
|
221
|
+
parsed.message ??
|
|
222
|
+
flatError ??
|
|
223
|
+
(typeof body === 'string' ? body : `HTTP ${status}`);
|
|
224
|
+
const requiredCapability = nested?.requiredCapability ?? parsed.requiredCapability;
|
|
225
|
+
const baseOpts = { code, httpStatus: status, requestId };
|
|
226
|
+
if (status === 401)
|
|
227
|
+
return new AbloAuthenticationError(message, baseOpts);
|
|
228
|
+
if (status === 403 || code === 'capability_scope_denied' || code === 'capability_invalid') {
|
|
229
|
+
if (code === 'capability_scope_denied' || code === 'capability_invalid') {
|
|
230
|
+
return new CapabilityError(code, message, requiredCapability);
|
|
231
|
+
}
|
|
232
|
+
return new AbloPermissionError(message, baseOpts);
|
|
233
|
+
}
|
|
234
|
+
if (status === 409)
|
|
235
|
+
return new AbloIdempotencyError(message, baseOpts);
|
|
236
|
+
if (status === 422 || status === 400)
|
|
237
|
+
return new AbloValidationError(message, baseOpts);
|
|
238
|
+
if (status === 429)
|
|
239
|
+
return new AbloRateLimitError(message, baseOpts);
|
|
240
|
+
if (status >= 500)
|
|
241
|
+
return new AbloServerError(message, baseOpts);
|
|
242
|
+
return new AbloError(message, baseOpts);
|
|
243
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @ablo/sync-engine — The Collaboration Layer for AI and Humans
|
|
3
|
+
*
|
|
4
|
+
* ```ts
|
|
5
|
+
* import Ablo from '@ablo/sync-engine';
|
|
6
|
+
*
|
|
7
|
+
* const ablo = Ablo({ schema, apiKey: process.env.ABLO_API_KEY });
|
|
8
|
+
* await ablo.tasks.load({ where: { id: 'task_123' } });
|
|
9
|
+
* await ablo.tasks.update('task_123', { title: 'Fix bug' });
|
|
10
|
+
*
|
|
11
|
+
* type Entry = Ablo.Peer;
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* `Ablo({ schema, apiKey })` gives typed model resources. `Ablo({ apiKey })`
|
|
15
|
+
* gives the lower-level Resource / Intent / Commit client for agents,
|
|
16
|
+
* MCP routes, and custom runtimes.
|
|
17
|
+
*
|
|
18
|
+
* Stripe / Anthropic / OpenAI all do this: one import, resources
|
|
19
|
+
* reached via dot-access on the engine, types via namespace dots.
|
|
20
|
+
*
|
|
21
|
+
* Public subpaths:
|
|
22
|
+
* @ablo/sync-engine/schema — defineSchema, model, z (Zod)
|
|
23
|
+
* @ablo/sync-engine/react — <AbloProvider>, useQuery, useMutate
|
|
24
|
+
* @ablo/sync-engine/testing — test harnesses + mocks
|
|
25
|
+
*
|
|
26
|
+
* Consumer code should converge on `ablo.<model>.load(...)`, which routes
|
|
27
|
+
* through the engine's `HydrationCoordinator` and dedupes single-flight
|
|
28
|
+
* hydrations.
|
|
29
|
+
*/
|
|
30
|
+
export { Ablo } from './client/Ablo.js';
|
|
31
|
+
export type { AbloOptions, ModelCountOptions, ModelListOptions, ModelListScope, ModelLoadOptions, ModelEditHandle, ModelEditOptions, ModelOperations, } from './client/Ablo.js';
|
|
32
|
+
export type { AbloPersistence } from './client/persistence.js';
|
|
33
|
+
export { session, agent } from './principal.js';
|
|
34
|
+
import { Ablo } from './client/Ablo.js';
|
|
35
|
+
export default Ablo;
|
|
36
|
+
export { dataSource, abloSource, signAbloSourceRequest, verifyAbloSourceRequest, } from './source/index.js';
|
|
37
|
+
export { defaultPolicy } from './policy/index.js';
|
|
38
|
+
export { SyncSessionError, AbloError, AbloAuthenticationError, AbloPermissionError, AbloRateLimitError, AbloIdempotencyError, AbloConnectionError, AbloValidationError, AbloServerError, AbloStaleContextError, AbloBusyError, CapabilityError, translateHttpError, } from './errors.js';
|
|
39
|
+
export type { CommitReceipt, RequiredCapability } from './errors.js';
|
|
40
|
+
export { defineMutators } from './mutators/defineMutators.js';
|
|
41
|
+
export { createTransaction, type Transaction } from './mutators/Transaction.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @ablo/sync-engine — The Collaboration Layer for AI and Humans
|
|
3
|
+
*
|
|
4
|
+
* ```ts
|
|
5
|
+
* import Ablo from '@ablo/sync-engine';
|
|
6
|
+
*
|
|
7
|
+
* const ablo = Ablo({ schema, apiKey: process.env.ABLO_API_KEY });
|
|
8
|
+
* await ablo.tasks.load({ where: { id: 'task_123' } });
|
|
9
|
+
* await ablo.tasks.update('task_123', { title: 'Fix bug' });
|
|
10
|
+
*
|
|
11
|
+
* type Entry = Ablo.Peer;
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* `Ablo({ schema, apiKey })` gives typed model resources. `Ablo({ apiKey })`
|
|
15
|
+
* gives the lower-level Resource / Intent / Commit client for agents,
|
|
16
|
+
* MCP routes, and custom runtimes.
|
|
17
|
+
*
|
|
18
|
+
* Stripe / Anthropic / OpenAI all do this: one import, resources
|
|
19
|
+
* reached via dot-access on the engine, types via namespace dots.
|
|
20
|
+
*
|
|
21
|
+
* Public subpaths:
|
|
22
|
+
* @ablo/sync-engine/schema — defineSchema, model, z (Zod)
|
|
23
|
+
* @ablo/sync-engine/react — <AbloProvider>, useQuery, useMutate
|
|
24
|
+
* @ablo/sync-engine/testing — test harnesses + mocks
|
|
25
|
+
*
|
|
26
|
+
* Consumer code should converge on `ablo.<model>.load(...)`, which routes
|
|
27
|
+
* through the engine's `HydrationCoordinator` and dedupes single-flight
|
|
28
|
+
* hydrations.
|
|
29
|
+
*/
|
|
30
|
+
// ── Consumer API ──────────────────────────────────────────────────────────
|
|
31
|
+
// These are the only symbols external consumers should need from this path.
|
|
32
|
+
// Everything else is in a subpath.
|
|
33
|
+
// The canonical surface — `Ablo` is a function, type, and namespace under
|
|
34
|
+
// one name. Matches `Stripe`, `OpenAI`, `Anthropic`. Default export so
|
|
35
|
+
// `import Ablo from '@ablo/sync-engine'` works; named export so
|
|
36
|
+
// `import { Ablo }` also compiles.
|
|
37
|
+
export { Ablo } from './client/Ablo.js';
|
|
38
|
+
// Participant types live under `Ablo.Participant.*` —
|
|
39
|
+
// `Ablo.Participant.Joined`, `Ablo.Participant.Manager`,
|
|
40
|
+
// `Ablo.Participant.JoinOptions`, etc. Same dot-access shape as
|
|
41
|
+
// `Ablo.Peer`, `Ablo.Claim`, `Ablo.Turn`. No flat re-exports.
|
|
42
|
+
// Principal constructors — explicit factories for delegation paths
|
|
43
|
+
// (`Ablo({ kind: 'agent', as: session({...}) })`). Function exports
|
|
44
|
+
// because they're constructors, not types.
|
|
45
|
+
export { session, agent } from './principal.js';
|
|
46
|
+
import { Ablo } from './client/Ablo.js';
|
|
47
|
+
export default Ablo;
|
|
48
|
+
// Customer-owned storage adapter. Used only when Ablo Cloud coordinates
|
|
49
|
+
// state while canonical rows remain in the customer's database. Runtime
|
|
50
|
+
// helpers ship flat; type counterparts live under `Ablo.Source.*`
|
|
51
|
+
// (`Ablo.Source.Operation`, `Ablo.Source.Commit.Params`, etc.).
|
|
52
|
+
export { dataSource, abloSource, signAbloSourceRequest, verifyAbloSourceRequest, } from './source/index.js';
|
|
53
|
+
// Schema DSL is intentionally published from `@ablo/sync-engine/schema`.
|
|
54
|
+
// Keeping it out of the root import preserves one clean runtime surface:
|
|
55
|
+
// `import Ablo from '@ablo/sync-engine'`.
|
|
56
|
+
// Conflict policy — `defaultPolicy` (the rejecting default) is a value
|
|
57
|
+
// callers reference if they want to compose. The type counterparts
|
|
58
|
+
// (`Conflict`, `ConflictPolicy`, etc.) live under `Ablo.Conflict`,
|
|
59
|
+
// `Ablo.Conflict.Policy` on the namespace.
|
|
60
|
+
export { defaultPolicy } from './policy/index.js';
|
|
61
|
+
// Typed error hierarchy — Stripe-style. One import gets every class
|
|
62
|
+
// consumers need to discriminate failures (`e instanceof AbloX` or
|
|
63
|
+
// `e.type === 'AbloX'`) plus the HTTP-response translator.
|
|
64
|
+
export { SyncSessionError, AbloError, AbloAuthenticationError, AbloPermissionError, AbloRateLimitError, AbloIdempotencyError, AbloConnectionError, AbloValidationError, AbloServerError, AbloStaleContextError, AbloBusyError, CapabilityError, translateHttpError, } from './errors.js';
|
|
65
|
+
// Typed-global augmentation point. Consumers declare their Schema/Presence/
|
|
66
|
+
// Intents/UserMeta once in a `.d.ts` via `declare global { interface AbloSync
|
|
67
|
+
// { ... } }`. Resolver types live under the `Ablo` namespace —
|
|
68
|
+
// `Ablo.ResolveSchema`, `Ablo.ResolvePresence`, etc. — pure type-level.
|
|
69
|
+
// Custom mutators — runtime entry point only.
|
|
70
|
+
// Type counterparts moved to the `Ablo` namespace:
|
|
71
|
+
// Ablo.Mutator.Fn, Ablo.Transaction
|
|
72
|
+
// Ablo.Mutator.UndoEntry, Ablo.Mutator.InverseOp
|
|
73
|
+
// Ablo.Query, Ablo.QueryBatch, Ablo.QueryBatchResult
|
|
74
|
+
export { defineMutators } from './mutators/defineMutators.js';
|
|
75
|
+
// `createTransaction` is exposed so non-React callers (the sandbox AI
|
|
76
|
+
// executor, server-side workers) can invoke `defineMutators`-style
|
|
77
|
+
// custom mutators without going through `useMutators`. Construct a tx
|
|
78
|
+
// against `ablo.schema` + `ablo._store` + `ablo.organizationId` and
|
|
79
|
+
// pass it as `{ tx, args }` to the mutator function.
|
|
80
|
+
export { createTransaction } from './mutators/Transaction.js';
|
|
81
|
+
// Undo runtime is intentionally not part of the public root surface. App code
|
|
82
|
+
// uses `useUndoScope` from `@ablo/sync-engine/react`.
|