@brownandroot/api 0.10.0 → 0.12.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
@@ -1,6 +1,6 @@
1
1
  # @brownandroot/api
2
2
 
3
- TypeScript client for the Brown & Root APIHub data service. Provides read-only access to company data and an LLM chat endpoint powered by Azure AI Foundry.
3
+ TypeScript client for the Brown & Root APIHub data service. Provides read-only access to company data (employees, business units, cost codes, pay types, work orders, job type/job steps) and an LLM chat endpoint powered by Azure AI Foundry.
4
4
 
5
5
  ## Installation
6
6
 
@@ -25,11 +25,12 @@ const client = new ApiHubClient({
25
25
 
26
26
  ```typescript
27
27
  const employees = await client.getEmployees()
28
- const employee = await client.getEmployee(12345)
28
+ const dropdown = await client.getEmployeesDropdown() // { value, label }[]
29
+ const employee = await client.getEmployee('12345')
29
30
  const results = await client.searchByName('John')
30
31
  const results = await client.searchByEmail('john@example.com')
31
- const reports = await client.getBySupervisor(12345)
32
- const chain = await client.getSupervisorChain(12345)
32
+ const reports = await client.getBySupervisor('12345')
33
+ const chain = await client.getSupervisorChain('12345')
33
34
  const { jde, employee } = await client.getJdeFromEmail('john@example.com')
34
35
  ```
35
36
 
@@ -37,6 +38,7 @@ const { jde, employee } = await client.getJdeFromEmail('john@example.com')
37
38
 
38
39
  ```typescript
39
40
  const units = await client.getBusinessUnits()
41
+ const dropdown = await client.getBusinessUnitsDropdown() // { value, label }[]
40
42
  const unit = await client.getBusinessUnit('BU001')
41
43
  ```
42
44
 
@@ -44,6 +46,7 @@ const unit = await client.getBusinessUnit('BU001')
44
46
 
45
47
  ```typescript
46
48
  const codes = await client.getCostcodes()
49
+ const dropdown = await client.getCostcodesDropdown() // { value, label }[]
47
50
  const code = await client.getCostcode('CC001')
48
51
  ```
49
52
 
@@ -51,6 +54,7 @@ const code = await client.getCostcode('CC001')
51
54
 
52
55
  ```typescript
53
56
  const types = await client.getPaytypes()
57
+ const dropdown = await client.getPaytypesDropdown() // { value, label, payClass }[]
54
58
  const type = await client.getPaytype('PT001')
55
59
  ```
56
60
 
@@ -58,9 +62,18 @@ const type = await client.getPaytype('PT001')
58
62
 
59
63
  ```typescript
60
64
  const orders = await client.getWorkorders()
65
+ const dropdown = await client.getWorkordersDropdown() // { value, label }[]
61
66
  const order = await client.getWorkorder('WO001')
62
67
  ```
63
68
 
69
+ ### Job Type / Job Steps
70
+
71
+ ```typescript
72
+ const items = await client.getJobtypejobsteps()
73
+ const dropdown = await client.getJobtypejobstepsDropdown() // { value, label }[]
74
+ const item = await client.getJobtypejobstep('JTJS001')
75
+ ```
76
+
64
77
  ### LLM
65
78
 
66
79
  ```typescript
@@ -89,11 +102,14 @@ import type {
89
102
  Costcode,
90
103
  Paytype,
91
104
  Workorder,
105
+ Jobtypejobstep,
92
106
  LlmLog,
93
107
  ChatMessage,
94
108
  ChatRequest,
95
109
  ChatResponse,
96
110
  ApiHubClientOptions,
111
+ DropdownOption,
112
+ PaytypeDropdownOption,
97
113
  } from '@brownandroot/api'
98
114
  ```
99
115
 
@@ -103,7 +119,7 @@ Methods throw an `Error` when the API returns a non-OK response. The error messa
103
119
 
104
120
  ```typescript
105
121
  try {
106
- const emp = await client.getEmployee(99999)
122
+ const emp = await client.getEmployee('99999')
107
123
  } catch (err) {
108
124
  console.error(err.message) // "Employee not found"
109
125
  }
package/dist/index.d.ts CHANGED
@@ -174,7 +174,7 @@ export declare class ApiHubClient {
174
174
  searchByEmail(email: string): Promise<Employee[]>;
175
175
  /** Get the supervisor chain above an employee */
176
176
  getSupervisorChain(employeeId: string): Promise<Employee[]>;
177
- /** Look up JDE number and employee data from email (with JDEService/CoreService fallback) */
177
+ /** Look up JDE number and employee data from email (with itime fallback) */
178
178
  getJdeFromEmail(email: string): Promise<{
179
179
  jde: string | null;
180
180
  employee: Employee | null;
@@ -189,11 +189,17 @@ export declare class ApiHubClient {
189
189
  getCostcodes(): Promise<Costcode[]>;
190
190
  getCostcodesDropdown(): Promise<DropdownOption[]>;
191
191
  getCostcode(id: string): Promise<Costcode>;
192
+ /** Get cost codes for a specific business unit, formatted for dropdown controls */
193
+ getCostcodesDropdownByBu(businessUnitId: string): Promise<DropdownOption[]>;
194
+ /** Get cost codes for a specific business unit and pay type, formatted for dropdown controls */
195
+ getCostcodesDropdownByBuAndPayType(businessUnitId: string, payTypeCode: string): Promise<DropdownOption[]>;
192
196
  getPaytypes(): Promise<Paytype[]>;
193
197
  getPaytypesDropdown(): Promise<PaytypeDropdownOption[]>;
194
198
  getPaytype(id: string): Promise<Paytype>;
195
199
  getWorkorders(): Promise<Workorder[]>;
196
200
  getWorkordersDropdown(): Promise<DropdownOption[]>;
201
+ /** Get work orders for a specific business unit, formatted for dropdown controls */
202
+ getWorkordersDropdownByBu(businessUnitId: string): Promise<DropdownOption[]>;
197
203
  getWorkorder(id: string): Promise<Workorder>;
198
204
  getJobtypejobsteps(): Promise<Jobtypejobstep[]>;
199
205
  getJobtypejobstepsDropdown(): Promise<DropdownOption[]>;
package/dist/index.js CHANGED
@@ -6,12 +6,20 @@ export class ApiHubClient {
6
6
  this.apiKey = options.apiKey;
7
7
  }
8
8
  async request(path) {
9
- const res = await fetch(`${this.baseUrl}${path}`, {
10
- headers: { 'x-api-key': this.apiKey },
11
- });
9
+ let res;
10
+ try {
11
+ res = await fetch(`${this.baseUrl}${path}`, {
12
+ headers: { 'x-api-key': this.apiKey },
13
+ });
14
+ }
15
+ catch {
16
+ throw new Error(`APIHub unavailable: ${this.baseUrl}${path}`);
17
+ }
12
18
  if (!res.ok) {
13
- const body = await res.json().catch(() => ({}));
14
- throw new Error(body.error ?? `Request failed: ${res.status}`);
19
+ const body = await res.json().catch(() => null);
20
+ const message = (body && typeof body === 'object' && 'error' in body && typeof body.error === 'string' ? body.error : null) ??
21
+ `Request failed: ${res.status} ${res.statusText}`;
22
+ throw new Error(message);
15
23
  }
16
24
  return res.json();
17
25
  }
@@ -43,7 +51,7 @@ export class ApiHubClient {
43
51
  async getSupervisorChain(employeeId) {
44
52
  return this.request(`/employees/${encodeURIComponent(employeeId)}/supervisor-chain`);
45
53
  }
46
- /** Look up JDE number and employee data from email (with JDEService/CoreService fallback) */
54
+ /** Look up JDE number and employee data from email (with itime fallback) */
47
55
  async getJdeFromEmail(email) {
48
56
  return this.request(`/employees/jde-from-email/${encodeURIComponent(email)}`);
49
57
  }
@@ -56,17 +64,25 @@ export class ApiHubClient {
56
64
  }
57
65
  /** Send a chat completion request to the LLM */
58
66
  async chat(request) {
59
- const res = await fetch(`${this.baseUrl}/llm/chat`, {
60
- method: 'POST',
61
- headers: {
62
- 'x-api-key': this.apiKey,
63
- 'Content-Type': 'application/json',
64
- },
65
- body: JSON.stringify(request),
66
- });
67
+ let res;
68
+ try {
69
+ res = await fetch(`${this.baseUrl}/llm/chat`, {
70
+ method: 'POST',
71
+ headers: {
72
+ 'x-api-key': this.apiKey,
73
+ 'Content-Type': 'application/json',
74
+ },
75
+ body: JSON.stringify(request),
76
+ });
77
+ }
78
+ catch {
79
+ throw new Error(`APIHub unavailable: ${this.baseUrl}/llm/chat`);
80
+ }
67
81
  if (!res.ok) {
68
- const body = await res.json().catch(() => ({}));
69
- throw new Error(body.error ?? `Request failed: ${res.status}`);
82
+ const body = await res.json().catch(() => null);
83
+ const message = (body && typeof body === 'object' && 'error' in body && typeof body.error === 'string' ? body.error : null) ??
84
+ `Request failed: ${res.status} ${res.statusText}`;
85
+ throw new Error(message);
70
86
  }
71
87
  return res.json();
72
88
  }
@@ -94,6 +110,14 @@ export class ApiHubClient {
94
110
  async getCostcode(id) {
95
111
  return this.request(`/costcodes/${encodeURIComponent(id)}`);
96
112
  }
113
+ /** Get cost codes for a specific business unit, formatted for dropdown controls */
114
+ async getCostcodesDropdownByBu(businessUnitId) {
115
+ return this.request(`/costcodes/by-bu/${encodeURIComponent(businessUnitId)}/dropdown`);
116
+ }
117
+ /** Get cost codes for a specific business unit and pay type, formatted for dropdown controls */
118
+ async getCostcodesDropdownByBuAndPayType(businessUnitId, payTypeCode) {
119
+ return this.request(`/costcodes/by-bu/${encodeURIComponent(businessUnitId)}/by-paytype/${encodeURIComponent(payTypeCode)}/dropdown`);
120
+ }
97
121
  // -----------------------------------------------------------------------
98
122
  // Pay Types
99
123
  // -----------------------------------------------------------------------
@@ -115,6 +139,10 @@ export class ApiHubClient {
115
139
  async getWorkordersDropdown() {
116
140
  return this.request('/workorders/dropdown');
117
141
  }
142
+ /** Get work orders for a specific business unit, formatted for dropdown controls */
143
+ async getWorkordersDropdownByBu(businessUnitId) {
144
+ return this.request(`/workorders/by-bu/${encodeURIComponent(businessUnitId)}/dropdown`);
145
+ }
118
146
  async getWorkorder(id) {
119
147
  return this.request(`/workorders/${encodeURIComponent(id)}`);
120
148
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brownandroot/api",
3
- "version": "0.10.0",
3
+ "version": "0.12.0",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",