@rayselfs/cf-rule-engine 1.6.1 → 1.7.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 (50) hide show
  1. package/README.md +5 -3
  2. package/dist/adapters/cf-function.cjs +7 -3
  3. package/dist/adapters/cf-function.d.cts +2 -1
  4. package/dist/adapters/cf-function.d.ts +2 -1
  5. package/dist/adapters/cf-function.js +7 -3
  6. package/dist/adapters/viewer-request.cjs +3 -2
  7. package/dist/adapters/viewer-request.d.cts +31 -2
  8. package/dist/adapters/viewer-request.d.ts +31 -2
  9. package/dist/adapters/viewer-request.js +2 -1
  10. package/dist/adapters/viewer-response.cjs +3 -3
  11. package/dist/adapters/viewer-response.d.cts +37 -2
  12. package/dist/adapters/viewer-response.d.ts +37 -2
  13. package/dist/adapters/viewer-response.js +2 -2
  14. package/dist/behaviors/index.cjs +2 -2
  15. package/dist/behaviors/index.js +1 -1
  16. package/dist/behaviors/set-security-headers.cjs +2 -2
  17. package/dist/behaviors/set-security-headers.d.cts +35 -19
  18. package/dist/behaviors/set-security-headers.d.ts +35 -19
  19. package/dist/behaviors/set-security-headers.js +1 -1
  20. package/dist/cf-function-BkfWpTfl.d.cts +10 -0
  21. package/dist/cf-function-CZwCWch-.d.ts +10 -0
  22. package/dist/chunk-3UXNXJ6N.cjs +21 -0
  23. package/dist/chunk-5ZIB3AJ7.cjs +20 -0
  24. package/dist/chunk-6NFAPLQ7.cjs +39 -0
  25. package/dist/chunk-BJZPAQHW.js +25 -0
  26. package/dist/chunk-CQ7YZ3AR.js +39 -0
  27. package/dist/chunk-N6QAQALU.cjs +36 -0
  28. package/dist/chunk-O4SOSGAP.js +21 -0
  29. package/dist/chunk-PR5UQJCC.js +20 -0
  30. package/dist/chunk-SGN2N3WI.cjs +25 -0
  31. package/dist/chunk-TURH5IFN.js +36 -0
  32. package/dist/criteria/index.cjs +12 -12
  33. package/dist/criteria/index.js +12 -12
  34. package/dist/helpers/index.cjs +6 -6
  35. package/dist/helpers/index.js +5 -5
  36. package/dist/helpers/whitelist.cjs +3 -3
  37. package/dist/helpers/whitelist.js +2 -2
  38. package/dist/index.cjs +6 -3
  39. package/dist/index.d.cts +3 -1
  40. package/dist/index.d.ts +3 -1
  41. package/dist/index.js +6 -3
  42. package/package.json +1 -1
  43. package/dist/chunk-NPMGSPNL.js +0 -88
  44. package/dist/chunk-SAXDN5NS.cjs +0 -88
  45. package/dist/chunk-UI6LKDJI.cjs +0 -19
  46. package/dist/chunk-VQCRSBWL.js +0 -19
  47. package/dist/viewer-response-C9eF2O9s.d.ts +0 -70
  48. package/dist/viewer-response-DIQHy8L7.d.cts +0 -70
  49. package/dist/{chunk-RL7ZETZR.js → chunk-ER2YEZZO.js} +3 -3
  50. package/dist/{chunk-T5EXFHVA.cjs → chunk-MO7HW25R.cjs} +3 -3
package/README.md CHANGED
@@ -18,7 +18,7 @@ npm install @rayselfs/cf-rule-engine
18
18
  import { rule, not } from '@rayselfs/cf-rule-engine'
19
19
  import { ipCidr, methodIs } from '@rayselfs/cf-rule-engine/criteria/index'
20
20
  import { redirect, constructResponse } from '@rayselfs/cf-rule-engine/behaviors/index'
21
- import { defineViewerRequest } from '@rayselfs/cf-rule-engine/adapters/cf-function'
21
+ import { defineViewerRequest } from '@rayselfs/cf-rule-engine/adapters/viewer-request'
22
22
 
23
23
  export default defineViewerRequest([
24
24
  rule(not(ipCidr(['10.0.0.0/8', '172.16.0.0/12'])), redirect(302, '/blocked')),
@@ -30,7 +30,7 @@ export default defineViewerRequest([
30
30
 
31
31
  ```typescript
32
32
  import { setSecurityHeaders, setCorsHeaders } from '@rayselfs/cf-rule-engine/behaviors/index'
33
- import { defineViewerResponse } from '@rayselfs/cf-rule-engine/adapters/cf-function'
33
+ import { defineViewerResponse } from '@rayselfs/cf-rule-engine/adapters/viewer-response'
34
34
 
35
35
  export default defineViewerResponse([
36
36
  setSecurityHeaders(),
@@ -70,7 +70,9 @@ Use `chain()` when one behavior must see the request mutations (URI rewrite, hea
70
70
 
71
71
  | Adapter | Import | Use for |
72
72
  |---|---|---|
73
- | CF Function | `@rayselfs/cf-rule-engine/adapters/cf-function` | `viewer-request`, `viewer-response` |
73
+ | CF Function (viewer-request) | `@rayselfs/cf-rule-engine/adapters/viewer-request` | `viewer-request` only — tree-shake-friendly |
74
+ | CF Function (viewer-response) | `@rayselfs/cf-rule-engine/adapters/viewer-response` | `viewer-response` only — tree-shake-friendly |
75
+ | CF Function (combined) | `@rayselfs/cf-rule-engine/adapters/cf-function` | both — backward compat |
74
76
  | Lambda@Edge | `@rayselfs/cf-rule-engine/adapters/lambda-edge` | `viewer-request`, `viewer-response` |
75
77
 
76
78
  ## Akamai → CloudFront Mapping
@@ -1,10 +1,14 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});require('../chunk-5ZIB3AJ7.cjs');
2
2
 
3
3
 
4
- var _chunkSAXDN5NScjs = require('../chunk-SAXDN5NS.cjs');
4
+ var _chunkSGN2N3WIcjs = require('../chunk-SGN2N3WI.cjs');
5
5
  require('../chunk-WKYMSRCD.cjs');
6
+
7
+
8
+ var _chunkN6QAQALUcjs = require('../chunk-N6QAQALU.cjs');
9
+ require('../chunk-6NFAPLQ7.cjs');
6
10
  require('../chunk-75ZPJI57.cjs');
7
11
 
8
12
 
9
13
 
10
- exports.defineViewerRequest = _chunkSAXDN5NScjs.defineViewerRequest; exports.defineViewerResponse = _chunkSAXDN5NScjs.defineViewerResponse;
14
+ exports.defineViewerRequest = _chunkSGN2N3WIcjs.defineViewerRequest; exports.defineViewerResponse = _chunkN6QAQALUcjs.defineViewerResponse;
@@ -1,2 +1,3 @@
1
+ export { defineViewerRequest } from './viewer-request.cjs';
2
+ export { defineViewerResponse } from './viewer-response.cjs';
1
3
  import '../core/types.cjs';
2
- export { d as defineViewerRequest, a as defineViewerResponse } from '../viewer-response-DIQHy8L7.cjs';
@@ -1,2 +1,3 @@
1
+ export { defineViewerRequest } from './viewer-request.js';
2
+ export { defineViewerResponse } from './viewer-response.js';
1
3
  import '../core/types.js';
2
- export { d as defineViewerRequest, a as defineViewerResponse } from '../viewer-response-C9eF2O9s.js';
@@ -1,8 +1,12 @@
1
+ import "../chunk-PR5UQJCC.js";
1
2
  import {
2
- defineViewerRequest,
3
- defineViewerResponse
4
- } from "../chunk-NPMGSPNL.js";
3
+ defineViewerRequest
4
+ } from "../chunk-BJZPAQHW.js";
5
5
  import "../chunk-Q4NP4C3B.js";
6
+ import {
7
+ defineViewerResponse
8
+ } from "../chunk-TURH5IFN.js";
9
+ import "../chunk-CQ7YZ3AR.js";
6
10
  import "../chunk-MLKGABMK.js";
7
11
  export {
8
12
  defineViewerRequest,
@@ -1,8 +1,9 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
- var _chunkSAXDN5NScjs = require('../chunk-SAXDN5NS.cjs');
3
+ var _chunkSGN2N3WIcjs = require('../chunk-SGN2N3WI.cjs');
4
4
  require('../chunk-WKYMSRCD.cjs');
5
+ require('../chunk-6NFAPLQ7.cjs');
5
6
  require('../chunk-75ZPJI57.cjs');
6
7
 
7
8
 
8
- exports.defineViewerRequest = _chunkSAXDN5NScjs.defineViewerRequest;
9
+ exports.defineViewerRequest = _chunkSGN2N3WIcjs.defineViewerRequest;
@@ -1,2 +1,31 @@
1
- export { d as defineViewerRequest } from '../viewer-response-DIQHy8L7.cjs';
2
- import '../core/types.cjs';
1
+ import { Rule } from '../core/types.cjs';
2
+
3
+ /**
4
+ * Creates a CloudFront Function viewer-request handler from an ordered list of rules.
5
+ *
6
+ * The returned function is the CloudFront Function entry point. Assign it as
7
+ * `export default` or `var handler` depending on your runtime configuration.
8
+ *
9
+ * Rules are evaluated in order. Processing stops at the first rule whose behavior
10
+ * returns a response (e.g. `redirect`, `constructResponse`). If all rules continue,
11
+ * the (possibly mutated) request is forwarded to the origin.
12
+ *
13
+ * @param rules - Ordered array of `Rule` objects created with `rule()`.
14
+ * @returns A CloudFront Function handler `(event) => request | response`.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * import { rule, not } from '@rayselfs/cf-rule-engine'
19
+ * import { ipCidr, pathPrefix } from '@rayselfs/cf-rule-engine/criteria'
20
+ * import { redirect, setRequestHeader } from '@rayselfs/cf-rule-engine/behaviors'
21
+ * import { defineViewerRequest } from '@rayselfs/cf-rule-engine/adapters/viewer-request'
22
+ *
23
+ * export default defineViewerRequest([
24
+ * rule(not(ipCidr(['10.0.0.0/8'])), redirect(302, 'https://www.example.com')),
25
+ * rule(pathPrefix(['/api/']), setRequestHeader('x-forwarded-host', 'api.internal')),
26
+ * ])
27
+ * ```
28
+ */
29
+ declare function defineViewerRequest(rules: Rule[]): (event: unknown) => unknown;
30
+
31
+ export { defineViewerRequest };
@@ -1,2 +1,31 @@
1
- export { d as defineViewerRequest } from '../viewer-response-C9eF2O9s.js';
2
- import '../core/types.js';
1
+ import { Rule } from '../core/types.js';
2
+
3
+ /**
4
+ * Creates a CloudFront Function viewer-request handler from an ordered list of rules.
5
+ *
6
+ * The returned function is the CloudFront Function entry point. Assign it as
7
+ * `export default` or `var handler` depending on your runtime configuration.
8
+ *
9
+ * Rules are evaluated in order. Processing stops at the first rule whose behavior
10
+ * returns a response (e.g. `redirect`, `constructResponse`). If all rules continue,
11
+ * the (possibly mutated) request is forwarded to the origin.
12
+ *
13
+ * @param rules - Ordered array of `Rule` objects created with `rule()`.
14
+ * @returns A CloudFront Function handler `(event) => request | response`.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * import { rule, not } from '@rayselfs/cf-rule-engine'
19
+ * import { ipCidr, pathPrefix } from '@rayselfs/cf-rule-engine/criteria'
20
+ * import { redirect, setRequestHeader } from '@rayselfs/cf-rule-engine/behaviors'
21
+ * import { defineViewerRequest } from '@rayselfs/cf-rule-engine/adapters/viewer-request'
22
+ *
23
+ * export default defineViewerRequest([
24
+ * rule(not(ipCidr(['10.0.0.0/8'])), redirect(302, 'https://www.example.com')),
25
+ * rule(pathPrefix(['/api/']), setRequestHeader('x-forwarded-host', 'api.internal')),
26
+ * ])
27
+ * ```
28
+ */
29
+ declare function defineViewerRequest(rules: Rule[]): (event: unknown) => unknown;
30
+
31
+ export { defineViewerRequest };
@@ -1,7 +1,8 @@
1
1
  import {
2
2
  defineViewerRequest
3
- } from "../chunk-NPMGSPNL.js";
3
+ } from "../chunk-BJZPAQHW.js";
4
4
  import "../chunk-Q4NP4C3B.js";
5
+ import "../chunk-CQ7YZ3AR.js";
5
6
  import "../chunk-MLKGABMK.js";
6
7
  export {
7
8
  defineViewerRequest
@@ -1,8 +1,8 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
- var _chunkSAXDN5NScjs = require('../chunk-SAXDN5NS.cjs');
4
- require('../chunk-WKYMSRCD.cjs');
3
+ var _chunkN6QAQALUcjs = require('../chunk-N6QAQALU.cjs');
4
+ require('../chunk-6NFAPLQ7.cjs');
5
5
  require('../chunk-75ZPJI57.cjs');
6
6
 
7
7
 
8
- exports.defineViewerResponse = _chunkSAXDN5NScjs.defineViewerResponse;
8
+ exports.defineViewerResponse = _chunkN6QAQALUcjs.defineViewerResponse;
@@ -1,2 +1,37 @@
1
- export { a as defineViewerResponse } from '../viewer-response-DIQHy8L7.cjs';
2
- import '../core/types.cjs';
1
+ import { ResponseBehaviorFn, ResponseRule } from '../core/types.cjs';
2
+
3
+ /**
4
+ * Creates a CloudFront Function viewer-response handler from an ordered list of
5
+ * response behaviors or response rules.
6
+ *
7
+ * Each entry can be either:
8
+ * - A bare `ResponseBehaviorFn` — runs unconditionally on every response.
9
+ * - A `ResponseRule` `{ criteria, behavior }` — runs only when `criteria` returns `true`
10
+ * for the current request.
11
+ *
12
+ * All behaviors are applied in order; none can short-circuit the response.
13
+ * The final merged response object is returned to CloudFront.
14
+ *
15
+ * Note: If no behavior explicitly sets a body, the `body` field is omitted from
16
+ * the returned response to avoid overwriting the origin's actual content.
17
+ *
18
+ * @param responseBehaviors - Ordered array of `ResponseBehaviorFn` functions or
19
+ * `ResponseRule` objects `{ criteria?, behavior }`.
20
+ * @returns A CloudFront Function handler `(event) => response`.
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * import { setSecurityHeaders, setCorsHeaders, setResponseHeader } from '@rayselfs/cf-rule-engine/behaviors'
25
+ * import { pathPrefix } from '@rayselfs/cf-rule-engine/criteria'
26
+ * import { defineViewerResponse } from '@rayselfs/cf-rule-engine/adapters/viewer-response'
27
+ *
28
+ * export default defineViewerResponse([
29
+ * setSecurityHeaders(),
30
+ * setCorsHeaders({ allowedOrigins: ['https://www.example.com'] }),
31
+ * { criteria: pathPrefix(['/api/']), behavior: setResponseHeader('cache-control', 'no-store') },
32
+ * ])
33
+ * ```
34
+ */
35
+ declare function defineViewerResponse(responseBehaviors: Array<ResponseBehaviorFn | ResponseRule>): (event: unknown) => unknown;
36
+
37
+ export { defineViewerResponse };
@@ -1,2 +1,37 @@
1
- export { a as defineViewerResponse } from '../viewer-response-C9eF2O9s.js';
2
- import '../core/types.js';
1
+ import { ResponseBehaviorFn, ResponseRule } from '../core/types.js';
2
+
3
+ /**
4
+ * Creates a CloudFront Function viewer-response handler from an ordered list of
5
+ * response behaviors or response rules.
6
+ *
7
+ * Each entry can be either:
8
+ * - A bare `ResponseBehaviorFn` — runs unconditionally on every response.
9
+ * - A `ResponseRule` `{ criteria, behavior }` — runs only when `criteria` returns `true`
10
+ * for the current request.
11
+ *
12
+ * All behaviors are applied in order; none can short-circuit the response.
13
+ * The final merged response object is returned to CloudFront.
14
+ *
15
+ * Note: If no behavior explicitly sets a body, the `body` field is omitted from
16
+ * the returned response to avoid overwriting the origin's actual content.
17
+ *
18
+ * @param responseBehaviors - Ordered array of `ResponseBehaviorFn` functions or
19
+ * `ResponseRule` objects `{ criteria?, behavior }`.
20
+ * @returns A CloudFront Function handler `(event) => response`.
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * import { setSecurityHeaders, setCorsHeaders, setResponseHeader } from '@rayselfs/cf-rule-engine/behaviors'
25
+ * import { pathPrefix } from '@rayselfs/cf-rule-engine/criteria'
26
+ * import { defineViewerResponse } from '@rayselfs/cf-rule-engine/adapters/viewer-response'
27
+ *
28
+ * export default defineViewerResponse([
29
+ * setSecurityHeaders(),
30
+ * setCorsHeaders({ allowedOrigins: ['https://www.example.com'] }),
31
+ * { criteria: pathPrefix(['/api/']), behavior: setResponseHeader('cache-control', 'no-store') },
32
+ * ])
33
+ * ```
34
+ */
35
+ declare function defineViewerResponse(responseBehaviors: Array<ResponseBehaviorFn | ResponseRule>): (event: unknown) => unknown;
36
+
37
+ export { defineViewerResponse };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  defineViewerResponse
3
- } from "../chunk-NPMGSPNL.js";
4
- import "../chunk-Q4NP4C3B.js";
3
+ } from "../chunk-TURH5IFN.js";
4
+ import "../chunk-CQ7YZ3AR.js";
5
5
  import "../chunk-MLKGABMK.js";
6
6
  export {
7
7
  defineViewerResponse
@@ -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');
@@ -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 = _chunkGK5JX7OMcjs.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";
@@ -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,10 @@
1
+ import { defineViewerRequest } from './adapters/viewer-request.cjs';
2
+ import { defineViewerResponse } from './adapters/viewer-response.cjs';
3
+
4
+ declare const cfFunction_defineViewerRequest: typeof defineViewerRequest;
5
+ declare const cfFunction_defineViewerResponse: typeof defineViewerResponse;
6
+ declare namespace cfFunction {
7
+ export { cfFunction_defineViewerRequest as defineViewerRequest, cfFunction_defineViewerResponse as defineViewerResponse };
8
+ }
9
+
10
+ export { cfFunction as c };
@@ -0,0 +1,10 @@
1
+ import { defineViewerRequest } from './adapters/viewer-request.js';
2
+ import { defineViewerResponse } from './adapters/viewer-response.js';
3
+
4
+ declare const cfFunction_defineViewerRequest: typeof defineViewerRequest;
5
+ declare const cfFunction_defineViewerResponse: typeof defineViewerResponse;
6
+ declare namespace cfFunction {
7
+ export { cfFunction_defineViewerRequest as defineViewerRequest, cfFunction_defineViewerResponse as defineViewerResponse };
8
+ }
9
+
10
+ export { cfFunction as c };
@@ -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;
@@ -0,0 +1,20 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
+
3
+ var _chunkSGN2N3WIcjs = require('./chunk-SGN2N3WI.cjs');
4
+
5
+
6
+ var _chunkN6QAQALUcjs = require('./chunk-N6QAQALU.cjs');
7
+
8
+
9
+ var _chunk75ZPJI57cjs = require('./chunk-75ZPJI57.cjs');
10
+
11
+ // src/adapters/cf-function.ts
12
+ var cf_function_exports = {};
13
+ _chunk75ZPJI57cjs.__export.call(void 0, cf_function_exports, {
14
+ defineViewerRequest: () => _chunkSGN2N3WIcjs.defineViewerRequest,
15
+ defineViewerResponse: () => _chunkN6QAQALUcjs.defineViewerResponse
16
+ });
17
+
18
+
19
+
20
+ exports.cf_function_exports = cf_function_exports;
@@ -0,0 +1,39 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/adapters/_normalize.ts
2
+ function normalizeRequest(event) {
3
+ const ev = event;
4
+ const req = ev.request;
5
+ const viewer = ev.viewer;
6
+ const headers = _nullishCoalesce(req.headers, () => ( {}));
7
+ return {
8
+ uri: req.uri,
9
+ method: req.method,
10
+ protocol: "https",
11
+ querystring: _nullishCoalesce(req.querystring, () => ( {})),
12
+ headers,
13
+ clientIp: _nullishCoalesce(_optionalChain([viewer, 'optionalAccess', _ => _.ip]), () => ( "")),
14
+ country: _optionalChain([headers, 'access', _2 => _2["cloudfront-viewer-country"], 'optionalAccess', _3 => _3.value])
15
+ };
16
+ }
17
+ function denormalizeRequest(req, cookies) {
18
+ return {
19
+ method: req.method,
20
+ uri: req.uri,
21
+ querystring: req.querystring,
22
+ headers: req.headers,
23
+ cookies
24
+ };
25
+ }
26
+ function denormalizeResponse(res) {
27
+ return {
28
+ statusCode: res.statusCode,
29
+ statusDescription: res.statusDescription,
30
+ headers: res.headers,
31
+ body: _nullishCoalesce(res.body, () => ( ""))
32
+ };
33
+ }
34
+
35
+
36
+
37
+
38
+
39
+ exports.normalizeRequest = normalizeRequest; exports.denormalizeRequest = denormalizeRequest; exports.denormalizeResponse = denormalizeResponse;
@@ -0,0 +1,25 @@
1
+ import {
2
+ runRules
3
+ } from "./chunk-Q4NP4C3B.js";
4
+ import {
5
+ denormalizeRequest,
6
+ denormalizeResponse,
7
+ normalizeRequest
8
+ } from "./chunk-CQ7YZ3AR.js";
9
+
10
+ // src/adapters/viewer-request.ts
11
+ function defineViewerRequest(rules) {
12
+ return (event) => {
13
+ const ev = event;
14
+ const evReq = ev.request;
15
+ const originalCookies = evReq.cookies ?? {};
16
+ const req = normalizeRequest(event);
17
+ const result = runRules(rules, req);
18
+ if (result.action === "respond") return denormalizeResponse(result.response);
19
+ return denormalizeRequest(result.request, originalCookies);
20
+ };
21
+ }
22
+
23
+ export {
24
+ defineViewerRequest
25
+ };