UNPKG

@clerk/chrome-extension

Version:

Clerk SDK for Chrome extensions

449 lines (432 loc) • 15.6 kB
import { Clerk } from '@clerk/clerk-js/no-rhc'; import browser from 'webextension-polyfill'; var __defProp = Object.defineProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; // ../shared/dist/chunk-3EORDU4Z.mjs function isClerkAPIResponseError(err) { return "clerkError" in err; } var ClerkRuntimeError = class _ClerkRuntimeError extends Error { constructor(message, { code }) { const prefix = "\u{1F512} Clerk:"; const regex = new RegExp(prefix.replace(" ", "\\s*"), "i"); const sanitized = message.replace(regex, ""); const _message = `${prefix} ${sanitized.trim()} (code="${code}") `; super(_message); this.toString = () => { return `[${this.name}] Message:${this.message}`; }; Object.setPrototypeOf(this, _ClerkRuntimeError.prototype); this.code = code; this.message = _message; this.clerkRuntimeError = true; this.name = "ClerkRuntimeError"; } }; var DefaultMessages = Object.freeze({ 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.`, MissingSecretKeyErrorMessage: `Missing secretKey. You can get your key at https://dashboard.clerk.com/last-active?path=api-keys.`, MissingClerkProvider: `{{source}} can only be used within the <ClerkProvider /> component. Learn more: https://clerk.com/docs/components/clerk-provider` }); function buildErrorThrower({ packageName, customMessages }) { let pkg = packageName; const messages = { ...DefaultMessages, ...customMessages }; function buildMessage(rawMessage, replacements) { 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: packageName2 }) { if (typeof packageName2 === "string") { pkg = packageName2; } return this; }, setMessages({ customMessages: customMessages2 }) { Object.assign(messages, customMessages2 || {}); return this; }, throwInvalidPublishableKeyError(params) { throw new Error(buildMessage(messages.InvalidPublishableKeyErrorMessage, params)); }, throwInvalidProxyUrl(params) { throw new Error(buildMessage(messages.InvalidProxyUrlErrorMessage, params)); }, throwMissingPublishableKeyError() { throw new Error(buildMessage(messages.MissingPublishableKeyErrorMessage)); }, throwMissingSecretKeyError() { throw new Error(buildMessage(messages.MissingSecretKeyErrorMessage)); }, throwMissingClerkProviderError(params) { throw new Error(buildMessage(messages.MissingClerkProvider, params)); }, throw(message) { throw new Error(buildMessage(message)); } }; } // ../shared/dist/chunk-7ELT755Q.mjs var __defProp2 = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __typeError = (msg) => { throw TypeError(msg); }; var __export2 = (target, all) => { for (var name in all) __defProp2(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp2(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default")); var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg); var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj)); var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value); var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method); // ../shared/dist/chunk-TETGTEI2.mjs var isomorphicAtob = (data) => { if (typeof atob !== "undefined" && typeof atob === "function") { return atob(data); } else if (typeof global !== "undefined" && global.Buffer) { return new global.Buffer(data, "base64").toString(); } return data; }; // ../shared/dist/chunk-I6MTSTOF.mjs var DEV_OR_STAGING_SUFFIXES = [ ".lcl.dev", ".stg.dev", ".lclstage.dev", ".stgstage.dev", ".dev.lclclerk.com", ".stg.lclclerk.com", ".accounts.lclclerk.com", "accountsstage.dev", "accounts.dev" ]; // ../shared/dist/chunk-G3VP5PJE.mjs var PUBLISHABLE_KEY_LIVE_PREFIX = "pk_live_"; var PUBLISHABLE_KEY_TEST_PREFIX = "pk_test_"; function parsePublishableKey(key, options = {}) { key = key || ""; if (!key || !isPublishableKey(key)) { if (options.fatal && !key) { throw new Error( "Publishable key is missing. Ensure that your publishable key is correctly configured. Double-check your environment configuration for your keys, or access them here: https://dashboard.clerk.com/last-active?path=api-keys" ); } if (options.fatal && !isPublishableKey(key)) { throw new Error("Publishable key not valid."); } return null; } const instanceType = key.startsWith(PUBLISHABLE_KEY_LIVE_PREFIX) ? "production" : "development"; let frontendApi = isomorphicAtob(key.split("_")[2]); frontendApi = frontendApi.slice(0, -1); if (options.proxyUrl) { frontendApi = options.proxyUrl; } else if (instanceType !== "development" && options.domain) { frontendApi = `clerk.${options.domain}`; } return { instanceType, frontendApi }; } function isPublishableKey(key = "") { try { const hasValidPrefix = key.startsWith(PUBLISHABLE_KEY_LIVE_PREFIX) || key.startsWith(PUBLISHABLE_KEY_TEST_PREFIX); const hasValidFrontendApiPostfix = isomorphicAtob(key.split("_")[2] || "").endsWith("$"); return hasValidPrefix && hasValidFrontendApiPostfix; } catch { return false; } } function createDevOrStagingUrlCache() { const devOrStagingUrlCache = /* @__PURE__ */ new Map(); return { isDevOrStagingUrl: (url) => { if (!url) { return false; } const hostname = typeof url === "string" ? url : url.hostname; let res = devOrStagingUrlCache.get(hostname); if (res === void 0) { res = DEV_OR_STAGING_SUFFIXES.some((s) => hostname.endsWith(s)); devOrStagingUrlCache.set(hostname, res); } return res; } }; } // src/types.ts var SCOPE = { BACKGROUND: "background" }; // ../shared/dist/chunk-K64INQ4C.mjs var DEV_BROWSER_JWT_KEY = "__clerk_db_jwt"; // src/internal/constants.ts var AUTH_HEADER = { PRODUCTION: "Authorization", DEVELOPMENT: "Clerk-Db-Jwt" }; var CLIENT_JWT_KEY = "__client"; var CLIENT_UAT_KEY = "__clerk_uat"; var DEFAULT_LOCAL_HOST_PERMISSION = "http://localhost"; var STORAGE_KEY_CLIENT_JWT = "__clerk_client_jwt"; // src/internal/utils/errors.ts var errorLogger = (err) => console.error(err, err.stack); var errorThrower = buildErrorThrower({ packageName: "@clerk/chrome-extension" }); var missingManifestKeyError = (key) => `Missing \`${key}\` entry in manifest.json`; function assertPublishableKey(publishableKey) { if (!publishableKey) { errorThrower.throwMissingPublishableKeyError(); } } function ensureFormattedUrl(url) { return url.startsWith("http") ? url : `https://${url}`; } async function getClientCookie({ url, name }) { return await browser.cookies.get({ name, url: ensureFormattedUrl(url) }); } function createClientCookieListener({ url, name, callback }) { const domain = new URL(url).hostname; const cookieDomain = domain.startsWith("www.") ? domain.slice(4) : domain; const listener = (changeInfo) => { if (changeInfo.cookie.domain === cookieDomain && changeInfo.cookie.name === name) { void callback(changeInfo); } }; return { add: () => browser.cookies.onChanged.addListener(listener), has: () => browser.cookies.onChanged.hasListener(listener), remove: () => browser.cookies.onChanged.removeListener(listener) }; } // src/internal/utils/jwt-handler.ts function shouldSync(sync, _params) { return Boolean(sync); } function JWTHandler(store, params) { const { sync, frontendApi, ...cookieParams } = params; const CACHE_KEY = store.createKey(frontendApi, STORAGE_KEY_CLIENT_JWT, "v2"); const set = async (value) => { return await store.set(CACHE_KEY, value).catch(errorLogger); }; const remove = async () => { return await store.remove(CACHE_KEY).catch(errorLogger); }; const get = async () => { if (shouldSync(sync)) { const syncedJWT = await getClientCookie(cookieParams).catch(errorLogger); if (syncedJWT) { await set(syncedJWT.value); return syncedJWT.value; } } return await store.get(CACHE_KEY); }; const listener = () => { if (!shouldSync(sync)) { return; } const { onListenerCallback, ...restCookieParams } = cookieParams; return createClientCookieListener({ ...restCookieParams, callback: async (changeInfo) => { const existingJWT = await get(); if (existingJWT === changeInfo.cookie.value) { const syncedUAT = await getClientCookie({ ...restCookieParams, name: CLIENT_UAT_KEY }).catch(errorLogger); if (!syncedUAT || (syncedUAT == null ? void 0 : syncedUAT.value) === "0") { onListenerCallback == null ? void 0 : onListenerCallback(); } return; } await set(changeInfo.cookie.value); onListenerCallback == null ? void 0 : onListenerCallback(); } }); }; return { get, listener, set, remove }; } // src/internal/utils/manifest.ts function validateRootManifestKey(manifest, key) { if (!manifest[key]) { errorThrower.throw(missingManifestKeyError(key)); } } function validateManifestPermission(manifest, key) { var _a; if (!((_a = manifest.permissions) == null ? void 0 : _a.includes(key))) { errorThrower.throw(missingManifestKeyError(`permissions.${key}`)); } } function hasAdditionalFeatures(features) { return Boolean(features) && Object.keys(features).length > 0; } function validateManifest(manifest, features) { validateRootManifestKey(manifest, "permissions"); validateManifestPermission(manifest, "storage"); if (!hasAdditionalFeatures(features)) { return; } if (features.background) { validateRootManifestKey(manifest, "background"); } if (features.sync) { validateManifestPermission(manifest, "cookies"); validateRootManifestKey(manifest, "host_permissions"); } } // src/internal/utils/request-handler.ts function requestHandler(jwtHandler, { isProd }) { const handler = async (requestInit) => { requestInit.credentials = "omit"; const currentJWT = await jwtHandler.get(); if (!currentJWT) { return; } if (isProd) { prodHandler(requestInit, currentJWT); } else { devHandler(requestInit, currentJWT); } }; return handler; } function devHandler(requestInit, jwt) { var _a; (_a = requestInit.url) == null ? void 0 : _a.searchParams.append("__clerk_db_jwt", jwt); } function prodHandler(requestInit, jwt) { var _a; (_a = requestInit.url) == null ? void 0 : _a.searchParams.append("_is_native", "1"); requestInit.headers.set(AUTH_HEADER.PRODUCTION, `Bearer ${jwt}`); } // src/internal/utils/response-handler.ts function responseHandler(jwtHandler, { isProd }) { const handler = async (_, response) => { if (isProd) { await prodHandler2(response, jwtHandler); } else { await devHandler2(response, jwtHandler); } }; return handler; } async function devHandler2(response, jwtHandler) { const header = response == null ? void 0 : response.headers.get(AUTH_HEADER.DEVELOPMENT); if (header) { await jwtHandler.set(header); } else { await jwtHandler.remove(); } } async function prodHandler2(response, jwtHandler) { const header = response == null ? void 0 : response.headers.get(AUTH_HEADER.PRODUCTION); if (header == null ? void 0 : header.startsWith("Bearer")) { const jwt = header.split(" ")[1] || void 0; if (jwt) { await jwtHandler.set(jwt); } else { await jwtHandler.remove(); } } else if (header) { await jwtHandler.set(header); } } var createKey = (...keys) => keys.filter(Boolean).join("|"); var createBrowserStorageCache = (opts = {}) => { const __storageArea = opts.storageArea || "local"; return { createKey, get: (key) => browser.storage[__storageArea].get(key).then((result) => result[key] || void 0), remove: (key) => browser.storage[__storageArea].remove(key), set: (key, value) => browser.storage[__storageArea].set({ [key]: value }) }; }; var BrowserStorageCache = createBrowserStorageCache(); // src/internal/clerk.ts var clerk; Clerk.sdkMetadata = { name: "@clerk/chrome-extension", version: "2.2.23" }; async function createClerkClient({ __experimental_syncHostListener = false, publishableKey, scope, storageCache = BrowserStorageCache, syncHost }) { if (scope === SCOPE.BACKGROUND) { Clerk.mountComponentRenderer = void 0; } if (clerk && scope !== SCOPE.BACKGROUND) { return clerk; } const sync = Boolean(syncHost); const key = parsePublishableKey(publishableKey); assertPublishableKey(key); const isProd = key.instanceType === "production"; const manifest = browser.runtime.getManifest(); validateManifest(manifest, { background: scope === SCOPE.BACKGROUND, sync }); const url = syncHost ? syncHost : DEFAULT_LOCAL_HOST_PERMISSION; clerk = new Clerk(publishableKey); const jwtOptions = { frontendApi: key.frontendApi, name: isProd ? CLIENT_JWT_KEY : DEV_BROWSER_JWT_KEY, url, sync }; if (jwtOptions.sync && __experimental_syncHostListener) { jwtOptions.onListenerCallback = () => { if (clerk.user) { clerk.user.reload(); } else { window.location.reload(); } }; } const jwt = JWTHandler(storageCache, jwtOptions); if (jwtOptions.sync && __experimental_syncHostListener) { const listener = jwt.listener(); listener == null ? void 0 : listener.add(); } clerk.__unstable__onAfterResponse(responseHandler(jwt, { isProd })); clerk.__unstable__onBeforeRequest(requestHandler(jwt, { isProd })); return clerk; } export { ClerkRuntimeError, SCOPE, __export, __export2, __privateGet, __privateMethod, __privateSet, __reExport, buildErrorThrower, createClerkClient, createDevOrStagingUrlCache, isClerkAPIResponseError, isPublishableKey }; //# sourceMappingURL=chunk-XNSJY45P.js.map //# sourceMappingURL=chunk-XNSJY45P.js.map