@timber-js/app 0.1.44 → 0.1.46

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.
@@ -6,14 +6,19 @@
6
6
  export declare const COMPRESSIBLE_TYPES: Set<string>;
7
7
  /**
8
8
  * Parse Accept-Encoding and return the best supported encoding.
9
- * Prefers brotli (br) over gzip. Returns null if no supported encoding.
9
+ * Returns 'gzip' if the client accepts it, null otherwise.
10
10
  *
11
- * We always prefer brotli regardless of quality values because:
12
- * 1. Brotli achieves better compression ratios than gzip
13
- * 2. All modern browsers that send br in Accept-Encoding support it well
14
- * 3. Respecting q-values for br vs gzip adds complexity with no real benefit
11
+ * Brotli (br) is intentionally not handled at the application level.
12
+ * At the streaming-friendly quality levels (0–4), brotli's compression
13
+ * ratio advantage over gzip is marginal, and node:zlib's brotli transform
14
+ * buffers output internally turning smooth streaming responses into
15
+ * large infrequent bursts. Brotli's real wins come from offline/static
16
+ * compression at higher quality levels (5–11), which CDNs and reverse
17
+ * proxies (Cloudflare, nginx, Caddy) apply on cached responses.
18
+ *
19
+ * See design/25-production-deployments.md.
15
20
  */
16
- export declare function negotiateEncoding(acceptEncoding: string): 'br' | 'gzip' | null;
21
+ export declare function negotiateEncoding(acceptEncoding: string): 'gzip' | null;
17
22
  /**
18
23
  * Determine if a response should be compressed.
19
24
  *
@@ -1 +1 @@
1
- {"version":3,"file":"compress.d.ts","sourceRoot":"","sources":["../../src/server/compress.ts"],"names":[],"mappings":"AAaA;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,aAc7B,CAAC;AASH;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAU9E;AAID;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAmB1D;AAID;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,QAAQ,CAmC/E"}
1
+ {"version":3,"file":"compress.d.ts","sourceRoot":"","sources":["../../src/server/compress.ts"],"names":[],"mappings":"AAYA;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,aAc7B,CAAC;AASH;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASvE;AAID;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAmB1D;AAID;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,QAAQ,CAiC/E"}
@@ -787,11 +787,13 @@ function pathnameMatchesPattern(pathname, pattern) {
787
787
  */
788
788
  function createPipeline(config) {
789
789
  const { proxy, matchRoute, render, earlyHints, stripTrailingSlash = true, slowRequestMs = 3e3, enableServerTiming = false, onPipelineError } = config;
790
+ let activeRequests = 0;
790
791
  return async (req) => {
791
792
  const url = new URL(req.url);
792
793
  const method = req.method;
793
794
  const path = url.pathname;
794
795
  const startTime = performance.now();
796
+ activeRequests++;
795
797
  return runWithTraceId(generateTraceId(), async () => {
796
798
  return runWithRequestContext(req, async () => {
797
799
  const runRequest = async () => {
@@ -815,22 +817,30 @@ function createPipeline(config) {
815
817
  result = ensureMutableResponse(result);
816
818
  result.headers.set("Server-Timing", serverTiming);
817
819
  }
820
+ } else {
821
+ const totalMs = Math.round(performance.now() - startTime);
822
+ result = ensureMutableResponse(result);
823
+ result.headers.set("Server-Timing", `total;dur=${totalMs}`);
818
824
  }
819
825
  return result;
820
826
  });
821
827
  const durationMs = Math.round(performance.now() - startTime);
822
828
  const status = response.status;
829
+ const concurrency = activeRequests;
830
+ activeRequests--;
823
831
  logRequestCompleted({
824
832
  method,
825
833
  path,
826
834
  status,
827
- durationMs
835
+ durationMs,
836
+ concurrency
828
837
  });
829
838
  if (slowRequestMs > 0 && durationMs > slowRequestMs) logSlowRequest({
830
839
  method,
831
840
  path,
832
841
  durationMs,
833
- threshold: slowRequestMs
842
+ threshold: slowRequestMs,
843
+ concurrency
834
844
  });
835
845
  return response;
836
846
  };
@@ -977,6 +987,14 @@ function createPipeline(config) {
977
987
  markResponseFlushed();
978
988
  return response;
979
989
  } catch (error) {
990
+ if (error instanceof DenySignal) return new Response(null, { status: error.status });
991
+ if (error instanceof RedirectSignal) {
992
+ responseHeaders.set("Location", error.location);
993
+ return new Response(null, {
994
+ status: error.status,
995
+ headers: responseHeaders
996
+ });
997
+ }
980
998
  logRenderError({
981
999
  method,
982
1000
  path,