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
@@ -13,7 +13,15 @@ type ServiceOps<Spec extends ServiceSpecification> = {
13
13
  type ServiceCustomOps<Spec extends ServiceSpecification> = {
14
14
  [Key in keyof Spec['customOperations']]: Spec['customOperations'][Key] extends OpDef<any, any> ? ReturnType<typeof buildOp<Spec['customOperations'][Key]>> : never;
15
15
  };
16
- type Service<Spec extends ServiceSpecification> = Omit<ServiceOps<Spec>, keyof ServiceCustomOps<Spec>> & ServiceCustomOps<Spec>;
16
+ /** Mapped index type of all sub services defined on a provided {@link ServiceSpecification] */
17
+ type ServiceSubServices<Spec extends ServiceSpecification> = {
18
+ [Key in keyof Spec['subService']]: Spec['subService'][Key] extends ServiceSpecification ? Service<Spec['subService'][Key]> : never;
19
+ };
20
+ /**
21
+ * Service constructed from a provided {@link ServiceSpecification} consisting of
22
+ * built operation and custom operation methods and sub services
23
+ */
24
+ type Service<Spec extends ServiceSpecification> = Omit<ServiceOps<Spec>, keyof ServiceCustomOps<Spec>> & ServiceCustomOps<Spec> & ServiceSubServices<Spec>;
17
25
  export type SdkClient<T extends Record<string, ServiceSpecification>> = {
18
26
  [ServiceName in keyof T]: Service<T[ServiceName]>;
19
27
  } & {
@@ -19,6 +19,20 @@ function serviceForContext(opContext) {
19
19
  for (const [customOpName, customOpFunc] of Object.entries(opContext.service.customOperations ?? {})) {
20
20
  service[customOpName] = buildOp(opContext, customOpFunc);
21
21
  }
22
+ for (const [subServiceName, subServiceSpec] of Object.entries(opContext.service.subService ?? {})) {
23
+ service[subServiceName] = serviceForContext({
24
+ get client() {
25
+ return opContext.client;
26
+ },
27
+ get request() {
28
+ return opContext.request;
29
+ },
30
+ get sdkConfig() {
31
+ return opContext.sdkConfig;
32
+ },
33
+ service: subServiceSpec,
34
+ });
35
+ }
22
36
  return service;
23
37
  }
24
38
  /** Builds the entire SDK client ready to be exported by the library and used by an end
@@ -1,16 +1,17 @@
1
- import { Account, Attendance, Auth, Availability, DailyBudgets, DailyRevenue, DayNote, DaysOff, Group, Leave, Role, Shift, TimeZone, Document, LeaveEmbargo, LeaveRequest, LeaveType, Location, Pin, Terminal, ToilAccrual, ToilAllowance, UserClockedIn, User, Settings } from './interfaces/index.js';
1
+ import { Account, Attendance, Auth, Availability, DailyBudgets, DailyRevenue, DayNote, DaysOff, Group, Leave, Role, Shift, TimeZone, Document, LeaveEmbargo, LeaveRequest, LeaveType, Location, Pin, Terminal, ToilAccrual, ToilAllowance, UserClockedIn, User, Settings, LogbookCategory } from './interfaces/index.js';
2
+ import { LogbookEntry, LogbookQueryParameters } from './interfaces/logbook.interface.js';
2
3
  import { AttendanceQueryParams, AvailabilityQueryParams, DailyBudgetsQueryParams, DailyRevenueQueryParams, DayNotesQueryParams, DaysOffQueryParams, DocumentsQueryParams, GroupsQueryParams, LeaveEmbargoesQueryParams, LeaveQueryParams, LeaveRequestsQueryParams, LocationsQueryParams, RolesQueryParams, SettingsQueryParams, ShiftsQueryParams, TerminalsQueryParams, ToilAccrualsQueryParams, ToilAllowanceQueryParams, UsersQueryParams } from './interfaces/query-params/index.js';
3
4
  import { RequirementsOf } from './utils.js';
4
5
  /** Endpoint versions supported by the API */
5
6
  export type EndpointVersion = 'v1' | 'v2';
6
7
  /** Associated types for a given API endpoint */
7
- export type Endpoint<Entity, QueryParameters = undefined, RequiredFields extends keyof Entity = any> = {
8
+ export type Endpoint<Entity, QueryParameters = undefined, CreateEntity extends keyof Entity | Partial<Entity> = any, RequiredFields extends keyof Entity = CreateEntity extends keyof Entity ? CreateEntity : never> = {
8
9
  /** The type returned by an endpoint */
9
10
  type: Entity;
10
11
  /** The query parameters for endpoints that support listing */
11
12
  queryParameters: QueryParameters;
12
13
  /** The entity type required for endpoints that support creation */
13
- createType: RequirementsOf<Entity, RequiredFields>;
14
+ createType: CreateEntity extends keyof Entity ? RequirementsOf<Entity, RequiredFields> : CreateEntity;
14
15
  };
15
16
  /** Mapping between a endpoint URL and it's associated entity type
16
17
  *
@@ -47,5 +48,8 @@ export interface EndpointEntityMap extends Record<EndpointVersion, Record<string
47
48
  users: Endpoint<User, UsersQueryParams, 'first_name' | 'last_name'>;
48
49
  };
49
50
  /** Type mappings for v2 endpoints */
50
- v2: {};
51
+ v2: {
52
+ logbook: Endpoint<LogbookEntry, LogbookQueryParameters, 'name' | 'description' | 'date' | 'userId'>;
53
+ 'logbook/categories': Endpoint<LogbookCategory, undefined, Pick<LogbookCategory, 'name'>>;
54
+ };
51
55
  }
@@ -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';
@@ -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,29 @@
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
+ export interface LogbookEntry {
10
+ id: number;
11
+ name: string;
12
+ description: string;
13
+ categoryId: number;
14
+ /** Date of entry in ISO 8601 format */
15
+ date: string;
16
+ time: string | null;
17
+ /** Date and time in ISO 8601 format */
18
+ createdAt: string | null;
19
+ createdBy: number;
20
+ /** Date and time in ISO 8601 format */
21
+ updatedAt: string | null;
22
+ updatedBy: number | null;
23
+ userId: number;
24
+ }
25
+ export interface LogbookQueryParameters {
26
+ userId: number;
27
+ /** Date in ISO 8601 format */
28
+ date?: string;
29
+ }
@@ -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';
@@ -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/dist/main.d.ts CHANGED
@@ -92,6 +92,22 @@ export declare const createRotaCloudClient: (config: import("./interfaces/sdk-co
92
92
  endpointVersion: "v1";
93
93
  operations: ("get" | "delete" | "list" | "listAll" | "create" | "update")[];
94
94
  };
95
+ logbook: {
96
+ endpoint: "logbook";
97
+ endpointVersion: "v2";
98
+ operations: ("get" | "delete" | "create" | "update")[];
99
+ customOperations: {
100
+ list: (ctx: import("./ops.js").OperationContext, query: import("./interfaces/logbook.interface.js").LogbookQueryParameters, opts: import("./utils.js").RequestOptions<unknown> | undefined) => AsyncGenerator<import("./interfaces/logbook.interface.js").LogbookEntry, any, any>;
101
+ listAll: (ctx: import("./ops.js").OperationContext, query: import("./interfaces/logbook.interface.js").LogbookQueryParameters, opts: import("./utils.js").RequestOptions<unknown> | undefined) => Promise<import("./interfaces/logbook.interface.js").LogbookEntry[]>;
102
+ };
103
+ subService: {
104
+ category: {
105
+ endpoint: "logbook/categories";
106
+ endpointVersion: "v2";
107
+ operations: ("get" | "delete" | "list" | "listAll" | "create" | "update")[];
108
+ };
109
+ };
110
+ };
95
111
  pin: {
96
112
  endpoint: "pins";
97
113
  endpointVersion: "v1";
@@ -144,16 +160,16 @@ export declare const createRotaCloudClient: (config: import("./interfaces/sdk-co
144
160
  };
145
161
  };
146
162
  terminalActive: {
147
- endpoint: "terminals";
163
+ endpoint: "terminals_active";
148
164
  endpointVersion: "v1";
149
165
  operations: ("list" | "listAll")[];
150
166
  customOperations: {
151
- launch: ({ request, service }: import("./ops.js").OperationContext, id: import("./interfaces/launch-terminal.interface.js").LaunchTerminal) => import("./ops.js").RequestConfig<void, import("./interfaces/terminal.interface.js").Terminal>;
152
- ping: ({ request, service }: import("./ops.js").OperationContext, id: {
167
+ launch: ({ request, service }: import("./ops.js").OperationContext, terminal: import("./interfaces/launch-terminal.interface.js").LaunchTerminal) => import("./ops.js").RequestConfig<import("./interfaces/launch-terminal.interface.js").LaunchTerminal, import("./interfaces/terminal.interface.js").Terminal>;
168
+ ping: ({ request, service }: import("./ops.js").OperationContext, terminal: {
153
169
  id: number;
154
170
  action: string;
155
171
  device: string;
156
- }) => import("./ops.js").RequestConfig<void, void>;
172
+ }) => import("./ops.js").RequestConfig<Omit<typeof terminal, "id">, void>;
157
173
  close: ({ request, service }: import("./ops.js").OperationContext, id: number) => import("./ops.js").RequestConfig<void, void>;
158
174
  };
159
175
  };
package/dist/ops.js CHANGED
@@ -45,8 +45,8 @@ function createOp(ctx, newEntity) {
45
45
  data: newEntity,
46
46
  };
47
47
  }
48
- /** Operation for updating an entity */
49
- function updateOp(ctx, entity) {
48
+ /** Operation for updating an entity for v1 endpoints */
49
+ function updateV1Op(ctx, entity) {
50
50
  return {
51
51
  ...ctx.request,
52
52
  method: 'POST',
@@ -54,6 +54,15 @@ function updateOp(ctx, entity) {
54
54
  data: entity,
55
55
  };
56
56
  }
57
+ /** Operation for updating an entity for v2 endpoints */
58
+ function updateV2Op(ctx, entity) {
59
+ return {
60
+ ...ctx.request,
61
+ method: 'PUT',
62
+ url: `${ctx.service.endpointVersion}/${ctx.service.endpoint}/${entity.id}`,
63
+ data: entity,
64
+ };
65
+ }
57
66
  /** Operation for deleting a list of entities */
58
67
  async function updateBatchOp(ctx, entities) {
59
68
  const res = await ctx.client.request({
@@ -228,7 +237,7 @@ async function* listByPageV2Op(ctx, query, opts) {
228
237
  yield res;
229
238
  if (entityCount >= maxEntities)
230
239
  return;
231
- let nextPage = res.data.pagination.next;
240
+ let nextPage = res.data.pagination.next ?? undefined;
232
241
  while (nextPage !== undefined) {
233
242
  const pagedRes = await ctx.client.request({
234
243
  ...queriedRequest,
@@ -237,7 +246,7 @@ async function* listByPageV2Op(ctx, query, opts) {
237
246
  cursor: nextPage,
238
247
  },
239
248
  });
240
- nextPage = pagedRes.data.pagination.next;
249
+ nextPage = pagedRes.data.pagination.next ?? undefined;
241
250
  yield pagedRes;
242
251
  entityCount += pagedRes.data.data.length;
243
252
  if (entityCount >= maxEntities)
@@ -286,7 +295,7 @@ export function getOpMap() {
286
295
  listAll: (listAllOp),
287
296
  listByPage: (listByPageOp),
288
297
  create: (createOp),
289
- update: (updateOp),
298
+ update: (updateV1Op),
290
299
  updateBatch: (updateBatchOp),
291
300
  },
292
301
  v2: {
@@ -297,7 +306,7 @@ export function getOpMap() {
297
306
  listAll: (listAllV2Op),
298
307
  listByPage: (listByPageV2Op),
299
308
  create: (createOp),
300
- update: (updateOp),
309
+ update: (updateV2Op),
301
310
  updateBatch: (updateBatchOp),
302
311
  },
303
312
  };
package/dist/ops.test.js 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 { createSdkClient } from './client-builder.js';
3
3
  import { getOpMap } from './ops.js';
4
4
  let mockAxiosClient;
@@ -18,7 +18,7 @@ vi.mock(import('axios'), async (importOriginal) => {
18
18
  };
19
19
  });
20
20
  describe('Operations', () => {
21
- const service = {
21
+ const serviceV1 = {
22
22
  endpoint: 'settings',
23
23
  endpointVersion: 'v1',
24
24
  operations: ['get', 'list'],
@@ -26,16 +26,28 @@ describe('Operations', () => {
26
26
  promiseOp: async () => 3,
27
27
  },
28
28
  };
29
+ const serviceV2 = {
30
+ endpoint: 'logbook',
31
+ endpointVersion: 'v2',
32
+ operations: ['get', 'list'],
33
+ customOperations: {
34
+ promiseOp: async () => 3,
35
+ },
36
+ };
29
37
  const clientBuilder = createSdkClient({
30
- service,
38
+ service: serviceV1,
39
+ serviceV2,
31
40
  });
32
41
  const client = clientBuilder({ basicAuth: '' });
42
+ afterEach(() => {
43
+ vi.restoreAllMocks();
44
+ });
33
45
  test('operations returning a request config trigger a request call', async () => {
34
46
  const basicOp = getOpMap().v1.get;
35
47
  const basicOpRes = basicOp({
36
48
  client: mockAxiosClient,
37
49
  request: {},
38
- service,
50
+ service: serviceV1,
39
51
  sdkConfig: { apiKey: '' },
40
52
  }, 1);
41
53
  expect(basicOpRes).toStrictEqual(expect.objectContaining({
@@ -45,57 +57,118 @@ describe('Operations', () => {
45
57
  expect(mockAxiosClient.request).toHaveBeenCalledWith(expect.objectContaining(basicOpRes));
46
58
  });
47
59
  test('operations returning a promise are returned as is', async () => {
48
- const promiseOpRes = await service.customOperations.promiseOp();
60
+ const promiseOpRes = await serviceV1.customOperations.promiseOp();
49
61
  expect(promiseOpRes).toStrictEqual(await client.service.promiseOp());
50
62
  });
51
- describe('list op', () => {
52
- test('respects `maxResults` parameter in legacy pagination', async () => {
53
- vi.spyOn(mockAxiosClient, 'request').mockResolvedValue({ data: [] });
54
- await client.service.list({}, { maxResults: 2 }).next();
55
- expect(mockAxiosClient.request).toHaveBeenCalledWith(expect.objectContaining({
56
- url: expect.any(String),
57
- params: {
58
- limit: 2,
59
- },
60
- }));
61
- });
62
- test('automatically paginates', async () => {
63
- const pageTotal = 3;
64
- let pageCount = 0;
65
- vi.spyOn(mockAxiosClient, 'request').mockResolvedValue({
66
- headers: {
67
- 'x-limit': 1,
68
- 'x-total-count': pageTotal,
69
- // eslint-disable-next-line no-plusplus
70
- 'x-offset': pageCount++,
71
- },
72
- data: [],
63
+ describe('list', () => {
64
+ describe('v1 ops', () => {
65
+ test('respects `maxResults` parameter in pagination', async () => {
66
+ vi.spyOn(mockAxiosClient, 'request').mockResolvedValue({ data: [] });
67
+ await client.service.list({}, { maxResults: 2 }).next();
68
+ expect(mockAxiosClient.request).toHaveBeenCalledWith(expect.objectContaining({
69
+ url: expect.any(String),
70
+ params: {
71
+ limit: 2,
72
+ },
73
+ }));
74
+ });
75
+ test('automatically paginates', async () => {
76
+ const pageTotal = 3;
77
+ let pageCount = 0;
78
+ vi.spyOn(mockAxiosClient, 'request').mockResolvedValue({
79
+ headers: {
80
+ 'x-limit': 1,
81
+ 'x-total-count': pageTotal,
82
+ // eslint-disable-next-line no-plusplus
83
+ 'x-offset': pageCount++,
84
+ },
85
+ data: [],
86
+ });
87
+ for await (const res of client.service.list({})) {
88
+ res;
89
+ }
90
+ expect(mockAxiosClient.request).toHaveBeenCalledTimes(pageTotal);
91
+ });
92
+ test('stops automatic pagination after maxResults reached', async () => {
93
+ const pageLimit = 2;
94
+ const pageTotal = 6;
95
+ let pageCount = 0;
96
+ vi.spyOn(mockAxiosClient, 'request').mockResolvedValue({
97
+ headers: {
98
+ 'x-limit': pageLimit,
99
+ 'x-total-count': pageTotal,
100
+ // eslint-disable-next-line no-plusplus
101
+ 'x-offset': pageCount++,
102
+ },
103
+ data: new Array(pageLimit).fill('entity'),
104
+ });
105
+ let resultCount = 0;
106
+ for await (const res of client.service.list({}, { maxResults: 3 })) {
107
+ resultCount += 1;
108
+ res;
109
+ }
110
+ expect(resultCount).toBe(3);
111
+ expect(mockAxiosClient.request).toHaveBeenCalledTimes(2);
73
112
  });
74
- for await (const res of client.service.list({})) {
75
- res;
76
- }
77
- expect(mockAxiosClient.request).toHaveBeenCalledTimes(pageTotal);
78
113
  });
79
- test('stops automatic pagination after maxResults reached', async () => {
80
- const pageLimit = 2;
81
- const pageTotal = 6;
82
- let pageCount = 0;
83
- vi.spyOn(mockAxiosClient, 'request').mockResolvedValue({
84
- headers: {
85
- 'x-limit': pageLimit,
86
- 'x-total-count': pageTotal,
87
- // eslint-disable-next-line no-plusplus
88
- 'x-offset': pageCount++,
89
- },
90
- data: new Array(pageLimit).fill('entity'),
114
+ describe('v2 ops', () => {
115
+ test('respects `maxResults` parameter in pagination', async () => {
116
+ vi.spyOn(mockAxiosClient, 'request').mockResolvedValue({
117
+ data: { data: [], pagination: { next: null, count: 0 } },
118
+ });
119
+ await client.serviceV2.list({ userId: 0 }, { maxResults: 2 }).next();
120
+ expect(mockAxiosClient.request).toHaveBeenCalledWith(expect.objectContaining({
121
+ url: expect.any(String),
122
+ params: expect.objectContaining({
123
+ limit: 2,
124
+ }),
125
+ }));
126
+ });
127
+ test('automatically paginates', async () => {
128
+ const pageTotal = 3;
129
+ const pageLimit = 2;
130
+ let pageCount = 0;
131
+ vi.spyOn(mockAxiosClient, 'request').mockImplementation(async () => {
132
+ pageCount += 1;
133
+ return {
134
+ data: {
135
+ data: new Array(pageLimit).fill('entity'),
136
+ pagination: {
137
+ next: pageCount < pageTotal ? String(pageCount) : null,
138
+ count: pageTotal,
139
+ },
140
+ },
141
+ };
142
+ });
143
+ for await (const res of client.serviceV2.list({ userId: 0 })) {
144
+ res;
145
+ }
146
+ expect(mockAxiosClient.request).toHaveBeenCalledTimes(pageTotal);
147
+ });
148
+ test('stops automatic pagination after maxResults reached', async () => {
149
+ const pageLimit = 2;
150
+ const pageTotal = 6;
151
+ let pageCount = 0;
152
+ vi.spyOn(mockAxiosClient, 'request').mockImplementation(() => {
153
+ pageCount += pageLimit;
154
+ return Promise.resolve({
155
+ data: {
156
+ data: new Array(pageLimit).fill('entity'),
157
+ pagination: {
158
+ next: pageCount < pageTotal ? String(pageCount) : null,
159
+ count: pageTotal,
160
+ },
161
+ },
162
+ });
163
+ });
164
+ let resultCount = 0;
165
+ for await (const res of client.serviceV2.list({ userId: 0 }, { maxResults: 3 })) {
166
+ resultCount += 1;
167
+ res;
168
+ }
169
+ expect(resultCount).toBe(3);
170
+ expect(mockAxiosClient.request).toHaveBeenCalledTimes(2);
91
171
  });
92
- let resultCount = 0;
93
- for await (const res of client.service.list({}, { maxResults: 3 })) {
94
- resultCount += 1;
95
- res;
96
- }
97
- expect(resultCount).toBe(3);
98
- expect(mockAxiosClient.request).toHaveBeenCalledTimes(2);
99
172
  });
100
173
  });
101
174
  });
package/dist/service.d.ts CHANGED
@@ -7,6 +7,7 @@ import { RequirementsOf, RequestOptions } from './utils.js';
7
7
  import { ShiftSwapRequest } from './interfaces/swap-request.interface.js';
8
8
  import { ShiftDropRequest } from './interfaces/drop-request.interface.js';
9
9
  import { ToilAllowanceQueryParams } from './interfaces/query-params/index.js';
10
+ import { LogbookEntry, LogbookQueryParameters } from './interfaces/logbook.interface.js';
10
11
  export type ServiceSpecification<CustomOp extends OpDef<unknown> = OpDef<any>> = {
11
12
  /** Operations allowed and usable for the endpoint */
12
13
  operations: Operation[];
@@ -15,6 +16,7 @@ export type ServiceSpecification<CustomOp extends OpDef<unknown> = OpDef<any>> =
15
16
  * Can be used to override operations listed in {@see ServiceSpecification['operations']}
16
17
  */
17
18
  customOperations?: Record<string, CustomOp>;
19
+ subService?: Record<string, ServiceSpecification<CustomOp>>;
18
20
  } & ({
19
21
  /** URL of the endpoint */
20
22
  endpoint: keyof EndpointEntityMap['v1'];
@@ -25,6 +27,15 @@ export type ServiceSpecification<CustomOp extends OpDef<unknown> = OpDef<any>> =
25
27
  endpoint: keyof EndpointEntityMap['v2'];
26
28
  /** API version of the endpoint */
27
29
  endpointVersion: 'v2';
30
+ } | {
31
+ endpoint: string;
32
+ endpointVersion: 'v1' | 'v2';
33
+ /**
34
+ * Marks the endpoint as one not defined in the {@link EndpointEntityMap}
35
+ *
36
+ * Intended for defining customOperations
37
+ * */
38
+ custom: true;
28
39
  });
29
40
  /**
30
41
  * Map of all officially supported service specifications used to generate the
@@ -122,6 +133,22 @@ export declare const SERVICES: {
122
133
  endpointVersion: "v1";
123
134
  operations: ("get" | "delete" | "list" | "listAll" | "create" | "update")[];
124
135
  };
136
+ logbook: {
137
+ endpoint: "logbook";
138
+ endpointVersion: "v2";
139
+ operations: ("get" | "delete" | "create" | "update")[];
140
+ customOperations: {
141
+ list: (ctx: OperationContext, query: LogbookQueryParameters, opts: RequestOptions<unknown> | undefined) => AsyncGenerator<LogbookEntry, any, any>;
142
+ listAll: (ctx: OperationContext, query: LogbookQueryParameters, opts: RequestOptions<unknown> | undefined) => Promise<LogbookEntry[]>;
143
+ };
144
+ subService: {
145
+ category: {
146
+ endpoint: "logbook/categories";
147
+ endpointVersion: "v2";
148
+ operations: ("get" | "delete" | "list" | "listAll" | "create" | "update")[];
149
+ };
150
+ };
151
+ };
125
152
  pin: {
126
153
  endpoint: "pins";
127
154
  endpointVersion: "v1";
@@ -174,16 +201,16 @@ export declare const SERVICES: {
174
201
  };
175
202
  };
176
203
  terminalActive: {
177
- endpoint: "terminals";
204
+ endpoint: "terminals_active";
178
205
  endpointVersion: "v1";
179
206
  operations: ("list" | "listAll")[];
180
207
  customOperations: {
181
- launch: ({ request, service }: OperationContext, id: LaunchTerminal) => RequestConfig<void, Terminal>;
182
- ping: ({ request, service }: OperationContext, id: {
208
+ launch: ({ request, service }: OperationContext, terminal: LaunchTerminal) => RequestConfig<LaunchTerminal, Terminal>;
209
+ ping: ({ request, service }: OperationContext, terminal: {
183
210
  id: number;
184
211
  action: string;
185
212
  device: string;
186
- }) => RequestConfig<void, void>;
213
+ }) => RequestConfig<Omit<typeof terminal, "id">, void>;
187
214
  close: ({ request, service }: OperationContext, id: number) => RequestConfig<void, void>;
188
215
  };
189
216
  };
package/dist/service.js CHANGED
@@ -1,4 +1,4 @@
1
- import { listAllOp, listOp, paramsFromOptions } from './ops.js';
1
+ import { listAllOp, listAllV2Op, listOp, listV2Op, paramsFromOptions, } from './ops.js';
2
2
  /**
3
3
  * Map of all officially supported service specifications used to generate the
4
4
  * SDK client where each key is the service name and each value is the service
@@ -141,6 +141,42 @@ export const SERVICES = {
141
141
  endpointVersion: 'v1',
142
142
  operations: ['create', 'get', 'list', 'listAll', 'update', 'delete'],
143
143
  },
144
+ logbook: {
145
+ endpoint: 'logbook',
146
+ endpointVersion: 'v2',
147
+ operations: ['create', 'get', 'delete', 'update'],
148
+ customOperations: {
149
+ list: (ctx, query, opts) =>
150
+ // Maps the "userId" query parameter into the endpoint URL
151
+ listV2Op({
152
+ ...ctx,
153
+ service: {
154
+ ...ctx.service,
155
+ endpoint: `${ctx.service.endpoint}/user/${query.userId}`,
156
+ endpointVersion: 'v2',
157
+ custom: true,
158
+ },
159
+ }, { date: query.date }, opts),
160
+ listAll: (ctx, query, opts) =>
161
+ // Maps the "userId" query parameter into the endpoint URL
162
+ listAllV2Op({
163
+ ...ctx,
164
+ service: {
165
+ ...ctx.service,
166
+ endpoint: `${ctx.service.endpoint}/user/${query.userId}`,
167
+ endpointVersion: 'v2',
168
+ custom: true,
169
+ },
170
+ }, { date: query.date }, opts),
171
+ },
172
+ subService: {
173
+ category: {
174
+ endpoint: 'logbook/categories',
175
+ endpointVersion: 'v2',
176
+ operations: ['get', 'create', 'update', 'delete', 'list', 'listAll'],
177
+ },
178
+ },
179
+ },
144
180
  pin: {
145
181
  endpoint: 'pins',
146
182
  endpointVersion: 'v1',
@@ -220,19 +256,21 @@ export const SERVICES = {
220
256
  },
221
257
  },
222
258
  terminalActive: {
223
- endpoint: 'terminals',
259
+ endpoint: 'terminals_active',
224
260
  endpointVersion: 'v1',
225
261
  operations: ['list', 'listAll'],
226
262
  customOperations: {
227
- launch: ({ request, service }, id) => ({
263
+ launch: ({ request, service }, terminal) => ({
228
264
  ...request,
229
- method: 'DELETE',
230
- url: `${service.endpointVersion}/${service.endpoint}/${id}`,
265
+ method: 'POST',
266
+ url: `${service.endpointVersion}/${service.endpoint}`,
267
+ data: terminal,
231
268
  }),
232
- ping: ({ request, service }, id) => ({
269
+ ping: ({ request, service }, terminal) => ({
233
270
  ...request,
234
- method: 'DELETE',
235
- url: `${service.endpointVersion}/${service.endpoint}/${id}`,
271
+ method: 'POST',
272
+ url: `${service.endpointVersion}/${service.endpoint}/${terminal.id}`,
273
+ data: { action: terminal.action, device: terminal.device },
236
274
  }),
237
275
  close: ({ request, service }, id) => ({
238
276
  ...request,
@@ -264,6 +302,7 @@ export const SERVICES = {
264
302
  ...ctx.service,
265
303
  endpoint: `${ctx.service.endpoint}/${query.year}`,
266
304
  endpointVersion: 'v1',
305
+ custom: true,
267
306
  },
268
307
  }, { users: query.users }, opts),
269
308
  listAll: (ctx, query, opts) =>
@@ -274,6 +313,7 @@ export const SERVICES = {
274
313
  ...ctx.service,
275
314
  endpoint: `${ctx.service.endpoint}/${query.year}`,
276
315
  endpointVersion: 'v1',
316
+ custom: true,
277
317
  },
278
318
  }, { users: query.users }, opts),
279
319
  },
package/dist/utils.js CHANGED
@@ -42,7 +42,7 @@ function toSearchParams(parameters) {
42
42
  }
43
43
  function parseClientError(error) {
44
44
  const axiosErrorLocation = error.response || error.request;
45
- const apiErrorMessage = axiosErrorLocation.data?.error;
45
+ const apiErrorMessage = axiosErrorLocation.data?.message;
46
46
  let url;
47
47
  try {
48
48
  url = new URL(error.config?.url ?? '', error.config?.baseURL);