diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e6480e42454..92e809b9150 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -294,7 +294,8 @@ jobs: strategy: fail-fast: false matrix: - test-name: [ + test-name: + [ "generic", "express", "ap-flows", @@ -303,7 +304,7 @@ jobs: "sessions:staging", "handshake", "handshake:staging", - # "astro", + "astro", "tanstack-react-start", "vue", "nuxt", @@ -403,7 +404,8 @@ jobs: uses: ./.github/actions/verdaccio with: publish-cmd: | - if [ "$(pnpm config get registry)" = "https://registry.npmjs.org/" ]; then echo 'Error: Using default registry' && exit 1; else CLERK_USE_RQ=${{ matrix.clerk-use-rq }} pnpm turbo build $TURBO_ARGS --only && pnpm changeset publish --no-git-tag; fi + if [ "$(pnpm config get registry)" = "https://registry.npmjs.org/" ]; then echo 'Error: Using default registry' && exit 1; else CLERK_USE_RQ=${{ matrix.clerk-use-rq }} pnpm turbo build $TURBO_ARGS --only && pnpm changeset publish --no-git-tag --tag integration; fi + - name: Edit .npmrc [link-workspace-packages=false] run: sed -i -E 's/link-workspace-packages=(deep|true)/link-workspace-packages=false/' .npmrc diff --git a/integration/presets/custom-flows.ts b/integration/presets/custom-flows.ts index fcae3cb8ddc..f816de17057 100644 --- a/integration/presets/custom-flows.ts +++ b/integration/presets/custom-flows.ts @@ -1,4 +1,3 @@ -import { constants } from '../constants'; import { applicationConfig } from '../models/applicationConfig'; import { templates } from '../templates'; import { linkPackage } from './utils'; @@ -11,8 +10,9 @@ const reactVite = applicationConfig() .addScript('dev', 'pnpm dev') .addScript('build', 'pnpm build') .addScript('serve', 'pnpm preview') - .addDependency('@clerk/react', constants.E2E_CLERK_JS_VERSION || linkPackage('react')) - .addDependency('@clerk/themes', constants.E2E_CLERK_JS_VERSION || linkPackage('themes')); + .addDependency('@clerk/react', linkPackage('react', 'integration')) + .addDependency('@clerk/shared', linkPackage('shared', 'integration')) + .addDependency('@clerk/themes', linkPackage('themes', 'integration')); export const customFlows = { reactVite, diff --git a/integration/presets/react.ts b/integration/presets/react.ts index 9a3344fa553..d2ea6b0861c 100644 --- a/integration/presets/react.ts +++ b/integration/presets/react.ts @@ -1,4 +1,3 @@ -import { constants } from '../constants'; import { applicationConfig } from '../models/applicationConfig'; import { templates } from '../templates'; import { linkPackage } from './utils'; @@ -11,8 +10,9 @@ const cra = applicationConfig() .addScript('dev', 'pnpm start') .addScript('build', 'pnpm build') .addScript('serve', 'pnpm start') - .addDependency('@clerk/react', constants.E2E_CLERK_JS_VERSION || linkPackage('react')) - .addDependency('@clerk/themes', constants.E2E_CLERK_JS_VERSION || linkPackage('themes')); + .addDependency('@clerk/react', linkPackage('react', 'integration')) + .addDependency('@clerk/shared', linkPackage('shared', 'integration')) + .addDependency('@clerk/themes', linkPackage('themes', 'integration')); const vite = cra .clone() diff --git a/integration/presets/utils.ts b/integration/presets/utils.ts index f7831c39663..d22e39250dd 100644 --- a/integration/presets/utils.ts +++ b/integration/presets/utils.ts @@ -1,9 +1,9 @@ import path from 'node:path'; -export function linkPackage(pkg: string) { +export function linkPackage(pkg: string, tag?: string) { // eslint-disable-next-line turbo/no-undeclared-env-vars if (process.env.CI === 'true') { - return '*'; + return tag || '*'; } return `link:${path.resolve(process.cwd(), `packages/${pkg}`)}`; diff --git a/packages/astro/src/integration/create-integration.ts b/packages/astro/src/integration/create-integration.ts index dcfa9b115f3..e8902271a96 100644 --- a/packages/astro/src/integration/create-integration.ts +++ b/packages/astro/src/integration/create-integration.ts @@ -11,9 +11,6 @@ const buildEnvVarFromOption = (valueToBeStored: unknown, envName: keyof Internal }; type HotloadAstroClerkIntegrationParams = AstroClerkIntegrationParams & { - clerkJSUrl?: string; - clerkJSVariant?: 'headless' | ''; - clerkJSVersion?: string; enableEnvSchema?: boolean; }; diff --git a/packages/astro/src/internal/create-clerk-instance.ts b/packages/astro/src/internal/create-clerk-instance.ts index e5c18399f41..b1e6ef64197 100644 --- a/packages/astro/src/internal/create-clerk-instance.ts +++ b/packages/astro/src/internal/create-clerk-instance.ts @@ -1,5 +1,10 @@ -import { loadClerkJsScript, setClerkJsLoadingErrorPackageName } from '@clerk/shared/loadClerkJsScript'; +import { + loadClerkJsScript, + loadClerkUiScript, + setClerkJsLoadingErrorPackageName, +} from '@clerk/shared/loadClerkJsScript'; import type { ClerkOptions } from '@clerk/shared/types'; +import type { ClerkUiConstructor } from '@clerk/shared/ui'; import { $clerkStore } from '../stores/external'; import { $clerk, $csrState } from '../stores/internal'; @@ -31,8 +36,20 @@ const createClerkInstance = runOnce(createClerkInstanceInternal); async function createClerkInstanceInternal(options?: AstroClerkCreateInstanceParams) { let clerkJSInstance = window.Clerk; + let clerkUiCtor: Promise | undefined; + if (!clerkJSInstance) { - await loadClerkJsScript(options); + // Load both clerk-js and clerk-ui in parallel + const clerkPromise = loadClerkJsScript(options); + clerkUiCtor = loadClerkUiScript(options).then(() => { + if (!window.__unstable_ClerkUiCtor) { + throw new Error('Failed to download latest Clerk UI. Contact support@clerk.com.'); + } + // After the check, TypeScript knows it's defined + return window.__unstable_ClerkUiCtor; + }); + + await clerkPromise; if (!window.Clerk) { throw new Error('Failed to download latest ClerkJS. Contact support@clerk.com.'); @@ -48,6 +65,8 @@ async function createClerkInstanceInternal(options?: AstroClerkCreateInstancePar routerPush: createNavigationHandler(window.history.pushState.bind(window.history)), routerReplace: createNavigationHandler(window.history.replaceState.bind(window.history)), ...options, + // Pass the clerk-ui constructor promise to clerk.load() + clerkUiCtor, }; return clerkJSInstance diff --git a/packages/astro/src/internal/merge-env-vars-with-params.ts b/packages/astro/src/internal/merge-env-vars-with-params.ts index c5498c1e0da..dea24762b16 100644 --- a/packages/astro/src/internal/merge-env-vars-with-params.ts +++ b/packages/astro/src/internal/merge-env-vars-with-params.ts @@ -14,6 +14,10 @@ const mergeEnvVarsWithParams = (params?: AstroClerkIntegrationParams & { publish domain: paramDomain, publishableKey: paramPublishableKey, telemetry: paramTelemetry, + clerkJSUrl: paramClerkJSUrl, + clerkUiUrl: paramClerkUiUrl, + clerkJSVariant: paramClerkJSVariant, + clerkJSVersion: paramClerkJSVersion, ...rest } = params || {}; @@ -24,6 +28,10 @@ const mergeEnvVarsWithParams = (params?: AstroClerkIntegrationParams & { publish proxyUrl: paramProxy || import.meta.env.PUBLIC_CLERK_PROXY_URL, domain: paramDomain || import.meta.env.PUBLIC_CLERK_DOMAIN, publishableKey: paramPublishableKey || import.meta.env.PUBLIC_CLERK_PUBLISHABLE_KEY || '', + clerkUiUrl: paramClerkUiUrl || import.meta.env.PUBLIC_CLERK_UI_URL, + clerkJSUrl: paramClerkJSUrl || import.meta.env.PUBLIC_CLERK_JS_URL, + clerkJSVariant: paramClerkJSVariant || import.meta.env.PUBLIC_CLERK_JS_VARIANT, + clerkJSVersion: paramClerkJSVersion || import.meta.env.PUBLIC_CLERK_JS_VERSION, telemetry: paramTelemetry || { disabled: isTruthy(import.meta.env.PUBLIC_CLERK_TELEMETRY_DISABLED), debug: isTruthy(import.meta.env.PUBLIC_CLERK_TELEMETRY_DEBUG), diff --git a/packages/astro/src/types.ts b/packages/astro/src/types.ts index ad47cedbd99..ed3b0313799 100644 --- a/packages/astro/src/types.ts +++ b/packages/astro/src/types.ts @@ -6,6 +6,7 @@ import type { ProtectProps, Without, } from '@clerk/shared/types'; +import type { ClerkUiConstructor } from '@clerk/shared/ui'; type AstroClerkUpdateOptions = Pick; @@ -20,8 +21,17 @@ type AstroClerkIntegrationParams = Without< | 'routerPush' | 'polling' | 'touchSession' + | 'clerkUiCtor' > & - MultiDomainAndOrProxyPrimitives; + MultiDomainAndOrProxyPrimitives & { + clerkJSUrl?: string; + clerkJSVariant?: 'headless' | ''; + clerkJSVersion?: string; + /** + * The URL that `@clerk/ui` should be hot-loaded from. + */ + clerkUiUrl?: string; + }; type AstroClerkCreateInstanceParams = AstroClerkIntegrationParams & { publishableKey: string }; @@ -42,6 +52,7 @@ declare global { __astro_clerk_component_props: Map>>; __astro_clerk_function_props: Map>>; Clerk: BrowserClerk; + __unstable_ClerkUiCtor?: ClerkUiConstructor; } }