From d92908854bd8ca6f56602f4c387eec30cf201a34 Mon Sep 17 00:00:00 2001 From: Nikos Douvlis Date: Tue, 8 Feb 2022 23:45:49 +0200 Subject: [PATCH 01/58] chore(repo): Open source `@clerk/types` v3 --- packages/types/package.json | 2 +- packages/types/src/clerk.ts | 74 ++++----------------------- packages/types/src/externalAccount.ts | 8 +-- packages/types/src/index.ts | 1 + packages/types/src/json.ts | 47 +++++------------ packages/types/src/oauth.ts | 51 +++++------------- packages/types/src/session.ts | 4 -- packages/types/src/ssr.ts | 36 +++++++++++++ packages/types/src/user.ts | 5 -- packages/types/src/verification.ts | 7 +-- 10 files changed, 79 insertions(+), 156 deletions(-) create mode 100644 packages/types/src/ssr.ts diff --git a/packages/types/package.json b/packages/types/package.json index 00c7d10240e..52708cf888c 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@clerk/types", - "version": "1.25.4", + "version": "2.0.0-alpha.5", "license": "MIT", "description": "Typings for Clerk libraries.", "keywords": [ diff --git a/packages/types/src/clerk.ts b/packages/types/src/clerk.ts index 82df8ea0589..eea1175370d 100644 --- a/packages/types/src/clerk.ts +++ b/packages/types/src/clerk.ts @@ -1,3 +1,4 @@ +import { EnvironmentResource } from '.'; import { ClientResource } from './client'; import { DisplayThemeJSON } from './json'; import { ActiveSessionResource } from './session'; @@ -32,6 +33,9 @@ export interface Clerk { /** Current User. */ user?: UserResource | null; + /** Clerk environment. */ + __unstable__environment?: EnvironmentResource | null; + /** * Signs out the current user on single-session instances, or all users on multi-session instances. * @@ -171,33 +175,19 @@ export interface Clerk { */ navigate: CustomNavigation; - /** - * Redirects to the configured sign in URL. Retrieved from {@link environment}. - * @deprecated Use the new {@link Clerk.redirectToSignIn} instead; - * @param returnBack will appends a query string parameter to the sign in URL so the user can be redirected back to the current page. Defaults to false. - */ - redirectToSignIn(returnBack?: boolean): Promise; - /** * Redirects to the configured sign in URL. Retrieved from {@link environment}. * * @param opts A {@link RedirectOptions} object */ - redirectToSignIn(opts: RedirectOptions): Promise; - - /** - * Redirects to the configured sign up URL. Retrieved from {@link environment}. - * @deprecated Use the new {@link Clerk.redirectToSignIn} instead; - * @param returnBack will appends a query string parameter to the sign in URL so the user can be redirected back to the current page. Defaults to false. - */ - redirectToSignUp(returnBack?: boolean): Promise; + redirectToSignIn(opts?: RedirectOptions): Promise; /** * Redirects to the configured sign up URL. Retrieved from {@link environment}. * * @param opts A {@link RedirectOptions} object */ - redirectToSignUp(opts: RedirectOptions): Promise; + redirectToSignUp(opts?: RedirectOptions): Promise; /** * Redirects to the configured user profile URL. Retrieved from {@link environment}. @@ -272,12 +262,12 @@ export type CustomNavigation = (to: string) => Promise | void; export type ClerkThemeOptions = DeepSnakeToCamel>; export interface ClerkOptions { + authVersion?: 1 | 2; + navigate?: (to: string) => Promise | unknown; + polling?: boolean; selectInitialSession?: ( client: ClientResource, ) => ActiveSessionResource | null; - navigate?: (to: string) => Promise | unknown; - polling?: boolean; - authVersion?: 1 | 2; theme?: ClerkThemeOptions; } @@ -327,16 +317,6 @@ export type SignInProps = { * Used to fill the "Sign up" link in the SignUp component. */ signUpUrl?: string; - - /** - * @deprecated Use {@link SignInProps.afterSignInUrl} instead; - */ - afterSignIn?: string | null; - - /** - * @deprecated Use {@link SignInProps.signUpUrl} instead; - */ - signUpURL?: string; } & RedirectOptions; export type SignUpProps = { @@ -355,16 +335,6 @@ export type SignUpProps = { * Used to fill the "Sign in" link in the SignUp component. */ signInUrl?: string; - - /** - * @deprecated Use {@link SignUpProps.afterSignUpUrl} instead; - */ - afterSignUp?: string | null; - - /** - * @deprecated Use {@link SignUpProps.signInUrl} instead; - */ - signInURL?: string; } & RedirectOptions; export type UserProfileProps = { @@ -423,30 +393,6 @@ export type UserButtonProps = { * Multi-session mode only. */ afterSwitchSessionUrl?: string; - - /** - * @deprecated Use {@link UserButtonProps.afterSwitchSessionUrl} instead; - */ - afterSwitchSession?: string; - - /** - * @deprecated Use {@link UserButtonProps.userProfileUrl} instead; - */ - userProfileURL?: string; - - /** - * @deprecated Use {@link UserButtonProps.signInUrl} instead; - */ signInURL?: string; - - /** - * @deprecated Use {@link UserButtonProps.afterSignOutAllUrl} instead; - */ - afterSignOutAll?: string; - - /** - * @deprecated Use {@link UserButtonProps.afterSignOutOneUrl} instead; - */ - afterSignOutOne?: string; }; export interface HandleMagicLinkVerificationParams { @@ -464,7 +410,7 @@ export interface HandleMagicLinkVerificationParams { * Callback function to be executed after successful magic link * verification on another device. */ - onVerifiedOnOtherDevice?: Function; + onVerifiedOnOtherDevice?: () => void; } export interface AuthenticateWithMetamaskParams { diff --git a/packages/types/src/externalAccount.ts b/packages/types/src/externalAccount.ts index 80b3b9ab55f..7cc10def859 100644 --- a/packages/types/src/externalAccount.ts +++ b/packages/types/src/externalAccount.ts @@ -1,14 +1,16 @@ -import { OAuthProvider } from './oauth'; +import { OAuthProvider } from '.'; export interface ExternalAccountResource { id: string; + identificationId: string; provider: OAuthProvider; - externalId: string; + providerUserId: string; emailAddress: string; approvedScopes: string; firstName: string; lastName: string; - picture: string; + avatarUrl: string; + providerSlug: () => OAuthProvider; providerTitle: () => string; } diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 57129c35cc3..6d81f2f4a9c 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -21,5 +21,6 @@ export * from './token'; export * from './user'; export * from './utils'; export * from './verification'; +export * from './ssr'; export * from './web3'; export * from './web3Wallet'; diff --git a/packages/types/src/json.ts b/packages/types/src/json.ts index 1340daf328c..3f7689d5e3d 100644 --- a/packages/types/src/json.ts +++ b/packages/types/src/json.ts @@ -5,6 +5,7 @@ import { ToggleType, ToggleTypeWithRequire } from './authConfig'; import { EmailAddressVerificationStrategy } from './emailAddress'; import { OAuthStrategy } from './oauth'; +import { OAuthProvider } from './oauth'; import { SessionStatus } from './session'; import { IdentificationStrategy, @@ -181,6 +182,18 @@ export interface Web3WalletJSON extends ClerkResourceJSON { verification: VerificationJSON | null; } +export interface ExternalAccountJSON extends ClerkResourceJSON { + object: 'external_account'; + provider: OAuthProvider; + identification_id: string; + provider_user_id: string; + approved_scopes: string; + email_address: string; + first_name: string; + last_name: string; + avatar_url: string; +} + export interface UserJSON extends ClerkResourceJSON { object: 'user'; id: string; @@ -283,37 +296,3 @@ export interface SessionActivityJSON extends ClerkResourceJSON { country?: string; is_mobile?: boolean; } - -// TODO: Generalize external account JSON payload to simplify type declarations -export type ExternalAccountJSON = - | { - object: 'google_account'; - id: string; - google_id: string; - approved_scopes: string; - email_address: string; - given_name: string; - family_name: string; - picture: string; - } - | { - object: 'facebook_account'; - id: string; - facebook_id: string; - approved_scopes: string; - email_address: string; - first_name: string; - last_name: string; - picture: string; - } - | { - object: 'external_account'; - provider: string; - identification_id: string; - provider_user_id: string; - approved_scopes: string; - email_address: string; - first_name: string; - last_name: string; - avatar_url: string; - }; diff --git a/packages/types/src/oauth.ts b/packages/types/src/oauth.ts index 82136a75f6f..8987f0dcd8b 100644 --- a/packages/types/src/oauth.ts +++ b/packages/types/src/oauth.ts @@ -15,47 +15,20 @@ export type OAuthProvider = export type OAuthStrategy = `oauth_${OAuthProvider}`; -/** - * @deprecated `OAuthCallbacks` has been deprecated and will be removed soon. - * Use {@link AuthenticateWithRedirectParams}, SignIn.authenticateWithRedirect() or SignUp.authenticateWithRedirect() instead. - */ -export type OAuthCallbacks = { - callbackUrl: string; - callbackUrlComplete: string; -}; - export type AuthenticateWithRedirectParams = { /** * One of the supported OAuth providers you can use to authenticate with, eg 'oauth_google'. */ strategy: OAuthStrategy; -} & ( - | { - /** - * Full URL or path to the route that will complete the OAuth flow. - * Typically, this will be a simple `/sso-callback` route that calls `Clerk.handleRedirectCallback` - * or mounts the component. - */ - redirectUrl: string; - /** - * Full URL or path to navigate after the OAuth flow completes. - */ - redirectUrlComplete: string; - callbackUrl?: never; - callbackUrlComplete?: never; - } - | { - /** - * @deprecated `callbackUrl` has been deprecated and will be removed soon. - * Use {@link AuthenticateWithRedirectParams.redirectUrl} instead. - */ - callbackUrl: string; - /** - * @deprecated `callbackUrlComplete` has been deprecated and will be removed soon. - * Use {@link AuthenticateWithRedirectParams.redirectUrlComplete} instead. - */ - callbackUrlComplete: string; - redirectUrl?: never; - redirectUrlComplete?: never; - } -); +} & { + /** + * Full URL or path to the route that will complete the OAuth flow. + * Typically, this will be a simple `/sso-callback` route that calls `Clerk.handleRedirectCallback` + * or mounts the component. + */ + redirectUrl: string; + /** + * Full URL or path to navigate after the OAuth flow completes. + */ + redirectUrlComplete: string; +}; diff --git a/packages/types/src/session.ts b/packages/types/src/session.ts index 804af7e4f61..83d4517cf31 100644 --- a/packages/types/src/session.ts +++ b/packages/types/src/session.ts @@ -12,10 +12,6 @@ export interface SessionResource extends ClerkResource { publicUserData: PublicUserData; end: () => Promise; remove: () => Promise; - /** - * `revoke` has been deprecated and will be removed soon. - */ - revoke: () => Promise; touch: () => Promise; getToken: (options?: GetSessionTokenOptions) => Promise; createdAt: Date; diff --git a/packages/types/src/ssr.ts b/packages/types/src/ssr.ts new file mode 100644 index 00000000000..f4ad6567aef --- /dev/null +++ b/packages/types/src/ssr.ts @@ -0,0 +1,36 @@ +import { SessionJSON, UserJSON } from './json'; +import { SessionResource } from './session'; +import { UserResource } from './user'; + +type SsrSessionState = + | { + sessionId: null; + session: null; + } + | { + sessionId: string; + session: SessionType | undefined; + }; + +type SsrUserState = + | { + userId: null; + user: null; + } + | { + userId: string; + user: UserType | undefined; + }; + +export type SsrAuthData = SsrSessionState & + SsrUserState; +export type ClerkSsrState = SsrSessionState & + SsrUserState; +export type InitialState = + | { + user: undefined; + userId: undefined; + session: undefined; + sessionId: undefined; + } + | (SsrSessionState & SsrUserState); diff --git a/packages/types/src/user.ts b/packages/types/src/user.ts index dc4bb08a0ae..01488263c38 100644 --- a/packages/types/src/user.ts +++ b/packages/types/src/user.ts @@ -5,7 +5,6 @@ import { UserJSON } from './json'; import { PhoneNumberResource } from './phoneNumber'; import { ClerkResource } from './resource'; import { SessionWithActivitiesResource } from './session'; -import { GetUserTokenOptions,JWTService } from './token'; import { SnakeToCamel } from './utils'; import { Web3WalletResource } from './web3Wallet'; @@ -39,10 +38,6 @@ export interface UserResource extends ClerkResource { isPrimaryIdentification: ( ident: EmailAddressResource | PhoneNumberResource, ) => boolean; - getToken: ( - service: JWTService, - options?: GetUserTokenOptions, - ) => Promise; getSessions: () => Promise; setProfileImage: (file: Blob | File) => Promise; } diff --git a/packages/types/src/verification.ts b/packages/types/src/verification.ts index ba812675fca..87092f904cb 100644 --- a/packages/types/src/verification.ts +++ b/packages/types/src/verification.ts @@ -34,12 +34,7 @@ export type VerificationAttemptParams = | SignatureVerificationAttemptParam; export interface StartMagicLinkFlowParams { - redirectUrl?: string; - // DX: Deprecated v2.4.4 - /** - * @deprecated Use {@link StartMagicLinkFlowParams.redirectUrl} instead. - */ - callbackUrl?: string; + redirectUrl: string; } export type CreateMagicLinkFlowReturn = { From 16ffa6d8c2489283c4fe9afee65944cbf952eea7 Mon Sep 17 00:00:00 2001 From: Nikos Douvlis Date: Tue, 8 Feb 2022 23:46:39 +0200 Subject: [PATCH 02/58] chore(repo): Open source `@clerk/clerk-expo` v3 --- packages/expo/package.json | 4 ++-- packages/expo/src/index.ts | 1 + packages/expo/src/singleton.ts | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/expo/package.json b/packages/expo/package.json index 4683507ed84..624c4939495 100644 --- a/packages/expo/package.json +++ b/packages/expo/package.json @@ -26,8 +26,8 @@ "dev": "tsc -p tsconfig.build.json --watch" }, "dependencies": { - "@clerk/clerk-js": "^2.14.3", - "@clerk/clerk-react": "^2.11.4", + "@clerk/clerk-js": "^3.0.0-alpha.5", + "@clerk/clerk-react": "^3.0.0-alpha.6", "base-64": "^1.0.0" }, "devDependencies": { diff --git a/packages/expo/src/index.ts b/packages/expo/src/index.ts index 1bdaf3d65c0..44da01dd3f7 100644 --- a/packages/expo/src/index.ts +++ b/packages/expo/src/index.ts @@ -5,6 +5,7 @@ export { useSignIn, useSignUp, useUser, + useAuth, withClerk, withSession, withUser, diff --git a/packages/expo/src/singleton.ts b/packages/expo/src/singleton.ts index a5962113c40..7d269a7bd61 100644 --- a/packages/expo/src/singleton.ts +++ b/packages/expo/src/singleton.ts @@ -1,5 +1,5 @@ // @ts-ignore -import Clerk from '@clerk/clerk-js/dist/clerk.nocomponents'; +import Clerk from '@clerk/clerk-js/dist/clerk.headless'; import type { FapiRequestInit, FapiResponse, From 014d5f61319aef2740165128c8580b67e6b7800a Mon Sep 17 00:00:00 2001 From: Nikos Douvlis Date: Tue, 8 Feb 2022 23:47:45 +0200 Subject: [PATCH 03/58] chore(repo): Open source `@clerk/clerk-react` v3 --- packages/react/package.json | 4 +- .../src/components/SignInButton.test.tsx | 9 +- .../react/src/components/SignInButton.tsx | 11 +- .../SignInWithMetamaskButton.test.tsx | 7 +- .../components/SignInWithMetamaskButton.tsx | 2 +- .../src/components/SignOutButton.test.tsx | 10 +- .../react/src/components/SignOutButton.tsx | 2 +- .../src/components/SignUpButton.test.tsx | 10 +- .../react/src/components/SignUpButton.tsx | 11 +- .../src/components/controlComponents.tsx | 73 +++++---- packages/react/src/components/index.ts | 5 + .../react/src/components/uiComponents.tsx | 2 +- packages/react/src/components/withClerk.tsx | 50 ++++++ packages/react/src/components/withSession.tsx | 42 +++++ packages/react/src/components/withUser.tsx | 42 +++++ packages/react/src/contexts/AuthContext.ts | 6 + .../src/contexts/ClerkContextProvider.tsx | 109 +++++++++++++ .../src/contexts/ClerkContextWrapper.tsx | 54 ------- packages/react/src/contexts/ClerkProvider.tsx | 32 ++-- packages/react/src/contexts/ClientContext.tsx | 27 ++-- .../src/contexts/IsomorphicClerkContext.tsx | 121 +-------------- .../react/src/contexts/SessionContext.tsx | 146 +----------------- .../react/src/contexts/StructureContext.tsx | 30 ++-- packages/react/src/contexts/UserContext.tsx | 144 +---------------- packages/react/src/contexts/assertHelpers.ts | 15 +- packages/react/src/contexts/index.ts | 3 - packages/react/src/errors.ts | 3 + packages/react/src/hooks/index.ts | 4 + packages/react/src/hooks/useAuth.ts | 119 ++++++++++++++ packages/react/src/hooks/useClerk.ts | 10 ++ packages/react/src/hooks/useSession.ts | 63 ++++++++ packages/react/src/hooks/useUser.ts | 80 ++++++++++ packages/react/src/index.ts | 8 + packages/react/src/info.ts | 4 +- packages/react/src/isomorphicClerk.ts | 68 ++++---- packages/react/src/types.ts | 10 +- packages/react/src/useMagicLink.ts | 2 +- packages/react/src/utils/childrenUtils.tsx | 42 ++--- packages/react/src/utils/inBrowser.ts | 3 - packages/react/src/utils/inClientSide.ts | 3 + packages/react/src/utils/index.ts | 2 +- .../react/src/utils/makeContextAndHook.ts | 17 ++ packages/react/src/utils/scriptLoader.ts | 35 +++-- .../src/utils/useMaxAllowedInstancesGuard.tsx | 2 +- 44 files changed, 801 insertions(+), 641 deletions(-) create mode 100644 packages/react/src/components/withClerk.tsx create mode 100644 packages/react/src/components/withSession.tsx create mode 100644 packages/react/src/components/withUser.tsx create mode 100644 packages/react/src/contexts/AuthContext.ts create mode 100644 packages/react/src/contexts/ClerkContextProvider.tsx delete mode 100644 packages/react/src/contexts/ClerkContextWrapper.tsx create mode 100644 packages/react/src/hooks/index.ts create mode 100644 packages/react/src/hooks/useAuth.ts create mode 100644 packages/react/src/hooks/useClerk.ts create mode 100644 packages/react/src/hooks/useSession.ts create mode 100644 packages/react/src/hooks/useUser.ts delete mode 100644 packages/react/src/utils/inBrowser.ts create mode 100644 packages/react/src/utils/inClientSide.ts create mode 100644 packages/react/src/utils/makeContextAndHook.ts diff --git a/packages/react/package.json b/packages/react/package.json index 74eb571dc1a..4e935d54837 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,6 +1,6 @@ { "name": "@clerk/clerk-react", - "version": "2.11.4", + "version": "3.0.0-alpha.6", "license": "MIT", "description": "Clerk.dev React library", "keywords": [ @@ -28,7 +28,7 @@ "test": "jest" }, "dependencies": { - "@clerk/types": "^1.25.4", + "@clerk/types": "^2.0.0-alpha.5", "tslib": "^2.3.1" }, "devDependencies": { diff --git a/packages/react/src/components/SignInButton.test.tsx b/packages/react/src/components/SignInButton.test.tsx index da48881df50..8e1b1d8b9dd 100644 --- a/packages/react/src/components/SignInButton.test.tsx +++ b/packages/react/src/components/SignInButton.test.tsx @@ -1,4 +1,9 @@ -import { render, screen, userEvent, waitFor } from '@clerk/shared/testUtils'; +import { + render, + screen, + userEvent, + waitFor, +} from '@clerk/shared/utils/testUtils'; import React from 'react'; import { SignInButton } from './SignInButton'; @@ -10,7 +15,7 @@ const mockClerk = { redirectToSignIn: mockRedirectToSignIn, } as any; -jest.mock('../contexts', () => { +jest.mock('./withClerk', () => { return { withClerk: (Component: any) => (props: any) => { return ; diff --git a/packages/react/src/components/SignInButton.tsx b/packages/react/src/components/SignInButton.tsx index 2f3d0d9a1dc..001635239b8 100644 --- a/packages/react/src/components/SignInButton.tsx +++ b/packages/react/src/components/SignInButton.tsx @@ -1,22 +1,17 @@ import React from 'react'; -import { withClerk } from '../contexts'; import { SignInButtonProps, WithClerkProp } from '../types'; import { assertSingleChild, normalizeWithDefaultValue, safeExecute, } from '../utils'; +import { withClerk } from './withClerk'; export const SignInButton = withClerk( ({ clerk, children, ...props }: WithClerkProp) => { - const { - afterSignInUrl, - afterSignUpUrl, - redirectUrl, - mode, - ...rest - } = props; + const { afterSignInUrl, afterSignUpUrl, redirectUrl, mode, ...rest } = + props; children = normalizeWithDefaultValue(children, 'Sign in'); const child = assertSingleChild(children)('SignInButton'); diff --git a/packages/react/src/components/SignInWithMetamaskButton.test.tsx b/packages/react/src/components/SignInWithMetamaskButton.test.tsx index 4d2cfb6b22e..aca11ea0ca6 100644 --- a/packages/react/src/components/SignInWithMetamaskButton.test.tsx +++ b/packages/react/src/components/SignInWithMetamaskButton.test.tsx @@ -17,11 +17,10 @@ const mockClerk = { authenticateWithMetamask: mockAuthenticatewithMetamask, } as any; -jest.mock('../contexts', () => { +jest.mock('./withClerk', () => { return { - withClerk: (Component: any) => (props: any) => ( - - ), + withClerk: (Component: any) => (props: any) => + , }; }); diff --git a/packages/react/src/components/SignInWithMetamaskButton.tsx b/packages/react/src/components/SignInWithMetamaskButton.tsx index c13a2ffe0a8..5fa87d0caf7 100644 --- a/packages/react/src/components/SignInWithMetamaskButton.tsx +++ b/packages/react/src/components/SignInWithMetamaskButton.tsx @@ -1,12 +1,12 @@ import React from 'react'; -import { withClerk } from '../contexts'; import { SignInWithMetamaskButtonProps, WithClerkProp } from '../types'; import { assertSingleChild, normalizeWithDefaultValue, safeExecute, } from '../utils'; +import { withClerk } from './withClerk'; export const SignInWithMetamaskButton = withClerk( ({ diff --git a/packages/react/src/components/SignOutButton.test.tsx b/packages/react/src/components/SignOutButton.test.tsx index 194332cd37c..c618eae1720 100644 --- a/packages/react/src/components/SignOutButton.test.tsx +++ b/packages/react/src/components/SignOutButton.test.tsx @@ -1,5 +1,9 @@ -import { render, screen, waitFor } from '@clerk/shared/testUtils'; -import { userEvent } from '@clerk/shared/utils/testUtils'; +import { + render, + screen, + userEvent, + waitFor, +} from '@clerk/shared/utils/testUtils'; import React from 'react'; import { SignOutButton } from './SignOutButton'; @@ -11,7 +15,7 @@ const mockClerk = { signOutOne: mockSignOutOne, } as any; -jest.mock('../contexts', () => { +jest.mock('./withClerk', () => { return { withClerk: (Component: any) => (props: any) => { return ; diff --git a/packages/react/src/components/SignOutButton.tsx b/packages/react/src/components/SignOutButton.tsx index 38c1b740d7c..0b2cd134046 100644 --- a/packages/react/src/components/SignOutButton.tsx +++ b/packages/react/src/components/SignOutButton.tsx @@ -1,12 +1,12 @@ import React from 'react'; -import { withClerk } from '../contexts'; import { SignOutButtonProps, WithClerkProp } from '../types'; import { assertSingleChild, normalizeWithDefaultValue, safeExecute, } from '../utils'; +import { withClerk } from './withClerk'; export const SignOutButton = withClerk( ({ diff --git a/packages/react/src/components/SignUpButton.test.tsx b/packages/react/src/components/SignUpButton.test.tsx index 19f601fa5ae..9a2af3bf66a 100644 --- a/packages/react/src/components/SignUpButton.test.tsx +++ b/packages/react/src/components/SignUpButton.test.tsx @@ -1,5 +1,9 @@ -import { render, screen, waitFor } from '@clerk/shared/testUtils'; -import { userEvent } from '@clerk/shared/utils/testUtils'; +import { + render, + screen, + userEvent, + waitFor, +} from '@clerk/shared/utils/testUtils'; import React from 'react'; import { SignUpButton } from './SignUpButton'; @@ -11,7 +15,7 @@ const mockClerk = { redirectToSignUp: mockRedirectToSignUp, } as any; -jest.mock('../contexts', () => { +jest.mock('./withClerk', () => { return { withClerk: (Component: any) => (props: any) => { return ; diff --git a/packages/react/src/components/SignUpButton.tsx b/packages/react/src/components/SignUpButton.tsx index b2118182334..878c1e52bc8 100644 --- a/packages/react/src/components/SignUpButton.tsx +++ b/packages/react/src/components/SignUpButton.tsx @@ -1,22 +1,17 @@ import React from 'react'; -import { withClerk } from '../contexts'; import { SignUpButtonProps, WithClerkProp } from '../types'; import { assertSingleChild, normalizeWithDefaultValue, safeExecute, } from '../utils'; +import { withClerk } from './withClerk'; export const SignUpButton = withClerk( ({ clerk, children, ...props }: WithClerkProp) => { - const { - afterSignInUrl, - afterSignUpUrl, - redirectUrl, - mode, - ...rest - } = props; + const { afterSignInUrl, afterSignUpUrl, redirectUrl, mode, ...rest } = + props; children = normalizeWithDefaultValue(children, 'Sign up'); const child = assertSingleChild(children)('SignUpButton'); diff --git a/packages/react/src/components/controlComponents.tsx b/packages/react/src/components/controlComponents.tsx index 08c22e6c0ee..2b11b5137f6 100644 --- a/packages/react/src/components/controlComponents.tsx +++ b/packages/react/src/components/controlComponents.tsx @@ -1,64 +1,74 @@ import { HandleOAuthCallbackParams } from '@clerk/types'; import React from 'react'; -import { withClerk, withUser } from '../contexts'; -import { useUserContext } from '../contexts/UserContext'; +import { useAuthContext } from '../contexts/AuthContext'; +import { useIsomorphicClerkContext } from '../contexts/IsomorphicClerkContext'; +import { useSessionContext } from '../contexts/SessionContext'; +import { LoadedGuarantee } from '../contexts/StructureContext'; import type { RedirectToProps, WithClerkProp } from '../types'; +import { withClerk } from './withClerk'; -export const SignedIn: React.FC = withUser(({ children }) => { - return <>{children}; -}, 'SignedIn'); +export const SignedIn: React.FC = ({ children }) => { + const { userId } = useAuthContext(); + if (userId) { + return <>{children}; + } + return null; +}; -export const SignedOut: React.FC = withClerk(({ children }) => { - const userCtx = useUserContext(); - return userCtx.value === null ? <>{children} : null; -}, 'SignedOut'); +export const SignedOut: React.FC = ({ children }) => { + const { userId } = useAuthContext(); + if (userId === null) { + return <>{children}; + } + return null; +}; -export const ClerkLoaded: React.FC = withClerk(({ children }) => { - return <>{children}; -}, 'ClerkLoaded'); +export const ClerkLoaded: React.FC = ({ children }) => { + const isomorphicClerk = useIsomorphicClerkContext(); + if (!isomorphicClerk.loaded) { + return null; + } + return {children}; +}; export const ClerkLoading: React.FC = ({ children }) => { - const userCtx = useUserContext(); - return userCtx.value === undefined ? <>{children} : null; + const isomorphicClerk = useIsomorphicClerkContext(); + if (isomorphicClerk.loaded) { + return null; + } + return <>{children}; }; -// DX: returnBack deprecated <=2.4.2 -// Deprecate the boolean type before removing returnBack export const RedirectToSignIn = withClerk( ({ clerk, ...props }: WithClerkProp) => { - const { returnBack, afterSignUpUrl, redirectUrl, afterSignInUrl } = props; - const redirectOptions = { afterSignUpUrl, redirectUrl, afterSignInUrl }; - const { client, session } = clerk; // TODO: Remove temp use of __unstable__environment const { __unstable__environment } = clerk as any; const hasActiveSessions = client.activeSessions && client.activeSessions.length > 0; + React.useEffect(() => { if (session === null && hasActiveSessions && __unstable__environment) { const { afterSignOutOneUrl } = __unstable__environment.displayConfig; void clerk.navigate(afterSignOutOneUrl); } else { - void clerk.redirectToSignIn((returnBack || redirectOptions) as any); + void clerk.redirectToSignIn(props); } }, []); + return null; }, 'RedirectToSignIn', ); -// DX: returnBack deprecated <=2.4.2 -// Deprecate the boolean type before removing returnBack export const RedirectToSignUp = withClerk( ({ clerk, ...props }: WithClerkProp) => { - const { returnBack, afterSignUpUrl, redirectUrl, afterSignInUrl } = props; - const redirectOptions = { afterSignUpUrl, redirectUrl, afterSignInUrl }; - React.useEffect(() => { - void clerk.redirectToSignUp((returnBack || redirectOptions) as any); + void clerk.redirectToSignUp(props); }, []); + return null; }, 'RedirectToSignUp', @@ -68,6 +78,7 @@ export const RedirectToUserProfile = withClerk(({ clerk }) => { React.useEffect(() => { clerk.redirectToUserProfile(); }, []); + return null; }, 'RedirectToUserProfile'); @@ -79,7 +90,17 @@ export const AuthenticateWithRedirectCallback = withClerk( React.useEffect(() => { void clerk.handleRedirectCallback(handleRedirectCallbackParams); }, []); + return null; }, 'AuthenticateWithRedirectCallback', ); + +export const MultisessionAppSupport: React.FC = ({ children }) => { + const session = useSessionContext(); + return ( + + {children} + + ); +}; diff --git a/packages/react/src/components/index.ts b/packages/react/src/components/index.ts index 4c84a1d05f2..2b88eb4a74f 100644 --- a/packages/react/src/components/index.ts +++ b/packages/react/src/components/index.ts @@ -9,8 +9,13 @@ export { RedirectToSignUp, RedirectToUserProfile, AuthenticateWithRedirectCallback, + MultisessionAppSupport, } from './controlComponents'; +export * from './withClerk'; +export * from './withUser'; +export * from './withSession'; + export * from './SignInButton'; export * from './SignUpButton'; export * from './SignOutButton'; diff --git a/packages/react/src/components/uiComponents.tsx b/packages/react/src/components/uiComponents.tsx index 4f13571f538..141de232376 100644 --- a/packages/react/src/components/uiComponents.tsx +++ b/packages/react/src/components/uiComponents.tsx @@ -6,8 +6,8 @@ import { } from '@clerk/types'; import React from 'react'; -import { withClerk } from '../contexts'; import { MountProps, WithClerkProp } from '../types'; +import { withClerk } from './withClerk'; // README: should be a class pure component in order for mount and unmount // lifecycle props to be invoked correctly. Replacing the class component with a diff --git a/packages/react/src/components/withClerk.tsx b/packages/react/src/components/withClerk.tsx new file mode 100644 index 00000000000..d411ef987da --- /dev/null +++ b/packages/react/src/components/withClerk.tsx @@ -0,0 +1,50 @@ +import { LoadedClerk } from '@clerk/types'; +import React from 'react'; + +import { useIsomorphicClerkContext } from '../contexts/IsomorphicClerkContext'; +import { LoadedGuarantee } from '../contexts/StructureContext'; +import { hocChildrenNotAFunctionError } from '../errors'; + +export const withClerk =

( + Component: React.ComponentType

, + displayName?: string, +) => { + displayName = + displayName || Component.displayName || Component.name || 'Component'; + Component.displayName = displayName; + const HOC = (props: Omit) => { + const clerk = useIsomorphicClerkContext(); + + if (!clerk.loaded) { + return null; + } + + return ( + + + + ); + }; + HOC.displayName = `withClerk(${displayName})`; + return HOC; +}; + +export const WithClerk: React.FC<{ + children: (clerk: LoadedClerk) => React.ReactNode; +}> = ({ children }) => { + const clerk = useIsomorphicClerkContext(); + + if (typeof children !== 'function') { + throw new Error(hocChildrenNotAFunctionError); + } + + if (!clerk.loaded) { + return null; + } + + return ( + + {children(clerk as unknown as LoadedClerk)} + + ); +}; diff --git a/packages/react/src/components/withSession.tsx b/packages/react/src/components/withSession.tsx new file mode 100644 index 00000000000..80dad74e062 --- /dev/null +++ b/packages/react/src/components/withSession.tsx @@ -0,0 +1,42 @@ +import { SessionResource } from '@clerk/types'; +import React from 'react'; + +import { useSessionContext } from '../contexts/SessionContext'; +import { hocChildrenNotAFunctionError } from '../errors'; + +export const withSession =

( + Component: React.ComponentType

, + displayName?: string, +) => { + displayName = + displayName || Component.displayName || Component.name || 'Component'; + Component.displayName = displayName; + const HOC: React.FC> = (props: Omit) => { + const session = useSessionContext(); + + if (!session) { + return null; + } + + return ; + }; + + HOC.displayName = `withSession(${displayName})`; + return HOC; +}; + +export const WithSession: React.FC<{ + children: (session: SessionResource) => React.ReactNode; +}> = ({ children }) => { + const session = useSessionContext(); + + if (typeof children !== 'function') { + throw new Error(hocChildrenNotAFunctionError); + } + + if (!session) { + return null; + } + + return <>{children(session)}; +}; diff --git a/packages/react/src/components/withUser.tsx b/packages/react/src/components/withUser.tsx new file mode 100644 index 00000000000..817d8916bf2 --- /dev/null +++ b/packages/react/src/components/withUser.tsx @@ -0,0 +1,42 @@ +import { UserResource } from '@clerk/types'; +import React from 'react'; + +import { useUserContext } from '../contexts/UserContext'; +import { hocChildrenNotAFunctionError } from '../errors'; + +export const withUser =

( + Component: React.ComponentType

, + displayName?: string, +) => { + displayName = + displayName || Component.displayName || Component.name || 'Component'; + Component.displayName = displayName; + const HOC: React.FC> = (props: Omit) => { + const user = useUserContext(); + + if (!user) { + return null; + } + + return ; + }; + + HOC.displayName = `withUser(${displayName})`; + return HOC; +}; + +export const WithUser: React.FC<{ + children: (user: UserResource) => React.ReactNode; +}> = ({ children }) => { + const user = useUserContext(); + + if (typeof children !== 'function') { + throw new Error(hocChildrenNotAFunctionError); + } + + if (!user) { + return null; + } + + return <>{children(user)}; +}; diff --git a/packages/react/src/contexts/AuthContext.ts b/packages/react/src/contexts/AuthContext.ts new file mode 100644 index 00000000000..dfdc1ef57a5 --- /dev/null +++ b/packages/react/src/contexts/AuthContext.ts @@ -0,0 +1,6 @@ +import { makeContextAndHook } from '../utils/makeContextAndHook'; + +export const [AuthContext, useAuthContext] = makeContextAndHook<{ + userId: string | null | undefined; + sessionId: string | null | undefined; +}>('AuthContext'); diff --git a/packages/react/src/contexts/ClerkContextProvider.tsx b/packages/react/src/contexts/ClerkContextProvider.tsx new file mode 100644 index 00000000000..9e396313529 --- /dev/null +++ b/packages/react/src/contexts/ClerkContextProvider.tsx @@ -0,0 +1,109 @@ +import { + ActiveSessionResource, + ClientResource, + InitialState, + Resources, + UserResource, +} from '@clerk/types'; +import React from 'react'; + +import IsomorphicClerk from '../isomorphicClerk'; +import { AuthContext } from './AuthContext'; +import { ClientContext } from './ClientContext'; +import { IsomorphicClerkContext } from './IsomorphicClerkContext'; +import { SessionContext } from './SessionContext'; +import { UserContext } from './UserContext'; + +type ClerkContextWrapperProps = { + isomorphicClerk: IsomorphicClerk; + children: React.ReactNode; + clerkLoaded: boolean; +}; + +type ClerkContextProviderState = Resources; + +export function ClerkContextProvider({ + isomorphicClerk, + children, + clerkLoaded, +}: ClerkContextWrapperProps): JSX.Element | null { + const clerk = isomorphicClerk; + + const initialState = clerk.initialState; + const [state, setState] = React.useState({ + client: clerk.client as ClientResource, + session: clerk.session, + user: clerk.user, + }); + const derivedState = deriveState(clerkLoaded, state, initialState); + + React.useEffect(() => { + return clerk.addListener(e => setState({ ...e })); + }, []); + + const clerkCtx = React.useMemo(() => ({ value: clerk }), [clerkLoaded]); + const clientCtx = React.useMemo( + () => ({ value: state.client }), + [state.client], + ); + + const authCtx = React.useMemo(() => { + return { + value: { sessionId: derivedState.sessionId, userId: derivedState.userId }, + }; + }, [derivedState.sessionId, derivedState.userId]); + + const userCtx = React.useMemo(() => { + return { value: derivedState.user }; + }, [derivedState.userId, derivedState.user]); + + const sessionCtx = React.useMemo(() => { + return { value: derivedState.session }; + }, [derivedState.sessionId, derivedState.session]); + + return ( + + + + + + {children} + + + + + + ); +} + +// This should be provided from isomorphicClerk +// TODO: move inside isomorphicClerk +function deriveState( + clerkLoaded: boolean, + state: ClerkContextProviderState, + initialState: InitialState | undefined, +): { + userId: string | null | undefined; + sessionId: string | null | undefined; + session: ActiveSessionResource | null | undefined; + user: UserResource | null | undefined; +} { + if (!clerkLoaded && initialState) { + const userId = initialState.userId; + // TODO: Instantiate an actual user resource + const user = initialState.user as any as UserResource; + const sessionId = initialState.sessionId; + // TODO: Instantiate an actual session resource + const session = initialState.session as any as ActiveSessionResource; + return { sessionId, session, userId, user }; + } + const userId: string | null | undefined = state.user + ? state.user.id + : state.user; + const user = state.user; + const sessionId: string | null | undefined = state.session + ? state.session.id + : state.session; + const session = state.session; + return { sessionId, session, userId, user }; +} diff --git a/packages/react/src/contexts/ClerkContextWrapper.tsx b/packages/react/src/contexts/ClerkContextWrapper.tsx deleted file mode 100644 index 88a8cddc06c..00000000000 --- a/packages/react/src/contexts/ClerkContextWrapper.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { ClientResource, Resources } from '@clerk/types'; -import React from 'react'; - -import IsomorphicClerk from '../isomorphicClerk'; -import { ClientContext } from './ClientContext'; -import { IsomorphicClerkContext } from './IsomorphicClerkContext'; -import { SessionContext } from './SessionContext'; -import { UserContext } from './UserContext'; - -type ClerkContextWrapperProps = { - isomorphicClerk: IsomorphicClerk; - children: React.ReactNode; - clerkLoaded: boolean; -}; - -type ClerkContextProviderState = Resources; - -export function ClerkContextWrapper({ - isomorphicClerk, - children, - clerkLoaded, -}: ClerkContextWrapperProps): JSX.Element | null { - const clerk = isomorphicClerk; - - const [state, setState] = React.useState({ - client: clerk.client as ClientResource, - session: clerk.session, - user: clerk.user, - }); - - React.useEffect(() => { - return clerk.addListener(e => setState({ ...e })); - }, []); - - const { client, session, user } = state; - const clerkCtx = React.useMemo(() => ({ value: clerk }), [clerkLoaded]); - const clientCtx = React.useMemo(() => ({ value: client }), [client]); - const sessionCtx = React.useMemo(() => ({ value: session }), [session]); - const userCtx = React.useMemo(() => ({ value: user }), [user]); - - return ( - - - - - - {children} - - - - - - ); -} diff --git a/packages/react/src/contexts/ClerkProvider.tsx b/packages/react/src/contexts/ClerkProvider.tsx index 61c51afffdb..ff31f06268d 100644 --- a/packages/react/src/contexts/ClerkProvider.tsx +++ b/packages/react/src/contexts/ClerkProvider.tsx @@ -1,41 +1,45 @@ +import { InitialState } from '@clerk/types'; import React, { useEffect, useMemo, useState } from 'react'; import { multipleClerkProvidersError } from '../errors'; import IsomorphicClerk from '../isomorphicClerk'; import type { ClerkProp, IsomorphicClerkOptions } from '../types'; import { withMaxAllowedInstancesGuard } from '../utils'; -import { ClerkContextWrapper } from './ClerkContextWrapper'; +import { ClerkContextProvider } from './ClerkContextProvider'; import { StructureContext, StructureContextStates } from './StructureContext'; export interface ClerkProviderProps extends IsomorphicClerkOptions { frontendApi?: string; Clerk?: ClerkProp; + initialState?: InitialState; } function ClerkProviderBase(props: React.PropsWithChildren) { + const [clerkLoaded, setClerkLoaded] = useState(false); const clerk = useMemo(() => { - const { frontendApi = '', Clerk: ClerkConstructor, ...rest } = props; - return new IsomorphicClerk(frontendApi, rest, ClerkConstructor); + const { + frontendApi = '', + Clerk: ClerkConstructor, + initialState, + ...rest + } = props; + return new IsomorphicClerk( + frontendApi, + rest, + ClerkConstructor, + initialState, + ); }, []); - const [clerkLoaded, setClerkLoaded] = useState(false); - useEffect(() => { void clerk.loadClerkJS().then(() => setClerkLoaded(true)); }, []); return ( - {clerk instanceof IsomorphicClerk && clerk.ssrData && ( - + +`; +}; + +export function Interstitial({ frontendApi, version }: { frontendApi: string; version: string }) { + return ; } diff --git a/packages/remix/src/errors.ts b/packages/remix/src/errors.ts index c0e5a79da4b..dde153ba8d3 100644 --- a/packages/remix/src/errors.ts +++ b/packages/remix/src/errors.ts @@ -71,7 +71,7 @@ export const getAuthInterstitialErrorRendered = createErrorMessage( ); export const noFrontendApiError = createErrorMessage(` -The CLERK_FRONTEND_API1 environment variable must be set before using Clerk. -During development, grab the Frontend Api value from the Clerk dashboard, create an .env file and set the CLERK_FRONTEND_API key. +The CLERK_FRONTEND_API environment variable must be set before using Clerk. +During development, grab the Frontend Api value from the Clerk Dashboard, create an .env file and set the CLERK_FRONTEND_API key. For production apps, please consult the Remix documentation on environment variables. `); diff --git a/packages/remix/src/ssr/getAuth.ts b/packages/remix/src/ssr/getAuth.ts index 34d7f02b4ae..56b93bc8522 100644 --- a/packages/remix/src/ssr/getAuth.ts +++ b/packages/remix/src/ssr/getAuth.ts @@ -12,9 +12,9 @@ export async function getAuth(argsOrReq: Request | LoaderFunctionArgs): GetAuthR throw new Error(noRequestPassedInGetAuth); } const request = 'request' in argsOrReq ? argsOrReq.request : argsOrReq; - const { authData, interstitial } = await getAuthData(request); + const { authData, showInterstitial } = await getAuthData(request); - if (interstitial || !authData) { + if (showInterstitial || !authData) { throw json(EMPTY_INTERSTITIAL_RESPONSE); } diff --git a/packages/remix/src/ssr/getAuthData.ts b/packages/remix/src/ssr/getAuthData.ts index 5fda8ecdd25..557b3783299 100644 --- a/packages/remix/src/ssr/getAuthData.ts +++ b/packages/remix/src/ssr/getAuthData.ts @@ -3,7 +3,7 @@ import Clerk, { sessions, users } from '@clerk/clerk-sdk-node'; import { GetSessionTokenOptions } from '@clerk/types'; import { RootAuthLoaderOptions } from './types'; -import { extractInterstitialHtmlContent, parseCookies } from './utils'; +import { parseCookies } from './utils'; export type AuthData = { sessionId: string | null; @@ -16,7 +16,7 @@ export type AuthData = { export async function getAuthData( req: Request, opts: RootAuthLoaderOptions = {}, -): Promise<{ authData: AuthData | null; interstitial?: string }> { +): Promise<{ authData: AuthData | null; showInterstitial?: boolean }> { const { loadSession, loadUser } = opts; const { headers } = req; const cookies = parseCookies(req); @@ -37,7 +37,7 @@ export async function getAuthData( }; try { - const { status, sessionClaims, interstitial } = await Clerk.base.getAuthState({ + const { status, sessionClaims } = await Clerk.base.getAuthState({ cookieToken: cookies['__session'], clientUat: cookies['__client_uat'], headerToken: headers.get('authorization')?.replace('Bearer ', ''), @@ -47,11 +47,11 @@ export async function getAuthData( forwardedHost: headers.get('x-forwarded-host') as string, referrer: headers.get('referer'), userAgent: headers.get('user-agent') as string, - fetchInterstitial: () => Clerk.fetchInterstitial(), + fetchInterstitial: () => Promise.resolve(''), }); if (status === AuthStatus.Interstitial) { - return { authData: null, interstitial: extractInterstitialHtmlContent(interstitial) }; + return { authData: null, showInterstitial: true }; } if (status === AuthStatus.SignedOut || !sessionClaims) { diff --git a/packages/remix/src/ssr/rootAuthLoader.ts b/packages/remix/src/ssr/rootAuthLoader.ts index 1b9d26a3706..fc27ffa3ccc 100644 --- a/packages/remix/src/ssr/rootAuthLoader.ts +++ b/packages/remix/src/ssr/rootAuthLoader.ts @@ -3,7 +3,7 @@ import { json } from '@remix-run/server-runtime'; import { invalidRootLoaderCallbackResponseReturn, invalidRootLoaderCallbackReturn } from '../errors'; import { getAuthData } from './getAuthData'; import { LoaderFunctionArgs, LoaderFunctionReturn, RootAuthLoaderCallback, RootAuthLoaderOptions } from './types'; -import { assertObject, injectAuthIntoArgs, isResponse, sanitizeAuthData, wrapClerkState } from './utils'; +import { assertObject, injectAuthIntoArgs, isRedirect, isResponse, sanitizeAuthData, wrapClerkState } from './utils'; export async function rootAuthLoader( args: LoaderFunctionArgs, @@ -27,11 +27,10 @@ export async function rootAuthLoader( : {}; const frontendApi = process.env.CLERK_FRONTEND_API || opts.frontendApi; + const { authData, showInterstitial } = await getAuthData(args.request, opts); - const { authData, interstitial } = await getAuthData(args.request, opts); - - if (interstitial) { - throw json(wrapClerkState({ __clerk_ssr_interstitial: interstitial })); + if (showInterstitial) { + throw json(wrapClerkState({ __clerk_ssr_interstitial: showInterstitial, __frontendApi: frontendApi })); } if (!callback) { @@ -43,7 +42,7 @@ export async function rootAuthLoader( // Pass through custom responses if (isResponse(callbackResult)) { - if (callbackResult.status >= 300 && callbackResult.status < 400) { + if (isRedirect(callbackResult)) { return callbackResult; } throw new Error(invalidRootLoaderCallbackResponseReturn); diff --git a/packages/remix/src/ssr/utils.ts b/packages/remix/src/ssr/utils.ts index bbbed84c741..2fee5604a41 100644 --- a/packages/remix/src/ssr/utils.ts +++ b/packages/remix/src/ssr/utils.ts @@ -3,8 +3,6 @@ import cookie from 'cookie'; import { AuthData } from './getAuthData'; import { LoaderFunctionArgs, LoaderFunctionArgsWithAuth } from './types'; -const INTER_HTML_CONTENT_REGEX = /([\s\S.]*)<\/html>/; - /** * Wraps obscured clerk internals with a readable `clerkState` key. * This is intended to be passed by the user into @@ -15,19 +13,6 @@ export const wrapClerkState = (data: any) => { return { clerkState: { __internal_clerk_state: { ...data } } }; }; -/** - * Extracts the content inside the tags of the interstitial page - * - * @internal - */ -export const extractInterstitialHtmlContent = (interstitial?: string) => { - try { - return (interstitial || '').match(INTER_HTML_CONTENT_REGEX)![1]; - } catch (e) { - throw new Error('This is a Clerk bug; Please report'); - } -}; - /** * Inject the `auth` attribute to the SSR provided context (ctx) object and * `user` and `session` attribute to the request (req) object. @@ -72,6 +57,13 @@ export function isResponse(value: any): value is Response { ); } +/** + * @internal + */ +export function isRedirect(res: Response): boolean { + return res.status >= 300 && res.status < 400; +} + /** * @internal */ From 4ef06cc2873a76a32b29a7e54f6cde5bbee43aa6 Mon Sep 17 00:00:00 2001 From: Nikos Douvlis Date: Tue, 8 Mar 2022 13:16:27 +0200 Subject: [PATCH 43/58] chore(repo): Update GitHub templates --- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- .github/ISSUE_TEMPLATE/feature_request.md | 2 +- .github/PULL_REQUEST_TEMPLATE.md | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 97f0a92770d..d1fd0a58738 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -19,7 +19,7 @@ labels: 'Status: Triage' - [ ] `@clerk/clerk-js` - [ ] `@clerk/clerk-react` - [ ] `@clerk/nextjs` -- [ ] `@clerk/clerk-remix` +- [ ] `@clerk/remix` - [ ] `@clerk/clerk-expo` - [ ] `@clerk/backend-core` - [ ] `@clerk/clerk-sdk-node` diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index bad473c94b7..e0f5cc53593 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -12,7 +12,7 @@ labels: 'Status: Feature Request' - [ ] `@clerk/clerk-js` - [ ] `@clerk/clerk-react` - [ ] `@clerk/nextjs` -- [ ] `@clerk/clerk-remix` +- [ ] `@clerk/remix` - [ ] `@clerk/clerk-expo` - [ ] `@clerk/backend-core` - [ ] `@clerk/clerk-sdk-node` diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 8a8a764843a..ec5c3ce53f2 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -11,6 +11,7 @@ - [ ] `@clerk/clerk-js` - [ ] `@clerk/clerk-react` - [ ] `@clerk/nextjs` +- [ ] `@clerk/remix` - [ ] `@clerk/types` - [ ] `@clerk/clerk-expo` - [ ] `@clerk/backend-core` From 1dddf134c2342480d2b406220acffb5fdd54a400 Mon Sep 17 00:00:00 2001 From: Peter Perlepes Date: Tue, 8 Mar 2022 15:29:49 +0200 Subject: [PATCH 44/58] fix(backend-core): Correctly use the forwarded-proto value --- .../src/__tests__/utils/request.test.ts | 15 +++++++++++++++ packages/backend-core/src/util/request.ts | 13 ++++++------- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/packages/backend-core/src/__tests__/utils/request.test.ts b/packages/backend-core/src/__tests__/utils/request.test.ts index b4b70260946..bac2a5c331c 100644 --- a/packages/backend-core/src/__tests__/utils/request.test.ts +++ b/packages/backend-core/src/__tests__/utils/request.test.ts @@ -25,6 +25,21 @@ describe('check cross-origin-referrer request utility', () => { expect(checkCrossOriginReferrer({ referrerURL, host })).toEqual(true); }); + test('is CO when HTTPS to HTTP with present x-forwarded-proto', () => { + const referrerURL = new URL('https://localhost'); + const host = new URL('http://someserver').host; + const forwardedHost = new URL('http://localhost').host; + const forwardedProto = 'http'; + expect( + checkCrossOriginReferrer({ + referrerURL, + host, + forwardedHost, + forwardedProto, + }), + ).toEqual(true); + }); + test('is CO when HTTPS to HTTP with forwarded port', () => { const referrerURL = new URL('https://localhost'); const host = new URL('http://localhost').host; diff --git a/packages/backend-core/src/util/request.ts b/packages/backend-core/src/util/request.ts index 47ad749f814..cac5fdf4396 100644 --- a/packages/backend-core/src/util/request.ts +++ b/packages/backend-core/src/util/request.ts @@ -18,15 +18,14 @@ export function checkCrossOriginReferrer({ forwardedPort?: string | null; forwardedProto?: string | null; }) { + if (forwardedProto && forwardedProto !== referrerURL.protocol) { + return true; + } + /* The forwarded host prioritised over host to be checked against the referrer. */ - const finalURL = convertHostHeaderValueToURL( - forwardedHost ? forwardedHost : host, - ); + const finalURL = convertHostHeaderValueToURL(forwardedHost || host); - finalURL.port = - forwardedPort || - (forwardedProto && (forwardedProto === 'https' ? '443' : '80')) || - finalURL.port; + finalURL.port = forwardedPort || finalURL.port; if (finalURL.port !== referrerURL.port) { return true; From db2360d84fbc9ce4cf62e0698099b59ad4bfc83c Mon Sep 17 00:00:00 2001 From: Peter Perlepes Date: Tue, 8 Mar 2022 19:31:26 +0200 Subject: [PATCH 45/58] fix(backend-core): Make sure to check cross-origin in more cases --- packages/backend-core/src/Base.ts | 19 +++++-- .../src/__tests__/utils/request.test.ts | 56 +++++++++---------- packages/backend-core/src/util/request.ts | 12 ++-- 3 files changed, 44 insertions(+), 43 deletions(-) diff --git a/packages/backend-core/src/Base.ts b/packages/backend-core/src/Base.ts index 660780f0085..698222ce30c 100644 --- a/packages/backend-core/src/Base.ts +++ b/packages/backend-core/src/Base.ts @@ -4,7 +4,7 @@ import { JWTExpiredError } from './api/utils/Errors'; import { parse } from './util/base64url'; import { isDevelopmentOrStaging, isProduction } from './util/clerkApiKey'; import { checkClaims, isExpired } from './util/jwt'; -import { checkCrossOriginReferrer } from './util/request'; +import { checkCrossOrigin } from './util/request'; import { JWT, JWTPayload } from './util/types'; export const API_KEY = process.env.CLERK_API_KEY || ''; @@ -266,9 +266,16 @@ export class Base { } // In cross-origin requests the use of Authorization header is mandatory - // TODO: The origin header can be present in same-origin POST, PUT, PATCH requests etc. - // Is this check enough for API endpoint authorization ? - if (origin) { + if ( + origin && + checkCrossOrigin({ + originURL: new URL(origin), + host, + forwardedHost, + forwardedPort, + forwardedProto, + }) + ) { return { status: AuthStatus.SignedOut }; } @@ -284,8 +291,8 @@ export class Base { if ( isDevelopmentOrStaging(API_KEY) && referrer && - checkCrossOriginReferrer({ - referrerURL: new URL(referrer), + checkCrossOrigin({ + originURL: new URL(referrer), host, forwardedHost, forwardedPort, diff --git a/packages/backend-core/src/__tests__/utils/request.test.ts b/packages/backend-core/src/__tests__/utils/request.test.ts index bac2a5c331c..f54e4afb9fb 100644 --- a/packages/backend-core/src/__tests__/utils/request.test.ts +++ b/packages/backend-core/src/__tests__/utils/request.test.ts @@ -1,38 +1,36 @@ -import { checkCrossOriginReferrer } from '../../util/request'; +import { checkCrossOrigin } from '../../util/request'; describe('check cross-origin-referrer request utility', () => { test('is not CO with IPv6', () => { - const referrerURL = new URL('http://[::1]'); + const originURL = new URL('http://[::1]'); const host = new URL('http://[::1]').host; - expect(checkCrossOriginReferrer({ referrerURL, host })).toEqual(false); + expect(checkCrossOrigin({ originURL, host })).toEqual(false); }); test('is not CO with set https and 443 port', () => { - const referrerURL = new URL('https://localhost:443'); + const originURL = new URL('https://localhost:443'); const host = new URL('https://localhost').host; - expect(checkCrossOriginReferrer({ referrerURL, host })).toEqual(false); + expect(checkCrossOrigin({ originURL, host })).toEqual(false); }); test('is CO with mixed default security ports', () => { - const referrerURL = new URL('https://localhost:80'); + const originURL = new URL('https://localhost:80'); const host = new URL('http://localhost:443').host; - expect(checkCrossOriginReferrer({ referrerURL, host })).toEqual(true); + expect(checkCrossOrigin({ originURL, host })).toEqual(true); }); - test.skip('is CO when HTTPS to HTTP', () => { - const referrerURL = new URL('https://localhost'); - const host = new URL('http://localhost').host; - expect(checkCrossOriginReferrer({ referrerURL, host })).toEqual(true); - }); + test.todo( + 'we cannot detect if the request is CO when HTTPS to HTTP and no other information is carried over', + ); test('is CO when HTTPS to HTTP with present x-forwarded-proto', () => { - const referrerURL = new URL('https://localhost'); + const originURL = new URL('https://localhost'); const host = new URL('http://someserver').host; const forwardedHost = new URL('http://localhost').host; const forwardedProto = 'http'; expect( - checkCrossOriginReferrer({ - referrerURL, + checkCrossOrigin({ + originURL, host, forwardedHost, forwardedProto, @@ -41,37 +39,33 @@ describe('check cross-origin-referrer request utility', () => { }); test('is CO when HTTPS to HTTP with forwarded port', () => { - const referrerURL = new URL('https://localhost'); + const originURL = new URL('https://localhost'); const host = new URL('http://localhost').host; const forwardedPort = '80'; - expect( - checkCrossOriginReferrer({ referrerURL, host, forwardedPort }), - ).toEqual(true); + expect(checkCrossOrigin({ originURL, host, forwardedPort })).toEqual(true); }); test('is CO with cross origin auth domain', () => { - const referrerURL = new URL('https://accounts.clerk.dev'); + const originURL = new URL('https://accounts.clerk.dev'); const host = new URL('https://localhost').host; - expect(checkCrossOriginReferrer({ referrerURL, host })).toEqual(true); + expect(checkCrossOrigin({ originURL, host })).toEqual(true); }); test('is CO when forwarded port overrides host derived port', () => { - const referrerURL = new URL('https://localhost:443'); + const originURL = new URL('https://localhost:443'); const host = new URL('https://localhost').host; const forwardedPort = '3001'; - expect( - checkCrossOriginReferrer({ referrerURL, host, forwardedPort }), - ).toEqual(true); + expect(checkCrossOrigin({ originURL, host, forwardedPort })).toEqual(true); }); test('is not CO with port included in x-forwarded host', () => { /* Example https://www.rfc-editor.org/rfc/rfc7239#section-4 */ - const referrerURL = new URL('http://localhost:3000'); + const originURL = new URL('http://localhost:3000'); const host = '127.0.0.1:3000'; const forwardedHost = 'localhost:3000'; expect( - checkCrossOriginReferrer({ - referrerURL, + checkCrossOrigin({ + originURL, host, forwardedHost, }), @@ -80,12 +74,12 @@ describe('check cross-origin-referrer request utility', () => { test('is CO with port included in x-forwarded host', () => { /* Example https://www.rfc-editor.org/rfc/rfc7239#section-4 */ - const referrerURL = new URL('http://localhost:3000'); + const originURL = new URL('http://localhost:3000'); const host = '127.0.0.1:3000'; const forwardedHost = 'localhost:4000'; expect( - checkCrossOriginReferrer({ - referrerURL, + checkCrossOrigin({ + originURL, host, forwardedHost, }), diff --git a/packages/backend-core/src/util/request.ts b/packages/backend-core/src/util/request.ts index cac5fdf4396..aa329b19fc9 100644 --- a/packages/backend-core/src/util/request.ts +++ b/packages/backend-core/src/util/request.ts @@ -5,20 +5,20 @@ * (This case most of the times signifies redirect from Clerk Auth pages) * */ -export function checkCrossOriginReferrer({ - referrerURL, +export function checkCrossOrigin({ + originURL, host, forwardedHost, forwardedPort, forwardedProto, }: { - referrerURL: URL; + originURL: URL; host: string; forwardedHost?: string | null; forwardedPort?: string | null; forwardedProto?: string | null; }) { - if (forwardedProto && forwardedProto !== referrerURL.protocol) { + if (forwardedProto && forwardedProto !== originURL.protocol) { return true; } @@ -27,10 +27,10 @@ export function checkCrossOriginReferrer({ finalURL.port = forwardedPort || finalURL.port; - if (finalURL.port !== referrerURL.port) { + if (finalURL.port !== originURL.port) { return true; } - if (finalURL.hostname !== referrerURL.hostname) { + if (finalURL.hostname !== originURL.hostname) { return true; } From 1026da8481d6d450390915e4f873cd53de299e61 Mon Sep 17 00:00:00 2001 From: Nikos Douvlis Date: Tue, 8 Mar 2022 22:01:05 +0200 Subject: [PATCH 46/58] chore(repo): Update v3 with the latest v2 changes (#90) * feat(clerk-js): Add organization basic resources * feat(clerk-js): Basic organization data shape tests * feat(clerk-js): Invitation flow draft * feat(clerk-js): SignUp with organization invitation flow draft * feat(clerk-js): Sign up next draft and fixes * feat(clerk-js): Add more attributes on organization models Type fixes and sign-in loading screen * chore(release): Publish - @clerk/clerk-js@2.15.0 - @clerk/clerk-expo@0.8.7 - @clerk/nextjs@2.11.5 - @clerk/clerk-react@2.11.5 - @clerk/shared@0.0.6 - @clerk/types@1.26.0 * feat(clerk-js): Add useOrganization hook * fix(clerk-js): Clear invalid invitation token value * feat(clerk-react,clerk-js): Add useOrganization hook using __unstable attribute * feat(types,clerk-js): Introduce Notion OAuth (#72) Introduce declarations for supporting Notion OAuth * chore(release): Publish - @clerk/clerk-js@2.16.0 - @clerk/clerk-expo@0.8.8 - @clerk/nextjs@2.11.6 - @clerk/clerk-react@2.11.6 - @clerk/shared@0.0.7 - @clerk/types@1.27.0 * chore(repo): Stop CHANGELOG generation for staging releases * fix(types): Consolidate oauth provider types * fix(clerk-js): Don't use ResizeObserver on old browsers * chore(release): Publish - @clerk/clerk-js@2.16.1 - @clerk/clerk-expo@0.8.9 - @clerk/nextjs@2.11.7 - @clerk/clerk-react@2.11.7 - @clerk/shared@0.0.8 - @clerk/types@1.27.1 * feat(clerk-js,clerk-react): GetOrganization/s hook methods, fetching mechanism alignment Fix state clearing of organizationInvitationToken * fix(types): Guarantee elements not in oauth sorting array will be sorted last * fix(clerk-expo): Add guard clause for tokenCache methods * fix(clerk-expo): Add early return if tokenCache is not provided * chore(types): Add license * chore(types): Add contribution docs * chore(types): Update README * chore(release): Publish - @clerk/clerk-js@2.17.0 - @clerk/clerk-expo@0.8.10 - @clerk/nextjs@2.11.8 - @clerk/clerk-react@2.12.0 - @clerk/shared@0.0.9 - @clerk/types@1.28.0 * fix(clerk-react,clerk-js,types): Crate of API feedback fixes * fix(types): Change type import from dot * feat(backend-core): Organizations API Added support for managing organizations through the OrganizationApi. Currently, the only method that is supported can be used to create a new organization and it's named createOrganization(). Added the Organization resource, along with types for organization properties and JSON serialization. * fix(types): Add OrganizationMembership methods on types * chore(release): Publish - @clerk/backend-core@0.5.0 - @clerk/clerk-js@2.17.1 - @clerk/edge@0.3.5 - @clerk/clerk-expo@0.8.11 - @clerk/nextjs@2.11.9 - @clerk/clerk-react@2.12.1 - @clerk/clerk-sdk-node@2.9.5 - @clerk/shared@0.0.10 - @clerk/types@1.28.1 * feat(types,backend-core,clerk-js): Add external account properties username, publicMetadata & label * fix(backend-core): Add JWTPayload orgs claim type * chore(release): Publish - @clerk/backend-core@0.5.1 - @clerk/edge@0.3.6 - @clerk/nextjs@2.11.10 - @clerk/clerk-sdk-node@2.9.6 * fix(types): Revoke typing on organizationInvitation * feat(backend-core): Add public_metadata to invitation create API (#85) Invitations can optionally carry metadata that will eventually end up in the created user once they sign up. The metadata must be a well-formed JSON object. In order to add metadata to an invitation, you can use the public_metadata property when the invitation is created: https://docs.clerk.dev/popular-guides/invitations#invitation-metadata * Revert "fix(clerk-js,clerk-react): Revert user settings work" This reverts commit 9a70576d1a47f01e6dbbfd8704f321daddcfe590. * chore(release): Publish - @clerk/clerk-js@2.16.1-staging.0 - @clerk/clerk-expo@0.8.9-staging.0 - @clerk/nextjs@2.11.7-staging.0 - @clerk/clerk-react@2.11.7-staging.0 - @clerk/shared@0.0.8-staging.0 - @clerk/types@1.27.1-staging.0 * chore(release): Publish - @clerk/clerk-js@2.16.2-staging.0 - @clerk/clerk-expo@0.8.10-staging.0 - @clerk/nextjs@2.11.8-staging.0 - @clerk/clerk-react@2.11.8-staging.0 - @clerk/shared@0.0.9-staging.0 - @clerk/types@1.27.2-staging.0 * chore(release): Publish - @clerk/clerk-js@2.16.3-staging.0 - @clerk/clerk-expo@0.8.11-staging.0 - @clerk/nextjs@2.11.9-staging.0 - @clerk/clerk-react@2.11.9-staging.0 - @clerk/shared@0.0.10-staging.0 - @clerk/types@1.27.3-staging.0 * chore(release): Publish - @clerk/backend-core@0.4.5-staging.0 - @clerk/clerk-js@2.17.1-staging.0 - @clerk/edge@0.3.5-staging.0 - @clerk/clerk-expo@0.8.11-staging.0 - @clerk/nextjs@2.11.9-staging.0 - @clerk/clerk-react@2.12.1-staging.0 - @clerk/clerk-sdk-node@2.9.5-staging.0 - @clerk/shared@0.0.10-staging.0 - @clerk/types@1.28.1-staging.0 * fixup! chore(release): Publish * chore(release): Publish - @clerk/backend-core@0.5.2-staging.0 - @clerk/clerk-js@2.17.2-staging.0 - @clerk/edge@0.3.7-staging.0 - @clerk/clerk-expo@0.8.12-staging.0 - @clerk/nextjs@2.11.11-staging.0 - @clerk/clerk-react@2.12.2-staging.0 - @clerk/clerk-sdk-node@2.9.7-staging.0 - @clerk/shared@0.0.11-staging.0 - @clerk/types@1.28.2-staging.0 * chore(repo): Bump turbo dependency Fix https://github.com/vercel/turborepo/issues/820 * chore(repo): Fix merge conflicts Co-authored-by: Peter Perlepes Co-authored-by: Sokratis Vidros Co-authored-by: Haris Chaniotakis Co-authored-by: Mark Pitsilos Co-authored-by: Ian McPhail Co-authored-by: Giannis Katsanos Co-authored-by: Giannis Katsanos Co-authored-by: Ian McPhail <97047001+devchampian@users.noreply.github.com> Co-authored-by: Devin Riegle --- package-lock.json | 524 +++++++++++++----- package.json | 4 +- packages/backend-core/API.md | 17 + packages/backend-core/CHANGELOG.md | 18 + packages/backend-core/package.json | 2 +- .../src/__tests__/apis/InvitationApi.test.ts | 36 ++ .../__tests__/apis/OrganizationApi.test.ts | 37 ++ .../src/__tests__/apis/UserApi.test.ts | 6 + .../src/__tests__/apis/responses/getUser.json | 12 +- .../src/__tests__/utils/Deserializer.test.ts | 21 + .../backend-core/src/api/ClerkBackendAPI.ts | 13 +- .../src/api/collection/InvitationApi.ts | 1 + .../src/api/collection/OrganizationApi.ts | 19 + .../backend-core/src/api/collection/index.ts | 1 + .../src/api/resources/ExternalAccount.ts | 6 + .../src/api/resources/Invitation.ts | 2 +- .../backend-core/src/api/resources/JSON.ts | 17 + .../src/api/resources/Organization.ts | 23 + .../backend-core/src/api/resources/Props.ts | 10 + .../backend-core/src/api/resources/index.ts | 1 + .../src/api/utils/Deserializer.ts | 21 +- packages/backend-core/src/util/types.ts | 7 + packages/clerk-js/CHANGELOG.md | 64 +++ packages/clerk-js/src/core/clerk.ts | 21 + .../clerk-js/src/core/resources/AuthConfig.ts | 42 +- packages/clerk-js/src/core/resources/Base.ts | 2 +- .../src/core/resources/Environment.ts | 10 +- .../src/core/resources/ExternalAccount.ts | 22 +- .../src/core/resources/Organization.test.ts | 18 + .../src/core/resources/Organization.ts | 144 +++++ .../resources/OrganizationInvitation.test.ts | 18 + .../core/resources/OrganizationInvitation.ts | 69 +++ .../resources/OrganizationMembership.test.ts | 24 + .../core/resources/OrganizationMembership.ts | 62 +++ packages/clerk-js/src/core/resources/Token.ts | 2 +- packages/clerk-js/src/core/resources/User.ts | 8 + .../src/core/resources/UserSettings.test.ts | 135 +++++ .../src/core/resources/UserSettings.ts | 79 +++ .../__snapshots__/Organization.test.ts.snap | 19 + .../OrganizationInvitation.test.ts.snap | 15 + .../OrganizationMembership.test.ts.snap | 21 + .../clerk-js/src/core/resources/internal.ts | 4 + packages/clerk-js/src/ui/common/constants.ts | 95 +--- packages/clerk-js/src/ui/common/logo/Logo.tsx | 6 + .../src/ui/common/withRedirectToHome.tsx | 8 +- .../src/ui/contexts/EnvironmentContext.tsx | 2 +- .../clerk-js/src/ui/signIn/SignIn.test.tsx | 8 +- .../ui/signIn/SignInAccountSwitcher.test.tsx | 7 +- .../src/ui/signIn/SignInFactorOne.test.tsx | 2 +- .../src/ui/signIn/SignInStart.test.tsx | 115 ++-- .../clerk-js/src/ui/signIn/SignInStart.tsx | 123 ++-- .../src/ui/signIn/strategies/OAuth.tsx | 18 +- .../src/ui/signIn/strategies/Web3.tsx | 4 +- .../clerk-js/src/ui/signUp/SignUp.test.tsx | 8 +- .../clerk-js/src/ui/signUp/SignUpOAuth.tsx | 12 +- .../src/ui/signUp/SignUpStart.test.tsx | 264 +++++---- .../clerk-js/src/ui/signUp/SignUpStart.tsx | 74 ++- .../src/ui/signUp/SignUpVerify.test.tsx | 75 ++- .../clerk-js/src/ui/signUp/SignUpVerify.tsx | 13 +- .../__snapshots__/SignUpVerify.test.tsx.snap | 6 +- packages/clerk-js/src/ui/signUp/utils.test.ts | 240 ++++---- packages/clerk-js/src/ui/signUp/utils.ts | 84 ++- .../src/ui/userProfile/UserProfile.test.tsx | 67 ++- .../__snapshots__/UserProfile.test.tsx.snap | 14 +- .../ui/userProfile/account/Account.test.tsx | 61 +- .../src/ui/userProfile/account/Account.tsx | 12 +- .../PersonalInformationCard.tsx | 22 +- .../account/profileCard/ProfileCard.test.tsx | 65 ++- .../account/profileCard/ProfileCard.tsx | 15 +- .../__snapshots__/ProfileCard.test.tsx.snap | 214 +++++++ .../emailAdressess/AddNewEmail.test.tsx | 18 +- ...lAddressVerificationWithMagicLink.test.tsx | 5 - .../emailAdressess/EmailDetail.test.tsx | 24 +- .../ui/userProfile/emailAdressess/utils.ts | 9 +- .../security/ChangePassword.test.tsx | 62 +++ .../userProfile/security/ChangePassword.tsx | 6 +- .../ui/userProfile/security/Security.test.tsx | 20 +- .../src/ui/userProfile/security/Security.tsx | 10 +- .../src/ui/userProfile/security/index.tsx | 7 +- .../clerk-js/src/utils/getClerkQueryParam.ts | 2 + packages/edge/CHANGELOG.md | 16 + packages/edge/package.json | 4 +- packages/edge/src/info.ts | 2 +- packages/expo/CHANGELOG.md | 42 ++ packages/expo/package.json | 2 +- packages/expo/src/singleton.ts | 9 +- packages/nextjs/CHANGELOG.md | 49 ++ packages/nextjs/package.json | 2 +- packages/react/CHANGELOG.md | 44 ++ packages/react/src/hooks/index.ts | 2 + .../react/src/{ => hooks}/useMagicLink.ts | 0 packages/react/src/hooks/useOrganizations.ts | 24 + packages/react/src/index.ts | 2 +- packages/react/src/isomorphicClerk.ts | 35 ++ packages/sdk-node/CHANGELOG.md | 16 + packages/sdk-node/package.json | 4 +- packages/sdk-node/src/info.ts | 2 +- packages/shared/CHANGELOG.md | 43 ++ packages/shared/package.json | 2 +- packages/types/CHANGELOG.md | 60 ++ packages/types/LICENSE | 21 + packages/types/README.md | 93 +++- packages/types/docs/CODE_OF_CONDUCT.md | 132 +++++ packages/types/docs/CONTRIBUTING.md | 120 ++++ packages/types/docs/SECURITY.md | 19 + packages/types/src/authConfig.ts | 52 -- packages/types/src/clerk.ts | 31 ++ packages/types/src/environment.ts | 2 + packages/types/src/externalAccount.ts | 4 +- packages/types/src/index.ts | 4 + packages/types/src/json.ts | 81 +-- packages/types/src/jwt.ts | 4 + packages/types/src/oauth.ts | 130 ++++- packages/types/src/organization.ts | 40 ++ packages/types/src/organizationInvitation.ts | 14 + packages/types/src/organizationMembership.ts | 20 + packages/types/src/session.ts | 1 + packages/types/src/signIn.ts | 9 +- packages/types/src/signUp.ts | 5 +- packages/types/src/userSettings.ts | 74 +++ 120 files changed, 3654 insertions(+), 936 deletions(-) create mode 100644 packages/backend-core/src/__tests__/apis/OrganizationApi.test.ts create mode 100644 packages/backend-core/src/api/collection/OrganizationApi.ts create mode 100644 packages/backend-core/src/api/resources/Organization.ts create mode 100644 packages/clerk-js/src/core/resources/Organization.test.ts create mode 100644 packages/clerk-js/src/core/resources/Organization.ts create mode 100644 packages/clerk-js/src/core/resources/OrganizationInvitation.test.ts create mode 100644 packages/clerk-js/src/core/resources/OrganizationInvitation.ts create mode 100644 packages/clerk-js/src/core/resources/OrganizationMembership.test.ts create mode 100644 packages/clerk-js/src/core/resources/OrganizationMembership.ts create mode 100644 packages/clerk-js/src/core/resources/UserSettings.test.ts create mode 100644 packages/clerk-js/src/core/resources/UserSettings.ts create mode 100644 packages/clerk-js/src/core/resources/__snapshots__/Organization.test.ts.snap create mode 100644 packages/clerk-js/src/core/resources/__snapshots__/OrganizationInvitation.test.ts.snap create mode 100644 packages/clerk-js/src/core/resources/__snapshots__/OrganizationMembership.test.ts.snap create mode 100644 packages/clerk-js/src/ui/userProfile/security/ChangePassword.test.tsx rename packages/react/src/{ => hooks}/useMagicLink.ts (100%) create mode 100644 packages/react/src/hooks/useOrganizations.ts create mode 100644 packages/types/LICENSE create mode 100644 packages/types/docs/CODE_OF_CONDUCT.md create mode 100644 packages/types/docs/CONTRIBUTING.md create mode 100644 packages/types/docs/SECURITY.md create mode 100644 packages/types/src/organization.ts create mode 100644 packages/types/src/organizationInvitation.ts create mode 100644 packages/types/src/organizationMembership.ts create mode 100644 packages/types/src/userSettings.ts diff --git a/package-lock.json b/package-lock.json index e133a1ac351..9ffc4483be0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "lerna": "^4.0.0", "prettier": "^2.3.1", "rimraf": "^3.0.2", - "turbo": "^1", + "turbo": "^1.1.5", "typescript": "4.5.5" }, "engines": { @@ -21593,33 +21593,33 @@ } }, "node_modules/turbo": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/turbo/-/turbo-1.1.2.tgz", - "integrity": "sha512-3ViHKyAkaBKNKwHASTa1zkVT3tVVhQNLrpxBS7LoN+794ouQUYmy6lf0rTqzG3iTZHtIDwC+piZSdTl4XjEVMg==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/turbo/-/turbo-1.1.5.tgz", + "integrity": "sha512-jXW8G4lr01/E/jS/66LYpEjwWFQAksC8TxR8gi3VGea7OeNj28l8zmXoY3IgT5H22MBnhmtOKV/GhsbPjI2Jrg==", "dev": true, "hasInstallScript": true, "bin": { "turbo": "bin/turbo" }, "optionalDependencies": { - "turbo-darwin-64": "1.1.2", - "turbo-darwin-arm64": "1.1.2", - "turbo-freebsd-64": "1.1.2", - "turbo-freebsd-arm64": "1.1.2", - "turbo-linux-32": "1.1.2", - "turbo-linux-64": "1.1.2", - "turbo-linux-arm": "1.1.2", - "turbo-linux-arm64": "1.1.2", - "turbo-linux-mips64le": "1.1.2", - "turbo-linux-ppc64le": "1.1.2", - "turbo-windows-32": "1.1.2", - "turbo-windows-64": "1.1.2" + "turbo-darwin-64": "1.1.5", + "turbo-darwin-arm64": "1.1.5", + "turbo-freebsd-64": "1.1.5", + "turbo-freebsd-arm64": "1.1.5", + "turbo-linux-32": "1.1.5", + "turbo-linux-64": "1.1.5", + "turbo-linux-arm": "1.1.5", + "turbo-linux-arm64": "1.1.5", + "turbo-linux-mips64le": "1.1.5", + "turbo-linux-ppc64le": "1.1.5", + "turbo-windows-32": "1.1.5", + "turbo-windows-64": "1.1.5" } }, "node_modules/turbo-darwin-64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-1.1.2.tgz", - "integrity": "sha512-rua17HnVvAqAU54gVfiQoH7cfopOqANv+yI6NtxLMD8aFfX2cJ9m8SSvH2v2vCaToNDW6OnTkdqDKQpqIHzbCw==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-1.1.5.tgz", + "integrity": "sha512-qdGMylQ408NmYhzuMmx+25W0iHFyFMRPO4579tDEv+WBiVDfAEYEzjajE4c+CQOLhd1aVEaPdSa+YhngQUgoDQ==", "cpu": [ "x64" ], @@ -21630,9 +21630,9 @@ ] }, "node_modules/turbo-darwin-arm64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-1.1.2.tgz", - "integrity": "sha512-otqSQNYDyKg0KqB3NM0BI4oiRPKdJkUE/XBn8dcUS+zeRLrL00XtaM0eSwynZs1tb6zU/Y+SPMSBRygD1TCOnw==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-1.1.5.tgz", + "integrity": "sha512-mXU324d3vYzxRT9FSSkW9yG2BvFosd0f4DUvqy4qms8wzM6Yv9Aeo4zZTL86rF88UYGUkbiRaPQUeceb/QARVg==", "cpu": [ "arm64" ], @@ -21643,9 +21643,9 @@ ] }, "node_modules/turbo-freebsd-64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/turbo-freebsd-64/-/turbo-freebsd-64-1.1.2.tgz", - "integrity": "sha512-2nxwVDTAM0DtIQ2i3UOfEsQLF7vp+XZ/b9SKtiHxz710fXvdyuGivYI25axDdcBn8kQ45rnbUnarF1aW8CMGgg==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/turbo-freebsd-64/-/turbo-freebsd-64-1.1.5.tgz", + "integrity": "sha512-qjjPTnZKOxw2x1Ito3yZAYDcwsCEg/5kYJwbPVvDn1jyXoxr3pUxTHUohroxQ6EmyxQ28qL7QpCVWDoQpDwrOQ==", "cpu": [ "x64" ], @@ -21656,9 +21656,9 @@ ] }, "node_modules/turbo-freebsd-arm64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/turbo-freebsd-arm64/-/turbo-freebsd-arm64-1.1.2.tgz", - "integrity": "sha512-ro1Ah96yzgzyT0BJe1mceAqxPxi0pUwzAvN3IKVpMqi4hYkT3aRbzDCaSxzyC6let2Al/NUsgHnbAv38OF2Xkw==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/turbo-freebsd-arm64/-/turbo-freebsd-arm64-1.1.5.tgz", + "integrity": "sha512-jYW+Th9Y6yEYevaFe7v3lFQoxyrpd8wX5KuuvqLazMRbNxvKgqTDmT7AbCOGJY5ejzqGnMlTGkQr8c3g3B8ndA==", "cpu": [ "arm64" ], @@ -21669,9 +21669,9 @@ ] }, "node_modules/turbo-linux-32": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/turbo-linux-32/-/turbo-linux-32-1.1.2.tgz", - "integrity": "sha512-HKBsETxQMVaf/DJwMg7pypPbGA6KEu0gEf9C8o2aPJvwMPBYgNsNaU08Xizuh5xzEQTzpbIWfQyqdNgMV4RG3Q==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/turbo-linux-32/-/turbo-linux-32-1.1.5.tgz", + "integrity": "sha512-c5I8tdR1jD8L8pJWk+rlO734bpWI1gwGdvNOaA/IGZxzOfDSn4CGoUErnUPgOadT8azi7lT9UPQf/pLfEvjCOw==", "cpu": [ "ia32" ], @@ -21682,9 +21682,9 @@ ] }, "node_modules/turbo-linux-64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-1.1.2.tgz", - "integrity": "sha512-IklKsOklcRHIWkTzKg95BQ6jgJ53kLvRMrp8yqzlvZprkWdiyhAgUxrUTTHOOTce2XA3+jdN2+MwixG44uY2vg==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-1.1.5.tgz", + "integrity": "sha512-BZAxLfIkEtQa7u+VPYpdeVVJH6ab4WwXv4oCrUDaZf2BseDUxr57y2ASAWNFsg40T3oXXt4Kcbdc5LibjWQdtQ==", "cpu": [ "x64" ], @@ -21695,9 +21695,9 @@ ] }, "node_modules/turbo-linux-arm": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/turbo-linux-arm/-/turbo-linux-arm-1.1.2.tgz", - "integrity": "sha512-CNbaTvRozq7H/5jpy9OZlzJ6BkeEXF+nF2n9dHiUrbAXd3nq84Qt9odcQJmGnexP19YS9w6l3tIHncX4BgwtqA==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/turbo-linux-arm/-/turbo-linux-arm-1.1.5.tgz", + "integrity": "sha512-X6J05gQSWTc2c/TCkOQdFLhr35pUjEExY6K8yanYs2QKgd4GvDHmxYaBZ+6f90qcIUHYpe++adDPJcuAUv+8ug==", "cpu": [ "arm" ], @@ -21708,9 +21708,9 @@ ] }, "node_modules/turbo-linux-arm64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-1.1.2.tgz", - "integrity": "sha512-3kS6sk2lOtuBBqkcL+yeGqD1yew4UZ1o7XUcbDD8UPwhF2kAfK7Qs0vTJw4lnO1scjhihkoTrmXM7yozvjf4/w==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-1.1.5.tgz", + "integrity": "sha512-8/yz5L0B6Jb0pNcvx/08LcPswizqggxQ0zlFEw+Oh9RAC+ZM5+X2YiMyKolvLCpkoRqrlKku0lmXH7mx6DWbig==", "cpu": [ "arm64" ], @@ -21721,9 +21721,9 @@ ] }, "node_modules/turbo-linux-mips64le": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/turbo-linux-mips64le/-/turbo-linux-mips64le-1.1.2.tgz", - "integrity": "sha512-CDoXVIlW43C6KLgYxe13KkG8h6DswXHxbTVHiZdOwRQ56j46lU+JOVpLoh6wpQGcHvj58VEiypZBRTGVFMeogw==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/turbo-linux-mips64le/-/turbo-linux-mips64le-1.1.5.tgz", + "integrity": "sha512-K26bEFcLDGPkcaW7Eq4CMSxUbJf/x58aE92+0tONhrxXzamaBqTrSxPYlk/T8OoH7HxOvja2ctkpeI/NRAoIyw==", "cpu": [ "mips64el" ], @@ -21734,9 +21734,9 @@ ] }, "node_modules/turbo-linux-ppc64le": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/turbo-linux-ppc64le/-/turbo-linux-ppc64le-1.1.2.tgz", - "integrity": "sha512-xPVMHoiOJE/qI63jSOXwYIUFQXLdstxDV6fLnRxvq0QnJNxgTKq+mLUeE8M4LDVh1bdqHLcfk/HmyQ6+X1XVkQ==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/turbo-linux-ppc64le/-/turbo-linux-ppc64le-1.1.5.tgz", + "integrity": "sha512-fr1/5yf8fe1BJiW/6Y9lmV+kxZZC3u3xvSBC5AXDSl9u3aJFZl96CRE9tOJbTZMaOVGxhplKD+EiHbjIxUnTrA==", "cpu": [ "ppc64" ], @@ -21747,9 +21747,9 @@ ] }, "node_modules/turbo-windows-32": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/turbo-windows-32/-/turbo-windows-32-1.1.2.tgz", - "integrity": "sha512-Gj1yvPE0aMDSOxGVSBaecLnwsVDT1xX8U0dtLrg52TYY2jlaci0atjHKr9nTFuX7z8uwAf6PopwdriGoCeT3ng==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/turbo-windows-32/-/turbo-windows-32-1.1.5.tgz", + "integrity": "sha512-K9LdIgQXJ7jL0aLJS0l2asJAH/vYBFP7qFzODiAcJ1EeKBjYqAVnIxFQrUN07lzNDtL9WK/aN5q0bJCDnhwTQw==", "cpu": [ "ia32" ], @@ -21760,9 +21760,9 @@ ] }, "node_modules/turbo-windows-64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-1.1.2.tgz", - "integrity": "sha512-0Ncx/iKhnKrdAU8hJ+8NUcF9jtFr8KoW5mMWfiFzy+mgUbVKbpzWT2eoGR6zJExedQsRvYOejbEX5iihbnj5bA==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-1.1.5.tgz", + "integrity": "sha512-c2Jkmw8yGZVz4opzEvB5HAf9XkA8CZBnorie46s44ec0FaNbcP9SCuUNvgAHxqDIHTGWC4A5PoPn0owkD3ss6A==", "cpu": [ "x64" ], @@ -23068,7 +23068,7 @@ }, "packages/backend-core": { "name": "@clerk/backend-core", - "version": "0.4.4", + "version": "0.5.2-staging.0", "license": "MIT", "dependencies": { "camelcase-keys": "^7.0.1", @@ -23203,10 +23203,10 @@ }, "packages/edge": { "name": "@clerk/edge", - "version": "0.3.4", + "version": "0.3.7-staging.0", "license": "MIT", "dependencies": { - "@clerk/backend-core": "^0.4.4", + "@clerk/backend-core": "^0.5.2-staging.0", "@peculiar/webcrypto": "^1.2.3", "next": "^12.0.7" }, @@ -23237,7 +23237,7 @@ "base-64": "^1.0.0" }, "devDependencies": { - "@clerk/types": "^1.25.4", + "@clerk/types": "^1.28.2-staging.0", "@types/jest": "^27.4.0", "@types/node": "^16.11.9", "@types/react": "^17.0.39", @@ -23257,9 +23257,9 @@ } }, "packages/expo/node_modules/@clerk/types": { - "version": "1.25.4", - "resolved": "https://registry.npmjs.org/@clerk/types/-/types-1.25.4.tgz", - "integrity": "sha512-KXwIjF6lP9zEUk8aQVpTDhmxyvpX1GZZPbQzEjL+oZserOe1zKW97RqYatzmkKImUzqyGG+GbMe6bunPnKqA1w==", + "version": "1.28.2-staging.0", + "resolved": "https://registry.npmjs.org/@clerk/types/-/types-1.28.2-staging.0.tgz", + "integrity": "sha512-fOGVQAJ2uId29upNNnxtLaiIYGxD4p2nQ/vqzlqBvk7gpUBhWR7b4I9TMaBBxUiFbBDnlwDXEGNz8IIYRchsvA==", "dev": true, "engines": { "node": ">=14" @@ -23277,7 +23277,7 @@ "license": "MIT", "dependencies": { "@clerk/clerk-react": "^3.0.0-alpha.9", - "@clerk/clerk-sdk-node": "^2.9.0", + "@clerk/clerk-sdk-node": "^2.9.6", "@clerk/types": "^2.0.0-alpha.8", "tslib": "^2.3.1" }, @@ -23300,12 +23300,87 @@ "next": ">=10" } }, + "packages/nextjs/node_modules/@clerk/backend-core": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@clerk/backend-core/-/backend-core-0.5.1.tgz", + "integrity": "sha512-+V/GbiLiFWkziXdMhooCXDEd3a+rDzDcjFo3LP3VNGUNxOW7mHBFxoVeWrjiBceQh8zhscrbUSRV+pmXq85Xdw==", + "dependencies": { + "camelcase-keys": "^7.0.1", + "query-string": "^7.0.1", + "snakecase-keys": "^5.1.2", + "tslib": "^2.3.1" + } + }, + "packages/nextjs/node_modules/@clerk/clerk-sdk-node": { + "version": "2.9.6", + "resolved": "https://registry.npmjs.org/@clerk/clerk-sdk-node/-/clerk-sdk-node-2.9.6.tgz", + "integrity": "sha512-T/fKQBMgRYyALN5ua7IpKwuyxpzCVYjK3bHk73hpqud+xm3mNe0gGmHGW+FH4YQhZ3rIArbPEkhyNnn50+nnmg==", + "dependencies": { + "@clerk/backend-core": "^0.5.1", + "@peculiar/webcrypto": "^1.2.3", + "camelcase-keys": "^6.2.2", + "cookies": "^0.8.0", + "deepmerge": "^4.2.2", + "got": "^11.8.2", + "jsonwebtoken": "^8.5.1", + "jwks-rsa": "^2.0.4", + "snakecase-keys": "^3.2.1", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=12" + } + }, + "packages/nextjs/node_modules/@clerk/clerk-sdk-node/node_modules/camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dependencies": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/nextjs/node_modules/@clerk/clerk-sdk-node/node_modules/snakecase-keys": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/snakecase-keys/-/snakecase-keys-3.2.1.tgz", + "integrity": "sha512-CjU5pyRfwOtaOITYv5C8DzpZ8XA/ieRsDpr93HI2r6e3YInC6moZpSQbmUtg8cTk58tq2x3jcG2gv+p1IZGmMA==", + "dependencies": { + "map-obj": "^4.1.0", + "to-snake-case": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, "packages/nextjs/node_modules/@types/node": { "version": "16.11.22", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.22.tgz", "integrity": "sha512-DYNtJWauMQ9RNpesl4aVothr97/tIJM8HbyOXJ0AYT1Z2bEjLHyfjOBPAQQVMLf8h3kSShYfNk8Wnto8B2zHUA==", "dev": true }, + "packages/nextjs/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + }, + "packages/nextjs/node_modules/quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "engines": { + "node": ">=8" + } + }, "packages/react": { "name": "@clerk/clerk-react", "version": "3.0.0-alpha.9", @@ -23378,12 +23453,79 @@ "remix": ">=1.2.1" } }, + "packages/remix/node_modules/@clerk/backend-core": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@clerk/backend-core/-/backend-core-0.5.1.tgz", + "integrity": "sha512-+V/GbiLiFWkziXdMhooCXDEd3a+rDzDcjFo3LP3VNGUNxOW7mHBFxoVeWrjiBceQh8zhscrbUSRV+pmXq85Xdw==", + "dependencies": { + "camelcase-keys": "^7.0.1", + "query-string": "^7.0.1", + "snakecase-keys": "^5.1.2", + "tslib": "^2.3.1" + } + }, + "packages/remix/node_modules/@clerk/clerk-sdk-node": { + "version": "2.9.6", + "resolved": "https://registry.npmjs.org/@clerk/clerk-sdk-node/-/clerk-sdk-node-2.9.6.tgz", + "integrity": "sha512-T/fKQBMgRYyALN5ua7IpKwuyxpzCVYjK3bHk73hpqud+xm3mNe0gGmHGW+FH4YQhZ3rIArbPEkhyNnn50+nnmg==", + "dependencies": { + "@clerk/backend-core": "^0.5.1", + "@peculiar/webcrypto": "^1.2.3", + "camelcase-keys": "^6.2.2", + "cookies": "^0.8.0", + "deepmerge": "^4.2.2", + "got": "^11.8.2", + "jsonwebtoken": "^8.5.1", + "jwks-rsa": "^2.0.4", + "snakecase-keys": "^3.2.1", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=12" + } + }, + "packages/remix/node_modules/@clerk/clerk-sdk-node/node_modules/camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dependencies": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/remix/node_modules/@clerk/clerk-sdk-node/node_modules/snakecase-keys": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/snakecase-keys/-/snakecase-keys-3.2.1.tgz", + "integrity": "sha512-CjU5pyRfwOtaOITYv5C8DzpZ8XA/ieRsDpr93HI2r6e3YInC6moZpSQbmUtg8cTk58tq2x3jcG2gv+p1IZGmMA==", + "dependencies": { + "map-obj": "^4.1.0", + "to-snake-case": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, "packages/remix/node_modules/@types/node": { "version": "16.11.25", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.25.tgz", "integrity": "sha512-NrTwfD7L1RTc2qrHQD4RTTy4p0CO2LatKBEKEds3CaVuhoM/+DJzmWZl5f+ikR8cm8F5mfJxK+9rQq07gRiSjQ==", "dev": true }, + "packages/remix/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + }, "packages/remix/node_modules/cookie": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", @@ -23392,12 +23534,20 @@ "node": ">= 0.6" } }, + "packages/remix/node_modules/quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "engines": { + "node": ">=8" + } + }, "packages/sdk-node": { "name": "@clerk/clerk-sdk-node", - "version": "2.9.4", + "version": "2.9.7-staging.0", "license": "MIT", "dependencies": { - "@clerk/backend-core": "^0.4.4", + "@clerk/backend-core": "^0.5.2-staging.0", "@peculiar/webcrypto": "^1.2.3", "camelcase-keys": "^6.2.2", "cookies": "^0.8.0", @@ -23676,7 +23826,7 @@ "@babel/core": "^7.13.14", "@babel/preset-env": "^7.13.12", "@babel/preset-react": "^7.13.13", - "@clerk/types": "^1.25.4", + "@clerk/types": "^1.28.2-staging.0", "@popperjs/core": "^2.5.4", "@sentry/browser": "^6.3.0", "@svgr/webpack": "^6.2.1", @@ -23723,9 +23873,9 @@ } }, "packages/shared/node_modules/@clerk/types": { - "version": "1.25.4", - "resolved": "https://registry.npmjs.org/@clerk/types/-/types-1.25.4.tgz", - "integrity": "sha512-KXwIjF6lP9zEUk8aQVpTDhmxyvpX1GZZPbQzEjL+oZserOe1zKW97RqYatzmkKImUzqyGG+GbMe6bunPnKqA1w==", + "version": "1.28.2-staging.0", + "resolved": "https://registry.npmjs.org/@clerk/types/-/types-1.28.2-staging.0.tgz", + "integrity": "sha512-fOGVQAJ2uId29upNNnxtLaiIYGxD4p2nQ/vqzlqBvk7gpUBhWR7b4I9TMaBBxUiFbBDnlwDXEGNz8IIYRchsvA==", "dev": true, "engines": { "node": ">=14" @@ -25070,7 +25220,7 @@ "requires": { "@clerk/clerk-js": "^3.0.0-alpha.8", "@clerk/clerk-react": "^3.0.0-alpha.9", - "@clerk/types": "^1.25.4", + "@clerk/types": "^1.28.2-staging.0", "@types/jest": "^27.4.0", "@types/node": "^16.11.9", "@types/react": "^17.0.39", @@ -25085,9 +25235,9 @@ }, "dependencies": { "@clerk/types": { - "version": "1.25.4", - "resolved": "https://registry.npmjs.org/@clerk/types/-/types-1.25.4.tgz", - "integrity": "sha512-KXwIjF6lP9zEUk8aQVpTDhmxyvpX1GZZPbQzEjL+oZserOe1zKW97RqYatzmkKImUzqyGG+GbMe6bunPnKqA1w==", + "version": "1.28.2-staging.0", + "resolved": "https://registry.npmjs.org/@clerk/types/-/types-1.28.2-staging.0.tgz", + "integrity": "sha512-fOGVQAJ2uId29upNNnxtLaiIYGxD4p2nQ/vqzlqBvk7gpUBhWR7b4I9TMaBBxUiFbBDnlwDXEGNz8IIYRchsvA==", "dev": true }, "@types/node": { @@ -25224,7 +25374,7 @@ "@clerk/clerk-sdk-node": { "version": "file:packages/sdk-node", "requires": { - "@clerk/backend-core": "^0.4.4", + "@clerk/backend-core": "^0.5.2-staging.0", "@peculiar/webcrypto": "^1.2.3", "@types/cookies": "^0.7.7", "@types/express": "^4.17.11", @@ -25425,7 +25575,7 @@ "@clerk/edge": { "version": "file:packages/edge", "requires": { - "@clerk/backend-core": "^0.4.4", + "@clerk/backend-core": "^0.5.2-staging.0", "@peculiar/webcrypto": "^1.2.3", "@types/jest": "^27.4.0", "@types/node": "^16.11.12", @@ -25447,7 +25597,7 @@ "version": "file:packages/nextjs", "requires": { "@clerk/clerk-react": "^3.0.0-alpha.9", - "@clerk/clerk-sdk-node": "^2.9.0", + "@clerk/clerk-sdk-node": "^2.9.6", "@clerk/types": "^2.0.0-alpha.8", "@types/jest": "^27.4.0", "@types/node": "^16.11.9", @@ -25462,11 +25612,70 @@ "typescript": "4.5.5" }, "dependencies": { + "@clerk/backend-core": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@clerk/backend-core/-/backend-core-0.5.1.tgz", + "integrity": "sha512-+V/GbiLiFWkziXdMhooCXDEd3a+rDzDcjFo3LP3VNGUNxOW7mHBFxoVeWrjiBceQh8zhscrbUSRV+pmXq85Xdw==", + "requires": { + "camelcase-keys": "^7.0.1", + "query-string": "^7.0.1", + "snakecase-keys": "^5.1.2", + "tslib": "^2.3.1" + } + }, + "@clerk/clerk-sdk-node": { + "version": "2.9.6", + "resolved": "https://registry.npmjs.org/@clerk/clerk-sdk-node/-/clerk-sdk-node-2.9.6.tgz", + "integrity": "sha512-T/fKQBMgRYyALN5ua7IpKwuyxpzCVYjK3bHk73hpqud+xm3mNe0gGmHGW+FH4YQhZ3rIArbPEkhyNnn50+nnmg==", + "requires": { + "@clerk/backend-core": "^0.5.1", + "@peculiar/webcrypto": "^1.2.3", + "camelcase-keys": "^6.2.2", + "cookies": "^0.8.0", + "deepmerge": "^4.2.2", + "got": "^11.8.2", + "jsonwebtoken": "^8.5.1", + "jwks-rsa": "^2.0.4", + "snakecase-keys": "^3.2.1", + "tslib": "^2.3.1" + }, + "dependencies": { + "camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "requires": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + } + }, + "snakecase-keys": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/snakecase-keys/-/snakecase-keys-3.2.1.tgz", + "integrity": "sha512-CjU5pyRfwOtaOITYv5C8DzpZ8XA/ieRsDpr93HI2r6e3YInC6moZpSQbmUtg8cTk58tq2x3jcG2gv+p1IZGmMA==", + "requires": { + "map-obj": "^4.1.0", + "to-snake-case": "^1.0.0" + } + } + } + }, "@types/node": { "version": "16.11.22", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.22.tgz", "integrity": "sha512-DYNtJWauMQ9RNpesl4aVothr97/tIJM8HbyOXJ0AYT1Z2bEjLHyfjOBPAQQVMLf8h3kSShYfNk8Wnto8B2zHUA==", "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, + "quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==" } } }, @@ -25490,16 +25699,75 @@ "typescript": "4.5.5" }, "dependencies": { + "@clerk/backend-core": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@clerk/backend-core/-/backend-core-0.5.1.tgz", + "integrity": "sha512-+V/GbiLiFWkziXdMhooCXDEd3a+rDzDcjFo3LP3VNGUNxOW7mHBFxoVeWrjiBceQh8zhscrbUSRV+pmXq85Xdw==", + "requires": { + "camelcase-keys": "^7.0.1", + "query-string": "^7.0.1", + "snakecase-keys": "^5.1.2", + "tslib": "^2.3.1" + } + }, + "@clerk/clerk-sdk-node": { + "version": "2.9.6", + "resolved": "https://registry.npmjs.org/@clerk/clerk-sdk-node/-/clerk-sdk-node-2.9.6.tgz", + "integrity": "sha512-T/fKQBMgRYyALN5ua7IpKwuyxpzCVYjK3bHk73hpqud+xm3mNe0gGmHGW+FH4YQhZ3rIArbPEkhyNnn50+nnmg==", + "requires": { + "@clerk/backend-core": "^0.5.1", + "@peculiar/webcrypto": "^1.2.3", + "camelcase-keys": "^6.2.2", + "cookies": "^0.8.0", + "deepmerge": "^4.2.2", + "got": "^11.8.2", + "jsonwebtoken": "^8.5.1", + "jwks-rsa": "^2.0.4", + "snakecase-keys": "^3.2.1", + "tslib": "^2.3.1" + }, + "dependencies": { + "camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "requires": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + } + }, + "snakecase-keys": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/snakecase-keys/-/snakecase-keys-3.2.1.tgz", + "integrity": "sha512-CjU5pyRfwOtaOITYv5C8DzpZ8XA/ieRsDpr93HI2r6e3YInC6moZpSQbmUtg8cTk58tq2x3jcG2gv+p1IZGmMA==", + "requires": { + "map-obj": "^4.1.0", + "to-snake-case": "^1.0.0" + } + } + } + }, "@types/node": { "version": "16.11.25", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.25.tgz", "integrity": "sha512-NrTwfD7L1RTc2qrHQD4RTTy4p0CO2LatKBEKEds3CaVuhoM/+DJzmWZl5f+ikR8cm8F5mfJxK+9rQq07gRiSjQ==", "dev": true }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, "cookie": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" + }, + "quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==" } } }, @@ -25509,7 +25777,7 @@ "@babel/core": "^7.13.14", "@babel/preset-env": "^7.13.12", "@babel/preset-react": "^7.13.13", - "@clerk/types": "^1.25.4", + "@clerk/types": "^1.28.2-staging.0", "@popperjs/core": "^2.5.4", "@sentry/browser": "^6.3.0", "@svgr/webpack": "^6.2.1", @@ -25545,9 +25813,9 @@ }, "dependencies": { "@clerk/types": { - "version": "1.25.4", - "resolved": "https://registry.npmjs.org/@clerk/types/-/types-1.25.4.tgz", - "integrity": "sha512-KXwIjF6lP9zEUk8aQVpTDhmxyvpX1GZZPbQzEjL+oZserOe1zKW97RqYatzmkKImUzqyGG+GbMe6bunPnKqA1w==", + "version": "1.28.2-staging.0", + "resolved": "https://registry.npmjs.org/@clerk/types/-/types-1.28.2-staging.0.tgz", + "integrity": "sha512-fOGVQAJ2uId29upNNnxtLaiIYGxD4p2nQ/vqzlqBvk7gpUBhWR7b4I9TMaBBxUiFbBDnlwDXEGNz8IIYRchsvA==", "dev": true }, "@types/node": { @@ -40575,106 +40843,106 @@ } }, "turbo": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/turbo/-/turbo-1.1.2.tgz", - "integrity": "sha512-3ViHKyAkaBKNKwHASTa1zkVT3tVVhQNLrpxBS7LoN+794ouQUYmy6lf0rTqzG3iTZHtIDwC+piZSdTl4XjEVMg==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/turbo/-/turbo-1.1.5.tgz", + "integrity": "sha512-jXW8G4lr01/E/jS/66LYpEjwWFQAksC8TxR8gi3VGea7OeNj28l8zmXoY3IgT5H22MBnhmtOKV/GhsbPjI2Jrg==", "dev": true, "requires": { - "turbo-darwin-64": "1.1.2", - "turbo-darwin-arm64": "1.1.2", - "turbo-freebsd-64": "1.1.2", - "turbo-freebsd-arm64": "1.1.2", - "turbo-linux-32": "1.1.2", - "turbo-linux-64": "1.1.2", - "turbo-linux-arm": "1.1.2", - "turbo-linux-arm64": "1.1.2", - "turbo-linux-mips64le": "1.1.2", - "turbo-linux-ppc64le": "1.1.2", - "turbo-windows-32": "1.1.2", - "turbo-windows-64": "1.1.2" + "turbo-darwin-64": "1.1.5", + "turbo-darwin-arm64": "1.1.5", + "turbo-freebsd-64": "1.1.5", + "turbo-freebsd-arm64": "1.1.5", + "turbo-linux-32": "1.1.5", + "turbo-linux-64": "1.1.5", + "turbo-linux-arm": "1.1.5", + "turbo-linux-arm64": "1.1.5", + "turbo-linux-mips64le": "1.1.5", + "turbo-linux-ppc64le": "1.1.5", + "turbo-windows-32": "1.1.5", + "turbo-windows-64": "1.1.5" } }, "turbo-darwin-64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-1.1.2.tgz", - "integrity": "sha512-rua17HnVvAqAU54gVfiQoH7cfopOqANv+yI6NtxLMD8aFfX2cJ9m8SSvH2v2vCaToNDW6OnTkdqDKQpqIHzbCw==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-1.1.5.tgz", + "integrity": "sha512-qdGMylQ408NmYhzuMmx+25W0iHFyFMRPO4579tDEv+WBiVDfAEYEzjajE4c+CQOLhd1aVEaPdSa+YhngQUgoDQ==", "dev": true, "optional": true }, "turbo-darwin-arm64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-1.1.2.tgz", - "integrity": "sha512-otqSQNYDyKg0KqB3NM0BI4oiRPKdJkUE/XBn8dcUS+zeRLrL00XtaM0eSwynZs1tb6zU/Y+SPMSBRygD1TCOnw==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-1.1.5.tgz", + "integrity": "sha512-mXU324d3vYzxRT9FSSkW9yG2BvFosd0f4DUvqy4qms8wzM6Yv9Aeo4zZTL86rF88UYGUkbiRaPQUeceb/QARVg==", "dev": true, "optional": true }, "turbo-freebsd-64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/turbo-freebsd-64/-/turbo-freebsd-64-1.1.2.tgz", - "integrity": "sha512-2nxwVDTAM0DtIQ2i3UOfEsQLF7vp+XZ/b9SKtiHxz710fXvdyuGivYI25axDdcBn8kQ45rnbUnarF1aW8CMGgg==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/turbo-freebsd-64/-/turbo-freebsd-64-1.1.5.tgz", + "integrity": "sha512-qjjPTnZKOxw2x1Ito3yZAYDcwsCEg/5kYJwbPVvDn1jyXoxr3pUxTHUohroxQ6EmyxQ28qL7QpCVWDoQpDwrOQ==", "dev": true, "optional": true }, "turbo-freebsd-arm64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/turbo-freebsd-arm64/-/turbo-freebsd-arm64-1.1.2.tgz", - "integrity": "sha512-ro1Ah96yzgzyT0BJe1mceAqxPxi0pUwzAvN3IKVpMqi4hYkT3aRbzDCaSxzyC6let2Al/NUsgHnbAv38OF2Xkw==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/turbo-freebsd-arm64/-/turbo-freebsd-arm64-1.1.5.tgz", + "integrity": "sha512-jYW+Th9Y6yEYevaFe7v3lFQoxyrpd8wX5KuuvqLazMRbNxvKgqTDmT7AbCOGJY5ejzqGnMlTGkQr8c3g3B8ndA==", "dev": true, "optional": true }, "turbo-linux-32": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/turbo-linux-32/-/turbo-linux-32-1.1.2.tgz", - "integrity": "sha512-HKBsETxQMVaf/DJwMg7pypPbGA6KEu0gEf9C8o2aPJvwMPBYgNsNaU08Xizuh5xzEQTzpbIWfQyqdNgMV4RG3Q==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/turbo-linux-32/-/turbo-linux-32-1.1.5.tgz", + "integrity": "sha512-c5I8tdR1jD8L8pJWk+rlO734bpWI1gwGdvNOaA/IGZxzOfDSn4CGoUErnUPgOadT8azi7lT9UPQf/pLfEvjCOw==", "dev": true, "optional": true }, "turbo-linux-64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-1.1.2.tgz", - "integrity": "sha512-IklKsOklcRHIWkTzKg95BQ6jgJ53kLvRMrp8yqzlvZprkWdiyhAgUxrUTTHOOTce2XA3+jdN2+MwixG44uY2vg==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-1.1.5.tgz", + "integrity": "sha512-BZAxLfIkEtQa7u+VPYpdeVVJH6ab4WwXv4oCrUDaZf2BseDUxr57y2ASAWNFsg40T3oXXt4Kcbdc5LibjWQdtQ==", "dev": true, "optional": true }, "turbo-linux-arm": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/turbo-linux-arm/-/turbo-linux-arm-1.1.2.tgz", - "integrity": "sha512-CNbaTvRozq7H/5jpy9OZlzJ6BkeEXF+nF2n9dHiUrbAXd3nq84Qt9odcQJmGnexP19YS9w6l3tIHncX4BgwtqA==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/turbo-linux-arm/-/turbo-linux-arm-1.1.5.tgz", + "integrity": "sha512-X6J05gQSWTc2c/TCkOQdFLhr35pUjEExY6K8yanYs2QKgd4GvDHmxYaBZ+6f90qcIUHYpe++adDPJcuAUv+8ug==", "dev": true, "optional": true }, "turbo-linux-arm64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-1.1.2.tgz", - "integrity": "sha512-3kS6sk2lOtuBBqkcL+yeGqD1yew4UZ1o7XUcbDD8UPwhF2kAfK7Qs0vTJw4lnO1scjhihkoTrmXM7yozvjf4/w==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-1.1.5.tgz", + "integrity": "sha512-8/yz5L0B6Jb0pNcvx/08LcPswizqggxQ0zlFEw+Oh9RAC+ZM5+X2YiMyKolvLCpkoRqrlKku0lmXH7mx6DWbig==", "dev": true, "optional": true }, "turbo-linux-mips64le": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/turbo-linux-mips64le/-/turbo-linux-mips64le-1.1.2.tgz", - "integrity": "sha512-CDoXVIlW43C6KLgYxe13KkG8h6DswXHxbTVHiZdOwRQ56j46lU+JOVpLoh6wpQGcHvj58VEiypZBRTGVFMeogw==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/turbo-linux-mips64le/-/turbo-linux-mips64le-1.1.5.tgz", + "integrity": "sha512-K26bEFcLDGPkcaW7Eq4CMSxUbJf/x58aE92+0tONhrxXzamaBqTrSxPYlk/T8OoH7HxOvja2ctkpeI/NRAoIyw==", "dev": true, "optional": true }, "turbo-linux-ppc64le": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/turbo-linux-ppc64le/-/turbo-linux-ppc64le-1.1.2.tgz", - "integrity": "sha512-xPVMHoiOJE/qI63jSOXwYIUFQXLdstxDV6fLnRxvq0QnJNxgTKq+mLUeE8M4LDVh1bdqHLcfk/HmyQ6+X1XVkQ==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/turbo-linux-ppc64le/-/turbo-linux-ppc64le-1.1.5.tgz", + "integrity": "sha512-fr1/5yf8fe1BJiW/6Y9lmV+kxZZC3u3xvSBC5AXDSl9u3aJFZl96CRE9tOJbTZMaOVGxhplKD+EiHbjIxUnTrA==", "dev": true, "optional": true }, "turbo-windows-32": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/turbo-windows-32/-/turbo-windows-32-1.1.2.tgz", - "integrity": "sha512-Gj1yvPE0aMDSOxGVSBaecLnwsVDT1xX8U0dtLrg52TYY2jlaci0atjHKr9nTFuX7z8uwAf6PopwdriGoCeT3ng==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/turbo-windows-32/-/turbo-windows-32-1.1.5.tgz", + "integrity": "sha512-K9LdIgQXJ7jL0aLJS0l2asJAH/vYBFP7qFzODiAcJ1EeKBjYqAVnIxFQrUN07lzNDtL9WK/aN5q0bJCDnhwTQw==", "dev": true, "optional": true }, "turbo-windows-64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-1.1.2.tgz", - "integrity": "sha512-0Ncx/iKhnKrdAU8hJ+8NUcF9jtFr8KoW5mMWfiFzy+mgUbVKbpzWT2eoGR6zJExedQsRvYOejbEX5iihbnj5bA==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-1.1.5.tgz", + "integrity": "sha512-c2Jkmw8yGZVz4opzEvB5HAf9XkA8CZBnorie46s44ec0FaNbcP9SCuUNvgAHxqDIHTGWC4A5PoPn0owkD3ss6A==", "dev": true, "optional": true }, diff --git a/package.json b/package.json index d9959f0785b..263371d8a3d 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "lerna": "^4.0.0", "prettier": "^2.3.1", "rimraf": "^3.0.2", - "turbo": "^1", + "turbo": "^1.1.5", "typescript": "4.5.5" }, "scripts": { @@ -36,7 +36,7 @@ "lint-fix": "eslint . --ext .ts", "bump": "lerna version", "bump:next": "lerna version --conventional-prerelease", - "bump:staging": "lerna version prepatch --preid staging", + "bump:staging": "lerna version prepatch --preid staging --no-changelog", "graduate": "lerna version --conventional-graduate", "release:staging": "lerna publish from-package --dist-tag staging", "release": "lerna publish from-package", diff --git a/packages/backend-core/API.md b/packages/backend-core/API.md index 12353e73706..8cc6c251a41 100644 --- a/packages/backend-core/API.md +++ b/packages/backend-core/API.md @@ -18,6 +18,8 @@ Reference of the methods supported in the Clerk Backend API wrapper. [API refere - [getInvitationList()](#getinvitationlist) - [createInvitation(params)](#createinvitationparams) - [revokeInvitation(invitationId)](#revokeinvitationinvitationId) +- [Organization operations](#organization-operations) + - [createOrganization(params)](#createorganizationparams) - [Session operations](#session-operations) - [getSessionList({ clientId, userId })](#getsessionlist-clientid-userid-) - [getSession(sessionId)](#getsessionsessionid) @@ -145,6 +147,21 @@ Only active (i.e. non-revoked) invitations can be revoked. const invitation = await clerkAPI.invitations.revokeInvitation('inv_some-id'); ``` +## Organization operations + +Organization operations are exposed by the `organizations` sub-api (`clerkAPI.organizations`). + +#### createOrganization(params) + +Creates a new organization with the given name. You need to provide the user ID who is going to be the organization owner. The user will become an administrator for the organization. + +```js +const organization = await clerkAPI.organizations.createOrganization({ + name: 'Acme Inc', + createdBy: 'user_1o4q123qMeCkKKIXcA9h8', +}); +``` + ## Session operations Session operations are exposed by the `sessions` sub-api (`clerkAPI.sessions`). diff --git a/packages/backend-core/CHANGELOG.md b/packages/backend-core/CHANGELOG.md index a975db5b6ad..5c602432889 100644 --- a/packages/backend-core/CHANGELOG.md +++ b/packages/backend-core/CHANGELOG.md @@ -3,6 +3,24 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +### [0.5.1](https://github.com/clerkinc/javascript/compare/@clerk/backend-core@0.5.0...@clerk/backend-core@0.5.1) (2022-03-04) + + +### Bug Fixes + +* **backend-core:** Add JWTPayload orgs claim type ([32bb54d](https://github.com/clerkinc/javascript/commit/32bb54d76339e3fbef6ce29bc9e77dd6ebc51b3b)) + + + +## [0.5.0](https://github.com/clerkinc/javascript/compare/@clerk/backend-core@0.4.4...@clerk/backend-core@0.5.0) (2022-03-04) + + +### Features + +* **backend-core:** Organizations API ([f4dde55](https://github.com/clerkinc/javascript/commit/f4dde550190d3b4f894e17f5784c29f934daab40)) + + + ### [0.4.4](https://github.com/clerkinc/javascript/compare/@clerk/backend-core@0.4.4-staging.0...@clerk/backend-core@0.4.4) (2022-02-24) **Note:** Version bump only for package @clerk/backend-core diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json index 51b82115a65..2db78bf7e53 100644 --- a/packages/backend-core/package.json +++ b/packages/backend-core/package.json @@ -1,6 +1,6 @@ { "name": "@clerk/backend-core", - "version": "0.4.4", + "version": "0.5.2-staging.0", "license": "MIT", "description": "Clerk Backend API core resources and authentication utilities for JavaScript environments.", "scripts": { diff --git a/packages/backend-core/src/__tests__/apis/InvitationApi.test.ts b/packages/backend-core/src/__tests__/apis/InvitationApi.test.ts index e2f6278f998..3bb5fa36b4b 100644 --- a/packages/backend-core/src/__tests__/apis/InvitationApi.test.ts +++ b/packages/backend-core/src/__tests__/apis/InvitationApi.test.ts @@ -76,6 +76,42 @@ test('createInvitation() accepts a redirectUrl', async () => { ); }); +test('createInvitation() accepts publicMetadata', async () => { + const emailAddress = 'test@example.com'; + const publicMetadata = { + hello: 'world', + }; + const resJSON = { + object: 'invitation', + id: 'inv_randomid', + email_address: emailAddress, + public_metadata: publicMetadata, + created_at: 1611948436, + updated_at: 1611948436, + }; + + nock('https://api.clerk.dev') + .post('/v1/invitations', { + email_address: emailAddress, + public_metadata: publicMetadata, + }) + .reply(200, resJSON); + + const invitation = await TestBackendAPIClient.invitations.createInvitation({ + emailAddress, + publicMetadata, + }); + expect(invitation).toEqual( + new Invitation({ + id: resJSON.id, + emailAddress, + publicMetadata, + createdAt: resJSON.created_at, + updatedAt: resJSON.updated_at, + }) + ); +}); + test('revokeInvitation() revokes an invitation', async () => { const id = 'inv_randomid'; const resJSON = { diff --git a/packages/backend-core/src/__tests__/apis/OrganizationApi.test.ts b/packages/backend-core/src/__tests__/apis/OrganizationApi.test.ts new file mode 100644 index 00000000000..ddc8b727768 --- /dev/null +++ b/packages/backend-core/src/__tests__/apis/OrganizationApi.test.ts @@ -0,0 +1,37 @@ +import nock from 'nock'; + +import { Organization } from '../../api/resources'; +import { TestBackendAPIClient } from '../TestBackendAPI'; + +test('createOrganization() creates an organization', async () => { + const name = 'Acme Inc'; + const createdBy = 'user_randomid'; + const resJSON = { + object: 'organization', + id: 'org_randomid', + name, + created_at: 1611948436, + updated_at: 1611948436, + }; + + nock('https://api.clerk.dev') + .post('/v1/organizations', { + name, + created_by: createdBy, + }) + .reply(200, resJSON); + + const organization = + await TestBackendAPIClient.organizations.createOrganization({ + name, + createdBy, + }); + expect(organization).toEqual( + new Organization({ + id: resJSON.id, + name, + createdAt: resJSON.created_at, + updatedAt: resJSON.updated_at, + }), + ); +}); diff --git a/packages/backend-core/src/__tests__/apis/UserApi.test.ts b/packages/backend-core/src/__tests__/apis/UserApi.test.ts index ed5377c06ba..f0599a848e6 100644 --- a/packages/backend-core/src/__tests__/apis/UserApi.test.ts +++ b/packages/backend-core/src/__tests__/apis/UserApi.test.ts @@ -115,7 +115,13 @@ test('getUser() returns a single user', async () => { expect(user.externalAccounts.length).toEqual(2); expect(user.externalAccounts[0].provider).toEqual('google'); + expect(user.externalAccounts[0].username).toEqual('tester'); + expect(user.externalAccounts[0].publicMetadata).toBeInstanceOf(Object); + expect(user.externalAccounts[0].label).toBeNull(); expect(user.externalAccounts[1].provider).toEqual('facebook'); + expect(user.externalAccounts[1].username).toBeNull(); + expect(user.externalAccounts[1].publicMetadata).toMatchObject({'extra': 'more info'}); + expect(user.externalAccounts[1].label).toEqual('clerk'); expect(user.web3Wallets.length).toEqual(1); expect(user.web3Wallets[0].web3Wallet).toEqual( diff --git a/packages/backend-core/src/__tests__/apis/responses/getUser.json b/packages/backend-core/src/__tests__/apis/responses/getUser.json index 87b26f55617..afd0be25f18 100644 --- a/packages/backend-core/src/__tests__/apis/responses/getUser.json +++ b/packages/backend-core/src/__tests__/apis/responses/getUser.json @@ -91,7 +91,10 @@ "email_address": "kyle@tech.com", "given_name": "Kyle", "family_name": "Reese", - "picture": "https://lh3.googleusercontent.com/-MvTefx9nU6o/BBBBBBBBBBI/BBBBBBBBBBB/ereRAMWiew8hQ5IaSVdTZWm1Y1G1z0T_P7Q/s96-c/photo.jpg" + "picture": "https://lh3.googleusercontent.com/-MvTefx9nU6o/BBBBBBBBBBI/BBBBBBBBBBB/ereRAMWiew8hQ5IaSVdTZWm1Y1G1z0T_P7Q/s96-c/photo.jpg", + "username": "tester", + "public_metadata": {}, + "label": null }, { "object": "facebook_account", @@ -101,7 +104,12 @@ "email_address": "kyle@tech.com", "first_name": "Kyle", "last_name": "Reese", - "picture": "https://platform-lookaside.fbsbx.com/platform/profilepic/?asid=16357923188267094&height=50&width=50&ext=2319847405&hash=AeQyoXRpxMMso8vNHSw" + "picture": "https://platform-lookaside.fbsbx.com/platform/profilepic/?asid=16357923188267094&height=50&width=50&ext=2319847405&hash=AeQyoXRpxMMso8vNHSw", + "username": null, + "public_metadata": { + "extra": "more info" + }, + "label": "clerk" } ], "public_metadata": { diff --git a/packages/backend-core/src/__tests__/utils/Deserializer.test.ts b/packages/backend-core/src/__tests__/utils/Deserializer.test.ts index d553f2cd2ca..3e65add1110 100644 --- a/packages/backend-core/src/__tests__/utils/Deserializer.test.ts +++ b/packages/backend-core/src/__tests__/utils/Deserializer.test.ts @@ -3,6 +3,7 @@ import { Client, Email, Invitation, + Organization, Session, SMSMessage, } from '../../api/resources'; @@ -46,6 +47,14 @@ const invitationJSON = { updated_at: 1612378465, }; +const organizationJSON = { + object: 'organization', + id: 'org_randomid', + name: 'Acme Inc', + created_at: 1612378465, + updated_at: 1612378465, +}; + const sessionJSON = { object: 'session', id: 'sess_efgh', @@ -108,6 +117,18 @@ test('deserializes an array of Invitation objects', () => { expect(invitations[0]).toBeInstanceOf(Invitation); }); +test('deserializes an Organization object', () => { + const organization = deserialize(organizationJSON); + expect(organization).toBeInstanceOf(Organization); +}); + +test('deserializes an array of Organization objects', () => { + const organizations = deserialize([organizationJSON]); + expect(organizations).toBeInstanceOf(Array); + expect(organizations.length).toBe(1); + expect(organizations[0]).toBeInstanceOf(Organization); +}); + test('deserializes a Session object', () => { const session = deserialize(sessionJSON); expect(session).toBeInstanceOf(Session); diff --git a/packages/backend-core/src/api/ClerkBackendAPI.ts b/packages/backend-core/src/api/ClerkBackendAPI.ts index 2c6d124bab0..918435b62ee 100644 --- a/packages/backend-core/src/api/ClerkBackendAPI.ts +++ b/packages/backend-core/src/api/ClerkBackendAPI.ts @@ -3,6 +3,7 @@ import { ClientApi, EmailApi, InvitationApi, + OrganizationApi, SessionApi, SMSMessageApi, UserApi, @@ -45,6 +46,7 @@ export class ClerkBackendAPI { private _clientApi?: ClientApi; private _emailApi?: EmailApi; private _invitationApi?: InvitationApi; + private _organizationApi?: OrganizationApi; private _sessionApi?: SessionApi; private _smsMessageApi?: SMSMessageApi; private _userApi?: UserApi; @@ -69,7 +71,7 @@ export class ClerkBackendAPI { fetcher, libName, libVersion, - packageRepo + packageRepo, ); } @@ -103,7 +105,7 @@ export class ClerkBackendAPI { get allowlistIdentifiers(): AllowlistIdentifierApi { if (!this._allowlistIdentifierApi) { this._allowlistIdentifierApi = new AllowlistIdentifierApi( - this._restClient + this._restClient, ); } return this._allowlistIdentifierApi; @@ -132,6 +134,13 @@ export class ClerkBackendAPI { return this._invitationApi; } + get organizations(): OrganizationApi { + if (!this._organizationApi) { + this._organizationApi = new OrganizationApi(this._restClient); + } + return this._organizationApi; + } + get sessions(): SessionApi { if (!this._sessionApi) { this._sessionApi = new SessionApi(this._restClient); diff --git a/packages/backend-core/src/api/collection/InvitationApi.ts b/packages/backend-core/src/api/collection/InvitationApi.ts index a760c56a84f..1f0726232fa 100644 --- a/packages/backend-core/src/api/collection/InvitationApi.ts +++ b/packages/backend-core/src/api/collection/InvitationApi.ts @@ -6,6 +6,7 @@ const basePath = '/invitations'; type CreateParams = { emailAddress: string; redirectUrl?: string; + publicMetadata?: Record; }; export class InvitationApi extends AbstractApi { diff --git a/packages/backend-core/src/api/collection/OrganizationApi.ts b/packages/backend-core/src/api/collection/OrganizationApi.ts new file mode 100644 index 00000000000..af5957afbdf --- /dev/null +++ b/packages/backend-core/src/api/collection/OrganizationApi.ts @@ -0,0 +1,19 @@ +import { Organization } from '../resources/Organization'; +import { AbstractApi } from './AbstractApi'; + +const basePath = '/organizations'; + +type CreateParams = { + name: string; + createdBy: string; +}; + +export class OrganizationApi extends AbstractApi { + public async createOrganization(params: CreateParams) { + return this._restClient.makeRequest({ + method: 'POST', + path: basePath, + bodyParams: params, + }); + } +} diff --git a/packages/backend-core/src/api/collection/index.ts b/packages/backend-core/src/api/collection/index.ts index 788b2354abd..67683873002 100644 --- a/packages/backend-core/src/api/collection/index.ts +++ b/packages/backend-core/src/api/collection/index.ts @@ -3,6 +3,7 @@ export * from './AllowlistIdentifierApi'; export * from './ClientApi'; export * from './EmailApi'; export * from './InvitationApi'; +export * from './OrganizationApi'; export * from './SMSMessageApi'; export * from './SessionApi'; export * from './UserApi'; diff --git a/packages/backend-core/src/api/resources/ExternalAccount.ts b/packages/backend-core/src/api/resources/ExternalAccount.ts index 461fc9becae..20496fa5659 100644 --- a/packages/backend-core/src/api/resources/ExternalAccount.ts +++ b/packages/backend-core/src/api/resources/ExternalAccount.ts @@ -16,6 +16,9 @@ export class ExternalAccount { 'firstName', 'lastName', 'picture', + 'username', + 'publicMetadata', + 'label', ]; static defaults = {}; @@ -30,6 +33,9 @@ export class ExternalAccount { obj.id = data.id; obj.approvedScopes = data.approved_scopes; obj.emailAddress = data.email_address; + obj.username = data.username; + obj.publicMetadata = data.public_metadata; + obj.label = data.label; switch (data.object) { case ObjectType.FacebookAccount: { diff --git a/packages/backend-core/src/api/resources/Invitation.ts b/packages/backend-core/src/api/resources/Invitation.ts index 77961a67848..80439725fb8 100644 --- a/packages/backend-core/src/api/resources/Invitation.ts +++ b/packages/backend-core/src/api/resources/Invitation.ts @@ -9,7 +9,7 @@ interface InvitationPayload extends InvitationProps {} export interface Invitation extends InvitationPayload {} export class Invitation { - static attributes = ['id', 'emailAddress', 'createdAt', 'updatedAt']; + static attributes = ['id', 'emailAddress', 'publicMetadata', 'createdAt', 'updatedAt']; static defaults = []; diff --git a/packages/backend-core/src/api/resources/JSON.ts b/packages/backend-core/src/api/resources/JSON.ts index 58e285c3d70..c1c4ecc9ea1 100644 --- a/packages/backend-core/src/api/resources/JSON.ts +++ b/packages/backend-core/src/api/resources/JSON.ts @@ -16,6 +16,7 @@ export enum ObjectType { FacebookAccount = 'facebook_account', GoogleAccount = 'google_account', Invitation = 'invitation', + Organization = 'organization', PhoneNumber = 'phone_number', Session = 'session', SignInAttempt = 'sign_in_attempt', @@ -73,6 +74,9 @@ export interface FacebookAccountJSON extends ClerkResourceJSON { first_name: string; last_name: string; picture: string; + username?: string; + public_metadata: Record; + label?: string; } export interface GoogleAccountJSON extends ClerkResourceJSON { @@ -83,6 +87,9 @@ export interface GoogleAccountJSON extends ClerkResourceJSON { given_name: string; family_name: string; picture: string; + username?: string; + public_metadata: Record; + label?: string; } export interface ExtAccountJSON extends ClerkResourceJSON { @@ -95,6 +102,9 @@ export interface ExtAccountJSON extends ClerkResourceJSON { first_name: string; last_name: string; avatar_url: string; + username?: string; + public_metadata: Record; + label?: string; } export type ExternalAccountJSON = @@ -113,6 +123,13 @@ export interface InvitationJSON extends ClerkResourceJSON { updated_at: number; } +export interface OrganizationJSON extends ClerkResourceJSON { + object: ObjectType.Organization; + name: string; + created_at: number; + updated_at: number; +} + export interface PhoneNumberJSON extends ClerkResourceJSON { object: ObjectType.PhoneNumber; phone_number: string; diff --git a/packages/backend-core/src/api/resources/Organization.ts b/packages/backend-core/src/api/resources/Organization.ts new file mode 100644 index 00000000000..d7886187c9c --- /dev/null +++ b/packages/backend-core/src/api/resources/Organization.ts @@ -0,0 +1,23 @@ +import camelcaseKeys from 'camelcase-keys'; + +import filterKeys from '../utils/Filter'; +import type { OrganizationJSON } from './JSON'; +import type { OrganizationProps } from './Props'; + +interface OrganizationPayload extends OrganizationProps {} + +export class Organization { + static attributes = ['id', 'name', 'createdAt', 'updatedAt']; + + static defaults = []; + + constructor(data: Partial = {}) { + Object.assign(this, Organization.defaults, data); + } + + static fromJSON(data: OrganizationJSON): Organization { + const camelcased = camelcaseKeys(data); + const filtered = filterKeys(camelcased, Organization.attributes); + return new Organization(filtered as OrganizationPayload); + } +} diff --git a/packages/backend-core/src/api/resources/Props.ts b/packages/backend-core/src/api/resources/Props.ts index 5f28a2b058b..7c233baeff7 100644 --- a/packages/backend-core/src/api/resources/Props.ts +++ b/packages/backend-core/src/api/resources/Props.ts @@ -51,6 +51,9 @@ export interface ExternalAccountProps extends ClerkProps { firstName: Nullable; lastName: Nullable; picture: Nullable; + username: Nullable; + publicMetadata: Record; + label: Nullable; } export interface IdentificationLinkProps extends ClerkProps { @@ -59,6 +62,13 @@ export interface IdentificationLinkProps extends ClerkProps { export interface InvitationProps extends ClerkProps { emailAddress: string; + publicMetadata?: Record; + createdAt: number; + updatedAt: number; +} + +export interface OrganizationProps extends ClerkProps { + name: string; createdAt: number; updatedAt: number; } diff --git a/packages/backend-core/src/api/resources/index.ts b/packages/backend-core/src/api/resources/index.ts index 45f667b7035..5776810fd6c 100644 --- a/packages/backend-core/src/api/resources/index.ts +++ b/packages/backend-core/src/api/resources/index.ts @@ -6,6 +6,7 @@ export * from './Enums'; export * from './ExternalAccount'; export * from './IdentificationLink'; export * from './Invitation'; +export * from './Organization'; export * from './JSON'; export * from './PhoneNumber'; export * from './Props'; diff --git a/packages/backend-core/src/api/utils/Deserializer.ts b/packages/backend-core/src/api/utils/Deserializer.ts index a5611e67620..8c64305ab7d 100644 --- a/packages/backend-core/src/api/utils/Deserializer.ts +++ b/packages/backend-core/src/api/utils/Deserializer.ts @@ -1,17 +1,20 @@ -import { AllowlistIdentifier } from '../resources/AllowlistIdentifier'; -import { Client } from '../resources/Client'; -import { Email } from '../resources/Email'; -import { Invitation } from '../resources/Invitation'; +import { + AllowlistIdentifier, + Client, + Email, + Invitation, + Organization, + Session, + SMSMessage, + User, +} from '../resources'; import { ObjectType } from '../resources/JSON'; -import { Session } from '../resources/Session'; -import { SMSMessage } from '../resources/SMSMessage'; -import { User } from '../resources/User'; import Logger from './Logger'; // FIXME don't return any export default function deserialize(data: any): any { if (Array.isArray(data)) { - return data.map((item) => jsonToObject(item)); + return data.map(item => jsonToObject(item)); } else { return jsonToObject(data); } @@ -29,6 +32,8 @@ function jsonToObject(item: any): any { return Email.fromJSON(item); case ObjectType.Invitation: return Invitation.fromJSON(item); + case ObjectType.Organization: + return Organization.fromJSON(item); case ObjectType.User: return User.fromJSON(item); case ObjectType.Session: diff --git a/packages/backend-core/src/util/types.ts b/packages/backend-core/src/util/types.ts index 4589873f1b0..ec43bd640f8 100644 --- a/packages/backend-core/src/util/types.ts +++ b/packages/backend-core/src/util/types.ts @@ -39,12 +39,19 @@ export interface JWTPayload { */ azp?: string; + /** + * + */ + orgs?: Record; + /** * Any other JWT Claim Set member. */ [propName: string]: unknown; } +type MembershipRole = 'admin' | 'basic_member'; + export interface JWT { header: JWTHeader; payload: JWTPayload; diff --git a/packages/clerk-js/CHANGELOG.md b/packages/clerk-js/CHANGELOG.md index 15713f39e91..802c0e4da9e 100644 --- a/packages/clerk-js/CHANGELOG.md +++ b/packages/clerk-js/CHANGELOG.md @@ -28,6 +28,70 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline +### [2.17.1](https://github.com/clerkinc/javascript/compare/@clerk/clerk-js@2.17.0...@clerk/clerk-js@2.17.1) (2022-03-04) + + +### Bug Fixes + +* **clerk-react,clerk-js,types:** Crate of API feedback fixes ([721ce72](https://github.com/clerkinc/javascript/commit/721ce7228c37b012891b2bec8caf290239164d05)) + + + +## [2.17.0](https://github.com/clerkinc/javascript/compare/@clerk/clerk-js@2.16.1...@clerk/clerk-js@2.17.0) (2022-03-04) + + +### Features + +* **clerk-js,clerk-react:** GetOrganization/s hook methods, fetching mechanism alignment ([fc11087](https://github.com/clerkinc/javascript/commit/fc110874f9a3e056cd43c773c267409dd9b318d6)) +* **clerk-js:** Add more attributes on organization models ([af010ba](https://github.com/clerkinc/javascript/commit/af010bac4b6e0519eff42d210049c7b3a6bda203)) +* **clerk-js:** Add organization basic resources ([09f9012](https://github.com/clerkinc/javascript/commit/09f90126282f757cee6f97e7eae8747abc641bb0)) +* **clerk-js:** Add useOrganization hook ([480c422](https://github.com/clerkinc/javascript/commit/480c422774472fc712afdfe6ded2677b458d3ef0)) +* **clerk-js:** Basic organization data shape tests ([0ca9a31](https://github.com/clerkinc/javascript/commit/0ca9a3114b34bfaa338e6e90f1b0d57e02b7dd58)) +* **clerk-js:** Invitation flow draft ([d6faaab](https://github.com/clerkinc/javascript/commit/d6faaabb7efec09a699c7e83ba24fd4bad199d6b)) +* **clerk-js:** Sign up next draft and fixes ([e2eef78](https://github.com/clerkinc/javascript/commit/e2eef782d644f7fd1925fee67ee81d27473255fc)) +* **clerk-js:** SignUp with organization invitation flow draft ([2a9edbd](https://github.com/clerkinc/javascript/commit/2a9edbd52916f9bc037f266d1f96269cf54023cb)) +* **clerk-react,clerk-js:** Add useOrganization hook using __unstable attribute ([1635132](https://github.com/clerkinc/javascript/commit/16351321a99945d167cbf6e6ca0efdbbbf7efe5a)) + + +### Bug Fixes + +* **clerk-js:** Don't use ResizeObserver on old browsers ([581c5cd](https://github.com/clerkinc/javascript/commit/581c5cde9df542b7dcb6d69f61feaf480f7a0075)) +* **types:** Guarantee elements not in oauth sorting array will be sorted last ([f3c2869](https://github.com/clerkinc/javascript/commit/f3c2869bc244fc594522ef8f889055f82d31463f)) + + + +### [2.16.1](https://github.com/clerkinc/javascript/compare/@clerk/clerk-js@2.16.0...@clerk/clerk-js@2.16.1) (2022-03-03) + + +### Bug Fixes + +* **types:** Consolidate oauth provider types ([bce9ef5](https://github.com/clerkinc/javascript/commit/bce9ef5cbfe02e11fe71db3e34dbf4fd9be9c3ed)) + + + +## [2.16.0](https://github.com/clerkinc/javascript/compare/@clerk/clerk-js@2.15.0...@clerk/clerk-js@2.16.0) (2022-03-02) + + +### Features + +* **types,clerk-js:** Introduce Notion OAuth ([#72](https://github.com/clerkinc/javascript/issues/72)) ([9e556d0](https://github.com/clerkinc/javascript/commit/9e556d00fb41dedbbd05de59947d00c720bb3d95)) + + +### Bug Fixes + +* **clerk-js:** Clear invalid invitation token value ([0c5dc85](https://github.com/clerkinc/javascript/commit/0c5dc85bd69b1050bf36e7108b38868e22022e61)) + + + +## [2.15.0](https://github.com/clerkinc/javascript/compare/@clerk/clerk-js@2.14.3...@clerk/clerk-js@2.15.0) (2022-03-01) + + +### Features + +* **types:** Add support for oauth_microsoft ([96c1cc6](https://github.com/clerkinc/javascript/commit/96c1cc6817b9bbc6917ea2773498299c1ff9b951)) + + + ### [2.14.3](https://github.com/clerkinc/javascript/compare/@clerk/clerk-js@2.14.3-staging.0...@clerk/clerk-js@2.14.3) (2022-02-24) **Note:** Version bump only for package @clerk/clerk-js diff --git a/packages/clerk-js/src/core/clerk.ts b/packages/clerk-js/src/core/clerk.ts index 03e2113a992..6ba9b6f1eab 100644 --- a/packages/clerk-js/src/core/clerk.ts +++ b/packages/clerk-js/src/core/clerk.ts @@ -7,10 +7,12 @@ import type { Clerk as ClerkInterface, ClerkOptions, ClientResource, + CreateOrganizationParams, EnvironmentResource, HandleMagicLinkVerificationParams, HandleOAuthCallbackParams, ListenerCallback, + OrganizationResource, RedirectOptions, Resources, SignInProps, @@ -61,6 +63,7 @@ import { Environment, MagicLinkError, MagicLinkErrorCode, + Organization, } from './resources/internal'; export type ClerkCoreBroadcastChannelEvent = { type: 'signout' }; @@ -570,6 +573,24 @@ export default class Clerk implements ClerkInterface { } }; + public createOrganization = async ({ + name, + }: CreateOrganizationParams): Promise => { + return await Organization.create(name); + }; + + public getOrganizations = async (): Promise => { + return await Organization.retrieve(); + }; + + public getOrganization = async ( + organizationId: string, + ): Promise => { + return (await Organization.retrieve()).find( + org => org.id === organizationId, + ); + }; + updateClient = (newClient: ClientResource): void => { if (!this.client) { // This is the first time client is being diff --git a/packages/clerk-js/src/core/resources/AuthConfig.ts b/packages/clerk-js/src/core/resources/AuthConfig.ts index c9bb1dfc8ad..2d176e87d7c 100644 --- a/packages/clerk-js/src/core/resources/AuthConfig.ts +++ b/packages/clerk-js/src/core/resources/AuthConfig.ts @@ -1,29 +1,8 @@ -import type { - AuthConfigJSON, - AuthConfigResource, - EmailAddressVerificationStrategy, - IdentificationStrategy, - SignInStrategyName, - ToggleType, - ToggleTypeWithRequire, -} from '@clerk/types'; +import type { AuthConfigJSON, AuthConfigResource } from '@clerk/types'; import { BaseResource } from './internal'; export class AuthConfig extends BaseResource implements AuthConfigResource { - id!: string; - firstName!: ToggleTypeWithRequire; - lastName!: ToggleTypeWithRequire; - emailAddress!: ToggleType; - phoneNumber!: ToggleType; - username!: ToggleType; - password!: string; - identificationStrategies!: IdentificationStrategy[]; - identificationRequirements!: IdentificationStrategy[][]; - passwordConditions!: any; - firstFactors!: SignInStrategyName[]; - secondFactors!: SignInStrategyName[]; - emailAddressVerificationStrategies!: EmailAddressVerificationStrategy[]; singleSessionMode!: boolean; public constructor(data: AuthConfigJSON) { @@ -31,23 +10,8 @@ export class AuthConfig extends BaseResource implements AuthConfigResource { this.fromJSON(data); } - protected fromJSON(data: AuthConfigJSON): this { - this.id = data.id; - this.firstName = data.first_name; - this.lastName = data.last_name; - this.emailAddress = data.email_address; - this.phoneNumber = data.phone_number; - this.username = data.username; - this.password = data.password; - this.identificationStrategies = data.identification_strategies; - this.identificationRequirements = data.identification_requirements; - this.passwordConditions = data.password_conditions; - this.firstFactors = data.first_factors; - this.secondFactors = data.second_factors; - this.emailAddressVerificationStrategies = - data.email_address_verification_strategies; - this.singleSessionMode = data.single_session_mode; - + protected fromJSON(data: AuthConfigJSON | null): this { + this.singleSessionMode = data ? data.single_session_mode : true; return this; } } diff --git a/packages/clerk-js/src/core/resources/Base.ts b/packages/clerk-js/src/core/resources/Base.ts index 6490956c1bd..8818f09cd48 100644 --- a/packages/clerk-js/src/core/resources/Base.ts +++ b/packages/clerk-js/src/core/resources/Base.ts @@ -6,8 +6,8 @@ import type { HTTPMethod, } from 'core/fapiClient'; -import type Clerk from '../clerk'; import { clerkMissingFapiClientInResources } from '../errors'; +import type { Clerk } from './internal'; import { ClerkAPIResponseError, Client } from './internal'; export type BaseFetchOptions = { forceUpdateClient?: boolean }; diff --git a/packages/clerk-js/src/core/resources/Environment.ts b/packages/clerk-js/src/core/resources/Environment.ts index 77e680ae2d9..7d91a877ab8 100644 --- a/packages/clerk-js/src/core/resources/Environment.ts +++ b/packages/clerk-js/src/core/resources/Environment.ts @@ -3,9 +3,15 @@ import type { DisplayConfigResource, EnvironmentJSON, EnvironmentResource, + UserSettingsResource, } from '@clerk/types'; -import { AuthConfig, BaseResource, DisplayConfig } from './internal'; +import { + AuthConfig, + BaseResource, + DisplayConfig, + UserSettings, +} from './internal'; export class Environment extends BaseResource implements EnvironmentResource { private static instance: Environment; @@ -13,6 +19,7 @@ export class Environment extends BaseResource implements EnvironmentResource { pathRoot = '/environment'; authConfig!: AuthConfigResource; displayConfig!: DisplayConfigResource; + userSettings!: UserSettingsResource; public static getInstance(): Environment { if (!Environment.instance) { @@ -50,6 +57,7 @@ export class Environment extends BaseResource implements EnvironmentResource { if (data) { this.authConfig = new AuthConfig(data.auth_config); this.displayConfig = new DisplayConfig(data.display_config); + this.userSettings = new UserSettings(data.user_settings); } return this; } diff --git a/packages/clerk-js/src/core/resources/ExternalAccount.ts b/packages/clerk-js/src/core/resources/ExternalAccount.ts index 29a6c61f838..99e5524afae 100644 --- a/packages/clerk-js/src/core/resources/ExternalAccount.ts +++ b/packages/clerk-js/src/core/resources/ExternalAccount.ts @@ -1,16 +1,9 @@ import { titleize } from '@clerk/shared/utils/string'; -import type { - ExternalAccountJSON, - ExternalAccountResource, - OAuthProvider, -} from '@clerk/types'; +import type { ExternalAccountJSON, ExternalAccountResource, OAuthProvider } from '@clerk/types'; import { BaseResource } from './Base'; -export class ExternalAccount - extends BaseResource - implements ExternalAccountResource -{ +export class ExternalAccount extends BaseResource implements ExternalAccountResource { id!: string; identificationId!: string; provider!: OAuthProvider; @@ -20,6 +13,9 @@ export class ExternalAccount firstName = ''; lastName = ''; avatarUrl = ''; + username = ''; + publicMetadata = {}; + label = ''; public constructor(data: Partial, pathRoot: string); public constructor(data: ExternalAccountJSON, pathRoot: string) { @@ -38,10 +34,10 @@ export class ExternalAccount this.firstName = data.first_name; this.lastName = data.last_name; // TODO: Send the provider name the `oauth` prefix from FAPI - this.provider = (data.provider || '').replace( - 'oauth_', - '', - ) as OAuthProvider; + this.provider = (data.provider || '').replace('oauth_', '') as OAuthProvider; + this.username = data.username; + this.publicMetadata = data.public_metadata; + this.label = data.label; return this; } diff --git a/packages/clerk-js/src/core/resources/Organization.test.ts b/packages/clerk-js/src/core/resources/Organization.test.ts new file mode 100644 index 00000000000..565ba96cf1a --- /dev/null +++ b/packages/clerk-js/src/core/resources/Organization.test.ts @@ -0,0 +1,18 @@ +import { Organization } from 'core/resources/internal'; + +describe('Organization', () => { + it('has the same initial properties', () => { + const organization = new Organization({ + object: 'organization', + id: 'test_id', + name: 'test_name', + role: 'basic_member', + created_at: 12345, + updated_at: 5678, + created_by: 'test_user_id', + instance_id: 'test_instance_id', + }); + + expect(organization).toMatchSnapshot(); + }); +}); diff --git a/packages/clerk-js/src/core/resources/Organization.ts b/packages/clerk-js/src/core/resources/Organization.ts new file mode 100644 index 00000000000..97029cf3b76 --- /dev/null +++ b/packages/clerk-js/src/core/resources/Organization.ts @@ -0,0 +1,144 @@ +import type { + GetMembershipsParams, + MembershipRole, + OrganizationInvitationJSON, + OrganizationJSON, + OrganizationMembershipJSON, + OrganizationResource, +} from '@clerk/types'; +import { unixEpochToDate } from 'utils/date'; + +import { + BaseResource, + OrganizationInvitation, + OrganizationMembership, +} from './internal'; + +export class Organization extends BaseResource implements OrganizationResource { + id!: string; + name!: string; + role!: MembershipRole; + instanceId!: string; + createdBy!: string; + createdAt!: Date; + updatedAt!: Date; + + constructor(data: OrganizationJSON) { + super(); + this.fromJSON(data); + } + + static async create(name: string): Promise { + const json = ( + await BaseResource._fetch({ + path: '/organizations', + method: 'POST', + body: { name } as any, + }) + )?.response as unknown as OrganizationJSON; + + return new Organization(json); + } + + static async retrieve( + getOrganizationParams?: GetOrganizationParams, + ): Promise { + return await BaseResource._fetch({ + path: '/me/organizations', + method: 'GET', + search: getOrganizationParams as any, + }) + .then(res => { + const organizationsJSON = + res?.response as unknown as OrganizationJSON[]; + return organizationsJSON.map(org => new Organization(org)); + }) + .catch(() => []); + } + + getMemberships = async ( + getMemberhipsParams?: GetMembershipsParams, + ): Promise => { + return await BaseResource._fetch({ + path: `/organizations/${this.id}/memberships`, + method: 'GET', + search: getMemberhipsParams as any, + }) + .then(res => { + const members = + res?.response as unknown as OrganizationMembershipJSON[]; + return members.map(member => new OrganizationMembership(member)); + }) + .catch(() => []); + }; + + getPendingInvitations = async (): Promise => { + return await BaseResource._fetch({ + path: `/organizations/${this.id}/invitations/pending`, + method: 'GET', + }) + .then(res => { + const pendingInvitations = + res?.response as unknown as OrganizationInvitationJSON[]; + return pendingInvitations.map( + pendingInvitation => new OrganizationInvitation(pendingInvitation), + ); + }) + .catch(() => []); + }; + + inviteMember = async (inviteMemberParams: InviteMemberParams) => { + return await OrganizationInvitation.create(this.id, inviteMemberParams); + }; + + updateMember = async ({ + userId, + role, + }: UpdateMembershipParams): Promise => { + return await BaseResource._fetch({ + method: 'PATCH', + path: `/organizations/${this.id}/memberships/${userId}`, + body: { role } as any, + }).then( + res => + new OrganizationMembership(res?.response as OrganizationMembershipJSON), + ); + }; + + removeMember = async (userId: string): Promise => { + return await BaseResource._fetch({ + method: 'DELETE', + path: `/organizations/${this.id}/memberships/${userId}`, + }).then( + res => + new OrganizationMembership(res?.response as OrganizationMembershipJSON), + ); + }; + + protected fromJSON(data: OrganizationJSON): this { + this.id = data.id; + this.name = data.name; + this.role = data.role; + this.instanceId = data.instance_id; + this.createdBy = data.created_by; + this.createdAt = unixEpochToDate(data.created_at); + this.updatedAt = unixEpochToDate(data.updated_at); + return this; + } +} + +export type GetOrganizationParams = { + limit?: number; + offset?: number; +}; + +export type InviteMemberParams = { + emailAddress: string; + role: MembershipRole; + redirectUrl?: string; +}; + +export type UpdateMembershipParams = { + userId: string; + role: MembershipRole; +}; diff --git a/packages/clerk-js/src/core/resources/OrganizationInvitation.test.ts b/packages/clerk-js/src/core/resources/OrganizationInvitation.test.ts new file mode 100644 index 00000000000..1ae8a90f837 --- /dev/null +++ b/packages/clerk-js/src/core/resources/OrganizationInvitation.test.ts @@ -0,0 +1,18 @@ +import { OrganizationInvitation } from 'core/resources/internal'; + +describe('OrganizationInvitation', () => { + it('has the same initial properties', () => { + const organizationInvitation = new OrganizationInvitation({ + object: 'organization_invitation', + email_address: 'test_email', + id: 'test_id', + organization_id: 'test_organization_id', + role: 'basic_member', + created_at: 12345, + updated_at: 5678, + status: 'pending', + }); + + expect(organizationInvitation).toMatchSnapshot(); + }); +}); diff --git a/packages/clerk-js/src/core/resources/OrganizationInvitation.ts b/packages/clerk-js/src/core/resources/OrganizationInvitation.ts new file mode 100644 index 00000000000..7e7223a7fbf --- /dev/null +++ b/packages/clerk-js/src/core/resources/OrganizationInvitation.ts @@ -0,0 +1,69 @@ +import { + MembershipRole, + OrganizationInvitationJSON, + OrganizationInvitationResource, + OrganizationInvitationStatus, +} from '@clerk/types'; +import { unixEpochToDate } from 'utils/date'; + +import { BaseResource } from './internal'; + +export class OrganizationInvitation + extends BaseResource + implements OrganizationInvitationResource +{ + id!: string; + emailAddress!: string; + organizationId!: string; + status!: OrganizationInvitationStatus; + role!: MembershipRole; + createdAt!: Date; + updatedAt!: Date; + + static async create( + organizationId: string, + { emailAddress, role, redirectUrl }: CreateOrganizationInvitationParams, + ): Promise { + const json = ( + await BaseResource._fetch({ + path: `/organizations/${organizationId}/invitations`, + method: 'POST', + body: { + email_address: emailAddress, + role, + redirect_url: redirectUrl, + } as any, + }) + )?.response as unknown as OrganizationInvitationJSON; + + return new OrganizationInvitation(json); + } + + constructor(data: OrganizationInvitationJSON) { + super(); + this.fromJSON(data); + } + + revoke = async (): Promise => { + return await this._basePost({ + path: `/organizations/${this.organizationId}/invitations/${this.id}/revoke`, + }); + }; + + protected fromJSON(data: OrganizationInvitationJSON): this { + this.id = data.id; + this.emailAddress = data.email_address; + this.organizationId = data.organization_id; + this.role = data.role; + this.status = data.status; + this.createdAt = unixEpochToDate(data.created_at); + this.updatedAt = unixEpochToDate(data.updated_at); + return this; + } +} + +export type CreateOrganizationInvitationParams = { + emailAddress: string; + role: MembershipRole; + redirectUrl?: string; +}; diff --git a/packages/clerk-js/src/core/resources/OrganizationMembership.test.ts b/packages/clerk-js/src/core/resources/OrganizationMembership.test.ts new file mode 100644 index 00000000000..d7ca7530fb2 --- /dev/null +++ b/packages/clerk-js/src/core/resources/OrganizationMembership.test.ts @@ -0,0 +1,24 @@ +import { OrganizationMembership } from 'core/resources/internal'; + +describe('OrganizationMembership', () => { + it('has the same initial properties', () => { + const organizationMemberShip = new OrganizationMembership({ + object: 'organization_membership', + id: 'test_id', + organization_id: 'test_org_id', + created_at: 12345, + updated_at: 5678, + role: 'admin', + public_user_data: { + object: 'public_user_data', + first_name: 'test_first_name', + last_name: 'test_last_name', + profile_image_url: 'test_url', + identifier: 'test@identifier.gr', + id: 'test_user_id', + }, + }); + + expect(organizationMemberShip).toMatchSnapshot(); + }); +}); diff --git a/packages/clerk-js/src/core/resources/OrganizationMembership.ts b/packages/clerk-js/src/core/resources/OrganizationMembership.ts new file mode 100644 index 00000000000..325cc67371c --- /dev/null +++ b/packages/clerk-js/src/core/resources/OrganizationMembership.ts @@ -0,0 +1,62 @@ +import { + MembershipRole, + OrganizationMembershipJSON, + OrganizationMembershipResource, + PublicUserData, +} from '@clerk/types'; +import { unixEpochToDate } from 'utils/date'; + +import { BaseResource } from './internal'; + +export class OrganizationMembership + extends BaseResource + implements OrganizationMembershipResource +{ + id!: string; + organizationId!: string; + publicUserData!: PublicUserData; + role!: MembershipRole; + createdAt!: Date; + updatedAt!: Date; + + constructor(data: OrganizationMembershipJSON) { + super(); + this.fromJSON(data); + } + + destroy = async (): Promise => { + // FIXME: Revise the return type of _baseDelete + return (await this._baseDelete({ + path: `/organizations/${this.organizationId}/memberships/${this.publicUserData.userId}`, + })) as unknown as OrganizationMembership; + }; + + update = async ({ + role, + }: UpdateOrganizationMembershipParams): Promise => { + return await this._basePatch({ + path: `/organizations/${this.organizationId}/memberships/${this.publicUserData.userId}`, + body: { role }, + }); + }; + + protected fromJSON(data: OrganizationMembershipJSON): this { + this.id = data.id; + this.organizationId = data.organization_id; + this.publicUserData = { + firstName: data.public_user_data.first_name, + lastName: data.public_user_data.last_name, + profileImageUrl: data.public_user_data.profile_image_url, + identifier: data.public_user_data.identifier, + userId: data.public_user_data.user_id, + }; + this.role = data.role; + this.createdAt = unixEpochToDate(data.created_at); + this.updatedAt = unixEpochToDate(data.updated_at); + return this; + } +} + +export type UpdateOrganizationMembershipParams = { + role: MembershipRole; +}; diff --git a/packages/clerk-js/src/core/resources/Token.ts b/packages/clerk-js/src/core/resources/Token.ts index edde8f44cd1..900c7f26b47 100644 --- a/packages/clerk-js/src/core/resources/Token.ts +++ b/packages/clerk-js/src/core/resources/Token.ts @@ -1,7 +1,7 @@ import type { JWT, TokenJSON, TokenResource } from '@clerk/types'; import { decode } from 'utils'; -import { BaseResource } from './Base'; +import { BaseResource } from './internal'; export class Token extends BaseResource implements TokenResource { pathRoot = 'tokens'; diff --git a/packages/clerk-js/src/core/resources/User.ts b/packages/clerk-js/src/core/resources/User.ts index de3dfce2667..76d5c773215 100644 --- a/packages/clerk-js/src/core/resources/User.ts +++ b/packages/clerk-js/src/core/resources/User.ts @@ -16,7 +16,9 @@ import { BaseResource, EmailAddress, ExternalAccount, + GetOrganizationParams, Image, + Organization, PhoneNumber, SessionWithActivities, Web3Wallet, @@ -128,6 +130,12 @@ export class User extends BaseResource implements UserResource { }); }; + getOrganizations = async ( + getOrganizationParams: GetOrganizationParams, + ): Promise => { + return await Organization.retrieve(getOrganizationParams); + }; + protected fromJSON(data: UserJSON): this { this.id = data.id; this.firstName = data.first_name; diff --git a/packages/clerk-js/src/core/resources/UserSettings.test.ts b/packages/clerk-js/src/core/resources/UserSettings.test.ts new file mode 100644 index 00000000000..9637420055c --- /dev/null +++ b/packages/clerk-js/src/core/resources/UserSettings.test.ts @@ -0,0 +1,135 @@ +import { UserSettingsJSON } from '@clerk/types'; +import { UserSettings } from 'core/resources/internal'; + +describe('UserSettings', () => { + it('returns enabled web3 first factors', function () { + const sut = new UserSettings({ + attributes: { + username: { + enabled: false, + required: false, + used_for_first_factor: false, + first_factors: [], + used_for_second_factor: false, + second_factors: [], + verifications: [], + verify_at_sign_up: false, + }, + web3_wallet: { + enabled: true, + required: true, + used_for_first_factor: true, + first_factors: ['web3_metamask_signature'], + used_for_second_factor: false, + second_factors: [], + verifications: ['web3_metamask_signature'], + verify_at_sign_up: true, + }, + }, + } as any as UserSettingsJSON); + + const res = sut.web3FirstFactors; + expect(res).toEqual(['web3_metamask_signature']); + }); + + it('returns if the instance is passwordless or password-based', function () { + let sut = new UserSettings({ + attributes: { + password: { + enabled: true, + required: true, + }, + }, + } as any as UserSettingsJSON); + + expect(sut.instanceIsPasswordBased).toEqual(true); + + sut = new UserSettings({ + attributes: { + password: { + enabled: true, + required: false, + }, + }, + } as any as UserSettingsJSON); + expect(sut.instanceIsPasswordBased).toEqual(false); + }); + + it('returns enabled social provider strategies', function () { + const sut = new UserSettings({ + social: { + oauth_google: { + enabled: true, + required: false, + authenticatable: true, + strategy: 'oauth_google', + }, + oauth_gitlab: { + enabled: false, + required: false, + authenticatable: false, + strategy: 'oauth_gitlab', + }, + oauth_facebook: { + enabled: true, + required: false, + authenticatable: true, + strategy: 'oauth_facebook', + }, + }, + attributes: { + username: { + enabled: true, + required: false, + }, + web3_wallet: { + enabled: false, + required: false, + }, + }, + } as any as UserSettingsJSON); + + const res = sut.socialProviderStrategies; + expect(res).toEqual(['oauth_facebook', 'oauth_google']); + }); + + it('returns enabled standard form attributes', function () { + const sut = new UserSettings({ + attributes: { + email_address: { + enabled: true, + required: false, + used_for_first_factor: true, + first_factors: ['email_link'], + used_for_second_factor: false, + second_factors: [], + verifications: ['email_link'], + verify_at_sign_up: true, + }, + phone_number: { + enabled: true, + required: false, + used_for_first_factor: true, + first_factors: ['phone_code'], + used_for_second_factor: true, + second_factors: ['phone_code'], + verifications: ['phone_code'], + verify_at_sign_up: true, + }, + username: { + enabled: false, + required: false, + used_for_first_factor: false, + first_factors: [], + used_for_second_factor: false, + second_factors: [], + verifications: [], + verify_at_sign_up: false, + }, + }, + } as any as UserSettingsJSON); + + const res = sut.enabledFirstFactorIdentifiers; + expect(res).toEqual(['email_address', 'phone_number']); + }); +}); diff --git a/packages/clerk-js/src/core/resources/UserSettings.ts b/packages/clerk-js/src/core/resources/UserSettings.ts new file mode 100644 index 00000000000..6b2a68a1100 --- /dev/null +++ b/packages/clerk-js/src/core/resources/UserSettings.ts @@ -0,0 +1,79 @@ +import type { + Attributes, + OauthProviders, + OAuthStrategy, + SignInData, + SignUpData, + UserSettingsJSON, + UserSettingsResource, + Web3Strategy, +} from '@clerk/types'; + +import { BaseResource } from './internal'; + +/** + * @internal + */ +export class UserSettings extends BaseResource implements UserSettingsResource { + id = undefined; + social!: OauthProviders; + attributes!: Attributes; + signIn!: SignInData; + signUp!: SignUpData; + + socialProviderStrategies: OAuthStrategy[] = []; + web3FirstFactors: Web3Strategy[] = []; + enabledFirstFactorIdentifiers: Array = []; + + public constructor(data: UserSettingsJSON) { + super(); + this.fromJSON(data); + } + + get instanceIsPasswordBased() { + return this.attributes.password.enabled && this.attributes.password.required; + } + + protected fromJSON(data: UserSettingsJSON): this { + this.social = data.social; + this.attributes = data.attributes; + this.signIn = data.sign_in; + this.signUp = data.sign_up; + this.socialProviderStrategies = this.getSocialProviderStrategies(data.social); + this.web3FirstFactors = this.getWeb3FirstFactors(data.attributes); + this.enabledFirstFactorIdentifiers = this.getEnabledFirstFactorIdentifiers(data.attributes); + return this; + } + + private getEnabledFirstFactorIdentifiers(attributes: Attributes): Array { + if (!attributes) { + return []; + } + + return Object.entries(attributes) + .filter(([name, attr]) => attr.used_for_first_factor && !name.startsWith('web3')) + .map(([name]) => name) as Array; + } + + private getWeb3FirstFactors(attributes: Attributes): Web3Strategy[] { + if (!attributes) { + return []; + } + + return Object.entries(attributes) + .filter(([name, attr]) => attr.used_for_first_factor && name.startsWith('web3')) + .map(([, desc]) => desc.first_factors) + .flat() as any as Web3Strategy[]; + } + + private getSocialProviderStrategies(social: OauthProviders): OAuthStrategy[] { + if (!social) { + return []; + } + + return Object.entries(social) + .filter(([, desc]) => desc.enabled) + .map(([, desc]) => desc.strategy) + .sort(); + } +} diff --git a/packages/clerk-js/src/core/resources/__snapshots__/Organization.test.ts.snap b/packages/clerk-js/src/core/resources/__snapshots__/Organization.test.ts.snap new file mode 100644 index 00000000000..5640abad70e --- /dev/null +++ b/packages/clerk-js/src/core/resources/__snapshots__/Organization.test.ts.snap @@ -0,0 +1,19 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Organization has the same initial properties 1`] = ` +Organization { + "createdAt": 1970-01-01T00:00:12.345Z, + "createdBy": "test_user_id", + "getMemberships": [Function], + "getPendingInvitations": [Function], + "id": "test_id", + "instanceId": "test_instance_id", + "inviteMember": [Function], + "name": "test_name", + "pathRoot": "", + "removeMember": [Function], + "role": "basic_member", + "updateMember": [Function], + "updatedAt": 1970-01-01T00:00:05.678Z, +} +`; diff --git a/packages/clerk-js/src/core/resources/__snapshots__/OrganizationInvitation.test.ts.snap b/packages/clerk-js/src/core/resources/__snapshots__/OrganizationInvitation.test.ts.snap new file mode 100644 index 00000000000..bb4da65a28d --- /dev/null +++ b/packages/clerk-js/src/core/resources/__snapshots__/OrganizationInvitation.test.ts.snap @@ -0,0 +1,15 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`OrganizationInvitation has the same initial properties 1`] = ` +OrganizationInvitation { + "createdAt": 1970-01-01T00:00:12.345Z, + "emailAddress": "test_email", + "id": "test_id", + "organizationId": "test_organization_id", + "pathRoot": "", + "revoke": [Function], + "role": "basic_member", + "status": "pending", + "updatedAt": 1970-01-01T00:00:05.678Z, +} +`; diff --git a/packages/clerk-js/src/core/resources/__snapshots__/OrganizationMembership.test.ts.snap b/packages/clerk-js/src/core/resources/__snapshots__/OrganizationMembership.test.ts.snap new file mode 100644 index 00000000000..d91444d13bc --- /dev/null +++ b/packages/clerk-js/src/core/resources/__snapshots__/OrganizationMembership.test.ts.snap @@ -0,0 +1,21 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`OrganizationMembership has the same initial properties 1`] = ` +OrganizationMembership { + "createdAt": 1970-01-01T00:00:12.345Z, + "destroy": [Function], + "id": "test_id", + "organizationId": "test_org_id", + "pathRoot": "", + "publicUserData": Object { + "firstName": "test_first_name", + "identifier": "test@identifier.gr", + "lastName": "test_last_name", + "profileImageUrl": "test_url", + "userId": undefined, + }, + "role": "admin", + "update": [Function], + "updatedAt": 1970-01-01T00:00:05.678Z, +} +`; diff --git a/packages/clerk-js/src/core/resources/internal.ts b/packages/clerk-js/src/core/resources/internal.ts index 91ce5a1d740..123f691a7d7 100644 --- a/packages/clerk-js/src/core/resources/internal.ts +++ b/packages/clerk-js/src/core/resources/internal.ts @@ -1,5 +1,6 @@ export type { default as Clerk } from '../clerk'; export * from './Base'; +export * from './UserSettings'; export * from './AuthConfig'; export * from './Client'; export * from './DisplayConfig'; @@ -10,6 +11,9 @@ export * from './ExternalAccount'; export * from './IdentificationLink'; export * from './Image'; export * from './PhoneNumber'; +export * from './Organization'; +export * from './OrganizationInvitation'; +export * from './OrganizationMembership'; export * from './Session'; export * from './SessionWithActivities'; export * from './SignIn'; diff --git a/packages/clerk-js/src/ui/common/constants.ts b/packages/clerk-js/src/ui/common/constants.ts index fb81a161cab..58381241c24 100644 --- a/packages/clerk-js/src/ui/common/constants.ts +++ b/packages/clerk-js/src/ui/common/constants.ts @@ -1,116 +1,49 @@ -import type { OAuthProvider, Web3Provider } from '@clerk/types'; +import type { Web3Provider } from '@clerk/types'; -export const FirstFactorConfigs = Object.freeze({ +const FirstFactorConfigs = Object.freeze({ email_address: { label: 'Email address', - icon: 'clerk-email', fieldType: 'email', }, phone_number: { label: 'Phone number', - icon: 'clerk-phone', fieldType: 'tel', }, username: { label: 'Username', - icon: 'clerk-person', fieldType: 'text', }, email_address_phone_number: { label: 'Email or phone', - icon: 'clerk-person', fieldType: 'text', }, email_address_username: { label: 'Email or username', - icon: 'clerk-person', fieldType: 'text', }, phone_number_username: { label: 'Phone number or username', - icon: 'clerk-person', fieldType: 'text', }, email_address_phone_number_username: { label: 'Email, phone, or username', - icon: 'clerk-person', fieldType: 'text', }, -} as Record); + default: { + label: '', + fieldType: 'text', + }, +} as Record); + +export const getIdentifierControlDisplayValues = (attributes: string[]) => { + const indexKey = attributes.length == 0 ? null : [...attributes].sort().join('_'); + return FirstFactorConfigs[indexKey || 'default']; +}; export const PREFERRED_SIGN_IN_STRATEGIES = Object.freeze({ Password: 'password', OTP: 'otp', }); -interface OAuthProviderData { - id: string; - name: string; -} - -type OAuthProviders = { - [key in OAuthProvider]: OAuthProviderData; -}; - -export const OAUTH_PROVIDERS: OAuthProviders = Object.freeze({ - facebook: { - id: 'facebook', - name: 'Facebook', - }, - google: { - id: 'google', - name: 'Google', - }, - hubspot: { - id: 'hubspot', - name: 'HubSpot', - }, - github: { - id: 'github', - name: 'GitHub', - }, - tiktok: { - id: 'tiktok', - name: 'TikTok', - }, - gitlab: { - id: 'gitlab', - name: 'GitLab', - }, - discord: { - id: 'discord', - name: 'Discord', - }, - twitter: { - id: 'twitter', - name: 'Twitter', - }, - twitch: { - id: 'twitch', - name: 'Twitch', - }, - linkedin: { - id: 'linkedin', - name: 'LinkedIn', - }, - dropbox: { - id: 'dropbox', - name: 'Dropbox', - }, - bitbucket: { - id: 'bitbucket', - name: 'Bitbucket', - }, - microsoft: { - id: 'microsoft', - name: 'Microsoft', - }, -}); - -export function getOAuthProviderData( - name: OAuthProvider, -): OAuthProviderData | undefined | null { - return OAUTH_PROVIDERS[name]; -} interface Web3ProviderData { id: string; @@ -128,9 +61,7 @@ export const WEB3_PROVIDERS: Web3Providers = Object.freeze({ }, }); -export function getWeb3ProviderData( - name: Web3Provider, -): Web3ProviderData | undefined | null { +export function getWeb3ProviderData(name: Web3Provider): Web3ProviderData | undefined | null { return WEB3_PROVIDERS[name]; } diff --git a/packages/clerk-js/src/ui/common/logo/Logo.tsx b/packages/clerk-js/src/ui/common/logo/Logo.tsx index 062bc7ed59e..c6228772cd6 100644 --- a/packages/clerk-js/src/ui/common/logo/Logo.tsx +++ b/packages/clerk-js/src/ui/common/logo/Logo.tsx @@ -36,6 +36,12 @@ export function Logo(): JSX.Element { if (hasLogoImage || !logoContainer || !name) { return; } + + if (typeof window === 'undefined' || !window.ResizeObserver) { + fitTextInOneLine(name, logoContainer, '48px'); + return; + } + const ro = new ResizeObserver(() => fitTextInOneLine(name, logoContainer, '48px'), ); diff --git a/packages/clerk-js/src/ui/common/withRedirectToHome.tsx b/packages/clerk-js/src/ui/common/withRedirectToHome.tsx index 26cdca8665e..e6fc8a92fbd 100644 --- a/packages/clerk-js/src/ui/common/withRedirectToHome.tsx +++ b/packages/clerk-js/src/ui/common/withRedirectToHome.tsx @@ -7,22 +7,22 @@ export function withRedirectToHome

( Component: React.ComponentType

, displayName?: string, ): (props: P) => null | JSX.Element { - displayName = - displayName || Component.displayName || Component.name || 'Component'; + displayName = displayName || Component.displayName || Component.name || 'Component'; Component.displayName = displayName; const HOC = (props: P) => { const { navigate } = useNavigate(); const { authConfig, displayConfig } = useEnvironment(); + const { singleSessionMode } = authConfig; const session = useCoreSession({ avoidUndefinedCheck: true }); React.useEffect(() => { - if (authConfig.singleSessionMode && !!session) { + if (singleSessionMode && !!session) { navigate(displayConfig.homeUrl); } }, []); - if (authConfig.singleSessionMode && !!session) { + if (singleSessionMode && !!session) { return null; } diff --git a/packages/clerk-js/src/ui/contexts/EnvironmentContext.tsx b/packages/clerk-js/src/ui/contexts/EnvironmentContext.tsx index 5b75d20f016..0bf1054c81a 100644 --- a/packages/clerk-js/src/ui/contexts/EnvironmentContext.tsx +++ b/packages/clerk-js/src/ui/contexts/EnvironmentContext.tsx @@ -8,7 +8,7 @@ const EnvironmentContext = React.createContext( interface EnvironmentProviderProps { children: React.ReactNode; - value: any; + value: EnvironmentResource; } function EnvironmentProvider({ diff --git a/packages/clerk-js/src/ui/signIn/SignIn.test.tsx b/packages/clerk-js/src/ui/signIn/SignIn.test.tsx index e32f8925889..a1cf8810f7e 100644 --- a/packages/clerk-js/src/ui/signIn/SignIn.test.tsx +++ b/packages/clerk-js/src/ui/signIn/SignIn.test.tsx @@ -1,6 +1,6 @@ import { render } from '@clerk/shared/testUtils'; import { EnvironmentResource } from '@clerk/types'; -import { AuthConfig, Session } from 'core/resources'; +import { AuthConfig, Session } from 'core/resources/internal'; import React from 'react'; import { SignIn } from 'ui/signIn/SignIn'; @@ -30,12 +30,6 @@ jest.mock('ui/contexts', () => { homeUrl: 'https://www.cnn.com', }, authConfig: { - identificationStrategies: [ - 'email_address', - 'oauth_google', - 'oauth_facebook', - ], - firstFactors: ['email_address', 'oauth_google', 'oauth_facebook'], singleSessionMode: true, } as Partial, } as Partial), diff --git a/packages/clerk-js/src/ui/signIn/SignInAccountSwitcher.test.tsx b/packages/clerk-js/src/ui/signIn/SignInAccountSwitcher.test.tsx index 7e702568e20..3f5cdd26ab7 100644 --- a/packages/clerk-js/src/ui/signIn/SignInAccountSwitcher.test.tsx +++ b/packages/clerk-js/src/ui/signIn/SignInAccountSwitcher.test.tsx @@ -28,12 +28,7 @@ jest.mock('ui/contexts', () => { }, }, authConfig: { - identification_strategies: [ - 'email_address', - 'oauth_google', - 'oauth_facebook', - ], - first_factors: ['email_address', 'oauth_google', 'oauth_facebook'], + singleSessionMode: false, }, })), useSignInContext: () => { diff --git a/packages/clerk-js/src/ui/signIn/SignInFactorOne.test.tsx b/packages/clerk-js/src/ui/signIn/SignInFactorOne.test.tsx index 4a8fc70bef3..b6ea2016302 100644 --- a/packages/clerk-js/src/ui/signIn/SignInFactorOne.test.tsx +++ b/packages/clerk-js/src/ui/signIn/SignInFactorOne.test.tsx @@ -685,7 +685,7 @@ describe('', () => { expect(container.querySelector('.cl-auth-form-spinner')).toBeDefined(); }); - it('renders the fallback screen', async () => { + it('renders the fallback screen', () => { ( useEnvironment as jest.Mock> ).mockImplementation(() => ({ diff --git a/packages/clerk-js/src/ui/signIn/SignInStart.test.tsx b/packages/clerk-js/src/ui/signIn/SignInStart.test.tsx index 3cd2983d9fd..7d77606fdd3 100644 --- a/packages/clerk-js/src/ui/signIn/SignInStart.test.tsx +++ b/packages/clerk-js/src/ui/signIn/SignInStart.test.tsx @@ -1,14 +1,7 @@ -import { - mocked, - render, - renderJSON, - screen, - userEvent, - waitFor, -} from '@clerk/shared/testUtils'; +import { mocked, render, renderJSON, screen, userEvent, waitFor } from '@clerk/shared/testUtils'; import { titleize } from '@clerk/shared/utils/string'; -import { EnvironmentResource, SignInResource } from '@clerk/types'; -import { ClerkAPIResponseError } from 'core/resources/Error'; +import { EnvironmentResource, SignInResource, UserSettingsJSON, UserSettingsResource } from '@clerk/types'; +import { ClerkAPIResponseError, UserSettings } from 'core/resources/internal'; import React from 'react'; import { useCoreSignIn } from 'ui/contexts'; @@ -18,6 +11,7 @@ const mockNavigate = jest.fn(); const mockCreateRequest = jest.fn(); const mockAuthenticateWithRedirect = jest.fn(); const mockNavigateAfterSignIn = jest.fn(); +let mockUserSettings: UserSettingsResource; jest.mock('ui/router/RouteContext'); @@ -42,15 +36,10 @@ jest.mock('ui/contexts', () => { preferredSignInStrategy: 'otp', afterSignInUrl: 'http://test.host', }, + userSettings: mockUserSettings, authConfig: { password: 'required', singleSessionMode: false, - identificationStrategies: [ - 'email_address', - 'oauth_google', - 'oauth_facebook', - ], - firstFactors: ['email_address', 'oauth_google', 'oauth_facebook'], }, } as any as EnvironmentResource), ), @@ -80,11 +69,46 @@ jest.mock('ui/hooks', () => ({ }, })); -describe('', () => { +fdescribe('', () => { beforeEach(() => { jest.clearAllMocks(); }); + beforeEach(() => { + mockUserSettings = new UserSettings({ + attributes: { + email_address: { + enabled: true, + required: false, + used_for_first_factor: true, + first_factors: ['email_link'], + used_for_second_factor: false, + second_factors: [], + verifications: ['email_link'], + verify_at_sign_up: false, + }, + password: { + enabled: true, + required: true, + }, + }, + social: { + oauth_google: { + enabled: true, + required: false, + authenticatable: false, + strategy: 'oauth_google', + }, + oauth_facebook: { + enabled: true, + required: false, + authenticatable: false, + strategy: 'oauth_facebook', + }, + }, + } as unknown as UserSettingsJSON); + }); + describe('when user is not signed in', () => { beforeAll(() => { mockCreateRequest.mockReturnValue({ @@ -93,7 +117,7 @@ describe('', () => { }); }); - it('renders the sign in start screen', async () => { + it('renders the sign in start screen', () => { const tree = renderJSON(); expect(tree).toMatchSnapshot(); }); @@ -102,7 +126,7 @@ describe('', () => { render(); const inputField = screen.getByLabelText('Email address'); - await userEvent.type(inputField, 'boss@clerk.dev'); + userEvent.type(inputField, 'boss@clerk.dev'); const signEmailButton = screen.getByRole('button', { name: /Continue/i }); userEvent.click(signEmailButton); @@ -123,17 +147,15 @@ describe('', () => { status: 'complete', }); - const instantPasswordField = container.querySelector( - 'input#password', - ) as HTMLInputElement; + const instantPasswordField = container.querySelector('input#password') as HTMLInputElement; expect(instantPasswordField).toBeDefined(); const inputField = screen.getByLabelText('Email address'); - await userEvent.type(inputField, 'boss@clerk.dev'); + userEvent.type(inputField, 'boss@clerk.dev'); // simulate password being filled by a pwd manager - await userEvent.type(instantPasswordField, '123456'); + userEvent.type(instantPasswordField, '123456'); const signEmailButton = screen.getByRole('button', { name: /Continue/i }); userEvent.click(signEmailButton); @@ -168,9 +190,7 @@ describe('', () => { status: 'needs_first_factor', })); - const instantPasswordField = container.querySelector( - 'input#password', - ) as HTMLInputElement; + const instantPasswordField = container.querySelector('input#password') as HTMLInputElement; expect(instantPasswordField).toBeDefined(); @@ -208,8 +228,7 @@ describe('', () => { data: [ { code: 'form_password_incorrect', - message: - 'Password is incorrect. Try again, or use another method.', + message: 'Password is incorrect. Try again, or use another method.', meta: { param_name: 'password', }, @@ -222,9 +241,7 @@ describe('', () => { status: 'needs_first_factor', })); - const instantPasswordField = container.querySelector( - 'input#password', - ) as HTMLInputElement; + const instantPasswordField = container.querySelector('input#password') as HTMLInputElement; expect(instantPasswordField).toBeDefined(); @@ -254,6 +271,21 @@ describe('', () => { }); }); + it('does not render instant password is instance is passwordless', () => { + mockUserSettings = new UserSettings({ + attributes: { + password: { + enabled: true, + required: false, + }, + }, + } as unknown as UserSettingsJSON); + + const { container } = render(); + const instantPasswordField = container.querySelector('input#password') as HTMLInputElement; + expect(instantPasswordField).toBeNull(); + }); + it.each(['google', 'facebook'])( 'renders the start screen, presses the %s button and starts an oauth flow', async provider => { @@ -315,24 +347,16 @@ describe('', () => { identifier: 'boss@clerk.dev', }); expect(mockNavigate).not.toHaveBeenCalled(); - expect(mockSetSession).toHaveBeenNthCalledWith( - 1, - 'deadbeef', - mockNavigateAfterSignIn, - ); + expect(mockSetSession).toHaveBeenNthCalledWith(1, 'deadbeef', mockNavigateAfterSignIn); }); }); }); describe('when the instance is invitation only', () => { it('renders the external account verification error if available', async () => { - const errorMsg = - 'You cannot sign up with sokratis.vidros@gmail.com since this is an invitation-only application'; + const errorMsg = 'You cannot sign up with sokratis.vidros@gmail.com since this is an invitation-only application'; - mocked( - useCoreSignIn as jest.Mock, - true, - ).mockImplementationOnce( + mocked(useCoreSignIn as jest.Mock, true).mockImplementationOnce( () => ({ create: mockCreateRequest, @@ -356,10 +380,7 @@ describe('', () => { it('renders the external account verification error if available', async () => { const errorMsg = 'You did not grant access to your Google account'; - mocked( - useCoreSignIn as jest.Mock, - true, - ).mockImplementationOnce( + mocked(useCoreSignIn as jest.Mock, true).mockImplementationOnce( () => ({ create: mockCreateRequest, diff --git a/packages/clerk-js/src/ui/signIn/SignInStart.tsx b/packages/clerk-js/src/ui/signIn/SignInStart.tsx index b3c9aa858de..4d19df2a728 100644 --- a/packages/clerk-js/src/ui/signIn/SignInStart.tsx +++ b/packages/clerk-js/src/ui/signIn/SignInStart.tsx @@ -1,20 +1,16 @@ import { Control } from '@clerk/shared/components/control'; import { Form } from '@clerk/shared/components/form'; -import { Input, InputType } from '@clerk/shared/components/input'; +import { Input } from '@clerk/shared/components/input'; import { PhoneInput } from '@clerk/shared/components/phoneInput'; -import { - ClerkAPIError, - OAuthStrategy, - SignInParams, - Web3Strategy, -} from '@clerk/types'; +import { ClerkAPIError, SignInParams } from '@clerk/types'; import cn from 'classnames'; import React from 'react'; import { buildRequest, FieldState, - FirstFactorConfigs, + getIdentifierControlDisplayValues, handleError, + LoadingScreen, PoweredByClerk, Separator, useFieldState, @@ -30,12 +26,13 @@ import { } from 'ui/contexts'; import { useNavigate } from 'ui/hooks'; import { useSupportEmail } from 'ui/hooks/useSupportEmail'; +import { getClerkQueryParam } from 'utils/getClerkQueryParam'; import { SignUpLink } from './SignUpLink'; import { OAuth, Web3 } from './strategies'; export function _SignInStart(): JSX.Element { - const environment = useEnvironment(); + const { userSettings } = useEnvironment(); const { setSession } = useCoreClerk(); const signIn = useCoreSignIn(); const { navigate } = useNavigate(); @@ -44,41 +41,52 @@ export function _SignInStart(): JSX.Element { const identifier = useFieldState('identifier', ''); const instantPassword = useFieldState('password', ''); + const organizationTicket = getClerkQueryParam('__clerk_ticket') || ''; const [error, setError] = React.useState(); + const [isLoading, setIsLoading] = React.useState(false); + + const standardFormAttributes = userSettings.enabledFirstFactorIdentifiers; + const web3FirstFactors = userSettings.web3FirstFactors; + const socialProviderStrategies = userSettings.socialProviderStrategies; + const passwordBasedInstance = userSettings.instanceIsPasswordBased; - const { authConfig } = environment; + React.useEffect(() => { + if (!organizationTicket) { + return; + } - const firstPartyOptions = authConfig.identificationStrategies.filter( - strategy => !strategy.includes('oauth') && !strategy.includes('web3'), + setIsLoading(true); + signIn + .create({ + strategy: 'ticket', + ticket: organizationTicket, + }) + .then(res => { + switch (res.status) { + case 'needs_first_factor': + return navigate('factor-one'); + case 'needs_second_factor': + return navigate('factor-two'); + case 'complete': + return setSession(res.createdSessionId, navigateAfterSignIn); + default: { + const msg = `Response: ${res.status} not supported yet.\nFor more information contact us at ${supportEmail}`; + alert(msg); + } + } + }) + .catch(err => { + return attemptToRecoverFromSignInError(err); + }) + .finally(() => { + setIsLoading(false); + }); + }, []); + + const identifierInputDisplayValues = getIdentifierControlDisplayValues( + standardFormAttributes, ); - const firstPartyKey = - firstPartyOptions.length == 0 - ? null - : [...firstPartyOptions].sort().join('_'); - - const firstPartyLabel = - firstPartyKey && FirstFactorConfigs[firstPartyKey] - ? FirstFactorConfigs[firstPartyKey].label - : ''; - - const fieldType: InputType = ( - firstPartyKey && FirstFactorConfigs[firstPartyKey] - ? FirstFactorConfigs[firstPartyKey].fieldType - : 'text' - ) as InputType; - - const firstFactors = authConfig.firstFactors; - const web3Options = firstFactors - .filter(fac => fac.startsWith('web3')) - .sort() as Web3Strategy[]; - const oauthOptions = firstFactors - .filter(fac => fac.startsWith('oauth')) - .sort() as OAuthStrategy[]; - - const passwordBasedInstance = authConfig.password === 'required'; - - // TODO: Clean up the following code end React.useEffect(() => { async function handleOauthError() { const error = signIn?.firstFactorVerification?.error; @@ -87,11 +95,8 @@ export function _SignInStart(): JSX.Element { error?.code === ERROR_CODES.OAUTH_ACCESS_DENIED ) { setError(error.longMessage); - - // TODO: This is a hack to reset the sign in attempt so that the oauth error - // does not persist on full page reloads. - // - // We will revise this strategy as part of the Clerk DX epic. + // TODO: This is a workaround in order to reset the sign in attempt + // so that the oauth error does not persist on full page reloads. void (await signIn.create({})); } } @@ -162,30 +167,42 @@ export function _SignInStart(): JSX.Element { return signInWithFields(identifier, instantPassword); }; + if (isLoading) { + return ; + } + const hasSocialOrWeb3Buttons = + !!socialProviderStrategies.length || !!web3FirstFactors.length; + return ( <>

- - + + - {firstPartyOptions.length > 0 && ( + {standardFormAttributes.length > 0 && ( <> - {(oauthOptions.length > 0 || web3Options.length > 0) && ( - - )} + {hasSocialOrWeb3Buttons && }
- {fieldType === phoneFieldType ? ( + {identifierInputDisplayValues.fieldType === phoneFieldType ? ( identifier.setValue(el.value || '')} value={identifier.value} autoFocus diff --git a/packages/clerk-js/src/ui/signIn/strategies/OAuth.tsx b/packages/clerk-js/src/ui/signIn/strategies/OAuth.tsx index 2242e104fac..fcc3ecd43f5 100644 --- a/packages/clerk-js/src/ui/signIn/strategies/OAuth.tsx +++ b/packages/clerk-js/src/ui/signIn/strategies/OAuth.tsx @@ -1,10 +1,10 @@ -import type { OAuthProvider, OAuthStrategy } from '@clerk/types'; +import type { OAuthStrategy } from '@clerk/types'; +import { getOAuthProviderData } from '@clerk/types'; import React from 'react'; import { buildSSOCallbackURL, ButtonSet, ButtonSetOptions, - getOAuthProviderData, handleError, } from 'ui/common'; import { useCoreSignIn, useEnvironment, useSignInContext } from 'ui/contexts'; @@ -22,10 +22,8 @@ export function OAuth({ }: OauthProps): JSX.Element | null { const ctx = useSignInContext(); const signIn = useCoreSignIn(); - const environment = useEnvironment(); - - const { displayConfig } = environment; - + const { displayConfig } = useEnvironment(); + const startOauth = async (e: React.MouseEvent, strategy: OAuthStrategy) => { e.preventDefault(); @@ -41,13 +39,13 @@ export function OAuth({ }; const options = oauthOptions.reduce((memo, o) => { - const key = o.replace('oauth_', '') as OAuthProvider; - const data = getOAuthProviderData(key); + const data = getOAuthProviderData({ strategy: o }); if (data) { memo.push({ - ...data, - strategy: o, + id: data.provider, + name: data.name, + strategy: data.strategy, }); } diff --git a/packages/clerk-js/src/ui/signIn/strategies/Web3.tsx b/packages/clerk-js/src/ui/signIn/strategies/Web3.tsx index f6e569f0b9e..07ceee4f470 100644 --- a/packages/clerk-js/src/ui/signIn/strategies/Web3.tsx +++ b/packages/clerk-js/src/ui/signIn/strategies/Web3.tsx @@ -21,9 +21,7 @@ export function Web3({ }: Web3Props): JSX.Element | null { const clerk = useCoreClerk(); const ctx = useSignInContext(); - const environment = useEnvironment(); - - const { displayConfig } = environment; + const { displayConfig } = useEnvironment(); const startWeb3 = async (e: React.MouseEvent) => { e.preventDefault(); diff --git a/packages/clerk-js/src/ui/signUp/SignUp.test.tsx b/packages/clerk-js/src/ui/signUp/SignUp.test.tsx index f8649630d58..5d7c38c60e1 100644 --- a/packages/clerk-js/src/ui/signUp/SignUp.test.tsx +++ b/packages/clerk-js/src/ui/signUp/SignUp.test.tsx @@ -1,6 +1,6 @@ import { render } from '@clerk/shared/testUtils'; import { EnvironmentResource } from '@clerk/types'; -import { AuthConfig, Session } from 'core/resources'; +import { AuthConfig, Session } from 'core/resources/internal'; import React from 'react'; import { SignUp } from 'ui/signUp/SignUp'; @@ -26,11 +26,7 @@ jest.mock('ui/contexts', () => { displayConfig: { homeUrl: 'https://www.bbc.com', }, - authConfig: { - identificationStrategies: ['email_address', 'oauth_google'], - firstFactors: ['email_address', 'oauth_google'], - singleSessionMode: true, - } as Partial, + authConfig: { singleSessionMode: true } as Partial, } as Partial), ), withCoreSessionSwitchGuard: (a: any) => a, diff --git a/packages/clerk-js/src/ui/signUp/SignUpOAuth.tsx b/packages/clerk-js/src/ui/signUp/SignUpOAuth.tsx index 868fc93f8cc..11a37c82485 100644 --- a/packages/clerk-js/src/ui/signUp/SignUpOAuth.tsx +++ b/packages/clerk-js/src/ui/signUp/SignUpOAuth.tsx @@ -1,10 +1,10 @@ -import type { OAuthProvider, OAuthStrategy } from '@clerk/types'; +import type { OAuthStrategy } from '@clerk/types'; +import { getOAuthProviderData } from '@clerk/types'; import React from 'react'; import { buildSSOCallbackURL, ButtonSet, ButtonSetOptions, - getOAuthProviderData, handleError, } from 'ui/common'; import { useCoreSignUp, useEnvironment, useSignUpContext } from 'ui/contexts'; @@ -39,13 +39,13 @@ export function SignUpOAuth({ }; const options = oauthOptions.reduce((memo, o) => { - const key = o.replace('oauth_', '') as OAuthProvider; - const data = getOAuthProviderData(key); + const data = getOAuthProviderData({ strategy: o as OAuthStrategy }); if (data) { memo.push({ - ...data, - strategy: o, + id: data.provider, + name: data.name, + strategy: data.strategy, }); } diff --git a/packages/clerk-js/src/ui/signUp/SignUpStart.test.tsx b/packages/clerk-js/src/ui/signUp/SignUpStart.test.tsx index a51ad533c96..437287aebee 100644 --- a/packages/clerk-js/src/ui/signUp/SignUpStart.test.tsx +++ b/packages/clerk-js/src/ui/signUp/SignUpStart.test.tsx @@ -6,7 +6,8 @@ import { waitFor, } from '@clerk/shared/testUtils'; import { titleize } from '@clerk/shared/utils/string'; -import { AuthConfig, Session } from 'core/resources'; +import { UserSettingsJSON } from '@clerk/types'; +import { Session, UserSettings } from 'core/resources/internal'; import React from 'react'; import { useCoreSignUp } from 'ui/contexts'; @@ -16,8 +17,7 @@ const navigateMock = jest.fn(); const mockCreateRequest = jest.fn(); const mockSetSession = jest.fn(); const mockAuthenticateWithRedirect = jest.fn(); -const mockIdentificationRequirements = jest.fn(); -let mockAuthConfig: Partial; +let mockUserSettings: UserSettings; const oldWindowLocation = window.location; const setWindowQueryParams = (params: Array<[string, string]>) => { @@ -61,7 +61,8 @@ jest.mock('ui/contexts', () => { applicationName: 'My test app', afterSignUpUrl: 'http://test.host', }, - authConfig: mockAuthConfig, + userSettings: mockUserSettings, + authConfig: { singleSessionMode: false }, })), }; }); @@ -78,9 +79,9 @@ describe('', () => { const { location } = window; beforeEach(() => { - mockIdentificationRequirements.mockImplementation(() => [ - ['email_address', 'oauth_google', 'oauth_facebook'], - ]); + // mockIdentificationRequirements.mockImplementation(() => [ + // ['email_address', 'oauth_google', 'oauth_facebook'], + // ]); mockCreateRequest.mockImplementation(() => Promise.resolve({ @@ -93,13 +94,43 @@ describe('', () => { }), ); - mockAuthConfig = { - username: 'on', - firstName: 'required', - lastName: 'required', - password: 'required', - identificationRequirements: mockIdentificationRequirements(), - }; + mockUserSettings = new UserSettings({ + attributes: { + username: { + enabled: true, + }, + first_name: { + enabled: true, + required: true, + }, + last_name: { + enabled: true, + required: true, + }, + password: { + enabled: true, + required: true, + }, + email_address: { + enabled: true, + required: true, + used_for_first_factor: true, + }, + phone_number: { + enabled: true, + }, + }, + social: { + oauth_google: { + enabled: true, + strategy: 'oauth_google', + }, + oauth_facebook: { + enabled: true, + strategy: 'oauth_facebook', + }, + }, + } as UserSettingsJSON); }); afterEach(() => { @@ -110,7 +141,7 @@ describe('', () => { global.window.location = location; }); - it('renders the sign up start screen', async () => { + it('renders the sign up start screen', () => { const tree = renderJSON(); expect(tree).toMatchSnapshot(); }); @@ -118,14 +149,11 @@ describe('', () => { it('renders the start screen, types the name, email, and password and creates a sign up attempt', async () => { render(); - await userEvent.type(screen.getByLabelText('First name'), 'John'); - await userEvent.type(screen.getByLabelText('Last name'), 'Doe'); - await userEvent.type(screen.getByLabelText('Username'), 'jdoe'); - await userEvent.type( - screen.getByLabelText('Email address'), - 'jdoe@example.com', - ); - await userEvent.type(screen.getByLabelText('Password'), 'p@ssW0rd'); + userEvent.type(screen.getByLabelText('First name'), 'John'); + userEvent.type(screen.getByLabelText('Last name'), 'Doe'); + userEvent.type(screen.getByLabelText('Username'), 'jdoe'); + userEvent.type(screen.getByLabelText('Email address'), 'jdoe@example.com'); + userEvent.type(screen.getByLabelText('Password'), 'p@ssW0rd'); userEvent.click(screen.getByRole('button', { name: 'Sign up' })); @@ -169,7 +197,7 @@ describe('', () => { }, ); - it('renders the external account verification error if available', async () => { + it('renders the external account verification error if available', () => { const errorMsg = 'You cannot sign up with sokratis.vidros@gmail.com since this is an invitation-only application'; @@ -193,14 +221,33 @@ describe('', () => { expect(mockCreateRequest).toHaveBeenNthCalledWith(1, {}); }); - it('only renders the SSO buttons if no other method is supported', async () => { - mockIdentificationRequirements.mockImplementation(() => [ - ['oauth_google', 'oauth_facebook'], - ]); - mockAuthConfig = { - username: 'off', - identificationRequirements: mockIdentificationRequirements(), - }; + it('only renders the SSO buttons if no other method is supported', () => { + mockUserSettings = new UserSettings({ + attributes: { + username: { + enabled: false, + }, + email_address: { + enabled: true, + }, + phone_number: { + enabled: true, + }, + password: { + required: false, + }, + }, + social: { + oauth_google: { + enabled: true, + strategy: 'oauth_google', + }, + oauth_facebook: { + enabled: true, + strategy: 'oauth_facebook', + }, + }, + } as UserSettingsJSON); render(); screen.getByRole('button', { name: /Google/ }); @@ -211,7 +258,7 @@ describe('', () => { }); describe('when the user does not grant access to their Facebook account', () => { - it('renders the external account verification error if available', async () => { + it('renders the external account verification error if available', () => { const errorMsg = 'You did not grant access to your Facebook account'; (useCoreSignUp as jest.Mock).mockImplementation(() => { @@ -235,79 +282,94 @@ describe('', () => { }); }); - describe('with __clerk_invitation_token parameter', () => { - beforeEach(() => { - setWindowQueryParams([['__clerk_invitation_token', '123456']]); - }); + describe('with invitation parameter', () => { + function runTokenTests(tokenType: string) { + describe(`with ${tokenType}`, () => { + beforeEach(() => { + setWindowQueryParams([[tokenType, '123456']]); + }); - it('it auto-completes sign up flow if sign up is complete after create', async () => { - mockCreateRequest.mockImplementation(() => - Promise.resolve({ - status: 'complete', - emailAddress: 'jdoe@example.com', - }), - ); - render(); - await waitFor(() => { - expect(mockSetSession).toHaveBeenCalled(); - }); - }); + it('it auto-completes sign up flow if sign up is complete after create', async () => { + mockCreateRequest.mockImplementation(() => + Promise.resolve({ + status: 'complete', + emailAddress: 'jdoe@example.com', + }), + ); + render(); + await waitFor(() => { + expect(mockSetSession).toHaveBeenCalled(); + }); + }); - it('it does not auto-complete sign up flow if sign up if requirements are missing', async () => { - mockCreateRequest.mockImplementation(() => - Promise.resolve({ - status: 'missing_requirements', - emailAddress: 'jdoe@example.com', - verifications: { - emailAddress: { - status: 'unverified', - }, - }, - }), - ); - render(); - await waitFor(() => { - expect(mockSetSession).not.toHaveBeenCalled(); - screen.getByText(/First name/); - screen.getByText(/Last name/); - screen.getByText(/Password/); - screen.getByText(/Username/); - }); - }); + it('it does not auto-complete sign up flow if sign up if requirements are missing', async () => { + mockCreateRequest.mockImplementation(() => + Promise.resolve({ + status: 'missing_requirements', + emailAddress: 'jdoe@example.com', + verifications: { + emailAddress: { + status: 'unverified', + }, + }, + }), + ); + render(); + await waitFor(() => { + expect(mockSetSession).not.toHaveBeenCalled(); + screen.getByText(/First name/); + screen.getByText(/Last name/); + screen.getByText(/Password/); + screen.getByText(/Username/); + }); + }); - it('it displays email and waits for input if sign up is not complete', async () => { - mockCreateRequest.mockImplementation(() => - Promise.resolve({ - status: 'missing_requirements', - emailAddress: 'jdoe@example.com', - verifications: { - emailAddress: { - status: 'unverified', + it('it displays email and waits for input if sign up is not complete', async () => { + mockCreateRequest.mockImplementation(() => + Promise.resolve({ + status: 'missing_requirements', + emailAddress: 'jdoe@example.com', + verifications: { + emailAddress: { + status: 'unverified', + }, + }, + }), + ); + render(); + await waitFor(() => { + const emailInput = screen.getByDisplayValue('jdoe@example.com'); + expect(emailInput).toBeDisabled(); + }); + }); + + it('does not render the phone number field', async () => { + mockUserSettings = new UserSettings({ + attributes: { + phone_number: { + enabled: true, + required: true, + }, + password: { + required: false, + }, }, - }, - }), - ); - render(); - await waitFor(() => { - const emailInput = screen.getByDisplayValue('jdoe@example.com'); - expect(emailInput).toBeDisabled(); + } as UserSettingsJSON); + + const { container } = render(); + const labels = container.querySelectorAll('label'); + await waitFor(() => { + expect( + Array.from(labels) + .map(l => l.htmlFor) + .includes('phoneNumber'), + ).toBeFalsy(); + }); + }); }); - }); - - it('does not render the phone number field', async () => { - mockIdentificationRequirements.mockImplementation(() => [ - ['phone_number'], - ]); + } - const { container } = render(); - const labels = container.querySelectorAll('label'); - await waitFor(() => { - expect( - Array.from(labels) - .map(l => l.htmlFor) - .includes('phoneNumber'), - ).toBeFalsy(); - }); - }); + runTokenTests('__clerk_invitation_token'); + runTokenTests('__clerk_ticket'); }); }); diff --git a/packages/clerk-js/src/ui/signUp/SignUpStart.tsx b/packages/clerk-js/src/ui/signUp/SignUpStart.tsx index fc8bcb0c742..aa53687c89e 100644 --- a/packages/clerk-js/src/ui/signUp/SignUpStart.tsx +++ b/packages/clerk-js/src/ui/signUp/SignUpStart.tsx @@ -2,7 +2,8 @@ import { Control } from '@clerk/shared/components/control'; import { Form } from '@clerk/shared/components/form'; import { Input } from '@clerk/shared/components/input'; import { PhoneInput } from '@clerk/shared/components/phoneInput'; -import { OAuthStrategy, SignUpResource, Web3Strategy } from '@clerk/types'; +import { noop } from '@clerk/shared/utils'; +import { SignUpParams, SignUpResource } from '@clerk/types'; import React from 'react'; import type { FieldState } from 'ui/common'; import { @@ -29,17 +30,14 @@ import { getClerkQueryParam } from 'utils/getClerkQueryParam'; import { SignInLink } from './SignInLink'; import { SignUpOAuth } from './SignUpOAuth'; import { SignUpWeb3 } from './SignUpWeb3'; -import { - determineFirstPartyFields, - determineOauthOptions, - determineWeb3Options, -} from './utils'; +import { determineFirstPartyFields } from './utils'; type ActiveIdentifier = 'emailAddress' | 'phoneNumber'; function _SignUpStart(): JSX.Element { const { navigate } = useNavigate(); const environment = useEnvironment(); + const { userSettings } = environment; const { setSession } = useCoreClerk(); const { navigateAfterSignUp } = useSignUpContext(); const [emailOrPhoneActive, setEmailOrPhoneActive] = @@ -57,27 +55,49 @@ function _SignUpStart(): JSX.Element { 'invitation_token', getClerkQueryParam('__clerk_invitation_token') || '', ), + organizationInvitationToken: useFieldState( + 'ticket', + getClerkQueryParam('__clerk_ticket') || '', + ), } as const; type FormFieldsKey = keyof typeof formFields; const [error, setError] = React.useState(); const hasInvitationToken = !!formFields.invitationToken.value; - const fields = determineFirstPartyFields(environment, hasInvitationToken); - const oauthOptions = determineOauthOptions(environment) as OAuthStrategy[]; - const web3Options = determineWeb3Options(environment) as Web3Strategy[]; - const handleInvitationFlow = async () => { - const token = formFields.invitationToken.value; - if (!token) { + const hasOrganizationInvitationToken = + !!formFields.organizationInvitationToken.value; + const hasToken = hasInvitationToken || hasOrganizationInvitationToken; + + const fields = determineFirstPartyFields( + environment, + hasInvitationToken, + hasOrganizationInvitationToken, + ); + const oauthOptions = userSettings.socialProviderStrategies; + const web3Options = userSettings.web3FirstFactors; + + const handleTokenFlow = () => { + const invitationToken = formFields.invitationToken.value; + const organizationInvitationToken = + formFields.organizationInvitationToken.value; + if (!invitationToken && !organizationInvitationToken) { return; } + const invitationParams: SignUpParams = invitationToken + ? { invitation_token: invitationToken } + : { strategy: 'ticket', ticket: organizationInvitationToken }; setIsLoading(true); + signUp - .create({ invitation_token: token }) + .create(invitationParams) .then(res => { formFields.emailAddress.setValue(res.emailAddress || ''); void completeSignUpFlow(res); }) .catch(err => { + /* Clear token values when an error occurs in the initial sign up attempt */ + formFields.invitationToken.setValue(''); + formFields.organizationInvitationToken.setValue(''); handleError(err, [], setError); }) .finally(() => { @@ -86,7 +106,7 @@ function _SignUpStart(): JSX.Element { }; React.useLayoutEffect(() => { - void handleInvitationFlow(); + void handleTokenFlow(); }, []); React.useEffect(() => { @@ -140,6 +160,20 @@ function _SignUpStart(): JSX.Element { reqFields.push(formFields.phoneNumber); } + if (fields.organizationInvitationToken) { + // FIXME: Constructing a fake fields object for strategy. + reqFields.push( + { + name: 'strategy', + value: 'ticket', + setError: noop, + setValue: noop, + error: undefined, + }, + formFields.emailAddress, + ); + } + try { setError(undefined); const res = await signUp.create(buildRequest(reqFields)); @@ -149,7 +183,7 @@ function _SignUpStart(): JSX.Element { } }; - const completeSignUpFlow = async (su: SignUpResource) => { + const completeSignUpFlow = (su: SignUpResource) => { if (su.status === 'complete') { return setSession(su.createdSessionId, navigateAfterSignUp); } else if ( @@ -246,10 +280,12 @@ function _SignUpStart(): JSX.Element { ) : null; const shouldShowEmailAddressField = - (hasInvitationToken && !!formFields.emailAddress.value) || + (hasToken && !!formFields.emailAddress.value) || fields.emailAddress || (fields.emailOrPhone && emailOrPhoneActive === 'emailAddress'); + const disabledEmailField = hasToken && !!formFields.emailAddress.value; + const emailAddressField = shouldShowEmailAddressField && ( formFields.emailAddress.setValue(el.value || '')} - disabled={hasInvitationToken && !!formFields.emailAddress.value} + disabled={disabledEmailField} /> ); @@ -300,10 +336,10 @@ function _SignUpStart(): JSX.Element { <>
- {!hasInvitationToken && oauthOptions.length > 0 && ( + {!hasToken && oauthOptions.length > 0 && ( )} - {!hasInvitationToken && web3Options.length > 0 && ( + {!hasToken && web3Options.length > 0 && ( )} {atLeastOneFormField && ( diff --git a/packages/clerk-js/src/ui/signUp/SignUpVerify.test.tsx b/packages/clerk-js/src/ui/signUp/SignUpVerify.test.tsx index f2ef2540df6..6153df4ec6d 100644 --- a/packages/clerk-js/src/ui/signUp/SignUpVerify.test.tsx +++ b/packages/clerk-js/src/ui/signUp/SignUpVerify.test.tsx @@ -1,9 +1,11 @@ import { render, renderJSON } from '@clerk/shared/testUtils'; import { + AttributeData, SessionResource, - SignInStrategyName, SignUpResource, + UserSettingsJSON, } from '@clerk/types'; +import { UserSettings } from 'core/resources/internal'; import React from 'react'; import { @@ -25,7 +27,7 @@ const mockStartMagicLinkFlow = jest.fn(() => { }, } as any as SignUpResource); }); -let mockFirstFactors: SignInStrategyName[]; +let mockEmailAddressAttribute: Partial; let mockDisabledStrategies: string[] = []; jest.mock('ui/router/RouteContext'); @@ -37,16 +39,42 @@ jest.mock('ui/contexts', () => { applicationName: 'My test app', afterSignUpUrl: 'http://test.host', }, - authConfig: { - username: 'on', - firstName: 'required', - lastName: 'required', - password: 'required', - firstFactors: mockFirstFactors, - identificationRequirements: [ - ['email_address', 'phone_address', 'oauth_google', 'oauth_facebook'], - ], - }, + userSettings: new UserSettings({ + attributes: { + first_name: { + enabled: true, + required: false, + }, + last_name: { + enabled: true, + required: false, + }, + password: { + enabled: true, + required: false, + }, + username: { + enabled: true, + required: false, + }, + email_address: mockEmailAddressAttribute, + }, + social: { + oauth_google: { + enabled: true, + required: false, + authenticatable: false, + strategy: 'oauth_google', + }, + oauth_facebook: { + enabled: true, + required: false, + authenticatable: false, + strategy: 'oauth_facebook', + }, + }, + } as unknown as UserSettingsJSON), + authConfig: { singleSessionMode: false }, })), useCoreSession: () => { return { id: 'sess_id' } as SessionResource; @@ -105,20 +133,29 @@ describe('', () => { }); describe('verify email address', () => { - it('renders the sign up verification form', async () => { - mockFirstFactors = ['email_code', 'phone_code', 'password']; + it('renders the OTP sign up verification form', () => { + mockEmailAddressAttribute = { + enabled: true, + verifications: ['email_code'], + }; const tree = renderJSON(); expect(tree).toMatchSnapshot(); }); - it('renders the sign up verification form but prefers email_link if exists', async () => { - mockFirstFactors = ['email_code', 'phone_code', 'password', 'email_link']; + it('renders the magic link sign up verification form ', () => { + mockEmailAddressAttribute = { + enabled: true, + verifications: ['email_link'], + }; const tree = renderJSON(); expect(tree).toMatchSnapshot(); }); - it('can skip disabled verification strategies', async () => { - mockFirstFactors = ['email_code', 'phone_code', 'password', 'email_link']; + it('can skip disabled verification strategies', () => { + mockEmailAddressAttribute = { + enabled: true, + verifications: ['email_link'], + }; mockDisabledStrategies = ['email_link']; const { container } = render(); expect(container.querySelector('.cl-otp-input')).not.toBeNull(); @@ -126,7 +163,7 @@ describe('', () => { }); describe('verify phone number', () => { - it('renders the sign up verification form', async () => { + it('renders the OTP sign up verification form', () => { const tree = renderJSON(); expect(tree).toMatchSnapshot(); }); diff --git a/packages/clerk-js/src/ui/signUp/SignUpVerify.tsx b/packages/clerk-js/src/ui/signUp/SignUpVerify.tsx index 11d2c923ae2..99335375494 100644 --- a/packages/clerk-js/src/ui/signUp/SignUpVerify.tsx +++ b/packages/clerk-js/src/ui/signUp/SignUpVerify.tsx @@ -24,18 +24,15 @@ import { import { SignUpVerifyEmailAddressWithMagicLink } from './SignUpVerifyEmailAddressWithMagicLink'; -const emailLinkStrategy = 'email_link'; - function _SignUpVerifyEmailAddress(): JSX.Element { - const { authConfig } = useEnvironment(); - const { firstFactors } = authConfig; + const { userSettings } = useEnvironment(); + const { attributes } = userSettings; - // TODO: SignUp should have a field similar to SignIn's supportedFirstFactors - // listing the available strategies for this signUp - const emailLinkStrategyEnabled = firstFactors.includes(emailLinkStrategy); + const emailLinkStrategyEnabled = + attributes.email_address.verifications.includes('email_link'); const disableEmailLink = shouldDisableStrategy( useSignUpContext(), - emailLinkStrategy, + 'email_link', ); if (emailLinkStrategyEnabled && !disableEmailLink) { diff --git a/packages/clerk-js/src/ui/signUp/__snapshots__/SignUpVerify.test.tsx.snap b/packages/clerk-js/src/ui/signUp/__snapshots__/SignUpVerify.test.tsx.snap index a9e5c2372c3..ee5b8822357 100644 --- a/packages/clerk-js/src/ui/signUp/__snapshots__/SignUpVerify.test.tsx.snap +++ b/packages/clerk-js/src/ui/signUp/__snapshots__/SignUpVerify.test.tsx.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[` verify email address renders the sign up verification form 1`] = ` +exports[` verify email address renders the OTP sign up verification form 1`] = ` Array [
verify email address renders the sign up verification form but prefers email_link if exists 1`] = ` +exports[` verify email address renders the magic link sign up verification form 1`] = `
@@ -203,7 +203,7 @@ exports[` verify email address renders the sign up verification f
`; -exports[` verify phone number renders the sign up verification form 1`] = ` +exports[` verify phone number renders the OTP sign up verification form 1`] = ` Array [
{ // For specs refer to https://www.notion.so/clerkdev/Vocabulary-8f775765258643978f5811c88b140b2d // and the current Instance User settings options describe('returns first party field based on auth config', () => { - type Scenario = [string, Object, Object]; + type Scenario = [string, any, any]; const scenaria: Scenario[] = [ [ 'email only option', { - authConfig: { - identificationRequirements: [['email_address']], - firstName: 'required', - lastName: 'required', - password: 'required', - username: 'on', - }, + userSettings: new UserSettings({ + attributes: { + email_address: { + enabled: true, + required: true, + used_for_first_factor: true, + }, + phone_number: { + enabled: true, + required: false, + }, + first_name: { + enabled: true, + required: true, + }, + last_name: { + enabled: true, + required: true, + }, + password: { + enabled: true, + required: true, + }, + username: { + enabled: true, + }, + }, + } as UserSettingsJSON), }, { emailAddress: 'required', @@ -35,13 +53,34 @@ describe('determineFirstPartyFields()', () => { [ 'phone only option', { - authConfig: { - identificationRequirements: [['phone_number']], - firstName: 'required', - lastName: 'required', - password: 'required', - username: 'on', - }, + userSettings: new UserSettings({ + attributes: { + email_address: { + enabled: true, + required: false, + }, + phone_number: { + enabled: true, + required: true, + used_for_first_factor: true, + }, + first_name: { + enabled: true, + required: true, + }, + last_name: { + enabled: true, + required: true, + }, + password: { + enabled: true, + required: true, + }, + username: { + enabled: true, + }, + }, + } as UserSettingsJSON), }, { phoneNumber: 'required', @@ -54,13 +93,35 @@ describe('determineFirstPartyFields()', () => { [ 'email or phone option', { - authConfig: { - identificationRequirements: [['email_address'], ['phone_number']], - firstName: 'required', - lastName: 'required', - password: 'required', - username: 'on', - }, + userSettings: new UserSettings({ + attributes: { + phone_number: { + enabled: true, + required: true, + used_for_first_factor: true, + }, + email_address: { + enabled: true, + required: true, + used_for_first_factor: true, + }, + first_name: { + enabled: true, + required: true, + }, + last_name: { + enabled: true, + required: true, + }, + password: { + enabled: true, + required: true, + }, + username: { + enabled: true, + }, + }, + } as UserSettingsJSON), }, { emailOrPhone: 'required', @@ -73,16 +134,31 @@ describe('determineFirstPartyFields()', () => { [ 'optional first and last name', { - authConfig: { - identificationRequirements: [['email_address'], ['phone_number']], - firstName: 'on', - lastName: 'on', - password: 'required', - username: 'on', - }, + userSettings: new UserSettings({ + attributes: { + first_name: { + enabled: true, + }, + last_name: { + enabled: true, + }, + password: { + enabled: true, + required: true, + }, + username: { + enabled: true, + }, + email_address: { + enabled: true, + }, + phone_number: { + enabled: true, + }, + }, + } as UserSettingsJSON), }, { - emailOrPhone: 'required', firstName: 'on', lastName: 'on', password: 'required', @@ -92,76 +168,52 @@ describe('determineFirstPartyFields()', () => { [ 'no fields enabled', { - authConfig: { - identificationRequirements: [], - firstName: 'off', - lastName: 'off', - password: 'off', - username: 'off', - }, + userSettings: new UserSettings({ + attributes: { + phone_number: { + enabled: false, + required: false, + }, + email_address: { + enabled: false, + required: false, + }, + first_name: { + enabled: false, + required: false, + }, + last_name: { + enabled: false, + required: false, + }, + password: { + enabled: false, + required: false, + }, + username: { + enabled: false, + }, + }, + } as UserSettingsJSON), }, {}, ], ]; it.each(scenaria)('%s', (___, environment, result) => { - expect( - determineFirstPartyFields(environment as EnvironmentResource), - ).toEqual(result); + expect(determineFirstPartyFields(environment as EnvironmentResource)).toEqual(result); }); it.each(scenaria)('with invitation, %s', (___, environment, result) => { // Email address or phone number cannot be required when there's an // invitation token present. Instead, we'll require the invitationToken // parameter - const { - // @ts-ignore 2339 - emailAddress: ___emailAddress, - // @ts-ignore 2339 - emailOrPhone: ___emailOrPhone, - // @ts-ignore 2339 - phoneNumber: ___phoneNumber, - ...expected - } = result; - expect( - determineFirstPartyFields(environment as EnvironmentResource, true), - ).toEqual({ ...expected, invitationToken: 'required' }); + const expected = { ...result, invitationToken: 'required' }; + delete expected.emailAddress; + delete expected.phoneNumber; + delete expected.emailOrPhone; + const res = determineFirstPartyFields(environment as EnvironmentResource, true); + expect(res).toMatchObject(expected); }); }); }); - -describe('determineOauthOptions(environment)', () => { - it('returns oauth options based on auth config', () => { - const environment = { - authConfig: { - identificationRequirements: [ - ['email_address', 'oauth_google', 'oauth_facebook'], - ['oauth_google'], - ], - }, - } as EnvironmentResource; - - expect(determineOauthOptions(environment)).toEqual([ - 'oauth_facebook', - 'oauth_google', - ]); - }); -}); - -describe('determineWeb3Options(environment)', () => { - it('returns web3 options based on auth config', () => { - const environment = { - authConfig: { - firstFactors: [ - 'email_address', - 'web3_metamask_signature', - 'oauth_facebook', - ], - }, - } as EnvironmentResource; - - expect(determineWeb3Options(environment)).toEqual([ - 'web3_metamask_signature', - ]); - }); -}); diff --git a/packages/clerk-js/src/ui/signUp/utils.ts b/packages/clerk-js/src/ui/signUp/utils.ts index 5c7c232beb2..c1e35a69983 100644 --- a/packages/clerk-js/src/ui/signUp/utils.ts +++ b/packages/clerk-js/src/ui/signUp/utils.ts @@ -1,9 +1,5 @@ -import type { - EnvironmentResource, - IdentificationStrategy, - SignInStrategyName, - ToggleTypeWithRequire, -} from '@clerk/types'; +import { snakeToCamel } from '@clerk/shared/utils'; +import type { Attributes, EnvironmentResource } from '@clerk/types'; type FieldKeys = | 'emailOrPhone' @@ -13,68 +9,56 @@ type FieldKeys = | 'firstName' | 'lastName' | 'password' - | 'invitationToken'; + | 'invitationToken' + | 'organizationInvitationToken'; +// TODO: Refactor SignUp component and remove +// this leftover type type Fields = { - [key in FieldKeys]?: ToggleTypeWithRequire; + [key in FieldKeys]?: 'on' | 'off' | 'required'; }; +function isEmailOrPhone(attributes: Attributes) { + return ( + attributes.email_address.used_for_first_factor && + attributes.phone_number.used_for_first_factor + ); +} + export function determineFirstPartyFields( environment: EnvironmentResource, hasInvitation?: boolean, + hasOrganizationInvitation?: boolean, ): Fields { - const idRequirements = - environment.authConfig.identificationRequirements.flat(); + const { attributes } = environment.userSettings; + const fields: Fields = {}; - const idByEmail = idRequirements.includes('email_address'); - const idByPhone = idRequirements.includes('phone_number'); - const idByEmailOrPhone = idByEmail && idByPhone; - const idByUsername = - idRequirements.includes('username') || - environment.authConfig.username === 'on'; + Object.entries(attributes) + .filter(([key]) => ['username', 'first_name', 'last_name'].includes(key)) + .filter(([, desc]) => desc.enabled) + .forEach( + ([key, desc]) => + (fields[snakeToCamel(key) as keyof Fields] = desc.required + ? 'required' + : 'on'), + ); + if (hasInvitation) { fields.invitationToken = 'required'; - } else if (idByEmailOrPhone) { + } else if (hasOrganizationInvitation) { + fields.organizationInvitationToken = 'required'; + } else if (isEmailOrPhone(attributes)) { fields.emailOrPhone = 'required'; - } else if (idByEmail) { + } else if (attributes.email_address.used_for_first_factor) { fields.emailAddress = 'required'; - } else if (idByPhone) { + } else if (attributes.phone_number.used_for_first_factor) { fields.phoneNumber = 'required'; } - if (idByEmailOrPhone || idByEmail || idByPhone) { - if (idByUsername) { - fields.username = environment.authConfig.username; - } - - if (environment.authConfig.password === 'required') { - fields.password = environment.authConfig.password; - } - - if (['on', 'required'].includes(environment.authConfig.firstName)) { - fields.firstName = environment.authConfig.firstName; - } - if (['on', 'required'].includes(environment.authConfig.lastName)) { - fields.lastName = environment.authConfig.lastName; - } + if (attributes.password.required) { + fields.password = 'required'; } return fields; } - -export function determineOauthOptions( - environment: EnvironmentResource, -): IdentificationStrategy[] { - const idRequirements = [ - ...new Set(environment.authConfig.identificationRequirements.flat()), - ]; - return idRequirements.filter(fac => fac.startsWith('oauth')).sort(); -} - -export function determineWeb3Options( - environment: EnvironmentResource, -): SignInStrategyName[] { - const idRequirements = [...new Set(environment.authConfig.firstFactors)]; - return idRequirements.filter(fac => fac.startsWith('web3')).sort(); -} diff --git a/packages/clerk-js/src/ui/userProfile/UserProfile.test.tsx b/packages/clerk-js/src/ui/userProfile/UserProfile.test.tsx index acac8e517e0..846310649fb 100644 --- a/packages/clerk-js/src/ui/userProfile/UserProfile.test.tsx +++ b/packages/clerk-js/src/ui/userProfile/UserProfile.test.tsx @@ -10,7 +10,7 @@ import { SignInResource, SignUpResource, } from '@clerk/types'; -import { AuthConfig } from 'core/resources'; +import { AuthConfig, ExternalAccount, UserSettings } from 'core/resources/internal'; import React from 'react'; import ReactDOM from 'react-dom'; @@ -65,11 +65,47 @@ jest.mock('ui/contexts', () => ({ }, }, }, + userSettings: { + attributes: { + phone_number: { + // this should be true since it is a first factor but keeping it false for the needs of the test case + enabled: false, + used_for_second_factor: true, + second_factors: ['phone_code'], + }, + email_address: { + // this should be true since it is a first factor but keeping it false for the needs of the test case + enabled: false, + used_for_first_factor: true, + first_factors: ['email_code'], + }, + first_name: { + enabled: true, + }, + last_name: { + enabled: true, + }, + username: { + enabled: false, + }, + password: { + enabled: false, + }, + web3_wallet: { + enabled: false, + }, + }, + social: { + oauth_google: { + enabled: true, + }, + oauth_facebook: { + enabled: true, + }, + }, + } as Partial, authConfig: { - secondFactors: ['phone_code'], singleSessionMode: true, - firstFactors: ['email_address', 'oauth_google', 'oauth_facebook'], - emailAddressVerificationStrategies: ['email_code'], } as Partial, })), withCoreUserGuard: (a: any) => a, @@ -77,17 +113,18 @@ jest.mock('ui/contexts', () => ({ return { twoFactorEnabled: () => true, externalAccounts: [ - { - id: 'fbac_yolo', - provider: 'facebook', - approvedScopes: 'email', - emailAddress: 'peter@gmail.com', - firstName: 'Peter', - lastName: 'Smith', - providerUserId: '10147951078263327', - providerSlug: () => 'facebook', - providerTitle: () => 'Facebook', - } as ExternalAccountResource, + new ExternalAccount( + { + id: 'fbac_yolo', + provider: 'facebook', + approvedScopes: 'email', + emailAddress: 'peter@gmail.com', + firstName: 'Peter', + lastName: 'Smith', + providerUserId: '10147951078263327', + } as ExternalAccountResource, + '/path', + ), ], phoneNumbers: [ { diff --git a/packages/clerk-js/src/ui/userProfile/__snapshots__/UserProfile.test.tsx.snap b/packages/clerk-js/src/ui/userProfile/__snapshots__/UserProfile.test.tsx.snap index 84c156feddb..d15c81647f7 100644 --- a/packages/clerk-js/src/ui/userProfile/__snapshots__/UserProfile.test.tsx.snap +++ b/packages/clerk-js/src/ui/userProfile/__snapshots__/UserProfile.test.tsx.snap @@ -119,11 +119,10 @@ Array [ >
Facebook - peter@gmail.com
@@ -3348,11 +3347,10 @@ Array [ >
Facebook - peter@gmail.com
Facebook   - Facebook + Facebook Account

-

- peter@gmail.com -
+
{ }; }); +const OTHER_ATTRIBUTES = { + username: { + enabled: false, + }, + email_address: { + enabled: false + }, + phone_number: { + enabled: false + }, + web3_wallet: { + enabled: false + } +}; + describe('', () => { afterEach(() => { jest.clearAllMocks(); @@ -34,9 +49,18 @@ describe('', () => { it('renders personal information for auth config that requires name', () => { mockEnvironment.mockImplementation(() => { return { - authConfig: { - firstName: 'required', - } as AuthConfigResource, + userSettings: { + attributes: { + first_name: { + enabled: true, + required: true + }, + last_name: { + enabled: false + }, + ...OTHER_ATTRIBUTES + } + } as UserSettingsResource, }; }); render(); @@ -46,9 +70,17 @@ describe('', () => { it('renders personal information for auth config that has name turned on', () => { mockEnvironment.mockImplementation(() => { return { - authConfig: { - lastName: 'on', - } as AuthConfigResource, + userSettings: { + attributes: { + last_name: { + enabled: true, + }, + first_name: { + enabled: false, + }, + ...OTHER_ATTRIBUTES + } + } as UserSettingsResource }; }); render(); @@ -58,10 +90,17 @@ describe('', () => { it('does not render personal information for auth config that has named turned off', () => { mockEnvironment.mockImplementation(() => { return { - authConfig: { - firstName: 'off', - lastName: 'off', - } as AuthConfigResource, + userSettings: { + attributes: { + first_name: { + enabled: false, + }, + last_name: { + enabled: false, + }, + ...OTHER_ATTRIBUTES + } + } as UserSettingsResource }; }); render(); diff --git a/packages/clerk-js/src/ui/userProfile/account/Account.tsx b/packages/clerk-js/src/ui/userProfile/account/Account.tsx index 3b47f6c91e5..fc43af04984 100644 --- a/packages/clerk-js/src/ui/userProfile/account/Account.tsx +++ b/packages/clerk-js/src/ui/userProfile/account/Account.tsx @@ -1,13 +1,9 @@ -import type { AuthConfigResource } from '@clerk/types'; import React from 'react'; -import { useEnvironment } from 'ui/contexts'; import { PersonalInformationCard } from 'ui/userProfile/account/personalInformation'; import { ProfileCard } from 'ui/userProfile/account/profileCard'; import { PageHeading } from 'ui/userProfile/pageHeading'; export const Account = (): JSX.Element => { - const { authConfig } = useEnvironment(); - return ( <> { subtitle='Manage settings related to your account' /> - {shouldShowPersonalInformation(authConfig) && } + ); }; - -function shouldShowPersonalInformation( - authConfig: AuthConfigResource, -): boolean { - return authConfig.firstName !== 'off' || authConfig.lastName !== 'off'; -} diff --git a/packages/clerk-js/src/ui/userProfile/account/personalInformation/PersonalInformationCard.tsx b/packages/clerk-js/src/ui/userProfile/account/personalInformation/PersonalInformationCard.tsx index 04dec96af3d..a151c248b26 100644 --- a/packages/clerk-js/src/ui/userProfile/account/personalInformation/PersonalInformationCard.tsx +++ b/packages/clerk-js/src/ui/userProfile/account/personalInformation/PersonalInformationCard.tsx @@ -1,12 +1,23 @@ import { List } from '@clerk/shared/components/list'; import { TitledCard } from '@clerk/shared/components/titledCard'; import React from 'react'; -import { useCoreUser } from 'ui/contexts'; +import { useCoreUser, useEnvironment } from 'ui/contexts'; import { useNavigate } from 'ui/hooks'; -export const PersonalInformationCard = (): JSX.Element => { +export const PersonalInformationCard = (): JSX.Element | null => { const user = useCoreUser(); const { navigate } = useNavigate(); + const { userSettings } = useEnvironment(); + const { + attributes: { first_name, last_name }, + } = userSettings; + + const hasAtLeastOneAttributeEnable = + first_name?.enabled || last_name?.enabled; + + if (!hasAtLeastOneAttributeEnable) { + return null; + } const firstNameRow = ( { ); + const showFirstName = first_name.enabled; + const showLastName = last_name.enabled; + return ( { subtitle='Manage personal information settings' > - {firstNameRow} - {lastnameRow} + {showFirstName && firstNameRow} + {showLastName && lastnameRow} ); diff --git a/packages/clerk-js/src/ui/userProfile/account/profileCard/ProfileCard.test.tsx b/packages/clerk-js/src/ui/userProfile/account/profileCard/ProfileCard.test.tsx index b834b1a6b2b..f7776423183 100644 --- a/packages/clerk-js/src/ui/userProfile/account/profileCard/ProfileCard.test.tsx +++ b/packages/clerk-js/src/ui/userProfile/account/profileCard/ProfileCard.test.tsx @@ -1,6 +1,10 @@ import { renderJSON } from '@clerk/shared/testUtils'; import { EmailAddressResource, UserResource } from '@clerk/types'; import * as React from 'react'; +import { PartialDeep } from 'type-fest'; +import { + useEnvironment +} from 'ui/contexts'; import { ProfileCard } from './ProfileCard'; @@ -12,15 +16,8 @@ jest.mock('ui/hooks', () => { jest.mock('ui/contexts', () => { return { - useEnvironment: () => ({ - authConfig: { - emailAddress: 'required', - phoneNumber: 'on', - username: 'off', - }, - displayConfig: {}, - }), - useCoreUser: (): Partial => { + useEnvironment: jest.fn(), + useCoreUser: (): PartialDeep => { return { isPrimaryIdentification: jest.fn(() => true), emailAddresses: [ @@ -37,15 +34,65 @@ jest.mock('ui/contexts', () => { ], phoneNumbers: [], externalAccounts: [], + web3Wallets: [{ web3Wallet: '0x123456789' }] }; }, useCoreClerk: jest.fn(), }; }); +(useEnvironment as jest.Mock).mockImplementation(() => ({ + displayConfig: {}, + userSettings: { + attributes: { + email_address: { + enabled: true + }, + phone_number: { + enabled: true + }, + username: { + enabled: false + }, + web3_wallet: { + enabled: false + } + } + } +})); + describe('', () => { + afterEach(() => { + jest.clearAllMocks(); + }); + it('renders the ProfileCard', () => { const tree = renderJSON(); expect(tree).toMatchSnapshot(); }); + + it('renders the ProfileCard ', () => { + (useEnvironment as jest.Mock).mockImplementation(() => ({ + displayConfig: {}, + userSettings: { + attributes: { + email_address: { + enabled: true + }, + phone_number: { + enabled: true + }, + username: { + enabled: false + }, + web3_wallet: { + enabled: true + } + } + } + })); + + const tree = renderJSON(); + expect(tree).toMatchSnapshot(); + }); }); diff --git a/packages/clerk-js/src/ui/userProfile/account/profileCard/ProfileCard.tsx b/packages/clerk-js/src/ui/userProfile/account/profileCard/ProfileCard.tsx index 91ced2e4547..4c0f95b6765 100644 --- a/packages/clerk-js/src/ui/userProfile/account/profileCard/ProfileCard.tsx +++ b/packages/clerk-js/src/ui/userProfile/account/profileCard/ProfileCard.tsx @@ -21,12 +21,9 @@ function getWeb3WalletAddress(user: UserResource): string { return ''; } -function checkIfSectionIsOn(section: string) { - return section === 'on' || section === 'required'; -} - export function ProfileCard(): JSX.Element { - const { authConfig } = useEnvironment(); + const { userSettings } = useEnvironment(); + const { attributes } = userSettings; const user = useCoreUser(); const { navigate } = useNavigate(); const web3Wallet = getWeb3WalletAddress(user); @@ -100,10 +97,10 @@ export function ProfileCard(): JSX.Element { ); - const showWebWallet = !!web3Wallet; - const showUsername = checkIfSectionIsOn(authConfig.username); - const showEmail = checkIfSectionIsOn(authConfig.emailAddress); - const showPhone = checkIfSectionIsOn(authConfig.phoneNumber); + const showWebWallet = attributes.web3_wallet.enabled; + const showUsername = attributes.username.enabled; + const showEmail = attributes.email_address.enabled; + const showPhone = attributes.phone_number.enabled; return ( renders the ProfileCard 1`] = ` +
+
+

+ Profile +

+

+ Manage profile settings +

+
+
+
+
+ Photo +
+
+
+
+ +
+ +
+
+ +
+
+
+
+
+
+ + + + +
+
+`; + exports[` renders the ProfileCard 1`] = `
{ jest.mock('ui/contexts/EnvironmentContext', () => { return { useEnvironment: jest.fn(() => ({ - authConfig: { - firstFactors: ['email_link'], - emailAddressVerificationStrategies: ['email_link'], - }, - })), + userSettings: { + attributes: { + email_address: { + enabled: true, + verifications: ['email_link'], + } + } + } + }) as PartialDeep), }; }); diff --git a/packages/clerk-js/src/ui/userProfile/emailAdressess/EmailAddressVerificationWithMagicLink.test.tsx b/packages/clerk-js/src/ui/userProfile/emailAdressess/EmailAddressVerificationWithMagicLink.test.tsx index a7297c5d3a3..b95a78b1231 100644 --- a/packages/clerk-js/src/ui/userProfile/emailAdressess/EmailAddressVerificationWithMagicLink.test.tsx +++ b/packages/clerk-js/src/ui/userProfile/emailAdressess/EmailAddressVerificationWithMagicLink.test.tsx @@ -7,11 +7,6 @@ import { EmailAddressVerificationWithMagicLink } from './EmailAddressVerificatio jest.mock('ui/contexts', () => { return { - useEnvironment: jest.fn(() => ({ - authConfig: { - firstFactors: ['email_link'], - }, - })), useUserProfileContext: jest.fn(() => { return { routing: 'path', diff --git a/packages/clerk-js/src/ui/userProfile/emailAdressess/EmailDetail.test.tsx b/packages/clerk-js/src/ui/userProfile/emailAdressess/EmailDetail.test.tsx index 62464a23cf6..1549f7c832a 100644 --- a/packages/clerk-js/src/ui/userProfile/emailAdressess/EmailDetail.test.tsx +++ b/packages/clerk-js/src/ui/userProfile/emailAdressess/EmailDetail.test.tsx @@ -1,14 +1,14 @@ import { render, renderJSON, screen, userEvent } from '@clerk/shared/testUtils'; -import { EmailAddressResource } from '@clerk/types'; -import { SignInStrategyName } from '@clerk/types'; +import { EmailAddressResource, EnvironmentResource, SignInStrategyName, UserSettingsResource } from '@clerk/types'; import { ClerkAPIResponseError } from 'core/resources/Error'; import React from 'react'; - +import { PartialDeep } from 'type-fest'; import { EmailDetail } from './EmailDetail'; + const mockNavigate = jest.fn(); const mockUseCoreUser = jest.fn(); -let mockFirstFactors = [] as SignInStrategyName[]; +let mockFirstFactors = {} as PartialDeep; jest.mock('ui/hooks', () => ({ useNavigate: () => { @@ -39,11 +39,8 @@ jest.mock('ui/contexts', () => { return { useCoreUser: () => mockUseCoreUser(), useEnvironment: jest.fn(() => ({ - authConfig: { - firstFactors: mockFirstFactors, - emailAddressVerificationStrategies: mockFirstFactors, - }, - })), + userSettings: mockFirstFactors + }) as PartialDeep), useUserProfileContext: jest.fn(() => { return { routing: 'path', @@ -75,7 +72,14 @@ describe('', () => { }); it('displays verification errors', async () => { - mockFirstFactors = ['email_code']; + mockFirstFactors = { + attributes: { + email_address: { + used_for_first_factor: true, + first_factors: ['email_code'] + } + } + } mockUseCoreUser.mockImplementation(() => { return { primaryEmailAddressId: '1', diff --git a/packages/clerk-js/src/ui/userProfile/emailAdressess/utils.ts b/packages/clerk-js/src/ui/userProfile/emailAdressess/utils.ts index 285df08801a..ef950b3c3d9 100644 --- a/packages/clerk-js/src/ui/userProfile/emailAdressess/utils.ts +++ b/packages/clerk-js/src/ui/userProfile/emailAdressess/utils.ts @@ -3,8 +3,9 @@ import { EnvironmentResource } from '@clerk/types'; export function magicLinksEnabledForInstance( env: EnvironmentResource, ): boolean { - // TODO: email verification should have a supported strategies field - const { authConfig } = env; - const { emailAddressVerificationStrategies } = authConfig; - return emailAddressVerificationStrategies.includes('email_link'); + const { userSettings } = env; + const { email_address } = userSettings.attributes; + return ( + email_address.enabled && email_address.verifications.includes('email_link') + ); } diff --git a/packages/clerk-js/src/ui/userProfile/security/ChangePassword.test.tsx b/packages/clerk-js/src/ui/userProfile/security/ChangePassword.test.tsx new file mode 100644 index 00000000000..fc55af4ba17 --- /dev/null +++ b/packages/clerk-js/src/ui/userProfile/security/ChangePassword.test.tsx @@ -0,0 +1,62 @@ +import { render, screen } from '@clerk/shared/testUtils'; +import { EnvironmentResource, UserResource } from '@clerk/types'; +import * as React from 'react'; +import { PartialDeep } from 'type-fest'; +import { useEnvironment } from 'ui/contexts'; +import { ChangePassword } from 'ui/userProfile/security/ChangePassword'; + + +jest.mock('ui/hooks', () => ({ + useNavigate: () => ({ navigate: jest.fn() }), +})); + +jest.mock('ui/router/RouteContext'); + +jest.mock('ui/contexts', () => { + return { + useCoreUser: (): Partial => ({ + passwordEnabled: true + }), + useEnvironment: jest.fn(), + }; +}); + +describe('', () => { + afterEach(() => { + jest.clearAllMocks(); + }); + + it('renders the ChangePassword page with showing remove password cta', async () => { + ( + useEnvironment as jest.Mock> + ).mockImplementation(() => ({ + userSettings: { + attributes: { + password: { + enabled: true + } + } + } + })); + + render(); + expect(screen.getByText('Remove password')).toBeInTheDocument(); + }); + + it('renders the ChangePassword page without showing remove password cta', async () => { + ( + useEnvironment as jest.Mock> + ).mockImplementation(() => ({ + userSettings: { + attributes: { + password: { + enabled: false + } + } + } + })); + + render(); + expect(screen.getByText('Remove password')).toBeInTheDocument(); + }); +}); diff --git a/packages/clerk-js/src/ui/userProfile/security/ChangePassword.tsx b/packages/clerk-js/src/ui/userProfile/security/ChangePassword.tsx index c34d7bdd89f..0f46dad5053 100644 --- a/packages/clerk-js/src/ui/userProfile/security/ChangePassword.tsx +++ b/packages/clerk-js/src/ui/userProfile/security/ChangePassword.tsx @@ -11,7 +11,8 @@ import { PageHeading } from 'ui/userProfile/pageHeading'; export function ChangePassword(): JSX.Element { const user = useCoreUser(); - const { authConfig } = useEnvironment(); + const { userSettings } = useEnvironment(); + const { attributes } = userSettings; const { navigate } = useNavigate(); const password = useFieldState('password', ''); @@ -32,8 +33,7 @@ export function ChangePassword(): JSX.Element { } }; - const showRemovePassword = - user.passwordEnabled && authConfig.password !== 'required'; + const showRemovePassword = user.passwordEnabled && !attributes.password.required; const onClickRemovePassword = async () => { try { diff --git a/packages/clerk-js/src/ui/userProfile/security/Security.test.tsx b/packages/clerk-js/src/ui/userProfile/security/Security.test.tsx index d5ec43cd6cd..402ec8ac9ac 100644 --- a/packages/clerk-js/src/ui/userProfile/security/Security.test.tsx +++ b/packages/clerk-js/src/ui/userProfile/security/Security.test.tsx @@ -55,16 +55,24 @@ describe('', () => { useEnvironment as jest.Mock>, true, ).mockImplementation( - () => - ({ - authConfig: { - secondFactors: ['phone_code'], - password: 'on', + () => ( + { + userSettings: { + attributes: { + phone_number: { + used_for_second_factor: true, + second_factors: ['phone_code'] + }, + password: { + enabled: true + } + } }, displayConfig: { branded: true, }, - } as PartialDeep), + } as PartialDeep + ) ); const tree = renderJSON(); expect(tree).toMatchSnapshot(); diff --git a/packages/clerk-js/src/ui/userProfile/security/Security.tsx b/packages/clerk-js/src/ui/userProfile/security/Security.tsx index c62419f131f..4b96bb4edb8 100644 --- a/packages/clerk-js/src/ui/userProfile/security/Security.tsx +++ b/packages/clerk-js/src/ui/userProfile/security/Security.tsx @@ -8,16 +8,16 @@ import { PageHeading } from 'ui/userProfile/pageHeading'; import { ActiveDevicesCard } from './DevicesAndActivity/ActiveDevicesCard'; export function Security(): JSX.Element { - const { authConfig } = useEnvironment(); + const { userSettings } = useEnvironment(); + const { attributes } = userSettings; const { navigate } = useNavigate(); const user = useCoreUser(); - const showPasswordRow = - authConfig.password === 'on' || authConfig.password === 'required'; + const showPasswordRow = attributes.password.enabled; const showSecondFactorRow = - authConfig.secondFactors.length > 0 && - authConfig.secondFactors.includes('phone_code'); + attributes.phone_number.used_for_second_factor && + attributes.phone_number.second_factors.includes('phone_code'); const buildPasswordRow = () => ( - authConfig.secondFactors.length > 0 && - authConfig.secondFactors.includes('phone_code'); + phone_number.used_for_second_factor && + phone_number.second_factors.includes('phone_code'); return ( { // https://reactnative.dev/docs/0.61/network#known-issues-with-fetch-and-cookie-based-authentication diff --git a/packages/nextjs/CHANGELOG.md b/packages/nextjs/CHANGELOG.md index db1d2162f20..b3f9fe53558 100644 --- a/packages/nextjs/CHANGELOG.md +++ b/packages/nextjs/CHANGELOG.md @@ -41,6 +41,55 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline + +### [2.11.10](https://github.com/clerkinc/javascript/compare/@clerk/nextjs@2.11.9...@clerk/nextjs@2.11.10) (2022-03-04) + +**Note:** Version bump only for package @clerk/nextjs + + + + + +### [2.11.9](https://github.com/clerkinc/javascript/compare/@clerk/nextjs@2.11.8...@clerk/nextjs@2.11.9) (2022-03-04) + +**Note:** Version bump only for package @clerk/nextjs + + + + + +### [2.11.8](https://github.com/clerkinc/javascript/compare/@clerk/nextjs@2.11.7...@clerk/nextjs@2.11.8) (2022-03-04) + +**Note:** Version bump only for package @clerk/nextjs + + + + + +### [2.11.7](https://github.com/clerkinc/javascript/compare/@clerk/nextjs@2.11.6...@clerk/nextjs@2.11.7) (2022-03-03) + +**Note:** Version bump only for package @clerk/nextjs + + + + + +### [2.11.6](https://github.com/clerkinc/javascript/compare/@clerk/nextjs@2.11.5...@clerk/nextjs@2.11.6) (2022-03-02) + +**Note:** Version bump only for package @clerk/nextjs + + + + + +### [2.11.5](https://github.com/clerkinc/javascript/compare/@clerk/nextjs@2.11.4...@clerk/nextjs@2.11.5) (2022-03-01) + +**Note:** Version bump only for package @clerk/nextjs + + + + + ### [2.11.4](https://github.com/clerkinc/javascript/compare/@clerk/nextjs@2.11.4-staging.0...@clerk/nextjs@2.11.4) (2022-02-24) **Note:** Version bump only for package @clerk/nextjs diff --git a/packages/nextjs/package.json b/packages/nextjs/package.json index d650fa96d24..c10cdc04a1b 100644 --- a/packages/nextjs/package.json +++ b/packages/nextjs/package.json @@ -33,7 +33,7 @@ }, "dependencies": { "@clerk/clerk-react": "^3.0.0-alpha.9", - "@clerk/clerk-sdk-node": "^2.9.0", + "@clerk/clerk-sdk-node": "^2.9.6", "@clerk/types": "^2.0.0-alpha.8", "tslib": "^2.3.1" }, diff --git a/packages/react/CHANGELOG.md b/packages/react/CHANGELOG.md index 6bbe2f175ac..c6f88ba44f1 100644 --- a/packages/react/CHANGELOG.md +++ b/packages/react/CHANGELOG.md @@ -30,6 +30,50 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline +### [2.12.1](https://github.com/clerkinc/javascript/compare/@clerk/clerk-react@2.12.0...@clerk/clerk-react@2.12.1) (2022-03-04) + + +### Bug Fixes + +* **clerk-react,clerk-js,types:** Crate of API feedback fixes ([721ce72](https://github.com/clerkinc/javascript/commit/721ce7228c37b012891b2bec8caf290239164d05)) + + + +## [2.12.0](https://github.com/clerkinc/javascript/compare/@clerk/clerk-react@2.11.7...@clerk/clerk-react@2.12.0) (2022-03-04) + + +### Features + +* **clerk-js,clerk-react:** GetOrganization/s hook methods, fetching mechanism alignment ([fc11087](https://github.com/clerkinc/javascript/commit/fc110874f9a3e056cd43c773c267409dd9b318d6)) +* **clerk-js:** Add useOrganization hook ([480c422](https://github.com/clerkinc/javascript/commit/480c422774472fc712afdfe6ded2677b458d3ef0)) +* **clerk-react,clerk-js:** Add useOrganization hook using __unstable attribute ([1635132](https://github.com/clerkinc/javascript/commit/16351321a99945d167cbf6e6ca0efdbbbf7efe5a)) + + + +### [2.11.7](https://github.com/clerkinc/javascript/compare/@clerk/clerk-react@2.11.6...@clerk/clerk-react@2.11.7) (2022-03-03) + +**Note:** Version bump only for package @clerk/clerk-react + + + + + +### [2.11.6](https://github.com/clerkinc/javascript/compare/@clerk/clerk-react@2.11.5...@clerk/clerk-react@2.11.6) (2022-03-02) + +**Note:** Version bump only for package @clerk/clerk-react + + + + + +### [2.11.5](https://github.com/clerkinc/javascript/compare/@clerk/clerk-react@2.11.4...@clerk/clerk-react@2.11.5) (2022-03-01) + +**Note:** Version bump only for package @clerk/clerk-react + + + + + ### [2.11.4](https://github.com/clerkinc/javascript/compare/@clerk/clerk-react@2.11.4-staging.0...@clerk/clerk-react@2.11.4) (2022-02-24) **Note:** Version bump only for package @clerk/clerk-react diff --git a/packages/react/src/hooks/index.ts b/packages/react/src/hooks/index.ts index 93ad87d2847..bb78f501683 100644 --- a/packages/react/src/hooks/index.ts +++ b/packages/react/src/hooks/index.ts @@ -2,3 +2,5 @@ export * from './useUser'; export * from './useAuth'; export * from './useSession'; export * from './useClerk'; +export * from './useOrganizations'; +export * from './useMagicLink'; diff --git a/packages/react/src/useMagicLink.ts b/packages/react/src/hooks/useMagicLink.ts similarity index 100% rename from packages/react/src/useMagicLink.ts rename to packages/react/src/hooks/useMagicLink.ts diff --git a/packages/react/src/hooks/useOrganizations.ts b/packages/react/src/hooks/useOrganizations.ts new file mode 100644 index 00000000000..9ba0e469ca4 --- /dev/null +++ b/packages/react/src/hooks/useOrganizations.ts @@ -0,0 +1,24 @@ +import { CreateOrganizationParams, OrganizationResource } from '@clerk/types'; +import { useContext } from 'react'; + +import { assertWrappedByClerkProvider } from '../contexts/assertHelpers'; +import { StructureContext } from '../contexts/StructureContext'; +import { useClerk } from './useClerk'; + +type UseOrganizations = { + createOrganization: (params: CreateOrganizationParams) => Promise; + getOrganizations: () => Promise; + getOrganization: (organizationId: string) => Promise; +}; + +export function useOrganizations(): UseOrganizations { + const structureCtx = useContext(StructureContext); + assertWrappedByClerkProvider(structureCtx); + const clerk = useClerk(); + + return { + createOrganization: clerk.createOrganization, + getOrganizations: clerk.getOrganizations, + getOrganization: clerk.getOrganization, + }; +} diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index ce3f913d31b..181fa89c3c9 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -3,7 +3,7 @@ export * from './components'; export * from './hooks'; export type { ClerkProp } from './types'; export { isMagicLinkError, MagicLinkErrorCode } from './errors'; -export { useMagicLink } from './useMagicLink'; +export { useMagicLink } from './hooks/useMagicLink'; declare global { // eslint-disable-next-line @typescript-eslint/naming-convention diff --git a/packages/react/src/isomorphicClerk.ts b/packages/react/src/isomorphicClerk.ts index d4bd0d72e67..f65c4c9c524 100644 --- a/packages/react/src/isomorphicClerk.ts +++ b/packages/react/src/isomorphicClerk.ts @@ -2,8 +2,12 @@ import type { ActiveSessionResource, AuthenticateWithMetamaskParams, ClientResource, + CreateOrganizationInvitationParams, + CreateOrganizationParams, HandleMagicLinkVerificationParams, HandleOAuthCallbackParams, + OrganizationInvitationResource, + OrganizationResource, InitialState, RedirectOptions, Resources, @@ -425,6 +429,37 @@ export default class IsomorphicClerk { } }; + createOrganization = async ( + params: CreateOrganizationParams, + ): Promise => { + const callback = () => this.clerkjs?.createOrganization(params); + if (this.clerkjs && this._loaded) { + return callback() as Promise; + } else { + this.premountMethodCalls.set('createOrganization', callback); + } + }; + + getOrganizations = async (): Promise => { + const callback = () => this.clerkjs?.getOrganizations(); + if (this.clerkjs && this._loaded) { + return callback() as Promise; + } else { + this.premountMethodCalls.set('getOrganizations', callback); + } + }; + + getOrganization = async ( + organizationId: string, + ): Promise => { + const callback = () => this.clerkjs?.getOrganization(organizationId); + if (this.clerkjs && this._loaded) { + return callback() as Promise; + } else { + this.premountMethodCalls.set('getOrganization', callback); + } + }; + signOut = async (signOutCallback?: SignOutCallback): Promise => { const callback = () => this.clerkjs?.signOut(signOutCallback); if (this.clerkjs && this._loaded) { diff --git a/packages/sdk-node/CHANGELOG.md b/packages/sdk-node/CHANGELOG.md index 7231eafb627..9d61d228a1a 100644 --- a/packages/sdk-node/CHANGELOG.md +++ b/packages/sdk-node/CHANGELOG.md @@ -3,6 +3,22 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +### [2.9.6](https://github.com/clerkinc/javascript/compare/@clerk/clerk-sdk-node@2.9.5...@clerk/clerk-sdk-node@2.9.6) (2022-03-04) + +**Note:** Version bump only for package @clerk/clerk-sdk-node + + + + + +### [2.9.5](https://github.com/clerkinc/javascript/compare/@clerk/clerk-sdk-node@2.9.4...@clerk/clerk-sdk-node@2.9.5) (2022-03-04) + +**Note:** Version bump only for package @clerk/clerk-sdk-node + + + + + ### [2.9.4](https://github.com/clerkinc/javascript/compare/@clerk/clerk-sdk-node@2.9.4-staging.0...@clerk/clerk-sdk-node@2.9.4) (2022-02-24) **Note:** Version bump only for package @clerk/clerk-sdk-node diff --git a/packages/sdk-node/package.json b/packages/sdk-node/package.json index 5311ededa54..19dd7a6f7c1 100644 --- a/packages/sdk-node/package.json +++ b/packages/sdk-node/package.json @@ -1,5 +1,5 @@ { - "version": "2.9.4", + "version": "2.9.7-staging.0", "license": "MIT", "main": "dist/index.js", "module": "esm/index.js", @@ -51,7 +51,7 @@ "typescript": "4.5.5" }, "dependencies": { - "@clerk/backend-core": "^0.4.4", + "@clerk/backend-core": "^0.5.2-staging.0", "@peculiar/webcrypto": "^1.2.3", "camelcase-keys": "^6.2.2", "cookies": "^0.8.0", diff --git a/packages/sdk-node/src/info.ts b/packages/sdk-node/src/info.ts index d240d725c78..77975de9054 100644 --- a/packages/sdk-node/src/info.ts +++ b/packages/sdk-node/src/info.ts @@ -1,4 +1,4 @@ /** DO NOT EDIT: This file is automatically generated by ../scripts/info.js */ -export const LIB_VERSION="2.9.4"; +export const LIB_VERSION="2.9.7-staging.0"; export const LIB_NAME="@clerk/clerk-sdk-node"; diff --git a/packages/shared/CHANGELOG.md b/packages/shared/CHANGELOG.md index 721d92ab1f8..1f087b2ccfc 100644 --- a/packages/shared/CHANGELOG.md +++ b/packages/shared/CHANGELOG.md @@ -21,6 +21,49 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline + + +### [0.0.10](https://github.com/clerkinc/clerk_docker/compare/@clerk/shared@0.0.9...@clerk/shared@0.0.10) (2022-03-04) + +**Note:** Version bump only for package @clerk/shared + + + + + +### [0.0.9](https://github.com/clerkinc/clerk_docker/compare/@clerk/shared@0.0.8...@clerk/shared@0.0.9) (2022-03-04) + +**Note:** Version bump only for package @clerk/shared + + + + + +### [0.0.8](https://github.com/clerkinc/clerk_docker/compare/@clerk/shared@0.0.7...@clerk/shared@0.0.8) (2022-03-03) + +**Note:** Version bump only for package @clerk/shared + + + + + +### [0.0.7](https://github.com/clerkinc/clerk_docker/compare/@clerk/shared@0.0.6...@clerk/shared@0.0.7) (2022-03-02) + +**Note:** Version bump only for package @clerk/shared + + + + + +### [0.0.6](https://github.com/clerkinc/clerk_docker/compare/@clerk/shared@0.0.5...@clerk/shared@0.0.6) (2022-03-01) + + +### Bug Fixes + +* **shared:** Phone input should start blank ([43f0b06](https://github.com/clerkinc/clerk_docker/commit/43f0b0603608866f6b9e0a37a284c0ea72c0004b)) + + + ### [0.0.5](https://github.com/clerkinc/clerk_docker/compare/@clerk/shared@0.0.5-staging.0...@clerk/shared@0.0.5) (2022-02-24) **Note:** Version bump only for package @clerk/shared diff --git a/packages/shared/package.json b/packages/shared/package.json index 53ecd129500..db92e702d68 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -26,7 +26,7 @@ "@babel/core": "^7.13.14", "@babel/preset-env": "^7.13.12", "@babel/preset-react": "^7.13.13", - "@clerk/types": "^1.25.4", + "@clerk/types": "^1.28.2-staging.0", "@popperjs/core": "^2.5.4", "@sentry/browser": "^6.3.0", "@svgr/webpack": "^6.2.1", diff --git a/packages/types/CHANGELOG.md b/packages/types/CHANGELOG.md index ba08dcbc4b5..5907bb0a036 100644 --- a/packages/types/CHANGELOG.md +++ b/packages/types/CHANGELOG.md @@ -31,6 +31,66 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline + +### [1.28.1](https://github.com/clerkinc/javascript/compare/@clerk/types@1.28.0...@clerk/types@1.28.1) (2022-03-04) + + +### Bug Fixes + +* **clerk-react,clerk-js,types:** Crate of API feedback fixes ([721ce72](https://github.com/clerkinc/javascript/commit/721ce7228c37b012891b2bec8caf290239164d05)) +* **types:** Add OrganizationMembership methods on types ([8bac04c](https://github.com/clerkinc/javascript/commit/8bac04c90ab79c6fb2e319f5c566f421e5984fa7)) +* **types:** Change type import from dot ([a1cdb79](https://github.com/clerkinc/javascript/commit/a1cdb79f9abde74b92911394b50e7d75107a9cfd)) + + + +## [1.28.0](https://github.com/clerkinc/javascript/compare/@clerk/types@1.27.1...@clerk/types@1.28.0) (2022-03-04) + + +### Features + +* **clerk-js,clerk-react:** GetOrganization/s hook methods, fetching mechanism alignment ([fc11087](https://github.com/clerkinc/javascript/commit/fc110874f9a3e056cd43c773c267409dd9b318d6)) +* **clerk-js:** Add more attributes on organization models ([af010ba](https://github.com/clerkinc/javascript/commit/af010bac4b6e0519eff42d210049c7b3a6bda203)) +* **clerk-js:** Add organization basic resources ([09f9012](https://github.com/clerkinc/javascript/commit/09f90126282f757cee6f97e7eae8747abc641bb0)) +* **clerk-js:** Basic organization data shape tests ([0ca9a31](https://github.com/clerkinc/javascript/commit/0ca9a3114b34bfaa338e6e90f1b0d57e02b7dd58)) +* **clerk-js:** Invitation flow draft ([d6faaab](https://github.com/clerkinc/javascript/commit/d6faaabb7efec09a699c7e83ba24fd4bad199d6b)) +* **clerk-js:** Sign up next draft and fixes ([e2eef78](https://github.com/clerkinc/javascript/commit/e2eef782d644f7fd1925fee67ee81d27473255fc)) +* **clerk-js:** SignUp with organization invitation flow draft ([2a9edbd](https://github.com/clerkinc/javascript/commit/2a9edbd52916f9bc037f266d1f96269cf54023cb)) +* **clerk-react,clerk-js:** Add useOrganization hook using __unstable attribute ([1635132](https://github.com/clerkinc/javascript/commit/16351321a99945d167cbf6e6ca0efdbbbf7efe5a)) + + +### Bug Fixes + +* **types:** Guarantee elements not in oauth sorting array will be sorted last ([f3c2869](https://github.com/clerkinc/javascript/commit/f3c2869bc244fc594522ef8f889055f82d31463f)) + + + +### [1.27.1](https://github.com/clerkinc/javascript/compare/@clerk/types@1.27.0...@clerk/types@1.27.1) (2022-03-03) + + +### Bug Fixes + +* **types:** Consolidate oauth provider types ([bce9ef5](https://github.com/clerkinc/javascript/commit/bce9ef5cbfe02e11fe71db3e34dbf4fd9be9c3ed)) + + + +## [1.27.0](https://github.com/clerkinc/javascript/compare/@clerk/types@1.26.0...@clerk/types@1.27.0) (2022-03-02) + + +### Features + +* **types,clerk-js:** Introduce Notion OAuth ([#72](https://github.com/clerkinc/javascript/issues/72)) ([9e556d0](https://github.com/clerkinc/javascript/commit/9e556d00fb41dedbbd05de59947d00c720bb3d95)) + + + +## [1.26.0](https://github.com/clerkinc/javascript/compare/@clerk/types@1.25.4...@clerk/types@1.26.0) (2022-03-01) + + +### Features + +* **types:** Add support for oauth_microsoft ([96c1cc6](https://github.com/clerkinc/javascript/commit/96c1cc6817b9bbc6917ea2773498299c1ff9b951)) + + + ### [1.25.4](https://github.com/clerkinc/javascript/compare/@clerk/types@1.25.4-staging.0...@clerk/types@1.25.4) (2022-02-24) **Note:** Version bump only for package @clerk/types diff --git a/packages/types/LICENSE b/packages/types/LICENSE new file mode 100644 index 00000000000..66914b6af7c --- /dev/null +++ b/packages/types/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Clerk, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/types/README.md b/packages/types/README.md index 5fed5ae7bf4..e36b00c6ba0 100644 --- a/packages/types/README.md +++ b/packages/types/README.md @@ -1,3 +1,94 @@ +

+ + Clerk logo + +
+

+ # @clerk/types -Typings for Clerk.dev libraries. +
+ +[![Chat on Discord](https://img.shields.io/discord/856971667393609759.svg?logo=discord)](https://discord.com/invite/b5rXHjAg7A) +[![Clerk documentation](https://img.shields.io/badge/documentation-clerk-green.svg)](https://docs.clerk.dev?utm_source=github&utm_medium=clerk_types) +[![Follow on Twitter](https://img.shields.io/twitter/follow/ClerkDev?style=social)](https://twitter.com/intent/follow?screen_name=ClerkDev) + +[Changelog](CHANGELOG.md) +· +[Report a Bug](https://github.com/clerkinc/javascript/issues/new?assignees=&labels=bug&template=bug_report.md&title=Bug%3A+) +· +[Request a Feature](https://github.com/clerkinc/javascript/issues/new?assignees=&labels=enhancement&template=feature_request.md&title=Feature%3A+) +· +[Ask a Question](https://github.com/clerkinc/javascript/issues/new?assignees=&labels=question&template=ask_a_question.md&title=Support%3A+) + +
+ +--- + +## Overview + +This package provides the TypeScript type declarations for Clerk libraries. + +## Getting Started + +It is worth noting that Clerk packages automatically include their type declarations when installed so adding this package manually is not typically necessary. + +### Installation + +```sh +npm install --save-dev @clerk/types +``` + +### Build + +```sh +npm run build +``` + +To build types in watch mode, run the following: + +```sh +npm run dev +``` + +## Usage + +Example implementation: + +```ts +import type { OAuthStrategy } from '@clerk/types'; + +export type OAuthProps = { + oAuthOptions: OAuthStrategy[]; + error?: string; + setError?: React.Dispatch>; +}; +``` + +_For further details and examples, please refer to our [Documentation](https://docs.clerk.dev?utm_source=github&utm_medium=clerk_types)._ + +## Support + +You can get in touch with us in any of the following ways: + +- Join our official community [Discord server](https://discord.com/invite/b5rXHjAg7A) +- Open a [GitHub support issue](https://github.com/clerkinc/javascript/issues/new?assignees=&labels=question&template=ask_a_question.md&title=Support%3A+) +- Contact options listed on [our Support page](https://clerk.dev/support?utm_source=github&utm_medium=clerk_types) + +## Contributing + +We're open to all community contributions! If you'd like to contribute in any way, please read [our contribution guidelines](docs/CONTRIBUTING.md). + +## Security + +`@clerk/types` follows good practices of security, but 100% security cannot be assured. + +`@clerk/types` is provided **"as is"** without any **warranty**. Use at your own risk. + +_For more information and to report security issues, please refer to our [security documentation](docs/SECURITY.md)._ + +## License + +This project is licensed under the **MIT license**. + +See [LICENSE](LICENSE) for more information. diff --git a/packages/types/docs/CODE_OF_CONDUCT.md b/packages/types/docs/CODE_OF_CONDUCT.md new file mode 100644 index 00000000000..ac0d295cf55 --- /dev/null +++ b/packages/types/docs/CODE_OF_CONDUCT.md @@ -0,0 +1,132 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall + community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of + any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, + without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +[community@clerk.dev](mailto:community@clerk.dev). +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at +[https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations diff --git a/packages/types/docs/CONTRIBUTING.md b/packages/types/docs/CONTRIBUTING.md new file mode 100644 index 00000000000..596289a82f1 --- /dev/null +++ b/packages/types/docs/CONTRIBUTING.md @@ -0,0 +1,120 @@ +# Contributing + +When contributing to this repository, please first discuss the change you wish to make via issue, email, or any other method with the owners of this repository before making a change. +Please note we have a [code of conduct](CODE_OF_CONDUCT.md), please follow it in all your interactions with the project. + +
+TABLE OF CONTENTS + +- [Development environment setup](#development-environment-setup) +- [Issues and feature requests](#issues-and-feature-requests) + - [How to submit a Pull Request](#how-to-submit-a-pull-request) +- [Publishing packages](#publishing-packages) + - [Publishing `@next` package versions](#publishing-next-package-versions) +- [License](#license) + +
+ +## Development environment setup + +The current monorepo setup is based on: + +- [Lerna](https://github.com/lerna/lerna) used mostly for task running and versioning. +- [npm workspaces](https://docs.npmjs.com/cli/v8/using-npm/workspaces) used for package linking. + +### A note on commit messages + +The processes required for Lerna to manage releases and changelogs is done through the [conventional-commits](https://www.conventionalcommits.org/en/v1.0.0/) specification. + +To set up your development environment, please follow these steps: + +1. Clone the repo + + ```sh + git clone https://github.com/clerkinc/javascript + ``` + +2. Change into the directory and install dependencies + + ```sh + cd javascript + npm install + ``` + +3. Build all the packages in the monorepo by running: + + ```sh + npm run build + ``` +## Issues and feature requests + +You've found a bug in the source code, a mistake in the documentation or maybe you'd like a new feature? You can help us by [submitting an issue on GitHub](https://github.com/clerkinc/javascript/issues). Before you create an issue, make sure to search the issue archive -- your issue may have already been addressed! + +Please try to create bug reports that are: + +- _Reproducible._ Include steps to reproduce the problem. +- _Specific._ Include as much detail as possible: which version, what environment, etc. +- _Unique._ Do not duplicate existing opened issues. +- _Scoped to a Single Bug._ One bug per report. + +**Even better: Submit a pull request with a fix or new feature!** + +### How to submit a Pull Request + +1. Search our repository for open or closed + [Pull Requests](https://github.com/clerkinc/javascript/pulls) + that relate to your submission. You don't want to duplicate effort. +2. Fork the project +3. Create your feature branch (`git checkout -b feat/amazing_feature`) +4. Commit your changes (`git commit -m 'feat: Add amazing_feature'`). Clerk uses [conventional commits](https://www.conventionalcommits.org), so please follow the specification in your commit messages. +5. Push to the branch (`git push origin feat/amazing_feature`) +6. [Open a Pull Request](https://github.com/clerkinc/javascript/compare?expand=1) + +## Publishing packages + +_Version updates and publishing is managed using Lerna._ + +### TL;DR +1. `npm run bump` +2. `npm run release` + +### Commands explanation + +After all the features have been merged and we want to create a new release, we use `npm run bump`. + +This script will use `lerna version` to check which packages need to be updated and in what way based on the updates since the previous release. + +The command will guide you through the version changes that are detected and will: +- Bump the package versions. +- Run the `version` hook updating the version info files. +- Create new tags and a "release" commit. +- Push the commit and tags to the origin. + +After that is done, and all seems valid, you can run `npm run release` which will go through the publish process of the packages included in the release commit. + +For more info you can check the [lerna version](https://github.com/lerna/lerna/tree/main/commands/version) and [lerna publish](https://github.com/lerna/lerna/tree/main/commands/publish) documentation. + + +## Publishing `@next` package versions + +_`@next` version updates and publishing is managed using Lerna._ + +Install the `@next` version using `npm install @clerk/{package_name}@next`. + +### TL;DR +1. `npm run bump:next` +2. `npm run release:next` + +### Graduate the next version +To graduate\* the version pointed by the `@next` tag: +1. `npm run graduate:next` +2. `npm run release` + +### Process explanation +The `bump:next` command will create an `alpha` version update on the packages changed. Next if you want to release this version on npm to be installed, you would run the `npm run release:next` which would publish the version under the `@next` tag. + +\* By 'graduate' we mean publishing the `@next` tagged versions, which in actual versions result in `x.y.z-alpha.a.b.c`, to the stable one `x.y.z`. + +## License + +By contributing to Clerk, you agree that your contributions will be licensed under its MIT License. diff --git a/packages/types/docs/SECURITY.md b/packages/types/docs/SECURITY.md new file mode 100644 index 00000000000..eb1a76f8257 --- /dev/null +++ b/packages/types/docs/SECURITY.md @@ -0,0 +1,19 @@ +# Security Policy + +We take the security of our systems seriously, and we value the security community. The disclosure of security vulnerabilities helps us ensure the security and privacy of our users. + +## Reporting a Vulnerability + +**Please do not report security vulnerabilities through public GitHub issues.** + +If you believe you’ve found a security vulnerability in one of our products or platforms, please send it to us by emailing [security@clerk.dev](mailto:security@clerk.dev). Please include the following details with your report: + +1. Description of the location and potential impact of the vulnerability; and + +2. A detailed description of the steps required to reproduce the vulnerability (POC scripts, screenshots, and compressed screen captures are all helpful to us). + +We will evaluate the vulnerability and, if necessary, release a fix or mitigating steps to address it. We will contact you to let you know the outcome, and will credit you in the report. + +Please **do not disclose the vulnerability publicly** until a fix is released. + +Once we have either a) published a fix, or b) declined to address the vulnerability for whatever reason, you are free to publicly disclose it. diff --git a/packages/types/src/authConfig.ts b/packages/types/src/authConfig.ts index fcacde472b6..f3e857d2fdf 100644 --- a/packages/types/src/authConfig.ts +++ b/packages/types/src/authConfig.ts @@ -1,60 +1,8 @@ -import { EmailAddressVerificationStrategy } from './emailAddress'; import { ClerkResource } from './resource'; -import { IdentificationStrategy, SignInStrategyName } from './signIn'; - -/** - * Authentication configuration attributes set. - */ export interface AuthConfigResource extends ClerkResource { - id: string; - - firstName: ToggleTypeWithRequire; - - lastName: ToggleTypeWithRequire; - - emailAddress: ToggleType; - - phoneNumber: ToggleType; - - username: ToggleType; - - password: string; - - /** - * Types of identification strategies selected. - */ - identificationStrategies: IdentificationStrategy[]; - - /** - * Combinations of strategies. - */ - identificationRequirements: IdentificationStrategy[][]; - - passwordConditions: any; - - /** - * Type of first factor authentication used. - */ - firstFactors: SignInStrategyName[]; - - /** - * Type of second factor authentication used. - */ - secondFactors: SignInStrategyName[]; - - /** - * All the verification strategies that can be used in - * this instance to verify an email address. - */ - emailAddressVerificationStrategies: EmailAddressVerificationStrategy[]; - /** * Enabled single session configuration at the instance level. */ singleSessionMode: boolean; } - -export type ToggleType = 'on' | 'off'; - -export type ToggleTypeWithRequire = ToggleType | 'required'; diff --git a/packages/types/src/clerk.ts b/packages/types/src/clerk.ts index 3927e74731a..addb7d3c910 100644 --- a/packages/types/src/clerk.ts +++ b/packages/types/src/clerk.ts @@ -1,6 +1,8 @@ import { EnvironmentResource } from '.'; import { ClientResource } from './client'; import { DisplayThemeJSON } from './json'; +import { OrganizationResource } from './organization'; +import { MembershipRole } from './organizationMembership'; import { ActiveSessionResource } from './session'; import { UserResource } from './user'; import { DeepPartial, DeepSnakeToCamel } from './utils'; @@ -217,6 +219,25 @@ export interface Clerk { params?: AuthenticateWithMetamaskParams, ) => Promise; + /** + * Creates an organization, adding the current user as admin. + */ + createOrganization: ( + params: CreateOrganizationParams, + ) => Promise; + + /** + * Retrieves all the organizations the current user is a member of. + */ + getOrganizations: () => Promise; + + /** + * Retrieves a single organization by id. + */ + getOrganization: ( + organizationId: string, + ) => Promise; + /** * Handles a 401 response from Frontend API by refreshing the client and session object accordingly */ @@ -412,6 +433,16 @@ export interface HandleMagicLinkVerificationParams { onVerifiedOnOtherDevice?: () => void; } +export type CreateOrganizationInvitationParams = { + emailAddress: string; + role: MembershipRole; + redirectUrl?: string; +}; + +export interface CreateOrganizationParams { + name: string; +} + export interface AuthenticateWithMetamaskParams { redirectUrl?: string; } diff --git a/packages/types/src/environment.ts b/packages/types/src/environment.ts index 798c7ebf763..d8447afa594 100644 --- a/packages/types/src/environment.ts +++ b/packages/types/src/environment.ts @@ -1,8 +1,10 @@ import { AuthConfigResource } from './authConfig'; import { DisplayConfigResource } from './displayConfig'; import { ClerkResource } from './resource'; +import { UserSettingsResource } from './userSettings'; export interface EnvironmentResource extends ClerkResource { + userSettings: UserSettingsResource; authConfig: AuthConfigResource; displayConfig: DisplayConfigResource; isSingleSession: () => boolean; diff --git a/packages/types/src/externalAccount.ts b/packages/types/src/externalAccount.ts index 7cc10def859..39559ec86cd 100644 --- a/packages/types/src/externalAccount.ts +++ b/packages/types/src/externalAccount.ts @@ -10,7 +10,9 @@ export interface ExternalAccountResource { firstName: string; lastName: string; avatarUrl: string; - + username?: string; + publicMetadata: Record; + label?: string; providerSlug: () => OAuthProvider; providerTitle: () => string; } diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 6d81f2f4a9c..afb9e59bb46 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -11,6 +11,9 @@ export * from './image'; export * from './json'; export * from './jwt'; export * from './oauth'; +export * from './organization'; +export * from './organizationInvitation'; +export * from './organizationMembership'; export * from './phoneNumber'; export * from './resource'; export * from './session'; @@ -19,6 +22,7 @@ export * from './signUp'; export * from './theme'; export * from './token'; export * from './user'; +export * from './userSettings'; export * from './utils'; export * from './verification'; export * from './ssr'; diff --git a/packages/types/src/json.ts b/packages/types/src/json.ts index 3f7689d5e3d..4ed7e4addbb 100644 --- a/packages/types/src/json.ts +++ b/packages/types/src/json.ts @@ -2,29 +2,14 @@ * Currently representing API DTOs in their JSON form. */ -import { ToggleType, ToggleTypeWithRequire } from './authConfig'; -import { EmailAddressVerificationStrategy } from './emailAddress'; -import { OAuthStrategy } from './oauth'; -import { OAuthProvider } from './oauth'; +import { OAuthProvider, OAuthStrategy } from './oauth'; +import { OrganizationInvitationStatus } from './organizationInvitation'; +import { MembershipRole } from './organizationMembership'; import { SessionStatus } from './session'; -import { - IdentificationStrategy, - PreferredSignInStrategy, - SignInFactor, - SignInIdentifier, - SignInStatus, - SignInStrategyName, - UserData, -} from './signIn'; +import { PreferredSignInStrategy, SignInFactor, SignInIdentifier, SignInStatus, UserData } from './signIn'; import { SignUpField, SignUpIdentificationField, SignUpStatus } from './signUp'; -import { - BoxShadow, - Color, - EmUnit, - FontFamily, - FontWeight, - HexColor, -} from './theme'; +import { BoxShadow, Color, EmUnit, FontFamily, FontWeight, HexColor } from './theme'; +import { UserSettingsJSON } from './userSettings'; import { VerificationStatus } from './verification'; export interface ClerkResourceJSON { @@ -87,6 +72,7 @@ export interface ImageJSON { export interface EnvironmentJSON extends ClerkResourceJSON { auth_config: AuthConfigJSON; display_config: DisplayConfigJSON; + user_settings: UserSettingsJSON; } export interface ClientJSON extends ClerkResourceJSON { @@ -192,6 +178,9 @@ export interface ExternalAccountJSON extends ClerkResourceJSON { first_name: string; last_name: string; avatar_url: string; + username: string; + public_metadata: Record; + label: string; } export interface UserJSON extends ClerkResourceJSON { @@ -222,29 +211,15 @@ export interface PublicUserDataJSON extends ClerkResourceJSON { last_name: string | null; profile_image_url: string; identifier: string; + user_id?: string; } export interface SessionWithActivitiesJSON extends Omit { user: null; latest_activity: SessionActivityJSON; - // activities: SessionActivityJSON[]; } -export interface AuthConfigJSON { - object: 'auth_config'; - id: string; - first_name: ToggleTypeWithRequire; - last_name: ToggleTypeWithRequire; - email_address: ToggleType; - phone_number: ToggleType; - username: ToggleType; - password: ToggleTypeWithRequire; - identification_strategies: IdentificationStrategy[]; - identification_requirements: IdentificationStrategy[][]; - password_conditions: any; - first_factors: SignInStrategyName[]; - second_factors: SignInStrategyName[]; - email_address_verification_strategies: EmailAddressVerificationStrategy[]; +export interface AuthConfigJSON extends ClerkResourceJSON { single_session_mode: boolean; } @@ -296,3 +271,35 @@ export interface SessionActivityJSON extends ClerkResourceJSON { country?: string; is_mobile?: boolean; } + +export interface OrganizationJSON extends ClerkResourceJSON { + object: 'organization'; + id: string; + name: string; + role: MembershipRole; + instance_id: string; + created_by: string; + created_at: number; + updated_at: number; +} + +export interface OrganizationMembershipJSON extends ClerkResourceJSON { + object: 'organization_membership'; + id: string; + organization_id: string; + public_user_data: PublicUserDataJSON; + role: MembershipRole; + created_at: number; + updated_at: number; +} + +export interface OrganizationInvitationJSON extends ClerkResourceJSON { + object: 'organization_invitation'; + id: string; + organization_id: string; + email_address: string; + status: OrganizationInvitationStatus; + role: MembershipRole; + created_at: number; + updated_at: number; +} diff --git a/packages/types/src/jwt.ts b/packages/types/src/jwt.ts index f26bb2926c0..db1ab00ff8c 100644 --- a/packages/types/src/jwt.ts +++ b/packages/types/src/jwt.ts @@ -1,3 +1,5 @@ +import { MembershipRole } from './organizationMembership'; + export interface JWTClaims { __raw: string; sub: string; @@ -8,9 +10,11 @@ export interface JWTClaims { iat?: number; nbf?: number; name?: string; + orgs?: OrganizationsJWTClaim; [key: string]: unknown; } +export type OrganizationsJWTClaim = Record; // eslint-disable-next-line @typescript-eslint/naming-convention export interface JWT { encoded: { header: string; payload: string; signature: string }; diff --git a/packages/types/src/oauth.ts b/packages/types/src/oauth.ts index 8987f0dcd8b..3c29ddd3b87 100644 --- a/packages/types/src/oauth.ts +++ b/packages/types/src/oauth.ts @@ -11,10 +11,138 @@ export type OAuthProvider = | 'linkedin' | 'dropbox' | 'bitbucket' - | 'microsoft'; + | 'microsoft' + | 'notion'; export type OAuthStrategy = `oauth_${OAuthProvider}`; +export interface OAuthProviderData { + provider: OAuthProvider; + strategy: OAuthStrategy, + name: string; + docsUrl: string; +} + +export const OAUTH_PROVIDERS: OAuthProviderData[] = [ + { + provider: 'google', + strategy: 'oauth_google', + name: 'Google', + docsUrl: 'https://docs.clerk.dev/reference/social-login-reference/social-login-google', + }, + { + provider: 'discord', + strategy: 'oauth_discord', + name: 'Discord', + docsUrl: 'https://docs.clerk.dev/reference/social-login-reference/discord', + }, + { + provider: 'facebook', + strategy: 'oauth_facebook', + name: 'Facebook', + docsUrl: 'https://docs.clerk.dev/reference/social-login-reference/social-login-facebook', + }, + { + provider: 'twitch', + strategy: 'oauth_twitch', + name: 'Twitch', + docsUrl: 'https://docs.clerk.dev/reference/social-login-reference/twitch', + }, + { + provider: 'twitter', + strategy: 'oauth_twitter', + name: 'Twitter', + docsUrl: 'https://docs.clerk.dev/reference/social-login-reference/twitter', + }, + { + provider: 'microsoft', + strategy: 'oauth_microsoft', + name: 'Microsoft', + docsUrl: 'https://docs.clerk.dev/reference/social-login-reference/microsoft', + }, + { + provider: 'tiktok', + strategy: 'oauth_tiktok', + name: 'TikTok', + docsUrl: 'https://docs.clerk.dev/reference/social-login-reference/tiktok', + }, + { + provider: 'linkedin', + strategy: 'oauth_linkedin', + name: 'LinkedIn', + docsUrl: 'https://docs.clerk.dev/reference/social-login-reference/linkedin', + }, + { + provider: 'github', + strategy: 'oauth_github', + name: 'GitHub', + docsUrl: 'https://docs.clerk.dev/reference/social-login-reference/github', + }, + { + provider: 'gitlab', + strategy: 'oauth_gitlab', + name: 'GitLab', + docsUrl: 'https://docs.clerk.dev/reference/social-login-reference/gitlab', + }, + { + provider: 'dropbox', + strategy: 'oauth_dropbox', + name: 'Dropbox', + docsUrl: 'https://docs.clerk.dev/reference/social-login-reference/dropbox', + }, + { + provider: 'bitbucket', + strategy: 'oauth_bitbucket', + name: 'Bitbucket', + docsUrl: 'https://docs.clerk.dev/reference/social-login-reference/bitbucket', + }, + { + provider: 'hubspot', + strategy: 'oauth_hubspot', + name: 'HubSpot', + docsUrl: 'https://docs.clerk.dev/reference/social-login-reference/hubspot', + }, + { + provider: 'notion', + strategy: 'oauth_notion', + name: 'Notion', + docsUrl: 'https://docs.clerk.dev/reference/social-login-reference/notion', + }, +]; + +interface getOAuthProviderDataProps { + provider?: OAuthProvider, + strategy?: OAuthStrategy, +} + +export function getOAuthProviderData({ provider, strategy }: getOAuthProviderDataProps): OAuthProviderData | undefined | null { + if (provider) { + return OAUTH_PROVIDERS.find(oauth_provider => oauth_provider.provider == provider); + } + + return OAUTH_PROVIDERS.find(oauth_provider => oauth_provider.strategy == strategy); +} + +export function sortedOAuthProviders(sortingArray: OAuthStrategy[]) { + return OAUTH_PROVIDERS + .slice() + .sort( + (a, b) => { + let aPos = sortingArray.indexOf(a.strategy); + if (aPos == -1) { + aPos = Number.MAX_SAFE_INTEGER; + } + + let bPos = sortingArray.indexOf(b.strategy); + if (bPos == -1) { + bPos = Number.MAX_SAFE_INTEGER; + } + + return aPos - bPos; + } + ) +} + export type AuthenticateWithRedirectParams = { /** * One of the supported OAuth providers you can use to authenticate with, eg 'oauth_google'. diff --git a/packages/types/src/organization.ts b/packages/types/src/organization.ts new file mode 100644 index 00000000000..9d0d24e4a86 --- /dev/null +++ b/packages/types/src/organization.ts @@ -0,0 +1,40 @@ +import { OrganizationInvitationResource } from './organizationInvitation'; +import { OrganizationMembershipResource } from './organizationMembership'; +import { MembershipRole } from './organizationMembership'; + +export interface OrganizationResource { + id: string; + name: string; + role: MembershipRole; + instanceId: string; + createdBy: string; + createdAt: Date; + updatedAt: Date; + getMemberships: ( + params?: GetMembershipsParams, + ) => Promise; + getPendingInvitations: () => Promise; + inviteMember: ( + params: InviteMemberParams, + ) => Promise; + updateMember: ( + params: UpdateMembershipParams, + ) => Promise; + removeMember: (userId: string) => Promise; +} + +export interface GetMembershipsParams { + limit?: number; + offset?: number; +} + +export interface InviteMemberParams { + emailAddress: string; + role: MembershipRole; + redirectUrl?: string; +} + +export interface UpdateMembershipParams { + userId: string; + role: MembershipRole; +} diff --git a/packages/types/src/organizationInvitation.ts b/packages/types/src/organizationInvitation.ts new file mode 100644 index 00000000000..f3fbdd568ed --- /dev/null +++ b/packages/types/src/organizationInvitation.ts @@ -0,0 +1,14 @@ +import { MembershipRole } from './organizationMembership'; + +export interface OrganizationInvitationResource { + id: string; + emailAddress: string; + organizationId: string; + role: MembershipRole; + status: OrganizationInvitationStatus; + createdAt: Date; + updatedAt: Date; + revoke: () => Promise; +} + +export type OrganizationInvitationStatus = 'pending' | 'accepted' | 'revoked'; diff --git a/packages/types/src/organizationMembership.ts b/packages/types/src/organizationMembership.ts new file mode 100644 index 00000000000..8d55667b665 --- /dev/null +++ b/packages/types/src/organizationMembership.ts @@ -0,0 +1,20 @@ +import { PublicUserData } from './session'; + +export interface OrganizationMembershipResource { + id: string; + organizationId: string; + publicUserData: PublicUserData; + role: MembershipRole; + createdAt: Date; + updatedAt: Date; + destroy: () => Promise; + update: ( + updateParams: UpdateOrganizationMembershipParams, + ) => Promise; +} + +export type MembershipRole = 'admin' | 'basic_member'; + +export type UpdateOrganizationMembershipParams = { + role: MembershipRole; +}; diff --git a/packages/types/src/session.ts b/packages/types/src/session.ts index 83d4517cf31..d68bec2cf40 100644 --- a/packages/types/src/session.ts +++ b/packages/types/src/session.ts @@ -58,4 +58,5 @@ export interface PublicUserData { lastName: string | null; profileImageUrl: string; identifier: string; + userId?: string; } diff --git a/packages/types/src/signIn.ts b/packages/types/src/signIn.ts index 3c4c48c5f23..d9af04ca6f6 100644 --- a/packages/types/src/signIn.ts +++ b/packages/types/src/signIn.ts @@ -70,7 +70,8 @@ export type SignInStrategyName = | 'phone_code' | Web3Strategy | EmailAddressVerificationStrategy - | OAuthStrategy; + | OAuthStrategy + | 'ticket'; export type SignInStatus = | 'needs_identifier' @@ -177,6 +178,12 @@ type SignInAttributes = { */ redirect_url?: string; + /** + * Organization invitation ticket. + * The logic is handled by the backend after the token and strategy is sent. + */ + ticket?: string; + /** * Optional if the strategy is one of the OAuth providers. * If the OAuth verification results in a completed Sign in, this is the URL that diff --git a/packages/types/src/signUp.ts b/packages/types/src/signUp.ts index 534344ddee8..f5aac00eeb9 100644 --- a/packages/types/src/signUp.ts +++ b/packages/types/src/signUp.ts @@ -106,16 +106,19 @@ export type SignUpAttribute = | 'birthday' | 'gender'; +type OrganizationSignUpStrategy = 'ticket'; + export type SignUpAttributes = { external_account_strategy: string; external_account_redirect_url: string; external_account_action_complete_redirect_url: string; - strategy: OAuthStrategy; + strategy: OAuthStrategy | OrganizationSignUpStrategy; redirect_url: string; action_complete_redirect_url: string; transfer: boolean; unsafe_metadata: Record; invitation_token: string; + ticket: string; } & Record< SignUpAttribute | Exclude, string diff --git a/packages/types/src/userSettings.ts b/packages/types/src/userSettings.ts new file mode 100644 index 00000000000..6343ce291e1 --- /dev/null +++ b/packages/types/src/userSettings.ts @@ -0,0 +1,74 @@ +import { ClerkResourceJSON } from './json'; +import { OAuthStrategy } from './oauth'; +import { ClerkResource } from './resource'; +import { Web3Strategy } from './web3'; + +type Attribute = + | 'email_address' + | 'phone_number' + | 'username' + | 'first_name' + | 'last_name' + | 'password' + | 'web3_wallet'; + +type VerificationStrategy = 'email_link' | 'email_code' | 'phone_code'; + +type OauthProviderData = { + enabled: boolean; + required: boolean; + authenticatable: boolean; + strategy: OAuthStrategy; +}; + +export type AttributeData = { + enabled: boolean; + required: boolean; + name: Attribute; + verifications: VerificationStrategy[]; + used_for_first_factor: boolean; + first_factors: VerificationStrategy[]; + used_for_second_factor: boolean; + second_factors: VerificationStrategy[]; + verify_at_sign_up: boolean; +}; + +export type SignInData = { + second_factor: { + required: boolean; + enabled: boolean; + }; +}; + +export type SignUpData = { + allowlist_only: boolean; +}; + +export type OauthProviders = { + [provider in OAuthStrategy]: OauthProviderData; +}; + +export type Attributes = { + [attribute in Attribute]: AttributeData; +}; + +export interface UserSettingsJSON extends ClerkResourceJSON { + id: never; + object: never; + attributes: Attributes; + social: OauthProviders; + sign_in: SignInData; + sign_up: SignUpData; +} + +export interface UserSettingsResource extends ClerkResource { + id: undefined; + social: OauthProviders; + attributes: Attributes; + signIn: SignInData; + signUp: SignUpData; + socialProviderStrategies: OAuthStrategy[]; + web3FirstFactors: Web3Strategy[]; + enabledFirstFactorIdentifiers: Attribute[]; + instanceIsPasswordBased: boolean; +} From 4feb7eb8be87b2a03c6f5cdd1499982ce7020961 Mon Sep 17 00:00:00 2001 From: Peter Perlepes Date: Wed, 9 Mar 2022 12:42:43 +0200 Subject: [PATCH 47/58] fix(clerk-sdk-node): Correct initialization params override on custom instance --- packages/sdk-node/src/Clerk.ts | 6 +++--- .../sdk-node/src/__tests__/instance.test.ts | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/packages/sdk-node/src/Clerk.ts b/packages/sdk-node/src/Clerk.ts index 1cdf4999ab9..f31b96f8592 100644 --- a/packages/sdk-node/src/Clerk.ts +++ b/packages/sdk-node/src/Clerk.ts @@ -113,9 +113,9 @@ export default class Clerk extends ClerkBackendAPI { }; super({ - apiKey: defaultApiKey, - apiVersion: defaultApiVersion, - serverApiUrl: defaultServerApiUrl, + apiKey, + apiVersion, + serverApiUrl, libName: LIB_NAME, libVersion: LIB_VERSION, packageRepo, diff --git a/packages/sdk-node/src/__tests__/instance.test.ts b/packages/sdk-node/src/__tests__/instance.test.ts index d065059428b..af64a7f1883 100644 --- a/packages/sdk-node/src/__tests__/instance.test.ts +++ b/packages/sdk-node/src/__tests__/instance.test.ts @@ -22,4 +22,23 @@ describe('Custom Clerk instance initialization', () => { const Clerk = require('../instance').default; expect(() => new Clerk()).not.toThrow(Error); }); + + test('custom keys overrides process env and default params', () => { + jest.resetModules(); + process.env.CLERK_API_KEY = TEST_API_KEY; + const Clerk = require('../instance').default; + expect(() => { + const customKey = 'custom_key'; + const customAPIVersion = 'v0'; + const customAPIUrl = 'https://customdomain.com'; + const instance = new Clerk({ + apiKey: customKey, + serverApiUrl: customAPIUrl, + apiVersion: customAPIVersion, + }); + expect(instance._restClient.apiKey).toBe(customKey); + expect(instance._restClient.serverApiUrl).toBe(customAPIUrl); + expect(instance._restClient.apiVersion).toBe(customAPIVersion); + }).not.toThrow(Error); + }); }); From ccfc83a56ad274878a97bb727da4cd8ec87c9c31 Mon Sep 17 00:00:00 2001 From: Peter Perlepes Date: Wed, 9 Mar 2022 13:09:39 +0200 Subject: [PATCH 48/58] chore(release): Publish - @clerk/nextjs@2.11.13 - @clerk/clerk-sdk-node@2.9.8 --- package-lock.json | 146 ++++++++++++++------------------- packages/nextjs/CHANGELOG.md | 8 ++ packages/nextjs/package.json | 4 +- packages/sdk-node/CHANGELOG.md | 9 ++ packages/sdk-node/package.json | 2 +- packages/sdk-node/src/info.ts | 2 +- 6 files changed, 83 insertions(+), 88 deletions(-) diff --git a/package-lock.json b/package-lock.json index 16e99f882d6..deaa08db73e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6761,7 +6761,7 @@ }, "node_modules/anymatch": { "version": "3.1.2", - "devOptional": true, + "dev": true, "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", @@ -7279,7 +7279,7 @@ }, "node_modules/binary-extensions": { "version": "2.2.0", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -7374,7 +7374,7 @@ }, "node_modules/braces": { "version": "3.0.2", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "fill-range": "^7.0.1" @@ -7727,7 +7727,7 @@ }, "node_modules/chokidar": { "version": "3.5.3", - "devOptional": true, + "dev": true, "funding": [ { "type": "individual", @@ -7753,7 +7753,7 @@ }, "node_modules/chokidar/node_modules/glob-parent": { "version": "5.1.2", - "devOptional": true, + "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.1" @@ -10032,7 +10032,7 @@ }, "node_modules/fill-range": { "version": "7.0.1", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" @@ -10415,6 +10415,7 @@ }, "node_modules/fsevents": { "version": "2.3.2", + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11236,7 +11237,7 @@ }, "node_modules/immutable": { "version": "4.0.0", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/import-fresh": { @@ -11530,7 +11531,7 @@ }, "node_modules/is-binary-path": { "version": "2.1.0", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" @@ -11622,7 +11623,7 @@ }, "node_modules/is-extglob": { "version": "2.1.1", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -11646,7 +11647,7 @@ }, "node_modules/is-glob": { "version": "4.0.3", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" @@ -11673,7 +11674,7 @@ }, "node_modules/is-number": { "version": "7.0.0", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=0.12.0" @@ -15352,7 +15353,7 @@ }, "node_modules/normalize-path": { "version": "3.0.0", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -16218,7 +16219,7 @@ }, "node_modules/picomatch": { "version": "2.3.1", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -17445,7 +17446,7 @@ }, "node_modules/readdirp": { "version": "3.6.0", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "picomatch": "^2.2.1" @@ -17835,7 +17836,7 @@ }, "node_modules/sass": { "version": "1.49.7", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "chokidar": ">=3.0.0 <4.0.0", @@ -19014,7 +19015,7 @@ }, "node_modules/to-regex-range": { "version": "5.0.1", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "is-number": "^7.0.0" @@ -20797,11 +20798,11 @@ }, "packages/nextjs": { "name": "@clerk/nextjs", - "version": "2.11.12", + "version": "2.11.13", "license": "MIT", "dependencies": { "@clerk/clerk-react": "^2.12.3", - "@clerk/clerk-sdk-node": "^2.9.7", + "@clerk/clerk-sdk-node": "^2.9.8", "@clerk/types": "^1.28.3", "tslib": "^2.3.1" }, @@ -20870,7 +20871,7 @@ }, "packages/sdk-node": { "name": "@clerk/clerk-sdk-node", - "version": "2.9.7", + "version": "2.9.8", "license": "MIT", "dependencies": { "@clerk/backend-core": "^0.5.2", @@ -22495,8 +22496,7 @@ }, "eslint-config-prettier": { "version": "8.3.0", - "dev": true, - "requires": {} + "dev": true }, "eslint-scope": { "version": "7.1.0", @@ -22563,7 +22563,7 @@ "version": "file:packages/nextjs", "requires": { "@clerk/clerk-react": "^2.12.3", - "@clerk/clerk-sdk-node": "^2.9.7", + "@clerk/clerk-sdk-node": "^2.9.8", "@clerk/types": "^1.28.3", "@types/jest": "^27.4.0", "@types/node": "^16.11.9", @@ -23000,8 +23000,7 @@ }, "@icons/material": { "version": "0.2.4", - "dev": true, - "requires": {} + "dev": true }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", @@ -24748,8 +24747,7 @@ }, "@octokit/plugin-request-log": { "version": "1.0.4", - "dev": true, - "requires": {} + "dev": true }, "@octokit/plugin-rest-endpoint-methods": { "version": "5.13.0", @@ -24949,43 +24947,35 @@ }, "@svgr/babel-plugin-add-jsx-attribute": { "version": "6.0.0", - "dev": true, - "requires": {} + "dev": true }, "@svgr/babel-plugin-remove-jsx-attribute": { "version": "6.0.0", - "dev": true, - "requires": {} + "dev": true }, "@svgr/babel-plugin-remove-jsx-empty-expression": { "version": "6.0.0", - "dev": true, - "requires": {} + "dev": true }, "@svgr/babel-plugin-replace-jsx-attribute-value": { "version": "6.0.0", - "dev": true, - "requires": {} + "dev": true }, "@svgr/babel-plugin-svg-dynamic-title": { "version": "6.0.0", - "dev": true, - "requires": {} + "dev": true }, "@svgr/babel-plugin-svg-em-dimensions": { "version": "6.0.0", - "dev": true, - "requires": {} + "dev": true }, "@svgr/babel-plugin-transform-react-native-svg": { "version": "6.0.0", - "dev": true, - "requires": {} + "dev": true }, "@svgr/babel-plugin-transform-svg-component": { "version": "6.2.0", - "dev": true, - "requires": {} + "dev": true }, "@svgr/babel-preset": { "version": "6.2.0", @@ -25890,8 +25880,7 @@ }, "@webpack-cli/configtest": { "version": "1.1.1", - "dev": true, - "requires": {} + "dev": true }, "@webpack-cli/info": { "version": "1.4.1", @@ -25902,8 +25891,7 @@ }, "@webpack-cli/serve": { "version": "1.6.1", - "dev": true, - "requires": {} + "dev": true }, "@xtuc/ieee754": { "version": "1.2.0", @@ -25949,13 +25937,11 @@ }, "acorn-import-assertions": { "version": "1.8.0", - "dev": true, - "requires": {} + "dev": true }, "acorn-jsx": { "version": "5.3.2", - "dev": true, - "requires": {} + "dev": true }, "acorn-walk": { "version": "7.2.0", @@ -26030,8 +26016,7 @@ }, "ajv-keywords": { "version": "3.5.2", - "dev": true, - "requires": {} + "dev": true }, "ansi-colors": { "version": "4.1.1", @@ -26067,7 +26052,7 @@ }, "anymatch": { "version": "3.1.2", - "devOptional": true, + "dev": true, "requires": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -26417,7 +26402,7 @@ }, "binary-extensions": { "version": "2.2.0", - "devOptional": true + "dev": true }, "body-parser": { "version": "1.19.1", @@ -26486,7 +26471,7 @@ }, "braces": { "version": "3.0.2", - "devOptional": true, + "dev": true, "requires": { "fill-range": "^7.0.1" } @@ -26709,7 +26694,7 @@ }, "chokidar": { "version": "3.5.3", - "devOptional": true, + "dev": true, "requires": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -26723,7 +26708,7 @@ "dependencies": { "glob-parent": { "version": "5.1.2", - "devOptional": true, + "dev": true, "requires": { "is-glob": "^4.0.1" } @@ -27908,13 +27893,11 @@ }, "eslint-config-prettier": { "version": "8.1.0", - "dev": true, - "requires": {} + "dev": true }, "eslint-plugin-simple-import-sort": { "version": "7.0.0", - "dev": true, - "requires": {} + "dev": true }, "eslint-scope": { "version": "5.1.1", @@ -28196,7 +28179,7 @@ }, "fill-range": { "version": "7.0.1", - "devOptional": true, + "dev": true, "requires": { "to-regex-range": "^5.0.1" } @@ -28434,6 +28417,7 @@ }, "fsevents": { "version": "2.3.2", + "dev": true, "optional": true }, "function-bind": { @@ -28955,8 +28939,7 @@ }, "icss-utils": { "version": "5.1.0", - "dev": true, - "requires": {} + "dev": true }, "identity-obj-proxy": { "version": "3.0.0", @@ -28978,7 +28961,7 @@ }, "immutable": { "version": "4.0.0", - "devOptional": true + "dev": true }, "import-fresh": { "version": "3.3.0", @@ -29166,7 +29149,7 @@ }, "is-binary-path": { "version": "2.1.0", - "devOptional": true, + "dev": true, "requires": { "binary-extensions": "^2.0.0" } @@ -29216,7 +29199,7 @@ }, "is-extglob": { "version": "2.1.1", - "devOptional": true + "dev": true }, "is-fullwidth-code-point": { "version": "3.0.0", @@ -29228,7 +29211,7 @@ }, "is-glob": { "version": "4.0.3", - "devOptional": true, + "dev": true, "requires": { "is-extglob": "^2.1.1" } @@ -29243,7 +29226,7 @@ }, "is-number": { "version": "7.0.0", - "devOptional": true + "dev": true }, "is-number-object": { "version": "1.0.6", @@ -30090,8 +30073,7 @@ }, "jest-pnp-resolver": { "version": "1.2.2", - "dev": true, - "requires": {} + "dev": true }, "jest-regex-util": { "version": "27.4.0", @@ -31635,7 +31617,7 @@ }, "normalize-path": { "version": "3.0.0", - "devOptional": true + "dev": true }, "normalize-range": { "version": "0.1.2", @@ -32191,7 +32173,7 @@ }, "picomatch": { "version": "2.3.1", - "devOptional": true + "dev": true }, "pidtree": { "version": "0.3.1", @@ -32341,8 +32323,7 @@ }, "postcss-modules-extract-imports": { "version": "3.0.0", - "dev": true, - "requires": {} + "dev": true }, "postcss-modules-local-by-default": { "version": "4.0.0", @@ -32981,7 +32962,7 @@ }, "readdirp": { "version": "3.6.0", - "devOptional": true, + "dev": true, "requires": { "picomatch": "^2.2.1" } @@ -33231,7 +33212,7 @@ }, "sass": { "version": "1.49.7", - "devOptional": true, + "dev": true, "requires": { "chokidar": ">=3.0.0 <4.0.0", "immutable": "^4.0.0", @@ -33785,8 +33766,7 @@ } }, "styled-jsx": { - "version": "5.0.0", - "requires": {} + "version": "5.0.0" }, "supports-color": { "version": "5.5.0", @@ -33982,7 +33962,7 @@ }, "to-regex-range": { "version": "5.0.1", - "devOptional": true, + "dev": true, "requires": { "is-number": "^7.0.0" } @@ -34681,8 +34661,7 @@ }, "ws": { "version": "8.4.2", - "dev": true, - "requires": {} + "dev": true } } }, @@ -34897,8 +34876,7 @@ }, "ws": { "version": "7.5.6", - "dev": true, - "requires": {} + "dev": true }, "xml-name-validator": { "version": "3.0.0", diff --git a/packages/nextjs/CHANGELOG.md b/packages/nextjs/CHANGELOG.md index fdd4d78e248..0dd89892d69 100644 --- a/packages/nextjs/CHANGELOG.md +++ b/packages/nextjs/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +### [2.11.13](https://github.com/clerkinc/javascript/compare/@clerk/nextjs@2.11.12...@clerk/nextjs@2.11.13) (2022-03-09) + +**Note:** Version bump only for package @clerk/nextjs + + + + + ### [2.11.12](https://github.com/clerkinc/javascript/compare/@clerk/nextjs@2.11.12-staging.0...@clerk/nextjs@2.11.12) (2022-03-09) **Note:** Version bump only for package @clerk/nextjs diff --git a/packages/nextjs/package.json b/packages/nextjs/package.json index 437a6715fca..bc93f0c247b 100644 --- a/packages/nextjs/package.json +++ b/packages/nextjs/package.json @@ -1,6 +1,6 @@ { "name": "@clerk/nextjs", - "version": "2.11.12", + "version": "2.11.13", "license": "MIT", "description": "Clerk.dev SDK for NextJS", "keywords": [ @@ -31,7 +31,7 @@ }, "dependencies": { "@clerk/clerk-react": "^2.12.3", - "@clerk/clerk-sdk-node": "^2.9.7", + "@clerk/clerk-sdk-node": "^2.9.8", "@clerk/types": "^1.28.3", "tslib": "^2.3.1" }, diff --git a/packages/sdk-node/CHANGELOG.md b/packages/sdk-node/CHANGELOG.md index bdca610fc21..711aa636350 100644 --- a/packages/sdk-node/CHANGELOG.md +++ b/packages/sdk-node/CHANGELOG.md @@ -3,6 +3,15 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +### [2.9.8](https://github.com/clerkinc/javascript/compare/@clerk/clerk-sdk-node@2.9.7...@clerk/clerk-sdk-node@2.9.8) (2022-03-09) + + +### Bug Fixes + +* **clerk-sdk-node:** Correct initialization params override on custom instance ([4feb7eb](https://github.com/clerkinc/javascript/commit/4feb7eb8be87b2a03c6f5cdd1499982ce7020961)) + + + ### [2.9.7](https://github.com/clerkinc/javascript/compare/@clerk/clerk-sdk-node@2.9.7-staging.0...@clerk/clerk-sdk-node@2.9.7) (2022-03-09) **Note:** Version bump only for package @clerk/clerk-sdk-node diff --git a/packages/sdk-node/package.json b/packages/sdk-node/package.json index 7bb5befdef8..519a503f738 100644 --- a/packages/sdk-node/package.json +++ b/packages/sdk-node/package.json @@ -1,5 +1,5 @@ { - "version": "2.9.7", + "version": "2.9.8", "license": "MIT", "main": "dist/index.js", "module": "esm/index.js", diff --git a/packages/sdk-node/src/info.ts b/packages/sdk-node/src/info.ts index 7e19121c349..aff8bff1ab2 100644 --- a/packages/sdk-node/src/info.ts +++ b/packages/sdk-node/src/info.ts @@ -1,4 +1,4 @@ /** DO NOT EDIT: This file is automatically generated by ../scripts/info.js */ -export const LIB_VERSION="2.9.7"; +export const LIB_VERSION="2.9.8"; export const LIB_NAME="@clerk/clerk-sdk-node"; From 6b4df78f481eb75767617f908915374c06db006b Mon Sep 17 00:00:00 2001 From: Nikos Douvlis Date: Wed, 9 Mar 2022 16:33:26 +0200 Subject: [PATCH 49/58] chore(repo): Update Typescript to 4.6.2 (#94) --- package-lock.json | 149 +++++++++++++++------------- package.json | 3 +- packages/backend-core/package.json | 4 +- packages/backend-core/tsconfig.json | 2 +- packages/clerk-js/package.json | 2 +- packages/edge/package.json | 2 +- packages/edge/tsconfig.json | 2 +- packages/expo/package.json | 2 +- packages/nextjs/package.json | 2 +- packages/react/package.json | 2 +- packages/remix/package.json | 2 +- packages/sdk-node/package.json | 2 +- packages/sdk-node/tsconfig.json | 3 +- packages/shared/package.json | 3 +- packages/types/package.json | 2 +- tsconfig.json | 2 +- 16 files changed, 101 insertions(+), 83 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9ffc4483be0..ec448e87489 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@commitlint/config-conventional": "^16.0.0", "@commitlint/config-lerna-scopes": "^16.0.0", "@types/node": "14.14.33", + "@types/web": "^0.0.55", "@typescript-eslint/eslint-plugin": "^5.5.0", "@typescript-eslint/parser": "^5.5.0", "conventional-changelog-conventionalcommits": "^4.6.3", @@ -24,7 +25,7 @@ "prettier": "^2.3.1", "rimraf": "^3.0.2", "turbo": "^1.1.5", - "typescript": "4.5.5" + "typescript": "^4.6.2" }, "engines": { "node": ">=16.8.0", @@ -5398,15 +5399,15 @@ } }, "node_modules/@peculiar/webcrypto": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.2.3.tgz", - "integrity": "sha512-q7wDfZy3k/tpnsYB23/MyyDkjn6IdHh8w+xwoVMS5cu6CjVoFzngXDZEOOuSE4zus2yO6ciQhhHxd4XkLpwVnQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.3.2.tgz", + "integrity": "sha512-oUgNj+8oT7uROEMEpZZ3U+kZjyxj1KXuvA8P5kiMUveTya9eyS8KTqu/dzdEtYC3u7dvjknVz+0sUfkWOBHfQg==", "dependencies": { "@peculiar/asn1-schema": "^2.0.44", "@peculiar/json-schema": "^1.1.12", - "pvtsutils": "^1.2.1", + "pvtsutils": "^1.2.2", "tslib": "^2.3.1", - "webcrypto-core": "^1.4.0" + "webcrypto-core": "^1.7.1" }, "engines": { "node": ">=10.12.0" @@ -6753,6 +6754,11 @@ "node": ">=0.10.0" } }, + "node_modules/@types/web": { + "version": "0.0.55", + "resolved": "https://registry.npmjs.org/@types/web/-/web-0.0.55.tgz", + "integrity": "sha512-YMH9aZrSJIMRMioCUwrgauI3iS/w2wRFN45Xxm0FE9Tt3hqaqkvOzjDFGsNjyKZzz7GJC0ilb+0tv59ytSUbrQ==" + }, "node_modules/@types/webpack": { "version": "4.41.32", "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.32.tgz", @@ -16664,9 +16670,9 @@ "dev": true }, "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { "brace-expansion": "^1.1.7" @@ -18978,17 +18984,17 @@ } }, "node_modules/pvtsutils": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.2.1.tgz", - "integrity": "sha512-Q867jEr30lBR2YSFFLZ0/XsEvpweqH6Kj096wmlRAFXrdRGPCNq2iz9B5Tk085EZ+OBZyYAVA5UhPkjSHGrUzQ==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.2.2.tgz", + "integrity": "sha512-OALo5ZEdqiI127i64+CXwkCOyFHUA+tCQgaUO/MvRDFXWPr53f2sx28ECNztUEzuyu5xvuuD1EB/szg9mwJoGA==", "dependencies": { "tslib": "^2.3.1" } }, "node_modules/pvutils": { - "version": "1.0.17", - "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.0.17.tgz", - "integrity": "sha512-wLHYUQxWaXVQvKnwIDWFVKDJku9XDCvyhhxoq8dc5MFdIlRenyPI9eSfEtcvgHgD7FlvCyGAlWgOzRnZD99GZQ==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", + "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==", "engines": { "node": ">=6.0.0" } @@ -21862,9 +21868,9 @@ } }, "node_modules/typescript": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", - "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz", + "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -22224,14 +22230,15 @@ } }, "node_modules/webcrypto-core": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.4.0.tgz", - "integrity": "sha512-HY3Zo0GcRIQUUDnlZ/shGjN+4f7LVMkdJZoGPog+oHhJsJdMz6iM8Za5xZ0t6qg7Fx/JXXz+oBv2J2p982hGTQ==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.7.1.tgz", + "integrity": "sha512-Gw2zLzYSJ7Imp5lLDu3CcWB5oTTACMDEE2PjoLfttGgIhd7BfackBdVgEzd9ZM/i65gpNq0+IelL0JZ48QwzNg==", "dependencies": { "@peculiar/asn1-schema": "^2.0.44", "@peculiar/json-schema": "^1.1.12", - "asn1js": "^2.1.1", - "pvtsutils": "^1.2.0", + "@types/web": "^0.0.55", + "asn1js": "^2.2.0", + "pvtsutils": "^1.2.2", "tslib": "^2.3.1" } }, @@ -23077,7 +23084,7 @@ "tslib": "^2.3.1" }, "devDependencies": { - "@peculiar/webcrypto": "^1.2.3", + "@peculiar/webcrypto": "^1.3.2", "@types/jest": "^27.4.0", "@types/node": "^16.11.12", "@types/node-fetch": "^2", @@ -23086,7 +23093,7 @@ "nock": "^13.2.1", "node-fetch": "^2.6.0", "ts-jest": "^27.1.3", - "typescript": "4.5.5" + "typescript": "^4.6.2" } }, "packages/backend-core/node_modules/@types/node": { @@ -23161,7 +23168,7 @@ "style-loader": "^2.0.0", "ts-jest": "^27.1.3", "type-fest": "^0.20.2", - "typescript": "4.5.5", + "typescript": "^4.6.2", "webpack": "^5.64.1", "webpack-cli": "^4.9.1", "webpack-dev-server": "^4.5.0", @@ -23215,7 +23222,7 @@ "@types/node": "^16.11.12", "jest": "^27.4.7", "ts-jest": "^27.1.3", - "typescript": "4.5.5" + "typescript": "^4.6.2" }, "engines": { "node": ">=12" @@ -23247,7 +23254,7 @@ "react-dom": "17.0.2", "ts-jest": "^27.1.3", "tslib": "^2.3.1", - "typescript": "4.5.5" + "typescript": "^4.6.2" }, "engines": { "node": ">=14" @@ -23291,7 +23298,7 @@ "react": "17.0.2", "react-dom": "17.0.2", "ts-jest": "^27.1.3", - "typescript": "4.5.5" + "typescript": "^4.6.2" }, "engines": { "node": ">=14" @@ -23406,7 +23413,7 @@ "react": "17.0.2", "react-dom": "17.0.2", "ts-jest": "^27.1.3", - "typescript": "4.5.5" + "typescript": "^4.6.2" }, "engines": { "node": ">=14" @@ -23442,7 +23449,7 @@ "react": "17.0.2", "react-dom": "17.0.2", "ts-jest": "^27.1.3", - "typescript": "4.5.5" + "typescript": "^4.6.2" }, "engines": { "node": ">=16" @@ -23572,7 +23579,7 @@ "npm-run-all": "^4.1.5", "prettier": "^2.5.0", "ts-jest": "^27.1.3", - "typescript": "4.5.5" + "typescript": "^4.6.2" }, "engines": { "node": ">=12" @@ -23858,7 +23865,8 @@ "react-dom": "17.0.2", "react-popper": "^2.2.4", "react-test-renderer": "17.0.2", - "ts-jest": "^27.1.3" + "ts-jest": "^27.1.3", + "typescript": "^4.6.2" }, "peerDependencies": { "@popperjs/core": "^2.5.4", @@ -23896,7 +23904,7 @@ "jest": "^27.4.7", "ts-jest": "^27.1.3", "typedoc": "^0.22.11", - "typescript": "4.5.5" + "typescript": "^4.6.2" }, "engines": { "node": ">=14" @@ -25191,7 +25199,7 @@ "@clerk/backend-core": { "version": "file:packages/backend-core", "requires": { - "@peculiar/webcrypto": "^1.2.3", + "@peculiar/webcrypto": "^1.3.2", "@types/jest": "^27.4.0", "@types/node": "^16.11.12", "@types/node-fetch": "^2", @@ -25204,7 +25212,7 @@ "snakecase-keys": "^5.1.2", "ts-jest": "^27.1.3", "tslib": "^2.3.1", - "typescript": "4.5.5" + "typescript": "^4.6.2" }, "dependencies": { "@types/node": { @@ -25231,7 +25239,7 @@ "react-dom": "17.0.2", "ts-jest": "^27.1.3", "tslib": "^2.3.1", - "typescript": "4.5.5" + "typescript": "^4.6.2" }, "dependencies": { "@clerk/types": { @@ -25310,7 +25318,7 @@ "style-loader": "^2.0.0", "ts-jest": "^27.1.3", "type-fest": "^0.20.2", - "typescript": "4.5.5", + "typescript": "^4.6.2", "webpack": "^5.64.1", "webpack-cli": "^4.9.1", "webpack-dev-server": "^4.5.0", @@ -25360,7 +25368,7 @@ "react-dom": "17.0.2", "ts-jest": "^27.1.3", "tslib": "^2.3.1", - "typescript": "4.5.5" + "typescript": "^4.6.2" }, "dependencies": { "@types/node": { @@ -25397,7 +25405,7 @@ "snakecase-keys": "^3.2.1", "ts-jest": "^27.1.3", "tslib": "^2.3.1", - "typescript": "4.5.5" + "typescript": "^4.6.2" }, "dependencies": { "@humanwhocodes/config-array": { @@ -25582,7 +25590,7 @@ "jest": "^27.4.7", "next": "^12.0.7", "ts-jest": "^27.1.3", - "typescript": "4.5.5" + "typescript": "^4.6.2" }, "dependencies": { "@types/node": { @@ -25609,7 +25617,7 @@ "react-dom": "17.0.2", "ts-jest": "^27.1.3", "tslib": "^2.3.1", - "typescript": "4.5.5" + "typescript": "^4.6.2" }, "dependencies": { "@clerk/backend-core": { @@ -25696,7 +25704,7 @@ "react-dom": "17.0.2", "ts-jest": "^27.1.3", "tslib": "^2.3.1", - "typescript": "4.5.5" + "typescript": "^4.6.2" }, "dependencies": { "@clerk/backend-core": { @@ -25809,7 +25817,8 @@ "react-dom": "17.0.2", "react-popper": "^2.2.4", "react-test-renderer": "17.0.2", - "ts-jest": "^27.1.3" + "ts-jest": "^27.1.3", + "typescript": "^4.6.2" }, "dependencies": { "@clerk/types": { @@ -25833,7 +25842,7 @@ "jest": "^27.4.7", "ts-jest": "^27.1.3", "typedoc": "^0.22.11", - "typescript": "4.5.5" + "typescript": "^4.6.2" } }, "@commitlint/cli": { @@ -28567,15 +28576,15 @@ } }, "@peculiar/webcrypto": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.2.3.tgz", - "integrity": "sha512-q7wDfZy3k/tpnsYB23/MyyDkjn6IdHh8w+xwoVMS5cu6CjVoFzngXDZEOOuSE4zus2yO6ciQhhHxd4XkLpwVnQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.3.2.tgz", + "integrity": "sha512-oUgNj+8oT7uROEMEpZZ3U+kZjyxj1KXuvA8P5kiMUveTya9eyS8KTqu/dzdEtYC3u7dvjknVz+0sUfkWOBHfQg==", "requires": { "@peculiar/asn1-schema": "^2.0.44", "@peculiar/json-schema": "^1.1.12", - "pvtsutils": "^1.2.1", + "pvtsutils": "^1.2.2", "tslib": "^2.3.1", - "webcrypto-core": "^1.4.0" + "webcrypto-core": "^1.7.1" } }, "@pmmmwh/react-refresh-webpack-plugin": { @@ -29647,6 +29656,11 @@ } } }, + "@types/web": { + "version": "0.0.55", + "resolved": "https://registry.npmjs.org/@types/web/-/web-0.0.55.tgz", + "integrity": "sha512-YMH9aZrSJIMRMioCUwrgauI3iS/w2wRFN45Xxm0FE9Tt3hqaqkvOzjDFGsNjyKZzz7GJC0ilb+0tv59ytSUbrQ==" + }, "@types/webpack": { "version": "4.41.32", "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.32.tgz", @@ -37134,9 +37148,9 @@ "dev": true }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -38868,17 +38882,17 @@ "dev": true }, "pvtsutils": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.2.1.tgz", - "integrity": "sha512-Q867jEr30lBR2YSFFLZ0/XsEvpweqH6Kj096wmlRAFXrdRGPCNq2iz9B5Tk085EZ+OBZyYAVA5UhPkjSHGrUzQ==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.2.2.tgz", + "integrity": "sha512-OALo5ZEdqiI127i64+CXwkCOyFHUA+tCQgaUO/MvRDFXWPr53f2sx28ECNztUEzuyu5xvuuD1EB/szg9mwJoGA==", "requires": { "tslib": "^2.3.1" } }, "pvutils": { - "version": "1.0.17", - "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.0.17.tgz", - "integrity": "sha512-wLHYUQxWaXVQvKnwIDWFVKDJku9XDCvyhhxoq8dc5MFdIlRenyPI9eSfEtcvgHgD7FlvCyGAlWgOzRnZD99GZQ==" + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", + "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==" }, "q": { "version": "1.5.1", @@ -41012,9 +41026,9 @@ } }, "typescript": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", - "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz", + "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==", "dev": true }, "uglify-js": { @@ -41304,14 +41318,15 @@ "dev": true }, "webcrypto-core": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.4.0.tgz", - "integrity": "sha512-HY3Zo0GcRIQUUDnlZ/shGjN+4f7LVMkdJZoGPog+oHhJsJdMz6iM8Za5xZ0t6qg7Fx/JXXz+oBv2J2p982hGTQ==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.7.1.tgz", + "integrity": "sha512-Gw2zLzYSJ7Imp5lLDu3CcWB5oTTACMDEE2PjoLfttGgIhd7BfackBdVgEzd9ZM/i65gpNq0+IelL0JZ48QwzNg==", "requires": { "@peculiar/asn1-schema": "^2.0.44", "@peculiar/json-schema": "^1.1.12", - "asn1js": "^2.1.1", - "pvtsutils": "^1.2.0", + "@types/web": "^0.0.55", + "asn1js": "^2.2.0", + "pvtsutils": "^1.2.2", "tslib": "^2.3.1" } }, diff --git a/package.json b/package.json index 263371d8a3d..b5b65e87d64 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "@commitlint/config-conventional": "^16.0.0", "@commitlint/config-lerna-scopes": "^16.0.0", "@types/node": "14.14.33", + "@types/web": "^0.0.55", "@typescript-eslint/eslint-plugin": "^5.5.0", "@typescript-eslint/parser": "^5.5.0", "conventional-changelog-conventionalcommits": "^4.6.3", @@ -29,7 +30,7 @@ "prettier": "^2.3.1", "rimraf": "^3.0.2", "turbo": "^1.1.5", - "typescript": "4.5.5" + "typescript": "^4.6.2" }, "scripts": { "dev": "lerna run dev --parallel --scope @clerk/types --scope @clerk/clerk-js --scope @clerk/clerk-react --scope @clerk/remix --scope @clerk/nextjs", diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json index 2db78bf7e53..9280012fe13 100644 --- a/packages/backend-core/package.json +++ b/packages/backend-core/package.json @@ -17,7 +17,7 @@ "tslib": "^2.3.1" }, "devDependencies": { - "@peculiar/webcrypto": "^1.2.3", + "@peculiar/webcrypto": "^1.3.2", "@types/jest": "^27.4.0", "@types/node": "^16.11.12", "@types/node-fetch": "^2", @@ -26,7 +26,7 @@ "nock": "^13.2.1", "node-fetch": "^2.6.0", "ts-jest": "^27.1.3", - "typescript": "4.5.5" + "typescript": "^4.6.2" }, "publishConfig": { "access": "public" diff --git a/packages/backend-core/tsconfig.json b/packages/backend-core/tsconfig.json index 5846254cca8..b6250342fd5 100644 --- a/packages/backend-core/tsconfig.json +++ b/packages/backend-core/tsconfig.json @@ -7,7 +7,7 @@ "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "importHelpers": true, - "lib": ["ES2020", "DOM"], + "lib": ["ES2020"], "moduleResolution": "node", "noUnusedLocals": true, "noUnusedParameters": true, diff --git a/packages/clerk-js/package.json b/packages/clerk-js/package.json index 0b592fb3594..1c91ddcf6c3 100644 --- a/packages/clerk-js/package.json +++ b/packages/clerk-js/package.json @@ -99,7 +99,7 @@ "style-loader": "^2.0.0", "ts-jest": "^27.1.3", "type-fest": "^0.20.2", - "typescript": "4.5.5", + "typescript": "^4.6.2", "webpack": "^5.64.1", "webpack-cli": "^4.9.1", "webpack-dev-server": "^4.5.0", diff --git a/packages/edge/package.json b/packages/edge/package.json index abf002b588e..209466845f6 100644 --- a/packages/edge/package.json +++ b/packages/edge/package.json @@ -51,7 +51,7 @@ "@types/node": "^16.11.12", "jest": "^27.4.7", "ts-jest": "^27.1.3", - "typescript": "4.5.5" + "typescript": "^4.6.2" }, "repository": { "type": "git", diff --git a/packages/edge/tsconfig.json b/packages/edge/tsconfig.json index f8dc655e086..2545d0f3e97 100644 --- a/packages/edge/tsconfig.json +++ b/packages/edge/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "lib": ["ES2020", "DOM"], + "lib": ["ES2020"], "strict": true, "declaration": true, "declarationMap": true, diff --git a/packages/expo/package.json b/packages/expo/package.json index 18b53ff57d9..39657efda6d 100644 --- a/packages/expo/package.json +++ b/packages/expo/package.json @@ -41,7 +41,7 @@ "react-dom": "17.0.2", "ts-jest": "^27.1.3", "tslib": "^2.3.1", - "typescript": "4.5.5" + "typescript": "^4.6.2" }, "peerDependencies": { "react": ">=16" diff --git a/packages/nextjs/package.json b/packages/nextjs/package.json index c10cdc04a1b..8cd5eec470a 100644 --- a/packages/nextjs/package.json +++ b/packages/nextjs/package.json @@ -47,7 +47,7 @@ "react": "17.0.2", "react-dom": "17.0.2", "ts-jest": "^27.1.3", - "typescript": "4.5.5" + "typescript": "^4.6.2" }, "peerDependencies": { "next": ">=10" diff --git a/packages/react/package.json b/packages/react/package.json index 509b2d44459..8b87fd6517f 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -48,7 +48,7 @@ "react": "17.0.2", "react-dom": "17.0.2", "ts-jest": "^27.1.3", - "typescript": "4.5.5" + "typescript": "^4.6.2" }, "peerDependencies": { "react": ">=16" diff --git a/packages/remix/package.json b/packages/remix/package.json index 97ddbacece1..5b38fc7e3eb 100644 --- a/packages/remix/package.json +++ b/packages/remix/package.json @@ -48,7 +48,7 @@ "react": "17.0.2", "react-dom": "17.0.2", "ts-jest": "^27.1.3", - "typescript": "4.5.5" + "typescript": "^4.6.2" }, "peerDependencies": { "@remix-run/react": "^1.2.1", diff --git a/packages/sdk-node/package.json b/packages/sdk-node/package.json index 19dd7a6f7c1..2df502865cc 100644 --- a/packages/sdk-node/package.json +++ b/packages/sdk-node/package.json @@ -48,7 +48,7 @@ "npm-run-all": "^4.1.5", "prettier": "^2.5.0", "ts-jest": "^27.1.3", - "typescript": "4.5.5" + "typescript": "^4.6.2" }, "dependencies": { "@clerk/backend-core": "^0.5.2-staging.0", diff --git a/packages/sdk-node/tsconfig.json b/packages/sdk-node/tsconfig.json index 3e08dfcd090..2d0df83c3f5 100644 --- a/packages/sdk-node/tsconfig.json +++ b/packages/sdk-node/tsconfig.json @@ -15,6 +15,7 @@ "forceConsistentCasingInFileNames": true, "target": "ES2019", "moduleResolution": "node", - "esModuleInterop": true + "esModuleInterop": true, + "lib": ["ES2020"] } } diff --git a/packages/shared/package.json b/packages/shared/package.json index db92e702d68..7ce6bc5f3ad 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -58,6 +58,7 @@ "react-dom": "17.0.2", "react-popper": "^2.2.4", "react-test-renderer": "17.0.2", - "ts-jest": "^27.1.3" + "ts-jest": "^27.1.3", + "typescript": "^4.6.2" } } diff --git a/packages/types/package.json b/packages/types/package.json index cd0ef7fa614..84982a811d5 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -32,7 +32,7 @@ "jest": "^27.4.7", "ts-jest": "^27.1.3", "typedoc": "^0.22.11", - "typescript": "4.5.5" + "typescript": "^4.6.2" }, "engines": { "node": ">=14" diff --git a/tsconfig.json b/tsconfig.json index 35b578301bd..d7f486cde6f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,7 +9,7 @@ "forceConsistentCasingInFileNames": true, "importHelpers": true, "inlineSources": true, - "lib": ["es6", "dom"], + "lib": ["es6"], "module": "commonjs", "moduleResolution": "node", "noEmitHelpers": true, From b2e5a0004a5043cbec4ec413017d56b23713ed4e Mon Sep 17 00:00:00 2001 From: Nikos Douvlis Date: Thu, 10 Mar 2022 02:17:19 +0200 Subject: [PATCH 50/58] Align useSignIn,useSignUp and useSessionList hooks (#91) * feat(clerk-react): Add isLoaded to `useSignIn` hook * feat(clerk-react): Add isLoaded to `useSignUp` hook * feat(clerk-react): Add isLoaded to `useSessionList` hook --- packages/react/src/contexts/ClientContext.tsx | 38 +------------------ packages/react/src/contexts/index.ts | 1 - packages/react/src/hooks/index.ts | 3 ++ packages/react/src/hooks/useSessionList.ts | 19 ++++++++++ packages/react/src/hooks/useSignIn.ts | 19 ++++++++++ packages/react/src/hooks/useSignUp.ts | 19 ++++++++++ 6 files changed, 62 insertions(+), 37 deletions(-) create mode 100644 packages/react/src/hooks/useSessionList.ts create mode 100644 packages/react/src/hooks/useSignIn.ts create mode 100644 packages/react/src/hooks/useSignUp.ts diff --git a/packages/react/src/contexts/ClientContext.tsx b/packages/react/src/contexts/ClientContext.tsx index e83df3f14cb..17f48f03d94 100644 --- a/packages/react/src/contexts/ClientContext.tsx +++ b/packages/react/src/contexts/ClientContext.tsx @@ -1,17 +1,7 @@ -import { - ClientResource, - SessionResource, - SignInResource, - SignUpResource, -} from '@clerk/types'; -import React, { useContext } from 'react'; +import { ClientResource } from '@clerk/types'; +import React from 'react'; import { makeContextAndHook } from '../utils/makeContextAndHook'; -import { - assertClerkLoadedGuarantee, - assertWrappedByClerkProvider, -} from './assertHelpers'; -import { StructureContext } from './StructureContext'; /** * @internal @@ -19,27 +9,3 @@ import { StructureContext } from './StructureContext'; export const [ClientContext, useClientContext] = makeContextAndHook< ClientResource | undefined | null >('ClientContext'); - -export function useSignIn(): SignInResource { - const structureCtx = useContext(StructureContext); - const client = useClientContext(); - assertWrappedByClerkProvider(structureCtx); - assertClerkLoadedGuarantee(structureCtx.guaranteedLoaded, 'useSignIn()'); - return (client as ClientResource).signIn; -} - -export function useSignUp(): SignUpResource { - const structureCtx = useContext(StructureContext); - const client = useClientContext(); - assertWrappedByClerkProvider(structureCtx); - assertClerkLoadedGuarantee(structureCtx.guaranteedLoaded, 'useSignUp()'); - return (client as ClientResource).signUp; -} - -export function useSessionList(): SessionResource[] { - const structureCtx = useContext(StructureContext); - const client = useClientContext(); - assertWrappedByClerkProvider(structureCtx); - assertClerkLoadedGuarantee(structureCtx.guaranteedLoaded, 'useSessionList()'); - return (client as ClientResource).sessions; -} diff --git a/packages/react/src/contexts/index.ts b/packages/react/src/contexts/index.ts index d29a5790768..1bd599a5223 100644 --- a/packages/react/src/contexts/index.ts +++ b/packages/react/src/contexts/index.ts @@ -1,2 +1 @@ export { ClerkProvider, ClerkProviderProps } from './ClerkProvider'; -export { useSignIn, useSessionList, useSignUp } from './ClientContext'; diff --git a/packages/react/src/hooks/index.ts b/packages/react/src/hooks/index.ts index bb78f501683..d6f6ddf4ea0 100644 --- a/packages/react/src/hooks/index.ts +++ b/packages/react/src/hooks/index.ts @@ -2,5 +2,8 @@ export * from './useUser'; export * from './useAuth'; export * from './useSession'; export * from './useClerk'; +export * from './useSignIn'; +export * from './useSignUp'; +export * from './useSessionList'; export * from './useOrganizations'; export * from './useMagicLink'; diff --git a/packages/react/src/hooks/useSessionList.ts b/packages/react/src/hooks/useSessionList.ts new file mode 100644 index 00000000000..63f38ae2ee6 --- /dev/null +++ b/packages/react/src/hooks/useSessionList.ts @@ -0,0 +1,19 @@ +import { SessionResource } from '@clerk/types'; + +import { useClientContext } from '../contexts/ClientContext'; + +type UseSessionListReturn = + | { isLoaded: false; sessions: undefined } + | { isLoaded: true; sessions: SessionResource[] }; + +type UseSessionList = () => UseSessionListReturn; + +export const useSessionList: UseSessionList = () => { + const client = useClientContext(); + + if (!client) { + return { isLoaded: false, sessions: undefined }; + } + + return { isLoaded: true, sessions: client.sessions }; +}; diff --git a/packages/react/src/hooks/useSignIn.ts b/packages/react/src/hooks/useSignIn.ts new file mode 100644 index 00000000000..67e5a545dce --- /dev/null +++ b/packages/react/src/hooks/useSignIn.ts @@ -0,0 +1,19 @@ +import { SignInResource } from '@clerk/types'; + +import { useClientContext } from '../contexts/ClientContext'; + +type UseSignInReturn = + | { isLoaded: false; signIn: undefined } + | { isLoaded: true; signIn: SignInResource }; + +type UseSignIn = () => UseSignInReturn; + +export const useSignIn: UseSignIn = () => { + const client = useClientContext(); + + if (!client) { + return { isLoaded: false, signIn: undefined }; + } + + return { isLoaded: true, signIn: client.signIn }; +}; diff --git a/packages/react/src/hooks/useSignUp.ts b/packages/react/src/hooks/useSignUp.ts new file mode 100644 index 00000000000..b252fde64ed --- /dev/null +++ b/packages/react/src/hooks/useSignUp.ts @@ -0,0 +1,19 @@ +import { SignUpResource } from '@clerk/types'; + +import { useClientContext } from '../contexts/ClientContext'; + +type UseSignUpReturn = + | { isLoaded: false; signUp: undefined } + | { isLoaded: true; signUp: SignUpResource }; + +type UseSignUp = () => UseSignUpReturn; + +export const useSignUp: UseSignUp = () => { + const client = useClientContext(); + + if (!client) { + return { isLoaded: false, signUp: undefined }; + } + + return { isLoaded: true, signUp: client.signUp }; +}; From 4046b291bb93d0f7471138c067cce8cf84cac265 Mon Sep 17 00:00:00 2001 From: Nikos Douvlis Date: Thu, 10 Mar 2022 13:10:08 +0200 Subject: [PATCH 51/58] feat(remix): Better server error handling (#95) --- packages/remix/src/client/ConnectClerk.tsx | 4 ++-- .../remix/src/client/RemixClerkProvider.tsx | 7 ++---- packages/remix/src/client/utils.ts | 19 --------------- packages/remix/src/ssr/rootAuthLoader.ts | 3 +++ packages/remix/src/utils.ts | 23 +++++++++++++++++++ 5 files changed, 30 insertions(+), 26 deletions(-) delete mode 100644 packages/remix/src/client/utils.ts create mode 100644 packages/remix/src/utils.ts diff --git a/packages/remix/src/client/ConnectClerk.tsx b/packages/remix/src/client/ConnectClerk.tsx index 5afc281be08..3c5c3c9b2cf 100644 --- a/packages/remix/src/client/ConnectClerk.tsx +++ b/packages/remix/src/client/ConnectClerk.tsx @@ -3,9 +3,9 @@ import React from 'react'; import { ClerkProvider, RemixClerkProviderProps } from './RemixClerkProvider'; -type ConnectClerkOptions = Partial>; +type ConnectClerkOptions = Partial>; -export function ConnectClerk(App: () => JSX.Element, opts: ConnectClerkOptions) { +export function ConnectClerk(App: () => JSX.Element, opts: ConnectClerkOptions = {}) { return () => { const { clerkState } = useLoaderData(); return ( diff --git a/packages/remix/src/client/RemixClerkProvider.tsx b/packages/remix/src/client/RemixClerkProvider.tsx index b7df2eb5757..3ed9c63074c 100644 --- a/packages/remix/src/client/RemixClerkProvider.tsx +++ b/packages/remix/src/client/RemixClerkProvider.tsx @@ -3,8 +3,7 @@ import { IsomorphicClerkOptions } from '@clerk/clerk-react/dist/types'; import { useNavigate } from '@remix-run/react'; import React from 'react'; -import { noFrontendApiError } from '../errors'; -import { assertValidClerkState, warnForSsr } from './utils'; +import { assertFrontendApi, assertValidClerkState, warnForSsr } from '../utils'; export * from '@clerk/clerk-react'; @@ -26,9 +25,7 @@ export function ClerkProvider({ children, ...rest }: RemixClerkProviderProps): J const { __clerk_ssr_state, __frontendApi } = clerkState?.__internal_clerk_state || {}; - if (!__frontendApi) { - throw new Error(noFrontendApiError); - } + assertFrontendApi(__frontendApi); return ( Date: Thu, 10 Mar 2022 16:14:05 +0200 Subject: [PATCH 52/58] feat(clerk-react): Add isLoaded to `useOrganizations` hook (#92) --- packages/react/src/hooks/useOrganizations.ts | 49 +++++++++++++------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/packages/react/src/hooks/useOrganizations.ts b/packages/react/src/hooks/useOrganizations.ts index d30d8be007a..554cdcc8e32 100644 --- a/packages/react/src/hooks/useOrganizations.ts +++ b/packages/react/src/hooks/useOrganizations.ts @@ -1,32 +1,45 @@ import { CreateOrganizationParams, + LoadedClerk, OrganizationMembershipResource, OrganizationResource, } from '@clerk/types'; -import { useContext } from 'react'; -import { assertWrappedByClerkProvider } from '../contexts/assertHelpers'; -import { StructureContext } from '../contexts/StructureContext'; -import { useClerk } from '../hooks'; +import { useIsomorphicClerkContext } from '../contexts/IsomorphicClerkContext'; -type UseOrganizations = { - createOrganization: ( - params: CreateOrganizationParams, - ) => Promise; - getOrganizationMemberships: () => Promise; - getOrganization: ( - organizationId: string, - ) => Promise; -}; +type UseOrganizationsReturn = + | { + isLoaded: false; + createOrganization: undefined; + getOrganizationMemberships: undefined; + getOrganization: undefined; + } + | { + isLoaded: true; + createOrganization: (params: CreateOrganizationParams) => Promise; + getOrganizationMemberships: () => Promise; + getOrganization: (organizationId: string) => Promise; + }; + +type UseOrganizations = () => UseOrganizationsReturn; -export function useOrganizations(): UseOrganizations { - const structureCtx = useContext(StructureContext); - assertWrappedByClerkProvider(structureCtx); - const clerk = useClerk(); +export const useOrganizations: UseOrganizations = () => { + const isomorphicClerk = useIsomorphicClerkContext(); + if (!isomorphicClerk.loaded) { + return { + isLoaded: false, + createOrganization: undefined, + getOrganizationMemberships: undefined, + getOrganization: undefined, + }; + } + + const clerk = isomorphicClerk as unknown as LoadedClerk; return { + isLoaded: true, createOrganization: clerk.createOrganization, getOrganizationMemberships: clerk.getOrganizationMemberships, getOrganization: clerk.getOrganization, }; -} +}; From ca71ddd2c94b4e528b85e96e340eb431f3b7b44c Mon Sep 17 00:00:00 2001 From: Ian McPhail Date: Mon, 7 Mar 2022 09:46:27 -0500 Subject: [PATCH 53/58] chore(clerk-react): Add contribution docs --- packages/react/docs/CODE_OF_CONDUCT.md | 132 +++++++++++++++++++++++++ packages/react/docs/CONTRIBUTING.md | 120 ++++++++++++++++++++++ packages/react/docs/SECURITY.md | 19 ++++ 3 files changed, 271 insertions(+) create mode 100644 packages/react/docs/CODE_OF_CONDUCT.md create mode 100644 packages/react/docs/CONTRIBUTING.md create mode 100644 packages/react/docs/SECURITY.md diff --git a/packages/react/docs/CODE_OF_CONDUCT.md b/packages/react/docs/CODE_OF_CONDUCT.md new file mode 100644 index 00000000000..ac0d295cf55 --- /dev/null +++ b/packages/react/docs/CODE_OF_CONDUCT.md @@ -0,0 +1,132 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall + community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of + any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, + without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +[community@clerk.dev](mailto:community@clerk.dev). +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at +[https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations diff --git a/packages/react/docs/CONTRIBUTING.md b/packages/react/docs/CONTRIBUTING.md new file mode 100644 index 00000000000..596289a82f1 --- /dev/null +++ b/packages/react/docs/CONTRIBUTING.md @@ -0,0 +1,120 @@ +# Contributing + +When contributing to this repository, please first discuss the change you wish to make via issue, email, or any other method with the owners of this repository before making a change. +Please note we have a [code of conduct](CODE_OF_CONDUCT.md), please follow it in all your interactions with the project. + +
+TABLE OF CONTENTS + +- [Development environment setup](#development-environment-setup) +- [Issues and feature requests](#issues-and-feature-requests) + - [How to submit a Pull Request](#how-to-submit-a-pull-request) +- [Publishing packages](#publishing-packages) + - [Publishing `@next` package versions](#publishing-next-package-versions) +- [License](#license) + +
+ +## Development environment setup + +The current monorepo setup is based on: + +- [Lerna](https://github.com/lerna/lerna) used mostly for task running and versioning. +- [npm workspaces](https://docs.npmjs.com/cli/v8/using-npm/workspaces) used for package linking. + +### A note on commit messages + +The processes required for Lerna to manage releases and changelogs is done through the [conventional-commits](https://www.conventionalcommits.org/en/v1.0.0/) specification. + +To set up your development environment, please follow these steps: + +1. Clone the repo + + ```sh + git clone https://github.com/clerkinc/javascript + ``` + +2. Change into the directory and install dependencies + + ```sh + cd javascript + npm install + ``` + +3. Build all the packages in the monorepo by running: + + ```sh + npm run build + ``` +## Issues and feature requests + +You've found a bug in the source code, a mistake in the documentation or maybe you'd like a new feature? You can help us by [submitting an issue on GitHub](https://github.com/clerkinc/javascript/issues). Before you create an issue, make sure to search the issue archive -- your issue may have already been addressed! + +Please try to create bug reports that are: + +- _Reproducible._ Include steps to reproduce the problem. +- _Specific._ Include as much detail as possible: which version, what environment, etc. +- _Unique._ Do not duplicate existing opened issues. +- _Scoped to a Single Bug._ One bug per report. + +**Even better: Submit a pull request with a fix or new feature!** + +### How to submit a Pull Request + +1. Search our repository for open or closed + [Pull Requests](https://github.com/clerkinc/javascript/pulls) + that relate to your submission. You don't want to duplicate effort. +2. Fork the project +3. Create your feature branch (`git checkout -b feat/amazing_feature`) +4. Commit your changes (`git commit -m 'feat: Add amazing_feature'`). Clerk uses [conventional commits](https://www.conventionalcommits.org), so please follow the specification in your commit messages. +5. Push to the branch (`git push origin feat/amazing_feature`) +6. [Open a Pull Request](https://github.com/clerkinc/javascript/compare?expand=1) + +## Publishing packages + +_Version updates and publishing is managed using Lerna._ + +### TL;DR +1. `npm run bump` +2. `npm run release` + +### Commands explanation + +After all the features have been merged and we want to create a new release, we use `npm run bump`. + +This script will use `lerna version` to check which packages need to be updated and in what way based on the updates since the previous release. + +The command will guide you through the version changes that are detected and will: +- Bump the package versions. +- Run the `version` hook updating the version info files. +- Create new tags and a "release" commit. +- Push the commit and tags to the origin. + +After that is done, and all seems valid, you can run `npm run release` which will go through the publish process of the packages included in the release commit. + +For more info you can check the [lerna version](https://github.com/lerna/lerna/tree/main/commands/version) and [lerna publish](https://github.com/lerna/lerna/tree/main/commands/publish) documentation. + + +## Publishing `@next` package versions + +_`@next` version updates and publishing is managed using Lerna._ + +Install the `@next` version using `npm install @clerk/{package_name}@next`. + +### TL;DR +1. `npm run bump:next` +2. `npm run release:next` + +### Graduate the next version +To graduate\* the version pointed by the `@next` tag: +1. `npm run graduate:next` +2. `npm run release` + +### Process explanation +The `bump:next` command will create an `alpha` version update on the packages changed. Next if you want to release this version on npm to be installed, you would run the `npm run release:next` which would publish the version under the `@next` tag. + +\* By 'graduate' we mean publishing the `@next` tagged versions, which in actual versions result in `x.y.z-alpha.a.b.c`, to the stable one `x.y.z`. + +## License + +By contributing to Clerk, you agree that your contributions will be licensed under its MIT License. diff --git a/packages/react/docs/SECURITY.md b/packages/react/docs/SECURITY.md new file mode 100644 index 00000000000..eb1a76f8257 --- /dev/null +++ b/packages/react/docs/SECURITY.md @@ -0,0 +1,19 @@ +# Security Policy + +We take the security of our systems seriously, and we value the security community. The disclosure of security vulnerabilities helps us ensure the security and privacy of our users. + +## Reporting a Vulnerability + +**Please do not report security vulnerabilities through public GitHub issues.** + +If you believe you’ve found a security vulnerability in one of our products or platforms, please send it to us by emailing [security@clerk.dev](mailto:security@clerk.dev). Please include the following details with your report: + +1. Description of the location and potential impact of the vulnerability; and + +2. A detailed description of the steps required to reproduce the vulnerability (POC scripts, screenshots, and compressed screen captures are all helpful to us). + +We will evaluate the vulnerability and, if necessary, release a fix or mitigating steps to address it. We will contact you to let you know the outcome, and will credit you in the report. + +Please **do not disclose the vulnerability publicly** until a fix is released. + +Once we have either a) published a fix, or b) declined to address the vulnerability for whatever reason, you are free to publicly disclose it. From ef7c9fb9943e2dae748972c9d48b54d4ba2d7e57 Mon Sep 17 00:00:00 2001 From: Ian McPhail Date: Mon, 7 Mar 2022 09:47:12 -0500 Subject: [PATCH 54/58] chore(clerk-react): Update license --- packages/react/LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react/LICENSE b/packages/react/LICENSE index 0d101f76fb2..66914b6af7c 100644 --- a/packages/react/LICENSE +++ b/packages/react/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021 Clerk Inc +Copyright (c) 2022 Clerk, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 0eba574bafb233c8f4a3faa52f4bc69c36038f58 Mon Sep 17 00:00:00 2001 From: Ian McPhail Date: Mon, 7 Mar 2022 15:27:15 -0500 Subject: [PATCH 55/58] chore(clerk-react): Update README --- packages/react/README.md | 127 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 124 insertions(+), 3 deletions(-) diff --git a/packages/react/README.md b/packages/react/README.md index be8084830b6..7a0e0c39413 100644 --- a/packages/react/README.md +++ b/packages/react/README.md @@ -1,7 +1,128 @@ +

+ + Clerk logo + +
+

+ # @clerk/clerk-react -Simple and beautiful user management. +
+ +[![Chat on Discord](https://img.shields.io/discord/856971667393609759.svg?logo=discord)](https://discord.com/invite/b5rXHjAg7A) +[![Clerk documentation](https://img.shields.io/badge/documentation-clerk-green.svg)](https://docs.clerk.dev) +[![Follow on Twitter](https://img.shields.io/twitter/follow/ClerkDev?style=social)](https://twitter.com/intent/follow?screen_name=ClerkDev) + +[Changelog](CHANGELOG.md) +· +[Report a Bug](https://github.com/clerkinc/javascript/issues/new?assignees=&labels=bug&template=bug_report.md&title=Bug%3A+) +· +[Request a Feature](https://github.com/clerkinc/javascript/issues/new?assignees=&labels=enhancement&template=feature_request.md&title=Feature%3A+) +· +[Ask a Question](https://github.com/clerkinc/javascript/issues/new?assignees=&labels=question&template=ask_a_question.md&title=Support%3A+) + +
+ +--- + +## Overview + +Clerk is the easiest way to add authentication and user management to your React application. Add sign up, sign in, and profile management to your application in minutes. + +## Getting Started + +### Prerequisites + +- React v16+ +- Node.js v14+ + +### Installation + +```sh +npm install @clerk/clerk-react +``` + +### Build + +```sh +npm run build +``` + +To build the package in watch mode, run the following: + +```sh +npm run dev +``` + +## Usage + +Clerk requires your application to be wrapped in the `` context. + +If using Create React App, set `REACT_APP_CLERK_FRONTEND_API` to your Frontend API in your `.env.local` file to make the environment variable accessible on `process.env` and pass it as the `frontendApi` prop. + +```jsx +import { render } from "react-dom"; + +import { + ClerkProvider, + SignedIn, + SignedOut, + SignInButton, + UserButton, +} from "@clerk/clerk-react"; + +const frontendApi = process.env.REACT_APP_CLERK_FRONTEND_API; + +render( + + + , + document.getElementById("root"), +); + +function App() { + return ( + <> +

Hello Clerk!

+ + + + + + + + ); +} +``` + +_For further details and examples, please refer to our [Documentation](https://docs.clerk.dev?utm_source=github&utm_medium=clerk_react)._ + +## Support + +You can get in touch with us in any of the following ways: + +- Join our official community [Discord server](https://discord.com/invite/b5rXHjAg7A) +- Open a [GitHub support issue](https://github.com/clerkinc/javascript/issues/new?assignees=&labels=question&template=ask_a_question.md&title=Support%3A+) +- Contact options listed on [our Support page](https://clerk.dev/support?utm_source=github&utm_medium=clerk_react) + +## Contributing + +We're open to all community contributions! If you'd like to contribute in any way, please read [our contribution guidelines](docs/CONTRIBUTING.md). + +## Security + +`@clerk/clerk-react` follows good practices of security, but 100% security cannot be assured. + +`@clerk/clerk-react` is provided **"as is"** without any **warranty**. Use at your own risk. + +_For more information and to report security issues, please refer to our [security documentation](docs/SECURITY.md)._ + +## License + +This project is licensed under the **MIT license**. + +See [LICENSE](LICENSE) for more information. -Add sign up, sign in, and profile management to your application in minutes. Theme our prebuilt frontends to match your branding, or customize everything with our APIs. +``` -[Go to Clerk.dev official documentation](https://docs.clerk.dev/) +``` From ce29b246fb787c21679cb1b5c7969ec55c5180a6 Mon Sep 17 00:00:00 2001 From: Ian McPhail Date: Tue, 8 Mar 2022 09:50:59 -0500 Subject: [PATCH 56/58] chore(clerk-react): Update README links to absolute paths --- packages/react/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/react/README.md b/packages/react/README.md index 7a0e0c39413..70255bcb2c6 100644 --- a/packages/react/README.md +++ b/packages/react/README.md @@ -13,7 +13,7 @@ [![Clerk documentation](https://img.shields.io/badge/documentation-clerk-green.svg)](https://docs.clerk.dev) [![Follow on Twitter](https://img.shields.io/twitter/follow/ClerkDev?style=social)](https://twitter.com/intent/follow?screen_name=ClerkDev) -[Changelog](CHANGELOG.md) +[Changelog](https://github.com/clerkinc/javascript/blob/main/packages/react/CHANGELOG.md) · [Report a Bug](https://github.com/clerkinc/javascript/issues/new?assignees=&labels=bug&template=bug_report.md&title=Bug%3A+) · @@ -107,7 +107,7 @@ You can get in touch with us in any of the following ways: ## Contributing -We're open to all community contributions! If you'd like to contribute in any way, please read [our contribution guidelines](docs/CONTRIBUTING.md). +We're open to all community contributions! If you'd like to contribute in any way, please read [our contribution guidelines](https://github.com/clerkinc/javascript/blob/main/packages/react/docs/CONTRIBUTING.md). ## Security @@ -115,13 +115,13 @@ We're open to all community contributions! If you'd like to contribute in any wa `@clerk/clerk-react` is provided **"as is"** without any **warranty**. Use at your own risk. -_For more information and to report security issues, please refer to our [security documentation](docs/SECURITY.md)._ +_For more information and to report security issues, please refer to our [security documentation](https://github.com/clerkinc/javascript/blob/main/packages/react/docs/SECURITY.md)._ ## License This project is licensed under the **MIT license**. -See [LICENSE](LICENSE) for more information. +See [LICENSE](https://github.com/clerkinc/javascript/blob/main/packages/react/LICENSE) for more information. ``` From 57b675c762187d1f16cde6d2577bac71f7993438 Mon Sep 17 00:00:00 2001 From: Agis Anastasopoulos Date: Tue, 8 Mar 2022 13:42:06 +0200 Subject: [PATCH 57/58] feat(types): Support for oauth_apple --- packages/backend-core/src/api/resources/Enums.ts | 8 +++++++- packages/types/src/oauth.ts | 9 ++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/packages/backend-core/src/api/resources/Enums.ts b/packages/backend-core/src/api/resources/Enums.ts index a322e4be819..de00aa5ac89 100644 --- a/packages/backend-core/src/api/resources/Enums.ts +++ b/packages/backend-core/src/api/resources/Enums.ts @@ -12,7 +12,13 @@ export type OAuthProvider = | 'gitlab' | 'discord' | 'twitter' - | 'twitch'; + | 'twitch' + | 'linkedin' + | 'dropbox' + | 'bitbucket' + | 'microsoft' + | 'notion' + | 'apple'; export type OAuthStrategy = `oauth_${OAuthProvider}`; diff --git a/packages/types/src/oauth.ts b/packages/types/src/oauth.ts index 6a77dc8d347..8bce1f15334 100644 --- a/packages/types/src/oauth.ts +++ b/packages/types/src/oauth.ts @@ -12,7 +12,8 @@ export type OAuthProvider = | 'dropbox' | 'bitbucket' | 'microsoft' - | 'notion'; + | 'notion' + | 'apple'; export type OAuthStrategy = `oauth_${OAuthProvider}`; @@ -108,6 +109,12 @@ export const OAUTH_PROVIDERS: OAuthProviderData[] = [ name: 'Notion', docsUrl: 'https://docs.clerk.dev/reference/social-login-reference/notion', }, + { + provider: 'apple', + strategy: 'oauth_apple', + name: 'Apple', + docsUrl: 'https://docs.clerk.dev/reference/social-login-reference/apple', + }, ]; interface getOAuthProviderDataProps { From 512055698ef62a9c760afb092aac0ca33a8e5408 Mon Sep 17 00:00:00 2001 From: Nikos Douvlis Date: Fri, 11 Mar 2022 03:18:36 +0200 Subject: [PATCH 58/58] chore(release): Publish - @clerk/backend-core@0.6.0-staging.0 - @clerk/clerk-js@3.0.0-alpha.9 - @clerk/edge@0.3.8-alpha.0 - @clerk/clerk-expo@0.8.13-alpha.1 - @clerk/nextjs@3.0.0-alpha.9 - @clerk/clerk-react@3.0.0-alpha.10 - @clerk/remix@0.1.0-alpha.6 - @clerk/clerk-sdk-node@2.9.9-alpha.0 - @clerk/shared@0.0.6-alpha.2 - @clerk/types@2.0.0-alpha.9 --- package-lock.json | 332 +++-------------------------- packages/backend-core/CHANGELOG.md | 16 ++ packages/backend-core/package.json | 2 +- packages/clerk-js/CHANGELOG.md | 8 + packages/clerk-js/package.json | 6 +- packages/edge/CHANGELOG.md | 8 + packages/edge/package.json | 2 +- packages/edge/src/info.ts | 2 +- packages/expo/CHANGELOG.md | 8 + packages/expo/package.json | 6 +- packages/nextjs/CHANGELOG.md | 13 ++ packages/nextjs/package.json | 8 +- packages/react/CHANGELOG.md | 10 + packages/react/package.json | 4 +- packages/react/src/info.ts | 2 +- packages/remix/CHANGELOG.md | 17 ++ packages/remix/package.json | 8 +- packages/sdk-node/CHANGELOG.md | 8 + packages/sdk-node/package.json | 2 +- packages/sdk-node/src/info.ts | 2 +- packages/shared/CHANGELOG.md | 8 + packages/shared/package.json | 2 +- packages/types/CHANGELOG.md | 10 + packages/types/package.json | 2 +- 24 files changed, 162 insertions(+), 324 deletions(-) diff --git a/package-lock.json b/package-lock.json index cf778280f3d..54f26a80622 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23075,7 +23075,7 @@ }, "packages/backend-core": { "name": "@clerk/backend-core", - "version": "0.5.2-staging.0", + "version": "0.6.0-staging.0", "license": "MIT", "dependencies": { "camelcase-keys": "^7.0.1", @@ -23104,10 +23104,10 @@ }, "packages/clerk-js": { "name": "@clerk/clerk-js", - "version": "3.0.0-alpha.8", + "version": "3.0.0-alpha.9", "license": "MIT", "dependencies": { - "@clerk/types": "^2.0.0-alpha.8", + "@clerk/types": "^2.0.0-alpha.9", "@popperjs/core": "^2.4.4", "browser-tabs-lock": "^1.2.15", "classnames": "^2.3.1", @@ -23127,7 +23127,7 @@ "@babel/preset-env": "^7.12.1", "@babel/preset-react": "^7.12.5", "@babel/preset-typescript": "^7.12.1", - "@clerk/shared": "0.0.6-alpha.1", + "@clerk/shared": "^0.0.6-alpha.2", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.2", "@svgr/webpack": "^6.2.1", "@testing-library/dom": "^7.28.1", @@ -23210,7 +23210,7 @@ }, "packages/edge": { "name": "@clerk/edge", - "version": "0.3.7", + "version": "0.3.8-alpha.0", "license": "MIT", "dependencies": { "@clerk/backend-core": "^0.5.2", @@ -23247,11 +23247,11 @@ }, "packages/expo": { "name": "@clerk/clerk-expo", - "version": "0.8.13-alpha.0", + "version": "0.8.13-alpha.1", "license": "MIT", "dependencies": { - "@clerk/clerk-js": "^3.0.0-alpha.8", - "@clerk/clerk-react": "^3.0.0-alpha.9", + "@clerk/clerk-js": "^3.0.0-alpha.9", + "@clerk/clerk-react": "^3.0.0-alpha.10", "base-64": "^1.0.0" }, "devDependencies": { @@ -23291,12 +23291,12 @@ }, "packages/nextjs": { "name": "@clerk/nextjs", - "version": "3.0.0-alpha.8", + "version": "3.0.0-alpha.9", "license": "MIT", "dependencies": { - "@clerk/clerk-react": "^3.0.0-alpha.9", - "@clerk/clerk-sdk-node": "^2.9.6", - "@clerk/types": "^2.0.0-alpha.8", + "@clerk/clerk-react": "^3.0.0-alpha.10", + "@clerk/clerk-sdk-node": "^2.9.9-alpha.0", + "@clerk/types": "^2.0.0-alpha.9", "tslib": "^2.3.1" }, "devDependencies": { @@ -23318,93 +23318,18 @@ "next": ">=10" } }, - "packages/nextjs/node_modules/@clerk/backend-core": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@clerk/backend-core/-/backend-core-0.5.1.tgz", - "integrity": "sha512-+V/GbiLiFWkziXdMhooCXDEd3a+rDzDcjFo3LP3VNGUNxOW7mHBFxoVeWrjiBceQh8zhscrbUSRV+pmXq85Xdw==", - "dependencies": { - "camelcase-keys": "^7.0.1", - "query-string": "^7.0.1", - "snakecase-keys": "^5.1.2", - "tslib": "^2.3.1" - } - }, - "packages/nextjs/node_modules/@clerk/clerk-sdk-node": { - "version": "2.9.6", - "resolved": "https://registry.npmjs.org/@clerk/clerk-sdk-node/-/clerk-sdk-node-2.9.6.tgz", - "integrity": "sha512-T/fKQBMgRYyALN5ua7IpKwuyxpzCVYjK3bHk73hpqud+xm3mNe0gGmHGW+FH4YQhZ3rIArbPEkhyNnn50+nnmg==", - "dependencies": { - "@clerk/backend-core": "^0.5.1", - "@peculiar/webcrypto": "^1.2.3", - "camelcase-keys": "^6.2.2", - "cookies": "^0.8.0", - "deepmerge": "^4.2.2", - "got": "^11.8.2", - "jsonwebtoken": "^8.5.1", - "jwks-rsa": "^2.0.4", - "snakecase-keys": "^3.2.1", - "tslib": "^2.3.1" - }, - "engines": { - "node": ">=12" - } - }, - "packages/nextjs/node_modules/@clerk/clerk-sdk-node/node_modules/camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "dependencies": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "packages/nextjs/node_modules/@clerk/clerk-sdk-node/node_modules/snakecase-keys": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/snakecase-keys/-/snakecase-keys-3.2.1.tgz", - "integrity": "sha512-CjU5pyRfwOtaOITYv5C8DzpZ8XA/ieRsDpr93HI2r6e3YInC6moZpSQbmUtg8cTk58tq2x3jcG2gv+p1IZGmMA==", - "dependencies": { - "map-obj": "^4.1.0", - "to-snake-case": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, "packages/nextjs/node_modules/@types/node": { "version": "16.11.22", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.22.tgz", "integrity": "sha512-DYNtJWauMQ9RNpesl4aVothr97/tIJM8HbyOXJ0AYT1Z2bEjLHyfjOBPAQQVMLf8h3kSShYfNk8Wnto8B2zHUA==", "dev": true }, - "packages/nextjs/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "engines": { - "node": ">=6" - } - }, - "packages/nextjs/node_modules/quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", - "engines": { - "node": ">=8" - } - }, "packages/react": { "name": "@clerk/clerk-react", - "version": "3.0.0-alpha.9", + "version": "3.0.0-alpha.10", "license": "MIT", "dependencies": { - "@clerk/types": "^2.0.0-alpha.8", + "@clerk/types": "^2.0.0-alpha.9", "tslib": "^2.3.1" }, "devDependencies": { @@ -23441,12 +23366,12 @@ }, "packages/remix": { "name": "@clerk/remix", - "version": "0.1.0-alpha.5", + "version": "0.1.0-alpha.6", "license": "MIT", "dependencies": { - "@clerk/clerk-react": "^3.0.0-alpha.9", - "@clerk/clerk-sdk-node": "^2.9.0", - "@clerk/types": "^2.0.0-alpha.8", + "@clerk/clerk-react": "^3.0.0-alpha.10", + "@clerk/clerk-sdk-node": "^2.9.9-alpha.0", + "@clerk/types": "^2.0.0-alpha.9", "cookie": "^0.4.2", "tslib": "^2.3.1" }, @@ -23471,79 +23396,12 @@ "remix": ">=1.2.1" } }, - "packages/remix/node_modules/@clerk/backend-core": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@clerk/backend-core/-/backend-core-0.5.1.tgz", - "integrity": "sha512-+V/GbiLiFWkziXdMhooCXDEd3a+rDzDcjFo3LP3VNGUNxOW7mHBFxoVeWrjiBceQh8zhscrbUSRV+pmXq85Xdw==", - "dependencies": { - "camelcase-keys": "^7.0.1", - "query-string": "^7.0.1", - "snakecase-keys": "^5.1.2", - "tslib": "^2.3.1" - } - }, - "packages/remix/node_modules/@clerk/clerk-sdk-node": { - "version": "2.9.6", - "resolved": "https://registry.npmjs.org/@clerk/clerk-sdk-node/-/clerk-sdk-node-2.9.6.tgz", - "integrity": "sha512-T/fKQBMgRYyALN5ua7IpKwuyxpzCVYjK3bHk73hpqud+xm3mNe0gGmHGW+FH4YQhZ3rIArbPEkhyNnn50+nnmg==", - "dependencies": { - "@clerk/backend-core": "^0.5.1", - "@peculiar/webcrypto": "^1.2.3", - "camelcase-keys": "^6.2.2", - "cookies": "^0.8.0", - "deepmerge": "^4.2.2", - "got": "^11.8.2", - "jsonwebtoken": "^8.5.1", - "jwks-rsa": "^2.0.4", - "snakecase-keys": "^3.2.1", - "tslib": "^2.3.1" - }, - "engines": { - "node": ">=12" - } - }, - "packages/remix/node_modules/@clerk/clerk-sdk-node/node_modules/camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "dependencies": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "packages/remix/node_modules/@clerk/clerk-sdk-node/node_modules/snakecase-keys": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/snakecase-keys/-/snakecase-keys-3.2.1.tgz", - "integrity": "sha512-CjU5pyRfwOtaOITYv5C8DzpZ8XA/ieRsDpr93HI2r6e3YInC6moZpSQbmUtg8cTk58tq2x3jcG2gv+p1IZGmMA==", - "dependencies": { - "map-obj": "^4.1.0", - "to-snake-case": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, "packages/remix/node_modules/@types/node": { "version": "16.11.25", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.25.tgz", "integrity": "sha512-NrTwfD7L1RTc2qrHQD4RTTy4p0CO2LatKBEKEds3CaVuhoM/+DJzmWZl5f+ikR8cm8F5mfJxK+9rQq07gRiSjQ==", "dev": true }, - "packages/remix/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "engines": { - "node": ">=6" - } - }, "packages/remix/node_modules/cookie": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", @@ -23552,17 +23410,9 @@ "node": ">= 0.6" } }, - "packages/remix/node_modules/quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", - "engines": { - "node": ">=8" - } - }, "packages/sdk-node": { "name": "@clerk/clerk-sdk-node", - "version": "2.9.8", + "version": "2.9.9-alpha.0", "license": "MIT", "dependencies": { "@clerk/backend-core": "^0.5.2", @@ -23924,7 +23774,7 @@ }, "packages/shared": { "name": "@clerk/shared", - "version": "0.0.6-alpha.1", + "version": "0.0.6-alpha.2", "devDependencies": { "@babel/core": "^7.13.14", "@babel/preset-env": "^7.13.12", @@ -23993,7 +23843,7 @@ }, "packages/types": { "name": "@clerk/types", - "version": "2.0.0-alpha.8", + "version": "2.0.0-alpha.9", "license": "MIT", "devDependencies": { "@types/jest": "^27.4.0", @@ -25322,8 +25172,8 @@ "@clerk/clerk-expo": { "version": "file:packages/expo", "requires": { - "@clerk/clerk-js": "^3.0.0-alpha.8", - "@clerk/clerk-react": "^3.0.0-alpha.9", + "@clerk/clerk-js": "^3.0.0-alpha.9", + "@clerk/clerk-react": "^3.0.0-alpha.10", "@clerk/types": "^1.28.2-staging.0", "@types/jest": "^27.4.0", "@types/node": "^16.11.9", @@ -25361,8 +25211,8 @@ "@babel/preset-env": "^7.12.1", "@babel/preset-react": "^7.12.5", "@babel/preset-typescript": "^7.12.1", - "@clerk/shared": "0.0.6-alpha.1", - "@clerk/types": "^2.0.0-alpha.8", + "@clerk/shared": "^0.0.6-alpha.2", + "@clerk/types": "^2.0.0-alpha.9", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.2", "@popperjs/core": "^2.4.4", "@svgr/webpack": "^6.2.1", @@ -25446,7 +25296,7 @@ "@clerk/clerk-react": { "version": "file:packages/react", "requires": { - "@clerk/types": "^2.0.0-alpha.8", + "@clerk/types": "^2.0.0-alpha.9", "@testing-library/dom": "^7.28.1", "@testing-library/jest-dom": "^5.11.6", "@testing-library/react": "^11.2.1", @@ -25767,9 +25617,9 @@ "@clerk/nextjs": { "version": "file:packages/nextjs", "requires": { - "@clerk/clerk-react": "^3.0.0-alpha.9", - "@clerk/clerk-sdk-node": "^2.9.6", - "@clerk/types": "^2.0.0-alpha.8", + "@clerk/clerk-react": "^3.0.0-alpha.10", + "@clerk/clerk-sdk-node": "^2.9.9-alpha.0", + "@clerk/types": "^2.0.0-alpha.9", "@types/jest": "^27.4.0", "@types/node": "^16.11.9", "@types/react": "^17.0.39", @@ -25783,79 +25633,20 @@ "typescript": "^4.6.2" }, "dependencies": { - "@clerk/backend-core": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@clerk/backend-core/-/backend-core-0.5.1.tgz", - "integrity": "sha512-+V/GbiLiFWkziXdMhooCXDEd3a+rDzDcjFo3LP3VNGUNxOW7mHBFxoVeWrjiBceQh8zhscrbUSRV+pmXq85Xdw==", - "requires": { - "camelcase-keys": "^7.0.1", - "query-string": "^7.0.1", - "snakecase-keys": "^5.1.2", - "tslib": "^2.3.1" - } - }, - "@clerk/clerk-sdk-node": { - "version": "2.9.6", - "resolved": "https://registry.npmjs.org/@clerk/clerk-sdk-node/-/clerk-sdk-node-2.9.6.tgz", - "integrity": "sha512-T/fKQBMgRYyALN5ua7IpKwuyxpzCVYjK3bHk73hpqud+xm3mNe0gGmHGW+FH4YQhZ3rIArbPEkhyNnn50+nnmg==", - "requires": { - "@clerk/backend-core": "^0.5.1", - "@peculiar/webcrypto": "^1.2.3", - "camelcase-keys": "^6.2.2", - "cookies": "^0.8.0", - "deepmerge": "^4.2.2", - "got": "^11.8.2", - "jsonwebtoken": "^8.5.1", - "jwks-rsa": "^2.0.4", - "snakecase-keys": "^3.2.1", - "tslib": "^2.3.1" - }, - "dependencies": { - "camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "requires": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" - } - }, - "snakecase-keys": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/snakecase-keys/-/snakecase-keys-3.2.1.tgz", - "integrity": "sha512-CjU5pyRfwOtaOITYv5C8DzpZ8XA/ieRsDpr93HI2r6e3YInC6moZpSQbmUtg8cTk58tq2x3jcG2gv+p1IZGmMA==", - "requires": { - "map-obj": "^4.1.0", - "to-snake-case": "^1.0.0" - } - } - } - }, "@types/node": { "version": "16.11.22", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.22.tgz", "integrity": "sha512-DYNtJWauMQ9RNpesl4aVothr97/tIJM8HbyOXJ0AYT1Z2bEjLHyfjOBPAQQVMLf8h3kSShYfNk8Wnto8B2zHUA==", "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" - }, - "quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==" } } }, "@clerk/remix": { "version": "file:packages/remix", "requires": { - "@clerk/clerk-react": "^3.0.0-alpha.9", - "@clerk/clerk-sdk-node": "^2.9.0", - "@clerk/types": "^2.0.0-alpha.8", + "@clerk/clerk-react": "^3.0.0-alpha.10", + "@clerk/clerk-sdk-node": "^2.9.9-alpha.0", + "@clerk/types": "^2.0.0-alpha.9", "@types/cookie": "^0.4.1", "@types/jest": "^27.4.0", "@types/node": "^16.11.9", @@ -25870,75 +25661,16 @@ "typescript": "^4.6.2" }, "dependencies": { - "@clerk/backend-core": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@clerk/backend-core/-/backend-core-0.5.1.tgz", - "integrity": "sha512-+V/GbiLiFWkziXdMhooCXDEd3a+rDzDcjFo3LP3VNGUNxOW7mHBFxoVeWrjiBceQh8zhscrbUSRV+pmXq85Xdw==", - "requires": { - "camelcase-keys": "^7.0.1", - "query-string": "^7.0.1", - "snakecase-keys": "^5.1.2", - "tslib": "^2.3.1" - } - }, - "@clerk/clerk-sdk-node": { - "version": "2.9.6", - "resolved": "https://registry.npmjs.org/@clerk/clerk-sdk-node/-/clerk-sdk-node-2.9.6.tgz", - "integrity": "sha512-T/fKQBMgRYyALN5ua7IpKwuyxpzCVYjK3bHk73hpqud+xm3mNe0gGmHGW+FH4YQhZ3rIArbPEkhyNnn50+nnmg==", - "requires": { - "@clerk/backend-core": "^0.5.1", - "@peculiar/webcrypto": "^1.2.3", - "camelcase-keys": "^6.2.2", - "cookies": "^0.8.0", - "deepmerge": "^4.2.2", - "got": "^11.8.2", - "jsonwebtoken": "^8.5.1", - "jwks-rsa": "^2.0.4", - "snakecase-keys": "^3.2.1", - "tslib": "^2.3.1" - }, - "dependencies": { - "camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "requires": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" - } - }, - "snakecase-keys": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/snakecase-keys/-/snakecase-keys-3.2.1.tgz", - "integrity": "sha512-CjU5pyRfwOtaOITYv5C8DzpZ8XA/ieRsDpr93HI2r6e3YInC6moZpSQbmUtg8cTk58tq2x3jcG2gv+p1IZGmMA==", - "requires": { - "map-obj": "^4.1.0", - "to-snake-case": "^1.0.0" - } - } - } - }, "@types/node": { "version": "16.11.25", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.25.tgz", "integrity": "sha512-NrTwfD7L1RTc2qrHQD4RTTy4p0CO2LatKBEKEds3CaVuhoM/+DJzmWZl5f+ikR8cm8F5mfJxK+9rQq07gRiSjQ==", "dev": true }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" - }, "cookie": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" - }, - "quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==" } } }, diff --git a/packages/backend-core/CHANGELOG.md b/packages/backend-core/CHANGELOG.md index 91354d5a4d9..33bae13ef2f 100644 --- a/packages/backend-core/CHANGELOG.md +++ b/packages/backend-core/CHANGELOG.md @@ -3,6 +3,22 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.6.0-staging.0](https://github.com/clerkinc/javascript/compare/@clerk/backend-core@0.5.2...@clerk/backend-core@0.6.0-staging.0) (2022-03-11) + + +### Features + +* **types:** Support for oauth_apple ([57b675c](https://github.com/clerkinc/javascript/commit/57b675c762187d1f16cde6d2577bac71f7993438)) + + +### Bug Fixes + +* **backend-core:** Correctly use the forwarded-proto value ([1dddf13](https://github.com/clerkinc/javascript/commit/1dddf134c2342480d2b406220acffb5fdd54a400)) +* **backend-core:** Make sure to check cross-origin in more cases ([db2360d](https://github.com/clerkinc/javascript/commit/db2360d84fbc9ce4cf62e0698099b59ad4bfc83c)) +* **backend-core:** More robust cross-origin check for dev/prod ([234ac48](https://github.com/clerkinc/javascript/commit/234ac487f56f235760449c755ed29869b511acab)) + + + ### [0.5.2](https://github.com/clerkinc/javascript/compare/@clerk/backend-core@0.5.2-staging.0...@clerk/backend-core@0.5.2) (2022-03-09) **Note:** Version bump only for package @clerk/backend-core diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json index 9280012fe13..4c6f3cd2388 100644 --- a/packages/backend-core/package.json +++ b/packages/backend-core/package.json @@ -1,6 +1,6 @@ { "name": "@clerk/backend-core", - "version": "0.5.2-staging.0", + "version": "0.6.0-staging.0", "license": "MIT", "description": "Clerk Backend API core resources and authentication utilities for JavaScript environments.", "scripts": { diff --git a/packages/clerk-js/CHANGELOG.md b/packages/clerk-js/CHANGELOG.md index 6b308f7d9d4..8192b445270 100644 --- a/packages/clerk-js/CHANGELOG.md +++ b/packages/clerk-js/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [3.0.0-alpha.9](https://github.com/clerkinc/javascript/compare/@clerk/clerk-js@2.17.3...@clerk/clerk-js@3.0.0-alpha.9) (2022-03-11) + +**Note:** Version bump only for package @clerk/clerk-js + + + + + ## [3.0.0-alpha.8](https://github.com/clerkinc/javascript/compare/@clerk/clerk-js@2.14.3...@clerk/clerk-js@3.0.0-alpha.8) (2022-02-28) diff --git a/packages/clerk-js/package.json b/packages/clerk-js/package.json index 7a35b9d565d..5d238d3421e 100644 --- a/packages/clerk-js/package.json +++ b/packages/clerk-js/package.json @@ -1,6 +1,6 @@ { "name": "@clerk/clerk-js", - "version": "3.0.0-alpha.8", + "version": "3.0.0-alpha.9", "license": "MIT", "description": "Clerk.dev JS library", "keywords": [ @@ -38,7 +38,7 @@ "test:coverage": "jest --collectCoverage" }, "dependencies": { - "@clerk/types": "^2.0.0-alpha.8", + "@clerk/types": "^2.0.0-alpha.9", "@popperjs/core": "^2.4.4", "browser-tabs-lock": "^1.2.15", "classnames": "^2.3.1", @@ -58,7 +58,7 @@ "@babel/preset-env": "^7.12.1", "@babel/preset-react": "^7.12.5", "@babel/preset-typescript": "^7.12.1", - "@clerk/shared": "0.0.6-alpha.1", + "@clerk/shared": "^0.0.6-alpha.2", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.2", "@svgr/webpack": "^6.2.1", "@testing-library/dom": "^7.28.1", diff --git a/packages/edge/CHANGELOG.md b/packages/edge/CHANGELOG.md index 52da79c8428..63c9fa1497b 100644 --- a/packages/edge/CHANGELOG.md +++ b/packages/edge/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +### [0.3.8-alpha.0](https://github.com/clerkinc/javascript/compare/@clerk/edge@0.3.7...@clerk/edge@0.3.8-alpha.0) (2022-03-11) + +**Note:** Version bump only for package @clerk/edge + + + + + ### [0.3.7](https://github.com/clerkinc/javascript/compare/@clerk/edge@0.3.7-staging.0...@clerk/edge@0.3.7) (2022-03-09) **Note:** Version bump only for package @clerk/edge diff --git a/packages/edge/package.json b/packages/edge/package.json index 107ade75539..8ba269b0468 100644 --- a/packages/edge/package.json +++ b/packages/edge/package.json @@ -1,6 +1,6 @@ { "name": "@clerk/edge", - "version": "0.3.7", + "version": "0.3.8-alpha.0", "license": "MIT", "description": "Clerk SDK for serverless and edge environments", "keywords": [ diff --git a/packages/edge/src/info.ts b/packages/edge/src/info.ts index 4b8e96e2f3d..ab83894cb0e 100644 --- a/packages/edge/src/info.ts +++ b/packages/edge/src/info.ts @@ -1,4 +1,4 @@ /** DO NOT EDIT: This file is automatically generated by ../scripts/info.js */ -export const LIB_VERSION="0.3.7"; +export const LIB_VERSION="0.3.8-alpha.0"; export const LIB_NAME="@clerk/edge"; diff --git a/packages/expo/CHANGELOG.md b/packages/expo/CHANGELOG.md index 56876f95735..cdeddece9fe 100644 --- a/packages/expo/CHANGELOG.md +++ b/packages/expo/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +### [0.8.13-alpha.1](https://github.com/clerkinc/javascript/compare/@clerk/clerk-expo@0.8.13...@clerk/clerk-expo@0.8.13-alpha.1) (2022-03-11) + +**Note:** Version bump only for package @clerk/clerk-expo + + + + + ### [0.8.3-alpha.2](https://github.com/clerkinc/javascript/compare/@clerk/clerk-expo@0.8.6...@clerk/clerk-expo@0.8.3-alpha.2) (2022-02-28) **Note:** Version bump only for package @clerk/clerk-expo diff --git a/packages/expo/package.json b/packages/expo/package.json index fd71515888b..c4e6ba4b3d9 100644 --- a/packages/expo/package.json +++ b/packages/expo/package.json @@ -1,6 +1,6 @@ { "name": "@clerk/clerk-expo", - "version": "0.8.13-alpha.0", + "version": "0.8.13-alpha.1", "license": "MIT", "description": "Clerk.dev React Native/Expo library", "keywords": [ @@ -26,8 +26,8 @@ "dev": "tsc -p tsconfig.build.json --watch" }, "dependencies": { - "@clerk/clerk-js": "^3.0.0-alpha.8", - "@clerk/clerk-react": "^3.0.0-alpha.9", + "@clerk/clerk-js": "^3.0.0-alpha.9", + "@clerk/clerk-react": "^3.0.0-alpha.10", "base-64": "^1.0.0" }, "devDependencies": { diff --git a/packages/nextjs/CHANGELOG.md b/packages/nextjs/CHANGELOG.md index 72517164326..7f5e5c94a8f 100644 --- a/packages/nextjs/CHANGELOG.md +++ b/packages/nextjs/CHANGELOG.md @@ -3,6 +3,19 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [3.0.0-alpha.9](https://github.com/clerkinc/javascript/compare/@clerk/nextjs@2.11.13...@clerk/nextjs@3.0.0-alpha.9) (2022-03-11) + + +### Features + +* **clerk-remix:** Remove load options from `getAuth` ([246fe76](https://github.com/clerkinc/javascript/commit/246fe76943aedc07bed8510761a286ef324049ec)) +* **nextjs:** Enforce withServerSideAuth callback return type ([3766a49](https://github.com/clerkinc/javascript/commit/3766a4938641de36f953ec49f45d539f971d778c)) +* **nextjs:** Fetch user and session in parallel ([#49](https://github.com/clerkinc/javascript/issues/49)) ([fb89732](https://github.com/clerkinc/javascript/commit/fb89732952fba2d45fe9ea73820b6264f5e02dbc)) +* **nextjs:** Move shared NextJS SSR types to types package ([78d8c7c](https://github.com/clerkinc/javascript/commit/78d8c7c3e84f3926127e48c655793a0fca3cdc2c)) +* **nextjs:** Strictly type all possible withServerSideAuth return value combinations ([beba831](https://github.com/clerkinc/javascript/commit/beba83195828737ef20ca4450badded92d95d098)) + + + ## [3.0.0-alpha.8](https://github.com/clerkinc/javascript/compare/@clerk/nextjs@2.11.4...@clerk/nextjs@3.0.0-alpha.8) (2022-02-28) diff --git a/packages/nextjs/package.json b/packages/nextjs/package.json index 8cd5eec470a..df1d2458e65 100644 --- a/packages/nextjs/package.json +++ b/packages/nextjs/package.json @@ -1,6 +1,6 @@ { "name": "@clerk/nextjs", - "version": "3.0.0-alpha.8", + "version": "3.0.0-alpha.9", "license": "MIT", "description": "Clerk.dev SDK for NextJS", "keywords": [ @@ -32,9 +32,9 @@ "dev": "tsc -p tsconfig.build.json --watch" }, "dependencies": { - "@clerk/clerk-react": "^3.0.0-alpha.9", - "@clerk/clerk-sdk-node": "^2.9.6", - "@clerk/types": "^2.0.0-alpha.8", + "@clerk/clerk-react": "^3.0.0-alpha.10", + "@clerk/clerk-sdk-node": "^2.9.9-alpha.0", + "@clerk/types": "^2.0.0-alpha.9", "tslib": "^2.3.1" }, "devDependencies": { diff --git a/packages/react/CHANGELOG.md b/packages/react/CHANGELOG.md index 1f3755dc933..2a93492d986 100644 --- a/packages/react/CHANGELOG.md +++ b/packages/react/CHANGELOG.md @@ -3,6 +3,16 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [3.0.0-alpha.10](https://github.com/clerkinc/javascript/compare/@clerk/clerk-react@2.12.3...@clerk/clerk-react@3.0.0-alpha.10) (2022-03-11) + + +### Features + +* **clerk-react:** Add isLoaded to `useOrganizations` hook ([#92](https://github.com/clerkinc/javascript/issues/92)) ([a316c7a](https://github.com/clerkinc/javascript/commit/a316c7a9d66f356639038ce89b5853625e44d4b7)) +* **clerk-remix:** Mark clerk-remix as side-effect free to fix Remix bundling ([c57a902](https://github.com/clerkinc/javascript/commit/c57a9024674a61aa3f2b7e359935e42fc034ffdd)) + + + ## [3.0.0-alpha.9](https://github.com/clerkinc/javascript/compare/@clerk/clerk-react@2.11.4...@clerk/clerk-react@3.0.0-alpha.9) (2022-02-28) diff --git a/packages/react/package.json b/packages/react/package.json index 8b87fd6517f..197454522b1 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,6 +1,6 @@ { "name": "@clerk/clerk-react", - "version": "3.0.0-alpha.9", + "version": "3.0.0-alpha.10", "license": "MIT", "description": "Clerk.dev React library", "keywords": [ @@ -28,7 +28,7 @@ "test": "jest" }, "dependencies": { - "@clerk/types": "^2.0.0-alpha.8", + "@clerk/types": "^2.0.0-alpha.9", "tslib": "^2.3.1" }, "devDependencies": { diff --git a/packages/react/src/info.ts b/packages/react/src/info.ts index 8e6f56a518c..9bb9b9e0e4e 100644 --- a/packages/react/src/info.ts +++ b/packages/react/src/info.ts @@ -1,4 +1,4 @@ /** DO NOT EDIT: This file is automatically generated by ../scripts/info.js */ -export const LIB_VERSION='3.0.0-alpha.9'; +export const LIB_VERSION='3.0.0-alpha.10'; export const LIB_NAME='@clerk/clerk-react'; diff --git a/packages/remix/CHANGELOG.md b/packages/remix/CHANGELOG.md index 37540dd9890..cf808ff56ba 100644 --- a/packages/remix/CHANGELOG.md +++ b/packages/remix/CHANGELOG.md @@ -3,6 +3,23 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.0-alpha.6](https://github.com/clerkinc/javascript/compare/@clerk/remix@0.1.0-alpha.5...@clerk/remix@0.1.0-alpha.6) (2022-03-11) + + +### Features + +* **remix:** Better server error handling ([#95](https://github.com/clerkinc/javascript/issues/95)) ([4046b29](https://github.com/clerkinc/javascript/commit/4046b291bb93d0f7471138c067cce8cf84cac265)) +* **remix:** Build interstitial locally instead of fetching ([2dd5bb3](https://github.com/clerkinc/javascript/commit/2dd5bb35d532ce6c0d9f19d66d68672e748d4ed8)) +* **remix:** Pass frontendApi from rootAuthLoader ([46a6c47](https://github.com/clerkinc/javascript/commit/46a6c47e0a977219c403327416e6f885ce7cfa4e)) +* **remix:** Throw the insterstitial from ConnectClerkCatchBoundary ([7b07bf0](https://github.com/clerkinc/javascript/commit/7b07bf02c6d9cad695e184a473ba507271f61fc3)) + + +### Reverts + +* Revert "Revert "fix(remix): Make `getAuth` stop loader execution during interstitial"" ([a0935f3](https://github.com/clerkinc/javascript/commit/a0935f355ff403b10a7f9d3e76957ff39f98f779)) + + + ## [0.1.0-alpha.5](https://github.com/clerkinc/javascript/compare/@clerk/remix@0.1.0-alpha.4...@clerk/remix@0.1.0-alpha.5) (2022-02-28) diff --git a/packages/remix/package.json b/packages/remix/package.json index 5b38fc7e3eb..caff5954fe2 100644 --- a/packages/remix/package.json +++ b/packages/remix/package.json @@ -1,6 +1,6 @@ { "name": "@clerk/remix", - "version": "0.1.0-alpha.5", + "version": "0.1.0-alpha.6", "license": "MIT", "description": "Clerk.dev SDK for Remix", "keywords": [ @@ -32,9 +32,9 @@ "dev": "tsc -p tsconfig.build.json --watch" }, "dependencies": { - "@clerk/clerk-react": "^3.0.0-alpha.9", - "@clerk/clerk-sdk-node": "^2.9.0", - "@clerk/types": "^2.0.0-alpha.8", + "@clerk/clerk-react": "^3.0.0-alpha.10", + "@clerk/clerk-sdk-node": "^2.9.9-alpha.0", + "@clerk/types": "^2.0.0-alpha.9", "cookie": "^0.4.2", "tslib": "^2.3.1" }, diff --git a/packages/sdk-node/CHANGELOG.md b/packages/sdk-node/CHANGELOG.md index 711aa636350..88933726fad 100644 --- a/packages/sdk-node/CHANGELOG.md +++ b/packages/sdk-node/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +### [2.9.9-alpha.0](https://github.com/clerkinc/javascript/compare/@clerk/clerk-sdk-node@2.9.8...@clerk/clerk-sdk-node@2.9.9-alpha.0) (2022-03-11) + +**Note:** Version bump only for package @clerk/clerk-sdk-node + + + + + ### [2.9.8](https://github.com/clerkinc/javascript/compare/@clerk/clerk-sdk-node@2.9.7...@clerk/clerk-sdk-node@2.9.8) (2022-03-09) diff --git a/packages/sdk-node/package.json b/packages/sdk-node/package.json index 462428e305e..b9777829d58 100644 --- a/packages/sdk-node/package.json +++ b/packages/sdk-node/package.json @@ -1,5 +1,5 @@ { - "version": "2.9.8", + "version": "2.9.9-alpha.0", "license": "MIT", "main": "dist/index.js", "module": "esm/index.js", diff --git a/packages/sdk-node/src/info.ts b/packages/sdk-node/src/info.ts index aff8bff1ab2..163e4d2dd82 100644 --- a/packages/sdk-node/src/info.ts +++ b/packages/sdk-node/src/info.ts @@ -1,4 +1,4 @@ /** DO NOT EDIT: This file is automatically generated by ../scripts/info.js */ -export const LIB_VERSION="2.9.8"; +export const LIB_VERSION="2.9.9-alpha.0"; export const LIB_NAME="@clerk/clerk-sdk-node"; diff --git a/packages/shared/CHANGELOG.md b/packages/shared/CHANGELOG.md index 107771d912d..4be12068107 100644 --- a/packages/shared/CHANGELOG.md +++ b/packages/shared/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +### [0.0.6-alpha.2](https://github.com/clerkinc/clerk_docker/compare/@clerk/shared@0.0.12...@clerk/shared@0.0.6-alpha.2) (2022-03-11) + +**Note:** Version bump only for package @clerk/shared + + + + + ### [0.0.6-alpha.1](https://github.com/clerkinc/clerk_docker/compare/@clerk/shared@0.0.5...@clerk/shared@0.0.6-alpha.1) (2022-02-28) diff --git a/packages/shared/package.json b/packages/shared/package.json index 7ce6bc5f3ad..4aff5e2f59f 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -1,6 +1,6 @@ { "name": "@clerk/shared", - "version": "0.0.6-alpha.1", + "version": "0.0.6-alpha.2", "private": true, "main": "index.js", "module": "index.js", diff --git a/packages/types/CHANGELOG.md b/packages/types/CHANGELOG.md index e75d61e0543..68bb4d3a89c 100644 --- a/packages/types/CHANGELOG.md +++ b/packages/types/CHANGELOG.md @@ -3,6 +3,16 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.0.0-alpha.9](https://github.com/clerkinc/javascript/compare/@clerk/types@1.28.3...@clerk/types@2.0.0-alpha.9) (2022-03-11) + + +### Features + +* **nextjs:** Move shared NextJS SSR types to types package ([78d8c7c](https://github.com/clerkinc/javascript/commit/78d8c7c3e84f3926127e48c655793a0fca3cdc2c)) +* **types:** Support for oauth_apple ([57b675c](https://github.com/clerkinc/javascript/commit/57b675c762187d1f16cde6d2577bac71f7993438)) + + + ## [2.0.0-alpha.8](https://github.com/clerkinc/javascript/compare/@clerk/types@1.25.4...@clerk/types@2.0.0-alpha.8) (2022-02-28) diff --git a/packages/types/package.json b/packages/types/package.json index 84982a811d5..72520144c67 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@clerk/types", - "version": "2.0.0-alpha.8", + "version": "2.0.0-alpha.9", "license": "MIT", "description": "Typings for Clerk libraries.", "keywords": [