@teamkeel/functions-runtime 0.413.3 → 0.413.5

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.d.cts CHANGED
@@ -497,7 +497,7 @@ interface BaseInputConfig<T> {
497
497
  helpText?: string;
498
498
  optional?: boolean;
499
499
  disabled?: boolean;
500
- validate?: (data: T) => Promise<boolean | string>;
500
+ validate?: (data: T) => Promise<null | string> | string | null;
501
501
  }
502
502
  interface BaseUiInputResponse<K, TData> {
503
503
  __type: K;
@@ -507,6 +507,7 @@ interface BaseUiInputResponse<K, TData> {
507
507
  helpText?: string;
508
508
  optional?: boolean;
509
509
  disabled?: boolean;
510
+ validationError?: string;
510
511
  }
511
512
  interface BaseUiDisplayResponse<K> {
512
513
  __type: K;
@@ -557,18 +558,24 @@ interface FlowConfig {
557
558
  title?: string;
558
559
  description?: string;
559
560
  }
561
+ interface FlowConfigAPI {
562
+ stages?: StageConfigObject[];
563
+ title: string;
564
+ description?: string;
565
+ }
560
566
  type FlowFunction<C extends FlowConfig, I extends any = {}> = (ctx: FlowContext<C>, inputs: I) => Promise<void>;
561
567
  type ExtractStageKeys<T extends FlowConfig> = T extends {
562
568
  stages: infer S;
563
569
  } ? S extends ReadonlyArray<infer U> ? U extends string ? U : U extends {
564
570
  key: infer K extends string;
565
571
  } ? K : never : never : never;
566
- type StageConfig = string | {
572
+ type StageConfigObject = {
567
573
  key: string;
568
574
  name: string;
569
575
  description?: string;
570
576
  initiallyHidden?: boolean;
571
577
  };
578
+ type StageConfig = string | StageConfigObject;
572
579
  declare function createFlowContext<C extends FlowConfig>(runId: string, data: any, spanId: string): FlowContext<C>;
573
580
 
574
581
  declare function ksuid(): string;
@@ -739,4 +746,4 @@ type dateDuration = `${number}Y${number}M${number}D` | `${number}Y${number}M` |
739
746
  type timeDuration = `${number}H${number}M${number}S` | `${number}H${number}M` | `${number}M${number}S` | `${number}H${number}S` | `${number}H` | `${number}M` | `${number}S`;
740
747
  type DurationString = `P${dateDuration}T${timeDuration}` | `P${dateDuration}` | `PT${timeDuration}`;
741
748
 
742
- export { type BooleanArrayQueryWhereCondition, type BooleanArrayWhereCondition, type BooleanWhereCondition, type ContextAPI, type DateArrayQueryWhereCondition, type DateArrayWhereCondition, type DateQueryInput, type DateWhereCondition, Duration, type DurationString, type DurationWhereCondition, ErrorPresets, type Errors, type ExtractStageKeys, File, type FlowConfig, type FlowContext, type FlowFunction, type FuncWithConfig, type FunctionConfig, type IDWhereCondition, InlineFile, ModelAPI, type NumberArrayQueryWhereCondition, type NumberArrayWhereCondition, type NumberWhereCondition, PERMISSION_STATE, type PageInfo, Permissions, type RelativeDateString, RequestHeaders, type Response, type SortDirection, type Step, type StringArrayQueryWhereCondition, type StringArrayWhereCondition, type StringWhereCondition, type TimestampQueryInput, type UI, type UIApiResponses, checkBuiltInPermissions, createFlowContext, handleFlow, handleJob, handleRequest, handleRoute, handleSubscriber, ksuid, tracing, useDatabase };
749
+ export { type BooleanArrayQueryWhereCondition, type BooleanArrayWhereCondition, type BooleanWhereCondition, type ContextAPI, type DateArrayQueryWhereCondition, type DateArrayWhereCondition, type DateQueryInput, type DateWhereCondition, Duration, type DurationString, type DurationWhereCondition, ErrorPresets, type Errors, type ExtractStageKeys, File, type FlowConfig, type FlowConfigAPI, type FlowContext, type FlowFunction, type FuncWithConfig, type FunctionConfig, type IDWhereCondition, InlineFile, ModelAPI, type NumberArrayQueryWhereCondition, type NumberArrayWhereCondition, type NumberWhereCondition, PERMISSION_STATE, type PageInfo, Permissions, type RelativeDateString, RequestHeaders, type Response, type SortDirection, type Step, type StringArrayQueryWhereCondition, type StringArrayWhereCondition, type StringWhereCondition, type TimestampQueryInput, type UI, type UIApiResponses, checkBuiltInPermissions, createFlowContext, handleFlow, handleJob, handleRequest, handleRoute, handleSubscriber, ksuid, tracing, useDatabase };
package/dist/index.d.ts CHANGED
@@ -497,7 +497,7 @@ interface BaseInputConfig<T> {
497
497
  helpText?: string;
498
498
  optional?: boolean;
499
499
  disabled?: boolean;
500
- validate?: (data: T) => Promise<boolean | string>;
500
+ validate?: (data: T) => Promise<null | string> | string | null;
501
501
  }
502
502
  interface BaseUiInputResponse<K, TData> {
503
503
  __type: K;
@@ -507,6 +507,7 @@ interface BaseUiInputResponse<K, TData> {
507
507
  helpText?: string;
508
508
  optional?: boolean;
509
509
  disabled?: boolean;
510
+ validationError?: string;
510
511
  }
511
512
  interface BaseUiDisplayResponse<K> {
512
513
  __type: K;
@@ -557,18 +558,24 @@ interface FlowConfig {
557
558
  title?: string;
558
559
  description?: string;
559
560
  }
561
+ interface FlowConfigAPI {
562
+ stages?: StageConfigObject[];
563
+ title: string;
564
+ description?: string;
565
+ }
560
566
  type FlowFunction<C extends FlowConfig, I extends any = {}> = (ctx: FlowContext<C>, inputs: I) => Promise<void>;
561
567
  type ExtractStageKeys<T extends FlowConfig> = T extends {
562
568
  stages: infer S;
563
569
  } ? S extends ReadonlyArray<infer U> ? U extends string ? U : U extends {
564
570
  key: infer K extends string;
565
571
  } ? K : never : never : never;
566
- type StageConfig = string | {
572
+ type StageConfigObject = {
567
573
  key: string;
568
574
  name: string;
569
575
  description?: string;
570
576
  initiallyHidden?: boolean;
571
577
  };
578
+ type StageConfig = string | StageConfigObject;
572
579
  declare function createFlowContext<C extends FlowConfig>(runId: string, data: any, spanId: string): FlowContext<C>;
573
580
 
574
581
  declare function ksuid(): string;
@@ -739,4 +746,4 @@ type dateDuration = `${number}Y${number}M${number}D` | `${number}Y${number}M` |
739
746
  type timeDuration = `${number}H${number}M${number}S` | `${number}H${number}M` | `${number}M${number}S` | `${number}H${number}S` | `${number}H` | `${number}M` | `${number}S`;
740
747
  type DurationString = `P${dateDuration}T${timeDuration}` | `P${dateDuration}` | `PT${timeDuration}`;
741
748
 
742
- export { type BooleanArrayQueryWhereCondition, type BooleanArrayWhereCondition, type BooleanWhereCondition, type ContextAPI, type DateArrayQueryWhereCondition, type DateArrayWhereCondition, type DateQueryInput, type DateWhereCondition, Duration, type DurationString, type DurationWhereCondition, ErrorPresets, type Errors, type ExtractStageKeys, File, type FlowConfig, type FlowContext, type FlowFunction, type FuncWithConfig, type FunctionConfig, type IDWhereCondition, InlineFile, ModelAPI, type NumberArrayQueryWhereCondition, type NumberArrayWhereCondition, type NumberWhereCondition, PERMISSION_STATE, type PageInfo, Permissions, type RelativeDateString, RequestHeaders, type Response, type SortDirection, type Step, type StringArrayQueryWhereCondition, type StringArrayWhereCondition, type StringWhereCondition, type TimestampQueryInput, type UI, type UIApiResponses, checkBuiltInPermissions, createFlowContext, handleFlow, handleJob, handleRequest, handleRoute, handleSubscriber, ksuid, tracing, useDatabase };
749
+ export { type BooleanArrayQueryWhereCondition, type BooleanArrayWhereCondition, type BooleanWhereCondition, type ContextAPI, type DateArrayQueryWhereCondition, type DateArrayWhereCondition, type DateQueryInput, type DateWhereCondition, Duration, type DurationString, type DurationWhereCondition, ErrorPresets, type Errors, type ExtractStageKeys, File, type FlowConfig, type FlowConfigAPI, type FlowContext, type FlowFunction, type FuncWithConfig, type FunctionConfig, type IDWhereCondition, InlineFile, ModelAPI, type NumberArrayQueryWhereCondition, type NumberArrayWhereCondition, type NumberWhereCondition, PERMISSION_STATE, type PageInfo, Permissions, type RelativeDateString, RequestHeaders, type Response, type SortDirection, type Step, type StringArrayQueryWhereCondition, type StringArrayWhereCondition, type StringWhereCondition, type TimestampQueryInput, type UI, type UIApiResponses, checkBuiltInPermissions, createFlowContext, handleFlow, handleJob, handleRequest, handleRoute, handleSubscriber, ksuid, tracing, useDatabase };
package/dist/index.js CHANGED
@@ -2290,7 +2290,7 @@ async function handleRoute(request, config) {
2290
2290
  }
2291
2291
  __name(handleRoute, "handleRoute");
2292
2292
 
2293
- // src/handleFlow.js
2293
+ // src/handleFlow.ts
2294
2294
  import {
2295
2295
  createJSONRPCErrorResponse as createJSONRPCErrorResponse6,
2296
2296
  createJSONRPCSuccessResponse as createJSONRPCSuccessResponse5,
@@ -2417,18 +2417,39 @@ var selectOne = /* @__PURE__ */ __name((name, options) => {
2417
2417
  }, "selectOne");
2418
2418
 
2419
2419
  // src/flows/ui/page.ts
2420
- var page = /* @__PURE__ */ __name((options) => {
2420
+ async function page(options, data) {
2421
2421
  const content = options.content;
2422
- const contentUiConfig = content.map((c) => c.uiConfig).filter(Boolean);
2422
+ let hasValidationErrors = false;
2423
+ const contentUiConfig = await Promise.all(
2424
+ content.map(async (c) => {
2425
+ const isInput = "__type" in c && c.__type == "input";
2426
+ const hasData = data && c.uiConfig.name in data;
2427
+ if (isInput && hasData && c.validate) {
2428
+ const validationError = await c.validate(data[c.uiConfig.name]);
2429
+ if (typeof validationError === "string") {
2430
+ hasValidationErrors = true;
2431
+ return {
2432
+ ...c.uiConfig,
2433
+ validationError
2434
+ };
2435
+ }
2436
+ }
2437
+ return c.uiConfig;
2438
+ }).filter(Boolean)
2439
+ );
2423
2440
  return {
2424
- __type: "ui.page",
2425
- stage: options.stage,
2426
- title: options.title,
2427
- description: options.description,
2428
- content: contentUiConfig,
2429
- actions: options.actions
2441
+ page: {
2442
+ __type: "ui.page",
2443
+ stage: options.stage,
2444
+ title: options.title,
2445
+ description: options.description,
2446
+ content: contentUiConfig,
2447
+ actions: options.actions
2448
+ },
2449
+ hasValidationErrors
2430
2450
  };
2431
- }, "page");
2451
+ }
2452
+ __name(page, "page");
2432
2453
 
2433
2454
  // src/flows/disrupts.ts
2434
2455
  var FlowDisrupt = class {
@@ -2642,10 +2663,14 @@ function createFlowContext(runId, data, spanId) {
2642
2663
  type: "UI" /* UI */,
2643
2664
  startTime: /* @__PURE__ */ new Date()
2644
2665
  }).returningAll().executeTakeFirst();
2645
- throw new UIRenderDisrupt(step?.id, page(options));
2666
+ throw new UIRenderDisrupt(step?.id, (await page(options, null)).page);
2646
2667
  }
2647
2668
  if (!data) {
2648
- throw new UIRenderDisrupt(step?.id, page(options));
2669
+ throw new UIRenderDisrupt(step?.id, (await page(options, null)).page);
2670
+ }
2671
+ const p = await page(options, data);
2672
+ if (p.hasValidationErrors) {
2673
+ throw new UIRenderDisrupt(step?.id, p.page);
2649
2674
  }
2650
2675
  await db.updateTable("keel.flow_step").set({
2651
2676
  status: "COMPLETED" /* COMPLETED */,
@@ -2692,7 +2717,8 @@ function withTimeout(promiseFn, timeout) {
2692
2717
  }
2693
2718
  __name(withTimeout, "withTimeout");
2694
2719
 
2695
- // src/handleFlow.js
2720
+ // src/handleFlow.ts
2721
+ import { sentenceCase } from "change-case";
2696
2722
  async function handleFlow(request, config) {
2697
2723
  const activeContext = opentelemetry6.propagation.extract(
2698
2724
  opentelemetry6.context.active(),
@@ -2733,7 +2759,20 @@ async function handleFlow(request, config) {
2733
2759
  span.spanContext().spanId
2734
2760
  );
2735
2761
  const flowFunction = flows[request.method].fn;
2736
- flowConfig = flows[request.method].config;
2762
+ const rawFlowConfig = flows[request.method].config;
2763
+ flowConfig = {
2764
+ ...rawFlowConfig,
2765
+ title: rawFlowConfig.title || sentenceCase(request.method || "flow"),
2766
+ stages: rawFlowConfig.stages?.map((stage) => {
2767
+ if (typeof stage === "string") {
2768
+ return {
2769
+ key: stage,
2770
+ name: stage
2771
+ };
2772
+ }
2773
+ return stage;
2774
+ })
2775
+ };
2737
2776
  const inputs = parseInputs(flowRun.input);
2738
2777
  try {
2739
2778
  await tryExecuteFlow(db, async () => {
@@ -2758,7 +2797,7 @@ async function handleFlow(request, config) {
2758
2797
  span.recordException(e);
2759
2798
  span.setStatus({
2760
2799
  code: opentelemetry6.SpanStatusCode.ERROR,
2761
- message: e.message
2800
+ message: e instanceof Error ? e.message : "unknown error"
2762
2801
  });
2763
2802
  if (e instanceof ExhuastedRetriesDisrupt) {
2764
2803
  return createJSONRPCSuccessResponse5(request.id, {
@@ -2771,7 +2810,7 @@ async function handleFlow(request, config) {
2771
2810
  return createJSONRPCSuccessResponse5(request.id, {
2772
2811
  runId,
2773
2812
  runCompleted: true,
2774
- error: e.message,
2813
+ error: e instanceof Error ? e.message : "unknown error",
2775
2814
  config: flowConfig
2776
2815
  });
2777
2816
  }