@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 +81 -48
- package/dist/auth.cjs +3 -1
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +1 -1
- package/dist/auth.d.ts +1 -1
- package/dist/auth.js +3 -1
- package/dist/auth.js.map +1 -1
- package/dist/index.cjs +168 -75
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -10
- package/dist/index.d.ts +12 -10
- package/dist/index.js +173 -76
- package/dist/index.js.map +1 -1
- package/dist/{payload-types-BjvBwB8Z.d.cts → payload-types-BUwpb306.d.cts} +295 -1384
- package/dist/{payload-types-BjvBwB8Z.d.ts → payload-types-BUwpb306.d.ts} +295 -1384
- package/dist/ui/code-block.cjs +8 -5
- package/dist/ui/code-block.cjs.map +1 -1
- package/dist/ui/code-block.js +8 -5
- package/dist/ui/code-block.js.map +1 -1
- package/dist/ui/flow.cjs +108 -60
- package/dist/ui/flow.cjs.map +1 -1
- package/dist/ui/flow.js +108 -60
- package/dist/ui/flow.js.map +1 -1
- package/dist/ui/form.d.cts +1 -1
- package/dist/ui/form.d.ts +1 -1
- package/dist/ui/rich-text.cjs.map +1 -1
- package/dist/ui/rich-text.js.map +1 -1
- package/dist/{webhook-_LdLdjGa.d.ts → webhook-BUcDo2Ny.d.cts} +2 -2
- package/dist/{webhook-CszIpUKn.d.cts → webhook-D8Bp97bF.d.ts} +2 -2
- package/dist/webhook.cjs +7 -5
- package/dist/webhook.cjs.map +1 -1
- package/dist/webhook.d.cts +2 -2
- package/dist/webhook.d.ts +2 -2
- package/dist/webhook.js +7 -5
- package/dist/webhook.js.map +1 -1
- package/package.json +3 -3
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 {
|
|
32
|
+
import {
|
|
33
|
+
createServerToken,
|
|
34
|
+
verifyServerToken,
|
|
35
|
+
createApiKey,
|
|
36
|
+
} from '@01.software/sdk/auth'
|
|
33
37
|
|
|
34
38
|
// Webhook only - webhook handlers
|
|
35
|
-
import {
|
|
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,
|
|
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
|
|
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
|
|
135
|
-
|
|
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('
|
|
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
|
|
153
|
-
|
|
154
|
-
|
|
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
|
|
196
|
-
|
|
197
|
-
| `find()`
|
|
198
|
-
| `findById()`
|
|
199
|
-
| `create()`
|
|
200
|
-
| `update()`
|
|
201
|
-
| `remove()`
|
|
202
|
-
| `count()`
|
|
203
|
-
| `findMetadata()`
|
|
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: '
|
|
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({
|
|
246
|
-
|
|
247
|
-
|
|
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({
|
|
286
|
-
|
|
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({
|
|
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: [
|
|
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
|
|
379
|
-
|
|
|
380
|
-
| Tenant
|
|
381
|
-
|
|
|
382
|
-
|
|
|
383
|
-
|
|
|
384
|
-
|
|
|
385
|
-
|
|
|
386
|
-
|
|
|
387
|
-
|
|
|
388
|
-
|
|
|
389
|
-
|
|
|
390
|
-
|
|
|
391
|
-
|
|
|
392
|
-
|
|
|
393
|
-
|
|
|
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(
|
|
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,
|
|
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
package/dist/auth.d.ts
CHANGED
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(
|
|
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,
|
|
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":[]}
|