@markwharton/eh-payroll 2.1.2 → 2.3.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/README.md +35 -2
- package/dist/client.d.ts +16 -1
- package/dist/client.js +101 -30
- package/dist/index.d.ts +4 -4
- package/dist/index.js +2 -2
- package/dist/types.d.ts +57 -0
- package/dist/types.js +5 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -43,6 +43,14 @@ const pubResult = await client.getRosterShifts('2026-02-03', '2026-02-09', {
|
|
|
43
43
|
});
|
|
44
44
|
if (pubResult.ok) console.log(pubResult.data); // EHRosterShift[]
|
|
45
45
|
|
|
46
|
+
// Get leave requests for a date range (all filters server-side)
|
|
47
|
+
const leaveResult = await client.getLeaveRequests({
|
|
48
|
+
fromDate: '2026-01-01',
|
|
49
|
+
toDate: '2026-03-31',
|
|
50
|
+
status: 'Approved',
|
|
51
|
+
});
|
|
52
|
+
if (leaveResult.ok) console.log(leaveResult.data); // EHLeaveRequest[]
|
|
53
|
+
|
|
46
54
|
// Get business locations
|
|
47
55
|
const locResult = await client.getLocations();
|
|
48
56
|
if (locResult.ok) console.log(locResult.data); // EHLocation[]
|
|
@@ -110,15 +118,35 @@ const employees = result.data;
|
|
|
110
118
|
| `getKiosks()` | — | `Result<EHKiosk[]>` |
|
|
111
119
|
| `getKioskStaff(kioskId, options?)` | `number, EHKioskStaffOptions?` | `Result<EHKioskEmployee[]>` |
|
|
112
120
|
| `getReportFields()` | — | `Result<EHReportField[]>` |
|
|
121
|
+
| `getLeaveRequests(options?)` | `EHLeaveRequestOptions?` | `Result<EHLeaveRequest[]>` |
|
|
113
122
|
| `getEmployeeDetailsReport(options?)` | `EHEmployeeDetailsReportOptions?` | `Result<Record<string, unknown>[]>` |
|
|
114
123
|
|
|
124
|
+
### `getLeaveRequests()`
|
|
125
|
+
|
|
126
|
+
Returns leave requests with all filters applied server-side. Unlike paginated endpoints, this returns a flat array.
|
|
127
|
+
|
|
128
|
+
**`EHLeaveRequestOptions`:**
|
|
129
|
+
|
|
130
|
+
| Option | Type | Description |
|
|
131
|
+
|--------|------|-------------|
|
|
132
|
+
| `fromDate` | `string` | Start date filter (YYYY-MM-DD) |
|
|
133
|
+
| `toDate` | `string` | End date filter (YYYY-MM-DD) |
|
|
134
|
+
| `status` | `EHLeaveRequestStatus` | `'Approved'`, `'Pending'`, `'Rejected'`, or `'Cancelled'` |
|
|
135
|
+
| `employeeId` | `number` | Filter by employee ID |
|
|
136
|
+
| `leaveCategoryId` | `number` | Filter by leave category ID |
|
|
137
|
+
| `locationId` | `number` | Filter by location ID |
|
|
138
|
+
|
|
139
|
+
### `getEmployeeDetailsReport()`
|
|
140
|
+
|
|
141
|
+
Returns all employees with the requested columns in a single API call. The response is dynamic — field keys depend on `selectedColumns`. Results are cached with `employeeDetailsReportTtl` (default: 2 min).
|
|
142
|
+
|
|
115
143
|
### `getRosterShifts()`
|
|
116
144
|
|
|
117
145
|
Automatically paginates through all results (100 per page). Returns the complete set of roster shifts for the requested date range. All filter options are applied server-side, reducing the number of results and pages fetched.
|
|
118
146
|
|
|
119
147
|
### Query Parameter Casing
|
|
120
148
|
|
|
121
|
-
The [KeyPay Swagger spec](https://api.keypay.com.au/swagger-au.json) uses inconsistent query parameter casing across endpoints. Roster shifts use PascalCase (`EmployeeId`, `ShiftStatus`), while
|
|
149
|
+
The [KeyPay Swagger spec](https://api.keypay.com.au/swagger-au.json) uses inconsistent query parameter casing across endpoints. Roster shifts and leave requests use PascalCase (`EmployeeId`, `ShiftStatus`, `FromDate`), while other endpoints use camelCase (`selectedColumns`, `filter.locationId`). The library accepts camelCase options throughout and converts to PascalCase internally where needed.
|
|
122
150
|
|
|
123
151
|
## Configuration
|
|
124
152
|
|
|
@@ -131,6 +159,7 @@ const client = new EHClient({
|
|
|
131
159
|
rateLimitPerSecond: 5, // Optional: rate limit (default 5, set 0 to disable)
|
|
132
160
|
onRequest: ({ method, url, description }) => { ... }, // Optional: debug callback
|
|
133
161
|
cache: {}, // Optional: enable TTL caching (defaults below)
|
|
162
|
+
cacheInstance: cache, // Optional: custom cache backend (e.g., LayeredCache)
|
|
134
163
|
retry: { // Optional: retry on 429/503
|
|
135
164
|
maxRetries: 3,
|
|
136
165
|
initialDelayMs: 1000,
|
|
@@ -139,7 +168,7 @@ const client = new EHClient({
|
|
|
139
168
|
});
|
|
140
169
|
```
|
|
141
170
|
|
|
142
|
-
`EHConfig` extends `ClientConfig` from api-core, which provides the `baseUrl`, `onRequest`, and `
|
|
171
|
+
`EHConfig` extends `ClientConfig` from api-core, which provides the `baseUrl`, `onRequest`, `retry`, and `cacheInstance` fields. `apiKey`, `businessId`, `region`, `cache`, and `rateLimitPerSecond` are EH-specific. Pass `cacheInstance` to use a custom cache backend (e.g., `LayeredCache` with persistent stores); otherwise `cache: {}` creates an in-memory `TTLCache`. PII data (`includePii: true`) automatically skips persistent stores.
|
|
143
172
|
|
|
144
173
|
### Cache TTLs
|
|
145
174
|
|
|
@@ -150,9 +179,13 @@ const client = new EHClient({
|
|
|
150
179
|
| Employee groups | 5 min |
|
|
151
180
|
| Standard hours | 5 min |
|
|
152
181
|
| Roster shifts | 2 min |
|
|
182
|
+
| Leave requests | 2 min |
|
|
153
183
|
| Kiosks | 5 min |
|
|
154
184
|
| Kiosk staff | 1 min |
|
|
155
185
|
| Report fields | 10 min |
|
|
186
|
+
| Employee details report | 2 min |
|
|
187
|
+
|
|
188
|
+
Failed API results (`ok: false`) are never cached — transient errors won't persist for the full TTL. See the [root README Cache System section](../../README.md#cache-system) for the full cache architecture (layered stores, PII handling, request coalescing).
|
|
156
189
|
|
|
157
190
|
### Rate Limiting
|
|
158
191
|
|
package/dist/client.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @see https://api.keypay.com.au/
|
|
8
8
|
*/
|
|
9
|
-
import type { EHConfig, EHEmployeeOptions, EHSingleEmployeeOptions, EHStandardHours, EHLocation, EHEmployeeGroup, EHRosterShift, EHRosterShiftOptions, EHKiosk, EHKioskEmployee, EHKioskStaffOptions, EHReportField, EHEmployeeDetailsReportOptions } from './types.js';
|
|
9
|
+
import type { EHConfig, EHLeaveRequest, EHLeaveRequestOptions, EHEmployeeOptions, EHSingleEmployeeOptions, EHStandardHours, EHLocation, EHEmployeeGroup, EHRosterShift, EHRosterShiftOptions, EHKiosk, EHKioskEmployee, EHKioskStaffOptions, EHReportField, EHEmployeeDetailsReportOptions } from './types.js';
|
|
10
10
|
import type { EHAuEmployee } from './employee-types.generated.js';
|
|
11
11
|
import type { Result } from '@markwharton/api-core';
|
|
12
12
|
/**
|
|
@@ -35,12 +35,18 @@ export declare class EHClient {
|
|
|
35
35
|
constructor(config: EHConfig);
|
|
36
36
|
/**
|
|
37
37
|
* Route through cache if enabled, otherwise call factory directly.
|
|
38
|
+
* Failed Results (ok === false) are never cached — transient errors
|
|
39
|
+
* shouldn't persist for the full TTL.
|
|
38
40
|
*/
|
|
39
41
|
private cached;
|
|
40
42
|
/**
|
|
41
43
|
* Clear all cached API responses.
|
|
42
44
|
*/
|
|
43
45
|
clearCache(): void;
|
|
46
|
+
/**
|
|
47
|
+
* Build a URL for a business-scoped endpoint.
|
|
48
|
+
*/
|
|
49
|
+
private businessUrl;
|
|
44
50
|
/**
|
|
45
51
|
* Make an authenticated request to the EH API
|
|
46
52
|
*
|
|
@@ -68,6 +74,15 @@ export declare class EHClient {
|
|
|
68
74
|
* Validate the API key by calling GET /user
|
|
69
75
|
*/
|
|
70
76
|
validateApiKey(): Promise<Result<void>>;
|
|
77
|
+
/**
|
|
78
|
+
* Get leave requests (server-side filtering)
|
|
79
|
+
*
|
|
80
|
+
* All filter options are passed as query parameters to the API.
|
|
81
|
+
* The endpoint returns a flat array (not paginated).
|
|
82
|
+
*
|
|
83
|
+
* @see https://api.keypay.com.au/australia/reference/leave-requests/au-business-hours-leave-request--list-leave-requests.html
|
|
84
|
+
*/
|
|
85
|
+
getLeaveRequests(options?: EHLeaveRequestOptions): Promise<Result<EHLeaveRequest[]>>;
|
|
71
86
|
/**
|
|
72
87
|
* Get all employees (unstructured format)
|
|
73
88
|
*/
|
package/dist/client.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @see https://api.keypay.com.au/
|
|
8
8
|
*/
|
|
9
|
-
import { AU_EMPLOYEE_OPERATIONAL_FIELDS, AU_EMPLOYEE_FIELDS, LOCATION_FIELDS, EMPLOYEE_GROUP_FIELDS, ROSTER_SHIFT_FIELDS, KIOSK_FIELDS, KIOSK_EMPLOYEE_FIELDS, } from './types.js';
|
|
9
|
+
import { AU_EMPLOYEE_OPERATIONAL_FIELDS, AU_EMPLOYEE_FIELDS, LEAVE_REQUEST_FIELDS, LOCATION_FIELDS, EMPLOYEE_GROUP_FIELDS, ROSTER_SHIFT_FIELDS, KIOSK_FIELDS, KIOSK_EMPLOYEE_FIELDS, } from './types.js';
|
|
10
10
|
import { buildBasicAuthHeader } from './utils.js';
|
|
11
11
|
import { parseEHPayrollErrorResponse } from './errors.js';
|
|
12
12
|
import { EH_API_BASE, EH_REGION_URLS } from './constants.js';
|
|
@@ -37,11 +37,12 @@ export class EHClient {
|
|
|
37
37
|
this.baseUrl = config.baseUrl ?? (config.region ? EH_REGION_URLS[config.region] : EH_API_BASE);
|
|
38
38
|
this.onRequest = config.onRequest;
|
|
39
39
|
// Initialize cache if configured
|
|
40
|
-
if (config.cache) {
|
|
41
|
-
this.cache = new TTLCache();
|
|
40
|
+
if (config.cache || config.cacheInstance) {
|
|
41
|
+
this.cache = config.cacheInstance ?? new TTLCache();
|
|
42
42
|
}
|
|
43
43
|
this.cacheTtl = {
|
|
44
44
|
employeesTtl: config.cache?.employeesTtl ?? 300000,
|
|
45
|
+
leaveRequestsTtl: config.cache?.leaveRequestsTtl ?? 120000,
|
|
45
46
|
locationsTtl: config.cache?.locationsTtl ?? 300000,
|
|
46
47
|
groupsTtl: config.cache?.groupsTtl ?? 300000,
|
|
47
48
|
standardHoursTtl: config.cache?.standardHoursTtl ?? 300000,
|
|
@@ -49,6 +50,7 @@ export class EHClient {
|
|
|
49
50
|
kiosksTtl: config.cache?.kiosksTtl ?? 300000,
|
|
50
51
|
kioskStaffTtl: config.cache?.kioskStaffTtl ?? 60000,
|
|
51
52
|
reportFieldsTtl: config.cache?.reportFieldsTtl ?? 600000,
|
|
53
|
+
employeeDetailsReportTtl: config.cache?.employeeDetailsReportTtl ?? 120000,
|
|
52
54
|
};
|
|
53
55
|
// Initialize retry config with defaults if provided
|
|
54
56
|
this.retryConfig = resolveRetryConfig(config.retry);
|
|
@@ -60,12 +62,16 @@ export class EHClient {
|
|
|
60
62
|
}
|
|
61
63
|
/**
|
|
62
64
|
* Route through cache if enabled, otherwise call factory directly.
|
|
65
|
+
* Failed Results (ok === false) are never cached — transient errors
|
|
66
|
+
* shouldn't persist for the full TTL.
|
|
63
67
|
*/
|
|
64
|
-
async cached(key, ttlMs, factory) {
|
|
65
|
-
if (this.cache)
|
|
66
|
-
return
|
|
67
|
-
|
|
68
|
-
|
|
68
|
+
async cached(key, ttlMs, factory, options) {
|
|
69
|
+
if (!this.cache)
|
|
70
|
+
return factory();
|
|
71
|
+
return this.cache.get(key, ttlMs, factory, {
|
|
72
|
+
...options,
|
|
73
|
+
shouldCache: (data) => data.ok !== false,
|
|
74
|
+
});
|
|
69
75
|
}
|
|
70
76
|
/**
|
|
71
77
|
* Clear all cached API responses.
|
|
@@ -73,6 +79,14 @@ export class EHClient {
|
|
|
73
79
|
clearCache() {
|
|
74
80
|
this.cache?.clear();
|
|
75
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* Build a URL for a business-scoped endpoint.
|
|
84
|
+
*/
|
|
85
|
+
businessUrl(path, params) {
|
|
86
|
+
const base = `${this.baseUrl}/business/${this.businessId}/${path}`;
|
|
87
|
+
const qs = params?.toString();
|
|
88
|
+
return qs ? `${base}?${qs}` : base;
|
|
89
|
+
}
|
|
76
90
|
/**
|
|
77
91
|
* Make an authenticated request to the EH API
|
|
78
92
|
*
|
|
@@ -182,6 +196,53 @@ export class EHClient {
|
|
|
182
196
|
}
|
|
183
197
|
}
|
|
184
198
|
// ============================================================================
|
|
199
|
+
// Leave Requests
|
|
200
|
+
// ============================================================================
|
|
201
|
+
/**
|
|
202
|
+
* Get leave requests (server-side filtering)
|
|
203
|
+
*
|
|
204
|
+
* All filter options are passed as query parameters to the API.
|
|
205
|
+
* The endpoint returns a flat array (not paginated).
|
|
206
|
+
*
|
|
207
|
+
* @see https://api.keypay.com.au/australia/reference/leave-requests/au-business-hours-leave-request--list-leave-requests.html
|
|
208
|
+
*/
|
|
209
|
+
async getLeaveRequests(options) {
|
|
210
|
+
const parts = ['leaverequests'];
|
|
211
|
+
if (options?.fromDate)
|
|
212
|
+
parts.push(`from:${options.fromDate}`);
|
|
213
|
+
if (options?.toDate)
|
|
214
|
+
parts.push(`to:${options.toDate}`);
|
|
215
|
+
if (options?.status)
|
|
216
|
+
parts.push(`s:${options.status}`);
|
|
217
|
+
if (options?.employeeId != null)
|
|
218
|
+
parts.push(`eid:${options.employeeId}`);
|
|
219
|
+
if (options?.leaveCategoryId != null)
|
|
220
|
+
parts.push(`lcid:${options.leaveCategoryId}`);
|
|
221
|
+
if (options?.locationId != null)
|
|
222
|
+
parts.push(`lid:${options.locationId}`);
|
|
223
|
+
const cacheKey = parts.join(':');
|
|
224
|
+
return this.cached(cacheKey, this.cacheTtl.leaveRequestsTtl, async () => {
|
|
225
|
+
const params = new URLSearchParams();
|
|
226
|
+
if (options?.fromDate)
|
|
227
|
+
params.set('FromDate', options.fromDate);
|
|
228
|
+
if (options?.toDate)
|
|
229
|
+
params.set('ToDate', options.toDate);
|
|
230
|
+
if (options?.status)
|
|
231
|
+
params.set('Status', options.status);
|
|
232
|
+
if (options?.employeeId != null)
|
|
233
|
+
params.set('EmployeeId', String(options.employeeId));
|
|
234
|
+
if (options?.leaveCategoryId != null)
|
|
235
|
+
params.set('LeaveCategoryId', String(options.leaveCategoryId));
|
|
236
|
+
if (options?.locationId != null)
|
|
237
|
+
params.set('LocationId', String(options.locationId));
|
|
238
|
+
const url = this.businessUrl('leaverequest', params);
|
|
239
|
+
return this.fetchAndParse(url, async (r) => {
|
|
240
|
+
return (await r.json())
|
|
241
|
+
.map(item => pickFields(item, LEAVE_REQUEST_FIELDS));
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
// ============================================================================
|
|
185
246
|
// Employees
|
|
186
247
|
// ============================================================================
|
|
187
248
|
/**
|
|
@@ -197,6 +258,7 @@ export class EHClient {
|
|
|
197
258
|
if (options?.includePii)
|
|
198
259
|
parts.push('pii');
|
|
199
260
|
const cacheKey = parts.join(':');
|
|
261
|
+
const persistOpt = options?.includePii ? { persist: false } : undefined;
|
|
200
262
|
return this.cached(cacheKey, this.cacheTtl.employeesTtl, () => {
|
|
201
263
|
const params = new URLSearchParams();
|
|
202
264
|
if (options?.payScheduleId != null)
|
|
@@ -208,7 +270,7 @@ export class EHClient {
|
|
|
208
270
|
params.set('$skip', String(skip));
|
|
209
271
|
return `${this.baseUrl}/business/${this.businessId}/employee/unstructured?${params}`;
|
|
210
272
|
}, fields);
|
|
211
|
-
});
|
|
273
|
+
}, persistOpt);
|
|
212
274
|
}
|
|
213
275
|
/**
|
|
214
276
|
* Get a single employee by ID
|
|
@@ -216,12 +278,13 @@ export class EHClient {
|
|
|
216
278
|
async getEmployee(employeeId, options) {
|
|
217
279
|
const fields = options?.includePii ? AU_EMPLOYEE_FIELDS : AU_EMPLOYEE_OPERATIONAL_FIELDS;
|
|
218
280
|
const cacheKey = options?.includePii ? `employee:${employeeId}:pii` : `employee:${employeeId}`;
|
|
281
|
+
const persistOpt = options?.includePii ? { persist: false } : undefined;
|
|
219
282
|
return this.cached(cacheKey, this.cacheTtl.employeesTtl, async () => {
|
|
220
283
|
const url = `${this.baseUrl}/business/${this.businessId}/employee/unstructured/${employeeId}`;
|
|
221
284
|
return this.fetchAndParse(url, async (r) => {
|
|
222
285
|
return pickFields(await r.json(), fields);
|
|
223
286
|
});
|
|
224
|
-
});
|
|
287
|
+
}, persistOpt);
|
|
225
288
|
}
|
|
226
289
|
// ============================================================================
|
|
227
290
|
// Standard Hours
|
|
@@ -380,10 +443,7 @@ export class EHClient {
|
|
|
380
443
|
if (options?.restrictCurrentShiftsToCurrentKioskLocation) {
|
|
381
444
|
params.set('restrictCurrentShiftsToCurrentKioskLocation', 'true');
|
|
382
445
|
}
|
|
383
|
-
const
|
|
384
|
-
const url = queryString
|
|
385
|
-
? `${this.baseUrl}/business/${this.businessId}/kiosk/${kioskId}/staff?${queryString}`
|
|
386
|
-
: `${this.baseUrl}/business/${this.businessId}/kiosk/${kioskId}/staff`;
|
|
446
|
+
const url = this.businessUrl(`kiosk/${kioskId}/staff`, params);
|
|
387
447
|
return this.fetchAndParse(url, async (r) => {
|
|
388
448
|
return (await r.json())
|
|
389
449
|
.map(item => pickFields(item, KIOSK_EMPLOYEE_FIELDS));
|
|
@@ -414,26 +474,37 @@ export class EHClient {
|
|
|
414
474
|
* The response is dynamic (JObject[]) — field keys depend on selectedColumns.
|
|
415
475
|
*/
|
|
416
476
|
async getEmployeeDetailsReport(options) {
|
|
417
|
-
const
|
|
418
|
-
if (options?.selectedColumns)
|
|
419
|
-
|
|
420
|
-
params.append('selectedColumns', col);
|
|
421
|
-
}
|
|
422
|
-
}
|
|
477
|
+
const parts = ['report:employeedetails'];
|
|
478
|
+
if (options?.selectedColumns?.length)
|
|
479
|
+
parts.push(`cols:${options.selectedColumns.join(',')}`);
|
|
423
480
|
if (options?.locationId != null)
|
|
424
|
-
|
|
481
|
+
parts.push(`loc:${options.locationId}`);
|
|
425
482
|
if (options?.employingEntityId != null)
|
|
426
|
-
|
|
483
|
+
parts.push(`ee:${options.employingEntityId}`);
|
|
427
484
|
if (options?.includeActive != null)
|
|
428
|
-
|
|
485
|
+
parts.push(`a:${options.includeActive}`);
|
|
429
486
|
if (options?.includeInactive != null)
|
|
430
|
-
|
|
431
|
-
const
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
487
|
+
parts.push(`i:${options.includeInactive}`);
|
|
488
|
+
const cacheKey = parts.join(':');
|
|
489
|
+
return this.cached(cacheKey, this.cacheTtl.employeeDetailsReportTtl, async () => {
|
|
490
|
+
const params = new URLSearchParams();
|
|
491
|
+
if (options?.selectedColumns) {
|
|
492
|
+
for (const col of options.selectedColumns) {
|
|
493
|
+
params.append('selectedColumns', col);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
if (options?.locationId != null)
|
|
497
|
+
params.set('locationId', String(options.locationId));
|
|
498
|
+
if (options?.employingEntityId != null)
|
|
499
|
+
params.set('employingEntityId', String(options.employingEntityId));
|
|
500
|
+
if (options?.includeActive != null)
|
|
501
|
+
params.set('includeActive', String(options.includeActive));
|
|
502
|
+
if (options?.includeInactive != null)
|
|
503
|
+
params.set('includeInactive', String(options.includeInactive));
|
|
504
|
+
const url = this.businessUrl('report/employeedetails', params);
|
|
505
|
+
return this.fetchAndParse(url, async (r) => {
|
|
506
|
+
return await r.json();
|
|
507
|
+
});
|
|
437
508
|
});
|
|
438
509
|
}
|
|
439
510
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -20,12 +20,12 @@
|
|
|
20
20
|
* ```
|
|
21
21
|
*/
|
|
22
22
|
export { EHClient } from './client.js';
|
|
23
|
-
export type { EHConfig, EHCacheConfig, EHRetryConfig, EHEmployee, EHEmployeeOptions, EHSingleEmployeeOptions, EHStandardHours, EHLocation, EHEmployeeGroup, EHRosterShift, EHRosterShiftOptions, EHAttendanceStatus, EHKiosk, EHKioskEmployee, EHKioskStaffOptions, EHReportField, EHEmployeeDetailsReportOptions, } from './types.js';
|
|
24
|
-
export { AU_EMPLOYEE_OPERATIONAL_FIELDS, AU_EMPLOYEE_PII_FIELDS, AU_EMPLOYEE_FIELDS, LOCATION_FIELDS, EMPLOYEE_GROUP_FIELDS, ROSTER_SHIFT_FIELDS, KIOSK_FIELDS, KIOSK_EMPLOYEE_FIELDS, } from './types.js';
|
|
23
|
+
export type { EHConfig, EHCacheConfig, EHRetryConfig, EHLeaveRequest, EHLeaveRequestOptions, EHLeaveRequestStatus, EHEmployee, EHEmployeeOptions, EHSingleEmployeeOptions, EHStandardHours, EHLocation, EHEmployeeGroup, EHRosterShift, EHRosterShiftOptions, EHAttendanceStatus, EHKiosk, EHKioskEmployee, EHKioskStaffOptions, EHReportField, EHEmployeeDetailsReportOptions, } from './types.js';
|
|
24
|
+
export { AU_EMPLOYEE_OPERATIONAL_FIELDS, AU_EMPLOYEE_PII_FIELDS, AU_EMPLOYEE_FIELDS, LEAVE_REQUEST_FIELDS, LOCATION_FIELDS, EMPLOYEE_GROUP_FIELDS, ROSTER_SHIFT_FIELDS, KIOSK_FIELDS, KIOSK_EMPLOYEE_FIELDS, } from './types.js';
|
|
25
25
|
export type { EHAuEmployee } from './employee-types.generated.js';
|
|
26
26
|
export { buildBasicAuthHeader } from './utils.js';
|
|
27
|
-
export { ok, err, getErrorMessage, pickFields, RateLimiter } from '@markwharton/api-core';
|
|
28
|
-
export type { Result, RetryConfig, OnRequestCallback, ClientConfig } from '@markwharton/api-core';
|
|
27
|
+
export { ok, err, getErrorMessage, pickFields, RateLimiter, TTLCache, MemoryCacheStore, LayeredCache } from '@markwharton/api-core';
|
|
28
|
+
export type { Result, RetryConfig, OnRequestCallback, ClientConfig, Cache, CacheStore, CacheGetOptions } from '@markwharton/api-core';
|
|
29
29
|
export { EH_API_BASE, EH_REGION_URLS } from './constants.js';
|
|
30
30
|
export type { EHRegion } from './constants.js';
|
|
31
31
|
export { EHPayrollError, parseEHPayrollErrorResponse } from './errors.js';
|
package/dist/index.js
CHANGED
|
@@ -22,11 +22,11 @@
|
|
|
22
22
|
// Main client
|
|
23
23
|
export { EHClient } from './client.js';
|
|
24
24
|
// Field key constants (whitelists for pickFields)
|
|
25
|
-
export { AU_EMPLOYEE_OPERATIONAL_FIELDS, AU_EMPLOYEE_PII_FIELDS, AU_EMPLOYEE_FIELDS, LOCATION_FIELDS, EMPLOYEE_GROUP_FIELDS, ROSTER_SHIFT_FIELDS, KIOSK_FIELDS, KIOSK_EMPLOYEE_FIELDS, } from './types.js';
|
|
25
|
+
export { AU_EMPLOYEE_OPERATIONAL_FIELDS, AU_EMPLOYEE_PII_FIELDS, AU_EMPLOYEE_FIELDS, LEAVE_REQUEST_FIELDS, LOCATION_FIELDS, EMPLOYEE_GROUP_FIELDS, ROSTER_SHIFT_FIELDS, KIOSK_FIELDS, KIOSK_EMPLOYEE_FIELDS, } from './types.js';
|
|
26
26
|
// Utilities
|
|
27
27
|
export { buildBasicAuthHeader } from './utils.js';
|
|
28
28
|
// Re-exported from @markwharton/api-core
|
|
29
|
-
export { ok, err, getErrorMessage, pickFields, RateLimiter } from '@markwharton/api-core';
|
|
29
|
+
export { ok, err, getErrorMessage, pickFields, RateLimiter, TTLCache, MemoryCacheStore, LayeredCache } from '@markwharton/api-core';
|
|
30
30
|
// Constants
|
|
31
31
|
export { EH_API_BASE, EH_REGION_URLS } from './constants.js';
|
|
32
32
|
// Errors
|
package/dist/types.d.ts
CHANGED
|
@@ -15,6 +15,8 @@ import type { RetryConfig, ClientConfig } from '@markwharton/api-core';
|
|
|
15
15
|
export interface EHCacheConfig {
|
|
16
16
|
/** TTL for employee list (default: 300000 = 5 min) */
|
|
17
17
|
employeesTtl?: number;
|
|
18
|
+
/** TTL for leave requests (default: 120000 = 2 min) */
|
|
19
|
+
leaveRequestsTtl?: number;
|
|
18
20
|
/** TTL for locations (default: 300000 = 5 min) */
|
|
19
21
|
locationsTtl?: number;
|
|
20
22
|
/** TTL for employee groups (default: 300000 = 5 min) */
|
|
@@ -29,6 +31,8 @@ export interface EHCacheConfig {
|
|
|
29
31
|
kioskStaffTtl?: number;
|
|
30
32
|
/** TTL for report fields (default: 600000 = 10 min) */
|
|
31
33
|
reportFieldsTtl?: number;
|
|
34
|
+
/** TTL for employee details report (default: 120000 = 2 min) */
|
|
35
|
+
employeeDetailsReportTtl?: number;
|
|
32
36
|
}
|
|
33
37
|
/** @deprecated Use `RetryConfig` from `@markwharton/api-core` directly. */
|
|
34
38
|
export type EHRetryConfig = RetryConfig;
|
|
@@ -172,6 +176,57 @@ export interface EHKioskEmployee {
|
|
|
172
176
|
/** Last recorded time in UTC */
|
|
173
177
|
recordedTimeUtc: string | null;
|
|
174
178
|
}
|
|
179
|
+
/**
|
|
180
|
+
* Leave request from the Payroll API
|
|
181
|
+
*
|
|
182
|
+
* From GET /business/{id}/leaverequest
|
|
183
|
+
* Field whitelist from Swagger HourLeaveRequestResponseModel.
|
|
184
|
+
*/
|
|
185
|
+
export interface EHLeaveRequest {
|
|
186
|
+
/** Leave request ID */
|
|
187
|
+
id: number;
|
|
188
|
+
/** Employee ID */
|
|
189
|
+
employeeId: number;
|
|
190
|
+
/** Leave category ID */
|
|
191
|
+
leaveCategoryId: number;
|
|
192
|
+
/** Employee display name */
|
|
193
|
+
employee: string;
|
|
194
|
+
/** Leave category name */
|
|
195
|
+
leaveCategory: string;
|
|
196
|
+
/** Start date (ISO 8601 datetime) */
|
|
197
|
+
fromDate: string;
|
|
198
|
+
/** End date (ISO 8601 datetime) */
|
|
199
|
+
toDate: string;
|
|
200
|
+
/** Total hours requested */
|
|
201
|
+
totalHours: number;
|
|
202
|
+
/** Hours actually applied */
|
|
203
|
+
hoursApplied: number;
|
|
204
|
+
/** Notes on the leave request */
|
|
205
|
+
notes: string | null;
|
|
206
|
+
/** Status: Approved, Pending, Rejected, Cancelled */
|
|
207
|
+
status: string;
|
|
208
|
+
}
|
|
209
|
+
/** Leave request status values */
|
|
210
|
+
export type EHLeaveRequestStatus = 'Approved' | 'Pending' | 'Rejected' | 'Cancelled';
|
|
211
|
+
/**
|
|
212
|
+
* Options for getLeaveRequests
|
|
213
|
+
*
|
|
214
|
+
* All filters are passed server-side to the API.
|
|
215
|
+
*/
|
|
216
|
+
export interface EHLeaveRequestOptions {
|
|
217
|
+
/** Filter by start date (ISO 8601 date-time → API FromDate) */
|
|
218
|
+
fromDate?: string;
|
|
219
|
+
/** Filter by end date (ISO 8601 date-time → API ToDate) */
|
|
220
|
+
toDate?: string;
|
|
221
|
+
/** Filter by status (→ API Status) */
|
|
222
|
+
status?: EHLeaveRequestStatus;
|
|
223
|
+
/** Filter by employee ID (→ API EmployeeId) */
|
|
224
|
+
employeeId?: number;
|
|
225
|
+
/** Filter by leave category ID (→ API LeaveCategoryId) */
|
|
226
|
+
leaveCategoryId?: number;
|
|
227
|
+
/** Filter by location ID (→ API LocationId) */
|
|
228
|
+
locationId?: number;
|
|
229
|
+
}
|
|
175
230
|
/**
|
|
176
231
|
* Options for getEmployees
|
|
177
232
|
*/
|
|
@@ -291,6 +346,8 @@ export interface EHEmployeeDetailsReportOptions {
|
|
|
291
346
|
/** Include inactive employees (default: false) */
|
|
292
347
|
includeInactive?: boolean;
|
|
293
348
|
}
|
|
349
|
+
/** Whitelisted fields for EHLeaveRequest */
|
|
350
|
+
export declare const LEAVE_REQUEST_FIELDS: readonly ["id", "employeeId", "leaveCategoryId", "employee", "leaveCategory", "fromDate", "toDate", "totalHours", "hoursApplied", "notes", "status"];
|
|
294
351
|
/** Whitelisted fields for EHLocation */
|
|
295
352
|
export declare const LOCATION_FIELDS: readonly ["id", "parentId", "name", "externalId", "source", "fullyQualifiedName", "isGlobal", "state", "country"];
|
|
296
353
|
/** Whitelisted fields for EHKiosk */
|
package/dist/types.js
CHANGED
|
@@ -7,6 +7,11 @@
|
|
|
7
7
|
// ============================================================================
|
|
8
8
|
// Field Key Constants (whitelists for pickFields)
|
|
9
9
|
// ============================================================================
|
|
10
|
+
/** Whitelisted fields for EHLeaveRequest */
|
|
11
|
+
export const LEAVE_REQUEST_FIELDS = [
|
|
12
|
+
'id', 'employeeId', 'leaveCategoryId', 'employee', 'leaveCategory',
|
|
13
|
+
'fromDate', 'toDate', 'totalHours', 'hoursApplied', 'notes', 'status',
|
|
14
|
+
];
|
|
10
15
|
/** Whitelisted fields for EHLocation */
|
|
11
16
|
export const LOCATION_FIELDS = [
|
|
12
17
|
'id', 'parentId', 'name', 'externalId', 'source',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markwharton/eh-payroll",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "Employment Hero Payroll API client",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"clean": "rm -rf dist"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@markwharton/api-core": "^1.
|
|
19
|
+
"@markwharton/api-core": "^1.3.0"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"@types/node": "^20.10.0",
|