@01.software/sdk 0.2.9-dev.260311.926a6d4 → 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.
Files changed (64) hide show
  1. package/README.md +95 -62
  2. package/dist/auth.cjs +3 -1
  3. package/dist/auth.cjs.map +1 -1
  4. package/dist/auth.d.cts +1 -1
  5. package/dist/auth.d.ts +1 -1
  6. package/dist/auth.js +3 -1
  7. package/dist/auth.js.map +1 -1
  8. package/dist/index.cjs +172 -91
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.d.cts +17 -35
  11. package/dist/index.d.ts +17 -35
  12. package/dist/index.js +177 -92
  13. package/dist/index.js.map +1 -1
  14. package/dist/{payload-types-BjvBwB8Z.d.cts → payload-types-BUwpb306.d.cts} +295 -1384
  15. package/dist/{payload-types-BjvBwB8Z.d.ts → payload-types-BUwpb306.d.ts} +295 -1384
  16. package/dist/{components → ui}/code-block.cjs +11 -8
  17. package/dist/ui/code-block.cjs.map +1 -0
  18. package/dist/{components → ui}/code-block.js +11 -8
  19. package/dist/ui/code-block.js.map +1 -0
  20. package/dist/{components → ui}/flow.cjs +117 -69
  21. package/dist/ui/flow.cjs.map +1 -0
  22. package/dist/{components → ui}/flow.js +114 -66
  23. package/dist/ui/flow.js.map +1 -0
  24. package/dist/{components → ui}/form.cjs +6 -6
  25. package/dist/ui/form.cjs.map +1 -0
  26. package/dist/{components → ui}/form.d.cts +1 -1
  27. package/dist/{components → ui}/form.d.ts +1 -1
  28. package/dist/{components → ui}/form.js +3 -3
  29. package/dist/ui/form.js.map +1 -0
  30. package/dist/{components → ui}/image.cjs +2 -2
  31. package/dist/ui/image.cjs.map +1 -0
  32. package/dist/{components → ui}/image.js +2 -2
  33. package/dist/ui/image.js.map +1 -0
  34. package/dist/{components → ui}/rich-text.cjs +6 -6
  35. package/dist/ui/rich-text.cjs.map +1 -0
  36. package/dist/{components → ui}/rich-text.js +3 -3
  37. package/dist/ui/rich-text.js.map +1 -0
  38. package/dist/{webhook-_LdLdjGa.d.ts → webhook-BUcDo2Ny.d.cts} +2 -2
  39. package/dist/{webhook-CszIpUKn.d.cts → webhook-D8Bp97bF.d.ts} +2 -2
  40. package/dist/webhook.cjs +7 -5
  41. package/dist/webhook.cjs.map +1 -1
  42. package/dist/webhook.d.cts +2 -2
  43. package/dist/webhook.d.ts +2 -2
  44. package/dist/webhook.js +7 -5
  45. package/dist/webhook.js.map +1 -1
  46. package/package.json +29 -28
  47. package/dist/components/code-block.cjs.map +0 -1
  48. package/dist/components/code-block.js.map +0 -1
  49. package/dist/components/flow.cjs.map +0 -1
  50. package/dist/components/flow.js.map +0 -1
  51. package/dist/components/form.cjs.map +0 -1
  52. package/dist/components/form.js.map +0 -1
  53. package/dist/components/image.cjs.map +0 -1
  54. package/dist/components/image.js.map +0 -1
  55. package/dist/components/rich-text.cjs.map +0 -1
  56. package/dist/components/rich-text.js.map +0 -1
  57. /package/dist/{components → ui}/code-block.d.cts +0 -0
  58. /package/dist/{components → ui}/code-block.d.ts +0 -0
  59. /package/dist/{components → ui}/flow.d.cts +0 -0
  60. /package/dist/{components → ui}/flow.d.ts +0 -0
  61. /package/dist/{components → ui}/image.d.cts +0 -0
  62. /package/dist/{components → ui}/image.d.ts +0 -0
  63. /package/dist/{components → ui}/rich-text.d.cts +0 -0
  64. /package/dist/{components → ui}/rich-text.d.ts +0 -0
package/README.md CHANGED
@@ -29,18 +29,24 @@ 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
- import { RichTextContent } from '@01.software/sdk/components/rich-text'
39
- import { Image } from '@01.software/sdk/components/image'
40
- import { FormRenderer } from '@01.software/sdk/components/form'
41
- import { CodeBlock } from '@01.software/sdk/components/code-block'
42
- import { FlowRenderer } from '@01.software/sdk/components/flow'
43
-
45
+ import { RichTextContent } from '@01.software/sdk/ui/rich-text'
46
+ import { Image } from '@01.software/sdk/ui/image'
47
+ import { FormRenderer } from '@01.software/sdk/ui/form'
48
+ import { CodeBlock } from '@01.software/sdk/ui/code-block'
49
+ import { FlowRenderer } from '@01.software/sdk/ui/flow'
44
50
  ```
45
51
 
46
52
  ## Getting Started
@@ -94,18 +100,19 @@ await client.query.prefetchQuery({
94
100
 
95
101
  ```typescript
96
102
  const client = createBrowserClient({
97
- clientKey: string, // Required
98
- environment?: Environment, // 'local' | 'development' | 'staging' | 'production'
99
- baseUrl?: string, // Custom API URL (overrides environment)
103
+ clientKey: string, // Required
100
104
  })
101
105
  ```
102
106
 
103
- | Option | Type | Description |
104
- | ------------- | ------------- | ---------------------------- |
105
- | `clientKey` | `string` | API client key |
106
- | `secretKey` | `string` | API secret key (server only) |
107
- | `environment` | `Environment` | API environment |
108
- | `baseUrl` | `string` | Custom API URL |
107
+ | Option | Type | Description |
108
+ | ----------- | -------- | ---------------------------- |
109
+ | `clientKey` | `string` | API client key |
110
+ | `secretKey` | `string` | API secret key (server only) |
111
+
112
+ API URL은 환경변수로 오버라이드 가능합니다:
113
+
114
+ - `SOFTWARE_API_URL` (서버용) 또는 `NEXT_PUBLIC_SOFTWARE_API_URL` (브라우저용)
115
+ - 미설정 시: dev 빌드(`@dev` 태그)는 `api-dev.01.software`, 정식 릴리즈는 `api.01.software`
109
116
 
110
117
  ### Query Builder
111
118
 
@@ -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
 
@@ -438,7 +471,7 @@ React component for rendering Payload CMS Lexical rich text. Two variants:
438
471
  - **`StyledRichTextContent`** — Headless component with slot-based customization (`components` prop)
439
472
 
440
473
  ```tsx
441
- import { RichTextContent, StyledRichTextContent } from '@01.software/sdk/components/rich-text'
474
+ import { RichTextContent, StyledRichTextContent } from '@01.software/sdk/ui/rich-text'
442
475
 
443
476
  // Base: full converter control
444
477
  <RichTextContent
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":[]}