@teamkeel/functions-runtime 0.397.0-next.1 → 0.397.1

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.397.0-next.1",
3
+ "version": "0.397.1",
4
4
  "description": "Internal package used by @teamkeel/sdk",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -35,5 +35,6 @@
35
35
  "pg": "^8.11.3",
36
36
  "traceparent": "^1.0.0",
37
37
  "ws": "^8.17.1"
38
- }
38
+ },
39
+ "packageManager": "pnpm@9.12.3+sha512.cce0f9de9c5a7c95bef944169cc5dfe8741abfb145078c0d508b868056848a87c81e626246cb60967cbd7fd29a6c062ef73ff840d96b3c86c40ac92cf4a813ee"
39
40
  }
package/src/File.js CHANGED
@@ -5,7 +5,7 @@ const {
5
5
  } = require("@aws-sdk/client-s3");
6
6
  const { fromEnv } = require("@aws-sdk/credential-providers");
7
7
  const { getSignedUrl } = require("@aws-sdk/s3-request-presigner");
8
- const { createDatabaseClient } = require("./database");
8
+ const { useDatabase } = require("./database");
9
9
  const { DatabaseError } = require("./errors");
10
10
  const KSUID = require("ksuid");
11
11
 
@@ -126,7 +126,7 @@ class File extends InlineFile {
126
126
  }
127
127
 
128
128
  // default to db storage
129
- const db = createDatabaseClient();
129
+ const db = useDatabase();
130
130
 
131
131
  try {
132
132
  let query = db
@@ -138,8 +138,6 @@ class File extends InlineFile {
138
138
  return row.data;
139
139
  } catch (e) {
140
140
  throw new DatabaseError(e);
141
- } finally {
142
- await db.destroy();
143
141
  }
144
142
  }
145
143
 
@@ -241,7 +239,7 @@ async function storeFile(contents, key, filename, contentType, expires) {
241
239
  throw error;
242
240
  }
243
241
  } else {
244
- const db = createDatabaseClient();
242
+ const db = useDatabase();
245
243
 
246
244
  try {
247
245
  let query = db
@@ -267,8 +265,6 @@ async function storeFile(contents, key, filename, contentType, expires) {
267
265
  await query.execute();
268
266
  } catch (e) {
269
267
  throw new DatabaseError(e);
270
- } finally {
271
- await db.destroy();
272
268
  }
273
269
  }
274
270
  }
package/src/database.js CHANGED
@@ -5,6 +5,7 @@ const { AuditContextPlugin } = require("./auditing");
5
5
  const pg = require("pg");
6
6
  const { withSpan } = require("./tracing");
7
7
  const ws = require("ws");
8
+ const fs = require("node:fs");
8
9
 
9
10
  // withDatabase is responsible for setting the correct database client in our AsyncLocalStorage
10
11
  // so that the the code in a custom function uses the correct client.
@@ -65,9 +66,9 @@ function useDatabase() {
65
66
  // createDatabaseClient will return a brand new instance of Kysely. Every instance of Kysely
66
67
  // represents an individual connection to the database.
67
68
  // not to be exported externally from our sdk - consumers should use useDatabase
68
- function createDatabaseClient() {
69
+ function createDatabaseClient({ connString } = {}) {
69
70
  const db = new Kysely({
70
- dialect: getDialect(),
71
+ dialect: getDialect(connString),
71
72
  plugins: [
72
73
  // ensures that the audit context data is written to Postgres configuration parameters
73
74
  new AuditContextPlugin(),
@@ -139,8 +140,8 @@ class InstrumentedClient extends pg.Client {
139
140
  }
140
141
  }
141
142
 
142
- function getDialect() {
143
- const dbConnType = process.env["KEEL_DB_CONN_TYPE"];
143
+ function getDialect(connString) {
144
+ const dbConnType = process.env.KEEL_DB_CONN_TYPE;
144
145
  switch (dbConnType) {
145
146
  case "pg":
146
147
  // Adding a custom type parser for numeric fields: see https://kysely.dev/docs/recipes/data-types#configuring-runtime-javascript-types
@@ -165,7 +166,14 @@ function getDialect() {
165
166
  // time is takes for a lambda to freeze (which is not a constant, but could be as short as several minutes,
166
167
  // https://www.pluralsight.com/resources/blog/cloud/how-long-does-aws-lambda-keep-your-idle-functions-around-before-a-cold-start)
167
168
  idleTimeoutMillis: 50000,
168
- connectionString: mustEnv("KEEL_DB_CONN"),
169
+
170
+ // If connString is not passed fall back to reading from env var
171
+ connectionString: connString || process.env.KEEL_DB_CONN,
172
+
173
+ // Allow the setting of a cert (.pem) file. RDS requires this to enforce SSL.
174
+ ...(process.env.KEEL_DB_CERT
175
+ ? { ssl: { ca: fs.readFileSync(process.env.KEEL_DB_CERT) } }
176
+ : undefined),
169
177
  }),
170
178
  });
171
179
  case "neon":
@@ -178,7 +186,8 @@ function getDialect() {
178
186
  neonserverless.neonConfig.webSocketConstructor = ws;
179
187
 
180
188
  const pool = new InstrumentedNeonServerlessPool({
181
- connectionString: mustEnv("KEEL_DB_CONN"),
189
+ // If connString is not passed fall back to reading from env var
190
+ connectionString: connString || process.env.KEEL_DB_CONN,
182
191
  });
183
192
 
184
193
  pool.on("connect", (client) => {
@@ -196,7 +205,7 @@ function getDialect() {
196
205
  return withSpan(spanName, function (span) {
197
206
  if (sqlAttribute) {
198
207
  span.setAttribute("sql", args[0]);
199
- span.setAttribute("dialect", process.env["KEEL_DB_CONN_TYPE"]);
208
+ span.setAttribute("dialect", dbConnType);
200
209
  }
201
210
  return originalQuery.apply(client, args);
202
211
  });
@@ -211,14 +220,6 @@ function getDialect() {
211
220
  }
212
221
  }
213
222
 
214
- function mustEnv(key) {
215
- const v = process.env[key];
216
- if (!v) {
217
- throw new Error(`expected environment variable ${key} to be set`);
218
- }
219
- return v;
220
- }
221
-
222
223
  module.exports = {
223
224
  createDatabaseClient,
224
225
  useDatabase,
package/src/handleJob.js CHANGED
@@ -53,7 +53,9 @@ async function handleJob(request, config) {
53
53
  ? true
54
54
  : null;
55
55
 
56
- db = createDatabaseClient();
56
+ db = createDatabaseClient({
57
+ connString: request.meta?.secrets?.KEEL_DB_CONN,
58
+ });
57
59
  const jobFunction = jobs[request.method];
58
60
  const actionType = PROTO_ACTION_TYPES.JOB;
59
61
 
@@ -64,7 +64,9 @@ async function handleRequest(request, config) {
64
64
  ? true
65
65
  : null;
66
66
 
67
- db = createDatabaseClient();
67
+ db = createDatabaseClient({
68
+ connString: request.meta?.secrets?.KEEL_DB_CONN,
69
+ });
68
70
  const customFunction = functions[request.method];
69
71
  const actionType = actionTypes[request.method];
70
72
 
@@ -87,7 +89,9 @@ async function handleRequest(request, config) {
87
89
  // Return the custom function to the containing tryExecuteFunction block
88
90
  // Once the custom function is called, tryExecuteFunction will check the schema's permission rules to see if it can continue committing
89
91
  // the transaction to the db. If a permission rule is violated, any changes made inside the transaction are rolled back.
90
- return customFunction(ctx, inputs);
92
+ const result = await customFunction(ctx, inputs);
93
+
94
+ return parseOutputs(result);
91
95
  }
92
96
  );
93
97
 
@@ -100,9 +104,7 @@ async function handleRequest(request, config) {
100
104
  return errorToJSONRPCResponse(request, result);
101
105
  }
102
106
 
103
- const parsed = await parseOutputs(result);
104
-
105
- const response = createJSONRPCSuccessResponse(request.id, parsed);
107
+ const response = createJSONRPCSuccessResponse(request.id, result);
106
108
 
107
109
  const responseHeaders = {};
108
110
  for (const pair of headers.entries()) {
@@ -48,7 +48,9 @@ async function handleSubscriber(request, config) {
48
48
  meta: request.meta,
49
49
  });
50
50
 
51
- db = createDatabaseClient();
51
+ db = createDatabaseClient({
52
+ connString: request.meta?.secrets?.KEEL_DB_CONN,
53
+ });
52
54
  const subscriberFunction = subscribers[request.method];
53
55
  const actionType = PROTO_ACTION_TYPES.SUBSCRIBER;
54
56