tina4-nodejs 3.13.140 → 3.13.142

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.
Files changed (38) hide show
  1. package/CLAUDE.md +2 -2
  2. package/package.json +1 -1
  3. package/packages/cli/dist/bin.js +438 -453
  4. package/packages/cli/src/bin.ts +4 -14
  5. package/packages/cli/src/commands/build.ts +2 -18
  6. package/packages/cli/src/commands/generate.ts +2 -22
  7. package/packages/cli/src/commands/lint.ts +3 -13
  8. package/packages/cli/src/commands/migrate.ts +2 -6
  9. package/packages/cli/src/commands/migrateRollback.ts +2 -6
  10. package/packages/cli/src/commands/migrateStatus.ts +2 -6
  11. package/packages/cli/src/commands/queue.ts +2 -30
  12. package/packages/cli/src/util.ts +90 -0
  13. package/packages/core/dist/index.js +215 -184
  14. package/packages/core/gallery/queue/src/lib/queueDb.ts +11 -0
  15. package/packages/core/gallery/queue/src/routes/api/gallery/queue/consume/post.ts +2 -5
  16. package/packages/core/gallery/queue/src/routes/api/gallery/queue/fail/post.ts +2 -5
  17. package/packages/core/src/devAdmin.ts +3 -12
  18. package/packages/core/src/dispatchPipeline.ts +2 -18
  19. package/packages/core/src/etag.ts +24 -0
  20. package/packages/core/src/feedback.ts +2 -11
  21. package/packages/core/src/session.ts +22 -66
  22. package/packages/core/src/sessionHandlers/respSessionHandler.ts +94 -0
  23. package/packages/core/src/sessionHandlers/valkeyHandler.ts +22 -73
  24. package/packages/core/src/static.ts +1 -13
  25. package/packages/core/src/upstreamResponse.ts +31 -0
  26. package/packages/core/src/websocket.ts +48 -7
  27. package/packages/orm/dist/index.js +215 -184
  28. package/packages/orm/src/graph/adapters/bolt.ts +8 -29
  29. package/packages/orm/src/graph/adapters/rowMapping.ts +57 -0
  30. package/packages/orm/src/graph/adapters/ultipa.ts +8 -30
  31. package/types/cli/src/util.d.ts +28 -0
  32. package/types/core/src/etag.d.ts +9 -0
  33. package/types/core/src/session.d.ts +2 -19
  34. package/types/core/src/sessionHandlers/respSessionHandler.d.ts +52 -0
  35. package/types/core/src/sessionHandlers/valkeyHandler.d.ts +2 -26
  36. package/types/core/src/upstreamResponse.d.ts +10 -0
  37. package/types/core/src/websocket.d.ts +21 -0
  38. package/types/orm/src/graph/adapters/rowMapping.d.ts +26 -0
@@ -13695,6 +13695,36 @@ var init_shapes = __esm({
13695
13695
  }
13696
13696
  });
13697
13697
 
13698
+ // ../orm/src/graph/adapters/rowMapping.ts
13699
+ function errorMessage(exc) {
13700
+ if (exc instanceof Error) return exc.message;
13701
+ return String(exc);
13702
+ }
13703
+ function nodeFromRow(row) {
13704
+ if (row === null || row === void 0) return null;
13705
+ return new GraphNode(
13706
+ String(row.id),
13707
+ row.labels ?? [],
13708
+ row.props ?? {}
13709
+ );
13710
+ }
13711
+ function edgeFromRow(row) {
13712
+ if (row === null || row === void 0) return null;
13713
+ return new GraphEdge(
13714
+ String(row.id),
13715
+ String(row.type),
13716
+ String(row.f),
13717
+ String(row.t),
13718
+ row.props ?? {}
13719
+ );
13720
+ }
13721
+ var init_rowMapping = __esm({
13722
+ "../orm/src/graph/adapters/rowMapping.ts"() {
13723
+ "use strict";
13724
+ init_shapes();
13725
+ }
13726
+ });
13727
+
13698
13728
  // ../orm/src/graph/connectTimeout.ts
13699
13729
  function resolveGraphConnectTimeout() {
13700
13730
  const raw = (process.env[GRAPH_CONNECT_TIMEOUT_VARIABLE] ?? "").trim();
@@ -13734,15 +13764,12 @@ function propClause(properties) {
13734
13764
  for (const key of keys) params[`p_${key}`] = props[key];
13735
13765
  return { clause: `{${pairs}}`, params };
13736
13766
  }
13737
- function errorMessage(exc) {
13738
- if (exc instanceof Error) return exc.message;
13739
- return String(exc);
13740
- }
13741
13767
  var DRIVER_PACKAGE, driver, UltipaClient, UltipaConnectError, UNBOUNDED_CONNECT_SECONDS, UltipaGraphAdapter;
13742
13768
  var init_ultipa = __esm({
13743
13769
  async "../orm/src/graph/adapters/ultipa.ts"() {
13744
13770
  "use strict";
13745
13771
  init_shapes();
13772
+ init_rowMapping();
13746
13773
  init_errors();
13747
13774
  init_connectTimeout2();
13748
13775
  DRIVER_PACKAGE = "tina4-ultipa";
@@ -13800,12 +13827,7 @@ var init_ultipa = __esm({
13800
13827
  }
13801
13828
  // -- portable node/edge/traverse core (GQL) ----------------------------
13802
13829
  nodeFromRow(row) {
13803
- if (row === null || row === void 0) return null;
13804
- return new GraphNode(
13805
- String(row.id),
13806
- row.labels ?? [],
13807
- row.props ?? {}
13808
- );
13830
+ return nodeFromRow(row);
13809
13831
  }
13810
13832
  async addNode(label, properties = null) {
13811
13833
  const { clause, params } = propClause(properties);
@@ -13819,15 +13841,7 @@ var init_ultipa = __esm({
13819
13841
  params.to_id = toId;
13820
13842
  const gql = `MATCH (a), (b) WHERE id(a) = $from_id AND id(b) = $to_id INSERT (a)-[e:\`${type2}\` ${clause}]->(b) RETURN id(e) AS id, type(e) AS type, id(a) AS f, id(b) AS t, properties(e) AS props`;
13821
13843
  const rows = (await this.run(gql, params, false)).dicts();
13822
- if (rows.length === 0) return null;
13823
- const row = rows[0];
13824
- return new GraphEdge(
13825
- String(row.id),
13826
- String(row.type),
13827
- String(row.f),
13828
- String(row.t),
13829
- row.props ?? {}
13830
- );
13844
+ return edgeFromRow(rows[0]);
13831
13845
  }
13832
13846
  async getNode(nodeId) {
13833
13847
  const gql = `MATCH (n) WHERE id(n) = $id RETURN id(n) AS id, labels(n) AS labels, properties(n) AS props`;
@@ -13892,10 +13906,6 @@ var bolt_exports = {};
13892
13906
  __export(bolt_exports, {
13893
13907
  BoltGraphAdapter: () => BoltGraphAdapter
13894
13908
  });
13895
- function errorMessage2(exc) {
13896
- if (exc instanceof Error) return exc.message;
13897
- return String(exc);
13898
- }
13899
13909
  function boltId(id) {
13900
13910
  const value = Number(id);
13901
13911
  return Number.isNaN(value) ? -1 : value;
@@ -13905,6 +13915,7 @@ var init_bolt = __esm({
13905
13915
  async "../orm/src/graph/adapters/bolt.ts"() {
13906
13916
  "use strict";
13907
13917
  init_shapes();
13918
+ init_rowMapping();
13908
13919
  init_errors();
13909
13920
  init_connectTimeout2();
13910
13921
  DRIVER_PACKAGE2 = "neo4j-driver";
@@ -13940,7 +13951,7 @@ var init_bolt = __esm({
13940
13951
  const result = await session.run(cypher, params ?? {});
13941
13952
  return result.records.map((record) => record.toObject());
13942
13953
  } catch (exc) {
13943
- this.lastError = errorMessage2(exc);
13954
+ this.lastError = errorMessage(exc);
13944
13955
  const code = exc?.code ?? "";
13945
13956
  const message = this.lastError.toLowerCase();
13946
13957
  if (code === "ServiceUnavailable" || code === neo4j.error?.SERVICE_UNAVAILABLE || message.includes("timed out") || message.includes("timeout")) {
@@ -13964,12 +13975,7 @@ var init_bolt = __esm({
13964
13975
  }
13965
13976
  // -- portable node/edge/traverse core (Cypher) -------------------------
13966
13977
  nodeFromRow(row) {
13967
- if (row === null || row === void 0) return null;
13968
- return new GraphNode(
13969
- String(row.id),
13970
- row.labels ?? [],
13971
- row.props ?? {}
13972
- );
13978
+ return nodeFromRow(row);
13973
13979
  }
13974
13980
  async addNode(label, properties = null) {
13975
13981
  const cypher = `CREATE (n:\`${label}\` $props) RETURN id(n) AS id, labels(n) AS labels, properties(n) AS props`;
@@ -13983,15 +13989,7 @@ var init_bolt = __esm({
13983
13989
  to_id: boltId(toId),
13984
13990
  props: properties ?? {}
13985
13991
  });
13986
- if (rows.length === 0) return null;
13987
- const row = rows[0];
13988
- return new GraphEdge(
13989
- String(row.id),
13990
- String(row.type),
13991
- String(row.f),
13992
- String(row.t),
13993
- row.props ?? {}
13994
- );
13992
+ return edgeFromRow(rows[0]);
13995
13993
  }
13996
13994
  async getNode(nodeId) {
13997
13995
  const cypher = `MATCH (n) WHERE id(n) = $id RETURN id(n) AS id, labels(n) AS labels, properties(n) AS props`;
@@ -14057,7 +14055,7 @@ function cleanProps(doc) {
14057
14055
  }
14058
14056
  return props;
14059
14057
  }
14060
- function errorMessage3(exc) {
14058
+ function errorMessage2(exc) {
14061
14059
  if (exc instanceof Error) return exc.message;
14062
14060
  return String(exc);
14063
14061
  }
@@ -14096,14 +14094,14 @@ var init_arango = __esm({
14096
14094
  this.db = new ArangoDatabase(config);
14097
14095
  }
14098
14096
  connectOrError(exc) {
14099
- const text = errorMessage3(exc).toLowerCase();
14097
+ const text = errorMessage2(exc).toLowerCase();
14100
14098
  if (text.includes("timed out") || text.includes("timeout") || text.includes("connection") || text.includes("econnrefused") || text.includes("etimedout") || text.includes("max retries")) {
14101
14099
  return new GraphConnectTimeout(
14102
14100
  `Graph connect to ${this.url.host}:${this.url.port} timed out (${GRAPH_CONNECT_TIMEOUT_VARIABLE}). Raise ${GRAPH_CONNECT_TIMEOUT_VARIABLE} if the server is simply slow, or set it to 0 to wait indefinitely.`,
14103
14101
  exc
14104
14102
  );
14105
14103
  }
14106
- return new GraphError(errorMessage3(exc), exc);
14104
+ return new GraphError(errorMessage2(exc), exc);
14107
14105
  }
14108
14106
  async ensureCollections() {
14109
14107
  if (this.ensured) return;
@@ -14114,7 +14112,7 @@ var init_arango = __esm({
14114
14112
  if (!await edges.exists()) await this.db.createEdgeCollection(EDGE_COLLECTION);
14115
14113
  this.ensured = true;
14116
14114
  } catch (exc) {
14117
- this.lastError = errorMessage3(exc);
14115
+ this.lastError = errorMessage2(exc);
14118
14116
  throw this.connectOrError(exc);
14119
14117
  }
14120
14118
  }
@@ -14124,7 +14122,7 @@ var init_arango = __esm({
14124
14122
  const cursor = await this.db.query({ query, bindVars: bind2 ?? {} });
14125
14123
  return await cursor.all();
14126
14124
  } catch (exc) {
14127
- this.lastError = errorMessage3(exc);
14125
+ this.lastError = errorMessage2(exc);
14128
14126
  throw this.connectOrError(exc);
14129
14127
  }
14130
14128
  }
@@ -22387,6 +22385,21 @@ var init_portTakeover = __esm({
22387
22385
  }
22388
22386
  });
22389
22387
 
22388
+ // src/etag.ts
22389
+ function etagMatches(ifNoneMatch, etag) {
22390
+ const strip = (tag) => tag.trim().replace(/^W\//, "");
22391
+ const target = strip(etag);
22392
+ return ifNoneMatch.split(",").some((candidate) => {
22393
+ const trimmed = candidate.trim();
22394
+ return trimmed === "*" || strip(trimmed) === target;
22395
+ });
22396
+ }
22397
+ var init_etag = __esm({
22398
+ "src/etag.ts"() {
22399
+ "use strict";
22400
+ }
22401
+ });
22402
+
22390
22403
  // src/sessionHandlers/syncBridge.ts
22391
22404
  import { Worker } from "node:worker_threads";
22392
22405
  function getBridge(key, workerSource, workerData) {
@@ -22668,42 +22681,35 @@ var init_respClient = __esm({
22668
22681
  }
22669
22682
  });
22670
22683
 
22671
- // src/sessionHandlers/valkeyHandler.ts
22672
- var ValkeySessionHandler;
22673
- var init_valkeyHandler = __esm({
22674
- "src/sessionHandlers/valkeyHandler.ts"() {
22684
+ // src/sessionHandlers/respSessionHandler.ts
22685
+ var RespSessionHandler;
22686
+ var init_respSessionHandler = __esm({
22687
+ "src/sessionHandlers/respSessionHandler.ts"() {
22675
22688
  "use strict";
22676
22689
  init_respClient();
22677
- ValkeySessionHandler = class {
22678
- host;
22679
- port;
22680
- password;
22681
- prefix;
22682
- db;
22683
- constructor(config) {
22684
- this.host = config?.host ?? process.env.TINA4_SESSION_VALKEY_HOST ?? "127.0.0.1";
22685
- this.port = config?.port ?? (process.env.TINA4_SESSION_VALKEY_PORT ? parseInt(process.env.TINA4_SESSION_VALKEY_PORT, 10) : 6379);
22686
- this.password = config?.password ?? process.env.TINA4_SESSION_VALKEY_PASSWORD ?? "";
22687
- this.prefix = config?.prefix ?? process.env.TINA4_SESSION_VALKEY_PREFIX ?? "tina4:session:";
22688
- this.db = config?.db ?? (process.env.TINA4_SESSION_VALKEY_DB ? parseInt(process.env.TINA4_SESSION_VALKEY_DB, 10) : 0);
22690
+ RespSessionHandler = class {
22691
+ constructor(conn, label) {
22692
+ this.conn = conn;
22693
+ this.label = label;
22689
22694
  }
22695
+ conn;
22696
+ label;
22690
22697
  /**
22691
- * Execute a RESP command synchronously against the live Valkey server.
22698
+ * Execute a RESP command synchronously against the live server.
22692
22699
  *
22693
- * Delegates to the shared {@link respCommandSync} transport: a genuine key miss
22694
- * yields `""`, and a transport/connection FAILURE (server unreachable, rejected
22695
- * AUTH, timeout) THROWS so the Session boundary can distinguish "not found"
22696
- * (silent) from "backend failed" (log-loud + degrade). Backend-failure parity.
22700
+ * Delegates to the shared {@link respCommandSync} transport: a genuine key
22701
+ * miss yields `""`, and a transport/connection FAILURE THROWS so the caller
22702
+ * can distinguish "not found" from "backend failed". Backend-failure parity.
22697
22703
  */
22698
22704
  execSync(args) {
22699
22705
  return respCommandSync(
22700
- { host: this.host, port: this.port, password: this.password, db: this.db },
22706
+ { host: this.conn.host, port: this.conn.port, password: this.conn.password, db: this.conn.db },
22701
22707
  args,
22702
- "Valkey"
22708
+ this.label
22703
22709
  );
22704
22710
  }
22705
22711
  key(sessionId) {
22706
- return `${this.prefix}${sessionId}`;
22712
+ return `${this.conn.prefix}${sessionId}`;
22707
22713
  }
22708
22714
  read(sessionId) {
22709
22715
  const raw = this.execSync(["GET", this.key(sessionId)]);
@@ -22714,7 +22720,7 @@ var init_valkeyHandler = __esm({
22714
22720
  return null;
22715
22721
  }
22716
22722
  }
22717
- write(sessionId, data, ttl) {
22723
+ write(sessionId, data, ttl = 0) {
22718
22724
  const json = JSON.stringify(data);
22719
22725
  if (ttl > 0) {
22720
22726
  this.execSync(["SETEX", this.key(sessionId), String(ttl), json]);
@@ -22729,6 +22735,29 @@ var init_valkeyHandler = __esm({
22729
22735
  }
22730
22736
  });
22731
22737
 
22738
+ // src/sessionHandlers/valkeyHandler.ts
22739
+ var ValkeySessionHandler;
22740
+ var init_valkeyHandler = __esm({
22741
+ "src/sessionHandlers/valkeyHandler.ts"() {
22742
+ "use strict";
22743
+ init_respSessionHandler();
22744
+ ValkeySessionHandler = class extends RespSessionHandler {
22745
+ constructor(config) {
22746
+ super(
22747
+ {
22748
+ host: config?.host ?? process.env.TINA4_SESSION_VALKEY_HOST ?? "127.0.0.1",
22749
+ port: config?.port ?? (process.env.TINA4_SESSION_VALKEY_PORT ? parseInt(process.env.TINA4_SESSION_VALKEY_PORT, 10) : 6379),
22750
+ password: config?.password ?? process.env.TINA4_SESSION_VALKEY_PASSWORD ?? "",
22751
+ prefix: config?.prefix ?? process.env.TINA4_SESSION_VALKEY_PREFIX ?? "tina4:session:",
22752
+ db: config?.db ?? (process.env.TINA4_SESSION_VALKEY_DB ? parseInt(process.env.TINA4_SESSION_VALKEY_DB, 10) : 0)
22753
+ },
22754
+ "Valkey"
22755
+ );
22756
+ }
22757
+ };
22758
+ }
22759
+ });
22760
+
22732
22761
  // src/sessionHandlers/memcachedHandler.ts
22733
22762
  import { createHash as createHash4 } from "node:crypto";
22734
22763
  var MAX_KEY_BYTES, MAX_RELATIVE_EXPTIME, MemcachedSessionHandler;
@@ -23794,7 +23823,7 @@ var init_session = __esm({
23794
23823
  "use strict";
23795
23824
  init_logger();
23796
23825
  init_dotenv();
23797
- init_respClient();
23826
+ init_respSessionHandler();
23798
23827
  init_valkeyHandler();
23799
23828
  init_memcachedHandler();
23800
23829
  init_mongoHandler();
@@ -23920,57 +23949,19 @@ var init_session = __esm({
23920
23949
  }
23921
23950
  }
23922
23951
  };
23923
- RedisSessionHandler = class {
23924
- host;
23925
- port;
23926
- password;
23927
- prefix;
23928
- db;
23952
+ RedisSessionHandler = class extends RespSessionHandler {
23929
23953
  constructor(config) {
23930
- this.host = config?.redisHost ?? process.env.TINA4_SESSION_REDIS_HOST ?? "127.0.0.1";
23931
- this.port = config?.redisPort ?? (process.env.TINA4_SESSION_REDIS_PORT ? parseInt(process.env.TINA4_SESSION_REDIS_PORT, 10) : 6379);
23932
- this.password = config?.redisPassword ?? process.env.TINA4_SESSION_REDIS_PASSWORD ?? "";
23933
- this.prefix = config?.redisPrefix ?? process.env.TINA4_SESSION_REDIS_PREFIX ?? "tina4:session:";
23934
- this.db = config?.redisDb ?? (process.env.TINA4_SESSION_REDIS_DB ? parseInt(process.env.TINA4_SESSION_REDIS_DB, 10) : 0);
23935
- }
23936
- /**
23937
- * Execute a Redis command synchronously against the live server.
23938
- *
23939
- * Delegates to the shared {@link respCommandSync} transport: a genuine key miss
23940
- * yields `""`, and a transport/connection FAILURE (server unreachable, rejected
23941
- * AUTH, timeout) THROWS so the Session boundary can distinguish "not found"
23942
- * (silent) from "backend failed" (log-loud + degrade). Backend-failure parity.
23943
- */
23944
- execSync(args) {
23945
- return respCommandSync(
23946
- { host: this.host, port: this.port, password: this.password, db: this.db },
23947
- args,
23954
+ super(
23955
+ {
23956
+ host: config?.redisHost ?? process.env.TINA4_SESSION_REDIS_HOST ?? "127.0.0.1",
23957
+ port: config?.redisPort ?? (process.env.TINA4_SESSION_REDIS_PORT ? parseInt(process.env.TINA4_SESSION_REDIS_PORT, 10) : 6379),
23958
+ password: config?.redisPassword ?? process.env.TINA4_SESSION_REDIS_PASSWORD ?? "",
23959
+ prefix: config?.redisPrefix ?? process.env.TINA4_SESSION_REDIS_PREFIX ?? "tina4:session:",
23960
+ db: config?.redisDb ?? (process.env.TINA4_SESSION_REDIS_DB ? parseInt(process.env.TINA4_SESSION_REDIS_DB, 10) : 0)
23961
+ },
23948
23962
  "Redis"
23949
23963
  );
23950
23964
  }
23951
- key(sessionId) {
23952
- return `${this.prefix}${sessionId}`;
23953
- }
23954
- read(sessionId) {
23955
- const raw = this.execSync(["GET", this.key(sessionId)]);
23956
- if (!raw) return null;
23957
- try {
23958
- return JSON.parse(raw);
23959
- } catch {
23960
- return null;
23961
- }
23962
- }
23963
- write(sessionId, data, ttl = 0) {
23964
- const json = JSON.stringify(data);
23965
- if (ttl > 0) {
23966
- this.execSync(["SETEX", this.key(sessionId), String(ttl), json]);
23967
- } else {
23968
- this.execSync(["SET", this.key(sessionId), json]);
23969
- }
23970
- }
23971
- destroy(sessionId) {
23972
- this.execSync(["DEL", this.key(sessionId)]);
23973
- }
23974
23965
  };
23975
23966
  FLASH_PREFIX = "_flash_";
23976
23967
  Session = class {
@@ -24380,14 +24371,6 @@ function headStripIntercept(rawReq, rawRes) {
24380
24371
  function isCompressibleContentType(contentType) {
24381
24372
  return COMPRESSIBLE_PREFIXES.some((prefix) => contentType.includes(prefix));
24382
24373
  }
24383
- function etagMatchesInm(ifNoneMatch, etag) {
24384
- const strip = (tag) => tag.trim().replace(/^W\//, "");
24385
- const target = strip(etag);
24386
- return ifNoneMatch.split(",").some((candidate) => {
24387
- const trimmed = candidate.trim();
24388
- return trimmed === "*" || strip(trimmed) === target;
24389
- });
24390
- }
24391
24374
  function maybeCompressResponse(body, rawReq, rawRes) {
24392
24375
  const acceptEncoding = String(rawReq.headers["accept-encoding"] ?? "");
24393
24376
  const contentTypeHeader = rawRes.getHeader("content-type");
@@ -24403,7 +24386,7 @@ function maybeCompressResponse(body, rawReq, rawRes) {
24403
24386
  }
24404
24387
  function responseIsNotModified(rawReq, rawRes, etag) {
24405
24388
  const ifNoneMatch = String(rawReq.headers["if-none-match"] ?? "");
24406
- if (ifNoneMatch) return etagMatchesInm(ifNoneMatch, etag);
24389
+ if (ifNoneMatch) return etagMatches(ifNoneMatch, etag);
24407
24390
  const lastModifiedHeader = rawRes.getHeader("last-modified");
24408
24391
  if (typeof lastModifiedHeader !== "string") return false;
24409
24392
  const ifModifiedSince = String(rawReq.headers["if-modified-since"] ?? "");
@@ -24531,6 +24514,7 @@ var init_dispatchPipeline = __esm({
24531
24514
  "src/dispatchPipeline.ts"() {
24532
24515
  "use strict";
24533
24516
  init_logger();
24517
+ init_etag();
24534
24518
  COMPRESSIBLE_PREFIXES = [
24535
24519
  "text/",
24536
24520
  "application/json",
@@ -24626,18 +24610,11 @@ function isNotModified(req2, etag, stat) {
24626
24610
  }
24627
24611
  return false;
24628
24612
  }
24629
- function etagMatches(ifNoneMatch, etag) {
24630
- const strip = (tag) => tag.trim().replace(/^W\//, "");
24631
- const target = strip(etag);
24632
- return ifNoneMatch.split(",").some((candidate) => {
24633
- const trimmed = candidate.trim();
24634
- return trimmed === "*" || strip(trimmed) === target;
24635
- });
24636
- }
24637
24613
  var COMPRESSIBLE_PREFIXES2, MIME_TYPES;
24638
24614
  var init_static = __esm({
24639
24615
  "src/static.ts"() {
24640
24616
  "use strict";
24617
+ init_etag();
24641
24618
  COMPRESSIBLE_PREFIXES2 = [
24642
24619
  "text/",
24643
24620
  "application/json",
@@ -25214,6 +25191,25 @@ Generated by DevMailbox.seed() for development purposes.`,
25214
25191
  }
25215
25192
  });
25216
25193
 
25194
+ // src/upstreamResponse.ts
25195
+ async function relayUpstreamResponse(res, upstream) {
25196
+ const raw = await upstream.text();
25197
+ const status2 = upstream.status || 200;
25198
+ try {
25199
+ res.json(JSON.parse(raw), status2);
25200
+ } catch {
25201
+ res.raw.writeHead(status2, {
25202
+ "Content-Type": upstream.headers.get("content-type") ?? "text/plain; charset=utf-8"
25203
+ });
25204
+ res.raw.end(raw);
25205
+ }
25206
+ }
25207
+ var init_upstreamResponse = __esm({
25208
+ "src/upstreamResponse.ts"() {
25209
+ "use strict";
25210
+ }
25211
+ });
25212
+
25217
25213
  // src/metrics.ts
25218
25214
  import * as fs3 from "node:fs";
25219
25215
  import * as path2 from "node:path";
@@ -25429,6 +25425,7 @@ var init_feedback = __esm({
25429
25425
  "use strict";
25430
25426
  init_auth();
25431
25427
  init_devAdmin();
25428
+ init_upstreamResponse();
25432
25429
  RATE_LIMIT_WINDOW_SEC = 3600;
25433
25430
  RATE_LIMIT_MAX = 5;
25434
25431
  _rateLimitHits = /* @__PURE__ */ new Map();
@@ -25475,16 +25472,7 @@ var init_feedback = __esm({
25475
25472
  return;
25476
25473
  }
25477
25474
  clearTimeout(timer);
25478
- const raw = await upstream.text();
25479
- const status2 = upstream.status || 200;
25480
- try {
25481
- res.json(JSON.parse(raw), status2);
25482
- } catch {
25483
- res.raw.writeHead(status2, {
25484
- "Content-Type": upstream.headers.get("content-type") ?? "text/plain; charset=utf-8"
25485
- });
25486
- res.raw.end(raw);
25487
- }
25475
+ await relayUpstreamResponse(res, upstream);
25488
25476
  };
25489
25477
  __feedbackDirname = dirname7(fileURLToPath2(import.meta.url));
25490
25478
  WIDGET_BUNDLE_PATH = resolve9(__feedbackDirname, "__feedback", "widget.js");
@@ -25534,6 +25522,38 @@ var init_version = __esm({
25534
25522
  }
25535
25523
  });
25536
25524
 
25525
+ // ../cli/src/util.ts
25526
+ function parseFlags(args, booleanFlags) {
25527
+ const flags = {};
25528
+ const positional = [];
25529
+ let i = 0;
25530
+ while (i < args.length) {
25531
+ const arg = args[i];
25532
+ if (arg.startsWith("--")) {
25533
+ const key = arg.slice(2);
25534
+ if (booleanFlags?.has(key)) {
25535
+ flags[key] = true;
25536
+ i += 1;
25537
+ } else if (i + 1 < args.length && !args[i + 1].startsWith("--")) {
25538
+ flags[key] = args[i + 1];
25539
+ i += 2;
25540
+ } else {
25541
+ flags[key] = true;
25542
+ i += 1;
25543
+ }
25544
+ } else {
25545
+ positional.push(arg);
25546
+ i += 1;
25547
+ }
25548
+ }
25549
+ return { flags, positional };
25550
+ }
25551
+ var init_util = __esm({
25552
+ "../cli/src/util.ts"() {
25553
+ "use strict";
25554
+ }
25555
+ });
25556
+
25537
25557
  // ../cli/src/commands/generate.ts
25538
25558
  var generate_exports = {};
25539
25559
  __export(generate_exports, {
@@ -25798,28 +25818,7 @@ function parseCliArgs(args) {
25798
25818
  "json",
25799
25819
  "dry-run"
25800
25820
  ]);
25801
- const flags = {};
25802
- const positional = [];
25803
- let i = 0;
25804
- while (i < args.length) {
25805
- if (args[i].startsWith("--")) {
25806
- const key = args[i].slice(2);
25807
- if (booleanFlags.has(key)) {
25808
- flags[key] = true;
25809
- i += 1;
25810
- } else if (i + 1 < args.length && !args[i + 1].startsWith("--")) {
25811
- flags[key] = args[i + 1];
25812
- i += 2;
25813
- } else {
25814
- flags[key] = true;
25815
- i += 1;
25816
- }
25817
- } else {
25818
- positional.push(args[i]);
25819
- i += 1;
25820
- }
25821
- }
25822
- return { flags, positional };
25821
+ return parseFlags(args, booleanFlags);
25823
25822
  }
25824
25823
  function parseEvery(every) {
25825
25824
  if (!every || every === true) return 60;
@@ -27380,6 +27379,7 @@ var FIELD_TYPE_MAP, SQL_RESERVED_TABLE_NAMES, RESOLUTION_ENVELOPE_VERSION, __res
27380
27379
  var init_generate = __esm({
27381
27380
  "../cli/src/commands/generate.ts"() {
27382
27381
  "use strict";
27382
+ init_util();
27383
27383
  FIELD_TYPE_MAP = {
27384
27384
  string: { orm: '"string"', sql: "VARCHAR(255)", defaultVal: "''" },
27385
27385
  str: { orm: '"string"', sql: "VARCHAR(255)", defaultVal: "''" },
@@ -30998,6 +30998,7 @@ __export(websocket_exports, {
30998
30998
  CLOSE_NORMAL: () => CLOSE_NORMAL,
30999
30999
  CLOSE_POLICY_VIOLATION: () => CLOSE_POLICY_VIOLATION,
31000
31000
  CLOSE_PROTOCOL_ERROR: () => CLOSE_PROTOCOL_ERROR,
31001
+ MessageAssembler: () => MessageAssembler,
31001
31002
  OP_BINARY: () => OP_BINARY,
31002
31003
  OP_CLOSE: () => OP_CLOSE,
31003
31004
  OP_CONTINUATION: () => OP_CONTINUATION,
@@ -31255,21 +31256,24 @@ function serveWebSocketRoute(req2, socket, head) {
31255
31256
  state.closed = true;
31256
31257
  void Promise.resolve().then(() => conn._onClose ? conn._onClose() : handler(conn, "close", "")).catch((e) => Log.error(`WebSocket close handler error: ${e.message}`)).finally(() => wsRouteManager.remove(conn.id));
31257
31258
  };
31259
+ const assembler = new MessageAssembler();
31258
31260
  socket.on("data", (chunk) => {
31259
31261
  buffer = Buffer.concat([buffer, chunk]);
31260
31262
  while (buffer.length > 0) {
31261
31263
  const frame = parseFrame(buffer);
31262
31264
  if (!frame) break;
31263
31265
  buffer = buffer.subarray(frame.bytesConsumed);
31264
- switch (frame.opcode) {
31266
+ const whole = assembler.push(frame);
31267
+ if (!whole) continue;
31268
+ switch (whole.opcode) {
31265
31269
  case OP_TEXT: {
31266
- const text = frame.payload.toString("utf-8");
31270
+ const text = whole.payload.toString("utf-8");
31267
31271
  void Promise.resolve().then(() => conn._onMessage ? conn._onMessage(text) : handler(conn, "message", text)).catch((e) => Log.error(`WebSocket message handler error: ${e.message}`));
31268
31272
  break;
31269
31273
  }
31270
31274
  case OP_PING:
31271
31275
  try {
31272
- socket.write(buildFrame(OP_PONG, frame.payload));
31276
+ socket.write(buildFrame(OP_PONG, whole.payload));
31273
31277
  } catch {
31274
31278
  }
31275
31279
  break;
@@ -31288,7 +31292,7 @@ function serveWebSocketRoute(req2, socket, head) {
31288
31292
  socket.on("error", fireClose);
31289
31293
  return true;
31290
31294
  }
31291
- var MAGIC_STRING, OP_CONTINUATION, OP_TEXT, OP_BINARY, OP_CLOSE, OP_PING, OP_PONG, CLOSE_NORMAL, CLOSE_GOING_AWAY, CLOSE_PROTOCOL_ERROR, CLOSE_POLICY_VIOLATION, WebSocketServer, WsRouteManager, wsRouteManager, DevReloadWsManager, devReloadWs;
31295
+ var MAGIC_STRING, OP_CONTINUATION, OP_TEXT, OP_BINARY, OP_CLOSE, OP_PING, OP_PONG, CLOSE_NORMAL, CLOSE_GOING_AWAY, CLOSE_PROTOCOL_ERROR, CLOSE_POLICY_VIOLATION, MessageAssembler, WebSocketServer, WsRouteManager, wsRouteManager, DevReloadWsManager, devReloadWs;
31292
31296
  var init_websocket = __esm({
31293
31297
  "src/websocket.ts"() {
31294
31298
  "use strict";
@@ -31307,6 +31311,30 @@ var init_websocket = __esm({
31307
31311
  CLOSE_GOING_AWAY = 1001;
31308
31312
  CLOSE_PROTOCOL_ERROR = 1002;
31309
31313
  CLOSE_POLICY_VIOLATION = 1008;
31314
+ MessageAssembler = class {
31315
+ parts = [];
31316
+ opcode = 0;
31317
+ push(frame) {
31318
+ if (frame.opcode >= 8) return { opcode: frame.opcode, payload: frame.payload };
31319
+ if (frame.opcode === OP_CONTINUATION) {
31320
+ if (!this.opcode) return null;
31321
+ this.parts.push(frame.payload);
31322
+ if (!frame.fin) return null;
31323
+ const whole = { opcode: this.opcode, payload: Buffer.concat(this.parts) };
31324
+ this.parts = [];
31325
+ this.opcode = 0;
31326
+ return whole;
31327
+ }
31328
+ if (frame.fin) {
31329
+ this.parts = [];
31330
+ this.opcode = 0;
31331
+ return { opcode: frame.opcode, payload: frame.payload };
31332
+ }
31333
+ this.opcode = frame.opcode;
31334
+ this.parts = [frame.payload];
31335
+ return null;
31336
+ }
31337
+ };
31310
31338
  WebSocketServer = class {
31311
31339
  port;
31312
31340
  server = null;
@@ -31749,6 +31777,15 @@ var init_websocket = __esm({
31749
31777
  this.emit("error", err, client);
31750
31778
  });
31751
31779
  }
31780
+ assemblers = /* @__PURE__ */ new WeakMap();
31781
+ assemblerFor(client) {
31782
+ let a = this.assemblers.get(client);
31783
+ if (!a) {
31784
+ a = new MessageAssembler();
31785
+ this.assemblers.set(client, a);
31786
+ }
31787
+ return a;
31788
+ }
31752
31789
  processBuffer(client, buffer, setBuffer) {
31753
31790
  let remaining = buffer;
31754
31791
  while (remaining.length > 0) {
@@ -31756,15 +31793,17 @@ var init_websocket = __esm({
31756
31793
  if (!frame) break;
31757
31794
  remaining = remaining.subarray(frame.bytesConsumed);
31758
31795
  client.lastActivity = Date.now();
31759
- switch (frame.opcode) {
31796
+ const whole = this.assemblerFor(client).push(frame);
31797
+ if (!whole) continue;
31798
+ switch (whole.opcode) {
31760
31799
  case OP_TEXT:
31761
- this.emit("message", client, frame.payload.toString("utf-8"));
31800
+ this.emit("message", client, whole.payload.toString("utf-8"));
31762
31801
  break;
31763
31802
  case OP_BINARY:
31764
- this.emit("message", client, frame.payload);
31803
+ this.emit("message", client, whole.payload);
31765
31804
  break;
31766
31805
  case OP_PING: {
31767
- const pongFrame = buildFrame(OP_PONG, frame.payload);
31806
+ const pongFrame = buildFrame(OP_PONG, whole.payload);
31768
31807
  try {
31769
31808
  client.socket.write(pongFrame);
31770
31809
  } catch {
@@ -36142,16 +36181,7 @@ async function proxyToSupervisor(req2, res, downstreamPath) {
36142
36181
  return;
36143
36182
  }
36144
36183
  clearTimeout(timer);
36145
- const raw = await upstream.text();
36146
- const status2 = upstream.status || 200;
36147
- try {
36148
- res.json(JSON.parse(raw), status2);
36149
- } catch {
36150
- res.raw.writeHead(status2, {
36151
- "Content-Type": upstream.headers.get("content-type") ?? "text/plain; charset=utf-8"
36152
- });
36153
- res.raw.end(raw);
36154
- }
36184
+ await relayUpstreamResponse(res, upstream);
36155
36185
  }
36156
36186
  function resolveDevEnvVar(key) {
36157
36187
  const live = process.env[key];
@@ -36593,6 +36623,7 @@ var init_devAdmin = __esm({
36593
36623
  "src/devAdmin.ts"() {
36594
36624
  "use strict";
36595
36625
  init_devMailbox();
36626
+ init_upstreamResponse();
36596
36627
  init_dotenv();
36597
36628
  init_metrics();
36598
36629
  init_feedback();