@homeflare/alchemy 0.43.0 → 0.45.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/README.md +10 -1
- package/dist/caddy/index.js +35 -1
- package/dist/caddy/index.js.map +3 -3
- package/dist/launchd/index.js +35 -1
- package/dist/launchd/index.js.map +3 -3
- package/dist/linux/index.js +35 -1
- package/dist/linux/index.js.map +3 -3
- package/dist/litellm/access-group-form.d.ts +26 -0
- package/dist/litellm/access-group-form.d.ts.map +1 -0
- package/dist/litellm/access-group-operations.d.ts +37 -0
- package/dist/litellm/access-group-operations.d.ts.map +1 -0
- package/dist/litellm/access-group-types.d.ts +49 -0
- package/dist/litellm/access-group-types.d.ts.map +1 -0
- package/dist/litellm/access-group.d.ts +55 -0
- package/dist/litellm/access-group.d.ts.map +1 -0
- package/dist/litellm/credential-errors.d.ts +131 -0
- package/dist/litellm/credential-errors.d.ts.map +1 -0
- package/dist/litellm/credential-form.d.ts +79 -0
- package/dist/litellm/credential-form.d.ts.map +1 -0
- package/dist/litellm/credential-operations.d.ts +84 -0
- package/dist/litellm/credential-operations.d.ts.map +1 -0
- package/dist/litellm/credential-rewrite.d.ts +6 -0
- package/dist/litellm/credential-rewrite.d.ts.map +1 -0
- package/dist/litellm/credential-types.d.ts +87 -0
- package/dist/litellm/credential-types.d.ts.map +1 -0
- package/dist/litellm/credential-values.d.ts +53 -0
- package/dist/litellm/credential-values.d.ts.map +1 -0
- package/dist/litellm/credential.d.ts +83 -0
- package/dist/litellm/credential.d.ts.map +1 -0
- package/dist/litellm/fake-access-group-litellm.d.ts +34 -0
- package/dist/litellm/fake-access-group-litellm.d.ts.map +1 -0
- package/dist/litellm/fake-credential-litellm.d.ts +54 -0
- package/dist/litellm/fake-credential-litellm.d.ts.map +1 -0
- package/dist/litellm/fake-keys.d.ts +53 -0
- package/dist/litellm/fake-keys.d.ts.map +1 -0
- package/dist/litellm/fake-litellm.d.ts +4 -1
- package/dist/litellm/fake-litellm.d.ts.map +1 -1
- package/dist/litellm/fake-mcp-litellm.d.ts +67 -0
- package/dist/litellm/fake-mcp-litellm.d.ts.map +1 -0
- package/dist/litellm/fake-model-litellm-post-update.d.ts +49 -0
- package/dist/litellm/fake-model-litellm-post-update.d.ts.map +1 -0
- package/dist/litellm/fake-model-litellm.d.ts +48 -0
- package/dist/litellm/fake-model-litellm.d.ts.map +1 -0
- package/dist/litellm/fake-policy-attachment-litellm.d.ts +33 -0
- package/dist/litellm/fake-policy-attachment-litellm.d.ts.map +1 -0
- package/dist/litellm/fake-policy-litellm.d.ts +32 -0
- package/dist/litellm/fake-policy-litellm.d.ts.map +1 -0
- package/dist/litellm/fake-registry-base.d.ts +42 -0
- package/dist/litellm/fake-registry-base.d.ts.map +1 -0
- package/dist/litellm/fake-stack.d.ts +8 -1
- package/dist/litellm/fake-stack.d.ts.map +1 -1
- package/dist/litellm/fake-team-litellm.d.ts +47 -0
- package/dist/litellm/fake-team-litellm.d.ts.map +1 -0
- package/dist/litellm/fake-tool-litellm.d.ts +28 -0
- package/dist/litellm/fake-tool-litellm.d.ts.map +1 -0
- package/dist/litellm/fake-toolset-litellm.d.ts +29 -0
- package/dist/litellm/fake-toolset-litellm.d.ts.map +1 -0
- package/dist/litellm/index.d.ts +18 -0
- package/dist/litellm/index.d.ts.map +1 -1
- package/dist/litellm/index.js +3078 -2
- package/dist/litellm/index.js.map +65 -4
- package/dist/litellm/key-errors.d.ts +169 -0
- package/dist/litellm/key-errors.d.ts.map +1 -0
- package/dist/litellm/key-form.d.ts +119 -0
- package/dist/litellm/key-form.d.ts.map +1 -0
- package/dist/litellm/key-harness.d.ts +41 -0
- package/dist/litellm/key-harness.d.ts.map +1 -0
- package/dist/litellm/key-metadata-errors.d.ts +30 -0
- package/dist/litellm/key-metadata-errors.d.ts.map +1 -0
- package/dist/litellm/key-metadata.d.ts +22 -0
- package/dist/litellm/key-metadata.d.ts.map +1 -0
- package/dist/litellm/key-operations.d.ts +63 -0
- package/dist/litellm/key-operations.d.ts.map +1 -0
- package/dist/litellm/key-secret.d.ts +33 -0
- package/dist/litellm/key-secret.d.ts.map +1 -0
- package/dist/litellm/key.d.ts +78 -0
- package/dist/litellm/key.d.ts.map +1 -0
- package/dist/litellm/mcp-server-credential.d.ts +50 -0
- package/dist/litellm/mcp-server-credential.d.ts.map +1 -0
- package/dist/litellm/mcp-server-errors.d.ts +101 -0
- package/dist/litellm/mcp-server-errors.d.ts.map +1 -0
- package/dist/litellm/mcp-server-form.d.ts +56 -0
- package/dist/litellm/mcp-server-form.d.ts.map +1 -0
- package/dist/litellm/mcp-server-locate.d.ts +26 -0
- package/dist/litellm/mcp-server-locate.d.ts.map +1 -0
- package/dist/litellm/mcp-server-operations.d.ts +63 -0
- package/dist/litellm/mcp-server-operations.d.ts.map +1 -0
- package/dist/litellm/mcp-server-shadow.d.ts +24 -0
- package/dist/litellm/mcp-server-shadow.d.ts.map +1 -0
- package/dist/litellm/mcp-server-types.d.ts +118 -0
- package/dist/litellm/mcp-server-types.d.ts.map +1 -0
- package/dist/litellm/mcp-server-url.d.ts +11 -0
- package/dist/litellm/mcp-server-url.d.ts.map +1 -0
- package/dist/litellm/mcp-server.d.ts +95 -0
- package/dist/litellm/mcp-server.d.ts.map +1 -0
- package/dist/litellm/model-claim.d.ts +24 -0
- package/dist/litellm/model-claim.d.ts.map +1 -0
- package/dist/litellm/model-credential.d.ts +12 -0
- package/dist/litellm/model-credential.d.ts.map +1 -0
- package/dist/litellm/model-errors.d.ts +119 -0
- package/dist/litellm/model-errors.d.ts.map +1 -0
- package/dist/litellm/model-form.d.ts +78 -0
- package/dist/litellm/model-form.d.ts.map +1 -0
- package/dist/litellm/model-locate.d.ts +13 -0
- package/dist/litellm/model-locate.d.ts.map +1 -0
- package/dist/litellm/model-operations.d.ts +59 -0
- package/dist/litellm/model-operations.d.ts.map +1 -0
- package/dist/litellm/model-types.d.ts +91 -0
- package/dist/litellm/model-types.d.ts.map +1 -0
- package/dist/litellm/model.d.ts +88 -0
- package/dist/litellm/model.d.ts.map +1 -0
- package/dist/litellm/policy-attachment-form.d.ts +19 -0
- package/dist/litellm/policy-attachment-form.d.ts.map +1 -0
- package/dist/litellm/policy-attachment-operations.d.ts +31 -0
- package/dist/litellm/policy-attachment-operations.d.ts.map +1 -0
- package/dist/litellm/policy-attachment-types.d.ts +48 -0
- package/dist/litellm/policy-attachment-types.d.ts.map +1 -0
- package/dist/litellm/policy-attachment.d.ts +61 -0
- package/dist/litellm/policy-attachment.d.ts.map +1 -0
- package/dist/litellm/policy-form.d.ts +22 -0
- package/dist/litellm/policy-form.d.ts.map +1 -0
- package/dist/litellm/policy-operations.d.ts +42 -0
- package/dist/litellm/policy-operations.d.ts.map +1 -0
- package/dist/litellm/policy-types.d.ts +57 -0
- package/dist/litellm/policy-types.d.ts.map +1 -0
- package/dist/litellm/policy.d.ts +65 -0
- package/dist/litellm/policy.d.ts.map +1 -0
- package/dist/litellm/providers.d.ts +1 -1
- package/dist/litellm/providers.d.ts.map +1 -1
- package/dist/litellm/registry-errors.d.ts +62 -0
- package/dist/litellm/registry-errors.d.ts.map +1 -0
- package/dist/litellm/registry-support.d.ts +42 -0
- package/dist/litellm/registry-support.d.ts.map +1 -0
- package/dist/litellm/team-form.d.ts +26 -0
- package/dist/litellm/team-form.d.ts.map +1 -0
- package/dist/litellm/team-members.d.ts +10 -0
- package/dist/litellm/team-members.d.ts.map +1 -0
- package/dist/litellm/team-operations.d.ts +38 -0
- package/dist/litellm/team-operations.d.ts.map +1 -0
- package/dist/litellm/team-permission.d.ts +35 -0
- package/dist/litellm/team-permission.d.ts.map +1 -0
- package/dist/litellm/team-types.d.ts +101 -0
- package/dist/litellm/team-types.d.ts.map +1 -0
- package/dist/litellm/team.d.ts +67 -0
- package/dist/litellm/team.d.ts.map +1 -0
- package/dist/litellm/tool-policy-form.d.ts +21 -0
- package/dist/litellm/tool-policy-form.d.ts.map +1 -0
- package/dist/litellm/tool-policy-operations.d.ts +30 -0
- package/dist/litellm/tool-policy-operations.d.ts.map +1 -0
- package/dist/litellm/tool-policy-types.d.ts +46 -0
- package/dist/litellm/tool-policy-types.d.ts.map +1 -0
- package/dist/litellm/tool-policy.d.ts +62 -0
- package/dist/litellm/tool-policy.d.ts.map +1 -0
- package/dist/litellm/toolset-form.d.ts +20 -0
- package/dist/litellm/toolset-form.d.ts.map +1 -0
- package/dist/litellm/toolset-operations.d.ts +39 -0
- package/dist/litellm/toolset-operations.d.ts.map +1 -0
- package/dist/litellm/toolset-types.d.ts +46 -0
- package/dist/litellm/toolset-types.d.ts.map +1 -0
- package/dist/litellm/toolset.d.ts +55 -0
- package/dist/litellm/toolset.d.ts.map +1 -0
- package/dist/openbao/index.js +35 -1
- package/dist/openbao/index.js.map +3 -3
- package/dist/ownership/rows.d.ts +11 -0
- package/dist/ownership/rows.d.ts.map +1 -1
- package/dist/postgres/connection.d.ts +14 -2
- package/dist/postgres/connection.d.ts.map +1 -1
- package/dist/postgres/database-sql.d.ts +27 -8
- package/dist/postgres/database-sql.d.ts.map +1 -1
- package/dist/postgres/fake-grants-parse.d.ts +37 -0
- package/dist/postgres/fake-grants-parse.d.ts.map +1 -0
- package/dist/postgres/fake-grants-read.d.ts +61 -0
- package/dist/postgres/fake-grants-read.d.ts.map +1 -0
- package/dist/postgres/fake-grants-sql.d.ts +46 -0
- package/dist/postgres/fake-grants-sql.d.ts.map +1 -0
- package/dist/postgres/fake-grants-write.d.ts +29 -0
- package/dist/postgres/fake-grants-write.d.ts.map +1 -0
- package/dist/postgres/fake-role-sql.d.ts +41 -0
- package/dist/postgres/fake-role-sql.d.ts.map +1 -0
- package/dist/postgres/fake-schema-sql.d.ts +42 -0
- package/dist/postgres/fake-schema-sql.d.ts.map +1 -0
- package/dist/postgres/fake-sql-parse.d.ts +23 -0
- package/dist/postgres/fake-sql-parse.d.ts.map +1 -0
- package/dist/postgres/fake-sql-quote.d.ts +12 -0
- package/dist/postgres/fake-sql-quote.d.ts.map +1 -0
- package/dist/postgres/fake-sql.d.ts +42 -0
- package/dist/postgres/fake-sql.d.ts.map +1 -1
- package/dist/postgres/grants-attrs.d.ts +115 -0
- package/dist/postgres/grants-attrs.d.ts.map +1 -0
- package/dist/postgres/grants-declare.d.ts +88 -0
- package/dist/postgres/grants-declare.d.ts.map +1 -0
- package/dist/postgres/grants-diff.d.ts +25 -0
- package/dist/postgres/grants-diff.d.ts.map +1 -0
- package/dist/postgres/grants-errors.d.ts +137 -0
- package/dist/postgres/grants-errors.d.ts.map +1 -0
- package/dist/postgres/grants-existence.d.ts +14 -0
- package/dist/postgres/grants-existence.d.ts.map +1 -0
- package/dist/postgres/grants-ops.d.ts +65 -0
- package/dist/postgres/grants-ops.d.ts.map +1 -0
- package/dist/postgres/grants-ownership.d.ts +18 -0
- package/dist/postgres/grants-ownership.d.ts.map +1 -0
- package/dist/postgres/grants-plan-restore.d.ts +22 -0
- package/dist/postgres/grants-plan-restore.d.ts.map +1 -0
- package/dist/postgres/grants-plan.d.ts +65 -0
- package/dist/postgres/grants-plan.d.ts.map +1 -0
- package/dist/postgres/grants-read-defaults.d.ts +17 -0
- package/dist/postgres/grants-read-defaults.d.ts.map +1 -0
- package/dist/postgres/grants-read.d.ts +77 -0
- package/dist/postgres/grants-read.d.ts.map +1 -0
- package/dist/postgres/grants-refuse.d.ts +25 -0
- package/dist/postgres/grants-refuse.d.ts.map +1 -0
- package/dist/postgres/grants-sql.d.ts +42 -0
- package/dist/postgres/grants-sql.d.ts.map +1 -0
- package/dist/postgres/grants-words.d.ts +29 -0
- package/dist/postgres/grants-words.d.ts.map +1 -0
- package/dist/postgres/grants.d.ts +37 -0
- package/dist/postgres/grants.d.ts.map +1 -0
- package/dist/postgres/index.d.ts +31 -6
- package/dist/postgres/index.d.ts.map +1 -1
- package/dist/postgres/index.js +1998 -37
- package/dist/postgres/index.js.map +46 -7
- package/dist/postgres/installed-classifier.d.ts +13 -0
- package/dist/postgres/installed-classifier.d.ts.map +1 -0
- package/dist/postgres/providers.d.ts +16 -8
- package/dist/postgres/providers.d.ts.map +1 -1
- package/dist/postgres/psql-executor.d.ts +4 -0
- package/dist/postgres/psql-executor.d.ts.map +1 -1
- package/dist/postgres/role-attrs.d.ts +112 -0
- package/dist/postgres/role-attrs.d.ts.map +1 -0
- package/dist/postgres/role-diff.d.ts +22 -0
- package/dist/postgres/role-diff.d.ts.map +1 -0
- package/dist/postgres/role-errors.d.ts +132 -0
- package/dist/postgres/role-errors.d.ts.map +1 -0
- package/dist/postgres/role-membership-sql.d.ts +78 -0
- package/dist/postgres/role-membership-sql.d.ts.map +1 -0
- package/dist/postgres/role-provider.d.ts +11 -0
- package/dist/postgres/role-provider.d.ts.map +1 -0
- package/dist/postgres/role-scram.d.ts +8 -0
- package/dist/postgres/role-scram.d.ts.map +1 -0
- package/dist/postgres/role-secrets.d.ts +38 -0
- package/dist/postgres/role-secrets.d.ts.map +1 -0
- package/dist/postgres/role-sql.d.ts +68 -0
- package/dist/postgres/role-sql.d.ts.map +1 -0
- package/dist/postgres/role.d.ts +57 -0
- package/dist/postgres/role.d.ts.map +1 -0
- package/dist/postgres/schema-assert.d.ts +50 -0
- package/dist/postgres/schema-assert.d.ts.map +1 -0
- package/dist/postgres/schema-attrs.d.ts +51 -0
- package/dist/postgres/schema-attrs.d.ts.map +1 -0
- package/dist/postgres/schema-delete.d.ts +28 -0
- package/dist/postgres/schema-delete.d.ts.map +1 -0
- package/dist/postgres/schema-diff.d.ts +14 -0
- package/dist/postgres/schema-diff.d.ts.map +1 -0
- package/dist/postgres/schema-errors.d.ts +139 -0
- package/dist/postgres/schema-errors.d.ts.map +1 -0
- package/dist/postgres/schema-identity.d.ts +8 -0
- package/dist/postgres/schema-identity.d.ts.map +1 -0
- package/dist/postgres/schema-reconcile.d.ts +12 -0
- package/dist/postgres/schema-reconcile.d.ts.map +1 -0
- package/dist/postgres/schema-sql.d.ts +45 -0
- package/dist/postgres/schema-sql.d.ts.map +1 -0
- package/dist/postgres/schema-test-kit.d.ts +67 -0
- package/dist/postgres/schema-test-kit.d.ts.map +1 -0
- package/dist/postgres/schema.d.ts +54 -0
- package/dist/postgres/schema.d.ts.map +1 -0
- package/dist/proxmox/index.js +35 -1
- package/dist/proxmox/index.js.map +3 -3
- package/dist/release/fake-engine.d.ts +10 -0
- package/dist/release/fake-engine.d.ts.map +1 -1
- package/dist/release/index.js +35 -1
- package/dist/release/index.js.map +3 -3
- package/dist/valkey/acl-attrs.d.ts +94 -0
- package/dist/valkey/acl-attrs.d.ts.map +1 -0
- package/dist/valkey/acl-compare.d.ts +28 -0
- package/dist/valkey/acl-compare.d.ts.map +1 -0
- package/dist/valkey/acl-connection.d.ts +6 -0
- package/dist/valkey/acl-connection.d.ts.map +1 -0
- package/dist/valkey/acl-form.d.ts +62 -0
- package/dist/valkey/acl-form.d.ts.map +1 -0
- package/dist/valkey/acl-managed.d.ts +4 -0
- package/dist/valkey/acl-managed.d.ts.map +1 -0
- package/dist/valkey/acl-ops.d.ts +37 -0
- package/dist/valkey/acl-ops.d.ts.map +1 -0
- package/dist/valkey/acl-profiles.d.ts +53 -0
- package/dist/valkey/acl-profiles.d.ts.map +1 -0
- package/dist/valkey/acl-reconcile.d.ts +26 -0
- package/dist/valkey/acl-reconcile.d.ts.map +1 -0
- package/dist/valkey/acl.d.ts +24 -0
- package/dist/valkey/acl.d.ts.map +1 -0
- package/dist/valkey/connection-service.d.ts +22 -0
- package/dist/valkey/connection-service.d.ts.map +1 -0
- package/dist/valkey/connection.d.ts +59 -0
- package/dist/valkey/connection.d.ts.map +1 -0
- package/dist/valkey/errors.d.ts +165 -0
- package/dist/valkey/errors.d.ts.map +1 -0
- package/dist/valkey/fake-acl.d.ts +29 -0
- package/dist/valkey/fake-acl.d.ts.map +1 -0
- package/dist/valkey/fake-valkey.d.ts +35 -0
- package/dist/valkey/fake-valkey.d.ts.map +1 -0
- package/dist/valkey/handler-test-fixture.d.ts +20 -0
- package/dist/valkey/handler-test-fixture.d.ts.map +1 -0
- package/dist/valkey/index.d.ts +18 -0
- package/dist/valkey/index.d.ts.map +1 -0
- package/dist/valkey/index.js +964 -0
- package/dist/valkey/index.js.map +27 -0
- package/dist/valkey/instance-attrs.d.ts +46 -0
- package/dist/valkey/instance-attrs.d.ts.map +1 -0
- package/dist/valkey/instance-form.d.ts +22 -0
- package/dist/valkey/instance-form.d.ts.map +1 -0
- package/dist/valkey/instance.d.ts +48 -0
- package/dist/valkey/instance.d.ts.map +1 -0
- package/dist/valkey/provider-socket-fixture.d.ts +8 -0
- package/dist/valkey/provider-socket-fixture.d.ts.map +1 -0
- package/dist/valkey/providers.d.ts +16 -0
- package/dist/valkey/providers.d.ts.map +1 -0
- package/dist/valkey/resp.d.ts +38 -0
- package/dist/valkey/resp.d.ts.map +1 -0
- package/dist/valkey/transport-error.d.ts +36 -0
- package/dist/valkey/transport-error.d.ts.map +1 -0
- package/dist/valkey/transport.d.ts +50 -0
- package/dist/valkey/transport.d.ts.map +1 -0
- package/docs/litellm-access-group.md +105 -0
- package/docs/litellm-credential.md +60 -0
- package/docs/litellm-key-metadata.md +56 -0
- package/docs/litellm-key.md +194 -0
- package/docs/litellm-mcp.md +187 -0
- package/docs/litellm-model.md +111 -0
- package/docs/litellm-policy-attachment.md +86 -0
- package/docs/litellm-policy.md +103 -0
- package/docs/litellm-team.md +117 -0
- package/docs/litellm-tool-policy.md +90 -0
- package/docs/litellm-toolset.md +92 -0
- package/docs/litellm.md +16 -9
- package/docs/peers.md +15 -6
- package/docs/postgres-grants-example.md +55 -0
- package/docs/postgres-grants.md +157 -0
- package/docs/postgres-role.md +126 -0
- package/docs/postgres-schema.md +139 -0
- package/docs/postgres.md +20 -3
- package/docs/valkey-transport.md +29 -0
- package/docs/valkey.md +187 -0
- package/package.json +6 -2
- package/src/ceph/ceph-argv.test.ts +1 -1
- package/src/launchd/sudo-allowlist.test.ts +2 -2
- package/src/linux/sudo-allowlist.test.ts +3 -3
- package/src/linux/sudo-runner.test.ts +2 -2
- package/src/litellm/access-group-form.ts +105 -0
- package/src/litellm/access-group-operations.ts +92 -0
- package/src/litellm/access-group-types.ts +49 -0
- package/src/litellm/access-group.test.ts +197 -0
- package/src/litellm/access-group.ts +151 -0
- package/src/litellm/credential-errors.ts +183 -0
- package/src/litellm/credential-form.test.ts +151 -0
- package/src/litellm/credential-form.ts +211 -0
- package/src/litellm/credential-guards.test.ts +241 -0
- package/src/litellm/credential-operations.ts +208 -0
- package/src/litellm/credential-recovery.test.ts +93 -0
- package/src/litellm/credential-rewrite.test.ts +164 -0
- package/src/litellm/credential-rewrite.ts +50 -0
- package/src/litellm/credential-types.ts +117 -0
- package/src/litellm/credential-values.ts +94 -0
- package/src/litellm/credential.test.ts +218 -0
- package/src/litellm/credential.ts +227 -0
- package/src/litellm/fake-access-group-litellm.ts +127 -0
- package/src/litellm/fake-credential-litellm.ts +216 -0
- package/src/litellm/fake-keys.ts +190 -0
- package/src/litellm/fake-litellm.ts +19 -9
- package/src/litellm/fake-mcp-litellm.ts +214 -0
- package/src/litellm/fake-model-litellm-post-update.ts +103 -0
- package/src/litellm/fake-model-litellm.ts +233 -0
- package/src/litellm/fake-policy-attachment-litellm.ts +97 -0
- package/src/litellm/fake-policy-litellm.ts +186 -0
- package/src/litellm/fake-registry-base.ts +69 -0
- package/src/litellm/fake-stack.ts +17 -1
- package/src/litellm/fake-team-litellm.ts +229 -0
- package/src/litellm/fake-tool-litellm.ts +88 -0
- package/src/litellm/fake-toolset-litellm.ts +110 -0
- package/src/litellm/index.ts +140 -0
- package/src/litellm/key-delete.test.ts +212 -0
- package/src/litellm/key-errors.ts +241 -0
- package/src/litellm/key-form.ts +200 -0
- package/src/litellm/key-harness.ts +121 -0
- package/src/litellm/key-metadata-errors.ts +49 -0
- package/src/litellm/key-metadata.test.ts +156 -0
- package/src/litellm/key-metadata.ts +74 -0
- package/src/litellm/key-operations.ts +184 -0
- package/src/litellm/key-rotation.test.ts +110 -0
- package/src/litellm/key-scope.test.ts +135 -0
- package/src/litellm/key-secret.test.ts +248 -0
- package/src/litellm/key-secret.ts +137 -0
- package/src/litellm/key-transport.test.ts +166 -0
- package/src/litellm/key.test.ts +231 -0
- package/src/litellm/key.ts +213 -0
- package/src/litellm/mcp-server-adopt.test.ts +86 -0
- package/src/litellm/mcp-server-alias.test.ts +184 -0
- package/src/litellm/mcp-server-credential.ts +85 -0
- package/src/litellm/mcp-server-errors.ts +141 -0
- package/src/litellm/mcp-server-exports.test.ts +15 -0
- package/src/litellm/mcp-server-form.test.ts +241 -0
- package/src/litellm/mcp-server-form.ts +233 -0
- package/src/litellm/mcp-server-handlers.test.ts +150 -0
- package/src/litellm/mcp-server-locate.ts +66 -0
- package/src/litellm/mcp-server-operations.ts +111 -0
- package/src/litellm/mcp-server-registry.test.ts +146 -0
- package/src/litellm/mcp-server-retype.test.ts +114 -0
- package/src/litellm/mcp-server-shadow.test.ts +91 -0
- package/src/litellm/mcp-server-shadow.ts +45 -0
- package/src/litellm/mcp-server-tools.test.ts +85 -0
- package/src/litellm/mcp-server-types.ts +143 -0
- package/src/litellm/mcp-server-url.ts +66 -0
- package/src/litellm/mcp-server.test.ts +213 -0
- package/src/litellm/mcp-server.ts +225 -0
- package/src/litellm/model-claim.ts +69 -0
- package/src/litellm/model-credential.ts +45 -0
- package/src/litellm/model-errors.ts +168 -0
- package/src/litellm/model-foreign-row.test.ts +173 -0
- package/src/litellm/model-form.test.ts +228 -0
- package/src/litellm/model-form.ts +223 -0
- package/src/litellm/model-locate.test.ts +128 -0
- package/src/litellm/model-locate.ts +67 -0
- package/src/litellm/model-operations.test.ts +93 -0
- package/src/litellm/model-operations.ts +146 -0
- package/src/litellm/model-params-preserve.test.ts +119 -0
- package/src/litellm/model-recovery.test.ts +57 -0
- package/src/litellm/model-types.ts +112 -0
- package/src/litellm/model.test.ts +222 -0
- package/src/litellm/model.ts +237 -0
- package/src/litellm/policy-attachment-form.ts +103 -0
- package/src/litellm/policy-attachment-operations.ts +74 -0
- package/src/litellm/policy-attachment-types.ts +48 -0
- package/src/litellm/policy-attachment.test.ts +198 -0
- package/src/litellm/policy-attachment.ts +178 -0
- package/src/litellm/policy-form.ts +122 -0
- package/src/litellm/policy-operations.ts +112 -0
- package/src/litellm/policy-types.ts +58 -0
- package/src/litellm/policy.test.ts +214 -0
- package/src/litellm/policy.ts +146 -0
- package/src/litellm/providers.ts +24 -3
- package/src/litellm/registry-errors.ts +88 -0
- package/src/litellm/registry-exports.test.ts +66 -0
- package/src/litellm/registry-support.ts +109 -0
- package/src/litellm/team-form.ts +140 -0
- package/src/litellm/team-members.test.ts +150 -0
- package/src/litellm/team-members.ts +58 -0
- package/src/litellm/team-operations.ts +90 -0
- package/src/litellm/team-permission.ts +159 -0
- package/src/litellm/team-read.test.ts +89 -0
- package/src/litellm/team-types.ts +106 -0
- package/src/litellm/team.test.ts +206 -0
- package/src/litellm/team.ts +159 -0
- package/src/litellm/tool-policy-form.ts +94 -0
- package/src/litellm/tool-policy-operations.ts +58 -0
- package/src/litellm/tool-policy-types.ts +48 -0
- package/src/litellm/tool-policy.test.ts +172 -0
- package/src/litellm/tool-policy.ts +125 -0
- package/src/litellm/toolset-form.ts +104 -0
- package/src/litellm/toolset-operations.ts +90 -0
- package/src/litellm/toolset-types.ts +47 -0
- package/src/litellm/toolset.test.ts +198 -0
- package/src/litellm/toolset.ts +151 -0
- package/src/ownership/ownership.test.ts +33 -1
- package/src/ownership/rows.ts +53 -0
- package/src/postgres/connection.ts +42 -7
- package/src/postgres/database-bigint-serialization.test.ts +1 -0
- package/src/postgres/database-refusals.test.ts +2 -2
- package/src/postgres/database-sql.ts +36 -9
- package/src/postgres/fake-grants-parse.ts +189 -0
- package/src/postgres/fake-grants-read.ts +250 -0
- package/src/postgres/fake-grants-sql.ts +207 -0
- package/src/postgres/fake-grants-write.ts +90 -0
- package/src/postgres/fake-role-sql.ts +240 -0
- package/src/postgres/fake-schema-semantics.test.ts +36 -0
- package/src/postgres/fake-schema-sql.ts +146 -0
- package/src/postgres/fake-sql-parse.ts +86 -0
- package/src/postgres/fake-sql-quote.ts +36 -0
- package/src/postgres/fake-sql.ts +166 -46
- package/src/postgres/fixtures/pg-REL_18_6-acl.h.txt +147 -0
- package/src/postgres/fixtures/pg-REL_18_6-aclexplode-func.txt +31 -0
- package/src/postgres/fixtures/pg-REL_18_6-alter-default-privileges-synopsis.txt +82 -0
- package/src/postgres/fixtures/pg-REL_18_6-alter_role.sgml.txt +44 -0
- package/src/postgres/fixtures/pg-REL_18_6-create_role.sgml.txt +26 -0
- package/src/postgres/fixtures/pg-REL_18_6-grant-synopsis.txt +95 -0
- package/src/postgres/fixtures/pg-REL_18_6-pg_attribute.h.txt +24 -0
- package/src/postgres/fixtures/pg-REL_18_6-pg_auth_members.h.txt +62 -0
- package/src/postgres/fixtures/pg-REL_18_6-pg_authid.h.txt +70 -0
- package/src/postgres/fixtures/pg-REL_18_6-pg_class.h.txt +33 -0
- package/src/postgres/fixtures/pg-REL_18_6-pg_default_acl.h.txt +81 -0
- package/src/postgres/fixtures/pg-REL_18_6-pg_namespace.h.txt +28 -0
- package/src/postgres/fixtures/pg-REL_18_6-revoke-synopsis.txt +124 -0
- package/src/postgres/grants-acl.test.ts +61 -0
- package/src/postgres/grants-attrs.ts +185 -0
- package/src/postgres/grants-database.test.ts +158 -0
- package/src/postgres/grants-declare.ts +172 -0
- package/src/postgres/grants-delete-proof.test.ts +154 -0
- package/src/postgres/grants-diff.ts +101 -0
- package/src/postgres/grants-errors.ts +215 -0
- package/src/postgres/grants-existence-guards.test.ts +113 -0
- package/src/postgres/grants-existence.ts +101 -0
- package/src/postgres/grants-lifecycle-guards.test.ts +208 -0
- package/src/postgres/grants-lifecycle-repair.test.ts +208 -0
- package/src/postgres/grants-lifecycle.test.ts +181 -0
- package/src/postgres/grants-ops.ts +229 -0
- package/src/postgres/grants-owner-revoke.test.ts +121 -0
- package/src/postgres/grants-ownership.ts +49 -0
- package/src/postgres/grants-plan-collateral.test.ts +202 -0
- package/src/postgres/grants-plan-diff.test.ts +204 -0
- package/src/postgres/grants-plan-restore.ts +43 -0
- package/src/postgres/grants-plan-revocations.test.ts +69 -0
- package/src/postgres/grants-plan.test.ts +148 -0
- package/src/postgres/grants-plan.ts +245 -0
- package/src/postgres/grants-provenance.test.ts +134 -0
- package/src/postgres/grants-psql-lifecycle.test.ts +105 -0
- package/src/postgres/grants-read-absent.test.ts +91 -0
- package/src/postgres/grants-read-defaults.ts +51 -0
- package/src/postgres/grants-read.ts +250 -0
- package/src/postgres/grants-refusals.test.ts +136 -0
- package/src/postgres/grants-refuse.ts +119 -0
- package/src/postgres/grants-relkind-wire.test.ts +111 -0
- package/src/postgres/grants-repair-plan.test.ts +201 -0
- package/src/postgres/grants-sql.test.ts +128 -0
- package/src/postgres/grants-sql.ts +144 -0
- package/src/postgres/grants-words.ts +34 -0
- package/src/postgres/grants.ts +110 -0
- package/src/postgres/index.ts +129 -5
- package/src/postgres/installed-classifier.ts +36 -0
- package/src/postgres/providers.ts +33 -9
- package/src/postgres/psql-executor-escaping.test.ts +67 -0
- package/src/postgres/psql-executor.test.ts +63 -2
- package/src/postgres/psql-executor.ts +74 -34
- package/src/postgres/role-adopt.test.ts +98 -0
- package/src/postgres/role-attrs.ts +137 -0
- package/src/postgres/role-diff.ts +93 -0
- package/src/postgres/role-errors.ts +206 -0
- package/src/postgres/role-guard.test.ts +60 -0
- package/src/postgres/role-identity.test.ts +197 -0
- package/src/postgres/role-lifecycle.test.ts +228 -0
- package/src/postgres/role-membership-options.test.ts +73 -0
- package/src/postgres/role-membership-repair.test.ts +153 -0
- package/src/postgres/role-membership-sql.ts +223 -0
- package/src/postgres/role-password-ascii.test.ts +53 -0
- package/src/postgres/role-password-transports.test.ts +123 -0
- package/src/postgres/role-password.test.ts +158 -0
- package/src/postgres/role-privilege.test.ts +107 -0
- package/src/postgres/role-provenance.test.ts +200 -0
- package/src/postgres/role-provider.ts +105 -0
- package/src/postgres/role-refusals.test.ts +225 -0
- package/src/postgres/role-scram.test.ts +38 -0
- package/src/postgres/role-scram.ts +40 -0
- package/src/postgres/role-secrets.ts +61 -0
- package/src/postgres/role-sql.ts +213 -0
- package/src/postgres/role-valid-until.test.ts +68 -0
- package/src/postgres/role.ts +226 -0
- package/src/postgres/schema-assert.ts +139 -0
- package/src/postgres/schema-attrs.ts +71 -0
- package/src/postgres/schema-delete-proofs.test.ts +192 -0
- package/src/postgres/schema-delete.ts +96 -0
- package/src/postgres/schema-diff.ts +44 -0
- package/src/postgres/schema-drop-2bp01.test.ts +146 -0
- package/src/postgres/schema-errors.ts +209 -0
- package/src/postgres/schema-handlers.test.ts +193 -0
- package/src/postgres/schema-identity.ts +39 -0
- package/src/postgres/schema-lifecycle.test.ts +246 -0
- package/src/postgres/schema-race.test.ts +70 -0
- package/src/postgres/schema-reconcile.ts +100 -0
- package/src/postgres/schema-refusals.test.ts +144 -0
- package/src/postgres/schema-socket.test.ts +162 -0
- package/src/postgres/schema-sql.ts +130 -0
- package/src/postgres/schema-takeover.test.ts +149 -0
- package/src/postgres/schema-test-kit.ts +85 -0
- package/src/postgres/schema.ts +130 -0
- package/src/release/binary-alias.test.ts +3 -3
- package/src/release/binary-claims.test.ts +3 -3
- package/src/release/binary-directory-umask.test.ts +65 -0
- package/src/release/fake-engine.ts +15 -0
- package/src/valkey/acl-attrs.ts +98 -0
- package/src/valkey/acl-compare.ts +57 -0
- package/src/valkey/acl-connection.ts +13 -0
- package/src/valkey/acl-delete.test.ts +127 -0
- package/src/valkey/acl-form.ts +239 -0
- package/src/valkey/acl-managed.ts +13 -0
- package/src/valkey/acl-ops.ts +122 -0
- package/src/valkey/acl-ownership.test.ts +118 -0
- package/src/valkey/acl-prefix.test.ts +38 -0
- package/src/valkey/acl-profiles.ts +81 -0
- package/src/valkey/acl-reconcile.ts +180 -0
- package/src/valkey/acl-reserved.test.ts +69 -0
- package/src/valkey/acl-revocation.test.ts +94 -0
- package/src/valkey/acl-seat-prefix.test.ts +111 -0
- package/src/valkey/acl-validation.test.ts +54 -0
- package/src/valkey/acl.test.ts +215 -0
- package/src/valkey/acl.ts +169 -0
- package/src/valkey/connection-service.ts +46 -0
- package/src/valkey/connection.ts +180 -0
- package/src/valkey/errors.ts +239 -0
- package/src/valkey/fake-acl.ts +128 -0
- package/src/valkey/fake-valkey.ts +224 -0
- package/src/valkey/handler-test-fixture.ts +43 -0
- package/src/valkey/handlers.test.ts +205 -0
- package/src/valkey/index.ts +54 -0
- package/src/valkey/instance-attrs.ts +48 -0
- package/src/valkey/instance-form.ts +104 -0
- package/src/valkey/instance.test.ts +108 -0
- package/src/valkey/instance.ts +160 -0
- package/src/valkey/provider-socket-fixture.ts +71 -0
- package/src/valkey/providers.test.ts +129 -0
- package/src/valkey/providers.ts +21 -0
- package/src/valkey/resp.ts +212 -0
- package/src/valkey/transport-bounds.test.ts +150 -0
- package/src/valkey/transport-error.ts +37 -0
- package/src/valkey/transport.test.ts +158 -0
- package/src/valkey/transport.ts +109 -0
- package/src/valkey/upstream-bounds.test.ts +14 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Props and live attributes for `Postgres.Schema`.
|
|
3
|
+
*
|
|
4
|
+
* Backed by `pg_namespace` (`nspname`, `nspowner`, `oid`) and `pg_description`
|
|
5
|
+
* (`obj_description(n.oid, 'pg_namespace')`).
|
|
6
|
+
*
|
|
7
|
+
* `CREATE SCHEMA` options are limited: only `IF NOT EXISTS`, the schema name and an optional
|
|
8
|
+
* `AUTHORIZATION` role. No altering option exists for a schema (`ALTER SCHEMA` only renames or
|
|
9
|
+
* changes owner in Postgres, neither of which this family implements — see `docs/postgres.md`
|
|
10
|
+
* for why `Postgres.Database` refuses all `ALTER DATABASE`).
|
|
11
|
+
*/
|
|
12
|
+
import { POSTGRES_NAME_MAX_BYTES, utf8ByteLength } from './database-attrs.ts';
|
|
13
|
+
|
|
14
|
+
export interface PostgresSchemaProps {
|
|
15
|
+
/** Schema name. At most 63 UTF-8 bytes (`NAMEDATALEN`), refused at plan. */
|
|
16
|
+
readonly name: string;
|
|
17
|
+
/**
|
|
18
|
+
* The database the schema lives in. The family connection points at a maintenance database
|
|
19
|
+
* (`docs/postgres.md#measured-path` — a brand-new database cannot be connected to on a cold
|
|
20
|
+
* plan), so the schema handlers open THIS database instead and prove it with
|
|
21
|
+
* `current_database()` (`PostgresSchemaWrongDatabase`) before any write. A change is refused
|
|
22
|
+
* at plan (`PostgresSchemaDatabaseRefused`) the same way a rename is.
|
|
23
|
+
*/
|
|
24
|
+
readonly database: string;
|
|
25
|
+
/** Owning role; becomes `AUTHORIZATION` in `CREATE SCHEMA`. The role must already exist. */
|
|
26
|
+
readonly owner?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Optional `COMMENT ON SCHEMA`. Stored in `pg_description`. A declared `''` IS "no comment":
|
|
29
|
+
* Postgres stores an empty comment as NULL, so it is normalized to `undefined`
|
|
30
|
+
* (`normalizedComment`) rather than compared against a live NULL forever.
|
|
31
|
+
*/
|
|
32
|
+
readonly comment?: string;
|
|
33
|
+
/**
|
|
34
|
+
* Whether `DELETE` with `RemovalPolicy.destroy()` may cascade into objects in the schema.
|
|
35
|
+
* Default `false`: `DROP SCHEMA` refuses when the schema is not empty.
|
|
36
|
+
*/
|
|
37
|
+
readonly cascade?: boolean;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface PostgresSchemaAttributes {
|
|
41
|
+
/** Schema name (`pg_namespace.nspname`). */
|
|
42
|
+
readonly name: string;
|
|
43
|
+
/** The database the row was read from (`current_database()`), equal to the declared prop on
|
|
44
|
+
* every honest read — the row itself carries the proof of where the statement ran. */
|
|
45
|
+
readonly database: string;
|
|
46
|
+
/** Owner role name (`pg_get_userbyid(nspowner)`). */
|
|
47
|
+
readonly owner: string;
|
|
48
|
+
/** Comment from `obj_description`, `null` when none. */
|
|
49
|
+
readonly comment: string | null;
|
|
50
|
+
/** `pg_namespace` OID, read as a native `oid` number. */
|
|
51
|
+
readonly oid: number;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* A declared `''` comment means "no comment": `COMMENT ON SCHEMA … IS ''` deletes the comment in
|
|
56
|
+
* Postgres (the stored value becomes NULL), so treating `''` as a value would drift against the
|
|
57
|
+
* live NULL on every later plan — a permanent update loop. Normalizing it to `undefined` keeps
|
|
58
|
+
* `''` and an absent comment identical everywhere they are compared.
|
|
59
|
+
*/
|
|
60
|
+
export const normalizedComment = (comment: string | undefined): string | undefined =>
|
|
61
|
+
comment === '' ? undefined : comment;
|
|
62
|
+
|
|
63
|
+
/** Refuse names PostgreSQL would silently truncate (see `database-attrs.ts`). */
|
|
64
|
+
export const schemaNameByteRefusal = (
|
|
65
|
+
name: string,
|
|
66
|
+
): { readonly byteLength: number; readonly limit: number } | undefined => {
|
|
67
|
+
const byteLength = utf8ByteLength(name);
|
|
68
|
+
return byteLength > POSTGRES_NAME_MAX_BYTES
|
|
69
|
+
? { byteLength, limit: POSTGRES_NAME_MAX_BYTES }
|
|
70
|
+
: undefined;
|
|
71
|
+
};
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The red-team-proven delete and read contracts of `Postgres.Schema` (PR #334, 2026-09-30),
|
|
3
|
+
* over the runner transport — the exact scenarios the Opus review measured live.
|
|
4
|
+
*
|
|
5
|
+
* 1. DELETE DROPS ONLY WHAT IT CAN PROVE IT CREATED. The engine does not re-read before a
|
|
6
|
+
* delete that has state (alchemy `Apply.ts`), so a schema dropped and recreated out of
|
|
7
|
+
* band under the same name — another role's, with its own objects — was dropped by NAME,
|
|
8
|
+
* `CASCADE` included. The handler now re-reads first: absent is idempotent success, and a
|
|
9
|
+
* live row whose `oid` or `owner` no longer matches the persisted proof is a typed
|
|
10
|
+
* `PostgresSchemaDeleteForeignRefused`, never a `DROP`.
|
|
11
|
+
* 2. A MISSING DECLARED DATABASE IS "SCHEMA ABSENT". A cold plan's `read` used to open the
|
|
12
|
+
* declared database directly and fail untyped (`ConnectionError` over psql, `UnknownError`
|
|
13
|
+
* 3D000 over the socket); now both `read` and `delete` probe `pg_database` over the FAMILY
|
|
14
|
+
* connection first and treat absence as schema-absence — the delete stays idempotent.
|
|
15
|
+
*/
|
|
16
|
+
import { describe, expect, test } from 'bun:test';
|
|
17
|
+
import * as Effect from 'effect/Effect';
|
|
18
|
+
import { makePsqlExecutor } from './psql-executor.ts';
|
|
19
|
+
import { postgresRunnerConnection } from './connection.ts';
|
|
20
|
+
import { deleteWithClient, postgresSchemaHandlers } from './schema.ts';
|
|
21
|
+
import { PostgresSchemaDeleteForeignRefused } from './schema-errors.ts';
|
|
22
|
+
import type { PostgresSchemaAttributes, PostgresSchemaProps } from './schema-attrs.ts';
|
|
23
|
+
import { deleteArgs, readArgs, route, router, runnerWith } from './schema-test-kit.ts';
|
|
24
|
+
|
|
25
|
+
if (postgresSchemaHandlers.read === undefined) {
|
|
26
|
+
throw new Error('Postgres.Schema is missing its read handler');
|
|
27
|
+
}
|
|
28
|
+
/** Narrowed once at module scope — the narrowing does not survive into `test` callbacks. */
|
|
29
|
+
const schemaRead = postgresSchemaHandlers.read;
|
|
30
|
+
|
|
31
|
+
/** The out-of-band recreation scenario the review measured: created by `seat_role` (oid 16442),
|
|
32
|
+
* dropped and recreated by `other_role` with a table and a row (oid 16443). */
|
|
33
|
+
const declared: PostgresSchemaProps = {
|
|
34
|
+
name: 's4',
|
|
35
|
+
database: 'agents',
|
|
36
|
+
owner: 'seat_role',
|
|
37
|
+
};
|
|
38
|
+
const persisted: PostgresSchemaAttributes = {
|
|
39
|
+
name: 's4',
|
|
40
|
+
database: 'agents',
|
|
41
|
+
oid: 16442,
|
|
42
|
+
owner: 'seat_role',
|
|
43
|
+
comment: null,
|
|
44
|
+
};
|
|
45
|
+
/** `oid` crosses the runner as a JSON string; the executor normalizes it to a number. */
|
|
46
|
+
const schemaRow = (oid: number, owner: string) =>
|
|
47
|
+
JSON.stringify([{ name: 's4', oid: String(oid), owner, comment: null, database: 'agents' }]);
|
|
48
|
+
/** The full router for a delete whose declared database exists. */
|
|
49
|
+
const answers = (schema: string) => ({
|
|
50
|
+
probe: '[{"present":1}]',
|
|
51
|
+
schema,
|
|
52
|
+
empty: '[{"empty":true}]',
|
|
53
|
+
proof: '[{"database":"agents"}]',
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
describe('delete drops only what it can prove it created (Important 1)', () => {
|
|
57
|
+
test('an absent schema is idempotent success — no DROP issued', async () => {
|
|
58
|
+
const { run, stdins } = runnerWith(router(answers('[]')));
|
|
59
|
+
await Effect.runPromise(
|
|
60
|
+
postgresSchemaHandlers
|
|
61
|
+
.delete(deleteArgs({ ...declared, cascade: true }, persisted))
|
|
62
|
+
.pipe(
|
|
63
|
+
Effect.provide(
|
|
64
|
+
postgresRunnerConnection({ run, database: 'postgres', username: 'postgres' }),
|
|
65
|
+
),
|
|
66
|
+
),
|
|
67
|
+
);
|
|
68
|
+
expect(stdins.some((s) => s.startsWith('DROP SCHEMA'))).toBe(false);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test('refuses on oid mismatch, CASCADE included — no DROP issued', async () => {
|
|
72
|
+
// The recreated row kept the declared owner but a different oid: the persisted proof
|
|
73
|
+
// cannot vouch for it, so the handler refuses before the emptiness check or any DROP.
|
|
74
|
+
const { run, stdins } = runnerWith(router(answers(schemaRow(16443, 'seat_role'))));
|
|
75
|
+
const error = await Effect.runPromise(
|
|
76
|
+
Effect.flip(
|
|
77
|
+
postgresSchemaHandlers
|
|
78
|
+
.delete(deleteArgs({ ...declared, cascade: true }, persisted))
|
|
79
|
+
.pipe(
|
|
80
|
+
Effect.provide(
|
|
81
|
+
postgresRunnerConnection({ run, database: 'postgres', username: 'postgres' }),
|
|
82
|
+
),
|
|
83
|
+
),
|
|
84
|
+
),
|
|
85
|
+
);
|
|
86
|
+
expect(error).toBeInstanceOf(PostgresSchemaDeleteForeignRefused);
|
|
87
|
+
expect(error).toMatchObject({
|
|
88
|
+
schema: 's4',
|
|
89
|
+
liveOid: 16443,
|
|
90
|
+
liveOwner: 'seat_role',
|
|
91
|
+
lastOid: 16442,
|
|
92
|
+
lastOwner: 'seat_role',
|
|
93
|
+
});
|
|
94
|
+
expect(stdins.some((s) => s.startsWith('DROP SCHEMA'))).toBe(false);
|
|
95
|
+
// Refused before the guarded drop, so the emptiness check never ran either.
|
|
96
|
+
expect(stdins.some((s) => s.includes('AS empty'))).toBe(false);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test('refuses on owner mismatch — no DROP issued', async () => {
|
|
100
|
+
// Same oid, another role: the schema under this name is no longer the one this resource
|
|
101
|
+
// created, and its objects must survive the delete.
|
|
102
|
+
const { run, stdins } = runnerWith(router(answers(schemaRow(16442, 'other_role'))));
|
|
103
|
+
const error = await Effect.runPromise(
|
|
104
|
+
Effect.flip(
|
|
105
|
+
postgresSchemaHandlers
|
|
106
|
+
.delete(deleteArgs(declared, persisted))
|
|
107
|
+
.pipe(
|
|
108
|
+
Effect.provide(
|
|
109
|
+
postgresRunnerConnection({ run, database: 'postgres', username: 'postgres' }),
|
|
110
|
+
),
|
|
111
|
+
),
|
|
112
|
+
),
|
|
113
|
+
);
|
|
114
|
+
expect(error).toBeInstanceOf(PostgresSchemaDeleteForeignRefused);
|
|
115
|
+
expect(error).toMatchObject({
|
|
116
|
+
liveOid: 16442,
|
|
117
|
+
liveOwner: 'other_role',
|
|
118
|
+
lastOid: 16442,
|
|
119
|
+
lastOwner: 'seat_role',
|
|
120
|
+
});
|
|
121
|
+
expect(stdins.some((s) => s.startsWith('DROP SCHEMA'))).toBe(false);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test('a live row with no persisted proof fails closed — the delete client core refuses', async () => {
|
|
125
|
+
// The engine passes state whenever it deletes, but the handler contract allows an
|
|
126
|
+
// `undefined` output: no proof means no vouching, so a live row is refused, not dropped.
|
|
127
|
+
const { run, stdins } = runnerWith(router(answers(schemaRow(16443, 'other_role'))));
|
|
128
|
+
const pg = makePsqlExecutor(run, { database: 'agents', username: 'postgres' });
|
|
129
|
+
const error = await Effect.runPromise(Effect.flip(deleteWithClient(pg, declared, undefined)));
|
|
130
|
+
expect(error).toBeInstanceOf(PostgresSchemaDeleteForeignRefused);
|
|
131
|
+
expect(error).toMatchObject({
|
|
132
|
+
liveOid: 16443,
|
|
133
|
+
liveOwner: 'other_role',
|
|
134
|
+
lastOid: undefined,
|
|
135
|
+
lastOwner: undefined,
|
|
136
|
+
});
|
|
137
|
+
expect(stdins.some((s) => s.startsWith('DROP SCHEMA'))).toBe(false);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
describe('a missing declared database is schema absent (Important 2)', () => {
|
|
142
|
+
test('delete of a schema whose declared database is gone is idempotent success', async () => {
|
|
143
|
+
// The probe answers ABSENT: only that one statement ran — over the FAMILY connection
|
|
144
|
+
// (its argv targets the maintenance database), never a connection to `agents`.
|
|
145
|
+
const { run, stdins, argvs } = runnerWith(router({ probe: '[]' }));
|
|
146
|
+
await Effect.runPromise(
|
|
147
|
+
postgresSchemaHandlers
|
|
148
|
+
.delete(deleteArgs({ ...declared, cascade: true }, persisted))
|
|
149
|
+
.pipe(
|
|
150
|
+
Effect.provide(
|
|
151
|
+
postgresRunnerConnection({ run, database: 'postgres', username: 'postgres' }),
|
|
152
|
+
),
|
|
153
|
+
),
|
|
154
|
+
);
|
|
155
|
+
expect(stdins.length).toBe(1);
|
|
156
|
+
expect(stdins[0]).toContain('FROM pg_database');
|
|
157
|
+
expect(argvs.length).toBe(1);
|
|
158
|
+
expect(argvs[0]?.at(-1)).toBe('postgres');
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
test('read of a schema whose declared database is gone answers absent, untyped connect never happens', async () => {
|
|
162
|
+
const { run, stdins } = runnerWith((stdin) => route(stdin, { probe: '[]' }) ?? '');
|
|
163
|
+
const result = await Effect.runPromise(
|
|
164
|
+
schemaRead(readArgs(declared)).pipe(
|
|
165
|
+
Effect.provide(
|
|
166
|
+
postgresRunnerConnection({ run, database: 'postgres', username: 'postgres' }),
|
|
167
|
+
),
|
|
168
|
+
),
|
|
169
|
+
);
|
|
170
|
+
expect(result).toBeUndefined();
|
|
171
|
+
expect(stdins.length).toBe(1);
|
|
172
|
+
expect(stdins[0]).toContain('FROM pg_database');
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
test('the `database` override reaches `psql -d`: the probe targets the family database, the rest the declared one', async () => {
|
|
176
|
+
// A live delete over a declared `agents`: the probe's argv runs `-d postgres` (the family
|
|
177
|
+
// connection), while every statement after it runs `-d agents` (the override).
|
|
178
|
+
const { run, stdins, argvs } = runnerWith(router(answers(schemaRow(16442, 'seat_role'))));
|
|
179
|
+
await Effect.runPromise(
|
|
180
|
+
postgresSchemaHandlers
|
|
181
|
+
.delete(deleteArgs(declared, persisted))
|
|
182
|
+
.pipe(
|
|
183
|
+
Effect.provide(
|
|
184
|
+
postgresRunnerConnection({ run, database: 'postgres', username: 'postgres' }),
|
|
185
|
+
),
|
|
186
|
+
),
|
|
187
|
+
);
|
|
188
|
+
expect(stdins.some((s) => s.startsWith('DROP SCHEMA'))).toBe(true);
|
|
189
|
+
expect(argvs[0]?.at(-1)).toBe('postgres');
|
|
190
|
+
expect(argvs.slice(1).every((argv) => argv.at(-1) === 'agents')).toBe(true);
|
|
191
|
+
});
|
|
192
|
+
});
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `Postgres.Schema`'s drop path: prove the connection, prove the schema is still ours, then
|
|
3
|
+
* the guarded `DROP SCHEMA`.
|
|
4
|
+
*
|
|
5
|
+
* ⛔ THE ENGINE DOES NOT RE-READ BEFORE A DELETE THAT HAS STATE (alchemy `Apply.ts`). When
|
|
6
|
+
* persisted attributes exist, `delete` receives the LAST asserted `oid` + `owner` and no
|
|
7
|
+
* fresh row — a schema dropped out of band and recreated under the same name by another role
|
|
8
|
+
* would be dropped by name, `CASCADE` included, destroying their objects.
|
|
9
|
+
* `deleteWithClient` re-reads `pg_namespace` first: absent is idempotent success, and a live
|
|
10
|
+
* row that no longer matches the persisted proof fails with
|
|
11
|
+
* `PostgresSchemaDeleteForeignRefused` (`schema-assert.ts#deleteForeignRefusal`) before any
|
|
12
|
+
* `DROP` is issued.
|
|
13
|
+
*/
|
|
14
|
+
import * as Effect from 'effect/Effect';
|
|
15
|
+
import type { SqlError } from 'effect/unstable/sql/SqlError';
|
|
16
|
+
import type { PgExecutor } from './database-sql.ts';
|
|
17
|
+
import type { PostgresSchemaAttributes, PostgresSchemaProps } from './schema-attrs.ts';
|
|
18
|
+
import { assertDatabase, deleteForeignRefusal } from './schema-assert.ts';
|
|
19
|
+
import {
|
|
20
|
+
type PostgresSchemaDeleteForeignRefused,
|
|
21
|
+
PostgresSchemaDropNotEmptyError,
|
|
22
|
+
type PostgresSchemaWrongDatabase,
|
|
23
|
+
} from './schema-errors.ts';
|
|
24
|
+
import {
|
|
25
|
+
buildDropSchemaSql,
|
|
26
|
+
isDependentObjectsError,
|
|
27
|
+
schemaIsEmpty,
|
|
28
|
+
selectSchema,
|
|
29
|
+
} from './schema-sql.ts';
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The guarded `DROP SCHEMA`, against any {@link PgExecutor}: refuses a non-empty schema
|
|
33
|
+
* without `cascade`, and classifies the server's own `2BP01` refusal as the same typed tag —
|
|
34
|
+
* for an object kind the emptiness check's four catalogs do not cover. Callers have already
|
|
35
|
+
* proven the connected database (`assertDatabase`) and, on the delete path, the schema's
|
|
36
|
+
* ownership.
|
|
37
|
+
*/
|
|
38
|
+
const dropGuarded = (
|
|
39
|
+
pg: PgExecutor,
|
|
40
|
+
props: PostgresSchemaProps,
|
|
41
|
+
): Effect.Effect<void, PostgresSchemaDropNotEmptyError | SqlError> =>
|
|
42
|
+
Effect.gen(function* () {
|
|
43
|
+
if (props.cascade !== true) {
|
|
44
|
+
const empty = yield* schemaIsEmpty(pg, props.name);
|
|
45
|
+
if (!empty) {
|
|
46
|
+
return yield* Effect.fail(new PostgresSchemaDropNotEmptyError({ schema: props.name }));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// The server's own `2BP01` refusal (an object kind the four catalogs miss) is classified
|
|
50
|
+
// into the same typed tag the emptiness check raises — one fail branch, classified before
|
|
51
|
+
// the fail, exactly as `database-sql.ts` classifies the `42P04` race.
|
|
52
|
+
const dropRefusal = (error: SqlError): PostgresSchemaDropNotEmptyError | SqlError =>
|
|
53
|
+
props.cascade !== true && isDependentObjectsError(error)
|
|
54
|
+
? new PostgresSchemaDropNotEmptyError({ schema: props.name })
|
|
55
|
+
: error;
|
|
56
|
+
yield* pg.unsafe(buildDropSchemaSql(props.name, props.cascade === true)).pipe(
|
|
57
|
+
Effect.asVoid,
|
|
58
|
+
Effect.catchTag('SqlError', (error) => Effect.fail(dropRefusal(error))),
|
|
59
|
+
);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
/** Prove the connected database, then the guarded drop — the drop core on its own, for the
|
|
63
|
+
* tests that drive it directly. */
|
|
64
|
+
export const dropWithClient = (
|
|
65
|
+
pg: PgExecutor,
|
|
66
|
+
props: PostgresSchemaProps,
|
|
67
|
+
): Effect.Effect<void, PostgresSchemaWrongDatabase | PostgresSchemaDropNotEmptyError | SqlError> =>
|
|
68
|
+
Effect.gen(function* () {
|
|
69
|
+
yield* assertDatabase(props, pg);
|
|
70
|
+
yield* dropGuarded(pg, props);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* The core of `delete`: re-read first (see the file header), refuse a schema the persisted
|
|
75
|
+
* proof cannot vouch for, then the guarded drop. `output` is the persisted state the engine
|
|
76
|
+
* hands over — `undefined` is no proof and refuses too.
|
|
77
|
+
*/
|
|
78
|
+
export const deleteWithClient = (
|
|
79
|
+
pg: PgExecutor,
|
|
80
|
+
props: PostgresSchemaProps,
|
|
81
|
+
output: PostgresSchemaAttributes | undefined,
|
|
82
|
+
): Effect.Effect<
|
|
83
|
+
void,
|
|
84
|
+
| PostgresSchemaWrongDatabase
|
|
85
|
+
| PostgresSchemaDeleteForeignRefused
|
|
86
|
+
| PostgresSchemaDropNotEmptyError
|
|
87
|
+
| SqlError
|
|
88
|
+
> =>
|
|
89
|
+
Effect.gen(function* () {
|
|
90
|
+
yield* assertDatabase(props, pg);
|
|
91
|
+
const live = yield* selectSchema(pg, props.name);
|
|
92
|
+
if (live === undefined) return;
|
|
93
|
+
const refusal = deleteForeignRefusal(props, live, output);
|
|
94
|
+
if (refusal !== undefined) return yield* Effect.fail(refusal);
|
|
95
|
+
yield* dropGuarded(pg, props);
|
|
96
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `Postgres.Schema`'s plan-time diff — entirely offline: `news` (declared) against `output`
|
|
3
|
+
* (last-applied attributes) and `olds` (last-applied props), never a live query (that
|
|
4
|
+
* authoritative check is `reconcileWithClient`'s, per S10). Extracted from `schema.ts` to keep
|
|
5
|
+
* each file under the house's 250-line cap.
|
|
6
|
+
*
|
|
7
|
+
* ⛔ `cascade` COMPARES AGAINST `olds`, NOT `output`. Attributes are the live row (name,
|
|
8
|
+
* database, owner, comment, oid) — `cascade` is a prop-only concern no catalog column
|
|
9
|
+
* carries. The engine's noop branch (`Apply.ts`) commits the OLD props unchanged, so a
|
|
10
|
+
* `cascade` flip must answer `update` to reach the persisted state at all: a schema first
|
|
11
|
+
* declared `cascade: true` and later set to `false` would otherwise keep dropping with
|
|
12
|
+
* `CASCADE` on every delete, because `delete`'s `olds` are read from those persisted props.
|
|
13
|
+
*/
|
|
14
|
+
import { assertSchemaTarget } from './schema-identity.ts';
|
|
15
|
+
import { isResolved } from 'alchemy/Diff';
|
|
16
|
+
import type { Input } from 'alchemy/Input';
|
|
17
|
+
import * as Effect from 'effect/Effect';
|
|
18
|
+
import type { PostgresSchemaAttributes, PostgresSchemaProps } from './schema-attrs.ts';
|
|
19
|
+
import { normalizedComment, schemaNameByteRefusal } from './schema-attrs.ts';
|
|
20
|
+
import { PostgresSchemaNameRefused } from './schema-errors.ts';
|
|
21
|
+
|
|
22
|
+
/** Plan-time only: rename refused, over-long name refused, a database move refused; a `cascade`
|
|
23
|
+
* flip answers `update` so the new prop reaches state, and every other change answers `update`
|
|
24
|
+
* too (which `reconcileWithClient` then applies as create, or refuses as drift on a live
|
|
25
|
+
* schema). */
|
|
26
|
+
export const diffPostgresSchema = (
|
|
27
|
+
news: Input<PostgresSchemaProps>,
|
|
28
|
+
output: PostgresSchemaAttributes | undefined,
|
|
29
|
+
olds?: PostgresSchemaProps,
|
|
30
|
+
) =>
|
|
31
|
+
Effect.gen(function* () {
|
|
32
|
+
if (output === undefined || !isResolved(news)) return undefined;
|
|
33
|
+
yield* assertSchemaTarget(news, output);
|
|
34
|
+
const nameRefusal = schemaNameByteRefusal(news.name);
|
|
35
|
+
if (nameRefusal !== undefined) {
|
|
36
|
+
return yield* Effect.fail(new PostgresSchemaNameRefused({ name: news.name, ...nameRefusal }));
|
|
37
|
+
}
|
|
38
|
+
const comment = normalizedComment(news.comment);
|
|
39
|
+
const changed =
|
|
40
|
+
(news.owner !== undefined && news.owner !== output.owner) ||
|
|
41
|
+
(comment !== undefined && comment !== (output.comment ?? undefined)) ||
|
|
42
|
+
(news.cascade ?? false) !== (olds?.cascade ?? false);
|
|
43
|
+
return changed ? ({ action: 'update' } as const) : ({ action: 'noop' } as const);
|
|
44
|
+
});
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLSTATE `2BP01` (`dependent_objects_still_exist`) must become
|
|
3
|
+
* `PostgresSchemaDropNotEmptyError` on both transports.
|
|
4
|
+
*
|
|
5
|
+
* Measured at `@effect/sql-pg@4.0.0-rc.115` `src/internal/sqlError.ts#classifySqlState`:
|
|
6
|
+
* only class `42` becomes `SqlSyntaxError`. `2BP01` is class `2B`, so the socket client
|
|
7
|
+
* wraps it as `UnknownError` with the raw code on `reason.cause.code`
|
|
8
|
+
* (`PgConnection.ts#classifyFields`). The runner transport copies that rule
|
|
9
|
+
* (`psql-executor.ts#failure`). A test that builds `SqlSyntaxError` by hand pins a shape
|
|
10
|
+
* neither driver produces.
|
|
11
|
+
*/
|
|
12
|
+
import { describe, expect, test } from 'bun:test';
|
|
13
|
+
import * as Effect from 'effect/Effect';
|
|
14
|
+
import type { SqlError } from 'effect/unstable/sql/SqlError';
|
|
15
|
+
import type { PgExecutor } from './database-sql.ts';
|
|
16
|
+
import { classifyInstalled } from './installed-classifier.ts';
|
|
17
|
+
import { postgresRunnerConnection } from './connection.ts';
|
|
18
|
+
import { type PsqlRunner, makePsqlExecutor } from './psql-executor.ts';
|
|
19
|
+
import { isDependentObjectsError } from './schema-sql.ts';
|
|
20
|
+
import { PostgresSchemaDropNotEmptyError } from './schema-errors.ts';
|
|
21
|
+
import { dropWithClient, postgresSchemaHandlers } from './schema.ts';
|
|
22
|
+
import type { PostgresSchemaAttributes, PostgresSchemaProps } from './schema-attrs.ts';
|
|
23
|
+
|
|
24
|
+
const baseProps: PostgresSchemaProps = { name: 'ledger', database: 'postgres', owner: 'tim' };
|
|
25
|
+
|
|
26
|
+
const socket2bp01 = (): Promise<SqlError> => classifyInstalled('2BP01');
|
|
27
|
+
|
|
28
|
+
/** Emptiness check says empty; the following DROP is the server's real `2BP01`. */
|
|
29
|
+
const emptyThenRefuse = (drop: Effect.Effect<ReadonlyArray<object>, SqlError>): PgExecutor => ({
|
|
30
|
+
unsafe: <A extends object>(text: string) => {
|
|
31
|
+
if (text.startsWith('SELECT current_database()')) {
|
|
32
|
+
return Effect.succeed([{ database: 'postgres' }] as unknown as ReadonlyArray<A>);
|
|
33
|
+
}
|
|
34
|
+
if (text.includes('AS empty')) {
|
|
35
|
+
return Effect.succeed([{ empty: true }] as unknown as ReadonlyArray<A>);
|
|
36
|
+
}
|
|
37
|
+
return drop as Effect.Effect<ReadonlyArray<A>, SqlError>;
|
|
38
|
+
},
|
|
39
|
+
transaction: () => Effect.void,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
describe('2BP01 classification', () => {
|
|
43
|
+
test('the installed socket classifier wraps 2BP01 as UnknownError, not SqlSyntaxError', async () => {
|
|
44
|
+
const error = await socket2bp01();
|
|
45
|
+
expect(error.reason._tag).toBe('UnknownError');
|
|
46
|
+
expect(isDependentObjectsError(error)).toBe(true);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test('dropWithClient classifies the socket 2BP01 shape as the typed not-empty tag', async () => {
|
|
50
|
+
const error = await Effect.runPromise(
|
|
51
|
+
Effect.flip(dropWithClient(emptyThenRefuse(Effect.fail(await socket2bp01())), baseProps)),
|
|
52
|
+
);
|
|
53
|
+
expect(error).toBeInstanceOf(PostgresSchemaDropNotEmptyError);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('the runner transport classifies a verbose 2BP01 line as the typed not-empty tag', async () => {
|
|
57
|
+
const run: PsqlRunner = ({ stdin }) => {
|
|
58
|
+
if (stdin.includes('current_database()')) {
|
|
59
|
+
return Promise.resolve({ code: 0, stdout: '[{"database":"postgres"}]', stderr: '' });
|
|
60
|
+
}
|
|
61
|
+
if (stdin.includes('AS empty')) {
|
|
62
|
+
return Promise.resolve({ code: 0, stdout: '[{"empty":true}]', stderr: '' });
|
|
63
|
+
}
|
|
64
|
+
return Promise.resolve({
|
|
65
|
+
code: 3,
|
|
66
|
+
stdout: '',
|
|
67
|
+
stderr: 'ERROR: 2BP01: dependent objects still exist\n',
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
const produced = await Effect.runPromise(
|
|
71
|
+
Effect.flip(
|
|
72
|
+
makePsqlExecutor(run, { database: 'postgres', username: 'postgres' }).unsafe(
|
|
73
|
+
'DROP SCHEMA IF EXISTS "ledger"',
|
|
74
|
+
),
|
|
75
|
+
),
|
|
76
|
+
);
|
|
77
|
+
expect(produced.reason._tag).toBe('UnknownError');
|
|
78
|
+
expect(isDependentObjectsError(produced)).toBe(true);
|
|
79
|
+
|
|
80
|
+
const error = await Effect.runPromise(
|
|
81
|
+
Effect.flip(
|
|
82
|
+
dropWithClient(
|
|
83
|
+
makePsqlExecutor(run, { database: 'postgres', username: 'postgres' }),
|
|
84
|
+
baseProps,
|
|
85
|
+
),
|
|
86
|
+
),
|
|
87
|
+
);
|
|
88
|
+
expect(error).toBeInstanceOf(PostgresSchemaDropNotEmptyError);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test('the real delete handler classifies a runner 2BP01 as the typed not-empty tag', async () => {
|
|
92
|
+
// Order is load-bearing (schema-handlers.test.ts#route): the probe must answer PRESENT so
|
|
93
|
+
// the absent-database short-circuit does not swallow the test, and the ownership re-read
|
|
94
|
+
// must answer the row the persisted output vouches for, so the delete reaches the DROP.
|
|
95
|
+
const run: PsqlRunner = ({ stdin }) => {
|
|
96
|
+
if (stdin.includes('AS empty')) {
|
|
97
|
+
return Promise.resolve({ code: 0, stdout: '[{"empty":true}]', stderr: '' });
|
|
98
|
+
}
|
|
99
|
+
if (stdin.includes('FROM pg_namespace')) {
|
|
100
|
+
return Promise.resolve({
|
|
101
|
+
code: 0,
|
|
102
|
+
stdout: '[{"name":"ledger","oid":1,"owner":"tim"}]',
|
|
103
|
+
stderr: '',
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
if (stdin.includes('FROM pg_database')) {
|
|
107
|
+
return Promise.resolve({ code: 0, stdout: '[{"present":1}]', stderr: '' });
|
|
108
|
+
}
|
|
109
|
+
if (stdin.includes('current_database()')) {
|
|
110
|
+
return Promise.resolve({ code: 0, stdout: '[{"database":"postgres"}]', stderr: '' });
|
|
111
|
+
}
|
|
112
|
+
return Promise.resolve({
|
|
113
|
+
code: 3,
|
|
114
|
+
stdout: '',
|
|
115
|
+
stderr: 'ERROR: 2BP01: dependent objects still exist\n',
|
|
116
|
+
});
|
|
117
|
+
};
|
|
118
|
+
const output: PostgresSchemaAttributes = {
|
|
119
|
+
name: 'ledger',
|
|
120
|
+
database: 'postgres',
|
|
121
|
+
oid: 1,
|
|
122
|
+
owner: 'tim',
|
|
123
|
+
comment: null,
|
|
124
|
+
};
|
|
125
|
+
const error = await Effect.runPromise(
|
|
126
|
+
Effect.flip(
|
|
127
|
+
postgresSchemaHandlers
|
|
128
|
+
.delete({
|
|
129
|
+
id: 'x',
|
|
130
|
+
fqn: 'x',
|
|
131
|
+
instanceId: 'x',
|
|
132
|
+
olds: baseProps,
|
|
133
|
+
output,
|
|
134
|
+
session: undefined as never,
|
|
135
|
+
bindings: [] as never,
|
|
136
|
+
})
|
|
137
|
+
.pipe(
|
|
138
|
+
Effect.provide(
|
|
139
|
+
postgresRunnerConnection({ run, database: 'postgres', username: 'postgres' }),
|
|
140
|
+
),
|
|
141
|
+
),
|
|
142
|
+
),
|
|
143
|
+
);
|
|
144
|
+
expect(error).toBeInstanceOf(PostgresSchemaDropNotEmptyError);
|
|
145
|
+
});
|
|
146
|
+
});
|