@keystrokehq/spotify 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +113 -0
- package/dist/_official/index.d.mts +32 -0
- package/dist/_official/index.mjs +3 -0
- package/dist/_runtime/index.d.mts +1 -0
- package/dist/_runtime/index.mjs +1 -0
- package/dist/albums.d.mts +265 -0
- package/dist/albums.mjs +72 -0
- package/dist/artists.d.mts +237 -0
- package/dist/artists.mjs +84 -0
- package/dist/audio-analysis.d.mts +91 -0
- package/dist/audio-analysis.mjs +19 -0
- package/dist/audio-features.d.mts +61 -0
- package/dist/audio-features.mjs +31 -0
- package/dist/audiobooks.d.mts +176 -0
- package/dist/audiobooks.mjs +59 -0
- package/dist/browse.d.mts +74 -0
- package/dist/browse.mjs +31 -0
- package/dist/categories.d.mts +118 -0
- package/dist/categories.mjs +66 -0
- package/dist/chapters.d.mts +163 -0
- package/dist/chapters.mjs +39 -0
- package/dist/client.d.mts +3486 -0
- package/dist/client.mjs +758 -0
- package/dist/connection.d.mts +2 -0
- package/dist/connection.mjs +3 -0
- package/dist/episodes.d.mts +149 -0
- package/dist/episodes.mjs +39 -0
- package/dist/errors.d.mts +34 -0
- package/dist/errors.mjs +89 -0
- package/dist/events.d.mts +613 -0
- package/dist/events.mjs +55 -0
- package/dist/factory-tZba6Hij.mjs +8 -0
- package/dist/follow.d.mts +83 -0
- package/dist/follow.mjs +65 -0
- package/dist/genres.d.mts +14 -0
- package/dist/genres.mjs +19 -0
- package/dist/index.d.mts +1 -0
- package/dist/index.mjs +1 -0
- package/dist/integration-DQ5Egd4f.d.mts +41 -0
- package/dist/integration-ykoImsCq.mjs +78 -0
- package/dist/library.d.mts +472 -0
- package/dist/library.mjs +225 -0
- package/dist/markets.d.mts +14 -0
- package/dist/markets.mjs +20 -0
- package/dist/me.d.mts +169 -0
- package/dist/me.mjs +58 -0
- package/dist/messaging.d.mts +1 -0
- package/dist/messaging.mjs +1 -0
- package/dist/operations.d.mts +6 -0
- package/dist/operations.mjs +237 -0
- package/dist/player.d.mts +877 -0
- package/dist/player.mjs +220 -0
- package/dist/playlists.d.mts +546 -0
- package/dist/playlists.mjs +243 -0
- package/dist/recommendations.d.mts +144 -0
- package/dist/recommendations.mjs +137 -0
- package/dist/schemas.d.mts +3312 -0
- package/dist/schemas.mjs +460 -0
- package/dist/search.d.mts +389 -0
- package/dist/search.mjs +42 -0
- package/dist/shows.d.mts +159 -0
- package/dist/shows.mjs +59 -0
- package/dist/tracks.d.mts +173 -0
- package/dist/tracks.mjs +37 -0
- package/dist/triggers.d.mts +45 -0
- package/dist/triggers.mjs +201 -0
- package/dist/users.d.mts +35 -0
- package/dist/users.mjs +20 -0
- package/dist/verification.d.mts +1 -0
- package/dist/verification.mjs +1 -0
- package/package.json +187 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import * as _keystrokehq_core0 from "@keystrokehq/core";
|
|
3
|
+
import * as _keystrokehq_core_credential_set0 from "@keystrokehq/core/credential-set";
|
|
4
|
+
|
|
5
|
+
//#region src/episodes.d.ts
|
|
6
|
+
declare const getEpisode: _keystrokehq_core0.Operation<z.ZodObject<{
|
|
7
|
+
id: z.ZodString;
|
|
8
|
+
market: z.ZodOptional<z.ZodString>;
|
|
9
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
10
|
+
audioPreviewUrl: z.ZodOptional<z.ZodUnion<readonly [z.ZodURL, z.ZodNull]>>;
|
|
11
|
+
description: z.ZodOptional<z.ZodString>;
|
|
12
|
+
durationMs: z.ZodNumber;
|
|
13
|
+
explicit: z.ZodBoolean;
|
|
14
|
+
externalUrls: z.ZodOptional<z.ZodObject<{
|
|
15
|
+
spotify: z.ZodOptional<z.ZodURL>;
|
|
16
|
+
}, z.core.$strip>>;
|
|
17
|
+
href: z.ZodOptional<z.ZodURL>;
|
|
18
|
+
htmlDescription: z.ZodOptional<z.ZodString>;
|
|
19
|
+
id: z.ZodString;
|
|
20
|
+
images: z.ZodArray<z.ZodObject<{
|
|
21
|
+
url: z.ZodURL;
|
|
22
|
+
height: z.ZodNullable<z.ZodNumber>;
|
|
23
|
+
width: z.ZodNullable<z.ZodNumber>;
|
|
24
|
+
}, z.core.$strip>>;
|
|
25
|
+
isExternallyHosted: z.ZodOptional<z.ZodBoolean>;
|
|
26
|
+
isPlayable: z.ZodOptional<z.ZodBoolean>;
|
|
27
|
+
language: z.ZodOptional<z.ZodString>;
|
|
28
|
+
languages: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
29
|
+
name: z.ZodString;
|
|
30
|
+
releaseDate: z.ZodOptional<z.ZodString>;
|
|
31
|
+
releaseDatePrecision: z.ZodOptional<z.ZodEnum<{
|
|
32
|
+
year: "year";
|
|
33
|
+
month: "month";
|
|
34
|
+
day: "day";
|
|
35
|
+
}>>;
|
|
36
|
+
resumePoint: z.ZodOptional<z.ZodObject<{
|
|
37
|
+
fullyPlayed: z.ZodBoolean;
|
|
38
|
+
resumePositionMs: z.ZodNumber;
|
|
39
|
+
}, z.core.$strip>>;
|
|
40
|
+
restrictions: z.ZodOptional<z.ZodObject<{
|
|
41
|
+
reason: z.ZodString;
|
|
42
|
+
}, z.core.$strip>>;
|
|
43
|
+
show: z.ZodOptional<z.ZodObject<{
|
|
44
|
+
availableMarkets: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
45
|
+
copyrights: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
46
|
+
text: z.ZodString;
|
|
47
|
+
type: z.ZodString;
|
|
48
|
+
}, z.core.$strip>>>;
|
|
49
|
+
description: z.ZodOptional<z.ZodString>;
|
|
50
|
+
explicit: z.ZodOptional<z.ZodBoolean>;
|
|
51
|
+
externalUrls: z.ZodOptional<z.ZodObject<{
|
|
52
|
+
spotify: z.ZodOptional<z.ZodURL>;
|
|
53
|
+
}, z.core.$strip>>;
|
|
54
|
+
href: z.ZodOptional<z.ZodURL>;
|
|
55
|
+
id: z.ZodString;
|
|
56
|
+
images: z.ZodArray<z.ZodObject<{
|
|
57
|
+
url: z.ZodURL;
|
|
58
|
+
height: z.ZodNullable<z.ZodNumber>;
|
|
59
|
+
width: z.ZodNullable<z.ZodNumber>;
|
|
60
|
+
}, z.core.$strip>>;
|
|
61
|
+
languages: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
62
|
+
mediaType: z.ZodOptional<z.ZodString>;
|
|
63
|
+
name: z.ZodString;
|
|
64
|
+
publisher: z.ZodOptional<z.ZodString>;
|
|
65
|
+
totalEpisodes: z.ZodOptional<z.ZodNumber>;
|
|
66
|
+
type: z.ZodLiteral<"show">;
|
|
67
|
+
uri: z.ZodOptional<z.ZodString>;
|
|
68
|
+
}, z.core.$strip>>;
|
|
69
|
+
type: z.ZodLiteral<"episode">;
|
|
70
|
+
uri: z.ZodOptional<z.ZodString>;
|
|
71
|
+
}, z.core.$strip>, readonly [_keystrokehq_core0.CredentialSet<"spotify", z.ZodObject<{
|
|
72
|
+
SPOTIFY_ACCESS_TOKEN: z.ZodString;
|
|
73
|
+
}, z.core.$strip>, readonly _keystrokehq_core_credential_set0.CredentialConnection<z.ZodObject<{
|
|
74
|
+
SPOTIFY_ACCESS_TOKEN: z.ZodString;
|
|
75
|
+
}, z.core.$strip>>[] | undefined>], undefined>;
|
|
76
|
+
declare const getSeveralEpisodes: _keystrokehq_core0.Operation<z.ZodObject<{
|
|
77
|
+
ids: z.ZodArray<z.ZodString>;
|
|
78
|
+
market: z.ZodOptional<z.ZodString>;
|
|
79
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
80
|
+
episodes: z.ZodArray<z.ZodObject<{
|
|
81
|
+
audioPreviewUrl: z.ZodOptional<z.ZodUnion<readonly [z.ZodURL, z.ZodNull]>>;
|
|
82
|
+
description: z.ZodOptional<z.ZodString>;
|
|
83
|
+
durationMs: z.ZodNumber;
|
|
84
|
+
explicit: z.ZodBoolean;
|
|
85
|
+
externalUrls: z.ZodOptional<z.ZodObject<{
|
|
86
|
+
spotify: z.ZodOptional<z.ZodURL>;
|
|
87
|
+
}, z.core.$strip>>;
|
|
88
|
+
href: z.ZodOptional<z.ZodURL>;
|
|
89
|
+
htmlDescription: z.ZodOptional<z.ZodString>;
|
|
90
|
+
id: z.ZodString;
|
|
91
|
+
images: z.ZodArray<z.ZodObject<{
|
|
92
|
+
url: z.ZodURL;
|
|
93
|
+
height: z.ZodNullable<z.ZodNumber>;
|
|
94
|
+
width: z.ZodNullable<z.ZodNumber>;
|
|
95
|
+
}, z.core.$strip>>;
|
|
96
|
+
isExternallyHosted: z.ZodOptional<z.ZodBoolean>;
|
|
97
|
+
isPlayable: z.ZodOptional<z.ZodBoolean>;
|
|
98
|
+
language: z.ZodOptional<z.ZodString>;
|
|
99
|
+
languages: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
100
|
+
name: z.ZodString;
|
|
101
|
+
releaseDate: z.ZodOptional<z.ZodString>;
|
|
102
|
+
releaseDatePrecision: z.ZodOptional<z.ZodEnum<{
|
|
103
|
+
year: "year";
|
|
104
|
+
month: "month";
|
|
105
|
+
day: "day";
|
|
106
|
+
}>>;
|
|
107
|
+
resumePoint: z.ZodOptional<z.ZodObject<{
|
|
108
|
+
fullyPlayed: z.ZodBoolean;
|
|
109
|
+
resumePositionMs: z.ZodNumber;
|
|
110
|
+
}, z.core.$strip>>;
|
|
111
|
+
restrictions: z.ZodOptional<z.ZodObject<{
|
|
112
|
+
reason: z.ZodString;
|
|
113
|
+
}, z.core.$strip>>;
|
|
114
|
+
show: z.ZodOptional<z.ZodObject<{
|
|
115
|
+
availableMarkets: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
116
|
+
copyrights: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
117
|
+
text: z.ZodString;
|
|
118
|
+
type: z.ZodString;
|
|
119
|
+
}, z.core.$strip>>>;
|
|
120
|
+
description: z.ZodOptional<z.ZodString>;
|
|
121
|
+
explicit: z.ZodOptional<z.ZodBoolean>;
|
|
122
|
+
externalUrls: z.ZodOptional<z.ZodObject<{
|
|
123
|
+
spotify: z.ZodOptional<z.ZodURL>;
|
|
124
|
+
}, z.core.$strip>>;
|
|
125
|
+
href: z.ZodOptional<z.ZodURL>;
|
|
126
|
+
id: z.ZodString;
|
|
127
|
+
images: z.ZodArray<z.ZodObject<{
|
|
128
|
+
url: z.ZodURL;
|
|
129
|
+
height: z.ZodNullable<z.ZodNumber>;
|
|
130
|
+
width: z.ZodNullable<z.ZodNumber>;
|
|
131
|
+
}, z.core.$strip>>;
|
|
132
|
+
languages: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
133
|
+
mediaType: z.ZodOptional<z.ZodString>;
|
|
134
|
+
name: z.ZodString;
|
|
135
|
+
publisher: z.ZodOptional<z.ZodString>;
|
|
136
|
+
totalEpisodes: z.ZodOptional<z.ZodNumber>;
|
|
137
|
+
type: z.ZodLiteral<"show">;
|
|
138
|
+
uri: z.ZodOptional<z.ZodString>;
|
|
139
|
+
}, z.core.$strip>>;
|
|
140
|
+
type: z.ZodLiteral<"episode">;
|
|
141
|
+
uri: z.ZodOptional<z.ZodString>;
|
|
142
|
+
}, z.core.$strip>>;
|
|
143
|
+
}, z.core.$strip>, readonly [_keystrokehq_core0.CredentialSet<"spotify", z.ZodObject<{
|
|
144
|
+
SPOTIFY_ACCESS_TOKEN: z.ZodString;
|
|
145
|
+
}, z.core.$strip>, readonly _keystrokehq_core_credential_set0.CredentialConnection<z.ZodObject<{
|
|
146
|
+
SPOTIFY_ACCESS_TOKEN: z.ZodString;
|
|
147
|
+
}, z.core.$strip>>[] | undefined>], undefined>;
|
|
148
|
+
//#endregion
|
|
149
|
+
export { getEpisode, getSeveralEpisodes };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { spotifyEpisodeSchema, spotifyIdSchema, spotifyMarketSchema } from "./schemas.mjs";
|
|
2
|
+
import { createSpotifyClient } from "./client.mjs";
|
|
3
|
+
import { t as spotifyOperation } from "./factory-tZba6Hij.mjs";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
|
|
6
|
+
//#region src/episodes.ts
|
|
7
|
+
const severalEpisodeIdsSchema = z.array(spotifyIdSchema).min(1).max(50);
|
|
8
|
+
const episodeLookupInputSchema = z.object({
|
|
9
|
+
id: spotifyIdSchema,
|
|
10
|
+
market: spotifyMarketSchema.optional()
|
|
11
|
+
});
|
|
12
|
+
const severalEpisodesInputSchema = z.object({
|
|
13
|
+
ids: severalEpisodeIdsSchema,
|
|
14
|
+
market: spotifyMarketSchema.optional()
|
|
15
|
+
});
|
|
16
|
+
const severalEpisodesOutputSchema = z.object({ episodes: z.array(spotifyEpisodeSchema) });
|
|
17
|
+
const getEpisode = spotifyOperation({
|
|
18
|
+
id: "get_spotify_episode",
|
|
19
|
+
name: "Get Spotify Episode",
|
|
20
|
+
description: "Fetch a single Spotify episode by ID.",
|
|
21
|
+
input: episodeLookupInputSchema,
|
|
22
|
+
output: spotifyEpisodeSchema,
|
|
23
|
+
run: async (input, credentials) => {
|
|
24
|
+
return createSpotifyClient(credentials).episodes.getEpisode(input.id, input.market);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
const getSeveralEpisodes = spotifyOperation({
|
|
28
|
+
id: "get_spotify_several_episodes",
|
|
29
|
+
name: "Get Several Spotify Episodes",
|
|
30
|
+
description: "Fetch multiple Spotify episodes in a single request.",
|
|
31
|
+
input: severalEpisodesInputSchema,
|
|
32
|
+
output: severalEpisodesOutputSchema,
|
|
33
|
+
run: async (input, credentials) => {
|
|
34
|
+
return createSpotifyClient(credentials).episodes.getSeveralEpisodes(input.ids, input.market);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
//#endregion
|
|
39
|
+
export { getEpisode, getSeveralEpisodes };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
//#region src/errors.d.ts
|
|
2
|
+
declare const spotifyApiErrorKinds: readonly ["http", "rate_limit", "auth", "premium_required", "deprecated", "validation"];
|
|
3
|
+
type SpotifyApiErrorKind = (typeof spotifyApiErrorKinds)[number];
|
|
4
|
+
interface SpotifyApiErrorOptions {
|
|
5
|
+
readonly kind: SpotifyApiErrorKind;
|
|
6
|
+
readonly message: string;
|
|
7
|
+
readonly status?: number;
|
|
8
|
+
readonly code?: string;
|
|
9
|
+
readonly requestId?: string;
|
|
10
|
+
readonly retryAfterSeconds?: number;
|
|
11
|
+
readonly retryable?: boolean;
|
|
12
|
+
readonly details?: Record<string, string | number | boolean | null | undefined>;
|
|
13
|
+
}
|
|
14
|
+
declare class SpotifyApiError extends Error {
|
|
15
|
+
readonly kind: SpotifyApiErrorKind;
|
|
16
|
+
readonly status?: number;
|
|
17
|
+
readonly code?: string;
|
|
18
|
+
readonly requestId?: string;
|
|
19
|
+
readonly retryAfterSeconds?: number;
|
|
20
|
+
readonly retryable: boolean;
|
|
21
|
+
readonly details?: Record<string, string | number | boolean | null | undefined>;
|
|
22
|
+
constructor(options: SpotifyApiErrorOptions);
|
|
23
|
+
}
|
|
24
|
+
declare function isRetryableStatus(status: number | undefined): boolean;
|
|
25
|
+
declare function classifySpotifyApiError(input: {
|
|
26
|
+
readonly status?: number;
|
|
27
|
+
readonly message: string;
|
|
28
|
+
readonly code?: string;
|
|
29
|
+
readonly retryAfterSeconds?: number;
|
|
30
|
+
readonly requestId?: string;
|
|
31
|
+
readonly details?: Record<string, string | number | boolean | null | undefined>;
|
|
32
|
+
}): SpotifyApiError;
|
|
33
|
+
//#endregion
|
|
34
|
+
export { SpotifyApiError, SpotifyApiErrorKind, SpotifyApiErrorOptions, classifySpotifyApiError, isRetryableStatus, spotifyApiErrorKinds };
|
package/dist/errors.mjs
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
//#region src/errors.ts
|
|
2
|
+
const spotifyApiErrorKinds = [
|
|
3
|
+
"http",
|
|
4
|
+
"rate_limit",
|
|
5
|
+
"auth",
|
|
6
|
+
"premium_required",
|
|
7
|
+
"deprecated",
|
|
8
|
+
"validation"
|
|
9
|
+
];
|
|
10
|
+
var SpotifyApiError = class extends Error {
|
|
11
|
+
kind;
|
|
12
|
+
status;
|
|
13
|
+
code;
|
|
14
|
+
requestId;
|
|
15
|
+
retryAfterSeconds;
|
|
16
|
+
retryable;
|
|
17
|
+
details;
|
|
18
|
+
constructor(options) {
|
|
19
|
+
super(options.message);
|
|
20
|
+
this.name = "SpotifyApiError";
|
|
21
|
+
this.kind = options.kind;
|
|
22
|
+
this.status = options.status;
|
|
23
|
+
this.code = options.code;
|
|
24
|
+
this.requestId = options.requestId;
|
|
25
|
+
this.retryAfterSeconds = options.retryAfterSeconds;
|
|
26
|
+
this.retryable = options.retryable ?? isRetryableStatus(options.status);
|
|
27
|
+
this.details = options.details;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
function isRetryableStatus(status) {
|
|
31
|
+
if (status === void 0) return false;
|
|
32
|
+
return status === 429 || status >= 500;
|
|
33
|
+
}
|
|
34
|
+
function classifySpotifyApiError(input) {
|
|
35
|
+
const normalizedMessage = input.message.toLowerCase();
|
|
36
|
+
const normalizedCode = input.code?.toLowerCase();
|
|
37
|
+
if (input.status === 429) return new SpotifyApiError({
|
|
38
|
+
kind: "rate_limit",
|
|
39
|
+
message: input.message,
|
|
40
|
+
status: input.status,
|
|
41
|
+
code: input.code,
|
|
42
|
+
requestId: input.requestId,
|
|
43
|
+
retryAfterSeconds: input.retryAfterSeconds,
|
|
44
|
+
retryable: true,
|
|
45
|
+
details: input.details
|
|
46
|
+
});
|
|
47
|
+
if (input.status === 401 || normalizedCode === "invalid_token" || normalizedMessage.includes("invalid access token") || normalizedMessage.includes("authentication")) return new SpotifyApiError({
|
|
48
|
+
kind: "auth",
|
|
49
|
+
message: input.message,
|
|
50
|
+
status: input.status,
|
|
51
|
+
code: input.code,
|
|
52
|
+
requestId: input.requestId,
|
|
53
|
+
retryAfterSeconds: input.retryAfterSeconds,
|
|
54
|
+
retryable: false,
|
|
55
|
+
details: input.details
|
|
56
|
+
});
|
|
57
|
+
if (input.status === 403 && (normalizedCode === "premium_required" || normalizedMessage.includes("premium required"))) return new SpotifyApiError({
|
|
58
|
+
kind: "premium_required",
|
|
59
|
+
message: input.message,
|
|
60
|
+
status: input.status,
|
|
61
|
+
code: input.code ?? "PREMIUM_REQUIRED",
|
|
62
|
+
requestId: input.requestId,
|
|
63
|
+
retryAfterSeconds: input.retryAfterSeconds,
|
|
64
|
+
retryable: false,
|
|
65
|
+
details: input.details
|
|
66
|
+
});
|
|
67
|
+
if (input.status === 404 && (normalizedMessage.includes("deprecated") || normalizedMessage.includes("not available to your app") || normalizedMessage.includes("restricted"))) return new SpotifyApiError({
|
|
68
|
+
kind: "deprecated",
|
|
69
|
+
message: input.message,
|
|
70
|
+
status: input.status,
|
|
71
|
+
code: input.code,
|
|
72
|
+
requestId: input.requestId,
|
|
73
|
+
retryAfterSeconds: input.retryAfterSeconds,
|
|
74
|
+
retryable: false,
|
|
75
|
+
details: input.details
|
|
76
|
+
});
|
|
77
|
+
return new SpotifyApiError({
|
|
78
|
+
kind: "http",
|
|
79
|
+
message: input.message,
|
|
80
|
+
status: input.status,
|
|
81
|
+
code: input.code,
|
|
82
|
+
requestId: input.requestId,
|
|
83
|
+
retryAfterSeconds: input.retryAfterSeconds,
|
|
84
|
+
details: input.details
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
//#endregion
|
|
89
|
+
export { SpotifyApiError, classifySpotifyApiError, isRetryableStatus, spotifyApiErrorKinds };
|