@01.software/sdk 0.2.9-dev.260311.bb95a4e → 0.2.9-dev.260312.8c43a16

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
@@ -29,10 +29,17 @@ pnpm add @01.software/sdk
29
29
  import { createBrowserClient, createServerClient } from '@01.software/sdk'
30
30
 
31
31
  // Auth only - JWT & API Key utilities (smaller bundle)
32
- import { createServerToken, verifyServerToken, createApiKey } from '@01.software/sdk/auth'
32
+ import {
33
+ createServerToken,
34
+ verifyServerToken,
35
+ createApiKey,
36
+ } from '@01.software/sdk/auth'
33
37
 
34
38
  // Webhook only - webhook handlers
35
- import { handleWebhook, createTypedWebhookHandler } from '@01.software/sdk/webhook'
39
+ import {
40
+ handleWebhook,
41
+ createTypedWebhookHandler,
42
+ } from '@01.software/sdk/webhook'
36
43
 
37
44
  // Components - sub-path imports per domain
38
45
  import { RichTextContent } from '@01.software/sdk/ui/rich-text'
@@ -40,7 +47,6 @@ import { Image } from '@01.software/sdk/ui/image'
40
47
  import { FormRenderer } from '@01.software/sdk/ui/form'
41
48
  import { CodeBlock } from '@01.software/sdk/ui/code-block'
42
49
  import { FlowRenderer } from '@01.software/sdk/ui/flow'
43
-
44
50
  ```
45
51
 
46
52
  ## Getting Started
@@ -94,7 +100,7 @@ await client.query.prefetchQuery({
94
100
 
95
101
  ```typescript
96
102
  const client = createBrowserClient({
97
- clientKey: string, // Required
103
+ clientKey: string, // Required
98
104
  })
99
105
  ```
100
106
 
@@ -104,6 +110,7 @@ const client = createBrowserClient({
104
110
  | `secretKey` | `string` | API secret key (server only) |
105
111
 
106
112
  API URL은 환경변수로 오버라이드 가능합니다:
113
+
107
114
  - `SOFTWARE_API_URL` (서버용) 또는 `NEXT_PUBLIC_SOFTWARE_API_URL` (브라우저용)
108
115
  - 미설정 시: dev 빌드(`@dev` 태그)는 `api-dev.01.software`, 정식 릴리즈는 `api.01.software`
109
116
 
@@ -128,19 +135,20 @@ const { docs, totalDocs, hasNextPage } = await client.from('products').find({
128
135
  const product = await client.from('products').findById('id')
129
136
 
130
137
  // Create (server only) - returns PayloadMutationResponse
131
- const { doc, message } = await client.from('products').create({ name: 'Product' })
138
+ const { doc, message } = await client
139
+ .from('products')
140
+ .create({ name: 'Product' })
132
141
 
133
142
  // Create with file upload (server only) - uses multipart/form-data
134
- const { doc } = await client.from('product-images').create(
135
- { product: 'product_id', alt: 'Hero image' },
136
- { file: imageFile, filename: 'hero.jpg' },
137
- )
143
+ const { doc } = await client
144
+ .from('images')
145
+ .create({ alt: 'Hero image' }, { file: imageFile, filename: 'hero.jpg' })
138
146
 
139
147
  // Update (server only) - returns PayloadMutationResponse
140
148
  const { doc } = await client.from('products').update('id', { name: 'Updated' })
141
149
 
142
150
  // Update with file replacement (server only)
143
- await client.from('media').update('id', { alt: 'New alt' }, { file: newFile })
151
+ await client.from('images').update('id', { alt: 'New alt' }, { file: newFile })
144
152
 
145
153
  // Delete (server only) - returns document directly
146
154
  const deletedDoc = await client.from('products').remove('id')
@@ -149,10 +157,12 @@ const deletedDoc = await client.from('products').remove('id')
149
157
  const { totalDocs } = await client.from('products').count()
150
158
 
151
159
  // SEO Metadata (fetch + generate in one call, depth: 1 auto-applied)
152
- const metadata = await client.from('products').findMetadata(
153
- { where: { slug: { equals: 'my-product' } } },
154
- { siteName: 'My Store' },
155
- )
160
+ const metadata = await client
161
+ .from('products')
162
+ .findMetadata(
163
+ { where: { slug: { equals: 'my-product' } } },
164
+ { siteName: 'My Store' },
165
+ )
156
166
 
157
167
  const metadataById = await client.from('products').findMetadataById('id', {
158
168
  siteName: 'My Store',
@@ -192,16 +202,16 @@ interface PayloadMutationResponse<T> {
192
202
  // findById() / remove() returns T (document directly)
193
203
  ```
194
204
 
195
- | Operation | Response Type |
196
- |-----------|--------------|
197
- | `find()` | `PayloadFindResponse<T>` - `{ docs, totalDocs, hasNextPage, ... }` |
198
- | `findById()` | `T` - document object directly |
199
- | `create()` | `PayloadMutationResponse<T>` - `{ doc, message }` |
200
- | `update()` | `PayloadMutationResponse<T>` - `{ doc, message }` |
201
- | `remove()` | `T` - deleted document object directly |
202
- | `count()` | `{ totalDocs: number }` |
203
- | `findMetadata()` | `Metadata \| null` - Next.js Metadata (null if no match) |
204
- | `findMetadataById()` | `Metadata` - Next.js Metadata (throws on 404) |
205
+ | Operation | Response Type |
206
+ | -------------------- | ------------------------------------------------------------------ |
207
+ | `find()` | `PayloadFindResponse<T>` - `{ docs, totalDocs, hasNextPage, ... }` |
208
+ | `findById()` | `T` - document object directly |
209
+ | `create()` | `PayloadMutationResponse<T>` - `{ doc, message }` |
210
+ | `update()` | `PayloadMutationResponse<T>` - `{ doc, message }` |
211
+ | `remove()` | `T` - deleted document object directly |
212
+ | `count()` | `{ totalDocs: number }` |
213
+ | `findMetadata()` | `Metadata \| null` - Next.js Metadata (null if no match) |
214
+ | `findMetadataById()` | `Metadata` - Next.js Metadata (throws on 404) |
205
215
 
206
216
  ### React Query Hooks
207
217
 
@@ -233,7 +243,7 @@ const { data, fetchNextPage, hasNextPage } = client.query.useInfiniteQuery({
233
243
  })
234
244
 
235
245
  // Mutation hooks — ServerClient only (auto-invalidate cache on success)
236
- const { mutate: create } = client.query.useCreate({ collection: 'product-images' })
246
+ const { mutate: create } = client.query.useCreate({ collection: 'images' })
237
247
  const { mutate: update } = client.query.useUpdate({ collection: 'products' })
238
248
  const { mutate: remove } = client.query.useRemove({ collection: 'products' })
239
249
 
@@ -242,9 +252,18 @@ update({ id: 'product_id', data: { title: 'Updated' } })
242
252
  remove('product_id')
243
253
 
244
254
  // SSR Prefetch
245
- await client.query.prefetchQuery({ collection: 'products', options: { limit: 10 } })
246
- await client.query.prefetchQueryById({ collection: 'products', id: 'product_id' })
247
- await client.query.prefetchInfiniteQuery({ collection: 'products', pageSize: 20 })
255
+ await client.query.prefetchQuery({
256
+ collection: 'products',
257
+ options: { limit: 10 },
258
+ })
259
+ await client.query.prefetchQueryById({
260
+ collection: 'products',
261
+ id: 'product_id',
262
+ })
263
+ await client.query.prefetchInfiniteQuery({
264
+ collection: 'products',
265
+ pageSize: 20,
266
+ })
248
267
 
249
268
  // Cache utilities
250
269
  client.query.invalidateQueries('products')
@@ -282,8 +301,15 @@ const client = createBrowserClient({
282
301
  })
283
302
 
284
303
  // Register & login
285
- const { customer } = await client.customer.register({ name: 'John', email: 'john@example.com', password: 'secure123' })
286
- const { token, customer } = await client.customer.login({ email: 'john@example.com', password: 'secure123' })
304
+ const { customer } = await client.customer.register({
305
+ name: 'John',
306
+ email: 'john@example.com',
307
+ password: 'secure123',
308
+ })
309
+ const { token, customer } = await client.customer.login({
310
+ email: 'john@example.com',
311
+ password: 'secure123',
312
+ })
287
313
 
288
314
  // Profile & token management
289
315
  const profile = await client.customer.me()
@@ -291,7 +317,11 @@ client.customer.isAuthenticated()
291
317
  client.customer.logout()
292
318
 
293
319
  // Orders
294
- const orders = await client.customer.getMyOrders({ page: 1, limit: 10, status: 'paid' })
320
+ const orders = await client.customer.getMyOrders({
321
+ page: 1,
322
+ limit: 10,
323
+ status: 'paid',
324
+ })
295
325
 
296
326
  // Password & email
297
327
  await client.customer.forgotPassword('john@example.com')
@@ -328,7 +358,10 @@ Available only in ServerClient via `client.product.*`.
328
358
  ```typescript
329
359
  // Batch stock check
330
360
  const { results, allAvailable } = await client.product.stockCheck({
331
- items: [{ optionId: 1, quantity: 2 }, { optionId: 3, quantity: 1 }],
361
+ items: [
362
+ { optionId: 1, quantity: 2 },
363
+ { optionId: 3, quantity: 1 },
364
+ ],
332
365
  })
333
366
  ```
334
367
 
@@ -375,22 +408,22 @@ const handler = createTypedWebhookHandler('orders', async (event) => {
375
408
 
376
409
  ## Supported Collections
377
410
 
378
- | Category | Collections |
379
- | -------- | ---------------------------------------------------------------------------------------------------------------------------------- |
380
- | Tenant | `tenants`, `tenant-metadata`, `tenant-logos`, `tenant-og-images` |
381
- | Products | `products`, `product-variants`, `product-options`, `product-categories`, `product-tags`, `product-images`, `product-collections`, `brands`, `brand-logos` |
382
- | Orders | `orders`, `order-products`, `returns`, `return-products`, `exchanges`, `exchange-products`, `fulfillments`, `fulfillment-items`, `transactions` |
383
- | Customers | `customers`, `customer-addresses`, `customer-groups`, `customer-group-images` |
384
- | Carts | `carts`, `cart-items` |
385
- | Commerce | `discounts`, `shipping-policies` |
386
- | Content | `posts`, `post-categories`, `post-tags`, `post-images`, `documents`, `document-categories`, `document-types`, `document-images` |
387
- | Playlists | `playlists`, `playlist-images`, `playlist-categories`, `playlist-tags`, `musics` |
388
- | Galleries | `galleries`, `gallery-images`, `gallery-categories`, `gallery-tags` |
389
- | Flows | `flows`, `flow-images`, `flow-node-types`, `flow-edge-types`, `flow-categories`, `flow-tags` |
390
- | Videos | `videos`, `video-images`, `video-categories`, `video-tags` |
391
- | Live Streams | `live-streams`, `live-stream-images` |
392
- | Forms | `forms`, `form-submissions` |
393
- | Media | `media` |
411
+ | Category | Collections |
412
+ | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- |
413
+ | Tenant | `tenants`, `tenant-metadata`, `tenant-logos` |
414
+ | Images | `images` (unified), `brand-logos` |
415
+ | Products | `products`, `product-variants`, `product-options`, `product-categories`, `product-tags`, `product-collections`, `brands` |
416
+ | Orders | `orders`, `order-products`, `returns`, `return-products`, `exchanges`, `exchange-products`, `fulfillments`, `fulfillment-items`, `transactions` |
417
+ | Customers | `customers`, `customer-addresses`, `customer-groups` |
418
+ | Carts | `carts`, `cart-items` |
419
+ | Commerce | `discounts`, `shipping-policies` |
420
+ | Content | `posts`, `post-categories`, `post-tags`, `documents`, `document-categories`, `document-types` |
421
+ | Playlists | `playlists`, `playlist-categories`, `playlist-tags`, `musics` |
422
+ | Galleries | `galleries`, `gallery-items`, `gallery-categories`, `gallery-tags` |
423
+ | Flows | `flows`, `flow-node-types`, `flow-edge-types`, `flow-categories`, `flow-tags` |
424
+ | Videos | `videos`, `video-categories`, `video-tags` |
425
+ | Live Streams | `live-streams` |
426
+ | Forms | `forms`, `form-submissions` |
394
427
 
395
428
  ## Utilities
396
429
 
package/dist/auth.cjs CHANGED
@@ -125,7 +125,9 @@ function parseApiKey(apiKey) {
125
125
  }
126
126
  return { clientKey, secretKey };
127
127
  } catch (e) {
128
- throw new Error('Invalid API key. Expected Base64 encoded "clientKey:secretKey"');
128
+ throw new Error(
129
+ 'Invalid API key. Expected Base64 encoded "clientKey:secretKey"'
130
+ );
129
131
  }
130
132
  }
131
133
  //# sourceMappingURL=auth.cjs.map
package/dist/auth.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/auth.ts","../src/core/internal/utils/jwt.ts","../src/core/internal/utils/encoding.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'\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 */\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 */\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 */\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 * Creates a Base64-encoded API key from clientKey and secretKey.\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 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 */\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"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,kBAA8C;AAY9C,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;AAKA,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;AAOO,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;;;AC1EO,SAAS,aAAa,WAAmB,WAA2B;AACzE,MAAI,CAAC,aAAa,CAAC,WAAW;AAC5B,UAAM,IAAI,MAAM,uCAAuC;AAAA,EACzD;AAEA,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;AAKO,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":[]}
1
+ {"version":3,"sources":["../src/auth.ts","../src/core/internal/utils/jwt.ts","../src/core/internal/utils/encoding.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'\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 */\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 */\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 */\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 * Creates a Base64-encoded API key from clientKey and secretKey.\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 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 */\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(\n 'Invalid API key. Expected Base64 encoded \"clientKey:secretKey\"',\n )\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,kBAA8C;AAY9C,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;AAKA,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;AAOO,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;;;AC1EO,SAAS,aAAa,WAAmB,WAA2B;AACzE,MAAI,CAAC,aAAa,CAAC,WAAW;AAC5B,UAAM,IAAI,MAAM,uCAAuC;AAAA,EACzD;AAEA,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;AAKO,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;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
package/dist/auth.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import './payload-types-BjvBwB8Z.cjs';
1
+ import './payload-types-BUwpb306.cjs';
2
2
 
3
3
  interface JwtPayload {
4
4
  clientKey: string;
package/dist/auth.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import './payload-types-BjvBwB8Z.js';
1
+ import './payload-types-BUwpb306.js';
2
2
 
3
3
  interface JwtPayload {
4
4
  clientKey: string;
package/dist/auth.js CHANGED
@@ -96,7 +96,9 @@ function parseApiKey(apiKey) {
96
96
  }
97
97
  return { clientKey, secretKey };
98
98
  } catch (e) {
99
- throw new Error('Invalid API key. Expected Base64 encoded "clientKey:secretKey"');
99
+ throw new Error(
100
+ 'Invalid API key. Expected Base64 encoded "clientKey:secretKey"'
101
+ );
100
102
  }
101
103
  }
102
104
  export {
package/dist/auth.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/internal/utils/jwt.ts","../src/core/internal/utils/encoding.ts"],"sourcesContent":["import { SignJWT, jwtVerify, decodeJwt } from 'jose'\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 */\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 */\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 */\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 * Creates a Base64-encoded API key from clientKey and secretKey.\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 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 */\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"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,SAAS,WAAW,iBAAiB;AAY9C,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;AAKA,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;AAOO,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;;;AC1EO,SAAS,aAAa,WAAmB,WAA2B;AACzE,MAAI,CAAC,aAAa,CAAC,WAAW;AAC5B,UAAM,IAAI,MAAM,uCAAuC;AAAA,EACzD;AAEA,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;AAKO,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":[]}
1
+ {"version":3,"sources":["../src/core/internal/utils/jwt.ts","../src/core/internal/utils/encoding.ts"],"sourcesContent":["import { SignJWT, jwtVerify, decodeJwt } from 'jose'\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 */\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 */\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 */\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 * Creates a Base64-encoded API key from clientKey and secretKey.\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 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 */\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(\n 'Invalid API key. Expected Base64 encoded \"clientKey:secretKey\"',\n )\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,SAAS,WAAW,iBAAiB;AAY9C,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;AAKA,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;AAOO,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;;;AC1EO,SAAS,aAAa,WAAmB,WAA2B;AACzE,MAAI,CAAC,aAAa,CAAC,WAAW;AAC5B,UAAM,IAAI,MAAM,uCAAuC;AAAA,EACzD;AAEA,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;AAKO,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;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;","names":[]}