@markwharton/eh-payroll 2.3.0 → 2.4.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 CHANGED
@@ -123,7 +123,11 @@ const employees = result.data;
123
123
 
124
124
  ### `getLeaveRequests()`
125
125
 
126
- Returns leave requests with all filters applied server-side. Unlike paginated endpoints, this returns a flat array.
126
+ Returns leave requests with all filters applied server-side. The business-level endpoint (`/api/v2/business/{businessId}/leaverequest`) returns a flat array — no pagination is available.
127
+
128
+ **Leave requests are time-series data** — unlike employees and locations which remain relatively stable, leave requests grow continuously as new requests accumulate. Always use `fromDate`/`toDate` filters to bound the result set. Without date filters, the API returns the entire leave request history.
129
+
130
+ > **Note:** The Payroll API also provides a per-employee endpoint (`/api/v2/business/{businessId}/employee/{employeeId}/leaverequest`) with OData support (`$filter`, `$orderby`, `$top`, `$skip`). This client currently uses only the business-level endpoint.
127
131
 
128
132
  **`EHLeaveRequestOptions`:**
129
133
 
package/dist/client.d.ts CHANGED
@@ -32,7 +32,10 @@ export declare class EHClient {
32
32
  private readonly cacheTtl;
33
33
  private readonly retryConfig?;
34
34
  private readonly rateLimiter?;
35
+ private readonly persistRestricted;
35
36
  constructor(config: EHConfig);
37
+ /** Cache options for restricted-tier methods: skip persistent stores when persistRestricted is false. */
38
+ private get restrictedPersistOpt();
36
39
  /**
37
40
  * Route through cache if enabled, otherwise call factory directly.
38
41
  * Failed Results (ok === false) are never cached — transient errors
package/dist/client.js CHANGED
@@ -59,6 +59,11 @@ export class EHClient {
59
59
  if (rateLimitPerSecond > 0) {
60
60
  this.rateLimiter = new RateLimiter(rateLimitPerSecond);
61
61
  }
62
+ this.persistRestricted = config.persistRestricted ?? true;
63
+ }
64
+ /** Cache options for restricted-tier methods: skip persistent stores when persistRestricted is false. */
65
+ get restrictedPersistOpt() {
66
+ return this.persistRestricted ? undefined : { persist: false };
62
67
  }
63
68
  /**
64
69
  * Route through cache if enabled, otherwise call factory directly.
@@ -240,7 +245,7 @@ export class EHClient {
240
245
  return (await r.json())
241
246
  .map(item => pickFields(item, LEAVE_REQUEST_FIELDS));
242
247
  });
243
- });
248
+ }, this.restrictedPersistOpt);
244
249
  }
245
250
  // ============================================================================
246
251
  // Employees
@@ -258,7 +263,7 @@ export class EHClient {
258
263
  if (options?.includePii)
259
264
  parts.push('pii');
260
265
  const cacheKey = parts.join(':');
261
- const persistOpt = options?.includePii ? { persist: false } : undefined;
266
+ const persistOpt = (options?.includePii || !this.persistRestricted) ? { persist: false } : undefined;
262
267
  return this.cached(cacheKey, this.cacheTtl.employeesTtl, () => {
263
268
  const params = new URLSearchParams();
264
269
  if (options?.payScheduleId != null)
@@ -278,7 +283,7 @@ export class EHClient {
278
283
  async getEmployee(employeeId, options) {
279
284
  const fields = options?.includePii ? AU_EMPLOYEE_FIELDS : AU_EMPLOYEE_OPERATIONAL_FIELDS;
280
285
  const cacheKey = options?.includePii ? `employee:${employeeId}:pii` : `employee:${employeeId}`;
281
- const persistOpt = options?.includePii ? { persist: false } : undefined;
286
+ const persistOpt = (options?.includePii || !this.persistRestricted) ? { persist: false } : undefined;
282
287
  return this.cached(cacheKey, this.cacheTtl.employeesTtl, async () => {
283
288
  const url = `${this.baseUrl}/business/${this.businessId}/employee/unstructured/${employeeId}`;
284
289
  return this.fetchAndParse(url, async (r) => {
@@ -298,7 +303,7 @@ export class EHClient {
298
303
  return this.fetchAndParse(url, async (r) => {
299
304
  return await r.json();
300
305
  }, { description: `Get standard hours for employee ${employeeId}` });
301
- });
306
+ }, this.restrictedPersistOpt);
302
307
  }
303
308
  // ============================================================================
304
309
  // Locations
@@ -505,6 +510,6 @@ export class EHClient {
505
510
  return this.fetchAndParse(url, async (r) => {
506
511
  return await r.json();
507
512
  });
508
- });
513
+ }, this.restrictedPersistOpt);
509
514
  }
510
515
  }
package/dist/index.d.ts CHANGED
@@ -22,6 +22,8 @@
22
22
  export { EHClient } from './client.js';
23
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
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
+ export type { AccessTier } from './types.js';
26
+ export { METHOD_TIERS } from './types.js';
25
27
  export type { EHAuEmployee } from './employee-types.generated.js';
26
28
  export { buildBasicAuthHeader } from './utils.js';
27
29
  export { ok, err, getErrorMessage, pickFields, RateLimiter, TTLCache, MemoryCacheStore, LayeredCache } from '@markwharton/api-core';
package/dist/index.js CHANGED
@@ -23,6 +23,7 @@
23
23
  export { EHClient } from './client.js';
24
24
  // Field key constants (whitelists for pickFields)
25
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
+ export { METHOD_TIERS } from './types.js';
26
27
  // Utilities
27
28
  export { buildBasicAuthHeader } from './utils.js';
28
29
  // Re-exported from @markwharton/api-core
package/dist/types.d.ts CHANGED
@@ -50,6 +50,8 @@ export interface EHConfig extends ClientConfig {
50
50
  cache?: EHCacheConfig;
51
51
  /** Max requests per second (default: 5 per API spec). Set 0 to disable. */
52
52
  rateLimitPerSecond?: number;
53
+ /** Whether to persist restricted-tier data in persistent cache stores (default: true). Set false to keep restricted data in memory only. */
54
+ persistRestricted?: boolean;
53
55
  }
54
56
  /**
55
57
  * Employee from unstructured endpoint
@@ -370,3 +372,13 @@ export declare const AU_EMPLOYEE_OPERATIONAL_FIELDS: readonly ["id", "externalId
370
372
  export declare const AU_EMPLOYEE_PII_FIELDS: readonly ["dateOfBirth", "gender", "title", "middleName", "preferredName", "previousSurname", "emailAddress", "homePhone", "mobilePhone", "workPhone", "bankAccount1_AccountName", "bankAccount1_AccountNumber", "bankAccount1_AllocatedPercentage", "bankAccount1_BSB", "bankAccount1_FixedAmount", "bankAccount2_AccountName", "bankAccount2_AccountNumber", "bankAccount2_AllocatedPercentage", "bankAccount2_BSB", "bankAccount2_FixedAmount", "bankAccount3_AccountName", "bankAccount3_AccountNumber", "bankAccount3_AllocatedPercentage", "bankAccount3_BSB", "bankAccount3_FixedAmount", "emergencyContact1_Address", "emergencyContact1_AlternateContactNumber", "emergencyContact1_ContactNumber", "emergencyContact1_Name", "emergencyContact1_Relationship", "emergencyContact2_Address", "emergencyContact2_AlternateContactNumber", "emergencyContact2_ContactNumber", "emergencyContact2_Name", "emergencyContact2_Relationship", "postalStreetAddress", "postalAddressLine2", "postalPostCode", "postalCountry", "postalState", "postalSuburb", "postalAddressIsOverseas", "residentialStreetAddress", "residentialAddressLine2", "residentialPostCode", "residentialCountry", "residentialState", "residentialSuburb", "residentialAddressIsOverseas", "taxFileNumber", "taxCategory", "taxVariation", "claimTaxFreeThreshold", "claimMedicareLevyReduction", "medicareLevyExemption", "medicareLevyReductionDependentCount", "medicareLevyReductionSpouse", "medicareLevySurchargeWithholdingTier", "seniorsTaxOffset", "otherTaxOffset", "stslDebt", "hasWithholdingVariation", "dateTaxFileDeclarationReported", "dateTaxFileDeclarationSigned", "superFund1_AllocatedPercentage", "superFund1_EmployerNominatedFund", "superFund1_FixedAmount", "superFund1_FundName", "superFund1_MemberNumber", "superFund1_ProductCode", "superFund2_AllocatedPercentage", "superFund2_EmployerNominatedFund", "superFund2_FixedAmount", "superFund2_FundName", "superFund2_MemberNumber", "superFund2_ProductCode", "superFund3_AllocatedPercentage", "superFund3_EmployerNominatedFund", "superFund3_FixedAmount", "superFund3_FundName", "superFund3_MemberNumber", "superFund3_ProductCode", "contractorABN", "employingEntityABN", "hasApprovedWorkingHolidayVisa", "workingHolidayVisaCountry", "workingHolidayVisaStartDate"];
371
373
  /** All whitelisted fields for EHAuEmployee (operational + PII) */
372
374
  export declare const AU_EMPLOYEE_FIELDS: readonly ["id", "externalId", "firstName", "surname", "status", "startDate", "endDate", "anniversaryDate", "dateCreated", "employmentType", "jobTitle", "employmentAgreement", "employmentAgreementId", "paySchedule", "payRateTemplate", "rate", "rateUnit", "hoursPerWeek", "hoursPerDay", "primaryPayCategory", "payConditionRuleSet", "overrideTemplateRate", "automaticallyPayEmployee", "primaryLocation", "locations", "tags", "workTypes", "reportingDimensionValues", "leaveAccrualStartDateType", "leaveTemplate", "leaveYearStart", "isEnabledForTimesheets", "rosteringNotificationChoices", "paySlipNotificationType", "terminationReason", "australianResident", "awardId", "businessAwardPackage", "automaticallyApplyPublicHolidayNotWorkedEarningsLines", "closelyHeldEmployee", "closelyHeldReporting", "disableAutoProgression", "dvlPaySlipDescription", "employingEntityId", "includeInPortableLongServiceLeaveReport", "portableLongServiceLeaveId", "isExemptFromFloodLevy", "isExemptFromPayrollTax", "isSeasonalWorker", "maximumQuarterlySuperContributionsBase", "superThresholdAmount", "singleTouchPayroll", "dateOfBirth", "gender", "title", "middleName", "preferredName", "previousSurname", "emailAddress", "homePhone", "mobilePhone", "workPhone", "bankAccount1_AccountName", "bankAccount1_AccountNumber", "bankAccount1_AllocatedPercentage", "bankAccount1_BSB", "bankAccount1_FixedAmount", "bankAccount2_AccountName", "bankAccount2_AccountNumber", "bankAccount2_AllocatedPercentage", "bankAccount2_BSB", "bankAccount2_FixedAmount", "bankAccount3_AccountName", "bankAccount3_AccountNumber", "bankAccount3_AllocatedPercentage", "bankAccount3_BSB", "bankAccount3_FixedAmount", "emergencyContact1_Address", "emergencyContact1_AlternateContactNumber", "emergencyContact1_ContactNumber", "emergencyContact1_Name", "emergencyContact1_Relationship", "emergencyContact2_Address", "emergencyContact2_AlternateContactNumber", "emergencyContact2_ContactNumber", "emergencyContact2_Name", "emergencyContact2_Relationship", "postalStreetAddress", "postalAddressLine2", "postalPostCode", "postalCountry", "postalState", "postalSuburb", "postalAddressIsOverseas", "residentialStreetAddress", "residentialAddressLine2", "residentialPostCode", "residentialCountry", "residentialState", "residentialSuburb", "residentialAddressIsOverseas", "taxFileNumber", "taxCategory", "taxVariation", "claimTaxFreeThreshold", "claimMedicareLevyReduction", "medicareLevyExemption", "medicareLevyReductionDependentCount", "medicareLevyReductionSpouse", "medicareLevySurchargeWithholdingTier", "seniorsTaxOffset", "otherTaxOffset", "stslDebt", "hasWithholdingVariation", "dateTaxFileDeclarationReported", "dateTaxFileDeclarationSigned", "superFund1_AllocatedPercentage", "superFund1_EmployerNominatedFund", "superFund1_FixedAmount", "superFund1_FundName", "superFund1_MemberNumber", "superFund1_ProductCode", "superFund2_AllocatedPercentage", "superFund2_EmployerNominatedFund", "superFund2_FixedAmount", "superFund2_FundName", "superFund2_MemberNumber", "superFund2_ProductCode", "superFund3_AllocatedPercentage", "superFund3_EmployerNominatedFund", "superFund3_FixedAmount", "superFund3_FundName", "superFund3_MemberNumber", "superFund3_ProductCode", "contractorABN", "employingEntityABN", "hasApprovedWorkingHolidayVisa", "workingHolidayVisaCountry", "workingHolidayVisaStartDate"];
375
+ /** Access tier for method-level authorization */
376
+ export type AccessTier = 'standard' | 'restricted';
377
+ /**
378
+ * Access tier for each data method.
379
+ *
380
+ * Standard: operational data (locations, groups, kiosks, roster shifts, report fields).
381
+ * Restricted: employee-level data (employees, standard hours, leave requests, employee reports).
382
+ * Utility methods (validate, clear, invalidate) are not included.
383
+ */
384
+ export declare const METHOD_TIERS: Record<string, AccessTier>;
package/dist/types.js CHANGED
@@ -123,3 +123,23 @@ export const AU_EMPLOYEE_FIELDS = [
123
123
  ...AU_EMPLOYEE_OPERATIONAL_FIELDS,
124
124
  ...AU_EMPLOYEE_PII_FIELDS,
125
125
  ];
126
+ /**
127
+ * Access tier for each data method.
128
+ *
129
+ * Standard: operational data (locations, groups, kiosks, roster shifts, report fields).
130
+ * Restricted: employee-level data (employees, standard hours, leave requests, employee reports).
131
+ * Utility methods (validate, clear, invalidate) are not included.
132
+ */
133
+ export const METHOD_TIERS = {
134
+ getLocations: 'standard',
135
+ getEmployeeGroups: 'standard',
136
+ getKiosks: 'standard',
137
+ getKioskStaff: 'standard',
138
+ getRosterShifts: 'standard',
139
+ getReportFields: 'standard',
140
+ getEmployees: 'restricted',
141
+ getLeaveRequests: 'restricted',
142
+ getEmployee: 'restricted',
143
+ getStandardHours: 'restricted',
144
+ getEmployeeDetailsReport: 'restricted',
145
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markwharton/eh-payroll",
3
- "version": "2.3.0",
3
+ "version": "2.4.0",
4
4
  "description": "Employment Hero Payroll API client",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",