@abloatai/ablo 0.35.0 → 0.36.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.
Files changed (215) hide show
  1. package/CHANGELOG.md +713 -629
  2. package/README.md +56 -519
  3. package/bin/ablo.cjs +39 -0
  4. package/dist/BaseSyncedStore.d.ts +24 -4
  5. package/dist/BaseSyncedStore.js +53 -37
  6. package/dist/Database.d.ts +8 -20
  7. package/dist/Database.js +61 -59
  8. package/dist/InstanceCache.d.ts +6 -2
  9. package/dist/InstanceCache.js +18 -16
  10. package/dist/Model.d.ts +17 -7
  11. package/dist/Model.js +17 -7
  12. package/dist/ModelRegistry.d.ts +4 -0
  13. package/dist/ModelRegistry.js +17 -15
  14. package/dist/NetworkMonitor.d.ts +3 -1
  15. package/dist/NetworkMonitor.js +7 -5
  16. package/dist/SyncClient.d.ts +5 -15
  17. package/dist/SyncClient.js +60 -57
  18. package/dist/client/Ablo.js +30 -19
  19. package/dist/client/createInternalComponents.d.ts +4 -0
  20. package/dist/client/createInternalComponents.js +8 -2
  21. package/dist/client/createModelProxy.d.ts +21 -1
  22. package/dist/client/createModelProxy.js +123 -57
  23. package/dist/client/humans.d.ts +30 -9
  24. package/dist/client/humans.js +45 -19
  25. package/dist/client/reactiveEngine.d.ts +16 -11
  26. package/dist/client/reactiveEngine.js +113 -335
  27. package/dist/client/storeCluster.d.ts +47 -0
  28. package/dist/client/storeCluster.js +118 -0
  29. package/dist/client/storeLifecycle.d.ts +61 -0
  30. package/dist/client/storeLifecycle.js +231 -0
  31. package/dist/context.d.ts +13 -0
  32. package/dist/context.js +23 -0
  33. package/dist/core/index.d.ts +1 -1
  34. package/dist/docs/catalog.js +6 -3
  35. package/dist/index.d.ts +4 -2
  36. package/dist/index.js +4 -2
  37. package/dist/query/client.d.ts +3 -0
  38. package/dist/query/client.js +6 -5
  39. package/dist/react/AbloProvider.d.ts +13 -1
  40. package/dist/react/AbloProvider.js +5 -2
  41. package/dist/react/context.d.ts +2 -2
  42. package/dist/react/createAbloReact.d.ts +56 -0
  43. package/dist/react/createAbloReact.js +51 -0
  44. package/dist/react/index.d.ts +1 -0
  45. package/dist/react/index.js +3 -0
  46. package/dist/react/useAblo.d.ts +9 -2
  47. package/dist/react/useAblo.js +25 -7
  48. package/dist/schema/coordination.js +5 -1
  49. package/dist/schema/index.d.ts +1 -0
  50. package/dist/schema/index.js +4 -0
  51. package/dist/schema/select.js +3 -0
  52. package/dist/schema/serialize.js +3 -0
  53. package/dist/source/adapter.d.ts +7 -5
  54. package/dist/source/adapter.js +7 -5
  55. package/dist/source/index.d.ts +1 -1
  56. package/dist/source/index.js +1 -1
  57. package/dist/{core/storeContract.d.ts → storeContract.d.ts} +5 -5
  58. package/dist/{core → stores}/DatabaseManager.d.ts +3 -1
  59. package/dist/{core → stores}/DatabaseManager.js +13 -12
  60. package/dist/{core → stores}/StoreManager.d.ts +5 -3
  61. package/dist/{core → stores}/StoreManager.js +24 -22
  62. package/dist/stores/SyncActionStore.d.ts +3 -1
  63. package/dist/stores/SyncActionStore.js +9 -7
  64. package/dist/sync/BootstrapFetcher.d.ts +4 -0
  65. package/dist/sync/BootstrapFetcher.js +28 -26
  66. package/dist/sync/OnDemandLoader.d.ts +3 -0
  67. package/dist/sync/OnDemandLoader.js +1 -0
  68. package/dist/sync/bootstrapApply.d.ts +3 -0
  69. package/dist/sync/bootstrapApply.js +2 -2
  70. package/dist/sync/deltaPipeline.d.ts +13 -12
  71. package/dist/sync/deltaPipeline.js +21 -4
  72. package/dist/sync/groupChange.d.ts +3 -0
  73. package/dist/sync/groupChange.js +16 -14
  74. package/dist/sync/participants.d.ts +19 -2
  75. package/dist/sync/participants.js +3 -1
  76. package/dist/sync/schemas.d.ts +2 -1
  77. package/dist/sync/schemas.js +3 -3
  78. package/dist/syncLog/contract.d.ts +20 -0
  79. package/dist/syncLog/contract.js +19 -0
  80. package/dist/syncLog/index.d.ts +1 -0
  81. package/dist/syncLog/index.js +1 -0
  82. package/dist/transaction/auth/capability.d.ts +35 -0
  83. package/dist/transaction/auth/capability.js +25 -0
  84. package/dist/transaction/coordination/awaitClaimGrant.d.ts +7 -0
  85. package/dist/transaction/coordination/awaitClaimGrant.js +12 -0
  86. package/dist/transaction/coordination/claimHeartbeatLoop.d.ts +34 -0
  87. package/dist/transaction/coordination/claimHeartbeatLoop.js +20 -0
  88. package/dist/transaction/coordination/index.d.ts +4 -4
  89. package/dist/transaction/coordination/index.js +4 -3
  90. package/dist/transaction/coordination/locator.d.ts +23 -2
  91. package/dist/transaction/coordination/locator.js +22 -2
  92. package/dist/transaction/coordination/schema.d.ts +125 -62
  93. package/dist/transaction/coordination/schema.js +228 -64
  94. package/dist/transaction/coordination/targetConflict.js +32 -28
  95. package/dist/transaction/errorCodes.d.ts +2 -2
  96. package/dist/transaction/errorCodes.js +13 -9
  97. package/dist/transaction/plugin.d.ts +95 -2
  98. package/dist/transaction/plugin.js +21 -2
  99. package/dist/transaction/resources/httpResources.d.ts +57 -2
  100. package/dist/transaction/resources/modelOperations.d.ts +148 -40
  101. package/dist/transaction/resources/where.d.ts +16 -0
  102. package/dist/transaction/resources/where.js +45 -0
  103. package/dist/transaction/schema/field.d.ts +12 -18
  104. package/dist/transaction/schema/fieldRef.d.ts +38 -0
  105. package/dist/transaction/schema/fieldRef.js +11 -0
  106. package/dist/transaction/schema/openapi.d.ts +16 -15
  107. package/dist/transaction/schema/openapi.js +186 -25
  108. package/dist/transaction/schema/relation.d.ts +7 -2
  109. package/dist/transaction/schema/schema.d.ts +27 -0
  110. package/dist/transaction/schema/schema.js +20 -0
  111. package/dist/transaction/transactions/settlement/commitEnvelope.d.ts +1 -1
  112. package/dist/transaction/transactions/settlement/pendingWrite.d.ts +1 -1
  113. package/dist/transaction/transport/httpClient.d.ts +9 -1
  114. package/dist/transaction/transport/httpClient.js +1 -0
  115. package/dist/transaction/transport/httpTransport.js +156 -44
  116. package/dist/transaction/transport/wsTransport.d.ts +2 -4
  117. package/dist/transaction/transport/wsTransport.js +16 -10
  118. package/dist/transaction/types/streams.d.ts +10 -0
  119. package/dist/transaction/utils/duration.d.ts +25 -0
  120. package/dist/transaction/utils/duration.js +32 -0
  121. package/dist/transaction/wire/accountResponses.d.ts +69 -0
  122. package/dist/transaction/wire/accountResponses.js +36 -1
  123. package/dist/transaction/wire/auth.d.ts +9 -2
  124. package/dist/transaction/wire/auth.js +7 -1
  125. package/dist/transaction/wire/claims.d.ts +164 -97
  126. package/dist/transaction/wire/claims.js +126 -28
  127. package/dist/transaction/wire/commit.d.ts +1 -1
  128. package/dist/transaction/wire/feedEvent.d.ts +27 -0
  129. package/dist/transaction/wire/feedEvent.js +27 -1
  130. package/dist/transaction/wire/frames.d.ts +2 -2
  131. package/dist/transaction/wire/inboundFrames.d.ts +12 -2
  132. package/dist/transaction/wire/index.d.ts +10 -6
  133. package/dist/transaction/wire/index.js +12 -3
  134. package/dist/transaction/wire/modelMutations.d.ts +31 -0
  135. package/dist/transaction/wire/modelMutations.js +52 -0
  136. package/dist/transaction/wire/modelShape.d.ts +78 -0
  137. package/dist/transaction/wire/modelShape.js +74 -0
  138. package/dist/transactions/mutations/MutationQueue.d.ts +6 -0
  139. package/dist/transactions/mutations/MutationQueue.js +55 -45
  140. package/dist/transactions/mutations/commitPayload.d.ts +3 -2
  141. package/dist/transactions/mutations/commitPayload.js +5 -5
  142. package/dist/transactions/mutations/deltaConfirmation.d.ts +4 -0
  143. package/dist/transactions/mutations/deltaConfirmation.js +10 -8
  144. package/dist/transactions/mutations/replayValidation.d.ts +2 -1
  145. package/dist/transactions/mutations/replayValidation.js +3 -2
  146. package/dist/{core → views}/QueryView.d.ts +1 -1
  147. package/dist/{core → views}/QueryView.js +1 -1
  148. package/dist/{core → views}/ViewRegistry.d.ts +1 -1
  149. package/dist/{core/queryUtils.d.ts → views/incrementalView.d.ts} +6 -6
  150. package/dist/{core/queryUtils.js → views/incrementalView.js} +6 -6
  151. package/docs/agents.md +1 -1
  152. package/docs/api-keys.md +6 -6
  153. package/docs/api.md +5 -43
  154. package/docs/audit.md +4 -3
  155. package/docs/cli.md +11 -11
  156. package/docs/client-behavior.md +4 -4
  157. package/docs/concurrency-convention.md +28 -42
  158. package/docs/coordination.md +235 -83
  159. package/docs/data-sources.md +4 -4
  160. package/docs/debugging.md +34 -12
  161. package/docs/deployment.md +8 -8
  162. package/docs/examples/scoped-agent.md +3 -3
  163. package/docs/groups.md +57 -3
  164. package/docs/guarantees.md +37 -10
  165. package/docs/how-it-works.md +29 -5
  166. package/docs/idempotency.md +6 -6
  167. package/docs/identity.md +22 -23
  168. package/docs/index.md +8 -8
  169. package/docs/integration-guide.md +14 -3
  170. package/docs/mcp.md +7 -7
  171. package/docs/migration.md +34 -15
  172. package/docs/projects.md +1 -1
  173. package/docs/react.md +19 -8
  174. package/docs/sessions.md +1 -1
  175. package/docs/webhooks.md +9 -9
  176. package/llms.txt +4 -4
  177. package/package.json +13 -20
  178. package/dist/cli.cjs +0 -288600
  179. package/dist/testing/fixtures/bootstrap.d.ts +0 -49
  180. package/dist/testing/fixtures/bootstrap.js +0 -59
  181. package/dist/testing/fixtures/deltas.d.ts +0 -83
  182. package/dist/testing/fixtures/deltas.js +0 -136
  183. package/dist/testing/fixtures/httpResponses.d.ts +0 -70
  184. package/dist/testing/fixtures/httpResponses.js +0 -90
  185. package/dist/testing/fixtures/models.d.ts +0 -83
  186. package/dist/testing/fixtures/models.js +0 -272
  187. package/dist/testing/helpers/reactWrapper.d.ts +0 -69
  188. package/dist/testing/helpers/reactWrapper.js +0 -67
  189. package/dist/testing/helpers/syncEngineHarness.d.ts +0 -54
  190. package/dist/testing/helpers/syncEngineHarness.js +0 -73
  191. package/dist/testing/helpers/wait.d.ts +0 -30
  192. package/dist/testing/helpers/wait.js +0 -49
  193. package/dist/testing/index.d.ts +0 -23
  194. package/dist/testing/index.js +0 -33
  195. package/dist/testing/mocks/FakeDatabase.d.ts +0 -18
  196. package/dist/testing/mocks/FakeDatabase.js +0 -10
  197. package/dist/testing/mocks/MockMutationExecutor.d.ts +0 -87
  198. package/dist/testing/mocks/MockMutationExecutor.js +0 -186
  199. package/dist/testing/mocks/MockNetworkMonitor.d.ts +0 -20
  200. package/dist/testing/mocks/MockNetworkMonitor.js +0 -46
  201. package/dist/testing/mocks/MockSyncContext.d.ts +0 -51
  202. package/dist/testing/mocks/MockSyncContext.js +0 -72
  203. package/dist/testing/mocks/MockSyncStore.d.ts +0 -88
  204. package/dist/testing/mocks/MockSyncStore.js +0 -171
  205. package/dist/testing/mocks/MockWebSocket.d.ts +0 -71
  206. package/dist/testing/mocks/MockWebSocket.js +0 -118
  207. package/docs/interaction-model.md +0 -99
  208. /package/dist/{core → query}/QueryProcessor.d.ts +0 -0
  209. /package/dist/{core → query}/QueryProcessor.js +0 -0
  210. /package/dist/{core/storeContract.js → storeContract.js} +0 -0
  211. /package/dist/{core → stores}/openIDBWithTimeout.d.ts +0 -0
  212. /package/dist/{core → stores}/openIDBWithTimeout.js +0 -0
  213. /package/dist/{source → transaction}/footprint.d.ts +0 -0
  214. /package/dist/{source → transaction}/footprint.js +0 -0
  215. /package/dist/{core → views}/ViewRegistry.js +0 -0
@@ -1,49 +0,0 @@
1
- /**
2
- * Factories that build well-formed bootstrap responses for tests. A
3
- * bootstrap response is what the server returns when a client first syncs:
4
- * either a full snapshot of the models or a partial batch of deltas since a
5
- * known point. These helpers produce the same shapes, so tests can exercise
6
- * client sync logic without a live server.
7
- */
8
- import type { BootstrapType } from '../../transaction/types/index.js';
9
- export type BootstrapModelData = Record<string, Record<string, unknown>[]>;
10
- export interface BootstrapResponse {
11
- type: BootstrapType;
12
- lastSyncId: number;
13
- models?: BootstrapModelData;
14
- deltas?: {
15
- id: number;
16
- modelName: string;
17
- modelId: string;
18
- action: string;
19
- data: Record<string, unknown>;
20
- }[];
21
- deltaCount?: number;
22
- failedModels?: string[];
23
- timestamp: number;
24
- }
25
- /**
26
- * Builds a full bootstrap response — a fresh snapshot of the given models,
27
- * as the server sends on a client's first sync.
28
- */
29
- export declare function createFullBootstrapResponse(models: BootstrapModelData, lastSyncId?: number): BootstrapResponse;
30
- /**
31
- * Builds a partial bootstrap response — a batch of deltas applied on top of
32
- * the client's last known sync point, given by `lastSyncId`.
33
- */
34
- export declare function createPartialBootstrapResponse(deltas: BootstrapResponse['deltas'], lastSyncId: number): BootstrapResponse;
35
- /**
36
- * Builds a full bootstrap response with the common test models
37
- * pre-populated. Pass any of the named model arrays to include them in the
38
- * snapshot.
39
- */
40
- export declare function createTestBootstrapResponse(options?: {
41
- tasks?: Record<string, unknown>[];
42
- projects?: Record<string, unknown>[];
43
- slideDecks?: Record<string, unknown>[];
44
- slides?: Record<string, unknown>[];
45
- slideLayers?: Record<string, unknown>[];
46
- comments?: Record<string, unknown>[];
47
- lastSyncId?: number;
48
- failedModels?: string[];
49
- }): BootstrapResponse;
@@ -1,59 +0,0 @@
1
- /**
2
- * Factories that build well-formed bootstrap responses for tests. A
3
- * bootstrap response is what the server returns when a client first syncs:
4
- * either a full snapshot of the models or a partial batch of deltas since a
5
- * known point. These helpers produce the same shapes, so tests can exercise
6
- * client sync logic without a live server.
7
- */
8
- /**
9
- * Builds a full bootstrap response — a fresh snapshot of the given models,
10
- * as the server sends on a client's first sync.
11
- */
12
- export function createFullBootstrapResponse(models, lastSyncId = 100) {
13
- return {
14
- type: 'full',
15
- lastSyncId,
16
- models,
17
- timestamp: Date.now(),
18
- };
19
- }
20
- /**
21
- * Builds a partial bootstrap response — a batch of deltas applied on top of
22
- * the client's last known sync point, given by `lastSyncId`.
23
- */
24
- export function createPartialBootstrapResponse(deltas, lastSyncId) {
25
- return {
26
- type: 'partial',
27
- lastSyncId,
28
- deltas,
29
- deltaCount: deltas?.length ?? 0,
30
- timestamp: Date.now(),
31
- };
32
- }
33
- /**
34
- * Builds a full bootstrap response with the common test models
35
- * pre-populated. Pass any of the named model arrays to include them in the
36
- * snapshot.
37
- */
38
- export function createTestBootstrapResponse(options = {}) {
39
- const models = {};
40
- if (options.tasks)
41
- models.Task = options.tasks;
42
- if (options.projects)
43
- models.Project = options.projects;
44
- if (options.slideDecks)
45
- models.SlideDeck = options.slideDecks;
46
- if (options.slides)
47
- models.Slide = options.slides;
48
- if (options.slideLayers)
49
- models.SlideLayer = options.slideLayers;
50
- if (options.comments)
51
- models.Comment = options.comments;
52
- return {
53
- type: 'full',
54
- lastSyncId: options.lastSyncId ?? 100,
55
- models,
56
- failedModels: options.failedModels,
57
- timestamp: Date.now(),
58
- };
59
- }
@@ -1,83 +0,0 @@
1
- /**
2
- * Factories that build well-formed delta objects for tests. A delta, a
3
- * {@link SyncAction}, is a single change to one model instance in the wire
4
- * format the server sends: an insert, update, delete, archive, and so on.
5
- * These helpers let tests construct deltas without a live server.
6
- */
7
- import type { SyncActionType, SyncAction } from '../../stores/syncAction.js';
8
- /** Reset the delta counter (call in beforeEach for deterministic IDs) */
9
- export declare function resetDeltaCounter(): void;
10
- export interface CreateDeltaOptions {
11
- /** Sync ID (auto-increments if not provided) */
12
- id?: number;
13
- /** Model name (e.g., 'Task', 'Slide') */
14
- modelName: string;
15
- /** Model ID */
16
- modelId: string;
17
- /** Action type: I=Insert, U=Update, D=Delete, A=Archive, V=Unarchive */
18
- action: SyncActionType;
19
- /** Delta payload data */
20
- data?: Record<string, unknown>;
21
- }
22
- /**
23
- * Builds a single delta ({@link SyncAction}) in the server's wire format.
24
- */
25
- export declare function createDelta(options: CreateDeltaOptions): SyncAction;
26
- /**
27
- * Builds an insert delta for a new entity.
28
- */
29
- export declare function createInsertDelta(modelName: string, modelId: string, data: Record<string, unknown>, syncId?: number): SyncAction;
30
- /**
31
- * Builds an update delta for an existing entity.
32
- */
33
- export declare function createUpdateDelta(modelName: string, modelId: string, data: Record<string, unknown>, syncId?: number): SyncAction;
34
- /**
35
- * Builds a delete delta.
36
- */
37
- export declare function createDeleteDelta(modelName: string, modelId: string, syncId?: number): SyncAction;
38
- /**
39
- * Builds an archive delta, stamping `archivedAt` with the current time.
40
- */
41
- export declare function createArchiveDelta(modelName: string, modelId: string, syncId?: number): SyncAction;
42
- /**
43
- * Builds an unarchive delta, clearing `archivedAt`.
44
- */
45
- export declare function createUnarchiveDelta(modelName: string, modelId: string, syncId?: number): SyncAction;
46
- /**
47
- * Builds a covering ('C') delta. It signals that the client has gained
48
- * permission to see an entity that already exists. The client treats it
49
- * like an insert, adding the entity to its local store as if newly created.
50
- * A covering delta typically follows a group-added delta.
51
- */
52
- export declare function createCoveringDelta(modelName: string, modelId: string, data: Record<string, unknown>, syncId?: number): SyncAction;
53
- /**
54
- * Builds a group-added ('G') delta in the incremental payload shape. It
55
- * signals that the recipient was added to a single sync group. The client
56
- * updates its subscription state and waits for covering deltas to deliver
57
- * the newly visible entities. Unlike the older payload that carries both
58
- * added and removed groups, this shape does not trigger a re-bootstrap.
59
- */
60
- export declare function createGroupAddedDelta(userId: string, group: string, syncId?: number): SyncAction;
61
- /**
62
- * Builds a group-change ('G') delta in the older payload shape, which
63
- * carries both added and removed groups in one delta and forces a full
64
- * re-bootstrap on the client. Useful for testing backward compatibility
65
- * with that older shape.
66
- */
67
- export declare function createLegacyGroupChangeDelta(userId: string, added: string[], removed: string[], syncId?: number): SyncAction;
68
- /**
69
- * Builds a group-removed ('S') delta. It signals that the recipient lost
70
- * access to a sync group. The client purges the affected local state and
71
- * re-bootstraps with the updated group list.
72
- */
73
- export declare function createGroupRemovedDelta(userId: string, group: string, syncId?: number): SyncAction;
74
- /**
75
- * Builds a batch of deltas with sequential sync IDs.
76
- */
77
- export declare function createDeltaBatch(deltas: Omit<CreateDeltaOptions, 'id'>[], startingSyncId?: number): SyncAction[];
78
- /**
79
- * Builds a confirmation delta, which signals that a mutation was persisted
80
- * by the server. The client's transaction queue watches for these to
81
- * confirm its in-flight writes.
82
- */
83
- export declare function createConfirmationDelta(modelName: string, modelId: string, syncId: number, action?: SyncActionType, data?: Record<string, unknown>): SyncAction;
@@ -1,136 +0,0 @@
1
- /**
2
- * Factories that build well-formed delta objects for tests. A delta, a
3
- * {@link SyncAction}, is a single change to one model instance in the wire
4
- * format the server sends: an insert, update, delete, archive, and so on.
5
- * These helpers let tests construct deltas without a live server.
6
- */
7
- let deltaCounter = 0;
8
- /** Reset the delta counter (call in beforeEach for deterministic IDs) */
9
- export function resetDeltaCounter() {
10
- deltaCounter = 0;
11
- }
12
- /**
13
- * Builds a single delta ({@link SyncAction}) in the server's wire format.
14
- */
15
- export function createDelta(options) {
16
- deltaCounter++;
17
- return {
18
- id: options.id ?? deltaCounter,
19
- modelName: options.modelName,
20
- modelId: options.modelId,
21
- action: options.action,
22
- data: options.data ?? {},
23
- __class: 'SyncAction',
24
- };
25
- }
26
- /**
27
- * Builds an insert delta for a new entity.
28
- */
29
- export function createInsertDelta(modelName, modelId, data, syncId) {
30
- return createDelta({ modelName, modelId, action: 'I', data, id: syncId });
31
- }
32
- /**
33
- * Builds an update delta for an existing entity.
34
- */
35
- export function createUpdateDelta(modelName, modelId, data, syncId) {
36
- return createDelta({ modelName, modelId, action: 'U', data, id: syncId });
37
- }
38
- /**
39
- * Builds a delete delta.
40
- */
41
- export function createDeleteDelta(modelName, modelId, syncId) {
42
- return createDelta({ modelName, modelId, action: 'D', data: {}, id: syncId });
43
- }
44
- /**
45
- * Builds an archive delta, stamping `archivedAt` with the current time.
46
- */
47
- export function createArchiveDelta(modelName, modelId, syncId) {
48
- return createDelta({
49
- modelName,
50
- modelId,
51
- action: 'A',
52
- data: { archivedAt: new Date().toISOString() },
53
- id: syncId,
54
- });
55
- }
56
- /**
57
- * Builds an unarchive delta, clearing `archivedAt`.
58
- */
59
- export function createUnarchiveDelta(modelName, modelId, syncId) {
60
- return createDelta({
61
- modelName,
62
- modelId,
63
- action: 'V',
64
- data: { archivedAt: null },
65
- id: syncId,
66
- });
67
- }
68
- /**
69
- * Builds a covering ('C') delta. It signals that the client has gained
70
- * permission to see an entity that already exists. The client treats it
71
- * like an insert, adding the entity to its local store as if newly created.
72
- * A covering delta typically follows a group-added delta.
73
- */
74
- export function createCoveringDelta(modelName, modelId, data, syncId) {
75
- return createDelta({ modelName, modelId, action: 'C', data, id: syncId });
76
- }
77
- /**
78
- * Builds a group-added ('G') delta in the incremental payload shape. It
79
- * signals that the recipient was added to a single sync group. The client
80
- * updates its subscription state and waits for covering deltas to deliver
81
- * the newly visible entities. Unlike the older payload that carries both
82
- * added and removed groups, this shape does not trigger a re-bootstrap.
83
- */
84
- export function createGroupAddedDelta(userId, group, syncId) {
85
- return createDelta({
86
- modelName: 'SyncGroupChange',
87
- modelId: `sga_${userId}`,
88
- action: 'G',
89
- data: { group, userId },
90
- id: syncId,
91
- });
92
- }
93
- /**
94
- * Builds a group-change ('G') delta in the older payload shape, which
95
- * carries both added and removed groups in one delta and forces a full
96
- * re-bootstrap on the client. Useful for testing backward compatibility
97
- * with that older shape.
98
- */
99
- export function createLegacyGroupChangeDelta(userId, added, removed, syncId) {
100
- return createDelta({
101
- modelName: 'SyncGroupChange',
102
- modelId: `sgc_${userId}`,
103
- action: 'G',
104
- data: { addedGroups: added, removedGroups: removed },
105
- id: syncId,
106
- });
107
- }
108
- /**
109
- * Builds a group-removed ('S') delta. It signals that the recipient lost
110
- * access to a sync group. The client purges the affected local state and
111
- * re-bootstraps with the updated group list.
112
- */
113
- export function createGroupRemovedDelta(userId, group, syncId) {
114
- return createDelta({
115
- modelName: 'SyncGroupChange',
116
- modelId: `sgr_${userId}`,
117
- action: 'S',
118
- data: { group, userId },
119
- id: syncId,
120
- });
121
- }
122
- /**
123
- * Builds a batch of deltas with sequential sync IDs.
124
- */
125
- export function createDeltaBatch(deltas, startingSyncId) {
126
- const start = startingSyncId ?? deltaCounter + 1;
127
- return deltas.map((d, i) => createDelta({ ...d, id: start + i }));
128
- }
129
- /**
130
- * Builds a confirmation delta, which signals that a mutation was persisted
131
- * by the server. The client's transaction queue watches for these to
132
- * confirm its in-flight writes.
133
- */
134
- export function createConfirmationDelta(modelName, modelId, syncId, action = 'U', data = {}) {
135
- return createDelta({ modelName, modelId, action, data, id: syncId });
136
- }
@@ -1,70 +0,0 @@
1
- /**
2
- * Response bodies for a fake HTTP server, built in the shapes the real one
3
- * answers with.
4
- *
5
- * A test that hand-rolls `{ data, stamp }` is asserting against a server it
6
- * invented. That is how a client and its server drift apart while every test
7
- * stays green: the fixture and the client agree, and neither has met the
8
- * route. Each builder here is `satisfies`-pinned to the wire schema the server
9
- * answers with and the client parses — so a change to the contract breaks these
10
- * fixtures at compile time, and the tests that use them describe a server that
11
- * exists.
12
- *
13
- * Only the fields a test actually varies are parameters; everything else is a
14
- * plausible default, because a fixture that makes you fill in `object: 'model'`
15
- * teaches nothing and gets copy-pasted wrong.
16
- */
17
- import type { ModelReadResponse, ModelListResponse, ClaimAcquiredResponse, ClaimQueuedResponse, ClaimListResponse, ClaimHeartbeatReply } from '../../transaction/wire/index.js';
18
- import type { ModelClaim } from '../../transaction/coordination/index.js';
19
- /** `GET /v1/models/{model}/{id}`. Pass `data: null` for a miss. */
20
- export declare function modelReadResponse(args: {
21
- model: string;
22
- id: string;
23
- data: unknown;
24
- stamp?: number;
25
- claims?: readonly ModelClaim[];
26
- }): ModelReadResponse;
27
- /** `GET /v1/models/{model}`. */
28
- export declare function modelListResponse(args: {
29
- model: string;
30
- data: readonly unknown[];
31
- hasMore?: boolean;
32
- nextCursor?: string | null;
33
- stamp?: number;
34
- }): ModelListResponse;
35
- /** One claim in the shape the HTTP claim routes return it. */
36
- export declare function modelClaim(args: {
37
- id: string;
38
- model: string;
39
- entityId: string;
40
- actor?: string;
41
- participantKind?: ModelClaim['participantKind'];
42
- description?: string;
43
- status?: 'active' | 'queued';
44
- position?: number;
45
- expiresAt?: number;
46
- fenceToken?: number;
47
- field?: string;
48
- }): ModelClaim;
49
- /** `POST /v1/models/{model}/{id}/claim` — 201, the lease is yours. */
50
- export declare function claimAcquiredResponse(claim: ModelClaim): ClaimAcquiredResponse;
51
- /** `POST /v1/models/{model}/{id}/claim` — 202, you are in the wait line. */
52
- export declare function claimQueuedResponse(args: {
53
- claimId: string;
54
- position: number;
55
- heldBy?: string;
56
- expiresAt?: number;
57
- }): ClaimQueuedResponse;
58
- /** `GET /v1/claims`. */
59
- export declare function claimListResponse(args?: {
60
- claims?: readonly ModelClaim[];
61
- queue?: readonly ModelClaim[];
62
- }): ClaimListResponse;
63
- /** `POST /v1/models/{model}/{id}/claim/heartbeat`. */
64
- export declare function claimHeartbeatReply(args: {
65
- claimId: string;
66
- status?: 'held' | 'queued';
67
- expiresAt?: number;
68
- queueDepth?: number;
69
- position?: number;
70
- }): ClaimHeartbeatReply;
@@ -1,90 +0,0 @@
1
- /**
2
- * Response bodies for a fake HTTP server, built in the shapes the real one
3
- * answers with.
4
- *
5
- * A test that hand-rolls `{ data, stamp }` is asserting against a server it
6
- * invented. That is how a client and its server drift apart while every test
7
- * stays green: the fixture and the client agree, and neither has met the
8
- * route. Each builder here is `satisfies`-pinned to the wire schema the server
9
- * answers with and the client parses — so a change to the contract breaks these
10
- * fixtures at compile time, and the tests that use them describe a server that
11
- * exists.
12
- *
13
- * Only the fields a test actually varies are parameters; everything else is a
14
- * plausible default, because a fixture that makes you fill in `object: 'model'`
15
- * teaches nothing and gets copy-pasted wrong.
16
- */
17
- /** `GET /v1/models/{model}/{id}`. Pass `data: null` for a miss. */
18
- export function modelReadResponse(args) {
19
- return {
20
- object: 'model',
21
- model: args.model,
22
- id: args.id,
23
- data: args.data,
24
- stamp: args.stamp ?? 0,
25
- claims: args.claims ?? [],
26
- };
27
- }
28
- /** `GET /v1/models/{model}`. */
29
- export function modelListResponse(args) {
30
- return {
31
- object: 'list',
32
- model: args.model,
33
- data: [...args.data],
34
- has_more: args.hasMore ?? false,
35
- next_cursor: args.nextCursor ?? null,
36
- stamp: args.stamp ?? 0,
37
- };
38
- }
39
- /** One claim in the shape the HTTP claim routes return it. */
40
- export function modelClaim(args) {
41
- return {
42
- id: args.id,
43
- actor: args.actor ?? 'user_fixture',
44
- participantKind: args.participantKind ?? 'user',
45
- description: args.description ?? 'editing',
46
- ...(args.field !== undefined ? { field: args.field } : {}),
47
- ...(args.status !== undefined ? { status: args.status } : {}),
48
- ...(args.position !== undefined ? { position: args.position } : {}),
49
- expiresAt: args.expiresAt ?? Date.now() + 60_000,
50
- ...(args.fenceToken !== undefined ? { fenceToken: args.fenceToken } : {}),
51
- target: { model: args.model, id: args.entityId },
52
- };
53
- }
54
- /** `POST /v1/models/{model}/{id}/claim` — 201, the lease is yours. */
55
- export function claimAcquiredResponse(claim) {
56
- return { id: claim.id, object: 'claim', claim };
57
- }
58
- /** `POST /v1/models/{model}/{id}/claim` — 202, you are in the wait line. */
59
- export function claimQueuedResponse(args) {
60
- return {
61
- status: 'queued',
62
- claimId: args.claimId,
63
- position: args.position,
64
- ...(args.heldBy !== undefined ? { heldBy: args.heldBy } : {}),
65
- ...(args.expiresAt !== undefined ? { expiresAt: args.expiresAt } : {}),
66
- };
67
- }
68
- /** `GET /v1/claims`. */
69
- export function claimListResponse(args = {}) {
70
- return {
71
- object: 'list',
72
- claims: args.claims ?? [],
73
- queue: args.queue ?? [],
74
- };
75
- }
76
- /** `POST /v1/models/{model}/{id}/claim/heartbeat`. */
77
- export function claimHeartbeatReply(args) {
78
- const status = args.status ?? 'held';
79
- return {
80
- object: 'claim_heartbeat',
81
- claimId: args.claimId,
82
- status,
83
- ...(status === 'held'
84
- ? {
85
- expiresAt: args.expiresAt ?? Date.now() + 60_000,
86
- ...(args.queueDepth !== undefined ? { queueDepth: args.queueDepth } : {}),
87
- }
88
- : { position: args.position ?? 0 }),
89
- };
90
- }
@@ -1,83 +0,0 @@
1
- /**
2
- * A small set of {@link Model} subclasses used across the package's tests.
3
- * They form two foreign-key chains and carry the creation priorities the
4
- * transaction queue uses to order dependent writes:
5
- * TestProject (10) → TestTask (10, references Project) → TestComment (30, references Task)
6
- * TestSlideDeck (10) → TestSlide (15, references SlideDeck) → TestSlideLayer (20, references Slide)
7
- */
8
- import { Model } from '../../Model.js';
9
- import { ModelRegistry } from '../../ModelRegistry.js';
10
- export declare class TestProject extends Model {
11
- name: string;
12
- description: string;
13
- organizationId: string;
14
- constructor(data?: Partial<TestProject> & Record<string, unknown>);
15
- getModelName(): string;
16
- }
17
- export declare class TestTask extends Model {
18
- title: string;
19
- status: string;
20
- projectId: string | null;
21
- assigneeId: string | null;
22
- organizationId: string;
23
- constructor(data?: Partial<TestTask> & Record<string, unknown>);
24
- getModelName(): string;
25
- }
26
- export declare class TestComment extends Model {
27
- body: string;
28
- taskId: string | null;
29
- organizationId: string;
30
- constructor(data?: Partial<TestComment> & Record<string, unknown>);
31
- getModelName(): string;
32
- }
33
- export declare class TestSlideDeck extends Model {
34
- title: string;
35
- organizationId: string;
36
- constructor(data?: Partial<TestSlideDeck> & Record<string, unknown>);
37
- getModelName(): string;
38
- }
39
- export declare class TestSlide extends Model {
40
- order: number;
41
- deckId: string | null;
42
- organizationId: string;
43
- constructor(data?: Partial<TestSlide> & Record<string, unknown>);
44
- getModelName(): string;
45
- }
46
- export declare class TestSlideLayer extends Model {
47
- slideId: string | null;
48
- zIndex: number;
49
- type: string;
50
- content: string;
51
- organizationId: string;
52
- constructor(data?: Partial<TestSlideLayer> & Record<string, unknown>);
53
- getModelName(): string;
54
- }
55
- /**
56
- * Maps each test model to its creation priority, matching the order the
57
- * transaction queue uses when writing dependent models.
58
- */
59
- export declare const TEST_MODEL_PRIORITIES: Map<string, number>;
60
- /**
61
- * Registers every test model with a {@link ModelRegistry}, wiring up their
62
- * properties, references, and foreign-key relationships.
63
- */
64
- export declare function registerTestModels(registry: ModelRegistry): void;
65
- /**
66
- * Builds a sync engine configuration pre-loaded with the test models'
67
- * creation priorities and related settings.
68
- */
69
- export declare function createTestConfig(): {
70
- modelCreatePriority: ReadonlyMap<string, number>;
71
- defaultCreatePriority: number;
72
- defaultNonCreatePriority: number;
73
- essentialFields: Readonly<Record<string, readonly string[]>>;
74
- classNameFallbackMap: Readonly<Record<string, string>>;
75
- };
76
- /** Reset the counter (call in beforeEach for deterministic IDs) */
77
- export declare function resetFixtureCounter(): void;
78
- export declare function createProjectFixture(overrides?: Partial<Record<string, unknown>>): TestProject;
79
- export declare function createTaskFixture(overrides?: Partial<Record<string, unknown>>): TestTask;
80
- export declare function createCommentFixture(overrides?: Partial<Record<string, unknown>>): TestComment;
81
- export declare function createSlideDeckFixture(overrides?: Partial<Record<string, unknown>>): TestSlideDeck;
82
- export declare function createSlideFixture(overrides?: Partial<Record<string, unknown>>): TestSlide;
83
- export declare function createSlideLayerFixture(overrides?: Partial<Record<string, unknown>>): TestSlideLayer;