@homeflare/alchemy 0.42.0 → 0.44.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/budget-errors.d.ts +36 -0
- package/dist/litellm/budget-errors.d.ts.map +1 -0
- package/dist/litellm/budget-form.d.ts +50 -0
- package/dist/litellm/budget-form.d.ts.map +1 -0
- package/dist/litellm/budget-operations.d.ts +20 -0
- package/dist/litellm/budget-operations.d.ts.map +1 -0
- package/dist/litellm/budget.d.ts +61 -0
- package/dist/litellm/budget.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 +9 -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 +20 -0
- package/dist/litellm/index.d.ts.map +1 -1
- package/dist/litellm/index.js +3201 -2
- package/dist/litellm/index.js.map +70 -5
- 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/operations.d.ts +22 -0
- package/dist/litellm/operations.d.ts.map +1 -1
- 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/auth-role-form.d.ts +9 -0
- package/dist/openbao/auth-role-form.d.ts.map +1 -1
- package/dist/openbao/auth-role-wire.d.ts.map +1 -1
- package/dist/openbao/fake-engines-roles.d.ts.map +1 -1
- package/dist/openbao/index.js +43 -6
- package/dist/openbao/index.js.map +5 -5
- package/dist/ownership/rows.d.ts +11 -0
- package/dist/ownership/rows.d.ts.map +1 -1
- package/dist/postgres/connection.d.ts +32 -2
- package/dist/postgres/connection.d.ts.map +1 -1
- package/dist/postgres/database-sql.d.ts +28 -9
- package/dist/postgres/database-sql.d.ts.map +1 -1
- package/dist/postgres/database.d.ts +1 -1
- package/dist/postgres/database.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 +40 -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 +35 -8
- package/dist/postgres/index.d.ts.map +1 -1
- package/dist/postgres/index.js +2063 -39
- package/dist/postgres/index.js.map +47 -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 +17 -7
- package/dist/postgres/providers.d.ts.map +1 -1
- package/dist/postgres/psql-executor.d.ts +25 -0
- package/dist/postgres/psql-executor.d.ts.map +1 -0
- package/dist/postgres/role-attrs.d.ts +109 -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 +126 -0
- package/dist/postgres/role-errors.d.ts.map +1 -0
- package/dist/postgres/role-membership-sql.d.ts +75 -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 +6 -0
- package/dist/postgres/role-scram.d.ts.map +1 -0
- package/dist/postgres/role-secrets.d.ts +30 -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/ceph-flag-types.d.ts +57 -0
- package/dist/proxmox/ceph-flag-types.d.ts.map +1 -0
- package/dist/proxmox/ceph-flag-wire.d.ts +77 -0
- package/dist/proxmox/ceph-flag-wire.d.ts.map +1 -0
- package/dist/proxmox/ceph-flag.d.ts +15 -50
- package/dist/proxmox/ceph-flag.d.ts.map +1 -1
- package/dist/proxmox/ceph-osd-write.d.ts +10 -13
- package/dist/proxmox/ceph-osd-write.d.ts.map +1 -1
- package/dist/proxmox/index.js +806 -740
- package/dist/proxmox/index.js.map +9 -8
- 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-budget.md +55 -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 -8
- 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 +114 -0
- package/docs/postgres-schema.md +139 -0
- package/docs/postgres.md +39 -0
- package/docs/proxmox-sdk-migration.md +45 -0
- package/docs/valkey-transport.md +29 -0
- package/docs/valkey.md +187 -0
- package/package.json +7 -3
- 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/budget-errors.ts +38 -0
- package/src/litellm/budget-form.ts +94 -0
- package/src/litellm/budget-operations.ts +51 -0
- package/src/litellm/budget.test.ts +105 -0
- package/src/litellm/budget.ts +127 -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 +66 -7
- 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 +153 -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/operations.ts +1 -1
- 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 +25 -1
- 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/openbao/auth-role-form.test.ts +37 -0
- package/src/openbao/auth-role-form.ts +12 -1
- package/src/openbao/auth-role-wire.test.ts +1 -0
- package/src/openbao/auth-role-wire.ts +13 -1
- package/src/openbao/distilled-retry.test.ts +1 -0
- package/src/openbao/fake-engines-roles.ts +7 -1
- package/src/ownership/ownership.test.ts +33 -1
- package/src/ownership/rows.ts +53 -0
- package/src/postgres/connection.ts +72 -3
- 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 +40 -12
- package/src/postgres/database.ts +3 -2
- 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 +220 -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 +161 -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 +137 -7
- package/src/postgres/installed-classifier.ts +36 -0
- package/src/postgres/providers.ts +44 -7
- package/src/postgres/psql-executor-escaping.test.ts +67 -0
- package/src/postgres/psql-executor.test.ts +167 -0
- package/src/postgres/psql-executor.ts +170 -0
- package/src/postgres/role-adopt.test.ts +98 -0
- package/src/postgres/role-attrs.ts +134 -0
- package/src/postgres/role-diff.ts +89 -0
- package/src/postgres/role-errors.ts +198 -0
- package/src/postgres/role-guard.test.ts +60 -0
- package/src/postgres/role-identity.test.ts +185 -0
- package/src/postgres/role-lifecycle.test.ts +228 -0
- package/src/postgres/role-membership-sql.ts +198 -0
- package/src/postgres/role-password.test.ts +158 -0
- package/src/postgres/role-privilege.test.ts +80 -0
- package/src/postgres/role-provenance.test.ts +200 -0
- package/src/postgres/role-provider.ts +104 -0
- package/src/postgres/role-refusals.test.ts +250 -0
- package/src/postgres/role-scram.test.ts +38 -0
- package/src/postgres/role-scram.ts +38 -0
- package/src/postgres/role-secrets.ts +46 -0
- package/src/postgres/role-sql.ts +211 -0
- package/src/postgres/role-valid-until.test.ts +68 -0
- package/src/postgres/role.ts +218 -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 +161 -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/proxmox/ceph-flag-types.ts +70 -0
- package/src/proxmox/ceph-flag-wire.test.ts +72 -0
- package/src/proxmox/ceph-flag-wire.ts +123 -0
- package/src/proxmox/ceph-flag.ts +77 -130
- package/src/proxmox/ceph-osd-write.ts +10 -13
- 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
|
@@ -18,6 +18,8 @@ import * as Context from 'effect/Context';
|
|
|
18
18
|
import * as Effect from 'effect/Effect';
|
|
19
19
|
import * as Layer from 'effect/Layer';
|
|
20
20
|
import type { SqlError } from 'effect/unstable/sql/SqlError';
|
|
21
|
+
import type { PgExecutor } from './database-sql.ts';
|
|
22
|
+
import { type PsqlRunner, makePsqlExecutor } from './psql-executor.ts';
|
|
21
23
|
|
|
22
24
|
/** What a stack passes to reach one cluster. `host` may be a socket directory (one beginning
|
|
23
25
|
* with `/` expands to `${host}/.s.PGSQL.${port}` — measured in
|
|
@@ -31,11 +33,30 @@ export interface PostgresConnectionConfig {
|
|
|
31
33
|
readonly ssl?: boolean;
|
|
32
34
|
}
|
|
33
35
|
|
|
36
|
+
/** The runner transport (`psql-executor.ts`): SQL goes through `run` instead of a socket, for a
|
|
37
|
+
* host whose Postgres is reachable only by a command (CT100: ssh + `podman exec`). `template`
|
|
38
|
+
* is the `CREATE DATABASE` template — `template0` by default, because CT100's `template1` is
|
|
39
|
+
* ParadeDB's and would copy postgis/pg_ivm/paradedb objects into every new database. */
|
|
40
|
+
export interface PostgresRunnerConfig {
|
|
41
|
+
readonly run: PsqlRunner;
|
|
42
|
+
readonly database: string;
|
|
43
|
+
readonly username: string;
|
|
44
|
+
readonly template?: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** What `withPg`'s callback learns about the transport beyond the client. `database` is the
|
|
48
|
+
* database the statements run IN: the family connection's, or the override `Postgres.Schema`
|
|
49
|
+
* and `Postgres.Grants` pass so they open their declared database and then prove it. */
|
|
50
|
+
export interface PgContext {
|
|
51
|
+
readonly template?: string;
|
|
52
|
+
readonly database: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
34
55
|
/** The lazy connection service. Its value is an `Effect` of the config, per S24 — see the file
|
|
35
56
|
* header for why. */
|
|
36
57
|
export class PostgresConnection extends Context.Service<
|
|
37
58
|
PostgresConnection,
|
|
38
|
-
Effect.Effect<PostgresConnectionConfig>
|
|
59
|
+
Effect.Effect<PostgresConnectionConfig | PostgresRunnerConfig>
|
|
39
60
|
>()('Postgres.Connection') {}
|
|
40
61
|
|
|
41
62
|
/** A stack's one-line way to provide a cluster: `Layer.provide(postgresConnection({ … }))` on
|
|
@@ -44,6 +65,19 @@ export const postgresConnection = (
|
|
|
44
65
|
config: PostgresConnectionConfig,
|
|
45
66
|
): Layer.Layer<PostgresConnection> => Layer.succeed(PostgresConnection, Effect.succeed(config));
|
|
46
67
|
|
|
68
|
+
/** A stack's one-line way to provide a cluster reached through a command runner. */
|
|
69
|
+
export const postgresRunnerConnection = (
|
|
70
|
+
config: PostgresRunnerConfig,
|
|
71
|
+
): Layer.Layer<PostgresConnection> => Layer.succeed(PostgresConnection, Effect.succeed(config));
|
|
72
|
+
|
|
73
|
+
/** Effect-scoped pool factory, like BaoGate: tests override it without process-wide module mocks. */
|
|
74
|
+
export const PostgresPool = Context.Reference<typeof PgClient.layer>('homeflare/postgres/Pool', {
|
|
75
|
+
defaultValue: () => PgClient.layer,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const isRunner = (c: PostgresConnectionConfig | PostgresRunnerConfig): c is PostgresRunnerConfig =>
|
|
79
|
+
'run' in c;
|
|
80
|
+
|
|
47
81
|
/**
|
|
48
82
|
* Run one operation against a freshly built, freshly closed connection pool.
|
|
49
83
|
*
|
|
@@ -51,12 +85,47 @@ export const postgresConnection = (
|
|
|
51
85
|
* operation — never once per statement — so a reconcile that runs a `SELECT`, then a `CREATE`,
|
|
52
86
|
* then a re-read shares one pool and closes it once, while a plan-only `read` still opens and
|
|
53
87
|
* closes its own.
|
|
88
|
+
*
|
|
89
|
+
* `database` overrides which database of the SAME cluster the pool opens — the declared
|
|
90
|
+
* database of `Postgres.Schema` and `Postgres.Grants`. The family connection is pointed at a
|
|
91
|
+
* maintenance database (a brand-new database cannot be connected to on a cold plan), so those
|
|
92
|
+
* resources pass their declared database here: the runner transport swaps the `psql -d` target,
|
|
93
|
+
* the socket path swaps the pool's `database`. The swap is proven, not trusted: schema rows
|
|
94
|
+
* carry `current_database()` (`schema-sql.ts`) and grants calls the same function before writing.
|
|
54
95
|
*/
|
|
55
96
|
export const withPg = <A, E>(
|
|
56
|
-
build: (pg:
|
|
97
|
+
build: (pg: PgExecutor, context: PgContext) => Effect.Effect<A, E>,
|
|
98
|
+
database?: string,
|
|
57
99
|
): Effect.Effect<A, E | SqlError, PostgresConnection> =>
|
|
58
100
|
Effect.gen(function* () {
|
|
59
101
|
const resolveConfig = yield* PostgresConnection;
|
|
60
102
|
const config = yield* resolveConfig;
|
|
61
|
-
|
|
103
|
+
const target: PostgresConnectionConfig | PostgresRunnerConfig =
|
|
104
|
+
database === undefined ? config : { ...config, database };
|
|
105
|
+
if (isRunner(target)) {
|
|
106
|
+
return yield* build(makePsqlExecutor(target.run, target), {
|
|
107
|
+
template: target.template ?? 'template0',
|
|
108
|
+
database: target.database,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
const pool = yield* PostgresPool;
|
|
112
|
+
return yield* Effect.provide(
|
|
113
|
+
Effect.flatMap(PgClient.PgClient, (pg) =>
|
|
114
|
+
build(
|
|
115
|
+
{
|
|
116
|
+
unsafe: (sql, params) => pg.unsafe(sql, params),
|
|
117
|
+
// One reserved connection (`SqlClient.withTransaction`). A pool checkout per
|
|
118
|
+
// statement would autocommit CREATE before GRANT.
|
|
119
|
+
transaction: (statements) =>
|
|
120
|
+
pg.withTransaction(
|
|
121
|
+
Effect.gen(function* () {
|
|
122
|
+
for (const sql of statements) yield* pg.unsafe(sql).pipe(Effect.asVoid);
|
|
123
|
+
}),
|
|
124
|
+
),
|
|
125
|
+
},
|
|
126
|
+
{ database: target.database },
|
|
127
|
+
),
|
|
128
|
+
),
|
|
129
|
+
pool(target),
|
|
130
|
+
);
|
|
62
131
|
});
|
|
@@ -50,12 +50,12 @@ describe('quoting', () => {
|
|
|
50
50
|
});
|
|
51
51
|
|
|
52
52
|
test('quoteStringLiteral doubles an embedded single quote', () => {
|
|
53
|
-
expect(quoteStringLiteral("en_US.UTF-8'; DROP")).toBe("'en_US.UTF-8''; DROP'");
|
|
53
|
+
expect(quoteStringLiteral("en_US.UTF-8'; DROP")).toBe("E'en_US.UTF-8''; DROP'");
|
|
54
54
|
});
|
|
55
55
|
|
|
56
56
|
test('buildCreateDatabaseSql never string-concatenates an unescaped value', () => {
|
|
57
57
|
const sql = buildCreateDatabaseSql({ name: 'db"1', owner: 'ro"le', encoding: "UT'F8" });
|
|
58
|
-
expect(sql).toBe('CREATE DATABASE "db""1" WITH OWNER "ro""le" ENCODING \'UT\'\'F8\'');
|
|
58
|
+
expect(sql).toBe('CREATE DATABASE "db""1" WITH OWNER "ro""le" ENCODING E\'UT\'\'F8\'');
|
|
59
59
|
});
|
|
60
60
|
});
|
|
61
61
|
|
|
@@ -19,23 +19,33 @@
|
|
|
19
19
|
* `createdb_opt_item`'s string branch is `opt_boolean_or_string → NonReservedWord_or_Sconst →
|
|
20
20
|
* NonReservedWord | Sconst`. A locale like `en_US.UTF-8` would hit the same dot-splitting
|
|
21
21
|
* `quoteIdent` avoids if it were identifier-quoted; a plain `Sconst` (`quoteStringLiteral`) has
|
|
22
|
-
* no such rule.
|
|
23
|
-
*
|
|
24
|
-
*
|
|
22
|
+
* no such rule. Use E'…' with doubled backslashes and quotes: PostgreSQL 18 lexical
|
|
23
|
+
* section 4.1.2.2 makes escape strings independent of standard_conforming_strings.
|
|
24
|
+
* Measured 2026-10-01: the former quote-only escaper allowed comment SQL injection when
|
|
25
|
+
* that setting was off; an input backslash escaped the first quote of a doubled pair.
|
|
25
26
|
*/
|
|
26
27
|
import type { SqlError } from 'effect/unstable/sql/SqlError';
|
|
27
28
|
import * as Effect from 'effect/Effect';
|
|
28
29
|
import type { PostgresDatabaseAttributes, PostgresDatabaseProps } from './database-attrs.ts';
|
|
29
30
|
|
|
30
31
|
/** What every function in this file needs from a client — real (`PgClient.PgClient`) or fake
|
|
31
|
-
* (`fake-sql.ts`). Deliberately smaller than `SqlClient`: nothing here
|
|
32
|
-
*
|
|
33
|
-
*
|
|
32
|
+
* (`fake-sql.ts`). Deliberately smaller than `SqlClient`: nothing here needs the tagged template
|
|
33
|
+
* or streaming. `transaction` is the exception `Postgres.Role`'s create and `Postgres.Grants`'
|
|
34
|
+
* repair share: role DDL commits per statement unless the statements share a transaction, and
|
|
35
|
+
* a grants repair's `REVOKE` must not autocommit apart from the `GRANT`s that restore it. */
|
|
34
36
|
export interface PgExecutor {
|
|
35
37
|
readonly unsafe: <A extends object>(
|
|
36
38
|
sql: string,
|
|
37
39
|
params?: ReadonlyArray<unknown>,
|
|
38
40
|
) => Effect.Effect<ReadonlyArray<A>, SqlError>;
|
|
41
|
+
/**
|
|
42
|
+
* Run `statements` in one transaction. `CREATE ROLE`, `ALTER ROLE` and `GRANT`/`REVOKE` of
|
|
43
|
+
* membership are transactional (`utility.c@REL_18_6`: those cases do not call
|
|
44
|
+
* `PreventInTransactionBlock`; `CREATE DATABASE` does). The socket client reserves one
|
|
45
|
+
* connection (`SqlClient.withTransaction`); the runner sends one `psql` script, because each
|
|
46
|
+
* `unsafe` call is its own session and would autocommit.
|
|
47
|
+
*/
|
|
48
|
+
readonly transaction: (statements: readonly string[]) => Effect.Effect<void, SqlError>;
|
|
39
49
|
}
|
|
40
50
|
|
|
41
51
|
/** Single-token identifier quoting: wrap in `"`, double any embedded `"`. No dot-splitting —
|
|
@@ -43,12 +53,14 @@ export interface PgExecutor {
|
|
|
43
53
|
* `NonReservedWord` too, for `OWNER` and `TABLESPACE`. */
|
|
44
54
|
export const quoteIdent = (value: string): string => `"${value.replace(/"/g, '""')}"`;
|
|
45
55
|
|
|
46
|
-
/**
|
|
47
|
-
*
|
|
48
|
-
export const quoteStringLiteral = (value: string): string =>
|
|
56
|
+
/** Escape-string quoting is safe with standard_conforming_strings either on or off.
|
|
57
|
+
* Double backslashes BEFORE quotes, so caller text cannot escape a closing delimiter. */
|
|
58
|
+
export const quoteStringLiteral = (value: string): string =>
|
|
59
|
+
`E'${value.replace(/\\/g, '\\\\').replace(/'/g, "''")}'`;
|
|
49
60
|
|
|
50
|
-
const withOptions = (props: PostgresDatabaseProps): string => {
|
|
61
|
+
const withOptions = (props: PostgresDatabaseProps, template?: string): string => {
|
|
51
62
|
const parts: string[] = [`OWNER ${quoteIdent(props.owner)}`];
|
|
63
|
+
if (template !== undefined) parts.push(`TEMPLATE ${quoteIdent(template)}`);
|
|
52
64
|
if (props.encoding !== undefined) parts.push(`ENCODING ${quoteStringLiteral(props.encoding)}`);
|
|
53
65
|
if (props.localeProvider !== undefined) {
|
|
54
66
|
parts.push(`LOCALE_PROVIDER ${quoteStringLiteral(props.localeProvider)}`);
|
|
@@ -74,8 +86,8 @@ const withOptions = (props: PostgresDatabaseProps): string => {
|
|
|
74
86
|
* `Math.trunc`ed and stringified, and a boolean is one of exactly two literal words this file
|
|
75
87
|
* writes, so no declared value reaches the statement through string interpolation unescaped.
|
|
76
88
|
*/
|
|
77
|
-
export const buildCreateDatabaseSql = (props: PostgresDatabaseProps): string =>
|
|
78
|
-
`CREATE DATABASE ${quoteIdent(props.name)} WITH ${withOptions(props)}`;
|
|
89
|
+
export const buildCreateDatabaseSql = (props: PostgresDatabaseProps, template?: string): string =>
|
|
90
|
+
`CREATE DATABASE ${quoteIdent(props.name)} WITH ${withOptions(props, template)}`;
|
|
79
91
|
|
|
80
92
|
/** `42P04` (`duplicate_database`) is a race: something else created the name between our read
|
|
81
93
|
* and our create. Measured at `internal/sqlError.ts@effect/sql-pg 4.0.0-rc.115`: every SQLSTATE
|
|
@@ -102,6 +114,22 @@ export const roleExists = (pg: PgExecutor, role: string): Effect.Effect<boolean,
|
|
|
102
114
|
(rows) => rows.length > 0,
|
|
103
115
|
);
|
|
104
116
|
|
|
117
|
+
const DATABASE_EXISTS_SQL = 'SELECT 1 AS present FROM pg_database WHERE datname = $1';
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Does one database of the cluster exist? `Postgres.Schema` runs this over the FAMILY
|
|
121
|
+
* connection (no `withPg` database override) before `read` and `delete`, so a declared
|
|
122
|
+
* database that does not exist yet answers "schema absent" instead of the transports' untyped
|
|
123
|
+
* connect failures (`ConnectionError` over psql, `UnknownError` 3D000 over the socket). The
|
|
124
|
+
* probe targets the maintenance database the family connection already points at, which a
|
|
125
|
+
* cold plan can always reach.
|
|
126
|
+
*/
|
|
127
|
+
export const databaseExists = (pg: PgExecutor, name: string): Effect.Effect<boolean, SqlError> =>
|
|
128
|
+
Effect.map(
|
|
129
|
+
pg.unsafe<{ readonly present: number }>(DATABASE_EXISTS_SQL, [name]),
|
|
130
|
+
(rows) => rows.length > 0,
|
|
131
|
+
);
|
|
132
|
+
|
|
105
133
|
/** `datlocprovider` is Postgres's internal 1-byte `"char"` type, which this client decodes as
|
|
106
134
|
* raw bytes rather than text (measured 2026-09-23 against the live socket — `docs/postgres.md`);
|
|
107
135
|
* the `CASE` maps it to the same three words `pg_collation.h@REL_18_6#collprovider_name` returns
|
package/src/postgres/database.ts
CHANGED
|
@@ -80,6 +80,7 @@ const liveDrift = (props: PostgresDatabaseProps, live: PostgresDatabaseAttribute
|
|
|
80
80
|
export const reconcileWithClient = (
|
|
81
81
|
pg: PgExecutor,
|
|
82
82
|
props: PostgresDatabaseProps,
|
|
83
|
+
template?: string,
|
|
83
84
|
): Effect.Effect<
|
|
84
85
|
PostgresDatabaseAttributes,
|
|
85
86
|
PostgresDatabaseOwnerMissing | PostgresDatabaseDrift | PostgresDatabaseCreateVanished | SqlError
|
|
@@ -93,7 +94,7 @@ export const reconcileWithClient = (
|
|
|
93
94
|
new PostgresDatabaseOwnerMissing({ database: props.name, owner: props.owner }),
|
|
94
95
|
);
|
|
95
96
|
}
|
|
96
|
-
yield* pg.unsafe(buildCreateDatabaseSql(props)).pipe(
|
|
97
|
+
yield* pg.unsafe(buildCreateDatabaseSql(props, template)).pipe(
|
|
97
98
|
Effect.asVoid,
|
|
98
99
|
Effect.catchTag('SqlError', (error) =>
|
|
99
100
|
isDuplicateDatabaseRace(error) ? Effect.succeed(undefined) : Effect.fail(error),
|
|
@@ -183,7 +184,7 @@ export const postgresDatabaseHandlers = PostgresDatabase.Provider.of({
|
|
|
183
184
|
new PostgresDatabaseNameRefused({ name: news.name, ...nameRefusal }),
|
|
184
185
|
);
|
|
185
186
|
}
|
|
186
|
-
return yield* withPg((pg) => reconcileWithClient(pg, news));
|
|
187
|
+
return yield* withPg((pg, ctx) => reconcileWithClient(pg, news, ctx.template));
|
|
187
188
|
}),
|
|
188
189
|
|
|
189
190
|
delete: ({ olds }) => Effect.fail(new PostgresDatabaseDropRefused({ database: olds.name })),
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The statement parser half of the `Postgres.Grants` test fake: it understands EXACTLY the
|
|
3
|
+
* ten statement shapes `grants-sql.ts` generates — `quoteIdent`'s quoting, one clause
|
|
4
|
+
* order — and nothing else, so a quoting or clause-order bug in a builder trips the parser
|
|
5
|
+
* instead of hiding behind lenient matching. The server-model half (entries, grant/revoke
|
|
6
|
+
* semantics, the aclexplode-shaped reads) lives in `fake-grants-sql.ts`.
|
|
7
|
+
*
|
|
8
|
+
* ⛔ IT PARSES ITS OWN OUTPUT, NOT SQL IN GENERAL (`fake-sql.ts`'s own rule): every value
|
|
9
|
+
* the builders `quoteIdent` is read back through the same `"…""…"` unquoting, and every
|
|
10
|
+
* statement ends in exactly one of the accepted shapes or the parse refuses.
|
|
11
|
+
* ⛔ A COLUMN GRANT CARRIES ONE COLUMN LIST PER WORD — `GRANT select ("id"), update ("id")`:
|
|
12
|
+
* a single trailing list binds only to the privilege it follows (gram.y@REL_18_6), so
|
|
13
|
+
* `GRANT select, update ("id")` is a table-level SELECT on a real server. The parser
|
|
14
|
+
* refuses that shape instead of filing it as a column-only grant.
|
|
15
|
+
*/
|
|
16
|
+
export interface AclObject {
|
|
17
|
+
readonly schema: string;
|
|
18
|
+
readonly table?: string;
|
|
19
|
+
readonly column?: string;
|
|
20
|
+
readonly defaultFor?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** One parsed write statement, already reduced to what the model applies. */
|
|
24
|
+
export interface ParsedWrite {
|
|
25
|
+
readonly kind: 'grant' | 'revoke';
|
|
26
|
+
/** `REVOKE ALL ON ALL TABLES IN SCHEMA … FROM PUBLIC` — applied per known relation. */
|
|
27
|
+
readonly allTables?: boolean;
|
|
28
|
+
readonly object: AclObject;
|
|
29
|
+
/** `'PUBLIC'` or a role name. */
|
|
30
|
+
readonly grantee: string;
|
|
31
|
+
/** Declared privilege words, lowercase, no `*` marks (the option clause carries the flag). */
|
|
32
|
+
readonly words: ReadonlyArray<string>;
|
|
33
|
+
readonly option: boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const unquote = (raw: string): string => raw.replace(/""/g, '"');
|
|
37
|
+
|
|
38
|
+
const IDENT = String.raw`"((?:[^"]|"")*)"`;
|
|
39
|
+
const WORDS = String.raw`([a-z]+(?:, [a-z]+)*)`;
|
|
40
|
+
/** One column-grant atom, `word ("col")` — the shape every builder column statement is made of. */
|
|
41
|
+
const SYNOPSIS = String.raw`[a-z]+ \("(?:[^"]|"")*"\)`;
|
|
42
|
+
const GRANTEE = String.raw`(?:"((?:[^"]|"")*)"|PUBLIC)`;
|
|
43
|
+
const OPTION = String.raw`(?:( WITH GRANT OPTION))?`;
|
|
44
|
+
|
|
45
|
+
interface Pattern {
|
|
46
|
+
readonly re: RegExp;
|
|
47
|
+
/** `undefined` when the regex matched but the shape is one no builder emits — the loop
|
|
48
|
+
* falls through and the parse refuses (a builder regression, not a tolerated statement). */
|
|
49
|
+
readonly parse: (m: RegExpExecArray) => Omit<ParsedWrite, 'kind'> | undefined;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const role = (raw: string | undefined): string => (raw === undefined ? 'PUBLIC' : unquote(raw));
|
|
53
|
+
|
|
54
|
+
/** Ordered: a column grant/revoke must be tried before the table form its text starts like,
|
|
55
|
+
* and the two default-privileges forms before the plain ones they begin as. */
|
|
56
|
+
const PATTERNS: ReadonlyArray<Pattern & { readonly kind: 'grant' | 'revoke' }> = [
|
|
57
|
+
{
|
|
58
|
+
kind: 'grant',
|
|
59
|
+
re: new RegExp(
|
|
60
|
+
`^ALTER DEFAULT PRIVILEGES FOR ROLE ${IDENT} IN SCHEMA ${IDENT} GRANT ${WORDS} ON TABLES TO ${GRANTEE}${OPTION}$`,
|
|
61
|
+
),
|
|
62
|
+
parse: (m) => ({
|
|
63
|
+
object: { schema: unquote(m[2] as string), defaultFor: unquote(m[1] as string) },
|
|
64
|
+
grantee: role(m[4] as string | undefined),
|
|
65
|
+
words: (m[3] as string).split(', '),
|
|
66
|
+
option: m[5] !== undefined,
|
|
67
|
+
}),
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
kind: 'revoke',
|
|
71
|
+
re: new RegExp(
|
|
72
|
+
`^ALTER DEFAULT PRIVILEGES FOR ROLE ${IDENT} IN SCHEMA ${IDENT} REVOKE ALL ON TABLES FROM ${GRANTEE}$`,
|
|
73
|
+
),
|
|
74
|
+
parse: (m) => ({
|
|
75
|
+
object: { schema: unquote(m[2] as string), defaultFor: unquote(m[1] as string) },
|
|
76
|
+
grantee: role(m[3] as string | undefined),
|
|
77
|
+
words: [],
|
|
78
|
+
option: false,
|
|
79
|
+
}),
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
kind: 'grant',
|
|
83
|
+
// ⛔ Every word carries its OWN column list — `GRANT select ("id"), update ("id") …`.
|
|
84
|
+
// A single trailing list binds only to the privilege it follows (gram.y@REL_18_6), so
|
|
85
|
+
// `GRANT select, update ("id")` is a table-level SELECT on a real server; the parser
|
|
86
|
+
// refuses that shape instead of filing it as a column-only grant (a builder that
|
|
87
|
+
// emits it would over-grant at the table level while the suite stays green).
|
|
88
|
+
re: new RegExp(
|
|
89
|
+
`^GRANT (${SYNOPSIS}(?:, ${SYNOPSIS})*) ON ${IDENT}\\.${IDENT} TO ${GRANTEE}${OPTION}$`,
|
|
90
|
+
),
|
|
91
|
+
parse: (m) => {
|
|
92
|
+
const pairs = [...(m[1] as string).matchAll(/([a-z]+) \("((?:[^"]|"")*)"\)/g)];
|
|
93
|
+
const first = pairs[0];
|
|
94
|
+
if (first === undefined) return undefined;
|
|
95
|
+
const column = unquote(first[2] as string);
|
|
96
|
+
// One statement grants ONE column: every synopsis pair must name the same one (the
|
|
97
|
+
// builders emit one column per statement) — mixed columns are a foreign shape.
|
|
98
|
+
if (pairs.some(([, , raw]) => unquote(raw as string) !== column)) return undefined;
|
|
99
|
+
return {
|
|
100
|
+
object: {
|
|
101
|
+
schema: unquote(m[2] as string),
|
|
102
|
+
table: unquote(m[3] as string),
|
|
103
|
+
column,
|
|
104
|
+
},
|
|
105
|
+
grantee: role(m[4] as string | undefined),
|
|
106
|
+
words: pairs.map(([, word]) => word as string),
|
|
107
|
+
option: m[5] !== undefined,
|
|
108
|
+
};
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
kind: 'revoke',
|
|
113
|
+
re: new RegExp(`^REVOKE ALL \\(${IDENT}\\) ON ${IDENT}\\.${IDENT} FROM ${GRANTEE}$`),
|
|
114
|
+
parse: (m) => ({
|
|
115
|
+
object: {
|
|
116
|
+
schema: unquote(m[2] as string),
|
|
117
|
+
table: unquote(m[3] as string),
|
|
118
|
+
column: unquote(m[1] as string),
|
|
119
|
+
},
|
|
120
|
+
grantee: role(m[4] as string | undefined),
|
|
121
|
+
words: [],
|
|
122
|
+
option: false,
|
|
123
|
+
}),
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
kind: 'grant',
|
|
127
|
+
re: new RegExp(`^GRANT ${WORDS} ON SCHEMA ${IDENT} TO ${GRANTEE}${OPTION}$`),
|
|
128
|
+
parse: (m) => ({
|
|
129
|
+
object: { schema: unquote(m[2] as string) },
|
|
130
|
+
grantee: role(m[3] as string | undefined),
|
|
131
|
+
words: (m[1] as string).split(', '),
|
|
132
|
+
option: m[4] !== undefined,
|
|
133
|
+
}),
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
kind: 'grant',
|
|
137
|
+
re: new RegExp(`^GRANT ${WORDS} ON ${IDENT}\\.${IDENT} TO ${GRANTEE}${OPTION}$`),
|
|
138
|
+
parse: (m) => ({
|
|
139
|
+
object: { schema: unquote(m[2] as string), table: unquote(m[3] as string) },
|
|
140
|
+
grantee: role(m[4] as string | undefined),
|
|
141
|
+
words: (m[1] as string).split(', '),
|
|
142
|
+
option: m[5] !== undefined,
|
|
143
|
+
}),
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
kind: 'revoke',
|
|
147
|
+
re: new RegExp(`^REVOKE ALL ON ${IDENT}\\.${IDENT} FROM ${GRANTEE}$`),
|
|
148
|
+
parse: (m) => ({
|
|
149
|
+
object: { schema: unquote(m[1] as string), table: unquote(m[2] as string) },
|
|
150
|
+
grantee: role(m[3] as string | undefined),
|
|
151
|
+
words: [],
|
|
152
|
+
option: false,
|
|
153
|
+
}),
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
kind: 'revoke',
|
|
157
|
+
re: new RegExp(`^REVOKE ALL ON SCHEMA ${IDENT} FROM ${GRANTEE}$`),
|
|
158
|
+
parse: (m) => ({
|
|
159
|
+
object: { schema: unquote(m[1] as string) },
|
|
160
|
+
grantee: role(m[2] as string | undefined),
|
|
161
|
+
words: [],
|
|
162
|
+
option: false,
|
|
163
|
+
}),
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
kind: 'revoke',
|
|
167
|
+
re: new RegExp(`^REVOKE ALL ON ALL TABLES IN SCHEMA ${IDENT} FROM ${GRANTEE}$`),
|
|
168
|
+
parse: (m) => ({
|
|
169
|
+
allTables: true,
|
|
170
|
+
object: { schema: unquote(m[1] as string) },
|
|
171
|
+
grantee: role(m[2] as string | undefined),
|
|
172
|
+
words: [],
|
|
173
|
+
option: false,
|
|
174
|
+
}),
|
|
175
|
+
},
|
|
176
|
+
];
|
|
177
|
+
|
|
178
|
+
/** `undefined` when the text is no statement this family generates — the model refuses it
|
|
179
|
+
* rather than guessing (a parse miss on a GRANT-shaped text means a builder regressed). */
|
|
180
|
+
export const parseGrantStatement = (text: string): ParsedWrite | undefined => {
|
|
181
|
+
for (const pattern of PATTERNS) {
|
|
182
|
+
const m = pattern.re.exec(text);
|
|
183
|
+
if (m === null) continue;
|
|
184
|
+
const parsed = pattern.parse(m);
|
|
185
|
+
if (parsed === undefined) continue;
|
|
186
|
+
return { kind: pattern.kind, ...parsed };
|
|
187
|
+
}
|
|
188
|
+
return undefined;
|
|
189
|
+
};
|