@abloatai/ablo 0.25.0 → 0.27.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/AGENTS.md +5 -3
- package/CHANGELOG.md +34 -0
- package/README.md +104 -88
- package/dist/BaseSyncedStore.d.ts +140 -266
- package/dist/BaseSyncedStore.js +338 -739
- package/dist/Database.d.ts +62 -77
- package/dist/Database.js +106 -127
- package/dist/{ObjectPool.d.ts → InstanceCache.d.ts} +10 -13
- package/dist/{ObjectPool.js → InstanceCache.js} +91 -83
- package/dist/LazyReferenceCollection.d.ts +11 -15
- package/dist/LazyReferenceCollection.js +16 -15
- package/dist/Model.d.ts +37 -52
- package/dist/Model.js +52 -69
- package/dist/ModelRegistry.d.ts +46 -25
- package/dist/ModelRegistry.js +32 -30
- package/dist/NetworkMonitor.d.ts +5 -6
- package/dist/NetworkMonitor.js +6 -7
- package/dist/SyncClient.d.ts +119 -109
- package/dist/SyncClient.js +303 -224
- package/dist/SyncEngineContext.d.ts +1 -3
- package/dist/SyncEngineContext.js +1 -2
- package/dist/adapters/alwaysOnline.d.ts +6 -8
- package/dist/adapters/alwaysOnline.js +6 -8
- package/dist/adapters/inMemoryStorage.d.ts +9 -9
- package/dist/adapters/inMemoryStorage.js +9 -9
- package/dist/agent/Agent.d.ts +39 -31
- package/dist/agent/Agent.js +35 -23
- 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} +30 -31
- package/dist/ai-sdk/index.d.ts +25 -22
- package/dist/ai-sdk/index.js +25 -22
- package/dist/ai-sdk/wrap.d.ts +7 -8
- package/dist/ai-sdk/wrap.js +2 -2
- package/dist/auth/credentialPolicy.d.ts +74 -71
- package/dist/auth/credentialPolicy.js +51 -56
- package/dist/auth/credentialSource.d.ts +7 -18
- package/dist/auth/credentialSource.js +10 -18
- package/dist/auth/index.d.ts +59 -58
- package/dist/auth/index.js +34 -40
- 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 +483 -369
- package/dist/client/Ablo.d.ts +107 -836
- package/dist/client/Ablo.js +174 -833
- package/dist/client/ApiClient.d.ts +44 -20
- package/dist/client/ApiClient.js +193 -44
- package/dist/client/auth.d.ts +51 -60
- package/dist/client/auth.js +137 -110
- package/dist/client/claimHeartbeatLoop.d.ts +50 -0
- package/dist/client/claimHeartbeatLoop.js +88 -0
- package/dist/client/consoleLogger.d.ts +35 -0
- package/dist/client/consoleLogger.js +44 -0
- package/dist/client/createInternalComponents.d.ts +14 -17
- package/dist/client/createInternalComponents.js +26 -31
- package/dist/client/createModelProxy.d.ts +130 -120
- package/dist/client/createModelProxy.js +158 -124
- package/dist/client/credentialEndpoint.d.ts +61 -0
- package/dist/client/credentialEndpoint.js +86 -0
- package/dist/client/functionalUpdate.d.ts +29 -27
- package/dist/client/functionalUpdate.js +21 -21
- package/dist/client/hostedEndpoints.d.ts +21 -0
- package/dist/client/hostedEndpoints.js +21 -0
- package/dist/client/httpClient.d.ts +58 -54
- package/dist/client/httpClient.js +29 -31
- package/dist/client/identity.d.ts +15 -20
- package/dist/client/identity.js +49 -59
- package/dist/client/modelRegistration.d.ts +10 -0
- package/dist/client/modelRegistration.js +301 -0
- package/dist/client/options.d.ts +373 -0
- package/dist/client/options.js +6 -0
- package/dist/client/registerDataSource.d.ts +9 -9
- package/dist/client/registerDataSource.js +15 -16
- package/dist/client/resourceTypes.d.ts +333 -0
- package/dist/client/resourceTypes.js +7 -0
- package/dist/client/schemaConfig.d.ts +44 -0
- package/dist/client/schemaConfig.js +176 -0
- package/dist/client/sessionMint.d.ts +17 -13
- package/dist/client/sessionMint.js +26 -31
- package/dist/client/validateAbloOptions.d.ts +12 -14
- package/dist/client/validateAbloOptions.js +9 -10
- package/dist/client/writeOptionsSchema.d.ts +18 -16
- package/dist/client/writeOptionsSchema.js +23 -20
- package/dist/client/wsMutationExecutor.d.ts +28 -0
- package/dist/client/wsMutationExecutor.js +71 -0
- package/dist/context.d.ts +6 -4
- package/dist/context.js +6 -7
- package/dist/coordination/index.d.ts +13 -4
- package/dist/coordination/index.js +29 -4
- package/dist/coordination/schema.d.ts +176 -128
- package/dist/coordination/schema.js +197 -133
- package/dist/coordination/trace.d.ts +9 -11
- package/dist/coordination/trace.js +13 -15
- package/dist/core/DatabaseManager.d.ts +5 -8
- package/dist/core/DatabaseManager.js +38 -40
- package/dist/core/QueryProcessor.d.ts +7 -9
- package/dist/core/QueryProcessor.js +27 -34
- package/dist/core/QueryView.d.ts +17 -5
- package/dist/core/QueryView.js +6 -7
- package/dist/core/StoreManager.d.ts +14 -16
- package/dist/core/StoreManager.js +26 -25
- package/dist/core/ViewRegistry.d.ts +5 -5
- package/dist/core/ViewRegistry.js +4 -4
- package/dist/core/index.d.ts +18 -13
- package/dist/core/index.js +32 -26
- package/dist/core/openIDBWithTimeout.d.ts +38 -36
- package/dist/core/openIDBWithTimeout.js +57 -54
- package/dist/core/queryUtils.d.ts +45 -0
- package/dist/core/queryUtils.js +69 -0
- package/dist/core/storeContract.d.ts +145 -0
- package/dist/core/storeContract.js +12 -0
- package/dist/environment.d.ts +28 -0
- package/dist/environment.js +21 -0
- package/dist/errorCodes.d.ts +118 -101
- package/dist/errorCodes.js +277 -260
- package/dist/errors.d.ts +170 -165
- package/dist/errors.js +161 -151
- package/dist/index.d.ts +30 -27
- package/dist/index.js +90 -82
- package/dist/interfaces/index.d.ts +108 -133
- package/dist/interfaces/index.js +5 -4
- package/dist/keys/index.d.ts +27 -29
- package/dist/keys/index.js +59 -49
- 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 +122 -131
- package/dist/mutators/UndoManager.js +149 -155
- package/dist/mutators/defineMutators.d.ts +24 -37
- 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 +105 -101
- package/dist/policy/types.js +67 -66
- package/dist/query/client.d.ts +32 -16
- package/dist/query/client.js +103 -72
- package/dist/query/types.d.ts +37 -60
- package/dist/query/types.js +13 -33
- package/dist/react/AbloProvider.d.ts +7 -11
- package/dist/react/AbloProvider.js +24 -17
- package/dist/react/context.d.ts +27 -146
- 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 +23 -22
- package/dist/react/useAblo.js +17 -15
- 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 +11 -12
- package/dist/react/useMutationFailureListener.d.ts +8 -8
- package/dist/react/useMutationFailureListener.js +9 -9
- package/dist/react/useMutators.d.ts +11 -11
- package/dist/react/useMutators.js +10 -4
- package/dist/react/useReactive.js +2 -3
- package/dist/react/useSyncStatus.d.ts +4 -6
- package/dist/react/useUndoScope.d.ts +7 -9
- package/dist/react/useUndoScope.js +3 -3
- 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 +35 -0
- package/dist/schema/ddlLock.js +46 -0
- 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 +36 -49
- package/dist/schema/generate.d.ts +12 -12
- package/dist/schema/generate.js +12 -12
- package/dist/schema/index.d.ts +5 -4
- package/dist/schema/index.js +29 -21
- package/dist/schema/model.d.ts +121 -146
- package/dist/schema/model.js +24 -35
- package/dist/schema/openapi.d.ts +10 -9
- package/dist/schema/openapi.js +7 -1
- package/dist/schema/queries.d.ts +30 -32
- package/dist/schema/queries.js +24 -25
- package/dist/schema/relation.d.ts +89 -99
- package/dist/schema/relation.js +13 -13
- package/dist/schema/residency.d.ts +38 -0
- package/dist/schema/residency.js +30 -0
- package/dist/schema/roles.d.ts +45 -27
- package/dist/schema/roles.js +52 -21
- package/dist/schema/schema.d.ts +36 -45
- package/dist/schema/schema.js +42 -39
- package/dist/schema/select.d.ts +13 -13
- package/dist/schema/select.js +13 -13
- package/dist/schema/serialize.d.ts +36 -39
- 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} +27 -50
- 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 +31 -26
- package/dist/source/adapter.js +10 -10
- package/dist/source/adapters/drizzle.d.ts +28 -23
- package/dist/source/adapters/drizzle.js +34 -28
- package/dist/source/adapters/kysely.d.ts +27 -25
- package/dist/source/adapters/kysely.js +28 -26
- package/dist/source/adapters/memory.d.ts +8 -7
- package/dist/source/adapters/memory.js +10 -9
- package/dist/source/adapters/prisma.d.ts +13 -12
- package/dist/source/adapters/prisma.js +27 -29
- package/dist/source/conformance.d.ts +18 -11
- package/dist/source/conformance.js +27 -19
- package/dist/source/connector.d.ts +31 -32
- package/dist/source/connector.js +30 -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 +94 -0
- package/dist/source/factory.js +268 -0
- package/dist/source/index.d.ts +10 -462
- package/dist/source/index.js +17 -421
- package/dist/source/migrations.d.ts +9 -9
- package/dist/source/migrations.js +9 -9
- package/dist/source/next.d.ts +10 -11
- package/dist/source/next.js +7 -8
- package/dist/source/pushQueue.d.ts +70 -48
- package/dist/source/pushQueue.js +36 -29
- package/dist/source/signing.d.ts +88 -0
- package/dist/source/signing.js +159 -0
- package/dist/source/types.d.ts +351 -0
- package/dist/source/types.js +43 -0
- package/dist/stores/ObjectStore.d.ts +11 -12
- package/dist/stores/ObjectStore.js +34 -35
- package/dist/stores/ObjectStoreContract.d.ts +12 -15
- package/dist/stores/SyncActionStore.d.ts +8 -12
- package/dist/stores/SyncActionStore.js +77 -46
- package/dist/surface.d.ts +28 -21
- package/dist/surface.js +28 -20
- package/dist/sync/{BootstrapHelper.d.ts → BootstrapFetcher.d.ts} +37 -45
- package/dist/sync/{BootstrapHelper.js → BootstrapFetcher.js} +101 -80
- package/dist/sync/ConnectionManager.d.ts +47 -50
- package/dist/sync/ConnectionManager.js +74 -70
- package/dist/sync/NetworkProbe.d.ts +27 -31
- package/dist/sync/NetworkProbe.js +67 -72
- package/dist/sync/{HydrationCoordinator.d.ts → OnDemandLoader.d.ts} +49 -36
- package/dist/sync/{HydrationCoordinator.js → OnDemandLoader.js} +79 -54
- package/dist/sync/{AreaOfInterestManager.d.ts → SubscriptionManager.d.ts} +45 -59
- package/dist/sync/{AreaOfInterestManager.js → SubscriptionManager.js} +44 -52
- package/dist/sync/SyncWebSocket.d.ts +175 -250
- package/dist/sync/SyncWebSocket.js +431 -769
- package/dist/sync/awaitClaimGrant.d.ts +18 -18
- package/dist/sync/awaitClaimGrant.js +38 -30
- package/dist/sync/bootstrapApply.d.ts +70 -0
- package/dist/sync/bootstrapApply.js +73 -0
- package/dist/sync/commitFrames.d.ts +44 -0
- package/dist/sync/commitFrames.js +94 -0
- package/dist/sync/createClaimStream.d.ts +23 -22
- package/dist/sync/createClaimStream.js +108 -25
- package/dist/sync/createPresenceStream.d.ts +19 -18
- package/dist/sync/createPresenceStream.js +25 -26
- package/dist/sync/createSnapshot.d.ts +13 -17
- package/dist/sync/createSnapshot.js +20 -26
- package/dist/sync/credentialLifecycle.d.ts +175 -0
- package/dist/sync/credentialLifecycle.js +322 -0
- package/dist/sync/deltaPipeline.d.ts +113 -0
- package/dist/sync/deltaPipeline.js +261 -0
- package/dist/sync/groupChange.d.ts +113 -0
- package/dist/sync/groupChange.js +242 -0
- package/dist/sync/heartbeat.d.ts +63 -0
- package/dist/sync/heartbeat.js +91 -0
- package/dist/sync/participants.d.ts +27 -27
- package/dist/sync/schemas.d.ts +3 -2
- package/dist/sync/schemas.js +14 -10
- package/dist/sync/syncCursor.d.ts +40 -0
- package/dist/sync/syncCursor.js +55 -0
- package/dist/sync/syncPlan.d.ts +54 -0
- package/dist/sync/syncPlan.js +50 -0
- package/dist/sync/syncPosition.d.ts +54 -49
- package/dist/sync/syncPosition.js +57 -52
- package/dist/sync/wsFrameHandlers.d.ts +116 -0
- package/dist/sync/wsFrameHandlers.js +374 -0
- package/dist/testing/fixtures/bootstrap.d.ts +21 -17
- package/dist/testing/fixtures/bootstrap.js +12 -6
- package/dist/testing/fixtures/deltas.d.ts +31 -34
- package/dist/testing/fixtures/deltas.js +30 -33
- package/dist/testing/fixtures/models.d.ts +11 -10
- package/dist/testing/fixtures/models.js +12 -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 -18
- package/dist/testing/helpers/{sync-engine-harness.js → syncEngineHarness.js} +14 -11
- package/dist/testing/helpers/wait.d.ts +13 -8
- package/dist/testing/helpers/wait.js +13 -8
- package/dist/testing/index.d.ts +4 -4
- package/dist/testing/index.js +3 -3
- 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 +21 -34
- package/dist/testing/mocks/MockSyncContext.js +16 -45
- package/dist/testing/mocks/MockSyncStore.d.ts +14 -14
- package/dist/testing/mocks/MockSyncStore.js +11 -11
- package/dist/testing/mocks/MockWebSocket.d.ts +28 -24
- package/dist/testing/mocks/MockWebSocket.js +22 -21
- package/dist/transactions/TransactionQueue.d.ts +190 -221
- package/dist/transactions/TransactionQueue.js +424 -822
- package/dist/transactions/TransactionStore.d.ts +20 -0
- package/dist/transactions/TransactionStore.js +53 -0
- package/dist/transactions/UnconfirmedWrites.d.ts +82 -0
- package/dist/transactions/UnconfirmedWrites.js +104 -0
- package/dist/transactions/coalesceRules.d.ts +58 -0
- package/dist/transactions/coalesceRules.js +140 -0
- package/dist/transactions/commitPayload.d.ts +130 -0
- package/dist/transactions/commitPayload.js +143 -0
- package/dist/transactions/deltaConfirmation.d.ts +58 -0
- package/dist/transactions/deltaConfirmation.js +215 -0
- package/dist/transactions/optimisticApply.d.ts +49 -0
- package/dist/transactions/optimisticApply.js +65 -0
- package/dist/transactions/replayValidation.d.ts +99 -0
- package/dist/transactions/replayValidation.js +111 -0
- package/dist/types/global.d.ts +46 -41
- package/dist/types/global.js +20 -19
- package/dist/types/index.d.ts +74 -80
- package/dist/types/index.js +22 -27
- package/dist/types/modelData.d.ts +10 -0
- package/dist/types/modelData.js +9 -0
- package/dist/types/participant.d.ts +20 -0
- package/dist/types/participant.js +10 -0
- package/dist/types/streams.d.ts +216 -209
- 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} +44 -100
- 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/{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 +35 -27
- package/dist/wire/errorEnvelope.js +38 -32
- package/dist/wire/frames.d.ts +150 -67
- package/dist/wire/frames.js +48 -1
- package/dist/wire/index.d.ts +18 -13
- package/dist/wire/index.js +36 -13
- package/dist/wire/listEnvelope.d.ts +16 -23
- package/dist/wire/listEnvelope.js +7 -6
- package/dist/wire/protocol.d.ts +38 -0
- package/dist/wire/protocol.js +38 -0
- package/dist/wire/protocolVersion.d.ts +60 -0
- package/dist/wire/protocolVersion.js +67 -0
- package/docs/api-keys.md +4 -3
- package/docs/coordination.md +59 -0
- package/docs/examples/existing-python-backend.md +3 -3
- package/docs/identity.md +4 -4
- package/docs/integration-guide.md +1 -1
- package/docs/react.md +1 -1
- package/docs/sessions.md +5 -7
- package/package.json +24 -21
- package/dist/ai-sdk/coordinated-tool.d.ts +0 -101
- package/dist/ai-sdk/coordination-context.d.ts +0 -52
- package/dist/client/index.d.ts +0 -36
- package/dist/client/index.js +0 -33
- package/dist/config/index.d.ts +0 -10
- package/dist/config/index.js +0 -12
- package/dist/core/query-utils.d.ts +0 -34
- package/dist/core/query-utils.js +0 -59
- package/dist/interfaces/headless.d.ts +0 -95
- package/dist/interfaces/headless.js +0 -41
- package/dist/query/index.d.ts +0 -6
- package/dist/query/index.js +0 -5
- package/dist/realtime/index.d.ts +0 -10
- package/dist/realtime/index.js +0 -9
- package/dist/schema/plane.d.ts +0 -23
- package/dist/schema/plane.js +0 -19
- package/dist/schema/sync-delta-row.js +0 -103
- package/dist/schema/sync-delta-wire.js +0 -102
- package/dist/server/next.d.ts +0 -51
- package/dist/server/next.js +0 -47
- 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 -1
- package/dist/server/storage-mode.js +0 -18
- package/dist/source/connector-protocol.d.ts +0 -159
- package/dist/source/connector-protocol.js +0 -161
- package/dist/sync/OfflineFlush.d.ts +0 -9
- package/dist/sync/OfflineFlush.js +0 -22
- package/dist/sync/OfflineTransactionStore.d.ts +0 -37
- package/dist/sync/OfflineTransactionStore.js +0 -263
- package/dist/transactions/OptimisticEchoTracker.d.ts +0 -82
- package/dist/transactions/OptimisticEchoTracker.js +0 -104
- package/dist/transactions/index.d.ts +0 -16
- package/dist/transactions/index.js +0 -7
- package/dist/transactions/mutation-error-handler.d.ts +0 -5
- package/dist/transactions/mutation-error-handler.js +0 -39
- package/dist/utils/mobx-setup.d.ts +0 -42
package/dist/schema/roles.d.ts
CHANGED
|
@@ -36,34 +36,35 @@ export type SyncGroup = z.infer<typeof syncGroupSchema>;
|
|
|
36
36
|
*/
|
|
37
37
|
export declare function syncGroup(kind: string, id: string): SyncGroup;
|
|
38
38
|
/**
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* (`` `org:${orgId}` `` checks without importing the constructor), or the
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* zero-fan-out ghost made flesh).
|
|
39
|
+
* The caller-facing input form of a sync group. Accepts a {@link SyncGroup}
|
|
40
|
+
* from the constructor, a template literal of the right shape
|
|
41
|
+
* (`` `org:${orgId}` `` type-checks without importing the constructor), or the
|
|
42
|
+
* reserved `'default'` anchor. A plain string with no colon is a compile error,
|
|
43
|
+
* because it would match no group and silently subscribe to nothing.
|
|
45
44
|
*/
|
|
46
45
|
export type SyncGroupInput = SyncGroup | `${string}:${string}` | 'default';
|
|
47
46
|
/**
|
|
48
|
-
* Runtime
|
|
49
|
-
*
|
|
50
|
-
* rejected
|
|
51
|
-
* subscribed
|
|
47
|
+
* Runtime validation for {@link SyncGroupInput}, used wherever a group crosses a
|
|
48
|
+
* trust boundary such as minting a capability or an ephemeral key. A malformed
|
|
49
|
+
* group is rejected with `invalid_sync_group` rather than stored and left
|
|
50
|
+
* silently subscribed to nothing.
|
|
52
51
|
*/
|
|
53
52
|
export declare const syncGroupInputSchema: z.ZodUnion<readonly [z.ZodLiteral<"default">, z.core.$ZodBranded<z.ZodTemplateLiteral<`${string}:${string}`>, "SyncGroup", "out">]>;
|
|
54
53
|
/** Runtime guard matching {@link SyncGroupInput}. */
|
|
55
54
|
export declare function isSyncGroupInput(value: unknown): value is SyncGroupInput;
|
|
56
55
|
/**
|
|
57
|
-
* The sync-group kinds the
|
|
58
|
-
*
|
|
56
|
+
* The sync-group kinds the authentication provider mints directly onto an
|
|
57
|
+
* identity. This is a fixed vocabulary: add to this list rather than write a
|
|
58
|
+
* new namespace string inline.
|
|
59
59
|
*
|
|
60
60
|
* - `org:<organizationId>` — every member of the organization
|
|
61
61
|
* - `user:<participantId>` — the participant itself
|
|
62
|
-
* - `project:<projectId>` — every credential scoped to the project
|
|
63
|
-
*
|
|
62
|
+
* - `project:<projectId>` — every credential scoped to the project; the
|
|
63
|
+
* organization's default project shares the organization's id
|
|
64
64
|
*
|
|
65
|
-
* Schema-declared roles ({@link identityRole}
|
|
66
|
-
* vocabulary per
|
|
65
|
+
* Schema-declared roles ({@link identityRole} and {@link entityRole}) extend
|
|
66
|
+
* this vocabulary per application; the kinds here are the ones the engine
|
|
67
|
+
* reserves.
|
|
67
68
|
*/
|
|
68
69
|
export declare const IDENTITY_ANCHOR_KINDS: readonly ["org", "user", "project"];
|
|
69
70
|
export type IdentityAnchorKind = (typeof IDENTITY_ANCHOR_KINDS)[number];
|
|
@@ -138,20 +139,17 @@ export declare const grantsRefSchema: z.ZodObject<{
|
|
|
138
139
|
scope: z.ZodString;
|
|
139
140
|
}, z.core.$strip>;
|
|
140
141
|
/**
|
|
141
|
-
* The
|
|
142
|
-
* option. One
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
* decides who may *read* a row, `groups` decides which delta *channels* a row
|
|
142
|
+
* The authoring form of a model's sync-group routing — the `groups: { ... }`
|
|
143
|
+
* option. One object collects the three independent routing controls. This is a
|
|
144
|
+
* separate concern from `policy`, which governs tenant isolation: `policy`
|
|
145
|
+
* decides who may read a row, while `groups` decides which change channels a row
|
|
146
146
|
* fans into.
|
|
147
147
|
*
|
|
148
|
-
* - `root` —
|
|
149
|
-
* (kind defaults
|
|
150
|
-
* `root` so it no longer collides with the (now removed) `scopedVia` tenancy
|
|
151
|
-
* sugar or the inner `grants.scope` relation name.
|
|
148
|
+
* - `root` — marks this model a scope root, so its records form the group
|
|
149
|
+
* `<kind>:<id>` (the kind defaults to the typename).
|
|
152
150
|
* - `grants` — a membership edge granting an identity access to a scope root.
|
|
153
|
-
* - `roles` —
|
|
154
|
-
*
|
|
151
|
+
* - `roles` — record-to-group roles keyed on a plain field rather than a
|
|
152
|
+
* relation, such as inbox fan-out. Accepts a single role or an array.
|
|
155
153
|
*/
|
|
156
154
|
export declare const groupsInputSchema: z.ZodObject<{
|
|
157
155
|
root: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>;
|
|
@@ -229,3 +227,23 @@ export declare function composeIdentitySyncGroups(identity: IdentityContext, sch
|
|
|
229
227
|
export declare function composeEntitySyncGroups(record: EntityContext, def: {
|
|
230
228
|
readonly entityRoles?: readonly EntityRole[];
|
|
231
229
|
}): readonly SyncGroup[];
|
|
230
|
+
/**
|
|
231
|
+
* Narrow a client's requested sync-group set to the groups it is actually
|
|
232
|
+
* allowed to subscribe to. This helper is fully generic — it never inspects the
|
|
233
|
+
* group strings — so it lives beside the composition helpers above.
|
|
234
|
+
*
|
|
235
|
+
* Behaviour:
|
|
236
|
+
* - If the client requested no groups, return the full identity-derived set,
|
|
237
|
+
* which is this participant's default subscription scope.
|
|
238
|
+
* - If the client requested some groups, keep only those that appear in the
|
|
239
|
+
* identity-derived allowed set and drop the rest, reporting the dropped
|
|
240
|
+
* groups through the optional `logDropped` callback.
|
|
241
|
+
* - If nothing survives the filter, fall back to the full allowed set rather
|
|
242
|
+
* than return `[]`, which would otherwise collapse to the server-side
|
|
243
|
+
* `'default'` fallback and deliver no changes at all.
|
|
244
|
+
*/
|
|
245
|
+
export declare function intersectRequestedWithAllowed(args: {
|
|
246
|
+
readonly requested: readonly string[];
|
|
247
|
+
readonly allowed: readonly string[];
|
|
248
|
+
readonly logDropped?: (dropped: readonly string[]) => void;
|
|
249
|
+
}): readonly string[];
|
package/dist/schema/roles.js
CHANGED
|
@@ -40,10 +40,10 @@ export function syncGroup(kind, id) {
|
|
|
40
40
|
return `${kind}:${id}`;
|
|
41
41
|
}
|
|
42
42
|
/**
|
|
43
|
-
* Runtime
|
|
44
|
-
*
|
|
45
|
-
* rejected
|
|
46
|
-
* subscribed
|
|
43
|
+
* Runtime validation for {@link SyncGroupInput}, used wherever a group crosses a
|
|
44
|
+
* trust boundary such as minting a capability or an ephemeral key. A malformed
|
|
45
|
+
* group is rejected with `invalid_sync_group` rather than stored and left
|
|
46
|
+
* silently subscribed to nothing.
|
|
47
47
|
*/
|
|
48
48
|
export const syncGroupInputSchema = z.union([z.literal('default'), syncGroupSchema]);
|
|
49
49
|
/** Runtime guard matching {@link SyncGroupInput}. */
|
|
@@ -52,16 +52,18 @@ export function isSyncGroupInput(value) {
|
|
|
52
52
|
}
|
|
53
53
|
// ── Identity anchors (closed vocabulary) ────────────────────────────────────
|
|
54
54
|
/**
|
|
55
|
-
* The sync-group kinds the
|
|
56
|
-
*
|
|
55
|
+
* The sync-group kinds the authentication provider mints directly onto an
|
|
56
|
+
* identity. This is a fixed vocabulary: add to this list rather than write a
|
|
57
|
+
* new namespace string inline.
|
|
57
58
|
*
|
|
58
59
|
* - `org:<organizationId>` — every member of the organization
|
|
59
60
|
* - `user:<participantId>` — the participant itself
|
|
60
|
-
* - `project:<projectId>` — every credential scoped to the project
|
|
61
|
-
*
|
|
61
|
+
* - `project:<projectId>` — every credential scoped to the project; the
|
|
62
|
+
* organization's default project shares the organization's id
|
|
62
63
|
*
|
|
63
|
-
* Schema-declared roles ({@link identityRole}
|
|
64
|
-
* vocabulary per
|
|
64
|
+
* Schema-declared roles ({@link identityRole} and {@link entityRole}) extend
|
|
65
|
+
* this vocabulary per application; the kinds here are the ones the engine
|
|
66
|
+
* reserves.
|
|
65
67
|
*/
|
|
66
68
|
export const IDENTITY_ANCHOR_KINDS = ['org', 'user', 'project'];
|
|
67
69
|
/** Mint an engine-reserved identity anchor (typed wrapper over {@link syncGroup}). */
|
|
@@ -113,20 +115,17 @@ export const grantsRefSchema = z.object({
|
|
|
113
115
|
scope: z.string().regex(/^[a-zA-Z_][a-zA-Z0-9_]*$/, 'grants.scope must name a relation'),
|
|
114
116
|
});
|
|
115
117
|
/**
|
|
116
|
-
* The
|
|
117
|
-
* option. One
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
* decides who may *read* a row, `groups` decides which delta *channels* a row
|
|
118
|
+
* The authoring form of a model's sync-group routing — the `groups: { ... }`
|
|
119
|
+
* option. One object collects the three independent routing controls. This is a
|
|
120
|
+
* separate concern from `policy`, which governs tenant isolation: `policy`
|
|
121
|
+
* decides who may read a row, while `groups` decides which change channels a row
|
|
121
122
|
* fans into.
|
|
122
123
|
*
|
|
123
|
-
* - `root` —
|
|
124
|
-
* (kind defaults
|
|
125
|
-
* `root` so it no longer collides with the (now removed) `scopedVia` tenancy
|
|
126
|
-
* sugar or the inner `grants.scope` relation name.
|
|
124
|
+
* - `root` — marks this model a scope root, so its records form the group
|
|
125
|
+
* `<kind>:<id>` (the kind defaults to the typename).
|
|
127
126
|
* - `grants` — a membership edge granting an identity access to a scope root.
|
|
128
|
-
* - `roles` —
|
|
129
|
-
*
|
|
127
|
+
* - `roles` — record-to-group roles keyed on a plain field rather than a
|
|
128
|
+
* relation, such as inbox fan-out. Accepts a single role or an array.
|
|
130
129
|
*/
|
|
131
130
|
export const groupsInputSchema = z.object({
|
|
132
131
|
root: scopeSchema.optional(),
|
|
@@ -197,3 +196,35 @@ export function composeEntitySyncGroups(record, def) {
|
|
|
197
196
|
}
|
|
198
197
|
return Array.from(out);
|
|
199
198
|
}
|
|
199
|
+
/**
|
|
200
|
+
* Narrow a client's requested sync-group set to the groups it is actually
|
|
201
|
+
* allowed to subscribe to. This helper is fully generic — it never inspects the
|
|
202
|
+
* group strings — so it lives beside the composition helpers above.
|
|
203
|
+
*
|
|
204
|
+
* Behaviour:
|
|
205
|
+
* - If the client requested no groups, return the full identity-derived set,
|
|
206
|
+
* which is this participant's default subscription scope.
|
|
207
|
+
* - If the client requested some groups, keep only those that appear in the
|
|
208
|
+
* identity-derived allowed set and drop the rest, reporting the dropped
|
|
209
|
+
* groups through the optional `logDropped` callback.
|
|
210
|
+
* - If nothing survives the filter, fall back to the full allowed set rather
|
|
211
|
+
* than return `[]`, which would otherwise collapse to the server-side
|
|
212
|
+
* `'default'` fallback and deliver no changes at all.
|
|
213
|
+
*/
|
|
214
|
+
export function intersectRequestedWithAllowed(args) {
|
|
215
|
+
const { requested, allowed, logDropped } = args;
|
|
216
|
+
if (requested.length === 0)
|
|
217
|
+
return allowed;
|
|
218
|
+
const allowedSet = new Set(allowed);
|
|
219
|
+
const accepted = [];
|
|
220
|
+
const dropped = [];
|
|
221
|
+
for (const g of requested) {
|
|
222
|
+
if (allowedSet.has(g))
|
|
223
|
+
accepted.push(g);
|
|
224
|
+
else
|
|
225
|
+
dropped.push(g);
|
|
226
|
+
}
|
|
227
|
+
if (dropped.length > 0 && logDropped)
|
|
228
|
+
logDropped(dropped);
|
|
229
|
+
return accepted.length > 0 ? accepted : allowed;
|
|
230
|
+
}
|
package/dist/schema/schema.d.ts
CHANGED
|
@@ -23,7 +23,7 @@ import { z } from 'zod';
|
|
|
23
23
|
import type { ModelDef, RelationRecord } from './model.js';
|
|
24
24
|
import type { RelationDef } from './relation.js';
|
|
25
25
|
import type { IdentityRole } from './roles.js';
|
|
26
|
-
export { type IdentityRole, type IdentityRoleSource, type IdentityContext, type EntityRole, type EntityRoleSource, type EntityContext, type RoleSource, type RoleContext, type SyncGroup, type SyncGroupInput, identityRole, entityRole, extractIdentityIds, extractEntityIds, composeIdentitySyncGroups, composeEntitySyncGroups, syncGroup, syncGroupSchema, syncGroupInputSchema, isSyncGroupInput, identityRoleSchema, entityRoleSchema, roleSchema, roleSourceSchema, scopeSchema, grantsRefSchema, groupsInputSchema, type GroupsInput, } from './roles.js';
|
|
26
|
+
export { type IdentityRole, type IdentityRoleSource, type IdentityContext, type EntityRole, type EntityRoleSource, type EntityContext, type RoleSource, type RoleContext, type SyncGroup, type SyncGroupInput, identityRole, entityRole, extractIdentityIds, extractEntityIds, composeIdentitySyncGroups, composeEntitySyncGroups, intersectRequestedWithAllowed, syncGroup, syncGroupSchema, syncGroupInputSchema, isSyncGroupInput, identityRoleSchema, entityRoleSchema, roleSchema, roleSourceSchema, scopeSchema, grantsRefSchema, groupsInputSchema, type GroupsInput, } from './roles.js';
|
|
27
27
|
/** The set of built-in casing conventions supported by `defineSchema`. */
|
|
28
28
|
export type CasingConvention = 'snake_case' | 'camelCase';
|
|
29
29
|
/** Plug point for custom conventions (e.g. mixed legacy databases). */
|
|
@@ -48,17 +48,16 @@ export interface DefineSchemaOptions {
|
|
|
48
48
|
*/
|
|
49
49
|
readonly casing?: Casing;
|
|
50
50
|
/**
|
|
51
|
-
* Identity-anchored sync-group roles.
|
|
52
|
-
* `composeIdentitySyncGroups`
|
|
53
|
-
* participant
|
|
54
|
-
* `
|
|
55
|
-
*
|
|
56
|
-
* controls both the template string and the extractor function.
|
|
51
|
+
* Identity-anchored sync-group roles. The server's
|
|
52
|
+
* `composeIdentitySyncGroups` reads these to build the set of groups a
|
|
53
|
+
* participant may subscribe to. See {@link IdentityRole} for the shape: you
|
|
54
|
+
* define the `kind` and which identity field supplies the id, with no fixed
|
|
55
|
+
* vocabulary of kinds.
|
|
57
56
|
*
|
|
58
|
-
* Leave unset for schemas that
|
|
59
|
-
*
|
|
60
|
-
* returns `[]` and
|
|
61
|
-
*
|
|
57
|
+
* Leave this unset for schemas that need no identity-derived scoping, such as
|
|
58
|
+
* fully public read models. When it is unset, `composeIdentitySyncGroups`
|
|
59
|
+
* returns `[]` and callers fall back to whatever explicit sync groups the
|
|
60
|
+
* authentication provider attached to the identity.
|
|
62
61
|
*/
|
|
63
62
|
readonly identityRoles?: readonly IdentityRole[];
|
|
64
63
|
}
|
|
@@ -79,20 +78,20 @@ export declare const baseFieldsSchema: z.ZodObject<{
|
|
|
79
78
|
createdBy: z.ZodOptional<z.ZodString>;
|
|
80
79
|
}, z.core.$strip>;
|
|
81
80
|
/**
|
|
82
|
-
* The base-column names every model carries automatically
|
|
83
|
-
* {@link baseFieldsSchema}
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
81
|
+
* The base-column names every model carries automatically — the keys of
|
|
82
|
+
* {@link baseFieldsSchema}, kept here as the single source of truth. Code
|
|
83
|
+
* generation reads it to avoid emitting a base column twice, and
|
|
84
|
+
* {@link defineSchema} uses it to reject a model that redeclares one, since
|
|
85
|
+
* merging the user's field over the base field would produce a `string & Date`
|
|
86
|
+
* type and break the build.
|
|
88
87
|
*/
|
|
89
88
|
export declare const BASE_FIELDS: readonly ["id", "createdAt", "updatedAt", "organizationId", "createdBy"];
|
|
90
89
|
/** The base fields type — pure data columns. */
|
|
91
90
|
export type BaseModelFields = z.infer<typeof baseFieldsSchema>;
|
|
92
91
|
/**
|
|
93
|
-
* Methods every
|
|
94
|
-
*
|
|
95
|
-
*
|
|
92
|
+
* Methods every model instance carries. These are intersected into
|
|
93
|
+
* {@link InferModel}, the read-side type, but not into the create or update
|
|
94
|
+
* input types, since methods are not valid input.
|
|
96
95
|
*/
|
|
97
96
|
export interface BaseModelMethods {
|
|
98
97
|
/** Wire-format model name (e.g. `'Slide'`, `'Comment'`). */
|
|
@@ -130,39 +129,37 @@ type RegisteredSchema = import('../types/global.js').Register extends {
|
|
|
130
129
|
Schema: infer S extends Schema;
|
|
131
130
|
} ? S : never;
|
|
132
131
|
/**
|
|
133
|
-
*
|
|
134
|
-
*
|
|
132
|
+
* The primary model-type helper. Once your project's `ablo/register.ts`
|
|
133
|
+
* registers the schema, a single argument is all it takes:
|
|
135
134
|
*
|
|
136
135
|
* ```ts
|
|
137
136
|
* type Task = Model<'tasks'>;
|
|
138
137
|
* ```
|
|
139
138
|
*
|
|
140
|
-
* Without registration
|
|
141
|
-
* `Model<typeof schema, 'tasks'>`.
|
|
139
|
+
* Without that registration, or for a second schema, pass the schema
|
|
140
|
+
* explicitly: `Model<typeof schema, 'tasks'>`.
|
|
142
141
|
*/
|
|
143
142
|
export type Model<A, B = never> = [B] extends [never] ? A extends keyof RegisteredSchema['models'] ? InferModel<RegisteredSchema, A> : never : A extends Schema ? InferModel<A, B extends keyof A['models'] ? B : never> : never;
|
|
144
143
|
/**
|
|
145
|
-
* @deprecated Use {@link Model} — `
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
* alias; no behavior difference.
|
|
144
|
+
* @deprecated Use {@link Model} instead — `Model<typeof schema, 'tasks'>` reads
|
|
145
|
+
* as the domain ("the Task model from my schema") rather than the machinery.
|
|
146
|
+
* Kept as an alias with no behavioral difference.
|
|
149
147
|
*/
|
|
150
148
|
export type InferModel<S extends Schema, ModelName extends keyof S['models']> = S['models'][ModelName] extends ModelDef<infer Shape, infer R, infer C> ? // `Omit<…, keyof BaseModelFields>` so a model that (wrongly) redeclares a
|
|
151
149
|
Omit<z.infer<z.ZodObject<Shape>>, keyof BaseModelFields> & BaseModelFields & BaseModelMethods & InferComputed<C> & InferRelations<S, R> : never;
|
|
152
150
|
/**
|
|
153
|
-
* Infer relation accessor types from a model's relations record.
|
|
151
|
+
* Infer the relation accessor types from a model's relations record.
|
|
154
152
|
*
|
|
155
|
-
*
|
|
156
|
-
* `
|
|
157
|
-
*
|
|
158
|
-
* write `slide.layers` and `slide.deck` without manual casts.
|
|
153
|
+
* At runtime the engine installs a getter for each declared relation, so this
|
|
154
|
+
* type mirrors them and you can read `slide.layers` and `slide.deck` without a
|
|
155
|
+
* cast.
|
|
159
156
|
*
|
|
160
157
|
* - `hasMany` → `InferModel<S, Target>[]`
|
|
161
158
|
* - `belongsTo` / `hasOne` → `InferModel<S, Target> | undefined` (undefined
|
|
162
|
-
* when the
|
|
159
|
+
* when the foreign key is unset or the parent has not loaded yet)
|
|
163
160
|
*
|
|
164
|
-
* Kept
|
|
165
|
-
*
|
|
161
|
+
* Kept `readonly` because the accessors are getters with no setter — assigning
|
|
162
|
+
* to `slide.layers` would have no effect at runtime.
|
|
166
163
|
*/
|
|
167
164
|
export type InferRelations<S extends Schema, R extends RelationRecord> = string extends keyof R ? unknown : {
|
|
168
165
|
readonly [K in keyof R]: R[K] extends RelationDef<infer Type, infer Target, infer _F, infer _O> ? Target extends keyof S['models'] ? Type extends 'hasMany' ? InferModel<S, Target>[] : Type extends 'hasOne' | 'belongsTo' ? InferModel<S, Target> | undefined : never : never : never;
|
|
@@ -202,9 +199,7 @@ Omit<z.input<z.ZodObject<Shape>>, keyof BaseModelFields> & Partial<BaseModelFiel
|
|
|
202
199
|
export type InferModelNames<S extends Schema> = keyof S['models'] & string;
|
|
203
200
|
/**
|
|
204
201
|
* The value type for inserting a new row. Same shape as {@link InferCreate}:
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
* Matches Zero's `InsertValue<TableSchema>` from `zql/src/mutate/crud.ts`.
|
|
202
|
+
* the fields you can write, plus an optional `id` for client-generated ids.
|
|
208
203
|
*/
|
|
209
204
|
export type InsertValue<S extends Schema, ModelName extends keyof S['models']> = InferCreate<S, ModelName>;
|
|
210
205
|
/**
|
|
@@ -217,18 +212,14 @@ export type UpsertValue<S extends Schema, ModelName extends keyof S['models']> =
|
|
|
217
212
|
* The value type for updating an existing row. `id` is required (identifies
|
|
218
213
|
* the row to update); all other fields are optional (only provided fields
|
|
219
214
|
* are changed).
|
|
220
|
-
*
|
|
221
|
-
* Matches Zero's `UpdateValue<TableSchema>` from `zql/src/mutate/crud.ts`.
|
|
222
215
|
*/
|
|
223
216
|
export type UpdateValue<S extends Schema, ModelName extends keyof S['models']> = S['models'][ModelName] extends ModelDef<infer Shape> ? {
|
|
224
217
|
id: string;
|
|
225
218
|
} & Partial<z.input<z.ZodObject<Shape>>> : never;
|
|
226
219
|
/**
|
|
227
220
|
* The value type for deleting a row. Just the primary key.
|
|
228
|
-
*
|
|
229
|
-
* Matches Zero's `DeleteID<TableSchema>` from `zql/src/mutate/crud.ts`.
|
|
230
221
|
*/
|
|
231
|
-
export
|
|
222
|
+
export interface DeleteId<S extends Schema, ModelName extends keyof S['models']> {
|
|
232
223
|
id: string;
|
|
233
|
-
}
|
|
224
|
+
}
|
|
234
225
|
export declare function defineSchema<const S extends SchemaRecord>(models: S, options?: DefineSchemaOptions): Schema<S>;
|
package/dist/schema/schema.js
CHANGED
|
@@ -22,10 +22,10 @@
|
|
|
22
22
|
import { z } from 'zod';
|
|
23
23
|
import { AbloValidationError } from '../errors.js';
|
|
24
24
|
import { scopeSchema, grantsRefSchema } from './roles.js';
|
|
25
|
-
// Sync-group roles (identity
|
|
26
|
-
// so
|
|
27
|
-
//
|
|
28
|
-
export { identityRole, entityRole, extractIdentityIds, extractEntityIds, composeIdentitySyncGroups, composeEntitySyncGroups, syncGroup, syncGroupSchema, syncGroupInputSchema, isSyncGroupInput, identityRoleSchema, entityRoleSchema, roleSchema, roleSourceSchema, scopeSchema, grantsRefSchema, groupsInputSchema, } from './roles.js';
|
|
25
|
+
// Sync-group roles (identity and entity) are defined in `./roles.js` and
|
|
26
|
+
// re-exported here so they can also be imported from this module. See
|
|
27
|
+
// `./roles.js` for the full vocabulary.
|
|
28
|
+
export { identityRole, entityRole, extractIdentityIds, extractEntityIds, composeIdentitySyncGroups, composeEntitySyncGroups, intersectRequestedWithAllowed, syncGroup, syncGroupSchema, syncGroupInputSchema, isSyncGroupInput, identityRoleSchema, entityRoleSchema, roleSchema, roleSourceSchema, scopeSchema, grantsRefSchema, groupsInputSchema, } from './roles.js';
|
|
29
29
|
function resolveCasing(fn) {
|
|
30
30
|
if (fn === undefined)
|
|
31
31
|
return (x) => x;
|
|
@@ -38,9 +38,9 @@ function resolveCasing(fn) {
|
|
|
38
38
|
return (x) => x;
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
|
-
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
41
|
+
/** Converts a camelCase identifier to snake_case. Kept local so the package
|
|
42
|
+
* carries no database-driver dependency, and so consumers on any stack get the
|
|
43
|
+
* same result. */
|
|
44
44
|
function camelToSnake(identifier) {
|
|
45
45
|
return identifier.replace(/[A-Z]/g, (ch) => `_${ch.toLowerCase()}`);
|
|
46
46
|
}
|
|
@@ -59,12 +59,12 @@ export const baseFieldsSchema = z.object({
|
|
|
59
59
|
createdBy: z.string().optional(),
|
|
60
60
|
});
|
|
61
61
|
/**
|
|
62
|
-
* The base-column names every model carries automatically
|
|
63
|
-
* {@link baseFieldsSchema}
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
62
|
+
* The base-column names every model carries automatically — the keys of
|
|
63
|
+
* {@link baseFieldsSchema}, kept here as the single source of truth. Code
|
|
64
|
+
* generation reads it to avoid emitting a base column twice, and
|
|
65
|
+
* {@link defineSchema} uses it to reject a model that redeclares one, since
|
|
66
|
+
* merging the user's field over the base field would produce a `string & Date`
|
|
67
|
+
* type and break the build.
|
|
68
68
|
*/
|
|
69
69
|
export const BASE_FIELDS = [
|
|
70
70
|
'id',
|
|
@@ -85,22 +85,21 @@ export const BASE_FIELDS = [
|
|
|
85
85
|
* ```
|
|
86
86
|
*/
|
|
87
87
|
/**
|
|
88
|
-
*
|
|
89
|
-
*
|
|
88
|
+
* Rejects field names that will not survive the sync driver's snake_case ↔
|
|
89
|
+
* camelCase round-trip. The driver maps identifiers like this:
|
|
90
90
|
*
|
|
91
|
-
* `content_json` → `contentJson`
|
|
92
|
-
* `contentJson` → `content_json`
|
|
93
|
-
* `contentJSON` → `content_j_s_o_n` (
|
|
91
|
+
* `content_json` → `contentJson` (snake → camel)
|
|
92
|
+
* `contentJson` → `content_json` (camel → snake)
|
|
93
|
+
* `contentJSON` → `content_j_s_o_n` (does not round-trip)
|
|
94
94
|
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
* definition time rather than at runtime.
|
|
95
|
+
* A name that does not round-trip through this pair of transforms will silently
|
|
96
|
+
* fail to populate on the client: the wire delivers one casing, the model reads
|
|
97
|
+
* another, and the field lands as `undefined`. Catching it here surfaces the
|
|
98
|
+
* problem when the schema is defined rather than at runtime.
|
|
100
99
|
*
|
|
101
|
-
*
|
|
102
|
-
* followed by lowercase letters
|
|
103
|
-
* `contentJSON` has `JSON` all
|
|
100
|
+
* The rule: a standard camelCase identifier has runs of a single uppercase
|
|
101
|
+
* letter followed by lowercase letters, never two uppercase letters in a row.
|
|
102
|
+
* `contentJSON` has `JSON` in all caps, so it is rejected.
|
|
104
103
|
*/
|
|
105
104
|
function assertRoundTrippableCamelCase(modelName, fieldName) {
|
|
106
105
|
// Base fields merged in by defineSchema are already validated; skip.
|
|
@@ -108,17 +107,18 @@ function assertRoundTrippableCamelCase(modelName, fieldName) {
|
|
|
108
107
|
return;
|
|
109
108
|
// Leading-lowercase constraint: fields must be camelCase, not PascalCase.
|
|
110
109
|
// PascalCase is reserved for typenames.
|
|
111
|
-
|
|
110
|
+
const first = fieldName.charAt(0);
|
|
111
|
+
if (first >= 'A' && first <= 'Z') {
|
|
112
112
|
throw new AbloValidationError(`[defineSchema] ${modelName}.${fieldName}: field names must start lowercase ` +
|
|
113
|
-
`(camelCase). Use "${
|
|
113
|
+
`(camelCase). Use "${first.toLowerCase()}${fieldName.slice(1)}" instead.`, { code: 'schema_field_not_camelcase' });
|
|
114
114
|
}
|
|
115
115
|
// Two-consecutive-uppercase check. The classic failure mode is
|
|
116
116
|
// `contentJSON`, `contentHTML`, `myURLParam`, etc. These don't round-trip
|
|
117
117
|
// through `postgres.camel` — the snake_case intermediate would be
|
|
118
118
|
// `content_j_s_o_n`, which is not a column that exists.
|
|
119
119
|
for (let i = 0; i < fieldName.length - 1; i++) {
|
|
120
|
-
const a = fieldName
|
|
121
|
-
const b = fieldName
|
|
120
|
+
const a = fieldName.charAt(i);
|
|
121
|
+
const b = fieldName.charAt(i + 1);
|
|
122
122
|
const aUpper = a >= 'A' && a <= 'Z';
|
|
123
123
|
const bUpper = b >= 'A' && b <= 'Z';
|
|
124
124
|
if (aUpper && bUpper) {
|
|
@@ -134,9 +134,9 @@ function assertRoundTrippableCamelCase(modelName, fieldName) {
|
|
|
134
134
|
}
|
|
135
135
|
export function defineSchema(models, options) {
|
|
136
136
|
// Build validators with base fields merged in, and resolve defaults for
|
|
137
|
-
// `typename` and `persist.store` so downstream code (the
|
|
138
|
-
//
|
|
139
|
-
//
|
|
137
|
+
// `typename` and `persist.store` so downstream code (the loader and the
|
|
138
|
+
// hydration pipeline) can rely on these fields being set without re-deriving
|
|
139
|
+
// them at every call site.
|
|
140
140
|
//
|
|
141
141
|
// Defaults:
|
|
142
142
|
// typename ← schema key (e.g. `slideLayer` → `'slideLayer'`)
|
|
@@ -184,8 +184,7 @@ export function defineSchema(models, options) {
|
|
|
184
184
|
// columns stay declared in the artifact instead of rediscovered by
|
|
185
185
|
// SQL compilers. Server-side SQL compilers read the resolved value
|
|
186
186
|
// directly.
|
|
187
|
-
for (const
|
|
188
|
-
const rel = def.relations[relName];
|
|
187
|
+
for (const rel of Object.values(def.relations)) {
|
|
189
188
|
const fieldColumn = def.fields[rel.foreignKey]?.column;
|
|
190
189
|
rel.foreignKeyColumn = fieldColumn ?? casing(rel.foreignKey);
|
|
191
190
|
}
|
|
@@ -211,10 +210,10 @@ export function defineSchema(models, options) {
|
|
|
211
210
|
};
|
|
212
211
|
}
|
|
213
212
|
/**
|
|
214
|
-
*
|
|
215
|
-
* at schema-build time, so a mistyped membership edge fails
|
|
216
|
-
*
|
|
217
|
-
* declaration —
|
|
213
|
+
* Validates the relation-driven sync-group declarations (`scope` and `grants`)
|
|
214
|
+
* at schema-build time, so a mistyped membership edge fails here — with a
|
|
215
|
+
* structured error (`code`, `param`, `doc_url`) pointing at the exact
|
|
216
|
+
* declaration — rather than silently mis-routing changes at runtime.
|
|
218
217
|
*/
|
|
219
218
|
function validateSyncGroupSchema(models) {
|
|
220
219
|
for (const [name, def] of Object.entries(models)) {
|
|
@@ -245,6 +244,10 @@ function validateSyncGroupSchema(models) {
|
|
|
245
244
|
// The scope edge must target a model that is actually a scope root —
|
|
246
245
|
// otherwise the resolved `<kind>:<id>` group is one nothing fans into.
|
|
247
246
|
const scopeRel = relations[def.grants.scope];
|
|
247
|
+
// Unreachable: the role loop above already threw if the scope relation
|
|
248
|
+
// is missing — this narrows the indexed access for the checks below.
|
|
249
|
+
if (!scopeRel)
|
|
250
|
+
continue;
|
|
248
251
|
const target = models[scopeRel.target];
|
|
249
252
|
if (target && !target.scope) {
|
|
250
253
|
throw new AbloValidationError(`Model "${name}": grants.scope "${def.grants.scope}" targets "${scopeRel.target}", ` +
|
package/dist/schema/select.d.ts
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `selectModels`
|
|
2
|
+
* `selectModels` projects a schema down to a subset of its models.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
4
|
+
* It lets one canonical schema serve several apps, each subscribing only to the
|
|
5
|
+
* models it needs. Rather than re-declare a model's fields in a second schema —
|
|
6
|
+
* which you would then have to keep identical by hand — an app selects the
|
|
7
|
+
* models it wants from the canonical schema. Field shapes, resolved foreign-key
|
|
8
|
+
* columns, computed getters, typenames, and identity roles all come from the
|
|
9
|
+
* source, so a subset cannot drift from the canonical definition.
|
|
10
10
|
*
|
|
11
11
|
* ```ts
|
|
12
|
-
* import { schema as full } from '
|
|
12
|
+
* import { schema as full } from './schema';
|
|
13
13
|
* import { selectModels } from '@abloatai/ablo/schema';
|
|
14
14
|
*
|
|
15
|
-
* //
|
|
15
|
+
* // Subscribe to identity and dataroom content only.
|
|
16
16
|
* export const schema = selectModels(full, ['users', 'organizations', 'datarooms', 'folders', 'files']);
|
|
17
17
|
* ```
|
|
18
18
|
*
|
|
19
|
-
* Relations whose target falls outside the selected set are dropped
|
|
20
|
-
* subset only
|
|
21
|
-
* scope-inheritance throws instead
|
|
22
|
-
* record's fan-out
|
|
19
|
+
* Relations whose target falls outside the selected set are dropped, so the
|
|
20
|
+
* subset sees only its own models. Dropping a relation that carries `parent`
|
|
21
|
+
* scope-inheritance throws instead, because silently losing it would mis-route
|
|
22
|
+
* a record's fan-out — the selected set must be closed under `parent` edges.
|
|
23
23
|
*/
|
|
24
24
|
import type { Schema, SchemaRecord } from './schema.js';
|
|
25
25
|
export declare function selectModels<S extends SchemaRecord, K extends keyof S & string>(schema: Schema<S>, keys: readonly K[]): Schema<Pick<S, K>>;
|
package/dist/schema/select.js
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `selectModels`
|
|
2
|
+
* `selectModels` projects a schema down to a subset of its models.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
4
|
+
* It lets one canonical schema serve several apps, each subscribing only to the
|
|
5
|
+
* models it needs. Rather than re-declare a model's fields in a second schema —
|
|
6
|
+
* which you would then have to keep identical by hand — an app selects the
|
|
7
|
+
* models it wants from the canonical schema. Field shapes, resolved foreign-key
|
|
8
|
+
* columns, computed getters, typenames, and identity roles all come from the
|
|
9
|
+
* source, so a subset cannot drift from the canonical definition.
|
|
10
10
|
*
|
|
11
11
|
* ```ts
|
|
12
|
-
* import { schema as full } from '
|
|
12
|
+
* import { schema as full } from './schema';
|
|
13
13
|
* import { selectModels } from '@abloatai/ablo/schema';
|
|
14
14
|
*
|
|
15
|
-
* //
|
|
15
|
+
* // Subscribe to identity and dataroom content only.
|
|
16
16
|
* export const schema = selectModels(full, ['users', 'organizations', 'datarooms', 'folders', 'files']);
|
|
17
17
|
* ```
|
|
18
18
|
*
|
|
19
|
-
* Relations whose target falls outside the selected set are dropped
|
|
20
|
-
* subset only
|
|
21
|
-
* scope-inheritance throws instead
|
|
22
|
-
* record's fan-out
|
|
19
|
+
* Relations whose target falls outside the selected set are dropped, so the
|
|
20
|
+
* subset sees only its own models. Dropping a relation that carries `parent`
|
|
21
|
+
* scope-inheritance throws instead, because silently losing it would mis-route
|
|
22
|
+
* a record's fan-out — the selected set must be closed under `parent` edges.
|
|
23
23
|
*/
|
|
24
24
|
import { AbloValidationError } from '../errors.js';
|
|
25
25
|
export function selectModels(schema, keys) {
|