@appwarden/middleware 3.11.5 → 3.12.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-5HCAAVK5.js → chunk-6YCNCR22.js} +3 -5
- package/{chunk-R7TXTHSG.js → chunk-EXGUJ5XK.js} +75 -143
- package/chunk-G6BMPIYD.js +11 -0
- package/chunk-HTSD4WPC.js +378 -0
- package/chunk-HUWGPM4M.js +9 -0
- package/{chunk-WBWF3PPX.js → chunk-ILIYP3TG.js} +4 -6
- package/{chunk-XFG6SUSV.js → chunk-M2YVPCTG.js} +15 -0
- package/chunk-NV7K5PRA.js +36 -0
- package/{chunk-ZTVJBORU.js → chunk-Z7P4QVEY.js} +74 -8
- package/cloudflare/astro.d.ts +3 -3
- package/cloudflare/astro.js +109 -62
- package/cloudflare/nextjs.d.ts +2 -2
- package/cloudflare/nextjs.js +65 -21
- package/cloudflare/react-router.d.ts +3 -3
- package/cloudflare/react-router.js +92 -57
- package/cloudflare/tanstack-start.d.ts +2 -2
- package/cloudflare/tanstack-start.js +92 -80
- package/cloudflare.d.ts +1 -1
- package/cloudflare.js +80 -11
- package/index.d.ts +1 -1
- package/index.js +2 -3
- package/package.json +1 -1
- package/{use-content-security-policy-CvdzUPYF.d.ts → use-content-security-policy-Dwdcwp33.d.ts} +0 -1
- package/vercel.js +38 -16
- package/chunk-AY4ZKZTF.js +0 -162
- package/chunk-QC2ZUZWY.js +0 -84
- package/chunk-WEM7GS4M.js +0 -29
- package/chunk-X7WZVYQS.js +0 -6
- package/cloudflare-MAHYENA6.js +0 -29
package/vercel.js
CHANGED
|
@@ -2,30 +2,35 @@ import {
|
|
|
2
2
|
isCacheUrl,
|
|
3
3
|
isValidCacheUrl
|
|
4
4
|
} from "./chunk-QEFORWCW.js";
|
|
5
|
+
import {
|
|
6
|
+
getErrors
|
|
7
|
+
} from "./chunk-NV7K5PRA.js";
|
|
8
|
+
import {
|
|
9
|
+
toNextResponse
|
|
10
|
+
} from "./chunk-HUWGPM4M.js";
|
|
5
11
|
import {
|
|
6
12
|
MemoryCache,
|
|
7
13
|
TEMPORARY_REDIRECT_STATUS,
|
|
8
14
|
buildLockPageUrl,
|
|
9
15
|
debug,
|
|
16
|
+
handleHeartbeatRequest,
|
|
10
17
|
isHTMLRequest,
|
|
11
|
-
|
|
12
|
-
|
|
18
|
+
isHeartbeatRequest,
|
|
19
|
+
isOnLockPage,
|
|
20
|
+
makeCSPHeader,
|
|
21
|
+
printMessage,
|
|
22
|
+
sanitizeConfigErrors
|
|
23
|
+
} from "./chunk-HTSD4WPC.js";
|
|
13
24
|
import {
|
|
14
25
|
APPWARDEN_CACHE_KEY,
|
|
26
|
+
AppwardenApiHostnameSchema,
|
|
15
27
|
CSPDirectivesSchema,
|
|
16
28
|
CSPModeSchema,
|
|
29
|
+
HEARTBEAT_SERVICES,
|
|
30
|
+
LockValue,
|
|
17
31
|
errors,
|
|
18
32
|
globalErrors
|
|
19
|
-
} from "./chunk-
|
|
20
|
-
import {
|
|
21
|
-
getErrors,
|
|
22
|
-
makeCSPHeader,
|
|
23
|
-
printMessage
|
|
24
|
-
} from "./chunk-R7TXTHSG.js";
|
|
25
|
-
import {
|
|
26
|
-
AppwardenApiHostnameSchema,
|
|
27
|
-
LockValue
|
|
28
|
-
} from "./chunk-WEM7GS4M.js";
|
|
33
|
+
} from "./chunk-Z7P4QVEY.js";
|
|
29
34
|
|
|
30
35
|
// src/runners/appwarden-on-vercel.ts
|
|
31
36
|
import { waitUntil } from "@vercel/functions";
|
|
@@ -250,6 +255,17 @@ function safeWaitUntil(promise) {
|
|
|
250
255
|
}
|
|
251
256
|
function createAppwardenMiddleware(config) {
|
|
252
257
|
return async (request) => {
|
|
258
|
+
const requestUrl = new URL(request.url);
|
|
259
|
+
if (isHeartbeatRequest(request, requestUrl)) {
|
|
260
|
+
const validationResult = AppwardenConfigSchema.safeParse(config);
|
|
261
|
+
const configErrors = validationResult.success ? [] : sanitizeConfigErrors(validationResult.error);
|
|
262
|
+
const response = handleHeartbeatRequest(
|
|
263
|
+
request,
|
|
264
|
+
HEARTBEAT_SERVICES.VERCEL,
|
|
265
|
+
configErrors
|
|
266
|
+
);
|
|
267
|
+
return toNextResponse(response);
|
|
268
|
+
}
|
|
253
269
|
if (validateConfig(config, AppwardenConfigSchema)) {
|
|
254
270
|
return NextResponse.next();
|
|
255
271
|
}
|
|
@@ -267,8 +283,15 @@ function createAppwardenMiddleware(config) {
|
|
|
267
283
|
}
|
|
268
284
|
return response;
|
|
269
285
|
};
|
|
286
|
+
const createMutableRedirectResponse = (location) => {
|
|
287
|
+
return new Response(null, {
|
|
288
|
+
status: TEMPORARY_REDIRECT_STATUS,
|
|
289
|
+
headers: {
|
|
290
|
+
Location: location
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
};
|
|
270
294
|
try {
|
|
271
|
-
const requestUrl = new URL(request.url);
|
|
272
295
|
const isHTML = isHTMLRequest(request);
|
|
273
296
|
debugFn(
|
|
274
297
|
`Appwarden middleware invoked for ${requestUrl.pathname}`,
|
|
@@ -319,9 +342,8 @@ function createAppwardenMiddleware(config) {
|
|
|
319
342
|
parsedConfig.lockPageSlug,
|
|
320
343
|
request.url
|
|
321
344
|
);
|
|
322
|
-
const redirectResponse =
|
|
323
|
-
lockPageUrl.toString()
|
|
324
|
-
TEMPORARY_REDIRECT_STATUS
|
|
345
|
+
const redirectResponse = createMutableRedirectResponse(
|
|
346
|
+
lockPageUrl.toString()
|
|
325
347
|
);
|
|
326
348
|
return applyCspHeaders(redirectResponse);
|
|
327
349
|
}
|
package/chunk-AY4ZKZTF.js
DELETED
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
LOCKDOWN_TEST_EXPIRY_MS
|
|
3
|
-
} from "./chunk-ZTVJBORU.js";
|
|
4
|
-
import {
|
|
5
|
-
printMessage
|
|
6
|
-
} from "./chunk-R7TXTHSG.js";
|
|
7
|
-
|
|
8
|
-
// src/utils/build-lock-page-url.ts
|
|
9
|
-
function normalizeLockPageSlug(lockPageSlug) {
|
|
10
|
-
return lockPageSlug.startsWith("/") ? lockPageSlug : `/${lockPageSlug}`;
|
|
11
|
-
}
|
|
12
|
-
function buildLockPageUrl(lockPageSlug, requestUrl) {
|
|
13
|
-
const normalizedSlug = normalizeLockPageSlug(lockPageSlug);
|
|
14
|
-
return new URL(normalizedSlug, requestUrl);
|
|
15
|
-
}
|
|
16
|
-
function normalizeTrailingSlash(path) {
|
|
17
|
-
if (path === "/") return path;
|
|
18
|
-
return path.endsWith("/") ? path.slice(0, -1) : path;
|
|
19
|
-
}
|
|
20
|
-
function isOnLockPage(lockPageSlug, requestUrl) {
|
|
21
|
-
const normalizedSlug = normalizeTrailingSlash(
|
|
22
|
-
normalizeLockPageSlug(lockPageSlug)
|
|
23
|
-
);
|
|
24
|
-
const url = typeof requestUrl === "string" ? new URL(requestUrl) : requestUrl;
|
|
25
|
-
const normalizedPathname = normalizeTrailingSlash(url.pathname);
|
|
26
|
-
return normalizedPathname === normalizedSlug;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// src/utils/create-redirect.ts
|
|
30
|
-
var TEMPORARY_REDIRECT_STATUS = 302;
|
|
31
|
-
var createRedirect = (url) => {
|
|
32
|
-
return new Response(null, {
|
|
33
|
-
status: TEMPORARY_REDIRECT_STATUS,
|
|
34
|
-
headers: {
|
|
35
|
-
Location: url.toString()
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
// src/utils/debug.ts
|
|
41
|
-
var debug = (isDebug) => (...msg) => {
|
|
42
|
-
if (!isDebug) return;
|
|
43
|
-
const parts = msg.map((m) => {
|
|
44
|
-
let content;
|
|
45
|
-
if (m instanceof Error) {
|
|
46
|
-
content = m.stack ?? m.message;
|
|
47
|
-
} else if (typeof m === "object" && m !== null) {
|
|
48
|
-
try {
|
|
49
|
-
content = JSON.stringify(m);
|
|
50
|
-
} catch {
|
|
51
|
-
try {
|
|
52
|
-
content = String(m);
|
|
53
|
-
} catch {
|
|
54
|
-
content = "[Unserializable value]";
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
} else {
|
|
58
|
-
content = String(m);
|
|
59
|
-
}
|
|
60
|
-
return content;
|
|
61
|
-
});
|
|
62
|
-
const message = parts.join(" ");
|
|
63
|
-
console.log(printMessage(message));
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
// src/utils/memory-cache.ts
|
|
67
|
-
var MemoryCache = class {
|
|
68
|
-
cache = /* @__PURE__ */ new Map();
|
|
69
|
-
maxSize;
|
|
70
|
-
constructor(options) {
|
|
71
|
-
this.maxSize = options.maxSize;
|
|
72
|
-
}
|
|
73
|
-
get(key) {
|
|
74
|
-
let item;
|
|
75
|
-
if (this.cache.has(key)) {
|
|
76
|
-
item = this.cache.get(key);
|
|
77
|
-
this.cache.delete(key);
|
|
78
|
-
if (item !== void 0) {
|
|
79
|
-
this.cache.set(key, item);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
return item;
|
|
83
|
-
}
|
|
84
|
-
put(key, value) {
|
|
85
|
-
if (this.cache.has(key)) {
|
|
86
|
-
this.cache.delete(key);
|
|
87
|
-
} else if (this.cache.size >= this.maxSize) {
|
|
88
|
-
const firstKey = this.cache.keys().next().value;
|
|
89
|
-
if (firstKey !== void 0) {
|
|
90
|
-
this.cache.delete(firstKey);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
this.cache.set(key, value);
|
|
94
|
-
}
|
|
95
|
-
getValues() {
|
|
96
|
-
return this.cache;
|
|
97
|
-
}
|
|
98
|
-
// the default value will be expired here
|
|
99
|
-
static isExpired = (lockValue) => {
|
|
100
|
-
if (!lockValue) {
|
|
101
|
-
return true;
|
|
102
|
-
}
|
|
103
|
-
return Date.now() > lockValue.lastCheck + 3e4;
|
|
104
|
-
};
|
|
105
|
-
static isTestExpired = (lockValue) => {
|
|
106
|
-
if (!lockValue) {
|
|
107
|
-
return true;
|
|
108
|
-
}
|
|
109
|
-
return Date.now() > lockValue.isLockedTest + LOCKDOWN_TEST_EXPIRY_MS;
|
|
110
|
-
};
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
// src/utils/request-checks.ts
|
|
114
|
-
function isHTMLResponse(response) {
|
|
115
|
-
return response.headers.get("Content-Type")?.includes("text/html") ?? false;
|
|
116
|
-
}
|
|
117
|
-
function isHTMLRequest(request) {
|
|
118
|
-
const accept = request.headers.get("accept");
|
|
119
|
-
if (!accept) {
|
|
120
|
-
return false;
|
|
121
|
-
}
|
|
122
|
-
const normalizedAccept = accept.toLowerCase();
|
|
123
|
-
const isWildcardOnlyAccept = (value) => {
|
|
124
|
-
const mediaRanges2 = value.split(",");
|
|
125
|
-
let hasNonEmptyRange = false;
|
|
126
|
-
for (const range of mediaRanges2) {
|
|
127
|
-
const [typeSubtype] = range.split(";");
|
|
128
|
-
const trimmed = typeSubtype.trim();
|
|
129
|
-
if (!trimmed) {
|
|
130
|
-
continue;
|
|
131
|
-
}
|
|
132
|
-
hasNonEmptyRange = true;
|
|
133
|
-
if (trimmed !== "*/*" && trimmed !== "*") {
|
|
134
|
-
return false;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
return hasNonEmptyRange;
|
|
138
|
-
};
|
|
139
|
-
if (isWildcardOnlyAccept(normalizedAccept)) {
|
|
140
|
-
return false;
|
|
141
|
-
}
|
|
142
|
-
const mediaRanges = normalizedAccept.split(",");
|
|
143
|
-
for (const range of mediaRanges) {
|
|
144
|
-
const [typeSubtype] = range.split(";");
|
|
145
|
-
const token = typeSubtype.trim();
|
|
146
|
-
if (token === "text/html") {
|
|
147
|
-
return true;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
return false;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
export {
|
|
154
|
-
buildLockPageUrl,
|
|
155
|
-
isOnLockPage,
|
|
156
|
-
TEMPORARY_REDIRECT_STATUS,
|
|
157
|
-
createRedirect,
|
|
158
|
-
debug,
|
|
159
|
-
MemoryCache,
|
|
160
|
-
isHTMLResponse,
|
|
161
|
-
isHTMLRequest
|
|
162
|
-
};
|
package/chunk-QC2ZUZWY.js
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
MemoryCache,
|
|
3
|
-
debug
|
|
4
|
-
} from "./chunk-AY4ZKZTF.js";
|
|
5
|
-
import {
|
|
6
|
-
APPWARDEN_CACHE_KEY,
|
|
7
|
-
APPWARDEN_TEST_ROUTE
|
|
8
|
-
} from "./chunk-ZTVJBORU.js";
|
|
9
|
-
import {
|
|
10
|
-
deleteEdgeValue,
|
|
11
|
-
getLockValue,
|
|
12
|
-
store,
|
|
13
|
-
syncEdgeValue
|
|
14
|
-
} from "./chunk-R7TXTHSG.js";
|
|
15
|
-
|
|
16
|
-
// src/core/check-lock-status.ts
|
|
17
|
-
var createContext = async (config) => {
|
|
18
|
-
const requestUrl = new URL(config.request.url);
|
|
19
|
-
const keyName = APPWARDEN_CACHE_KEY;
|
|
20
|
-
const provider = "cloudflare-cache";
|
|
21
|
-
const debugFn = debug(config.debug ?? false);
|
|
22
|
-
const edgeCache = store.json(
|
|
23
|
-
{
|
|
24
|
-
serviceOrigin: requestUrl.origin,
|
|
25
|
-
cache: await caches.open("appwarden:lock"),
|
|
26
|
-
debug: debugFn
|
|
27
|
-
},
|
|
28
|
-
keyName
|
|
29
|
-
);
|
|
30
|
-
return {
|
|
31
|
-
keyName,
|
|
32
|
-
request: config.request,
|
|
33
|
-
edgeCache,
|
|
34
|
-
requestUrl,
|
|
35
|
-
provider,
|
|
36
|
-
debug: debugFn,
|
|
37
|
-
lockPageSlug: config.lockPageSlug,
|
|
38
|
-
appwardenApiToken: config.appwardenApiToken,
|
|
39
|
-
appwardenApiHostname: config.appwardenApiHostname,
|
|
40
|
-
waitUntil: config.waitUntil
|
|
41
|
-
};
|
|
42
|
-
};
|
|
43
|
-
var resolveLockStatus = async (context) => {
|
|
44
|
-
const { lockValue, shouldDeleteEdgeValue } = await getLockValue(context);
|
|
45
|
-
if (shouldDeleteEdgeValue) {
|
|
46
|
-
context.debug("Deleting corrupted cache value");
|
|
47
|
-
await deleteEdgeValue(context);
|
|
48
|
-
}
|
|
49
|
-
const isTestRoute = context.requestUrl.pathname === APPWARDEN_TEST_ROUTE;
|
|
50
|
-
const isTestLock = isTestRoute && !MemoryCache.isTestExpired(lockValue) && !!lockValue;
|
|
51
|
-
return {
|
|
52
|
-
isLocked: !!lockValue?.isLocked || isTestLock,
|
|
53
|
-
isTestLock,
|
|
54
|
-
lockValue,
|
|
55
|
-
wasDeleted: shouldDeleteEdgeValue ?? false
|
|
56
|
-
};
|
|
57
|
-
};
|
|
58
|
-
var checkLockStatus = async (config) => {
|
|
59
|
-
const context = await createContext(config);
|
|
60
|
-
let { isLocked, isTestLock, lockValue, wasDeleted } = await resolveLockStatus(context);
|
|
61
|
-
const isExpired = MemoryCache.isExpired(lockValue);
|
|
62
|
-
if (!isExpired && !wasDeleted && lockValue) {
|
|
63
|
-
context.debug("Lock value resolved from cache");
|
|
64
|
-
}
|
|
65
|
-
if (isExpired || wasDeleted) {
|
|
66
|
-
if (!lockValue || wasDeleted || lockValue.isLocked) {
|
|
67
|
-
context.debug(
|
|
68
|
-
"No fresh cached lock status available - syncing with API synchronously"
|
|
69
|
-
);
|
|
70
|
-
await syncEdgeValue(context);
|
|
71
|
-
({ isLocked, isTestLock } = await resolveLockStatus(context));
|
|
72
|
-
} else {
|
|
73
|
-
context.debug(
|
|
74
|
-
"Cached lock status expired but last known state unlocked - syncing with API in background"
|
|
75
|
-
);
|
|
76
|
-
config.waitUntil(syncEdgeValue(context));
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
return { isLocked, isTestLock };
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
export {
|
|
83
|
-
checkLockStatus
|
|
84
|
-
};
|
package/chunk-WEM7GS4M.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
// src/schemas/helpers.ts
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
var BoolOrStringSchema = z.union([z.string(), z.boolean()]).optional();
|
|
4
|
-
var BooleanSchema = BoolOrStringSchema.transform((val) => {
|
|
5
|
-
if (val === "true" || val === true) {
|
|
6
|
-
return true;
|
|
7
|
-
} else if (val === "false" || val === false) {
|
|
8
|
-
return false;
|
|
9
|
-
}
|
|
10
|
-
throw new Error("Invalid value");
|
|
11
|
-
});
|
|
12
|
-
var AppwardenApiTokenSchema = z.string().refine((val) => !!val, { message: "appwardenApiToken is required" });
|
|
13
|
-
var AppwardenApiHostnameSchema = z.string().url({
|
|
14
|
-
message: "Invalid `appwardenApiHostname`. Please provide an absolute URL (e.g. https://api.appwarden.io)."
|
|
15
|
-
}).refine((value) => value.startsWith("https://"), {
|
|
16
|
-
message: "`appwardenApiHostname` must use the https:// scheme (e.g. https://api.appwarden.io)."
|
|
17
|
-
});
|
|
18
|
-
var LockValue = z.object({
|
|
19
|
-
isLocked: z.number(),
|
|
20
|
-
isLockedTest: z.number(),
|
|
21
|
-
lastCheck: z.number()
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
export {
|
|
25
|
-
BooleanSchema,
|
|
26
|
-
AppwardenApiTokenSchema,
|
|
27
|
-
AppwardenApiHostnameSchema,
|
|
28
|
-
LockValue
|
|
29
|
-
};
|
package/chunk-X7WZVYQS.js
DELETED
package/cloudflare-MAHYENA6.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CSP_KEYWORDS,
|
|
3
|
-
autoQuoteCSPDirectiveArray,
|
|
4
|
-
autoQuoteCSPDirectiveValue,
|
|
5
|
-
autoQuoteCSPKeyword,
|
|
6
|
-
deleteEdgeValue,
|
|
7
|
-
getLockValue,
|
|
8
|
-
insertErrorLogs,
|
|
9
|
-
isCSPKeyword,
|
|
10
|
-
isQuoted,
|
|
11
|
-
makeCSPHeader,
|
|
12
|
-
store,
|
|
13
|
-
syncEdgeValue
|
|
14
|
-
} from "./chunk-R7TXTHSG.js";
|
|
15
|
-
import "./chunk-WEM7GS4M.js";
|
|
16
|
-
export {
|
|
17
|
-
CSP_KEYWORDS,
|
|
18
|
-
autoQuoteCSPDirectiveArray,
|
|
19
|
-
autoQuoteCSPDirectiveValue,
|
|
20
|
-
autoQuoteCSPKeyword,
|
|
21
|
-
deleteEdgeValue,
|
|
22
|
-
getLockValue,
|
|
23
|
-
insertErrorLogs,
|
|
24
|
-
isCSPKeyword,
|
|
25
|
-
isQuoted,
|
|
26
|
-
makeCSPHeader,
|
|
27
|
-
store,
|
|
28
|
-
syncEdgeValue
|
|
29
|
-
};
|