@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,423 @@
|
|
|
1
|
+
import type { Schema, SchemaRecord, InferCreate } from '../schema/schema.js';
|
|
2
|
+
export type SourcePrimitive = string | number | boolean | null;
|
|
3
|
+
export type SourceWhere = readonly [field: string, value: SourcePrimitive] | readonly [
|
|
4
|
+
field: string,
|
|
5
|
+
op: '=' | '!=' | '<' | '<=' | '>' | '>=' | 'IN' | 'NOT IN' | 'IS' | 'IS NOT' | 'LIKE' | 'NOT LIKE' | 'ILIKE' | 'NOT ILIKE',
|
|
6
|
+
value: SourcePrimitive | readonly SourcePrimitive[]
|
|
7
|
+
];
|
|
8
|
+
export interface SourceListQuery {
|
|
9
|
+
readonly where?: readonly SourceWhere[];
|
|
10
|
+
readonly limit?: number;
|
|
11
|
+
readonly orderBy?: string;
|
|
12
|
+
readonly order?: 'asc' | 'desc';
|
|
13
|
+
readonly related?: readonly string[];
|
|
14
|
+
/**
|
|
15
|
+
* Opaque cursor returned by a previous `list` call. The customer's
|
|
16
|
+
* `list` handler defines what this encodes (page index, last id,
|
|
17
|
+
* keyset). Ablo treats it as a black box — round-trips it back to
|
|
18
|
+
* fetch the next page until the handler returns no `nextCursor`.
|
|
19
|
+
*/
|
|
20
|
+
readonly cursor?: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Optional structured shape for a `list` handler that supports
|
|
24
|
+
* pagination. Handlers may keep returning a plain `Row[]` (no
|
|
25
|
+
* pagination, single-shot) or upgrade to this shape to expose a
|
|
26
|
+
* cursor that Ablo will round-trip on the next request.
|
|
27
|
+
*/
|
|
28
|
+
export interface SourceListPage<Row> {
|
|
29
|
+
readonly rows: readonly Row[];
|
|
30
|
+
readonly nextCursor?: string;
|
|
31
|
+
}
|
|
32
|
+
export type SourceListResult<Row> = readonly Row[] | SourceListPage<Row>;
|
|
33
|
+
/**
|
|
34
|
+
* Read-side scope context that Ablo attaches to source requests so
|
|
35
|
+
* the customer's `authorize` / model handlers can refuse calls that
|
|
36
|
+
* fall outside the participant's permitted syncGroups.
|
|
37
|
+
*
|
|
38
|
+
* This is informational — the customer is the only side that can
|
|
39
|
+
* actually enforce, since the canonical data lives in their store.
|
|
40
|
+
* Mirrors how Auth0 Custom DB scripts receive the requested scope and
|
|
41
|
+
* trust the script to honor it.
|
|
42
|
+
*/
|
|
43
|
+
export interface SourceRequestContext {
|
|
44
|
+
readonly participantId?: string;
|
|
45
|
+
readonly participantKind?: 'user' | 'agent' | 'system';
|
|
46
|
+
readonly organizationId?: string;
|
|
47
|
+
readonly requiredSyncGroups?: readonly string[];
|
|
48
|
+
/**
|
|
49
|
+
* Test/live mode for this request. Customers branch their source
|
|
50
|
+
* handlers on this (`if (mode === 'test') db = testDb`) so test
|
|
51
|
+
* traffic exercises the same code path against an isolated store.
|
|
52
|
+
*
|
|
53
|
+
* Mirrors Stripe's `sk_test_` / `sk_live_` distinction: same wire
|
|
54
|
+
* shape, same handler code, different namespace. Ablo's server-side
|
|
55
|
+
* fan-out does not yet partition deltas by mode — that lands when
|
|
56
|
+
* `sync_deltas.mode` ships. Until then, isolation is enforced
|
|
57
|
+
* customer-side via this field, which is the right boundary anyway
|
|
58
|
+
* (the customer's database is where the canonical data lives).
|
|
59
|
+
*
|
|
60
|
+
* Defaults to `'live'` when omitted so callers that don't opt in
|
|
61
|
+
* keep the existing behavior.
|
|
62
|
+
*/
|
|
63
|
+
readonly mode?: 'test' | 'live';
|
|
64
|
+
}
|
|
65
|
+
export interface SourceOperation {
|
|
66
|
+
readonly type: 'CREATE' | 'UPDATE' | 'DELETE' | 'ARCHIVE' | 'UNARCHIVE';
|
|
67
|
+
readonly model: string;
|
|
68
|
+
readonly id?: string | null;
|
|
69
|
+
readonly input?: Record<string, unknown> | null;
|
|
70
|
+
readonly transactionId?: string | null;
|
|
71
|
+
readonly readAt?: number | null;
|
|
72
|
+
readonly onStale?: 'reject' | 'force' | 'flag' | 'merge' | null;
|
|
73
|
+
}
|
|
74
|
+
export interface SourceDelta {
|
|
75
|
+
readonly model: string;
|
|
76
|
+
readonly id: string;
|
|
77
|
+
readonly type: SourceOperation['type'];
|
|
78
|
+
readonly data?: Record<string, unknown> | null;
|
|
79
|
+
readonly transactionId?: string | null;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* A change that happened in the customer's store. The source's
|
|
83
|
+
* `events` handler returns these so Ablo can append them to
|
|
84
|
+
* `sync_deltas` and fan them out to connected clients exactly like
|
|
85
|
+
* SDK-originated commits.
|
|
86
|
+
*
|
|
87
|
+
* The events handler can return everything from the outbox unfiltered;
|
|
88
|
+
* Ablo dedupes against `mutation_log` server-side using `clientTxId`.
|
|
89
|
+
* Events with no `clientTxId` are treated as external (cron jobs,
|
|
90
|
+
* dashboard edits, batch imports) and always fan out.
|
|
91
|
+
*/
|
|
92
|
+
export interface SourceEvent {
|
|
93
|
+
/**
|
|
94
|
+
* Globally unique event id from the customer's outbox. Used by Ablo
|
|
95
|
+
* for replay protection — re-delivering the same id is a no-op.
|
|
96
|
+
*/
|
|
97
|
+
readonly id: string;
|
|
98
|
+
readonly model: string;
|
|
99
|
+
readonly entityId: string;
|
|
100
|
+
readonly type: SourceOperation['type'];
|
|
101
|
+
readonly data?: Record<string, unknown> | null;
|
|
102
|
+
/**
|
|
103
|
+
* Tenant the event belongs to. Multi-tenant customers populate this
|
|
104
|
+
* from the row's organization column. Single-tenant deployments may
|
|
105
|
+
* omit it and let the poller fall back to its configured default.
|
|
106
|
+
* Drives the sync-group fan-out: clients in `org:${organizationId}`
|
|
107
|
+
* receive the resulting delta.
|
|
108
|
+
*/
|
|
109
|
+
readonly organizationId?: string;
|
|
110
|
+
/**
|
|
111
|
+
* Originating Ablo SDK commit id, when known. If the customer's
|
|
112
|
+
* outbox stores the `clientTxId` Ablo passed into the matching
|
|
113
|
+
* `commit` handler, round-trip it here and Ablo will skip events
|
|
114
|
+
* whose commit already produced a delta. External-origin events
|
|
115
|
+
* (cron jobs, batch imports, manual edits) leave this unset.
|
|
116
|
+
*/
|
|
117
|
+
readonly clientTxId?: string;
|
|
118
|
+
/**
|
|
119
|
+
* Wall-clock time the event occurred in the source. Optional; used
|
|
120
|
+
* only for ordering hints. Ablo trusts the customer's response order
|
|
121
|
+
* over this field.
|
|
122
|
+
*/
|
|
123
|
+
readonly occurredAt?: number;
|
|
124
|
+
}
|
|
125
|
+
export interface SourceCommitResult<Row = Record<string, unknown>> {
|
|
126
|
+
/**
|
|
127
|
+
* Canonical rows after the write. Ablo uses these to update hosted
|
|
128
|
+
* realtime projections and append deltas.
|
|
129
|
+
*/
|
|
130
|
+
readonly rows?: readonly Row[];
|
|
131
|
+
/**
|
|
132
|
+
* Optional explicit deltas when the source already computes them.
|
|
133
|
+
* Most sources can return rows and let Ablo derive the delta payload.
|
|
134
|
+
*/
|
|
135
|
+
readonly deltas?: readonly SourceDelta[];
|
|
136
|
+
}
|
|
137
|
+
export interface SourceCommitParams<TAuth = unknown> {
|
|
138
|
+
readonly operations: readonly SourceOperation[];
|
|
139
|
+
readonly clientTxId?: string;
|
|
140
|
+
readonly context: SourceHandlerContext<TAuth>;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Operation-level permission tag used by `resolveScopes`. Mirrors the
|
|
144
|
+
* four wire request types: a secret/key carries the set of operations
|
|
145
|
+
* it's allowed to invoke. Stripe's restricted-key model at the
|
|
146
|
+
* operation granularity — model-level scoping is a future addition.
|
|
147
|
+
*/
|
|
148
|
+
export type SourceScope = 'load' | 'list' | 'commit' | 'events';
|
|
149
|
+
export interface SourceEventsResult {
|
|
150
|
+
readonly events: readonly SourceEvent[];
|
|
151
|
+
/**
|
|
152
|
+
* Cursor for the next poll. When omitted Ablo treats the feed as
|
|
153
|
+
* fully drained for this round and uses the last event's cursor (or
|
|
154
|
+
* the initial cursor) for the next call.
|
|
155
|
+
*/
|
|
156
|
+
readonly nextCursor?: string;
|
|
157
|
+
}
|
|
158
|
+
export type SourceEventsHandler<TAuth = unknown> = (params: {
|
|
159
|
+
/**
|
|
160
|
+
* Cursor returned by a previous `events` call. Undefined on the
|
|
161
|
+
* first poll for a freshly-onboarded source. The customer decides
|
|
162
|
+
* what it encodes (last event id, timestamp, LSN, etc).
|
|
163
|
+
*/
|
|
164
|
+
readonly cursor?: string;
|
|
165
|
+
/**
|
|
166
|
+
* Caller-suggested upper bound on returned events. Customers may
|
|
167
|
+
* return fewer; returning more risks tripping Ablo's per-poll cap.
|
|
168
|
+
*/
|
|
169
|
+
readonly limit?: number;
|
|
170
|
+
readonly context: SourceHandlerContext<TAuth>;
|
|
171
|
+
}) => Promise<SourceEventsResult> | SourceEventsResult;
|
|
172
|
+
export interface SourceAuthorizeContext {
|
|
173
|
+
readonly request: Request;
|
|
174
|
+
readonly body: unknown;
|
|
175
|
+
readonly rawBody: string;
|
|
176
|
+
}
|
|
177
|
+
export interface SourceHandlerContext<TAuth = unknown> {
|
|
178
|
+
readonly auth: TAuth;
|
|
179
|
+
readonly request: Request;
|
|
180
|
+
/**
|
|
181
|
+
* `webhook-id` from the signed request — globally unique per the
|
|
182
|
+
* Standard Webhooks spec. Customers should dedupe by this id to
|
|
183
|
+
* defend against replay (Ablo doesn't dedupe at the source-handler
|
|
184
|
+
* boundary; it does at the delta-append boundary via `clientTxId`).
|
|
185
|
+
*/
|
|
186
|
+
readonly messageId?: string;
|
|
187
|
+
readonly signedAt?: number;
|
|
188
|
+
/**
|
|
189
|
+
* Scope context Ablo attached to this request. Present when the
|
|
190
|
+
* caller (sync-server) opted into scope-aware source mode. Customers
|
|
191
|
+
* can use it in `authorize` (to reject out-of-scope calls) and in
|
|
192
|
+
* `list` / `load` (to filter rows the participant is allowed to see).
|
|
193
|
+
*
|
|
194
|
+
* Absent for calls made without scope context (legacy callers,
|
|
195
|
+
* tests, or single-tenant deployments that haven't enabled it).
|
|
196
|
+
*/
|
|
197
|
+
readonly scope?: SourceRequestContext;
|
|
198
|
+
}
|
|
199
|
+
export interface SourceModelHandlers<Row, CreateInput, TAuth = unknown> {
|
|
200
|
+
load?(params: {
|
|
201
|
+
readonly id: string;
|
|
202
|
+
readonly context: SourceHandlerContext<TAuth>;
|
|
203
|
+
}): Promise<Row | null> | Row | null;
|
|
204
|
+
list?(params: {
|
|
205
|
+
readonly query: SourceListQuery;
|
|
206
|
+
readonly context: SourceHandlerContext<TAuth>;
|
|
207
|
+
}): Promise<SourceListResult<Row>> | SourceListResult<Row>;
|
|
208
|
+
/**
|
|
209
|
+
* Apply one or more operations for this model in the customer's own
|
|
210
|
+
* transaction. The source must be idempotent by operation/clientTxId.
|
|
211
|
+
*/
|
|
212
|
+
commit?(params: {
|
|
213
|
+
readonly operations: readonly SourceOperation[];
|
|
214
|
+
readonly clientTxId?: string;
|
|
215
|
+
readonly context: SourceHandlerContext<TAuth>;
|
|
216
|
+
}): Promise<SourceCommitResult<Row>> | SourceCommitResult<Row>;
|
|
217
|
+
}
|
|
218
|
+
export type SourceCommitHandler<TAuth = unknown> = (params: SourceCommitParams<TAuth>) => Promise<SourceCommitResult> | SourceCommitResult;
|
|
219
|
+
type SourceModels<S extends SchemaRecord, TAuth> = Partial<{
|
|
220
|
+
readonly [K in keyof S & string]: SourceModelHandlers<InferCreate<Schema<S>, K> & {
|
|
221
|
+
readonly id: string;
|
|
222
|
+
} & Record<string, unknown>, InferCreate<Schema<S>, K>, TAuth>;
|
|
223
|
+
}>;
|
|
224
|
+
export type SourceSecret = string | ((context: SourceAuthorizeContext) => Promise<string> | string);
|
|
225
|
+
export interface SourceSignatureOptions {
|
|
226
|
+
readonly secret: string;
|
|
227
|
+
readonly body: string;
|
|
228
|
+
/**
|
|
229
|
+
* Unique message id (`webhook-id` per the Standard Webhooks spec).
|
|
230
|
+
* Required: it goes into the HMAC input for replay defense, and
|
|
231
|
+
* receivers may dedupe by it.
|
|
232
|
+
*/
|
|
233
|
+
readonly messageId: string;
|
|
234
|
+
readonly timestamp?: number;
|
|
235
|
+
}
|
|
236
|
+
export interface SourceSignatureVerificationOptions {
|
|
237
|
+
readonly request: Request;
|
|
238
|
+
readonly body: string;
|
|
239
|
+
readonly secret: string;
|
|
240
|
+
readonly toleranceMs?: number;
|
|
241
|
+
}
|
|
242
|
+
export interface SourceSignatureVerificationResult {
|
|
243
|
+
readonly messageId: string;
|
|
244
|
+
readonly signedAt: number;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* HTTP headers used on signed source requests. Conforms to the
|
|
248
|
+
* Standard Webhooks specification (https://www.standardwebhooks.com/)
|
|
249
|
+
* so customer code can verify our signatures with any of the official
|
|
250
|
+
* libraries (svix, standardwebhooks, hookdeck, etc.) — no Ablo-
|
|
251
|
+
* specific verifier required.
|
|
252
|
+
*/
|
|
253
|
+
export declare const ABLO_SOURCE_HEADERS: {
|
|
254
|
+
readonly signature: "webhook-signature";
|
|
255
|
+
readonly timestamp: "webhook-timestamp";
|
|
256
|
+
readonly id: "webhook-id";
|
|
257
|
+
readonly idempotencyKey: "Idempotency-Key";
|
|
258
|
+
};
|
|
259
|
+
export declare class SourceSignatureError extends Error {
|
|
260
|
+
readonly code: 'source_signature_missing' | 'source_id_missing' | 'source_timestamp_missing' | 'source_timestamp_invalid' | 'source_timestamp_expired' | 'source_signature_invalid' | 'source_forbidden';
|
|
261
|
+
constructor(code: SourceSignatureError['code'], message: string);
|
|
262
|
+
}
|
|
263
|
+
export type AbloSourceOptions<S extends SchemaRecord, TAuth = unknown> = {
|
|
264
|
+
readonly schema: Schema<S>;
|
|
265
|
+
/**
|
|
266
|
+
* Shared secret for Ablo Cloud -> customer source calls. When set,
|
|
267
|
+
* abloSource verifies HMAC_SHA256(secret, `${timestamp}.${body}`)
|
|
268
|
+
* before `authorize` or any model handler runs.
|
|
269
|
+
*
|
|
270
|
+
* @deprecated Use `signingSecret`. Kept so existing source routes
|
|
271
|
+
* do not break during the Data Source naming cleanup.
|
|
272
|
+
*/
|
|
273
|
+
readonly secret?: SourceSecret;
|
|
274
|
+
/**
|
|
275
|
+
* Signing secret for Ablo -> customer Data Source calls. The value is
|
|
276
|
+
* created for the Data Source endpoint in Ablo and stored in the
|
|
277
|
+
* customer's app environment. Used to verify Standard Webhooks
|
|
278
|
+
* headers before any handler runs.
|
|
279
|
+
*/
|
|
280
|
+
readonly signingSecret?: SourceSecret;
|
|
281
|
+
/**
|
|
282
|
+
* Clock-skew window for signed source requests. Default: 5 minutes.
|
|
283
|
+
*/
|
|
284
|
+
readonly signatureToleranceMs?: number;
|
|
285
|
+
/**
|
|
286
|
+
* Verify the Ablo request and return customer-owned context such as
|
|
287
|
+
* a database handle, account scope, or current actor. Keep database
|
|
288
|
+
* credentials in this function's environment; never send them to Ablo.
|
|
289
|
+
*
|
|
290
|
+
* Signature verification is handled by `secret` before this function
|
|
291
|
+
* runs. `authorize` should only attach business context.
|
|
292
|
+
*/
|
|
293
|
+
readonly authorize?: (context: SourceAuthorizeContext) => Promise<TAuth> | TAuth;
|
|
294
|
+
/**
|
|
295
|
+
* Optional per-request scope resolver. When set, the helper checks
|
|
296
|
+
* the resolved scope set against the request's operation
|
|
297
|
+
* (`load`/`list`/`commit`/`events`) and returns 403
|
|
298
|
+
* `source_forbidden` if not allowed — before any model handler
|
|
299
|
+
* runs.
|
|
300
|
+
*
|
|
301
|
+
* Customers typically extract a key id from the request (e.g.
|
|
302
|
+
* `webhook-id` prefix, a custom header, or the secret itself) and
|
|
303
|
+
* look up the scopes for that key in their store. Mirrors Stripe
|
|
304
|
+
* restricted keys: one secret can read, another can read + write.
|
|
305
|
+
*
|
|
306
|
+
* When omitted, all operations are allowed (back-compat). Returning
|
|
307
|
+
* an empty set denies all operations.
|
|
308
|
+
*/
|
|
309
|
+
readonly resolveScopes?: (params: {
|
|
310
|
+
readonly auth: TAuth;
|
|
311
|
+
readonly request: Request;
|
|
312
|
+
readonly body: SourceRequest;
|
|
313
|
+
}) => Promise<ReadonlySet<SourceScope> | readonly SourceScope[]> | ReadonlySet<SourceScope> | readonly SourceScope[];
|
|
314
|
+
/**
|
|
315
|
+
* Top-level atomic commit handler. Prefer this for real applications:
|
|
316
|
+
* one UI/action commit can span several models and should run inside
|
|
317
|
+
* one customer-owned transaction.
|
|
318
|
+
*/
|
|
319
|
+
readonly commit?: SourceCommitHandler<TAuth>;
|
|
320
|
+
/**
|
|
321
|
+
* External-write feed. Ablo polls this to learn about changes that
|
|
322
|
+
* happened outside the SDK (cron jobs, dashboard edits, batch
|
|
323
|
+
* imports). Each returned event becomes a delta and fans out to
|
|
324
|
+
* connected clients.
|
|
325
|
+
*
|
|
326
|
+
* MUST exclude events that originated from Ablo SDK commits — those
|
|
327
|
+
* already produced deltas via the `commit` path. Returning them here
|
|
328
|
+
* would surface as duplicate updates on every connected client.
|
|
329
|
+
* Customers typically tag outbox rows with the originating
|
|
330
|
+
* `clientTxId` and skip rows whose tag is non-null.
|
|
331
|
+
*/
|
|
332
|
+
readonly events?: SourceEventsHandler<TAuth>;
|
|
333
|
+
/**
|
|
334
|
+
* Optional grouped form. The object-key form below is usually terser:
|
|
335
|
+
* `abloSource({ schema, files: { load, list, commit } })`.
|
|
336
|
+
*/
|
|
337
|
+
readonly models?: SourceModels<S, TAuth>;
|
|
338
|
+
} & SourceModels<S, TAuth>;
|
|
339
|
+
export type SourceLoadRequest = {
|
|
340
|
+
readonly type: 'load';
|
|
341
|
+
readonly model: string;
|
|
342
|
+
readonly id: string;
|
|
343
|
+
readonly scope?: SourceRequestContext;
|
|
344
|
+
};
|
|
345
|
+
export type SourceListRequest = {
|
|
346
|
+
readonly type: 'list';
|
|
347
|
+
readonly model: string;
|
|
348
|
+
readonly query?: SourceListQuery;
|
|
349
|
+
readonly scope?: SourceRequestContext;
|
|
350
|
+
};
|
|
351
|
+
export type SourceCommitRequest = {
|
|
352
|
+
readonly type: 'commit';
|
|
353
|
+
/**
|
|
354
|
+
* Legacy single-model hint. Omit for cross-model commits; top-level
|
|
355
|
+
* `commit` receives the whole operation array unchanged.
|
|
356
|
+
*/
|
|
357
|
+
readonly model?: string;
|
|
358
|
+
readonly operations: readonly SourceOperation[];
|
|
359
|
+
readonly clientTxId?: string;
|
|
360
|
+
readonly scope?: SourceRequestContext;
|
|
361
|
+
};
|
|
362
|
+
export type SourceEventsRequest = {
|
|
363
|
+
readonly type: 'events';
|
|
364
|
+
readonly cursor?: string;
|
|
365
|
+
readonly limit?: number;
|
|
366
|
+
readonly scope?: SourceRequestContext;
|
|
367
|
+
};
|
|
368
|
+
export type SourceRequest = SourceLoadRequest | SourceListRequest | SourceCommitRequest | SourceEventsRequest;
|
|
369
|
+
export type SourceResponse<Row = Record<string, unknown>> = {
|
|
370
|
+
readonly row: Row | null;
|
|
371
|
+
} | {
|
|
372
|
+
readonly rows: readonly Row[];
|
|
373
|
+
readonly nextCursor?: string;
|
|
374
|
+
} | {
|
|
375
|
+
readonly rows?: readonly Row[];
|
|
376
|
+
readonly deltas?: readonly SourceDelta[];
|
|
377
|
+
};
|
|
378
|
+
export declare function signAbloSourceRequest(options: SourceSignatureOptions): Promise<{
|
|
379
|
+
readonly headers: Record<string, string>;
|
|
380
|
+
readonly signedAt: number;
|
|
381
|
+
readonly signature: string;
|
|
382
|
+
}>;
|
|
383
|
+
export declare function verifyAbloSourceRequest(options: SourceSignatureVerificationOptions): Promise<SourceSignatureVerificationResult>;
|
|
384
|
+
/**
|
|
385
|
+
* Create a customer-owned data source endpoint.
|
|
386
|
+
*
|
|
387
|
+
* App code still talks to Ablo with `ablo.files.load/list/update`.
|
|
388
|
+
* This helper is only for customers who keep canonical rows in their own
|
|
389
|
+
* database and want Ablo Cloud to call a narrow, signed endpoint instead
|
|
390
|
+
* of receiving database credentials.
|
|
391
|
+
*/
|
|
392
|
+
export type DataSourcePrimitive = SourcePrimitive;
|
|
393
|
+
export type DataSourceWhere = SourceWhere;
|
|
394
|
+
export type DataSourceListQuery = SourceListQuery;
|
|
395
|
+
export type DataSourceListPage<Row> = SourceListPage<Row>;
|
|
396
|
+
export type DataSourceListResult<Row> = SourceListResult<Row>;
|
|
397
|
+
export type DataSourceRequestContext = SourceRequestContext;
|
|
398
|
+
export type DataSourceOperation = SourceOperation;
|
|
399
|
+
export type DataSourceDelta = SourceDelta;
|
|
400
|
+
export type DataSourceEvent = SourceEvent;
|
|
401
|
+
export type DataSourceCommitResult<Row = Record<string, unknown>> = SourceCommitResult<Row>;
|
|
402
|
+
export type DataSourceCommitParams<TAuth = unknown> = SourceCommitParams<TAuth>;
|
|
403
|
+
export type DataSourceScope = SourceScope;
|
|
404
|
+
export type DataSourceEventsResult = SourceEventsResult;
|
|
405
|
+
export type DataSourceEventsHandler<TAuth = unknown> = SourceEventsHandler<TAuth>;
|
|
406
|
+
export type DataSourceAuthorizeContext = SourceAuthorizeContext;
|
|
407
|
+
export type DataSourceHandlerContext<TAuth = unknown> = SourceHandlerContext<TAuth>;
|
|
408
|
+
export type DataSourceModelHandlers<Row, CreateInput, TAuth = unknown> = SourceModelHandlers<Row, CreateInput, TAuth>;
|
|
409
|
+
export type DataSourceCommitHandler<TAuth = unknown> = SourceCommitHandler<TAuth>;
|
|
410
|
+
export type DataSourceSecret = SourceSecret;
|
|
411
|
+
export type DataSourceSignatureOptions = SourceSignatureOptions;
|
|
412
|
+
export type DataSourceSignatureVerificationOptions = SourceSignatureVerificationOptions;
|
|
413
|
+
export type DataSourceSignatureVerificationResult = SourceSignatureVerificationResult;
|
|
414
|
+
export type DataSourceOptions<S extends SchemaRecord, TAuth = unknown> = AbloSourceOptions<S, TAuth>;
|
|
415
|
+
export type DataSourceLoadRequest = SourceLoadRequest;
|
|
416
|
+
export type DataSourceListRequest = SourceListRequest;
|
|
417
|
+
export type DataSourceCommitRequest = SourceCommitRequest;
|
|
418
|
+
export type DataSourceEventsRequest = SourceEventsRequest;
|
|
419
|
+
export type DataSourceRequest = SourceRequest;
|
|
420
|
+
export type DataSourceResponse<Row = Record<string, unknown>> = SourceResponse<Row>;
|
|
421
|
+
export declare function abloSource<const S extends SchemaRecord, TAuth = unknown>(options: AbloSourceOptions<S, TAuth>): (request: Request) => Promise<Response>;
|
|
422
|
+
export declare function dataSource<const S extends SchemaRecord, TAuth = unknown>(options: DataSourceOptions<S, TAuth>): (request: Request) => Promise<Response>;
|
|
423
|
+
export { createPushQueue, InMemoryPushQueueStorage, STANDARD_WEBHOOKS_RETRY_SCHEDULE, type PushQueue, type PushQueueItem, type PushQueueOptions, type PushQueueStorage, } from './pushQueue.js';
|