diff --git a/.changeset/wild-carrots-reply.md b/.changeset/wild-carrots-reply.md new file mode 100644 index 0000000000..fabaf13958 --- /dev/null +++ b/.changeset/wild-carrots-reply.md @@ -0,0 +1,61 @@ +--- +"@clerk/shared": major +--- + +The package was reworked to allow for better isomorphic use cases and ESM support, resulting in some breaking changes. It now allows for [subpath exports](https://nodejs.org/api/packages.html#subpath-exports) and restricts some imports to specific subpaths. + +Instead of importing from the root `@clerk/shared` import you can now use subpaths for most things: + +```diff +- import { deprecated, OrganizationProvider } from "@clerk/shared" ++ import { deprecated } from "@clerk/shared/deprecated" ++ import { OrganizationProvider } from "@clerk/shared/react" +``` + +By using subpaths you can tell bundlers to only bundle specific parts, potentially helping with tree-shaking. It also mitigates issues where e.g. modules only relevant for React where picked up in Node.js-only environments. + +If you're not using `@clerk/shared` directly (only by proxy through e.g. `@clerk/clerk-react`) you don't need to do anything. If you are relying on `@clerk/shared`, please read through the breaking changes below and change your code accordingly. You can rely on your IDE to give you hints on which exports are available at `@clerk/shared` and `@clerk/shared/` subpaths. + +**Breaking Changes** + +- `@clerk/shared` was and still is a dual CJS/ESM package. The ESM files provided by `@clerk/shared` now use `.mjs` file extensions and also define them in their import paths, following the ESM spec. Your bundler should handle this for you. +- Some imports where moved from the root `@clerk/shared` import to isolated subpaths. + - Helper utils for cookies and globs: + + ```diff + - import { createCookieHandler, globs } from "@clerk/shared" + + import { createCookieHandler } from "@clerk/shared/cookie" + + import { globs } from "@clerk/shared/globs" + ``` + - Everything related to React. Below is a small example and the full list of exports: + + ```diff + - import { useSafeLayoutEffect, ClerkInstanceContext } from "@clerk/shared" + + import { useSafeLayoutEffect, ClerkInstanceContext } from "@clerk/shared/react" + ``` + + Full list of exports moved to `@clerk/shared/react`: + + ```ts + export { + ClerkInstanceContext, + ClientContext, + OrganizationContext, + OrganizationProvider, + SessionContext, + UserContext, + assertContextExists, + createContextAndHook, + useClerkInstanceContext, + useClientContext, + useOrganization, + useOrganizationContext, + useOrganizationList, + useOrganizations, + useSafeLayoutEffect, + useSessionContext, + useUserContext + } + ``` + +If you run into an issues that might be a bug, please [open a bug report](https://github.com/clerkinc/javascript/issues/new?assignees=&labels=needs-triage&projects=&template=BUG_REPORT.yml) with a minimal reproduction. diff --git a/package-lock.json b/package-lock.json index 4f0b27f186..a7ca31b48c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32473,11 +32473,11 @@ }, "packages/backend": { "name": "@clerk/backend", - "version": "0.31.0", + "version": "0.31.1", "license": "MIT", "dependencies": { - "@clerk/shared": "0.24.4", - "@clerk/types": "3.55.0", + "@clerk/shared": "0.24.5", + "@clerk/types": "3.56.0", "@peculiar/webcrypto": "1.4.1", "@types/node": "16.18.6", "cookie": "0.5.0", @@ -32518,11 +32518,11 @@ }, "packages/chrome-extension": { "name": "@clerk/chrome-extension", - "version": "0.4.7", + "version": "0.4.8", "license": "MIT", "dependencies": { - "@clerk/clerk-js": "4.61.0", - "@clerk/clerk-react": "4.26.4" + "@clerk/clerk-js": "4.62.0", + "@clerk/clerk-react": "4.26.5" }, "devDependencies": { "@types/chrome": "*", @@ -32538,12 +32538,12 @@ }, "packages/clerk-js": { "name": "@clerk/clerk-js", - "version": "4.61.0", + "version": "4.62.0", "license": "MIT", "dependencies": { - "@clerk/localizations": "1.26.4", - "@clerk/shared": "0.24.4", - "@clerk/types": "3.55.0", + "@clerk/localizations": "1.26.5", + "@clerk/shared": "0.24.5", + "@clerk/types": "3.56.0", "@emotion/cache": "11.11.0", "@emotion/react": "11.11.1", "@floating-ui/react": "0.25.4", @@ -32877,17 +32877,17 @@ }, "packages/expo": { "name": "@clerk/clerk-expo", - "version": "0.19.9", + "version": "0.19.10", "license": "MIT", "dependencies": { - "@clerk/clerk-js": "4.61.0", - "@clerk/clerk-react": "4.26.4", - "@clerk/shared": "0.24.4", + "@clerk/clerk-js": "4.62.0", + "@clerk/clerk-react": "4.26.5", + "@clerk/shared": "0.24.5", "base-64": "1.0.0", "react-native-url-polyfill": "2.0.0" }, "devDependencies": { - "@clerk/types": "^3.55.0", + "@clerk/types": "^3.56.0", "@types/base-64": "^1.0.0", "@types/node": "^16.11.55", "@types/react": "*", @@ -32908,12 +32908,12 @@ }, "packages/fastify": { "name": "@clerk/fastify", - "version": "0.6.14", + "version": "0.6.15", "license": "MIT", "dependencies": { - "@clerk/backend": "0.31.0", - "@clerk/shared": "0.24.4", - "@clerk/types": "3.55.0", + "@clerk/backend": "0.31.1", + "@clerk/shared": "0.24.5", + "@clerk/types": "3.56.0", "cookies": "0.8.0" }, "devDependencies": { @@ -32929,13 +32929,13 @@ } }, "packages/gatsby-plugin-clerk": { - "version": "4.4.15", + "version": "4.4.16", "license": "MIT", "dependencies": { - "@clerk/backend": "0.31.0", - "@clerk/clerk-react": "4.26.4", - "@clerk/clerk-sdk-node": "4.12.13", - "@clerk/types": "3.55.0", + "@clerk/backend": "0.31.1", + "@clerk/clerk-react": "4.26.5", + "@clerk/clerk-sdk-node": "4.12.14", + "@clerk/types": "3.56.0", "cookie": "0.5.0", "tslib": "2.4.1" }, @@ -32958,10 +32958,10 @@ }, "packages/localizations": { "name": "@clerk/localizations", - "version": "1.26.4", + "version": "1.26.5", "license": "MIT", "dependencies": { - "@clerk/types": "3.55.0" + "@clerk/types": "3.56.0" }, "devDependencies": { "tsup": "*", @@ -32976,14 +32976,14 @@ }, "packages/nextjs": { "name": "@clerk/nextjs", - "version": "4.25.4", + "version": "4.25.5", "license": "MIT", "dependencies": { - "@clerk/backend": "0.31.0", - "@clerk/clerk-react": "4.26.4", - "@clerk/clerk-sdk-node": "4.12.13", - "@clerk/shared": "0.24.4", - "@clerk/types": "3.55.0", + "@clerk/backend": "0.31.1", + "@clerk/clerk-react": "4.26.5", + "@clerk/clerk-sdk-node": "4.12.14", + "@clerk/shared": "0.24.5", + "@clerk/types": "3.56.0", "path-to-regexp": "6.2.1", "tslib": "2.4.1" }, @@ -33015,11 +33015,11 @@ }, "packages/react": { "name": "@clerk/clerk-react", - "version": "4.26.4", + "version": "4.26.5", "license": "MIT", "dependencies": { - "@clerk/shared": "0.24.4", - "@clerk/types": "3.55.0", + "@clerk/shared": "0.24.5", + "@clerk/types": "3.56.0", "tslib": "2.4.1" }, "devDependencies": { @@ -33041,13 +33041,13 @@ }, "packages/remix": { "name": "@clerk/remix", - "version": "3.0.6", + "version": "3.0.7", "license": "MIT", "dependencies": { - "@clerk/backend": "0.31.0", - "@clerk/clerk-react": "4.26.4", - "@clerk/shared": "0.24.4", - "@clerk/types": "3.55.0", + "@clerk/backend": "0.31.1", + "@clerk/clerk-react": "4.26.5", + "@clerk/shared": "0.24.5", + "@clerk/types": "3.56.0", "cookie": "0.5.0", "tslib": "2.4.1" }, @@ -33076,12 +33076,12 @@ }, "packages/sdk-node": { "name": "@clerk/clerk-sdk-node", - "version": "4.12.13", + "version": "4.12.14", "license": "MIT", "dependencies": { - "@clerk/backend": "0.31.0", - "@clerk/shared": "0.24.4", - "@clerk/types": "3.55.0", + "@clerk/backend": "0.31.1", + "@clerk/shared": "0.24.5", + "@clerk/types": "3.56.0", "@types/cookies": "0.7.7", "@types/express": "4.17.14", "@types/node-fetch": "2.6.2", @@ -33117,7 +33117,7 @@ }, "packages/shared": { "name": "@clerk/shared", - "version": "0.24.4", + "version": "0.24.5", "license": "MIT", "dependencies": { "glob-to-regexp": "0.4.1", @@ -33125,7 +33125,7 @@ "swr": "2.2.0" }, "devDependencies": { - "@clerk/types": "3.55.0", + "@clerk/types": "3.56.0", "@types/glob-to-regexp": "0.4.1", "@types/js-cookie": "3.0.2", "tsup": "*", @@ -33142,10 +33142,10 @@ }, "packages/themes": { "name": "@clerk/themes", - "version": "1.7.7", + "version": "1.7.8", "license": "MIT", "devDependencies": { - "@clerk/types": "3.55.0", + "@clerk/types": "3.56.0", "typescript": "*" }, "engines": { @@ -33157,7 +33157,7 @@ }, "packages/types": { "name": "@clerk/types", - "version": "3.55.0", + "version": "3.56.0", "license": "MIT", "dependencies": { "csstype": "3.1.1" diff --git a/packages/backend/src/api/endpoints/OrganizationApi.ts b/packages/backend/src/api/endpoints/OrganizationApi.ts index e8427747f4..7ac2435fcb 100644 --- a/packages/backend/src/api/endpoints/OrganizationApi.ts +++ b/packages/backend/src/api/endpoints/OrganizationApi.ts @@ -1,4 +1,4 @@ -import { deprecated } from '@clerk/shared'; +import { deprecated } from '@clerk/shared/deprecated'; import runtime from '../../runtime'; import { joinPaths } from '../../util/path'; diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index 9879546c9e..0d1a552ca2 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -1,4 +1,4 @@ -import { deprecatedObjectProperty } from '@clerk/shared'; +import { deprecatedObjectProperty } from '@clerk/shared/deprecated'; import type { CreateBackendApiOptions } from './api'; import { createBackendApiClient } from './api'; diff --git a/packages/backend/src/runtime/index.ts b/packages/backend/src/runtime/index.ts index 7636f93eb0..f77338cb6d 100644 --- a/packages/backend/src/runtime/index.ts +++ b/packages/backend/src/runtime/index.ts @@ -12,9 +12,9 @@ * TODO: Support TS runtime modules */ -// @ts-expect-error +// @ts-ignore - These are package subpaths import crypto from '#crypto'; -// @ts-expect-error +// @ts-ignore - These are package subpaths import * as fetchApisPolyfill from '#fetch'; const { diff --git a/packages/backend/src/tokens/authObjects.ts b/packages/backend/src/tokens/authObjects.ts index bd2e5bcb72..ccecdd637b 100644 --- a/packages/backend/src/tokens/authObjects.ts +++ b/packages/backend/src/tokens/authObjects.ts @@ -1,4 +1,4 @@ -import { deprecated } from '@clerk/shared'; +import { deprecated } from '@clerk/shared/deprecated'; import type { ActClaim, JwtPayload, ServerGetToken, ServerGetTokenOptions } from '@clerk/types'; import type { Organization, Session, User } from '../api'; diff --git a/packages/backend/src/tokens/jwt/verifyJwt.ts b/packages/backend/src/tokens/jwt/verifyJwt.ts index b5ab9f5e93..164a1a9a11 100644 --- a/packages/backend/src/tokens/jwt/verifyJwt.ts +++ b/packages/backend/src/tokens/jwt/verifyJwt.ts @@ -1,4 +1,4 @@ -import { deprecatedObjectProperty } from '@clerk/shared'; +import { deprecatedObjectProperty } from '@clerk/shared/deprecated'; import type { Jwt, JwtPayload } from '@clerk/types'; // DO NOT CHANGE: Runtime needs to be imported as a default export so that we can stub its dependencies with Sinon.js diff --git a/packages/backend/src/util/shared.ts b/packages/backend/src/util/shared.ts index de2bd9a6ae..1b4d09e38a 100644 --- a/packages/backend/src/util/shared.ts +++ b/packages/backend/src/util/shared.ts @@ -6,11 +6,10 @@ export { isDevelopmentFromApiKey, isProductionFromApiKey, parsePublishableKey, - deprecated, - deprecatedProperty, } from '@clerk/shared'; +export { deprecated, deprecatedProperty } from '@clerk/shared/deprecated'; -import { buildErrorThrower } from '@clerk/shared'; +import { buildErrorThrower } from '@clerk/shared/error'; // TODO: replace packageName with `${PACKAGE_NAME}@${PACKAGE_VERSION}` from tsup.config.ts export const errorThrower = buildErrorThrower({ packageName: '@clerk/backend' }); diff --git a/packages/backend/tsconfig.json b/packages/backend/tsconfig.json index 94d7f5aae5..6c79dfa9a5 100644 --- a/packages/backend/tsconfig.json +++ b/packages/backend/tsconfig.json @@ -2,12 +2,14 @@ "compilerOptions": { "allowSyntheticDefaultImports": true, "baseUrl": ".", + "rootDir": "src", "declaration": true, "declarationMap": false, "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "importHelpers": true, - "moduleResolution": "node", + "moduleResolution": "NodeNext", + "module": "NodeNext", "noImplicitReturns": true, "noUnusedLocals": false, "noUnusedParameters": true, diff --git a/packages/backend/tsconfig.test.json b/packages/backend/tsconfig.test.json index f3c144d470..c1959296aa 100644 --- a/packages/backend/tsconfig.test.json +++ b/packages/backend/tsconfig.test.json @@ -7,7 +7,10 @@ "moduleResolution": "Node", "noImplicitAny": false, "outDir": "./tests/dist", - "target": "ES2020" + "target": "ES2020", + "paths": { + "@clerk/shared/*": ["../shared/dist/*.js"] + } }, "include": ["src/**/*.test.ts"], "exclude": ["node_modules", "dist", "src/__tests__"] diff --git a/packages/clerk-js/src/core/clerk.ts b/packages/clerk-js/src/core/clerk.ts index c12f4aebe5..e371105201 100644 --- a/packages/clerk-js/src/core/clerk.ts +++ b/packages/clerk-js/src/core/clerk.ts @@ -3,7 +3,7 @@ import { addClerkPrefix, deprecated, handleValueOrFn, - inClientSide, + inBrowser as inClientSide, is4xxError, isHttpOrHttps, isLegacyFrontendApiKey, diff --git a/packages/clerk-js/src/core/resources/Base.ts b/packages/clerk-js/src/core/resources/Base.ts index 04a5112a9d..7f032cd8c4 100644 --- a/packages/clerk-js/src/core/resources/Base.ts +++ b/packages/clerk-js/src/core/resources/Base.ts @@ -1,4 +1,4 @@ -import { isValidBrowserOnline } from '@clerk/shared'; +import { isValidBrowserOnline } from '@clerk/shared/browser'; import type { ClerkAPIErrorJSON, ClerkResourceJSON, ClerkResourceReloadParams, DeletedObjectJSON } from '@clerk/types'; import { clerkMissingFapiClientInResources } from '../errors'; diff --git a/packages/clerk-js/src/core/resources/DisplayConfig.ts b/packages/clerk-js/src/core/resources/DisplayConfig.ts index ee83cca78a..5a2313b69c 100644 --- a/packages/clerk-js/src/core/resources/DisplayConfig.ts +++ b/packages/clerk-js/src/core/resources/DisplayConfig.ts @@ -1,4 +1,4 @@ -import { deprecatedProperty } from '@clerk/shared'; +import { deprecatedProperty } from '@clerk/shared/deprecated'; import type { DisplayConfigJSON, DisplayConfigResource, DisplayThemeJSON, PreferredSignInStrategy } from '@clerk/types'; import { BaseResource } from './internal'; diff --git a/packages/clerk-js/src/core/resources/EmailAddress.ts b/packages/clerk-js/src/core/resources/EmailAddress.ts index 340fb620ee..2dbf00cd2a 100644 --- a/packages/clerk-js/src/core/resources/EmailAddress.ts +++ b/packages/clerk-js/src/core/resources/EmailAddress.ts @@ -1,4 +1,5 @@ -import { deprecated, Poller } from '@clerk/shared'; +import { deprecated } from '@clerk/shared/deprecated'; +import { Poller } from '@clerk/shared/poller'; import type { AttemptEmailAddressVerificationParams, CreateEmailLinkFlowReturn, diff --git a/packages/clerk-js/src/core/resources/Error.ts b/packages/clerk-js/src/core/resources/Error.ts index b659a38014..a8baf8742a 100644 --- a/packages/clerk-js/src/core/resources/Error.ts +++ b/packages/clerk-js/src/core/resources/Error.ts @@ -13,5 +13,5 @@ export { MagicLinkErrorCode, parseError, parseErrors, -} from '@clerk/shared'; -export type { MetamaskError } from '@clerk/shared'; +} from '@clerk/shared/error'; +export type { MetamaskError } from '@clerk/shared/error'; diff --git a/packages/clerk-js/src/core/resources/Organization.ts b/packages/clerk-js/src/core/resources/Organization.ts index 29019b8d8b..5a8e8c2b6b 100644 --- a/packages/clerk-js/src/core/resources/Organization.ts +++ b/packages/clerk-js/src/core/resources/Organization.ts @@ -1,4 +1,4 @@ -import { deprecated, deprecatedProperty } from '@clerk/shared'; +import { deprecated, deprecatedProperty } from '@clerk/shared/deprecated'; import type { AddMemberParams, ClerkPaginatedResponse, diff --git a/packages/clerk-js/src/core/resources/OrganizationMembership.ts b/packages/clerk-js/src/core/resources/OrganizationMembership.ts index c96b484cdc..0a4c188f6e 100644 --- a/packages/clerk-js/src/core/resources/OrganizationMembership.ts +++ b/packages/clerk-js/src/core/resources/OrganizationMembership.ts @@ -1,4 +1,4 @@ -import { deprecated } from '@clerk/shared'; +import { deprecated } from '@clerk/shared/deprecated'; import type { ClerkPaginatedResponse, ClerkResourceReloadParams, diff --git a/packages/clerk-js/src/core/resources/PublicUserData.ts b/packages/clerk-js/src/core/resources/PublicUserData.ts index a3de715ab7..7fd6e93de6 100644 --- a/packages/clerk-js/src/core/resources/PublicUserData.ts +++ b/packages/clerk-js/src/core/resources/PublicUserData.ts @@ -1,4 +1,4 @@ -import { deprecatedProperty } from '@clerk/shared'; +import { deprecatedProperty } from '@clerk/shared/deprecated'; import type { PublicUserData as IPublicUserData } from '@clerk/types'; import type { PublicUserDataJSON } from '@clerk/types'; diff --git a/packages/clerk-js/src/core/resources/Session.ts b/packages/clerk-js/src/core/resources/Session.ts index c8acaac84e..b719060194 100644 --- a/packages/clerk-js/src/core/resources/Session.ts +++ b/packages/clerk-js/src/core/resources/Session.ts @@ -1,5 +1,5 @@ -import { is4xxError } from '@clerk/shared'; import { runWithExponentialBackOff } from '@clerk/shared'; +import { is4xxError } from '@clerk/shared/error'; import type { ActJWTClaim, GetToken, @@ -70,6 +70,8 @@ export class Session extends BaseResource implements SessionResource { return SessionTokenCache.clear(); }; + // TODO: Fix this eslint error + // eslint-disable-next-line @typescript-eslint/require-await getToken: GetToken = async (options?: GetTokenOptions): Promise => { return runWithExponentialBackOff(() => this._getToken(options), { shouldRetry: (error: unknown, currentIteration: number) => !is4xxError(error) && currentIteration < 4, diff --git a/packages/clerk-js/src/core/resources/User.ts b/packages/clerk-js/src/core/resources/User.ts index 99ac453716..3733a32429 100644 --- a/packages/clerk-js/src/core/resources/User.ts +++ b/packages/clerk-js/src/core/resources/User.ts @@ -1,5 +1,4 @@ -import { deprecated } from '@clerk/shared'; -import { deprecatedProperty } from '@clerk/shared'; +import { deprecated, deprecatedProperty } from '@clerk/shared/deprecated'; import type { BackupCodeJSON, BackupCodeResource, diff --git a/packages/clerk-js/src/core/resources/UserData.ts b/packages/clerk-js/src/core/resources/UserData.ts index f19e284d24..00dfa60e2d 100644 --- a/packages/clerk-js/src/core/resources/UserData.ts +++ b/packages/clerk-js/src/core/resources/UserData.ts @@ -1,4 +1,4 @@ -import { deprecatedProperty } from '@clerk/shared'; +import { deprecatedProperty } from '@clerk/shared/deprecated'; import type { UserData as IUserData } from '@clerk/types'; import type { UserDataJSON } from '@clerk/types'; diff --git a/packages/clerk-js/src/core/resources/Web3Wallet.ts b/packages/clerk-js/src/core/resources/Web3Wallet.ts index 3359495db5..3386a077b9 100644 --- a/packages/clerk-js/src/core/resources/Web3Wallet.ts +++ b/packages/clerk-js/src/core/resources/Web3Wallet.ts @@ -1,4 +1,4 @@ -import { deprecated } from '@clerk/shared'; +import { deprecated } from '@clerk/shared/deprecated'; import type { AttemptWeb3WalletVerificationParams, PrepareWeb3WalletVerificationParams, diff --git a/packages/clerk-js/src/core/services/authentication/SessionCookieService.ts b/packages/clerk-js/src/core/services/authentication/SessionCookieService.ts index 9fdde1428d..ad75670e4b 100644 --- a/packages/clerk-js/src/core/services/authentication/SessionCookieService.ts +++ b/packages/clerk-js/src/core/services/authentication/SessionCookieService.ts @@ -1,6 +1,4 @@ -import { isClerkAPIResponseError } from '@clerk/shared'; -import { isNetworkError } from '@clerk/shared'; -import { is4xxError } from '@clerk/shared'; +import { is4xxError, isClerkAPIResponseError, isNetworkError } from '@clerk/shared/error'; import type { Clerk, EnvironmentResource, SessionResource, TokenResource } from '@clerk/types'; import type { CookieHandler } from '../../../utils'; diff --git a/packages/clerk-js/src/ui/Components.tsx b/packages/clerk-js/src/ui/Components.tsx index c6df252b7a..c21c106eed 100644 --- a/packages/clerk-js/src/ui/Components.tsx +++ b/packages/clerk-js/src/ui/Components.tsx @@ -1,4 +1,5 @@ -import { createDeferredPromise, useSafeLayoutEffect } from '@clerk/shared'; +import { createDeferredPromise } from '@clerk/shared'; +import { useSafeLayoutEffect } from '@clerk/shared/react'; import type { Appearance, Clerk, diff --git a/packages/clerk-js/src/ui/common/EmailLinkVerify.tsx b/packages/clerk-js/src/ui/common/EmailLinkVerify.tsx index 188eee35a6..9c20e2ce05 100644 --- a/packages/clerk-js/src/ui/common/EmailLinkVerify.tsx +++ b/packages/clerk-js/src/ui/common/EmailLinkVerify.tsx @@ -1,4 +1,4 @@ -import { EmailLinkErrorCode, isEmailLinkError } from '@clerk/shared'; +import { EmailLinkErrorCode, isEmailLinkError } from '@clerk/shared/error'; import React from 'react'; import type { VerificationStatus } from '../../utils/getClerkQueryParam'; diff --git a/packages/clerk-js/src/ui/common/__tests__/verification.test.ts b/packages/clerk-js/src/ui/common/__tests__/verification.test.ts index 5f76b4e780..6cb7970a46 100644 --- a/packages/clerk-js/src/ui/common/__tests__/verification.test.ts +++ b/packages/clerk-js/src/ui/common/__tests__/verification.test.ts @@ -1,4 +1,4 @@ -import { ClerkAPIResponseError } from '@clerk/shared'; +import { ClerkAPIResponseError } from '@clerk/shared/error'; import { isVerificationExpiredError, VerificationErrorMessage, verificationErrorMessage } from '../verification'; diff --git a/packages/clerk-js/src/ui/common/constants.ts b/packages/clerk-js/src/ui/common/constants.ts index 6ed53f9888..a4e9d3165b 100644 --- a/packages/clerk-js/src/ui/common/constants.ts +++ b/packages/clerk-js/src/ui/common/constants.ts @@ -1,4 +1,4 @@ -import { deprecated } from '@clerk/shared'; +import { deprecated } from '@clerk/shared/deprecated'; import type { Attribute, Web3Provider } from '@clerk/types'; import type { LocalizationKey } from '../localization/localizationKeys'; diff --git a/packages/clerk-js/src/ui/components/OrganizationProfile/InviteMembersForm.tsx b/packages/clerk-js/src/ui/components/OrganizationProfile/InviteMembersForm.tsx index 1cabd921aa..c8924e7120 100644 --- a/packages/clerk-js/src/ui/components/OrganizationProfile/InviteMembersForm.tsx +++ b/packages/clerk-js/src/ui/components/OrganizationProfile/InviteMembersForm.tsx @@ -1,4 +1,4 @@ -import { isClerkAPIResponseError } from '@clerk/shared'; +import { isClerkAPIResponseError } from '@clerk/shared/error'; import type { ClerkAPIError, MembershipRole, OrganizationResource } from '@clerk/types'; import React from 'react'; diff --git a/packages/clerk-js/src/ui/components/UserButton/useMultisessionActions.tsx b/packages/clerk-js/src/ui/components/UserButton/useMultisessionActions.tsx index 696982a244..ab6430e2a0 100644 --- a/packages/clerk-js/src/ui/components/UserButton/useMultisessionActions.tsx +++ b/packages/clerk-js/src/ui/components/UserButton/useMultisessionActions.tsx @@ -1,4 +1,4 @@ -import { deprecatedObjectProperty } from '@clerk/shared'; +import { deprecatedObjectProperty } from '@clerk/shared/deprecated'; import type { ActiveSessionResource, UserButtonProps, UserResource } from '@clerk/types'; import { windowNavigate } from '../../../utils/windowNavigate'; @@ -64,6 +64,8 @@ export const useMultisessionActions = (opts: UseMultisessionActionsParams) => { return signOut(opts.navigateAfterSignOut); }; + // TODO: Fix this eslint error + // eslint-disable-next-line @typescript-eslint/require-await const handleSessionClicked = (session: ActiveSessionResource) => async () => { card.setLoading(); return setActive({ session, beforeEmit: opts.navigateAfterSwitchSession }).finally(() => { diff --git a/packages/clerk-js/src/ui/contexts/CoreClerkContext.tsx b/packages/clerk-js/src/ui/contexts/CoreClerkContext.tsx index 6e32523bc4..66b28dd85f 100644 --- a/packages/clerk-js/src/ui/contexts/CoreClerkContext.tsx +++ b/packages/clerk-js/src/ui/contexts/CoreClerkContext.tsx @@ -1,3 +1,3 @@ -import { ClerkInstanceContext, useClerkInstanceContext } from '@clerk/shared'; +import { ClerkInstanceContext, useClerkInstanceContext } from '@clerk/shared/react'; export const [CoreClerkContext, useCoreClerk] = [ClerkInstanceContext, useClerkInstanceContext]; diff --git a/packages/clerk-js/src/ui/contexts/CoreClientContext.tsx b/packages/clerk-js/src/ui/contexts/CoreClientContext.tsx index 30864cd3ce..b0d5ad7a42 100644 --- a/packages/clerk-js/src/ui/contexts/CoreClientContext.tsx +++ b/packages/clerk-js/src/ui/contexts/CoreClientContext.tsx @@ -1,4 +1,4 @@ -import { assertContextExists, ClientContext, useClientContext } from '@clerk/shared'; +import { assertContextExists, ClientContext, useClientContext } from '@clerk/shared/react'; import type { SessionResource, SignInResource, SignUpResource } from '@clerk/types'; export const CoreClientContext = ClientContext; diff --git a/packages/clerk-js/src/ui/contexts/CoreOrganizationContext.tsx b/packages/clerk-js/src/ui/contexts/CoreOrganizationContext.tsx index 5ece45ac17..5f093f521f 100644 --- a/packages/clerk-js/src/ui/contexts/CoreOrganizationContext.tsx +++ b/packages/clerk-js/src/ui/contexts/CoreOrganizationContext.tsx @@ -1,4 +1,4 @@ -import { OrganizationProvider, useOrganization, useOrganizationList, useOrganizations } from '@clerk/shared'; +import { OrganizationProvider, useOrganization, useOrganizationList, useOrganizations } from '@clerk/shared/react'; export const CoreOrganizationProvider = OrganizationProvider; export const useCoreOrganization = useOrganization; diff --git a/packages/clerk-js/src/ui/contexts/CoreSessionContext.tsx b/packages/clerk-js/src/ui/contexts/CoreSessionContext.tsx index d8f4e3f605..3cd86e17c6 100644 --- a/packages/clerk-js/src/ui/contexts/CoreSessionContext.tsx +++ b/packages/clerk-js/src/ui/contexts/CoreSessionContext.tsx @@ -1,4 +1,4 @@ -import { assertContextExists, SessionContext, useSessionContext } from '@clerk/shared'; +import { assertContextExists, SessionContext, useSessionContext } from '@clerk/shared/react'; import type { SessionResource } from '@clerk/types'; import React from 'react'; diff --git a/packages/clerk-js/src/ui/contexts/CoreUserContext.tsx b/packages/clerk-js/src/ui/contexts/CoreUserContext.tsx index 350b915f3b..6936128b80 100644 --- a/packages/clerk-js/src/ui/contexts/CoreUserContext.tsx +++ b/packages/clerk-js/src/ui/contexts/CoreUserContext.tsx @@ -1,4 +1,4 @@ -import { assertContextExists, UserContext, useUserContext } from '@clerk/shared'; +import { assertContextExists, UserContext, useUserContext } from '@clerk/shared/react'; import React, { useContext } from 'react'; import { clerkCoreErrorUserIsNotDefined } from '../../core/errors'; diff --git a/packages/clerk-js/src/ui/customizables/AppearanceContext.tsx b/packages/clerk-js/src/ui/customizables/AppearanceContext.tsx index 91f6b8296c..201edc9cab 100644 --- a/packages/clerk-js/src/ui/customizables/AppearanceContext.tsx +++ b/packages/clerk-js/src/ui/customizables/AppearanceContext.tsx @@ -1,4 +1,4 @@ -import { createContextAndHook } from '@clerk/shared'; +import { createContextAndHook } from '@clerk/shared/react'; import React from 'react'; import { useDeepEqualMemo } from '../hooks'; diff --git a/packages/clerk-js/src/ui/elements/Form.tsx b/packages/clerk-js/src/ui/elements/Form.tsx index 657f1c2425..012b02482b 100644 --- a/packages/clerk-js/src/ui/elements/Form.tsx +++ b/packages/clerk-js/src/ui/elements/Form.tsx @@ -1,4 +1,4 @@ -import { createContextAndHook } from '@clerk/shared'; +import { createContextAndHook } from '@clerk/shared/react'; import type { FieldId } from '@clerk/types'; import React, { useState } from 'react'; diff --git a/packages/clerk-js/src/ui/elements/Menu.tsx b/packages/clerk-js/src/ui/elements/Menu.tsx index 2eeaa3a2ac..4d6f2f64bd 100644 --- a/packages/clerk-js/src/ui/elements/Menu.tsx +++ b/packages/clerk-js/src/ui/elements/Menu.tsx @@ -1,4 +1,4 @@ -import { createContextAndHook } from '@clerk/shared'; +import { createContextAndHook } from '@clerk/shared/react'; import type { MenuId } from '@clerk/types'; import type { PropsWithChildren } from 'react'; import React, { cloneElement, isValidElement, useLayoutEffect, useRef } from 'react'; diff --git a/packages/clerk-js/src/ui/elements/Modal.tsx b/packages/clerk-js/src/ui/elements/Modal.tsx index af4f568a75..290351a471 100644 --- a/packages/clerk-js/src/ui/elements/Modal.tsx +++ b/packages/clerk-js/src/ui/elements/Modal.tsx @@ -1,4 +1,4 @@ -import { createContextAndHook, useSafeLayoutEffect } from '@clerk/shared'; +import { createContextAndHook, useSafeLayoutEffect } from '@clerk/shared/react'; import React, { useRef } from 'react'; import { descriptors, Flex } from '../customizables'; diff --git a/packages/clerk-js/src/ui/elements/Navbar.tsx b/packages/clerk-js/src/ui/elements/Navbar.tsx index d80eeb1d17..4f348f2c4d 100644 --- a/packages/clerk-js/src/ui/elements/Navbar.tsx +++ b/packages/clerk-js/src/ui/elements/Navbar.tsx @@ -1,4 +1,4 @@ -import { createContextAndHook, useSafeLayoutEffect } from '@clerk/shared'; +import { createContextAndHook, useSafeLayoutEffect } from '@clerk/shared/react'; import type { NavbarItemId } from '@clerk/types'; import React, { useEffect } from 'react'; diff --git a/packages/clerk-js/src/ui/elements/Select.tsx b/packages/clerk-js/src/ui/elements/Select.tsx index f081b51527..52813e4f4f 100644 --- a/packages/clerk-js/src/ui/elements/Select.tsx +++ b/packages/clerk-js/src/ui/elements/Select.tsx @@ -1,4 +1,4 @@ -import { createContextAndHook } from '@clerk/shared'; +import { createContextAndHook } from '@clerk/shared/react'; import type { SelectId } from '@clerk/types'; import type { PropsWithChildren, ReactElement } from 'react'; import React, { useState } from 'react'; diff --git a/packages/clerk-js/src/ui/elements/Tabs.tsx b/packages/clerk-js/src/ui/elements/Tabs.tsx index 9e34c8b0e5..4b38e24482 100644 --- a/packages/clerk-js/src/ui/elements/Tabs.tsx +++ b/packages/clerk-js/src/ui/elements/Tabs.tsx @@ -1,4 +1,4 @@ -import { createContextAndHook } from '@clerk/shared'; +import { createContextAndHook } from '@clerk/shared/react'; import type { PropsWithChildren } from 'react'; import React from 'react'; diff --git a/packages/clerk-js/src/ui/elements/TimerButton.tsx b/packages/clerk-js/src/ui/elements/TimerButton.tsx index f4496095ba..eebcb538cf 100644 --- a/packages/clerk-js/src/ui/elements/TimerButton.tsx +++ b/packages/clerk-js/src/ui/elements/TimerButton.tsx @@ -1,4 +1,4 @@ -import { useSafeLayoutEffect } from '@clerk/shared'; +import { useSafeLayoutEffect } from '@clerk/shared/react'; import React, { useEffect } from 'react'; import { Button, useLocalizations } from '../customizables'; diff --git a/packages/clerk-js/src/ui/elements/contexts/CardStateContext.tsx b/packages/clerk-js/src/ui/elements/contexts/CardStateContext.tsx index 2381e51b61..744c080e53 100644 --- a/packages/clerk-js/src/ui/elements/contexts/CardStateContext.tsx +++ b/packages/clerk-js/src/ui/elements/contexts/CardStateContext.tsx @@ -1,4 +1,4 @@ -import { createContextAndHook } from '@clerk/shared'; +import { createContextAndHook } from '@clerk/shared/react'; import type { ClerkAPIError, ClerkRuntimeError } from '@clerk/types'; import React from 'react'; diff --git a/packages/clerk-js/src/ui/elements/contexts/FlowMetadataContext.tsx b/packages/clerk-js/src/ui/elements/contexts/FlowMetadataContext.tsx index f547b49fa7..35bcd088af 100644 --- a/packages/clerk-js/src/ui/elements/contexts/FlowMetadataContext.tsx +++ b/packages/clerk-js/src/ui/elements/contexts/FlowMetadataContext.tsx @@ -1,4 +1,4 @@ -import { createContextAndHook } from '@clerk/shared'; +import { createContextAndHook } from '@clerk/shared/react'; import React from 'react'; type FlowMetadata = { diff --git a/packages/clerk-js/src/ui/localization/makeLocalizable.tsx b/packages/clerk-js/src/ui/localization/makeLocalizable.tsx index 11f6c9748b..96f4604ed9 100644 --- a/packages/clerk-js/src/ui/localization/makeLocalizable.tsx +++ b/packages/clerk-js/src/ui/localization/makeLocalizable.tsx @@ -1,4 +1,4 @@ -import { isClerkRuntimeError } from '@clerk/shared'; +import { isClerkRuntimeError } from '@clerk/shared/error'; import type { ClerkAPIError, ClerkRuntimeError, LocalizationResource } from '@clerk/types'; import React from 'react'; diff --git a/packages/clerk-js/src/ui/primitives/hooks/useFormControl.tsx b/packages/clerk-js/src/ui/primitives/hooks/useFormControl.tsx index a739218249..0fb370722f 100644 --- a/packages/clerk-js/src/ui/primitives/hooks/useFormControl.tsx +++ b/packages/clerk-js/src/ui/primitives/hooks/useFormControl.tsx @@ -1,4 +1,4 @@ -import { createContextAndHook } from '@clerk/shared'; +import { createContextAndHook } from '@clerk/shared/react'; import type { ClerkAPIError } from '@clerk/types'; import React from 'react'; diff --git a/packages/clerk-js/src/ui/styledSystem/types.ts b/packages/clerk-js/src/ui/styledSystem/types.ts index 14496171f3..082f6ab0e1 100644 --- a/packages/clerk-js/src/ui/styledSystem/types.ts +++ b/packages/clerk-js/src/ui/styledSystem/types.ts @@ -13,7 +13,7 @@ type StyleRule = Exclude<_Interpolation, string | number | boolea type ThemableCssProp = ((params: InternalTheme) => StyleRule) | StyleRule; type CssProp = { css?: ThemableCssProp }; -export type AsProp = { as?: React.ElementType }; +export type AsProp = { as?: React.ElementType | undefined }; type ElementProps = { div: React.JSX.IntrinsicElements['div']; diff --git a/packages/clerk-js/src/utils/captcha.ts b/packages/clerk-js/src/utils/captcha.ts index 079817108a..69ab5fbc7c 100644 --- a/packages/clerk-js/src/utils/captcha.ts +++ b/packages/clerk-js/src/utils/captcha.ts @@ -1,4 +1,4 @@ -import { loadScript } from '@clerk/shared'; +import { loadScript } from '@clerk/shared/loadScript'; import { clerkFailedToLoadThirdPartyScript } from '../core/errors'; diff --git a/packages/clerk-js/src/utils/cookies/client.ts b/packages/clerk-js/src/utils/cookies/client.ts index 60ce9cd82c..e1b96625bc 100644 --- a/packages/clerk-js/src/utils/cookies/client.ts +++ b/packages/clerk-js/src/utils/cookies/client.ts @@ -1,4 +1,4 @@ -import { createCookieHandler } from '@clerk/shared'; +import { createCookieHandler } from '@clerk/shared/cookie'; const CLIENT_COOKIE_NAME = '__client'; diff --git a/packages/clerk-js/src/utils/cookies/client_uat.ts b/packages/clerk-js/src/utils/cookies/client_uat.ts index c214efdddd..7125b9e426 100644 --- a/packages/clerk-js/src/utils/cookies/client_uat.ts +++ b/packages/clerk-js/src/utils/cookies/client_uat.ts @@ -1,4 +1,4 @@ -import { createCookieHandler } from '@clerk/shared'; +import { createCookieHandler } from '@clerk/shared/cookie'; const CLIENT_UAT_COOKIE_NAME = '__client_uat'; diff --git a/packages/clerk-js/src/utils/cookies/devBrowser.ts b/packages/clerk-js/src/utils/cookies/devBrowser.ts index 946ca497d0..849d2aef37 100644 --- a/packages/clerk-js/src/utils/cookies/devBrowser.ts +++ b/packages/clerk-js/src/utils/cookies/devBrowser.ts @@ -1,4 +1,4 @@ -import { createCookieHandler } from '@clerk/shared'; +import { createCookieHandler } from '@clerk/shared/cookie'; import { DEV_BROWSER_JWT_MARKER } from '../devBrowser'; diff --git a/packages/clerk-js/src/utils/cookies/initted.ts b/packages/clerk-js/src/utils/cookies/initted.ts index 42dcad0268..16db5a4be0 100644 --- a/packages/clerk-js/src/utils/cookies/initted.ts +++ b/packages/clerk-js/src/utils/cookies/initted.ts @@ -1,4 +1,4 @@ -import { createCookieHandler } from '@clerk/shared'; +import { createCookieHandler } from '@clerk/shared/cookie'; const INITTED_COOKIE_NAME = '__initted'; diff --git a/packages/clerk-js/src/utils/cookies/session.ts b/packages/clerk-js/src/utils/cookies/session.ts index 222d0af611..34c8872eeb 100644 --- a/packages/clerk-js/src/utils/cookies/session.ts +++ b/packages/clerk-js/src/utils/cookies/session.ts @@ -1,4 +1,4 @@ -import { createCookieHandler } from '@clerk/shared'; +import { createCookieHandler } from '@clerk/shared/cookie'; const SESSION_COOKIE_NAME = '__session'; diff --git a/packages/clerk-js/src/utils/errorThrower.ts b/packages/clerk-js/src/utils/errorThrower.ts index b3d4f97263..b2c4437b31 100644 --- a/packages/clerk-js/src/utils/errorThrower.ts +++ b/packages/clerk-js/src/utils/errorThrower.ts @@ -1,4 +1,4 @@ -import { buildErrorThrower } from '@clerk/shared'; +import { buildErrorThrower } from '@clerk/shared/error'; const errorThrower = buildErrorThrower({ packageName: __PKG_NAME__ }); diff --git a/packages/clerk-js/src/utils/image.ts b/packages/clerk-js/src/utils/image.ts index 0b8ccf701f..12006582a1 100644 --- a/packages/clerk-js/src/utils/image.ts +++ b/packages/clerk-js/src/utils/image.ts @@ -1,4 +1,4 @@ -import { isomorphicAtob } from '@clerk/shared'; +import { isomorphicAtob } from '@clerk/shared/isomorphicAtob'; /** * @private diff --git a/packages/clerk-js/src/utils/jwt.ts b/packages/clerk-js/src/utils/jwt.ts index 2177dbd4c0..e0f96218e7 100644 --- a/packages/clerk-js/src/utils/jwt.ts +++ b/packages/clerk-js/src/utils/jwt.ts @@ -1,4 +1,4 @@ -import { deprecatedObjectProperty } from '@clerk/shared'; +import { deprecatedObjectProperty } from '@clerk/shared/deprecated'; import type { JWT, JWTClaims } from '@clerk/types'; import { urlDecodeB64 } from './encoders'; diff --git a/packages/clerk-js/src/utils/pageLifecycle.ts b/packages/clerk-js/src/utils/pageLifecycle.ts index b127fdc9d8..eae6ee697d 100644 --- a/packages/clerk-js/src/utils/pageLifecycle.ts +++ b/packages/clerk-js/src/utils/pageLifecycle.ts @@ -1,4 +1,4 @@ -import { inClientSide } from '@clerk/shared'; +import { inBrowser } from '@clerk/shared/browser'; const noop = () => { // @@ -15,7 +15,7 @@ const noop = () => { * @internal */ export const createPageLifecycle = () => { - if (!inClientSide()) { + if (!inBrowser()) { return { isUnloading: noop, onPageVisible: noop }; } diff --git a/packages/clerk-js/src/utils/url.ts b/packages/clerk-js/src/utils/url.ts index 2475b288d5..685d9f1a0b 100644 --- a/packages/clerk-js/src/utils/url.ts +++ b/packages/clerk-js/src/utils/url.ts @@ -1,4 +1,5 @@ -import { camelToSnake, createDevOrStagingUrlCache, globs } from '@clerk/shared'; +import { camelToSnake, createDevOrStagingUrlCache } from '@clerk/shared'; +import { globs } from '@clerk/shared/globs'; import type { SignUpResource } from '@clerk/types'; import { joinPaths } from './path'; diff --git a/packages/clerk-js/tsconfig.json b/packages/clerk-js/tsconfig.json index c422f4aa8f..feaf686475 100644 --- a/packages/clerk-js/tsconfig.json +++ b/packages/clerk-js/tsconfig.json @@ -7,7 +7,7 @@ "isolatedModules": true, "module": "esnext", "lib": ["es2021.intl"], - "moduleResolution": "Node", + "moduleResolution": "Bundler", "noEmit": true, "noFallthroughCasesInSwitch": true, "noImplicitReturns": true, diff --git a/packages/clerk-js/webpack.config.js b/packages/clerk-js/webpack.config.js index 9f945187cb..54ad82f7dc 100644 --- a/packages/clerk-js/webpack.config.js +++ b/packages/clerk-js/webpack.config.js @@ -29,7 +29,9 @@ const common = ({ mode }) => { return { mode, resolve: { - extensions: ['.ts', '.tsx', '.js', '.jsx'], + // Attempt to resolve these extensions in order + // @see https://webpack.js.org/configuration/resolve/#resolveextensions + extensions: ['.ts', '.tsx', '.mjs', '.js', '.jsx'], }, plugins: [ new webpack.DefinePlugin({ @@ -100,7 +102,7 @@ const svgLoader = () => { /** @type { () => (import('webpack').RuleSetRule) } */ const typescriptLoaderProd = () => { return { - test: /\.(ts|js)x?$/, + test: /\.(js|mjs|jsx|ts|tsx)$/, exclude: /node_modules/, resolve: { fullySpecified: false, @@ -117,7 +119,7 @@ const typescriptLoaderProd = () => { /** @type { () => (import('webpack').RuleSetRule) } */ const typescriptLoaderDev = () => { return { - test: /\.(ts|js)x?$/, + test: /\.(js|mjs|jsx|ts|tsx)$/, exclude: /node_modules/, resolve: { fullySpecified: false, diff --git a/packages/expo/src/ClerkProvider.tsx b/packages/expo/src/ClerkProvider.tsx index f2563956ae..136ce8b28f 100644 --- a/packages/expo/src/ClerkProvider.tsx +++ b/packages/expo/src/ClerkProvider.tsx @@ -3,7 +3,7 @@ import './polyfills'; import type { ClerkProviderProps as ClerkReactProviderProps } from '@clerk/clerk-react'; import { __internal__setErrorThrowerOptions, ClerkProvider as ClerkReactProvider } from '@clerk/clerk-react'; -import { deprecated } from '@clerk/shared'; +import { deprecated } from '@clerk/shared/deprecated'; import React from 'react'; import type { TokenCache } from './cache'; diff --git a/packages/expo/tsconfig.json b/packages/expo/tsconfig.json index 339f1c1697..d423ec1c4a 100644 --- a/packages/expo/tsconfig.json +++ b/packages/expo/tsconfig.json @@ -4,8 +4,8 @@ "baseUrl": ".", "lib": ["es6", "dom"], "jsx": "react", - "module": "commonjs", - "moduleResolution": "node", + "module": "NodeNext", + "moduleResolution": "NodeNext", "importHelpers": true, "declaration": true, "declarationMap": false, diff --git a/packages/fastify/src/constants.ts b/packages/fastify/src/constants.ts index da0a6cd5bd..3a1e1b4836 100644 --- a/packages/fastify/src/constants.ts +++ b/packages/fastify/src/constants.ts @@ -1,6 +1,6 @@ /* eslint-disable turbo/no-undeclared-env-vars */ import { constants } from '@clerk/backend'; -import { deprecated } from '@clerk/shared'; +import { deprecated } from '@clerk/shared/deprecated'; export const API_URL = process.env.CLERK_API_URL || 'https://api.clerk.dev'; export const API_VERSION = process.env.CLERK_API_VERSION || 'v1'; diff --git a/packages/fastify/tsconfig.json b/packages/fastify/tsconfig.json index ec21549562..f06061d1ec 100644 --- a/packages/fastify/tsconfig.json +++ b/packages/fastify/tsconfig.json @@ -1,6 +1,7 @@ { "compilerOptions": { - "moduleResolution": "node", + "moduleResolution": "NodeNext", + "module": "NodeNext", "sourceMap": false, "strict": true, "esModuleInterop": true, diff --git a/packages/gatsby-plugin-clerk/src/constants.ts b/packages/gatsby-plugin-clerk/src/constants.ts index 682dbbc41d..608f1f6772 100644 --- a/packages/gatsby-plugin-clerk/src/constants.ts +++ b/packages/gatsby-plugin-clerk/src/constants.ts @@ -1,4 +1,4 @@ -import { deprecated } from '@clerk/shared'; +import { deprecated } from '@clerk/shared/deprecated'; export const API_URL = process.env.CLERK_API_URL || 'https://api.clerk.dev'; export const API_VERSION = process.env.CLERK_API_VERSION || 'v1'; diff --git a/packages/gatsby-plugin-clerk/tsconfig.json b/packages/gatsby-plugin-clerk/tsconfig.json index 339f1c1697..d423ec1c4a 100644 --- a/packages/gatsby-plugin-clerk/tsconfig.json +++ b/packages/gatsby-plugin-clerk/tsconfig.json @@ -4,8 +4,8 @@ "baseUrl": ".", "lib": ["es6", "dom"], "jsx": "react", - "module": "commonjs", - "moduleResolution": "node", + "module": "NodeNext", + "moduleResolution": "NodeNext", "importHelpers": true, "declaration": true, "declarationMap": false, diff --git a/packages/localizations/tsconfig.json b/packages/localizations/tsconfig.json index bb28a737e0..5020342437 100644 --- a/packages/localizations/tsconfig.json +++ b/packages/localizations/tsconfig.json @@ -1,6 +1,7 @@ { "compilerOptions": { - "moduleResolution": "node", + "moduleResolution": "NodeNext", + "module": "NodeNext", "sourceMap": false, "strict": true, "esModuleInterop": true, diff --git a/packages/nextjs/src/app-beta/ClerkProvider.tsx b/packages/nextjs/src/app-beta/ClerkProvider.tsx index 6147b4f1de..c467ec694e 100644 --- a/packages/nextjs/src/app-beta/ClerkProvider.tsx +++ b/packages/nextjs/src/app-beta/ClerkProvider.tsx @@ -1,4 +1,4 @@ -import { deprecated } from '@clerk/shared'; +import { deprecated } from '@clerk/shared/deprecated'; deprecated( '@clerk/nextjs/app-beta', diff --git a/packages/nextjs/src/app-beta/auth.ts b/packages/nextjs/src/app-beta/auth.ts index e9be20b298..74d31afc37 100644 --- a/packages/nextjs/src/app-beta/auth.ts +++ b/packages/nextjs/src/app-beta/auth.ts @@ -1,4 +1,4 @@ -import { deprecated } from '@clerk/shared'; +import { deprecated } from '@clerk/shared/deprecated'; deprecated( '@clerk/nextjs/app-beta', diff --git a/packages/nextjs/src/app-beta/clerkClient.ts b/packages/nextjs/src/app-beta/clerkClient.ts index 9f01e147df..b681f8bfb6 100644 --- a/packages/nextjs/src/app-beta/clerkClient.ts +++ b/packages/nextjs/src/app-beta/clerkClient.ts @@ -1,4 +1,4 @@ -import { deprecated } from '@clerk/shared'; +import { deprecated } from '@clerk/shared/deprecated'; deprecated( '@clerk/nextjs/app-beta', diff --git a/packages/nextjs/src/app-beta/client/ClerkProvider.tsx b/packages/nextjs/src/app-beta/client/ClerkProvider.tsx index ab833405fd..25e6a06a1a 100644 --- a/packages/nextjs/src/app-beta/client/ClerkProvider.tsx +++ b/packages/nextjs/src/app-beta/client/ClerkProvider.tsx @@ -1,5 +1,5 @@ 'use client'; -import { deprecated } from '@clerk/shared'; +import { deprecated } from '@clerk/shared/deprecated'; deprecated( '@clerk/nextjs/app-beta', diff --git a/packages/nextjs/src/app-beta/client/clerk-react.ts b/packages/nextjs/src/app-beta/client/clerk-react.ts index bae3acab59..38710d2af7 100644 --- a/packages/nextjs/src/app-beta/client/clerk-react.ts +++ b/packages/nextjs/src/app-beta/client/clerk-react.ts @@ -54,12 +54,12 @@ export const useEmailLink = _useEmailLink; * @deprecated Use imports from `@clerk/nextjs` instead. * For more details, consult the middleware documentation: https://clerk.com/docs/nextjs/middleware */ -export const useOrganization = _useOrganization; +export const useOrganization: typeof _useOrganization = _useOrganization; /** * @deprecated Use imports from `@clerk/nextjs` instead. * For more details, consult the middleware documentation: https://clerk.com/docs/nextjs/middleware */ -export const useOrganizationList = _useOrganizationList; +export const useOrganizationList: typeof _useOrganizationList = _useOrganizationList; /** * @deprecated Use imports from `@clerk/nextjs` instead. * For more details, consult the middleware documentation: https://clerk.com/docs/nextjs/middleware diff --git a/packages/nextjs/src/app-beta/client/ui-components.tsx b/packages/nextjs/src/app-beta/client/ui-components.tsx index da5f93837b..f7c4a0d389 100644 --- a/packages/nextjs/src/app-beta/client/ui-components.tsx +++ b/packages/nextjs/src/app-beta/client/ui-components.tsx @@ -1,5 +1,5 @@ 'use client'; -import { deprecated } from '@clerk/shared'; +import { deprecated } from '@clerk/shared/deprecated'; deprecated( '@clerk/nextjs/app-beta', diff --git a/packages/nextjs/src/app-beta/control-components.tsx b/packages/nextjs/src/app-beta/control-components.tsx index 95f6f47656..59974404d9 100644 --- a/packages/nextjs/src/app-beta/control-components.tsx +++ b/packages/nextjs/src/app-beta/control-components.tsx @@ -1,4 +1,4 @@ -import { deprecated } from '@clerk/shared'; +import { deprecated } from '@clerk/shared/deprecated'; import React from 'react'; deprecated( diff --git a/packages/nextjs/src/app-beta/currentUser.ts b/packages/nextjs/src/app-beta/currentUser.ts index 308f0ab668..e1be302607 100644 --- a/packages/nextjs/src/app-beta/currentUser.ts +++ b/packages/nextjs/src/app-beta/currentUser.ts @@ -1,5 +1,5 @@ import type { User } from '@clerk/backend'; -import { deprecated } from '@clerk/shared'; +import { deprecated } from '@clerk/shared/deprecated'; deprecated( '@clerk/nextjs/app-beta', diff --git a/packages/nextjs/src/server/constants.ts b/packages/nextjs/src/server/constants.ts index c5c3eb7115..e7682801ee 100644 --- a/packages/nextjs/src/server/constants.ts +++ b/packages/nextjs/src/server/constants.ts @@ -1,4 +1,4 @@ -import { deprecated } from '@clerk/shared'; +import { deprecated } from '@clerk/shared/deprecated'; /** * @deprecated Use `CLERK_JS_VERSION` instead. diff --git a/packages/nextjs/src/server/withClerkMiddleware.ts b/packages/nextjs/src/server/withClerkMiddleware.ts index 0beca065c5..433cdad862 100644 --- a/packages/nextjs/src/server/withClerkMiddleware.ts +++ b/packages/nextjs/src/server/withClerkMiddleware.ts @@ -1,6 +1,6 @@ import type { RequestState } from '@clerk/backend'; import { constants, debugRequestState } from '@clerk/backend'; -import { deprecated } from '@clerk/shared'; +import { deprecated } from '@clerk/shared/deprecated'; import type { NextFetchEvent, NextMiddleware, NextRequest } from 'next/server'; import { NextResponse } from 'next/server'; diff --git a/packages/nextjs/src/ssr/withServerSideAuth.ts b/packages/nextjs/src/ssr/withServerSideAuth.ts index 409e47ba49..e9baa11722 100644 --- a/packages/nextjs/src/ssr/withServerSideAuth.ts +++ b/packages/nextjs/src/ssr/withServerSideAuth.ts @@ -1,6 +1,6 @@ import type { RequestState } from '@clerk/backend'; import { constants, debugRequestState } from '@clerk/backend'; -import { deprecated } from '@clerk/shared'; +import { deprecated } from '@clerk/shared/deprecated'; import type { ServerResponse } from 'http'; import type { GetServerSidePropsContext, GetServerSidePropsResult } from 'next'; diff --git a/packages/nextjs/tsconfig.json b/packages/nextjs/tsconfig.json index b74f37fa41..f0d8acec46 100644 --- a/packages/nextjs/tsconfig.json +++ b/packages/nextjs/tsconfig.json @@ -9,8 +9,8 @@ "isolatedModules": true, "jsx": "react", "lib": ["es6", "dom"], - "module": "commonjs", - "moduleResolution": "node", + "module": "NodeNext", + "moduleResolution": "NodeNext", "noImplicitReturns": true, "noUnusedLocals": true, "noUnusedParameters": true, diff --git a/packages/react/src/contexts/AuthContext.ts b/packages/react/src/contexts/AuthContext.ts index d7ae34a938..ce346388e4 100644 --- a/packages/react/src/contexts/AuthContext.ts +++ b/packages/react/src/contexts/AuthContext.ts @@ -1,4 +1,4 @@ -import { createContextAndHook } from '@clerk/shared'; +import { createContextAndHook } from '@clerk/shared/react'; import type { ActJWTClaim, MembershipRole } from '@clerk/types'; export const [AuthContext, useAuthContext] = createContextAndHook<{ diff --git a/packages/react/src/contexts/ClerkContextProvider.tsx b/packages/react/src/contexts/ClerkContextProvider.tsx index 84948aff11..432444fc40 100644 --- a/packages/react/src/contexts/ClerkContextProvider.tsx +++ b/packages/react/src/contexts/ClerkContextProvider.tsx @@ -1,4 +1,4 @@ -import { deprecated } from '@clerk/shared'; +import { deprecated } from '@clerk/shared/deprecated'; import type { ClientResource, InitialState, Resources } from '@clerk/types'; import React from 'react'; diff --git a/packages/react/src/contexts/ClientContext.tsx b/packages/react/src/contexts/ClientContext.tsx index ea29bce0f6..7dd27732e1 100644 --- a/packages/react/src/contexts/ClientContext.tsx +++ b/packages/react/src/contexts/ClientContext.tsx @@ -1 +1 @@ -export { ClientContext, useClientContext } from '@clerk/shared'; +export { ClientContext, useClientContext } from '@clerk/shared/react'; diff --git a/packages/react/src/contexts/IsomorphicClerkContext.tsx b/packages/react/src/contexts/IsomorphicClerkContext.tsx index 2de3f1c6e6..fc2476711b 100644 --- a/packages/react/src/contexts/IsomorphicClerkContext.tsx +++ b/packages/react/src/contexts/IsomorphicClerkContext.tsx @@ -1,3 +1,3 @@ -import { ClerkInstanceContext, useClerkInstanceContext } from '@clerk/shared'; +import { ClerkInstanceContext, useClerkInstanceContext } from '@clerk/shared/react'; export const [IsomorphicClerkContext, useIsomorphicClerkContext] = [ClerkInstanceContext, useClerkInstanceContext]; diff --git a/packages/react/src/contexts/OrganizationContext.tsx b/packages/react/src/contexts/OrganizationContext.tsx index 13ed6bf2e2..f6f820acfa 100644 --- a/packages/react/src/contexts/OrganizationContext.tsx +++ b/packages/react/src/contexts/OrganizationContext.tsx @@ -1 +1 @@ -export { OrganizationProvider, OrganizationContext, useOrganizationContext } from '@clerk/shared'; +export { OrganizationProvider, OrganizationContext, useOrganizationContext } from '@clerk/shared/react'; diff --git a/packages/react/src/contexts/SessionContext.tsx b/packages/react/src/contexts/SessionContext.tsx index 174509b795..4de2102593 100644 --- a/packages/react/src/contexts/SessionContext.tsx +++ b/packages/react/src/contexts/SessionContext.tsx @@ -1 +1 @@ -export { SessionContext, useSessionContext } from '@clerk/shared'; +export { SessionContext, useSessionContext } from '@clerk/shared/react'; diff --git a/packages/react/src/contexts/UserContext.tsx b/packages/react/src/contexts/UserContext.tsx index 8c5c75ff58..c5ef71321e 100644 --- a/packages/react/src/contexts/UserContext.tsx +++ b/packages/react/src/contexts/UserContext.tsx @@ -1 +1 @@ -export { UserContext, useUserContext } from '@clerk/shared'; +export { UserContext, useUserContext } from '@clerk/shared/react'; diff --git a/packages/react/src/errors.ts b/packages/react/src/errors.ts index 739f04142f..4e567a9742 100644 --- a/packages/react/src/errors.ts +++ b/packages/react/src/errors.ts @@ -6,7 +6,7 @@ export { isMetamaskError, isMagicLinkError, isEmailLinkError, -} from '@clerk/shared'; +} from '@clerk/shared/error'; export const noFrontendApiError = 'Clerk: You must add the frontendApi prop to your '; diff --git a/packages/react/src/hooks/index.ts b/packages/react/src/hooks/index.ts index bdbb220379..7b1f97f9e0 100644 --- a/packages/react/src/hooks/index.ts +++ b/packages/react/src/hooks/index.ts @@ -1,12 +1,12 @@ -export * from './useUser'; -export * from './useAuth'; -export * from './useSession'; -export * from './useClerk'; -export * from './useSignIn'; -export * from './useSignUp'; -export * from './useSessionList'; -export * from './useOrganization'; -export * from './useOrganizationList'; -export * from './useOrganizations'; -export * from './useMagicLink'; -export * from './useEmailLink'; +export { useUser } from './useUser'; +export { useAuth } from './useAuth'; +export { useSession } from './useSession'; +export { useClerk } from './useClerk'; +export { useSignIn } from './useSignIn'; +export { useSignUp } from './useSignUp'; +export { useSessionList } from './useSessionList'; +export { useOrganization } from './useOrganization'; +export { useOrganizationList } from './useOrganizationList'; +export { useOrganizations } from './useOrganizations'; +export { useMagicLink } from './useMagicLink'; +export { useEmailLink } from './useEmailLink'; diff --git a/packages/react/src/hooks/useMagicLink.ts b/packages/react/src/hooks/useMagicLink.ts index 673f62c1d3..9db5743931 100644 --- a/packages/react/src/hooks/useMagicLink.ts +++ b/packages/react/src/hooks/useMagicLink.ts @@ -1,4 +1,4 @@ -import { deprecated } from '@clerk/shared'; +import { deprecated } from '@clerk/shared/deprecated'; import type { CreateMagicLinkFlowReturn, EmailAddressResource, diff --git a/packages/react/src/hooks/useOrganization.ts b/packages/react/src/hooks/useOrganization.ts index 175145ff0a..0cf70872ec 100644 --- a/packages/react/src/hooks/useOrganization.ts +++ b/packages/react/src/hooks/useOrganization.ts @@ -1 +1 @@ -export { useOrganization } from '@clerk/shared'; +export { useOrganization } from '@clerk/shared/react'; diff --git a/packages/react/src/hooks/useOrganizationList.ts b/packages/react/src/hooks/useOrganizationList.ts index 7b4192401b..905ba6b1e5 100644 --- a/packages/react/src/hooks/useOrganizationList.ts +++ b/packages/react/src/hooks/useOrganizationList.ts @@ -1 +1 @@ -export { useOrganizationList } from '@clerk/shared'; +export { useOrganizationList } from '@clerk/shared/react'; diff --git a/packages/react/src/hooks/useOrganizations.ts b/packages/react/src/hooks/useOrganizations.ts index 36174f1958..1f25e6ba3b 100644 --- a/packages/react/src/hooks/useOrganizations.ts +++ b/packages/react/src/hooks/useOrganizations.ts @@ -1 +1 @@ -export { useOrganizations } from '@clerk/shared'; +export { useOrganizations } from '@clerk/shared/react'; diff --git a/packages/react/src/isomorphicClerk.ts b/packages/react/src/isomorphicClerk.ts index d51e2a93d1..1cfa352eb8 100644 --- a/packages/react/src/isomorphicClerk.ts +++ b/packages/react/src/isomorphicClerk.ts @@ -1,4 +1,4 @@ -import { deprecated, handleValueOrFn, inClientSide } from '@clerk/shared'; +import { deprecated, handleValueOrFn, inBrowser } from '@clerk/shared'; import type { ActiveSessionResource, AuthenticateWithMetamaskParams, @@ -93,7 +93,7 @@ export default class IsomorphicClerk { // During CSR: use the cached instance for the whole lifetime of the app // Also will recreate the instance if the provided Clerk instance changes // This method should be idempotent in both scenarios - if (!inClientSide() || !this.#instance || (options.Clerk && this.#instance.Clerk !== options.Clerk)) { + if (!inBrowser() || !this.#instance || (options.Clerk && this.#instance.Clerk !== options.Clerk)) { this.#instance = new IsomorphicClerk(options); } return this.#instance; @@ -131,7 +131,7 @@ export default class IsomorphicClerk { this.#domain = options?.domain; this.options = options; this.Clerk = Clerk; - this.mode = inClientSide() ? 'browser' : 'server'; + this.mode = inBrowser() ? 'browser' : 'server'; void this.loadClerkJS(); } diff --git a/packages/react/src/utils/errorThrower.ts b/packages/react/src/utils/errorThrower.ts index 853da1baee..66f0290d9d 100644 --- a/packages/react/src/utils/errorThrower.ts +++ b/packages/react/src/utils/errorThrower.ts @@ -1,5 +1,5 @@ -import type { ErrorThrowerOptions } from '@clerk/shared'; -import { buildErrorThrower } from '@clerk/shared'; +import type { ErrorThrowerOptions } from '@clerk/shared/error'; +import { buildErrorThrower } from '@clerk/shared/error'; const errorThrower = buildErrorThrower({ packageName: '@clerk/react' }); diff --git a/packages/react/tsconfig.json b/packages/react/tsconfig.json index 71b3019c59..be04afbdc5 100644 --- a/packages/react/tsconfig.json +++ b/packages/react/tsconfig.json @@ -8,7 +8,8 @@ "isolatedModules": true, "jsx": "react", "lib": ["es6", "dom"], - "moduleResolution": "node", + "moduleResolution": "NodeNext", + "module": "NodeNext", "noImplicitReturns": true, "noUnusedLocals": false, "noUnusedParameters": true, diff --git a/packages/remix/src/errorThrower.ts b/packages/remix/src/errorThrower.ts index 68fc22437e..a7f17471d0 100644 --- a/packages/remix/src/errorThrower.ts +++ b/packages/remix/src/errorThrower.ts @@ -1,5 +1,5 @@ -import type { ErrorThrowerOptions } from '@clerk/shared'; -import { buildErrorThrower } from '@clerk/shared'; +import type { ErrorThrowerOptions } from '@clerk/shared/error'; +import { buildErrorThrower } from '@clerk/shared/error'; const errorThrower = buildErrorThrower({ packageName: '@clerk/remix' }); diff --git a/packages/remix/tsconfig.json b/packages/remix/tsconfig.json index 339f1c1697..d423ec1c4a 100644 --- a/packages/remix/tsconfig.json +++ b/packages/remix/tsconfig.json @@ -4,8 +4,8 @@ "baseUrl": ".", "lib": ["es6", "dom"], "jsx": "react", - "module": "commonjs", - "moduleResolution": "node", + "module": "NodeNext", + "moduleResolution": "NodeNext", "importHelpers": true, "declaration": true, "declarationMap": false, diff --git a/packages/sdk-node/package.json b/packages/sdk-node/package.json index 558c4327cb..abec244eba 100644 --- a/packages/sdk-node/package.json +++ b/packages/sdk-node/package.json @@ -1,7 +1,7 @@ { + "name": "@clerk/clerk-sdk-node", "version": "4.12.15", "license": "MIT", - "type": "commonjs", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.mjs", "types": "./dist/types/index.d.ts", @@ -46,7 +46,6 @@ "test": "jest", "test:ci": "jest --maxWorkers=70%" }, - "name": "@clerk/clerk-sdk-node", "author": { "name": "Clerk, Inc.", "email": "support@clerk.com", diff --git a/packages/sdk-node/src/authenticateRequest.ts b/packages/sdk-node/src/authenticateRequest.ts index f4acb71810..d710b24332 100644 --- a/packages/sdk-node/src/authenticateRequest.ts +++ b/packages/sdk-node/src/authenticateRequest.ts @@ -1,8 +1,9 @@ import type { RequestState } from '@clerk/backend'; import { buildRequestUrl, constants, createIsomorphicRequest } from '@clerk/backend'; +import { handleValueOrFn } from '@clerk/shared/handleValueOrFn'; +import { isHttpOrHttps, isProxyUrlRelative, isValidProxyUrl } from '@clerk/shared/proxy'; import type { ServerResponse } from 'http'; -import { handleValueOrFn, isHttpOrHttps, isProxyUrlRelative, isValidProxyUrl } from './shared'; import type { AuthenticateRequestParams, ClerkClient } from './types'; import { loadApiEnv, loadClientEnv } from './utils'; diff --git a/packages/sdk-node/src/shared.ts b/packages/sdk-node/src/shared.ts deleted file mode 100644 index 1e125eab2c..0000000000 --- a/packages/sdk-node/src/shared.ts +++ /dev/null @@ -1,45 +0,0 @@ -/** - * These functions originate from @clerk/shared - * Maintain these until @clerk/shared does not depend on react - */ -export function isValidProxyUrl(key: string | undefined) { - if (!key) { - return true; - } - - return isHttpOrHttps(key) || isProxyUrlRelative(key); -} - -export function isHttpOrHttps(key: string | undefined) { - return /^http(s)?:\/\//.test(key || ''); -} - -export function isProxyUrlRelative(key: string) { - return key.startsWith('/'); -} - -export function proxyUrlToAbsoluteURL(url: string | undefined): string { - if (!url) { - return ''; - } - return isProxyUrlRelative(url) ? new URL(url, window.location.origin).toString() : url; -} - -type VOrFnReturnsV = T | undefined | ((v: URL) => T); -export function handleValueOrFn(value: VOrFnReturnsV, url: URL): T | undefined; -export function handleValueOrFn(value: VOrFnReturnsV, url: URL, defaultValue: T): T; -export function handleValueOrFn(value: VOrFnReturnsV, url: URL, defaultValue?: unknown): unknown { - if (typeof value === 'function') { - return (value as (v: URL) => T)(url); - } - - if (typeof value !== 'undefined') { - return value; - } - - if (typeof defaultValue !== 'undefined') { - return defaultValue; - } - - return undefined; -} diff --git a/packages/sdk-node/src/utils.ts b/packages/sdk-node/src/utils.ts index 537f5279da..331495f4b1 100644 --- a/packages/sdk-node/src/utils.ts +++ b/packages/sdk-node/src/utils.ts @@ -1,5 +1,5 @@ /* eslint-disable turbo/no-undeclared-env-vars */ -import { deprecated } from '@clerk/shared'; +import { deprecated } from '@clerk/shared/deprecated'; import type { IncomingMessage, ServerResponse } from 'http'; // https://nextjs.org/docs/api-routes/api-middlewares#connectexpress-middleware-support diff --git a/packages/sdk-node/tsconfig.json b/packages/sdk-node/tsconfig.json index 9579a15f86..81ebb93d55 100644 --- a/packages/sdk-node/tsconfig.json +++ b/packages/sdk-node/tsconfig.json @@ -6,7 +6,8 @@ "forceConsistentCasingInFileNames": true, "importHelpers": true, "isolatedModules": true, - "moduleResolution": "node", + "moduleResolution": "NodeNext", + "module": "NodeNext", "noImplicitReturns": true, "noUnusedLocals": true, "noUnusedParameters": true, diff --git a/packages/shared/README.md b/packages/shared/README.md new file mode 100644 index 0000000000..e0dddaca1a --- /dev/null +++ b/packages/shared/README.md @@ -0,0 +1,3 @@ +# @clerk/shared + +Utilities used in `@clerk` packages diff --git a/packages/shared/jest.config.js b/packages/shared/jest.config.js index d2615837d8..aeb14bfe98 100644 --- a/packages/shared/jest.config.js +++ b/packages/shared/jest.config.js @@ -14,7 +14,6 @@ const config = { moduleDirectories: ['node_modules', '/src'], transform: { '^.+\\.m?tsx?$': ['ts-jest', { tsconfig: 'tsconfig.test.json', diagnostics: false }], - // '^.+\\.svg$': '/svgTransform.js', }, }; diff --git a/packages/shared/package.json b/packages/shared/package.json index 293edcc6b4..966ecb8e7c 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -2,25 +2,48 @@ "name": "@clerk/shared", "version": "0.24.5", "description": "Internal package utils used by the Clerk SDKs", - "types": "./dist/types/index.d.ts", - "main": "./dist/cjs/index.js", - "module": "./dist/esm/index.js", "sideEffects": false, "files": [ "dist" ], + "main": "./dist/index.js", + "module": "./dist/index.mjs", "exports": { ".": { - "types": "./dist/types/index.d.ts", - "import": "./dist/esm/index.js", - "require": "./dist/cjs/index.js" + "import": { + "types": "./dist/index.d.mts", + "default": "./dist/index.mjs" + }, + "require": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } + }, + "./*": { + "import": { + "types": "./dist/*.d.mts", + "default": "./dist/*.mjs" + }, + "require": { + "types": "./dist/*.d.ts", + "default": "./dist/*.js" + } + }, + "./react": { + "import": { + "types": "./dist/react/index.d.mts", + "default": "./dist/react/index.mjs" + }, + "require": { + "types": "./dist/react/index.d.ts", + "default": "./dist/react/index.js" + } } }, "scripts": { "build": "tsup", "dev": "tsup --watch", "dev:publish": "npm run dev -- --env.publish", - "build:declarations": "tsc -p tsconfig.json", "publish:local": "npx yalc push --replace --sig", "clean": "rimraf ./dist", "lint": "eslint src/", diff --git a/packages/shared/src/utils/browser.test.ts b/packages/shared/src/__tests__/browser.test.ts similarity index 99% rename from packages/shared/src/utils/browser.test.ts rename to packages/shared/src/__tests__/browser.test.ts index ca6a16ce2a..5a801e7d9b 100644 --- a/packages/shared/src/utils/browser.test.ts +++ b/packages/shared/src/__tests__/browser.test.ts @@ -1,4 +1,4 @@ -import { inBrowser, isValidBrowserOnline, userAgentIsRobot } from './browser'; +import { inBrowser, isValidBrowserOnline, userAgentIsRobot } from '../browser'; describe('inBrowser()', () => { it('returns true if window is defined', () => { diff --git a/packages/shared/src/utils/color/cssColorUtils.test.ts b/packages/shared/src/__tests__/color.test.ts similarity index 97% rename from packages/shared/src/utils/color/cssColorUtils.test.ts rename to packages/shared/src/__tests__/color.test.ts index 01ecb4e484..7dc19e3d8c 100644 --- a/packages/shared/src/utils/color/cssColorUtils.test.ts +++ b/packages/shared/src/__tests__/color.test.ts @@ -1,6 +1,6 @@ import type { Color } from '@clerk/types'; -import { colorToSameTypeString, hexStringToRgbaColor, stringToHslaColor, stringToSameTypeColor } from './cssColorUtils'; +import { colorToSameTypeString, hexStringToRgbaColor, stringToHslaColor, stringToSameTypeColor } from '../color'; describe('stringToHslaColor(color)', function () { const hsla = { h: 195, s: 1, l: 0.5 }; diff --git a/packages/shared/src/utils/date.test.ts b/packages/shared/src/__tests__/date.test.ts similarity index 97% rename from packages/shared/src/utils/date.test.ts rename to packages/shared/src/__tests__/date.test.ts index 2bfc288e96..56acc62117 100644 --- a/packages/shared/src/utils/date.test.ts +++ b/packages/shared/src/__tests__/date.test.ts @@ -1,5 +1,5 @@ -import type { RelativeDateCase } from './date'; -import { addYears, dateTo12HourTime, differenceInCalendarDays, formatRelative } from './date'; +import type { RelativeDateCase } from '../date'; +import { addYears, dateTo12HourTime, differenceInCalendarDays, formatRelative } from '../date'; describe('date utils', () => { describe('dateTo12HourTime(date)', () => { diff --git a/packages/shared/src/utils/deprecated.test.ts b/packages/shared/src/__tests__/deprecated.test.ts similarity index 98% rename from packages/shared/src/utils/deprecated.test.ts rename to packages/shared/src/__tests__/deprecated.test.ts index 9a96475925..cc9876bc94 100644 --- a/packages/shared/src/utils/deprecated.test.ts +++ b/packages/shared/src/__tests__/deprecated.test.ts @@ -1,12 +1,12 @@ -jest.mock('./runtimeEnvironment', () => { +jest.mock('../utils/runtimeEnvironment', () => { return { isTestEnvironment: jest.fn(() => false), isProductionEnvironment: jest.fn(() => false), }; }); -import { deprecated, deprecatedObjectProperty, deprecatedProperty } from './deprecated'; -import { isProductionEnvironment, isTestEnvironment } from './runtimeEnvironment'; +import { deprecated, deprecatedObjectProperty, deprecatedProperty } from '../deprecated'; +import { isProductionEnvironment, isTestEnvironment } from '../utils/runtimeEnvironment'; describe('deprecated(fnName, warning)', () => { let consoleWarnSpy; diff --git a/packages/shared/src/errors/thrower.test.ts b/packages/shared/src/__tests__/error.test.ts similarity index 93% rename from packages/shared/src/errors/thrower.test.ts rename to packages/shared/src/__tests__/error.test.ts index 33bbf11c71..6d668c99f2 100644 --- a/packages/shared/src/errors/thrower.test.ts +++ b/packages/shared/src/__tests__/error.test.ts @@ -1,5 +1,5 @@ -import type { ErrorThrowerOptions } from './thrower'; -import { buildErrorThrower } from './thrower'; +import type { ErrorThrowerOptions } from '../error'; +import { buildErrorThrower } from '../error'; describe('ErrorThrower', () => { const errorThrower = buildErrorThrower({ packageName: '@clerk/test-package' }); diff --git a/packages/shared/src/utils/multiDomain.test.ts b/packages/shared/src/__tests__/handleValueOrFn.test.ts similarity index 94% rename from packages/shared/src/utils/multiDomain.test.ts rename to packages/shared/src/__tests__/handleValueOrFn.test.ts index 613634ed3d..e48a321c14 100644 --- a/packages/shared/src/utils/multiDomain.test.ts +++ b/packages/shared/src/__tests__/handleValueOrFn.test.ts @@ -1,4 +1,4 @@ -import { handleValueOrFn } from './multiDomain'; +import { handleValueOrFn } from '../handleValueOrFn'; const url = new URL('https://example.com'); diff --git a/packages/shared/src/utils/keys.test.ts b/packages/shared/src/__tests__/keys.test.ts similarity index 98% rename from packages/shared/src/utils/keys.test.ts rename to packages/shared/src/__tests__/keys.test.ts index 703d1b9826..5867c95e97 100644 --- a/packages/shared/src/utils/keys.test.ts +++ b/packages/shared/src/__tests__/keys.test.ts @@ -4,7 +4,7 @@ import { isLegacyFrontendApiKey, isPublishableKey, parsePublishableKey, -} from './keys'; +} from '../keys'; describe('buildPublishableKey(key)', () => { const cases = [ @@ -37,7 +37,9 @@ describe('parsePublishableKey(key)', () => { ], ]; + // @ts-ignore test.each(cases)('given %p as a publishable key string, returns %p', (publishableKeyStr, expectedPublishableKey) => { + // @ts-ignore const result = parsePublishableKey(publishableKeyStr); expect(result).toEqual(expectedPublishableKey); }); diff --git a/packages/shared/src/utils/localStorageBroadcastChannel.test.ts b/packages/shared/src/__tests__/localStorageBroadcastChannel.test.ts similarity index 94% rename from packages/shared/src/utils/localStorageBroadcastChannel.test.ts rename to packages/shared/src/__tests__/localStorageBroadcastChannel.test.ts index 3f576f1411..110ef7e053 100644 --- a/packages/shared/src/utils/localStorageBroadcastChannel.test.ts +++ b/packages/shared/src/__tests__/localStorageBroadcastChannel.test.ts @@ -1,4 +1,4 @@ -import { LocalStorageBroadcastChannel } from './localStorageBroadcastChannel'; +import { LocalStorageBroadcastChannel } from '../localStorageBroadcastChannel'; const bcName = 'clerk'; diff --git a/packages/shared/src/utils/proxy.test.ts b/packages/shared/src/__tests__/proxy.test.ts similarity index 98% rename from packages/shared/src/utils/proxy.test.ts rename to packages/shared/src/__tests__/proxy.test.ts index e5b7e2ba47..a34aca2dbe 100644 --- a/packages/shared/src/utils/proxy.test.ts +++ b/packages/shared/src/__tests__/proxy.test.ts @@ -1,4 +1,4 @@ -import { isHttpOrHttps, isProxyUrlRelative, isValidProxyUrl, proxyUrlToAbsoluteURL } from './proxy'; +import { isHttpOrHttps, isProxyUrlRelative, isValidProxyUrl, proxyUrlToAbsoluteURL } from '../proxy'; describe('isValidProxyUrl(key)', () => { it('returns true if the proxyUrl is valid', () => { diff --git a/packages/shared/src/utils/object.test.ts b/packages/shared/src/__tests__/underscore.test.ts similarity index 76% rename from packages/shared/src/utils/object.test.ts rename to packages/shared/src/__tests__/underscore.test.ts index 01b42cd456..2398cf84d3 100644 --- a/packages/shared/src/utils/object.test.ts +++ b/packages/shared/src/__tests__/underscore.test.ts @@ -1,4 +1,39 @@ -import { deepCamelToSnake, deepSnakeToCamel } from './object'; +import { deepCamelToSnake, deepSnakeToCamel, isIPV4Address, titleize, toSentence } from '../underscore'; + +describe('toSentence', () => { + it('returns a single item as-is', () => { + expect(toSentence(['xyz'])).toBe('xyz'); + expect(toSentence(['abc'])).toBe('abc'); + }); + + it('joins multiple items but the last with a comma and the last with ", or"', () => { + expect(toSentence(['abc', 'def'])).toBe('abc, or def'); + expect(toSentence(['qwe', 'zxc', 'asd'])).toBe('qwe, zxc, or asd'); + }); + + it('returns empty string if passed an empty array', () => { + expect(toSentence([])).toBe(''); + }); +}); + +describe('isIPV4Address(str)', () => { + it('checks if as string is an IP V4', () => { + expect(isIPV4Address(null)).toBe(false); + expect(isIPV4Address(undefined)).toBe(false); + expect(isIPV4Address('')).toBe(false); + expect(isIPV4Address('127.0.0.1')).toBe(true); + }); +}); + +describe('titleize(str)', () => { + it('titleizes the string', () => { + expect(titleize(null)).toBe(''); + expect(titleize(undefined)).toBe(''); + expect(titleize('')).toBe(''); + expect(titleize('foo')).toBe('Foo'); + expect(titleize('foo bar')).toBe('Foo bar'); + }); +}); describe('camelToSnakeKeys', () => { it('creates a copy and does not modify the original', () => { diff --git a/packages/shared/src/utils/url.test.ts b/packages/shared/src/__tests__/url.test.ts similarity index 99% rename from packages/shared/src/utils/url.test.ts rename to packages/shared/src/__tests__/url.test.ts index b26033e4f4..6410f67c83 100644 --- a/packages/shared/src/utils/url.test.ts +++ b/packages/shared/src/__tests__/url.test.ts @@ -1,4 +1,4 @@ -import { addClerkPrefix, parseSearchParams, stripScheme } from './url'; +import { addClerkPrefix, parseSearchParams, stripScheme } from '../url'; describe('parseSearchParams(queryString)', () => { it('parses query string and returns a URLSearchParams object', () => { diff --git a/packages/shared/src/utils/browser.ts b/packages/shared/src/browser.ts similarity index 71% rename from packages/shared/src/utils/browser.ts rename to packages/shared/src/browser.ts index 825e342641..0df2f36f2b 100644 --- a/packages/shared/src/utils/browser.ts +++ b/packages/shared/src/browser.ts @@ -1,3 +1,7 @@ +/** + * Checks if the window object is defined. You can also use this to check if something is happening on the client side. + * @returns {boolean} + */ export function inBrowser(): boolean { return typeof window !== 'undefined'; } @@ -34,10 +38,19 @@ const botAgents = [ ]; const botAgentRegex = new RegExp(botAgents.join('|'), 'i'); +/** + * Checks if the user agent is a bot. + * @param userAgent - Any user agent string + * @returns {boolean} + */ export function userAgentIsRobot(userAgent: string): boolean { return !userAgent ? false : botAgentRegex.test(userAgent); } +/** + * Checks if the current environment is a browser and the user agent is not a bot. + * @returns {boolean} + */ export function isValidBrowser(): boolean { const navigator = window?.navigator; if (!inBrowser() || !navigator) { @@ -46,6 +59,10 @@ export function isValidBrowser(): boolean { return !userAgentIsRobot(navigator?.userAgent) && !navigator?.webdriver; } +/** + * Checks if the current environment is a browser and if the navigator is online. + * @returns {boolean} + */ export function isBrowserOnline(): boolean { const navigator = window?.navigator; if (!inBrowser() || !navigator) { @@ -61,6 +78,10 @@ export function isBrowserOnline(): boolean { return isExperimentalConnectionOnline && isNavigatorOnline; } +/** + * Runs `isBrowserOnline` and `isValidBrowser` to check if the current environment is a valid browser and if the navigator is online. + * @returns {boolean} + */ export function isValidBrowserOnline(): boolean { return isBrowserOnline() && isValidBrowser(); } diff --git a/packages/shared/src/utils/color/cssColorUtils.ts b/packages/shared/src/color.ts similarity index 75% rename from packages/shared/src/utils/color/cssColorUtils.ts rename to packages/shared/src/color.ts index 71d51f69a4..696a8db2e2 100644 --- a/packages/shared/src/utils/color/cssColorUtils.ts +++ b/packages/shared/src/color.ts @@ -1,13 +1,40 @@ import type { Color, HslaColor, RgbaColor, TransparentColor } from '@clerk/types'; -import { - isHSLColor, - isRGBColor, - isTransparent, - isValidHexString, - isValidHslaString, - isValidRgbaString, -} from './predicates'; +const IS_HEX_COLOR_REGEX = /^#?([A-F0-9]{6}|[A-F0-9]{3})$/i; + +const IS_RGB_COLOR_REGEX = /^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/i; +const IS_RGBA_COLOR_REGEX = /^rgba\((\d+),\s*(\d+),\s*(\d+)(,\s*\d+(\.\d+)?)\)$/i; + +const IS_HSL_COLOR_REGEX = /^hsl\((\d+),\s*([\d.]+)%,\s*([\d.]+)%\)$/i; +const IS_HSLA_COLOR_REGEX = /^hsla\((\d+),\s*([\d.]+)%,\s*([\d.]+)%(,\s*\d+(\.\d+)?)*\)$/i; + +export const isValidHexString = (s: string) => { + return !!s.match(IS_HEX_COLOR_REGEX); +}; + +export const isValidRgbaString = (s: string) => { + return !!(s.match(IS_RGB_COLOR_REGEX) || s.match(IS_RGBA_COLOR_REGEX)); +}; + +export const isValidHslaString = (s: string) => { + return !!s.match(IS_HSL_COLOR_REGEX) || !!s.match(IS_HSLA_COLOR_REGEX); +}; + +export const isRGBColor = (c: Color): c is RgbaColor => { + return typeof c !== 'string' && 'r' in c; +}; + +export const isHSLColor = (c: Color): c is HslaColor => { + return typeof c !== 'string' && 'h' in c; +}; + +export const isTransparent = (c: Color): c is TransparentColor => { + return c === 'transparent'; +}; + +export const hasAlpha = (color: Color): boolean => { + return typeof color !== 'string' && color.a != undefined && color.a < 1; +}; const CLEAN_HSLA_REGEX = /[hsla()]/g; const CLEAN_RGBA_REGEX = /[rgba()]/g; diff --git a/packages/shared/src/utils/cookies.ts b/packages/shared/src/cookie.ts similarity index 100% rename from packages/shared/src/utils/cookies.ts rename to packages/shared/src/cookie.ts diff --git a/packages/shared/src/utils/date.ts b/packages/shared/src/date.ts similarity index 95% rename from packages/shared/src/utils/date.ts rename to packages/shared/src/date.ts index 4ef305220a..73442627d1 100644 --- a/packages/shared/src/utils/date.ts +++ b/packages/shared/src/date.ts @@ -34,8 +34,9 @@ type DateFormatRelativeParams = { relativeTo: Date | string | number; }; -type RelativeDateCase = 'previous6Days' | 'lastDay' | 'sameDay' | 'nextDay' | 'next6Days' | 'other'; +export type RelativeDateCase = 'previous6Days' | 'lastDay' | 'sameDay' | 'nextDay' | 'next6Days' | 'other'; type RelativeDateReturn = { relativeDateCase: RelativeDateCase; date: Date } | null; + export function formatRelative(props: DateFormatRelativeParams): RelativeDateReturn { const { date, relativeTo } = props; if (!date || !relativeTo) { diff --git a/packages/shared/src/utils/deprecated.ts b/packages/shared/src/deprecated.ts similarity index 96% rename from packages/shared/src/utils/deprecated.ts rename to packages/shared/src/deprecated.ts index faa17dce4f..0d5d55e2c3 100644 --- a/packages/shared/src/utils/deprecated.ts +++ b/packages/shared/src/deprecated.ts @@ -1,4 +1,4 @@ -import { isProductionEnvironment, isTestEnvironment } from './runtimeEnvironment'; +import { isProductionEnvironment, isTestEnvironment } from './utils/runtimeEnvironment'; /** * Mark class method / function as deprecated. * diff --git a/packages/shared/src/errors/Error.ts b/packages/shared/src/error.ts similarity index 58% rename from packages/shared/src/errors/Error.ts rename to packages/shared/src/error.ts index 7280057eed..1c6539b123 100644 --- a/packages/shared/src/errors/Error.ts +++ b/packages/shared/src/error.ts @@ -1,6 +1,23 @@ import type { ClerkAPIError, ClerkAPIErrorJSON } from '@clerk/types'; -import { deprecated } from '../utils'; +import { deprecated } from './deprecated'; + +export function isUnauthorizedError(e: any): boolean { + const status = e?.status; + const code = e?.errors?.[0]?.code; + return code === 'authentication_invalid' && status === 401; +} + +export function is4xxError(e: any): boolean { + const status = e?.status; + return !!status && status >= 400 && status < 500; +} + +export function isNetworkError(e: any): boolean { + // TODO: revise during error handling epic + const message = (`${e.message}${e.name}` || '').toLowerCase().replace(/\s+/g, ''); + return message.includes('networkerror'); +} interface ClerkAPIResponseOptions { data: ClerkAPIErrorJSON[]; @@ -180,6 +197,7 @@ const _MagicLinkErrorCode = { Expired: 'expired', Failed: 'failed', }; + /** * @deprecated Use `EmailLinkErrorCode` instead. */ @@ -194,3 +212,85 @@ export const EmailLinkErrorCode = { Expired: 'expired', Failed: 'failed', }; + +const DefaultMessages = Object.freeze({ + InvalidFrontendApiErrorMessage: `The frontendApi passed to Clerk is invalid. You can get your Frontend API key at https://dashboard.clerk.com/last-active?path=api-keys. (key={{key}})`, + InvalidProxyUrlErrorMessage: `The proxyUrl passed to Clerk is invalid. The expected value for proxyUrl is an absolute URL or a relative path with a leading '/'. (key={{url}})`, + InvalidPublishableKeyErrorMessage: `The publishableKey passed to Clerk is invalid. You can get your Publishable key at https://dashboard.clerk.com/last-active?path=api-keys. (key={{key}})`, + MissingPublishableKeyErrorMessage: `Missing publishableKey. You can get your key at https://dashboard.clerk.com/last-active?path=api-keys.`, +}); + +type MessageKeys = keyof typeof DefaultMessages; + +type Messages = Record; + +type CustomMessages = Partial; + +export type ErrorThrowerOptions = { + packageName: string; + customMessages?: CustomMessages; +}; + +export interface ErrorThrower { + setPackageName(options: ErrorThrowerOptions): ErrorThrower; + setMessages(options: ErrorThrowerOptions): ErrorThrower; + throwInvalidPublishableKeyError(params: { key?: string }): never; + throwInvalidFrontendApiError(params: { key?: string }): never; + throwInvalidProxyUrl(params: { url?: string }): never; + throwMissingPublishableKeyError(): never; +} + +export function buildErrorThrower({ packageName, customMessages }: ErrorThrowerOptions): ErrorThrower { + let pkg = packageName; + + const messages = { + ...DefaultMessages, + ...customMessages, + }; + + function buildMessage(rawMessage: string, replacements?: Record) { + if (!replacements) { + return `${pkg}: ${rawMessage}`; + } + + let msg = rawMessage; + const matches = rawMessage.matchAll(/{{([a-zA-Z0-9-_]+)}}/g); + + for (const match of matches) { + const replacement = (replacements[match[1]] || '').toString(); + msg = msg.replace(`{{${match[1]}}}`, replacement); + } + + return `${pkg}: ${msg}`; + } + + return { + setPackageName({ packageName }: ErrorThrowerOptions): ErrorThrower { + if (typeof packageName === 'string') { + pkg = packageName; + } + return this; + }, + + setMessages({ customMessages }: ErrorThrowerOptions): ErrorThrower { + Object.assign(messages, customMessages || {}); + return this; + }, + + throwInvalidPublishableKeyError(params: { key?: string }): never { + throw new Error(buildMessage(messages.InvalidPublishableKeyErrorMessage, params)); + }, + + throwInvalidFrontendApiError(params: { key?: string }): never { + throw new Error(buildMessage(messages.InvalidFrontendApiErrorMessage, params)); + }, + + throwInvalidProxyUrl(params: { url?: string }): never { + throw new Error(buildMessage(messages.InvalidProxyUrlErrorMessage, params)); + }, + + throwMissingPublishableKeyError(): never { + throw new Error(buildMessage(messages.MissingPublishableKeyErrorMessage)); + }, + }; +} diff --git a/packages/shared/src/errors/thrower.ts b/packages/shared/src/errors/thrower.ts deleted file mode 100644 index 12f91b3419..0000000000 --- a/packages/shared/src/errors/thrower.ts +++ /dev/null @@ -1,81 +0,0 @@ -const DefaultMessages = Object.freeze({ - InvalidFrontendApiErrorMessage: `The frontendApi passed to Clerk is invalid. You can get your Frontend API key at https://dashboard.clerk.com/last-active?path=api-keys. (key={{key}})`, - InvalidProxyUrlErrorMessage: `The proxyUrl passed to Clerk is invalid. The expected value for proxyUrl is an absolute URL or a relative path with a leading '/'. (key={{url}})`, - InvalidPublishableKeyErrorMessage: `The publishableKey passed to Clerk is invalid. You can get your Publishable key at https://dashboard.clerk.com/last-active?path=api-keys. (key={{key}})`, - MissingPublishableKeyErrorMessage: `Missing publishableKey. You can get your key at https://dashboard.clerk.com/last-active?path=api-keys.`, -}); - -type MessageKeys = keyof typeof DefaultMessages; - -type Messages = Record; - -type CustomMessages = Partial; - -export type ErrorThrowerOptions = { - packageName: string; - customMessages?: CustomMessages; -}; - -export interface ErrorThrower { - setPackageName(options: ErrorThrowerOptions): ErrorThrower; - setMessages(options: ErrorThrowerOptions): ErrorThrower; - throwInvalidPublishableKeyError(params: { key?: string }): never; - throwInvalidFrontendApiError(params: { key?: string }): never; - throwInvalidProxyUrl(params: { url?: string }): never; - throwMissingPublishableKeyError(): never; -} - -export function buildErrorThrower({ packageName, customMessages }: ErrorThrowerOptions): ErrorThrower { - let pkg = packageName; - - const messages = { - ...DefaultMessages, - ...customMessages, - }; - - function buildMessage(rawMessage: string, replacements?: Record) { - if (!replacements) { - return `${pkg}: ${rawMessage}`; - } - - let msg = rawMessage; - const matches = rawMessage.matchAll(/{{([a-zA-Z0-9-_]+)}}/g); - - for (const match of matches) { - const replacement = (replacements[match[1]] || '').toString(); - msg = msg.replace(`{{${match[1]}}}`, replacement); - } - - return `${pkg}: ${msg}`; - } - - return { - setPackageName({ packageName }: ErrorThrowerOptions): ErrorThrower { - if (typeof packageName === 'string') { - pkg = packageName; - } - return this; - }, - - setMessages({ customMessages }: ErrorThrowerOptions): ErrorThrower { - Object.assign(messages, customMessages || {}); - return this; - }, - - throwInvalidPublishableKeyError(params: { key?: string }): never { - throw new Error(buildMessage(messages.InvalidPublishableKeyErrorMessage, params)); - }, - - throwInvalidFrontendApiError(params: { key?: string }): never { - throw new Error(buildMessage(messages.InvalidFrontendApiErrorMessage, params)); - }, - - throwInvalidProxyUrl(params: { url?: string }): never { - throw new Error(buildMessage(messages.InvalidProxyUrlErrorMessage, params)); - }, - - throwMissingPublishableKeyError(): never { - throw new Error(buildMessage(messages.MissingPublishableKeyErrorMessage)); - }, - }; -} diff --git a/packages/shared/src/utils/file.ts b/packages/shared/src/file.ts similarity index 55% rename from packages/shared/src/utils/file.ts rename to packages/shared/src/file.ts index 82dc23a713..88c4f85c3d 100644 --- a/packages/shared/src/utils/file.ts +++ b/packages/shared/src/file.ts @@ -16,3 +16,18 @@ export function readJSONFile(file: File): Promise { reader.readAsText(file); }); } + +const MimeTypeToExtensionMap = Object.freeze({ + 'image/png': 'png', + 'image/jpeg': 'jpg', + 'image/gif': 'gif', + 'image/webp': 'webp', + 'image/x-icon': 'ico', + 'image/vnd.microsoft.icon': 'ico', +} as const); + +export type SupportedMimeType = keyof typeof MimeTypeToExtensionMap; + +export const extension = (mimeType: SupportedMimeType): string => { + return MimeTypeToExtensionMap[mimeType]; +}; diff --git a/packages/shared/src/utils/globs.ts b/packages/shared/src/globs.ts similarity index 100% rename from packages/shared/src/utils/globs.ts rename to packages/shared/src/globs.ts diff --git a/packages/shared/src/utils/multiDomain.ts b/packages/shared/src/handleValueOrFn.ts similarity index 100% rename from packages/shared/src/utils/multiDomain.ts rename to packages/shared/src/handleValueOrFn.ts diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index e2fbe82050..f572339a09 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -1,34 +1,28 @@ -/** - * Errors +/** The following files are not exported on purpose: + * - cookie.ts + * - globs.ts + * + * The following folders are also not exported on purpose: + * - react + * + * People should always use @clerk/shared/ instead */ -export { buildErrorThrower } from './errors/thrower'; -export type { ErrorThrower, ErrorThrowerOptions } from './errors/thrower'; -export * from './errors/Error'; - -/** - * Utils - */ export * from './utils'; -/** - * Hooks - */ -export { assertContextExists, createContextAndHook } from './hooks/createContextAndHook'; -export { useOrganization } from './hooks/useOrganization'; -export { useOrganizationList } from './hooks/useOrganizationList'; -export { useOrganizations } from './hooks/useOrganizations'; -export { useSafeLayoutEffect } from './hooks/useSafeLayoutEffect'; -export { - ClerkInstanceContext, - ClientContext, - OrganizationContext, - OrganizationProvider, - SessionContext, - useClerkInstanceContext, - useClientContext, - useOrganizationContext, - UserContext, - useSessionContext, - useUserContext, -} from './hooks/contexts'; +export { createWorkerTimers } from './workerTimers'; +export * from './browser'; +export * from './color'; +export * from './date'; +export * from './deprecated'; +export * from './error'; +export * from './file'; +export { handleValueOrFn } from './handleValueOrFn'; +export { isomorphicAtob } from './isomorphicAtob'; +export * from './keys'; +export { loadScript } from './loadScript'; +export { LocalStorageBroadcastChannel } from './localStorageBroadcastChannel'; +export * from './poller'; +export * from './proxy'; +export * from './underscore'; +export * from './url'; diff --git a/packages/shared/src/utils/isomorphicAtob.ts b/packages/shared/src/isomorphicAtob.ts similarity index 56% rename from packages/shared/src/utils/isomorphicAtob.ts rename to packages/shared/src/isomorphicAtob.ts index 4399e0cc31..c6adaeb9a7 100644 --- a/packages/shared/src/utils/isomorphicAtob.ts +++ b/packages/shared/src/isomorphicAtob.ts @@ -1,3 +1,7 @@ +/** + * A function that decodes a string of data which has been encoded using base-64 encoding. + * Uses `atob` if available, otherwise uses `Buffer` from `global`. If neither are available, returns the data as-is. + */ export const isomorphicAtob = (data: string) => { if (typeof atob !== 'undefined' && typeof atob === 'function') { return atob(data); diff --git a/packages/shared/src/utils/keys.ts b/packages/shared/src/keys.ts similarity index 100% rename from packages/shared/src/utils/keys.ts rename to packages/shared/src/keys.ts diff --git a/packages/shared/src/utils/loadScript.ts b/packages/shared/src/loadScript.ts similarity index 100% rename from packages/shared/src/utils/loadScript.ts rename to packages/shared/src/loadScript.ts diff --git a/packages/shared/src/utils/localStorageBroadcastChannel.ts b/packages/shared/src/localStorageBroadcastChannel.ts similarity index 100% rename from packages/shared/src/utils/localStorageBroadcastChannel.ts rename to packages/shared/src/localStorageBroadcastChannel.ts diff --git a/packages/shared/src/utils/poller.ts b/packages/shared/src/poller.ts similarity index 100% rename from packages/shared/src/utils/poller.ts rename to packages/shared/src/poller.ts diff --git a/packages/shared/src/utils/proxy.ts b/packages/shared/src/proxy.ts similarity index 100% rename from packages/shared/src/utils/proxy.ts rename to packages/shared/src/proxy.ts diff --git a/packages/shared/src/hooks/clerk-swr.ts b/packages/shared/src/react/clerk-swr.ts similarity index 64% rename from packages/shared/src/hooks/clerk-swr.ts rename to packages/shared/src/react/clerk-swr.ts index 060ecc6865..11aedf73c0 100644 --- a/packages/shared/src/hooks/clerk-swr.ts +++ b/packages/shared/src/react/clerk-swr.ts @@ -1,4 +1,4 @@ 'use client'; export * from 'swr'; -export { default as useSWR } from 'swr'; +export { default as useSWR, SWRConfig } from 'swr'; export { default as useSWRInfinite } from 'swr/infinite'; diff --git a/packages/shared/src/hooks/contexts.tsx b/packages/shared/src/react/contexts.tsx similarity index 96% rename from packages/shared/src/hooks/contexts.tsx rename to packages/shared/src/react/contexts.tsx index 74c0aeb90a..863622e98d 100644 --- a/packages/shared/src/hooks/contexts.tsx +++ b/packages/shared/src/react/contexts.tsx @@ -12,9 +12,9 @@ import type { import type { PropsWithChildren } from 'react'; import React from 'react'; -import { deprecated } from '../utils'; +import { deprecated } from '../deprecated'; import { SWRConfig } from './clerk-swr'; -import { createContextAndHook } from './createContextAndHook'; +import { createContextAndHook } from './hooks/createContextAndHook'; const [ClerkInstanceContext, useClerkInstanceContext] = createContextAndHook('ClerkInstanceContext'); const [UserContext, useUserContext] = createContextAndHook('UserContext'); diff --git a/packages/shared/src/hooks/createContextAndHook.ts b/packages/shared/src/react/hooks/createContextAndHook.ts similarity index 100% rename from packages/shared/src/hooks/createContextAndHook.ts rename to packages/shared/src/react/hooks/createContextAndHook.ts diff --git a/packages/shared/src/react/hooks/index.ts b/packages/shared/src/react/hooks/index.ts new file mode 100644 index 0000000000..a250361a7f --- /dev/null +++ b/packages/shared/src/react/hooks/index.ts @@ -0,0 +1,5 @@ +export { assertContextExists, createContextAndHook } from './createContextAndHook'; +export { useOrganization } from './useOrganization'; +export { useOrganizationList } from './useOrganizationList'; +export { useOrganizations } from './useOrganizations'; +export { useSafeLayoutEffect } from './useSafeLayoutEffect'; diff --git a/packages/shared/src/hooks/useOrganization.tsx b/packages/shared/src/react/hooks/useOrganization.tsx similarity index 98% rename from packages/shared/src/hooks/useOrganization.tsx rename to packages/shared/src/react/hooks/useOrganization.tsx index 3c27babf3c..1e0fe64340 100644 --- a/packages/shared/src/hooks/useOrganization.tsx +++ b/packages/shared/src/react/hooks/useOrganization.tsx @@ -14,10 +14,10 @@ import type { import type { ClerkPaginatedResponse } from '@clerk/types'; import type { GetMembersParams } from '@clerk/types'; -import { deprecated } from '../utils'; -import { useSWR } from './clerk-swr'; -import { useClerkInstanceContext, useOrganizationContext, useSessionContext } from './contexts'; -import type { PaginatedResources, PaginatedResourcesWithDefault } from './types'; +import { deprecated } from '../../deprecated'; +import { useSWR } from '../clerk-swr'; +import { useClerkInstanceContext, useOrganizationContext, useSessionContext } from '../contexts'; +import type { PaginatedResources, PaginatedResourcesWithDefault } from '../types'; import { usePagesOrInfinite, useWithSafeValues } from './usePagesOrInfinite'; type UseOrganizationParams = { diff --git a/packages/shared/src/hooks/useOrganizationList.tsx b/packages/shared/src/react/hooks/useOrganizationList.tsx similarity index 97% rename from packages/shared/src/hooks/useOrganizationList.tsx rename to packages/shared/src/react/hooks/useOrganizationList.tsx index e536b57b8a..beae119aa1 100644 --- a/packages/shared/src/hooks/useOrganizationList.tsx +++ b/packages/shared/src/react/hooks/useOrganizationList.tsx @@ -11,9 +11,9 @@ import type { UserOrganizationInvitationResource, } from '@clerk/types'; -import { deprecatedObjectProperty } from '../utils'; -import { useClerkInstanceContext, useUserContext } from './contexts'; -import type { PaginatedResources, PaginatedResourcesWithDefault } from './types'; +import { deprecatedObjectProperty } from '../../deprecated'; +import { useClerkInstanceContext, useUserContext } from '../contexts'; +import type { PaginatedResources, PaginatedResourcesWithDefault } from '../types'; import { usePagesOrInfinite, useWithSafeValues } from './usePagesOrInfinite'; type UseOrganizationListParams = { diff --git a/packages/shared/src/hooks/useOrganizations.tsx b/packages/shared/src/react/hooks/useOrganizations.tsx similarity index 95% rename from packages/shared/src/hooks/useOrganizations.tsx rename to packages/shared/src/react/hooks/useOrganizations.tsx index 41439235b9..60bfe8ca77 100644 --- a/packages/shared/src/hooks/useOrganizations.tsx +++ b/packages/shared/src/react/hooks/useOrganizations.tsx @@ -1,7 +1,7 @@ import type { CreateOrganizationParams, OrganizationMembershipResource, OrganizationResource } from '@clerk/types'; -import { deprecated } from '../utils'; -import { useClerkInstanceContext } from './contexts'; +import { deprecated } from '../../deprecated'; +import { useClerkInstanceContext } from '../contexts'; type UseOrganizationsReturn = | { diff --git a/packages/shared/src/hooks/usePagesOrInfinite.ts b/packages/shared/src/react/hooks/usePagesOrInfinite.ts similarity index 97% rename from packages/shared/src/hooks/usePagesOrInfinite.ts rename to packages/shared/src/react/hooks/usePagesOrInfinite.ts index 1af2afa023..be8e12f281 100644 --- a/packages/shared/src/hooks/usePagesOrInfinite.ts +++ b/packages/shared/src/react/hooks/usePagesOrInfinite.ts @@ -2,9 +2,9 @@ import { useCallback, useMemo, useRef, useState } from 'react'; -import { useSWR, useSWRInfinite } from './clerk-swr'; -import type { ValueOrSetter } from './types'; -import type { PaginatedResources } from './types'; +import { useSWR, useSWRInfinite } from '../clerk-swr'; +import type { ValueOrSetter } from '../types'; +import type { PaginatedResources } from '../types'; function getDifferentKeys(obj1: Record, obj2: Record): Record { const keysSet = new Set(Object.keys(obj2)); diff --git a/packages/shared/src/hooks/useSafeLayoutEffect.tsx b/packages/shared/src/react/hooks/useSafeLayoutEffect.tsx similarity index 100% rename from packages/shared/src/hooks/useSafeLayoutEffect.tsx rename to packages/shared/src/react/hooks/useSafeLayoutEffect.tsx diff --git a/packages/shared/src/react/index.ts b/packages/shared/src/react/index.ts new file mode 100644 index 0000000000..f1c1afd549 --- /dev/null +++ b/packages/shared/src/react/index.ts @@ -0,0 +1,15 @@ +export * from './hooks'; + +export { + ClerkInstanceContext, + ClientContext, + OrganizationContext, + OrganizationProvider, + SessionContext, + useClerkInstanceContext, + useClientContext, + useOrganizationContext, + UserContext, + useSessionContext, + useUserContext, +} from './contexts'; diff --git a/packages/shared/src/hooks/types.ts b/packages/shared/src/react/types.ts similarity index 100% rename from packages/shared/src/hooks/types.ts rename to packages/shared/src/react/types.ts diff --git a/packages/shared/src/underscore.ts b/packages/shared/src/underscore.ts new file mode 100644 index 0000000000..76a0adca0f --- /dev/null +++ b/packages/shared/src/underscore.ts @@ -0,0 +1,84 @@ +/** + * Converts an array of strings to a comma-separated sentence + * @param items {Array} + * @returns {string} Returns a string with the items joined by a comma and the last item joined by ", or" + */ +export const toSentence = (items: string[]): string => { + // TODO: Once Safari supports it, use Intl.ListFormat + if (items.length == 0) { + return ''; + } + if (items.length == 1) { + return items[0]; + } + let sentence = items.slice(0, -1).join(', '); + sentence += `, or ${items.slice(-1)}`; + return sentence; +}; + +const IP_V4_ADDRESS_REGEX = + /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/; + +export function isIPV4Address(str: string | undefined | null): boolean { + return IP_V4_ADDRESS_REGEX.test(str || ''); +} + +export function titleize(str: string | undefined | null): string { + const s = str || ''; + return s.charAt(0).toUpperCase() + s.slice(1); +} + +export function snakeToCamel(str: string | undefined): string { + return str ? str.replace(/([-_][a-z])/g, match => match.toUpperCase().replace(/-|_/, '')) : ''; +} + +export function camelToSnake(str: string | undefined): string { + return str ? str.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`) : ''; +} + +const createDeepObjectTransformer = (transform: any) => { + const deepTransform = (obj: any): any => { + if (!obj) { + return obj; + } + + if (Array.isArray(obj)) { + return obj.map(el => { + if (typeof el === 'object' || Array.isArray(el)) { + return deepTransform(el); + } + return el; + }); + } + + const copy = { ...obj }; + const keys = Object.keys(copy); + for (const oldName of keys) { + const newName = transform(oldName.toString()); + if (newName !== oldName) { + copy[newName] = copy[oldName]; + delete copy[oldName]; + } + if (typeof copy[newName] === 'object') { + copy[newName] = deepTransform(copy[newName]); + } + } + return copy; + }; + + return deepTransform; +}; + +/** + * Transforms camelCased objects/ arrays to snake_cased. + * This function recursively traverses all objects and arrays of the passed value + * camelCased keys are removed. + */ +export const deepCamelToSnake = createDeepObjectTransformer(camelToSnake); + +/** + * Transforms snake_cased objects/ arrays to camelCased. + * This function recursively traverses all objects and arrays of the passed value + * camelCased keys are removed. + */ +export const deepSnakeToCamel = createDeepObjectTransformer(snakeToCamel); diff --git a/packages/shared/src/utils/url.ts b/packages/shared/src/url.ts similarity index 97% rename from packages/shared/src/utils/url.ts rename to packages/shared/src/url.ts index c9668586d0..dfadc27ed7 100644 --- a/packages/shared/src/utils/url.ts +++ b/packages/shared/src/url.ts @@ -1,4 +1,4 @@ -import { isStaging } from './instance'; +import { isStaging } from './utils/instance'; export function parseSearchParams(queryString = ''): URLSearchParams { if (queryString.startsWith('?')) { diff --git a/packages/shared/src/utils/array.test.ts b/packages/shared/src/utils/array.test.ts deleted file mode 100644 index 98d65d671e..0000000000 --- a/packages/shared/src/utils/array.test.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { toSentence } from './array'; - -describe('toSentence', () => { - it('returns a single item as-is', () => { - expect(toSentence(['xyz'])).toBe('xyz'); - expect(toSentence(['abc'])).toBe('abc'); - }); - - it('joins multiple items but the last with a comma and the last with ", or"', () => { - expect(toSentence(['abc', 'def'])).toBe('abc, or def'); - expect(toSentence(['qwe', 'zxc', 'asd'])).toBe('qwe, zxc, or asd'); - }); - - it('returns empty string if passed an empty array', () => { - expect(toSentence([])).toBe(''); - }); -}); diff --git a/packages/shared/src/utils/array.ts b/packages/shared/src/utils/array.ts deleted file mode 100644 index 6e72606e37..0000000000 --- a/packages/shared/src/utils/array.ts +++ /dev/null @@ -1,12 +0,0 @@ -export const toSentence = (items: string[]): string => { - // TODO: Once Safari supports it, use Intl.ListFormat - if (items.length == 0) { - return ''; - } - if (items.length == 1) { - return items[0]; - } - let sentence = items.slice(0, -1).join(', '); - sentence += `, or ${items.slice(-1)}`; - return sentence; -}; diff --git a/packages/shared/src/utils/color/index.ts b/packages/shared/src/utils/color/index.ts deleted file mode 100644 index 738532889d..0000000000 --- a/packages/shared/src/utils/color/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './cssColorUtils'; -export * from './predicates'; diff --git a/packages/shared/src/utils/color/predicates.ts b/packages/shared/src/utils/color/predicates.ts deleted file mode 100644 index 1db624d763..0000000000 --- a/packages/shared/src/utils/color/predicates.ts +++ /dev/null @@ -1,37 +0,0 @@ -import type { Color, HslaColor, RgbaColor, TransparentColor } from '@clerk/types'; - -const IS_HEX_COLOR_REGEX = /^#?([A-F0-9]{6}|[A-F0-9]{3})$/i; - -const IS_RGB_COLOR_REGEX = /^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/i; -const IS_RGBA_COLOR_REGEX = /^rgba\((\d+),\s*(\d+),\s*(\d+)(,\s*\d+(\.\d+)?)\)$/i; - -const IS_HSL_COLOR_REGEX = /^hsl\((\d+),\s*([\d.]+)%,\s*([\d.]+)%\)$/i; -const IS_HSLA_COLOR_REGEX = /^hsla\((\d+),\s*([\d.]+)%,\s*([\d.]+)%(,\s*\d+(\.\d+)?)*\)$/i; - -export const isValidHexString = (s: string) => { - return !!s.match(IS_HEX_COLOR_REGEX); -}; - -export const isValidRgbaString = (s: string) => { - return !!(s.match(IS_RGB_COLOR_REGEX) || s.match(IS_RGBA_COLOR_REGEX)); -}; - -export const isValidHslaString = (s: string) => { - return !!s.match(IS_HSL_COLOR_REGEX) || !!s.match(IS_HSLA_COLOR_REGEX); -}; - -export const isRGBColor = (c: Color): c is RgbaColor => { - return typeof c !== 'string' && 'r' in c; -}; - -export const isHSLColor = (c: Color): c is HslaColor => { - return typeof c !== 'string' && 'h' in c; -}; - -export const isTransparent = (c: Color): c is TransparentColor => { - return c === 'transparent'; -}; - -export const hasAlpha = (color: Color): boolean => { - return typeof color !== 'string' && color.a != undefined && color.a < 1; -}; diff --git a/packages/shared/src/utils/errors.ts b/packages/shared/src/utils/errors.ts deleted file mode 100644 index 82a5f2e901..0000000000 --- a/packages/shared/src/utils/errors.ts +++ /dev/null @@ -1,16 +0,0 @@ -export function isUnauthorizedError(e: any): boolean { - const status = e?.status; - const code = e?.errors?.[0]?.code; - return code === 'authentication_invalid' && status === 401; -} - -export function is4xxError(e: any): boolean { - const status = e?.status; - return !!status && status >= 400 && status < 500; -} - -export function isNetworkError(e: any): boolean { - // TODO: revise during error handling epic - const message = (`${e.message}${e.name}` || '').toLowerCase().replace(/\s+/g, ''); - return message.includes('networkerror'); -} diff --git a/packages/shared/src/utils/index.ts b/packages/shared/src/utils/index.ts index 25f7edca19..8d2ae051ce 100644 --- a/packages/shared/src/utils/index.ts +++ b/packages/shared/src/utils/index.ts @@ -1,28 +1,6 @@ -export * from './array'; -export * from './browser'; -export * from './color'; -export * from './cookies'; -export * from './createDeferredPromise'; -export * from './date'; -export * from './errors'; -export * from './file'; -export * from './keys'; -export * from './localStorageBroadcastChannel'; -export * from './mimeTypeExtensions'; -export * from './multiDomain'; -export * from './noop'; -export * from './object'; -export * from './poller'; -export * from './proxy'; -export * from './ssr'; -export * from './string'; -export * from './url'; -export * from './workerTimers'; -export * from './runWithExponentialBackOff'; -export * from './isomorphicAtob'; -export * from './globs'; -export * from './loadScript'; -export * from './runtimeEnvironment'; -export { deprecated, deprecatedProperty, deprecatedObjectProperty } from './deprecated'; export { callWithRetry } from './callWithRetry'; +export * from './createDeferredPromise'; export { isDevelopmentFromApiKey, isProductionFromApiKey, isStaging } from './instance'; +export { noop } from './noop'; +export * from './runtimeEnvironment'; +export * from './runWithExponentialBackOff'; diff --git a/packages/shared/src/utils/mimeTypeExtensions.ts b/packages/shared/src/utils/mimeTypeExtensions.ts deleted file mode 100644 index 3d206056ad..0000000000 --- a/packages/shared/src/utils/mimeTypeExtensions.ts +++ /dev/null @@ -1,14 +0,0 @@ -const MimeTypeToExtensionMap = Object.freeze({ - 'image/png': 'png', - 'image/jpeg': 'jpg', - 'image/gif': 'gif', - 'image/webp': 'webp', - 'image/x-icon': 'ico', - 'image/vnd.microsoft.icon': 'ico', -} as const); - -export type SupportedMimeType = keyof typeof MimeTypeToExtensionMap; - -export const extension = (mimeType: SupportedMimeType): string => { - return MimeTypeToExtensionMap[mimeType]; -}; diff --git a/packages/shared/src/utils/noop.ts b/packages/shared/src/utils/noop.ts index e65a0290b9..d9b9e12b4f 100644 --- a/packages/shared/src/utils/noop.ts +++ b/packages/shared/src/utils/noop.ts @@ -1,3 +1,2 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ -/* eslint-disable @typescript-eslint/no-empty-function */ +// eslint-disable-next-line @typescript-eslint/no-empty-function export const noop = (..._args: any[]): void => {}; diff --git a/packages/shared/src/utils/object.ts b/packages/shared/src/utils/object.ts deleted file mode 100644 index 6d9b58b8f4..0000000000 --- a/packages/shared/src/utils/object.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { camelToSnake, snakeToCamel } from './string'; - -const createDeepObjectTransformer = (transform: any) => { - const deepTransform = (obj: any): any => { - if (!obj) { - return obj; - } - - if (Array.isArray(obj)) { - return obj.map(el => { - if (typeof el === 'object' || Array.isArray(el)) { - return deepTransform(el); - } - return el; - }); - } - - const copy = { ...obj }; - const keys = Object.keys(copy); - for (const oldName of keys) { - const newName = transform(oldName.toString()); - if (newName !== oldName) { - copy[newName] = copy[oldName]; - delete copy[oldName]; - } - if (typeof copy[newName] === 'object') { - copy[newName] = deepTransform(copy[newName]); - } - } - return copy; - }; - - return deepTransform; -}; - -/** - * Transforms camelCased objects/ arrays to snake_cased. - * This function recursively traverses all objects and arrays of the passed value - * camelCased keys are removed. - */ -export const deepCamelToSnake = createDeepObjectTransformer(camelToSnake); - -/** - * Transforms snake_cased objects/ arrays to camelCased. - * This function recursively traverses all objects and arrays of the passed value - * camelCased keys are removed. - */ -export const deepSnakeToCamel = createDeepObjectTransformer(snakeToCamel); diff --git a/packages/shared/src/utils/ssr.ts b/packages/shared/src/utils/ssr.ts deleted file mode 100644 index e0ede1979d..0000000000 --- a/packages/shared/src/utils/ssr.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const inClientSide = (): boolean => { - return typeof window !== 'undefined'; -}; diff --git a/packages/shared/src/utils/string.test.ts b/packages/shared/src/utils/string.test.ts deleted file mode 100644 index db64e565c1..0000000000 --- a/packages/shared/src/utils/string.test.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { isIPV4Address, titleize } from './string'; - -describe('isIPV4Address(str)', () => { - it('checks if as string is an IP V4', () => { - expect(isIPV4Address(null)).toBe(false); - expect(isIPV4Address(undefined)).toBe(false); - expect(isIPV4Address('')).toBe(false); - expect(isIPV4Address('127.0.0.1')).toBe(true); - }); -}); - -describe('titleize(str)', () => { - it('titleizes the string', () => { - expect(titleize(null)).toBe(''); - expect(titleize(undefined)).toBe(''); - expect(titleize('')).toBe(''); - expect(titleize('foo')).toBe('Foo'); - expect(titleize('foo bar')).toBe('Foo bar'); - }); -}); diff --git a/packages/shared/src/utils/string.ts b/packages/shared/src/utils/string.ts deleted file mode 100644 index 06f84780be..0000000000 --- a/packages/shared/src/utils/string.ts +++ /dev/null @@ -1,19 +0,0 @@ -const IP_V4_ADDRESS_REGEX = - /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/; - -export function isIPV4Address(str: string | undefined | null): boolean { - return IP_V4_ADDRESS_REGEX.test(str || ''); -} - -export function titleize(str: string | undefined | null): string { - const s = str || ''; - return s.charAt(0).toUpperCase() + s.slice(1); -} - -export function snakeToCamel(str: string | undefined): string { - return str ? str.replace(/([-_][a-z])/g, match => match.toUpperCase().replace(/-|_/, '')) : ''; -} - -export function camelToSnake(str: string | undefined): string { - return str ? str.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`) : ''; -} diff --git a/packages/shared/src/utils/workerTimers/createWorkerTimers.ts b/packages/shared/src/workerTimers/createWorkerTimers.ts similarity index 98% rename from packages/shared/src/utils/workerTimers/createWorkerTimers.ts rename to packages/shared/src/workerTimers/createWorkerTimers.ts index 7c5a1c9d65..91c32ba816 100644 --- a/packages/shared/src/utils/workerTimers/createWorkerTimers.ts +++ b/packages/shared/src/workerTimers/createWorkerTimers.ts @@ -1,4 +1,4 @@ -import { noop } from '../noop'; +import { noop } from '../utils/noop'; import type { WorkerClearTimeout, WorkerSetTimeout, diff --git a/packages/shared/src/utils/workerTimers/index.ts b/packages/shared/src/workerTimers/index.ts similarity index 100% rename from packages/shared/src/utils/workerTimers/index.ts rename to packages/shared/src/workerTimers/index.ts diff --git a/packages/shared/src/utils/workerTimers/workerTimers.types.ts b/packages/shared/src/workerTimers/workerTimers.types.ts similarity index 100% rename from packages/shared/src/utils/workerTimers/workerTimers.types.ts rename to packages/shared/src/workerTimers/workerTimers.types.ts diff --git a/packages/shared/src/utils/workerTimers/workerTimers.worker.ts b/packages/shared/src/workerTimers/workerTimers.worker.ts similarity index 100% rename from packages/shared/src/utils/workerTimers/workerTimers.worker.ts rename to packages/shared/src/workerTimers/workerTimers.worker.ts diff --git a/packages/shared/tsconfig.json b/packages/shared/tsconfig.json index 153c24097f..ef183915a6 100644 --- a/packages/shared/tsconfig.json +++ b/packages/shared/tsconfig.json @@ -4,7 +4,8 @@ "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "isolatedModules": true, - "moduleResolution": "node", + "moduleResolution": "Bundler", + "module": "ESNext", "preserveWatchOutput": true, "skipLibCheck": true, "strict": true, diff --git a/packages/shared/tsup.config.ts b/packages/shared/tsup.config.ts index aec902e0ac..8c912b55a0 100644 --- a/packages/shared/tsup.config.ts +++ b/packages/shared/tsup.config.ts @@ -1,24 +1,22 @@ import type { Plugin } from 'esbuild'; import { transform } from 'esbuild'; import { readFile } from 'fs/promises'; -import type { Options } from 'tsup'; import { defineConfig } from 'tsup'; -import { runAfterLast } from '../../scripts/utils'; import { name, version } from './package.json'; export default defineConfig(overrideOptions => { const isWatch = !!overrideOptions.watch; - const shouldPublish = !!overrideOptions.env?.publish; - const common: Options = { - entry: ['./src/**/*.{ts,tsx,js,jsx}'], - bundle: false, + return { + entry: ['./src/*.{ts,tsx}', './src/react/index.ts', '!./src/**/*.test.{ts,tsx}'], + format: ['cjs', 'esm'], + bundle: true, clean: true, minify: false, sourcemap: true, - legacyOutput: true, - external: ['@testing-library', 'react', 'jest', 'jest-environment-jsdom', 'react-dom'], + dts: true, + external: ['react', 'react-dom'], esbuildPlugins: [WebWorkerMinifyPlugin as any], define: { PACKAGE_NAME: `"${name}"`, @@ -26,19 +24,6 @@ export default defineConfig(overrideOptions => { __DEV__: `${isWatch}`, }, }; - - const esm: Options = { - ...common, - format: 'esm', - }; - - const cjs: Options = { - ...common, - format: 'cjs', - outDir: './dist/cjs', - }; - - return runAfterLast(['npm run build:declarations', shouldPublish && 'npm run publish:local'])(esm, cjs); }); // Read transform and minify any files ending in .worker.ts