@rayselfs/cf-rule-engine 1.6.2 → 1.8.0

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 (41) hide show
  1. package/README.md +29 -3
  2. package/dist/adapters/lambda-edge.d.cts +1 -1
  3. package/dist/adapters/lambda-edge.d.ts +1 -1
  4. package/dist/behaviors/index.cjs +3 -3
  5. package/dist/behaviors/index.js +2 -2
  6. package/dist/behaviors/set-cors-headers.cjs +6 -2
  7. package/dist/behaviors/set-cors-headers.d.cts +39 -38
  8. package/dist/behaviors/set-cors-headers.d.ts +39 -38
  9. package/dist/behaviors/set-cors-headers.js +5 -1
  10. package/dist/behaviors/set-security-headers.cjs +2 -2
  11. package/dist/behaviors/set-security-headers.d.cts +35 -19
  12. package/dist/behaviors/set-security-headers.d.ts +35 -19
  13. package/dist/behaviors/set-security-headers.js +1 -1
  14. package/dist/chunk-3UXNXJ6N.cjs +21 -0
  15. package/dist/{chunk-H2LO6MQG.js → chunk-3VYYXEER.js} +20 -10
  16. package/dist/{chunk-63WIEBQB.cjs → chunk-45SNLNLR.cjs} +20 -10
  17. package/dist/chunk-O4SOSGAP.js +21 -0
  18. package/dist/{chunk-SOBTD7AD.js → chunk-SRA2DFKG.js} +21 -10
  19. package/dist/chunk-WAKA4OJD.cjs +50 -0
  20. package/dist/criteria/header-equals.d.cts +2 -2
  21. package/dist/criteria/header-equals.d.ts +2 -2
  22. package/dist/criteria/index.cjs +12 -12
  23. package/dist/criteria/index.js +12 -12
  24. package/dist/helpers/index.cjs +8 -7
  25. package/dist/helpers/index.js +7 -6
  26. package/dist/helpers/preflight-request.cjs +3 -2
  27. package/dist/helpers/preflight-request.d.cts +5 -4
  28. package/dist/helpers/preflight-request.d.ts +5 -4
  29. package/dist/helpers/preflight-request.js +2 -1
  30. package/dist/helpers/whitelist.cjs +3 -3
  31. package/dist/helpers/whitelist.js +2 -2
  32. package/dist/index.d.cts +1 -1
  33. package/dist/index.d.ts +1 -1
  34. package/dist/{lambda-edge-9xiONGmR.d.cts → lambda-edge-D1NHYwvA.d.cts} +1 -1
  35. package/dist/{lambda-edge-BK3-bFx8.d.ts → lambda-edge-DnIvWFGe.d.ts} +1 -1
  36. package/package.json +1 -1
  37. package/dist/chunk-GK5JX7OM.cjs +0 -39
  38. package/dist/chunk-UI6LKDJI.cjs +0 -19
  39. package/dist/chunk-VQCRSBWL.js +0 -19
  40. package/dist/{chunk-RL7ZETZR.js → chunk-ER2YEZZO.js} +3 -3
  41. package/dist/{chunk-T5EXFHVA.cjs → chunk-MO7HW25R.cjs} +3 -3
package/README.md CHANGED
@@ -29,12 +29,12 @@ export default defineViewerRequest([
29
29
  **viewer-response** — security and CORS headers:
30
30
 
31
31
  ```typescript
32
- import { setSecurityHeaders, setCorsHeaders } from '@rayselfs/cf-rule-engine/behaviors/index'
32
+ import { setSecurityHeaders, setCorsHeaders, ORIGIN_WILDCARD } from '@rayselfs/cf-rule-engine/behaviors/index'
33
33
  import { defineViewerResponse } from '@rayselfs/cf-rule-engine/adapters/viewer-response'
34
34
 
35
35
  export default defineViewerResponse([
36
36
  setSecurityHeaders(),
37
- setCorsHeaders({ allowedOrigins: ['https://www.example.com'] }),
37
+ setCorsHeaders({ allowedOrigins: ORIGIN_WILDCARD }),
38
38
  ])
39
39
  ```
40
40
 
@@ -113,6 +113,31 @@ Use `chain()` when one behavior must see the request mutations (URI rewrite, hea
113
113
  | `imageOptimize(options)` | ✅ | ✅ |
114
114
  | `verifyToken(options)` | ❌ | ✅ |
115
115
 
116
+ ### setCorsHeaders — OriginPolicy
117
+
118
+ `allowedOrigins` accepts an `OriginPolicy` that controls how `Access-Control-Allow-Origin` is set:
119
+
120
+ | Value | Behavior |
121
+ |---|---|
122
+ | `ORIGIN_WILDCARD` (`'*'`) | Static `Access-Control-Allow-Origin: *` — for fully public APIs |
123
+ | `Origin[]` | Compare request `Origin` against the list; echo if matched, skip if not. Supports wildcard subdomains (`https://*.example.com`). |
124
+ | `ORIGIN_ECHO` (`'echo'`) | Echo any request `Origin` if present, skip if none — use with `allowCredentials: true` |
125
+
126
+ ```typescript
127
+ import { setCorsHeaders, ORIGIN_WILDCARD, ORIGIN_ECHO } from '@rayselfs/cf-rule-engine/behaviors/index'
128
+
129
+ // Public API
130
+ setCorsHeaders({ allowedOrigins: ORIGIN_WILDCARD })
131
+
132
+ // Restricted — echo only listed origins
133
+ setCorsHeaders({ allowedOrigins: ['https://*.viverse.com', 'https://sdk-api.viverse.com'] })
134
+
135
+ // Echo any origin (required when allowCredentials: true)
136
+ setCorsHeaders({ allowedOrigins: ORIGIN_ECHO, allowCredentials: true })
137
+ ```
138
+
139
+ `allowedMethods` and `allowedHeaders` are optional — omit to exclude those headers from the response.
140
+
116
141
  ## Helpers (`@rayselfs/cf-rule-engine/helpers/index`)
117
142
 
118
143
  Helpers are pre-configured rule factories that combine multiple criteria and behaviors for common use cases.
@@ -134,9 +159,10 @@ Adds `x-cf-distribution: staging` to the response when the request carries `aws-
134
159
 
135
160
  ```typescript
136
161
  import { stagingIndicator } from '@rayselfs/cf-rule-engine/helpers/index'
162
+ import { setCorsHeaders, ORIGIN_WILDCARD } from '@rayselfs/cf-rule-engine/behaviors/index'
137
163
 
138
164
  defineViewerResponse([
139
- setCorsHeaders({ allowedOrigins: ['https://www.example.com'] }),
165
+ setCorsHeaders({ allowedOrigins: ORIGIN_WILDCARD }),
140
166
  stagingIndicator(),
141
167
  ])
142
168
  ```
@@ -1,2 +1,2 @@
1
1
  import '../core/types.cjs';
2
- export { d as defineViewerRequest, a as defineViewerResponse } from '../lambda-edge-9xiONGmR.cjs';
2
+ export { d as defineViewerRequest, a as defineViewerResponse } from '../lambda-edge-D1NHYwvA.cjs';
@@ -1,2 +1,2 @@
1
1
  import '../core/types.js';
2
- export { d as defineViewerRequest, a as defineViewerResponse } from '../lambda-edge-BK3-bFx8.js';
2
+ export { d as defineViewerRequest, a as defineViewerResponse } from '../lambda-edge-DnIvWFGe.js';
@@ -6,7 +6,7 @@ var _chunkPPUHEL4Hcjs = require('../chunk-PPUHEL4H.cjs');
6
6
  var _chunkB4WEJSEZcjs = require('../chunk-B4WEJSEZ.cjs');
7
7
 
8
8
 
9
- var _chunkUI6LKDJIcjs = require('../chunk-UI6LKDJI.cjs');
9
+ var _chunk3UXNXJ6Ncjs = require('../chunk-3UXNXJ6N.cjs');
10
10
 
11
11
 
12
12
  var _chunkMSES76XKcjs = require('../chunk-MSES76XK.cjs');
@@ -27,7 +27,7 @@ var _chunkMRPTC74Icjs = require('../chunk-MRPTC74I.cjs');
27
27
  var _chunkCV234DQTcjs = require('../chunk-CV234DQT.cjs');
28
28
 
29
29
 
30
- var _chunkGK5JX7OMcjs = require('../chunk-GK5JX7OM.cjs');
30
+ var _chunkWAKA4OJDcjs = require('../chunk-WAKA4OJD.cjs');
31
31
 
32
32
 
33
33
  var _chunkZXS23HXAcjs = require('../chunk-ZXS23HXA.cjs');
@@ -123,4 +123,4 @@ function verifyToken(options) {
123
123
 
124
124
 
125
125
 
126
- exports.constructResponse = _chunkOSGZTNTScjs.constructResponse; exports.copyHeader = _chunkJU5WX5RUcjs.copyHeader; exports.directoryIndex = _chunkLTLBEBKLcjs.directoryIndex; exports.imageOptimize = _chunkKXC6ES3Bcjs.imageOptimize; exports.redirect = _chunkWWSRNCUPcjs.redirect; exports.removeResponseHeaders = _chunkSGEBNQR2cjs.removeResponseHeaders; exports.rewriteUri = _chunkMRPTC74Icjs.rewriteUri; exports.setCacheControl = _chunkCV234DQTcjs.setCacheControl; exports.setCorsHeaders = _chunkGK5JX7OMcjs.setCorsHeaders; exports.setCsp = _chunkZXS23HXAcjs.setCsp; exports.setRequestHeader = _chunkPPUHEL4Hcjs.setRequestHeader; exports.setResponseHeader = _chunkB4WEJSEZcjs.setResponseHeader; exports.setSecurityHeaders = _chunkUI6LKDJIcjs.setSecurityHeaders; exports.stripQueryParams = _chunkMSES76XKcjs.stripQueryParams; exports.verifyToken = verifyToken;
126
+ exports.constructResponse = _chunkOSGZTNTScjs.constructResponse; exports.copyHeader = _chunkJU5WX5RUcjs.copyHeader; exports.directoryIndex = _chunkLTLBEBKLcjs.directoryIndex; exports.imageOptimize = _chunkKXC6ES3Bcjs.imageOptimize; exports.redirect = _chunkWWSRNCUPcjs.redirect; exports.removeResponseHeaders = _chunkSGEBNQR2cjs.removeResponseHeaders; exports.rewriteUri = _chunkMRPTC74Icjs.rewriteUri; exports.setCacheControl = _chunkCV234DQTcjs.setCacheControl; exports.setCorsHeaders = _chunkWAKA4OJDcjs.setCorsHeaders; exports.setCsp = _chunkZXS23HXAcjs.setCsp; exports.setRequestHeader = _chunkPPUHEL4Hcjs.setRequestHeader; exports.setResponseHeader = _chunkB4WEJSEZcjs.setResponseHeader; exports.setSecurityHeaders = _chunk3UXNXJ6Ncjs.setSecurityHeaders; exports.stripQueryParams = _chunkMSES76XKcjs.stripQueryParams; exports.verifyToken = verifyToken;
@@ -6,7 +6,7 @@ import {
6
6
  } from "../chunk-RBBKFG5J.js";
7
7
  import {
8
8
  setSecurityHeaders
9
- } from "../chunk-VQCRSBWL.js";
9
+ } from "../chunk-O4SOSGAP.js";
10
10
  import {
11
11
  stripQueryParams
12
12
  } from "../chunk-XPQG5IML.js";
@@ -27,7 +27,7 @@ import {
27
27
  } from "../chunk-ZTMSH34E.js";
28
28
  import {
29
29
  setCorsHeaders
30
- } from "../chunk-SOBTD7AD.js";
30
+ } from "../chunk-SRA2DFKG.js";
31
31
  import {
32
32
  setCsp
33
33
  } from "../chunk-XUI4Y22M.js";
@@ -1,7 +1,11 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
- var _chunkGK5JX7OMcjs = require('../chunk-GK5JX7OM.cjs');
3
+
4
+
5
+ var _chunkWAKA4OJDcjs = require('../chunk-WAKA4OJD.cjs');
4
6
  require('../chunk-75ZPJI57.cjs');
5
7
 
6
8
 
7
- exports.setCorsHeaders = _chunkGK5JX7OMcjs.setCorsHeaders;
9
+
10
+
11
+ exports.ORIGIN_ECHO = _chunkWAKA4OJDcjs.ORIGIN_ECHO; exports.ORIGIN_WILDCARD = _chunkWAKA4OJDcjs.ORIGIN_WILDCARD; exports.setCorsHeaders = _chunkWAKA4OJDcjs.setCorsHeaders;
@@ -1,38 +1,42 @@
1
1
  import { ResponseBehaviorFn } from '../core/types.cjs';
2
2
 
3
+ declare const ORIGIN_WILDCARD: "*";
4
+ type OriginWildcard = typeof ORIGIN_WILDCARD;
5
+ declare const ORIGIN_ECHO: "echo";
6
+ type OriginEcho = typeof ORIGIN_ECHO;
3
7
  /**
4
- * CORS configuration options for the `setCorsHeaders` behavior.
8
+ * A valid HTTP origin must start with `https://` or `http://`.
9
+ * Supports wildcard subdomains (e.g. `https://*.viverse.com`).
10
+ */
11
+ type Origin = `https://${string}` | `http://${string}`;
12
+ /**
13
+ * Controls how `Access-Control-Allow-Origin` is set:
14
+ * - `ORIGIN_WILDCARD` (`'*'`) — static `*`, allows all origins without inspection
15
+ * - `Origin[]` — compare request `Origin` header against the list; echo if matched, skip if not
16
+ * - `ORIGIN_ECHO` (`'echo'`) — echo any request `Origin` if present, skip if none
17
+ */
18
+ type OriginPolicy = OriginWildcard | Origin[] | OriginEcho;
19
+ /**
20
+ * CORS configuration options for `setCorsHeaders` and `preflightRequest`.
5
21
  */
6
22
  interface CorsOptions {
7
23
  /**
8
- * List of allowed origin patterns. Supports exact strings and wildcard `*` patterns
9
- * (e.g. `'https://*.example.com'`). Use `['*']` to allow all origins.
10
- * Default: `['*']`
24
+ * Origin policy. See `OriginPolicy` for details.
11
25
  */
12
- allowedOrigins?: string[];
13
- /**
14
- * When `true`, reflects the incoming `Origin` request header as the
15
- * `Access-Control-Allow-Origin` response value, provided it matches one of
16
- * `allowedOrigins`. Required when `allowCredentials` is `true` (browsers reject
17
- * `Access-Control-Allow-Origin: *` with credentials).
18
- * Default: `false`
19
- */
20
- allowOriginEcho?: boolean;
26
+ allowedOrigins: OriginPolicy;
21
27
  /**
22
28
  * Value for the `Access-Control-Allow-Methods` header.
23
- * Default: `'GET, POST, OPTIONS'`
29
+ * Omit to exclude the header.
24
30
  */
25
31
  allowedMethods?: string;
26
32
  /**
27
33
  * Value for the `Access-Control-Allow-Headers` header.
28
- * Default: `'Content-Type, Cache-Control, Pragma, Range'`
34
+ * Omit to exclude the header.
29
35
  */
30
36
  allowedHeaders?: string;
31
37
  /**
32
38
  * When `true`, sets `Access-Control-Allow-Credentials: true`.
33
- * Must be used together with `allowOriginEcho: true`; browsers reject
34
- * wildcard origins when credentials are present.
35
- * Default: `false`
39
+ * Use with `ORIGIN_ECHO` or `Origin[]` browsers reject `*` with credentials.
36
40
  */
37
41
  allowCredentials?: boolean;
38
42
  /**
@@ -42,35 +46,32 @@ interface CorsOptions {
42
46
  maxAge?: number;
43
47
  }
44
48
  /**
45
- * Sets CORS response headers with configurable origin matching, methods, headers,
46
- * credentials, and preflight cache duration.
47
- *
48
- * Akamai equivalent: typically implemented via `modifyOutgoingResponseHeader` rules
49
- * for each CORS header individually.
49
+ * Sets CORS response headers with configurable origin policy.
50
50
  *
51
- * @param options - CORS configuration. All fields are optional with safe defaults.
51
+ * @param options - CORS configuration. `allowedOrigins` is required.
52
52
  * @returns A `ResponseBehaviorFn` to use directly in `defineViewerResponse` or wrapped in a `ResponseRule`.
53
53
  *
54
54
  * @example
55
55
  * ```ts
56
- * import { setCorsHeaders } from '@rayselfs/cf-rule-engine/behaviors'
57
- * import { defineViewerResponse } from '@rayselfs/cf-rule-engine/adapters/cf-function'
56
+ * import { setCorsHeaders, ORIGIN_WILDCARD, ORIGIN_ECHO } from '@rayselfs/cf-rule-engine/behaviors/set-cors-headers'
57
+ * import { defineViewerResponse } from '@rayselfs/cf-rule-engine/adapters/viewer-response'
58
58
  *
59
- * // Allow all origins (default)
60
- * export default defineViewerResponse([setCorsHeaders()])
59
+ * // Public API static Access-Control-Allow-Origin: *
60
+ * export default defineViewerResponse([
61
+ * setCorsHeaders({ allowedOrigins: ORIGIN_WILDCARD }),
62
+ * ])
63
+ *
64
+ * // Restricted — echo only listed origins (supports wildcard subdomains)
65
+ * export default defineViewerResponse([
66
+ * setCorsHeaders({ allowedOrigins: ['https://*.viverse.com', 'https://sdk-api.viverse.com'] }),
67
+ * ])
61
68
  *
62
- * // Echo origin with credentials (e.g. for authenticated API endpoints)
69
+ * // Echo any origin (e.g. for credentialed requests)
63
70
  * export default defineViewerResponse([
64
- * setCorsHeaders({
65
- * allowedOrigins: ['https://www.example.com', 'https://*.example.com'],
66
- * allowOriginEcho: true,
67
- * allowCredentials: true,
68
- * allowedMethods: 'GET, POST, PUT, DELETE, OPTIONS',
69
- * maxAge: 86400,
70
- * }),
71
+ * setCorsHeaders({ allowedOrigins: ORIGIN_ECHO, allowCredentials: true }),
71
72
  * ])
72
73
  * ```
73
74
  */
74
- declare function setCorsHeaders(options?: CorsOptions): ResponseBehaviorFn;
75
+ declare function setCorsHeaders(options: CorsOptions): ResponseBehaviorFn;
75
76
 
76
- export { type CorsOptions, setCorsHeaders };
77
+ export { type CorsOptions, ORIGIN_ECHO, ORIGIN_WILDCARD, type Origin, type OriginEcho, type OriginPolicy, type OriginWildcard, setCorsHeaders };
@@ -1,38 +1,42 @@
1
1
  import { ResponseBehaviorFn } from '../core/types.js';
2
2
 
3
+ declare const ORIGIN_WILDCARD: "*";
4
+ type OriginWildcard = typeof ORIGIN_WILDCARD;
5
+ declare const ORIGIN_ECHO: "echo";
6
+ type OriginEcho = typeof ORIGIN_ECHO;
3
7
  /**
4
- * CORS configuration options for the `setCorsHeaders` behavior.
8
+ * A valid HTTP origin must start with `https://` or `http://`.
9
+ * Supports wildcard subdomains (e.g. `https://*.viverse.com`).
10
+ */
11
+ type Origin = `https://${string}` | `http://${string}`;
12
+ /**
13
+ * Controls how `Access-Control-Allow-Origin` is set:
14
+ * - `ORIGIN_WILDCARD` (`'*'`) — static `*`, allows all origins without inspection
15
+ * - `Origin[]` — compare request `Origin` header against the list; echo if matched, skip if not
16
+ * - `ORIGIN_ECHO` (`'echo'`) — echo any request `Origin` if present, skip if none
17
+ */
18
+ type OriginPolicy = OriginWildcard | Origin[] | OriginEcho;
19
+ /**
20
+ * CORS configuration options for `setCorsHeaders` and `preflightRequest`.
5
21
  */
6
22
  interface CorsOptions {
7
23
  /**
8
- * List of allowed origin patterns. Supports exact strings and wildcard `*` patterns
9
- * (e.g. `'https://*.example.com'`). Use `['*']` to allow all origins.
10
- * Default: `['*']`
24
+ * Origin policy. See `OriginPolicy` for details.
11
25
  */
12
- allowedOrigins?: string[];
13
- /**
14
- * When `true`, reflects the incoming `Origin` request header as the
15
- * `Access-Control-Allow-Origin` response value, provided it matches one of
16
- * `allowedOrigins`. Required when `allowCredentials` is `true` (browsers reject
17
- * `Access-Control-Allow-Origin: *` with credentials).
18
- * Default: `false`
19
- */
20
- allowOriginEcho?: boolean;
26
+ allowedOrigins: OriginPolicy;
21
27
  /**
22
28
  * Value for the `Access-Control-Allow-Methods` header.
23
- * Default: `'GET, POST, OPTIONS'`
29
+ * Omit to exclude the header.
24
30
  */
25
31
  allowedMethods?: string;
26
32
  /**
27
33
  * Value for the `Access-Control-Allow-Headers` header.
28
- * Default: `'Content-Type, Cache-Control, Pragma, Range'`
34
+ * Omit to exclude the header.
29
35
  */
30
36
  allowedHeaders?: string;
31
37
  /**
32
38
  * When `true`, sets `Access-Control-Allow-Credentials: true`.
33
- * Must be used together with `allowOriginEcho: true`; browsers reject
34
- * wildcard origins when credentials are present.
35
- * Default: `false`
39
+ * Use with `ORIGIN_ECHO` or `Origin[]` browsers reject `*` with credentials.
36
40
  */
37
41
  allowCredentials?: boolean;
38
42
  /**
@@ -42,35 +46,32 @@ interface CorsOptions {
42
46
  maxAge?: number;
43
47
  }
44
48
  /**
45
- * Sets CORS response headers with configurable origin matching, methods, headers,
46
- * credentials, and preflight cache duration.
47
- *
48
- * Akamai equivalent: typically implemented via `modifyOutgoingResponseHeader` rules
49
- * for each CORS header individually.
49
+ * Sets CORS response headers with configurable origin policy.
50
50
  *
51
- * @param options - CORS configuration. All fields are optional with safe defaults.
51
+ * @param options - CORS configuration. `allowedOrigins` is required.
52
52
  * @returns A `ResponseBehaviorFn` to use directly in `defineViewerResponse` or wrapped in a `ResponseRule`.
53
53
  *
54
54
  * @example
55
55
  * ```ts
56
- * import { setCorsHeaders } from '@rayselfs/cf-rule-engine/behaviors'
57
- * import { defineViewerResponse } from '@rayselfs/cf-rule-engine/adapters/cf-function'
56
+ * import { setCorsHeaders, ORIGIN_WILDCARD, ORIGIN_ECHO } from '@rayselfs/cf-rule-engine/behaviors/set-cors-headers'
57
+ * import { defineViewerResponse } from '@rayselfs/cf-rule-engine/adapters/viewer-response'
58
58
  *
59
- * // Allow all origins (default)
60
- * export default defineViewerResponse([setCorsHeaders()])
59
+ * // Public API static Access-Control-Allow-Origin: *
60
+ * export default defineViewerResponse([
61
+ * setCorsHeaders({ allowedOrigins: ORIGIN_WILDCARD }),
62
+ * ])
63
+ *
64
+ * // Restricted — echo only listed origins (supports wildcard subdomains)
65
+ * export default defineViewerResponse([
66
+ * setCorsHeaders({ allowedOrigins: ['https://*.viverse.com', 'https://sdk-api.viverse.com'] }),
67
+ * ])
61
68
  *
62
- * // Echo origin with credentials (e.g. for authenticated API endpoints)
69
+ * // Echo any origin (e.g. for credentialed requests)
63
70
  * export default defineViewerResponse([
64
- * setCorsHeaders({
65
- * allowedOrigins: ['https://www.example.com', 'https://*.example.com'],
66
- * allowOriginEcho: true,
67
- * allowCredentials: true,
68
- * allowedMethods: 'GET, POST, PUT, DELETE, OPTIONS',
69
- * maxAge: 86400,
70
- * }),
71
+ * setCorsHeaders({ allowedOrigins: ORIGIN_ECHO, allowCredentials: true }),
71
72
  * ])
72
73
  * ```
73
74
  */
74
- declare function setCorsHeaders(options?: CorsOptions): ResponseBehaviorFn;
75
+ declare function setCorsHeaders(options: CorsOptions): ResponseBehaviorFn;
75
76
 
76
- export { type CorsOptions, setCorsHeaders };
77
+ export { type CorsOptions, ORIGIN_ECHO, ORIGIN_WILDCARD, type Origin, type OriginEcho, type OriginPolicy, type OriginWildcard, setCorsHeaders };
@@ -1,7 +1,11 @@
1
1
  import {
2
+ ORIGIN_ECHO,
3
+ ORIGIN_WILDCARD,
2
4
  setCorsHeaders
3
- } from "../chunk-SOBTD7AD.js";
5
+ } from "../chunk-SRA2DFKG.js";
4
6
  import "../chunk-MLKGABMK.js";
5
7
  export {
8
+ ORIGIN_ECHO,
9
+ ORIGIN_WILDCARD,
6
10
  setCorsHeaders
7
11
  };
@@ -1,7 +1,7 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
- var _chunkUI6LKDJIcjs = require('../chunk-UI6LKDJI.cjs');
3
+ var _chunk3UXNXJ6Ncjs = require('../chunk-3UXNXJ6N.cjs');
4
4
  require('../chunk-75ZPJI57.cjs');
5
5
 
6
6
 
7
- exports.setSecurityHeaders = _chunkUI6LKDJIcjs.setSecurityHeaders;
7
+ exports.setSecurityHeaders = _chunk3UXNXJ6Ncjs.setSecurityHeaders;
@@ -1,55 +1,71 @@
1
1
  import { ResponseBehaviorFn } from '../core/types.cjs';
2
2
 
3
3
  /**
4
- * Options for overriding individual security header values.
5
- * All fields are optional; omitted fields fall back to their secure defaults.
4
+ * Options for individual security header values.
5
+ *
6
+ * Only headers with a provided value are emitted — omitted fields are **not** added to the
7
+ * response. There are no built-in defaults; every emitted header value is explicit.
8
+ *
9
+ * Pass at least one field.
6
10
  */
7
11
  interface SecurityHeadersOptions {
8
12
  /**
9
13
  * Value for the `Strict-Transport-Security` header.
10
- * Default: `'max-age=31536000; includeSubDomains'`
14
+ * Example: `'max-age=31536000; includeSubDomains'`
11
15
  */
12
16
  hsts?: string;
13
17
  /**
14
18
  * Value for the `X-Frame-Options` header. Controls whether the page can be
15
19
  * embedded in an iframe. Common values: `'DENY'`, `'SAMEORIGIN'`.
16
- * Default: `'SAMEORIGIN'`
17
20
  */
18
21
  xFrameOptions?: string;
19
22
  /**
20
23
  * Value for the `X-Content-Type-Options` header. Set to `'nosniff'` to
21
24
  * prevent browsers from MIME-sniffing the response content type.
22
- * Default: `'nosniff'`
23
25
  */
24
26
  xContentTypeOptions?: string;
27
+ /**
28
+ * Value for the `X-XSS-Protection` header.
29
+ * Example: `'1; mode=block'`
30
+ *
31
+ * Note: deprecated in modern browsers but still used for legacy compatibility.
32
+ */
33
+ xXssProtection?: string;
25
34
  }
26
35
  /**
27
- * Sets common security headers on the outgoing response.
36
+ * Sets security headers on the outgoing response.
37
+ *
38
+ * Only headers explicitly provided in `options` are emitted — there are **no built-in
39
+ * defaults**. This avoids silently overriding headers set elsewhere in the pipeline and
40
+ * lets Akamai-migrated properties carry their original values verbatim.
28
41
  *
29
- * Applied headers and their defaults:
30
- * - `Strict-Transport-Security`: `max-age=31536000; includeSubDomains`
31
- * - `X-Frame-Options`: `SAMEORIGIN`
32
- * - `X-Content-Type-Options`: `nosniff`
42
+ * Supported headers:
43
+ * - `Strict-Transport-Security` (`hsts`)
44
+ * - `X-Frame-Options` (`xFrameOptions`)
45
+ * - `X-Content-Type-Options` (`xContentTypeOptions`)
46
+ * - `X-XSS-Protection` (`xXssProtection`)
33
47
  *
34
- * Akamai equivalent: `httpStrictTransportSecurity` behavior (HSTS only).
48
+ * Akamai equivalents: `httpStrictTransportSecurity` (HSTS), `modifyOutgoingResponseHeader`
49
+ * (frame options, content-type options, XSS protection).
35
50
  *
36
- * @param options - Optional overrides for individual header values.
37
- * @returns A `ResponseBehaviorFn` to use directly in `defineViewerResponse` or wrapped in a `ResponseRule`.
51
+ * @param options - Security header values to set. Pass at least one field.
52
+ * @returns A `ResponseBehaviorFn` to use in `defineViewerResponse` or a `ResponseRule`.
38
53
  *
39
54
  * @example
40
55
  * ```ts
41
56
  * import { setSecurityHeaders } from '@rayselfs/cf-rule-engine/behaviors'
42
57
  * import { defineViewerResponse } from '@rayselfs/cf-rule-engine/adapters/cf-function'
43
58
  *
44
- * // Apply defaults
45
- * export default defineViewerResponse([setSecurityHeaders()])
46
- *
47
- * // Override HSTS and frame options
48
59
  * export default defineViewerResponse([
49
- * setSecurityHeaders({ hsts: 'max-age=63072000; includeSubDomains; preload', xFrameOptions: 'DENY' }),
60
+ * setSecurityHeaders({
61
+ * hsts: 'max-age=31536000; includeSubDomains',
62
+ * xFrameOptions: 'SAMEORIGIN',
63
+ * xContentTypeOptions: 'nosniff',
64
+ * xXssProtection: '1; mode=block',
65
+ * }),
50
66
  * ])
51
67
  * ```
52
68
  */
53
- declare function setSecurityHeaders(options?: SecurityHeadersOptions): ResponseBehaviorFn;
69
+ declare function setSecurityHeaders(options: SecurityHeadersOptions): ResponseBehaviorFn;
54
70
 
55
71
  export { type SecurityHeadersOptions, setSecurityHeaders };
@@ -1,55 +1,71 @@
1
1
  import { ResponseBehaviorFn } from '../core/types.js';
2
2
 
3
3
  /**
4
- * Options for overriding individual security header values.
5
- * All fields are optional; omitted fields fall back to their secure defaults.
4
+ * Options for individual security header values.
5
+ *
6
+ * Only headers with a provided value are emitted — omitted fields are **not** added to the
7
+ * response. There are no built-in defaults; every emitted header value is explicit.
8
+ *
9
+ * Pass at least one field.
6
10
  */
7
11
  interface SecurityHeadersOptions {
8
12
  /**
9
13
  * Value for the `Strict-Transport-Security` header.
10
- * Default: `'max-age=31536000; includeSubDomains'`
14
+ * Example: `'max-age=31536000; includeSubDomains'`
11
15
  */
12
16
  hsts?: string;
13
17
  /**
14
18
  * Value for the `X-Frame-Options` header. Controls whether the page can be
15
19
  * embedded in an iframe. Common values: `'DENY'`, `'SAMEORIGIN'`.
16
- * Default: `'SAMEORIGIN'`
17
20
  */
18
21
  xFrameOptions?: string;
19
22
  /**
20
23
  * Value for the `X-Content-Type-Options` header. Set to `'nosniff'` to
21
24
  * prevent browsers from MIME-sniffing the response content type.
22
- * Default: `'nosniff'`
23
25
  */
24
26
  xContentTypeOptions?: string;
27
+ /**
28
+ * Value for the `X-XSS-Protection` header.
29
+ * Example: `'1; mode=block'`
30
+ *
31
+ * Note: deprecated in modern browsers but still used for legacy compatibility.
32
+ */
33
+ xXssProtection?: string;
25
34
  }
26
35
  /**
27
- * Sets common security headers on the outgoing response.
36
+ * Sets security headers on the outgoing response.
37
+ *
38
+ * Only headers explicitly provided in `options` are emitted — there are **no built-in
39
+ * defaults**. This avoids silently overriding headers set elsewhere in the pipeline and
40
+ * lets Akamai-migrated properties carry their original values verbatim.
28
41
  *
29
- * Applied headers and their defaults:
30
- * - `Strict-Transport-Security`: `max-age=31536000; includeSubDomains`
31
- * - `X-Frame-Options`: `SAMEORIGIN`
32
- * - `X-Content-Type-Options`: `nosniff`
42
+ * Supported headers:
43
+ * - `Strict-Transport-Security` (`hsts`)
44
+ * - `X-Frame-Options` (`xFrameOptions`)
45
+ * - `X-Content-Type-Options` (`xContentTypeOptions`)
46
+ * - `X-XSS-Protection` (`xXssProtection`)
33
47
  *
34
- * Akamai equivalent: `httpStrictTransportSecurity` behavior (HSTS only).
48
+ * Akamai equivalents: `httpStrictTransportSecurity` (HSTS), `modifyOutgoingResponseHeader`
49
+ * (frame options, content-type options, XSS protection).
35
50
  *
36
- * @param options - Optional overrides for individual header values.
37
- * @returns A `ResponseBehaviorFn` to use directly in `defineViewerResponse` or wrapped in a `ResponseRule`.
51
+ * @param options - Security header values to set. Pass at least one field.
52
+ * @returns A `ResponseBehaviorFn` to use in `defineViewerResponse` or a `ResponseRule`.
38
53
  *
39
54
  * @example
40
55
  * ```ts
41
56
  * import { setSecurityHeaders } from '@rayselfs/cf-rule-engine/behaviors'
42
57
  * import { defineViewerResponse } from '@rayselfs/cf-rule-engine/adapters/cf-function'
43
58
  *
44
- * // Apply defaults
45
- * export default defineViewerResponse([setSecurityHeaders()])
46
- *
47
- * // Override HSTS and frame options
48
59
  * export default defineViewerResponse([
49
- * setSecurityHeaders({ hsts: 'max-age=63072000; includeSubDomains; preload', xFrameOptions: 'DENY' }),
60
+ * setSecurityHeaders({
61
+ * hsts: 'max-age=31536000; includeSubDomains',
62
+ * xFrameOptions: 'SAMEORIGIN',
63
+ * xContentTypeOptions: 'nosniff',
64
+ * xXssProtection: '1; mode=block',
65
+ * }),
50
66
  * ])
51
67
  * ```
52
68
  */
53
- declare function setSecurityHeaders(options?: SecurityHeadersOptions): ResponseBehaviorFn;
69
+ declare function setSecurityHeaders(options: SecurityHeadersOptions): ResponseBehaviorFn;
54
70
 
55
71
  export { type SecurityHeadersOptions, setSecurityHeaders };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  setSecurityHeaders
3
- } from "../chunk-VQCRSBWL.js";
3
+ } from "../chunk-O4SOSGAP.js";
4
4
  import "../chunk-MLKGABMK.js";
5
5
  export {
6
6
  setSecurityHeaders
@@ -0,0 +1,21 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/behaviors/set-security-headers.ts
2
+ function setSecurityHeaders(options) {
3
+ return (_request, response) => {
4
+ const extra = {};
5
+ if (options.hsts !== void 0)
6
+ extra["strict-transport-security"] = { value: options.hsts };
7
+ if (options.xFrameOptions !== void 0)
8
+ extra["x-frame-options"] = { value: options.xFrameOptions };
9
+ if (options.xContentTypeOptions !== void 0)
10
+ extra["x-content-type-options"] = { value: options.xContentTypeOptions };
11
+ if (options.xXssProtection !== void 0)
12
+ extra["x-xss-protection"] = { value: options.xXssProtection };
13
+ return Object.assign({}, response, {
14
+ headers: Object.assign({}, response.headers, extra)
15
+ });
16
+ };
17
+ }
18
+
19
+
20
+
21
+ exports.setSecurityHeaders = setSecurityHeaders;
@@ -1,6 +1,10 @@
1
1
  import {
2
2
  methodIs
3
3
  } from "./chunk-PY3JMRDG.js";
4
+ import {
5
+ ORIGIN_ECHO,
6
+ ORIGIN_WILDCARD
7
+ } from "./chunk-SRA2DFKG.js";
4
8
 
5
9
  // src/helpers/preflight-request.ts
6
10
  function matchesOriginPattern(origin, pattern) {
@@ -10,27 +14,33 @@ function matchesOriginPattern(origin, pattern) {
10
14
  return new RegExp(`^${escaped}$`).test(origin);
11
15
  }
12
16
  function preflightRequest(options) {
13
- const allowedOrigins = options?.allowedOrigins ?? ["*"];
14
- const allowedMethods = options?.allowedMethods ?? "GET, POST, OPTIONS";
15
- const allowedHeaders = options?.allowedHeaders ?? "Content-Type, Cache-Control, Pragma, Range";
16
- const allowCredentials = options?.allowCredentials ?? false;
17
- const maxAge = options?.maxAge;
17
+ const { allowedOrigins } = options;
18
+ const allowedMethods = options.allowedMethods ?? "GET, POST, OPTIONS";
19
+ const allowedHeaders = options.allowedHeaders ?? "Content-Type, Cache-Control, Pragma, Range";
20
+ const allowCredentials = options.allowCredentials ?? false;
21
+ const maxAge = options.maxAge;
18
22
  return {
19
23
  criteria: methodIs(["OPTIONS"]),
20
24
  behavior: (request) => {
21
25
  let allowOrigin;
22
- if (options?.allowOriginEcho) {
23
- const originHeader = request.headers["origin"]?.value;
24
- allowOrigin = originHeader && allowedOrigins.some((p) => matchesOriginPattern(originHeader, p)) ? originHeader : allowedOrigins[0] ?? "*";
26
+ if (allowedOrigins === ORIGIN_WILDCARD) {
27
+ allowOrigin = "*";
28
+ } else if (allowedOrigins === ORIGIN_ECHO) {
29
+ allowOrigin = request.headers["origin"]?.value;
25
30
  } else {
26
- allowOrigin = allowedOrigins.includes("*") ? "*" : allowedOrigins[0] ?? "*";
31
+ const originHeader = request.headers["origin"]?.value;
32
+ if (originHeader && allowedOrigins.some((p) => matchesOriginPattern(originHeader, p))) {
33
+ allowOrigin = originHeader;
34
+ }
27
35
  }
28
36
  const headers = {
29
37
  "cache-control": { value: "no-store" },
30
- "access-control-allow-origin": { value: allowOrigin },
31
38
  "access-control-allow-methods": { value: allowedMethods },
32
39
  "access-control-allow-headers": { value: allowedHeaders }
33
40
  };
41
+ if (allowOrigin !== void 0) {
42
+ headers["access-control-allow-origin"] = { value: allowOrigin };
43
+ }
34
44
  if (allowCredentials) {
35
45
  headers["access-control-allow-credentials"] = { value: "true" };
36
46
  }