@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.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.
|
|
763
|
-
if (
|
|
616
|
+
const endpoint = process.env.KEEL_S3_ENDPOINT;
|
|
617
|
+
if (endpoint) {
|
|
618
|
+
return new import_client_s3.S3Client({
|
|
619
|
+
region: process.env.KEEL_REGION,
|
|
620
|
+
credentials: {
|
|
621
|
+
accessKeyId: "keelstorage",
|
|
622
|
+
secretAccessKey: "keelstorage"
|
|
623
|
+
},
|
|
624
|
+
endpoint
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
const testEndpoint = process.env.TEST_AWS_ENDPOINT;
|
|
628
|
+
if (testEndpoint) {
|
|
764
629
|
return new import_client_s3.S3Client({
|
|
765
630
|
region: process.env.KEEL_REGION,
|
|
766
|
-
credentials:
|
|
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
|
-
|
|
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,17 +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
|
-
|
|
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
|
-
return new URL(`${process.env.KEEL_API_URL}/files/${this.key}`);
|
|
777
|
+
if (!s3Client) {
|
|
778
|
+
throw new Error("S3 client is required");
|
|
929
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);
|
|
930
787
|
}
|
|
931
788
|
// Persists the file
|
|
932
789
|
toDbRecord() {
|
|
@@ -942,54 +799,36 @@ var File = class _File extends InlineFile {
|
|
|
942
799
|
}
|
|
943
800
|
};
|
|
944
801
|
async function storeFile(contents, key, filename, contentType, size, expires) {
|
|
945
|
-
if (s3Client) {
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
}
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
const command = new import_client_s3.PutObjectCommand(params);
|
|
967
|
-
try {
|
|
968
|
-
await s3Client.send(command);
|
|
969
|
-
} catch (error) {
|
|
970
|
-
console.error("Error uploading file:", error);
|
|
971
|
-
throw error;
|
|
972
|
-
}
|
|
973
|
-
} else {
|
|
974
|
-
const db = useDatabase();
|
|
975
|
-
try {
|
|
976
|
-
const query = db.insertInto("keel_storage").values({
|
|
977
|
-
id: key,
|
|
978
|
-
filename,
|
|
979
|
-
content_type: contentType,
|
|
980
|
-
data: contents
|
|
981
|
-
}).onConflict(
|
|
982
|
-
(oc) => oc.column("id").doUpdateSet(() => ({
|
|
983
|
-
filename,
|
|
984
|
-
content_type: contentType,
|
|
985
|
-
data: contents
|
|
986
|
-
})).where("keel_storage.id", "=", key)
|
|
987
|
-
).returningAll();
|
|
988
|
-
await query.execute();
|
|
989
|
-
} catch (e) {
|
|
990
|
-
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.");
|
|
991
823
|
}
|
|
992
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
|
+
}
|
|
993
832
|
}
|
|
994
833
|
__name(storeFile, "storeFile");
|
|
995
834
|
|
|
@@ -1429,6 +1268,150 @@ function joinAlias(tablePath) {
|
|
|
1429
1268
|
}
|
|
1430
1269
|
__name(joinAlias, "joinAlias");
|
|
1431
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
|
+
|
|
1432
1415
|
// src/QueryBuilder.js
|
|
1433
1416
|
var QueryBuilder = class _QueryBuilder {
|
|
1434
1417
|
static {
|
|
@@ -2501,15 +2484,38 @@ async function page(options, data, action) {
|
|
|
2501
2484
|
const content = options.content;
|
|
2502
2485
|
let hasValidationErrors = false;
|
|
2503
2486
|
let validationError;
|
|
2504
|
-
if (options.actions &&
|
|
2505
|
-
const
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
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
|
+
}
|
|
2512
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
|
+
);
|
|
2513
2519
|
}
|
|
2514
2520
|
const contentUiConfig = await Promise.all(
|
|
2515
2521
|
content.map(async (c) => {
|