@appwarden/middleware 3.12.0 → 3.13.1
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/README.md +7 -1
- package/{chunk-EXGUJ5XK.js → chunk-CVOSFBOE.js} +2 -2
- package/{chunk-Z7P4QVEY.js → chunk-OIEAURS7.js} +94 -19
- package/{chunk-ILIYP3TG.js → chunk-Q5LVKCWK.js} +2 -2
- package/{chunk-M2YVPCTG.js → chunk-QM56445N.js} +1 -1
- package/{chunk-HTSD4WPC.js → chunk-U7E4KM2B.js} +96 -29
- package/{chunk-6YCNCR22.js → chunk-UBWPR24M.js} +1 -1
- package/cloudflare/astro.d.ts +2 -2
- package/cloudflare/astro.js +5 -5
- package/cloudflare/nextjs.d.ts +2 -2
- package/cloudflare/nextjs.js +3 -3
- package/cloudflare/react-router.d.ts +2 -2
- package/cloudflare/react-router.js +5 -5
- package/cloudflare/tanstack-start.d.ts +2 -2
- package/cloudflare/tanstack-start.js +5 -5
- package/cloudflare.js +5 -5
- package/index.d.ts +150 -1
- package/index.js +34 -4
- package/package.json +2 -2
- package/vercel.js +2 -2
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
[](https://github.com/appwarden/middleware)
|
|
5
5
|
[](https://www.npmjs.com/package/@appwarden/middleware)
|
|
6
6
|
[](https://docs.npmjs.com/generating-provenance-statements)
|
|
7
|
-

|
|
8
8
|
[](https://opensource.org/licenses/MIT)
|
|
9
9
|
|
|
10
10
|
## Core Features
|
|
@@ -320,6 +320,12 @@ Please review our [security policy](SECURITY.md) for details on how we handle vu
|
|
|
320
320
|
|
|
321
321
|
This package is published with npm trusted publishers, to prevent npm token exfiltration, and 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).
|
|
322
322
|
|
|
323
|
+
## Versioning & dependencies
|
|
324
|
+
|
|
325
|
+
- This project uses Conventional Commits and automated release tooling to keep versions and the changelog up to date.
|
|
326
|
+
- Patch releases may include bug fixes and internal maintenance or dependency updates (for example, Cloudflare Workers types, Wrangler, and GitHub Action tooling). New features are shipped in minor releases.
|
|
327
|
+
- See `CHANGELOG.md` for the complete release history.
|
|
328
|
+
|
|
323
329
|
## License
|
|
324
330
|
|
|
325
331
|
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
@@ -2,12 +2,12 @@ import {
|
|
|
2
2
|
MemoryCache,
|
|
3
3
|
debug,
|
|
4
4
|
printMessage
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-U7E4KM2B.js";
|
|
6
6
|
import {
|
|
7
7
|
APPWARDEN_CACHE_KEY,
|
|
8
8
|
APPWARDEN_TEST_ROUTE,
|
|
9
9
|
LockValue
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-OIEAURS7.js";
|
|
11
11
|
|
|
12
12
|
// src/utils/cloudflare/cloudflare-cache.ts
|
|
13
13
|
var store = {
|
|
@@ -5,10 +5,13 @@ var globalErrors = [errors.badCacheConnection];
|
|
|
5
5
|
var APPWARDEN_TEST_ROUTE = "/_appwarden/test";
|
|
6
6
|
var APPWARDEN_HEARTBEAT_ROUTE = "/_appwarden/heartbeat";
|
|
7
7
|
var HEARTBEAT_CONTRACT_VERSION = 1;
|
|
8
|
+
var HEARTBEAT_VERSION_MAX_LENGTH = 128;
|
|
8
9
|
var HEARTBEAT_CONFIG_ERROR_MAX_COUNT = 10;
|
|
9
10
|
var HEARTBEAT_CONFIG_ERROR_MAX_PATH_DEPTH = 10;
|
|
10
11
|
var HEARTBEAT_CONFIG_ERROR_MAX_CODE_LENGTH = 100;
|
|
11
12
|
var HEARTBEAT_CONFIG_ERROR_MAX_MESSAGE_LENGTH = 500;
|
|
13
|
+
var HEARTBEAT_CONFIG_ERRORS_MAX_SERIALIZED_BYTES = 12 * 1024;
|
|
14
|
+
var HEARTBEAT_RESPONSE_BODY_MAX_SERIALIZED_BYTES = 32 * 1024;
|
|
12
15
|
var HEARTBEAT_CONFIG_ERROR_MAX_PATH_SEGMENT_LENGTH = 100;
|
|
13
16
|
var APPWARDEN_CACHE_KEY = "appwarden-lock";
|
|
14
17
|
var HEARTBEAT_SERVICE_VALUES = [
|
|
@@ -36,13 +39,78 @@ var HEARTBEAT_SERVICES = {
|
|
|
36
39
|
VERCEL
|
|
37
40
|
};
|
|
38
41
|
|
|
42
|
+
// src/types/heartbeat.ts
|
|
43
|
+
import { z } from "zod";
|
|
44
|
+
function getSerializedJsonByteLength(value) {
|
|
45
|
+
return new TextEncoder().encode(JSON.stringify(value)).length;
|
|
46
|
+
}
|
|
47
|
+
function getHeartbeatResponseBodyByteBudgetIssue() {
|
|
48
|
+
return {
|
|
49
|
+
code: z.ZodIssueCode.custom,
|
|
50
|
+
message: `Serialized heartbeat response body must be at most ${HEARTBEAT_RESPONSE_BODY_MAX_SERIALIZED_BYTES} bytes`,
|
|
51
|
+
path: []
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function getHeartbeatResponseBodySerializationIssue() {
|
|
55
|
+
return {
|
|
56
|
+
code: z.ZodIssueCode.custom,
|
|
57
|
+
message: "Heartbeat response body must be JSON-serializable",
|
|
58
|
+
path: []
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
var HeartbeatConfigErrorPathSegmentSchema = z.union([
|
|
62
|
+
z.string().max(HEARTBEAT_CONFIG_ERROR_MAX_PATH_SEGMENT_LENGTH),
|
|
63
|
+
z.number().int().nonnegative()
|
|
64
|
+
]);
|
|
65
|
+
var HeartbeatConfigErrorSchema = z.object({
|
|
66
|
+
path: z.array(HeartbeatConfigErrorPathSegmentSchema).max(HEARTBEAT_CONFIG_ERROR_MAX_PATH_DEPTH),
|
|
67
|
+
code: z.string().min(1).max(HEARTBEAT_CONFIG_ERROR_MAX_CODE_LENGTH),
|
|
68
|
+
message: z.string().min(1).max(HEARTBEAT_CONFIG_ERROR_MAX_MESSAGE_LENGTH)
|
|
69
|
+
}).strict();
|
|
70
|
+
var HeartbeatConfigErrorsSchema = z.array(HeartbeatConfigErrorSchema).max(HEARTBEAT_CONFIG_ERROR_MAX_COUNT).superRefine((configErrors, ctx) => {
|
|
71
|
+
if (getSerializedJsonByteLength(configErrors) > HEARTBEAT_CONFIG_ERRORS_MAX_SERIALIZED_BYTES) {
|
|
72
|
+
ctx.addIssue({
|
|
73
|
+
code: z.ZodIssueCode.custom,
|
|
74
|
+
message: `Serialized configErrors payload must be at most ${HEARTBEAT_CONFIG_ERRORS_MAX_SERIALIZED_BYTES} bytes`
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
var HeartbeatResponseBodySchema = z.object({
|
|
79
|
+
app: z.literal("appwarden"),
|
|
80
|
+
kind: z.literal("heartbeat"),
|
|
81
|
+
status: z.literal("ok"),
|
|
82
|
+
contractVersion: z.literal(HEARTBEAT_CONTRACT_VERSION),
|
|
83
|
+
service: z.enum(HEARTBEAT_SERVICE_VALUES),
|
|
84
|
+
version: z.string().min(1).max(HEARTBEAT_VERSION_MAX_LENGTH),
|
|
85
|
+
configErrors: HeartbeatConfigErrorsSchema
|
|
86
|
+
}).strict().superRefine((body, ctx) => {
|
|
87
|
+
if (getSerializedJsonByteLength(body) > HEARTBEAT_RESPONSE_BODY_MAX_SERIALIZED_BYTES) {
|
|
88
|
+
ctx.addIssue({
|
|
89
|
+
code: z.ZodIssueCode.custom,
|
|
90
|
+
message: `Serialized heartbeat response body must be at most ${HEARTBEAT_RESPONSE_BODY_MAX_SERIALIZED_BYTES} bytes`
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
function validateHeartbeatResponseBody(value) {
|
|
95
|
+
let serializedJsonByteLength;
|
|
96
|
+
try {
|
|
97
|
+
serializedJsonByteLength = getSerializedJsonByteLength(value);
|
|
98
|
+
} catch {
|
|
99
|
+
throw new z.ZodError([getHeartbeatResponseBodySerializationIssue()]);
|
|
100
|
+
}
|
|
101
|
+
if (serializedJsonByteLength > HEARTBEAT_RESPONSE_BODY_MAX_SERIALIZED_BYTES) {
|
|
102
|
+
throw new z.ZodError([getHeartbeatResponseBodyByteBudgetIssue()]);
|
|
103
|
+
}
|
|
104
|
+
return HeartbeatResponseBodySchema.parse(value);
|
|
105
|
+
}
|
|
106
|
+
|
|
39
107
|
// src/schemas/use-content-security-policy.ts
|
|
40
|
-
import { z as
|
|
108
|
+
import { z as z4 } from "zod";
|
|
41
109
|
|
|
42
110
|
// src/types/csp.ts
|
|
43
|
-
import { z } from "zod";
|
|
44
|
-
var stringySchema =
|
|
45
|
-
var ContentSecurityPolicySchema =
|
|
111
|
+
import { z as z2 } from "zod";
|
|
112
|
+
var stringySchema = z2.union([z2.array(z2.string()), z2.string(), z2.boolean()]);
|
|
113
|
+
var ContentSecurityPolicySchema = z2.object({
|
|
46
114
|
"default-src": stringySchema.optional(),
|
|
47
115
|
"script-src": stringySchema.optional(),
|
|
48
116
|
"style-src": stringySchema.optional(),
|
|
@@ -72,8 +140,8 @@ var ContentSecurityPolicySchema = z.object({
|
|
|
72
140
|
});
|
|
73
141
|
|
|
74
142
|
// src/schemas/helpers.ts
|
|
75
|
-
import { z as
|
|
76
|
-
var BoolOrStringSchema =
|
|
143
|
+
import { z as z3 } from "zod";
|
|
144
|
+
var BoolOrStringSchema = z3.union([z3.string(), z3.boolean()]).optional();
|
|
77
145
|
var BooleanSchema = BoolOrStringSchema.transform((val) => {
|
|
78
146
|
if (val === "true" || val === true) {
|
|
79
147
|
return true;
|
|
@@ -82,29 +150,29 @@ var BooleanSchema = BoolOrStringSchema.transform((val) => {
|
|
|
82
150
|
}
|
|
83
151
|
throw new Error("Invalid value");
|
|
84
152
|
});
|
|
85
|
-
var AppwardenApiTokenSchema =
|
|
86
|
-
var AppwardenApiHostnameSchema =
|
|
153
|
+
var AppwardenApiTokenSchema = z3.string().refine((val) => !!val, { message: "appwardenApiToken is required" });
|
|
154
|
+
var AppwardenApiHostnameSchema = z3.string().url({
|
|
87
155
|
message: "Invalid `appwardenApiHostname`. Please provide an absolute URL (e.g. https://api.appwarden.io)."
|
|
88
156
|
}).refine((value) => value.startsWith("https://"), {
|
|
89
157
|
message: "`appwardenApiHostname` must use the https:// scheme (e.g. https://api.appwarden.io)."
|
|
90
158
|
});
|
|
91
|
-
var LockValue =
|
|
92
|
-
isLocked:
|
|
93
|
-
isLockedTest:
|
|
94
|
-
lastCheck:
|
|
159
|
+
var LockValue = z3.object({
|
|
160
|
+
isLocked: z3.number(),
|
|
161
|
+
isLockedTest: z3.number(),
|
|
162
|
+
lastCheck: z3.number()
|
|
95
163
|
});
|
|
96
164
|
|
|
97
165
|
// src/schemas/use-content-security-policy.ts
|
|
98
|
-
var CSPDirectivesSchema =
|
|
99
|
-
|
|
166
|
+
var CSPDirectivesSchema = z4.union([
|
|
167
|
+
z4.string(),
|
|
100
168
|
ContentSecurityPolicySchema
|
|
101
169
|
]);
|
|
102
|
-
var CSPModeSchema =
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
170
|
+
var CSPModeSchema = z4.union([
|
|
171
|
+
z4.literal("disabled"),
|
|
172
|
+
z4.literal("report-only"),
|
|
173
|
+
z4.literal("enforced")
|
|
106
174
|
]);
|
|
107
|
-
var UseCSPInputSchema =
|
|
175
|
+
var UseCSPInputSchema = z4.object({
|
|
108
176
|
mode: CSPModeSchema,
|
|
109
177
|
directives: CSPDirectivesSchema.refine(
|
|
110
178
|
(val) => {
|
|
@@ -130,17 +198,24 @@ export {
|
|
|
130
198
|
APPWARDEN_TEST_ROUTE,
|
|
131
199
|
APPWARDEN_HEARTBEAT_ROUTE,
|
|
132
200
|
HEARTBEAT_CONTRACT_VERSION,
|
|
201
|
+
HEARTBEAT_VERSION_MAX_LENGTH,
|
|
133
202
|
HEARTBEAT_CONFIG_ERROR_MAX_COUNT,
|
|
134
203
|
HEARTBEAT_CONFIG_ERROR_MAX_PATH_DEPTH,
|
|
135
204
|
HEARTBEAT_CONFIG_ERROR_MAX_CODE_LENGTH,
|
|
136
205
|
HEARTBEAT_CONFIG_ERROR_MAX_MESSAGE_LENGTH,
|
|
206
|
+
HEARTBEAT_CONFIG_ERRORS_MAX_SERIALIZED_BYTES,
|
|
207
|
+
HEARTBEAT_RESPONSE_BODY_MAX_SERIALIZED_BYTES,
|
|
137
208
|
HEARTBEAT_CONFIG_ERROR_MAX_PATH_SEGMENT_LENGTH,
|
|
138
209
|
APPWARDEN_CACHE_KEY,
|
|
210
|
+
HEARTBEAT_SERVICE_VALUES,
|
|
139
211
|
HEARTBEAT_SERVICES,
|
|
140
212
|
BooleanSchema,
|
|
141
213
|
AppwardenApiTokenSchema,
|
|
142
214
|
AppwardenApiHostnameSchema,
|
|
143
215
|
LockValue,
|
|
216
|
+
HeartbeatConfigErrorSchema,
|
|
217
|
+
HeartbeatResponseBodySchema,
|
|
218
|
+
validateHeartbeatResponseBody,
|
|
144
219
|
CSPDirectivesSchema,
|
|
145
220
|
CSPModeSchema,
|
|
146
221
|
UseCSPInputSchema
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
isHTMLResponse,
|
|
3
3
|
makeCSPHeader
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-U7E4KM2B.js";
|
|
5
5
|
import {
|
|
6
6
|
UseCSPInputSchema
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-OIEAURS7.js";
|
|
8
8
|
|
|
9
9
|
// src/middlewares/use-content-security-policy.ts
|
|
10
10
|
var AppendAttribute = (attribute, nonce) => ({
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
APPWARDEN_HEARTBEAT_ROUTE,
|
|
3
|
+
HEARTBEAT_CONFIG_ERRORS_MAX_SERIALIZED_BYTES,
|
|
3
4
|
HEARTBEAT_CONFIG_ERROR_MAX_CODE_LENGTH,
|
|
4
5
|
HEARTBEAT_CONFIG_ERROR_MAX_COUNT,
|
|
5
6
|
HEARTBEAT_CONFIG_ERROR_MAX_MESSAGE_LENGTH,
|
|
6
7
|
HEARTBEAT_CONFIG_ERROR_MAX_PATH_DEPTH,
|
|
7
8
|
HEARTBEAT_CONFIG_ERROR_MAX_PATH_SEGMENT_LENGTH,
|
|
8
9
|
HEARTBEAT_CONTRACT_VERSION,
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
HEARTBEAT_RESPONSE_BODY_MAX_SERIALIZED_BYTES,
|
|
11
|
+
LOCKDOWN_TEST_EXPIRY_MS,
|
|
12
|
+
validateHeartbeatResponseBody
|
|
13
|
+
} from "./chunk-OIEAURS7.js";
|
|
11
14
|
|
|
12
15
|
// src/utils/build-lock-page-url.ts
|
|
13
16
|
function normalizeLockPageSlug(lockPageSlug) {
|
|
@@ -119,9 +122,14 @@ var MemoryCache = class {
|
|
|
119
122
|
};
|
|
120
123
|
|
|
121
124
|
// src/version.ts
|
|
122
|
-
var MIDDLEWARE_VERSION = "3.
|
|
125
|
+
var MIDDLEWARE_VERSION = "3.13.0";
|
|
123
126
|
|
|
124
127
|
// src/utils/heartbeat.ts
|
|
128
|
+
var DEFAULT_HEARTBEAT_CONFIG_ERROR_CODE = "custom";
|
|
129
|
+
var DEFAULT_HEARTBEAT_CONFIG_ERROR_MESSAGE = "Appwarden configuration validation failed";
|
|
130
|
+
var HEARTBEAT_CONSTRUCTION_FAILURE_BODY = JSON.stringify({
|
|
131
|
+
error: "appwarden_heartbeat_construction_failed"
|
|
132
|
+
});
|
|
125
133
|
function createSanitizedMessage(code, path) {
|
|
126
134
|
const fieldName = path.length > 0 ? path[path.length - 1] : "field";
|
|
127
135
|
switch (code) {
|
|
@@ -159,39 +167,80 @@ function createSanitizedMessage(code, path) {
|
|
|
159
167
|
return `Validation error for ${fieldName}`;
|
|
160
168
|
}
|
|
161
169
|
}
|
|
170
|
+
function truncateWithEllipsis(value, maxLength) {
|
|
171
|
+
if (value.length <= maxLength) {
|
|
172
|
+
return value;
|
|
173
|
+
}
|
|
174
|
+
if (maxLength <= 3) {
|
|
175
|
+
return value.substring(0, maxLength);
|
|
176
|
+
}
|
|
177
|
+
return value.substring(0, maxLength - 3) + "...";
|
|
178
|
+
}
|
|
179
|
+
function sanitizePathSegment(segment) {
|
|
180
|
+
if (typeof segment === "number" && Number.isFinite(segment)) {
|
|
181
|
+
return Number.isSafeInteger(segment) ? Math.max(0, segment) : Math.max(0, Math.trunc(segment));
|
|
182
|
+
}
|
|
183
|
+
return truncateWithEllipsis(
|
|
184
|
+
typeof segment === "string" ? segment : String(segment),
|
|
185
|
+
HEARTBEAT_CONFIG_ERROR_MAX_PATH_SEGMENT_LENGTH
|
|
186
|
+
);
|
|
187
|
+
}
|
|
162
188
|
function sanitizePath(path) {
|
|
163
189
|
const truncatedPath = path.slice(0, HEARTBEAT_CONFIG_ERROR_MAX_PATH_DEPTH);
|
|
164
|
-
return truncatedPath.map(
|
|
165
|
-
if (typeof segment === "string" && segment.length > HEARTBEAT_CONFIG_ERROR_MAX_PATH_SEGMENT_LENGTH) {
|
|
166
|
-
return segment.substring(
|
|
167
|
-
0,
|
|
168
|
-
HEARTBEAT_CONFIG_ERROR_MAX_PATH_SEGMENT_LENGTH - 3
|
|
169
|
-
) + "...";
|
|
170
|
-
}
|
|
171
|
-
return segment;
|
|
172
|
-
});
|
|
190
|
+
return truncatedPath.map(sanitizePathSegment);
|
|
173
191
|
}
|
|
174
192
|
function truncateMessage(message) {
|
|
175
|
-
|
|
176
|
-
|
|
193
|
+
return truncateWithEllipsis(
|
|
194
|
+
message,
|
|
195
|
+
HEARTBEAT_CONFIG_ERROR_MAX_MESSAGE_LENGTH
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
function truncateCode(code) {
|
|
199
|
+
return truncateWithEllipsis(code, HEARTBEAT_CONFIG_ERROR_MAX_CODE_LENGTH);
|
|
200
|
+
}
|
|
201
|
+
function normalizeNonEmptyString(value, fallback, truncate) {
|
|
202
|
+
const normalizedValue = truncate(value.trim());
|
|
203
|
+
if (normalizedValue.length > 0) {
|
|
204
|
+
return normalizedValue;
|
|
177
205
|
}
|
|
178
|
-
return
|
|
206
|
+
return truncate(fallback);
|
|
207
|
+
}
|
|
208
|
+
function getSerializedJsonByteLength(value) {
|
|
209
|
+
return new TextEncoder().encode(JSON.stringify(value)).length;
|
|
210
|
+
}
|
|
211
|
+
function isConfigErrorsWithinByteBudget(configErrors) {
|
|
212
|
+
return getSerializedJsonByteLength(configErrors) <= HEARTBEAT_CONFIG_ERRORS_MAX_SERIALIZED_BYTES;
|
|
213
|
+
}
|
|
214
|
+
function isResponseBodyWithinByteBudget(body) {
|
|
215
|
+
return getSerializedJsonByteLength(body) <= HEARTBEAT_RESPONSE_BODY_MAX_SERIALIZED_BYTES;
|
|
179
216
|
}
|
|
180
217
|
function createHeartbeatConfigError(path, code, message) {
|
|
181
218
|
return {
|
|
182
219
|
path: sanitizePath(path),
|
|
183
|
-
code:
|
|
184
|
-
|
|
220
|
+
code: normalizeNonEmptyString(
|
|
221
|
+
code,
|
|
222
|
+
DEFAULT_HEARTBEAT_CONFIG_ERROR_CODE,
|
|
223
|
+
truncateCode
|
|
224
|
+
),
|
|
225
|
+
message: normalizeNonEmptyString(
|
|
226
|
+
message,
|
|
227
|
+
DEFAULT_HEARTBEAT_CONFIG_ERROR_MESSAGE,
|
|
228
|
+
truncateMessage
|
|
229
|
+
)
|
|
185
230
|
};
|
|
186
231
|
}
|
|
187
232
|
function normalizeHeartbeatConfigErrors(configErrors) {
|
|
188
|
-
|
|
233
|
+
const normalizedConfigErrors = configErrors.slice(0, HEARTBEAT_CONFIG_ERROR_MAX_COUNT).map(
|
|
189
234
|
(configError) => createHeartbeatConfigError(
|
|
190
235
|
configError.path,
|
|
191
236
|
configError.code,
|
|
192
237
|
configError.message
|
|
193
238
|
)
|
|
194
239
|
);
|
|
240
|
+
while (normalizedConfigErrors.length > 0 && !isConfigErrorsWithinByteBudget(normalizedConfigErrors)) {
|
|
241
|
+
normalizedConfigErrors.pop();
|
|
242
|
+
}
|
|
243
|
+
return normalizedConfigErrors;
|
|
195
244
|
}
|
|
196
245
|
function sanitizeConfigErrors(error) {
|
|
197
246
|
if (!error) {
|
|
@@ -213,30 +262,48 @@ function sanitizeConfigErrors(error) {
|
|
|
213
262
|
return errors;
|
|
214
263
|
}
|
|
215
264
|
function createHeartbeatResponseBody(service, configErrors = []) {
|
|
216
|
-
|
|
265
|
+
const normalizedConfigErrors = normalizeHeartbeatConfigErrors(configErrors);
|
|
266
|
+
const body = {
|
|
217
267
|
app: "appwarden",
|
|
218
268
|
kind: "heartbeat",
|
|
219
269
|
status: "ok",
|
|
220
270
|
contractVersion: HEARTBEAT_CONTRACT_VERSION,
|
|
221
271
|
service,
|
|
222
272
|
version: MIDDLEWARE_VERSION,
|
|
223
|
-
configErrors:
|
|
273
|
+
configErrors: normalizedConfigErrors
|
|
224
274
|
};
|
|
275
|
+
while (body.configErrors.length > 0 && !isResponseBodyWithinByteBudget(body)) {
|
|
276
|
+
body.configErrors.pop();
|
|
277
|
+
}
|
|
278
|
+
return validateHeartbeatResponseBody(body);
|
|
225
279
|
}
|
|
226
|
-
function
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
status: 200,
|
|
280
|
+
function createHeartbeatConstructionFailureResponse() {
|
|
281
|
+
return new Response(HEARTBEAT_CONSTRUCTION_FAILURE_BODY, {
|
|
282
|
+
status: 500,
|
|
230
283
|
headers: {
|
|
231
284
|
"content-type": "application/json",
|
|
232
|
-
"cache-control": "no-store"
|
|
233
|
-
"x-appwarden-heartbeat": "1",
|
|
234
|
-
"x-appwarden-contract-version": String(HEARTBEAT_CONTRACT_VERSION),
|
|
235
|
-
"x-appwarden-service": service,
|
|
236
|
-
"x-appwarden-version": MIDDLEWARE_VERSION
|
|
285
|
+
"cache-control": "no-store"
|
|
237
286
|
}
|
|
238
287
|
});
|
|
239
288
|
}
|
|
289
|
+
function createHeartbeatResponse(service, configErrors = []) {
|
|
290
|
+
try {
|
|
291
|
+
const body = createHeartbeatResponseBody(service, configErrors);
|
|
292
|
+
return new Response(JSON.stringify(body), {
|
|
293
|
+
status: 200,
|
|
294
|
+
headers: {
|
|
295
|
+
"content-type": "application/json",
|
|
296
|
+
"cache-control": "no-store",
|
|
297
|
+
"x-appwarden-heartbeat": "1",
|
|
298
|
+
"x-appwarden-contract-version": String(HEARTBEAT_CONTRACT_VERSION),
|
|
299
|
+
"x-appwarden-service": service,
|
|
300
|
+
"x-appwarden-version": MIDDLEWARE_VERSION
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
} catch {
|
|
304
|
+
return createHeartbeatConstructionFailureResponse();
|
|
305
|
+
}
|
|
306
|
+
}
|
|
240
307
|
function isHeartbeatRoute(url) {
|
|
241
308
|
return url.pathname === APPWARDEN_HEARTBEAT_ROUTE;
|
|
242
309
|
}
|
package/cloudflare/astro.d.ts
CHANGED
|
@@ -270,8 +270,8 @@ declare const AstroCloudflareConfigSchema: z.ZodObject<{
|
|
|
270
270
|
};
|
|
271
271
|
}>>>;
|
|
272
272
|
}, "strip", z.ZodTypeAny, {
|
|
273
|
-
lockPageSlug: string;
|
|
274
273
|
debug: boolean;
|
|
274
|
+
lockPageSlug: string;
|
|
275
275
|
appwardenApiToken: string;
|
|
276
276
|
contentSecurityPolicy?: {
|
|
277
277
|
mode: "disabled" | "report-only" | "enforced";
|
|
@@ -308,6 +308,7 @@ declare const AstroCloudflareConfigSchema: z.ZodObject<{
|
|
|
308
308
|
}, {
|
|
309
309
|
lockPageSlug: string;
|
|
310
310
|
appwardenApiToken: string;
|
|
311
|
+
debug?: string | boolean | undefined;
|
|
311
312
|
contentSecurityPolicy?: {
|
|
312
313
|
mode: "disabled" | "report-only" | "enforced";
|
|
313
314
|
directives: string | {
|
|
@@ -339,7 +340,6 @@ declare const AstroCloudflareConfigSchema: z.ZodObject<{
|
|
|
339
340
|
"require-trusted-types-for"?: string | boolean | string[] | undefined;
|
|
340
341
|
};
|
|
341
342
|
} | undefined;
|
|
342
|
-
debug?: string | boolean | undefined;
|
|
343
343
|
appwardenApiHostname?: string | undefined;
|
|
344
344
|
}>;
|
|
345
345
|
type AstroCloudflareConfig = z.infer<typeof AstroCloudflareConfigSchema>;
|
package/cloudflare/astro.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
applyContentSecurityPolicyToResponse,
|
|
3
3
|
isResponseLike
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-
|
|
4
|
+
} from "../chunk-QM56445N.js";
|
|
5
|
+
import "../chunk-Q5LVKCWK.js";
|
|
6
6
|
import {
|
|
7
7
|
getNowMs,
|
|
8
8
|
logElapsed
|
|
9
9
|
} from "../chunk-G6BMPIYD.js";
|
|
10
10
|
import {
|
|
11
11
|
checkLockStatus
|
|
12
|
-
} from "../chunk-
|
|
12
|
+
} from "../chunk-CVOSFBOE.js";
|
|
13
13
|
import {
|
|
14
14
|
TEMPORARY_REDIRECT_STATUS,
|
|
15
15
|
buildLockPageUrl,
|
|
@@ -22,14 +22,14 @@ import {
|
|
|
22
22
|
isOnLockPage,
|
|
23
23
|
printMessage,
|
|
24
24
|
sanitizeConfigErrors
|
|
25
|
-
} from "../chunk-
|
|
25
|
+
} from "../chunk-U7E4KM2B.js";
|
|
26
26
|
import {
|
|
27
27
|
AppwardenApiHostnameSchema,
|
|
28
28
|
AppwardenApiTokenSchema,
|
|
29
29
|
BooleanSchema,
|
|
30
30
|
HEARTBEAT_SERVICES,
|
|
31
31
|
UseCSPInputSchema
|
|
32
|
-
} from "../chunk-
|
|
32
|
+
} from "../chunk-OIEAURS7.js";
|
|
33
33
|
|
|
34
34
|
// src/adapters/astro-cloudflare.ts
|
|
35
35
|
import { waitUntil } from "cloudflare:workers";
|
package/cloudflare/nextjs.d.ts
CHANGED
|
@@ -329,8 +329,8 @@ declare const NextJsCloudflareConfigSchema: z.ZodObject<{
|
|
|
329
329
|
};
|
|
330
330
|
}>>>;
|
|
331
331
|
}, "strip", z.ZodTypeAny, {
|
|
332
|
-
lockPageSlug: string;
|
|
333
332
|
debug: boolean;
|
|
333
|
+
lockPageSlug: string;
|
|
334
334
|
appwardenApiToken: string;
|
|
335
335
|
contentSecurityPolicy?: {
|
|
336
336
|
mode: "disabled" | "report-only" | "enforced";
|
|
@@ -367,6 +367,7 @@ declare const NextJsCloudflareConfigSchema: z.ZodObject<{
|
|
|
367
367
|
}, {
|
|
368
368
|
lockPageSlug: string;
|
|
369
369
|
appwardenApiToken: string;
|
|
370
|
+
debug?: string | boolean | undefined;
|
|
370
371
|
contentSecurityPolicy?: {
|
|
371
372
|
mode: "disabled" | "report-only" | "enforced";
|
|
372
373
|
directives: string | {
|
|
@@ -398,7 +399,6 @@ declare const NextJsCloudflareConfigSchema: z.ZodObject<{
|
|
|
398
399
|
"require-trusted-types-for"?: string | boolean | string[] | undefined;
|
|
399
400
|
};
|
|
400
401
|
} | undefined;
|
|
401
|
-
debug?: string | boolean | undefined;
|
|
402
402
|
appwardenApiHostname?: string | undefined;
|
|
403
403
|
}>;
|
|
404
404
|
type NextJsCloudflareConfig = z.infer<typeof NextJsCloudflareConfigSchema>;
|
package/cloudflare/nextjs.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
} from "../chunk-G6BMPIYD.js";
|
|
8
8
|
import {
|
|
9
9
|
checkLockStatus
|
|
10
|
-
} from "../chunk-
|
|
10
|
+
} from "../chunk-CVOSFBOE.js";
|
|
11
11
|
import {
|
|
12
12
|
TEMPORARY_REDIRECT_STATUS,
|
|
13
13
|
buildLockPageUrl,
|
|
@@ -20,14 +20,14 @@ import {
|
|
|
20
20
|
makeCSPHeader,
|
|
21
21
|
printMessage,
|
|
22
22
|
sanitizeConfigErrors
|
|
23
|
-
} from "../chunk-
|
|
23
|
+
} from "../chunk-U7E4KM2B.js";
|
|
24
24
|
import {
|
|
25
25
|
AppwardenApiHostnameSchema,
|
|
26
26
|
AppwardenApiTokenSchema,
|
|
27
27
|
BooleanSchema,
|
|
28
28
|
HEARTBEAT_SERVICES,
|
|
29
29
|
UseCSPInputSchema
|
|
30
|
-
} from "../chunk-
|
|
30
|
+
} from "../chunk-OIEAURS7.js";
|
|
31
31
|
|
|
32
32
|
// src/adapters/nextjs-cloudflare.ts
|
|
33
33
|
import { getCloudflareContext } from "@opennextjs/cloudflare";
|
|
@@ -268,8 +268,8 @@ declare const ReactRouterCloudflareConfigSchema: z.ZodObject<{
|
|
|
268
268
|
};
|
|
269
269
|
}>>>;
|
|
270
270
|
}, "strip", z.ZodTypeAny, {
|
|
271
|
-
lockPageSlug: string;
|
|
272
271
|
debug: boolean;
|
|
272
|
+
lockPageSlug: string;
|
|
273
273
|
appwardenApiToken: string;
|
|
274
274
|
contentSecurityPolicy?: {
|
|
275
275
|
mode: "disabled" | "report-only" | "enforced";
|
|
@@ -306,6 +306,7 @@ declare const ReactRouterCloudflareConfigSchema: z.ZodObject<{
|
|
|
306
306
|
}, {
|
|
307
307
|
lockPageSlug: string;
|
|
308
308
|
appwardenApiToken: string;
|
|
309
|
+
debug?: string | boolean | undefined;
|
|
309
310
|
contentSecurityPolicy?: {
|
|
310
311
|
mode: "disabled" | "report-only" | "enforced";
|
|
311
312
|
directives: string | {
|
|
@@ -337,7 +338,6 @@ declare const ReactRouterCloudflareConfigSchema: z.ZodObject<{
|
|
|
337
338
|
"require-trusted-types-for"?: string | boolean | string[] | undefined;
|
|
338
339
|
};
|
|
339
340
|
} | undefined;
|
|
340
|
-
debug?: string | boolean | undefined;
|
|
341
341
|
appwardenApiHostname?: string | undefined;
|
|
342
342
|
}>;
|
|
343
343
|
type ReactRouterCloudflareConfig = z.infer<typeof ReactRouterCloudflareConfigSchema>;
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
applyContentSecurityPolicyToResponse,
|
|
3
3
|
isResponseLike
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-
|
|
4
|
+
} from "../chunk-QM56445N.js";
|
|
5
|
+
import "../chunk-Q5LVKCWK.js";
|
|
6
6
|
import {
|
|
7
7
|
getNowMs,
|
|
8
8
|
logElapsed
|
|
9
9
|
} from "../chunk-G6BMPIYD.js";
|
|
10
10
|
import {
|
|
11
11
|
checkLockStatus
|
|
12
|
-
} from "../chunk-
|
|
12
|
+
} from "../chunk-CVOSFBOE.js";
|
|
13
13
|
import {
|
|
14
14
|
buildLockPageUrl,
|
|
15
15
|
createHeartbeatConfigError,
|
|
@@ -21,14 +21,14 @@ import {
|
|
|
21
21
|
isOnLockPage,
|
|
22
22
|
printMessage,
|
|
23
23
|
sanitizeConfigErrors
|
|
24
|
-
} from "../chunk-
|
|
24
|
+
} from "../chunk-U7E4KM2B.js";
|
|
25
25
|
import {
|
|
26
26
|
AppwardenApiHostnameSchema,
|
|
27
27
|
AppwardenApiTokenSchema,
|
|
28
28
|
BooleanSchema,
|
|
29
29
|
HEARTBEAT_SERVICES,
|
|
30
30
|
UseCSPInputSchema
|
|
31
|
-
} from "../chunk-
|
|
31
|
+
} from "../chunk-OIEAURS7.js";
|
|
32
32
|
|
|
33
33
|
// src/adapters/react-router-cloudflare.ts
|
|
34
34
|
import { waitUntil } from "cloudflare:workers";
|
|
@@ -268,8 +268,8 @@ declare const TanStackStartCloudflareConfigSchema: z.ZodObject<{
|
|
|
268
268
|
};
|
|
269
269
|
}>>>;
|
|
270
270
|
}, "strip", z.ZodTypeAny, {
|
|
271
|
-
lockPageSlug: string;
|
|
272
271
|
debug: boolean;
|
|
272
|
+
lockPageSlug: string;
|
|
273
273
|
appwardenApiToken: string;
|
|
274
274
|
contentSecurityPolicy?: {
|
|
275
275
|
mode: "disabled" | "report-only" | "enforced";
|
|
@@ -306,6 +306,7 @@ declare const TanStackStartCloudflareConfigSchema: z.ZodObject<{
|
|
|
306
306
|
}, {
|
|
307
307
|
lockPageSlug: string;
|
|
308
308
|
appwardenApiToken: string;
|
|
309
|
+
debug?: string | boolean | undefined;
|
|
309
310
|
contentSecurityPolicy?: {
|
|
310
311
|
mode: "disabled" | "report-only" | "enforced";
|
|
311
312
|
directives: string | {
|
|
@@ -337,7 +338,6 @@ declare const TanStackStartCloudflareConfigSchema: z.ZodObject<{
|
|
|
337
338
|
"require-trusted-types-for"?: string | boolean | string[] | undefined;
|
|
338
339
|
};
|
|
339
340
|
} | undefined;
|
|
340
|
-
debug?: string | boolean | undefined;
|
|
341
341
|
appwardenApiHostname?: string | undefined;
|
|
342
342
|
}>;
|
|
343
343
|
type TanStackStartCloudflareConfig = z.infer<typeof TanStackStartCloudflareConfigSchema>;
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
applyContentSecurityPolicyToResponse,
|
|
3
3
|
isResponseLike
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-
|
|
4
|
+
} from "../chunk-QM56445N.js";
|
|
5
|
+
import "../chunk-Q5LVKCWK.js";
|
|
6
6
|
import {
|
|
7
7
|
getNowMs,
|
|
8
8
|
logElapsed
|
|
9
9
|
} from "../chunk-G6BMPIYD.js";
|
|
10
10
|
import {
|
|
11
11
|
checkLockStatus
|
|
12
|
-
} from "../chunk-
|
|
12
|
+
} from "../chunk-CVOSFBOE.js";
|
|
13
13
|
import {
|
|
14
14
|
buildLockPageUrl,
|
|
15
15
|
createHeartbeatConfigError,
|
|
@@ -21,14 +21,14 @@ import {
|
|
|
21
21
|
isOnLockPage,
|
|
22
22
|
printMessage,
|
|
23
23
|
sanitizeConfigErrors
|
|
24
|
-
} from "../chunk-
|
|
24
|
+
} from "../chunk-U7E4KM2B.js";
|
|
25
25
|
import {
|
|
26
26
|
AppwardenApiHostnameSchema,
|
|
27
27
|
AppwardenApiTokenSchema,
|
|
28
28
|
BooleanSchema,
|
|
29
29
|
HEARTBEAT_SERVICES,
|
|
30
30
|
UseCSPInputSchema
|
|
31
|
-
} from "../chunk-
|
|
31
|
+
} from "../chunk-OIEAURS7.js";
|
|
32
32
|
|
|
33
33
|
// src/adapters/tanstack-start-cloudflare.ts
|
|
34
34
|
import { waitUntil } from "cloudflare:workers";
|
package/cloudflare.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
UseAppwardenInputSchema,
|
|
3
3
|
lockPageSlugRefinement
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-UBWPR24M.js";
|
|
5
5
|
import {
|
|
6
6
|
getErrors
|
|
7
7
|
} from "./chunk-NV7K5PRA.js";
|
|
8
8
|
import {
|
|
9
9
|
useContentSecurityPolicy
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-Q5LVKCWK.js";
|
|
11
11
|
import {
|
|
12
12
|
checkLockStatus
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-CVOSFBOE.js";
|
|
14
14
|
import {
|
|
15
15
|
buildLockPageUrl,
|
|
16
16
|
createHeartbeatConfigError,
|
|
@@ -22,10 +22,10 @@ import {
|
|
|
22
22
|
isOnLockPage,
|
|
23
23
|
printMessage,
|
|
24
24
|
sanitizeConfigErrors
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-U7E4KM2B.js";
|
|
26
26
|
import {
|
|
27
27
|
HEARTBEAT_SERVICES
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-OIEAURS7.js";
|
|
29
29
|
|
|
30
30
|
// src/runners/appwarden-on-cloudflare.ts
|
|
31
31
|
import { ZodError } from "zod";
|
package/index.d.ts
CHANGED
|
@@ -2,7 +2,156 @@ export { B as Bindings, C as CSPDirectivesSchema, a as CSPModeSchema, M as Middl
|
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
|
|
4
4
|
declare const LOCKDOWN_TEST_EXPIRY_MS: number;
|
|
5
|
+
declare const APPWARDEN_HEARTBEAT_ROUTE = "/_appwarden/heartbeat";
|
|
6
|
+
declare const HEARTBEAT_CONTRACT_VERSION: 1;
|
|
7
|
+
declare const HEARTBEAT_VERSION_MAX_LENGTH = 128;
|
|
8
|
+
/**
|
|
9
|
+
* Maximum number of public heartbeat config errors.
|
|
10
|
+
* Prevents unbounded response sizes.
|
|
11
|
+
*/
|
|
12
|
+
declare const HEARTBEAT_CONFIG_ERROR_MAX_COUNT = 10;
|
|
13
|
+
/**
|
|
14
|
+
* Maximum path depth for public heartbeat config errors.
|
|
15
|
+
* Prevents deeply nested paths from being exposed.
|
|
16
|
+
*/
|
|
17
|
+
declare const HEARTBEAT_CONFIG_ERROR_MAX_PATH_DEPTH = 10;
|
|
18
|
+
/**
|
|
19
|
+
* Maximum length for public heartbeat config error codes.
|
|
20
|
+
* Keeps error codes within the contract bounds.
|
|
21
|
+
*/
|
|
22
|
+
declare const HEARTBEAT_CONFIG_ERROR_MAX_CODE_LENGTH = 100;
|
|
23
|
+
/**
|
|
24
|
+
* Maximum length for public heartbeat config error messages.
|
|
25
|
+
* Prevents excessively long messages from being exposed.
|
|
26
|
+
*/
|
|
27
|
+
declare const HEARTBEAT_CONFIG_ERROR_MAX_MESSAGE_LENGTH = 500;
|
|
28
|
+
declare const HEARTBEAT_CONFIG_ERRORS_MAX_SERIALIZED_BYTES: number;
|
|
29
|
+
declare const HEARTBEAT_RESPONSE_BODY_MAX_SERIALIZED_BYTES: number;
|
|
30
|
+
/**
|
|
31
|
+
* Maximum length for individual public heartbeat config error path segments.
|
|
32
|
+
* Prevents excessively long path segments from being exposed.
|
|
33
|
+
*/
|
|
34
|
+
declare const HEARTBEAT_CONFIG_ERROR_MAX_PATH_SEGMENT_LENGTH = 100;
|
|
5
35
|
declare const APPWARDEN_CACHE_KEY: "appwarden-lock";
|
|
36
|
+
declare const HEARTBEAT_SERVICE_VALUES: readonly ["cloudflare", "cloudflare-astro", "cloudflare-react-router", "cloudflare-tanstack-start", "cloudflare-nextjs", "vercel"];
|
|
37
|
+
/**
|
|
38
|
+
* Service identifiers for different middleware adapters.
|
|
39
|
+
* These are hardcoded per adapter bundle.
|
|
40
|
+
*/
|
|
41
|
+
declare const HEARTBEAT_SERVICES: {
|
|
42
|
+
readonly CLOUDFLARE: "cloudflare";
|
|
43
|
+
readonly CLOUDFLARE_ASTRO: "cloudflare-astro";
|
|
44
|
+
readonly CLOUDFLARE_REACT_ROUTER: "cloudflare-react-router";
|
|
45
|
+
readonly CLOUDFLARE_TANSTACK_START: "cloudflare-tanstack-start";
|
|
46
|
+
readonly CLOUDFLARE_NEXTJS: "cloudflare-nextjs";
|
|
47
|
+
readonly VERCEL: "vercel";
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Service identifiers for different middleware adapters.
|
|
52
|
+
* These are hardcoded per adapter bundle.
|
|
53
|
+
*/
|
|
54
|
+
type HeartbeatService = (typeof HEARTBEAT_SERVICE_VALUES)[number];
|
|
55
|
+
/**
|
|
56
|
+
* Schema for validating heartbeat config errors.
|
|
57
|
+
* Ensures errors are bounded and sanitized.
|
|
58
|
+
*/
|
|
59
|
+
declare const HeartbeatConfigErrorSchema: z.ZodObject<{
|
|
60
|
+
path: z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodNumber]>, "many">;
|
|
61
|
+
code: z.ZodString;
|
|
62
|
+
message: z.ZodString;
|
|
63
|
+
}, "strict", z.ZodTypeAny, {
|
|
64
|
+
message: string;
|
|
65
|
+
code: string;
|
|
66
|
+
path: (string | number)[];
|
|
67
|
+
}, {
|
|
68
|
+
message: string;
|
|
69
|
+
code: string;
|
|
70
|
+
path: (string | number)[];
|
|
71
|
+
}>;
|
|
72
|
+
type HeartbeatConfigError = z.infer<typeof HeartbeatConfigErrorSchema>;
|
|
73
|
+
/**
|
|
74
|
+
* Schema for validating the heartbeat response body.
|
|
75
|
+
*/
|
|
76
|
+
declare const HeartbeatResponseBodySchema: z.ZodEffects<z.ZodObject<{
|
|
77
|
+
app: z.ZodLiteral<"appwarden">;
|
|
78
|
+
kind: z.ZodLiteral<"heartbeat">;
|
|
79
|
+
status: z.ZodLiteral<"ok">;
|
|
80
|
+
contractVersion: z.ZodLiteral<1>;
|
|
81
|
+
service: z.ZodEnum<["cloudflare", "cloudflare-astro", "cloudflare-react-router", "cloudflare-tanstack-start", "cloudflare-nextjs", "vercel"]>;
|
|
82
|
+
version: z.ZodString;
|
|
83
|
+
configErrors: z.ZodEffects<z.ZodArray<z.ZodObject<{
|
|
84
|
+
path: z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodNumber]>, "many">;
|
|
85
|
+
code: z.ZodString;
|
|
86
|
+
message: z.ZodString;
|
|
87
|
+
}, "strict", z.ZodTypeAny, {
|
|
88
|
+
message: string;
|
|
89
|
+
code: string;
|
|
90
|
+
path: (string | number)[];
|
|
91
|
+
}, {
|
|
92
|
+
message: string;
|
|
93
|
+
code: string;
|
|
94
|
+
path: (string | number)[];
|
|
95
|
+
}>, "many">, {
|
|
96
|
+
message: string;
|
|
97
|
+
code: string;
|
|
98
|
+
path: (string | number)[];
|
|
99
|
+
}[], {
|
|
100
|
+
message: string;
|
|
101
|
+
code: string;
|
|
102
|
+
path: (string | number)[];
|
|
103
|
+
}[]>;
|
|
104
|
+
}, "strict", z.ZodTypeAny, {
|
|
105
|
+
status: "ok";
|
|
106
|
+
app: "appwarden";
|
|
107
|
+
kind: "heartbeat";
|
|
108
|
+
contractVersion: 1;
|
|
109
|
+
service: "cloudflare" | "cloudflare-astro" | "cloudflare-react-router" | "cloudflare-tanstack-start" | "cloudflare-nextjs" | "vercel";
|
|
110
|
+
version: string;
|
|
111
|
+
configErrors: {
|
|
112
|
+
message: string;
|
|
113
|
+
code: string;
|
|
114
|
+
path: (string | number)[];
|
|
115
|
+
}[];
|
|
116
|
+
}, {
|
|
117
|
+
status: "ok";
|
|
118
|
+
app: "appwarden";
|
|
119
|
+
kind: "heartbeat";
|
|
120
|
+
contractVersion: 1;
|
|
121
|
+
service: "cloudflare" | "cloudflare-astro" | "cloudflare-react-router" | "cloudflare-tanstack-start" | "cloudflare-nextjs" | "vercel";
|
|
122
|
+
version: string;
|
|
123
|
+
configErrors: {
|
|
124
|
+
message: string;
|
|
125
|
+
code: string;
|
|
126
|
+
path: (string | number)[];
|
|
127
|
+
}[];
|
|
128
|
+
}>, {
|
|
129
|
+
status: "ok";
|
|
130
|
+
app: "appwarden";
|
|
131
|
+
kind: "heartbeat";
|
|
132
|
+
contractVersion: 1;
|
|
133
|
+
service: "cloudflare" | "cloudflare-astro" | "cloudflare-react-router" | "cloudflare-tanstack-start" | "cloudflare-nextjs" | "vercel";
|
|
134
|
+
version: string;
|
|
135
|
+
configErrors: {
|
|
136
|
+
message: string;
|
|
137
|
+
code: string;
|
|
138
|
+
path: (string | number)[];
|
|
139
|
+
}[];
|
|
140
|
+
}, {
|
|
141
|
+
status: "ok";
|
|
142
|
+
app: "appwarden";
|
|
143
|
+
kind: "heartbeat";
|
|
144
|
+
contractVersion: 1;
|
|
145
|
+
service: "cloudflare" | "cloudflare-astro" | "cloudflare-react-router" | "cloudflare-tanstack-start" | "cloudflare-nextjs" | "vercel";
|
|
146
|
+
version: string;
|
|
147
|
+
configErrors: {
|
|
148
|
+
message: string;
|
|
149
|
+
code: string;
|
|
150
|
+
path: (string | number)[];
|
|
151
|
+
}[];
|
|
152
|
+
}>;
|
|
153
|
+
type HeartbeatResponseBody = z.infer<typeof HeartbeatResponseBodySchema>;
|
|
154
|
+
declare function validateHeartbeatResponseBody(value: unknown): HeartbeatResponseBody;
|
|
6
155
|
|
|
7
156
|
/**
|
|
8
157
|
* Extracts the Edge Config ID from a valid Edge Config URL
|
|
@@ -787,4 +936,4 @@ declare const LockValue: z.ZodObject<{
|
|
|
787
936
|
}>;
|
|
788
937
|
type LockValueType = z.infer<typeof LockValue>;
|
|
789
938
|
|
|
790
|
-
export { APPWARDEN_CACHE_KEY, LOCKDOWN_TEST_EXPIRY_MS, type LockValueType, UseAppwardenInputSchema, getEdgeConfigId, isCacheUrl, isValidCacheUrl };
|
|
939
|
+
export { APPWARDEN_CACHE_KEY, APPWARDEN_HEARTBEAT_ROUTE, HEARTBEAT_CONFIG_ERRORS_MAX_SERIALIZED_BYTES, HEARTBEAT_CONFIG_ERROR_MAX_CODE_LENGTH, HEARTBEAT_CONFIG_ERROR_MAX_COUNT, HEARTBEAT_CONFIG_ERROR_MAX_MESSAGE_LENGTH, HEARTBEAT_CONFIG_ERROR_MAX_PATH_DEPTH, HEARTBEAT_CONFIG_ERROR_MAX_PATH_SEGMENT_LENGTH, HEARTBEAT_CONTRACT_VERSION, HEARTBEAT_RESPONSE_BODY_MAX_SERIALIZED_BYTES, HEARTBEAT_SERVICES, HEARTBEAT_SERVICE_VALUES, HEARTBEAT_VERSION_MAX_LENGTH, type HeartbeatConfigError, HeartbeatConfigErrorSchema, type HeartbeatResponseBody, HeartbeatResponseBodySchema, type HeartbeatService, LOCKDOWN_TEST_EXPIRY_MS, type LockValueType, UseAppwardenInputSchema, getEdgeConfigId, isCacheUrl, isValidCacheUrl, validateHeartbeatResponseBody };
|
package/index.js
CHANGED
|
@@ -5,20 +5,50 @@ import {
|
|
|
5
5
|
} from "./chunk-QEFORWCW.js";
|
|
6
6
|
import {
|
|
7
7
|
UseAppwardenInputSchema
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-UBWPR24M.js";
|
|
9
9
|
import {
|
|
10
10
|
APPWARDEN_CACHE_KEY,
|
|
11
|
+
APPWARDEN_HEARTBEAT_ROUTE,
|
|
11
12
|
CSPDirectivesSchema,
|
|
12
13
|
CSPModeSchema,
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
HEARTBEAT_CONFIG_ERRORS_MAX_SERIALIZED_BYTES,
|
|
15
|
+
HEARTBEAT_CONFIG_ERROR_MAX_CODE_LENGTH,
|
|
16
|
+
HEARTBEAT_CONFIG_ERROR_MAX_COUNT,
|
|
17
|
+
HEARTBEAT_CONFIG_ERROR_MAX_MESSAGE_LENGTH,
|
|
18
|
+
HEARTBEAT_CONFIG_ERROR_MAX_PATH_DEPTH,
|
|
19
|
+
HEARTBEAT_CONFIG_ERROR_MAX_PATH_SEGMENT_LENGTH,
|
|
20
|
+
HEARTBEAT_CONTRACT_VERSION,
|
|
21
|
+
HEARTBEAT_RESPONSE_BODY_MAX_SERIALIZED_BYTES,
|
|
22
|
+
HEARTBEAT_SERVICES,
|
|
23
|
+
HEARTBEAT_SERVICE_VALUES,
|
|
24
|
+
HEARTBEAT_VERSION_MAX_LENGTH,
|
|
25
|
+
HeartbeatConfigErrorSchema,
|
|
26
|
+
HeartbeatResponseBodySchema,
|
|
27
|
+
LOCKDOWN_TEST_EXPIRY_MS,
|
|
28
|
+
validateHeartbeatResponseBody
|
|
29
|
+
} from "./chunk-OIEAURS7.js";
|
|
15
30
|
export {
|
|
16
31
|
APPWARDEN_CACHE_KEY,
|
|
32
|
+
APPWARDEN_HEARTBEAT_ROUTE,
|
|
17
33
|
CSPDirectivesSchema,
|
|
18
34
|
CSPModeSchema,
|
|
35
|
+
HEARTBEAT_CONFIG_ERRORS_MAX_SERIALIZED_BYTES,
|
|
36
|
+
HEARTBEAT_CONFIG_ERROR_MAX_CODE_LENGTH,
|
|
37
|
+
HEARTBEAT_CONFIG_ERROR_MAX_COUNT,
|
|
38
|
+
HEARTBEAT_CONFIG_ERROR_MAX_MESSAGE_LENGTH,
|
|
39
|
+
HEARTBEAT_CONFIG_ERROR_MAX_PATH_DEPTH,
|
|
40
|
+
HEARTBEAT_CONFIG_ERROR_MAX_PATH_SEGMENT_LENGTH,
|
|
41
|
+
HEARTBEAT_CONTRACT_VERSION,
|
|
42
|
+
HEARTBEAT_RESPONSE_BODY_MAX_SERIALIZED_BYTES,
|
|
43
|
+
HEARTBEAT_SERVICES,
|
|
44
|
+
HEARTBEAT_SERVICE_VALUES,
|
|
45
|
+
HEARTBEAT_VERSION_MAX_LENGTH,
|
|
46
|
+
HeartbeatConfigErrorSchema,
|
|
47
|
+
HeartbeatResponseBodySchema,
|
|
19
48
|
LOCKDOWN_TEST_EXPIRY_MS,
|
|
20
49
|
UseAppwardenInputSchema,
|
|
21
50
|
getEdgeConfigId,
|
|
22
51
|
isCacheUrl,
|
|
23
|
-
isValidCacheUrl
|
|
52
|
+
isValidCacheUrl,
|
|
53
|
+
validateHeartbeatResponseBody
|
|
24
54
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@appwarden/middleware",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.13.1",
|
|
4
4
|
"description": "Instantly disable all user interaction with your app deployed on Cloudflare or Vercel",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"node": ">=24"
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"@upstash/redis": "^1.36.
|
|
61
|
+
"@upstash/redis": "^1.36.4",
|
|
62
62
|
"@vercel/edge-config": "^1.4.3",
|
|
63
63
|
"zod": "^3.25.76"
|
|
64
64
|
},
|
package/vercel.js
CHANGED
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
makeCSPHeader,
|
|
21
21
|
printMessage,
|
|
22
22
|
sanitizeConfigErrors
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-U7E4KM2B.js";
|
|
24
24
|
import {
|
|
25
25
|
APPWARDEN_CACHE_KEY,
|
|
26
26
|
AppwardenApiHostnameSchema,
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
LockValue,
|
|
31
31
|
errors,
|
|
32
32
|
globalErrors
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-OIEAURS7.js";
|
|
34
34
|
|
|
35
35
|
// src/runners/appwarden-on-vercel.ts
|
|
36
36
|
import { waitUntil } from "@vercel/functions";
|