@becklyn/deployment-protection 0.3.0 → 0.4.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # `@becklyn/deployment-protection`
2
2
 
3
- Simple, shared deployment gate for Next.js apps on Vercel.
3
+ Simple, shared deployment gate for Next.js apps and static Storybook deploys on Vercel.
4
4
 
5
5
  Use this instead of (or after disabling) Vercel platform Deployment Protection when you need:
6
6
 
@@ -9,7 +9,10 @@ Use this instead of (or after disabling) Vercel platform Deployment Protection w
9
9
  - always-on **automation bypass** via `x-vercel-protection-bypass` / `VERCEL_AUTOMATION_BYPASS_SECRET`
10
10
  - a kill switch (`DEPLOYMENT_PROTECTION_ENABLED`, on by default)
11
11
 
12
- Protection runs in Next.js **middleware** (Next ≤15) or **proxy** (Next 16+).
12
+ Protection runs in:
13
+
14
+ - Next.js **middleware** (Next ≤15) or **proxy** (Next 16+)
15
+ - **Vercel Edge Middleware** for static Storybook (`@becklyn/deployment-protection/storybook`)
13
16
 
14
17
  > **Note:** Vercel Connect is unrelated (third-party API tokens). Platform Vercel Authentication cookies are not visible to your app once platform protection is off — team members use the **Sign in with Vercel** button instead.
15
18
 
@@ -21,7 +24,47 @@ npm i @becklyn/deployment-protection
21
24
 
22
25
  ## Quick setup
23
26
 
24
- ### 1. Middleware / proxy
27
+ ### Storybook (static on Vercel)
28
+
29
+ Built Storybook is static (`storybook-static`), so protection is **Vercel Routing Middleware** — not a Storybook addon.
30
+
31
+ 1. Install the package in the project that deploys Storybook (published build, or workspace package after `npm run build`).
32
+ 2. Add `middleware.ts` at the **Vercel project root** (same level Vercel uses for `vercel.json` / output):
33
+
34
+ ```ts
35
+ import { withStorybookDeploymentProtection } from "@becklyn/deployment-protection/storybook";
36
+
37
+ export default withStorybookDeploymentProtection();
38
+
39
+ export const config = {
40
+ matcher: ["/((?!.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js|map|txt|xml|woff2?|mjs)$).*)"],
41
+ };
42
+ ```
43
+
44
+ 3. Set the same environment variables as for Next.js (below).
45
+ 4. `vercel.json` for a Storybook-only project — **`framework` must be `null`** (Other). Do **not** use the Vercel “Storybook” framework preset; it sets `disableRootMiddleware` and skips middleware entirely:
46
+
47
+ ```json
48
+ {
49
+ "buildCommand": "npm run build-storybook",
50
+ "outputDirectory": "storybook-static",
51
+ "framework": null
52
+ }
53
+ ```
54
+
55
+ `withStorybookDeploymentProtection` does **not** require the `next` package. The matcher must stay a **string literal** in `middleware.ts` (same static-analysis rule as Next.js).
56
+
57
+ Prefer the default **edge** runtime. `runtime: "nodejs"` is supported as well — both resolve to a self-contained ESM bundle (`dist/storybook.mjs` / `dist/edge.mjs`) so Vercel does not need to trace the multi-file tsc graph.
58
+
59
+ Framework-agnostic alias (same implementation):
60
+
61
+ ```ts
62
+ import { withEdgeDeploymentProtection } from "@becklyn/deployment-protection/edge";
63
+
64
+ export default withEdgeDeploymentProtection();
65
+ ```
66
+
67
+ ### 1. Next.js middleware / proxy
25
68
 
26
69
  Next.js requires `config.matcher` to be a **string literal in the local middleware/proxy file**.
27
70
  It cannot be imported from a package (Next analyzes the matcher statically at build time).
@@ -205,10 +248,13 @@ import {
205
248
  handleDeploymentProtection,
206
249
  resolveConfig,
207
250
  withDeploymentProtection,
251
+ withEdgeDeploymentProtection,
208
252
  } from "@becklyn/deployment-protection";
253
+ import { withStorybookDeploymentProtection } from "@becklyn/deployment-protection/storybook";
209
254
  ```
210
255
 
211
- - `withDeploymentProtection(options?)` / `withDeploymentProtection(next, options?)` — middleware/proxy factory
256
+ - `withDeploymentProtection(options?)` / `withDeploymentProtection(next, options?)` — Next.js middleware/proxy factory
257
+ - `withStorybookDeploymentProtection(options?)` / `withEdgeDeploymentProtection(options?)` — Vercel Edge Middleware for Storybook / static deploys (no Next.js)
212
258
  - `handleDeploymentProtection(request, options?)` — framework-agnostic core (`null` = continue)
213
259
  - `handleAuthProxyStart` / `handleAuthProxyCallback` — central auth-proxy routes
214
260
 
@@ -0,0 +1,14 @@
1
+ import type { DeploymentProtectionOptions } from "./types";
2
+ /**
3
+ * Tell Vercel Edge Middleware to continue to the upstream / static asset.
4
+ * Same signal as `NextResponse.next()` without depending on the Next.js runtime.
5
+ */
6
+ export declare function middlewarePassThrough(): Response;
7
+ /**
8
+ * Framework-agnostic Vercel Edge Middleware factory (no Next.js runtime).
9
+ *
10
+ * Intended for static deployments such as Storybook `storybook-static` on Vercel.
11
+ * Reuses the same env vars and auth behaviour as {@link withDeploymentProtection}.
12
+ */
13
+ export declare function withEdgeDeploymentProtection(options?: DeploymentProtectionOptions): (request: Request) => Promise<Response>;
14
+ //# sourceMappingURL=edge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edge.d.ts","sourceRoot":"","sources":["../../src/edge.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,SAAS,CAAC;AAE3D;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,QAAQ,CAOhD;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,OAAO,GAAE,2BAAgC,IACzB,SAAS,OAAO,KAAG,OAAO,CAAC,QAAQ,CAAC,CAShG"}
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.middlewarePassThrough = middlewarePassThrough;
4
+ exports.withEdgeDeploymentProtection = withEdgeDeploymentProtection;
5
+ const handler_1 = require("./handler");
6
+ /**
7
+ * Tell Vercel Edge Middleware to continue to the upstream / static asset.
8
+ * Same signal as `NextResponse.next()` without depending on the Next.js runtime.
9
+ */
10
+ function middlewarePassThrough() {
11
+ return new Response(null, {
12
+ status: 200,
13
+ headers: {
14
+ "x-middleware-next": "1",
15
+ },
16
+ });
17
+ }
18
+ /**
19
+ * Framework-agnostic Vercel Edge Middleware factory (no Next.js runtime).
20
+ *
21
+ * Intended for static deployments such as Storybook `storybook-static` on Vercel.
22
+ * Reuses the same env vars and auth behaviour as {@link withDeploymentProtection}.
23
+ */
24
+ function withEdgeDeploymentProtection(options = {}) {
25
+ return async function deploymentProtectionEdgeMiddleware(request) {
26
+ const protectionResponse = await (0, handler_1.handleDeploymentProtection)(request, options);
27
+ if (protectionResponse) {
28
+ return protectionResponse;
29
+ }
30
+ return middlewarePassThrough();
31
+ };
32
+ }
@@ -2,6 +2,7 @@ export { INTERNAL_PATH_PREFIX, VERCEL_AUTHORIZE_PATH, VERCEL_CALLBACK_PATH } fro
2
2
  export { AUTH_PROXY_CALLBACK_PATH, AUTH_PROXY_START_PATH, handleAuthProxyCallback, handleAuthProxyStart, } from "./auth-proxy";
3
3
  export { handleDeploymentProtection } from "./handler";
4
4
  export { withDeploymentProtection } from "./middleware";
5
+ export { middlewarePassThrough, withEdgeDeploymentProtection } from "./edge";
5
6
  export { resolveConfig, hasPasswordAuth, hasVercelAuth, hasVercelDirectAuth, hasVercelProxyAuth, isProtectionActive, } from "./config";
6
7
  export type { AuthMethod, DeploymentProtectionConfig, DeploymentProtectionOptions, FormOptions, SessionPayload, } from "./types";
7
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAChG,OAAO,EACH,wBAAwB,EACxB,qBAAqB,EACrB,uBAAuB,EACvB,oBAAoB,GACvB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,0BAA0B,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EACH,aAAa,EACb,eAAe,EACf,aAAa,EACb,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,GACrB,MAAM,UAAU,CAAC;AAClB,YAAY,EACR,UAAU,EACV,0BAA0B,EAC1B,2BAA2B,EAC3B,WAAW,EACX,cAAc,GACjB,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAChG,OAAO,EACH,wBAAwB,EACxB,qBAAqB,EACrB,uBAAuB,EACvB,oBAAoB,GACvB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,0BAA0B,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,4BAA4B,EAAE,MAAM,QAAQ,CAAC;AAC7E,OAAO,EACH,aAAa,EACb,eAAe,EACf,aAAa,EACb,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,GACrB,MAAM,UAAU,CAAC;AAClB,YAAY,EACR,UAAU,EACV,0BAA0B,EAC1B,2BAA2B,EAC3B,WAAW,EACX,cAAc,GACjB,MAAM,SAAS,CAAC"}
package/dist/cjs/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isProtectionActive = exports.hasVercelProxyAuth = exports.hasVercelDirectAuth = exports.hasVercelAuth = exports.hasPasswordAuth = exports.resolveConfig = exports.withDeploymentProtection = exports.handleDeploymentProtection = exports.handleAuthProxyStart = exports.handleAuthProxyCallback = exports.AUTH_PROXY_START_PATH = exports.AUTH_PROXY_CALLBACK_PATH = exports.VERCEL_CALLBACK_PATH = exports.VERCEL_AUTHORIZE_PATH = exports.INTERNAL_PATH_PREFIX = void 0;
3
+ exports.isProtectionActive = exports.hasVercelProxyAuth = exports.hasVercelDirectAuth = exports.hasVercelAuth = exports.hasPasswordAuth = exports.resolveConfig = exports.withEdgeDeploymentProtection = exports.middlewarePassThrough = exports.withDeploymentProtection = exports.handleDeploymentProtection = exports.handleAuthProxyStart = exports.handleAuthProxyCallback = exports.AUTH_PROXY_START_PATH = exports.AUTH_PROXY_CALLBACK_PATH = exports.VERCEL_CALLBACK_PATH = exports.VERCEL_AUTHORIZE_PATH = exports.INTERNAL_PATH_PREFIX = void 0;
4
4
  var constants_1 = require("./constants");
5
5
  Object.defineProperty(exports, "INTERNAL_PATH_PREFIX", { enumerable: true, get: function () { return constants_1.INTERNAL_PATH_PREFIX; } });
6
6
  Object.defineProperty(exports, "VERCEL_AUTHORIZE_PATH", { enumerable: true, get: function () { return constants_1.VERCEL_AUTHORIZE_PATH; } });
@@ -14,6 +14,9 @@ var handler_1 = require("./handler");
14
14
  Object.defineProperty(exports, "handleDeploymentProtection", { enumerable: true, get: function () { return handler_1.handleDeploymentProtection; } });
15
15
  var middleware_1 = require("./middleware");
16
16
  Object.defineProperty(exports, "withDeploymentProtection", { enumerable: true, get: function () { return middleware_1.withDeploymentProtection; } });
17
+ var edge_1 = require("./edge");
18
+ Object.defineProperty(exports, "middlewarePassThrough", { enumerable: true, get: function () { return edge_1.middlewarePassThrough; } });
19
+ Object.defineProperty(exports, "withEdgeDeploymentProtection", { enumerable: true, get: function () { return edge_1.withEdgeDeploymentProtection; } });
17
20
  var config_1 = require("./config");
18
21
  Object.defineProperty(exports, "resolveConfig", { enumerable: true, get: function () { return config_1.resolveConfig; } });
19
22
  Object.defineProperty(exports, "hasPasswordAuth", { enumerable: true, get: function () { return config_1.hasPasswordAuth; } });
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Storybook deployment protection for Vercel.
3
+ *
4
+ * Built Storybooks are static sites, so protection runs as **Vercel Routing Middleware**
5
+ * (not Storybook config). Drop a `middleware.ts` next to the Vercel project root that
6
+ * serves `storybook-static` and set the same env vars as the Next.js integration.
7
+ *
8
+ * The published `./storybook` and `./edge` entry points resolve to self-contained ESM
9
+ * bundles so Vercel edge/nodejs middleware can load them without tracing multi-file
10
+ * package internals.
11
+ *
12
+ * @example middleware.ts
13
+ * ```ts
14
+ * import { withStorybookDeploymentProtection } from "@becklyn/deployment-protection/storybook";
15
+ *
16
+ * export default withStorybookDeploymentProtection();
17
+ *
18
+ * // Matcher must be a string literal in this file (Vercel/Next static analysis).
19
+ * export const config = {
20
+ * matcher: [
21
+ * "/((?!.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js|map|txt|xml|woff2?|mjs)$).*)",
22
+ * ],
23
+ * };
24
+ * ```
25
+ *
26
+ * Optional `vercel.json` for a Storybook-only project (`framework` must be `null`):
27
+ * ```json
28
+ * {
29
+ * "buildCommand": "npm run build-storybook",
30
+ * "outputDirectory": "storybook-static",
31
+ * "framework": null
32
+ * }
33
+ * ```
34
+ */
35
+ export { middlewarePassThrough, withEdgeDeploymentProtection as withStorybookDeploymentProtection, } from "./edge";
36
+ export type { DeploymentProtectionOptions } from "./types";
37
+ //# sourceMappingURL=storybook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storybook.d.ts","sourceRoot":"","sources":["../../src/storybook.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,OAAO,EACH,qBAAqB,EACrB,4BAA4B,IAAI,iCAAiC,GACpE,MAAM,QAAQ,CAAC;AAChB,YAAY,EAAE,2BAA2B,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.withStorybookDeploymentProtection = exports.middlewarePassThrough = void 0;
4
+ /**
5
+ * Storybook deployment protection for Vercel.
6
+ *
7
+ * Built Storybooks are static sites, so protection runs as **Vercel Routing Middleware**
8
+ * (not Storybook config). Drop a `middleware.ts` next to the Vercel project root that
9
+ * serves `storybook-static` and set the same env vars as the Next.js integration.
10
+ *
11
+ * The published `./storybook` and `./edge` entry points resolve to self-contained ESM
12
+ * bundles so Vercel edge/nodejs middleware can load them without tracing multi-file
13
+ * package internals.
14
+ *
15
+ * @example middleware.ts
16
+ * ```ts
17
+ * import { withStorybookDeploymentProtection } from "@becklyn/deployment-protection/storybook";
18
+ *
19
+ * export default withStorybookDeploymentProtection();
20
+ *
21
+ * // Matcher must be a string literal in this file (Vercel/Next static analysis).
22
+ * export const config = {
23
+ * matcher: [
24
+ * "/((?!.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js|map|txt|xml|woff2?|mjs)$).*)",
25
+ * ],
26
+ * };
27
+ * ```
28
+ *
29
+ * Optional `vercel.json` for a Storybook-only project (`framework` must be `null`):
30
+ * ```json
31
+ * {
32
+ * "buildCommand": "npm run build-storybook",
33
+ * "outputDirectory": "storybook-static",
34
+ * "framework": null
35
+ * }
36
+ * ```
37
+ */
38
+ var edge_1 = require("./edge");
39
+ Object.defineProperty(exports, "middlewarePassThrough", { enumerable: true, get: function () { return edge_1.middlewarePassThrough; } });
40
+ Object.defineProperty(exports, "withStorybookDeploymentProtection", { enumerable: true, get: function () { return edge_1.withEdgeDeploymentProtection; } });
@@ -0,0 +1,7 @@
1
+ {
2
+ "format": "esm",
3
+ "entries": [
4
+ "dist/edge.mjs",
5
+ "dist/storybook.mjs"
6
+ ]
7
+ }