@jphil/bookwhen-client 0.4.2 → 0.5.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/README.md CHANGED
@@ -1,351 +1,118 @@
1
1
  # `@jphil/bookwhen-client`
2
2
 
3
- A universal API client library for the [Bookwhen](https://www.bookwhen.com) booking platform [API (v2)](https://api.bookwhen.com/v2), written in TypeScript for both NodeJS and browser environments.
3
+ TypeScript client for the [Bookwhen API v2](https://api.bookwhen.com/v2), built for Node.js and browser environments.
4
4
 
5
- ## Table of Contents
5
+ This package is currently pre-1.0 and under active development.
6
6
 
7
- - [Overview](#overview)
8
- - [Features](#features)
9
- - [Installation](#installation)
10
- - [Usage](#usage)
11
- - [JSON:API Response Structure](#jsonapi-response-structure)
12
- - [Migration from v0.3.2](#migration-from-v032)
13
- - [Browser Usage](#browser-usage)
14
- - [Error Handling](#error-handling)
15
- - [Configuration](#configuration)
16
- - [Contributing](#contributing)
17
- - [Roadmap](#roadmap)
18
- - [License](#license)
7
+ ## Quick Start
19
8
 
20
- ## Overview
21
-
22
- You'll likely be at least somewhat familiar with the [Bookwhen](https://www.bookwhen.com) booking platform if you've landed here. But if not, you'll want to have a look at their [API (v2) documentation](https://api.bookwhen.com/v2). There's also a nice [Swagger style layout of the Bookwhen API v2 docs](https://petstore.swagger.io/?url=https://api.bookwhen.com/v2/openapi.yaml)
23
-
24
- ## Features
25
-
26
- - Provides an easy way to access Bookwhen API from both NodeJS and browsers
27
- - Browser-compatible with proper CORS handling
28
- - Provides fully typed methods for each model (so far just the Events model) provided in the Bookwhen API v2
29
- - **Full JSON:API compliance** with access to included resources, links, and meta data
30
- - **Relationship resolution utilities** for working with included data
31
- - **Type-safe JSON:API response interfaces** with proper TypeScript support
32
-
33
- ## Installation
34
-
35
- Install via pnpm:
9
+ Install the library and peer dependencies:
36
10
 
37
11
  ```bash
38
- pnpm add @jphil/bookwhen-client
12
+ pnpm add @jphil/bookwhen-client axios zod
39
13
  ```
40
14
 
41
- As `axios` and `zod` are peer dependencies, ensure they are also installed in your project:
42
-
43
- ```bash
44
- pnpm add axios zod
45
- # or npm install axios zod
46
- # or yarn add axios zod
47
- ```
48
-
49
- ## Usage
50
-
51
- This library is distributed as an ES module. The following usage pattern applies to modern Node.js environments (with `type: "module"` in your `package.json` or when using `.mjs` files) and browser environments when using a bundler. For direct browser usage without a bundler, see the [Browser Usage](#browser-usage) section below.
15
+ Create a client and fetch events:
52
16
 
53
17
  ```typescript
54
- // import the client factory
55
18
  import { createBookwhenClient } from '@jphil/bookwhen-client';
56
19
 
57
- // create the client
58
20
  const client = createBookwhenClient({
59
- apiKey: 'your-API-key',
60
- debug: true, // Optional: enables request logging
21
+ apiKey: process.env.BOOKWHEN_API_KEY!,
61
22
  });
62
23
 
63
- // Get a single event - returns full JSON:API response
64
- const eventResponse = await client.events.getById({
65
- eventId: 'some-id',
66
- includes: ['location', 'tickets'], // Optional: include related resources
67
- });
68
- const event = eventResponse.data; // Access the event data
69
-
70
- // get all events - returns full JSON:API response
71
- const eventsResponse = await client.events.getMultiple();
72
- const events = eventsResponse.data; // Access the events array
73
-
74
- // get all events in 2025 tagged with 'workshop' with included locations
75
- const events2025Response = await client.events.getMultiple({
76
- filters: {
77
- // Optional: filter by various
78
- from: '20250101',
79
- to: '20251231',
80
- tag: ['workshop'],
81
- },
82
- includes: ['location'], // Optional: Include related resources
24
+ const response = await client.events.getMultiple({
25
+ filters: { from: '20250101', to: '20251231' },
26
+ includes: ['location', 'tickets'],
83
27
  });
84
- const events2025 = events2025Response.data; // Access the events array
85
- const includedLocations = events2025Response.included; // Access included location data
86
- ```
87
-
88
- (N.B. Ensure you wrap the above statements in try/catch blocks to catch errors which could be thrown)
89
28
 
90
- Valid filters and includes for each method are detailed in the [API v2 docs](https://petstore.swagger.io/?url=https://api.bookwhen.com/v2/openapi.yaml)
29
+ const events = response.data;
30
+ const included = response.included;
31
+ ```
91
32
 
92
- ## JSON:API Response Structure
33
+ ## API Coverage
93
34
 
94
- Service methods now return full JSON:API response objects instead of just data arrays. This provides access to all data returned by the Bookwhen API, including included resources, links, and metadata.
35
+ Bookwhen resources currently implemented in this client:
95
36
 
96
- ### Response Structure Example
37
+ | Resource | Status | Endpoints |
38
+ | ------------ | ----------- | ------------------------------------------------ |
39
+ | Events | Implemented | `/events`, `/events/{event_id}` |
40
+ | Tickets | Implemented | `/tickets`, `/tickets/{ticket_id}` |
41
+ | Locations | Implemented | `/locations`, `/locations/{location_id}` |
42
+ | Attachments | Implemented | `/attachments`, `/attachments/{attachment_id}` |
43
+ | Class passes | Implemented | `/class_passes`, `/class_passes/{class_pass_id}` |
97
44
 
98
- ```typescript
99
- const response = await client.events.getMultiple({
100
- includes: ['location', 'tickets']
101
- });
45
+ Reference docs:
102
46
 
103
- // response structure:
104
- {
105
- data: [
106
- {
107
- id: 'ev-123',
108
- type: 'event',
109
- attributes: {
110
- title: 'Thai massage with Justin',
111
- start_at: '2025-11-02T11:00:00.000+00:00',
112
- // ... other event attributes
113
- },
114
- relationships: {
115
- location: { data: { id: 'loc-1', type: 'location' } },
116
- tickets: { data: [{ id: 'ticket-1', type: 'ticket' }] }
117
- }
118
- }
119
- ],
120
- included: [
121
- {
122
- id: 'loc-1',
123
- type: 'location',
124
- attributes: {
125
- address_text: 'MovingStillness Studio\nColdean\nBrighton',
126
- latitude: 50.8608545,
127
- longitude: -0.1070177
128
- }
129
- },
130
- {
131
- id: 'ticket-1',
132
- type: 'ticket',
133
- attributes: {
134
- name: 'Standard Ticket',
135
- price: 100,
136
- available: true
137
- }
138
- }
139
- ],
140
- links: {
141
- self: 'https://api.bookwhen.com/v2/events'
142
- },
143
- meta: {
144
- // Optional metadata
145
- }
146
- }
147
- ```
47
+ - Bookwhen API docs: https://api.bookwhen.com/v2
48
+ - Swagger layout: https://petstore.swagger.io/?url=https://api.bookwhen.com/v2/openapi.yaml
148
49
 
149
- ### Working with Included Data
50
+ ## Response Shape
150
51
 
151
- The library provides utility functions to help resolve relationships between resources:
52
+ Service methods return full JSON:API response envelopes (not just `data`).
152
53
 
153
54
  ```typescript
154
- import { resolveJsonApiRelationships, resolveJsonApiResource } from '@jphil/bookwhen-client';
155
-
156
- // For multiple events
157
- const eventsResponse = await client.events.getMultiple({
158
- includes: ['location', 'tickets']
159
- });
160
-
161
- // Resolve relationships for all events
162
- const resolvedEvents = resolveJsonApiRelationships(
163
- eventsResponse.data,
164
- eventsResponse.included
165
- );
166
-
167
- // For a single event
168
55
  const eventResponse = await client.events.getById({
169
56
  eventId: 'ev-123',
170
- includes: ['location']
57
+ includes: ['location'],
171
58
  });
172
59
 
173
- // Resolve relationships for a single event
174
- const resolvedEvent = resolveJsonApiResource(
175
- eventResponse.data,
176
- eventResponse.included
177
- );
60
+ eventResponse.data;
61
+ eventResponse.included;
62
+ eventResponse.links;
63
+ eventResponse.meta;
178
64
  ```
179
65
 
180
- ## Migration from v0.3.2
181
-
182
- Version 0.4.0 introduces breaking changes to return full JSON:API responses:
183
-
184
- ### Before (v0.3.2)
185
- ```typescript
186
- const events = await client.events.getMultiple(); // BookwhenEvent[]
187
- const event = await client.events.getById({ eventId: '123' }); // BookwhenEvent
188
- ```
189
-
190
- ### After (v0.4.0)
191
- ```typescript
192
- const response = await client.events.getMultiple(); // EventsResponse
193
- const events = response.data; // BookwhenEvent[]
194
-
195
- const eventResponse = await client.events.getById({ eventId: '123' }); // EventResponse
196
- const event = eventResponse.data; // BookwhenEvent
197
- ```
198
-
199
- Services for the other models in the API are in the pipeline.
200
-
201
- N.B. This library is still a pre-1.0.0 WIP, please use accordingly, and pls submit issues for any bugs!
202
-
203
- ## Browser Usage
204
-
205
- The client is well-suited for browser environments.
206
-
207
- ### With a Bundler (Recommended for Browser Projects)
208
-
209
- If you are using a JavaScript bundler (like Webpack, Rollup, Vite, Parcel, etc.) in your browser project, you can import and use the client as shown in the main [Usage](#usage) section:
66
+ Relationship helper utilities are exported:
210
67
 
211
68
  ```typescript
212
- import { createBookwhenClient } from '@jphil/bookwhen-client';
213
- // ... rest of your code
214
- ```
215
-
216
- Ensure that `axios` and `zod` are also installed in your project, as they are peer dependencies. Your bundler will typically handle resolving these.
217
-
218
- ### Directly with `<script type="module">` (Advanced)
219
-
220
- For direct usage in a browser via `<script type="module">` without a bundler, you will need to:
221
-
222
- 1. Ensure ES module versions of `axios` and `zod` are accessible to your page (e.g., served locally or via a CDN).
223
- 2. Use an [import map](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap) to tell the browser how to resolve the module specifiers for `@jphil/bookwhen-client`, `axios`, and `zod`.
224
-
225
- Example import map:
226
-
227
- ```html
228
- <script type="importmap">
229
- {
230
- "imports": {
231
- "@jphil/bookwhen-client": "/node_modules/@jphil/bookwhen-client/dist/index.es.js",
232
- "axios": "/node_modules/axios/dist/esm/axios.js",
233
- "zod": "/node_modules/zod/lib/index.mjs"
234
- }
235
- }
236
- </script>
237
- <script type="module">
238
- import { createBookwhenClient } from '@jphil/bookwhen-client';
239
- // ...
240
- </script>
69
+ import {
70
+ resolveJsonApiRelationships,
71
+ resolveJsonApiResource,
72
+ } from '@jphil/bookwhen-client';
73
+
74
+ const resolvedMany = resolveJsonApiRelationships(
75
+ response.data,
76
+ response.included,
77
+ );
78
+ const resolvedOne = resolveJsonApiResource(
79
+ eventResponse.data,
80
+ eventResponse.included,
81
+ );
241
82
  ```
242
83
 
243
- Note: The exact paths in the import map will depend on how you serve these dependencies. Usage with a bundler is generally simpler for browser projects.
244
-
245
- ### Important Note on API Keys in Client-Side Usage
246
-
247
- When using this library in a browser (client-side), your Bookwhen API key will necessarily be included in the client-side code and thus visible.
84
+ ## Browser Notes
248
85
 
249
- - It is crucial to use an API key that has the minimum necessary permissions for the operations you intend to perform from the client-side.
250
- - This library enables access to Bookwhen API endpoints based on the permissions granted to the API key you provide.
86
+ - The library works in browser contexts and includes browser-aware error handling.
87
+ - Client-side API keys are visible to users; use least-privilege Bookwhen API tokens.
251
88
 
252
- ## Error Handling
89
+ ## Development
253
90
 
254
- The library provides comprehensive error handling that works consistently in both Node.js and browser environments. Custom error objects thrown by the library will have the following properties:
91
+ Common local commands:
255
92
 
256
- - `code`: An error code string identifying the type of error (e.g., `NETWORK_ERROR`, `API_ERROR`).
257
- - `message`: A human-readable description of the error.
258
- - `isBrowser`: A boolean indicating if the error occurred in a browser environment.
259
- - `context`: An object containing additional details, which may include the original error, status codes, etc.
260
- - `timestamp`: The time the error occurred.
261
-
262
- ### Error Types
263
-
264
- - `NETWORK_ERROR`: Indicates a failure in API communication (e.g., DNS resolution, connection refused).
265
- - `SECURITY_ERROR`: Specific to browsers, indicates security restrictions prevented API access (e.g., CORS issues not handled by the server, mixed content).
266
- - `API_ERROR`: The Bookwhen API returned an error response (e.g., 4xx or 5xx status code). The `context` may include `statusCode` and `responseData`.
267
- - `CONFIG_ERROR`: The client was configured incorrectly (e.g., missing API key).
268
- - `UNKNOWN_ERROR`: An unexpected error occurred within the library.
269
-
270
- Example:
271
-
272
- ```typescript
273
- try {
274
- await client.events.getById({ eventId: 'invalid-id' });
275
- } catch (error: any) {
276
- // It's good practice to type the error if you have custom error types defined
277
- console.error(`Error Code: ${error.code}`);
278
- console.error(`Message: ${error.message}`);
279
- if (error.code === 'API_ERROR') {
280
- console.error('API Error Details:', error.context?.responseData);
281
- } else if (error.code === 'NETWORK_ERROR') {
282
- // Handle network issues, maybe retry or inform user
283
- }
284
- // Other error handling...
285
- }
93
+ ```bash
94
+ pnpm install
95
+ pnpm test
96
+ pnpm build
97
+ pnpm lint
286
98
  ```
287
99
 
288
- ## Configuration
289
-
290
- Required configuration:
291
-
292
- - **apiKey**: Your Bookwhen API key (required)
293
-
294
- API requests to the Bookwhen API are authenticated using Basic Authentication with the API Key as the username and a blank password.
295
-
296
- API keys can be generated in the [API tokens setup area of your Bookwhen account](https://admin.bookwhen.com/settings/api_access_permission_sets). (This will link to the API settings page in your Bookwhen account if you have one and are logged into your admin account)
297
-
298
- ## Contributing
299
-
300
- Please see the docs in the CONTRIBUTIONS.md file, thanks!
301
-
302
- ## Mainainter release process
303
-
304
- [refining]
305
-
306
- From main branch on local:
100
+ ## Documentation
307
101
 
308
- - Pull latest code
309
- - git checkout -b some-new-branch
310
- - git commit -m 'feat(context): my latest work on feature x'
311
- - git push, copy URL
102
+ Project docs are intentionally lightweight and living:
312
103
 
313
- On github/local:
314
-
315
- - Open PR on github
316
- - Perfect the PR, merge when checks pass
317
-
318
- On local:
319
-
320
- - checkout main
321
- - git pull
322
- - git branch -d release (so we have a clean release branch)
323
- - git checkout -b release
324
- - pnpm changeset (provide changelog message - commit will occur in next step, not this one)
325
- - pnpm changeset version (bumps version numbers, and updates changelog, and commits >>> note new version number)
326
- - git push
327
-
328
- On github:
329
-
330
- - Open PR for release to merge into main
331
- - Perfect the PR, merge when checks pass (check why no build)
332
-
333
- On local:
334
-
335
- - git checkout main
336
- - git pull
337
- - git tag -a vx.x.x -m 'release vx.x.x'
338
- - git push origin vx.x.x <<<< RELEASE to github and NPM
104
+ - [CONTRIBUTING.md](CONTRIBUTING.md) - Contribution workflow and release notes
105
+ - [TODO.md](TODO.md) - Active work and backlog
106
+ - [DECISIONS.md](DECISIONS.md) - Architectural decisions
107
+ - [LEARNINGS.md](LEARNINGS.md) - Validated findings and gotchas
108
+ - [AGENTS.md](AGENTS.md) - Context and constraints for coding agents
339
109
 
340
110
  ## Roadmap
341
111
 
342
- - Proceed towards a 1.0.0 with community feedback.
343
- - Keep up with any future changes or additions to the [Bookwhen API](https://api.bookwhen.com/v2).
344
-
345
- ### Todos
346
-
347
- @see the issue queue.
112
+ - Expand coverage to remaining Bookwhen v2 content models.
113
+ - Continue improving test depth across browser and Node environments.
114
+ - Iterate toward a stable 1.0 release with community feedback.
348
115
 
349
116
  ## License
350
117
 
351
- ISC License. See [LICENSE](LICENSE) for more information.
118
+ ISC License. See [LICENSE](LICENSE).