@ansango/lastfm-api 3.1.3 → 3.3.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 +54 -0
  2. package/README.md +150 -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 +41 -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 +48 -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 +35 -1
  73. package/dist/services/auth.d.ts.map +1 -1
  74. package/dist/services/auth.js +19 -2
  75. package/dist/services/auth.js.map +1 -1
  76. package/dist/services/auth.schemas.d.ts +10 -1
  77. package/dist/services/auth.schemas.d.ts.map +1 -1
  78. package/dist/services/auth.schemas.js +13 -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 +122 -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,60 @@ 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.3.0] - 2026-08-28
13
+
14
+ ### ✨ Features
15
+
16
+ - `auth.getToken()` now returns a pre-built `authUrl` so consumers don't have to
17
+ construct the browser-flow URL themselves. The CLI prints it; Scalar renders it
18
+ in the response. (#115) ([c69cd53](https://github.com/ansango/lastfm-api/commit/c69cd53))
19
+
20
+ ### ⚠️ Breaking Changes
21
+
22
+ - `auth.getMobileSession` has been **removed**. The method was deprecated in 3.2.0
23
+ (PR #106) with the warning that it would be removed in a future major release.
24
+ Last.fm restricts this endpoint to mobile-classified API keys, which are not
25
+ exposed through the public self-service create form. Every consumer can use the
26
+ browser flow (`auth.getToken` + `auth.getSession`) instead. (#117) ([99c4466](https://github.com/ansango/lastfm-api/commit/99c4466))
27
+
28
+ **Migration:**
29
+
30
+ ```ts
31
+ // 3.2.x — no longer compiles
32
+ const { session } = await client.auth.getMobileSession({
33
+ username: "...",
34
+ password: "...",
35
+ });
36
+
37
+ // 3.3.0 — use the browser flow
38
+ const { token, authUrl } = await client.auth.getToken();
39
+ // open authUrl in a browser, authorize, copy token from URL bar
40
+ const { session } = await client.auth.getSession({ token });
41
+ ```
42
+
43
+ The Scalar tool surface no longer exposes `POST /auth/get-mobile-session`. The
44
+ `x-lastfm-sk` header description and the `AUTH_TAG_DESCRIPTION` were rewritten
45
+ to point at the browser flow + `authUrl`. The 57-method surface is now 56.
46
+
47
+
48
+ ## [3.2.0] - 2026-08-28
49
+
50
+ ### ✨ Features
51
+
52
+ - **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))
53
+
54
+ ### 📚 Documentation
55
+
56
+ - 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))
57
+ - add Callback URL setup prerequisite to README and Scalar auth tag (#110) ([c64410d](https://github.com/ansango/lastfm-api/commit/c64410d))
58
+ - deprecate `auth.getMobileSession` and reorient the auth flow to lead with the web flow (#105) ([4446f10](https://github.com/ansango/lastfm-api/commit/4446f10))
59
+
60
+ ### 🛠️ Tooling
61
+
62
+ - friendly startup error when `LASTFM_API_KEY` is missing (#103) ([cca87a2](https://github.com/ansango/lastfm-api/commit/cca87a2))
63
+ - add Biome for lint + format, replace unused Prettier config (#111) ([071c1e7](https://github.com/ansango/lastfm-api/commit/071c1e7))
64
+
65
+
12
66
  ## [3.1.3] - 2026-08-02
13
67
 
14
68
  ### 📚 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,26 @@ 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
+
135
+ // Now-playing and tag/love mutations (all require an authenticated session)
136
+ await client.track.updateNowPlaying({
137
+ artist: 'Cher',
138
+ track: 'Believe',
139
+ album: 'Believe',
140
+ duration: 240
141
+ });
142
+
143
+ await client.track.addTags({
144
+ artist: 'Cher',
145
+ track: 'Believe',
146
+ tags: ['favorites', '90s']
147
+ });
148
+ await client.track.love({ artist: 'Cher', track: 'Believe' });
149
+
150
+ await client.album.addTags({ artist: 'Cher', album: 'Believe', tags: ['favorites'] });
151
+ await client.artist.addTags({ artist: 'Cher', tags: ['favorites'] });
131
152
  ```
132
153
 
133
154
  ### Using Global Configuration
@@ -282,23 +303,85 @@ const client = new LastFmClient({
282
303
 
283
304
  ## Authentication & Scrobbling
284
305
 
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.
306
+ Methods that mutate user state require an authenticated session. The full list of write methods is:
307
+
308
+ - `auth.getSession`, `auth.getToken`
309
+ - `track.scrobble`, `track.updateNowPlaying`
310
+ - `track.addTags`, `track.removeTag`, `track.love`, `track.unlove`
311
+ - `album.addTags`, `album.removeTag`
312
+ - `artist.addTags`, `artist.removeTag`
313
+
314
+ The browser flow below works for every self-service API key — there is no mobile flow in this package anymore.
315
+
316
+ ### Browser flow (recommended — works for all self-service keys)
317
+
318
+ 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
319
 
287
320
  ```typescript
288
321
  import { LastFmClient } from '@ansango/lastfm-api';
289
322
 
323
+ // 1. Get a request token (signed GET, no session needed).
324
+ const client = new LastFmClient({
325
+ apiKey: process.env.LASTFM_API_KEY!,
326
+ sharedSecret: process.env.LASTFM_SHARED_SECRET!,
327
+ });
328
+ const { token } = await client.auth.getToken();
329
+
330
+ // 2. Direct the user to authorize the token in a browser:
331
+ // https://www.last.fm/api/auth/?api_key=<KEY>&token=<token>
332
+ // After authorizing, Last.fm redirects to the callback URL configured
333
+ // on the API account (the token appears in the URL).
334
+
335
+ // 3. Exchange the authorized token for a session key.
336
+ const { session } = await client.auth.getSession({ token });
337
+ const sessionKey = session.key; // pass this to write methods
338
+ ```
339
+
340
+ ### Callback URL setup (one-time, in your Last.fm account)
341
+
342
+ Before the browser flow works end-to-end, set a callback URL on your API account at <https://www.last.fm/api/account>:
343
+
344
+ 1. Open <https://www.last.fm/api/account>, find your app, click **Edit**.
345
+ 2. In the **Callback URL** field, enter a URL.
346
+ 3. Save.
347
+
348
+ **What to enter depends on how you'll consume the token:**
349
+
350
+ - **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.
351
+ - **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.
352
+
353
+ 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.
354
+
355
+ > **Note:** `auth.getMobileSession` was removed in v4.0.0. Last.fm restricts that endpoint to mobile-classified API keys, which are not exposed through the public self-service create form; the browser flow above works for every API key Last.fm issues today.
356
+
357
+ ### Passing the session key to write methods
358
+
359
+ Once you have a session key, you can pass it in two ways:
360
+
361
+ - **Per-request** (`params.sk`): preferred for ad-hoc calls or one-off scripts.
362
+ - **On the `LastFmConfig`** (`sessionKey`): preferred for long-lived clients; the transport injects it into every signed call automatically.
363
+
364
+ ```typescript
365
+ // Option A: session key in the config (recommended for long-lived clients).
290
366
  const client = new LastFmClient({
291
367
  apiKey: process.env.LASTFM_API_KEY!,
292
368
  sharedSecret: process.env.LASTFM_SHARED_SECRET!,
293
369
  sessionKey: process.env.LASTFM_SESSION_KEY!,
294
370
  });
295
371
 
296
- // Scrobble a track — `sk` is auto-injected from `config.sessionKey`,
297
- // so you don't need to pass it explicitly.
372
+ // `sk` is auto-injected from config.sessionKey; you don't need to pass it.
373
+ await client.track.scrobble({
374
+ artist: 'Cher',
375
+ track: 'Believe',
376
+ timestamp: Math.floor(Date.now() / 1000),
377
+ });
378
+
379
+ // Option B: session key per-request (preferred for ad-hoc calls).
298
380
  await client.track.scrobble({
299
381
  artist: 'Cher',
300
382
  track: 'Believe',
301
383
  timestamp: Math.floor(Date.now() / 1000),
384
+ sk: 'paste-the-session-key-here',
302
385
  });
303
386
  ```
304
387
 
@@ -367,17 +450,19 @@ function resetGlobalConfig(): void;
367
450
 
368
451
  ### Services
369
452
 
370
- Each service provides methods for interacting with specific Last.fm API endpoints:
453
+ 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.
454
+
455
+ - **UserService**: 13 methods — `getInfo`, `getFriends`, `getLovedTracks`, `getRecentTracks`, `getTopAlbums`, `getTopArtists`, `getTopTags`, `getTopTracks`, `getWeeklyAlbumChart`, `getWeeklyArtistChart`, `getWeeklyChartList`, `getWeeklyTrackChart`, `getPersonalTags`
456
+ - **AlbumService**: 6 methods — `getInfo`, `getTags`, `getTopTags`, `search`, `addTags`¹, `removeTag`¹
457
+ - **ArtistService**: 10 methods — `getInfo`, `getTags`, `getSimilar`, `getTopTags`, `getTopAlbums`, `getTopTracks`, `search`, `getCorrection`, `addTags`¹, `removeTag`¹
458
+ - **TrackService**: 12 methods — `getInfo`, `getSimilar`, `getTags`, `getTopTags`, `search`, `scrobble`¹, `getCorrection`, `addTags`¹, `removeTag`¹, `love`¹, `unlove`¹, `updateNowPlaying`¹
459
+ - **TagService**: 7 methods — `getInfo`, `getSimilar`, `getTopAlbums`, `getTopArtists`, `getTopTags`, `getTopTracks`, `getWeeklyChartList`
460
+ - **ChartService**: 3 methods — `getTopArtists`, `getTopTags`, `getTopTracks`
461
+ - **GeoService**: 2 methods — `getTopArtists`, `getTopTracks`
462
+ - **LibraryService**: 1 method — `getArtists`
463
+ - **AuthService**: 2 methods — `getSession`, `getToken` (removed `getMobileSession` in v4.0.0)
371
464
 
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.)
465
+ ¹ Requires an authenticated session.
381
466
 
382
467
  ## TypeScript Support
383
468
 
@@ -426,13 +511,63 @@ bun run dev
426
511
  # Build the project
427
512
  bun run build
428
513
 
429
- # Run tests
430
- bun test
514
+ # Typecheck (no emit)
515
+ bun run typecheck
516
+
517
+ # Run deterministic unit tests (no network, mocked fetch)
518
+ bun run test:unit
519
+
520
+ # Run live integration (requires Last.fm credentials in .env)
521
+ bun run test:integration:live
522
+
523
+ # Lint (Biome — formatter + linter, single command)
524
+ bun run lint
525
+
526
+ # Auto-fix what Biome can (formatting, safe lint fixes)
527
+ bun run lint:fix
528
+
529
+ # Format only (no lint)
530
+ bun run format
531
+ bun run format:check
532
+
533
+ # Run the local interactive docs server (Hono + Scalar, see #92)
534
+ bun run tool:dev
431
535
 
432
536
  # Clean build artifacts
433
537
  bun run clean
434
538
  ```
435
539
 
540
+ ## Interactive API Explorer
541
+
542
+ The repo ships with a local Hono + Scalar server under `tool/api-scalar/`
543
+ that turns the package into a fully interactive OpenAPI explorer. All 57
544
+ canonical Last.fm methods are wired declaratively from the package's own
545
+ Zod schemas and service functions — no method is hand-written, no schema
546
+ is duplicated.
547
+
548
+ ```sh
549
+ bun install --cwd tool/api-scalar
550
+ cp tool/api-scalar/.env.example .env # fill in LASTFM_API_KEY and LASTFM_SHARED_SECRET
551
+ bun run tool:dev
552
+ ```
553
+
554
+ Then open <http://localhost:3000>. "Try it" calls the real Last.fm API
555
+ through the package; the shared secret and session key live in env vars,
556
+ never in the browser. See [`tool/api-scalar/README.md`](./tool/api-scalar/README.md)
557
+ for the full guide and [`#92`](https://github.com/ansango/lastfm-api/issues/92)
558
+ for the design notes.
559
+
560
+ ### Testing
561
+
562
+ The test suite is split into two layers:
563
+
564
+ - **`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.
565
+ - **`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`.
566
+
567
+ The `bun test` alias points to the deterministic suite, so a normal `bun test` is safe to run anywhere.
568
+
569
+ 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.
570
+
436
571
  ### Release Process
437
572
 
438
573
  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"}