@brownandroot/api 1.2.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cache.d.ts CHANGED
@@ -97,46 +97,34 @@ export interface JobtypejobstepFilters {
97
97
  /** Case-insensitive partial match on description, jobType, or jobStep */
98
98
  q?: string;
99
99
  }
100
- export declare function getEmployees(filters?: EmployeeFilters): Promise<Employee[]>;
101
- export declare function getEmployeesDropdown(filters?: EmployeeFilters): Promise<DropdownOption[]>;
102
- /** Single employee by ID — always fetches fresh (no IndexedDB). */
103
- export declare function getEmployee(employeeId: string): Promise<Employee>;
100
+ declare function getEmployees(filters?: EmployeeFilters): Promise<Employee[]>;
101
+ declare function getEmployeesDropdown(filters?: EmployeeFilters): Promise<DropdownOption[]>;
104
102
  /** Single employee by ID including compensation fields — always fetches fresh (no IndexedDB). */
105
- export declare function getEmployeePrivileged(employeeId: string): Promise<EmployeePrivileged>;
103
+ declare function getEmployeePrivileged(employeeId: string): Promise<EmployeePrivileged>;
106
104
  /** Full supervisor chain above an employee — always fetches fresh. */
107
- export declare function getSupervisorChain(employeeId: string): Promise<Employee[]>;
105
+ declare function getSupervisorChain(employeeId: string): Promise<Employee[]>;
108
106
  /** Look up JDE number and employee from email — always fetches fresh. */
109
- export declare function getJdeFromEmail(email: string): Promise<{
107
+ declare function getJdeFromEmail(email: string): Promise<{
110
108
  jde: string | null;
111
109
  employee: Employee | null;
112
110
  }>;
113
111
  /** Verify employee identity — always fetches fresh. */
114
- export declare function verifyIdentity(inputs: {
112
+ declare function verifyIdentity(inputs: {
115
113
  first3FirstName: string;
116
114
  first3LastName: string;
117
115
  dob: string;
118
116
  ssn4: string;
119
117
  }): Promise<Employee | null>;
120
- export declare function getWorkorders(filters?: WorkorderFilters): Promise<Workorder[]>;
121
- export declare function getWorkordersDropdown(filters?: WorkorderFilters): Promise<DropdownOption[]>;
122
- /** Single workorder by ID — always fetches fresh (no IndexedDB). */
123
- export declare function getWorkorder(id: string): Promise<Workorder>;
124
- export declare function getCostcodes(filters?: CostcodeFilters): Promise<Costcode[]>;
125
- export declare function getCostcodesDropdown(filters?: CostcodeFilters): Promise<DropdownOption[]>;
126
- /** Single cost code by ID — always fetches fresh (no IndexedDB). */
127
- export declare function getCostcode(id: string): Promise<Costcode>;
128
- export declare function getPaytypes(filters?: PaytypeFilters): Promise<Paytype[]>;
129
- export declare function getPaytypesDropdown(filters?: PaytypeFilters): Promise<PaytypeDropdownOption[]>;
130
- /** Single pay type by ID — always fetches fresh (no IndexedDB). */
131
- export declare function getPaytype(id: string): Promise<Paytype>;
132
- export declare function getBusinessUnits(filters?: BusinessUnitFilters): Promise<BusinessUnit[]>;
133
- export declare function getBusinessUnitsDropdown(filters?: BusinessUnitFilters): Promise<DropdownOption[]>;
134
- /** Single business unit by ID — always fetches fresh (no IndexedDB). */
135
- export declare function getBusinessUnit(id: string): Promise<BusinessUnit>;
136
- export declare function getJobtypejobsteps(filters?: JobtypejobstepFilters): Promise<Jobtypejobstep[]>;
137
- export declare function getJobtypejobstepsDropdown(filters?: JobtypejobstepFilters): Promise<DropdownOption[]>;
138
- /** Single job type/job step by ID — always fetches fresh (no IndexedDB). */
139
- export declare function getJobtypejobstep(id: string): Promise<Jobtypejobstep>;
118
+ declare function getWorkorders(filters?: WorkorderFilters): Promise<Workorder[]>;
119
+ declare function getWorkordersDropdown(filters?: WorkorderFilters): Promise<DropdownOption[]>;
120
+ declare function getCostcodes(filters?: CostcodeFilters): Promise<Costcode[]>;
121
+ declare function getCostcodesDropdown(filters?: CostcodeFilters): Promise<DropdownOption[]>;
122
+ declare function getPaytypes(filters?: PaytypeFilters): Promise<Paytype[]>;
123
+ declare function getPaytypesDropdown(filters?: PaytypeFilters): Promise<PaytypeDropdownOption[]>;
124
+ declare function getBusinessUnits(filters?: BusinessUnitFilters): Promise<BusinessUnit[]>;
125
+ declare function getBusinessUnitsDropdown(filters?: BusinessUnitFilters): Promise<DropdownOption[]>;
126
+ declare function getJobtypejobsteps(filters?: JobtypejobstepFilters): Promise<Jobtypejobstep[]>;
127
+ declare function getJobtypejobstepsDropdown(filters?: JobtypejobstepFilters): Promise<DropdownOption[]>;
140
128
  /**
141
129
  * Clear the IndexedDB cache for a specific entity, or all entities.
142
130
  *
@@ -150,3 +138,38 @@ export declare function getJobtypejobstep(id: string): Promise<Jobtypejobstep>;
150
138
  * clearCache() // clear everything
151
139
  */
152
140
  export declare function clearCache(entity?: IdbStore): void;
141
+ export declare const employees: {
142
+ getAll: typeof getEmployees;
143
+ dropdown: typeof getEmployeesDropdown;
144
+ get: (id: string) => Promise<Employee | null>;
145
+ getPrivileged: typeof getEmployeePrivileged;
146
+ getSupervisorChain: typeof getSupervisorChain;
147
+ getJdeFromEmail: typeof getJdeFromEmail;
148
+ verifyIdentity: typeof verifyIdentity;
149
+ };
150
+ export declare const workorders: {
151
+ getAll: typeof getWorkorders;
152
+ dropdown: typeof getWorkordersDropdown;
153
+ get: (id: string) => Promise<Workorder | null>;
154
+ };
155
+ export declare const costcodes: {
156
+ getAll: typeof getCostcodes;
157
+ dropdown: typeof getCostcodesDropdown;
158
+ get: (id: string) => Promise<Costcode | null>;
159
+ };
160
+ export declare const paytypes: {
161
+ getAll: typeof getPaytypes;
162
+ dropdown: typeof getPaytypesDropdown;
163
+ get: (id: string) => Promise<Paytype | null>;
164
+ };
165
+ export declare const businessUnits: {
166
+ getAll: typeof getBusinessUnits;
167
+ dropdown: typeof getBusinessUnitsDropdown;
168
+ get: (id: string) => Promise<BusinessUnit | null>;
169
+ };
170
+ export declare const jobtypejobsteps: {
171
+ getAll: typeof getJobtypejobsteps;
172
+ dropdown: typeof getJobtypejobstepsDropdown;
173
+ get: (id: string) => Promise<Jobtypejobstep | null>;
174
+ };
175
+ export {};
package/dist/cache.js CHANGED
@@ -9,18 +9,36 @@
9
9
  */
10
10
  import { idbGet, idbSet, idbClear } from './idb.js';
11
11
  // Remote functions — called as HTTP on the client, directly on the server (SSR)
12
- import { getEmployees as _getEmployees, getEmployee as _getEmployee, getEmployeePrivileged as _getEmployeePrivileged, getJdeFromEmail as _getJdeFromEmail, getSupervisorChain as _getSupervisorChain, verifyIdentity as _verifyIdentity, } from './employees.remote.js';
13
- import { getBusinessUnits as _getBusinessUnits, getBusinessUnit as _getBusinessUnit } from './businessUnits.remote.js';
14
- import { getCostcodes as _getCostcodes, getCostcode as _getCostcode } from './costcodes.remote.js';
15
- import { getPaytypes as _getPaytypes, getPaytype as _getPaytype } from './paytypes.remote.js';
16
- import { getWorkorders as _getWorkorders, getWorkorder as _getWorkorder } from './workorders.remote.js';
17
- import { getJobtypejobsteps as _getJobtypejobsteps, getJobtypejobstep as _getJobtypejobstep, } from './jobtypejobsteps.remote.js';
12
+ import { employees as remoteEmployees } from './employees.remote.js';
13
+ import { businessUnits as remoteBusinessUnits } from './businessUnits.remote.js';
14
+ import { costcodes as remoteCostcodes } from './costcodes.remote.js';
15
+ import { paytypes as remotePaytypes } from './paytypes.remote.js';
16
+ import { workorders as remoteWorkorders } from './workorders.remote.js';
17
+ import { jobtypejobsteps as remoteJobtypejobsteps } from './jobtypejobsteps.remote.js';
18
18
  // ---------------------------------------------------------------------------
19
19
  // Internal: stale-while-revalidate fetch helpers
20
20
  // ---------------------------------------------------------------------------
21
21
  /** How long cached data is considered fresh before a background refresh is triggered. */
22
22
  const CACHE_TTL_MS = 4 * 60 * 60 * 1000; // 4 hours
23
+ /** Server-side in-memory cache TTL for SSR/BFF usage. */
24
+ const SERVER_CACHE_TTL_MS = 2 * 60 * 1000; // 2 minutes
25
+ const serverCache = new Map();
26
+ function logReadFailure(operation, error) {
27
+ if (typeof window !== 'undefined')
28
+ return;
29
+ const detail = error instanceof Error ? { name: error.name, message: error.message } : { error };
30
+ console.error(`[APIHubReadFailOpen] ${operation}`, detail);
31
+ }
23
32
  async function loadCached(store, fetcher) {
33
+ if (typeof window === 'undefined') {
34
+ const cached = serverCache.get(store);
35
+ if (cached && Date.now() - cached.fetchedAt < SERVER_CACHE_TTL_MS) {
36
+ return cached.data;
37
+ }
38
+ const data = await fetcher();
39
+ serverCache.set(store, { data, fetchedAt: Date.now() });
40
+ return data;
41
+ }
24
42
  const cached = await idbGet(store, 'all');
25
43
  if (cached) {
26
44
  // Only refresh in the background if the cached data is older than the TTL
@@ -167,7 +185,7 @@ async function applyCostcodeFilters(data, f) {
167
185
  // Resolve payTypeCode → objectAccount
168
186
  let payTypeObjectAccount;
169
187
  if (f.payTypeCode !== undefined) {
170
- const allPaytypes = await loadCached('paytypes', () => _getPaytypes());
188
+ const allPaytypes = await loadCached('paytypes', () => remotePaytypes.getAll());
171
189
  payTypeObjectAccount = allPaytypes.find((p) => p.id === f.payTypeCode)?.objectAccount;
172
190
  }
173
191
  return data.filter((c) => {
@@ -195,57 +213,102 @@ async function applyCostcodeFilters(data, f) {
195
213
  // ---------------------------------------------------------------------------
196
214
  // Public API — Employees
197
215
  // ---------------------------------------------------------------------------
198
- export async function getEmployees(filters) {
199
- const all = await loadCached('employees', () => _getEmployees());
216
+ async function getEmployees(filters) {
217
+ let all;
218
+ try {
219
+ all = await loadCached('employees', () => remoteEmployees.getAll());
220
+ }
221
+ catch (error) {
222
+ logReadFailure('employees.getAll', error);
223
+ return [];
224
+ }
200
225
  return applyEmployeeFilters(all, filters);
201
226
  }
202
- export async function getEmployeesDropdown(filters) {
227
+ async function getEmployeesDropdown(filters) {
203
228
  const results = await getEmployees(filters);
204
229
  return results.map((e) => ({ value: e.employeeId, label: e.name ?? e.employeeId }));
205
230
  }
206
231
  /** Single employee by ID — always fetches fresh (no IndexedDB). */
207
- export async function getEmployee(employeeId) {
208
- return _getEmployee(employeeId);
232
+ async function getEmployee(employeeId) {
233
+ try {
234
+ return await remoteEmployees.get(employeeId);
235
+ }
236
+ catch (error) {
237
+ logReadFailure('employees.get', error);
238
+ return null;
239
+ }
209
240
  }
210
241
  /** Single employee by ID including compensation fields — always fetches fresh (no IndexedDB). */
211
- export async function getEmployeePrivileged(employeeId) {
212
- return _getEmployeePrivileged(employeeId);
242
+ async function getEmployeePrivileged(employeeId) {
243
+ return remoteEmployees.getPrivileged(employeeId);
213
244
  }
214
245
  /** Full supervisor chain above an employee — always fetches fresh. */
215
- export async function getSupervisorChain(employeeId) {
216
- return _getSupervisorChain(employeeId);
246
+ async function getSupervisorChain(employeeId) {
247
+ try {
248
+ return await remoteEmployees.getSupervisorChain(employeeId);
249
+ }
250
+ catch (error) {
251
+ logReadFailure('employees.getSupervisorChain', error);
252
+ return [];
253
+ }
217
254
  }
218
255
  /** Look up JDE number and employee from email — always fetches fresh. */
219
- export async function getJdeFromEmail(email) {
220
- return _getJdeFromEmail(email);
256
+ async function getJdeFromEmail(email) {
257
+ try {
258
+ return await remoteEmployees.getJdeFromEmail(email);
259
+ }
260
+ catch (error) {
261
+ logReadFailure('employees.getJdeFromEmail', error);
262
+ return { jde: null, employee: null };
263
+ }
221
264
  }
222
265
  /** Verify employee identity — always fetches fresh. */
223
- export async function verifyIdentity(inputs) {
224
- return _verifyIdentity(inputs);
266
+ async function verifyIdentity(inputs) {
267
+ return remoteEmployees.verifyIdentity(inputs);
225
268
  }
226
269
  // ---------------------------------------------------------------------------
227
270
  // Public API — Workorders
228
271
  // ---------------------------------------------------------------------------
229
- export async function getWorkorders(filters) {
230
- const all = await loadCached('workorders', () => _getWorkorders());
272
+ async function getWorkorders(filters) {
273
+ let all;
274
+ try {
275
+ all = await loadCached('workorders', () => remoteWorkorders.getAll());
276
+ }
277
+ catch (error) {
278
+ logReadFailure('workorders.getAll', error);
279
+ return [];
280
+ }
231
281
  return applyWorkorderFilters(all, filters);
232
282
  }
233
- export async function getWorkordersDropdown(filters) {
283
+ async function getWorkordersDropdown(filters) {
234
284
  const results = await getWorkorders({ isActive: true, ...filters });
235
285
  return results.map((w) => ({ value: w.id, label: w.description ?? w.id }));
236
286
  }
237
287
  /** Single workorder by ID — always fetches fresh (no IndexedDB). */
238
- export async function getWorkorder(id) {
239
- return _getWorkorder(id);
288
+ async function getWorkorder(id) {
289
+ try {
290
+ return await remoteWorkorders.get(id);
291
+ }
292
+ catch (error) {
293
+ logReadFailure('workorders.get', error);
294
+ return null;
295
+ }
240
296
  }
241
297
  // ---------------------------------------------------------------------------
242
298
  // Public API — Cost Codes
243
299
  // ---------------------------------------------------------------------------
244
- export async function getCostcodes(filters) {
245
- const all = await loadCached('costcodes', () => _getCostcodes());
300
+ async function getCostcodes(filters) {
301
+ let all;
302
+ try {
303
+ all = await loadCached('costcodes', () => remoteCostcodes.getAll());
304
+ }
305
+ catch (error) {
306
+ logReadFailure('costcodes.getAll', error);
307
+ return [];
308
+ }
246
309
  return applyCostcodeFilters(all, filters);
247
310
  }
248
- export async function getCostcodesDropdown(filters) {
311
+ async function getCostcodesDropdown(filters) {
249
312
  const mergedFilters = { isActive: true, entryFlag: true, ...filters };
250
313
  const results = await getCostcodes(mergedFilters);
251
314
  const now = new Date();
@@ -257,56 +320,104 @@ export async function getCostcodesDropdown(filters) {
257
320
  }));
258
321
  }
259
322
  /** Single cost code by ID — always fetches fresh (no IndexedDB). */
260
- export async function getCostcode(id) {
261
- return _getCostcode(id);
323
+ async function getCostcode(id) {
324
+ try {
325
+ return await remoteCostcodes.get(id);
326
+ }
327
+ catch (error) {
328
+ logReadFailure('costcodes.get', error);
329
+ return null;
330
+ }
262
331
  }
263
332
  // ---------------------------------------------------------------------------
264
333
  // Public API — Pay Types
265
334
  // ---------------------------------------------------------------------------
266
- export async function getPaytypes(filters) {
267
- const all = await loadCached('paytypes', () => _getPaytypes());
335
+ async function getPaytypes(filters) {
336
+ let all;
337
+ try {
338
+ all = await loadCached('paytypes', () => remotePaytypes.getAll());
339
+ }
340
+ catch (error) {
341
+ logReadFailure('paytypes.getAll', error);
342
+ return [];
343
+ }
268
344
  return applyPaytypeFilters(all, filters);
269
345
  }
270
- export async function getPaytypesDropdown(filters) {
271
- const results = await getPaytypes(filters);
346
+ async function getPaytypesDropdown(filters) {
347
+ const mergedFilters = { isActive: true, ...filters };
348
+ const results = await getPaytypes(mergedFilters);
272
349
  return results.map((p) => ({ value: p.id, label: p.description, payClass: p.payClass }));
273
350
  }
274
351
  /** Single pay type by ID — always fetches fresh (no IndexedDB). */
275
- export async function getPaytype(id) {
276
- return _getPaytype(id);
352
+ async function getPaytype(id) {
353
+ try {
354
+ return await remotePaytypes.get(id);
355
+ }
356
+ catch (error) {
357
+ logReadFailure('paytypes.get', error);
358
+ return null;
359
+ }
277
360
  }
278
361
  // ---------------------------------------------------------------------------
279
362
  // Public API — Business Units
280
363
  // ---------------------------------------------------------------------------
281
- export async function getBusinessUnits(filters) {
282
- const all = await loadCached('businessUnits', () => _getBusinessUnits());
364
+ async function getBusinessUnits(filters) {
365
+ let all;
366
+ try {
367
+ all = await loadCached('businessUnits', () => remoteBusinessUnits.getAll());
368
+ }
369
+ catch (error) {
370
+ logReadFailure('businessUnits.getAll', error);
371
+ return [];
372
+ }
283
373
  return applyBusinessUnitFilters(all, filters);
284
374
  }
285
- export async function getBusinessUnitsDropdown(filters) {
286
- const results = await getBusinessUnits(filters);
375
+ async function getBusinessUnitsDropdown(filters) {
376
+ const mergedFilters = { isActive: true, ...filters };
377
+ const results = await getBusinessUnits(mergedFilters);
287
378
  return results.map((b) => ({ value: b.id, label: b.description }));
288
379
  }
289
380
  /** Single business unit by ID — always fetches fresh (no IndexedDB). */
290
- export async function getBusinessUnit(id) {
291
- return _getBusinessUnit(id);
381
+ async function getBusinessUnit(id) {
382
+ try {
383
+ return await remoteBusinessUnits.get(id);
384
+ }
385
+ catch (error) {
386
+ logReadFailure('businessUnits.get', error);
387
+ return null;
388
+ }
292
389
  }
293
390
  // ---------------------------------------------------------------------------
294
391
  // Public API — Job Type / Job Steps
295
392
  // ---------------------------------------------------------------------------
296
- export async function getJobtypejobsteps(filters) {
297
- const all = await loadCached('jobtypejobsteps', () => _getJobtypejobsteps());
393
+ async function getJobtypejobsteps(filters) {
394
+ let all;
395
+ try {
396
+ all = await loadCached('jobtypejobsteps', () => remoteJobtypejobsteps.getAll());
397
+ }
398
+ catch (error) {
399
+ logReadFailure('jobtypejobsteps.getAll', error);
400
+ return [];
401
+ }
298
402
  return applyJobtypejobstepFilters(all, filters);
299
403
  }
300
- export async function getJobtypejobstepsDropdown(filters) {
301
- const results = await getJobtypejobsteps(filters);
404
+ async function getJobtypejobstepsDropdown(filters) {
405
+ const mergedFilters = { isActive: true, ...filters };
406
+ const results = await getJobtypejobsteps(mergedFilters);
302
407
  return results.map((j) => ({
303
408
  value: j.id,
304
409
  label: j.description ?? `${j.jobType ?? ''} ${j.jobStep ?? ''}`.trim(),
305
410
  }));
306
411
  }
307
412
  /** Single job type/job step by ID — always fetches fresh (no IndexedDB). */
308
- export async function getJobtypejobstep(id) {
309
- return _getJobtypejobstep(id);
413
+ async function getJobtypejobstep(id) {
414
+ try {
415
+ return await remoteJobtypejobsteps.get(id);
416
+ }
417
+ catch (error) {
418
+ logReadFailure('jobtypejobsteps.get', error);
419
+ return null;
420
+ }
310
421
  }
311
422
  // ---------------------------------------------------------------------------
312
423
  // Cache management
@@ -324,5 +435,48 @@ export async function getJobtypejobstep(id) {
324
435
  * clearCache() // clear everything
325
436
  */
326
437
  export function clearCache(entity) {
438
+ if (entity) {
439
+ serverCache.delete(entity);
440
+ }
441
+ else {
442
+ serverCache.clear();
443
+ }
327
444
  idbClear(entity).catch(() => { });
328
445
  }
446
+ // ---------------------------------------------------------------------------
447
+ // Unified domain-style API (v2 contract)
448
+ // ---------------------------------------------------------------------------
449
+ export const employees = {
450
+ getAll: getEmployees,
451
+ dropdown: getEmployeesDropdown,
452
+ get: (id) => getEmployee(id),
453
+ getPrivileged: getEmployeePrivileged,
454
+ getSupervisorChain,
455
+ getJdeFromEmail,
456
+ verifyIdentity,
457
+ };
458
+ export const workorders = {
459
+ getAll: getWorkorders,
460
+ dropdown: getWorkordersDropdown,
461
+ get: (id) => getWorkorder(id),
462
+ };
463
+ export const costcodes = {
464
+ getAll: getCostcodes,
465
+ dropdown: getCostcodesDropdown,
466
+ get: (id) => getCostcode(id),
467
+ };
468
+ export const paytypes = {
469
+ getAll: getPaytypes,
470
+ dropdown: getPaytypesDropdown,
471
+ get: (id) => getPaytype(id),
472
+ };
473
+ export const businessUnits = {
474
+ getAll: getBusinessUnits,
475
+ dropdown: getBusinessUnitsDropdown,
476
+ get: (id) => getBusinessUnit(id),
477
+ };
478
+ export const jobtypejobsteps = {
479
+ getAll: getJobtypejobsteps,
480
+ dropdown: getJobtypejobstepsDropdown,
481
+ get: (id) => getJobtypejobstep(id),
482
+ };
@@ -1,3 +1,5 @@
1
- export declare const getCostcodes: import("@sveltejs/kit").RemoteQueryFunction<void, import("./index.js").Costcode[]>;
2
- export declare const getCostcodesDropdown: import("@sveltejs/kit").RemoteQueryFunction<void, import("./index.js").DropdownOption[]>;
3
- export declare const getCostcode: import("@sveltejs/kit").RemoteQueryFunction<string, import("./index.js").Costcode>;
1
+ export declare const costcodes: {
2
+ getAll: import("@sveltejs/kit").RemoteQueryFunction<void, import("./index.js").Costcode[]>;
3
+ dropdown: import("@sveltejs/kit").RemoteQueryFunction<void, import("./index.js").DropdownOption[]>;
4
+ get: import("@sveltejs/kit").RemoteQueryFunction<string, import("./index.js").Costcode | null>;
5
+ };
@@ -1,6 +1,26 @@
1
1
  import { query } from '$app/server';
2
2
  import { z } from 'zod';
3
3
  import { getClient } from './client.js';
4
- export const getCostcodes = query(async () => getClient().getCostcodes());
5
- export const getCostcodesDropdown = query(async () => getClient().getCostcodesDropdown());
6
- export const getCostcode = query(z.string(), async (id) => getClient().getCostcode(id));
4
+ function isNotFoundError(error) {
5
+ if (!(error instanceof Error))
6
+ return false;
7
+ return /not found/i.test(error.message);
8
+ }
9
+ async function asNullable(fetcher) {
10
+ try {
11
+ return await fetcher();
12
+ }
13
+ catch (error) {
14
+ if (isNotFoundError(error))
15
+ return null;
16
+ throw error;
17
+ }
18
+ }
19
+ const getAll = query(async () => getClient().getCostcodes());
20
+ const dropdown = query(async () => getClient().getCostcodesDropdown());
21
+ const get = query(z.string(), async (id) => asNullable(() => getClient().getCostcode(id)));
22
+ export const costcodes = {
23
+ getAll,
24
+ dropdown,
25
+ get,
26
+ };
@@ -1,15 +1,17 @@
1
- export declare const getEmployees: import("@sveltejs/kit").RemoteQueryFunction<void, import("./index.js").Employee[]>;
2
- export declare const getEmployeesDropdown: import("@sveltejs/kit").RemoteQueryFunction<void, import("./index.js").DropdownOption[]>;
3
- export declare const getEmployee: import("@sveltejs/kit").RemoteQueryFunction<string, import("./index.js").Employee>;
4
- export declare const getEmployeePrivileged: import("@sveltejs/kit").RemoteQueryFunction<string, import("./index.js").EmployeePrivileged>;
5
- export declare const getSupervisorChain: import("@sveltejs/kit").RemoteQueryFunction<string, import("./index.js").Employee[]>;
6
- export declare const getJdeFromEmail: import("@sveltejs/kit").RemoteQueryFunction<string, {
7
- jde: string | null;
8
- employee: import("./index.js").Employee | null;
9
- }>;
10
- export declare const verifyIdentity: import("@sveltejs/kit").RemoteCommand<{
11
- first3FirstName: string;
12
- first3LastName: string;
13
- dob: string;
14
- ssn4: string;
15
- }, Promise<import("./index.js").Employee | null>>;
1
+ export declare const employees: {
2
+ getAll: import("@sveltejs/kit").RemoteQueryFunction<void, import("./index.js").Employee[]>;
3
+ dropdown: import("@sveltejs/kit").RemoteQueryFunction<void, import("./index.js").DropdownOption[]>;
4
+ get: import("@sveltejs/kit").RemoteQueryFunction<string, import("./index.js").Employee | null>;
5
+ getPrivileged: import("@sveltejs/kit").RemoteQueryFunction<string, import("./index.js").EmployeePrivileged>;
6
+ getSupervisorChain: import("@sveltejs/kit").RemoteQueryFunction<string, import("./index.js").Employee[]>;
7
+ getJdeFromEmail: import("@sveltejs/kit").RemoteQueryFunction<string, {
8
+ jde: string | null;
9
+ employee: import("./index.js").Employee | null;
10
+ }>;
11
+ verifyIdentity: import("@sveltejs/kit").RemoteCommand<{
12
+ first3FirstName: string;
13
+ first3LastName: string;
14
+ dob: string;
15
+ ssn4: string;
16
+ }, Promise<import("./index.js").Employee | null>>;
17
+ };
@@ -1,6 +1,21 @@
1
1
  import { query, command } from '$app/server';
2
2
  import { z } from 'zod';
3
3
  import { getClient } from './client.js';
4
+ function isNotFoundError(error) {
5
+ if (!(error instanceof Error))
6
+ return false;
7
+ return /not found/i.test(error.message);
8
+ }
9
+ async function asNullable(fetcher) {
10
+ try {
11
+ return await fetcher();
12
+ }
13
+ catch (error) {
14
+ if (isNotFoundError(error))
15
+ return null;
16
+ throw error;
17
+ }
18
+ }
4
19
  const employeeIdSchema = z.string().min(1);
5
20
  const verifyIdentitySchema = z.object({
6
21
  first3FirstName: z.string(),
@@ -8,10 +23,19 @@ const verifyIdentitySchema = z.object({
8
23
  dob: z.string(),
9
24
  ssn4: z.string(),
10
25
  });
11
- export const getEmployees = query(async () => getClient().getEmployees());
12
- export const getEmployeesDropdown = query(async () => getClient().getEmployeesDropdown());
13
- export const getEmployee = query(employeeIdSchema, async (employeeId) => getClient().getEmployee(employeeId));
14
- export const getEmployeePrivileged = query(employeeIdSchema, async (employeeId) => getClient().getEmployeePrivileged(employeeId));
15
- export const getSupervisorChain = query(employeeIdSchema, async (employeeId) => getClient().getSupervisorChain(employeeId));
16
- export const getJdeFromEmail = query(z.string(), async (email) => getClient().getJdeFromEmail(email));
17
- export const verifyIdentity = command(verifyIdentitySchema, async (inputs) => getClient().verifyIdentity(inputs));
26
+ const getAll = query(async () => getClient().getEmployees());
27
+ const dropdown = query(async () => getClient().getEmployeesDropdown());
28
+ const get = query(employeeIdSchema, async (employeeId) => asNullable(() => getClient().getEmployee(employeeId)));
29
+ const getPrivileged = query(employeeIdSchema, async (employeeId) => getClient().getEmployeePrivileged(employeeId));
30
+ const getSupervisorChain = query(employeeIdSchema, async (employeeId) => getClient().getSupervisorChain(employeeId));
31
+ const getJdeFromEmail = query(z.string(), async (email) => getClient().getJdeFromEmail(email));
32
+ const verifyIdentity = command(verifyIdentitySchema, async (inputs) => getClient().verifyIdentity(inputs));
33
+ export const employees = {
34
+ getAll,
35
+ dropdown,
36
+ get,
37
+ getPrivileged,
38
+ getSupervisorChain,
39
+ getJdeFromEmail,
40
+ verifyIdentity,
41
+ };
package/dist/index.d.ts CHANGED
@@ -57,6 +57,29 @@ export interface ApiHubClientOptions {
57
57
  apiKey: string;
58
58
  /** Default cache TTL in milliseconds. Set to 0 to disable caching. Default: 5 minutes. */
59
59
  cacheTtl?: number;
60
+ /** Request timeout in milliseconds. Default: 10000. */
61
+ timeoutMs?: number;
62
+ /** Retry count for idempotent GET requests on transient failures. Default: 2. */
63
+ retryCount?: number;
64
+ /** Optional hook invoked whenever an APIHubError is raised. */
65
+ onError?: (error: ApiHubError) => void;
66
+ }
67
+ export declare class ApiHubError extends Error {
68
+ status: number | null;
69
+ path: string;
70
+ url: string;
71
+ responseBody: unknown;
72
+ retriable: boolean;
73
+ service: string;
74
+ constructor(options: {
75
+ message: string;
76
+ status: number | null;
77
+ path: string;
78
+ url: string;
79
+ responseBody: unknown;
80
+ retriable: boolean;
81
+ service?: string;
82
+ });
60
83
  }
61
84
  export interface DropdownOption {
62
85
  value: number | string;
@@ -208,8 +231,15 @@ export declare class ApiHubClient {
208
231
  private baseUrl;
209
232
  private apiKey;
210
233
  private cacheTtl;
234
+ private timeoutMs;
235
+ private retryCount;
236
+ private onError?;
211
237
  private cache;
212
238
  constructor(options: ApiHubClientOptions);
239
+ private isRetriableStatus;
240
+ private createApiHubError;
241
+ private fetchWithTimeout;
242
+ private delay;
213
243
  /** Clear all cached responses, or a specific path */
214
244
  clearCache(path?: string): void;
215
245
  private cachedRequest;
@@ -288,3 +318,7 @@ export declare class ApiHubClient {
288
318
  getJobtypejobstepsDropdown(): Promise<DropdownOption[]>;
289
319
  getJobtypejobstep(id: string): Promise<Jobtypejobstep>;
290
320
  }
321
+ export { employees, workorders, costcodes, paytypes, businessUnits, jobtypejobsteps, clearCache } from './cache.js';
322
+ export { llm } from './llm.remote.js';
323
+ export { rag } from './rag.remote.js';
324
+ export type { EmployeeFilters, WorkorderFilters, CostcodeFilters, PaytypeFilters, BusinessUnitFilters, JobtypejobstepFilters, } from './cache.js';