@atproto/oauth-provider 0.6.6 → 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 +39 -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 +10 -7
- 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
package/src/lib/http/request.ts
CHANGED
@@ -1,10 +1,13 @@
|
|
1
|
-
import { randomBytes } from 'node:crypto'
|
2
1
|
import type { IncomingMessage, ServerResponse } from 'node:http'
|
3
2
|
import { languages, mediaType } from '@hapi/accept'
|
4
|
-
import {
|
3
|
+
import {
|
4
|
+
CookieSerializeOptions,
|
5
|
+
parse as parseCookie,
|
6
|
+
serialize as serializeCookie,
|
7
|
+
} from 'cookie'
|
5
8
|
import forwarded from 'forwarded'
|
6
9
|
import createHttpError from 'http-errors'
|
7
|
-
import { appendHeader } from './
|
10
|
+
import { appendHeader } from './headers.js'
|
8
11
|
import { UrlReference, urlMatch } from './url.js'
|
9
12
|
|
10
13
|
export function validateHeaderValue(
|
@@ -30,7 +33,6 @@ export function validateHeaderValue(
|
|
30
33
|
|
31
34
|
export function validateFetchMode(
|
32
35
|
req: IncomingMessage,
|
33
|
-
res: ServerResponse,
|
34
36
|
expectedMode: readonly (
|
35
37
|
| null
|
36
38
|
| 'navigate'
|
@@ -44,7 +46,6 @@ export function validateFetchMode(
|
|
44
46
|
|
45
47
|
export function validateFetchDest(
|
46
48
|
req: IncomingMessage,
|
47
|
-
res: ServerResponse,
|
48
49
|
expectedDest: readonly (
|
49
50
|
| null
|
50
51
|
| 'document'
|
@@ -68,7 +69,6 @@ export function validateFetchDest(
|
|
68
69
|
|
69
70
|
export function validateFetchSite(
|
70
71
|
req: IncomingMessage,
|
71
|
-
res: ServerResponse,
|
72
72
|
expectedSite: readonly (
|
73
73
|
| null
|
74
74
|
| 'same-origin'
|
@@ -80,103 +80,68 @@ export function validateFetchSite(
|
|
80
80
|
validateHeaderValue(req, 'sec-fetch-site', expectedSite)
|
81
81
|
}
|
82
82
|
|
83
|
-
export function
|
83
|
+
export function validateReferrer(
|
84
84
|
req: IncomingMessage,
|
85
|
-
res: ServerResponse,
|
86
85
|
reference: UrlReference,
|
87
86
|
allowNull: true,
|
88
87
|
): URL | null
|
89
|
-
export function
|
88
|
+
export function validateReferrer(
|
90
89
|
req: IncomingMessage,
|
91
|
-
res: ServerResponse,
|
92
90
|
reference: UrlReference,
|
93
91
|
allowNull?: false,
|
94
92
|
): URL
|
95
|
-
export function
|
93
|
+
export function validateReferrer(
|
96
94
|
req: IncomingMessage,
|
97
|
-
res: ServerResponse,
|
98
95
|
reference: UrlReference,
|
99
96
|
allowNull = false,
|
100
97
|
) {
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
98
|
+
// @NOTE The header name "referer" is actually a misspelling of the word
|
99
|
+
// "referrer". https://en.wikipedia.org/wiki/HTTP_referer
|
100
|
+
const referrer = req.headers['referer']
|
101
|
+
const referrerUrl = referrer ? new URL(referrer) : null
|
102
|
+
if (referrerUrl ? !urlMatch(referrerUrl, reference) : !allowNull) {
|
103
|
+
throw createHttpError(400, `Invalid referrer ${referrer}`)
|
105
104
|
}
|
106
|
-
return
|
105
|
+
return referrerUrl
|
107
106
|
}
|
108
107
|
|
109
|
-
export
|
108
|
+
export function validateOrigin(
|
110
109
|
req: IncomingMessage,
|
111
|
-
|
112
|
-
|
113
|
-
) {
|
114
|
-
const csrfToken = randomBytes(8).toString('hex')
|
115
|
-
appendHeader(
|
116
|
-
res,
|
117
|
-
'Set-Cookie',
|
118
|
-
serializeCookie(cookieName, csrfToken, {
|
119
|
-
secure: true,
|
120
|
-
httpOnly: false,
|
121
|
-
sameSite: 'lax',
|
122
|
-
path: req.url?.split('?', 1)[0] || '/',
|
123
|
-
}),
|
124
|
-
)
|
125
|
-
}
|
126
|
-
|
127
|
-
// CORS ensure not cross origin
|
128
|
-
export function validateSameOrigin(
|
129
|
-
req: IncomingMessage,
|
130
|
-
res: ServerResponse,
|
131
|
-
origin: string,
|
132
|
-
allowNull = true,
|
110
|
+
expectedOrigin: string,
|
111
|
+
optional = true,
|
133
112
|
) {
|
134
113
|
const reqOrigin = req.headers['origin']
|
135
|
-
if (reqOrigin ? reqOrigin !==
|
114
|
+
if (reqOrigin ? reqOrigin !== expectedOrigin : !optional) {
|
136
115
|
throw createHttpError(400, `Invalid origin ${reqOrigin}`)
|
137
116
|
}
|
138
117
|
}
|
139
118
|
|
140
|
-
export
|
141
|
-
|
119
|
+
export type { CookieSerializeOptions }
|
120
|
+
|
121
|
+
export function setCookie(
|
142
122
|
res: ServerResponse,
|
143
|
-
|
144
|
-
|
145
|
-
|
123
|
+
cookieName: string,
|
124
|
+
value: string,
|
125
|
+
options?: CookieSerializeOptions,
|
146
126
|
) {
|
147
|
-
|
148
|
-
|
149
|
-
typeof csrfToken !== 'string' ||
|
150
|
-
!csrfToken ||
|
151
|
-
!cookies ||
|
152
|
-
!cookieName ||
|
153
|
-
cookies[cookieName] !== csrfToken
|
154
|
-
) {
|
155
|
-
throw createHttpError(400, `Invalid CSRF token`)
|
156
|
-
}
|
127
|
+
appendHeader(res, 'Set-Cookie', serializeCookie(cookieName, value, options))
|
128
|
+
}
|
157
129
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
httpOnly: false,
|
165
|
-
sameSite: 'lax',
|
166
|
-
maxAge: 0,
|
167
|
-
}),
|
168
|
-
)
|
169
|
-
}
|
130
|
+
export function clearCookie(
|
131
|
+
res: ServerResponse,
|
132
|
+
cookieName: string,
|
133
|
+
options?: Omit<CookieSerializeOptions, 'maxAge' | 'expires'>,
|
134
|
+
) {
|
135
|
+
setCookie(res, cookieName, '', { ...options, maxAge: 0 })
|
170
136
|
}
|
171
137
|
|
172
138
|
export function parseHttpCookies(
|
173
|
-
req: IncomingMessage,
|
174
|
-
):
|
175
|
-
|
176
|
-
? (req.
|
177
|
-
:
|
178
|
-
|
179
|
-
: null
|
139
|
+
req: IncomingMessage & { cookies?: any },
|
140
|
+
): Record<string, undefined | string> {
|
141
|
+
req.cookies ??= req.headers['cookie']
|
142
|
+
? parseCookie(req.headers['cookie'])
|
143
|
+
: Object.create(null)
|
144
|
+
return req.cookies
|
180
145
|
}
|
181
146
|
|
182
147
|
export type ExtractRequestMetadataOptions = {
|
package/src/lib/http/response.ts
CHANGED
@@ -1,25 +1,14 @@
|
|
1
|
-
import type { ServerResponse } from 'node:http'
|
1
|
+
import type { IncomingMessage, ServerResponse } from 'node:http'
|
2
2
|
import { type Readable, pipeline } from 'node:stream'
|
3
|
+
import createHttpError from 'http-errors'
|
4
|
+
import { Awaitable } from '../util/type.js'
|
5
|
+
import { negotiateResponseContent } from './request.js'
|
3
6
|
import {
|
4
7
|
SecurityHeadersOptions,
|
5
8
|
setSecurityHeaders,
|
6
9
|
} from './security-headers.js'
|
7
10
|
import type { Handler, Middleware } from './types.js'
|
8
11
|
|
9
|
-
export function appendHeader(
|
10
|
-
res: ServerResponse,
|
11
|
-
header: string,
|
12
|
-
value: string | readonly string[],
|
13
|
-
): void {
|
14
|
-
const existing = res.getHeader(header)
|
15
|
-
if (existing == null) {
|
16
|
-
res.setHeader(header, value)
|
17
|
-
} else {
|
18
|
-
const arr = Array.isArray(existing) ? existing : [String(existing)]
|
19
|
-
res.setHeader(header, arr.concat(value))
|
20
|
-
}
|
21
|
-
}
|
22
|
-
|
23
12
|
export function writeRedirect(
|
24
13
|
res: ServerResponse,
|
25
14
|
url: string,
|
@@ -111,3 +100,38 @@ export function cacheControlMiddleware(maxAge: number): Middleware<void> {
|
|
111
100
|
next()
|
112
101
|
}
|
113
102
|
}
|
103
|
+
|
104
|
+
export function jsonHandler<
|
105
|
+
T,
|
106
|
+
Req extends IncomingMessage = IncomingMessage,
|
107
|
+
Res extends ServerResponse = ServerResponse,
|
108
|
+
>(
|
109
|
+
buildJson: (
|
110
|
+
this: T,
|
111
|
+
req: Req,
|
112
|
+
res: Res,
|
113
|
+
) => Awaitable<{ payload: unknown; status?: number }>,
|
114
|
+
): Middleware<T, Req, Res> {
|
115
|
+
return function (req, res, next) {
|
116
|
+
// Ensure we can agree on a content encoding & type before starting to
|
117
|
+
// build the JSON response.
|
118
|
+
if (negotiateResponseContent(req, ['application/json'])) {
|
119
|
+
// A middleware should not be async, so we wrap the async operation in a
|
120
|
+
// promise and return it.
|
121
|
+
void (async () => {
|
122
|
+
try {
|
123
|
+
const { payload, status = 200 } = await buildJson.call(this, req, res)
|
124
|
+
writeJson(res, payload, { status })
|
125
|
+
} catch (cause) {
|
126
|
+
const error =
|
127
|
+
cause instanceof Error
|
128
|
+
? cause
|
129
|
+
: new Error('Failed to build JSON response', { cause })
|
130
|
+
next(error satisfies Error)
|
131
|
+
}
|
132
|
+
})()
|
133
|
+
} else {
|
134
|
+
next(createHttpError(406, 'Unsupported media type'))
|
135
|
+
}
|
136
|
+
}
|
137
|
+
}
|
package/src/lib/http/route.ts
CHANGED
@@ -5,9 +5,12 @@ import { combineMiddlewares } from './middleware.js'
|
|
5
5
|
import { Params, Path, createPathMatcher } from './path.js'
|
6
6
|
import { Middleware } from './types.js'
|
7
7
|
|
8
|
-
export type RouteCtx<
|
8
|
+
export type RouteCtx<
|
9
|
+
T extends object | void,
|
10
|
+
P extends Params = Params,
|
11
|
+
> = SubCtx<T, { params: Readonly<P> }>
|
9
12
|
export type RouteMiddleware<
|
10
|
-
T,
|
13
|
+
T extends object | void,
|
11
14
|
P extends Params,
|
12
15
|
Req = IncomingMessage,
|
13
16
|
Res = ServerResponse,
|
@@ -28,8 +31,8 @@ export type RouteMiddleware<
|
|
28
31
|
* ```
|
29
32
|
*/
|
30
33
|
export function createRoute<
|
31
|
-
P extends Params,
|
32
|
-
T = void,
|
34
|
+
P extends Params = Params,
|
35
|
+
T extends object | void = void,
|
33
36
|
Req extends IncomingMessage = IncomingMessage,
|
34
37
|
Res extends ServerResponse = ServerResponse,
|
35
38
|
>(
|
@@ -47,7 +50,7 @@ export function createRoute<
|
|
47
50
|
const pathname = req.url?.split('?')[0] ?? '/'
|
48
51
|
const params = paramsMatcher(pathname)
|
49
52
|
if (params) {
|
50
|
-
const context = subCtx(this,
|
53
|
+
const context = subCtx(this, { params })
|
51
54
|
return middleware.call(context, req, res, next)
|
52
55
|
}
|
53
56
|
}
|
package/src/lib/http/router.ts
CHANGED
@@ -1,33 +1,37 @@
|
|
1
1
|
import type { IncomingMessage, ServerResponse } from 'node:http'
|
2
2
|
import { SubCtx, subCtx } from './context.js'
|
3
3
|
import { MethodMatcherInput } from './method.js'
|
4
|
-
import {
|
4
|
+
import { combineMiddlewares } from './middleware.js'
|
5
5
|
import { Params, Path } from './path.js'
|
6
6
|
import { RouteMiddleware, createRoute } from './route.js'
|
7
7
|
import { Middleware } from './types.js'
|
8
8
|
|
9
|
-
export type RouterCtx<T
|
9
|
+
export type RouterCtx<T extends object | void = void> = SubCtx<
|
10
|
+
T,
|
11
|
+
{ url: Readonly<URL> }
|
12
|
+
>
|
13
|
+
|
10
14
|
export type RouterMiddleware<
|
11
|
-
T = void,
|
15
|
+
T extends object | void = void,
|
12
16
|
Req = IncomingMessage,
|
13
17
|
Res = ServerResponse,
|
14
18
|
> = Middleware<RouterCtx<T>, Req, Res>
|
15
19
|
|
20
|
+
export type RouterConfig = {
|
21
|
+
/** Used to build the origin of the {@link RouterCtx['url']} context property */
|
22
|
+
protocol?: string
|
23
|
+
/** Used to build the origin of the {@link RouterCtx['url']} context property */
|
24
|
+
host?: string
|
25
|
+
}
|
26
|
+
|
16
27
|
export class Router<
|
17
|
-
T = void,
|
28
|
+
T extends object | void = void,
|
18
29
|
Req extends IncomingMessage = IncomingMessage,
|
19
30
|
Res extends ServerResponse = ServerResponse,
|
20
31
|
> {
|
21
32
|
private readonly middlewares: RouterMiddleware<T, Req, Res>[] = []
|
22
33
|
|
23
|
-
constructor(
|
24
|
-
private readonly url?: {
|
25
|
-
/** Used to build the origin of the {@link RouterCtx['url']} context property */
|
26
|
-
protocol?: string
|
27
|
-
/** Used to build the origin of the {@link RouterCtx['url']} context property */
|
28
|
-
host?: string
|
29
|
-
},
|
30
|
-
) {}
|
34
|
+
constructor(private readonly config?: RouterConfig) {}
|
31
35
|
|
32
36
|
use(...middlewares: RouterMiddleware<T, Req, Res>[]) {
|
33
37
|
this.middlewares.push(...middlewares)
|
@@ -73,8 +77,8 @@ export class Router<
|
|
73
77
|
/**
|
74
78
|
* @returns router middleware which dispatches a route matching the request.
|
75
79
|
*/
|
76
|
-
|
77
|
-
const
|
80
|
+
buildMiddleware(): Middleware<T, Req, Res> {
|
81
|
+
const { config } = this
|
78
82
|
|
79
83
|
// Calling next('router') from a middleware will skip all the remaining
|
80
84
|
// middlewares in the stack.
|
@@ -82,38 +86,28 @@ export class Router<
|
|
82
86
|
skipKeyword: 'router',
|
83
87
|
})
|
84
88
|
|
85
|
-
return
|
86
|
-
//
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
this != null &&
|
94
|
-
typeof this === 'object' &&
|
95
|
-
'url' in this &&
|
96
|
-
this.url instanceof URL
|
97
|
-
) {
|
98
|
-
// If the context already contains a "url" (router inside router), let's
|
99
|
-
// use it.
|
100
|
-
url = this.url
|
101
|
-
} else {
|
102
|
-
// Parse the URL using node's URL parser.
|
103
|
-
try {
|
104
|
-
const protocol = routerUrl?.protocol || 'https:'
|
105
|
-
const host = req.headers.host || routerUrl?.host || 'localhost'
|
106
|
-
const pathname = req.url || '/'
|
107
|
-
url = new URL(pathname, `${protocol}//${host}`)
|
108
|
-
} catch (cause) {
|
109
|
-
const error =
|
110
|
-
cause instanceof Error ? cause : new Error('Invalid URL', { cause })
|
111
|
-
return next(Object.assign(error, { status: 400, statusCode: 400 }))
|
112
|
-
}
|
113
|
-
}
|
114
|
-
|
115
|
-
const context = subCtx(this, 'url', url)
|
89
|
+
return function (this, req, res, next) {
|
90
|
+
// Parse the URL using node's URL parser.
|
91
|
+
const url = extractUrl(req, config)
|
92
|
+
if (url instanceof Error) return next(url)
|
93
|
+
|
94
|
+
// Any error thrown here will be uncaught/unhandled (a middleware should
|
95
|
+
// never throw)
|
96
|
+
const context = subCtx(this, { url })
|
116
97
|
middleware.call(context, req, res, next)
|
117
|
-
}
|
98
|
+
}
|
99
|
+
}
|
100
|
+
}
|
101
|
+
|
102
|
+
function extractUrl(req: IncomingMessage, config?: RouterConfig): URL | Error {
|
103
|
+
try {
|
104
|
+
const protocol = config?.protocol || 'https:'
|
105
|
+
const host = config?.host || req.headers.host || 'localhost'
|
106
|
+
const pathname = req.url || '/'
|
107
|
+
return new URL(pathname, `${protocol}//${host}`)
|
108
|
+
} catch (cause) {
|
109
|
+
const error =
|
110
|
+
cause instanceof Error ? cause : new Error('Invalid URL', { cause })
|
111
|
+
return Object.assign(error, { status: 400, statusCode: 400 })
|
118
112
|
}
|
119
113
|
}
|
@@ -75,7 +75,7 @@ export function setSecurityHeaders(
|
|
75
75
|
res.setHeader('Strict-Transport-Security', buildHstsValue(hsts))
|
76
76
|
}
|
77
77
|
|
78
|
-
// @TODO
|
78
|
+
// @TODO make these headers configurable (?)
|
79
79
|
res.setHeader('Permissions-Policy', 'otp-credentials=*, document-domain=()')
|
80
80
|
res.setHeader('Referrer-Policy', 'same-origin')
|
81
81
|
res.setHeader('X-Frame-Options', 'DENY')
|
package/src/lib/http/types.ts
CHANGED
@@ -6,12 +6,7 @@ export type Middleware<
|
|
6
6
|
T = void,
|
7
7
|
Req = IncomingMessage,
|
8
8
|
Res = ServerResponse,
|
9
|
-
> = (
|
10
|
-
this: T,
|
11
|
-
req: Req,
|
12
|
-
res: Res,
|
13
|
-
next: NextFunction,
|
14
|
-
) => void | PromiseLike<void>
|
9
|
+
> = (this: T, req: Req, res: Res, next: NextFunction) => void
|
15
10
|
|
16
11
|
export type Handler<T = void, Req = IncomingMessage, Res = ServerResponse> = (
|
17
12
|
this: T,
|
@@ -1,13 +1,13 @@
|
|
1
1
|
import { createHash } from 'node:crypto'
|
2
2
|
import type { ServerResponse } from 'node:http'
|
3
|
-
import { CspConfig, CspValue, mergeCsp } from '
|
3
|
+
import { CspConfig, CspValue, mergeCsp } from './csp/index.js'
|
4
4
|
import {
|
5
5
|
AssetRef,
|
6
6
|
BuildDocumentOptions,
|
7
7
|
Html,
|
8
8
|
buildDocument,
|
9
|
-
} from '
|
10
|
-
import { WriteHtmlOptions, writeHtml } from '
|
9
|
+
} from './html/index.js'
|
10
|
+
import { WriteHtmlOptions, writeHtml } from './http/response.js'
|
11
11
|
|
12
12
|
export const DEFAULT_CSP: CspConfig = {
|
13
13
|
'upgrade-insecure-requests': true,
|
@@ -16,10 +16,10 @@ export const DEFAULT_CSP: CspConfig = {
|
|
16
16
|
|
17
17
|
export type SendWebPageOptions = BuildDocumentOptions & WriteHtmlOptions
|
18
18
|
|
19
|
-
export
|
19
|
+
export function sendWebPage(
|
20
20
|
res: ServerResponse,
|
21
21
|
{ csp: inputCsp, ...options }: SendWebPageOptions,
|
22
|
-
):
|
22
|
+
): void {
|
23
23
|
// @NOTE the csp string might be quite long. In that case it might be tempting
|
24
24
|
// to set it through the http-equiv <meta> in the HTML. However, some
|
25
25
|
// directives cannot be enforced by browsers when set through the meta tag
|
@@ -27,15 +27,16 @@ export async function sendWebPage(
|
|
27
27
|
// HTTP header.
|
28
28
|
const csp = mergeCsp(DEFAULT_CSP, inputCsp, {
|
29
29
|
'base-uri': options.base?.origin as undefined | `https://${string}`,
|
30
|
-
'script-src': options.scripts?.map(assetToCsp),
|
31
|
-
'style-src': options.styles?.map(assetToCsp),
|
30
|
+
'script-src': options.scripts?.map(assetToCsp).filter((v) => v != null),
|
31
|
+
'style-src': options.styles?.map(assetToCsp).filter((v) => v != null),
|
32
32
|
})
|
33
33
|
|
34
34
|
const html = buildDocument(options).toString()
|
35
|
-
|
35
|
+
writeHtml(res, html, { ...options, csp })
|
36
36
|
}
|
37
37
|
|
38
|
-
function assetToCsp(asset
|
38
|
+
function assetToCsp(asset?: Html | AssetRef): undefined | CspValue {
|
39
|
+
if (asset == null) return undefined
|
39
40
|
if (asset instanceof Html) {
|
40
41
|
// Inline assets are "allowed" by their hash
|
41
42
|
const hash = createHash('sha256')
|
@@ -0,0 +1,132 @@
|
|
1
|
+
import { parseUi8Dec, parseUi8Hex } from './ui8.js'
|
2
|
+
|
3
|
+
export type RgbColor = { r: number; g: number; b: number }
|
4
|
+
export type HslColor = { h: number; s: number; l: number }
|
5
|
+
export type RgbaColor = { r: number; g: number; b: number; a: number }
|
6
|
+
export type HslaColor = { h: number; s: number; l: number; a: number }
|
7
|
+
|
8
|
+
export function parseColor(color: string): RgbColor | RgbaColor {
|
9
|
+
if (color.startsWith('#')) {
|
10
|
+
return parseHexColor(color)
|
11
|
+
}
|
12
|
+
|
13
|
+
if (color.startsWith('rgba(')) {
|
14
|
+
return parseRgbaColor(color)
|
15
|
+
}
|
16
|
+
|
17
|
+
if (color.startsWith('rgb(')) {
|
18
|
+
return parseRgbColor(color)
|
19
|
+
}
|
20
|
+
|
21
|
+
// Should never happen (as long as the input is a validated WebColor)
|
22
|
+
throw new TypeError(`Invalid color value: ${color}`)
|
23
|
+
}
|
24
|
+
|
25
|
+
export function parseHexColor(v: string): RgbColor | RgbaColor {
|
26
|
+
// parseInt('az', 16) does not return NaN so we need to check the format
|
27
|
+
if (!/^#[0-9a-f]+$/i.test(v)) {
|
28
|
+
throw new TypeError(`Invalid hex color value: ${v}`)
|
29
|
+
}
|
30
|
+
|
31
|
+
if (v.length === 4 || v.length === 5) {
|
32
|
+
const r = parseUi8Hex(v[1].repeat(2))
|
33
|
+
const g = parseUi8Hex(v[2].repeat(2))
|
34
|
+
const b = parseUi8Hex(v[3].repeat(2))
|
35
|
+
const a = v.length > 4 ? parseUi8Hex(v[4].repeat(2)) : undefined
|
36
|
+
return a == null ? { r, g, b } : { r, g, b, a }
|
37
|
+
}
|
38
|
+
|
39
|
+
if (v.length === 7 || v.length === 9) {
|
40
|
+
const r = parseUi8Hex(v.slice(1, 3))
|
41
|
+
const g = parseUi8Hex(v.slice(3, 5))
|
42
|
+
const b = parseUi8Hex(v.slice(5, 7))
|
43
|
+
const a = v.length > 8 ? parseUi8Hex(v.slice(7, 9)) : undefined
|
44
|
+
return a == null ? { r, g, b } : { r, g, b, a }
|
45
|
+
}
|
46
|
+
|
47
|
+
throw new TypeError(`Invalid hex color value: ${v}`)
|
48
|
+
}
|
49
|
+
|
50
|
+
export function parseRgbColor(v: string): RgbColor {
|
51
|
+
const matches = v.match(/^\s*rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/)
|
52
|
+
if (!matches) throw new TypeError(`Invalid rgb color value: ${v}`)
|
53
|
+
|
54
|
+
const r = parseUi8Dec(matches[1])
|
55
|
+
const g = parseUi8Dec(matches[2])
|
56
|
+
const b = parseUi8Dec(matches[3])
|
57
|
+
return { r, g, b }
|
58
|
+
}
|
59
|
+
|
60
|
+
export function parseRgbaColor(v: string): RgbaColor {
|
61
|
+
const matches = v.match(
|
62
|
+
/^\s*rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/,
|
63
|
+
)
|
64
|
+
if (!matches) throw new TypeError(`Invalid rgba color value: ${v}`)
|
65
|
+
|
66
|
+
const r = parseUi8Dec(matches[1])
|
67
|
+
const g = parseUi8Dec(matches[2])
|
68
|
+
const b = parseUi8Dec(matches[3])
|
69
|
+
const a = parseUi8Dec(matches[4])
|
70
|
+
return { r, g, b, a }
|
71
|
+
}
|
72
|
+
|
73
|
+
/**
|
74
|
+
* Return the color that has the best contrast with the reference color.
|
75
|
+
*/
|
76
|
+
export function pickContrastColor(ref: RgbColor, a: RgbColor, b: RgbColor) {
|
77
|
+
return computeContrastRatio(ref, a) > computeContrastRatio(ref, b) ? a : b
|
78
|
+
}
|
79
|
+
|
80
|
+
/**
|
81
|
+
* @see {@link https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef}
|
82
|
+
*/
|
83
|
+
function relativeLuminance({ r, g, b }: RgbColor) {
|
84
|
+
return rgbLum(r) * 0.2126 + rgbLum(g) * 0.7152 + rgbLum(b) * 0.0722
|
85
|
+
}
|
86
|
+
|
87
|
+
function rgbLum(value) {
|
88
|
+
const rgb = value / 255
|
89
|
+
return rgb < 0.03928 ? rgb / 12.92 : Math.pow((rgb + 0.055) / 1.055, 2.4)
|
90
|
+
}
|
91
|
+
|
92
|
+
/**
|
93
|
+
* @see {@link https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef}
|
94
|
+
*/
|
95
|
+
function computeContrastRatio(a: RgbColor, b: RgbColor) {
|
96
|
+
const aLum = relativeLuminance(a)
|
97
|
+
const bLum = relativeLuminance(b)
|
98
|
+
const [lighter, darker] = aLum > bLum ? [aLum, bLum] : [bLum, aLum]
|
99
|
+
return (lighter + 0.05) / (darker + 0.05)
|
100
|
+
}
|
101
|
+
|
102
|
+
export function extractHue(input: RgbColor): number {
|
103
|
+
const r = input.r / 255
|
104
|
+
const g = input.g / 255
|
105
|
+
const b = input.b / 255
|
106
|
+
|
107
|
+
const max = Math.max(r, g, b)
|
108
|
+
const min = Math.min(r, g, b)
|
109
|
+
|
110
|
+
const chroma = max - min
|
111
|
+
|
112
|
+
switch (max) {
|
113
|
+
case min:
|
114
|
+
return 0 // Achromatic
|
115
|
+
case r: {
|
116
|
+
const segment = (g - b) / chroma
|
117
|
+
const shift = segment < 0 ? 360 / 60 : 0 / 60
|
118
|
+
return 60 * (segment + shift)
|
119
|
+
}
|
120
|
+
case g: {
|
121
|
+
const segment = (b - r) / chroma
|
122
|
+
const shift = 120 / 60
|
123
|
+
return 60 * (segment + shift)
|
124
|
+
}
|
125
|
+
// "default" needed for type safety. In practice, should be same as "case b:"
|
126
|
+
default: {
|
127
|
+
const segment = (r - g) / chroma
|
128
|
+
const shift = 240 / 60
|
129
|
+
return 60 * (segment + shift)
|
130
|
+
}
|
131
|
+
}
|
132
|
+
}
|
package/src/lib/util/crypto.ts
CHANGED
@@ -1,16 +1,21 @@
|
|
1
1
|
import { randomBytes } from 'node:crypto'
|
2
2
|
|
3
|
-
export async function
|
4
|
-
return new Promise<
|
3
|
+
export async function randomBuffer(bytesLength = 16) {
|
4
|
+
return new Promise<Buffer>((resolve, reject) => {
|
5
5
|
randomBytes(bytesLength, (err, buf) => {
|
6
6
|
if (err) return reject(err)
|
7
|
-
resolve(buf
|
7
|
+
resolve(buf)
|
8
8
|
})
|
9
9
|
})
|
10
10
|
}
|
11
11
|
|
12
|
+
export async function randomHexId(bytesLength = 16) {
|
13
|
+
const buffer = await randomBuffer(bytesLength)
|
14
|
+
return buffer.toString('hex')
|
15
|
+
}
|
16
|
+
|
12
17
|
// Basically all algorithms supported by "jose"'s jwtVerify().
|
13
|
-
// @TODO
|
18
|
+
// @TODO Is there a way to get this list from the runtime instead of hardcoding it?
|
14
19
|
export const VERIFY_ALGOS = [
|
15
20
|
'RS256',
|
16
21
|
'RS384',
|
package/src/lib/util/function.ts
CHANGED
@@ -19,3 +19,17 @@ export async function callAsync<F extends (...args: any[]) => unknown>(
|
|
19
19
|
): Promise<Awaited<ReturnType<F>> | undefined> {
|
20
20
|
return (await fn?.(...args)) as Awaited<ReturnType<F>> | undefined
|
21
21
|
}
|
22
|
+
|
23
|
+
export function invokeOnce<T extends (this: any, ...a: any[]) => any>(
|
24
|
+
fn: T,
|
25
|
+
): T {
|
26
|
+
let fnNullable: T | null = fn
|
27
|
+
return function (...args) {
|
28
|
+
if (fnNullable) {
|
29
|
+
const fn = fnNullable
|
30
|
+
fnNullable = null
|
31
|
+
return fn.call(this, ...args)
|
32
|
+
}
|
33
|
+
throw new Error('Function called multiple times')
|
34
|
+
} as T
|
35
|
+
}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
import { z } from 'zod'
|
2
|
+
|
3
|
+
export const localeSchema = z
|
4
|
+
.string()
|
5
|
+
.regex(/^[a-z]{2,3}(-[A-Z]{2})?$/, 'Invalid locale')
|
6
|
+
export type Locale = z.infer<typeof localeSchema>
|
7
|
+
|
8
|
+
export const multiLangStringSchema = z.intersection(
|
9
|
+
z.object({ en: z.string() }), // en is required
|
10
|
+
z.record(localeSchema, z.string().optional()),
|
11
|
+
)
|
12
|
+
export type MultiLangString = z.infer<typeof multiLangStringSchema>
|
13
|
+
|
14
|
+
export const localizedStringSchema = z.union([
|
15
|
+
z.string(),
|
16
|
+
multiLangStringSchema,
|
17
|
+
])
|
18
|
+
export type LocalizedString = z.infer<typeof localizedStringSchema>
|