@appwarden/middleware 1.0.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Appwarden
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,110 @@
1
+ # @appwarden/middleware
2
+
3
+ ![Test Coverage](https://img.shields.io/badge/coverage-97.58%25-brightgreen)
4
+ [![npm version](https://img.shields.io/npm/v/@appwarden/middleware.svg)](https://www.npmjs.com/package/@appwarden/middleware)
5
+ [![npm provenance](https://img.shields.io/badge/npm-provenance-green)](https://docs.npmjs.com/generating-provenance-statements)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ > Read the docs [to learn more](https://appwarden.io/docs)
9
+
10
+ ## Stop in progress attacks in their tracks
11
+
12
+ ### Core Features
13
+
14
+ - **Instant Quarantine**: Immediately redirects all visitors to a maintenance page when activated
15
+ - **Discord Integration**: Trigger lockdowns via Discord commands (`/quarantine lock your.app.io`)
16
+ - **Nonce-based Content Security Policy**: On Cloudflare, deploy a nonce-based Content Security Policy to supercharge your website security
17
+
18
+ ### Performance Optimizations
19
+
20
+ - **Background Synchronization**: Uses `waitUntil()` to update cache state without blocking responses
21
+ - **Minimal Runtime Overhead**: Lightweight implementation with negligible performance impact
22
+
23
+ ## Installation
24
+
25
+ Compatible with websites powered by [Cloudflare](https://developers.cloudflare.com/pages/) or [Vercel](https://vercel.com).
26
+
27
+ For detailed usage instructions, please refer to our [documentation](https://appwarden.io/docs).
28
+
29
+ ### Cloudflare
30
+
31
+ We recommend using the [`@appwarden/build-cloudflare-action`](https://github.com/appwarden/build-cloudflare-action) Github Action to deploy automatically on Cloudflare.
32
+
33
+ > Read the docs [to get started](https://appwarden.io/docs/guides/cloudflare-integration)
34
+
35
+ ```typescript
36
+ import {
37
+ withAppwarden,
38
+ useContentSecurityPolicy,
39
+ } from "@appwarden/middleware/cloudflare"
40
+
41
+ export default {
42
+ fetch: withAppwarden((context) => ({
43
+ debug: context.env.DEBUG,
44
+ lockPageSlug: context.env.LOCK_PAGE_SLUG,
45
+ appwardenApiToken: context.env.APPWARDEN_API_TOKEN,
46
+ middleware: {
47
+ before: [
48
+ useContentSecurityPolicy({
49
+ mode: "enforced",
50
+ directives: {
51
+ "script-src": ["self", "{{nonce}}"],
52
+ "style-src": ["self", "{{nonce}}"],
53
+ },
54
+ }),
55
+ ],
56
+ },
57
+ })),
58
+ }
59
+ ```
60
+
61
+ ### Vercel
62
+
63
+ > Read the docs [to get started](https://appwarden.io/docs/guides/vercel-integration)
64
+
65
+ ```typescript
66
+ import { withAppwarden } from "@appwarden/middleware/vercel"
67
+
68
+ export default withAppwarden({
69
+ cacheUrl: process.env.EDGE_CONFIG_URL || process.env.UPSTASH_URL,
70
+ appwardenApiToken: process.env.APPWARDEN_API_TOKEN,
71
+ vercelApiToken: process.env.VERCEL_API_TOKEN,
72
+ lockPageSlug: "/maintenance",
73
+ })
74
+
75
+ // Configures middleware to match all routes
76
+ export const config = {
77
+ matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
78
+ }
79
+ ```
80
+
81
+ ## Contributing
82
+
83
+ Contributions are welcome! Please feel free to submit a Pull Request.
84
+
85
+ 1. Fork the repository
86
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
87
+ 3. Commit your changes (`git commit -m 'Add some amazing feature'`)
88
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
89
+ 5. Open a Pull Request
90
+
91
+ ## Development
92
+
93
+ ```bash
94
+ # Install dependencies
95
+ pnpm install
96
+
97
+ # Build the package
98
+ pnpm build
99
+
100
+ # Run tests
101
+ pnpm test
102
+ ```
103
+
104
+ ## Security
105
+
106
+ This package is published with npm provenance enabled, which provides a verifiable link between the published package and its source code. For more information, see [npm provenance documentation](https://docs.npmjs.com/generating-provenance-statements).
107
+
108
+ ## License
109
+
110
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,108 @@
1
+ import {
2
+ LOCKDOWN_TEST_EXPIRY_MS
3
+ } from "./chunk-JWUAFJ2E.js";
4
+
5
+ // src/utils/errors.ts
6
+ var errorsMap = {
7
+ mode: '`CSP_MODE` must be one of "disabled", "report-only", or "enforced"',
8
+ directives: {
9
+ ["DirectivesRequired" /* DirectivesRequired */]: '`CSP_DIRECTIVES` must be provided when `CSP_MODE` is "report-only" or "enforced"',
10
+ ["DirectivesBadParse" /* DirectivesBadParse */]: "Failed to parse `CSP_DIRECTIVES`. Is it a valid JSON string?"
11
+ },
12
+ appwardenApiToken: "Please provide a valid `appwardenApiToken`. Learn more at https://appwarden.com/docs/guides/api-token-management."
13
+ };
14
+ var getErrors = (error) => {
15
+ const matches = [];
16
+ const errors = [...Object.entries(error.flatten().fieldErrors)];
17
+ for (const issue of error.issues) {
18
+ errors.push(
19
+ ...Object.entries(
20
+ "returnTypeError" in issue ? issue.returnTypeError.flatten().fieldErrors : {}
21
+ )
22
+ );
23
+ }
24
+ for (const [field, maybeSchemaErrorKey] of errors) {
25
+ let match = errorsMap[field];
26
+ if (match) {
27
+ if (match instanceof Object) {
28
+ if (maybeSchemaErrorKey) {
29
+ match = match[maybeSchemaErrorKey[0]];
30
+ }
31
+ }
32
+ matches.push(match);
33
+ }
34
+ }
35
+ return matches;
36
+ };
37
+
38
+ // src/utils/memory-cache.ts
39
+ var MemoryCache = class {
40
+ cache = /* @__PURE__ */ new Map();
41
+ maxSize;
42
+ constructor(options) {
43
+ this.maxSize = options.maxSize;
44
+ }
45
+ get(key) {
46
+ let item;
47
+ if (this.cache.has(key)) {
48
+ item = this.cache.get(key);
49
+ this.cache.delete(key);
50
+ if (item !== void 0) {
51
+ this.cache.set(key, item);
52
+ }
53
+ }
54
+ return item;
55
+ }
56
+ put(key, value) {
57
+ if (this.cache.has(key)) {
58
+ this.cache.delete(key);
59
+ } else if (this.cache.size >= this.maxSize) {
60
+ const firstKey = this.cache.keys().next().value;
61
+ if (firstKey !== void 0) {
62
+ this.cache.delete(firstKey);
63
+ }
64
+ }
65
+ this.cache.set(key, value);
66
+ }
67
+ getValues() {
68
+ return this.cache;
69
+ }
70
+ // the default value will be expired here
71
+ static isExpired = (lockValue) => {
72
+ if (!lockValue) {
73
+ return true;
74
+ }
75
+ return Date.now() > lockValue.lastCheck + 3e4;
76
+ };
77
+ static isTestExpired = (lockValue) => {
78
+ if (!lockValue) {
79
+ return true;
80
+ }
81
+ return Date.now() > lockValue.isLockedTest + LOCKDOWN_TEST_EXPIRY_MS;
82
+ };
83
+ };
84
+
85
+ // src/schemas/helpers.ts
86
+ import { z } from "zod";
87
+ var BoolOrStringSchema = z.union([z.string(), z.boolean()]).optional();
88
+ var BooleanSchema = BoolOrStringSchema.transform((val) => {
89
+ if (val === "true" || val === true) {
90
+ return true;
91
+ } else if (val === "false" || val === false) {
92
+ return false;
93
+ }
94
+ throw new Error("Invalid value");
95
+ });
96
+ var LockValue = z.object({
97
+ isLocked: z.number(),
98
+ isLockedTest: z.number(),
99
+ lastCheck: z.number(),
100
+ code: z.string()
101
+ });
102
+
103
+ export {
104
+ getErrors,
105
+ MemoryCache,
106
+ BooleanSchema,
107
+ LockValue
108
+ };
@@ -0,0 +1,29 @@
1
+ // src/constants.ts
2
+ var LOCKDOWN_TEST_EXPIRY_MS = 5 * 60 * 1e3;
3
+ var errors = { badCacheConnection: "BAD_CACHE_CONNECTION" };
4
+ var globalErrors = [errors.badCacheConnection];
5
+ var APPWARDEN_TEST_ROUTE = "/_appwarden/test";
6
+ var APPWARDEN_USER_AGENT = "Appwarden-Monitor";
7
+ var APPWARDEN_CACHE_KEY = "appwarden-lock";
8
+
9
+ // src/utils/debug.ts
10
+ var debug = (...msg) => {
11
+ if (true) {
12
+ console.log(...msg);
13
+ }
14
+ };
15
+
16
+ // src/utils/print-message.ts
17
+ var addSlashes = (str) => str.replace(/[\\"'`]/g, "\\$&").replace(/\u0000/g, "\\0");
18
+ var printMessage = (message) => `[@appwarden/middleware] ${addSlashes(message)}`;
19
+
20
+ export {
21
+ LOCKDOWN_TEST_EXPIRY_MS,
22
+ errors,
23
+ globalErrors,
24
+ APPWARDEN_TEST_ROUTE,
25
+ APPWARDEN_USER_AGENT,
26
+ APPWARDEN_CACHE_KEY,
27
+ debug,
28
+ printMessage
29
+ };
@@ -0,0 +1,145 @@
1
+ import {
2
+ debug,
3
+ printMessage
4
+ } from "./chunk-JWUAFJ2E.js";
5
+
6
+ // src/schemas/use-content-security-policy.ts
7
+ import { z as z2 } from "zod";
8
+
9
+ // src/types/csp.ts
10
+ import { z } from "zod";
11
+ var stringySchema = z.union([z.array(z.string()), z.string(), z.boolean()]);
12
+ var ContentSecurityPolicySchema = z.object({
13
+ "default-src": stringySchema.optional(),
14
+ "script-src": stringySchema.optional(),
15
+ "style-src": stringySchema.optional(),
16
+ "img-src": stringySchema.optional(),
17
+ "connect-src": stringySchema.optional(),
18
+ "font-src": stringySchema.optional(),
19
+ "object-src": stringySchema.optional(),
20
+ "media-src": stringySchema.optional(),
21
+ "frame-src": stringySchema.optional(),
22
+ sandbox: stringySchema.optional(),
23
+ "report-uri": stringySchema.optional(),
24
+ "child-src": stringySchema.optional(),
25
+ "form-action": stringySchema.optional(),
26
+ "frame-ancestors": stringySchema.optional(),
27
+ "plugin-types": stringySchema.optional(),
28
+ "base-uri": stringySchema.optional(),
29
+ "report-to": stringySchema.optional(),
30
+ "worker-src": stringySchema.optional(),
31
+ "manifest-src": stringySchema.optional(),
32
+ "prefetch-src": stringySchema.optional(),
33
+ "navigate-to": stringySchema.optional(),
34
+ "require-sri-for": stringySchema.optional(),
35
+ "block-all-mixed-content": stringySchema.optional(),
36
+ "upgrade-insecure-requests": stringySchema.optional(),
37
+ "trusted-types": stringySchema.optional(),
38
+ "require-trusted-types-for": stringySchema.optional()
39
+ });
40
+
41
+ // src/schemas/use-content-security-policy.ts
42
+ var CSPDirectivesSchema = z2.union([
43
+ z2.string(),
44
+ ContentSecurityPolicySchema
45
+ ]);
46
+ var CSPModeSchema = z2.union([
47
+ z2.literal("disabled"),
48
+ z2.literal("report-only"),
49
+ z2.literal("enforced")
50
+ ]).optional().default("disabled");
51
+ var UseCSPInputSchema = z2.object({
52
+ mode: CSPModeSchema,
53
+ directives: CSPDirectivesSchema.optional().refine(
54
+ (val) => {
55
+ try {
56
+ if (typeof val === "string") {
57
+ JSON.parse(val);
58
+ }
59
+ return true;
60
+ } catch (error) {
61
+ return false;
62
+ }
63
+ },
64
+ { message: "DirectivesBadParse" /* DirectivesBadParse */ }
65
+ ).transform(
66
+ (val) => typeof val === "string" ? JSON.parse(val) : val
67
+ )
68
+ }).refine(
69
+ (values) => (
70
+ // validate that directives are provided when the mode is "report-only" or "enforced"
71
+ ["report-only", "enforced"].includes(values.mode) ? !!values.directives : true
72
+ ),
73
+ { path: ["directives"], message: "DirectivesRequired" /* DirectivesRequired */ }
74
+ );
75
+
76
+ // src/utils/cloudflare/make-csp-header.ts
77
+ var addNonce = (value, cspNonce) => value.replace("{{nonce}}", `'nonce-${cspNonce}'`);
78
+ var makeCSPHeader = (cspNonce, directives, mode) => {
79
+ const namesSeen = /* @__PURE__ */ new Set(), result = [];
80
+ Object.entries(directives ?? {}).forEach(([originalName, value]) => {
81
+ const name = originalName.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
82
+ if (namesSeen.has(name)) {
83
+ throw new Error(`${originalName} is specified more than once`);
84
+ }
85
+ namesSeen.add(name);
86
+ if (Array.isArray(value)) {
87
+ value = addNonce(value.join(" "), cspNonce);
88
+ } else if (value === true) {
89
+ value = "";
90
+ }
91
+ if (value) {
92
+ result.push(`${name} ${addNonce(value, cspNonce)}`);
93
+ } else if (value !== false) {
94
+ result.push(name);
95
+ }
96
+ });
97
+ return [
98
+ mode === "enforced" ? "Content-Security-Policy" : "Content-Security-Policy-Report-Only",
99
+ result.join("; ")
100
+ ];
101
+ };
102
+
103
+ // src/middlewares/use-content-security-policy.ts
104
+ var AppendAttribute = (attribute, nonce) => ({
105
+ element: function(element) {
106
+ element.setAttribute(attribute, nonce);
107
+ }
108
+ });
109
+ var useContentSecurityPolicy = (input) => {
110
+ const parsedInput = UseCSPInputSchema.safeParse(input);
111
+ if (!parsedInput.success) {
112
+ throw parsedInput.error;
113
+ }
114
+ const config = parsedInput.data;
115
+ return async (context, next) => {
116
+ await next();
117
+ const { response } = context;
118
+ if (
119
+ // if the csp is disabled
120
+ !["enforced", "report-only"].includes(config.mode)
121
+ ) {
122
+ debug(printMessage("csp is disabled"));
123
+ return;
124
+ }
125
+ if (response.headers.has("Content-Type") && !response.headers.get("Content-Type")?.includes("text/html")) {
126
+ return;
127
+ }
128
+ const cspNonce = btoa(crypto.getRandomValues(new Uint32Array(2)).toString());
129
+ const [cspHeaderName, cspHeaderValue] = makeCSPHeader(
130
+ cspNonce,
131
+ config.directives,
132
+ config.mode
133
+ );
134
+ const nextResponse = new Response(response.body, response);
135
+ nextResponse.headers.set(cspHeaderName, cspHeaderValue);
136
+ nextResponse.headers.set("content-type", "text/html; charset=utf-8");
137
+ context.response = new HTMLRewriter().on("style", AppendAttribute("nonce", cspNonce)).on("script", AppendAttribute("nonce", cspNonce)).transform(nextResponse);
138
+ };
139
+ };
140
+
141
+ export {
142
+ CSPDirectivesSchema,
143
+ CSPModeSchema,
144
+ useContentSecurityPolicy
145
+ };
@@ -0,0 +1,84 @@
1
+ // src/utils/is-cache-url.ts
2
+ var getEdgeConfigId = (value = "") => {
3
+ if (isValidCacheUrl.edgeConfig(value)) {
4
+ const url = new URL(value);
5
+ return url.pathname.replace("/", "");
6
+ }
7
+ return void 0;
8
+ };
9
+ var isCacheUrl = {
10
+ /**
11
+ * Checks if a URL is a valid Edge Config URL (hostname check only)
12
+ * @param value The URL to check
13
+ * @returns True if the URL is a valid Edge Config URL, false otherwise
14
+ */
15
+ edgeConfig: (value = "") => {
16
+ try {
17
+ const url = new URL(value);
18
+ return url.hostname === "edge-config.vercel.com";
19
+ } catch {
20
+ return /^https:\/\/edge-config\.vercel\.com\//.test(value);
21
+ }
22
+ },
23
+ /**
24
+ * Checks if a URL is a valid Upstash URL (hostname check only)
25
+ * @param value The URL to check
26
+ * @returns True if the URL is a valid Upstash URL, false otherwise
27
+ */
28
+ upstash: (value = "") => {
29
+ try {
30
+ const url = new URL(value);
31
+ return url.hostname.endsWith(".upstash.io");
32
+ } catch {
33
+ return /^.*\.upstash\.io$/.test(value || "");
34
+ }
35
+ }
36
+ };
37
+ var isValidCacheUrl = {
38
+ /**
39
+ * Strictly validates an Edge Config URL
40
+ * @param value The URL to validate
41
+ * @returns True if the URL is a valid Edge Config URL, false otherwise
42
+ */
43
+ edgeConfig: (value = "") => {
44
+ try {
45
+ const url = new URL(value);
46
+ return (
47
+ // Only allow HTTPS for security
48
+ url.protocol === "https:" && // Exact hostname match
49
+ url.hostname === "edge-config.vercel.com" && // Path must start with /ecfg_
50
+ url.pathname.startsWith("/ecfg_") && // Must have a token parameter
51
+ url.searchParams.has("token") && // Token should not be empty
52
+ url.searchParams.get("token") !== ""
53
+ );
54
+ } catch {
55
+ return false;
56
+ }
57
+ },
58
+ /**
59
+ * Strictly validates an Upstash URL
60
+ * @param value The URL to validate
61
+ * @returns The password if the URL is valid, false otherwise
62
+ */
63
+ upstash: (value = "") => {
64
+ try {
65
+ const url = new URL(value);
66
+ if (
67
+ // Only allow redis: or rediss: protocols
68
+ ["redis:", "rediss:"].includes(url.protocol) && // Hostname must end with .upstash.io
69
+ url.hostname.endsWith(".upstash.io")
70
+ ) {
71
+ return url.password || "";
72
+ }
73
+ return false;
74
+ } catch {
75
+ return false;
76
+ }
77
+ }
78
+ };
79
+
80
+ export {
81
+ getEdgeConfigId,
82
+ isCacheUrl,
83
+ isValidCacheUrl
84
+ };
@@ -0,0 +1,99 @@
1
+ import { z } from 'zod';
2
+
3
+ declare const ContentSecurityPolicySchema: z.ZodObject<{
4
+ "default-src": z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodString, z.ZodBoolean]>>;
5
+ "script-src": z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodString, z.ZodBoolean]>>;
6
+ "style-src": z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodString, z.ZodBoolean]>>;
7
+ "img-src": z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodString, z.ZodBoolean]>>;
8
+ "connect-src": z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodString, z.ZodBoolean]>>;
9
+ "font-src": z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodString, z.ZodBoolean]>>;
10
+ "object-src": z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodString, z.ZodBoolean]>>;
11
+ "media-src": z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodString, z.ZodBoolean]>>;
12
+ "frame-src": z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodString, z.ZodBoolean]>>;
13
+ sandbox: z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodString, z.ZodBoolean]>>;
14
+ "report-uri": z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodString, z.ZodBoolean]>>;
15
+ "child-src": z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodString, z.ZodBoolean]>>;
16
+ "form-action": z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodString, z.ZodBoolean]>>;
17
+ "frame-ancestors": z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodString, z.ZodBoolean]>>;
18
+ "plugin-types": z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodString, z.ZodBoolean]>>;
19
+ "base-uri": z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodString, z.ZodBoolean]>>;
20
+ "report-to": z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodString, z.ZodBoolean]>>;
21
+ "worker-src": z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodString, z.ZodBoolean]>>;
22
+ "manifest-src": z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodString, z.ZodBoolean]>>;
23
+ "prefetch-src": z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodString, z.ZodBoolean]>>;
24
+ "navigate-to": z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodString, z.ZodBoolean]>>;
25
+ "require-sri-for": z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodString, z.ZodBoolean]>>;
26
+ "block-all-mixed-content": z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodString, z.ZodBoolean]>>;
27
+ "upgrade-insecure-requests": z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodString, z.ZodBoolean]>>;
28
+ "trusted-types": z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodString, z.ZodBoolean]>>;
29
+ "require-trusted-types-for": z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodString, z.ZodBoolean]>>;
30
+ }, "strip", z.ZodTypeAny, {
31
+ "default-src"?: string | boolean | string[] | undefined;
32
+ "script-src"?: string | boolean | string[] | undefined;
33
+ "style-src"?: string | boolean | string[] | undefined;
34
+ "img-src"?: string | boolean | string[] | undefined;
35
+ "connect-src"?: string | boolean | string[] | undefined;
36
+ "font-src"?: string | boolean | string[] | undefined;
37
+ "object-src"?: string | boolean | string[] | undefined;
38
+ "media-src"?: string | boolean | string[] | undefined;
39
+ "frame-src"?: string | boolean | string[] | undefined;
40
+ sandbox?: string | boolean | string[] | undefined;
41
+ "report-uri"?: string | boolean | string[] | undefined;
42
+ "child-src"?: string | boolean | string[] | undefined;
43
+ "form-action"?: string | boolean | string[] | undefined;
44
+ "frame-ancestors"?: string | boolean | string[] | undefined;
45
+ "plugin-types"?: string | boolean | string[] | undefined;
46
+ "base-uri"?: string | boolean | string[] | undefined;
47
+ "report-to"?: string | boolean | string[] | undefined;
48
+ "worker-src"?: string | boolean | string[] | undefined;
49
+ "manifest-src"?: string | boolean | string[] | undefined;
50
+ "prefetch-src"?: string | boolean | string[] | undefined;
51
+ "navigate-to"?: string | boolean | string[] | undefined;
52
+ "require-sri-for"?: string | boolean | string[] | undefined;
53
+ "block-all-mixed-content"?: string | boolean | string[] | undefined;
54
+ "upgrade-insecure-requests"?: string | boolean | string[] | undefined;
55
+ "trusted-types"?: string | boolean | string[] | undefined;
56
+ "require-trusted-types-for"?: string | boolean | string[] | undefined;
57
+ }, {
58
+ "default-src"?: string | boolean | string[] | undefined;
59
+ "script-src"?: string | boolean | string[] | undefined;
60
+ "style-src"?: string | boolean | string[] | undefined;
61
+ "img-src"?: string | boolean | string[] | undefined;
62
+ "connect-src"?: string | boolean | string[] | undefined;
63
+ "font-src"?: string | boolean | string[] | undefined;
64
+ "object-src"?: string | boolean | string[] | undefined;
65
+ "media-src"?: string | boolean | string[] | undefined;
66
+ "frame-src"?: string | boolean | string[] | undefined;
67
+ sandbox?: string | boolean | string[] | undefined;
68
+ "report-uri"?: string | boolean | string[] | undefined;
69
+ "child-src"?: string | boolean | string[] | undefined;
70
+ "form-action"?: string | boolean | string[] | undefined;
71
+ "frame-ancestors"?: string | boolean | string[] | undefined;
72
+ "plugin-types"?: string | boolean | string[] | undefined;
73
+ "base-uri"?: string | boolean | string[] | undefined;
74
+ "report-to"?: string | boolean | string[] | undefined;
75
+ "worker-src"?: string | boolean | string[] | undefined;
76
+ "manifest-src"?: string | boolean | string[] | undefined;
77
+ "prefetch-src"?: string | boolean | string[] | undefined;
78
+ "navigate-to"?: string | boolean | string[] | undefined;
79
+ "require-sri-for"?: string | boolean | string[] | undefined;
80
+ "block-all-mixed-content"?: string | boolean | string[] | undefined;
81
+ "upgrade-insecure-requests"?: string | boolean | string[] | undefined;
82
+ "trusted-types"?: string | boolean | string[] | undefined;
83
+ "require-trusted-types-for"?: string | boolean | string[] | undefined;
84
+ }>;
85
+ type ContentSecurityPolicyType = z.infer<typeof ContentSecurityPolicySchema>;
86
+
87
+ declare global {
88
+ interface CloudflareEnv extends Bindings {
89
+ }
90
+ }
91
+ type Bindings = {
92
+ DEBUG: string | boolean;
93
+ LOCK_PAGE_SLUG: string;
94
+ CSP_MODE: "disabled" | "report-only" | "enforced";
95
+ CSP_DIRECTIVES: string | ContentSecurityPolicyType;
96
+ APPWARDEN_API_TOKEN: string;
97
+ };
98
+
99
+ export type { Bindings as B };
@@ -0,0 +1,45 @@
1
+ import { B as Bindings } from './cloudflare-2PkEr25r.js';
2
+ import { z } from 'zod';
3
+ import { M as Middleware } from './use-content-security-policy-C89AROtC.js';
4
+ export { u as useContentSecurityPolicy } from './use-content-security-policy-C89AROtC.js';
5
+
6
+ declare const ConfigFnInputSchema: z.ZodFunction<z.ZodTuple<[z.ZodType<{
7
+ env: CloudflareEnv;
8
+ cf: Record<string, unknown>;
9
+ ctx: unknown;
10
+ }, z.ZodTypeDef, {
11
+ env: CloudflareEnv;
12
+ cf: Record<string, unknown>;
13
+ ctx: unknown;
14
+ }>], z.ZodUnknown>, z.ZodObject<{
15
+ debug: z.ZodDefault<z.ZodEffects<z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodBoolean]>>, boolean, string | boolean | undefined>>;
16
+ lockPageSlug: z.ZodString;
17
+ appwardenApiToken: z.ZodEffects<z.ZodString, string, string>;
18
+ } & {
19
+ middleware: z.ZodDefault<z.ZodObject<{
20
+ before: z.ZodDefault<z.ZodArray<z.ZodType<Middleware, z.ZodTypeDef, Middleware>, "many">>;
21
+ }, "strip", z.ZodTypeAny, {
22
+ before: Middleware[];
23
+ }, {
24
+ before?: Middleware[] | undefined;
25
+ }>>;
26
+ }, "strip", z.ZodTypeAny, {
27
+ debug: boolean;
28
+ lockPageSlug: string;
29
+ appwardenApiToken: string;
30
+ middleware: {
31
+ before: Middleware[];
32
+ };
33
+ }, {
34
+ lockPageSlug: string;
35
+ appwardenApiToken: string;
36
+ debug?: string | boolean | undefined;
37
+ middleware?: {
38
+ before?: Middleware[] | undefined;
39
+ } | undefined;
40
+ }>>;
41
+ type CloudflareConfigType = ReturnType<z.infer<typeof ConfigFnInputSchema>>;
42
+
43
+ declare const withAppwarden: (inputFn: CloudflareConfigType) => ExportedHandlerFetchHandler<Bindings>;
44
+
45
+ export { withAppwarden };