@forge-connect/server 0.1.0

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/dist/index.cjs ADDED
@@ -0,0 +1,222 @@
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 index_exports = {};
22
+ __export(index_exports, {
23
+ ForgeConnectError: () => ForgeConnectError,
24
+ ForgeConnectServer: () => ForgeConnectServer,
25
+ JWKSVerifier: () => JWKSVerifier,
26
+ TokenExpiredError: () => TokenExpiredError,
27
+ TokenInvalidError: () => TokenInvalidError
28
+ });
29
+ module.exports = __toCommonJS(index_exports);
30
+
31
+ // src/jwt.ts
32
+ var import_jose = require("jose");
33
+
34
+ // src/errors.ts
35
+ var ForgeConnectError = class _ForgeConnectError extends Error {
36
+ status;
37
+ code;
38
+ details;
39
+ constructor(status, code, message, details) {
40
+ super(message);
41
+ this.name = "ForgeConnectError";
42
+ this.status = status;
43
+ this.code = code;
44
+ this.details = details;
45
+ }
46
+ static fromResponse(status, body) {
47
+ const { code, message, details } = body.error;
48
+ if (status === 401 && message.toLowerCase().includes("expired")) {
49
+ return new TokenExpiredError(message);
50
+ }
51
+ if (status === 401) {
52
+ return new TokenInvalidError(message);
53
+ }
54
+ return new _ForgeConnectError(status, code, message, details);
55
+ }
56
+ };
57
+ var TokenExpiredError = class extends ForgeConnectError {
58
+ constructor(message = "Token has expired") {
59
+ super(401, "TOKEN_EXPIRED", message);
60
+ this.name = "TokenExpiredError";
61
+ }
62
+ };
63
+ var TokenInvalidError = class extends ForgeConnectError {
64
+ constructor(message = "Token is invalid") {
65
+ super(401, "TOKEN_INVALID", message);
66
+ this.name = "TokenInvalidError";
67
+ }
68
+ };
69
+
70
+ // src/jwt.ts
71
+ var JWKSVerifier = class {
72
+ jwks;
73
+ constructor(apiUrl) {
74
+ const jwksUrl = new URL("/.well-known/jwks.json", apiUrl);
75
+ this.jwks = (0, import_jose.createRemoteJWKSet)(jwksUrl);
76
+ }
77
+ async verify(token) {
78
+ let result;
79
+ try {
80
+ result = await (0, import_jose.jwtVerify)(token, this.jwks, {
81
+ algorithms: ["RS256"]
82
+ });
83
+ } catch (err) {
84
+ if (err instanceof Error && err.message.includes("exp")) {
85
+ throw new TokenExpiredError();
86
+ }
87
+ throw new TokenInvalidError();
88
+ }
89
+ const payload = result.payload;
90
+ return {
91
+ sub: payload.sub,
92
+ tid: payload.tid,
93
+ scopes: payload.scopes ?? [],
94
+ iat: payload.iat,
95
+ exp: payload.exp
96
+ };
97
+ }
98
+ };
99
+
100
+ // src/http.ts
101
+ async function request(url, options = {}) {
102
+ const { method = "GET", headers = {}, body } = options;
103
+ const res = await fetch(url, {
104
+ method,
105
+ headers: {
106
+ "Content-Type": "application/json",
107
+ ...headers
108
+ },
109
+ body: body ? JSON.stringify(body) : void 0
110
+ });
111
+ if (!res.ok) {
112
+ let errorBody;
113
+ try {
114
+ errorBody = await res.json();
115
+ } catch {
116
+ throw new ForgeConnectError(res.status, "UNKNOWN", res.statusText);
117
+ }
118
+ throw ForgeConnectError.fromResponse(res.status, errorBody);
119
+ }
120
+ return res.json();
121
+ }
122
+
123
+ // src/client.ts
124
+ var ForgeConnectServer = class {
125
+ apiUrl;
126
+ serviceKey;
127
+ jwks;
128
+ constructor(config) {
129
+ this.apiUrl = config.apiUrl.replace(/\/+$/, "");
130
+ this.serviceKey = config.serviceKey;
131
+ this.jwks = new JWKSVerifier(this.apiUrl);
132
+ }
133
+ // ── Token Verification ──
134
+ /**
135
+ * Verify a JWT locally using the JWKS endpoint (fast, no network call after initial key fetch).
136
+ * Use this in middleware for every request.
137
+ */
138
+ async verifyToken(token) {
139
+ return this.jwks.verify(token);
140
+ }
141
+ /**
142
+ * Verify a token via the ForgeConnect `/service/verify-token` endpoint.
143
+ * Slower but checks session revocation server-side.
144
+ */
145
+ async verifyTokenRemote(token) {
146
+ return request(`${this.apiUrl}/service/verify-token`, {
147
+ method: "POST",
148
+ headers: { "x-service-key": this.serviceKey },
149
+ body: { token }
150
+ });
151
+ }
152
+ // ── Service Operations ──
153
+ /**
154
+ * Look up a user ID by wallet address.
155
+ */
156
+ async getUserByWallet(address, chain = "solana") {
157
+ return request(`${this.apiUrl}/service/user-by-wallet`, {
158
+ method: "POST",
159
+ headers: { "x-service-key": this.serviceKey },
160
+ body: { walletAddress: address, chain }
161
+ });
162
+ }
163
+ // ── Admin Operations ──
164
+ /**
165
+ * List users with pagination and optional search.
166
+ */
167
+ async listUsers(params = {}) {
168
+ const query = new URLSearchParams();
169
+ if (params.page) query.set("page", String(params.page));
170
+ if (params.limit) query.set("limit", String(params.limit));
171
+ if (params.search) query.set("search", params.search);
172
+ const qs = query.toString();
173
+ return request(
174
+ `${this.apiUrl}/admin/users${qs ? `?${qs}` : ""}`,
175
+ { headers: { "x-service-key": this.serviceKey } }
176
+ );
177
+ }
178
+ /**
179
+ * Get a single user by ID, including auth methods and wallets.
180
+ */
181
+ async getUser(userId) {
182
+ return request(`${this.apiUrl}/admin/users/${userId}`, {
183
+ headers: { "x-service-key": this.serviceKey }
184
+ });
185
+ }
186
+ /**
187
+ * Update a user's status (active, suspended, deleted).
188
+ */
189
+ async updateUserStatus(userId, status) {
190
+ await request(`${this.apiUrl}/admin/users/${userId}/status`, {
191
+ method: "PATCH",
192
+ headers: { "x-service-key": this.serviceKey },
193
+ body: { status }
194
+ });
195
+ }
196
+ /**
197
+ * Get all sessions for a user.
198
+ */
199
+ async getUserSessions(userId) {
200
+ return request(`${this.apiUrl}/admin/users/${userId}/sessions`, {
201
+ headers: { "x-service-key": this.serviceKey }
202
+ });
203
+ }
204
+ /**
205
+ * Revoke all sessions for a user.
206
+ */
207
+ async revokeUserSessions(userId) {
208
+ await request(`${this.apiUrl}/admin/users/${userId}/sessions`, {
209
+ method: "DELETE",
210
+ headers: { "x-service-key": this.serviceKey }
211
+ });
212
+ }
213
+ };
214
+ // Annotate the CommonJS export names for ESM import in node:
215
+ 0 && (module.exports = {
216
+ ForgeConnectError,
217
+ ForgeConnectServer,
218
+ JWKSVerifier,
219
+ TokenExpiredError,
220
+ TokenInvalidError
221
+ });
222
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/jwt.ts","../src/errors.ts","../src/http.ts","../src/client.ts"],"sourcesContent":["export { ForgeConnectServer } from './client';\nexport { JWKSVerifier } from './jwt';\nexport { ForgeConnectError, TokenExpiredError, TokenInvalidError } from './errors';\nexport type {\n ForgeConnectServerConfig,\n JWTPayload,\n User,\n UserWithRelations,\n AuthMethod,\n AuthProvider,\n Wallet,\n Chain,\n Session,\n PaginatedResponse,\n VerifyTokenResponse,\n UserByWalletResponse,\n ListUsersParams,\n ApiErrorBody,\n} from './types';\n","import { createRemoteJWKSet, jwtVerify, type JWTVerifyResult } from 'jose';\nimport type { JWTPayload } from './types';\nimport { TokenExpiredError, TokenInvalidError } from './errors';\n\nexport class JWKSVerifier {\n private jwks: ReturnType<typeof createRemoteJWKSet>;\n\n constructor(apiUrl: string) {\n const jwksUrl = new URL('/.well-known/jwks.json', apiUrl);\n this.jwks = createRemoteJWKSet(jwksUrl);\n }\n\n async verify(token: string): Promise<JWTPayload> {\n let result: JWTVerifyResult;\n try {\n result = await jwtVerify(token, this.jwks, {\n algorithms: ['RS256'],\n });\n } catch (err: unknown) {\n if (err instanceof Error && err.message.includes('exp')) {\n throw new TokenExpiredError();\n }\n throw new TokenInvalidError();\n }\n\n const payload = result.payload as unknown as JWTPayload;\n return {\n sub: payload.sub,\n tid: payload.tid,\n scopes: payload.scopes ?? [],\n iat: payload.iat,\n exp: payload.exp,\n };\n }\n}\n","import type { ApiErrorBody } from './types';\n\nexport class ForgeConnectError extends Error {\n public readonly status: number;\n public readonly code: string;\n public readonly details?: unknown[];\n\n constructor(status: number, code: string, message: string, details?: unknown[]) {\n super(message);\n this.name = 'ForgeConnectError';\n this.status = status;\n this.code = code;\n this.details = details;\n }\n\n static fromResponse(status: number, body: ApiErrorBody): ForgeConnectError {\n const { code, message, details } = body.error;\n if (status === 401 && message.toLowerCase().includes('expired')) {\n return new TokenExpiredError(message);\n }\n if (status === 401) {\n return new TokenInvalidError(message);\n }\n return new ForgeConnectError(status, code, message, details);\n }\n}\n\nexport class TokenExpiredError extends ForgeConnectError {\n constructor(message = 'Token has expired') {\n super(401, 'TOKEN_EXPIRED', message);\n this.name = 'TokenExpiredError';\n }\n}\n\nexport class TokenInvalidError extends ForgeConnectError {\n constructor(message = 'Token is invalid') {\n super(401, 'TOKEN_INVALID', message);\n this.name = 'TokenInvalidError';\n }\n}\n","import type { ApiErrorBody } from './types';\nimport { ForgeConnectError } from './errors';\n\nexport interface HttpOptions {\n method?: string;\n headers?: Record<string, string>;\n body?: unknown;\n}\n\nexport async function request<T>(url: string, options: HttpOptions = {}): Promise<T> {\n const { method = 'GET', headers = {}, body } = options;\n\n const res = await fetch(url, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!res.ok) {\n let errorBody: ApiErrorBody;\n try {\n errorBody = await res.json() as ApiErrorBody;\n } catch {\n throw new ForgeConnectError(res.status, 'UNKNOWN', res.statusText);\n }\n throw ForgeConnectError.fromResponse(res.status, errorBody);\n }\n\n return res.json() as Promise<T>;\n}\n","import type {\n ForgeConnectServerConfig,\n JWTPayload,\n VerifyTokenResponse,\n UserByWalletResponse,\n PaginatedResponse,\n User,\n UserWithRelations,\n Session,\n Chain,\n ListUsersParams,\n} from './types';\nimport { JWKSVerifier } from './jwt';\nimport { request } from './http';\n\nexport class ForgeConnectServer {\n private readonly apiUrl: string;\n private readonly serviceKey: string;\n private readonly jwks: JWKSVerifier;\n\n constructor(config: ForgeConnectServerConfig) {\n this.apiUrl = config.apiUrl.replace(/\\/+$/, '');\n this.serviceKey = config.serviceKey;\n this.jwks = new JWKSVerifier(this.apiUrl);\n }\n\n // ── Token Verification ──\n\n /**\n * Verify a JWT locally using the JWKS endpoint (fast, no network call after initial key fetch).\n * Use this in middleware for every request.\n */\n async verifyToken(token: string): Promise<JWTPayload> {\n return this.jwks.verify(token);\n }\n\n /**\n * Verify a token via the ForgeConnect `/service/verify-token` endpoint.\n * Slower but checks session revocation server-side.\n */\n async verifyTokenRemote(token: string): Promise<VerifyTokenResponse> {\n return request<VerifyTokenResponse>(`${this.apiUrl}/service/verify-token`, {\n method: 'POST',\n headers: { 'x-service-key': this.serviceKey },\n body: { token },\n });\n }\n\n // ── Service Operations ──\n\n /**\n * Look up a user ID by wallet address.\n */\n async getUserByWallet(address: string, chain: Chain = 'solana'): Promise<UserByWalletResponse> {\n return request<UserByWalletResponse>(`${this.apiUrl}/service/user-by-wallet`, {\n method: 'POST',\n headers: { 'x-service-key': this.serviceKey },\n body: { walletAddress: address, chain },\n });\n }\n\n // ── Admin Operations ──\n\n /**\n * List users with pagination and optional search.\n */\n async listUsers(params: ListUsersParams = {}): Promise<PaginatedResponse<User>> {\n const query = new URLSearchParams();\n if (params.page) query.set('page', String(params.page));\n if (params.limit) query.set('limit', String(params.limit));\n if (params.search) query.set('search', params.search);\n const qs = query.toString();\n\n return request<PaginatedResponse<User>>(\n `${this.apiUrl}/admin/users${qs ? `?${qs}` : ''}`,\n { headers: { 'x-service-key': this.serviceKey } },\n );\n }\n\n /**\n * Get a single user by ID, including auth methods and wallets.\n */\n async getUser(userId: string): Promise<UserWithRelations> {\n return request<UserWithRelations>(`${this.apiUrl}/admin/users/${userId}`, {\n headers: { 'x-service-key': this.serviceKey },\n });\n }\n\n /**\n * Update a user's status (active, suspended, deleted).\n */\n async updateUserStatus(userId: string, status: 'active' | 'suspended' | 'deleted'): Promise<void> {\n await request(`${this.apiUrl}/admin/users/${userId}/status`, {\n method: 'PATCH',\n headers: { 'x-service-key': this.serviceKey },\n body: { status },\n });\n }\n\n /**\n * Get all sessions for a user.\n */\n async getUserSessions(userId: string): Promise<Session[]> {\n return request<Session[]>(`${this.apiUrl}/admin/users/${userId}/sessions`, {\n headers: { 'x-service-key': this.serviceKey },\n });\n }\n\n /**\n * Revoke all sessions for a user.\n */\n async revokeUserSessions(userId: string): Promise<void> {\n await request(`${this.apiUrl}/admin/users/${userId}/sessions`, {\n method: 'DELETE',\n headers: { 'x-service-key': this.serviceKey },\n });\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,145 @@
1
+ interface ForgeConnectServerConfig {
2
+ /** Base URL of the ForgeConnect API (e.g. "https://connect.forge.dev") */
3
+ apiUrl: string;
4
+ /** Service key for inter-service authentication */
5
+ serviceKey: string;
6
+ }
7
+ interface JWTPayload {
8
+ sub: string;
9
+ tid?: string;
10
+ scopes: string[];
11
+ iat?: number;
12
+ exp?: number;
13
+ }
14
+ interface User {
15
+ id: string;
16
+ displayName: string | null;
17
+ avatarUrl: string | null;
18
+ primaryEmail: string | null;
19
+ status: 'active' | 'suspended' | 'deleted' | 'guest';
20
+ createdAt: string;
21
+ updatedAt: string;
22
+ }
23
+ type AuthProvider = 'email' | 'google' | 'twitter' | 'discord' | 'apple' | 'solana_wallet' | 'ethereum_wallet';
24
+ interface AuthMethod {
25
+ id: string;
26
+ provider: AuthProvider;
27
+ providerId: string;
28
+ isVerified: boolean;
29
+ verifiedAt: string | null;
30
+ createdAt: string;
31
+ }
32
+ type Chain = 'solana' | 'ethereum';
33
+ interface Wallet {
34
+ id: string;
35
+ userId: string;
36
+ chain: Chain;
37
+ address: string;
38
+ label: string | null;
39
+ isPrimary: boolean;
40
+ verifiedAt: string | null;
41
+ lastUsedAt: string | null;
42
+ }
43
+ interface Session {
44
+ id: string;
45
+ createdAt: string;
46
+ expiresAt: string;
47
+ lastActiveAt: string;
48
+ deviceInfo: Record<string, unknown> | null;
49
+ ipAddress: string;
50
+ }
51
+ interface PaginatedResponse<T> {
52
+ data: T[];
53
+ page: number;
54
+ limit: number;
55
+ total: number;
56
+ }
57
+ interface VerifyTokenResponse {
58
+ active: true;
59
+ user_id: string;
60
+ tenant_id: string | null;
61
+ scopes: string[];
62
+ }
63
+ interface UserByWalletResponse {
64
+ user_id: string;
65
+ }
66
+ interface UserWithRelations extends User {
67
+ authMethods: AuthMethod[];
68
+ wallets: Wallet[];
69
+ }
70
+ interface ListUsersParams {
71
+ page?: number;
72
+ limit?: number;
73
+ search?: string;
74
+ }
75
+ interface ApiErrorBody {
76
+ success: false;
77
+ error: {
78
+ code: string;
79
+ message: string;
80
+ details?: unknown[];
81
+ };
82
+ }
83
+
84
+ declare class ForgeConnectServer {
85
+ private readonly apiUrl;
86
+ private readonly serviceKey;
87
+ private readonly jwks;
88
+ constructor(config: ForgeConnectServerConfig);
89
+ /**
90
+ * Verify a JWT locally using the JWKS endpoint (fast, no network call after initial key fetch).
91
+ * Use this in middleware for every request.
92
+ */
93
+ verifyToken(token: string): Promise<JWTPayload>;
94
+ /**
95
+ * Verify a token via the ForgeConnect `/service/verify-token` endpoint.
96
+ * Slower but checks session revocation server-side.
97
+ */
98
+ verifyTokenRemote(token: string): Promise<VerifyTokenResponse>;
99
+ /**
100
+ * Look up a user ID by wallet address.
101
+ */
102
+ getUserByWallet(address: string, chain?: Chain): Promise<UserByWalletResponse>;
103
+ /**
104
+ * List users with pagination and optional search.
105
+ */
106
+ listUsers(params?: ListUsersParams): Promise<PaginatedResponse<User>>;
107
+ /**
108
+ * Get a single user by ID, including auth methods and wallets.
109
+ */
110
+ getUser(userId: string): Promise<UserWithRelations>;
111
+ /**
112
+ * Update a user's status (active, suspended, deleted).
113
+ */
114
+ updateUserStatus(userId: string, status: 'active' | 'suspended' | 'deleted'): Promise<void>;
115
+ /**
116
+ * Get all sessions for a user.
117
+ */
118
+ getUserSessions(userId: string): Promise<Session[]>;
119
+ /**
120
+ * Revoke all sessions for a user.
121
+ */
122
+ revokeUserSessions(userId: string): Promise<void>;
123
+ }
124
+
125
+ declare class JWKSVerifier {
126
+ private jwks;
127
+ constructor(apiUrl: string);
128
+ verify(token: string): Promise<JWTPayload>;
129
+ }
130
+
131
+ declare class ForgeConnectError extends Error {
132
+ readonly status: number;
133
+ readonly code: string;
134
+ readonly details?: unknown[];
135
+ constructor(status: number, code: string, message: string, details?: unknown[]);
136
+ static fromResponse(status: number, body: ApiErrorBody): ForgeConnectError;
137
+ }
138
+ declare class TokenExpiredError extends ForgeConnectError {
139
+ constructor(message?: string);
140
+ }
141
+ declare class TokenInvalidError extends ForgeConnectError {
142
+ constructor(message?: string);
143
+ }
144
+
145
+ export { type ApiErrorBody, type AuthMethod, type AuthProvider, type Chain, ForgeConnectError, ForgeConnectServer, type ForgeConnectServerConfig, JWKSVerifier, type JWTPayload, type ListUsersParams, type PaginatedResponse, type Session, TokenExpiredError, TokenInvalidError, type User, type UserByWalletResponse, type UserWithRelations, type VerifyTokenResponse, type Wallet };
@@ -0,0 +1,145 @@
1
+ interface ForgeConnectServerConfig {
2
+ /** Base URL of the ForgeConnect API (e.g. "https://connect.forge.dev") */
3
+ apiUrl: string;
4
+ /** Service key for inter-service authentication */
5
+ serviceKey: string;
6
+ }
7
+ interface JWTPayload {
8
+ sub: string;
9
+ tid?: string;
10
+ scopes: string[];
11
+ iat?: number;
12
+ exp?: number;
13
+ }
14
+ interface User {
15
+ id: string;
16
+ displayName: string | null;
17
+ avatarUrl: string | null;
18
+ primaryEmail: string | null;
19
+ status: 'active' | 'suspended' | 'deleted' | 'guest';
20
+ createdAt: string;
21
+ updatedAt: string;
22
+ }
23
+ type AuthProvider = 'email' | 'google' | 'twitter' | 'discord' | 'apple' | 'solana_wallet' | 'ethereum_wallet';
24
+ interface AuthMethod {
25
+ id: string;
26
+ provider: AuthProvider;
27
+ providerId: string;
28
+ isVerified: boolean;
29
+ verifiedAt: string | null;
30
+ createdAt: string;
31
+ }
32
+ type Chain = 'solana' | 'ethereum';
33
+ interface Wallet {
34
+ id: string;
35
+ userId: string;
36
+ chain: Chain;
37
+ address: string;
38
+ label: string | null;
39
+ isPrimary: boolean;
40
+ verifiedAt: string | null;
41
+ lastUsedAt: string | null;
42
+ }
43
+ interface Session {
44
+ id: string;
45
+ createdAt: string;
46
+ expiresAt: string;
47
+ lastActiveAt: string;
48
+ deviceInfo: Record<string, unknown> | null;
49
+ ipAddress: string;
50
+ }
51
+ interface PaginatedResponse<T> {
52
+ data: T[];
53
+ page: number;
54
+ limit: number;
55
+ total: number;
56
+ }
57
+ interface VerifyTokenResponse {
58
+ active: true;
59
+ user_id: string;
60
+ tenant_id: string | null;
61
+ scopes: string[];
62
+ }
63
+ interface UserByWalletResponse {
64
+ user_id: string;
65
+ }
66
+ interface UserWithRelations extends User {
67
+ authMethods: AuthMethod[];
68
+ wallets: Wallet[];
69
+ }
70
+ interface ListUsersParams {
71
+ page?: number;
72
+ limit?: number;
73
+ search?: string;
74
+ }
75
+ interface ApiErrorBody {
76
+ success: false;
77
+ error: {
78
+ code: string;
79
+ message: string;
80
+ details?: unknown[];
81
+ };
82
+ }
83
+
84
+ declare class ForgeConnectServer {
85
+ private readonly apiUrl;
86
+ private readonly serviceKey;
87
+ private readonly jwks;
88
+ constructor(config: ForgeConnectServerConfig);
89
+ /**
90
+ * Verify a JWT locally using the JWKS endpoint (fast, no network call after initial key fetch).
91
+ * Use this in middleware for every request.
92
+ */
93
+ verifyToken(token: string): Promise<JWTPayload>;
94
+ /**
95
+ * Verify a token via the ForgeConnect `/service/verify-token` endpoint.
96
+ * Slower but checks session revocation server-side.
97
+ */
98
+ verifyTokenRemote(token: string): Promise<VerifyTokenResponse>;
99
+ /**
100
+ * Look up a user ID by wallet address.
101
+ */
102
+ getUserByWallet(address: string, chain?: Chain): Promise<UserByWalletResponse>;
103
+ /**
104
+ * List users with pagination and optional search.
105
+ */
106
+ listUsers(params?: ListUsersParams): Promise<PaginatedResponse<User>>;
107
+ /**
108
+ * Get a single user by ID, including auth methods and wallets.
109
+ */
110
+ getUser(userId: string): Promise<UserWithRelations>;
111
+ /**
112
+ * Update a user's status (active, suspended, deleted).
113
+ */
114
+ updateUserStatus(userId: string, status: 'active' | 'suspended' | 'deleted'): Promise<void>;
115
+ /**
116
+ * Get all sessions for a user.
117
+ */
118
+ getUserSessions(userId: string): Promise<Session[]>;
119
+ /**
120
+ * Revoke all sessions for a user.
121
+ */
122
+ revokeUserSessions(userId: string): Promise<void>;
123
+ }
124
+
125
+ declare class JWKSVerifier {
126
+ private jwks;
127
+ constructor(apiUrl: string);
128
+ verify(token: string): Promise<JWTPayload>;
129
+ }
130
+
131
+ declare class ForgeConnectError extends Error {
132
+ readonly status: number;
133
+ readonly code: string;
134
+ readonly details?: unknown[];
135
+ constructor(status: number, code: string, message: string, details?: unknown[]);
136
+ static fromResponse(status: number, body: ApiErrorBody): ForgeConnectError;
137
+ }
138
+ declare class TokenExpiredError extends ForgeConnectError {
139
+ constructor(message?: string);
140
+ }
141
+ declare class TokenInvalidError extends ForgeConnectError {
142
+ constructor(message?: string);
143
+ }
144
+
145
+ export { type ApiErrorBody, type AuthMethod, type AuthProvider, type Chain, ForgeConnectError, ForgeConnectServer, type ForgeConnectServerConfig, JWKSVerifier, type JWTPayload, type ListUsersParams, type PaginatedResponse, type Session, TokenExpiredError, TokenInvalidError, type User, type UserByWalletResponse, type UserWithRelations, type VerifyTokenResponse, type Wallet };
package/dist/index.js ADDED
@@ -0,0 +1,191 @@
1
+ // src/jwt.ts
2
+ import { createRemoteJWKSet, jwtVerify } from "jose";
3
+
4
+ // src/errors.ts
5
+ var ForgeConnectError = class _ForgeConnectError extends Error {
6
+ status;
7
+ code;
8
+ details;
9
+ constructor(status, code, message, details) {
10
+ super(message);
11
+ this.name = "ForgeConnectError";
12
+ this.status = status;
13
+ this.code = code;
14
+ this.details = details;
15
+ }
16
+ static fromResponse(status, body) {
17
+ const { code, message, details } = body.error;
18
+ if (status === 401 && message.toLowerCase().includes("expired")) {
19
+ return new TokenExpiredError(message);
20
+ }
21
+ if (status === 401) {
22
+ return new TokenInvalidError(message);
23
+ }
24
+ return new _ForgeConnectError(status, code, message, details);
25
+ }
26
+ };
27
+ var TokenExpiredError = class extends ForgeConnectError {
28
+ constructor(message = "Token has expired") {
29
+ super(401, "TOKEN_EXPIRED", message);
30
+ this.name = "TokenExpiredError";
31
+ }
32
+ };
33
+ var TokenInvalidError = class extends ForgeConnectError {
34
+ constructor(message = "Token is invalid") {
35
+ super(401, "TOKEN_INVALID", message);
36
+ this.name = "TokenInvalidError";
37
+ }
38
+ };
39
+
40
+ // src/jwt.ts
41
+ var JWKSVerifier = class {
42
+ jwks;
43
+ constructor(apiUrl) {
44
+ const jwksUrl = new URL("/.well-known/jwks.json", apiUrl);
45
+ this.jwks = createRemoteJWKSet(jwksUrl);
46
+ }
47
+ async verify(token) {
48
+ let result;
49
+ try {
50
+ result = await jwtVerify(token, this.jwks, {
51
+ algorithms: ["RS256"]
52
+ });
53
+ } catch (err) {
54
+ if (err instanceof Error && err.message.includes("exp")) {
55
+ throw new TokenExpiredError();
56
+ }
57
+ throw new TokenInvalidError();
58
+ }
59
+ const payload = result.payload;
60
+ return {
61
+ sub: payload.sub,
62
+ tid: payload.tid,
63
+ scopes: payload.scopes ?? [],
64
+ iat: payload.iat,
65
+ exp: payload.exp
66
+ };
67
+ }
68
+ };
69
+
70
+ // src/http.ts
71
+ async function request(url, options = {}) {
72
+ const { method = "GET", headers = {}, body } = options;
73
+ const res = await fetch(url, {
74
+ method,
75
+ headers: {
76
+ "Content-Type": "application/json",
77
+ ...headers
78
+ },
79
+ body: body ? JSON.stringify(body) : void 0
80
+ });
81
+ if (!res.ok) {
82
+ let errorBody;
83
+ try {
84
+ errorBody = await res.json();
85
+ } catch {
86
+ throw new ForgeConnectError(res.status, "UNKNOWN", res.statusText);
87
+ }
88
+ throw ForgeConnectError.fromResponse(res.status, errorBody);
89
+ }
90
+ return res.json();
91
+ }
92
+
93
+ // src/client.ts
94
+ var ForgeConnectServer = class {
95
+ apiUrl;
96
+ serviceKey;
97
+ jwks;
98
+ constructor(config) {
99
+ this.apiUrl = config.apiUrl.replace(/\/+$/, "");
100
+ this.serviceKey = config.serviceKey;
101
+ this.jwks = new JWKSVerifier(this.apiUrl);
102
+ }
103
+ // ── Token Verification ──
104
+ /**
105
+ * Verify a JWT locally using the JWKS endpoint (fast, no network call after initial key fetch).
106
+ * Use this in middleware for every request.
107
+ */
108
+ async verifyToken(token) {
109
+ return this.jwks.verify(token);
110
+ }
111
+ /**
112
+ * Verify a token via the ForgeConnect `/service/verify-token` endpoint.
113
+ * Slower but checks session revocation server-side.
114
+ */
115
+ async verifyTokenRemote(token) {
116
+ return request(`${this.apiUrl}/service/verify-token`, {
117
+ method: "POST",
118
+ headers: { "x-service-key": this.serviceKey },
119
+ body: { token }
120
+ });
121
+ }
122
+ // ── Service Operations ──
123
+ /**
124
+ * Look up a user ID by wallet address.
125
+ */
126
+ async getUserByWallet(address, chain = "solana") {
127
+ return request(`${this.apiUrl}/service/user-by-wallet`, {
128
+ method: "POST",
129
+ headers: { "x-service-key": this.serviceKey },
130
+ body: { walletAddress: address, chain }
131
+ });
132
+ }
133
+ // ── Admin Operations ──
134
+ /**
135
+ * List users with pagination and optional search.
136
+ */
137
+ async listUsers(params = {}) {
138
+ const query = new URLSearchParams();
139
+ if (params.page) query.set("page", String(params.page));
140
+ if (params.limit) query.set("limit", String(params.limit));
141
+ if (params.search) query.set("search", params.search);
142
+ const qs = query.toString();
143
+ return request(
144
+ `${this.apiUrl}/admin/users${qs ? `?${qs}` : ""}`,
145
+ { headers: { "x-service-key": this.serviceKey } }
146
+ );
147
+ }
148
+ /**
149
+ * Get a single user by ID, including auth methods and wallets.
150
+ */
151
+ async getUser(userId) {
152
+ return request(`${this.apiUrl}/admin/users/${userId}`, {
153
+ headers: { "x-service-key": this.serviceKey }
154
+ });
155
+ }
156
+ /**
157
+ * Update a user's status (active, suspended, deleted).
158
+ */
159
+ async updateUserStatus(userId, status) {
160
+ await request(`${this.apiUrl}/admin/users/${userId}/status`, {
161
+ method: "PATCH",
162
+ headers: { "x-service-key": this.serviceKey },
163
+ body: { status }
164
+ });
165
+ }
166
+ /**
167
+ * Get all sessions for a user.
168
+ */
169
+ async getUserSessions(userId) {
170
+ return request(`${this.apiUrl}/admin/users/${userId}/sessions`, {
171
+ headers: { "x-service-key": this.serviceKey }
172
+ });
173
+ }
174
+ /**
175
+ * Revoke all sessions for a user.
176
+ */
177
+ async revokeUserSessions(userId) {
178
+ await request(`${this.apiUrl}/admin/users/${userId}/sessions`, {
179
+ method: "DELETE",
180
+ headers: { "x-service-key": this.serviceKey }
181
+ });
182
+ }
183
+ };
184
+ export {
185
+ ForgeConnectError,
186
+ ForgeConnectServer,
187
+ JWKSVerifier,
188
+ TokenExpiredError,
189
+ TokenInvalidError
190
+ };
191
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/jwt.ts","../src/errors.ts","../src/http.ts","../src/client.ts"],"sourcesContent":["import { createRemoteJWKSet, jwtVerify, type JWTVerifyResult } from 'jose';\nimport type { JWTPayload } from './types';\nimport { TokenExpiredError, TokenInvalidError } from './errors';\n\nexport class JWKSVerifier {\n private jwks: ReturnType<typeof createRemoteJWKSet>;\n\n constructor(apiUrl: string) {\n const jwksUrl = new URL('/.well-known/jwks.json', apiUrl);\n this.jwks = createRemoteJWKSet(jwksUrl);\n }\n\n async verify(token: string): Promise<JWTPayload> {\n let result: JWTVerifyResult;\n try {\n result = await jwtVerify(token, this.jwks, {\n algorithms: ['RS256'],\n });\n } catch (err: unknown) {\n if (err instanceof Error && err.message.includes('exp')) {\n throw new TokenExpiredError();\n }\n throw new TokenInvalidError();\n }\n\n const payload = result.payload as unknown as JWTPayload;\n return {\n sub: payload.sub,\n tid: payload.tid,\n scopes: payload.scopes ?? [],\n iat: payload.iat,\n exp: payload.exp,\n };\n }\n}\n","import type { ApiErrorBody } from './types';\n\nexport class ForgeConnectError extends Error {\n public readonly status: number;\n public readonly code: string;\n public readonly details?: unknown[];\n\n constructor(status: number, code: string, message: string, details?: unknown[]) {\n super(message);\n this.name = 'ForgeConnectError';\n this.status = status;\n this.code = code;\n this.details = details;\n }\n\n static fromResponse(status: number, body: ApiErrorBody): ForgeConnectError {\n const { code, message, details } = body.error;\n if (status === 401 && message.toLowerCase().includes('expired')) {\n return new TokenExpiredError(message);\n }\n if (status === 401) {\n return new TokenInvalidError(message);\n }\n return new ForgeConnectError(status, code, message, details);\n }\n}\n\nexport class TokenExpiredError extends ForgeConnectError {\n constructor(message = 'Token has expired') {\n super(401, 'TOKEN_EXPIRED', message);\n this.name = 'TokenExpiredError';\n }\n}\n\nexport class TokenInvalidError extends ForgeConnectError {\n constructor(message = 'Token is invalid') {\n super(401, 'TOKEN_INVALID', message);\n this.name = 'TokenInvalidError';\n }\n}\n","import type { ApiErrorBody } from './types';\nimport { ForgeConnectError } from './errors';\n\nexport interface HttpOptions {\n method?: string;\n headers?: Record<string, string>;\n body?: unknown;\n}\n\nexport async function request<T>(url: string, options: HttpOptions = {}): Promise<T> {\n const { method = 'GET', headers = {}, body } = options;\n\n const res = await fetch(url, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!res.ok) {\n let errorBody: ApiErrorBody;\n try {\n errorBody = await res.json() as ApiErrorBody;\n } catch {\n throw new ForgeConnectError(res.status, 'UNKNOWN', res.statusText);\n }\n throw ForgeConnectError.fromResponse(res.status, errorBody);\n }\n\n return res.json() as Promise<T>;\n}\n","import type {\n ForgeConnectServerConfig,\n JWTPayload,\n VerifyTokenResponse,\n UserByWalletResponse,\n PaginatedResponse,\n User,\n UserWithRelations,\n Session,\n Chain,\n ListUsersParams,\n} from './types';\nimport { JWKSVerifier } from './jwt';\nimport { request } from './http';\n\nexport class ForgeConnectServer {\n private readonly apiUrl: string;\n private readonly serviceKey: string;\n private readonly jwks: JWKSVerifier;\n\n constructor(config: ForgeConnectServerConfig) {\n this.apiUrl = config.apiUrl.replace(/\\/+$/, '');\n this.serviceKey = config.serviceKey;\n this.jwks = new JWKSVerifier(this.apiUrl);\n }\n\n // ── Token Verification ──\n\n /**\n * Verify a JWT locally using the JWKS endpoint (fast, no network call after initial key fetch).\n * Use this in middleware for every request.\n */\n async verifyToken(token: string): Promise<JWTPayload> {\n return this.jwks.verify(token);\n }\n\n /**\n * Verify a token via the ForgeConnect `/service/verify-token` endpoint.\n * Slower but checks session revocation server-side.\n */\n async verifyTokenRemote(token: string): Promise<VerifyTokenResponse> {\n return request<VerifyTokenResponse>(`${this.apiUrl}/service/verify-token`, {\n method: 'POST',\n headers: { 'x-service-key': this.serviceKey },\n body: { token },\n });\n }\n\n // ── Service Operations ──\n\n /**\n * Look up a user ID by wallet address.\n */\n async getUserByWallet(address: string, chain: Chain = 'solana'): Promise<UserByWalletResponse> {\n return request<UserByWalletResponse>(`${this.apiUrl}/service/user-by-wallet`, {\n method: 'POST',\n headers: { 'x-service-key': this.serviceKey },\n body: { walletAddress: address, chain },\n });\n }\n\n // ── Admin Operations ──\n\n /**\n * List users with pagination and optional search.\n */\n async listUsers(params: ListUsersParams = {}): Promise<PaginatedResponse<User>> {\n const query = new URLSearchParams();\n if (params.page) query.set('page', String(params.page));\n if (params.limit) query.set('limit', String(params.limit));\n if (params.search) query.set('search', params.search);\n const qs = query.toString();\n\n return request<PaginatedResponse<User>>(\n `${this.apiUrl}/admin/users${qs ? `?${qs}` : ''}`,\n { headers: { 'x-service-key': this.serviceKey } },\n );\n }\n\n /**\n * Get a single user by ID, including auth methods and wallets.\n */\n async getUser(userId: string): Promise<UserWithRelations> {\n return request<UserWithRelations>(`${this.apiUrl}/admin/users/${userId}`, {\n headers: { 'x-service-key': this.serviceKey },\n });\n }\n\n /**\n * Update a user's status (active, suspended, deleted).\n */\n async updateUserStatus(userId: string, status: 'active' | 'suspended' | 'deleted'): Promise<void> {\n await request(`${this.apiUrl}/admin/users/${userId}/status`, {\n method: 'PATCH',\n headers: { 'x-service-key': this.serviceKey },\n body: { status },\n });\n }\n\n /**\n * Get all sessions for a user.\n */\n async getUserSessions(userId: string): Promise<Session[]> {\n return request<Session[]>(`${this.apiUrl}/admin/users/${userId}/sessions`, {\n headers: { 'x-service-key': this.serviceKey },\n });\n }\n\n /**\n * Revoke all sessions for a user.\n */\n async revokeUserSessions(userId: string): Promise<void> {\n await request(`${this.apiUrl}/admin/users/${userId}/sessions`, {\n method: 'DELETE',\n headers: { 'x-service-key': this.serviceKey },\n });\n }\n}\n"],"mappings":";AAAA,SAAS,oBAAoB,iBAAuC;;;ACE7D,IAAM,oBAAN,MAAM,2BAA0B,MAAM;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EAEhB,YAAY,QAAgB,MAAc,SAAiB,SAAqB;AAC9E,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,SAAS;AACd,SAAK,OAAO;AACZ,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,OAAO,aAAa,QAAgB,MAAuC;AACzE,UAAM,EAAE,MAAM,SAAS,QAAQ,IAAI,KAAK;AACxC,QAAI,WAAW,OAAO,QAAQ,YAAY,EAAE,SAAS,SAAS,GAAG;AAC/D,aAAO,IAAI,kBAAkB,OAAO;AAAA,IACtC;AACA,QAAI,WAAW,KAAK;AAClB,aAAO,IAAI,kBAAkB,OAAO;AAAA,IACtC;AACA,WAAO,IAAI,mBAAkB,QAAQ,MAAM,SAAS,OAAO;AAAA,EAC7D;AACF;AAEO,IAAM,oBAAN,cAAgC,kBAAkB;AAAA,EACvD,YAAY,UAAU,qBAAqB;AACzC,UAAM,KAAK,iBAAiB,OAAO;AACnC,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,oBAAN,cAAgC,kBAAkB;AAAA,EACvD,YAAY,UAAU,oBAAoB;AACxC,UAAM,KAAK,iBAAiB,OAAO;AACnC,SAAK,OAAO;AAAA,EACd;AACF;;;ADnCO,IAAM,eAAN,MAAmB;AAAA,EAChB;AAAA,EAER,YAAY,QAAgB;AAC1B,UAAM,UAAU,IAAI,IAAI,0BAA0B,MAAM;AACxD,SAAK,OAAO,mBAAmB,OAAO;AAAA,EACxC;AAAA,EAEA,MAAM,OAAO,OAAoC;AAC/C,QAAI;AACJ,QAAI;AACF,eAAS,MAAM,UAAU,OAAO,KAAK,MAAM;AAAA,QACzC,YAAY,CAAC,OAAO;AAAA,MACtB,CAAC;AAAA,IACH,SAAS,KAAc;AACrB,UAAI,eAAe,SAAS,IAAI,QAAQ,SAAS,KAAK,GAAG;AACvD,cAAM,IAAI,kBAAkB;AAAA,MAC9B;AACA,YAAM,IAAI,kBAAkB;AAAA,IAC9B;AAEA,UAAM,UAAU,OAAO;AACvB,WAAO;AAAA,MACL,KAAK,QAAQ;AAAA,MACb,KAAK,QAAQ;AAAA,MACb,QAAQ,QAAQ,UAAU,CAAC;AAAA,MAC3B,KAAK,QAAQ;AAAA,MACb,KAAK,QAAQ;AAAA,IACf;AAAA,EACF;AACF;;;AEzBA,eAAsB,QAAW,KAAa,UAAuB,CAAC,GAAe;AACnF,QAAM,EAAE,SAAS,OAAO,UAAU,CAAC,GAAG,KAAK,IAAI;AAE/C,QAAM,MAAM,MAAM,MAAM,KAAK;AAAA,IAC3B;AAAA,IACA,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,GAAG;AAAA,IACL;AAAA,IACA,MAAM,OAAO,KAAK,UAAU,IAAI,IAAI;AAAA,EACtC,CAAC;AAED,MAAI,CAAC,IAAI,IAAI;AACX,QAAI;AACJ,QAAI;AACF,kBAAY,MAAM,IAAI,KAAK;AAAA,IAC7B,QAAQ;AACN,YAAM,IAAI,kBAAkB,IAAI,QAAQ,WAAW,IAAI,UAAU;AAAA,IACnE;AACA,UAAM,kBAAkB,aAAa,IAAI,QAAQ,SAAS;AAAA,EAC5D;AAEA,SAAO,IAAI,KAAK;AAClB;;;ACjBO,IAAM,qBAAN,MAAyB;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,QAAkC;AAC5C,SAAK,SAAS,OAAO,OAAO,QAAQ,QAAQ,EAAE;AAC9C,SAAK,aAAa,OAAO;AACzB,SAAK,OAAO,IAAI,aAAa,KAAK,MAAM;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,YAAY,OAAoC;AACpD,WAAO,KAAK,KAAK,OAAO,KAAK;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,kBAAkB,OAA6C;AACnE,WAAO,QAA6B,GAAG,KAAK,MAAM,yBAAyB;AAAA,MACzE,QAAQ;AAAA,MACR,SAAS,EAAE,iBAAiB,KAAK,WAAW;AAAA,MAC5C,MAAM,EAAE,MAAM;AAAA,IAChB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,gBAAgB,SAAiB,QAAe,UAAyC;AAC7F,WAAO,QAA8B,GAAG,KAAK,MAAM,2BAA2B;AAAA,MAC5E,QAAQ;AAAA,MACR,SAAS,EAAE,iBAAiB,KAAK,WAAW;AAAA,MAC5C,MAAM,EAAE,eAAe,SAAS,MAAM;AAAA,IACxC,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,UAAU,SAA0B,CAAC,GAAqC;AAC9E,UAAM,QAAQ,IAAI,gBAAgB;AAClC,QAAI,OAAO,KAAM,OAAM,IAAI,QAAQ,OAAO,OAAO,IAAI,CAAC;AACtD,QAAI,OAAO,MAAO,OAAM,IAAI,SAAS,OAAO,OAAO,KAAK,CAAC;AACzD,QAAI,OAAO,OAAQ,OAAM,IAAI,UAAU,OAAO,MAAM;AACpD,UAAM,KAAK,MAAM,SAAS;AAE1B,WAAO;AAAA,MACL,GAAG,KAAK,MAAM,eAAe,KAAK,IAAI,EAAE,KAAK,EAAE;AAAA,MAC/C,EAAE,SAAS,EAAE,iBAAiB,KAAK,WAAW,EAAE;AAAA,IAClD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAQ,QAA4C;AACxD,WAAO,QAA2B,GAAG,KAAK,MAAM,gBAAgB,MAAM,IAAI;AAAA,MACxE,SAAS,EAAE,iBAAiB,KAAK,WAAW;AAAA,IAC9C,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAiB,QAAgB,QAA2D;AAChG,UAAM,QAAQ,GAAG,KAAK,MAAM,gBAAgB,MAAM,WAAW;AAAA,MAC3D,QAAQ;AAAA,MACR,SAAS,EAAE,iBAAiB,KAAK,WAAW;AAAA,MAC5C,MAAM,EAAE,OAAO;AAAA,IACjB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBAAgB,QAAoC;AACxD,WAAO,QAAmB,GAAG,KAAK,MAAM,gBAAgB,MAAM,aAAa;AAAA,MACzE,SAAS,EAAE,iBAAiB,KAAK,WAAW;AAAA,IAC9C,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,mBAAmB,QAA+B;AACtD,UAAM,QAAQ,GAAG,KAAK,MAAM,gBAAgB,MAAM,aAAa;AAAA,MAC7D,QAAQ;AAAA,MACR,SAAS,EAAE,iBAAiB,KAAK,WAAW;AAAA,IAC9C,CAAC;AAAA,EACH;AACF;","names":[]}
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@forge-connect/server",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "./dist/index.cjs",
6
+ "module": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": {
11
+ "types": "./dist/index.d.ts",
12
+ "default": "./dist/index.js"
13
+ },
14
+ "require": {
15
+ "types": "./dist/index.d.cts",
16
+ "default": "./dist/index.cjs"
17
+ }
18
+ }
19
+ },
20
+ "files": [
21
+ "dist"
22
+ ],
23
+ "dependencies": {
24
+ "jose": "^6.1.3"
25
+ },
26
+ "devDependencies": {
27
+ "tsup": "^8.4.0",
28
+ "typescript": "^5.9.3"
29
+ },
30
+ "scripts": {
31
+ "build": "tsup",
32
+ "dev": "tsup --watch"
33
+ }
34
+ }