@teamkeel/functions-runtime 0.418.0 → 0.420.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/dist/index.cjs CHANGED
@@ -786,9 +786,9 @@ var InlineFile = class _InlineFile {
786
786
  const mime = info.split(";")[0];
787
787
  const name = info.split(";")[1].split("=")[1];
788
788
  const buffer = Buffer.from(data, "base64");
789
- const file = new _InlineFile({ filename: name, contentType: mime });
790
- file.write(buffer);
791
- return file;
789
+ const file2 = new _InlineFile({ filename: name, contentType: mime });
790
+ file2.write(buffer);
791
+ return file2;
792
792
  }
793
793
  // Gets size of the file's contents in bytes
794
794
  get size() {
@@ -2362,6 +2362,7 @@ var textInput = /* @__PURE__ */ __name((name, options) => {
2362
2362
  minLength: options?.minLength
2363
2363
  },
2364
2364
  validate: options?.validate,
2365
+ onLeave: options?.onLeave,
2365
2366
  getData: /* @__PURE__ */ __name((x) => x, "getData")
2366
2367
  };
2367
2368
  }, "textInput");
@@ -2383,6 +2384,7 @@ var numberInput = /* @__PURE__ */ __name((name, options) => {
2383
2384
  max: options?.max
2384
2385
  },
2385
2386
  validate: options?.validate,
2387
+ onLeave: options?.onLeave,
2386
2388
  getData: /* @__PURE__ */ __name((x) => x, "getData")
2387
2389
  };
2388
2390
  }, "numberInput");
@@ -2411,6 +2413,7 @@ var booleanInput = /* @__PURE__ */ __name((name, options) => {
2411
2413
  mode: options?.mode || "checkbox"
2412
2414
  },
2413
2415
  validate: options?.validate,
2416
+ onLeave: options?.onLeave,
2414
2417
  getData: /* @__PURE__ */ __name((x) => x, "getData")
2415
2418
  };
2416
2419
  }, "booleanInput");
@@ -2472,6 +2475,22 @@ var selectOne = /* @__PURE__ */ __name((name, options) => {
2472
2475
  }, "selectOne");
2473
2476
 
2474
2477
  // src/flows/ui/page.ts
2478
+ async function callbackFn(elements, elementName, callbackName, data) {
2479
+ const element = elements.find(
2480
+ (el) => el.uiConfig && el.uiConfig.name === elementName
2481
+ );
2482
+ if (!element) {
2483
+ throw new Error(`Element with name ${elementName} not found`);
2484
+ }
2485
+ const cb = element[callbackName];
2486
+ if (typeof cb !== "function") {
2487
+ throw new Error(
2488
+ `Callback ${callbackName} not found on element ${elementName}`
2489
+ );
2490
+ }
2491
+ return await cb(data);
2492
+ }
2493
+ __name(callbackFn, "callbackFn");
2475
2494
  async function page(options, data, action) {
2476
2495
  const content = options.content;
2477
2496
  let hasValidationErrors = false;
@@ -2521,7 +2540,8 @@ async function page(options, data, action) {
2521
2540
  return a;
2522
2541
  }),
2523
2542
  hasValidationErrors,
2524
- validationError
2543
+ validationError,
2544
+ allowBack: options.allowBack
2525
2545
  },
2526
2546
  hasValidationErrors
2527
2547
  };
@@ -2658,6 +2678,16 @@ var ExhuastedRetriesDisrupt = class extends FlowDisrupt {
2658
2678
  super();
2659
2679
  }
2660
2680
  };
2681
+ var CallbackDisrupt = class extends FlowDisrupt {
2682
+ constructor(response, error) {
2683
+ super();
2684
+ this.response = response;
2685
+ this.error = error;
2686
+ }
2687
+ static {
2688
+ __name(this, "CallbackDisrupt");
2689
+ }
2690
+ };
2661
2691
 
2662
2692
  // src/flows/ui/elements/display/banner.ts
2663
2693
  var banner = /* @__PURE__ */ __name((options) => {
@@ -2913,32 +2943,48 @@ var NonRetriableError = class extends Error {
2913
2943
  }
2914
2944
  };
2915
2945
 
2916
- // src/flows/ui/elements/interactive/bulkScan.ts
2917
- var bulkScan = /* @__PURE__ */ __name((name, options) => {
2946
+ // src/flows/ui/elements/input/scan.ts
2947
+ var isMultiMode = /* @__PURE__ */ __name((opts) => opts && opts.mode === "multi", "isMultiMode");
2948
+ var scan = /* @__PURE__ */ __name((name, options) => {
2918
2949
  return {
2919
2950
  __type: "input",
2920
2951
  uiConfig: {
2921
- __type: "ui.interactive.bulkScan",
2952
+ __type: "ui.input.scan",
2922
2953
  name,
2923
2954
  title: options?.title ?? void 0,
2924
2955
  description: options?.description ?? void 0,
2925
2956
  unit: options?.unit ?? void 0,
2926
- max: options?.max ?? void 0,
2927
- min: options?.min ?? void 0,
2928
- duplicateHandling: options?.duplicateHandling ?? "none"
2957
+ mode: options?.mode ?? "single",
2958
+ duplicateHandling: "none",
2959
+ ...isMultiMode(options) ? {
2960
+ max: options.max ?? void 0,
2961
+ min: options.min ?? void 0,
2962
+ duplicateHandling: options.duplicateHandling ?? "none"
2963
+ } : {}
2929
2964
  },
2930
2965
  validate: /* @__PURE__ */ __name(async (data) => {
2931
- if (!("scans" in data)) {
2932
- return "Missing scans in response";
2933
- }
2934
- if (!Array.isArray(data.scans)) {
2935
- return "Scans must be an array";
2936
- }
2937
2966
  return options?.validate?.(data) ?? true;
2938
2967
  }, "validate"),
2939
2968
  getData: /* @__PURE__ */ __name((x) => x, "getData")
2940
2969
  };
2941
- }, "bulkScan");
2970
+ }, "scan");
2971
+
2972
+ // src/flows/ui/elements/display/file.ts
2973
+ var file = /* @__PURE__ */ __name(async (options) => {
2974
+ const title = options.title || options.file.filename;
2975
+ const url = await options.file.getPresignedUrl();
2976
+ const metadata = await options.file.toJSON();
2977
+ return {
2978
+ uiConfig: {
2979
+ __type: "ui.display.file",
2980
+ title,
2981
+ file: metadata ? {
2982
+ url: url?.toString() || "",
2983
+ ...metadata
2984
+ } : void 0
2985
+ }
2986
+ };
2987
+ }, "file");
2942
2988
 
2943
2989
  // src/flows/index.ts
2944
2990
  var STEP_STATUS = /* @__PURE__ */ ((STEP_STATUS2) => {
@@ -2974,7 +3020,7 @@ var defaultOpts = {
2974
3020
  retries: 4,
2975
3021
  timeout: 6e4
2976
3022
  };
2977
- function createFlowContext(runId, data, action, spanId, ctx) {
3023
+ function createFlowContext(runId, data, action, callback, element, spanId, ctx) {
2978
3024
  const usedNames = /* @__PURE__ */ new Set();
2979
3025
  return {
2980
3026
  identity: ctx.identity,
@@ -3086,6 +3132,7 @@ function createFlowContext(runId, data, action, spanId, ctx) {
3086
3132
  ui: {
3087
3133
  page: /* @__PURE__ */ __name(async (name, options) => {
3088
3134
  const db = useDatabase();
3135
+ const isCallback = element && callback;
3089
3136
  if (usedNames.has(name)) {
3090
3137
  await db.insertInto("keel.flow_step").values({
3091
3138
  run_id: runId,
@@ -3121,6 +3168,25 @@ function createFlowContext(runId, data, action, spanId, ctx) {
3121
3168
  (await page(options, null, null)).page
3122
3169
  );
3123
3170
  }
3171
+ if (isCallback) {
3172
+ try {
3173
+ const response = await callbackFn(
3174
+ options.content,
3175
+ element,
3176
+ callback,
3177
+ data
3178
+ );
3179
+ throw new CallbackDisrupt(response, false);
3180
+ } catch (e) {
3181
+ if (e instanceof CallbackDisrupt) {
3182
+ throw e;
3183
+ }
3184
+ throw new CallbackDisrupt(
3185
+ e instanceof Error ? e.message : `An error occurred`,
3186
+ true
3187
+ );
3188
+ }
3189
+ }
3124
3190
  if (!data) {
3125
3191
  throw new UIRenderDisrupt(
3126
3192
  step?.id,
@@ -3157,7 +3223,8 @@ function createFlowContext(runId, data, action, spanId, ctx) {
3157
3223
  text: textInput,
3158
3224
  number: numberInput,
3159
3225
  boolean: booleanInput,
3160
- dataGrid: dataGridInput
3226
+ dataGrid: dataGridInput,
3227
+ scan
3161
3228
  },
3162
3229
  display: {
3163
3230
  divider,
@@ -3169,7 +3236,8 @@ function createFlowContext(runId, data, action, spanId, ctx) {
3169
3236
  code,
3170
3237
  grid,
3171
3238
  list,
3172
- keyValue
3239
+ keyValue,
3240
+ file
3173
3241
  },
3174
3242
  select: {
3175
3243
  one: selectOne,
@@ -3178,8 +3246,7 @@ function createFlowContext(runId, data, action, spanId, ctx) {
3178
3246
  iterator,
3179
3247
  interactive: {
3180
3248
  print,
3181
- pickList,
3182
- bulkScan
3249
+ pickList
3183
3250
  }
3184
3251
  }
3185
3252
  };
@@ -3255,6 +3322,8 @@ async function handleFlow(request, config) {
3255
3322
  request.meta.runId,
3256
3323
  request.meta.data,
3257
3324
  request.meta.action,
3325
+ request.meta.callback,
3326
+ request.meta.element,
3258
3327
  span.spanContext().spanId,
3259
3328
  createFlowContextAPI({
3260
3329
  meta: request.meta
@@ -3290,6 +3359,12 @@ async function handleFlow(request, config) {
3290
3359
  executeAfter: e.executeAfter
3291
3360
  });
3292
3361
  }
3362
+ if (e instanceof CallbackDisrupt) {
3363
+ if (e.error) {
3364
+ return (0, import_json_rpc_26.createJSONRPCErrorResponse)(request.id, 500, e.response);
3365
+ }
3366
+ return (0, import_json_rpc_26.createJSONRPCSuccessResponse)(request.id, e.response);
3367
+ }
3293
3368
  if (e instanceof UIRenderDisrupt) {
3294
3369
  return (0, import_json_rpc_26.createJSONRPCSuccessResponse)(request.id, {
3295
3370
  runId,