@appwarden/middleware 3.1.0 → 3.2.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # @appwarden/middleware
2
2
 
3
- ![Test Coverage](https://img.shields.io/badge/coverage-96.08%25-brightgreen)
3
+ ![Test Coverage](https://img.shields.io/badge/coverage-95.67%25-brightgreen)
4
4
  [![npm version](https://img.shields.io/npm/v/@appwarden/middleware.svg)](https://www.npmjs.com/package/@appwarden/middleware)
5
5
  [![npm provenance](https://img.shields.io/badge/npm-provenance-green)](https://docs.npmjs.com/generating-provenance-statements)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
@@ -26,13 +26,17 @@ For detailed usage instructions, please refer to our [documentation](https://app
26
26
 
27
27
  ### On Cloudflare
28
28
 
29
- Cloudflare has two deployment options: [pages.dev](https://pages.dev) and [Workers static assets](https://developers.cloudflare.com/workers/static-assets/). We support both.
29
+ For all websites deployed on Cloudflare—including popular modern frameworks like Astro, Next.js, React Router, TanStack Start, and more—we recommend using the [build-cloudflare-action](https://github.com/appwarden/build-cloudflare-action). This action builds a worker that runs on the root of your domain (e.g., `your.app.io/*` for an `your.app.io` website), providing seamless integration with Appwarden without modifying your application code.
30
30
 
31
- #### On pages.dev
31
+ Please see the [build-cloudflare-action documentation](https://github.com/appwarden/build-cloudflare-action) for more information.
32
32
 
33
- - [All websites on pages.dev](https://appwarden.io/docs/guides/cloudflare-integration)
33
+ #### Recommended: build-cloudflare-action
34
34
 
35
- #### On Workers static assets
35
+ - [build-cloudflare-action](https://github.com/appwarden/build-cloudflare-action) Seamless integration with Appwarden for Cloudflare-deployed websites.
36
+
37
+ #### Framework adapters (alternative)
38
+
39
+ If you cannot use the `build-cloudflare-action`, you can use framework-specific adapters instead:
36
40
 
37
41
  - [Astro](https://appwarden.io/docs/guides/astro-cloudflare)
38
42
  - [React Router](https://appwarden.io/docs/guides/react-router-cloudflare)
@@ -0,0 +1,27 @@
1
+ import {
2
+ getErrors
3
+ } from "./chunk-ZX5QO4Y2.js";
4
+ import {
5
+ printMessage
6
+ } from "./chunk-L5EQIJZB.js";
7
+
8
+ // src/utils/validate-config.ts
9
+ function validateConfig(config, schema) {
10
+ const result = schema.safeParse(config);
11
+ const hasErrors = !result.success;
12
+ if (hasErrors) {
13
+ const mappedErrors = getErrors(result.error);
14
+ if (mappedErrors.length > 0) {
15
+ for (const error of mappedErrors) {
16
+ console.error(printMessage(error));
17
+ }
18
+ } else {
19
+ console.error(printMessage(result.error.message));
20
+ }
21
+ }
22
+ return hasErrors;
23
+ }
24
+
25
+ export {
26
+ validateConfig
27
+ };
@@ -2,7 +2,7 @@ import {
2
2
  debug,
3
3
  isHTMLResponse,
4
4
  printMessage
5
- } from "./chunk-7UTT3M2S.js";
5
+ } from "./chunk-L5EQIJZB.js";
6
6
 
7
7
  // src/schemas/use-content-security-policy.ts
8
8
  import { z as z2 } from "zod";
@@ -8,7 +8,24 @@ var APPWARDEN_CACHE_KEY = "appwarden-lock";
8
8
  // src/utils/debug.ts
9
9
  var debug = (...msg) => {
10
10
  if (true) {
11
- console.log(...msg);
11
+ const formatted = msg.map((m) => {
12
+ if (typeof m === "object" && m !== null) {
13
+ if (m instanceof Error) {
14
+ return m.stack ?? m.message;
15
+ }
16
+ try {
17
+ return JSON.stringify(m);
18
+ } catch {
19
+ try {
20
+ return String(m);
21
+ } catch {
22
+ return "[Unserializable value]";
23
+ }
24
+ }
25
+ }
26
+ return m;
27
+ });
28
+ console.log(...formatted);
12
29
  }
13
30
  };
14
31
 
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  LockValue,
3
3
  MemoryCache
4
- } from "./chunk-B5IE7V77.js";
4
+ } from "./chunk-ZX5QO4Y2.js";
5
5
  import {
6
6
  APPWARDEN_CACHE_KEY,
7
7
  APPWARDEN_TEST_ROUTE,
8
8
  debug,
9
9
  printMessage
10
- } from "./chunk-7UTT3M2S.js";
10
+ } from "./chunk-L5EQIJZB.js";
11
11
 
12
12
  // src/utils/cloudflare/cloudflare-cache.ts
13
13
  var store = {
@@ -1,6 +1,38 @@
1
1
  import {
2
2
  LOCKDOWN_TEST_EXPIRY_MS
3
- } from "./chunk-7UTT3M2S.js";
3
+ } from "./chunk-L5EQIJZB.js";
4
+
5
+ // src/utils/build-lock-page-url.ts
6
+ function normalizeLockPageSlug(lockPageSlug) {
7
+ return lockPageSlug.startsWith("/") ? lockPageSlug : `/${lockPageSlug}`;
8
+ }
9
+ function buildLockPageUrl(lockPageSlug, requestUrl) {
10
+ const normalizedSlug = normalizeLockPageSlug(lockPageSlug);
11
+ return new URL(normalizedSlug, requestUrl);
12
+ }
13
+ function normalizeTrailingSlash(path) {
14
+ if (path === "/") return path;
15
+ return path.endsWith("/") ? path.slice(0, -1) : path;
16
+ }
17
+ function isOnLockPage(lockPageSlug, requestUrl) {
18
+ const normalizedSlug = normalizeTrailingSlash(
19
+ normalizeLockPageSlug(lockPageSlug)
20
+ );
21
+ const url = typeof requestUrl === "string" ? new URL(requestUrl) : requestUrl;
22
+ const normalizedPathname = normalizeTrailingSlash(url.pathname);
23
+ return normalizedPathname === normalizedSlug;
24
+ }
25
+
26
+ // src/utils/create-redirect.ts
27
+ var TEMPORARY_REDIRECT_STATUS = 302;
28
+ var createRedirect = (url) => {
29
+ return new Response(null, {
30
+ status: TEMPORARY_REDIRECT_STATUS,
31
+ headers: {
32
+ Location: url.toString()
33
+ }
34
+ });
35
+ };
4
36
 
5
37
  // src/utils/memory-cache.ts
6
38
  var MemoryCache = class {
@@ -102,6 +134,10 @@ var LockValue = z.object({
102
134
  });
103
135
 
104
136
  export {
137
+ buildLockPageUrl,
138
+ isOnLockPage,
139
+ TEMPORARY_REDIRECT_STATUS,
140
+ createRedirect,
105
141
  getErrors,
106
142
  MemoryCache,
107
143
  BooleanSchema,
@@ -1,23 +1,21 @@
1
1
  import {
2
- TEMPORARY_REDIRECT_STATUS,
3
- createRedirect
4
- } from "../chunk-6M7BE3AW.js";
5
- import {
6
- buildLockPageUrl,
7
- isOnLockPage,
8
2
  validateConfig
9
- } from "../chunk-4JGYMZTR.js";
3
+ } from "../chunk-COV6SHCD.js";
10
4
  import {
11
5
  checkLockStatus
12
- } from "../chunk-5DEXVBY6.js";
6
+ } from "../chunk-MDODCAA3.js";
13
7
  import {
14
8
  AppwardenApiTokenSchema,
15
- BooleanSchema
16
- } from "../chunk-B5IE7V77.js";
9
+ BooleanSchema,
10
+ TEMPORARY_REDIRECT_STATUS,
11
+ buildLockPageUrl,
12
+ createRedirect,
13
+ isOnLockPage
14
+ } from "../chunk-ZX5QO4Y2.js";
17
15
  import {
18
16
  isHTMLRequest,
19
17
  printMessage
20
- } from "../chunk-7UTT3M2S.js";
18
+ } from "../chunk-L5EQIJZB.js";
21
19
 
22
20
  // src/schemas/astro-cloudflare.ts
23
21
  import { z } from "zod";
@@ -1,22 +1,20 @@
1
1
  import {
2
- TEMPORARY_REDIRECT_STATUS
3
- } from "../chunk-6M7BE3AW.js";
4
- import {
5
- buildLockPageUrl,
6
- isOnLockPage,
7
2
  validateConfig
8
- } from "../chunk-4JGYMZTR.js";
3
+ } from "../chunk-COV6SHCD.js";
9
4
  import {
10
5
  checkLockStatus
11
- } from "../chunk-5DEXVBY6.js";
6
+ } from "../chunk-MDODCAA3.js";
12
7
  import {
13
8
  AppwardenApiTokenSchema,
14
- BooleanSchema
15
- } from "../chunk-B5IE7V77.js";
9
+ BooleanSchema,
10
+ TEMPORARY_REDIRECT_STATUS,
11
+ buildLockPageUrl,
12
+ isOnLockPage
13
+ } from "../chunk-ZX5QO4Y2.js";
16
14
  import {
17
15
  isHTMLRequest,
18
16
  printMessage
19
- } from "../chunk-7UTT3M2S.js";
17
+ } from "../chunk-L5EQIJZB.js";
20
18
 
21
19
  // src/adapters/nextjs-cloudflare.ts
22
20
  import {
@@ -1,22 +1,20 @@
1
1
  import {
2
- createRedirect
3
- } from "../chunk-6M7BE3AW.js";
4
- import {
5
- buildLockPageUrl,
6
- isOnLockPage,
7
2
  validateConfig
8
- } from "../chunk-4JGYMZTR.js";
3
+ } from "../chunk-COV6SHCD.js";
9
4
  import {
10
5
  checkLockStatus
11
- } from "../chunk-5DEXVBY6.js";
6
+ } from "../chunk-MDODCAA3.js";
12
7
  import {
13
8
  AppwardenApiTokenSchema,
14
- BooleanSchema
15
- } from "../chunk-B5IE7V77.js";
9
+ BooleanSchema,
10
+ buildLockPageUrl,
11
+ createRedirect,
12
+ isOnLockPage
13
+ } from "../chunk-ZX5QO4Y2.js";
16
14
  import {
17
15
  isHTMLRequest,
18
16
  printMessage
19
- } from "../chunk-7UTT3M2S.js";
17
+ } from "../chunk-L5EQIJZB.js";
20
18
 
21
19
  // src/schemas/react-router-cloudflare.ts
22
20
  import { z } from "zod";
@@ -1,22 +1,20 @@
1
1
  import {
2
- createRedirect
3
- } from "../chunk-6M7BE3AW.js";
4
- import {
5
- buildLockPageUrl,
6
- isOnLockPage,
7
2
  validateConfig
8
- } from "../chunk-4JGYMZTR.js";
3
+ } from "../chunk-COV6SHCD.js";
9
4
  import {
10
5
  checkLockStatus
11
- } from "../chunk-5DEXVBY6.js";
6
+ } from "../chunk-MDODCAA3.js";
12
7
  import {
13
8
  AppwardenApiTokenSchema,
14
- BooleanSchema
15
- } from "../chunk-B5IE7V77.js";
9
+ BooleanSchema,
10
+ buildLockPageUrl,
11
+ createRedirect,
12
+ isOnLockPage
13
+ } from "../chunk-ZX5QO4Y2.js";
16
14
  import {
17
15
  isHTMLRequest,
18
16
  printMessage
19
- } from "../chunk-7UTT3M2S.js";
17
+ } from "../chunk-L5EQIJZB.js";
20
18
 
21
19
  // src/schemas/tanstack-start-cloudflare.ts
22
20
  import { z } from "zod";
package/cloudflare.js CHANGED
@@ -1,21 +1,24 @@
1
1
  import {
2
2
  useContentSecurityPolicy
3
- } from "./chunk-MOTPEQEU.js";
3
+ } from "./chunk-FGAJVKNM.js";
4
4
  import {
5
5
  checkLockStatus,
6
6
  getLockValue,
7
7
  store
8
- } from "./chunk-5DEXVBY6.js";
8
+ } from "./chunk-MDODCAA3.js";
9
9
  import {
10
10
  AppwardenApiTokenSchema,
11
11
  BooleanSchema,
12
- getErrors
13
- } from "./chunk-B5IE7V77.js";
12
+ buildLockPageUrl,
13
+ createRedirect,
14
+ getErrors,
15
+ isOnLockPage
16
+ } from "./chunk-ZX5QO4Y2.js";
14
17
  import {
15
18
  APPWARDEN_CACHE_KEY,
16
- isHTMLResponse,
19
+ isHTMLRequest,
17
20
  printMessage
18
- } from "./chunk-7UTT3M2S.js";
21
+ } from "./chunk-L5EQIJZB.js";
19
22
 
20
23
  // src/runners/appwarden-on-cloudflare.ts
21
24
  import { ZodError } from "zod";
@@ -79,14 +82,6 @@ var usePipeline = (...initMiddlewares) => {
79
82
  };
80
83
  };
81
84
 
82
- // src/utils/render-lock-page.ts
83
- var renderLockPage = (context) => fetch(new URL(context.lockPageSlug, context.requestUrl.origin), {
84
- headers: {
85
- // no browser caching, otherwise we need to hard refresh to disable lock screen
86
- "Cache-Control": "no-store"
87
- }
88
- });
89
-
90
85
  // src/utils/cloudflare/insert-errors-logs.ts
91
86
  var insertErrorLogs = async (context, error) => {
92
87
  const errors = getErrors(error);
@@ -124,42 +119,46 @@ var handleResetCache = async (keyName, provider, edgeCache, request) => {
124
119
 
125
120
  // src/middlewares/use-appwarden.ts
126
121
  var useAppwarden = (input) => async (context, next) => {
127
- await next();
128
- const { request, response } = context;
122
+ const { request } = context;
123
+ let shouldCallNext = true;
129
124
  try {
130
125
  const requestUrl = new URL(request.url);
131
- const provider = "cloudflare-cache";
132
- const keyName = APPWARDEN_CACHE_KEY;
133
- const edgeCache = store.json(
134
- {
135
- serviceOrigin: requestUrl.origin,
136
- cache: await caches.open("appwarden:lock")
137
- },
138
- keyName
139
- );
140
126
  if (isResetCacheRequest(request)) {
127
+ const provider = "cloudflare-cache";
128
+ const keyName = APPWARDEN_CACHE_KEY;
129
+ const edgeCache = store.json(
130
+ {
131
+ serviceOrigin: requestUrl.origin,
132
+ cache: await caches.open("appwarden:lock")
133
+ },
134
+ keyName
135
+ );
141
136
  await handleResetCache(keyName, provider, edgeCache, request);
142
137
  return;
143
138
  }
144
- if (isHTMLResponse(response)) {
145
- const lockPageSlug = input.multidomainConfig?.[requestUrl.hostname]?.lockPageSlug ?? input.lockPageSlug;
146
- if (!lockPageSlug) {
147
- return;
148
- }
149
- const result = await checkLockStatus({
150
- request,
151
- appwardenApiToken: input.appwardenApiToken,
152
- appwardenApiHostname: input.appwardenApiHostname,
153
- debug: input.debug,
154
- lockPageSlug,
155
- waitUntil: (fn) => context.waitUntil(fn)
156
- });
157
- if (result.isLocked) {
158
- context.response = await renderLockPage({
159
- lockPageSlug,
160
- requestUrl
161
- });
162
- }
139
+ if (!isHTMLRequest(request)) {
140
+ return;
141
+ }
142
+ const lockPageSlug = input.multidomainConfig?.[requestUrl.hostname]?.lockPageSlug ?? input.lockPageSlug;
143
+ if (!lockPageSlug) {
144
+ return;
145
+ }
146
+ if (isOnLockPage(lockPageSlug, request.url)) {
147
+ return;
148
+ }
149
+ const result = await checkLockStatus({
150
+ request,
151
+ appwardenApiToken: input.appwardenApiToken,
152
+ appwardenApiHostname: input.appwardenApiHostname,
153
+ debug: input.debug,
154
+ lockPageSlug,
155
+ waitUntil: (fn) => context.waitUntil(fn)
156
+ });
157
+ if (result.isLocked) {
158
+ const lockPageUrl = buildLockPageUrl(lockPageSlug, request.url);
159
+ context.response = createRedirect(lockPageUrl);
160
+ shouldCallNext = false;
161
+ return;
163
162
  }
164
163
  } catch (e) {
165
164
  const message = "Appwarden encountered an unknown error. Please contact Appwarden support at https://appwarden.io/join-community.";
@@ -168,6 +167,10 @@ var useAppwarden = (input) => async (context, next) => {
168
167
  e instanceof Error ? `${message} - ${e.message}` : message
169
168
  )
170
169
  );
170
+ } finally {
171
+ if (shouldCallNext) {
172
+ await next();
173
+ }
171
174
  }
172
175
  };
173
176
 
package/index.js CHANGED
@@ -7,11 +7,11 @@ import {
7
7
  CSPDirectivesSchema,
8
8
  CSPModeSchema,
9
9
  useContentSecurityPolicy
10
- } from "./chunk-MOTPEQEU.js";
10
+ } from "./chunk-FGAJVKNM.js";
11
11
  import {
12
12
  APPWARDEN_CACHE_KEY,
13
13
  LOCKDOWN_TEST_EXPIRY_MS
14
- } from "./chunk-7UTT3M2S.js";
14
+ } from "./chunk-L5EQIJZB.js";
15
15
  export {
16
16
  APPWARDEN_CACHE_KEY,
17
17
  CSPDirectivesSchema,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appwarden/middleware",
3
- "version": "3.1.0",
3
+ "version": "3.2.0",
4
4
  "description": "Instantly shut off access your app deployed on Cloudflare or Vercel",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/vercel.js CHANGED
@@ -3,13 +3,15 @@ import {
3
3
  isValidCacheUrl
4
4
  } from "./chunk-QEFORWCW.js";
5
5
  import {
6
- isOnLockPage,
7
6
  validateConfig
8
- } from "./chunk-4JGYMZTR.js";
7
+ } from "./chunk-COV6SHCD.js";
9
8
  import {
10
9
  LockValue,
11
- MemoryCache
12
- } from "./chunk-B5IE7V77.js";
10
+ MemoryCache,
11
+ TEMPORARY_REDIRECT_STATUS,
12
+ buildLockPageUrl,
13
+ isOnLockPage
14
+ } from "./chunk-ZX5QO4Y2.js";
13
15
  import {
14
16
  APPWARDEN_CACHE_KEY,
15
17
  debug,
@@ -17,7 +19,7 @@ import {
17
19
  globalErrors,
18
20
  isHTMLRequest,
19
21
  printMessage
20
- } from "./chunk-7UTT3M2S.js";
22
+ } from "./chunk-L5EQIJZB.js";
21
23
 
22
24
  // src/runners/appwarden-on-vercel.ts
23
25
  import { waitUntil } from "@vercel/functions";
@@ -233,8 +235,14 @@ function createAppwardenMiddleware(config) {
233
235
  provider
234
236
  })).lockValue;
235
237
  if (lockValue?.isLocked) {
236
- const lockPageUrl = new URL(parsedConfig.lockPageSlug, request.url);
237
- return Response.redirect(lockPageUrl.toString(), 302);
238
+ const lockPageUrl = buildLockPageUrl(
239
+ parsedConfig.lockPageSlug,
240
+ request.url
241
+ );
242
+ return Response.redirect(
243
+ lockPageUrl.toString(),
244
+ TEMPORARY_REDIRECT_STATUS
245
+ );
238
246
  }
239
247
  return NextResponse.next();
240
248
  } catch (e) {
package/chunk-4JGYMZTR.js DELETED
@@ -1,50 +0,0 @@
1
- import {
2
- getErrors
3
- } from "./chunk-B5IE7V77.js";
4
- import {
5
- printMessage
6
- } from "./chunk-7UTT3M2S.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/validate-config.ts
30
- function validateConfig(config, schema) {
31
- const result = schema.safeParse(config);
32
- const hasErrors = !result.success;
33
- if (hasErrors) {
34
- const mappedErrors = getErrors(result.error);
35
- if (mappedErrors.length > 0) {
36
- for (const error of mappedErrors) {
37
- console.error(printMessage(error));
38
- }
39
- } else {
40
- console.error(printMessage(result.error.message));
41
- }
42
- }
43
- return hasErrors;
44
- }
45
-
46
- export {
47
- buildLockPageUrl,
48
- isOnLockPage,
49
- validateConfig
50
- };
package/chunk-6M7BE3AW.js DELETED
@@ -1,15 +0,0 @@
1
- // src/utils/create-redirect.ts
2
- var TEMPORARY_REDIRECT_STATUS = 302;
3
- var createRedirect = (url) => {
4
- return new Response(null, {
5
- status: TEMPORARY_REDIRECT_STATUS,
6
- headers: {
7
- Location: url.toString()
8
- }
9
- });
10
- };
11
-
12
- export {
13
- TEMPORARY_REDIRECT_STATUS,
14
- createRedirect
15
- };