@appwarden/middleware 3.12.0 → 3.13.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/README.md +1 -1
- package/{chunk-HTSD4WPC.js → chunk-2ZSJUEHK.js} +96 -29
- package/{chunk-6YCNCR22.js → chunk-GNDWHKJ5.js} +1 -1
- package/{chunk-EXGUJ5XK.js → chunk-HP5GMFH7.js} +2 -2
- package/{chunk-ILIYP3TG.js → chunk-J2TA6BEU.js} +2 -2
- package/{chunk-Z7P4QVEY.js → chunk-SREQAAZC.js} +92 -19
- package/{chunk-M2YVPCTG.js → chunk-TBSMAMWC.js} +1 -1
- package/cloudflare/astro.js +5 -5
- package/cloudflare/nextjs.js +3 -3
- package/cloudflare/react-router.js +5 -5
- package/cloudflare/tanstack-start.js +5 -5
- package/cloudflare.js +5 -5
- package/index.d.ts +108 -1
- package/index.js +10 -4
- package/package.json +1 -1
- 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
|
|
@@ -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-SREQAAZC.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.12.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
|
}
|
|
@@ -2,12 +2,12 @@ import {
|
|
|
2
2
|
MemoryCache,
|
|
3
3
|
debug,
|
|
4
4
|
printMessage
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-2ZSJUEHK.js";
|
|
6
6
|
import {
|
|
7
7
|
APPWARDEN_CACHE_KEY,
|
|
8
8
|
APPWARDEN_TEST_ROUTE,
|
|
9
9
|
LockValue
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-SREQAAZC.js";
|
|
11
11
|
|
|
12
12
|
// src/utils/cloudflare/cloudflare-cache.ts
|
|
13
13
|
var store = {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
isHTMLResponse,
|
|
3
3
|
makeCSPHeader
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-2ZSJUEHK.js";
|
|
5
5
|
import {
|
|
6
6
|
UseCSPInputSchema
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-SREQAAZC.js";
|
|
8
8
|
|
|
9
9
|
// src/middlewares/use-content-security-policy.ts
|
|
10
10
|
var AppendAttribute = (attribute, nonce) => ({
|
|
@@ -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) => {
|
|
@@ -134,6 +202,8 @@ export {
|
|
|
134
202
|
HEARTBEAT_CONFIG_ERROR_MAX_PATH_DEPTH,
|
|
135
203
|
HEARTBEAT_CONFIG_ERROR_MAX_CODE_LENGTH,
|
|
136
204
|
HEARTBEAT_CONFIG_ERROR_MAX_MESSAGE_LENGTH,
|
|
205
|
+
HEARTBEAT_CONFIG_ERRORS_MAX_SERIALIZED_BYTES,
|
|
206
|
+
HEARTBEAT_RESPONSE_BODY_MAX_SERIALIZED_BYTES,
|
|
137
207
|
HEARTBEAT_CONFIG_ERROR_MAX_PATH_SEGMENT_LENGTH,
|
|
138
208
|
APPWARDEN_CACHE_KEY,
|
|
139
209
|
HEARTBEAT_SERVICES,
|
|
@@ -141,6 +211,9 @@ export {
|
|
|
141
211
|
AppwardenApiTokenSchema,
|
|
142
212
|
AppwardenApiHostnameSchema,
|
|
143
213
|
LockValue,
|
|
214
|
+
HeartbeatConfigErrorSchema,
|
|
215
|
+
HeartbeatResponseBodySchema,
|
|
216
|
+
validateHeartbeatResponseBody,
|
|
144
217
|
CSPDirectivesSchema,
|
|
145
218
|
CSPModeSchema,
|
|
146
219
|
UseCSPInputSchema
|
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-TBSMAMWC.js";
|
|
5
|
+
import "../chunk-J2TA6BEU.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-HP5GMFH7.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-2ZSJUEHK.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-SREQAAZC.js";
|
|
33
33
|
|
|
34
34
|
// src/adapters/astro-cloudflare.ts
|
|
35
35
|
import { waitUntil } from "cloudflare:workers";
|
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-HP5GMFH7.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-2ZSJUEHK.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-SREQAAZC.js";
|
|
31
31
|
|
|
32
32
|
// src/adapters/nextjs-cloudflare.ts
|
|
33
33
|
import { getCloudflareContext } from "@opennextjs/cloudflare";
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
applyContentSecurityPolicyToResponse,
|
|
3
3
|
isResponseLike
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-
|
|
4
|
+
} from "../chunk-TBSMAMWC.js";
|
|
5
|
+
import "../chunk-J2TA6BEU.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-HP5GMFH7.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-2ZSJUEHK.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-SREQAAZC.js";
|
|
32
32
|
|
|
33
33
|
// src/adapters/react-router-cloudflare.ts
|
|
34
34
|
import { waitUntil } from "cloudflare:workers";
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
applyContentSecurityPolicyToResponse,
|
|
3
3
|
isResponseLike
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-
|
|
4
|
+
} from "../chunk-TBSMAMWC.js";
|
|
5
|
+
import "../chunk-J2TA6BEU.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-HP5GMFH7.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-2ZSJUEHK.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-SREQAAZC.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-GNDWHKJ5.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-J2TA6BEU.js";
|
|
11
11
|
import {
|
|
12
12
|
checkLockStatus
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-HP5GMFH7.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-2ZSJUEHK.js";
|
|
26
26
|
import {
|
|
27
27
|
HEARTBEAT_SERVICES
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-SREQAAZC.js";
|
|
29
29
|
|
|
30
30
|
// src/runners/appwarden-on-cloudflare.ts
|
|
31
31
|
import { ZodError } from "zod";
|
package/index.d.ts
CHANGED
|
@@ -3,6 +3,113 @@ import { z } from 'zod';
|
|
|
3
3
|
|
|
4
4
|
declare const LOCKDOWN_TEST_EXPIRY_MS: number;
|
|
5
5
|
declare const APPWARDEN_CACHE_KEY: "appwarden-lock";
|
|
6
|
+
declare const HEARTBEAT_SERVICE_VALUES: readonly ["cloudflare", "cloudflare-astro", "cloudflare-react-router", "cloudflare-tanstack-start", "cloudflare-nextjs", "vercel"];
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Service identifiers for different middleware adapters.
|
|
10
|
+
* These are hardcoded per adapter bundle.
|
|
11
|
+
*/
|
|
12
|
+
type HeartbeatService = (typeof HEARTBEAT_SERVICE_VALUES)[number];
|
|
13
|
+
/**
|
|
14
|
+
* Schema for validating heartbeat config errors.
|
|
15
|
+
* Ensures errors are bounded and sanitized.
|
|
16
|
+
*/
|
|
17
|
+
declare const HeartbeatConfigErrorSchema: z.ZodObject<{
|
|
18
|
+
path: z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodNumber]>, "many">;
|
|
19
|
+
code: z.ZodString;
|
|
20
|
+
message: z.ZodString;
|
|
21
|
+
}, "strict", z.ZodTypeAny, {
|
|
22
|
+
message: string;
|
|
23
|
+
code: string;
|
|
24
|
+
path: (string | number)[];
|
|
25
|
+
}, {
|
|
26
|
+
message: string;
|
|
27
|
+
code: string;
|
|
28
|
+
path: (string | number)[];
|
|
29
|
+
}>;
|
|
30
|
+
type HeartbeatConfigError = z.infer<typeof HeartbeatConfigErrorSchema>;
|
|
31
|
+
/**
|
|
32
|
+
* Schema for validating the heartbeat response body.
|
|
33
|
+
*/
|
|
34
|
+
declare const HeartbeatResponseBodySchema: z.ZodEffects<z.ZodObject<{
|
|
35
|
+
app: z.ZodLiteral<"appwarden">;
|
|
36
|
+
kind: z.ZodLiteral<"heartbeat">;
|
|
37
|
+
status: z.ZodLiteral<"ok">;
|
|
38
|
+
contractVersion: z.ZodLiteral<1>;
|
|
39
|
+
service: z.ZodEnum<["cloudflare", "cloudflare-astro", "cloudflare-react-router", "cloudflare-tanstack-start", "cloudflare-nextjs", "vercel"]>;
|
|
40
|
+
version: z.ZodString;
|
|
41
|
+
configErrors: z.ZodEffects<z.ZodArray<z.ZodObject<{
|
|
42
|
+
path: z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodNumber]>, "many">;
|
|
43
|
+
code: z.ZodString;
|
|
44
|
+
message: z.ZodString;
|
|
45
|
+
}, "strict", z.ZodTypeAny, {
|
|
46
|
+
message: string;
|
|
47
|
+
code: string;
|
|
48
|
+
path: (string | number)[];
|
|
49
|
+
}, {
|
|
50
|
+
message: string;
|
|
51
|
+
code: string;
|
|
52
|
+
path: (string | number)[];
|
|
53
|
+
}>, "many">, {
|
|
54
|
+
message: string;
|
|
55
|
+
code: string;
|
|
56
|
+
path: (string | number)[];
|
|
57
|
+
}[], {
|
|
58
|
+
message: string;
|
|
59
|
+
code: string;
|
|
60
|
+
path: (string | number)[];
|
|
61
|
+
}[]>;
|
|
62
|
+
}, "strict", z.ZodTypeAny, {
|
|
63
|
+
status: "ok";
|
|
64
|
+
app: "appwarden";
|
|
65
|
+
kind: "heartbeat";
|
|
66
|
+
contractVersion: 1;
|
|
67
|
+
service: "cloudflare" | "cloudflare-astro" | "cloudflare-react-router" | "cloudflare-tanstack-start" | "cloudflare-nextjs" | "vercel";
|
|
68
|
+
version: string;
|
|
69
|
+
configErrors: {
|
|
70
|
+
message: string;
|
|
71
|
+
code: string;
|
|
72
|
+
path: (string | number)[];
|
|
73
|
+
}[];
|
|
74
|
+
}, {
|
|
75
|
+
status: "ok";
|
|
76
|
+
app: "appwarden";
|
|
77
|
+
kind: "heartbeat";
|
|
78
|
+
contractVersion: 1;
|
|
79
|
+
service: "cloudflare" | "cloudflare-astro" | "cloudflare-react-router" | "cloudflare-tanstack-start" | "cloudflare-nextjs" | "vercel";
|
|
80
|
+
version: string;
|
|
81
|
+
configErrors: {
|
|
82
|
+
message: string;
|
|
83
|
+
code: string;
|
|
84
|
+
path: (string | number)[];
|
|
85
|
+
}[];
|
|
86
|
+
}>, {
|
|
87
|
+
status: "ok";
|
|
88
|
+
app: "appwarden";
|
|
89
|
+
kind: "heartbeat";
|
|
90
|
+
contractVersion: 1;
|
|
91
|
+
service: "cloudflare" | "cloudflare-astro" | "cloudflare-react-router" | "cloudflare-tanstack-start" | "cloudflare-nextjs" | "vercel";
|
|
92
|
+
version: string;
|
|
93
|
+
configErrors: {
|
|
94
|
+
message: string;
|
|
95
|
+
code: string;
|
|
96
|
+
path: (string | number)[];
|
|
97
|
+
}[];
|
|
98
|
+
}, {
|
|
99
|
+
status: "ok";
|
|
100
|
+
app: "appwarden";
|
|
101
|
+
kind: "heartbeat";
|
|
102
|
+
contractVersion: 1;
|
|
103
|
+
service: "cloudflare" | "cloudflare-astro" | "cloudflare-react-router" | "cloudflare-tanstack-start" | "cloudflare-nextjs" | "vercel";
|
|
104
|
+
version: string;
|
|
105
|
+
configErrors: {
|
|
106
|
+
message: string;
|
|
107
|
+
code: string;
|
|
108
|
+
path: (string | number)[];
|
|
109
|
+
}[];
|
|
110
|
+
}>;
|
|
111
|
+
type HeartbeatResponseBody = z.infer<typeof HeartbeatResponseBodySchema>;
|
|
112
|
+
declare function validateHeartbeatResponseBody(value: unknown): HeartbeatResponseBody;
|
|
6
113
|
|
|
7
114
|
/**
|
|
8
115
|
* Extracts the Edge Config ID from a valid Edge Config URL
|
|
@@ -787,4 +894,4 @@ declare const LockValue: z.ZodObject<{
|
|
|
787
894
|
}>;
|
|
788
895
|
type LockValueType = z.infer<typeof LockValue>;
|
|
789
896
|
|
|
790
|
-
export { APPWARDEN_CACHE_KEY, LOCKDOWN_TEST_EXPIRY_MS, type LockValueType, UseAppwardenInputSchema, getEdgeConfigId, isCacheUrl, isValidCacheUrl };
|
|
897
|
+
export { APPWARDEN_CACHE_KEY, 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,26 @@ import {
|
|
|
5
5
|
} from "./chunk-QEFORWCW.js";
|
|
6
6
|
import {
|
|
7
7
|
UseAppwardenInputSchema
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-GNDWHKJ5.js";
|
|
9
9
|
import {
|
|
10
10
|
APPWARDEN_CACHE_KEY,
|
|
11
11
|
CSPDirectivesSchema,
|
|
12
12
|
CSPModeSchema,
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
HeartbeatConfigErrorSchema,
|
|
14
|
+
HeartbeatResponseBodySchema,
|
|
15
|
+
LOCKDOWN_TEST_EXPIRY_MS,
|
|
16
|
+
validateHeartbeatResponseBody
|
|
17
|
+
} from "./chunk-SREQAAZC.js";
|
|
15
18
|
export {
|
|
16
19
|
APPWARDEN_CACHE_KEY,
|
|
17
20
|
CSPDirectivesSchema,
|
|
18
21
|
CSPModeSchema,
|
|
22
|
+
HeartbeatConfigErrorSchema,
|
|
23
|
+
HeartbeatResponseBodySchema,
|
|
19
24
|
LOCKDOWN_TEST_EXPIRY_MS,
|
|
20
25
|
UseAppwardenInputSchema,
|
|
21
26
|
getEdgeConfigId,
|
|
22
27
|
isCacheUrl,
|
|
23
|
-
isValidCacheUrl
|
|
28
|
+
isValidCacheUrl,
|
|
29
|
+
validateHeartbeatResponseBody
|
|
24
30
|
};
|
package/package.json
CHANGED
package/vercel.js
CHANGED
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
makeCSPHeader,
|
|
21
21
|
printMessage,
|
|
22
22
|
sanitizeConfigErrors
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-2ZSJUEHK.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-SREQAAZC.js";
|
|
34
34
|
|
|
35
35
|
// src/runners/appwarden-on-vercel.ts
|
|
36
36
|
import { waitUntil } from "@vercel/functions";
|