@faasjs/knex 8.0.0-beta.5 → 8.0.0-beta.7

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/README.md CHANGED
@@ -13,9 +13,13 @@ npm install @faasjs/knex
13
13
 
14
14
  ## Functions
15
15
 
16
+ - [createPgliteKnex](functions/createPgliteKnex.md)
17
+ - [initPostgresTypeParsers](functions/initPostgresTypeParsers.md)
18
+ - [mountFaasKnex](functions/mountFaasKnex.md)
16
19
  - [query](functions/query.md)
17
20
  - [raw](functions/raw.md)
18
21
  - [transaction](functions/transaction.md)
22
+ - [unmountFaasKnex](functions/unmountFaasKnex.md)
19
23
  - [useKnex](functions/useKnex.md)
20
24
 
21
25
  ## Classes
@@ -25,6 +29,7 @@ npm install @faasjs/knex
25
29
  ## Type Aliases
26
30
 
27
31
  - [KnexConfig](type-aliases/KnexConfig.md)
32
+ - [MountFaasKnexOptions](type-aliases/MountFaasKnexOptions.md)
28
33
 
29
34
  ## Variables
30
35
 
package/dist/index.cjs CHANGED
@@ -1,237 +1,312 @@
1
- 'use strict';
2
-
3
- var crypto = require('crypto');
4
- var deep_merge = require('@faasjs/deep_merge');
5
- var func = require('@faasjs/func');
6
- var load = require('@faasjs/load');
7
- var knex = require('knex');
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ //#region \0rolldown/runtime.js
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
12
+ key = keys[i];
13
+ if (!__hasOwnProp.call(to, key) && key !== except) {
14
+ __defProp(to, key, {
15
+ get: ((k) => from[k]).bind(null, key),
16
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
17
+ });
18
+ }
19
+ }
20
+ }
21
+ return to;
22
+ };
23
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
24
+ value: mod,
25
+ enumerable: true
26
+ }) : target, mod));
8
27
 
9
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
28
+ //#endregion
29
+ let node_crypto = require("node:crypto");
30
+ let _faasjs_func = require("@faasjs/func");
31
+ let _faasjs_node_utils = require("@faasjs/node-utils");
32
+ let knex = require("knex");
33
+ knex = __toESM(knex);
34
+ let node_fs = require("node:fs");
35
+ let node_path = require("node:path");
10
36
 
11
- var knex__default = /*#__PURE__*/_interopDefault(knex);
37
+ //#region src/pglite.ts
38
+ function parsePgliteConnection(connection) {
39
+ if (typeof connection === "undefined" || connection === null) return `memory://${(0, node_crypto.randomUUID)()}`;
40
+ if (typeof connection !== "string" || !connection.trim().length) throw Error("[Knex] Invalid \"pglite\" connection, expected non-empty string in config.connection or SECRET_<NAME>_CONNECTION.");
41
+ return connection;
42
+ }
43
+ function ensurePgliteConnectionPath(connection) {
44
+ if (connection.includes("://")) return;
45
+ (0, node_fs.mkdirSync)((0, node_path.dirname)((0, node_path.resolve)(connection)), { recursive: true });
46
+ }
47
+ async function loadPglitePackages() {
48
+ try {
49
+ const pgliteModule = await (0, _faasjs_node_utils.loadPackage)("@electric-sql/pglite", []);
50
+ const PgliteDialect = await (0, _faasjs_node_utils.loadPackage)("knex-pglite");
51
+ if (typeof pgliteModule.PGlite !== "function" || !pgliteModule.types) throw Error("Invalid @electric-sql/pglite exports");
52
+ if (typeof PgliteDialect !== "function") throw Error("Invalid knex-pglite exports");
53
+ return {
54
+ PGlite: pgliteModule.PGlite,
55
+ types: pgliteModule.types,
56
+ PgliteDialect
57
+ };
58
+ } catch {
59
+ throw Error("[Knex] client \"pglite\" requires dependencies \"@electric-sql/pglite\" and \"knex-pglite\". Please install both packages in your project.");
60
+ }
61
+ }
62
+ /**
63
+ * Create a knex instance backed by `knex-pglite`.
64
+ * If connection is missing, it defaults to an in-memory database.
65
+ */
66
+ async function createPgliteKnex(config = {}, connection) {
67
+ const resolvedConnection = parsePgliteConnection(connection ?? config.connection);
68
+ ensurePgliteConnectionPath(resolvedConnection);
69
+ const { PGlite, types, PgliteDialect } = await loadPglitePackages();
70
+ const { client: _client, connection: _connection, pool: _pool, ...restConfig } = config;
71
+ const pglite = new PGlite(resolvedConnection, { parsers: {
72
+ [types.INT2]: (v) => Number.parseInt(v, 10),
73
+ [types.INT4]: (v) => Number.parseInt(v, 10),
74
+ [types.INT8]: (v) => Number.parseInt(v, 10),
75
+ [types.FLOAT4]: (v) => Number.parseFloat(v),
76
+ [types.FLOAT8]: (v) => Number.parseFloat(v),
77
+ [types.NUMERIC]: (v) => Number.parseFloat(v)
78
+ } });
79
+ return (0, knex.default)({
80
+ ...restConfig,
81
+ client: PgliteDialect,
82
+ connection: { pglite }
83
+ });
84
+ }
85
+ /**
86
+ * Mount a knex adapter to `globalThis.FaasJS_Knex` for `@faasjs/knex`.
87
+ */
88
+ function mountFaasKnex(db, options = {}) {
89
+ const globalWithFaasKnex = globalThis;
90
+ const name = options.name || "knex";
91
+ if (!globalWithFaasKnex.FaasJS_Knex) globalWithFaasKnex.FaasJS_Knex = {};
92
+ globalWithFaasKnex.FaasJS_Knex[name] = {
93
+ adapter: db,
94
+ query: db,
95
+ config: options.config || {}
96
+ };
97
+ }
98
+ /**
99
+ * Remove mounted knex adapter from `globalThis.FaasJS_Knex`.
100
+ */
101
+ function unmountFaasKnex(name = "knex") {
102
+ const globalWithFaasKnex = globalThis;
103
+ if (!globalWithFaasKnex.FaasJS_Knex) return;
104
+ delete globalWithFaasKnex.FaasJS_Knex[name];
105
+ }
12
106
 
13
- // src/index.ts
14
- var originKnex = knex__default.default;
15
- var Name = "knex";
16
- if (!global.FaasJS_Knex) {
17
- global.FaasJS_Knex = {};
107
+ //#endregion
108
+ //#region src/index.ts
109
+ /**
110
+ * FaasJS's sql plugin, base on [Knex](https://knexjs.org/).
111
+ *
112
+ * [![License: MIT](https://img.shields.io/npm/l/@faasjs/knex.svg)](https://github.com/faasjs/faasjs/blob/main/packages/knex/LICENSE)
113
+ * [![NPM Version](https://img.shields.io/npm/v/@faasjs/knex.svg)](https://www.npmjs.com/package/@faasjs/knex)
114
+ *
115
+ * ## Install
116
+ *
117
+ * ```sh
118
+ * npm install @faasjs/knex
119
+ * ```
120
+ * @packageDocumentation
121
+ */
122
+ /**
123
+ * Origin [knex](https://knexjs.org/) instance.
124
+ */
125
+ const originKnex = knex.default;
126
+ const Name = "knex";
127
+ if (!global.FaasJS_Knex) global.FaasJS_Knex = {};
128
+ function getGlobalKnexAdapters() {
129
+ if (!global.FaasJS_Knex) global.FaasJS_Knex = {};
130
+ return global.FaasJS_Knex;
131
+ }
132
+ async function initPostgresTypeParsers() {
133
+ const pg = await (0, _faasjs_node_utils.loadPackage)("pg");
134
+ pg.types.setTypeParser(pg.types.builtins.INT2, (v) => Number.parseInt(v, 10));
135
+ pg.types.setTypeParser(pg.types.builtins.INT4, (v) => Number.parseInt(v, 10));
136
+ pg.types.setTypeParser(pg.types.builtins.INT8, (v) => Number.parseInt(v, 10));
137
+ pg.types.setTypeParser(pg.types.builtins.FLOAT4, (v) => Number.parseFloat(v));
138
+ pg.types.setTypeParser(pg.types.builtins.FLOAT8, (v) => Number.parseFloat(v));
139
+ pg.types.setTypeParser(pg.types.builtins.NUMERIC, (v) => Number.parseFloat(v));
18
140
  }
19
141
  var Knex = class {
20
- type = "knex";
21
- name = Name;
22
- config;
23
- adapter;
24
- query;
25
- logger;
26
- constructor(config) {
27
- if (config) {
28
- this.name = config.name || this.name;
29
- this.config = config.config || /* @__PURE__ */ Object.create(null);
30
- } else {
31
- this.config = /* @__PURE__ */ Object.create(null);
32
- }
33
- }
34
- async onMount(data, next) {
35
- this.logger = data.logger;
36
- if (global.FaasJS_Knex[this.name]) {
37
- this.config = global.FaasJS_Knex[this.name].config;
38
- this.adapter = global.FaasJS_Knex[this.name].adapter;
39
- this.query = this.adapter;
40
- this.logger.debug("use exists adapter");
41
- await next();
42
- return;
43
- }
44
- const prefix = `SECRET_${this.name.toUpperCase()}_`;
45
- for (let key in process.env)
46
- if (key.startsWith(prefix)) {
47
- const value = process.env[key];
48
- key = key.replace(prefix, "").toLowerCase();
49
- if (typeof this.config[key] === "undefined")
50
- if (key.startsWith("connection_")) {
51
- if (!this.config.connection) {
52
- this.config.connection = /* @__PURE__ */ Object.create(null);
53
- }
54
- this.config.connection[key.replace("connection_", "")] = value;
55
- } else this.config[key] = value;
56
- }
57
- if (data.config.plugins?.[this.name || this.type]?.config)
58
- this.config = deep_merge.deepMerge(
59
- data.config.plugins[this.name || this.type].config,
60
- this.config
61
- );
62
- switch (this.config.client) {
63
- case "sqlite3":
64
- this.config.client = "better-sqlite3";
65
- this.config.useNullAsDefault = true;
66
- break;
67
- case "pg":
68
- if (!this.config.pool) this.config.pool = /* @__PURE__ */ Object.create(null);
69
- this.config.pool = Object.assign(
70
- {
71
- propagateCreateError: false,
72
- min: 0,
73
- max: 10,
74
- acquireTimeoutMillis: 5e3,
75
- idleTimeoutMillis: 3e4
76
- },
77
- this.config.pool
78
- );
79
- if (typeof this.config.connection === "string" && !this.config.connection.includes("json=true"))
80
- this.config.connection = `${this.config.connection}?json=true`;
81
- break;
82
- default:
83
- if (typeof this.config.client === "string") {
84
- if (this.config.client.startsWith("npm:")) {
85
- const client = await load.loadPackage(
86
- this.config.client.replace("npm:", "")
87
- );
88
- if (!client) throw Error(`Invalid client: ${this.config.client}`);
89
- if (typeof client === "function") {
90
- this.config.client = client;
91
- break;
92
- }
93
- if (client.default && typeof client.default === "function") {
94
- this.config.client = client.default;
95
- break;
96
- }
97
- throw Error(`Invalid client: ${this.config.client}`);
98
- }
99
- }
100
- break;
101
- }
102
- this.adapter = knex__default.default(this.config);
103
- if (this.config.client === "pg") {
104
- const pg = await load.loadPackage("pg");
105
- pg.types.setTypeParser(
106
- pg.types.builtins.INT2,
107
- (v) => Number.parseInt(v)
108
- );
109
- pg.types.setTypeParser(
110
- pg.types.builtins.INT4,
111
- (v) => Number.parseInt(v)
112
- );
113
- pg.types.setTypeParser(
114
- pg.types.builtins.INT8,
115
- (v) => Number.parseInt(v)
116
- );
117
- pg.types.setTypeParser(
118
- pg.types.builtins.FLOAT4,
119
- (v) => Number.parseFloat(v)
120
- );
121
- pg.types.setTypeParser(
122
- pg.types.builtins.FLOAT8,
123
- (v) => Number.parseFloat(v)
124
- );
125
- pg.types.setTypeParser(
126
- pg.types.builtins.NUMERIC,
127
- (v) => Number.parseFloat(v)
128
- );
129
- }
130
- this.query = this.adapter;
131
- this.query.on("query", ({ sql, __knexQueryUid, bindings }) => {
132
- if (!__knexQueryUid) return;
133
- this.logger.time(`Knex${this.name}${__knexQueryUid}`);
134
- this.logger.debug(
135
- "[%s] query begin: %s %j",
136
- __knexQueryUid,
137
- sql,
138
- bindings
139
- );
140
- }).on("query-response", (response, { sql, __knexQueryUid, bindings }) => {
141
- if (!__knexQueryUid) return;
142
- this.logger.timeEnd(
143
- `Knex${this.name}${__knexQueryUid}`,
144
- "[%s] query done: %s %j %j",
145
- __knexQueryUid,
146
- sql,
147
- bindings,
148
- response
149
- );
150
- }).on("query-error", (_, { __knexQueryUid, sql, bindings }) => {
151
- if (!__knexQueryUid) return;
152
- this.logger.timeEnd(
153
- `Knex${this.name}${__knexQueryUid}`,
154
- "[%s] query failed: %s %j",
155
- __knexQueryUid,
156
- sql,
157
- bindings
158
- );
159
- });
160
- data.logger.debug("connected");
161
- global.FaasJS_Knex[this.name] = this;
162
- await next();
163
- }
164
- async onInvoke(data, next) {
165
- this.logger = data.logger;
166
- await next();
167
- }
168
- async raw(sql, bindings = []) {
169
- if (!this.adapter) throw Error("[Knex] Client not initialized.");
170
- return this.adapter.raw(sql, bindings);
171
- }
172
- /**
173
- * Wraps a transaction, returning a promise that resolves to the return value of the callback.
174
- *
175
- * - Support 'commit' and 'rollback' event.
176
- */
177
- async transaction(scope, config, options) {
178
- if (!this.adapter) throw Error(`[${this.name}] Client not initialized.`);
179
- if (options?.trx) return scope(options.trx);
180
- const trx = await this.adapter.transaction(config);
181
- const trxId = crypto.randomUUID();
182
- this.logger.debug("[%s] transaction begin", trxId);
183
- try {
184
- const result = await scope(trx);
185
- if (trx.isCompleted()) {
186
- this.logger.debug("[%s] transaction has been finished in scope", trxId);
187
- return result;
188
- }
189
- this.logger.debug("[%s] transaction begin commit", trxId);
190
- await trx.commit();
191
- this.logger.debug("[%s] transaction committed: %j", trxId, result);
192
- trx.emit("commit");
193
- return result;
194
- } catch (error) {
195
- await trx.rollback(error);
196
- this.logger.error("[%s] transaction rollback: %s", trxId, error);
197
- trx.emit("rollback", error);
198
- throw error;
199
- }
200
- }
201
- schema() {
202
- if (!this.adapter) throw Error(`[${this.name}] Client not initialized.`);
203
- return this.adapter.schema;
204
- }
205
- async quit() {
206
- if (!global.FaasJS_Knex[this.name]) return;
207
- try {
208
- await global.FaasJS_Knex[this.name].adapter.destroy();
209
- delete global.FaasJS_Knex[this.name];
210
- } catch (error) {
211
- console.error(error);
212
- }
213
- }
142
+ type = "knex";
143
+ name = Name;
144
+ config;
145
+ adapter;
146
+ query;
147
+ logger;
148
+ constructor(config) {
149
+ if (config) {
150
+ this.name = config.name || this.name;
151
+ this.config = config.config || Object.create(null);
152
+ } else this.config = Object.create(null);
153
+ }
154
+ async onMount(data, next) {
155
+ this.logger = data.logger;
156
+ const existsAdapter = getGlobalKnexAdapters()[this.name];
157
+ if (existsAdapter) {
158
+ this.config = existsAdapter.config;
159
+ this.adapter = existsAdapter.adapter;
160
+ this.query = this.adapter;
161
+ this.logger.debug("use exists adapter");
162
+ await next();
163
+ return;
164
+ }
165
+ const prefix = `SECRET_${this.name.toUpperCase()}_`;
166
+ for (let key in process.env) if (key.startsWith(prefix)) {
167
+ const value = process.env[key];
168
+ key = key.replace(prefix, "").toLowerCase();
169
+ if (typeof this.config[key] === "undefined") if (key.startsWith("connection_")) {
170
+ if (typeof this.config.connection === "string") continue;
171
+ if (!this.config.connection || typeof this.config.connection !== "object") this.config.connection = Object.create(null);
172
+ this.config.connection[key.replace("connection_", "")] = value;
173
+ } else this.config[key] = value;
174
+ }
175
+ if (data.config.plugins?.[this.name || this.type]?.config) this.config = (0, _faasjs_node_utils.deepMerge)(data.config.plugins[this.name || this.type].config, this.config);
176
+ if (this.config.client === "pglite") {
177
+ const connectionEnvKeys = Object.keys(process.env).filter((key) => key.startsWith(`${prefix}CONNECTION_`));
178
+ if (connectionEnvKeys.length) throw Error(`[Knex] Invalid "pglite" env keys: ${connectionEnvKeys.join(", ")}. Use ${prefix}CONNECTION instead.`);
179
+ this.adapter = await createPgliteKnex(this.config);
180
+ } else {
181
+ switch (this.config.client) {
182
+ case "sqlite3":
183
+ this.config.client = "better-sqlite3";
184
+ this.config.useNullAsDefault = true;
185
+ break;
186
+ case "pg":
187
+ if (!this.config.pool) this.config.pool = Object.create(null);
188
+ this.config.pool = Object.assign({
189
+ propagateCreateError: false,
190
+ min: 0,
191
+ max: 10,
192
+ acquireTimeoutMillis: 5e3,
193
+ idleTimeoutMillis: 3e4
194
+ }, this.config.pool);
195
+ if (typeof this.config.connection === "string" && !this.config.connection.includes("json=true")) this.config.connection = `${this.config.connection}?json=true`;
196
+ break;
197
+ default:
198
+ if (typeof this.config.client === "string") {
199
+ if (this.config.client.startsWith("npm:")) {
200
+ const client = await (0, _faasjs_node_utils.loadPackage)(this.config.client.replace("npm:", ""));
201
+ if (!client) throw Error(`Invalid client: ${this.config.client}`);
202
+ if (typeof client === "function") {
203
+ this.config.client = client;
204
+ break;
205
+ }
206
+ if (client.default && typeof client.default === "function") {
207
+ this.config.client = client.default;
208
+ break;
209
+ }
210
+ throw Error(`Invalid client: ${this.config.client}`);
211
+ }
212
+ }
213
+ break;
214
+ }
215
+ this.adapter = (0, knex.default)(this.config);
216
+ if (this.config.client === "pg") await initPostgresTypeParsers();
217
+ }
218
+ this.query = this.adapter;
219
+ this.query.on("query", ({ sql, __knexQueryUid, bindings }) => {
220
+ if (!__knexQueryUid) return;
221
+ this.logger.time(`Knex${this.name}${__knexQueryUid}`);
222
+ this.logger.debug("[%s] query begin: %s %j", __knexQueryUid, sql, bindings);
223
+ }).on("query-response", (response, { sql, __knexQueryUid, bindings }) => {
224
+ if (!__knexQueryUid) return;
225
+ this.logger.timeEnd(`Knex${this.name}${__knexQueryUid}`, "[%s] query done: %s %j %j", __knexQueryUid, sql, bindings, response);
226
+ }).on("query-error", (_, { __knexQueryUid, sql, bindings }) => {
227
+ if (!__knexQueryUid) return;
228
+ this.logger.timeEnd(`Knex${this.name}${__knexQueryUid}`, "[%s] query failed: %s %j", __knexQueryUid, sql, bindings);
229
+ });
230
+ data.logger.debug("connected");
231
+ getGlobalKnexAdapters()[this.name] = this;
232
+ await next();
233
+ }
234
+ async onInvoke(data, next) {
235
+ this.logger = data.logger;
236
+ await next();
237
+ }
238
+ async raw(sql, bindings = []) {
239
+ if (!this.adapter) throw Error("[Knex] Client not initialized.");
240
+ return this.adapter.raw(sql, bindings);
241
+ }
242
+ /**
243
+ * Wraps a transaction, returning a promise that resolves to the return value of the callback.
244
+ *
245
+ * - Support 'commit' and 'rollback' event.
246
+ */
247
+ async transaction(scope, config, options) {
248
+ if (!this.adapter) throw Error(`[${this.name}] Client not initialized.`);
249
+ if (options?.trx) return scope(options.trx);
250
+ const trx = await this.adapter.transaction(config);
251
+ const trxId = (0, node_crypto.randomUUID)();
252
+ this.logger.debug("[%s] transaction begin", trxId);
253
+ try {
254
+ const result = await scope(trx);
255
+ if (trx.isCompleted()) {
256
+ this.logger.debug("[%s] transaction has been finished in scope", trxId);
257
+ return result;
258
+ }
259
+ this.logger.debug("[%s] transaction begin commit", trxId);
260
+ await trx.commit();
261
+ this.logger.debug("[%s] transaction committed: %j", trxId, result);
262
+ trx.emit("commit");
263
+ return result;
264
+ } catch (error) {
265
+ await trx.rollback(error);
266
+ this.logger.error("[%s] transaction rollback: %s", trxId, error);
267
+ trx.emit("rollback", error);
268
+ throw error;
269
+ }
270
+ }
271
+ schema() {
272
+ if (!this.adapter) throw Error(`[${this.name}] Client not initialized.`);
273
+ return this.adapter.schema;
274
+ }
275
+ async quit() {
276
+ const adapters = getGlobalKnexAdapters();
277
+ if (!adapters[this.name]) return;
278
+ try {
279
+ await adapters[this.name].adapter.destroy();
280
+ delete adapters[this.name];
281
+ } catch (error) {
282
+ console.error(error);
283
+ }
284
+ }
214
285
  };
215
286
  function useKnex(config) {
216
- const name = config?.name || Name;
217
- if (global.FaasJS_Knex[name]) return func.usePlugin(global.FaasJS_Knex[name]);
218
- return func.usePlugin(new Knex(config));
287
+ const name = config?.name || Name;
288
+ const adapters = getGlobalKnexAdapters();
289
+ if (adapters[name]) return (0, _faasjs_func.usePlugin)(adapters[name]);
290
+ return (0, _faasjs_func.usePlugin)(new Knex(config));
219
291
  }
220
292
  function query(table) {
221
- return useKnex().query(
222
- table
223
- );
293
+ return useKnex().query(table);
224
294
  }
225
295
  async function transaction(scope, config, options) {
226
- return useKnex().transaction(scope, config, options);
296
+ return useKnex().transaction(scope, config, options);
227
297
  }
228
298
  async function raw(sql, bindings = []) {
229
- return useKnex().raw(sql, bindings);
299
+ return useKnex().raw(sql, bindings);
230
300
  }
231
301
 
302
+ //#endregion
232
303
  exports.Knex = Knex;
304
+ exports.createPgliteKnex = createPgliteKnex;
305
+ exports.initPostgresTypeParsers = initPostgresTypeParsers;
306
+ exports.mountFaasKnex = mountFaasKnex;
233
307
  exports.originKnex = originKnex;
234
308
  exports.query = query;
235
309
  exports.raw = raw;
236
310
  exports.transaction = transaction;
237
- exports.useKnex = useKnex;
311
+ exports.unmountFaasKnex = unmountFaasKnex;
312
+ exports.useKnex = useKnex;
package/dist/index.d.ts CHANGED
@@ -1,67 +1,72 @@
1
- import { Plugin, MountData, Next, InvokeData, UseifyPlugin } from '@faasjs/func';
2
- import { Logger } from '@faasjs/logger';
3
- import knex, { Knex as Knex$1 } from 'knex';
4
- export { Knex as OriginKnex } from 'knex';
1
+ import { InvokeData, MountData, Next, Plugin, UseifyPlugin } from "@faasjs/func";
2
+ import knex, { Knex as Knex$1, Knex as OriginKnex } from "knex";
3
+ import { Logger } from "@faasjs/logger";
5
4
 
5
+ //#region src/pglite.d.ts
6
+ type MountFaasKnexOptions = {
7
+ /** key of `globalThis.FaasJS_Knex`, default is `knex` */name?: string; /** optional config metadata passed through to `@faasjs/knex` */
8
+ config?: Record<string, unknown>;
9
+ };
6
10
  /**
7
- * FaasJS's sql plugin, base on [Knex](https://knexjs.org/).
8
- *
9
- * [![License: MIT](https://img.shields.io/npm/l/@faasjs/knex.svg)](https://github.com/faasjs/faasjs/blob/main/packages/knex/LICENSE)
10
- * [![NPM Version](https://img.shields.io/npm/v/@faasjs/knex.svg)](https://www.npmjs.com/package/@faasjs/knex)
11
- *
12
- * ## Install
13
- *
14
- * ```sh
15
- * npm install @faasjs/knex
16
- * ```
17
- * @packageDocumentation
11
+ * Create a knex instance backed by `knex-pglite`.
12
+ * If connection is missing, it defaults to an in-memory database.
18
13
  */
19
-
14
+ declare function createPgliteKnex(config?: Partial<Knex$1.Config>, connection?: string): Promise<Knex$1>;
15
+ /**
16
+ * Mount a knex adapter to `globalThis.FaasJS_Knex` for `@faasjs/knex`.
17
+ */
18
+ declare function mountFaasKnex(db: Knex$1, options?: MountFaasKnexOptions): void;
19
+ /**
20
+ * Remove mounted knex adapter from `globalThis.FaasJS_Knex`.
21
+ */
22
+ declare function unmountFaasKnex(name?: string): void;
23
+ //#endregion
24
+ //#region src/index.d.ts
20
25
  /**
21
26
  * Origin [knex](https://knexjs.org/) instance.
22
27
  */
23
28
  declare const originKnex: typeof knex;
24
-
25
29
  type KnexConfig = {
26
- name?: string;
27
- config?: Knex$1.Config;
30
+ name?: string;
31
+ config?: OriginKnex.Config;
28
32
  };
33
+ declare function initPostgresTypeParsers(): Promise<void>;
29
34
  declare class Knex implements Plugin {
30
- readonly type = "knex";
31
- readonly name: string;
32
- config: Knex$1.Config;
33
- adapter: Knex$1;
34
- query: Knex$1;
35
- logger: Logger;
36
- constructor(config?: KnexConfig);
37
- onMount(data: MountData, next: Next): Promise<void>;
38
- onInvoke(data: InvokeData<any, any, any>, next: Next): Promise<void>;
39
- raw<TResult = any>(sql: string, bindings?: Knex$1.RawBinding[] | Knex$1.ValueDict): Promise<Knex$1.Raw<TResult>>;
40
- /**
41
- * Wraps a transaction, returning a promise that resolves to the return value of the callback.
42
- *
43
- * - Support 'commit' and 'rollback' event.
44
- */
45
- transaction<TResult = any>(scope: (trx: Knex$1.Transaction<any, any>) => Promise<TResult>, config?: Knex$1.TransactionConfig, options?: {
46
- trx?: Knex$1.Transaction;
47
- }): Promise<TResult>;
48
- schema(): Knex$1.SchemaBuilder;
49
- quit(): Promise<void>;
35
+ readonly type = "knex";
36
+ readonly name: string;
37
+ config: OriginKnex.Config;
38
+ adapter: OriginKnex;
39
+ query: OriginKnex;
40
+ logger: Logger;
41
+ constructor(config?: KnexConfig);
42
+ onMount(data: MountData, next: Next): Promise<void>;
43
+ onInvoke(data: InvokeData<any, any, any>, next: Next): Promise<void>;
44
+ raw<TResult = any>(sql: string, bindings?: OriginKnex.RawBinding[] | OriginKnex.ValueDict): Promise<OriginKnex.Raw<TResult>>;
45
+ /**
46
+ * Wraps a transaction, returning a promise that resolves to the return value of the callback.
47
+ *
48
+ * - Support 'commit' and 'rollback' event.
49
+ */
50
+ transaction<TResult = any>(scope: (trx: OriginKnex.Transaction<any, any>) => Promise<TResult>, config?: OriginKnex.TransactionConfig, options?: {
51
+ trx?: OriginKnex.Transaction;
52
+ }): Promise<TResult>;
53
+ schema(): OriginKnex.SchemaBuilder;
54
+ quit(): Promise<void>;
50
55
  }
51
56
  declare function useKnex(config?: KnexConfig): UseifyPlugin<Knex>;
52
- declare function query<TName extends Knex$1.TableNames>(table: TName): Knex$1.QueryBuilder<Knex$1.TableType<TName>, {
53
- _base: Knex$1.ResolveTableType<Knex$1.TableType<TName>, 'base'>;
54
- _hasSelection: false;
55
- _keys: never;
56
- _aliases: {};
57
- _single: false;
58
- _intersectProps: {};
59
- _unionProps: never;
57
+ declare function query<TName extends OriginKnex.TableNames>(table: TName): OriginKnex.QueryBuilder<OriginKnex.TableType<TName>, {
58
+ _base: OriginKnex.ResolveTableType<OriginKnex.TableType<TName>, 'base'>;
59
+ _hasSelection: false;
60
+ _keys: never;
61
+ _aliases: {};
62
+ _single: false;
63
+ _intersectProps: {};
64
+ _unionProps: never;
60
65
  }[]>;
61
- declare function query<TName extends {} = any, TResult = any[]>(table: string): Knex$1.QueryBuilder<TName, TResult>;
62
- declare function transaction<TResult = any>(scope: (trx: Knex$1.Transaction<any, any>) => Promise<TResult>, config?: Knex$1.TransactionConfig, options?: {
63
- trx?: Knex$1.Transaction;
66
+ declare function query<TName extends {} = any, TResult = any[]>(table: string): OriginKnex.QueryBuilder<TName, TResult>;
67
+ declare function transaction<TResult = any>(scope: (trx: OriginKnex.Transaction<any, any>) => Promise<TResult>, config?: OriginKnex.TransactionConfig, options?: {
68
+ trx?: OriginKnex.Transaction;
64
69
  }): Promise<TResult>;
65
- declare function raw<TResult = any>(sql: string, bindings?: Knex$1.RawBinding[] | Knex$1.ValueDict): Promise<Knex$1.Raw<TResult>>;
66
-
67
- export { Knex, type KnexConfig, originKnex, query, raw, transaction, useKnex };
70
+ declare function raw<TResult = any>(sql: string, bindings?: OriginKnex.RawBinding[] | OriginKnex.ValueDict): Promise<OriginKnex.Raw<TResult>>;
71
+ //#endregion
72
+ export { Knex, KnexConfig, type MountFaasKnexOptions, type OriginKnex, createPgliteKnex, initPostgresTypeParsers, mountFaasKnex, originKnex, query, raw, transaction, unmountFaasKnex, useKnex };
package/dist/index.mjs CHANGED
@@ -1,226 +1,274 @@
1
- import { randomUUID } from 'crypto';
2
- import { deepMerge } from '@faasjs/deep_merge';
3
- import { usePlugin } from '@faasjs/func';
4
- import { loadPackage } from '@faasjs/load';
5
- import knex from 'knex';
1
+ import { randomUUID } from "node:crypto";
2
+ import { usePlugin } from "@faasjs/func";
3
+ import { deepMerge, loadPackage } from "@faasjs/node-utils";
4
+ import knex from "knex";
5
+ import { mkdirSync } from "node:fs";
6
+ import { dirname, resolve } from "node:path";
6
7
 
7
- // src/index.ts
8
- var originKnex = knex;
9
- var Name = "knex";
10
- if (!global.FaasJS_Knex) {
11
- global.FaasJS_Knex = {};
8
+ //#region src/pglite.ts
9
+ function parsePgliteConnection(connection) {
10
+ if (typeof connection === "undefined" || connection === null) return `memory://${randomUUID()}`;
11
+ if (typeof connection !== "string" || !connection.trim().length) throw Error("[Knex] Invalid \"pglite\" connection, expected non-empty string in config.connection or SECRET_<NAME>_CONNECTION.");
12
+ return connection;
13
+ }
14
+ function ensurePgliteConnectionPath(connection) {
15
+ if (connection.includes("://")) return;
16
+ mkdirSync(dirname(resolve(connection)), { recursive: true });
17
+ }
18
+ async function loadPglitePackages() {
19
+ try {
20
+ const pgliteModule = await loadPackage("@electric-sql/pglite", []);
21
+ const PgliteDialect = await loadPackage("knex-pglite");
22
+ if (typeof pgliteModule.PGlite !== "function" || !pgliteModule.types) throw Error("Invalid @electric-sql/pglite exports");
23
+ if (typeof PgliteDialect !== "function") throw Error("Invalid knex-pglite exports");
24
+ return {
25
+ PGlite: pgliteModule.PGlite,
26
+ types: pgliteModule.types,
27
+ PgliteDialect
28
+ };
29
+ } catch {
30
+ throw Error("[Knex] client \"pglite\" requires dependencies \"@electric-sql/pglite\" and \"knex-pglite\". Please install both packages in your project.");
31
+ }
32
+ }
33
+ /**
34
+ * Create a knex instance backed by `knex-pglite`.
35
+ * If connection is missing, it defaults to an in-memory database.
36
+ */
37
+ async function createPgliteKnex(config = {}, connection) {
38
+ const resolvedConnection = parsePgliteConnection(connection ?? config.connection);
39
+ ensurePgliteConnectionPath(resolvedConnection);
40
+ const { PGlite, types, PgliteDialect } = await loadPglitePackages();
41
+ const { client: _client, connection: _connection, pool: _pool, ...restConfig } = config;
42
+ const pglite = new PGlite(resolvedConnection, { parsers: {
43
+ [types.INT2]: (v) => Number.parseInt(v, 10),
44
+ [types.INT4]: (v) => Number.parseInt(v, 10),
45
+ [types.INT8]: (v) => Number.parseInt(v, 10),
46
+ [types.FLOAT4]: (v) => Number.parseFloat(v),
47
+ [types.FLOAT8]: (v) => Number.parseFloat(v),
48
+ [types.NUMERIC]: (v) => Number.parseFloat(v)
49
+ } });
50
+ return knex({
51
+ ...restConfig,
52
+ client: PgliteDialect,
53
+ connection: { pglite }
54
+ });
55
+ }
56
+ /**
57
+ * Mount a knex adapter to `globalThis.FaasJS_Knex` for `@faasjs/knex`.
58
+ */
59
+ function mountFaasKnex(db, options = {}) {
60
+ const globalWithFaasKnex = globalThis;
61
+ const name = options.name || "knex";
62
+ if (!globalWithFaasKnex.FaasJS_Knex) globalWithFaasKnex.FaasJS_Knex = {};
63
+ globalWithFaasKnex.FaasJS_Knex[name] = {
64
+ adapter: db,
65
+ query: db,
66
+ config: options.config || {}
67
+ };
68
+ }
69
+ /**
70
+ * Remove mounted knex adapter from `globalThis.FaasJS_Knex`.
71
+ */
72
+ function unmountFaasKnex(name = "knex") {
73
+ const globalWithFaasKnex = globalThis;
74
+ if (!globalWithFaasKnex.FaasJS_Knex) return;
75
+ delete globalWithFaasKnex.FaasJS_Knex[name];
76
+ }
77
+
78
+ //#endregion
79
+ //#region src/index.ts
80
+ /**
81
+ * FaasJS's sql plugin, base on [Knex](https://knexjs.org/).
82
+ *
83
+ * [![License: MIT](https://img.shields.io/npm/l/@faasjs/knex.svg)](https://github.com/faasjs/faasjs/blob/main/packages/knex/LICENSE)
84
+ * [![NPM Version](https://img.shields.io/npm/v/@faasjs/knex.svg)](https://www.npmjs.com/package/@faasjs/knex)
85
+ *
86
+ * ## Install
87
+ *
88
+ * ```sh
89
+ * npm install @faasjs/knex
90
+ * ```
91
+ * @packageDocumentation
92
+ */
93
+ /**
94
+ * Origin [knex](https://knexjs.org/) instance.
95
+ */
96
+ const originKnex = knex;
97
+ const Name = "knex";
98
+ if (!global.FaasJS_Knex) global.FaasJS_Knex = {};
99
+ function getGlobalKnexAdapters() {
100
+ if (!global.FaasJS_Knex) global.FaasJS_Knex = {};
101
+ return global.FaasJS_Knex;
102
+ }
103
+ async function initPostgresTypeParsers() {
104
+ const pg = await loadPackage("pg");
105
+ pg.types.setTypeParser(pg.types.builtins.INT2, (v) => Number.parseInt(v, 10));
106
+ pg.types.setTypeParser(pg.types.builtins.INT4, (v) => Number.parseInt(v, 10));
107
+ pg.types.setTypeParser(pg.types.builtins.INT8, (v) => Number.parseInt(v, 10));
108
+ pg.types.setTypeParser(pg.types.builtins.FLOAT4, (v) => Number.parseFloat(v));
109
+ pg.types.setTypeParser(pg.types.builtins.FLOAT8, (v) => Number.parseFloat(v));
110
+ pg.types.setTypeParser(pg.types.builtins.NUMERIC, (v) => Number.parseFloat(v));
12
111
  }
13
112
  var Knex = class {
14
- type = "knex";
15
- name = Name;
16
- config;
17
- adapter;
18
- query;
19
- logger;
20
- constructor(config) {
21
- if (config) {
22
- this.name = config.name || this.name;
23
- this.config = config.config || /* @__PURE__ */ Object.create(null);
24
- } else {
25
- this.config = /* @__PURE__ */ Object.create(null);
26
- }
27
- }
28
- async onMount(data, next) {
29
- this.logger = data.logger;
30
- if (global.FaasJS_Knex[this.name]) {
31
- this.config = global.FaasJS_Knex[this.name].config;
32
- this.adapter = global.FaasJS_Knex[this.name].adapter;
33
- this.query = this.adapter;
34
- this.logger.debug("use exists adapter");
35
- await next();
36
- return;
37
- }
38
- const prefix = `SECRET_${this.name.toUpperCase()}_`;
39
- for (let key in process.env)
40
- if (key.startsWith(prefix)) {
41
- const value = process.env[key];
42
- key = key.replace(prefix, "").toLowerCase();
43
- if (typeof this.config[key] === "undefined")
44
- if (key.startsWith("connection_")) {
45
- if (!this.config.connection) {
46
- this.config.connection = /* @__PURE__ */ Object.create(null);
47
- }
48
- this.config.connection[key.replace("connection_", "")] = value;
49
- } else this.config[key] = value;
50
- }
51
- if (data.config.plugins?.[this.name || this.type]?.config)
52
- this.config = deepMerge(
53
- data.config.plugins[this.name || this.type].config,
54
- this.config
55
- );
56
- switch (this.config.client) {
57
- case "sqlite3":
58
- this.config.client = "better-sqlite3";
59
- this.config.useNullAsDefault = true;
60
- break;
61
- case "pg":
62
- if (!this.config.pool) this.config.pool = /* @__PURE__ */ Object.create(null);
63
- this.config.pool = Object.assign(
64
- {
65
- propagateCreateError: false,
66
- min: 0,
67
- max: 10,
68
- acquireTimeoutMillis: 5e3,
69
- idleTimeoutMillis: 3e4
70
- },
71
- this.config.pool
72
- );
73
- if (typeof this.config.connection === "string" && !this.config.connection.includes("json=true"))
74
- this.config.connection = `${this.config.connection}?json=true`;
75
- break;
76
- default:
77
- if (typeof this.config.client === "string") {
78
- if (this.config.client.startsWith("npm:")) {
79
- const client = await loadPackage(
80
- this.config.client.replace("npm:", "")
81
- );
82
- if (!client) throw Error(`Invalid client: ${this.config.client}`);
83
- if (typeof client === "function") {
84
- this.config.client = client;
85
- break;
86
- }
87
- if (client.default && typeof client.default === "function") {
88
- this.config.client = client.default;
89
- break;
90
- }
91
- throw Error(`Invalid client: ${this.config.client}`);
92
- }
93
- }
94
- break;
95
- }
96
- this.adapter = knex(this.config);
97
- if (this.config.client === "pg") {
98
- const pg = await loadPackage("pg");
99
- pg.types.setTypeParser(
100
- pg.types.builtins.INT2,
101
- (v) => Number.parseInt(v)
102
- );
103
- pg.types.setTypeParser(
104
- pg.types.builtins.INT4,
105
- (v) => Number.parseInt(v)
106
- );
107
- pg.types.setTypeParser(
108
- pg.types.builtins.INT8,
109
- (v) => Number.parseInt(v)
110
- );
111
- pg.types.setTypeParser(
112
- pg.types.builtins.FLOAT4,
113
- (v) => Number.parseFloat(v)
114
- );
115
- pg.types.setTypeParser(
116
- pg.types.builtins.FLOAT8,
117
- (v) => Number.parseFloat(v)
118
- );
119
- pg.types.setTypeParser(
120
- pg.types.builtins.NUMERIC,
121
- (v) => Number.parseFloat(v)
122
- );
123
- }
124
- this.query = this.adapter;
125
- this.query.on("query", ({ sql, __knexQueryUid, bindings }) => {
126
- if (!__knexQueryUid) return;
127
- this.logger.time(`Knex${this.name}${__knexQueryUid}`);
128
- this.logger.debug(
129
- "[%s] query begin: %s %j",
130
- __knexQueryUid,
131
- sql,
132
- bindings
133
- );
134
- }).on("query-response", (response, { sql, __knexQueryUid, bindings }) => {
135
- if (!__knexQueryUid) return;
136
- this.logger.timeEnd(
137
- `Knex${this.name}${__knexQueryUid}`,
138
- "[%s] query done: %s %j %j",
139
- __knexQueryUid,
140
- sql,
141
- bindings,
142
- response
143
- );
144
- }).on("query-error", (_, { __knexQueryUid, sql, bindings }) => {
145
- if (!__knexQueryUid) return;
146
- this.logger.timeEnd(
147
- `Knex${this.name}${__knexQueryUid}`,
148
- "[%s] query failed: %s %j",
149
- __knexQueryUid,
150
- sql,
151
- bindings
152
- );
153
- });
154
- data.logger.debug("connected");
155
- global.FaasJS_Knex[this.name] = this;
156
- await next();
157
- }
158
- async onInvoke(data, next) {
159
- this.logger = data.logger;
160
- await next();
161
- }
162
- async raw(sql, bindings = []) {
163
- if (!this.adapter) throw Error("[Knex] Client not initialized.");
164
- return this.adapter.raw(sql, bindings);
165
- }
166
- /**
167
- * Wraps a transaction, returning a promise that resolves to the return value of the callback.
168
- *
169
- * - Support 'commit' and 'rollback' event.
170
- */
171
- async transaction(scope, config, options) {
172
- if (!this.adapter) throw Error(`[${this.name}] Client not initialized.`);
173
- if (options?.trx) return scope(options.trx);
174
- const trx = await this.adapter.transaction(config);
175
- const trxId = randomUUID();
176
- this.logger.debug("[%s] transaction begin", trxId);
177
- try {
178
- const result = await scope(trx);
179
- if (trx.isCompleted()) {
180
- this.logger.debug("[%s] transaction has been finished in scope", trxId);
181
- return result;
182
- }
183
- this.logger.debug("[%s] transaction begin commit", trxId);
184
- await trx.commit();
185
- this.logger.debug("[%s] transaction committed: %j", trxId, result);
186
- trx.emit("commit");
187
- return result;
188
- } catch (error) {
189
- await trx.rollback(error);
190
- this.logger.error("[%s] transaction rollback: %s", trxId, error);
191
- trx.emit("rollback", error);
192
- throw error;
193
- }
194
- }
195
- schema() {
196
- if (!this.adapter) throw Error(`[${this.name}] Client not initialized.`);
197
- return this.adapter.schema;
198
- }
199
- async quit() {
200
- if (!global.FaasJS_Knex[this.name]) return;
201
- try {
202
- await global.FaasJS_Knex[this.name].adapter.destroy();
203
- delete global.FaasJS_Knex[this.name];
204
- } catch (error) {
205
- console.error(error);
206
- }
207
- }
113
+ type = "knex";
114
+ name = Name;
115
+ config;
116
+ adapter;
117
+ query;
118
+ logger;
119
+ constructor(config) {
120
+ if (config) {
121
+ this.name = config.name || this.name;
122
+ this.config = config.config || Object.create(null);
123
+ } else this.config = Object.create(null);
124
+ }
125
+ async onMount(data, next) {
126
+ this.logger = data.logger;
127
+ const existsAdapter = getGlobalKnexAdapters()[this.name];
128
+ if (existsAdapter) {
129
+ this.config = existsAdapter.config;
130
+ this.adapter = existsAdapter.adapter;
131
+ this.query = this.adapter;
132
+ this.logger.debug("use exists adapter");
133
+ await next();
134
+ return;
135
+ }
136
+ const prefix = `SECRET_${this.name.toUpperCase()}_`;
137
+ for (let key in process.env) if (key.startsWith(prefix)) {
138
+ const value = process.env[key];
139
+ key = key.replace(prefix, "").toLowerCase();
140
+ if (typeof this.config[key] === "undefined") if (key.startsWith("connection_")) {
141
+ if (typeof this.config.connection === "string") continue;
142
+ if (!this.config.connection || typeof this.config.connection !== "object") this.config.connection = Object.create(null);
143
+ this.config.connection[key.replace("connection_", "")] = value;
144
+ } else this.config[key] = value;
145
+ }
146
+ if (data.config.plugins?.[this.name || this.type]?.config) this.config = deepMerge(data.config.plugins[this.name || this.type].config, this.config);
147
+ if (this.config.client === "pglite") {
148
+ const connectionEnvKeys = Object.keys(process.env).filter((key) => key.startsWith(`${prefix}CONNECTION_`));
149
+ if (connectionEnvKeys.length) throw Error(`[Knex] Invalid "pglite" env keys: ${connectionEnvKeys.join(", ")}. Use ${prefix}CONNECTION instead.`);
150
+ this.adapter = await createPgliteKnex(this.config);
151
+ } else {
152
+ switch (this.config.client) {
153
+ case "sqlite3":
154
+ this.config.client = "better-sqlite3";
155
+ this.config.useNullAsDefault = true;
156
+ break;
157
+ case "pg":
158
+ if (!this.config.pool) this.config.pool = Object.create(null);
159
+ this.config.pool = Object.assign({
160
+ propagateCreateError: false,
161
+ min: 0,
162
+ max: 10,
163
+ acquireTimeoutMillis: 5e3,
164
+ idleTimeoutMillis: 3e4
165
+ }, this.config.pool);
166
+ if (typeof this.config.connection === "string" && !this.config.connection.includes("json=true")) this.config.connection = `${this.config.connection}?json=true`;
167
+ break;
168
+ default:
169
+ if (typeof this.config.client === "string") {
170
+ if (this.config.client.startsWith("npm:")) {
171
+ const client = await loadPackage(this.config.client.replace("npm:", ""));
172
+ if (!client) throw Error(`Invalid client: ${this.config.client}`);
173
+ if (typeof client === "function") {
174
+ this.config.client = client;
175
+ break;
176
+ }
177
+ if (client.default && typeof client.default === "function") {
178
+ this.config.client = client.default;
179
+ break;
180
+ }
181
+ throw Error(`Invalid client: ${this.config.client}`);
182
+ }
183
+ }
184
+ break;
185
+ }
186
+ this.adapter = knex(this.config);
187
+ if (this.config.client === "pg") await initPostgresTypeParsers();
188
+ }
189
+ this.query = this.adapter;
190
+ this.query.on("query", ({ sql, __knexQueryUid, bindings }) => {
191
+ if (!__knexQueryUid) return;
192
+ this.logger.time(`Knex${this.name}${__knexQueryUid}`);
193
+ this.logger.debug("[%s] query begin: %s %j", __knexQueryUid, sql, bindings);
194
+ }).on("query-response", (response, { sql, __knexQueryUid, bindings }) => {
195
+ if (!__knexQueryUid) return;
196
+ this.logger.timeEnd(`Knex${this.name}${__knexQueryUid}`, "[%s] query done: %s %j %j", __knexQueryUid, sql, bindings, response);
197
+ }).on("query-error", (_, { __knexQueryUid, sql, bindings }) => {
198
+ if (!__knexQueryUid) return;
199
+ this.logger.timeEnd(`Knex${this.name}${__knexQueryUid}`, "[%s] query failed: %s %j", __knexQueryUid, sql, bindings);
200
+ });
201
+ data.logger.debug("connected");
202
+ getGlobalKnexAdapters()[this.name] = this;
203
+ await next();
204
+ }
205
+ async onInvoke(data, next) {
206
+ this.logger = data.logger;
207
+ await next();
208
+ }
209
+ async raw(sql, bindings = []) {
210
+ if (!this.adapter) throw Error("[Knex] Client not initialized.");
211
+ return this.adapter.raw(sql, bindings);
212
+ }
213
+ /**
214
+ * Wraps a transaction, returning a promise that resolves to the return value of the callback.
215
+ *
216
+ * - Support 'commit' and 'rollback' event.
217
+ */
218
+ async transaction(scope, config, options) {
219
+ if (!this.adapter) throw Error(`[${this.name}] Client not initialized.`);
220
+ if (options?.trx) return scope(options.trx);
221
+ const trx = await this.adapter.transaction(config);
222
+ const trxId = randomUUID();
223
+ this.logger.debug("[%s] transaction begin", trxId);
224
+ try {
225
+ const result = await scope(trx);
226
+ if (trx.isCompleted()) {
227
+ this.logger.debug("[%s] transaction has been finished in scope", trxId);
228
+ return result;
229
+ }
230
+ this.logger.debug("[%s] transaction begin commit", trxId);
231
+ await trx.commit();
232
+ this.logger.debug("[%s] transaction committed: %j", trxId, result);
233
+ trx.emit("commit");
234
+ return result;
235
+ } catch (error) {
236
+ await trx.rollback(error);
237
+ this.logger.error("[%s] transaction rollback: %s", trxId, error);
238
+ trx.emit("rollback", error);
239
+ throw error;
240
+ }
241
+ }
242
+ schema() {
243
+ if (!this.adapter) throw Error(`[${this.name}] Client not initialized.`);
244
+ return this.adapter.schema;
245
+ }
246
+ async quit() {
247
+ const adapters = getGlobalKnexAdapters();
248
+ if (!adapters[this.name]) return;
249
+ try {
250
+ await adapters[this.name].adapter.destroy();
251
+ delete adapters[this.name];
252
+ } catch (error) {
253
+ console.error(error);
254
+ }
255
+ }
208
256
  };
209
257
  function useKnex(config) {
210
- const name = config?.name || Name;
211
- if (global.FaasJS_Knex[name]) return usePlugin(global.FaasJS_Knex[name]);
212
- return usePlugin(new Knex(config));
258
+ const name = config?.name || Name;
259
+ const adapters = getGlobalKnexAdapters();
260
+ if (adapters[name]) return usePlugin(adapters[name]);
261
+ return usePlugin(new Knex(config));
213
262
  }
214
263
  function query(table) {
215
- return useKnex().query(
216
- table
217
- );
264
+ return useKnex().query(table);
218
265
  }
219
266
  async function transaction(scope, config, options) {
220
- return useKnex().transaction(scope, config, options);
267
+ return useKnex().transaction(scope, config, options);
221
268
  }
222
269
  async function raw(sql, bindings = []) {
223
- return useKnex().raw(sql, bindings);
270
+ return useKnex().raw(sql, bindings);
224
271
  }
225
272
 
226
- export { Knex, originKnex, query, raw, transaction, useKnex };
273
+ //#endregion
274
+ export { Knex, createPgliteKnex, initPostgresTypeParsers, mountFaasKnex, originKnex, query, raw, transaction, unmountFaasKnex, useKnex };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@faasjs/knex",
3
- "version": "v8.0.0-beta.5",
3
+ "version": "8.0.0-beta.7",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -24,29 +24,26 @@
24
24
  },
25
25
  "funding": "https://github.com/sponsors/faasjs",
26
26
  "scripts": {
27
- "build": "tsup-node src/index.ts --config ../../tsup.config.ts"
27
+ "build": "tsdown src/index.ts --config ../../tsdown.config.ts"
28
28
  },
29
29
  "files": [
30
30
  "dist"
31
31
  ],
32
32
  "peerDependencies": {
33
33
  "knex": "*",
34
- "@faasjs/deep_merge": ">=v8.0.0-beta.5",
35
- "@faasjs/func": ">=v8.0.0-beta.5",
36
- "@faasjs/logger": ">=v8.0.0-beta.5"
34
+ "@faasjs/func": ">=8.0.0-beta.7",
35
+ "@faasjs/logger": ">=8.0.0-beta.7",
36
+ "@faasjs/node-utils": ">=8.0.0-beta.7"
37
37
  },
38
38
  "devDependencies": {
39
39
  "knex": "*",
40
- "@faasjs/deep_merge": ">=v8.0.0-beta.5",
41
- "@faasjs/func": ">=v8.0.0-beta.5",
42
- "@faasjs/logger": ">=v8.0.0-beta.5",
43
- "@faasjs/load": ">=v8.0.0-beta.5",
44
- "@types/mysql": "*",
45
- "@types/node": "*",
40
+ "@faasjs/func": ">=8.0.0-beta.7",
41
+ "@faasjs/logger": ">=8.0.0-beta.7",
42
+ "@faasjs/node-utils": ">=8.0.0-beta.7",
43
+ "better-sqlite3": "*",
44
+ "knex-pglite": "*",
46
45
  "@types/pg": "*",
47
- "mysql": "*",
48
46
  "pg": "*",
49
- "better-sqlite3": "*",
50
47
  "cloudflare-d1-http-knex": "*"
51
48
  },
52
49
  "engines": {