@teamkeel/functions-runtime 0.424.0 → 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 +245 -239
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +245 -239
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -558,175 +558,40 @@ import {
|
|
|
558
558
|
} from "@aws-sdk/client-s3";
|
|
559
559
|
import { fromEnv } from "@aws-sdk/credential-providers";
|
|
560
560
|
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
|
|
561
|
-
|
|
562
|
-
// src/errors.js
|
|
563
|
-
import { createJSONRPCErrorResponse } from "json-rpc-2.0";
|
|
564
|
-
var RuntimeErrors = {
|
|
565
|
-
// Catchall error type for unhandled execution errors during custom function
|
|
566
|
-
UnknownError: -32001,
|
|
567
|
-
// DatabaseError represents any error at pg level that isn't handled explicitly below
|
|
568
|
-
DatabaseError: -32002,
|
|
569
|
-
// No result returned from custom function by user
|
|
570
|
-
NoResultError: -32003,
|
|
571
|
-
// When trying to delete/update a non existent record in the db
|
|
572
|
-
RecordNotFoundError: -32004,
|
|
573
|
-
ForeignKeyConstraintError: -32005,
|
|
574
|
-
NotNullConstraintError: -32006,
|
|
575
|
-
UniqueConstraintError: -32007,
|
|
576
|
-
PermissionError: -32008,
|
|
577
|
-
BadRequestError: -32009
|
|
578
|
-
};
|
|
579
|
-
var PermissionError = class extends Error {
|
|
580
|
-
static {
|
|
581
|
-
__name(this, "PermissionError");
|
|
582
|
-
}
|
|
583
|
-
};
|
|
584
|
-
var DatabaseError = class extends Error {
|
|
585
|
-
static {
|
|
586
|
-
__name(this, "DatabaseError");
|
|
587
|
-
}
|
|
588
|
-
constructor(error) {
|
|
589
|
-
super(error.message);
|
|
590
|
-
this.error = error;
|
|
591
|
-
}
|
|
592
|
-
};
|
|
593
|
-
var NotFoundError = class extends Error {
|
|
594
|
-
static {
|
|
595
|
-
__name(this, "NotFoundError");
|
|
596
|
-
}
|
|
597
|
-
errorCode = RuntimeErrors.RecordNotFoundError;
|
|
598
|
-
constructor(message) {
|
|
599
|
-
super(message);
|
|
600
|
-
}
|
|
601
|
-
};
|
|
602
|
-
var BadRequestError = class extends Error {
|
|
603
|
-
static {
|
|
604
|
-
__name(this, "BadRequestError");
|
|
605
|
-
}
|
|
606
|
-
errorCode = RuntimeErrors.BadRequestError;
|
|
607
|
-
constructor(message = "bad request") {
|
|
608
|
-
super(message);
|
|
609
|
-
}
|
|
610
|
-
};
|
|
611
|
-
var UnknownError = class extends Error {
|
|
612
|
-
static {
|
|
613
|
-
__name(this, "UnknownError");
|
|
614
|
-
}
|
|
615
|
-
errorCode = RuntimeErrors.UnknownError;
|
|
616
|
-
constructor(message = "unknown error") {
|
|
617
|
-
super(message);
|
|
618
|
-
}
|
|
619
|
-
};
|
|
620
|
-
var ErrorPresets = {
|
|
621
|
-
NotFound: NotFoundError,
|
|
622
|
-
BadRequest: BadRequestError,
|
|
623
|
-
Unknown: UnknownError
|
|
624
|
-
};
|
|
625
|
-
function errorToJSONRPCResponse(request, e) {
|
|
626
|
-
switch (e.constructor.name) {
|
|
627
|
-
case "PermissionError":
|
|
628
|
-
return createJSONRPCErrorResponse(
|
|
629
|
-
request.id,
|
|
630
|
-
RuntimeErrors.PermissionError,
|
|
631
|
-
e.message
|
|
632
|
-
);
|
|
633
|
-
// Any error thrown in the ModelAPI class is
|
|
634
|
-
// wrapped in a DatabaseError in order to differentiate 'our code' vs the user's own code.
|
|
635
|
-
case "NoResultError":
|
|
636
|
-
return createJSONRPCErrorResponse(
|
|
637
|
-
request.id,
|
|
638
|
-
// to be matched to https://github.com/teamkeel/keel/blob/e3115ffe381bfc371d4f45bbf96a15072a994ce5/runtime/actions/update.go#L54-L54
|
|
639
|
-
RuntimeErrors.RecordNotFoundError,
|
|
640
|
-
""
|
|
641
|
-
// 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
|
|
642
|
-
);
|
|
643
|
-
case "DatabaseError":
|
|
644
|
-
let err = e;
|
|
645
|
-
if (e instanceof DatabaseError) {
|
|
646
|
-
err = e.error;
|
|
647
|
-
}
|
|
648
|
-
if (err.constructor.name == "NoResultError") {
|
|
649
|
-
return createJSONRPCErrorResponse(
|
|
650
|
-
request.id,
|
|
651
|
-
// to be matched to https://github.com/teamkeel/keel/blob/e3115ffe381bfc371d4f45bbf96a15072a994ce5/runtime/actions/update.go#L54-L54
|
|
652
|
-
RuntimeErrors.RecordNotFoundError,
|
|
653
|
-
""
|
|
654
|
-
// 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
|
|
655
|
-
);
|
|
656
|
-
}
|
|
657
|
-
if ("code" in err) {
|
|
658
|
-
const { code: code2, detail, table: table2 } = err;
|
|
659
|
-
let rpcErrorCode, column, value;
|
|
660
|
-
const [col, val] = parseKeyMessage(err.detail);
|
|
661
|
-
column = col;
|
|
662
|
-
value = val;
|
|
663
|
-
switch (code2) {
|
|
664
|
-
case "23502":
|
|
665
|
-
rpcErrorCode = RuntimeErrors.NotNullConstraintError;
|
|
666
|
-
column = err.column;
|
|
667
|
-
break;
|
|
668
|
-
case "23503":
|
|
669
|
-
rpcErrorCode = RuntimeErrors.ForeignKeyConstraintError;
|
|
670
|
-
break;
|
|
671
|
-
case "23505":
|
|
672
|
-
rpcErrorCode = RuntimeErrors.UniqueConstraintError;
|
|
673
|
-
break;
|
|
674
|
-
default:
|
|
675
|
-
rpcErrorCode = RuntimeErrors.DatabaseError;
|
|
676
|
-
break;
|
|
677
|
-
}
|
|
678
|
-
return createJSONRPCErrorResponse(request.id, rpcErrorCode, e.message, {
|
|
679
|
-
table: table2,
|
|
680
|
-
column,
|
|
681
|
-
code: code2,
|
|
682
|
-
detail,
|
|
683
|
-
value
|
|
684
|
-
});
|
|
685
|
-
}
|
|
686
|
-
return createJSONRPCErrorResponse(
|
|
687
|
-
request.id,
|
|
688
|
-
RuntimeErrors.DatabaseError,
|
|
689
|
-
e.message
|
|
690
|
-
);
|
|
691
|
-
default:
|
|
692
|
-
return createJSONRPCErrorResponse(
|
|
693
|
-
request.id,
|
|
694
|
-
e.errorCode ?? RuntimeErrors.UnknownError,
|
|
695
|
-
e.message
|
|
696
|
-
);
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
__name(errorToJSONRPCResponse, "errorToJSONRPCResponse");
|
|
700
|
-
var keyMessagePattern = /\Key\s[(](.*)[)][=][(](.*)[)]/;
|
|
701
|
-
var parseKeyMessage = /* @__PURE__ */ __name((msg) => {
|
|
702
|
-
const [, col, value] = keyMessagePattern.exec(msg) || [];
|
|
703
|
-
return [col, value];
|
|
704
|
-
}, "parseKeyMessage");
|
|
705
|
-
|
|
706
|
-
// src/File.ts
|
|
707
561
|
import KSUID from "ksuid";
|
|
708
562
|
var s3Client = (() => {
|
|
709
563
|
if (!process.env.KEEL_FILES_BUCKET_NAME) {
|
|
710
564
|
return null;
|
|
711
565
|
}
|
|
712
|
-
const endpoint = process.env.
|
|
713
|
-
if (
|
|
566
|
+
const endpoint = process.env.KEEL_S3_ENDPOINT;
|
|
567
|
+
if (endpoint) {
|
|
568
|
+
return new S3Client({
|
|
569
|
+
region: process.env.KEEL_REGION,
|
|
570
|
+
credentials: {
|
|
571
|
+
accessKeyId: "keelstorage",
|
|
572
|
+
secretAccessKey: "keelstorage"
|
|
573
|
+
},
|
|
574
|
+
endpoint
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
const testEndpoint = process.env.TEST_AWS_ENDPOINT;
|
|
578
|
+
if (testEndpoint) {
|
|
714
579
|
return new S3Client({
|
|
715
580
|
region: process.env.KEEL_REGION,
|
|
716
|
-
credentials:
|
|
581
|
+
credentials: {
|
|
582
|
+
accessKeyId: "test",
|
|
583
|
+
secretAccessKey: "test"
|
|
584
|
+
},
|
|
585
|
+
endpointProvider: /* @__PURE__ */ __name(() => {
|
|
586
|
+
return {
|
|
587
|
+
url: new URL(testEndpoint)
|
|
588
|
+
};
|
|
589
|
+
}, "endpointProvider")
|
|
717
590
|
});
|
|
718
591
|
}
|
|
719
592
|
return new S3Client({
|
|
720
593
|
region: process.env.KEEL_REGION,
|
|
721
|
-
credentials:
|
|
722
|
-
accessKeyId: "test",
|
|
723
|
-
secretAccessKey: "test"
|
|
724
|
-
},
|
|
725
|
-
endpointProvider: /* @__PURE__ */ __name(() => {
|
|
726
|
-
return {
|
|
727
|
-
url: new URL(endpoint)
|
|
728
|
-
};
|
|
729
|
-
}, "endpointProvider")
|
|
594
|
+
credentials: fromEnv()
|
|
730
595
|
});
|
|
731
596
|
})();
|
|
732
597
|
var InlineFile = class _InlineFile {
|
|
@@ -831,24 +696,17 @@ var File = class _File extends InlineFile {
|
|
|
831
696
|
const arrayBuffer = await this._contents.arrayBuffer();
|
|
832
697
|
return Buffer.from(arrayBuffer);
|
|
833
698
|
}
|
|
834
|
-
if (s3Client) {
|
|
835
|
-
|
|
836
|
-
Bucket: process.env.KEEL_FILES_BUCKET_NAME,
|
|
837
|
-
Key: "files/" + this.key
|
|
838
|
-
};
|
|
839
|
-
const command = new GetObjectCommand(params);
|
|
840
|
-
const response = await s3Client.send(command);
|
|
841
|
-
const blob = await response.Body.transformToByteArray();
|
|
842
|
-
return Buffer.from(blob);
|
|
843
|
-
}
|
|
844
|
-
const db = useDatabase();
|
|
845
|
-
try {
|
|
846
|
-
const query = db.selectFrom("keel_storage").select("data").where("id", "=", this.key);
|
|
847
|
-
const row = await query.executeTakeFirstOrThrow();
|
|
848
|
-
return row.data;
|
|
849
|
-
} catch (e) {
|
|
850
|
-
throw new DatabaseError(e);
|
|
699
|
+
if (!s3Client) {
|
|
700
|
+
throw new Error("S3 client is required");
|
|
851
701
|
}
|
|
702
|
+
const params = {
|
|
703
|
+
Bucket: process.env.KEEL_FILES_BUCKET_NAME,
|
|
704
|
+
Key: "files/" + this.key
|
|
705
|
+
};
|
|
706
|
+
const command = new GetObjectCommand(params);
|
|
707
|
+
const response = await s3Client.send(command);
|
|
708
|
+
const blob = await response.Body.transformToByteArray();
|
|
709
|
+
return Buffer.from(blob);
|
|
852
710
|
}
|
|
853
711
|
async store(expires = null) {
|
|
854
712
|
if (this._contents) {
|
|
@@ -866,17 +724,16 @@ var File = class _File extends InlineFile {
|
|
|
866
724
|
}
|
|
867
725
|
// Generates a presigned download URL
|
|
868
726
|
async getPresignedUrl() {
|
|
869
|
-
if (s3Client) {
|
|
870
|
-
|
|
871
|
-
Bucket: process.env.KEEL_FILES_BUCKET_NAME,
|
|
872
|
-
Key: "files/" + this.key,
|
|
873
|
-
ResponseContentDisposition: "inline"
|
|
874
|
-
});
|
|
875
|
-
const url = await getSignedUrl(s3Client, command, { expiresIn: 60 * 60 });
|
|
876
|
-
return new URL(url);
|
|
877
|
-
} else {
|
|
878
|
-
return new URL(`${process.env.KEEL_API_URL}/files/${this.key}`);
|
|
727
|
+
if (!s3Client) {
|
|
728
|
+
throw new Error("S3 client is required");
|
|
879
729
|
}
|
|
730
|
+
const command = new GetObjectCommand({
|
|
731
|
+
Bucket: process.env.KEEL_FILES_BUCKET_NAME,
|
|
732
|
+
Key: "files/" + this.key,
|
|
733
|
+
ResponseContentDisposition: "inline"
|
|
734
|
+
});
|
|
735
|
+
const url = await getSignedUrl(s3Client, command, { expiresIn: 60 * 60 });
|
|
736
|
+
return new URL(url);
|
|
880
737
|
}
|
|
881
738
|
// Persists the file
|
|
882
739
|
toDbRecord() {
|
|
@@ -892,54 +749,36 @@ var File = class _File extends InlineFile {
|
|
|
892
749
|
}
|
|
893
750
|
};
|
|
894
751
|
async function storeFile(contents, key, filename, contentType, size, expires) {
|
|
895
|
-
if (s3Client) {
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
}
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
const command = new PutObjectCommand(params);
|
|
917
|
-
try {
|
|
918
|
-
await s3Client.send(command);
|
|
919
|
-
} catch (error) {
|
|
920
|
-
console.error("Error uploading file:", error);
|
|
921
|
-
throw error;
|
|
922
|
-
}
|
|
923
|
-
} else {
|
|
924
|
-
const db = useDatabase();
|
|
925
|
-
try {
|
|
926
|
-
const query = db.insertInto("keel_storage").values({
|
|
927
|
-
id: key,
|
|
928
|
-
filename,
|
|
929
|
-
content_type: contentType,
|
|
930
|
-
data: contents
|
|
931
|
-
}).onConflict(
|
|
932
|
-
(oc) => oc.column("id").doUpdateSet(() => ({
|
|
933
|
-
filename,
|
|
934
|
-
content_type: contentType,
|
|
935
|
-
data: contents
|
|
936
|
-
})).where("keel_storage.id", "=", key)
|
|
937
|
-
).returningAll();
|
|
938
|
-
await query.execute();
|
|
939
|
-
} catch (e) {
|
|
940
|
-
throw new DatabaseError(e);
|
|
752
|
+
if (!s3Client) {
|
|
753
|
+
throw new Error("S3 client is required");
|
|
754
|
+
}
|
|
755
|
+
const params = {
|
|
756
|
+
Bucket: process.env.KEEL_FILES_BUCKET_NAME,
|
|
757
|
+
Key: "files/" + key,
|
|
758
|
+
Body: contents,
|
|
759
|
+
ContentType: contentType,
|
|
760
|
+
ContentDisposition: `attachment; filename="${encodeURIComponent(
|
|
761
|
+
filename
|
|
762
|
+
)}"`,
|
|
763
|
+
Metadata: {
|
|
764
|
+
filename
|
|
765
|
+
},
|
|
766
|
+
ACL: "private"
|
|
767
|
+
};
|
|
768
|
+
if (expires) {
|
|
769
|
+
if (expires instanceof Date) {
|
|
770
|
+
params.Expires = expires;
|
|
771
|
+
} else {
|
|
772
|
+
console.warn("Invalid expires value. Skipping Expires parameter.");
|
|
941
773
|
}
|
|
942
774
|
}
|
|
775
|
+
const command = new PutObjectCommand(params);
|
|
776
|
+
try {
|
|
777
|
+
await s3Client.send(command);
|
|
778
|
+
} catch (error) {
|
|
779
|
+
console.error("Error uploading file:", error);
|
|
780
|
+
throw error;
|
|
781
|
+
}
|
|
943
782
|
}
|
|
944
783
|
__name(storeFile, "storeFile");
|
|
945
784
|
|
|
@@ -1379,6 +1218,150 @@ function joinAlias(tablePath) {
|
|
|
1379
1218
|
}
|
|
1380
1219
|
__name(joinAlias, "joinAlias");
|
|
1381
1220
|
|
|
1221
|
+
// src/errors.js
|
|
1222
|
+
import { createJSONRPCErrorResponse } from "json-rpc-2.0";
|
|
1223
|
+
var RuntimeErrors = {
|
|
1224
|
+
// Catchall error type for unhandled execution errors during custom function
|
|
1225
|
+
UnknownError: -32001,
|
|
1226
|
+
// DatabaseError represents any error at pg level that isn't handled explicitly below
|
|
1227
|
+
DatabaseError: -32002,
|
|
1228
|
+
// No result returned from custom function by user
|
|
1229
|
+
NoResultError: -32003,
|
|
1230
|
+
// When trying to delete/update a non existent record in the db
|
|
1231
|
+
RecordNotFoundError: -32004,
|
|
1232
|
+
ForeignKeyConstraintError: -32005,
|
|
1233
|
+
NotNullConstraintError: -32006,
|
|
1234
|
+
UniqueConstraintError: -32007,
|
|
1235
|
+
PermissionError: -32008,
|
|
1236
|
+
BadRequestError: -32009
|
|
1237
|
+
};
|
|
1238
|
+
var PermissionError = class extends Error {
|
|
1239
|
+
static {
|
|
1240
|
+
__name(this, "PermissionError");
|
|
1241
|
+
}
|
|
1242
|
+
};
|
|
1243
|
+
var DatabaseError = class extends Error {
|
|
1244
|
+
static {
|
|
1245
|
+
__name(this, "DatabaseError");
|
|
1246
|
+
}
|
|
1247
|
+
constructor(error) {
|
|
1248
|
+
super(error.message);
|
|
1249
|
+
this.error = error;
|
|
1250
|
+
}
|
|
1251
|
+
};
|
|
1252
|
+
var NotFoundError = class extends Error {
|
|
1253
|
+
static {
|
|
1254
|
+
__name(this, "NotFoundError");
|
|
1255
|
+
}
|
|
1256
|
+
errorCode = RuntimeErrors.RecordNotFoundError;
|
|
1257
|
+
constructor(message) {
|
|
1258
|
+
super(message);
|
|
1259
|
+
}
|
|
1260
|
+
};
|
|
1261
|
+
var BadRequestError = class extends Error {
|
|
1262
|
+
static {
|
|
1263
|
+
__name(this, "BadRequestError");
|
|
1264
|
+
}
|
|
1265
|
+
errorCode = RuntimeErrors.BadRequestError;
|
|
1266
|
+
constructor(message = "bad request") {
|
|
1267
|
+
super(message);
|
|
1268
|
+
}
|
|
1269
|
+
};
|
|
1270
|
+
var UnknownError = class extends Error {
|
|
1271
|
+
static {
|
|
1272
|
+
__name(this, "UnknownError");
|
|
1273
|
+
}
|
|
1274
|
+
errorCode = RuntimeErrors.UnknownError;
|
|
1275
|
+
constructor(message = "unknown error") {
|
|
1276
|
+
super(message);
|
|
1277
|
+
}
|
|
1278
|
+
};
|
|
1279
|
+
var ErrorPresets = {
|
|
1280
|
+
NotFound: NotFoundError,
|
|
1281
|
+
BadRequest: BadRequestError,
|
|
1282
|
+
Unknown: UnknownError
|
|
1283
|
+
};
|
|
1284
|
+
function errorToJSONRPCResponse(request, e) {
|
|
1285
|
+
switch (e.constructor.name) {
|
|
1286
|
+
case "PermissionError":
|
|
1287
|
+
return createJSONRPCErrorResponse(
|
|
1288
|
+
request.id,
|
|
1289
|
+
RuntimeErrors.PermissionError,
|
|
1290
|
+
e.message
|
|
1291
|
+
);
|
|
1292
|
+
// Any error thrown in the ModelAPI class is
|
|
1293
|
+
// wrapped in a DatabaseError in order to differentiate 'our code' vs the user's own code.
|
|
1294
|
+
case "NoResultError":
|
|
1295
|
+
return createJSONRPCErrorResponse(
|
|
1296
|
+
request.id,
|
|
1297
|
+
// to be matched to https://github.com/teamkeel/keel/blob/e3115ffe381bfc371d4f45bbf96a15072a994ce5/runtime/actions/update.go#L54-L54
|
|
1298
|
+
RuntimeErrors.RecordNotFoundError,
|
|
1299
|
+
""
|
|
1300
|
+
// 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
|
|
1301
|
+
);
|
|
1302
|
+
case "DatabaseError":
|
|
1303
|
+
let err = e;
|
|
1304
|
+
if (e instanceof DatabaseError) {
|
|
1305
|
+
err = e.error;
|
|
1306
|
+
}
|
|
1307
|
+
if (err.constructor.name == "NoResultError") {
|
|
1308
|
+
return createJSONRPCErrorResponse(
|
|
1309
|
+
request.id,
|
|
1310
|
+
// to be matched to https://github.com/teamkeel/keel/blob/e3115ffe381bfc371d4f45bbf96a15072a994ce5/runtime/actions/update.go#L54-L54
|
|
1311
|
+
RuntimeErrors.RecordNotFoundError,
|
|
1312
|
+
""
|
|
1313
|
+
// 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
|
|
1314
|
+
);
|
|
1315
|
+
}
|
|
1316
|
+
if ("code" in err) {
|
|
1317
|
+
const { code: code2, detail, table: table2 } = err;
|
|
1318
|
+
let rpcErrorCode, column, value;
|
|
1319
|
+
const [col, val] = parseKeyMessage(err.detail);
|
|
1320
|
+
column = col;
|
|
1321
|
+
value = val;
|
|
1322
|
+
switch (code2) {
|
|
1323
|
+
case "23502":
|
|
1324
|
+
rpcErrorCode = RuntimeErrors.NotNullConstraintError;
|
|
1325
|
+
column = err.column;
|
|
1326
|
+
break;
|
|
1327
|
+
case "23503":
|
|
1328
|
+
rpcErrorCode = RuntimeErrors.ForeignKeyConstraintError;
|
|
1329
|
+
break;
|
|
1330
|
+
case "23505":
|
|
1331
|
+
rpcErrorCode = RuntimeErrors.UniqueConstraintError;
|
|
1332
|
+
break;
|
|
1333
|
+
default:
|
|
1334
|
+
rpcErrorCode = RuntimeErrors.DatabaseError;
|
|
1335
|
+
break;
|
|
1336
|
+
}
|
|
1337
|
+
return createJSONRPCErrorResponse(request.id, rpcErrorCode, e.message, {
|
|
1338
|
+
table: table2,
|
|
1339
|
+
column,
|
|
1340
|
+
code: code2,
|
|
1341
|
+
detail,
|
|
1342
|
+
value
|
|
1343
|
+
});
|
|
1344
|
+
}
|
|
1345
|
+
return createJSONRPCErrorResponse(
|
|
1346
|
+
request.id,
|
|
1347
|
+
RuntimeErrors.DatabaseError,
|
|
1348
|
+
e.message
|
|
1349
|
+
);
|
|
1350
|
+
default:
|
|
1351
|
+
return createJSONRPCErrorResponse(
|
|
1352
|
+
request.id,
|
|
1353
|
+
e.errorCode ?? RuntimeErrors.UnknownError,
|
|
1354
|
+
e.message
|
|
1355
|
+
);
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
__name(errorToJSONRPCResponse, "errorToJSONRPCResponse");
|
|
1359
|
+
var keyMessagePattern = /\Key\s[(](.*)[)][=][(](.*)[)]/;
|
|
1360
|
+
var parseKeyMessage = /* @__PURE__ */ __name((msg) => {
|
|
1361
|
+
const [, col, value] = keyMessagePattern.exec(msg) || [];
|
|
1362
|
+
return [col, value];
|
|
1363
|
+
}, "parseKeyMessage");
|
|
1364
|
+
|
|
1382
1365
|
// src/QueryBuilder.js
|
|
1383
1366
|
var QueryBuilder = class _QueryBuilder {
|
|
1384
1367
|
static {
|
|
@@ -2471,15 +2454,38 @@ async function page(options, data, action) {
|
|
|
2471
2454
|
const content = options.content;
|
|
2472
2455
|
let hasValidationErrors = false;
|
|
2473
2456
|
let validationError;
|
|
2474
|
-
if (options.actions &&
|
|
2475
|
-
const
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2457
|
+
if (options.actions && options.actions.length > 0) {
|
|
2458
|
+
const normalizedAction = action === "undefined" || action === void 0 ? null : action;
|
|
2459
|
+
if (data !== null) {
|
|
2460
|
+
if (normalizedAction === null) {
|
|
2461
|
+
const validValues = options.actions.map((a) => {
|
|
2462
|
+
if (typeof a === "string") return a;
|
|
2463
|
+
return a && typeof a === "object" && "value" in a ? a.value : "";
|
|
2464
|
+
}).filter(Boolean);
|
|
2465
|
+
throw new Error(
|
|
2466
|
+
`action is required. Valid actions are: ${validValues.join(", ")}`
|
|
2467
|
+
);
|
|
2468
|
+
}
|
|
2469
|
+
const isValidAction = options.actions.some((a) => {
|
|
2470
|
+
if (typeof a === "string") return a === normalizedAction;
|
|
2471
|
+
return a && typeof a === "object" && "value" in a && a.value === normalizedAction;
|
|
2472
|
+
});
|
|
2473
|
+
if (!isValidAction) {
|
|
2474
|
+
const validValues = options.actions.map((a) => {
|
|
2475
|
+
if (typeof a === "string") return a;
|
|
2476
|
+
return a && typeof a === "object" && "value" in a ? a.value : "";
|
|
2477
|
+
}).filter(Boolean);
|
|
2478
|
+
throw new Error(
|
|
2479
|
+
`invalid action "${normalizedAction}". Valid actions are: ${validValues.join(
|
|
2480
|
+
", "
|
|
2481
|
+
)}`
|
|
2482
|
+
);
|
|
2483
|
+
}
|
|
2482
2484
|
}
|
|
2485
|
+
} else if (action !== null && action !== void 0 && action !== "undefined") {
|
|
2486
|
+
throw new Error(
|
|
2487
|
+
`invalid action "${action}". No actions are defined for this page`
|
|
2488
|
+
);
|
|
2483
2489
|
}
|
|
2484
2490
|
const contentUiConfig = await Promise.all(
|
|
2485
2491
|
content.map(async (c) => {
|