Compare changes

Choose any two refs to compare.

+1
.gitignore
··· 23 23 # jetbrains setting folder 24 24 .idea/ 25 25 .refreshToken 26 + .accessToken
-16
Dockerfile
··· 1 - FROM node:24-alpine 2 - WORKDIR /app 3 - 4 - # install pnpm 5 - ENV PNPM_HOME="/pnpm" 6 - ENV PATH="$PNPM_HOME:$PATH" 7 - RUN corepack enable pnpm && corepack install -g pnpm@latest 8 - 9 - # copy whole project, install packages, and build 10 - COPY . ./ 11 - RUN pnpm install --prod 12 - RUN pnpm run build 13 - 14 - EXPOSE 4321 15 - 16 - CMD ["node", "./dist/server/entry.mjs"]
+5 -19
astro.config.mjs
··· 3 3 4 4 import node from "@astrojs/node"; 5 5 6 - import sitemap from "@astrojs/sitemap"; 7 - 8 6 // https://astro.build/config 9 7 export default defineConfig({ 10 - site: "https://vielle.dev", 11 - 12 - markdown: { 13 - shikiConfig: { 14 - theme: "dracula-soft", 15 - }, 16 - }, 17 - 18 - integrations: [sitemap()], 19 - 20 - adapter: node({ 21 - mode: "standalone", 22 - }), 23 - 24 - server: { 25 - host: true, 26 - }, 8 + output: "server", 27 9 28 10 env: { 29 11 schema: { ··· 42 24 }), 43 25 }, 44 26 }, 27 + 28 + adapter: node({ 29 + mode: "standalone", 30 + }), 45 31 });
+2 -15
package.json
··· 11 11 }, 12 12 "dependencies": { 13 13 "@astrojs/node": "^9.3.1", 14 - "@astrojs/rss": "^4.0.12", 15 - "@astrojs/sitemap": "^3.5.0", 16 - "@atcute/atproto": "^3.1.1", 17 - "@atcute/bluesky": "^3.2.0", 18 - "@atcute/bluesky-richtext-segmenter": "^2.0.3", 19 - "@atcute/client": "^4.0.3", 20 - "@atcute/identity-resolver": "^1.1.3", 21 - "@atcute/lexicons": "^1.1.0", 22 - "@oddbird/css-anchor-positioning": "^0.6.1", 23 14 "@spotify/web-api-ts-sdk": "^1.2.0", 24 - "astro": "^5.12.6", 25 - "sharp": "^0.34.3" 15 + "astro": "^5.12.6" 26 16 }, 27 17 "devDependencies": { 28 18 "prettier": "3.6.2", ··· 31 21 "pnpm": { 32 22 "patchedDependencies": { 33 23 "@spotify/web-api-ts-sdk": "patches/@spotify__web-api-ts-sdk.patch" 34 - }, 35 - "onlyBuiltDependencies": [ 36 - "sharp" 37 - ] 24 + } 38 25 } 39 26 }
+915 -163
patches/@spotify__web-api-ts-sdk.patch
··· 1 + diff --git a/dist/cjs/SpotifyApi.d.ts b/dist/cjs/SpotifyApi.d.ts 2 + index cf5eff3cb728065892287539b2a85e2fe16b283b..fe3c2a037f4e47e6c748753a5661261552cfcc1b 100644 3 + --- a/dist/cjs/SpotifyApi.d.ts 4 + +++ b/dist/cjs/SpotifyApi.d.ts 5 + @@ -35,7 +35,7 @@ export declare class SpotifyApi { 6 + search: SearchExecutionFunction; 7 + currentUser: CurrentUserEndpoints; 8 + constructor(authentication: IAuthStrategy, config?: SdkOptions); 9 + - makeRequest<TReturnType>(method: "GET" | "POST" | "PUT" | "DELETE", url: string, body?: any, contentType?: string | undefined): Promise<TReturnType>; 10 + + makeRequest<TReturnType>(method: "GET" | "POST" | "PUT" | "DELETE", url: string, body?: any, contentType?: string | undefined): Promise<TReturnType | null>; 11 + private initializeSdk; 12 + switchAuthenticationStrategy(authentication: IAuthStrategy): void; 13 + /** 1 14 diff --git a/dist/cjs/SpotifyApi.js.map b/dist/cjs/SpotifyApi.js.map 2 15 index 2d356d41a56db1b8984445364ad2a94c05632cfa..195edd6643860eb7cc5da74c080cfaef47c9a323 100644 3 16 --- a/dist/cjs/SpotifyApi.js.map ··· 96 109 \ No newline at end of file 97 110 +{"version":3,"file":"GenericCache.js","sourceRoot":"","sources":["../../../src/caching/GenericCache.ts"],"names":[],"mappings":"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"} 98 111 \ No newline at end of file 112 + diff --git a/dist/cjs/endpoints/AlbumsEndpoints.d.ts b/dist/cjs/endpoints/AlbumsEndpoints.d.ts 113 + index 18274fea2c934cd17f8ca87d551477cf8bda5291..bed7d9e02f1e65693b5f6772e78463a52ef442a8 100644 114 + --- a/dist/cjs/endpoints/AlbumsEndpoints.d.ts 115 + +++ b/dist/cjs/endpoints/AlbumsEndpoints.d.ts 116 + @@ -3,5 +3,5 @@ import EndpointsBase from './EndpointsBase.js'; 117 + export default class AlbumsEndpoints extends EndpointsBase { 118 + get(id: string, market?: Market): Promise<Album>; 119 + get(ids: string[], market?: Market): Promise<Album[]>; 120 + - tracks(albumId: string, market?: Market, limit?: MaxInt<50>, offset?: number): Promise<Page<SimplifiedTrack>>; 121 + + tracks(albumId: string, market?: Market, limit?: MaxInt<50>, offset?: number): Promise<Page<SimplifiedTrack> | null>; 122 + } 123 + diff --git a/dist/cjs/endpoints/AlbumsEndpoints.js b/dist/cjs/endpoints/AlbumsEndpoints.js 124 + index 558f566069a7756bd8506298655a3d04dc9d0727..2eb39da32149091646eed89e3461f64aff27297e 100644 125 + --- a/dist/cjs/endpoints/AlbumsEndpoints.js 126 + +++ b/dist/cjs/endpoints/AlbumsEndpoints.js 127 + @@ -14,6 +14,8 @@ class AlbumsEndpoints extends EndpointsBase_js_1.default { 128 + const params = this.paramsFor({ ids: idOrIds, market }); 129 + // TODO: only returns top 20, validate here 130 + const response = await this.getRequest(`albums${params}`); 131 + + if (!response) 132 + + return response; 133 + return response.albums; 134 + } 135 + tracks(albumId, market, limit, offset) { 99 136 diff --git a/dist/cjs/endpoints/AlbumsEndpoints.js.map b/dist/cjs/endpoints/AlbumsEndpoints.js.map 100 - index 13c3a0d24c5ffef9729936189d90d7639729896d..298227fb7a1617bbaaeacb240b74e1ea57948799 100644 137 + index 13c3a0d24c5ffef9729936189d90d7639729896d..fc40487a6c97f94a0480f25290934be5d4dcbbe8 100644 101 138 --- a/dist/cjs/endpoints/AlbumsEndpoints.js.map 102 139 +++ b/dist/cjs/endpoints/AlbumsEndpoints.js.map 103 140 @@ -1 +1 @@ 104 141 -{"version":3,"file":"AlbumsEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/AlbumsEndpoints.ts"],"names":[],"mappings":";;;;;AACA,0EAA+C;AAE/C,MAAqB,eAAgB,SAAQ,0BAAa;IAI/C,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAe;QACxD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;YAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1C,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,UAAU,CAAQ,UAAU,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;YACzE,OAAO,KAAK,CAAC;SAChB;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,2CAA2C;QAC3C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAS,SAAS,MAAM,EAAE,CAAC,CAAC;QAClE,OAAO,QAAQ,CAAC,MAAM,CAAC;IAC3B,CAAC;IAEM,MAAM,CAAC,OAAe,EAAE,MAAe,EAAE,KAAkB,EAAE,MAAe;QAC/E,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACzD,OAAO,IAAI,CAAC,UAAU,CAAwB,UAAU,OAAO,UAAU,MAAM,EAAE,CAAC,CAAC;IACvF,CAAC;CACJ;AArBD,kCAqBC"} 105 142 \ No newline at end of file 106 - +{"version":3,"file":"AlbumsEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/AlbumsEndpoints.ts"],"names":[],"mappings":";;;;;AACA,0EAA+C;AAE/C,MAAqB,eAAgB,SAAQ,0BAAa;IAI/C,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAe;QACxD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1C,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,UAAU,CAAQ,UAAU,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;YACzE,OAAO,KAAK,CAAC;QACjB,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,2CAA2C;QAC3C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAS,SAAS,MAAM,EAAE,CAAC,CAAC;QAClE,OAAO,QAAQ,CAAC,MAAM,CAAC;IAC3B,CAAC;IAEM,MAAM,CAAC,OAAe,EAAE,MAAe,EAAE,KAAkB,EAAE,MAAe;QAC/E,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACzD,OAAO,IAAI,CAAC,UAAU,CAAwB,UAAU,OAAO,UAAU,MAAM,EAAE,CAAC,CAAC;IACvF,CAAC;CACJ;AArBD,kCAqBC"} 143 + +{"version":3,"file":"AlbumsEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/AlbumsEndpoints.ts"],"names":[],"mappings":";;;;;AACA,0EAA+C;AAE/C,MAAqB,eAAgB,SAAQ,0BAAa;IAI/C,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAe;QACxD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1C,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,UAAU,CAAQ,UAAU,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;YACzE,OAAO,KAAK,CAAC;QACjB,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,2CAA2C;QAC3C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAS,SAAS,MAAM,EAAE,CAAC,CAAC;QAClE,IAAI,CAAC,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAC/B,OAAO,QAAQ,CAAC,MAAM,CAAC;IAC3B,CAAC;IAEM,MAAM,CAAC,OAAe,EAAE,MAAe,EAAE,KAAkB,EAAE,MAAe;QAC/E,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACzD,OAAO,IAAI,CAAC,UAAU,CAAwB,UAAU,OAAO,UAAU,MAAM,EAAE,CAAC,CAAC;IACvF,CAAC;CACJ;AAtBD,kCAsBC"} 107 144 \ No newline at end of file 145 + diff --git a/dist/cjs/endpoints/ArtistsEndpoints.d.ts b/dist/cjs/endpoints/ArtistsEndpoints.d.ts 146 + index 4b5237b7acbc95486893d7384fb6adcdf71ee74a..8bdba8fcbc5a9c45deb1a49580764c7cbbd1cd7b 100644 147 + --- a/dist/cjs/endpoints/ArtistsEndpoints.d.ts 148 + +++ b/dist/cjs/endpoints/ArtistsEndpoints.d.ts 149 + @@ -3,7 +3,7 @@ import EndpointsBase from "./EndpointsBase.js"; 150 + export default class ArtistsEndpoints extends EndpointsBase { 151 + get(id: string): Promise<Artist>; 152 + get(ids: string[]): Promise<Artist[]>; 153 + - albums(id: string, includeGroups?: string, market?: Market, limit?: MaxInt<50>, offset?: number): Promise<Page<SimplifiedAlbum>>; 154 + - topTracks(id: string, market: Market): Promise<TopTracksResult>; 155 + - relatedArtists(id: string): Promise<Artists>; 156 + + albums(id: string, includeGroups?: string, market?: Market, limit?: MaxInt<50>, offset?: number): Promise<Page<SimplifiedAlbum> | null>; 157 + + topTracks(id: string, market: Market): Promise<TopTracksResult | null>; 158 + + relatedArtists(id: string): Promise<Artists | null>; 159 + } 160 + diff --git a/dist/cjs/endpoints/ArtistsEndpoints.js b/dist/cjs/endpoints/ArtistsEndpoints.js 161 + index 6c6eee4d65b70db5df80865431c035ab10d60262..09a222ee0b5a3a0b93396008bb72a2ba69728c28 100644 162 + --- a/dist/cjs/endpoints/ArtistsEndpoints.js 163 + +++ b/dist/cjs/endpoints/ArtistsEndpoints.js 164 + @@ -12,6 +12,8 @@ class ArtistsEndpoints extends EndpointsBase_js_1.default { 165 + } 166 + const params = this.paramsFor({ ids: idOrIds }); 167 + const response = await this.getRequest(`artists${params}`); 168 + + if (!response) 169 + + return response; 170 + return response.artists; 171 + } 172 + albums(id, includeGroups, market, limit, offset) { 108 173 diff --git a/dist/cjs/endpoints/ArtistsEndpoints.js.map b/dist/cjs/endpoints/ArtistsEndpoints.js.map 109 - index 8bf5c0c2e5bfbeabc81b764bc66814010a7e828b..3ef89674d83081ce15e1a24a3a80fb7cff9071f9 100644 174 + index 8bf5c0c2e5bfbeabc81b764bc66814010a7e828b..b7d33f131af79fb432943e5f78b69afbafff1f9b 100644 110 175 --- a/dist/cjs/endpoints/ArtistsEndpoints.js.map 111 176 +++ b/dist/cjs/endpoints/ArtistsEndpoints.js.map 112 177 @@ -1 +1 @@ 113 178 -{"version":3,"file":"ArtistsEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/ArtistsEndpoints.ts"],"names":[],"mappings":";;;;;AAUA,0EAA+C;AAE/C,MAAqB,gBAAiB,SAAQ,0BAAa;IAGhD,KAAK,CAAC,GAAG,CAAC,OAA0B;QACvC,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;YAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAS,WAAW,OAAO,EAAE,CAAC,CAAC;YAC7D,OAAO,MAAM,CAAC;SACjB;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QAChD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAU,UAAU,MAAM,EAAE,CAAC,CAAC;QACpE,OAAO,QAAQ,CAAC,OAAO,CAAC;IAC5B,CAAC;IAEM,MAAM,CACT,EAAU,EACV,aAAsB,EACtB,MAAe,EACf,KAAkB,EAClB,MAAe;QAEf,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC;YAC1B,cAAc,EAAE,aAAa;YAC7B,MAAM;YACN,KAAK;YACL,MAAM;SACT,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,UAAU,CAClB,WAAW,EAAE,UAAU,MAAM,EAAE,CAClC,CAAC;IACN,CAAC;IAEM,SAAS,CAAC,EAAU,EAAE,MAAc;QACvC,+FAA+F;QAC/F,0BAA0B;QAE1B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QAC1C,OAAO,IAAI,CAAC,UAAU,CAClB,WAAW,EAAE,cAAc,MAAM,EAAE,CACtC,CAAC;IACN,CAAC;IAEM,cAAc,CAAC,EAAU;QAC5B,OAAO,IAAI,CAAC,UAAU,CAAU,WAAW,EAAE,kBAAkB,CAAC,CAAC;IACrE,CAAC;CACJ;AA7CD,mCA6CC"} 114 179 \ No newline at end of file 115 - +{"version":3,"file":"ArtistsEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/ArtistsEndpoints.ts"],"names":[],"mappings":";;;;;AAUA,0EAA+C;AAE/C,MAAqB,gBAAiB,SAAQ,0BAAa;IAGhD,KAAK,CAAC,GAAG,CAAC,OAA0B;QACvC,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAS,WAAW,OAAO,EAAE,CAAC,CAAC;YAC7D,OAAO,MAAM,CAAC;QAClB,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QAChD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAU,UAAU,MAAM,EAAE,CAAC,CAAC;QACpE,OAAO,QAAQ,CAAC,OAAO,CAAC;IAC5B,CAAC;IAEM,MAAM,CACT,EAAU,EACV,aAAsB,EACtB,MAAe,EACf,KAAkB,EAClB,MAAe;QAEf,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC;YAC1B,cAAc,EAAE,aAAa;YAC7B,MAAM;YACN,KAAK;YACL,MAAM;SACT,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,UAAU,CAClB,WAAW,EAAE,UAAU,MAAM,EAAE,CAClC,CAAC;IACN,CAAC;IAEM,SAAS,CAAC,EAAU,EAAE,MAAc;QACvC,+FAA+F;QAC/F,0BAA0B;QAE1B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QAC1C,OAAO,IAAI,CAAC,UAAU,CAClB,WAAW,EAAE,cAAc,MAAM,EAAE,CACtC,CAAC;IACN,CAAC;IAEM,cAAc,CAAC,EAAU;QAC5B,OAAO,IAAI,CAAC,UAAU,CAAU,WAAW,EAAE,kBAAkB,CAAC,CAAC;IACrE,CAAC;CACJ;AA7CD,mCA6CC"} 180 + +{"version":3,"file":"ArtistsEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/ArtistsEndpoints.ts"],"names":[],"mappings":";;;;;AAUA,0EAA+C;AAE/C,MAAqB,gBAAiB,SAAQ,0BAAa;IAGhD,KAAK,CAAC,GAAG,CAAC,OAA0B;QACvC,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAS,WAAW,OAAO,EAAE,CAAC,CAAC;YAC7D,OAAO,MAAM,CAAC;QAClB,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QAChD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAU,UAAU,MAAM,EAAE,CAAC,CAAC;QACpE,IAAI,CAAC,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAC/B,OAAO,QAAQ,CAAC,OAAO,CAAC;IAC5B,CAAC;IAEM,MAAM,CACT,EAAU,EACV,aAAsB,EACtB,MAAe,EACf,KAAkB,EAClB,MAAe;QAEf,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC;YAC1B,cAAc,EAAE,aAAa;YAC7B,MAAM;YACN,KAAK;YACL,MAAM;SACT,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,UAAU,CAClB,WAAW,EAAE,UAAU,MAAM,EAAE,CAClC,CAAC;IACN,CAAC;IAEM,SAAS,CAAC,EAAU,EAAE,MAAc;QACvC,+FAA+F;QAC/F,0BAA0B;QAE1B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QAC1C,OAAO,IAAI,CAAC,UAAU,CAClB,WAAW,EAAE,cAAc,MAAM,EAAE,CACtC,CAAC;IACN,CAAC;IAEM,cAAc,CAAC,EAAU;QAC5B,OAAO,IAAI,CAAC,UAAU,CAAU,WAAW,EAAE,kBAAkB,CAAC,CAAC;IACrE,CAAC;CACJ;AA9CD,mCA8CC"} 116 181 \ No newline at end of file 182 + diff --git a/dist/cjs/endpoints/AudiobooksEndpoints.d.ts b/dist/cjs/endpoints/AudiobooksEndpoints.d.ts 183 + index cfe18b338a678454c67cba7086ef4b292e0ab54a..33f2577aa2b4050e49f22b3bdca75b8ba1993fdd 100644 184 + --- a/dist/cjs/endpoints/AudiobooksEndpoints.d.ts 185 + +++ b/dist/cjs/endpoints/AudiobooksEndpoints.d.ts 186 + @@ -3,5 +3,5 @@ import EndpointsBase from './EndpointsBase.js'; 187 + export default class AudiobooksEndpoints extends EndpointsBase { 188 + get(id: string, market?: Market): Promise<Audiobook>; 189 + get(ids: string[], market?: Market): Promise<Audiobook[]>; 190 + - getAudiobookChapters(id: string, market?: Market, limit?: MaxInt<50>, offset?: number): Promise<Page<SimplifiedChapter>>; 191 + + getAudiobookChapters(id: string, market?: Market, limit?: MaxInt<50>, offset?: number): Promise<Page<SimplifiedChapter> | null>; 192 + } 193 + diff --git a/dist/cjs/endpoints/AudiobooksEndpoints.js b/dist/cjs/endpoints/AudiobooksEndpoints.js 194 + index 5cd33ac00e938d5af436107bbf0dfb055d1f87c0..e227dda6bb5c8720b801245827fe768e4ad54693 100644 195 + --- a/dist/cjs/endpoints/AudiobooksEndpoints.js 196 + +++ b/dist/cjs/endpoints/AudiobooksEndpoints.js 197 + @@ -12,6 +12,8 @@ class AudiobooksEndpoints extends EndpointsBase_js_1.default { 198 + } 199 + const params = this.paramsFor({ ids: idOrIds, market }); 200 + const response = await this.getRequest(`audiobooks${params}`); 201 + + if (!response) 202 + + return response; 203 + return response.audiobooks; 204 + } 205 + getAudiobookChapters(id, market, limit, offset) { 117 206 diff --git a/dist/cjs/endpoints/AudiobooksEndpoints.js.map b/dist/cjs/endpoints/AudiobooksEndpoints.js.map 118 - index 4f5a448ad51548883d3eb68a057aa825e766e146..d87a7c24f3292e3d4728d9398d70222b524ac2c6 100644 207 + index 4f5a448ad51548883d3eb68a057aa825e766e146..7fa408648e38a4091db7288d18d9b4893e47fe98 100644 119 208 --- a/dist/cjs/endpoints/AudiobooksEndpoints.js.map 120 209 +++ b/dist/cjs/endpoints/AudiobooksEndpoints.js.map 121 210 @@ -1 +1 @@ 122 211 -{"version":3,"file":"AudiobooksEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/AudiobooksEndpoints.ts"],"names":[],"mappings":";;;;;AACA,0EAA+C;AAE/C,MAAqB,mBAAoB,SAAQ,0BAAa;IAGnD,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAe;QACxD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;YAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1C,OAAO,IAAI,CAAC,UAAU,CAAY,cAAc,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;SACvE;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAa,aAAa,MAAM,EAAE,CAAC,CAAC;QAC1E,OAAO,QAAQ,CAAC,UAAU,CAAC;IAC/B,CAAC;IAEM,oBAAoB,CAAC,EAAU,EAAE,MAAe,EAAE,KAAkB,EAAE,MAAe;QACxF,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACzD,OAAO,IAAI,CAAC,UAAU,CAA0B,cAAc,EAAE,YAAY,MAAM,EAAE,CAAC,CAAC;IAC1F,CAAC;CAEJ;AAnBD,sCAmBC"} 123 212 \ No newline at end of file 124 - +{"version":3,"file":"AudiobooksEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/AudiobooksEndpoints.ts"],"names":[],"mappings":";;;;;AACA,0EAA+C;AAE/C,MAAqB,mBAAoB,SAAQ,0BAAa;IAGnD,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAe;QACxD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1C,OAAO,IAAI,CAAC,UAAU,CAAY,cAAc,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;QACxE,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAa,aAAa,MAAM,EAAE,CAAC,CAAC;QAC1E,OAAO,QAAQ,CAAC,UAAU,CAAC;IAC/B,CAAC;IAEM,oBAAoB,CAAC,EAAU,EAAE,MAAe,EAAE,KAAkB,EAAE,MAAe;QACxF,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACzD,OAAO,IAAI,CAAC,UAAU,CAA0B,cAAc,EAAE,YAAY,MAAM,EAAE,CAAC,CAAC;IAC1F,CAAC;CAEJ;AAnBD,sCAmBC"} 213 + +{"version":3,"file":"AudiobooksEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/AudiobooksEndpoints.ts"],"names":[],"mappings":";;;;;AACA,0EAA+C;AAE/C,MAAqB,mBAAoB,SAAQ,0BAAa;IAGnD,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAe;QACxD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1C,OAAO,IAAI,CAAC,UAAU,CAAY,cAAc,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;QACxE,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAa,aAAa,MAAM,EAAE,CAAC,CAAC;QAC1E,IAAI,CAAC,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAC/B,OAAO,QAAQ,CAAC,UAAU,CAAC;IAC/B,CAAC;IAEM,oBAAoB,CAAC,EAAU,EAAE,MAAe,EAAE,KAAkB,EAAE,MAAe;QACxF,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACzD,OAAO,IAAI,CAAC,UAAU,CAA0B,cAAc,EAAE,YAAY,MAAM,EAAE,CAAC,CAAC;IAC1F,CAAC;CAEJ;AApBD,sCAoBC"} 125 214 \ No newline at end of file 215 + diff --git a/dist/cjs/endpoints/BrowseEndpoints.d.ts b/dist/cjs/endpoints/BrowseEndpoints.d.ts 216 + index 7f998995a6b7cdb8c31dcfc9d0284826cf9b8a90..87b59ecd24941b849bd43e472ab8421cbba0e0d3 100644 217 + --- a/dist/cjs/endpoints/BrowseEndpoints.d.ts 218 + +++ b/dist/cjs/endpoints/BrowseEndpoints.d.ts 219 + @@ -1,9 +1,9 @@ 220 + import type { CountryCodeA2, MaxInt, Categories, Category, NewReleases, FeaturedPlaylists } from '../types.js'; 221 + import EndpointsBase from './EndpointsBase.js'; 222 + export default class BrowseEndpoints extends EndpointsBase { 223 + - getCategories(country?: CountryCodeA2, locale?: string, limit?: MaxInt<50>, offset?: number): Promise<Categories>; 224 + - getCategory(categoryId: string, country?: CountryCodeA2, locale?: string): Promise<Category>; 225 + - getNewReleases(country?: string, limit?: MaxInt<50>, offset?: number): Promise<NewReleases>; 226 + - getFeaturedPlaylists(country?: CountryCodeA2, locale?: string, timestamp?: string, limit?: MaxInt<50>, offset?: number): Promise<FeaturedPlaylists>; 227 + - getPlaylistsForCategory(category_id: string, country?: CountryCodeA2, limit?: MaxInt<50>, offset?: number): Promise<FeaturedPlaylists>; 228 + + getCategories(country?: CountryCodeA2, locale?: string, limit?: MaxInt<50>, offset?: number): Promise<Categories | null>; 229 + + getCategory(categoryId: string, country?: CountryCodeA2, locale?: string): Promise<Category | null>; 230 + + getNewReleases(country?: string, limit?: MaxInt<50>, offset?: number): Promise<NewReleases | null>; 231 + + getFeaturedPlaylists(country?: CountryCodeA2, locale?: string, timestamp?: string, limit?: MaxInt<50>, offset?: number): Promise<FeaturedPlaylists | null>; 232 + + getPlaylistsForCategory(category_id: string, country?: CountryCodeA2, limit?: MaxInt<50>, offset?: number): Promise<FeaturedPlaylists | null>; 233 + } 234 + diff --git a/dist/cjs/endpoints/ChaptersEndpoints.js b/dist/cjs/endpoints/ChaptersEndpoints.js 235 + index f3ac2c65fb099887371999b1b018b54e8a6ef532..6b6dbc9ccba2f74c2b611ecab82d5f0764b7bd77 100644 236 + --- a/dist/cjs/endpoints/ChaptersEndpoints.js 237 + +++ b/dist/cjs/endpoints/ChaptersEndpoints.js 238 + @@ -13,6 +13,8 @@ class ChaptersEndpoints extends EndpointsBase_js_1.default { 239 + // TODO: Only returns top 50, validate / pre-check here 240 + const params = this.paramsFor({ ids: idOrIds, market }); 241 + const response = await this.getRequest(`chapters${params}`); 242 + + if (!response) 243 + + return response; 244 + return response.chapters; 245 + } 246 + } 126 247 diff --git a/dist/cjs/endpoints/ChaptersEndpoints.js.map b/dist/cjs/endpoints/ChaptersEndpoints.js.map 127 - index b47dff3998031c839fc89777937b00373ad8bd4e..a78b064098b825d65f1272420f388fcbbc79ff8f 100644 248 + index b47dff3998031c839fc89777937b00373ad8bd4e..2b2588de79ed0f2cbb141428dac235e9517550de 100644 128 249 --- a/dist/cjs/endpoints/ChaptersEndpoints.js.map 129 250 +++ b/dist/cjs/endpoints/ChaptersEndpoints.js.map 130 251 @@ -1 +1 @@ 131 252 -{"version":3,"file":"ChaptersEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/ChaptersEndpoints.ts"],"names":[],"mappings":";;;;;AACA,0EAA+C;AAK/C,MAAqB,iBAAkB,SAAQ,0BAAa;IAGjD,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAqB;QAC9D,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;YAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1C,OAAO,IAAI,CAAC,UAAU,CAAU,YAAY,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;SACnE;QAED,uDAAuD;QACvD,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAW,WAAW,MAAM,EAAE,CAAC,CAAC;QACtE,OAAO,QAAQ,CAAC,QAAQ,CAAC;IAC7B,CAAC;CACJ;AAdD,oCAcC"} 132 253 \ No newline at end of file 133 - +{"version":3,"file":"ChaptersEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/ChaptersEndpoints.ts"],"names":[],"mappings":";;;;;AACA,0EAA+C;AAK/C,MAAqB,iBAAkB,SAAQ,0BAAa;IAGjD,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAqB;QAC9D,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1C,OAAO,IAAI,CAAC,UAAU,CAAU,YAAY,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;QACpE,CAAC;QAED,uDAAuD;QACvD,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAW,WAAW,MAAM,EAAE,CAAC,CAAC;QACtE,OAAO,QAAQ,CAAC,QAAQ,CAAC;IAC7B,CAAC;CACJ;AAdD,oCAcC"} 254 + +{"version":3,"file":"ChaptersEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/ChaptersEndpoints.ts"],"names":[],"mappings":";;;;;AACA,0EAA+C;AAK/C,MAAqB,iBAAkB,SAAQ,0BAAa;IAGjD,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAqB;QAC9D,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1C,OAAO,IAAI,CAAC,UAAU,CAAU,YAAY,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;QACpE,CAAC;QAED,uDAAuD;QACvD,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAW,WAAW,MAAM,EAAE,CAAC,CAAC;QACtE,IAAI,CAAC,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAC/B,OAAO,QAAQ,CAAC,QAAQ,CAAC;IAC7B,CAAC;CACJ;AAfD,oCAeC"} 134 255 \ No newline at end of file 256 + diff --git a/dist/cjs/endpoints/CurrentUserEndpoints.d.ts b/dist/cjs/endpoints/CurrentUserEndpoints.d.ts 257 + index ef1c96f9bb072d17d9ce2aecfd3ac918c0f268f9..20d31d09d22308a87cb0be7072c2a40937b58206 100644 258 + --- a/dist/cjs/endpoints/CurrentUserEndpoints.d.ts 259 + +++ b/dist/cjs/endpoints/CurrentUserEndpoints.d.ts 260 + @@ -9,47 +9,47 @@ export default class CurrentUserEndpoints extends EndpointsBase { 261 + shows: CurrentUserShowsEndpoints; 262 + tracks: CurrentUserTracksEndpoints; 263 + constructor(api: SpotifyApi); 264 + - profile(): Promise<UserProfile>; 265 + - topItems<T extends "artists" | "tracks">(type: T, time_range?: 'short_term' | 'medium_term' | 'long_term', limit?: MaxInt<50>, offset?: number): Promise<Page<T extends "artists" ? Artist : Track>>; 266 + - followedArtists(after?: string, limit?: MaxInt<50>): Promise<FollowedArtists>; 267 + + profile(): Promise<UserProfile | null>; 268 + + topItems<T extends "artists" | "tracks">(type: T, time_range?: 'short_term' | 'medium_term' | 'long_term', limit?: MaxInt<50>, offset?: number): Promise<Page<T extends "artists" ? Artist : Track> | null>; 269 + + followedArtists(after?: string, limit?: MaxInt<50>): Promise<FollowedArtists | null>; 270 + followArtistsOrUsers(ids: string[], type: 'artist' | 'user'): Promise<void>; 271 + unfollowArtistsOrUsers(ids: string[], type: 'artist' | 'user'): Promise<void>; 272 + - followsArtistsOrUsers(ids: string[], type: 'artist' | 'user'): Promise<boolean[]>; 273 + + followsArtistsOrUsers(ids: string[], type: 'artist' | 'user'): Promise<boolean[] | null>; 274 + } 275 + declare class CurrentUserAlbumsEndpoints extends EndpointsBase { 276 + - savedAlbums(limit?: MaxInt<50>, offset?: number, market?: Market): Promise<Page<SavedAlbum>>; 277 + + savedAlbums(limit?: MaxInt<50>, offset?: number, market?: Market): Promise<Page<SavedAlbum> | null>; 278 + saveAlbums(ids: string[]): Promise<void>; 279 + removeSavedAlbums(ids: string[]): Promise<void>; 280 + - hasSavedAlbums(ids: string[]): Promise<boolean[]>; 281 + + hasSavedAlbums(ids: string[]): Promise<boolean[] | null>; 282 + } 283 + declare class CurrentUserAudiobooksEndpoints extends EndpointsBase { 284 + - savedAudiobooks(limit?: MaxInt<50>, offset?: number): Promise<Page<SimplifiedAudiobook>>; 285 + + savedAudiobooks(limit?: MaxInt<50>, offset?: number): Promise<Page<SimplifiedAudiobook> | null>; 286 + saveAudiobooks(ids: string[]): Promise<void>; 287 + removeSavedAudiobooks(ids: string[]): Promise<void>; 288 + - hasSavedAudiobooks(ids: string[]): Promise<boolean[]>; 289 + + hasSavedAudiobooks(ids: string[]): Promise<boolean[] | null>; 290 + } 291 + declare class CurrentUserEpisodesEndpoints extends EndpointsBase { 292 + - savedEpisodes(market?: Market, limit?: MaxInt<50>, offset?: number): Promise<Page<SavedEpisode>>; 293 + + savedEpisodes(market?: Market, limit?: MaxInt<50>, offset?: number): Promise<Page<SavedEpisode> | null>; 294 + saveEpisodes(ids: string[]): Promise<void>; 295 + removeSavedEpisodes(ids: string[]): Promise<void>; 296 + - hasSavedEpisodes(ids: string[]): Promise<boolean[]>; 297 + + hasSavedEpisodes(ids: string[]): Promise<boolean[] | null>; 298 + } 299 + declare class CurrentUserPlaylistsEndpoints extends EndpointsBase { 300 + - playlists(limit?: MaxInt<50>, offset?: number): Promise<Page<SimplifiedPlaylist>>; 301 + + playlists(limit?: MaxInt<50>, offset?: number): Promise<Page<SimplifiedPlaylist> | null>; 302 + follow(playlist_id: string): Promise<void>; 303 + unfollow(playlist_id: string): Promise<void>; 304 + - isFollowing(playlistId: string, ids: string[]): Promise<boolean[]>; 305 + + isFollowing(playlistId: string, ids: string[]): Promise<boolean[] | null>; 306 + } 307 + declare class CurrentUserShowsEndpoints extends EndpointsBase { 308 + - savedShows(limit?: MaxInt<50>, offset?: number): Promise<Page<SavedShow>>; 309 + + savedShows(limit?: MaxInt<50>, offset?: number): Promise<Page<SavedShow> | null>; 310 + saveShows(ids: string[]): Promise<unknown>; 311 + removeSavedShows(ids: string[], market?: Market): Promise<unknown>; 312 + - hasSavedShow(ids: string[]): Promise<boolean[]>; 313 + + hasSavedShow(ids: string[]): Promise<boolean[] | null>; 314 + } 315 + declare class CurrentUserTracksEndpoints extends EndpointsBase { 316 + - savedTracks(limit?: MaxInt<50>, offset?: number, market?: Market): Promise<Page<SavedTrack>>; 317 + + savedTracks(limit?: MaxInt<50>, offset?: number, market?: Market): Promise<Page<SavedTrack> | null>; 318 + saveTracks(ids: string[]): Promise<void>; 319 + removeSavedTracks(ids: string[]): Promise<void>; 320 + - hasSavedTracks(ids: string[]): Promise<boolean[]>; 321 + + hasSavedTracks(ids: string[]): Promise<boolean[] | null>; 322 + } 323 + export {}; 324 + diff --git a/dist/cjs/endpoints/EndpointsBase.d.ts b/dist/cjs/endpoints/EndpointsBase.d.ts 325 + index c91dff76bfa4664d7a9976f84c98a8e65b08cb70..62e63dac60f91346fae2b6dc121e309df52ba3f3 100644 326 + --- a/dist/cjs/endpoints/EndpointsBase.d.ts 327 + +++ b/dist/cjs/endpoints/EndpointsBase.d.ts 328 + @@ -2,9 +2,9 @@ import { SpotifyApi } from "../SpotifyApi.js"; 329 + export default class EndpointsBase { 330 + protected api: SpotifyApi; 331 + constructor(api: SpotifyApi); 332 + - protected getRequest<TReturnType>(url: string): Promise<TReturnType>; 333 + - protected postRequest<TReturnType, TBody = unknown>(url: string, body?: TBody, contentType?: string | undefined): Promise<TReturnType>; 334 + - protected putRequest<TReturnType, TBody = unknown>(url: string, body?: TBody, contentType?: string | undefined): Promise<TReturnType>; 335 + - protected deleteRequest<TReturnType, TBody = unknown>(url: string, body?: TBody): Promise<TReturnType>; 336 + + protected getRequest<TReturnType>(url: string): Promise<TReturnType | null>; 337 + + protected postRequest<TReturnType, TBody = unknown>(url: string, body?: TBody, contentType?: string | undefined): Promise<TReturnType | null>; 338 + + protected putRequest<TReturnType, TBody = unknown>(url: string, body?: TBody, contentType?: string | undefined): Promise<TReturnType | null>; 339 + + protected deleteRequest<TReturnType, TBody = unknown>(url: string, body?: TBody): Promise<TReturnType | null>; 340 + protected paramsFor(args: any): string; 341 + } 135 342 diff --git a/dist/cjs/endpoints/EndpointsBase.js.map b/dist/cjs/endpoints/EndpointsBase.js.map 136 343 index f0473508d6cc503ca83c96ded895d202b48977b3..1b8c6d680673f2fedda300ebe82ccdbe7111b782 100644 137 344 --- a/dist/cjs/endpoints/EndpointsBase.js.map ··· 141 348 \ No newline at end of file 142 349 +{"version":3,"file":"EndpointsBase.js","sourceRoot":"","sources":["../../../src/endpoints/EndpointsBase.ts"],"names":[],"mappings":";;AAEA,MAAqB,aAAa;IACR;IAAtB,YAAsB,GAAe;QAAf,QAAG,GAAH,GAAG,CAAY;IACrC,CAAC;IAES,KAAK,CAAC,UAAU,CAAc,GAAW;QAC/C,OAAO,MAAM,IAAI,CAAC,GAAG,CAAC,WAAW,CAAc,KAAK,EAAE,GAAG,CAAC,CAAC;IAC/D,CAAC;IAES,KAAK,CAAC,WAAW,CAA+B,GAAW,EAAE,IAAY,EAAE,cAAkC,SAAS;QAC5H,OAAO,MAAM,IAAI,CAAC,GAAG,CAAC,WAAW,CAAc,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC;IACnF,CAAC;IAES,KAAK,CAAC,UAAU,CAA+B,GAAW,EAAE,IAAY,EAAE,cAAkC,SAAS;QAC3H,OAAO,MAAM,IAAI,CAAC,GAAG,CAAC,WAAW,CAAc,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC;IAClF,CAAC;IAES,KAAK,CAAC,aAAa,CAA+B,GAAW,EAAE,IAAY;QACjF,OAAO,MAAM,IAAI,CAAC,GAAG,CAAC,WAAW,CAAc,QAAQ,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;IACxE,CAAC;IAES,SAAS,CAAC,IAAS;QACzB,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QACrC,KAAK,IAAI,GAAG,IAAI,MAAM,CAAC,mBAAmB,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/C,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,SAAS,CAAC,EAAE,CAAC;gBACnF,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC7C,CAAC;QACL,CAAC;QACD,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACjE,CAAC;CACJ;AA7BD,gCA6BC"} 143 350 \ No newline at end of file 351 + diff --git a/dist/cjs/endpoints/EpisodesEndpoints.js b/dist/cjs/endpoints/EpisodesEndpoints.js 352 + index aa809afbe2f5e30bab4622b94c978700341651d8..58960a963d789cb7320bcee8517f8128762e85ad 100644 353 + --- a/dist/cjs/endpoints/EpisodesEndpoints.js 354 + +++ b/dist/cjs/endpoints/EpisodesEndpoints.js 355 + @@ -12,6 +12,8 @@ class EpisodesEndpoints extends EndpointsBase_js_1.default { 356 + } 357 + const params = this.paramsFor({ ids: idOrIds, market }); 358 + const response = await this.getRequest(`episodes${params}`); 359 + + if (!response) 360 + + return response; 361 + return response.episodes; 362 + } 363 + } 144 364 diff --git a/dist/cjs/endpoints/EpisodesEndpoints.js.map b/dist/cjs/endpoints/EpisodesEndpoints.js.map 145 - index 017ea1fb67b3751fff77c143d67f57514bb5b996..bc10678835b90f42d2a9be229570c95c3b8a56e5 100644 365 + index 017ea1fb67b3751fff77c143d67f57514bb5b996..c60f6af5f86147d8059412c3d89e4ba9beab762d 100644 146 366 --- a/dist/cjs/endpoints/EpisodesEndpoints.js.map 147 367 +++ b/dist/cjs/endpoints/EpisodesEndpoints.js.map 148 368 @@ -1 +1 @@ 149 369 -{"version":3,"file":"EpisodesEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/EpisodesEndpoints.ts"],"names":[],"mappings":";;;;;AACA,0EAA+C;AAE/C,MAAqB,iBAAkB,SAAQ,0BAAa;IAIjD,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAc;QACvD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;YAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1C,OAAO,IAAI,CAAC,UAAU,CAAU,YAAY,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;SACnE;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAW,WAAW,MAAM,EAAE,CAAC,CAAC;QACtE,OAAO,QAAQ,CAAC,QAAQ,CAAC;IAC7B,CAAC;CACJ;AAdD,oCAcC"} 150 370 \ No newline at end of file 151 - +{"version":3,"file":"EpisodesEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/EpisodesEndpoints.ts"],"names":[],"mappings":";;;;;AACA,0EAA+C;AAE/C,MAAqB,iBAAkB,SAAQ,0BAAa;IAIjD,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAc;QACvD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1C,OAAO,IAAI,CAAC,UAAU,CAAU,YAAY,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;QACpE,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAW,WAAW,MAAM,EAAE,CAAC,CAAC;QACtE,OAAO,QAAQ,CAAC,QAAQ,CAAC;IAC7B,CAAC;CACJ;AAdD,oCAcC"} 371 + +{"version":3,"file":"EpisodesEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/EpisodesEndpoints.ts"],"names":[],"mappings":";;;;;AACA,0EAA+C;AAE/C,MAAqB,iBAAkB,SAAQ,0BAAa;IAIjD,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAc;QACvD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1C,OAAO,IAAI,CAAC,UAAU,CAAU,YAAY,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;QACpE,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAW,WAAW,MAAM,EAAE,CAAC,CAAC;QACtE,IAAI,CAAC,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAC/B,OAAO,QAAQ,CAAC,QAAQ,CAAC;IAC7B,CAAC;CACJ;AAfD,oCAeC"} 152 372 \ No newline at end of file 373 + diff --git a/dist/cjs/endpoints/MarketsEndpoints.d.ts b/dist/cjs/endpoints/MarketsEndpoints.d.ts 374 + index 4ceb08e53ada5c140d6cba3267e8d60b35586827..cc046b287cf3a12a23cdec477d197319189b0c6b 100644 375 + --- a/dist/cjs/endpoints/MarketsEndpoints.d.ts 376 + +++ b/dist/cjs/endpoints/MarketsEndpoints.d.ts 377 + @@ -1,5 +1,5 @@ 378 + import type { Markets } from '../types.js'; 379 + import EndpointsBase from './EndpointsBase.js'; 380 + export default class MarketsEndpoints extends EndpointsBase { 381 + - getAvailableMarkets(): Promise<Markets>; 382 + + getAvailableMarkets(): Promise<Markets | null>; 383 + } 384 + diff --git a/dist/cjs/endpoints/PlayerEndpoints.d.ts b/dist/cjs/endpoints/PlayerEndpoints.d.ts 385 + index 52792b8fb66f5a4e5056c674a175fb12d9b6c43b..2b6ec0f5e0199cd5d908e63fe6b410fce8c55315 100644 386 + --- a/dist/cjs/endpoints/PlayerEndpoints.d.ts 387 + +++ b/dist/cjs/endpoints/PlayerEndpoints.d.ts 388 + @@ -5,11 +5,11 @@ interface QueryRange { 389 + type: "before" | "after"; 390 + } 391 + export default class PlayerEndpoints extends EndpointsBase { 392 + - getPlaybackState(market?: Market, additional_types?: string): Promise<PlaybackState>; 393 + - getAvailableDevices(): Promise<Devices>; 394 + - getCurrentlyPlayingTrack(market?: Market, additional_types?: string): Promise<PlaybackState>; 395 + - getRecentlyPlayedTracks(limit?: MaxInt<50>, queryRange?: QueryRange): Promise<RecentlyPlayedTracksPage>; 396 + - getUsersQueue(): Promise<Queue>; 397 + + getPlaybackState(market?: Market, additional_types?: string): Promise<PlaybackState | null>; 398 + + getAvailableDevices(): Promise<Devices | null>; 399 + + getCurrentlyPlayingTrack(market?: Market, additional_types?: string): Promise<PlaybackState | null>; 400 + + getRecentlyPlayedTracks(limit?: MaxInt<50>, queryRange?: QueryRange): Promise<RecentlyPlayedTracksPage | null>; 401 + + getUsersQueue(): Promise<Queue | null>; 402 + transferPlayback(device_ids: string[], play?: boolean): Promise<void>; 403 + startResumePlayback(device_id: string, context_uri?: string, uris?: string[], offset?: object, positionMs?: number): Promise<void>; 404 + pausePlayback(device_id: string): Promise<void>; 153 405 diff --git a/dist/cjs/endpoints/PlayerEndpoints.js.map b/dist/cjs/endpoints/PlayerEndpoints.js.map 154 406 index 94159b453d45d007e614ab4f0d81e8eafd4501f3..c862611b08e57318150f4218c0d74580b4a5473b 100644 155 407 --- a/dist/cjs/endpoints/PlayerEndpoints.js.map ··· 160 412 +{"version":3,"file":"PlayerEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/PlayerEndpoints.ts"],"names":[],"mappings":"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"} 161 413 \ No newline at end of file 162 414 diff --git a/dist/cjs/endpoints/PlaylistsEndpoints.d.ts b/dist/cjs/endpoints/PlaylistsEndpoints.d.ts 163 - index 8760c8c7b8d61681a85537a40d33aafeff8d1cd0..8a439ea2f95f5bdbd5bec4cc9dde867e06d74ec2 100644 415 + index 8760c8c7b8d61681a85537a40d33aafeff8d1cd0..1477d0769fae34f47b34a4d85c46e29337dac979 100644 164 416 --- a/dist/cjs/endpoints/PlaylistsEndpoints.d.ts 165 417 +++ b/dist/cjs/endpoints/PlaylistsEndpoints.d.ts 166 - @@ -1,4 +1,3 @@ 418 + @@ -1,17 +1,16 @@ 167 419 -/// <reference types="node" /> 168 420 import type { Market, Playlist, MaxInt, Page, Track, SnapshotReference, Image, PlaylistedTrack, QueryAdditionalTypes, TrackItem } from '../types.js'; 169 421 import EndpointsBase from './EndpointsBase.js'; 170 422 export default class PlaylistsEndpoints extends EndpointsBase { 423 + - getPlaylist<AdditionalTypes extends QueryAdditionalTypes | undefined = undefined>(playlist_id: string, market?: Market, fields?: string, additional_types?: AdditionalTypes): Promise<Playlist<AdditionalTypes extends undefined ? Track : TrackItem>>; 424 + - getPlaylistItems<AdditionalTypes extends QueryAdditionalTypes | undefined = undefined>(playlist_id: string, market?: Market, fields?: string, limit?: MaxInt<50>, offset?: number, additional_types?: AdditionalTypes): Promise<Page<PlaylistedTrack<AdditionalTypes extends undefined ? Track : TrackItem>>>; 425 + + getPlaylist<AdditionalTypes extends QueryAdditionalTypes | undefined = undefined>(playlist_id: string, market?: Market, fields?: string, additional_types?: AdditionalTypes): Promise<Playlist<AdditionalTypes extends undefined ? Track : TrackItem> | null>; 426 + + getPlaylistItems<AdditionalTypes extends QueryAdditionalTypes | undefined = undefined>(playlist_id: string, market?: Market, fields?: string, limit?: MaxInt<50>, offset?: number, additional_types?: AdditionalTypes): Promise<Page<PlaylistedTrack<AdditionalTypes extends undefined ? Track : TrackItem>> | null>; 427 + changePlaylistDetails(playlist_id: string, request: ChangePlaylistDetailsRequest): Promise<void>; 428 + - movePlaylistItems(playlist_id: string, range_start: number, range_length: number, moveToPosition: number): Promise<SnapshotReference>; 429 + - updatePlaylistItems(playlist_id: string, request: UpdatePlaylistItemsRequest): Promise<SnapshotReference>; 430 + + movePlaylistItems(playlist_id: string, range_start: number, range_length: number, moveToPosition: number): Promise<SnapshotReference | null>; 431 + + updatePlaylistItems(playlist_id: string, request: UpdatePlaylistItemsRequest): Promise<SnapshotReference | null>; 432 + addItemsToPlaylist(playlist_id: string, uris?: string[], position?: number): Promise<void>; 433 + removeItemsFromPlaylist(playlist_id: string, request: RemovePlaylistItemsRequest): Promise<void>; 434 + - getUsersPlaylists(user_id: string, limit?: MaxInt<50>, offset?: number): Promise<Page<Playlist<TrackItem>>>; 435 + - createPlaylist(user_id: string, request: CreatePlaylistRequest): Promise<Playlist<TrackItem>>; 436 + - getPlaylistCoverImage(playlist_id: string): Promise<Image[]>; 437 + + getUsersPlaylists(user_id: string, limit?: MaxInt<50>, offset?: number): Promise<Page<Playlist<TrackItem>> | null>; 438 + + createPlaylist(user_id: string, request: CreatePlaylistRequest): Promise<Playlist<TrackItem> | null>; 439 + + getPlaylistCoverImage(playlist_id: string): Promise<Image[] | null>; 440 + addCustomPlaylistCoverImage(playlist_id: string, imageData: Buffer | HTMLImageElement | HTMLCanvasElement | string): Promise<void>; 441 + addCustomPlaylistCoverImageFromBase64String(playlist_id: string, base64EncodedJpeg: string): Promise<void>; 442 + } 171 443 diff --git a/dist/cjs/endpoints/PlaylistsEndpoints.js.map b/dist/cjs/endpoints/PlaylistsEndpoints.js.map 172 444 index 4bfe4e675a39d5043db26002aca95c1b321aed01..733e9743acf49400060efdb6d211e6871ef151c6 100644 173 445 --- a/dist/cjs/endpoints/PlaylistsEndpoints.js.map ··· 177 449 \ No newline at end of file 178 450 +{"version":3,"file":"PlaylistsEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/PlaylistsEndpoints.ts"],"names":[],"mappings":"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"} 179 451 \ No newline at end of file 452 + diff --git a/dist/cjs/endpoints/RecommendationsEndpoints.d.ts b/dist/cjs/endpoints/RecommendationsEndpoints.d.ts 453 + index ddd71517d997daee270a15e60782d6bd29fa3a6a..cf864f5fa1f48da6fc836df78a3a19e70eece0c5 100644 454 + --- a/dist/cjs/endpoints/RecommendationsEndpoints.d.ts 455 + +++ b/dist/cjs/endpoints/RecommendationsEndpoints.d.ts 456 + @@ -1,8 +1,8 @@ 457 + import type { Genres, Track } from '../types.js'; 458 + import EndpointsBase from './EndpointsBase.js'; 459 + export default class RecommendationsEndpoints extends EndpointsBase { 460 + - get(request: RecommendationsRequestRequiredArguments | RecommendationsRequest): Promise<RecommendationsResponse>; 461 + - genreSeeds(): Promise<Genres>; 462 + + get(request: RecommendationsRequestRequiredArguments | RecommendationsRequest): Promise<RecommendationsResponse | null>; 463 + + genreSeeds(): Promise<Genres | null>; 464 + } 465 + export interface RecommendationsRequestRequiredArguments { 466 + seed_artists?: string[]; 467 + diff --git a/dist/cjs/endpoints/SearchEndpoints.d.ts b/dist/cjs/endpoints/SearchEndpoints.d.ts 468 + index 71fcb99808b86ed766d459b11d09a2ad5080408d..6656f5bc3f1c94612ed548b96693692c7859cdf0 100644 469 + --- a/dist/cjs/endpoints/SearchEndpoints.d.ts 470 + +++ b/dist/cjs/endpoints/SearchEndpoints.d.ts 471 + @@ -1,8 +1,8 @@ 472 + import type { ItemTypes, Market, MaxInt, SearchResults } from '../types.js'; 473 + import EndpointsBase from './EndpointsBase.js'; 474 + export interface SearchExecutionFunction { 475 + - <const T extends readonly ItemTypes[]>(q: string, type: T, market?: Market, limit?: MaxInt<50>, offset?: number, include_external?: string): Promise<SearchResults<T>>; 476 + + <const T extends readonly ItemTypes[]>(q: string, type: T, market?: Market, limit?: MaxInt<50>, offset?: number, include_external?: string): Promise<SearchResults<T> | null>; 477 + } 478 + export default class SearchEndpoints extends EndpointsBase { 479 + - execute<const T extends readonly ItemTypes[]>(q: string, type: T, market?: Market, limit?: MaxInt<50>, offset?: number, include_external?: string): Promise<SearchResults<T>>; 480 + + execute<const T extends readonly ItemTypes[]>(q: string, type: T, market?: Market, limit?: MaxInt<50>, offset?: number, include_external?: string): Promise<SearchResults<T> | null>; 481 + } 482 + diff --git a/dist/cjs/endpoints/ShowsEndpoints.d.ts b/dist/cjs/endpoints/ShowsEndpoints.d.ts 483 + index 41b64a4de6399faa92e28aec51b977cddd06d00b..4e6fe35b6161bf21820819775281600f74a23325 100644 484 + --- a/dist/cjs/endpoints/ShowsEndpoints.d.ts 485 + +++ b/dist/cjs/endpoints/ShowsEndpoints.d.ts 486 + @@ -3,5 +3,5 @@ import EndpointsBase from './EndpointsBase.js'; 487 + export default class ShowsEndpoints extends EndpointsBase { 488 + get(id: string, market: Market): Promise<Show>; 489 + get(ids: string[], market: Market): Promise<Show[]>; 490 + - episodes(id: string, market?: Market, limit?: MaxInt<50>, offset?: number): Promise<Page<SimplifiedEpisode>>; 491 + + episodes(id: string, market?: Market, limit?: MaxInt<50>, offset?: number): Promise<Page<SimplifiedEpisode> | null>; 492 + } 493 + diff --git a/dist/cjs/endpoints/ShowsEndpoints.js b/dist/cjs/endpoints/ShowsEndpoints.js 494 + index fe5565df19dc961e1a238e07847d230e3d4d27e6..4864a186e753748e85544e36da09f90d2c20e3b6 100644 495 + --- a/dist/cjs/endpoints/ShowsEndpoints.js 496 + +++ b/dist/cjs/endpoints/ShowsEndpoints.js 497 + @@ -13,6 +13,8 @@ class ShowsEndpoints extends EndpointsBase_js_1.default { 498 + // TODO: only returns 50, validate here 499 + const params = this.paramsFor({ ids: idOrIds, market }); 500 + const response = await this.getRequest(`shows${params}`); 501 + + if (!response) 502 + + return response; 503 + return response.shows; 504 + } 505 + episodes(id, market, limit, offset) { 180 506 diff --git a/dist/cjs/endpoints/ShowsEndpoints.js.map b/dist/cjs/endpoints/ShowsEndpoints.js.map 181 - index 4b4438eaaa344bbe5161c18ce31a25dd0a007e19..1cc228ddceafcfb3551c3431b2401a99cdd2f747 100644 507 + index 4b4438eaaa344bbe5161c18ce31a25dd0a007e19..bc822b62ea5a1c3f4d733c89eb61f321bdfc849c 100644 182 508 --- a/dist/cjs/endpoints/ShowsEndpoints.js.map 183 509 +++ b/dist/cjs/endpoints/ShowsEndpoints.js.map 184 510 @@ -1 +1 @@ 185 511 -{"version":3,"file":"ShowsEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/ShowsEndpoints.ts"],"names":[],"mappings":";;;;;AACA,0EAA+C;AAE/C,MAAqB,cAAe,SAAQ,0BAAa;IAI9C,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAc;QACvD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;YAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAA;YACzC,OAAO,IAAI,CAAC,UAAU,CAAO,SAAS,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;SAC7D;QAED,uCAAuC;QACvC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAQ,QAAQ,MAAM,EAAE,CAAC,CAAC;QAChE,OAAO,QAAQ,CAAC,KAAK,CAAC;IAC1B,CAAC;IAEM,QAAQ,CAAC,EAAU,EAAE,MAAe,EAAE,KAAkB,EAAE,MAAe;QAC5E,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;QACxD,OAAO,IAAI,CAAC,UAAU,CAA0B,SAAS,EAAE,YAAY,MAAM,EAAE,CAAC,CAAC;IACrF,CAAC;CACJ;AApBD,iCAoBC"} 186 512 \ No newline at end of file 187 - +{"version":3,"file":"ShowsEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/ShowsEndpoints.ts"],"names":[],"mappings":";;;;;AACA,0EAA+C;AAE/C,MAAqB,cAAe,SAAQ,0BAAa;IAI9C,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAc;QACvD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAA;YACzC,OAAO,IAAI,CAAC,UAAU,CAAO,SAAS,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;QAC9D,CAAC;QAED,uCAAuC;QACvC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAQ,QAAQ,MAAM,EAAE,CAAC,CAAC;QAChE,OAAO,QAAQ,CAAC,KAAK,CAAC;IAC1B,CAAC;IAEM,QAAQ,CAAC,EAAU,EAAE,MAAe,EAAE,KAAkB,EAAE,MAAe;QAC5E,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;QACxD,OAAO,IAAI,CAAC,UAAU,CAA0B,SAAS,EAAE,YAAY,MAAM,EAAE,CAAC,CAAC;IACrF,CAAC;CACJ;AApBD,iCAoBC"} 513 + +{"version":3,"file":"ShowsEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/ShowsEndpoints.ts"],"names":[],"mappings":";;;;;AACA,0EAA+C;AAE/C,MAAqB,cAAe,SAAQ,0BAAa;IAI9C,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAc;QACvD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAA;YACzC,OAAO,IAAI,CAAC,UAAU,CAAO,SAAS,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;QAC9D,CAAC;QAED,uCAAuC;QACvC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAQ,QAAQ,MAAM,EAAE,CAAC,CAAC;QAChE,IAAI,CAAC,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAC/B,OAAO,QAAQ,CAAC,KAAK,CAAC;IAC1B,CAAC;IAEM,QAAQ,CAAC,EAAU,EAAE,MAAe,EAAE,KAAkB,EAAE,MAAe;QAC5E,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;QACxD,OAAO,IAAI,CAAC,UAAU,CAA0B,SAAS,EAAE,YAAY,MAAM,EAAE,CAAC,CAAC;IACrF,CAAC;CACJ;AArBD,iCAqBC"} 188 514 \ No newline at end of file 515 + diff --git a/dist/cjs/endpoints/TracksEndpoints.d.ts b/dist/cjs/endpoints/TracksEndpoints.d.ts 516 + index 5a2811cbe7365ec4e81823f69046dea8141941de..7a8109f3f656be9ed76e4f781e83343c85a907d7 100644 517 + --- a/dist/cjs/endpoints/TracksEndpoints.d.ts 518 + +++ b/dist/cjs/endpoints/TracksEndpoints.d.ts 519 + @@ -5,5 +5,5 @@ export default class TracksEndpoints extends EndpointsBase { 520 + get(ids: string[], market?: Market): Promise<Track[]>; 521 + audioFeatures(id: string): Promise<AudioFeatures>; 522 + audioFeatures(ids: string[]): Promise<AudioFeatures[]>; 523 + - audioAnalysis(id: string): Promise<AudioAnalysis>; 524 + + audioAnalysis(id: string): Promise<AudioAnalysis | null>; 525 + } 526 + diff --git a/dist/cjs/endpoints/TracksEndpoints.js b/dist/cjs/endpoints/TracksEndpoints.js 527 + index ff233256c9f33dba91583197a8b5ef27e21f470d..b2979f790208db343d83ef929994ec5fe2d30dc9 100644 528 + --- a/dist/cjs/endpoints/TracksEndpoints.js 529 + +++ b/dist/cjs/endpoints/TracksEndpoints.js 530 + @@ -13,6 +13,8 @@ class TracksEndpoints extends EndpointsBase_js_1.default { 531 + const params = this.paramsFor({ ids: idOrIds, market }); 532 + // TODO: only returns top 20, validate here 533 + const response = await this.getRequest(`tracks${params}`); 534 + + if (!response) 535 + + return response; 536 + return response.tracks; 537 + } 538 + async audioFeatures(idOrIds) { 539 + @@ -21,6 +23,8 @@ class TracksEndpoints extends EndpointsBase_js_1.default { 540 + } 541 + const params = this.paramsFor({ ids: idOrIds }); 542 + const response = await this.getRequest(`audio-features${params}`); 543 + + if (!response) 544 + + return response; 545 + return response.audio_features; 546 + } 547 + audioAnalysis(id) { 189 548 diff --git a/dist/cjs/endpoints/TracksEndpoints.js.map b/dist/cjs/endpoints/TracksEndpoints.js.map 190 - index 4a7e10a5243a977c350f671555dabed75ecb6bea..d3a3d4c9ea19af96f1f0bc95ed4a32fe51015ab4 100644 549 + index 4a7e10a5243a977c350f671555dabed75ecb6bea..2b87ede72498b34c2bf5eed23e422b56610daff6 100644 191 550 --- a/dist/cjs/endpoints/TracksEndpoints.js.map 192 551 +++ b/dist/cjs/endpoints/TracksEndpoints.js.map 193 552 @@ -1 +1 @@ 194 553 -{"version":3,"file":"TracksEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/TracksEndpoints.ts"],"names":[],"mappings":";;;;;AACA,0EAA+C;AAE/C,MAAqB,eAAgB,SAAQ,0BAAa;IAI/C,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAe;QACxD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;YAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1C,OAAO,IAAI,CAAC,UAAU,CAAQ,UAAU,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;SAC/D;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,2CAA2C;QAC3C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAS,SAAS,MAAM,EAAE,CAAC,CAAC;QAClE,OAAO,QAAQ,CAAC,MAAM,CAAC;IAC3B,CAAC;IAIM,KAAK,CAAC,aAAa,CAAC,OAA0B;QACjD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;YAC7B,OAAO,IAAI,CAAC,UAAU,CAAgB,kBAAkB,OAAO,EAAE,CAAC,CAAC;SACtE;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QAChD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAA0B,iBAAiB,MAAM,EAAE,CAAC,CAAC;QAC3F,OAAO,QAAQ,CAAC,cAAc,CAAC;IACnC,CAAC;IAEM,aAAa,CAAC,EAAU;QAC3B,OAAO,IAAI,CAAC,UAAU,CAAgB,kBAAkB,EAAE,EAAE,CAAC,CAAC;IAClE,CAAC;CAEJ;AA/BD,kCA+BC"} 195 554 \ No newline at end of file 196 - +{"version":3,"file":"TracksEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/TracksEndpoints.ts"],"names":[],"mappings":";;;;;AACA,0EAA+C;AAE/C,MAAqB,eAAgB,SAAQ,0BAAa;IAI/C,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAe;QACxD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1C,OAAO,IAAI,CAAC,UAAU,CAAQ,UAAU,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;QAChE,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,2CAA2C;QAC3C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAS,SAAS,MAAM,EAAE,CAAC,CAAC;QAClE,OAAO,QAAQ,CAAC,MAAM,CAAC;IAC3B,CAAC;IAIM,KAAK,CAAC,aAAa,CAAC,OAA0B;QACjD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC,UAAU,CAAgB,kBAAkB,OAAO,EAAE,CAAC,CAAC;QACvE,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QAChD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAA0B,iBAAiB,MAAM,EAAE,CAAC,CAAC;QAC3F,OAAO,QAAQ,CAAC,cAAc,CAAC;IACnC,CAAC;IAEM,aAAa,CAAC,EAAU;QAC3B,OAAO,IAAI,CAAC,UAAU,CAAgB,kBAAkB,EAAE,EAAE,CAAC,CAAC;IAClE,CAAC;CAEJ;AA/BD,kCA+BC"} 555 + +{"version":3,"file":"TracksEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/TracksEndpoints.ts"],"names":[],"mappings":";;;;;AACA,0EAA+C;AAE/C,MAAqB,eAAgB,SAAQ,0BAAa;IAI/C,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAe;QACxD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1C,OAAO,IAAI,CAAC,UAAU,CAAQ,UAAU,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;QAChE,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,2CAA2C;QAC3C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAS,SAAS,MAAM,EAAE,CAAC,CAAC;QAClE,IAAI,CAAC,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAC/B,OAAO,QAAQ,CAAC,MAAM,CAAC;IAC3B,CAAC;IAIM,KAAK,CAAC,aAAa,CAAC,OAA0B;QACjD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC,UAAU,CAAgB,kBAAkB,OAAO,EAAE,CAAC,CAAC;QACvE,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QAChD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAA0B,iBAAiB,MAAM,EAAE,CAAC,CAAC;QAC3F,IAAI,CAAC,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAC/B,OAAO,QAAQ,CAAC,cAAc,CAAC;IACnC,CAAC;IAEM,aAAa,CAAC,EAAU;QAC3B,OAAO,IAAI,CAAC,UAAU,CAAgB,kBAAkB,EAAE,EAAE,CAAC,CAAC;IAClE,CAAC;CAEJ;AAjCD,kCAiCC"} 197 556 \ No newline at end of file 198 - diff --git a/dist/cjs/index.d.ts b/dist/cjs/index.d.ts 199 - index fbf77964cdd33a0bac5c37ad35e2b1af18d95cd4..44ddaef876d324384ab51d28b5a83300d3be84e7 100644 200 - --- a/dist/cjs/index.d.ts 201 - +++ b/dist/cjs/index.d.ts 202 - @@ -12,7 +12,8 @@ import DocumentLocationRedirectionStrategy from "./redirection/DocumentLocationR 203 - import DefaultResponseValidator from "./responsevalidation/DefaultResponseValidator.js"; 204 - import DefaultResponseDeserializer from "./serialization/DefaultResponseDeserializer.js"; 205 - import { Scopes } from "./Scopes.js"; 206 - +import ProvidedAccessTokenStrategy from "./auth/ProvidedAccessTokenStrategy.js"; 207 - import { emptyAccessToken } from "./auth/IAuthStrategy.js"; 208 - -export { SpotifyApi, AuthorizationCodeWithPKCEStrategy, ClientCredentialsStrategy, InMemoryCachingStrategy, LocalStorageCachingStrategy, GenericCache, ConsoleLoggingErrorHandler, NoOpErrorHandler, DocumentLocationRedirectionStrategy, DefaultResponseValidator, DefaultResponseDeserializer, Scopes, emptyAccessToken }; 209 - +export { SpotifyApi, AuthorizationCodeWithPKCEStrategy, ClientCredentialsStrategy, InMemoryCachingStrategy, LocalStorageCachingStrategy, GenericCache, ConsoleLoggingErrorHandler, NoOpErrorHandler, DocumentLocationRedirectionStrategy, DefaultResponseValidator, DefaultResponseDeserializer, Scopes, ProvidedAccessTokenStrategy, emptyAccessToken, }; 210 - export type * from "./types.js"; 211 - -export type { IAuthStrategy, ICacheStore, }; 212 - +export type { IAuthStrategy, ICacheStore }; 213 - diff --git a/dist/cjs/index.js b/dist/cjs/index.js 214 - index 8a61bc1e3b1d350548a56297763db57b348cf036..7fa6b7fe124d083df5e433bf9ca062431b9a931a 100644 215 - --- a/dist/cjs/index.js 216 - +++ b/dist/cjs/index.js 217 - @@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { 218 - return (mod && mod.__esModule) ? mod : { "default": mod }; 219 - }; 220 - Object.defineProperty(exports, "__esModule", { value: true }); 221 - -exports.emptyAccessToken = exports.Scopes = exports.DefaultResponseDeserializer = exports.DefaultResponseValidator = exports.DocumentLocationRedirectionStrategy = exports.NoOpErrorHandler = exports.ConsoleLoggingErrorHandler = exports.GenericCache = exports.LocalStorageCachingStrategy = exports.InMemoryCachingStrategy = exports.ClientCredentialsStrategy = exports.AuthorizationCodeWithPKCEStrategy = exports.SpotifyApi = void 0; 222 - +exports.emptyAccessToken = exports.ProvidedAccessTokenStrategy = exports.Scopes = exports.DefaultResponseDeserializer = exports.DefaultResponseValidator = exports.DocumentLocationRedirectionStrategy = exports.NoOpErrorHandler = exports.ConsoleLoggingErrorHandler = exports.GenericCache = exports.LocalStorageCachingStrategy = exports.InMemoryCachingStrategy = exports.ClientCredentialsStrategy = exports.AuthorizationCodeWithPKCEStrategy = exports.SpotifyApi = void 0; 223 - const SpotifyApi_js_1 = require("./SpotifyApi.js"); 224 - Object.defineProperty(exports, "SpotifyApi", { enumerable: true, get: function () { return SpotifyApi_js_1.SpotifyApi; } }); 225 - const AuthorizationCodeWithPKCEStrategy_js_1 = __importDefault(require("./auth/AuthorizationCodeWithPKCEStrategy.js")); 226 - @@ -28,6 +28,8 @@ const DefaultResponseDeserializer_js_1 = __importDefault(require("./serializatio 227 - exports.DefaultResponseDeserializer = DefaultResponseDeserializer_js_1.default; 228 - const Scopes_js_1 = require("./Scopes.js"); 229 - Object.defineProperty(exports, "Scopes", { enumerable: true, get: function () { return Scopes_js_1.Scopes; } }); 230 - +const ProvidedAccessTokenStrategy_js_1 = __importDefault(require("./auth/ProvidedAccessTokenStrategy.js")); 231 - +exports.ProvidedAccessTokenStrategy = ProvidedAccessTokenStrategy_js_1.default; 232 - const IAuthStrategy_js_1 = require("./auth/IAuthStrategy.js"); 233 - Object.defineProperty(exports, "emptyAccessToken", { enumerable: true, get: function () { return IAuthStrategy_js_1.emptyAccessToken; } }); 234 - //# sourceMappingURL=index.js.map 235 - \ No newline at end of file 236 - diff --git a/dist/cjs/index.js.map b/dist/cjs/index.js.map 237 - index 46aff6b589a7a9b2ba5c22bae770313f827ee9d3..158f74fc9607ace092aa7a1e4cabb2e4cc234957 100644 238 - --- a/dist/cjs/index.js.map 239 - +++ b/dist/cjs/index.js.map 240 - @@ -1 +1 @@ 241 - -{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;AAAA,mDAA6C;AAiBzC,2FAjBK,0BAAU,OAiBL;AAhBd,uHAA4F;AAiBxF,4CAjBG,8CAAiC,CAiBH;AAhBrC,uGAA4E;AAiBxE,oCAjBG,sCAAyB,CAiBH;AAf7B,sGAA2E;AAgBvE,kCAhBG,oCAAuB,CAgBH;AAf3B,8GAAmF;AAgB/E,sCAhBG,wCAA2B,CAgBH;AAd/B,gFAAqD;AAejD,uBAfG,yBAAY,CAeH;AAdhB,kHAAuF;AAenF,qCAfG,uCAA0B,CAeH;AAd9B,8FAAmE;AAe/D,2BAfG,6BAAgB,CAeH;AAdpB,kIAAuG;AAenG,8CAfG,gDAAmC,CAeH;AAdvC,mHAAwF;AAepF,mCAfG,qCAAwB,CAeH;AAd5B,oHAAyF;AAerF,sCAfG,wCAA2B,CAeH;AAd/B,2CAAqC;AAejC,uFAfK,kBAAM,OAeL;AAdV,8DAA2D;AAevD,iGAfK,mCAAgB,OAeL"} 242 - \ No newline at end of file 243 - +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;AAAA,mDAA6C;AAkB3C,2FAlBO,0BAAU,OAkBP;AAjBZ,uHAA4F;AAkB1F,4CAlBK,8CAAiC,CAkBL;AAjBnC,uGAA4E;AAkB1E,oCAlBK,sCAAyB,CAkBL;AAhB3B,sGAA2E;AAiBzE,kCAjBK,oCAAuB,CAiBL;AAhBzB,8GAAmF;AAiBjF,sCAjBK,wCAA2B,CAiBL;AAf7B,gFAAqD;AAgBnD,uBAhBK,yBAAY,CAgBL;AAfd,kHAAuF;AAgBrF,qCAhBK,uCAA0B,CAgBL;AAf5B,8FAAmE;AAgBjE,2BAhBK,6BAAgB,CAgBL;AAflB,kIAAuG;AAgBrG,8CAhBK,gDAAmC,CAgBL;AAfrC,mHAAwF;AAgBtF,mCAhBK,qCAAwB,CAgBL;AAf1B,oHAAyF;AAgBvF,sCAhBK,wCAA2B,CAgBL;AAf7B,2CAAqC;AAgBnC,uFAhBO,kBAAM,OAgBP;AAfR,2GAAgF;AAgB9E,sCAhBK,wCAA2B,CAgBL;AAf7B,8DAA2D;AAgBzD,iGAhBO,mCAAgB,OAgBP"} 244 - \ No newline at end of file 557 + diff --git a/dist/cjs/endpoints/UsersEndpoints.d.ts b/dist/cjs/endpoints/UsersEndpoints.d.ts 558 + index 613633e0d2cf885fbc0aca7a67855b67dbcc465e..172bf9cf6f6d69e2fad97b578ef487d28e34f90f 100644 559 + --- a/dist/cjs/endpoints/UsersEndpoints.d.ts 560 + +++ b/dist/cjs/endpoints/UsersEndpoints.d.ts 561 + @@ -1,5 +1,5 @@ 562 + import type { User } from '../types.js'; 563 + import EndpointsBase from './EndpointsBase.js'; 564 + export default class UsersEndpoints extends EndpointsBase { 565 + - profile(userId: string): Promise<User>; 566 + + profile(userId: string): Promise<User | null>; 567 + } 245 568 diff --git a/dist/cjs/responsevalidation/DefaultResponseValidator.js.map b/dist/cjs/responsevalidation/DefaultResponseValidator.js.map 246 569 index 068804c9b81eb0a8b14280e3cac9ae1f978d788f..183a8e3201157d54088092006c84a3502f752ba4 100644 247 570 --- a/dist/cjs/responsevalidation/DefaultResponseValidator.js.map ··· 260 583 \ No newline at end of file 261 584 +{"version":3,"file":"DefaultResponseDeserializer.js","sourceRoot":"","sources":["../../../src/serialization/DefaultResponseDeserializer.ts"],"names":[],"mappings":";;AAEA,MAAqB,2BAA2B;IACrC,KAAK,CAAC,WAAW,CAAc,QAAkB;QACpD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAEnC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC9B,OAAO,IAAmB,CAAC;QAC/B,CAAC;QAED,OAAO,IAAmB,CAAC;IAC/B,CAAC;CACJ;AAXD,8CAWC"} 262 585 \ No newline at end of file 586 + diff --git a/dist/mjs/SpotifyApi.d.ts b/dist/mjs/SpotifyApi.d.ts 587 + index cf5eff3cb728065892287539b2a85e2fe16b283b..fe3c2a037f4e47e6c748753a5661261552cfcc1b 100644 588 + --- a/dist/mjs/SpotifyApi.d.ts 589 + +++ b/dist/mjs/SpotifyApi.d.ts 590 + @@ -35,7 +35,7 @@ export declare class SpotifyApi { 591 + search: SearchExecutionFunction; 592 + currentUser: CurrentUserEndpoints; 593 + constructor(authentication: IAuthStrategy, config?: SdkOptions); 594 + - makeRequest<TReturnType>(method: "GET" | "POST" | "PUT" | "DELETE", url: string, body?: any, contentType?: string | undefined): Promise<TReturnType>; 595 + + makeRequest<TReturnType>(method: "GET" | "POST" | "PUT" | "DELETE", url: string, body?: any, contentType?: string | undefined): Promise<TReturnType | null>; 596 + private initializeSdk; 597 + switchAuthenticationStrategy(authentication: IAuthStrategy): void; 598 + /** 263 599 diff --git a/dist/mjs/SpotifyApi.js.map b/dist/mjs/SpotifyApi.js.map 264 600 index e98086ce346896a304fce6450801e17c0ec79b2a..8a04aacb1823ed6fbc8fb4d5ce9a7050ad0e7754 100644 265 601 --- a/dist/mjs/SpotifyApi.js.map ··· 332 668 \ No newline at end of file 333 669 +{"version":3,"file":"GenericCache.js","sourceRoot":"","sources":["../../../src/caching/GenericCache.ts"],"names":[],"mappings":"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"} 334 670 \ No newline at end of file 671 + diff --git a/dist/mjs/endpoints/AlbumsEndpoints.d.ts b/dist/mjs/endpoints/AlbumsEndpoints.d.ts 672 + index 18274fea2c934cd17f8ca87d551477cf8bda5291..bed7d9e02f1e65693b5f6772e78463a52ef442a8 100644 673 + --- a/dist/mjs/endpoints/AlbumsEndpoints.d.ts 674 + +++ b/dist/mjs/endpoints/AlbumsEndpoints.d.ts 675 + @@ -3,5 +3,5 @@ import EndpointsBase from './EndpointsBase.js'; 676 + export default class AlbumsEndpoints extends EndpointsBase { 677 + get(id: string, market?: Market): Promise<Album>; 678 + get(ids: string[], market?: Market): Promise<Album[]>; 679 + - tracks(albumId: string, market?: Market, limit?: MaxInt<50>, offset?: number): Promise<Page<SimplifiedTrack>>; 680 + + tracks(albumId: string, market?: Market, limit?: MaxInt<50>, offset?: number): Promise<Page<SimplifiedTrack> | null>; 681 + } 682 + diff --git a/dist/mjs/endpoints/AlbumsEndpoints.js b/dist/mjs/endpoints/AlbumsEndpoints.js 683 + index f93c182f9ab3a47c25db61a5cc896b65b89c249d..1b761c1b125b704e5c6fe48ba278ceb999f34192 100644 684 + --- a/dist/mjs/endpoints/AlbumsEndpoints.js 685 + +++ b/dist/mjs/endpoints/AlbumsEndpoints.js 686 + @@ -9,6 +9,8 @@ export default class AlbumsEndpoints extends EndpointsBase { 687 + const params = this.paramsFor({ ids: idOrIds, market }); 688 + // TODO: only returns top 20, validate here 689 + const response = await this.getRequest(`albums${params}`); 690 + + if (!response) 691 + + return response; 692 + return response.albums; 693 + } 694 + tracks(albumId, market, limit, offset) { 335 695 diff --git a/dist/mjs/endpoints/AlbumsEndpoints.js.map b/dist/mjs/endpoints/AlbumsEndpoints.js.map 336 - index e0b9429b4a0a7bcf28635430262b0345c40938b2..2b89fc1b01507a7230d7c891bda9e407d6ffb445 100644 696 + index e0b9429b4a0a7bcf28635430262b0345c40938b2..07be0dc89ec1e4dcb7020fb0e8474f13b7712a36 100644 337 697 --- a/dist/mjs/endpoints/AlbumsEndpoints.js.map 338 698 +++ b/dist/mjs/endpoints/AlbumsEndpoints.js.map 339 699 @@ -1 +1 @@ 340 700 -{"version":3,"file":"AlbumsEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/AlbumsEndpoints.ts"],"names":[],"mappings":"AACA,OAAO,aAAa,MAAM,oBAAoB,CAAC;AAE/C,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,aAAa;IAI/C,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAe;QACxD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;YAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1C,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,UAAU,CAAQ,UAAU,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;YACzE,OAAO,KAAK,CAAC;SAChB;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,2CAA2C;QAC3C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAS,SAAS,MAAM,EAAE,CAAC,CAAC;QAClE,OAAO,QAAQ,CAAC,MAAM,CAAC;IAC3B,CAAC;IAEM,MAAM,CAAC,OAAe,EAAE,MAAe,EAAE,KAAkB,EAAE,MAAe;QAC/E,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACzD,OAAO,IAAI,CAAC,UAAU,CAAwB,UAAU,OAAO,UAAU,MAAM,EAAE,CAAC,CAAC;IACvF,CAAC;CACJ"} 341 701 \ No newline at end of file 342 - +{"version":3,"file":"AlbumsEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/AlbumsEndpoints.ts"],"names":[],"mappings":"AACA,OAAO,aAAa,MAAM,oBAAoB,CAAC;AAE/C,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,aAAa;IAI/C,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAe;QACxD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1C,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,UAAU,CAAQ,UAAU,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;YACzE,OAAO,KAAK,CAAC;QACjB,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,2CAA2C;QAC3C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAS,SAAS,MAAM,EAAE,CAAC,CAAC;QAClE,OAAO,QAAQ,CAAC,MAAM,CAAC;IAC3B,CAAC;IAEM,MAAM,CAAC,OAAe,EAAE,MAAe,EAAE,KAAkB,EAAE,MAAe;QAC/E,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACzD,OAAO,IAAI,CAAC,UAAU,CAAwB,UAAU,OAAO,UAAU,MAAM,EAAE,CAAC,CAAC;IACvF,CAAC;CACJ"} 702 + +{"version":3,"file":"AlbumsEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/AlbumsEndpoints.ts"],"names":[],"mappings":"AACA,OAAO,aAAa,MAAM,oBAAoB,CAAC;AAE/C,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,aAAa;IAI/C,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAe;QACxD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1C,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,UAAU,CAAQ,UAAU,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;YACzE,OAAO,KAAK,CAAC;QACjB,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,2CAA2C;QAC3C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAS,SAAS,MAAM,EAAE,CAAC,CAAC;QAClE,IAAI,CAAC,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAC/B,OAAO,QAAQ,CAAC,MAAM,CAAC;IAC3B,CAAC;IAEM,MAAM,CAAC,OAAe,EAAE,MAAe,EAAE,KAAkB,EAAE,MAAe;QAC/E,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACzD,OAAO,IAAI,CAAC,UAAU,CAAwB,UAAU,OAAO,UAAU,MAAM,EAAE,CAAC,CAAC;IACvF,CAAC;CACJ"} 343 703 \ No newline at end of file 704 + diff --git a/dist/mjs/endpoints/ArtistsEndpoints.d.ts b/dist/mjs/endpoints/ArtistsEndpoints.d.ts 705 + index 4b5237b7acbc95486893d7384fb6adcdf71ee74a..8bdba8fcbc5a9c45deb1a49580764c7cbbd1cd7b 100644 706 + --- a/dist/mjs/endpoints/ArtistsEndpoints.d.ts 707 + +++ b/dist/mjs/endpoints/ArtistsEndpoints.d.ts 708 + @@ -3,7 +3,7 @@ import EndpointsBase from "./EndpointsBase.js"; 709 + export default class ArtistsEndpoints extends EndpointsBase { 710 + get(id: string): Promise<Artist>; 711 + get(ids: string[]): Promise<Artist[]>; 712 + - albums(id: string, includeGroups?: string, market?: Market, limit?: MaxInt<50>, offset?: number): Promise<Page<SimplifiedAlbum>>; 713 + - topTracks(id: string, market: Market): Promise<TopTracksResult>; 714 + - relatedArtists(id: string): Promise<Artists>; 715 + + albums(id: string, includeGroups?: string, market?: Market, limit?: MaxInt<50>, offset?: number): Promise<Page<SimplifiedAlbum> | null>; 716 + + topTracks(id: string, market: Market): Promise<TopTracksResult | null>; 717 + + relatedArtists(id: string): Promise<Artists | null>; 718 + } 719 + diff --git a/dist/mjs/endpoints/ArtistsEndpoints.js b/dist/mjs/endpoints/ArtistsEndpoints.js 720 + index ab7fe438b8946ba19b545ba7c7fea4a3d021b7f2..8c786497cde5010bc4558712eaee1b271017f1c2 100644 721 + --- a/dist/mjs/endpoints/ArtistsEndpoints.js 722 + +++ b/dist/mjs/endpoints/ArtistsEndpoints.js 723 + @@ -7,6 +7,8 @@ export default class ArtistsEndpoints extends EndpointsBase { 724 + } 725 + const params = this.paramsFor({ ids: idOrIds }); 726 + const response = await this.getRequest(`artists${params}`); 727 + + if (!response) 728 + + return response; 729 + return response.artists; 730 + } 731 + albums(id, includeGroups, market, limit, offset) { 344 732 diff --git a/dist/mjs/endpoints/ArtistsEndpoints.js.map b/dist/mjs/endpoints/ArtistsEndpoints.js.map 345 - index 033e2a97bc6d715d348326791260fc2303addd1d..f662e72b69a48f1e5929bf8f1a25b599b6984161 100644 733 + index 033e2a97bc6d715d348326791260fc2303addd1d..c83be3b97ed6fac3630a5bf9928193102e6f78d5 100644 346 734 --- a/dist/mjs/endpoints/ArtistsEndpoints.js.map 347 735 +++ b/dist/mjs/endpoints/ArtistsEndpoints.js.map 348 736 @@ -1 +1 @@ 349 737 -{"version":3,"file":"ArtistsEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/ArtistsEndpoints.ts"],"names":[],"mappings":"AAUA,OAAO,aAAa,MAAM,oBAAoB,CAAC;AAE/C,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,aAAa;IAGhD,KAAK,CAAC,GAAG,CAAC,OAA0B;QACvC,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;YAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAS,WAAW,OAAO,EAAE,CAAC,CAAC;YAC7D,OAAO,MAAM,CAAC;SACjB;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QAChD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAU,UAAU,MAAM,EAAE,CAAC,CAAC;QACpE,OAAO,QAAQ,CAAC,OAAO,CAAC;IAC5B,CAAC;IAEM,MAAM,CACT,EAAU,EACV,aAAsB,EACtB,MAAe,EACf,KAAkB,EAClB,MAAe;QAEf,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC;YAC1B,cAAc,EAAE,aAAa;YAC7B,MAAM;YACN,KAAK;YACL,MAAM;SACT,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,UAAU,CAClB,WAAW,EAAE,UAAU,MAAM,EAAE,CAClC,CAAC;IACN,CAAC;IAEM,SAAS,CAAC,EAAU,EAAE,MAAc;QACvC,+FAA+F;QAC/F,0BAA0B;QAE1B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QAC1C,OAAO,IAAI,CAAC,UAAU,CAClB,WAAW,EAAE,cAAc,MAAM,EAAE,CACtC,CAAC;IACN,CAAC;IAEM,cAAc,CAAC,EAAU;QAC5B,OAAO,IAAI,CAAC,UAAU,CAAU,WAAW,EAAE,kBAAkB,CAAC,CAAC;IACrE,CAAC;CACJ"} 350 738 \ No newline at end of file 351 - +{"version":3,"file":"ArtistsEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/ArtistsEndpoints.ts"],"names":[],"mappings":"AAUA,OAAO,aAAa,MAAM,oBAAoB,CAAC;AAE/C,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,aAAa;IAGhD,KAAK,CAAC,GAAG,CAAC,OAA0B;QACvC,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAS,WAAW,OAAO,EAAE,CAAC,CAAC;YAC7D,OAAO,MAAM,CAAC;QAClB,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QAChD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAU,UAAU,MAAM,EAAE,CAAC,CAAC;QACpE,OAAO,QAAQ,CAAC,OAAO,CAAC;IAC5B,CAAC;IAEM,MAAM,CACT,EAAU,EACV,aAAsB,EACtB,MAAe,EACf,KAAkB,EAClB,MAAe;QAEf,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC;YAC1B,cAAc,EAAE,aAAa;YAC7B,MAAM;YACN,KAAK;YACL,MAAM;SACT,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,UAAU,CAClB,WAAW,EAAE,UAAU,MAAM,EAAE,CAClC,CAAC;IACN,CAAC;IAEM,SAAS,CAAC,EAAU,EAAE,MAAc;QACvC,+FAA+F;QAC/F,0BAA0B;QAE1B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QAC1C,OAAO,IAAI,CAAC,UAAU,CAClB,WAAW,EAAE,cAAc,MAAM,EAAE,CACtC,CAAC;IACN,CAAC;IAEM,cAAc,CAAC,EAAU;QAC5B,OAAO,IAAI,CAAC,UAAU,CAAU,WAAW,EAAE,kBAAkB,CAAC,CAAC;IACrE,CAAC;CACJ"} 739 + +{"version":3,"file":"ArtistsEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/ArtistsEndpoints.ts"],"names":[],"mappings":"AAUA,OAAO,aAAa,MAAM,oBAAoB,CAAC;AAE/C,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,aAAa;IAGhD,KAAK,CAAC,GAAG,CAAC,OAA0B;QACvC,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAS,WAAW,OAAO,EAAE,CAAC,CAAC;YAC7D,OAAO,MAAM,CAAC;QAClB,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QAChD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAU,UAAU,MAAM,EAAE,CAAC,CAAC;QACpE,IAAI,CAAC,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAC/B,OAAO,QAAQ,CAAC,OAAO,CAAC;IAC5B,CAAC;IAEM,MAAM,CACT,EAAU,EACV,aAAsB,EACtB,MAAe,EACf,KAAkB,EAClB,MAAe;QAEf,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC;YAC1B,cAAc,EAAE,aAAa;YAC7B,MAAM;YACN,KAAK;YACL,MAAM;SACT,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,UAAU,CAClB,WAAW,EAAE,UAAU,MAAM,EAAE,CAClC,CAAC;IACN,CAAC;IAEM,SAAS,CAAC,EAAU,EAAE,MAAc;QACvC,+FAA+F;QAC/F,0BAA0B;QAE1B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QAC1C,OAAO,IAAI,CAAC,UAAU,CAClB,WAAW,EAAE,cAAc,MAAM,EAAE,CACtC,CAAC;IACN,CAAC;IAEM,cAAc,CAAC,EAAU;QAC5B,OAAO,IAAI,CAAC,UAAU,CAAU,WAAW,EAAE,kBAAkB,CAAC,CAAC;IACrE,CAAC;CACJ"} 352 740 \ No newline at end of file 741 + diff --git a/dist/mjs/endpoints/AudiobooksEndpoints.d.ts b/dist/mjs/endpoints/AudiobooksEndpoints.d.ts 742 + index cfe18b338a678454c67cba7086ef4b292e0ab54a..33f2577aa2b4050e49f22b3bdca75b8ba1993fdd 100644 743 + --- a/dist/mjs/endpoints/AudiobooksEndpoints.d.ts 744 + +++ b/dist/mjs/endpoints/AudiobooksEndpoints.d.ts 745 + @@ -3,5 +3,5 @@ import EndpointsBase from './EndpointsBase.js'; 746 + export default class AudiobooksEndpoints extends EndpointsBase { 747 + get(id: string, market?: Market): Promise<Audiobook>; 748 + get(ids: string[], market?: Market): Promise<Audiobook[]>; 749 + - getAudiobookChapters(id: string, market?: Market, limit?: MaxInt<50>, offset?: number): Promise<Page<SimplifiedChapter>>; 750 + + getAudiobookChapters(id: string, market?: Market, limit?: MaxInt<50>, offset?: number): Promise<Page<SimplifiedChapter> | null>; 751 + } 752 + diff --git a/dist/mjs/endpoints/AudiobooksEndpoints.js b/dist/mjs/endpoints/AudiobooksEndpoints.js 753 + index 3e7854353fff37736fd746eb929285dda337486f..571cb4acbc2f4554115ae2604837a9afd842e241 100644 754 + --- a/dist/mjs/endpoints/AudiobooksEndpoints.js 755 + +++ b/dist/mjs/endpoints/AudiobooksEndpoints.js 756 + @@ -7,6 +7,8 @@ export default class AudiobooksEndpoints extends EndpointsBase { 757 + } 758 + const params = this.paramsFor({ ids: idOrIds, market }); 759 + const response = await this.getRequest(`audiobooks${params}`); 760 + + if (!response) 761 + + return response; 762 + return response.audiobooks; 763 + } 764 + getAudiobookChapters(id, market, limit, offset) { 353 765 diff --git a/dist/mjs/endpoints/AudiobooksEndpoints.js.map b/dist/mjs/endpoints/AudiobooksEndpoints.js.map 354 - index 916809ef07644ef1d5ce8b1c9feb0e5d7ff747b0..cbae806d0e71e1b3d050abc26e910189f9d46aad 100644 766 + index 916809ef07644ef1d5ce8b1c9feb0e5d7ff747b0..07c830a5638b4fa623b78a8d389bf75cb0f6dbc0 100644 355 767 --- a/dist/mjs/endpoints/AudiobooksEndpoints.js.map 356 768 +++ b/dist/mjs/endpoints/AudiobooksEndpoints.js.map 357 769 @@ -1 +1 @@ 358 770 -{"version":3,"file":"AudiobooksEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/AudiobooksEndpoints.ts"],"names":[],"mappings":"AACA,OAAO,aAAa,MAAM,oBAAoB,CAAC;AAE/C,MAAM,CAAC,OAAO,OAAO,mBAAoB,SAAQ,aAAa;IAGnD,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAe;QACxD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;YAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1C,OAAO,IAAI,CAAC,UAAU,CAAY,cAAc,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;SACvE;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAa,aAAa,MAAM,EAAE,CAAC,CAAC;QAC1E,OAAO,QAAQ,CAAC,UAAU,CAAC;IAC/B,CAAC;IAEM,oBAAoB,CAAC,EAAU,EAAE,MAAe,EAAE,KAAkB,EAAE,MAAe;QACxF,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACzD,OAAO,IAAI,CAAC,UAAU,CAA0B,cAAc,EAAE,YAAY,MAAM,EAAE,CAAC,CAAC;IAC1F,CAAC;CAEJ"} 359 771 \ No newline at end of file 360 - +{"version":3,"file":"AudiobooksEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/AudiobooksEndpoints.ts"],"names":[],"mappings":"AACA,OAAO,aAAa,MAAM,oBAAoB,CAAC;AAE/C,MAAM,CAAC,OAAO,OAAO,mBAAoB,SAAQ,aAAa;IAGnD,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAe;QACxD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1C,OAAO,IAAI,CAAC,UAAU,CAAY,cAAc,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;QACxE,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAa,aAAa,MAAM,EAAE,CAAC,CAAC;QAC1E,OAAO,QAAQ,CAAC,UAAU,CAAC;IAC/B,CAAC;IAEM,oBAAoB,CAAC,EAAU,EAAE,MAAe,EAAE,KAAkB,EAAE,MAAe;QACxF,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACzD,OAAO,IAAI,CAAC,UAAU,CAA0B,cAAc,EAAE,YAAY,MAAM,EAAE,CAAC,CAAC;IAC1F,CAAC;CAEJ"} 772 + +{"version":3,"file":"AudiobooksEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/AudiobooksEndpoints.ts"],"names":[],"mappings":"AACA,OAAO,aAAa,MAAM,oBAAoB,CAAC;AAE/C,MAAM,CAAC,OAAO,OAAO,mBAAoB,SAAQ,aAAa;IAGnD,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAe;QACxD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1C,OAAO,IAAI,CAAC,UAAU,CAAY,cAAc,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;QACxE,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAa,aAAa,MAAM,EAAE,CAAC,CAAC;QAC1E,IAAI,CAAC,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAC/B,OAAO,QAAQ,CAAC,UAAU,CAAC;IAC/B,CAAC;IAEM,oBAAoB,CAAC,EAAU,EAAE,MAAe,EAAE,KAAkB,EAAE,MAAe;QACxF,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACzD,OAAO,IAAI,CAAC,UAAU,CAA0B,cAAc,EAAE,YAAY,MAAM,EAAE,CAAC,CAAC;IAC1F,CAAC;CAEJ"} 361 773 \ No newline at end of file 774 + diff --git a/dist/mjs/endpoints/BrowseEndpoints.d.ts b/dist/mjs/endpoints/BrowseEndpoints.d.ts 775 + index 7f998995a6b7cdb8c31dcfc9d0284826cf9b8a90..87b59ecd24941b849bd43e472ab8421cbba0e0d3 100644 776 + --- a/dist/mjs/endpoints/BrowseEndpoints.d.ts 777 + +++ b/dist/mjs/endpoints/BrowseEndpoints.d.ts 778 + @@ -1,9 +1,9 @@ 779 + import type { CountryCodeA2, MaxInt, Categories, Category, NewReleases, FeaturedPlaylists } from '../types.js'; 780 + import EndpointsBase from './EndpointsBase.js'; 781 + export default class BrowseEndpoints extends EndpointsBase { 782 + - getCategories(country?: CountryCodeA2, locale?: string, limit?: MaxInt<50>, offset?: number): Promise<Categories>; 783 + - getCategory(categoryId: string, country?: CountryCodeA2, locale?: string): Promise<Category>; 784 + - getNewReleases(country?: string, limit?: MaxInt<50>, offset?: number): Promise<NewReleases>; 785 + - getFeaturedPlaylists(country?: CountryCodeA2, locale?: string, timestamp?: string, limit?: MaxInt<50>, offset?: number): Promise<FeaturedPlaylists>; 786 + - getPlaylistsForCategory(category_id: string, country?: CountryCodeA2, limit?: MaxInt<50>, offset?: number): Promise<FeaturedPlaylists>; 787 + + getCategories(country?: CountryCodeA2, locale?: string, limit?: MaxInt<50>, offset?: number): Promise<Categories | null>; 788 + + getCategory(categoryId: string, country?: CountryCodeA2, locale?: string): Promise<Category | null>; 789 + + getNewReleases(country?: string, limit?: MaxInt<50>, offset?: number): Promise<NewReleases | null>; 790 + + getFeaturedPlaylists(country?: CountryCodeA2, locale?: string, timestamp?: string, limit?: MaxInt<50>, offset?: number): Promise<FeaturedPlaylists | null>; 791 + + getPlaylistsForCategory(category_id: string, country?: CountryCodeA2, limit?: MaxInt<50>, offset?: number): Promise<FeaturedPlaylists | null>; 792 + } 793 + diff --git a/dist/mjs/endpoints/ChaptersEndpoints.js b/dist/mjs/endpoints/ChaptersEndpoints.js 794 + index 057eecb900d09464670463c5cb24feb41ff80e4e..6d3e3a846de0f82e683685d3f083356e6ed1a634 100644 795 + --- a/dist/mjs/endpoints/ChaptersEndpoints.js 796 + +++ b/dist/mjs/endpoints/ChaptersEndpoints.js 797 + @@ -8,6 +8,8 @@ export default class ChaptersEndpoints extends EndpointsBase { 798 + // TODO: Only returns top 50, validate / pre-check here 799 + const params = this.paramsFor({ ids: idOrIds, market }); 800 + const response = await this.getRequest(`chapters${params}`); 801 + + if (!response) 802 + + return response; 803 + return response.chapters; 804 + } 805 + } 362 806 diff --git a/dist/mjs/endpoints/ChaptersEndpoints.js.map b/dist/mjs/endpoints/ChaptersEndpoints.js.map 363 - index d686d3ea29f38e83ebabd541f0ef9fa58f914cd9..5889fb7b1d5d40275a93b9432e4fd9de9c3142aa 100644 807 + index d686d3ea29f38e83ebabd541f0ef9fa58f914cd9..4930112f3e0b51baa979cc53721081c717a4598d 100644 364 808 --- a/dist/mjs/endpoints/ChaptersEndpoints.js.map 365 809 +++ b/dist/mjs/endpoints/ChaptersEndpoints.js.map 366 810 @@ -1 +1 @@ 367 811 -{"version":3,"file":"ChaptersEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/ChaptersEndpoints.ts"],"names":[],"mappings":"AACA,OAAO,aAAa,MAAM,oBAAoB,CAAC;AAK/C,MAAM,CAAC,OAAO,OAAO,iBAAkB,SAAQ,aAAa;IAGjD,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAqB;QAC9D,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;YAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1C,OAAO,IAAI,CAAC,UAAU,CAAU,YAAY,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;SACnE;QAED,uDAAuD;QACvD,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAW,WAAW,MAAM,EAAE,CAAC,CAAC;QACtE,OAAO,QAAQ,CAAC,QAAQ,CAAC;IAC7B,CAAC;CACJ"} 368 812 \ No newline at end of file 369 - +{"version":3,"file":"ChaptersEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/ChaptersEndpoints.ts"],"names":[],"mappings":"AACA,OAAO,aAAa,MAAM,oBAAoB,CAAC;AAK/C,MAAM,CAAC,OAAO,OAAO,iBAAkB,SAAQ,aAAa;IAGjD,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAqB;QAC9D,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1C,OAAO,IAAI,CAAC,UAAU,CAAU,YAAY,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;QACpE,CAAC;QAED,uDAAuD;QACvD,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAW,WAAW,MAAM,EAAE,CAAC,CAAC;QACtE,OAAO,QAAQ,CAAC,QAAQ,CAAC;IAC7B,CAAC;CACJ"} 813 + +{"version":3,"file":"ChaptersEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/ChaptersEndpoints.ts"],"names":[],"mappings":"AACA,OAAO,aAAa,MAAM,oBAAoB,CAAC;AAK/C,MAAM,CAAC,OAAO,OAAO,iBAAkB,SAAQ,aAAa;IAGjD,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAqB;QAC9D,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1C,OAAO,IAAI,CAAC,UAAU,CAAU,YAAY,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;QACpE,CAAC;QAED,uDAAuD;QACvD,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAW,WAAW,MAAM,EAAE,CAAC,CAAC;QACtE,IAAI,CAAC,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAC/B,OAAO,QAAQ,CAAC,QAAQ,CAAC;IAC7B,CAAC;CACJ"} 370 814 \ No newline at end of file 815 + diff --git a/dist/mjs/endpoints/CurrentUserEndpoints.d.ts b/dist/mjs/endpoints/CurrentUserEndpoints.d.ts 816 + index ef1c96f9bb072d17d9ce2aecfd3ac918c0f268f9..20d31d09d22308a87cb0be7072c2a40937b58206 100644 817 + --- a/dist/mjs/endpoints/CurrentUserEndpoints.d.ts 818 + +++ b/dist/mjs/endpoints/CurrentUserEndpoints.d.ts 819 + @@ -9,47 +9,47 @@ export default class CurrentUserEndpoints extends EndpointsBase { 820 + shows: CurrentUserShowsEndpoints; 821 + tracks: CurrentUserTracksEndpoints; 822 + constructor(api: SpotifyApi); 823 + - profile(): Promise<UserProfile>; 824 + - topItems<T extends "artists" | "tracks">(type: T, time_range?: 'short_term' | 'medium_term' | 'long_term', limit?: MaxInt<50>, offset?: number): Promise<Page<T extends "artists" ? Artist : Track>>; 825 + - followedArtists(after?: string, limit?: MaxInt<50>): Promise<FollowedArtists>; 826 + + profile(): Promise<UserProfile | null>; 827 + + topItems<T extends "artists" | "tracks">(type: T, time_range?: 'short_term' | 'medium_term' | 'long_term', limit?: MaxInt<50>, offset?: number): Promise<Page<T extends "artists" ? Artist : Track> | null>; 828 + + followedArtists(after?: string, limit?: MaxInt<50>): Promise<FollowedArtists | null>; 829 + followArtistsOrUsers(ids: string[], type: 'artist' | 'user'): Promise<void>; 830 + unfollowArtistsOrUsers(ids: string[], type: 'artist' | 'user'): Promise<void>; 831 + - followsArtistsOrUsers(ids: string[], type: 'artist' | 'user'): Promise<boolean[]>; 832 + + followsArtistsOrUsers(ids: string[], type: 'artist' | 'user'): Promise<boolean[] | null>; 833 + } 834 + declare class CurrentUserAlbumsEndpoints extends EndpointsBase { 835 + - savedAlbums(limit?: MaxInt<50>, offset?: number, market?: Market): Promise<Page<SavedAlbum>>; 836 + + savedAlbums(limit?: MaxInt<50>, offset?: number, market?: Market): Promise<Page<SavedAlbum> | null>; 837 + saveAlbums(ids: string[]): Promise<void>; 838 + removeSavedAlbums(ids: string[]): Promise<void>; 839 + - hasSavedAlbums(ids: string[]): Promise<boolean[]>; 840 + + hasSavedAlbums(ids: string[]): Promise<boolean[] | null>; 841 + } 842 + declare class CurrentUserAudiobooksEndpoints extends EndpointsBase { 843 + - savedAudiobooks(limit?: MaxInt<50>, offset?: number): Promise<Page<SimplifiedAudiobook>>; 844 + + savedAudiobooks(limit?: MaxInt<50>, offset?: number): Promise<Page<SimplifiedAudiobook> | null>; 845 + saveAudiobooks(ids: string[]): Promise<void>; 846 + removeSavedAudiobooks(ids: string[]): Promise<void>; 847 + - hasSavedAudiobooks(ids: string[]): Promise<boolean[]>; 848 + + hasSavedAudiobooks(ids: string[]): Promise<boolean[] | null>; 849 + } 850 + declare class CurrentUserEpisodesEndpoints extends EndpointsBase { 851 + - savedEpisodes(market?: Market, limit?: MaxInt<50>, offset?: number): Promise<Page<SavedEpisode>>; 852 + + savedEpisodes(market?: Market, limit?: MaxInt<50>, offset?: number): Promise<Page<SavedEpisode> | null>; 853 + saveEpisodes(ids: string[]): Promise<void>; 854 + removeSavedEpisodes(ids: string[]): Promise<void>; 855 + - hasSavedEpisodes(ids: string[]): Promise<boolean[]>; 856 + + hasSavedEpisodes(ids: string[]): Promise<boolean[] | null>; 857 + } 858 + declare class CurrentUserPlaylistsEndpoints extends EndpointsBase { 859 + - playlists(limit?: MaxInt<50>, offset?: number): Promise<Page<SimplifiedPlaylist>>; 860 + + playlists(limit?: MaxInt<50>, offset?: number): Promise<Page<SimplifiedPlaylist> | null>; 861 + follow(playlist_id: string): Promise<void>; 862 + unfollow(playlist_id: string): Promise<void>; 863 + - isFollowing(playlistId: string, ids: string[]): Promise<boolean[]>; 864 + + isFollowing(playlistId: string, ids: string[]): Promise<boolean[] | null>; 865 + } 866 + declare class CurrentUserShowsEndpoints extends EndpointsBase { 867 + - savedShows(limit?: MaxInt<50>, offset?: number): Promise<Page<SavedShow>>; 868 + + savedShows(limit?: MaxInt<50>, offset?: number): Promise<Page<SavedShow> | null>; 869 + saveShows(ids: string[]): Promise<unknown>; 870 + removeSavedShows(ids: string[], market?: Market): Promise<unknown>; 871 + - hasSavedShow(ids: string[]): Promise<boolean[]>; 872 + + hasSavedShow(ids: string[]): Promise<boolean[] | null>; 873 + } 874 + declare class CurrentUserTracksEndpoints extends EndpointsBase { 875 + - savedTracks(limit?: MaxInt<50>, offset?: number, market?: Market): Promise<Page<SavedTrack>>; 876 + + savedTracks(limit?: MaxInt<50>, offset?: number, market?: Market): Promise<Page<SavedTrack> | null>; 877 + saveTracks(ids: string[]): Promise<void>; 878 + removeSavedTracks(ids: string[]): Promise<void>; 879 + - hasSavedTracks(ids: string[]): Promise<boolean[]>; 880 + + hasSavedTracks(ids: string[]): Promise<boolean[] | null>; 881 + } 882 + export {}; 883 + diff --git a/dist/mjs/endpoints/EndpointsBase.d.ts b/dist/mjs/endpoints/EndpointsBase.d.ts 884 + index c91dff76bfa4664d7a9976f84c98a8e65b08cb70..62e63dac60f91346fae2b6dc121e309df52ba3f3 100644 885 + --- a/dist/mjs/endpoints/EndpointsBase.d.ts 886 + +++ b/dist/mjs/endpoints/EndpointsBase.d.ts 887 + @@ -2,9 +2,9 @@ import { SpotifyApi } from "../SpotifyApi.js"; 888 + export default class EndpointsBase { 889 + protected api: SpotifyApi; 890 + constructor(api: SpotifyApi); 891 + - protected getRequest<TReturnType>(url: string): Promise<TReturnType>; 892 + - protected postRequest<TReturnType, TBody = unknown>(url: string, body?: TBody, contentType?: string | undefined): Promise<TReturnType>; 893 + - protected putRequest<TReturnType, TBody = unknown>(url: string, body?: TBody, contentType?: string | undefined): Promise<TReturnType>; 894 + - protected deleteRequest<TReturnType, TBody = unknown>(url: string, body?: TBody): Promise<TReturnType>; 895 + + protected getRequest<TReturnType>(url: string): Promise<TReturnType | null>; 896 + + protected postRequest<TReturnType, TBody = unknown>(url: string, body?: TBody, contentType?: string | undefined): Promise<TReturnType | null>; 897 + + protected putRequest<TReturnType, TBody = unknown>(url: string, body?: TBody, contentType?: string | undefined): Promise<TReturnType | null>; 898 + + protected deleteRequest<TReturnType, TBody = unknown>(url: string, body?: TBody): Promise<TReturnType | null>; 899 + protected paramsFor(args: any): string; 900 + } 371 901 diff --git a/dist/mjs/endpoints/EndpointsBase.js.map b/dist/mjs/endpoints/EndpointsBase.js.map 372 902 index e93c0f83790363247c53b09de0fa2fa19523eb6a..ab3c7550cdc23ea60e4aa5503a02f4c4b1cd1a64 100644 373 903 --- a/dist/mjs/endpoints/EndpointsBase.js.map ··· 377 907 \ No newline at end of file 378 908 +{"version":3,"file":"EndpointsBase.js","sourceRoot":"","sources":["../../../src/endpoints/EndpointsBase.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,OAAO,OAAO,aAAa;IACR;IAAtB,YAAsB,GAAe;QAAf,QAAG,GAAH,GAAG,CAAY;IACrC,CAAC;IAES,KAAK,CAAC,UAAU,CAAc,GAAW;QAC/C,OAAO,MAAM,IAAI,CAAC,GAAG,CAAC,WAAW,CAAc,KAAK,EAAE,GAAG,CAAC,CAAC;IAC/D,CAAC;IAES,KAAK,CAAC,WAAW,CAA+B,GAAW,EAAE,IAAY,EAAE,cAAkC,SAAS;QAC5H,OAAO,MAAM,IAAI,CAAC,GAAG,CAAC,WAAW,CAAc,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC;IACnF,CAAC;IAES,KAAK,CAAC,UAAU,CAA+B,GAAW,EAAE,IAAY,EAAE,cAAkC,SAAS;QAC3H,OAAO,MAAM,IAAI,CAAC,GAAG,CAAC,WAAW,CAAc,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC;IAClF,CAAC;IAES,KAAK,CAAC,aAAa,CAA+B,GAAW,EAAE,IAAY;QACjF,OAAO,MAAM,IAAI,CAAC,GAAG,CAAC,WAAW,CAAc,QAAQ,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;IACxE,CAAC;IAES,SAAS,CAAC,IAAS;QACzB,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QACrC,KAAK,IAAI,GAAG,IAAI,MAAM,CAAC,mBAAmB,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/C,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,SAAS,CAAC,EAAE,CAAC;gBACnF,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC7C,CAAC;QACL,CAAC;QACD,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACjE,CAAC;CACJ"} 379 909 \ No newline at end of file 910 + diff --git a/dist/mjs/endpoints/EpisodesEndpoints.js b/dist/mjs/endpoints/EpisodesEndpoints.js 911 + index c526dba76d93e55281b093f8ba9762b8b248b1a4..1e301fe0ab04b6a053ca7518027d4e34e135d5ac 100644 912 + --- a/dist/mjs/endpoints/EpisodesEndpoints.js 913 + +++ b/dist/mjs/endpoints/EpisodesEndpoints.js 914 + @@ -7,6 +7,8 @@ export default class EpisodesEndpoints extends EndpointsBase { 915 + } 916 + const params = this.paramsFor({ ids: idOrIds, market }); 917 + const response = await this.getRequest(`episodes${params}`); 918 + + if (!response) 919 + + return response; 920 + return response.episodes; 921 + } 922 + } 380 923 diff --git a/dist/mjs/endpoints/EpisodesEndpoints.js.map b/dist/mjs/endpoints/EpisodesEndpoints.js.map 381 - index 19c79bb444c2b9e1ad0727be8846d2711ef74a47..858b2e925ab48fa3746b03562c976d435fadfe9b 100644 924 + index 19c79bb444c2b9e1ad0727be8846d2711ef74a47..678e9c7aebd4344dc960b2bda2674b1c140e0b3e 100644 382 925 --- a/dist/mjs/endpoints/EpisodesEndpoints.js.map 383 926 +++ b/dist/mjs/endpoints/EpisodesEndpoints.js.map 384 927 @@ -1 +1 @@ 385 928 -{"version":3,"file":"EpisodesEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/EpisodesEndpoints.ts"],"names":[],"mappings":"AACA,OAAO,aAAa,MAAM,oBAAoB,CAAC;AAE/C,MAAM,CAAC,OAAO,OAAO,iBAAkB,SAAQ,aAAa;IAIjD,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAc;QACvD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;YAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1C,OAAO,IAAI,CAAC,UAAU,CAAU,YAAY,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;SACnE;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAW,WAAW,MAAM,EAAE,CAAC,CAAC;QACtE,OAAO,QAAQ,CAAC,QAAQ,CAAC;IAC7B,CAAC;CACJ"} 386 929 \ No newline at end of file 387 - +{"version":3,"file":"EpisodesEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/EpisodesEndpoints.ts"],"names":[],"mappings":"AACA,OAAO,aAAa,MAAM,oBAAoB,CAAC;AAE/C,MAAM,CAAC,OAAO,OAAO,iBAAkB,SAAQ,aAAa;IAIjD,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAc;QACvD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1C,OAAO,IAAI,CAAC,UAAU,CAAU,YAAY,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;QACpE,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAW,WAAW,MAAM,EAAE,CAAC,CAAC;QACtE,OAAO,QAAQ,CAAC,QAAQ,CAAC;IAC7B,CAAC;CACJ"} 930 + +{"version":3,"file":"EpisodesEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/EpisodesEndpoints.ts"],"names":[],"mappings":"AACA,OAAO,aAAa,MAAM,oBAAoB,CAAC;AAE/C,MAAM,CAAC,OAAO,OAAO,iBAAkB,SAAQ,aAAa;IAIjD,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAc;QACvD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1C,OAAO,IAAI,CAAC,UAAU,CAAU,YAAY,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;QACpE,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAW,WAAW,MAAM,EAAE,CAAC,CAAC;QACtE,IAAI,CAAC,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAC/B,OAAO,QAAQ,CAAC,QAAQ,CAAC;IAC7B,CAAC;CACJ"} 388 931 \ No newline at end of file 932 + diff --git a/dist/mjs/endpoints/MarketsEndpoints.d.ts b/dist/mjs/endpoints/MarketsEndpoints.d.ts 933 + index 4ceb08e53ada5c140d6cba3267e8d60b35586827..cc046b287cf3a12a23cdec477d197319189b0c6b 100644 934 + --- a/dist/mjs/endpoints/MarketsEndpoints.d.ts 935 + +++ b/dist/mjs/endpoints/MarketsEndpoints.d.ts 936 + @@ -1,5 +1,5 @@ 937 + import type { Markets } from '../types.js'; 938 + import EndpointsBase from './EndpointsBase.js'; 939 + export default class MarketsEndpoints extends EndpointsBase { 940 + - getAvailableMarkets(): Promise<Markets>; 941 + + getAvailableMarkets(): Promise<Markets | null>; 942 + } 943 + diff --git a/dist/mjs/endpoints/PlayerEndpoints.d.ts b/dist/mjs/endpoints/PlayerEndpoints.d.ts 944 + index 52792b8fb66f5a4e5056c674a175fb12d9b6c43b..2b6ec0f5e0199cd5d908e63fe6b410fce8c55315 100644 945 + --- a/dist/mjs/endpoints/PlayerEndpoints.d.ts 946 + +++ b/dist/mjs/endpoints/PlayerEndpoints.d.ts 947 + @@ -5,11 +5,11 @@ interface QueryRange { 948 + type: "before" | "after"; 949 + } 950 + export default class PlayerEndpoints extends EndpointsBase { 951 + - getPlaybackState(market?: Market, additional_types?: string): Promise<PlaybackState>; 952 + - getAvailableDevices(): Promise<Devices>; 953 + - getCurrentlyPlayingTrack(market?: Market, additional_types?: string): Promise<PlaybackState>; 954 + - getRecentlyPlayedTracks(limit?: MaxInt<50>, queryRange?: QueryRange): Promise<RecentlyPlayedTracksPage>; 955 + - getUsersQueue(): Promise<Queue>; 956 + + getPlaybackState(market?: Market, additional_types?: string): Promise<PlaybackState | null>; 957 + + getAvailableDevices(): Promise<Devices | null>; 958 + + getCurrentlyPlayingTrack(market?: Market, additional_types?: string): Promise<PlaybackState | null>; 959 + + getRecentlyPlayedTracks(limit?: MaxInt<50>, queryRange?: QueryRange): Promise<RecentlyPlayedTracksPage | null>; 960 + + getUsersQueue(): Promise<Queue | null>; 961 + transferPlayback(device_ids: string[], play?: boolean): Promise<void>; 962 + startResumePlayback(device_id: string, context_uri?: string, uris?: string[], offset?: object, positionMs?: number): Promise<void>; 963 + pausePlayback(device_id: string): Promise<void>; 389 964 diff --git a/dist/mjs/endpoints/PlayerEndpoints.js.map b/dist/mjs/endpoints/PlayerEndpoints.js.map 390 965 index 6b1c7937d058d128aa981035117b3fa06d4564cf..015469900dd2ed19f8ab3d962bb6aa469fc65265 100644 391 966 --- a/dist/mjs/endpoints/PlayerEndpoints.js.map ··· 396 971 +{"version":3,"file":"PlayerEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/PlayerEndpoints.ts"],"names":[],"mappings":"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"} 397 972 \ No newline at end of file 398 973 diff --git a/dist/mjs/endpoints/PlaylistsEndpoints.d.ts b/dist/mjs/endpoints/PlaylistsEndpoints.d.ts 399 - index 8760c8c7b8d61681a85537a40d33aafeff8d1cd0..8a439ea2f95f5bdbd5bec4cc9dde867e06d74ec2 100644 974 + index 8760c8c7b8d61681a85537a40d33aafeff8d1cd0..1477d0769fae34f47b34a4d85c46e29337dac979 100644 400 975 --- a/dist/mjs/endpoints/PlaylistsEndpoints.d.ts 401 976 +++ b/dist/mjs/endpoints/PlaylistsEndpoints.d.ts 402 - @@ -1,4 +1,3 @@ 977 + @@ -1,17 +1,16 @@ 403 978 -/// <reference types="node" /> 404 979 import type { Market, Playlist, MaxInt, Page, Track, SnapshotReference, Image, PlaylistedTrack, QueryAdditionalTypes, TrackItem } from '../types.js'; 405 980 import EndpointsBase from './EndpointsBase.js'; 406 981 export default class PlaylistsEndpoints extends EndpointsBase { 982 + - getPlaylist<AdditionalTypes extends QueryAdditionalTypes | undefined = undefined>(playlist_id: string, market?: Market, fields?: string, additional_types?: AdditionalTypes): Promise<Playlist<AdditionalTypes extends undefined ? Track : TrackItem>>; 983 + - getPlaylistItems<AdditionalTypes extends QueryAdditionalTypes | undefined = undefined>(playlist_id: string, market?: Market, fields?: string, limit?: MaxInt<50>, offset?: number, additional_types?: AdditionalTypes): Promise<Page<PlaylistedTrack<AdditionalTypes extends undefined ? Track : TrackItem>>>; 984 + + getPlaylist<AdditionalTypes extends QueryAdditionalTypes | undefined = undefined>(playlist_id: string, market?: Market, fields?: string, additional_types?: AdditionalTypes): Promise<Playlist<AdditionalTypes extends undefined ? Track : TrackItem> | null>; 985 + + getPlaylistItems<AdditionalTypes extends QueryAdditionalTypes | undefined = undefined>(playlist_id: string, market?: Market, fields?: string, limit?: MaxInt<50>, offset?: number, additional_types?: AdditionalTypes): Promise<Page<PlaylistedTrack<AdditionalTypes extends undefined ? Track : TrackItem>> | null>; 986 + changePlaylistDetails(playlist_id: string, request: ChangePlaylistDetailsRequest): Promise<void>; 987 + - movePlaylistItems(playlist_id: string, range_start: number, range_length: number, moveToPosition: number): Promise<SnapshotReference>; 988 + - updatePlaylistItems(playlist_id: string, request: UpdatePlaylistItemsRequest): Promise<SnapshotReference>; 989 + + movePlaylistItems(playlist_id: string, range_start: number, range_length: number, moveToPosition: number): Promise<SnapshotReference | null>; 990 + + updatePlaylistItems(playlist_id: string, request: UpdatePlaylistItemsRequest): Promise<SnapshotReference | null>; 991 + addItemsToPlaylist(playlist_id: string, uris?: string[], position?: number): Promise<void>; 992 + removeItemsFromPlaylist(playlist_id: string, request: RemovePlaylistItemsRequest): Promise<void>; 993 + - getUsersPlaylists(user_id: string, limit?: MaxInt<50>, offset?: number): Promise<Page<Playlist<TrackItem>>>; 994 + - createPlaylist(user_id: string, request: CreatePlaylistRequest): Promise<Playlist<TrackItem>>; 995 + - getPlaylistCoverImage(playlist_id: string): Promise<Image[]>; 996 + + getUsersPlaylists(user_id: string, limit?: MaxInt<50>, offset?: number): Promise<Page<Playlist<TrackItem>> | null>; 997 + + createPlaylist(user_id: string, request: CreatePlaylistRequest): Promise<Playlist<TrackItem> | null>; 998 + + getPlaylistCoverImage(playlist_id: string): Promise<Image[] | null>; 999 + addCustomPlaylistCoverImage(playlist_id: string, imageData: Buffer | HTMLImageElement | HTMLCanvasElement | string): Promise<void>; 1000 + addCustomPlaylistCoverImageFromBase64String(playlist_id: string, base64EncodedJpeg: string): Promise<void>; 1001 + } 407 1002 diff --git a/dist/mjs/endpoints/PlaylistsEndpoints.js.map b/dist/mjs/endpoints/PlaylistsEndpoints.js.map 408 1003 index 0482d4fe4c4294e273f728a2e5b046420f303a5a..7d15483da9c877cd43a2e33cec89be974d34b55b 100644 409 1004 --- a/dist/mjs/endpoints/PlaylistsEndpoints.js.map ··· 413 1008 \ No newline at end of file 414 1009 +{"version":3,"file":"PlaylistsEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/PlaylistsEndpoints.ts"],"names":[],"mappings":"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"} 415 1010 \ No newline at end of file 1011 + diff --git a/dist/mjs/endpoints/RecommendationsEndpoints.d.ts b/dist/mjs/endpoints/RecommendationsEndpoints.d.ts 1012 + index ddd71517d997daee270a15e60782d6bd29fa3a6a..cf864f5fa1f48da6fc836df78a3a19e70eece0c5 100644 1013 + --- a/dist/mjs/endpoints/RecommendationsEndpoints.d.ts 1014 + +++ b/dist/mjs/endpoints/RecommendationsEndpoints.d.ts 1015 + @@ -1,8 +1,8 @@ 1016 + import type { Genres, Track } from '../types.js'; 1017 + import EndpointsBase from './EndpointsBase.js'; 1018 + export default class RecommendationsEndpoints extends EndpointsBase { 1019 + - get(request: RecommendationsRequestRequiredArguments | RecommendationsRequest): Promise<RecommendationsResponse>; 1020 + - genreSeeds(): Promise<Genres>; 1021 + + get(request: RecommendationsRequestRequiredArguments | RecommendationsRequest): Promise<RecommendationsResponse | null>; 1022 + + genreSeeds(): Promise<Genres | null>; 1023 + } 1024 + export interface RecommendationsRequestRequiredArguments { 1025 + seed_artists?: string[]; 1026 + diff --git a/dist/mjs/endpoints/SearchEndpoints.d.ts b/dist/mjs/endpoints/SearchEndpoints.d.ts 1027 + index 71fcb99808b86ed766d459b11d09a2ad5080408d..6656f5bc3f1c94612ed548b96693692c7859cdf0 100644 1028 + --- a/dist/mjs/endpoints/SearchEndpoints.d.ts 1029 + +++ b/dist/mjs/endpoints/SearchEndpoints.d.ts 1030 + @@ -1,8 +1,8 @@ 1031 + import type { ItemTypes, Market, MaxInt, SearchResults } from '../types.js'; 1032 + import EndpointsBase from './EndpointsBase.js'; 1033 + export interface SearchExecutionFunction { 1034 + - <const T extends readonly ItemTypes[]>(q: string, type: T, market?: Market, limit?: MaxInt<50>, offset?: number, include_external?: string): Promise<SearchResults<T>>; 1035 + + <const T extends readonly ItemTypes[]>(q: string, type: T, market?: Market, limit?: MaxInt<50>, offset?: number, include_external?: string): Promise<SearchResults<T> | null>; 1036 + } 1037 + export default class SearchEndpoints extends EndpointsBase { 1038 + - execute<const T extends readonly ItemTypes[]>(q: string, type: T, market?: Market, limit?: MaxInt<50>, offset?: number, include_external?: string): Promise<SearchResults<T>>; 1039 + + execute<const T extends readonly ItemTypes[]>(q: string, type: T, market?: Market, limit?: MaxInt<50>, offset?: number, include_external?: string): Promise<SearchResults<T> | null>; 1040 + } 1041 + diff --git a/dist/mjs/endpoints/ShowsEndpoints.d.ts b/dist/mjs/endpoints/ShowsEndpoints.d.ts 1042 + index 41b64a4de6399faa92e28aec51b977cddd06d00b..4e6fe35b6161bf21820819775281600f74a23325 100644 1043 + --- a/dist/mjs/endpoints/ShowsEndpoints.d.ts 1044 + +++ b/dist/mjs/endpoints/ShowsEndpoints.d.ts 1045 + @@ -3,5 +3,5 @@ import EndpointsBase from './EndpointsBase.js'; 1046 + export default class ShowsEndpoints extends EndpointsBase { 1047 + get(id: string, market: Market): Promise<Show>; 1048 + get(ids: string[], market: Market): Promise<Show[]>; 1049 + - episodes(id: string, market?: Market, limit?: MaxInt<50>, offset?: number): Promise<Page<SimplifiedEpisode>>; 1050 + + episodes(id: string, market?: Market, limit?: MaxInt<50>, offset?: number): Promise<Page<SimplifiedEpisode> | null>; 1051 + } 1052 + diff --git a/dist/mjs/endpoints/ShowsEndpoints.js b/dist/mjs/endpoints/ShowsEndpoints.js 1053 + index d19128c3c9ba72d5a968bb19d9e5b9d4863194e3..88e6701f007445bcc75c233490adf6d0a27a18db 100644 1054 + --- a/dist/mjs/endpoints/ShowsEndpoints.js 1055 + +++ b/dist/mjs/endpoints/ShowsEndpoints.js 1056 + @@ -8,6 +8,8 @@ export default class ShowsEndpoints extends EndpointsBase { 1057 + // TODO: only returns 50, validate here 1058 + const params = this.paramsFor({ ids: idOrIds, market }); 1059 + const response = await this.getRequest(`shows${params}`); 1060 + + if (!response) 1061 + + return response; 1062 + return response.shows; 1063 + } 1064 + episodes(id, market, limit, offset) { 416 1065 diff --git a/dist/mjs/endpoints/ShowsEndpoints.js.map b/dist/mjs/endpoints/ShowsEndpoints.js.map 417 - index 3f1eb890cfd275ad7bb8439691256c8b9b6a7971..6e1fbe7ad3e743c9461aec546320d427df1f8ac8 100644 1066 + index 3f1eb890cfd275ad7bb8439691256c8b9b6a7971..5e87e6f5390575a5d65f6b3fc430c087ffba03e1 100644 418 1067 --- a/dist/mjs/endpoints/ShowsEndpoints.js.map 419 1068 +++ b/dist/mjs/endpoints/ShowsEndpoints.js.map 420 1069 @@ -1 +1 @@ 421 1070 -{"version":3,"file":"ShowsEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/ShowsEndpoints.ts"],"names":[],"mappings":"AACA,OAAO,aAAa,MAAM,oBAAoB,CAAC;AAE/C,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,aAAa;IAI9C,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAc;QACvD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;YAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAA;YACzC,OAAO,IAAI,CAAC,UAAU,CAAO,SAAS,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;SAC7D;QAED,uCAAuC;QACvC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAQ,QAAQ,MAAM,EAAE,CAAC,CAAC;QAChE,OAAO,QAAQ,CAAC,KAAK,CAAC;IAC1B,CAAC;IAEM,QAAQ,CAAC,EAAU,EAAE,MAAe,EAAE,KAAkB,EAAE,MAAe;QAC5E,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;QACxD,OAAO,IAAI,CAAC,UAAU,CAA0B,SAAS,EAAE,YAAY,MAAM,EAAE,CAAC,CAAC;IACrF,CAAC;CACJ"} 422 1071 \ No newline at end of file 423 - +{"version":3,"file":"ShowsEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/ShowsEndpoints.ts"],"names":[],"mappings":"AACA,OAAO,aAAa,MAAM,oBAAoB,CAAC;AAE/C,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,aAAa;IAI9C,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAc;QACvD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAA;YACzC,OAAO,IAAI,CAAC,UAAU,CAAO,SAAS,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;QAC9D,CAAC;QAED,uCAAuC;QACvC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAQ,QAAQ,MAAM,EAAE,CAAC,CAAC;QAChE,OAAO,QAAQ,CAAC,KAAK,CAAC;IAC1B,CAAC;IAEM,QAAQ,CAAC,EAAU,EAAE,MAAe,EAAE,KAAkB,EAAE,MAAe;QAC5E,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;QACxD,OAAO,IAAI,CAAC,UAAU,CAA0B,SAAS,EAAE,YAAY,MAAM,EAAE,CAAC,CAAC;IACrF,CAAC;CACJ"} 1072 + +{"version":3,"file":"ShowsEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/ShowsEndpoints.ts"],"names":[],"mappings":"AACA,OAAO,aAAa,MAAM,oBAAoB,CAAC;AAE/C,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,aAAa;IAI9C,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAc;QACvD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAA;YACzC,OAAO,IAAI,CAAC,UAAU,CAAO,SAAS,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;QAC9D,CAAC;QAED,uCAAuC;QACvC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAQ,QAAQ,MAAM,EAAE,CAAC,CAAC;QAChE,IAAI,CAAC,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAC/B,OAAO,QAAQ,CAAC,KAAK,CAAC;IAC1B,CAAC;IAEM,QAAQ,CAAC,EAAU,EAAE,MAAe,EAAE,KAAkB,EAAE,MAAe;QAC5E,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;QACxD,OAAO,IAAI,CAAC,UAAU,CAA0B,SAAS,EAAE,YAAY,MAAM,EAAE,CAAC,CAAC;IACrF,CAAC;CACJ"} 424 1073 \ No newline at end of file 1074 + diff --git a/dist/mjs/endpoints/TracksEndpoints.d.ts b/dist/mjs/endpoints/TracksEndpoints.d.ts 1075 + index 5a2811cbe7365ec4e81823f69046dea8141941de..7a8109f3f656be9ed76e4f781e83343c85a907d7 100644 1076 + --- a/dist/mjs/endpoints/TracksEndpoints.d.ts 1077 + +++ b/dist/mjs/endpoints/TracksEndpoints.d.ts 1078 + @@ -5,5 +5,5 @@ export default class TracksEndpoints extends EndpointsBase { 1079 + get(ids: string[], market?: Market): Promise<Track[]>; 1080 + audioFeatures(id: string): Promise<AudioFeatures>; 1081 + audioFeatures(ids: string[]): Promise<AudioFeatures[]>; 1082 + - audioAnalysis(id: string): Promise<AudioAnalysis>; 1083 + + audioAnalysis(id: string): Promise<AudioAnalysis | null>; 1084 + } 1085 + diff --git a/dist/mjs/endpoints/TracksEndpoints.js b/dist/mjs/endpoints/TracksEndpoints.js 1086 + index 203d45d432745ef347824e4b03a7b6fcfd5743e1..29eff54383e6ce4a7ce5b5b7293d4566f91ffc0e 100644 1087 + --- a/dist/mjs/endpoints/TracksEndpoints.js 1088 + +++ b/dist/mjs/endpoints/TracksEndpoints.js 1089 + @@ -8,6 +8,8 @@ export default class TracksEndpoints extends EndpointsBase { 1090 + const params = this.paramsFor({ ids: idOrIds, market }); 1091 + // TODO: only returns top 20, validate here 1092 + const response = await this.getRequest(`tracks${params}`); 1093 + + if (!response) 1094 + + return response; 1095 + return response.tracks; 1096 + } 1097 + async audioFeatures(idOrIds) { 1098 + @@ -16,6 +18,8 @@ export default class TracksEndpoints extends EndpointsBase { 1099 + } 1100 + const params = this.paramsFor({ ids: idOrIds }); 1101 + const response = await this.getRequest(`audio-features${params}`); 1102 + + if (!response) 1103 + + return response; 1104 + return response.audio_features; 1105 + } 1106 + audioAnalysis(id) { 425 1107 diff --git a/dist/mjs/endpoints/TracksEndpoints.js.map b/dist/mjs/endpoints/TracksEndpoints.js.map 426 - index 979607aae926efc41a44f301b96ff9419a4b3b65..c84a80853f5e023d29ad53a0b4449e137f9b9841 100644 1108 + index 979607aae926efc41a44f301b96ff9419a4b3b65..bf8fa7c3ca4506d867e073438df2fbd668b627c0 100644 427 1109 --- a/dist/mjs/endpoints/TracksEndpoints.js.map 428 1110 +++ b/dist/mjs/endpoints/TracksEndpoints.js.map 429 1111 @@ -1 +1 @@ 430 1112 -{"version":3,"file":"TracksEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/TracksEndpoints.ts"],"names":[],"mappings":"AACA,OAAO,aAAa,MAAM,oBAAoB,CAAC;AAE/C,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,aAAa;IAI/C,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAe;QACxD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;YAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1C,OAAO,IAAI,CAAC,UAAU,CAAQ,UAAU,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;SAC/D;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,2CAA2C;QAC3C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAS,SAAS,MAAM,EAAE,CAAC,CAAC;QAClE,OAAO,QAAQ,CAAC,MAAM,CAAC;IAC3B,CAAC;IAIM,KAAK,CAAC,aAAa,CAAC,OAA0B;QACjD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;YAC7B,OAAO,IAAI,CAAC,UAAU,CAAgB,kBAAkB,OAAO,EAAE,CAAC,CAAC;SACtE;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QAChD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAA0B,iBAAiB,MAAM,EAAE,CAAC,CAAC;QAC3F,OAAO,QAAQ,CAAC,cAAc,CAAC;IACnC,CAAC;IAEM,aAAa,CAAC,EAAU;QAC3B,OAAO,IAAI,CAAC,UAAU,CAAgB,kBAAkB,EAAE,EAAE,CAAC,CAAC;IAClE,CAAC;CAEJ"} 431 1113 \ No newline at end of file 432 - +{"version":3,"file":"TracksEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/TracksEndpoints.ts"],"names":[],"mappings":"AACA,OAAO,aAAa,MAAM,oBAAoB,CAAC;AAE/C,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,aAAa;IAI/C,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAe;QACxD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1C,OAAO,IAAI,CAAC,UAAU,CAAQ,UAAU,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;QAChE,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,2CAA2C;QAC3C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAS,SAAS,MAAM,EAAE,CAAC,CAAC;QAClE,OAAO,QAAQ,CAAC,MAAM,CAAC;IAC3B,CAAC;IAIM,KAAK,CAAC,aAAa,CAAC,OAA0B;QACjD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC,UAAU,CAAgB,kBAAkB,OAAO,EAAE,CAAC,CAAC;QACvE,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QAChD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAA0B,iBAAiB,MAAM,EAAE,CAAC,CAAC;QAC3F,OAAO,QAAQ,CAAC,cAAc,CAAC;IACnC,CAAC;IAEM,aAAa,CAAC,EAAU;QAC3B,OAAO,IAAI,CAAC,UAAU,CAAgB,kBAAkB,EAAE,EAAE,CAAC,CAAC;IAClE,CAAC;CAEJ"} 1114 + +{"version":3,"file":"TracksEndpoints.js","sourceRoot":"","sources":["../../../src/endpoints/TracksEndpoints.ts"],"names":[],"mappings":"AACA,OAAO,aAAa,MAAM,oBAAoB,CAAC;AAE/C,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,aAAa;IAI/C,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,MAAe;QACxD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1C,OAAO,IAAI,CAAC,UAAU,CAAQ,UAAU,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;QAChE,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,2CAA2C;QAC3C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAS,SAAS,MAAM,EAAE,CAAC,CAAC;QAClE,IAAI,CAAC,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAC/B,OAAO,QAAQ,CAAC,MAAM,CAAC;IAC3B,CAAC;IAIM,KAAK,CAAC,aAAa,CAAC,OAA0B;QACjD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC,UAAU,CAAgB,kBAAkB,OAAO,EAAE,CAAC,CAAC;QACvE,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QAChD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAA0B,iBAAiB,MAAM,EAAE,CAAC,CAAC;QAC3F,IAAI,CAAC,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAC/B,OAAO,QAAQ,CAAC,cAAc,CAAC;IACnC,CAAC;IAEM,aAAa,CAAC,EAAU;QAC3B,OAAO,IAAI,CAAC,UAAU,CAAgB,kBAAkB,EAAE,EAAE,CAAC,CAAC;IAClE,CAAC;CAEJ"} 433 1115 \ No newline at end of file 434 - diff --git a/dist/mjs/index.d.ts b/dist/mjs/index.d.ts 435 - index fbf77964cdd33a0bac5c37ad35e2b1af18d95cd4..44ddaef876d324384ab51d28b5a83300d3be84e7 100644 436 - --- a/dist/mjs/index.d.ts 437 - +++ b/dist/mjs/index.d.ts 438 - @@ -12,7 +12,8 @@ import DocumentLocationRedirectionStrategy from "./redirection/DocumentLocationR 439 - import DefaultResponseValidator from "./responsevalidation/DefaultResponseValidator.js"; 440 - import DefaultResponseDeserializer from "./serialization/DefaultResponseDeserializer.js"; 441 - import { Scopes } from "./Scopes.js"; 442 - +import ProvidedAccessTokenStrategy from "./auth/ProvidedAccessTokenStrategy.js"; 443 - import { emptyAccessToken } from "./auth/IAuthStrategy.js"; 444 - -export { SpotifyApi, AuthorizationCodeWithPKCEStrategy, ClientCredentialsStrategy, InMemoryCachingStrategy, LocalStorageCachingStrategy, GenericCache, ConsoleLoggingErrorHandler, NoOpErrorHandler, DocumentLocationRedirectionStrategy, DefaultResponseValidator, DefaultResponseDeserializer, Scopes, emptyAccessToken }; 445 - +export { SpotifyApi, AuthorizationCodeWithPKCEStrategy, ClientCredentialsStrategy, InMemoryCachingStrategy, LocalStorageCachingStrategy, GenericCache, ConsoleLoggingErrorHandler, NoOpErrorHandler, DocumentLocationRedirectionStrategy, DefaultResponseValidator, DefaultResponseDeserializer, Scopes, ProvidedAccessTokenStrategy, emptyAccessToken, }; 446 - export type * from "./types.js"; 447 - -export type { IAuthStrategy, ICacheStore, }; 448 - +export type { IAuthStrategy, ICacheStore }; 449 - diff --git a/dist/mjs/index.js b/dist/mjs/index.js 450 - index b850ca13517ccfc7df23ea9655f26075c9d06e92..88008269940e3448565381716765aad8e8102e41 100644 451 - --- a/dist/mjs/index.js 452 - +++ b/dist/mjs/index.js 453 - @@ -10,6 +10,7 @@ import DocumentLocationRedirectionStrategy from "./redirection/DocumentLocationR 454 - import DefaultResponseValidator from "./responsevalidation/DefaultResponseValidator.js"; 455 - import DefaultResponseDeserializer from "./serialization/DefaultResponseDeserializer.js"; 456 - import { Scopes } from "./Scopes.js"; 457 - +import ProvidedAccessTokenStrategy from "./auth/ProvidedAccessTokenStrategy.js"; 458 - import { emptyAccessToken } from "./auth/IAuthStrategy.js"; 459 - -export { SpotifyApi, AuthorizationCodeWithPKCEStrategy, ClientCredentialsStrategy, InMemoryCachingStrategy, LocalStorageCachingStrategy, GenericCache, ConsoleLoggingErrorHandler, NoOpErrorHandler, DocumentLocationRedirectionStrategy, DefaultResponseValidator, DefaultResponseDeserializer, Scopes, emptyAccessToken }; 460 - +export { SpotifyApi, AuthorizationCodeWithPKCEStrategy, ClientCredentialsStrategy, InMemoryCachingStrategy, LocalStorageCachingStrategy, GenericCache, ConsoleLoggingErrorHandler, NoOpErrorHandler, DocumentLocationRedirectionStrategy, DefaultResponseValidator, DefaultResponseDeserializer, Scopes, ProvidedAccessTokenStrategy, emptyAccessToken, }; 461 - //# sourceMappingURL=index.js.map 462 - \ No newline at end of file 463 - diff --git a/dist/mjs/index.js.map b/dist/mjs/index.js.map 464 - index 5713a86abb96eea14b688db85121fea9a0154532..f10ec14395391f8f9fb580f526620088f9eeffd6 100644 465 - --- a/dist/mjs/index.js.map 466 - +++ b/dist/mjs/index.js.map 467 - @@ -1 +1 @@ 468 - -{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,iCAAiC,MAAM,6CAA6C,CAAC;AAC5F,OAAO,yBAAyB,MAAM,qCAAqC,CAAC;AAE5E,OAAO,uBAAuB,MAAM,sCAAsC,CAAC;AAC3E,OAAO,2BAA2B,MAAM,0CAA0C,CAAC;AAEnF,OAAO,YAAY,MAAM,2BAA2B,CAAC;AACrD,OAAO,0BAA0B,MAAM,+CAA+C,CAAC;AACvF,OAAO,gBAAgB,MAAM,qCAAqC,CAAC;AACnE,OAAO,mCAAmC,MAAM,sDAAsD,CAAC;AACvG,OAAO,wBAAwB,MAAM,kDAAkD,CAAC;AACxF,OAAO,2BAA2B,MAAM,gDAAgD,CAAC;AACzF,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,EACH,UAAU,EACV,iCAAiC,EACjC,yBAAyB,EACzB,uBAAuB,EACvB,2BAA2B,EAC3B,YAAY,EACZ,0BAA0B,EAC1B,gBAAgB,EAChB,mCAAmC,EACnC,wBAAwB,EACxB,2BAA2B,EAC3B,MAAM,EACN,gBAAgB,EACnB,CAAA"} 469 - \ No newline at end of file 470 - +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,iCAAiC,MAAM,6CAA6C,CAAC;AAC5F,OAAO,yBAAyB,MAAM,qCAAqC,CAAC;AAE5E,OAAO,uBAAuB,MAAM,sCAAsC,CAAC;AAC3E,OAAO,2BAA2B,MAAM,0CAA0C,CAAC;AAEnF,OAAO,YAAY,MAAM,2BAA2B,CAAC;AACrD,OAAO,0BAA0B,MAAM,+CAA+C,CAAC;AACvF,OAAO,gBAAgB,MAAM,qCAAqC,CAAC;AACnE,OAAO,mCAAmC,MAAM,sDAAsD,CAAC;AACvG,OAAO,wBAAwB,MAAM,kDAAkD,CAAC;AACxF,OAAO,2BAA2B,MAAM,gDAAgD,CAAC;AACzF,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,2BAA2B,MAAM,uCAAuC,CAAC;AAChF,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,EACL,UAAU,EACV,iCAAiC,EACjC,yBAAyB,EACzB,uBAAuB,EACvB,2BAA2B,EAC3B,YAAY,EACZ,0BAA0B,EAC1B,gBAAgB,EAChB,mCAAmC,EACnC,wBAAwB,EACxB,2BAA2B,EAC3B,MAAM,EACN,2BAA2B,EAC3B,gBAAgB,GACjB,CAAC"} 471 - \ No newline at end of file 1116 + diff --git a/dist/mjs/endpoints/UsersEndpoints.d.ts b/dist/mjs/endpoints/UsersEndpoints.d.ts 1117 + index 613633e0d2cf885fbc0aca7a67855b67dbcc465e..172bf9cf6f6d69e2fad97b578ef487d28e34f90f 100644 1118 + --- a/dist/mjs/endpoints/UsersEndpoints.d.ts 1119 + +++ b/dist/mjs/endpoints/UsersEndpoints.d.ts 1120 + @@ -1,5 +1,5 @@ 1121 + import type { User } from '../types.js'; 1122 + import EndpointsBase from './EndpointsBase.js'; 1123 + export default class UsersEndpoints extends EndpointsBase { 1124 + - profile(userId: string): Promise<User>; 1125 + + profile(userId: string): Promise<User | null>; 1126 + } 472 1127 diff --git a/dist/mjs/responsevalidation/DefaultResponseValidator.js.map b/dist/mjs/responsevalidation/DefaultResponseValidator.js.map 473 1128 index 02df457d0327575055c3c1b8ff28eb7ddad93532..9a36ddcdd58aeb0753350e88204064e4f7e5f009 100644 474 1129 --- a/dist/mjs/responsevalidation/DefaultResponseValidator.js.map ··· 487 1142 \ No newline at end of file 488 1143 +{"version":3,"file":"DefaultResponseDeserializer.js","sourceRoot":"","sources":["../../../src/serialization/DefaultResponseDeserializer.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,OAAO,OAAO,2BAA2B;IACrC,KAAK,CAAC,WAAW,CAAc,QAAkB;QACpD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAEnC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC9B,OAAO,IAAmB,CAAC;QAC/B,CAAC;QAED,OAAO,IAAmB,CAAC;IAC/B,CAAC;CACJ"} 489 1144 \ No newline at end of file 490 - diff --git a/src/index.ts b/src/index.ts 491 - index c930787038206b886c1769a30324c1863f36ad4c..7697be275db7b9f690ea2ac5675358181c944321 100644 492 - --- a/src/index.ts 493 - +++ b/src/index.ts 494 - @@ -12,27 +12,26 @@ import DocumentLocationRedirectionStrategy from "./redirection/DocumentLocationR 495 - import DefaultResponseValidator from "./responsevalidation/DefaultResponseValidator.js"; 496 - import DefaultResponseDeserializer from "./serialization/DefaultResponseDeserializer.js"; 497 - import { Scopes } from "./Scopes.js"; 498 - +import ProvidedAccessTokenStrategy from "./auth/ProvidedAccessTokenStrategy.js"; 499 - import { emptyAccessToken } from "./auth/IAuthStrategy.js"; 1145 + diff --git a/src/SpotifyApi.ts b/src/SpotifyApi.ts 1146 + index cc3438644134cdf4ce25456be665def9f0e4bff7..6cb80d473be9ebb70d8eb641a962545e54f27bf4 100644 1147 + --- a/src/SpotifyApi.ts 1148 + +++ b/src/SpotifyApi.ts 1149 + @@ -74,7 +74,7 @@ export class SpotifyApi { 1150 + this.authenticationStrategy.setConfiguration(this.sdkConfig); 1151 + } 1152 + 1153 + - public async makeRequest<TReturnType>(method: "GET" | "POST" | "PUT" | "DELETE", url: string, body: any = undefined, contentType: string | undefined = undefined): Promise<TReturnType> { 1154 + + public async makeRequest<TReturnType>(method: "GET" | "POST" | "PUT" | "DELETE", url: string, body: any = undefined, contentType: string | undefined = undefined): Promise<TReturnType | null> { 1155 + try { 1156 + const accessToken = await this.authenticationStrategy.getOrCreateAccessToken(); 1157 + if (isEmptyAccessToken(accessToken)) { 1158 + diff --git a/src/endpoints/AlbumsEndpoints.ts b/src/endpoints/AlbumsEndpoints.ts 1159 + index 79311e52dabcb0318bd09600d1bd3de0e70525b0..f5d300eb6aae9d0eb86cfc0e8b18e484a1997b7e 100644 1160 + --- a/src/endpoints/AlbumsEndpoints.ts 1161 + +++ b/src/endpoints/AlbumsEndpoints.ts 1162 + @@ -15,6 +15,7 @@ export default class AlbumsEndpoints extends EndpointsBase { 1163 + const params = this.paramsFor({ ids: idOrIds, market }); 1164 + // TODO: only returns top 20, validate here 1165 + const response = await this.getRequest<Albums>(`albums${params}`); 1166 + + if (!response) return response; 1167 + return response.albums; 1168 + } 1169 + 1170 + diff --git a/src/endpoints/ArtistsEndpoints.ts b/src/endpoints/ArtistsEndpoints.ts 1171 + index f1e95ca5ae7bfe7afad48de0efc998fc96abe312..d7cbe4b02baeae866268da2dc0346327a6f3dd0f 100644 1172 + --- a/src/endpoints/ArtistsEndpoints.ts 1173 + +++ b/src/endpoints/ArtistsEndpoints.ts 1174 + @@ -21,6 +21,7 @@ export default class ArtistsEndpoints extends EndpointsBase { 1175 + 1176 + const params = this.paramsFor({ ids: idOrIds }); 1177 + const response = await this.getRequest<Artists>(`artists${params}`); 1178 + + if (!response) return response; 1179 + return response.artists; 1180 + } 1181 + 1182 + diff --git a/src/endpoints/AudiobooksEndpoints.ts b/src/endpoints/AudiobooksEndpoints.ts 1183 + index ceaa6465119e98c624f777308f90ea1a1e1bc5b5..6620b7e18394f79fb30c28bb6b53b8ed5e4e5220 100644 1184 + --- a/src/endpoints/AudiobooksEndpoints.ts 1185 + +++ b/src/endpoints/AudiobooksEndpoints.ts 1186 + @@ -12,6 +12,7 @@ export default class AudiobooksEndpoints extends EndpointsBase { 1187 + 1188 + const params = this.paramsFor({ ids: idOrIds, market }); 1189 + const response = await this.getRequest<Audiobooks>(`audiobooks${params}`); 1190 + + if (!response) return response; 1191 + return response.audiobooks; 1192 + } 1193 + 1194 + diff --git a/src/endpoints/ChaptersEndpoints.ts b/src/endpoints/ChaptersEndpoints.ts 1195 + index 80afd92cfc9ed41e74b8fe5e8b31aa9c5c17f8c4..4989c6c70c7990f2c3e96b3c2e206c97bbbf396c 100644 1196 + --- a/src/endpoints/ChaptersEndpoints.ts 1197 + +++ b/src/endpoints/ChaptersEndpoints.ts 1198 + @@ -16,6 +16,7 @@ export default class ChaptersEndpoints extends EndpointsBase { 1199 + // TODO: Only returns top 50, validate / pre-check here 1200 + const params = this.paramsFor({ ids: idOrIds, market }); 1201 + const response = await this.getRequest<Chapters>(`chapters${params}`); 1202 + + if (!response) return response; 1203 + return response.chapters; 1204 + } 1205 + } 1206 + diff --git a/src/endpoints/EndpointsBase.ts b/src/endpoints/EndpointsBase.ts 1207 + index 588270c5581f8d4f617750c8486f77ed942a4ae8..8f1f38b971e23c6e250b1ad0c9d1ff1d9ae7cdbd 100644 1208 + --- a/src/endpoints/EndpointsBase.ts 1209 + +++ b/src/endpoints/EndpointsBase.ts 1210 + @@ -4,19 +4,19 @@ export default class EndpointsBase { 1211 + constructor(protected api: SpotifyApi) { 1212 + } 500 1213 501 - export { 502 - - SpotifyApi, 503 - - AuthorizationCodeWithPKCEStrategy, 504 - - ClientCredentialsStrategy, 505 - - InMemoryCachingStrategy, 506 - - LocalStorageCachingStrategy, 507 - - GenericCache, 508 - - ConsoleLoggingErrorHandler, 509 - - NoOpErrorHandler, 510 - - DocumentLocationRedirectionStrategy, 511 - - DefaultResponseValidator, 512 - - DefaultResponseDeserializer, 513 - - Scopes, 514 - - emptyAccessToken 515 - -} 516 - + SpotifyApi, 517 - + AuthorizationCodeWithPKCEStrategy, 518 - + ClientCredentialsStrategy, 519 - + InMemoryCachingStrategy, 520 - + LocalStorageCachingStrategy, 521 - + GenericCache, 522 - + ConsoleLoggingErrorHandler, 523 - + NoOpErrorHandler, 524 - + DocumentLocationRedirectionStrategy, 525 - + DefaultResponseValidator, 526 - + DefaultResponseDeserializer, 527 - + Scopes, 528 - + ProvidedAccessTokenStrategy, 529 - + emptyAccessToken, 530 - +}; 1214 + - protected async getRequest<TReturnType>(url: string): Promise<TReturnType> { 1215 + + protected async getRequest<TReturnType>(url: string): Promise<TReturnType | null> { 1216 + return await this.api.makeRequest<TReturnType>("GET", url); 1217 + } 531 1218 532 - export type * from "./types.js"; 1219 + - protected async postRequest<TReturnType, TBody = unknown>(url: string, body?: TBody, contentType: string | undefined = undefined): Promise<TReturnType> { 1220 + + protected async postRequest<TReturnType, TBody = unknown>(url: string, body?: TBody, contentType: string | undefined = undefined): Promise<TReturnType | null> { 1221 + return await this.api.makeRequest<TReturnType>("POST", url, body, contentType); 1222 + } 533 1223 534 - -export type { 535 - - IAuthStrategy, 536 - - ICacheStore, 537 - -} 538 - +export type { IAuthStrategy, ICacheStore }; 1224 + - protected async putRequest<TReturnType, TBody = unknown>(url: string, body?: TBody, contentType: string | undefined = undefined): Promise<TReturnType> { 1225 + + protected async putRequest<TReturnType, TBody = unknown>(url: string, body?: TBody, contentType: string | undefined = undefined): Promise<TReturnType | null> { 1226 + return await this.api.makeRequest<TReturnType>("PUT", url, body, contentType); 1227 + } 1228 + 1229 + - protected async deleteRequest<TReturnType, TBody = unknown>(url: string, body?: TBody): Promise<TReturnType> { 1230 + + protected async deleteRequest<TReturnType, TBody = unknown>(url: string, body?: TBody): Promise<TReturnType | null> { 1231 + return await this.api.makeRequest<TReturnType>("DELETE", url, body); 1232 + } 1233 + 1234 + diff --git a/src/endpoints/EpisodesEndpoints.ts b/src/endpoints/EpisodesEndpoints.ts 1235 + index c002e872232ccad4056172d02a662c3168f3b180..b19df1797ef9ed84d6f6f89dd488c84b4cfb31ab 100644 1236 + --- a/src/endpoints/EpisodesEndpoints.ts 1237 + +++ b/src/endpoints/EpisodesEndpoints.ts 1238 + @@ -13,6 +13,7 @@ export default class EpisodesEndpoints extends EndpointsBase { 1239 + 1240 + const params = this.paramsFor({ ids: idOrIds, market }); 1241 + const response = await this.getRequest<Episodes>(`episodes${params}`); 1242 + + if (!response) return response; 1243 + return response.episodes; 1244 + } 1245 + } 1246 + diff --git a/src/endpoints/SearchEndpoints.ts b/src/endpoints/SearchEndpoints.ts 1247 + index c6d08d27dc979bef80652f1c389e3b8249a670b9..ba788ddd6ddd8809fdf83c040edc78a4fe91c1a9 100644 1248 + --- a/src/endpoints/SearchEndpoints.ts 1249 + +++ b/src/endpoints/SearchEndpoints.ts 1250 + @@ -2,7 +2,7 @@ import type { ItemTypes, Market, MaxInt, SearchResults } from '../types.js'; 1251 + import EndpointsBase from './EndpointsBase.js'; 1252 + 1253 + export interface SearchExecutionFunction { 1254 + - <const T extends readonly ItemTypes[]>(q: string, type: T, market?: Market, limit?: MaxInt<50>, offset?: number, include_external?: string): Promise<SearchResults<T>>; 1255 + + <const T extends readonly ItemTypes[]>(q: string, type: T, market?: Market, limit?: MaxInt<50>, offset?: number, include_external?: string): Promise<SearchResults<T> | null>; 1256 + } 1257 + 1258 + export default class SearchEndpoints extends EndpointsBase { 1259 + diff --git a/src/endpoints/ShowsEndpoints.ts b/src/endpoints/ShowsEndpoints.ts 1260 + index 664c3a6a82ffd75b0eadbac0092330ba0e19aed1..fd59f795d5b789416e4c25f890ee4b159a972c43 100644 1261 + --- a/src/endpoints/ShowsEndpoints.ts 1262 + +++ b/src/endpoints/ShowsEndpoints.ts 1263 + @@ -14,6 +14,7 @@ export default class ShowsEndpoints extends EndpointsBase { 1264 + // TODO: only returns 50, validate here 1265 + const params = this.paramsFor({ ids: idOrIds, market }); 1266 + const response = await this.getRequest<Shows>(`shows${params}`); 1267 + + if (!response) return response; 1268 + return response.shows; 1269 + } 1270 + 1271 + diff --git a/src/endpoints/TracksEndpoints.ts b/src/endpoints/TracksEndpoints.ts 1272 + index c8019773d46cb560c9554482279abd35706b003a..6fbe67410aeef98d38dea2ea3ead491f47391d1c 100644 1273 + --- a/src/endpoints/TracksEndpoints.ts 1274 + +++ b/src/endpoints/TracksEndpoints.ts 1275 + @@ -14,6 +14,7 @@ export default class TracksEndpoints extends EndpointsBase { 1276 + const params = this.paramsFor({ ids: idOrIds, market }); 1277 + // TODO: only returns top 20, validate here 1278 + const response = await this.getRequest<Tracks>(`tracks${params}`); 1279 + + if (!response) return response; 1280 + return response.tracks; 1281 + } 1282 + 1283 + @@ -25,6 +26,7 @@ export default class TracksEndpoints extends EndpointsBase { 1284 + } 1285 + const params = this.paramsFor({ ids: idOrIds }); 1286 + const response = await this.getRequest<AudioFeaturesCollection>(`audio-features${params}`); 1287 + + if (!response) return response; 1288 + return response.audio_features; 1289 + } 1290 +
+13 -464
pnpm-lock.yaml
··· 6 6 7 7 patchedDependencies: 8 8 '@spotify/web-api-ts-sdk': 9 - hash: b36369a918d02543ad679d04428064d9b233b61da7ff46f9af693ee7cd3901d9 9 + hash: ptw4jgazdhouuxg5ym53ts4jam 10 10 path: patches/@spotify__web-api-ts-sdk.patch 11 11 12 12 importers: ··· 16 16 '@astrojs/node': 17 17 specifier: ^9.3.1 18 18 version: 9.3.1(astro@5.12.6(@types/node@24.1.0)(rollup@4.46.2)(typescript@5.8.3)) 19 - '@astrojs/rss': 20 - specifier: ^4.0.12 21 - version: 4.0.12 22 - '@astrojs/sitemap': 23 - specifier: ^3.5.0 24 - version: 3.5.0 25 - '@atcute/atproto': 26 - specifier: ^3.1.1 27 - version: 3.1.1 28 - '@atcute/bluesky': 29 - specifier: ^3.2.0 30 - version: 3.2.0 31 - '@atcute/bluesky-richtext-segmenter': 32 - specifier: ^2.0.3 33 - version: 2.0.3 34 - '@atcute/client': 35 - specifier: ^4.0.3 36 - version: 4.0.3 37 - '@atcute/identity-resolver': 38 - specifier: ^1.1.3 39 - version: 1.1.3(@atcute/identity@1.0.3) 40 - '@atcute/lexicons': 41 - specifier: ^1.1.0 42 - version: 1.1.0 43 - '@oddbird/css-anchor-positioning': 44 - specifier: ^0.6.1 45 - version: 0.6.1 46 19 '@spotify/web-api-ts-sdk': 47 20 specifier: ^1.2.0 48 - version: 1.2.0(patch_hash=b36369a918d02543ad679d04428064d9b233b61da7ff46f9af693ee7cd3901d9) 21 + version: 1.2.0(patch_hash=ptw4jgazdhouuxg5ym53ts4jam) 49 22 astro: 50 23 specifier: ^5.12.6 51 24 version: 5.12.6(@types/node@24.1.0)(rollup@4.46.2)(typescript@5.8.3) 52 - sharp: 53 - specifier: ^0.34.3 54 - version: 0.34.3 55 25 devDependencies: 56 26 prettier: 57 27 specifier: 3.6.2 ··· 80 50 resolution: {integrity: sha512-q8VwfU/fDZNoDOf+r7jUnMC2//H2l0TuQ6FkGJL8vD8nw/q5KiL3DS1KKBI3QhI9UQhpJ5dc7AtqfbXWuOgLCQ==} 81 51 engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0} 82 52 83 - '@astrojs/rss@4.0.12': 84 - resolution: {integrity: sha512-O5yyxHuDVb6DQ6VLOrbUVFSm+NpObulPxjs6XT9q3tC+RoKbN4HXMZLpv0LvXd1qdAjzVgJ1NFD+zKHJNDXikw==} 85 - 86 - '@astrojs/sitemap@3.5.0': 87 - resolution: {integrity: sha512-ldOvoBxuRgpcdndzksskOTzU55g76tkHC/POpejUbPGz6zR4rJKiXh8thX4WEPWDhCTZUafhJ1qf7k1muStHfg==} 88 - 89 53 '@astrojs/telemetry@3.3.0': 90 54 resolution: {integrity: sha512-UFBgfeldP06qu6khs/yY+q1cDAaArM2/7AEIqQ9Cuvf7B1hNLq0xDrZkct+QoIGyjq56y8IaE2I3CTvG99mlhQ==} 91 55 engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0} 92 56 93 - '@atcute/atproto@3.1.1': 94 - resolution: {integrity: sha512-D+RLTIPF0xLu7BPZY8KSewAPemJFh+3n3zeQ3ROsLxbTtCHbrTDMAmAFexaVRAPGcPYrwXaBUlv7yZjScJolMg==} 95 - 96 - '@atcute/bluesky-richtext-segmenter@2.0.3': 97 - resolution: {integrity: sha512-8Jy2EHdqx0mKI0k8l4h2cnaBN1pGgSzSazO0Gp85ttIQmgynZsQX6l4OWgaQx0aNZFmqZRXJ7N0rj/b2dlO1eQ==} 98 - 99 - '@atcute/bluesky@3.2.0': 100 - resolution: {integrity: sha512-OqPLqUNjXcgQ25MaPdU7H0QcWmZrx6QQk7d5B22A5U4xy+hZJ954kQ5mSAn24Bt0DEm4j/isq1WZovr3vaPTUA==} 101 - 102 - '@atcute/client@4.0.3': 103 - resolution: {integrity: sha512-RIOZWFVLca/HiPAAUDqQPOdOreCxTbL5cb+WUf5yqQOKIu5yEAP3eksinmlLmgIrlr5qVOE7brazUUzaskFCfw==} 104 - 105 - '@atcute/identity-resolver@1.1.3': 106 - resolution: {integrity: sha512-KZgGgg99CWaV7Df3+h3X/WMrDzTPQVfsaoIVbTNLx2B56BvCL2EmaxPSVw/7BFUJMZHlVU4rtoEB4lyvNyMswA==} 107 - peerDependencies: 108 - '@atcute/identity': ^1.0.0 109 - 110 - '@atcute/identity@1.0.3': 111 - resolution: {integrity: sha512-mNMxbKHFGys03A8JXKk0KfMBzdd0vrYMzZZWjpw1nYTs0+ea6bo5S1hwqVUZxHdo1gFHSe/t63jxQIF4yL9aKw==} 112 - 113 - '@atcute/lexicons@1.1.0': 114 - resolution: {integrity: sha512-LFqwnria78xLYb62Ri/+WwQpUTgZp2DuyolNGIIOV1dpiKhFFFh//nscHMA6IExFLQRqWDs3tTjy7zv0h3sf1Q==} 115 - 116 - '@atcute/util-fetch@1.0.1': 117 - resolution: {integrity: sha512-Clc0E/5ufyGBVfYBUwWNlHONlZCoblSr4Ho50l1LhmRPGB1Wu/AQ9Sz+rsBg7fdaW/auve8ulmwhRhnX2cGRow==} 118 - 119 57 '@babel/helper-string-parser@7.27.1': 120 58 resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} 121 59 engines: {node: '>=6.9.0'} ··· 132 70 '@babel/types@7.28.2': 133 71 resolution: {integrity: sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==} 134 72 engines: {node: '>=6.9.0'} 135 - 136 - '@badrap/valita@0.4.6': 137 - resolution: {integrity: sha512-4kdqcjyxo/8RQ8ayjms47HCWZIF5981oE5nIenbfThKDxWXtEHKipAOWlflpPJzZx9y/JWYQkp18Awr7VuepFg==} 138 - engines: {node: '>= 18'} 139 73 140 74 '@capsizecss/unpack@2.4.0': 141 75 resolution: {integrity: sha512-GrSU71meACqcmIUxPYOJvGKF0yryjN/L1aCuE9DViCTJI7bfkjgYDPD1zbNDcINJwSSP6UaBZY9GAbYDO7re0Q==} ··· 299 233 cpu: [x64] 300 234 os: [win32] 301 235 302 - '@floating-ui/core@1.7.3': 303 - resolution: {integrity: sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==} 304 - 305 - '@floating-ui/dom@1.7.3': 306 - resolution: {integrity: sha512-uZA413QEpNuhtb3/iIKoYMSK07keHPYeXF02Zhd6e213j+d1NamLix/mCLxBUDW/Gx52sPH2m+chlUsyaBs/Ag==} 307 - 308 - '@floating-ui/utils@0.2.10': 309 - resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==} 310 - 311 236 '@img/sharp-darwin-arm64@0.33.5': 312 237 resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==} 313 238 engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 314 239 cpu: [arm64] 315 240 os: [darwin] 316 241 317 - '@img/sharp-darwin-arm64@0.34.3': 318 - resolution: {integrity: sha512-ryFMfvxxpQRsgZJqBd4wsttYQbCxsJksrv9Lw/v798JcQ8+w84mBWuXwl+TT0WJ/WrYOLaYpwQXi3sA9nTIaIg==} 319 - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 320 - cpu: [arm64] 321 - os: [darwin] 322 - 323 242 '@img/sharp-darwin-x64@0.33.5': 324 243 resolution: {integrity: sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==} 325 244 engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 326 245 cpu: [x64] 327 246 os: [darwin] 328 247 329 - '@img/sharp-darwin-x64@0.34.3': 330 - resolution: {integrity: sha512-yHpJYynROAj12TA6qil58hmPmAwxKKC7reUqtGLzsOHfP7/rniNGTL8tjWX6L3CTV4+5P4ypcS7Pp+7OB+8ihA==} 331 - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 332 - cpu: [x64] 333 - os: [darwin] 334 - 335 248 '@img/sharp-libvips-darwin-arm64@1.0.4': 336 249 resolution: {integrity: sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==} 337 250 cpu: [arm64] 338 251 os: [darwin] 339 252 340 - '@img/sharp-libvips-darwin-arm64@1.2.0': 341 - resolution: {integrity: sha512-sBZmpwmxqwlqG9ueWFXtockhsxefaV6O84BMOrhtg/YqbTaRdqDE7hxraVE3y6gVM4eExmfzW4a8el9ArLeEiQ==} 342 - cpu: [arm64] 343 - os: [darwin] 344 - 345 253 '@img/sharp-libvips-darwin-x64@1.0.4': 346 254 resolution: {integrity: sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==} 347 255 cpu: [x64] 348 256 os: [darwin] 349 257 350 - '@img/sharp-libvips-darwin-x64@1.2.0': 351 - resolution: {integrity: sha512-M64XVuL94OgiNHa5/m2YvEQI5q2cl9d/wk0qFTDVXcYzi43lxuiFTftMR1tOnFQovVXNZJ5TURSDK2pNe9Yzqg==} 352 - cpu: [x64] 353 - os: [darwin] 354 - 355 258 '@img/sharp-libvips-linux-arm64@1.0.4': 356 259 resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==} 357 260 cpu: [arm64] 358 261 os: [linux] 359 262 360 - '@img/sharp-libvips-linux-arm64@1.2.0': 361 - resolution: {integrity: sha512-RXwd0CgG+uPRX5YYrkzKyalt2OJYRiJQ8ED/fi1tq9WQW2jsQIn0tqrlR5l5dr/rjqq6AHAxURhj2DVjyQWSOA==} 362 - cpu: [arm64] 363 - os: [linux] 364 - 365 263 '@img/sharp-libvips-linux-arm@1.0.5': 366 264 resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==} 367 265 cpu: [arm] 368 266 os: [linux] 369 267 370 - '@img/sharp-libvips-linux-arm@1.2.0': 371 - resolution: {integrity: sha512-mWd2uWvDtL/nvIzThLq3fr2nnGfyr/XMXlq8ZJ9WMR6PXijHlC3ksp0IpuhK6bougvQrchUAfzRLnbsen0Cqvw==} 372 - cpu: [arm] 373 - os: [linux] 374 - 375 - '@img/sharp-libvips-linux-ppc64@1.2.0': 376 - resolution: {integrity: sha512-Xod/7KaDDHkYu2phxxfeEPXfVXFKx70EAFZ0qyUdOjCcxbjqyJOEUpDe6RIyaunGxT34Anf9ue/wuWOqBW2WcQ==} 377 - cpu: [ppc64] 378 - os: [linux] 379 - 380 268 '@img/sharp-libvips-linux-s390x@1.0.4': 381 269 resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==} 382 270 cpu: [s390x] 383 271 os: [linux] 384 272 385 - '@img/sharp-libvips-linux-s390x@1.2.0': 386 - resolution: {integrity: sha512-eMKfzDxLGT8mnmPJTNMcjfO33fLiTDsrMlUVcp6b96ETbnJmd4uvZxVJSKPQfS+odwfVaGifhsB07J1LynFehw==} 387 - cpu: [s390x] 388 - os: [linux] 389 - 390 273 '@img/sharp-libvips-linux-x64@1.0.4': 391 274 resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==} 392 275 cpu: [x64] 393 276 os: [linux] 394 277 395 - '@img/sharp-libvips-linux-x64@1.2.0': 396 - resolution: {integrity: sha512-ZW3FPWIc7K1sH9E3nxIGB3y3dZkpJlMnkk7z5tu1nSkBoCgw2nSRTFHI5pB/3CQaJM0pdzMF3paf9ckKMSE9Tg==} 397 - cpu: [x64] 398 - os: [linux] 399 - 400 278 '@img/sharp-libvips-linuxmusl-arm64@1.0.4': 401 279 resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==} 402 280 cpu: [arm64] 403 281 os: [linux] 404 282 405 - '@img/sharp-libvips-linuxmusl-arm64@1.2.0': 406 - resolution: {integrity: sha512-UG+LqQJbf5VJ8NWJ5Z3tdIe/HXjuIdo4JeVNADXBFuG7z9zjoegpzzGIyV5zQKi4zaJjnAd2+g2nna8TZvuW9Q==} 407 - cpu: [arm64] 408 - os: [linux] 409 - 410 283 '@img/sharp-libvips-linuxmusl-x64@1.0.4': 411 284 resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==} 412 285 cpu: [x64] 413 286 os: [linux] 414 287 415 - '@img/sharp-libvips-linuxmusl-x64@1.2.0': 416 - resolution: {integrity: sha512-SRYOLR7CXPgNze8akZwjoGBoN1ThNZoqpOgfnOxmWsklTGVfJiGJoC/Lod7aNMGA1jSsKWM1+HRX43OP6p9+6Q==} 417 - cpu: [x64] 418 - os: [linux] 419 - 420 288 '@img/sharp-linux-arm64@0.33.5': 421 289 resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==} 422 - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 423 - cpu: [arm64] 424 - os: [linux] 425 - 426 - '@img/sharp-linux-arm64@0.34.3': 427 - resolution: {integrity: sha512-QdrKe3EvQrqwkDrtuTIjI0bu6YEJHTgEeqdzI3uWJOH6G1O8Nl1iEeVYRGdj1h5I21CqxSvQp1Yv7xeU3ZewbA==} 428 290 engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 429 291 cpu: [arm64] 430 292 os: [linux] ··· 435 297 cpu: [arm] 436 298 os: [linux] 437 299 438 - '@img/sharp-linux-arm@0.34.3': 439 - resolution: {integrity: sha512-oBK9l+h6KBN0i3dC8rYntLiVfW8D8wH+NPNT3O/WBHeW0OQWCjfWksLUaPidsrDKpJgXp3G3/hkmhptAW0I3+A==} 440 - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 441 - cpu: [arm] 442 - os: [linux] 443 - 444 - '@img/sharp-linux-ppc64@0.34.3': 445 - resolution: {integrity: sha512-GLtbLQMCNC5nxuImPR2+RgrviwKwVql28FWZIW1zWruy6zLgA5/x2ZXk3mxj58X/tszVF69KK0Is83V8YgWhLA==} 446 - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 447 - cpu: [ppc64] 448 - os: [linux] 449 - 450 300 '@img/sharp-linux-s390x@0.33.5': 451 301 resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==} 452 302 engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 453 303 cpu: [s390x] 454 304 os: [linux] 455 305 456 - '@img/sharp-linux-s390x@0.34.3': 457 - resolution: {integrity: sha512-3gahT+A6c4cdc2edhsLHmIOXMb17ltffJlxR0aC2VPZfwKoTGZec6u5GrFgdR7ciJSsHT27BD3TIuGcuRT0KmQ==} 458 - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 459 - cpu: [s390x] 460 - os: [linux] 461 - 462 306 '@img/sharp-linux-x64@0.33.5': 463 307 resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==} 464 308 engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 465 309 cpu: [x64] 466 310 os: [linux] 467 311 468 - '@img/sharp-linux-x64@0.34.3': 469 - resolution: {integrity: sha512-8kYso8d806ypnSq3/Ly0QEw90V5ZoHh10yH0HnrzOCr6DKAPI6QVHvwleqMkVQ0m+fc7EH8ah0BB0QPuWY6zJQ==} 470 - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 471 - cpu: [x64] 472 - os: [linux] 473 - 474 312 '@img/sharp-linuxmusl-arm64@0.33.5': 475 313 resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==} 476 - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 477 - cpu: [arm64] 478 - os: [linux] 479 - 480 - '@img/sharp-linuxmusl-arm64@0.34.3': 481 - resolution: {integrity: sha512-vAjbHDlr4izEiXM1OTggpCcPg9tn4YriK5vAjowJsHwdBIdx0fYRsURkxLG2RLm9gyBq66gwtWI8Gx0/ov+JKQ==} 482 314 engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 483 315 cpu: [arm64] 484 316 os: [linux] ··· 489 321 cpu: [x64] 490 322 os: [linux] 491 323 492 - '@img/sharp-linuxmusl-x64@0.34.3': 493 - resolution: {integrity: sha512-gCWUn9547K5bwvOn9l5XGAEjVTTRji4aPTqLzGXHvIr6bIDZKNTA34seMPgM0WmSf+RYBH411VavCejp3PkOeQ==} 494 - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 495 - cpu: [x64] 496 - os: [linux] 497 - 498 324 '@img/sharp-wasm32@0.33.5': 499 325 resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==} 500 326 engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 501 327 cpu: [wasm32] 502 328 503 - '@img/sharp-wasm32@0.34.3': 504 - resolution: {integrity: sha512-+CyRcpagHMGteySaWos8IbnXcHgfDn7pO2fiC2slJxvNq9gDipYBN42/RagzctVRKgxATmfqOSulgZv5e1RdMg==} 505 - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 506 - cpu: [wasm32] 507 - 508 - '@img/sharp-win32-arm64@0.34.3': 509 - resolution: {integrity: sha512-MjnHPnbqMXNC2UgeLJtX4XqoVHHlZNd+nPt1kRPmj63wURegwBhZlApELdtxM2OIZDRv/DFtLcNhVbd1z8GYXQ==} 510 - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 511 - cpu: [arm64] 512 - os: [win32] 513 - 514 329 '@img/sharp-win32-ia32@0.33.5': 515 330 resolution: {integrity: sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==} 516 331 engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 517 332 cpu: [ia32] 518 333 os: [win32] 519 334 520 - '@img/sharp-win32-ia32@0.34.3': 521 - resolution: {integrity: sha512-xuCdhH44WxuXgOM714hn4amodJMZl3OEvf0GVTm0BEyMeA2to+8HEdRPShH0SLYptJY1uBw+SCFP9WVQi1Q/cw==} 522 - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 523 - cpu: [ia32] 524 - os: [win32] 525 - 526 335 '@img/sharp-win32-x64@0.33.5': 527 336 resolution: {integrity: sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==} 528 337 engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 529 338 cpu: [x64] 530 339 os: [win32] 531 340 532 - '@img/sharp-win32-x64@0.34.3': 533 - resolution: {integrity: sha512-OWwz05d++TxzLEv4VnsTz5CmZ6mI6S05sfQGEMrNrQcOEERbX46332IvE7pO/EUiw7jUrrS40z/M7kPyjfl04g==} 534 - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 535 - cpu: [x64] 536 - os: [win32] 537 - 538 341 '@jridgewell/sourcemap-codec@1.5.4': 539 342 resolution: {integrity: sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==} 540 - 541 - '@oddbird/css-anchor-positioning@0.6.1': 542 - resolution: {integrity: sha512-/M1guQMJROMAFjS0uTmcg93S2X5r0Gwe6m5DqmRrGxNEUe1llmY6/Qw8UuhvexP6yeD+GDCP9CJtXBJS1vS9UQ==} 543 343 544 344 '@oslojs/encoding@1.1.0': 545 345 resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==} ··· 680 480 '@swc/helpers@0.5.17': 681 481 resolution: {integrity: sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==} 682 482 683 - '@types/css-tree@2.3.10': 684 - resolution: {integrity: sha512-WcaBazJ84RxABvRttQjjFWgTcHvZR9jGr0Y3hccPkHjFyk/a3N8EuxjKr+QfrwjoM5b1yI1Uj1i7EzOAAwBwag==} 685 - 686 483 '@types/debug@4.1.12': 687 484 resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} 688 485 ··· 703 500 704 501 '@types/nlcst@2.0.3': 705 502 resolution: {integrity: sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==} 706 - 707 - '@types/node@17.0.45': 708 - resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} 709 503 710 504 '@types/node@24.1.0': 711 505 resolution: {integrity: sha512-ut5FthK5moxFKH2T1CUOC6ctR67rQRvvHdFLCD2Ql6KXmMuCrjsSsRI9UsLCm9M18BMwClv4pn327UvB7eeO1w==} 712 506 713 - '@types/sax@1.2.7': 714 - resolution: {integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==} 715 - 716 507 '@types/unist@3.0.3': 717 508 resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} 718 509 ··· 742 533 anymatch@3.1.3: 743 534 resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} 744 535 engines: {node: '>= 8'} 745 - 746 - arg@5.0.2: 747 - resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} 748 536 749 537 argparse@2.0.1: 750 538 resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} ··· 952 740 resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} 953 741 engines: {node: '>=12'} 954 742 955 - esm-env@1.2.2: 956 - resolution: {integrity: sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==} 957 - 958 743 estree-walker@2.0.2: 959 744 resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} 960 745 ··· 973 758 974 759 fast-deep-equal@3.1.3: 975 760 resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} 976 - 977 - fast-xml-parser@5.2.5: 978 - resolution: {integrity: sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==} 979 - hasBin: true 980 761 981 762 fdir@6.4.6: 982 763 resolution: {integrity: sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==} ··· 1265 1046 engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 1266 1047 hasBin: true 1267 1048 1268 - nanoid@5.1.5: 1269 - resolution: {integrity: sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==} 1270 - engines: {node: ^18 || >=20} 1271 - hasBin: true 1272 - 1273 1049 neotraverse@0.6.18: 1274 1050 resolution: {integrity: sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==} 1275 1051 engines: {node: '>= 10'} ··· 1448 1224 sass-formatter@0.7.9: 1449 1225 resolution: {integrity: sha512-CWZ8XiSim+fJVG0cFLStwDvft1VI7uvXdCNJYXhDvowiv+DsbD1nXLiQ4zrE5UBvj5DWZJ93cwN0NX5PMsr1Pw==} 1450 1226 1451 - sax@1.4.1: 1452 - resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==} 1453 - 1454 1227 semver@7.7.2: 1455 1228 resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} 1456 1229 engines: {node: '>=10'} ··· 1470 1243 resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==} 1471 1244 engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 1472 1245 1473 - sharp@0.34.3: 1474 - resolution: {integrity: sha512-eX2IQ6nFohW4DbvHIOLRB3MHFpYqaqvXd3Tp5e/T/dSH83fxaNJQRvDMhASmkNTsNTVF2/OOopzRCt7xokgPfg==} 1475 - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 1476 - 1477 1246 shiki@3.8.1: 1478 1247 resolution: {integrity: sha512-+MYIyjwGPCaegbpBeFN9+oOifI8CKiKG3awI/6h3JeT85c//H2wDW/xCJEGuQ5jPqtbboKNqNy+JyX9PYpGwNg==} 1479 1248 ··· 1483 1252 sisteransi@1.0.5: 1484 1253 resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} 1485 1254 1486 - sitemap@8.0.0: 1487 - resolution: {integrity: sha512-+AbdxhM9kJsHtruUF39bwS/B0Fytw6Fr1o4ZAIAEqA6cke2xcoO2GleBw9Zw7nRzILVEgz7zBM5GiTJjie1G9A==} 1488 - engines: {node: '>=14.0.0', npm: '>=6.0.0'} 1489 - hasBin: true 1490 - 1491 1255 smol-toml@1.4.1: 1492 1256 resolution: {integrity: sha512-CxdwHXyYTONGHThDbq5XdwbFsuY4wlClRGejfE2NtwUtiHYsP1QtNsHb/hnj31jKYSchztJsaA8pSQoVzkfCFg==} 1493 1257 engines: {node: '>= 18'} ··· 1506 1270 statuses@2.0.2: 1507 1271 resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} 1508 1272 engines: {node: '>= 0.8'} 1509 - 1510 - stream-replace-string@2.0.0: 1511 - resolution: {integrity: sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w==} 1512 1273 1513 1274 string-width@4.2.3: 1514 1275 resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} ··· 1528 1289 strip-ansi@7.1.0: 1529 1290 resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} 1530 1291 engines: {node: '>=12'} 1531 - 1532 - strnum@2.1.1: 1533 - resolution: {integrity: sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==} 1534 1292 1535 1293 suf-log@2.5.3: 1536 1294 resolution: {integrity: sha512-KvC8OPjzdNOe+xQ4XWJV2whQA0aM1kGVczMQ8+dStAO6KfEB140JEVQ9dE76ONZ0/Ylf67ni4tILPJB41U0eow==} ··· 1849 1607 dependencies: 1850 1608 prismjs: 1.30.0 1851 1609 1852 - '@astrojs/rss@4.0.12': 1853 - dependencies: 1854 - fast-xml-parser: 5.2.5 1855 - kleur: 4.1.5 1856 - 1857 - '@astrojs/sitemap@3.5.0': 1858 - dependencies: 1859 - sitemap: 8.0.0 1860 - stream-replace-string: 2.0.0 1861 - zod: 3.25.76 1862 - 1863 1610 '@astrojs/telemetry@3.3.0': 1864 1611 dependencies: 1865 1612 ci-info: 4.3.0 ··· 1872 1619 transitivePeerDependencies: 1873 1620 - supports-color 1874 1621 1875 - '@atcute/atproto@3.1.1': 1876 - dependencies: 1877 - '@atcute/lexicons': 1.1.0 1878 - 1879 - '@atcute/bluesky-richtext-segmenter@2.0.3': 1880 - dependencies: 1881 - '@atcute/bluesky': 3.2.0 1882 - '@atcute/lexicons': 1.1.0 1883 - 1884 - '@atcute/bluesky@3.2.0': 1885 - dependencies: 1886 - '@atcute/atproto': 3.1.1 1887 - '@atcute/lexicons': 1.1.0 1888 - 1889 - '@atcute/client@4.0.3': 1890 - dependencies: 1891 - '@atcute/identity': 1.0.3 1892 - '@atcute/lexicons': 1.1.0 1893 - 1894 - '@atcute/identity-resolver@1.1.3(@atcute/identity@1.0.3)': 1895 - dependencies: 1896 - '@atcute/identity': 1.0.3 1897 - '@atcute/lexicons': 1.1.0 1898 - '@atcute/util-fetch': 1.0.1 1899 - '@badrap/valita': 0.4.6 1900 - 1901 - '@atcute/identity@1.0.3': 1902 - dependencies: 1903 - '@atcute/lexicons': 1.1.0 1904 - '@badrap/valita': 0.4.6 1905 - 1906 - '@atcute/lexicons@1.1.0': 1907 - dependencies: 1908 - esm-env: 1.2.2 1909 - 1910 - '@atcute/util-fetch@1.0.1': 1911 - dependencies: 1912 - '@badrap/valita': 0.4.6 1913 - 1914 1622 '@babel/helper-string-parser@7.27.1': {} 1915 1623 1916 1624 '@babel/helper-validator-identifier@7.27.1': {} ··· 1923 1631 dependencies: 1924 1632 '@babel/helper-string-parser': 7.27.1 1925 1633 '@babel/helper-validator-identifier': 7.27.1 1926 - 1927 - '@badrap/valita@0.4.6': {} 1928 1634 1929 1635 '@capsizecss/unpack@2.4.0': 1930 1636 dependencies: ··· 2017 1723 '@esbuild/win32-x64@0.25.8': 2018 1724 optional: true 2019 1725 2020 - '@floating-ui/core@1.7.3': 2021 - dependencies: 2022 - '@floating-ui/utils': 0.2.10 2023 - 2024 - '@floating-ui/dom@1.7.3': 2025 - dependencies: 2026 - '@floating-ui/core': 1.7.3 2027 - '@floating-ui/utils': 0.2.10 2028 - 2029 - '@floating-ui/utils@0.2.10': {} 2030 - 2031 1726 '@img/sharp-darwin-arm64@0.33.5': 2032 1727 optionalDependencies: 2033 1728 '@img/sharp-libvips-darwin-arm64': 1.0.4 2034 1729 optional: true 2035 1730 2036 - '@img/sharp-darwin-arm64@0.34.3': 2037 - optionalDependencies: 2038 - '@img/sharp-libvips-darwin-arm64': 1.2.0 2039 - optional: true 2040 - 2041 1731 '@img/sharp-darwin-x64@0.33.5': 2042 1732 optionalDependencies: 2043 1733 '@img/sharp-libvips-darwin-x64': 1.0.4 2044 1734 optional: true 2045 1735 2046 - '@img/sharp-darwin-x64@0.34.3': 2047 - optionalDependencies: 2048 - '@img/sharp-libvips-darwin-x64': 1.2.0 2049 - optional: true 2050 - 2051 1736 '@img/sharp-libvips-darwin-arm64@1.0.4': 2052 1737 optional: true 2053 1738 2054 - '@img/sharp-libvips-darwin-arm64@1.2.0': 2055 - optional: true 2056 - 2057 1739 '@img/sharp-libvips-darwin-x64@1.0.4': 2058 1740 optional: true 2059 1741 2060 - '@img/sharp-libvips-darwin-x64@1.2.0': 2061 - optional: true 2062 - 2063 1742 '@img/sharp-libvips-linux-arm64@1.0.4': 2064 1743 optional: true 2065 1744 2066 - '@img/sharp-libvips-linux-arm64@1.2.0': 2067 - optional: true 2068 - 2069 1745 '@img/sharp-libvips-linux-arm@1.0.5': 2070 1746 optional: true 2071 1747 2072 - '@img/sharp-libvips-linux-arm@1.2.0': 2073 - optional: true 2074 - 2075 - '@img/sharp-libvips-linux-ppc64@1.2.0': 2076 - optional: true 2077 - 2078 1748 '@img/sharp-libvips-linux-s390x@1.0.4': 2079 - optional: true 2080 - 2081 - '@img/sharp-libvips-linux-s390x@1.2.0': 2082 1749 optional: true 2083 1750 2084 1751 '@img/sharp-libvips-linux-x64@1.0.4': 2085 1752 optional: true 2086 1753 2087 - '@img/sharp-libvips-linux-x64@1.2.0': 2088 - optional: true 2089 - 2090 1754 '@img/sharp-libvips-linuxmusl-arm64@1.0.4': 2091 1755 optional: true 2092 1756 2093 - '@img/sharp-libvips-linuxmusl-arm64@1.2.0': 2094 - optional: true 2095 - 2096 1757 '@img/sharp-libvips-linuxmusl-x64@1.0.4': 2097 1758 optional: true 2098 1759 2099 - '@img/sharp-libvips-linuxmusl-x64@1.2.0': 2100 - optional: true 2101 - 2102 1760 '@img/sharp-linux-arm64@0.33.5': 2103 1761 optionalDependencies: 2104 1762 '@img/sharp-libvips-linux-arm64': 1.0.4 2105 - optional: true 2106 - 2107 - '@img/sharp-linux-arm64@0.34.3': 2108 - optionalDependencies: 2109 - '@img/sharp-libvips-linux-arm64': 1.2.0 2110 1763 optional: true 2111 1764 2112 1765 '@img/sharp-linux-arm@0.33.5': ··· 2114 1767 '@img/sharp-libvips-linux-arm': 1.0.5 2115 1768 optional: true 2116 1769 2117 - '@img/sharp-linux-arm@0.34.3': 2118 - optionalDependencies: 2119 - '@img/sharp-libvips-linux-arm': 1.2.0 2120 - optional: true 2121 - 2122 - '@img/sharp-linux-ppc64@0.34.3': 2123 - optionalDependencies: 2124 - '@img/sharp-libvips-linux-ppc64': 1.2.0 2125 - optional: true 2126 - 2127 1770 '@img/sharp-linux-s390x@0.33.5': 2128 1771 optionalDependencies: 2129 1772 '@img/sharp-libvips-linux-s390x': 1.0.4 2130 - optional: true 2131 - 2132 - '@img/sharp-linux-s390x@0.34.3': 2133 - optionalDependencies: 2134 - '@img/sharp-libvips-linux-s390x': 1.2.0 2135 1773 optional: true 2136 1774 2137 1775 '@img/sharp-linux-x64@0.33.5': ··· 2139 1777 '@img/sharp-libvips-linux-x64': 1.0.4 2140 1778 optional: true 2141 1779 2142 - '@img/sharp-linux-x64@0.34.3': 2143 - optionalDependencies: 2144 - '@img/sharp-libvips-linux-x64': 1.2.0 2145 - optional: true 2146 - 2147 1780 '@img/sharp-linuxmusl-arm64@0.33.5': 2148 1781 optionalDependencies: 2149 1782 '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 2150 1783 optional: true 2151 1784 2152 - '@img/sharp-linuxmusl-arm64@0.34.3': 2153 - optionalDependencies: 2154 - '@img/sharp-libvips-linuxmusl-arm64': 1.2.0 2155 - optional: true 2156 - 2157 1785 '@img/sharp-linuxmusl-x64@0.33.5': 2158 1786 optionalDependencies: 2159 1787 '@img/sharp-libvips-linuxmusl-x64': 1.0.4 2160 - optional: true 2161 - 2162 - '@img/sharp-linuxmusl-x64@0.34.3': 2163 - optionalDependencies: 2164 - '@img/sharp-libvips-linuxmusl-x64': 1.2.0 2165 1788 optional: true 2166 1789 2167 1790 '@img/sharp-wasm32@0.33.5': ··· 2169 1792 '@emnapi/runtime': 1.4.5 2170 1793 optional: true 2171 1794 2172 - '@img/sharp-wasm32@0.34.3': 2173 - dependencies: 2174 - '@emnapi/runtime': 1.4.5 2175 - optional: true 2176 - 2177 - '@img/sharp-win32-arm64@0.34.3': 2178 - optional: true 2179 - 2180 1795 '@img/sharp-win32-ia32@0.33.5': 2181 - optional: true 2182 - 2183 - '@img/sharp-win32-ia32@0.34.3': 2184 1796 optional: true 2185 1797 2186 1798 '@img/sharp-win32-x64@0.33.5': 2187 - optional: true 2188 - 2189 - '@img/sharp-win32-x64@0.34.3': 2190 1799 optional: true 2191 1800 2192 1801 '@jridgewell/sourcemap-codec@1.5.4': {} 2193 - 2194 - '@oddbird/css-anchor-positioning@0.6.1': 2195 - dependencies: 2196 - '@floating-ui/dom': 1.7.3 2197 - '@types/css-tree': 2.3.10 2198 - css-tree: 3.1.0 2199 - nanoid: 5.1.5 2200 1802 2201 1803 '@oslojs/encoding@1.1.0': {} 2202 1804 ··· 2301 1903 2302 1904 '@shikijs/vscode-textmate@10.0.2': {} 2303 1905 2304 - '@spotify/web-api-ts-sdk@1.2.0(patch_hash=b36369a918d02543ad679d04428064d9b233b61da7ff46f9af693ee7cd3901d9)': {} 1906 + '@spotify/web-api-ts-sdk@1.2.0(patch_hash=ptw4jgazdhouuxg5ym53ts4jam)': {} 2305 1907 2306 1908 '@swc/helpers@0.5.17': 2307 1909 dependencies: 2308 1910 tslib: 2.8.1 2309 - 2310 - '@types/css-tree@2.3.10': {} 2311 1911 2312 1912 '@types/debug@4.1.12': 2313 1913 dependencies: ··· 2333 1933 dependencies: 2334 1934 '@types/unist': 3.0.3 2335 1935 2336 - '@types/node@17.0.45': {} 2337 - 2338 1936 '@types/node@24.1.0': 2339 1937 dependencies: 2340 1938 undici-types: 7.8.0 2341 1939 2342 - '@types/sax@1.2.7': 2343 - dependencies: 2344 - '@types/node': 24.1.0 2345 - 2346 1940 '@types/unist@3.0.3': {} 2347 1941 2348 1942 '@ungap/structured-clone@1.3.0': {} ··· 2363 1957 dependencies: 2364 1958 normalize-path: 3.0.0 2365 1959 picomatch: 2.3.1 2366 - 2367 - arg@5.0.2: {} 2368 1960 2369 1961 argparse@2.0.1: {} 2370 1962 ··· 2525 2117 color-convert@2.0.1: 2526 2118 dependencies: 2527 2119 color-name: 1.1.4 2120 + optional: true 2528 2121 2529 - color-name@1.1.4: {} 2122 + color-name@1.1.4: 2123 + optional: true 2530 2124 2531 2125 color-string@1.9.1: 2532 2126 dependencies: 2533 2127 color-name: 1.1.4 2534 2128 simple-swizzle: 0.2.2 2129 + optional: true 2535 2130 2536 2131 color@4.2.3: 2537 2132 dependencies: 2538 2133 color-convert: 2.0.1 2539 2134 color-string: 1.9.1 2135 + optional: true 2540 2136 2541 2137 comma-separated-tokens@2.0.3: {} 2542 2138 ··· 2579 2175 2580 2176 destr@2.0.5: {} 2581 2177 2582 - detect-libc@2.0.4: {} 2178 + detect-libc@2.0.4: 2179 + optional: true 2583 2180 2584 2181 deterministic-object-hash@2.0.2: 2585 2182 dependencies: ··· 2644 2241 2645 2242 escape-string-regexp@5.0.0: {} 2646 2243 2647 - esm-env@1.2.2: {} 2648 - 2649 2244 estree-walker@2.0.2: {} 2650 2245 2651 2246 estree-walker@3.0.3: ··· 2659 2254 extend@3.0.2: {} 2660 2255 2661 2256 fast-deep-equal@3.1.3: {} 2662 - 2663 - fast-xml-parser@5.2.5: 2664 - dependencies: 2665 - strnum: 2.1.1 2666 2257 2667 2258 fdir@6.4.6(picomatch@4.0.3): 2668 2259 optionalDependencies: ··· 2815 2406 2816 2407 iron-webcrypto@1.2.1: {} 2817 2408 2818 - is-arrayish@0.3.2: {} 2409 + is-arrayish@0.3.2: 2410 + optional: true 2819 2411 2820 2412 is-docker@3.0.0: {} 2821 2413 ··· 3180 2772 3181 2773 nanoid@3.3.11: {} 3182 2774 3183 - nanoid@5.1.5: {} 3184 - 3185 2775 neotraverse@0.6.18: {} 3186 2776 3187 2777 nlcst-to-string@4.0.0: ··· 3418 3008 dependencies: 3419 3009 suf-log: 2.5.3 3420 3010 3421 - sax@1.4.1: {} 3422 - 3423 3011 semver@7.7.2: {} 3424 3012 3425 3013 send@1.2.0: ··· 3469 3057 '@img/sharp-win32-x64': 0.33.5 3470 3058 optional: true 3471 3059 3472 - sharp@0.34.3: 3473 - dependencies: 3474 - color: 4.2.3 3475 - detect-libc: 2.0.4 3476 - semver: 7.7.2 3477 - optionalDependencies: 3478 - '@img/sharp-darwin-arm64': 0.34.3 3479 - '@img/sharp-darwin-x64': 0.34.3 3480 - '@img/sharp-libvips-darwin-arm64': 1.2.0 3481 - '@img/sharp-libvips-darwin-x64': 1.2.0 3482 - '@img/sharp-libvips-linux-arm': 1.2.0 3483 - '@img/sharp-libvips-linux-arm64': 1.2.0 3484 - '@img/sharp-libvips-linux-ppc64': 1.2.0 3485 - '@img/sharp-libvips-linux-s390x': 1.2.0 3486 - '@img/sharp-libvips-linux-x64': 1.2.0 3487 - '@img/sharp-libvips-linuxmusl-arm64': 1.2.0 3488 - '@img/sharp-libvips-linuxmusl-x64': 1.2.0 3489 - '@img/sharp-linux-arm': 0.34.3 3490 - '@img/sharp-linux-arm64': 0.34.3 3491 - '@img/sharp-linux-ppc64': 0.34.3 3492 - '@img/sharp-linux-s390x': 0.34.3 3493 - '@img/sharp-linux-x64': 0.34.3 3494 - '@img/sharp-linuxmusl-arm64': 0.34.3 3495 - '@img/sharp-linuxmusl-x64': 0.34.3 3496 - '@img/sharp-wasm32': 0.34.3 3497 - '@img/sharp-win32-arm64': 0.34.3 3498 - '@img/sharp-win32-ia32': 0.34.3 3499 - '@img/sharp-win32-x64': 0.34.3 3500 - 3501 3060 shiki@3.8.1: 3502 3061 dependencies: 3503 3062 '@shikijs/core': 3.8.1 ··· 3512 3071 simple-swizzle@0.2.2: 3513 3072 dependencies: 3514 3073 is-arrayish: 0.3.2 3074 + optional: true 3515 3075 3516 3076 sisteransi@1.0.5: {} 3517 3077 3518 - sitemap@8.0.0: 3519 - dependencies: 3520 - '@types/node': 17.0.45 3521 - '@types/sax': 1.2.7 3522 - arg: 5.0.2 3523 - sax: 1.4.1 3524 - 3525 3078 smol-toml@1.4.1: {} 3526 3079 3527 3080 source-map-js@1.2.1: {} ··· 3531 3084 statuses@2.0.1: {} 3532 3085 3533 3086 statuses@2.0.2: {} 3534 - 3535 - stream-replace-string@2.0.0: {} 3536 3087 3537 3088 string-width@4.2.3: 3538 3089 dependencies: ··· 3558 3109 strip-ansi@7.1.0: 3559 3110 dependencies: 3560 3111 ansi-regex: 6.1.0 3561 - 3562 - strnum@2.1.1: {} 3563 3112 3564 3113 suf-log@2.5.3: 3565 3114 dependencies:
+6
public/favicon.svg
··· 1 + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 128 128"> 2 + <path 3 + d="M50.4 78.5a75.1 75.1 0 0 0-28.5 6.9l24.2-65.7c.7-2 1.9-3.2 3.4-3.2h29c1.5 0 2.7 1.2 3.4 3.2l24.2 65.7s-11.6-7-28.5-7L67 45.5c-.4-1.7-1.6-2.8-2.9-2.8-1.3 0-2.5 1.1-2.9 2.7L50.4 78.5Zm-1.1 28.2Zm-4.2-20.2c-2 6.6-.6 15.8 4.2 20.2a17.5 17.5 0 0 1 .2-.7 5.5 5.5 0 0 1 5.7-4.5c2.8.1 4.3 1.5 4.7 4.7.2 1.1.2 2.3.2 3.5v.4c0 2.7.7 5.2 2.2 7.4a13 13 0 0 0 5.7 4.9v-.3l-.2-.3c-1.8-5.6-.5-9.5 4.4-12.8l1.5-1a73 73 0 0 0 3.2-2.2 16 16 0 0 0 6.8-11.4c.3-2 .1-4-.6-6l-.8.6-1.6 1a37 37 0 0 1-22.4 2.7c-5-.7-9.7-2-13.2-6.2Z" 4 + fill="#f00" 5 + /> 6 + </svg>
src/assets/blockquote.png

This is a binary file and will not be displayed.

src/assets/box-4x3-mask.png

This is a binary file and will not be displayed.

src/assets/box-circle-mask.png

This is a binary file and will not be displayed.

src/assets/box-lr.png

This is a binary file and will not be displayed.

src/assets/box-rounded-top.png

This is a binary file and will not be displayed.

src/assets/box-tb.png

This is a binary file and will not be displayed.

src/assets/circle.png

This is a binary file and will not be displayed.

src/assets/hr.png

This is a binary file and will not be displayed.

+3 -9
src/assets/icons/Bluesky.svg
··· 6 6 height="24" 7 7 fill="none" 8 8 stroke="currentColor" 9 - stroke-width="2" 9 + stroke-width="1" 10 10 stroke-linecap="round" 11 11 stroke-linejoin="round" 12 12 > 13 - <title></title> 13 + <title>Bluesky</title> 14 14 <path 15 - d="M 12,10.899575 16 - C 11.003583,8.9617423 8.2911667,5.3509923 5.7685,3.5708256 3.3521667,1.8649089 2.4309167,2.1600756 1.8268333,2.4341589 1.1274167,2.7485756 1,3.8229089 1,4.4535756 17 - c 0,0.6325 0.3465,5.1791667 0.572,5.9390834 0.7470833,2.508 3.4035833,3.355 5.8510833,3.083666 0.1246667,-0.01833 0.2520834,-0.03575 0.3804167,-0.05133 -0.1265,0.02017 -0.253,0.03667 -0.3804167,0.05133 -3.586,0.531667 -6.77141663,1.837917 -2.5941666,6.488167 4.59525,4.7575 6.2975003,-1.02025 7.1710833,-3.949 0.873583,2.92875 1.879167,8.498417 7.088583,3.949 3.911417,-3.949 1.074334,-5.9565 -2.511666,-6.488167 18 - A 8.0125833,8.0125833 0 0 1 16.1965,13.424992 19 - c 0.128333,0.01558 0.25575,0.033 0.380417,0.05133 2.4475,0.27225 5.104,-0.575666 5.851083,-3.083666 20 - C 22.6535,9.6336589 23,5.0851589 23,4.4544923 23,3.8219923 22.872583,2.7485756 22.173167,2.4323256 21.569083,2.1591589 20.647833,1.8639922 18.2315,3.5689923 15.708833,5.3519089 12.996417,8.9626589 12,10.899575 21 - Z" 15 + d="M12 10.8c-1.087-2.114-4.046-6.053-6.798-7.995C2.566.944 1.561 1.266.902 1.565.139 1.908 0 3.08 0 3.768c0 .69.378 5.65.624 6.479.815 2.736 3.713 3.66 6.383 3.364.136-.02.275-.039.415-.056-.138.022-.276.04-.415.056-3.912.58-7.387 2.005-2.83 7.078 5.013 5.19 6.87-1.113 7.823-4.308.953 3.195 2.05 9.271 7.733 4.308 4.267-4.308 1.172-6.498-2.74-7.078a8.741 8.741 0 0 1-.415-.056c.14.017.279.036.415.056 2.67.297 5.568-.628 6.383-3.364.246-.828.624-5.79.624-6.478 0-.69-.139-1.861-.902-2.206-.659-.298-1.664-.62-4.3 1.24C16.046 4.748 13.087 8.687 12 10.8Z" 22 16 /> 23 17 </svg>
+4 -25
src/assets/icons/Git.svg
··· 6 6 height="24" 7 7 fill="none" 8 8 stroke="currentColor" 9 - stroke-width="2" 9 + stroke-width="1" 10 10 stroke-linecap="round" 11 11 stroke-linejoin="round" 12 12 > 13 - <title></title> 13 + <title>Git</title> 14 14 <path 15 - d="m 13.028802,1.3895454 9.581951,9.5816836 16 - c 0.569955,0.569938 0.569955,1.487603 0,2.057543 17 - L 13.0288,22.610454 18 - c -0.569954,0.56994 -1.487647,0.56994 -2.0576,0 19 - L 1.3892477,13.028771 20 - c -0.56995568,-0.56994 -0.56995568,-1.487605 0,-2.057543 21 - L 10.9712,1.3895454 22 - c 0.569953,-0.56993957 1.487646,-0.56993954 2.057602,0 23 - z" 24 - ></path> 25 - <path 26 - d="m 8.4658392,3.9500992 27 - c 1.026761,1.0352655 1.8785438,1.8251323 2.9091608,2.8565414 -0.208863,0.1861442 -0.328257,0.4526483 -0.328125,0.7324219 0,0.541498 0.438971,0.9804688 0.980469,0.9804687 0.01042,1.66e-4 0.02083,1.66e-4 0.03125,0 28 - l 0.03516,7.2109378 -0.0332,-7.2109378 29 - c 0.268151,-0.0091 0.520859,-0.1276865 0.699219,-0.328125 1.07369,1.0722953 2.148025,2.1434858 3.222656,3.2148438 -0.203224,0.186072 -0.318773,0.449069 -0.31836,0.724609 0,0.541498 0.438971,0.980469 0.980469,0.980469 0.541498,0 0.980469,-0.438971 0.980469,-0.980469 0,-0.541498 -0.438971,-0.980468 -0.980469,-0.980468 -0.243978,-4.49e-4 -0.479359,0.09008 -0.660156,0.253906 30 - l -3.21875,-3.2187501 31 - c 0.156434,-0.1790076 0.242503,-0.4087548 0.242187,-0.6464844 0,-0.5414976 -0.43897,-0.9804683 -0.980468,-0.9804687 -0.237057,1.572e-4 -0.466031,0.086195 -0.644532,0.2421874 32 - z 33 - 34 - M 12.09375,15.730469 35 - c -0.01886,-0.0012 -0.03775,-0.0018 -0.05664,-0.002 -0.541497,0 -0.980468,0.438971 -0.980468,0.980468 0,0.541498 0.43897,0.980469 0.980468,0.980469 0.541498,0 0.980469,-0.438971 0.980469,-0.980469 -1.68e-4,-0.519374 -0.405321,-0.948511 -0.923828,-0.978515 36 - z" 37 - ></path> 15 + d="M23.546 10.93L13.067.452c-.604-.603-1.582-.603-2.188 0L8.708 2.627l2.76 2.76c.645-.215 1.379-.07 1.889.441.516.515.658 1.258.438 1.9l2.658 2.66c.645-.223 1.387-.078 1.9.435.721.72.721 1.884 0 2.604-.719.719-1.881.719-2.6 0-.539-.541-.674-1.337-.404-1.996L12.86 8.955v6.525c.176.086.342.203.488.348.713.721.713 1.883 0 2.6-.719.721-1.889.721-2.609 0-.719-.719-.719-1.879 0-2.598.182-.18.387-.316.605-.406V8.835c-.217-.091-.424-.222-.6-.401-.545-.545-.676-1.342-.396-2.009L7.636 3.7.45 10.881c-.6.605-.6 1.584 0 2.189l10.48 10.477c.604.604 1.582.604 2.186 0l10.43-10.43c.605-.603.605-1.582 0-2.187" 16 + /> 38 17 </svg>
+4 -45
src/assets/icons/GitHub.svg
··· 6 6 height="24" 7 7 fill="none" 8 8 stroke="currentColor" 9 - stroke-width="2" 9 + stroke-width="1" 10 10 stroke-linecap="round" 11 11 stroke-linejoin="round" 12 12 > 13 - <title></title> 13 + <title>GitHub</title> 14 14 <path 15 - d="M 5.8769531 4.2480469 16 - C 5.746875 4.2539869 5.6835936 4.2734375 5.6835938 4.2734375 17 - C 5.0385937 5.9264375 5.443125 7.1462186 5.578125 7.4492188 18 - C 4.808125 8.2892185 4.34375 9.3599216 4.34375 10.669922 19 - C 4.34375 15.267922 7.1455469 16.299609 9.8105469 16.599609 20 - C 9.4675469 16.899609 9.0593119 17.481835 9.0097656 18.802734 21 - C 8.9602196 20.123633 9.0229586 21.587198 9.0253906 21.945312 22 - C 9.0244037 21.963603 9.0234375 21.98145 9.0234375 22 23 - C 9.0234375 22.0087 9.0251806 22.016781 9.0253906 22.025391 24 - C 9.0390439 22.567316 9.4781028 23 10.023438 23 25 - L 13.941406 23 26 - C 14.48674 23 14.9258 22.567318 14.939453 22.025391 27 - C 14.93967 22.016791 14.941406 22.00867 14.941406 22 28 - C 14.941406 21.98036 14.940606 21.960756 14.939453 21.941406 29 - C 14.941753 21.428312 14.953125 20.246397 14.953125 18.810547 30 - C 14.953125 17.686547 14.564531 16.949844 14.144531 16.589844 31 - C 16.814531 16.294844 19.619141 15.279922 19.619141 10.669922 32 - C 19.619141 9.3599216 19.153672 8.2892186 18.388672 7.4492188 33 - C 18.508672 7.1462186 18.914531 5.9264375 18.269531 4.2734375 34 - C 18.269531 4.2734375 17.264375 3.9519064 14.984375 5.5039062 35 - C 14.024375 5.2369062 13.004375 5.1056094 11.984375 5.0996094 36 - C 10.964375 5.1056094 9.944375 5.2369064 8.984375 5.5039062 37 - C 7.263127 4.3399014 6.2671875 4.2302344 5.8769531 4.2480469 38 - z 39 - 40 - M 3.4179688 16.230469 41 - C 3.4179687 16.230469 4.8933619 17.08105 5.1425781 17.517578 42 - C 5.1416718 17.515904 5.1415245 17.513381 5.140625 17.511719 43 - C 4.9086875 17.083094 3.4179688 16.230469 3.4179688 16.230469 44 - z 45 - 46 - M 5.3261719 17.839844 47 - C 5.6927844 18.468641 6.0093194 18.905008 6.7558594 19.234375 48 - C 6.0448766 18.893281 5.5989558 18.29342 5.3261719 17.839844 49 - z 50 - 51 - M 6.7558594 19.234375 52 - C 6.8276855 19.268834 6.9011563 19.301312 6.9785156 19.330078 53 - C 7.9110688 19.676849 8.7204476 19.140683 8.9101562 19 54 - C 8.719366 19.137703 7.9001297 19.667221 6.9824219 19.326172 55 - C 6.9026923 19.296542 6.8272738 19.265882 6.7558594 19.234375 56 - z" 57 - ></path> 15 + d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" 16 + /> 58 17 </svg>
+17
src/assets/icons/Tumblr.svg
··· 1 + <svg 2 + role="img" 3 + viewBox="0 0 24 24" 4 + xmlns="http://www.w3.org/2000/svg" 5 + width="24" 6 + height="24" 7 + fill="none" 8 + stroke="currentColor" 9 + stroke-width="1" 10 + stroke-linecap="round" 11 + stroke-linejoin="round" 12 + > 13 + <title>Tumblr</title> 14 + <path 15 + d="M14.563 24c-5.093 0-7.031-3.756-7.031-6.411V9.747H5.116V6.648c3.63-1.313 4.512-4.596 4.71-6.469C9.84.051 9.941 0 9.999 0h3.517v6.114h4.801v3.633h-4.82v7.47c.016 1.001.375 2.371 2.207 2.371h.09c.631-.02 1.486-.205 1.936-.419l1.156 3.425c-.436.636-2.4 1.374-4.156 1.404h-.178l.011.002z" 16 + /> 17 + </svg>
src/assets/line.png

This is a binary file and will not be displayed.

src/assets/popout-speech.png

This is a binary file and will not be displayed.

src/assets/right-arrow-2x-outline.png

This is a binary file and will not be displayed.

src/assets/small-box-mask-1-0.png

This is a binary file and will not be displayed.

src/assets/small-box-mask-1-180.png

This is a binary file and will not be displayed.

src/assets/small-box-mask-1-270.png

This is a binary file and will not be displayed.

src/assets/small-box-mask-1-90.png

This is a binary file and will not be displayed.

src/assets/small-box-mask-2-0.png

This is a binary file and will not be displayed.

src/assets/small-box-mask-2-180.png

This is a binary file and will not be displayed.

src/assets/small-box-mask-2-270.png

This is a binary file and will not be displayed.

src/assets/small-box-mask-2-90.png

This is a binary file and will not be displayed.

src/assets/small-box-mask-3-0.png

This is a binary file and will not be displayed.

src/assets/small-box-mask-3-180.png

This is a binary file and will not be displayed.

src/assets/small-box-mask-3-270.png

This is a binary file and will not be displayed.

src/assets/small-box-mask-3-90.png

This is a binary file and will not be displayed.

src/assets/small-box-mask.png

This is a binary file and will not be displayed.

src/assets/vr.png

This is a binary file and will not be displayed.

src/assets/white-gradient.png

This is a binary file and will not be displayed.

+3 -46
src/components/Base.astro
··· 3 3 4 4 interface Props { 5 5 title?: string; 6 - graph?: { 7 - description: string; 8 - url: string; 9 - type?: "website" | "article" | `${"music" | "video"}.${string}`; 10 - image?: string; 11 - }; 12 6 } 13 - 14 - const { graph } = Astro.props; 15 - const title = Astro.props.title 16 - ? `${Astro.props.title} | vielle.dev` 17 - : "vielle.dev"; 18 7 --- 19 8 20 9 <html lang="en"> 21 10 <head> 22 11 <meta charset="utf-8" /> 12 + <link rel="icon" type="image/svg+xml" href="/favicon.svg" /> 23 13 <meta name="viewport" content="width=device-width" /> 24 - <link rel="sitemap" href="/sitemap-index.xml" /> 25 - <link 26 - rel="alternate" 27 - type="application/rss+xml" 28 - title="vielle.dev" 29 - href={new URL("rss", Astro.site)} 30 - /> 31 - <link 32 - rel="icon" 33 - href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>๐Ÿชค</text></svg>" 34 - /> 35 - 14 + <meta name="generator" content={Astro.generator} /> 36 15 <title> 37 - {title} 16 + {Astro.props.title ? `${Astro.props.title} | vielle.dev` : "vielle.dev"} 38 17 </title> 39 - <meta name="generator" content={Astro.generator} /> 40 - { 41 - graph && ( 42 - <Fragment> 43 - <meta name="description" content={graph.description} /> 44 - 45 - {/* opengraph */} 46 - <meta property="og:url" content={graph.url.toString()} /> 47 - <meta property="og:type" content={graph.type ?? "website"} /> 48 - <meta property="og:title" content={title} /> 49 - <meta property="og:description" content={graph.description} /> 50 - {graph.image && <meta property="og:image" content={graph.image} />} 51 - 52 - {/* twt card markup */} 53 - <meta name="twitter:card" content="summary_large_image" /> 54 - <meta name="twitter:title" content={title} /> 55 - <meta name="twitter:description" content={graph.description} /> 56 - {graph.image && <meta name="twitter:image" content={graph.image} />} 57 - </Fragment> 58 - ) 59 - } 60 18 61 19 <style is:global> 62 20 @layer reset { 63 21 :root { 64 22 font-family: sans-serif; 65 23 interpolate-size: allow-keywords; 66 - image-rendering: pixelated; 67 24 } 68 25 69 26 * {
+11 -35
src/components/Header.astro
··· 66 66 </header> 67 67 68 68 <style> 69 - /* UPDATE RSS STYLE XML WHEN YOU CHANGE THESE */ 70 69 header { 70 + image-rendering: pixelated; 71 71 border-image: var(--box-blr-png) 10 fill / 20px / 20px round; 72 72 margin: 0 20px 20px; 73 73 padding: 10px 20px; 74 - height: 3rem; /* 2rem * 1.5 */ 75 - /* render over feed bg */ 76 - z-index: 2; 74 + overflow: auto; 77 75 78 76 display: flex; 79 77 flex-direction: row; 80 78 justify-content: space-between; 81 79 align-items: center; 82 80 83 - @media (max-width: 650px) { 81 + @media (max-width: 600px) { 84 82 flex-direction: column; 85 83 align-items: start; 86 - height: 4.5rem; /* (2rem + 1rem) * 1.5 */ 87 - 88 - nav { 84 + nav, 85 + h1 { 89 86 margin-inline: auto; 90 - contain: inline-size; 91 - width: 100%; 92 - overflow: auto; 93 - scrollbar-width: thin; 94 - } 95 - 96 - h1 { 97 - width: 100%; 98 - text-align: center; 99 87 } 100 88 } 101 89 ··· 104 92 flex-direction: row; 105 93 align-items: center; 106 94 justify-content: start; 95 + max-width: 100%; 107 96 gap: 10px; 108 - z-index: 999; 109 - width: fit-content; 110 - margin-inline: auto; 111 97 112 98 & > li { 113 99 display: flex; ··· 121 107 122 108 & + &::before { 123 109 content: ""; 110 + image-rendering: pixelated; 124 111 background-image: var(--dot-png); 125 112 background-size: contain; 126 113 width: 9px; ··· 136 123 } 137 124 138 125 details { 139 - summary { 140 - cursor: pointer; 141 - text-wrap: nowrap; 142 - } 143 - 144 - & > ul { 126 + > ul { 145 127 position: absolute; 146 128 z-index: 99999; 147 129 148 - @media (max-width: 650px) { 149 - inset: auto 15px; 150 - } 151 - 152 130 margin-top: 10px; 153 131 padding: 20px; 154 - padding-left: 40px; 132 + border-image: var(--box-tlbr-png) 10 fill / 20px round; 133 + 134 + padding-left: 30px; 155 135 & ul { 156 136 margin-left: 10px; 157 137 } 158 - 159 - border-image: var(--box-tlbr-png) 10 fill / 20px round; 160 138 } 161 139 } 162 140 163 141 h1 { 164 142 margin-block: 0; 165 - position: sticky; 166 - inset: 0; 167 143 } 168 144 </style>
-71
src/components/Markdown.astro
··· 1 - --- 2 - import Base from "./Base.astro"; 3 - 4 - import Box4x3Mask from "/assets/box-4x3-mask.png"; 5 - import Hr from "/assets/hr.png"; 6 - 7 - import "/components/markdown.css"; 8 - 9 - interface Props { 10 - frontmatter: { 11 - title: string; 12 - graph?: { 13 - description: string; 14 - type?: "website" | "article" | `${"music" | "video"}.${string}`; 15 - image?: string; 16 - }; 17 - }; 18 - } 19 - 20 - const { frontmatter } = Astro.props; 21 - --- 22 - 23 - <Base 24 - title={frontmatter.title} 25 - graph={{ 26 - description: "", 27 - ...frontmatter.graph, 28 - url: Astro.url.toString(), 29 - }} 30 - > 31 - <header style={`--box-4x3-mask-png: url(${Box4x3Mask.src});`}> 32 - {frontmatter.graph?.image && <img src={frontmatter.graph.image} alt="" />} 33 - <h1>{frontmatter.title}</h1> 34 - </header> 35 - 36 - <hr style={`--hr-png: url(${Hr.src});`} /> 37 - 38 - <article class="markdown-style"> 39 - <slot /> 40 - </article> 41 - </Base> 42 - 43 - <style> 44 - header { 45 - max-width: 60ch; 46 - padding: 10px; 47 - margin: auto; 48 - } 49 - 50 - img { 51 - width: 100%; 52 - aspect-ratio: 4/3; 53 - object-fit: cover; 54 - mask-image: var(--box-4x3-mask-png); 55 - mask-size: 100%; 56 - } 57 - 58 - hr { 59 - margin-block: 5px; 60 - height: 5px; 61 - border: none; 62 - border-image: var(--hr-png) 0 5 fill / 0 5px round; 63 - width: clamp(60ch, 80vw, 80ch); 64 - margin-inline: auto; 65 - 66 - @media (max-width: 60ch) { 67 - width: calc(100% - 20px); 68 - margin-inline: 10px; 69 - } 70 - } 71 - </style>
-98
src/components/home/Blog.astro
··· 1 - --- 2 - import { getCollection } from "astro:content"; 3 - 4 - import BoxTlbr from "/assets/box-tlbr.png"; 5 - import Hr from "/assets/hr.png"; 6 - import Box4x3Mask from "/assets/box-4x3-mask.png"; 7 - 8 - const posts = await getCollection("blog").then((x) => 9 - x.sort( 10 - (a, b) => 11 - // cast needed as you can subtract Date but ts doesnt like it 12 - (b.data.pub as unknown as number) - (a.data.pub as unknown as number), 13 - ), 14 - ); 15 - 16 - interface Props { 17 - heading?: string; 18 - } 19 - 20 - const HeadingLevel = Astro.props.heading ?? "h2"; 21 - --- 22 - 23 - <section 24 - class="blog" 25 - style={` 26 - --box-tlbr-png: url(${BoxTlbr.src}); 27 - --hr-png: url(${Hr.src}); 28 - --box-4x3-mask-png: url(${Box4x3Mask.src}) 29 - `} 30 - > 31 - <HeadingLevel>Blog Posts</HeadingLevel> 32 - { 33 - posts.map((post) => ( 34 - <article class="post"> 35 - <a href={`/blog/${post.id}`}> 36 - {import( 37 - `../../content/blog/assets/${post.data.banner.replace(".png", "")}.png` 38 - ).then(({ default: img }) => ( 39 - <img src={img.src} alt="" /> 40 - ))} 41 - <hr /> 42 - <h3 class="title">{post.data.title}</h3> 43 - <div class="bio">{post.data.bio}</div> 44 - <time 45 - datetime={`${post.data.pub.getFullYear()}-${post.data.pub.getMonth()}-${post.data.pub.getDate()}`} 46 - class="pub" 47 - > 48 - {post.data.pub.getDate()}-{post.data.pub.getMonth()}- 49 - {post.data.pub.getFullYear()} 50 - </time> 51 - </a> 52 - </article> 53 - )) 54 - } 55 - </section> 56 - 57 - <style> 58 - .blog { 59 - contain: size; 60 - height: 100%; 61 - overflow-y: auto; 62 - } 63 - 64 - .post { 65 - border-image: var(--box-tlbr-png) 10 10 fill / 20px 20px round; 66 - padding: 30px; 67 - } 68 - 69 - img { 70 - width: 100%; 71 - aspect-ratio: 4/3; 72 - object-fit: cover; 73 - mask-image: var(--box-4x3-mask-png); 74 - mask-size: 100%; 75 - } 76 - 77 - a { 78 - color: black; 79 - text-decoration-line: none; 80 - 81 - &:hover, 82 - &:focus, 83 - &:active { 84 - text-decoration-line: underline; 85 - } 86 - 87 - &:active { 88 - text-decoration-style: dashed; 89 - } 90 - } 91 - 92 - hr { 93 - margin-block: 5px; 94 - height: 5px; 95 - border: none; 96 - border-image: var(--hr-png) 0 5 fill / 0 5px round; 97 - } 98 - </style>
+33 -80
src/components/home/Landing.astro
··· 1 1 --- 2 2 import { socials } from "/site-config"; 3 3 4 - import Circle from "/assets/circle.png"; 5 - import line from "/assets/line.png"; 4 + import boxRoundedTop from "/assets/box-rounded-top.png"; 5 + import boxCircleMask from "/assets/box-circle-mask.png"; 6 6 7 7 const avatar = await fetch( 8 8 "https://api.bsky.app/xrpc/app.bsky.actor.getProfile?actor=" + 9 - socials.atproto.did, 9 + socials.atproto, 10 10 ) 11 11 .then((x) => { 12 12 if (!x.ok) { ··· 17 17 .then((x) => x.json()) 18 18 .then((x) => x.avatar) 19 19 .catch((e) => { 20 - console.error("Got bsky pfp error", e); 20 + console.error("Got error", e); 21 21 return undefined; 22 22 }); 23 23 --- 24 24 25 - <article 26 - class="landing" 27 - style={`--line-png: url("${line.src}"); 28 - --circle-png: url("${Circle.src}");`} 29 - > 25 + <section class="landing"> 30 26 <h2>Hello World ๐Ÿณ๏ธโ€โšง๏ธ</h2> 31 - <p class="no-anchor-warning"> 32 - โš ๏ธ Your browser doesnt support anchor positioning or javascript! 33 - </p> 34 - { 35 - avatar && ( 36 - <div class="avatar"> 37 - <img src={avatar} alt="" /> 38 - </div> 39 - ) 40 - } 27 + <figure style={`--box-rounded-top-png: url("${boxRoundedTop.src}")`}> 28 + <img 29 + src={avatar ?? "http://undefined"} 30 + alt="" 31 + style={`--box-circle-mask-png: url("${boxCircleMask.src}")`} 32 + /> 33 + <figcaption>bsky pfp</figcaption> 34 + </figure> 41 35 <p> 42 - <!-- todo update this content --> 43 - Hi! I'm Kai<wbr />/<wbr />Nico<wbr />/<wbr />Alex<wbr />/<wbr />Jen [she<wbr 44 - />/<wbr />it] (non binary) and I make silly websites! I'm a big fan of 45 - progressive enhancement, open source, and linux. (I use arch btw) 36 + Hi! I'm Kai/Nico/Alex/Jen [she/it] (non binary) and I make silly websites! 37 + I'm a big fan of progressive enhancement, open source, and linux. (I use 38 + arch btw) 46 39 </p> 47 40 <p> 48 41 My preferred tools are vanilla html/css, typescript, vite, astro, svelte, 49 42 deno, and rust! 50 43 </p> 51 - </article> 44 + </section> 52 45 53 46 <style> 54 - article { 47 + section { 55 48 padding: 10px; 56 49 height: fit-content; 57 - z-index: 1; 58 - 59 - /* desktop border image */ 60 - @media not (max-width: 110ch) { 61 - position: relative; 62 - z-index: 0; 63 - &::before { 64 - content: ""; 65 - display: block; 66 - background-image: var(--line-png); 67 - background-size: 60px; 68 - z-index: -1; 69 - width: 50vw; 70 - height: 20px; 71 - position: absolute; 72 - bottom: -20px; 73 - right: -50px; 74 - } 75 - } 76 50 } 77 51 78 - .avatar { 52 + figure { 79 53 float: right; 80 54 box-sizing: border-box; 81 55 width: 120px; 82 - height: 120px; 83 - margin: 20px; 56 + height: 180px; 57 + margin: 0 0 10px 10px; 84 58 85 - --outline-size: 10px; 86 - 87 - filter: drop-shadow(var(--outline-size) 0 black) 88 - drop-shadow(calc(-1 * var(--outline-size)) 0 black) 89 - drop-shadow(0 var(--outline-size) black) 90 - drop-shadow(0 calc(-1 * var(--outline-size)) black); 59 + image-rendering: pixelated; 60 + background-image: var(--box-rounded-top-png); 61 + background-repeat: no-repeat; 62 + background-size: 100% 100%; 91 63 92 64 img { 93 - width: 100%; 94 65 aspect-ratio: 1; 66 + width: 100%; 95 67 background-color: #008282; 96 - mask-image: var(--circle-png); 68 + mask-image: var(--box-circle-mask-png); 97 69 mask-size: 120px 120px; 98 70 } 99 - } 100 71 101 - p { 102 - margin-block: 5px; 103 - } 104 - 105 - @keyframes fade-in { 106 - from, 107 - to { 108 - height: auto; 109 - } 110 - 111 - to { 112 - opacity: 1; 72 + figcaption { 73 + margin: auto; 74 + width: fit-content; 75 + margin-block: 10px; 113 76 } 114 77 } 115 78 116 - .no-anchor-warning { 117 - @supports (top: calc(anchor(--player bottom) + 10px)) { 118 - display: none; 119 - } 120 - 121 - background: rgb(from goldenrod r g b / 0.2); 122 - margin: 0; 123 - padding: 0; 124 - 125 - opacity: 0; 126 - height: 0; 127 - animation: 0s ease-in-out 2s 1 forwards fade-in; 79 + p { 80 + margin-block: 5px; 128 81 } 129 82 </style>
+118
src/components/home/feeds/Bluesky.astro
··· 1 + --- 2 + 3 + --- 4 + 5 + <h1>Bsky</h1> 6 + 7 + Lorem,<br /> 8 + ipsum<br /> 9 + dolor<br /> 10 + sit<br /> 11 + amet<br /> 12 + consectetur<br /> 13 + adipisicing<br /> 14 + elit.<br /> 15 + Reiciendis,<br /> 16 + rem aspernatur?<br /> 17 + Voluptas<br /> 18 + assumenda<br /> 19 + et<br /> 20 + sapiente<br /> 21 + voluptates<br /> 22 + cumque<br /> 23 + facere<br /> 24 + suscipit quis<br /> 25 + labore<br /> 26 + aspernatur<br /> 27 + nostrum<br /> 28 + recusandae,<br /> 29 + quos<br /> 30 + adipisci<br /> 31 + dicta,<br /> 32 + consectetur illum.<br /> 33 + Dignissimos.<br /> 34 + Cupiditate<br /> 35 + natus<br /> 36 + eos,<br /> 37 + dolor<br /> 38 + vel<br /> 39 + aliquid<br /> 40 + distinctio<br /> 41 + eius<br /> 42 + quos enim<br /> 43 + tempora<br /> 44 + molestiae<br /> 45 + amet.<br /> 46 + Non<br /> 47 + id<br /> 48 + ab<br /> 49 + velit<br /> 50 + minima.<br /> 51 + Necessitatibus<br /> 52 + perferendis temporibus<br /> 53 + tempore<br /> 54 + ratione<br /> 55 + dicta<br /> 56 + voluptatibus<br /> 57 + quas<br /> 58 + et<br /> 59 + sapiente<br /> 60 + doloremque<br /> 61 + natus! Pariatur<br /> 62 + harum,<br /> 63 + perspiciatis<br /> 64 + iure<br /> 65 + quod<br /> 66 + ratione<br /> 67 + et<br /> 68 + est<br /> 69 + illo<br /> 70 + iste<br /> 71 + vero<br /> 72 + eligendi, accusantium<br /> 73 + inventore<br /> 74 + tempore.<br /> 75 + Illum,<br /> 76 + et!<br /> 77 + Voluptatem,<br /> 78 + beatae<br /> 79 + dolores.<br /> 80 + Rerum itaque,<br /> 81 + provident<br /> 82 + ad<br /> 83 + impedit<br /> 84 + voluptatum<br /> 85 + optio<br /> 86 + in<br /> 87 + eos<br /> 88 + suscipit!<br /> 89 + Porro<br /> 90 + repellendus blanditiis<br /> 91 + atque<br /> 92 + labore<br /> 93 + eveniet<br /> 94 + nemo<br /> 95 + voluptas<br /> 96 + possimus<br /> 97 + neque.<br /> 98 + Velit<br /> 99 + voluptatum animi<br /> 100 + magni<br /> 101 + nulla<br /> 102 + eaque<br /> 103 + voluptate<br /> 104 + recusandae<br /> 105 + earum<br /> 106 + accusantium<br /> 107 + nemo,<br /> 108 + vel necessitatibus<br /> 109 + neque<br /> 110 + nam<br /> 111 + libero,<br /> 112 + nesciunt<br /> 113 + odio<br /> 114 + minima<br /> 115 + tempore!<br /> 116 + Repellat<br /> 117 + eveniet ipsum<br /> 118 + sequi<br />
-105
src/components/home/feeds/Feed.astro
··· 1 - --- 2 - import boxLR from "/assets/box-lr.png"; 3 - import { socials } from "/site-config"; 4 - import { is, type ResourceUri } from "@atcute/lexicons"; 5 - import { AppBskyFeedPost } from "@atcute/bluesky"; 6 - import Post from "./Post.astro"; 7 - import type { Author } from "./post-types"; 8 - import { client } from "./atproto"; 9 - 10 - const { ok, data } = await client.get("app.bsky.feed.getAuthorFeed", { 11 - params: { 12 - actor: socials.atproto.did, 13 - limit: 100, 14 - filter: "posts_no_replies" 15 - }, 16 - }); 17 - 18 - if (!ok) { 19 - // error occoured 20 - console.error(data.error, data.message); 21 - 22 - return "Error 500: Internal server error fetching this feed. Try refreshing the page"; 23 - } 24 - 25 - let posts: { 26 - record: AppBskyFeedPost.Main; 27 - author: Author; 28 - uri: ResourceUri; 29 - }[] = data.feed 30 - // make sure it was by me (exclude reposts) 31 - .filter((x) => x.post.author.did === socials.atproto.did) 32 - // makes sure its not a reply 33 - .filter((x) => !x.reply) 34 - // this list now includes original posts & quote skeets 35 - .map((x) => { 36 - return { 37 - record: is(AppBskyFeedPost.mainSchema, x.post.record) 38 - ? x.post.record 39 - : // never type bc it gets filtered out 40 - (undefined as never), 41 - author: { 42 - did: x.post.author.did, 43 - displayName: x.post.author.displayName, 44 - handle: x.post.author.handle, 45 - avatar: x.post.author.avatar, 46 - }, 47 - uri: x.post.uri, 48 - }; 49 - }) 50 - .filter((x) => x.record); 51 - --- 52 - 53 - <section class="feed" style={`--box-lr-png: url("${boxLR.src}");`}> 54 - <div class="feed-contents"> 55 - <h2>Bluesky ๐Ÿฆ‹</h2> 56 - <ul> 57 - { 58 - posts.map((x) => { 59 - const uriFragments = x.uri.match( 60 - new RegExp( 61 - "at:\/\/(?<did>did:(?:plc|web):[^\/]*)\/(?<nsid>[^\/]*)\/(?<rkey>.*)", 62 - ), 63 - ); 64 - let rkey: string = uriFragments?.groups?.rkey ?? ""; 65 - return ( 66 - <li> 67 - <Post post={x.record} author={x.author} {rkey} /> 68 - </li> 69 - ); 70 - }) 71 - } 72 - </ul> 73 - </div> 74 - </section> 75 - 76 - <style> 77 - /* wrapper */ 78 - .feed { 79 - contain: size; 80 - height: 100%; 81 - 82 - @media (max-width: 110ch) { 83 - height: auto; 84 - } 85 - 86 - z-index: 0; 87 - 88 - border-image: var(--box-lr-png) 0 10 fill / 0 20px / 10000px 20px round; 89 - } 90 - 91 - /* tab contents */ 92 - .feed-contents { 93 - grid-area: contents; 94 - overflow-y: auto; 95 - height: 100%; 96 - 97 - @media (max-width: 110ch) { 98 - height: auto; 99 - } 100 - } 101 - 102 - ul { 103 - list-style: none; 104 - } 105 - </style>
+122
src/components/home/feeds/Feeds.astro
··· 1 + --- 2 + import Bluesky from "./Bluesky.astro"; 3 + import Tumblr from "./Tumblr.astro"; 4 + import Tangled from "./Tangled.astro"; 5 + import Github from "./Github.astro"; 6 + 7 + import IconBluesky from "/assets/icons/Bluesky.svg"; 8 + import IconTumblr from "/assets/icons/Tumblr.svg"; 9 + import IconGit from "/assets/icons/Git.svg"; 10 + import IconGithub from "/assets/icons/GitHub.svg"; 11 + 12 + const tabs: { 13 + id: string; 14 + label: string; 15 + icon?: ((_props: astroHTML.JSX.SVGAttributes) => any) | string; 16 + content: (_props: Record<string, any>) => any; 17 + }[] = [ 18 + { id: "bsky", label: "Bluesky", icon: IconBluesky, content: Bluesky }, 19 + { id: "tmlblr", label: "Tumblr", icon: IconTumblr, content: Tumblr }, 20 + { id: "tangled", label: "Tangled", icon: IconGit, content: Tangled }, 21 + { id: "gh", label: "Github", icon: IconGithub, content: Github }, 22 + ]; 23 + --- 24 + 25 + <section class="feeds"> 26 + <!-- tabindex -1 disables tabbing onto this element 27 + tabbing is disabled because when the element overflows its focusable 28 + to scrub across children etc. which is a logical default 29 + but in this case is annoying as scrubbing is already possible via the tabs 30 + --> 31 + <div id="tab-container" tabindex="-1"> 32 + { 33 + tabs.map((tab, i) => ( 34 + <label> 35 + <input 36 + type="radio" 37 + name="social-tab" 38 + data-tab-for={tab.id} 39 + checked={i === 0} 40 + /> 41 + {tab.icon && 42 + (typeof tab.icon === "string" ? ( 43 + <img src={tab.icon} alt="" /> 44 + ) : ( 45 + <tab.icon /> 46 + ))} 47 + <span class="label">{tab.label}</span> 48 + </label> 49 + )) 50 + } 51 + </div> 52 + 53 + <div id="tabs"> 54 + { 55 + tabs.map((tab) => ( 56 + <div class="tab" data-tab={tab.id} id={tab.id}> 57 + <tab.content /> 58 + </div> 59 + )) 60 + } 61 + </div> 62 + </section> 63 + 64 + <!-- god i want /ref/ combinators so fuckin bad 65 + this could be so clean 66 + `#tab-container :checked /data-tab-for/ .tab` --> 67 + <style 68 + set:html={tabs 69 + .map( 70 + ({ id }) => 71 + `#tab-container:has([data-tab-for="${id}"]:checked) ~ #tabs #${id} { display: var(--display, block); }`, 72 + ) 73 + .join("\n")} 74 + ></style> 75 + 76 + <style> 77 + .tab { 78 + display: none; 79 + } 80 + 81 + #tab-container { 82 + display: flex; 83 + flex-direction: row; 84 + gap: 10px; 85 + overflow-x: auto; 86 + scrollbar-width: none; 87 + 88 + label { 89 + display: grid; 90 + grid-template: "icon text" 1fr / auto auto; 91 + flex-direction: row; 92 + gap: 2.5px; 93 + margin: 2.5px; 94 + padding: 2.5px; 95 + 96 + &:has(:checked) { 97 + border-bottom: 5px solid blue; 98 + } 99 + 100 + &:focus-within { 101 + border: 1px solid red; 102 + } 103 + 104 + img, 105 + svg { 106 + width: 24px; 107 + height: 24px; 108 + grid-area: icon; 109 + } 110 + 111 + .label { 112 + grid-area: text; 113 + } 114 + 115 + input { 116 + /* visually hide it but dont remove from dom/accessibility tree for focus */ 117 + opacity: 0; 118 + grid-area: icon; 119 + } 120 + } 121 + } 122 + </style>
+5
src/components/home/feeds/Github.astro
··· 1 + --- 2 + 3 + --- 4 + 5 + <h3>gh</h3>
-329
src/components/home/feeds/Post.astro
··· 1 - --- 2 - import { docResolver } from "./atproto"; 3 - import { type Blob, type LegacyBlob } from "@atcute/lexicons"; 4 - import { AppBskyFeedPost } from "@atcute/bluesky"; 5 - import { segmentize } from "@atcute/bluesky-richtext-segmenter"; 6 - import { 7 - type Author, 8 - understoodDid, 9 - type embed, 10 - type embedImages, 11 - type embedVideo, 12 - type embedExternal, 13 - type embedRecord, 14 - type embedRecordWithMedia, 15 - } from "./post-types"; 16 - import { 17 - images, 18 - video, 19 - external, 20 - record, 21 - recordWithMedia, 22 - } from "./post-embeds"; 23 - 24 - import BoxTlbr from "/assets/box-tlbr.png"; 25 - import Hr from "/assets/hr.png"; 26 - 27 - interface Props { 28 - post: AppBskyFeedPost.Main; 29 - author: Author; 30 - nested?: boolean; 31 - rkey: string; 32 - } 33 - 34 - const { post, author, nested = false, rkey } = Astro.props; 35 - 36 - // resolve the pds. bit hacky but should work 37 - const pds = await docResolver 38 - .resolve(understoodDid(author.did) ? author.did : "did:plc:failure") 39 - .then( 40 - (pds) => 41 - pds.service && 42 - pds.service.filter( 43 - (service) => service.type === "AtprotoPersonalDataServer", 44 - )[0].serviceEndpoint + "", 45 - ); 46 - 47 - // helper functions 48 - const cidSrc = (blob: Blob | LegacyBlob, did: `did:${string}:${string}`) => 49 - new URL( 50 - "/xrpc/com.atproto.sync.getBlob/?" + 51 - new URLSearchParams({ 52 - did: did, 53 - cid: "cid" in blob ? blob.cid : blob.ref.$link, 54 - }).toString(), 55 - pds, 56 - ).toString(); 57 - 58 - const embed: embed | null = await (async () => { 59 - if (!post.embed) return null; 60 - switch (post.embed.$type) { 61 - case "app.bsky.embed.images": 62 - return images(post.embed.images); 63 - 64 - case "app.bsky.embed.video": 65 - return video(post.embed.video, post.embed.alt, post.embed.captions); 66 - 67 - case "app.bsky.embed.external": 68 - return external(post.embed.external); 69 - 70 - case "app.bsky.embed.record": 71 - return await record(post.embed.record.uri, nested); 72 - 73 - case "app.bsky.embed.recordWithMedia": 74 - return recordWithMedia( 75 - post.embed.record.record.uri, 76 - post.embed.media, 77 - nested, 78 - ); 79 - } 80 - })(); 81 - --- 82 - 83 - <article 84 - class="post" 85 - style={` 86 - --box-tlbr-png: url(${BoxTlbr.src}); 87 - --hr-png: url(${Hr.src}); 88 - `} 89 - > 90 - <section class="author"> 91 - {author.avatar && <img src={author.avatar} alt="" class="avatar" />} 92 - { 93 - author.displayName ? ( 94 - <a class="name" href={`https://deer.social/profile/${author.did}`}> 95 - {author.displayName} 96 - </a> 97 - ) : null 98 - } 99 - <div class="handle"> 100 - @<a href={`https://${author.handle}/`}>{author.handle}</a> 101 - </div> 102 - { 103 - !author.displayName ? ( 104 - <a 105 - class="name no-name" 106 - href={`https://deer.social/profile/${author.did}`} 107 - > 108 - Profile on deer.social 109 - </a> 110 - ) : null 111 - } 112 - </section> 113 - <div class="link"> 114 - Open on 115 - <a href={`https://deer.social/profile/${author.did}/post/${rkey}`}> 116 - deer.social 117 - </a> 118 - </div> 119 - <hr /> 120 - <section class="content"> 121 - <div> 122 - <!-- ignore is needed bc otherwise this and 123 - the anchors have leading/trailing whitespace 124 - and i cant tell prettier to stop sooo --> 125 - <!-- prettier-ignore --> 126 - <div class="post-text">{ 127 - !post.facets 128 - ? post.text 129 - : segmentize(post.text.trim(), post.facets).map((x) => !x.features 130 - ? x.text 131 - : x.features.reduce( 132 - (acc, cur) => 133 - cur.$type === "app.bsky.richtext.facet#link" ? ( 134 - <a href={cur.uri}>{acc}</a> 135 - ) : cur.$type === "app.bsky.richtext.facet#mention" ? ( 136 - <a href={`https://deer.social/profile/${cur.did}`}>{acc}</a> 137 - ) : ( 138 - <a href={`https://deer.social/hashtag/${cur.tag}`}>{acc}</a> 139 - ), 140 - x.text, 141 - )) 142 - } 143 - </div> 144 - { 145 - embed && ( 146 - <div class="embed"> 147 - {(() => { 148 - const images = (img: embedImages) => 149 - img.images.map((image) => ( 150 - <img src={cidSrc(image.cid, author.did)} alt={image.alt} /> 151 - )); 152 - const video = (vid: embedVideo) => ( 153 - <video 154 - controls 155 - crossorigin="anonymous" 156 - src={cidSrc(vid.cid, author.did)} 157 - aria-label={vid.alt} 158 - > 159 - {vid.subtitles && 160 - vid.subtitles.map((track, i) => ( 161 - <track 162 - default={i === 0} 163 - kind="captions" 164 - srclang={track.lang} 165 - src={cidSrc(track.cid, author.did)} 166 - /> 167 - ))} 168 - </video> 169 - ); 170 - const external = (external: embedExternal) => ( 171 - <a href={external.url} class="external" title={external.url}> 172 - {external.thumb && ( 173 - <img src={cidSrc(external.thumb, author.did)} alt="" /> 174 - )} 175 - <span class="name">{external.title}</span> 176 - <span class="url">{new URL(external.url).host}</span> 177 - </a> 178 - ); 179 - const record = (record: embedRecord) => { 180 - const uriFragments = record.uri.match( 181 - new RegExp( 182 - "at:\/\/(?<did>did:(?:plc|web):[^\/]*)\/(?<nsid>[^\/]*)\/(?<rkey>.*)", 183 - ), 184 - ); 185 - let rkey: string = uriFragments?.groups?.rkey ?? ""; 186 - return record.record && record.author ? ( 187 - <Astro.self 188 - post={record.record} 189 - author={record.author} 190 - {rkey} 191 - nested 192 - /> 193 - ) : ( 194 - <div class="post"> 195 - Read More on 196 - <a 197 - href={`https://deer.social/profile/${author.did}/post/${rkey}`} 198 - > 199 - deer.social 200 - </a> 201 - </div> 202 - ); 203 - }; 204 - const recordWithMedia = (recordWMedia: embedRecordWithMedia) => { 205 - const quoted = record(recordWMedia.record); 206 - const media = 207 - recordWMedia.media.$type === "app.bsky.embed.images" 208 - ? images(recordWMedia.media) 209 - : recordWMedia.media.$type === "app.bsky.embed.video" 210 - ? video(recordWMedia.media) 211 - : external(recordWMedia.media); 212 - return ( 213 - <> 214 - {media} 215 - {quoted} 216 - </> 217 - ); 218 - }; 219 - 220 - switch (embed.$type) { 221 - case "app.bsky.embed.images": 222 - return images(embed); 223 - case "app.bsky.embed.video": 224 - return video(embed); 225 - case "app.bsky.embed.external": 226 - return external(embed); 227 - case "app.bsky.embed.record": 228 - return record(embed); 229 - case "app.bsky.embed.recordWithMedia": 230 - return recordWithMedia(embed); 231 - } 232 - })()} 233 - </div> 234 - ) 235 - } 236 - </div> 237 - </section> 238 - </article> 239 - 240 - <style> 241 - .post, 242 - .external { 243 - display: block; 244 - border-image: var(--box-tlbr-png) 10 10 fill / 20px 20px round; 245 - padding: 30px; 246 - } 247 - 248 - .author { 249 - display: grid; 250 - grid-template: 251 - "avatar name" 1.5em 252 - "avatar handle" 1.5em / 253 - auto 1fr; 254 - 255 - &:has(.no-name) { 256 - grid-template-areas: "avatar handle" "avatar name"; 257 - } 258 - 259 - gap: 0 5px; 260 - align-items: center; 261 - justify-content: start; 262 - 263 - .avatar { 264 - grid-area: avatar; 265 - width: 3em; 266 - height: 3em; 267 - border-radius: 100%; 268 - } 269 - 270 - .name { 271 - grid-area: name; 272 - overflow: hidden; 273 - white-space: nowrap; 274 - /* use string instead of keyword so its longer */ 275 - text-overflow: "..."; 276 - } 277 - 278 - .handle { 279 - grid-area: handle; 280 - } 281 - } 282 - 283 - hr { 284 - margin-block: 5px; 285 - height: 5px; 286 - border: none; 287 - border-image: var(--hr-png) 0 5 fill / 0 5px round; 288 - } 289 - 290 - .post-text { 291 - white-space: pre-wrap; 292 - } 293 - 294 - .embed img { 295 - image-rendering: smooth; 296 - } 297 - 298 - .embed .external { 299 - * { 300 - display: block; 301 - } 302 - 303 - img, 304 - .name { 305 - margin-bottom: 5px; 306 - } 307 - 308 - .url { 309 - opacity: 0.65; 310 - } 311 - } 312 - 313 - a { 314 - color: black; 315 - 316 - &:hover, 317 - &:focus { 318 - text-decoration-style: dashed; 319 - } 320 - 321 - &:active { 322 - text-decoration: none; 323 - } 324 - } 325 - 326 - ul { 327 - list-style: none; 328 - } 329 - </style>
+5
src/components/home/feeds/Tangled.astro
··· 1 + --- 2 + 3 + --- 4 + 5 + <h4>tangled.sh</h4>
+5
src/components/home/feeds/Tumblr.astro
··· 1 + --- 2 + 3 + --- 4 + 5 + <h2>tmlr</h2>
-23
src/components/home/feeds/atproto.ts
··· 1 - // create a single client instance 2 - import { Client, simpleFetchHandler } from "@atcute/client"; 3 - import { 4 - CompositeDidDocumentResolver, 5 - PlcDidDocumentResolver, 6 - WebDidDocumentResolver, 7 - } from "@atcute/identity-resolver"; 8 - import { socials } from "/site-config"; 9 - 10 - export const client = new Client({ 11 - handler: simpleFetchHandler({ service: "https://public.api.bsky.app" }), 12 - }); 13 - 14 - export const pds = new Client({ 15 - handler: simpleFetchHandler({ service: socials.atproto.pds }), 16 - }); 17 - 18 - export const docResolver = new CompositeDidDocumentResolver({ 19 - methods: { 20 - plc: new PlcDidDocumentResolver(), 21 - web: new WebDidDocumentResolver(), 22 - }, 23 - });
-124
src/components/home/feeds/post-embeds.ts
··· 1 - import { AppBskyFeedPost } from "@atcute/bluesky"; 2 - import { 3 - type LegacyBlob, 4 - type Blob, 5 - type ResourceUri, 6 - is, 7 - } from "@atcute/lexicons"; 8 - import { client } from "./atproto"; 9 - import type { 10 - embedImages, 11 - embedVideo, 12 - embedExternal, 13 - embedRecord, 14 - embedRecordWithMedia, 15 - } from "./post-types"; 16 - import { throws, type Prettify } from "/utils"; 17 - 18 - export const images = ( 19 - images: { alt: string; image: Blob | LegacyBlob }[], 20 - ): embedImages => ({ 21 - $type: "app.bsky.embed.images", 22 - images: images.map((image) => ({ 23 - alt: image.alt, 24 - cid: image.image, 25 - })), 26 - }); 27 - 28 - export const video = ( 29 - video: Blob | LegacyBlob, 30 - alt: string | undefined, 31 - captions: 32 - | { 33 - file: Blob | LegacyBlob; 34 - lang: string; 35 - }[] 36 - | undefined, 37 - ): embedVideo => ({ 38 - $type: "app.bsky.embed.video", 39 - cid: video, 40 - alt: alt, 41 - subtitles: 42 - captions && 43 - captions.map((captions) => ({ 44 - cid: captions.file, 45 - lang: captions.lang, 46 - })), 47 - }); 48 - 49 - export const external = (external: { 50 - title: string; 51 - uri: `${string}:${string}`; 52 - thumb?: Blob | LegacyBlob | undefined; 53 - }): embedExternal => ({ 54 - $type: "app.bsky.embed.external", 55 - title: external.title, 56 - url: external.uri, 57 - thumb: external.thumb, 58 - }); 59 - 60 - export const record = async ( 61 - uri: ResourceUri, 62 - nested: boolean, 63 - ): Promise<Prettify<embedRecord>> => { 64 - if (nested) 65 - return { $type: "app.bsky.embed.record", record: null, author: null, uri }; 66 - const data = await client 67 - .get("app.bsky.feed.getPosts", { 68 - params: { 69 - uris: [uri], 70 - }, 71 - }) 72 - .then(({ ok, data }) => 73 - ok ? data : throws(data.error + "\n" + data.message), 74 - ); 75 - 76 - return { 77 - $type: "app.bsky.embed.record", 78 - record: is(AppBskyFeedPost.mainSchema, data.posts[0].record) 79 - ? data.posts[0].record 80 - : throws("Malformed embeded post"), 81 - author: { 82 - did: data.posts[0].author.did, 83 - displayName: data.posts[0].author.displayName, 84 - handle: data.posts[0].author.handle, 85 - avatar: data.posts[0].author.avatar, 86 - }, 87 - uri, 88 - }; 89 - }; 90 - 91 - export const recordWithMedia = async ( 92 - uri: ResourceUri, 93 - media: 94 - | { 95 - $type: "app.bsky.embed.images"; 96 - images: { alt: string; image: Blob | LegacyBlob }[]; 97 - } 98 - | { 99 - $type: "app.bsky.embed.video"; 100 - video: Blob | LegacyBlob; 101 - alt?: string | undefined; 102 - captions?: { lang: string; file: Blob | LegacyBlob }[] | undefined; 103 - } 104 - | { 105 - $type: "app.bsky.embed.external"; 106 - external: { 107 - title: string; 108 - uri: `${string}:${string}`; 109 - thumb?: Blob | LegacyBlob | undefined; 110 - }; 111 - }, 112 - nested: boolean, 113 - ): Promise<embedRecordWithMedia> => { 114 - return { 115 - $type: "app.bsky.embed.recordWithMedia", 116 - record: await record(uri, nested), 117 - media: 118 - media.$type === "app.bsky.embed.images" 119 - ? images(media.images) 120 - : media.$type === "app.bsky.embed.video" 121 - ? video(media.video, media.alt, media.captions) 122 - : external(media.external), 123 - }; 124 - };
-57
src/components/home/feeds/post-types.ts
··· 1 - import type { AppBskyFeedPost } from "@atcute/bluesky"; 2 - import type { Blob, LegacyBlob, ResourceUri } from "@atcute/lexicons"; 3 - 4 - export interface Author { 5 - did: `did:${string}:${string}`; 6 - handle: `${string}.${string}`; 7 - displayName?: string; 8 - avatar?: `${string}:${string}`; 9 - } 10 - 11 - export const understoodDid = ( 12 - did: `did:${string}:${string}`, 13 - ): did is `did:${"plc" | "web"}:${string}` => 14 - did.startsWith("did:web") || did.startsWith("did:plc"); 15 - 16 - export type embedImages = { 17 - $type: "app.bsky.embed.images"; 18 - images: { alt: string; cid: Blob | LegacyBlob }[]; 19 - }; 20 - 21 - export type embedVideo = { 22 - $type: "app.bsky.embed.video"; 23 - cid: Blob | LegacyBlob; 24 - alt: string | undefined; 25 - subtitles: 26 - | { 27 - cid: Blob | LegacyBlob; 28 - lang: string; 29 - }[] 30 - | undefined; 31 - }; 32 - 33 - export type embedExternal = { 34 - $type: "app.bsky.embed.external"; 35 - title: string; 36 - url: string; 37 - thumb: Blob | LegacyBlob | undefined; 38 - }; 39 - export type embedRecord = { 40 - $type: "app.bsky.embed.record"; 41 - record: AppBskyFeedPost.Main | null; 42 - author: Author | null; 43 - uri: ResourceUri; 44 - }; 45 - 46 - export type embedRecordWithMedia = { 47 - $type: "app.bsky.embed.recordWithMedia"; 48 - record: embedRecord; 49 - media: embedImages | embedVideo | embedExternal; 50 - }; 51 - 52 - export type embed = 53 - | embedImages 54 - | embedVideo 55 - | embedExternal 56 - | embedRecord 57 - | embedRecordWithMedia;
+72 -205
src/components/home/playing/NowPlaying.astro
··· 1 1 --- 2 - import type { PlaybackState, Track } from "@spotify/web-api-ts-sdk"; 3 2 import { sdk } from "./spotify"; 4 - 5 - import TopSongs from "./TopSongs.astro"; 6 3 7 4 import mp3Base from "/assets/mp3/base.png"; 8 5 import mp3AlbumArtMask from "/assets/mp3/album-art-mask.png"; ··· 10 7 import mp3HeadCircle from "/assets/mp3/head-circle.png"; 11 8 import mp3PlaybackHead from "/assets/mp3/playback-head.png"; 12 9 import boxTlbr from "/assets/box-tlbr.png"; 13 - import boxTB from "/assets/box-tb.png"; 14 10 import popoutSpeech from "/assets/popout-speech.png"; 15 - import smallBoxMask from "/assets/small-box-mask-1-0.png"; 16 - import whiteGradient from "/assets/white-gradient.png"; 17 - import rightArrow from "/assets/right-arrow-2x-outline.png"; 11 + import smallBoxMask from "/assets/small-box-mask.png"; 12 + import type { PlaybackState, Track } from "@spotify/web-api-ts-sdk"; 18 13 19 - const track = await sdk.player.getCurrentlyPlayingTrack().catch(() => null); 14 + const track = await sdk.player.getCurrentlyPlayingTrack(); 20 15 21 16 const isSong = ( 22 17 item: PlaybackState | null, ··· 33 28 --mp3-head-circle-png: url(${mp3HeadCircle.src}); 34 29 --mp3-playback-head-png: url(${mp3PlaybackHead.src}); 35 30 --box-tlbr-png: url("${boxTlbr.src}"); 36 - --box-tb-png: url("${boxTB.src}"); 37 31 --popout-speech-png: url("${popoutSpeech.src}"); 38 32 --small-box-mask-png: url("${smallBoxMask.src}"); 39 - --white-gradient-png: url("${whiteGradient.src}"); 40 - --right-arrow-png: url("${rightArrow.src}"); 41 33 `} 42 34 > 43 - <button 35 + <div 44 36 class="player" 37 + tabindex="0" 45 38 aria-label="Record player" 46 - popovertarget="nowplaying" 47 39 data-playing={isSong(track) ? "true" : "false"} 48 40 > 49 41 <div class="spinner"></div> ··· 64 56 65 57 <!-- aria-live=off means aria updates are only announced when focused. 66 58 this makes sense as what im listening too is irrelevant if --> 67 - <now-playing 68 - data-render={isSong(track)} 69 - aria-live="off" 70 - id="nowplaying" 71 - popover="auto" 72 - > 59 + <now-playing data-render={isSong(track)} aria-live="off"> 73 60 <a 74 61 slot="title" 75 62 href={isSong(track) ? track.item.external_urls.spotify : "#"} ··· 119 106 </div> 120 107 </div> 121 108 122 - <style is:inline> 123 - :host { 124 - background: none; 125 - border-image: var(--box-tlbr-png) 10 fill / calc((20 / 3) * 1cqw) 126 - round; 109 + <style> 110 + /* dont show element if it errored or nothing is playing */ 111 + :host([data-render="false"]) { 112 + display: none !important; 113 + } 127 114 115 + :host { 128 116 contain: layout; 129 - box-sizing: border-box; 117 + position: absolute; 118 + bottom: 105cqh; 130 119 131 120 width: 100cqw; 132 - height: max-content; 121 + height: auto; 122 + 123 + box-sizing: border-box; 133 124 /* gets overridden by the fukcin * selector. for some reason */ 134 125 padding: calc((25 / 3) * 1cqw) !important; 135 126 136 - overflow: visible; 127 + border-image: var(--box-tlbr-png) 10 fill / calc((20 / 3) * 1cqw) 128 + round; 137 129 138 130 &::after { 139 131 content: ""; ··· 159 151 "name art" auto 160 152 "artists art" auto 161 153 / 1fr 80px; 162 - gap: 0px 10px; 163 154 align-items: center; 164 155 justify-content: center; 165 156 ··· 176 167 .art { 177 168 grid-area: art; 178 169 width: 80px; 179 - height: 80px; 170 + height: 80ps; 180 171 } 181 172 } 182 173 </style> 183 174 </template> 184 175 </now-playing> 185 - </button> 186 - 187 - <TopSongs /> 176 + </div> 188 177 </section> 189 178 190 179 <style> ··· 215 204 } 216 205 } 217 206 218 - .playing { 219 - z-index: 2; 220 - 221 - contain: size; 222 - overflow: visible auto; 223 - 224 - @media (max-width: 110ch) { 225 - /* mobile border image */ 226 - border-image-source: var(--box-tb-png); 227 - border-image-slice: 10 0 fill; 228 - border-image-width: 20px 0; 229 - border-image-outset: 20px 10000px; 230 - border-image-repeat: round; 231 - 232 - contain: inline-size; 233 - overflow: auto visible; 234 - 235 - display: grid; 236 - grid-template-columns: auto auto 40px; 237 - align-items: center; 238 - 239 - &::after { 240 - /* visual hint */ 241 - content: var(--right-arrow-png) / ""; 242 - position: sticky; 243 - right: 0px; 244 - 245 - padding-inline: 5px; 246 - height: 100%; 247 - width: 40px; 248 - 249 - background-image: var(--white-gradient-png); 250 - background-size: 100%; 251 - 252 - display: flex; 253 - align-items: center; 254 - justify-content: end; 255 - } 256 - } 257 - } 258 - 259 207 .player { 260 208 /* internal and external nodes dont affect each other 261 209 children dont affect this size 262 210 properties dont affect external nodes */ 263 211 contain: layout size style; 264 212 container: player / size; 265 - overflow: clip; 266 213 width: 100%; 267 - @media (max-width: 110ch) { 268 - width: 400px; 269 - height: 325.333px; 270 - } 271 214 /* design size is 300px by 244px 272 215 treat 1cqw = 3px. 273 216 */ 274 217 aspect-ratio: 300/244; 275 - flex: none; 276 - /* float: left; */ 277 218 219 + image-rendering: pixelated; 278 220 background-image: var(--mp3-base-png); 279 221 background-size: contain; 280 222 281 - /* remove the button styles */ 282 - background: none; 283 - border: none; 284 - 285 223 * { 286 224 background-size: contain; 287 225 } ··· 298 236 background-image: var(--mp3-record-circle-png); 299 237 300 238 animation: 30s linear forwards infinite spin; 301 - 302 - @media (prefers-reduced-motion: reduce) { 303 - animation-delay: -20s; 304 - animation-play-state: paused; 305 - } 306 239 307 240 [data-playing="false"] & { 308 241 animation-play-state: paused; ··· 333 266 334 267 animation: 60s linear 2.5s infinite forwards head-move; 335 268 336 - @media (prefers-reduced-motion: reduce) { 337 - animation-delay: -20s; 338 - animation-play-state: paused; 339 - } 340 - 341 269 [data-playing="false"] & { 342 270 animation-play-state: paused; 343 271 } ··· 357 285 } 358 286 } 359 287 288 + now-playing { 289 + display: none; 290 + } 291 + 360 292 /* setup the ::before to be usable for the outline 361 293 filter cannot be applied straight to .player 362 294 as the now-playing is a child and also gets the outline ··· 373 305 374 306 background-image: var(--mp3-base-png); 375 307 background-size: contain; 376 - 377 - z-index: -99999; 378 308 } 379 309 380 310 .player:focus, ··· 391 321 drop-shadow(var(--outline-colour) 0 calc(-1 * var(--outline-size))) 392 322 drop-shadow(var(--outline-colour) calc(-1 * var(--outline-size)) 0); 393 323 } 394 - } 395 - </style> 396 324 397 - <style is:inline> 398 - .player { 399 - anchor-name: --player; 325 + & now-playing { 326 + display: block; 327 + } 400 328 } 401 329 402 330 now-playing { 403 - left: var(--player-left, anchor(--player left)); 404 - bottom: calc(var(--player-top, anchor(--player top)) + 20px); 405 - top: unset; 406 - right: unset; 407 - text-align: left; 408 - font-size: 1rem; 409 - 410 331 & img { 411 332 mask-image: var(--small-box-mask-png); 412 333 mask-size: contain; 413 334 } 414 - 415 335 & a { 416 336 color: black; 417 337 ··· 426 346 } 427 347 } 428 348 </style> 429 - 430 349 <script> 431 350 /*********** 432 351 * IMPORTS * ··· 645 564 * ANIMATIONS * 646 565 **************/ 647 566 648 - const reducedMotion = window.matchMedia("(prefers-reduced-motion:reduce)"); 567 + // delete css animations since we r going to use our own 568 + elements.spinner.forEach((el) => 569 + el.getAnimations().forEach((anim) => anim.cancel()), 570 + ); 649 571 650 572 const playHeadAnimation = [ 651 573 { ··· 672 594 // start state is infered 673 595 const goToStartAnimation = [{ rotate: "0deg" }]; 674 596 675 - let animations: Animation[] = []; 676 - 677 - // we only do js animations if reduced motion is disabled 678 - // if reduce motion is reduced, the static css animations are fine 679 - if (!reducedMotion.matches) { 680 - // delete css animations since we r going to use our own 681 - elements.spinner.forEach((el) => 682 - el.getAnimations().forEach((anim) => anim.cancel()), 683 - ); 684 - 685 - animations = elements.spinner.map((el) => 686 - el.animate(playHeadAnimation, { 687 - duration: 30 * 1000, 688 - fill: "forwards", 689 - iterations: Infinity, 690 - }), 691 - ); 597 + const animations = elements.spinner.map((el) => 598 + el.animate(playHeadAnimation, { 599 + duration: 30 * 1000, 600 + fill: "forwards", 601 + iterations: Infinity, 602 + }), 603 + ); 692 604 693 - // pause the animations if nothing is playing or reduced motion is enabled 694 - if (elements.player.dataset.playing === "false") { 695 - // dont play animations 696 - animations.forEach((anim) => anim.pause()); 697 - } 605 + if (elements.player.dataset.playing === "false") { 606 + // dont play animations 607 + animations.forEach((anim) => anim.pause()); 698 608 } 699 609 700 610 /************ ··· 738 648 // there is now a difference between the previous setting and the new setting 739 649 // so it is worth updating the UI 740 650 741 - if (!reducedMotion) { 742 - // spinner head animation: 743 - // 1. pause current animation. 744 - animations.forEach((anim) => anim.pause()); 745 - elements.spinner.forEach((el) => 746 - // 2. send the playback head to the start 747 - el 748 - .animate(goToStartAnimation, { 749 - duration: 2.5 * 1000, 750 - easing: "ease-in-out", 751 - }) 752 - // 3. when the playback head is at the start 753 - .finished.then(async () => { 754 - // 4. update the record art 755 - elements.recordArt.src = data ? data?.art : "https://undefined"; 756 - 757 - // 5. update popup 758 - if (data) elements.nowPlaying.updateMetadata(data); 759 - else elements.nowPlaying.nothingPlaying(); 760 - 761 - // 6. reset the position of the infinite animation 762 - animations.forEach((anim) => (anim.currentTime = 0)); 651 + // spinner head animation: 652 + // 1. pause current animation. 653 + animations.forEach((anim) => anim.pause()); 654 + elements.spinner.forEach((el) => 655 + // 2. send the playback head to the start 656 + el 657 + .animate(goToStartAnimation, { 658 + duration: 2.5 * 1000, 659 + easing: "ease-in-out", 660 + }) 661 + // 3. when the playback head is at the start 662 + .finished.then(async () => { 663 + // 4. update the record art 664 + elements.recordArt.src = data ? data?.art : "https://undefined"; 763 665 764 - // 7. if new track is not null then, after 2s 765 - if (data) 766 - setTimeout(() => { 767 - // 8. resume the infinite animation 768 - animations.forEach((anim) => anim.play()); 769 - }, 2000); 666 + // 5. update popup 667 + if (data) elements.nowPlaying.updateMetadata(data); 668 + else elements.nowPlaying.nothingPlaying(); 770 669 771 - // 9. make sure the record is in the right state (playing or paused) 772 - elements.player.dataset.playing = data ? "true" : "false"; 773 - }), 774 - ); 775 - // the user requested reduced motion, so instantly update state 776 - } else { 777 - elements.recordArt.src = data ? data?.art : "https://undefined"; 670 + // 6. reset the position of the infinite animation 671 + animations.forEach((anim) => (anim.currentTime = 0)); 778 672 779 - if (data) elements.nowPlaying.updateMetadata(data); 780 - else elements.nowPlaying.nothingPlaying(); 673 + // 7. if new track is not null then, after 2s 674 + if (data) 675 + setTimeout(() => { 676 + // 8. resume the infinite animation 677 + animations.forEach((anim) => anim.play()); 678 + }, 2000); 781 679 782 - elements.player.dataset.playing = data ? "true" : "false"; 783 - } 680 + // 9. make sure the record is in the right state (playing or paused) 681 + elements.player.dataset.playing = data ? "true" : "false"; 682 + }), 683 + ); 784 684 } 785 685 } finally { 786 686 prev = data; 787 687 } 788 688 }); 789 - 790 - /********** 791 - * ANCHOR * 792 - **********/ 793 - 794 - const position = () => { 795 - // recalculate anchor positions 796 - elements.nowPlaying.style.setProperty( 797 - "--player-left", 798 - elements.player.getBoundingClientRect().left + "px", 799 - ); 800 - elements.nowPlaying.style.setProperty( 801 - "--player-top", 802 - window.innerHeight - elements.player.getBoundingClientRect().top + "px", 803 - ); 804 - }; 805 - 806 - if (!CSS.supports("top", "calc(anchor(--player bottom) + 10px)")) { 807 - position(); 808 - elements.nowPlaying.addEventListener("beforetoggle", position); 809 - window.addEventListener("scroll", position); 810 - elements.player.parentNode?.addEventListener("scroll", position); 811 - new ResizeObserver(position).observe(document.documentElement); 812 - } 813 - 814 - // hide the warning element 815 - document 816 - .querySelectorAll(".no-anchor-warning") 817 - .forEach((el) => 818 - el instanceof HTMLElement 819 - ? el.style.setProperty("display", "none") 820 - : null, 821 - ); 822 689 </script>
-76
src/components/home/playing/TopSongs.astro
··· 1 - --- 2 - import { sdk } from "./spotify"; 3 - import { throws } from "/utils"; 4 - 5 - const masks = ( 6 - await Promise.all([ 7 - import("/assets/small-box-mask-1-0.png"), 8 - import("/assets/small-box-mask-1-90.png"), 9 - import("/assets/small-box-mask-1-180.png"), 10 - import("/assets/small-box-mask-1-270.png"), 11 - 12 - import("/assets/small-box-mask-2-0.png"), 13 - import("/assets/small-box-mask-2-90.png"), 14 - import("/assets/small-box-mask-2-180.png"), 15 - import("/assets/small-box-mask-2-270.png"), 16 - 17 - import("/assets/small-box-mask-3-0.png"), 18 - import("/assets/small-box-mask-3-90.png"), 19 - import("/assets/small-box-mask-3-180.png"), 20 - import("/assets/small-box-mask-3-270.png"), 21 - ]) 22 - ).map((x) => x.default.src); 23 - 24 - const topSongs = await sdk.currentUser 25 - .topItems("tracks", "short_term", 48) 26 - .then((tracks) => (!tracks ? throws("Top tracks failed") : tracks)) 27 - .catch((err) => console.error(err)); 28 - 29 - if (!topSongs) return "Error 500 failed to get top songs!!"; 30 - --- 31 - 32 - <ul class="top-songs"> 33 - { 34 - topSongs.items.map( 35 - (song) => 36 - song.album.images[0].url && ( 37 - <li 38 - style={`--mask: url(${masks[Math.floor(Math.random() * masks.length)] ?? masks[0]})`} 39 - > 40 - <a href={song.external_urls.spotify}> 41 - <img 42 - src={song.album.images[0].url} 43 - alt={`${song.name} by ${song.artists.map((artist) => artist.name).join(", ")}`} 44 - title={`${song.name} by ${song.artists.map((artist) => artist.name).join(", ")}`} 45 - /> 46 - </a> 47 - </li> 48 - ), 49 - ) 50 - } 51 - </ul> 52 - 53 - <style> 54 - ul { 55 - list-style: none; 56 - display: grid; 57 - grid-template-columns: repeat(3, 1fr); 58 - gap: 10px; 59 - padding: 10px; 60 - 61 - @media (max-width: 110ch) { 62 - grid-template-columns: auto; 63 - grid-template-rows: repeat(3, 100px); 64 - grid-auto-columns: 100px; 65 - grid-auto-flow: column; 66 - } 67 - } 68 - 69 - img { 70 - aspect-ratio: 1; 71 - 72 - mask-image: var(--mask); 73 - mask-size: 100% 100%; 74 - mask-repeat: no-repeat; 75 - } 76 - </style>
+64 -130
src/components/home/playing/spotify/index.ts
··· 1 1 /** 2 2 * types and logic for getting now playing information 3 3 */ 4 - import { 5 - DefaultResponseDeserializer, 6 - DefaultResponseValidator, 7 - DocumentLocationRedirectionStrategy, 8 - InMemoryCachingStrategy, 9 - NoOpErrorHandler, 10 - SpotifyApi, 11 - type AccessToken, 12 - type IAuthStrategy, 13 - type IHandleErrors, 14 - type SdkConfiguration, 15 - } from "@spotify/web-api-ts-sdk"; 4 + 5 + import { SpotifyApi, type AccessToken } from "@spotify/web-api-ts-sdk"; 16 6 import { SPOTIFY_CLIENT_ID, SPOTIFY_CLIENT_SECRET } from "astro:env/server"; 17 7 18 - import fs from "fs/promises"; 19 - import { isObj, throws, type Prettify } from "/utils"; 8 + import fs from "node:fs/promises"; 9 + import { isObj } from "/utils"; 20 10 21 - type AuthAccessToken = Prettify<AccessToken & { expires: number }>; 11 + /** 12 + * the refresh_token field is not checked as 13 + */ 14 + const isSpotifyAccessToken = (token: any): token is AccessToken => 15 + isObj(token) && 16 + "access_token" in token && 17 + typeof token.access_token === "string" && 18 + "token_type" in token && 19 + token.token_type === "Bearer" && 20 + "expires_in" in token && 21 + typeof token.expires_in === "number"; 22 22 23 - const defaultConfig: SdkConfiguration = { 24 - fetch: (req: string | Request | URL, init?: RequestInit) => fetch(req, init), 25 - beforeRequest: () => {}, 26 - afterRequest: () => {}, 27 - deserializer: new DefaultResponseDeserializer(), 28 - responseValidator: new DefaultResponseValidator(), 29 - errorHandler: new NoOpErrorHandler(), 30 - redirectionStrategy: new DocumentLocationRedirectionStrategy(), 31 - cachingStrategy: new InMemoryCachingStrategy(), 32 - }; 23 + // try load last known refresh token from file 24 + const refreshToken = await fs 25 + .readFile("./.refreshToken", { encoding: "utf-8" }) 26 + .then((token) => (token ? token : console.log("invalid `./.refreshToken`"))) 27 + // if anything errors its undefined 28 + .catch((err) => console.error(err)); 33 29 34 - class Auth implements IAuthStrategy { 35 - config: SdkConfiguration = { ...defaultConfig }; 36 - 37 - accessToken: AuthAccessToken | null = null; 38 - 39 - /** update the stored config with the new config */ 40 - setConfiguration(config: SdkConfiguration): void { 41 - this.config = { ...defaultConfig, ...config }; 42 - } 43 - 44 - /** return the stored access token. if no token is stored, authenticate 45 - * will always include the `expires` field 46 - */ 47 - async getOrCreateAccessToken(): Promise<AuthAccessToken> { 48 - // if the token is stored and the token hasn't yet expired, return it 49 - if (this.accessToken && this.accessToken.expires > Date.now()) 50 - return this.accessToken; 51 - 52 - // no token is stored OR the token has expired, so we ignore the stored token and refresh it 53 - // if we cannot read the file there is no way to recover this and we should let the error throw 54 - // this will get caught in the `catch` branch of SpotifyAPI.makeRequest() and handled by the handler 55 - const refreshToken = await fs.readFile("./.refreshToken", { 56 - encoding: "utf8", 57 - }); 30 + // if refreshToken is undefined then we dont have a valid one saved, and can request the user obtain one 31 + // (this could be corruption, failed save, or missing file) 32 + if (!refreshToken) 33 + throw new Error( 34 + "No access token is stored in `./.refreshToken`. Please generate one using the `/callback` endpoint in a dev server.", 35 + ); 58 36 59 - const res = await fetch("https://accounts.spotify.com/api/token", { 60 - method: "POST", 61 - headers: { 62 - "Content-Type": "application/x-www-form-urlencoded", 63 - Authorization: 64 - "Basic " + 65 - Buffer.from(SPOTIFY_CLIENT_ID + ":" + SPOTIFY_CLIENT_SECRET).toString( 66 - "base64", 67 - ), 68 - }, 69 - body: new URLSearchParams({ 70 - grant_type: "refresh_token", 71 - refresh_token: refreshToken, 72 - }).toString(), 73 - }); 37 + const accessToken = await fetch("https://accounts.spotify.com/api/token", { 38 + method: "post", 74 39 75 - // if its not a 200 code, throw 76 - if (!res.ok) 77 - throw new Error( 78 - `Token request recived error ${res.status}: ${res.statusText}`, 79 - ); 40 + headers: { 41 + "content-type": "application/x-www-form-urlencoded", 42 + Authorization: 43 + "Basic " + 44 + Buffer.from(SPOTIFY_CLIENT_ID + ":" + SPOTIFY_CLIENT_SECRET).toString( 45 + "base64", 46 + ), 47 + }, 80 48 81 - // dont handle the exception, this is covered by the user handler 82 - const result = await res.json(); 83 - // check the result is formed correctly 84 - if (!isObj(result)) throw new Error("Didnt recive an object from spotify"); 49 + body: new URLSearchParams({ 50 + grant_type: "refresh_token", 51 + refresh_token: refreshToken, 52 + }).toString(), 53 + }) 54 + .then((res) => res.json()) 55 + .then((token) => 56 + isSpotifyAccessToken(token) 57 + ? { 58 + ...token, 59 + // if no refresh_token is provided then insert it 60 + ...(token.refresh_token ? {} : { refresh_token: refreshToken }), 61 + } 62 + : console.error("Response was not a valid access token:", token), 63 + ) 64 + .catch((err) => console.error(err)); 85 65 86 - this.accessToken = { 87 - access_token: 88 - "access_token" in result && typeof result.access_token === "string" 89 - ? result.access_token 90 - : throws(new Error("Invalid access_token field")), 91 - token_type: 92 - "access_token" in result && typeof result.access_token === "string" 93 - ? result.access_token 94 - : throws(new Error("Invalid access_token field")), 95 - expires_in: 96 - "expires_in" in result && typeof result.expires_in === "number" 97 - ? result.expires_in 98 - : throws(new Error("Invalid expires_in field")), 99 - refresh_token: 100 - "refresh_token" in result 101 - ? typeof result.refresh_token === "string" 102 - ? result.refresh_token 103 - : throws(new Error("Invalid refresh_token field")) 104 - : refreshToken, 105 - expires: 106 - // get current time 107 - Date.now() - 108 - // subtract 1 minute to account for all possible latency 109 - 60 * 1000 + 110 - // get the expires_in time in ms 111 - ("expires_in" in result && typeof result.expires_in === "number" 112 - ? result.expires_in * 1000 113 - : throws(new Error("Invalid expires_in field"))), 114 - }; 66 + if (!accessToken) 67 + throw new Error( 68 + "Could not generate a new access token from the refresh token", 69 + ); 115 70 116 - // write the new refresh token to a file. we dont need to save this one 117 - fs.writeFile("./.refreshToken", this.accessToken.refresh_token, { 118 - encoding: "utf8", 71 + export const sdk = SpotifyApi.withAccessToken(SPOTIFY_CLIENT_ID, accessToken, { 72 + async afterRequest() { 73 + const token = await sdk.getAccessToken(); 74 + if (!token) return; 75 + fs.writeFile("./.refreshToken", token.refresh_token, { 76 + encoding: "utf-8", 119 77 }); 120 - 121 - return this.accessToken; 122 - } 123 - 124 - /** get the current stored token. null means no token is stored */ 125 - async getAccessToken(): Promise<AccessToken | null> { 126 - return this.accessToken; 127 - } 128 - 129 - /** delete the access token */ 130 - removeAccessToken(): void { 131 - this.accessToken = null; 132 - } 133 - } 134 - 135 - class ErrHandler implements IHandleErrors { 136 - async handleErrors(error: any): Promise<boolean> { 137 - console.trace("sdk threw error:", error); 138 - // always claim its handled so it gets a null value 139 - return true; 140 - } 141 - } 142 - 143 - export const sdk = new SpotifyApi(new Auth(), { 144 - errorHandler: new ErrHandler(), 78 + }, 145 79 });
-122
src/components/markdown.css
··· 1 - /* all styles should be scoped 2 - to be child of article to avoid 3 - conflicting other styles */ 4 - .markdown-style { 5 - /* comfy reading width centered */ 6 - max-width: 60ch; 7 - padding: 10px; 8 - margin: auto; 9 - --content-gap: 20px; 10 - 11 - /* all headings should have 12 - leading and trailing margins 13 - but not between other headings */ 14 - h1, 15 - h2, 16 - h3, 17 - h4, 18 - h5, 19 - h6 { 20 - margin-block: var(--content-gap); 21 - 22 - & + & { 23 - margin-block-start: 0px; 24 - } 25 - 26 - &:has(+ &) { 27 - margin-block-end: 0px; 28 - } 29 - } 30 - 31 - > p, 32 - > ul, 33 - > ol, 34 - pre, 35 - blockquote, 36 - table, 37 - hr { 38 - margin-block: var(--content-gap); 39 - } 40 - 41 - :not(pre) > code { 42 - background-color: #00000020; 43 - padding: 2.5px; 44 - border-radius: 5px; 45 - box-decoration-break: clone; 46 - } 47 - 48 - pre { 49 - padding: 10px; 50 - border-radius: 10px; 51 - } 52 - 53 - blockquote { 54 - margin-left: 10px; 55 - padding-inline: 15px; 56 - padding-block: 5px; 57 - border-image: url(../assets/blockquote.png) 5 5 fill / 5px round; 58 - } 59 - 60 - hr { 61 - height: 5px; 62 - border: none; 63 - border-image: url(../assets/hr.png) 0 5 fill / 0 5px round; 64 - } 65 - 66 - ul, 67 - ol { 68 - padding-inline-start: 2em; 69 - 70 - & ol { 71 - list-style: lower-alpha; 72 - 73 - & ol { 74 - list-style: lower-roman; 75 - 76 - & ol { 77 - list-style: lower-greek; 78 - 79 - & ol { 80 - list-style: decimal; 81 - 82 - & ol ol { 83 - /* easter egg incase i ever go 7 deep lmao */ 84 - list-style: hebrew; 85 - } 86 - } 87 - } 88 - } 89 - } 90 - 91 - &.contains-task-list { 92 - /* checkbox is marker */ 93 - list-style-type: none; 94 - 95 - input { 96 - margin-inline-end: 0.5em; 97 - } 98 - } 99 - } 100 - 101 - img, 102 - audio, 103 - video, 104 - iframe, 105 - svg { 106 - width: 100%; 107 - height: auto; 108 - } 109 - 110 - table { 111 - border-collapse: collapse; 112 - thead { 113 - background: #00000020; 114 - } 115 - 116 - th, 117 - td { 118 - padding: 5px; 119 - border: 1px solid #00000040; 120 - } 121 - } 122 - }
src/content/blog/assets/blue-skies.png

This is a binary file and will not be displayed.

src/content/blog/assets/mixins.png

This is a binary file and will not be displayed.

src/content/blog/assets/pds-pi-graph.png

This is a binary file and will not be displayed.

-391
src/content/blog/css-functions-and-mixins.md
··· 1 - --- 2 - title: CSS functions and mixins 3 - bio: tl;dr and my 2 cents; Photo by ะžะปะตะณ ะœะพั€ะพะท on Unsplash 4 - banner: mixins.png 5 - pub: 2025-08-31 6 - --- 7 - 8 - The CSS `@function` rule is now available in chrome 139, with a definition for `@mixin` in the editors draft. (Referenced [First Public Working Draft](https://www.w3.org/TR/2025/WD-css-mixins-1-20250515/), Referenced [Editors Draft](https://drafts.csswg.org/css-mixins/)) 9 - I wanted an excuse to read into a spec, and this seems quite an interesting one so I thought why not write a post about it! (this is definitely not also because I need something to post when i deploy my site so it doesn't look empty lmao) 10 - 11 - > _All ye who travel beyond this point, head this warning_: 12 - > This spec got hands and idk how to shut up so this is a long ish post. Sorry! Also sorry about any syntax highlighting bugs. This is an experimental spec and I'm using nesting too, which might cause visual bugs with my syntax highlighter. This should resolve with time though. I hope. 13 - 14 - --- 15 - 16 - ## 1. What's in a function anyway? 17 - 18 - CSS has a bunch of functions (`rgb`, `anchor`, `blur`, and `var` to name a few), which are all free of side effects and consistent\*, but are fully defined in the spec, without any way for developers to specify their own functions. 19 - 20 - \*CSS random, as discussed in [this webkit post](https://webkit.org/blog/17285/rolling-the-dice-with-css-random/), isn't always consistent (it's a random function after all) however it is 1) not in anything except safari TP so I'm not gonna count it and 2) I Cant Find Any Actual Spec. So. also not gonna count it. 21 - 22 - Imagine this css: 23 - 24 - ```css 25 - h1 { 26 - font-size: 3em; 27 - 28 - @media (max-width: 1200px) { 29 - font-size: 2em; 30 - } 31 - @media (max-width: 600px) { 32 - font-size: 1em; 33 - } 34 - } 35 - 36 - img { 37 - width: 1000px; 38 - 39 - @media (max-width: 1200px) { 40 - width: 800px; 41 - } 42 - @media (max-width: 600px) { 43 - width: 450px; 44 - } 45 - } 46 - 47 - .screen-mode::after { 48 - content: "desktop"; 49 - 50 - @media (max-width: 1200px) { 51 - content: "tablet"; 52 - } 53 - @media (max-width: 600px) { 54 - content: "mobile"; 55 - } 56 - } 57 - ``` 58 - 59 - While this isn't the most realistic css (the font size probably doesn't need to change, the image could be more fluid with %/vw/vh/etc, and you would basically never need to do that with `::after`), it's useful for demonstration of a potentially useful function. 60 - 61 - Below we're going to start defining a function which will take in 1 to 3 parameters, and return values matching the media queries above (ie: if it matches 600px it'll return `--mobile`, falling back to `--tablet` if not defined, and falling back to `--desktop` if thats not defined, etc) It'll make more sense when we define it 62 - 63 - ```css 64 - @function --media(--desktop, --tablet, --mobile) { 65 - /* function body here */ 66 - } 67 - ``` 68 - 69 - This CSS defines a new function, which we could later use like `width: --media(1000px, 800px, 450px)`, however currently the arguments don't matter, and the result is the "guaranteed-invalid value" (same as if you use something like `var(--not-set)` without a fallback) and so won't work. 70 - 71 - For this to be useful, we need a `result`. `result` is a property which can be used within `@function` to define the output of the function. A simple negation function could look something like this: 72 - 73 - ```css 74 - @function --negate( 75 - --value type(<length> | <number> | <length-percentage>): initial 76 - ) { 77 - result: calc(-1 * var(--value)); 78 - } 79 - ``` 80 - 81 - But wait, I hear you ask, what does all that stuff after `--value` mean??? 82 - CSS functions let you define a type and default value for a function. I've used the type definition of `type(<length> | <number> | <length-percentage>)` to tell the browser that if you pass in a value that isn't either a length, number, or length percentage, then it should treat the value as invalid. (note: browser dev tools for this aren't the _best_ right now, but this will come with time) 83 - The `: initial` 84 - 85 - Going back to our `--negate` function, usage like `--negate(10px)` returns `-10px`, and `--negate(-5%)` returns `5%`, however something like `--negate(twenty)` wouldn't work, as `twenty` is not of type number, and even if we didn't have the type, `calc(-1 * twenty)` makes no sense, and would be invalid. 86 - 87 - So we can see that `result` simply defines the output for the function. This is great for making complex, repeated calculations more legible, and for repeating reused syntax (`result: 10px 10px 5px var(--colour, black)` could be used for a `--shadow` function), but doesn't solve our function, which does media query things. Thankfully, `@function` supports `@media` inside it (and some other @rules) 88 - 89 - ```css 90 - @function --media( 91 - --desktop, 92 - --tablet: var(--desktop), 93 - --mobile: var(--tablet) 94 - ) { 95 - result: var(--desktop); 96 - 97 - @media (max-width: 1200px) { 98 - result: var(--tablet); 99 - } 100 - @media (max-width: 600px) { 101 - result: var(--mobile); 102 - } 103 - } 104 - ``` 105 - 106 - This above code returns desktop, unless the screen is <1200px, in which case it returns tablet, and if the screen is <600px, it returns mobile. If mobile isn't defined, it's the same as tablet, and if tablet isn't defined, its the same as desktop. 107 - 108 - We can now replace our original example with an updated `--media()` function! 109 - 110 - ```css 111 - h1 { 112 - font-size: --media(3em, 2em, 1em); 113 - } 114 - 115 - img { 116 - width: --media(1000px, 800px, 450px); 117 - } 118 - 119 - .screen-mode::after { 120 - content: --media("desktop", "tablet", "mobile"); 121 - } 122 - ``` 123 - 124 - Another thing worth noting about `@function` is that it can access custom properties from the "calling scope": 125 - 126 - ```css 127 - @function --double--x() { 128 - result: calc(2 * var(--x)); 129 - } 130 - 131 - h1 { 132 - --x: 2em; 133 - font-size: --double--x(); 134 - } 135 - ``` 136 - 137 - Keep in mind that arguments "shadow" the custom properties. 138 - 139 - ```css 140 - @function --double--x(--x) { 141 - result: calc(2 * var(--x)); 142 - } 143 - 144 - h1 { 145 - --x: 2em; 146 - /* wont work because --x is not passed in */ 147 - font-size: --double--x(); 148 - } 149 - ``` 150 - 151 - If you want to be able to use custom properties when no argument is provided, you can set the default value to "inherit" 152 - 153 - ```css 154 - @function --double--x(--x: inherit) { 155 - result: calc(2 * var(--x)); 156 - } 157 - 158 - h1 { 159 - --x: 2em; 160 - /* works because --x is inherited from context */ 161 - font-size: --double--x(); 162 - } 163 - ``` 164 - 165 - As you can see; there's quite a lot to functions. If you want more specific and detailed information, or anything not explained here (like how to pass in comma seperated lists or more specific type syntax), your best bet is to reference the spec (and eventually MDN) and just experiment! 166 - 167 - ## Mixin? Mixin what? Mixin. Now. 168 - 169 - (I don't know what the title means and at this point I'm too afraid to ask [my brain]) 170 - 171 - As mixins are experimental and subject to change (and have no browser support yet) I'm not going to go into masses of detail like I did with `@function`, and instead just hit the highlights. 172 - Also these examples might be stupid I'm not justifying the feature its Fine 173 - 174 - ### Mixin Arguments 175 - 176 - The most basic mixin definition is like this: 177 - 178 - ```css 179 - @mixin --copy-paste() { 180 - /* properties go here */ 181 - } 182 - ``` 183 - 184 - `@mixin` is defined in basically the same way as `@function`: 185 - 186 - ```css 187 - @mixin --horrible( 188 - --background <color>: red, 189 - --accent <color>: blue, 190 - --scale <number>: 1 191 - ) { 192 - /* properties go here */ 193 - } 194 - ``` 195 - 196 - Unlike `@function`, mixin properties are exposed under `env()`, not `var()`, so theres no risk of conflict and the properties arent injected outside the body. If you want values to be able to be accessed from outsize the mixin, you can still use custom properties. 197 - 198 - Mixins can also accept blocks of properties as an argument: 199 - 200 - ```css 201 - @mixin --mobile(@contents) { 202 - /* properties go here */ 203 - } 204 - ``` 205 - 206 - And can accept both at the same time: 207 - 208 - ```css 209 - @mixin --weird(--bg: <color>, @contents) { 210 - /* properties go here */ 211 - } 212 - ``` 213 - 214 - ### Mixin Application 215 - 216 - When no args are passed/needed, you can do this to `@apply` a mixin: 217 - 218 - ```css 219 - body { 220 - @apply --copy-paste; 221 - } 222 - ``` 223 - 224 - Passing arguments is basically the same as custom functions: 225 - 226 - ```css 227 - body { 228 - @apply --horrible(orange, purple, 2); 229 - } 230 - ``` 231 - 232 - `@content` can be used like this: 233 - 234 - ```css 235 - body { 236 - @apply --mobile { 237 - background-color: red; 238 - } 239 - } 240 - ``` 241 - 242 - And you can use arguments and `@contents` together like this: 243 - 244 - ```css 245 - body { 246 - @apply --weird(red) { 247 - color: blue; 248 - } 249 - } 250 - ``` 251 - 252 - ### Mixin Bodies 253 - 254 - Mixin bodies are **_basically_** inserted wherever `@apply` is used. Just list the properties you want to include inside the mixin and they'll be inserted, including custom properties. 255 - 256 - You can access the arguments to the function via a dashed indent in `env()`: 257 - 258 - ```css 259 - @mixin --horrible( 260 - --background <color>: red, 261 - --accent <color>: blue, 262 - --scale <number>: 1 263 - ) { 264 - background-color: env(--background); 265 - color: env(--accent); 266 - border: calc(5px * env(--scale)) groove env(--accent); 267 - border-radius: 50%; 268 - float: right; 269 - &:hover { 270 - background-color: env(--accent); 271 - color: env(--background); 272 - border-color: env(--background); 273 - } 274 - } 275 - ``` 276 - 277 - You can insert whatever properties were passed into a mixin using the `@contents` at rule: 278 - 279 - ```css 280 - @mixin --mobile(@contents) { 281 - @media (max-width: 600px) { 282 - @contents; 283 - } 284 - } 285 - ``` 286 - 287 - You can also provide a default value for `@contents`: 288 - 289 - ```css 290 - @mixin --mobile(@contents) { 291 - @media (max-width: 600px) { 292 - @contents { 293 - &::before, 294 - &::after { 295 - display: block; 296 - background-color: red; 297 - color: black; 298 - contents: "Warning: Unused `@apply --mobile`. Include a declaration list"; 299 - } 300 - } 301 - } 302 - } 303 - ``` 304 - 305 - If no declaration list is passed to the mixin, the fallback will be used instead. 306 - 307 - In a mixin, if you use custom properties, they are inserted along with other properties. This is useful if you want values to be accessible to the user (ie: exposing a colour derived from input for use elsewhere), but also pollutes the namespace. As such, you should avoid using custom properties when you don't explicitly want the user to read/override things. As such, use `@env` to define environment variables scoped to the mixin body. 308 - 309 - ```css 310 - @mixin --mix-colour(--col1, --col2) { 311 - @env --mix: color-mix(in oklab, env(--col1), env(--col2)); 312 - color: env(--mix); 313 - } 314 - ``` 315 - 316 - In this example `env(--mix)` is only avaliable inside the `--mix-colour` body, and doesnt pollute the calling context. 317 - 318 - Thats about the gist on mixins, its very new and experimental and has 0 implementation so go read the spec yourself lol 319 - 320 - ## Listen to me speak now please thank you 321 - 322 - First note: I think these are really good so far, maybe some slight tweaks needed for mixins. I will say that with mixins I'm not the BIGGEST fan of using `env()`, but if I remember correctly it originally started with an `@result` at rule or something like that, so I'm pretty sure theres a reason we got an `@env` etc instead. That said I dont really mind `env()` to much so its Fine lmao. 323 - 324 - I also think its worth considering named `@contents` blocks instead, maybe something like this: 325 - 326 - ```css 327 - @mixin --media(--desktop @contents, --mobile @contents) { 328 - @media not (max-width: 600px) { 329 - @contents --desktop { 330 - desktop-fallback: here; 331 - } 332 - } 333 - @media (max-width: 600px) { 334 - @contents --mobile { 335 - mobile-fallback: here; 336 - } 337 - } 338 - } 339 - 340 - body { 341 - @apply --media() { 342 - desktop-properties: here; 343 - } { 344 - mobile-properties: here; 345 - } 346 - } 347 - } 348 - ``` 349 - 350 - The current syntax of having a single trailing `@contents` and single trailing `{/*properties*/}` for cases where only one `@contents` is needed. This might need some tweaking for legibility etc, but some way to add multiple `@contents` blocks would be nice. I agree with the enforcing of them being at the end of the argument list though. 351 - 352 - Another suggestion, which may be defered to level 2: expose functions to CSS houdini. 353 - 354 - For example, something like this: 355 - 356 - ```js 357 - // index.js 358 - CSS.functions.addModule("css-arrays.js"); 359 - ``` 360 - 361 - ```js 362 - // css-arrays.js 363 - registerFunction( 364 - "--get", 365 - class { 366 - static get arguments() { 367 - return [ 368 - { 369 - type: "<string>#", 370 - }, 371 - { 372 - type: "<number>", 373 - default: 0, 374 - }, 375 - ]; 376 - } 377 - 378 - eval(array, index) { 379 - return array[index]; 380 - } 381 - }, 382 - ); 383 - ``` 384 - 385 - `css-arrays.js` would run in a custom Worklet environment, most likely a plain ECMAScript environment with no APIs, which may be created and destroyed on each call. It wouldn't open the door to advanced functionality like `--anchor`, but could make "simpler" functions ponyfillable, like arrays/objects, or even things like `color-mix`. 386 - 387 - This is NOT a formal proposal, just a suggestion. Might make an issue in the repo later if I can be bothered. 388 - 389 - --- 390 - 391 - Anyway, to conclude: I'm extremely happy with the reccomended API right now, and I would be happy to see this or something very similar land in browsers. Also let us do functions with JS it would be v good for ponyfilling.
-274
src/content/blog/pds-on-a-pi.md
··· 1 - --- 2 - title: PDS on a pi 3 - bio: installing a pds on my raspberry pi; Photo by Ritam Baishya on Unsplash 4 - banner: blue-skies.png 5 - pub: 2025-09-13 6 - --- 7 - 8 - I want to self host my own pds for atproto, but I wanna host it on my own hardware in my room, since that feels fun and whimsical. I've got a pi 5 sat on my floor which I'm going to use for this, and then I'll route it out of my vps using tailscale and caddy. Currently the pi doesn't have ethernet or constant power (i attached a screen to it and forgot how to take it off so i turn it off at night lmfao) so I'm going to create a test account (at://test.vielle.dev) and use that for now. This'll also be a chance to create a did:web account to mess with. 9 - 10 - > _Note_: I'm writing this blog post while I do it so its going to be messy 11 - 12 - The plan is to have all my services running on docker compose, which then can be accessed by using tailscale on the pi host. This then goes into tailscale on the vps, which goes into caddy, which goes out to the net. Little complex but should work. Heres a graph 13 - 14 - <style> 15 - /* select all images who's alt text starts with "Traffic from my docker containers" */ 16 - img[alt^="Traffic from my docker containers"] { 17 - image-rendering: auto; 18 - } 19 - </style> 20 - 21 - ![Traffic from my docker containers in my pi go to tailscale on the pi. This goes to tailscale on the vps. This + other docker containers go into a caddy docker container, which goes into the outside internet](assets/pds-pi-graph.png) 22 - 23 - ## 1. Get a dummy service on the pi 24 - 25 - I'm gonna get a dummy ping/pong https thing on the pi which i can test forwarding. Presumably if this works, then the PDS will work too when I add it. 26 - 27 - `ping-pong/main.ts` 28 - 29 - ```ts 30 - // using Deno 31 - // new http server on 0.0.0.0:8000 which just sends "Hello" 32 - Deno.serve({ port: 8000, hostname: "0.0.0.0" }, (req) => { 33 - return new Response("Hello! " + req.url); 34 - }); 35 - ``` 36 - 37 - `ping-pong/Dockerfile` 38 - 39 - ```Dockerfile 40 - FROM denoland/deno:latest 41 - WORKDIR /app 42 - COPY . . 43 - CMD ["deno", "run", "--allow-net", "main.ts"] 44 - ``` 45 - 46 - `compose.yml` 47 - 48 - ```yaml 49 - services: 50 - pingpong: 51 - build: ./ping-pong 52 - restart: unless-stopped 53 - ports: 54 - - 8000:8000 55 - ``` 56 - 57 - It works, so now I'm going to add a caddy rule to route port 8000 of my pi (`http://pi:8000`) to `https://pds.vielle.dev:443`. 58 - 59 - ## 2. Routing traffic from vps -> pi 60 - 61 - All I need to do is add this code to my Caddyfile and run it locally to test. 62 - 63 - ```caddyfile 64 - pds.{$HOST:localhost} { 65 - reverse_proxy pi:8000 66 - } 67 - ``` 68 - 69 - Once I'm ready to deploy, this SHOULD just be a matter of pushing the commit to master and assuming my shitty cicd works it'll be deployed, along with this post! 70 - 71 - ## 3. Installing the pds in the container. 72 - 73 - For this one, we're gonna look at the pds setup from <https://github.com/bluesky-social/pds/>. This has 3 parts: 74 - 75 - - A caddy container 76 - - The pds 77 - - Watchtower 78 - 79 - ### 3.1. Caddyfile 80 - 81 - Starting with the caddy container, let's just make sure our vps has anything in the caddy config its missing. 82 - The config is below, [found here](https://github.com/bluesky-social/pds/blob/00078b4658def4eb419efab717fa970d01fce045/installer.sh#L302) 83 - 84 - ```Caddyfile 85 - { 86 - email ${PDS_ADMIN_EMAIL} 87 - on_demand_tls { 88 - ask http://localhost:3000/tls-check 89 - } 90 - } 91 - 92 - *.${PDS_HOSTNAME}, ${PDS_HOSTNAME} { 93 - tls { 94 - on_demand 95 - } 96 - reverse_proxy http://localhost:3000 97 - } 98 - ``` 99 - 100 - This is using global config for an email address, which is set further up the script, but I'll configure with environment variables, and for on demand tls which is on the pds. This means the pds can decide which subdomains get tls, with any level of wildcarding. I don't plan on using on demand tls for anything else on my site right now, but since it can't be scoped I might need to make a custom handler myself. 101 - 102 - Anyway heres the updated caddyfile config: 103 - 104 - ```caddyfile 105 - { 106 - email {$PDS_ADMIN_EMAIL:404@vielle.dev} 107 - on_demand_tls { 108 - ask pi:8000/tls-check 109 - } 110 - } 111 - 112 - # ... 113 - 114 - *.pds.{$HOST:localhost}, pds.{$HOST:localhost} { 115 - tls { 116 - on_demand 117 - } 118 - reverse_proxy pi:8000 119 - } 120 - ``` 121 - 122 - This refuses to connect but I'm going to assume its because the on demand tls is failing so theres just no cert which I can tell firefox to accept. 123 - 124 - ### 3.2. Watchtower 125 - 126 - Googling it, watchtower seems to be a way to automatically update containers? 127 - I'm just going to add it straight into the compose file lmao 128 - 129 - ```yaml 130 - services: 131 - pingpong: 132 - build: ./ping-pong 133 - restart: unless-stopped 134 - ports: 135 - - 8000:8000 136 - 137 - watchtower: 138 - container_name: watchtower 139 - image: containrrr/watchtower:latest 140 - network_mode: host 141 - volumes: 142 - - type: bind 143 - source: /var/run/docker.sock 144 - target: /var/run/docker.sock 145 - restart: unless-stopped 146 - environment: 147 - WATCHTOWER_CLEANUP: true 148 - WATCHTOWER_SCHEDULE: "@midnight" 149 - ``` 150 - 151 - ### 3.3. The PDS 152 - 153 - The reference compose file configures the pds like this: 154 - 155 - ```yaml 156 - pds: 157 - container_name: pds 158 - image: ghcr.io/bluesky-social/pds:0.4 159 - network_mode: host 160 - restart: unless-stopped 161 - volumes: 162 - - type: bind 163 - source: /pds 164 - target: /pds 165 - env_file: 166 - - /pds/pds.env 167 - ``` 168 - 169 - This is self explanatory; we make a pds directory, bind it to /pds, and make sure theres at least a pds.env file in there, which is the only file we need, based on installer.sh 170 - 171 - In installer.sh, they generate the env file like so: 172 - 173 - ```bash 174 - cat <<PDS_CONFIG >"${PDS_DATADIR}/pds.env" 175 - PDS_HOSTNAME=${PDS_HOSTNAME} 176 - PDS_JWT_SECRET=$(eval "${GENERATE_SECURE_SECRET_CMD}") 177 - PDS_ADMIN_PASSWORD=${PDS_ADMIN_PASSWORD} 178 - PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX=$(eval "${GENERATE_K256_PRIVATE_KEY_CMD}") 179 - PDS_DATA_DIRECTORY=${PDS_DATADIR} 180 - PDS_BLOBSTORE_DISK_LOCATION=${PDS_DATADIR}/blocks 181 - PDS_BLOB_UPLOAD_LIMIT=52428800 182 - PDS_DID_PLC_URL=${PDS_DID_PLC_URL} 183 - PDS_BSKY_APP_VIEW_URL=${PDS_BSKY_APP_VIEW_URL} 184 - PDS_BSKY_APP_VIEW_DID=${PDS_BSKY_APP_VIEW_DID} 185 - PDS_REPORT_SERVICE_URL=${PDS_REPORT_SERVICE_URL} 186 - PDS_REPORT_SERVICE_DID=${PDS_REPORT_SERVICE_DID} 187 - PDS_CRAWLERS=${PDS_CRAWLERS} 188 - LOG_ENABLED=true 189 - PDS_CONFIG 190 - ``` 191 - 192 - Lets write our own pds.env file first: 193 - 194 - - PDS_HOSTNAME is just `pds.vielle.dev` 195 - - PDS_JWT_SECRET is just `openssl rand --hex 16` 196 - - PDS_ADMIN_PASSWORD is also just `openssl rand --hex 16`, but must be different 197 - - PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX is `openssl ecparam --name secp256k1 --genkey --noout --outform DER | tail --bytes=+8 | head --bytes=32 | xxd --plain --cols 32` 198 - - PDS_DATA_DIRECTORY is PDS_DATADIR, which is hardcoded to `/pds` in the shell. Since this is currrently hardcoded to `/pds`, we can hardcode it 199 - - PDS_BLOBSTORE_DISK_LOCATION is PDS_DATADIR/blocks, so `/pds/blocks` 200 - - PDS_BLOB_UPLOAD_LIMIT is set to `52428800` 201 - - PDS_DID_PLC_URL is `https://plc.directory` 202 - - PDS_BSKY_APP_VIEW_URL is `https://api.bsky.app` 203 - - PDS_BSKY_APP_VIEW_DID is `did:web:api.bsky.app` 204 - - PDS_REPORT_SERVICE_URL is `https://mod.bsky.app` 205 - - PDS_REPORT_SERVICE_DID is `did:plc:ar7c4by46qjdydhdevvrndac` 206 - - PDS_CRAWLERS is `https://bsky.network`, but I'll expand this to include things like <https://atproto.africa/> & bad example's EU relays 207 - - LOG_ENABLED is `true` 208 - 209 - So to generate all this, I'm just going to run 210 - 211 - ```sh 212 - mkdir ./pds 213 - cat <<EOF > ./pds/pds.env 214 - PDS_HOSTNAME=pds.vielle.dev 215 - PDS_JWT_SECRET=$(eval "openssl rand --hex 16") 216 - PDS_ADMIN_PASSWORD=$(eval "openssl rand --hex 16") 217 - PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX=$(eval "openssl ecparam --name secp256k1 --genkey --noout --outform DER | tail --bytes=+8 | head --bytes=32 | xxd --plain --cols 32") 218 - PDS_DATA_DIRECTORY=./pds # edit: change this to /pds (see below) 219 - PDS_BLOBSTORE_DISK_LOCATION=./pds/blocks # edit: change this to /pds/blocks (see below) 220 - PDS_BLOB_UPLOAD_LIMIT=52428800 221 - PDS_DID_PLC_URL=https://plc.directory 222 - PDS_BSKY_APP_VIEW_URL=https://api.bsky.app 223 - PDS_BSKY_APP_VIEW_DID=did:web:api.bsky.app 224 - PDS_REPORT_SERVICE_URL=https://mod.bsky.app 225 - PDS_REPORT_SERVICE_DID=did:plc:ar7c4by46qjdydhdevvrndac 226 - PDS_CRAWLERS=https://bsky.network,https://atproto.africa,https://relay1.us-east.bsky.network,https://relay.fire.hose.cam,https://relay3.fr.hose.cam,https://relay.hayescmd.net,https://relay.xero.systems 227 - LOG_ENABLED=true 228 - EOF 229 - ``` 230 - 231 - Pretty much everythings set up for a pds now, last step is to configure pds in the compose file and it should be online ! 232 - 233 - Just got to add this to my compose file and it should all work! 234 - 235 - ```yaml 236 - pds: 237 - container_name: pds 238 - image: ghcr.io/bluesky-social/pds:0.4 239 - restart: unless-stopped 240 - # removed network_mode: host since it should still work without it 241 - # and instead bound port 3000 of container to 8000 of host 242 - ports: 243 - - 8000:3000 244 - volumes: 245 - - type: bind 246 - # source is relative 247 - source: ./pds 248 - target: /pds 249 - # env is relative 250 - env_file: 251 - - ./pds/pds.env 252 - ``` 253 - 254 - Ok. So. Seems i didn't configure it correctly: `Error: Must configure plc rotation key`. I was missing the `xxd` command and somehow missed that? A simple `sudo apt-get install xxd` should fix things. Running the env command again gives an error that the directory for the database doesnt exist !! How Fun !! 255 - 256 - The issue was that i had `./pds` in the environment variables, (which were used inside the container), when the container used `/pds` as the datadir. Simple fix, and now it all works!! 257 - 258 - ## Next steps: 259 - 260 - Deploy this post + caddy changes, create a test account or two, find a permanent setup for the pi, and setup regular backups of the pds; then migrate to it myself!! 261 - 262 - ## Update (17/09/25) 263 - 264 - Required changes to get this properly working: 265 - 266 - - Tailscale doesn't let you do subdomains so I needed to do some rewrites on the url + modifying the default image to allow for handle resolution (see: [@vielle.dev/server-config](https://tangled.sh/@vielle.dev/server-config/blob/master/caddy/Caddyfile#:~:text=rewrite%20/.well-known/atproto-did%20/.well-known/atproto-did/{http.request.host}) and [@vielle.dev/pi-config](<https://tangled.sh/@vielle.dev/pi-config/blob/main/pds/service/index.js#:~:text=async%20function%20customDidRoute(/**%20@type%20{PDS}%20*/%20pds,/**%20@type%20{import('express').Request}%20*/%20req,/**%20@type%20{import('express').Response}%20*/%20res)%20{const%20handle%20=%20req.params.handle;const%20supportedHandle%20=%20pds.ctx.cfg.identity.serviceHandleDomains.some((host)%20=%3E%20handle.endsWith(host)%20||%20handle%20===%20host.slice(1));if%20(!supportedHandle)%20{return%20res.status(404).send(%22User%20not%20found%22);}let%20did;try%20{const%20user%20=%20await%20pds.ctx.accountManager.getAccount(handle);did%20=%20user?.did;}%20catch%20(err)%20{return%20res.status(500).send(%22Internal%20Server%20Error%22);}if%20(!did)%20{return%20res.status(404).send(%22User%20not%20found%22);}res.type(%22text/plain%22).send(did);}>)) 267 - - Tailscale magicDNS is slow so you need to use 100.x.y.z ip addresses 268 - - Probably smart to up the timeout for reverse proxy (I did 3s -> 5s) 269 - - You need to symlink ./pds to /pds to make pdsadmin.sh work properly 270 - 271 - Other notes: 272 - 273 - - Handles like `test.{domain}` dont work because of a reserved list which is hardcoded on in the official pds package. You need to patch or fork it to override it afaict. 274 - - Configure `PDS_PRIMARY_COLOR` for custom theming (ex: `PDS_PRIMARY_COLOR="#008282"`) and `PDS_OAUTH_PROVIDER_NAME` for a custom name somewhere, idk where
-14
src/content/config.ts
··· 1 - import { defineCollection, z } from "astro:content"; 2 - import { glob } from "astro/loaders"; 3 - 4 - const blog = defineCollection({ 5 - loader: glob({ pattern: "**/*.md", base: "./src/content/blog" }), 6 - schema: z.object({ 7 - title: z.string(), 8 - bio: z.string(), 9 - banner: z.string().endsWith(".png"), 10 - pub: z.date(), 11 - }), 12 - }); 13 - 14 - export const collections = { blog };
+1 -1
src/pages/_callback.astro
··· 37 37 .catch((err) => console.error(err)); 38 38 } 39 39 40 - const href = `https://accounts.spotify.com/authorize?response_type=code&client_id=${SPOTIFY_CLIENT_ID}&scope=user-read-currently-playing user-top-read&redirect_uri=${SPOTIFY_REDIRECT_URI}`; 40 + const href = `https://accounts.spotify.com/authorize?response_type=code&client_id=${SPOTIFY_CLIENT_ID}&scope=user-read-currently-playing&redirect_uri=${SPOTIFY_REDIRECT_URI}`; 41 41 --- 42 42 43 43 <p>
-19
src/pages/ai.md
··· 1 - --- 2 - layout: /components/Markdown.astro 3 - title: AI Manifesto 4 - --- 5 - 6 - All the code and content I have written for this site was written by me without the use of generative AI. Any images on this site were either created by me or given attribution on the site. 7 - 8 - With regards specifically to generative AI for programming (although much of this extends to genAI for art, music, writing, etc) I currently refuse to use it due to: 9 - - The environmental impact of training the AI model. 10 - - Profit off free and paid work without attribution and compensation. 11 - - Impact of the AI hype cycle on labour in tech. 12 - - Increased reliance on large corporate third party entities. 13 - 14 - I will not use AI to intentionally cause harm to another person or living entity. 15 - 16 - --- 17 - 18 - This is my [`/ai`](https://www.bydamo.la/p/ai-manifesto) page. 19 -
+2 -106
src/pages/blog/[...slug].astro
··· 1 1 --- 2 - import { getCollection } from "astro:content"; 3 2 import Base from "/components/Base.astro"; 4 - import { render } from "astro:content"; 5 - 6 - import Box4x3Mask from "/assets/box-4x3-mask.png"; 7 - import Hr from "/assets/hr.png"; 8 - 9 - import "/components/markdown.css"; 10 - 11 - export async function getStaticPaths() { 12 - return await Promise.all( 13 - await getCollection("blog").then((posts) => 14 - posts.map(async (post) => ({ 15 - params: { slug: post.id }, 16 - props: { 17 - post, 18 - banner: await import( 19 - `../../content/blog/assets/${post.data.banner.replace(".png", "")}.png` 20 - ).then(({ default: img }) => img.src as string), 21 - }, 22 - })), 23 - ), 24 - ); 25 - } 26 - 27 - const { post, banner } = Astro.props; 28 - const { Content } = await render(post); 29 3 --- 30 4 31 - <Base 32 - title={post.data.title} 33 - graph={{ 34 - description: post.data.bio, 35 - url: Astro.url.toString(), 36 - type: "article", 37 - image: banner, 38 - }} 39 - > 40 - <article> 41 - <header 42 - style={` 43 - --box-4x3-mask-png: url(${Box4x3Mask.src}); 44 - `} 45 - > 46 - <img src={banner} alt="" /> 47 - <div class="header"> 48 - <h1>{post.data.title}</h1> 49 - <p>{post.data.bio}</p> 50 - <time 51 - datetime={`${post.data.pub.getFullYear()}-${post.data.pub.getMonth() + 1}-${post.data.pub.getDate()}`} 52 - > 53 - {post.data.pub.getDate()}-{post.data.pub.getMonth() + 1}-{ 54 - post.data.pub.getFullYear() 55 - } 56 - </time> 57 - </div> 58 - </header> 59 - 60 - <hr style={`--hr-png: url(${Hr.src});`} /> 61 - 62 - <div class="markdown-style"> 63 - <Content /> 64 - </div> 65 - </article> 5 + <Base> 6 + <h1>vielle.dev</h1> 66 7 </Base> 67 - 68 - <style> 69 - header { 70 - max-width: 60ch; 71 - padding: 10px; 72 - margin: auto; 73 - 74 - position: relative; 75 - } 76 - 77 - .header { 78 - /* just use old layout on mobile 79 - it works there */ 80 - @media not (max-width: 60ch) { 81 - position: absolute; 82 - inset: auto 50px 0; 83 - 84 - background-image: var(--box-4x3-mask-png); 85 - background-size: 100% 100%; 86 - padding: 20px; 87 - } 88 - } 89 - 90 - img { 91 - width: 100%; 92 - aspect-ratio: 4/3; 93 - object-fit: cover; 94 - mask-image: var(--box-4x3-mask-png); 95 - mask-size: 100%; 96 - } 97 - 98 - time { 99 - color: #000000b0; 100 - } 101 - 102 - hr { 103 - margin-block: 5px; 104 - height: 5px; 105 - border: none; 106 - border-image: var(--hr-png) 0 5 fill / 0 5px round; 107 - width: 100%; 108 - max-width: 70ch; 109 - margin-inline: auto; 110 - } 111 - </style>
+1 -23
src/pages/blog/index.astro
··· 1 1 --- 2 2 import Base from "/components/Base.astro"; 3 - import Blog from "/components/home/Blog.astro"; 4 3 --- 5 4 6 5 <Base> 7 - <main> 8 - <Blog heading="h1" /> 9 - </main> 6 + <h1>vielle.dev</h1> 10 7 </Base> 11 - 12 - <style is:global> 13 - main { 14 - max-width: 40ch; 15 - margin: auto; 16 - } 17 - 18 - .blog { 19 - contain: none !important; 20 - 21 - h1 { 22 - margin-block-end: 10px; 23 - } 24 - 25 - article { 26 - margin-block-end: 5px; 27 - } 28 - } 29 - </style>
+19 -36
src/pages/index.astro
··· 1 1 --- 2 - export const prerender = false; 3 - 4 2 import Base from "/components/Base.astro"; 5 - import Blog from "/components/home/Blog.astro"; 6 - import Feed from "/components/home/feeds/Feed.astro"; 3 + import Feeds from "/components/home/feeds/Feeds.astro"; 7 4 import Landing from "/components/home/Landing.astro"; 8 5 import NowPlaying from "/components/home/playing/NowPlaying.astro"; 9 - // start the sdk setup while other components and requests are ongoing 10 - // so that the sdk is ready or closer to being ready when needed 11 - import { sdk } from "/components/home/playing/spotify"; 12 - // prevent treeshaking 13 - sdk; 14 6 --- 15 7 16 - <Base 17 - graph={{ 18 - description: "My website!", 19 - url: "https://vielle.dev/", 20 - }} 21 - > 8 + <Base> 22 9 <main> 23 10 <!-- landing --> 24 11 <Landing /> 25 12 <!-- now playing --> 26 13 <NowPlaying /> 27 14 <!-- feeds --> 28 - <Feed /> 15 + <Feeds /> 29 16 <!-- blog --> 30 - <Blog /> 17 + <section class="blog">blog</section> 31 18 </main> 32 19 33 20 <style> 34 21 :global(body) { 35 - display: grid; 36 - grid-template: "header" auto "main" 1fr / 1fr; 22 + display: flex; 23 + flex-direction: column; 37 24 width: 100%; 38 - 39 - > :global(header) { 40 - grid-area: header; 41 - } 42 - 43 - > main { 44 - grid-area: main; 45 - } 46 25 } 47 26 48 27 main { 49 28 display: grid; 50 29 grid-template: 51 - ". landing feed blog ." min-content 52 - ". playing feed blog ." 1fr 53 - / auto minmax(25ch, 50ch) 40ch 30ch auto; 30 + ". landing feeds blog ." min-content 31 + ". playing feeds blog ." 1fr 32 + / auto minmax(30ch, 50ch) minmax(30ch, 50ch) minmax(30ch, 50ch) auto; 54 33 max-width: 100%; 55 - gap: 20px; 34 + flex: 2; 56 35 57 - @media (max-width: 110ch) { 36 + @media (max-width: 90ch) { 58 37 grid-template: 59 38 ". landing ." min-content 60 - "playing playing playing" min-content 61 - ". feed ." 1fr 39 + ". playing ." min-content 40 + ". feeds ." 1fr 62 41 / auto minmax(30ch, 50ch) auto; 63 42 64 43 & :global(.blog) { ··· 66 45 } 67 46 } 68 47 48 + & :global(section) { 49 + border: 1px solid red; 50 + } 51 + 69 52 & :global(.landing) { 70 53 grid-area: landing; 71 54 } ··· 74 57 grid-area: playing; 75 58 } 76 59 77 - & :global(.feed) { 78 - grid-area: feed; 60 + & :global(.feeds) { 61 + grid-area: feeds; 79 62 } 80 63 81 64 & :global(.blog) {
+1 -3
src/pages/now-playing-sse.ts
··· 1 1 import { sdk } from "/components/home/playing/spotify"; 2 2 import type { nowPlaying } from "/components/home/playing/spotify/client"; 3 3 4 - export const prerender = false; 5 - 6 4 export async function GET() { 7 5 const update = async (): Promise<string> => { 8 6 // extract a subset to reduce size for client ··· 46 44 console.error("/now-playing-sse", "GOT ERROR:", err); 47 45 }); 48 46 await new Promise((res, rej) => { 49 - setTimeout(res, 20 * 1000); 47 + setTimeout(res, 5000); 50 48 abort.signal.addEventListener("abort", rej); 51 49 }); 52 50 }
-236
src/pages/rss.style.xml.ts
··· 1 - import BoxTlbr from "/assets/box-tlbr.png"; 2 - import Box4x3Mask from "/assets/box-4x3-mask.png"; 3 - import { experimental_AstroContainer } from "astro/container"; 4 - import Header from "/components/Header.astro"; 5 - 6 - const header = await experimental_AstroContainer 7 - .create() 8 - .then((x) => x.renderToString(Header)) 9 - .then((x) => 10 - // match data-astro-cid attributes where there no value 11 - // this is because xml hates boolean attributes for some reason. :( 12 - x.replaceAll(/data-astro-cid-[a-zA-Z0-9]*(?!=["'])/gm, (m) => m + '=""'), 13 - ) 14 - .then((x) => 15 - // match wbr tags (with data astro cid) and close em 16 - x.replaceAll(/<wbr data-astro-cid-[a-zA-Z0-9]*="">/gm, (m) => m + "</wbr>"), 17 - ); 18 - 19 - export async function GET() { 20 - return new Response( 21 - ` 22 - <!DOCTYPE XSL [ <!ENTITY shy "ยญ"> ]> 23 - <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 24 - <xsl:output method="html" /> 25 - 26 - <xsl:template match="/"> 27 - <html lang="en"> 28 - <head> 29 - <title>RSS | vielle.dev</title> 30 - <style> 31 - :root { 32 - font-family: sans-serif; 33 - interpolate-size: allow-keywords; 34 - image-rendering: pixelated; 35 - } 36 - 37 - * { 38 - margin: 0; 39 - padding: 0; 40 - } 41 - 42 - html, 43 - body { 44 - min-width: 30ch; 45 - } 46 - 47 - .blog { 48 - width: 30ch; 49 - margin: auto; 50 - } 51 - 52 - .intro { 53 - max-width: 60ch; 54 - padding-inline: 20px; 55 - margin: 20px auto; 56 - } 57 - 58 - img, 59 - svg, 60 - iframe, 61 - audio, 62 - video { 63 - max-width: 100%; 64 - display: block; 65 - } 66 - 67 - .post { 68 - border-image: url("${BoxTlbr.src}") 10 10 fill / 20px 20px round; 69 - padding: 30px; 70 - } 71 - 72 - img { 73 - width: 100%; 74 - aspect-ratio: 4/3; 75 - object-fit: cover; 76 - mask-image: url("${Box4x3Mask.src}"); 77 - mask-size: 100%; 78 - } 79 - 80 - a { 81 - color: black; 82 - text-decoration-line: none; 83 - } 84 - 85 - a:hover, 86 - a:focus, 87 - a:active { 88 - text-decoration-line: underline; 89 - } 90 - 91 - a:active { 92 - text-decoration-style: dashed; 93 - } 94 - 95 - /* from Header.astro */ 96 - header { 97 - border-image: var(--box-blr-png) 10 fill / 20px / 20px round; 98 - margin: 0 20px 20px; 99 - padding: 10px 20px; 100 - height: 3rem; /* 2rem * 1.5 */ 101 - /* render over feed bg */ 102 - z-index: 2; 103 - 104 - display: flex; 105 - flex-direction: row; 106 - justify-content: space-between; 107 - align-items: center; 108 - 109 - @media (max-width: 650px) { 110 - flex-direction: column; 111 - align-items: start; 112 - height: 4.5rem; /* (2rem + 1rem) * 1.5 */ 113 - 114 - nav { 115 - margin-inline: auto; 116 - contain: inline-size; 117 - width: 100%; 118 - overflow: auto; 119 - scrollbar-width: thin; 120 - } 121 - 122 - h1 { 123 - width: 100%; 124 - text-align: center; 125 - } 126 - } 127 - 128 - &amp; > nav > ul { 129 - display: flex; 130 - flex-direction: row; 131 - align-items: center; 132 - justify-content: start; 133 - gap: 10px; 134 - z-index: 999; 135 - width: fit-content; 136 - margin-inline: auto; 137 - 138 - &amp; > li { 139 - display: flex; 140 - flex-direction: row; 141 - align-items: center; 142 - gap: 10px; 143 - 144 - &amp;::marker { 145 - content: none; 146 - } 147 - 148 - &amp; + &amp;::before { 149 - content: ""; 150 - background-image: var(--dot-png); 151 - background-size: contain; 152 - width: 9px; 153 - height: 9px; 154 - display: block; 155 - } 156 - } 157 - } 158 - } 159 - 160 - nav > ul > li:last-child > details > ul { 161 - right: 10px; 162 - } 163 - 164 - details { 165 - summary { 166 - cursor: pointer; 167 - text-wrap: nowrap; 168 - } 169 - 170 - &amp; > ul { 171 - position: absolute; 172 - z-index: 99999; 173 - 174 - @media (max-width: 650px) { 175 - inset: auto 15px; 176 - } 177 - 178 - margin-top: 10px; 179 - padding: 20px; 180 - padding-left: 40px; 181 - &amp; ul { 182 - margin-left: 10px; 183 - } 184 - 185 - border-image: var(--box-tlbr-png) 10 fill / 20px round; 186 - } 187 - } 188 - 189 - header h1 { 190 - margin-block: 0; 191 - position: sticky; 192 - inset: 0; 193 - } 194 - </style> 195 - </head> 196 - 197 - <body> 198 - ${header} 199 - <section class="intro"> 200 - <h1>Blog Posts</h1> 201 - <p>If you want to use this page in your RSS reader, simply paste this page's URL in and it'll just work. To view the original RSS, view the page source. The styling of this page is made possible by <a href="https://developer.mozilla.org/en-US/docs/Web/XML/XSLT" target="_blank">XSLT</a></p> 202 - </section> 203 - <section class="blog"> 204 - <xsl:for-each select="/rss/channel/item"> 205 - <a target="_blank"> 206 - <xsl:attribute name="href"> 207 - <xsl:value-of select="link" /> 208 - </xsl:attribute> 209 - <article class="post"> 210 - 211 - <img alt=""> 212 - <xsl:attribute name="src"> 213 - <xsl:value-of select="image" /> 214 - </xsl:attribute> 215 - </img> 216 - 217 - <h2 class="title"><xsl:value-of select="title" /></h2> 218 - <div class="bio"><xsl:value-of select="description" /></div> 219 - <time><xsl:value-of select="pubDate" /></time> 220 - 221 - </article> 222 - </a> 223 - </xsl:for-each> 224 - </section> 225 - </body> 226 - </html> 227 - </xsl:template> 228 - </xsl:stylesheet> 229 - `, 230 - { 231 - headers: { 232 - "Content-Type": "text/xml", 233 - }, 234 - }, 235 - ); 236 - }
+7 -60
src/pages/rss.xml.ts
··· 1 - import { getCollection } from "astro:content"; 2 - import { getRssString } from "@astrojs/rss"; 3 - import type { APIRoute, ImageMetadata } from "astro"; 4 - import { experimental_AstroContainer } from "astro/container"; 5 - 6 - const container = await experimental_AstroContainer.create(); 7 - 8 - const postBodies = import.meta.glob("../content/blog/**/*.md"); 9 - console.log("postBodies", postBodies); 10 - 11 - export const GET: APIRoute = async ({ site }) => { 12 - const posts = await getCollection("blog"); 13 - 14 - const rss = await getRssString({ 15 - title: "vielle.dev", 16 - description: "Posts from vielle.dev", 17 - site: site?.toString() ?? "", 18 - items: await Promise.all( 19 - posts.map(async (post) => { 20 - const res = { 21 - title: post.data.title, 22 - description: post.data.bio, 23 - pubDate: post.data.pub, 24 - link: `/blog/${post.id}/`, 25 - customData: await import( 26 - `../content/blog/assets/${post.data.banner.replace(".png", "")}.png` 27 - ).then( 28 - ({ default: img }: { default: ImageMetadata }) => 29 - // custom image component for the xslt transform 30 - `<image>${img.src}</image>`, 31 - ), 32 - }; 33 - 34 - if (post.filePath) { 35 - const { default: Content } = (await postBodies[ 36 - `../content/blog/${post.id}.md` 37 - ]()) as any; 38 - const content = await container.renderToString(Content); 39 - 40 - return { 41 - ...res, 42 - content: content, 43 - }; 44 - } else return res; 45 - }), 46 - ), 47 - }); 48 - 49 - return new Response( 50 - rss.replace( 51 - '<?xml version="1.0" encoding="UTF-8"?>', 52 - '<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet href="/rss.style.xml" type="text/xsl" ?>', 53 - ), 54 - { 55 - headers: { 56 - "Content-Type": "application/xml", 57 - }, 58 - }, 59 - ); 60 - }; 1 + export function GET( 2 + { 3 + // params, request 4 + }, 5 + ) { 6 + return new Response(`RSS Feed!`); 7 + }
+7
src/pages/use.astro
··· 1 + --- 2 + import Base from "/components/Base.astro"; 3 + --- 4 + 5 + <Base> 6 + <h1>vielle.dev</h1> 7 + </Base>
-30
src/pages/use.md
··· 1 - --- 2 - layout: /components/Markdown.astro 3 - title: Things I Use 4 - --- 5 - 6 - - Editor 7 - - [VS Code](https://code.visualstudio.com/) 8 - - [Catppuccin Frappรฉ](https://catppuccin.com/) 9 - - [Monaspace Neon](https://monaspace.githubnext.com/) 10 - 11 - - Terminal 12 - - [Konsole](https://konsole.kde.org/) 13 - - [Oh My Zsh](https://ohmyz.sh/) 14 - - [Scientifica](https://github.com/oppiliappan/scientifica) 15 - 16 - - Apps 17 - - [Firefox Nightly](https://www.firefox.com/en-US/channel/desktop/) 18 - - [Obsidian](https://obsidian.md/) for writing D&D notes/planning 19 - - [Syncthing](https://syncthing.net/) for syncing files and notes across my devices 20 - 21 - - OS 22 - - PC 23 - - [Arch Linux](https://archlinux.org/) 24 - - [KDE Plasma](https://kde.org/plasma-desktop/) 25 - - Laptop 26 - - [NixOS](https://nixos.org/) 27 - - [KDE Plasma](https://kde.org/plasma-desktop/) 28 - - Phone 29 - - [Android](https://www.android.com/) 30 - - [Nova Launcher](https://novalauncher.com/) for a consistent launcher across different vendors
+4 -8
src/site-config.ts
··· 1 1 export const socials = { 2 - atproto: { 3 - handle: "vielle.dev", 4 - did: "did:plc:4zht3z4caxwrw3dlsybodywc", 5 - pds: "https://puffball.us-east.host.bsky.network", 6 - }, 2 + atproto: "vielle.dev", 7 3 tumblr: "what-if-doctor-who-was-yuri-yaoi", 8 4 github: "Afterlifepro", 9 5 spotify: "viwn798qleabtpxqgt6oppm8l", ··· 49 45 name: "atproto", 50 46 children: [ 51 47 { 52 - slug: "https://bsky.app/profile/" + socials.atproto.handle, 48 + slug: "https://bsky.app/profile/" + socials.atproto, 53 49 name: "Blue&shy;sky", 54 50 }, 55 51 { 56 - slug: "https://tangled.sh/@" + socials.atproto.handle, 52 + slug: "https://tangled.sh/@" + socials.atproto, 57 53 name: "tangled<wbr>.sh", 58 54 }, 59 55 { 60 - slug: "https://pdsls://at://" + socials.atproto.did, 56 + slug: "https://pdsls://at://" + socials.atproto, 61 57 name: "pdsls", 62 58 }, 63 59 ],
+1 -3
tsconfig.json
··· 5 5 "compilerOptions": { 6 6 "paths": { 7 7 "/*": ["./src/*"] 8 - }, 9 - 10 - "types": ["@atcute/atproto", "@atcute/bluesky"] 8 + } 11 9 } 12 10 }