@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/index.js
CHANGED
|
@@ -1,12 +1,67 @@
|
|
|
1
|
+
export class ApiHubError extends Error {
|
|
2
|
+
status;
|
|
3
|
+
path;
|
|
4
|
+
url;
|
|
5
|
+
responseBody;
|
|
6
|
+
retriable;
|
|
7
|
+
service;
|
|
8
|
+
constructor(options) {
|
|
9
|
+
super(options.message);
|
|
10
|
+
this.name = 'ApiHubError';
|
|
11
|
+
this.status = options.status;
|
|
12
|
+
this.path = options.path;
|
|
13
|
+
this.url = options.url;
|
|
14
|
+
this.responseBody = options.responseBody;
|
|
15
|
+
this.retriable = options.retriable;
|
|
16
|
+
this.service = options.service ?? 'apihub';
|
|
17
|
+
}
|
|
18
|
+
}
|
|
1
19
|
export class ApiHubClient {
|
|
2
20
|
baseUrl;
|
|
3
21
|
apiKey;
|
|
4
22
|
cacheTtl;
|
|
23
|
+
timeoutMs;
|
|
24
|
+
retryCount;
|
|
25
|
+
onError;
|
|
5
26
|
cache = new Map();
|
|
6
27
|
constructor(options) {
|
|
7
28
|
this.baseUrl = options.baseUrl.replace(/\/+$/, '');
|
|
8
29
|
this.apiKey = options.apiKey;
|
|
9
30
|
this.cacheTtl = options.cacheTtl ?? 5 * 60 * 1000;
|
|
31
|
+
this.timeoutMs = options.timeoutMs ?? 10_000;
|
|
32
|
+
this.retryCount = options.retryCount ?? 2;
|
|
33
|
+
this.onError = options.onError;
|
|
34
|
+
}
|
|
35
|
+
isRetriableStatus(status) {
|
|
36
|
+
return status === 429 || status === 502 || status === 503 || status === 504;
|
|
37
|
+
}
|
|
38
|
+
createApiHubError(options) {
|
|
39
|
+
const error = new ApiHubError({ ...options, service: 'apihub' });
|
|
40
|
+
this.onError?.(error);
|
|
41
|
+
if (typeof window === 'undefined') {
|
|
42
|
+
console.error('[APIHubError]', {
|
|
43
|
+
status: error.status,
|
|
44
|
+
path: error.path,
|
|
45
|
+
url: error.url,
|
|
46
|
+
retriable: error.retriable,
|
|
47
|
+
responseBody: error.responseBody,
|
|
48
|
+
message: error.message,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
return error;
|
|
52
|
+
}
|
|
53
|
+
async fetchWithTimeout(url, init) {
|
|
54
|
+
const controller = new AbortController();
|
|
55
|
+
const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
56
|
+
try {
|
|
57
|
+
return await fetch(url, { ...init, signal: controller.signal });
|
|
58
|
+
}
|
|
59
|
+
finally {
|
|
60
|
+
clearTimeout(timeout);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async delay(ms) {
|
|
64
|
+
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
10
65
|
}
|
|
11
66
|
/** Clear all cached responses, or a specific path */
|
|
12
67
|
clearCache(path) {
|
|
@@ -32,22 +87,62 @@ export class ApiHubClient {
|
|
|
32
87
|
return data;
|
|
33
88
|
}
|
|
34
89
|
async request(path) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
res
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
90
|
+
const url = `${this.baseUrl}${path}`;
|
|
91
|
+
for (let attempt = 0; attempt <= this.retryCount; attempt++) {
|
|
92
|
+
let res;
|
|
93
|
+
try {
|
|
94
|
+
res = await this.fetchWithTimeout(url, {
|
|
95
|
+
headers: { 'x-api-key': this.apiKey },
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
const retriable = attempt < this.retryCount;
|
|
100
|
+
if (retriable) {
|
|
101
|
+
const jitter = Math.floor(Math.random() * 100);
|
|
102
|
+
await this.delay(150 * Math.pow(2, attempt) + jitter);
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
const message = error instanceof Error && error.name === 'AbortError'
|
|
106
|
+
? `APIHub request timed out after ${this.timeoutMs}ms`
|
|
107
|
+
: 'APIHub unavailable';
|
|
108
|
+
throw this.createApiHubError({
|
|
109
|
+
message,
|
|
110
|
+
status: null,
|
|
111
|
+
path,
|
|
112
|
+
url,
|
|
113
|
+
responseBody: null,
|
|
114
|
+
retriable: false,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
if (res.ok) {
|
|
118
|
+
return res.json();
|
|
119
|
+
}
|
|
45
120
|
const body = await res.json().catch(() => null);
|
|
121
|
+
const retriable = this.isRetriableStatus(res.status);
|
|
122
|
+
if (retriable && attempt < this.retryCount) {
|
|
123
|
+
const jitter = Math.floor(Math.random() * 100);
|
|
124
|
+
await this.delay(150 * Math.pow(2, attempt) + jitter);
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
46
127
|
const message = (body && typeof body === 'object' && 'error' in body && typeof body.error === 'string' ? body.error : null) ??
|
|
47
128
|
`Request failed: ${res.status} ${res.statusText}`;
|
|
48
|
-
throw
|
|
129
|
+
throw this.createApiHubError({
|
|
130
|
+
message,
|
|
131
|
+
status: res.status,
|
|
132
|
+
path,
|
|
133
|
+
url,
|
|
134
|
+
responseBody: body,
|
|
135
|
+
retriable,
|
|
136
|
+
});
|
|
49
137
|
}
|
|
50
|
-
|
|
138
|
+
throw this.createApiHubError({
|
|
139
|
+
message: 'APIHub request failed after retries',
|
|
140
|
+
status: null,
|
|
141
|
+
path,
|
|
142
|
+
url,
|
|
143
|
+
responseBody: null,
|
|
144
|
+
retriable: false,
|
|
145
|
+
});
|
|
51
146
|
}
|
|
52
147
|
/** Get all employees */
|
|
53
148
|
async getEmployees() {
|
|
@@ -333,3 +428,6 @@ export class ApiHubClient {
|
|
|
333
428
|
return this.request(`/jobtypejobsteps/${encodeURIComponent(id)}`);
|
|
334
429
|
}
|
|
335
430
|
}
|
|
431
|
+
export { employees, workorders, costcodes, paytypes, businessUnits, jobtypejobsteps, clearCache } from './cache.js';
|
|
432
|
+
export { llm } from './llm.remote.js';
|
|
433
|
+
export { rag } from './rag.remote.js';
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
export declare const
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
export declare const jobtypejobsteps: {
|
|
2
|
+
getAll: import("@sveltejs/kit").RemoteQueryFunction<void, import("./index.js").Jobtypejobstep[]>;
|
|
3
|
+
dropdown: import("@sveltejs/kit").RemoteQueryFunction<void, import("./index.js").DropdownOption[]>;
|
|
4
|
+
get: import("@sveltejs/kit").RemoteQueryFunction<string, import("./index.js").Jobtypejobstep | 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
|
-
|
|
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().getJobtypejobsteps());
|
|
20
|
+
const dropdown = query(async () => getClient().getJobtypejobstepsDropdown());
|
|
21
|
+
const get = query(z.string(), async (id) => asNullable(() => getClient().getJobtypejobstep(id)));
|
|
22
|
+
export const jobtypejobsteps = {
|
|
23
|
+
getAll,
|
|
24
|
+
dropdown,
|
|
25
|
+
get,
|
|
26
|
+
};
|
package/dist/llm.remote.d.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
export declare const
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
export declare const llm: {
|
|
2
|
+
getLogs: import("@sveltejs/kit").RemoteQueryFunction<void, import("./index.js").LlmLog[]>;
|
|
3
|
+
chat: import("@sveltejs/kit").RemoteCommand<{
|
|
4
|
+
user: string;
|
|
5
|
+
messages: {
|
|
6
|
+
role: "system" | "user" | "assistant";
|
|
7
|
+
content: string;
|
|
8
|
+
}[];
|
|
9
|
+
source: string;
|
|
10
|
+
function?: string | undefined;
|
|
11
|
+
temperature?: number | undefined;
|
|
12
|
+
maxTokens?: number | undefined;
|
|
13
|
+
}, Promise<import("./index.js").ChatResponse>>;
|
|
14
|
+
};
|
package/dist/llm.remote.js
CHANGED
|
@@ -13,5 +13,9 @@ const chatRequestSchema = z.object({
|
|
|
13
13
|
temperature: z.number().min(0).max(2).optional(),
|
|
14
14
|
maxTokens: z.number().int().positive().optional(),
|
|
15
15
|
});
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
const getLogs = query(async () => getClient().getLlmLogs());
|
|
17
|
+
const chat = command(chatRequestSchema, async (request) => getClient().chat(request));
|
|
18
|
+
export const llm = {
|
|
19
|
+
getLogs,
|
|
20
|
+
chat,
|
|
21
|
+
};
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
export declare const
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
export declare const paytypes: {
|
|
2
|
+
getAll: import("@sveltejs/kit").RemoteQueryFunction<void, import("./index.js").Paytype[]>;
|
|
3
|
+
dropdown: import("@sveltejs/kit").RemoteQueryFunction<void, import("./index.js").PaytypeDropdownOption[]>;
|
|
4
|
+
get: import("@sveltejs/kit").RemoteQueryFunction<string, import("./index.js").Paytype | null>;
|
|
5
|
+
};
|
package/dist/paytypes.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().getPaytypes());
|
|
20
|
+
const dropdown = query(async () => getClient().getPaytypesDropdown());
|
|
21
|
+
const get = query(z.string(), async (id) => asNullable(() => getClient().getPaytype(id)));
|
|
22
|
+
export const paytypes = {
|
|
23
|
+
getAll,
|
|
24
|
+
dropdown,
|
|
25
|
+
get,
|
|
26
|
+
};
|
package/dist/rag.remote.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
export declare const
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
export declare const rag: {
|
|
2
|
+
list: import("@sveltejs/kit").RemoteQueryFunction<void, import("./index.js").DocumentRecord[]>;
|
|
3
|
+
upload: import("@sveltejs/kit").RemoteCommand<{
|
|
4
|
+
fileName: string;
|
|
5
|
+
base64Content: string;
|
|
6
|
+
uploadedBy: string;
|
|
7
|
+
}, Promise<import("./index.js").DocumentRecord>>;
|
|
8
|
+
delete: import("@sveltejs/kit").RemoteCommand<number, Promise<void>>;
|
|
9
|
+
search: import("@sveltejs/kit").RemoteCommand<{
|
|
10
|
+
query: string;
|
|
11
|
+
topK?: number | undefined;
|
|
12
|
+
}, Promise<import("./index.js").SearchResult[]>>;
|
|
13
|
+
};
|
package/dist/rag.remote.js
CHANGED
|
@@ -10,7 +10,13 @@ const searchDocumentsSchema = z.object({
|
|
|
10
10
|
query: z.string().min(1),
|
|
11
11
|
topK: z.number().int().positive().optional(),
|
|
12
12
|
});
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
const list = query(async () => getClient().listDocuments());
|
|
14
|
+
const upload = command(uploadDocumentSchema, async ({ fileName, base64Content, uploadedBy }) => getClient().uploadDocument(fileName, base64Content, uploadedBy));
|
|
15
|
+
const remove = command(z.number().int().positive(), async (id) => getClient().deleteDocument(id));
|
|
16
|
+
const search = command(searchDocumentsSchema, async ({ query: q, topK }) => getClient().searchDocuments(q, topK));
|
|
17
|
+
export const rag = {
|
|
18
|
+
list,
|
|
19
|
+
upload,
|
|
20
|
+
delete: remove,
|
|
21
|
+
search,
|
|
22
|
+
};
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
export declare const
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
export declare const workorders: {
|
|
2
|
+
getAll: import("@sveltejs/kit").RemoteQueryFunction<void, import("./index.js").Workorder[]>;
|
|
3
|
+
dropdown: import("@sveltejs/kit").RemoteQueryFunction<void, import("./index.js").DropdownOption[]>;
|
|
4
|
+
get: import("@sveltejs/kit").RemoteQueryFunction<string, import("./index.js").Workorder | 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
|
-
|
|
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().getWorkorders());
|
|
20
|
+
const dropdown = query(async () => getClient().getWorkordersDropdown());
|
|
21
|
+
const get = query(z.string(), async (id) => asNullable(() => getClient().getWorkorder(id)));
|
|
22
|
+
export const workorders = {
|
|
23
|
+
getAll,
|
|
24
|
+
dropdown,
|
|
25
|
+
get,
|
|
26
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brownandroot/api",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -13,42 +13,6 @@
|
|
|
13
13
|
".": {
|
|
14
14
|
"types": "./dist/index.d.ts",
|
|
15
15
|
"default": "./dist/index.js"
|
|
16
|
-
},
|
|
17
|
-
"./cache": {
|
|
18
|
-
"types": "./dist/cache.d.ts",
|
|
19
|
-
"default": "./dist/cache.js"
|
|
20
|
-
},
|
|
21
|
-
"./employees": {
|
|
22
|
-
"types": "./dist/employees.remote.d.ts",
|
|
23
|
-
"default": "./dist/employees.remote.js"
|
|
24
|
-
},
|
|
25
|
-
"./businessUnits": {
|
|
26
|
-
"types": "./dist/businessUnits.remote.d.ts",
|
|
27
|
-
"default": "./dist/businessUnits.remote.js"
|
|
28
|
-
},
|
|
29
|
-
"./costcodes": {
|
|
30
|
-
"types": "./dist/costcodes.remote.d.ts",
|
|
31
|
-
"default": "./dist/costcodes.remote.js"
|
|
32
|
-
},
|
|
33
|
-
"./paytypes": {
|
|
34
|
-
"types": "./dist/paytypes.remote.d.ts",
|
|
35
|
-
"default": "./dist/paytypes.remote.js"
|
|
36
|
-
},
|
|
37
|
-
"./workorders": {
|
|
38
|
-
"types": "./dist/workorders.remote.d.ts",
|
|
39
|
-
"default": "./dist/workorders.remote.js"
|
|
40
|
-
},
|
|
41
|
-
"./jobtypejobsteps": {
|
|
42
|
-
"types": "./dist/jobtypejobsteps.remote.d.ts",
|
|
43
|
-
"default": "./dist/jobtypejobsteps.remote.js"
|
|
44
|
-
},
|
|
45
|
-
"./llm": {
|
|
46
|
-
"types": "./dist/llm.remote.d.ts",
|
|
47
|
-
"default": "./dist/llm.remote.js"
|
|
48
|
-
},
|
|
49
|
-
"./rag": {
|
|
50
|
-
"types": "./dist/rag.remote.d.ts",
|
|
51
|
-
"default": "./dist/rag.remote.js"
|
|
52
16
|
}
|
|
53
17
|
},
|
|
54
18
|
"files": [
|