@jphil/bookwhen-client 0.0.9 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +20 -6
  2. package/dist/client/BookwhenClient.d.ts +38 -0
  3. package/dist/client/BookwhenClient.integration.test.d.ts +1 -0
  4. package/dist/client/BookwhenClient.integration.test.js +78 -0
  5. package/dist/client/BookwhenClient.integration.test.js.map +1 -0
  6. package/dist/client/BookwhenClient.js +69 -0
  7. package/dist/client/BookwhenClient.js.map +1 -0
  8. package/dist/client/BookwhenClient.unit.test.d.ts +1 -0
  9. package/dist/client/BookwhenClient.unit.test.js +70 -0
  10. package/dist/client/BookwhenClient.unit.test.js.map +1 -0
  11. package/dist/index.d.ts +3 -1
  12. package/dist/index.js +5 -3
  13. package/dist/index.js.map +1 -1
  14. package/dist/index.test.js +9 -3
  15. package/dist/index.test.js.map +1 -1
  16. package/dist/request/BookwhenRequest.d.ts +46 -0
  17. package/dist/request/BookwhenRequest.js +126 -0
  18. package/dist/request/BookwhenRequest.js.map +1 -0
  19. package/dist/request/BookwhenRequest.unit.test.d.ts +1 -0
  20. package/dist/request/BookwhenRequest.unit.test.js +141 -0
  21. package/dist/request/BookwhenRequest.unit.test.js.map +1 -0
  22. package/dist/request/httpStatusCodes.d.ts +3 -0
  23. package/dist/request/httpStatusCodes.js +15 -0
  24. package/dist/request/httpStatusCodes.js.map +1 -0
  25. package/dist/services/event/Event.d.ts +32 -0
  26. package/dist/services/event/Event.js +72 -0
  27. package/dist/services/event/Event.js.map +1 -0
  28. package/dist/services/event/Event.unit.test.d.ts +1 -0
  29. package/dist/services/event/Event.unit.test.js +104 -0
  30. package/dist/services/event/Event.unit.test.js.map +1 -0
  31. package/dist/services/event/EventInterfaces.d.ts +53 -0
  32. package/dist/services/event/EventInterfaces.js +3 -0
  33. package/dist/services/event/EventInterfaces.js.map +1 -0
  34. package/dist/services/event/EventSchemas.d.ts +12 -0
  35. package/dist/services/event/EventSchemas.js +8 -0
  36. package/dist/services/event/EventSchemas.js.map +1 -0
  37. package/dist/services/event/EventTypes.d.ts +36 -0
  38. package/dist/services/event/EventTypes.js +2 -0
  39. package/dist/services/event/EventTypes.js.map +1 -0
  40. package/dist/types/GlobalTypes.d.ts +9 -0
  41. package/dist/types/GlobalTypes.js +2 -0
  42. package/dist/types/GlobalTypes.js.map +1 -0
  43. package/dist/utils/http-utils.d.ts +8 -0
  44. package/dist/utils/http-utils.js +19 -0
  45. package/dist/utils/http-utils.js.map +1 -0
  46. package/package.json +12 -5
package/README.md CHANGED
@@ -21,8 +21,8 @@ You'll likely be at least somewhat familiar with the [Bookwhen](www.bookwhen.com
21
21
 
22
22
  ## Features
23
23
 
24
- - Lightweight and easy to integrate
25
- - Fully typed for TypeScript support
24
+ - Provides an easy way to pull your data from Bookwhen for NodeJS environments
25
+ - Provides fully typed methods for each model (so far just the events model) in the Bookwhen API v2
26
26
 
27
27
  ## Installation
28
28
 
@@ -34,10 +34,18 @@ pnpm add @jphil/bookwhen-client
34
34
 
35
35
  ## Usage
36
36
 
37
- \[wip\]!
37
+ !N.B. this usage structure may change as I progress towards a 1.0.0
38
38
 
39
39
  ```typescript
40
- // ... todo
40
+ import { createBookwhenClient } from 'bookwhen-client';
41
+
42
+ const client = createBookwhenClient(YOUR_API_KEY)
43
+ const event = client.event.getByID({myEventId});
44
+ const events = client.event.getMultiple({
45
+ filters: ["filter1", "filter2"]
46
+ includes: ["inc1", "inc2"]
47
+ });
48
+
41
49
  ```
42
50
 
43
51
  ## Configuration
@@ -56,9 +64,15 @@ Please see the docs in the CONTRIBUTIONS.md file, thanks!
56
64
 
57
65
  ## Roadmap
58
66
 
59
- - Keep up with any future changes or additions to the [Bookwhen API](https://api.bookwhen.com/v2).
67
+ - Keep up with any future changes or additions to the [Bookwhen API](https://api.bookwhen.com/v2), additions will be driven mainly by this.
68
+ - Possibly add a "fields" param to service methods to allow response filtering
69
+
70
+ - Todos
71
+ [] - put Zod in place in more areas to strengthen runtime type guards
72
+ [] - refine error handling
73
+ [] - write more integration tests
74
+ [] - write services for the other integrations
60
75
 
61
76
  ## License
62
77
 
63
78
  ISC License. See [LICENSE](LICENSE) for more information.
64
-
@@ -0,0 +1,38 @@
1
+ import type { AxiosInstance } from 'axios';
2
+ import { EventService } from '../services/event/Event.js';
3
+ /**
4
+ * Client for the Bookwhen API.
5
+ *
6
+ * @see https://petstore.swagger.io/?url=https://api.bookwhen.com/v2/openapi.yaml#/ClassPass/get_class_passes__class_pass_id_
7
+ */
8
+ export declare class BookwhenClient {
9
+ private axiosInstance;
10
+ private eventService?;
11
+ /**
12
+ * Creates a new instance of the BookwhenClient class.
13
+ * @param axiosInstance - Configured Axios instance for making HTTP requests.
14
+ * @throws Error if axiosInstance is not provided.
15
+ */
16
+ constructor(axiosInstance: AxiosInstance);
17
+ /**
18
+ * Gets the EventService instance.
19
+ *
20
+ * Available methods:
21
+ * - getById(params: GetEventByIdParams): Promise<BookwhenEvent>
22
+ * - getMultiple(params: GetMultipleEventsParams): Promise<BookwhenEvent[]>
23
+ *
24
+ * @returns The EventService instance.
25
+ */
26
+ get events(): EventService;
27
+ }
28
+ interface BookwhenClientOptions {
29
+ apiKey: string;
30
+ baseURL?: string;
31
+ }
32
+ /**
33
+ * Creates an instance of Axios with the provided API key.
34
+ * @param apiKey - The API key used for authentication.
35
+ * @returns The Axios instance.
36
+ */
37
+ export declare function createBookwhenClient(options: BookwhenClientOptions): BookwhenClient;
38
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,78 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
2
+ import { BookwhenClient } from './BookwhenClient.js';
3
+ import { EventService } from '../services/event/Event.js';
4
+ vi.mock('axios');
5
+ vi.mock('../src/services/event/Event');
6
+ describe('BookwhenClient Integration', () => {
7
+ describe('BookwhenClient - Events Service', () => {
8
+ it('should call the correct endpoint when getById is called', async () => {
9
+ const mockAxiosInstance = {
10
+ get: vi.fn().mockResolvedValue({
11
+ data: {
12
+ data: { id: 'event123' }
13
+ }
14
+ }),
15
+ };
16
+ const client = new BookwhenClient(mockAxiosInstance);
17
+ const eventId = 'event123';
18
+ const event = await client.events.getById({ eventId });
19
+ expect(mockAxiosInstance.get).toHaveBeenCalledWith('/events/event123');
20
+ expect(event).toEqual({ id: 'event123' });
21
+ });
22
+ it('should call the correct endpoint with correct parameters when events.getMultiple is called', async () => {
23
+ const mockAxiosInstance = {
24
+ get: vi.fn().mockResolvedValue({
25
+ data: {
26
+ data: [{ id: 'event1' }, { id: 'event2' }],
27
+ },
28
+ }),
29
+ };
30
+ const client = new BookwhenClient(mockAxiosInstance);
31
+ const includes = ['location', 'tickets'];
32
+ const filters = {
33
+ title: ['Workshop'],
34
+ start_at: ['2023-01-01']
35
+ };
36
+ const eventsData = [
37
+ { id: '1', type: 'event' },
38
+ { id: '2', type: 'event' },
39
+ ];
40
+ const events = await client.events.getMultiple({ includes, filters });
41
+ expect(mockAxiosInstance.get).toHaveBeenCalledWith('/events?filter[title]=Workshop&filter[start_at]=2023-01-01&include=location,tickets');
42
+ expect(events).toEqual([{ id: 'event1' }, { id: 'event2' }]);
43
+ });
44
+ it('should correctly initialize and expose the events service via the client', () => {
45
+ const mockAxiosInstance = {};
46
+ const client = new BookwhenClient(mockAxiosInstance);
47
+ const eventsService = client.events;
48
+ expect(eventsService).toBeInstanceOf(EventService);
49
+ });
50
+ it('should use the same axios instance in events service as in the BookwhenClient', () => {
51
+ const mockAxiosInstance = {};
52
+ const client = new BookwhenClient(mockAxiosInstance);
53
+ const eventsService = client.events;
54
+ expect(eventsService['axiosInstance']).toBe(client['axiosInstance']);
55
+ });
56
+ it('should handle errors thrown by the events service methods', async () => {
57
+ const mockAxiosInstance = {
58
+ get: vi.fn().mockRejectedValue(new Error('Network Error')),
59
+ };
60
+ const client = new BookwhenClient(mockAxiosInstance);
61
+ // @ts-ignore - Testing invalid parameter type
62
+ await expect(client.events.getById(453453)).rejects.toThrow('events.getById: Schema Validation failed: Expected object, received number');
63
+ // @ts-ignore - Testing invalid parameter type
64
+ await expect(client.events.getById('invalidId')).rejects.toThrow('events.getById: Schema Validation failed: Expected object, received string');
65
+ });
66
+ it('should correctly pass filters and includes to events.getMultiple method', async () => {
67
+ const mockAxiosInstance = {
68
+ get: vi.fn().mockResolvedValue({ data: { data: [] } }),
69
+ };
70
+ const client = new BookwhenClient(mockAxiosInstance);
71
+ const filters = { tag: ['workshop', 'seminar'], from: '20220101' };
72
+ const includes = ['location', 'tickets.events'];
73
+ await client.events.getMultiple({ filters, includes });
74
+ expect(mockAxiosInstance.get).toHaveBeenCalledWith('/events?filter[tag]=workshop,seminar&filter[from]=20220101&include=location,tickets.events');
75
+ });
76
+ });
77
+ });
78
+ //# sourceMappingURL=BookwhenClient.integration.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BookwhenClient.integration.test.js","sourceRoot":"","sources":["../../src/client/BookwhenClient.integration.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ // src/clients/BookwhenClient.ts
2
+ import axios from 'axios';
3
+ import { EventService } from '../services/event/Event.js'; // Ensure this file and class are setup accordingly
4
+ import { CLIENT_HTTP_STATUS_CODES } from '../request/httpStatusCodes.js';
5
+ /**
6
+ * Client for the Bookwhen API.
7
+ *
8
+ * @see https://petstore.swagger.io/?url=https://api.bookwhen.com/v2/openapi.yaml#/ClassPass/get_class_passes__class_pass_id_
9
+ */
10
+ export class BookwhenClient {
11
+ axiosInstance;
12
+ eventService;
13
+ /**
14
+ * Creates a new instance of the BookwhenClient class.
15
+ * @param axiosInstance - Configured Axios instance for making HTTP requests.
16
+ * @throws Error if axiosInstance is not provided.
17
+ */
18
+ constructor(axiosInstance) {
19
+ this.axiosInstance = axiosInstance;
20
+ if (!axiosInstance) {
21
+ throw new Error('BookwhenClient - you must provide an axios instance');
22
+ }
23
+ }
24
+ /**
25
+ * Gets the EventService instance.
26
+ *
27
+ * Available methods:
28
+ * - getById(params: GetEventByIdParams): Promise<BookwhenEvent>
29
+ * - getMultiple(params: GetMultipleEventsParams): Promise<BookwhenEvent[]>
30
+ *
31
+ * @returns The EventService instance.
32
+ */
33
+ get events() {
34
+ if (!this.eventService) {
35
+ this.eventService = new EventService(this.axiosInstance);
36
+ }
37
+ return this.eventService;
38
+ }
39
+ }
40
+ /**
41
+ * Creates an instance of Axios with the provided API key.
42
+ * @param apiKey - The API key used for authentication.
43
+ * @returns The Axios instance.
44
+ */
45
+ export function createBookwhenClient(options) {
46
+ const { apiKey, baseURL = 'https://api.bookwhen.com/v2' } = options;
47
+ const axiosInstance = axios.create({
48
+ baseURL: 'https://api.bookwhen.com/v2',
49
+ auth: { username: apiKey, password: '' },
50
+ });
51
+ axiosInstance.interceptors.response.use((response) => response.data ?? response, (error) => {
52
+ if (error.response) {
53
+ const status = error.response.status;
54
+ const clientError = CLIENT_HTTP_STATUS_CODES[status];
55
+ if (clientError) {
56
+ return Promise.reject(new Error(clientError.message));
57
+ }
58
+ }
59
+ else if (error.request) {
60
+ throw new Error('No response received from the server');
61
+ }
62
+ else {
63
+ throw new Error('An error occurred setting up the request');
64
+ }
65
+ return Promise.reject(error);
66
+ });
67
+ return new BookwhenClient(axiosInstance);
68
+ }
69
+ //# sourceMappingURL=BookwhenClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BookwhenClient.js","sourceRoot":"","sources":["../../src/client/BookwhenClient.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC,CAAE,mDAAmD;AAC/G,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAEzE;;;;GAIG;AACH,MAAM,OAAO,cAAc;IAQL;IAPZ,YAAY,CAAgB;IAEpC;;;;OAIG;IACH,YAAoB,aAA4B;QAA5B,kBAAa,GAAb,aAAa,CAAe;QAC9C,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;QACzE,CAAC;IACH,CAAC;IAED;;;;;;;;OAQG;IACH,IAAI,MAAM;QACR,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YACvB,IAAI,CAAC,YAAY,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC3D,CAAC;QACD,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;CACF;AAOD;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAClC,OAA8B;IAE9B,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,6BAA6B,EAAE,GAAG,OAAO,CAAC;IAEpE,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC;QACjC,OAAO,EAAE,6BAA6B;QACtC,IAAI,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE;KACzC,CAAC,CAAC;IAEH,aAAa,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,CACrC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,IAAI,QAAQ,EACvC,CAAC,KAAK,EAAE,EAAE;QACR,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YACnB,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;YACrC,MAAM,WAAW,GAAG,wBAAwB,CAAC,MAAM,CAAC,CAAC;YACrD,IAAI,WAAW,EAAE,CAAC;gBAChB,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC;YACxD,CAAC;QACH,CAAC;aAAM,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAC1D,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC9D,CAAC;QACD,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC,CACF,CAAC;IAEF,OAAO,IAAI,cAAc,CAAC,aAAa,CAAC,CAAC;AAC3C,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,70 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
2
+ import axios from 'axios';
3
+ import { createBookwhenClient } from './BookwhenClient.js';
4
+ import { BookwhenClient } from './BookwhenClient.js';
5
+ import { EventService } from '../services/event/Event.js';
6
+ vi.mock('axios');
7
+ vi.mock('../src/services/event/Event');
8
+ describe('BookwhenClient', () => {
9
+ it('should throw an error if axiosInstance is not provided', () => {
10
+ expect(() => new BookwhenClient(undefined)).toThrowError('BookwhenClient - you must provide an axios instance');
11
+ });
12
+ it('should assign axiosInstance correctly', () => {
13
+ const mockAxiosInstance = {};
14
+ const client = new BookwhenClient(mockAxiosInstance);
15
+ expect(client['axiosInstance']).toBe(mockAxiosInstance);
16
+ });
17
+ it('should expose EventService via getter', () => {
18
+ const mockAxiosInstance = {};
19
+ const client = new BookwhenClient(mockAxiosInstance);
20
+ const eventService = client.events;
21
+ expect(eventService['axiosInstance']).toBe(mockAxiosInstance);
22
+ expect(eventService).toBeInstanceOf(EventService);
23
+ });
24
+ it('should share axiosInstance with EventService', () => {
25
+ const mockAxiosInstance = {};
26
+ const client = new BookwhenClient(mockAxiosInstance);
27
+ const eventService = client.events;
28
+ expect(eventService['axiosInstance']).toBe(mockAxiosInstance);
29
+ });
30
+ });
31
+ describe('createBookwhenClient', () => {
32
+ let mockAxiosInstance;
33
+ beforeEach(() => {
34
+ // Create mock axios instance with interceptors
35
+ mockAxiosInstance = {
36
+ interceptors: {
37
+ response: {
38
+ use: vi.fn()
39
+ },
40
+ request: {
41
+ use: vi.fn()
42
+ }
43
+ }
44
+ };
45
+ // Mock axios.create to return our mock instance
46
+ vi.spyOn(axios, 'create').mockReturnValue(mockAxiosInstance);
47
+ });
48
+ it('should create an axiosInstance with correct config and return a BookwhenClient', () => {
49
+ const apiKey = 'test-api-key';
50
+ const client = createBookwhenClient({ apiKey });
51
+ expect(axios.create).toHaveBeenCalledWith({
52
+ baseURL: 'https://api.bookwhen.com/v2',
53
+ auth: { username: apiKey, password: '' },
54
+ });
55
+ expect(mockAxiosInstance.interceptors.response.use).toHaveBeenCalled();
56
+ expect(client).toBeInstanceOf(BookwhenClient);
57
+ });
58
+ it('should handle errors using the interceptor', async () => {
59
+ const axiosInstance = axios.create();
60
+ const errorResponse = { response: { status: 400 } };
61
+ vi.spyOn(axios, 'create').mockReturnValue(axiosInstance);
62
+ // Mock the interceptor
63
+ const interceptor = vi.fn();
64
+ axiosInstance.interceptors.response.use = interceptor;
65
+ createBookwhenClient({ apiKey: 'test-api-key' });
66
+ const [, errorHandler] = interceptor.mock.calls[0];
67
+ await expect(errorHandler(errorResponse)).rejects.toThrowError('BookwhenClient: Bad request');
68
+ });
69
+ });
70
+ //# sourceMappingURL=BookwhenClient.unit.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BookwhenClient.unit.test.js","sourceRoot":"","sources":["../../src/client/BookwhenClient.unit.test.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1 +1,3 @@
1
- export declare const test: () => void;
1
+ export * from './types/GlobalTypes.js';
2
+ export * from './services/event/EventInterfaces.js';
3
+ export { createBookwhenClient } from './client/BookwhenClient.js';
package/dist/index.js CHANGED
@@ -1,4 +1,6 @@
1
- export const test = () => {
2
- console.log('hello test');
3
- };
1
+ import * as dotenv from 'dotenv';
2
+ dotenv.config();
3
+ export * from './types/GlobalTypes.js';
4
+ export * from './services/event/EventInterfaces.js';
5
+ export { createBookwhenClient } from './client/BookwhenClient.js';
4
6
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,IAAI,GAAG,GAAG,EAAE;IACvB,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;AAC5B,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,MAAM,CAAC,MAAM,EAAE,CAAC;AAEhB,cAAc,wBAAwB,CAAC;AACvC,cAAc,qCAAqC,CAAC;AAEpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC"}
@@ -1,7 +1,13 @@
1
1
  import { describe, it, expect } from 'vitest';
2
- describe('something', () => {
3
- it('should pass CI', () => {
4
- expect(1).toBe(1);
2
+ import * as dotenv from 'dotenv';
3
+ import { createBookwhenClient } from './index.js';
4
+ dotenv.config();
5
+ describe('index.ts', () => {
6
+ it('should load environment variables', () => {
7
+ expect(process.env).toHaveProperty('NODE_ENV');
8
+ });
9
+ it('should export BookwhenClient', () => {
10
+ expect(createBookwhenClient).toBeDefined();
5
11
  });
6
12
  });
7
13
  //# sourceMappingURL=index.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE9C,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;IACzB,EAAE,CAAC,gBAAgB,EAAE,GAAG,EAAE;QACxB,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,CAAC,MAAM,EAAE,CAAC;AAEhB,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE;IACtB,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QACzC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,oBAAoB,CAAC,CAAC,WAAW,EAAE,CAAC;IAC/C,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
@@ -0,0 +1,46 @@
1
+ import type { Resources, Filters } from "../types/GlobalTypes.js";
2
+ /**
3
+ * QueryBuilder class to help build query strings for Bookwhen API requests.
4
+ */
5
+ export declare class BookwhenRequest {
6
+ private path;
7
+ private filters;
8
+ private includes;
9
+ constructor(path: string);
10
+ /**
11
+ * Adds filters to the BookwhenQuery object.
12
+ * @param filters - An array of key-value pairs representing the filters to be added.
13
+ *
14
+ * Example resultant query strings:
15
+ * /v2/events?filter[from]=20200401&filter[to]=20200404
16
+ * /v2/events?filter[tag]=tag%20one,tag%20two
17
+ * /v2/events?filter[title]=advanced,pro&filter[detail]=masterclass
18
+ *
19
+ * @see https://petstore.swagger.io/?url=https://api.bookwhen.com/v2/openapi.yaml
20
+ *
21
+ * @returns The updated BookwhenQuery object.
22
+ */
23
+ addFilters(filters: Filters): BookwhenRequest;
24
+ /**
25
+ * Adds an include query parameter to the BookwhenRequest object.
26
+ * @param includes - An array of strings representing the resources to include.
27
+ *
28
+ * @returns The updated BookwhenRequest object.
29
+ *
30
+ * @throws Error if any include is not a valid string.
31
+ */
32
+ addIncludes(includes: Resources): BookwhenRequest;
33
+ /**
34
+ * Does the actual work of putting together a valid query string given:
35
+ * - filters
36
+ * - includes
37
+ * - segments
38
+ *
39
+ * @returns
40
+ */
41
+ build(): string;
42
+ /**
43
+ * @returns the constructed query string
44
+ */
45
+ toString(): string;
46
+ }
@@ -0,0 +1,126 @@
1
+ import z from 'zod';
2
+ /**
3
+ * QueryBuilder class to help build query strings for Bookwhen API requests.
4
+ */
5
+ export class BookwhenRequest {
6
+ path = '';
7
+ filters = [];
8
+ includes = [];
9
+ constructor(path) {
10
+ try {
11
+ if (!path) {
12
+ throw new Error('Path is required');
13
+ }
14
+ this.path = path;
15
+ }
16
+ catch (error) {
17
+ throw new Error("BookwhenQuery error: " + error.message);
18
+ }
19
+ }
20
+ /**
21
+ * Adds filters to the BookwhenQuery object.
22
+ * @param filters - An array of key-value pairs representing the filters to be added.
23
+ *
24
+ * Example resultant query strings:
25
+ * /v2/events?filter[from]=20200401&filter[to]=20200404
26
+ * /v2/events?filter[tag]=tag%20one,tag%20two
27
+ * /v2/events?filter[title]=advanced,pro&filter[detail]=masterclass
28
+ *
29
+ * @see https://petstore.swagger.io/?url=https://api.bookwhen.com/v2/openapi.yaml
30
+ *
31
+ * @returns The updated BookwhenQuery object.
32
+ */
33
+ addFilters(filters) {
34
+ // @todo add zod validation for filters?
35
+ try {
36
+ for (let key in filters) {
37
+ let value = filters[key];
38
+ if (Array.isArray(value) && value && value.length > 0) {
39
+ // const encodedValues = value.map((v: string) => {
40
+ // console.log('typeof v', typeof v);
41
+ // if (typeof v === 'undefined') {
42
+ // return '';
43
+ // }
44
+ // if (v.length === 0) {
45
+ // return '';
46
+ // }
47
+ // return encodeURIComponent(v);
48
+ // }).join(',');
49
+ const encodedValues = value
50
+ .filter((v) => typeof v === 'string' && v.length > 0)
51
+ .map((v) => encodeURIComponent(v))
52
+ .join(',');
53
+ this.filters.push(`filter[${encodeURIComponent(key)}]=${encodedValues}`);
54
+ }
55
+ else if (typeof value === 'string' && value !== '') {
56
+ if (key.length === 0) {
57
+ throw new Error('Invalid filter key' + key);
58
+ }
59
+ this.filters.push(`filter[${encodeURIComponent(key)}]=${encodeURIComponent(value)}`);
60
+ }
61
+ else if (typeof value === 'undefined' && value !== '') {
62
+ // ignore undefined values
63
+ }
64
+ }
65
+ }
66
+ catch (error) {
67
+ throw new Error("BookwhenQuery error: " + error.message);
68
+ }
69
+ return this;
70
+ }
71
+ /**
72
+ * Adds an include query parameter to the BookwhenRequest object.
73
+ * @param includes - An array of strings representing the resources to include.
74
+ *
75
+ * @returns The updated BookwhenRequest object.
76
+ *
77
+ * @throws Error if any include is not a valid string.
78
+ */
79
+ addIncludes(includes) {
80
+ try {
81
+ const validIncludes = includes.filter((include) => include.length > 0);
82
+ if (validIncludes.length !== includes.length) {
83
+ throw new Error('Invalid includes');
84
+ }
85
+ if (validIncludes.length > 0) {
86
+ const includeQuery = validIncludes.join(',');
87
+ this.includes.push(`include=${includeQuery}`);
88
+ }
89
+ }
90
+ catch (error) {
91
+ throw new Error("BookwhenQuery error: " + error.message);
92
+ }
93
+ return this;
94
+ }
95
+ /**
96
+ * Does the actual work of putting together a valid query string given:
97
+ * - filters
98
+ * - includes
99
+ * - segments
100
+ *
101
+ * @returns
102
+ */
103
+ build() {
104
+ let queryString = '';
105
+ // Concatenate filters and includes, if any
106
+ if (this.filters.length > 0) {
107
+ queryString += this.filters.join('&');
108
+ }
109
+ if (this.includes.length > 0) {
110
+ // Add '&' if filters already added to queryString
111
+ queryString += queryString ? '&' : '';
112
+ queryString += this.includes.join('&');
113
+ }
114
+ // Strip any leading slashes from this.path
115
+ const cleanedPath = this.path.replace(/^\/+/, '');
116
+ // Return the full URI, including query string only if it's non-empty
117
+ return `/${cleanedPath}${queryString ? '?' + queryString : ''}`;
118
+ }
119
+ /**
120
+ * @returns the constructed query string
121
+ */
122
+ toString() {
123
+ return this.build();
124
+ }
125
+ }
126
+ //# sourceMappingURL=BookwhenRequest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BookwhenRequest.js","sourceRoot":"","sources":["../../src/request/BookwhenRequest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,141 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
2
+ import { BookwhenRequest } from './BookwhenRequest.js';
3
+ describe('BookwhenRequest', () => {
4
+ const testpath = "path";
5
+ describe('path handling', () => {
6
+ it('should return a /"path" when called with "path"', () => {
7
+ const request = new BookwhenRequest(testpath);
8
+ expect(request.toString()).toBe('/' + testpath);
9
+ });
10
+ it('should throw an error if the path is empty', () => {
11
+ expect(() => new BookwhenRequest('')).toThrow('Path is required');
12
+ });
13
+ it('should throw an error if the path is undefined', () => {
14
+ expect(() => new BookwhenRequest(undefined)).toThrow('Path is required');
15
+ });
16
+ });
17
+ describe('addIncludes', () => {
18
+ it('should return the given path with an empty string when no resources are provided', () => {
19
+ const resources = [];
20
+ const query = new BookwhenRequest(testpath);
21
+ query.addIncludes(resources);
22
+ expect(query.toString()).toEqual('/' + testpath);
23
+ });
24
+ it('should return a query string with a single resource', () => {
25
+ const resources = ['resource1'];
26
+ const query = new BookwhenRequest(testpath);
27
+ query.addIncludes(resources);
28
+ expect(query.toString()).toEqual('/' + testpath + '?include=resource1');
29
+ });
30
+ it('should return a query string with multiple resources separated by commas', () => {
31
+ const resources = ['resource1', 'resource2', 'resource3'];
32
+ const query = new BookwhenRequest(testpath);
33
+ query.addIncludes(resources);
34
+ expect(query.toString()).toEqual('/' + testpath + '?include=resource1,resource2,resource3');
35
+ });
36
+ });
37
+ describe('addFilters', () => {
38
+ it('should return a query with no filters, if an empty filters array is given', () => {
39
+ const filters = {};
40
+ const query = new BookwhenRequest(testpath);
41
+ query.addFilters(filters);
42
+ expect(query.toString()).toEqual('/' + testpath);
43
+ });
44
+ it('should return a query string with a single filter', () => {
45
+ const filters = { 'key': "value" };
46
+ const query = new BookwhenRequest(testpath);
47
+ query.addFilters(filters);
48
+ expect(query.toString()).toEqual('/' + testpath + '?filter[key]=value');
49
+ });
50
+ it('should return a query string with a single filter and multiple values', () => {
51
+ const filters = { 'key': ['value one', 'value two'] };
52
+ const query = new BookwhenRequest(testpath);
53
+ query.addFilters(filters);
54
+ expect(query.toString()).toEqual('/' + testpath + '?filter[key]=value%20one,value%20two');
55
+ });
56
+ it('should return a query string with multiple filters where values are strings', () => {
57
+ const filters = {
58
+ title: 'advanced',
59
+ detail: 'masterclass',
60
+ };
61
+ const query = new BookwhenRequest(testpath);
62
+ query.addFilters(filters);
63
+ expect(query.toString()).toEqual('/' + testpath + '?filter[title]=advanced&filter[detail]=masterclass');
64
+ });
65
+ it('should return a query string with multiple filters where values are arrays of strings', () => {
66
+ const filters = {
67
+ title: ['title1', 'title2'],
68
+ detail: ['detail1', 'detail2', 'detail3'],
69
+ };
70
+ const query = new BookwhenRequest(testpath);
71
+ query.addFilters(filters);
72
+ expect(query.toString()).toEqual('/' + testpath + '?filter[title]=title1,title2&filter[detail]=detail1,detail2,detail3');
73
+ });
74
+ it('should ignore empty string filter values', () => {
75
+ const filters = { key: '', key2: 'value' };
76
+ const query = new BookwhenRequest(testpath);
77
+ query.addFilters(filters);
78
+ expect(query.toString()).toEqual('/' + testpath + '?filter[key2]=value');
79
+ });
80
+ it('should ignore undefined filter values', () => {
81
+ const filters = { key: undefined, key2: 'value' };
82
+ const query = new BookwhenRequest(testpath);
83
+ query.addFilters(filters);
84
+ expect(query.toString()).toEqual('/' + testpath + '?filter[key2]=value');
85
+ });
86
+ it('should ignore null filter values', () => {
87
+ const filters = { key: null, key2: 'value' };
88
+ const query = new BookwhenRequest(testpath);
89
+ query.addFilters(filters);
90
+ expect(query.toString()).toEqual('/' + testpath + '?filter[key2]=value');
91
+ });
92
+ it('should ignore an "empty array" filter value', () => {
93
+ const filters = { key: [] };
94
+ const query = new BookwhenRequest(testpath);
95
+ query.addFilters(filters);
96
+ expect(query.toString()).toEqual('/' + testpath);
97
+ });
98
+ it('should ignore empty string elements, where a filter value is an array', () => {
99
+ const filters = { key: ['', 'value'] };
100
+ const query = new BookwhenRequest(testpath);
101
+ expect(query.toString()).toEqual('/' + testpath);
102
+ });
103
+ it('should ignore undefined array elements, where a filter value is an array', () => {
104
+ const filters = { key: [undefined, 'value'], key2: 'value2' };
105
+ const query = new BookwhenRequest(testpath);
106
+ query.addFilters(filters);
107
+ expect(query.toString()).toEqual('/' + testpath + '?filter[key]=value&filter[key2]=value2');
108
+ });
109
+ it('should ignore null array elements, where a filter value is an array', () => {
110
+ const filters = { key: [null, 'value'], key2: 'value2' };
111
+ const query = new BookwhenRequest(testpath);
112
+ query.addFilters(filters);
113
+ expect(query.toString()).toEqual('/' + testpath + '?filter[key]=value&filter[key2]=value2');
114
+ });
115
+ it('should return a query string with a single filter when value is an array with a single value', () => {
116
+ const filters = { key: ['value'] };
117
+ const query = new BookwhenRequest(testpath);
118
+ query.addFilters(filters);
119
+ expect(query.toString()).toEqual('/' + testpath + '?filter[key]=value');
120
+ });
121
+ it('should build a URL query string from the provided parameters, skipping invalid value types', () => {
122
+ const params = {
123
+ key1: 'value1',
124
+ key2: ['value2', null, 'value3', ''],
125
+ key3: undefined,
126
+ key4: ['key3skipped', undefined, '123'],
127
+ key5: "1234",
128
+ key6: null,
129
+ key7: undefined,
130
+ key8: [],
131
+ key9: 'undefined',
132
+ };
133
+ const expectedFilterString = '/path?filter[key1]=value1&filter[key2]=value2,value3&filter[key4]=key3skipped,123&filter[key5]=1234&filter[key9]=undefined';
134
+ const query = new BookwhenRequest(testpath);
135
+ // @ts-ignore
136
+ query.addFilters(params);
137
+ expect(query.toString()).toEqual(expectedFilterString);
138
+ });
139
+ });
140
+ });
141
+ //# sourceMappingURL=BookwhenRequest.unit.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BookwhenRequest.unit.test.js","sourceRoot":"","sources":["../../src/request/BookwhenRequest.unit.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { HttpStatus } from '../types/GlobalTypes.js';
2
+ export declare const CLIENT_HTTP_STATUS_CODES: Record<number, HttpStatus>;
3
+ export declare const SERVICE_HTTP_STATUS_CODES: Record<number, HttpStatus>;
@@ -0,0 +1,15 @@
1
+ export const CLIENT_HTTP_STATUS_CODES = {
2
+ 400: { code: 400, message: 'BookwhenClient: Bad request' },
3
+ 401: { code: 401, message: 'BookwhenClient: Unauthorized - check your API key' },
4
+ 403: { code: 403, message: 'BookwhenClient: Forbidden - check your permissions' },
5
+ 500: { code: 500, message: 'BookwhenClient: Internal server error' },
6
+ 502: { code: 502, message: 'BookwhenClient: Bad gateway' },
7
+ 503: { code: 503, message: 'BookwhenClient: Service unavailable' },
8
+ 504: { code: 504, message: 'BookwhenClient: Gateway timeout' },
9
+ };
10
+ export const SERVICE_HTTP_STATUS_CODES = {
11
+ 400: { code: 400, message: 'BookwhenClient: Bad request' },
12
+ 404: { code: 404, message: 'BookwhenClient: The requested resource could not be found' },
13
+ 429: { code: 429, message: 'BookwhenClient: Rate limit exceeded' },
14
+ };
15
+ //# sourceMappingURL=httpStatusCodes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"httpStatusCodes.js","sourceRoot":"","sources":["../../src/request/httpStatusCodes.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,wBAAwB,GAA+B;IAClE,GAAG,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,6BAA6B,EAAE;IAC1D,GAAG,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,mDAAmD,EAAE;IAChF,GAAG,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,oDAAoD,EAAE;IACjF,GAAG,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,uCAAuC,EAAE;IACpE,GAAG,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,6BAA6B,EAAE;IAC1D,GAAG,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,qCAAqC,EAAE;IAClE,GAAG,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,iCAAiC,EAAE;CAC/D,CAAC;AAEF,MAAM,CAAC,MAAM,yBAAyB,GAA+B;IACnE,GAAG,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,6BAA6B,EAAE;IAC1D,GAAG,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,2DAA2D,EAAE;IACxF,GAAG,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,qCAAqC,EAAE;CACnE,CAAC"}
@@ -0,0 +1,32 @@
1
+ import type { IEventService, GetMultipleEventsParams } from './EventInterfaces.js';
2
+ import type { BookwhenEvent } from './EventTypes.js';
3
+ import type { AxiosInstance } from 'axios';
4
+ import { GetEventByIdParamsSchema } from './EventSchemas.js';
5
+ import { z } from 'zod';
6
+ /**
7
+ * Service class for managing events in the Bookwhen API.
8
+ */
9
+ export declare class EventService implements IEventService {
10
+ private axiosInstance;
11
+ /**
12
+ * Initializes EventService with an Axios instance for dependency injection.
13
+ * @param axiosInstance - The Axios instance to use for API requests.
14
+ */
15
+ constructor(axiosInstance: AxiosInstance);
16
+ /**
17
+ * Retrieves a single event by its ID from the Bookwhen API.
18
+ *
19
+ * @param {Object} param - The parameters for retrieving an event.
20
+ * @param {string} param.eventId - The ID of the event to retrieve.
21
+ * @param {string} [param.include] - Optional parameter to include additional data.
22
+ * @returns {Promise<BookwhenEvent>} A Promise that resolves to the BookwhenEvent object.
23
+ */
24
+ getById(params: z.infer<typeof GetEventByIdParamsSchema>): Promise<BookwhenEvent>;
25
+ /**
26
+ * Retrieves multiple events based on filtering and pagination parameters.
27
+ *
28
+ * @param {GetMultipleEventsParams} params - Optional parameters for filtering and pagination.
29
+ * @return {Promise<BookwhenEvent[]>} A Promise that resolves to an array of BookwhenEvent objects.
30
+ */
31
+ getMultiple(params?: GetMultipleEventsParams): Promise<BookwhenEvent[]>;
32
+ }
@@ -0,0 +1,72 @@
1
+ import { handleServiceHTTPErrors } from '../../utils/http-utils.js';
2
+ import { SERVICE_HTTP_STATUS_CODES } from '../../request/httpStatusCodes.js';
3
+ import { BookwhenRequest } from '../../request/BookwhenRequest.js';
4
+ import { GetEventByIdParamsSchema } from './EventSchemas.js';
5
+ import { z } from 'zod';
6
+ /**
7
+ * Service class for managing events in the Bookwhen API.
8
+ */
9
+ export class EventService {
10
+ axiosInstance;
11
+ /**
12
+ * Initializes EventService with an Axios instance for dependency injection.
13
+ * @param axiosInstance - The Axios instance to use for API requests.
14
+ */
15
+ constructor(axiosInstance) {
16
+ this.axiosInstance = axiosInstance;
17
+ }
18
+ /**
19
+ * Retrieves a single event by its ID from the Bookwhen API.
20
+ *
21
+ * @param {Object} param - The parameters for retrieving an event.
22
+ * @param {string} param.eventId - The ID of the event to retrieve.
23
+ * @param {string} [param.include] - Optional parameter to include additional data.
24
+ * @returns {Promise<BookwhenEvent>} A Promise that resolves to the BookwhenEvent object.
25
+ */
26
+ async getById(params) {
27
+ try {
28
+ const validParams = GetEventByIdParamsSchema.parse(params);
29
+ const query = new BookwhenRequest(`/events/${validParams.eventId}`);
30
+ if (validParams.includes) {
31
+ query.addIncludes(validParams.includes);
32
+ }
33
+ const response = await this.axiosInstance.get(`${query}`);
34
+ return response.data?.data;
35
+ }
36
+ catch (error) {
37
+ if (error instanceof z.ZodError) {
38
+ const errorMessages = error.errors.map(e => e.message).join(', ');
39
+ throw new Error(`events.getById: Schema Validation failed: ${errorMessages}`);
40
+ }
41
+ else {
42
+ handleServiceHTTPErrors(error, SERVICE_HTTP_STATUS_CODES, {
43
+ 404: {
44
+ code: 404,
45
+ message: 'Event not found. Please check the event ID and try again.',
46
+ },
47
+ });
48
+ }
49
+ }
50
+ }
51
+ /**
52
+ * Retrieves multiple events based on filtering and pagination parameters.
53
+ *
54
+ * @param {GetMultipleEventsParams} params - Optional parameters for filtering and pagination.
55
+ * @return {Promise<BookwhenEvent[]>} A Promise that resolves to an array of BookwhenEvent objects.
56
+ */
57
+ async getMultiple(params = {}) {
58
+ try {
59
+ const query = new BookwhenRequest('/events');
60
+ if (params.includes)
61
+ query.addIncludes(params.includes);
62
+ if (params.filters)
63
+ query.addFilters(params.filters);
64
+ const response = await this.axiosInstance.get(`${query}`); // uses the toString method
65
+ return response.data.data;
66
+ }
67
+ catch (error) {
68
+ handleServiceHTTPErrors(error, SERVICE_HTTP_STATUS_CODES);
69
+ }
70
+ }
71
+ }
72
+ //# sourceMappingURL=Event.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Event.js","sourceRoot":"","sources":["../../../src/services/event/Event.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAC7E,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAEnE,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;GAEG;AACH,MAAM,OAAO,YAAY;IAEf,aAAa,CAAgB;IAErC;;;OAGG;IACH,YAAY,aAA4B;QACtC,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;IACrC,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,OAAO,CAAC,MAAgD;QAC5D,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,wBAAwB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAE3D,MAAM,KAAK,GAAG,IAAI,eAAe,CAAC,WAAW,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC;YACpE,IAAI,WAAW,CAAC,QAAQ,EAAE,CAAC;gBACzB,KAAK,CAAC,WAAW,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;YAC1C,CAAC;YAED,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAAgB,GAAG,KAAK,EAAE,CAAC,CAAC;YACzE,OAAO,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;QAC7B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,CAAC,CAAC,QAAQ,EAAE,CAAC;gBAChC,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAClE,MAAM,IAAI,KAAK,CAAC,6CAA6C,aAAa,EAAE,CAAC,CAAC;YAChF,CAAC;iBAAM,CAAC;gBACN,uBAAuB,CAAC,KAAK,EAAE,yBAAyB,EAAE;oBACxD,GAAG,EAAE;wBACH,IAAI,EAAE,GAAG;wBACT,OAAO,EAAE,2DAA2D;qBACrE;iBACF,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,WAAW,CAAC,SAAkC,EAAE;QACpD,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,IAAI,eAAe,CAAC,SAAS,CAAC,CAAC;YAC7C,IAAI,MAAM,CAAC,QAAQ;gBAAE,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YACxD,IAAI,MAAM,CAAC,OAAO;gBAAE,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAErD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAAiB,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,2BAA2B;YACtG,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;QAC5B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,uBAAuB,CAAC,KAAK,EAAE,yBAAyB,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,104 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
2
+ import axios from 'axios';
3
+ import { EventService } from './Event.js';
4
+ describe('EventService', () => {
5
+ let eventService;
6
+ let mockAxiosInstance;
7
+ beforeEach(() => {
8
+ // Create a mock instance of axios for dependency injection
9
+ mockAxiosInstance = axios.create();
10
+ eventService = new EventService(mockAxiosInstance); // Inject mock axios instance
11
+ });
12
+ afterEach(() => {
13
+ vi.restoreAllMocks();
14
+ });
15
+ it('should retrieve a single event by ID', async () => {
16
+ const eventId = '123';
17
+ const eventData = {
18
+ id: eventId,
19
+ };
20
+ // Mock Axios request using vi.spyOn
21
+ mockAxiosInstance.get = vi.fn().mockResolvedValue({ data: { data: eventData } });
22
+ const result = await eventService.getById({ eventId });
23
+ expect(mockAxiosInstance.get).toHaveBeenCalledWith(`/events/${eventId}`);
24
+ expect(result).toEqual(eventData);
25
+ });
26
+ it('should handle error when retrieving a single event by ID', async () => {
27
+ const eventId = '123';
28
+ const errorMessage = 'Event not found. Please check the event ID and try again.';
29
+ // Mock Axios request using vi.spyOn
30
+ vi.spyOn(mockAxiosInstance, 'get').mockRejectedValue({
31
+ response: {
32
+ status: 404,
33
+ data: { message: errorMessage }
34
+ }
35
+ });
36
+ expect(eventService.getById({ eventId })).rejects.toThrow(errorMessage);
37
+ });
38
+ it('should handle error when retrieving multiple events', async () => {
39
+ const errorMessage = 'BookwhenClient: The requested resource could not be found';
40
+ // Mock Axios request using vi.spyOn
41
+ vi.spyOn(mockAxiosInstance, 'get').mockRejectedValue({
42
+ response: {
43
+ status: 404,
44
+ data: { message: errorMessage }
45
+ }
46
+ });
47
+ expect(eventService.getMultiple()).rejects.toThrow(errorMessage);
48
+ expect(mockAxiosInstance.get).toHaveBeenCalledWith('/events');
49
+ });
50
+ it('should retrieve multiple events', async () => {
51
+ const eventsData = [
52
+ { id: '1', type: 'event' },
53
+ { id: '2', type: 'event' },
54
+ ];
55
+ // Mock Axios request using vi.spyOn
56
+ vi.spyOn(mockAxiosInstance, 'get').mockResolvedValue({ data: { data: eventsData } });
57
+ const result = await eventService.getMultiple();
58
+ expect(result).toEqual(eventsData);
59
+ });
60
+ it('should retrieve multiple events with filters', async () => {
61
+ const filters = {
62
+ title: ['Test Event'],
63
+ from: 'test',
64
+ detail: ['Event Details'],
65
+ };
66
+ const eventsData = [
67
+ { id: '1', type: 'event' },
68
+ { id: '2', type: 'event' },
69
+ ];
70
+ // Mock Axios request using vi.spyOn
71
+ vi.spyOn(mockAxiosInstance, 'get').mockResolvedValue({ data: { data: eventsData } });
72
+ const result = await eventService.getMultiple({ filters });
73
+ expect(result).toEqual(eventsData);
74
+ expect(mockAxiosInstance.get).toHaveBeenCalledWith('/events?filter[title]=Test%20Event&filter[from]=test&filter[detail]=Event%20Details');
75
+ });
76
+ it('should retrieve multiple events with includes', async () => {
77
+ const includes = ['location', 'attachments'];
78
+ const eventsData = [
79
+ { id: '1', type: 'event' },
80
+ { id: '2', type: 'event' },
81
+ ];
82
+ // Mock Axios request using vi.spyOn
83
+ vi.spyOn(mockAxiosInstance, 'get').mockResolvedValue({ data: { data: eventsData } });
84
+ const result = await eventService.getMultiple({ includes });
85
+ expect(result).toEqual(eventsData);
86
+ expect(mockAxiosInstance.get).toHaveBeenCalledWith('/events?include=location,attachments');
87
+ });
88
+ it('should retrieve multiple events with includes and filters', async () => {
89
+ const includes = ['location', 'tickets'];
90
+ const filters = {
91
+ title: ['Workshop'],
92
+ start_at: ['2023-01-01']
93
+ };
94
+ const eventsData = [
95
+ { id: '1', type: 'event' },
96
+ { id: '2', type: 'event' },
97
+ ];
98
+ vi.spyOn(mockAxiosInstance, 'get').mockResolvedValue({ data: { data: eventsData } });
99
+ const result = await eventService.getMultiple({ filters, includes });
100
+ expect(result).toEqual(eventsData);
101
+ expect(mockAxiosInstance.get).toHaveBeenCalledWith('/events?filter[title]=Workshop&filter[start_at]=2023-01-01&include=location,tickets');
102
+ });
103
+ });
104
+ //# sourceMappingURL=Event.unit.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Event.unit.test.js","sourceRoot":"","sources":["../../../src/services/event/Event.unit.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ import type { BookwhenEvent } from './EventTypes.js';
2
+ /**
3
+ * Interface for services handling events via the Bookwhen API V2.
4
+ */
5
+ export interface IEventService {
6
+ /**
7
+ * Retrieves a single event by its ID.
8
+ * @param eventId The unique identifier of the event.
9
+ * @param include Optional parameter to include additional data.
10
+ * @returns A Promise that resolves to an Event object, as defined by the Bookwhen API data structure.
11
+ */
12
+ getById(params: GetEventByIdParams): Promise<BookwhenEvent>;
13
+ /**
14
+ * Retrieves multiple events based on specified parameters.
15
+ * @param params Optional parameters to filter and control the list of returned events, according to what the Bookwhen API supports.
16
+ * @returns A Promise that resolves to an array of Event objects.
17
+ */
18
+ getMultiple?(params?: GetMultipleEventsParams): Promise<BookwhenEvent[]>;
19
+ }
20
+ /**
21
+ * Parameters for querying a single event from the Bookwhen API, including optional include parameter.
22
+ * @param eventId The unique identifier of the event.
23
+ * @param include Optional parameter to include additional data.
24
+ */
25
+ export interface GetEventByIdParams {
26
+ eventId: string;
27
+ includes?: EventResource[];
28
+ }
29
+ /**
30
+ * Represents the parameters for getting multiple events.
31
+ * @param filter The filter parameters to apply to the query.
32
+ * @param include The data to side load and include with the returned events.
33
+ */
34
+ export interface GetMultipleEventsParams {
35
+ filters?: EventFilters;
36
+ includes?: EventResource[];
37
+ }
38
+ interface EventFiltersMap {
39
+ calendar?: string[];
40
+ entry?: string[];
41
+ location?: string[];
42
+ tag?: string[];
43
+ title?: string[];
44
+ detail?: string[];
45
+ from?: string;
46
+ to?: string;
47
+ compact?: boolean;
48
+ }
49
+ export type EventFilters = {
50
+ [K in keyof EventFiltersMap]?: EventFiltersMap[K];
51
+ };
52
+ export type EventResource = 'location' | 'attachments' | 'tickets' | 'tickets.events' | 'tickets.class_passes';
53
+ export {};
@@ -0,0 +1,3 @@
1
+ ;
2
+ export {};
3
+ //# sourceMappingURL=EventInterfaces.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EventInterfaces.js","sourceRoot":"","sources":["../../../src/services/event/EventInterfaces.ts"],"names":[],"mappings":"AAqDC,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { z } from 'zod';
2
+ export declare const EventResourceSchema: z.ZodEnum<["location", "attachments", "tickets", "tickets.events", "tickets.class_passes"]>;
3
+ export declare const GetEventByIdParamsSchema: z.ZodObject<{
4
+ eventId: z.ZodString;
5
+ includes: z.ZodOptional<z.ZodArray<z.ZodEnum<["location", "attachments", "tickets", "tickets.events", "tickets.class_passes"]>, "many">>;
6
+ }, "strip", z.ZodTypeAny, {
7
+ eventId: string;
8
+ includes?: ("location" | "attachments" | "tickets" | "tickets.events" | "tickets.class_passes")[] | undefined;
9
+ }, {
10
+ eventId: string;
11
+ includes?: ("location" | "attachments" | "tickets" | "tickets.events" | "tickets.class_passes")[] | undefined;
12
+ }>;
@@ -0,0 +1,8 @@
1
+ import { z } from 'zod';
2
+ export const EventResourceSchema = z.enum(['location', 'attachments', 'tickets', 'tickets.events', 'tickets.class_passes']);
3
+ // Define GetEventByIdParams schema
4
+ export const GetEventByIdParamsSchema = z.object({
5
+ eventId: z.string().min(1, 'Invalid event ID'),
6
+ includes: EventResourceSchema.array().optional(),
7
+ });
8
+ //# sourceMappingURL=EventSchemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EventSchemas.js","sourceRoot":"","sources":["../../../src/services/event/EventSchemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,aAAa,EAAE,SAAS,EAAE,gBAAgB,EAAE,sBAAsB,CAAC,CAAC,CAAC;AAE5H,mCAAmC;AACnC,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/C,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,kBAAkB,CAAC;IAC9C,QAAQ,EAAE,mBAAmB,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE;CACjD,CAAC,CAAC"}
@@ -0,0 +1,36 @@
1
+ export interface EventImage {
2
+ image_url: string;
3
+ alt_ratio_16x9_1x_url: string;
4
+ alt_ratio_16x9_2x_url: string;
5
+ alt_ratio_16x9_3x_url: string;
6
+ alt_ratio_4x3_1x_url: string;
7
+ alt_ratio_4x3_2x_url: string;
8
+ alt_ratio_4x3_3x_url: string;
9
+ alt_ratio_1x1_1x_url: string;
10
+ alt_ratio_1x1_2x_url: string;
11
+ alt_ratio_1x1_3x_url: string;
12
+ }
13
+ export interface EventAttributes {
14
+ title: string;
15
+ details: string;
16
+ all_day: boolean;
17
+ start_at: string;
18
+ end_at: string;
19
+ attendee_limit: number;
20
+ attendee_count: number;
21
+ waiting_list: boolean;
22
+ max_tickets_per_booking: number;
23
+ tags: string[];
24
+ event_image: EventImage;
25
+ }
26
+ export interface BookwhenEvent {
27
+ id: string;
28
+ type: string;
29
+ attributes: EventAttributes;
30
+ }
31
+ export interface EventsResponse {
32
+ data: BookwhenEvent[];
33
+ }
34
+ export interface EventResponse {
35
+ data: BookwhenEvent;
36
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=EventTypes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EventTypes.js","sourceRoot":"","sources":["../../../src/services/event/EventTypes.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
1
+ export interface HttpStatus {
2
+ code: number;
3
+ message: string;
4
+ }
5
+ export type Resource = string;
6
+ export type Resources = Resource[];
7
+ export interface Filters {
8
+ [key: string]: string | string[] | boolean;
9
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=GlobalTypes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GlobalTypes.js","sourceRoot":"","sources":["../../src/types/GlobalTypes.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ import type { HttpStatus } from '../types/GlobalTypes.js';
2
+ /**
3
+ * Handles errors for service methods
4
+ * @param error The error object caught in service methods.
5
+ * @param statusCodes General service-level status codes and messages.
6
+ * @param methodErrors Optional method-specific error messages.
7
+ */
8
+ export declare function handleServiceHTTPErrors(error: any, statusCodes: Record<number, HttpStatus>, methodErrors?: Record<number, HttpStatus>): never;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Handles errors for service methods
3
+ * @param error The error object caught in service methods.
4
+ * @param statusCodes General service-level status codes and messages.
5
+ * @param methodErrors Optional method-specific error messages.
6
+ */
7
+ export function handleServiceHTTPErrors(error, statusCodes, methodErrors = {}) {
8
+ if (error.response) {
9
+ const status = error.response.status;
10
+ // First, check for method-specific errors, then fall back to general service errors
11
+ const errorMessage = methodErrors[status]?.message || statusCodes[status]?.message || `Unhandled service error with status code: ${status}`;
12
+ throw new Error(errorMessage);
13
+ }
14
+ else {
15
+ // If no response was received, this is likely a serious client or network issue
16
+ throw new Error("An unexpected network or client error occurred, with no response property.");
17
+ }
18
+ }
19
+ //# sourceMappingURL=http-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-utils.js","sourceRoot":"","sources":["../../src/utils/http-utils.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,KAAU,EAAE,WAAuC,EAAE,eAA2C,EAAE;IACxI,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QACjB,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;QACrC,oFAAoF;QACpF,MAAM,YAAY,GAAG,YAAY,CAAC,MAAM,CAAC,EAAE,OAAO,IAAI,WAAW,CAAC,MAAM,CAAC,EAAE,OAAO,IAAI,6CAA6C,MAAM,EAAE,CAAC;QAC5I,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC;IAClC,CAAC;SAAM,CAAC;QACJ,gFAAgF;QAChF,MAAM,IAAI,KAAK,CAAC,4EAA4E,CAAC,CAAC;IAClG,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jphil/bookwhen-client",
3
- "version": "0.0.9",
3
+ "version": "0.1.0",
4
4
  "description": "",
5
5
  "private": false,
6
6
  "main": "dist/index.js",
@@ -33,8 +33,15 @@
33
33
  "@changesets/cli": "^2.27.9",
34
34
  "@commitlint/cli": "^19.5.0",
35
35
  "@commitlint/config-conventional": "^19.5.0",
36
+ "@types/node": "^22.9.0",
37
+ "@typescript-eslint/eslint-plugin": "^8.13.0",
38
+ "@typescript-eslint/parser": "^8.13.0",
39
+ "@vitest/coverage-v8": "2.1.3",
40
+ "axios": "^1.7.7",
41
+ "c8": "^10.1.2",
36
42
  "commitizen": "^4.3.1",
37
43
  "cz-conventional-changelog": "^3.3.0",
44
+ "dotenv": "^16.4.5",
38
45
  "eslint": "^9.13.0",
39
46
  "eslint-config-prettier": "^9.1.0",
40
47
  "eslint-plugin-prettier": "^5.2.1",
@@ -43,21 +50,21 @@
43
50
  "tsup": "^8.3.4",
44
51
  "typescript": "^5.6.3",
45
52
  "vite": "^5.4.10",
46
- "vitest": "^2.1.3"
53
+ "vite-tsconfig-paths": "^5.1.0",
54
+ "vitest": "^2.1.3",
55
+ "zod": "^3.23.8"
47
56
  },
48
57
  "config": {
49
58
  "commitizen": {
50
59
  "path": "./node_modules/cz-conventional-changelog"
51
60
  }
52
61
  },
53
- "dependencies": {
54
- "rollup": "^4.24.0"
55
- },
56
62
  "scripts": {
57
63
  "dev": "vitest",
58
64
  "build": "tsc",
59
65
  "lint": "tsc",
60
66
  "test": "vitest run",
67
+ "coverage": "vitest run --coverage",
61
68
  "type-check": "tsc --noEmit",
62
69
  "check-exports": "attw --pack . --ignore-rules=cjs-resolves-to-esm",
63
70
  "prettier-check": "prettier --check 'src/**/*.ts'",