From 27b98bd43405a8b5b69085d4ed067def8937eb12 Mon Sep 17 00:00:00 2001 From: Andrew Bobkov Date: Mon, 12 Feb 2024 11:35:47 +0000 Subject: [PATCH 01/17] chore(valibot-validator): Replace `jsonT` in tests --- packages/valibot-validator/test/index.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/valibot-validator/test/index.test.ts b/packages/valibot-validator/test/index.test.ts index 20aebe88..9da7e817 100644 --- a/packages/valibot-validator/test/index.test.ts +++ b/packages/valibot-validator/test/index.test.ts @@ -16,7 +16,7 @@ describe('Basic', () => { const route = app.post('/author', vValidator('json', schema), (c) => { const data = c.req.valid('json') - return c.jsonT({ + return c.json({ success: true, message: `${data.name} is ${data.age}`, }) From cc02ada95e4b0f493cc0b8cc05f671af2278eca9 Mon Sep 17 00:00:00 2001 From: Andrew Bobkov Date: Mon, 12 Feb 2024 11:44:22 +0000 Subject: [PATCH 02/17] fix(valibot-validator): Handle optional schema --- packages/valibot-validator/src/index.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/valibot-validator/src/index.ts b/packages/valibot-validator/src/index.ts index 987324b0..2a8db08c 100644 --- a/packages/valibot-validator/src/index.ts +++ b/packages/valibot-validator/src/index.ts @@ -8,16 +8,18 @@ type Hook = ( c: Context ) => Response | Promise | void | Promise +type HasUndefined = undefined extends T ? true : false + export const vValidator = < T extends BaseSchema, Target extends keyof ValidationTargets, E extends Env, P extends string, V extends { - in: { [K in Target]: Input } + in: HasUndefined> extends true ? { [K in Target]?: Input } : { [K in Target]: Input } out: { [K in Target]: Output } } = { - in: { [K in Target]: Input } + in: HasUndefined> extends true ? { [K in Target]?: Input } : { [K in Target]: Input } out: { [K in Target]: Output } } >( From e754c260d802b703d024ddf3e8400252beb9e9fa Mon Sep 17 00:00:00 2001 From: Andrew Bobkov Date: Mon, 12 Feb 2024 11:44:32 +0000 Subject: [PATCH 03/17] test(valibot-validator): Update tests --- packages/valibot-validator/test/index.test.ts | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/packages/valibot-validator/test/index.test.ts b/packages/valibot-validator/test/index.test.ts index 9da7e817..683b62b9 100644 --- a/packages/valibot-validator/test/index.test.ts +++ b/packages/valibot-validator/test/index.test.ts @@ -1,6 +1,6 @@ import { Hono } from 'hono' import type { Equal, Expect } from 'hono/utils/types' -import { number, object, string } from 'valibot' +import { number, object, string, optional } from 'valibot' import { vValidator } from '../src' // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -14,11 +14,17 @@ describe('Basic', () => { age: number(), }) - const route = app.post('/author', vValidator('json', schema), (c) => { + const querySchema = optional(object({ + search: optional(string()) + })) + + const route = app.post('/author', vValidator('json', schema), vValidator('query', querySchema), (c) => { const data = c.req.valid('json') + const query = c.req.valid('query') + return c.json({ success: true, - message: `${data.name} is ${data.age}`, + message: `${data.name} is ${data.age}, search is ${query?.search}`, }) }) @@ -31,6 +37,10 @@ describe('Basic', () => { name: string age: number } + } & { + query?: { + search?: string | undefined + } | undefined } output: { success: boolean @@ -44,7 +54,7 @@ describe('Basic', () => { type verify = Expect> it('Should return 200 response', async () => { - const req = new Request('http://localhost/author', { + const req = new Request('http://localhost/author?search=hello', { body: JSON.stringify({ name: 'Superman', age: 20, @@ -59,7 +69,7 @@ describe('Basic', () => { expect(res.status).toBe(200) expect(await res.json()).toEqual({ success: true, - message: 'Superman is 20', + message: 'Superman is 20, search is hello', }) }) From 324b65e3275085cd5c2dd2436025266f6b3a2386 Mon Sep 17 00:00:00 2001 From: Andrew Bobkov Date: Mon, 12 Feb 2024 11:47:11 +0000 Subject: [PATCH 04/17] chore(valibot-validator): Add changeset --- .changeset/old-suns-matter.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/old-suns-matter.md diff --git a/.changeset/old-suns-matter.md b/.changeset/old-suns-matter.md new file mode 100644 index 00000000..25090a43 --- /dev/null +++ b/.changeset/old-suns-matter.md @@ -0,0 +1,5 @@ +--- +'@hono/valibot-validator': patch +--- + +fix(valibot-validator): make validation input optional when schema is optional From 90b2f1e7e122e0d013004e1c6319a2d57574f00a Mon Sep 17 00:00:00 2001 From: Andrew Bobkov Date: Mon, 12 Feb 2024 11:51:00 +0000 Subject: [PATCH 05/17] chore(valibot-validator): Fix formatting --- packages/valibot-validator/src/index.ts | 8 +++- packages/valibot-validator/test/index.test.ts | 37 ++++++++++++------- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/packages/valibot-validator/src/index.ts b/packages/valibot-validator/src/index.ts index 2a8db08c..23c51760 100644 --- a/packages/valibot-validator/src/index.ts +++ b/packages/valibot-validator/src/index.ts @@ -16,10 +16,14 @@ export const vValidator = < E extends Env, P extends string, V extends { - in: HasUndefined> extends true ? { [K in Target]?: Input } : { [K in Target]: Input } + in: HasUndefined> extends true + ? { [K in Target]?: Input } + : { [K in Target]: Input } out: { [K in Target]: Output } } = { - in: HasUndefined> extends true ? { [K in Target]?: Input } : { [K in Target]: Input } + in: HasUndefined> extends true + ? { [K in Target]?: Input } + : { [K in Target]: Input } out: { [K in Target]: Output } } >( diff --git a/packages/valibot-validator/test/index.test.ts b/packages/valibot-validator/test/index.test.ts index 683b62b9..c0073b67 100644 --- a/packages/valibot-validator/test/index.test.ts +++ b/packages/valibot-validator/test/index.test.ts @@ -14,19 +14,26 @@ describe('Basic', () => { age: number(), }) - const querySchema = optional(object({ - search: optional(string()) - })) + const querySchema = optional( + object({ + search: optional(string()), + }) + ) - const route = app.post('/author', vValidator('json', schema), vValidator('query', querySchema), (c) => { - const data = c.req.valid('json') - const query = c.req.valid('query') + const route = app.post( + '/author', + vValidator('json', schema), + vValidator('query', querySchema), + (c) => { + const data = c.req.valid('json') + const query = c.req.valid('query') - return c.json({ - success: true, - message: `${data.name} is ${data.age}, search is ${query?.search}`, - }) - }) + return c.json({ + success: true, + message: `${data.name} is ${data.age}, search is ${query?.search}`, + }) + } + ) type Actual = ExtractSchema type Expected = { @@ -38,9 +45,11 @@ describe('Basic', () => { age: number } } & { - query?: { - search?: string | undefined - } | undefined + query?: + | { + search?: string | undefined + } + | undefined } output: { success: boolean From 37ceb9dfe00b86a5e9bc9368cb5a6bb613d5cace Mon Sep 17 00:00:00 2001 From: Andrew Bobkov Date: Sat, 20 Apr 2024 13:25:53 +0000 Subject: [PATCH 06/17] remove old changeset --- .changeset/old-suns-matter.md | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 .changeset/old-suns-matter.md diff --git a/.changeset/old-suns-matter.md b/.changeset/old-suns-matter.md deleted file mode 100644 index 25090a43..00000000 --- a/.changeset/old-suns-matter.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hono/valibot-validator': patch ---- - -fix(valibot-validator): make validation input optional when schema is optional From f09a66102c61a6901ecc155e2795a96bdcf07850 Mon Sep 17 00:00:00 2001 From: Andrew Bobkov Date: Sat, 20 Apr 2024 14:20:15 +0000 Subject: [PATCH 07/17] feat(clerk-auth): Migrate to Clerk Core v2 --- packages/clerk-auth/jest.config.js | 4 - packages/clerk-auth/package.json | 9 +- packages/clerk-auth/src/index.ts | 50 +++----- packages/clerk-auth/test/index.test.ts | 99 +++++---------- yarn.lock | 159 +++++-------------------- 5 files changed, 87 insertions(+), 234 deletions(-) diff --git a/packages/clerk-auth/jest.config.js b/packages/clerk-auth/jest.config.js index c2e3e8a8..e7b24f3d 100644 --- a/packages/clerk-auth/jest.config.js +++ b/packages/clerk-auth/jest.config.js @@ -5,8 +5,4 @@ module.exports = { testMatch: ['**/test/**/*.+(ts|tsx|js)', '**/src/**/(*.)+(spec|test).+(ts|tsx|js)'], transform: { '^.+\\.m?tsx?$': 'ts-jest' }, testPathIgnorePatterns: ['/node_modules/', '/jest/'], - moduleNameMapper: { - '#crypto': '@clerk/backend/dist/runtime/node/crypto.js', - '#fetch': '@clerk/backend/dist/runtime/node/fetch.js', - }, } diff --git a/packages/clerk-auth/package.json b/packages/clerk-auth/package.json index 69a52add..51c180dc 100644 --- a/packages/clerk-auth/package.json +++ b/packages/clerk-auth/package.json @@ -24,16 +24,21 @@ }, "homepage": "https://github.com/honojs/middleware", "peerDependencies": { - "@clerk/backend": "0.30.*", + "@clerk/backend": "1", + "@clerk/shared": "2", "hono": ">=3.*" }, "devDependencies": { - "@clerk/backend": "^0.30.1", + "@clerk/backend": "1", + "@clerk/shared": "2", "@types/react": "^18", "hono": "^3.11.7", "jest": "^29.7.0", "node-fetch-native": "^1.4.0", "react": "^18.2.0", "rimraf": "^5.0.5" + }, + "engines": { + "node": ">=16.x.x" } } diff --git a/packages/clerk-auth/src/index.ts b/packages/clerk-auth/src/index.ts index a376ddbe..b89352ab 100644 --- a/packages/clerk-auth/src/index.ts +++ b/packages/clerk-auth/src/index.ts @@ -1,14 +1,13 @@ -import type { ClerkOptions } from '@clerk/backend' -import { Clerk, createIsomorphicRequest, constants } from '@clerk/backend' +import { type ClerkClient, type ClerkOptions, createClerkClient } from '@clerk/backend' +import type { RequestState } from '@clerk/backend/dist/tokens/authStatus' +import { PROD_API_URL } from '@clerk/shared' import type { Context, MiddlewareHandler } from 'hono' import { env } from 'hono/adapter' -type ClerkAuth = Awaited['authenticateRequest']>>['toAuth'] - declare module 'hono' { interface ContextVariableMap { - clerk: ReturnType - clerkAuth: ReturnType + clerk: ClerkClient + clerkAuth: ReturnType } } @@ -21,7 +20,6 @@ type ClerkEnv = { CLERK_PUBLISHABLE_KEY: string CLERK_API_URL: string CLERK_API_VERSION: string - CLERK_FRONTEND_API: string } export const clerkMiddleware = (options?: ClerkOptions): MiddlewareHandler => { @@ -30,10 +28,9 @@ export const clerkMiddleware = (options?: ClerkOptions): MiddlewareHandler => { const { secretKey, publishableKey, apiUrl, apiVersion, ...rest } = options || { secretKey: clerkEnv.CLERK_SECRET_KEY || '', publishableKey: clerkEnv.CLERK_PUBLISHABLE_KEY || '', - apiUrl: clerkEnv.CLERK_API_URL || 'https://api.clerk.dev', + apiUrl: clerkEnv.CLERK_API_URL || PROD_API_URL, apiVersion: clerkEnv.CLERK_API_VERSION || 'v1', } - const frontendApi = clerkEnv.CLERK_FRONTEND_API || '' if (!secretKey) { throw new Error('Missing Clerk Secret key') } @@ -42,7 +39,7 @@ export const clerkMiddleware = (options?: ClerkOptions): MiddlewareHandler => { throw new Error('Missing Clerk Publishable key') } - const clerkClient = Clerk({ + const clerkClient = createClerkClient({ ...rest, apiUrl, apiVersion, @@ -50,35 +47,26 @@ export const clerkMiddleware = (options?: ClerkOptions): MiddlewareHandler => { publishableKey, }) - const requestState = await clerkClient.authenticateRequest({ + const requestState = await clerkClient.authenticateRequest(c.req.raw, { ...rest, secretKey, publishableKey, - request: createIsomorphicRequest((Request) => { - return new Request(c.req.url, { - method: c.req.method, - headers: c.req.raw.headers, - }) - }), }) - // Interstitial cases - if (requestState.isUnknown) { - c.header(constants.Headers.AuthReason, requestState.reason) - c.header(constants.Headers.AuthMessage, requestState.message) - return c.body(null, 401) + // Append headers from clerk + if (requestState.headers) { + requestState.headers.forEach((value, key) => c.header(key, value, { append: true })) } - if (requestState.isInterstitial) { - const interstitialHtmlPage = clerkClient.localInterstitial({ - publishableKey, - frontendApi, - }) - - c.header(constants.Headers.AuthReason, requestState.reason) - c.header(constants.Headers.AuthMessage, requestState.message) + // Interstitial case + if (requestState.status === 'handshake') { + // Throw an error if state is handshake without a redirect (see https://github.com/clerk/javascript/blob/83ec173b08bdf18fda805e0d68e0034dbae0eb24/packages/sdk-node/src/authenticateRequest.ts#L72) + const hasLocationHeader = requestState.headers.get('location') + if (!hasLocationHeader) { + throw new Error('Clerk: unexpected handshake without redirect') + } - return c.html(interstitialHtmlPage, 401) + return c.body(null, 307) } c.set('clerkAuth', requestState.toAuth()) diff --git a/packages/clerk-auth/test/index.test.ts b/packages/clerk-auth/test/index.test.ts index b84b992f..74f58cfc 100644 --- a/packages/clerk-auth/test/index.test.ts +++ b/packages/clerk-auth/test/index.test.ts @@ -8,15 +8,13 @@ const EnvVariables = { } const authenticateRequestMock = jest.fn() -const localInterstitialMock = jest.fn() jest.mock('@clerk/backend', () => { return { ...jest.requireActual('@clerk/backend'), - Clerk: () => { + createClerkClient: () => { return { authenticateRequest: (...args: any) => authenticateRequestMock(...args), - localInterstitial: (...args: any) => localInterstitialMock(...args), } }, } @@ -36,10 +34,8 @@ describe('clerkMiddleware()', () => { }) test('handles signin with Authorization Bearer', async () => { - authenticateRequestMock.mockResolvedValue({ - isUnknown: false, - isInterstitial: false, - isSignedIn: true, + authenticateRequestMock.mockResolvedValueOnce({ + headers: new Headers(), toAuth: () => 'mockedAuth', }) const app = new Hono() @@ -67,20 +63,17 @@ describe('clerkMiddleware()', () => { expect(response.status).toEqual(200) expect(await response.json()).toEqual({ auth: 'mockedAuth' }) - expect(authenticateRequestMock).toBeCalledWith( + expect(authenticateRequestMock).toHaveBeenCalledWith( + expect.any(Request), expect.objectContaining({ secretKey: EnvVariables.CLERK_SECRET_KEY, - publishableKey: EnvVariables.CLERK_PUBLISHABLE_KEY, - request: expect.any(Request), - }) + }), ) }) test('handles signin with cookie', async () => { - authenticateRequestMock.mockResolvedValue({ - isUnknown: false, - isInterstitial: false, - isSignedIn: true, + authenticateRequestMock.mockResolvedValueOnce({ + headers: new Headers(), toAuth: () => 'mockedAuth', }) const app = new Hono() @@ -108,22 +101,25 @@ describe('clerkMiddleware()', () => { expect(response.status).toEqual(200) expect(await response.json()).toEqual({ auth: 'mockedAuth' }) - expect(authenticateRequestMock).toBeCalledWith( + expect(authenticateRequestMock).toHaveBeenCalledWith( + expect.any(Request), expect.objectContaining({ secretKey: EnvVariables.CLERK_SECRET_KEY, - publishableKey: EnvVariables.CLERK_PUBLISHABLE_KEY, - request: expect.any(Request), - }) + }), ) }) - test('handles unknown case by terminating the request with empty response and 401 http code', async () => { - authenticateRequestMock.mockResolvedValue({ - isUnknown: true, - isInterstitial: false, - isSignedIn: false, + test('handles handshake case by redirecting the request to fapi', async () => { + authenticateRequestMock.mockResolvedValueOnce({ + status: 'handshake', reason: 'auth-reason', message: 'auth-message', + headers: new Headers({ + location: 'https://fapi.example.com/v1/clients/handshake', + 'x-clerk-auth-message': 'auth-message', + 'x-clerk-auth-reason': 'auth-reason', + 'x-clerk-auth-status': 'handshake', + }), toAuth: () => 'mockedAuth', }) const app = new Hono() @@ -142,50 +138,18 @@ describe('clerkMiddleware()', () => { const response = await app.request(req) - expect(response.status).toEqual(401) - expect(response.headers.get('x-clerk-auth-reason')).toEqual('auth-reason') - expect(response.headers.get('x-clerk-auth-message')).toEqual('auth-message') - expect(await response.text()).toEqual('') - }) - - test('handles interstitial case by terminating the request with interstitial html page and 401 http code', async () => { - authenticateRequestMock.mockResolvedValue({ - isUnknown: false, - isInterstitial: true, - isSignedIn: false, - reason: 'auth-reason', - message: 'auth-message', - toAuth: () => 'mockedAuth', + expect(response.status).toEqual(307) + expect(Object.fromEntries(response.headers.entries())).toMatchObject({ + location: 'https://fapi.example.com/v1/clients/handshake', + 'x-clerk-auth-status': 'handshake', + 'x-clerk-auth-reason': 'auth-reason', + 'x-clerk-auth-message': 'auth-message', }) - localInterstitialMock.mockReturnValue('Interstitial') - const app = new Hono() - app.use('*', clerkMiddleware()) - - app.get('/', (ctx) => { - const auth = getAuth(ctx) - return ctx.json({ auth }) - }) - - const req = new Request('http://localhost/', { - headers: { - cookie: '_gcl_au=value1; ko_id=value2; __session=deadbeef; __client_uat=1675692233', - }, - }) - - const response = await app.request(req) - - expect(response.status).toEqual(401) - expect(response.headers.get('content-type')).toMatch('text/html') - expect(response.headers.get('x-clerk-auth-reason')).toEqual('auth-reason') - expect(response.headers.get('x-clerk-auth-message')).toEqual('auth-message') - expect(await response.text()).toEqual('Interstitial') }) test('handles signout case by populating the req.auth', async () => { - authenticateRequestMock.mockResolvedValue({ - isUnknown: false, - isInterstitial: false, - isSignedIn: false, + authenticateRequestMock.mockResolvedValueOnce({ + headers: new Headers(), toAuth: () => 'mockedAuth', }) const app = new Hono() @@ -206,12 +170,11 @@ describe('clerkMiddleware()', () => { expect(response.status).toEqual(200) expect(await response.json()).toEqual({ auth: 'mockedAuth' }) - expect(authenticateRequestMock).toBeCalledWith( + expect(authenticateRequestMock).toHaveBeenCalledWith( + expect.any(Request), expect.objectContaining({ secretKey: EnvVariables.CLERK_SECRET_KEY, - publishableKey: EnvVariables.CLERK_PUBLISHABLE_KEY, - request: expect.any(Request), - }) + }), ) }) }) diff --git a/yarn.lock b/yarn.lock index afd74818..3db3546c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -788,42 +788,35 @@ __metadata: languageName: node linkType: hard -"@clerk/backend@npm:^0.30.1": - version: 0.30.3 - resolution: "@clerk/backend@npm:0.30.3" - dependencies: - "@clerk/shared": "npm:0.24.3" - "@clerk/types": "npm:3.54.0" - "@peculiar/webcrypto": "npm:1.4.1" - "@types/node": "npm:16.18.6" +"@clerk/backend@npm:1": + version: 1.0.0 + resolution: "@clerk/backend@npm:1.0.0" + dependencies: + "@clerk/shared": "npm:2.0.0" cookie: "npm:0.5.0" - deepmerge: "npm:4.2.2" - node-fetch-native: "npm:1.0.1" snakecase-keys: "npm:5.4.4" tslib: "npm:2.4.1" - checksum: 558a15525d1a5f90a505e607408ed902f5e06f5c126c95fa4bf69623ec493276ff9ce199e3f2d47516fc0f324ca20bf021b5909be405c31e0f7123fdfa172c64 + checksum: 95c03aabba87abd60427aa59e91706a61075cc00ad02ef3dd3760abe76761a4358c5e45d1c17c8f85e8ec859a60fff66b6d0f9beeaadc51e4c2bbc0f2af77af9 languageName: node linkType: hard -"@clerk/shared@npm:0.24.3": - version: 0.24.3 - resolution: "@clerk/shared@npm:0.24.3" +"@clerk/shared@npm:2, @clerk/shared@npm:2.0.0": + version: 2.0.0 + resolution: "@clerk/shared@npm:2.0.0" dependencies: glob-to-regexp: "npm:0.4.1" js-cookie: "npm:3.0.1" + std-env: "npm:^3.7.0" swr: "npm:2.2.0" peerDependencies: - react: ">=16" - checksum: b204aeded6ef0d0ec843c3785fb857ec59cbe8609b7519ab73a3f43470752ee0cb910b1c205b6c3064105a3f8ebd5390d32c6cfc506476d219d39065cf3c25ba - languageName: node - linkType: hard - -"@clerk/types@npm:3.54.0": - version: 3.54.0 - resolution: "@clerk/types@npm:3.54.0" - dependencies: - csstype: "npm:3.1.1" - checksum: fb68a7cf471431a061e5adae0bbb4382952ccaa0a490649620a35cf0d46b4fbdb4909a766c92c2236c0c1abfeccbd9c12977cb0317a1f70854251d29444571e6 + react: ">=18" + react-dom: ">=18" + peerDependenciesMeta: + react: + optional: true + react-dom: + optional: true + checksum: 3423ac83d8b2dad30135ada38dc0b2d065f087c2315f80e94dc8fe8ba0b525a9c2aab8a4b57ad1c5cbef917759377d5175dc4a4faabf0917b6f28a8e19efeca5 languageName: node linkType: hard @@ -1818,7 +1811,8 @@ __metadata: version: 0.0.0-use.local resolution: "@hono/clerk-auth@workspace:packages/clerk-auth" dependencies: - "@clerk/backend": "npm:^0.30.1" + "@clerk/backend": "npm:1" + "@clerk/shared": "npm:2" "@types/react": "npm:^18" hono: "npm:^3.11.7" jest: "npm:^29.7.0" @@ -1826,7 +1820,8 @@ __metadata: react: "npm:^18.2.0" rimraf: "npm:^5.0.5" peerDependencies: - "@clerk/backend": 0.30.* + "@clerk/backend": 1 + "@clerk/shared": 2 hono: ">=3.*" languageName: unknown linkType: soft @@ -3299,39 +3294,6 @@ __metadata: languageName: node linkType: hard -"@peculiar/asn1-schema@npm:^2.3.0, @peculiar/asn1-schema@npm:^2.3.6": - version: 2.3.8 - resolution: "@peculiar/asn1-schema@npm:2.3.8" - dependencies: - asn1js: "npm:^3.0.5" - pvtsutils: "npm:^1.3.5" - tslib: "npm:^2.6.2" - checksum: 65f16b2a7eb91365b6dac47730ffcad4617ef04b821e0a4286c379ac7283588b0a6744032ee686e0914a0886c2a055108ed945b9c4d22821a3b123640b61f3b2 - languageName: node - linkType: hard - -"@peculiar/json-schema@npm:^1.1.12": - version: 1.1.12 - resolution: "@peculiar/json-schema@npm:1.1.12" - dependencies: - tslib: "npm:^2.0.0" - checksum: 202132c66dcc6b6aca5d0af971c015be2e163da2f7f992910783c5d39c8a7db59b6ec4f4ce419459a1f954b7e1d17b6b253f0e60072c1b3d254079f4eaebc311 - languageName: node - linkType: hard - -"@peculiar/webcrypto@npm:1.4.1": - version: 1.4.1 - resolution: "@peculiar/webcrypto@npm:1.4.1" - dependencies: - "@peculiar/asn1-schema": "npm:^2.3.0" - "@peculiar/json-schema": "npm:^1.1.12" - pvtsutils: "npm:^1.3.2" - tslib: "npm:^2.4.1" - webcrypto-core: "npm:^1.7.4" - checksum: 5acf1b025664525452e2b0748573b0f4100c6840d71ff5577188dfb81b97d463911deff17b4b0c3e59f35fe93c54fec4591f1c42f0a54dae1d5710a03c5e55d3 - languageName: node - linkType: hard - "@pkgjs/parseargs@npm:^0.11.0": version: 0.11.0 resolution: "@pkgjs/parseargs@npm:0.11.0" @@ -4074,13 +4036,6 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:16.18.6": - version: 16.18.6 - resolution: "@types/node@npm:16.18.6" - checksum: 88192f5cd3d21ca827898c903ce6fbb8a92a51d0f9d8f7e93ac3f2f3b46cdd9f29c969fe3af9ba004833bb265c6330042f37d11cd97b9e4f54dabf2b34399075 - languageName: node - linkType: hard - "@types/node@npm:^12.7.1": version: 12.20.55 resolution: "@types/node@npm:12.20.55" @@ -5241,17 +5196,6 @@ __metadata: languageName: node linkType: hard -"asn1js@npm:^3.0.1, asn1js@npm:^3.0.5": - version: 3.0.5 - resolution: "asn1js@npm:3.0.5" - dependencies: - pvtsutils: "npm:^1.3.2" - pvutils: "npm:^1.1.3" - tslib: "npm:^2.4.0" - checksum: bb8eaf4040c8f49dd475566874986f5976b81bae65a6b5526e2208a13cdca323e69ce297bcd435fdda3eb6933defe888e71974d705b6fcb14f2734a907f8aed4 - languageName: node - linkType: hard - "assertion-error@npm:^1.1.0": version: 1.1.0 resolution: "assertion-error@npm:1.1.0" @@ -6694,13 +6638,6 @@ __metadata: languageName: node linkType: hard -"csstype@npm:3.1.1": - version: 3.1.1 - resolution: "csstype@npm:3.1.1" - checksum: 7c8b8c5923049d84132581c13bae6e1faf999746fe3998ba5f3819a8e1cdc7512ace87b7d0a4a69f0f4b8ba11daf835d4f1390af23e09fc4f0baad52c084753a - languageName: node - linkType: hard - "csstype@npm:^3.0.2, csstype@npm:^3.1.2": version: 3.1.3 resolution: "csstype@npm:3.1.3" @@ -6911,13 +6848,6 @@ __metadata: languageName: node linkType: hard -"deepmerge@npm:4.2.2": - version: 4.2.2 - resolution: "deepmerge@npm:4.2.2" - checksum: d6136eee869057fea7a829aa2d10073ed49db5216e42a77cc737dd385334aab9b68dae22020a00c24c073d5f79cbbdd3f11b8d4fc87700d112ddaa0e1f968ef2 - languageName: node - linkType: hard - "deepmerge@npm:^4.2.2": version: 4.3.1 resolution: "deepmerge@npm:4.3.1" @@ -13777,13 +13707,6 @@ __metadata: languageName: node linkType: hard -"node-fetch-native@npm:1.0.1": - version: 1.0.1 - resolution: "node-fetch-native@npm:1.0.1" - checksum: 27841116388ea5309037400de7fa1003712e974dc57a048f78e5fc659fa80095403f34051c069096a9bd705c7445876d88624121365847f617520325693d67c8 - languageName: node - linkType: hard - "node-fetch-native@npm:^1.4.0": version: 1.4.1 resolution: "node-fetch-native@npm:1.4.1" @@ -15233,22 +15156,6 @@ __metadata: languageName: node linkType: hard -"pvtsutils@npm:^1.3.2, pvtsutils@npm:^1.3.5": - version: 1.3.5 - resolution: "pvtsutils@npm:1.3.5" - dependencies: - tslib: "npm:^2.6.1" - checksum: d425aed316907e0b447a459bfb97c55d22270c3cfdba5a07ec90da0737b0e40f4f1771a444636f85bb6a453de90ff8c6b5f4f6ddba7597977166af49974b4534 - languageName: node - linkType: hard - -"pvutils@npm:^1.1.3": - version: 1.1.3 - resolution: "pvutils@npm:1.1.3" - checksum: 23489e6b3c76b6afb6964a20f891d6bef092939f401c78bba186b2bfcdc7a13904a0af0a78f7933346510f8c1228d5ab02d3c80e968fd84d3c76ff98d8ec9aac - languageName: node - linkType: hard - "qs@npm:6.11.0": version: 6.11.0 resolution: "qs@npm:6.11.0" @@ -16561,6 +16468,13 @@ __metadata: languageName: node linkType: hard +"std-env@npm:^3.7.0": + version: 3.7.0 + resolution: "std-env@npm:3.7.0" + checksum: 60edf2d130a4feb7002974af3d5a5f3343558d1ccf8d9b9934d225c638606884db4a20d2fe6440a09605bca282af6b042ae8070a10490c0800d69e82e478f41e + languageName: node + linkType: hard + "stoppable@npm:^1.1.0": version: 1.1.0 resolution: "stoppable@npm:1.1.0" @@ -17418,7 +17332,7 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.0.0, tslib@npm:^2.0.1, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.2.0, tslib@npm:^2.4.0, tslib@npm:^2.4.1, tslib@npm:^2.6.1, tslib@npm:^2.6.2": +"tslib@npm:^2.0.1, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.2.0, tslib@npm:^2.4.0": version: 2.6.2 resolution: "tslib@npm:2.6.2" checksum: e03a8a4271152c8b26604ed45535954c0a45296e32445b4b87f8a5abdb2421f40b59b4ca437c4346af0f28179780d604094eb64546bee2019d903d01c6c19bdb @@ -18729,19 +18643,6 @@ __metadata: languageName: node linkType: hard -"webcrypto-core@npm:^1.7.4": - version: 1.7.7 - resolution: "webcrypto-core@npm:1.7.7" - dependencies: - "@peculiar/asn1-schema": "npm:^2.3.6" - "@peculiar/json-schema": "npm:^1.1.12" - asn1js: "npm:^3.0.1" - pvtsutils: "npm:^1.3.2" - tslib: "npm:^2.4.0" - checksum: 57f0bee4e6c39f04fe5fc5fa615f245b3a9d41b330855cd1c525b96e9124d94e6cd06a174cbe1ff63dcb3b296995ae516e3ff02bad94baddd2a4e1060a854282 - languageName: node - linkType: hard - "webidl-conversions@npm:^3.0.0": version: 3.0.1 resolution: "webidl-conversions@npm:3.0.1" From 2c91344f9fac1de5ccffa4d216540fae3d5b02fb Mon Sep 17 00:00:00 2001 From: Andrew Bobkov Date: Sat, 20 Apr 2024 14:21:52 +0000 Subject: [PATCH 08/17] chore: Add changeset --- .changeset/lazy-pumpkins-help.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/lazy-pumpkins-help.md diff --git a/.changeset/lazy-pumpkins-help.md b/.changeset/lazy-pumpkins-help.md new file mode 100644 index 00000000..81623744 --- /dev/null +++ b/.changeset/lazy-pumpkins-help.md @@ -0,0 +1,5 @@ +--- +'@hono/clerk-auth': major +--- + +Migrate to Clerk Core v2 From adc5f3cb03d0c4206e21bf42370dcb2909a268bc Mon Sep 17 00:00:00 2001 From: Andrew Bobkov Date: Sat, 20 Apr 2024 14:34:31 +0000 Subject: [PATCH 09/17] fix: Add back tsup devDep --- packages/clerk-auth/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/clerk-auth/package.json b/packages/clerk-auth/package.json index 50eb61fd..42dc313c 100644 --- a/packages/clerk-auth/package.json +++ b/packages/clerk-auth/package.json @@ -50,6 +50,7 @@ "jest": "^29.7.0", "node-fetch-native": "^1.4.0", "react": "^18.2.0", + "tsup": "^8.0.1", "rimraf": "^5.0.5" }, "engines": { From 14c704a7f3e139508907471d676adfecb65e8a6e Mon Sep 17 00:00:00 2001 From: Andrew Bobkov Date: Sat, 20 Apr 2024 14:35:31 +0000 Subject: [PATCH 10/17] chore: Fix lockfile --- packages/clerk-auth/package.json | 4 ++-- yarn.lock | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/clerk-auth/package.json b/packages/clerk-auth/package.json index 42dc313c..e13c39c7 100644 --- a/packages/clerk-auth/package.json +++ b/packages/clerk-auth/package.json @@ -50,8 +50,8 @@ "jest": "^29.7.0", "node-fetch-native": "^1.4.0", "react": "^18.2.0", - "tsup": "^8.0.1", - "rimraf": "^5.0.5" + "rimraf": "^5.0.5", + "tsup": "^8.0.1" }, "engines": { "node": ">=16.x.x" diff --git a/yarn.lock b/yarn.lock index bfeaa03d..6c63dd06 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1818,6 +1818,7 @@ __metadata: jest: "npm:^29.7.0" node-fetch-native: "npm:^1.4.0" react: "npm:^18.2.0" + rimraf: "npm:^5.0.5" tsup: "npm:^8.0.1" peerDependencies: "@clerk/backend": 1 From c467cf41025018a08b18704541b82d7b695b9628 Mon Sep 17 00:00:00 2001 From: Andrew Bobkov Date: Sun, 21 Apr 2024 15:53:51 +0000 Subject: [PATCH 11/17] chore: infer clerkAuth type instead of importing it directly --- packages/clerk-auth/src/index.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/clerk-auth/src/index.ts b/packages/clerk-auth/src/index.ts index b89352ab..c5b13df5 100644 --- a/packages/clerk-auth/src/index.ts +++ b/packages/clerk-auth/src/index.ts @@ -1,13 +1,14 @@ import { type ClerkClient, type ClerkOptions, createClerkClient } from '@clerk/backend' -import type { RequestState } from '@clerk/backend/dist/tokens/authStatus' import { PROD_API_URL } from '@clerk/shared' import type { Context, MiddlewareHandler } from 'hono' import { env } from 'hono/adapter' +type ClerkAuth = ReturnType>['toAuth']> + declare module 'hono' { interface ContextVariableMap { clerk: ClerkClient - clerkAuth: ReturnType + clerkAuth: ClerkAuth } } From 7c08e24589b9c8af05bd440df5c5a3869f00ca94 Mon Sep 17 00:00:00 2001 From: Andrew Bobkov Date: Sun, 21 Apr 2024 15:57:08 +0000 Subject: [PATCH 12/17] chore: refactor redirect handling --- packages/clerk-auth/src/index.ts | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/packages/clerk-auth/src/index.ts b/packages/clerk-auth/src/index.ts index c5b13df5..5522708b 100644 --- a/packages/clerk-auth/src/index.ts +++ b/packages/clerk-auth/src/index.ts @@ -54,20 +54,16 @@ export const clerkMiddleware = (options?: ClerkOptions): MiddlewareHandler => { publishableKey, }) - // Append headers from clerk if (requestState.headers) { - requestState.headers.forEach((value, key) => c.header(key, value, { append: true })) - } + requestState.headers.forEach((value, key) => c.res.headers.append(key, value)) - // Interstitial case - if (requestState.status === 'handshake') { - // Throw an error if state is handshake without a redirect (see https://github.com/clerk/javascript/blob/83ec173b08bdf18fda805e0d68e0034dbae0eb24/packages/sdk-node/src/authenticateRequest.ts#L72) - const hasLocationHeader = requestState.headers.get('location') - if (!hasLocationHeader) { + const locationHeader = requestState.headers.get('location') + + if (locationHeader) { + return c.redirect(locationHeader, 307) + } else if (requestState.status === 'handshake') { throw new Error('Clerk: unexpected handshake without redirect') } - - return c.body(null, 307) } c.set('clerkAuth', requestState.toAuth()) From 9f250d588a01e510c7d99a15ef087770790c695c Mon Sep 17 00:00:00 2001 From: Andrew Bobkov Date: Sun, 21 Apr 2024 16:00:36 +0000 Subject: [PATCH 13/17] chore: remove unnecessary `rimraf` devDep --- packages/clerk-auth/package.json | 1 - yarn.lock | 1 - 2 files changed, 2 deletions(-) diff --git a/packages/clerk-auth/package.json b/packages/clerk-auth/package.json index e13c39c7..0b2c20c9 100644 --- a/packages/clerk-auth/package.json +++ b/packages/clerk-auth/package.json @@ -50,7 +50,6 @@ "jest": "^29.7.0", "node-fetch-native": "^1.4.0", "react": "^18.2.0", - "rimraf": "^5.0.5", "tsup": "^8.0.1" }, "engines": { diff --git a/yarn.lock b/yarn.lock index 6c63dd06..bfeaa03d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1818,7 +1818,6 @@ __metadata: jest: "npm:^29.7.0" node-fetch-native: "npm:^1.4.0" react: "npm:^18.2.0" - rimraf: "npm:^5.0.5" tsup: "npm:^8.0.1" peerDependencies: "@clerk/backend": 1 From 00d66b41136d6228796871e2d01b9e77c4e265c4 Mon Sep 17 00:00:00 2001 From: Andrew Bobkov Date: Sun, 21 Apr 2024 16:01:45 +0000 Subject: [PATCH 14/17] chore: rewrite clerk devDeps versions --- packages/clerk-auth/package.json | 4 ++-- yarn.lock | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/clerk-auth/package.json b/packages/clerk-auth/package.json index 0b2c20c9..3e2a30ff 100644 --- a/packages/clerk-auth/package.json +++ b/packages/clerk-auth/package.json @@ -43,8 +43,8 @@ "hono": ">=3.*" }, "devDependencies": { - "@clerk/backend": "1", - "@clerk/shared": "2", + "@clerk/backend": "^1.0.0", + "@clerk/shared": "^2.0.0", "@types/react": "^18", "hono": "^3.11.7", "jest": "^29.7.0", diff --git a/yarn.lock b/yarn.lock index bfeaa03d..a9583f18 100644 --- a/yarn.lock +++ b/yarn.lock @@ -788,7 +788,7 @@ __metadata: languageName: node linkType: hard -"@clerk/backend@npm:1": +"@clerk/backend@npm:^1.0.0": version: 1.0.0 resolution: "@clerk/backend@npm:1.0.0" dependencies: @@ -800,7 +800,7 @@ __metadata: languageName: node linkType: hard -"@clerk/shared@npm:2, @clerk/shared@npm:2.0.0": +"@clerk/shared@npm:2.0.0, @clerk/shared@npm:^2.0.0": version: 2.0.0 resolution: "@clerk/shared@npm:2.0.0" dependencies: @@ -1811,8 +1811,8 @@ __metadata: version: 0.0.0-use.local resolution: "@hono/clerk-auth@workspace:packages/clerk-auth" dependencies: - "@clerk/backend": "npm:1" - "@clerk/shared": "npm:2" + "@clerk/backend": "npm:^1.0.0" + "@clerk/shared": "npm:^2.0.0" "@types/react": "npm:^18" hono: "npm:^3.11.7" jest: "npm:^29.7.0" From d331d6ef85ea6a173ade7f825ee546f9a83912f0 Mon Sep 17 00:00:00 2001 From: Andrew Bobkov Date: Wed, 24 Apr 2024 18:02:38 +0000 Subject: [PATCH 15/17] chore: fix peerDeps --- packages/clerk-auth/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/clerk-auth/package.json b/packages/clerk-auth/package.json index 3e2a30ff..41671d04 100644 --- a/packages/clerk-auth/package.json +++ b/packages/clerk-auth/package.json @@ -38,8 +38,8 @@ }, "homepage": "https://github.com/honojs/middleware", "peerDependencies": { - "@clerk/backend": "1", - "@clerk/shared": "2", + "@clerk/backend": "^1.0.0", + "@clerk/shared": "^2.0.0", "hono": ">=3.*" }, "devDependencies": { From cfec020a4c6a527467fad9e18b3201636719f407 Mon Sep 17 00:00:00 2001 From: Andrew Bobkov Date: Wed, 24 Apr 2024 18:02:55 +0000 Subject: [PATCH 16/17] chore: update lockfile --- yarn.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn.lock b/yarn.lock index a9583f18..47f96c0d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1820,8 +1820,8 @@ __metadata: react: "npm:^18.2.0" tsup: "npm:^8.0.1" peerDependencies: - "@clerk/backend": 1 - "@clerk/shared": 2 + "@clerk/backend": ^1.0.0 + "@clerk/shared": ^2.0.0 hono: ">=3.*" languageName: unknown linkType: soft From 8310fe1fa627f0768f9b257f3e87583641356886 Mon Sep 17 00:00:00 2001 From: Andrew Bobkov Date: Thu, 25 Apr 2024 09:49:19 +0000 Subject: [PATCH 17/17] drop `@clerk/shared` peerDep --- packages/clerk-auth/package.json | 2 -- packages/clerk-auth/src/index.ts | 5 ++--- yarn.lock | 4 +--- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/packages/clerk-auth/package.json b/packages/clerk-auth/package.json index 41671d04..e3e87a12 100644 --- a/packages/clerk-auth/package.json +++ b/packages/clerk-auth/package.json @@ -39,12 +39,10 @@ "homepage": "https://github.com/honojs/middleware", "peerDependencies": { "@clerk/backend": "^1.0.0", - "@clerk/shared": "^2.0.0", "hono": ">=3.*" }, "devDependencies": { "@clerk/backend": "^1.0.0", - "@clerk/shared": "^2.0.0", "@types/react": "^18", "hono": "^3.11.7", "jest": "^29.7.0", diff --git a/packages/clerk-auth/src/index.ts b/packages/clerk-auth/src/index.ts index 5522708b..0cbc657b 100644 --- a/packages/clerk-auth/src/index.ts +++ b/packages/clerk-auth/src/index.ts @@ -1,5 +1,4 @@ import { type ClerkClient, type ClerkOptions, createClerkClient } from '@clerk/backend' -import { PROD_API_URL } from '@clerk/shared' import type { Context, MiddlewareHandler } from 'hono' import { env } from 'hono/adapter' @@ -29,8 +28,8 @@ export const clerkMiddleware = (options?: ClerkOptions): MiddlewareHandler => { const { secretKey, publishableKey, apiUrl, apiVersion, ...rest } = options || { secretKey: clerkEnv.CLERK_SECRET_KEY || '', publishableKey: clerkEnv.CLERK_PUBLISHABLE_KEY || '', - apiUrl: clerkEnv.CLERK_API_URL || PROD_API_URL, - apiVersion: clerkEnv.CLERK_API_VERSION || 'v1', + apiUrl: clerkEnv.CLERK_API_URL, + apiVersion: clerkEnv.CLERK_API_VERSION, } if (!secretKey) { throw new Error('Missing Clerk Secret key') diff --git a/yarn.lock b/yarn.lock index 47f96c0d..175647e3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -800,7 +800,7 @@ __metadata: languageName: node linkType: hard -"@clerk/shared@npm:2.0.0, @clerk/shared@npm:^2.0.0": +"@clerk/shared@npm:2.0.0": version: 2.0.0 resolution: "@clerk/shared@npm:2.0.0" dependencies: @@ -1812,7 +1812,6 @@ __metadata: resolution: "@hono/clerk-auth@workspace:packages/clerk-auth" dependencies: "@clerk/backend": "npm:^1.0.0" - "@clerk/shared": "npm:^2.0.0" "@types/react": "npm:^18" hono: "npm:^3.11.7" jest: "npm:^29.7.0" @@ -1821,7 +1820,6 @@ __metadata: tsup: "npm:^8.0.1" peerDependencies: "@clerk/backend": ^1.0.0 - "@clerk/shared": ^2.0.0 hono: ">=3.*" languageName: unknown linkType: soft