@abloatai/ablo 0.26.0 → 0.28.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 +42 -2
- package/README.md +102 -86
- package/dist/BaseSyncedStore.d.ts +85 -88
- package/dist/BaseSyncedStore.js +134 -151
- package/dist/Database.d.ts +68 -69
- package/dist/Database.js +316 -135
- package/dist/{ObjectPool.d.ts → InstanceCache.d.ts} +10 -13
- package/dist/{ObjectPool.js → InstanceCache.js} +85 -83
- package/dist/LazyReferenceCollection.d.ts +11 -15
- package/dist/LazyReferenceCollection.js +12 -16
- package/dist/Model.d.ts +54 -52
- package/dist/Model.js +78 -62
- package/dist/ModelRegistry.d.ts +21 -19
- package/dist/ModelRegistry.js +23 -27
- package/dist/NetworkMonitor.d.ts +5 -6
- package/dist/NetworkMonitor.js +5 -6
- package/dist/SyncClient.d.ts +122 -118
- package/dist/SyncClient.js +541 -245
- package/dist/adapters/alwaysOnline.d.ts +6 -8
- package/dist/adapters/alwaysOnline.js +6 -8
- package/dist/adapters/inMemoryStorage.d.ts +10 -9
- package/dist/adapters/inMemoryStorage.js +21 -9
- package/dist/agent/Agent.d.ts +27 -32
- package/dist/agent/Agent.js +18 -19
- package/dist/agent/index.d.ts +4 -4
- package/dist/agent/index.js +5 -5
- package/dist/agent/session.d.ts +47 -44
- package/dist/agent/session.js +37 -48
- package/dist/agent/types.d.ts +26 -31
- package/dist/agent/types.js +6 -7
- package/dist/ai-sdk/coordinatedTool.d.ts +108 -0
- package/dist/ai-sdk/{coordinated-tool.js → coordinatedTool.js} +44 -38
- package/dist/ai-sdk/coordinationContext.d.ts +46 -0
- package/dist/ai-sdk/{coordination-context.js → coordinationContext.js} +26 -33
- package/dist/ai-sdk/index.d.ts +25 -22
- package/dist/ai-sdk/index.js +25 -22
- package/dist/ai-sdk/wrap.d.ts +6 -7
- package/dist/ai-sdk/wrap.js +1 -1
- package/dist/auth/credentialPolicy.d.ts +69 -74
- package/dist/auth/credentialPolicy.js +51 -56
- package/dist/auth/credentialSource.d.ts +6 -5
- package/dist/auth/credentialSource.js +9 -10
- package/dist/auth/index.d.ts +59 -58
- package/dist/auth/index.js +31 -37
- package/dist/auth/schemas.d.ts +5 -4
- package/dist/auth/schemas.js +5 -4
- package/dist/batching/index.d.ts +19 -21
- package/dist/batching/index.js +14 -17
- package/dist/cli.cjs +173 -121
- package/dist/client/Ablo.d.ts +97 -74
- package/dist/client/Ablo.js +129 -163
- package/dist/client/ApiClient.d.ts +30 -19
- package/dist/client/ApiClient.js +442 -81
- package/dist/client/auth.d.ts +47 -47
- package/dist/client/auth.js +108 -117
- package/dist/client/claimHeartbeatLoop.d.ts +50 -0
- package/dist/client/claimHeartbeatLoop.js +88 -0
- package/dist/client/consoleLogger.d.ts +5 -6
- package/dist/client/consoleLogger.js +5 -6
- package/dist/client/createInternalComponents.d.ts +16 -17
- package/dist/client/createInternalComponents.js +26 -31
- package/dist/client/createModelProxy.d.ts +130 -120
- package/dist/client/createModelProxy.js +152 -122
- package/dist/client/credentialEndpoint.d.ts +40 -42
- package/dist/client/credentialEndpoint.js +35 -36
- package/dist/client/functionalUpdate.d.ts +29 -27
- package/dist/client/functionalUpdate.js +21 -21
- package/dist/client/hostedEndpoints.d.ts +9 -12
- package/dist/client/hostedEndpoints.js +9 -12
- package/dist/client/httpClient.d.ts +59 -53
- package/dist/client/httpClient.js +29 -31
- package/dist/client/identity.d.ts +15 -20
- package/dist/client/identity.js +47 -58
- package/dist/client/modelRegistration.d.ts +5 -9
- package/dist/client/modelRegistration.js +78 -87
- package/dist/client/options.d.ts +157 -157
- package/dist/client/options.js +3 -7
- package/dist/client/registerDataSource.d.ts +9 -9
- package/dist/client/registerDataSource.js +15 -16
- package/dist/client/resourceTypes.d.ts +64 -75
- package/dist/client/resourceTypes.js +4 -10
- package/dist/client/schemaConfig.d.ts +31 -43
- package/dist/client/schemaConfig.js +38 -50
- package/dist/client/sessionMint.d.ts +16 -12
- package/dist/client/sessionMint.js +26 -31
- package/dist/client/validateAbloOptions.d.ts +12 -14
- package/dist/client/validateAbloOptions.js +8 -9
- package/dist/client/writeOptionsSchema.d.ts +18 -16
- package/dist/client/writeOptionsSchema.js +23 -20
- package/dist/client/wsMutationExecutor.d.ts +16 -20
- package/dist/client/wsMutationExecutor.js +18 -23
- package/dist/commit/contract.d.ts +493 -0
- package/dist/commit/contract.js +187 -0
- package/dist/commit/index.d.ts +6 -0
- package/dist/commit/index.js +5 -0
- package/dist/context.d.ts +6 -4
- package/dist/context.js +6 -4
- package/dist/coordination/index.d.ts +10 -8
- package/dist/coordination/index.js +14 -12
- package/dist/coordination/schema.d.ts +176 -128
- package/dist/coordination/schema.js +197 -133
- package/dist/coordination/trace.d.ts +9 -10
- package/dist/coordination/trace.js +13 -14
- package/dist/core/DatabaseManager.d.ts +5 -7
- package/dist/core/DatabaseManager.js +15 -19
- package/dist/core/QueryProcessor.d.ts +7 -9
- package/dist/core/QueryProcessor.js +22 -28
- package/dist/core/QueryView.d.ts +8 -8
- package/dist/core/QueryView.js +2 -2
- package/dist/core/StoreManager.d.ts +14 -14
- package/dist/core/StoreManager.js +33 -24
- package/dist/core/ViewRegistry.d.ts +5 -5
- package/dist/core/ViewRegistry.js +4 -4
- package/dist/core/index.d.ts +17 -12
- package/dist/core/index.js +32 -26
- package/dist/core/openIDBWithTimeout.d.ts +38 -36
- package/dist/core/openIDBWithTimeout.js +42 -43
- package/dist/core/queryUtils.d.ts +45 -0
- package/dist/core/queryUtils.js +69 -0
- package/dist/core/storeContract.d.ts +63 -61
- package/dist/core/storeContract.js +8 -12
- package/dist/environment.d.ts +28 -0
- package/dist/environment.js +21 -0
- package/dist/errorCodes.d.ts +107 -99
- package/dist/errorCodes.js +137 -134
- package/dist/errors.d.ts +160 -166
- package/dist/errors.js +155 -158
- package/dist/index.d.ts +36 -27
- package/dist/index.js +91 -86
- package/dist/interfaces/index.d.ts +102 -113
- package/dist/interfaces/index.js +5 -4
- package/dist/keys/index.d.ts +27 -29
- package/dist/keys/index.js +41 -40
- package/dist/mutators/RecordingTransaction.d.ts +16 -16
- package/dist/mutators/RecordingTransaction.js +31 -37
- package/dist/mutators/Transaction.d.ts +18 -26
- package/dist/mutators/Transaction.js +14 -20
- package/dist/mutators/UndoManager.d.ts +124 -131
- package/dist/mutators/UndoManager.js +177 -156
- package/dist/mutators/defineMutators.d.ts +23 -34
- package/dist/mutators/defineMutators.js +14 -20
- package/dist/mutators/inverseOp.d.ts +12 -15
- package/dist/mutators/inverseOp.js +12 -15
- package/dist/mutators/mutateActions.d.ts +10 -9
- package/dist/mutators/mutateActions.js +1 -1
- package/dist/mutators/readerActions.d.ts +9 -8
- package/dist/mutators/readerActions.js +2 -2
- package/dist/mutators/undoApply.d.ts +31 -27
- package/dist/mutators/undoApply.js +26 -24
- package/dist/policy/index.d.ts +5 -3
- package/dist/policy/index.js +5 -3
- package/dist/policy/types.d.ts +104 -100
- package/dist/policy/types.js +67 -66
- package/dist/query/client.d.ts +28 -23
- package/dist/query/client.js +45 -43
- package/dist/query/types.d.ts +37 -60
- package/dist/query/types.js +13 -33
- package/dist/react/AbloProvider.d.ts +1 -1
- package/dist/react/AbloProvider.js +2 -2
- package/dist/react/context.d.ts +25 -28
- package/dist/react/context.js +9 -10
- package/dist/react/index.d.ts +41 -42
- package/dist/react/index.js +37 -38
- package/dist/react/internalContext.d.ts +17 -19
- package/dist/react/useAblo.d.ts +28 -25
- package/dist/react/useAblo.js +41 -17
- package/dist/react/useCurrentUserId.d.ts +8 -7
- package/dist/react/useCurrentUserId.js +8 -7
- package/dist/react/useErrorListener.d.ts +7 -7
- package/dist/react/useErrorListener.js +10 -11
- package/dist/react/useMutationFailureListener.d.ts +8 -8
- package/dist/react/useMutationFailureListener.js +8 -8
- package/dist/react/useMutators.d.ts +11 -11
- package/dist/react/useMutators.js +3 -3
- package/dist/react/useReactive.js +2 -2
- package/dist/react/useSyncStatus.d.ts +4 -6
- package/dist/react/useUndoScope.d.ts +7 -9
- package/dist/react/useUndoScope.js +1 -1
- package/dist/schema/coordination.d.ts +21 -25
- package/dist/schema/coordination.js +21 -25
- package/dist/schema/ddl.d.ts +43 -39
- package/dist/schema/ddl.js +75 -68
- package/dist/schema/ddlLock.d.ts +20 -24
- package/dist/schema/ddlLock.js +18 -23
- package/dist/schema/diff.d.ts +99 -61
- package/dist/schema/diff.js +43 -34
- package/dist/schema/field.d.ts +37 -42
- package/dist/schema/field.js +35 -48
- package/dist/schema/generate.d.ts +12 -12
- package/dist/schema/generate.js +12 -12
- package/dist/schema/index.d.ts +3 -3
- package/dist/schema/index.js +21 -23
- package/dist/schema/model.d.ts +118 -143
- package/dist/schema/model.js +22 -33
- package/dist/schema/openapi.d.ts +10 -9
- package/dist/schema/openapi.js +5 -3
- package/dist/schema/queries.d.ts +29 -31
- package/dist/schema/queries.js +23 -25
- package/dist/schema/relation.d.ts +89 -99
- package/dist/schema/relation.js +13 -13
- package/dist/schema/residency.d.ts +16 -13
- package/dist/schema/residency.js +16 -13
- package/dist/schema/roles.d.ts +36 -43
- package/dist/schema/roles.js +31 -37
- package/dist/schema/schema.d.ts +64 -43
- package/dist/schema/schema.js +31 -32
- package/dist/schema/select.d.ts +13 -13
- package/dist/schema/select.js +13 -13
- package/dist/schema/serialize.d.ts +28 -31
- package/dist/schema/serialize.js +27 -31
- package/dist/schema/sugar.d.ts +17 -32
- package/dist/schema/sugar.js +14 -29
- package/dist/schema/{sync-delta-row.d.ts → syncDeltaRow.d.ts} +26 -49
- package/dist/schema/syncDeltaRow.js +89 -0
- package/dist/schema/tenancy.d.ts +44 -46
- package/dist/schema/tenancy.js +46 -48
- package/dist/server/adapter.d.ts +58 -58
- package/dist/server/adapter.js +13 -14
- package/dist/server/commit.d.ts +60 -64
- package/dist/server/index.d.ts +9 -10
- package/dist/server/index.js +1 -1
- package/dist/server/readConfig.d.ts +70 -0
- package/dist/server/readConfig.js +8 -0
- package/dist/server/storageMode.d.ts +23 -0
- package/dist/server/storageMode.js +17 -0
- package/dist/source/adapter.d.ts +30 -25
- package/dist/source/adapter.js +10 -10
- package/dist/source/adapters/drizzle.d.ts +28 -23
- package/dist/source/adapters/drizzle.js +30 -25
- package/dist/source/adapters/kysely.d.ts +27 -25
- package/dist/source/adapters/kysely.js +24 -23
- package/dist/source/adapters/memory.d.ts +8 -7
- package/dist/source/adapters/memory.js +9 -8
- package/dist/source/adapters/prisma.d.ts +13 -12
- package/dist/source/adapters/prisma.js +22 -25
- package/dist/source/conformance.d.ts +18 -11
- package/dist/source/conformance.js +17 -11
- package/dist/source/connector.d.ts +31 -32
- package/dist/source/connector.js +28 -28
- package/dist/source/connectorProtocol.d.ts +160 -0
- package/dist/source/connectorProtocol.js +162 -0
- package/dist/source/contract.d.ts +26 -27
- package/dist/source/contract.js +28 -29
- package/dist/source/factory.d.ts +46 -58
- package/dist/source/factory.js +22 -27
- package/dist/source/index.d.ts +7 -9
- package/dist/source/index.js +12 -14
- package/dist/source/migrations.d.ts +9 -9
- package/dist/source/migrations.js +9 -9
- package/dist/source/next.d.ts +9 -10
- package/dist/source/next.js +6 -7
- package/dist/source/pushQueue.d.ts +69 -47
- package/dist/source/pushQueue.js +32 -28
- package/dist/source/signing.d.ts +46 -17
- package/dist/source/signing.js +28 -11
- package/dist/source/types.d.ts +121 -104
- package/dist/source/types.js +13 -14
- package/dist/stores/ObjectStore.d.ts +24 -12
- package/dist/stores/ObjectStore.js +38 -16
- package/dist/stores/ObjectStoreContract.d.ts +14 -15
- package/dist/stores/SyncActionStore.d.ts +7 -11
- package/dist/stores/SyncActionStore.js +13 -17
- package/dist/surface.d.ts +28 -21
- package/dist/surface.js +29 -20
- package/dist/sync/{BootstrapHelper.d.ts → BootstrapFetcher.d.ts} +36 -42
- package/dist/sync/{BootstrapHelper.js → BootstrapFetcher.js} +76 -76
- package/dist/sync/ConnectionManager.d.ts +39 -50
- package/dist/sync/ConnectionManager.js +55 -66
- package/dist/sync/NetworkProbe.d.ts +24 -29
- package/dist/sync/NetworkProbe.js +63 -69
- package/dist/sync/{HydrationCoordinator.d.ts → OnDemandLoader.d.ts} +42 -41
- package/dist/sync/{HydrationCoordinator.js → OnDemandLoader.js} +59 -54
- package/dist/sync/{AreaOfInterestManager.d.ts → SubscriptionManager.d.ts} +43 -57
- package/dist/sync/{AreaOfInterestManager.js → SubscriptionManager.js} +43 -51
- package/dist/sync/SyncWebSocket.d.ts +141 -166
- package/dist/sync/SyncWebSocket.js +191 -223
- package/dist/sync/awaitClaimGrant.d.ts +18 -18
- package/dist/sync/awaitClaimGrant.js +11 -11
- package/dist/sync/bootstrapApply.d.ts +34 -24
- package/dist/sync/bootstrapApply.js +27 -19
- package/dist/sync/commitFrames.d.ts +21 -20
- package/dist/sync/commitFrames.js +18 -18
- package/dist/sync/createClaimStream.d.ts +23 -22
- package/dist/sync/createClaimStream.js +105 -23
- package/dist/sync/createPresenceStream.d.ts +19 -18
- package/dist/sync/createPresenceStream.js +25 -26
- package/dist/sync/createSnapshot.d.ts +12 -14
- package/dist/sync/createSnapshot.js +20 -26
- package/dist/sync/credentialLifecycle.d.ts +104 -104
- package/dist/sync/credentialLifecycle.js +140 -147
- package/dist/sync/deltaPipeline.d.ts +36 -34
- package/dist/sync/deltaPipeline.js +64 -65
- package/dist/sync/groupChange.d.ts +63 -61
- package/dist/sync/groupChange.js +74 -78
- package/dist/sync/heartbeat.d.ts +34 -33
- package/dist/sync/heartbeat.js +31 -31
- package/dist/sync/participants.d.ts +19 -19
- package/dist/sync/persistedPrefix.d.ts +12 -0
- package/dist/sync/persistedPrefix.js +22 -0
- package/dist/sync/schemas.d.ts +3 -2
- package/dist/sync/schemas.js +14 -10
- package/dist/sync/syncCursor.d.ts +17 -21
- package/dist/sync/syncCursor.js +17 -21
- package/dist/sync/syncPlan.d.ts +28 -36
- package/dist/sync/syncPlan.js +18 -19
- package/dist/sync/syncPosition.d.ts +54 -49
- package/dist/sync/syncPosition.js +57 -52
- package/dist/sync/wsFrameHandlers.d.ts +35 -36
- package/dist/sync/wsFrameHandlers.js +63 -67
- package/dist/testing/fixtures/bootstrap.d.ts +12 -6
- package/dist/testing/fixtures/bootstrap.js +12 -6
- package/dist/testing/fixtures/deltas.d.ts +30 -33
- package/dist/testing/fixtures/deltas.js +30 -33
- package/dist/testing/fixtures/models.d.ts +11 -10
- package/dist/testing/fixtures/models.js +11 -10
- package/dist/testing/helpers/{react-wrapper.d.ts → reactWrapper.d.ts} +13 -10
- package/dist/testing/helpers/{react-wrapper.js → reactWrapper.js} +15 -12
- package/dist/testing/helpers/{sync-engine-harness.d.ts → syncEngineHarness.d.ts} +17 -15
- package/dist/testing/helpers/{sync-engine-harness.js → syncEngineHarness.js} +12 -10
- package/dist/testing/helpers/wait.d.ts +13 -8
- package/dist/testing/helpers/wait.js +13 -8
- package/dist/testing/index.d.ts +5 -3
- package/dist/testing/index.js +3 -2
- package/dist/testing/mocks/FakeDatabase.d.ts +18 -0
- package/dist/testing/mocks/FakeDatabase.js +10 -0
- package/dist/testing/mocks/MockMutationExecutor.d.ts +18 -17
- package/dist/testing/mocks/MockMutationExecutor.js +15 -14
- package/dist/testing/mocks/MockNetworkMonitor.d.ts +8 -8
- package/dist/testing/mocks/MockNetworkMonitor.js +8 -8
- package/dist/testing/mocks/MockSyncContext.d.ts +20 -17
- package/dist/testing/mocks/MockSyncContext.js +15 -13
- package/dist/testing/mocks/MockSyncStore.d.ts +10 -10
- package/dist/testing/mocks/MockSyncStore.js +11 -11
- package/dist/testing/mocks/MockWebSocket.d.ts +28 -23
- package/dist/testing/mocks/MockWebSocket.js +22 -21
- package/dist/transactions/TransactionQueue.d.ts +244 -181
- package/dist/transactions/TransactionQueue.js +929 -423
- package/dist/transactions/TransactionStore.d.ts +6 -4
- package/dist/transactions/TransactionStore.js +6 -4
- package/dist/transactions/UnconfirmedWrites.d.ts +82 -0
- package/dist/transactions/UnconfirmedWrites.js +104 -0
- package/dist/transactions/coalesceRules.d.ts +41 -17
- package/dist/transactions/coalesceRules.js +40 -17
- package/dist/transactions/commitEnvelope.d.ts +132 -0
- package/dist/transactions/commitEnvelope.js +139 -0
- package/dist/transactions/commitOutboxStore.d.ts +32 -0
- package/dist/transactions/commitOutboxStore.js +26 -0
- package/dist/transactions/commitPayload.d.ts +63 -52
- package/dist/transactions/commitPayload.js +54 -57
- package/dist/transactions/deltaConfirmation.d.ts +20 -22
- package/dist/transactions/deltaConfirmation.js +37 -45
- package/dist/transactions/httpCommitEnvelope.d.ts +43 -0
- package/dist/transactions/httpCommitEnvelope.js +179 -0
- package/dist/transactions/optimisticApply.d.ts +49 -0
- package/dist/transactions/optimisticApply.js +65 -0
- package/dist/transactions/replayValidation.d.ts +182 -0
- package/dist/transactions/replayValidation.js +156 -0
- package/dist/types/global.d.ts +46 -41
- package/dist/types/global.js +20 -19
- package/dist/types/index.d.ts +71 -77
- package/dist/types/index.js +22 -22
- package/dist/types/modelData.d.ts +6 -8
- package/dist/types/modelData.js +5 -7
- package/dist/types/participant.d.ts +10 -11
- package/dist/types/participant.js +6 -8
- package/dist/types/streams.d.ts +208 -195
- package/dist/types/streams.js +7 -7
- package/dist/utils/asyncIterator.d.ts +25 -32
- package/dist/utils/asyncIterator.js +25 -32
- package/dist/utils/duration.d.ts +12 -15
- package/dist/utils/duration.js +12 -15
- package/dist/utils/mobxSetup.d.ts +53 -0
- package/dist/utils/{mobx-setup.js → mobxSetup.js} +42 -98
- package/dist/webhooks/events.d.ts +21 -16
- package/dist/webhooks/events.js +10 -8
- package/dist/webhooks/index.d.ts +5 -7
- package/dist/webhooks/index.js +5 -7
- package/dist/wire/bootstrapReason.d.ts +9 -0
- package/dist/wire/bootstrapReason.js +8 -0
- package/dist/{schema/sync-delta-wire.d.ts → wire/delta.d.ts} +58 -41
- package/dist/wire/delta.js +114 -0
- package/dist/wire/errorEnvelope.d.ts +30 -31
- package/dist/wire/errorEnvelope.js +34 -40
- package/dist/wire/frames.d.ts +315 -86
- package/dist/wire/frames.js +47 -33
- package/dist/wire/index.d.ts +18 -14
- package/dist/wire/index.js +32 -27
- package/dist/wire/listEnvelope.d.ts +16 -23
- package/dist/wire/listEnvelope.js +7 -6
- package/dist/wire/protocol.d.ts +25 -32
- package/dist/wire/protocol.js +25 -32
- package/dist/wire/protocolVersion.d.ts +44 -40
- package/dist/wire/protocolVersion.js +44 -40
- package/docs/api.md +10 -10
- package/docs/coordination.md +59 -0
- package/docs/mcp.md +1 -1
- package/package.json +17 -11
- package/dist/ai-sdk/coordinated-tool.d.ts +0 -101
- package/dist/ai-sdk/coordination-context.d.ts +0 -52
- package/dist/core/query-utils.d.ts +0 -34
- package/dist/core/query-utils.js +0 -59
- package/dist/schema/sync-delta-row.js +0 -103
- package/dist/schema/sync-delta-wire.js +0 -102
- package/dist/server/read-config.d.ts +0 -67
- package/dist/server/read-config.js +0 -8
- package/dist/server/storage-mode.d.ts +0 -8
- package/dist/server/storage-mode.js +0 -28
- package/dist/source/connector-protocol.d.ts +0 -159
- package/dist/source/connector-protocol.js +0 -161
- package/dist/transactions/OptimisticEchoTracker.d.ts +0 -82
- package/dist/transactions/OptimisticEchoTracker.js +0 -104
- package/dist/transactions/mutation-error-handler.d.ts +0 -5
- package/dist/transactions/mutation-error-handler.js +0 -39
- package/dist/transactions/optimistic.d.ts +0 -24
- package/dist/transactions/optimistic.js +0 -45
- package/dist/transactions/persistedReplay.d.ts +0 -93
- package/dist/transactions/persistedReplay.js +0 -105
- package/dist/utils/mobx-setup.d.ts +0 -42
package/dist/Model.d.ts
CHANGED
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Model
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* - Return updates/changes (not perform them)
|
|
9
|
-
*
|
|
10
|
-
* Models do NOT:
|
|
11
|
-
* - Access stores or singletons
|
|
12
|
-
* - Perform side effects (saving, notifications)
|
|
13
|
-
* - Know about sync infrastructure
|
|
2
|
+
* Model is the base class for the sync engine's domain models. A model is a
|
|
3
|
+
* plain domain object: it holds data and business logic, tracks its own
|
|
4
|
+
* property changes, and validates itself, and it returns the changes to apply
|
|
5
|
+
* rather than applying them. It does not reach into stores or singletons and
|
|
6
|
+
* does not perform side effects such as saving or sending notifications;
|
|
7
|
+
* persistence and sync are driven by the store that owns the model.
|
|
14
8
|
*/
|
|
15
9
|
/** Store interface — methods that Model subclasses can call on the store */
|
|
16
10
|
interface SyncStoreRef {
|
|
@@ -67,9 +61,10 @@ export interface ModelChanges {
|
|
|
67
61
|
timestamp: Date;
|
|
68
62
|
}
|
|
69
63
|
/**
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
64
|
+
* The abstract base class every domain model extends. It holds the model's id
|
|
65
|
+
* and timestamps, tracks in-place property changes for change detection and
|
|
66
|
+
* undo, and serializes itself, while leaving persistence and sync to the store
|
|
67
|
+
* that owns it.
|
|
73
68
|
*/
|
|
74
69
|
export declare abstract class Model {
|
|
75
70
|
/** Static reference to active SyncedStore for reactive queries */
|
|
@@ -156,27 +151,17 @@ export declare abstract class Model {
|
|
|
156
151
|
*/
|
|
157
152
|
isNew(): boolean;
|
|
158
153
|
/**
|
|
159
|
-
*
|
|
160
|
-
* load.
|
|
161
|
-
*
|
|
162
|
-
* `modifiedProperties
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
* Architectural note: this method exists because we allow direct
|
|
166
|
-
* property writes (`slide.title = 'foo'`) AND mutator-recorded
|
|
167
|
-
* writes to coexist. Zero / Replicache structurally avoids this:
|
|
168
|
-
* every mutation MUST go through a registered mutator function,
|
|
169
|
-
* mutator args are serialized, and on server pull all unacked
|
|
170
|
-
* mutations are dropped and the mutator functions are replayed on
|
|
171
|
-
* the new basis (rebase). That makes per-instance baselines
|
|
172
|
-
* unnecessary because the b-tree at the new basis IS the
|
|
173
|
-
* authoritative pre-session state.
|
|
154
|
+
* Return a read-only view of the snapshot taken at {@link markAsPersisted}
|
|
155
|
+
* or at load time. The undo machinery uses it to recover a field's pre-edit
|
|
156
|
+
* value when the field was written without first being tracked in
|
|
157
|
+
* `modifiedProperties`. The returned object is the live snapshot, so callers
|
|
158
|
+
* must not mutate it.
|
|
174
159
|
*
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
* `
|
|
178
|
-
*
|
|
179
|
-
*
|
|
160
|
+
* This per-instance baseline is needed because application code can edit a
|
|
161
|
+
* model in two ways that coexist: a direct property write
|
|
162
|
+
* (`slide.title = 'foo'`) and a recorded mutation. A design in which every
|
|
163
|
+
* write went through a single recorded path would not need it, since the
|
|
164
|
+
* last acknowledged state would already be the authoritative baseline.
|
|
180
165
|
*/
|
|
181
166
|
getOriginalSnapshot(): Readonly<ModelData> | undefined;
|
|
182
167
|
/**
|
|
@@ -184,7 +169,7 @@ export declare abstract class Model {
|
|
|
184
169
|
*/
|
|
185
170
|
clearChanges(): void;
|
|
186
171
|
/**
|
|
187
|
-
* Capture a before-image for `keys` — the
|
|
172
|
+
* Capture a before-image for `keys` — the single source of truth for the
|
|
188
173
|
* "previous value" that undo inverses are built from. Both undo paths call
|
|
189
174
|
* this so they can never drift: the stream path
|
|
190
175
|
* (`TransactionQueue.extractPreviousData`) and the manual-record path
|
|
@@ -194,10 +179,10 @@ export declare abstract class Model {
|
|
|
194
179
|
* 1. `modifiedProperties.get(key).old` — first-old-wins pre-session
|
|
195
180
|
* baseline, set whenever the field was mutated in place before commit.
|
|
196
181
|
* 2. `getOriginalSnapshot()[key]` — the last loaded/acked row, the correct
|
|
197
|
-
* before-image for a key written
|
|
182
|
+
* before-image for a key written without a prior in-place mutation
|
|
198
183
|
* (e.g. a `precomputedChanges` write).
|
|
199
184
|
* 3. `fallbackToLive` only — the current live value. The manual-record path
|
|
200
|
-
* wants this last resort; the stream path deliberately
|
|
185
|
+
* wants this last resort; the stream path deliberately omits unresolved
|
|
201
186
|
* keys so `buildUndoOps` drops an un-revertible inverse rather than
|
|
202
187
|
* inventing one. The flag is the one intentional difference between the
|
|
203
188
|
* two callers — do not collapse it.
|
|
@@ -205,8 +190,8 @@ export declare abstract class Model {
|
|
|
205
190
|
* `id` is always skipped. Values are read out per-key, so the
|
|
206
191
|
* `getOriginalSnapshot()` "callers must not mutate" contract is preserved.
|
|
207
192
|
*
|
|
208
|
-
* Invariant this relies on: a given undo scope is
|
|
209
|
-
* (`recordFromStream: true`)
|
|
193
|
+
* Invariant this relies on: a given undo scope is either stream-recorded
|
|
194
|
+
* (`recordFromStream: true`) or manual (`useMutators({ undoScope })`), never
|
|
210
195
|
* both — otherwise a write would be captured twice. No surface sets both.
|
|
211
196
|
*/
|
|
212
197
|
capturePreviousValues(keys: Iterable<string>, opts?: {
|
|
@@ -214,7 +199,7 @@ export declare abstract class Model {
|
|
|
214
199
|
}): ModelData;
|
|
215
200
|
/**
|
|
216
201
|
* Drop the `modifiedProperties` entries for `keys` — re-baselines a field
|
|
217
|
-
* after its `.old` has been frozen into a committed transaction, so the
|
|
202
|
+
* after its `.old` has been frozen into a committed transaction, so the next
|
|
218
203
|
* write to the same field starts from this commit's result rather than the
|
|
219
204
|
* stale pre-session `.old` that {@link propertyChanged}'s first-old-wins
|
|
220
205
|
* policy preserves. Safe because the committed transaction owns its own
|
|
@@ -257,7 +242,7 @@ export declare abstract class Model {
|
|
|
257
242
|
* properties, and coercing date fields. Shared by `updateFromData`
|
|
258
243
|
* (hydration) and `applyChanges` (local user update).
|
|
259
244
|
*
|
|
260
|
-
* Change tracking is
|
|
245
|
+
* Change tracking is explicit: for every field actually
|
|
261
246
|
* written, `onWrite(key, oldValue, newValue)` is invoked with the value
|
|
262
247
|
* captured immediately before assignment. `applyChanges` passes a hook
|
|
263
248
|
* that records the change in `modifiedProperties`; `updateFromData`
|
|
@@ -270,10 +255,10 @@ export declare abstract class Model {
|
|
|
270
255
|
* Update from raw data (hydration)
|
|
271
256
|
*
|
|
272
257
|
* Used for inbound server deltas and pool upserts. Change tracking is
|
|
273
|
-
* deliberately suppressed: hydration writes must
|
|
258
|
+
* deliberately suppressed: hydration writes must not land in
|
|
274
259
|
* `modifiedProperties`, otherwise applying a server delta would queue a
|
|
275
260
|
* brand-new outbound mutation and the record would echo forever. For a
|
|
276
|
-
*
|
|
261
|
+
* local user edit, use `applyChanges` instead.
|
|
277
262
|
*
|
|
278
263
|
* Suppression is belt-and-suspenders: we pass no `onWrite` hook AND
|
|
279
264
|
* clear/restore `modifiedProperties` around the assignment, so any
|
|
@@ -282,18 +267,18 @@ export declare abstract class Model {
|
|
|
282
267
|
*/
|
|
283
268
|
updateFromData(data: ModelData): void;
|
|
284
269
|
/**
|
|
285
|
-
* Apply a
|
|
286
|
-
* path for `proxy.update({ id, data })`, which is the
|
|
270
|
+
* Apply a local, user-initiated update from a data object — the write
|
|
271
|
+
* path for `proxy.update({ id, data })`, which is the one and only way
|
|
287
272
|
* application code mutates synced fields.
|
|
288
273
|
*
|
|
289
274
|
* Unlike `updateFromData` (hydration, untracked), this records every
|
|
290
275
|
* written field in `modifiedProperties` via `propertyChanged`, so
|
|
291
|
-
* `getChanges()`
|
|
292
|
-
* server and the undo system gets a correct pre-write baseline.
|
|
293
|
-
*
|
|
294
|
-
*
|
|
276
|
+
* `getChanges()` and the transaction queue send the edited fields to the
|
|
277
|
+
* server and the undo system gets a correct pre-write baseline. Recording
|
|
278
|
+
* is explicit here, through the `onWrite` hook, and does not rely on any
|
|
279
|
+
* MobX `observe()` side channel.
|
|
295
280
|
*
|
|
296
|
-
* `_originalData` is intentionally
|
|
281
|
+
* `_originalData` is intentionally not reset here: it stays as the
|
|
297
282
|
* last-persisted baseline until `clearChanges()` runs on sync-ack.
|
|
298
283
|
*/
|
|
299
284
|
applyChanges(data: ModelData): void;
|
|
@@ -335,7 +320,7 @@ export declare abstract class Model {
|
|
|
335
320
|
_unregisterObservedCollection(collection: Disposable): void;
|
|
336
321
|
/**
|
|
337
322
|
* Check if any collection on this model is currently being observed by React
|
|
338
|
-
* Used by
|
|
323
|
+
* Used by InstanceCache GC to prevent disposing models in active use
|
|
339
324
|
*/
|
|
340
325
|
hasObservedCollections(): boolean;
|
|
341
326
|
/**
|
|
@@ -379,8 +364,25 @@ export declare abstract class Model {
|
|
|
379
364
|
* the schema's `T` describes. Computed relations (`referenceModel`/
|
|
380
365
|
* `referenceCollection`) and ephemeral fields are skipped, matching `toJSON`'s
|
|
381
366
|
* row projection; they're lazy/recursive and not part of the row's data.
|
|
367
|
+
*
|
|
368
|
+
* Schema-derived getters (`computed:` entries and `${field}Json` getters) ARE
|
|
369
|
+
* materialized, as non-enumerable own values. The schema's inferred row type
|
|
370
|
+
* includes them, so omitting them would make every snapshot read of a computed
|
|
371
|
+
* silently `undefined` — a type-level lie. They're evaluated here, inside the
|
|
372
|
+
* caller's tracked function, so the reaction subscribes to whatever fields the
|
|
373
|
+
* getter reads. Non-enumerable keeps write-path parity with model instances:
|
|
374
|
+
* an instance's getters sit on the prototype and never enter `{...model}`
|
|
375
|
+
* spreads or `JSON.stringify`, and materialized values must not either — a
|
|
376
|
+
* spread-into-update would otherwise send computed keys to the server.
|
|
382
377
|
*/
|
|
383
378
|
toReactiveSnapshot<T = ModelData>(): T;
|
|
379
|
+
/**
|
|
380
|
+
* Names of schema-derived getters — `computed:` entries and `${field}Json`
|
|
381
|
+
* getters — that {@link toReactiveSnapshot} materializes onto snapshots.
|
|
382
|
+
* The dynamic model class built by `registerModelsFromSchema` overrides this;
|
|
383
|
+
* hand-written Model subclasses default to none.
|
|
384
|
+
*/
|
|
385
|
+
getDerivedGetterNames(): readonly string[];
|
|
384
386
|
/**
|
|
385
387
|
* Get field changes for activity tracking
|
|
386
388
|
*/
|
package/dist/Model.js
CHANGED
|
@@ -1,20 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Model
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* - Return updates/changes (not perform them)
|
|
9
|
-
*
|
|
10
|
-
* Models do NOT:
|
|
11
|
-
* - Access stores or singletons
|
|
12
|
-
* - Perform side effects (saving, notifications)
|
|
13
|
-
* - Know about sync infrastructure
|
|
2
|
+
* Model is the base class for the sync engine's domain models. A model is a
|
|
3
|
+
* plain domain object: it holds data and business logic, tracks its own
|
|
4
|
+
* property changes, and validates itself, and it returns the changes to apply
|
|
5
|
+
* rather than applying them. It does not reach into stores or singletons and
|
|
6
|
+
* does not perform side effects such as saving or sending notifications;
|
|
7
|
+
* persistence and sync are driven by the store that owns the model.
|
|
14
8
|
*/
|
|
15
9
|
import { runInAction, isComputedProp } from 'mobx';
|
|
16
10
|
import { v4 as uuid } from 'uuid';
|
|
17
|
-
import { M1 } from './utils/
|
|
11
|
+
import { M1 } from './utils/mobxSetup.js';
|
|
18
12
|
import { getActiveRegistry, hasActiveRegistry } from './ModelRegistry.js';
|
|
19
13
|
import { getContext } from './context.js';
|
|
20
14
|
import { AbloValidationError } from './errors.js';
|
|
@@ -29,10 +23,13 @@ export class ValidationError extends Error {
|
|
|
29
23
|
this.name = 'ValidationError';
|
|
30
24
|
}
|
|
31
25
|
}
|
|
26
|
+
/** Shared frozen default for {@link Model.getDerivedGetterNames}. */
|
|
27
|
+
const EMPTY_DERIVED_GETTERS = Object.freeze([]);
|
|
32
28
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
29
|
+
* The abstract base class every domain model extends. It holds the model's id
|
|
30
|
+
* and timestamps, tracks in-place property changes for change detection and
|
|
31
|
+
* undo, and serializes itself, while leaving persistence and sync to the store
|
|
32
|
+
* that owns it.
|
|
36
33
|
*/
|
|
37
34
|
export class Model {
|
|
38
35
|
/** Static reference to active SyncedStore for reactive queries */
|
|
@@ -189,27 +186,17 @@ export class Model {
|
|
|
189
186
|
return this._isNew;
|
|
190
187
|
}
|
|
191
188
|
/**
|
|
192
|
-
*
|
|
193
|
-
* load.
|
|
194
|
-
*
|
|
195
|
-
* `modifiedProperties
|
|
196
|
-
*
|
|
189
|
+
* Return a read-only view of the snapshot taken at {@link markAsPersisted}
|
|
190
|
+
* or at load time. The undo machinery uses it to recover a field's pre-edit
|
|
191
|
+
* value when the field was written without first being tracked in
|
|
192
|
+
* `modifiedProperties`. The returned object is the live snapshot, so callers
|
|
193
|
+
* must not mutate it.
|
|
197
194
|
*
|
|
198
|
-
*
|
|
199
|
-
*
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
* mutations are dropped and the mutator functions are replayed on
|
|
204
|
-
* the new basis (rebase). That makes per-instance baselines
|
|
205
|
-
* unnecessary because the b-tree at the new basis IS the
|
|
206
|
-
* authoritative pre-session state.
|
|
207
|
-
*
|
|
208
|
-
* If we ever migrate to "mutators are the only write path," this
|
|
209
|
-
* snapshot field, `_originalData`, and most of
|
|
210
|
-
* `RecordingTransaction.snapshotFields` become dead code. See
|
|
211
|
-
* `packages/replicache/src/db/rebase.ts` (rocicorp/mono) for the
|
|
212
|
-
* pattern.
|
|
195
|
+
* This per-instance baseline is needed because application code can edit a
|
|
196
|
+
* model in two ways that coexist: a direct property write
|
|
197
|
+
* (`slide.title = 'foo'`) and a recorded mutation. A design in which every
|
|
198
|
+
* write went through a single recorded path would not need it, since the
|
|
199
|
+
* last acknowledged state would already be the authoritative baseline.
|
|
213
200
|
*/
|
|
214
201
|
getOriginalSnapshot() {
|
|
215
202
|
return this._originalData;
|
|
@@ -224,7 +211,7 @@ export class Model {
|
|
|
224
211
|
});
|
|
225
212
|
}
|
|
226
213
|
/**
|
|
227
|
-
* Capture a before-image for `keys` — the
|
|
214
|
+
* Capture a before-image for `keys` — the single source of truth for the
|
|
228
215
|
* "previous value" that undo inverses are built from. Both undo paths call
|
|
229
216
|
* this so they can never drift: the stream path
|
|
230
217
|
* (`TransactionQueue.extractPreviousData`) and the manual-record path
|
|
@@ -234,10 +221,10 @@ export class Model {
|
|
|
234
221
|
* 1. `modifiedProperties.get(key).old` — first-old-wins pre-session
|
|
235
222
|
* baseline, set whenever the field was mutated in place before commit.
|
|
236
223
|
* 2. `getOriginalSnapshot()[key]` — the last loaded/acked row, the correct
|
|
237
|
-
* before-image for a key written
|
|
224
|
+
* before-image for a key written without a prior in-place mutation
|
|
238
225
|
* (e.g. a `precomputedChanges` write).
|
|
239
226
|
* 3. `fallbackToLive` only — the current live value. The manual-record path
|
|
240
|
-
* wants this last resort; the stream path deliberately
|
|
227
|
+
* wants this last resort; the stream path deliberately omits unresolved
|
|
241
228
|
* keys so `buildUndoOps` drops an un-revertible inverse rather than
|
|
242
229
|
* inventing one. The flag is the one intentional difference between the
|
|
243
230
|
* two callers — do not collapse it.
|
|
@@ -245,8 +232,8 @@ export class Model {
|
|
|
245
232
|
* `id` is always skipped. Values are read out per-key, so the
|
|
246
233
|
* `getOriginalSnapshot()` "callers must not mutate" contract is preserved.
|
|
247
234
|
*
|
|
248
|
-
* Invariant this relies on: a given undo scope is
|
|
249
|
-
* (`recordFromStream: true`)
|
|
235
|
+
* Invariant this relies on: a given undo scope is either stream-recorded
|
|
236
|
+
* (`recordFromStream: true`) or manual (`useMutators({ undoScope })`), never
|
|
250
237
|
* both — otherwise a write would be captured twice. No surface sets both.
|
|
251
238
|
*/
|
|
252
239
|
capturePreviousValues(keys, opts) {
|
|
@@ -271,7 +258,7 @@ export class Model {
|
|
|
271
258
|
}
|
|
272
259
|
/**
|
|
273
260
|
* Drop the `modifiedProperties` entries for `keys` — re-baselines a field
|
|
274
|
-
* after its `.old` has been frozen into a committed transaction, so the
|
|
261
|
+
* after its `.old` has been frozen into a committed transaction, so the next
|
|
275
262
|
* write to the same field starts from this commit's result rather than the
|
|
276
263
|
* stale pre-session `.old` that {@link propertyChanged}'s first-old-wins
|
|
277
264
|
* policy preserves. Safe because the committed transaction owns its own
|
|
@@ -362,7 +349,7 @@ export class Model {
|
|
|
362
349
|
// New model - return create operation
|
|
363
350
|
return {
|
|
364
351
|
type: 'create',
|
|
365
|
-
modelName: this.getModelName(), //
|
|
352
|
+
modelName: this.getModelName(), // the registered model name
|
|
366
353
|
modelId: this.id,
|
|
367
354
|
timestamp: new Date(),
|
|
368
355
|
};
|
|
@@ -371,7 +358,7 @@ export class Model {
|
|
|
371
358
|
// Existing model with changes - return update operation
|
|
372
359
|
return {
|
|
373
360
|
type: 'update',
|
|
374
|
-
modelName: this.getModelName(), //
|
|
361
|
+
modelName: this.getModelName(), // the registered model name
|
|
375
362
|
modelId: this.id,
|
|
376
363
|
changes: new Map(this.modifiedProperties),
|
|
377
364
|
timestamp: new Date(),
|
|
@@ -392,7 +379,7 @@ export class Model {
|
|
|
392
379
|
this.willDelete();
|
|
393
380
|
return {
|
|
394
381
|
type: 'delete',
|
|
395
|
-
modelName: this.getModelName(), //
|
|
382
|
+
modelName: this.getModelName(), // the registered model name
|
|
396
383
|
modelId: this.id,
|
|
397
384
|
timestamp: new Date(),
|
|
398
385
|
};
|
|
@@ -409,7 +396,7 @@ export class Model {
|
|
|
409
396
|
this.archivedAt = new Date();
|
|
410
397
|
return {
|
|
411
398
|
type: 'archive',
|
|
412
|
-
modelName: this.getModelName(), //
|
|
399
|
+
modelName: this.getModelName(), // the registered model name
|
|
413
400
|
modelId: this.id,
|
|
414
401
|
timestamp: new Date(),
|
|
415
402
|
};
|
|
@@ -426,7 +413,7 @@ export class Model {
|
|
|
426
413
|
this.archivedAt = null;
|
|
427
414
|
return {
|
|
428
415
|
type: 'unarchive',
|
|
429
|
-
modelName: this.getModelName(), //
|
|
416
|
+
modelName: this.getModelName(), // the registered model name
|
|
430
417
|
modelId: this.id,
|
|
431
418
|
timestamp: new Date(),
|
|
432
419
|
};
|
|
@@ -437,7 +424,7 @@ export class Model {
|
|
|
437
424
|
* properties, and coercing date fields. Shared by `updateFromData`
|
|
438
425
|
* (hydration) and `applyChanges` (local user update).
|
|
439
426
|
*
|
|
440
|
-
* Change tracking is
|
|
427
|
+
* Change tracking is explicit: for every field actually
|
|
441
428
|
* written, `onWrite(key, oldValue, newValue)` is invoked with the value
|
|
442
429
|
* captured immediately before assignment. `applyChanges` passes a hook
|
|
443
430
|
* that records the change in `modifiedProperties`; `updateFromData`
|
|
@@ -497,10 +484,10 @@ export class Model {
|
|
|
497
484
|
* Update from raw data (hydration)
|
|
498
485
|
*
|
|
499
486
|
* Used for inbound server deltas and pool upserts. Change tracking is
|
|
500
|
-
* deliberately suppressed: hydration writes must
|
|
487
|
+
* deliberately suppressed: hydration writes must not land in
|
|
501
488
|
* `modifiedProperties`, otherwise applying a server delta would queue a
|
|
502
489
|
* brand-new outbound mutation and the record would echo forever. For a
|
|
503
|
-
*
|
|
490
|
+
* local user edit, use `applyChanges` instead.
|
|
504
491
|
*
|
|
505
492
|
* Suppression is belt-and-suspenders: we pass no `onWrite` hook AND
|
|
506
493
|
* clear/restore `modifiedProperties` around the assignment, so any
|
|
@@ -527,18 +514,18 @@ export class Model {
|
|
|
527
514
|
this.didUpdate();
|
|
528
515
|
}
|
|
529
516
|
/**
|
|
530
|
-
* Apply a
|
|
531
|
-
* path for `proxy.update({ id, data })`, which is the
|
|
517
|
+
* Apply a local, user-initiated update from a data object — the write
|
|
518
|
+
* path for `proxy.update({ id, data })`, which is the one and only way
|
|
532
519
|
* application code mutates synced fields.
|
|
533
520
|
*
|
|
534
521
|
* Unlike `updateFromData` (hydration, untracked), this records every
|
|
535
522
|
* written field in `modifiedProperties` via `propertyChanged`, so
|
|
536
|
-
* `getChanges()`
|
|
537
|
-
* server and the undo system gets a correct pre-write baseline.
|
|
538
|
-
*
|
|
539
|
-
*
|
|
523
|
+
* `getChanges()` and the transaction queue send the edited fields to the
|
|
524
|
+
* server and the undo system gets a correct pre-write baseline. Recording
|
|
525
|
+
* is explicit here, through the `onWrite` hook, and does not rely on any
|
|
526
|
+
* MobX `observe()` side channel.
|
|
540
527
|
*
|
|
541
|
-
* `_originalData` is intentionally
|
|
528
|
+
* `_originalData` is intentionally not reset here: it stays as the
|
|
542
529
|
* last-persisted baseline until `clearChanges()` runs on sync-ack.
|
|
543
530
|
*/
|
|
544
531
|
applyChanges(data) {
|
|
@@ -564,8 +551,8 @@ export class Model {
|
|
|
564
551
|
const modelName = this.getModelName();
|
|
565
552
|
const properties = getActiveRegistry().getProperties(modelName);
|
|
566
553
|
const result = {
|
|
567
|
-
__class: this.getModelName(), //
|
|
568
|
-
__typename: this.getModelName(), //
|
|
554
|
+
__class: this.getModelName(), // the registered model name for consistency
|
|
555
|
+
__typename: this.getModelName(), // __typename mirrors __class as the wire type discriminator
|
|
569
556
|
id: this.id,
|
|
570
557
|
createdAt: this.createdAt?.toISOString(),
|
|
571
558
|
updatedAt: this.updatedAt?.toISOString(),
|
|
@@ -656,7 +643,7 @@ export class Model {
|
|
|
656
643
|
}
|
|
657
644
|
/**
|
|
658
645
|
* Check if any collection on this model is currently being observed by React
|
|
659
|
-
* Used by
|
|
646
|
+
* Used by InstanceCache GC to prevent disposing models in active use
|
|
660
647
|
*/
|
|
661
648
|
hasObservedCollections() {
|
|
662
649
|
return this._observedCollections.size > 0;
|
|
@@ -749,6 +736,16 @@ export class Model {
|
|
|
749
736
|
* the schema's `T` describes. Computed relations (`referenceModel`/
|
|
750
737
|
* `referenceCollection`) and ephemeral fields are skipped, matching `toJSON`'s
|
|
751
738
|
* row projection; they're lazy/recursive and not part of the row's data.
|
|
739
|
+
*
|
|
740
|
+
* Schema-derived getters (`computed:` entries and `${field}Json` getters) ARE
|
|
741
|
+
* materialized, as non-enumerable own values. The schema's inferred row type
|
|
742
|
+
* includes them, so omitting them would make every snapshot read of a computed
|
|
743
|
+
* silently `undefined` — a type-level lie. They're evaluated here, inside the
|
|
744
|
+
* caller's tracked function, so the reaction subscribes to whatever fields the
|
|
745
|
+
* getter reads. Non-enumerable keeps write-path parity with model instances:
|
|
746
|
+
* an instance's getters sit on the prototype and never enter `{...model}`
|
|
747
|
+
* spreads or `JSON.stringify`, and materialized values must not either — a
|
|
748
|
+
* spread-into-update would otherwise send computed keys to the server.
|
|
752
749
|
*/
|
|
753
750
|
toReactiveSnapshot() {
|
|
754
751
|
const snapshot = {
|
|
@@ -759,8 +756,8 @@ export class Model {
|
|
|
759
756
|
if (this.archivedAt !== undefined)
|
|
760
757
|
snapshot.archivedAt = this.archivedAt;
|
|
761
758
|
const properties = getActiveRegistry().getProperties(this.getModelName());
|
|
759
|
+
const self = this;
|
|
762
760
|
if (properties) {
|
|
763
|
-
const self = this;
|
|
764
761
|
for (const [propName, metadata] of properties) {
|
|
765
762
|
if (metadata.type === 'ephemeralProperty' ||
|
|
766
763
|
metadata.type === 'referenceModel' ||
|
|
@@ -772,8 +769,27 @@ export class Model {
|
|
|
772
769
|
snapshot[propName] = self[propName];
|
|
773
770
|
}
|
|
774
771
|
}
|
|
772
|
+
for (const name of this.getDerivedGetterNames()) {
|
|
773
|
+
Object.defineProperty(snapshot, name, {
|
|
774
|
+
// Evaluated on the model instance so `${field}Json` caches stay on it
|
|
775
|
+
// and the enclosing reaction tracks the fields the getter reads.
|
|
776
|
+
value: self[name],
|
|
777
|
+
enumerable: false,
|
|
778
|
+
configurable: true,
|
|
779
|
+
writable: false,
|
|
780
|
+
});
|
|
781
|
+
}
|
|
775
782
|
return snapshot;
|
|
776
783
|
}
|
|
784
|
+
/**
|
|
785
|
+
* Names of schema-derived getters — `computed:` entries and `${field}Json`
|
|
786
|
+
* getters — that {@link toReactiveSnapshot} materializes onto snapshots.
|
|
787
|
+
* The dynamic model class built by `registerModelsFromSchema` overrides this;
|
|
788
|
+
* hand-written Model subclasses default to none.
|
|
789
|
+
*/
|
|
790
|
+
getDerivedGetterNames() {
|
|
791
|
+
return EMPTY_DERIVED_GETTERS;
|
|
792
|
+
}
|
|
777
793
|
/**
|
|
778
794
|
* Get field changes for activity tracking
|
|
779
795
|
*/
|
|
@@ -813,7 +829,7 @@ export class Model {
|
|
|
813
829
|
}
|
|
814
830
|
// Try to get model class by identifier
|
|
815
831
|
let ModelClass = getActiveRegistry().getModelByName(modelIdentifier);
|
|
816
|
-
// If not found
|
|
832
|
+
// If not found by registered name, try mapping to the class name
|
|
817
833
|
if (!ModelClass) {
|
|
818
834
|
const classNameMap = {
|
|
819
835
|
Task: 'TaskModel',
|
package/dist/ModelRegistry.d.ts
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* ModelRegistry
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* - Comprehensive error reporting
|
|
10
|
-
* - Best practices from Linear Sync Engine
|
|
2
|
+
* ModelRegistry is the source of truth for model metadata: which model classes
|
|
3
|
+
* exist, the properties and references declared on each, the back-references
|
|
4
|
+
* used for cascade handling, and a stable hash of the whole schema.
|
|
5
|
+
* {@link Model} instances resolve their metadata through the active registry,
|
|
6
|
+
* and {@link InstanceCache} uses it to map between model names and constructor
|
|
7
|
+
* classes. References resolve lazily, so a model may declare a reference to
|
|
8
|
+
* another model that is registered later.
|
|
11
9
|
*/
|
|
12
10
|
import { type ModelMetadata, type PropertyMetadata, type ReferenceMetadata, LoadStrategy } from './types/index.js';
|
|
13
11
|
import type { Model } from './Model.js';
|
|
@@ -30,7 +28,8 @@ export type ModelClassInput = new (...args: never[]) => Model;
|
|
|
30
28
|
*/
|
|
31
29
|
export type RegisteredModelClass = Omit<typeof Model, never> & ConcreteModelConstructor<Model>;
|
|
32
30
|
/**
|
|
33
|
-
*
|
|
31
|
+
* {@link ReferenceMetadata} extended with cascade behavior: what happens to a
|
|
32
|
+
* referencing model when the referenced model is deleted or archived.
|
|
34
33
|
*/
|
|
35
34
|
export interface ExtendedReferenceMetadata extends ReferenceMetadata {
|
|
36
35
|
onDelete?: 'cascade' | 'nullify' | 'restrict';
|
|
@@ -47,8 +46,9 @@ export interface SerializedReferenceMetadata extends Omit<ExtendedReferenceMetad
|
|
|
47
46
|
referencedModel: string;
|
|
48
47
|
}
|
|
49
48
|
/**
|
|
50
|
-
*
|
|
51
|
-
*
|
|
49
|
+
* Metadata that records a child model's foreign key to a parent model, used
|
|
50
|
+
* for cascade-aware transaction handling: when the parent is deleted, the
|
|
51
|
+
* child's pending transactions can be cancelled.
|
|
52
52
|
*/
|
|
53
53
|
export interface BackReferenceMetadata {
|
|
54
54
|
/** The parent model name (e.g., 'SlideDeck') */
|
|
@@ -81,7 +81,6 @@ export declare class ModelRegistry {
|
|
|
81
81
|
private schemaHash?;
|
|
82
82
|
private config;
|
|
83
83
|
private registeredModels;
|
|
84
|
-
private batchMode;
|
|
85
84
|
private pendingHashUpdate;
|
|
86
85
|
constructor(config?: RegistryConfig);
|
|
87
86
|
private validateModelConstructor;
|
|
@@ -102,13 +101,14 @@ export declare class ModelRegistry {
|
|
|
102
101
|
*/
|
|
103
102
|
registerReference(modelName: string, propertyName: string, metadata: ExtendedReferenceMetadata): void;
|
|
104
103
|
/**
|
|
105
|
-
*
|
|
104
|
+
* Register a back-reference for cascade-aware transaction handling.
|
|
106
105
|
*
|
|
107
|
-
* When a parent model is deleted, the
|
|
108
|
-
* transactions for
|
|
106
|
+
* When a parent model is deleted, the transaction queue cancels pending
|
|
107
|
+
* transactions for every child model that declares a back-reference to that
|
|
108
|
+
* parent.
|
|
109
109
|
*
|
|
110
|
-
* @param childModelName - The model that
|
|
111
|
-
* @param metadata -
|
|
110
|
+
* @param childModelName - The model that holds a foreign key to the parent (e.g., 'Slide')
|
|
111
|
+
* @param metadata - The back-reference configuration
|
|
112
112
|
*/
|
|
113
113
|
registerBackReference(childModelName: string, metadata: BackReferenceMetadata): void;
|
|
114
114
|
/** Get all models with specific load strategy. */
|
|
@@ -141,7 +141,9 @@ export declare class ModelRegistry {
|
|
|
141
141
|
foreignKey: string;
|
|
142
142
|
}[];
|
|
143
143
|
/**
|
|
144
|
-
*
|
|
144
|
+
* Compute a stable hash of the registered schema — model names, property
|
|
145
|
+
* types, and their indexed and optional flags. Memoized until the schema
|
|
146
|
+
* changes.
|
|
145
147
|
*/
|
|
146
148
|
getSchemaHash(): string;
|
|
147
149
|
/**
|