nuabase 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.
@@ -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,447 +180,215 @@ function getErrorMessageFromException(error) {
55
180
  return String(error);
56
181
  }
57
182
 
58
- const isBrowserEnvironment = () => typeof window !== "undefined" && !!window.document;
59
- class NuabaseAuthTokenManager {
183
+ function isErrorResponse(response) {
184
+ return Boolean(response && typeof response === "object" && "error" in response);
185
+ }
186
+ class GatewayBackend {
60
187
  constructor(config) {
61
- this.apiKey = resolveConfigValue(config, "apiKey", "NUABASE_API_KEY") || void 0;
62
- this.fetchToken = config.fetchToken;
63
- if (this.apiKey && this.fetchToken) {
64
- throw new Error("Provide either an apiKey or a fetchToken function, but not both.");
65
- }
66
- if (!this.apiKey && !this.fetchToken) {
67
- throw new Error(
68
- "Authentication is required. Provide config.apiKey/NUABASE_API_KEY or a fetchToken function."
69
- );
70
- }
71
- if (this.apiKey && isBrowserEnvironment()) {
72
- throw new Error(
73
- "found config.apiKey. It is a private secret that must only be used in server environments."
74
- );
75
- }
188
+ this.baseUrl = resolveConfigValue(config, "baseUrl", "NUABASE_API_URL") || "https://api.nuabase.com";
189
+ this.authManager = new AuthTokenManager(config);
76
190
  }
77
- async getToken() {
78
- if (this.apiKey) {
79
- return this.apiKey;
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 };
80
200
  }
81
- if (!this.fetchToken) {
82
- throw new Error("Unable to resolve API token because no fetchToken function is configured.");
83
- }
84
- if (this.apiToken) {
85
- return this.apiToken;
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
+ };
221
+ }
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 };
86
231
  }
87
- if (!this.pendingTokenPromise) {
88
- this.pendingTokenPromise = this.fetchToken().then((token) => {
89
- if (!token) {
90
- throw new Error("fetchToken must resolve a non-empty API token.");
91
- }
92
- this.apiToken = token;
93
- return token;
94
- }).finally(() => {
95
- this.pendingTokenPromise = void 0;
96
- });
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" };
97
260
  }
98
- return this.pendingTokenPromise;
261
+ const apiResponse = response;
262
+ return { success: true, jobId: apiResponse.jobId, source: "gateway" };
99
263
  }
100
- }
101
- class NuabaseAPIClient {
102
- constructor(config = {}) {
103
- this.baseUrl = resolveConfigValue(config, "baseUrl", "NUABASE_API_URL") || "https://api.nuabase.com";
104
- this.authTokenManager = new NuabaseAuthTokenManager(config);
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" };
105
274
  }
106
- async request(method, urlPath, params) {
107
- const url = `${this.baseUrl}/${urlPath}`;
275
+ async post(path, body) {
276
+ const url = `${this.baseUrl}/${path}`;
108
277
  let response;
109
- const hasBody = method !== "GET" && params !== void 0;
110
278
  const headers = {
111
- Authorization: `Bearer ${await this.authTokenManager.getToken()}`
279
+ Authorization: `Bearer ${await this.authManager.getToken()}`,
280
+ "Content-Type": "application/json"
112
281
  };
113
- if (hasBody) {
114
- headers["Content-Type"] = "application/json";
115
- }
116
282
  try {
117
283
  response = await fetch(url, {
118
- method,
284
+ method: "POST",
119
285
  headers,
120
- body: hasBody ? JSON.stringify(params) : void 0
286
+ body: JSON.stringify(body)
121
287
  });
122
288
  } catch (e) {
123
289
  return { error: `Error calling Nuabase API: ${getErrorMessageFromException(e)}` };
124
290
  }
125
- let result;
126
291
  if (!response.ok) {
127
- return await parseErrorResponse(response, urlPath);
292
+ return await parseErrorResponse(response, path);
128
293
  }
129
294
  try {
130
- result = await response.json();
295
+ return await response.json();
131
296
  } catch {
132
297
  return { error: "Invalid response received from Nuabase API call, unable to parse" };
133
298
  }
134
- return result;
135
299
  }
136
300
  }
137
301
 
138
- const zs_NuaQueuedResponse = zod.z.object({
139
- id: zod.z.string(),
140
- sseUrl: zod.z.string().min(1)
141
- }).strict();
142
-
143
- const validateArrayRequestParams = (data, primaryKeyName) => {
144
- if (!Array.isArray(data)) {
145
- throw new Error("`data` must be an array of objects.");
302
+ class Nua {
303
+ constructor(backend) {
304
+ this.backend = backend;
146
305
  }
147
- if (!primaryKeyName || typeof primaryKeyName !== "string") {
148
- throw new Error("`primaryKeyName` must be a non-empty string.");
306
+ static gateway(config) {
307
+ return new Nua(new GatewayBackend(config));
149
308
  }
150
- data.forEach((item, index) => {
151
- if (item === null || typeof item !== "object" || Array.isArray(item)) {
152
- throw new Error(`data[${index}] must be a non-null object.`);
153
- }
154
- if (!(primaryKeyName in item)) {
155
- throw new Error(`data[${index}] must contain property '${primaryKeyName}'.`);
156
- }
157
- });
158
- };
159
-
160
- const zs_NormalizedUsage = zod.z.object({
161
- promptTokens: zod.z.number(),
162
- completionTokens: zod.z.number(),
163
- totalTokens: zod.z.number()
164
- }).strict();
165
-
166
- const zs_ResponseRecord = (primaryKeyName, outputKey, outputSchema) => {
167
- const primaryKeySchema = zod.z.any();
168
- const shape = {
169
- [primaryKeyName]: primaryKeySchema,
170
- [outputKey]: outputSchema
171
- };
172
- return zod.z.object(shape).strict();
173
- };
174
- const createNuaApiResponseCastArray = (primaryKeyName, outputKey, outputSchema) => {
175
- const recordSchema = zs_ResponseRecord(
176
- primaryKeyName,
177
- outputKey,
178
- outputSchema
179
- );
180
- const dataSchema = zod.z.array(recordSchema);
181
- return zod.z.object({
182
- llmRequestId: zod.z.string(),
183
- kind: zod.z.literal("cast/array"),
184
- data: dataSchema,
185
- cacheHits: zod.z.number(),
186
- rowsWithNoResults: zod.z.array(zod.z.string()),
187
- isSuccess: zod.z.literal(true),
188
- isError: zod.z.optional(zod.z.literal(false)),
189
- usage: zs_NormalizedUsage
190
- }).strict();
191
- };
192
- const zs_NuaApiResponse_CastArray = createNuaApiResponseCastArray;
193
-
194
- const zs_ArrayFnDef = zod.z.object({
195
- prompt: zod.z.string(),
196
- output: zod.z.object({
197
- name: zod.z.string(),
198
- schema: zod.z.custom(
199
- (value) => value instanceof zod.z.ZodType,
200
- "Expected a Zod schema"
201
- )
202
- })
203
- });
204
- const validateArrayFnDef = (fnDef) => {
205
- const parsed = zs_ArrayFnDef.safeParse(fnDef);
206
- if (!parsed.success) {
207
- const message = zod.z.prettifyError(parsed.error);
208
- throw new TypeError(`Invalid array function definition: ${message}`);
309
+ static direct(config) {
310
+ return new Nua(new DirectBackend(config));
209
311
  }
210
- return parsed.data;
211
- };
212
-
213
- function addOriginalInputRows(inputRows, outputRows, primaryKeyName) {
214
- const lookup = /* @__PURE__ */ new Map();
215
- for (const row of inputRows) {
216
- lookup.set(row[primaryKeyName], row);
217
- }
218
- return outputRows.map((row) => {
219
- const primaryKeyValue = row[primaryKeyName];
220
- const sourceRow = lookup.get(primaryKeyValue);
221
- if (!sourceRow) {
222
- throw new Error(
223
- `Unable to locate source row for primary key "${String(primaryKeyValue)}" in cast array response.`
224
- );
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");
225
316
  }
226
- return {
227
- ...row,
228
- sourceRow
229
- };
230
- });
231
- }
232
- const toCastArrayApiRequest = (prompt, data, primaryKeyName, outputName, outputSchema) => ({
233
- input: {
234
- prompt,
235
- data,
236
- primaryKey: primaryKeyName
237
- },
238
- output: {
239
- schema: outputSchema,
240
- 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
+ });
241
326
  }
242
- });
243
- const createArrayFn = (client, inputFnDef) => {
244
- const fnDef = validateArrayFnDef(inputFnDef);
245
- const outputJsonSchema = zod.z.toJSONSchema(fnDef.output.schema);
246
- const toNuabaseError = (response) => {
247
- if (response && typeof response === "object" && "error" in response)
248
- return { error: String(response.error), isError: true };
249
- return void 0;
250
- };
251
- const queueFn = async (data, primaryKeyName) => {
252
- validateArrayRequestParams(data, primaryKeyName);
253
- const response = await client.request(
254
- "POST",
255
- "cast/array",
256
- toCastArrayApiRequest(
257
- fnDef.prompt,
258
- data,
259
- primaryKeyName,
260
- fnDef.output.name,
261
- outputJsonSchema
262
- )
263
- );
264
- const error = toNuabaseError(response);
265
- if (error) return error;
266
- const parsedResponse = zs_NuaQueuedResponse.safeParse(response);
267
- if (!parsedResponse.success) {
268
- const emsg = zod.z.prettifyError(parsedResponse.error);
269
- 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");
270
331
  }
271
- return parsedResponse.data;
272
- };
273
- const baseNowFn = async (data, primaryKeyName) => {
274
- validateArrayRequestParams(data, primaryKeyName);
275
- const response = await client.request(
276
- "POST",
277
- "cast/array/now",
278
- toCastArrayApiRequest(
279
- fnDef.prompt,
280
- data,
281
- primaryKeyName,
282
- fnDef.output.name,
283
- outputJsonSchema
284
- )
285
- );
286
- const error = toNuabaseError(response);
287
- if (error) return error;
288
- const outputKey = fnDef.output.name;
289
- const successSchema = zs_NuaApiResponse_CastArray(primaryKeyName, outputKey, fnDef.output.schema);
290
- const parsedResponse = successSchema.safeParse(response);
291
- if (!parsedResponse.success) {
292
- const emsg = zod.z.prettifyError(parsedResponse.error);
293
- 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()");
294
334
  }
295
- return {
296
- isSuccess: true,
297
- llmRequestId: parsedResponse.data.llmRequestId,
298
- kind: parsedResponse.data.kind,
299
- data: addOriginalInputRows(
300
- data,
301
- parsedResponse.data.data,
302
- primaryKeyName
303
- ),
304
- rowsWithNoResults: parsedResponse.data.rowsWithNoResults,
305
- cacheHits: parsedResponse.data.cacheHits,
306
- usage: parsedResponse.data.usage
307
- };
308
- };
309
- return Object.assign(baseNowFn, {
310
- queue: queueFn
311
- });
312
- };
313
-
314
- const createNuaApiResponseCastValue = (outputKey, outputSchema) => {
315
- return zod.z.object({
316
- llmRequestId: zod.z.string(),
317
- kind: zod.z.literal("cast/value"),
318
- data: outputSchema,
319
- isCacheHit: zod.z.boolean(),
320
- isSuccess: zod.z.literal(true),
321
- isError: zod.z.optional(zod.z.literal(false)),
322
- usage: zs_NormalizedUsage
323
- }).strict();
324
- };
325
- const zs_NuaApiResponse_CastValue = createNuaApiResponseCastValue;
326
-
327
- const zs_ValueFnDef = zod.z.object({
328
- prompt: zod.z.string(),
329
- output: zod.z.object({
330
- name: zod.z.string(),
331
- schema: zod.z.custom(
332
- (value) => value instanceof zod.z.ZodType,
333
- "Expected a Zod schema for `output.schema`"
334
- )
335
- })
336
- });
337
- const validateValueFnDef = (fnDef) => {
338
- const parsed = zs_ValueFnDef.safeParse(fnDef);
339
- if (!parsed.success) {
340
- const message = zod.z.prettifyError(parsed.error);
341
- 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
+ });
342
346
  }
343
- return parsed.data;
344
- };
345
-
346
- const toCastValueApiRequest = (prompt, data, outputName, outputSchema) => ({
347
- input: {
348
- prompt,
349
- data
350
- },
351
- output: {
352
- schema: outputSchema,
353
- 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
+ });
354
364
  }
355
- });
356
- const createValueFn = (client, inputFnDef) => {
357
- const fnDef = validateValueFnDef(inputFnDef);
358
- const outputJsonSchema = zod.z.toJSONSchema(fnDef.output.schema);
359
- const toNuabaseError = (response) => {
360
- if (response && typeof response === "object" && "error" in response)
361
- return { error: String(response.error), isError: true };
362
- return void 0;
363
- };
364
- const sendRequest = async (path, data) => client.request(
365
- "POST",
366
- path,
367
- toCastValueApiRequest(fnDef.prompt, data, fnDef.output.name, outputJsonSchema)
368
- );
369
- const queueFn = async (data) => {
370
- const response = await sendRequest("cast/value", data);
371
- const error = toNuabaseError(response);
372
- if (error) return error;
373
- const parsedResponse = zs_NuaQueuedResponse.safeParse(response);
374
- if (!parsedResponse.success) {
375
- const emsg = zod.z.prettifyError(parsedResponse.error);
376
- 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");
377
369
  }
378
- return parsedResponse.data;
379
- };
380
- const baseNowFn = async (data) => {
381
- const response = await sendRequest("cast/value/now", data);
382
- const error = toNuabaseError(response);
383
- if (error) return error;
384
- const outputKey = fnDef.output.name;
385
- const successSchema = zs_NuaApiResponse_CastValue(
386
- outputKey,
387
- fnDef.output.schema
388
- );
389
- const parsedResponse = successSchema.safeParse(response);
390
- if (!parsedResponse.success) {
391
- const emsg = zod.z.prettifyError(parsedResponse.error);
392
- 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");
393
372
  }
394
- return {
395
- isSuccess: true,
396
- llmRequestId: parsedResponse.data.llmRequestId,
397
- kind: parsedResponse.data.kind,
398
- data: parsedResponse.data.data,
399
- isCacheHit: parsedResponse.data.isCacheHit,
400
- usage: parsedResponse.data.usage
401
- };
402
- };
403
- return Object.assign(baseNowFn, {
404
- queue: queueFn
405
- });
406
- };
407
-
408
- const errorParseFailed = {
409
- kind: "internal-error",
410
- message: "Unable to parse stored LLM result"
411
- };
412
- const dateFromIso = zod.z.preprocess(
413
- (value) => {
414
- if (value == null) return null;
415
- if (value instanceof Date) return value;
416
- if (typeof value === "string") {
417
- const parsed = new Date(value);
418
- if (!Number.isNaN(parsed.getTime())) return parsed;
373
+ if (!Array.isArray(options.input)) {
374
+ throw new TypeError("Input must be an array for queueList()");
419
375
  }
420
- return zod.z.NEVER;
421
- },
422
- zod.z.union([zod.z.date(), zod.z.null()])
423
- );
424
- const mandatoryDateFromIso = zod.z.preprocess((value) => {
425
- if (value instanceof Date) return value;
426
- if (typeof value === "string") {
427
- const parsed = new Date(value);
428
- if (!Number.isNaN(parsed.getTime())) return parsed;
429
- }
430
- return zod.z.NEVER;
431
- }, zod.z.date());
432
- const apiResponseSchema = zod.z.object({
433
- id: zod.z.string(),
434
- requestType: zod.z.string(),
435
- llmStatus: zod.z.union([
436
- zod.z.literal("pending"),
437
- zod.z.literal("processing"),
438
- zod.z.literal("success"),
439
- zod.z.literal("failed")
440
- ]),
441
- sseStatus: zod.z.union([
442
- zod.z.literal("n/a"),
443
- zod.z.literal("pending"),
444
- zod.z.literal("sent"),
445
- zod.z.literal("failed")
446
- ]),
447
- webhookStatus: zod.z.union([
448
- zod.z.literal("n/a"),
449
- zod.z.literal("pending"),
450
- zod.z.literal("sent"),
451
- zod.z.literal("failed")
452
- ]),
453
- input: zod.z.object({
454
- prompt: zod.z.union([zod.z.string(), zod.z.null()]),
455
- data: zod.z.union([zod.z.string(), zod.z.null()]),
456
- primaryKey: zod.z.union([zod.z.string(), zod.z.null()])
457
- }),
458
- output: zod.z.object({
459
- name: zod.z.string(),
460
- schema: zod.z.string(),
461
- effectiveSchema: zod.z.string()
462
- }),
463
- result: zod.z.union([zod.z.record(zod.z.string(), zod.z.unknown()), zod.z.null()]).optional(),
464
- error: zod.z.union([zod.z.string(), zod.z.null()]),
465
- fullPrompt: zod.z.string(),
466
- model: zod.z.string(),
467
- provider: zod.z.string(),
468
- startedAt: dateFromIso,
469
- finishedAt: dateFromIso,
470
- createdAt: mandatoryDateFromIso,
471
- updatedAt: mandatoryDateFromIso
472
- });
473
- const isNuabaseError = (value) => Boolean(value && typeof value === "object" && "isError" in value && value.isError);
474
- async function getRequest(client, llmRequestId) {
475
- const response = await client.request("GET", `requests/${encodeURIComponent(llmRequestId)}`);
476
- if (isNuabaseError(response)) {
477
- return response;
478
- }
479
- const parsedResponse = apiResponseSchema.safeParse(response);
480
- if (!parsedResponse.success) {
481
- return errorParseFailed;
482
- }
483
- return parsedResponse.data;
484
- }
485
-
486
- class Nua {
487
- constructor(config) {
488
- this.apiClient = new NuabaseAPIClient(config);
489
- }
490
- createArrayFn(fnDef) {
491
- return createArrayFn(this.apiClient, fnDef);
492
- }
493
- createFn(fnDef) {
494
- return createValueFn(this.apiClient, fnDef);
495
- }
496
- async getRequest(llmRequestId) {
497
- 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
+ });
498
387
  }
499
388
  }
500
389
 
390
+ Object.defineProperty(exports, "z", {
391
+ enumerable: true,
392
+ get: function () { return zod.z; }
393
+ });
501
394
  exports.Nua = Nua;