Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(clerk-react): Add versionSelector helper #1780

5 changes: 5 additions & 0 deletions .changeset/neat-needles-poke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@clerk/clerk-react": patch
---

Refactor our script loading logic to use a `versionSelector` helper function. No change in behavior should occur. This internal change allows versions tagged with `snapshot` and `staging` to use the exact corresponding NPM version of `@clerk/clerk-js`.
1 change: 1 addition & 0 deletions packages/react/src/globals.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ export {};
declare global {
const PACKAGE_NAME: string;
const PACKAGE_VERSION: string;
const JS_PACKAGE_VERSION: string;
const __DEV__: boolean;
}
32 changes: 32 additions & 0 deletions packages/react/src/utils/__tests__/versionSelector.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */
import { versionSelector } from '../versionSelector';

describe('versionSelector', () => {
it('should return the clerkJSVersion if it is provided', () => {
expect(versionSelector('1.0.0')).toEqual('1.0.0');
});
it('should use the major version if there is no prerelease tag', () => {
// @ts-ignore
global.PACKAGE_VERSION = '1.0.0';
// @ts-ignore
global.JS_PACKAGE_VERSION = '2.0.0';

expect(versionSelector(undefined)).toEqual('1');
});
it('should use the prerelease tag when it is not snapshot', () => {
// @ts-ignore
global.PACKAGE_VERSION = '1.0.0-next.0';
// @ts-ignore
global.JS_PACKAGE_VERSION = '2.0.0-next.0';

expect(versionSelector(undefined)).toEqual('next');
});
it('should use the exact JS version if tag is snapshot', () => {
// @ts-ignore
global.PACKAGE_VERSION = '1.0.0-snapshot.0';
// @ts-ignore
global.JS_PACKAGE_VERSION = '2.0.0-snapshot.0';

expect(versionSelector(undefined)).toEqual('2.0.0-snapshot.0');
});
});
7 changes: 2 additions & 5 deletions packages/react/src/utils/loadClerkJsScript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { addClerkPrefix, isValidProxyUrl, loadScript, parsePublishableKey, proxy
import type { IsomorphicClerkOptions } from '../types';
import { errorThrower } from './errorThrower';
import { isDevOrStagingUrl } from './isDevOrStageUrl';
import { versionSelector } from './versionSelector';

const FAILED_TO_LOAD_ERROR = 'Clerk: Failed to load Clerk';

Expand Down Expand Up @@ -44,7 +45,7 @@ const clerkJsScriptUrl = (opts: LoadClerkJsScriptOptions) => {
}

const variant = clerkJSVariant ? `${clerkJSVariant.replace(/\.+$/, '')}.` : '';
const version = clerkJSVersion || getPrereleaseTag(PACKAGE_VERSION) || getMajorVersion(PACKAGE_VERSION);
const version = versionSelector(clerkJSVersion);
return `https://${scriptHost}/npm/@clerk/clerk-js@${version}/dist/clerk.${variant}browser.js`;
};

Expand All @@ -64,7 +65,3 @@ const applyClerkJsScriptAttributes = (options: LoadClerkJsScriptOptions) => (scr
script.setAttribute('data-clerk-domain', domain);
}
};

const getPrereleaseTag = (packageVersion: string) => packageVersion.match(/-(.*)\./)?.[1];

const getMajorVersion = (packageVersion: string) => packageVersion.split('.')[0];
29 changes: 29 additions & 0 deletions packages/react/src/utils/versionSelector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* This version selector is a bit complicated, so here is the flow:
* 1. Use the clerkJSVersion prop on the provider
* 2. Use the exact `@clerk/clerk-js` version if it is a `@snapshot` prerelease for `@clerk/clerk-react`
* 3. Use the prerelease tag of `@clerk/clerk-react`
* 4. Fallback to the major version of `@clerk/clerk-react`
* @param clerkJSVersion - The optional clerkJSVersion prop on the provider
* @returns The npm tag, version or major version to use
*/
export const versionSelector = (clerkJSVersion: string | undefined) => {
if (clerkJSVersion) {
return clerkJSVersion;
}

const prereleaseTag = getPrereleaseTag(PACKAGE_VERSION);
if (prereleaseTag) {
if (prereleaseTag === 'snapshot') {
return JS_PACKAGE_VERSION;
}

return prereleaseTag;
}

return getMajorVersion(PACKAGE_VERSION);
};

// TODO: Replace these with "semver" package
const getPrereleaseTag = (packageVersion: string) => packageVersion.match(/-(.*)\./)?.[1];
const getMajorVersion = (packageVersion: string) => packageVersion.split('.')[0];
2 changes: 2 additions & 0 deletions packages/react/tsup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { Options } from 'tsup';
import { defineConfig } from 'tsup';

import { runAfterLast } from '../../scripts/utils';
import { version as clerkJsVersion } from '../clerk-js/package.json';
import { name, version } from './package.json';

export default defineConfig(overrideOptions => {
Expand All @@ -18,6 +19,7 @@ export default defineConfig(overrideOptions => {
define: {
PACKAGE_NAME: `"${name}"`,
PACKAGE_VERSION: `"${version}"`,
JS_PACKAGE_VERSION: `"${clerkJsVersion}"`,
__DEV__: `${isWatch}`,
},
};
Expand Down