nuabase 1.1.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.
@@ -1,7 +1,80 @@
1
1
  'use strict';
2
2
 
3
+ var nuaLlmCore = require('nua-llm-core');
3
4
  var zod = require('zod');
4
5
 
6
+ const normalizedUsageZero = {
7
+ promptTokens: 0,
8
+ completionTokens: 0,
9
+ totalTokens: 0
10
+ };
11
+ class DirectBackend {
12
+ constructor(config) {
13
+ if (!config.model) {
14
+ throw new Error("model is required for direct mode");
15
+ }
16
+ this.model = config.model;
17
+ this.client = new nuaLlmCore.NuaLlmClient({ providers: config.providers });
18
+ }
19
+ async castValue(params) {
20
+ const startTime = Date.now();
21
+ const result = await this.client.castValue({
22
+ model: this.model,
23
+ input: { prompt: params.prompt, data: params.data },
24
+ output: { name: params.outputName, effectiveSchema: params.outputSchema }
25
+ });
26
+ const latencyMs = Date.now() - startTime;
27
+ if (!result.success) {
28
+ return {
29
+ success: false,
30
+ error: result.error || "Unknown error",
31
+ source: "direct",
32
+ latencyMs
33
+ };
34
+ }
35
+ return {
36
+ success: true,
37
+ data: result.data,
38
+ usage: result.usage || normalizedUsageZero,
39
+ model: this.model,
40
+ latencyMs,
41
+ source: "direct",
42
+ meta: {}
43
+ };
44
+ }
45
+ async castArray(params) {
46
+ const startTime = Date.now();
47
+ const wrappedSchema = nuaLlmCore.wrapArraySchema(params.outputSchema, {
48
+ primaryKey: params.primaryKey,
49
+ outputName: params.outputName
50
+ });
51
+ const result = await this.client.castArray({
52
+ model: this.model,
53
+ data: params.data,
54
+ input: { prompt: params.prompt, primaryKey: params.primaryKey },
55
+ output: { name: params.outputName, effectiveSchema: wrappedSchema }
56
+ });
57
+ const latencyMs = Date.now() - startTime;
58
+ if (!result.success) {
59
+ return {
60
+ success: false,
61
+ error: result.error || "Unknown error",
62
+ source: "direct",
63
+ latencyMs
64
+ };
65
+ }
66
+ return {
67
+ success: true,
68
+ data: result.data,
69
+ usage: result.usage || normalizedUsageZero,
70
+ model: this.model,
71
+ latencyMs,
72
+ source: "direct",
73
+ meta: {}
74
+ };
75
+ }
76
+ }
77
+
5
78
  function resolveConfigValue(config, key, envVar) {
6
79
  if (config[key]) return config[key];
7
80
  const pe = globalThis.process;
@@ -12,6 +85,50 @@ function resolveConfigValue(config, key, envVar) {
12
85
  return void 0;
13
86
  }
14
87
 
88
+ const isBrowserEnvironment = () => typeof window !== "undefined" && !!window.document;
89
+ class AuthTokenManager {
90
+ constructor(config) {
91
+ this.apiKey = resolveConfigValue(config, "apiKey", "NUABASE_API_KEY") || void 0;
92
+ this.fetchToken = config.fetchToken;
93
+ if (this.apiKey && this.fetchToken) {
94
+ throw new Error("Provide either an apiKey or a fetchToken function, but not both.");
95
+ }
96
+ if (!this.apiKey && !this.fetchToken) {
97
+ throw new Error(
98
+ "Authentication is required. Provide config.apiKey/NUABASE_API_KEY or a fetchToken function."
99
+ );
100
+ }
101
+ if (this.apiKey && isBrowserEnvironment()) {
102
+ throw new Error(
103
+ "found config.apiKey. It is a private secret that must only be used in server environments."
104
+ );
105
+ }
106
+ }
107
+ async getToken() {
108
+ if (this.apiKey) {
109
+ return this.apiKey;
110
+ }
111
+ if (!this.fetchToken) {
112
+ throw new Error("Unable to resolve API token because no fetchToken function is configured.");
113
+ }
114
+ if (this.apiToken) {
115
+ return this.apiToken;
116
+ }
117
+ if (!this.pendingTokenPromise) {
118
+ this.pendingTokenPromise = this.fetchToken().then((token) => {
119
+ if (!token) {
120
+ throw new Error("fetchToken must resolve a non-empty API token.");
121
+ }
122
+ this.apiToken = token;
123
+ return token;
124
+ }).finally(() => {
125
+ this.pendingTokenPromise = void 0;
126
+ });
127
+ }
128
+ return this.pendingTokenPromise;
129
+ }
130
+ }
131
+
15
132
  async function parseErrorResponse(response, urlPath) {
16
133
  const fallbackMessage = `Request to ${urlPath} failed with status ${response.status}${response.statusText ? ` ${response.statusText}` : ""}`;
17
134
  let responseBody = "";
@@ -40,9 +157,17 @@ function safeParseJson(payload) {
40
157
  }
41
158
  }
42
159
  function extractErrorMessage(body) {
43
- const e = body["error"];
44
- if (e && typeof e === "string") return e;
45
- return void 0;
160
+ const parts = [];
161
+ const error = body["error"];
162
+ if (typeof error === "string" && error.trim()) {
163
+ parts.push(error.trim());
164
+ }
165
+ const message = body["message"];
166
+ if (typeof message === "string" && message.trim()) {
167
+ parts.push(message.trim());
168
+ }
169
+ if (parts.length === 0) return void 0;
170
+ return parts.join(". ");
46
171
  }
47
172
 
48
173
  function isErrorWithMessage(error) {
@@ -55,399 +180,215 @@ function getErrorMessageFromException(error) {
55
180
  return String(error);
56
181
  }
57
182
 
58
- class NuabaseAPIClient {
59
- constructor(config = {}) {
60
- this.apiKey = resolveConfigValue(config, "apiKey", "NUABASE_API_KEY") || "";
183
+ function isErrorResponse(response) {
184
+ return Boolean(response && typeof response === "object" && "error" in response);
185
+ }
186
+ class GatewayBackend {
187
+ constructor(config) {
61
188
  this.baseUrl = resolveConfigValue(config, "baseUrl", "NUABASE_API_URL") || "https://api.nuabase.com";
62
- if (!this.apiKey) {
63
- throw new Error(
64
- "API key is required. Provide it via config.apiKey or NUABASE_API_KEY environment variable."
65
- );
189
+ this.authManager = new AuthTokenManager(config);
190
+ }
191
+ async castValue(params) {
192
+ const startTime = Date.now();
193
+ const response = await this.post("cast/value/now", {
194
+ input: { prompt: params.prompt, data: params.data },
195
+ output: { name: params.outputName, schema: params.outputSchema }
196
+ });
197
+ const latencyMs = Date.now() - startTime;
198
+ if (isErrorResponse(response)) {
199
+ return { success: false, error: response.error, source: "gateway", latencyMs };
66
200
  }
201
+ const apiResponse = response;
202
+ const usage = {
203
+ promptTokens: apiResponse.llmUsage.promptTokens + apiResponse.cacheUsage.promptTokens,
204
+ completionTokens: apiResponse.llmUsage.completionTokens + apiResponse.cacheUsage.completionTokens,
205
+ totalTokens: apiResponse.llmUsage.totalTokens + apiResponse.cacheUsage.totalTokens
206
+ };
207
+ return {
208
+ success: true,
209
+ data: apiResponse.data,
210
+ usage,
211
+ model: apiResponse.model ?? "unknown",
212
+ latencyMs,
213
+ source: "gateway",
214
+ meta: {
215
+ requestId: apiResponse.llmRequestId,
216
+ cached: apiResponse.isCacheHit,
217
+ llmUsage: apiResponse.llmUsage,
218
+ cacheUsage: apiResponse.cacheUsage
219
+ }
220
+ };
67
221
  }
68
- async request(method, urlPath, params) {
69
- const url = `${this.baseUrl}/${urlPath}`;
222
+ async castArray(params) {
223
+ const startTime = Date.now();
224
+ const response = await this.post("cast/array/now", {
225
+ input: { prompt: params.prompt, data: params.data, primaryKey: params.primaryKey },
226
+ output: { name: params.outputName, schema: params.outputSchema }
227
+ });
228
+ const latencyMs = Date.now() - startTime;
229
+ if (isErrorResponse(response)) {
230
+ return { success: false, error: response.error, source: "gateway", latencyMs };
231
+ }
232
+ const apiResponse = response;
233
+ const usage = {
234
+ promptTokens: apiResponse.llmUsage.promptTokens + apiResponse.cacheUsage.promptTokens,
235
+ completionTokens: apiResponse.llmUsage.completionTokens + apiResponse.cacheUsage.completionTokens,
236
+ totalTokens: apiResponse.llmUsage.totalTokens + apiResponse.cacheUsage.totalTokens
237
+ };
238
+ return {
239
+ success: true,
240
+ data: apiResponse.data,
241
+ usage,
242
+ model: apiResponse.model ?? "unknown",
243
+ latencyMs,
244
+ source: "gateway",
245
+ meta: {
246
+ requestId: apiResponse.llmRequestId,
247
+ cached: apiResponse.cacheHits === apiResponse.data.length,
248
+ llmUsage: apiResponse.llmUsage,
249
+ cacheUsage: apiResponse.cacheUsage
250
+ }
251
+ };
252
+ }
253
+ async queueCastValue(params) {
254
+ const response = await this.post("cast/value", {
255
+ input: { prompt: params.prompt, data: params.data },
256
+ output: { name: params.outputName, schema: params.outputSchema }
257
+ });
258
+ if (isErrorResponse(response)) {
259
+ return { success: false, error: response.error, source: "gateway" };
260
+ }
261
+ const apiResponse = response;
262
+ return { success: true, jobId: apiResponse.jobId, source: "gateway" };
263
+ }
264
+ async queueCastArray(params) {
265
+ const response = await this.post("cast/array", {
266
+ input: { prompt: params.prompt, data: params.data, primaryKey: params.primaryKey },
267
+ output: { name: params.outputName, schema: params.outputSchema }
268
+ });
269
+ if (isErrorResponse(response)) {
270
+ return { success: false, error: response.error, source: "gateway" };
271
+ }
272
+ const apiResponse = response;
273
+ return { success: true, jobId: apiResponse.jobId, source: "gateway" };
274
+ }
275
+ async post(path, body) {
276
+ const url = `${this.baseUrl}/${path}`;
70
277
  let response;
71
- const hasBody = method !== "GET" && params !== void 0;
72
278
  const headers = {
73
- Authorization: `Bearer ${this.apiKey}`
279
+ Authorization: `Bearer ${await this.authManager.getToken()}`,
280
+ "Content-Type": "application/json"
74
281
  };
75
- if (hasBody) {
76
- headers["Content-Type"] = "application/json";
77
- }
78
282
  try {
79
283
  response = await fetch(url, {
80
- method,
284
+ method: "POST",
81
285
  headers,
82
- body: hasBody ? JSON.stringify(params) : void 0
286
+ body: JSON.stringify(body)
83
287
  });
84
288
  } catch (e) {
85
289
  return { error: `Error calling Nuabase API: ${getErrorMessageFromException(e)}` };
86
290
  }
87
- let result;
88
291
  if (!response.ok) {
89
- return await parseErrorResponse(response, urlPath);
292
+ return await parseErrorResponse(response, path);
90
293
  }
91
294
  try {
92
- result = await response.json();
295
+ return await response.json();
93
296
  } catch {
94
297
  return { error: "Invalid response received from Nuabase API call, unable to parse" };
95
298
  }
96
- return result;
97
299
  }
98
300
  }
99
301
 
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.");
302
+ class Nua {
303
+ constructor(backend) {
304
+ this.backend = backend;
108
305
  }
109
- if (!primaryKeyName || typeof primaryKeyName !== "string") {
110
- throw new Error("`primaryKeyName` must be a non-empty string.");
306
+ static gateway(config) {
307
+ return new Nua(new GatewayBackend(config));
111
308
  }
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) => {
123
- const primaryKeySchema = zod.z.any();
124
- const shape = {
125
- [primaryKeyName]: primaryKeySchema,
126
- [outputKey]: outputSchema
127
- };
128
- return zod.z.object(shape).strict();
129
- };
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);
137
- return zod.z.object({
138
- llmRequestId: zod.z.string(),
139
- kind: zod.z.literal("cast/array"),
140
- data: dataSchema,
141
- cacheHits: zod.z.number(),
142
- rowsWithNoResults: zod.z.array(zod.z.string()),
143
- isSuccess: zod.z.literal(true),
144
- isError: zod.z.optional(zod.z.literal(false))
145
- }).strict();
146
- };
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}`);
164
- }
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);
309
+ static direct(config) {
310
+ return new Nua(new DirectBackend(config));
172
311
  }
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
- );
312
+ // Implementation
313
+ async get(prompt, options) {
314
+ if (typeof prompt !== "string" || prompt.trim() === "") {
315
+ throw new TypeError("Prompt must be a non-empty string");
180
316
  }
181
- return {
182
- ...row,
183
- sourceRow
184
- };
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
317
+ const outputSchema = options?.output?.schema ?? zod.z.string();
318
+ const outputName = options?.output?.name ?? "result";
319
+ const jsonSchema = zod.z.toJSONSchema(outputSchema);
320
+ return this.backend.castValue({
321
+ prompt,
322
+ data: options?.input ?? null,
323
+ outputName,
324
+ outputSchema: jsonSchema
325
+ });
196
326
  }
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 };
327
+ // ========== list() - Array Operations ==========
328
+ async list(prompt, options) {
329
+ if (typeof prompt !== "string" || prompt.trim() === "") {
330
+ throw new TypeError("Prompt must be a non-empty string");
225
331
  }
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 };
332
+ if (!Array.isArray(options.input)) {
333
+ throw new TypeError("Input must be an array for list()");
249
334
  }
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
261
- };
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}`);
335
+ if (typeof options.primaryKey !== "string" || options.primaryKey.trim() === "") {
336
+ throw new TypeError("primaryKey must be a non-empty string");
337
+ }
338
+ const jsonSchema = zod.z.toJSONSchema(options.output.schema);
339
+ return this.backend.castArray({
340
+ prompt,
341
+ data: options.input,
342
+ primaryKey: options.primaryKey,
343
+ outputName: options.output.name,
344
+ outputSchema: jsonSchema
345
+ });
295
346
  }
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
347
+ // Implementation
348
+ async queueGet(prompt, options) {
349
+ if (typeof prompt !== "string" || prompt.trim() === "") {
350
+ throw new TypeError("Prompt must be a non-empty string");
351
+ }
352
+ if (!this.backend.queueCastValue) {
353
+ throw new Error("Queue operations are only supported in gateway mode");
354
+ }
355
+ const outputSchema = options?.output?.schema ?? zod.z.string();
356
+ const outputName = options?.output?.name ?? "result";
357
+ const jsonSchema = zod.z.toJSONSchema(outputSchema);
358
+ return this.backend.queueCastValue({
359
+ prompt,
360
+ data: options?.input ?? null,
361
+ outputName,
362
+ outputSchema: jsonSchema
363
+ });
307
364
  }
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 };
365
+ // ========== queueList() - Async Array Operations ==========
366
+ async queueList(prompt, options) {
367
+ if (typeof prompt !== "string" || prompt.trim() === "") {
368
+ throw new TypeError("Prompt must be a non-empty string");
330
369
  }
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 };
370
+ if (!this.backend.queueCastArray) {
371
+ throw new Error("Queue operations are only supported in gateway mode");
346
372
  }
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
353
- };
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;
373
+ if (!Array.isArray(options.input)) {
374
+ throw new TypeError("Input must be an array for queueList()");
371
375
  }
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);
376
+ if (typeof options.primaryKey !== "string" || options.primaryKey.trim() === "") {
377
+ throw new TypeError("primaryKey must be a non-empty string");
378
+ }
379
+ const jsonSchema = zod.z.toJSONSchema(options.output.schema);
380
+ return this.backend.queueCastArray({
381
+ prompt,
382
+ data: options.input,
383
+ primaryKey: options.primaryKey,
384
+ outputName: options.output.name,
385
+ outputSchema: jsonSchema
386
+ });
450
387
  }
451
388
  }
452
389
 
390
+ Object.defineProperty(exports, "z", {
391
+ enumerable: true,
392
+ get: function () { return zod.z; }
393
+ });
453
394
  exports.Nua = Nua;