nuabase 1.0.0 → 1.1.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 +21 -18
- package/dist/cjs/index.cjs +355 -80
- package/dist/esm/index.mjs +355 -80
- package/dist/types/__tests__/utils/sse.d.ts +12 -0
- package/dist/types/lib/api-client.d.ts +1 -1
- package/dist/types/lib/env.d.ts +1 -0
- package/dist/types/nua/cast_array/factory.d.ts +4 -0
- package/dist/types/nua/cast_array/request-validation.d.ts +1 -0
- package/dist/types/nua/cast_array/response-schema.d.ts +17 -0
- package/dist/types/nua/cast_array/types.d.ts +33 -0
- package/dist/types/nua/cast_value/factory.d.ts +4 -0
- package/dist/types/nua/cast_value/response-schema.d.ts +13 -0
- package/dist/types/nua/cast_value/types.d.ts +18 -0
- package/dist/types/nua/common/queued-response.d.ts +6 -0
- package/dist/types/nua/core.d.ts +12 -0
- package/dist/types/nua/get-request/index.d.ts +6 -0
- package/dist/types/nua/get-request/types.d.ts +34 -0
- package/dist/types/nua/index.d.ts +5 -0
- package/dist/types/nua.d.ts +3 -33
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -1,26 +1,25 @@
|
|
|
1
|
-
|
|
1
|
+
## Nuabase TypeScript SDK
|
|
2
2
|
|
|
3
|
-
Nuabase turns LLM prompts into type-safe functions in under five lines.
|
|
3
|
+
Nuabase turns LLM prompts into type-safe functions in under five lines of code. Set up your free account now at [Nuabase](https://nuabase.com).
|
|
4
|
+
|
|
5
|
+
With Nuabase, you write a prompt, specify the output schema, and get back a well-typed function. You can invoke it with input data, like any other code in your application, and receive data that matches the exact schema you specified.
|
|
4
6
|
|
|
5
7
|
Example use-cases:
|
|
6
|
-
* Enrich a list of food items with nutrition facts
|
|
7
|
-
* Tag sales leads with more details about the company
|
|
8
|
-
* Convert free-form instructions into precise order forms—directly inside your application.
|
|
9
8
|
|
|
10
|
-
|
|
9
|
+
- Provide free-form text input for faster filling of complex HTML forms
|
|
10
|
+
- Enrich a list of food items with nutrition facts
|
|
11
|
+
- Tag sales leads with more details about the company
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
Behind the scenes, Nuabase runs the LLM transformation as async jobs, and once ready, call your server API with the results using Webhooks. It can also stream the result directly to your front-end using SSE. You can also see all requests and responses as they happen in the [Nuabase Console](https://console.nuabase.com). All outputs are guaranteed to match the schema you specified.
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
One major reason I built Nuabase is the need for granular, row-level caching. For example, let's say you want to classify your bank transaction entries, and map them to your chart of accounts. With Nuabase's row-level caching, it will only send new entries to the LLM. Any specific entry that it has seen before will be returned from the cache. This also means you can make LLM requests multiple times with identical values, and after the first time, they will return immediately without needing to go through the LLM.
|
|
15
16
|
|
|
16
|
-
##
|
|
17
|
+
## Usage at a glance
|
|
17
18
|
|
|
18
19
|
**1. Input.** Start with the data you want to send to the LLM:
|
|
19
20
|
|
|
20
21
|
```ts
|
|
21
|
-
const leads = [
|
|
22
|
-
{ id: 'lead-101', notes: 'Growth-stage SaaS, ~80 employees, wants a demo.' },
|
|
23
|
-
];
|
|
22
|
+
const leads = [{ id: 'lead-101', notes: 'Growth-stage SaaS, ~80 employees, wants a demo.' }];
|
|
24
23
|
```
|
|
25
24
|
|
|
26
25
|
**2. Desired shape.** Describe the structure you expect back:
|
|
@@ -35,10 +34,12 @@ const LeadInsights = z.object({
|
|
|
35
34
|
**3. Declare the prompt.** Turn it into a typed function:
|
|
36
35
|
|
|
37
36
|
```ts
|
|
38
|
-
const classifyLeads = new Nua().
|
|
39
|
-
name: 'insights',
|
|
40
|
-
output: LeadInsights,
|
|
37
|
+
const classifyLeads = new Nua().createArrayFn({
|
|
41
38
|
prompt: 'Classify each lead with industry and company_size bucket.',
|
|
39
|
+
output: {
|
|
40
|
+
name: 'leadInsights',
|
|
41
|
+
schema: LeadInsights,
|
|
42
|
+
},
|
|
42
43
|
});
|
|
43
44
|
```
|
|
44
45
|
|
|
@@ -78,11 +79,13 @@ const LeadInsights = z.object({
|
|
|
78
79
|
recommended_follow_up: z.enum(['Call', 'Email', 'Event']),
|
|
79
80
|
});
|
|
80
81
|
|
|
81
|
-
const enrichLeads = nua.
|
|
82
|
-
name: 'leadInsights',
|
|
83
|
-
output: LeadInsights,
|
|
82
|
+
const enrichLeads = nua.createArrayFn({
|
|
84
83
|
prompt:
|
|
85
84
|
'Summarize each inbound lead by extracting company_name, industry, company_size bucket (SMB, Mid-market, Enterprise), and the recommended_follow_up channel (Call, Email, or Event) based on their notes.',
|
|
85
|
+
output: {
|
|
86
|
+
name: 'leadInsights',
|
|
87
|
+
schema: LeadInsights,
|
|
88
|
+
},
|
|
86
89
|
});
|
|
87
90
|
|
|
88
91
|
const rows = [
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
var zod = require('zod');
|
|
4
4
|
|
|
5
|
+
function resolveConfigValue(config, key, envVar) {
|
|
6
|
+
if (config[key]) return config[key];
|
|
7
|
+
const pe = globalThis.process;
|
|
8
|
+
const isNode = !!pe?.versions?.node;
|
|
9
|
+
if (isNode) {
|
|
10
|
+
return pe?.env?.[envVar];
|
|
11
|
+
}
|
|
12
|
+
return void 0;
|
|
13
|
+
}
|
|
14
|
+
|
|
5
15
|
async function parseErrorResponse(response, urlPath) {
|
|
6
16
|
const fallbackMessage = `Request to ${urlPath} failed with status ${response.status}${response.statusText ? ` ${response.statusText}` : ""}`;
|
|
7
17
|
let responseBody = "";
|
|
@@ -47,25 +57,29 @@ function getErrorMessageFromException(error) {
|
|
|
47
57
|
|
|
48
58
|
class NuabaseAPIClient {
|
|
49
59
|
constructor(config = {}) {
|
|
50
|
-
this.apiKey = config
|
|
51
|
-
this.baseUrl = config
|
|
60
|
+
this.apiKey = resolveConfigValue(config, "apiKey", "NUABASE_API_KEY") || "";
|
|
61
|
+
this.baseUrl = resolveConfigValue(config, "baseUrl", "NUABASE_API_URL") || "https://api.nuabase.com";
|
|
52
62
|
if (!this.apiKey) {
|
|
53
63
|
throw new Error(
|
|
54
64
|
"API key is required. Provide it via config.apiKey or NUABASE_API_KEY environment variable."
|
|
55
65
|
);
|
|
56
66
|
}
|
|
57
67
|
}
|
|
58
|
-
async request(urlPath, params) {
|
|
68
|
+
async request(method, urlPath, params) {
|
|
59
69
|
const url = `${this.baseUrl}/${urlPath}`;
|
|
60
70
|
let response;
|
|
71
|
+
const hasBody = method !== "GET" && params !== void 0;
|
|
72
|
+
const headers = {
|
|
73
|
+
Authorization: `Bearer ${this.apiKey}`
|
|
74
|
+
};
|
|
75
|
+
if (hasBody) {
|
|
76
|
+
headers["Content-Type"] = "application/json";
|
|
77
|
+
}
|
|
61
78
|
try {
|
|
62
79
|
response = await fetch(url, {
|
|
63
|
-
method
|
|
64
|
-
headers
|
|
65
|
-
|
|
66
|
-
Authorization: `Bearer ${this.apiKey}`
|
|
67
|
-
},
|
|
68
|
-
body: JSON.stringify(params)
|
|
80
|
+
method,
|
|
81
|
+
headers,
|
|
82
|
+
body: hasBody ? JSON.stringify(params) : void 0
|
|
69
83
|
});
|
|
70
84
|
} catch (e) {
|
|
71
85
|
return { error: `Error calling Nuabase API: ${getErrorMessageFromException(e)}` };
|
|
@@ -83,22 +97,46 @@ class NuabaseAPIClient {
|
|
|
83
97
|
}
|
|
84
98
|
}
|
|
85
99
|
|
|
86
|
-
const
|
|
100
|
+
const zs_NuaQueuedResponse = zod.z.object({
|
|
101
|
+
id: zod.z.string(),
|
|
102
|
+
sseUrl: zod.z.string().min(1)
|
|
103
|
+
}).strict();
|
|
104
|
+
|
|
105
|
+
const validateArrayRequestParams = (data, primaryKeyName) => {
|
|
106
|
+
if (!Array.isArray(data)) {
|
|
107
|
+
throw new Error("`data` must be an array of objects.");
|
|
108
|
+
}
|
|
109
|
+
if (!primaryKeyName || typeof primaryKeyName !== "string") {
|
|
110
|
+
throw new Error("`primaryKeyName` must be a non-empty string.");
|
|
111
|
+
}
|
|
112
|
+
data.forEach((item, index) => {
|
|
113
|
+
if (item === null || typeof item !== "object" || Array.isArray(item)) {
|
|
114
|
+
throw new Error(`data[${index}] must be a non-null object.`);
|
|
115
|
+
}
|
|
116
|
+
if (!(primaryKeyName in item)) {
|
|
117
|
+
throw new Error(`data[${index}] must contain property '${primaryKeyName}'.`);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const zs_ResponseRecord = (primaryKeyName, outputKey, outputSchema) => {
|
|
87
123
|
const primaryKeySchema = zod.z.any();
|
|
88
|
-
|
|
124
|
+
const shape = {
|
|
89
125
|
[primaryKeyName]: primaryKeySchema,
|
|
90
126
|
[outputKey]: outputSchema
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const zs_MapSuccessDataResult = (primaryKeyName, outputKey, outputSchema) => {
|
|
94
|
-
const recordSchema = zs_MapResponseRecord(primaryKeyName, outputKey, outputSchema);
|
|
95
|
-
return zod.z.array(recordSchema);
|
|
127
|
+
};
|
|
128
|
+
return zod.z.object(shape).strict();
|
|
96
129
|
};
|
|
97
|
-
const
|
|
98
|
-
const
|
|
130
|
+
const createNuaApiResponseCastArray = (primaryKeyName, outputKey, outputSchema) => {
|
|
131
|
+
const recordSchema = zs_ResponseRecord(
|
|
132
|
+
primaryKeyName,
|
|
133
|
+
outputKey,
|
|
134
|
+
outputSchema
|
|
135
|
+
);
|
|
136
|
+
const dataSchema = zod.z.array(recordSchema);
|
|
99
137
|
return zod.z.object({
|
|
100
138
|
llmRequestId: zod.z.string(),
|
|
101
|
-
kind: zod.z.literal("
|
|
139
|
+
kind: zod.z.literal("cast/array"),
|
|
102
140
|
data: dataSchema,
|
|
103
141
|
cacheHits: zod.z.number(),
|
|
104
142
|
rowsWithNoResults: zod.z.array(zod.z.string()),
|
|
@@ -106,72 +144,309 @@ const zs_MapRequestApiResponse_Success = (primaryKeyName, outputKey, outputSchem
|
|
|
106
144
|
isError: zod.z.optional(zod.z.literal(false))
|
|
107
145
|
}).strict();
|
|
108
146
|
};
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
147
|
+
const zs_NuaApiResponse_CastArray = createNuaApiResponseCastArray;
|
|
148
|
+
|
|
149
|
+
const zs_ArrayFnDef = zod.z.object({
|
|
150
|
+
prompt: zod.z.string(),
|
|
151
|
+
output: zod.z.object({
|
|
152
|
+
name: zod.z.string(),
|
|
153
|
+
schema: zod.z.custom(
|
|
154
|
+
(value) => value instanceof zod.z.ZodType,
|
|
155
|
+
"Expected a Zod schema"
|
|
156
|
+
)
|
|
157
|
+
})
|
|
158
|
+
});
|
|
159
|
+
const validateArrayFnDef = (fnDef) => {
|
|
160
|
+
const parsed = zs_ArrayFnDef.safeParse(fnDef);
|
|
161
|
+
if (!parsed.success) {
|
|
162
|
+
const message = zod.z.prettifyError(parsed.error);
|
|
163
|
+
throw new TypeError(`Invalid array function definition: ${message}`);
|
|
112
164
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
165
|
+
return parsed.data;
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
function addOriginalInputRows(inputRows, outputRows, primaryKeyName) {
|
|
169
|
+
const lookup = /* @__PURE__ */ new Map();
|
|
170
|
+
for (const row of inputRows) {
|
|
171
|
+
lookup.set(row[primaryKeyName], row);
|
|
172
|
+
}
|
|
173
|
+
return outputRows.map((row) => {
|
|
174
|
+
const primaryKeyValue = row[primaryKeyName];
|
|
175
|
+
const sourceRow = lookup.get(primaryKeyValue);
|
|
176
|
+
if (!sourceRow) {
|
|
177
|
+
throw new Error(
|
|
178
|
+
`Unable to locate source row for primary key "${String(primaryKeyValue)}" in cast array response.`
|
|
179
|
+
);
|
|
121
180
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
126
|
-
if (!(primaryKeyName in item)) {
|
|
127
|
-
throw new Error(`data[${index}] must contain property '${primaryKeyName}'.`);
|
|
128
|
-
}
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
map(fnDef) {
|
|
132
|
-
const client = this.apiClient;
|
|
133
|
-
const outputJsonSchema = zod.z.toJSONSchema(fnDef.output);
|
|
134
|
-
const makeRequest = async (path, data, primaryKeyName) => {
|
|
135
|
-
Nua.validateMapRequestParams(data, primaryKeyName);
|
|
136
|
-
const response = await client.request(path, {
|
|
137
|
-
input: {
|
|
138
|
-
prompt: fnDef.prompt,
|
|
139
|
-
data,
|
|
140
|
-
primaryKey: primaryKeyName
|
|
141
|
-
},
|
|
142
|
-
output: {
|
|
143
|
-
schema: outputJsonSchema,
|
|
144
|
-
name: fnDef.name
|
|
145
|
-
}
|
|
146
|
-
});
|
|
147
|
-
if (response && typeof response === "object" && "error" in response)
|
|
148
|
-
return { error: String(response.error), isError: true };
|
|
149
|
-
const outputKey = fnDef.name;
|
|
150
|
-
const successSchema = zs_MapRequestApiResponse_Success(primaryKeyName, outputKey, fnDef.output);
|
|
151
|
-
const parsedResponse = successSchema.safeParse(response);
|
|
152
|
-
if (!parsedResponse.success) {
|
|
153
|
-
const emsg = zod.z.prettifyError(parsedResponse.error);
|
|
154
|
-
return { error: `Invalid data received from Nuabase API: ${emsg}`, isError: true };
|
|
155
|
-
}
|
|
156
|
-
return {
|
|
157
|
-
isSuccess: true,
|
|
158
|
-
llmRequestId: parsedResponse.data.llmRequestId,
|
|
159
|
-
kind: parsedResponse.data.kind,
|
|
160
|
-
data: parsedResponse.data.data,
|
|
161
|
-
rowsWithNoResults: parsedResponse.data.rowsWithNoResults,
|
|
162
|
-
cacheHits: parsedResponse.data.cacheHits
|
|
163
|
-
};
|
|
181
|
+
return {
|
|
182
|
+
...row,
|
|
183
|
+
sourceRow
|
|
164
184
|
};
|
|
165
|
-
|
|
166
|
-
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
const toCastArrayApiRequest = (prompt, data, primaryKeyName, outputName, outputSchema) => ({
|
|
188
|
+
input: {
|
|
189
|
+
prompt,
|
|
190
|
+
data,
|
|
191
|
+
primaryKey: primaryKeyName
|
|
192
|
+
},
|
|
193
|
+
output: {
|
|
194
|
+
schema: outputSchema,
|
|
195
|
+
name: outputName
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
const createArrayFn = (client, inputFnDef) => {
|
|
199
|
+
const fnDef = validateArrayFnDef(inputFnDef);
|
|
200
|
+
const outputJsonSchema = zod.z.toJSONSchema(fnDef.output.schema);
|
|
201
|
+
const toNuabaseError = (response) => {
|
|
202
|
+
if (response && typeof response === "object" && "error" in response)
|
|
203
|
+
return { error: String(response.error), isError: true };
|
|
204
|
+
return void 0;
|
|
205
|
+
};
|
|
206
|
+
const baseFn = async (data, primaryKeyName) => {
|
|
207
|
+
validateArrayRequestParams(data, primaryKeyName);
|
|
208
|
+
const response = await client.request(
|
|
209
|
+
"POST",
|
|
210
|
+
"cast/array",
|
|
211
|
+
toCastArrayApiRequest(
|
|
212
|
+
fnDef.prompt,
|
|
213
|
+
data,
|
|
214
|
+
primaryKeyName,
|
|
215
|
+
fnDef.output.name,
|
|
216
|
+
outputJsonSchema
|
|
217
|
+
)
|
|
218
|
+
);
|
|
219
|
+
const error = toNuabaseError(response);
|
|
220
|
+
if (error) return error;
|
|
221
|
+
const parsedResponse = zs_NuaQueuedResponse.safeParse(response);
|
|
222
|
+
if (!parsedResponse.success) {
|
|
223
|
+
const emsg = zod.z.prettifyError(parsedResponse.error);
|
|
224
|
+
return { error: `Invalid queued response received from Nuabase API: ${emsg}`, isError: true };
|
|
225
|
+
}
|
|
226
|
+
return parsedResponse.data;
|
|
227
|
+
};
|
|
228
|
+
const nowFn = async (data, primaryKeyName) => {
|
|
229
|
+
validateArrayRequestParams(data, primaryKeyName);
|
|
230
|
+
const response = await client.request(
|
|
231
|
+
"POST",
|
|
232
|
+
"cast/array/now",
|
|
233
|
+
toCastArrayApiRequest(
|
|
234
|
+
fnDef.prompt,
|
|
235
|
+
data,
|
|
236
|
+
primaryKeyName,
|
|
237
|
+
fnDef.output.name,
|
|
238
|
+
outputJsonSchema
|
|
239
|
+
)
|
|
240
|
+
);
|
|
241
|
+
const error = toNuabaseError(response);
|
|
242
|
+
if (error) return error;
|
|
243
|
+
const outputKey = fnDef.output.name;
|
|
244
|
+
const successSchema = zs_NuaApiResponse_CastArray(primaryKeyName, outputKey, fnDef.output.schema);
|
|
245
|
+
const parsedResponse = successSchema.safeParse(response);
|
|
246
|
+
if (!parsedResponse.success) {
|
|
247
|
+
const emsg = zod.z.prettifyError(parsedResponse.error);
|
|
248
|
+
return { error: `Invalid data received from Nuabase API: ${emsg}`, isError: true };
|
|
249
|
+
}
|
|
250
|
+
return {
|
|
251
|
+
isSuccess: true,
|
|
252
|
+
llmRequestId: parsedResponse.data.llmRequestId,
|
|
253
|
+
kind: parsedResponse.data.kind,
|
|
254
|
+
data: addOriginalInputRows(
|
|
255
|
+
data,
|
|
256
|
+
parsedResponse.data.data,
|
|
257
|
+
primaryKeyName
|
|
258
|
+
),
|
|
259
|
+
rowsWithNoResults: parsedResponse.data.rowsWithNoResults,
|
|
260
|
+
cacheHits: parsedResponse.data.cacheHits
|
|
167
261
|
};
|
|
168
|
-
|
|
169
|
-
|
|
262
|
+
};
|
|
263
|
+
return Object.assign(baseFn, {
|
|
264
|
+
now: nowFn
|
|
265
|
+
});
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
const createNuaApiResponseCastValue = (outputKey, outputSchema) => {
|
|
269
|
+
return zod.z.object({
|
|
270
|
+
llmRequestId: zod.z.string(),
|
|
271
|
+
kind: zod.z.literal("cast/value"),
|
|
272
|
+
data: outputSchema,
|
|
273
|
+
isCacheHit: zod.z.boolean(),
|
|
274
|
+
isSuccess: zod.z.literal(true),
|
|
275
|
+
isError: zod.z.optional(zod.z.literal(false))
|
|
276
|
+
}).strict();
|
|
277
|
+
};
|
|
278
|
+
const zs_NuaApiResponse_CastValue = createNuaApiResponseCastValue;
|
|
279
|
+
|
|
280
|
+
const zs_ValueFnDef = zod.z.object({
|
|
281
|
+
prompt: zod.z.string(),
|
|
282
|
+
output: zod.z.object({
|
|
283
|
+
name: zod.z.string(),
|
|
284
|
+
schema: zod.z.custom(
|
|
285
|
+
(value) => value instanceof zod.z.ZodType,
|
|
286
|
+
"Expected a Zod schema for `output.schema`"
|
|
287
|
+
)
|
|
288
|
+
})
|
|
289
|
+
});
|
|
290
|
+
const validateValueFnDef = (fnDef) => {
|
|
291
|
+
const parsed = zs_ValueFnDef.safeParse(fnDef);
|
|
292
|
+
if (!parsed.success) {
|
|
293
|
+
const message = zod.z.prettifyError(parsed.error);
|
|
294
|
+
throw new TypeError(`Invalid value function definition: ${message}`);
|
|
295
|
+
}
|
|
296
|
+
return parsed.data;
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
const toCastValueApiRequest = (prompt, data, outputName, outputSchema) => ({
|
|
300
|
+
input: {
|
|
301
|
+
prompt,
|
|
302
|
+
data
|
|
303
|
+
},
|
|
304
|
+
output: {
|
|
305
|
+
schema: outputSchema,
|
|
306
|
+
name: outputName
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
const createValueFn = (client, inputFnDef) => {
|
|
310
|
+
const fnDef = validateValueFnDef(inputFnDef);
|
|
311
|
+
const outputJsonSchema = zod.z.toJSONSchema(fnDef.output.schema);
|
|
312
|
+
const toNuabaseError = (response) => {
|
|
313
|
+
if (response && typeof response === "object" && "error" in response)
|
|
314
|
+
return { error: String(response.error), isError: true };
|
|
315
|
+
return void 0;
|
|
316
|
+
};
|
|
317
|
+
const sendRequest = async (path, data) => client.request(
|
|
318
|
+
"POST",
|
|
319
|
+
path,
|
|
320
|
+
toCastValueApiRequest(fnDef.prompt, data, fnDef.output.name, outputJsonSchema)
|
|
321
|
+
);
|
|
322
|
+
const baseFn = async (data) => {
|
|
323
|
+
const response = await sendRequest("cast/value", data);
|
|
324
|
+
const error = toNuabaseError(response);
|
|
325
|
+
if (error) return error;
|
|
326
|
+
const parsedResponse = zs_NuaQueuedResponse.safeParse(response);
|
|
327
|
+
if (!parsedResponse.success) {
|
|
328
|
+
const emsg = zod.z.prettifyError(parsedResponse.error);
|
|
329
|
+
return { error: `Invalid queued response received from Nuabase API: ${emsg}`, isError: true };
|
|
330
|
+
}
|
|
331
|
+
return parsedResponse.data;
|
|
332
|
+
};
|
|
333
|
+
const nowFn = async (data) => {
|
|
334
|
+
const response = await sendRequest("cast/value/now", data);
|
|
335
|
+
const error = toNuabaseError(response);
|
|
336
|
+
if (error) return error;
|
|
337
|
+
const outputKey = fnDef.output.name;
|
|
338
|
+
const successSchema = zs_NuaApiResponse_CastValue(
|
|
339
|
+
outputKey,
|
|
340
|
+
fnDef.output.schema
|
|
341
|
+
);
|
|
342
|
+
const parsedResponse = successSchema.safeParse(response);
|
|
343
|
+
if (!parsedResponse.success) {
|
|
344
|
+
const emsg = zod.z.prettifyError(parsedResponse.error);
|
|
345
|
+
return { error: `Invalid data received from Nuabase API: ${emsg}`, isError: true };
|
|
346
|
+
}
|
|
347
|
+
return {
|
|
348
|
+
isSuccess: true,
|
|
349
|
+
llmRequestId: parsedResponse.data.llmRequestId,
|
|
350
|
+
kind: parsedResponse.data.kind,
|
|
351
|
+
data: parsedResponse.data.data,
|
|
352
|
+
isCacheHit: parsedResponse.data.isCacheHit
|
|
170
353
|
};
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
354
|
+
};
|
|
355
|
+
return Object.assign(baseFn, {
|
|
356
|
+
now: nowFn
|
|
357
|
+
});
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
const errorParseFailed = {
|
|
361
|
+
kind: "internal-error",
|
|
362
|
+
message: "Unable to parse stored LLM result"
|
|
363
|
+
};
|
|
364
|
+
const dateFromIso = zod.z.preprocess(
|
|
365
|
+
(value) => {
|
|
366
|
+
if (value == null) return null;
|
|
367
|
+
if (value instanceof Date) return value;
|
|
368
|
+
if (typeof value === "string") {
|
|
369
|
+
const parsed = new Date(value);
|
|
370
|
+
if (!Number.isNaN(parsed.getTime())) return parsed;
|
|
371
|
+
}
|
|
372
|
+
return zod.z.NEVER;
|
|
373
|
+
},
|
|
374
|
+
zod.z.union([zod.z.date(), zod.z.null()])
|
|
375
|
+
);
|
|
376
|
+
const mandatoryDateFromIso = zod.z.preprocess((value) => {
|
|
377
|
+
if (value instanceof Date) return value;
|
|
378
|
+
if (typeof value === "string") {
|
|
379
|
+
const parsed = new Date(value);
|
|
380
|
+
if (!Number.isNaN(parsed.getTime())) return parsed;
|
|
381
|
+
}
|
|
382
|
+
return zod.z.NEVER;
|
|
383
|
+
}, zod.z.date());
|
|
384
|
+
const apiResponseSchema = zod.z.object({
|
|
385
|
+
id: zod.z.string(),
|
|
386
|
+
requestType: zod.z.string(),
|
|
387
|
+
llmStatus: zod.z.union([
|
|
388
|
+
zod.z.literal("pending"),
|
|
389
|
+
zod.z.literal("processing"),
|
|
390
|
+
zod.z.literal("success"),
|
|
391
|
+
zod.z.literal("failed")
|
|
392
|
+
]),
|
|
393
|
+
sseStatus: zod.z.union([
|
|
394
|
+
zod.z.literal("n/a"),
|
|
395
|
+
zod.z.literal("pending"),
|
|
396
|
+
zod.z.literal("sent"),
|
|
397
|
+
zod.z.literal("failed")
|
|
398
|
+
]),
|
|
399
|
+
webhookStatus: zod.z.union([
|
|
400
|
+
zod.z.literal("n/a"),
|
|
401
|
+
zod.z.literal("pending"),
|
|
402
|
+
zod.z.literal("sent"),
|
|
403
|
+
zod.z.literal("failed")
|
|
404
|
+
]),
|
|
405
|
+
input: zod.z.object({
|
|
406
|
+
prompt: zod.z.union([zod.z.string(), zod.z.null()]),
|
|
407
|
+
data: zod.z.union([zod.z.string(), zod.z.null()]),
|
|
408
|
+
primaryKey: zod.z.union([zod.z.string(), zod.z.null()])
|
|
409
|
+
}),
|
|
410
|
+
output: zod.z.object({
|
|
411
|
+
name: zod.z.string(),
|
|
412
|
+
schema: zod.z.string(),
|
|
413
|
+
effectiveSchema: zod.z.string()
|
|
414
|
+
}),
|
|
415
|
+
result: zod.z.union([zod.z.record(zod.z.string(), zod.z.unknown()), zod.z.null()]).optional(),
|
|
416
|
+
error: zod.z.union([zod.z.string(), zod.z.null()]),
|
|
417
|
+
fullPrompt: zod.z.string(),
|
|
418
|
+
model: zod.z.string(),
|
|
419
|
+
provider: zod.z.string(),
|
|
420
|
+
startedAt: dateFromIso,
|
|
421
|
+
finishedAt: dateFromIso,
|
|
422
|
+
createdAt: mandatoryDateFromIso,
|
|
423
|
+
updatedAt: mandatoryDateFromIso
|
|
424
|
+
});
|
|
425
|
+
const isNuabaseError = (value) => Boolean(value && typeof value === "object" && "isError" in value && value.isError);
|
|
426
|
+
async function getRequest(client, llmRequestId) {
|
|
427
|
+
const response = await client.request("GET", `requests/${encodeURIComponent(llmRequestId)}`);
|
|
428
|
+
if (isNuabaseError(response)) {
|
|
429
|
+
return response;
|
|
430
|
+
}
|
|
431
|
+
const parsedResponse = apiResponseSchema.safeParse(response);
|
|
432
|
+
if (!parsedResponse.success) {
|
|
433
|
+
return errorParseFailed;
|
|
434
|
+
}
|
|
435
|
+
return parsedResponse.data;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
class Nua {
|
|
439
|
+
constructor(config) {
|
|
440
|
+
this.apiClient = new NuabaseAPIClient(config);
|
|
441
|
+
}
|
|
442
|
+
createArrayFn(fnDef) {
|
|
443
|
+
return createArrayFn(this.apiClient, fnDef);
|
|
444
|
+
}
|
|
445
|
+
createFn(fnDef) {
|
|
446
|
+
return createValueFn(this.apiClient, fnDef);
|
|
447
|
+
}
|
|
448
|
+
async getRequest(llmRequestId) {
|
|
449
|
+
return getRequest(this.apiClient, llmRequestId);
|
|
175
450
|
}
|
|
176
451
|
}
|
|
177
452
|
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
|
|
3
|
+
function resolveConfigValue(config, key, envVar) {
|
|
4
|
+
if (config[key]) return config[key];
|
|
5
|
+
const pe = globalThis.process;
|
|
6
|
+
const isNode = !!pe?.versions?.node;
|
|
7
|
+
if (isNode) {
|
|
8
|
+
return pe?.env?.[envVar];
|
|
9
|
+
}
|
|
10
|
+
return void 0;
|
|
11
|
+
}
|
|
12
|
+
|
|
3
13
|
async function parseErrorResponse(response, urlPath) {
|
|
4
14
|
const fallbackMessage = `Request to ${urlPath} failed with status ${response.status}${response.statusText ? ` ${response.statusText}` : ""}`;
|
|
5
15
|
let responseBody = "";
|
|
@@ -45,25 +55,29 @@ function getErrorMessageFromException(error) {
|
|
|
45
55
|
|
|
46
56
|
class NuabaseAPIClient {
|
|
47
57
|
constructor(config = {}) {
|
|
48
|
-
this.apiKey = config
|
|
49
|
-
this.baseUrl = config
|
|
58
|
+
this.apiKey = resolveConfigValue(config, "apiKey", "NUABASE_API_KEY") || "";
|
|
59
|
+
this.baseUrl = resolveConfigValue(config, "baseUrl", "NUABASE_API_URL") || "https://api.nuabase.com";
|
|
50
60
|
if (!this.apiKey) {
|
|
51
61
|
throw new Error(
|
|
52
62
|
"API key is required. Provide it via config.apiKey or NUABASE_API_KEY environment variable."
|
|
53
63
|
);
|
|
54
64
|
}
|
|
55
65
|
}
|
|
56
|
-
async request(urlPath, params) {
|
|
66
|
+
async request(method, urlPath, params) {
|
|
57
67
|
const url = `${this.baseUrl}/${urlPath}`;
|
|
58
68
|
let response;
|
|
69
|
+
const hasBody = method !== "GET" && params !== void 0;
|
|
70
|
+
const headers = {
|
|
71
|
+
Authorization: `Bearer ${this.apiKey}`
|
|
72
|
+
};
|
|
73
|
+
if (hasBody) {
|
|
74
|
+
headers["Content-Type"] = "application/json";
|
|
75
|
+
}
|
|
59
76
|
try {
|
|
60
77
|
response = await fetch(url, {
|
|
61
|
-
method
|
|
62
|
-
headers
|
|
63
|
-
|
|
64
|
-
Authorization: `Bearer ${this.apiKey}`
|
|
65
|
-
},
|
|
66
|
-
body: JSON.stringify(params)
|
|
78
|
+
method,
|
|
79
|
+
headers,
|
|
80
|
+
body: hasBody ? JSON.stringify(params) : void 0
|
|
67
81
|
});
|
|
68
82
|
} catch (e) {
|
|
69
83
|
return { error: `Error calling Nuabase API: ${getErrorMessageFromException(e)}` };
|
|
@@ -81,22 +95,46 @@ class NuabaseAPIClient {
|
|
|
81
95
|
}
|
|
82
96
|
}
|
|
83
97
|
|
|
84
|
-
const
|
|
98
|
+
const zs_NuaQueuedResponse = z.object({
|
|
99
|
+
id: z.string(),
|
|
100
|
+
sseUrl: z.string().min(1)
|
|
101
|
+
}).strict();
|
|
102
|
+
|
|
103
|
+
const validateArrayRequestParams = (data, primaryKeyName) => {
|
|
104
|
+
if (!Array.isArray(data)) {
|
|
105
|
+
throw new Error("`data` must be an array of objects.");
|
|
106
|
+
}
|
|
107
|
+
if (!primaryKeyName || typeof primaryKeyName !== "string") {
|
|
108
|
+
throw new Error("`primaryKeyName` must be a non-empty string.");
|
|
109
|
+
}
|
|
110
|
+
data.forEach((item, index) => {
|
|
111
|
+
if (item === null || typeof item !== "object" || Array.isArray(item)) {
|
|
112
|
+
throw new Error(`data[${index}] must be a non-null object.`);
|
|
113
|
+
}
|
|
114
|
+
if (!(primaryKeyName in item)) {
|
|
115
|
+
throw new Error(`data[${index}] must contain property '${primaryKeyName}'.`);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const zs_ResponseRecord = (primaryKeyName, outputKey, outputSchema) => {
|
|
85
121
|
const primaryKeySchema = z.any();
|
|
86
|
-
|
|
122
|
+
const shape = {
|
|
87
123
|
[primaryKeyName]: primaryKeySchema,
|
|
88
124
|
[outputKey]: outputSchema
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const zs_MapSuccessDataResult = (primaryKeyName, outputKey, outputSchema) => {
|
|
92
|
-
const recordSchema = zs_MapResponseRecord(primaryKeyName, outputKey, outputSchema);
|
|
93
|
-
return z.array(recordSchema);
|
|
125
|
+
};
|
|
126
|
+
return z.object(shape).strict();
|
|
94
127
|
};
|
|
95
|
-
const
|
|
96
|
-
const
|
|
128
|
+
const createNuaApiResponseCastArray = (primaryKeyName, outputKey, outputSchema) => {
|
|
129
|
+
const recordSchema = zs_ResponseRecord(
|
|
130
|
+
primaryKeyName,
|
|
131
|
+
outputKey,
|
|
132
|
+
outputSchema
|
|
133
|
+
);
|
|
134
|
+
const dataSchema = z.array(recordSchema);
|
|
97
135
|
return z.object({
|
|
98
136
|
llmRequestId: z.string(),
|
|
99
|
-
kind: z.literal("
|
|
137
|
+
kind: z.literal("cast/array"),
|
|
100
138
|
data: dataSchema,
|
|
101
139
|
cacheHits: z.number(),
|
|
102
140
|
rowsWithNoResults: z.array(z.string()),
|
|
@@ -104,72 +142,309 @@ const zs_MapRequestApiResponse_Success = (primaryKeyName, outputKey, outputSchem
|
|
|
104
142
|
isError: z.optional(z.literal(false))
|
|
105
143
|
}).strict();
|
|
106
144
|
};
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
145
|
+
const zs_NuaApiResponse_CastArray = createNuaApiResponseCastArray;
|
|
146
|
+
|
|
147
|
+
const zs_ArrayFnDef = z.object({
|
|
148
|
+
prompt: z.string(),
|
|
149
|
+
output: z.object({
|
|
150
|
+
name: z.string(),
|
|
151
|
+
schema: z.custom(
|
|
152
|
+
(value) => value instanceof z.ZodType,
|
|
153
|
+
"Expected a Zod schema"
|
|
154
|
+
)
|
|
155
|
+
})
|
|
156
|
+
});
|
|
157
|
+
const validateArrayFnDef = (fnDef) => {
|
|
158
|
+
const parsed = zs_ArrayFnDef.safeParse(fnDef);
|
|
159
|
+
if (!parsed.success) {
|
|
160
|
+
const message = z.prettifyError(parsed.error);
|
|
161
|
+
throw new TypeError(`Invalid array function definition: ${message}`);
|
|
110
162
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
163
|
+
return parsed.data;
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
function addOriginalInputRows(inputRows, outputRows, primaryKeyName) {
|
|
167
|
+
const lookup = /* @__PURE__ */ new Map();
|
|
168
|
+
for (const row of inputRows) {
|
|
169
|
+
lookup.set(row[primaryKeyName], row);
|
|
170
|
+
}
|
|
171
|
+
return outputRows.map((row) => {
|
|
172
|
+
const primaryKeyValue = row[primaryKeyName];
|
|
173
|
+
const sourceRow = lookup.get(primaryKeyValue);
|
|
174
|
+
if (!sourceRow) {
|
|
175
|
+
throw new Error(
|
|
176
|
+
`Unable to locate source row for primary key "${String(primaryKeyValue)}" in cast array response.`
|
|
177
|
+
);
|
|
119
178
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}
|
|
124
|
-
if (!(primaryKeyName in item)) {
|
|
125
|
-
throw new Error(`data[${index}] must contain property '${primaryKeyName}'.`);
|
|
126
|
-
}
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
map(fnDef) {
|
|
130
|
-
const client = this.apiClient;
|
|
131
|
-
const outputJsonSchema = z.toJSONSchema(fnDef.output);
|
|
132
|
-
const makeRequest = async (path, data, primaryKeyName) => {
|
|
133
|
-
Nua.validateMapRequestParams(data, primaryKeyName);
|
|
134
|
-
const response = await client.request(path, {
|
|
135
|
-
input: {
|
|
136
|
-
prompt: fnDef.prompt,
|
|
137
|
-
data,
|
|
138
|
-
primaryKey: primaryKeyName
|
|
139
|
-
},
|
|
140
|
-
output: {
|
|
141
|
-
schema: outputJsonSchema,
|
|
142
|
-
name: fnDef.name
|
|
143
|
-
}
|
|
144
|
-
});
|
|
145
|
-
if (response && typeof response === "object" && "error" in response)
|
|
146
|
-
return { error: String(response.error), isError: true };
|
|
147
|
-
const outputKey = fnDef.name;
|
|
148
|
-
const successSchema = zs_MapRequestApiResponse_Success(primaryKeyName, outputKey, fnDef.output);
|
|
149
|
-
const parsedResponse = successSchema.safeParse(response);
|
|
150
|
-
if (!parsedResponse.success) {
|
|
151
|
-
const emsg = z.prettifyError(parsedResponse.error);
|
|
152
|
-
return { error: `Invalid data received from Nuabase API: ${emsg}`, isError: true };
|
|
153
|
-
}
|
|
154
|
-
return {
|
|
155
|
-
isSuccess: true,
|
|
156
|
-
llmRequestId: parsedResponse.data.llmRequestId,
|
|
157
|
-
kind: parsedResponse.data.kind,
|
|
158
|
-
data: parsedResponse.data.data,
|
|
159
|
-
rowsWithNoResults: parsedResponse.data.rowsWithNoResults,
|
|
160
|
-
cacheHits: parsedResponse.data.cacheHits
|
|
161
|
-
};
|
|
179
|
+
return {
|
|
180
|
+
...row,
|
|
181
|
+
sourceRow
|
|
162
182
|
};
|
|
163
|
-
|
|
164
|
-
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
const toCastArrayApiRequest = (prompt, data, primaryKeyName, outputName, outputSchema) => ({
|
|
186
|
+
input: {
|
|
187
|
+
prompt,
|
|
188
|
+
data,
|
|
189
|
+
primaryKey: primaryKeyName
|
|
190
|
+
},
|
|
191
|
+
output: {
|
|
192
|
+
schema: outputSchema,
|
|
193
|
+
name: outputName
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
const createArrayFn = (client, inputFnDef) => {
|
|
197
|
+
const fnDef = validateArrayFnDef(inputFnDef);
|
|
198
|
+
const outputJsonSchema = z.toJSONSchema(fnDef.output.schema);
|
|
199
|
+
const toNuabaseError = (response) => {
|
|
200
|
+
if (response && typeof response === "object" && "error" in response)
|
|
201
|
+
return { error: String(response.error), isError: true };
|
|
202
|
+
return void 0;
|
|
203
|
+
};
|
|
204
|
+
const baseFn = async (data, primaryKeyName) => {
|
|
205
|
+
validateArrayRequestParams(data, primaryKeyName);
|
|
206
|
+
const response = await client.request(
|
|
207
|
+
"POST",
|
|
208
|
+
"cast/array",
|
|
209
|
+
toCastArrayApiRequest(
|
|
210
|
+
fnDef.prompt,
|
|
211
|
+
data,
|
|
212
|
+
primaryKeyName,
|
|
213
|
+
fnDef.output.name,
|
|
214
|
+
outputJsonSchema
|
|
215
|
+
)
|
|
216
|
+
);
|
|
217
|
+
const error = toNuabaseError(response);
|
|
218
|
+
if (error) return error;
|
|
219
|
+
const parsedResponse = zs_NuaQueuedResponse.safeParse(response);
|
|
220
|
+
if (!parsedResponse.success) {
|
|
221
|
+
const emsg = z.prettifyError(parsedResponse.error);
|
|
222
|
+
return { error: `Invalid queued response received from Nuabase API: ${emsg}`, isError: true };
|
|
223
|
+
}
|
|
224
|
+
return parsedResponse.data;
|
|
225
|
+
};
|
|
226
|
+
const nowFn = async (data, primaryKeyName) => {
|
|
227
|
+
validateArrayRequestParams(data, primaryKeyName);
|
|
228
|
+
const response = await client.request(
|
|
229
|
+
"POST",
|
|
230
|
+
"cast/array/now",
|
|
231
|
+
toCastArrayApiRequest(
|
|
232
|
+
fnDef.prompt,
|
|
233
|
+
data,
|
|
234
|
+
primaryKeyName,
|
|
235
|
+
fnDef.output.name,
|
|
236
|
+
outputJsonSchema
|
|
237
|
+
)
|
|
238
|
+
);
|
|
239
|
+
const error = toNuabaseError(response);
|
|
240
|
+
if (error) return error;
|
|
241
|
+
const outputKey = fnDef.output.name;
|
|
242
|
+
const successSchema = zs_NuaApiResponse_CastArray(primaryKeyName, outputKey, fnDef.output.schema);
|
|
243
|
+
const parsedResponse = successSchema.safeParse(response);
|
|
244
|
+
if (!parsedResponse.success) {
|
|
245
|
+
const emsg = z.prettifyError(parsedResponse.error);
|
|
246
|
+
return { error: `Invalid data received from Nuabase API: ${emsg}`, isError: true };
|
|
247
|
+
}
|
|
248
|
+
return {
|
|
249
|
+
isSuccess: true,
|
|
250
|
+
llmRequestId: parsedResponse.data.llmRequestId,
|
|
251
|
+
kind: parsedResponse.data.kind,
|
|
252
|
+
data: addOriginalInputRows(
|
|
253
|
+
data,
|
|
254
|
+
parsedResponse.data.data,
|
|
255
|
+
primaryKeyName
|
|
256
|
+
),
|
|
257
|
+
rowsWithNoResults: parsedResponse.data.rowsWithNoResults,
|
|
258
|
+
cacheHits: parsedResponse.data.cacheHits
|
|
165
259
|
};
|
|
166
|
-
|
|
167
|
-
|
|
260
|
+
};
|
|
261
|
+
return Object.assign(baseFn, {
|
|
262
|
+
now: nowFn
|
|
263
|
+
});
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
const createNuaApiResponseCastValue = (outputKey, outputSchema) => {
|
|
267
|
+
return z.object({
|
|
268
|
+
llmRequestId: z.string(),
|
|
269
|
+
kind: z.literal("cast/value"),
|
|
270
|
+
data: outputSchema,
|
|
271
|
+
isCacheHit: z.boolean(),
|
|
272
|
+
isSuccess: z.literal(true),
|
|
273
|
+
isError: z.optional(z.literal(false))
|
|
274
|
+
}).strict();
|
|
275
|
+
};
|
|
276
|
+
const zs_NuaApiResponse_CastValue = createNuaApiResponseCastValue;
|
|
277
|
+
|
|
278
|
+
const zs_ValueFnDef = z.object({
|
|
279
|
+
prompt: z.string(),
|
|
280
|
+
output: z.object({
|
|
281
|
+
name: z.string(),
|
|
282
|
+
schema: z.custom(
|
|
283
|
+
(value) => value instanceof z.ZodType,
|
|
284
|
+
"Expected a Zod schema for `output.schema`"
|
|
285
|
+
)
|
|
286
|
+
})
|
|
287
|
+
});
|
|
288
|
+
const validateValueFnDef = (fnDef) => {
|
|
289
|
+
const parsed = zs_ValueFnDef.safeParse(fnDef);
|
|
290
|
+
if (!parsed.success) {
|
|
291
|
+
const message = z.prettifyError(parsed.error);
|
|
292
|
+
throw new TypeError(`Invalid value function definition: ${message}`);
|
|
293
|
+
}
|
|
294
|
+
return parsed.data;
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
const toCastValueApiRequest = (prompt, data, outputName, outputSchema) => ({
|
|
298
|
+
input: {
|
|
299
|
+
prompt,
|
|
300
|
+
data
|
|
301
|
+
},
|
|
302
|
+
output: {
|
|
303
|
+
schema: outputSchema,
|
|
304
|
+
name: outputName
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
const createValueFn = (client, inputFnDef) => {
|
|
308
|
+
const fnDef = validateValueFnDef(inputFnDef);
|
|
309
|
+
const outputJsonSchema = z.toJSONSchema(fnDef.output.schema);
|
|
310
|
+
const toNuabaseError = (response) => {
|
|
311
|
+
if (response && typeof response === "object" && "error" in response)
|
|
312
|
+
return { error: String(response.error), isError: true };
|
|
313
|
+
return void 0;
|
|
314
|
+
};
|
|
315
|
+
const sendRequest = async (path, data) => client.request(
|
|
316
|
+
"POST",
|
|
317
|
+
path,
|
|
318
|
+
toCastValueApiRequest(fnDef.prompt, data, fnDef.output.name, outputJsonSchema)
|
|
319
|
+
);
|
|
320
|
+
const baseFn = async (data) => {
|
|
321
|
+
const response = await sendRequest("cast/value", data);
|
|
322
|
+
const error = toNuabaseError(response);
|
|
323
|
+
if (error) return error;
|
|
324
|
+
const parsedResponse = zs_NuaQueuedResponse.safeParse(response);
|
|
325
|
+
if (!parsedResponse.success) {
|
|
326
|
+
const emsg = z.prettifyError(parsedResponse.error);
|
|
327
|
+
return { error: `Invalid queued response received from Nuabase API: ${emsg}`, isError: true };
|
|
328
|
+
}
|
|
329
|
+
return parsedResponse.data;
|
|
330
|
+
};
|
|
331
|
+
const nowFn = async (data) => {
|
|
332
|
+
const response = await sendRequest("cast/value/now", data);
|
|
333
|
+
const error = toNuabaseError(response);
|
|
334
|
+
if (error) return error;
|
|
335
|
+
const outputKey = fnDef.output.name;
|
|
336
|
+
const successSchema = zs_NuaApiResponse_CastValue(
|
|
337
|
+
outputKey,
|
|
338
|
+
fnDef.output.schema
|
|
339
|
+
);
|
|
340
|
+
const parsedResponse = successSchema.safeParse(response);
|
|
341
|
+
if (!parsedResponse.success) {
|
|
342
|
+
const emsg = z.prettifyError(parsedResponse.error);
|
|
343
|
+
return { error: `Invalid data received from Nuabase API: ${emsg}`, isError: true };
|
|
344
|
+
}
|
|
345
|
+
return {
|
|
346
|
+
isSuccess: true,
|
|
347
|
+
llmRequestId: parsedResponse.data.llmRequestId,
|
|
348
|
+
kind: parsedResponse.data.kind,
|
|
349
|
+
data: parsedResponse.data.data,
|
|
350
|
+
isCacheHit: parsedResponse.data.isCacheHit
|
|
168
351
|
};
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
352
|
+
};
|
|
353
|
+
return Object.assign(baseFn, {
|
|
354
|
+
now: nowFn
|
|
355
|
+
});
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
const errorParseFailed = {
|
|
359
|
+
kind: "internal-error",
|
|
360
|
+
message: "Unable to parse stored LLM result"
|
|
361
|
+
};
|
|
362
|
+
const dateFromIso = z.preprocess(
|
|
363
|
+
(value) => {
|
|
364
|
+
if (value == null) return null;
|
|
365
|
+
if (value instanceof Date) return value;
|
|
366
|
+
if (typeof value === "string") {
|
|
367
|
+
const parsed = new Date(value);
|
|
368
|
+
if (!Number.isNaN(parsed.getTime())) return parsed;
|
|
369
|
+
}
|
|
370
|
+
return z.NEVER;
|
|
371
|
+
},
|
|
372
|
+
z.union([z.date(), z.null()])
|
|
373
|
+
);
|
|
374
|
+
const mandatoryDateFromIso = z.preprocess((value) => {
|
|
375
|
+
if (value instanceof Date) return value;
|
|
376
|
+
if (typeof value === "string") {
|
|
377
|
+
const parsed = new Date(value);
|
|
378
|
+
if (!Number.isNaN(parsed.getTime())) return parsed;
|
|
379
|
+
}
|
|
380
|
+
return z.NEVER;
|
|
381
|
+
}, z.date());
|
|
382
|
+
const apiResponseSchema = z.object({
|
|
383
|
+
id: z.string(),
|
|
384
|
+
requestType: z.string(),
|
|
385
|
+
llmStatus: z.union([
|
|
386
|
+
z.literal("pending"),
|
|
387
|
+
z.literal("processing"),
|
|
388
|
+
z.literal("success"),
|
|
389
|
+
z.literal("failed")
|
|
390
|
+
]),
|
|
391
|
+
sseStatus: z.union([
|
|
392
|
+
z.literal("n/a"),
|
|
393
|
+
z.literal("pending"),
|
|
394
|
+
z.literal("sent"),
|
|
395
|
+
z.literal("failed")
|
|
396
|
+
]),
|
|
397
|
+
webhookStatus: z.union([
|
|
398
|
+
z.literal("n/a"),
|
|
399
|
+
z.literal("pending"),
|
|
400
|
+
z.literal("sent"),
|
|
401
|
+
z.literal("failed")
|
|
402
|
+
]),
|
|
403
|
+
input: z.object({
|
|
404
|
+
prompt: z.union([z.string(), z.null()]),
|
|
405
|
+
data: z.union([z.string(), z.null()]),
|
|
406
|
+
primaryKey: z.union([z.string(), z.null()])
|
|
407
|
+
}),
|
|
408
|
+
output: z.object({
|
|
409
|
+
name: z.string(),
|
|
410
|
+
schema: z.string(),
|
|
411
|
+
effectiveSchema: z.string()
|
|
412
|
+
}),
|
|
413
|
+
result: z.union([z.record(z.string(), z.unknown()), z.null()]).optional(),
|
|
414
|
+
error: z.union([z.string(), z.null()]),
|
|
415
|
+
fullPrompt: z.string(),
|
|
416
|
+
model: z.string(),
|
|
417
|
+
provider: z.string(),
|
|
418
|
+
startedAt: dateFromIso,
|
|
419
|
+
finishedAt: dateFromIso,
|
|
420
|
+
createdAt: mandatoryDateFromIso,
|
|
421
|
+
updatedAt: mandatoryDateFromIso
|
|
422
|
+
});
|
|
423
|
+
const isNuabaseError = (value) => Boolean(value && typeof value === "object" && "isError" in value && value.isError);
|
|
424
|
+
async function getRequest(client, llmRequestId) {
|
|
425
|
+
const response = await client.request("GET", `requests/${encodeURIComponent(llmRequestId)}`);
|
|
426
|
+
if (isNuabaseError(response)) {
|
|
427
|
+
return response;
|
|
428
|
+
}
|
|
429
|
+
const parsedResponse = apiResponseSchema.safeParse(response);
|
|
430
|
+
if (!parsedResponse.success) {
|
|
431
|
+
return errorParseFailed;
|
|
432
|
+
}
|
|
433
|
+
return parsedResponse.data;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
class Nua {
|
|
437
|
+
constructor(config) {
|
|
438
|
+
this.apiClient = new NuabaseAPIClient(config);
|
|
439
|
+
}
|
|
440
|
+
createArrayFn(fnDef) {
|
|
441
|
+
return createArrayFn(this.apiClient, fnDef);
|
|
442
|
+
}
|
|
443
|
+
createFn(fnDef) {
|
|
444
|
+
return createValueFn(this.apiClient, fnDef);
|
|
445
|
+
}
|
|
446
|
+
async getRequest(llmRequestId) {
|
|
447
|
+
return getRequest(this.apiClient, llmRequestId);
|
|
173
448
|
}
|
|
174
449
|
}
|
|
175
450
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import z from 'zod';
|
|
2
|
+
export declare const processedSchema: z.ZodObject<{
|
|
3
|
+
processed_id: z.ZodString;
|
|
4
|
+
}, z.core.$strip>;
|
|
5
|
+
export declare const sseResponseSchema: z.ZodObject<{
|
|
6
|
+
isSuccess: z.ZodLiteral<true>;
|
|
7
|
+
llmRequestId: z.ZodString;
|
|
8
|
+
kind: z.ZodLiteral<"cast/value">;
|
|
9
|
+
data: z.ZodUnknown;
|
|
10
|
+
isCacheHit: z.ZodOptional<z.ZodBoolean>;
|
|
11
|
+
}, z.core.$loose>;
|
|
12
|
+
export declare const waitForSuccessfulSseMessage: (sseUrl: string, timeoutMs?: number) => Promise<Record<string, unknown>>;
|
|
@@ -7,5 +7,5 @@ export declare class NuabaseAPIClient {
|
|
|
7
7
|
private readonly apiKey;
|
|
8
8
|
private readonly baseUrl;
|
|
9
9
|
constructor(config?: NuabaseConfig);
|
|
10
|
-
request(urlPath: string, params
|
|
10
|
+
request(method: 'GET' | 'POST', urlPath: string, params?: object): Promise<NuabaseError | unknown>;
|
|
11
11
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function resolveConfigValue<T extends Record<string, any>>(config: T, key: keyof T, envVar: string): string | undefined;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { NuabaseAPIClient } from '../../lib/api-client';
|
|
2
|
+
import { ArrayFn, ArrayFnDef } from './types';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
export declare const createArrayFn: <OutputName extends string, OutputZodSchema extends z.ZodTypeAny>(client: NuabaseAPIClient, inputFnDef: ArrayFnDef<OutputName, OutputZodSchema>) => ArrayFn<OutputZodSchema, OutputName>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const validateArrayRequestParams: (data: unknown, primaryKeyName: unknown) => void;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export type UserDataPKValue = string | number;
|
|
3
|
+
export type PrimaryKeyedInputRecord<PrimaryKeyName extends string> = Record<PrimaryKeyName, UserDataPKValue> & Record<string, unknown>;
|
|
4
|
+
type ResponseRow<OutputZodSchema extends z.ZodTypeAny, OutputName extends string, PrimaryKeyName extends string, InputRecord extends PrimaryKeyedInputRecord<PrimaryKeyName>> = Pick<InputRecord, PrimaryKeyName> & Record<OutputName, z.infer<OutputZodSchema>>;
|
|
5
|
+
type NuaApiResponseShape<OutputZodSchema extends z.ZodTypeAny, OutputName extends string, PrimaryKeyName extends string, InputRecord extends PrimaryKeyedInputRecord<PrimaryKeyName>> = {
|
|
6
|
+
llmRequestId: string;
|
|
7
|
+
kind: 'cast/array';
|
|
8
|
+
data: Array<ResponseRow<OutputZodSchema, OutputName, PrimaryKeyName, InputRecord>>;
|
|
9
|
+
cacheHits: number;
|
|
10
|
+
rowsWithNoResults: UserDataPKValue[];
|
|
11
|
+
isSuccess: true;
|
|
12
|
+
isError?: false;
|
|
13
|
+
};
|
|
14
|
+
type NuaApiResponseCastArrayBuilder = <OutputZodSchema extends z.ZodTypeAny, OutputName extends string, PrimaryKeyName extends string, InputRecord extends PrimaryKeyedInputRecord<PrimaryKeyName>>(primaryKeyName: PrimaryKeyName, outputKey: OutputName, outputSchema: OutputZodSchema) => z.ZodType<NuaApiResponseShape<OutputZodSchema, OutputName, PrimaryKeyName, InputRecord>>;
|
|
15
|
+
export declare const zs_NuaApiResponse_CastArray: NuaApiResponseCastArrayBuilder;
|
|
16
|
+
export type NuaApiResponse_CastArray<OutputZodSchema extends z.ZodTypeAny, OutputName extends string, PrimaryKeyName extends string, InputRecord extends PrimaryKeyedInputRecord<PrimaryKeyName>> = z.infer<ReturnType<typeof zs_NuaApiResponse_CastArray<OutputZodSchema, OutputName, PrimaryKeyName, InputRecord>>>;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { NuabaseError } from '../../lib/error-response';
|
|
2
|
+
import { NuaQueuedResponse } from '../common/queued-response';
|
|
3
|
+
import type { NuaApiResponse_CastArray, PrimaryKeyedInputRecord } from './response-schema';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
export type ArrayFnDef<OutputName extends string, OutputZodSchema extends z.ZodTypeAny> = {
|
|
6
|
+
prompt: string;
|
|
7
|
+
output: {
|
|
8
|
+
name: OutputName;
|
|
9
|
+
schema: OutputZodSchema;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
export declare const validateArrayFnDef: <OutputName extends string, OutputZodSchema extends z.ZodTypeAny>(fnDef: ArrayFnDef<OutputName, OutputZodSchema>) => ArrayFnDef<OutputName, OutputZodSchema>;
|
|
13
|
+
type CastArraySuccessFromApi<OutputZodSchema extends z.ZodTypeAny, OutputName extends string, PrimaryKeyName extends string, InputRecord extends PrimaryKeyedInputRecord<PrimaryKeyName>> = NuaApiResponse_CastArray<OutputZodSchema, OutputName, PrimaryKeyName, InputRecord>;
|
|
14
|
+
type CastArraySourceRowAugmentation<PrimaryKeyName extends string, InputRecord extends PrimaryKeyedInputRecord<PrimaryKeyName>> = {
|
|
15
|
+
/**
|
|
16
|
+
* SDK-added field containing the full input row for convenience; not returned by the API.
|
|
17
|
+
*/
|
|
18
|
+
sourceRow: InputRecord;
|
|
19
|
+
};
|
|
20
|
+
type CastArraySuccessRowWithSource<OutputZodSchema extends z.ZodTypeAny, OutputName extends string, PrimaryKeyName extends string, InputRecord extends PrimaryKeyedInputRecord<PrimaryKeyName>> = CastArraySuccessFromApi<OutputZodSchema, OutputName, PrimaryKeyName, InputRecord>['data'][number] & CastArraySourceRowAugmentation<PrimaryKeyName, InputRecord>;
|
|
21
|
+
export type CastArraySuccessWithSource<OutputZodSchema extends z.ZodTypeAny, OutputName extends string, PrimaryKeyName extends string, InputRecord extends PrimaryKeyedInputRecord<PrimaryKeyName>> = Omit<CastArraySuccessFromApi<OutputZodSchema, OutputName, PrimaryKeyName, InputRecord>, 'data'> & {
|
|
22
|
+
/**
|
|
23
|
+
* Each row mirrors the API payload and includes the SDK-provided `sourceRow`.
|
|
24
|
+
*/
|
|
25
|
+
data: CastArraySuccessRowWithSource<OutputZodSchema, OutputName, PrimaryKeyName, InputRecord>[];
|
|
26
|
+
};
|
|
27
|
+
export type ArrayFnResult<OutputZodSchema extends z.ZodTypeAny, OutputName extends string, PrimaryKeyName extends string, InputRecord extends PrimaryKeyedInputRecord<PrimaryKeyName>> = NuabaseError | CastArraySuccessWithSource<OutputZodSchema, OutputName, PrimaryKeyName, InputRecord>;
|
|
28
|
+
export type ArrayFnQueuedResult = NuabaseError | NuaQueuedResponse;
|
|
29
|
+
export type ArrayFn<OutputZodSchema extends z.ZodTypeAny, OutputName extends string> = {
|
|
30
|
+
<PrimaryKeyName extends string, InputRecord extends PrimaryKeyedInputRecord<PrimaryKeyName>>(data: InputRecord[], primaryKeyName: PrimaryKeyName): Promise<ArrayFnQueuedResult>;
|
|
31
|
+
now: <PrimaryKeyName extends string, InputRecord extends PrimaryKeyedInputRecord<PrimaryKeyName>>(data: InputRecord[], primaryKeyName: PrimaryKeyName) => Promise<ArrayFnResult<OutputZodSchema, OutputName, PrimaryKeyName, InputRecord>>;
|
|
32
|
+
};
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { NuabaseAPIClient } from '../../lib/api-client';
|
|
2
|
+
import { ValueFn, ValueFnDef } from './types';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
export declare const createValueFn: <OutputName extends string, OutputZodSchema extends z.ZodTypeAny>(client: NuabaseAPIClient, inputFnDef: ValueFnDef<OutputName, OutputZodSchema>) => ValueFn<OutputZodSchema, OutputName>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
type NuaApiResponseShape<OutputZodSchema extends z.ZodTypeAny> = {
|
|
3
|
+
llmRequestId: string;
|
|
4
|
+
kind: 'cast/value';
|
|
5
|
+
data: z.infer<OutputZodSchema>;
|
|
6
|
+
isCacheHit: boolean;
|
|
7
|
+
isSuccess: true;
|
|
8
|
+
isError?: false;
|
|
9
|
+
};
|
|
10
|
+
type NuaApiResponseCastValueBuilder = <OutputZodSchema extends z.ZodTypeAny, OutputName extends string>(outputKey: OutputName, outputSchema: OutputZodSchema) => z.ZodType<NuaApiResponseShape<OutputZodSchema>>;
|
|
11
|
+
export declare const zs_NuaApiResponse_CastValue: NuaApiResponseCastValueBuilder;
|
|
12
|
+
export type NuaApiResponse_CastValue<OutputZodSchema extends z.ZodTypeAny, OutputName extends string> = z.infer<ReturnType<typeof zs_NuaApiResponse_CastValue<OutputZodSchema, OutputName>>>;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { NuabaseError } from '../../lib/error-response';
|
|
2
|
+
import { NuaQueuedResponse } from '../common/queued-response';
|
|
3
|
+
import { NuaApiResponse_CastValue } from './response-schema';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
export type ValueFnDef<OutputName extends string, OutputZodSchema extends z.ZodTypeAny> = {
|
|
6
|
+
prompt: string;
|
|
7
|
+
output: {
|
|
8
|
+
name: OutputName;
|
|
9
|
+
schema: OutputZodSchema;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
export declare const validateValueFnDef: <OutputName extends string, OutputZodSchema extends z.ZodTypeAny>(fnDef: ValueFnDef<OutputName, OutputZodSchema>) => ValueFnDef<OutputName, OutputZodSchema>;
|
|
13
|
+
export type ValueFnResult<OutputZodSchema extends z.ZodTypeAny, OutputName extends string> = NuabaseError | NuaApiResponse_CastValue<OutputZodSchema, OutputName>;
|
|
14
|
+
export type ValueFnQueuedResult = NuabaseError | NuaQueuedResponse;
|
|
15
|
+
export type ValueFn<OutputZodSchema extends z.ZodTypeAny, OutputName extends string> = {
|
|
16
|
+
(data: unknown): Promise<ValueFnQueuedResult>;
|
|
17
|
+
now: (data: unknown) => Promise<ValueFnResult<OutputZodSchema, OutputName>>;
|
|
18
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { NuabaseAPIClient, NuabaseConfig } from '../lib/api-client';
|
|
2
|
+
import { ArrayFn, ArrayFnDef } from './cast_array/types';
|
|
3
|
+
import { ValueFn, ValueFnDef } from './cast_value/types';
|
|
4
|
+
import { GetRequestResult } from './get-request';
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
export declare class Nua {
|
|
7
|
+
apiClient: NuabaseAPIClient;
|
|
8
|
+
constructor(config?: NuabaseConfig);
|
|
9
|
+
createArrayFn<OutputName extends string, OutputZodSchema extends z.ZodTypeAny>(fnDef: ArrayFnDef<OutputName, OutputZodSchema>): ArrayFn<OutputZodSchema, OutputName>;
|
|
10
|
+
createFn<OutputName extends string, OutputZodSchema extends z.ZodTypeAny>(fnDef: ValueFnDef<OutputName, OutputZodSchema>): ValueFn<OutputZodSchema, OutputName>;
|
|
11
|
+
getRequest(llmRequestId: string): Promise<GetRequestResult>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { NuabaseAPIClient } from '../../lib/api-client';
|
|
2
|
+
import { NuabaseError } from '../../lib/error-response';
|
|
3
|
+
import { ApiResponseLlmRequest, NuaInternalError } from './types';
|
|
4
|
+
export type GetRequestResult = ApiResponseLlmRequest | NuaInternalError | NuabaseError;
|
|
5
|
+
export declare function getRequest(client: NuabaseAPIClient, llmRequestId: string): Promise<GetRequestResult>;
|
|
6
|
+
export type { ApiResponseLlmRequest, LlmRequestStatus, NuaInternalError, SseRequestStatus, WebhookRequestStatus, } from './types';
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export type LlmRequestType = string;
|
|
2
|
+
export type LlmRequestStatus = 'pending' | 'processing' | 'success' | 'failed';
|
|
3
|
+
export type SseRequestStatus = 'n/a' | 'pending' | 'sent' | 'failed';
|
|
4
|
+
export type WebhookRequestStatus = 'n/a' | 'pending' | 'sent' | 'failed';
|
|
5
|
+
export type NuaInternalError = {
|
|
6
|
+
kind: 'internal-error';
|
|
7
|
+
message: string;
|
|
8
|
+
};
|
|
9
|
+
export type ApiResponseLlmRequest = {
|
|
10
|
+
id: string;
|
|
11
|
+
requestType: LlmRequestType;
|
|
12
|
+
llmStatus: LlmRequestStatus;
|
|
13
|
+
sseStatus: SseRequestStatus;
|
|
14
|
+
webhookStatus: WebhookRequestStatus;
|
|
15
|
+
input: {
|
|
16
|
+
prompt: string | null;
|
|
17
|
+
data: string | null;
|
|
18
|
+
primaryKey: string | null;
|
|
19
|
+
};
|
|
20
|
+
output: {
|
|
21
|
+
name: string;
|
|
22
|
+
schema: string;
|
|
23
|
+
effectiveSchema: string;
|
|
24
|
+
};
|
|
25
|
+
result?: Record<string, unknown> | null;
|
|
26
|
+
error: string | null;
|
|
27
|
+
fullPrompt: string;
|
|
28
|
+
model: string;
|
|
29
|
+
provider: string;
|
|
30
|
+
startedAt: Date | null;
|
|
31
|
+
finishedAt: Date | null;
|
|
32
|
+
createdAt: Date;
|
|
33
|
+
updatedAt: Date;
|
|
34
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { Nua } from './core';
|
|
2
|
+
export { createArrayFn } from './cast_array/factory';
|
|
3
|
+
export { validateArrayRequestParams } from './cast_array/request-validation';
|
|
4
|
+
export type { ArrayFn, ArrayFnDef } from './cast_array/types';
|
|
5
|
+
export type { ApiResponseLlmRequest, GetRequestResult, LlmRequestStatus, NuaInternalError, SseRequestStatus, WebhookRequestStatus, } from './get-request';
|
package/dist/types/nua.d.ts
CHANGED
|
@@ -1,33 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
type MappingFnDef<OutputName extends string, OutputZodSchema extends z.ZodTypeAny> = {
|
|
5
|
-
name: OutputName;
|
|
6
|
-
prompt: string;
|
|
7
|
-
output: OutputZodSchema;
|
|
8
|
-
};
|
|
9
|
-
type MapResponseRecord<OutputZodSchema extends z.ZodTypeAny, OutputName extends string, InputRecord extends Record<string, unknown>, PrimaryKeyName extends keyof InputRecord & string> = {
|
|
10
|
-
[Key in PrimaryKeyName | OutputName]: Key extends PrimaryKeyName ? InputRecord[PrimaryKeyName] : z.infer<OutputZodSchema>;
|
|
11
|
-
};
|
|
12
|
-
type MapSuccessDataResult<OutputZodSchema extends z.ZodTypeAny, OutputName extends string, InputRecord extends Record<string, unknown>, PrimaryKeyName extends keyof InputRecord & string> = Array<MapResponseRecord<OutputZodSchema, OutputName, InputRecord, PrimaryKeyName>>;
|
|
13
|
-
type MapRequestApiResponse_Success<OutputZodSchema extends z.ZodTypeAny, OutputName extends string, InputRecord extends Record<string, unknown>, PrimaryKeyName extends keyof InputRecord & string> = {
|
|
14
|
-
data: MapSuccessDataResult<OutputZodSchema, OutputName, InputRecord, PrimaryKeyName>;
|
|
15
|
-
cacheHits: number;
|
|
16
|
-
llmRequestId: string;
|
|
17
|
-
kind: 'map';
|
|
18
|
-
rowsWithNoResults: string[];
|
|
19
|
-
isSuccess: true;
|
|
20
|
-
isError?: false;
|
|
21
|
-
};
|
|
22
|
-
type MapResult<OutputZodSchema extends z.ZodTypeAny, OutputName extends string, InputRecord extends Record<string, unknown>, PrimaryKeyName extends keyof InputRecord & string> = NuabaseError | MapRequestApiResponse_Success<OutputZodSchema, OutputName, InputRecord, PrimaryKeyName>;
|
|
23
|
-
type MapInvoker<OutputZodSchema extends z.ZodTypeAny, OutputName extends string> = {
|
|
24
|
-
<InputRecord extends Record<string, unknown>, PrimaryKeyName extends keyof InputRecord & string>(data: InputRecord[], primaryKeyName: PrimaryKeyName): Promise<MapResult<OutputZodSchema, OutputName, InputRecord, PrimaryKeyName>>;
|
|
25
|
-
now: <InputRecord extends Record<string, unknown>, PrimaryKeyName extends keyof InputRecord & string>(data: InputRecord[], primaryKeyName: PrimaryKeyName) => Promise<MapResult<OutputZodSchema, OutputName, InputRecord, PrimaryKeyName>>;
|
|
26
|
-
};
|
|
27
|
-
export declare class Nua {
|
|
28
|
-
apiClient: NuabaseAPIClient;
|
|
29
|
-
constructor(config?: NuabaseConfig);
|
|
30
|
-
static validateMapRequestParams(data: unknown, primaryKeyName: unknown): void;
|
|
31
|
-
map<OutputName extends string, OutputZodSchema extends z.ZodTypeAny>(fnDef: MappingFnDef<OutputName, OutputZodSchema>): MapInvoker<OutputZodSchema, OutputName>;
|
|
32
|
-
}
|
|
33
|
-
export {};
|
|
1
|
+
export { Nua } from './nua/index';
|
|
2
|
+
export { createArrayFn, validateArrayRequestParams } from './nua/index';
|
|
3
|
+
export type { ArrayFn, ArrayFnDef } from './nua/index';
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "nuabase",
|
|
3
3
|
"description": "Nuabase TypeScript client to create typed functions from LLM prompts",
|
|
4
4
|
"packageManager": "yarn@4.10.3+sha512.c38cafb5c7bb273f3926d04e55e1d8c9dfa7d9c3ea1f36a4868fa028b9e5f72298f0b7f401ad5eb921749eb012eb1c3bb74bf7503df3ee43fd600d14a018266f",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.1.0",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"author": "Jasim A Basheer <jasim@nuabase.com>",
|
|
8
8
|
"engines": {
|
|
@@ -69,6 +69,7 @@
|
|
|
69
69
|
"chalk": "^5.6.2",
|
|
70
70
|
"esbuild": "^0.25.9",
|
|
71
71
|
"eslint": "^9.35.0",
|
|
72
|
+
"eventsource": "^4.0.0",
|
|
72
73
|
"fs-extra": "^11.3.1",
|
|
73
74
|
"jest": "^30.1.3",
|
|
74
75
|
"knip": "^5.63.1",
|