@benliam12/spotify-api-helper 1.0.0-DEV.3

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/README.md ADDED
@@ -0,0 +1,2 @@
1
+ # Spotify API Helper
2
+ Help you use the Spotify API without having to implement everything.
@@ -0,0 +1,9 @@
1
+ import { MetricDataType } from "./types";
2
+ export declare class KPI_Data {
3
+ Date: Date | undefined;
4
+ Data: Partial<Record<MetricDataType, number>>;
5
+ constructor(date?: Date);
6
+ set(metric: MetricDataType, value: number): void;
7
+ get(metric: MetricDataType): number | undefined;
8
+ clear(metric?: MetricDataType): void;
9
+ }
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.KPI_Data = void 0;
4
+ class KPI_Data {
5
+ constructor(date) {
6
+ this.Data = {};
7
+ this.Date = date;
8
+ }
9
+ set(metric, value) {
10
+ this.Data[metric] = value;
11
+ }
12
+ get(metric) {
13
+ return this.Data[metric];
14
+ }
15
+ clear(metric) {
16
+ if (metric) {
17
+ delete this.Data[metric];
18
+ }
19
+ else {
20
+ this.Data = {};
21
+ }
22
+ }
23
+ }
24
+ exports.KPI_Data = KPI_Data;
@@ -0,0 +1,21 @@
1
+ import { IProject, ISection } from "./types";
2
+ export declare class Project implements IProject {
3
+ id: string | undefined;
4
+ name: string | undefined;
5
+ description?: string | undefined;
6
+ sections?: ISection[];
7
+ constructor(id?: string, name?: string);
8
+ create(): void;
9
+ /**
10
+ * Check if a section exists in the project
11
+ * @param sectionId Section number.
12
+ * @returns boolean
13
+ */
14
+ hasSection(sectionId: string): boolean;
15
+ /**
16
+ * Remove a section from the project
17
+ * @param sectionId Section number.
18
+ */
19
+ removeSection(sectionId: string): void;
20
+ addSection(section: ISection): void;
21
+ }
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Project = void 0;
4
+ class Project {
5
+ constructor(id, name) {
6
+ this.sections = [];
7
+ this.id = id;
8
+ this.name = name;
9
+ }
10
+ create() {
11
+ throw new Error("Method not implemented.");
12
+ }
13
+ /**
14
+ * Check if a section exists in the project
15
+ * @param sectionId Section number.
16
+ * @returns boolean
17
+ */
18
+ hasSection(sectionId) {
19
+ for (const section of this.sections || []) {
20
+ if (section.id === sectionId) {
21
+ return true;
22
+ }
23
+ }
24
+ return false;
25
+ }
26
+ /**
27
+ * Remove a section from the project
28
+ * @param sectionId Section number.
29
+ */
30
+ removeSection(sectionId) {
31
+ if (!this.sections) {
32
+ return;
33
+ }
34
+ this.sections = this.sections.filter(section => section.id !== sectionId);
35
+ }
36
+ addSection(section) {
37
+ if (!this.sections) {
38
+ this.sections = [];
39
+ }
40
+ let exists = false;
41
+ for (const existingSection of this.sections) {
42
+ if (existingSection.id === section.id) {
43
+ exists = true;
44
+ break;
45
+ }
46
+ }
47
+ if (!exists) {
48
+ this.sections.push(section);
49
+ }
50
+ }
51
+ }
52
+ exports.Project = Project;
@@ -0,0 +1,13 @@
1
+ import { IProject, ISection, ITask } from "./types";
2
+ export declare class Section implements ISection {
3
+ id: string | undefined;
4
+ projectId: string | undefined;
5
+ title: string | undefined;
6
+ content: string | undefined;
7
+ tasks: ITask[];
8
+ parentProject?: IProject | undefined;
9
+ addTask(task: ITask): void;
10
+ hasTask(taskId: string): boolean;
11
+ removeTask(taskId: string): void;
12
+ create(): void;
13
+ }
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Section = void 0;
4
+ class Section {
5
+ constructor() {
6
+ this.tasks = [];
7
+ }
8
+ addTask(task) {
9
+ if (!this.tasks) {
10
+ this.tasks = [];
11
+ }
12
+ let exists = false;
13
+ for (const existingTask of this.tasks) {
14
+ if (existingTask.id === task.id) {
15
+ exists = true;
16
+ break;
17
+ }
18
+ }
19
+ if (!exists) {
20
+ this.tasks.push(task);
21
+ }
22
+ }
23
+ hasTask(taskId) {
24
+ for (const task of this.tasks) {
25
+ if (task.id === taskId) {
26
+ return true;
27
+ }
28
+ }
29
+ return false;
30
+ }
31
+ removeTask(taskId) {
32
+ this.tasks = this.tasks.filter(task => task.id !== taskId);
33
+ }
34
+ create() {
35
+ throw new Error("Method not implemented.");
36
+ }
37
+ }
38
+ exports.Section = Section;
@@ -0,0 +1,6 @@
1
+ export declare class SpotifyConfiguration {
2
+ clientId: string;
3
+ clientSecret: string;
4
+ redirectUri: string;
5
+ constructor(clientId: string, clientSecret: string, redirectUri: string);
6
+ }
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SpotifyConfiguration = void 0;
4
+ class SpotifyConfiguration {
5
+ constructor(clientId, clientSecret, redirectUri) {
6
+ this.clientId = clientId;
7
+ this.clientSecret = clientSecret;
8
+ this.redirectUri = redirectUri;
9
+ }
10
+ }
11
+ exports.SpotifyConfiguration = SpotifyConfiguration;
@@ -0,0 +1,8 @@
1
+ import { SpotifyConfiguration } from "./SpotifyConfiguration";
2
+ import { Album } from "./SpotifyTypes";
3
+ export declare class SpotifyHelper {
4
+ config: SpotifyConfiguration;
5
+ constructor(config: SpotifyConfiguration);
6
+ getAlbum(albumId: string): Promise<Album | null>;
7
+ getTrack(trackId: string): Promise<void>;
8
+ }
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SpotifyHelper = void 0;
4
+ class SpotifyHelper {
5
+ constructor(config) {
6
+ this.config = config;
7
+ }
8
+ async getAlbum(albumId) {
9
+ try {
10
+ }
11
+ catch (error) {
12
+ return null;
13
+ }
14
+ return null;
15
+ }
16
+ async getTrack(trackId) {
17
+ }
18
+ }
19
+ exports.SpotifyHelper = SpotifyHelper;
@@ -0,0 +1,9 @@
1
+ export interface Album {
2
+ id: string;
3
+ market: string;
4
+ album_type: string;
5
+ total_tracks: number;
6
+ available_markets: string[];
7
+ }
8
+ export interface Track {
9
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,15 @@
1
+ export interface SpotifyConfigOptions {
2
+ clientId: string;
3
+ clientSecret: string;
4
+ redirectUri: string;
5
+ }
6
+ export declare class SpotifyConfiguration {
7
+ clientId: string;
8
+ clientSecret: string;
9
+ redirectUri: string;
10
+ constructor(config: SpotifyConfigOptions);
11
+ isValid(): boolean;
12
+ getClientID(): string;
13
+ getClientSecret(): string;
14
+ getRedirectUri(): string;
15
+ }
@@ -0,0 +1,19 @@
1
+ export class SpotifyConfiguration {
2
+ constructor(config) {
3
+ this.clientId = config.clientId ?? "";
4
+ this.clientSecret = config.clientSecret ?? "";
5
+ this.redirectUri = config.redirectUri ?? "";
6
+ }
7
+ isValid() {
8
+ return this.clientId !== "" && this.clientSecret !== "" && this.redirectUri !== "";
9
+ }
10
+ getClientID() {
11
+ return this.clientId;
12
+ }
13
+ getClientSecret() {
14
+ return this.clientSecret;
15
+ }
16
+ getRedirectUri() {
17
+ return this.redirectUri;
18
+ }
19
+ }
@@ -0,0 +1,116 @@
1
+ import { SpotifyConfiguration } from "./SpotifyConfiguration.js";
2
+ import { Album, Track, Artist } from "./SpotifyTypes.js";
3
+ /**
4
+ * Result wrapper for operations that can fail
5
+ */
6
+ export type SpotifyResult<T> = {
7
+ success: true;
8
+ data: T;
9
+ } | {
10
+ success: false;
11
+ error: string;
12
+ statusCode?: number;
13
+ };
14
+ /**
15
+ * Options for configuring the SpotifyHelper
16
+ */
17
+ export interface SpotifyHelperOptions {
18
+ /**
19
+ * How long before token expiry to refresh (in milliseconds)
20
+ * Default: 60000 (60 seconds)
21
+ */
22
+ tokenRefreshBufferMs?: number;
23
+ /**
24
+ * Callback for when errors occur (for logging/monitoring)
25
+ */
26
+ onError?: (error: SpotifyError) => void;
27
+ /**
28
+ * Whether to log errors to console
29
+ * Default: false
30
+ */
31
+ logErrors?: boolean;
32
+ }
33
+ export interface SpotifyError {
34
+ message: string;
35
+ statusCode?: number;
36
+ operation: string;
37
+ timestamp: Date;
38
+ }
39
+ export declare class SpotifyHelper {
40
+ config: SpotifyConfiguration;
41
+ private clientToken;
42
+ private tokenRefreshPromise;
43
+ private readonly options;
44
+ constructor(config: SpotifyConfiguration, options?: SpotifyHelperOptions);
45
+ /**
46
+ * Initialize the helper by fetching the first token.
47
+ * Returns true if successful, false otherwise.
48
+ */
49
+ initialize(): Promise<boolean>;
50
+ /**
51
+ * Ensures we have a valid token, refreshing if necessary.
52
+ * Returns null if token fetch fails (instead of throwing).
53
+ */
54
+ private ensureValidToken;
55
+ /**
56
+ * Checks if the token is expired or about to expire soon
57
+ */
58
+ private isTokenExpiringSoon;
59
+ /**
60
+ * Fetches a new token from Spotify.
61
+ * Returns null if fetch fails (instead of throwing).
62
+ */
63
+ private fetchNewToken;
64
+ /**
65
+ * Makes an authenticated request to the Spotify API.
66
+ * Returns a result object instead of throwing.
67
+ */
68
+ private makeAuthenticatedRequest;
69
+ /**
70
+ * Handle errors consistently - log and/or call callback
71
+ */
72
+ private handleError;
73
+ test(): string;
74
+ /**
75
+ * Get an album by ID.
76
+ * Returns null if the request fails.
77
+ */
78
+ getAlbum(albumId: string): Promise<Album | null>;
79
+ /**
80
+ * Get a track by ID.
81
+ * Returns null if the request fails.
82
+ */
83
+ getTrack(trackId: string): Promise<Track | null>;
84
+ /**
85
+ * Get an artist by ID.
86
+ * Returns null if the request fails.
87
+ */
88
+ getArtist(artistId: string): Promise<Artist | null>;
89
+ /**
90
+ * Get a playlist by ID.
91
+ * Returns null if the request fails.
92
+ */
93
+ getPlaylist(playlistId: string): Promise<any | null>;
94
+ /**
95
+ * Get available markets.
96
+ * Returns empty array if the request fails.
97
+ */
98
+ getAvailableMarkets(): Promise<string[]>;
99
+ /**
100
+ * Check if the helper is properly authenticated.
101
+ * Useful for health checks.
102
+ */
103
+ isAuthenticated(): Promise<boolean>;
104
+ /**
105
+ * Manually clear the token (useful for testing or forcing a refresh).
106
+ */
107
+ clearToken(): void;
108
+ /**
109
+ * Get token info for debugging (without exposing the actual token).
110
+ */
111
+ getTokenInfo(): {
112
+ hasToken: boolean;
113
+ expiresAt: Date | null;
114
+ isExpiringSoon: boolean;
115
+ };
116
+ }
@@ -0,0 +1,263 @@
1
+ export class SpotifyHelper {
2
+ constructor(config, options = {}) {
3
+ this.clientToken = null;
4
+ this.tokenRefreshPromise = null;
5
+ this.config = config;
6
+ this.options = {
7
+ tokenRefreshBufferMs: options.tokenRefreshBufferMs ?? 60000,
8
+ onError: options.onError ?? (() => { }),
9
+ logErrors: options.logErrors ?? false
10
+ };
11
+ }
12
+ /**
13
+ * Initialize the helper by fetching the first token.
14
+ * Returns true if successful, false otherwise.
15
+ */
16
+ async initialize() {
17
+ const token = await this.ensureValidToken();
18
+ return token !== null;
19
+ }
20
+ /**
21
+ * Ensures we have a valid token, refreshing if necessary.
22
+ * Returns null if token fetch fails (instead of throwing).
23
+ */
24
+ async ensureValidToken() {
25
+ // If there's already a refresh in progress, wait for it
26
+ if (this.tokenRefreshPromise) {
27
+ return this.tokenRefreshPromise;
28
+ }
29
+ // Check if we need to refresh
30
+ const needsRefresh = !this.clientToken || this.isTokenExpiringSoon();
31
+ if (needsRefresh) {
32
+ // Start the refresh and store the promise
33
+ this.tokenRefreshPromise = this.fetchNewToken();
34
+ try {
35
+ this.clientToken = await this.tokenRefreshPromise;
36
+ return this.clientToken;
37
+ }
38
+ finally {
39
+ // Clear the promise once done (success or failure)
40
+ this.tokenRefreshPromise = null;
41
+ }
42
+ }
43
+ // Token is still valid, return it
44
+ return this.clientToken;
45
+ }
46
+ /**
47
+ * Checks if the token is expired or about to expire soon
48
+ */
49
+ isTokenExpiringSoon() {
50
+ if (!this.clientToken) {
51
+ return true;
52
+ }
53
+ const now = new Date();
54
+ const expiryTime = this.clientToken.expires_at.getTime();
55
+ const currentTime = now.getTime();
56
+ return currentTime >= (expiryTime - this.options.tokenRefreshBufferMs);
57
+ }
58
+ /**
59
+ * Fetches a new token from Spotify.
60
+ * Returns null if fetch fails (instead of throwing).
61
+ */
62
+ async fetchNewToken() {
63
+ const params = new URLSearchParams();
64
+ params.append('grant_type', 'client_credentials');
65
+ try {
66
+ const response = await fetch("https://accounts.spotify.com/api/token", {
67
+ method: "POST",
68
+ headers: {
69
+ "Content-Type": "application/x-www-form-urlencoded",
70
+ "Authorization": "Basic " + Buffer.from(this.config.clientId + ":" + this.config.clientSecret).toString("base64")
71
+ },
72
+ body: params.toString()
73
+ });
74
+ if (!response.ok) {
75
+ const errorText = await response.text();
76
+ this.handleError({
77
+ message: `Failed to get token: ${response.status} ${response.statusText} - ${errorText}`,
78
+ statusCode: response.status,
79
+ operation: "fetchNewToken",
80
+ timestamp: new Date()
81
+ });
82
+ return null;
83
+ }
84
+ const data = await response.json();
85
+ if (!data.access_token || !data.expires_in) {
86
+ this.handleError({
87
+ message: "Invalid token response from Spotify - missing access_token or expires_in",
88
+ operation: "fetchNewToken",
89
+ timestamp: new Date()
90
+ });
91
+ return null;
92
+ }
93
+ const token = {
94
+ access_token: data.access_token,
95
+ token_type: data.token_type,
96
+ expires_at: new Date(Date.now() + data.expires_in * 1000)
97
+ };
98
+ return token;
99
+ }
100
+ catch (error) {
101
+ this.handleError({
102
+ message: `Network error fetching token: ${error instanceof Error ? error.message : String(error)}`,
103
+ operation: "fetchNewToken",
104
+ timestamp: new Date()
105
+ });
106
+ return null;
107
+ }
108
+ }
109
+ /**
110
+ * Makes an authenticated request to the Spotify API.
111
+ * Returns a result object instead of throwing.
112
+ */
113
+ async makeAuthenticatedRequest(url, operation, options = {}) {
114
+ const token = await this.ensureValidToken();
115
+ if (!token) {
116
+ return {
117
+ success: false,
118
+ error: "Failed to obtain valid authentication token"
119
+ };
120
+ }
121
+ try {
122
+ const response = await fetch(url, {
123
+ ...options,
124
+ headers: {
125
+ ...options.headers,
126
+ "Authorization": `Bearer ${token.access_token}`
127
+ }
128
+ });
129
+ if (!response.ok) {
130
+ const errorText = await response.text();
131
+ this.handleError({
132
+ message: `API request failed: ${response.status} ${response.statusText} - ${errorText}`,
133
+ statusCode: response.status,
134
+ operation,
135
+ timestamp: new Date()
136
+ });
137
+ return {
138
+ success: false,
139
+ error: `Request failed: ${response.status} ${response.statusText}`,
140
+ statusCode: response.status
141
+ };
142
+ }
143
+ const data = await response.json();
144
+ return { success: true, data };
145
+ }
146
+ catch (error) {
147
+ const errorMessage = error instanceof Error ? error.message : String(error);
148
+ this.handleError({
149
+ message: `Network error during ${operation}: ${errorMessage}`,
150
+ operation,
151
+ timestamp: new Date()
152
+ });
153
+ return {
154
+ success: false,
155
+ error: `Network error: ${errorMessage}`
156
+ };
157
+ }
158
+ }
159
+ /**
160
+ * Handle errors consistently - log and/or call callback
161
+ */
162
+ handleError(error) {
163
+ if (this.options.logErrors) {
164
+ console.error(`[SpotifyHelper] ${error.operation}:`, error.message);
165
+ }
166
+ this.options.onError(error);
167
+ }
168
+ test() {
169
+ return "SpotifyHelper is working!";
170
+ }
171
+ /**
172
+ * Get an album by ID.
173
+ * Returns null if the request fails.
174
+ */
175
+ async getAlbum(albumId) {
176
+ const result = await this.makeAuthenticatedRequest(`https://api.spotify.com/v1/albums/${albumId}`, "getAlbum", { method: "GET" });
177
+ if (!result.success) {
178
+ return null;
179
+ }
180
+ const data = result.data;
181
+ const album = {
182
+ id: data.id,
183
+ name: data.name,
184
+ market: data.market,
185
+ album_type: data.album_type,
186
+ total_tracks: data.total_tracks,
187
+ available_markets: data.available_markets
188
+ };
189
+ return album;
190
+ }
191
+ /**
192
+ * Get a track by ID.
193
+ * Returns null if the request fails.
194
+ */
195
+ async getTrack(trackId) {
196
+ const result = await this.makeAuthenticatedRequest(`https://api.spotify.com/v1/tracks/${trackId}`, "getTrack", { method: "GET" });
197
+ if (!result.success) {
198
+ return null;
199
+ }
200
+ // Map to your Track type based on your type definition
201
+ // For now returning null as placeholder
202
+ return null;
203
+ }
204
+ /**
205
+ * Get an artist by ID.
206
+ * Returns null if the request fails.
207
+ */
208
+ async getArtist(artistId) {
209
+ const result = await this.makeAuthenticatedRequest(`https://api.spotify.com/v1/artists/${artistId}`, "getArtist", { method: "GET" });
210
+ if (!result.success) {
211
+ return null;
212
+ }
213
+ // Map to your Artist type based on your type definition
214
+ // For now returning null as placeholder
215
+ return null;
216
+ }
217
+ /**
218
+ * Get a playlist by ID.
219
+ * Returns null if the request fails.
220
+ */
221
+ async getPlaylist(playlistId) {
222
+ const result = await this.makeAuthenticatedRequest(`https://api.spotify.com/v1/playlists/${playlistId}`, "getPlaylist", { method: "GET" });
223
+ if (!result.success) {
224
+ return null;
225
+ }
226
+ return result.data;
227
+ }
228
+ /**
229
+ * Get available markets.
230
+ * Returns empty array if the request fails.
231
+ */
232
+ async getAvailableMarkets() {
233
+ const result = await this.makeAuthenticatedRequest(`https://api.spotify.com/v1/markets`, "getAvailableMarkets", { method: "GET" });
234
+ if (!result.success) {
235
+ return [];
236
+ }
237
+ return result.data.markets || [];
238
+ }
239
+ /**
240
+ * Check if the helper is properly authenticated.
241
+ * Useful for health checks.
242
+ */
243
+ async isAuthenticated() {
244
+ const token = await this.ensureValidToken();
245
+ return token !== null;
246
+ }
247
+ /**
248
+ * Manually clear the token (useful for testing or forcing a refresh).
249
+ */
250
+ clearToken() {
251
+ this.clientToken = null;
252
+ }
253
+ /**
254
+ * Get token info for debugging (without exposing the actual token).
255
+ */
256
+ getTokenInfo() {
257
+ return {
258
+ hasToken: this.clientToken !== null,
259
+ expiresAt: this.clientToken?.expires_at || null,
260
+ isExpiringSoon: this.isTokenExpiringSoon()
261
+ };
262
+ }
263
+ }
@@ -0,0 +1,17 @@
1
+ export interface Album {
2
+ id: string;
3
+ name: string;
4
+ market: string;
5
+ album_type: string;
6
+ total_tracks: number;
7
+ available_markets: string[];
8
+ }
9
+ export interface Track {
10
+ }
11
+ export interface Artist {
12
+ }
13
+ export interface ClientToken {
14
+ access_token: string;
15
+ token_type: string;
16
+ expires_at: Date;
17
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,13 @@
1
+ import { ISection, ITask } from "./types";
2
+ export declare class Task implements ITask {
3
+ id?: string | undefined;
4
+ parentSection?: ISection | undefined;
5
+ title: string | undefined;
6
+ completed: boolean;
7
+ startDate?: Date | undefined;
8
+ EndDate?: Date | undefined;
9
+ CompleteConfirmation?: boolean | undefined;
10
+ markComplete(): void;
11
+ markIncomplete(): void;
12
+ create(): void;
13
+ }
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Task = void 0;
4
+ class Task {
5
+ constructor() {
6
+ this.completed = false;
7
+ }
8
+ markComplete() {
9
+ throw new Error("Method not implemented.");
10
+ }
11
+ markIncomplete() {
12
+ throw new Error("Method not implemented.");
13
+ }
14
+ create() {
15
+ throw new Error("Method not implemented.");
16
+ }
17
+ }
18
+ exports.Task = Task;
@@ -0,0 +1,3 @@
1
+ export declare class Utils {
2
+ generateRandomString(length: number): string;
3
+ }
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Utils = void 0;
4
+ class Utils {
5
+ generateRandomString(length) {
6
+ var text = '';
7
+ var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
8
+ for (var i = 0; i < length; i++) {
9
+ text += possible.charAt(Math.floor(Math.random() * possible.length));
10
+ }
11
+ return text;
12
+ }
13
+ }
14
+ exports.Utils = Utils;
@@ -0,0 +1,48 @@
1
+ export interface IProject {
2
+ id: string | undefined;
3
+ name: string | undefined;
4
+ description?: string;
5
+ sections?: ISection[];
6
+ addSection(section: ISection): void;
7
+ hasSection(sectionId: string): boolean;
8
+ removeSection(sectionId: string): void;
9
+ create(): void;
10
+ }
11
+ export interface ISection {
12
+ id: string | undefined;
13
+ projectId: string | undefined;
14
+ title: string | undefined;
15
+ content: string | undefined;
16
+ tasks: ITask[];
17
+ parentProject?: IProject;
18
+ addTask(task: ITask): void;
19
+ hasTask(taskId: string): boolean;
20
+ removeTask(taskId: string): void;
21
+ create(): void;
22
+ }
23
+ export interface ITask {
24
+ id?: string | undefined;
25
+ parentSection?: ISection;
26
+ title: string | undefined;
27
+ completed: boolean;
28
+ startDate?: Date;
29
+ EndDate?: Date;
30
+ CompleteConfirmation?: boolean;
31
+ markComplete(): void;
32
+ markIncomplete(): void;
33
+ create(): void;
34
+ }
35
+ export declare enum MetricDataType {
36
+ SHOP_HRS = "SHOP_HRS",
37
+ ENG_HRS = "ENG_HRS",
38
+ SHOP_HRS_BUDGET = "SHOP_HRS_BUDGET",
39
+ ENG_HRS_BUDGET = "ENG_HRS_BUDGET",
40
+ SHOP_HRS_ACTUAL = "SHOP_HRS_ACTUAL",
41
+ ENG_HRS_ACTUAL = "ENG_HRS_ACTUAL",
42
+ SSC_HRS = "SSC_HRS",
43
+ SSC_HRS_BUDGET = "SSC_HRS_BUDGET",
44
+ SSC_HRS_ACTUAL = "SSC_HRS_ACTUAL",
45
+ ESC_HRS = "ESC_HRS",
46
+ ESC_HRS_BUDGET = "ESC_HRS_BUDGET",
47
+ ESC_HRS_ACTUAL = "ESC_HRS_ACTUAL"
48
+ }
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MetricDataType = void 0;
4
+ var MetricDataType;
5
+ (function (MetricDataType) {
6
+ MetricDataType["SHOP_HRS"] = "SHOP_HRS";
7
+ MetricDataType["ENG_HRS"] = "ENG_HRS";
8
+ MetricDataType["SHOP_HRS_BUDGET"] = "SHOP_HRS_BUDGET";
9
+ MetricDataType["ENG_HRS_BUDGET"] = "ENG_HRS_BUDGET";
10
+ MetricDataType["SHOP_HRS_ACTUAL"] = "SHOP_HRS_ACTUAL";
11
+ MetricDataType["ENG_HRS_ACTUAL"] = "ENG_HRS_ACTUAL";
12
+ MetricDataType["SSC_HRS"] = "SSC_HRS";
13
+ MetricDataType["SSC_HRS_BUDGET"] = "SSC_HRS_BUDGET";
14
+ MetricDataType["SSC_HRS_ACTUAL"] = "SSC_HRS_ACTUAL";
15
+ MetricDataType["ESC_HRS"] = "ESC_HRS";
16
+ MetricDataType["ESC_HRS_BUDGET"] = "ESC_HRS_BUDGET";
17
+ MetricDataType["ESC_HRS_ACTUAL"] = "ESC_HRS_ACTUAL";
18
+ })(MetricDataType || (exports.MetricDataType = MetricDataType = {}));
@@ -0,0 +1,3 @@
1
+ export * from "./core/SpotifyTypes.js";
2
+ export { SpotifyHelper } from "./core/SpotifyHelper.js";
3
+ export { SpotifyConfiguration } from "./core/SpotifyConfiguration.js";
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export * from "./core/SpotifyTypes.js";
2
+ export { SpotifyHelper } from "./core/SpotifyHelper.js";
3
+ export { SpotifyConfiguration } from "./core/SpotifyConfiguration.js";
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@benliam12/spotify-api-helper",
3
+ "version": "1.0.0-DEV.3",
4
+ "description": "A utility package for Node.js",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "test": "jest",
14
+ "lint": "eslint src --ext .ts",
15
+ "prepare": "npm run build",
16
+ "semantic-release": "semantic-release"
17
+ },
18
+ "keywords": [
19
+ "utility",
20
+ "helpers"
21
+ ],
22
+ "author": "benliam12",
23
+ "license": "MIT",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+https://github.com/Benliam12/SpotifyAPIHelper.git"
27
+ },
28
+ "bugs": {
29
+ "url": "https://github.com/Benliam12/SpotifyAPIHelper/issues"
30
+ },
31
+ "homepage": "https://github.com/Benliam12/SpotifyAPIHelper#readme",
32
+ "devDependencies": {
33
+ "@types/jest": "^30.0.0",
34
+ "@types/node": "^22.19.3",
35
+ "@typescript-eslint/eslint-plugin": "^8.50.1",
36
+ "@typescript-eslint/parser": "^8.50.1",
37
+ "eslint": "^9.39.2",
38
+ "jest": "^29.7.0",
39
+ "semantic-release": "^25.0.2",
40
+ "ts-jest": "^29.4.6",
41
+ "typescript": "^5.9.3"
42
+ },
43
+ "publishConfig": {
44
+ "access": "public"
45
+ }
46
+ }