@ledewire/browser 0.4.0 → 0.6.0

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 d = Object.defineProperty;
2
+ var g = (s, e, t) => e in s ? d(s, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : s[e] = t;
3
+ var n = (s, e, t) => g(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,33 +23,33 @@ 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 k 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 f 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 B 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 T = "https://api.ledewire.com";
47
+ class y {
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 ?? T).replace(/\/$/, ""), this.getAccessToken = e.getAccessToken ?? (() => null), this.onUnauthorized = e.onUnauthorized ?? (() => null);
41
53
  }
42
54
  /**
43
55
  * GET request with optional query parameters.
@@ -99,7 +111,7 @@ class f {
99
111
  if (a.status === 401 && !o) {
100
112
  if (await this.onUnauthorized())
101
113
  return this.request(e, t, r, !0);
102
- throw new u("Session expired. Please re-authenticate.");
114
+ throw new l("Session expired. Please re-authenticate.");
103
115
  }
104
116
  if (a.ok || await this.throwApiError(a), a.status !== 204)
105
117
  return a.json();
@@ -113,18 +125,18 @@ class f {
113
125
  const r = t?.error.message ?? e.statusText, o = t?.error.code;
114
126
  switch (e.status) {
115
127
  case 401:
116
- throw new u(r, o);
128
+ throw new l(r, o);
117
129
  case 403:
118
- throw new d(r, o);
130
+ throw new k(r, o);
119
131
  case 404:
120
- throw new g(r, o);
132
+ throw new f(r, o);
121
133
  default:
122
134
  throw new c(r, e.status, o);
123
135
  }
124
136
  }
125
137
  }
126
- const T = 6e4;
127
- class y {
138
+ const m = 6e4;
139
+ class E {
128
140
  constructor(e) {
129
141
  n(this, "storage");
130
142
  n(this, "refreshFn");
@@ -139,7 +151,7 @@ class y {
139
151
  */
140
152
  async getAccessToken() {
141
153
  const e = await this.storage.getTokens();
142
- return e ? e.expiresAt - Date.now() < T ? (await this.performRefresh(e.refreshToken))?.accessToken ?? null : e.accessToken : null;
154
+ return e ? e.expiresAt - Date.now() < m ? (await this.performRefresh(e.refreshToken))?.accessToken ?? null : e.accessToken : null;
143
155
  }
144
156
  /**
145
157
  * Called by `HttpClient` when a 401 is received.
@@ -165,13 +177,13 @@ class y {
165
177
  // ---------------------------------------------------------------------------
166
178
  performRefresh(e) {
167
179
  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.");
180
+ throw this.storage.clearTokens(), new l("Token refresh failed. Please re-authenticate.");
169
181
  }).finally(() => {
170
182
  this.refreshPromise = null;
171
183
  }), this.refreshPromise);
172
184
  }
173
185
  }
174
- class m {
186
+ class A {
175
187
  constructor() {
176
188
  n(this, "tokens", null);
177
189
  }
@@ -185,10 +197,10 @@ class m {
185
197
  this.tokens = null;
186
198
  }
187
199
  }
188
- function l(s) {
200
+ function p(s) {
189
201
  return new Date(s).getTime();
190
202
  }
191
- class E {
203
+ class S {
192
204
  /** @internal */
193
205
  constructor(e, t) {
194
206
  this.http = e, this.tokenManager = t;
@@ -227,38 +239,52 @@ class E {
227
239
  return await this.storeTokens(t), t;
228
240
  }
229
241
  /**
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.
242
+ * Request a password reset code to be sent to the buyer's email address.
234
243
  *
235
- * Use this before calling `lw.seller.content.*` methods.
244
+ * The response is intentionally ambiguous — if the email does not exist,
245
+ * the API returns the same success message to prevent account enumeration.
236
246
  *
237
- * @param body - API key credentials.
238
- * @returns The authentication token response.
247
+ * @param body - The buyer's email address.
248
+ * @returns A response with a confirmation message.
239
249
  *
240
250
  * @example
241
251
  * ```ts
242
- * // View access (read-only) — sufficient for seller.content.list/search/get
243
- * await lw.auth.loginWithApiKey({ key: 'your_api_key' })
252
+ * await lw.auth.requestPasswordReset({ email: 'buyer@example.com' })
253
+ * // → { data: { message: 'If an account with this email exists, a reset code has been sent.' } }
254
+ * ```
255
+ */
256
+ async requestPasswordReset(e) {
257
+ return this.http.post("/v1/auth/password/reset-request", e);
258
+ }
259
+ /**
260
+ * Reset a buyer's password using the code delivered to their email.
244
261
  *
245
- * // Full access (read/write)
246
- * await lw.auth.loginWithApiKey({ key: 'your_api_key', secret: 'your_secret' })
262
+ * Obtain the reset code first by calling `requestPasswordReset()`.
263
+ *
264
+ * @param body - Email address, 6-digit reset code, and the new password.
265
+ * @returns A response with a confirmation message.
266
+ *
267
+ * @example
268
+ * ```ts
269
+ * await lw.auth.resetPassword({
270
+ * email: 'buyer@example.com',
271
+ * reset_code: '123456',
272
+ * password: 'new-secure-password',
273
+ * })
247
274
  * ```
248
275
  */
249
- async loginWithApiKey(e) {
250
- const t = await this.http.post("/v1/auth/login/api-key", e);
251
- return await this.storeTokens(t), t;
276
+ async resetPassword(e) {
277
+ return this.http.post("/v1/auth/password/reset", e);
252
278
  }
253
279
  async storeTokens(e) {
254
280
  await this.tokenManager.setTokens({
255
281
  accessToken: e.access_token,
256
282
  refreshToken: e.refresh_token,
257
- expiresAt: l(e.expires_at)
283
+ expiresAt: p(e.expires_at)
258
284
  });
259
285
  }
260
286
  }
261
- class A {
287
+ class v {
262
288
  /** @internal */
263
289
  constructor(e) {
264
290
  this.http = e;
@@ -281,7 +307,7 @@ class A {
281
307
  return this.http.get("/v1/config/public");
282
308
  }
283
309
  }
284
- class v {
310
+ class x {
285
311
  constructor(e) {
286
312
  this.http = e;
287
313
  }
@@ -290,18 +316,24 @@ class v {
290
316
  * authenticated buyer (or a generic access response when unauthenticated).
291
317
  *
292
318
  * @param id - The content ID.
293
- * @param userId - Optional user ID to check a specific user's access status.
294
- * @returns The content item with access information.
319
+ * @returns The content item with access information. `content_body` and
320
+ * `teaser` are returned as plain UTF-8 text — the SDK decodes base64
321
+ * transparently so you can render them directly.
322
+ *
323
+ * @example
324
+ * ```ts
325
+ * const result = await lw.content.getWithAccess('article-123')
326
+ * if (result.access_info.next_required_action === 'view_content') {
327
+ * renderMarkdown(result.content_body ?? '')
328
+ * }
329
+ * ```
295
330
  */
296
- async getWithAccess(e, t) {
297
- const r = {};
298
- return t !== void 0 && (r.user_id = t), this.http.get(
299
- `/v1/content/${e}/with-access`,
300
- Object.keys(r).length > 0 ? r : void 0
301
- );
331
+ async getWithAccess(e) {
332
+ const t = await this.http.get(`/v1/content/${e}/with-access`);
333
+ return u(t);
302
334
  }
303
335
  }
304
- class x {
336
+ class b {
305
337
  constructor(e) {
306
338
  this.http = e;
307
339
  }
@@ -341,7 +373,8 @@ class U {
341
373
  * List all content for the authenticated seller's store.
342
374
  * Requires a token with at least `view` permission.
343
375
  *
344
- * @returns Array of content items.
376
+ * @returns Array of content items. `teaser` is returned as plain text —
377
+ * the SDK decodes base64 automatically.
345
378
  *
346
379
  * @example
347
380
  * ```ts
@@ -349,7 +382,7 @@ class U {
349
382
  * ```
350
383
  */
351
384
  async list() {
352
- return this.http.get("/v1/seller/content");
385
+ return (await this.http.get("/v1/seller/content")).map(u);
353
386
  }
354
387
  /**
355
388
  * Search content by title, URI, and/or metadata (AND logic).
@@ -357,43 +390,77 @@ class U {
357
390
  * Requires a token with at least `view` permission.
358
391
  *
359
392
  * @param body - Search criteria (title, uri, and/or metadata).
360
- * @returns Array of matching content items.
393
+ * @returns Array of matching content items. `teaser` is returned as plain
394
+ * text — the SDK decodes base64 automatically.
361
395
  *
362
396
  * @example
363
397
  * ```ts
364
398
  * const results = await lw.seller.content.search({ title: 'intro' })
365
399
  * const byUri = await lw.seller.content.search({ uri: 'vimeo.com' })
400
+ * const byId = await lw.seller.content.search({ external_identifier: 'vimeo:123456789' })
366
401
  * const byMeta = await lw.seller.content.search({ metadata: { author: 'Alice' } })
367
402
  * ```
368
403
  */
369
404
  async search(e) {
370
- return this.http.post("/v1/seller/content/search", e);
405
+ return (await this.http.post("/v1/seller/content/search", e)).map(u);
371
406
  }
372
407
  /**
373
408
  * Get a single content item by ID.
374
409
  * Requires a token with at least `view` permission.
375
410
  *
376
411
  * @param id - The content ID.
377
- * @returns The content item.
412
+ * @returns The content item. `content_body` and `teaser` are returned as
413
+ * plain UTF-8 text — the SDK decodes base64 automatically so you can render
414
+ * them directly without calling `atob()`.
378
415
  *
379
416
  * @example
380
417
  * ```ts
381
418
  * const item = await lw.seller.content.get('content-id')
419
+ * // item.content_body is plain markdown — no atob() needed
382
420
  * ```
383
421
  */
384
422
  async get(e) {
385
- return this.http.get(`/v1/seller/content/${e}`);
423
+ const t = await this.http.get(`/v1/seller/content/${e}`);
424
+ return u(t);
386
425
  }
387
426
  }
388
- class S {
427
+ class P {
389
428
  /** @internal */
390
- constructor(e) {
429
+ constructor(e, t) {
391
430
  /** Seller content: list, search, and get by API key. */
392
431
  n(this, "content");
393
- this.content = new U(e);
432
+ this.http = e, this.tokenManager = t, this.content = new U(e);
433
+ }
434
+ /**
435
+ * Log in using an API key to obtain a seller token.
436
+ * Provide only `key` for read-only (`view`) access.
437
+ * Provide both `key` and `secret` for read/write (`full`) access.
438
+ * Tokens are stored automatically after successful authentication.
439
+ *
440
+ * Use this before calling `lw.seller.content.*` methods.
441
+ *
442
+ * @param body - API key credentials.
443
+ * @returns The authentication token response.
444
+ *
445
+ * @example
446
+ * ```ts
447
+ * // View access (read-only) — sufficient for seller.content.list/search/get
448
+ * await lw.seller.loginWithApiKey({ key: 'your_api_key' })
449
+ *
450
+ * // Full access (read/write)
451
+ * await lw.seller.loginWithApiKey({ key: 'your_api_key', secret: 'your_secret' })
452
+ * ```
453
+ */
454
+ async loginWithApiKey(e) {
455
+ const t = await this.http.post("/v1/auth/login/api-key", e);
456
+ return await this.tokenManager.setTokens({
457
+ accessToken: t.access_token,
458
+ refreshToken: t.refresh_token,
459
+ expiresAt: p(t.expires_at)
460
+ }), t;
394
461
  }
395
462
  }
396
- class b {
463
+ class N {
397
464
  constructor(e) {
398
465
  this.http = e;
399
466
  }
@@ -432,7 +499,7 @@ class b {
432
499
  return this.http.get(`/v1/wallet/payment-status/${e}`);
433
500
  }
434
501
  }
435
- class P {
502
+ class _ {
436
503
  constructor(e) {
437
504
  this.http = e;
438
505
  }
@@ -451,8 +518,8 @@ class P {
451
518
  return this.http.get(`/v1/checkout/state/${e}`);
452
519
  }
453
520
  }
454
- function C(s) {
455
- const e = s.baseUrl ?? "https://api.ledewire.com", t = s.storage ?? new m(), r = new y({
521
+ function q(s) {
522
+ const e = s.baseUrl ?? "https://api.ledewire.com", t = s.storage ?? new A(), r = new E({
456
523
  storage: t,
457
524
  refreshFn: async (h) => {
458
525
  const i = await fetch(`${e}/v1/auth/token/refresh`, {
@@ -465,23 +532,23 @@ function C(s) {
465
532
  return {
466
533
  accessToken: a.access_token,
467
534
  refreshToken: a.refresh_token,
468
- expiresAt: l(a.expires_at)
535
+ expiresAt: p(a.expires_at)
469
536
  };
470
537
  },
471
538
  ...s.onAuthExpired !== void 0 && { onAuthExpired: s.onAuthExpired }
472
- }), o = new f({
539
+ }), o = new y({
473
540
  baseUrl: e,
474
541
  getAccessToken: () => r.getAccessToken(),
475
542
  onUnauthorized: () => r.handleUnauthorized()
476
543
  });
477
- return new N(o, r, s);
544
+ return new R(o, r, s);
478
545
  }
479
- class N {
546
+ class R {
480
547
  /** @internal */
481
548
  constructor(e, t, r) {
482
549
  /** Platform-level public configuration (no auth required) */
483
550
  n(this, "config");
484
- /** Buyer authentication: email/password signup/login, Google, password reset */
551
+ /** Buyer authentication: email/password signup/login, Google OAuth, password reset */
485
552
  n(this, "auth");
486
553
  /** Checkout state machine: determines next action for a piece of content */
487
554
  n(this, "checkout");
@@ -491,13 +558,13 @@ class N {
491
558
  n(this, "purchases");
492
559
  /** Public content with per-user access information */
493
560
  n(this, "content");
494
- /** Seller content: list, search, and get (requires API key view token) */
561
+ /** Seller operations: API key login, content list/search/get */
495
562
  n(this, "seller");
496
- 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);
563
+ this._http = e, this._tokenManager = t, this._config = r, this.config = new v(e), this.auth = new S(e, t), this.checkout = new _(e), this.wallet = new N(e), this.purchases = new b(e), this.content = new x(e), this.seller = new P(e, t);
497
564
  }
498
565
  }
499
- const R = "lw:tokens";
500
- function B(s = R) {
566
+ const F = "lw:tokens";
567
+ function L(s = F) {
501
568
  return {
502
569
  getTokens() {
503
570
  const e = localStorage.getItem(s);
@@ -516,15 +583,36 @@ function B(s = R) {
516
583
  }
517
584
  };
518
585
  }
586
+ const O = "lw:tokens";
587
+ function M(s = O) {
588
+ return {
589
+ getTokens() {
590
+ const e = sessionStorage.getItem(s);
591
+ if (!e) return null;
592
+ try {
593
+ return JSON.parse(e);
594
+ } catch {
595
+ return null;
596
+ }
597
+ },
598
+ setTokens(e) {
599
+ sessionStorage.setItem(s, JSON.stringify(e));
600
+ },
601
+ clearTokens() {
602
+ sessionStorage.removeItem(s);
603
+ }
604
+ };
605
+ }
519
606
  export {
520
- u as AuthError,
521
- d as ForbiddenError,
607
+ l as AuthError,
608
+ k as ForbiddenError,
522
609
  c as LedewireError,
523
- m as MemoryTokenStorage,
524
- g as NotFoundError,
525
- $ as PurchaseError,
526
- C as init,
527
- B as localStorageAdapter,
528
- l as parseExpiresAt
610
+ A as MemoryTokenStorage,
611
+ f as NotFoundError,
612
+ B as PurchaseError,
613
+ q as init,
614
+ L as localStorageAdapter,
615
+ p as parseExpiresAt,
616
+ M as sessionStorageAdapter
529
617
  };
530
618
  //# sourceMappingURL=index.js.map