@everystack/server 0.4.35 → 0.4.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,12 @@ All notable changes to `@everystack/server` are documented here.
4
4
 
5
5
  Format based on [Keep a Changelog](https://keepachangelog.com/).
6
6
 
7
+ ## [0.4.36] - 2026-10-18
8
+
9
+ ### Fixed
10
+
11
+ - the Lambda entry strips edge query params (_v by default) before routing
12
+
7
13
  ## [0.4.35] - 2026-10-14
8
14
 
9
15
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@everystack/server",
3
- "version": "0.4.35",
3
+ "version": "0.4.36",
4
4
  "description": "Server runtime primitives for Lambda — event adapters, routing, SSR, image processing",
5
5
  "license": "AGPL-3.0-only",
6
6
  "author": "Scalable Technology, Inc. <licensing@scalable.technology>",
@@ -192,8 +192,8 @@
192
192
  "sst": "4.13.1",
193
193
  "ts-jest": "29.4.9",
194
194
  "typescript": "5.9.3",
195
- "@everystack/auth": "0.4.9",
196
- "@everystack/cli": "0.4.99"
195
+ "@everystack/cli": "0.4.100",
196
+ "@everystack/auth": "0.4.9"
197
197
  },
198
198
  "scripts": {
199
199
  "test": "jest",
package/src/index.ts CHANGED
@@ -17,6 +17,7 @@ import type {
17
17
 
18
18
  import { log } from './log';
19
19
  import { buildTimingHeaders } from './timing';
20
+ import { DEFAULT_STRIP_QUERY_PARAMS, stripQueryParams } from './strip-query-params';
20
21
 
21
22
  export { buildTimingHeaders } from './timing';
22
23
  export type { TimingHeaderOptions } from './timing';
@@ -99,6 +100,13 @@ export interface LambdaHandlerOptions {
99
100
  logSink?: LogSink;
100
101
  /** Emit Server-Timing headers on responses. Default true. */
101
102
  observability?: boolean;
103
+ /**
104
+ * Query params removed from every HTTP request before routing, matched by decoded name whatever
105
+ * the value. The CDN edge appends `?_v=<epoch>` and CloudFront forwards the whole query string,
106
+ * so without this the REST handler would answer 400 to a param with no operator. List any params
107
+ * your own edge adds. Default `['_v']`; `[]` disables stripping.
108
+ */
109
+ stripQueryParams?: string[];
102
110
  }
103
111
 
104
112
  // --- Event Adapter ---
@@ -256,7 +264,10 @@ export function createLambdaHandler(
256
264
 
257
265
  try {
258
266
  const { router } = await ensureInitialized();
259
- const request = eventToRequest(httpEvent);
267
+ const request = stripQueryParams(
268
+ eventToRequest(httpEvent),
269
+ options.stripQueryParams ?? DEFAULT_STRIP_QUERY_PARAMS,
270
+ );
260
271
  const path = httpEvent.rawPath;
261
272
  const method = httpEvent.requestContext.http.method;
262
273
  const handlerFn = router(path, method);
package/src/plugin.ts CHANGED
@@ -36,6 +36,7 @@ import {
36
36
  log,
37
37
  } from './index';
38
38
  import { splitSqlStatements, stripSqlComments } from './sql-lex';
39
+ import { DEFAULT_STRIP_QUERY_PARAMS, stripQueryParams } from './strip-query-params';
39
40
 
40
41
  // --- Plugin Types ---
41
42
 
@@ -138,6 +139,13 @@ export interface PluginLambdaHandlerOptions {
138
139
  * here, not in the HTTP-facing API function.
139
140
  */
140
141
  http?: boolean;
142
+ /**
143
+ * Query params removed from every HTTP request before routing, matched by decoded name whatever
144
+ * the value. The CDN edge appends `?_v=<epoch>` and CloudFront forwards the whole query string,
145
+ * so without this the REST handler would answer 400 to a param with no operator. List any params
146
+ * your own edge adds. Default `['_v']`; `[]` disables stripping.
147
+ */
148
+ stripQueryParams?: string[];
141
149
  }
142
150
 
143
151
  // --- Plugin Lambda Handler Implementation ---
@@ -272,7 +280,10 @@ export function createPluginLambdaHandler(
272
280
 
273
281
  try {
274
282
  const { router, logSink } = await ensureInitialized();
275
- const request = eventToRequest(httpEvent);
283
+ const request = stripQueryParams(
284
+ eventToRequest(httpEvent),
285
+ options.stripQueryParams ?? DEFAULT_STRIP_QUERY_PARAMS,
286
+ );
276
287
  const path = httpEvent.rawPath;
277
288
  const method = httpEvent.requestContext.http.method;
278
289
  const handlerFn = router!(path, method);
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Internal (not exported from the package): removes edge-added query params from a Request before
3
+ * routing. Both Lambda entry points (createLambdaHandler, createPluginLambdaHandler) call it right
4
+ * after eventToRequest.
5
+ */
6
+
7
+ /** The CDN edge's cache-version param (cacheVersionFeature, docs/caching.md). */
8
+ export const DEFAULT_STRIP_QUERY_PARAMS: readonly string[] = ['_v'];
9
+
10
+ /** Decodes a raw query-pair name the way a form-encoded parser does; null if it cannot decode. */
11
+ function decodeName(raw: string): string | null {
12
+ try {
13
+ return decodeURIComponent(raw.replace(/\+/g, ' '));
14
+ } catch {
15
+ return null;
16
+ }
17
+ }
18
+
19
+ /**
20
+ * Returns `request` with every query pair whose decoded name is in `names` removed. The kept pairs
21
+ * keep their exact bytes and order (no URLSearchParams re-serialization). When nothing is removed
22
+ * the same Request object is returned; otherwise a new Request carries the original method,
23
+ * headers and body.
24
+ */
25
+ export function stripQueryParams(request: Request, names: readonly string[]): Request {
26
+ if (names.length === 0) return request;
27
+ const url = request.url;
28
+ const q = url.indexOf('?');
29
+ if (q === -1) return request;
30
+
31
+ const pairs = url.slice(q + 1).split('&');
32
+ const kept = pairs.filter((pair) => {
33
+ const eq = pair.indexOf('=');
34
+ const name = decodeName(eq === -1 ? pair : pair.slice(0, eq));
35
+ return name === null || !names.includes(name);
36
+ });
37
+ if (kept.length === pairs.length) return request;
38
+
39
+ const query = kept.join('&');
40
+ return new Request(url.slice(0, q) + (query ? '?' + query : ''), request);
41
+ }