@clerk/hono 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +154 -0
- package/dist/index.d.mts +58 -0
- package/dist/index.d.ts +58 -0
- package/dist/index.js +101 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +73 -0
- package/dist/index.mjs.map +1 -0
- package/dist/types.d.mts +14 -0
- package/dist/types.d.ts +14 -0
- package/dist/types.js +19 -0
- package/dist/types.js.map +1 -0
- package/dist/types.mjs +1 -0
- package/dist/types.mjs.map +1 -0
- package/dist/webhooks.d.mts +33 -0
- package/dist/webhooks.d.ts +33 -0
- package/dist/webhooks.js +41 -0
- package/dist/webhooks.js.map +1 -0
- package/dist/webhooks.mjs +14 -0
- package/dist/webhooks.mjs.map +1 -0
- package/package.json +91 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 Clerk Inc
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://clerk.com?utm_source=github&utm_medium=clerk_hono" target="_blank" rel="noopener noreferrer">
|
|
3
|
+
<picture>
|
|
4
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://images.clerk.com/static/logo-dark-mode-400x400.png">
|
|
5
|
+
<img src="https://images.clerk.com/static/logo-light-mode-400x400.png" height="64">
|
|
6
|
+
</picture>
|
|
7
|
+
</a>
|
|
8
|
+
<br />
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
# @clerk/hono
|
|
12
|
+
|
|
13
|
+
<div align="center">
|
|
14
|
+
|
|
15
|
+
[](https://clerk.com/discord)
|
|
16
|
+
[](https://clerk.com/docs?utm_source=github&utm_medium=clerk_hono)
|
|
17
|
+
[](https://twitter.com/intent/follow?screen_name=ClerkDev)
|
|
18
|
+
|
|
19
|
+
[Changelog](https://github.com/clerk/javascript/blob/main/packages/hono/CHANGELOG.md)
|
|
20
|
+
·
|
|
21
|
+
[Report a Bug](https://github.com/clerk/javascript/issues/new?assignees=&labels=needs-triage&projects=&template=BUG_REPORT.yml)
|
|
22
|
+
·
|
|
23
|
+
[Request a Feature](https://feedback.clerk.com/roadmap)
|
|
24
|
+
·
|
|
25
|
+
[Get help](https://clerk.com/contact/support?utm_source=github&utm_medium=clerk_hono)
|
|
26
|
+
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
## Getting Started
|
|
30
|
+
|
|
31
|
+
[Clerk](https://clerk.com/?utm_source=github&utm_medium=clerk_hono) is the easiest way to add authentication and user management to your Hono application. Add sign up, sign in, and profile management to your application in minutes.
|
|
32
|
+
|
|
33
|
+
### Prerequisites
|
|
34
|
+
|
|
35
|
+
- Hono 4+
|
|
36
|
+
- Node.js 20+
|
|
37
|
+
|
|
38
|
+
### Installation
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
npm install @clerk/hono
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Configuration
|
|
45
|
+
|
|
46
|
+
Set your Clerk API keys as environment variables:
|
|
47
|
+
|
|
48
|
+
```sh
|
|
49
|
+
CLERK_SECRET_KEY=sk_****
|
|
50
|
+
CLERK_PUBLISHABLE_KEY=pk_****
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Usage
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
import { Hono } from 'hono';
|
|
57
|
+
import { clerkMiddleware, getAuth } from '@clerk/hono';
|
|
58
|
+
|
|
59
|
+
const app = new Hono();
|
|
60
|
+
|
|
61
|
+
// Apply Clerk middleware to all routes
|
|
62
|
+
app.use('*', clerkMiddleware());
|
|
63
|
+
|
|
64
|
+
// Public route
|
|
65
|
+
app.get('/', c => {
|
|
66
|
+
return c.json({ message: 'Hello!' });
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// Protected route
|
|
70
|
+
app.get('/protected', c => {
|
|
71
|
+
const { userId } = getAuth(c);
|
|
72
|
+
|
|
73
|
+
if (!userId) {
|
|
74
|
+
return c.json({ error: 'Unauthorized' }, 401);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return c.json({ message: 'Hello authenticated user!', userId });
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
export default app;
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Accessing the Clerk Client
|
|
84
|
+
|
|
85
|
+
You can access the Clerk Backend API client directly from the context:
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
app.get('/user/:id', async c => {
|
|
89
|
+
const clerkClient = c.get('clerk');
|
|
90
|
+
const user = await clerkClient.users.getUser(c.req.param('id'));
|
|
91
|
+
return c.json({ user });
|
|
92
|
+
});
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Using `acceptsToken` for Machine Auth
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
app.get('/api', c => {
|
|
99
|
+
const auth = getAuth(c, { acceptsToken: 'api_key' });
|
|
100
|
+
|
|
101
|
+
if (!auth.userId) {
|
|
102
|
+
return c.json({ error: 'Unauthorized' }, 401);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return c.json({ message: 'API access granted' });
|
|
106
|
+
});
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Webhook Verification
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
import { Hono } from 'hono';
|
|
113
|
+
import { verifyWebhook } from '@clerk/hono/webhooks';
|
|
114
|
+
|
|
115
|
+
const app = new Hono();
|
|
116
|
+
|
|
117
|
+
app.post('/webhooks/clerk', async c => {
|
|
118
|
+
const evt = await verifyWebhook(c);
|
|
119
|
+
|
|
120
|
+
switch (evt.type) {
|
|
121
|
+
case 'user.created':
|
|
122
|
+
console.log('User created:', evt.data.id);
|
|
123
|
+
break;
|
|
124
|
+
// Handle other event types...
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return c.json({ received: true });
|
|
128
|
+
});
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Support
|
|
132
|
+
|
|
133
|
+
You can get in touch with us in any of the following ways:
|
|
134
|
+
|
|
135
|
+
- Join our official community [Discord server](https://clerk.com/discord)
|
|
136
|
+
- On [our support page](https://clerk.com/contact/support?utm_source=github&utm_medium=clerk_hono)
|
|
137
|
+
|
|
138
|
+
## Contributing
|
|
139
|
+
|
|
140
|
+
We're open to all community contributions! If you'd like to contribute in any way, please read [our contribution guidelines](https://github.com/clerk/javascript/blob/main/docs/CONTRIBUTING.md) and [code of conduct](https://github.com/clerk/javascript/blob/main/docs/CODE_OF_CONDUCT.md).
|
|
141
|
+
|
|
142
|
+
## Security
|
|
143
|
+
|
|
144
|
+
`@clerk/hono` follows good practices of security, but 100% security cannot be assured.
|
|
145
|
+
|
|
146
|
+
`@clerk/hono` is provided **"as is"** without any **warranty**. Use at your own risk.
|
|
147
|
+
|
|
148
|
+
_For more information and to report security issues, please refer to our [security documentation](https://github.com/clerk/javascript/blob/main/docs/SECURITY.md)._
|
|
149
|
+
|
|
150
|
+
## License
|
|
151
|
+
|
|
152
|
+
This project is licensed under the **MIT license**.
|
|
153
|
+
|
|
154
|
+
See [LICENSE](https://github.com/clerk/javascript/blob/main/packages/hono/LICENSE) for more information.
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { AuthenticateRequestOptions, GetAuthFn } from '@clerk/backend/internal';
|
|
2
|
+
import { MiddlewareHandler, Context } from 'hono';
|
|
3
|
+
import { ClerkHonoVariables } from './types.mjs';
|
|
4
|
+
import '@clerk/shared/types';
|
|
5
|
+
import '@clerk/backend';
|
|
6
|
+
|
|
7
|
+
type ClerkMiddlewareOptions = Omit<AuthenticateRequestOptions, 'acceptsToken'>;
|
|
8
|
+
/**
|
|
9
|
+
* Clerk middleware for Hono that authenticates requests and attaches
|
|
10
|
+
* auth data to the Hono context.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* import { Hono } from 'hono';
|
|
15
|
+
* import { clerkMiddleware, getAuth } from '@clerk/hono';
|
|
16
|
+
*
|
|
17
|
+
* const app = new Hono();
|
|
18
|
+
* app.use('*', clerkMiddleware());
|
|
19
|
+
*
|
|
20
|
+
* app.get('/', (c) => {
|
|
21
|
+
* const { userId } = getAuth(c);
|
|
22
|
+
* return c.json({ userId });
|
|
23
|
+
* });
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
declare const clerkMiddleware: (options?: ClerkMiddlewareOptions) => MiddlewareHandler;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Retrieves the Clerk auth object from the Hono context.
|
|
30
|
+
* Must be used after clerkMiddleware() has been applied.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* app.get('/protected', (c) => {
|
|
35
|
+
* const { userId } = getAuth(c);
|
|
36
|
+
* if (!userId) {
|
|
37
|
+
* return c.json({ error: 'Unauthorized' }, 401);
|
|
38
|
+
* }
|
|
39
|
+
* return c.json({ message: 'Hello!' });
|
|
40
|
+
* });
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* @example Using acceptsToken for API keys
|
|
44
|
+
* ```ts
|
|
45
|
+
* app.get('/api', (c) => {
|
|
46
|
+
* const auth = getAuth(c, { acceptsToken: 'api_key' });
|
|
47
|
+
* // auth will be typed for API key tokens
|
|
48
|
+
* });
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
declare const getAuth: GetAuthFn<Context>;
|
|
52
|
+
|
|
53
|
+
declare module 'hono' {
|
|
54
|
+
interface ContextVariableMap extends ClerkHonoVariables {
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export { ClerkHonoVariables, type ClerkMiddlewareOptions, clerkMiddleware, getAuth };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { AuthenticateRequestOptions, GetAuthFn } from '@clerk/backend/internal';
|
|
2
|
+
import { MiddlewareHandler, Context } from 'hono';
|
|
3
|
+
import { ClerkHonoVariables } from './types.js';
|
|
4
|
+
import '@clerk/shared/types';
|
|
5
|
+
import '@clerk/backend';
|
|
6
|
+
|
|
7
|
+
type ClerkMiddlewareOptions = Omit<AuthenticateRequestOptions, 'acceptsToken'>;
|
|
8
|
+
/**
|
|
9
|
+
* Clerk middleware for Hono that authenticates requests and attaches
|
|
10
|
+
* auth data to the Hono context.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* import { Hono } from 'hono';
|
|
15
|
+
* import { clerkMiddleware, getAuth } from '@clerk/hono';
|
|
16
|
+
*
|
|
17
|
+
* const app = new Hono();
|
|
18
|
+
* app.use('*', clerkMiddleware());
|
|
19
|
+
*
|
|
20
|
+
* app.get('/', (c) => {
|
|
21
|
+
* const { userId } = getAuth(c);
|
|
22
|
+
* return c.json({ userId });
|
|
23
|
+
* });
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
declare const clerkMiddleware: (options?: ClerkMiddlewareOptions) => MiddlewareHandler;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Retrieves the Clerk auth object from the Hono context.
|
|
30
|
+
* Must be used after clerkMiddleware() has been applied.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* app.get('/protected', (c) => {
|
|
35
|
+
* const { userId } = getAuth(c);
|
|
36
|
+
* if (!userId) {
|
|
37
|
+
* return c.json({ error: 'Unauthorized' }, 401);
|
|
38
|
+
* }
|
|
39
|
+
* return c.json({ message: 'Hello!' });
|
|
40
|
+
* });
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* @example Using acceptsToken for API keys
|
|
44
|
+
* ```ts
|
|
45
|
+
* app.get('/api', (c) => {
|
|
46
|
+
* const auth = getAuth(c, { acceptsToken: 'api_key' });
|
|
47
|
+
* // auth will be typed for API key tokens
|
|
48
|
+
* });
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
declare const getAuth: GetAuthFn<Context>;
|
|
52
|
+
|
|
53
|
+
declare module 'hono' {
|
|
54
|
+
interface ContextVariableMap extends ClerkHonoVariables {
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export { ClerkHonoVariables, type ClerkMiddlewareOptions, clerkMiddleware, getAuth };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
clerkMiddleware: () => clerkMiddleware,
|
|
24
|
+
getAuth: () => getAuth
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(src_exports);
|
|
27
|
+
|
|
28
|
+
// src/clerkMiddleware.ts
|
|
29
|
+
var import_backend = require("@clerk/backend");
|
|
30
|
+
var import_internal = require("@clerk/backend/internal");
|
|
31
|
+
var import_adapter = require("hono/adapter");
|
|
32
|
+
var clerkMiddleware = (options) => {
|
|
33
|
+
return async (c, next) => {
|
|
34
|
+
const clerkEnv = (0, import_adapter.env)(c);
|
|
35
|
+
const { secretKey, publishableKey, apiUrl, apiVersion, ...rest } = options || {
|
|
36
|
+
secretKey: clerkEnv.CLERK_SECRET_KEY || "",
|
|
37
|
+
publishableKey: clerkEnv.CLERK_PUBLISHABLE_KEY || "",
|
|
38
|
+
apiUrl: clerkEnv.CLERK_API_URL,
|
|
39
|
+
apiVersion: clerkEnv.CLERK_API_VERSION
|
|
40
|
+
};
|
|
41
|
+
if (!secretKey) {
|
|
42
|
+
throw new Error(
|
|
43
|
+
"Clerk: Missing Secret Key. Set CLERK_SECRET_KEY in your environment or pass secretKey to clerkMiddleware()."
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
if (!publishableKey) {
|
|
47
|
+
throw new Error(
|
|
48
|
+
"Clerk: Missing Publishable Key. Set CLERK_PUBLISHABLE_KEY in your environment or pass publishableKey to clerkMiddleware()."
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
const clerkClient = (0, import_backend.createClerkClient)({
|
|
52
|
+
...rest,
|
|
53
|
+
apiUrl,
|
|
54
|
+
apiVersion,
|
|
55
|
+
secretKey,
|
|
56
|
+
publishableKey,
|
|
57
|
+
userAgent: `${"@clerk/hono"}@${"0.0.1"}`
|
|
58
|
+
});
|
|
59
|
+
const requestState = await clerkClient.authenticateRequest(c.req.raw, {
|
|
60
|
+
...rest,
|
|
61
|
+
secretKey,
|
|
62
|
+
publishableKey,
|
|
63
|
+
acceptsToken: "any"
|
|
64
|
+
});
|
|
65
|
+
if (requestState.headers) {
|
|
66
|
+
requestState.headers.forEach((value, key) => {
|
|
67
|
+
c.res.headers.append(key, value);
|
|
68
|
+
});
|
|
69
|
+
const locationHeader = requestState.headers.get("location");
|
|
70
|
+
if (locationHeader) {
|
|
71
|
+
return c.redirect(locationHeader, 307);
|
|
72
|
+
} else if (requestState.status === "handshake") {
|
|
73
|
+
throw new Error("Clerk: Unexpected handshake without redirect");
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const authObjectFn = ((authOptions) => (0, import_internal.getAuthObjectForAcceptedToken)({
|
|
77
|
+
authObject: requestState.toAuth(authOptions),
|
|
78
|
+
acceptsToken: "any"
|
|
79
|
+
}));
|
|
80
|
+
c.set("clerkAuth", authObjectFn);
|
|
81
|
+
c.set("clerk", clerkClient);
|
|
82
|
+
await next();
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
// src/getAuth.ts
|
|
87
|
+
var getAuth = ((c, options) => {
|
|
88
|
+
const authFn = c.get("clerkAuth");
|
|
89
|
+
if (!authFn) {
|
|
90
|
+
throw new Error(
|
|
91
|
+
"Clerk: getAuth() called without clerkMiddleware() being applied. Make sure to use clerkMiddleware() before calling getAuth()."
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
return authFn(options);
|
|
95
|
+
});
|
|
96
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
97
|
+
0 && (module.exports = {
|
|
98
|
+
clerkMiddleware,
|
|
99
|
+
getAuth
|
|
100
|
+
});
|
|
101
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/clerkMiddleware.ts","../src/getAuth.ts"],"sourcesContent":["export { clerkMiddleware } from './clerkMiddleware';\nexport type { ClerkMiddlewareOptions } from './clerkMiddleware';\n\nexport { getAuth } from './getAuth';\n\nimport type { ClerkHonoVariables } from './types';\nexport type { ClerkHonoVariables };\n\n// Augment Hono's ContextVariableMap so users get type inference\n// for c.get('clerk') and c.get('clerkAuth')\ndeclare module 'hono' {\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n interface ContextVariableMap extends ClerkHonoVariables {}\n}\n","import type { AuthObject } from '@clerk/backend';\nimport { createClerkClient } from '@clerk/backend';\nimport type { AuthenticateRequestOptions, AuthOptions, GetAuthFnNoRequest } from '@clerk/backend/internal';\nimport { getAuthObjectForAcceptedToken } from '@clerk/backend/internal';\nimport type { MiddlewareHandler } from 'hono';\nimport { env } from 'hono/adapter';\n\ntype ClerkEnv = {\n CLERK_SECRET_KEY: string;\n CLERK_PUBLISHABLE_KEY: string;\n CLERK_API_URL?: string;\n CLERK_API_VERSION?: string;\n};\n\nexport type ClerkMiddlewareOptions = Omit<AuthenticateRequestOptions, 'acceptsToken'>;\n\n/**\n * Clerk middleware for Hono that authenticates requests and attaches\n * auth data to the Hono context.\n *\n * @example\n * ```ts\n * import { Hono } from 'hono';\n * import { clerkMiddleware, getAuth } from '@clerk/hono';\n *\n * const app = new Hono();\n * app.use('*', clerkMiddleware());\n *\n * app.get('/', (c) => {\n * const { userId } = getAuth(c);\n * return c.json({ userId });\n * });\n * ```\n */\nexport const clerkMiddleware = (options?: ClerkMiddlewareOptions): MiddlewareHandler => {\n return async (c, next) => {\n const clerkEnv = env<ClerkEnv>(c);\n const { secretKey, publishableKey, apiUrl, apiVersion, ...rest } = options || {\n secretKey: clerkEnv.CLERK_SECRET_KEY || '',\n publishableKey: clerkEnv.CLERK_PUBLISHABLE_KEY || '',\n apiUrl: clerkEnv.CLERK_API_URL,\n apiVersion: clerkEnv.CLERK_API_VERSION,\n };\n\n if (!secretKey) {\n throw new Error(\n 'Clerk: Missing Secret Key. Set CLERK_SECRET_KEY in your environment or pass secretKey to clerkMiddleware().',\n );\n }\n\n if (!publishableKey) {\n throw new Error(\n 'Clerk: Missing Publishable Key. Set CLERK_PUBLISHABLE_KEY in your environment or pass publishableKey to clerkMiddleware().',\n );\n }\n\n const clerkClient = createClerkClient({\n ...rest,\n apiUrl,\n apiVersion,\n secretKey,\n publishableKey,\n userAgent: `${PACKAGE_NAME}@${PACKAGE_VERSION}`,\n });\n\n const requestState = await clerkClient.authenticateRequest(c.req.raw, {\n ...rest,\n secretKey,\n publishableKey,\n acceptsToken: 'any',\n });\n\n if (requestState.headers) {\n requestState.headers.forEach((value, key) => {\n c.res.headers.append(key, value);\n });\n\n const locationHeader = requestState.headers.get('location');\n\n if (locationHeader) {\n return c.redirect(locationHeader, 307);\n } else if (requestState.status === 'handshake') {\n throw new Error('Clerk: Unexpected handshake without redirect');\n }\n }\n\n const authObjectFn = ((authOptions?: AuthOptions) =>\n getAuthObjectForAcceptedToken({\n authObject: requestState.toAuth(authOptions) as AuthObject,\n acceptsToken: 'any',\n })) as GetAuthFnNoRequest;\n\n c.set('clerkAuth', authObjectFn);\n c.set('clerk', clerkClient);\n\n await next();\n };\n};\n","import type { AuthOptions, GetAuthFn } from '@clerk/backend/internal';\nimport type { Context } from 'hono';\n\n/**\n * Retrieves the Clerk auth object from the Hono context.\n * Must be used after clerkMiddleware() has been applied.\n *\n * @example\n * ```ts\n * app.get('/protected', (c) => {\n * const { userId } = getAuth(c);\n * if (!userId) {\n * return c.json({ error: 'Unauthorized' }, 401);\n * }\n * return c.json({ message: 'Hello!' });\n * });\n * ```\n *\n * @example Using acceptsToken for API keys\n * ```ts\n * app.get('/api', (c) => {\n * const auth = getAuth(c, { acceptsToken: 'api_key' });\n * // auth will be typed for API key tokens\n * });\n * ```\n */\nexport const getAuth: GetAuthFn<Context> = ((c: Context, options?: AuthOptions) => {\n const authFn = c.get('clerkAuth');\n\n if (!authFn) {\n throw new Error(\n 'Clerk: getAuth() called without clerkMiddleware() being applied. Make sure to use clerkMiddleware() before calling getAuth().',\n );\n }\n\n return authFn(options);\n}) as GetAuthFn<Context>;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACCA,qBAAkC;AAElC,sBAA8C;AAE9C,qBAAoB;AA6Bb,IAAM,kBAAkB,CAAC,YAAwD;AACtF,SAAO,OAAO,GAAG,SAAS;AACxB,UAAM,eAAW,oBAAc,CAAC;AAChC,UAAM,EAAE,WAAW,gBAAgB,QAAQ,YAAY,GAAG,KAAK,IAAI,WAAW;AAAA,MAC5E,WAAW,SAAS,oBAAoB;AAAA,MACxC,gBAAgB,SAAS,yBAAyB;AAAA,MAClD,QAAQ,SAAS;AAAA,MACjB,YAAY,SAAS;AAAA,IACvB;AAEA,QAAI,CAAC,WAAW;AACd,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,gBAAgB;AACnB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,kBAAc,kCAAkB;AAAA,MACpC,GAAG;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW,GAAG,aAAY,IAAI,OAAe;AAAA,IAC/C,CAAC;AAED,UAAM,eAAe,MAAM,YAAY,oBAAoB,EAAE,IAAI,KAAK;AAAA,MACpE,GAAG;AAAA,MACH;AAAA,MACA;AAAA,MACA,cAAc;AAAA,IAChB,CAAC;AAED,QAAI,aAAa,SAAS;AACxB,mBAAa,QAAQ,QAAQ,CAAC,OAAO,QAAQ;AAC3C,UAAE,IAAI,QAAQ,OAAO,KAAK,KAAK;AAAA,MACjC,CAAC;AAED,YAAM,iBAAiB,aAAa,QAAQ,IAAI,UAAU;AAE1D,UAAI,gBAAgB;AAClB,eAAO,EAAE,SAAS,gBAAgB,GAAG;AAAA,MACvC,WAAW,aAAa,WAAW,aAAa;AAC9C,cAAM,IAAI,MAAM,8CAA8C;AAAA,MAChE;AAAA,IACF;AAEA,UAAM,gBAAgB,CAAC,oBACrB,+CAA8B;AAAA,MAC5B,YAAY,aAAa,OAAO,WAAW;AAAA,MAC3C,cAAc;AAAA,IAChB,CAAC;AAEH,MAAE,IAAI,aAAa,YAAY;AAC/B,MAAE,IAAI,SAAS,WAAW;AAE1B,UAAM,KAAK;AAAA,EACb;AACF;;;ACvEO,IAAM,WAA+B,CAAC,GAAY,YAA0B;AACjF,QAAM,SAAS,EAAE,IAAI,WAAW;AAEhC,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,SAAO,OAAO,OAAO;AACvB;","names":[]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// src/clerkMiddleware.ts
|
|
2
|
+
import { createClerkClient } from "@clerk/backend";
|
|
3
|
+
import { getAuthObjectForAcceptedToken } from "@clerk/backend/internal";
|
|
4
|
+
import { env } from "hono/adapter";
|
|
5
|
+
var clerkMiddleware = (options) => {
|
|
6
|
+
return async (c, next) => {
|
|
7
|
+
const clerkEnv = env(c);
|
|
8
|
+
const { secretKey, publishableKey, apiUrl, apiVersion, ...rest } = options || {
|
|
9
|
+
secretKey: clerkEnv.CLERK_SECRET_KEY || "",
|
|
10
|
+
publishableKey: clerkEnv.CLERK_PUBLISHABLE_KEY || "",
|
|
11
|
+
apiUrl: clerkEnv.CLERK_API_URL,
|
|
12
|
+
apiVersion: clerkEnv.CLERK_API_VERSION
|
|
13
|
+
};
|
|
14
|
+
if (!secretKey) {
|
|
15
|
+
throw new Error(
|
|
16
|
+
"Clerk: Missing Secret Key. Set CLERK_SECRET_KEY in your environment or pass secretKey to clerkMiddleware()."
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
if (!publishableKey) {
|
|
20
|
+
throw new Error(
|
|
21
|
+
"Clerk: Missing Publishable Key. Set CLERK_PUBLISHABLE_KEY in your environment or pass publishableKey to clerkMiddleware()."
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
const clerkClient = createClerkClient({
|
|
25
|
+
...rest,
|
|
26
|
+
apiUrl,
|
|
27
|
+
apiVersion,
|
|
28
|
+
secretKey,
|
|
29
|
+
publishableKey,
|
|
30
|
+
userAgent: `${"@clerk/hono"}@${"0.0.1"}`
|
|
31
|
+
});
|
|
32
|
+
const requestState = await clerkClient.authenticateRequest(c.req.raw, {
|
|
33
|
+
...rest,
|
|
34
|
+
secretKey,
|
|
35
|
+
publishableKey,
|
|
36
|
+
acceptsToken: "any"
|
|
37
|
+
});
|
|
38
|
+
if (requestState.headers) {
|
|
39
|
+
requestState.headers.forEach((value, key) => {
|
|
40
|
+
c.res.headers.append(key, value);
|
|
41
|
+
});
|
|
42
|
+
const locationHeader = requestState.headers.get("location");
|
|
43
|
+
if (locationHeader) {
|
|
44
|
+
return c.redirect(locationHeader, 307);
|
|
45
|
+
} else if (requestState.status === "handshake") {
|
|
46
|
+
throw new Error("Clerk: Unexpected handshake without redirect");
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
const authObjectFn = ((authOptions) => getAuthObjectForAcceptedToken({
|
|
50
|
+
authObject: requestState.toAuth(authOptions),
|
|
51
|
+
acceptsToken: "any"
|
|
52
|
+
}));
|
|
53
|
+
c.set("clerkAuth", authObjectFn);
|
|
54
|
+
c.set("clerk", clerkClient);
|
|
55
|
+
await next();
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// src/getAuth.ts
|
|
60
|
+
var getAuth = ((c, options) => {
|
|
61
|
+
const authFn = c.get("clerkAuth");
|
|
62
|
+
if (!authFn) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
"Clerk: getAuth() called without clerkMiddleware() being applied. Make sure to use clerkMiddleware() before calling getAuth()."
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
return authFn(options);
|
|
68
|
+
});
|
|
69
|
+
export {
|
|
70
|
+
clerkMiddleware,
|
|
71
|
+
getAuth
|
|
72
|
+
};
|
|
73
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/clerkMiddleware.ts","../src/getAuth.ts"],"sourcesContent":["import type { AuthObject } from '@clerk/backend';\nimport { createClerkClient } from '@clerk/backend';\nimport type { AuthenticateRequestOptions, AuthOptions, GetAuthFnNoRequest } from '@clerk/backend/internal';\nimport { getAuthObjectForAcceptedToken } from '@clerk/backend/internal';\nimport type { MiddlewareHandler } from 'hono';\nimport { env } from 'hono/adapter';\n\ntype ClerkEnv = {\n CLERK_SECRET_KEY: string;\n CLERK_PUBLISHABLE_KEY: string;\n CLERK_API_URL?: string;\n CLERK_API_VERSION?: string;\n};\n\nexport type ClerkMiddlewareOptions = Omit<AuthenticateRequestOptions, 'acceptsToken'>;\n\n/**\n * Clerk middleware for Hono that authenticates requests and attaches\n * auth data to the Hono context.\n *\n * @example\n * ```ts\n * import { Hono } from 'hono';\n * import { clerkMiddleware, getAuth } from '@clerk/hono';\n *\n * const app = new Hono();\n * app.use('*', clerkMiddleware());\n *\n * app.get('/', (c) => {\n * const { userId } = getAuth(c);\n * return c.json({ userId });\n * });\n * ```\n */\nexport const clerkMiddleware = (options?: ClerkMiddlewareOptions): MiddlewareHandler => {\n return async (c, next) => {\n const clerkEnv = env<ClerkEnv>(c);\n const { secretKey, publishableKey, apiUrl, apiVersion, ...rest } = options || {\n secretKey: clerkEnv.CLERK_SECRET_KEY || '',\n publishableKey: clerkEnv.CLERK_PUBLISHABLE_KEY || '',\n apiUrl: clerkEnv.CLERK_API_URL,\n apiVersion: clerkEnv.CLERK_API_VERSION,\n };\n\n if (!secretKey) {\n throw new Error(\n 'Clerk: Missing Secret Key. Set CLERK_SECRET_KEY in your environment or pass secretKey to clerkMiddleware().',\n );\n }\n\n if (!publishableKey) {\n throw new Error(\n 'Clerk: Missing Publishable Key. Set CLERK_PUBLISHABLE_KEY in your environment or pass publishableKey to clerkMiddleware().',\n );\n }\n\n const clerkClient = createClerkClient({\n ...rest,\n apiUrl,\n apiVersion,\n secretKey,\n publishableKey,\n userAgent: `${PACKAGE_NAME}@${PACKAGE_VERSION}`,\n });\n\n const requestState = await clerkClient.authenticateRequest(c.req.raw, {\n ...rest,\n secretKey,\n publishableKey,\n acceptsToken: 'any',\n });\n\n if (requestState.headers) {\n requestState.headers.forEach((value, key) => {\n c.res.headers.append(key, value);\n });\n\n const locationHeader = requestState.headers.get('location');\n\n if (locationHeader) {\n return c.redirect(locationHeader, 307);\n } else if (requestState.status === 'handshake') {\n throw new Error('Clerk: Unexpected handshake without redirect');\n }\n }\n\n const authObjectFn = ((authOptions?: AuthOptions) =>\n getAuthObjectForAcceptedToken({\n authObject: requestState.toAuth(authOptions) as AuthObject,\n acceptsToken: 'any',\n })) as GetAuthFnNoRequest;\n\n c.set('clerkAuth', authObjectFn);\n c.set('clerk', clerkClient);\n\n await next();\n };\n};\n","import type { AuthOptions, GetAuthFn } from '@clerk/backend/internal';\nimport type { Context } from 'hono';\n\n/**\n * Retrieves the Clerk auth object from the Hono context.\n * Must be used after clerkMiddleware() has been applied.\n *\n * @example\n * ```ts\n * app.get('/protected', (c) => {\n * const { userId } = getAuth(c);\n * if (!userId) {\n * return c.json({ error: 'Unauthorized' }, 401);\n * }\n * return c.json({ message: 'Hello!' });\n * });\n * ```\n *\n * @example Using acceptsToken for API keys\n * ```ts\n * app.get('/api', (c) => {\n * const auth = getAuth(c, { acceptsToken: 'api_key' });\n * // auth will be typed for API key tokens\n * });\n * ```\n */\nexport const getAuth: GetAuthFn<Context> = ((c: Context, options?: AuthOptions) => {\n const authFn = c.get('clerkAuth');\n\n if (!authFn) {\n throw new Error(\n 'Clerk: getAuth() called without clerkMiddleware() being applied. Make sure to use clerkMiddleware() before calling getAuth().',\n );\n }\n\n return authFn(options);\n}) as GetAuthFn<Context>;\n"],"mappings":";AACA,SAAS,yBAAyB;AAElC,SAAS,qCAAqC;AAE9C,SAAS,WAAW;AA6Bb,IAAM,kBAAkB,CAAC,YAAwD;AACtF,SAAO,OAAO,GAAG,SAAS;AACxB,UAAM,WAAW,IAAc,CAAC;AAChC,UAAM,EAAE,WAAW,gBAAgB,QAAQ,YAAY,GAAG,KAAK,IAAI,WAAW;AAAA,MAC5E,WAAW,SAAS,oBAAoB;AAAA,MACxC,gBAAgB,SAAS,yBAAyB;AAAA,MAClD,QAAQ,SAAS;AAAA,MACjB,YAAY,SAAS;AAAA,IACvB;AAEA,QAAI,CAAC,WAAW;AACd,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,gBAAgB;AACnB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,cAAc,kBAAkB;AAAA,MACpC,GAAG;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW,GAAG,aAAY,IAAI,OAAe;AAAA,IAC/C,CAAC;AAED,UAAM,eAAe,MAAM,YAAY,oBAAoB,EAAE,IAAI,KAAK;AAAA,MACpE,GAAG;AAAA,MACH;AAAA,MACA;AAAA,MACA,cAAc;AAAA,IAChB,CAAC;AAED,QAAI,aAAa,SAAS;AACxB,mBAAa,QAAQ,QAAQ,CAAC,OAAO,QAAQ;AAC3C,UAAE,IAAI,QAAQ,OAAO,KAAK,KAAK;AAAA,MACjC,CAAC;AAED,YAAM,iBAAiB,aAAa,QAAQ,IAAI,UAAU;AAE1D,UAAI,gBAAgB;AAClB,eAAO,EAAE,SAAS,gBAAgB,GAAG;AAAA,MACvC,WAAW,aAAa,WAAW,aAAa;AAC9C,cAAM,IAAI,MAAM,8CAA8C;AAAA,MAChE;AAAA,IACF;AAEA,UAAM,gBAAgB,CAAC,gBACrB,8BAA8B;AAAA,MAC5B,YAAY,aAAa,OAAO,WAAW;AAAA,MAC3C,cAAc;AAAA,IAChB,CAAC;AAEH,MAAE,IAAI,aAAa,YAAY;AAC/B,MAAE,IAAI,SAAS,WAAW;AAE1B,UAAM,KAAK;AAAA,EACb;AACF;;;ACvEO,IAAM,WAA+B,CAAC,GAAY,YAA0B;AACjF,QAAM,SAAS,EAAE,IAAI,WAAW;AAEhC,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,SAAO,OAAO,OAAO;AACvB;","names":[]}
|
package/dist/types.d.mts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export * from '@clerk/shared/types';
|
|
2
|
+
import { ClerkClient } from '@clerk/backend';
|
|
3
|
+
import { GetAuthFnNoRequest } from '@clerk/backend/internal';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Variables that clerkMiddleware sets on the Hono context.
|
|
7
|
+
* Access via c.get('clerk') and c.get('clerkAuth').
|
|
8
|
+
*/
|
|
9
|
+
type ClerkHonoVariables = {
|
|
10
|
+
clerk: ClerkClient;
|
|
11
|
+
clerkAuth: GetAuthFnNoRequest;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type { ClerkHonoVariables };
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export * from '@clerk/shared/types';
|
|
2
|
+
import { ClerkClient } from '@clerk/backend';
|
|
3
|
+
import { GetAuthFnNoRequest } from '@clerk/backend/internal';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Variables that clerkMiddleware sets on the Hono context.
|
|
7
|
+
* Access via c.get('clerk') and c.get('clerkAuth').
|
|
8
|
+
*/
|
|
9
|
+
type ClerkHonoVariables = {
|
|
10
|
+
clerk: ClerkClient;
|
|
11
|
+
clerkAuth: GetAuthFnNoRequest;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type { ClerkHonoVariables };
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __copyProps = (to, from, except, desc) => {
|
|
7
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
8
|
+
for (let key of __getOwnPropNames(from))
|
|
9
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
10
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
11
|
+
}
|
|
12
|
+
return to;
|
|
13
|
+
};
|
|
14
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
15
|
+
|
|
16
|
+
// src/types/index.ts
|
|
17
|
+
var types_exports = {};
|
|
18
|
+
module.exports = __toCommonJS(types_exports);
|
|
19
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types/index.ts"],"sourcesContent":["/**\n * Re-export all shared Clerk types for convenient access via @clerk/hono/types\n */\nexport type * from '@clerk/shared/types';\n\n/**\n * Hono-specific types\n */\nexport type { ClerkHonoVariables } from '../types';\n"],"mappings":";;;;;;;;;;;;;;;;AAAA;AAAA;","names":[]}
|
package/dist/types.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=types.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import * as _clerk_backend_webhooks from '@clerk/backend/webhooks';
|
|
2
|
+
import { VerifyWebhookOptions } from '@clerk/backend/webhooks';
|
|
3
|
+
export * from '@clerk/backend/webhooks';
|
|
4
|
+
import { Context } from 'hono';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Verifies the authenticity of a webhook request from Clerk using Svix.
|
|
8
|
+
*
|
|
9
|
+
* @param c - The Hono Context object from the webhook handler
|
|
10
|
+
* @param options - Optional configuration object
|
|
11
|
+
* @param options.signingSecret - Custom signing secret. If not provided, falls back to CLERK_WEBHOOK_SIGNING_SECRET env variable
|
|
12
|
+
* @throws Will throw an error if the webhook signature verification fails
|
|
13
|
+
* @returns A promise that resolves to the verified webhook event data
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { Hono } from 'hono';
|
|
18
|
+
* import { verifyWebhook } from '@clerk/hono/webhooks';
|
|
19
|
+
*
|
|
20
|
+
* const app = new Hono();
|
|
21
|
+
*
|
|
22
|
+
* app.post('/webhooks/clerk', async (c) => {
|
|
23
|
+
* const evt = await verifyWebhook(c);
|
|
24
|
+
* // Handle the webhook event
|
|
25
|
+
* return c.json({ received: true });
|
|
26
|
+
* });
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @see {@link https://clerk.com/docs/webhooks/sync-data} to learn more about syncing Clerk data to your application using webhooks
|
|
30
|
+
*/
|
|
31
|
+
declare function verifyWebhook(c: Context, options?: VerifyWebhookOptions): Promise<_clerk_backend_webhooks.WebhookEvent>;
|
|
32
|
+
|
|
33
|
+
export { verifyWebhook };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import * as _clerk_backend_webhooks from '@clerk/backend/webhooks';
|
|
2
|
+
import { VerifyWebhookOptions } from '@clerk/backend/webhooks';
|
|
3
|
+
export * from '@clerk/backend/webhooks';
|
|
4
|
+
import { Context } from 'hono';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Verifies the authenticity of a webhook request from Clerk using Svix.
|
|
8
|
+
*
|
|
9
|
+
* @param c - The Hono Context object from the webhook handler
|
|
10
|
+
* @param options - Optional configuration object
|
|
11
|
+
* @param options.signingSecret - Custom signing secret. If not provided, falls back to CLERK_WEBHOOK_SIGNING_SECRET env variable
|
|
12
|
+
* @throws Will throw an error if the webhook signature verification fails
|
|
13
|
+
* @returns A promise that resolves to the verified webhook event data
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { Hono } from 'hono';
|
|
18
|
+
* import { verifyWebhook } from '@clerk/hono/webhooks';
|
|
19
|
+
*
|
|
20
|
+
* const app = new Hono();
|
|
21
|
+
*
|
|
22
|
+
* app.post('/webhooks/clerk', async (c) => {
|
|
23
|
+
* const evt = await verifyWebhook(c);
|
|
24
|
+
* // Handle the webhook event
|
|
25
|
+
* return c.json({ received: true });
|
|
26
|
+
* });
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @see {@link https://clerk.com/docs/webhooks/sync-data} to learn more about syncing Clerk data to your application using webhooks
|
|
30
|
+
*/
|
|
31
|
+
declare function verifyWebhook(c: Context, options?: VerifyWebhookOptions): Promise<_clerk_backend_webhooks.WebhookEvent>;
|
|
32
|
+
|
|
33
|
+
export { verifyWebhook };
|
package/dist/webhooks.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
|
|
21
|
+
// src/webhooks.ts
|
|
22
|
+
var webhooks_exports = {};
|
|
23
|
+
__export(webhooks_exports, {
|
|
24
|
+
verifyWebhook: () => verifyWebhook
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(webhooks_exports);
|
|
27
|
+
var import_webhooks = require("@clerk/backend/webhooks");
|
|
28
|
+
__reExport(webhooks_exports, require("@clerk/backend/webhooks"), module.exports);
|
|
29
|
+
async function verifyWebhook(c, options) {
|
|
30
|
+
const body = await c.req.text();
|
|
31
|
+
const clonedRequest = new Request(c.req.raw, {
|
|
32
|
+
body
|
|
33
|
+
});
|
|
34
|
+
return (0, import_webhooks.verifyWebhook)(clonedRequest, options);
|
|
35
|
+
}
|
|
36
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
37
|
+
0 && (module.exports = {
|
|
38
|
+
verifyWebhook,
|
|
39
|
+
...require("@clerk/backend/webhooks")
|
|
40
|
+
});
|
|
41
|
+
//# sourceMappingURL=webhooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/webhooks.ts"],"sourcesContent":["/* eslint-disable import/export */\nimport type { VerifyWebhookOptions } from '@clerk/backend/webhooks';\nimport { verifyWebhook as verifyWebhookBase } from '@clerk/backend/webhooks';\nimport type { Context } from 'hono';\n\n// Re-export everything from backend webhooks\nexport * from '@clerk/backend/webhooks';\n\n/**\n * Verifies the authenticity of a webhook request from Clerk using Svix.\n *\n * @param c - The Hono Context object from the webhook handler\n * @param options - Optional configuration object\n * @param options.signingSecret - Custom signing secret. If not provided, falls back to CLERK_WEBHOOK_SIGNING_SECRET env variable\n * @throws Will throw an error if the webhook signature verification fails\n * @returns A promise that resolves to the verified webhook event data\n *\n * @example\n * ```ts\n * import { Hono } from 'hono';\n * import { verifyWebhook } from '@clerk/hono/webhooks';\n *\n * const app = new Hono();\n *\n * app.post('/webhooks/clerk', async (c) => {\n * const evt = await verifyWebhook(c);\n * // Handle the webhook event\n * return c.json({ received: true });\n * });\n * ```\n *\n * @see {@link https://clerk.com/docs/webhooks/sync-data} to learn more about syncing Clerk data to your application using webhooks\n */\nexport async function verifyWebhook(c: Context, options?: VerifyWebhookOptions) {\n // Hono's c.req.raw is already a standard Web Request\n // We need to clone it with the body for verification\n const body = await c.req.text();\n const clonedRequest = new Request(c.req.raw, {\n body,\n });\n return verifyWebhookBase(clonedRequest, options);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,sBAAmD;AAInD,6BAAc,oCANd;AAiCA,eAAsB,cAAc,GAAY,SAAgC;AAG9E,QAAM,OAAO,MAAM,EAAE,IAAI,KAAK;AAC9B,QAAM,gBAAgB,IAAI,QAAQ,EAAE,IAAI,KAAK;AAAA,IAC3C;AAAA,EACF,CAAC;AACD,aAAO,gBAAAA,eAAkB,eAAe,OAAO;AACjD;","names":["verifyWebhookBase"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// src/webhooks.ts
|
|
2
|
+
import { verifyWebhook as verifyWebhookBase } from "@clerk/backend/webhooks";
|
|
3
|
+
export * from "@clerk/backend/webhooks";
|
|
4
|
+
async function verifyWebhook(c, options) {
|
|
5
|
+
const body = await c.req.text();
|
|
6
|
+
const clonedRequest = new Request(c.req.raw, {
|
|
7
|
+
body
|
|
8
|
+
});
|
|
9
|
+
return verifyWebhookBase(clonedRequest, options);
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
verifyWebhook
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=webhooks.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/webhooks.ts"],"sourcesContent":["/* eslint-disable import/export */\nimport type { VerifyWebhookOptions } from '@clerk/backend/webhooks';\nimport { verifyWebhook as verifyWebhookBase } from '@clerk/backend/webhooks';\nimport type { Context } from 'hono';\n\n// Re-export everything from backend webhooks\nexport * from '@clerk/backend/webhooks';\n\n/**\n * Verifies the authenticity of a webhook request from Clerk using Svix.\n *\n * @param c - The Hono Context object from the webhook handler\n * @param options - Optional configuration object\n * @param options.signingSecret - Custom signing secret. If not provided, falls back to CLERK_WEBHOOK_SIGNING_SECRET env variable\n * @throws Will throw an error if the webhook signature verification fails\n * @returns A promise that resolves to the verified webhook event data\n *\n * @example\n * ```ts\n * import { Hono } from 'hono';\n * import { verifyWebhook } from '@clerk/hono/webhooks';\n *\n * const app = new Hono();\n *\n * app.post('/webhooks/clerk', async (c) => {\n * const evt = await verifyWebhook(c);\n * // Handle the webhook event\n * return c.json({ received: true });\n * });\n * ```\n *\n * @see {@link https://clerk.com/docs/webhooks/sync-data} to learn more about syncing Clerk data to your application using webhooks\n */\nexport async function verifyWebhook(c: Context, options?: VerifyWebhookOptions) {\n // Hono's c.req.raw is already a standard Web Request\n // We need to clone it with the body for verification\n const body = await c.req.text();\n const clonedRequest = new Request(c.req.raw, {\n body,\n });\n return verifyWebhookBase(clonedRequest, options);\n}\n"],"mappings":";AAEA,SAAS,iBAAiB,yBAAyB;AAInD,cAAc;AA2Bd,eAAsB,cAAc,GAAY,SAAgC;AAG9E,QAAM,OAAO,MAAM,EAAE,IAAI,KAAK;AAC9B,QAAM,gBAAgB,IAAI,QAAQ,EAAE,IAAI,KAAK;AAAA,IAC3C;AAAA,EACF,CAAC;AACD,SAAO,kBAAkB,eAAe,OAAO;AACjD;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@clerk/hono",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Clerk SDK for Hono",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"auth",
|
|
7
|
+
"authentication",
|
|
8
|
+
"passwordless",
|
|
9
|
+
"session",
|
|
10
|
+
"jwt",
|
|
11
|
+
"hono",
|
|
12
|
+
"clerk"
|
|
13
|
+
],
|
|
14
|
+
"homepage": "https://clerk.com/",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/clerk/javascript/issues"
|
|
17
|
+
},
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "git+https://github.com/clerk/javascript.git",
|
|
21
|
+
"directory": "packages/hono"
|
|
22
|
+
},
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"author": "Clerk",
|
|
25
|
+
"sideEffects": false,
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"import": {
|
|
29
|
+
"types": "./dist/index.d.mts",
|
|
30
|
+
"default": "./dist/index.mjs"
|
|
31
|
+
},
|
|
32
|
+
"require": {
|
|
33
|
+
"types": "./dist/index.d.ts",
|
|
34
|
+
"default": "./dist/index.js"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"./webhooks": {
|
|
38
|
+
"import": {
|
|
39
|
+
"types": "./dist/webhooks.d.mts",
|
|
40
|
+
"default": "./dist/webhooks.mjs"
|
|
41
|
+
},
|
|
42
|
+
"require": {
|
|
43
|
+
"types": "./dist/webhooks.d.ts",
|
|
44
|
+
"default": "./dist/webhooks.js"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"./types": {
|
|
48
|
+
"import": {
|
|
49
|
+
"types": "./dist/types.d.mts"
|
|
50
|
+
},
|
|
51
|
+
"require": {
|
|
52
|
+
"types": "./dist/types.d.ts"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
"main": "./dist/index.js",
|
|
57
|
+
"module": "./dist/index.mjs",
|
|
58
|
+
"types": "./dist/index.d.ts",
|
|
59
|
+
"files": [
|
|
60
|
+
"dist"
|
|
61
|
+
],
|
|
62
|
+
"dependencies": {
|
|
63
|
+
"@clerk/backend": "3.0.0-canary.v20260211111223",
|
|
64
|
+
"@clerk/shared": "4.0.0-canary.v20260211111223"
|
|
65
|
+
},
|
|
66
|
+
"devDependencies": {
|
|
67
|
+
"hono": "^4.7.4"
|
|
68
|
+
},
|
|
69
|
+
"peerDependencies": {
|
|
70
|
+
"hono": ">=4"
|
|
71
|
+
},
|
|
72
|
+
"engines": {
|
|
73
|
+
"node": ">=20"
|
|
74
|
+
},
|
|
75
|
+
"publishConfig": {
|
|
76
|
+
"access": "public"
|
|
77
|
+
},
|
|
78
|
+
"scripts": {
|
|
79
|
+
"build": "tsup --env.NODE_ENV production",
|
|
80
|
+
"clean": "rimraf ./dist",
|
|
81
|
+
"dev": "tsup --watch",
|
|
82
|
+
"format": "node ../../scripts/format-package.mjs",
|
|
83
|
+
"format:check": "node ../../scripts/format-package.mjs --check",
|
|
84
|
+
"lint": "eslint src",
|
|
85
|
+
"lint:attw": "attw --pack . --profile node16",
|
|
86
|
+
"lint:publint": "publint",
|
|
87
|
+
"publish:local": "pnpm yalc push --replace --sig",
|
|
88
|
+
"test": "vitest run",
|
|
89
|
+
"test:watch": "vitest watch"
|
|
90
|
+
}
|
|
91
|
+
}
|