@brownandroot/api 1.0.0 → 1.2.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 +346 -152
- package/dist/businessUnits.remote.d.ts +3 -4
- package/dist/businessUnits.remote.js +0 -1
- package/dist/cache.d.ts +152 -0
- package/dist/cache.js +324 -0
- package/dist/costcodes.remote.d.ts +3 -6
- package/dist/costcodes.remote.js +0 -7
- package/dist/employees.remote.d.ts +15 -10
- package/dist/employees.remote.js +1 -4
- package/dist/idb.d.ts +13 -0
- package/dist/idb.js +79 -0
- package/dist/index.d.ts +9 -2
- package/dist/index.js +4 -0
- package/dist/jobtypejobsteps.remote.d.ts +3 -3
- package/dist/llm.remote.d.ts +12 -2
- package/dist/paytypes.remote.d.ts +3 -4
- package/dist/paytypes.remote.js +0 -1
- package/dist/rag.remote.d.ts +11 -4
- package/dist/workorders.remote.d.ts +3 -5
- package/dist/workorders.remote.js +0 -2
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -8,7 +8,271 @@ TypeScript client for the Brown & Root APIHub data service. Provides access to e
|
|
|
8
8
|
npm install @brownandroot/api
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Client-Side Cache API (recommended for SvelteKit)
|
|
14
|
+
|
|
15
|
+
The package ships a browser-side API at `@brownandroot/api/cache` that wraps every remote function with an **IndexedDB stale-while-revalidate cache**. On the first call the data is fetched from the server; on every subsequent call the cached data is returned instantly and a background refresh keeps the cache warm.
|
|
16
|
+
|
|
17
|
+
All list and dropdown functions accept an optional filter object — every entity field is available as an optional filter key. The `q` field performs a case-insensitive partial-text match across the entity's searchable text fields.
|
|
18
|
+
|
|
19
|
+
### Setup
|
|
20
|
+
|
|
21
|
+
Add to your app's `.env`:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
APIHUB_URL=https://your-apihub-url.com
|
|
25
|
+
APIHUB_API_KEY=your-api-key
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Enable remote functions in `svelte.config.js` (if not already):
|
|
29
|
+
|
|
30
|
+
```js
|
|
31
|
+
kit: {
|
|
32
|
+
experimental: {
|
|
33
|
+
remoteFunctions: true
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Usage
|
|
39
|
+
|
|
40
|
+
```svelte
|
|
41
|
+
<script lang="ts">
|
|
42
|
+
import { getWorkordersDropdown, getEmployees, clearCache } from '@brownandroot/api/cache'
|
|
43
|
+
|
|
44
|
+
// First page load: fetches from server and caches in IndexedDB.
|
|
45
|
+
// Subsequent loads: returns from IndexedDB instantly, refreshes in background.
|
|
46
|
+
const workorders = $derived(await getWorkordersDropdown({ businessUnitId: 'BU001' }))
|
|
47
|
+
|
|
48
|
+
// Multiple filters compose freely
|
|
49
|
+
const employees = $derived(await getEmployees({
|
|
50
|
+
hbu: 'TX01',
|
|
51
|
+
payClass: 'H',
|
|
52
|
+
q: 'john',
|
|
53
|
+
}))
|
|
54
|
+
|
|
55
|
+
// After a mutation, clear the affected entity so the next read re-fetches
|
|
56
|
+
async function onCreate() {
|
|
57
|
+
await createWorkorder(formData)
|
|
58
|
+
clearCache('workorders')
|
|
59
|
+
}
|
|
60
|
+
</script>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Filter reference
|
|
64
|
+
|
|
65
|
+
All filter fields are optional. Omit the filter object entirely to return all records.
|
|
66
|
+
|
|
67
|
+
#### Workorders
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
import { getWorkorders, getWorkordersDropdown } from '@brownandroot/api/cache'
|
|
71
|
+
|
|
72
|
+
interface WorkorderFilters {
|
|
73
|
+
businessUnitId?: string // exact match
|
|
74
|
+
costCodeId?: string // exact match
|
|
75
|
+
isActive?: boolean // exact match
|
|
76
|
+
completed?: boolean // exact match
|
|
77
|
+
area?: string // exact match
|
|
78
|
+
parentWorkOrder?: string // exact match
|
|
79
|
+
q?: string // partial match on description or clientWorkOrderId
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Returns Workorder[]
|
|
83
|
+
const all = await getWorkorders()
|
|
84
|
+
const active = await getWorkorders({ isActive: true })
|
|
85
|
+
const byBu = await getWorkorders({ businessUnitId: 'BU001', isActive: true })
|
|
86
|
+
const search = await getWorkorders({ q: 'pipe' })
|
|
87
|
+
|
|
88
|
+
// Returns { value, label }[] — always applies isActive: true by default
|
|
89
|
+
const dropdown = await getWorkordersDropdown({ businessUnitId: 'BU001' })
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
#### Employees
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
import { getEmployees, getEmployeesDropdown } from '@brownandroot/api/cache'
|
|
96
|
+
|
|
97
|
+
interface EmployeeFilters {
|
|
98
|
+
businessUnitId?: string // exact match
|
|
99
|
+
hbu?: string // exact match on home business unit
|
|
100
|
+
supervisor?: string // exact match on supervisor employee ID
|
|
101
|
+
payClass?: string // exact match
|
|
102
|
+
jobType?: string // exact match
|
|
103
|
+
jobStep?: string // exact match
|
|
104
|
+
sector?: string // exact match
|
|
105
|
+
division?: string // exact match
|
|
106
|
+
q?: string // partial match on name or email
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const byHbu = await getEmployees({ hbu: 'TX01' })
|
|
110
|
+
const byName = await getEmployees({ q: 'john' })
|
|
111
|
+
const dropdown = await getEmployeesDropdown({ businessUnitId: 'BU001' })
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
#### Cost Codes
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
import { getCostcodes, getCostcodesDropdown } from '@brownandroot/api/cache'
|
|
118
|
+
|
|
119
|
+
interface CostcodeFilters {
|
|
120
|
+
businessUnitId?: string // exact match
|
|
121
|
+
isActive?: boolean // exact match
|
|
122
|
+
entryFlag?: boolean // exact match
|
|
123
|
+
payTypeCode?: string // resolves pay type → objectAccount, filters by match
|
|
124
|
+
q?: string // partial match on description or jdeCostCode
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const byBu = await getCostcodes({ businessUnitId: 'BU001' })
|
|
128
|
+
const search = await getCostcodes({ q: 'labor' })
|
|
129
|
+
|
|
130
|
+
// Dropdown applies isActive: true and entryFlag: true by default,
|
|
131
|
+
// and also excludes expired cost codes
|
|
132
|
+
const dropdown = await getCostcodesDropdown({ businessUnitId: 'BU001' })
|
|
133
|
+
const dropdownByPayType = await getCostcodesDropdown({
|
|
134
|
+
businessUnitId: 'BU001',
|
|
135
|
+
payTypeCode: 'PT01',
|
|
136
|
+
})
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
> **payTypeCode cross-reference:** When `payTypeCode` is set, the filter looks up that pay type's `objectAccount` from the (also cached) pay types list and only returns cost codes whose `objectAccount` matches. If the pay type has no `objectAccount`, all cost codes pass this filter.
|
|
140
|
+
|
|
141
|
+
#### Pay Types
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
import { getPaytypes, getPaytypesDropdown } from '@brownandroot/api/cache'
|
|
145
|
+
|
|
146
|
+
interface PaytypeFilters {
|
|
147
|
+
payClass?: string // exact match
|
|
148
|
+
category?: string // exact match
|
|
149
|
+
type?: string // exact match
|
|
150
|
+
isActive?: boolean // exact match
|
|
151
|
+
perDiemPayType?: boolean // exact match
|
|
152
|
+
q?: string // partial match on description
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const hourly = await getPaytypes({ payClass: 'H' })
|
|
156
|
+
const dropdown = await getPaytypesDropdown({ isActive: true })
|
|
157
|
+
// Dropdown returns { value, label, payClass }[]
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
#### Business Units
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
import { getBusinessUnits, getBusinessUnitsDropdown } from '@brownandroot/api/cache'
|
|
164
|
+
|
|
165
|
+
interface BusinessUnitFilters {
|
|
166
|
+
subsector?: string // exact match
|
|
167
|
+
isActive?: boolean // exact match
|
|
168
|
+
clientId?: string // exact match
|
|
169
|
+
q?: string // partial match on description or clientDescription
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const active = await getBusinessUnits({ isActive: true })
|
|
173
|
+
const dropdown = await getBusinessUnitsDropdown({ subsector: 'Gulf Coast' })
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
#### Job Type / Job Steps
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
import { getJobtypejobsteps, getJobtypejobstepsDropdown } from '@brownandroot/api/cache'
|
|
180
|
+
|
|
181
|
+
interface JobtypejobstepFilters {
|
|
182
|
+
jobType?: string // exact match
|
|
183
|
+
payclass?: string // exact match
|
|
184
|
+
isActive?: boolean // exact match
|
|
185
|
+
grp?: string // exact match
|
|
186
|
+
q?: string // partial match on description, jobType, or jobStep
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const welders = await getJobtypejobsteps({ jobType: 'WE' })
|
|
190
|
+
const dropdown = await getJobtypejobstepsDropdown({ isActive: true })
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Single-record lookups
|
|
194
|
+
|
|
195
|
+
Single-record functions always fetch fresh from the server (no IndexedDB):
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
import {
|
|
199
|
+
getEmployee,
|
|
200
|
+
getSupervisorChain,
|
|
201
|
+
getJdeFromEmail,
|
|
202
|
+
verifyIdentity,
|
|
203
|
+
getWorkorder,
|
|
204
|
+
getCostcode,
|
|
205
|
+
getPaytype,
|
|
206
|
+
getBusinessUnit,
|
|
207
|
+
getJobtypejobstep,
|
|
208
|
+
} from '@brownandroot/api/cache'
|
|
209
|
+
|
|
210
|
+
const emp = await getEmployee('12345')
|
|
211
|
+
const chain = await getSupervisorChain('12345')
|
|
212
|
+
const { jde, employee } = await getJdeFromEmail('john@example.com')
|
|
213
|
+
const verified = await verifyIdentity({
|
|
214
|
+
first3FirstName: 'joh',
|
|
215
|
+
first3LastName: 'doe',
|
|
216
|
+
dob: '1985-03-15',
|
|
217
|
+
ssn4: '4321',
|
|
218
|
+
})
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Cache management
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
import { clearCache } from '@brownandroot/api/cache'
|
|
225
|
+
|
|
226
|
+
clearCache() // clear all entities
|
|
227
|
+
clearCache('workorders') // clear a specific entity
|
|
228
|
+
clearCache('employees')
|
|
229
|
+
clearCache('costcodes')
|
|
230
|
+
clearCache('paytypes')
|
|
231
|
+
clearCache('businessUnits')
|
|
232
|
+
clearCache('jobtypejobsteps')
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Call `clearCache(entity)` immediately after any mutation that changes that entity so the next read fetches fresh data.
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## Remote Functions (server-side)
|
|
240
|
+
|
|
241
|
+
For SvelteKit apps that need direct server-side access without the IndexedDB layer, the package also ships ready-to-use remote functions that run on the server and read credentials from environment variables automatically.
|
|
242
|
+
|
|
243
|
+
```svelte
|
|
244
|
+
<script lang="ts">
|
|
245
|
+
import { getEmployees } from '@brownandroot/api/employees'
|
|
246
|
+
import { getBusinessUnits } from '@brownandroot/api/businessUnits'
|
|
247
|
+
|
|
248
|
+
// These always fetch from the server on every call
|
|
249
|
+
const employees = $derived(await getEmployees())
|
|
250
|
+
const businessUnits = $derived(await getBusinessUnits())
|
|
251
|
+
</script>
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Or compose with your own remote functions:
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
import { query } from '$app/server'
|
|
258
|
+
import { getSupervisorChain } from '@brownandroot/api/employees'
|
|
259
|
+
|
|
260
|
+
export const getMyManagers = query(async () => {
|
|
261
|
+
return (await getSupervisorChain('12345')).slice(0, 2)
|
|
262
|
+
})
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
**Available sub-paths:** `employees`, `businessUnits`, `costcodes`, `paytypes`, `workorders`, `jobtypejobsteps`, `llm`, `rag`
|
|
266
|
+
|
|
267
|
+
> `chatStream` is not available as a remote function — use `ApiHubClient` directly to proxy the SSE response.
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## ApiHubClient (direct usage)
|
|
272
|
+
|
|
273
|
+
For non-SvelteKit environments or when you need full control (caching, streaming):
|
|
274
|
+
|
|
275
|
+
### Setup
|
|
12
276
|
|
|
13
277
|
```typescript
|
|
14
278
|
import { ApiHubClient } from '@brownandroot/api'
|
|
@@ -27,36 +291,15 @@ const client = new ApiHubClient({
|
|
|
27
291
|
### Fetching
|
|
28
292
|
|
|
29
293
|
```typescript
|
|
30
|
-
// All employees
|
|
31
294
|
const employees = await client.getEmployees()
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
// Single employee by ID — throws if not found
|
|
37
|
-
const employee = await client.getEmployee('12345')
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
### Search
|
|
41
|
-
|
|
42
|
-
```typescript
|
|
43
|
-
// By name (case-insensitive partial match)
|
|
44
|
-
const results = await client.searchByName('John')
|
|
45
|
-
|
|
46
|
-
// By email (case-insensitive partial match)
|
|
47
|
-
const results = await client.searchByEmail('john@example.com')
|
|
48
|
-
|
|
49
|
-
// By home business unit (case-insensitive partial match)
|
|
50
|
-
const results = await client.searchByHbu('TX01')
|
|
295
|
+
const dropdown = await client.getEmployeesDropdown() // { value: employeeId, label: name }[]
|
|
296
|
+
const employee = await client.getEmployee('12345') // throws if not found
|
|
297
|
+
const employeePrivileged = await client.getEmployeePrivileged('12345') // includes hourlyRate and annualSalary
|
|
51
298
|
```
|
|
52
299
|
|
|
53
300
|
### Org hierarchy
|
|
54
301
|
|
|
55
302
|
```typescript
|
|
56
|
-
// All employees reporting directly to a supervisor
|
|
57
|
-
const reports = await client.getBySupervisor('12345')
|
|
58
|
-
|
|
59
|
-
// Full supervisor chain above an employee (excludes the employee themselves)
|
|
60
303
|
const chain = await client.getSupervisorChain('12345')
|
|
61
304
|
```
|
|
62
305
|
|
|
@@ -70,21 +313,14 @@ const { jde, employee } = await client.getJdeFromEmail('john@example.com')
|
|
|
70
313
|
|
|
71
314
|
### Identity verification
|
|
72
315
|
|
|
73
|
-
Verifies an employee's identity from name, date of birth, and last 4 of SSN alone — no employee ID needed. Returns the full employee record on a match.
|
|
74
|
-
|
|
75
316
|
```typescript
|
|
76
317
|
const employee = await client.verifyIdentity({
|
|
77
|
-
first3FirstName: 'joh',
|
|
78
|
-
first3LastName: 'doe',
|
|
79
|
-
dob: '1985-03-15',
|
|
80
|
-
ssn4: '4321',
|
|
318
|
+
first3FirstName: 'joh',
|
|
319
|
+
first3LastName: 'doe',
|
|
320
|
+
dob: '1985-03-15',
|
|
321
|
+
ssn4: '4321',
|
|
81
322
|
})
|
|
82
|
-
|
|
83
|
-
if (employee) {
|
|
84
|
-
// identity confirmed — full Employee object returned
|
|
85
|
-
} else {
|
|
86
|
-
// no employee matched these inputs
|
|
87
|
-
}
|
|
323
|
+
// Employee on match, null on no match
|
|
88
324
|
// Throws on 400 (missing fields) or 503 (not configured server-side)
|
|
89
325
|
```
|
|
90
326
|
|
|
@@ -92,75 +328,59 @@ if (employee) {
|
|
|
92
328
|
|
|
93
329
|
```typescript
|
|
94
330
|
interface Employee {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
// Security & reporting
|
|
146
|
-
securityLevel: string | null
|
|
147
|
-
reportingLevel: string | null
|
|
148
|
-
|
|
149
|
-
// Relationships
|
|
150
|
-
supervisor: string | null // supervisor employee ID
|
|
151
|
-
mentor: string | null
|
|
152
|
-
|
|
153
|
-
// Dates
|
|
154
|
-
hireDate: string | null
|
|
155
|
-
termDate: string | null
|
|
156
|
-
adjustedServiceDate: string | null
|
|
157
|
-
|
|
158
|
-
// Metadata
|
|
159
|
-
source: string | null
|
|
160
|
-
createdAt: string | null
|
|
161
|
-
updatedAtJulian: number | null
|
|
162
|
-
updatedAt: string | null
|
|
331
|
+
employeeId: string
|
|
332
|
+
name: string | null
|
|
333
|
+
email: string | null
|
|
334
|
+
personalEmail: string | null
|
|
335
|
+
clientEmail: string | null
|
|
336
|
+
workEmail: string | null
|
|
337
|
+
badgeNumber: string | null
|
|
338
|
+
nccerNumber: string | null
|
|
339
|
+
company: string | null
|
|
340
|
+
businessUnitId: string | null
|
|
341
|
+
hbu: string | null
|
|
342
|
+
departmentCode: string | null
|
|
343
|
+
division: string | null
|
|
344
|
+
sector: string | null
|
|
345
|
+
subsector: string | null
|
|
346
|
+
phone: string | null
|
|
347
|
+
employementStatus: string | null
|
|
348
|
+
employeePayStatus: string | null
|
|
349
|
+
recordType: string | null
|
|
350
|
+
jobType: string | null
|
|
351
|
+
jobStep: string | null
|
|
352
|
+
jobDescription: string | null
|
|
353
|
+
workSchedule: string | null
|
|
354
|
+
shift: string | null
|
|
355
|
+
payClass: string | null
|
|
356
|
+
payFrequency: string | null
|
|
357
|
+
payCycleCode: string | null
|
|
358
|
+
checkRouteCode: string | null
|
|
359
|
+
residentTaxArea: string | null
|
|
360
|
+
workTaxArea: string | null
|
|
361
|
+
benefitGroup: string | null
|
|
362
|
+
topFlexPtoDate: string | null
|
|
363
|
+
clientPtoDate: string | null
|
|
364
|
+
securityLevel: string | null
|
|
365
|
+
reportingLevel: string | null
|
|
366
|
+
supervisor: string | null
|
|
367
|
+
mentor: string | null
|
|
368
|
+
hireDate: string | null
|
|
369
|
+
termDate: string | null
|
|
370
|
+
adjustedServiceDate: string | null
|
|
371
|
+
identityHash: string | null
|
|
372
|
+
source: string | null
|
|
373
|
+
createdAt: string | null
|
|
374
|
+
updatedAtJulian: number | null
|
|
375
|
+
updatedAt: string | null
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
interface EmployeePrivileged extends Employee {
|
|
379
|
+
hourlyRate: string | null
|
|
380
|
+
annualSalary: string | null
|
|
163
381
|
}
|
|
382
|
+
|
|
383
|
+
getEmployees, getEmployee, employee searches, getJdeFromEmail, and verifyIdentity all return the public Employee shape (without compensation fields). Use getEmployeePrivileged when compensation fields are required.
|
|
164
384
|
```
|
|
165
385
|
|
|
166
386
|
---
|
|
@@ -171,9 +391,6 @@ interface Employee {
|
|
|
171
391
|
const units = await client.getBusinessUnits()
|
|
172
392
|
const dropdown = await client.getBusinessUnitsDropdown() // { value, label }[]
|
|
173
393
|
const unit = await client.getBusinessUnit('BU001')
|
|
174
|
-
|
|
175
|
-
// Search by description (case-insensitive partial match)
|
|
176
|
-
const results = await client.searchBusinessUnits('west')
|
|
177
394
|
```
|
|
178
395
|
|
|
179
396
|
---
|
|
@@ -184,15 +401,6 @@ const results = await client.searchBusinessUnits('west')
|
|
|
184
401
|
const codes = await client.getCostcodes()
|
|
185
402
|
const dropdown = await client.getCostcodesDropdown() // { value, label }[]
|
|
186
403
|
const code = await client.getCostcode('CC001')
|
|
187
|
-
|
|
188
|
-
// Filtered by business unit
|
|
189
|
-
const buDropdown = await client.getCostcodesDropdownByBu('BU001')
|
|
190
|
-
|
|
191
|
-
// Filtered by business unit and pay type
|
|
192
|
-
const buPtDropdown = await client.getCostcodesDropdownByBuAndPayType('BU001', 'PT01')
|
|
193
|
-
|
|
194
|
-
// Search by description or JDE cost code (case-insensitive partial match)
|
|
195
|
-
const results = await client.searchCostcodes('labor')
|
|
196
404
|
```
|
|
197
405
|
|
|
198
406
|
---
|
|
@@ -203,9 +411,6 @@ const results = await client.searchCostcodes('labor')
|
|
|
203
411
|
const types = await client.getPaytypes()
|
|
204
412
|
const dropdown = await client.getPaytypesDropdown() // { value, label, payClass }[]
|
|
205
413
|
const type = await client.getPaytype('PT001')
|
|
206
|
-
|
|
207
|
-
// Search by description (case-insensitive partial match)
|
|
208
|
-
const results = await client.searchPaytypes('regular')
|
|
209
414
|
```
|
|
210
415
|
|
|
211
416
|
---
|
|
@@ -216,12 +421,6 @@ const results = await client.searchPaytypes('regular')
|
|
|
216
421
|
const orders = await client.getWorkorders()
|
|
217
422
|
const dropdown = await client.getWorkordersDropdown() // { value, label }[]
|
|
218
423
|
const order = await client.getWorkorder('WO001')
|
|
219
|
-
|
|
220
|
-
// Filtered by business unit
|
|
221
|
-
const buDropdown = await client.getWorkordersDropdownByBu('BU001')
|
|
222
|
-
|
|
223
|
-
// Search by description or client work order ID (case-insensitive partial match)
|
|
224
|
-
const results = await client.searchWorkorders('pipe')
|
|
225
424
|
```
|
|
226
425
|
|
|
227
426
|
---
|
|
@@ -243,11 +442,11 @@ const item = await client.getJobtypejobstep('JTJS001')
|
|
|
243
442
|
```typescript
|
|
244
443
|
const result = await client.chat({
|
|
245
444
|
messages: [{ role: 'user', content: 'Summarize this document...' }],
|
|
246
|
-
source: 'my-app',
|
|
247
|
-
user: 'jane.doe',
|
|
248
|
-
function: 'summarize',
|
|
249
|
-
temperature: 0.7,
|
|
250
|
-
maxTokens: 1000,
|
|
445
|
+
source: 'my-app',
|
|
446
|
+
user: 'jane.doe',
|
|
447
|
+
function: 'summarize',
|
|
448
|
+
temperature: 0.7,
|
|
449
|
+
maxTokens: 1000,
|
|
251
450
|
})
|
|
252
451
|
|
|
253
452
|
console.log(result.message.content)
|
|
@@ -256,17 +455,13 @@ console.log(result.usage) // { tokensIn, tokensOut, totalTokens }
|
|
|
256
455
|
|
|
257
456
|
### Streaming chat
|
|
258
457
|
|
|
259
|
-
Returns a raw SSE `Response` for you to proxy or consume directly.
|
|
260
|
-
|
|
261
458
|
```typescript
|
|
262
459
|
const response = await client.chatStream({
|
|
263
460
|
messages: [{ role: 'user', content: 'Hello' }],
|
|
264
461
|
userContext: { name: 'Jane Doe', department: 'Engineering', roles: ['admin'] },
|
|
265
|
-
useRag: true,
|
|
266
|
-
tools: ['...'], // optional
|
|
462
|
+
useRag: true,
|
|
267
463
|
source: 'my-app',
|
|
268
464
|
})
|
|
269
|
-
|
|
270
465
|
// Proxy to the browser, or read the SSE stream directly
|
|
271
466
|
```
|
|
272
467
|
|
|
@@ -280,31 +475,20 @@ const logs = await client.getLlmLogs() // newest first
|
|
|
280
475
|
|
|
281
476
|
## Documents (RAG)
|
|
282
477
|
|
|
283
|
-
Upload and search documents in the knowledge base.
|
|
284
|
-
|
|
285
478
|
```typescript
|
|
286
|
-
// Upload a document (PDF or CSV)
|
|
287
479
|
const doc = await client.uploadDocument('report.pdf', base64Content, 'jane.doe')
|
|
288
|
-
|
|
289
|
-
// List all documents
|
|
290
480
|
const docs = await client.listDocuments()
|
|
291
|
-
|
|
292
|
-
// Search with a natural language query
|
|
293
481
|
const results = await client.searchDocuments('overtime policy', 5)
|
|
294
482
|
// results: { chunkId, content, fileName, documentType, score }[]
|
|
295
|
-
|
|
296
|
-
// Delete a document and all its chunks
|
|
297
483
|
await client.deleteDocument(doc.id)
|
|
298
484
|
```
|
|
299
485
|
|
|
300
486
|
---
|
|
301
487
|
|
|
302
|
-
## Cache management
|
|
303
|
-
|
|
304
|
-
All GET methods cache responses client-side for `cacheTtl` milliseconds (default 5 minutes). To invalidate:
|
|
488
|
+
## Cache management (ApiHubClient)
|
|
305
489
|
|
|
306
490
|
```typescript
|
|
307
|
-
client.clearCache()
|
|
491
|
+
client.clearCache() // clear everything
|
|
308
492
|
client.clearCache('/employees') // clear a specific path
|
|
309
493
|
```
|
|
310
494
|
|
|
@@ -332,20 +516,30 @@ import type {
|
|
|
332
516
|
DropdownOption,
|
|
333
517
|
PaytypeDropdownOption,
|
|
334
518
|
} from '@brownandroot/api'
|
|
519
|
+
|
|
520
|
+
// Filter interfaces (from cache module)
|
|
521
|
+
import type {
|
|
522
|
+
EmployeeFilters,
|
|
523
|
+
WorkorderFilters,
|
|
524
|
+
CostcodeFilters,
|
|
525
|
+
PaytypeFilters,
|
|
526
|
+
BusinessUnitFilters,
|
|
527
|
+
JobtypejobstepFilters,
|
|
528
|
+
} from '@brownandroot/api/cache'
|
|
335
529
|
```
|
|
336
530
|
|
|
337
531
|
---
|
|
338
532
|
|
|
339
533
|
## Error handling
|
|
340
534
|
|
|
341
|
-
All methods throw an `Error` when the API returns a non-OK response.
|
|
535
|
+
All methods throw an `Error` when the API returns a non-OK response.
|
|
342
536
|
|
|
343
537
|
```typescript
|
|
344
538
|
try {
|
|
345
|
-
const emp = await
|
|
539
|
+
const emp = await getEmployee('99999')
|
|
346
540
|
} catch (err) {
|
|
347
541
|
console.error(err.message) // "Employee not found"
|
|
348
542
|
}
|
|
349
543
|
```
|
|
350
544
|
|
|
351
|
-
`verifyIdentity`
|
|
545
|
+
`verifyIdentity` returns `null` when no employee matches the inputs, and only throws for request errors (400, 503, network failure).
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
export declare const getBusinessUnits:
|
|
2
|
-
export declare const getBusinessUnitsDropdown:
|
|
3
|
-
export declare const getBusinessUnit:
|
|
4
|
-
export declare const searchBusinessUnits: any;
|
|
1
|
+
export declare const getBusinessUnits: import("@sveltejs/kit").RemoteQueryFunction<void, import("./index.js").BusinessUnit[]>;
|
|
2
|
+
export declare const getBusinessUnitsDropdown: import("@sveltejs/kit").RemoteQueryFunction<void, import("./index.js").DropdownOption[]>;
|
|
3
|
+
export declare const getBusinessUnit: import("@sveltejs/kit").RemoteQueryFunction<string, import("./index.js").BusinessUnit>;
|
|
@@ -4,4 +4,3 @@ import { getClient } from './client.js';
|
|
|
4
4
|
export const getBusinessUnits = query(async () => getClient().getBusinessUnits());
|
|
5
5
|
export const getBusinessUnitsDropdown = query(async () => getClient().getBusinessUnitsDropdown());
|
|
6
6
|
export const getBusinessUnit = query(z.string(), async (id) => getClient().getBusinessUnit(id));
|
|
7
|
-
export const searchBusinessUnits = query(z.string(), async (q) => getClient().searchBusinessUnits(q));
|