@ansango/lastfm-api 3.1.3 → 3.2.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.
Files changed (168) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +165 -15
  3. package/dist/client.d.ts +1 -1
  4. package/dist/client.d.ts.map +1 -1
  5. package/dist/client.js +2 -2
  6. package/dist/client.js.map +1 -1
  7. package/dist/config.d.ts.map +1 -1
  8. package/dist/config.js +2 -2
  9. package/dist/config.js.map +1 -1
  10. package/dist/entrypoints/album.d.ts +1 -1
  11. package/dist/entrypoints/album.d.ts.map +1 -1
  12. package/dist/entrypoints/album.js.map +1 -1
  13. package/dist/entrypoints/album.schemas.d.ts.map +1 -1
  14. package/dist/entrypoints/album.schemas.js.map +1 -1
  15. package/dist/entrypoints/artist.d.ts +1 -1
  16. package/dist/entrypoints/artist.d.ts.map +1 -1
  17. package/dist/entrypoints/artist.js.map +1 -1
  18. package/dist/entrypoints/artist.schemas.d.ts.map +1 -1
  19. package/dist/entrypoints/artist.schemas.js.map +1 -1
  20. package/dist/entrypoints/auth.d.ts +1 -1
  21. package/dist/entrypoints/auth.d.ts.map +1 -1
  22. package/dist/entrypoints/auth.js.map +1 -1
  23. package/dist/entrypoints/auth.schemas.d.ts.map +1 -1
  24. package/dist/entrypoints/auth.schemas.js.map +1 -1
  25. package/dist/entrypoints/base.schemas.d.ts.map +1 -1
  26. package/dist/entrypoints/base.schemas.js.map +1 -1
  27. package/dist/entrypoints/chart.d.ts +1 -1
  28. package/dist/entrypoints/chart.d.ts.map +1 -1
  29. package/dist/entrypoints/chart.js.map +1 -1
  30. package/dist/entrypoints/chart.schemas.d.ts.map +1 -1
  31. package/dist/entrypoints/chart.schemas.js.map +1 -1
  32. package/dist/entrypoints/geo.d.ts.map +1 -1
  33. package/dist/entrypoints/geo.js.map +1 -1
  34. package/dist/entrypoints/geo.schemas.d.ts.map +1 -1
  35. package/dist/entrypoints/geo.schemas.js.map +1 -1
  36. package/dist/entrypoints/library.d.ts.map +1 -1
  37. package/dist/entrypoints/library.js.map +1 -1
  38. package/dist/entrypoints/library.schemas.d.ts.map +1 -1
  39. package/dist/entrypoints/library.schemas.js.map +1 -1
  40. package/dist/entrypoints/tag.d.ts.map +1 -1
  41. package/dist/entrypoints/tag.js.map +1 -1
  42. package/dist/entrypoints/tag.schemas.d.ts.map +1 -1
  43. package/dist/entrypoints/tag.schemas.js.map +1 -1
  44. package/dist/entrypoints/track.d.ts.map +1 -1
  45. package/dist/entrypoints/track.js.map +1 -1
  46. package/dist/entrypoints/track.schemas.d.ts.map +1 -1
  47. package/dist/entrypoints/track.schemas.js.map +1 -1
  48. package/dist/entrypoints/user.d.ts.map +1 -1
  49. package/dist/entrypoints/user.js.map +1 -1
  50. package/dist/entrypoints/user.schemas.d.ts.map +1 -1
  51. package/dist/entrypoints/user.schemas.js.map +1 -1
  52. package/dist/index.d.ts +18 -18
  53. package/dist/index.d.ts.map +1 -1
  54. package/dist/index.js +10 -10
  55. package/dist/index.js.map +1 -1
  56. package/dist/services/album.d.ts +43 -1
  57. package/dist/services/album.d.ts.map +1 -1
  58. package/dist/services/album.js +35 -2
  59. package/dist/services/album.js.map +1 -1
  60. package/dist/services/album.schemas.d.ts +51 -12
  61. package/dist/services/album.schemas.d.ts.map +1 -1
  62. package/dist/services/album.schemas.js +48 -10
  63. package/dist/services/album.schemas.js.map +1 -1
  64. package/dist/services/artist.d.ts +50 -1
  65. package/dist/services/artist.d.ts.map +1 -1
  66. package/dist/services/artist.js +34 -2
  67. package/dist/services/artist.js.map +1 -1
  68. package/dist/services/artist.schemas.d.ts +99 -25
  69. package/dist/services/artist.schemas.d.ts.map +1 -1
  70. package/dist/services/artist.schemas.js +125 -60
  71. package/dist/services/artist.schemas.js.map +1 -1
  72. package/dist/services/auth.d.ts +72 -1
  73. package/dist/services/auth.d.ts.map +1 -1
  74. package/dist/services/auth.js +37 -2
  75. package/dist/services/auth.js.map +1 -1
  76. package/dist/services/auth.schemas.d.ts +23 -1
  77. package/dist/services/auth.schemas.d.ts.map +1 -1
  78. package/dist/services/auth.schemas.js +20 -2
  79. package/dist/services/auth.schemas.js.map +1 -1
  80. package/dist/services/chart.d.ts +1 -1
  81. package/dist/services/chart.d.ts.map +1 -1
  82. package/dist/services/chart.js +2 -2
  83. package/dist/services/chart.js.map +1 -1
  84. package/dist/services/chart.schemas.d.ts +6 -6
  85. package/dist/services/chart.schemas.d.ts.map +1 -1
  86. package/dist/services/chart.schemas.js +21 -21
  87. package/dist/services/chart.schemas.js.map +1 -1
  88. package/dist/services/geo.d.ts +1 -1
  89. package/dist/services/geo.d.ts.map +1 -1
  90. package/dist/services/geo.js +2 -2
  91. package/dist/services/geo.js.map +1 -1
  92. package/dist/services/geo.schemas.d.ts +6 -6
  93. package/dist/services/geo.schemas.d.ts.map +1 -1
  94. package/dist/services/geo.schemas.js +17 -17
  95. package/dist/services/geo.schemas.js.map +1 -1
  96. package/dist/services/index.d.ts +12 -12
  97. package/dist/services/index.d.ts.map +1 -1
  98. package/dist/services/index.js +13 -13
  99. package/dist/services/index.js.map +1 -1
  100. package/dist/services/library.d.ts +1 -1
  101. package/dist/services/library.d.ts.map +1 -1
  102. package/dist/services/library.js +2 -2
  103. package/dist/services/library.js.map +1 -1
  104. package/dist/services/library.schemas.d.ts +3 -3
  105. package/dist/services/library.schemas.d.ts.map +1 -1
  106. package/dist/services/library.schemas.js +8 -8
  107. package/dist/services/library.schemas.js.map +1 -1
  108. package/dist/services/schemas/base.entities.schemas.d.ts +3 -3
  109. package/dist/services/schemas/base.entities.schemas.d.ts.map +1 -1
  110. package/dist/services/schemas/base.entities.schemas.js +9 -9
  111. package/dist/services/schemas/base.entities.schemas.js.map +1 -1
  112. package/dist/services/schemas/base.entity-names.schemas.d.ts +1 -1
  113. package/dist/services/schemas/base.entity-names.schemas.d.ts.map +1 -1
  114. package/dist/services/schemas/base.entity-names.schemas.js +1 -1
  115. package/dist/services/schemas/base.entity-names.schemas.js.map +1 -1
  116. package/dist/services/schemas/base.metadata.schemas.d.ts +1 -1
  117. package/dist/services/schemas/base.metadata.schemas.d.ts.map +1 -1
  118. package/dist/services/schemas/base.metadata.schemas.js +1 -1
  119. package/dist/services/schemas/base.metadata.schemas.js.map +1 -1
  120. package/dist/services/schemas/base.pagination.schemas.d.ts +1 -1
  121. package/dist/services/schemas/base.pagination.schemas.d.ts.map +1 -1
  122. package/dist/services/schemas/base.pagination.schemas.js +1 -1
  123. package/dist/services/schemas/base.pagination.schemas.js.map +1 -1
  124. package/dist/services/schemas/base.primitives.schemas.d.ts +3 -1
  125. package/dist/services/schemas/base.primitives.schemas.d.ts.map +1 -1
  126. package/dist/services/schemas/base.primitives.schemas.js +8 -7
  127. package/dist/services/schemas/base.primitives.schemas.js.map +1 -1
  128. package/dist/services/schemas/index.d.ts +5 -5
  129. package/dist/services/schemas/index.d.ts.map +1 -1
  130. package/dist/services/schemas/index.js +5 -5
  131. package/dist/services/schemas/index.js.map +1 -1
  132. package/dist/services/tag.d.ts +1 -1
  133. package/dist/services/tag.d.ts.map +1 -1
  134. package/dist/services/tag.js +2 -2
  135. package/dist/services/tag.js.map +1 -1
  136. package/dist/services/tag.schemas.d.ts +13 -13
  137. package/dist/services/tag.schemas.d.ts.map +1 -1
  138. package/dist/services/tag.schemas.js +50 -50
  139. package/dist/services/tag.schemas.js.map +1 -1
  140. package/dist/services/track.d.ts +128 -4
  141. package/dist/services/track.d.ts.map +1 -1
  142. package/dist/services/track.js +79 -10
  143. package/dist/services/track.js.map +1 -1
  144. package/dist/services/track.schemas.d.ts +213 -25
  145. package/dist/services/track.schemas.d.ts.map +1 -1
  146. package/dist/services/track.schemas.js +206 -57
  147. package/dist/services/track.schemas.js.map +1 -1
  148. package/dist/services/track.utils.d.ts +16 -7
  149. package/dist/services/track.utils.d.ts.map +1 -1
  150. package/dist/services/track.utils.js +49 -48
  151. package/dist/services/track.utils.js.map +1 -1
  152. package/dist/services/user.d.ts +19 -1
  153. package/dist/services/user.d.ts.map +1 -1
  154. package/dist/services/user.js +3 -2
  155. package/dist/services/user.js.map +1 -1
  156. package/dist/services/user.schemas.d.ts +321 -63
  157. package/dist/services/user.schemas.d.ts.map +1 -1
  158. package/dist/services/user.schemas.js +197 -88
  159. package/dist/services/user.schemas.js.map +1 -1
  160. package/dist/utils.d.ts +37 -2
  161. package/dist/utils.d.ts.map +1 -1
  162. package/dist/utils.js +105 -20
  163. package/dist/utils.js.map +1 -1
  164. package/package.json +167 -154
  165. package/dist/__tests__/utils.test.d.ts +0 -2
  166. package/dist/__tests__/utils.test.d.ts.map +0 -1
  167. package/dist/__tests__/utils.test.js +0 -86
  168. package/dist/__tests__/utils.test.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -9,6 +9,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
  > [ansango/lastfm-api](https://github.com/ansango/lastfm-api). Entries below preserve the
10
10
  > historical package and repository names used by their original releases.
11
11
 
12
+ ## [3.2.0] - 2026-08-28
13
+
14
+ ### ✨ Features
15
+
16
+ - **tool**: surface `x-lastfm-sk` header on the 10 POST signed methods in Scalar's "Try it" form (#100) ([b904451](https://github.com/ansango/lastfm-api/commit/b904451))
17
+
18
+ ### 📚 Documentation
19
+
20
+ - document `sk` parameter and the browser auth flow on the 10 write methods (JSDoc + README) (#101) ([49c10da](https://github.com/ansango/lastfm-api/commit/49c10da))
21
+ - add Callback URL setup prerequisite to README and Scalar auth tag (#110) ([c64410d](https://github.com/ansango/lastfm-api/commit/c64410d))
22
+ - deprecate `auth.getMobileSession` and reorient the auth flow to lead with the web flow (#105) ([4446f10](https://github.com/ansango/lastfm-api/commit/4446f10))
23
+
24
+ ### 🛠️ Tooling
25
+
26
+ - friendly startup error when `LASTFM_API_KEY` is missing (#103) ([cca87a2](https://github.com/ansango/lastfm-api/commit/cca87a2))
27
+ - add Biome for lint + format, replace unused Prettier config (#111) ([071c1e7](https://github.com/ansango/lastfm-api/commit/071c1e7))
28
+
29
+
12
30
  ## [3.1.3] - 2026-08-02
13
31
 
14
32
  ### 📚 Documentation
package/README.md CHANGED
@@ -14,6 +14,7 @@ A universal Last.fm API client for Node.js and Browser, written in TypeScript.
14
14
  ## Features
15
15
 
16
16
  - ✅ **Universal**: Works in Node.js (≥20.0.0) and Browser
17
+ - ✅ **Complete coverage**: All 57 canonical Last.fm API methods across 9 namespaces
17
18
  - ✅ **TypeScript**: Full type safety with comprehensive type definitions
18
19
  - ✅ **Zod Schemas**: Runtime validation schemas for all types
19
20
  - ✅ **ESM**: Modern ES modules with tree-shaking support
@@ -128,6 +129,31 @@ const libraryArtists = await client.library.getArtists({ user: 'ansango' });
128
129
 
129
130
  // Auth service (for scrobbling and authenticated methods)
130
131
  const session = await client.auth.getSession({ token: 'AUTH_TOKEN' });
132
+ // Request an auth token (signed GET, no sk)
133
+ const { token } = await client.auth.getToken();
134
+ // Username/password login (signed POST, no sk) — server-side / trusted only
135
+ const { session: mobileSession } = await client.auth.getMobileSession({
136
+ username: 'someone',
137
+ password: process.env.LASTFM_PASSWORD!
138
+ });
139
+
140
+ // Now-playing and tag/love mutations (all require an authenticated session)
141
+ await client.track.updateNowPlaying({
142
+ artist: 'Cher',
143
+ track: 'Believe',
144
+ album: 'Believe',
145
+ duration: 240
146
+ });
147
+
148
+ await client.track.addTags({
149
+ artist: 'Cher',
150
+ track: 'Believe',
151
+ tags: ['favorites', '90s']
152
+ });
153
+ await client.track.love({ artist: 'Cher', track: 'Believe' });
154
+
155
+ await client.album.addTags({ artist: 'Cher', album: 'Believe', tags: ['favorites'] });
156
+ await client.artist.addTags({ artist: 'Cher', tags: ['favorites'] });
131
157
  ```
132
158
 
133
159
  ### Using Global Configuration
@@ -282,24 +308,96 @@ const client = new LastFmClient({
282
308
 
283
309
  ## Authentication & Scrobbling
284
310
 
285
- Methods that mutate user state (`track.scrobble`, `track.scrobbleMany`, plus future write methods) require an authenticated session. Get one with `client.auth.getSession({ token })` after the user authorizes the token in a browser. Once you have a session key, pass it as `sessionKey` in your config — the client injects it into every authenticated call.
311
+ Methods that mutate user state require an authenticated session. The full list of write methods is:
312
+
313
+ - `auth.getSession`, `auth.getToken`, `auth.getMobileSession`
314
+ - `track.scrobble`, `track.updateNowPlaying`
315
+ - `track.addTags`, `track.removeTag`, `track.love`, `track.unlove`
316
+ - `album.addTags`, `album.removeTag`
317
+ - `artist.addTags`, `artist.removeTag`
318
+
319
+ There are two paths to obtain a session key — pick the one that matches your Last.fm API key's app classification. The browser flow below works for **every** self-service API key; the mobile flow only works for mobile-classified keys, which Last.fm does not expose through the public create form.
320
+
321
+ ### Browser flow (recommended — works for all self-service keys)
322
+
323
+ The browser flow is the canonical Last.fm auth path and works with the API key every self-service user gets from <https://www.last.fm/api/account/create>.
286
324
 
287
325
  ```typescript
288
326
  import { LastFmClient } from '@ansango/lastfm-api';
289
327
 
328
+ // 1. Get a request token (signed GET, no session needed).
329
+ const client = new LastFmClient({
330
+ apiKey: process.env.LASTFM_API_KEY!,
331
+ sharedSecret: process.env.LASTFM_SHARED_SECRET!,
332
+ });
333
+ const { token } = await client.auth.getToken();
334
+
335
+ // 2. Direct the user to authorize the token in a browser:
336
+ // https://www.last.fm/api/auth/?api_key=<KEY>&token=<token>
337
+ // After authorizing, Last.fm redirects to the callback URL configured
338
+ // on the API account (the token appears in the URL).
339
+
340
+ // 3. Exchange the authorized token for a session key.
341
+ const { session } = await client.auth.getSession({ token });
342
+ const sessionKey = session.key; // pass this to write methods
343
+ ```
344
+
345
+ ### Callback URL setup (one-time, in your Last.fm account)
346
+
347
+ Before the browser flow works end-to-end, set a callback URL on your API account at <https://www.last.fm/api/account>:
348
+
349
+ 1. Open <https://www.last.fm/api/account>, find your app, click **Edit**.
350
+ 2. In the **Callback URL** field, enter a URL.
351
+ 3. Save.
352
+
353
+ **What to enter depends on how you'll consume the token:**
354
+
355
+ - **Manual flow (default):** any URL works. Last.fm redirects there with `?token=<token>` in the URL bar; you copy the token by hand. Examples that are valid: `http://example.com/`, `http://localhost:3000/`, even `oops`. The URL is just a destination.
356
+ - **Auto-catch flow (with a local server, e.g. `lastfm-cli`'s `--callback` flag):** set it to the URL where your local server listens. Default for the CLI is `http://127.0.0.1:8765/`. Use `127.0.0.1`, not `localhost` — Last.fm's redirect host matching is strict.
357
+
358
+ If you skip this step, the redirect after **Allow access** lands on a Last.fm error page instead of your URL, and the token is lost. You have to call `auth.getToken` again and re-authorize.
359
+
360
+ ### Mobile flow (mobile-class API keys only)
361
+
362
+ `auth.getMobileSession` exchanges a username + password for a session key in a single call, but it only works for API keys classified as **mobile / standalone** in the API account settings. Last.fm's self-service create form does not expose this classification; every new key is a web key by default. If you registered your key as a web app, this method will fail with `error: 4 — Authentication Failed`. To get a mobile-class key, you need to email `partners@last.fm` and ask for a reclassification.
363
+
364
+ ```typescript
365
+ // Only works for mobile-class API keys.
366
+ const { session } = await client.auth.getMobileSession({
367
+ username: process.env.LASTFM_USERNAME!,
368
+ password: process.env.LASTFM_PASSWORD!,
369
+ });
370
+ ```
371
+
372
+ ### Passing the session key to write methods
373
+
374
+ Once you have a session key, you can pass it in two ways:
375
+
376
+ - **Per-request** (`params.sk`): preferred for ad-hoc calls or one-off scripts.
377
+ - **On the `LastFmConfig`** (`sessionKey`): preferred for long-lived clients; the transport injects it into every signed call automatically.
378
+
379
+ ```typescript
380
+ // Option A: session key in the config (recommended for long-lived clients).
290
381
  const client = new LastFmClient({
291
382
  apiKey: process.env.LASTFM_API_KEY!,
292
383
  sharedSecret: process.env.LASTFM_SHARED_SECRET!,
293
384
  sessionKey: process.env.LASTFM_SESSION_KEY!,
294
385
  });
295
386
 
296
- // Scrobble a track — `sk` is auto-injected from `config.sessionKey`,
297
- // so you don't need to pass it explicitly.
387
+ // `sk` is auto-injected from config.sessionKey; you don't need to pass it.
298
388
  await client.track.scrobble({
299
389
  artist: 'Cher',
300
390
  track: 'Believe',
301
391
  timestamp: Math.floor(Date.now() / 1000),
302
392
  });
393
+
394
+ // Option B: session key per-request (preferred for ad-hoc calls).
395
+ await client.track.scrobble({
396
+ artist: 'Cher',
397
+ track: 'Believe',
398
+ timestamp: Math.floor(Date.now() / 1000),
399
+ sk: 'paste-the-session-key-here',
400
+ });
303
401
  ```
304
402
 
305
403
  > **Note:** The previous method names `postTrackScrobble` and `postBatchTrackScrobble` are still available as deprecated aliases. They forward to `scrobble` and `scrobbleMany` respectively and will be removed in the next major release.
@@ -367,17 +465,19 @@ function resetGlobalConfig(): void;
367
465
 
368
466
  ### Services
369
467
 
370
- Each service provides methods for interacting with specific Last.fm API endpoints:
468
+ The package covers all 57 canonical Last.fm API methods across 9 namespaces. See [docs/api-coverage.md](docs/api-coverage.md) for the full table.
469
+
470
+ - **UserService**: 13 methods — `getInfo`, `getFriends`, `getLovedTracks`, `getRecentTracks`, `getTopAlbums`, `getTopArtists`, `getTopTags`, `getTopTracks`, `getWeeklyAlbumChart`, `getWeeklyArtistChart`, `getWeeklyChartList`, `getWeeklyTrackChart`, `getPersonalTags`
471
+ - **AlbumService**: 6 methods — `getInfo`, `getTags`, `getTopTags`, `search`, `addTags`¹, `removeTag`¹
472
+ - **ArtistService**: 10 methods — `getInfo`, `getTags`, `getSimilar`, `getTopTags`, `getTopAlbums`, `getTopTracks`, `search`, `getCorrection`, `addTags`¹, `removeTag`¹
473
+ - **TrackService**: 12 methods — `getInfo`, `getSimilar`, `getTags`, `getTopTags`, `search`, `scrobble`¹, `getCorrection`, `addTags`¹, `removeTag`¹, `love`¹, `unlove`¹, `updateNowPlaying`¹
474
+ - **TagService**: 7 methods — `getInfo`, `getSimilar`, `getTopAlbums`, `getTopArtists`, `getTopTags`, `getTopTracks`, `getWeeklyChartList`
475
+ - **ChartService**: 3 methods — `getTopArtists`, `getTopTags`, `getTopTracks`
476
+ - **GeoService**: 2 methods — `getTopArtists`, `getTopTracks`
477
+ - **LibraryService**: 1 method — `getArtists`
478
+ - **AuthService**: 3 methods — `getSession`, `getToken`, `getMobileSession`¹
371
479
 
372
- - **UserService**: User-related methods (getInfo, getTopArtists, getRecentTracks, etc.)
373
- - **AlbumService**: Album methods (getInfo, search, getTags, etc.)
374
- - **ArtistService**: Artist methods (getInfo, getSimilar, getTopAlbums, etc.)
375
- - **TrackService**: Track methods (getInfo, search, scrobble, scrobbleMany, etc.)
376
- - **TagService**: Tag methods (getInfo, getTopArtists, getTopTracks, etc.)
377
- - **ChartService**: Chart methods (getTopArtists, getTopTracks, etc.)
378
- - **GeoService**: Geographic methods (getTopArtists, getTopTracks by country)
379
- - **LibraryService**: Library methods (getArtists, etc.)
380
- - **AuthService**: Authentication methods (getSession, etc.)
480
+ ¹ Requires an authenticated session.
381
481
 
382
482
  ## TypeScript Support
383
483
 
@@ -426,13 +526,63 @@ bun run dev
426
526
  # Build the project
427
527
  bun run build
428
528
 
429
- # Run tests
430
- bun test
529
+ # Typecheck (no emit)
530
+ bun run typecheck
531
+
532
+ # Run deterministic unit tests (no network, mocked fetch)
533
+ bun run test:unit
534
+
535
+ # Run live integration (requires Last.fm credentials in .env)
536
+ bun run test:integration:live
537
+
538
+ # Lint (Biome — formatter + linter, single command)
539
+ bun run lint
540
+
541
+ # Auto-fix what Biome can (formatting, safe lint fixes)
542
+ bun run lint:fix
543
+
544
+ # Format only (no lint)
545
+ bun run format
546
+ bun run format:check
547
+
548
+ # Run the local interactive docs server (Hono + Scalar, see #92)
549
+ bun run tool:dev
431
550
 
432
551
  # Clean build artifacts
433
552
  bun run clean
434
553
  ```
435
554
 
555
+ ## Interactive API Explorer
556
+
557
+ The repo ships with a local Hono + Scalar server under `tool/api-scalar/`
558
+ that turns the package into a fully interactive OpenAPI explorer. All 57
559
+ canonical Last.fm methods are wired declaratively from the package's own
560
+ Zod schemas and service functions — no method is hand-written, no schema
561
+ is duplicated.
562
+
563
+ ```sh
564
+ bun install --cwd tool/api-scalar
565
+ cp tool/api-scalar/.env.example .env # fill in LASTFM_API_KEY and LASTFM_SHARED_SECRET
566
+ bun run tool:dev
567
+ ```
568
+
569
+ Then open <http://localhost:3000>. "Try it" calls the real Last.fm API
570
+ through the package; the shared secret and session key live in env vars,
571
+ never in the browser. See [`tool/api-scalar/README.md`](./tool/api-scalar/README.md)
572
+ for the full guide and [`#92`](https://github.com/ansango/lastfm-api/issues/92)
573
+ for the design notes.
574
+
575
+ ### Testing
576
+
577
+ The test suite is split into two layers:
578
+
579
+ - **`bun run test:unit`** — deterministic tests with mocked `globalThis.fetch`. They cover every canonical Last.fm method that the package implements, assert the correct `namespace.method` routing, validate that `api_key`/`format=json` are present, and verify that Last.fm error envelopes surface as `LastFmApiError`. They do not require an API key or any network access, and they run as part of CI on every push and pull request.
580
+ - **`bun run test:integration:live`** — runs `test-real.ts` against the real Last.fm API. It is **not** part of CI and must be invoked manually by a developer with valid credentials in `.env`.
581
+
582
+ The `bun test` alias points to the deterministic suite, so a normal `bun test` is safe to run anywhere.
583
+
584
+ An `inventory.test.ts` file asserts the **57/57 canonical-method baseline** — every namespace.method pair listed in the official Last.fm API index is exposed on the `LastFmClient` and callable. The per-namespace breakdown is mirrored in [docs/api-coverage.md](docs/api-coverage.md) and stays in sync with the inventory test.
585
+
436
586
  ### Release Process
437
587
 
438
588
  This project uses automated release scripts:
package/dist/client.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { LastFmConfig } from './config.js';
2
- import { type UserService, type AlbumService, type ArtistService, type TrackService, type TagService, type ChartService, type GeoService, type LibraryService, type AuthService } from './services/index.js';
2
+ import { type AlbumService, type ArtistService, type AuthService, type ChartService, type GeoService, type LibraryService, type TagService, type TrackService, type UserService } from './services/index.js';
3
3
  /**
4
4
  * Last.fm API Client
5
5
  *
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,EAUN,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,YAAY;IACxB,SAAgB,IAAI,EAAE,WAAW,CAAC;IAClC,SAAgB,KAAK,EAAE,YAAY,CAAC;IACpC,SAAgB,MAAM,EAAE,aAAa,CAAC;IACtC,SAAgB,KAAK,EAAE,YAAY,CAAC;IACpC,SAAgB,GAAG,EAAE,UAAU,CAAC;IAChC,SAAgB,KAAK,EAAE,YAAY,CAAC;IACpC,SAAgB,GAAG,EAAE,UAAU,CAAC;IAChC,SAAgB,OAAO,EAAE,cAAc,CAAC;IACxC,SAAgB,IAAI,EAAE,WAAW,CAAC;IAElC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;gBAE1B,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC;IAe1C;;OAEG;IACH,SAAS,IAAI,QAAQ,CAAC,YAAY,CAAC;CAGnC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY,CAEzE"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE/C,OAAO,EACN,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,YAAY,EAUjB,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,MAAM,qBAAqB,CAAA;AAE5B;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,YAAY;IACxB,SAAgB,IAAI,EAAE,WAAW,CAAA;IACjC,SAAgB,KAAK,EAAE,YAAY,CAAA;IACnC,SAAgB,MAAM,EAAE,aAAa,CAAA;IACrC,SAAgB,KAAK,EAAE,YAAY,CAAA;IACnC,SAAgB,GAAG,EAAE,UAAU,CAAA;IAC/B,SAAgB,KAAK,EAAE,YAAY,CAAA;IACnC,SAAgB,GAAG,EAAE,UAAU,CAAA;IAC/B,SAAgB,OAAO,EAAE,cAAc,CAAA;IACvC,SAAgB,IAAI,EAAE,WAAW,CAAA;IAEjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;gBAEzB,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC;IAe1C;;OAEG;IACH,SAAS,IAAI,QAAQ,CAAC,YAAY,CAAC;CAGnC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY,CAEzE"}
package/dist/client.js CHANGED
@@ -1,5 +1,5 @@
1
- import { getGlobalConfig, createConfig } from './config.js';
2
- import { createUserService, createAlbumService, createArtistService, createTrackService, createTagService, createChartService, createGeoService, createLibraryService, createAuthService } from './services/index.js';
1
+ import { createConfig, getGlobalConfig } from './config.js';
2
+ import { createAlbumService, createArtistService, createAuthService, createChartService, createGeoService, createLibraryService, createTagService, createTrackService, createUserService, } from './services/index.js';
3
3
  /**
4
4
  * Last.fm API Client
5
5
  *
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EACN,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,EAUjB,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,OAAO,YAAY;IACR,IAAI,CAAc;IAClB,KAAK,CAAe;IACpB,MAAM,CAAgB;IACtB,KAAK,CAAe;IACpB,GAAG,CAAa;IAChB,KAAK,CAAe;IACpB,GAAG,CAAa;IAChB,OAAO,CAAiB;IACxB,IAAI,CAAc;IAEjB,MAAM,CAAe;IAEtC,YAAY,MAA8B;QACzC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC;QAEhE,0BAA0B;QAC1B,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC3C,IAAI,CAAC,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC7C,IAAI,CAAC,MAAM,GAAG,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC/C,IAAI,CAAC,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC7C,IAAI,CAAC,GAAG,GAAG,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,CAAC,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC7C,IAAI,CAAC,GAAG,GAAG,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,CAAC,OAAO,GAAG,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACjD,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5C,CAAC;IAED;;OAEG;IACH,SAAS;QACR,OAAO,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;IAC3B,CAAC;CACD;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY,CAAC,MAA8B;IAC1D,OAAO,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC;AACjC,CAAC"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC3D,OAAO,EAKN,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,GAMjB,MAAM,qBAAqB,CAAA;AAE5B;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,OAAO,YAAY;IACR,IAAI,CAAa;IACjB,KAAK,CAAc;IACnB,MAAM,CAAe;IACrB,KAAK,CAAc;IACnB,GAAG,CAAY;IACf,KAAK,CAAc;IACnB,GAAG,CAAY;IACf,OAAO,CAAgB;IACvB,IAAI,CAAa;IAEhB,MAAM,CAAc;IAErC,YAAY,MAA8B;QACzC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,eAAe,EAAE,CAAA;QAE/D,0BAA0B;QAC1B,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAC1C,IAAI,CAAC,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAC5C,IAAI,CAAC,MAAM,GAAG,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAC9C,IAAI,CAAC,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAC5C,IAAI,CAAC,GAAG,GAAG,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACxC,IAAI,CAAC,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAC5C,IAAI,CAAC,GAAG,GAAG,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACxC,IAAI,CAAC,OAAO,GAAG,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAChD,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAC3C,CAAC;IAED;;OAEG;IACH,SAAS;QACR,OAAO,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAA;IAC1B,CAAC;CACD;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY,CAAC,MAA8B;IAC1D,OAAO,IAAI,YAAY,CAAC,MAAM,CAAC,CAAA;AAChC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AA+BD;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,OAAO,CAAC,YAAY,CAAM,GAAG,YAAY,CAU9E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,IAAI,CAEnE;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,YAAY,CAK9C;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,OAAO,CAAC,EAAE,MAAM,CAAA;CAChB;AA6BD;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,OAAO,CAAC,YAAY,CAAM,GAAG,YAAY,CAU9E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,IAAI,CAEnE;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,YAAY,CAK9C;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
package/dist/config.js CHANGED
@@ -8,7 +8,7 @@ function loadEnvConfig() {
8
8
  apiKey: process.env.LASTFM_API_KEY,
9
9
  sharedSecret: process.env.LASTFM_SHARED_SECRET,
10
10
  sessionKey: process.env.LASTFM_SESSION_KEY,
11
- baseUrl: process.env.LASTFM_BASE_URL
11
+ baseUrl: process.env.LASTFM_BASE_URL,
12
12
  };
13
13
  }
14
14
  return {};
@@ -30,7 +30,7 @@ export function createConfig(options = {}) {
30
30
  const config = {
31
31
  baseUrl: 'https://ws.audioscrobbler.com/2.0/',
32
32
  ...envConfig,
33
- ...options
33
+ ...options,
34
34
  };
35
35
  validateConfig(config);
36
36
  return config;
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAOA,IAAI,YAAY,GAAwB,IAAI,CAAC;AAE7C;;GAEG;AACH,SAAS,aAAa;IACrB,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QACnD,OAAO;YACN,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc;YAClC,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,oBAAoB;YAC9C,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB;YAC1C,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe;SACpC,CAAC;IACH,CAAC;IACD,OAAO,EAAE,CAAC;AACX,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,MAA6B;IACpD,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CACd,4FAA4F,CAC5F,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,UAAiC,EAAE;IAC/D,MAAM,SAAS,GAAG,aAAa,EAAE,CAAC;IAClC,MAAM,MAAM,GAAG;QACd,OAAO,EAAE,oCAAoC;QAC7C,GAAG,SAAS;QACZ,GAAG,OAAO;KACV,CAAC;IAEF,cAAc,CAAC,MAAM,CAAC,CAAC;IACvB,OAAO,MAAsB,CAAC;AAC/B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,MAA6B;IAC5D,YAAY,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;AACrC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe;IAC9B,IAAI,CAAC,YAAY,EAAE,CAAC;QACnB,YAAY,GAAG,YAAY,EAAE,CAAC;IAC/B,CAAC;IACD,OAAO,YAAY,CAAC;AACrB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB;IAChC,YAAY,GAAG,IAAI,CAAC;AACrB,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAOA,IAAI,YAAY,GAAwB,IAAI,CAAA;AAE5C;;GAEG;AACH,SAAS,aAAa;IACrB,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QACnD,OAAO;YACN,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc;YAClC,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,oBAAoB;YAC9C,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB;YAC1C,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe;SACpC,CAAA;IACF,CAAC;IACD,OAAO,EAAE,CAAA;AACV,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,MAA6B;IACpD,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,4FAA4F,CAAC,CAAA;IAC9G,CAAC;IACD,OAAO,IAAI,CAAA;AACZ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,UAAiC,EAAE;IAC/D,MAAM,SAAS,GAAG,aAAa,EAAE,CAAA;IACjC,MAAM,MAAM,GAAG;QACd,OAAO,EAAE,oCAAoC;QAC7C,GAAG,SAAS;QACZ,GAAG,OAAO;KACV,CAAA;IAED,cAAc,CAAC,MAAM,CAAC,CAAA;IACtB,OAAO,MAAsB,CAAA;AAC9B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,MAA6B;IAC5D,YAAY,GAAG,YAAY,CAAC,MAAM,CAAC,CAAA;AACpC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe;IAC9B,IAAI,CAAC,YAAY,EAAE,CAAC;QACnB,YAAY,GAAG,YAAY,EAAE,CAAA;IAC9B,CAAC;IACD,OAAO,YAAY,CAAA;AACpB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB;IAChC,YAAY,GAAG,IAAI,CAAA;AACpB,CAAC"}
@@ -1,4 +1,4 @@
1
- export { createAlbumService, type AlbumService } from '../services/album.js';
1
+ export { type AlbumService, createAlbumService } from '../services/album.js';
2
2
  export type * from '../services/album.schemas.js';
3
3
  export * from '../services/album.schemas.js';
4
4
  //# sourceMappingURL=album.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"album.d.ts","sourceRoot":"","sources":["../../src/entrypoints/album.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAC7E,mBAAmB,8BAA8B,CAAC;AAClD,cAAc,8BAA8B,CAAC"}
1
+ {"version":3,"file":"album.d.ts","sourceRoot":"","sources":["../../src/entrypoints/album.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAC5E,mBAAmB,8BAA8B,CAAA;AACjD,cAAc,8BAA8B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"album.js","sourceRoot":"","sources":["../../src/entrypoints/album.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAqB,MAAM,sBAAsB,CAAC;AAE7E,cAAc,8BAA8B,CAAC"}
1
+ {"version":3,"file":"album.js","sourceRoot":"","sources":["../../src/entrypoints/album.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAE5E,cAAc,8BAA8B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"album.schemas.d.ts","sourceRoot":"","sources":["../../src/entrypoints/album.schemas.ts"],"names":[],"mappings":"AACA,cAAc,8BAA8B,CAAC"}
1
+ {"version":3,"file":"album.schemas.d.ts","sourceRoot":"","sources":["../../src/entrypoints/album.schemas.ts"],"names":[],"mappings":"AACA,cAAc,8BAA8B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"album.schemas.js","sourceRoot":"","sources":["../../src/entrypoints/album.schemas.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,cAAc,8BAA8B,CAAC"}
1
+ {"version":3,"file":"album.schemas.js","sourceRoot":"","sources":["../../src/entrypoints/album.schemas.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,cAAc,8BAA8B,CAAA"}
@@ -1,4 +1,4 @@
1
- export { createArtistService, type ArtistService } from '../services/artist.js';
1
+ export { type ArtistService, createArtistService } from '../services/artist.js';
2
2
  export type * from '../services/artist.schemas.js';
3
3
  export * from '../services/artist.schemas.js';
4
4
  //# sourceMappingURL=artist.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"artist.d.ts","sourceRoot":"","sources":["../../src/entrypoints/artist.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAChF,mBAAmB,+BAA+B,CAAC;AACnD,cAAc,+BAA+B,CAAC"}
1
+ {"version":3,"file":"artist.d.ts","sourceRoot":"","sources":["../../src/entrypoints/artist.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAC/E,mBAAmB,+BAA+B,CAAA;AAClD,cAAc,+BAA+B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"artist.js","sourceRoot":"","sources":["../../src/entrypoints/artist.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAsB,MAAM,uBAAuB,CAAC;AAEhF,cAAc,+BAA+B,CAAC"}
1
+ {"version":3,"file":"artist.js","sourceRoot":"","sources":["../../src/entrypoints/artist.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAE/E,cAAc,+BAA+B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"artist.schemas.d.ts","sourceRoot":"","sources":["../../src/entrypoints/artist.schemas.ts"],"names":[],"mappings":"AACA,cAAc,+BAA+B,CAAC"}
1
+ {"version":3,"file":"artist.schemas.d.ts","sourceRoot":"","sources":["../../src/entrypoints/artist.schemas.ts"],"names":[],"mappings":"AACA,cAAc,+BAA+B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"artist.schemas.js","sourceRoot":"","sources":["../../src/entrypoints/artist.schemas.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,cAAc,+BAA+B,CAAC"}
1
+ {"version":3,"file":"artist.schemas.js","sourceRoot":"","sources":["../../src/entrypoints/artist.schemas.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,cAAc,+BAA+B,CAAA"}
@@ -1,4 +1,4 @@
1
- export { createAuthService, type AuthService } from '../services/auth.js';
1
+ export { type AuthService, createAuthService } from '../services/auth.js';
2
2
  export type * from '../services/auth.schemas.js';
3
3
  export * from '../services/auth.schemas.js';
4
4
  //# sourceMappingURL=auth.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/entrypoints/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC1E,mBAAmB,6BAA6B,CAAC;AACjD,cAAc,6BAA6B,CAAC"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/entrypoints/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AACzE,mBAAmB,6BAA6B,CAAA;AAChD,cAAc,6BAA6B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/entrypoints/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAoB,MAAM,qBAAqB,CAAC;AAE1E,cAAc,6BAA6B,CAAC"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/entrypoints/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAEzE,cAAc,6BAA6B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"auth.schemas.d.ts","sourceRoot":"","sources":["../../src/entrypoints/auth.schemas.ts"],"names":[],"mappings":"AACA,cAAc,6BAA6B,CAAC"}
1
+ {"version":3,"file":"auth.schemas.d.ts","sourceRoot":"","sources":["../../src/entrypoints/auth.schemas.ts"],"names":[],"mappings":"AACA,cAAc,6BAA6B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"auth.schemas.js","sourceRoot":"","sources":["../../src/entrypoints/auth.schemas.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,cAAc,6BAA6B,CAAC"}
1
+ {"version":3,"file":"auth.schemas.js","sourceRoot":"","sources":["../../src/entrypoints/auth.schemas.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,cAAc,6BAA6B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"base.schemas.d.ts","sourceRoot":"","sources":["../../src/entrypoints/base.schemas.ts"],"names":[],"mappings":"AACA,cAAc,8BAA8B,CAAC"}
1
+ {"version":3,"file":"base.schemas.d.ts","sourceRoot":"","sources":["../../src/entrypoints/base.schemas.ts"],"names":[],"mappings":"AACA,cAAc,8BAA8B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"base.schemas.js","sourceRoot":"","sources":["../../src/entrypoints/base.schemas.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,cAAc,8BAA8B,CAAC"}
1
+ {"version":3,"file":"base.schemas.js","sourceRoot":"","sources":["../../src/entrypoints/base.schemas.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,cAAc,8BAA8B,CAAA"}
@@ -1,4 +1,4 @@
1
- export { createChartService, type ChartService } from '../services/chart.js';
1
+ export { type ChartService, createChartService } from '../services/chart.js';
2
2
  export type * from '../services/chart.schemas.js';
3
3
  export * from '../services/chart.schemas.js';
4
4
  //# sourceMappingURL=chart.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"chart.d.ts","sourceRoot":"","sources":["../../src/entrypoints/chart.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAC7E,mBAAmB,8BAA8B,CAAC;AAClD,cAAc,8BAA8B,CAAC"}
1
+ {"version":3,"file":"chart.d.ts","sourceRoot":"","sources":["../../src/entrypoints/chart.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAC5E,mBAAmB,8BAA8B,CAAA;AACjD,cAAc,8BAA8B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"chart.js","sourceRoot":"","sources":["../../src/entrypoints/chart.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAqB,MAAM,sBAAsB,CAAC;AAE7E,cAAc,8BAA8B,CAAC"}
1
+ {"version":3,"file":"chart.js","sourceRoot":"","sources":["../../src/entrypoints/chart.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAE5E,cAAc,8BAA8B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"chart.schemas.d.ts","sourceRoot":"","sources":["../../src/entrypoints/chart.schemas.ts"],"names":[],"mappings":"AACA,cAAc,8BAA8B,CAAC"}
1
+ {"version":3,"file":"chart.schemas.d.ts","sourceRoot":"","sources":["../../src/entrypoints/chart.schemas.ts"],"names":[],"mappings":"AACA,cAAc,8BAA8B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"chart.schemas.js","sourceRoot":"","sources":["../../src/entrypoints/chart.schemas.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,cAAc,8BAA8B,CAAC"}
1
+ {"version":3,"file":"chart.schemas.js","sourceRoot":"","sources":["../../src/entrypoints/chart.schemas.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,cAAc,8BAA8B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"geo.d.ts","sourceRoot":"","sources":["../../src/entrypoints/geo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACvE,mBAAmB,4BAA4B,CAAC;AAChD,cAAc,4BAA4B,CAAC"}
1
+ {"version":3,"file":"geo.d.ts","sourceRoot":"","sources":["../../src/entrypoints/geo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAA;AACtE,mBAAmB,4BAA4B,CAAA;AAC/C,cAAc,4BAA4B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"geo.js","sourceRoot":"","sources":["../../src/entrypoints/geo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAmB,MAAM,oBAAoB,CAAC;AAEvE,cAAc,4BAA4B,CAAC"}
1
+ {"version":3,"file":"geo.js","sourceRoot":"","sources":["../../src/entrypoints/geo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAmB,MAAM,oBAAoB,CAAA;AAEtE,cAAc,4BAA4B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"geo.schemas.d.ts","sourceRoot":"","sources":["../../src/entrypoints/geo.schemas.ts"],"names":[],"mappings":"AACA,cAAc,4BAA4B,CAAC"}
1
+ {"version":3,"file":"geo.schemas.d.ts","sourceRoot":"","sources":["../../src/entrypoints/geo.schemas.ts"],"names":[],"mappings":"AACA,cAAc,4BAA4B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"geo.schemas.js","sourceRoot":"","sources":["../../src/entrypoints/geo.schemas.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,cAAc,4BAA4B,CAAC"}
1
+ {"version":3,"file":"geo.schemas.js","sourceRoot":"","sources":["../../src/entrypoints/geo.schemas.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,cAAc,4BAA4B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"library.d.ts","sourceRoot":"","sources":["../../src/entrypoints/library.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACnF,mBAAmB,gCAAgC,CAAC;AACpD,cAAc,gCAAgC,CAAC"}
1
+ {"version":3,"file":"library.d.ts","sourceRoot":"","sources":["../../src/entrypoints/library.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAClF,mBAAmB,gCAAgC,CAAA;AACnD,cAAc,gCAAgC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"library.js","sourceRoot":"","sources":["../../src/entrypoints/library.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAuB,MAAM,wBAAwB,CAAC;AAEnF,cAAc,gCAAgC,CAAC"}
1
+ {"version":3,"file":"library.js","sourceRoot":"","sources":["../../src/entrypoints/library.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAuB,MAAM,wBAAwB,CAAA;AAElF,cAAc,gCAAgC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"library.schemas.d.ts","sourceRoot":"","sources":["../../src/entrypoints/library.schemas.ts"],"names":[],"mappings":"AACA,cAAc,gCAAgC,CAAC"}
1
+ {"version":3,"file":"library.schemas.d.ts","sourceRoot":"","sources":["../../src/entrypoints/library.schemas.ts"],"names":[],"mappings":"AACA,cAAc,gCAAgC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"library.schemas.js","sourceRoot":"","sources":["../../src/entrypoints/library.schemas.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,cAAc,gCAAgC,CAAC"}
1
+ {"version":3,"file":"library.schemas.js","sourceRoot":"","sources":["../../src/entrypoints/library.schemas.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,cAAc,gCAAgC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"tag.d.ts","sourceRoot":"","sources":["../../src/entrypoints/tag.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACvE,mBAAmB,4BAA4B,CAAC;AAChD,cAAc,4BAA4B,CAAC"}
1
+ {"version":3,"file":"tag.d.ts","sourceRoot":"","sources":["../../src/entrypoints/tag.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAA;AACtE,mBAAmB,4BAA4B,CAAA;AAC/C,cAAc,4BAA4B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"tag.js","sourceRoot":"","sources":["../../src/entrypoints/tag.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAmB,MAAM,oBAAoB,CAAC;AAEvE,cAAc,4BAA4B,CAAC"}
1
+ {"version":3,"file":"tag.js","sourceRoot":"","sources":["../../src/entrypoints/tag.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAmB,MAAM,oBAAoB,CAAA;AAEtE,cAAc,4BAA4B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"tag.schemas.d.ts","sourceRoot":"","sources":["../../src/entrypoints/tag.schemas.ts"],"names":[],"mappings":"AACA,cAAc,4BAA4B,CAAC"}
1
+ {"version":3,"file":"tag.schemas.d.ts","sourceRoot":"","sources":["../../src/entrypoints/tag.schemas.ts"],"names":[],"mappings":"AACA,cAAc,4BAA4B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"tag.schemas.js","sourceRoot":"","sources":["../../src/entrypoints/tag.schemas.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,cAAc,4BAA4B,CAAC"}
1
+ {"version":3,"file":"tag.schemas.js","sourceRoot":"","sources":["../../src/entrypoints/tag.schemas.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,cAAc,4BAA4B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"track.d.ts","sourceRoot":"","sources":["../../src/entrypoints/track.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAC7E,mBAAmB,8BAA8B,CAAC;AAClD,cAAc,8BAA8B,CAAC"}
1
+ {"version":3,"file":"track.d.ts","sourceRoot":"","sources":["../../src/entrypoints/track.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAC5E,mBAAmB,8BAA8B,CAAA;AACjD,cAAc,8BAA8B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"track.js","sourceRoot":"","sources":["../../src/entrypoints/track.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAqB,MAAM,sBAAsB,CAAC;AAE7E,cAAc,8BAA8B,CAAC"}
1
+ {"version":3,"file":"track.js","sourceRoot":"","sources":["../../src/entrypoints/track.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAqB,MAAM,sBAAsB,CAAA;AAE5E,cAAc,8BAA8B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"track.schemas.d.ts","sourceRoot":"","sources":["../../src/entrypoints/track.schemas.ts"],"names":[],"mappings":"AACA,cAAc,8BAA8B,CAAC"}
1
+ {"version":3,"file":"track.schemas.d.ts","sourceRoot":"","sources":["../../src/entrypoints/track.schemas.ts"],"names":[],"mappings":"AACA,cAAc,8BAA8B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"track.schemas.js","sourceRoot":"","sources":["../../src/entrypoints/track.schemas.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,cAAc,8BAA8B,CAAC"}
1
+ {"version":3,"file":"track.schemas.js","sourceRoot":"","sources":["../../src/entrypoints/track.schemas.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,cAAc,8BAA8B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../../src/entrypoints/user.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC1E,mBAAmB,6BAA6B,CAAC;AACjD,cAAc,6BAA6B,CAAC"}
1
+ {"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../../src/entrypoints/user.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACzE,mBAAmB,6BAA6B,CAAA;AAChD,cAAc,6BAA6B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"user.js","sourceRoot":"","sources":["../../src/entrypoints/user.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAoB,MAAM,qBAAqB,CAAC;AAE1E,cAAc,6BAA6B,CAAC"}
1
+ {"version":3,"file":"user.js","sourceRoot":"","sources":["../../src/entrypoints/user.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAoB,MAAM,qBAAqB,CAAA;AAEzE,cAAc,6BAA6B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"user.schemas.d.ts","sourceRoot":"","sources":["../../src/entrypoints/user.schemas.ts"],"names":[],"mappings":"AACA,cAAc,6BAA6B,CAAC"}
1
+ {"version":3,"file":"user.schemas.d.ts","sourceRoot":"","sources":["../../src/entrypoints/user.schemas.ts"],"names":[],"mappings":"AACA,cAAc,6BAA6B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"user.schemas.js","sourceRoot":"","sources":["../../src/entrypoints/user.schemas.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,cAAc,6BAA6B,CAAC"}
1
+ {"version":3,"file":"user.schemas.js","sourceRoot":"","sources":["../../src/entrypoints/user.schemas.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,cAAc,6BAA6B,CAAA"}