Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
c8489d3
introduce @clerk/ui and move clerk-js/src/ui into the new package
nikosdouvlis Nov 2, 2025
f1e618e
disable JSDoc description requirement and add internal JSDoc rules fo…
nikosdouvlis Nov 2, 2025
8706f56
Remove dependency on @clerk/localizations from clerk-js
nikosdouvlis Nov 2, 2025
96f059e
move common utils from clerk-js to shared/internal
nikosdouvlis Nov 2, 2025
37e0b97
move windowNavigate to shared/internal
nikosdouvlis Nov 2, 2025
6502415
move completeSignUpFlow to shared/internal
nikosdouvlis Nov 2, 2025
ecfdec0
move inCrossOriginIframe utility to shared/internal
nikosdouvlis Nov 2, 2025
bd74fe2
move CAPTCHA_ELEMENT_ID and CAPTCHA_INVISIBLE_CLASSNAME to shared/int…
nikosdouvlis Nov 2, 2025
0927f8a
move RedirectUrls to shared/internal
nikosdouvlis Nov 2, 2025
7e36272
move isOrganizationId to shared/internal
nikosdouvlis Nov 2, 2025
f3eb0a6
move email utils to clerk/shared/internal
nikosdouvlis Nov 2, 2025
820fe4a
update error handling to specify 'any' type in catch blocks
nikosdouvlis Nov 2, 2025
91bb982
add global type declarations for SVG modules and build constants
nikosdouvlis Nov 2, 2025
bc594cd
add Emotion integration with custom theme support
nikosdouvlis Nov 2, 2025
0fe0fae
move one-tap to shared/internal
nikosdouvlis Nov 2, 2025
202345b
move img-utils to shared/internal
nikosdouvlis Nov 2, 2025
1bc8b09
refactor passkey utilities to shared/internal
nikosdouvlis Nov 2, 2025
3811e4b
add global type declaration for Clerk interface on Window object
nikosdouvlis Nov 2, 2025
60072b5
move web3 utils into shared/internal
nikosdouvlis Nov 2, 2025
cb29f2d
update TypeScript configuration and enhance global type declarations …
nikosdouvlis Nov 2, 2025
6e99d60
remove yalc patch file and integrate YAML parsing for catalog depende…
nikosdouvlis Nov 3, 2025
6f55b1b
fix createTheme build
nikosdouvlis Nov 3, 2025
63a2d13
add clerkUiUrl to nextjs
nikosdouvlis Nov 3, 2025
32299f9
fix self-referencing imports in shared
nikosdouvlis Nov 3, 2025
1fc7fc5
wip
nikosdouvlis Nov 3, 2025
fc579c5
move all react deps to clerk/ui
nikosdouvlis Nov 4, 2025
cc2818f
fix clerk/ui chunks
nikosdouvlis Nov 4, 2025
7b53832
replace ClerkJSScript with ClerkScripts to inject clerk/clerk-js and …
nikosdouvlis Nov 5, 2025
da0849e
Add UI module with related types and utilities in shared package
nikosdouvlis Nov 6, 2025
3b6cdf2
do not block clerkjs while clerk ui loads
nikosdouvlis Nov 6, 2025
d7841c4
refactor clerk/ui, clerk/js and clerk/react to use the shared ClerkUi…
nikosdouvlis Nov 7, 2025
fa2fb6e
Merge branch 'vincent-and-the-doctor' into nikos/ui-versioning-p1
nikosdouvlis Nov 7, 2025
ca2b57e
introduce safeImport
nikosdouvlis Nov 7, 2025
9fba735
Merge branch 'vincent-and-the-doctor' into nikos/ui-versioning-p1
nikosdouvlis Nov 10, 2025
88c4b72
fix build for all packages
nikosdouvlis Nov 10, 2025
c86c5e7
fix build wip
nikosdouvlis Nov 10, 2025
16c213b
fix shared tests
nikosdouvlis Nov 10, 2025
c8b3b3d
enforce that @clerk/shared cannot reference self through imports
nikosdouvlis Nov 10, 2025
684fb49
mock script loading and set up global Clerk objects for tests
nikosdouvlis Nov 10, 2025
6fd87fd
fix typos in typedoc configuration and update return type of loadCler…
nikosdouvlis Nov 10, 2025
22a82cf
dedupe
nikosdouvlis Nov 10, 2025
c61f121
fix e2e
nikosdouvlis Nov 11, 2025
558cf13
fix vercel cicd
nikosdouvlis Nov 11, 2025
12db539
fix e2e p 2
nikosdouvlis Nov 11, 2025
5bb6f4d
Revert "fix vercel cicd"
nikosdouvlis Nov 11, 2025
c78a4e6
fix vercel sandbox app deployment
nikosdouvlis Nov 11, 2025
fc21a09
Merge branch 'vincent-and-the-doctor' into nikos/ui-versioning-p1
nikosdouvlis Nov 11, 2025
d912ca6
Merge branch 'vincent-and-the-doctor' into nikos/ui-versioning-p1
nikosdouvlis Nov 11, 2025
2d28ced
fix e2e p 3
nikosdouvlis Nov 11, 2025
3955dd3
fix express e2e
nikosdouvlis Nov 11, 2025
aeeea09
fix express e2e p5
nikosdouvlis Nov 11, 2025
188b5d0
disable express e2e
nikosdouvlis Nov 11, 2025
e17c0f6
support vue
nikosdouvlis Nov 11, 2025
e106a3a
temporarily disable astro and billing e2e
nikosdouvlis Nov 11, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 6 additions & 0 deletions .changeset/fix-ui-cicd.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@clerk/ui": patch
---

Fix UI package serving in CI/CD integration tests

30 changes: 20 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -294,17 +294,16 @@ jobs:
strategy:
fail-fast: false
matrix:
test-name:
[
test-name: [
"generic",
"express",
# "express",
"ap-flows",
"localhost",
"sessions",
"sessions:staging",
"handshake",
"handshake:staging",
"astro",
# "astro",
"tanstack-react-start",
"vue",
"nuxt",
Expand All @@ -314,12 +313,12 @@ jobs:
]
test-project: ["chrome"]
include:
- test-name: "billing"
test-project: "chrome"
clerk-use-rq: "false"
- test-name: "billing"
test-project: "chrome"
clerk-use-rq: "true"
# - test-name: "billing"
# test-project: "chrome"
# clerk-use-rq: "false"
# - test-name: "billing"
# test-project: "chrome"
# clerk-use-rq: "true"
- test-name: "nextjs"
test-project: "chrome"
next-version: "15"
Expand Down Expand Up @@ -367,6 +366,7 @@ jobs:
id: task-status
env:
E2E_APP_CLERK_JS_DIR: ${{runner.temp}}
E2E_APP_CLERK_UI_DIR: ${{runner.temp}}
E2E_CLERK_VERSION: "latest"
E2E_NEXTJS_VERSION: ${{ matrix.next-version }}
E2E_PROJECT: ${{ matrix.test-project }}
Expand Down Expand Up @@ -424,6 +424,15 @@ jobs:
pnpm config set minimum-release-age-exclude @clerk/*
pnpm add @clerk/clerk-js

- name: Install @clerk/ui in os temp
if: ${{ steps.task-status.outputs.affected == '1' }}
working-directory: ${{runner.temp}}
run: |
mkdir clerk-ui && cd clerk-ui
pnpm init
pnpm config set minimum-release-age-exclude @clerk/*
pnpm add @clerk/ui

- name: Copy components @clerk/astro
if: ${{ matrix.test-name == 'astro' }}
run: cd packages/astro && pnpm copy:components
Expand Down Expand Up @@ -458,6 +467,7 @@ jobs:
run: pnpm turbo test:integration:${{ matrix.test-name }} $TURBO_ARGS
env:
E2E_APP_CLERK_JS_DIR: ${{runner.temp}}
E2E_APP_CLERK_UI_DIR: ${{runner.temp}}
E2E_CLERK_VERSION: "latest"
E2E_NEXTJS_VERSION: ${{ matrix.next-version }}
E2E_PROJECT: ${{ matrix.test-project }}
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/nightly-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ jobs:
working-directory: ${{runner.temp}}
run: mkdir clerk-js && cd clerk-js && pnpm init && pnpm add @clerk/clerk-js

- name: Install @clerk/ui in os temp
working-directory: ${{runner.temp}}
run: mkdir clerk-ui && cd clerk-ui && pnpm init && pnpm add @clerk/ui

- name: Run Integration Tests
id: integration_tests
continue-on-error: true
Expand All @@ -59,6 +63,7 @@ jobs:
echo "exit_code=${PIPESTATUS[0]}" >> $GITHUB_OUTPUT
env:
E2E_APP_CLERK_JS_DIR: ${{runner.temp}}
E2E_APP_CLERK_UI_DIR: ${{runner.temp}}
E2E_CLERK_VERSION: 'latest'
E2E_NEXTJS_VERSION: 'canary'
E2E_NPM_FORCE: 'true'
Expand All @@ -78,6 +83,7 @@ jobs:
integration/test-results/
integration/.next/
${{runner.temp}}/clerk-js/node_modules/
${{runner.temp}}/clerk-ui/node_modules/
retention-days: 7

- name: Report Status
Expand Down
7 changes: 6 additions & 1 deletion .github/workflows/preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ jobs:
turbo-signature: ${{ secrets.TURBO_REMOTE_CACHE_SIGNATURE_KEY }}
turbo-team: ${{ vars.TURBO_TEAM }}
turbo-token: ${{ secrets.TURBO_TOKEN }}
registry-url: 'https://registry.npmjs.org'
registry-url: "https://registry.npmjs.org"

- name: Build packages
run: pnpm turbo build $TURBO_ARGS
Expand All @@ -101,12 +101,17 @@ jobs:
run: |
cp -r $GITHUB_WORKSPACE/packages/clerk-js/dist $FULL_TMP_FOLDER/public/clerk-js

- name: Copy ui/dist/browser into public/clerk-ui of test site
run: |
cp -r $GITHUB_WORKSPACE/packages/ui/dist/browser $FULL_TMP_FOLDER/public/clerk-ui

- name: Build with Vercel
run: |
cd $FULL_TMP_FOLDER
vercel build --yes
env:
NEXT_PUBLIC_CLERK_JS_URL: /clerk-js/clerk.browser.js
NEXT_PUBLIC_CLERK_UI_URL: /clerk-ui/ui.browser.js

- name: Deploy to Vercel (prebuilt)
id: vercel-deploy
Expand Down
35 changes: 34 additions & 1 deletion eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,29 @@ export default tseslint.config([
'@typescript-eslint/unbound-method': 'off',
},
},
{
name: 'packages/shared',
files: ['packages/shared/src/**/*'],
rules: {
'no-restricted-imports': [
'error',
{
patterns: [
{
group: ['@clerk/shared', '@clerk/shared/*'],
message:
'Do not import from @clerk/shared package exports within the package itself. Use the @/ alias or relative imports from source files instead (e.g., import from "@/types" or "../../types").',
},
{
group: ['../../../*'],
message:
'Relative imports should not traverse more than 2 levels up (../../). Use the @/ path alias instead (e.g., import from "@/types").',
},
],
},
],
},
},
{
name: 'packages/expo-passkeys',
files: ['packages/expo-passkeys/src/**/*'],
Expand Down Expand Up @@ -442,7 +465,7 @@ export default tseslint.config([
{ definedTags: ['inline', 'unionReturnHeadings', 'displayFunctionSignature', 'paramExtension'], typed: false },
],
'jsdoc/require-hyphen-before-param-description': 'warn',
'jsdoc/require-description': 'warn',
'jsdoc/require-description': 'off',
'jsdoc/require-description-complete-sentence': 'warn',
'jsdoc/require-param': ['warn', { ignoreWhenAllParamsMissing: true }],
'jsdoc/require-param-description': 'warn',
Expand All @@ -455,6 +478,16 @@ export default tseslint.config([
],
},
},
{
name: 'repo/jsdoc-internal',
files: ['packages/shared/src/**/internal/**/*.{ts,tsx}', 'packages/shared/src/**/*.{ts,tsx}'],
plugins: {
jsdoc: pluginJsDoc,
},
rules: {
'jsdoc/require-jsdoc': 'off',
},
},
...pluginYml.configs['flat/recommended'],
{
name: 'eslint-prettier',
Expand Down
9 changes: 9 additions & 0 deletions integration/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ export const constants = {
* Controls the path where clerk.browser.js is located on the disk.
*/
E2E_APP_CLERK_JS_DIR: process.env.E2E_APP_CLERK_JS_DIR,
/**
* Controls the URL the apps will load ui.browser.js from.
* If this is set, clerk-ui will not be served automatically from the test runner.
*/
E2E_APP_CLERK_UI: process.env.E2E_APP_CLERK_UI,
/**
* Controls the path where ui.browser.js is located on the disk.
*/
E2E_APP_CLERK_UI_DIR: process.env.E2E_APP_CLERK_UI_DIR,
/**
* If CLEANUP=0 is used, the .tmp_integration directory will not be deleted.
* This is useful for debugging locally.
Expand Down
18 changes: 18 additions & 0 deletions integration/models/stateFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ type StateFile = Partial<{
* The PID is used to teardown the http-server after the tests are done.
*/
clerkJsHttpServerPid: number;
/**
* This prop describes the pid of the http server that serves the clerk-ui hotloaded lib.
* The http-server replaces the production clerk-ui delivery mechanism.
* The PID is used to teardown the http-server after the tests are done.
*/
clerkUiHttpServerPid: number;
}>;

const createStateFile = () => {
Expand Down Expand Up @@ -83,6 +89,16 @@ const createStateFile = () => {
return read().clerkJsHttpServerPid;
};

const setClerkUiHttpServerPid = (pid: number) => {
const json = read();
json.clerkUiHttpServerPid = pid;
write(json);
};

const getClerkUiHttpServerPid = () => {
return read().clerkUiHttpServerPid;
};

const debug = () => {
const json = read();
console.log('state file', JSON.stringify(json, null, 2));
Expand All @@ -94,6 +110,8 @@ const createStateFile = () => {
getStandAloneApp,
setClerkJsHttpServerPid,
getClerkJsHttpServerPid,
setClerkUiHttpServerPid,
getClerkUiHttpServerPid,
addLongRunningApp,
getLongRunningApps,
debug,
Expand Down
12 changes: 8 additions & 4 deletions integration/presets/envs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ const base = environmentConfig()
.setEnvVariable('public', 'CLERK_KEYLESS_DISABLED', true)
.setEnvVariable('public', 'CLERK_SIGN_IN_URL', '/sign-in')
.setEnvVariable('public', 'CLERK_SIGN_UP_URL', '/sign-up')
.setEnvVariable('public', 'CLERK_JS_URL', constants.E2E_APP_CLERK_JS || 'http://localhost:18211/clerk.browser.js');
.setEnvVariable('public', 'CLERK_JS_URL', constants.E2E_APP_CLERK_JS || 'http://localhost:18211/clerk.browser.js')
.setEnvVariable('public', 'CLERK_UI_URL', constants.E2E_APP_CLERK_UI || 'http://localhost:18212/ui.browser.js');

const withKeyless = base
.clone()
Expand Down Expand Up @@ -56,7 +57,8 @@ const sessionsProd1 = base
.setId('sessionsProd1')
.setEnvVariable('private', 'CLERK_SECRET_KEY', instanceKeys.get('sessions-prod-1').sk)
.setEnvVariable('public', 'CLERK_PUBLISHABLE_KEY', instanceKeys.get('sessions-prod-1').pk)
.setEnvVariable('public', 'CLERK_JS_URL', '');
.setEnvVariable('public', 'CLERK_JS_URL', '')
.setEnvVariable('public', 'CLERK_UI_URL', '');

const withEmailCodes_destroy_client = withEmailCodes
.clone()
Expand Down Expand Up @@ -91,7 +93,8 @@ const withAPCore1ClerkLatest = environmentConfig()
.setEnvVariable('public', 'CLERK_TELEMETRY_DISABLED', true)
.setEnvVariable('private', 'CLERK_SECRET_KEY', instanceKeys.get('with-email-codes').sk)
.setEnvVariable('public', 'CLERK_PUBLISHABLE_KEY', instanceKeys.get('with-email-codes').pk)
.setEnvVariable('public', 'CLERK_JS_URL', constants.E2E_APP_CLERK_JS || 'http://localhost:18211/clerk.browser.js');
.setEnvVariable('public', 'CLERK_JS_URL', constants.E2E_APP_CLERK_JS || 'http://localhost:18211/clerk.browser.js')
.setEnvVariable('public', 'CLERK_UI_URL', constants.E2E_APP_CLERK_UI || 'http://localhost:18212/ui.browser.js');

const withAPCore1ClerkV4 = environmentConfig()
.setId('withAPCore1ClerkV4')
Expand All @@ -104,7 +107,8 @@ const withAPCore2ClerkLatest = environmentConfig()
.setEnvVariable('public', 'CLERK_TELEMETRY_DISABLED', true)
.setEnvVariable('private', 'CLERK_SECRET_KEY', instanceKeys.get('core-2-all-enabled').sk)
.setEnvVariable('public', 'CLERK_PUBLISHABLE_KEY', instanceKeys.get('core-2-all-enabled').pk)
.setEnvVariable('public', 'CLERK_JS_URL', constants.E2E_APP_CLERK_JS || 'http://localhost:18211/clerk.browser.js');
.setEnvVariable('public', 'CLERK_JS_URL', constants.E2E_APP_CLERK_JS || 'http://localhost:18211/clerk.browser.js')
.setEnvVariable('public', 'CLERK_UI_URL', constants.E2E_APP_CLERK_UI || 'http://localhost:18212/ui.browser.js');

const withAPCore2ClerkV4 = environmentConfig()
.setId('withAPCore2ClerkV4')
Expand Down
71 changes: 19 additions & 52 deletions integration/scripts/clerkJsServer.ts
Original file line number Diff line number Diff line change
@@ -1,67 +1,34 @@
/* eslint-disable turbo/no-undeclared-env-vars */

import os from 'node:os';
import path from 'node:path';

import { constants } from '../constants';
import { stateFile } from '../models/stateFile';
import { awaitableTreekill, fs, waitForServer } from '.';
import { run } from './run';
import { getTempDir, killHttpServer, startHttpServer } from './httpServer';

export const startClerkJsHttpServer = async () => {
export const startClerkJsHttpServer = async (): Promise<void> => {
if (process.env.E2E_APP_CLERK_JS) {
return;
}
if (!process.env.CI) {
await copyClerkJsToTempDir();
}
return serveFromTempDir();
};

export const killClerkJsHttpServer = async () => {
const clerkJsHttpServerPid = stateFile.getClerkJsHttpServerPid();
if (clerkJsHttpServerPid) {
console.log('Killing clerkJsHttpServer', clerkJsHttpServerPid);
await awaitableTreekill(clerkJsHttpServerPid, 'SIGKILL');
}
};

// If we are running the tests locally, then clerk.browser.js should be built already
// so we simply copy it from packages/clerk to the same location as CICD would install it
const copyClerkJsToTempDir = async () => {
const clerkJsTempDir = getClerkJsTempDir();
await fs.remove(clerkJsTempDir);
await fs.ensureDir(clerkJsTempDir);
const packagesClerkJsDistPath = path.join(process.cwd(), 'packages/clerk-js/dist');
fs.copySync(packagesClerkJsDistPath, clerkJsTempDir);
};
const clerkJsTempDir = getTempDir('clerk-js/node_modules/@clerk/clerk-js/dist', 'E2E_APP_CLERK_JS_DIR');
const sourceDir = path.join(process.cwd(), 'packages/clerk-js/dist');

const serveFromTempDir = async () => {
console.log('Serving clerkJs from temp dir');
const port = 18211;
const serverUrl = `http://localhost:${port}`;
const now = Date.now();
const stdoutFilePath = path.resolve(constants.TMP_DIR, `clerkJsHttpServer.${now}.log`);
const stderrFilePath = path.resolve(constants.TMP_DIR, `clerkJsHttpServer.${now}.err.log`);
const clerkJsTempDir = getClerkJsTempDir();
const proc = run(`node_modules/.bin/http-server ${clerkJsTempDir} -d --gzip --cors -a localhost`, {
cwd: process.cwd(),
env: { PORT: port.toString() },
detached: true,
stdout: fs.openSync(stdoutFilePath, 'a'),
stderr: fs.openSync(stderrFilePath, 'a'),
const { pid } = await startHttpServer({
name: 'clerkJs',
port: 18211,
sourceDir,
targetTempDir: clerkJsTempDir,
envVarOverride: 'E2E_APP_CLERK_JS',
envVarDirOverride: 'E2E_APP_CLERK_JS_DIR',
shouldCopyInLocal: true,
});
stateFile.setClerkJsHttpServerPid(proc.pid);
await waitForServer(serverUrl, { log: console.log, maxAttempts: Infinity });
console.log('clerk.browser.js is being served from', serverUrl);

stateFile.setClerkJsHttpServerPid(pid);
};

// The location where the clerk.browser.js is served from
// For simplicity, on CICD we install `@clerk/clerk-js` on osTemp
// so the actual clerk.browser.file is at osTemp/clerk-js/node_modules/@clerk/clerk-js/dist
// Locally, it's the osTemp/clerk-js/node_modules/@clerk/clerk-js/dist
// You can override it by setting the `E2E_APP_CLERK_JS_DIR` env variable
const getClerkJsTempDir = () => {
const osTempDir = process.env.E2E_APP_CLERK_JS_DIR || os.tmpdir();
return path.join(osTempDir, ...'clerk-js/node_modules/@clerk/clerk-js/dist'.split('/'));
export const killClerkJsHttpServer = async (): Promise<void> => {
const clerkJsHttpServerPid = stateFile.getClerkJsHttpServerPid();
if (clerkJsHttpServerPid) {
await killHttpServer(clerkJsHttpServerPid, 'clerkJs');
}
};
Loading
Loading