@atproto/oauth-provider 0.6.5 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -0
- package/dist/access-token/access-token-mode.d.ts +5 -0
- package/dist/access-token/access-token-mode.d.ts.map +1 -0
- package/dist/access-token/access-token-mode.js +9 -0
- package/dist/access-token/access-token-mode.js.map +1 -0
- package/dist/account/account-manager.d.ts +13 -7
- package/dist/account/account-manager.d.ts.map +1 -1
- package/dist/account/account-manager.js +69 -52
- package/dist/account/account-manager.js.map +1 -1
- package/dist/account/account-store.d.ts +88 -77
- package/dist/account/account-store.d.ts.map +1 -1
- package/dist/account/account-store.js +24 -73
- package/dist/account/account-store.js.map +1 -1
- package/dist/account/sign-in-data.d.ts +4 -13
- package/dist/account/sign-in-data.d.ts.map +1 -1
- package/dist/account/sign-in-data.js +9 -9
- package/dist/account/sign-in-data.js.map +1 -1
- package/dist/account/sign-up-input.d.ts +4 -5
- package/dist/account/sign-up-input.d.ts.map +1 -1
- package/dist/account/sign-up-input.js +13 -3
- package/dist/account/sign-up-input.js.map +1 -1
- package/dist/client/client-manager.d.ts +4 -1
- package/dist/client/client-manager.d.ts.map +1 -1
- package/dist/client/client-manager.js +13 -1
- package/dist/client/client-manager.js.map +1 -1
- package/dist/client/client-store.d.ts +1 -1
- package/dist/client/client-store.d.ts.map +1 -1
- package/dist/constants.d.ts +5 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +6 -2
- package/dist/constants.js.map +1 -1
- package/dist/customization/branding.d.ts +54 -0
- package/dist/customization/branding.d.ts.map +1 -0
- package/dist/customization/branding.js +13 -0
- package/dist/customization/branding.js.map +1 -0
- package/dist/customization/build-customization-css.d.ts +3 -0
- package/dist/customization/build-customization-css.d.ts.map +1 -0
- package/dist/customization/build-customization-css.js +27 -0
- package/dist/customization/build-customization-css.js.map +1 -0
- package/dist/customization/build-customization-data.d.ts +4 -0
- package/dist/customization/build-customization-data.d.ts.map +1 -0
- package/dist/customization/build-customization-data.js +18 -0
- package/dist/customization/build-customization-data.js.map +1 -0
- package/dist/customization/colors.d.ts +7 -0
- package/dist/customization/colors.d.ts.map +1 -0
- package/dist/customization/colors.js +27 -0
- package/dist/customization/colors.js.map +1 -0
- package/dist/customization/customization.d.ts +129 -0
- package/dist/customization/customization.d.ts.map +1 -0
- package/dist/customization/customization.js +26 -0
- package/dist/customization/customization.js.map +1 -0
- package/dist/customization/links.d.ts +26 -0
- package/dist/customization/links.d.ts.map +1 -0
- package/dist/customization/links.js +12 -0
- package/dist/customization/links.js.map +1 -0
- package/dist/device/device-id.d.ts +1 -0
- package/dist/device/device-id.d.ts.map +1 -1
- package/dist/device/device-id.js +4 -0
- package/dist/device/device-id.js.map +1 -1
- package/dist/device/device-manager.d.ts +6 -36
- package/dist/device/device-manager.d.ts.map +1 -1
- package/dist/device/device-manager.js +49 -43
- package/dist/device/device-manager.js.map +1 -1
- package/dist/device/device-store.d.ts +1 -0
- package/dist/device/device-store.d.ts.map +1 -1
- package/dist/device/device-store.js.map +1 -1
- package/dist/dpop/dpop-manager.d.ts +3 -3
- package/dist/dpop/dpop-nonce.d.ts +3 -3
- package/dist/dpop/dpop-nonce.d.ts.map +1 -1
- package/dist/errors/access-denied-error.d.ts +4 -3
- package/dist/errors/access-denied-error.d.ts.map +1 -1
- package/dist/errors/access-denied-error.js +5 -6
- package/dist/errors/access-denied-error.js.map +1 -1
- package/dist/{output/build-error-payload.d.ts → errors/error-parser.d.ts} +1 -1
- package/dist/errors/error-parser.d.ts.map +1 -0
- package/dist/{output/build-error-payload.js → errors/error-parser.js} +2 -2
- package/dist/errors/error-parser.js.map +1 -0
- package/dist/errors/invalid-grant-error.d.ts +1 -0
- package/dist/errors/invalid-grant-error.d.ts.map +1 -1
- package/dist/errors/invalid-grant-error.js +5 -0
- package/dist/errors/invalid-grant-error.js.map +1 -1
- package/dist/errors/login-required-error.d.ts +1 -0
- package/dist/errors/login-required-error.d.ts.map +1 -1
- package/dist/errors/login-required-error.js +5 -0
- package/dist/errors/login-required-error.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/html/build-document.d.ts +2 -2
- package/dist/lib/html/build-document.d.ts.map +1 -1
- package/dist/lib/html/build-document.js +4 -0
- package/dist/lib/html/build-document.js.map +1 -1
- package/dist/lib/html/hydration-data.d.ts +4 -0
- package/dist/lib/html/hydration-data.d.ts.map +1 -0
- package/dist/{output/backend-data.js → lib/html/hydration-data.js} +8 -8
- package/dist/lib/html/hydration-data.js.map +1 -0
- package/dist/lib/html/tags.d.ts +1 -1
- package/dist/lib/html/tags.d.ts.map +1 -1
- package/dist/lib/html/tags.js +1 -1
- package/dist/lib/html/tags.js.map +1 -1
- package/dist/lib/http/accept.d.ts +2 -2
- package/dist/lib/http/accept.d.ts.map +1 -1
- package/dist/lib/http/accept.js +1 -1
- package/dist/lib/http/accept.js.map +1 -1
- package/dist/lib/http/context.d.ts +2 -4
- package/dist/lib/http/context.d.ts.map +1 -1
- package/dist/lib/http/context.js +29 -4
- package/dist/lib/http/context.js.map +1 -1
- package/dist/lib/http/headers.d.ts +3 -0
- package/dist/lib/http/headers.d.ts.map +1 -0
- package/dist/lib/http/headers.js +14 -0
- package/dist/lib/http/headers.js.map +1 -0
- package/dist/lib/http/index.d.ts +1 -0
- package/dist/lib/http/index.d.ts.map +1 -1
- package/dist/lib/http/index.js +1 -0
- package/dist/lib/http/index.js.map +1 -1
- package/dist/lib/http/middleware.d.ts +1 -1
- package/dist/lib/http/middleware.d.ts.map +1 -1
- package/dist/lib/http/middleware.js +8 -24
- package/dist/lib/http/middleware.js.map +1 -1
- package/dist/lib/http/parser.d.ts +3 -3
- package/dist/lib/http/parser.d.ts.map +1 -1
- package/dist/lib/http/request.d.ts +13 -9
- package/dist/lib/http/request.d.ts.map +1 -1
- package/dist/lib/http/request.js +27 -49
- package/dist/lib/http/request.js.map +1 -1
- package/dist/lib/http/response.d.ts +6 -2
- package/dist/lib/http/response.d.ts.map +1 -1
- package/dist/lib/http/response.js +31 -11
- package/dist/lib/http/response.js.map +1 -1
- package/dist/lib/http/route.d.ts +3 -3
- package/dist/lib/http/route.d.ts.map +1 -1
- package/dist/lib/http/route.js +1 -1
- package/dist/lib/http/route.js.map +1 -1
- package/dist/lib/http/router.d.ts +12 -11
- package/dist/lib/http/router.d.ts.map +1 -1
- package/dist/lib/http/router.js +26 -34
- package/dist/lib/http/router.js.map +1 -1
- package/dist/lib/http/security-headers.js +1 -1
- package/dist/lib/http/security-headers.js.map +1 -1
- package/dist/lib/http/stream.d.ts +3 -3
- package/dist/lib/http/stream.d.ts.map +1 -1
- package/dist/lib/http/types.d.ts +1 -1
- package/dist/lib/http/types.d.ts.map +1 -1
- package/dist/lib/send-web-page.d.ts +8 -0
- package/dist/lib/send-web-page.d.ts.map +1 -0
- package/dist/{output → lib}/send-web-page.js +9 -7
- package/dist/lib/send-web-page.js.map +1 -0
- package/dist/lib/util/authorization-header.d.ts.map +1 -1
- package/dist/lib/util/color.d.ts +32 -0
- package/dist/lib/util/color.d.ts.map +1 -0
- package/dist/lib/util/color.js +116 -0
- package/dist/lib/util/color.js.map +1 -0
- package/dist/lib/util/crypto.d.ts +1 -0
- package/dist/lib/util/crypto.d.ts.map +1 -1
- package/dist/lib/util/crypto.js +8 -3
- package/dist/lib/util/crypto.js.map +1 -1
- package/dist/lib/util/function.d.ts +1 -0
- package/dist/lib/util/function.d.ts.map +1 -1
- package/dist/lib/util/function.js +12 -0
- package/dist/lib/util/function.js.map +1 -1
- package/dist/lib/util/locale.d.ts +20 -0
- package/dist/lib/util/locale.d.ts.map +1 -0
- package/dist/lib/util/locale.js +14 -0
- package/dist/lib/util/locale.js.map +1 -0
- package/dist/lib/util/time.d.ts +1 -1
- package/dist/lib/util/time.d.ts.map +1 -1
- package/dist/lib/util/time.js +1 -1
- package/dist/lib/util/time.js.map +1 -1
- package/dist/lib/util/type.d.ts +22 -0
- package/dist/lib/util/type.d.ts.map +1 -1
- package/dist/lib/util/type.js.map +1 -1
- package/dist/lib/util/ui8.d.ts +4 -0
- package/dist/lib/util/ui8.d.ts.map +1 -0
- package/dist/lib/util/ui8.js +17 -0
- package/dist/lib/util/ui8.js.map +1 -0
- package/dist/lib/util/zod-error.d.ts +2 -0
- package/dist/lib/util/zod-error.d.ts.map +1 -0
- package/dist/lib/util/zod-error.js +16 -0
- package/dist/lib/util/zod-error.js.map +1 -0
- package/dist/oauth-errors.d.ts +22 -22
- package/dist/oauth-errors.d.ts.map +1 -1
- package/dist/oauth-errors.js +37 -45
- package/dist/oauth-errors.js.map +1 -1
- package/dist/oauth-hooks.d.ts +11 -23
- package/dist/oauth-hooks.d.ts.map +1 -1
- package/dist/oauth-hooks.js.map +1 -1
- package/dist/oauth-middleware.d.ts +12 -0
- package/dist/oauth-middleware.d.ts.map +1 -0
- package/dist/oauth-middleware.js +32 -0
- package/dist/oauth-middleware.js.map +1 -0
- package/dist/oauth-provider.d.ts +109 -113
- package/dist/oauth-provider.d.ts.map +1 -1
- package/dist/oauth-provider.js +124 -542
- package/dist/oauth-provider.js.map +1 -1
- package/dist/oauth-verifier.d.ts +7 -26
- package/dist/oauth-verifier.d.ts.map +1 -1
- package/dist/oauth-verifier.js +6 -16
- package/dist/oauth-verifier.js.map +1 -1
- package/dist/request/code.d.ts.map +1 -1
- package/dist/request/request-data.d.ts +2 -4
- package/dist/request/request-data.d.ts.map +1 -1
- package/dist/request/request-data.js.map +1 -1
- package/dist/request/request-manager.d.ts +4 -2
- package/dist/request/request-manager.d.ts.map +1 -1
- package/dist/request/request-manager.js +9 -8
- package/dist/request/request-manager.js.map +1 -1
- package/dist/request/request-store.d.ts +6 -0
- package/dist/request/request-store.d.ts.map +1 -1
- package/dist/request/request-store.js +3 -1
- package/dist/request/request-store.js.map +1 -1
- package/dist/result/authorization-redirect-parameters.d.ts +18 -0
- package/dist/result/authorization-redirect-parameters.d.ts.map +1 -0
- package/dist/result/authorization-redirect-parameters.js +3 -0
- package/dist/result/authorization-redirect-parameters.js.map +1 -0
- package/dist/result/authorization-result-authorize-page.d.ts +13 -0
- package/dist/result/authorization-result-authorize-page.d.ts.map +1 -0
- package/dist/result/authorization-result-authorize-page.js +3 -0
- package/dist/result/authorization-result-authorize-page.js.map +1 -0
- package/dist/result/authorization-result-redirect.d.ts +8 -0
- package/dist/result/authorization-result-redirect.d.ts.map +1 -0
- package/dist/result/authorization-result-redirect.js +3 -0
- package/dist/result/authorization-result-redirect.js.map +1 -0
- package/dist/router/assets/assets-manifest.d.ts +10 -0
- package/dist/router/assets/assets-manifest.d.ts.map +1 -0
- package/dist/router/assets/assets-manifest.js +77 -0
- package/dist/router/assets/assets-manifest.js.map +1 -0
- package/dist/router/assets/assets.d.ts +16 -0
- package/dist/router/assets/assets.d.ts.map +1 -0
- package/dist/router/assets/assets.js +43 -0
- package/dist/router/assets/assets.js.map +1 -0
- package/dist/router/assets/csrf.d.ts +4 -0
- package/dist/router/assets/csrf.d.ts.map +1 -0
- package/dist/router/assets/csrf.js +51 -0
- package/dist/router/assets/csrf.js.map +1 -0
- package/dist/router/assets/send-account-page.d.ts +7 -0
- package/dist/router/assets/send-account-page.d.ts.map +1 -0
- package/dist/router/assets/send-account-page.js +34 -0
- package/dist/router/assets/send-account-page.js.map +1 -0
- package/dist/router/assets/send-authorization-page.d.ts +5 -0
- package/dist/router/assets/send-authorization-page.d.ts.map +1 -0
- package/dist/router/assets/send-authorization-page.js +49 -0
- package/dist/router/assets/send-authorization-page.js.map +1 -0
- package/dist/router/assets/send-error-page.d.ts +4 -0
- package/dist/router/assets/send-error-page.d.ts.map +1 -0
- package/dist/router/assets/send-error-page.js +34 -0
- package/dist/router/assets/send-error-page.js.map +1 -0
- package/dist/router/create-account-page-middleware.d.ts +6 -0
- package/dist/router/create-account-page-middleware.d.ts.map +1 -0
- package/dist/router/create-account-page-middleware.js +39 -0
- package/dist/router/create-account-page-middleware.js.map +1 -0
- package/dist/router/create-api-middleware.d.ts +8 -0
- package/dist/router/create-api-middleware.d.ts.map +1 -0
- package/dist/router/create-api-middleware.js +501 -0
- package/dist/router/create-api-middleware.js.map +1 -0
- package/dist/router/create-authorization-page-middleware.d.ts +6 -0
- package/dist/router/create-authorization-page-middleware.d.ts.map +1 -0
- package/dist/router/create-authorization-page-middleware.js +104 -0
- package/dist/router/create-authorization-page-middleware.js.map +1 -0
- package/dist/router/create-oauth-middleware.d.ts +6 -0
- package/dist/router/create-oauth-middleware.d.ts.map +1 -0
- package/dist/router/create-oauth-middleware.js +142 -0
- package/dist/router/create-oauth-middleware.js.map +1 -0
- package/dist/router/error-handler.d.ts +3 -0
- package/dist/router/error-handler.d.ts.map +1 -0
- package/dist/{account/account.js → router/error-handler.js} +1 -1
- package/dist/router/error-handler.js.map +1 -0
- package/dist/router/middleware-options.d.ts +6 -0
- package/dist/router/middleware-options.d.ts.map +1 -0
- package/dist/router/middleware-options.js +3 -0
- package/dist/router/middleware-options.js.map +1 -0
- package/dist/router/send-redirect.d.ts +16 -0
- package/dist/router/send-redirect.d.ts.map +1 -0
- package/dist/{output/send-authorize-redirect.js → router/send-redirect.js} +40 -24
- package/dist/router/send-redirect.js.map +1 -0
- package/dist/{token/token-claims.d.ts → signer/api-token-payload.d.ts} +237 -232
- package/dist/signer/api-token-payload.d.ts.map +1 -0
- package/dist/signer/api-token-payload.js +17 -0
- package/dist/signer/api-token-payload.js.map +1 -0
- package/dist/signer/signed-token-payload.d.ts +164 -159
- package/dist/signer/signed-token-payload.d.ts.map +1 -1
- package/dist/signer/signed-token-payload.js +10 -16
- package/dist/signer/signed-token-payload.js.map +1 -1
- package/dist/signer/signer.d.ts +42 -11246
- package/dist/signer/signer.d.ts.map +1 -1
- package/dist/signer/signer.js +30 -15
- package/dist/signer/signer.js.map +1 -1
- package/dist/token/refresh-token.d.ts.map +1 -1
- package/dist/token/token-data.d.ts +1 -1
- package/dist/token/token-data.d.ts.map +1 -1
- package/dist/token/token-id.d.ts.map +1 -1
- package/dist/token/token-manager.d.ts +28 -26
- package/dist/token/token-manager.d.ts.map +1 -1
- package/dist/token/token-manager.js +138 -196
- package/dist/token/token-manager.js.map +1 -1
- package/dist/token/token-store.d.ts +4 -4
- package/dist/token/token-store.d.ts.map +1 -1
- package/dist/token/token-store.js +1 -0
- package/dist/token/token-store.js.map +1 -1
- package/dist/token/verify-token-claims.d.ts +3 -3
- package/dist/token/verify-token-claims.d.ts.map +1 -1
- package/dist/token/verify-token-claims.js +1 -1
- package/dist/token/verify-token-claims.js.map +1 -1
- package/dist/types/email-otp.d.ts +3 -0
- package/dist/types/email-otp.d.ts.map +1 -0
- package/dist/types/email-otp.js +6 -0
- package/dist/types/email-otp.js.map +1 -0
- package/dist/types/email.d.ts +3 -0
- package/dist/types/email.d.ts.map +1 -0
- package/dist/types/email.js +29 -0
- package/dist/types/email.js.map +1 -0
- package/dist/types/handle.d.ts +3 -0
- package/dist/types/handle.d.ts.map +1 -0
- package/dist/types/handle.js +22 -0
- package/dist/types/handle.js.map +1 -0
- package/dist/types/invite-code.d.ts +4 -0
- package/dist/types/invite-code.d.ts.map +1 -0
- package/dist/types/invite-code.js +6 -0
- package/dist/types/invite-code.js.map +1 -0
- package/dist/types/password.d.ts +4 -0
- package/dist/types/password.d.ts.map +1 -0
- package/dist/types/password.js +7 -0
- package/dist/types/password.js.map +1 -0
- package/package.json +11 -8
- package/src/access-token/access-token-mode.ts +4 -0
- package/src/account/account-manager.ts +105 -75
- package/src/account/account-store.ts +118 -114
- package/src/account/sign-in-data.ts +10 -10
- package/src/account/sign-up-input.ts +13 -4
- package/src/client/client-manager.ts +34 -2
- package/src/client/client-store.ts +1 -1
- package/src/constants.ts +6 -1
- package/src/customization/branding.ts +12 -0
- package/src/customization/build-customization-css.ts +30 -0
- package/src/customization/build-customization-data.ts +22 -0
- package/src/customization/colors.ts +30 -0
- package/src/customization/customization.ts +25 -0
- package/src/customization/links.ts +10 -0
- package/src/device/device-id.ts +5 -0
- package/src/device/device-manager.ts +76 -66
- package/src/device/device-store.ts +2 -0
- package/src/errors/access-denied-error.ts +24 -17
- package/src/{output/build-error-payload.ts → errors/error-parser.ts} +1 -1
- package/src/errors/invalid-grant-error.ts +5 -0
- package/src/errors/login-required-error.ts +10 -0
- package/src/index.ts +1 -0
- package/src/lib/html/build-document.ts +6 -4
- package/src/{output/backend-data.ts → lib/html/hydration-data.ts} +7 -5
- package/src/lib/html/tags.ts +2 -2
- package/src/lib/http/accept.ts +3 -3
- package/src/lib/http/context.ts +41 -10
- package/src/lib/http/headers.ts +15 -0
- package/src/lib/http/index.ts +1 -0
- package/src/lib/http/middleware.ts +8 -23
- package/src/lib/http/request.ts +40 -75
- package/src/lib/http/response.ts +39 -15
- package/src/lib/http/route.ts +8 -5
- package/src/lib/http/router.ts +40 -46
- package/src/lib/http/security-headers.ts +1 -1
- package/src/lib/http/types.ts +1 -6
- package/src/{output → lib}/send-web-page.ts +10 -9
- package/src/lib/util/color.ts +132 -0
- package/src/lib/util/crypto.ts +9 -4
- package/src/lib/util/function.ts +14 -0
- package/src/lib/util/locale.ts +18 -0
- package/src/lib/util/time.ts +3 -4
- package/src/lib/util/type.ts +24 -0
- package/src/lib/util/ui8.ts +14 -0
- package/src/lib/util/zod-error.ts +14 -0
- package/src/oauth-errors.ts +22 -22
- package/src/oauth-hooks.ts +11 -24
- package/src/oauth-middleware.ts +53 -0
- package/src/oauth-provider.ts +290 -1061
- package/src/oauth-verifier.ts +9 -55
- package/src/request/request-data.ts +5 -4
- package/src/request/request-manager.ts +11 -11
- package/src/request/request-store.ts +7 -0
- package/src/result/authorization-redirect-parameters.ts +24 -0
- package/src/result/authorization-result-authorize-page.ts +14 -0
- package/src/result/authorization-result-redirect.ts +8 -0
- package/src/router/assets/assets-manifest.ts +108 -0
- package/src/router/assets/assets.ts +54 -0
- package/src/router/assets/csrf.ts +63 -0
- package/src/router/assets/send-account-page.ts +43 -0
- package/src/router/assets/send-authorization-page.ts +62 -0
- package/src/router/assets/send-error-page.ts +42 -0
- package/src/router/create-account-page-middleware.ts +69 -0
- package/src/router/create-api-middleware.ts +814 -0
- package/src/router/create-authorization-page-middleware.ts +173 -0
- package/src/router/create-oauth-middleware.ts +247 -0
- package/src/router/error-handler.ts +6 -0
- package/src/router/middleware-options.ts +9 -0
- package/src/router/send-redirect.ts +142 -0
- package/src/signer/api-token-payload.ts +18 -0
- package/src/signer/signed-token-payload.ts +18 -28
- package/src/signer/signer.ts +49 -34
- package/src/token/token-data.ts +1 -1
- package/src/token/token-manager.ts +190 -239
- package/src/token/token-store.ts +6 -4
- package/src/token/verify-token-claims.ts +4 -4
- package/src/types/email-otp.ts +3 -0
- package/src/types/email.ts +26 -0
- package/src/types/handle.ts +18 -0
- package/src/types/invite-code.ts +4 -0
- package/src/types/password.ts +4 -0
- package/tsconfig.build.tsbuildinfo +1 -0
- package/tsconfig.json +1 -1
- package/dist/access-token/access-token-type.d.ts +0 -6
- package/dist/access-token/access-token-type.d.ts.map +0 -1
- package/dist/access-token/access-token-type.js +0 -10
- package/dist/access-token/access-token-type.js.map +0 -1
- package/dist/account/account.d.ts +0 -2
- package/dist/account/account.d.ts.map +0 -1
- package/dist/account/account.js.map +0 -1
- package/dist/assets/assets-middleware.d.ts +0 -5
- package/dist/assets/assets-middleware.d.ts.map +0 -1
- package/dist/assets/assets-middleware.js +0 -41
- package/dist/assets/assets-middleware.js.map +0 -1
- package/dist/lib/locale.d.ts +0 -15
- package/dist/lib/locale.d.ts.map +0 -1
- package/dist/lib/locale.js +0 -17
- package/dist/lib/locale.js.map +0 -1
- package/dist/output/backend-data.d.ts +0 -4
- package/dist/output/backend-data.d.ts.map +0 -1
- package/dist/output/backend-data.js.map +0 -1
- package/dist/output/build-authorize-data.d.ts +0 -29
- package/dist/output/build-authorize-data.d.ts.map +0 -1
- package/dist/output/build-authorize-data.js +0 -21
- package/dist/output/build-authorize-data.js.map +0 -1
- package/dist/output/build-customization-data.d.ts +0 -234
- package/dist/output/build-customization-data.d.ts.map +0 -1
- package/dist/output/build-customization-data.js +0 -174
- package/dist/output/build-customization-data.js.map +0 -1
- package/dist/output/build-error-data.d.ts +0 -3
- package/dist/output/build-error-data.d.ts.map +0 -1
- package/dist/output/build-error-data.js +0 -10
- package/dist/output/build-error-data.js.map +0 -1
- package/dist/output/build-error-payload.d.ts.map +0 -1
- package/dist/output/build-error-payload.js.map +0 -1
- package/dist/output/output-manager.d.ts +0 -28
- package/dist/output/output-manager.d.ts.map +0 -1
- package/dist/output/output-manager.js +0 -134
- package/dist/output/output-manager.js.map +0 -1
- package/dist/output/send-authorize-redirect.d.ts +0 -25
- package/dist/output/send-authorize-redirect.d.ts.map +0 -1
- package/dist/output/send-authorize-redirect.js.map +0 -1
- package/dist/output/send-web-page.d.ts +0 -8
- package/dist/output/send-web-page.d.ts.map +0 -1
- package/dist/output/send-web-page.js.map +0 -1
- package/dist/token/token-claims.d.ts.map +0 -1
- package/dist/token/token-claims.js +0 -27
- package/dist/token/token-claims.js.map +0 -1
- package/src/access-token/access-token-type.ts +0 -5
- package/src/account/account.ts +0 -1
- package/src/assets/assets-middleware.ts +0 -44
- package/src/lib/locale.ts +0 -21
- package/src/output/build-authorize-data.ts +0 -53
- package/src/output/build-customization-data.ts +0 -217
- package/src/output/build-error-data.ts +0 -8
- package/src/output/output-manager.ts +0 -188
- package/src/output/send-authorize-redirect.ts +0 -137
- package/src/token/token-claims.ts +0 -30
- package/tsconfig.backend.tsbuildinfo +0 -1
- /package/{tsconfig.backend.json → tsconfig.build.json} +0 -0
@@ -1,11 +1,19 @@
|
|
1
1
|
import type { IncomingMessage, ServerResponse } from 'node:http'
|
2
|
-
import { serialize as serializeCookie } from 'cookie'
|
3
2
|
import { z } from 'zod'
|
4
3
|
import { SESSION_FIXATION_MAX_AGE } from '../constants.js'
|
5
|
-
import {
|
6
|
-
import {
|
4
|
+
import { parseHttpCookies } from '../lib/http/index.js'
|
5
|
+
import {
|
6
|
+
RequestMetadata,
|
7
|
+
extractRequestMetadata,
|
8
|
+
setCookie,
|
9
|
+
} from '../lib/http/request.js'
|
7
10
|
import { DeviceData } from './device-data.js'
|
8
|
-
import {
|
11
|
+
import {
|
12
|
+
DeviceId,
|
13
|
+
deviceIdSchema,
|
14
|
+
generateDeviceId,
|
15
|
+
isDeviceId,
|
16
|
+
} from './device-id.js'
|
9
17
|
import { DeviceStore } from './device-store.js'
|
10
18
|
import { generateSessionId, sessionIdSchema } from './session-id.js'
|
11
19
|
|
@@ -41,24 +49,6 @@ export const deviceManagerOptionsSchema = z.object({
|
|
41
49
|
cookie: z
|
42
50
|
.object({
|
43
51
|
keys: keygripSchema.optional(),
|
44
|
-
/**
|
45
|
-
* Name of the cookie used to identify the device
|
46
|
-
*
|
47
|
-
* @default 'session-id'
|
48
|
-
*/
|
49
|
-
device: z.string().default('device-id'),
|
50
|
-
/**
|
51
|
-
* Name of the cookie used to identify the session
|
52
|
-
*
|
53
|
-
* @default 'session-id'
|
54
|
-
*/
|
55
|
-
session: z.string().default('session-id'),
|
56
|
-
/**
|
57
|
-
* Url path for the cookie
|
58
|
-
*
|
59
|
-
* @default '/oauth/authorize'
|
60
|
-
*/
|
61
|
-
path: z.string().default('/oauth/authorize'),
|
62
52
|
/**
|
63
53
|
* Amount of time (in ms) after which the session cookie will expire.
|
64
54
|
* If set to `null`, the cookie will be a session cookie (deleted when the
|
@@ -88,8 +78,10 @@ export const deviceManagerOptionsSchema = z.object({
|
|
88
78
|
|
89
79
|
export type DeviceManagerOptions = z.input<typeof deviceManagerOptionsSchema>
|
90
80
|
|
91
|
-
|
92
|
-
|
81
|
+
type CookieValue = {
|
82
|
+
deviceId: DeviceId
|
83
|
+
sessionId: string
|
84
|
+
}
|
93
85
|
|
94
86
|
export type DeviceInfo = {
|
95
87
|
deviceId: DeviceId
|
@@ -116,7 +108,7 @@ export class DeviceManager {
|
|
116
108
|
res: ServerResponse,
|
117
109
|
forceRotate = false,
|
118
110
|
): Promise<DeviceInfo> {
|
119
|
-
const cookie = await this.
|
111
|
+
const cookie = await this.getCookies(req, res)
|
120
112
|
if (cookie) {
|
121
113
|
return this.refresh(
|
122
114
|
req,
|
@@ -147,7 +139,7 @@ export class DeviceManager {
|
|
147
139
|
ipAddress: deviceMetadata.ipAddress,
|
148
140
|
})
|
149
141
|
|
150
|
-
this.
|
142
|
+
await this.setCookies(req, res, { deviceId, sessionId })
|
151
143
|
|
152
144
|
return { deviceId, deviceMetadata }
|
153
145
|
}
|
@@ -155,7 +147,7 @@ export class DeviceManager {
|
|
155
147
|
private async refresh(
|
156
148
|
req: IncomingMessage,
|
157
149
|
res: ServerResponse,
|
158
|
-
|
150
|
+
{ deviceId, sessionId }: CookieValue,
|
159
151
|
forceRotate = false,
|
160
152
|
): Promise<DeviceInfo> {
|
161
153
|
const data = await this.store.readDevice(deviceId)
|
@@ -207,36 +199,56 @@ export class DeviceManager {
|
|
207
199
|
lastSeenAt: new Date(),
|
208
200
|
})
|
209
201
|
|
210
|
-
this.
|
202
|
+
await this.setCookies(req, res, { deviceId, sessionId })
|
211
203
|
}
|
212
204
|
|
213
|
-
private async
|
205
|
+
private async getCookies(
|
214
206
|
req: IncomingMessage,
|
207
|
+
res: ServerResponse,
|
215
208
|
): Promise<{ value: CookieValue; mustRotate: boolean } | null> {
|
216
209
|
const cookies = parseHttpCookies(req)
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
210
|
+
|
211
|
+
// Old cookies were set for the "/oauth/authorize" path while new cookies
|
212
|
+
// need to be set for the "/" path (in order to be valid on the api,
|
213
|
+
// authorization page and account page). This means that if a user has both
|
214
|
+
// cookies set, the browser would use the old cookie for the
|
215
|
+
// "/oauth/authorize" path and the new cookie for all other paths. Because
|
216
|
+
// of this, different "phantom" sessions would be created for the same
|
217
|
+
// device. To avoid this, we needed to change the cookie name. We can still
|
218
|
+
// attempt to read the old cookie in order to carry over the session from
|
219
|
+
// the "/oauth/authorize" path to the "/" path. This will only work if the
|
220
|
+
// user visits the "/oauth/authorize" path first.
|
221
|
+
|
222
|
+
const device =
|
223
|
+
this.parseCookie(cookies, `dev-id`, deviceIdSchema) ||
|
224
|
+
this.parseCookie(cookies, 'device-id', deviceIdSchema)
|
225
|
+
const session =
|
226
|
+
this.parseCookie(cookies, `ses-id`, sessionIdSchema) ||
|
227
|
+
this.parseCookie(cookies, 'session-id', sessionIdSchema)
|
228
|
+
|
229
|
+
const deviceId = device?.value
|
230
|
+
const sessionId = session?.value
|
231
|
+
|
232
|
+
// Clear the legacy cookies, if they are set.
|
233
|
+
if (isDeviceId(cookies['device-id']) && cookies['device-id'] !== deviceId) {
|
234
|
+
await this.store.deleteDevice(cookies['device-id'])
|
235
|
+
}
|
236
|
+
if (cookies['device-id'] || cookies['session-id']) {
|
237
|
+
const options = { path: '/oauth/authorize', maxAge: 0 } as const
|
238
|
+
setCookie(res, 'device-id', '', options)
|
239
|
+
setCookie(res, 'session-id', '', options)
|
240
|
+
}
|
229
241
|
|
230
242
|
// Silently ignore invalid cookies
|
231
|
-
if (!
|
243
|
+
if (!deviceId || !sessionId) {
|
232
244
|
// If the device cookie is valid, let's cleanup the DB
|
233
|
-
if (
|
245
|
+
if (deviceId) await this.store.deleteDevice(deviceId)
|
234
246
|
|
235
247
|
return null
|
236
248
|
}
|
237
249
|
|
238
250
|
return {
|
239
|
-
value:
|
251
|
+
value: { deviceId, sessionId },
|
240
252
|
mustRotate: device.mustRotate || session.mustRotate,
|
241
253
|
}
|
242
254
|
}
|
@@ -246,16 +258,21 @@ export class DeviceManager {
|
|
246
258
|
name: string,
|
247
259
|
schema: z.ZodType<T> | z.ZodEffects<z.ZodTypeAny, T, string>,
|
248
260
|
): null | { value: T; mustRotate: boolean } {
|
249
|
-
const
|
261
|
+
const rawValue = Object.hasOwn(cookies, name) ? cookies[name] : null
|
262
|
+
if (!rawValue) return null
|
263
|
+
|
264
|
+
const result = schema.safeParse(rawValue, { path: ['cookie', name] })
|
250
265
|
if (!result.success) return null
|
251
266
|
|
252
267
|
const value = result.data
|
253
268
|
|
254
269
|
if (this.options.cookie.keys) {
|
255
|
-
const
|
270
|
+
const hashName = `${name}:hash`
|
271
|
+
|
272
|
+
const hash = Object.hasOwn(cookies, hashName) ? cookies[hashName] : null
|
256
273
|
if (!hash) return null
|
257
274
|
|
258
|
-
const idx = this.options.cookie.keys.index(
|
275
|
+
const idx = this.options.cookie.keys.index(rawValue, hash)
|
259
276
|
if (idx < 0) return null
|
260
277
|
|
261
278
|
return { value, mustRotate: idx !== 0 }
|
@@ -264,9 +281,13 @@ export class DeviceManager {
|
|
264
281
|
return { value, mustRotate: false }
|
265
282
|
}
|
266
283
|
|
267
|
-
private
|
268
|
-
|
269
|
-
|
284
|
+
private async setCookies(
|
285
|
+
req: IncomingMessage,
|
286
|
+
res: ServerResponse,
|
287
|
+
{ deviceId, sessionId }: CookieValue,
|
288
|
+
) {
|
289
|
+
this.writeCookie(res, `dev-id`, deviceId)
|
290
|
+
this.writeCookie(res, `ses-id`, sessionId)
|
270
291
|
}
|
271
292
|
|
272
293
|
private writeCookie(res: ServerResponse, name: string, value?: string) {
|
@@ -277,27 +298,16 @@ export class DeviceManager {
|
|
277
298
|
: this.options.cookie.age / 1000
|
278
299
|
: 0,
|
279
300
|
httpOnly: true,
|
280
|
-
path:
|
301
|
+
path: '/',
|
281
302
|
secure: this.options.cookie.secure !== false,
|
282
|
-
sameSite: this.options.cookie.sameSite
|
303
|
+
sameSite: this.options.cookie.sameSite,
|
283
304
|
} as const
|
284
305
|
|
285
|
-
|
286
|
-
res,
|
287
|
-
'Set-Cookie',
|
288
|
-
serializeCookie(name, value || '', cookieOptions),
|
289
|
-
)
|
306
|
+
setCookie(res, name, value || '', cookieOptions)
|
290
307
|
|
291
308
|
if (this.options.cookie.keys) {
|
292
|
-
|
293
|
-
|
294
|
-
'Set-Cookie',
|
295
|
-
serializeCookie(
|
296
|
-
`${name}:hash`,
|
297
|
-
value ? this.options.cookie.keys.sign(value) : '',
|
298
|
-
cookieOptions,
|
299
|
-
),
|
300
|
-
)
|
309
|
+
const hash = value ? this.options.cookie.keys.sign(value) : ''
|
310
|
+
setCookie(res, `${name}:hash`, hash, cookieOptions)
|
301
311
|
}
|
302
312
|
}
|
303
313
|
|
@@ -7,6 +7,8 @@ export * from './device-data.js'
|
|
7
7
|
export * from './device-id.js'
|
8
8
|
export * from './session-id.js'
|
9
9
|
|
10
|
+
export type { Awaitable }
|
11
|
+
|
10
12
|
export interface DeviceStore {
|
11
13
|
createDevice(deviceId: DeviceId, data: DeviceData): Awaitable<void>
|
12
14
|
readDevice(deviceId: DeviceId): Awaitable<DeviceData | null>
|
@@ -1,12 +1,27 @@
|
|
1
|
-
import {
|
2
|
-
|
1
|
+
import {
|
2
|
+
OAuthAuthenticationErrorResponse,
|
3
|
+
OAuthAuthorizationRequestParameters,
|
4
|
+
OidcAuthenticationErrorResponse,
|
5
|
+
} from '@atproto/oauth-types'
|
6
|
+
import { buildErrorPayload } from './error-parser.js'
|
3
7
|
import { OAuthError } from './oauth-error.js'
|
4
8
|
|
9
|
+
export type AuthenticationErrorResponse =
|
10
|
+
| OAuthAuthenticationErrorResponse
|
11
|
+
// OIDC authentication error response are not part of the ATproto flavoured
|
12
|
+
// OAuth but we allow them because they provide better feedback to the client
|
13
|
+
// (in particular when SSO is used).
|
14
|
+
| OidcAuthenticationErrorResponse
|
15
|
+
// This error is defined by rfc9396 (not part of the OAuth 2.1 or OIDC). But
|
16
|
+
// since, in ATproto flavoured OAuth, client registration is a dynamic part of
|
17
|
+
// the authorization process, we allow it.
|
18
|
+
| 'invalid_authorization_details'
|
19
|
+
|
5
20
|
export class AccessDeniedError extends OAuthError {
|
6
21
|
constructor(
|
7
22
|
public readonly parameters: OAuthAuthorizationRequestParameters,
|
8
23
|
error_description: string,
|
9
|
-
error = 'access_denied',
|
24
|
+
error: AuthenticationErrorResponse = 'access_denied',
|
10
25
|
cause?: unknown,
|
11
26
|
) {
|
12
27
|
super(error, error_description, 400, cause)
|
@@ -14,19 +29,11 @@ export class AccessDeniedError extends OAuthError {
|
|
14
29
|
|
15
30
|
static from(
|
16
31
|
parameters: OAuthAuthorizationRequestParameters,
|
17
|
-
cause
|
18
|
-
|
19
|
-
) {
|
20
|
-
if (cause
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
const { error, error_description } = buildErrorPayload(cause)
|
25
|
-
return new AccessDeniedError(
|
26
|
-
parameters,
|
27
|
-
error_description,
|
28
|
-
fallbackError ?? error,
|
29
|
-
cause,
|
30
|
-
)
|
32
|
+
cause: unknown,
|
33
|
+
error: AuthenticationErrorResponse,
|
34
|
+
): AccessDeniedError {
|
35
|
+
if (cause instanceof AccessDeniedError) return cause
|
36
|
+
const { error_description } = buildErrorPayload(cause)
|
37
|
+
return new AccessDeniedError(parameters, error_description, error, cause)
|
31
38
|
}
|
32
39
|
}
|
@@ -13,4 +13,9 @@ export class InvalidGrantError extends OAuthError {
|
|
13
13
|
constructor(error_description: string, cause?: unknown) {
|
14
14
|
super('invalid_grant', error_description, 400, cause)
|
15
15
|
}
|
16
|
+
|
17
|
+
static from(err: unknown, error_description: string): InvalidGrantError {
|
18
|
+
if (err instanceof InvalidGrantError) return err
|
19
|
+
return new InvalidGrantError(error_description, err)
|
20
|
+
}
|
16
21
|
}
|
@@ -9,4 +9,14 @@ export class LoginRequiredError extends AccessDeniedError {
|
|
9
9
|
) {
|
10
10
|
super(parameters, error_description, 'login_required', cause)
|
11
11
|
}
|
12
|
+
|
13
|
+
static from(
|
14
|
+
parameters: OAuthAuthorizationRequestParameters,
|
15
|
+
cause?: unknown,
|
16
|
+
fallbackError?: string,
|
17
|
+
): LoginRequiredError {
|
18
|
+
if (cause instanceof LoginRequiredError) return cause
|
19
|
+
|
20
|
+
return new LoginRequiredError(parameters, fallbackError, cause)
|
21
|
+
}
|
12
22
|
}
|
package/src/index.ts
CHANGED
@@ -10,6 +10,7 @@ export * from './oauth-client.js'
|
|
10
10
|
export * from './oauth-dpop.js'
|
11
11
|
export * from './oauth-errors.js'
|
12
12
|
export * from './oauth-hooks.js'
|
13
|
+
export * from './oauth-middleware.js'
|
13
14
|
export * from './oauth-provider.js'
|
14
15
|
export * from './oauth-store.js'
|
15
16
|
export * from './oauth-verifier.js'
|
@@ -61,8 +61,8 @@ export type BuildDocumentOptions = {
|
|
61
61
|
preloads?: readonly AssetRef[]
|
62
62
|
head?: HtmlValue
|
63
63
|
title?: HtmlValue
|
64
|
-
scripts?: readonly (Html | AssetRef)[]
|
65
|
-
styles?: readonly (Html | AssetRef)[]
|
64
|
+
scripts?: readonly (Html | AssetRef | undefined)[]
|
65
|
+
styles?: readonly (Html | AssetRef | undefined)[]
|
66
66
|
body?: HtmlValue
|
67
67
|
bodyAttrs?: Attrs
|
68
68
|
}
|
@@ -134,14 +134,16 @@ function linkPreload(asset: AssetRef) {
|
|
134
134
|
return undefined
|
135
135
|
}
|
136
136
|
|
137
|
-
function scriptToHtml(script
|
137
|
+
function scriptToHtml(script?: Html | AssetRef): Html | undefined {
|
138
|
+
if (script == null) return undefined
|
138
139
|
return script instanceof Html
|
139
140
|
? // prettier-ignore
|
140
141
|
html`<script>${script}</script>` // hash validity requires no space around the content
|
141
142
|
: html`<script type="module" src="${script.url}"></script>`
|
142
143
|
}
|
143
144
|
|
144
|
-
function styleToHtml(style
|
145
|
+
function styleToHtml(style?: Html | AssetRef): Html | undefined {
|
146
|
+
if (style == null) return undefined
|
145
147
|
return style instanceof Html
|
146
148
|
? // prettier-ignore
|
147
149
|
html`<style>${style}</style>` // hash validity requires no space around the content
|
@@ -1,14 +1,16 @@
|
|
1
|
-
import { Html, js } from '
|
1
|
+
import { Html, js } from './index.js'
|
2
2
|
|
3
|
-
export function
|
4
|
-
|
3
|
+
export function declareHydrationData<T extends Record<string, unknown>>(
|
4
|
+
values: T,
|
5
|
+
): Html {
|
6
|
+
return Html.dangerouslyCreate(hydrationDataGenerator(values))
|
5
7
|
}
|
6
8
|
|
7
|
-
export function*
|
9
|
+
export function* hydrationDataGenerator(
|
8
10
|
values: Record<string, unknown>,
|
9
11
|
): Generator<Html> {
|
10
12
|
for (const [key, val] of Object.entries(values)) {
|
11
|
-
yield js`window[${key}]
|
13
|
+
yield js`window[${key}]=JSON.parse(${JSON.stringify(val)});`
|
12
14
|
}
|
13
15
|
// The script tag is removed after the data is assigned to the global
|
14
16
|
// variables to prevent other scripts from reading the values. The "app"
|
package/src/lib/html/tags.ts
CHANGED
@@ -54,5 +54,5 @@ export const jsonCode = (value: unknown) =>
|
|
54
54
|
/**
|
55
55
|
* Escapes a value to be uses as CSS styles inside a `<style>` tag.
|
56
56
|
*/
|
57
|
-
export const cssCode = (code
|
58
|
-
Html.dangerouslyCreate(cssEscaper(code))
|
57
|
+
export const cssCode = (code?: string) =>
|
58
|
+
code ? Html.dangerouslyCreate(cssEscaper(code)) : undefined
|
package/src/lib/http/accept.ts
CHANGED
@@ -4,7 +4,7 @@ import { SubCtx, subCtx } from './context.js'
|
|
4
4
|
import { Middleware, NextFunction } from './types.js'
|
5
5
|
|
6
6
|
type View<
|
7
|
-
T,
|
7
|
+
T extends object | void,
|
8
8
|
D,
|
9
9
|
Req extends IncomingMessage = IncomingMessage,
|
10
10
|
Res extends ServerResponse = ServerResponse,
|
@@ -38,7 +38,7 @@ type View<
|
|
38
38
|
*/
|
39
39
|
export function acceptMiddleware<
|
40
40
|
D,
|
41
|
-
T = void,
|
41
|
+
T extends object | void = void,
|
42
42
|
Req extends IncomingMessage = IncomingMessage,
|
43
43
|
Res extends ServerResponse = ServerResponse,
|
44
44
|
>(
|
@@ -71,7 +71,7 @@ export function acceptMiddleware<
|
|
71
71
|
|
72
72
|
if (view) {
|
73
73
|
const data = await controller.call(this, req, res)
|
74
|
-
const ctx = subCtx(this,
|
74
|
+
const ctx = subCtx(this, { data })
|
75
75
|
if (type) res.setHeader('Content-Type', type)
|
76
76
|
|
77
77
|
await view.call(ctx, req, res, next)
|
package/src/lib/http/context.ts
CHANGED
@@ -1,11 +1,42 @@
|
|
1
|
-
export type SubCtx<Parent, Child> = Child &
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
): SubCtx<
|
8
|
-
|
9
|
-
|
10
|
-
|
1
|
+
export type SubCtx<Parent extends object | void, Child extends object> = Child &
|
2
|
+
Omit<Parent, keyof Child>
|
3
|
+
|
4
|
+
export function subCtx<Parent extends object | void, Child extends object>(
|
5
|
+
parent: Parent,
|
6
|
+
child: Child,
|
7
|
+
): SubCtx<Parent, Child> {
|
8
|
+
const proto = typeof parent === 'object' ? parent : null
|
9
|
+
const entries = Object.entries(child)
|
10
|
+
|
11
|
+
// Optimization for small objects
|
12
|
+
switch (entries.length) {
|
13
|
+
case 0:
|
14
|
+
return Object.create(proto)
|
15
|
+
case 1: {
|
16
|
+
const e0 = entries[0]
|
17
|
+
return Object.create(proto, {
|
18
|
+
[e0[0]]: valueDescriptor(e0[1]),
|
19
|
+
})
|
20
|
+
}
|
21
|
+
case 2: {
|
22
|
+
const e0 = entries[0]
|
23
|
+
const e1 = entries[1]
|
24
|
+
return Object.create(proto, {
|
25
|
+
[e0[0]]: valueDescriptor(e0[1]),
|
26
|
+
[e1[0]]: valueDescriptor(e1[1]),
|
27
|
+
})
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
return Object.create(proto, Object.fromEntries(entries.map(entryToEntryDesc)))
|
32
|
+
}
|
33
|
+
|
34
|
+
function entryToEntryDesc(
|
35
|
+
entry: [string, unknown],
|
36
|
+
): [string, PropertyDescriptor] {
|
37
|
+
return [entry[0], valueDescriptor(entry[1])]
|
38
|
+
}
|
39
|
+
|
40
|
+
function valueDescriptor(value: unknown): PropertyDescriptor {
|
41
|
+
return { value, enumerable: true, writable: false }
|
11
42
|
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import type { ServerResponse } from 'node:http'
|
2
|
+
|
3
|
+
export function appendHeader(
|
4
|
+
res: ServerResponse,
|
5
|
+
header: string,
|
6
|
+
value: string | readonly string[],
|
7
|
+
): void {
|
8
|
+
const existing = res.getHeader(header)
|
9
|
+
if (existing == null) {
|
10
|
+
res.setHeader(header, value)
|
11
|
+
} else {
|
12
|
+
const arr = Array.isArray(existing) ? existing : [String(existing)]
|
13
|
+
res.setHeader(header, arr.concat(value))
|
14
|
+
}
|
15
|
+
}
|
package/src/lib/http/index.ts
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import type { IncomingMessage, ServerResponse } from 'node:http'
|
2
|
+
import { invokeOnce } from '../util/function.js'
|
2
3
|
import { writeJson } from './response.js'
|
3
4
|
import { Handler, Middleware, NextFunction } from './types.js'
|
4
5
|
|
@@ -33,13 +34,8 @@ export function combineMiddlewares(
|
|
33
34
|
next()
|
34
35
|
} else {
|
35
36
|
const currentMiddleware = middlewaresArray[i++]!
|
36
|
-
const currentNext =
|
37
|
-
|
38
|
-
const result = currentMiddleware.call(this, req, res, currentNext)
|
39
|
-
Promise.resolve(result).catch(currentNext)
|
40
|
-
} catch (err) {
|
41
|
-
currentNext(err)
|
42
|
-
}
|
37
|
+
const currentNext = invokeOnce(nextMiddleware)
|
38
|
+
currentMiddleware.call(this, req, res, currentNext)
|
43
39
|
}
|
44
40
|
}
|
45
41
|
nextMiddleware()
|
@@ -63,12 +59,14 @@ export function asHandler<M extends Middleware<any, any, any>>(
|
|
63
59
|
this,
|
64
60
|
req,
|
65
61
|
res,
|
66
|
-
next =
|
62
|
+
next = invokeOnce(createFinalHandler(req, res, options)),
|
67
63
|
) {
|
68
64
|
return middleware.call(this, req, res, next)
|
69
65
|
} as AsHandler<M>
|
70
66
|
}
|
71
67
|
|
68
|
+
export const DEV_MODE = process.env['NODE_ENV'] === 'development'
|
69
|
+
|
72
70
|
export type FinalHandlerOptions = {
|
73
71
|
debug?: boolean
|
74
72
|
}
|
@@ -79,7 +77,7 @@ export function createFinalHandler(
|
|
79
77
|
options?: FinalHandlerOptions,
|
80
78
|
): NextFunction {
|
81
79
|
return (err) => {
|
82
|
-
if (err && (options?.debug ??
|
80
|
+
if (err != null && (options?.debug ?? DEV_MODE)) {
|
83
81
|
console.error(err)
|
84
82
|
}
|
85
83
|
|
@@ -129,10 +127,7 @@ function buildFallbackPayload(
|
|
129
127
|
'Unknown error'
|
130
128
|
: 'System error'
|
131
129
|
: `Cannot ${req.method} ${req.url}`,
|
132
|
-
stack:
|
133
|
-
err instanceof Error && process.env['NODE_ENV'] === 'development'
|
134
|
-
? err.stack
|
135
|
-
: undefined,
|
130
|
+
stack: DEV_MODE && err instanceof Error ? err.stack : undefined,
|
136
131
|
}
|
137
132
|
}
|
138
133
|
|
@@ -142,16 +137,6 @@ function getErrorStatusCode(err: NonNullable<unknown>): number {
|
|
142
137
|
return status != null && status >= 400 && status < 600 ? status : 500
|
143
138
|
}
|
144
139
|
|
145
|
-
export function once<T extends NextFunction>(next: T): T {
|
146
|
-
let nextNullable: T | null = next
|
147
|
-
return function (err) {
|
148
|
-
if (!nextNullable) throw new Error('next() called multiple times')
|
149
|
-
const next = nextNullable
|
150
|
-
nextNullable = null
|
151
|
-
return next(err)
|
152
|
-
} as T
|
153
|
-
}
|
154
|
-
|
155
140
|
// eslint-disable-next-line
|
156
141
|
function getProp(obj: unknown, key: string, t: 'function'): Function | undefined
|
157
142
|
function getProp(obj: unknown, key: string, t: 'string'): string | undefined
|