@teamkeel/functions-runtime 0.245.0 → 0.245.2

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/src/ModelAPI.js CHANGED
@@ -24,6 +24,13 @@ const { camelCaseObject, snakeCaseObject } = require("./casing");
24
24
  * @typedef {Object.<string, TableConfig>} TableConfigMap
25
25
  */
26
26
 
27
+ class DatabaseError extends Error {
28
+ constructor(error) {
29
+ super(error.message);
30
+ this.error = error;
31
+ }
32
+ }
33
+
27
34
  class ModelAPI {
28
35
  /**
29
36
  * @param {string} tableName The name of the table this API is for
@@ -39,18 +46,22 @@ class ModelAPI {
39
46
  }
40
47
 
41
48
  async create(values) {
42
- const row = await this._db
43
- .insertInto(this._tableName)
44
- .values(
45
- snakeCaseObject({
46
- ...this._defaultValues(),
47
- ...values,
48
- })
49
- )
50
- .returningAll()
51
- .executeTakeFirst();
52
-
53
- return camelCaseObject(row);
49
+ try {
50
+ const row = await this._db
51
+ .insertInto(this._tableName)
52
+ .values(
53
+ snakeCaseObject({
54
+ ...this._defaultValues(),
55
+ ...values,
56
+ })
57
+ )
58
+ .returningAll()
59
+ .executeTakeFirstOrThrow();
60
+
61
+ return camelCaseObject(row);
62
+ } catch (e) {
63
+ throw new DatabaseError(e);
64
+ }
54
65
  }
55
66
 
56
67
  async findOne(where) {
@@ -97,8 +108,13 @@ class ModelAPI {
97
108
  // TODO: support joins for update
98
109
  builder = applyWhereConditions(context, builder, where);
99
110
 
100
- const row = await builder.executeTakeFirstOrThrow();
101
- return camelCaseObject(row);
111
+ try {
112
+ const row = await builder.executeTakeFirstOrThrow();
113
+
114
+ return camelCaseObject(row);
115
+ } catch (e) {
116
+ throw new DatabaseError(e);
117
+ }
102
118
  }
103
119
 
104
120
  async delete(where) {
@@ -109,8 +125,13 @@ class ModelAPI {
109
125
  // TODO: support joins for delete
110
126
  builder = applyWhereConditions(context, builder, where);
111
127
 
112
- const row = await builder.executeTakeFirstOrThrow();
113
- return row.id;
128
+ try {
129
+ const row = await builder.executeTakeFirstOrThrow();
130
+
131
+ return row.id;
132
+ } catch (e) {
133
+ throw new DatabaseError(e);
134
+ }
114
135
  }
115
136
 
116
137
  where(where) {
@@ -130,4 +151,5 @@ class ModelAPI {
130
151
 
131
152
  module.exports = {
132
153
  ModelAPI,
154
+ DatabaseError,
133
155
  };
package/src/errors.js ADDED
@@ -0,0 +1,34 @@
1
+ const { DatabaseError } = require("./ModelAPI");
2
+ const { createJSONRPCErrorResponse } = require("json-rpc-2.0");
3
+
4
+ const RuntimeErrors = {
5
+ UnknownError: -32001,
6
+ DatabaseError: -32002,
7
+ };
8
+
9
+ // transforms a JavaScript Error instance (or derivative) into a valid JSONRPC response object
10
+ // to pass back to the Keel runtime
11
+ function errorToJSONRPCResponse(request, e) {
12
+ // we want to switch on instanceof but there is no way to do that in js, so best to check the constructor class of the error
13
+
14
+ // todo: fuzzy matching on postgres errors from both rds-data-api and pg-protocol
15
+ switch (e.constructor) {
16
+ case DatabaseError:
17
+ return createJSONRPCErrorResponse(
18
+ request.id,
19
+ RuntimeErrors.DatabaseError,
20
+ e.message
21
+ );
22
+ default:
23
+ return createJSONRPCErrorResponse(
24
+ request.id,
25
+ RuntimeErrors.UnknownError,
26
+ e.message
27
+ );
28
+ }
29
+ }
30
+
31
+ module.exports = {
32
+ errorToJSONRPCResponse,
33
+ RuntimeErrors,
34
+ };
@@ -4,6 +4,8 @@ const {
4
4
  JSONRPCErrorCode,
5
5
  } = require("json-rpc-2.0");
6
6
 
7
+ const { errorToJSONRPCResponse, RuntimeErrors } = require("./errors");
8
+
7
9
  // Generic handler function that is agnostic to runtime environment (local or lambda)
8
10
  // to execute a custom function based on the contents of a jsonrpc-2.0 payload object.
9
11
  // To read more about jsonrpc request and response shapes, please read https://www.jsonrpc.org/specification
@@ -35,20 +37,19 @@ async function handleRequest(request, config) {
35
37
 
36
38
  return createJSONRPCSuccessResponse(request.id, result);
37
39
  } catch (e) {
38
- let msg = "";
39
-
40
40
  if (e instanceof Error) {
41
- msg = e.message;
42
- } else {
43
- msg = JSON.stringify(e);
41
+ return errorToJSONRPCResponse(request, e);
44
42
  }
45
43
 
46
44
  return createJSONRPCErrorResponse(
47
45
  request.id,
48
- JSONRPCErrorCode.InternalError,
49
- msg
46
+ RuntimeErrors.UnknownError,
47
+ JSON.stringify(e)
50
48
  );
51
49
  }
52
50
  }
53
51
 
54
- module.exports.handleRequest = handleRequest;
52
+ module.exports = {
53
+ handleRequest,
54
+ RuntimeErrors,
55
+ };
@@ -1,5 +1,5 @@
1
1
  import { createJSONRPCRequest, JSONRPCErrorCode } from "json-rpc-2.0";
2
- import { handleRequest } from "./handleRequest";
2
+ import { handleRequest, RuntimeErrors } from "./handleRequest";
3
3
  import { test, expect } from "vitest";
4
4
 
5
5
  test("when the custom function returns expected value", async () => {
@@ -83,7 +83,7 @@ test("when there is an unexpected error in the custom function", async () => {
83
83
  id: "123",
84
84
  jsonrpc: "2.0",
85
85
  error: {
86
- code: JSONRPCErrorCode.InternalError,
86
+ code: RuntimeErrors.UnknownError,
87
87
  message: "oopsie daisy",
88
88
  },
89
89
  });
@@ -105,7 +105,7 @@ test("when there is an unexpected object thrown in the custom function", async (
105
105
  id: "123",
106
106
  jsonrpc: "2.0",
107
107
  error: {
108
- code: JSONRPCErrorCode.InternalError,
108
+ code: RuntimeErrors.UnknownError,
109
109
  message: '{"err":"oopsie daisy"}',
110
110
  },
111
111
  });