@bajustone/fortress 1.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1011 -0
- package/LICENSE +21 -0
- package/README.md +760 -0
- package/SECURITY.md +197 -0
- package/bin/fortress.ts +667 -0
- package/dist/auth-service-BcyQ2PuZ.d.cts +307 -0
- package/dist/auth-service-BkzZkWfH.d.ts +307 -0
- package/dist/config-B2366s_G.d.ts +665 -0
- package/dist/config-GtlVt6ZD.d.cts +665 -0
- package/dist/convert-routes-BLCQT57f.d.ts +72 -0
- package/dist/convert-routes-BdMvP2_X.d.cts +72 -0
- package/dist/crypto.cjs +61 -0
- package/dist/crypto.d.cts +36 -0
- package/dist/crypto.d.ts +36 -0
- package/dist/crypto.js +35 -0
- package/dist/drift-BT1wtMDJ.d.cts +22 -0
- package/dist/drift-k9LiYpRP.d.ts +22 -0
- package/dist/drizzle/pg.cjs +481 -0
- package/dist/drizzle/pg.d.cts +15 -0
- package/dist/drizzle/pg.d.ts +15 -0
- package/dist/drizzle/pg.js +454 -0
- package/dist/drizzle.cjs +1442 -0
- package/dist/drizzle.d.cts +85 -0
- package/dist/drizzle.d.ts +85 -0
- package/dist/drizzle.js +1411 -0
- package/dist/express.cjs +1357 -0
- package/dist/express.d.cts +333 -0
- package/dist/express.d.ts +333 -0
- package/dist/express.js +1314 -0
- package/dist/fetcher.cjs +77 -0
- package/dist/fetcher.d.cts +7 -0
- package/dist/fetcher.d.ts +7 -0
- package/dist/fetcher.js +41 -0
- package/dist/fortress-BmSvFfqK.d.cts +1089 -0
- package/dist/fortress-uA-_cheR.d.ts +1089 -0
- package/dist/hono.cjs +1530 -0
- package/dist/hono.d.cts +514 -0
- package/dist/hono.d.ts +514 -0
- package/dist/hono.js +1483 -0
- package/dist/index-CxEkfCA0.d.cts +77 -0
- package/dist/index-CxEkfCA0.d.ts +77 -0
- package/dist/index-D054pcb-.d.cts +146 -0
- package/dist/index-jAMbbUAY.d.ts +146 -0
- package/dist/index.cjs +9046 -0
- package/dist/index.d.cts +717 -0
- package/dist/index.d.ts +717 -0
- package/dist/index.js +8935 -0
- package/dist/jwt.cjs +255 -0
- package/dist/jwt.d.cts +90 -0
- package/dist/jwt.d.ts +90 -0
- package/dist/jwt.js +227 -0
- package/dist/otel.cjs +108 -0
- package/dist/otel.d.cts +62 -0
- package/dist/otel.d.ts +62 -0
- package/dist/otel.js +73 -0
- package/dist/plugins/account-lockout.cjs +322 -0
- package/dist/plugins/account-lockout.d.cts +42 -0
- package/dist/plugins/account-lockout.d.ts +42 -0
- package/dist/plugins/account-lockout.js +295 -0
- package/dist/plugins/admin.cjs +2378 -0
- package/dist/plugins/admin.d.cts +72 -0
- package/dist/plugins/admin.d.ts +72 -0
- package/dist/plugins/admin.js +2351 -0
- package/dist/plugins/api-key.cjs +792 -0
- package/dist/plugins/api-key.d.cts +121 -0
- package/dist/plugins/api-key.d.ts +121 -0
- package/dist/plugins/api-key.js +765 -0
- package/dist/plugins/audit-log.cjs +493 -0
- package/dist/plugins/audit-log.d.cts +86 -0
- package/dist/plugins/audit-log.d.ts +86 -0
- package/dist/plugins/audit-log.js +468 -0
- package/dist/plugins/data-isolation.cjs +211 -0
- package/dist/plugins/data-isolation.d.cts +49 -0
- package/dist/plugins/data-isolation.d.ts +49 -0
- package/dist/plugins/data-isolation.js +186 -0
- package/dist/plugins/email-verification.cjs +273 -0
- package/dist/plugins/email-verification.d.cts +44 -0
- package/dist/plugins/email-verification.d.ts +44 -0
- package/dist/plugins/email-verification.js +246 -0
- package/dist/plugins/magic-link.cjs +231 -0
- package/dist/plugins/magic-link.d.cts +39 -0
- package/dist/plugins/magic-link.d.ts +39 -0
- package/dist/plugins/magic-link.js +204 -0
- package/dist/plugins/oauth.cjs +1696 -0
- package/dist/plugins/oauth.d.cts +406 -0
- package/dist/plugins/oauth.d.ts +406 -0
- package/dist/plugins/oauth.js +1669 -0
- package/dist/plugins/openapi.cjs +1185 -0
- package/dist/plugins/openapi.d.cts +6 -0
- package/dist/plugins/openapi.d.ts +6 -0
- package/dist/plugins/openapi.js +1158 -0
- package/dist/plugins/rate-limit/express.cjs +55 -0
- package/dist/plugins/rate-limit/express.d.cts +64 -0
- package/dist/plugins/rate-limit/express.d.ts +64 -0
- package/dist/plugins/rate-limit/express.js +30 -0
- package/dist/plugins/rate-limit/hono.cjs +51 -0
- package/dist/plugins/rate-limit/hono.d.cts +59 -0
- package/dist/plugins/rate-limit/hono.d.ts +59 -0
- package/dist/plugins/rate-limit/hono.js +26 -0
- package/dist/plugins/rate-limit/sveltekit.cjs +49 -0
- package/dist/plugins/rate-limit/sveltekit.d.cts +59 -0
- package/dist/plugins/rate-limit/sveltekit.d.ts +59 -0
- package/dist/plugins/rate-limit/sveltekit.js +24 -0
- package/dist/plugins/rate-limit.cjs +354 -0
- package/dist/plugins/rate-limit.d.cts +140 -0
- package/dist/plugins/rate-limit.d.ts +140 -0
- package/dist/plugins/rate-limit.js +325 -0
- package/dist/plugins/social-login.cjs +905 -0
- package/dist/plugins/social-login.d.cts +114 -0
- package/dist/plugins/social-login.d.ts +114 -0
- package/dist/plugins/social-login.js +880 -0
- package/dist/plugins/tenancy.cjs +780 -0
- package/dist/plugins/tenancy.d.cts +108 -0
- package/dist/plugins/tenancy.d.ts +108 -0
- package/dist/plugins/tenancy.js +753 -0
- package/dist/plugins/two-factor.cjs +555 -0
- package/dist/plugins/two-factor.d.cts +67 -0
- package/dist/plugins/two-factor.d.ts +67 -0
- package/dist/plugins/two-factor.js +526 -0
- package/dist/plugins/webauthn.cjs +786 -0
- package/dist/plugins/webauthn.d.cts +72 -0
- package/dist/plugins/webauthn.d.ts +72 -0
- package/dist/plugins/webauthn.js +766 -0
- package/dist/plugins/webhook.cjs +819 -0
- package/dist/plugins/webhook.d.cts +254 -0
- package/dist/plugins/webhook.d.ts +254 -0
- package/dist/plugins/webhook.js +789 -0
- package/dist/protect-D1v_0upK.d.cts +123 -0
- package/dist/protect-DsxV_-dJ.d.ts +123 -0
- package/dist/sveltekit.cjs +1258 -0
- package/dist/sveltekit.d.cts +420 -0
- package/dist/sveltekit.d.ts +420 -0
- package/dist/sveltekit.js +1207 -0
- package/dist/testing.cjs +4294 -0
- package/dist/testing.d.cts +197 -0
- package/dist/testing.d.ts +197 -0
- package/dist/testing.js +4264 -0
- package/dist/types-et0R8tsC.d.cts +217 -0
- package/dist/types-et0R8tsC.d.ts +217 -0
- package/docs/adapter-typed-helpers.md +192 -0
- package/docs/admin-recipes.md +227 -0
- package/docs/architecture.md +434 -0
- package/docs/ci/github-actions.yml +59 -0
- package/docs/ci.md +109 -0
- package/docs/compatibility.md +115 -0
- package/docs/deployment.md +305 -0
- package/docs/hardening.md +118 -0
- package/docs/host-owned-routes.md +154 -0
- package/docs/migrations/0001-schema-version.md +54 -0
- package/docs/migrations/0002-initial-schema.md +84 -0
- package/docs/migrations/upgrade-guide.md +160 -0
- package/docs/observability.md +394 -0
- package/docs/plugins/account-lockout.md +131 -0
- package/docs/plugins/admin.md +402 -0
- package/docs/plugins/api-key.md +327 -0
- package/docs/plugins/audit-log.md +261 -0
- package/docs/plugins/data-isolation.md +186 -0
- package/docs/plugins/email-verification.md +121 -0
- package/docs/plugins/magic-link.md +123 -0
- package/docs/plugins/oauth.md +544 -0
- package/docs/plugins/openapi.md +250 -0
- package/docs/plugins/rate-limit.md +223 -0
- package/docs/plugins/social-login.md +337 -0
- package/docs/plugins/tenancy.md +122 -0
- package/docs/plugins/two-factor.md +191 -0
- package/docs/plugins/webauthn.md +188 -0
- package/docs/plugins/webhook.md +242 -0
- package/docs/policy-as-code.md +156 -0
- package/docs/route-manifest.md +46 -0
- package/docs/security.md +261 -0
- package/docs/threat-model.md +161 -0
- package/examples/README.md +119 -0
- package/examples/express-app/index.ts +747 -0
- package/examples/hono-app/docker-compose.yml +14 -0
- package/examples/hono-app/index.ts +1009 -0
- package/examples/policy/fortress.policy.json +47 -0
- package/examples/sveltekit-app/README.md +125 -0
- package/examples/sveltekit-app/src/app.d.ts +16 -0
- package/examples/sveltekit-app/src/hooks.server.ts +23 -0
- package/examples/sveltekit-app/src/lib/server/fortress.ts +81 -0
- package/examples/sveltekit-app/src/routes/api/echo/[id]/+server.ts +32 -0
- package/examples/sveltekit-app/src/routes/api/fortress/[...path]/+server.ts +15 -0
- package/examples/sveltekit-app/src/routes/dashboard/+page.server.ts +20 -0
- package/examples/sveltekit-app/src/routes/login/+page.server.ts +48 -0
- package/examples/sveltekit-app/src/routes/oauth/consent/+page.server.ts +69 -0
- package/examples/sveltekit-app/src/routes/oauth/consent/+page.svelte +83 -0
- package/migrations/pg/0001_schema_version.down.sql +2 -0
- package/migrations/pg/0001_schema_version.sql +8 -0
- package/migrations/pg/0002_initial_schema.down.sql +36 -0
- package/migrations/pg/0002_initial_schema.sql +376 -0
- package/migrations/pg/0003_auth_continuation.down.sql +6 -0
- package/migrations/pg/0003_auth_continuation.sql +30 -0
- package/migrations/pg/0004_tenant_default_unique.down.sql +1 -0
- package/migrations/pg/0004_tenant_default_unique.sql +14 -0
- package/migrations/pg/0005_hot_indexes_timestamptz.down.sql +71 -0
- package/migrations/pg/0005_hot_indexes_timestamptz.sql +71 -0
- package/migrations/pg/0006_canonical_email.down.sql +3 -0
- package/migrations/pg/0006_canonical_email.sql +8 -0
- package/migrations/pg/0007_audit_chain_anchor.down.sql +1 -0
- package/migrations/pg/0007_audit_chain_anchor.sql +8 -0
- package/migrations/pg/0008_two_factor_hardening.down.sql +8 -0
- package/migrations/pg/0008_two_factor_hardening.sql +8 -0
- package/migrations/pg/0009_encrypt_totp_secrets.down.sql +2 -0
- package/migrations/pg/0009_encrypt_totp_secrets.sql +5 -0
- package/migrations/pg/0010_bigint_append_only_ids.down.sql +2 -0
- package/migrations/pg/0010_bigint_append_only_ids.sql +23 -0
- package/migrations/sqlite/0001_schema_version.down.sql +2 -0
- package/migrations/sqlite/0001_schema_version.sql +8 -0
- package/migrations/sqlite/0002_initial_schema.down.sql +36 -0
- package/migrations/sqlite/0002_initial_schema.sql +376 -0
- package/migrations/sqlite/0003_auth_continuation.down.sql +27 -0
- package/migrations/sqlite/0003_auth_continuation.sql +45 -0
- package/migrations/sqlite/0004_tenant_default_unique.down.sql +1 -0
- package/migrations/sqlite/0004_tenant_default_unique.sql +13 -0
- package/migrations/sqlite/0005_hot_indexes_timestamptz.down.sql +10 -0
- package/migrations/sqlite/0005_hot_indexes_timestamptz.sql +10 -0
- package/migrations/sqlite/0006_canonical_email.down.sql +3 -0
- package/migrations/sqlite/0006_canonical_email.sql +8 -0
- package/migrations/sqlite/0007_audit_chain_anchor.down.sql +1 -0
- package/migrations/sqlite/0007_audit_chain_anchor.sql +8 -0
- package/migrations/sqlite/0008_two_factor_hardening.down.sql +14 -0
- package/migrations/sqlite/0008_two_factor_hardening.sql +7 -0
- package/migrations/sqlite/0009_encrypt_totp_secrets.down.sql +2 -0
- package/migrations/sqlite/0009_encrypt_totp_secrets.sql +5 -0
- package/migrations/sqlite/0010_bigint_append_only_ids.down.sql +1 -0
- package/migrations/sqlite/0010_bigint_append_only_ids.sql +2 -0
- package/package.json +398 -0
- package/src/adapters/database/index.ts +63 -0
- package/src/adapters/database/types.ts +22 -0
- package/src/changelog-script.test.ts +21 -0
- package/src/cli.test.ts +79 -0
- package/src/core/auth/auth-admin.test.ts +247 -0
- package/src/core/auth/auth-endpoints.ts +558 -0
- package/src/core/auth/auth-observer.test.ts +191 -0
- package/src/core/auth/auth-service.ts +1464 -0
- package/src/core/auth/email.test.ts +17 -0
- package/src/core/auth/email.ts +11 -0
- package/src/core/auth/hooks.test.ts +251 -0
- package/src/core/auth/impersonation.test.ts +179 -0
- package/src/core/auth/jwt.test.ts +184 -0
- package/src/core/auth/jwt.ts +239 -0
- package/src/core/auth/login-timing.test.ts +77 -0
- package/src/core/auth/password-policy.test.ts +253 -0
- package/src/core/auth/password-policy.ts +220 -0
- package/src/core/auth/password.test.ts +42 -0
- package/src/core/auth/password.ts +62 -0
- package/src/core/auth/post-auth-gate.test.ts +258 -0
- package/src/core/auth/post-auth-gate.ts +228 -0
- package/src/core/auth/refresh-token.test.ts +86 -0
- package/src/core/auth/refresh-token.ts +105 -0
- package/src/core/auth/timing-safe.ts +23 -0
- package/src/core/config.ts +212 -0
- package/src/core/endpoint.ts +149 -0
- package/src/core/errors.ts +199 -0
- package/src/core/fetcher-interop.test.ts +106 -0
- package/src/core/fortress.test.ts +354 -0
- package/src/core/fortress.ts +550 -0
- package/src/core/http/call.test.ts +148 -0
- package/src/core/http/call.ts +149 -0
- package/src/core/http/cookie-serialize.test.ts +198 -0
- package/src/core/http/cookie-serialize.ts +107 -0
- package/src/core/http/csrf.test.ts +140 -0
- package/src/core/http/csrf.ts +173 -0
- package/src/core/http/dispatch.ts +652 -0
- package/src/core/http/error-response.test.ts +69 -0
- package/src/core/http/error-response.ts +93 -0
- package/src/core/http/fortress-rbac.test.ts +43 -0
- package/src/core/http/fortress-rbac.ts +127 -0
- package/src/core/http/handle-request.test.ts +441 -0
- package/src/core/http/handle-request.ts +354 -0
- package/src/core/http/match.test.ts +122 -0
- package/src/core/http/match.ts +126 -0
- package/src/core/http/outbound.test.ts +34 -0
- package/src/core/http/outbound.ts +105 -0
- package/src/core/http/plugin-middleware.ts +67 -0
- package/src/core/http/principal.test.ts +345 -0
- package/src/core/http/principal.ts +86 -0
- package/src/core/http/protect.test.ts +220 -0
- package/src/core/http/protect.ts +394 -0
- package/src/core/http/token-extraction.test.ts +59 -0
- package/src/core/http/token-extraction.ts +53 -0
- package/src/core/iam/explain.test.ts +177 -0
- package/src/core/iam/explain.ts +302 -0
- package/src/core/iam/iam-endpoints.ts +779 -0
- package/src/core/iam/iam-service.test.ts +829 -0
- package/src/core/iam/iam-service.ts +1137 -0
- package/src/core/iam/permission-cache.test.ts +115 -0
- package/src/core/iam/permission-cache.ts +71 -0
- package/src/core/iam/permission-check-observer.test.ts +90 -0
- package/src/core/iam/permission-evaluator.test.ts +291 -0
- package/src/core/iam/permission-evaluator.ts +198 -0
- package/src/core/iam/permission-sync.test.ts +166 -0
- package/src/core/iam/permission-sync.ts +192 -0
- package/src/core/iam/resource-sync.test.ts +70 -0
- package/src/core/iam/resource-sync.ts +182 -0
- package/src/core/iam/service-account-http.test.ts +529 -0
- package/src/core/iam/service-account.test.ts +282 -0
- package/src/core/internal-adapter.test.ts +389 -0
- package/src/core/internal-adapter.ts +435 -0
- package/src/core/json-schema.ts +50 -0
- package/src/core/manifest/__snapshots__/route-manifest.test.ts.snap +192 -0
- package/src/core/manifest/drift.ts +103 -0
- package/src/core/manifest/route-manifest.test.ts +142 -0
- package/src/core/manifest/route-manifest.ts +154 -0
- package/src/core/migrate.test.ts +72 -0
- package/src/core/migrations/engine.test.ts +308 -0
- package/src/core/migrations/engine.ts +548 -0
- package/src/core/migrations/migrations.ts +1771 -0
- package/src/core/migrations/pg-migration.integration-test.ts +353 -0
- package/src/core/migrations/upgrade-fixture.test.ts +378 -0
- package/src/core/observability/db-instrumentation.ts +205 -0
- package/src/core/observability/listener-list.test.ts +124 -0
- package/src/core/observability/listener-list.ts +73 -0
- package/src/core/observability/logger.test.ts +43 -0
- package/src/core/observability/logger.ts +49 -0
- package/src/core/observability/spans.test.ts +193 -0
- package/src/core/observability/types.ts +80 -0
- package/src/core/openapi-drift.test.ts +41 -0
- package/src/core/openapi.ts +47 -0
- package/src/core/plugin-methods-map.ts +75 -0
- package/src/core/plugin-runner.test.ts +233 -0
- package/src/core/plugin-runner.ts +276 -0
- package/src/core/plugin.ts +210 -0
- package/src/core/policy/apply.ts +272 -0
- package/src/core/policy/diff.ts +288 -0
- package/src/core/policy/loader.test.ts +63 -0
- package/src/core/policy/loader.ts +214 -0
- package/src/core/policy/policy.test.ts +232 -0
- package/src/core/policy/types.ts +105 -0
- package/src/core/schema-builder.test.ts +660 -0
- package/src/core/schema-builder.ts +881 -0
- package/src/core/standard-schema.ts +56 -0
- package/src/core/types.ts +258 -0
- package/src/core/validation.test.ts +195 -0
- package/src/core/validation.ts +192 -0
- package/src/drizzle/adapter.test.ts +425 -0
- package/src/drizzle/adapter.ts +474 -0
- package/src/drizzle/index.ts +31 -0
- package/src/drizzle/pg/adapter.integration-test.ts +456 -0
- package/src/drizzle/pg/index.ts +13 -0
- package/src/drizzle/pg/pg.integration-test.ts +1539 -0
- package/src/drizzle/pg/schema.ts +539 -0
- package/src/drizzle/pg-error-map.test.ts +218 -0
- package/src/drizzle/pg-error-map.ts +151 -0
- package/src/drizzle/schema.ts +544 -0
- package/src/drizzle/sqlite-serialization.test.ts +106 -0
- package/src/express/express-api-key-user-routes.test.ts +241 -0
- package/src/express/express.test.ts +442 -0
- package/src/express/handle.ts +191 -0
- package/src/express/index.ts +62 -0
- package/src/express/middleware.ts +551 -0
- package/src/express/protect.ts +154 -0
- package/src/express/validated.test.ts +86 -0
- package/src/express/validated.ts +99 -0
- package/src/fetcher/index.ts +81 -0
- package/src/hono/convert-routes.test.ts +220 -0
- package/src/hono/convert-routes.ts +196 -0
- package/src/hono/converters.test.ts +50 -0
- package/src/hono/converters.ts +43 -0
- package/src/hono/handle.ts +79 -0
- package/src/hono/helpers.ts +2 -0
- package/src/hono/hono-api-key-user-routes.test.ts +225 -0
- package/src/hono/hono-handlers.test.ts +861 -0
- package/src/hono/hono.test.ts +454 -0
- package/src/hono/index.ts +101 -0
- package/src/hono/middleware/auth.ts +236 -0
- package/src/hono/middleware/auth.types.test.ts +94 -0
- package/src/hono/middleware/csrf.test.ts +127 -0
- package/src/hono/middleware/csrf.ts +68 -0
- package/src/hono/middleware/error-handler.ts +12 -0
- package/src/hono/middleware/plugin-middleware.ts +35 -0
- package/src/hono/middleware/rbac.ts +131 -0
- package/src/hono/middleware/security-headers.test.ts +88 -0
- package/src/hono/middleware/security-headers.ts +68 -0
- package/src/hono/openapi.ts +237 -0
- package/src/hono/protect.ts +87 -0
- package/src/hono/validated.test.ts +123 -0
- package/src/hono/validated.ts +62 -0
- package/src/index.ts +309 -0
- package/src/integration.test.ts +718 -0
- package/src/internal/changelog.ts +56 -0
- package/src/otel/index.ts +158 -0
- package/src/otel/otel-types.test.ts +35 -0
- package/src/otel/otel.test.ts +235 -0
- package/src/plugins/account-lockout/account-lockout.test.ts +367 -0
- package/src/plugins/account-lockout/index.ts +267 -0
- package/src/plugins/admin/admin-api-key.test.ts +438 -0
- package/src/plugins/admin/index.ts +1612 -0
- package/src/plugins/api-key/api-key.test.ts +684 -0
- package/src/plugins/api-key/core.ts +336 -0
- package/src/plugins/api-key/index.ts +315 -0
- package/src/plugins/audit-log/audit-log.test.ts +749 -0
- package/src/plugins/audit-log/index.ts +680 -0
- package/src/plugins/data-isolation/data-isolation.test.ts +197 -0
- package/src/plugins/data-isolation/index.ts +157 -0
- package/src/plugins/email-verification/email-verification.test.ts +199 -0
- package/src/plugins/email-verification/index.ts +190 -0
- package/src/plugins/magic-link/index.ts +129 -0
- package/src/plugins/magic-link/magic-link.test.ts +156 -0
- package/src/plugins/oauth/id-token.ts +86 -0
- package/src/plugins/oauth/index.ts +2145 -0
- package/src/plugins/oauth/jwks.test.ts +32 -0
- package/src/plugins/oauth/jwks.ts +182 -0
- package/src/plugins/oauth/oauth.test.ts +2220 -0
- package/src/plugins/oauth/pkce.ts +58 -0
- package/src/plugins/openapi/index.ts +298 -0
- package/src/plugins/openapi/openapi.test.ts +425 -0
- package/src/plugins/openapi/spec-builder.ts +287 -0
- package/src/plugins/rate-limit/express.test.ts +89 -0
- package/src/plugins/rate-limit/express.ts +86 -0
- package/src/plugins/rate-limit/hono.test.ts +60 -0
- package/src/plugins/rate-limit/hono.ts +74 -0
- package/src/plugins/rate-limit/index.ts +383 -0
- package/src/plugins/rate-limit/memory-store.ts +61 -0
- package/src/plugins/rate-limit/rate-limit.test.ts +756 -0
- package/src/plugins/rate-limit/sveltekit.test.ts +58 -0
- package/src/plugins/rate-limit/sveltekit.ts +66 -0
- package/src/plugins/social-login/index.ts +715 -0
- package/src/plugins/social-login/providers/apple.ts +34 -0
- package/src/plugins/social-login/providers/discord.ts +26 -0
- package/src/plugins/social-login/providers/github.ts +54 -0
- package/src/plugins/social-login/providers/google.ts +23 -0
- package/src/plugins/social-login/providers/index.ts +22 -0
- package/src/plugins/social-login/providers/microsoft.ts +35 -0
- package/src/plugins/social-login/providers/oidc.ts +37 -0
- package/src/plugins/social-login/providers/providers.test.ts +211 -0
- package/src/plugins/social-login/social-login.test.ts +675 -0
- package/src/plugins/social-login/types.ts +80 -0
- package/src/plugins/tenancy/index.ts +544 -0
- package/src/plugins/tenancy/tenancy.test.ts +323 -0
- package/src/plugins/two-factor/index.ts +569 -0
- package/src/plugins/two-factor/two-factor.test.ts +235 -0
- package/src/plugins/webauthn/index.ts +554 -0
- package/src/plugins/webauthn/webauthn.test.ts +472 -0
- package/src/plugins/webhook/builtin-events.ts +29 -0
- package/src/plugins/webhook/delivery.test.ts +51 -0
- package/src/plugins/webhook/delivery.ts +154 -0
- package/src/plugins/webhook/hooks.ts +89 -0
- package/src/plugins/webhook/index.ts +445 -0
- package/src/plugins/webhook/queue/database.ts +67 -0
- package/src/plugins/webhook/queue/in-memory.test.ts +48 -0
- package/src/plugins/webhook/queue/in-memory.ts +71 -0
- package/src/plugins/webhook/queue/types.ts +51 -0
- package/src/plugins/webhook/registry.test.ts +48 -0
- package/src/plugins/webhook/registry.ts +64 -0
- package/src/plugins/webhook/signing.ts +45 -0
- package/src/plugins/webhook/ssrf.ts +198 -0
- package/src/plugins/webhook/types.ts +138 -0
- package/src/plugins/webhook/webhook.test.ts +324 -0
- package/src/sveltekit/actions.ts +233 -0
- package/src/sveltekit/catch-all.ts +43 -0
- package/src/sveltekit/cookies.ts +136 -0
- package/src/sveltekit/handle.ts +356 -0
- package/src/sveltekit/helpers.ts +69 -0
- package/src/sveltekit/index.ts +74 -0
- package/src/sveltekit/protect.ts +80 -0
- package/src/sveltekit/sveltekit-types.test.ts +31 -0
- package/src/sveltekit/sveltekit.test.ts +799 -0
- package/src/sveltekit/types.ts +134 -0
- package/src/sveltekit/validated.test.ts +117 -0
- package/src/sveltekit/validated.ts +78 -0
- package/src/testing/adapter-conformance.test.ts +408 -0
- package/src/testing/checks.test.ts +124 -0
- package/src/testing/checks.ts +304 -0
- package/src/testing/index.ts +107 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { FortressError } from '../core/errors';
|
|
3
|
+
import { findSqlstate, rethrowDbError } from './pg-error-map';
|
|
4
|
+
|
|
5
|
+
describe('findSqlstate', () => {
|
|
6
|
+
it('returns the code from the top-level error', () => {
|
|
7
|
+
expect(findSqlstate({ code: '23505' })).toBe('23505');
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it('walks the cause chain to find the SQLSTATE', () => {
|
|
11
|
+
const err = new Error('drizzle wrapper');
|
|
12
|
+
(err as any).cause = new Error('postgres-js wrapper');
|
|
13
|
+
((err as any).cause as any).cause = { code: '40P01', message: 'deadlock' };
|
|
14
|
+
expect(findSqlstate(err)).toBe('40P01');
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('only recognizes the 5-char alnum SQLSTATE shape', () => {
|
|
18
|
+
expect(findSqlstate({ code: 'CONFLICT' })).toBeNull();
|
|
19
|
+
expect(findSqlstate({ code: 'abc12' })).toBeNull(); // lowercase not allowed
|
|
20
|
+
expect(findSqlstate({ code: 12345 })).toBeNull(); // number not allowed
|
|
21
|
+
expect(findSqlstate(null)).toBeNull();
|
|
22
|
+
expect(findSqlstate(undefined)).toBeNull();
|
|
23
|
+
expect(findSqlstate('not an object')).toBeNull();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('gives up after a fixed depth', () => {
|
|
27
|
+
// Build a chain longer than MAX_CAUSE_DEPTH (6)
|
|
28
|
+
let leaf: any = { code: '23505' };
|
|
29
|
+
for (let i = 0; i < 10; i++)
|
|
30
|
+
leaf = { cause: leaf };
|
|
31
|
+
expect(findSqlstate(leaf)).toBeNull();
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
describe('rethrowDbError', () => {
|
|
36
|
+
it('passes a non-constraint sqlite error through untouched', () => {
|
|
37
|
+
// A pg SQLSTATE is not a SQLite constraint code, so under the sqlite
|
|
38
|
+
// dialect it is not recognized and the original is re-thrown.
|
|
39
|
+
const original = { code: '23505', message: 'unique violation' };
|
|
40
|
+
expect(() => rethrowDbError(original, 'sqlite')).toThrow();
|
|
41
|
+
try {
|
|
42
|
+
rethrowDbError(original, 'sqlite');
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
expect(err).toBe(original);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('maps a sqlite UNIQUE violation to CONFLICT/409 (by code)', () => {
|
|
50
|
+
try {
|
|
51
|
+
rethrowDbError({ code: 'SQLITE_CONSTRAINT_UNIQUE', message: 'UNIQUE constraint failed: user.email' }, 'sqlite');
|
|
52
|
+
throw new Error('should have thrown');
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
expect(err).toBeInstanceOf(FortressError);
|
|
56
|
+
expect((err as FortressError).code).toBe('CONFLICT');
|
|
57
|
+
expect((err as FortressError).statusCode).toBe(409);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('maps a sqlite UNIQUE violation to CONFLICT by message alone', () => {
|
|
62
|
+
// Older drivers set only the message, not a SQLITE_CONSTRAINT_* code.
|
|
63
|
+
try {
|
|
64
|
+
rethrowDbError(new Error('UNIQUE constraint failed: social_account.provider'), 'sqlite');
|
|
65
|
+
throw new Error('should have thrown');
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
expect((err as FortressError).code).toBe('CONFLICT');
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('maps sqlite PRIMARYKEY to CONFLICT and FOREIGNKEY to UNPROCESSABLE_ENTITY', () => {
|
|
73
|
+
try {
|
|
74
|
+
rethrowDbError({ code: 'SQLITE_CONSTRAINT_PRIMARYKEY' }, 'sqlite');
|
|
75
|
+
throw new Error('should have thrown');
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
expect((err as FortressError).code).toBe('CONFLICT');
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
rethrowDbError({ code: 'SQLITE_CONSTRAINT_FOREIGNKEY' }, 'sqlite');
|
|
82
|
+
throw new Error('should have thrown');
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
expect((err as FortressError).code).toBe('UNPROCESSABLE_ENTITY');
|
|
86
|
+
expect((err as FortressError).statusCode).toBe(422);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('walks the cause chain for a wrapped sqlite constraint error', () => {
|
|
91
|
+
const driver = new Error('UNIQUE constraint failed: user.email');
|
|
92
|
+
(driver as any).code = 'SQLITE_CONSTRAINT_UNIQUE';
|
|
93
|
+
const wrapper = new Error('DrizzleQueryError');
|
|
94
|
+
(wrapper as any).cause = driver;
|
|
95
|
+
try {
|
|
96
|
+
rethrowDbError(wrapper, 'sqlite');
|
|
97
|
+
throw new Error('should have thrown');
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
expect((err as FortressError).code).toBe('CONFLICT');
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('passes through unrecognized SQLSTATEs on pg', () => {
|
|
105
|
+
const original = { code: 'P0001', message: 'raise exception' };
|
|
106
|
+
try {
|
|
107
|
+
rethrowDbError(original, 'pg');
|
|
108
|
+
throw new Error('should have thrown');
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
expect(err).toBe(original);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('maps 23505 (unique_violation) to CONFLICT/409', () => {
|
|
116
|
+
try {
|
|
117
|
+
rethrowDbError({ code: '23505' }, 'pg');
|
|
118
|
+
throw new Error('should have thrown');
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
expect(err).toBeInstanceOf(FortressError);
|
|
122
|
+
expect((err as FortressError).code).toBe('CONFLICT');
|
|
123
|
+
expect((err as FortressError).statusCode).toBe(409);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('maps 23503 (foreign_key_violation) to UNPROCESSABLE_ENTITY/422', () => {
|
|
128
|
+
try {
|
|
129
|
+
rethrowDbError({ code: '23503' }, 'pg');
|
|
130
|
+
throw new Error('should have thrown');
|
|
131
|
+
}
|
|
132
|
+
catch (err) {
|
|
133
|
+
expect(err).toBeInstanceOf(FortressError);
|
|
134
|
+
expect((err as FortressError).code).toBe('UNPROCESSABLE_ENTITY');
|
|
135
|
+
expect((err as FortressError).statusCode).toBe(422);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('maps 23502 (not_null_violation) to BAD_REQUEST/400', () => {
|
|
140
|
+
try {
|
|
141
|
+
rethrowDbError({ code: '23502' }, 'pg');
|
|
142
|
+
throw new Error('should have thrown');
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
expect((err as FortressError).code).toBe('BAD_REQUEST');
|
|
146
|
+
expect((err as FortressError).statusCode).toBe(400);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it('maps 23514 (check_violation) to UNPROCESSABLE_ENTITY/422', () => {
|
|
151
|
+
try {
|
|
152
|
+
rethrowDbError({ code: '23514' }, 'pg');
|
|
153
|
+
throw new Error('should have thrown');
|
|
154
|
+
}
|
|
155
|
+
catch (err) {
|
|
156
|
+
expect((err as FortressError).code).toBe('UNPROCESSABLE_ENTITY');
|
|
157
|
+
expect((err as FortressError).statusCode).toBe(422);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('maps 40001 (serialization_failure) to CONFLICT/409', () => {
|
|
162
|
+
try {
|
|
163
|
+
rethrowDbError({ code: '40001' }, 'pg');
|
|
164
|
+
throw new Error('should have thrown');
|
|
165
|
+
}
|
|
166
|
+
catch (err) {
|
|
167
|
+
expect((err as FortressError).code).toBe('CONFLICT');
|
|
168
|
+
expect((err as FortressError).statusCode).toBe(409);
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it('maps 40P01 (deadlock_detected) to CONFLICT/409', () => {
|
|
173
|
+
try {
|
|
174
|
+
rethrowDbError({ code: '40P01' }, 'pg');
|
|
175
|
+
throw new Error('should have thrown');
|
|
176
|
+
}
|
|
177
|
+
catch (err) {
|
|
178
|
+
expect((err as FortressError).code).toBe('CONFLICT');
|
|
179
|
+
expect((err as FortressError).statusCode).toBe(409);
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it('maps 57014 (query_canceled) to SERVICE_UNAVAILABLE/503', () => {
|
|
184
|
+
try {
|
|
185
|
+
rethrowDbError({ code: '57014' }, 'pg');
|
|
186
|
+
throw new Error('should have thrown');
|
|
187
|
+
}
|
|
188
|
+
catch (err) {
|
|
189
|
+
expect((err as FortressError).code).toBe('SERVICE_UNAVAILABLE');
|
|
190
|
+
expect((err as FortressError).statusCode).toBe(503);
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it('preserves the original error as cause on the FortressError', () => {
|
|
195
|
+
const original = new Error('postgres: duplicate key value');
|
|
196
|
+
(original as any).code = '23505';
|
|
197
|
+
try {
|
|
198
|
+
rethrowDbError(original, 'pg');
|
|
199
|
+
throw new Error('should have thrown');
|
|
200
|
+
}
|
|
201
|
+
catch (err) {
|
|
202
|
+
expect((err as FortressError).cause).toBe(original);
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it('walks cause chain to find SQLSTATE on wrapped drizzle errors', () => {
|
|
207
|
+
const driver = { code: '23505', message: 'duplicate key' };
|
|
208
|
+
const wrapper = new Error('DrizzleQueryError');
|
|
209
|
+
(wrapper as any).cause = driver;
|
|
210
|
+
try {
|
|
211
|
+
rethrowDbError(wrapper, 'pg');
|
|
212
|
+
throw new Error('should have thrown');
|
|
213
|
+
}
|
|
214
|
+
catch (err) {
|
|
215
|
+
expect((err as FortressError).code).toBe('CONFLICT');
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
});
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database constraint-error → {@link FortressError} translation for the
|
|
3
|
+
* Drizzle adapter.
|
|
4
|
+
*
|
|
5
|
+
* Drizzle wraps driver-level errors before re-throwing, so a constraint
|
|
6
|
+
* violation typically surfaces as a generic `DrizzleQueryError` with the
|
|
7
|
+
* real driver error tucked under `error.cause`. Both matchers walk the
|
|
8
|
+
* cause chain up to a small fixed depth: {@link findSqlstate} looks for a
|
|
9
|
+
* Postgres 5-character SQLSTATE `code`, and the SQLite matcher looks for a
|
|
10
|
+
* `SQLITE_CONSTRAINT_*` code or the driver's constraint message.
|
|
11
|
+
*
|
|
12
|
+
* The mapping tables cover the constraint/concurrency states that almost
|
|
13
|
+
* every CRUD endpoint cares about. Anything not in the table is re-thrown
|
|
14
|
+
* unchanged so callers can still observe the raw driver error.
|
|
15
|
+
*
|
|
16
|
+
* {@link rethrowDbError} routes on the adapter `dialect`: Postgres via
|
|
17
|
+
* SQLSTATE, SQLite via constraint code/message. Unique violations map to
|
|
18
|
+
* `CONFLICT` (409) on both dialects so a mixed-dialect call site gets a
|
|
19
|
+
* stable wire response without branching.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import type { FortressError } from '../core/errors';
|
|
23
|
+
import type { DrizzleDialect } from './adapter';
|
|
24
|
+
import { Errors } from '../core/errors';
|
|
25
|
+
|
|
26
|
+
/** How many `cause` levels to walk while hunting for the SQLSTATE. */
|
|
27
|
+
const MAX_CAUSE_DEPTH = 6;
|
|
28
|
+
|
|
29
|
+
const SQLSTATE_PATTERN = /^[0-9A-Z]{5}$/;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* SQLSTATE → factory that produces the matched {@link FortressError}.
|
|
33
|
+
*
|
|
34
|
+
* Each entry maps a Postgres error class to the canonical Fortress HTTP
|
|
35
|
+
* status so downstream `protect()` middleware emits a stable wire response
|
|
36
|
+
* without the host writing a try/catch.
|
|
37
|
+
*
|
|
38
|
+
* | SQLSTATE | Meaning | Fortress error | HTTP |
|
|
39
|
+
* | -------- | -------------------- | ----------------------- | ---- |
|
|
40
|
+
* | `23505` | unique_violation | `CONFLICT` | 409 |
|
|
41
|
+
* | `23503` | foreign_key_violation| `UNPROCESSABLE_ENTITY` | 422 |
|
|
42
|
+
* | `23502` | not_null_violation | `BAD_REQUEST` | 400 |
|
|
43
|
+
* | `23514` | check_violation | `UNPROCESSABLE_ENTITY` | 422 |
|
|
44
|
+
* | `40001` | serialization_failure| `CONFLICT` | 409 |
|
|
45
|
+
* | `40P01` | deadlock_detected | `CONFLICT` | 409 |
|
|
46
|
+
* | `57014` | query_canceled | `SERVICE_UNAVAILABLE` | 503 |
|
|
47
|
+
*/
|
|
48
|
+
const PG_SQLSTATE_MAP: Record<string, (cause: unknown) => FortressError> = {
|
|
49
|
+
'23505': cause => Errors.conflict('Resource already exists', { cause }),
|
|
50
|
+
'23503': cause => Errors.unprocessable('Referenced resource does not exist', { cause }),
|
|
51
|
+
'23502': _cause => Errors.badRequest('Required field is missing'),
|
|
52
|
+
'23514': cause => Errors.unprocessable('Constraint check failed', { cause }),
|
|
53
|
+
'40001': cause => Errors.conflict('Serialization failure, retry the request', { cause }),
|
|
54
|
+
'40P01': cause => Errors.conflict('Deadlock detected, retry the request', { cause }),
|
|
55
|
+
'57014': cause => Errors.serviceUnavailable('Query canceled', { cause }),
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
interface MaybeCoded {
|
|
59
|
+
code?: unknown;
|
|
60
|
+
message?: unknown;
|
|
61
|
+
cause?: unknown;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* SQLite constraint matchers. better-sqlite3 and bun:sqlite both surface a
|
|
66
|
+
* `SQLITE_CONSTRAINT_*` `code`; older builds only set the message, so each
|
|
67
|
+
* entry matches either. Tested against `${code} ${message}` at every level
|
|
68
|
+
* of the cause chain.
|
|
69
|
+
*/
|
|
70
|
+
const SQLITE_CONSTRAINT_MAP: { match: RegExp; factory: (cause: unknown) => FortressError }[] = [
|
|
71
|
+
{
|
|
72
|
+
match: /SQLITE_CONSTRAINT_(?:UNIQUE|PRIMARYKEY)|UNIQUE constraint failed/i,
|
|
73
|
+
factory: cause => Errors.conflict('Resource already exists', { cause }),
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
match: /SQLITE_CONSTRAINT_FOREIGNKEY|FOREIGN KEY constraint failed/i,
|
|
77
|
+
factory: cause => Errors.unprocessable('Referenced resource does not exist', { cause }),
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
match: /SQLITE_CONSTRAINT_NOTNULL|NOT NULL constraint failed/i,
|
|
81
|
+
factory: _cause => Errors.badRequest('Required field is missing'),
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Walk the `cause` chain looking for a SQLite constraint violation, testing
|
|
87
|
+
* each level's `code`/`message` against {@link SQLITE_CONSTRAINT_MAP}.
|
|
88
|
+
* Returns the matching {@link FortressError} or `null` when none is found
|
|
89
|
+
* within {@link MAX_CAUSE_DEPTH} hops.
|
|
90
|
+
*/
|
|
91
|
+
function mapSqliteConstraint(err: unknown): FortressError | null {
|
|
92
|
+
let current: unknown = err;
|
|
93
|
+
for (let i = 0; i < MAX_CAUSE_DEPTH; i++) {
|
|
94
|
+
if (current === null || typeof current !== 'object')
|
|
95
|
+
return null;
|
|
96
|
+
const coded = current as MaybeCoded;
|
|
97
|
+
const code = typeof coded.code === 'string' ? coded.code : '';
|
|
98
|
+
const message = typeof coded.message === 'string' ? coded.message : '';
|
|
99
|
+
const haystack = `${code} ${message}`;
|
|
100
|
+
for (const { match, factory } of SQLITE_CONSTRAINT_MAP) {
|
|
101
|
+
if (match.test(haystack))
|
|
102
|
+
return factory(err);
|
|
103
|
+
}
|
|
104
|
+
current = coded.cause;
|
|
105
|
+
}
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Walk the `cause` chain of an unknown thrown value looking for a property
|
|
111
|
+
* named `code` that smells like a Postgres SQLSTATE (5 uppercase
|
|
112
|
+
* alphanumerics, e.g. `23505`, `40P01`). Returns the first match it finds
|
|
113
|
+
* or `null` when none is present within {@link MAX_CAUSE_DEPTH} hops.
|
|
114
|
+
*/
|
|
115
|
+
export function findSqlstate(err: unknown): string | null {
|
|
116
|
+
let current: unknown = err;
|
|
117
|
+
for (let i = 0; i < MAX_CAUSE_DEPTH; i++) {
|
|
118
|
+
if (current === null || typeof current !== 'object')
|
|
119
|
+
return null;
|
|
120
|
+
const candidate = (current as MaybeCoded).code;
|
|
121
|
+
if (typeof candidate === 'string' && SQLSTATE_PATTERN.test(candidate))
|
|
122
|
+
return candidate;
|
|
123
|
+
current = (current as MaybeCoded).cause;
|
|
124
|
+
}
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Translate a driver constraint error into a {@link FortressError} for the
|
|
130
|
+
* given `dialect`, then throw it. Postgres routes through
|
|
131
|
+
* {@link PG_SQLSTATE_MAP} by SQLSTATE; SQLite through
|
|
132
|
+
* {@link SQLITE_CONSTRAINT_MAP} by constraint code/message. Errors that
|
|
133
|
+
* don't match a known constraint are re-thrown unchanged so callers can
|
|
134
|
+
* still observe the raw driver error.
|
|
135
|
+
*/
|
|
136
|
+
export function rethrowDbError(err: unknown, dialect: DrizzleDialect): never {
|
|
137
|
+
if (dialect === 'pg') {
|
|
138
|
+
const sqlstate = findSqlstate(err);
|
|
139
|
+
const factory = sqlstate ? PG_SQLSTATE_MAP[sqlstate] : undefined;
|
|
140
|
+
if (factory)
|
|
141
|
+
throw factory(err);
|
|
142
|
+
throw err;
|
|
143
|
+
}
|
|
144
|
+
if (dialect === 'sqlite') {
|
|
145
|
+
const mapped = mapSqliteConstraint(err);
|
|
146
|
+
if (mapped)
|
|
147
|
+
throw mapped;
|
|
148
|
+
throw err;
|
|
149
|
+
}
|
|
150
|
+
throw err;
|
|
151
|
+
}
|