@lukoweb/apitogo 0.1.23 → 0.1.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +92 -0
- package/cli.js +13 -13
- package/client.d.ts +8 -8
- package/dist/cli/cli.js +1117 -624
- package/dist/declarations/config/config.d.ts +4 -0
- package/dist/declarations/config/loader.d.ts +2 -0
- package/dist/declarations/config/resolve-modules.d.ts +34 -0
- package/dist/declarations/config/validators/InputNavigationSchema.d.ts +7 -7
- package/dist/declarations/config/validators/ModulesSchema.d.ts +417 -0
- package/dist/declarations/config/validators/ZudokuConfig.d.ts +123 -4
- package/dist/declarations/index.d.ts +3 -1
- package/dist/declarations/lib/authentication/components/ProductionUnlockPage.d.ts +1 -0
- package/dist/declarations/lib/authentication/hook.d.ts +3 -19
- package/dist/declarations/lib/authentication/providers/dev-portal-constants.d.ts +16 -0
- package/dist/declarations/lib/authentication/providers/dev-portal-utils.d.ts +9 -0
- package/dist/declarations/lib/authentication/providers/dev-portal.d.ts +39 -0
- package/dist/declarations/lib/authentication/state.d.ts +12 -26
- package/dist/declarations/lib/components/LandingLayout.d.ts +4 -0
- package/dist/declarations/lib/components/index.d.ts +2 -0
- package/dist/declarations/lib/plugins/api-keys/index.d.ts +2 -1
- package/dist/flat-config.d.ts +209 -24
- package/docs/components/alert.mdx +130 -0
- package/docs/components/badge.mdx +70 -0
- package/docs/components/button.mdx +132 -0
- package/docs/components/callout.mdx +112 -0
- package/docs/components/card.mdx +104 -0
- package/docs/components/checkbox.mdx +72 -0
- package/docs/components/client-only.mdx +79 -0
- package/docs/components/code-tabs.mdx +179 -0
- package/docs/components/dialog.mdx +167 -0
- package/docs/components/head.mdx +200 -0
- package/docs/components/icons.mdx +27 -0
- package/docs/components/input.mdx +96 -0
- package/docs/components/label.mdx +86 -0
- package/docs/components/link.mdx +242 -0
- package/docs/components/markdown.mdx +151 -0
- package/docs/components/mermaid.mdx +81 -0
- package/docs/components/playground.mdx +87 -0
- package/docs/components/secret.mdx +79 -0
- package/docs/components/select.mdx +176 -0
- package/docs/components/shadcn.mdx +73 -0
- package/docs/components/slider.mdx +108 -0
- package/docs/components/slot.mdx +119 -0
- package/docs/components/stepper.mdx +138 -0
- package/docs/components/switch.mdx +96 -0
- package/docs/components/syntax-highlight.mdx +602 -0
- package/docs/components/textarea.mdx +78 -0
- package/docs/components/tooltip.mdx +195 -0
- package/docs/components/typography.mdx +61 -0
- package/docs/concepts/auth-provider-api-identities.md +109 -0
- package/docs/configuration/ai-assistants.md +65 -0
- package/docs/configuration/api-catalog.md +109 -0
- package/docs/configuration/api-reference.md +397 -0
- package/docs/configuration/authentication-auth0.md +174 -0
- package/docs/configuration/authentication-azure-ad.md +238 -0
- package/docs/configuration/authentication-clerk.md +110 -0
- package/docs/configuration/authentication-firebase.md +62 -0
- package/docs/configuration/authentication-pingfederate.md +136 -0
- package/docs/configuration/authentication-supabase.md +226 -0
- package/docs/configuration/authentication.md +231 -0
- package/docs/configuration/build-configuration.mdx +147 -0
- package/docs/configuration/docs.md +282 -0
- package/docs/configuration/footer.mdx +214 -0
- package/docs/configuration/llms.md +90 -0
- package/docs/configuration/make-config.mdx +90 -0
- package/docs/configuration/navigation.mdx +422 -0
- package/docs/configuration/overview.md +380 -0
- package/docs/configuration/protected-routes.md +150 -0
- package/docs/configuration/search.md +163 -0
- package/docs/configuration/sentry.mdx +44 -0
- package/docs/configuration/site.md +124 -0
- package/docs/configuration/slots.mdx +125 -0
- package/docs/configuration/vite-config.md +18 -0
- package/docs/custom-plugins.md +285 -0
- package/docs/customization/colors-theme.mdx +276 -0
- package/docs/customization/fonts.md +110 -0
- package/docs/deploy/apache-nginx.md +41 -0
- package/docs/deploy/apitogo.md +139 -0
- package/docs/deploy/cloudflare-pages.md +75 -0
- package/docs/deploy/direct-upload.md +18 -0
- package/docs/deploy/github-pages.md +50 -0
- package/docs/deploy/vercel.md +103 -0
- package/docs/deployment.md +21 -0
- package/docs/extending/events.md +124 -0
- package/docs/guides/custom-pages.md +106 -0
- package/docs/guides/environment-variables.md +99 -0
- package/docs/guides/managing-api-keys-and-identities.md +172 -0
- package/docs/guides/mermaid.mdx +70 -0
- package/docs/guides/navigation-migration.md +87 -0
- package/docs/guides/navigation-rules.mdx +203 -0
- package/docs/guides/processors.mdx +234 -0
- package/docs/guides/static-files.md +55 -0
- package/docs/guides/transforming-examples.md +156 -0
- package/docs/guides/using-multiple-apis.md +87 -0
- package/docs/markdown/admonitions.md +128 -0
- package/docs/markdown/code-blocks.md +196 -0
- package/docs/markdown/frontmatter.md +173 -0
- package/docs/markdown/mdx.md +68 -0
- package/docs/markdown/overview.md +275 -0
- package/docs/plugins.md +5 -0
- package/docs/quickstart.md +87 -0
- package/docs/writing.mdx +72 -0
- package/package.json +170 -116
- package/src/app/ZuploBuildConfig.ts +36 -36
- package/src/app/defaultTheme.css +77 -77
- package/src/app/demo-cdn.html +37 -37
- package/src/app/demo.html +21 -21
- package/src/app/demo.tsx +77 -77
- package/src/app/entry.client.tsx +118 -118
- package/src/app/entry.server.tsx +160 -160
- package/src/app/env.ts +40 -40
- package/src/app/font.geist.css +73 -73
- package/src/app/main.css +390 -390
- package/src/app/main.tsx +8 -1
- package/src/app/polyfills.ts +47 -47
- package/src/app/processRoutes.tsx +51 -25
- package/src/app/sentry.ts +24 -24
- package/src/app/standalone.html +23 -23
- package/src/app/standalone.tsx +60 -60
- package/src/app/utils/createRedirectRoutes.ts +11 -11
- package/src/config/config.ts +32 -0
- package/src/config/create-plugin.ts +71 -71
- package/src/config/file-exists.ts +6 -6
- package/src/config/loader.ts +11 -1
- package/src/config/resolve-modules.ts +260 -0
- package/src/config/validators/BuildSchema.ts +95 -95
- package/src/config/validators/HeaderNavigationSchema.ts +41 -41
- package/src/config/validators/InputNavigationSchema.test-d.ts +178 -178
- package/src/config/validators/InputNavigationSchema.ts +206 -206
- package/src/config/validators/ModulesSchema.ts +312 -0
- package/src/config/validators/ProtectedRoutesSchema.ts +35 -35
- package/src/config/validators/ZudokuConfig.ts +766 -729
- package/src/config/validators/auth.ts +3 -3
- package/src/config/validators/reason-codes.ts +7 -7
- package/src/env.d.ts +11 -11
- package/src/index.ts +31 -0
- package/src/lib/MissingIcon.tsx +22 -22
- package/src/lib/assets/language-icons/bun.tsx +50 -50
- package/src/lib/assets/language-icons/c.tsx +31 -31
- package/src/lib/assets/language-icons/commonlisp.tsx +22 -22
- package/src/lib/assets/language-icons/cpp.tsx +35 -35
- package/src/lib/assets/language-icons/csharp.tsx +35 -35
- package/src/lib/assets/language-icons/css.tsx +36 -36
- package/src/lib/assets/language-icons/dart.tsx +39 -39
- package/src/lib/assets/language-icons/elixir.tsx +19 -19
- package/src/lib/assets/language-icons/go.tsx +19 -19
- package/src/lib/assets/language-icons/graphql.tsx +19 -19
- package/src/lib/assets/language-icons/html.tsx +24 -24
- package/src/lib/assets/language-icons/java.tsx +35 -35
- package/src/lib/assets/language-icons/javascript.tsx +11 -11
- package/src/lib/assets/language-icons/json.tsx +19 -19
- package/src/lib/assets/language-icons/kotlin.tsx +30 -30
- package/src/lib/assets/language-icons/markdown.tsx +19 -19
- package/src/lib/assets/language-icons/mdx.tsx +23 -23
- package/src/lib/assets/language-icons/npm.tsx +15 -15
- package/src/lib/assets/language-icons/objectivec.tsx +23 -23
- package/src/lib/assets/language-icons/ocaml.tsx +34 -34
- package/src/lib/assets/language-icons/php.tsx +19 -19
- package/src/lib/assets/language-icons/pnpm.tsx +32 -32
- package/src/lib/assets/language-icons/powershell.tsx +27 -27
- package/src/lib/assets/language-icons/python.tsx +23 -23
- package/src/lib/assets/language-icons/react.tsx +21 -21
- package/src/lib/assets/language-icons/ruby.tsx +19 -19
- package/src/lib/assets/language-icons/rust.tsx +19 -19
- package/src/lib/assets/language-icons/scala.tsx +19 -19
- package/src/lib/assets/language-icons/shell.tsx +19 -19
- package/src/lib/assets/language-icons/swift.tsx +19 -19
- package/src/lib/assets/language-icons/toml.tsx +23 -23
- package/src/lib/assets/language-icons/typescript.tsx +23 -23
- package/src/lib/assets/language-icons/xml.tsx +19 -19
- package/src/lib/assets/language-icons/yaml.tsx +23 -23
- package/src/lib/assets/language-icons/yarn.tsx +17 -17
- package/src/lib/assets/language-icons/zig.tsx +32 -32
- package/src/lib/auth/issuer.ts +34 -31
- package/src/lib/authentication/AuthenticationPlugin.tsx +33 -33
- package/src/lib/authentication/authentication.ts +48 -48
- package/src/lib/authentication/components/OAuthErrorPage.tsx +197 -197
- package/src/lib/authentication/components/ProductionUnlockPage.tsx +27 -0
- package/src/lib/authentication/components/SignOut.tsx +15 -15
- package/src/lib/authentication/constants.ts +1 -1
- package/src/lib/authentication/errors.ts +34 -34
- package/src/lib/authentication/hook.ts +141 -139
- package/src/lib/authentication/providers/auth0.tsx +91 -91
- package/src/lib/authentication/providers/azureb2c.tsx +223 -223
- package/src/lib/authentication/providers/dev-portal-constants.ts +21 -0
- package/src/lib/authentication/providers/dev-portal-utils.ts +107 -0
- package/src/lib/authentication/providers/dev-portal.tsx +270 -0
- package/src/lib/authentication/providers/firebase.tsx +486 -486
- package/src/lib/authentication/providers/openid.tsx +516 -516
- package/src/lib/authentication/providers/supabase.tsx +412 -412
- package/src/lib/authentication/providers/util.ts +26 -26
- package/src/lib/authentication/state.ts +179 -91
- package/src/lib/authentication/ui/icons/Apple.tsx +10 -10
- package/src/lib/authentication/ui/icons/Facebook.tsx +15 -15
- package/src/lib/authentication/ui/icons/Github.tsx +16 -16
- package/src/lib/authentication/ui/icons/Google.tsx +16 -16
- package/src/lib/authentication/ui/icons/Microsoft.tsx +12 -12
- package/src/lib/authentication/ui/icons/X.tsx +10 -10
- package/src/lib/authentication/utils/relativeRedirectUrl.ts +16 -16
- package/src/lib/components/AnchorLink.tsx +24 -24
- package/src/lib/components/Banner.tsx +52 -52
- package/src/lib/components/Bootstrap.tsx +77 -77
- package/src/lib/components/BuildCheck.tsx +87 -87
- package/src/lib/components/CategoryHeading.tsx +19 -19
- package/src/lib/components/ClientOnly.tsx +19 -19
- package/src/lib/components/ErrorPage.tsx +26 -26
- package/src/lib/components/Footer.tsx +140 -140
- package/src/lib/components/Framed.tsx +51 -51
- package/src/lib/components/Header.tsx +11 -3
- package/src/lib/components/HeaderNavigation.tsx +148 -148
- package/src/lib/components/Heading.tsx +84 -84
- package/src/lib/components/InlineCode.tsx +15 -15
- package/src/lib/components/LandingLayout.tsx +21 -0
- package/src/lib/components/LanguageIcon.tsx +199 -199
- package/src/lib/components/Markdown.tsx +55 -55
- package/src/lib/components/Meta.tsx +46 -46
- package/src/lib/components/MobileTopNavigation.tsx +11 -3
- package/src/lib/components/NotFoundPage.tsx +37 -37
- package/src/lib/components/PageProgress.tsx +28 -28
- package/src/lib/components/PagefindSearchMeta.tsx +14 -14
- package/src/lib/components/Pagination.tsx +44 -44
- package/src/lib/components/PathRenderer.tsx +61 -61
- package/src/lib/components/PluginHeads.tsx +17 -17
- package/src/lib/components/Search.tsx +70 -70
- package/src/lib/components/Slot.tsx +64 -64
- package/src/lib/components/Spinner.tsx +5 -5
- package/src/lib/components/StatusPage.tsx +96 -96
- package/src/lib/components/ThemeSwitch.tsx +49 -49
- package/src/lib/components/Typography.tsx +12 -12
- package/src/lib/components/Zudoku.tsx +106 -106
- package/src/lib/components/cache.ts +27 -27
- package/src/lib/components/context/RenderContext.ts +11 -11
- package/src/lib/components/context/RouterEventsEmitter.tsx +19 -19
- package/src/lib/components/context/SlotProvider.tsx +149 -149
- package/src/lib/components/context/ViewportAnchorContext.tsx +137 -137
- package/src/lib/components/context/ZudokuContext.ts +140 -140
- package/src/lib/components/context/ZudokuProvider.tsx +22 -22
- package/src/lib/components/context/ZudokuReactContext.tsx +17 -17
- package/src/lib/components/index.ts +2 -0
- package/src/lib/components/navigation/Navigation.tsx +51 -51
- package/src/lib/components/navigation/NavigationBadge.tsx +48 -48
- package/src/lib/components/navigation/NavigationFilterContext.tsx +28 -28
- package/src/lib/components/navigation/NavigationWrapper.tsx +49 -49
- package/src/lib/components/navigation/Toc.tsx +137 -137
- package/src/lib/components/navigation/ZudokuLogo.tsx +25 -25
- package/src/lib/components/navigation/ZuploLogo.tsx +14 -14
- package/src/lib/components/navigation/utils.ts +234 -234
- package/src/lib/core/RouteGuard.tsx +11 -1
- package/src/lib/core/ZudokuContext.ts +271 -271
- package/src/lib/core/plugins.ts +138 -138
- package/src/lib/core/react-query.ts +1 -1
- package/src/lib/core/router.ts +1 -1
- package/src/lib/core/transform-config.ts +67 -67
- package/src/lib/demo/DemoAnnouncement.tsx +17 -17
- package/src/lib/errors/ErrorAlert.tsx +28 -28
- package/src/lib/errors/RouterError.tsx +18 -18
- package/src/lib/errors/ServerError.tsx +5 -5
- package/src/lib/errors/TopLevelError.tsx +6 -6
- package/src/lib/hooks/index.ts +13 -13
- package/src/lib/hooks/useEvent.ts +41 -41
- package/src/lib/hooks/useHighlighter.ts +15 -15
- package/src/lib/hooks/useHotkey.ts +70 -70
- package/src/lib/icons.ts +2 -2
- package/src/lib/navigation/applyRules.ts +127 -127
- package/src/lib/navigation/pathMatcher.ts +81 -81
- package/src/lib/oas/graphql/circular.ts +69 -69
- package/src/lib/oas/graphql/constants.ts +2 -2
- package/src/lib/oas/graphql/index.ts +791 -791
- package/src/lib/oas/parser/dereference/index.ts +84 -84
- package/src/lib/oas/parser/dereference/resolveRef.ts +32 -32
- package/src/lib/oas/parser/index.ts +129 -129
- package/src/lib/oas/parser/schemas/v3.0.json +1489 -1489
- package/src/lib/oas/parser/schemas/v3.1.json +1298 -1298
- package/src/lib/oas/parser/upgrade/index.ts +174 -174
- package/src/lib/plugins/api-catalog/index.tsx +119 -119
- package/src/lib/plugins/api-keys/ProtectedRoute.tsx +33 -33
- package/src/lib/plugins/api-keys/index.tsx +274 -272
- package/src/lib/plugins/api-keys/settings/ApiKeyList.tsx +67 -67
- package/src/lib/plugins/custom-pages/index.tsx +32 -32
- package/src/lib/plugins/markdown/assets/ChatGPTLogo.tsx +11 -11
- package/src/lib/plugins/markdown/assets/ClaudeLogo.tsx +19 -19
- package/src/lib/plugins/markdown/index.tsx +62 -62
- package/src/lib/plugins/openapi/ColorizedParam.tsx +115 -115
- package/src/lib/plugins/openapi/Endpoint.tsx +85 -85
- package/src/lib/plugins/openapi/MCPEndpoint.tsx +273 -273
- package/src/lib/plugins/openapi/OasProvider.tsx +74 -74
- package/src/lib/plugins/openapi/OperationList.tsx +275 -275
- package/src/lib/plugins/openapi/ParamInfos.tsx +96 -96
- package/src/lib/plugins/openapi/ParameterList.tsx +53 -53
- package/src/lib/plugins/openapi/ParameterListItem.tsx +161 -161
- package/src/lib/plugins/openapi/PlaygroundDialogWrapper.tsx +67 -67
- package/src/lib/plugins/openapi/SidecarBox.tsx +57 -57
- package/src/lib/plugins/openapi/SimpleSelect.tsx +46 -46
- package/src/lib/plugins/openapi/client/GraphQLClient.tsx +73 -73
- package/src/lib/plugins/openapi/client/GraphQLContext.tsx +16 -16
- package/src/lib/plugins/openapi/client/createServer.ts +35 -35
- package/src/lib/plugins/openapi/client/useCreateQuery.ts +44 -44
- package/src/lib/plugins/openapi/components/ConstValue.tsx +24 -24
- package/src/lib/plugins/openapi/components/NonHighlightedCode.tsx +22 -22
- package/src/lib/plugins/openapi/components/SelectOnClick.tsx +29 -29
- package/src/lib/plugins/openapi/context.tsx +16 -16
- package/src/lib/plugins/openapi/graphql/fragment-masking.ts +104 -104
- package/src/lib/plugins/openapi/graphql/gql.ts +95 -95
- package/src/lib/plugins/openapi/graphql/graphql.ts +835 -835
- package/src/lib/plugins/openapi/graphql/index.ts +2 -2
- package/src/lib/plugins/openapi/index.tsx +221 -221
- package/src/lib/plugins/openapi/interfaces.ts +100 -100
- package/src/lib/plugins/openapi/playground/Headers.tsx +6 -6
- package/src/lib/plugins/openapi/playground/PathParams.tsx +53 -53
- package/src/lib/plugins/openapi/playground/Spinner.tsx +87 -87
- package/src/lib/plugins/openapi/playground/createUrl.ts +25 -25
- package/src/lib/plugins/openapi/playground/fileUtils.ts +36 -36
- package/src/lib/plugins/openapi/playground/rememberedIdentity.ts +26 -26
- package/src/lib/plugins/openapi/playground/request-panel/UrlPath.tsx +31 -31
- package/src/lib/plugins/openapi/playground/request-panel/UrlQueryParams.tsx +29 -29
- package/src/lib/plugins/openapi/playground/request-panel/useKeyValueFieldManager.ts +340 -340
- package/src/lib/plugins/openapi/playground/result-panel/ResponseStatusBar.tsx +117 -117
- package/src/lib/plugins/openapi/playground/result-panel/convertToTypes.ts +36 -36
- package/src/lib/plugins/openapi/playground/serializeQueryParams.ts +125 -125
- package/src/lib/plugins/openapi/playground/useRememberSkipLoginDialog.tsx +23 -23
- package/src/lib/plugins/openapi/processors/removeExtensions.ts +29 -29
- package/src/lib/plugins/openapi/processors/removeParameters.ts +103 -103
- package/src/lib/plugins/openapi/processors/removePaths.ts +57 -57
- package/src/lib/plugins/openapi/processors/traverse.ts +1 -1
- package/src/lib/plugins/openapi/schema/SchemaExampleAndDefault.tsx +39 -39
- package/src/lib/plugins/openapi/schema/UnionView.tsx +132 -132
- package/src/lib/plugins/openapi/schema/union-helpers.ts +123 -123
- package/src/lib/plugins/openapi/schema/utils.ts +49 -49
- package/src/lib/plugins/openapi/state.ts +36 -36
- package/src/lib/plugins/openapi/util/buildTagCategories.ts +54 -54
- package/src/lib/plugins/openapi/util/createHttpSnippet.ts +135 -135
- package/src/lib/plugins/openapi/util/createNavigationCategory.tsx +39 -39
- package/src/lib/plugins/openapi/util/generateSchemaExample.ts +191 -191
- package/src/lib/plugins/openapi/util/getRoutes.tsx +265 -265
- package/src/lib/plugins/openapi/util/methodColorMap.tsx +11 -11
- package/src/lib/plugins/openapi/util/methodToColor.ts +27 -27
- package/src/lib/plugins/openapi/util/sanitizeMarkdownForMetatag.tsx +32 -32
- package/src/lib/plugins/openapi/util/useWarmupSchema.ts +23 -23
- package/src/lib/plugins/search-inkeep/index.tsx +108 -108
- package/src/lib/plugins/search-inkeep/inkeep.ts +24 -24
- package/src/lib/plugins/search-pagefind/get-results.tsx +74 -74
- package/src/lib/plugins/search-pagefind/index.tsx +21 -21
- package/src/lib/plugins/search-pagefind/types.ts +118 -118
- package/src/lib/shiki-constants.ts +24 -24
- package/src/lib/testing/index.tsx +146 -146
- package/src/lib/ui/Accordion.tsx +55 -55
- package/src/lib/ui/Alert.tsx +84 -84
- package/src/lib/ui/AlertDialog.tsx +195 -195
- package/src/lib/ui/AspectRatio.tsx +5 -5
- package/src/lib/ui/Badge.tsx +48 -48
- package/src/lib/ui/Breadcrumb.tsx +115 -115
- package/src/lib/ui/Button.tsx +65 -65
- package/src/lib/ui/ButtonGroup.tsx +80 -80
- package/src/lib/ui/Callout.tsx +113 -113
- package/src/lib/ui/Card.tsx +95 -95
- package/src/lib/ui/Carousel.tsx +259 -259
- package/src/lib/ui/Checkbox.tsx +28 -28
- package/src/lib/ui/CodeBlock.tsx +92 -92
- package/src/lib/ui/CodeTabPanel.tsx +13 -13
- package/src/lib/ui/CodeTabs.tsx +161 -161
- package/src/lib/ui/Collapsible.tsx +31 -31
- package/src/lib/ui/Dialog.tsx +138 -138
- package/src/lib/ui/DismissibleAlert.tsx +74 -74
- package/src/lib/ui/Drawer.tsx +121 -121
- package/src/lib/ui/DropdownMenu.tsx +254 -254
- package/src/lib/ui/EmbeddedCodeBlock.tsx +99 -99
- package/src/lib/ui/Form.tsx +176 -176
- package/src/lib/ui/Frame.tsx +81 -81
- package/src/lib/ui/HoverCard.tsx +26 -26
- package/src/lib/ui/Input.tsx +23 -23
- package/src/lib/ui/InputGroup.tsx +168 -168
- package/src/lib/ui/Item.tsx +213 -213
- package/src/lib/ui/Kbd.tsx +28 -28
- package/src/lib/ui/Label.tsx +23 -23
- package/src/lib/ui/NativeSelect.tsx +48 -48
- package/src/lib/ui/NavigationMenu.tsx +169 -169
- package/src/lib/ui/Pagination.tsx +115 -115
- package/src/lib/ui/Popover.tsx +28 -28
- package/src/lib/ui/Progress.tsx +25 -25
- package/src/lib/ui/RadioGroup.tsx +41 -41
- package/src/lib/ui/ReactComponentDoc.tsx +68 -68
- package/src/lib/ui/ScrollArea.tsx +45 -45
- package/src/lib/ui/Secret.tsx +133 -133
- package/src/lib/ui/Select.tsx +184 -184
- package/src/lib/ui/Separator.tsx +25 -25
- package/src/lib/ui/Skeleton.tsx +15 -15
- package/src/lib/ui/Slider.tsx +25 -25
- package/src/lib/ui/Stepper.tsx +8 -8
- package/src/lib/ui/Switch.tsx +26 -26
- package/src/lib/ui/SyntaxHighlight.tsx +54 -54
- package/src/lib/ui/Tabs.tsx +52 -52
- package/src/lib/ui/Textarea.tsx +22 -22
- package/src/lib/ui/Toggle.tsx +42 -42
- package/src/lib/ui/ToggleGroup.tsx +58 -58
- package/src/lib/ui/Tooltip.tsx +65 -65
- package/src/lib/ui/Value.tsx +42 -42
- package/src/lib/ui/util.tsx +8 -8
- package/src/lib/util/cn.ts +6 -6
- package/src/lib/util/createVariantComponent.tsx +61 -61
- package/src/lib/util/ensureArray.ts +3 -3
- package/src/lib/util/flattenAllOf.ts +72 -72
- package/src/lib/util/flattenAllOfProcessor.ts +74 -74
- package/src/lib/util/hastToJsx.tsx +67 -67
- package/src/lib/util/humanFileSize.ts +15 -15
- package/src/lib/util/invariant.ts +52 -52
- package/src/lib/util/joinUrl.ts +60 -60
- package/src/lib/util/logInit.ts +9 -9
- package/src/lib/util/objectEntries.ts +5 -5
- package/src/lib/util/os.ts +18 -18
- package/src/lib/util/pastellize.ts +25 -25
- package/src/lib/util/problemJson.ts +63 -63
- package/src/lib/util/readFrontmatter.ts +14 -14
- package/src/lib/util/renderIf.ts +4 -4
- package/src/lib/util/scrollIntoViewIfNeeded.ts +18 -18
- package/src/lib/util/slugify.ts +21 -21
- package/src/lib/util/syncZustandState.ts +22 -22
- package/src/lib/util/traverse.ts +70 -70
- package/src/lib/util/types.ts +7 -7
- package/src/lib/util/url.ts +18 -18
- package/src/lib/util/useCopyToClipboard.ts +17 -17
- package/src/lib/util/useExposedProps.tsx +27 -27
- package/src/lib/util/useIsomorphicLayoutEffect.ts +6 -6
- package/src/lib/util/useLatest.ts +18 -18
- package/src/lib/util/useOnScreen.ts +34 -34
- package/src/lib/util/useScrollToAnchor.ts +70 -70
- package/src/lib/util/useScrollToTop.ts +18 -18
- package/src/types.d.ts +57 -53
- package/src/vite/api/SchemaManager.ts +371 -371
- package/src/vite/api/schema-codegen.ts +163 -163
- package/src/vite/config.ts +5 -1
- package/src/vite/css/collect.ts +42 -42
- package/src/vite/css/plugin.ts +105 -105
- package/src/vite/debug.ts +18 -18
- package/src/vite/dev-portal-env.ts +93 -0
- package/src/vite/html.ts +54 -54
- package/src/vite/index.ts +2 -2
- package/src/vite/mdx/rehype-extract-toc-with-jsx-export.ts +19 -19
- package/src/vite/mdx/rehype-extract-toc-with-jsx.ts +70 -70
- package/src/vite/mdx/remark-code-tabs.ts +47 -47
- package/src/vite/mdx/remark-inject-filepath.ts +13 -13
- package/src/vite/mdx/remark-last-modified.ts +103 -103
- package/src/vite/mdx/remark-link-rewrite.ts +23 -23
- package/src/vite/mdx/remark-normalize-image-url.ts +15 -15
- package/src/vite/mdx/remark-static-generation.ts +149 -149
- package/src/vite/mdx/utils.ts +32 -32
- package/src/vite/output.ts +261 -261
- package/src/vite/package-root.ts +12 -12
- package/src/vite/pagefind-dev-index.ts +100 -100
- package/src/vite/plugin-api-keys.ts +6 -1
- package/src/vite/plugin-api.ts +4 -1
- package/src/vite/plugin-auth.ts +5 -1
- package/src/vite/plugin-component.ts +1 -1
- package/src/vite/plugin-config-reload.ts +49 -49
- package/src/vite/plugin-doc-metadata.ts +45 -45
- package/src/vite/plugin-docs.ts +4 -1
- package/src/vite/plugin-metadata.ts +30 -30
- package/src/vite/plugin-modules.ts +144 -0
- package/src/vite/plugin-shiki-register.ts +97 -97
- package/src/vite/plugin-theme.ts +399 -399
- package/src/vite/plugin.ts +2 -0
- package/src/vite/prerender/utils.ts +76 -76
- package/src/vite/prerender/worker.ts +118 -118
- package/src/vite/reporter.ts +34 -34
- package/src/vite/shadcn-registry.ts +48 -48
- package/src/vite/sitemap.ts +78 -78
- package/src/vite/ssr-templates/cloudflare.ts +19 -19
- package/src/vite/ssr-templates/node.ts +25 -25
- package/src/vite/ssr-templates/vercel.ts +22 -22
- package/src/vite/zuplo.ts +30 -30
- package/src/vite-env.d.ts +6 -6
- package/src/zuplo/enrich-with-zuplo-mcp.ts +168 -168
- package/src/zuplo/enrich-with-zuplo.ts +256 -256
- package/src/zuplo/policy-types.ts +46 -46
- package/src/zuplo/with-zuplo-processors.ts +36 -36
- package/src/zuplo/with-zuplo.ts +14 -14
- package/LICENSE.md +0 -18
- package/dist/declarations/lib/components/navigation/ZudokuLogo.d.ts +0 -6
|
@@ -1,486 +1,486 @@
|
|
|
1
|
-
import { type FirebaseApp, initializeApp } from "firebase/app";
|
|
2
|
-
import {
|
|
3
|
-
type Auth,
|
|
4
|
-
createUserWithEmailAndPassword,
|
|
5
|
-
getAuth,
|
|
6
|
-
isSignInWithEmailLink,
|
|
7
|
-
sendEmailVerification,
|
|
8
|
-
sendPasswordResetEmail,
|
|
9
|
-
sendSignInLinkToEmail,
|
|
10
|
-
signInWithEmailAndPassword,
|
|
11
|
-
signInWithEmailLink,
|
|
12
|
-
signInWithPopup,
|
|
13
|
-
signOut,
|
|
14
|
-
type User,
|
|
15
|
-
} from "firebase/auth";
|
|
16
|
-
import type { FirebaseAuthenticationConfig } from "../../../config/config.js";
|
|
17
|
-
import { ClientOnly } from "../../components/ClientOnly.js";
|
|
18
|
-
import { ZudokuError } from "../../util/invariant.js";
|
|
19
|
-
import { joinUrl } from "../../util/joinUrl.js";
|
|
20
|
-
import type {
|
|
21
|
-
AuthActionContext,
|
|
22
|
-
AuthActionOptions,
|
|
23
|
-
AuthenticationPlugin,
|
|
24
|
-
AuthenticationProviderInitializer,
|
|
25
|
-
} from "../authentication.js";
|
|
26
|
-
import { CoreAuthenticationPlugin } from "../AuthenticationPlugin.js";
|
|
27
|
-
import { SignOut } from "../components/SignOut.js";
|
|
28
|
-
import { AuthorizationError } from "../errors.js";
|
|
29
|
-
import { useAuthState } from "../state.js";
|
|
30
|
-
import { EmailLinkCallbackUi } from "../ui/EmailLinkCallbackUi.js";
|
|
31
|
-
import { EmailLinkSentUi } from "../ui/EmailLinkSentUi.js";
|
|
32
|
-
import { EmailLinkSignInUi } from "../ui/EmailLinkSignInUi.js";
|
|
33
|
-
import { EmailVerificationUi } from "../ui/EmailVerificationUi.js";
|
|
34
|
-
import {
|
|
35
|
-
ZudokuPasswordResetUi,
|
|
36
|
-
ZudokuSignInUi,
|
|
37
|
-
ZudokuSignUpUi,
|
|
38
|
-
} from "../ui/ZudokuAuthUi.js";
|
|
39
|
-
|
|
40
|
-
export type FirebaseProviderData = {
|
|
41
|
-
type: "firebase";
|
|
42
|
-
user: User;
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
declare module "../state.js" {
|
|
46
|
-
interface ProviderDataRegistry {
|
|
47
|
-
firebase: FirebaseProviderData;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
import { EMAIL_LINK_STORAGE_KEY } from "../constants.js";
|
|
52
|
-
|
|
53
|
-
class FirebaseAuthenticationProvider
|
|
54
|
-
extends CoreAuthenticationPlugin
|
|
55
|
-
implements AuthenticationPlugin
|
|
56
|
-
{
|
|
57
|
-
private readonly app: FirebaseApp;
|
|
58
|
-
private readonly auth: Auth;
|
|
59
|
-
private readonly providers: string[];
|
|
60
|
-
private readonly enableUsernamePassword: boolean;
|
|
61
|
-
private readonly enableEmailLink: boolean;
|
|
62
|
-
|
|
63
|
-
constructor(config: FirebaseAuthenticationConfig) {
|
|
64
|
-
super();
|
|
65
|
-
|
|
66
|
-
this.app = initializeApp({
|
|
67
|
-
apiKey: config.apiKey,
|
|
68
|
-
authDomain: config.authDomain,
|
|
69
|
-
projectId: config.projectId,
|
|
70
|
-
storageBucket: config.storageBucket,
|
|
71
|
-
messagingSenderId: config.messagingSenderId,
|
|
72
|
-
appId: config.appId,
|
|
73
|
-
measurementId: config.measurementId,
|
|
74
|
-
});
|
|
75
|
-
this.auth = getAuth(this.app);
|
|
76
|
-
this.providers =
|
|
77
|
-
config.providers?.filter((p) => p !== "password" && p !== "emailLink") ??
|
|
78
|
-
[];
|
|
79
|
-
this.enableUsernamePassword =
|
|
80
|
-
config.providers?.includes("password") ?? false;
|
|
81
|
-
this.enableEmailLink = config.providers?.includes("emailLink") ?? false;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
async initialize() {
|
|
85
|
-
await this.auth.authStateReady();
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
async signRequest(request: Request): Promise<Request> {
|
|
89
|
-
const accessToken = await this.auth.currentUser?.getIdToken();
|
|
90
|
-
if (!accessToken) {
|
|
91
|
-
throw new AuthorizationError("User is not authenticated");
|
|
92
|
-
}
|
|
93
|
-
request.headers.set("Authorization", `Bearer ${accessToken}`);
|
|
94
|
-
return request;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
signUp = async (
|
|
98
|
-
{ navigate }: AuthActionContext,
|
|
99
|
-
{ redirectTo }: AuthActionOptions,
|
|
100
|
-
) => {
|
|
101
|
-
void navigate(
|
|
102
|
-
redirectTo
|
|
103
|
-
? `/signup?redirectTo=${encodeURIComponent(redirectTo)}`
|
|
104
|
-
: `/signup`,
|
|
105
|
-
);
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
signIn = async (
|
|
109
|
-
{ navigate }: AuthActionContext,
|
|
110
|
-
{ redirectTo }: AuthActionOptions,
|
|
111
|
-
) => {
|
|
112
|
-
void navigate(
|
|
113
|
-
redirectTo
|
|
114
|
-
? `/signin?redirectTo=${encodeURIComponent(redirectTo)}`
|
|
115
|
-
: `/signin`,
|
|
116
|
-
);
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
requestEmailVerification = async (
|
|
120
|
-
{ navigate }: AuthActionContext,
|
|
121
|
-
{ redirectTo }: AuthActionOptions,
|
|
122
|
-
) => {
|
|
123
|
-
if (!this.auth.currentUser) {
|
|
124
|
-
throw new ZudokuError("User is not authenticated", {
|
|
125
|
-
title: "User not authenticated",
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
await sendEmailVerification(this.auth.currentUser);
|
|
130
|
-
void navigate(
|
|
131
|
-
redirectTo
|
|
132
|
-
? `/verify-email?redirectTo=${encodeURIComponent(redirectTo)}`
|
|
133
|
-
: `/verify-email`,
|
|
134
|
-
);
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
private getEmailLinkActionCodeSettings(redirectTo?: string) {
|
|
138
|
-
const callbackUrl = new URL(window.location.origin);
|
|
139
|
-
callbackUrl.pathname = joinUrl(
|
|
140
|
-
import.meta.env.BASE_URL,
|
|
141
|
-
"/signin/email-link-callback",
|
|
142
|
-
);
|
|
143
|
-
if (redirectTo) {
|
|
144
|
-
callbackUrl.searchParams.set("redirectTo", redirectTo);
|
|
145
|
-
}
|
|
146
|
-
return {
|
|
147
|
-
url: callbackUrl.toString(),
|
|
148
|
-
handleCodeInApp: true as const,
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
private async sendEmailLink(email: string, redirectTo?: string) {
|
|
153
|
-
try {
|
|
154
|
-
await sendSignInLinkToEmail(
|
|
155
|
-
this.auth,
|
|
156
|
-
email,
|
|
157
|
-
this.getEmailLinkActionCodeSettings(redirectTo),
|
|
158
|
-
);
|
|
159
|
-
} catch (error) {
|
|
160
|
-
throw new Error(getFirebaseErrorMessage(error), { cause: error });
|
|
161
|
-
}
|
|
162
|
-
localStorage.setItem(EMAIL_LINK_STORAGE_KEY, email);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
getRoutes = () => {
|
|
166
|
-
return [
|
|
167
|
-
{
|
|
168
|
-
path: "/verify-email",
|
|
169
|
-
element: (
|
|
170
|
-
<EmailVerificationUi
|
|
171
|
-
onResendVerification={async () => {
|
|
172
|
-
if (!this.auth.currentUser) {
|
|
173
|
-
throw new ZudokuError("User is not authenticated", {
|
|
174
|
-
title: "User not authenticated",
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
await sendEmailVerification(this.auth.currentUser);
|
|
178
|
-
}}
|
|
179
|
-
onCheckVerification={async () => {
|
|
180
|
-
if (!this.auth.currentUser) {
|
|
181
|
-
throw new ZudokuError("User is not authenticated", {
|
|
182
|
-
title: "User not authenticated",
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
await this.auth.currentUser.reload();
|
|
186
|
-
const isVerified = this.auth.currentUser.emailVerified;
|
|
187
|
-
|
|
188
|
-
if (isVerified) {
|
|
189
|
-
await this.auth.currentUser.getIdToken(true);
|
|
190
|
-
await this.setUserLoggedIn(this.auth.currentUser);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
return isVerified;
|
|
194
|
-
}}
|
|
195
|
-
/>
|
|
196
|
-
),
|
|
197
|
-
},
|
|
198
|
-
{
|
|
199
|
-
path: "/reset-password",
|
|
200
|
-
element: (
|
|
201
|
-
<ZudokuPasswordResetUi
|
|
202
|
-
onPasswordReset={async (email: string) => {
|
|
203
|
-
try {
|
|
204
|
-
await sendPasswordResetEmail(this.auth, email);
|
|
205
|
-
} catch (error) {
|
|
206
|
-
throw Error(getFirebaseErrorMessage(error), { cause: error });
|
|
207
|
-
}
|
|
208
|
-
}}
|
|
209
|
-
/>
|
|
210
|
-
),
|
|
211
|
-
},
|
|
212
|
-
{
|
|
213
|
-
path: "/signin",
|
|
214
|
-
element: (
|
|
215
|
-
<ZudokuSignInUi
|
|
216
|
-
providers={this.providers}
|
|
217
|
-
enableUsernamePassword={this.enableUsernamePassword}
|
|
218
|
-
onOAuthSignIn={async (providerId: string) => {
|
|
219
|
-
useAuthState.setState({ isPending: true });
|
|
220
|
-
const provider = await getProviderForId(providerId);
|
|
221
|
-
if (!provider) {
|
|
222
|
-
throw new AuthorizationError(
|
|
223
|
-
`Provider ${providerId} not found`,
|
|
224
|
-
);
|
|
225
|
-
}
|
|
226
|
-
const result = await signInWithPopup(this.auth, provider);
|
|
227
|
-
useAuthState.setState({ isPending: false });
|
|
228
|
-
useAuthState.getState().setLoggedIn({
|
|
229
|
-
providerData: { type: "firebase", user: result.user },
|
|
230
|
-
profile: {
|
|
231
|
-
sub: result.user.uid,
|
|
232
|
-
email: result.user.email ?? undefined,
|
|
233
|
-
name: result.user.displayName ?? undefined,
|
|
234
|
-
emailVerified: result.user.emailVerified,
|
|
235
|
-
pictureUrl: result.user.photoURL ?? undefined,
|
|
236
|
-
},
|
|
237
|
-
});
|
|
238
|
-
}}
|
|
239
|
-
onUsernamePasswordSignIn={async (
|
|
240
|
-
email: string,
|
|
241
|
-
password: string,
|
|
242
|
-
) => {
|
|
243
|
-
try {
|
|
244
|
-
useAuthState.setState({ isPending: false });
|
|
245
|
-
const result = await signInWithEmailAndPassword(
|
|
246
|
-
this.auth,
|
|
247
|
-
email,
|
|
248
|
-
password,
|
|
249
|
-
);
|
|
250
|
-
await this.setUserLoggedIn(result.user);
|
|
251
|
-
} catch (error) {
|
|
252
|
-
throw Error(getFirebaseErrorMessage(error), { cause: error });
|
|
253
|
-
}
|
|
254
|
-
}}
|
|
255
|
-
enableEmailLink={this.enableEmailLink}
|
|
256
|
-
/>
|
|
257
|
-
),
|
|
258
|
-
},
|
|
259
|
-
{
|
|
260
|
-
path: "/signup",
|
|
261
|
-
element: (
|
|
262
|
-
<ZudokuSignUpUi
|
|
263
|
-
providers={this.providers}
|
|
264
|
-
enableUsernamePassword={this.enableUsernamePassword}
|
|
265
|
-
enableEmailLink={this.enableEmailLink}
|
|
266
|
-
onOAuthSignUp={async (providerId: string) => {
|
|
267
|
-
const provider = await getProviderForId(providerId);
|
|
268
|
-
if (!provider) {
|
|
269
|
-
throw new AuthorizationError(
|
|
270
|
-
`Provider ${providerId} not found`,
|
|
271
|
-
);
|
|
272
|
-
}
|
|
273
|
-
await signInWithPopup(this.auth, provider);
|
|
274
|
-
}}
|
|
275
|
-
onUsernamePasswordSignUp={async (
|
|
276
|
-
email: string,
|
|
277
|
-
password: string,
|
|
278
|
-
) => {
|
|
279
|
-
useAuthState.setState({ isPending: true });
|
|
280
|
-
const createUser = await createUserWithEmailAndPassword(
|
|
281
|
-
this.auth,
|
|
282
|
-
email,
|
|
283
|
-
password,
|
|
284
|
-
);
|
|
285
|
-
await this.setUserLoggedIn(createUser.user);
|
|
286
|
-
}}
|
|
287
|
-
/>
|
|
288
|
-
),
|
|
289
|
-
},
|
|
290
|
-
{
|
|
291
|
-
path: "/signin/email-link",
|
|
292
|
-
element: (
|
|
293
|
-
<EmailLinkSignInUi
|
|
294
|
-
onSubmit={async (email: string, redirectTo?: string) => {
|
|
295
|
-
await this.sendEmailLink(email, redirectTo);
|
|
296
|
-
}}
|
|
297
|
-
/>
|
|
298
|
-
),
|
|
299
|
-
},
|
|
300
|
-
{
|
|
301
|
-
path: "/signin/email-link-sent",
|
|
302
|
-
element: (
|
|
303
|
-
<ClientOnly>
|
|
304
|
-
<EmailLinkSentUi
|
|
305
|
-
onResendEmailLink={async () => {
|
|
306
|
-
const email = localStorage.getItem(EMAIL_LINK_STORAGE_KEY);
|
|
307
|
-
if (!email) {
|
|
308
|
-
throw new ZudokuError(
|
|
309
|
-
"No email address found. Please go back and try again.",
|
|
310
|
-
{ title: "Email not found" },
|
|
311
|
-
);
|
|
312
|
-
}
|
|
313
|
-
await this.sendEmailLink(email);
|
|
314
|
-
}}
|
|
315
|
-
/>
|
|
316
|
-
</ClientOnly>
|
|
317
|
-
),
|
|
318
|
-
},
|
|
319
|
-
{
|
|
320
|
-
path: "/signin/email-link-callback",
|
|
321
|
-
element: (
|
|
322
|
-
<ClientOnly>
|
|
323
|
-
<EmailLinkCallbackUi
|
|
324
|
-
onCompleteSignIn={async (email: string) => {
|
|
325
|
-
try {
|
|
326
|
-
const result = await signInWithEmailLink(
|
|
327
|
-
this.auth,
|
|
328
|
-
email,
|
|
329
|
-
window.location.href,
|
|
330
|
-
);
|
|
331
|
-
await this.setUserLoggedIn(result.user);
|
|
332
|
-
} catch (error) {
|
|
333
|
-
throw Error(getFirebaseErrorMessage(error), {
|
|
334
|
-
cause: error,
|
|
335
|
-
});
|
|
336
|
-
}
|
|
337
|
-
}}
|
|
338
|
-
isEmailLinkUrl={(url: string) =>
|
|
339
|
-
isSignInWithEmailLink(this.auth, url)
|
|
340
|
-
}
|
|
341
|
-
/>
|
|
342
|
-
</ClientOnly>
|
|
343
|
-
),
|
|
344
|
-
},
|
|
345
|
-
{
|
|
346
|
-
path: "/signout",
|
|
347
|
-
element: <SignOut />,
|
|
348
|
-
},
|
|
349
|
-
];
|
|
350
|
-
};
|
|
351
|
-
|
|
352
|
-
signOut = async () => {
|
|
353
|
-
await signOut(this.auth);
|
|
354
|
-
|
|
355
|
-
useAuthState.setState({
|
|
356
|
-
isAuthenticated: false,
|
|
357
|
-
isPending: false,
|
|
358
|
-
profile: undefined,
|
|
359
|
-
providerData: undefined,
|
|
360
|
-
});
|
|
361
|
-
};
|
|
362
|
-
|
|
363
|
-
onPageLoad = async () => {
|
|
364
|
-
const user = this.auth.currentUser;
|
|
365
|
-
|
|
366
|
-
if (user) {
|
|
367
|
-
await this.setUserLoggedIn(user);
|
|
368
|
-
} else {
|
|
369
|
-
useAuthState.setState({ isPending: false });
|
|
370
|
-
}
|
|
371
|
-
};
|
|
372
|
-
|
|
373
|
-
private async setUserLoggedIn(user: User) {
|
|
374
|
-
useAuthState.getState().setLoggedIn({
|
|
375
|
-
profile: {
|
|
376
|
-
sub: user.uid,
|
|
377
|
-
email: user.email ?? undefined,
|
|
378
|
-
name: user.displayName ?? undefined,
|
|
379
|
-
emailVerified: user.emailVerified,
|
|
380
|
-
pictureUrl: user.photoURL ?? undefined,
|
|
381
|
-
},
|
|
382
|
-
providerData: { type: "firebase", user },
|
|
383
|
-
});
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
const supabaseAuth: AuthenticationProviderInitializer<
|
|
388
|
-
FirebaseAuthenticationConfig
|
|
389
|
-
> = (options) => new FirebaseAuthenticationProvider(options);
|
|
390
|
-
|
|
391
|
-
export default supabaseAuth;
|
|
392
|
-
|
|
393
|
-
const getProviderForId = async (providerId: string) => {
|
|
394
|
-
switch (providerId) {
|
|
395
|
-
case "google": {
|
|
396
|
-
const { GoogleAuthProvider } = await import("firebase/auth");
|
|
397
|
-
return new GoogleAuthProvider();
|
|
398
|
-
}
|
|
399
|
-
case "github": {
|
|
400
|
-
const { GithubAuthProvider } = await import("firebase/auth");
|
|
401
|
-
return new GithubAuthProvider();
|
|
402
|
-
}
|
|
403
|
-
case "facebook": {
|
|
404
|
-
const { FacebookAuthProvider } = await import("firebase/auth");
|
|
405
|
-
return new FacebookAuthProvider();
|
|
406
|
-
}
|
|
407
|
-
case "twitter": {
|
|
408
|
-
const { TwitterAuthProvider } = await import("firebase/auth");
|
|
409
|
-
return new TwitterAuthProvider();
|
|
410
|
-
}
|
|
411
|
-
case "microsoft": {
|
|
412
|
-
const { OAuthProvider } = await import("firebase/auth");
|
|
413
|
-
return new OAuthProvider("microsoft.com");
|
|
414
|
-
}
|
|
415
|
-
case "apple": {
|
|
416
|
-
const { OAuthProvider } = await import("firebase/auth");
|
|
417
|
-
return new OAuthProvider("apple.com");
|
|
418
|
-
}
|
|
419
|
-
case "yahoo": {
|
|
420
|
-
const { OAuthProvider } = await import("firebase/auth");
|
|
421
|
-
return new OAuthProvider("yahoo.com");
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
throw new AuthorizationError(`Provider ${providerId} not found`);
|
|
426
|
-
};
|
|
427
|
-
|
|
428
|
-
const getFirebaseErrorMessage = (error: unknown): string => {
|
|
429
|
-
if (!(error instanceof Error)) {
|
|
430
|
-
return "An unexpected error occurred. Please try again.";
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
const errorCode = (error as { code?: string }).code;
|
|
434
|
-
|
|
435
|
-
switch (errorCode) {
|
|
436
|
-
case "auth/email-already-in-use":
|
|
437
|
-
return "The email address is already used by another account.";
|
|
438
|
-
case "auth/invalid-email":
|
|
439
|
-
return "That email address isn't correct.";
|
|
440
|
-
case "auth/operation-not-allowed":
|
|
441
|
-
return "This sign-in method is not enabled. Please contact support.";
|
|
442
|
-
case "auth/weak-password":
|
|
443
|
-
return "The password must be at least 6 characters long.";
|
|
444
|
-
case "auth/user-disabled":
|
|
445
|
-
return "This account has been disabled. Please contact support.";
|
|
446
|
-
case "auth/user-not-found":
|
|
447
|
-
return "That email address doesn't match an existing account.";
|
|
448
|
-
case "auth/wrong-password":
|
|
449
|
-
return "The email and password you entered don't match.";
|
|
450
|
-
case "auth/too-many-requests":
|
|
451
|
-
return "You have entered an incorrect password too many times. Please try again in a few minutes.";
|
|
452
|
-
case "auth/popup-blocked":
|
|
453
|
-
return "The sign-in popup was blocked by your browser. Please allow popups and try again.";
|
|
454
|
-
case "auth/popup-closed-by-user":
|
|
455
|
-
return "The sign-in popup was closed before completing. Please try again.";
|
|
456
|
-
case "auth/network-request-failed":
|
|
457
|
-
return "A network error has occurred. Please check your connection and try again.";
|
|
458
|
-
case "auth/requires-recent-login":
|
|
459
|
-
return "Please login again to perform this operation.";
|
|
460
|
-
case "auth/invalid-credential":
|
|
461
|
-
return "The credential is invalid or has expired. Please try again.";
|
|
462
|
-
case "auth/account-exists-with-different-credential":
|
|
463
|
-
return "An account already exists with the same email address but different sign-in credentials.";
|
|
464
|
-
case "auth/credential-already-in-use":
|
|
465
|
-
return "This credential is already associated with a different user account.";
|
|
466
|
-
case "auth/invalid-verification-code":
|
|
467
|
-
return "Wrong code. Try again.";
|
|
468
|
-
case "auth/invalid-verification-id":
|
|
469
|
-
return "The verification ID is invalid.";
|
|
470
|
-
case "auth/missing-verification-code":
|
|
471
|
-
return "Please enter the verification code.";
|
|
472
|
-
case "auth/user-cancelled":
|
|
473
|
-
return "Please authorize the required permissions to sign in.";
|
|
474
|
-
case "auth/expired-action-code":
|
|
475
|
-
return "This code has expired.";
|
|
476
|
-
case "auth/invalid-action-code":
|
|
477
|
-
return "The action code is invalid. This can happen if the code is malformed or has already been used.";
|
|
478
|
-
case "auth/unauthorized-domain":
|
|
479
|
-
return "This domain is not authorized for OAuth operations.";
|
|
480
|
-
default:
|
|
481
|
-
return (
|
|
482
|
-
error.message ||
|
|
483
|
-
"An error occurred during authentication. Please try again."
|
|
484
|
-
);
|
|
485
|
-
}
|
|
486
|
-
};
|
|
1
|
+
import { type FirebaseApp, initializeApp } from "firebase/app";
|
|
2
|
+
import {
|
|
3
|
+
type Auth,
|
|
4
|
+
createUserWithEmailAndPassword,
|
|
5
|
+
getAuth,
|
|
6
|
+
isSignInWithEmailLink,
|
|
7
|
+
sendEmailVerification,
|
|
8
|
+
sendPasswordResetEmail,
|
|
9
|
+
sendSignInLinkToEmail,
|
|
10
|
+
signInWithEmailAndPassword,
|
|
11
|
+
signInWithEmailLink,
|
|
12
|
+
signInWithPopup,
|
|
13
|
+
signOut,
|
|
14
|
+
type User,
|
|
15
|
+
} from "firebase/auth";
|
|
16
|
+
import type { FirebaseAuthenticationConfig } from "../../../config/config.js";
|
|
17
|
+
import { ClientOnly } from "../../components/ClientOnly.js";
|
|
18
|
+
import { ZudokuError } from "../../util/invariant.js";
|
|
19
|
+
import { joinUrl } from "../../util/joinUrl.js";
|
|
20
|
+
import type {
|
|
21
|
+
AuthActionContext,
|
|
22
|
+
AuthActionOptions,
|
|
23
|
+
AuthenticationPlugin,
|
|
24
|
+
AuthenticationProviderInitializer,
|
|
25
|
+
} from "../authentication.js";
|
|
26
|
+
import { CoreAuthenticationPlugin } from "../AuthenticationPlugin.js";
|
|
27
|
+
import { SignOut } from "../components/SignOut.js";
|
|
28
|
+
import { AuthorizationError } from "../errors.js";
|
|
29
|
+
import { useAuthState } from "../state.js";
|
|
30
|
+
import { EmailLinkCallbackUi } from "../ui/EmailLinkCallbackUi.js";
|
|
31
|
+
import { EmailLinkSentUi } from "../ui/EmailLinkSentUi.js";
|
|
32
|
+
import { EmailLinkSignInUi } from "../ui/EmailLinkSignInUi.js";
|
|
33
|
+
import { EmailVerificationUi } from "../ui/EmailVerificationUi.js";
|
|
34
|
+
import {
|
|
35
|
+
ZudokuPasswordResetUi,
|
|
36
|
+
ZudokuSignInUi,
|
|
37
|
+
ZudokuSignUpUi,
|
|
38
|
+
} from "../ui/ZudokuAuthUi.js";
|
|
39
|
+
|
|
40
|
+
export type FirebaseProviderData = {
|
|
41
|
+
type: "firebase";
|
|
42
|
+
user: User;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
declare module "../state.js" {
|
|
46
|
+
interface ProviderDataRegistry {
|
|
47
|
+
firebase: FirebaseProviderData;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
import { EMAIL_LINK_STORAGE_KEY } from "../constants.js";
|
|
52
|
+
|
|
53
|
+
class FirebaseAuthenticationProvider
|
|
54
|
+
extends CoreAuthenticationPlugin
|
|
55
|
+
implements AuthenticationPlugin
|
|
56
|
+
{
|
|
57
|
+
private readonly app: FirebaseApp;
|
|
58
|
+
private readonly auth: Auth;
|
|
59
|
+
private readonly providers: string[];
|
|
60
|
+
private readonly enableUsernamePassword: boolean;
|
|
61
|
+
private readonly enableEmailLink: boolean;
|
|
62
|
+
|
|
63
|
+
constructor(config: FirebaseAuthenticationConfig) {
|
|
64
|
+
super();
|
|
65
|
+
|
|
66
|
+
this.app = initializeApp({
|
|
67
|
+
apiKey: config.apiKey,
|
|
68
|
+
authDomain: config.authDomain,
|
|
69
|
+
projectId: config.projectId,
|
|
70
|
+
storageBucket: config.storageBucket,
|
|
71
|
+
messagingSenderId: config.messagingSenderId,
|
|
72
|
+
appId: config.appId,
|
|
73
|
+
measurementId: config.measurementId,
|
|
74
|
+
});
|
|
75
|
+
this.auth = getAuth(this.app);
|
|
76
|
+
this.providers =
|
|
77
|
+
config.providers?.filter((p) => p !== "password" && p !== "emailLink") ??
|
|
78
|
+
[];
|
|
79
|
+
this.enableUsernamePassword =
|
|
80
|
+
config.providers?.includes("password") ?? false;
|
|
81
|
+
this.enableEmailLink = config.providers?.includes("emailLink") ?? false;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async initialize() {
|
|
85
|
+
await this.auth.authStateReady();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async signRequest(request: Request): Promise<Request> {
|
|
89
|
+
const accessToken = await this.auth.currentUser?.getIdToken();
|
|
90
|
+
if (!accessToken) {
|
|
91
|
+
throw new AuthorizationError("User is not authenticated");
|
|
92
|
+
}
|
|
93
|
+
request.headers.set("Authorization", `Bearer ${accessToken}`);
|
|
94
|
+
return request;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
signUp = async (
|
|
98
|
+
{ navigate }: AuthActionContext,
|
|
99
|
+
{ redirectTo }: AuthActionOptions,
|
|
100
|
+
) => {
|
|
101
|
+
void navigate(
|
|
102
|
+
redirectTo
|
|
103
|
+
? `/signup?redirectTo=${encodeURIComponent(redirectTo)}`
|
|
104
|
+
: `/signup`,
|
|
105
|
+
);
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
signIn = async (
|
|
109
|
+
{ navigate }: AuthActionContext,
|
|
110
|
+
{ redirectTo }: AuthActionOptions,
|
|
111
|
+
) => {
|
|
112
|
+
void navigate(
|
|
113
|
+
redirectTo
|
|
114
|
+
? `/signin?redirectTo=${encodeURIComponent(redirectTo)}`
|
|
115
|
+
: `/signin`,
|
|
116
|
+
);
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
requestEmailVerification = async (
|
|
120
|
+
{ navigate }: AuthActionContext,
|
|
121
|
+
{ redirectTo }: AuthActionOptions,
|
|
122
|
+
) => {
|
|
123
|
+
if (!this.auth.currentUser) {
|
|
124
|
+
throw new ZudokuError("User is not authenticated", {
|
|
125
|
+
title: "User not authenticated",
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
await sendEmailVerification(this.auth.currentUser);
|
|
130
|
+
void navigate(
|
|
131
|
+
redirectTo
|
|
132
|
+
? `/verify-email?redirectTo=${encodeURIComponent(redirectTo)}`
|
|
133
|
+
: `/verify-email`,
|
|
134
|
+
);
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
private getEmailLinkActionCodeSettings(redirectTo?: string) {
|
|
138
|
+
const callbackUrl = new URL(window.location.origin);
|
|
139
|
+
callbackUrl.pathname = joinUrl(
|
|
140
|
+
import.meta.env.BASE_URL,
|
|
141
|
+
"/signin/email-link-callback",
|
|
142
|
+
);
|
|
143
|
+
if (redirectTo) {
|
|
144
|
+
callbackUrl.searchParams.set("redirectTo", redirectTo);
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
url: callbackUrl.toString(),
|
|
148
|
+
handleCodeInApp: true as const,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
private async sendEmailLink(email: string, redirectTo?: string) {
|
|
153
|
+
try {
|
|
154
|
+
await sendSignInLinkToEmail(
|
|
155
|
+
this.auth,
|
|
156
|
+
email,
|
|
157
|
+
this.getEmailLinkActionCodeSettings(redirectTo),
|
|
158
|
+
);
|
|
159
|
+
} catch (error) {
|
|
160
|
+
throw new Error(getFirebaseErrorMessage(error), { cause: error });
|
|
161
|
+
}
|
|
162
|
+
localStorage.setItem(EMAIL_LINK_STORAGE_KEY, email);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
getRoutes = () => {
|
|
166
|
+
return [
|
|
167
|
+
{
|
|
168
|
+
path: "/verify-email",
|
|
169
|
+
element: (
|
|
170
|
+
<EmailVerificationUi
|
|
171
|
+
onResendVerification={async () => {
|
|
172
|
+
if (!this.auth.currentUser) {
|
|
173
|
+
throw new ZudokuError("User is not authenticated", {
|
|
174
|
+
title: "User not authenticated",
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
await sendEmailVerification(this.auth.currentUser);
|
|
178
|
+
}}
|
|
179
|
+
onCheckVerification={async () => {
|
|
180
|
+
if (!this.auth.currentUser) {
|
|
181
|
+
throw new ZudokuError("User is not authenticated", {
|
|
182
|
+
title: "User not authenticated",
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
await this.auth.currentUser.reload();
|
|
186
|
+
const isVerified = this.auth.currentUser.emailVerified;
|
|
187
|
+
|
|
188
|
+
if (isVerified) {
|
|
189
|
+
await this.auth.currentUser.getIdToken(true);
|
|
190
|
+
await this.setUserLoggedIn(this.auth.currentUser);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return isVerified;
|
|
194
|
+
}}
|
|
195
|
+
/>
|
|
196
|
+
),
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
path: "/reset-password",
|
|
200
|
+
element: (
|
|
201
|
+
<ZudokuPasswordResetUi
|
|
202
|
+
onPasswordReset={async (email: string) => {
|
|
203
|
+
try {
|
|
204
|
+
await sendPasswordResetEmail(this.auth, email);
|
|
205
|
+
} catch (error) {
|
|
206
|
+
throw Error(getFirebaseErrorMessage(error), { cause: error });
|
|
207
|
+
}
|
|
208
|
+
}}
|
|
209
|
+
/>
|
|
210
|
+
),
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
path: "/signin",
|
|
214
|
+
element: (
|
|
215
|
+
<ZudokuSignInUi
|
|
216
|
+
providers={this.providers}
|
|
217
|
+
enableUsernamePassword={this.enableUsernamePassword}
|
|
218
|
+
onOAuthSignIn={async (providerId: string) => {
|
|
219
|
+
useAuthState.setState({ isPending: true });
|
|
220
|
+
const provider = await getProviderForId(providerId);
|
|
221
|
+
if (!provider) {
|
|
222
|
+
throw new AuthorizationError(
|
|
223
|
+
`Provider ${providerId} not found`,
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
const result = await signInWithPopup(this.auth, provider);
|
|
227
|
+
useAuthState.setState({ isPending: false });
|
|
228
|
+
useAuthState.getState().setLoggedIn({
|
|
229
|
+
providerData: { type: "firebase", user: result.user },
|
|
230
|
+
profile: {
|
|
231
|
+
sub: result.user.uid,
|
|
232
|
+
email: result.user.email ?? undefined,
|
|
233
|
+
name: result.user.displayName ?? undefined,
|
|
234
|
+
emailVerified: result.user.emailVerified,
|
|
235
|
+
pictureUrl: result.user.photoURL ?? undefined,
|
|
236
|
+
},
|
|
237
|
+
});
|
|
238
|
+
}}
|
|
239
|
+
onUsernamePasswordSignIn={async (
|
|
240
|
+
email: string,
|
|
241
|
+
password: string,
|
|
242
|
+
) => {
|
|
243
|
+
try {
|
|
244
|
+
useAuthState.setState({ isPending: false });
|
|
245
|
+
const result = await signInWithEmailAndPassword(
|
|
246
|
+
this.auth,
|
|
247
|
+
email,
|
|
248
|
+
password,
|
|
249
|
+
);
|
|
250
|
+
await this.setUserLoggedIn(result.user);
|
|
251
|
+
} catch (error) {
|
|
252
|
+
throw Error(getFirebaseErrorMessage(error), { cause: error });
|
|
253
|
+
}
|
|
254
|
+
}}
|
|
255
|
+
enableEmailLink={this.enableEmailLink}
|
|
256
|
+
/>
|
|
257
|
+
),
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
path: "/signup",
|
|
261
|
+
element: (
|
|
262
|
+
<ZudokuSignUpUi
|
|
263
|
+
providers={this.providers}
|
|
264
|
+
enableUsernamePassword={this.enableUsernamePassword}
|
|
265
|
+
enableEmailLink={this.enableEmailLink}
|
|
266
|
+
onOAuthSignUp={async (providerId: string) => {
|
|
267
|
+
const provider = await getProviderForId(providerId);
|
|
268
|
+
if (!provider) {
|
|
269
|
+
throw new AuthorizationError(
|
|
270
|
+
`Provider ${providerId} not found`,
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
await signInWithPopup(this.auth, provider);
|
|
274
|
+
}}
|
|
275
|
+
onUsernamePasswordSignUp={async (
|
|
276
|
+
email: string,
|
|
277
|
+
password: string,
|
|
278
|
+
) => {
|
|
279
|
+
useAuthState.setState({ isPending: true });
|
|
280
|
+
const createUser = await createUserWithEmailAndPassword(
|
|
281
|
+
this.auth,
|
|
282
|
+
email,
|
|
283
|
+
password,
|
|
284
|
+
);
|
|
285
|
+
await this.setUserLoggedIn(createUser.user);
|
|
286
|
+
}}
|
|
287
|
+
/>
|
|
288
|
+
),
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
path: "/signin/email-link",
|
|
292
|
+
element: (
|
|
293
|
+
<EmailLinkSignInUi
|
|
294
|
+
onSubmit={async (email: string, redirectTo?: string) => {
|
|
295
|
+
await this.sendEmailLink(email, redirectTo);
|
|
296
|
+
}}
|
|
297
|
+
/>
|
|
298
|
+
),
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
path: "/signin/email-link-sent",
|
|
302
|
+
element: (
|
|
303
|
+
<ClientOnly>
|
|
304
|
+
<EmailLinkSentUi
|
|
305
|
+
onResendEmailLink={async () => {
|
|
306
|
+
const email = localStorage.getItem(EMAIL_LINK_STORAGE_KEY);
|
|
307
|
+
if (!email) {
|
|
308
|
+
throw new ZudokuError(
|
|
309
|
+
"No email address found. Please go back and try again.",
|
|
310
|
+
{ title: "Email not found" },
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
await this.sendEmailLink(email);
|
|
314
|
+
}}
|
|
315
|
+
/>
|
|
316
|
+
</ClientOnly>
|
|
317
|
+
),
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
path: "/signin/email-link-callback",
|
|
321
|
+
element: (
|
|
322
|
+
<ClientOnly>
|
|
323
|
+
<EmailLinkCallbackUi
|
|
324
|
+
onCompleteSignIn={async (email: string) => {
|
|
325
|
+
try {
|
|
326
|
+
const result = await signInWithEmailLink(
|
|
327
|
+
this.auth,
|
|
328
|
+
email,
|
|
329
|
+
window.location.href,
|
|
330
|
+
);
|
|
331
|
+
await this.setUserLoggedIn(result.user);
|
|
332
|
+
} catch (error) {
|
|
333
|
+
throw Error(getFirebaseErrorMessage(error), {
|
|
334
|
+
cause: error,
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
}}
|
|
338
|
+
isEmailLinkUrl={(url: string) =>
|
|
339
|
+
isSignInWithEmailLink(this.auth, url)
|
|
340
|
+
}
|
|
341
|
+
/>
|
|
342
|
+
</ClientOnly>
|
|
343
|
+
),
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
path: "/signout",
|
|
347
|
+
element: <SignOut />,
|
|
348
|
+
},
|
|
349
|
+
];
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
signOut = async () => {
|
|
353
|
+
await signOut(this.auth);
|
|
354
|
+
|
|
355
|
+
useAuthState.setState({
|
|
356
|
+
isAuthenticated: false,
|
|
357
|
+
isPending: false,
|
|
358
|
+
profile: undefined,
|
|
359
|
+
providerData: undefined,
|
|
360
|
+
});
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
onPageLoad = async () => {
|
|
364
|
+
const user = this.auth.currentUser;
|
|
365
|
+
|
|
366
|
+
if (user) {
|
|
367
|
+
await this.setUserLoggedIn(user);
|
|
368
|
+
} else {
|
|
369
|
+
useAuthState.setState({ isPending: false });
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
private async setUserLoggedIn(user: User) {
|
|
374
|
+
useAuthState.getState().setLoggedIn({
|
|
375
|
+
profile: {
|
|
376
|
+
sub: user.uid,
|
|
377
|
+
email: user.email ?? undefined,
|
|
378
|
+
name: user.displayName ?? undefined,
|
|
379
|
+
emailVerified: user.emailVerified,
|
|
380
|
+
pictureUrl: user.photoURL ?? undefined,
|
|
381
|
+
},
|
|
382
|
+
providerData: { type: "firebase", user },
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
const supabaseAuth: AuthenticationProviderInitializer<
|
|
388
|
+
FirebaseAuthenticationConfig
|
|
389
|
+
> = (options) => new FirebaseAuthenticationProvider(options);
|
|
390
|
+
|
|
391
|
+
export default supabaseAuth;
|
|
392
|
+
|
|
393
|
+
const getProviderForId = async (providerId: string) => {
|
|
394
|
+
switch (providerId) {
|
|
395
|
+
case "google": {
|
|
396
|
+
const { GoogleAuthProvider } = await import("firebase/auth");
|
|
397
|
+
return new GoogleAuthProvider();
|
|
398
|
+
}
|
|
399
|
+
case "github": {
|
|
400
|
+
const { GithubAuthProvider } = await import("firebase/auth");
|
|
401
|
+
return new GithubAuthProvider();
|
|
402
|
+
}
|
|
403
|
+
case "facebook": {
|
|
404
|
+
const { FacebookAuthProvider } = await import("firebase/auth");
|
|
405
|
+
return new FacebookAuthProvider();
|
|
406
|
+
}
|
|
407
|
+
case "twitter": {
|
|
408
|
+
const { TwitterAuthProvider } = await import("firebase/auth");
|
|
409
|
+
return new TwitterAuthProvider();
|
|
410
|
+
}
|
|
411
|
+
case "microsoft": {
|
|
412
|
+
const { OAuthProvider } = await import("firebase/auth");
|
|
413
|
+
return new OAuthProvider("microsoft.com");
|
|
414
|
+
}
|
|
415
|
+
case "apple": {
|
|
416
|
+
const { OAuthProvider } = await import("firebase/auth");
|
|
417
|
+
return new OAuthProvider("apple.com");
|
|
418
|
+
}
|
|
419
|
+
case "yahoo": {
|
|
420
|
+
const { OAuthProvider } = await import("firebase/auth");
|
|
421
|
+
return new OAuthProvider("yahoo.com");
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
throw new AuthorizationError(`Provider ${providerId} not found`);
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
const getFirebaseErrorMessage = (error: unknown): string => {
|
|
429
|
+
if (!(error instanceof Error)) {
|
|
430
|
+
return "An unexpected error occurred. Please try again.";
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
const errorCode = (error as { code?: string }).code;
|
|
434
|
+
|
|
435
|
+
switch (errorCode) {
|
|
436
|
+
case "auth/email-already-in-use":
|
|
437
|
+
return "The email address is already used by another account.";
|
|
438
|
+
case "auth/invalid-email":
|
|
439
|
+
return "That email address isn't correct.";
|
|
440
|
+
case "auth/operation-not-allowed":
|
|
441
|
+
return "This sign-in method is not enabled. Please contact support.";
|
|
442
|
+
case "auth/weak-password":
|
|
443
|
+
return "The password must be at least 6 characters long.";
|
|
444
|
+
case "auth/user-disabled":
|
|
445
|
+
return "This account has been disabled. Please contact support.";
|
|
446
|
+
case "auth/user-not-found":
|
|
447
|
+
return "That email address doesn't match an existing account.";
|
|
448
|
+
case "auth/wrong-password":
|
|
449
|
+
return "The email and password you entered don't match.";
|
|
450
|
+
case "auth/too-many-requests":
|
|
451
|
+
return "You have entered an incorrect password too many times. Please try again in a few minutes.";
|
|
452
|
+
case "auth/popup-blocked":
|
|
453
|
+
return "The sign-in popup was blocked by your browser. Please allow popups and try again.";
|
|
454
|
+
case "auth/popup-closed-by-user":
|
|
455
|
+
return "The sign-in popup was closed before completing. Please try again.";
|
|
456
|
+
case "auth/network-request-failed":
|
|
457
|
+
return "A network error has occurred. Please check your connection and try again.";
|
|
458
|
+
case "auth/requires-recent-login":
|
|
459
|
+
return "Please login again to perform this operation.";
|
|
460
|
+
case "auth/invalid-credential":
|
|
461
|
+
return "The credential is invalid or has expired. Please try again.";
|
|
462
|
+
case "auth/account-exists-with-different-credential":
|
|
463
|
+
return "An account already exists with the same email address but different sign-in credentials.";
|
|
464
|
+
case "auth/credential-already-in-use":
|
|
465
|
+
return "This credential is already associated with a different user account.";
|
|
466
|
+
case "auth/invalid-verification-code":
|
|
467
|
+
return "Wrong code. Try again.";
|
|
468
|
+
case "auth/invalid-verification-id":
|
|
469
|
+
return "The verification ID is invalid.";
|
|
470
|
+
case "auth/missing-verification-code":
|
|
471
|
+
return "Please enter the verification code.";
|
|
472
|
+
case "auth/user-cancelled":
|
|
473
|
+
return "Please authorize the required permissions to sign in.";
|
|
474
|
+
case "auth/expired-action-code":
|
|
475
|
+
return "This code has expired.";
|
|
476
|
+
case "auth/invalid-action-code":
|
|
477
|
+
return "The action code is invalid. This can happen if the code is malformed or has already been used.";
|
|
478
|
+
case "auth/unauthorized-domain":
|
|
479
|
+
return "This domain is not authorized for OAuth operations.";
|
|
480
|
+
default:
|
|
481
|
+
return (
|
|
482
|
+
error.message ||
|
|
483
|
+
"An error occurred during authentication. Please try again."
|
|
484
|
+
);
|
|
485
|
+
}
|
|
486
|
+
};
|