@faasjs/knex 8.0.0-beta.6 → 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,10 +13,13 @@ npm install @faasjs/knex
13
13
 
14
14
  ## Functions
15
15
 
16
+ - [createPgliteKnex](functions/createPgliteKnex.md)
16
17
  - [initPostgresTypeParsers](functions/initPostgresTypeParsers.md)
18
+ - [mountFaasKnex](functions/mountFaasKnex.md)
17
19
  - [query](functions/query.md)
18
20
  - [raw](functions/raw.md)
19
21
  - [transaction](functions/transaction.md)
22
+ - [unmountFaasKnex](functions/unmountFaasKnex.md)
20
23
  - [useKnex](functions/useKnex.md)
21
24
 
22
25
  ## Classes
@@ -26,6 +29,7 @@ npm install @faasjs/knex
26
29
  ## Type Aliases
27
30
 
28
31
  - [KnexConfig](type-aliases/KnexConfig.md)
32
+ - [MountFaasKnexOptions](type-aliases/MountFaasKnexOptions.md)
29
33
 
30
34
  ## Variables
31
35
 
package/dist/index.cjs CHANGED
@@ -1,239 +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;
18
131
  }
19
132
  async function initPostgresTypeParsers() {
20
- const pg = await load.loadPackage("pg");
21
- pg.types.setTypeParser(
22
- pg.types.builtins.INT2,
23
- (v) => Number.parseInt(v, 10)
24
- );
25
- pg.types.setTypeParser(
26
- pg.types.builtins.INT4,
27
- (v) => Number.parseInt(v, 10)
28
- );
29
- pg.types.setTypeParser(
30
- pg.types.builtins.INT8,
31
- (v) => Number.parseInt(v, 10)
32
- );
33
- pg.types.setTypeParser(
34
- pg.types.builtins.FLOAT4,
35
- (v) => Number.parseFloat(v)
36
- );
37
- pg.types.setTypeParser(
38
- pg.types.builtins.FLOAT8,
39
- (v) => Number.parseFloat(v)
40
- );
41
- pg.types.setTypeParser(
42
- pg.types.builtins.NUMERIC,
43
- (v) => Number.parseFloat(v)
44
- );
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));
45
140
  }
46
141
  var Knex = class {
47
- type = "knex";
48
- name = Name;
49
- config;
50
- adapter;
51
- query;
52
- logger;
53
- constructor(config) {
54
- if (config) {
55
- this.name = config.name || this.name;
56
- this.config = config.config || /* @__PURE__ */ Object.create(null);
57
- } else {
58
- this.config = /* @__PURE__ */ Object.create(null);
59
- }
60
- }
61
- async onMount(data, next) {
62
- this.logger = data.logger;
63
- if (global.FaasJS_Knex[this.name]) {
64
- this.config = global.FaasJS_Knex[this.name].config;
65
- this.adapter = global.FaasJS_Knex[this.name].adapter;
66
- this.query = this.adapter;
67
- this.logger.debug("use exists adapter");
68
- await next();
69
- return;
70
- }
71
- const prefix = `SECRET_${this.name.toUpperCase()}_`;
72
- for (let key in process.env)
73
- if (key.startsWith(prefix)) {
74
- const value = process.env[key];
75
- key = key.replace(prefix, "").toLowerCase();
76
- if (typeof this.config[key] === "undefined")
77
- if (key.startsWith("connection_")) {
78
- if (!this.config.connection) {
79
- this.config.connection = /* @__PURE__ */ Object.create(null);
80
- }
81
- this.config.connection[key.replace("connection_", "")] = value;
82
- } else this.config[key] = value;
83
- }
84
- if (data.config.plugins?.[this.name || this.type]?.config)
85
- this.config = deep_merge.deepMerge(
86
- data.config.plugins[this.name || this.type].config,
87
- this.config
88
- );
89
- switch (this.config.client) {
90
- case "sqlite3":
91
- this.config.client = "better-sqlite3";
92
- this.config.useNullAsDefault = true;
93
- break;
94
- case "pg":
95
- if (!this.config.pool) this.config.pool = /* @__PURE__ */ Object.create(null);
96
- this.config.pool = Object.assign(
97
- {
98
- propagateCreateError: false,
99
- min: 0,
100
- max: 10,
101
- acquireTimeoutMillis: 5e3,
102
- idleTimeoutMillis: 3e4
103
- },
104
- this.config.pool
105
- );
106
- if (typeof this.config.connection === "string" && !this.config.connection.includes("json=true"))
107
- this.config.connection = `${this.config.connection}?json=true`;
108
- break;
109
- default:
110
- if (typeof this.config.client === "string") {
111
- if (this.config.client.startsWith("npm:")) {
112
- const client = await load.loadPackage(
113
- this.config.client.replace("npm:", "")
114
- );
115
- if (!client) throw Error(`Invalid client: ${this.config.client}`);
116
- if (typeof client === "function") {
117
- this.config.client = client;
118
- break;
119
- }
120
- if (client.default && typeof client.default === "function") {
121
- this.config.client = client.default;
122
- break;
123
- }
124
- throw Error(`Invalid client: ${this.config.client}`);
125
- }
126
- }
127
- break;
128
- }
129
- this.adapter = knex__default.default(this.config);
130
- if (this.config.client === "pg") await initPostgresTypeParsers();
131
- this.query = this.adapter;
132
- this.query.on("query", ({ sql, __knexQueryUid, bindings }) => {
133
- if (!__knexQueryUid) return;
134
- this.logger.time(`Knex${this.name}${__knexQueryUid}`);
135
- this.logger.debug(
136
- "[%s] query begin: %s %j",
137
- __knexQueryUid,
138
- sql,
139
- bindings
140
- );
141
- }).on("query-response", (response, { sql, __knexQueryUid, bindings }) => {
142
- if (!__knexQueryUid) return;
143
- this.logger.timeEnd(
144
- `Knex${this.name}${__knexQueryUid}`,
145
- "[%s] query done: %s %j %j",
146
- __knexQueryUid,
147
- sql,
148
- bindings,
149
- response
150
- );
151
- }).on("query-error", (_, { __knexQueryUid, sql, bindings }) => {
152
- if (!__knexQueryUid) return;
153
- this.logger.timeEnd(
154
- `Knex${this.name}${__knexQueryUid}`,
155
- "[%s] query failed: %s %j",
156
- __knexQueryUid,
157
- sql,
158
- bindings
159
- );
160
- });
161
- data.logger.debug("connected");
162
- global.FaasJS_Knex[this.name] = this;
163
- await next();
164
- }
165
- async onInvoke(data, next) {
166
- this.logger = data.logger;
167
- await next();
168
- }
169
- async raw(sql, bindings = []) {
170
- if (!this.adapter) throw Error("[Knex] Client not initialized.");
171
- return this.adapter.raw(sql, bindings);
172
- }
173
- /**
174
- * Wraps a transaction, returning a promise that resolves to the return value of the callback.
175
- *
176
- * - Support 'commit' and 'rollback' event.
177
- */
178
- async transaction(scope, config, options) {
179
- if (!this.adapter) throw Error(`[${this.name}] Client not initialized.`);
180
- if (options?.trx) return scope(options.trx);
181
- const trx = await this.adapter.transaction(config);
182
- const trxId = crypto.randomUUID();
183
- this.logger.debug("[%s] transaction begin", trxId);
184
- try {
185
- const result = await scope(trx);
186
- if (trx.isCompleted()) {
187
- this.logger.debug("[%s] transaction has been finished in scope", trxId);
188
- return result;
189
- }
190
- this.logger.debug("[%s] transaction begin commit", trxId);
191
- await trx.commit();
192
- this.logger.debug("[%s] transaction committed: %j", trxId, result);
193
- trx.emit("commit");
194
- return result;
195
- } catch (error) {
196
- await trx.rollback(error);
197
- this.logger.error("[%s] transaction rollback: %s", trxId, error);
198
- trx.emit("rollback", error);
199
- throw error;
200
- }
201
- }
202
- schema() {
203
- if (!this.adapter) throw Error(`[${this.name}] Client not initialized.`);
204
- return this.adapter.schema;
205
- }
206
- async quit() {
207
- if (!global.FaasJS_Knex[this.name]) return;
208
- try {
209
- await global.FaasJS_Knex[this.name].adapter.destroy();
210
- delete global.FaasJS_Knex[this.name];
211
- } catch (error) {
212
- console.error(error);
213
- }
214
- }
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
+ }
215
285
  };
216
286
  function useKnex(config) {
217
- const name = config?.name || Name;
218
- if (global.FaasJS_Knex[name]) return func.usePlugin(global.FaasJS_Knex[name]);
219
- 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));
220
291
  }
221
292
  function query(table) {
222
- return useKnex().query(
223
- table
224
- );
293
+ return useKnex().query(table);
225
294
  }
226
295
  async function transaction(scope, config, options) {
227
- return useKnex().transaction(scope, config, options);
296
+ return useKnex().transaction(scope, config, options);
228
297
  }
229
298
  async function raw(sql, bindings = []) {
230
- return useKnex().raw(sql, bindings);
299
+ return useKnex().raw(sql, bindings);
231
300
  }
232
301
 
302
+ //#endregion
233
303
  exports.Knex = Knex;
304
+ exports.createPgliteKnex = createPgliteKnex;
234
305
  exports.initPostgresTypeParsers = initPostgresTypeParsers;
306
+ exports.mountFaasKnex = mountFaasKnex;
235
307
  exports.originKnex = originKnex;
236
308
  exports.query = query;
237
309
  exports.raw = raw;
238
310
  exports.transaction = transaction;
239
- exports.useKnex = useKnex;
311
+ exports.unmountFaasKnex = unmountFaasKnex;
312
+ exports.useKnex = useKnex;
package/dist/index.d.ts CHANGED
@@ -1,68 +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
  };
29
33
  declare function initPostgresTypeParsers(): Promise<void>;
30
34
  declare class Knex implements Plugin {
31
- readonly type = "knex";
32
- readonly name: string;
33
- config: Knex$1.Config;
34
- adapter: Knex$1;
35
- query: Knex$1;
36
- logger: Logger;
37
- constructor(config?: KnexConfig);
38
- onMount(data: MountData, next: Next): Promise<void>;
39
- onInvoke(data: InvokeData<any, any, any>, next: Next): Promise<void>;
40
- raw<TResult = any>(sql: string, bindings?: Knex$1.RawBinding[] | Knex$1.ValueDict): Promise<Knex$1.Raw<TResult>>;
41
- /**
42
- * Wraps a transaction, returning a promise that resolves to the return value of the callback.
43
- *
44
- * - Support 'commit' and 'rollback' event.
45
- */
46
- transaction<TResult = any>(scope: (trx: Knex$1.Transaction<any, any>) => Promise<TResult>, config?: Knex$1.TransactionConfig, options?: {
47
- trx?: Knex$1.Transaction;
48
- }): Promise<TResult>;
49
- schema(): Knex$1.SchemaBuilder;
50
- 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>;
51
55
  }
52
56
  declare function useKnex(config?: KnexConfig): UseifyPlugin<Knex>;
53
- declare function query<TName extends Knex$1.TableNames>(table: TName): Knex$1.QueryBuilder<Knex$1.TableType<TName>, {
54
- _base: Knex$1.ResolveTableType<Knex$1.TableType<TName>, 'base'>;
55
- _hasSelection: false;
56
- _keys: never;
57
- _aliases: {};
58
- _single: false;
59
- _intersectProps: {};
60
- _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;
61
65
  }[]>;
62
- declare function query<TName extends {} = any, TResult = any[]>(table: string): Knex$1.QueryBuilder<TName, TResult>;
63
- declare function transaction<TResult = any>(scope: (trx: Knex$1.Transaction<any, any>) => Promise<TResult>, config?: Knex$1.TransactionConfig, options?: {
64
- 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;
65
69
  }): Promise<TResult>;
66
- declare function raw<TResult = any>(sql: string, bindings?: Knex$1.RawBinding[] | Knex$1.ValueDict): Promise<Knex$1.Raw<TResult>>;
67
-
68
- export { Knex, type KnexConfig, initPostgresTypeParsers, 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,227 +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;
12
102
  }
13
103
  async function initPostgresTypeParsers() {
14
- const pg = await loadPackage("pg");
15
- pg.types.setTypeParser(
16
- pg.types.builtins.INT2,
17
- (v) => Number.parseInt(v, 10)
18
- );
19
- pg.types.setTypeParser(
20
- pg.types.builtins.INT4,
21
- (v) => Number.parseInt(v, 10)
22
- );
23
- pg.types.setTypeParser(
24
- pg.types.builtins.INT8,
25
- (v) => Number.parseInt(v, 10)
26
- );
27
- pg.types.setTypeParser(
28
- pg.types.builtins.FLOAT4,
29
- (v) => Number.parseFloat(v)
30
- );
31
- pg.types.setTypeParser(
32
- pg.types.builtins.FLOAT8,
33
- (v) => Number.parseFloat(v)
34
- );
35
- pg.types.setTypeParser(
36
- pg.types.builtins.NUMERIC,
37
- (v) => Number.parseFloat(v)
38
- );
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));
39
111
  }
40
112
  var Knex = class {
41
- type = "knex";
42
- name = Name;
43
- config;
44
- adapter;
45
- query;
46
- logger;
47
- constructor(config) {
48
- if (config) {
49
- this.name = config.name || this.name;
50
- this.config = config.config || /* @__PURE__ */ Object.create(null);
51
- } else {
52
- this.config = /* @__PURE__ */ Object.create(null);
53
- }
54
- }
55
- async onMount(data, next) {
56
- this.logger = data.logger;
57
- if (global.FaasJS_Knex[this.name]) {
58
- this.config = global.FaasJS_Knex[this.name].config;
59
- this.adapter = global.FaasJS_Knex[this.name].adapter;
60
- this.query = this.adapter;
61
- this.logger.debug("use exists adapter");
62
- await next();
63
- return;
64
- }
65
- const prefix = `SECRET_${this.name.toUpperCase()}_`;
66
- for (let key in process.env)
67
- if (key.startsWith(prefix)) {
68
- const value = process.env[key];
69
- key = key.replace(prefix, "").toLowerCase();
70
- if (typeof this.config[key] === "undefined")
71
- if (key.startsWith("connection_")) {
72
- if (!this.config.connection) {
73
- this.config.connection = /* @__PURE__ */ Object.create(null);
74
- }
75
- this.config.connection[key.replace("connection_", "")] = value;
76
- } else this.config[key] = value;
77
- }
78
- if (data.config.plugins?.[this.name || this.type]?.config)
79
- this.config = deepMerge(
80
- data.config.plugins[this.name || this.type].config,
81
- this.config
82
- );
83
- switch (this.config.client) {
84
- case "sqlite3":
85
- this.config.client = "better-sqlite3";
86
- this.config.useNullAsDefault = true;
87
- break;
88
- case "pg":
89
- if (!this.config.pool) this.config.pool = /* @__PURE__ */ Object.create(null);
90
- this.config.pool = Object.assign(
91
- {
92
- propagateCreateError: false,
93
- min: 0,
94
- max: 10,
95
- acquireTimeoutMillis: 5e3,
96
- idleTimeoutMillis: 3e4
97
- },
98
- this.config.pool
99
- );
100
- if (typeof this.config.connection === "string" && !this.config.connection.includes("json=true"))
101
- this.config.connection = `${this.config.connection}?json=true`;
102
- break;
103
- default:
104
- if (typeof this.config.client === "string") {
105
- if (this.config.client.startsWith("npm:")) {
106
- const client = await loadPackage(
107
- this.config.client.replace("npm:", "")
108
- );
109
- if (!client) throw Error(`Invalid client: ${this.config.client}`);
110
- if (typeof client === "function") {
111
- this.config.client = client;
112
- break;
113
- }
114
- if (client.default && typeof client.default === "function") {
115
- this.config.client = client.default;
116
- break;
117
- }
118
- throw Error(`Invalid client: ${this.config.client}`);
119
- }
120
- }
121
- break;
122
- }
123
- this.adapter = knex(this.config);
124
- if (this.config.client === "pg") await initPostgresTypeParsers();
125
- this.query = this.adapter;
126
- this.query.on("query", ({ sql, __knexQueryUid, bindings }) => {
127
- if (!__knexQueryUid) return;
128
- this.logger.time(`Knex${this.name}${__knexQueryUid}`);
129
- this.logger.debug(
130
- "[%s] query begin: %s %j",
131
- __knexQueryUid,
132
- sql,
133
- bindings
134
- );
135
- }).on("query-response", (response, { sql, __knexQueryUid, bindings }) => {
136
- if (!__knexQueryUid) return;
137
- this.logger.timeEnd(
138
- `Knex${this.name}${__knexQueryUid}`,
139
- "[%s] query done: %s %j %j",
140
- __knexQueryUid,
141
- sql,
142
- bindings,
143
- response
144
- );
145
- }).on("query-error", (_, { __knexQueryUid, sql, bindings }) => {
146
- if (!__knexQueryUid) return;
147
- this.logger.timeEnd(
148
- `Knex${this.name}${__knexQueryUid}`,
149
- "[%s] query failed: %s %j",
150
- __knexQueryUid,
151
- sql,
152
- bindings
153
- );
154
- });
155
- data.logger.debug("connected");
156
- global.FaasJS_Knex[this.name] = this;
157
- await next();
158
- }
159
- async onInvoke(data, next) {
160
- this.logger = data.logger;
161
- await next();
162
- }
163
- async raw(sql, bindings = []) {
164
- if (!this.adapter) throw Error("[Knex] Client not initialized.");
165
- return this.adapter.raw(sql, bindings);
166
- }
167
- /**
168
- * Wraps a transaction, returning a promise that resolves to the return value of the callback.
169
- *
170
- * - Support 'commit' and 'rollback' event.
171
- */
172
- async transaction(scope, config, options) {
173
- if (!this.adapter) throw Error(`[${this.name}] Client not initialized.`);
174
- if (options?.trx) return scope(options.trx);
175
- const trx = await this.adapter.transaction(config);
176
- const trxId = randomUUID();
177
- this.logger.debug("[%s] transaction begin", trxId);
178
- try {
179
- const result = await scope(trx);
180
- if (trx.isCompleted()) {
181
- this.logger.debug("[%s] transaction has been finished in scope", trxId);
182
- return result;
183
- }
184
- this.logger.debug("[%s] transaction begin commit", trxId);
185
- await trx.commit();
186
- this.logger.debug("[%s] transaction committed: %j", trxId, result);
187
- trx.emit("commit");
188
- return result;
189
- } catch (error) {
190
- await trx.rollback(error);
191
- this.logger.error("[%s] transaction rollback: %s", trxId, error);
192
- trx.emit("rollback", error);
193
- throw error;
194
- }
195
- }
196
- schema() {
197
- if (!this.adapter) throw Error(`[${this.name}] Client not initialized.`);
198
- return this.adapter.schema;
199
- }
200
- async quit() {
201
- if (!global.FaasJS_Knex[this.name]) return;
202
- try {
203
- await global.FaasJS_Knex[this.name].adapter.destroy();
204
- delete global.FaasJS_Knex[this.name];
205
- } catch (error) {
206
- console.error(error);
207
- }
208
- }
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
+ }
209
256
  };
210
257
  function useKnex(config) {
211
- const name = config?.name || Name;
212
- if (global.FaasJS_Knex[name]) return usePlugin(global.FaasJS_Knex[name]);
213
- 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));
214
262
  }
215
263
  function query(table) {
216
- return useKnex().query(
217
- table
218
- );
264
+ return useKnex().query(table);
219
265
  }
220
266
  async function transaction(scope, config, options) {
221
- return useKnex().transaction(scope, config, options);
267
+ return useKnex().transaction(scope, config, options);
222
268
  }
223
269
  async function raw(sql, bindings = []) {
224
- return useKnex().raw(sql, bindings);
270
+ return useKnex().raw(sql, bindings);
225
271
  }
226
272
 
227
- export { Knex, initPostgresTypeParsers, 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": "8.0.0-beta.6",
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": ">=8.0.0-beta.6",
35
- "@faasjs/func": ">=8.0.0-beta.6",
36
- "@faasjs/logger": ">=8.0.0-beta.6"
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": ">=8.0.0-beta.6",
41
- "@faasjs/func": ">=8.0.0-beta.6",
42
- "@faasjs/logger": ">=8.0.0-beta.6",
43
- "@faasjs/load": ">=8.0.0-beta.6",
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": {