@brownandroot/api 1.2.0 → 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/README.md +90 -471
- package/dist/businessUnits.remote.d.ts +5 -3
- package/dist/businessUnits.remote.js +23 -3
- package/dist/cache.d.ts +51 -28
- package/dist/cache.js +210 -52
- package/dist/costcodes.remote.d.ts +5 -3
- package/dist/costcodes.remote.js +23 -3
- package/dist/employees.remote.d.ts +17 -15
- package/dist/employees.remote.js +31 -7
- package/dist/index.d.ts +34 -0
- package/dist/index.js +110 -12
- package/dist/jobtypejobsteps.remote.d.ts +5 -3
- package/dist/jobtypejobsteps.remote.js +23 -3
- package/dist/llm.remote.d.ts +14 -12
- package/dist/llm.remote.js +6 -2
- package/dist/paytypes.remote.d.ts +5 -3
- package/dist/paytypes.remote.js +23 -3
- package/dist/rag.remote.d.ts +13 -11
- package/dist/rag.remote.js +10 -4
- package/dist/workorders.remote.d.ts +5 -3
- package/dist/workorders.remote.js +23 -3
- package/package.json +1 -37
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
|
-
|
|
101
|
-
|
|
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
|
-
|
|
103
|
+
declare function getEmployeePrivileged(employeeId: string): Promise<EmployeePrivileged>;
|
|
106
104
|
/** Full supervisor chain above an employee — always fetches fresh. */
|
|
107
|
-
|
|
105
|
+
declare function getSupervisorChain(employeeId: string): Promise<Employee[]>;
|
|
108
106
|
/** Look up JDE number and employee from email — always fetches fresh. */
|
|
109
|
-
|
|
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
|
-
|
|
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
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
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,22 +9,44 @@
|
|
|
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 {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
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
|
+
/** How long cached data is considered fresh before a background refresh is triggered. */
|
|
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
|
+
}
|
|
21
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
|
+
}
|
|
22
42
|
const cached = await idbGet(store, 'all');
|
|
23
43
|
if (cached) {
|
|
24
|
-
//
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
44
|
+
// Only refresh in the background if the cached data is older than the TTL
|
|
45
|
+
if (Date.now() - cached.fetchedAt >= CACHE_TTL_MS) {
|
|
46
|
+
fetcher()
|
|
47
|
+
.then((fresh) => idbSet(store, 'all', fresh))
|
|
48
|
+
.catch(() => { });
|
|
49
|
+
}
|
|
28
50
|
return cached.data;
|
|
29
51
|
}
|
|
30
52
|
// Cache miss — must await
|
|
@@ -163,7 +185,7 @@ async function applyCostcodeFilters(data, f) {
|
|
|
163
185
|
// Resolve payTypeCode → objectAccount
|
|
164
186
|
let payTypeObjectAccount;
|
|
165
187
|
if (f.payTypeCode !== undefined) {
|
|
166
|
-
const allPaytypes = await loadCached('paytypes', () =>
|
|
188
|
+
const allPaytypes = await loadCached('paytypes', () => remotePaytypes.getAll());
|
|
167
189
|
payTypeObjectAccount = allPaytypes.find((p) => p.id === f.payTypeCode)?.objectAccount;
|
|
168
190
|
}
|
|
169
191
|
return data.filter((c) => {
|
|
@@ -191,57 +213,102 @@ async function applyCostcodeFilters(data, f) {
|
|
|
191
213
|
// ---------------------------------------------------------------------------
|
|
192
214
|
// Public API — Employees
|
|
193
215
|
// ---------------------------------------------------------------------------
|
|
194
|
-
|
|
195
|
-
|
|
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
|
+
}
|
|
196
225
|
return applyEmployeeFilters(all, filters);
|
|
197
226
|
}
|
|
198
|
-
|
|
227
|
+
async function getEmployeesDropdown(filters) {
|
|
199
228
|
const results = await getEmployees(filters);
|
|
200
229
|
return results.map((e) => ({ value: e.employeeId, label: e.name ?? e.employeeId }));
|
|
201
230
|
}
|
|
202
231
|
/** Single employee by ID — always fetches fresh (no IndexedDB). */
|
|
203
|
-
|
|
204
|
-
|
|
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
|
+
}
|
|
205
240
|
}
|
|
206
241
|
/** Single employee by ID including compensation fields — always fetches fresh (no IndexedDB). */
|
|
207
|
-
|
|
208
|
-
return
|
|
242
|
+
async function getEmployeePrivileged(employeeId) {
|
|
243
|
+
return remoteEmployees.getPrivileged(employeeId);
|
|
209
244
|
}
|
|
210
245
|
/** Full supervisor chain above an employee — always fetches fresh. */
|
|
211
|
-
|
|
212
|
-
|
|
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
|
+
}
|
|
213
254
|
}
|
|
214
255
|
/** Look up JDE number and employee from email — always fetches fresh. */
|
|
215
|
-
|
|
216
|
-
|
|
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
|
+
}
|
|
217
264
|
}
|
|
218
265
|
/** Verify employee identity — always fetches fresh. */
|
|
219
|
-
|
|
220
|
-
return
|
|
266
|
+
async function verifyIdentity(inputs) {
|
|
267
|
+
return remoteEmployees.verifyIdentity(inputs);
|
|
221
268
|
}
|
|
222
269
|
// ---------------------------------------------------------------------------
|
|
223
270
|
// Public API — Workorders
|
|
224
271
|
// ---------------------------------------------------------------------------
|
|
225
|
-
|
|
226
|
-
|
|
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
|
+
}
|
|
227
281
|
return applyWorkorderFilters(all, filters);
|
|
228
282
|
}
|
|
229
|
-
|
|
283
|
+
async function getWorkordersDropdown(filters) {
|
|
230
284
|
const results = await getWorkorders({ isActive: true, ...filters });
|
|
231
285
|
return results.map((w) => ({ value: w.id, label: w.description ?? w.id }));
|
|
232
286
|
}
|
|
233
287
|
/** Single workorder by ID — always fetches fresh (no IndexedDB). */
|
|
234
|
-
|
|
235
|
-
|
|
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
|
+
}
|
|
236
296
|
}
|
|
237
297
|
// ---------------------------------------------------------------------------
|
|
238
298
|
// Public API — Cost Codes
|
|
239
299
|
// ---------------------------------------------------------------------------
|
|
240
|
-
|
|
241
|
-
|
|
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
|
+
}
|
|
242
309
|
return applyCostcodeFilters(all, filters);
|
|
243
310
|
}
|
|
244
|
-
|
|
311
|
+
async function getCostcodesDropdown(filters) {
|
|
245
312
|
const mergedFilters = { isActive: true, entryFlag: true, ...filters };
|
|
246
313
|
const results = await getCostcodes(mergedFilters);
|
|
247
314
|
const now = new Date();
|
|
@@ -253,56 +320,104 @@ export async function getCostcodesDropdown(filters) {
|
|
|
253
320
|
}));
|
|
254
321
|
}
|
|
255
322
|
/** Single cost code by ID — always fetches fresh (no IndexedDB). */
|
|
256
|
-
|
|
257
|
-
|
|
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
|
+
}
|
|
258
331
|
}
|
|
259
332
|
// ---------------------------------------------------------------------------
|
|
260
333
|
// Public API — Pay Types
|
|
261
334
|
// ---------------------------------------------------------------------------
|
|
262
|
-
|
|
263
|
-
|
|
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
|
+
}
|
|
264
344
|
return applyPaytypeFilters(all, filters);
|
|
265
345
|
}
|
|
266
|
-
|
|
267
|
-
const
|
|
346
|
+
async function getPaytypesDropdown(filters) {
|
|
347
|
+
const mergedFilters = { isActive: true, ...filters };
|
|
348
|
+
const results = await getPaytypes(mergedFilters);
|
|
268
349
|
return results.map((p) => ({ value: p.id, label: p.description, payClass: p.payClass }));
|
|
269
350
|
}
|
|
270
351
|
/** Single pay type by ID — always fetches fresh (no IndexedDB). */
|
|
271
|
-
|
|
272
|
-
|
|
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
|
+
}
|
|
273
360
|
}
|
|
274
361
|
// ---------------------------------------------------------------------------
|
|
275
362
|
// Public API — Business Units
|
|
276
363
|
// ---------------------------------------------------------------------------
|
|
277
|
-
|
|
278
|
-
|
|
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
|
+
}
|
|
279
373
|
return applyBusinessUnitFilters(all, filters);
|
|
280
374
|
}
|
|
281
|
-
|
|
282
|
-
const
|
|
375
|
+
async function getBusinessUnitsDropdown(filters) {
|
|
376
|
+
const mergedFilters = { isActive: true, ...filters };
|
|
377
|
+
const results = await getBusinessUnits(mergedFilters);
|
|
283
378
|
return results.map((b) => ({ value: b.id, label: b.description }));
|
|
284
379
|
}
|
|
285
380
|
/** Single business unit by ID — always fetches fresh (no IndexedDB). */
|
|
286
|
-
|
|
287
|
-
|
|
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
|
+
}
|
|
288
389
|
}
|
|
289
390
|
// ---------------------------------------------------------------------------
|
|
290
391
|
// Public API — Job Type / Job Steps
|
|
291
392
|
// ---------------------------------------------------------------------------
|
|
292
|
-
|
|
293
|
-
|
|
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
|
+
}
|
|
294
402
|
return applyJobtypejobstepFilters(all, filters);
|
|
295
403
|
}
|
|
296
|
-
|
|
297
|
-
const
|
|
404
|
+
async function getJobtypejobstepsDropdown(filters) {
|
|
405
|
+
const mergedFilters = { isActive: true, ...filters };
|
|
406
|
+
const results = await getJobtypejobsteps(mergedFilters);
|
|
298
407
|
return results.map((j) => ({
|
|
299
408
|
value: j.id,
|
|
300
409
|
label: j.description ?? `${j.jobType ?? ''} ${j.jobStep ?? ''}`.trim(),
|
|
301
410
|
}));
|
|
302
411
|
}
|
|
303
412
|
/** Single job type/job step by ID — always fetches fresh (no IndexedDB). */
|
|
304
|
-
|
|
305
|
-
|
|
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
|
+
}
|
|
306
421
|
}
|
|
307
422
|
// ---------------------------------------------------------------------------
|
|
308
423
|
// Cache management
|
|
@@ -320,5 +435,48 @@ export async function getJobtypejobstep(id) {
|
|
|
320
435
|
* clearCache() // clear everything
|
|
321
436
|
*/
|
|
322
437
|
export function clearCache(entity) {
|
|
438
|
+
if (entity) {
|
|
439
|
+
serverCache.delete(entity);
|
|
440
|
+
}
|
|
441
|
+
else {
|
|
442
|
+
serverCache.clear();
|
|
443
|
+
}
|
|
323
444
|
idbClear(entity).catch(() => { });
|
|
324
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
|
|
2
|
-
|
|
3
|
-
|
|
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
|
+
};
|
package/dist/costcodes.remote.js
CHANGED
|
@@ -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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
+
};
|
package/dist/employees.remote.js
CHANGED
|
@@ -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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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';
|