@teamkeel/functions-runtime 0.366.0-audit-logs0 → 0.366.0-prerelease0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teamkeel/functions-runtime",
3
- "version": "0.366.0-audit-logs0",
3
+ "version": "0.366.0-prerelease0",
4
4
  "description": "Internal package used by @teamkeel/sdk",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
package/src/auditing.js CHANGED
@@ -44,14 +44,6 @@ class AuditContextPlugin {
44
44
  this.traceIdAlias = "__keel_trace_id";
45
45
  }
46
46
 
47
- #setIdentityClause(value) {
48
- return `set_identity_id('${value}')`;
49
- }
50
-
51
- #setTraceIdClause(value) {
52
- return `set_trace_id('${value}')`;
53
- }
54
-
55
47
  // Appends set_identity_id() and set_trace_id() function calls to the returning statement
56
48
  // of INSERT, UPDATE and DELETE operations.
57
49
  transformQuery(args) {
@@ -59,10 +51,13 @@ class AuditContextPlugin {
59
51
  case "InsertQueryNode":
60
52
  case "UpdateQueryNode":
61
53
  case "DeleteQueryNode":
54
+ // Represents a RETURNING clause in a SQL statement.
62
55
  const returning = {
63
56
  kind: "ReturningNode",
64
57
  selections: [],
65
58
  };
59
+
60
+ // If the query already has a selection, then append it.
66
61
  if (args.node.returning) {
67
62
  returning.selections.push(...args.node.returning.selections);
68
63
  }
@@ -71,10 +66,7 @@ class AuditContextPlugin {
71
66
  const audit = getAuditContext();
72
67
 
73
68
  if (audit.identityId) {
74
- const rawNode = sql
75
- .raw(
76
- this.#setIdentityClause(audit.identityId, this.identityIdAlias)
77
- )
69
+ const rawNode = sql`set_identity_id(${audit.identityId})`
78
70
  .as(this.identityIdAlias)
79
71
  .toOperationNode();
80
72
 
@@ -82,8 +74,7 @@ class AuditContextPlugin {
82
74
  }
83
75
 
84
76
  if (audit.traceId) {
85
- const rawNode = sql
86
- .raw(this.#setTraceIdClause(audit.traceId))
77
+ const rawNode = sql`set_trace_id(${audit.traceId})`
87
78
  .as(this.traceIdAlias)
88
79
  .toOperationNode();
89
80
 
package/src/database.js CHANGED
@@ -129,7 +129,7 @@ class InstrumentedClient extends pg.Client {
129
129
  sqlAttribute = true;
130
130
  }
131
131
 
132
- return await withSpan(spanName, function (span) {
132
+ return withSpan(spanName, function (span) {
133
133
  if (sqlAttribute) {
134
134
  span.setAttribute("sql", args[0]);
135
135
  }
@@ -282,4 +282,77 @@ describe("ModelAPI error handling", () => {
282
282
  },
283
283
  });
284
284
  });
285
+ test("when there is a uniqueness constraint error", async () => {
286
+ await sql`
287
+ INSERT INTO post (id, title, author_id) values(${
288
+ KSUID.randomSync().string
289
+ }, 'hello', 'adam')
290
+ `.execute(db);
291
+
292
+ const rpcReq = createJSONRPCRequest("123", "createPost", {
293
+ title: "hello",
294
+ author_id: "something",
295
+ });
296
+
297
+ expect(await handleRequest(rpcReq, functionConfig)).toEqual({
298
+ id: "123",
299
+ jsonrpc: "2.0",
300
+ error: {
301
+ code: RuntimeErrors.UniqueConstraintError,
302
+ message:
303
+ 'duplicate key value violates unique constraint "post_title_key"',
304
+ data: {
305
+ code: "23505",
306
+ column: "title",
307
+ detail: "Key (title)=(hello) already exists.",
308
+ table: "post",
309
+ value: "hello",
310
+ },
311
+ },
312
+ });
313
+ });
314
+
315
+ test("when there is a null value in a foreign key column", async () => {
316
+ const rpcReq = createJSONRPCRequest("123", "createPost", { title: "123" });
317
+
318
+ expect(await handleRequest(rpcReq, functionConfig)).toEqual({
319
+ id: "123",
320
+ jsonrpc: "2.0",
321
+ error: {
322
+ code: RuntimeErrors.NotNullConstraintError,
323
+ message:
324
+ 'null value in column "author_id" violates not-null constraint',
325
+ data: {
326
+ code: "23502",
327
+ column: "author_id",
328
+ detail: expect.stringContaining("Failing row contains"),
329
+ table: "post",
330
+ },
331
+ },
332
+ });
333
+ });
334
+
335
+ test("when there is a foreign key constraint violation", async () => {
336
+ const rpcReq2 = createJSONRPCRequest("123", "createPost", {
337
+ title: "123",
338
+ author_id: "fake",
339
+ });
340
+
341
+ expect(await handleRequest(rpcReq2, functionConfig)).toEqual({
342
+ id: "123",
343
+ jsonrpc: "2.0",
344
+ error: {
345
+ code: RuntimeErrors.ForeignKeyConstraintError,
346
+ message:
347
+ 'insert or update on table "post" violates foreign key constraint "post_author_id_fkey"',
348
+ data: {
349
+ code: "23503",
350
+ column: "author_id",
351
+ detail: 'Key (author_id)=(fake) is not present in table "author".',
352
+ table: "post",
353
+ value: "fake",
354
+ },
355
+ },
356
+ });
357
+ });
285
358
  });