@teamkeel/functions-runtime 0.338.0 → 0.339.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.
@@ -4,9 +4,6 @@ const { sql } = require("kysely");
4
4
  const { useDatabase } = require("./database");
5
5
  const KSUID = require("ksuid");
6
6
 
7
- process.env.KEEL_DB_CONN_TYPE = "pg";
8
- process.env.KEEL_DB_CONN = `postgresql://postgres:postgres@localhost:5432/functions-runtime`;
9
-
10
7
  let personAPI;
11
8
  let postAPI;
12
9
  let authorAPI;
package/src/database.js CHANGED
@@ -1,4 +1,4 @@
1
- const { Kysely, PostgresDialect } = require("kysely");
1
+ const { Kysely, PostgresDialect, CamelCasePlugin } = require("kysely");
2
2
  const { AsyncLocalStorage } = require("async_hooks");
3
3
  const pg = require("pg");
4
4
  const { PROTO_ACTION_TYPES } = require("./consts");
@@ -35,24 +35,51 @@ async function withDatabase(db, actionType, cb) {
35
35
  }
36
36
 
37
37
  let db = null;
38
+
38
39
  const dbInstance = new AsyncLocalStorage();
39
40
 
40
41
  // useDatabase will retrieve the database client set by withDatabase from the local storage
41
42
  function useDatabase() {
43
+ // retrieve the instance of the database client from the store which is aware of
44
+ // which context the current connection to the db is running in - e.g does the context
45
+ // require a transaction or not?
42
46
  let fromStore = dbInstance.getStore();
43
47
  if (fromStore) {
44
48
  return fromStore;
45
49
  }
46
50
 
51
+ // if the NODE_ENV is 'test' then we know we are inside of the vitest environment
52
+ // which covers any test files ending in *.test.ts. Custom function code runs in a different node process which will not have this environment variable. Tests written using our testing
53
+ // framework call actions (and in turn custom function code) over http using the ActionExecutor class
54
+ if ("NODE_ENV" in process.env && process.env.NODE_ENV == "test") {
55
+ return getDatabaseClient();
56
+ }
57
+
58
+ // If we've gotten to this point, then we know that we are in a custom function runtime server
59
+ // context and we haven't been able to retrieve the in-context instance of Kysely, which means we should throw an error.
60
+ throw new Error("useDatabase must be called within a function");
61
+ }
62
+
63
+ // getDatabaseClient will return a brand new instance of Kysely. Every instance of Kysely
64
+ // represents an individual connection to the database.
65
+ // not to be exported externally from our sdk - consumers should use useDatabase
66
+ function getDatabaseClient() {
67
+ // 'db' represents the singleton connection to the database which is stored
68
+ // as a module scope variable.
47
69
  if (db) {
48
70
  return db;
49
71
  }
50
72
 
51
- // todo: ideally we wouldn't want to give you a fresh Kysely instance here if nothing
52
- // has been found in the context, but the @teamkeel/testing package needs some restructuring
53
- // to allow for the database client to be set in the store so that this method can throw an error at this line instead of returning a fresh kysely instance.
54
73
  db = new Kysely({
55
74
  dialect: getDialect(),
75
+ plugins: [
76
+ // allows users to query using camelCased versions of the database column names, which
77
+ // should match the names we use in our schema.
78
+ // https://kysely-org.github.io/kysely/classes/CamelCasePlugin.html
79
+ // If they don't, then we can create a custom implementation of the plugin where we control
80
+ // the casing behaviour (see url above for example)
81
+ new CamelCasePlugin(),
82
+ ],
56
83
  log(event) {
57
84
  if ("DEBUG" in process.env) {
58
85
  if (event.level === "query") {
@@ -66,14 +93,6 @@ function useDatabase() {
66
93
  return db;
67
94
  }
68
95
 
69
- function mustEnv(key) {
70
- const v = process.env[key];
71
- if (!v) {
72
- throw new Error(`expected environment variable ${key} to be set`);
73
- }
74
- return v;
75
- }
76
-
77
96
  class InstrumentedPool extends pg.Pool {
78
97
  async connect(...args) {
79
98
  const _super = super.connect.bind(this);
@@ -127,5 +146,17 @@ function getDialect() {
127
146
  }
128
147
  }
129
148
 
149
+ function mustEnv(key) {
150
+ const v = process.env[key];
151
+ if (!v) {
152
+ throw new Error(`expected environment variable ${key} to be set`);
153
+ }
154
+ return v;
155
+ }
156
+
157
+ // initialise the database client at module scope level so the db variable is set
158
+ getDatabaseClient();
159
+
160
+ module.exports.getDatabaseClient = getDatabaseClient;
130
161
  module.exports.useDatabase = useDatabase;
131
162
  module.exports.withDatabase = withDatabase;
@@ -3,7 +3,7 @@ const {
3
3
  createJSONRPCSuccessResponse,
4
4
  JSONRPCErrorCode,
5
5
  } = require("json-rpc-2.0");
6
- const { useDatabase } = require("./database");
6
+ const { getDatabaseClient } = require("./database");
7
7
  const { tryExecuteFunction } = require("./tryExecuteFunction");
8
8
  const { errorToJSONRPCResponse, RuntimeErrors } = require("./errors");
9
9
  const opentelemetry = require("@opentelemetry/api");
@@ -57,7 +57,7 @@ async function handleRequest(request, config) {
57
57
  ? true
58
58
  : null;
59
59
 
60
- const db = useDatabase();
60
+ const db = getDatabaseClient();
61
61
  const customFunction = functions[request.method];
62
62
 
63
63
  const result = await tryExecuteFunction(
@@ -8,9 +8,6 @@ const { Permissions } = require("./permissions");
8
8
  import { PROTO_ACTION_TYPES } from "./consts";
9
9
  import KSUID from "ksuid";
10
10
 
11
- process.env.KEEL_DB_CONN_TYPE = "pg";
12
- process.env.KEEL_DB_CONN = `postgresql://postgres:postgres@localhost:5432/functions-runtime`;
13
-
14
11
  test("when the custom function returns expected value", async () => {
15
12
  const config = {
16
13
  functions: {
@@ -10,9 +10,6 @@ import { useDatabase } from "./database";
10
10
 
11
11
  import { beforeEach, describe, expect, test } from "vitest";
12
12
 
13
- process.env.KEEL_DB_CONN_TYPE = "pg";
14
- process.env.KEEL_DB_CONN = `postgresql://postgres:postgres@localhost:5432/functions-runtime`;
15
-
16
13
  let permissions;
17
14
  let ctx = {};
18
15
  let db = useDatabase();
package/vite.config.js ADDED
@@ -0,0 +1,7 @@
1
+ import { defineConfig, loadEnv } from "vite";
2
+
3
+ export default ({ mode }) => {
4
+ process.env = { ...process.env, ...loadEnv(mode, process.cwd(), "") };
5
+
6
+ return defineConfig({});
7
+ };