@farm.js/plugin 0.1.0-beta.58 → 0.1.0-beta.59

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/dist/index.d.ts CHANGED
@@ -39,5 +39,5 @@
39
39
  * })
40
40
  * ```
41
41
  */
42
- export declare const version = "0.1.0-beta.58";
42
+ export declare const version = "0.1.0-beta.59";
43
43
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -39,7 +39,7 @@
39
39
  * })
40
40
  * ```
41
41
  */
42
- export const version = "0.1.0-beta.58";
42
+ export const version = "0.1.0-beta.59";
43
43
  // Note: Import plugins from their respective subpaths:
44
44
  // - @farm.js/plugin/rsc
45
45
  // - @farm.js/plugin/middleware
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/middleware/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/middleware/index.ts"],"names":[],"mappings":"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"}
@@ -16,6 +16,7 @@
16
16
  import { createRequire } from "node:module";
17
17
  import { _withAfterNodeMiddleware } from "@farm.js/core/after";
18
18
  import { devServableFileExists } from "../dev-static.js";
19
+ import { middlewareMatchesPath, parseCookies, serializeCookie } from "./matching.js";
19
20
  // Create require for ESM compatibility
20
21
  const require_ = createRequire(import.meta.url);
21
22
  // Get picocolors with forced color support (to handle NO_COLOR env being set)
@@ -43,52 +44,6 @@ const getColors = () => {
43
44
  magenta: id,
44
45
  };
45
46
  };
46
- /**
47
- * Parse cookies from Cookie header
48
- */
49
- function parseCookies(cookieHeader) {
50
- if (!cookieHeader)
51
- return {};
52
- return cookieHeader.split(";").reduce((cookies, cookie) => {
53
- const [name, ...rest] = cookie.split("=");
54
- const value = rest.join("=").trim();
55
- if (name && value) {
56
- cookies[name.trim()] = decodeURIComponent(value);
57
- }
58
- return cookies;
59
- }, {});
60
- }
61
- /**
62
- * Serialize a cookie
63
- */
64
- function serializeCookie(name, value, options = {}) {
65
- let cookie = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;
66
- if (options.maxAge) {
67
- cookie += `; Max-Age=${options.maxAge}`;
68
- }
69
- if (options.expires) {
70
- cookie += `; Expires=${options.expires.toUTCString()}`;
71
- }
72
- if (options.path) {
73
- cookie += `; Path=${options.path}`;
74
- }
75
- else {
76
- cookie += "; Path=/";
77
- }
78
- if (options.domain) {
79
- cookie += `; Domain=${options.domain}`;
80
- }
81
- if (options.secure) {
82
- cookie += "; Secure";
83
- }
84
- if (options.httpOnly) {
85
- cookie += "; HttpOnly";
86
- }
87
- if (options.sameSite) {
88
- cookie += `; SameSite=${options.sameSite.charAt(0).toUpperCase() + options.sameSite.slice(1)}`;
89
- }
90
- return cookie;
91
- }
92
47
  /**
93
48
  * Create a cookie jar for managing cookies
94
49
  */
@@ -294,11 +249,7 @@ export default function farmMiddleware(options = {}) {
294
249
  }
295
250
  // Find applicable middleware (cascading from root to specific)
296
251
  const applicable = Array.from(middlewareCache.values())
297
- .filter((mw) => {
298
- if (mw.path === "/")
299
- return true;
300
- return pathname.startsWith(mw.path) || pathname === mw.path;
301
- })
252
+ .filter((mw) => middlewareMatchesPath(pathname, mw.path))
302
253
  .sort((a, b) => a.path.split("/").length - b.path.split("/").length);
303
254
  if (applicable.length === 0)
304
255
  return false;
@@ -0,0 +1,29 @@
1
+ import type { CookieOptions } from "./index.js";
2
+ /**
3
+ * Parse cookies from a Cookie header.
4
+ *
5
+ * A single request cookie whose value is not valid UTF-8 percent-encoding
6
+ * (a latin-1 value from an old link, a crawler, or a bare `%`) must not take
7
+ * the whole map down: an unguarded `decodeURIComponent` throws `URIError`,
8
+ * which — because the middleware runner swallows the throw and calls `next()` —
9
+ * would silently skip every middleware for that request (a dev-time auth
10
+ * bypass). Decoding falls back to the raw value per entry instead.
11
+ */
12
+ export declare function parseCookies(cookieHeader?: string): Record<string, string>;
13
+ /**
14
+ * Whether a middleware registered at `middlewarePath` applies to `pathname`.
15
+ *
16
+ * Matching is by path segment, not raw string prefix: middleware at `/admin`
17
+ * covers `/admin` and everything under `/admin/`, but not sibling routes like
18
+ * `/administrator` or `/admin-public` that merely share a textual prefix.
19
+ */
20
+ export declare function middlewareMatchesPath(pathname: string, middlewarePath: string): boolean;
21
+ /**
22
+ * Serialize a cookie.
23
+ *
24
+ * `Max-Age=0` is the canonical immediate-expiry directive, so the attribute is
25
+ * emitted whenever `maxAge` is provided — a `0` must not be dropped the way a
26
+ * plain truthiness check would drop it.
27
+ */
28
+ export declare function serializeCookie(name: string, value: string, options?: CookieOptions): string;
29
+ //# sourceMappingURL=matching.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matching.d.ts","sourceRoot":"","sources":["../../src/middleware/matching.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAc1E;AAUD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAIvF;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,MAAM,CAkChG"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Parse cookies from a Cookie header.
3
+ *
4
+ * A single request cookie whose value is not valid UTF-8 percent-encoding
5
+ * (a latin-1 value from an old link, a crawler, or a bare `%`) must not take
6
+ * the whole map down: an unguarded `decodeURIComponent` throws `URIError`,
7
+ * which — because the middleware runner swallows the throw and calls `next()` —
8
+ * would silently skip every middleware for that request (a dev-time auth
9
+ * bypass). Decoding falls back to the raw value per entry instead.
10
+ */
11
+ export function parseCookies(cookieHeader) {
12
+ if (!cookieHeader)
13
+ return {};
14
+ return cookieHeader.split(";").reduce((cookies, cookie) => {
15
+ const [name, ...rest] = cookie.split("=");
16
+ const value = rest.join("=").trim();
17
+ if (name && value) {
18
+ cookies[name.trim()] = decodeCookieValue(value);
19
+ }
20
+ return cookies;
21
+ }, {});
22
+ }
23
+ function decodeCookieValue(value) {
24
+ try {
25
+ return decodeURIComponent(value);
26
+ }
27
+ catch {
28
+ return value;
29
+ }
30
+ }
31
+ /**
32
+ * Whether a middleware registered at `middlewarePath` applies to `pathname`.
33
+ *
34
+ * Matching is by path segment, not raw string prefix: middleware at `/admin`
35
+ * covers `/admin` and everything under `/admin/`, but not sibling routes like
36
+ * `/administrator` or `/admin-public` that merely share a textual prefix.
37
+ */
38
+ export function middlewareMatchesPath(pathname, middlewarePath) {
39
+ if (middlewarePath === "/")
40
+ return true;
41
+ if (pathname === middlewarePath)
42
+ return true;
43
+ return pathname.startsWith(`${middlewarePath}/`);
44
+ }
45
+ /**
46
+ * Serialize a cookie.
47
+ *
48
+ * `Max-Age=0` is the canonical immediate-expiry directive, so the attribute is
49
+ * emitted whenever `maxAge` is provided — a `0` must not be dropped the way a
50
+ * plain truthiness check would drop it.
51
+ */
52
+ export function serializeCookie(name, value, options = {}) {
53
+ let cookie = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;
54
+ if (options.maxAge != null) {
55
+ cookie += `; Max-Age=${options.maxAge}`;
56
+ }
57
+ if (options.expires) {
58
+ cookie += `; Expires=${options.expires.toUTCString()}`;
59
+ }
60
+ if (options.path) {
61
+ cookie += `; Path=${options.path}`;
62
+ }
63
+ else {
64
+ cookie += "; Path=/";
65
+ }
66
+ if (options.domain) {
67
+ cookie += `; Domain=${options.domain}`;
68
+ }
69
+ if (options.secure) {
70
+ cookie += "; Secure";
71
+ }
72
+ if (options.httpOnly) {
73
+ cookie += "; HttpOnly";
74
+ }
75
+ if (options.sameSite) {
76
+ cookie += `; SameSite=${options.sameSite.charAt(0).toUpperCase() + options.sameSite.slice(1)}`;
77
+ }
78
+ return cookie;
79
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farm.js/plugin",
3
- "version": "0.1.0-beta.58",
3
+ "version": "0.1.0-beta.59",
4
4
  "description": "Official plugins for Farm.js framework",
5
5
  "license": "MIT",
6
6
  "author": "Farm.js Team",
@@ -61,7 +61,7 @@
61
61
  "nitro": "3.0.1-alpha.0",
62
62
  "picocolors": "^1.0.0",
63
63
  "rsc-html-stream": "^0.0.4",
64
- "@farm.js/core": "0.1.0-beta.58"
64
+ "@farm.js/core": "0.1.0-beta.59"
65
65
  },
66
66
  "devDependencies": {
67
67
  "@types/node": "^20.19.21",
@@ -82,7 +82,7 @@
82
82
  "react-dom": "19.2.8",
83
83
  "react-server-dom-webpack": "19.2.8",
84
84
  "vite": ">=6.0.0",
85
- "@farm.js/core": "0.1.0-beta.58"
85
+ "@farm.js/core": "0.1.0-beta.59"
86
86
  },
87
87
  "peerDependenciesMeta": {
88
88
  "@vitejs/plugin-rsc": {