rotacloud 2.0.3 → 2.1.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.
Files changed (33) hide show
  1. package/dist/client-builder.d.ts +9 -1
  2. package/dist/client-builder.js +14 -0
  3. package/dist/endpoint.d.ts +8 -4
  4. package/dist/interfaces/index.d.ts +1 -2
  5. package/dist/interfaces/index.js +1 -2
  6. package/dist/interfaces/logbook.interface.d.ts +29 -0
  7. package/dist/interfaces/query-params/index.d.ts +0 -1
  8. package/dist/interfaces/query-params/index.js +0 -1
  9. package/dist/main.d.ts +20 -4
  10. package/dist/ops.js +15 -6
  11. package/dist/ops.test.js +123 -50
  12. package/dist/service.d.ts +31 -4
  13. package/dist/service.js +48 -8
  14. package/dist/utils.js +1 -1
  15. package/package.json +4 -4
  16. package/src/client-builder.ts +28 -1
  17. package/src/endpoint.ts +18 -3
  18. package/src/interfaces/index.ts +1 -2
  19. package/src/interfaces/logbook.interface.ts +31 -0
  20. package/src/interfaces/query-params/index.ts +0 -1
  21. package/src/ops.test.ts +133 -51
  22. package/src/ops.ts +19 -6
  23. package/src/service.ts +83 -10
  24. package/src/utils.ts +1 -1
  25. package/dist/interfaces/logbook-category.interface.d.ts +0 -5
  26. package/dist/interfaces/logbook-event.interface.d.ts +0 -16
  27. package/dist/interfaces/logbook-event.interface.js +0 -1
  28. package/dist/interfaces/query-params/logbook-events-query-params.interface.d.ts +0 -3
  29. package/dist/interfaces/query-params/logbook-events-query-params.interface.js +0 -1
  30. package/src/interfaces/logbook-category.interface.ts +0 -5
  31. package/src/interfaces/logbook-event.interface.ts +0 -16
  32. package/src/interfaces/query-params/logbook-events-query-params.interface.ts +0 -3
  33. /package/dist/interfaces/{logbook-category.interface.js → logbook.interface.js} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rotacloud",
3
- "version": "2.0.3",
3
+ "version": "2.1.1",
4
4
  "description": "The RotaCloud SDK for the RotaCloud API",
5
5
  "type": "module",
6
6
  "engines": {
@@ -40,9 +40,9 @@
40
40
  "eslint-config-airbnb-typescript": "^17.1.0",
41
41
  "eslint-config-prettier": "^9.0.0",
42
42
  "eslint-plugin-import": "^2.31.0",
43
- "prettier": "~3.4.1",
44
- "typescript": "^5.6.3",
45
- "vitest": "^2.1.6"
43
+ "prettier": "~3.5.0",
44
+ "typescript": "^5.7.3",
45
+ "vitest": "^3.0.5"
46
46
  },
47
47
  "dependencies": {
48
48
  "axios": "^1.7.7",
@@ -26,8 +26,21 @@ type ServiceCustomOps<Spec extends ServiceSpecification> = {
26
26
  ? ReturnType<typeof buildOp<Spec['customOperations'][Key]>>
27
27
  : never;
28
28
  };
29
+
30
+ /** Mapped index type of all sub services defined on a provided {@link ServiceSpecification] */
31
+ type ServiceSubServices<Spec extends ServiceSpecification> = {
32
+ [Key in keyof Spec['subService']]: Spec['subService'][Key] extends ServiceSpecification
33
+ ? Service<Spec['subService'][Key]>
34
+ : never;
35
+ };
36
+
37
+ /**
38
+ * Service constructed from a provided {@link ServiceSpecification} consisting of
39
+ * built operation and custom operation methods and sub services
40
+ */
29
41
  type Service<Spec extends ServiceSpecification> = Omit<ServiceOps<Spec>, keyof ServiceCustomOps<Spec>> &
30
- ServiceCustomOps<Spec>;
42
+ ServiceCustomOps<Spec> &
43
+ ServiceSubServices<Spec>;
31
44
 
32
45
  export type SdkClient<T extends Record<string, ServiceSpecification>> = {
33
46
  [ServiceName in keyof T]: Service<T[ServiceName]>;
@@ -59,6 +72,20 @@ function serviceForContext<Spec extends ServiceSpecification>(opContext: Operati
59
72
  for (const [customOpName, customOpFunc] of Object.entries(opContext.service.customOperations ?? {})) {
60
73
  service[customOpName] = buildOp(opContext, customOpFunc);
61
74
  }
75
+ for (const [subServiceName, subServiceSpec] of Object.entries(opContext.service.subService ?? {})) {
76
+ service[subServiceName] = serviceForContext({
77
+ get client() {
78
+ return opContext.client;
79
+ },
80
+ get request() {
81
+ return opContext.request;
82
+ },
83
+ get sdkConfig() {
84
+ return opContext.sdkConfig;
85
+ },
86
+ service: subServiceSpec,
87
+ });
88
+ }
62
89
 
63
90
  return service as Service<Spec>;
64
91
  }
package/src/endpoint.ts CHANGED
@@ -24,7 +24,9 @@ import {
24
24
  UserClockedIn,
25
25
  User,
26
26
  Settings,
27
+ LogbookCategory,
27
28
  } from './interfaces/index.js';
29
+ import { LogbookEntry, LogbookQueryParameters } from './interfaces/logbook.interface.js';
28
30
  import {
29
31
  AttendanceQueryParams,
30
32
  AvailabilityQueryParams,
@@ -51,13 +53,23 @@ import { RequirementsOf } from './utils.js';
51
53
  /** Endpoint versions supported by the API */
52
54
  export type EndpointVersion = 'v1' | 'v2';
53
55
  /** Associated types for a given API endpoint */
54
- export type Endpoint<Entity, QueryParameters = undefined, RequiredFields extends keyof Entity = any> = {
56
+ export type Endpoint<
57
+ Entity,
58
+ QueryParameters = undefined,
59
+ CreateEntity extends keyof Entity | Partial<Entity> = any,
60
+ // NOTE: introduced to work around TS inferring `RequirementsOf<Entity, CreateEntity>` incorrectly
61
+ // TS resolves type to:
62
+ // `RequirementsOf<Entity, "key 1"> | RequirementsOf<Entity "key 2">`
63
+ // instead of:
64
+ // `RequirementsOf<Entity, "key 1" | "key 2">`
65
+ RequiredFields extends keyof Entity = CreateEntity extends keyof Entity ? CreateEntity : never,
66
+ > = {
55
67
  /** The type returned by an endpoint */
56
68
  type: Entity;
57
69
  /** The query parameters for endpoints that support listing */
58
70
  queryParameters: QueryParameters;
59
71
  /** The entity type required for endpoints that support creation */
60
- createType: RequirementsOf<Entity, RequiredFields>;
72
+ createType: CreateEntity extends keyof Entity ? RequirementsOf<Entity, RequiredFields> : CreateEntity;
61
73
  };
62
74
 
63
75
  /** Mapping between a endpoint URL and it's associated entity type
@@ -95,5 +107,8 @@ export interface EndpointEntityMap extends Record<EndpointVersion, Record<string
95
107
  users: Endpoint<User, UsersQueryParams, 'first_name' | 'last_name'>;
96
108
  };
97
109
  /** Type mappings for v2 endpoints */
98
- v2: {};
110
+ v2: {
111
+ logbook: Endpoint<LogbookEntry, LogbookQueryParameters, 'name' | 'description' | 'date' | 'userId'>;
112
+ 'logbook/categories': Endpoint<LogbookCategory, undefined, Pick<LogbookCategory, 'name'>>;
113
+ };
99
114
  }
@@ -20,8 +20,7 @@ export * from './leave-type.interface.js';
20
20
  export * from './leave.interface.js';
21
21
  export * from './location-coordinate.interface.js';
22
22
  export * from './location.interface.js';
23
- export * from './logbook-category.interface.js';
24
- export * from './logbook-event.interface.js';
23
+ export * from './logbook.interface.js';
25
24
  export * from './pay-period.interface.js';
26
25
  export * from './pin.interface.js';
27
26
  export * from './role-rate.interface.js';
@@ -0,0 +1,31 @@
1
+ export interface LogbookCategory {
2
+ id: number;
3
+ name: string;
4
+ deleted: boolean;
5
+ /** Date and time in ISO 8601 format */
6
+ createdAt: string;
7
+ createdBy: number;
8
+ }
9
+
10
+ export interface LogbookEntry {
11
+ id: number;
12
+ name: string;
13
+ description: string;
14
+ categoryId: number;
15
+ /** Date of entry in ISO 8601 format */
16
+ date: string;
17
+ time: string | null;
18
+ /** Date and time in ISO 8601 format */
19
+ createdAt: string | null;
20
+ createdBy: number;
21
+ /** Date and time in ISO 8601 format */
22
+ updatedAt: string | null;
23
+ updatedBy: number | null;
24
+ userId: number;
25
+ }
26
+
27
+ export interface LogbookQueryParameters {
28
+ userId: number;
29
+ /** Date in ISO 8601 format */
30
+ date?: string;
31
+ }
@@ -13,7 +13,6 @@ export * from './leave-embargoes-query-params.interface.js';
13
13
  export * from './leave-query-params.interface.js';
14
14
  export * from './leave-requests-query-params.interface.js';
15
15
  export * from './locations-query-params.interface.js';
16
- export * from './logbook-events-query-params.interface.js';
17
16
  export * from './pay-periods-query-params.interface.js';
18
17
  export * from './roles-query-params.interface.js';
19
18
  export * from './settings-query-params.interface.js';
package/src/ops.test.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { describe, expect, test, vi } from 'vitest';
1
+ import { afterEach, describe, expect, test, vi } from 'vitest';
2
2
  import { Axios } from 'axios';
3
3
  import { createSdkClient } from './client-builder.js';
4
4
  import { getOpMap } from './ops.js';
@@ -22,7 +22,7 @@ vi.mock(import('axios'), async (importOriginal) => {
22
22
  });
23
23
 
24
24
  describe('Operations', () => {
25
- const service = {
25
+ const serviceV1 = {
26
26
  endpoint: 'settings',
27
27
  endpointVersion: 'v1',
28
28
  operations: ['get', 'list'],
@@ -30,18 +30,31 @@ describe('Operations', () => {
30
30
  promiseOp: async () => 3,
31
31
  },
32
32
  } satisfies ServiceSpecification;
33
+ const serviceV2 = {
34
+ endpoint: 'logbook',
35
+ endpointVersion: 'v2',
36
+ operations: ['get', 'list'],
37
+ customOperations: {
38
+ promiseOp: async () => 3,
39
+ },
40
+ } satisfies ServiceSpecification;
33
41
  const clientBuilder = createSdkClient({
34
- service,
42
+ service: serviceV1,
43
+ serviceV2,
35
44
  });
36
45
  const client = clientBuilder({ basicAuth: '' });
37
46
 
47
+ afterEach(() => {
48
+ vi.restoreAllMocks();
49
+ });
50
+
38
51
  test('operations returning a request config trigger a request call', async () => {
39
52
  const basicOp = getOpMap().v1.get;
40
53
  const basicOpRes = basicOp(
41
54
  {
42
55
  client: mockAxiosClient,
43
56
  request: {},
44
- service,
57
+ service: serviceV1,
45
58
  sdkConfig: { apiKey: '' },
46
59
  },
47
60
  1,
@@ -57,65 +70,134 @@ describe('Operations', () => {
57
70
  });
58
71
 
59
72
  test('operations returning a promise are returned as is', async () => {
60
- const promiseOpRes = await service.customOperations.promiseOp();
73
+ const promiseOpRes = await serviceV1.customOperations.promiseOp();
61
74
  expect(promiseOpRes).toStrictEqual(await client.service.promiseOp());
62
75
  });
63
76
 
64
- describe('list op', () => {
65
- test('respects `maxResults` parameter in legacy pagination', async () => {
66
- vi.spyOn(mockAxiosClient, 'request').mockResolvedValue({ data: [] });
77
+ describe('list', () => {
78
+ describe('v1 ops', () => {
79
+ test('respects `maxResults` parameter in pagination', async () => {
80
+ vi.spyOn(mockAxiosClient, 'request').mockResolvedValue({ data: [] });
67
81
 
68
- await client.service.list({}, { maxResults: 2 }).next();
69
- expect(mockAxiosClient.request).toHaveBeenCalledWith(
70
- expect.objectContaining({
71
- url: expect.any(String),
72
- params: {
73
- limit: 2,
82
+ await client.service.list({}, { maxResults: 2 }).next();
83
+ expect(mockAxiosClient.request).toHaveBeenCalledWith(
84
+ expect.objectContaining({
85
+ url: expect.any(String),
86
+ params: {
87
+ limit: 2,
88
+ },
89
+ }),
90
+ );
91
+ });
92
+
93
+ test('automatically paginates', async () => {
94
+ const pageTotal = 3;
95
+ let pageCount = 0;
96
+ vi.spyOn(mockAxiosClient, 'request').mockResolvedValue({
97
+ headers: {
98
+ 'x-limit': 1,
99
+ 'x-total-count': pageTotal,
100
+ // eslint-disable-next-line no-plusplus
101
+ 'x-offset': pageCount++,
74
102
  },
75
- }),
76
- );
77
- });
103
+ data: [],
104
+ });
78
105
 
79
- test('automatically paginates', async () => {
80
- const pageTotal = 3;
81
- let pageCount = 0;
82
- vi.spyOn(mockAxiosClient, 'request').mockResolvedValue({
83
- headers: {
84
- 'x-limit': 1,
85
- 'x-total-count': pageTotal,
86
- // eslint-disable-next-line no-plusplus
87
- 'x-offset': pageCount++,
88
- },
89
- data: [],
106
+ for await (const res of client.service.list({})) {
107
+ res;
108
+ }
109
+ expect(mockAxiosClient.request).toHaveBeenCalledTimes(pageTotal);
90
110
  });
91
111
 
92
- for await (const res of client.service.list({})) {
93
- res;
94
- }
95
- expect(mockAxiosClient.request).toHaveBeenCalledTimes(pageTotal);
112
+ test('stops automatic pagination after maxResults reached', async () => {
113
+ const pageLimit = 2;
114
+ const pageTotal = 6;
115
+ let pageCount = 0;
116
+ vi.spyOn(mockAxiosClient, 'request').mockResolvedValue({
117
+ headers: {
118
+ 'x-limit': pageLimit,
119
+ 'x-total-count': pageTotal,
120
+ // eslint-disable-next-line no-plusplus
121
+ 'x-offset': pageCount++,
122
+ },
123
+ data: new Array(pageLimit).fill('entity'),
124
+ });
125
+
126
+ let resultCount = 0;
127
+ for await (const res of client.service.list({}, { maxResults: 3 })) {
128
+ resultCount += 1;
129
+ res;
130
+ }
131
+ expect(resultCount).toBe(3);
132
+ expect(mockAxiosClient.request).toHaveBeenCalledTimes(2);
133
+ });
96
134
  });
97
135
 
98
- test('stops automatic pagination after maxResults reached', async () => {
99
- const pageLimit = 2;
100
- const pageTotal = 6;
101
- let pageCount = 0;
102
- vi.spyOn(mockAxiosClient, 'request').mockResolvedValue({
103
- headers: {
104
- 'x-limit': pageLimit,
105
- 'x-total-count': pageTotal,
106
- // eslint-disable-next-line no-plusplus
107
- 'x-offset': pageCount++,
108
- },
109
- data: new Array(pageLimit).fill('entity'),
136
+ describe('v2 ops', () => {
137
+ test('respects `maxResults` parameter in pagination', async () => {
138
+ vi.spyOn(mockAxiosClient, 'request').mockResolvedValue({
139
+ data: { data: [], pagination: { next: null, count: 0 } },
140
+ });
141
+
142
+ await client.serviceV2.list({ userId: 0 }, { maxResults: 2 }).next();
143
+ expect(mockAxiosClient.request).toHaveBeenCalledWith(
144
+ expect.objectContaining({
145
+ url: expect.any(String),
146
+ params: expect.objectContaining({
147
+ limit: 2,
148
+ }),
149
+ }),
150
+ );
110
151
  });
111
152
 
112
- let resultCount = 0;
113
- for await (const res of client.service.list({}, { maxResults: 3 })) {
114
- resultCount += 1;
115
- res;
116
- }
117
- expect(resultCount).toBe(3);
118
- expect(mockAxiosClient.request).toHaveBeenCalledTimes(2);
153
+ test('automatically paginates', async () => {
154
+ const pageTotal = 3;
155
+ const pageLimit = 2;
156
+ let pageCount = 0;
157
+ vi.spyOn(mockAxiosClient, 'request').mockImplementation(async () => {
158
+ pageCount += 1;
159
+ return {
160
+ data: {
161
+ data: new Array(pageLimit).fill('entity'),
162
+ pagination: {
163
+ next: pageCount < pageTotal ? String(pageCount) : null,
164
+ count: pageTotal,
165
+ },
166
+ },
167
+ };
168
+ });
169
+
170
+ for await (const res of client.serviceV2.list({ userId: 0 })) {
171
+ res;
172
+ }
173
+ expect(mockAxiosClient.request).toHaveBeenCalledTimes(pageTotal);
174
+ });
175
+
176
+ test('stops automatic pagination after maxResults reached', async () => {
177
+ const pageLimit = 2;
178
+ const pageTotal = 6;
179
+ let pageCount = 0;
180
+ vi.spyOn(mockAxiosClient, 'request').mockImplementation(() => {
181
+ pageCount += pageLimit;
182
+ return Promise.resolve({
183
+ data: {
184
+ data: new Array(pageLimit).fill('entity'),
185
+ pagination: {
186
+ next: pageCount < pageTotal ? String(pageCount) : null,
187
+ count: pageTotal,
188
+ },
189
+ },
190
+ });
191
+ });
192
+
193
+ let resultCount = 0;
194
+ for await (const res of client.serviceV2.list({ userId: 0 }, { maxResults: 3 })) {
195
+ resultCount += 1;
196
+ res;
197
+ }
198
+ expect(resultCount).toBe(3);
199
+ expect(mockAxiosClient.request).toHaveBeenCalledTimes(2);
200
+ });
119
201
  });
120
202
  });
121
203
  });
package/src/ops.ts CHANGED
@@ -220,8 +220,8 @@ function createOp<T = unknown, NewEntity = unknown>(
220
220
  };
221
221
  }
222
222
 
223
- /** Operation for updating an entity */
224
- function updateOp<Return, Entity extends { id: number } & Partial<Return>>(
223
+ /** Operation for updating an entity for v1 endpoints */
224
+ function updateV1Op<Return, Entity extends { id: number } & Partial<Return>>(
225
225
  ctx: OperationContext,
226
226
  entity: Entity,
227
227
  ): RequestConfig<Entity, Return> {
@@ -233,6 +233,19 @@ function updateOp<Return, Entity extends { id: number } & Partial<Return>>(
233
233
  };
234
234
  }
235
235
 
236
+ /** Operation for updating an entity for v2 endpoints */
237
+ function updateV2Op<Return, Entity extends { id: number } & Partial<Return>>(
238
+ ctx: OperationContext,
239
+ entity: Entity,
240
+ ): RequestConfig<Entity, Return> {
241
+ return {
242
+ ...ctx.request,
243
+ method: 'PUT',
244
+ url: `${ctx.service.endpointVersion}/${ctx.service.endpoint}/${entity.id}`,
245
+ data: entity,
246
+ };
247
+ }
248
+
236
249
  /** Operation for deleting a list of entities */
237
250
  async function updateBatchOp<Return, Entity extends { id: number } & Partial<Return>>(
238
251
  ctx: OperationContext,
@@ -439,7 +452,7 @@ async function* listByPageV2Op<T, Query>(
439
452
  yield res;
440
453
  if (entityCount >= maxEntities) return;
441
454
 
442
- let nextPage = res.data.pagination.next;
455
+ let nextPage = res.data.pagination.next ?? undefined;
443
456
  while (nextPage !== undefined) {
444
457
  const pagedRes = await ctx.client.request<PagedResponse<T>>({
445
458
  ...queriedRequest,
@@ -448,7 +461,7 @@ async function* listByPageV2Op<T, Query>(
448
461
  cursor: nextPage,
449
462
  },
450
463
  });
451
- nextPage = pagedRes.data.pagination.next;
464
+ nextPage = pagedRes.data.pagination.next ?? undefined;
452
465
  yield pagedRes;
453
466
  entityCount += pagedRes.data.data.length;
454
467
  if (entityCount >= maxEntities) return;
@@ -515,7 +528,7 @@ export function getOpMap<E extends Endpoint<any, any>, T extends E['type'] = E['
515
528
  listAll: listAllOp<T, E['queryParameters']>,
516
529
  listByPage: listByPageOp<T, E['queryParameters']>,
517
530
  create: createOp<T, E['createType']>,
518
- update: updateOp<T, T extends { id: number } ? RequirementsOf<T, 'id'> : never>,
531
+ update: updateV1Op<T, T extends { id: number } ? RequirementsOf<T, 'id'> : never>,
519
532
  updateBatch: updateBatchOp<T, T extends { id: number } ? RequirementsOf<T, 'id'> : never>,
520
533
  },
521
534
  v2: {
@@ -526,7 +539,7 @@ export function getOpMap<E extends Endpoint<any, any>, T extends E['type'] = E['
526
539
  listAll: listAllV2Op<T, E['queryParameters']>,
527
540
  listByPage: listByPageV2Op<T, E['queryParameters']>,
528
541
  create: createOp<T, E['createType']>,
529
- update: updateOp<T, T extends { id: number } ? RequirementsOf<T, 'id'> : never>,
542
+ update: updateV2Op<T, T extends { id: number } ? RequirementsOf<T, 'id'> : never>,
530
543
  updateBatch: updateBatchOp<T, T extends { id: number } ? RequirementsOf<T, 'id'> : never>,
531
544
  },
532
545
  } satisfies Record<EndpointVersion, Record<Operation, OpDef<any, any>>>;
package/src/service.ts CHANGED
@@ -14,12 +14,23 @@ import {
14
14
  UserClockedOut,
15
15
  } from './interfaces/index.js';
16
16
  import { LaunchTerminal } from './interfaces/launch-terminal.interface.js';
17
- import { OpDef, Operation, OperationContext, RequestConfig, listAllOp, listOp, paramsFromOptions } from './ops.js';
17
+ import {
18
+ OpDef,
19
+ Operation,
20
+ OperationContext,
21
+ RequestConfig,
22
+ listAllOp,
23
+ listAllV2Op,
24
+ listOp,
25
+ listV2Op,
26
+ paramsFromOptions,
27
+ } from './ops.js';
18
28
  import { UserBreakRequest, UserClockIn, UserClockOut } from './interfaces/user-clock-in.interface.js';
19
29
  import { RequirementsOf, RequestOptions } from './utils.js';
20
30
  import { ShiftSwapRequest } from './interfaces/swap-request.interface.js';
21
31
  import { ShiftDropRequest } from './interfaces/drop-request.interface.js';
22
32
  import { ToilAllowanceQueryParams } from './interfaces/query-params/index.js';
33
+ import { LogbookEntry, LogbookQueryParameters } from './interfaces/logbook.interface.js';
23
34
 
24
35
  export type ServiceSpecification<CustomOp extends OpDef<unknown> = OpDef<any>> = {
25
36
  /** Operations allowed and usable for the endpoint */
@@ -29,6 +40,7 @@ export type ServiceSpecification<CustomOp extends OpDef<unknown> = OpDef<any>> =
29
40
  * Can be used to override operations listed in {@see ServiceSpecification['operations']}
30
41
  */
31
42
  customOperations?: Record<string, CustomOp>;
43
+ subService?: Record<string, ServiceSpecification<CustomOp>>;
32
44
  } & (
33
45
  | {
34
46
  /** URL of the endpoint */
@@ -42,6 +54,16 @@ export type ServiceSpecification<CustomOp extends OpDef<unknown> = OpDef<any>> =
42
54
  /** API version of the endpoint */
43
55
  endpointVersion: 'v2';
44
56
  }
57
+ | {
58
+ endpoint: string;
59
+ endpointVersion: 'v1' | 'v2';
60
+ /**
61
+ * Marks the endpoint as one not defined in the {@link EndpointEntityMap}
62
+ *
63
+ * Intended for defining customOperations
64
+ * */
65
+ custom: true;
66
+ }
45
67
  );
46
68
 
47
69
  /**
@@ -193,6 +215,50 @@ export const SERVICES = {
193
215
  endpointVersion: 'v1',
194
216
  operations: ['create', 'get', 'list', 'listAll', 'update', 'delete'],
195
217
  },
218
+ logbook: {
219
+ endpoint: 'logbook',
220
+ endpointVersion: 'v2',
221
+ operations: ['create', 'get', 'delete', 'update'],
222
+ customOperations: {
223
+ list: (ctx, query: LogbookQueryParameters, opts) =>
224
+ // Maps the "userId" query parameter into the endpoint URL
225
+ listV2Op<LogbookEntry, Omit<typeof query, 'userId'>>(
226
+ {
227
+ ...ctx,
228
+ service: {
229
+ ...ctx.service,
230
+ endpoint: `${ctx.service.endpoint}/user/${query.userId}`,
231
+ endpointVersion: 'v2',
232
+ custom: true,
233
+ },
234
+ },
235
+ { date: query.date },
236
+ opts,
237
+ ),
238
+ listAll: (ctx, query: LogbookQueryParameters, opts) =>
239
+ // Maps the "userId" query parameter into the endpoint URL
240
+ listAllV2Op<LogbookEntry, Omit<typeof query, 'userId'>>(
241
+ {
242
+ ...ctx,
243
+ service: {
244
+ ...ctx.service,
245
+ endpoint: `${ctx.service.endpoint}/user/${query.userId}`,
246
+ endpointVersion: 'v2',
247
+ custom: true,
248
+ },
249
+ },
250
+ { date: query.date },
251
+ opts,
252
+ ),
253
+ },
254
+ subService: {
255
+ category: {
256
+ endpoint: 'logbook/categories',
257
+ endpointVersion: 'v2',
258
+ operations: ['get', 'create', 'update', 'delete', 'list', 'listAll'],
259
+ },
260
+ },
261
+ },
196
262
  pin: {
197
263
  endpoint: 'pins',
198
264
  endpointVersion: 'v1',
@@ -278,19 +344,24 @@ export const SERVICES = {
278
344
  },
279
345
  },
280
346
  terminalActive: {
281
- endpoint: 'terminals',
347
+ endpoint: 'terminals_active',
282
348
  endpointVersion: 'v1',
283
349
  operations: ['list', 'listAll'],
284
350
  customOperations: {
285
- launch: ({ request, service }, id: LaunchTerminal): RequestConfig<void, Terminal> => ({
351
+ launch: ({ request, service }, terminal: LaunchTerminal): RequestConfig<LaunchTerminal, Terminal> => ({
286
352
  ...request,
287
- method: 'DELETE',
288
- url: `${service.endpointVersion}/${service.endpoint}/${id}`,
353
+ method: 'POST',
354
+ url: `${service.endpointVersion}/${service.endpoint}`,
355
+ data: terminal,
289
356
  }),
290
- ping: ({ request, service }, id: { id: number; action: string; device: string }): RequestConfig<void, void> => ({
357
+ ping: (
358
+ { request, service },
359
+ terminal: { id: number; action: string; device: string },
360
+ ): RequestConfig<Omit<typeof terminal, 'id'>, void> => ({
291
361
  ...request,
292
- method: 'DELETE',
293
- url: `${service.endpointVersion}/${service.endpoint}/${id}`,
362
+ method: 'POST',
363
+ url: `${service.endpointVersion}/${service.endpoint}/${terminal.id}`,
364
+ data: { action: terminal.action, device: terminal.device },
294
365
  }),
295
366
  close: ({ request, service }, id: number): RequestConfig<void, void> => ({
296
367
  ...request,
@@ -321,8 +392,9 @@ export const SERVICES = {
321
392
  ...ctx,
322
393
  service: {
323
394
  ...ctx.service,
324
- endpoint: `${ctx.service.endpoint}/${query.year}` as typeof ctx.service.endpoint,
395
+ endpoint: `${ctx.service.endpoint}/${query.year}`,
325
396
  endpointVersion: 'v1',
397
+ custom: true,
326
398
  },
327
399
  },
328
400
  { users: query.users },
@@ -335,8 +407,9 @@ export const SERVICES = {
335
407
  ...ctx,
336
408
  service: {
337
409
  ...ctx.service,
338
- endpoint: `${ctx.service.endpoint}/${query.year}` as typeof ctx.service.endpoint,
410
+ endpoint: `${ctx.service.endpoint}/${query.year}`,
339
411
  endpointVersion: 'v1',
412
+ custom: true,
340
413
  },
341
414
  },
342
415
  { users: query.users },
package/src/utils.ts CHANGED
@@ -73,7 +73,7 @@ function toSearchParams(parameters?: Record<string, QueryParameterValue>): URLSe
73
73
 
74
74
  function parseClientError(error: AxiosError): SDKError {
75
75
  const axiosErrorLocation = error.response || error.request;
76
- const apiErrorMessage = axiosErrorLocation.data?.error;
76
+ const apiErrorMessage = axiosErrorLocation.data?.message;
77
77
  let url: URL | undefined;
78
78
  try {
79
79
  url = new URL(error.config?.url ?? '', error.config?.baseURL);
@@ -1,5 +0,0 @@
1
- export interface LogbookCategory {
2
- id: number;
3
- name: string;
4
- deleted?: boolean | null;
5
- }
@@ -1,16 +0,0 @@
1
- export interface LogbookEvent {
2
- id: number;
3
- created_at: number;
4
- created_by: number;
5
- updated_at: string;
6
- updated_by: string;
7
- deleted: boolean;
8
- deleted_at: string;
9
- deleted_by: string;
10
- user: number;
11
- category: number;
12
- date: string;
13
- time: string;
14
- name: string;
15
- description: string;
16
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,3 +0,0 @@
1
- export interface LogbookEventsQueryParams {
2
- user?: number;
3
- }
@@ -1,5 +0,0 @@
1
- export interface LogbookCategory {
2
- id: number;
3
- name: string;
4
- deleted?: boolean | null;
5
- }