@ledewire/browser 0.5.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,6 +1,18 @@
1
- var p = Object.defineProperty;
2
- var w = (s, e, t) => e in s ? p(s, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : s[e] = t;
3
- var n = (s, e, t) => w(s, typeof e != "symbol" ? e + "" : e, t);
1
+ var g = Object.defineProperty;
2
+ var k = (s, e, t) => e in s ? g(s, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : s[e] = t;
3
+ var n = (s, e, t) => k(s, typeof e != "symbol" ? e + "" : e, t);
4
+ function w(s) {
5
+ return atob(s);
6
+ }
7
+ function u(s) {
8
+ return {
9
+ ...s,
10
+ ...typeof s.content_body == "string" && {
11
+ content_body: w(s.content_body)
12
+ },
13
+ ...typeof s.teaser == "string" && { teaser: w(s.teaser) }
14
+ };
15
+ }
4
16
  class c extends Error {
5
17
  constructor(t, r, o) {
6
18
  super(t);
@@ -11,38 +23,38 @@ class c extends Error {
11
23
  this.name = "LedewireError", this.statusCode = r, this.code = o, Object.setPrototypeOf(this, new.target.prototype);
12
24
  }
13
25
  }
14
- class u extends c {
26
+ class l extends c {
15
27
  constructor(e, t) {
16
28
  super(e, 401, t), this.name = "AuthError";
17
29
  }
18
30
  }
19
- class d extends c {
31
+ class T extends c {
20
32
  constructor(e, t) {
21
33
  super(e, 403, t), this.name = "ForbiddenError";
22
34
  }
23
35
  }
24
- class g extends c {
36
+ class y extends c {
25
37
  constructor(e, t) {
26
38
  super(e, 404, t), this.name = "NotFoundError";
27
39
  }
28
40
  }
29
- class $ extends c {
41
+ class q extends c {
30
42
  constructor(e, t, r) {
31
43
  super(e, t, r), this.name = "PurchaseError";
32
44
  }
33
45
  }
34
- const k = "https://api.ledewire.com";
35
- class f {
46
+ const d = "https://api.ledewire.com";
47
+ class A {
36
48
  constructor(e = {}) {
37
49
  n(this, "baseUrl");
38
50
  n(this, "getAccessToken");
39
51
  n(this, "onUnauthorized");
40
- this.baseUrl = (e.baseUrl ?? k).replace(/\/$/, ""), this.getAccessToken = e.getAccessToken ?? (() => null), this.onUnauthorized = e.onUnauthorized ?? (() => null);
52
+ this.baseUrl = (e.baseUrl ?? d).replace(/\/$/, ""), this.getAccessToken = e.getAccessToken ?? (() => null), this.onUnauthorized = e.onUnauthorized ?? (() => null);
41
53
  }
42
54
  /**
43
55
  * GET request with optional query parameters.
44
56
  * @param path - API path (e.g. `/v1/wallet/balance`)
45
- * @param params - Query string parameters
57
+ * @param params - Query string parameters. `undefined` values are omitted; numbers are coerced to strings.
46
58
  */
47
59
  async get(e, t) {
48
60
  return this.request("GET", this.buildUrl(e, t));
@@ -51,9 +63,10 @@ class f {
51
63
  * POST request.
52
64
  * @param path - API path
53
65
  * @param body - Request body (JSON-serialized)
66
+ * @param params - Optional query string parameters. `undefined` values are omitted; numbers are coerced to strings.
54
67
  */
55
- async post(e, t) {
56
- return this.request("POST", this.buildUrl(e), t);
68
+ async post(e, t, r) {
69
+ return this.request("POST", this.buildUrl(e, r), t);
57
70
  }
58
71
  /**
59
72
  * PUT request.
@@ -83,7 +96,13 @@ class f {
83
96
  // ---------------------------------------------------------------------------
84
97
  buildUrl(e, t) {
85
98
  const r = `${this.baseUrl}${e}`;
86
- return !t || Object.keys(t).length === 0 ? r : `${r}?${new URLSearchParams(t).toString()}`;
99
+ if (!t) return r;
100
+ const o = Object.entries(t).filter(
101
+ (i) => i[1] !== void 0
102
+ );
103
+ if (o.length === 0) return r;
104
+ const h = new URLSearchParams(o.map(([i, a]) => [i, String(a)]));
105
+ return `${r}?${h.toString()}`;
87
106
  }
88
107
  async request(e, t, r, o = !1) {
89
108
  const h = await this.getAccessToken(), i = {
@@ -99,7 +118,7 @@ class f {
99
118
  if (a.status === 401 && !o) {
100
119
  if (await this.onUnauthorized())
101
120
  return this.request(e, t, r, !0);
102
- throw new u("Session expired. Please re-authenticate.");
121
+ throw new l("Session expired. Please re-authenticate.");
103
122
  }
104
123
  if (a.ok || await this.throwApiError(a), a.status !== 204)
105
124
  return a.json();
@@ -113,18 +132,18 @@ class f {
113
132
  const r = t?.error.message ?? e.statusText, o = t?.error.code;
114
133
  switch (e.status) {
115
134
  case 401:
116
- throw new u(r, o);
135
+ throw new l(r, o);
117
136
  case 403:
118
- throw new d(r, o);
137
+ throw new T(r, o);
119
138
  case 404:
120
- throw new g(r, o);
139
+ throw new y(r, o);
121
140
  default:
122
141
  throw new c(r, e.status, o);
123
142
  }
124
143
  }
125
144
  }
126
- const T = 6e4;
127
- class y {
145
+ const m = 6e4;
146
+ class E {
128
147
  constructor(e) {
129
148
  n(this, "storage");
130
149
  n(this, "refreshFn");
@@ -139,7 +158,7 @@ class y {
139
158
  */
140
159
  async getAccessToken() {
141
160
  const e = await this.storage.getTokens();
142
- return e ? e.expiresAt - Date.now() < T ? (await this.performRefresh(e.refreshToken))?.accessToken ?? null : e.accessToken : null;
161
+ return e ? e.expiresAt - Date.now() < m ? (await this.performRefresh(e.refreshToken))?.accessToken ?? null : e.accessToken : null;
143
162
  }
144
163
  /**
145
164
  * Called by `HttpClient` when a 401 is received.
@@ -165,13 +184,13 @@ class y {
165
184
  // ---------------------------------------------------------------------------
166
185
  performRefresh(e) {
167
186
  return this.refreshPromise ? this.refreshPromise : (this.refreshPromise = this.refreshFn(e).then(async (t) => (await this.storage.setTokens(t), await this.onTokenRefreshed?.(t), t)).catch((t) => {
168
- throw this.storage.clearTokens(), new u("Token refresh failed. Please re-authenticate.");
187
+ throw this.storage.clearTokens(), new l("Token refresh failed. Please re-authenticate.");
169
188
  }).finally(() => {
170
189
  this.refreshPromise = null;
171
190
  }), this.refreshPromise);
172
191
  }
173
192
  }
174
- class m {
193
+ class v {
175
194
  constructor() {
176
195
  n(this, "tokens", null);
177
196
  }
@@ -185,10 +204,26 @@ class m {
185
204
  this.tokens = null;
186
205
  }
187
206
  }
188
- function l(s) {
207
+ function p(s) {
189
208
  return new Date(s).getTime();
190
209
  }
191
- class E {
210
+ function x(s) {
211
+ return async (e) => {
212
+ const t = await fetch(`${s}/v1/auth/token/refresh`, {
213
+ method: "POST",
214
+ headers: { "Content-Type": "application/json" },
215
+ body: JSON.stringify({ refresh_token: e })
216
+ });
217
+ if (!t.ok) throw new Error("Token refresh failed");
218
+ const r = await t.json();
219
+ return {
220
+ accessToken: r.access_token,
221
+ refreshToken: r.refresh_token,
222
+ expiresAt: p(r.expires_at)
223
+ };
224
+ };
225
+ }
226
+ class S {
192
227
  /** @internal */
193
228
  constructor(e, t) {
194
229
  this.http = e, this.tokenManager = t;
@@ -226,30 +261,6 @@ class E {
226
261
  const t = await this.http.post("/v1/auth/login/google", e);
227
262
  return await this.storeTokens(t), t;
228
263
  }
229
- /**
230
- * Log in using an API key to obtain a seller token.
231
- * Provide only `key` for read-only (`view`) access.
232
- * Provide both `key` and `secret` for read/write (`full`) access.
233
- * Tokens are stored automatically after successful authentication.
234
- *
235
- * Use this before calling `lw.seller.content.*` methods.
236
- *
237
- * @param body - API key credentials.
238
- * @returns The authentication token response.
239
- *
240
- * @example
241
- * ```ts
242
- * // View access (read-only) — sufficient for seller.content.list/search/get
243
- * await lw.auth.loginWithApiKey({ key: 'your_api_key' })
244
- *
245
- * // Full access (read/write)
246
- * await lw.auth.loginWithApiKey({ key: 'your_api_key', secret: 'your_secret' })
247
- * ```
248
- */
249
- async loginWithApiKey(e) {
250
- const t = await this.http.post("/v1/auth/login/api-key", e);
251
- return await this.storeTokens(t), t;
252
- }
253
264
  /**
254
265
  * Request a password reset code to be sent to the buyer's email address.
255
266
  *
@@ -292,11 +303,11 @@ class E {
292
303
  await this.tokenManager.setTokens({
293
304
  accessToken: e.access_token,
294
305
  refreshToken: e.refresh_token,
295
- expiresAt: l(e.expires_at)
306
+ expiresAt: p(e.expires_at)
296
307
  });
297
308
  }
298
309
  }
299
- class A {
310
+ class b {
300
311
  /** @internal */
301
312
  constructor(e) {
302
313
  this.http = e;
@@ -319,7 +330,7 @@ class A {
319
330
  return this.http.get("/v1/config/public");
320
331
  }
321
332
  }
322
- class v {
333
+ class U {
323
334
  constructor(e) {
324
335
  this.http = e;
325
336
  }
@@ -328,18 +339,24 @@ class v {
328
339
  * authenticated buyer (or a generic access response when unauthenticated).
329
340
  *
330
341
  * @param id - The content ID.
331
- * @param userId - Optional user ID to check a specific user's access status.
332
- * @returns The content item with access information.
342
+ * @returns The content item with access information. `content_body` and
343
+ * `teaser` are returned as plain UTF-8 text — the SDK decodes base64
344
+ * transparently so you can render them directly.
345
+ *
346
+ * @example
347
+ * ```ts
348
+ * const result = await lw.content.getWithAccess('article-123')
349
+ * if (result.access_info.next_required_action === 'view_content') {
350
+ * renderMarkdown(result.content_body ?? '')
351
+ * }
352
+ * ```
333
353
  */
334
- async getWithAccess(e, t) {
335
- const r = {};
336
- return t !== void 0 && (r.user_id = t), this.http.get(
337
- `/v1/content/${e}/with-access`,
338
- Object.keys(r).length > 0 ? r : void 0
339
- );
354
+ async getWithAccess(e) {
355
+ const t = await this.http.get(`/v1/content/${e}/with-access`);
356
+ return u(t);
340
357
  }
341
358
  }
342
- class x {
359
+ class P {
343
360
  constructor(e) {
344
361
  this.http = e;
345
362
  }
@@ -370,7 +387,7 @@ class x {
370
387
  return this.http.get(`/v1/purchases/${e}`);
371
388
  }
372
389
  }
373
- class U {
390
+ class R {
374
391
  /** @internal */
375
392
  constructor(e) {
376
393
  this.http = e;
@@ -379,7 +396,8 @@ class U {
379
396
  * List all content for the authenticated seller's store.
380
397
  * Requires a token with at least `view` permission.
381
398
  *
382
- * @returns Array of content items.
399
+ * @returns Array of content items. `teaser` is returned as plain text —
400
+ * the SDK decodes base64 automatically.
383
401
  *
384
402
  * @example
385
403
  * ```ts
@@ -387,7 +405,7 @@ class U {
387
405
  * ```
388
406
  */
389
407
  async list() {
390
- return this.http.get("/v1/seller/content");
408
+ return (await this.http.get("/v1/seller/content")).map(u);
391
409
  }
392
410
  /**
393
411
  * Search content by title, URI, and/or metadata (AND logic).
@@ -395,43 +413,77 @@ class U {
395
413
  * Requires a token with at least `view` permission.
396
414
  *
397
415
  * @param body - Search criteria (title, uri, and/or metadata).
398
- * @returns Array of matching content items.
416
+ * @returns Array of matching content items. `teaser` is returned as plain
417
+ * text — the SDK decodes base64 automatically.
399
418
  *
400
419
  * @example
401
420
  * ```ts
402
421
  * const results = await lw.seller.content.search({ title: 'intro' })
403
422
  * const byUri = await lw.seller.content.search({ uri: 'vimeo.com' })
423
+ * const byId = await lw.seller.content.search({ external_identifier: 'vimeo:123456789' })
404
424
  * const byMeta = await lw.seller.content.search({ metadata: { author: 'Alice' } })
405
425
  * ```
406
426
  */
407
427
  async search(e) {
408
- return this.http.post("/v1/seller/content/search", e);
428
+ return (await this.http.post("/v1/seller/content/search", e)).map(u);
409
429
  }
410
430
  /**
411
431
  * Get a single content item by ID.
412
432
  * Requires a token with at least `view` permission.
413
433
  *
414
434
  * @param id - The content ID.
415
- * @returns The content item.
435
+ * @returns The content item. `content_body` and `teaser` are returned as
436
+ * plain UTF-8 text — the SDK decodes base64 automatically so you can render
437
+ * them directly without calling `atob()`.
416
438
  *
417
439
  * @example
418
440
  * ```ts
419
441
  * const item = await lw.seller.content.get('content-id')
442
+ * // item.content_body is plain markdown — no atob() needed
420
443
  * ```
421
444
  */
422
445
  async get(e) {
423
- return this.http.get(`/v1/seller/content/${e}`);
446
+ const t = await this.http.get(`/v1/seller/content/${e}`);
447
+ return u(t);
424
448
  }
425
449
  }
426
- class S {
450
+ class F {
427
451
  /** @internal */
428
- constructor(e) {
452
+ constructor(e, t) {
429
453
  /** Seller content: list, search, and get by API key. */
430
454
  n(this, "content");
431
- this.content = new U(e);
455
+ this.http = e, this.tokenManager = t, this.content = new R(e);
456
+ }
457
+ /**
458
+ * Log in using an API key to obtain a seller token.
459
+ * Provide only `key` for read-only (`view`) access.
460
+ * Provide both `key` and `secret` for read/write (`full`) access.
461
+ * Tokens are stored automatically after successful authentication.
462
+ *
463
+ * Use this before calling `lw.seller.content.*` methods.
464
+ *
465
+ * @param body - API key credentials.
466
+ * @returns The authentication token response.
467
+ *
468
+ * @example
469
+ * ```ts
470
+ * // View access (read-only) — sufficient for seller.content.list/search/get
471
+ * await lw.seller.loginWithApiKey({ key: 'your_api_key' })
472
+ *
473
+ * // Full access (read/write)
474
+ * await lw.seller.loginWithApiKey({ key: 'your_api_key', secret: 'your_secret' })
475
+ * ```
476
+ */
477
+ async loginWithApiKey(e) {
478
+ const t = await this.http.post("/v1/auth/login/api-key", e);
479
+ return await this.tokenManager.setTokens({
480
+ accessToken: t.access_token,
481
+ refreshToken: t.refresh_token,
482
+ expiresAt: p(t.expires_at)
483
+ }), t;
432
484
  }
433
485
  }
434
- class b {
486
+ class N {
435
487
  constructor(e) {
436
488
  this.http = e;
437
489
  }
@@ -470,7 +522,7 @@ class b {
470
522
  return this.http.get(`/v1/wallet/payment-status/${e}`);
471
523
  }
472
524
  }
473
- class P {
525
+ class _ {
474
526
  constructor(e) {
475
527
  this.http = e;
476
528
  }
@@ -489,37 +541,24 @@ class P {
489
541
  return this.http.get(`/v1/checkout/state/${e}`);
490
542
  }
491
543
  }
492
- function C(s) {
493
- const e = s.baseUrl ?? "https://api.ledewire.com", t = s.storage ?? new m(), r = new y({
544
+ function M(s) {
545
+ const e = s.baseUrl ?? d, t = s.storage ?? new v(), r = new E({
494
546
  storage: t,
495
- refreshFn: async (h) => {
496
- const i = await fetch(`${e}/v1/auth/token/refresh`, {
497
- method: "POST",
498
- headers: { "Content-Type": "application/json" },
499
- body: JSON.stringify({ refresh_token: h })
500
- });
501
- if (!i.ok) throw new Error("Token refresh failed");
502
- const a = await i.json();
503
- return {
504
- accessToken: a.access_token,
505
- refreshToken: a.refresh_token,
506
- expiresAt: l(a.expires_at)
507
- };
508
- },
547
+ refreshFn: x(e),
509
548
  ...s.onAuthExpired !== void 0 && { onAuthExpired: s.onAuthExpired }
510
- }), o = new f({
549
+ }), o = new A({
511
550
  baseUrl: e,
512
551
  getAccessToken: () => r.getAccessToken(),
513
552
  onUnauthorized: () => r.handleUnauthorized()
514
553
  });
515
- return new N(o, r, s);
554
+ return new C(o, r, s);
516
555
  }
517
- class N {
556
+ class C {
518
557
  /** @internal */
519
558
  constructor(e, t, r) {
520
559
  /** Platform-level public configuration (no auth required) */
521
560
  n(this, "config");
522
- /** Buyer authentication: email/password signup/login, Google, password reset */
561
+ /** Buyer authentication: email/password signup/login, Google OAuth, password reset */
523
562
  n(this, "auth");
524
563
  /** Checkout state machine: determines next action for a piece of content */
525
564
  n(this, "checkout");
@@ -529,40 +568,47 @@ class N {
529
568
  n(this, "purchases");
530
569
  /** Public content with per-user access information */
531
570
  n(this, "content");
532
- /** Seller content: list, search, and get (requires API key view token) */
571
+ /** Seller operations: API key login, content list/search/get */
533
572
  n(this, "seller");
534
- this._http = e, this._tokenManager = t, this._config = r, this.config = new A(e), this.auth = new E(e, t), this.checkout = new P(e), this.wallet = new b(e), this.purchases = new x(e), this.content = new v(e), this.seller = new S(e);
573
+ this._http = e, this._tokenManager = t, this._config = r, this.config = new b(e), this.auth = new S(e, t), this.checkout = new _(e), this.wallet = new N(e), this.purchases = new P(e), this.content = new U(e), this.seller = new F(e, t);
535
574
  }
536
575
  }
537
- const R = "lw:tokens";
538
- function B(s = R) {
576
+ const $ = "lw:tokens";
577
+ function f(s, e = $) {
539
578
  return {
540
579
  getTokens() {
541
- const e = localStorage.getItem(s);
542
- if (!e) return null;
580
+ const t = s.getItem(e);
581
+ if (!t) return null;
543
582
  try {
544
- return JSON.parse(e);
583
+ return JSON.parse(t);
545
584
  } catch {
546
585
  return null;
547
586
  }
548
587
  },
549
- setTokens(e) {
550
- localStorage.setItem(s, JSON.stringify(e));
588
+ setTokens(t) {
589
+ s.setItem(e, JSON.stringify(t));
551
590
  },
552
591
  clearTokens() {
553
- localStorage.removeItem(s);
592
+ s.removeItem(e);
554
593
  }
555
594
  };
556
595
  }
596
+ function j(s) {
597
+ return f(localStorage, s);
598
+ }
599
+ function z(s) {
600
+ return f(sessionStorage, s);
601
+ }
557
602
  export {
558
- u as AuthError,
559
- d as ForbiddenError,
603
+ l as AuthError,
604
+ T as ForbiddenError,
560
605
  c as LedewireError,
561
- m as MemoryTokenStorage,
562
- g as NotFoundError,
563
- $ as PurchaseError,
564
- C as init,
565
- B as localStorageAdapter,
566
- l as parseExpiresAt
606
+ v as MemoryTokenStorage,
607
+ y as NotFoundError,
608
+ q as PurchaseError,
609
+ M as init,
610
+ j as localStorageAdapter,
611
+ p as parseExpiresAt,
612
+ z as sessionStorageAdapter
567
613
  };
568
614
  //# sourceMappingURL=index.js.map