miqro 7.2.9 → 7.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,6 +7,7 @@ interface MiqroJSON {
7
7
  browser?: string | boolean;
8
8
  logFile?: string | boolean;
9
9
  editor?: boolean;
10
+ etag?: boolean;
10
11
  https?: boolean;
11
12
  serverOptions?: ServerOptions;
12
13
  httpsRedirect?: number;
@@ -23,6 +24,7 @@ export interface Arguments {
23
24
  inflateFlat?: boolean;
24
25
  name?: string;
25
26
  noBuild?: boolean;
27
+ etag?: boolean;
26
28
  noMinify?: boolean;
27
29
  browser?: string | boolean;
28
30
  logFile?: string | boolean;
@@ -16,6 +16,7 @@ const MiqroJSONSchema = {
16
16
  type: "object",
17
17
  properties: {
18
18
  name: "string?",
19
+ etag: "boolean?",
19
20
  services: "string[]?",
20
21
  noBuild: "boolean?",
21
22
  noMinify: "boolean?",
@@ -53,6 +54,7 @@ export function parseArguments() {
53
54
  const args = cluster.isPrimary ? process.argv.slice(2, process.argv.length) : process.argv.slice(3, process.argv.length);
54
55
  const flags = {
55
56
  inflateFlat: null,
57
+ etag: null,
56
58
  inflateOnlyAssets: null,
57
59
  inflateParallel: null,
58
60
  httpsRedirect: null,
@@ -182,6 +184,22 @@ export function parseArguments() {
182
184
  }
183
185
  flags.install = true;
184
186
  continue;
187
+ case "--disable-etag":
188
+ if (flags.etag !== null) {
189
+ console.error("bad arguments.");
190
+ console.error(usage);
191
+ process.exit(EXIT_CODES.BAD_ARGUMENTS);
192
+ }
193
+ flags.etag = false;
194
+ continue;
195
+ case "--enable-etag":
196
+ if (flags.etag !== null) {
197
+ console.error("bad arguments.");
198
+ console.error(usage);
199
+ process.exit(EXIT_CODES.BAD_ARGUMENTS);
200
+ }
201
+ flags.etag = true;
202
+ continue;
185
203
  case "--watch":
186
204
  if (flags.watch !== null) {
187
205
  console.error("bad arguments.");
@@ -542,6 +560,11 @@ export function parseArguments() {
542
560
  flags.https = miqroRC.https;
543
561
  }
544
562
  }
563
+ if (flags.etag === null) {
564
+ if (miqroRC.etag !== undefined) {
565
+ flags.etag = miqroRC.etag;
566
+ }
567
+ }
545
568
  if (flags.httpsRedirect === null) {
546
569
  if (miqroRC.httpsRedirect && flags.https) {
547
570
  /*console.log("reading key from " + String(miqroRC.serverOptions?.key));
@@ -692,6 +715,7 @@ export function parseArguments() {
692
715
  process.exit(EXIT_CODES.BAD_ARGUMENTS);
693
716
  }
694
717
  return {
718
+ etag: flags.etag !== null ? flags.etag : true,
695
719
  inflateFlat: flags.inflateFlat === null ? false : flags.inflateFlat,
696
720
  inflateOnlyAssets: flags.inflateOnlyAssets === null ? undefined : flags.inflateOnlyAssets,
697
721
  noMinify: flags.noMinify === null ? false : flags.noMinify,
@@ -1,3 +1,3 @@
1
1
  export declare const BIN_NAME = "miqro";
2
2
  export declare const usage = "usage: miqro [...FLAGS] --service app/\n\n==examples==\n\nmiqro --watch --service front/\nPORT=8181 miqro --service api/ --service front/\nmiqro --test --service front/\nmiqro --inflate --service front/\nmiqro --generate-doc --generate-doc-out API.md --service front/\nCLUSTER_COUNT=10 miqro-cluster --service api/";
3
- export declare const help = "\n==flags==\n\n-v, --version\n\toutputs the version number\n-h, --help\n\toutputs this page.\n--watch\n\tuse to auto reload the server when files change.\n--hot-reload\n\tenables the hot-reload functionality use with --watch.\n--test\n\trun the tests for a service.\n--migrate-up\n\tmigrations up.\n--migrate-down\n\tmigrations down.\n--inflate\n\tinflates the application into a directory using esbuild.\n--inflate-dir\n\tto set the output directory of the --inflate command. default value is inflated/.\n--editor\n\truns the application with a built-in editor.\n--generate-doc\n\tgenerates a documentation for the api endpoints of the service.\n--generate-doc-out\n\tthe output file for the generated documentation. default value is API.md.\n--generate-doc-type\n\tthe format of the generated documentation. it can be JSON or MD. default value is MD.\n--generate-doc-all\n\toutputs all the server routes in the documentation output.\n--compile\n\tinflates the application and tries to create a NODE SEA binary.\n--no-build\n\tdisables calling esbuild during imports in runtime. Notice that to use jsx you will need to run tsc or esbuild on your jsx files to transpile them to js.\n--no-minify\n\tdisables calling minifing min.js files.\n--inflate-only-assets\n\tinflates ONLY the application assets. must be used with --inflate.\n--inflate-flat\n\tinflates files into the inflate-dir directly.\n--inflate-sea\n\tinflates the application with sea compilation scripts.\n--install-tsconfig\n\tcreates a tsconfig.json configured to use with --install-types.\n--install-miqrojson\n\tcreates a default miqro.json file.\n--install\n\tcreates a node_modules folder from binary cache (only available in sea binary).\n--disable-miqrojson\n\tdisables the load of miqro.json file.\n--log-file\n\toverrides the default log file from LOG_FILE.\n--browser\n\toverrides the default browser from BROWSER.\n--config\n\toverrides the default miqro.json path.\n--port\n\toverrides the default port from PORT.\n--name\n\toverrides the default name of the server.\n--https\n\tserves the server in https instead of http\n--https-key\n\tpoint to a server.key file for https.\n--https-cert\n\tpoint to a server.cert file for https.\n--https-redirect\n\tserves an aditional http server that redirects to https. it needs a port number.\n--inflate-parallel\n\tsets the max parallel esbuild instances. defaults to 1.\n\n==environment variables==\n\nPORT\n\toverride the default 8080 port.\nBROWSER\n\toverride the default browser. change to none to disable.\".\nLOG_FILE\n\toverride the default ./server.log file\nDB\n\tenable the server.db features\nDB_STORAGE\n\toverride the default local db location ./db.sqlite3\nDB_DIALECT\n\toverride the default node:sqlite\nDB_CONNECTION\n\toverride the default connection url\nCLEAR_JSX_CACHE\n\tset to 1 or 0 to enable or disable the clearing of the esbuild cache defaults to 1.\nJSX_TMP\n\tset custom location of esbuild builds defaults to /tmp/jsx_tmp.\n";
3
+ export declare const help = "\n==flags==\n\n-v, --version\n\toutputs the version number\n-h, --help\n\toutputs this page.\n--disable-etag\n\tuse to disable etag generation by default. each route can still enable this.\n--enable-etag\n\tuse to enable etag generation by default. each route can still disable this. ( by default etag is enabled )\n--watch\n\tuse to auto reload the server when files change.\n--hot-reload\n\tenables the hot-reload functionality use with --watch.\n--test\n\trun the tests for a service.\n--migrate-up\n\tmigrations up.\n--migrate-down\n\tmigrations down.\n--inflate\n\tinflates the application into a directory using esbuild.\n--inflate-dir\n\tto set the output directory of the --inflate command. default value is inflated/.\n--editor\n\truns the application with a built-in editor.\n--generate-doc\n\tgenerates a documentation for the api endpoints of the service.\n--generate-doc-out\n\tthe output file for the generated documentation. default value is API.md.\n--generate-doc-type\n\tthe format of the generated documentation. it can be JSON or MD. default value is MD.\n--generate-doc-all\n\toutputs all the server routes in the documentation output.\n--compile\n\tinflates the application and tries to create a NODE SEA binary.\n--no-build\n\tdisables calling esbuild during imports in runtime. Notice that to use jsx you will need to run tsc or esbuild on your jsx files to transpile them to js.\n--no-minify\n\tdisables calling minifing min.js files.\n--inflate-only-assets\n\tinflates ONLY the application assets. must be used with --inflate.\n--inflate-flat\n\tinflates files into the inflate-dir directly.\n--inflate-sea\n\tinflates the application with sea compilation scripts.\n--install-tsconfig\n\tcreates a tsconfig.json configured to use with --install-types.\n--install-miqrojson\n\tcreates a default miqro.json file.\n--install\n\tcreates a node_modules folder from binary cache (only available in sea binary).\n--disable-miqrojson\n\tdisables the load of miqro.json file.\n--log-file\n\toverrides the default log file from LOG_FILE.\n--browser\n\toverrides the default browser from BROWSER.\n--config\n\toverrides the default miqro.json path.\n--port\n\toverrides the default port from PORT.\n--name\n\toverrides the default name of the server.\n--https\n\tserves the server in https instead of http\n--https-key\n\tpoint to a server.key file for https.\n--https-cert\n\tpoint to a server.cert file for https.\n--https-redirect\n\tserves an aditional http server that redirects to https. it needs a port number.\n--inflate-parallel\n\tsets the max parallel esbuild instances. defaults to 1.\n\n==environment variables==\n\nPORT\n\toverride the default 8080 port.\nBROWSER\n\toverride the default browser. change to none to disable.\".\nLOG_FILE\n\toverride the default ./server.log file\nDB\n\tenable the server.db features\nDB_STORAGE\n\toverride the default local db location ./db.sqlite3\nDB_DIALECT\n\toverride the default node:sqlite\nDB_CONNECTION\n\toverride the default connection url\nCLEAR_JSX_CACHE\n\tset to 1 or 0 to enable or disable the clearing of the esbuild cache defaults to 1.\nJSX_TMP\n\tset custom location of esbuild builds defaults to /tmp/jsx_tmp.\n";
@@ -15,6 +15,8 @@ export const help = `
15
15
 
16
16
  -v, --version\n\toutputs the version number
17
17
  -h, --help\n\toutputs this page.
18
+ --disable-etag\n\tuse to disable etag generation by default. each route can still enable this.
19
+ --enable-etag\n\tuse to enable etag generation by default. each route can still disable this. ( by default etag is enabled )
18
20
  --watch\n\tuse to auto reload the server when files change.
19
21
  --hot-reload\n\tenables the hot-reload functionality use with --watch.
20
22
  --test\n\trun the tests for a service.
@@ -17,7 +17,7 @@ export async function encryptJWT(payload, secret, options) {
17
17
  .setIssuer(options?.iss ? options?.iss : 'urn:example:issuer')
18
18
  .setAudience(options?.aud ? options?.aud : 'urn:example:audience')
19
19
  .setExpirationTime(options?.exp ? options?.exp : '2h');
20
- return await en.encrypt(secret, options?.options);
20
+ return en.encrypt(secret, options?.options);
21
21
  }
22
22
  /**
23
23
  * decrypts a JWT token with jose
@@ -27,7 +27,7 @@ export async function encryptJWT(payload, secret, options) {
27
27
  * @returns
28
28
  */
29
29
  export async function decryptJWT(jwt, secret, options) {
30
- return await joseJWTDecrypt(jwt, secret, options);
30
+ return joseJWTDecrypt(jwt, secret, options);
31
31
  }
32
32
  /**
33
33
  * verify a JWT token with jose
@@ -37,7 +37,7 @@ export async function decryptJWT(jwt, secret, options) {
37
37
  * @returns
38
38
  */
39
39
  export async function verifyJWT(jwt, secret, options) {
40
- return await jwtVerify(jwt, secret, options);
40
+ return jwtVerify(jwt, secret, options);
41
41
  }
42
42
  /**
43
43
  * creates a signed JWT with jose
@@ -86,7 +86,7 @@ async function createStaticRoute(inflateJSXOptions, service, logger, router, dir
86
86
  }
87
87
  // router.use(assertGlobalTampered);
88
88
  router.get(path, async function (_req, res) {
89
- await new Promise((resolve, reject) => {
89
+ return new Promise((resolve, reject) => {
90
90
  try {
91
91
  readFile(file.filePath, async (err, body) => {
92
92
  if (err) {
@@ -94,14 +94,13 @@ async function createStaticRoute(inflateJSXOptions, service, logger, router, dir
94
94
  }
95
95
  else {
96
96
  try {
97
- await res.asyncEnd({
97
+ resolve({
98
98
  status: 200,
99
99
  headers: {
100
100
  ["Content-Type"]: contentType ? contentType : DEFAULT_CONTENT_TYPE
101
101
  },
102
102
  body
103
103
  });
104
- resolve();
105
104
  }
106
105
  catch (e) {
107
106
  reject(e);
@@ -113,6 +112,10 @@ async function createStaticRoute(inflateJSXOptions, service, logger, router, dir
113
112
  reject(e);
114
113
  }
115
114
  });
115
+ }, {
116
+ response: {
117
+ etag: true
118
+ }
116
119
  });
117
120
  resolve();
118
121
  }
@@ -250,13 +253,13 @@ async function createRouterFromDirectory(importOptions, inflateJSXOptions, serve
250
253
  // router.use(assertGlobalTampered);
251
254
  router.use(async function (req, res) {
252
255
  const JSON = await getJSON(req, res, newURL(req.path), module.apiOptions?.basePath, module.default);
253
- return res.asyncEnd({
256
+ return {
254
257
  status: 200,
255
258
  headers: {
256
259
  ["Content-Type"]: contentType ? contentType : DEFAULT_CONTENT_TYPE
257
260
  },
258
261
  body: JSON
259
- });
262
+ };
260
263
  }, r.path, r.method, r.options);
261
264
  }
262
265
  return resolve();
@@ -310,13 +313,13 @@ async function createRouterFromDirectory(importOptions, inflateJSXOptions, serve
310
313
  router.use(async function (req, res) {
311
314
  const toRender = typeof module.default === "function" ? module.default(req, res) : module.default;
312
315
  const HTML = await getHTML(hotreload, req, res, newURL(req.path), module.apiOptions?.basePath, await toRender);
313
- return res.asyncEnd({
316
+ return {
314
317
  status: 200,
315
318
  headers: {
316
319
  ["Content-Type"]: contentType ? contentType : DEFAULT_CONTENT_TYPE
317
320
  },
318
321
  body: HTML
319
- });
322
+ };
320
323
  }, r.path, r.method, r.options);
321
324
  }
322
325
  return resolve();
@@ -364,13 +367,17 @@ async function createRouterFromDirectory(importOptions, inflateJSXOptions, serve
364
367
  }
365
368
  // router.use(assertGlobalTampered);
366
369
  router.get(path, async function (req, res) {
367
- return res.asyncEnd({
370
+ return {
368
371
  status: 200,
369
372
  headers: {
370
373
  ["Content-Type"]: contentType ? contentType : DEFAULT_CONTENT_TYPE
371
374
  },
372
375
  body: code
373
- });
376
+ };
377
+ }, {
378
+ response: {
379
+ etag: true
380
+ }
374
381
  });
375
382
  return resolve();
376
383
  }
@@ -413,13 +420,17 @@ async function createRouterFromDirectory(importOptions, inflateJSXOptions, serve
413
420
  }
414
421
  // router.use(assertGlobalTampered);
415
422
  router.get(path, async function (_req, res) {
416
- res.asyncEnd({
423
+ return {
417
424
  status: 200,
418
425
  headers: {
419
426
  ["Content-Type"]: contentType ? contentType : DEFAULT_CONTENT_TYPE
420
427
  },
421
428
  body: code
422
- });
429
+ };
430
+ }, {
431
+ response: {
432
+ etag: true
433
+ }
423
434
  });
424
435
  return resolve();
425
436
  }
@@ -472,13 +483,17 @@ async function createRouterFromDirectory(importOptions, inflateJSXOptions, serve
472
483
  }
473
484
  // router.use(assertGlobalTampered);
474
485
  router.get(path, async function (_req, res) {
475
- res.asyncEnd({
486
+ return {
476
487
  status: 200,
477
488
  headers: {
478
489
  ["Content-Type"]: contentType ? contentType : DEFAULT_CONTENT_TYPE
479
490
  },
480
491
  body: code
481
- });
492
+ };
493
+ }, {
494
+ response: {
495
+ etag: true
496
+ }
482
497
  });
483
498
  return resolve();
484
499
  }
@@ -529,13 +544,17 @@ async function createRouterFromDirectory(importOptions, inflateJSXOptions, serve
529
544
  }
530
545
  // router.use(assertGlobalTampered);
531
546
  router.get(path, async function (_req, res) {
532
- res.asyncEnd({
547
+ return {
533
548
  status: 200,
534
549
  headers: {
535
550
  ["Content-Type"]: contentType ? contentType : DEFAULT_CONTENT_TYPE
536
551
  },
537
552
  body: code
538
- });
553
+ };
554
+ }, {
555
+ response: {
556
+ etag: true
557
+ }
539
558
  });
540
559
  return resolve();
541
560
  }
@@ -16,6 +16,7 @@ async function main(args) {
16
16
  else {
17
17
  const app = new Miqro({
18
18
  editor: args.editor,
19
+ etag: args.etag,
19
20
  name: args.name ? args.name : undefined,
20
21
  port: args.test ? TEST_SOCKET : args.port,
21
22
  services: args.services,
@@ -24,6 +24,7 @@ export interface MiqroOptions extends ImportJSXFileOptions {
24
24
  hotreload?: boolean;
25
25
  watch?: boolean;
26
26
  serverOptions?: ServerOptions<any, any>;
27
+ etag?: boolean;
27
28
  https?: boolean;
28
29
  httpRedirect?: number;
29
30
  noMinify?: boolean;
@@ -47,6 +47,7 @@ export class Miqro {
47
47
  constructor(options) {
48
48
  this.options = {
49
49
  noMinify: false,
50
+ etag: true,
50
51
  editor: false,
51
52
  name: "server",
52
53
  noBuild: false,
@@ -374,6 +375,7 @@ export class Miqro {
374
375
  this.logger?.error(e);
375
376
  }
376
377
  },
378
+ etag: this.options?.etag ?? true,
377
379
  loggerFactory: this.loggerProvider.requestLoggerFactory,
378
380
  serverOptions: this.options?.serverOptions,
379
381
  https: this.options?.https
@@ -19,7 +19,9 @@ export function getRoutes(prePath, defaultPath, apiOptions) {
19
19
  parser: apiOptions?.parser,
20
20
  policy: apiOptions?.policy,
21
21
  request: apiOptions?.request,
22
- response: apiOptions?.response,
22
+ response: apiOptions?.response ?? {
23
+ etag: true
24
+ },
23
25
  session: apiOptions?.session
24
26
  },
25
27
  inflatePath: defaultInflatePath,
@@ -42,7 +44,9 @@ export function getRoutes(prePath, defaultPath, apiOptions) {
42
44
  parser: apiOptions?.parser,
43
45
  policy: apiOptions?.policy,
44
46
  request: apiOptions?.request,
45
- response: apiOptions?.response,
47
+ response: apiOptions?.response ?? {
48
+ etag: true
49
+ },
46
50
  session: apiOptions?.session
47
51
  },
48
52
  inflatePath: p !== "/" ? join(prePath, p) : defaultInflatePath,
package/build/lib.cjs CHANGED
@@ -1013,31 +1013,37 @@ function ResultParser(options, parser4) {
1013
1013
  }
1014
1014
  };
1015
1015
  }
1016
- async function ResponseHandler(req, res) {
1017
- req.logger.trace("results [%o]", req.results);
1018
- if (!req.results || req.results.length === 0) {
1019
- throw new Error(`no response to send. Is your handler returning a value differente than boolean 'true|false' ?`);
1020
- } else {
1021
- const lastResult = req.results[req.results.length - 1];
1022
- req.logger.debug("response [%o]", lastResult);
1023
- if (lastResult !== void 0) {
1024
- const headers = lastResult.headers;
1025
- const body = lastResult.body;
1026
- const status = lastResult.status;
1027
- const noContentType = headers && !headers["Content-Type"] || !headers;
1028
- if (noContentType) {
1029
- await res.json(body, headers, status);
1016
+ function ResponseHandler(options) {
1017
+ const isEtagEnabled = options?.etag !== void 0;
1018
+ return async function ResponseHandler2(req, res) {
1019
+ req.logger.trace("results [%o]", req.results);
1020
+ if (!req.results || req.results.length === 0) {
1021
+ throw new Error(`no response to send. Is your handler returning a value differente than boolean 'true|false' ?`);
1022
+ } else {
1023
+ const lastResult = req.results[req.results.length - 1];
1024
+ req.logger.debug("response [%o]", lastResult);
1025
+ if (lastResult !== void 0) {
1026
+ let headers = lastResult.headers;
1027
+ const body = lastResult.body;
1028
+ const status = lastResult.status;
1029
+ const noContentType = headers && !headers["Content-Type"] || !headers;
1030
+ if (options?.etag !== void 0) {
1031
+ res.setETag(options?.etag);
1032
+ }
1033
+ if (noContentType) {
1034
+ await res.json(body, headers, status);
1035
+ } else {
1036
+ await res.asyncEnd({
1037
+ body,
1038
+ headers,
1039
+ status
1040
+ });
1041
+ }
1030
1042
  } else {
1031
- await res.asyncEnd({
1032
- body,
1033
- headers,
1034
- status
1035
- });
1043
+ throw new Error(`no response to send. Is your handler returning a value different than boolean 'true|false' ?`);
1036
1044
  }
1037
- } else {
1038
- throw new Error(`no response to send. Is your handler returning a value different than boolean 'true|false' ?`);
1039
1045
  }
1040
- }
1046
+ };
1041
1047
  }
1042
1048
  function parsePart(req, part, value, args, mode, parser4) {
1043
1049
  for (let i = 0; i < args.length; i++) {
@@ -1349,6 +1355,9 @@ function isMinimalRouter(obj) {
1349
1355
  function defineRoute(route) {
1350
1356
  return route;
1351
1357
  }
1358
+ function defaultETag({ body }) {
1359
+ return body ? `"${(0, import_node_crypto.createHash)("sha1").update(body instanceof Buffer ? body : typeof body === "object" ? JSON.stringify(body) : String(body)).digest("hex").slice(0, 16)}"` : null;
1360
+ }
1352
1361
  function pathPartTokenize(token) {
1353
1362
  const isWild = token.value[0] === ":";
1354
1363
  const optional = token.value[token.value.length - 1] === "?";
@@ -1452,12 +1461,12 @@ function parseSearchParams(search) {
1452
1461
  });
1453
1462
  return query;
1454
1463
  }
1455
- var import_cookie2, import_crypto, import_http, LoggerErrorEvent, GroupPolicySchema, SessionHandlerOptionsOptionsSchema, SessionHandlerOptionsSchema, OptionalSchema, OptionalSchemaWithBoolean, OptionalParserModeSchema, RouteOptionsSchema, RouterHandlerOptionsSchema, HandlerWithOptionsSchema, MinimalRouterSchema, APIRouteSchema, Request, Response, splitPath;
1464
+ var import_cookie2, import_node_crypto, import_node_http, LoggerErrorEvent, GroupPolicySchema, SessionHandlerOptionsOptionsSchema, SessionHandlerOptionsSchema, OptionalSchema, OptionalSchemaWithBoolean, OptionalParserModeSchema, RouteOptionsSchema, RouterHandlerOptionsSchema, HandlerWithOptionsSchema, MinimalRouterSchema, APIRouteSchema, Request, Response, splitPath;
1456
1465
  var init_types = __esm({
1457
1466
  "node_modules/@miqro/core/build/types.js"() {
1458
1467
  import_cookie2 = __toESM(require_dist(), 1);
1459
- import_crypto = require("crypto");
1460
- import_http = require("http");
1468
+ import_node_crypto = require("node:crypto");
1469
+ import_node_http = require("node:http");
1461
1470
  init_session();
1462
1471
  LoggerErrorEvent = class extends Event {
1463
1472
  constructor(event, init) {
@@ -1548,6 +1557,7 @@ var init_types = __esm({
1548
1557
  response: {
1549
1558
  type: "object?|boolean?",
1550
1559
  properties: {
1560
+ etag: "boolean?|function?",
1551
1561
  status: "number[]!?",
1552
1562
  headers: OptionalSchema,
1553
1563
  headersMode: OptionalParserModeSchema,
@@ -1624,7 +1634,7 @@ var init_types = __esm({
1624
1634
  init: "function?"
1625
1635
  }
1626
1636
  };
1627
- Request = class extends import_http.IncomingMessage {
1637
+ Request = class extends import_node_http.IncomingMessage {
1628
1638
  constructor(socket) {
1629
1639
  super(socket);
1630
1640
  this.logger = console;
@@ -1636,7 +1646,7 @@ var init_types = __esm({
1636
1646
  this.params = /* @__PURE__ */ Object.create(null);
1637
1647
  this.results = [];
1638
1648
  this.startMS = Date.now();
1639
- this.uuid = (0, import_crypto.randomUUID)();
1649
+ this.uuid = (0, import_node_crypto.randomUUID)();
1640
1650
  let vURL;
1641
1651
  Object.defineProperty(this, "url", {
1642
1652
  get: () => {
@@ -1680,12 +1690,16 @@ var init_types = __esm({
1680
1690
  });
1681
1691
  }
1682
1692
  };
1683
- Response = class _Response extends import_http.ServerResponse {
1693
+ Response = class _Response extends import_node_http.ServerResponse {
1684
1694
  //logger: Logger;
1685
1695
  constructor(req) {
1686
1696
  super(req);
1697
+ this.useETag = false;
1687
1698
  this.removeHeader("Date");
1688
1699
  }
1700
+ setETag(useETag) {
1701
+ this.useETag = useETag;
1702
+ }
1689
1703
  async redirect(url, headers, status) {
1690
1704
  return this.asyncEnd({
1691
1705
  status: status !== void 0 ? status : 302,
@@ -1778,18 +1792,38 @@ var init_types = __esm({
1778
1792
  if (this.headersSent) {
1779
1793
  return Promise.reject(new Error("already ended"));
1780
1794
  }
1781
- return new Promise((resolve24, reject) => {
1795
+ return new Promise(async (resolve24, reject) => {
1782
1796
  try {
1783
1797
  if (this.headersSent) {
1784
1798
  reject(new Error("already ended"));
1799
+ return;
1785
1800
  } else {
1786
1801
  const body = args ? args.body : void 0;
1802
+ const nBody = body !== void 0 ? body instanceof Buffer ? body : String(body) : null;
1787
1803
  if (args !== void 0) {
1788
1804
  const { status, headers } = args;
1789
1805
  const nStatus = status !== void 0 ? parseInt(String(status), 10) : 200;
1790
1806
  if (isNaN(nStatus)) {
1791
1807
  reject(new Error("status not a number!"));
1808
+ return;
1792
1809
  } else {
1810
+ if (this.useETag) {
1811
+ let incomingETag = this.req.headers["if-none-match"];
1812
+ if (incomingETag && incomingETag.indexOf("W/") === 0) {
1813
+ incomingETag = incomingETag.substring("W/".length);
1814
+ }
1815
+ const etag = typeof this.useETag === "function" ? await this.useETag(args) : defaultETag({ body: nBody });
1816
+ if (incomingETag && etag && etag === incomingETag && nStatus >= 200 && nStatus < 300) {
1817
+ this.statusCode = 304;
1818
+ this.setHeader("ETag", etag);
1819
+ this.end(() => {
1820
+ resolve24();
1821
+ });
1822
+ return;
1823
+ } else if (etag) {
1824
+ this.setHeader("ETag", etag);
1825
+ }
1826
+ }
1793
1827
  this.statusCode = nStatus;
1794
1828
  if (headers) {
1795
1829
  const keys = Object.keys(headers);
@@ -1805,7 +1839,6 @@ var init_types = __esm({
1805
1839
  }
1806
1840
  }
1807
1841
  this.setHeader("connection", "close");
1808
- const nBody = body !== void 0 ? body instanceof Buffer ? body : String(body) : null;
1809
1842
  this.end(nBody, () => {
1810
1843
  resolve24();
1811
1844
  });
@@ -2262,6 +2295,9 @@ var init_router = __esm({
2262
2295
  const loggerFactory = this.config && this.config.loggerFactory ? this.config.loggerFactory : routerDefaultLoggerFactory;
2263
2296
  this.listener = async (req, res) => {
2264
2297
  req.logger = loggerFactory(req.uuid, req);
2298
+ if (this.config?.etag !== void 0) {
2299
+ res.setETag(this.config?.etag);
2300
+ }
2265
2301
  req.logger.trace(`request received`);
2266
2302
  await this.run(req, res);
2267
2303
  };
@@ -2416,7 +2452,11 @@ ${tab}${tab}${methodData.description}` : ""}`;
2416
2452
  }
2417
2453
  handlers = handlers.concat(routeHandlers);
2418
2454
  if (this.options && this.options.response && !this.isRouter) {
2419
- const responseMiddleware = typeof this.options.response === "boolean" ? [ResponseHandler] : this.options.response.middleware ? this.options.response.middleware instanceof Array ? this.options.response.middleware : [this.options.response.middleware] : [ResponseHandler];
2455
+ const responseMiddleware = typeof this.options.response === "boolean" ? [ResponseHandler({
2456
+ etag: true
2457
+ })] : this.options.response.middleware ? this.options.response.middleware instanceof Array ? this.options.response.middleware : [this.options.response.middleware] : [ResponseHandler({
2458
+ etag: this.options?.response?.etag !== void 0 ? this.options?.response?.etag : true
2459
+ })];
2420
2460
  if (typeof this.options.response !== "boolean") {
2421
2461
  handlers.push(ResultParser(this.options.response, this.options.parser));
2422
2462
  }
@@ -2518,14 +2558,14 @@ ${tab}${tab}${methodData.description}` : ""}`;
2518
2558
  });
2519
2559
 
2520
2560
  // node_modules/@miqro/core/build/app.js
2521
- var import_http2, import_https, import_crypto2, App;
2561
+ var import_http, import_https, import_crypto, App;
2522
2562
  var init_app = __esm({
2523
2563
  "node_modules/@miqro/core/build/app.js"() {
2524
- import_http2 = require("http");
2564
+ import_http = require("http");
2525
2565
  import_https = require("https");
2526
2566
  init_router();
2527
2567
  init_common();
2528
- import_crypto2 = require("crypto");
2568
+ import_crypto = require("crypto");
2529
2569
  App = class extends Router2 {
2530
2570
  constructor(config) {
2531
2571
  super(config);
@@ -2544,6 +2584,9 @@ var init_app = __esm({
2544
2584
  const logger = loggerFactory(req.uuid, req);
2545
2585
  try {
2546
2586
  req.logger = logger;
2587
+ if (this.config?.etag !== void 0) {
2588
+ res.setETag(this.config?.etag);
2589
+ }
2547
2590
  try {
2548
2591
  req.logger.trace(`request received for [%s]`, req.path);
2549
2592
  if (this.shouldCloseConnection) {
@@ -2581,10 +2624,10 @@ var init_app = __esm({
2581
2624
  console.error(loggerError);
2582
2625
  }
2583
2626
  };
2584
- const createS = config && config.https ? import_https.createServer : import_http2.createServer;
2627
+ const createS = config && config.https ? import_https.createServer : import_http.createServer;
2585
2628
  this.httpServer = createS(this.serverOptions, this.listener);
2586
2629
  this.httpServer.on("connection", (conn) => {
2587
- const key = (0, import_crypto2.randomUUID)();
2630
+ const key = (0, import_crypto.randomUUID)();
2588
2631
  this.connections[key] = conn;
2589
2632
  conn.on("close", () => {
2590
2633
  delete this.connections[key];
@@ -2670,7 +2713,7 @@ var init_app = __esm({
2670
2713
 
2671
2714
  // node_modules/@miqro/core/build/websocket.js
2672
2715
  function createUpgradeHeaders(acceptKey, extraHeaders) {
2673
- const acceptValue = (0, import_crypto3.createHash)("sha1").update(acceptKey + GUID, "binary").digest("base64");
2716
+ const acceptValue = (0, import_crypto2.createHash)("sha1").update(acceptKey + GUID, "binary").digest("base64");
2674
2717
  let extra = extraHeaders && extraHeaders.length > 0 ? `\r
2675
2718
  ${extraHeaders.map((h) => `${h.name}: ${h.value}`).join("\r\n")}` : "";
2676
2719
  return `HTTP/1.1 101 Switching Protocols\r
@@ -2746,10 +2789,10 @@ function createFrame(payload) {
2746
2789
  buffer.write(payload, payloadBytesOffset);
2747
2790
  return buffer;
2748
2791
  }
2749
- var import_crypto3, WebSocketServer, PING, OPCODES, GUID, DEFAULT_MAX_FRAME_SIZE;
2792
+ var import_crypto2, WebSocketServer, PING, OPCODES, GUID, DEFAULT_MAX_FRAME_SIZE;
2750
2793
  var init_websocket = __esm({
2751
2794
  "node_modules/@miqro/core/build/websocket.js"() {
2752
- import_crypto3 = require("crypto");
2795
+ import_crypto2 = require("crypto");
2753
2796
  WebSocketServer = class {
2754
2797
  constructor(options) {
2755
2798
  this.options = options;
@@ -2825,7 +2868,7 @@ var init_websocket = __esm({
2825
2868
  return;
2826
2869
  } else {
2827
2870
  const validateRet = this.options.validate ? await this.options.validate(req) : true;
2828
- const uuid = typeof validateRet === "boolean" ? validateRet ? (0, import_crypto3.randomUUID)() : null : typeof validateRet === "object" ? validateRet.uuid : validateRet ? (0, import_crypto3.randomUUID)() : null;
2871
+ const uuid = typeof validateRet === "boolean" ? validateRet ? (0, import_crypto2.randomUUID)() : null : typeof validateRet === "object" ? validateRet.uuid : validateRet ? (0, import_crypto2.randomUUID)() : null;
2829
2872
  const extraHeaders = typeof validateRet === "object" ? validateRet.headers : void 0;
2830
2873
  if (!uuid) {
2831
2874
  req.logger.debug("validating failed with result [%s]", validateRet);
@@ -9052,7 +9095,7 @@ var DEFAULT_BUILD_DIR = (0, import_os.tmpdir)();
9052
9095
 
9053
9096
  // src/common/jsx.ts
9054
9097
  var import_node_path6 = require("node:path");
9055
- var import_node_crypto3 = require("node:crypto");
9098
+ var import_node_crypto4 = require("node:crypto");
9056
9099
  init_lib();
9057
9100
  init_lib3();
9058
9101
  var import_node_process3 = require("node:process");
@@ -9066,7 +9109,7 @@ var import_node_sea = require("node:sea");
9066
9109
  var import_node_path3 = require("node:path");
9067
9110
 
9068
9111
  // src/common/checksum.ts
9069
- var import_node_crypto = require("node:crypto");
9112
+ var import_node_crypto2 = require("node:crypto");
9070
9113
  var import_node_fs2 = require("node:fs");
9071
9114
  async function calculateChecksum(filePath) {
9072
9115
  return calculateChecksumFromStream((0, import_node_fs2.createReadStream)(filePath));
@@ -9074,7 +9117,7 @@ async function calculateChecksum(filePath) {
9074
9117
  async function calculateChecksumFromStream(input) {
9075
9118
  return new Promise((resolve24, reject) => {
9076
9119
  try {
9077
- const hash = (0, import_node_crypto.createHash)("sha256");
9120
+ const hash = (0, import_node_crypto2.createHash)("sha256");
9078
9121
  input.on("readable", () => {
9079
9122
  const data = input.read();
9080
9123
  if (data)
@@ -9094,7 +9137,7 @@ async function calculateChecksumFromStream(input) {
9094
9137
  async function calculateChecksumFromBuffer(buffer) {
9095
9138
  return new Promise((resolve24, reject) => {
9096
9139
  try {
9097
- const hash = (0, import_node_crypto.createHash)("sha256");
9140
+ const hash = (0, import_node_crypto2.createHash)("sha256");
9098
9141
  hash.update(buffer);
9099
9142
  resolve24(hash.digest("hex").toString());
9100
9143
  } catch (e) {
@@ -9298,13 +9341,13 @@ async function initAsset(logger, path, buffer, executable, checksum, logInstalla
9298
9341
 
9299
9342
  // src/common/paths.ts
9300
9343
  init_lib3();
9301
- var import_node_crypto2 = require("node:crypto");
9344
+ var import_node_crypto3 = require("node:crypto");
9302
9345
  var import_node_fs5 = require("node:fs");
9303
9346
  var import_node_os = require("node:os");
9304
9347
  var import_node_path4 = require("node:path");
9305
9348
  var import_node_process2 = require("node:process");
9306
9349
  var JSX_TMP_DIR = checkEnvVariable(`JSX_TMP`, (0, import_node_path4.resolve)((0, import_node_os.tmpdir)(), "jsx_tmp"));
9307
- var TEST_SOCKET = (0, import_node_path4.resolve)(JSX_TMP_DIR, `test.${(0, import_node_crypto2.randomUUID)()}.sock`);
9350
+ var TEST_SOCKET = (0, import_node_path4.resolve)(JSX_TMP_DIR, `test.${(0, import_node_crypto3.randomUUID)()}.sock`);
9308
9351
  function getServicePath(service) {
9309
9352
  return (0, import_node_path4.resolve)((0, import_node_process2.cwd)(), service);
9310
9353
  }
@@ -9461,7 +9504,7 @@ function JSXTemplate(inFile, useExport = true) {
9461
9504
  return `${useExport ? `export * from "${inFile}";import * as lib from "${inFile}";export default lib.default;` : `import * as lib from "${inFile}"`}`;
9462
9505
  }
9463
9506
  async function inflateJSX(inFile, options) {
9464
- const tmpBuildDir = (0, import_node_path6.resolve)(JSX_TMP_DIR, String(process.pid), "build", Date.now() + "-" + (0, import_node_crypto3.randomUUID)());
9507
+ const tmpBuildDir = (0, import_node_path6.resolve)(JSX_TMP_DIR, String(process.pid), "build", Date.now() + "-" + (0, import_node_crypto4.randomUUID)());
9465
9508
  const inFileTmp = (0, import_node_path6.resolve)(tmpBuildDir, (0, import_node_path6.basename)(inFile) + ".mjs");
9466
9509
  const logger = options.logger;
9467
9510
  try {
@@ -9792,7 +9835,7 @@ async function importJSXFile(inFile, options, logger) {
9792
9835
  platform: "node",
9793
9836
  logger
9794
9837
  });
9795
- const tmpBuildDir = (0, import_node_path6.resolve)(JSX_TMP_DIR, String(process.pid), "import", Date.now() + "-" + (0, import_node_crypto3.randomUUID)());
9838
+ const tmpBuildDir = (0, import_node_path6.resolve)(JSX_TMP_DIR, String(process.pid), "import", Date.now() + "-" + (0, import_node_crypto4.randomUUID)());
9796
9839
  const inFileTmp = (0, import_node_path6.resolve)(tmpBuildDir, (0, import_node_path6.basename)(inFile) + ".cjs");
9797
9840
  await mkdirASync(tmpBuildDir, {
9798
9841
  recursive: true
@@ -12632,7 +12675,9 @@ function getRoutes(prePath, defaultPath, apiOptions) {
12632
12675
  parser: apiOptions?.parser,
12633
12676
  policy: apiOptions?.policy,
12634
12677
  request: apiOptions?.request,
12635
- response: apiOptions?.response,
12678
+ response: apiOptions?.response ?? {
12679
+ etag: true
12680
+ },
12636
12681
  session: apiOptions?.session
12637
12682
  },
12638
12683
  inflatePath: defaultInflatePath,
@@ -12654,7 +12699,9 @@ function getRoutes(prePath, defaultPath, apiOptions) {
12654
12699
  parser: apiOptions?.parser,
12655
12700
  policy: apiOptions?.policy,
12656
12701
  request: apiOptions?.request,
12657
- response: apiOptions?.response,
12702
+ response: apiOptions?.response ?? {
12703
+ etag: true
12704
+ },
12658
12705
  session: apiOptions?.session
12659
12706
  },
12660
12707
  inflatePath: p !== "/" ? (0, import_node_path9.join)(prePath, p) : defaultInflatePath,
@@ -12842,21 +12889,20 @@ async function createStaticRoute(inflateJSXOptions, service, logger, router, dir
12842
12889
  }
12843
12890
  }
12844
12891
  router.get(path, async function(_req, res) {
12845
- await new Promise((resolve25, reject2) => {
12892
+ return new Promise((resolve25, reject2) => {
12846
12893
  try {
12847
12894
  (0, import_node_fs11.readFile)(file.filePath, async (err, body) => {
12848
12895
  if (err) {
12849
12896
  reject2(err);
12850
12897
  } else {
12851
12898
  try {
12852
- await res.asyncEnd({
12899
+ resolve25({
12853
12900
  status: 200,
12854
12901
  headers: {
12855
12902
  ["Content-Type"]: contentType ? contentType : DEFAULT_CONTENT_TYPE
12856
12903
  },
12857
12904
  body
12858
12905
  });
12859
- resolve25();
12860
12906
  } catch (e) {
12861
12907
  reject2(e);
12862
12908
  }
@@ -12866,6 +12912,10 @@ async function createStaticRoute(inflateJSXOptions, service, logger, router, dir
12866
12912
  reject2(e);
12867
12913
  }
12868
12914
  });
12915
+ }, {
12916
+ response: {
12917
+ etag: true
12918
+ }
12869
12919
  });
12870
12920
  resolve24();
12871
12921
  } catch (e) {
@@ -12987,13 +13037,13 @@ async function createRouterFromDirectory(importOptions, inflateJSXOptions, serve
12987
13037
  }
12988
13038
  router.use(async function(req, res) {
12989
13039
  const JSON2 = await getJSON(req, res, newURL2(req.path), module2.apiOptions?.basePath, module2.default);
12990
- return res.asyncEnd({
13040
+ return {
12991
13041
  status: 200,
12992
13042
  headers: {
12993
13043
  ["Content-Type"]: contentType ? contentType : DEFAULT_CONTENT_TYPE
12994
13044
  },
12995
13045
  body: JSON2
12996
- });
13046
+ };
12997
13047
  }, r.path, r.method, r.options);
12998
13048
  }
12999
13049
  return resolve24();
@@ -13044,13 +13094,13 @@ async function createRouterFromDirectory(importOptions, inflateJSXOptions, serve
13044
13094
  router.use(async function(req, res) {
13045
13095
  const toRender = typeof module2.default === "function" ? module2.default(req, res) : module2.default;
13046
13096
  const HTML = await getHTML(hotreload, req, res, newURL2(req.path), module2.apiOptions?.basePath, await toRender);
13047
- return res.asyncEnd({
13097
+ return {
13048
13098
  status: 200,
13049
13099
  headers: {
13050
13100
  ["Content-Type"]: contentType ? contentType : DEFAULT_CONTENT_TYPE
13051
13101
  },
13052
13102
  body: HTML
13053
- });
13103
+ };
13054
13104
  }, r.path, r.method, r.options);
13055
13105
  }
13056
13106
  return resolve24();
@@ -13096,13 +13146,17 @@ async function createRouterFromDirectory(importOptions, inflateJSXOptions, serve
13096
13146
  }
13097
13147
  }
13098
13148
  router.get(path, async function(req, res) {
13099
- return res.asyncEnd({
13149
+ return {
13100
13150
  status: 200,
13101
13151
  headers: {
13102
13152
  ["Content-Type"]: contentType ? contentType : DEFAULT_CONTENT_TYPE
13103
13153
  },
13104
13154
  body: code
13105
- });
13155
+ };
13156
+ }, {
13157
+ response: {
13158
+ etag: true
13159
+ }
13106
13160
  });
13107
13161
  return resolve24();
13108
13162
  }
@@ -13144,13 +13198,17 @@ async function createRouterFromDirectory(importOptions, inflateJSXOptions, serve
13144
13198
  }
13145
13199
  }
13146
13200
  router.get(path, async function(_req, res) {
13147
- res.asyncEnd({
13201
+ return {
13148
13202
  status: 200,
13149
13203
  headers: {
13150
13204
  ["Content-Type"]: contentType ? contentType : DEFAULT_CONTENT_TYPE
13151
13205
  },
13152
13206
  body: code
13153
- });
13207
+ };
13208
+ }, {
13209
+ response: {
13210
+ etag: true
13211
+ }
13154
13212
  });
13155
13213
  return resolve24();
13156
13214
  }
@@ -13202,13 +13260,17 @@ async function createRouterFromDirectory(importOptions, inflateJSXOptions, serve
13202
13260
  }
13203
13261
  }
13204
13262
  router.get(path, async function(_req, res) {
13205
- res.asyncEnd({
13263
+ return {
13206
13264
  status: 200,
13207
13265
  headers: {
13208
13266
  ["Content-Type"]: contentType ? contentType : DEFAULT_CONTENT_TYPE
13209
13267
  },
13210
13268
  body: code
13211
- });
13269
+ };
13270
+ }, {
13271
+ response: {
13272
+ etag: true
13273
+ }
13212
13274
  });
13213
13275
  return resolve24();
13214
13276
  }
@@ -13252,13 +13314,17 @@ async function createRouterFromDirectory(importOptions, inflateJSXOptions, serve
13252
13314
  }
13253
13315
  }
13254
13316
  router.get(path, async function(_req, res) {
13255
- res.asyncEnd({
13317
+ return {
13256
13318
  status: 200,
13257
13319
  headers: {
13258
13320
  ["Content-Type"]: contentType ? contentType : DEFAULT_CONTENT_TYPE
13259
13321
  },
13260
13322
  body: code
13261
- });
13323
+ };
13324
+ }, {
13325
+ response: {
13326
+ etag: true
13327
+ }
13262
13328
  });
13263
13329
  return resolve24();
13264
13330
  }
@@ -14055,7 +14121,7 @@ init_constants();
14055
14121
  init_constants();
14056
14122
 
14057
14123
  // editor/auth.ts
14058
- var import_node_crypto4 = require("node:crypto");
14124
+ var import_node_crypto5 = require("node:crypto");
14059
14125
  var ADMIN_EDITOR_AUTH_KEY = "$$ADMIN_EDITOR_AUTH_KEY$$";
14060
14126
  var ADMIN_EDITOR_AUTH_QUERY = "key";
14061
14127
  var ADMIN_EDITOR_AUTH_COOKIE = ADMIN_EDITOR_AUTH_KEY;
@@ -14074,7 +14140,7 @@ var auth_default = {
14074
14140
  const queryToken = args.req.query[ADMIN_EDITOR_AUTH_QUERY];
14075
14141
  const cookieToken = args.req.cookies[ADMIN_EDITOR_AUTH_COOKIE];
14076
14142
  if (queryToken) {
14077
- if (typeof queryToken === "string" && (0, import_node_crypto4.timingSafeEqual)(Buffer.from(queryToken), Buffer.from(KEY))) {
14143
+ if (typeof queryToken === "string" && (0, import_node_crypto5.timingSafeEqual)(Buffer.from(queryToken), Buffer.from(KEY))) {
14078
14144
  args.res.setCookie(ADMIN_EDITOR_AUTH_COOKIE, KEY, {
14079
14145
  expires: new Date(Date.now() + 1e3 * 60 * 60 * 24 * 31 * 12 * 500),
14080
14146
  httpOnly: true,
@@ -14109,7 +14175,7 @@ var ws_default = {
14109
14175
  };
14110
14176
 
14111
14177
  // editor/server.ts
14112
- var import_node_crypto5 = require("node:crypto");
14178
+ var import_node_crypto6 = require("node:crypto");
14113
14179
  init_constants();
14114
14180
  var import_node_fs17 = require("node:fs");
14115
14181
  var import_node_path18 = require("node:path");
@@ -14124,7 +14190,7 @@ var server_default = {
14124
14190
  serverInterface.logger.warn("loading static ADMIN_KEY from [%s]", (0, import_node_path18.relative)(process.cwd(), adminKEYPath));
14125
14191
  cache2.set(ADMIN_EDITOR_AUTH_KEY, (0, import_node_fs17.readFileSync)(adminKEYPath).toString().trim());
14126
14192
  } else {
14127
- cache2.set(ADMIN_EDITOR_AUTH_KEY, (0, import_node_crypto5.randomUUID)());
14193
+ cache2.set(ADMIN_EDITOR_AUTH_KEY, (0, import_node_crypto6.randomUUID)());
14128
14194
  }
14129
14195
  }
14130
14196
  }
@@ -17048,13 +17114,13 @@ async function encryptJWT(payload, secret, options) {
17048
17114
  alg: options?.alg ? options?.alg : "dir",
17049
17115
  enc: options?.enc ? options?.enc : "A128CBC-HS256"
17050
17116
  }).setIssuedAt(options?.iat).setIssuer(options?.iss ? options?.iss : "urn:example:issuer").setAudience(options?.aud ? options?.aud : "urn:example:audience").setExpirationTime(options?.exp ? options?.exp : "2h");
17051
- return await en.encrypt(secret, options?.options);
17117
+ return en.encrypt(secret, options?.options);
17052
17118
  }
17053
17119
  async function decryptJWT(jwt2, secret, options) {
17054
- return await jwtDecrypt(jwt2, secret, options);
17120
+ return jwtDecrypt(jwt2, secret, options);
17055
17121
  }
17056
17122
  async function verifyJWT(jwt2, secret, options) {
17057
- return await jwtVerify(jwt2, secret, options);
17123
+ return jwtVerify(jwt2, secret, options);
17058
17124
  }
17059
17125
  async function signJWT(payload, secret, options) {
17060
17126
  const sign2 = new SignJWT(payload).setProtectedHeader({
@@ -17070,9 +17136,9 @@ function decodeJWT(jwt2) {
17070
17136
  }
17071
17137
 
17072
17138
  // src/services/utils/jwt.ts
17073
- var import_node_crypto6 = require("node:crypto");
17139
+ var import_node_crypto7 = require("node:crypto");
17074
17140
  var jwt = {
17075
- createSecretKey: import_node_crypto6.createSecretKey,
17141
+ createSecretKey: import_node_crypto7.createSecretKey,
17076
17142
  decode(jwt2) {
17077
17143
  return decodeJWT(jwt2);
17078
17144
  },
@@ -17208,6 +17274,7 @@ var MiqroJSONSchema = {
17208
17274
  type: "object",
17209
17275
  properties: {
17210
17276
  name: "string?",
17277
+ etag: "boolean?",
17211
17278
  services: "string[]?",
17212
17279
  noBuild: "boolean?",
17213
17280
  noMinify: "boolean?",
@@ -17346,6 +17413,7 @@ var Miqro = class _Miqro {
17346
17413
  constructor(options) {
17347
17414
  this.options = {
17348
17415
  noMinify: false,
17416
+ etag: true,
17349
17417
  editor: false,
17350
17418
  name: "server",
17351
17419
  noBuild: false,
@@ -17637,6 +17705,7 @@ var Miqro = class _Miqro {
17637
17705
  this.logger?.error(e);
17638
17706
  }
17639
17707
  },
17708
+ etag: this.options?.etag ?? true,
17640
17709
  loggerFactory: this.loggerProvider.requestLoggerFactory,
17641
17710
  serverOptions: this.options?.serverOptions,
17642
17711
  https: this.options?.https
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "miqro",
3
- "version": "7.2.9",
3
+ "version": "7.3.1",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "build/esm/src/lib.js",
@@ -16,7 +16,7 @@
16
16
  "prerelease:package": "npm run compile",
17
17
  "prebuild": "rm -Rf build/;",
18
18
  "build": "tsc",
19
- "postbuild": "npm run postbuild:lib && npm run postbuild:sh && npm run postbuild:assets && npm run postbuild:editor && npm run postbuild:editor-assets && npm run postbuild:versiontag",
19
+ "postbuild": "npm run postbuild:lib && npm run postbuild:sh && npm run postbuild:editor && npm run postbuild:editor-assets && npm run postbuild:versiontag",
20
20
  "postbuild:versiontag": "node sea/version.tag.js",
21
21
  "postbuild:editor-assets": "cp sea/editor-assets/style.css build/style.css",
22
22
  "postbuild:editor": "esbuild --external:node:process --external:node:path --bundle --loader:.js=jsx --jsx-factory=jsx.createElement --jsx-fragment=jsx.Fragment sea/editor-assets/editor.bundle.in.mjs --outfile=build/editor.bundle.js",
@@ -41,10 +41,10 @@
41
41
  },
42
42
  "dependencies": {
43
43
  "postject": "1.0.0-alpha.6",
44
- "@miqro/core": "^5.0.20",
44
+ "@miqro/core": "^5.1.1",
45
45
  "@miqro/jsx": "^1.0.2",
46
46
  "@miqro/jsx-dom": "^1.0.6",
47
- "@miqro/jsx-node": "^1.0.7",
47
+ "@miqro/jsx-node": "^1.0.8",
48
48
  "@miqro/parser": "^2.0.6",
49
49
  "@miqro/query": "^0.0.8",
50
50
  "@miqro/runner": "^2.0.3",