miqro 7.3.3 → 7.3.5

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.
@@ -18,13 +18,15 @@ export default {
18
18
  const cookieToken = args.req.cookies[ADMIN_EDITOR_AUTH_COOKIE];
19
19
  //console.log("\n\nqueryToken[%s] cookieToken[%s] KEY[%s]\n\n", queryToken, cookieToken, KEY);
20
20
  if (queryToken) {
21
- if (typeof queryToken === "string" && timingSafeEqual(Buffer.from(queryToken), Buffer.from(KEY))) {
21
+ const queryBuf = Buffer.from(String(queryToken));
22
+ const keyBuf = Buffer.from(KEY);
23
+ if (typeof queryToken === "string" && queryBuf.length === keyBuf.length && timingSafeEqual(queryBuf, keyBuf)) {
22
24
  args.res.setCookie(ADMIN_EDITOR_AUTH_COOKIE, KEY, {
23
- expires: new Date(Date.now() + 1000 * 60 * 60 * 24 * 31 * 12 * 500),
25
+ expires: new Date(Date.now() + 1000 * 60 * 60 * 24),
24
26
  httpOnly: true,
25
- //secure: true,
27
+ //secure: args.req.secure,
28
+ sameSite: "strict",
26
29
  path: "/",
27
- //sameSite: "strict"
28
30
  });
29
31
  args.req.searchParams.delete(ADMIN_EDITOR_AUTH_QUERY);
30
32
  const queryString = args.req.searchParams.toString();
@@ -59,6 +59,7 @@ export async function esBuild(options, logger) {
59
59
  else {
60
60
  exec(esBuildCMD, {
61
61
  maxBuffer: 1024 * 1000 * 2000,
62
+ timeout: 60000,
62
63
  cwd: dirname(options.entryPoints[0])
63
64
  }, (err, stdout, _stderr) => {
64
65
  if (err) {
@@ -80,20 +80,38 @@ export function setupExitHandlers(app) {
80
80
  }
81
81
  process.exit(EXIT_CODES.ABNORMAL_UNCONTROLLED);
82
82
  });
83
- process.on("SIGTERM", function () {
83
+ process.on("SIGTERM", async function () {
84
84
  app.logger?.info('SIGTERM received');
85
+ if (app.server) {
86
+ await Promise.race([
87
+ app.stop(),
88
+ new Promise(r => setTimeout(r, 5000))
89
+ ]);
90
+ }
85
91
  process.exit(EXIT_CODES.ABNORMAL_UNCONTROLLED);
86
92
  });
87
- process.on('SIGHUP', function () {
93
+ process.on('SIGHUP', async function () {
88
94
  app.logger?.info('SIGHUP received');
95
+ if (app.server) {
96
+ await Promise.race([
97
+ app.stop(),
98
+ new Promise(r => setTimeout(r, 5000))
99
+ ]);
100
+ }
89
101
  process.exit(EXIT_CODES.ABNORMAL_UNCONTROLLED);
90
102
  });
91
103
  /*process.on('SIGKILL', function () {
92
104
  server.logger.info('SIGKILL received');
93
105
  process.exit(EXIT_CODES.ABNORMAL_UNCONTROLLED);
94
106
  });*/
95
- process.on('SIGINT', function () {
107
+ process.on('SIGINT', async function () {
96
108
  app.logger?.info('SIGINT received');
109
+ if (app.server) {
110
+ await Promise.race([
111
+ app.stop(),
112
+ new Promise(r => setTimeout(r, 5000))
113
+ ]);
114
+ }
97
115
  process.exit(EXIT_CODES.ABNORMAL_UNCONTROLLED);
98
116
  });
99
117
  }
@@ -173,6 +173,29 @@ export const DBConfigSchema = {
173
173
  type: "object",
174
174
  properties: {
175
175
  url: "string?",
176
+ executor: {
177
+ type: "object?",
178
+ properties: {
179
+ prepare: "function",
180
+ query: "function",
181
+ disconnect: "function",
182
+ connect: "function",
183
+ transaction: "function",
184
+ target: "any",
185
+ transformInput: "function",
186
+ transformOutput: "function"
187
+ }
188
+ },
189
+ pool: {
190
+ type: "object?",
191
+ properties: {
192
+ min: "number?",
193
+ max: "number?",
194
+ idleTimeoutMillis: "number?",
195
+ connectionTimeoutMillis: "number?",
196
+ maxLifetimeSeconds: "number?"
197
+ }
198
+ },
176
199
  disabled: "boolean?",
177
200
  storage: "string?",
178
201
  dialect: "string?",
@@ -28,6 +28,7 @@ export interface MiqroOptions extends ImportJSXFileOptions {
28
28
  https?: boolean;
29
29
  httpRedirect?: number;
30
30
  noMinify?: boolean;
31
+ allowedRedirectHosts?: string[];
31
32
  }
32
33
  export interface InflateOptions {
33
34
  inflateDir?: string;
@@ -383,7 +383,12 @@ export class Miqro {
383
383
  if (this.options?.httpRedirect) {
384
384
  this.httpsRedirectServer = new App();
385
385
  this.httpsRedirectServer.use(async (req, res) => {
386
- const hostname = req.headers.host.split(":").length > 1 ? req.headers.host.split(":")[0] : req.headers.host;
386
+ const hostname = req.headers.host?.split(":")[0] ?? "";
387
+ const allowed = this.options?.allowedRedirectHosts;
388
+ if (allowed && !allowed.includes(hostname)) {
389
+ res.writeHead(400).end("Invalid Host header");
390
+ return;
391
+ }
387
392
  return await res.redirect('https://' + hostname + ":" + this.options.port + req.url);
388
393
  });
389
394
  }
@@ -15,9 +15,11 @@ export class DBManager {
15
15
  this.options?.logger?.debug("setting up db connection [%s]", config.name);
16
16
  this.options?.logger?.trace("creating db connection [%s]", config.name);
17
17
  const db = new Database({
18
+ executor: config.executor,
18
19
  dialect: config.dialect ? config.dialect : "node:sqlite",
19
20
  storage: config.storage ? config.storage : "./db.sqlite3",
20
21
  connectionString: config.url,
22
+ pool: config.pool,
21
23
  logger: this.options?.loggerProvider?.getLogger(`${DB_IDENTIFIER}_${config.name}`)
22
24
  });
23
25
  this.options?.logger?.trace("connecting db connection [%s]", config.name);
@@ -1,4 +1,4 @@
1
- import { Database } from "@miqro/query";
1
+ import { Database, QueryExecutor } from "@miqro/query";
2
2
  import { WebSocketServerOptions, SessionHandlerOptions, Logger, WebSocketServer, ReadBuffer, URLEncodedParser, JSONParser, TextParser, CORS, SessionHandler, RouteOptions, Handler, Request, Response, LogLevel, LoggerTransportWriteArgs, CORSOptions, HandlerWithOptions, ErrorHandler, SchemaProperties, APIRoute as BaseAPIRoute } from "@miqro/core";
3
3
  import { request } from "@miqro/request";
4
4
  import { Parser, ParserInterface } from "@miqro/parser";
@@ -219,9 +219,17 @@ export interface ServerConfig {
219
219
  export interface DBConfig {
220
220
  dialect?: string;
221
221
  storage?: string;
222
+ executor?: QueryExecutor;
222
223
  url?: string;
223
224
  disabled?: boolean;
224
225
  name: string;
226
+ pool?: {
227
+ min?: number;
228
+ max?: number;
229
+ idleTimeoutMillis?: number;
230
+ connectionTimeoutMillis?: number;
231
+ maxLifetimeSeconds?: number;
232
+ };
225
233
  }
226
234
  export interface APIOptions<TBody extends SchemaProperties | string | boolean | undefined = SchemaProperties | string | boolean | undefined, TParams extends SchemaProperties | string | boolean | undefined = SchemaProperties | string | boolean | undefined, TQuery extends SchemaProperties | string | boolean | undefined = SchemaProperties | string | boolean | undefined> extends Partial<RouteOptions<TBody, TParams, TQuery>> {
227
235
  basePath?: string;
package/build/lib.cjs CHANGED
@@ -720,7 +720,7 @@ function ReadBuffer(options) {
720
720
  req.removeListener("end", endListener);
721
721
  try {
722
722
  const concatBuffers = Buffer.concat(buffers);
723
- const responseBuffer = req.headers["content-encoding"] === "gzip" ? (0, import_zlib.gunzipSync)(concatBuffers) : concatBuffers;
723
+ const responseBuffer = req.headers["content-encoding"] === "gzip" ? (0, import_zlib.gunzipSync)(concatBuffers, { maxOutputLength: limit }) : concatBuffers;
724
724
  req.logger.trace("ctx.buffer %o", responseBuffer);
725
725
  req.buffer = responseBuffer;
726
726
  resolve24();
@@ -2897,32 +2897,42 @@ var init_websocket = __esm({
2897
2897
  req.logger.debug("upgrading connection");
2898
2898
  socket.write(createUpgradeHeaders(acceptKey, extraHeaders));
2899
2899
  socket.on("data", async (data) => {
2900
- const frame = parseFrame(data, this.options.maxFrameSize);
2901
- if (frame === PING) {
2902
- try {
2903
- socket.write(Buffer.from([138, 0]));
2904
- } catch (e) {
2905
- req.logger.error(e);
2906
- }
2907
- } else if (frame !== null) {
2908
- if (!this.options.onMessage) {
2909
- socket.end();
2910
- socket.destroy();
2900
+ try {
2901
+ const frame = parseFrame(data, this.options.maxFrameSize);
2902
+ if (frame === PING) {
2903
+ try {
2904
+ socket.write(Buffer.from([138, 0]));
2905
+ } catch (e) {
2906
+ req.logger.error(e);
2907
+ }
2908
+ } else if (frame !== null) {
2909
+ if (!this.options.onMessage) {
2910
+ socket.end();
2911
+ socket.destroy();
2912
+ } else {
2913
+ try {
2914
+ await this.options.onMessage(client, frame);
2915
+ } catch (e) {
2916
+ req.logger.error(e);
2917
+ }
2918
+ }
2911
2919
  } else {
2912
2920
  try {
2913
- await this.options.onMessage(client, frame);
2921
+ socket.write(Buffer.from([136, 0]));
2914
2922
  } catch (e) {
2915
2923
  req.logger.error(e);
2916
2924
  }
2925
+ socket.end();
2926
+ socket.destroy();
2917
2927
  }
2918
- } else {
2928
+ } catch (e) {
2919
2929
  try {
2920
- socket.write(Buffer.from([136, 0]));
2921
- } catch (e) {
2922
- req.logger.error(e);
2930
+ req.logger?.error(e);
2931
+ socket.end();
2932
+ socket.destroy();
2933
+ } catch (e2) {
2934
+ console.error(e2);
2923
2935
  }
2924
- socket.end();
2925
- socket.destroy();
2926
2936
  }
2927
2937
  });
2928
2938
  socket.on("error", async (error2) => {
@@ -9446,6 +9456,7 @@ async function esBuild2(options, logger) {
9446
9456
  } else {
9447
9457
  (0, import_node_child_process.exec)(esBuildCMD, {
9448
9458
  maxBuffer: 1024 * 1e3 * 2e3,
9459
+ timeout: 6e4,
9449
9460
  cwd: (0, import_node_path5.dirname)(options.entryPoints[0])
9450
9461
  }, (err, stdout, _stderr) => {
9451
9462
  if (err) {
@@ -9603,6 +9614,29 @@ var DBConfigSchema = {
9603
9614
  type: "object",
9604
9615
  properties: {
9605
9616
  url: "string?",
9617
+ executor: {
9618
+ type: "object?",
9619
+ properties: {
9620
+ prepare: "function",
9621
+ query: "function",
9622
+ disconnect: "function",
9623
+ connect: "function",
9624
+ transaction: "function",
9625
+ target: "any",
9626
+ transformInput: "function",
9627
+ transformOutput: "function"
9628
+ }
9629
+ },
9630
+ pool: {
9631
+ type: "object?",
9632
+ properties: {
9633
+ min: "number?",
9634
+ max: "number?",
9635
+ idleTimeoutMillis: "number?",
9636
+ connectionTimeoutMillis: "number?",
9637
+ maxLifetimeSeconds: "number?"
9638
+ }
9639
+ },
9606
9640
  disabled: "boolean?",
9607
9641
  storage: "string?",
9608
9642
  dialect: "string?",
@@ -9883,7 +9917,7 @@ function jsx2HTML(out, runtime) {
9883
9917
  // src/types.ts
9884
9918
  init_lib3();
9885
9919
 
9886
- // node_modules/@miqro/query/build/executors/sqlite3/utils.js
9920
+ // node_modules/@miqro/query/build/executors/sqlite-native/utils.js
9887
9921
  function sqlite3ExecutorPrepare(args) {
9888
9922
  switch (args._type) {
9889
9923
  case "delete": {
@@ -9891,7 +9925,7 @@ function sqlite3ExecutorPrepare(args) {
9891
9925
  const where = getWhereStatement(q);
9892
9926
  const returing = q._returning.length === 0 ? "*" : q._returning.join(",");
9893
9927
  const whereSQL = where.sql !== "" ? ` WHERE ${where.sql}` : "";
9894
- const sql = `DELETE FROM "${q._table}"${whereSQL}${getOrderBy(q._orderBy)}${getLimit(q._limitBy, q._offsetBy)} RETURNING ${returing}`;
9928
+ const sql = `DELETE FROM ${renderTable(q._table)}${whereSQL}${getOrderBy(q._orderBy)}${getLimit(q._limitBy, q._offsetBy)} RETURNING ${returing}`;
9895
9929
  return {
9896
9930
  sql,
9897
9931
  values: where.values
@@ -9904,7 +9938,7 @@ function sqlite3ExecutorPrepare(args) {
9904
9938
  }
9905
9939
  case "create-table": {
9906
9940
  const q = args;
9907
- const sql = `CREATE TABLE${q._ignoreDuplicate ? " IF NOT EXISTS" : ""} "${q._table}"${getCreateTableColumns(q._definition)}`;
9941
+ const sql = `CREATE TABLE${q._ignoreDuplicate ? " IF NOT EXISTS" : ""} ${renderTable(q._table)}${getCreateTableColumns(q._definition)}`;
9908
9942
  return sql;
9909
9943
  }
9910
9944
  case "drop-database": {
@@ -9914,7 +9948,7 @@ function sqlite3ExecutorPrepare(args) {
9914
9948
  }
9915
9949
  case "drop-table": {
9916
9950
  const q = args;
9917
- const sql = `DROP TABLE${q._ignoreDuplicate ? " IF EXISTS" : ""} "${q._table}"`;
9951
+ const sql = `DROP TABLE${q._ignoreDuplicate ? " IF EXISTS" : ""} ${renderTable(q._table)}`;
9918
9952
  return sql;
9919
9953
  }
9920
9954
  case "alter-table": {
@@ -9933,17 +9967,17 @@ function sqlite3ExecutorPrepare(args) {
9933
9967
  throw new Error("unsupported alter action add without definition");
9934
9968
  }
9935
9969
  alters.push({
9936
- sql: `ALTER TABLE "${q._table}" ADD COLUMN ${getCreateTableColumn(l._column, l._definition, [])}`
9970
+ sql: `ALTER TABLE ${renderTable(q._table)} ADD COLUMN ${getCreateTableColumn(l._column, l._definition, [])}`
9937
9971
  });
9938
9972
  break;
9939
9973
  case "drop":
9940
9974
  alters.push({
9941
- sql: `ALTER TABLE "${q._table}" DROP COLUMN "${l._column}"`
9975
+ sql: `ALTER TABLE ${renderTable(q._table)} DROP COLUMN "${l._column}"`
9942
9976
  });
9943
9977
  break;
9944
9978
  case "rename":
9945
9979
  alters.push({
9946
- sql: `ALTER TABLE "${q._table}" RENAME COLUMN "${l._column}" TO "${l._newName}"`
9980
+ sql: `ALTER TABLE ${renderTable(q._table)} RENAME COLUMN "${l._column}" TO "${l._newName}"`
9947
9981
  });
9948
9982
  break;
9949
9983
  default:
@@ -9956,7 +9990,7 @@ function sqlite3ExecutorPrepare(args) {
9956
9990
  const q = args;
9957
9991
  const rows = getInsertValues(q._columns, q._values);
9958
9992
  const returing = q._returning.length === 0 ? "*" : q._returning.join(",");
9959
- const sql = `INSERT${q._ignoreDuplicate ? " OR IGNORE" : ""} INTO "${q._table}"${getInsertColumns(q._columns)}${rows.sql} RETURNING ${returing}`;
9993
+ const sql = `INSERT${q._ignoreDuplicate ? " OR IGNORE" : ""} INTO ${renderTable(q._table)}${getInsertColumns(q._columns)}${rows.sql} RETURNING ${returing}`;
9960
9994
  return [{
9961
9995
  sql,
9962
9996
  values: rows.values
@@ -9994,7 +10028,7 @@ function sqlite3ExecutorPrepare(args) {
9994
10028
  const where = getWhereStatement(q);
9995
10029
  const whereSQL = where.sql !== "" ? ` WHERE ${where.sql}` : "";
9996
10030
  const setSQL = ` SET ${q._sets.map((set) => `${renderColumn(set.column)}=?`)}`;
9997
- const sql = `UPDATE "${q._table}"${setSQL}${whereSQL}${getOrderBy(q._orderBy)}${getLimit(q._limitBy, q._offsetBy)} RETURNING ${returing}`;
10031
+ const sql = `UPDATE ${renderTable(q._table)}${setSQL}${whereSQL}${getOrderBy(q._orderBy)}${getLimit(q._limitBy, q._offsetBy)} RETURNING ${returing}`;
9998
10032
  return [{
9999
10033
  sql,
10000
10034
  values: q._sets.map((set) => set.value).concat(where.values)
@@ -10159,7 +10193,7 @@ function getCreateTableColumns(definition) {
10159
10193
  function getCreateTableColumn(columnName, def, primaryKeyColumns) {
10160
10194
  const primaryKey = primaryKeyColumns.length === 1 && columnName === primaryKeyColumns[0] ? " PRIMARY KEY" : "";
10161
10195
  const notNull = `${def.allowNull == false ? " NOT NULL" : ""}`;
10162
- const defaultValue = `${def.defaultValue !== void 0 ? ` DEFAULT '${def.defaultValue}'` : ""}`;
10196
+ const defaultValue = def.defaultValue !== void 0 ? ` DEFAULT '${String(def.defaultValue).replace(/'/g, "''")}'` : "";
10163
10197
  const autoIncrement = `${def.autoIncrement !== void 0 && def.autoIncrement === true ? ` AUTOINCREMENT` : ""}`;
10164
10198
  switch (def.type) {
10165
10199
  case "datetime":
@@ -10204,8 +10238,21 @@ function getOrderBy(orderBy, wrapper = '"') {
10204
10238
  function getLimit(limit, offsetBy) {
10205
10239
  return `${limit !== void 0 ? ` LIMIT ${limit}` : ""}${offsetBy ? ` OFFSET ${offsetBy}` : ""}`;
10206
10240
  }
10241
+ var IDENT_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
10207
10242
  function renderColumn(column, wrapper = '"') {
10208
- return `${column.split(".").map((c) => `${wrapper}${c}${wrapper}`).join(".")}`;
10243
+ const parts = column.split(".");
10244
+ for (const p of parts) {
10245
+ if (!IDENT_RE.test(p)) {
10246
+ throw new Error(`invalid identifier: ${p}`);
10247
+ }
10248
+ }
10249
+ return parts.map((c) => `${wrapper}${c}${wrapper}`).join(".");
10250
+ }
10251
+ function renderTable(name, wrapper = '"') {
10252
+ if (!IDENT_RE.test(name)) {
10253
+ throw new Error(`invalid table name: ${name}`);
10254
+ }
10255
+ return `${wrapper}${name}${wrapper}`;
10209
10256
  }
10210
10257
  function mergePrepareArgs(to, merge, concatOperator = " AND ") {
10211
10258
  return (merge instanceof Array ? merge : [merge]).reduce((current, value) => {
@@ -10236,7 +10283,9 @@ var DATABASE_CONFIG_SCHEMA = {
10236
10283
  properties: {
10237
10284
  prepare: "function",
10238
10285
  query: "function",
10239
- disconnect: "function"
10286
+ disconnect: "function",
10287
+ connect: "function",
10288
+ target: "any"
10240
10289
  }
10241
10290
  },
10242
10291
  logger: {
@@ -10247,11 +10296,21 @@ var DATABASE_CONFIG_SCHEMA = {
10247
10296
  error: "function?"
10248
10297
  }
10249
10298
  },
10299
+ pool: {
10300
+ type: "object?",
10301
+ properties: {
10302
+ min: "number?",
10303
+ max: "number?",
10304
+ idleTimeoutMillis: "number?",
10305
+ connectionTimeoutMillis: "number?",
10306
+ maxLifetimeSeconds: "number?"
10307
+ }
10308
+ },
10250
10309
  storage: "string?",
10251
10310
  connectionString: "string?",
10252
10311
  dialect: {
10253
10312
  type: "enum?",
10254
- enumValues: ["node:sqlite", "sqlite3-cli", "sqlite3", "pg"]
10313
+ enumValues: ["node:sqlite", "pg", "pg-pool"]
10255
10314
  }
10256
10315
  }
10257
10316
  };
@@ -10346,143 +10405,188 @@ function pgTransformOutput(type, value) {
10346
10405
  }
10347
10406
  }
10348
10407
 
10349
- // node_modules/@miqro/query/build/executors/sqlite3/lib.js
10350
- var SQLITE_CONFIG_SCHEMA = {
10408
+ // node_modules/@miqro/query/build/executors/pg/lib.js
10409
+ var PG_DATABASE_CONFIG_SCHEMA = {
10351
10410
  type: "object",
10352
10411
  mode: "remove_extra",
10353
10412
  properties: {
10354
- storage: "string"
10413
+ connectionString: "string",
10414
+ pool: {
10415
+ type: "object?",
10416
+ properties: {
10417
+ min: "number?",
10418
+ max: "number?",
10419
+ idleTimeoutMillis: "number?",
10420
+ connectionTimeoutMillis: "number?",
10421
+ maxLifetimeSeconds: "number?"
10422
+ }
10423
+ }
10355
10424
  }
10356
10425
  };
10357
- async function sqlite3Executor(config) {
10358
- const databaseOptions = parser2.parse(config, SQLITE_CONFIG_SCHEMA);
10359
- if (!databaseOptions) {
10360
- throw new Error("config not valid");
10361
- }
10362
- const sqlite3 = await import("sqlite3");
10363
- const driver = new sqlite3.default.Database(databaseOptions.storage);
10364
- return {
10365
- disconnect: async function sqlite3ExecutorDisconnect() {
10366
- await driver.close();
10367
- },
10368
- prepare: sqlite3ExecutorPrepare,
10369
- transformInput: sqliteTransformInput,
10370
- transformOutput: sqliteTransformOutput,
10371
- query: async function sqlite3Executor2(sql, values) {
10372
- return new Promise((resolve24, reject) => {
10373
- const st = driver.prepare(sql, values, function(error2) {
10374
- if (error2) {
10375
- reject(error2);
10376
- } else {
10377
- st.all(function(error3, rows) {
10378
- if (error3) {
10379
- reject(error3);
10380
- } else {
10381
- st.finalize((error4) => {
10382
- if (error4) {
10383
- reject(error4);
10384
- } else {
10385
- resolve24(rows);
10386
- }
10387
- });
10388
- }
10389
- });
10390
- }
10426
+ function postgresExecutorPrepare(args) {
10427
+ switch (args._type) {
10428
+ case "create-table": {
10429
+ const q = args;
10430
+ const sql = `CREATE TABLE${q._ignoreDuplicate ? " IF NOT EXISTS" : ""} ${renderTable(q._table)}${getCreateTableColumns2(q._definition)}`;
10431
+ return sql;
10432
+ }
10433
+ case "insert": {
10434
+ const q = args;
10435
+ const rows = getInsertValues(q._columns, q._values);
10436
+ const returing = q._returning.length === 0 ? "*" : q._returning.join(",");
10437
+ const sql = `INSERT INTO ${renderTable(q._table)}${getInsertColumns(q._columns)}${rows.sql} ${q._ignoreDuplicate ? "ON CONFLICT DO NOTHING " : ""}RETURNING ${returing}`;
10438
+ return {
10439
+ sql,
10440
+ values: rows.values
10441
+ };
10442
+ }
10443
+ case "alter-table": {
10444
+ const q = args;
10445
+ let alters = [];
10446
+ if (q._renameTable) {
10447
+ alters.push({
10448
+ sql: `ALTER TABLE ${renderTable(q._table)} RENAME TO "?"`,
10449
+ values: [q._renameTable]
10391
10450
  });
10392
- });
10451
+ }
10452
+ for (let l of q._changes) {
10453
+ switch (l._action) {
10454
+ case "add":
10455
+ if (!l._definition) {
10456
+ throw new Error("unsupported alter action add without definition");
10457
+ }
10458
+ alters.push({
10459
+ sql: `ALTER TABLE ${renderTable(q._table)} ADD COLUMN ${getCreateTableColumn2(l._column, l._definition, [])}`
10460
+ });
10461
+ break;
10462
+ case "drop":
10463
+ alters.push({
10464
+ sql: `ALTER TABLE ${renderTable(q._table)} DROP COLUMN "${l._column}"`
10465
+ });
10466
+ break;
10467
+ case "rename":
10468
+ alters.push({
10469
+ sql: `ALTER TABLE ${renderTable(q._table)} RENAME COLUMN "${l._column}" TO "${l._newName}"`
10470
+ });
10471
+ break;
10472
+ default:
10473
+ throw new Error("unsupported alter action");
10474
+ }
10475
+ }
10476
+ return alters;
10477
+ }
10478
+ default:
10479
+ return sqlite3ExecutorPrepare(args);
10480
+ }
10481
+ }
10482
+ function pgQuery(client) {
10483
+ return async function postgresExecutor2(sql, values) {
10484
+ try {
10485
+ const result = await client.query(tokens2Postgres(sql, values), values);
10486
+ return result.rows;
10487
+ } catch (e) {
10488
+ throw e;
10393
10489
  }
10394
10490
  };
10395
10491
  }
10396
-
10397
- // node_modules/@miqro/query/build/executors/pg/lib.js
10398
- var PG_DATABASE_CONFIG_SCHEMA = {
10399
- type: "object",
10400
- mode: "remove_extra",
10401
- properties: {
10402
- connectionString: "string"
10403
- }
10404
- };
10405
- async function postgresExecutor(config) {
10492
+ async function postgresExecutor(config, usePool) {
10493
+ const target = new EventTarget();
10494
+ const usingPool = config.pool && usePool === void 0 || usePool === true;
10406
10495
  const databaseOptions = parser2.parse(config, PG_DATABASE_CONFIG_SCHEMA);
10407
10496
  if (!databaseOptions) {
10408
10497
  throw new Error("bad options");
10409
10498
  }
10410
- const pg = await import("pg");
10411
- const driver = new pg.default.Client({
10412
- connectionString: databaseOptions.connectionString
10413
- // "postgresql://postgres:password@localhost:5432/db"
10414
- });
10415
- await driver.connect();
10499
+ const { Pool, Client } = await import("pg");
10500
+ let driver;
10501
+ if (usingPool) {
10502
+ driver = new Pool({
10503
+ connectionString: databaseOptions.connectionString,
10504
+ // "postgresql://postgres:password@localhost:5432/db",
10505
+ max: databaseOptions.pool?.max,
10506
+ min: databaseOptions.pool?.min,
10507
+ idleTimeoutMillis: databaseOptions.pool?.idleTimeoutMillis,
10508
+ connectionTimeoutMillis: databaseOptions.pool?.connectionTimeoutMillis,
10509
+ maxLifetimeSeconds: databaseOptions.pool?.maxLifetimeSeconds
10510
+ });
10511
+ driver.on("error", (err) => {
10512
+ const errorEvent = new CustomEvent("error", {
10513
+ detail: err
10514
+ });
10515
+ target.dispatchEvent(errorEvent);
10516
+ });
10517
+ } else {
10518
+ driver = new Client({
10519
+ connectionString: databaseOptions.connectionString
10520
+ // "postgresql://postgres:password@localhost:5432/db",
10521
+ });
10522
+ driver.on("error", (err) => {
10523
+ const errorEvent = new CustomEvent("error", {
10524
+ detail: err
10525
+ });
10526
+ target.dispatchEvent(errorEvent);
10527
+ });
10528
+ }
10416
10529
  return {
10417
- disconnect: async function postgresExecutorDisconnect() {
10418
- await driver.end();
10419
- },
10420
- transformInput: pgTransformInput,
10421
- transformOutput: pgTransformOutput,
10422
- prepare: function postgresExecutorPrepare(args) {
10423
- switch (args._type) {
10424
- case "create-table": {
10425
- const q = args;
10426
- const sql = `CREATE TABLE${q._ignoreDuplicate ? " IF NOT EXISTS" : ""} "${q._table}"${getCreateTableColumns2(q._definition)}`;
10427
- return sql;
10428
- }
10429
- case "insert": {
10430
- const q = args;
10431
- const rows = getInsertValues(q._columns, q._values);
10432
- const returing = q._returning.length === 0 ? "*" : q._returning.join(",");
10433
- const sql = `INSERT INTO "${q._table}"${getInsertColumns(q._columns)}${rows.sql} ${q._ignoreDuplicate ? "ON CONFLICT DO NOTHING " : ""}RETURNING ${returing}`;
10434
- return {
10435
- sql,
10436
- values: rows.values
10437
- };
10438
- }
10439
- case "alter-table": {
10440
- const q = args;
10441
- let alters = [];
10442
- if (q._renameTable) {
10443
- alters.push({
10444
- sql: `ALTER TABLE "${q._table}" RENAME TO "?"`,
10445
- values: [q._renameTable]
10446
- });
10447
- }
10448
- for (let l of q._changes) {
10449
- switch (l._action) {
10450
- case "add":
10451
- if (!l._definition) {
10452
- throw new Error("unsupported alter action add without definition");
10453
- }
10454
- alters.push({
10455
- sql: `ALTER TABLE "${q._table}" ADD COLUMN ${getCreateTableColumn2(l._column, l._definition, [])}`
10456
- });
10457
- break;
10458
- case "drop":
10459
- alters.push({
10460
- sql: `ALTER TABLE "${q._table}" DROP COLUMN "${l._column}"`
10461
- });
10462
- break;
10463
- case "rename":
10464
- alters.push({
10465
- sql: `ALTER TABLE "${q._table}" RENAME COLUMN "${l._column}" TO "${l._newName}"`
10466
- });
10467
- break;
10468
- default:
10469
- throw new Error("unsupported alter action");
10470
- }
10530
+ target,
10531
+ transaction: async (cb) => {
10532
+ const client = usingPool ? await driver.connect() : await (async () => {
10533
+ const newClient = new Client({
10534
+ connectionString: databaseOptions.connectionString
10535
+ // "postgresql://postgres:password@localhost:5432/db",
10536
+ });
10537
+ newClient.on("error", (err) => {
10538
+ const errorEvent = new CustomEvent("error", {
10539
+ detail: err
10540
+ });
10541
+ target.dispatchEvent(errorEvent);
10542
+ });
10543
+ await newClient.connect();
10544
+ return newClient;
10545
+ })();
10546
+ const newExecutor = {
10547
+ target: new EventTarget(),
10548
+ transaction: async (cb2) => cb2(newExecutor),
10549
+ connect: async () => {
10550
+ },
10551
+ disconnect: async () => {
10552
+ if (usingPool) {
10553
+ await client.release();
10554
+ } else {
10555
+ await client.end();
10471
10556
  }
10472
- return alters;
10473
- }
10474
- default:
10475
- return sqlite3ExecutorPrepare(args);
10476
- }
10477
- },
10478
- query: async function postgresExecutor2(sql, values) {
10557
+ },
10558
+ transformInput: pgTransformInput,
10559
+ transformOutput: pgTransformOutput,
10560
+ prepare: postgresExecutorPrepare,
10561
+ query: pgQuery(client)
10562
+ };
10479
10563
  try {
10480
- const result = await driver.query(tokens2Postgres(sql, values), values);
10481
- return result.rows;
10564
+ await newExecutor.query("BEGIN;");
10565
+ const ret = await cb(newExecutor);
10566
+ await newExecutor.query("COMMIT;");
10567
+ return ret;
10482
10568
  } catch (e) {
10569
+ await newExecutor.query("ROLLBACK;");
10483
10570
  throw e;
10571
+ } finally {
10572
+ newExecutor.disconnect();
10484
10573
  }
10485
- }
10574
+ },
10575
+ connect: async () => {
10576
+ if (usingPool) {
10577
+ const client = await driver.connect();
10578
+ await client.release();
10579
+ } else {
10580
+ await driver.connect();
10581
+ }
10582
+ },
10583
+ disconnect: async function postgresExecutorDisconnect() {
10584
+ await driver.end();
10585
+ },
10586
+ transformInput: pgTransformInput,
10587
+ transformOutput: pgTransformOutput,
10588
+ prepare: postgresExecutorPrepare,
10589
+ query: pgQuery(driver)
10486
10590
  };
10487
10591
  }
10488
10592
  function getCreateTableColumns2(definition) {
@@ -10498,7 +10602,7 @@ function getCreateTableColumns2(definition) {
10498
10602
  function getCreateTableColumn2(columnName, def, primaryKeyColumns) {
10499
10603
  const primaryKey = primaryKeyColumns.length === 1 && columnName === primaryKeyColumns[0] ? " PRIMARY KEY" : "";
10500
10604
  const notNull = `${def.allowNull == false ? " NOT NULL" : ""}`;
10501
- const defaultValue = `${def.defaultValue !== void 0 ? ` DEFAULT '${def.defaultValue}'` : ""}`;
10605
+ const defaultValue = def.defaultValue !== void 0 ? ` DEFAULT '${String(def.defaultValue).replace(/'/g, "''")}'` : "";
10502
10606
  if (def.autoIncrement) {
10503
10607
  return `"${columnName}" BIGSERIAL${primaryKey}`;
10504
10608
  }
@@ -10583,10 +10687,12 @@ async function runStatements(db, stmts, logger) {
10583
10687
 
10584
10688
  // node_modules/@miqro/query/build/query/create-database.js
10585
10689
  var CreateDatabase = class _CreateDatabase {
10690
+ db;
10691
+ _dbName;
10692
+ _type = "create-database";
10586
10693
  constructor(db, _dbName) {
10587
10694
  this.db = db;
10588
10695
  this._dbName = _dbName;
10589
- this._type = "create-database";
10590
10696
  }
10591
10697
  async yield(logger) {
10592
10698
  return runStatements(this.db, this.db.getExecutor().prepare(this), logger);
@@ -10602,12 +10708,15 @@ var CreateDatabase = class _CreateDatabase {
10602
10708
 
10603
10709
  // node_modules/@miqro/query/build/query/create-table.js
10604
10710
  var CreateTable = class _CreateTable {
10711
+ db;
10712
+ _table;
10713
+ _definition;
10714
+ _ignoreDuplicate = false;
10715
+ _type = "create-table";
10605
10716
  constructor(db, _table, _definition = {}) {
10606
10717
  this.db = db;
10607
10718
  this._table = _table;
10608
10719
  this._definition = _definition;
10609
- this._ignoreDuplicate = false;
10610
- this._type = "create-table";
10611
10720
  this._definition = assertNotUndefined2(parser2.parse(_definition, TableSchemaSchema));
10612
10721
  }
10613
10722
  column(column, definition) {
@@ -10642,11 +10751,13 @@ var CreateTable = class _CreateTable {
10642
10751
 
10643
10752
  // node_modules/@miqro/query/build/query/drop-table.js
10644
10753
  var DropTable = class _DropTable {
10754
+ db;
10755
+ _table;
10756
+ _type = "drop-table";
10757
+ _ignoreDuplicate = false;
10645
10758
  constructor(db, _table) {
10646
10759
  this.db = db;
10647
10760
  this._table = _table;
10648
- this._type = "drop-table";
10649
- this._ignoreDuplicate = false;
10650
10761
  }
10651
10762
  prepare() {
10652
10763
  return getStatements(this.db.getExecutor().prepare(this));
@@ -10667,12 +10778,16 @@ var DropTable = class _DropTable {
10667
10778
 
10668
10779
  // node_modules/@miqro/query/build/query/alter-table.js
10669
10780
  var AlterTable = class _AlterTable {
10781
+ db;
10782
+ _table;
10783
+ _inTransaction;
10784
+ _type = "alter-table";
10785
+ _renameTable;
10786
+ _changes = [];
10670
10787
  constructor(db, _table, _inTransaction = false) {
10671
10788
  this.db = db;
10672
10789
  this._table = _table;
10673
10790
  this._inTransaction = _inTransaction;
10674
- this._type = "alter-table";
10675
- this._changes = [];
10676
10791
  }
10677
10792
  rename(name) {
10678
10793
  this._renameTable = name;
@@ -10717,14 +10832,17 @@ var AlterTable = class _AlterTable {
10717
10832
 
10718
10833
  // node_modules/@miqro/query/build/query/insert.js
10719
10834
  var Insert = class _Insert {
10835
+ db;
10836
+ _table;
10837
+ _type = "insert";
10838
+ _columns = [];
10839
+ _returning = [];
10840
+ _values = [];
10841
+ _ignoreDuplicate = false;
10842
+ _schema;
10720
10843
  constructor(db, _table, schema) {
10721
10844
  this.db = db;
10722
10845
  this._table = _table;
10723
- this._type = "insert";
10724
- this._columns = [];
10725
- this._returning = [];
10726
- this._values = [];
10727
- this._ignoreDuplicate = false;
10728
10846
  this._schema = schema;
10729
10847
  }
10730
10848
  value(value) {
@@ -10776,10 +10894,10 @@ var Insert = class _Insert {
10776
10894
 
10777
10895
  // node_modules/@miqro/query/build/executors/where.js
10778
10896
  var Where = class _Where {
10779
- constructor() {
10780
- this._orderBy = [];
10781
- this._filters = [];
10782
- }
10897
+ _orderBy = [];
10898
+ _limitBy;
10899
+ _offsetBy;
10900
+ _filters = [];
10783
10901
  clone() {
10784
10902
  const ret = new _Where();
10785
10903
  ret._filters = structuredClone(this._filters);
@@ -10793,10 +10911,16 @@ var Where = class _Where {
10793
10911
  return this;
10794
10912
  }
10795
10913
  limit(limit) {
10914
+ if (typeof limit !== "number" || !Number.isInteger(limit) || limit < 0) {
10915
+ throw new Error("limit must be a non-negative integer");
10916
+ }
10796
10917
  this._limitBy = limit;
10797
10918
  return this;
10798
10919
  }
10799
10920
  offset(offset) {
10921
+ if (typeof offset !== "number" || !Number.isInteger(offset) || offset < 0) {
10922
+ throw new Error("offset must be a non-negative integer");
10923
+ }
10800
10924
  this._offsetBy = offset;
10801
10925
  return this;
10802
10926
  }
@@ -11075,15 +11199,19 @@ async function yieldWithInclude(db, schema, assocMap, include, filters, orderBy,
11075
11199
 
11076
11200
  // node_modules/@miqro/query/build/query/select.js
11077
11201
  var Select = class _Select extends Where {
11202
+ db;
11203
+ _type = "select";
11204
+ _columns = [];
11205
+ _selectFrom = [];
11206
+ _groupBy = [];
11207
+ _joins = [];
11208
+ _orderBy = [];
11209
+ _schema;
11210
+ _assocMap;
11211
+ _include;
11078
11212
  constructor(db, schema, associations) {
11079
11213
  super();
11080
11214
  this.db = db;
11081
- this._type = "select";
11082
- this._columns = [];
11083
- this._selectFrom = [];
11084
- this._groupBy = [];
11085
- this._joins = [];
11086
- this._orderBy = [];
11087
11215
  this._schema = schema;
11088
11216
  if (associations) {
11089
11217
  this._assocMap = new Map(Object.entries(associations));
@@ -11172,13 +11300,14 @@ var Select = class _Select extends Where {
11172
11300
 
11173
11301
  // node_modules/@miqro/query/build/query/count.js
11174
11302
  var Count = class _Count extends Where {
11303
+ db;
11304
+ _type = "count";
11305
+ _selectFrom = [];
11306
+ _groupBy = [];
11307
+ _joins = [];
11175
11308
  constructor(db) {
11176
11309
  super();
11177
11310
  this.db = db;
11178
- this._type = "count";
11179
- this._selectFrom = [];
11180
- this._groupBy = [];
11181
- this._joins = [];
11182
11311
  }
11183
11312
  clone() {
11184
11313
  const ret = new _Count(this.db);
@@ -11231,13 +11360,16 @@ async function parseCountResult(rows) {
11231
11360
 
11232
11361
  // node_modules/@miqro/query/build/query/update.js
11233
11362
  var Update = class _Update extends Where {
11363
+ db;
11364
+ _table;
11365
+ _type = "update";
11366
+ _sets = [];
11367
+ _returning = [];
11368
+ _schema;
11234
11369
  constructor(db, _table, schema) {
11235
11370
  super();
11236
11371
  this.db = db;
11237
11372
  this._table = _table;
11238
- this._type = "update";
11239
- this._sets = [];
11240
- this._returning = [];
11241
11373
  this._schema = schema;
11242
11374
  }
11243
11375
  prepare() {
@@ -11275,12 +11407,15 @@ var Update = class _Update extends Where {
11275
11407
 
11276
11408
  // node_modules/@miqro/query/build/query/delete.js
11277
11409
  var Delete = class _Delete extends Where {
11410
+ db;
11411
+ _table;
11412
+ _type = "delete";
11413
+ _returning = [];
11414
+ _schema;
11278
11415
  constructor(db, _table, schema) {
11279
11416
  super();
11280
11417
  this.db = db;
11281
11418
  this._table = _table;
11282
- this._type = "delete";
11283
- this._returning = [];
11284
11419
  this._schema = schema;
11285
11420
  }
11286
11421
  prepare() {
@@ -11309,11 +11444,13 @@ var Delete = class _Delete extends Where {
11309
11444
 
11310
11445
  // node_modules/@miqro/query/build/query/drop-database.js
11311
11446
  var DropDatabase = class _DropDatabase {
11447
+ db;
11448
+ _dbName;
11449
+ _type = "drop-database";
11450
+ _ignoreDuplicate = false;
11312
11451
  constructor(db, _dbName) {
11313
11452
  this.db = db;
11314
11453
  this._dbName = _dbName;
11315
- this._type = "drop-database";
11316
- this._ignoreDuplicate = false;
11317
11454
  }
11318
11455
  prepare() {
11319
11456
  return getStatements(this.db.getExecutor().prepare(this));
@@ -11333,72 +11470,119 @@ var DropDatabase = class _DropDatabase {
11333
11470
  };
11334
11471
 
11335
11472
  // node_modules/@miqro/query/build/executors/sqlite-native/lib.js
11336
- var SQLITE_CONFIG_SCHEMA2 = {
11473
+ var SQLITE_CONFIG_SCHEMA = {
11337
11474
  type: "object",
11338
11475
  mode: "remove_extra",
11339
11476
  properties: {
11340
11477
  storage: "string"
11341
11478
  }
11342
11479
  };
11480
+ function nativeSqliteQuery(driver) {
11481
+ return async function sqlite3Executor(sql, values) {
11482
+ return new Promise((resolve24, reject) => {
11483
+ try {
11484
+ if (values) {
11485
+ for (let i = 0; i < values.length; i++) {
11486
+ switch (typeof values[i]) {
11487
+ case "object":
11488
+ if (values[i] instanceof Date) {
11489
+ values[i] = values[i].toString();
11490
+ }
11491
+ break;
11492
+ case "boolean":
11493
+ values[i] = values[i] ? 1 : 0;
11494
+ break;
11495
+ }
11496
+ }
11497
+ }
11498
+ const stmt = driver.prepare(sql);
11499
+ stmt.setReadBigInts(true);
11500
+ const ret = values && values.length > 0 ? stmt.all(...values) : stmt.all();
11501
+ resolve24(ret.map((row) => {
11502
+ const out = {};
11503
+ for (const key of Object.keys(row)) {
11504
+ const v = row[key];
11505
+ out[key] = typeof v === "bigint" && v >= Number.MIN_SAFE_INTEGER && v <= Number.MAX_SAFE_INTEGER ? Number(v) : typeof v === "number" ? Number(v) : v;
11506
+ }
11507
+ return out;
11508
+ }));
11509
+ } catch (e) {
11510
+ reject(e);
11511
+ }
11512
+ });
11513
+ };
11514
+ }
11343
11515
  async function nativeSqlite(config) {
11344
- const databaseOptions = parser2.parse(config, SQLITE_CONFIG_SCHEMA2);
11516
+ const databaseOptions = parser2.parse(config, SQLITE_CONFIG_SCHEMA);
11517
+ const target = new EventTarget();
11345
11518
  if (!databaseOptions) {
11346
11519
  throw new Error("config not valid");
11347
11520
  }
11348
11521
  const sqliteModule = await import("node:sqlite");
11349
11522
  const driver = new sqliteModule.DatabaseSync(databaseOptions.storage);
11350
11523
  return {
11524
+ target,
11525
+ transaction: async (cb) => {
11526
+ const client = new sqliteModule.DatabaseSync(databaseOptions.storage);
11527
+ const newExecutor = {
11528
+ target: new EventTarget(),
11529
+ transaction: async (cb2) => cb2(newExecutor),
11530
+ connect: async () => {
11531
+ },
11532
+ disconnect: async () => {
11533
+ if (client.isOpen)
11534
+ return client.close();
11535
+ },
11536
+ prepare: sqlite3ExecutorPrepare,
11537
+ transformInput: sqliteTransformInput,
11538
+ transformOutput: sqliteTransformOutput,
11539
+ query: nativeSqliteQuery(client)
11540
+ };
11541
+ let begin = false;
11542
+ try {
11543
+ await newExecutor.query("BEGIN;");
11544
+ begin = true;
11545
+ const ret = await cb(newExecutor);
11546
+ await newExecutor.query("COMMIT;");
11547
+ return ret;
11548
+ } catch (e) {
11549
+ if (begin) {
11550
+ await newExecutor.query("ROLLBACK;");
11551
+ }
11552
+ throw e;
11553
+ } finally {
11554
+ newExecutor.disconnect();
11555
+ }
11556
+ },
11557
+ connect: async () => {
11558
+ },
11351
11559
  // we just use the sqlite3Executor prepare function
11352
11560
  prepare: sqlite3ExecutorPrepare,
11353
11561
  transformInput: sqliteTransformInput,
11354
11562
  transformOutput: sqliteTransformOutput,
11355
11563
  disconnect: async function sqlite3ExecutorDisconnect() {
11356
- return driver.close();
11564
+ if (driver.isOpen)
11565
+ return driver.close();
11357
11566
  },
11358
- query: async function sqlite3Executor2(sql, values) {
11359
- return new Promise((resolve24, reject) => {
11360
- try {
11361
- if (values) {
11362
- for (let i = 0; i < values.length; i++) {
11363
- switch (typeof values[i]) {
11364
- case "object":
11365
- if (values[i] instanceof Date) {
11366
- values[i] = values[i].toString();
11367
- }
11368
- break;
11369
- case "boolean":
11370
- values[i] = values[i] ? 1 : 0;
11371
- break;
11372
- }
11373
- }
11374
- }
11375
- const stmt = driver.prepare(sql);
11376
- stmt.setReadBigInts(true);
11377
- const ret = values && values.length > 0 ? stmt.all(...values) : stmt.all();
11378
- resolve24(ret.map((row) => {
11379
- const out = {};
11380
- for (const key of Object.keys(row)) {
11381
- const v = row[key];
11382
- out[key] = typeof v === "bigint" && v >= Number.MIN_SAFE_INTEGER && v <= Number.MAX_SAFE_INTEGER ? Number(v) : typeof v === "number" ? Number(v) : v;
11383
- }
11384
- return out;
11385
- }));
11386
- } catch (e) {
11387
- reject(e);
11388
- }
11389
- });
11390
- }
11567
+ query: nativeSqliteQuery(driver)
11391
11568
  };
11392
11569
  }
11393
11570
 
11394
11571
  // node_modules/@miqro/query/build/db.js
11395
- var Database = class {
11572
+ var Database = class _Database extends EventTarget {
11573
+ config;
11574
+ status = "disconnected";
11575
+ executor = null;
11576
+ _errorListener;
11396
11577
  constructor(config) {
11578
+ super();
11397
11579
  this.config = config;
11398
- this.status = "disconnected";
11399
- this.executor = null;
11400
11580
  parser2.parse(config, DATABASE_CONFIG_SCHEMA, "no_extra");
11401
11581
  this.executor = null;
11582
+ this._errorListener = (event) => {
11583
+ this.config.logger?.error(event.detail);
11584
+ this.dispatchEvent(event);
11585
+ };
11402
11586
  }
11403
11587
  async connect() {
11404
11588
  if (this.status !== "disconnected") {
@@ -11410,6 +11594,8 @@ var Database = class {
11410
11594
  this.status = "connecting";
11411
11595
  try {
11412
11596
  this.executor = await getExecutor(this.config);
11597
+ this.executor.target.addEventListener("error", this._errorListener);
11598
+ await this.executor.connect();
11413
11599
  this.status = "connected";
11414
11600
  } catch (e) {
11415
11601
  this.status = "error";
@@ -11423,6 +11609,9 @@ var Database = class {
11423
11609
  this.status = "disconnecting";
11424
11610
  try {
11425
11611
  await this.getExecutor().disconnect();
11612
+ if (this.executor) {
11613
+ this.executor.target.removeEventListener("error", this._errorListener);
11614
+ }
11426
11615
  this.executor = null;
11427
11616
  this.status = "disconnected";
11428
11617
  } catch (e) {
@@ -11448,15 +11637,15 @@ var Database = class {
11448
11637
  }
11449
11638
  }
11450
11639
  async transaction(transactionCB, logger) {
11451
- try {
11452
- await this.query("BEGIN", void 0, logger);
11453
- const ret = await transactionCB(this, logger);
11454
- await this.query("COMMIT", void 0, logger);
11455
- return ret;
11456
- } catch (e) {
11457
- await this.query("ROLLBACK", void 0, logger);
11458
- throw e;
11459
- }
11640
+ const ret = await this.executor?.transaction(async (transactionExecutor) => {
11641
+ const newDB = new _Database({
11642
+ executor: transactionExecutor
11643
+ });
11644
+ await newDB.connect();
11645
+ const ret2 = await transactionCB(newDB, logger);
11646
+ return ret2;
11647
+ });
11648
+ return ret;
11460
11649
  }
11461
11650
  createDatabase(dbName) {
11462
11651
  return new CreateDatabase(this, dbName);
@@ -11494,12 +11683,12 @@ var Database = class {
11494
11683
  };
11495
11684
  async function getExecutor(config) {
11496
11685
  switch (config.dialect) {
11686
+ case "pg-pool":
11687
+ return await postgresExecutor(config, true);
11497
11688
  case "node:sqlite":
11498
11689
  return await nativeSqlite(config);
11499
11690
  case "pg":
11500
11691
  return await postgresExecutor(config);
11501
- case "sqlite3":
11502
- return await sqlite3Executor(config);
11503
11692
  default:
11504
11693
  if (config.executor) {
11505
11694
  const e = config.executor;
@@ -12304,9 +12493,11 @@ var DBManager = class {
12304
12493
  this.options?.logger?.debug("setting up db connection [%s]", config.name);
12305
12494
  this.options?.logger?.trace("creating db connection [%s]", config.name);
12306
12495
  const db = new Database({
12496
+ executor: config.executor,
12307
12497
  dialect: config.dialect ? config.dialect : "node:sqlite",
12308
12498
  storage: config.storage ? config.storage : "./db.sqlite3",
12309
12499
  connectionString: config.url,
12500
+ pool: config.pool,
12310
12501
  logger: this.options?.loggerProvider?.getLogger(`${DB_IDENTIFIER}_${config.name}`)
12311
12502
  });
12312
12503
  this.options?.logger?.trace("connecting db connection [%s]", config.name);
@@ -14133,13 +14324,15 @@ var auth_default = {
14133
14324
  const queryToken = args.req.query[ADMIN_EDITOR_AUTH_QUERY];
14134
14325
  const cookieToken = args.req.cookies[ADMIN_EDITOR_AUTH_COOKIE];
14135
14326
  if (queryToken) {
14136
- if (typeof queryToken === "string" && (0, import_node_crypto5.timingSafeEqual)(Buffer.from(queryToken), Buffer.from(KEY))) {
14327
+ const queryBuf = Buffer.from(String(queryToken));
14328
+ const keyBuf = Buffer.from(KEY);
14329
+ if (typeof queryToken === "string" && queryBuf.length === keyBuf.length && (0, import_node_crypto5.timingSafeEqual)(queryBuf, keyBuf)) {
14137
14330
  args.res.setCookie(ADMIN_EDITOR_AUTH_COOKIE, KEY, {
14138
- expires: new Date(Date.now() + 1e3 * 60 * 60 * 24 * 31 * 12 * 500),
14331
+ expires: new Date(Date.now() + 1e3 * 60 * 60 * 24),
14139
14332
  httpOnly: true,
14140
- //secure: true,
14333
+ //secure: args.req.secure,
14334
+ sameSite: "strict",
14141
14335
  path: "/"
14142
- //sameSite: "strict"
14143
14336
  });
14144
14337
  args.req.searchParams.delete(ADMIN_EDITOR_AUTH_QUERY);
14145
14338
  const queryString = args.req.searchParams.toString();
@@ -14407,16 +14600,34 @@ function setupExitHandlers(app) {
14407
14600
  }
14408
14601
  process.exit(EXIT_CODES.ABNORMAL_UNCONTROLLED);
14409
14602
  });
14410
- process.on("SIGTERM", function() {
14603
+ process.on("SIGTERM", async function() {
14411
14604
  app.logger?.info("SIGTERM received");
14605
+ if (app.server) {
14606
+ await Promise.race([
14607
+ app.stop(),
14608
+ new Promise((r) => setTimeout(r, 5e3))
14609
+ ]);
14610
+ }
14412
14611
  process.exit(EXIT_CODES.ABNORMAL_UNCONTROLLED);
14413
14612
  });
14414
- process.on("SIGHUP", function() {
14613
+ process.on("SIGHUP", async function() {
14415
14614
  app.logger?.info("SIGHUP received");
14615
+ if (app.server) {
14616
+ await Promise.race([
14617
+ app.stop(),
14618
+ new Promise((r) => setTimeout(r, 5e3))
14619
+ ]);
14620
+ }
14416
14621
  process.exit(EXIT_CODES.ABNORMAL_UNCONTROLLED);
14417
14622
  });
14418
- process.on("SIGINT", function() {
14623
+ process.on("SIGINT", async function() {
14419
14624
  app.logger?.info("SIGINT received");
14625
+ if (app.server) {
14626
+ await Promise.race([
14627
+ app.stop(),
14628
+ new Promise((r) => setTimeout(r, 5e3))
14629
+ ]);
14630
+ }
14420
14631
  process.exit(EXIT_CODES.ABNORMAL_UNCONTROLLED);
14421
14632
  });
14422
14633
  }
@@ -17706,7 +17917,12 @@ var Miqro = class _Miqro {
17706
17917
  if (this.options?.httpRedirect) {
17707
17918
  this.httpsRedirectServer = new App();
17708
17919
  this.httpsRedirectServer.use(async (req, res) => {
17709
- const hostname = req.headers.host.split(":").length > 1 ? req.headers.host.split(":")[0] : req.headers.host;
17920
+ const hostname = req.headers.host?.split(":")[0] ?? "";
17921
+ const allowed2 = this.options?.allowedRedirectHosts;
17922
+ if (allowed2 && !allowed2.includes(hostname)) {
17923
+ res.writeHead(400).end("Invalid Host header");
17924
+ return;
17925
+ }
17710
17926
  return await res.redirect("https://" + hostname + ":" + this.options.port + req.url);
17711
17927
  });
17712
17928
  }
package/editor/auth.ts CHANGED
@@ -28,14 +28,15 @@ export default {
28
28
  //console.log("\n\nqueryToken[%s] cookieToken[%s] KEY[%s]\n\n", queryToken, cookieToken, KEY);
29
29
 
30
30
  if (queryToken) {
31
- if (typeof queryToken === "string" && timingSafeEqual(Buffer.from(queryToken), Buffer.from(KEY))) {
31
+ const queryBuf = Buffer.from(String(queryToken));
32
+ const keyBuf = Buffer.from(KEY);
33
+ if (typeof queryToken === "string" && queryBuf.length === keyBuf.length && timingSafeEqual(queryBuf, keyBuf)) {
32
34
  args.res.setCookie(ADMIN_EDITOR_AUTH_COOKIE, KEY, {
33
- expires: new Date(Date.now() + 1000 * 60 * 60 * 24 * 31 * 12 * 500),
35
+ expires: new Date(Date.now() + 1000 * 60 * 60 * 24),
34
36
  httpOnly: true,
35
-
36
- //secure: true,
37
+ //secure: args.req.secure,
38
+ sameSite: "strict",
37
39
  path: "/",
38
- //sameSite: "strict"
39
40
  });
40
41
  args.req.searchParams.delete(ADMIN_EDITOR_AUTH_QUERY);
41
42
  const queryString = args.req.searchParams.toString();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "miqro",
3
- "version": "7.3.3",
3
+ "version": "7.3.5",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "build/esm/src/lib.js",
@@ -41,12 +41,12 @@
41
41
  },
42
42
  "dependencies": {
43
43
  "postject": "1.0.0-alpha.6",
44
- "@miqro/core": "^5.1.1",
44
+ "@miqro/core": "^5.1.2",
45
45
  "@miqro/jsx": "^1.0.2",
46
46
  "@miqro/jsx-dom": "^1.0.6",
47
47
  "@miqro/jsx-node": "^1.0.9",
48
48
  "@miqro/parser": "^2.0.6",
49
- "@miqro/query": "^0.0.8",
49
+ "@miqro/query": "^0.1.0",
50
50
  "@miqro/runner": "^2.0.3",
51
51
  "@miqro/test": "^0.2.10",
52
52
  "@miqro/test-http": "^0.1.4",