@teamkeel/functions-runtime 0.423.3 → 0.425.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
@@ -608,175 +608,40 @@ __name(getDialect, "getDialect");
608
608
  var import_client_s3 = require("@aws-sdk/client-s3");
609
609
  var import_credential_providers = require("@aws-sdk/credential-providers");
610
610
  var import_s3_request_presigner = require("@aws-sdk/s3-request-presigner");
611
-
612
- // src/errors.js
613
- var import_json_rpc_2 = require("json-rpc-2.0");
614
- var RuntimeErrors = {
615
- // Catchall error type for unhandled execution errors during custom function
616
- UnknownError: -32001,
617
- // DatabaseError represents any error at pg level that isn't handled explicitly below
618
- DatabaseError: -32002,
619
- // No result returned from custom function by user
620
- NoResultError: -32003,
621
- // When trying to delete/update a non existent record in the db
622
- RecordNotFoundError: -32004,
623
- ForeignKeyConstraintError: -32005,
624
- NotNullConstraintError: -32006,
625
- UniqueConstraintError: -32007,
626
- PermissionError: -32008,
627
- BadRequestError: -32009
628
- };
629
- var PermissionError = class extends Error {
630
- static {
631
- __name(this, "PermissionError");
632
- }
633
- };
634
- var DatabaseError = class extends Error {
635
- static {
636
- __name(this, "DatabaseError");
637
- }
638
- constructor(error) {
639
- super(error.message);
640
- this.error = error;
641
- }
642
- };
643
- var NotFoundError = class extends Error {
644
- static {
645
- __name(this, "NotFoundError");
646
- }
647
- errorCode = RuntimeErrors.RecordNotFoundError;
648
- constructor(message) {
649
- super(message);
650
- }
651
- };
652
- var BadRequestError = class extends Error {
653
- static {
654
- __name(this, "BadRequestError");
655
- }
656
- errorCode = RuntimeErrors.BadRequestError;
657
- constructor(message = "bad request") {
658
- super(message);
659
- }
660
- };
661
- var UnknownError = class extends Error {
662
- static {
663
- __name(this, "UnknownError");
664
- }
665
- errorCode = RuntimeErrors.UnknownError;
666
- constructor(message = "unknown error") {
667
- super(message);
668
- }
669
- };
670
- var ErrorPresets = {
671
- NotFound: NotFoundError,
672
- BadRequest: BadRequestError,
673
- Unknown: UnknownError
674
- };
675
- function errorToJSONRPCResponse(request, e) {
676
- switch (e.constructor.name) {
677
- case "PermissionError":
678
- return (0, import_json_rpc_2.createJSONRPCErrorResponse)(
679
- request.id,
680
- RuntimeErrors.PermissionError,
681
- e.message
682
- );
683
- // Any error thrown in the ModelAPI class is
684
- // wrapped in a DatabaseError in order to differentiate 'our code' vs the user's own code.
685
- case "NoResultError":
686
- return (0, import_json_rpc_2.createJSONRPCErrorResponse)(
687
- request.id,
688
- // to be matched to https://github.com/teamkeel/keel/blob/e3115ffe381bfc371d4f45bbf96a15072a994ce5/runtime/actions/update.go#L54-L54
689
- RuntimeErrors.RecordNotFoundError,
690
- ""
691
- // Don't pass on the message as we want to normalise these at the runtime layer but still support custom messages in other NotFound errors
692
- );
693
- case "DatabaseError":
694
- let err = e;
695
- if (e instanceof DatabaseError) {
696
- err = e.error;
697
- }
698
- if (err.constructor.name == "NoResultError") {
699
- return (0, import_json_rpc_2.createJSONRPCErrorResponse)(
700
- request.id,
701
- // to be matched to https://github.com/teamkeel/keel/blob/e3115ffe381bfc371d4f45bbf96a15072a994ce5/runtime/actions/update.go#L54-L54
702
- RuntimeErrors.RecordNotFoundError,
703
- ""
704
- // Don't pass on the message as we want to normalise these at the runtime layer but still support custom messages in other NotFound errors
705
- );
706
- }
707
- if ("code" in err) {
708
- const { code: code2, detail, table: table2 } = err;
709
- let rpcErrorCode, column, value;
710
- const [col, val] = parseKeyMessage(err.detail);
711
- column = col;
712
- value = val;
713
- switch (code2) {
714
- case "23502":
715
- rpcErrorCode = RuntimeErrors.NotNullConstraintError;
716
- column = err.column;
717
- break;
718
- case "23503":
719
- rpcErrorCode = RuntimeErrors.ForeignKeyConstraintError;
720
- break;
721
- case "23505":
722
- rpcErrorCode = RuntimeErrors.UniqueConstraintError;
723
- break;
724
- default:
725
- rpcErrorCode = RuntimeErrors.DatabaseError;
726
- break;
727
- }
728
- return (0, import_json_rpc_2.createJSONRPCErrorResponse)(request.id, rpcErrorCode, e.message, {
729
- table: table2,
730
- column,
731
- code: code2,
732
- detail,
733
- value
734
- });
735
- }
736
- return (0, import_json_rpc_2.createJSONRPCErrorResponse)(
737
- request.id,
738
- RuntimeErrors.DatabaseError,
739
- e.message
740
- );
741
- default:
742
- return (0, import_json_rpc_2.createJSONRPCErrorResponse)(
743
- request.id,
744
- e.errorCode ?? RuntimeErrors.UnknownError,
745
- e.message
746
- );
747
- }
748
- }
749
- __name(errorToJSONRPCResponse, "errorToJSONRPCResponse");
750
- var keyMessagePattern = /\Key\s[(](.*)[)][=][(](.*)[)]/;
751
- var parseKeyMessage = /* @__PURE__ */ __name((msg) => {
752
- const [, col, value] = keyMessagePattern.exec(msg) || [];
753
- return [col, value];
754
- }, "parseKeyMessage");
755
-
756
- // src/File.ts
757
611
  var import_ksuid = __toESM(require("ksuid"), 1);
758
612
  var s3Client = (() => {
759
613
  if (!process.env.KEEL_FILES_BUCKET_NAME) {
760
614
  return null;
761
615
  }
762
- const endpoint = process.env.TEST_AWS_ENDPOINT;
763
- if (!endpoint) {
616
+ const endpoint = process.env.KEEL_S3_ENDPOINT;
617
+ if (endpoint) {
764
618
  return new import_client_s3.S3Client({
765
619
  region: process.env.KEEL_REGION,
766
- credentials: (0, import_credential_providers.fromEnv)()
620
+ credentials: {
621
+ accessKeyId: "keelstorage",
622
+ secretAccessKey: "keelstorage"
623
+ },
624
+ endpoint
625
+ });
626
+ }
627
+ const testEndpoint = process.env.TEST_AWS_ENDPOINT;
628
+ if (testEndpoint) {
629
+ return new import_client_s3.S3Client({
630
+ region: process.env.KEEL_REGION,
631
+ credentials: {
632
+ accessKeyId: "test",
633
+ secretAccessKey: "test"
634
+ },
635
+ endpointProvider: /* @__PURE__ */ __name(() => {
636
+ return {
637
+ url: new URL(testEndpoint)
638
+ };
639
+ }, "endpointProvider")
767
640
  });
768
641
  }
769
642
  return new import_client_s3.S3Client({
770
643
  region: process.env.KEEL_REGION,
771
- credentials: {
772
- accessKeyId: "test",
773
- secretAccessKey: "test"
774
- },
775
- endpointProvider: /* @__PURE__ */ __name(() => {
776
- return {
777
- url: new URL(endpoint)
778
- };
779
- }, "endpointProvider")
644
+ credentials: (0, import_credential_providers.fromEnv)()
780
645
  });
781
646
  })();
782
647
  var InlineFile = class _InlineFile {
@@ -881,24 +746,17 @@ var File = class _File extends InlineFile {
881
746
  const arrayBuffer = await this._contents.arrayBuffer();
882
747
  return Buffer.from(arrayBuffer);
883
748
  }
884
- if (s3Client) {
885
- const params = {
886
- Bucket: process.env.KEEL_FILES_BUCKET_NAME,
887
- Key: "files/" + this.key
888
- };
889
- const command = new import_client_s3.GetObjectCommand(params);
890
- const response = await s3Client.send(command);
891
- const blob = await response.Body.transformToByteArray();
892
- return Buffer.from(blob);
893
- }
894
- const db = useDatabase();
895
- try {
896
- const query = db.selectFrom("keel_storage").select("data").where("id", "=", this.key);
897
- const row = await query.executeTakeFirstOrThrow();
898
- return row.data;
899
- } catch (e) {
900
- throw new DatabaseError(e);
749
+ if (!s3Client) {
750
+ throw new Error("S3 client is required");
901
751
  }
752
+ const params = {
753
+ Bucket: process.env.KEEL_FILES_BUCKET_NAME,
754
+ Key: "files/" + this.key
755
+ };
756
+ const command = new import_client_s3.GetObjectCommand(params);
757
+ const response = await s3Client.send(command);
758
+ const blob = await response.Body.transformToByteArray();
759
+ return Buffer.from(blob);
902
760
  }
903
761
  async store(expires = null) {
904
762
  if (this._contents) {
@@ -916,19 +774,16 @@ var File = class _File extends InlineFile {
916
774
  }
917
775
  // Generates a presigned download URL
918
776
  async getPresignedUrl() {
919
- if (s3Client) {
920
- const command = new import_client_s3.GetObjectCommand({
921
- Bucket: process.env.KEEL_FILES_BUCKET_NAME,
922
- Key: "files/" + this.key,
923
- ResponseContentDisposition: "inline"
924
- });
925
- const url = await (0, import_s3_request_presigner.getSignedUrl)(s3Client, command, { expiresIn: 60 * 60 });
926
- return new URL(url);
927
- } else {
928
- const contents = await this.read();
929
- const dataurl = `data:${this.contentType};name=${this.filename};base64,${contents.toString("base64")}`;
930
- return new URL(dataurl);
777
+ if (!s3Client) {
778
+ throw new Error("S3 client is required");
931
779
  }
780
+ const command = new import_client_s3.GetObjectCommand({
781
+ Bucket: process.env.KEEL_FILES_BUCKET_NAME,
782
+ Key: "files/" + this.key,
783
+ ResponseContentDisposition: "inline"
784
+ });
785
+ const url = await (0, import_s3_request_presigner.getSignedUrl)(s3Client, command, { expiresIn: 60 * 60 });
786
+ return new URL(url);
932
787
  }
933
788
  // Persists the file
934
789
  toDbRecord() {
@@ -944,54 +799,36 @@ var File = class _File extends InlineFile {
944
799
  }
945
800
  };
946
801
  async function storeFile(contents, key, filename, contentType, size, expires) {
947
- if (s3Client) {
948
- const params = {
949
- Bucket: process.env.KEEL_FILES_BUCKET_NAME,
950
- Key: "files/" + key,
951
- Body: contents,
952
- ContentType: contentType,
953
- ContentDisposition: `attachment; filename="${encodeURIComponent(
954
- filename
955
- )}"`,
956
- Metadata: {
957
- filename
958
- },
959
- ACL: "private"
960
- };
961
- if (expires) {
962
- if (expires instanceof Date) {
963
- params.Expires = expires;
964
- } else {
965
- console.warn("Invalid expires value. Skipping Expires parameter.");
966
- }
967
- }
968
- const command = new import_client_s3.PutObjectCommand(params);
969
- try {
970
- await s3Client.send(command);
971
- } catch (error) {
972
- console.error("Error uploading file:", error);
973
- throw error;
974
- }
975
- } else {
976
- const db = useDatabase();
977
- try {
978
- const query = db.insertInto("keel_storage").values({
979
- id: key,
980
- filename,
981
- content_type: contentType,
982
- data: contents
983
- }).onConflict(
984
- (oc) => oc.column("id").doUpdateSet(() => ({
985
- filename,
986
- content_type: contentType,
987
- data: contents
988
- })).where("keel_storage.id", "=", key)
989
- ).returningAll();
990
- await query.execute();
991
- } catch (e) {
992
- throw new DatabaseError(e);
802
+ if (!s3Client) {
803
+ throw new Error("S3 client is required");
804
+ }
805
+ const params = {
806
+ Bucket: process.env.KEEL_FILES_BUCKET_NAME,
807
+ Key: "files/" + key,
808
+ Body: contents,
809
+ ContentType: contentType,
810
+ ContentDisposition: `attachment; filename="${encodeURIComponent(
811
+ filename
812
+ )}"`,
813
+ Metadata: {
814
+ filename
815
+ },
816
+ ACL: "private"
817
+ };
818
+ if (expires) {
819
+ if (expires instanceof Date) {
820
+ params.Expires = expires;
821
+ } else {
822
+ console.warn("Invalid expires value. Skipping Expires parameter.");
993
823
  }
994
824
  }
825
+ const command = new import_client_s3.PutObjectCommand(params);
826
+ try {
827
+ await s3Client.send(command);
828
+ } catch (error) {
829
+ console.error("Error uploading file:", error);
830
+ throw error;
831
+ }
995
832
  }
996
833
  __name(storeFile, "storeFile");
997
834
 
@@ -1431,6 +1268,150 @@ function joinAlias(tablePath) {
1431
1268
  }
1432
1269
  __name(joinAlias, "joinAlias");
1433
1270
 
1271
+ // src/errors.js
1272
+ var import_json_rpc_2 = require("json-rpc-2.0");
1273
+ var RuntimeErrors = {
1274
+ // Catchall error type for unhandled execution errors during custom function
1275
+ UnknownError: -32001,
1276
+ // DatabaseError represents any error at pg level that isn't handled explicitly below
1277
+ DatabaseError: -32002,
1278
+ // No result returned from custom function by user
1279
+ NoResultError: -32003,
1280
+ // When trying to delete/update a non existent record in the db
1281
+ RecordNotFoundError: -32004,
1282
+ ForeignKeyConstraintError: -32005,
1283
+ NotNullConstraintError: -32006,
1284
+ UniqueConstraintError: -32007,
1285
+ PermissionError: -32008,
1286
+ BadRequestError: -32009
1287
+ };
1288
+ var PermissionError = class extends Error {
1289
+ static {
1290
+ __name(this, "PermissionError");
1291
+ }
1292
+ };
1293
+ var DatabaseError = class extends Error {
1294
+ static {
1295
+ __name(this, "DatabaseError");
1296
+ }
1297
+ constructor(error) {
1298
+ super(error.message);
1299
+ this.error = error;
1300
+ }
1301
+ };
1302
+ var NotFoundError = class extends Error {
1303
+ static {
1304
+ __name(this, "NotFoundError");
1305
+ }
1306
+ errorCode = RuntimeErrors.RecordNotFoundError;
1307
+ constructor(message) {
1308
+ super(message);
1309
+ }
1310
+ };
1311
+ var BadRequestError = class extends Error {
1312
+ static {
1313
+ __name(this, "BadRequestError");
1314
+ }
1315
+ errorCode = RuntimeErrors.BadRequestError;
1316
+ constructor(message = "bad request") {
1317
+ super(message);
1318
+ }
1319
+ };
1320
+ var UnknownError = class extends Error {
1321
+ static {
1322
+ __name(this, "UnknownError");
1323
+ }
1324
+ errorCode = RuntimeErrors.UnknownError;
1325
+ constructor(message = "unknown error") {
1326
+ super(message);
1327
+ }
1328
+ };
1329
+ var ErrorPresets = {
1330
+ NotFound: NotFoundError,
1331
+ BadRequest: BadRequestError,
1332
+ Unknown: UnknownError
1333
+ };
1334
+ function errorToJSONRPCResponse(request, e) {
1335
+ switch (e.constructor.name) {
1336
+ case "PermissionError":
1337
+ return (0, import_json_rpc_2.createJSONRPCErrorResponse)(
1338
+ request.id,
1339
+ RuntimeErrors.PermissionError,
1340
+ e.message
1341
+ );
1342
+ // Any error thrown in the ModelAPI class is
1343
+ // wrapped in a DatabaseError in order to differentiate 'our code' vs the user's own code.
1344
+ case "NoResultError":
1345
+ return (0, import_json_rpc_2.createJSONRPCErrorResponse)(
1346
+ request.id,
1347
+ // to be matched to https://github.com/teamkeel/keel/blob/e3115ffe381bfc371d4f45bbf96a15072a994ce5/runtime/actions/update.go#L54-L54
1348
+ RuntimeErrors.RecordNotFoundError,
1349
+ ""
1350
+ // Don't pass on the message as we want to normalise these at the runtime layer but still support custom messages in other NotFound errors
1351
+ );
1352
+ case "DatabaseError":
1353
+ let err = e;
1354
+ if (e instanceof DatabaseError) {
1355
+ err = e.error;
1356
+ }
1357
+ if (err.constructor.name == "NoResultError") {
1358
+ return (0, import_json_rpc_2.createJSONRPCErrorResponse)(
1359
+ request.id,
1360
+ // to be matched to https://github.com/teamkeel/keel/blob/e3115ffe381bfc371d4f45bbf96a15072a994ce5/runtime/actions/update.go#L54-L54
1361
+ RuntimeErrors.RecordNotFoundError,
1362
+ ""
1363
+ // Don't pass on the message as we want to normalise these at the runtime layer but still support custom messages in other NotFound errors
1364
+ );
1365
+ }
1366
+ if ("code" in err) {
1367
+ const { code: code2, detail, table: table2 } = err;
1368
+ let rpcErrorCode, column, value;
1369
+ const [col, val] = parseKeyMessage(err.detail);
1370
+ column = col;
1371
+ value = val;
1372
+ switch (code2) {
1373
+ case "23502":
1374
+ rpcErrorCode = RuntimeErrors.NotNullConstraintError;
1375
+ column = err.column;
1376
+ break;
1377
+ case "23503":
1378
+ rpcErrorCode = RuntimeErrors.ForeignKeyConstraintError;
1379
+ break;
1380
+ case "23505":
1381
+ rpcErrorCode = RuntimeErrors.UniqueConstraintError;
1382
+ break;
1383
+ default:
1384
+ rpcErrorCode = RuntimeErrors.DatabaseError;
1385
+ break;
1386
+ }
1387
+ return (0, import_json_rpc_2.createJSONRPCErrorResponse)(request.id, rpcErrorCode, e.message, {
1388
+ table: table2,
1389
+ column,
1390
+ code: code2,
1391
+ detail,
1392
+ value
1393
+ });
1394
+ }
1395
+ return (0, import_json_rpc_2.createJSONRPCErrorResponse)(
1396
+ request.id,
1397
+ RuntimeErrors.DatabaseError,
1398
+ e.message
1399
+ );
1400
+ default:
1401
+ return (0, import_json_rpc_2.createJSONRPCErrorResponse)(
1402
+ request.id,
1403
+ e.errorCode ?? RuntimeErrors.UnknownError,
1404
+ e.message
1405
+ );
1406
+ }
1407
+ }
1408
+ __name(errorToJSONRPCResponse, "errorToJSONRPCResponse");
1409
+ var keyMessagePattern = /\Key\s[(](.*)[)][=][(](.*)[)]/;
1410
+ var parseKeyMessage = /* @__PURE__ */ __name((msg) => {
1411
+ const [, col, value] = keyMessagePattern.exec(msg) || [];
1412
+ return [col, value];
1413
+ }, "parseKeyMessage");
1414
+
1434
1415
  // src/QueryBuilder.js
1435
1416
  var QueryBuilder = class _QueryBuilder {
1436
1417
  static {
@@ -2503,15 +2484,38 @@ async function page(options, data, action) {
2503
2484
  const content = options.content;
2504
2485
  let hasValidationErrors = false;
2505
2486
  let validationError;
2506
- if (options.actions && action !== null) {
2507
- const isValidAction = options.actions.some((a) => {
2508
- if (typeof a === "string") return a === action;
2509
- return a && typeof a === "object" && "value" in a && a.value === action;
2510
- });
2511
- if (!isValidAction) {
2512
- hasValidationErrors = true;
2513
- validationError = "invalid action";
2487
+ if (options.actions && options.actions.length > 0) {
2488
+ const normalizedAction = action === "undefined" || action === void 0 ? null : action;
2489
+ if (data !== null) {
2490
+ if (normalizedAction === null) {
2491
+ const validValues = options.actions.map((a) => {
2492
+ if (typeof a === "string") return a;
2493
+ return a && typeof a === "object" && "value" in a ? a.value : "";
2494
+ }).filter(Boolean);
2495
+ throw new Error(
2496
+ `action is required. Valid actions are: ${validValues.join(", ")}`
2497
+ );
2498
+ }
2499
+ const isValidAction = options.actions.some((a) => {
2500
+ if (typeof a === "string") return a === normalizedAction;
2501
+ return a && typeof a === "object" && "value" in a && a.value === normalizedAction;
2502
+ });
2503
+ if (!isValidAction) {
2504
+ const validValues = options.actions.map((a) => {
2505
+ if (typeof a === "string") return a;
2506
+ return a && typeof a === "object" && "value" in a ? a.value : "";
2507
+ }).filter(Boolean);
2508
+ throw new Error(
2509
+ `invalid action "${normalizedAction}". Valid actions are: ${validValues.join(
2510
+ ", "
2511
+ )}`
2512
+ );
2513
+ }
2514
2514
  }
2515
+ } else if (action !== null && action !== void 0 && action !== "undefined") {
2516
+ throw new Error(
2517
+ `invalid action "${action}". No actions are defined for this page`
2518
+ );
2515
2519
  }
2516
2520
  const contentUiConfig = await Promise.all(
2517
2521
  content.map(async (c) => {
@@ -2519,14 +2523,15 @@ async function page(options, data, action) {
2519
2523
  const elementData = data && typeof data === "object" && resolvedC.uiConfig.name in data ? data[resolvedC.uiConfig.name] : void 0;
2520
2524
  const { uiConfig, validationErrors } = await recursivelyProcessElement(
2521
2525
  c,
2522
- elementData
2526
+ elementData,
2527
+ options.actions && options.actions.length > 0 ? action : null
2523
2528
  );
2524
2529
  if (validationErrors) hasValidationErrors = true;
2525
2530
  return uiConfig;
2526
2531
  })
2527
2532
  );
2528
2533
  if (data && options.validate) {
2529
- const validationResult = await options.validate(data);
2534
+ const validationResult = options.actions && action !== null ? await options.validate(data, action) : await options.validate(data);
2530
2535
  if (typeof validationResult === "string") {
2531
2536
  hasValidationErrors = true;
2532
2537
  validationError = validationResult;
@@ -2556,19 +2561,21 @@ async function page(options, data, action) {
2556
2561
  };
2557
2562
  }
2558
2563
  __name(page, "page");
2559
- var recursivelyProcessElement = /* @__PURE__ */ __name(async (c, data) => {
2564
+ var recursivelyProcessElement = /* @__PURE__ */ __name(async (c, data, action) => {
2560
2565
  const resolvedC = await c;
2561
2566
  const elementType = "__type" in resolvedC ? resolvedC.__type : null;
2562
2567
  switch (elementType) {
2563
2568
  case "input":
2564
2569
  return processInputElement(
2565
2570
  resolvedC,
2566
- data
2571
+ data,
2572
+ action
2567
2573
  );
2568
2574
  case "iterator":
2569
2575
  return processIteratorElement(
2570
2576
  resolvedC,
2571
- data
2577
+ data,
2578
+ action
2572
2579
  );
2573
2580
  default:
2574
2581
  return {
@@ -2577,7 +2584,7 @@ var recursivelyProcessElement = /* @__PURE__ */ __name(async (c, data) => {
2577
2584
  };
2578
2585
  }
2579
2586
  }, "recursivelyProcessElement");
2580
- var processInputElement = /* @__PURE__ */ __name(async (element, data) => {
2587
+ var processInputElement = /* @__PURE__ */ __name(async (element, data, action) => {
2581
2588
  const hasData = data !== void 0 && data !== null;
2582
2589
  if (!hasData || !element.validate) {
2583
2590
  return {
@@ -2585,7 +2592,7 @@ var processInputElement = /* @__PURE__ */ __name(async (element, data) => {
2585
2592
  validationErrors: false
2586
2593
  };
2587
2594
  }
2588
- const validationError = await element.validate(data);
2595
+ const validationError = action !== null ? await element.validate(data, action) : await element.validate(data);
2589
2596
  const hasValidationErrors = typeof validationError === "string";
2590
2597
  return {
2591
2598
  uiConfig: {
@@ -2595,19 +2602,23 @@ var processInputElement = /* @__PURE__ */ __name(async (element, data) => {
2595
2602
  validationErrors: hasValidationErrors
2596
2603
  };
2597
2604
  }, "processInputElement");
2598
- var processIteratorElement = /* @__PURE__ */ __name(async (element, data) => {
2605
+ var processIteratorElement = /* @__PURE__ */ __name(async (element, data, action) => {
2599
2606
  const elements = element.uiConfig.content;
2600
2607
  const dataArr = data;
2601
2608
  const ui = [];
2602
2609
  for (const el of elements) {
2603
- const result = await recursivelyProcessElement(el, void 0);
2610
+ const result = await recursivelyProcessElement(el, void 0, action);
2604
2611
  ui.push(result.uiConfig);
2605
2612
  }
2606
- const validationErrors = await validateIteratorData(elements, dataArr);
2613
+ const validationErrors = await validateIteratorData(
2614
+ elements,
2615
+ dataArr,
2616
+ action
2617
+ );
2607
2618
  let hasValidationErrors = validationErrors.length > 0;
2608
2619
  let validationError = void 0;
2609
2620
  if (dataArr && element.validate) {
2610
- const v = await element.validate(dataArr);
2621
+ const v = action !== null ? await element.validate(dataArr, action) : await element.validate(dataArr);
2611
2622
  if (typeof v === "string") {
2612
2623
  hasValidationErrors = true;
2613
2624
  validationError = v;
@@ -2623,7 +2634,7 @@ var processIteratorElement = /* @__PURE__ */ __name(async (element, data) => {
2623
2634
  validationErrors: hasValidationErrors
2624
2635
  };
2625
2636
  }, "processIteratorElement");
2626
- var validateIteratorData = /* @__PURE__ */ __name(async (elements, dataArr) => {
2637
+ var validateIteratorData = /* @__PURE__ */ __name(async (elements, dataArr, action) => {
2627
2638
  const validationErrors = [];
2628
2639
  if (!dataArr || dataArr.length === 0) {
2629
2640
  return validationErrors;
@@ -2635,9 +2646,7 @@ var validateIteratorData = /* @__PURE__ */ __name(async (elements, dataArr) => {
2635
2646
  if ("__type" in resolvedEl && resolvedEl.__type === "input" && "validate" in resolvedEl && resolvedEl.validate && typeof resolvedEl.validate === "function") {
2636
2647
  const fieldName = resolvedEl.uiConfig.name;
2637
2648
  if (rowData && typeof rowData === "object" && fieldName in rowData) {
2638
- const validationError = await resolvedEl.validate(
2639
- rowData[fieldName]
2640
- );
2649
+ const validationError = action !== null ? await resolvedEl.validate(rowData[fieldName], action) : await resolvedEl.validate(rowData[fieldName]);
2641
2650
  if (typeof validationError === "string") {
2642
2651
  validationErrors.push({
2643
2652
  index: i,
@@ -2906,17 +2915,22 @@ var iterator = /* @__PURE__ */ __name((name, options) => {
2906
2915
  var print = /* @__PURE__ */ __name(async (options) => {
2907
2916
  const dataConfig = Array.isArray(options.jobs) ? options.jobs : [options.jobs];
2908
2917
  const dataPromises = dataConfig.map(async (d) => {
2909
- if ("type" in d && d.type) {
2910
- return {
2911
- type: d.type,
2912
- name: d.name,
2913
- data: Array.isArray(d.data) ? d.data : [d.data],
2914
- printer: d.printer
2915
- };
2916
- }
2917
- return null;
2918
+ return {
2919
+ type: d.type,
2920
+ name: d.name,
2921
+ data: "data" in d && d.data ? Array.isArray(d.data) ? d.data : [d.data] : void 0,
2922
+ printer: d.printer,
2923
+ url: "url" in d && d.url ? d.url : void 0,
2924
+ ...d.type === "rawPdf" ? {
2925
+ dpi: d.dpi,
2926
+ pageWidth: d.pageWidth,
2927
+ pageHeight: d.pageHeight
2928
+ } : {}
2929
+ };
2918
2930
  });
2919
- const data = (await Promise.all(dataPromises)).filter((x) => x !== null);
2931
+ const data = (await Promise.all(dataPromises)).filter(
2932
+ (x) => x !== null
2933
+ );
2920
2934
  return {
2921
2935
  uiConfig: {
2922
2936
  __type: "ui.interactive.print",
@@ -2954,7 +2968,7 @@ var pickList = /* @__PURE__ */ __name((name, options) => {
2954
2968
  };
2955
2969
  })
2956
2970
  },
2957
- validate: /* @__PURE__ */ __name(async (data) => {
2971
+ validate: /* @__PURE__ */ __name(async (data, action) => {
2958
2972
  if (!("items" in data)) {
2959
2973
  return "Missing items in response";
2960
2974
  }
@@ -2966,7 +2980,7 @@ var pickList = /* @__PURE__ */ __name((name, options) => {
2966
2980
  )) {
2967
2981
  return "Invalid data";
2968
2982
  }
2969
- return options?.validate?.(data) ?? true;
2983
+ return options?.validate?.(data, action) ?? true;
2970
2984
  }, "validate"),
2971
2985
  getData: /* @__PURE__ */ __name((x) => x, "getData")
2972
2986
  };
@@ -3006,8 +3020,8 @@ var scan = /* @__PURE__ */ __name((name, options) => {
3006
3020
  autoContinue: options.autoContinue
3007
3021
  } : {}
3008
3022
  },
3009
- validate: /* @__PURE__ */ __name(async (data) => {
3010
- return options?.validate?.(data) ?? true;
3023
+ validate: /* @__PURE__ */ __name(async (data, action) => {
3024
+ return options?.validate?.(data, action) ?? true;
3011
3025
  }, "validate"),
3012
3026
  getData: /* @__PURE__ */ __name((x) => x, "getData")
3013
3027
  };
@@ -3178,7 +3192,7 @@ function createFlowContext(runId, data, action, callback, element, spanId, ctx)
3178
3192
  });
3179
3193
  }, "step"),
3180
3194
  ui: {
3181
- page: /* @__PURE__ */ __name(async (name, options) => {
3195
+ page: /* @__PURE__ */ __name((async (name, options) => {
3182
3196
  return withSpan(`Page - ${name}`, async (span) => {
3183
3197
  const db = useDatabase();
3184
3198
  const isCallback = element && callback;
@@ -3274,7 +3288,7 @@ function createFlowContext(runId, data, action, callback, element, spanId, ctx)
3274
3288
  }
3275
3289
  return data;
3276
3290
  });
3277
- }, "page"),
3291
+ }), "page"),
3278
3292
  inputs: {
3279
3293
  text: textInput,
3280
3294
  number: numberInput,