@rikalabs/akter 0.1.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/LICENSE +202 -0
- package/NOTICE +8 -0
- package/README.md +116 -0
- package/dist/actor/codecs.d.ts +77 -0
- package/dist/actor/codecs.js +87 -0
- package/dist/actor/connections.d.ts +34 -0
- package/dist/actor/connections.js +145 -0
- package/dist/actor/definition.d.ts +893 -0
- package/dist/actor/definition.js +147 -0
- package/dist/actor/descriptor.d.ts +172 -0
- package/dist/actor/descriptor.js +367 -0
- package/dist/actor/handles.d.ts +77 -0
- package/dist/actor/handles.js +265 -0
- package/dist/actor/jobs.d.ts +10 -0
- package/dist/actor/jobs.js +137 -0
- package/dist/actor/layers.d.ts +41 -0
- package/dist/actor/layers.js +177 -0
- package/dist/actor/reads.d.ts +47 -0
- package/dist/actor/reads.js +224 -0
- package/dist/actor/served.d.ts +120 -0
- package/dist/actor/served.js +72 -0
- package/dist/actor/turns.d.ts +13 -0
- package/dist/actor/turns.js +332 -0
- package/dist/actor/workflows.d.ts +16 -0
- package/dist/actor/workflows.js +37 -0
- package/dist/client/calls.d.ts +47 -0
- package/dist/client/calls.js +425 -0
- package/dist/client/clock.d.ts +56 -0
- package/dist/client/clock.js +119 -0
- package/dist/client/fleet-page.d.ts +15 -0
- package/dist/client/fleet-page.js +13 -0
- package/dist/client/fleet.d.ts +29 -0
- package/dist/client/fleet.js +51 -0
- package/dist/client/index.d.ts +17 -0
- package/dist/client/index.js +6 -0
- package/dist/client/make.d.ts +157 -0
- package/dist/client/make.js +221 -0
- package/dist/client/offline/queue.d.ts +118 -0
- package/dist/client/offline/queue.js +292 -0
- package/dist/client/offline/store.d.ts +74 -0
- package/dist/client/offline/store.js +78 -0
- package/dist/client/optimistic.d.ts +57 -0
- package/dist/client/optimistic.js +136 -0
- package/dist/client/report.d.ts +2 -0
- package/dist/client/report.js +8 -0
- package/dist/client/sessions/connection.d.ts +118 -0
- package/dist/client/sessions/connection.js +162 -0
- package/dist/client/sessions/feed.d.ts +42 -0
- package/dist/client/sessions/feed.js +43 -0
- package/dist/client/sessions/sse.d.ts +47 -0
- package/dist/client/sessions/sse.js +112 -0
- package/dist/client/sessions/stream.d.ts +28 -0
- package/dist/client/sessions/stream.js +35 -0
- package/dist/client/sessions/watch.d.ts +34 -0
- package/dist/client/sessions/watch.js +40 -0
- package/dist/client/transport.d.ts +37 -0
- package/dist/client/transport.js +66 -0
- package/dist/contexts/command.d.ts +132 -0
- package/dist/contexts/command.js +20 -0
- package/dist/contexts/connection.d.ts +68 -0
- package/dist/contexts/connection.js +0 -0
- package/dist/contexts/job.d.ts +49 -0
- package/dist/contexts/job.js +0 -0
- package/dist/contexts/workflow.d.ts +147 -0
- package/dist/contexts/workflow.js +22 -0
- package/dist/errors/actor.d.ts +200 -0
- package/dist/errors/actor.js +271 -0
- package/dist/errors/content.d.ts +19 -0
- package/dist/errors/content.js +14 -0
- package/dist/errors/database.d.ts +22 -0
- package/dist/errors/database.js +23 -0
- package/dist/errors/events.d.ts +17 -0
- package/dist/errors/events.js +14 -0
- package/dist/errors/subscription.d.ts +12 -0
- package/dist/errors/subscription.js +8 -0
- package/dist/errors/workflow.d.ts +28 -0
- package/dist/errors/workflow.js +17 -0
- package/dist/handles/actors.d.ts +17 -0
- package/dist/handles/actors.js +7 -0
- package/dist/handles/content.d.ts +59 -0
- package/dist/handles/content.js +36 -0
- package/dist/handles/intents.d.ts +164 -0
- package/dist/handles/intents.js +214 -0
- package/dist/handles/run.d.ts +31 -0
- package/dist/handles/run.js +21 -0
- package/dist/handles/workflow.d.ts +27 -0
- package/dist/handles/workflow.js +23 -0
- package/dist/identity/caller.d.ts +105 -0
- package/dist/identity/caller.js +68 -0
- package/dist/identity/child.d.ts +18 -0
- package/dist/identity/child.js +39 -0
- package/dist/identity/command.d.ts +19 -0
- package/dist/identity/command.js +21 -0
- package/dist/identity/connection.d.ts +24 -0
- package/dist/identity/connection.js +29 -0
- package/dist/identity/content.d.ts +18 -0
- package/dist/identity/content.js +12 -0
- package/dist/identity/digest.d.ts +4 -0
- package/dist/identity/digest.js +5 -0
- package/dist/identity/execution.d.ts +32 -0
- package/dist/identity/execution.js +63 -0
- package/dist/identity/mint.d.ts +51 -0
- package/dist/identity/mint.js +76 -0
- package/dist/identity/version.d.ts +2 -0
- package/dist/identity/version.js +3 -0
- package/dist/index.d.ts +159 -0
- package/dist/index.js +97 -0
- package/dist/members/blob.d.ts +43 -0
- package/dist/members/blob.js +29 -0
- package/dist/members/command.d.ts +109 -0
- package/dist/members/command.js +61 -0
- package/dist/members/connection.d.ts +55 -0
- package/dist/members/connection.js +49 -0
- package/dist/members/event.d.ts +36 -0
- package/dist/members/event.js +24 -0
- package/dist/members/job.d.ts +157 -0
- package/dist/members/job.js +67 -0
- package/dist/members/payload.d.ts +93 -0
- package/dist/members/payload.js +145 -0
- package/dist/members/reducer.d.ts +64 -0
- package/dist/members/reducer.js +27 -0
- package/dist/members/stream.d.ts +36 -0
- package/dist/members/stream.js +14 -0
- package/dist/members/subscription.d.ts +182 -0
- package/dist/members/subscription.js +91 -0
- package/dist/members/workflow.d.ts +99 -0
- package/dist/members/workflow.js +2 -0
- package/dist/policies/access.d.ts +35 -0
- package/dist/policies/access.js +6 -0
- package/dist/policies/command.d.ts +127 -0
- package/dist/policies/command.js +45 -0
- package/dist/policies/job.d.ts +28 -0
- package/dist/policies/job.js +60 -0
- package/dist/policies/schedules.d.ts +33 -0
- package/dist/policies/schedules.js +131 -0
- package/dist/protocol/frames.d.ts +66 -0
- package/dist/protocol/frames.js +55 -0
- package/dist/protocol/inspection.d.ts +807 -0
- package/dist/protocol/inspection.js +243 -0
- package/dist/protocol/wire.d.ts +184 -0
- package/dist/protocol/wire.js +150 -0
- package/dist/runtime/actors.d.ts +155 -0
- package/dist/runtime/actors.js +4 -0
- package/dist/runtime/admission.d.ts +34 -0
- package/dist/runtime/admission.js +72 -0
- package/dist/runtime/adoption/backfill.d.ts +27 -0
- package/dist/runtime/adoption/backfill.js +144 -0
- package/dist/runtime/adoption/enforce.d.ts +55 -0
- package/dist/runtime/adoption/enforce.js +241 -0
- package/dist/runtime/adoption/observe.d.ts +43 -0
- package/dist/runtime/adoption/observe.js +139 -0
- package/dist/runtime/adoption/plan.d.ts +45 -0
- package/dist/runtime/adoption/plan.js +192 -0
- package/dist/runtime/adoption/startup.d.ts +32 -0
- package/dist/runtime/adoption/startup.js +76 -0
- package/dist/runtime/adoption/status.d.ts +23 -0
- package/dist/runtime/adoption/status.js +47 -0
- package/dist/runtime/adoption/target.d.ts +33 -0
- package/dist/runtime/adoption/target.js +49 -0
- package/dist/runtime/connections/holder.d.ts +221 -0
- package/dist/runtime/connections/holder.js +816 -0
- package/dist/runtime/connections/owner.d.ts +263 -0
- package/dist/runtime/connections/owner.js +896 -0
- package/dist/runtime/connections/protocol.d.ts +441 -0
- package/dist/runtime/connections/protocol.js +222 -0
- package/dist/runtime/connections/reads.d.ts +24 -0
- package/dist/runtime/connections/reads.js +19 -0
- package/dist/runtime/connections/streams.d.ts +62 -0
- package/dist/runtime/connections/streams.js +128 -0
- package/dist/runtime/connections/transport.d.ts +40 -0
- package/dist/runtime/connections/transport.js +68 -0
- package/dist/runtime/connections/watch.d.ts +52 -0
- package/dist/runtime/connections/watch.js +159 -0
- package/dist/runtime/content/grant.d.ts +34 -0
- package/dist/runtime/content/grant.js +58 -0
- package/dist/runtime/content/store.d.ts +63 -0
- package/dist/runtime/content/store.js +294 -0
- package/dist/runtime/cron/key.d.ts +2 -0
- package/dist/runtime/cron/key.js +2 -0
- package/dist/runtime/cron/schedule.d.ts +69 -0
- package/dist/runtime/cron/schedule.js +144 -0
- package/dist/runtime/database/bounded.d.ts +43 -0
- package/dist/runtime/database/bounded.js +108 -0
- package/dist/runtime/database/connection.d.ts +8 -0
- package/dist/runtime/database/connection.js +18 -0
- package/dist/runtime/database/coordination.d.ts +19 -0
- package/dist/runtime/database/coordination.js +72 -0
- package/dist/runtime/database/flock.d.ts +10 -0
- package/dist/runtime/database/flock.js +60 -0
- package/dist/runtime/database/gate.d.ts +26 -0
- package/dist/runtime/database/gate.js +54 -0
- package/dist/runtime/database/keepalive.d.ts +11 -0
- package/dist/runtime/database/keepalive.js +22 -0
- package/dist/runtime/database/migrations.d.ts +177 -0
- package/dist/runtime/database/migrations.js +1018 -0
- package/dist/runtime/database/neki/migrations.d.ts +31 -0
- package/dist/runtime/database/neki/migrations.js +276 -0
- package/dist/runtime/database/neki/session.d.ts +23 -0
- package/dist/runtime/database/neki/session.js +31 -0
- package/dist/runtime/database/pglite.d.ts +21 -0
- package/dist/runtime/database/pglite.js +74 -0
- package/dist/runtime/database/replica.d.ts +41 -0
- package/dist/runtime/database/replica.js +51 -0
- package/dist/runtime/database/shards.d.ts +21 -0
- package/dist/runtime/database/shards.js +37 -0
- package/dist/runtime/database/snapshot.d.ts +7 -0
- package/dist/runtime/database/snapshot.js +7 -0
- package/dist/runtime/database/tenancy.d.ts +69 -0
- package/dist/runtime/database/tenancy.js +145 -0
- package/dist/runtime/database/transient.d.ts +10 -0
- package/dist/runtime/database/transient.js +25 -0
- package/dist/runtime/drain.d.ts +132 -0
- package/dist/runtime/drain.js +109 -0
- package/dist/runtime/entity/mailbox.d.ts +86 -0
- package/dist/runtime/entity/mailbox.js +121 -0
- package/dist/runtime/entity/register.d.ts +424 -0
- package/dist/runtime/entity/register.js +669 -0
- package/dist/runtime/events/append.d.ts +192 -0
- package/dist/runtime/events/append.js +128 -0
- package/dist/runtime/events/cursor.d.ts +2 -0
- package/dist/runtime/events/cursor.js +5 -0
- package/dist/runtime/events/replay.d.ts +20 -0
- package/dist/runtime/events/replay.js +45 -0
- package/dist/runtime/feeds.d.ts +26 -0
- package/dist/runtime/feeds.js +100 -0
- package/dist/runtime/fleet/checks.d.ts +17 -0
- package/dist/runtime/fleet/checks.js +106 -0
- package/dist/runtime/fleet/maintainer.d.ts +38 -0
- package/dist/runtime/fleet/maintainer.js +383 -0
- package/dist/runtime/fleet/pgoutput.d.ts +41 -0
- package/dist/runtime/fleet/pgoutput.js +102 -0
- package/dist/runtime/fleet/setup.d.ts +36 -0
- package/dist/runtime/fleet/setup.js +58 -0
- package/dist/runtime/fleet/subscribe.d.ts +42 -0
- package/dist/runtime/fleet/subscribe.js +147 -0
- package/dist/runtime/index.d.ts +66 -0
- package/dist/runtime/index.js +37 -0
- package/dist/runtime/inspector/http.d.ts +19 -0
- package/dist/runtime/inspector/http.js +36 -0
- package/dist/runtime/inspector/layer.d.ts +46 -0
- package/dist/runtime/inspector/layer.js +180 -0
- package/dist/runtime/inspector/queries.d.ts +711 -0
- package/dist/runtime/inspector/queries.js +494 -0
- package/dist/runtime/jobs/attempt.d.ts +254 -0
- package/dist/runtime/jobs/attempt.js +413 -0
- package/dist/runtime/jobs/isolation.d.ts +20 -0
- package/dist/runtime/jobs/isolation.js +10 -0
- package/dist/runtime/jobs/progress.d.ts +95 -0
- package/dist/runtime/jobs/progress.js +144 -0
- package/dist/runtime/layer.d.ts +260 -0
- package/dist/runtime/layer.js +876 -0
- package/dist/runtime/members.d.ts +381 -0
- package/dist/runtime/members.js +8 -0
- package/dist/runtime/operators/audit.d.ts +64 -0
- package/dist/runtime/operators/audit.js +56 -0
- package/dist/runtime/operators/auth.d.ts +29 -0
- package/dist/runtime/operators/auth.js +42 -0
- package/dist/runtime/operators/export.d.ts +68 -0
- package/dist/runtime/operators/export.js +137 -0
- package/dist/runtime/operators/grants.d.ts +45 -0
- package/dist/runtime/operators/grants.js +40 -0
- package/dist/runtime/operators/repair.d.ts +206 -0
- package/dist/runtime/operators/repair.js +226 -0
- package/dist/runtime/operators/routes.d.ts +35 -0
- package/dist/runtime/operators/routes.js +190 -0
- package/dist/runtime/operators/seed.d.ts +123 -0
- package/dist/runtime/operators/seed.js +123 -0
- package/dist/runtime/payloads/versions.d.ts +65 -0
- package/dist/runtime/payloads/versions.js +240 -0
- package/dist/runtime/peering/authority.d.ts +42 -0
- package/dist/runtime/peering/authority.js +132 -0
- package/dist/runtime/peering/credentials.d.ts +21 -0
- package/dist/runtime/peering/credentials.js +13 -0
- package/dist/runtime/peering/transport.d.ts +51 -0
- package/dist/runtime/peering/transport.js +175 -0
- package/dist/runtime/queries.d.ts +18 -0
- package/dist/runtime/queries.js +169 -0
- package/dist/runtime/readiness.d.ts +36 -0
- package/dist/runtime/readiness.js +44 -0
- package/dist/runtime/registration.d.ts +58 -0
- package/dist/runtime/registration.js +186 -0
- package/dist/runtime/request.d.ts +158 -0
- package/dist/runtime/request.js +102 -0
- package/dist/runtime/retry.d.ts +8 -0
- package/dist/runtime/retry.js +11 -0
- package/dist/runtime/runner.d.ts +93 -0
- package/dist/runtime/runner.js +122 -0
- package/dist/runtime/storage/codec.d.ts +39 -0
- package/dist/runtime/storage/codec.js +41 -0
- package/dist/runtime/storage/generation.d.ts +69 -0
- package/dist/runtime/storage/generation.js +49 -0
- package/dist/runtime/storage/placements.d.ts +15 -0
- package/dist/runtime/storage/placements.js +38 -0
- package/dist/runtime/storage/platform.d.ts +6 -0
- package/dist/runtime/storage/platform.js +9 -0
- package/dist/runtime/storage/retention.d.ts +73 -0
- package/dist/runtime/storage/retention.js +158 -0
- package/dist/runtime/subscriptions/identity.d.ts +31 -0
- package/dist/runtime/subscriptions/identity.js +45 -0
- package/dist/runtime/subscriptions/relay.d.ts +175 -0
- package/dist/runtime/subscriptions/relay.js +763 -0
- package/dist/runtime/subscriptions/storage.d.ts +40 -0
- package/dist/runtime/subscriptions/storage.js +98 -0
- package/dist/runtime/sweeps.d.ts +39 -0
- package/dist/runtime/sweeps.js +54 -0
- package/dist/runtime/telemetry/defects.d.ts +57 -0
- package/dist/runtime/telemetry/defects.js +43 -0
- package/dist/runtime/telemetry/metrics.d.ts +52 -0
- package/dist/runtime/telemetry/metrics.js +138 -0
- package/dist/runtime/telemetry/routes.d.ts +19 -0
- package/dist/runtime/telemetry/routes.js +18 -0
- package/dist/runtime/telemetry/sampler.d.ts +26 -0
- package/dist/runtime/telemetry/sampler.js +101 -0
- package/dist/runtime/telemetry/spans.d.ts +38 -0
- package/dist/runtime/telemetry/spans.js +44 -0
- package/dist/runtime/telemetry/usage.d.ts +52 -0
- package/dist/runtime/telemetry/usage.js +30 -0
- package/dist/runtime/topology/admission.d.ts +13 -0
- package/dist/runtime/topology/admission.js +36 -0
- package/dist/runtime/topology/locks.d.ts +56 -0
- package/dist/runtime/topology/locks.js +81 -0
- package/dist/runtime/topology/messages.d.ts +15 -0
- package/dist/runtime/topology/messages.js +32 -0
- package/dist/runtime/turn/admission.d.ts +22 -0
- package/dist/runtime/turn/admission.js +41 -0
- package/dist/runtime/turn/blobs.d.ts +38 -0
- package/dist/runtime/turn/blobs.js +215 -0
- package/dist/runtime/turn/execute.d.ts +208 -0
- package/dist/runtime/turn/execute.js +972 -0
- package/dist/runtime/turn/group.d.ts +165 -0
- package/dist/runtime/turn/group.js +326 -0
- package/dist/runtime/turn/hooks.d.ts +44 -0
- package/dist/runtime/turn/hooks.js +28 -0
- package/dist/runtime/turn/outbox.d.ts +159 -0
- package/dist/runtime/turn/outbox.js +269 -0
- package/dist/runtime/turn/pipeline.d.ts +68 -0
- package/dist/runtime/turn/pipeline.js +83 -0
- package/dist/runtime/turn/receipt.d.ts +81 -0
- package/dist/runtime/turn/receipt.js +32 -0
- package/dist/runtime/turn/relay.d.ts +179 -0
- package/dist/runtime/turn/relay.js +685 -0
- package/dist/runtime/turn/rows.d.ts +43 -0
- package/dist/runtime/turn/rows.js +592 -0
- package/dist/runtime/workflows/compatibility.d.ts +125 -0
- package/dist/runtime/workflows/compatibility.js +285 -0
- package/dist/runtime/workflows/engine.d.ts +107 -0
- package/dist/runtime/workflows/engine.js +826 -0
- package/dist/runtime/workflows/manifest.d.ts +34 -0
- package/dist/runtime/workflows/manifest.js +39 -0
- package/dist/runtime/workflows/steps.d.ts +33 -0
- package/dist/runtime/workflows/steps.js +152 -0
- package/dist/serve/api.d.ts +99 -0
- package/dist/serve/api.js +403 -0
- package/dist/serve/assertion/binding.d.ts +41 -0
- package/dist/serve/assertion/binding.js +92 -0
- package/dist/serve/assertion/verify.d.ts +93 -0
- package/dist/serve/assertion/verify.js +189 -0
- package/dist/serve/auth.d.ts +200 -0
- package/dist/serve/auth.js +92 -0
- package/dist/serve/clock.d.ts +10 -0
- package/dist/serve/clock.js +25 -0
- package/dist/serve/jwt.d.ts +65 -0
- package/dist/serve/jwt.js +202 -0
- package/dist/serve/layer.d.ts +98 -0
- package/dist/serve/layer.js +809 -0
- package/dist/serve/mcp/endpoint.d.ts +39 -0
- package/dist/serve/mcp/endpoint.js +187 -0
- package/dist/serve/mcp/tools.d.ts +37 -0
- package/dist/serve/mcp/tools.js +125 -0
- package/dist/serve/origin.d.ts +6 -0
- package/dist/serve/origin.js +21 -0
- package/dist/serve/sessions/feed.d.ts +79 -0
- package/dist/serve/sessions/feed.js +115 -0
- package/dist/serve/sessions/socket.d.ts +56 -0
- package/dist/serve/sessions/socket.js +212 -0
- package/dist/serve/sessions/sse.d.ts +27 -0
- package/dist/serve/sessions/sse.js +26 -0
- package/dist/serve/sessions/stream.d.ts +9 -0
- package/dist/serve/sessions/stream.js +9 -0
- package/dist/serve/sessions/watch.d.ts +12 -0
- package/dist/serve/sessions/watch.js +11 -0
- package/dist/serve/wire.d.ts +16 -0
- package/dist/serve/wire.js +50 -0
- package/dist/state/blob.d.ts +71 -0
- package/dist/state/blob.js +0 -0
- package/dist/state/migration.d.ts +53 -0
- package/dist/state/migration.js +29 -0
- package/dist/tables/fleet.d.ts +170 -0
- package/dist/tables/fleet.js +214 -0
- package/dist/tables/owned.d.ts +250 -0
- package/dist/tables/owned.js +233 -0
- package/dist/testing/actor-test.d.ts +360 -0
- package/dist/testing/actor-test.js +337 -0
- package/dist/testing/cluster.d.ts +93 -0
- package/dist/testing/cluster.js +296 -0
- package/dist/testing/conformance/access.d.ts +5 -0
- package/dist/testing/conformance/access.js +531 -0
- package/dist/testing/conformance/admission.d.ts +11 -0
- package/dist/testing/conformance/admission.js +182 -0
- package/dist/testing/conformance/adoption.d.ts +2 -0
- package/dist/testing/conformance/adoption.js +1019 -0
- package/dist/testing/conformance/assertions.d.ts +202 -0
- package/dist/testing/conformance/assertions.js +849 -0
- package/dist/testing/conformance/batches.d.ts +41 -0
- package/dist/testing/conformance/batches.js +388 -0
- package/dist/testing/conformance/blobs.d.ts +14 -0
- package/dist/testing/conformance/blobs.js +405 -0
- package/dist/testing/conformance/capacity.d.ts +8 -0
- package/dist/testing/conformance/capacity.js +433 -0
- package/dist/testing/conformance/client.d.ts +5 -0
- package/dist/testing/conformance/client.js +719 -0
- package/dist/testing/conformance/cold-serve.d.ts +16 -0
- package/dist/testing/conformance/cold-serve.js +254 -0
- package/dist/testing/conformance/connections/actors.d.ts +1143 -0
- package/dist/testing/conformance/connections/actors.js +180 -0
- package/dist/testing/conformance/connections/harness.d.ts +1754 -0
- package/dist/testing/conformance/connections/harness.js +142 -0
- package/dist/testing/conformance/connections/holders.d.ts +4 -0
- package/dist/testing/conformance/connections/holders.js +165 -0
- package/dist/testing/conformance/connections/lifecycle.d.ts +4 -0
- package/dist/testing/conformance/connections/lifecycle.js +113 -0
- package/dist/testing/conformance/connections/limits.d.ts +4 -0
- package/dist/testing/conformance/connections/limits.js +127 -0
- package/dist/testing/conformance/connections/reauthorization.d.ts +4 -0
- package/dist/testing/conformance/connections/reauthorization.js +170 -0
- package/dist/testing/conformance/connections/resync.d.ts +4 -0
- package/dist/testing/conformance/connections/resync.js +360 -0
- package/dist/testing/conformance/connections/takeover.d.ts +4 -0
- package/dist/testing/conformance/connections/takeover.js +287 -0
- package/dist/testing/conformance/connections.d.ts +4 -0
- package/dist/testing/conformance/connections.js +15 -0
- package/dist/testing/conformance/content-blobs.d.ts +16 -0
- package/dist/testing/conformance/content-blobs.js +534 -0
- package/dist/testing/conformance/counter.d.ts +16 -0
- package/dist/testing/conformance/counter.js +813 -0
- package/dist/testing/conformance/cron.d.ts +5 -0
- package/dist/testing/conformance/cron.js +665 -0
- package/dist/testing/conformance/drain.d.ts +26 -0
- package/dist/testing/conformance/drain.js +540 -0
- package/dist/testing/conformance/effect-control.d.ts +38 -0
- package/dist/testing/conformance/effect-control.js +1059 -0
- package/dist/testing/conformance/effects.d.ts +23 -0
- package/dist/testing/conformance/effects.js +432 -0
- package/dist/testing/conformance/events.d.ts +28 -0
- package/dist/testing/conformance/events.js +335 -0
- package/dist/testing/conformance/export.d.ts +2 -0
- package/dist/testing/conformance/export.js +368 -0
- package/dist/testing/conformance/fleet.d.ts +444 -0
- package/dist/testing/conformance/fleet.js +1009 -0
- package/dist/testing/conformance/groups.d.ts +7 -0
- package/dist/testing/conformance/groups.js +353 -0
- package/dist/testing/conformance/heap.d.ts +3 -0
- package/dist/testing/conformance/heap.js +149 -0
- package/dist/testing/conformance/http.d.ts +2809 -0
- package/dist/testing/conformance/http.js +1234 -0
- package/dist/testing/conformance/inspection-views.d.ts +8 -0
- package/dist/testing/conformance/inspection-views.js +272 -0
- package/dist/testing/conformance/inspector.d.ts +7 -0
- package/dist/testing/conformance/inspector.js +650 -0
- package/dist/testing/conformance/mint.d.ts +58 -0
- package/dist/testing/conformance/mint.js +692 -0
- package/dist/testing/conformance/multi-runner.d.ts +8 -0
- package/dist/testing/conformance/multi-runner.js +403 -0
- package/dist/testing/conformance/neki/plan.d.ts +19 -0
- package/dist/testing/conformance/neki/plan.js +30 -0
- package/dist/testing/conformance/observability.d.ts +3 -0
- package/dist/testing/conformance/observability.js +343 -0
- package/dist/testing/conformance/offline.d.ts +4 -0
- package/dist/testing/conformance/offline.js +474 -0
- package/dist/testing/conformance/operator-harness.d.ts +57 -0
- package/dist/testing/conformance/operator-harness.js +78 -0
- package/dist/testing/conformance/operator.d.ts +3 -0
- package/dist/testing/conformance/operator.js +379 -0
- package/dist/testing/conformance/outbox-cross-shard.d.ts +14 -0
- package/dist/testing/conformance/outbox-cross-shard.js +160 -0
- package/dist/testing/conformance/outbox.d.ts +36 -0
- package/dist/testing/conformance/outbox.js +437 -0
- package/dist/testing/conformance/payload-migrations.d.ts +3 -0
- package/dist/testing/conformance/payload-migrations.js +612 -0
- package/dist/testing/conformance/pipeline.d.ts +3 -0
- package/dist/testing/conformance/pipeline.js +1040 -0
- package/dist/testing/conformance/placement.d.ts +22 -0
- package/dist/testing/conformance/placement.js +539 -0
- package/dist/testing/conformance/platform.d.ts +40 -0
- package/dist/testing/conformance/platform.js +101 -0
- package/dist/testing/conformance/progress.d.ts +39 -0
- package/dist/testing/conformance/progress.js +666 -0
- package/dist/testing/conformance/properties.d.ts +6 -0
- package/dist/testing/conformance/properties.js +295 -0
- package/dist/testing/conformance/protocols.d.ts +4 -0
- package/dist/testing/conformance/protocols.js +618 -0
- package/dist/testing/conformance/provider/advertise.d.ts +21 -0
- package/dist/testing/conformance/provider/advertise.js +44 -0
- package/dist/testing/conformance/read-your-writes.d.ts +20 -0
- package/dist/testing/conformance/read-your-writes.js +192 -0
- package/dist/testing/conformance/reducers.d.ts +8 -0
- package/dist/testing/conformance/reducers.js +258 -0
- package/dist/testing/conformance/relay.d.ts +42 -0
- package/dist/testing/conformance/relay.js +1115 -0
- package/dist/testing/conformance/restore.d.ts +43 -0
- package/dist/testing/conformance/restore.js +341 -0
- package/dist/testing/conformance/retention.d.ts +14 -0
- package/dist/testing/conformance/retention.js +463 -0
- package/dist/testing/conformance/rls.d.ts +24 -0
- package/dist/testing/conformance/rls.js +576 -0
- package/dist/testing/conformance/simulation.d.ts +31 -0
- package/dist/testing/conformance/simulation.js +167 -0
- package/dist/testing/conformance/single-shard.d.ts +2 -0
- package/dist/testing/conformance/single-shard.js +125 -0
- package/dist/testing/conformance/singleton.d.ts +3 -0
- package/dist/testing/conformance/singleton.js +293 -0
- package/dist/testing/conformance/statements.d.ts +60 -0
- package/dist/testing/conformance/statements.js +108 -0
- package/dist/testing/conformance/streams.d.ts +7 -0
- package/dist/testing/conformance/streams.js +280 -0
- package/dist/testing/conformance/subscriptions/access.d.ts +4 -0
- package/dist/testing/conformance/subscriptions/access.js +98 -0
- package/dist/testing/conformance/subscriptions/actors.d.ts +4910 -0
- package/dist/testing/conformance/subscriptions/actors.js +372 -0
- package/dist/testing/conformance/subscriptions/cluster.d.ts +4 -0
- package/dist/testing/conformance/subscriptions/cluster.js +89 -0
- package/dist/testing/conformance/subscriptions/delivery.d.ts +4 -0
- package/dist/testing/conformance/subscriptions/delivery.js +253 -0
- package/dist/testing/conformance/subscriptions/deploys.d.ts +4 -0
- package/dist/testing/conformance/subscriptions/deploys.js +162 -0
- package/dist/testing/conformance/subscriptions/epochs.d.ts +4 -0
- package/dist/testing/conformance/subscriptions/epochs.js +169 -0
- package/dist/testing/conformance/subscriptions/failures.d.ts +4 -0
- package/dist/testing/conformance/subscriptions/failures.js +108 -0
- package/dist/testing/conformance/subscriptions/feeds.d.ts +4 -0
- package/dist/testing/conformance/subscriptions/feeds.js +218 -0
- package/dist/testing/conformance/subscriptions/harness.d.ts +124 -0
- package/dist/testing/conformance/subscriptions/harness.js +143 -0
- package/dist/testing/conformance/subscriptions/operator.d.ts +4 -0
- package/dist/testing/conformance/subscriptions/operator.js +128 -0
- package/dist/testing/conformance/subscriptions/retention.d.ts +4 -0
- package/dist/testing/conformance/subscriptions/retention.js +288 -0
- package/dist/testing/conformance/subscriptions/routing.d.ts +4 -0
- package/dist/testing/conformance/subscriptions/routing.js +179 -0
- package/dist/testing/conformance/subscriptions.d.ts +4 -0
- package/dist/testing/conformance/subscriptions.js +19 -0
- package/dist/testing/conformance/tables.d.ts +125 -0
- package/dist/testing/conformance/tables.js +664 -0
- package/dist/testing/conformance/transports/actors.d.ts +1907 -0
- package/dist/testing/conformance/transports/actors.js +163 -0
- package/dist/testing/conformance/transports/client.d.ts +3 -0
- package/dist/testing/conformance/transports/client.js +237 -0
- package/dist/testing/conformance/transports/feeds.d.ts +3 -0
- package/dist/testing/conformance/transports/feeds.js +232 -0
- package/dist/testing/conformance/transports/harness.d.ts +93 -0
- package/dist/testing/conformance/transports/harness.js +84 -0
- package/dist/testing/conformance/transports/streams.d.ts +3 -0
- package/dist/testing/conformance/transports/streams.js +96 -0
- package/dist/testing/conformance/transports/websocket.d.ts +3 -0
- package/dist/testing/conformance/transports/websocket.js +384 -0
- package/dist/testing/conformance/transports/wire.d.ts +141 -0
- package/dist/testing/conformance/transports/wire.js +204 -0
- package/dist/testing/conformance/transports.d.ts +3 -0
- package/dist/testing/conformance/transports.js +11 -0
- package/dist/testing/conformance/watch.d.ts +59 -0
- package/dist/testing/conformance/watch.js +879 -0
- package/dist/testing/conformance/workflow-engine.d.ts +97 -0
- package/dist/testing/conformance/workflow-engine.js +253 -0
- package/dist/testing/conformance/workflow-versions.d.ts +3 -0
- package/dist/testing/conformance/workflow-versions.js +545 -0
- package/dist/testing/conformance/workflows/access.d.ts +4 -0
- package/dist/testing/conformance/workflows/access.js +147 -0
- package/dist/testing/conformance/workflows/actors.d.ts +2317 -0
- package/dist/testing/conformance/workflows/actors.js +305 -0
- package/dist/testing/conformance/workflows/basics.d.ts +4 -0
- package/dist/testing/conformance/workflows/basics.js +144 -0
- package/dist/testing/conformance/workflows/engine.d.ts +4 -0
- package/dist/testing/conformance/workflows/engine.js +80 -0
- package/dist/testing/conformance/workflows/guards.d.ts +4 -0
- package/dist/testing/conformance/workflows/guards.js +172 -0
- package/dist/testing/conformance/workflows/harness.d.ts +14 -0
- package/dist/testing/conformance/workflows/harness.js +44 -0
- package/dist/testing/conformance/workflows/recovery.d.ts +4 -0
- package/dist/testing/conformance/workflows/recovery.js +181 -0
- package/dist/testing/conformance/workflows/starts.d.ts +4 -0
- package/dist/testing/conformance/workflows/starts.js +57 -0
- package/dist/testing/conformance/workflows/suspension.d.ts +4 -0
- package/dist/testing/conformance/workflows/suspension.js +106 -0
- package/dist/testing/conformance/workflows/waits.d.ts +4 -0
- package/dist/testing/conformance/workflows/waits.js +284 -0
- package/dist/testing/conformance/workflows.d.ts +4 -0
- package/dist/testing/conformance/workflows.js +19 -0
- package/dist/testing/conformance.d.ts +330 -0
- package/dist/testing/conformance.js +364 -0
- package/dist/testing/database.d.ts +31 -0
- package/dist/testing/database.js +70 -0
- package/dist/testing/foundation.d.ts +41 -0
- package/dist/testing/foundation.js +517 -0
- package/dist/testing/index.d.ts +20 -0
- package/dist/testing/index.js +12 -0
- package/dist/testing/property.d.ts +40 -0
- package/dist/testing/property.js +95 -0
- package/dist/testing/simulate-cluster.d.ts +112 -0
- package/dist/testing/simulate-cluster.js +257 -0
- package/dist/testing/simulate.d.ts +90 -0
- package/dist/testing/simulate.js +127 -0
- package/package.json +1 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { SqlClient } from "effect/sql";
|
|
3
|
+
import { adoptionTargets, qualifiedName } from "./target.js";
|
|
4
|
+
const identifier = (name) => `"${name.replaceAll('"', '""')}"`;
|
|
5
|
+
/** `"schema"."table"`, quoted for the SQL the CLI prints and runs. */
|
|
6
|
+
export const quotedTable = (target) => `${identifier(target.schema)}.${identifier(target.table)}`;
|
|
7
|
+
/** The index columns a scoped statement leads with: `routing_key` first when the runtime writes the table. */
|
|
8
|
+
export const ownerIndexColumns = (target) => [
|
|
9
|
+
...(target.access === "write" ? ["routing_key"] : []),
|
|
10
|
+
target.tenantColumn,
|
|
11
|
+
target.actorColumn,
|
|
12
|
+
];
|
|
13
|
+
/** The statement that adds an index leading with the mapped columns. */
|
|
14
|
+
export const ownerIndexSql = (target) => `CREATE INDEX CONCURRENTLY IF NOT EXISTS ${identifier(`${target.table}_durable_owner`)} ON ${quotedTable(target)} (${ownerIndexColumns(target).map(identifier).join(", ")})`;
|
|
15
|
+
/**
|
|
16
|
+
* The problems that stop a table from being adopted as declared: it must
|
|
17
|
+
* exist, its mapped columns must exist, and they must be text, varchar, or uuid
|
|
18
|
+
* with a deterministic collation. Shared by `plan` and `observe`.
|
|
19
|
+
*/
|
|
20
|
+
export const mappingProblems = Effect.fnUntraced(function* (target) {
|
|
21
|
+
const sql = yield* SqlClient.SqlClient;
|
|
22
|
+
const exists = yield* sql `SELECT 1 FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
23
|
+
WHERE n.nspname = ${target.schema} AND c.relname = ${target.table} AND c.relkind IN ('r', 'p')`;
|
|
24
|
+
if (exists.length === 0)
|
|
25
|
+
return [`${qualifiedName(target)} does not exist`];
|
|
26
|
+
const columns = yield* sql `
|
|
27
|
+
SELECT a.attname AS name, t.typname AS type, co.collisdeterministic AS deterministic,
|
|
28
|
+
a.attnotnull AS not_null
|
|
29
|
+
FROM pg_attribute a
|
|
30
|
+
JOIN pg_class c ON c.oid = a.attrelid JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
31
|
+
JOIN pg_type t ON t.oid = a.atttypid
|
|
32
|
+
LEFT JOIN pg_collation co ON co.oid = a.attcollation AND a.attcollation <> 0
|
|
33
|
+
WHERE n.nspname = ${target.schema} AND c.relname = ${target.table}
|
|
34
|
+
AND a.attnum > 0 AND NOT a.attisdropped
|
|
35
|
+
AND a.attname IN (${target.tenantColumn}, ${target.actorColumn})`;
|
|
36
|
+
const problems = [];
|
|
37
|
+
for (const [role, name, kind] of [
|
|
38
|
+
["tenant", target.tenantColumn, target.tenantKind],
|
|
39
|
+
["actor", target.actorColumn, target.actorKind],
|
|
40
|
+
]) {
|
|
41
|
+
const column = columns.find((candidate) => candidate.name === name);
|
|
42
|
+
if (column === undefined) {
|
|
43
|
+
problems.push(`${role} column ${name} does not exist in ${qualifiedName(target)}`);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (column.type === "citext" || !["text", "varchar", "uuid"].includes(column.type)) {
|
|
47
|
+
problems.push(`${role} column ${name} is ${column.type}; only text, varchar, and uuid columns can be mapped`);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if ((column.type === "uuid") !== (kind === "uuid"))
|
|
51
|
+
problems.push(`${role} column ${name} is ${column.type} but is declared as a ${kind} column`);
|
|
52
|
+
if (column.deterministic === false)
|
|
53
|
+
problems.push(`${role} column ${name} has a nondeterministic collation`);
|
|
54
|
+
}
|
|
55
|
+
return problems;
|
|
56
|
+
});
|
|
57
|
+
const tableOid = (target) => `(SELECT c.oid FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace WHERE n.nspname = '${target.schema.replaceAll("'", "''")}' AND c.relname = '${target.table.replaceAll("'", "''")}')`;
|
|
58
|
+
const hasOwnerIndex = Effect.fnUntraced(function* (target) {
|
|
59
|
+
const sql = yield* SqlClient.SqlClient;
|
|
60
|
+
const expected = ownerIndexColumns(target);
|
|
61
|
+
const leading = yield* sql.unsafe(`SELECT array_agg(a.attname ORDER BY k.ord) AS columns
|
|
62
|
+
FROM pg_index i
|
|
63
|
+
JOIN pg_class ic ON ic.oid = i.indexrelid
|
|
64
|
+
JOIN pg_am am ON am.oid = ic.relam AND am.amname = 'btree'
|
|
65
|
+
CROSS JOIN LATERAL unnest(i.indkey::int2[]) WITH ORDINALITY AS k(attnum, ord)
|
|
66
|
+
JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = k.attnum
|
|
67
|
+
WHERE i.indrelid = ${tableOid(target)} AND i.indpred IS NULL AND i.indexprs IS NULL
|
|
68
|
+
AND k.ord <= ${expected.length}
|
|
69
|
+
GROUP BY i.indexrelid`);
|
|
70
|
+
return leading.some((index) => index.columns.length === expected.length && index.columns.join() === expected.join());
|
|
71
|
+
});
|
|
72
|
+
/** True when an index leading with the mapped columns exists, so scoped statements do not scan the table. */
|
|
73
|
+
export const ownerIndexExists = hasOwnerIndex;
|
|
74
|
+
/**
|
|
75
|
+
* Reads the catalog for every adopted table of `actors` and reports what
|
|
76
|
+
* adoption would meet, and the SQL each step would run. Changes nothing.
|
|
77
|
+
*/
|
|
78
|
+
export const planAdoption = Effect.fnUntraced(function* (actors, only) {
|
|
79
|
+
const sql = yield* SqlClient.SqlClient;
|
|
80
|
+
const plans = [];
|
|
81
|
+
for (const target of yield* adoptionTargets(actors, only)) {
|
|
82
|
+
const name = qualifiedName(target);
|
|
83
|
+
const problems = [...(yield* mappingProblems(target))];
|
|
84
|
+
const warnings = [];
|
|
85
|
+
const exists = !problems.some((problem) => problem.endsWith("does not exist"));
|
|
86
|
+
if (!exists) {
|
|
87
|
+
plans.push({
|
|
88
|
+
table: name,
|
|
89
|
+
actor: target.actor,
|
|
90
|
+
access: target.access,
|
|
91
|
+
problems,
|
|
92
|
+
warnings,
|
|
93
|
+
foreignKeys: [],
|
|
94
|
+
triggers: [],
|
|
95
|
+
rules: [],
|
|
96
|
+
views: [],
|
|
97
|
+
owner: "",
|
|
98
|
+
writers: [],
|
|
99
|
+
indexSql: undefined,
|
|
100
|
+
steps: [],
|
|
101
|
+
});
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
const oid = tableOid(target);
|
|
105
|
+
const foreign = yield* sql.unsafe(`SELECT con.conname AS name, pg_get_constraintdef(con.oid) AS definition,
|
|
106
|
+
con.confrelid = ${oid} AS incoming, con.confdeltype AS delete_action
|
|
107
|
+
FROM pg_constraint con
|
|
108
|
+
WHERE con.contype = 'f' AND (con.conrelid = ${oid} OR con.confrelid = ${oid})
|
|
109
|
+
ORDER BY con.conname`);
|
|
110
|
+
const triggers = yield* sql.unsafe(`SELECT tgname AS name FROM pg_trigger
|
|
111
|
+
WHERE tgrelid = ${oid} AND NOT tgisinternal AND tgname NOT LIKE 'actor\\_adoption\\_%'
|
|
112
|
+
ORDER BY tgname`);
|
|
113
|
+
const rules = yield* sql.unsafe(`SELECT rulename AS name FROM pg_rules
|
|
114
|
+
WHERE schemaname = '${target.schema.replaceAll("'", "''")}'
|
|
115
|
+
AND tablename = '${target.table.replaceAll("'", "''")}'
|
|
116
|
+
ORDER BY rulename`);
|
|
117
|
+
const views = yield* sql.unsafe(`SELECT DISTINCT vn.nspname || '.' || v.relname AS name
|
|
118
|
+
FROM pg_depend d
|
|
119
|
+
JOIN pg_rewrite r ON r.oid = d.objid
|
|
120
|
+
JOIN pg_class v ON v.oid = r.ev_class AND v.relkind = 'v'
|
|
121
|
+
JOIN pg_namespace vn ON vn.oid = v.relnamespace
|
|
122
|
+
WHERE d.refobjid = ${oid} AND d.classid = 'pg_rewrite'::regclass
|
|
123
|
+
ORDER BY 1`);
|
|
124
|
+
const owner = (yield* sql.unsafe(`SELECT r.rolname AS name FROM pg_class c JOIN pg_roles r ON r.oid = c.relowner
|
|
125
|
+
WHERE c.oid = ${oid}`))[0].name;
|
|
126
|
+
const writers = yield* sql.unsafe(`SELECT r.rolname AS name FROM pg_roles r
|
|
127
|
+
WHERE r.rolname !~ '^pg_' AND has_table_privilege(r.oid, ${oid}, 'INSERT, UPDATE, DELETE, TRUNCATE')
|
|
128
|
+
ORDER BY r.rolname`);
|
|
129
|
+
const keyless = target.primaryKey.length === 0 && target.access === "write";
|
|
130
|
+
if (keyless)
|
|
131
|
+
problems.push(`${name} has no primary key, which upserts and backfill need`);
|
|
132
|
+
for (const column of [target.tenantColumn, target.actorColumn]) {
|
|
133
|
+
const notNull = yield* sql.unsafe(`SELECT attnotnull AS not_null FROM pg_attribute
|
|
134
|
+
WHERE attrelid = ${oid} AND attname = '${column.replaceAll("'", "''")}'`);
|
|
135
|
+
if (notNull[0]?.not_null === false)
|
|
136
|
+
warnings.push(`${column} is nullable; enforce adds a check constraint and refuses rows with NULL`);
|
|
137
|
+
}
|
|
138
|
+
for (const key of foreign) {
|
|
139
|
+
if (key.incoming)
|
|
140
|
+
continue;
|
|
141
|
+
if (target.access === "write")
|
|
142
|
+
warnings.push(`foreign key ${key.name} from ${name} to a shared parent adds multixact contention on a high-volume actor table`);
|
|
143
|
+
if (key.delete_action === "c" || key.delete_action === "n")
|
|
144
|
+
warnings.push(`foreign key ${key.name} of ${name} has ${key.delete_action === "c" ? "ON DELETE CASCADE" : "ON DELETE SET NULL"} on its parent, so a parent delete would change this table as its owner; enforce refuses until it is resolved`);
|
|
145
|
+
}
|
|
146
|
+
const indexed = yield* hasOwnerIndex(target);
|
|
147
|
+
const index = indexed ? undefined : ownerIndexSql(target);
|
|
148
|
+
if (index !== undefined)
|
|
149
|
+
warnings.push(`no index leads with (${ownerIndexColumns(target).join(", ")}); every scoped statement scans the table and startup refuses`);
|
|
150
|
+
const quoted = quotedTable(target);
|
|
151
|
+
const indexSteps = index === undefined ? [] : [index];
|
|
152
|
+
const steps = target.access === "read"
|
|
153
|
+
? indexSteps
|
|
154
|
+
: [
|
|
155
|
+
...indexSteps,
|
|
156
|
+
`ALTER TABLE ${quoted} ADD COLUMN IF NOT EXISTS routing_key bigint`,
|
|
157
|
+
`CREATE TRIGGER actor_adoption_observe_insert AFTER INSERT ON ${quoted} REFERENCING NEW TABLE AS new_rows FOR EACH STATEMENT EXECUTE FUNCTION actor_adoption_observe()`,
|
|
158
|
+
`CREATE TRIGGER actor_adoption_observe_update AFTER UPDATE ON ${quoted} REFERENCING OLD TABLE AS old_rows NEW TABLE AS new_rows FOR EACH STATEMENT EXECUTE FUNCTION actor_adoption_observe()`,
|
|
159
|
+
`CREATE TRIGGER actor_adoption_observe_delete AFTER DELETE ON ${quoted} REFERENCING OLD TABLE AS old_rows FOR EACH STATEMENT EXECUTE FUNCTION actor_adoption_observe()`,
|
|
160
|
+
`CREATE TRIGGER actor_adoption_observe_truncate AFTER TRUNCATE ON ${quoted} FOR EACH STATEMENT EXECUTE FUNCTION actor_adoption_observe()`,
|
|
161
|
+
];
|
|
162
|
+
plans.push({
|
|
163
|
+
table: name,
|
|
164
|
+
actor: target.actor,
|
|
165
|
+
access: target.access,
|
|
166
|
+
problems,
|
|
167
|
+
warnings,
|
|
168
|
+
foreignKeys: foreign.map((key) => `${key.name}: ${key.definition}`),
|
|
169
|
+
triggers: triggers.map(({ name }) => name),
|
|
170
|
+
rules: rules.map(({ name }) => name),
|
|
171
|
+
views: views.map(({ name }) => name),
|
|
172
|
+
owner,
|
|
173
|
+
writers: writers.map(({ name }) => name),
|
|
174
|
+
indexSql: index,
|
|
175
|
+
steps,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
return plans;
|
|
179
|
+
});
|
|
180
|
+
/** What `plan` prints: one block per table. */
|
|
181
|
+
export const formatAdoptionPlan = (plan) => [
|
|
182
|
+
`${plan.table} (${plan.actor}, ${plan.access === "read" ? "read only" : "writable"})`,
|
|
183
|
+
...plan.problems.map((problem) => ` problem: ${problem}`),
|
|
184
|
+
...plan.warnings.map((warning) => ` warning: ${warning}`),
|
|
185
|
+
...(plan.owner === "" ? [] : [` owner: ${plan.owner}`]),
|
|
186
|
+
...(plan.writers.length === 0 ? [] : [` roles that can write: ${plan.writers.join(", ")}`]),
|
|
187
|
+
...plan.foreignKeys.map((key) => ` foreign key ${key}`),
|
|
188
|
+
...plan.triggers.map((trigger) => ` existing trigger ${trigger}`),
|
|
189
|
+
...plan.rules.map((rule) => ` existing rule ${rule}`),
|
|
190
|
+
...plan.views.map((view) => ` view over the table: ${view}`),
|
|
191
|
+
...plan.steps.map((step) => ` ${step};`),
|
|
192
|
+
].join("\n");
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { SqlClient } from "effect/sql";
|
|
3
|
+
import type { AdoptionTarget } from "./target.ts";
|
|
4
|
+
/**
|
|
5
|
+
* Refuses an enforced table whose protection was changed behind the
|
|
6
|
+
* runtime's back. `refuse` names the table and the fix. The guard triggers
|
|
7
|
+
* must exist, be enabled always, and carry exactly the recorded writer,
|
|
8
|
+
* allowed roles, columns, and actor type; no role but the writer and the
|
|
9
|
+
* allowed ones may hold a write privilege, so a grant added later is caught
|
|
10
|
+
* here and by the trigger.
|
|
11
|
+
*/
|
|
12
|
+
export declare const checkEnforcedTable: (args_0: {
|
|
13
|
+
readonly target: Pick<AdoptionTarget, "schema" | "table" | "tenantColumn" | "actorColumn" | "actor">;
|
|
14
|
+
readonly writerRole: string;
|
|
15
|
+
readonly allowedRoles: ReadonlyArray<string>;
|
|
16
|
+
readonly runtimeRole: string | undefined;
|
|
17
|
+
readonly refuse: (message: string) => Effect.Effect<never>;
|
|
18
|
+
}) => Effect.Effect<undefined, import("effect/sql/SqlError").SqlError, SqlClient.SqlClient>;
|
|
19
|
+
/**
|
|
20
|
+
* Refuses a writer role a turn cannot run as: it must exist, this login must
|
|
21
|
+
* be able to take it, and it must read and write every framework table and
|
|
22
|
+
* every table in `tables` without owning one, because the whole turn runs as
|
|
23
|
+
* the writer.
|
|
24
|
+
*/
|
|
25
|
+
export declare const checkWriterRole: (args_0: {
|
|
26
|
+
readonly role: string;
|
|
27
|
+
readonly tables: ReadonlyArray<{
|
|
28
|
+
readonly schema: string;
|
|
29
|
+
readonly table: string;
|
|
30
|
+
}>;
|
|
31
|
+
readonly refuse: (message: string) => Effect.Effect<never>;
|
|
32
|
+
}) => Effect.Effect<undefined, import("effect/sql/SqlError").SqlError, SqlClient.SqlClient>;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { SqlClient } from "effect/sql";
|
|
3
|
+
import { guardArguments, writeGrants } from "./enforce.js";
|
|
4
|
+
const GUARD_ROW_TYPE = 31;
|
|
5
|
+
const GUARD_TRUNCATE_TYPE = 34;
|
|
6
|
+
/**
|
|
7
|
+
* Refuses an enforced table whose protection was changed behind the
|
|
8
|
+
* runtime's back. `refuse` names the table and the fix. The guard triggers
|
|
9
|
+
* must exist, be enabled always, and carry exactly the recorded writer,
|
|
10
|
+
* allowed roles, columns, and actor type; no role but the writer and the
|
|
11
|
+
* allowed ones may hold a write privilege, so a grant added later is caught
|
|
12
|
+
* here and by the trigger.
|
|
13
|
+
*/
|
|
14
|
+
export const checkEnforcedTable = Effect.fnUntraced(function* ({ target, writerRole, allowedRoles, runtimeRole, refuse, }) {
|
|
15
|
+
const sql = yield* SqlClient.SqlClient;
|
|
16
|
+
if (runtimeRole === undefined)
|
|
17
|
+
return yield* refuse(`is enforced for writer role ${writerRole}; start the runtime with adoption: { role: "${writerRole}" }`);
|
|
18
|
+
if (runtimeRole !== writerRole)
|
|
19
|
+
return yield* refuse(`is enforced for writer role ${writerRole}, but the runtime takes ${runtimeRole}; set adoption.role to ${writerRole}`);
|
|
20
|
+
const triggers = yield* sql `
|
|
21
|
+
SELECT t.tgname AS name, t.tgenabled AS enabled, t.tgtype::int AS type,
|
|
22
|
+
p.proname AS function, encode(t.tgargs, 'escape') AS arguments
|
|
23
|
+
FROM pg_trigger t
|
|
24
|
+
JOIN pg_class c ON c.oid = t.tgrelid JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
25
|
+
JOIN pg_proc p ON p.oid = t.tgfoid
|
|
26
|
+
WHERE n.nspname = ${target.schema} AND c.relname = ${target.table} AND NOT t.tgisinternal
|
|
27
|
+
AND t.tgname IN ('actor_adoption_guard', 'actor_adoption_guard_truncate')`;
|
|
28
|
+
const expected = guardArguments({ target, writerRole, allowedRoles });
|
|
29
|
+
for (const [name, type] of [
|
|
30
|
+
["actor_adoption_guard", GUARD_ROW_TYPE],
|
|
31
|
+
["actor_adoption_guard_truncate", GUARD_TRUNCATE_TYPE],
|
|
32
|
+
]) {
|
|
33
|
+
const found = triggers.find((trigger) => trigger.name === name);
|
|
34
|
+
if (found === undefined)
|
|
35
|
+
return yield* refuse(`is enforced but its guard trigger ${name} is missing; run durable adopt release ${target.table} --to observe and enforce it again`);
|
|
36
|
+
if (found.enabled !== "A")
|
|
37
|
+
return yield* refuse(`is enforced but its guard trigger ${name} is not enabled always; run ALTER TABLE ${target.table} ENABLE ALWAYS TRIGGER ${name}`);
|
|
38
|
+
if (found.function !== "actor_adoption_guard" || found.type !== type)
|
|
39
|
+
return yield* refuse(`is enforced but its trigger ${name} is not the framework guard`);
|
|
40
|
+
if (found.arguments !== `${expected.join("\\000")}\\000`)
|
|
41
|
+
return yield* refuse(`is enforced but its guard trigger ${name} does not carry the recorded writer, allowed roles, and columns`);
|
|
42
|
+
}
|
|
43
|
+
const stray = (yield* writeGrants(target)).filter((grant) => grant.grantee !== writerRole && !allowedRoles.includes(grant.grantee));
|
|
44
|
+
if (stray.length > 0)
|
|
45
|
+
return yield* refuse(`is enforced but ${[...new Set(stray.map((grant) => grant.grantee))].join(", ")} hold write privileges again; revoke them (REVOKE INSERT, UPDATE, DELETE, TRUNCATE ON ${target.table} FROM …)`);
|
|
46
|
+
});
|
|
47
|
+
/**
|
|
48
|
+
* Refuses a writer role a turn cannot run as: it must exist, this login must
|
|
49
|
+
* be able to take it, and it must read and write every framework table and
|
|
50
|
+
* every table in `tables` without owning one, because the whole turn runs as
|
|
51
|
+
* the writer.
|
|
52
|
+
*/
|
|
53
|
+
export const checkWriterRole = Effect.fnUntraced(function* ({ role, tables, refuse, }) {
|
|
54
|
+
const sql = yield* SqlClient.SqlClient;
|
|
55
|
+
const [found] = yield* sql `
|
|
56
|
+
SELECT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = ${role}) AS exists`;
|
|
57
|
+
if (found?.exists !== true)
|
|
58
|
+
return yield* refuse(`writer role ${role} does not exist`);
|
|
59
|
+
yield* sql `SELECT set_config('role', ${role}, true)`.pipe(sql.withTransaction, Effect.catch(() => refuse(`this login cannot SET ROLE ${role}`)));
|
|
60
|
+
const owned = yield* sql `
|
|
61
|
+
SELECT n.nspname AS schema, c.relname AS table,
|
|
62
|
+
pg_has_role(${role}, c.relowner, 'USAGE') AS owned,
|
|
63
|
+
has_table_privilege(${role}, c.oid, 'SELECT') AND has_table_privilege(${role}, c.oid, 'INSERT')
|
|
64
|
+
AND has_table_privilege(${role}, c.oid, 'UPDATE') AND has_table_privilege(${role}, c.oid, 'DELETE') AS usable
|
|
65
|
+
FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
66
|
+
WHERE c.relkind = 'r' AND (
|
|
67
|
+
(n.oid = current_schema()::regnamespace AND (c.relname LIKE 'actor\\_%' OR c.relname LIKE 'tenant\\_content%'))
|
|
68
|
+
OR (n.nspname, c.relname) IN (${sql.csv(tables.map(({ schema, table }) => sql `(${schema}, ${table})`))}))
|
|
69
|
+
ORDER BY 1, 2`;
|
|
70
|
+
for (const table of owned) {
|
|
71
|
+
if (table.owned)
|
|
72
|
+
return yield* refuse(`writer role ${role} owns ${table.schema}.${table.table}; the writer must not own a table it is guarded on`);
|
|
73
|
+
if (!table.usable)
|
|
74
|
+
return yield* refuse(`writer role ${role} cannot read and write ${table.schema}.${table.table}; grant it SELECT, INSERT, UPDATE, and DELETE`);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { SqlClient } from "effect/sql";
|
|
3
|
+
/** One adopted table as `durable adopt status` reports it. */
|
|
4
|
+
export interface AdoptionStatus {
|
|
5
|
+
readonly table: string;
|
|
6
|
+
readonly actor: string;
|
|
7
|
+
readonly mode: "observe" | "enforce";
|
|
8
|
+
/** Rows still without a `routing_key`; enforcement needs none. */
|
|
9
|
+
readonly unbackfilled: number;
|
|
10
|
+
/** The last write neither the runtime nor an allowed role made, in epoch milliseconds. */
|
|
11
|
+
readonly lastLegacyWriteMs: number | undefined;
|
|
12
|
+
readonly writerRole: string | undefined;
|
|
13
|
+
/** Roles that may still write the table directly; adoption is complete when this is empty. */
|
|
14
|
+
readonly allowedRoles: ReadonlyArray<string>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Every recorded adoption in the database, with its unbackfilled row count
|
|
18
|
+
* and its last legacy write. Reads only the catalog and the recorded writes,
|
|
19
|
+
* so it needs no actor definitions.
|
|
20
|
+
*/
|
|
21
|
+
export declare const adoptionStatus: Effect.Effect<AdoptionStatus[], import("effect/sql/SqlError").SqlError, SqlClient.SqlClient>;
|
|
22
|
+
/** One line per adopted table. */
|
|
23
|
+
export declare const formatAdoptionStatus: (status: AdoptionStatus) => string;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { DateTime, Effect } from "effect";
|
|
2
|
+
import { SqlClient } from "effect/sql";
|
|
3
|
+
/**
|
|
4
|
+
* Every recorded adoption in the database, with its unbackfilled row count
|
|
5
|
+
* and its last legacy write. Reads only the catalog and the recorded writes,
|
|
6
|
+
* so it needs no actor definitions.
|
|
7
|
+
*/
|
|
8
|
+
export const adoptionStatus = Effect.gen(function* () {
|
|
9
|
+
const sql = yield* SqlClient.SqlClient;
|
|
10
|
+
const adoptions = yield* sql `SELECT table_schema, table_name, actor_type, mode, writer_role, allowed_roles
|
|
11
|
+
FROM actor_adoptions ORDER BY table_schema, table_name`;
|
|
12
|
+
const statuses = [];
|
|
13
|
+
for (const adoption of adoptions) {
|
|
14
|
+
const table = `"${adoption.table_schema.replaceAll('"', '""')}"."${adoption.table_name.replaceAll('"', '""')}"`;
|
|
15
|
+
const [counted] = yield* sql.unsafe(`SELECT count(*)::text AS unbackfilled FROM ${table} WHERE routing_key IS NULL`);
|
|
16
|
+
const [last] = yield* sql `
|
|
17
|
+
SELECT max(observed_at_ms)::text AS last FROM actor_adoption_writes
|
|
18
|
+
WHERE table_schema = ${adoption.table_schema} AND table_name = ${adoption.table_name}
|
|
19
|
+
AND NOT in_turn AND NOT allowed`;
|
|
20
|
+
statuses.push({
|
|
21
|
+
table: `${adoption.table_schema}.${adoption.table_name}`,
|
|
22
|
+
actor: adoption.actor_type,
|
|
23
|
+
mode: adoption.mode,
|
|
24
|
+
unbackfilled: Number(counted.unbackfilled),
|
|
25
|
+
lastLegacyWriteMs: last?.last == null ? undefined : Number(last.last),
|
|
26
|
+
writerRole: adoption.writer_role ?? undefined,
|
|
27
|
+
allowedRoles: adoption.allowed_roles,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
return statuses;
|
|
31
|
+
});
|
|
32
|
+
/** One line per adopted table. */
|
|
33
|
+
export const formatAdoptionStatus = (status) => [
|
|
34
|
+
`${status.table} ${status.actor} ${status.mode}`,
|
|
35
|
+
`${status.unbackfilled} rows without routing_key`,
|
|
36
|
+
status.lastLegacyWriteMs === undefined
|
|
37
|
+
? "no legacy write recorded"
|
|
38
|
+
: `last legacy write ${DateTime.formatIso(DateTime.makeUnsafe(status.lastLegacyWriteMs))}`,
|
|
39
|
+
...(status.mode === "enforce"
|
|
40
|
+
? [
|
|
41
|
+
`writer ${status.writerRole}`,
|
|
42
|
+
status.allowedRoles.length === 0
|
|
43
|
+
? "no allowed roles: adoption is complete"
|
|
44
|
+
: `allowed roles ${status.allowedRoles.join(", ")}`,
|
|
45
|
+
]
|
|
46
|
+
: []),
|
|
47
|
+
].join(" ");
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Effect, Schema } from "effect";
|
|
2
|
+
import { SqlClient } from "effect/sql";
|
|
3
|
+
import { type AdoptionAccess, type MappedKind } from "../../tables/owned.ts";
|
|
4
|
+
import type { Placement } from "../storage/codec.ts";
|
|
5
|
+
declare const AdoptionRefused_base: Schema.Class<AdoptionRefused, Schema.TaggedStruct<"AdoptionRefused", {
|
|
6
|
+
readonly message: Schema.String;
|
|
7
|
+
}>, import("effect/Cause").YieldableError>;
|
|
8
|
+
/** A command's precondition failed; the message names the table and the fix. */
|
|
9
|
+
export declare class AdoptionRefused extends AdoptionRefused_base {
|
|
10
|
+
}
|
|
11
|
+
/** One existing table an actor type declares with `Actor.table(existing, { owner })`. */
|
|
12
|
+
export interface AdoptionTarget {
|
|
13
|
+
readonly actor: string;
|
|
14
|
+
readonly placement: Placement;
|
|
15
|
+
readonly access: AdoptionAccess;
|
|
16
|
+
readonly schema: string;
|
|
17
|
+
readonly table: string;
|
|
18
|
+
readonly tenantColumn: string;
|
|
19
|
+
readonly actorColumn: string;
|
|
20
|
+
readonly tenantKind: MappedKind;
|
|
21
|
+
readonly actorKind: MappedKind;
|
|
22
|
+
/** SQL names of the primary key columns, in key order. */
|
|
23
|
+
readonly primaryKey: ReadonlyArray<string>;
|
|
24
|
+
}
|
|
25
|
+
/** The table's name as `schema.table`, which the CLI and every report print. */
|
|
26
|
+
export declare const qualifiedName: (target: Pick<AdoptionTarget, "schema" | "table">) => string;
|
|
27
|
+
/**
|
|
28
|
+
* The adopted tables of `actors`, resolved against the connection's current
|
|
29
|
+
* schema. `only` is a table name or `schema.table`; naming a table no actor
|
|
30
|
+
* adopts is refused, so a typo never silently does nothing.
|
|
31
|
+
*/
|
|
32
|
+
export declare const adoptionTargets: (actors: readonly WeakKey[], only?: string | undefined) => Effect.Effect<AdoptionTarget[], AdoptionRefused | import("effect/sql/SqlError").SqlError, SqlClient.SqlClient>;
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { getTableColumns } from "drizzle-orm";
|
|
2
|
+
import { Effect, Schema } from "effect";
|
|
3
|
+
import { SqlClient } from "effect/sql";
|
|
4
|
+
import { descriptorOf } from "../../actor/descriptor.js";
|
|
5
|
+
import { ownership } from "../../tables/owned.js";
|
|
6
|
+
/** A command's precondition failed; the message names the table and the fix. */
|
|
7
|
+
export class AdoptionRefused extends Schema.TaggedError()("AdoptionRefused", {
|
|
8
|
+
message: Schema.String,
|
|
9
|
+
}) {
|
|
10
|
+
}
|
|
11
|
+
/** The table's name as `schema.table`, which the CLI and every report print. */
|
|
12
|
+
export const qualifiedName = (target) => `${target.schema}.${target.table}`;
|
|
13
|
+
/**
|
|
14
|
+
* The adopted tables of `actors`, resolved against the connection's current
|
|
15
|
+
* schema. `only` is a table name or `schema.table`; naming a table no actor
|
|
16
|
+
* adopts is refused, so a typo never silently does nothing.
|
|
17
|
+
*/
|
|
18
|
+
export const adoptionTargets = Effect.fnUntraced(function* (actors, only) {
|
|
19
|
+
const sql = yield* SqlClient.SqlClient;
|
|
20
|
+
const current = (yield* sql `SELECT current_schema() AS schema`)[0].schema;
|
|
21
|
+
const targets = [];
|
|
22
|
+
for (const actor of actors) {
|
|
23
|
+
const declared = descriptorOf(actor);
|
|
24
|
+
for (const table of declared?.tables ?? []) {
|
|
25
|
+
const info = ownership(table);
|
|
26
|
+
if (!info.adopted)
|
|
27
|
+
continue;
|
|
28
|
+
const columns = getTableColumns(table);
|
|
29
|
+
targets.push({
|
|
30
|
+
actor: declared.name,
|
|
31
|
+
placement: declared.placement,
|
|
32
|
+
access: info.access,
|
|
33
|
+
schema: info.schema ?? current,
|
|
34
|
+
table: info.table,
|
|
35
|
+
tenantColumn: columns[info.tenantKey].name,
|
|
36
|
+
actorColumn: columns[info.actorKey].name,
|
|
37
|
+
tenantKind: info.tenantKind,
|
|
38
|
+
actorKind: info.actorKind,
|
|
39
|
+
primaryKey: info.primaryKey.map((key) => columns[key].name),
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (only === undefined)
|
|
44
|
+
return targets;
|
|
45
|
+
const named = targets.filter((target) => target.table === only || qualifiedName(target) === only);
|
|
46
|
+
if (named.length === 0)
|
|
47
|
+
return yield* AdoptionRefused.make({ message: `No actor type adopts a table named ${only}` });
|
|
48
|
+
return named;
|
|
49
|
+
});
|