@01.software/sdk 0.1.0-dev.260210.4ecca43 → 0.1.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.
@@ -0,0 +1,267 @@
1
+ import { Sort, Where } from 'payload';
2
+ import './payload-types-BE-5_Y2d.js';
3
+
4
+ declare class SDKError extends Error {
5
+ readonly code: string;
6
+ readonly status?: number;
7
+ readonly details?: unknown;
8
+ readonly userMessage?: string;
9
+ readonly suggestion?: string;
10
+ constructor(code: string, message: string, status?: number, details?: unknown, userMessage?: string, suggestion?: string);
11
+ getUserMessage(): string;
12
+ toJSON(): {
13
+ name: string;
14
+ code: string;
15
+ message: string;
16
+ status: number | undefined;
17
+ details: unknown;
18
+ userMessage: string | undefined;
19
+ suggestion: string | undefined;
20
+ };
21
+ }
22
+ declare class NetworkError extends SDKError {
23
+ constructor(message: string, status?: number, details?: unknown, userMessage?: string, suggestion?: string);
24
+ }
25
+ declare class ValidationError extends SDKError {
26
+ constructor(message: string, details?: unknown, userMessage?: string, suggestion?: string);
27
+ }
28
+ declare class ApiError extends SDKError {
29
+ constructor(message: string, status: number, details?: unknown, userMessage?: string, suggestion?: string);
30
+ }
31
+ declare class ConfigError extends SDKError {
32
+ constructor(message: string, details?: unknown, userMessage?: string, suggestion?: string);
33
+ }
34
+ declare class TimeoutError extends SDKError {
35
+ constructor(message?: string, details?: unknown, userMessage?: string, suggestion?: string);
36
+ }
37
+ declare class UsageLimitError extends SDKError {
38
+ readonly usage: {
39
+ limit: number;
40
+ current: number;
41
+ remaining: number;
42
+ };
43
+ constructor(message: string, usage: {
44
+ limit: number;
45
+ current: number;
46
+ remaining: number;
47
+ }, details?: unknown, userMessage?: string, suggestion?: string);
48
+ toJSON(): {
49
+ usage: {
50
+ limit: number;
51
+ current: number;
52
+ remaining: number;
53
+ };
54
+ name: string;
55
+ code: string;
56
+ message: string;
57
+ status: number | undefined;
58
+ details: unknown;
59
+ userMessage: string | undefined;
60
+ suggestion: string | undefined;
61
+ };
62
+ }
63
+ declare function isSDKError(error: unknown): error is SDKError;
64
+ declare function isNetworkError(error: unknown): error is NetworkError;
65
+ declare function isValidationError(error: unknown): error is ValidationError;
66
+ declare function isApiError(error: unknown): error is ApiError;
67
+ declare function isConfigError(error: unknown): error is ConfigError;
68
+ declare function isTimeoutError(error: unknown): error is TimeoutError;
69
+ declare function isUsageLimitError(error: unknown): error is UsageLimitError;
70
+
71
+ type Environment = 'local' | 'development' | 'staging' | 'production';
72
+ declare const API_URLS: Record<Environment, string>;
73
+ /**
74
+ * 환경에 맞는 API URL을 반환합니다.
75
+ * 우선순위: baseUrl > environment > 환경변수 > 기본값(production)
76
+ */
77
+ declare function resolveApiUrl(config?: {
78
+ baseUrl?: string;
79
+ environment?: Environment;
80
+ }): string;
81
+ interface ClientBrowserConfig {
82
+ clientKey: string;
83
+ /**
84
+ * API 환경 설정.
85
+ * - 'local': localhost:3000
86
+ * - 'development': dev.01.software
87
+ * - 'staging': stg.01.software
88
+ * - 'production': api.01.software
89
+ *
90
+ * baseUrl이 설정되면 이 값은 무시됩니다.
91
+ * @default 'production'
92
+ */
93
+ environment?: Environment;
94
+ /**
95
+ * 커스텀 API URL. 설정 시 environment 값은 무시됩니다.
96
+ * @example 'https://my-custom-api.example.com'
97
+ */
98
+ baseUrl?: string;
99
+ }
100
+ interface ClientServerConfig extends ClientBrowserConfig {
101
+ secretKey: string;
102
+ }
103
+ interface ClientMetadata {
104
+ userAgent?: string;
105
+ timestamp: number;
106
+ }
107
+ interface ClientState {
108
+ metadata: ClientMetadata;
109
+ }
110
+ interface PaginationMeta {
111
+ page: number;
112
+ limit: number;
113
+ totalDocs: number;
114
+ totalPages: number;
115
+ hasNextPage: boolean;
116
+ hasPrevPage: boolean;
117
+ pagingCounter: number;
118
+ prevPage: number | null;
119
+ nextPage: number | null;
120
+ }
121
+ /**
122
+ * Payload CMS Find (List) Response
123
+ * GET /api/{collection}
124
+ */
125
+ interface PayloadFindResponse<T = unknown> {
126
+ docs: T[];
127
+ totalDocs: number;
128
+ limit: number;
129
+ totalPages: number;
130
+ page: number;
131
+ pagingCounter: number;
132
+ hasPrevPage: boolean;
133
+ hasNextPage: boolean;
134
+ prevPage: number | null;
135
+ nextPage: number | null;
136
+ }
137
+ /**
138
+ * Payload CMS Create/Update Response
139
+ * POST /api/{collection}
140
+ * PATCH /api/{collection}/{id}
141
+ */
142
+ interface PayloadMutationResponse<T = unknown> {
143
+ message: string;
144
+ doc: T;
145
+ errors?: unknown[];
146
+ }
147
+ interface ApiQueryOptions {
148
+ page?: number;
149
+ limit?: number;
150
+ sort?: Sort;
151
+ where?: Where;
152
+ depth?: number;
153
+ select?: Record<string, boolean>;
154
+ }
155
+ interface ApiQueryReactOptions {
156
+ keepPreviousData?: boolean;
157
+ }
158
+ interface DebugConfig {
159
+ logRequests?: boolean;
160
+ logResponses?: boolean;
161
+ logErrors?: boolean;
162
+ }
163
+ interface RetryConfig {
164
+ maxRetries?: number;
165
+ retryableStatuses?: number[];
166
+ retryDelay?: (attempt: number) => number;
167
+ }
168
+ interface ErrorLogger {
169
+ log(error: SDKError | Error, context?: Record<string, unknown>): void;
170
+ }
171
+ type DeepPartial<T> = {
172
+ [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
173
+ };
174
+ type ExtractArrayType<T> = T extends (infer U)[] ? U : never;
175
+
176
+ interface FetchOptions extends RequestInit {
177
+ clientKey?: string;
178
+ secretKey?: string;
179
+ timeout?: number;
180
+ baseUrl?: string;
181
+ debug?: boolean | DebugConfig;
182
+ retry?: RetryConfig;
183
+ }
184
+ interface JwtPayload {
185
+ clientKey: string;
186
+ iat?: number;
187
+ exp?: number;
188
+ }
189
+ /**
190
+ * Creates a JWT token for server-side authentication.
191
+ * The token is valid for 1 hour by default.
192
+ *
193
+ * @param clientKey - Client API key
194
+ * @param secretKey - Secret key used for signing
195
+ * @param expiresIn - Token expiration time (default: '1h')
196
+ * @returns Promise<string> JWT token
197
+ *
198
+ * @example
199
+ * ```typescript
200
+ * const token = await createServerToken('client-key', 'secret-key')
201
+ * // Use in Authorization header: `Bearer ${token}`
202
+ * ```
203
+ */
204
+ declare function createServerToken(clientKey: string, secretKey: string, expiresIn?: string): Promise<string>;
205
+ /**
206
+ * Verifies a JWT token and returns the payload.
207
+ *
208
+ * @param token - JWT token to verify
209
+ * @param secretKey - Secret key used for verification
210
+ * @returns Promise<JwtPayload> Verified payload containing clientKey
211
+ * @throws Error if token is invalid or expired
212
+ *
213
+ * @example
214
+ * ```typescript
215
+ * const payload = await verifyServerToken(token, 'secret-key')
216
+ * console.log(payload.clientKey)
217
+ * ```
218
+ */
219
+ declare function verifyServerToken(token: string, secretKey: string): Promise<JwtPayload>;
220
+ /**
221
+ * Decodes a JWT token without verification.
222
+ * WARNING: Use this only when you need to inspect token contents.
223
+ * Always use verifyServerToken for authentication.
224
+ *
225
+ * @param token - JWT token to decode
226
+ * @returns JwtPayload Decoded payload (unverified)
227
+ *
228
+ * @example
229
+ * ```typescript
230
+ * const payload = decodeServerToken(token)
231
+ * console.log(payload.clientKey) // Unverified!
232
+ * ```
233
+ */
234
+ declare function decodeServerToken(token: string): JwtPayload;
235
+ /**
236
+ * Creates a Base64-encoded API key from clientKey and secretKey.
237
+ * Use this for MCP server authentication.
238
+ *
239
+ * @param clientKey - Client API key
240
+ * @param secretKey - Secret key
241
+ * @returns Base64-encoded API key
242
+ *
243
+ * @example
244
+ * ```typescript
245
+ * const apiKey = createApiKey('client-key', 'secret-key')
246
+ * // Use in x-api-key header
247
+ * ```
248
+ */
249
+ declare function createApiKey(clientKey: string, secretKey: string): string;
250
+ /**
251
+ * Parses a Base64-encoded API key to extract clientKey and secretKey.
252
+ *
253
+ * @param apiKey - Base64-encoded API key
254
+ * @returns Object containing clientKey and secretKey
255
+ * @throws Error if API key is invalid
256
+ *
257
+ * @example
258
+ * ```typescript
259
+ * const { clientKey, secretKey } = parseApiKey(apiKey)
260
+ * ```
261
+ */
262
+ declare function parseApiKey(apiKey: string): {
263
+ clientKey: string;
264
+ secretKey: string;
265
+ };
266
+
267
+ export { type ApiQueryOptions as A, type ClientBrowserConfig as C, type DeepPartial as D, type ExtractArrayType as E, type FetchOptions as F, type JwtPayload as J, NetworkError as N, type PayloadFindResponse as P, type RetryConfig as R, SDKError as S, TimeoutError as T, UsageLimitError as U, ValidationError as V, type PayloadMutationResponse as a, type ClientState as b, type ClientServerConfig as c, type DebugConfig as d, type ErrorLogger as e, ApiError as f, ConfigError as g, isNetworkError as h, isSDKError as i, isValidationError as j, isApiError as k, isConfigError as l, isTimeoutError as m, isUsageLimitError as n, createServerToken as o, decodeServerToken as p, createApiKey as q, parseApiKey as r, type Environment as s, API_URLS as t, resolveApiUrl as u, verifyServerToken as v, type ClientMetadata as w, type PaginationMeta as x, type ApiQueryReactOptions as y };
package/dist/auth.cjs ADDED
@@ -0,0 +1,129 @@
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
+ var __async = (__this, __arguments, generator) => {
20
+ return new Promise((resolve, reject) => {
21
+ var fulfilled = (value) => {
22
+ try {
23
+ step(generator.next(value));
24
+ } catch (e) {
25
+ reject(e);
26
+ }
27
+ };
28
+ var rejected = (value) => {
29
+ try {
30
+ step(generator.throw(value));
31
+ } catch (e) {
32
+ reject(e);
33
+ }
34
+ };
35
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
36
+ step((generator = generator.apply(__this, __arguments)).next());
37
+ });
38
+ };
39
+
40
+ // src/auth.ts
41
+ var auth_exports = {};
42
+ __export(auth_exports, {
43
+ createApiKey: () => createApiKey,
44
+ createServerToken: () => createServerToken,
45
+ decodeServerToken: () => decodeServerToken,
46
+ parseApiKey: () => parseApiKey,
47
+ verifyServerToken: () => verifyServerToken
48
+ });
49
+ module.exports = __toCommonJS(auth_exports);
50
+
51
+ // src/core/internal/utils/index.ts
52
+ var import_jose = require("jose");
53
+ function createServerToken(clientKey, secretKey, expiresIn = "1h") {
54
+ return __async(this, null, function* () {
55
+ if (!clientKey || !secretKey) {
56
+ throw new Error("clientKey and secretKey are required.");
57
+ }
58
+ const secret = new TextEncoder().encode(secretKey);
59
+ return new import_jose.SignJWT({ clientKey }).setProtectedHeader({ alg: "HS256" }).setIssuedAt().setExpirationTime(expiresIn).sign(secret);
60
+ });
61
+ }
62
+ function verifyServerToken(token, secretKey) {
63
+ return __async(this, null, function* () {
64
+ if (!token || !secretKey) {
65
+ throw new Error("token and secretKey are required.");
66
+ }
67
+ const secret = new TextEncoder().encode(secretKey);
68
+ const { payload } = yield (0, import_jose.jwtVerify)(token, secret, {
69
+ algorithms: ["HS256"]
70
+ });
71
+ if (!payload.clientKey || typeof payload.clientKey !== "string") {
72
+ throw new Error("Invalid token payload: clientKey is missing");
73
+ }
74
+ return {
75
+ clientKey: payload.clientKey,
76
+ iat: payload.iat,
77
+ exp: payload.exp
78
+ };
79
+ });
80
+ }
81
+ function decodeServerToken(token) {
82
+ if (!token) {
83
+ throw new Error("token is required.");
84
+ }
85
+ const payload = (0, import_jose.decodeJwt)(token);
86
+ if (!payload.clientKey || typeof payload.clientKey !== "string") {
87
+ throw new Error("Invalid token payload: clientKey is missing");
88
+ }
89
+ return {
90
+ clientKey: payload.clientKey,
91
+ iat: payload.iat,
92
+ exp: payload.exp
93
+ };
94
+ }
95
+ function createApiKey(clientKey, secretKey) {
96
+ if (!clientKey || !secretKey) {
97
+ throw new Error("clientKey and secretKey are required.");
98
+ }
99
+ if (typeof Buffer !== "undefined") {
100
+ return Buffer.from(`${clientKey}:${secretKey}`).toString("base64");
101
+ }
102
+ return btoa(`${clientKey}:${secretKey}`);
103
+ }
104
+ function parseApiKey(apiKey) {
105
+ if (!apiKey) {
106
+ throw new Error("apiKey is required.");
107
+ }
108
+ try {
109
+ let decoded;
110
+ if (typeof Buffer !== "undefined") {
111
+ decoded = Buffer.from(apiKey, "base64").toString("utf-8");
112
+ } else {
113
+ decoded = atob(apiKey);
114
+ }
115
+ const colonIndex = decoded.indexOf(":");
116
+ if (colonIndex === -1) {
117
+ throw new Error("Invalid format: missing colon separator");
118
+ }
119
+ const clientKey = decoded.substring(0, colonIndex);
120
+ const secretKey = decoded.substring(colonIndex + 1);
121
+ if (!clientKey || !secretKey) {
122
+ throw new Error("Invalid format: empty clientKey or secretKey");
123
+ }
124
+ return { clientKey, secretKey };
125
+ } catch (e) {
126
+ throw new Error('Invalid API key. Expected Base64 encoded "clientKey:secretKey"');
127
+ }
128
+ }
129
+ //# sourceMappingURL=auth.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/auth.ts","../src/core/internal/utils/index.ts"],"sourcesContent":["export type { JwtPayload } from './core/internal/utils'\nexport {\n createServerToken,\n verifyServerToken,\n decodeServerToken,\n createApiKey,\n parseApiKey,\n} from './core/internal/utils'\n","import { SignJWT, jwtVerify, decodeJwt } from 'jose'\nimport { createNetworkError, createUsageLimitError, createTimeoutError, TimeoutError, NetworkError } from '../errors'\nimport type { DebugConfig, RetryConfig } from '../../client/types'\nimport { API_URLS } from '../../client/types'\n\nconst DEFAULT_TIMEOUT = 30000\nconst DEFAULT_RETRYABLE_STATUSES = [408, 429, 500, 502, 503, 504]\nconst NON_RETRYABLE_STATUSES = [401, 403, 404, 422]\n\nexport interface FetchOptions extends RequestInit {\n clientKey?: string\n secretKey?: string\n timeout?: number\n baseUrl?: string\n debug?: boolean | DebugConfig\n retry?: RetryConfig\n}\n\nexport interface JwtPayload {\n clientKey: string\n iat?: number\n exp?: number\n}\n\n/**\n * Creates a JWT token for server-side authentication.\n * The token is valid for 1 hour by default.\n *\n * @param clientKey - Client API key\n * @param secretKey - Secret key used for signing\n * @param expiresIn - Token expiration time (default: '1h')\n * @returns Promise<string> JWT token\n *\n * @example\n * ```typescript\n * const token = await createServerToken('client-key', 'secret-key')\n * // Use in Authorization header: `Bearer ${token}`\n * ```\n */\nexport async function createServerToken(\n clientKey: string,\n secretKey: string,\n expiresIn: string = '1h',\n): Promise<string> {\n if (!clientKey || !secretKey) {\n throw new Error('clientKey and secretKey are required.')\n }\n\n const secret = new TextEncoder().encode(secretKey)\n return new SignJWT({ clientKey })\n .setProtectedHeader({ alg: 'HS256' })\n .setIssuedAt()\n .setExpirationTime(expiresIn)\n .sign(secret)\n}\n\n/**\n * Verifies a JWT token and returns the payload.\n *\n * @param token - JWT token to verify\n * @param secretKey - Secret key used for verification\n * @returns Promise<JwtPayload> Verified payload containing clientKey\n * @throws Error if token is invalid or expired\n *\n * @example\n * ```typescript\n * const payload = await verifyServerToken(token, 'secret-key')\n * console.log(payload.clientKey)\n * ```\n */\nexport async function verifyServerToken(\n token: string,\n secretKey: string,\n): Promise<JwtPayload> {\n if (!token || !secretKey) {\n throw new Error('token and secretKey are required.')\n }\n\n const secret = new TextEncoder().encode(secretKey)\n const { payload } = await jwtVerify(token, secret, {\n algorithms: ['HS256'],\n })\n\n if (!payload.clientKey || typeof payload.clientKey !== 'string') {\n throw new Error('Invalid token payload: clientKey is missing')\n }\n\n return {\n clientKey: payload.clientKey as string,\n iat: payload.iat,\n exp: payload.exp,\n }\n}\n\n/**\n * Decodes a JWT token without verification.\n * WARNING: Use this only when you need to inspect token contents.\n * Always use verifyServerToken for authentication.\n *\n * @param token - JWT token to decode\n * @returns JwtPayload Decoded payload (unverified)\n *\n * @example\n * ```typescript\n * const payload = decodeServerToken(token)\n * console.log(payload.clientKey) // Unverified!\n * ```\n */\nexport function decodeServerToken(token: string): JwtPayload {\n if (!token) {\n throw new Error('token is required.')\n }\n\n const payload = decodeJwt(token)\n\n if (!payload.clientKey || typeof payload.clientKey !== 'string') {\n throw new Error('Invalid token payload: clientKey is missing')\n }\n\n return {\n clientKey: payload.clientKey as string,\n iat: payload.iat,\n exp: payload.exp,\n }\n}\n\n// ============================================================================\n// API Key Utilities\n// ============================================================================\n\n/**\n * Creates a Base64-encoded API key from clientKey and secretKey.\n * Use this for MCP server authentication.\n *\n * @param clientKey - Client API key\n * @param secretKey - Secret key\n * @returns Base64-encoded API key\n *\n * @example\n * ```typescript\n * const apiKey = createApiKey('client-key', 'secret-key')\n * // Use in x-api-key header\n * ```\n */\nexport function createApiKey(clientKey: string, secretKey: string): string {\n if (!clientKey || !secretKey) {\n throw new Error('clientKey and secretKey are required.')\n }\n\n // Browser와 Node.js 모두 지원\n if (typeof Buffer !== 'undefined') {\n return Buffer.from(`${clientKey}:${secretKey}`).toString('base64')\n }\n return btoa(`${clientKey}:${secretKey}`)\n}\n\n/**\n * Parses a Base64-encoded API key to extract clientKey and secretKey.\n *\n * @param apiKey - Base64-encoded API key\n * @returns Object containing clientKey and secretKey\n * @throws Error if API key is invalid\n *\n * @example\n * ```typescript\n * const { clientKey, secretKey } = parseApiKey(apiKey)\n * ```\n */\nexport function parseApiKey(apiKey: string): {\n clientKey: string\n secretKey: string\n} {\n if (!apiKey) {\n throw new Error('apiKey is required.')\n }\n\n try {\n let decoded: string\n if (typeof Buffer !== 'undefined') {\n decoded = Buffer.from(apiKey, 'base64').toString('utf-8')\n } else {\n decoded = atob(apiKey)\n }\n\n const colonIndex = decoded.indexOf(':')\n if (colonIndex === -1) {\n throw new Error('Invalid format: missing colon separator')\n }\n\n const clientKey = decoded.substring(0, colonIndex)\n const secretKey = decoded.substring(colonIndex + 1)\n\n if (!clientKey || !secretKey) {\n throw new Error('Invalid format: empty clientKey or secretKey')\n }\n\n return { clientKey, secretKey }\n } catch {\n throw new Error('Invalid API key. Expected Base64 encoded \"clientKey:secretKey\"')\n }\n}\n\nfunction debugLog(\n debug: boolean | DebugConfig | undefined,\n type: 'request' | 'response' | 'error',\n message: string,\n data?: unknown,\n) {\n if (!debug) return\n\n const shouldLog =\n debug === true ||\n (type === 'request' && (debug as DebugConfig).logRequests) ||\n (type === 'response' && (debug as DebugConfig).logResponses) ||\n (type === 'error' && (debug as DebugConfig).logErrors)\n\n if (shouldLog) {\n console.group(`[SDK ${type.toUpperCase()}] ${message}`)\n if (data) console.log(data)\n console.groupEnd()\n }\n}\n\nfunction getErrorSuggestion(status: number): string | undefined {\n if (status === 401) return 'Please check your authentication credentials.'\n if (status === 404) return 'The requested resource was not found.'\n if (status >= 500)\n return 'A server error occurred. Please try again later.'\n return undefined\n}\n\nasync function delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nexport async function _fetch(\n url: string,\n options?: FetchOptions,\n): Promise<Response> {\n const {\n clientKey,\n secretKey,\n timeout = DEFAULT_TIMEOUT,\n baseUrl = API_URLS.production,\n debug,\n retry,\n ...requestInit\n } = options || {}\n\n const retryConfig = {\n maxRetries: retry?.maxRetries ?? 3,\n retryableStatuses: retry?.retryableStatuses ?? DEFAULT_RETRYABLE_STATUSES,\n retryDelay:\n retry?.retryDelay ??\n ((attempt: number) => Math.min(1000 * 2 ** attempt, 10000)),\n }\n\n // Generate JWT once before retry loop (token valid for 1h)\n let authToken: string | undefined\n if (secretKey && clientKey) {\n authToken = await createServerToken(clientKey, secretKey)\n }\n\n let lastError: Error | undefined\n\n for (let attempt = 0; attempt <= retryConfig.maxRetries; attempt++) {\n try {\n const headers = new Headers(requestInit.headers)\n\n if (clientKey) {\n headers.set('X-Client-Key', clientKey)\n }\n\n if (authToken) {\n headers.set('Authorization', `Bearer ${authToken}`)\n }\n\n if (!headers.has('Content-Type') && requestInit.body) {\n headers.set('Content-Type', 'application/json')\n }\n\n debugLog(debug, 'request', url, {\n method: requestInit.method || 'GET',\n headers: Object.fromEntries(headers.entries()),\n attempt: attempt + 1,\n })\n\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), timeout)\n\n const response = await fetch(`${baseUrl}${url}`, {\n ...requestInit,\n headers,\n signal: controller.signal,\n })\n\n clearTimeout(timeoutId)\n\n debugLog(debug, 'response', url, {\n status: response.status,\n statusText: response.statusText,\n headers: Object.fromEntries(response.headers.entries()),\n })\n\n if (!response.ok) {\n // Usage limit 429 — never retry (distinguished by X-Usage-Limit header)\n if (\n response.status === 429 &&\n response.headers.get('X-Usage-Limit')\n ) {\n const limit = parseInt(response.headers.get('X-Usage-Limit') || '0', 10)\n const current = parseInt(response.headers.get('X-Usage-Current') || '0', 10)\n const remaining = parseInt(response.headers.get('X-Usage-Remaining') || '0', 10)\n\n throw createUsageLimitError(\n `Monthly API usage limit exceeded (${current.toLocaleString()}/${limit.toLocaleString()})`,\n { limit, current, remaining },\n { url, method: requestInit.method || 'GET', attempt: attempt + 1 },\n 'Monthly API call limit exceeded. Please upgrade your plan.',\n 'Upgrade your tenant plan to increase the monthly API call limit.',\n )\n }\n\n // Never retry non-retryable statuses regardless of user config\n if (NON_RETRYABLE_STATUSES.includes(response.status)) {\n throw createNetworkError(\n `HTTP ${response.status}: ${response.statusText}`,\n response.status,\n { url, method: requestInit.method || 'GET', attempt: attempt + 1 },\n `Request failed (status: ${response.status})`,\n getErrorSuggestion(response.status),\n )\n }\n\n const error = createNetworkError(\n `HTTP ${response.status}: ${response.statusText}`,\n response.status,\n { url, method: requestInit.method || 'GET', attempt: attempt + 1 },\n `Request failed (status: ${response.status})`,\n getErrorSuggestion(response.status),\n )\n\n if (\n attempt < retryConfig.maxRetries &&\n retryConfig.retryableStatuses.includes(response.status)\n ) {\n lastError = error\n const retryDelay = retryConfig.retryDelay(attempt)\n debugLog(debug, 'error', `Retrying in ${retryDelay}ms...`, error)\n await delay(retryDelay)\n continue\n }\n\n throw error\n }\n\n return response\n } catch (error) {\n debugLog(debug, 'error', url, error)\n\n if (error instanceof Error && error.name === 'AbortError') {\n const timeoutError = createTimeoutError(\n `Request timed out after ${timeout}ms.`,\n { url, timeout, attempt: attempt + 1 },\n 'The request timed out.',\n 'Please check your network connection or try again later.',\n )\n\n if (attempt < retryConfig.maxRetries) {\n lastError = timeoutError\n await delay(retryConfig.retryDelay(attempt))\n continue\n }\n\n throw timeoutError\n }\n\n if (error instanceof TypeError) {\n const networkError = createNetworkError(\n 'Network connection failed.',\n undefined,\n { url, originalError: error.message, attempt: attempt + 1 },\n 'Network connection failed.',\n 'Please check your internet connection and try again.',\n )\n\n if (attempt < retryConfig.maxRetries) {\n lastError = networkError\n await delay(retryConfig.retryDelay(attempt))\n continue\n }\n\n throw networkError\n }\n\n if (error instanceof NetworkError || error instanceof TimeoutError) {\n if (\n attempt < retryConfig.maxRetries &&\n error.status &&\n !NON_RETRYABLE_STATUSES.includes(error.status) &&\n retryConfig.retryableStatuses.includes(error.status)\n ) {\n lastError = error\n await delay(retryConfig.retryDelay(attempt))\n continue\n }\n\n throw error\n }\n\n const unknownError = createNetworkError(\n error instanceof Error\n ? error.message\n : 'An unknown network error occurred.',\n undefined,\n { url, originalError: error, attempt: attempt + 1 },\n 'An unknown error occurred.',\n 'Please try again later.',\n )\n\n if (attempt < retryConfig.maxRetries) {\n lastError = unknownError\n await delay(retryConfig.retryDelay(attempt))\n continue\n }\n\n throw unknownError\n }\n }\n\n throw lastError!\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,kBAA8C;AAuC9C,SAAsB,kBACpB,WACA,WACA,YAAoB,MACH;AAAA;AACjB,QAAI,CAAC,aAAa,CAAC,WAAW;AAC5B,YAAM,IAAI,MAAM,uCAAuC;AAAA,IACzD;AAEA,UAAM,SAAS,IAAI,YAAY,EAAE,OAAO,SAAS;AACjD,WAAO,IAAI,oBAAQ,EAAE,UAAU,CAAC,EAC7B,mBAAmB,EAAE,KAAK,QAAQ,CAAC,EACnC,YAAY,EACZ,kBAAkB,SAAS,EAC3B,KAAK,MAAM;AAAA,EAChB;AAAA;AAgBA,SAAsB,kBACpB,OACA,WACqB;AAAA;AACrB,QAAI,CAAC,SAAS,CAAC,WAAW;AACxB,YAAM,IAAI,MAAM,mCAAmC;AAAA,IACrD;AAEA,UAAM,SAAS,IAAI,YAAY,EAAE,OAAO,SAAS;AACjD,UAAM,EAAE,QAAQ,IAAI,UAAM,uBAAU,OAAO,QAAQ;AAAA,MACjD,YAAY,CAAC,OAAO;AAAA,IACtB,CAAC;AAED,QAAI,CAAC,QAAQ,aAAa,OAAO,QAAQ,cAAc,UAAU;AAC/D,YAAM,IAAI,MAAM,6CAA6C;AAAA,IAC/D;AAEA,WAAO;AAAA,MACL,WAAW,QAAQ;AAAA,MACnB,KAAK,QAAQ;AAAA,MACb,KAAK,QAAQ;AAAA,IACf;AAAA,EACF;AAAA;AAgBO,SAAS,kBAAkB,OAA2B;AAC3D,MAAI,CAAC,OAAO;AACV,UAAM,IAAI,MAAM,oBAAoB;AAAA,EACtC;AAEA,QAAM,cAAU,uBAAU,KAAK;AAE/B,MAAI,CAAC,QAAQ,aAAa,OAAO,QAAQ,cAAc,UAAU;AAC/D,UAAM,IAAI,MAAM,6CAA6C;AAAA,EAC/D;AAEA,SAAO;AAAA,IACL,WAAW,QAAQ;AAAA,IACnB,KAAK,QAAQ;AAAA,IACb,KAAK,QAAQ;AAAA,EACf;AACF;AAoBO,SAAS,aAAa,WAAmB,WAA2B;AACzE,MAAI,CAAC,aAAa,CAAC,WAAW;AAC5B,UAAM,IAAI,MAAM,uCAAuC;AAAA,EACzD;AAGA,MAAI,OAAO,WAAW,aAAa;AACjC,WAAO,OAAO,KAAK,GAAG,SAAS,IAAI,SAAS,EAAE,EAAE,SAAS,QAAQ;AAAA,EACnE;AACA,SAAO,KAAK,GAAG,SAAS,IAAI,SAAS,EAAE;AACzC;AAcO,SAAS,YAAY,QAG1B;AACA,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,qBAAqB;AAAA,EACvC;AAEA,MAAI;AACF,QAAI;AACJ,QAAI,OAAO,WAAW,aAAa;AACjC,gBAAU,OAAO,KAAK,QAAQ,QAAQ,EAAE,SAAS,OAAO;AAAA,IAC1D,OAAO;AACL,gBAAU,KAAK,MAAM;AAAA,IACvB;AAEA,UAAM,aAAa,QAAQ,QAAQ,GAAG;AACtC,QAAI,eAAe,IAAI;AACrB,YAAM,IAAI,MAAM,yCAAyC;AAAA,IAC3D;AAEA,UAAM,YAAY,QAAQ,UAAU,GAAG,UAAU;AACjD,UAAM,YAAY,QAAQ,UAAU,aAAa,CAAC;AAElD,QAAI,CAAC,aAAa,CAAC,WAAW;AAC5B,YAAM,IAAI,MAAM,8CAA8C;AAAA,IAChE;AAEA,WAAO,EAAE,WAAW,UAAU;AAAA,EAChC,SAAQ;AACN,UAAM,IAAI,MAAM,gEAAgE;AAAA,EAClF;AACF;","names":[]}
@@ -0,0 +1,3 @@
1
+ export { J as JwtPayload, q as createApiKey, o as createServerToken, p as decodeServerToken, r as parseApiKey, v as verifyServerToken } from './auth-BipHkgbu.cjs';
2
+ import 'payload';
3
+ import './payload-types-BE-5_Y2d.cjs';
package/dist/auth.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export { J as JwtPayload, q as createApiKey, o as createServerToken, p as decodeServerToken, r as parseApiKey, v as verifyServerToken } from './auth-Brdn6voY.js';
2
+ import 'payload';
3
+ import './payload-types-BE-5_Y2d.js';
package/dist/auth.js ADDED
@@ -0,0 +1,107 @@
1
+ var __async = (__this, __arguments, generator) => {
2
+ return new Promise((resolve, reject) => {
3
+ var fulfilled = (value) => {
4
+ try {
5
+ step(generator.next(value));
6
+ } catch (e) {
7
+ reject(e);
8
+ }
9
+ };
10
+ var rejected = (value) => {
11
+ try {
12
+ step(generator.throw(value));
13
+ } catch (e) {
14
+ reject(e);
15
+ }
16
+ };
17
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
18
+ step((generator = generator.apply(__this, __arguments)).next());
19
+ });
20
+ };
21
+
22
+ // src/core/internal/utils/index.ts
23
+ import { SignJWT, jwtVerify, decodeJwt } from "jose";
24
+ function createServerToken(clientKey, secretKey, expiresIn = "1h") {
25
+ return __async(this, null, function* () {
26
+ if (!clientKey || !secretKey) {
27
+ throw new Error("clientKey and secretKey are required.");
28
+ }
29
+ const secret = new TextEncoder().encode(secretKey);
30
+ return new SignJWT({ clientKey }).setProtectedHeader({ alg: "HS256" }).setIssuedAt().setExpirationTime(expiresIn).sign(secret);
31
+ });
32
+ }
33
+ function verifyServerToken(token, secretKey) {
34
+ return __async(this, null, function* () {
35
+ if (!token || !secretKey) {
36
+ throw new Error("token and secretKey are required.");
37
+ }
38
+ const secret = new TextEncoder().encode(secretKey);
39
+ const { payload } = yield jwtVerify(token, secret, {
40
+ algorithms: ["HS256"]
41
+ });
42
+ if (!payload.clientKey || typeof payload.clientKey !== "string") {
43
+ throw new Error("Invalid token payload: clientKey is missing");
44
+ }
45
+ return {
46
+ clientKey: payload.clientKey,
47
+ iat: payload.iat,
48
+ exp: payload.exp
49
+ };
50
+ });
51
+ }
52
+ function decodeServerToken(token) {
53
+ if (!token) {
54
+ throw new Error("token is required.");
55
+ }
56
+ const payload = decodeJwt(token);
57
+ if (!payload.clientKey || typeof payload.clientKey !== "string") {
58
+ throw new Error("Invalid token payload: clientKey is missing");
59
+ }
60
+ return {
61
+ clientKey: payload.clientKey,
62
+ iat: payload.iat,
63
+ exp: payload.exp
64
+ };
65
+ }
66
+ function createApiKey(clientKey, secretKey) {
67
+ if (!clientKey || !secretKey) {
68
+ throw new Error("clientKey and secretKey are required.");
69
+ }
70
+ if (typeof Buffer !== "undefined") {
71
+ return Buffer.from(`${clientKey}:${secretKey}`).toString("base64");
72
+ }
73
+ return btoa(`${clientKey}:${secretKey}`);
74
+ }
75
+ function parseApiKey(apiKey) {
76
+ if (!apiKey) {
77
+ throw new Error("apiKey is required.");
78
+ }
79
+ try {
80
+ let decoded;
81
+ if (typeof Buffer !== "undefined") {
82
+ decoded = Buffer.from(apiKey, "base64").toString("utf-8");
83
+ } else {
84
+ decoded = atob(apiKey);
85
+ }
86
+ const colonIndex = decoded.indexOf(":");
87
+ if (colonIndex === -1) {
88
+ throw new Error("Invalid format: missing colon separator");
89
+ }
90
+ const clientKey = decoded.substring(0, colonIndex);
91
+ const secretKey = decoded.substring(colonIndex + 1);
92
+ if (!clientKey || !secretKey) {
93
+ throw new Error("Invalid format: empty clientKey or secretKey");
94
+ }
95
+ return { clientKey, secretKey };
96
+ } catch (e) {
97
+ throw new Error('Invalid API key. Expected Base64 encoded "clientKey:secretKey"');
98
+ }
99
+ }
100
+ export {
101
+ createApiKey,
102
+ createServerToken,
103
+ decodeServerToken,
104
+ parseApiKey,
105
+ verifyServerToken
106
+ };
107
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/internal/utils/index.ts"],"sourcesContent":["import { SignJWT, jwtVerify, decodeJwt } from 'jose'\nimport { createNetworkError, createUsageLimitError, createTimeoutError, TimeoutError, NetworkError } from '../errors'\nimport type { DebugConfig, RetryConfig } from '../../client/types'\nimport { API_URLS } from '../../client/types'\n\nconst DEFAULT_TIMEOUT = 30000\nconst DEFAULT_RETRYABLE_STATUSES = [408, 429, 500, 502, 503, 504]\nconst NON_RETRYABLE_STATUSES = [401, 403, 404, 422]\n\nexport interface FetchOptions extends RequestInit {\n clientKey?: string\n secretKey?: string\n timeout?: number\n baseUrl?: string\n debug?: boolean | DebugConfig\n retry?: RetryConfig\n}\n\nexport interface JwtPayload {\n clientKey: string\n iat?: number\n exp?: number\n}\n\n/**\n * Creates a JWT token for server-side authentication.\n * The token is valid for 1 hour by default.\n *\n * @param clientKey - Client API key\n * @param secretKey - Secret key used for signing\n * @param expiresIn - Token expiration time (default: '1h')\n * @returns Promise<string> JWT token\n *\n * @example\n * ```typescript\n * const token = await createServerToken('client-key', 'secret-key')\n * // Use in Authorization header: `Bearer ${token}`\n * ```\n */\nexport async function createServerToken(\n clientKey: string,\n secretKey: string,\n expiresIn: string = '1h',\n): Promise<string> {\n if (!clientKey || !secretKey) {\n throw new Error('clientKey and secretKey are required.')\n }\n\n const secret = new TextEncoder().encode(secretKey)\n return new SignJWT({ clientKey })\n .setProtectedHeader({ alg: 'HS256' })\n .setIssuedAt()\n .setExpirationTime(expiresIn)\n .sign(secret)\n}\n\n/**\n * Verifies a JWT token and returns the payload.\n *\n * @param token - JWT token to verify\n * @param secretKey - Secret key used for verification\n * @returns Promise<JwtPayload> Verified payload containing clientKey\n * @throws Error if token is invalid or expired\n *\n * @example\n * ```typescript\n * const payload = await verifyServerToken(token, 'secret-key')\n * console.log(payload.clientKey)\n * ```\n */\nexport async function verifyServerToken(\n token: string,\n secretKey: string,\n): Promise<JwtPayload> {\n if (!token || !secretKey) {\n throw new Error('token and secretKey are required.')\n }\n\n const secret = new TextEncoder().encode(secretKey)\n const { payload } = await jwtVerify(token, secret, {\n algorithms: ['HS256'],\n })\n\n if (!payload.clientKey || typeof payload.clientKey !== 'string') {\n throw new Error('Invalid token payload: clientKey is missing')\n }\n\n return {\n clientKey: payload.clientKey as string,\n iat: payload.iat,\n exp: payload.exp,\n }\n}\n\n/**\n * Decodes a JWT token without verification.\n * WARNING: Use this only when you need to inspect token contents.\n * Always use verifyServerToken for authentication.\n *\n * @param token - JWT token to decode\n * @returns JwtPayload Decoded payload (unverified)\n *\n * @example\n * ```typescript\n * const payload = decodeServerToken(token)\n * console.log(payload.clientKey) // Unverified!\n * ```\n */\nexport function decodeServerToken(token: string): JwtPayload {\n if (!token) {\n throw new Error('token is required.')\n }\n\n const payload = decodeJwt(token)\n\n if (!payload.clientKey || typeof payload.clientKey !== 'string') {\n throw new Error('Invalid token payload: clientKey is missing')\n }\n\n return {\n clientKey: payload.clientKey as string,\n iat: payload.iat,\n exp: payload.exp,\n }\n}\n\n// ============================================================================\n// API Key Utilities\n// ============================================================================\n\n/**\n * Creates a Base64-encoded API key from clientKey and secretKey.\n * Use this for MCP server authentication.\n *\n * @param clientKey - Client API key\n * @param secretKey - Secret key\n * @returns Base64-encoded API key\n *\n * @example\n * ```typescript\n * const apiKey = createApiKey('client-key', 'secret-key')\n * // Use in x-api-key header\n * ```\n */\nexport function createApiKey(clientKey: string, secretKey: string): string {\n if (!clientKey || !secretKey) {\n throw new Error('clientKey and secretKey are required.')\n }\n\n // Browser와 Node.js 모두 지원\n if (typeof Buffer !== 'undefined') {\n return Buffer.from(`${clientKey}:${secretKey}`).toString('base64')\n }\n return btoa(`${clientKey}:${secretKey}`)\n}\n\n/**\n * Parses a Base64-encoded API key to extract clientKey and secretKey.\n *\n * @param apiKey - Base64-encoded API key\n * @returns Object containing clientKey and secretKey\n * @throws Error if API key is invalid\n *\n * @example\n * ```typescript\n * const { clientKey, secretKey } = parseApiKey(apiKey)\n * ```\n */\nexport function parseApiKey(apiKey: string): {\n clientKey: string\n secretKey: string\n} {\n if (!apiKey) {\n throw new Error('apiKey is required.')\n }\n\n try {\n let decoded: string\n if (typeof Buffer !== 'undefined') {\n decoded = Buffer.from(apiKey, 'base64').toString('utf-8')\n } else {\n decoded = atob(apiKey)\n }\n\n const colonIndex = decoded.indexOf(':')\n if (colonIndex === -1) {\n throw new Error('Invalid format: missing colon separator')\n }\n\n const clientKey = decoded.substring(0, colonIndex)\n const secretKey = decoded.substring(colonIndex + 1)\n\n if (!clientKey || !secretKey) {\n throw new Error('Invalid format: empty clientKey or secretKey')\n }\n\n return { clientKey, secretKey }\n } catch {\n throw new Error('Invalid API key. Expected Base64 encoded \"clientKey:secretKey\"')\n }\n}\n\nfunction debugLog(\n debug: boolean | DebugConfig | undefined,\n type: 'request' | 'response' | 'error',\n message: string,\n data?: unknown,\n) {\n if (!debug) return\n\n const shouldLog =\n debug === true ||\n (type === 'request' && (debug as DebugConfig).logRequests) ||\n (type === 'response' && (debug as DebugConfig).logResponses) ||\n (type === 'error' && (debug as DebugConfig).logErrors)\n\n if (shouldLog) {\n console.group(`[SDK ${type.toUpperCase()}] ${message}`)\n if (data) console.log(data)\n console.groupEnd()\n }\n}\n\nfunction getErrorSuggestion(status: number): string | undefined {\n if (status === 401) return 'Please check your authentication credentials.'\n if (status === 404) return 'The requested resource was not found.'\n if (status >= 500)\n return 'A server error occurred. Please try again later.'\n return undefined\n}\n\nasync function delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nexport async function _fetch(\n url: string,\n options?: FetchOptions,\n): Promise<Response> {\n const {\n clientKey,\n secretKey,\n timeout = DEFAULT_TIMEOUT,\n baseUrl = API_URLS.production,\n debug,\n retry,\n ...requestInit\n } = options || {}\n\n const retryConfig = {\n maxRetries: retry?.maxRetries ?? 3,\n retryableStatuses: retry?.retryableStatuses ?? DEFAULT_RETRYABLE_STATUSES,\n retryDelay:\n retry?.retryDelay ??\n ((attempt: number) => Math.min(1000 * 2 ** attempt, 10000)),\n }\n\n // Generate JWT once before retry loop (token valid for 1h)\n let authToken: string | undefined\n if (secretKey && clientKey) {\n authToken = await createServerToken(clientKey, secretKey)\n }\n\n let lastError: Error | undefined\n\n for (let attempt = 0; attempt <= retryConfig.maxRetries; attempt++) {\n try {\n const headers = new Headers(requestInit.headers)\n\n if (clientKey) {\n headers.set('X-Client-Key', clientKey)\n }\n\n if (authToken) {\n headers.set('Authorization', `Bearer ${authToken}`)\n }\n\n if (!headers.has('Content-Type') && requestInit.body) {\n headers.set('Content-Type', 'application/json')\n }\n\n debugLog(debug, 'request', url, {\n method: requestInit.method || 'GET',\n headers: Object.fromEntries(headers.entries()),\n attempt: attempt + 1,\n })\n\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), timeout)\n\n const response = await fetch(`${baseUrl}${url}`, {\n ...requestInit,\n headers,\n signal: controller.signal,\n })\n\n clearTimeout(timeoutId)\n\n debugLog(debug, 'response', url, {\n status: response.status,\n statusText: response.statusText,\n headers: Object.fromEntries(response.headers.entries()),\n })\n\n if (!response.ok) {\n // Usage limit 429 — never retry (distinguished by X-Usage-Limit header)\n if (\n response.status === 429 &&\n response.headers.get('X-Usage-Limit')\n ) {\n const limit = parseInt(response.headers.get('X-Usage-Limit') || '0', 10)\n const current = parseInt(response.headers.get('X-Usage-Current') || '0', 10)\n const remaining = parseInt(response.headers.get('X-Usage-Remaining') || '0', 10)\n\n throw createUsageLimitError(\n `Monthly API usage limit exceeded (${current.toLocaleString()}/${limit.toLocaleString()})`,\n { limit, current, remaining },\n { url, method: requestInit.method || 'GET', attempt: attempt + 1 },\n 'Monthly API call limit exceeded. Please upgrade your plan.',\n 'Upgrade your tenant plan to increase the monthly API call limit.',\n )\n }\n\n // Never retry non-retryable statuses regardless of user config\n if (NON_RETRYABLE_STATUSES.includes(response.status)) {\n throw createNetworkError(\n `HTTP ${response.status}: ${response.statusText}`,\n response.status,\n { url, method: requestInit.method || 'GET', attempt: attempt + 1 },\n `Request failed (status: ${response.status})`,\n getErrorSuggestion(response.status),\n )\n }\n\n const error = createNetworkError(\n `HTTP ${response.status}: ${response.statusText}`,\n response.status,\n { url, method: requestInit.method || 'GET', attempt: attempt + 1 },\n `Request failed (status: ${response.status})`,\n getErrorSuggestion(response.status),\n )\n\n if (\n attempt < retryConfig.maxRetries &&\n retryConfig.retryableStatuses.includes(response.status)\n ) {\n lastError = error\n const retryDelay = retryConfig.retryDelay(attempt)\n debugLog(debug, 'error', `Retrying in ${retryDelay}ms...`, error)\n await delay(retryDelay)\n continue\n }\n\n throw error\n }\n\n return response\n } catch (error) {\n debugLog(debug, 'error', url, error)\n\n if (error instanceof Error && error.name === 'AbortError') {\n const timeoutError = createTimeoutError(\n `Request timed out after ${timeout}ms.`,\n { url, timeout, attempt: attempt + 1 },\n 'The request timed out.',\n 'Please check your network connection or try again later.',\n )\n\n if (attempt < retryConfig.maxRetries) {\n lastError = timeoutError\n await delay(retryConfig.retryDelay(attempt))\n continue\n }\n\n throw timeoutError\n }\n\n if (error instanceof TypeError) {\n const networkError = createNetworkError(\n 'Network connection failed.',\n undefined,\n { url, originalError: error.message, attempt: attempt + 1 },\n 'Network connection failed.',\n 'Please check your internet connection and try again.',\n )\n\n if (attempt < retryConfig.maxRetries) {\n lastError = networkError\n await delay(retryConfig.retryDelay(attempt))\n continue\n }\n\n throw networkError\n }\n\n if (error instanceof NetworkError || error instanceof TimeoutError) {\n if (\n attempt < retryConfig.maxRetries &&\n error.status &&\n !NON_RETRYABLE_STATUSES.includes(error.status) &&\n retryConfig.retryableStatuses.includes(error.status)\n ) {\n lastError = error\n await delay(retryConfig.retryDelay(attempt))\n continue\n }\n\n throw error\n }\n\n const unknownError = createNetworkError(\n error instanceof Error\n ? error.message\n : 'An unknown network error occurred.',\n undefined,\n { url, originalError: error, attempt: attempt + 1 },\n 'An unknown error occurred.',\n 'Please try again later.',\n )\n\n if (attempt < retryConfig.maxRetries) {\n lastError = unknownError\n await delay(retryConfig.retryDelay(attempt))\n continue\n }\n\n throw unknownError\n }\n }\n\n throw lastError!\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,SAAS,WAAW,iBAAiB;AAuC9C,SAAsB,kBACpB,WACA,WACA,YAAoB,MACH;AAAA;AACjB,QAAI,CAAC,aAAa,CAAC,WAAW;AAC5B,YAAM,IAAI,MAAM,uCAAuC;AAAA,IACzD;AAEA,UAAM,SAAS,IAAI,YAAY,EAAE,OAAO,SAAS;AACjD,WAAO,IAAI,QAAQ,EAAE,UAAU,CAAC,EAC7B,mBAAmB,EAAE,KAAK,QAAQ,CAAC,EACnC,YAAY,EACZ,kBAAkB,SAAS,EAC3B,KAAK,MAAM;AAAA,EAChB;AAAA;AAgBA,SAAsB,kBACpB,OACA,WACqB;AAAA;AACrB,QAAI,CAAC,SAAS,CAAC,WAAW;AACxB,YAAM,IAAI,MAAM,mCAAmC;AAAA,IACrD;AAEA,UAAM,SAAS,IAAI,YAAY,EAAE,OAAO,SAAS;AACjD,UAAM,EAAE,QAAQ,IAAI,MAAM,UAAU,OAAO,QAAQ;AAAA,MACjD,YAAY,CAAC,OAAO;AAAA,IACtB,CAAC;AAED,QAAI,CAAC,QAAQ,aAAa,OAAO,QAAQ,cAAc,UAAU;AAC/D,YAAM,IAAI,MAAM,6CAA6C;AAAA,IAC/D;AAEA,WAAO;AAAA,MACL,WAAW,QAAQ;AAAA,MACnB,KAAK,QAAQ;AAAA,MACb,KAAK,QAAQ;AAAA,IACf;AAAA,EACF;AAAA;AAgBO,SAAS,kBAAkB,OAA2B;AAC3D,MAAI,CAAC,OAAO;AACV,UAAM,IAAI,MAAM,oBAAoB;AAAA,EACtC;AAEA,QAAM,UAAU,UAAU,KAAK;AAE/B,MAAI,CAAC,QAAQ,aAAa,OAAO,QAAQ,cAAc,UAAU;AAC/D,UAAM,IAAI,MAAM,6CAA6C;AAAA,EAC/D;AAEA,SAAO;AAAA,IACL,WAAW,QAAQ;AAAA,IACnB,KAAK,QAAQ;AAAA,IACb,KAAK,QAAQ;AAAA,EACf;AACF;AAoBO,SAAS,aAAa,WAAmB,WAA2B;AACzE,MAAI,CAAC,aAAa,CAAC,WAAW;AAC5B,UAAM,IAAI,MAAM,uCAAuC;AAAA,EACzD;AAGA,MAAI,OAAO,WAAW,aAAa;AACjC,WAAO,OAAO,KAAK,GAAG,SAAS,IAAI,SAAS,EAAE,EAAE,SAAS,QAAQ;AAAA,EACnE;AACA,SAAO,KAAK,GAAG,SAAS,IAAI,SAAS,EAAE;AACzC;AAcO,SAAS,YAAY,QAG1B;AACA,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,qBAAqB;AAAA,EACvC;AAEA,MAAI;AACF,QAAI;AACJ,QAAI,OAAO,WAAW,aAAa;AACjC,gBAAU,OAAO,KAAK,QAAQ,QAAQ,EAAE,SAAS,OAAO;AAAA,IAC1D,OAAO;AACL,gBAAU,KAAK,MAAM;AAAA,IACvB;AAEA,UAAM,aAAa,QAAQ,QAAQ,GAAG;AACtC,QAAI,eAAe,IAAI;AACrB,YAAM,IAAI,MAAM,yCAAyC;AAAA,IAC3D;AAEA,UAAM,YAAY,QAAQ,UAAU,GAAG,UAAU;AACjD,UAAM,YAAY,QAAQ,UAAU,aAAa,CAAC;AAElD,QAAI,CAAC,aAAa,CAAC,WAAW;AAC5B,YAAM,IAAI,MAAM,8CAA8C;AAAA,IAChE;AAEA,WAAO,EAAE,WAAW,UAAU;AAAA,EAChC,SAAQ;AACN,UAAM,IAAI,MAAM,gEAAgE;AAAA,EAClF;AACF;","names":[]}
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __defProps = Object.defineProperties;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
7
+ var __getOwnPropNames = Object.getOwnPropertyNames;
8
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
9
+ var __getProtoOf = Object.getPrototypeOf;
10
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
11
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
12
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
13
+ var __spreadValues = (a, b) => {
14
+ for (var prop in b || (b = {}))
15
+ if (__hasOwnProp.call(b, prop))
16
+ __defNormalProp(a, prop, b[prop]);
17
+ if (__getOwnPropSymbols)
18
+ for (var prop of __getOwnPropSymbols(b)) {
19
+ if (__propIsEnum.call(b, prop))
20
+ __defNormalProp(a, prop, b[prop]);
21
+ }
22
+ return a;
23
+ };
24
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
25
+ var __export = (target, all) => {
26
+ for (var name in all)
27
+ __defProp(target, name, { get: all[name], enumerable: true });
28
+ };
29
+ var __copyProps = (to, from, except, desc) => {
30
+ if (from && typeof from === "object" || typeof from === "function") {
31
+ for (let key of __getOwnPropNames(from))
32
+ if (!__hasOwnProp.call(to, key) && key !== except)
33
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
34
+ }
35
+ return to;
36
+ };
37
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
38
+ // If the importer is in node compatibility mode or this is not an ESM
39
+ // file that has been converted to a CommonJS file using a Babel-
40
+ // compatible transform (i.e. "__esModule" has not been set), then set
41
+ // "default" to the CommonJS "module.exports" for node compatibility.
42
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
43
+ mod
44
+ ));
45
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
46
+
47
+ // src/components/index.ts
48
+ var components_exports = {};
49
+ __export(components_exports, {
50
+ RichTextContent: () => RichTextContent
51
+ });
52
+ module.exports = __toCommonJS(components_exports);
53
+
54
+ // src/components/RichTextContent/index.tsx
55
+ var import_react = __toESM(require("react"), 1);
56
+ var import_react2 = require("@payloadcms/richtext-lexical/react");
57
+ function RichTextContent({
58
+ data,
59
+ className,
60
+ internalDocToHref,
61
+ blocks
62
+ }) {
63
+ return /* @__PURE__ */ import_react.default.createElement(
64
+ import_react2.RichText,
65
+ {
66
+ data,
67
+ className,
68
+ converters: __spreadProps(__spreadValues(__spreadValues({}, import_react2.defaultJSXConverters), (0, import_react2.LinkJSXConverter)({
69
+ internalDocToHref
70
+ })), {
71
+ blocks: blocks ? blocks : void 0
72
+ })
73
+ }
74
+ );
75
+ }
76
+ //# sourceMappingURL=components.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/index.ts","../src/components/RichTextContent/index.tsx"],"sourcesContent":["export * from './RichTextContent'\n","'use client'\n\nimport React from 'react'\nimport {\n SerializedBlockNode,\n SerializedLinkNode,\n} from '@payloadcms/richtext-lexical'\nimport {\n SerializedEditorState,\n SerializedLexicalNode,\n} from '@payloadcms/richtext-lexical/lexical'\nimport {\n defaultJSXConverters,\n JSXConverter,\n LinkJSXConverter,\n RichText,\n} from '@payloadcms/richtext-lexical/react'\n\nexport type RichTextData = SerializedEditorState<SerializedLexicalNode>\n\nexport interface RichTextContentProps {\n data: RichTextData\n className?: string\n internalDocToHref?: (args: { linkNode: SerializedLinkNode }) => string\n blocks?: {\n Iframe?: JSXConverter<\n SerializedBlockNode<{\n blockName?: string | null\n blockType: string\n url: string\n }>\n >\n Player?: JSXConverter<\n SerializedBlockNode<{\n blockName?: string | null\n blockType: string\n url: string\n }>\n >\n }\n}\n\nexport function RichTextContent({\n data,\n className,\n internalDocToHref,\n blocks,\n}: RichTextContentProps) {\n return (\n <RichText\n data={data}\n className={className}\n converters={{\n ...defaultJSXConverters,\n ...LinkJSXConverter({\n internalDocToHref,\n }),\n blocks: blocks\n ? (blocks as Record<\n string,\n JSXConverter<\n SerializedBlockNode<{\n blockName?: string | null\n blockType: string\n }>\n >\n >)\n : undefined,\n }}\n />\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEA,mBAAkB;AASlB,IAAAA,gBAKO;AA0BA,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAyB;AACvB,SACE,6BAAAC,QAAA;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,YAAY,gDACP,yCACA,gCAAiB;AAAA,QAClB;AAAA,MACF,CAAC,IAJS;AAAA,QAKV,QAAQ,SACH,SASD;AAAA,MACN;AAAA;AAAA,EACF;AAEJ;","names":["import_react","React"]}