@segmentstream/ontology 0.0.0-stage → 0.92.1
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/LICENSE +201 -0
- package/NOTICE +2 -0
- package/README.md +1655 -2
- package/dist/action.d.ts +193 -0
- package/dist/action.js +41 -0
- package/dist/agent-chat.d.ts +44 -0
- package/dist/agent-chat.js +91 -0
- package/dist/agent-task-contract.d.ts +64 -0
- package/dist/agent-task-contract.js +15 -0
- package/dist/agent-task.d.ts +39 -0
- package/dist/agent-task.js +112 -0
- package/dist/analyze.d.ts +215 -0
- package/dist/analyze.js +2438 -0
- package/dist/app-feedback.d.ts +167 -0
- package/dist/app-feedback.js +176 -0
- package/dist/authoring-input.d.ts +3 -0
- package/dist/authoring-input.js +107 -0
- package/dist/authoring-names.d.ts +4 -0
- package/dist/authoring-names.js +13 -0
- package/dist/authoring-records.d.ts +35 -0
- package/dist/authoring-records.js +264 -0
- package/dist/authoring.d.ts +15 -0
- package/dist/authoring.js +331 -0
- package/dist/bin/check.d.ts +30 -0
- package/dist/bin/check.js +99 -0
- package/dist/bin/load.d.ts +48 -0
- package/dist/bin/load.js +139 -0
- package/dist/bin/main.d.ts +31 -0
- package/dist/bin/main.js +121 -0
- package/dist/bin/migrate.d.ts +57 -0
- package/dist/bin/migrate.js +170 -0
- package/dist/bin/output.d.ts +31 -0
- package/dist/bin/output.js +84 -0
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +31 -0
- package/dist/blob.d.ts +52 -0
- package/dist/blob.js +87 -0
- package/dist/channel-session.d.ts +16 -0
- package/dist/channel-session.js +16 -0
- package/dist/chat.d.ts +43 -0
- package/dist/chat.js +34 -0
- package/dist/confirmation.d.ts +46 -0
- package/dist/confirmation.js +41 -0
- package/dist/connection.d.ts +213 -0
- package/dist/connection.js +289 -0
- package/dist/deployment.d.ts +35 -0
- package/dist/deployment.js +76 -0
- package/dist/diagnostics.d.ts +27 -0
- package/dist/diagnostics.js +106 -0
- package/dist/emails.d.ts +70 -0
- package/dist/emails.js +221 -0
- package/dist/entity.d.ts +331 -0
- package/dist/entity.js +153 -0
- package/dist/errors.d.ts +154 -0
- package/dist/errors.js +109 -0
- package/dist/feedback-config.d.ts +24 -0
- package/dist/feedback-config.js +126 -0
- package/dist/files.d.ts +39 -0
- package/dist/files.js +4 -0
- package/dist/groups.d.ts +95 -0
- package/dist/groups.js +280 -0
- package/dist/index.d.ts +109 -0
- package/dist/index.js +70 -0
- package/dist/internal/diagnostics.js +594 -0
- package/dist/legacy.d.ts +160 -0
- package/dist/legacy.js +270 -0
- package/dist/manifest-compatibility.d.ts +8 -0
- package/dist/manifest-compatibility.js +87 -0
- package/dist/manifest.d.ts +3329 -0
- package/dist/manifest.js +757 -0
- package/dist/me.d.ts +46 -0
- package/dist/me.js +109 -0
- package/dist/metric-filters.d.ts +48 -0
- package/dist/metric-filters.js +252 -0
- package/dist/metric-routes.d.ts +132 -0
- package/dist/metric-routes.js +498 -0
- package/dist/metric.d.ts +172 -0
- package/dist/metric.js +132 -0
- package/dist/migrate/apply.d.ts +94 -0
- package/dist/migrate/apply.js +526 -0
- package/dist/migrate/errors.d.ts +46 -0
- package/dist/migrate/errors.js +38 -0
- package/dist/migrate/index.d.ts +10 -0
- package/dist/migrate/index.js +7 -0
- package/dist/migrate/model.d.ts +2311 -0
- package/dist/migrate/model.js +148 -0
- package/dist/migrate/plan.d.ts +51 -0
- package/dist/migrate/plan.js +1856 -0
- package/dist/migrate/preview.d.ts +13 -0
- package/dist/migrate/preview.js +65 -0
- package/dist/migrate/storage.d.ts +226 -0
- package/dist/migrate/storage.js +774 -0
- package/dist/model-metrics.d.ts +22 -0
- package/dist/model-metrics.js +545 -0
- package/dist/names.d.ts +49 -0
- package/dist/names.js +110 -0
- package/dist/navigation-artifact.d.ts +13 -0
- package/dist/navigation-artifact.js +11 -0
- package/dist/navigation-catalog.d.ts +55 -0
- package/dist/navigation-catalog.js +297 -0
- package/dist/nitro-navigation.d.ts +3 -0
- package/dist/nitro-navigation.js +64 -0
- package/dist/nitro-workflows.d.ts +108 -0
- package/dist/nitro-workflows.js +286 -0
- package/dist/nitro.d.ts +40 -0
- package/dist/nitro.js +50 -0
- package/dist/ontology.d.ts +41 -0
- package/dist/ontology.js +46 -0
- package/dist/permissions.d.ts +198 -0
- package/dist/permissions.js +272 -0
- package/dist/property.d.ts +188 -0
- package/dist/property.js +301 -0
- package/dist/query.d.ts +245 -0
- package/dist/query.js +615 -0
- package/dist/relationship.d.ts +99 -0
- package/dist/relationship.js +33 -0
- package/dist/render.d.ts +81 -0
- package/dist/render.js +512 -0
- package/dist/replication/baseline.d.ts +51 -0
- package/dist/replication/baseline.js +215 -0
- package/dist/replication/bigquery.d.ts +37 -0
- package/dist/replication/bigquery.js +211 -0
- package/dist/replication/coverage.d.ts +14 -0
- package/dist/replication/coverage.js +53 -0
- package/dist/replication/evolution.d.ts +25 -0
- package/dist/replication/evolution.js +184 -0
- package/dist/replication/identities.d.ts +6 -0
- package/dist/replication/identities.js +47 -0
- package/dist/replication/legacy-baseline.d.ts +27 -0
- package/dist/replication/legacy-baseline.js +109 -0
- package/dist/replication/legacy-store.d.ts +19 -0
- package/dist/replication/legacy-store.js +63 -0
- package/dist/replication/lineage.d.ts +36 -0
- package/dist/replication/lineage.js +72 -0
- package/dist/replication/migrate.d.ts +21 -0
- package/dist/replication/migrate.js +84 -0
- package/dist/replication/model.d.ts +52 -0
- package/dist/replication/model.js +99 -0
- package/dist/replication/scans.d.ts +34 -0
- package/dist/replication/scans.js +158 -0
- package/dist/replication/schema.d.ts +11 -0
- package/dist/replication/schema.js +226 -0
- package/dist/replication/shadow-schema.d.ts +4 -0
- package/dist/replication/shadow-schema.js +61 -0
- package/dist/replication/shadow.d.ts +127 -0
- package/dist/replication/shadow.js +614 -0
- package/dist/replication/source-replacement.d.ts +33 -0
- package/dist/replication/source-replacement.js +76 -0
- package/dist/replication/store.d.ts +36 -0
- package/dist/replication/store.js +382 -0
- package/dist/replication/transaction.d.ts +23 -0
- package/dist/replication/transaction.js +88 -0
- package/dist/role.d.ts +61 -0
- package/dist/role.js +76 -0
- package/dist/runtime/action-deadlocks.d.ts +21 -0
- package/dist/runtime/action-deadlocks.js +130 -0
- package/dist/runtime/action-transactions.d.ts +35 -0
- package/dist/runtime/action-transactions.js +54 -0
- package/dist/runtime/agent-counters.d.ts +26 -0
- package/dist/runtime/agent-counters.js +98 -0
- package/dist/runtime/agent-tasks.d.ts +63 -0
- package/dist/runtime/agent-tasks.js +120 -0
- package/dist/runtime/agents.d.ts +15 -0
- package/dist/runtime/agents.js +457 -0
- package/dist/runtime/batch-diagnostics.d.ts +22 -0
- package/dist/runtime/batch-diagnostics.js +89 -0
- package/dist/runtime/batch.d.ts +52 -0
- package/dist/runtime/batch.js +534 -0
- package/dist/runtime/channel-session-revocation.d.ts +3 -0
- package/dist/runtime/channel-session-revocation.js +5 -0
- package/dist/runtime/channel-sessions.d.ts +4 -0
- package/dist/runtime/channel-sessions.js +61 -0
- package/dist/runtime/confirmations.d.ts +29 -0
- package/dist/runtime/confirmations.js +57 -0
- package/dist/runtime/cursor.d.ts +23 -0
- package/dist/runtime/cursor.js +100 -0
- package/dist/runtime/deployment.d.ts +7 -0
- package/dist/runtime/deployment.js +4 -0
- package/dist/runtime/errors.d.ts +118 -0
- package/dist/runtime/errors.js +109 -0
- package/dist/runtime/federation-tables.d.ts +2 -0
- package/dist/runtime/federation-tables.js +20 -0
- package/dist/runtime/federation.d.ts +42 -0
- package/dist/runtime/federation.js +222 -0
- package/dist/runtime/files.d.ts +39 -0
- package/dist/runtime/files.js +44 -0
- package/dist/runtime/generated-actions.d.ts +37 -0
- package/dist/runtime/generated-actions.js +307 -0
- package/dist/runtime/history.d.ts +91 -0
- package/dist/runtime/history.js +77 -0
- package/dist/runtime/ids.d.ts +6 -0
- package/dist/runtime/ids.js +39 -0
- package/dist/runtime/member-tables.d.ts +8 -0
- package/dist/runtime/member-tables.js +33 -0
- package/dist/runtime/member-writes.d.ts +78 -0
- package/dist/runtime/member-writes.js +202 -0
- package/dist/runtime/metric-query.d.ts +19 -0
- package/dist/runtime/metric-query.js +411 -0
- package/dist/runtime/model.d.ts +67 -0
- package/dist/runtime/model.js +150 -0
- package/dist/runtime/new-user-hook.d.ts +6 -0
- package/dist/runtime/new-user-hook.js +37 -0
- package/dist/runtime/oauth.d.ts +9 -0
- package/dist/runtime/oauth.js +299 -0
- package/dist/runtime/pipeline.d.ts +155 -0
- package/dist/runtime/pipeline.js +597 -0
- package/dist/runtime/postgres-tls.d.ts +10 -0
- package/dist/runtime/postgres-tls.js +14 -0
- package/dist/runtime/principals.d.ts +302 -0
- package/dist/runtime/principals.js +1307 -0
- package/dist/runtime/reads.d.ts +55 -0
- package/dist/runtime/reads.js +313 -0
- package/dist/runtime/records.d.ts +42 -0
- package/dist/runtime/records.js +245 -0
- package/dist/runtime/resolve-agent-identity.d.ts +6 -0
- package/dist/runtime/resolve-agent-identity.js +181 -0
- package/dist/runtime/service-binding.d.ts +18 -0
- package/dist/runtime/service-binding.js +266 -0
- package/dist/runtime/sign-in-links.d.ts +68 -0
- package/dist/runtime/sign-in-links.js +147 -0
- package/dist/runtime/sql-runtime.d.ts +131 -0
- package/dist/runtime/sql-runtime.js +362 -0
- package/dist/runtime/statement.d.ts +18 -0
- package/dist/runtime/statement.js +31 -0
- package/dist/runtime/user-identities.d.ts +66 -0
- package/dist/runtime/user-identities.js +106 -0
- package/dist/runtime/user-identity-sql.d.ts +86 -0
- package/dist/runtime/user-identity-sql.js +297 -0
- package/dist/runtime/user-roles.d.ts +16 -0
- package/dist/runtime/user-roles.js +32 -0
- package/dist/runtime/validation.d.ts +16 -0
- package/dist/runtime/validation.js +26 -0
- package/dist/runtime/where.d.ts +57 -0
- package/dist/runtime/where.js +404 -0
- package/dist/runtime/workflow-admission.d.ts +49 -0
- package/dist/runtime/workflow-admission.js +92 -0
- package/dist/runtime/workflow-argument-codec.d.ts +10 -0
- package/dist/runtime/workflow-argument-codec.js +120 -0
- package/dist/runtime/workflow-arguments.d.ts +17 -0
- package/dist/runtime/workflow-arguments.js +99 -0
- package/dist/runtime/workflow-starts.d.ts +203 -0
- package/dist/runtime/workflow-starts.js +493 -0
- package/dist/runtime/workflow-users.d.ts +9 -0
- package/dist/runtime/workflow-users.js +17 -0
- package/dist/runtime/workload.d.ts +25 -0
- package/dist/runtime/workload.js +24 -0
- package/dist/runtime/writes.d.ts +108 -0
- package/dist/runtime/writes.js +491 -0
- package/dist/runtime-source.d.ts +22 -0
- package/dist/runtime-source.js +28 -0
- package/dist/runtime.d.ts +310 -0
- package/dist/runtime.js +31 -0
- package/dist/server.d.ts +23 -0
- package/dist/server.js +107 -0
- package/dist/service/agent/attachments.d.ts +33 -0
- package/dist/service/agent/attachments.js +228 -0
- package/dist/service/agent/authentication.d.ts +22 -0
- package/dist/service/agent/authentication.js +58 -0
- package/dist/service/agent/confirmations.d.ts +5 -0
- package/dist/service/agent/confirmations.js +73 -0
- package/dist/service/agent/conversation-routes.d.ts +14 -0
- package/dist/service/agent/conversation-routes.js +45 -0
- package/dist/service/agent/conversations.d.ts +40 -0
- package/dist/service/agent/conversations.js +69 -0
- package/dist/service/agent/files.d.ts +12 -0
- package/dist/service/agent/files.js +69 -0
- package/dist/service/agent/protocol.d.ts +90 -0
- package/dist/service/agent/protocol.js +114 -0
- package/dist/service/agent/server.d.ts +28 -0
- package/dist/service/agent/server.js +374 -0
- package/dist/service/agent/task-caller.d.ts +21 -0
- package/dist/service/agent/task-caller.js +35 -0
- package/dist/service/agent/task-start.d.ts +53 -0
- package/dist/service/agent/task-start.js +161 -0
- package/dist/service/agent/tasks.d.ts +40 -0
- package/dist/service/agent/tasks.js +155 -0
- package/dist/service/api.d.ts +50 -0
- package/dist/service/api.js +288 -0
- package/dist/service/authentication.d.ts +227 -0
- package/dist/service/authentication.js +767 -0
- package/dist/service/caller-context.d.ts +24 -0
- package/dist/service/caller-context.js +6 -0
- package/dist/service/catalog.d.ts +42 -0
- package/dist/service/catalog.js +66 -0
- package/dist/service/channel/provider.d.ts +10 -0
- package/dist/service/channel/provider.js +1 -0
- package/dist/service/channel/providers/telegram.d.ts +18 -0
- package/dist/service/channel/providers/telegram.js +108 -0
- package/dist/service/channel/sessions.d.ts +5 -0
- package/dist/service/channel/sessions.js +53 -0
- package/dist/service/channel/sign-in.d.ts +7 -0
- package/dist/service/channel/sign-in.js +78 -0
- package/dist/service/chat/archive.d.ts +64 -0
- package/dist/service/chat/archive.js +62 -0
- package/dist/service/chat/attribution.d.ts +26 -0
- package/dist/service/chat/attribution.js +28 -0
- package/dist/service/chat/delivery.d.ts +18 -0
- package/dist/service/chat/delivery.js +251 -0
- package/dist/service/chat/diagnostics.d.ts +2 -0
- package/dist/service/chat/diagnostics.js +35 -0
- package/dist/service/chat/envelope.d.ts +96 -0
- package/dist/service/chat/envelope.js +39 -0
- package/dist/service/chat/idempotency.d.ts +19 -0
- package/dist/service/chat/idempotency.js +37 -0
- package/dist/service/chat/providers/telegram.d.ts +36 -0
- package/dist/service/chat/providers/telegram.js +133 -0
- package/dist/service/chat/reads.d.ts +25 -0
- package/dist/service/chat/reads.js +75 -0
- package/dist/service/chat/resolve.d.ts +34 -0
- package/dist/service/chat/resolve.js +150 -0
- package/dist/service/chat/routes.d.ts +23 -0
- package/dist/service/chat/routes.js +75 -0
- package/dist/service/chat/schemas.d.ts +43 -0
- package/dist/service/chat/schemas.js +31 -0
- package/dist/service/config.d.ts +218 -0
- package/dist/service/config.js +265 -0
- package/dist/service/connection-stream.d.ts +10 -0
- package/dist/service/connection-stream.js +191 -0
- package/dist/service/connections.d.ts +60 -0
- package/dist/service/connections.js +271 -0
- package/dist/service/decisions.d.ts +35 -0
- package/dist/service/decisions.js +63 -0
- package/dist/service/descriptions.d.ts +8 -0
- package/dist/service/descriptions.js +20 -0
- package/dist/service/discovery-schemas.d.ts +92 -0
- package/dist/service/discovery-schemas.js +59 -0
- package/dist/service/discovery-search.d.ts +30 -0
- package/dist/service/discovery-search.js +95 -0
- package/dist/service/discovery.d.ts +37 -0
- package/dist/service/discovery.js +436 -0
- package/dist/service/docs.d.ts +9 -0
- package/dist/service/docs.js +197 -0
- package/dist/service/errors.d.ts +145 -0
- package/dist/service/errors.js +704 -0
- package/dist/service/federation-provider.d.ts +36 -0
- package/dist/service/federation-provider.js +110 -0
- package/dist/service/federation-server.d.ts +20 -0
- package/dist/service/federation-server.js +249 -0
- package/dist/service/federation-status.d.ts +40 -0
- package/dist/service/federation-status.js +151 -0
- package/dist/service/handlers.d.ts +18 -0
- package/dist/service/handlers.js +287 -0
- package/dist/service/mcp/confirmation.d.ts +68 -0
- package/dist/service/mcp/confirmation.js +178 -0
- package/dist/service/mcp/find-input.d.ts +12 -0
- package/dist/service/mcp/find-input.js +122 -0
- package/dist/service/mcp/input-schema.d.ts +6 -0
- package/dist/service/mcp/input-schema.js +126 -0
- package/dist/service/mcp/listing.d.ts +26 -0
- package/dist/service/mcp/listing.js +92 -0
- package/dist/service/mcp/metric-tools.d.ts +85 -0
- package/dist/service/mcp/metric-tools.js +258 -0
- package/dist/service/mcp/request-log.d.ts +5 -0
- package/dist/service/mcp/request-log.js +53 -0
- package/dist/service/mcp/runtime-policy.d.ts +27 -0
- package/dist/service/mcp/runtime-policy.js +62 -0
- package/dist/service/mcp/server.d.ts +52 -0
- package/dist/service/mcp/server.js +861 -0
- package/dist/service/mcp/tools.d.ts +99 -0
- package/dist/service/mcp/tools.js +938 -0
- package/dist/service/member-file-routes.d.ts +22 -0
- package/dist/service/member-file-routes.js +52 -0
- package/dist/service/member-files.d.ts +245 -0
- package/dist/service/member-files.js +258 -0
- package/dist/service/metric-query-platform.d.ts +77 -0
- package/dist/service/metric-query-platform.js +198 -0
- package/dist/service/metric-query-scopes.d.ts +43 -0
- package/dist/service/metric-query-scopes.js +147 -0
- package/dist/service/metric-query.d.ts +48 -0
- package/dist/service/metric-query.js +200 -0
- package/dist/service/name-suggestions.d.ts +3 -0
- package/dist/service/name-suggestions.js +38 -0
- package/dist/service/navigation-schemas.d.ts +80 -0
- package/dist/service/navigation-schemas.js +49 -0
- package/dist/service/navigation.d.ts +20 -0
- package/dist/service/navigation.js +165 -0
- package/dist/service/oauth/protocol.d.ts +70 -0
- package/dist/service/oauth/protocol.js +157 -0
- package/dist/service/oauth/refresh-replay.d.ts +2 -0
- package/dist/service/oauth/refresh-replay.js +20 -0
- package/dist/service/oauth/server.d.ts +28 -0
- package/dist/service/oauth/server.js +769 -0
- package/dist/service/operations.d.ts +170 -0
- package/dist/service/operations.js +392 -0
- package/dist/service/plan.d.ts +57 -0
- package/dist/service/plan.js +96 -0
- package/dist/service/rate-limit.d.ts +22 -0
- package/dist/service/rate-limit.js +52 -0
- package/dist/service/record-reads.d.ts +21 -0
- package/dist/service/record-reads.js +155 -0
- package/dist/service/replication.d.ts +5 -0
- package/dist/service/replication.js +39 -0
- package/dist/service/runtime-contract.d.ts +508 -0
- package/dist/service/runtime-contract.js +18 -0
- package/dist/service/runtime-identity.d.ts +71 -0
- package/dist/service/runtime-identity.js +122 -0
- package/dist/service/schemas.d.ts +961 -0
- package/dist/service/schemas.js +639 -0
- package/dist/service/service.d.ts +21 -0
- package/dist/service/service.js +526 -0
- package/dist/service/warehouse-platform.d.ts +17 -0
- package/dist/service/warehouse-platform.js +122 -0
- package/dist/service/warehouse-query.d.ts +24 -0
- package/dist/service/warehouse-query.js +280 -0
- package/dist/service/webhooks.d.ts +106 -0
- package/dist/service/webhooks.js +233 -0
- package/dist/service/workflow-admission-provider.d.ts +31 -0
- package/dist/service/workflow-admission-provider.js +205 -0
- package/dist/service/workflow-argument-serialization.d.ts +2 -0
- package/dist/service/workflow-argument-serialization.js +14 -0
- package/dist/service/workflow-callback.d.ts +22 -0
- package/dist/service/workflow-callback.js +75 -0
- package/dist/service/workflow-deployment.d.ts +8 -0
- package/dist/service/workflow-deployment.js +131 -0
- package/dist/service/workflow-diagnostics.d.ts +23 -0
- package/dist/service/workflow-diagnostics.js +263 -0
- package/dist/service/workflow-errors.d.ts +26 -0
- package/dist/service/workflow-errors.js +181 -0
- package/dist/service/workflow-logging.d.ts +2 -0
- package/dist/service/workflow-logging.js +50 -0
- package/dist/service/workflow-queue-fence.d.ts +6 -0
- package/dist/service/workflow-queue-fence.js +66 -0
- package/dist/service/workflows.d.ts +200 -0
- package/dist/service/workflows.js +1549 -0
- package/dist/sign-in.d.ts +58 -0
- package/dist/sign-in.js +57 -0
- package/dist/source.d.ts +30 -0
- package/dist/source.js +107 -0
- package/dist/start-recovery-contract.d.ts +49 -0
- package/dist/start-recovery-contract.js +26 -0
- package/dist/start-recovery.d.ts +27 -0
- package/dist/start-recovery.js +81 -0
- package/dist/storage/api.d.ts +4 -0
- package/dist/storage/api.js +40 -0
- package/dist/storage/attachments.d.ts +146 -0
- package/dist/storage/attachments.js +733 -0
- package/dist/storage/authorization.d.ts +38 -0
- package/dist/storage/authorization.js +83 -0
- package/dist/storage/file-access.d.ts +17 -0
- package/dist/storage/file-access.js +8 -0
- package/dist/storage/limits.d.ts +12 -0
- package/dist/storage/limits.js +17 -0
- package/dist/storage/maintenance-auth.d.ts +20 -0
- package/dist/storage/maintenance-auth.js +24 -0
- package/dist/storage/maintenance.d.ts +11 -0
- package/dist/storage/maintenance.js +67 -0
- package/dist/storage/neon.d.ts +4 -0
- package/dist/storage/neon.js +318 -0
- package/dist/storage/operator.d.ts +11 -0
- package/dist/storage/operator.js +30 -0
- package/dist/storage/provider.d.ts +93 -0
- package/dist/storage/provider.js +36 -0
- package/dist/storage/sessions.d.ts +184 -0
- package/dist/storage/sessions.js +688 -0
- package/dist/storage/tables.d.ts +54 -0
- package/dist/storage/tables.js +205 -0
- package/dist/storage/transfers.d.ts +16 -0
- package/dist/storage/transfers.js +153 -0
- package/dist/storage/writes.d.ts +7 -0
- package/dist/storage/writes.js +88 -0
- package/dist/telegram.d.ts +35 -0
- package/dist/telegram.js +173 -0
- package/dist/user-identity.d.ts +28 -0
- package/dist/user-identity.js +106 -0
- package/dist/user.d.ts +75 -0
- package/dist/user.js +111 -0
- package/dist/warehouse-backed.d.ts +6 -0
- package/dist/warehouse-backed.js +495 -0
- package/dist/webhook-token.d.ts +11 -0
- package/dist/webhook-token.js +18 -0
- package/dist/webhooks.d.ts +40 -0
- package/dist/webhooks.js +55 -0
- package/dist/wire.d.ts +10 -0
- package/dist/wire.js +35 -0
- package/dist/workflow-runtime.d.ts +116 -0
- package/dist/workflow-runtime.js +109 -0
- package/dist/workflow-topics.d.ts +28 -0
- package/dist/workflow-topics.js +28 -0
- package/dist/workflow.d.ts +284 -0
- package/dist/workflow.js +259 -0
- package/dist/workflows.d.ts +24 -0
- package/dist/workflows.js +18 -0
- package/package.json +127 -4
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { migratedReplicationIdentities, replicationIdentities } from "./identities.js";
|
|
2
|
+
import { prepareShadowEpoch, servingShadowEpoch, migrateShadowCapture, candidateShadowEpoch, shadowEpoch, shadowProjectionHash, enableShadowCapture, expandShadowRoutes, } from "./shadow.js";
|
|
3
|
+
import { Effect } from "effect";
|
|
4
|
+
import { historyTableName, quoteIdentifier as qi, tableName, joinTableName, columnName, } from "../migrate/storage.js";
|
|
5
|
+
import { queryFields } from "../query.js";
|
|
6
|
+
import { migratedReplicationLineage, renamedReplicationField } from "./lineage.js";
|
|
7
|
+
import { replicationScanScopes, scheduleReplicationScans, upgradeReplicationScans, reconcileReplicationScans, } from "./scans.js";
|
|
8
|
+
/** Freeze an import's source order before migrations change declaration order or storage names. */
|
|
9
|
+
export const prepareReplicationEvolution = (sql) => Effect.gen(function* () {
|
|
10
|
+
const targets = yield* sql.unsafe("SELECT * FROM _ontology_replication_targets");
|
|
11
|
+
for (const target of targets) {
|
|
12
|
+
if (target.backfill_complete === false && !target.backfill_sources) {
|
|
13
|
+
const sources = [
|
|
14
|
+
{ table: null },
|
|
15
|
+
...target.selection.map((item) => ({
|
|
16
|
+
table: historyTableName(target.manifest.entities.find((entity) => entity.id === item.entityId).name),
|
|
17
|
+
})),
|
|
18
|
+
];
|
|
19
|
+
yield* sql.unsafe("UPDATE _ontology_replication_targets SET backfill_sources = $2::jsonb WHERE generation = $1::uuid", [target.generation, JSON.stringify(sources)]);
|
|
20
|
+
}
|
|
21
|
+
yield* upgradeReplicationScans(sql, target);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
export function replicationRecoveryScopes(current, target, retained) {
|
|
25
|
+
const scopes = [];
|
|
26
|
+
const resets = [];
|
|
27
|
+
for (const next of target.selection) {
|
|
28
|
+
const previous = current.selection.find((item) => item.entityId === next.entityId);
|
|
29
|
+
const before = current.manifest.entities.find((entity) => entity.id === next.entityId);
|
|
30
|
+
const entity = target.manifest.entities.find((entity) => entity.id === next.entityId);
|
|
31
|
+
const kept = retained?.entities.find((entity) => entity.id === next.entityId);
|
|
32
|
+
if (!previous || !before) {
|
|
33
|
+
const all = replicationScanScopes({ selection: [next] });
|
|
34
|
+
scopes.push(...all);
|
|
35
|
+
resets.push(...all);
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
const previousFields = new Set(queryFields(before).map((field) => field.name));
|
|
39
|
+
const needsRecords = next.fields.some((field) => {
|
|
40
|
+
const old = renamedReplicationField(current.manifest, target.manifest, entity.id, field) ?? field;
|
|
41
|
+
return ((!previous.fields.includes(old) && previousFields.has(old)) ||
|
|
42
|
+
kept?.fields.properties.some((property) => property.name === field) ||
|
|
43
|
+
kept?.fields.relationships.some((relationship) => `${relationship.name}_id` === field));
|
|
44
|
+
});
|
|
45
|
+
if (needsRecords) {
|
|
46
|
+
scopes.push({ entityId: entity.id, kind: "entity" });
|
|
47
|
+
}
|
|
48
|
+
for (const name of next.relationships ?? []) {
|
|
49
|
+
if (!previous.relationships?.includes(name) ||
|
|
50
|
+
kept?.fields.relationships.some((relationship) => relationship.name === name)) {
|
|
51
|
+
const scope = { entityId: entity.id, kind: `edge:${name}` };
|
|
52
|
+
scopes.push(scope);
|
|
53
|
+
resets.push(scope);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return { scopes, resets };
|
|
58
|
+
}
|
|
59
|
+
export const refreshReplicationProjection = (sql, current, target, retained, options = {}) => Effect.gen(function* () {
|
|
60
|
+
const [version] = yield* sql.unsafe("SELECT version FROM _ontology_replication WHERE id");
|
|
61
|
+
if ((version?.version ?? 0) >= 6) {
|
|
62
|
+
target = { ...target, identities: migratedReplicationIdentities(current, target) };
|
|
63
|
+
if (!options.resuming && shadowProjectionHash(current) === shadowProjectionHash(target)) {
|
|
64
|
+
const [capture] = yield* sql.unsafe("SELECT capturing FROM _ontology_replication_targets WHERE generation=$1::uuid", [current.generation]);
|
|
65
|
+
if (!capture?.capturing) {
|
|
66
|
+
yield* enableShadowCapture(sql, current, replicationScanScopes(current));
|
|
67
|
+
}
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
yield* migrateShadowCapture(sql, current.manifest, target.manifest, target.selection, replicationIdentities(target));
|
|
71
|
+
const serving = yield* servingShadowEpoch(sql);
|
|
72
|
+
const pending = yield* candidateShadowEpoch(sql);
|
|
73
|
+
const previous = pending?.predecessor
|
|
74
|
+
? yield* shadowEpoch(sql, pending.predecessor)
|
|
75
|
+
: undefined;
|
|
76
|
+
// Only a recorded serving epoch (or its recorded predecessor) is publication evidence.
|
|
77
|
+
// An unfinished first scan is never coverage that another epoch may reuse.
|
|
78
|
+
const predecessor = serving ?? previous;
|
|
79
|
+
// Explicit resume must recover writes missed while capture was paused. Migration callers
|
|
80
|
+
// omit that intent: their transaction-local capture fence still permits scoped recovery.
|
|
81
|
+
const scopes = predecessor && !options.resuming
|
|
82
|
+
? replicationRecoveryScopes(predecessor.target, target, retained).scopes
|
|
83
|
+
: replicationScanScopes(target);
|
|
84
|
+
yield* prepareShadowEpoch(sql, {
|
|
85
|
+
target: { ...target, generation: crypto.randomUUID() },
|
|
86
|
+
affected: scopes,
|
|
87
|
+
predecessor,
|
|
88
|
+
});
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const [revision] = yield* sql.unsafe("SELECT (CASE WHEN is_called THEN last_value ELSE 0 END)::text AS revision FROM _ontology_replication_revision");
|
|
92
|
+
const { scopes, resets } = replicationRecoveryScopes(current, target, retained);
|
|
93
|
+
const lineage = migratedReplicationLineage(current, target, revision.revision, resets);
|
|
94
|
+
yield* sql.unsafe(`UPDATE _ontology_replication_targets SET manifest = $2::jsonb, selection = $3::jsonb,
|
|
95
|
+
fills = $4::jsonb, lineage = $5::jsonb WHERE generation = $1::uuid`, [
|
|
96
|
+
target.generation,
|
|
97
|
+
JSON.stringify(target.manifest),
|
|
98
|
+
JSON.stringify(target.selection),
|
|
99
|
+
JSON.stringify(target.fills ?? {}),
|
|
100
|
+
JSON.stringify(lineage),
|
|
101
|
+
]);
|
|
102
|
+
yield* reconcileReplicationScans(sql, target);
|
|
103
|
+
yield* scheduleReplicationScans(sql, target.generation, scopes, { reset: true });
|
|
104
|
+
});
|
|
105
|
+
/** Pending and replayable envelopes outlive storage explicitly dropped by a supported migration. */
|
|
106
|
+
export const retainReplicationHistory = (sql, table) => Effect.gen(function* () {
|
|
107
|
+
const [exists] = yield* sql.unsafe("SELECT to_regclass($1) IS NOT NULL AS present", [qi(table)]);
|
|
108
|
+
if (!exists?.present) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
// Imports may not yet have reached this history. Materialize only this affected history before
|
|
112
|
+
// its DROP, in the same transaction, retaining original IDs, revisions and acceptance receipts.
|
|
113
|
+
yield* sql.unsafe(`INSERT INTO _ontology_replication_delivery
|
|
114
|
+
(generation,event_id,history_table,revision,payload,accepted_at,verified_at)
|
|
115
|
+
SELECT t.generation,h.id,NULL,(h.replication->>'revision')::bigint,h.replication,r.accepted_at,r.verified_at
|
|
116
|
+
FROM _ontology_replication_targets t CROSS JOIN ${qi(table)} h
|
|
117
|
+
LEFT JOIN _ontology_replication_receipts r ON r.generation=t.generation AND r.event_id=h.id
|
|
118
|
+
WHERE NOT t.backfill_complete AND h.replication IS NOT NULL
|
|
119
|
+
AND h.replication->>'source_id'=t.source_id::text
|
|
120
|
+
AND (h.replication->>'revision')::bigint > t.from_revision
|
|
121
|
+
AND (h.replication->>'revision')::bigint <= t.backfill_revision
|
|
122
|
+
AND EXISTS (SELECT 1 FROM jsonb_array_elements(t.backfill_sources) s WHERE s->>'table'=$1)
|
|
123
|
+
ON CONFLICT DO NOTHING`, [table]);
|
|
124
|
+
yield* sql.unsafe(`UPDATE _ontology_replication_delivery d SET payload=h.replication, history_table=NULL
|
|
125
|
+
FROM ${qi(table)} h WHERE d.history_table=$1 AND d.event_id=h.id`, [table]);
|
|
126
|
+
yield* sql.unsafe(`UPDATE _ontology_replication_targets t SET backfill_sources=(
|
|
127
|
+
SELECT jsonb_agg(CASE WHEN s->>'table'=$1 THEN s || '{"skip":true}'::jsonb ELSE s END ORDER BY n)
|
|
128
|
+
FROM jsonb_array_elements(t.backfill_sources) WITH ORDINALITY AS item(s,n))
|
|
129
|
+
WHERE t.backfill_sources IS NOT NULL`, [table]);
|
|
130
|
+
});
|
|
131
|
+
export const renameReplicationHistory = (sql, previous, next) => Effect.gen(function* () {
|
|
132
|
+
yield* sql.unsafe("UPDATE _ontology_replication_delivery SET history_table=$2 WHERE history_table=$1", [previous, next]);
|
|
133
|
+
yield* sql.unsafe(`UPDATE _ontology_replication_targets t SET backfill_sources=(
|
|
134
|
+
SELECT jsonb_agg(CASE WHEN s->>'table'=$1 THEN jsonb_set(s,'{table}',to_jsonb($2::text)) ELSE s END ORDER BY n)
|
|
135
|
+
FROM jsonb_array_elements(t.backfill_sources) WITH ORDINALITY AS item(s,n))
|
|
136
|
+
WHERE t.backfill_sources IS NOT NULL`, [previous, next]);
|
|
137
|
+
});
|
|
138
|
+
/** Physical cleanup may proceed after cutover; only storage still needed by serving is protected. */
|
|
139
|
+
export const dropsServingReplicationStorage = (sql, input) => Effect.gen(function* () {
|
|
140
|
+
const destructive = input.steps.filter((step) => step.classification === "destructive");
|
|
141
|
+
if (!destructive.length) {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
const epochs = input.version >= 6
|
|
145
|
+
? yield* sql.unsafe(`SELECT target, routes FROM _ontology_replication_epochs WHERE state='serving'
|
|
146
|
+
OR (state='retired' AND retired_at IS NULL)`)
|
|
147
|
+
: [];
|
|
148
|
+
const routes = epochs.length
|
|
149
|
+
? epochs.flatMap((epoch) => expandShadowRoutes(epoch.routes, epoch.target))
|
|
150
|
+
: replicationScanScopes(input.target).map((scope) => ({ ...scope, target: input.target }));
|
|
151
|
+
const captures = input.version >= 6
|
|
152
|
+
? yield* sql.unsafe("SELECT generation::text,capture_bindings FROM _ontology_replication_targets WHERE capturing")
|
|
153
|
+
: [];
|
|
154
|
+
const statements = destructive
|
|
155
|
+
.flatMap((step) => step.sql)
|
|
156
|
+
.map((statement) => statement.replace(/\s+/g, " "));
|
|
157
|
+
for (const route of routes) {
|
|
158
|
+
const entity = route.target.manifest.entities.find((entity) => entity.id === route.entityId);
|
|
159
|
+
const name = input.current.entities.find((item) => item.id === entity.id)?.name ??
|
|
160
|
+
input.retained?.entities.find((item) => item.id === entity.id)?.name ??
|
|
161
|
+
entity.name;
|
|
162
|
+
const table = route.kind === "entity" ? tableName(name) : joinTableName(name, route.kind.slice(5));
|
|
163
|
+
if (statements.some((statement) => statement.includes(`DROP TABLE ${qi(table)}`))) {
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
if (route.kind !== "entity") {
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
const selection = route.target.selection.find((item) => item.entityId === entity.id);
|
|
170
|
+
const bindings = captures.find((capture) => capture.generation === route.target.generation)
|
|
171
|
+
?.capture_bindings?.[entity.id];
|
|
172
|
+
const fields = route.target.lineage?.epochs.at(-1)?.fields[entity.id];
|
|
173
|
+
for (const field of selection.fields) {
|
|
174
|
+
const slot = fields?.[field]?.key ?? field;
|
|
175
|
+
const current = bindings?.[slot] ?? field;
|
|
176
|
+
const column = columnName(current);
|
|
177
|
+
if (statements.some((statement) => statement.includes(`ALTER TABLE ${qi(table)} `) &&
|
|
178
|
+
statement.includes(`DROP COLUMN ${qi(column)}`))) {
|
|
179
|
+
return true;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return false;
|
|
184
|
+
});
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ReplicationTarget } from "./baseline.js";
|
|
2
|
+
/** Logical field identities survive renames and copies, but never transfer to a reused name. */
|
|
3
|
+
export type ReplicationIdentities = Readonly<Record<string, Readonly<Record<string, string>>>>;
|
|
4
|
+
export declare function replicationIdentities(target: ReplicationTarget): ReplicationIdentities;
|
|
5
|
+
export declare function migratedReplicationIdentities(current: ReplicationTarget, target: ReplicationTarget): ReplicationIdentities;
|
|
6
|
+
export declare function permittedReplicationField(actual: ReplicationTarget, policy: ReplicationTarget, entity: string, field: string): boolean;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { queryFields } from "../query.js";
|
|
3
|
+
import { renamedReplicationField } from "./lineage.js";
|
|
4
|
+
export function replicationIdentities(target) {
|
|
5
|
+
return (target.identities ??
|
|
6
|
+
Object.fromEntries(target.manifest.entities.map((entity) => [
|
|
7
|
+
entity.id,
|
|
8
|
+
Object.fromEntries([
|
|
9
|
+
...queryFields(entity).map((field) => field.name),
|
|
10
|
+
...entity.relationships
|
|
11
|
+
.filter((relationship) => relationship.cardinality === "many")
|
|
12
|
+
.map((relationship) => `edge:${relationship.name}`),
|
|
13
|
+
].map((field) => [
|
|
14
|
+
field,
|
|
15
|
+
createHash("sha256")
|
|
16
|
+
.update(`${target.source_id}:${target.generation}:${target.manifest.hash}:${entity.id}:${field}`)
|
|
17
|
+
.digest("hex"),
|
|
18
|
+
])),
|
|
19
|
+
])));
|
|
20
|
+
}
|
|
21
|
+
export function migratedReplicationIdentities(current, target) {
|
|
22
|
+
const previous = replicationIdentities(current);
|
|
23
|
+
const initial = replicationIdentities({ ...target, identities: undefined });
|
|
24
|
+
return Object.fromEntries(Object.entries(initial).map(([entityId, fields]) => [
|
|
25
|
+
entityId,
|
|
26
|
+
Object.fromEntries(Object.entries(fields).map(([field, identity]) => {
|
|
27
|
+
const old = renamedReplicationField(current.manifest, target.manifest, entityId, field) ?? field;
|
|
28
|
+
return [field, previous[entityId]?.[old] ?? identity];
|
|
29
|
+
})),
|
|
30
|
+
]));
|
|
31
|
+
}
|
|
32
|
+
export function permittedReplicationField(actual, policy, entity, field) {
|
|
33
|
+
const selected = policy.selection.find((item) => item.entityId === entity);
|
|
34
|
+
const actualIdentity = replicationIdentities(actual)[entity]?.[field];
|
|
35
|
+
if (!selected || !actualIdentity) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
const identities = replicationIdentities(policy)[entity] ?? {};
|
|
39
|
+
const permitted = field.startsWith("edge:")
|
|
40
|
+
? (selected.relationships ?? []).map((name) => `edge:${name}`)
|
|
41
|
+
: ["id", ...selected.fields];
|
|
42
|
+
// When the public name still exists, it must denote this exact identity. Only an absent old name
|
|
43
|
+
// may remain a compatibility alias for a permitted renamed property.
|
|
44
|
+
return identities[field] !== undefined
|
|
45
|
+
? permitted.includes(field) && identities[field] === actualIdentity
|
|
46
|
+
: permitted.some((name) => identities[name] === actualIdentity);
|
|
47
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Effect, Schema } from "effect";
|
|
2
|
+
import type { SqlClient } from "effect/unstable/sql";
|
|
3
|
+
import type { OntologyManifest } from "../manifest.js";
|
|
4
|
+
import { type ReplicationSelection, type ReplicationExclusion } from "./model.js";
|
|
5
|
+
export interface ReplicationTarget {
|
|
6
|
+
readonly generation: string;
|
|
7
|
+
readonly source_id: string;
|
|
8
|
+
readonly from_revision: string;
|
|
9
|
+
readonly manifest: OntologyManifest;
|
|
10
|
+
readonly selection: ReadonlyArray<ReplicationSelection>;
|
|
11
|
+
}
|
|
12
|
+
declare const ReplicationBaselineFailed_base: Schema.Class<ReplicationBaselineFailed, Schema.TaggedStruct<"ReplicationBaselineFailed", {
|
|
13
|
+
readonly message: Schema.String;
|
|
14
|
+
readonly cause: Schema.optionalKey<Schema.Unknown>;
|
|
15
|
+
}>, import("effect/Cause").YieldableError>;
|
|
16
|
+
/** An initial snapshot cannot be created with the requested state or record projection. */
|
|
17
|
+
export declare class ReplicationBaselineFailed extends ReplicationBaselineFailed_base {
|
|
18
|
+
}
|
|
19
|
+
/** Legacy snapshots commit with enablement; an upgraded protocol uses resumable online pages. */
|
|
20
|
+
export declare const createReplicationBaseline: (sql: SqlClient.SqlClient, input: {
|
|
21
|
+
readonly generation: string;
|
|
22
|
+
readonly manifest: OntologyManifest;
|
|
23
|
+
readonly exclusions?: ReadonlyArray<ReplicationExclusion>;
|
|
24
|
+
readonly selection: ReadonlyArray<ReplicationSelection>;
|
|
25
|
+
readonly newSource?: boolean;
|
|
26
|
+
}) => Effect.Effect<ReplicationTarget, import("effect/unstable/sql/SqlError").SqlError | import("./baseline.js").ReplicationBaselineFailed | ReplicationBaselineFailed, never>;
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { Effect, Schema } from "effect";
|
|
3
|
+
import { joinColumnNames, joinTableName, quoteIdentifier as qi, quoteLiteral as ql, tableName, } from "../migrate/storage.js";
|
|
4
|
+
import { REPLICATION_RECORD_BYTES, validateReplicationSelection, } from "./model.js";
|
|
5
|
+
import { snapshotExpression } from "./schema.js";
|
|
6
|
+
import { createReplicationBaseline as createCurrentBaseline } from "./baseline.js";
|
|
7
|
+
import { lockReplicationLifecycle } from "./transaction.js";
|
|
8
|
+
/** An initial snapshot cannot be created with the requested state or record projection. */
|
|
9
|
+
export class ReplicationBaselineFailed extends Schema.TaggedError()("ReplicationBaselineFailed", { message: Schema.String, cause: Schema.optionalKey(Schema.Unknown) }) {
|
|
10
|
+
}
|
|
11
|
+
// @legacy ontology.replication-older-source-protocols
|
|
12
|
+
/** Legacy snapshots commit with enablement; an upgraded protocol uses resumable online pages. */
|
|
13
|
+
export const createReplicationBaseline = (sql, input) => sql.withTransaction(Effect.gen(function* () {
|
|
14
|
+
yield* sql.unsafe("SET LOCAL statement_timeout = '30s'");
|
|
15
|
+
yield* sql.unsafe("SET LOCAL lock_timeout = '5s'");
|
|
16
|
+
yield* lockReplicationLifecycle(sql);
|
|
17
|
+
const [state] = yield* sql.unsafe("SELECT source_id::text, revision::text, enabled, version FROM _ontology_replication WHERE id");
|
|
18
|
+
if (!state) {
|
|
19
|
+
return yield* new ReplicationBaselineFailed({
|
|
20
|
+
message: "Run the ontology SDK migration before enabling replication.",
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
// Protocol dispatch happened outside this transaction; a migration may have upgraded it.
|
|
24
|
+
if (state.version >= 4) {
|
|
25
|
+
return yield* createCurrentBaseline(sql, input);
|
|
26
|
+
}
|
|
27
|
+
const existing = yield* sql.unsafe("SELECT * FROM _ontology_replication_targets WHERE generation = $1::uuid", [input.generation]);
|
|
28
|
+
if (existing[0]) {
|
|
29
|
+
return existing[0];
|
|
30
|
+
}
|
|
31
|
+
const manifest = input.manifest;
|
|
32
|
+
yield* Effect.try({
|
|
33
|
+
try: () => validateReplicationSelection(manifest, input.selection),
|
|
34
|
+
catch: (cause) => new ReplicationBaselineFailed({ message: "Invalid replication projection.", cause }),
|
|
35
|
+
});
|
|
36
|
+
// Drain older SDK transactions that started before the compatibility fence was enabled.
|
|
37
|
+
const tables = manifest.entities
|
|
38
|
+
.filter((e) => e.source === undefined && !e.builtIn)
|
|
39
|
+
.flatMap((e) => [
|
|
40
|
+
tableName(e.name),
|
|
41
|
+
...e.relationships
|
|
42
|
+
.filter((r) => r.cardinality === "many")
|
|
43
|
+
.map((r) => joinTableName(e.name, r.name)),
|
|
44
|
+
]);
|
|
45
|
+
if (tables.length > 0) {
|
|
46
|
+
yield* sql.unsafe(`LOCK TABLE ${tables.map(qi).join(", ")} IN SHARE MODE`);
|
|
47
|
+
}
|
|
48
|
+
const source = input.newSource ? randomUUID() : state.source_id;
|
|
49
|
+
const selection = Object.fromEntries(input.selection.map((s) => [s.entityId, s]));
|
|
50
|
+
yield* sql.unsafe(`UPDATE _ontology_replication SET source_id = $1::uuid, selection = $2::jsonb, enabled = true,
|
|
51
|
+
exclusions = $3::jsonb, active_generation = $4::uuid WHERE id`, [
|
|
52
|
+
source,
|
|
53
|
+
JSON.stringify(selection),
|
|
54
|
+
JSON.stringify(input.exclusions ?? []),
|
|
55
|
+
input.generation,
|
|
56
|
+
]);
|
|
57
|
+
const target = {
|
|
58
|
+
generation: input.generation,
|
|
59
|
+
source_id: source,
|
|
60
|
+
from_revision: state.revision,
|
|
61
|
+
manifest,
|
|
62
|
+
selection: input.selection,
|
|
63
|
+
};
|
|
64
|
+
yield* sql.unsafe(`INSERT INTO _ontology_replication_targets (generation, source_id, from_revision, manifest, selection)
|
|
65
|
+
VALUES ($1::uuid, $2::uuid, $3::bigint, $4::jsonb, $5::jsonb)`, [
|
|
66
|
+
target.generation,
|
|
67
|
+
source,
|
|
68
|
+
state.revision,
|
|
69
|
+
JSON.stringify(manifest),
|
|
70
|
+
JSON.stringify(input.selection),
|
|
71
|
+
]);
|
|
72
|
+
const baseline = (entityId, kind, records) => Effect.gen(function* () {
|
|
73
|
+
// Keep the snapshot in PostgreSQL; large baselines must not fill a serverless process's heap.
|
|
74
|
+
const [size] = yield* sql.unsafe(`SELECT EXISTS (
|
|
75
|
+
SELECT 1 FROM (${records}) snapshot
|
|
76
|
+
WHERE octet_length(payload::text) > ${REPLICATION_RECORD_BYTES}
|
|
77
|
+
) AS oversized`);
|
|
78
|
+
if (size.oversized) {
|
|
79
|
+
return yield* new ReplicationBaselineFailed({
|
|
80
|
+
message: `A projected baseline record exceeds ${REPLICATION_RECORD_BYTES} bytes; ` +
|
|
81
|
+
"exclude large fields before enabling replication.",
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
yield* sql.unsafe(`INSERT INTO _ontology_replication_baselines (generation, event)
|
|
85
|
+
SELECT $1::uuid, jsonb_build_object('source_id', $2::text, 'entity_id', $3::text,
|
|
86
|
+
'record_key', record_key, 'record_kind', $4::text, 'revision', $5::text,
|
|
87
|
+
'deleted', false, 'schema_hash', $6::text, 'payload', payload::text)
|
|
88
|
+
FROM (${records}) snapshot`, [target.generation, source, entityId, kind, state.revision, manifest.hash]);
|
|
89
|
+
});
|
|
90
|
+
for (const item of input.selection) {
|
|
91
|
+
const entity = manifest.entities.find((e) => e.id === item.entityId);
|
|
92
|
+
yield* baseline(entity.id, "entity", `SELECT r.id::text AS record_key,
|
|
93
|
+
(SELECT jsonb_object_agg(key, value) FROM jsonb_each(${snapshotExpression(entity, "r")})
|
|
94
|
+
WHERE key = 'id' OR ${ql(JSON.stringify(item.fields))}::jsonb ? key) AS payload
|
|
95
|
+
FROM ${qi(tableName(entity.name))} r`);
|
|
96
|
+
for (const relationship of entity.relationships.filter((r) => item.relationships?.includes(r.name))) {
|
|
97
|
+
const columns = joinColumnNames({
|
|
98
|
+
entity: entity.name,
|
|
99
|
+
relationship: relationship.name,
|
|
100
|
+
target: relationship.to,
|
|
101
|
+
});
|
|
102
|
+
yield* baseline(entity.id, `edge:${relationship.name}`, `SELECT ${qi(columns.source)}::text || ':' || ${qi(columns.target)}::text AS record_key,
|
|
103
|
+
jsonb_build_object('source_id', ${qi(columns.source)}::text,
|
|
104
|
+
'target_id', ${qi(columns.target)}::text) AS payload
|
|
105
|
+
FROM ${qi(joinTableName(entity.name, relationship.name))}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return target;
|
|
109
|
+
}));
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import type { SqlClient } from "effect/unstable/sql";
|
|
3
|
+
import { type ReplicationEvent } from "./model.js";
|
|
4
|
+
import type { ReplicationTarget } from "./baseline.js";
|
|
5
|
+
/** No timestamp/high-water cursor: every unacknowledged immutable event remains discoverable. */
|
|
6
|
+
export declare function replicationEventsSql(target: ReplicationTarget): string;
|
|
7
|
+
export declare const pendingReplicationEvents: (sql: SqlClient.SqlClient, target: ReplicationTarget) => Effect.Effect<{
|
|
8
|
+
readonly historyId: string;
|
|
9
|
+
readonly event: ReplicationEvent;
|
|
10
|
+
}[], import("effect/unstable/sql/SqlError").SqlError, never>;
|
|
11
|
+
/** Call only after Pub/Sub accepts the complete batch. Lost responses deliberately produce duplicates. */
|
|
12
|
+
export declare const acknowledgeReplication: (sql: SqlClient.SqlClient, generation: string, ids: ReadonlyArray<string>) => import("effect/unstable/sql/Statement").Statement<object>;
|
|
13
|
+
export declare const replayReplication: (sql: SqlClient.SqlClient, generation: string) => import("effect/unstable/sql/Statement").Statement<object>;
|
|
14
|
+
export declare const replicationStatus: (sql: SqlClient.SqlClient, target: ReplicationTarget) => Effect.Effect<{
|
|
15
|
+
total: string;
|
|
16
|
+
accepted: string;
|
|
17
|
+
}, import("effect/unstable/sql/SqlError").SqlError, never>;
|
|
18
|
+
/** Legacy writers serialize their revisions; the platform persists this fixed upper boundary. */
|
|
19
|
+
export declare const replicationInitiallyReady: (sql: SqlClient.SqlClient, target: ReplicationTarget, initialRevision: string) => Effect.Effect<boolean, import("effect/unstable/sql/SqlError").SqlError, never>;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { historyTableName, quoteIdentifier as qi } from "../migrate/storage.js";
|
|
3
|
+
import { REPLICATION_BATCH_BYTES, REPLICATION_BATCH_SIZE, publishMessage, replicationEventId, } from "./model.js";
|
|
4
|
+
/** No timestamp/high-water cursor: every unacknowledged immutable event remains discoverable. */
|
|
5
|
+
export function replicationEventsSql(target) {
|
|
6
|
+
const histories = target.selection.map((item) => {
|
|
7
|
+
const entity = target.manifest.entities.find((e) => e.id === item.entityId);
|
|
8
|
+
return `SELECT id, replication AS event FROM ${qi(historyTableName(entity.name))}
|
|
9
|
+
WHERE replication IS NOT NULL AND replication->>'source_id' = $2
|
|
10
|
+
AND (replication->>'revision')::bigint > $3::bigint`;
|
|
11
|
+
});
|
|
12
|
+
const baseline = `SELECT id, event FROM _ontology_replication_baselines WHERE generation = $1::uuid
|
|
13
|
+
AND $2::text IS NOT NULL AND $3::bigint IS NOT NULL`;
|
|
14
|
+
return [baseline, ...histories].join(" UNION ALL ");
|
|
15
|
+
}
|
|
16
|
+
export const pendingReplicationEvents = (sql, target) => sql
|
|
17
|
+
.unsafe(`SELECT e.id::text, e.event FROM (${replicationEventsSql(target)}) e
|
|
18
|
+
WHERE NOT EXISTS (SELECT 1 FROM _ontology_replication_receipts r
|
|
19
|
+
WHERE r.generation = $1::uuid AND r.event_id = e.id)
|
|
20
|
+
ORDER BY (event->>'revision')::bigint, id LIMIT ${REPLICATION_BATCH_SIZE}`, [target.generation, target.source_id, target.from_revision])
|
|
21
|
+
.pipe(Effect.map((rows) => {
|
|
22
|
+
let size = 32;
|
|
23
|
+
const result = [];
|
|
24
|
+
for (const row of rows) {
|
|
25
|
+
const event = {
|
|
26
|
+
...row.event,
|
|
27
|
+
generation: target.generation,
|
|
28
|
+
event_id: replicationEventId(target.source_id, row.id, target.generation),
|
|
29
|
+
};
|
|
30
|
+
const bytes = Buffer.byteLength(JSON.stringify(publishMessage(event))) + 1;
|
|
31
|
+
if (bytes + 32 > REPLICATION_BATCH_BYTES) {
|
|
32
|
+
throw new Error("A replication event exceeds the publish request limit.");
|
|
33
|
+
}
|
|
34
|
+
if (size + bytes > REPLICATION_BATCH_BYTES) {
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
size += bytes;
|
|
38
|
+
result.push({ historyId: row.id, event });
|
|
39
|
+
}
|
|
40
|
+
return result;
|
|
41
|
+
}));
|
|
42
|
+
/** Call only after Pub/Sub accepts the complete batch. Lost responses deliberately produce duplicates. */
|
|
43
|
+
export const acknowledgeReplication = (sql, generation, ids) => sql.unsafe(`INSERT INTO _ontology_replication_receipts (generation, event_id)
|
|
44
|
+
SELECT $1::uuid, value::uuid FROM jsonb_array_elements_text($2::jsonb) ON CONFLICT DO NOTHING`, [generation, JSON.stringify(ids)]);
|
|
45
|
+
export const replayReplication = (sql, generation) => sql.unsafe("DELETE FROM _ontology_replication_receipts WHERE generation = $1::uuid", [
|
|
46
|
+
generation,
|
|
47
|
+
]);
|
|
48
|
+
export const replicationStatus = (sql, target) => sql
|
|
49
|
+
.unsafe(`SELECT count(*)::text AS total, count(r.event_id)::text AS accepted
|
|
50
|
+
FROM (${replicationEventsSql(target)}) e
|
|
51
|
+
LEFT JOIN _ontology_replication_receipts r ON r.generation = $1::uuid AND r.event_id = e.id`, [target.generation, target.source_id, target.from_revision])
|
|
52
|
+
.pipe(Effect.map((rows) => rows[0]));
|
|
53
|
+
// @legacy ontology.replication-older-source-protocols
|
|
54
|
+
/** Legacy writers serialize their revisions; the platform persists this fixed upper boundary. */
|
|
55
|
+
export const replicationInitiallyReady = (sql, target, initialRevision) => sql
|
|
56
|
+
.unsafe(`SELECT NOT EXISTS (
|
|
57
|
+
SELECT 1 FROM (${replicationEventsSql(target)}) e
|
|
58
|
+
WHERE (e.event->>'revision')::bigint <= $4::bigint AND NOT EXISTS (
|
|
59
|
+
SELECT 1 FROM _ontology_replication_receipts r
|
|
60
|
+
WHERE r.generation = $1::uuid AND r.event_id = e.id
|
|
61
|
+
)
|
|
62
|
+
) AS ready`, [target.generation, target.source_id, target.from_revision, initialRevision])
|
|
63
|
+
.pipe(Effect.map((rows) => rows[0].ready));
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { OntologyManifest } from "../manifest.js";
|
|
2
|
+
import type { ReplicationFills, ReplicationSelection } from "./model.js";
|
|
3
|
+
/** One logical property's representation in a captured schema. A missing key is not JSON null. */
|
|
4
|
+
export interface ReplicationFieldBinding {
|
|
5
|
+
readonly key: string | null;
|
|
6
|
+
readonly fill?: unknown;
|
|
7
|
+
}
|
|
8
|
+
export interface ReplicationProjectionEpoch {
|
|
9
|
+
readonly schemaHash: string;
|
|
10
|
+
/** Inclusive, fixed while lifecycle admission drains all earlier writers. */
|
|
11
|
+
readonly throughRevision?: string;
|
|
12
|
+
readonly fields: Readonly<Record<string, Readonly<Record<string, ReplicationFieldBinding>>>>;
|
|
13
|
+
}
|
|
14
|
+
export interface ReplicationLineage {
|
|
15
|
+
readonly epochs: ReadonlyArray<ReplicationProjectionEpoch>;
|
|
16
|
+
/** Earlier incarnations of re-included records/edges must not resurrect after a scoped scan. */
|
|
17
|
+
readonly minimumRevisions: Readonly<Record<string, Readonly<Record<string, string>>>>;
|
|
18
|
+
}
|
|
19
|
+
interface Projection {
|
|
20
|
+
readonly manifest: OntologyManifest;
|
|
21
|
+
readonly selection: ReadonlyArray<ReplicationSelection>;
|
|
22
|
+
readonly fills?: ReplicationFills;
|
|
23
|
+
readonly lineage?: ReplicationLineage | null;
|
|
24
|
+
}
|
|
25
|
+
export declare function renamedReplicationField(current: OntologyManifest, target: OntologyManifest, entityId: string, field: string): string | undefined;
|
|
26
|
+
export declare function initialReplicationLineage(projection: Projection): ReplicationLineage;
|
|
27
|
+
/**
|
|
28
|
+
* Rewrite historical bindings, never historical events. Revision intervals disambiguate a schema
|
|
29
|
+
* hash used again after a rollback or a name reused for a different property. Hashes record the
|
|
30
|
+
* schema at each boundary; migrations with identical wire fields need no different expression.
|
|
31
|
+
*/
|
|
32
|
+
export declare function migratedReplicationLineage(current: Projection, target: Projection, throughRevision: string, resetScopes?: ReadonlyArray<{
|
|
33
|
+
readonly entityId: string;
|
|
34
|
+
readonly kind: string;
|
|
35
|
+
}>): ReplicationLineage;
|
|
36
|
+
export {};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { toSnakeCase } from "../names.js";
|
|
2
|
+
const fieldsWithId = (fields) => fields.includes("id") ? fields : ["id", ...fields];
|
|
3
|
+
export function renamedReplicationField(current, target, entityId, field) {
|
|
4
|
+
const previous = current.entities.find((entity) => entity.id === entityId);
|
|
5
|
+
const property = target.entities
|
|
6
|
+
.find((entity) => entity.id === entityId)
|
|
7
|
+
?.properties.find((property) => property.name === field);
|
|
8
|
+
const old = property?.renamedFrom;
|
|
9
|
+
// `renamedFrom` can remain in a manifest after the migration already renamed its storage.
|
|
10
|
+
if (!old || previous?.properties.some((property) => property.name === field)) {
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
return previous?.properties.find((property) => property.name === old || property.name === toSnakeCase(old))?.name;
|
|
14
|
+
}
|
|
15
|
+
export function initialReplicationLineage(projection) {
|
|
16
|
+
return {
|
|
17
|
+
epochs: [
|
|
18
|
+
{
|
|
19
|
+
schemaHash: projection.manifest.hash,
|
|
20
|
+
fields: Object.fromEntries(projection.selection.map((entity) => [
|
|
21
|
+
entity.entityId,
|
|
22
|
+
Object.fromEntries(fieldsWithId(entity.fields).map((field) => [
|
|
23
|
+
field,
|
|
24
|
+
{
|
|
25
|
+
key: field,
|
|
26
|
+
...(Object.hasOwn(projection.fills?.[entity.entityId] ?? {}, field)
|
|
27
|
+
? { fill: projection.fills[entity.entityId][field] }
|
|
28
|
+
: {}),
|
|
29
|
+
},
|
|
30
|
+
])),
|
|
31
|
+
])),
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
minimumRevisions: {},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Rewrite historical bindings, never historical events. Revision intervals disambiguate a schema
|
|
39
|
+
* hash used again after a rollback or a name reused for a different property. Hashes record the
|
|
40
|
+
* schema at each boundary; migrations with identical wire fields need no different expression.
|
|
41
|
+
*/
|
|
42
|
+
export function migratedReplicationLineage(current, target, throughRevision, resetScopes = []) {
|
|
43
|
+
const lineage = current.lineage ?? initialReplicationLineage(current);
|
|
44
|
+
const epochs = lineage.epochs.map((epoch) => ({
|
|
45
|
+
schemaHash: epoch.schemaHash,
|
|
46
|
+
throughRevision: epoch.throughRevision ?? throughRevision,
|
|
47
|
+
fields: Object.fromEntries(target.selection.map((next) => {
|
|
48
|
+
const previous = current.selection.find((entity) => entity.entityId === next.entityId);
|
|
49
|
+
const bindings = Object.fromEntries(fieldsWithId(next.fields).map((field) => {
|
|
50
|
+
const old = renamedReplicationField(current.manifest, target.manifest, next.entityId, field) ??
|
|
51
|
+
field;
|
|
52
|
+
const captured = previous !== undefined && (old === "id" || previous.fields.includes(old));
|
|
53
|
+
const binding = captured ? epoch.fields[next.entityId]?.[old] : undefined;
|
|
54
|
+
const fill = target.fills?.[next.entityId];
|
|
55
|
+
return [
|
|
56
|
+
field,
|
|
57
|
+
binding ?? {
|
|
58
|
+
key: null,
|
|
59
|
+
...(Object.hasOwn(fill ?? {}, field) ? { fill: fill[field] } : {}),
|
|
60
|
+
},
|
|
61
|
+
];
|
|
62
|
+
}));
|
|
63
|
+
return [next.entityId, bindings];
|
|
64
|
+
})),
|
|
65
|
+
}));
|
|
66
|
+
const next = initialReplicationLineage(target).epochs[0];
|
|
67
|
+
const minimumRevisions = Object.fromEntries(Object.entries(lineage.minimumRevisions).map(([entity, kinds]) => [entity, { ...kinds }]));
|
|
68
|
+
for (const scope of resetScopes) {
|
|
69
|
+
(minimumRevisions[scope.entityId] ??= {})[scope.kind] = throughRevision;
|
|
70
|
+
}
|
|
71
|
+
return { epochs: [...epochs, next], minimumRevisions };
|
|
72
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import type { SqlClient } from "effect/unstable/sql";
|
|
3
|
+
import type { OntologyManifest } from "../manifest.js";
|
|
4
|
+
import type { RetainedStorage } from "../migrate/model.js";
|
|
5
|
+
import type { ReplicationTarget } from "./baseline.js";
|
|
6
|
+
import { type ReplicationExclusion, type ReplicationSelection } from "./model.js";
|
|
7
|
+
/** Persist exclusions across temporary removals, and follow a property's logical rename. */
|
|
8
|
+
export declare function migrationReplicationExclusions(current: OntologyManifest, target: OntologyManifest, exclusions: ReadonlyArray<ReplicationExclusion>): ReadonlyArray<ReplicationExclusion>;
|
|
9
|
+
/** Only current declarations participate; retained exclusions still protect a later restoration. */
|
|
10
|
+
export declare function effectiveReplicationExclusions(manifest: OntologyManifest, exclusions: readonly ReplicationExclusion[]): {
|
|
11
|
+
relationships?: ReadonlyArray<string>;
|
|
12
|
+
fields?: ReadonlyArray<string>;
|
|
13
|
+
entityId: string;
|
|
14
|
+
disabled?: boolean;
|
|
15
|
+
}[];
|
|
16
|
+
/**
|
|
17
|
+
* Fills of the migrated target, read inside the migration transaction after its steps. PostgreSQL gives
|
|
18
|
+
* a field added to an existing entity one value on every row, so any row shows it as capture would
|
|
19
|
+
* serialize it. A null value needs no fill: a missing key already reads as null.
|
|
20
|
+
*/
|
|
21
|
+
export declare const migratedReplicationFills: (sql: SqlClient.SqlClient, current: ReplicationTarget, manifest: OntologyManifest, selection: ReadonlyArray<ReplicationSelection>, retained?: RetainedStorage) => Effect.Effect<Readonly<Record<string, Readonly<Record<string, unknown>>>>, import("effect/unstable/sql/SqlError").SqlError, never>;
|