Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/nasty-baboons-cheer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@clerk/astro": patch
"@clerk/shared": patch
---

Introduce functions that can be reused across front-end SDKs
2 changes: 0 additions & 2 deletions packages/astro/src/client/bundled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ export function createClerkInstanceInternal(options?: AstroClerkCreateInstancePa
let clerkJSInstance = window.Clerk as unknown as Clerk;
if (!clerkJSInstance) {
clerkJSInstance = new Clerk(options!.publishableKey);
// @ts-ignore
$clerk.set(clerkJSInstance);
// @ts-ignore
window.Clerk = clerkJSInstance;
}

Expand Down
14 changes: 9 additions & 5 deletions packages/astro/src/client/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { waitForClerkScript } from '../internal/utils/loadClerkJSScript';
import { loadClerkJsScript } from '@clerk/shared/loadClerkJsScript';

import { $clerk, $csrState } from '../stores/internal';
import type { AstroClerkIntegrationParams, AstroClerkUpdateOptions } from '../types';
import { mountAllClerkAstroJSComponents } from './mount-clerk-astro-js-components';
import { runOnce } from './run-once';

let initOptions: AstroClerkIntegrationParams | undefined;

const HARDCODED_LATEST_CLERK_JS_VERSION = '5';

/**
* Prevents firing clerk.load multiple times
*/
Expand All @@ -14,7 +17,10 @@ export const createClerkInstance = runOnce(createClerkInstanceInternal);
export async function createClerkInstanceInternal(options?: AstroClerkIntegrationParams) {
let clerkJSInstance = window.Clerk;
if (!clerkJSInstance) {
await waitForClerkScript();
await loadClerkJsScript({
clerkJSVersion: HARDCODED_LATEST_CLERK_JS_VERSION,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll need to remove this, I'll explain it in https://github.com/clerk/javascript/pull/3681/files#r1672868119

...(options as any),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The as any is a code smell, ideally the options has the correct type, could be a footgun in the future

});

if (!window.Clerk) {
throw new Error('Failed to download latest ClerkJS. Contact [email protected].');
Expand All @@ -23,13 +29,11 @@ export async function createClerkInstanceInternal(options?: AstroClerkIntegratio
}

if (!$clerk.get()) {
// @ts-ignore
$clerk.set(clerkJSInstance);
}

initOptions = options;
// TODO: Update Clerk type from @clerk/types to include this method
return (clerkJSInstance as any)
return clerkJSInstance
.load(options)
.then(() => {
$csrState.setKey('isLoaded', true);
Expand Down
20 changes: 14 additions & 6 deletions packages/astro/src/internal/merge-env-vars-with-params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,21 @@ const mergeEnvVarsWithParams = (params?: AstroClerkIntegrationParams & { publish
...rest
} = params || {};

// We have an eslint config that requires us to declare env variables in the turbo.json file.
// We're skipping/disabling it below as we use it only for the Astro integration.
return {
signInUrl: paramSignIn || import.meta.env.PUBLIC_ASTRO_APP_CLERK_SIGN_IN_URL,
signUpUrl: paramSignUp || import.meta.env.PUBLIC_ASTRO_APP_CLERK_SIGN_UP_URL,
isSatellite: paramSatellite || import.meta.env.PUBLIC_ASTRO_APP_CLERK_IS_SATELLITE,
proxyUrl: paramProxy || import.meta.env.PUBLIC_ASTRO_APP_CLERK_PROXY_URL,
domain: paramDomain || import.meta.env.PUBLIC_ASTRO_APP_CLERK_DOMAIN,
publishableKey: paramPublishableKey || import.meta.env.PUBLIC_ASTRO_APP_CLERK_PUBLISHABLE_KEY || '',
// eslint-disable-next-line turbo/no-undeclared-env-vars
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Use block comments (https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) because then it's more concise

signInUrl: paramSignIn || import.meta.env.PUBLIC_CLERK_SIGN_IN_URL,
// eslint-disable-next-line turbo/no-undeclared-env-vars
signUpUrl: paramSignUp || import.meta.env.PUBLIC_CLERK_SIGN_UP_URL,
// eslint-disable-next-line turbo/no-undeclared-env-vars
isSatellite: paramSatellite || import.meta.env.PUBLIC_CLERK_IS_SATELLITE,
// eslint-disable-next-line turbo/no-undeclared-env-vars
proxyUrl: paramProxy || import.meta.env.PUBLIC_CLERK_PROXY_URL,
// eslint-disable-next-line turbo/no-undeclared-env-vars
domain: paramDomain || import.meta.env.PUBLIC_CLERK_DOMAIN,
// eslint-disable-next-line turbo/no-undeclared-env-vars
publishableKey: paramPublishableKey || import.meta.env.PUBLIC_CLERK_PUBLISHABLE_KEY || '',
...rest,
};
};
Expand Down
17 changes: 0 additions & 17 deletions packages/astro/src/internal/utils/loadClerkJSScript.ts

This file was deleted.

9 changes: 0 additions & 9 deletions packages/astro/src/internal/utils/versionSelector.ts

This file was deleted.

64 changes: 0 additions & 64 deletions packages/astro/src/server/build-clerk-hotload-script.ts

This file was deleted.

6 changes: 0 additions & 6 deletions packages/astro/src/server/clerk-middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import type { APIContext } from 'astro';
// @ts-ignore
import { authAsyncStorage } from '#async-local-storage';

import { buildClerkHotloadScript } from './build-clerk-hotload-script';
import { clerkClient } from './clerk-client';
import { createCurrentUser } from './current-user';
import { getAuth } from './get-auth';
Expand Down Expand Up @@ -263,7 +262,6 @@ async function decorateRequest(
const clerkSafeEnvVariables = encoder.encode(
`<script id="__CLERK_ASTRO_SAFE_VARS__" type="application/json">${JSON.stringify(getClientSafeEnv(locals))}</script>\n`,
);
const hotloadScript = encoder.encode(buildClerkHotloadScript(locals));

const stream = res.body!.pipeThrough(
new TransformStream({
Expand All @@ -279,10 +277,6 @@ async function decorateRequest(
controller.enqueue(clerkAstroData);
controller.enqueue(clerkSafeEnvVariables);

if (__HOTLOAD__) {
controller.enqueue(hotloadScript);
}

Comment on lines -282 to -285
Copy link
Member Author

@wobsoriano wobsoriano Jul 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are no longer attaching the hotload script to the Response since we're using the loadClerkJsScript shared function in client instead.

If for some reason the current implementation is performant than this one, we can adjust to 3-4 commits back where I only used the script builders to clean up some repeating logic but still build the hotload script on the server

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We definitely prefer the current implementation because it will result in faster loading times.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can still use loadClerkJsScript in the client but we will expect to read the existing script.

controller.enqueue(closingHeadTag);
controller.enqueue(chunk.slice(index + closingHeadTag.length));
} else {
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/stores/external.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { deriveState } from '@clerk/shared/deriveState';
import { eventMethodCalled } from '@clerk/shared/telemetry';
import { computed, onMount, type Store } from 'nanostores';

import { $clerk, $csrState, $initialState } from './internal';
import { deriveState } from './utils';

/**
* A client side store that is prepopulated with the authentication context during SSR.
Expand Down
1 change: 1 addition & 0 deletions packages/shared/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ export {};

declare global {
const PACKAGE_VERSION: string;
const JS_PACKAGE_VERSION: string;
const __DEV__: boolean;
}
5 changes: 5 additions & 0 deletions packages/shared/jest.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const { name } = require('./package.json');
const { version: clerkJsVersion } = require('../clerk-js/package.json');

/** @type {import('ts-jest').JestConfigWithTsJest} */
const config = {
Expand All @@ -17,6 +18,10 @@ const config = {
transform: {
'^.+\\.m?tsx?$': ['ts-jest', { tsconfig: 'tsconfig.test.json', diagnostics: false }],
},

globals: {
JS_PACKAGE_VERSION: clerkJsVersion,
},
};

module.exports = config;
3 changes: 3 additions & 0 deletions packages/shared/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,19 +51,22 @@
"cookie",
"date",
"deprecated",
"deriveState",
"error",
"file",
"globs",
"handleValueOrFn",
"isomorphicAtob",
"isomorphicBtoa",
"keys",
"loadClerkJsScript",
"loadScript",
"localStorageBroadcastChannel",
"poller",
"proxy",
"underscore",
"url",
"versionSelector",
"react",
"constants",
"apiUrlFromPublishableKey",
Expand Down
36 changes: 36 additions & 0 deletions packages/shared/src/__tests__/deriveState.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import type { InitialState, Resources } from '@clerk/types';

import { deriveState } from '../deriveState';

describe('deriveState', () => {
const mockInitialState = {
userId: 'user_2U330vGHg3llBga8Oi0fzzeNAaG',
sessionId: 'sess_2j1R7g3AUeKMx9M23dBO0XLEQGY',
orgId: 'org_2U330vGHg3llBga8Oi0fzzeNAaG',
} as InitialState;

const mockResources = {
client: {},
user: { id: mockInitialState.userId },
session: { id: mockInitialState.sessionId },
organization: { id: mockInitialState.orgId },
} as Resources;

it('uses SSR state when !clerkLoaded and initialState is provided', () => {
expect(deriveState(false, {} as Resources, mockInitialState)).toEqual(mockInitialState);
});

it('uses CSR state when clerkLoaded', () => {
const result = deriveState(true, mockResources, undefined);
expect(result.userId).toBe(mockInitialState.userId);
expect(result.sessionId).toBe(mockInitialState.sessionId);
expect(result.orgId).toBe(mockInitialState.orgId);
});

it('handles !clerkLoaded and undefined initialState', () => {
const result = deriveState(false, {} as Resources, undefined);
expect(result.userId).toBeUndefined();
expect(result.sessionId).toBeUndefined();
expect(result.orgId).toBeUndefined();
});
});
Loading