@slotchain/sdk 1.1.3 → 1.2.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/dist/index.cjs.js +257 -16
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.mts +324 -28
- package/dist/index.d.ts +324 -28
- package/dist/index.esm.js +257 -16
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -2
- package/src/clients/__tests__/service-client.spec.ts +450 -0
- package/src/clients/customer-client.ts +129 -29
- package/src/clients/customer-client.ts.bak +165 -0
- package/src/clients/document-client.ts +148 -0
- package/src/clients/service-client.ts +87 -1
- package/src/clients/slot-client.ts +8 -5
- package/src/index.ts +17 -0
- package/src/types/api.ts +172 -7
- package/src/types/next-ambient.d.ts +29 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { AxiosInstance } from 'axios';
|
|
2
|
+
import { ApiResponse, Customer, Booking } from '../types/api';
|
|
3
|
+
|
|
4
|
+
export class CustomerClient {
|
|
5
|
+
constructor(private client: AxiosInstance) {}
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Get customer by ID
|
|
9
|
+
* GET /api/v1/customers/:id
|
|
10
|
+
*
|
|
11
|
+
* @param id - Customer ID
|
|
12
|
+
* @returns Customer details
|
|
13
|
+
*/
|
|
14
|
+
async getById(id: string): Promise<ApiResponse<Customer>> {
|
|
15
|
+
const response = await this.client.get<ApiResponse<Customer>>(
|
|
16
|
+
`/api/v1/customers/${id}`
|
|
17
|
+
);
|
|
18
|
+
return response.data;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Get customer by email
|
|
23
|
+
* GET /api/v1/customers?email=:email&tenant_id=:id
|
|
24
|
+
*
|
|
25
|
+
* @param email - Customer email
|
|
26
|
+
* @param tenantId - Required tenant ID for scoping
|
|
27
|
+
* @returns Customer details
|
|
28
|
+
*/
|
|
29
|
+
async getByEmail(email: string, tenantId: string): Promise<ApiResponse<Customer>> {
|
|
30
|
+
const response = await this.client.get<ApiResponse<Customer>>(
|
|
31
|
+
'/api/v1/customers',
|
|
32
|
+
{ params: { email, tenant_id: tenantId } }
|
|
33
|
+
);
|
|
34
|
+
return response.data;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* List customers with optional filters
|
|
39
|
+
* GET /api/v1/customers
|
|
40
|
+
*
|
|
41
|
+
* @param params - Query parameters (tenant_id required, page, limit, search, is_guest)
|
|
42
|
+
* @returns Paginated list of customers
|
|
43
|
+
*/
|
|
44
|
+
async list(params: {
|
|
45
|
+
tenant_id: string;
|
|
46
|
+
page?: number;
|
|
47
|
+
limit?: number;
|
|
48
|
+
search?: string;
|
|
49
|
+
is_guest?: boolean;
|
|
50
|
+
}): Promise<ApiResponse<Customer[]>> {
|
|
51
|
+
const response = await this.client.get<ApiResponse<Customer[]>>(
|
|
52
|
+
'/api/v1/customers',
|
|
53
|
+
{ params }
|
|
54
|
+
);
|
|
55
|
+
return response.data;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Create a new customer
|
|
60
|
+
* POST /api/v1/customers
|
|
61
|
+
*
|
|
62
|
+
* @param data - Customer creation data (tenant_id, name, email required)
|
|
63
|
+
* @returns Created customer
|
|
64
|
+
*/
|
|
65
|
+
async create(data: Partial<Customer>): Promise<ApiResponse<Customer>> {
|
|
66
|
+
const response = await this.client.post<ApiResponse<Customer>>(
|
|
67
|
+
'/api/v1/customers',
|
|
68
|
+
data
|
|
69
|
+
);
|
|
70
|
+
return response.data;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Update customer by ID
|
|
75
|
+
* PUT /api/v1/customers/:id
|
|
76
|
+
*
|
|
77
|
+
* @param id - Customer ID
|
|
78
|
+
* @param data - Customer update data
|
|
79
|
+
* @returns Updated customer
|
|
80
|
+
*/
|
|
81
|
+
async update(id: string, data: Partial<Customer>): Promise<ApiResponse<Customer>> {
|
|
82
|
+
const response = await this.client.put<ApiResponse<Customer>>(
|
|
83
|
+
`/api/v1/customers/${id}`,
|
|
84
|
+
data
|
|
85
|
+
);
|
|
86
|
+
return response.data;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Delete customer by ID
|
|
91
|
+
* DELETE /api/v1/customers/:id
|
|
92
|
+
*
|
|
93
|
+
* @param id - Customer ID
|
|
94
|
+
* @returns Empty response on success
|
|
95
|
+
*/
|
|
96
|
+
async delete(id: string): Promise<ApiResponse<void>> {
|
|
97
|
+
const response = await this.client.delete<ApiResponse<void>>(
|
|
98
|
+
`/api/v1/customers/${id}`
|
|
99
|
+
);
|
|
100
|
+
return response.data;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Lookup customer by userId or tenantId
|
|
105
|
+
* GET /api/v1/customers/lookup
|
|
106
|
+
*
|
|
107
|
+
* @param params - Query parameters (userId optional, tenantId required)
|
|
108
|
+
* @returns Customer or null
|
|
109
|
+
*/
|
|
110
|
+
async lookup(params: {
|
|
111
|
+
userId?: string;
|
|
112
|
+
tenantId: string;
|
|
113
|
+
}): Promise<ApiResponse<Customer | null>> {
|
|
114
|
+
const response = await this.client.get<ApiResponse<Customer | null>>(
|
|
115
|
+
'/api/v1/customers/lookup',
|
|
116
|
+
{ params: { userId: params.userId, tenantId: params.tenantId } }
|
|
117
|
+
);
|
|
118
|
+
return response.data;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Get autocomplete data from existing customers and bookings
|
|
123
|
+
* GET /api/v1/customers/autocomplete
|
|
124
|
+
*
|
|
125
|
+
* @param tenantId - Tenant ID (required)
|
|
126
|
+
* @returns Autocomplete data
|
|
127
|
+
*/
|
|
128
|
+
async autocomplete(tenantId: string): Promise<ApiResponse<any>> {
|
|
129
|
+
const response = await this.client.get<ApiResponse<any>>(
|
|
130
|
+
'/api/v1/customers/autocomplete',
|
|
131
|
+
{ params: { tenantId } }
|
|
132
|
+
);
|
|
133
|
+
return response.data;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Get all bookings for a customer
|
|
138
|
+
* GET /api/v1/customers/bookings
|
|
139
|
+
*
|
|
140
|
+
* @param params - Query parameters (email optional, userId optional, tenantId required)
|
|
141
|
+
* @returns Customer bookings data
|
|
142
|
+
*/
|
|
143
|
+
async getBookings(params: {
|
|
144
|
+
email?: string;
|
|
145
|
+
userId?: string;
|
|
146
|
+
tenantId: string;
|
|
147
|
+
}): Promise<ApiResponse<{
|
|
148
|
+
customer: Customer | null;
|
|
149
|
+
bookings: Booking[];
|
|
150
|
+
groupedBySlot: Record<string, Booking[]>;
|
|
151
|
+
total: number;
|
|
152
|
+
}>> {
|
|
153
|
+
const response = await this.client.get<ApiResponse<{
|
|
154
|
+
customer: Customer | null;
|
|
155
|
+
bookings: Booking[];
|
|
156
|
+
groupedBySlot: Record<string, Booking[]>;
|
|
157
|
+
total: number;
|
|
158
|
+
}>>(
|
|
159
|
+
'/api/v1/customers/bookings',
|
|
160
|
+
{ params }
|
|
161
|
+
);
|
|
162
|
+
return response.data;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import type { AxiosInstance } from 'axios';
|
|
2
|
+
import type {
|
|
3
|
+
ApiResponse,
|
|
4
|
+
Artifact,
|
|
5
|
+
ArtifactWithUrl,
|
|
6
|
+
ListArtifactsOptions,
|
|
7
|
+
UploadArtifactOptions,
|
|
8
|
+
ArtifactEntityType,
|
|
9
|
+
} from '../types/api';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* DocumentClient — manage file artifacts attached to Slotly entities.
|
|
13
|
+
*
|
|
14
|
+
* Artifacts are tenant-scoped files (CVs, invoices, images, etc.) linked
|
|
15
|
+
* to a customer, booking, slot, service, or tenant record.
|
|
16
|
+
*
|
|
17
|
+
* @example Upload a CV for a customer
|
|
18
|
+
* ```ts
|
|
19
|
+
* const artifact = await slotly.document.upload({
|
|
20
|
+
* file: buffer,
|
|
21
|
+
* filename: 'cv-2024.pdf',
|
|
22
|
+
* related_entity_type: 'customer',
|
|
23
|
+
* related_entity_id: customerId,
|
|
24
|
+
* label: 'CV',
|
|
25
|
+
* });
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* @example List all CVs for a customer
|
|
29
|
+
* ```ts
|
|
30
|
+
* const { data } = await slotly.document.listByEntity('customer', customerId, { signed: true });
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export class DocumentClient {
|
|
34
|
+
private readonly client: AxiosInstance;
|
|
35
|
+
private readonly base = '/api/v1/artifacts';
|
|
36
|
+
|
|
37
|
+
constructor(client: AxiosInstance) {
|
|
38
|
+
this.client = client;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Upload a file artifact.
|
|
43
|
+
* Sends as multipart/form-data.
|
|
44
|
+
*/
|
|
45
|
+
async upload(options: UploadArtifactOptions): Promise<Artifact> {
|
|
46
|
+
const form = new FormData();
|
|
47
|
+
|
|
48
|
+
// Normalise file to Blob for FormData compatibility
|
|
49
|
+
let blob: Blob;
|
|
50
|
+
if (options.file instanceof Blob) {
|
|
51
|
+
blob = options.file;
|
|
52
|
+
} else {
|
|
53
|
+
blob = new Blob([options.file], { type: options.mime_type ?? 'application/octet-stream' });
|
|
54
|
+
}
|
|
55
|
+
form.append('file', blob, options.filename);
|
|
56
|
+
form.append('related_entity_type', options.related_entity_type);
|
|
57
|
+
form.append('related_entity_id', options.related_entity_id);
|
|
58
|
+
if (options.label) form.append('label', options.label);
|
|
59
|
+
if (options.mime_type) form.append('mime_type', options.mime_type);
|
|
60
|
+
if (options.metadata) form.append('metadata', JSON.stringify(options.metadata));
|
|
61
|
+
|
|
62
|
+
const response = await this.client.post<ApiResponse<Artifact>>(this.base, form, {
|
|
63
|
+
headers: { 'Content-Type': 'multipart/form-data' },
|
|
64
|
+
});
|
|
65
|
+
const { data } = response.data;
|
|
66
|
+
if (!data) throw new Error('No artifact returned from upload');
|
|
67
|
+
return data;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* List artifacts for a specific entity.
|
|
72
|
+
* Pass `signed: true` to get download URLs in each result.
|
|
73
|
+
*/
|
|
74
|
+
async listByEntity(
|
|
75
|
+
entityType: ArtifactEntityType,
|
|
76
|
+
entityId: string,
|
|
77
|
+
options?: Omit<ListArtifactsOptions, 'related_entity_type' | 'related_entity_id'>
|
|
78
|
+
): Promise<ApiResponse<(Artifact | ArtifactWithUrl)[]>> {
|
|
79
|
+
const response = await this.client.get<ApiResponse<(Artifact | ArtifactWithUrl)[]>>(
|
|
80
|
+
this.base,
|
|
81
|
+
{
|
|
82
|
+
params: {
|
|
83
|
+
related_entity_type: entityType,
|
|
84
|
+
related_entity_id: entityId,
|
|
85
|
+
...options,
|
|
86
|
+
},
|
|
87
|
+
}
|
|
88
|
+
);
|
|
89
|
+
return response.data;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* List artifacts with full filter options.
|
|
94
|
+
*/
|
|
95
|
+
async list(
|
|
96
|
+
options: ListArtifactsOptions
|
|
97
|
+
): Promise<ApiResponse<(Artifact | ArtifactWithUrl)[]>> {
|
|
98
|
+
const response = await this.client.get<ApiResponse<(Artifact | ArtifactWithUrl)[]>>(
|
|
99
|
+
this.base,
|
|
100
|
+
{ params: options }
|
|
101
|
+
);
|
|
102
|
+
return response.data;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Get a single artifact by ID.
|
|
107
|
+
*/
|
|
108
|
+
async get(id: string, signed = false): Promise<Artifact | ArtifactWithUrl> {
|
|
109
|
+
const response = await this.client.get<ApiResponse<Artifact | ArtifactWithUrl>>(
|
|
110
|
+
`${this.base}/${id}`,
|
|
111
|
+
{ params: signed ? { signed: true } : undefined }
|
|
112
|
+
);
|
|
113
|
+
const { data } = response.data;
|
|
114
|
+
if (!data) throw new Error(`Artifact ${id} not found`);
|
|
115
|
+
return data;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Get a signed download URL for an artifact.
|
|
120
|
+
* Returns the full ArtifactWithUrl including `signed_url` and `signed_url_expires_at`.
|
|
121
|
+
*/
|
|
122
|
+
async getUrl(id: string): Promise<ArtifactWithUrl> {
|
|
123
|
+
return this.get(id, true) as Promise<ArtifactWithUrl>;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Delete an artifact and its stored file.
|
|
128
|
+
*/
|
|
129
|
+
async delete(id: string): Promise<void> {
|
|
130
|
+
await this.client.delete(`${this.base}/${id}`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Update artifact label or metadata.
|
|
135
|
+
*/
|
|
136
|
+
async update(
|
|
137
|
+
id: string,
|
|
138
|
+
patch: { label?: string; metadata?: Record<string, unknown> }
|
|
139
|
+
): Promise<Artifact> {
|
|
140
|
+
const response = await this.client.patch<ApiResponse<Artifact>>(
|
|
141
|
+
`${this.base}/${id}`,
|
|
142
|
+
patch
|
|
143
|
+
);
|
|
144
|
+
const { data } = response.data;
|
|
145
|
+
if (!data) throw new Error(`Artifact ${id} not found`);
|
|
146
|
+
return data;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AxiosInstance } from 'axios';
|
|
2
|
-
import { ApiResponse, Service, ServiceWithItems, Category } from '../types/api';
|
|
2
|
+
import { ApiResponse, Service, ServiceWithItems, SlotServiceWithItems, Category } from '../types/api';
|
|
3
3
|
|
|
4
4
|
export class ServiceClient {
|
|
5
5
|
constructor(private client: AxiosInstance) {}
|
|
@@ -20,10 +20,95 @@ export class ServiceClient {
|
|
|
20
20
|
return response.data;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Get services for a tenant (full list with optional filters)
|
|
25
|
+
* GET /api/v1/services
|
|
26
|
+
*
|
|
27
|
+
* @param options - Query options
|
|
28
|
+
* @param options.tenantId - Tenant ID (UUID) - required if tenantSlug not provided
|
|
29
|
+
* @param options.tenantSlug - Tenant slug - required if tenantId not provided
|
|
30
|
+
* @param options.slotId - Slot ID (DEPRECATED - accepted but ignored for API compatibility)
|
|
31
|
+
* @param options.isActive - Filter by active status
|
|
32
|
+
* @param options.includeItems - Include nested service items (default: false)
|
|
33
|
+
* @param options.page - Page number (default: 1)
|
|
34
|
+
* @param options.limit - Items per page (default: 20, max: 100)
|
|
35
|
+
* @returns Services with optional pagination metadata
|
|
36
|
+
*/
|
|
37
|
+
async getServicesByTenant(options: {
|
|
38
|
+
tenantId?: string;
|
|
39
|
+
tenantSlug?: string;
|
|
40
|
+
slotId?: string; // DEPRECATED - accepted but ignored
|
|
41
|
+
isActive?: boolean;
|
|
42
|
+
includeItems?: boolean;
|
|
43
|
+
page?: number;
|
|
44
|
+
limit?: number;
|
|
45
|
+
}): Promise<ApiResponse<Service[] | ServiceWithItems[]>> {
|
|
46
|
+
// Validate that either tenantId or tenantSlug is provided
|
|
47
|
+
if (!options.tenantId && !options.tenantSlug) {
|
|
48
|
+
return {
|
|
49
|
+
success: false,
|
|
50
|
+
error: {
|
|
51
|
+
code: 'MISSING_TENANT_ID',
|
|
52
|
+
message: 'tenantId or tenantSlug is required',
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Build query parameters
|
|
58
|
+
const params: Record<string, any> = {};
|
|
59
|
+
|
|
60
|
+
if (options.tenantId) {
|
|
61
|
+
params.tenant_id = options.tenantId;
|
|
62
|
+
}
|
|
63
|
+
if (options.tenantSlug) {
|
|
64
|
+
params.tenantSlug = options.tenantSlug;
|
|
65
|
+
}
|
|
66
|
+
if (options.slotId) {
|
|
67
|
+
// Include for API compatibility, even though it's ignored
|
|
68
|
+
params.slot_id = options.slotId;
|
|
69
|
+
}
|
|
70
|
+
if (options.isActive !== undefined) {
|
|
71
|
+
params.is_active = options.isActive;
|
|
72
|
+
}
|
|
73
|
+
if (options.includeItems) {
|
|
74
|
+
params.includeItems = true;
|
|
75
|
+
}
|
|
76
|
+
if (options.page !== undefined) {
|
|
77
|
+
params.page = options.page;
|
|
78
|
+
}
|
|
79
|
+
if (options.limit !== undefined) {
|
|
80
|
+
params.limit = Math.min(options.limit, 100); // Enforce max limit
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const response = await this.client.get<ApiResponse<Service[] | ServiceWithItems[]>>(
|
|
84
|
+
'/api/v1/services',
|
|
85
|
+
{ params }
|
|
86
|
+
);
|
|
87
|
+
return response.data;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Get services for a specific slot
|
|
92
|
+
* GET /api/v1/slots/:id/services
|
|
93
|
+
*
|
|
94
|
+
* Note: Services are tenant-level entities. This endpoint returns all active services
|
|
95
|
+
* for the slot's tenant with items included. The response uses 'items' property (not 'serviceItems').
|
|
96
|
+
*
|
|
97
|
+
* @param slotId - Slot ID (UUID)
|
|
98
|
+
* @returns Services with nested items (always includes items, only active services)
|
|
99
|
+
*/
|
|
100
|
+
async getServicesBySlot(slotId: string): Promise<ApiResponse<SlotServiceWithItems[]>> {
|
|
101
|
+
const response = await this.client.get<ApiResponse<SlotServiceWithItems[]>>(
|
|
102
|
+
`/api/v1/slots/${slotId}/services`
|
|
103
|
+
);
|
|
104
|
+
return response.data;
|
|
105
|
+
}
|
|
106
|
+
|
|
23
107
|
/**
|
|
24
108
|
* List services by tenant slug
|
|
25
109
|
* GET /api/v1/services?tenantSlug=:slug
|
|
26
110
|
*
|
|
111
|
+
* @deprecated Consider using getServicesByTenant() for better type safety and validation
|
|
27
112
|
* @param slug - Tenant slug (or use tenant_id in list() method)
|
|
28
113
|
* @param params - Optional parameters (includeItems, page, limit, is_active)
|
|
29
114
|
* @returns List of services for the tenant
|
|
@@ -48,6 +133,7 @@ export class ServiceClient {
|
|
|
48
133
|
* List services with optional filters
|
|
49
134
|
* GET /api/v1/services
|
|
50
135
|
*
|
|
136
|
+
* @deprecated Consider using getServicesByTenant() for better type safety and validation
|
|
51
137
|
* @param params - Query parameters (tenant_id, tenantSlug, slot_id, page, limit, is_active, includeItems)
|
|
52
138
|
* @returns Paginated list of services
|
|
53
139
|
*/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AxiosInstance } from 'axios';
|
|
2
|
-
import { ApiResponse, Slot,
|
|
2
|
+
import { ApiResponse, Slot, SlotServiceWithItems, Tenant } from '../types/api';
|
|
3
3
|
|
|
4
4
|
export class SlotClient {
|
|
5
5
|
constructor(private client: AxiosInstance) {}
|
|
@@ -113,11 +113,14 @@ export class SlotClient {
|
|
|
113
113
|
* Get all active services for a slot with their items
|
|
114
114
|
* GET /api/v1/slots/:id/services
|
|
115
115
|
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
116
|
+
* Note: Services are tenant-level entities. This endpoint returns all active services
|
|
117
|
+
* for the slot's tenant with items included. The response uses 'items' property (not 'serviceItems').
|
|
118
|
+
*
|
|
119
|
+
* @param id - Slot ID (UUID)
|
|
120
|
+
* @returns Services with nested items (always includes items, only active services)
|
|
118
121
|
*/
|
|
119
|
-
async getServices(id: string): Promise<ApiResponse<
|
|
120
|
-
const response = await this.client.get<ApiResponse<
|
|
122
|
+
async getServices(id: string): Promise<ApiResponse<SlotServiceWithItems[]>> {
|
|
123
|
+
const response = await this.client.get<ApiResponse<SlotServiceWithItems[]>>(
|
|
121
124
|
`/api/v1/slots/${id}/services`
|
|
122
125
|
);
|
|
123
126
|
return response.data;
|
package/src/index.ts
CHANGED
|
@@ -10,6 +10,7 @@ import { StudioClient } from './clients/studio-client';
|
|
|
10
10
|
import { NotificationClient } from './clients/notification-client';
|
|
11
11
|
import { DataQualityClient } from './clients/data-quality-client';
|
|
12
12
|
import { OrganizationClient } from './clients/organization-client';
|
|
13
|
+
import { DocumentClient } from './clients/document-client';
|
|
13
14
|
import { setupRequestInterceptor, setupResponseInterceptor, setupErrorInterceptor } from './interceptors';
|
|
14
15
|
import { setupRetryInterceptor } from './retry';
|
|
15
16
|
import { SlotlyConfigurationError } from './errors';
|
|
@@ -26,10 +27,17 @@ export type {
|
|
|
26
27
|
Service,
|
|
27
28
|
ServiceItem,
|
|
28
29
|
ServiceWithItems,
|
|
30
|
+
SlotServiceWithItems,
|
|
29
31
|
ServiceItemWithService,
|
|
30
32
|
Category,
|
|
31
33
|
Slot,
|
|
32
34
|
Customer,
|
|
35
|
+
CustomerIdentity,
|
|
36
|
+
CustomerWithIdentities,
|
|
37
|
+
NotificationPreferences,
|
|
38
|
+
CustomerWithBookings,
|
|
39
|
+
ResolveCustomerOptions,
|
|
40
|
+
FindOrCreateCustomerOptions,
|
|
33
41
|
Flow,
|
|
34
42
|
FlowStep,
|
|
35
43
|
Studio,
|
|
@@ -38,6 +46,12 @@ export type {
|
|
|
38
46
|
Organization,
|
|
39
47
|
OrganizationFullConfig,
|
|
40
48
|
GetOrganizationOptions,
|
|
49
|
+
Artifact,
|
|
50
|
+
ArtifactWithUrl,
|
|
51
|
+
ArtifactEntityType,
|
|
52
|
+
ArtifactMimeCategory,
|
|
53
|
+
ListArtifactsOptions,
|
|
54
|
+
UploadArtifactOptions,
|
|
41
55
|
} from './types/api';
|
|
42
56
|
|
|
43
57
|
// Re-export errors
|
|
@@ -104,6 +118,8 @@ export interface SlotlyApi {
|
|
|
104
118
|
notification: NotificationClient;
|
|
105
119
|
dataQuality: DataQualityClient;
|
|
106
120
|
organization: OrganizationClient;
|
|
121
|
+
/** Upload and retrieve file artifacts (CVs, invoices, images) linked to any Slotly entity */
|
|
122
|
+
document: DocumentClient;
|
|
107
123
|
}
|
|
108
124
|
|
|
109
125
|
const defaultBaseURL = typeof process !== 'undefined' && process.env?.SLOTLY_API_URL
|
|
@@ -297,6 +313,7 @@ export const useSlotly = (options: SlotlyClientOptions): SlotlyApi => {
|
|
|
297
313
|
notification: new NotificationClient(client),
|
|
298
314
|
dataQuality: new DataQualityClient(client),
|
|
299
315
|
organization: new OrganizationClient(client),
|
|
316
|
+
document: new DocumentClient(client),
|
|
300
317
|
};
|
|
301
318
|
};
|
|
302
319
|
|