@bookinglab/booking-journey-api 1.0.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 BookingLab
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,178 @@
1
+ # @bookinglab/booking-journey-api
2
+
3
+ A lightweight, developer-friendly TypeScript library for BookingLab and JRNI APIs. Supports both vanilla JavaScript/TypeScript and React applications.
4
+
5
+ ## Features
6
+
7
+ - 🎯 **Type-safe** - Full TypeScript support with comprehensive type definitions
8
+ - ⚛️ **React-ready** - Context providers and hooks for seamless React integration
9
+ - 🌳 **Tree-shakable** - Only bundle what you use
10
+ - 🔧 **Flexible** - Works with vanilla JS/TS or React
11
+ - 📦 **Lightweight** - Minimal dependencies
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install @bookinglab/booking-journey-api
17
+ ```
18
+
19
+ For React applications, you'll also need:
20
+
21
+ ```bash
22
+ npm install @tanstack/react-query
23
+ ```
24
+
25
+ ## Quick Start
26
+
27
+ ### Vanilla JavaScript/TypeScript
28
+
29
+ ```typescript
30
+ import { createJrniClient } from '@bookinglab/booking-journey-api';
31
+
32
+ const client = createJrniClient('https://api.jrni.com', {
33
+ appId: 'your-app-id',
34
+ appKey: 'your-app-key',
35
+ });
36
+
37
+ // Login
38
+ const response = await client.login({
39
+ email: 'user@example.com',
40
+ password: 'password',
41
+ });
42
+
43
+ console.log(response.data.auth_token);
44
+ ```
45
+
46
+ ### React Applications
47
+
48
+ ```tsx
49
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
50
+ import { JrniProvider, useLogin } from '@bookinglab/booking-journey-api';
51
+
52
+ const queryClient = new QueryClient();
53
+
54
+ function App() {
55
+ return (
56
+ <QueryClientProvider client={queryClient}>
57
+ <JrniProvider
58
+ baseUrl="https://api.jrni.com"
59
+ config={{ appId: 'your-app-id', appKey: 'your-app-key' }}
60
+ >
61
+ <LoginForm />
62
+ </JrniProvider>
63
+ </QueryClientProvider>
64
+ );
65
+ }
66
+
67
+ function LoginForm() {
68
+ const loginMutation = useLogin();
69
+
70
+ const handleLogin = () => {
71
+ loginMutation.mutate({
72
+ email: 'user@example.com',
73
+ password: 'password',
74
+ });
75
+ };
76
+
77
+ return (
78
+ <button onClick={handleLogin} disabled={loginMutation.isPending}>
79
+ {loginMutation.isPending ? 'Logging in...' : 'Login'}
80
+ </button>
81
+ );
82
+ }
83
+ ```
84
+
85
+ ## API Reference
86
+
87
+ ### Core Client
88
+
89
+ #### `createJrniClient(baseUrl, config)`
90
+
91
+ Creates a new JRNI client instance.
92
+
93
+ ```typescript
94
+ const client = createJrniClient('https://api.jrni.com', {
95
+ appId: 'your-app-id',
96
+ appKey: 'your-app-key',
97
+ });
98
+ ```
99
+
100
+ #### Client Methods
101
+
102
+ - `client.login(credentials)` - Authenticate a user
103
+
104
+ ### React Providers
105
+
106
+ #### `JrniProvider`
107
+
108
+ Provides JRNI client context to React components.
109
+
110
+ ```tsx
111
+ <JrniProvider
112
+ baseUrl="https://api.jrni.com"
113
+ config={{ appId: 'your-app-id', appKey: 'your-app-key' }}
114
+ >
115
+ {children}
116
+ </JrniProvider>
117
+ ```
118
+
119
+ #### `ApiClientProvider`
120
+
121
+ Combined provider for applications using multiple API clients.
122
+
123
+ ```tsx
124
+ <ApiClientProvider
125
+ jrniBaseUrl="https://api.jrni.com"
126
+ jrniConfig={{ appId: 'your-app-id', appKey: 'your-app-key' }}
127
+ >
128
+ {children}
129
+ </ApiClientProvider>
130
+ ```
131
+
132
+ ### React Hooks
133
+
134
+ #### `useLogin()`
135
+
136
+ Hook for user authentication.
137
+
138
+ ```typescript
139
+ const { mutate, isPending, isError, data } = useLogin();
140
+
141
+ mutate({ email: 'user@example.com', password: 'password' });
142
+ ```
143
+
144
+ #### `useJrniClient()`
145
+
146
+ Access the JRNI client directly for custom operations.
147
+
148
+ ```typescript
149
+ const client = useJrniClient();
150
+ const response = await client.login(credentials);
151
+ ```
152
+
153
+ ## Types
154
+
155
+ The library exports comprehensive TypeScript types:
156
+
157
+ ```typescript
158
+ import type {
159
+ LoginRequest,
160
+ LoginResponse,
161
+ JrniService,
162
+ ServicesResponse,
163
+ Question,
164
+ QuestionsResponse,
165
+ Location,
166
+ LocationsResponse,
167
+ Vehicle,
168
+ VehiclesResponse,
169
+ JrniBooking,
170
+ MemberBookingsResponse,
171
+ AvailabilityTime,
172
+ AvailabilityTimesResponse,
173
+ } from '@bookinglab/booking-journey-api';
174
+ ```
175
+
176
+ ## License
177
+
178
+ MIT
@@ -0,0 +1,404 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+ import * as _tanstack_react_query from '@tanstack/react-query';
4
+
5
+ /**
6
+ * Core API Client Types
7
+ */
8
+ interface ApiClientConfig {
9
+ baseUrl: string;
10
+ headers?: Record<string, string>;
11
+ timeout?: number;
12
+ }
13
+ interface RequestOptions extends RequestInit {
14
+ params?: Record<string, string | number | boolean | undefined>;
15
+ }
16
+ interface ApiResponse<T = any> {
17
+ data: T;
18
+ status: number;
19
+ headers: Headers;
20
+ }
21
+ interface ApiError {
22
+ message: string;
23
+ status?: number;
24
+ code?: string;
25
+ details?: any;
26
+ }
27
+ /**
28
+ * JRNI Configuration
29
+ */
30
+ interface JrniConfig {
31
+ appId: string;
32
+ appKey: string;
33
+ }
34
+ /**
35
+ * JRNI API Types
36
+ */
37
+ interface LoginRequest {
38
+ email: string;
39
+ password: string;
40
+ }
41
+ interface LoginResponse {
42
+ email: string;
43
+ auth_token: string;
44
+ company_id: number;
45
+ path: string;
46
+ role?: string;
47
+ _embedded?: {
48
+ members?: Array<{
49
+ id: number;
50
+ name: string;
51
+ first_name: string;
52
+ last_name: string;
53
+ email: string;
54
+ [key: string]: any;
55
+ }>;
56
+ administrators?: any[];
57
+ };
58
+ _links?: any;
59
+ }
60
+ interface JrniService {
61
+ id: number;
62
+ name: string;
63
+ description: string;
64
+ durations: number[];
65
+ prices: number[];
66
+ detail_group_id: number;
67
+ listed_durations: any[];
68
+ extra: Record<string, any>;
69
+ booking_time_step: number;
70
+ can_refund_automatically: boolean;
71
+ is_event_group: boolean;
72
+ type: string;
73
+ group_id: number | null;
74
+ deleted: boolean;
75
+ queuing_disabled: boolean;
76
+ company_id: number;
77
+ min_advance_period: number;
78
+ max_advance_period: number;
79
+ min_cancel_period: number;
80
+ booking_type_public: string;
81
+ booking_type: number;
82
+ mbooking_type: number;
83
+ min_bookings: number;
84
+ max_bookings: number;
85
+ method_of_appointment: string;
86
+ groups: any[];
87
+ order: number;
88
+ child_level_service: boolean;
89
+ global_id: number;
90
+ availability: number;
91
+ prices_in_major_units: number[];
92
+ combine_resource_and_staff: boolean;
93
+ disabled: boolean;
94
+ _links: Record<string, any>;
95
+ }
96
+ interface ServicesResponse {
97
+ total_entries: number;
98
+ _embedded: {
99
+ services: JrniService[];
100
+ };
101
+ _links: Record<string, any>;
102
+ }
103
+ interface QuestionOption {
104
+ name: string;
105
+ price: number;
106
+ is_default: boolean;
107
+ id: number;
108
+ }
109
+ interface Question {
110
+ id: number;
111
+ name: string;
112
+ required: boolean;
113
+ important: boolean;
114
+ admin_only: boolean;
115
+ applies_to: number;
116
+ ask_member: boolean;
117
+ detail_type: string;
118
+ options?: QuestionOption[];
119
+ settings: Record<string, any>;
120
+ price: number;
121
+ price_per_booking: boolean;
122
+ outcome: boolean;
123
+ hide_on_customer_journey: boolean;
124
+ default?: string;
125
+ help_text?: string;
126
+ _links: Record<string, any>;
127
+ }
128
+ interface QuestionsResponse {
129
+ company_id: number;
130
+ questions: Question[];
131
+ name: string;
132
+ _links: Record<string, any>;
133
+ }
134
+ interface Location {
135
+ id: number;
136
+ name: string;
137
+ description: string;
138
+ company_type: string;
139
+ address: {
140
+ id: number;
141
+ address1: string;
142
+ address2: string;
143
+ address3: string;
144
+ address4: string;
145
+ address5: string;
146
+ postcode: string;
147
+ country: string;
148
+ };
149
+ }
150
+ interface LocationsResponse {
151
+ total_entries: number;
152
+ _embedded: {
153
+ resources: Location[];
154
+ };
155
+ _links: Record<string, any>;
156
+ }
157
+ interface Vehicle {
158
+ id: number;
159
+ name: string;
160
+ description: string;
161
+ type: string;
162
+ extra: {
163
+ vehicle_registration?: string;
164
+ vehicle_make?: string;
165
+ vehicle_model?: string;
166
+ vehicle_size?: string;
167
+ fuel_type?: string;
168
+ vehicle_brand?: string;
169
+ vehicle_transmission?: string;
170
+ base_location?: string;
171
+ driver_name?: string;
172
+ driver_email?: string;
173
+ };
174
+ group_id: number | null;
175
+ deleted: boolean;
176
+ disabled: boolean;
177
+ company_id: number;
178
+ order: number;
179
+ created_at: string;
180
+ updated_at: string;
181
+ _links: Record<string, any>;
182
+ }
183
+ interface VehiclesResponse {
184
+ total_entries: number;
185
+ _embedded: {
186
+ people: Vehicle[];
187
+ };
188
+ _links: Record<string, any>;
189
+ }
190
+ interface AddBasketItemRequest {
191
+ service_id: number;
192
+ start: string;
193
+ duration: number;
194
+ company_id: string;
195
+ person_id: number;
196
+ questions: Array<{
197
+ id: string;
198
+ answer: string;
199
+ }>;
200
+ }
201
+ interface AvailabilityTime {
202
+ start: string;
203
+ available: boolean;
204
+ durations: number[];
205
+ prices: number[];
206
+ _links: Record<string, any>;
207
+ }
208
+ interface AvailabilityTimesResponse {
209
+ times: AvailabilityTime[];
210
+ }
211
+ interface JrniBooking {
212
+ id: number;
213
+ full_describe: string;
214
+ describe: string;
215
+ person_name: string;
216
+ datetime: string;
217
+ end_datetime: string;
218
+ duration: number;
219
+ service_name: string;
220
+ service_id: number;
221
+ status: string;
222
+ is_cancelled: boolean;
223
+ min_cancellation_time?: number;
224
+ person_ids?: number[];
225
+ settings?: {
226
+ current_multi_stat?: string;
227
+ multi_stats?: Record<string, string>;
228
+ obfuscated_id?: string;
229
+ who_updated?: string;
230
+ };
231
+ questions: Record<string, {
232
+ answer: string;
233
+ answer_id: number | null;
234
+ name: string;
235
+ }>;
236
+ _embedded?: {
237
+ answers?: Array<{
238
+ id: number;
239
+ value: string;
240
+ question_text: string;
241
+ }>;
242
+ };
243
+ }
244
+ interface MemberBookingsResponse {
245
+ total_entries: number;
246
+ _embedded: {
247
+ bookings: JrniBooking[];
248
+ };
249
+ _links: Record<string, any>;
250
+ }
251
+ interface PersonImage {
252
+ id: number;
253
+ name: string;
254
+ url: string;
255
+ order: number;
256
+ person_id?: number;
257
+ }
258
+ interface PersonImagesResponse {
259
+ _embedded: {
260
+ images: PersonImage[];
261
+ };
262
+ _links: Record<string, any>;
263
+ }
264
+ interface UpdateClientDetailsData {
265
+ first_name: string;
266
+ last_name: string;
267
+ mobile: string;
268
+ questions?: Record<string, {
269
+ answer: string;
270
+ }>;
271
+ }
272
+ interface UpdateMemberDetailsData {
273
+ first_name: string;
274
+ last_name: string;
275
+ mobile?: string;
276
+ q?: Record<string, {
277
+ answer: string;
278
+ answer_id: number;
279
+ name: string;
280
+ }>;
281
+ answers?: Array<{
282
+ question_id: number;
283
+ name: string;
284
+ answer: string;
285
+ answer_id: number;
286
+ }>;
287
+ }
288
+
289
+ /**
290
+ * Core API Client
291
+ * Base class for making HTTP requests
292
+ */
293
+
294
+ declare class ApiClient {
295
+ protected baseUrl: string;
296
+ protected headers: Record<string, string>;
297
+ protected timeout: number;
298
+ constructor(config: ApiClientConfig);
299
+ /**
300
+ * Update client configuration
301
+ */
302
+ setConfig(config: Partial<ApiClientConfig>): void;
303
+ /**
304
+ * Set authorization token
305
+ */
306
+ setAuthToken(token: string): void;
307
+ /**
308
+ * Make an HTTP request
309
+ */
310
+ protected request<T>(endpoint: string, options?: RequestOptions): Promise<ApiResponse<T>>;
311
+ /**
312
+ * GET request
313
+ */
314
+ protected get<T>(endpoint: string, options?: RequestOptions): Promise<ApiResponse<T>>;
315
+ /**
316
+ * POST request
317
+ */
318
+ protected post<T>(endpoint: string, body?: any, options?: RequestOptions): Promise<ApiResponse<T>>;
319
+ /**
320
+ * PUT request
321
+ */
322
+ protected put<T>(endpoint: string, body?: any, options?: RequestOptions): Promise<ApiResponse<T>>;
323
+ /**
324
+ * DELETE request
325
+ */
326
+ protected delete<T>(endpoint: string, options?: RequestOptions): Promise<ApiResponse<T>>;
327
+ /**
328
+ * Handle error responses
329
+ */
330
+ private handleError;
331
+ /**
332
+ * Normalize errors to consistent format
333
+ */
334
+ private normalizeError;
335
+ }
336
+
337
+ /**
338
+ * JRNI API Client
339
+ * Provides methods for interacting with the JRNI API
340
+ */
341
+
342
+ declare class JrniClient extends ApiClient {
343
+ private appId;
344
+ private appKey;
345
+ constructor(baseUrl: string, config: JrniConfig);
346
+ /**
347
+ * Login to JRNI
348
+ */
349
+ login(credentials: LoginRequest): Promise<ApiResponse<LoginResponse>>;
350
+ /**
351
+ * Update JRNI configuration
352
+ */
353
+ setJrniConfig(config: Partial<JrniConfig>): void;
354
+ }
355
+ /**
356
+ * Create a new JRNI client instance
357
+ */
358
+ declare function createJrniClient(baseUrl: string, config: JrniConfig): JrniClient;
359
+
360
+ interface ApiClientContextValue {
361
+ jrniClient: JrniClient | null;
362
+ }
363
+ interface ApiClientProviderProps {
364
+ children: ReactNode;
365
+ jrniBaseUrl?: string;
366
+ jrniConfig?: JrniConfig;
367
+ }
368
+ /**
369
+ * Combined provider for multiple API clients
370
+ */
371
+ declare function ApiClientProvider({ children, jrniBaseUrl, jrniConfig, }: ApiClientProviderProps): react_jsx_runtime.JSX.Element;
372
+ /**
373
+ * Hook to access API client context
374
+ */
375
+ declare function useApiClientContext(): ApiClientContextValue;
376
+
377
+ interface JrniProviderProps {
378
+ children: ReactNode;
379
+ baseUrl: string;
380
+ config: JrniConfig;
381
+ }
382
+ /**
383
+ * Provider component for JRNI client
384
+ */
385
+ declare function JrniProvider({ children, baseUrl, config }: JrniProviderProps): react_jsx_runtime.JSX.Element;
386
+ /**
387
+ * Hook to access JRNI client from context
388
+ */
389
+ declare function useJrniContext(): JrniClient;
390
+
391
+ /**
392
+ * Hook to access API clients from context
393
+ */
394
+ /**
395
+ * Hook to get JRNI client from either ApiClientProvider or JrniProvider
396
+ */
397
+ declare function useJrniClient(): JrniClient;
398
+
399
+ /**
400
+ * Hook for JRNI login
401
+ */
402
+ declare function useLogin(): _tanstack_react_query.UseMutationResult<LoginResponse, Error, LoginRequest, unknown>;
403
+
404
+ export { type AddBasketItemRequest, ApiClient, type ApiClientConfig, ApiClientProvider, type ApiError, type ApiResponse, type AvailabilityTime, type AvailabilityTimesResponse, type JrniBooking, JrniClient, type JrniConfig, JrniProvider, type JrniService, type Location, type LocationsResponse, type LoginRequest, type LoginResponse, type MemberBookingsResponse, type PersonImage, type PersonImagesResponse, type Question, type QuestionOption, type QuestionsResponse, type RequestOptions, type ServicesResponse, type UpdateClientDetailsData, type UpdateMemberDetailsData, type Vehicle, type VehiclesResponse, createJrniClient, useApiClientContext, useJrniClient, useJrniContext, useLogin };