@nitrotool/jwt 0.0.8 → 1.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/README.md CHANGED
@@ -1,77 +1,149 @@
1
1
  # @nitrotool/jwt
2
2
 
3
- Lightweight JWT utilities for Nitro/UnJS environments with optional h3 helpers.
3
+ Lightweight JWT utilities for Nuxt/Nitro/UnJS environments **with built-in h3 helpers**.
4
4
 
5
5
  - Built on `@tsndr/cloudflare-worker-jwt`
6
6
  - Helpers that read `jwtSecret` from your Nitro runtime config
7
- - h3 utilities to extract tokens from requests and enforce authentication
7
+ - Batteries included with h3 utilities to extract tokens from requests and enforce authentication
8
+
9
+ Learn more about JWT and how it works:
10
+
11
+ - [What is a JWT?](https://www.jwt.io/introduction#what-is-json-web-token)
12
+ - [JWT.io](https://jwt.io/)
8
13
 
9
14
  ## Installation
10
15
 
16
+ ```bash
17
+ pnpm install @nitrotool/jwt
18
+ ```
19
+
11
20
  ```bash
12
21
  npm install @nitrotool/jwt
13
22
  ```
14
23
 
15
- Peer dependency:
16
- - `h3` is required only when using the h3 helpers.
24
+ Required peer dependency:
25
+
26
+ - `h3` (this package expects `h3` to be present)
27
+
28
+ ## Nuxt setup
29
+
30
+ ```ts
31
+ export default defineNuxtConfig({
32
+ modules: ['@nitrotool/jwt'],
33
+ //You can also
34
+ jwt: {
35
+ //default secret (only use this locally, and override it in prod)
36
+ secret: 'some-random-secret-yes-it-is-not-very-secure',
37
+ // Alternatively also available as NUXT_JWT_SECRET env var
38
+ },
39
+ });
40
+
41
+ ```
42
+
43
+ ### Usage with Nuxt 3/4
44
+
45
+ > This is available all places where auto-imported can be used on the server-side.
46
+
47
+ ```ts
48
+ type MyClaims = { tenantId: string };
49
+
50
+ const token = await encodeJwt<MyClaims>({tenantId: '123', sub: '123'});
51
+
52
+ // Later…
53
+ const isValid = await verifyJwt(token);
54
+ const payload = await decodeJwt<MyClaims>(token);
55
+
56
+
57
+ // or
58
+ export default defineEventHandler(async (event) => {
59
+ const jwt = await requireJwt(event);
60
+ // you now have access to a required JWT token via Authorization bearer header.
61
+ })
62
+
63
+ ```
17
64
 
18
65
  ## Importing
19
66
 
20
- You can import from the main entry or subpath exports:
67
+ Import from the main entry or subpaths:
21
68
 
22
69
  ```ts
23
- // Main (all helpers)
24
- import { encodeJwt, verifyJwt, decodeJwt } from '@nitrotool/jwt';
70
+ // Node-only helpers
71
+ import {encodeJwtRaw, verifyJwtRaw, decodeJwtRaw} from '@nitrotool/jwt/core';
72
+
73
+ // h3-only helpers
74
+ import {extractApiToken, requireApiToken} from '@nitrotool/jwt/h3';
75
+ ```
25
76
 
26
- // Subpath (JWT-only)
27
- import { encodeJwtRaw, verifyJwtRaw, decodeJwtRaw } from '@nitrotool/jwt/jwt';
77
+ ## Quick Start Nitro
78
+
79
+ ### 1. Create plugin to load secret.
80
+
81
+ ```ts
82
+ // plugins/0.jwt.ts
83
+ import { defineNitroPlugin, useRuntimeConfig } from 'nitropack/runtime';
84
+ import { configureJwtRuntime } from '@nitrotool/jwt';
85
+
86
+ export default defineNitroPlugin(() => {
87
+ configureJwtRuntime(() => useRuntimeConfig() as any);
88
+ });
28
89
 
29
- // Subpath (h3 helpers)
30
- import { extractApiToken, requireApiToken } from '@nitrotool/jwt/h3';
31
90
  ```
32
91
 
33
- ## Quick Start
92
+ ### 2. Basic usage
34
93
 
35
94
  ```ts
36
- import { encodeJwt, verifyJwt, decodeJwt } from '@nitrotool/jwt';
95
+ import {encodeJwt, verifyJwt, decodeJwt} from '@nitrotool/jwt';
37
96
 
38
- type MyClaims = { userId: string };
97
+ type MyClaims = { tenantId: string };
98
+
99
+ const token = await encodeJwt<MyClaims>({tenantId: '123', sub: '123'});
39
100
 
40
- const token = await encodeJwt<MyClaims>({ userId: '123' });
41
101
  // Later…
42
102
  const isValid = await verifyJwt(token);
43
- const payload = await decodeJwt<MyClaims>(token); // { userId: '123', exp: ... }
103
+ const payload = await decodeJwt<MyClaims>(token); // { sub: '123', tenantId: '123', exp: ... }
44
104
  ```
45
105
 
46
106
  By default, non-`Raw` helpers read the secret from your runtime config:
107
+
47
108
  - `useRuntimeConfig().jwtSecret`
48
109
 
49
110
  If you need to pass a secret explicitly, use the `*Raw` variants.
50
111
 
51
- ## Usage with h3
112
+ ### 3. In a route handler
52
113
 
53
114
  Extract API tokens and enforce authentication in request handlers:
54
115
 
116
+ #### Require a JWT token
117
+ ```ts
118
+ import {defineEventHandler} from 'h3';
119
+ import {requireJwt} from '@nitrotool/jwt';
120
+
121
+ export default defineEventHandler(async (event) => {
122
+ const decodedJwt = await requireJwt(event)
123
+ })
124
+ ```
125
+
126
+ #### Extract a JWT token manually
55
127
  ```ts
56
128
  import { defineEventHandler } from 'h3';
57
- import { extractApiToken, requireApiToken } from '@nitrotool/jwt/h3';
58
- import { decodeJwt } from '@nitrotool/jwt';
129
+ import { extractApiToken, requireApiToken, decodeJwt } from '@nitrotool/jwt';
59
130
 
60
131
  export default defineEventHandler(async (event) => {
61
- // Try to read token (Authorization: Bearer <token> or ?token=<token>)
62
- const token = extractApiToken(event);
132
+ // Try to read token (Authorization: Bearer <token> or ?<queryKey>=<token>)
133
+ const token = extractApiToken(event, {queryKey: 'token'}); // queryKey defaults to 'token'
63
134
 
64
- // Or strictly require it (throws UnauthenticatedError if missing)
65
- const requiredToken = requireApiToken(event);
135
+ // Or strictly require it (throws UnauthenticatedError if missing)
136
+ const requiredToken = requireApiToken(event);
66
137
 
67
- // Optionally decode/verify
68
- const claims = await decodeJwt<{ userId: string }>(requiredToken);
138
+ // Optionally decode/verify
139
+ const claims = await decodeJwt<{ userId: string }>(requiredToken);
69
140
 
70
- return { ok: true, userId: claims.userId };
141
+ return { ok: true, userId: claims.userId };
71
142
  });
72
143
  ```
73
144
 
74
145
  Supported token locations:
146
+
75
147
  - Authorization header: `Authorization: Bearer <token>`
76
148
  - Query string: `?token=<token>`
77
149
 
@@ -80,11 +152,11 @@ Supported token locations:
80
152
  When using non-`Raw` helpers, ensure a secret is available at runtime:
81
153
 
82
154
  ```ts
83
- // Example: Nuxt/Nitro runtime config
155
+ // nuxt.config.ts (Nuxt/Nitro runtime config)
84
156
  export default defineNuxtConfig({
85
- runtimeConfig: {
86
- jwtSecret: process.env.JWT_SECRET || 'super-secret',
87
- },
157
+ runtimeConfig: {
158
+ jwtSecret: 'some-random-secret-yes-it-is-not-very-secure',
159
+ },
88
160
  });
89
161
  ```
90
162
 
@@ -93,27 +165,27 @@ export default defineNuxtConfig({
93
165
  Sign with custom TTL:
94
166
 
95
167
  ```ts
96
- import { encodeJwtRaw } from '@nitrotool/jwt';
168
+ import {encodeJwtRaw} from '@nitrotool/jwt';
97
169
 
98
170
  const token = await encodeJwtRaw(
99
- { userId: '123', role: 'admin' },
100
- process.env.JWT_SECRET!,
101
- 60 * 10 // 10 minutes
171
+ {userId: '123', role: 'admin'},
172
+ process.env.JWT_SECRET!,
173
+ 60 * 10 // 10 minutes
102
174
  );
103
175
  ```
104
176
 
105
177
  Decode without verifying signature (use only for non-sensitive scenarios):
106
178
 
107
179
  ```ts
108
- import { decodeJwt } from '@nitrotool/jwt';
180
+ import {decodeJwt} from '@nitrotool/jwt';
109
181
 
110
- const payload = await decodeJwt<{ userId: string }>(token, { verify: false });
182
+ const payload = await decodeJwt<{ userId: string }>(token, {verify: false});
111
183
  ```
112
184
 
113
185
  Verify with an explicit secret:
114
186
 
115
187
  ```ts
116
- import { verifyJwtRaw } from '@nitrotool/jwt';
188
+ import {verifyJwtRaw} from '@nitrotool/jwt';
117
189
 
118
190
  const ok = await verifyJwtRaw(token, process.env.JWT_SECRET!);
119
191
  ```
@@ -139,9 +211,9 @@ All helpers are asynchronous.
139
211
  - `encodeJwtRaw<T>(payload, secret, ttl = 60): Promise<string>`
140
212
  - Signs a token with the provided `secret`.
141
213
  - `ttl` is in seconds. Default: `60`.
142
- - `exp` is set automatically from `ttl`.
214
+ - `exp` is set **automagically** from `ttl`.
143
215
 
144
- - `encodeJwt<T>(payload): Promise<string>`
216
+ - `encodeJwt<T>(payload, ttl = 60): Promise<string>`
145
217
  - Same as `encodeJwtRaw`, but uses `useRuntimeConfig().jwtSecret`.
146
218
 
147
219
  - `verifyJwtRaw(token, secret): Promise<boolean>`
@@ -160,14 +232,15 @@ All helpers are asynchronous.
160
232
  - Throws `UnauthorizedError('Invalid JWT token.')` if verification fails.
161
233
 
162
234
  Types:
235
+
163
236
  - `ExtendableJwtPayload<T>` lets you define custom claims merged with standard JWT claims.
164
237
 
165
- ### h3 helpers
238
+ ### h3 helpers (required)
166
239
 
167
240
  - `extractBearerToken(event): string | undefined`
168
241
  - Reads `Authorization` header and returns the token without `Bearer `.
169
242
 
170
- - `extractQueryToken(event): string | undefined`
243
+ - `extractQueryToken(event, key = 'token'): string | undefined`
171
244
  - Reads `token` from the query string.
172
245
 
173
246
  - `extractApiToken(event): string | undefined`
@@ -176,7 +249,6 @@ Types:
176
249
  - `requireApiToken(event): string`
177
250
  - Same as `extractApiToken`, but throws `UnauthenticatedError` if missing.
178
251
 
179
-
180
252
  ## License
181
253
 
182
- MIT
254
+ MIT
@@ -0,0 +1,11 @@
1
+ import { JwtPayload } from '@tsndr/cloudflare-worker-jwt';
2
+
3
+ type ExtendableJwtPayload<T extends Record<string, any> = {}> = Partial<JwtPayload> & T;
4
+ declare const encodeJwtRaw: <T extends Record<string, any> = {}>(payload: ExtendableJwtPayload<T>, secret: string, ttlSec?: number) => Promise<string>;
5
+ declare const verifyJwtRaw: (token: string, secret: string) => Promise<boolean>;
6
+ declare const decodeJwtRaw: <T extends Record<string, any> = {}>(token: string, secret: string, opts?: {
7
+ verify?: boolean;
8
+ }) => Promise<ExtendableJwtPayload<T>>;
9
+
10
+ export { decodeJwtRaw, encodeJwtRaw, verifyJwtRaw };
11
+ export type { ExtendableJwtPayload };
@@ -0,0 +1,11 @@
1
+ import { JwtPayload } from '@tsndr/cloudflare-worker-jwt';
2
+
3
+ type ExtendableJwtPayload<T extends Record<string, any> = {}> = Partial<JwtPayload> & T;
4
+ declare const encodeJwtRaw: <T extends Record<string, any> = {}>(payload: ExtendableJwtPayload<T>, secret: string, ttlSec?: number) => Promise<string>;
5
+ declare const verifyJwtRaw: (token: string, secret: string) => Promise<boolean>;
6
+ declare const decodeJwtRaw: <T extends Record<string, any> = {}>(token: string, secret: string, opts?: {
7
+ verify?: boolean;
8
+ }) => Promise<ExtendableJwtPayload<T>>;
9
+
10
+ export { decodeJwtRaw, encodeJwtRaw, verifyJwtRaw };
11
+ export type { ExtendableJwtPayload };
@@ -0,0 +1,26 @@
1
+ import jwt from '@tsndr/cloudflare-worker-jwt';
2
+ import { UnauthorizedError } from '@nitrotool/errors';
3
+
4
+ const encodeJwtRaw = async (payload, secret, ttlSec = 60) => {
5
+ return jwt.sign(
6
+ { exp: Math.floor(Date.now() / 1e3) + ttlSec, ...payload },
7
+ secret
8
+ );
9
+ };
10
+ const verifyJwtRaw = async (token, secret) => {
11
+ return new Promise(async (resolve) => {
12
+ if (await jwt.verify(token, secret, { throwError: false })) {
13
+ return resolve(true);
14
+ }
15
+ return resolve(false);
16
+ });
17
+ };
18
+ const decodeJwtRaw = async (token, secret, opts = { verify: true }) => {
19
+ if (opts.verify) {
20
+ const ok = await verifyJwtRaw(token, secret);
21
+ if (!ok) throw UnauthorizedError("Invalid JWT token.");
22
+ }
23
+ return jwt.decode(token).payload;
24
+ };
25
+
26
+ export { decodeJwtRaw, encodeJwtRaw, verifyJwtRaw };
@@ -1,8 +1,10 @@
1
1
  import { H3Event } from 'h3';
2
2
 
3
- declare const extractBearerToken: (event: H3Event) => string;
3
+ declare const extractBearerToken: (event: H3Event) => string | undefined;
4
4
  declare const extractQueryToken: (event: H3Event, key?: string) => string | undefined;
5
- declare const extractApiToken: (event: H3Event) => string | undefined;
5
+ declare const extractApiToken: (event: H3Event, opts?: {
6
+ queryKey: string;
7
+ }) => string | undefined;
6
8
  declare const requireApiToken: (event: H3Event) => string;
7
9
 
8
10
  export { extractApiToken, extractBearerToken, extractQueryToken, requireApiToken };
@@ -1,8 +1,10 @@
1
1
  import { H3Event } from 'h3';
2
2
 
3
- declare const extractBearerToken: (event: H3Event) => string;
3
+ declare const extractBearerToken: (event: H3Event) => string | undefined;
4
4
  declare const extractQueryToken: (event: H3Event, key?: string) => string | undefined;
5
- declare const extractApiToken: (event: H3Event) => string | undefined;
5
+ declare const extractApiToken: (event: H3Event, opts?: {
6
+ queryKey: string;
7
+ }) => string | undefined;
6
8
  declare const requireApiToken: (event: H3Event) => string;
7
9
 
8
10
  export { extractApiToken, extractBearerToken, extractQueryToken, requireApiToken };
@@ -1,9 +1,15 @@
1
- import { getRequestHeader, getQuery } from 'h3';
1
+ import { getQuery, getHeader } from 'h3';
2
2
  import { UnauthenticatedError } from '@nitrotool/errors';
3
3
 
4
- const extractBearerToken = (event) => getRequestHeader(event, "Authorization")?.replace("Bearer ", "") || void 0;
4
+ const extractBearerToken = (event) => {
5
+ const auth = getHeader(event, "authorization");
6
+ if (!auth?.startsWith("Bearer ")) {
7
+ return void 0;
8
+ }
9
+ return auth.slice(7);
10
+ };
5
11
  const extractQueryToken = (event, key = "token") => getQuery(event)?.[key] || void 0;
6
- const extractApiToken = (event) => extractBearerToken(event) || extractQueryToken(event);
12
+ const extractApiToken = (event, opts = { queryKey: "token" }) => extractBearerToken(event) || extractQueryToken(event, opts.queryKey);
7
13
  const requireApiToken = (event) => {
8
14
  const token = extractApiToken(event);
9
15
  if (!token) {
package/dist/index.d.mts CHANGED
@@ -1,4 +1,9 @@
1
- export { extractApiToken, extractBearerToken, extractQueryToken, requireApiToken } from './h3.mjs';
2
- export { ExtendableJwtPayload, decodeJwt, decodeJwtRaw, encodeJwt, encodeJwtRaw, verifyJwt, verifyJwtRaw } from './jwt.mjs';
3
- import 'h3';
1
+ export { configureJwtRuntime, decodeJwt, encodeJwt, getJwtSecret, verifyJwt } from './runtime/server/index.mjs';
2
+ export { requireApiToken } from './h3/index.mjs';
3
+ import { H3Event } from 'h3';
4
+ import './core/index.mjs';
4
5
  import '@tsndr/cloudflare-worker-jwt';
6
+
7
+ declare const requireJwt: <T extends Record<string, any> = {}>(event: H3Event) => Promise<any>;
8
+
9
+ export { requireJwt };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,9 @@
1
- export { extractApiToken, extractBearerToken, extractQueryToken, requireApiToken } from './h3.js';
2
- export { ExtendableJwtPayload, decodeJwt, decodeJwtRaw, encodeJwt, encodeJwtRaw, verifyJwt, verifyJwtRaw } from './jwt.js';
3
- import 'h3';
1
+ export { configureJwtRuntime, decodeJwt, encodeJwt, getJwtSecret, verifyJwt } from './runtime/server/index.js';
2
+ export { requireApiToken } from './h3/index.js';
3
+ import { H3Event } from 'h3';
4
+ import './core/index.js';
4
5
  import '@tsndr/cloudflare-worker-jwt';
6
+
7
+ declare const requireJwt: <T extends Record<string, any> = {}>(event: H3Event) => Promise<any>;
8
+
9
+ export { requireJwt };
package/dist/index.mjs CHANGED
@@ -1,5 +1,8 @@
1
- export { extractApiToken, extractBearerToken, extractQueryToken, requireApiToken } from './h3.mjs';
2
- export { decodeJwt, decodeJwtRaw, encodeJwt, encodeJwtRaw, verifyJwt, verifyJwtRaw } from './jwt.mjs';
3
- import 'h3';
4
- import '@nitrotool/errors';
1
+ export { r as requireJwt } from './shared/jwt.Cd03UmUN.mjs';
2
+ export { decodeJwt, encodeJwt, verifyJwt } from './runtime/server/index.mjs';
3
+ export { requireApiToken } from './h3/index.mjs';
4
+ export { c as configureJwtRuntime, g as getJwtSecret } from './shared/jwt.Cgq_6NMU.mjs';
5
+ import './core/index.mjs';
5
6
  import '@tsndr/cloudflare-worker-jwt';
7
+ import '@nitrotool/errors';
8
+ import 'h3';
@@ -0,0 +1,9 @@
1
+ import * as _nuxt_schema from '@nuxt/schema';
2
+
3
+ interface ModuleOptions {
4
+ secret?: string;
5
+ }
6
+ declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
7
+
8
+ export { _default as default };
9
+ export type { ModuleOptions };
@@ -0,0 +1,9 @@
1
+ import * as _nuxt_schema from '@nuxt/schema';
2
+
3
+ interface ModuleOptions {
4
+ secret?: string;
5
+ }
6
+ declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
7
+
8
+ export { _default as default };
9
+ export type { ModuleOptions };
@@ -0,0 +1,72 @@
1
+ import fs from 'node:fs';
2
+ import { defineNuxtModule, createResolver, addServerScanDir, addServerPlugin, addServerTemplate } from '@nuxt/kit';
3
+ import { consola } from 'consola';
4
+ import { join } from 'pathe';
5
+
6
+ const version = "1.0.1";
7
+
8
+ async function getFilesInDirectory(dir) {
9
+ const files = await fs.promises.readdir(dir);
10
+ const filePaths = [];
11
+ for (const file of files) {
12
+ const fullPath = join(dir, file);
13
+ const stat = await fs.promises.stat(fullPath);
14
+ if (stat.isFile()) {
15
+ filePaths.push(fullPath);
16
+ }
17
+ }
18
+ return filePaths;
19
+ }
20
+ async function getFilesInDirectoryRecursive(dir) {
21
+ const files = await fs.promises.readdir(dir);
22
+ const filePaths = [];
23
+ for (const file of files) {
24
+ const fullPath = join(dir, file);
25
+ const stat = await fs.promises.stat(fullPath);
26
+ if (stat.isFile()) {
27
+ filePaths.push(fullPath);
28
+ } else if (stat.isDirectory()) {
29
+ const subdirectoryFiles = await getFilesInDirectory(fullPath);
30
+ filePaths.push(...subdirectoryFiles);
31
+ }
32
+ }
33
+ return filePaths;
34
+ }
35
+
36
+ const module = defineNuxtModule({
37
+ meta: {
38
+ name: "@nitrotool/jwt",
39
+ configKey: "jwt",
40
+ version
41
+ },
42
+ async setup(options, nuxt) {
43
+ const logger = consola.withTag("jwt");
44
+ const resolver = createResolver(import.meta.url);
45
+ if (nuxt.options._prepare) {
46
+ logger.debug("Skipping module init due to nuxt.options._prepare = true");
47
+ return;
48
+ }
49
+ if (nuxt.options.runtimeConfig.jwtSecret) {
50
+ options.secret = nuxt.options.runtimeConfig.jwtSecret;
51
+ }
52
+ addServerScanDir([resolver.resolve("./runtime/server/nitro")]);
53
+ addServerPlugin(resolver.resolve("./runtime/server/nitro/plugin"));
54
+ const runtimeFiles = await getFilesInDirectoryRecursive(
55
+ resolver.resolve("./runtime/server")
56
+ );
57
+ for (const file of runtimeFiles) {
58
+ const relativeName = file.replace(
59
+ resolver.resolve("./runtime/server"),
60
+ ""
61
+ );
62
+ logger.debug(`Adding server template: ${relativeName}`);
63
+ addServerTemplate({
64
+ filename: relativeName,
65
+ getContents: () => fs.readFileSync(file, "utf-8")
66
+ });
67
+ }
68
+ nuxt.options.runtimeConfig.jwtSecret = options.secret;
69
+ }
70
+ });
71
+
72
+ export { module as default };
@@ -0,0 +1,16 @@
1
+ import { ExtendableJwtPayload } from '../../core/index.mjs';
2
+ import '@tsndr/cloudflare-worker-jwt';
3
+
4
+ type JwtRuntimeConfig = {
5
+ jwtSecret?: string;
6
+ };
7
+ declare const configureJwtRuntime: (getter: () => JwtRuntimeConfig) => void;
8
+ declare const getJwtSecret: () => string;
9
+
10
+ declare const encodeJwt: <T extends Record<string, any> = {}>(payload: ExtendableJwtPayload<T>, ttlSec?: number) => Promise<any>;
11
+ declare const verifyJwt: (token: string) => Promise<any>;
12
+ declare const decodeJwt: <T extends Record<string, any> = {}>(token: string, opts?: {
13
+ verify?: boolean;
14
+ }) => Promise<any>;
15
+
16
+ export { ExtendableJwtPayload, configureJwtRuntime, decodeJwt, encodeJwt, getJwtSecret, verifyJwt };
@@ -0,0 +1,16 @@
1
+ import { ExtendableJwtPayload } from '../../core/index.js';
2
+ import '@tsndr/cloudflare-worker-jwt';
3
+
4
+ type JwtRuntimeConfig = {
5
+ jwtSecret?: string;
6
+ };
7
+ declare const configureJwtRuntime: (getter: () => JwtRuntimeConfig) => void;
8
+ declare const getJwtSecret: () => string;
9
+
10
+ declare const encodeJwt: <T extends Record<string, any> = {}>(payload: ExtendableJwtPayload<T>, ttlSec?: number) => Promise<any>;
11
+ declare const verifyJwt: (token: string) => Promise<any>;
12
+ declare const decodeJwt: <T extends Record<string, any> = {}>(token: string, opts?: {
13
+ verify?: boolean;
14
+ }) => Promise<any>;
15
+
16
+ export { ExtendableJwtPayload, configureJwtRuntime, decodeJwt, encodeJwt, getJwtSecret, verifyJwt };
@@ -0,0 +1,17 @@
1
+ import { g as getJwtSecret } from '../../shared/jwt.Cgq_6NMU.mjs';
2
+ export { c as configureJwtRuntime } from '../../shared/jwt.Cgq_6NMU.mjs';
3
+ import { encodeJwtRaw, decodeJwtRaw, verifyJwtRaw } from '../../core/index.mjs';
4
+ import '@tsndr/cloudflare-worker-jwt';
5
+ import '@nitrotool/errors';
6
+
7
+ const encodeJwt = async (payload, ttlSec = 60) => {
8
+ return encodeJwtRaw(payload, getJwtSecret(), ttlSec);
9
+ };
10
+ const verifyJwt = async (token) => {
11
+ return verifyJwtRaw(token, getJwtSecret());
12
+ };
13
+ const decodeJwt = async (token, opts = { verify: true }) => {
14
+ return decodeJwtRaw(token, getJwtSecret(), opts);
15
+ };
16
+
17
+ export { decodeJwt, encodeJwt, getJwtSecret, verifyJwt };
@@ -0,0 +1,3 @@
1
+ declare const _default: any;
2
+
3
+ export { _default as default };
@@ -0,0 +1,3 @@
1
+ declare const _default: any;
2
+
3
+ export { _default as default };
@@ -0,0 +1,10 @@
1
+ import { defineNitroPlugin, useRuntimeConfig } from 'nitropack/runtime';
2
+ import { c as configureJwtRuntime } from '../../../shared/jwt.Cgq_6NMU.mjs';
3
+ import '@tsndr/cloudflare-worker-jwt';
4
+ import '@nitrotool/errors';
5
+
6
+ const plugin = defineNitroPlugin(() => {
7
+ configureJwtRuntime(() => useRuntimeConfig());
8
+ });
9
+
10
+ export { plugin as default };
@@ -0,0 +1,6 @@
1
+ export { requireJwt } from '../../../../index.mjs';
2
+ export { configureJwtRuntime, decodeJwt, encodeJwt, getJwtSecret, verifyJwt } from '../../index.mjs';
3
+ export { requireApiToken } from '../../../../h3/index.mjs';
4
+ import 'h3';
5
+ import '../../../../core/index.mjs';
6
+ import '@tsndr/cloudflare-worker-jwt';
@@ -0,0 +1,6 @@
1
+ export { requireJwt } from '../../../../index.js';
2
+ export { configureJwtRuntime, decodeJwt, encodeJwt, getJwtSecret, verifyJwt } from '../../index.js';
3
+ export { requireApiToken } from '../../../../h3/index.js';
4
+ import 'h3';
5
+ import '../../../../core/index.js';
6
+ import '@tsndr/cloudflare-worker-jwt';
@@ -0,0 +1,8 @@
1
+ export { r as requireJwt } from '../../../../shared/jwt.Cd03UmUN.mjs';
2
+ export { decodeJwt, encodeJwt, verifyJwt } from '../../index.mjs';
3
+ export { requireApiToken } from '../../../../h3/index.mjs';
4
+ export { c as configureJwtRuntime, g as getJwtSecret } from '../../../../shared/jwt.Cgq_6NMU.mjs';
5
+ import '../../../../core/index.mjs';
6
+ import '@tsndr/cloudflare-worker-jwt';
7
+ import '@nitrotool/errors';
8
+ import 'h3';
@@ -0,0 +1,8 @@
1
+ import { decodeJwt } from '../runtime/server/index.mjs';
2
+ import { requireApiToken } from '../h3/index.mjs';
3
+
4
+ const requireJwt = async (event) => {
5
+ return decodeJwt(requireApiToken(event));
6
+ };
7
+
8
+ export { requireJwt as r };
@@ -0,0 +1,16 @@
1
+ let getRuntimeConfig = () => ({});
2
+ const configureJwtRuntime = (getter) => {
3
+ getRuntimeConfig = getter;
4
+ };
5
+ const getJwtSecret = () => {
6
+ const cfg = getRuntimeConfig();
7
+ if (cfg?.jwtSecret) return cfg.jwtSecret;
8
+ if (process?.env?.NUXT_JWT_SECRET) return process?.env?.NUXT_JWT_SECRET;
9
+ if (process?.env?.NITRO_JWT_SECRET) return process?.env?.NITRO_JWT_SECRET;
10
+ if (process?.env?.JWT_SECRET) return process.env.JWT_SECRET;
11
+ throw new Error(
12
+ "jwtSecret is not configured. configure using NUXT_JWT_SECRET or jwt.secret"
13
+ );
14
+ };
15
+
16
+ export { configureJwtRuntime as c, getJwtSecret as g };
package/package.json CHANGED
@@ -1,17 +1,35 @@
1
1
  {
2
2
  "name": "@nitrotool/jwt",
3
- "version": "0.0.8",
4
- "main": "dist/index.mjs",
3
+ "version": "1.0.1",
5
4
  "type": "module",
5
+ "main": "dist/index.mjs",
6
+ "types": "./dist/index.d.ts",
6
7
  "exports": {
7
- ".": "./dist/index.mjs",
8
- "./jwt": "./dist/jwt.mjs",
9
- "./h3": "./dist/h3.mjs"
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.mjs"
11
+ },
12
+ "./module": {
13
+ "types": "./dist/module.d.ts",
14
+ "import": "./dist/module.mjs"
15
+ },
16
+ "./core": {
17
+ "types": "./dist/core/index.d.ts",
18
+ "import": "./dist/core/index.mjs"
19
+ },
20
+ "./h3": {
21
+ "types": "./dist/h3/index.d.ts",
22
+ "import": "./dist/h3/index.mjs"
23
+ }
10
24
  },
11
- "types": "./dist/index.d.ts",
12
25
  "dependencies": {
13
26
  "@tsndr/cloudflare-worker-jwt": "^3.2.0",
14
- "@nitrotool/errors": "0.0.8"
27
+ "@nitrotool/errors": "1.0.1",
28
+ "@nuxt/kit": "latest",
29
+ "pathe": "^2.0.3",
30
+ "@nuxt/schema": "^4.2.2",
31
+ "consola": "^3.4.2",
32
+ "nitropack": "^2.13.1"
15
33
  },
16
34
  "peerDependencies": {
17
35
  "h3": "^1.15.3"
@@ -19,6 +37,19 @@
19
37
  "devDependencies": {
20
38
  "unbuild": "^3.5.0"
21
39
  },
40
+ "unbuild": {
41
+ "entries": [
42
+ "src/index",
43
+ "src/module",
44
+ "src/core/index",
45
+ "src/h3/index",
46
+ "src/runtime/server/index",
47
+ "src/runtime/server/nitro/plugin",
48
+ "src/runtime/server/nitro/utils/index"
49
+ ],
50
+ "declaration": true,
51
+ "clean": true
52
+ },
22
53
  "scripts": {
23
54
  "build": "unbuild ."
24
55
  }
package/dist/jwt.d.mts DELETED
@@ -1,16 +0,0 @@
1
- import { JwtPayload } from '@tsndr/cloudflare-worker-jwt';
2
-
3
- type ExtendableJwtPayload<T extends Record<string, any> = {}> = Partial<JwtPayload> & T;
4
- declare const encodeJwtRaw: <T extends Record<string, any> = {}>(payload: ExtendableJwtPayload<T>, secret: string, ttl?: number) => Promise<string>;
5
- declare const encodeJwt: <T extends Record<string, any> = {}>(payload: ExtendableJwtPayload<T>) => Promise<string>;
6
- declare const verifyJwtRaw: (token: string, secret: string) => Promise<boolean>;
7
- declare const verifyJwt: (token: string) => Promise<boolean>;
8
- declare const decodeJwtRaw: <T extends Record<string, any> = {}>(token: string, secret: string, { verify }?: {
9
- verify?: boolean;
10
- }) => Promise<ExtendableJwtPayload<T>>;
11
- declare const decodeJwt: <T extends Record<string, any> = {}>(token: string, { verify }?: {
12
- verify?: boolean;
13
- }) => Promise<ExtendableJwtPayload<T>>;
14
-
15
- export { decodeJwt, decodeJwtRaw, encodeJwt, encodeJwtRaw, verifyJwt, verifyJwtRaw };
16
- export type { ExtendableJwtPayload };
package/dist/jwt.d.ts DELETED
@@ -1,16 +0,0 @@
1
- import { JwtPayload } from '@tsndr/cloudflare-worker-jwt';
2
-
3
- type ExtendableJwtPayload<T extends Record<string, any> = {}> = Partial<JwtPayload> & T;
4
- declare const encodeJwtRaw: <T extends Record<string, any> = {}>(payload: ExtendableJwtPayload<T>, secret: string, ttl?: number) => Promise<string>;
5
- declare const encodeJwt: <T extends Record<string, any> = {}>(payload: ExtendableJwtPayload<T>) => Promise<string>;
6
- declare const verifyJwtRaw: (token: string, secret: string) => Promise<boolean>;
7
- declare const verifyJwt: (token: string) => Promise<boolean>;
8
- declare const decodeJwtRaw: <T extends Record<string, any> = {}>(token: string, secret: string, { verify }?: {
9
- verify?: boolean;
10
- }) => Promise<ExtendableJwtPayload<T>>;
11
- declare const decodeJwt: <T extends Record<string, any> = {}>(token: string, { verify }?: {
12
- verify?: boolean;
13
- }) => Promise<ExtendableJwtPayload<T>>;
14
-
15
- export { decodeJwt, decodeJwtRaw, encodeJwt, encodeJwtRaw, verifyJwt, verifyJwtRaw };
16
- export type { ExtendableJwtPayload };
package/dist/jwt.mjs DELETED
@@ -1,52 +0,0 @@
1
- import jwt from '@tsndr/cloudflare-worker-jwt';
2
- import { UnauthorizedError } from '@nitrotool/errors';
3
-
4
- const encodeJwtRaw = async (payload, secret, ttl = 60) => {
5
- return await jwt.sign(
6
- {
7
- exp: Date.now() / 1e3 + ttl,
8
- ...payload
9
- },
10
- secret
11
- );
12
- };
13
- const encodeJwt = async (payload) => {
14
- const secret = (
15
- //@ts-expect-error Expected.
16
- typeof useRuntimeConfig === "function" ? useRuntimeConfig()?.jwtSecret : ""
17
- );
18
- return encodeJwtRaw(payload, secret);
19
- };
20
- const verifyJwtRaw = async (token, secret) => {
21
- return new Promise(async (resolve) => {
22
- if (await jwt.verify(token, secret, { throwError: false })) {
23
- return resolve(true);
24
- }
25
- return resolve(false);
26
- });
27
- };
28
- const verifyJwt = async (token) => {
29
- const secret = (
30
- //@ts-expect-error Expected.
31
- typeof useRuntimeConfig === "function" ? useRuntimeConfig()?.jwtSecret : ""
32
- );
33
- return verifyJwtRaw(token, secret);
34
- };
35
- const decodeJwtRaw = async (token, secret, { verify } = { verify: true }) => {
36
- if (!secret && verify)
37
- throw new Error("Cannot check signature without secret.");
38
- if (secret && verify && !await verifyJwtRaw(token, secret)) {
39
- throw UnauthorizedError("Invalid JWT token.");
40
- }
41
- const { payload } = jwt.decode(token);
42
- return payload;
43
- };
44
- const decodeJwt = async (token, { verify } = { verify: true }) => {
45
- if (verify && !await verifyJwt(token)) {
46
- throw UnauthorizedError("Invalid JWT token.");
47
- }
48
- const { payload } = jwt.decode(token);
49
- return payload;
50
- };
51
-
52
- export { decodeJwt, decodeJwtRaw, encodeJwt, encodeJwtRaw, verifyJwt, verifyJwtRaw };