@catmint/adapter-vercel 0.0.0-prealpha.1 → 0.0.0-prealpha.11
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 +45 -0
- package/dist/config-gen.d.ts +3 -0
- package/dist/config-gen.d.ts.map +1 -1
- package/dist/config-gen.js +35 -2
- package/dist/config-gen.js.map +1 -1
- package/dist/function-gen.d.ts +1 -1
- package/dist/function-gen.d.ts.map +1 -1
- package/dist/function-gen.js +426 -44
- package/dist/function-gen.js.map +1 -1
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +74 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# @catmint/adapter-vercel
|
|
2
|
+
|
|
3
|
+
Vercel deployment adapter for [Catmint](https://github.com/darylcecile/catmint).
|
|
4
|
+
|
|
5
|
+
Generates output in the [Vercel Build Output API v3](https://vercel.com/docs/build-output-api/v3) format, including serverless functions, static assets, and prerender functions for cached routes.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm add @catmint/adapter-vercel
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
// catmint.config.ts
|
|
17
|
+
import { defineConfig } from "catmint/config";
|
|
18
|
+
import vercelAdapter from "@catmint/adapter-vercel";
|
|
19
|
+
|
|
20
|
+
export default defineConfig({
|
|
21
|
+
mode: "fullstack",
|
|
22
|
+
adapter: vercelAdapter({
|
|
23
|
+
runtime: "nodejs",
|
|
24
|
+
regions: ["iad1"],
|
|
25
|
+
}),
|
|
26
|
+
});
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Options
|
|
30
|
+
|
|
31
|
+
| Option | Type | Default | Description |
|
|
32
|
+
| --------- | ---------------------- | ---------- | --------------------------- |
|
|
33
|
+
| `runtime` | `"nodejs"` \| `"edge"` | `"nodejs"` | Serverless function runtime |
|
|
34
|
+
| `regions` | `string[]` | -- | Deployment regions |
|
|
35
|
+
|
|
36
|
+
## Deploy
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
catmint build
|
|
40
|
+
vercel deploy --prebuilt
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## License
|
|
44
|
+
|
|
45
|
+
GNU General Public License v2
|
package/dist/config-gen.d.ts
CHANGED
package/dist/config-gen.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-gen.d.ts","sourceRoot":"","sources":["../src/config-gen.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD;;GAEG;AACH,UAAU,iBAAiB;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,KAAK,CAAC;QACV,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;QAC7C,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC,CAAC;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;GAIG;AACH,UAAU,kBAAkB;IAC1B,MAAM,EAAE,SAAS,GAAG,YAAY,GAAG,UAAU,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,CAAC;IACzE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,KAAK,WAAW,GAAG,iBAAiB,GAAG,kBAAkB,CAAC;AAE1D;;GAEG;AACH,UAAU,YAAY;IACpB,OAAO,EAAE,CAAC,CAAC;IACX,MAAM,EAAE,WAAW,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"config-gen.d.ts","sourceRoot":"","sources":["../src/config-gen.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD;;GAEG;AACH,UAAU,iBAAiB;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,KAAK,CAAC;QACV,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;QAC7C,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC,CAAC;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;GAIG;AACH,UAAU,kBAAkB;IAC1B,MAAM,EAAE,SAAS,GAAG,YAAY,GAAG,UAAU,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,CAAC;IACzE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,KAAK,WAAW,GAAG,iBAAiB,GAAG,kBAAkB,CAAC;AAE1D;;GAEG;AACH,UAAU,YAAY;IACpB,OAAO,EAAE,CAAC,CAAC;IACX,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC9C;AAmBD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,WAAW,GAAG,YAAY,CA6GxE"}
|
package/dist/config-gen.js
CHANGED
|
@@ -40,7 +40,11 @@ export function generateVercelConfig(manifest) {
|
|
|
40
40
|
dest: "/index",
|
|
41
41
|
});
|
|
42
42
|
// 3. Process manifest routes
|
|
43
|
+
// Skip static routes without middleware — they are served directly from
|
|
44
|
+
// the static/ directory via { handle: "filesystem" } below.
|
|
43
45
|
for (const route of [...manifest.routes, ...manifest.endpoints]) {
|
|
46
|
+
if (route.renderMode === "static" && !route.hasMiddleware)
|
|
47
|
+
continue;
|
|
44
48
|
const src = routePathToVercelSrc(route.path);
|
|
45
49
|
// For cached routes with prerender configs, route to the dedicated function
|
|
46
50
|
const routeName = route.cache && route.path !== "/"
|
|
@@ -69,11 +73,25 @@ export function generateVercelConfig(manifest) {
|
|
|
69
73
|
}
|
|
70
74
|
routes.push(vercelRoute);
|
|
71
75
|
}
|
|
72
|
-
// 4.
|
|
76
|
+
// 4. Rewrite middleware-protected static routes to the serverless function.
|
|
77
|
+
// These paths have pre-rendered HTML but must go through middleware, so
|
|
78
|
+
// they MUST NOT be served from the static/ directory by Vercel's CDN.
|
|
79
|
+
// This rewrite rule runs BEFORE { handle: "filesystem" } to intercept
|
|
80
|
+
// the request before Vercel checks for a matching static file.
|
|
81
|
+
for (const route of manifest.routes) {
|
|
82
|
+
if (route.hasMiddleware && route.renderMode === "static") {
|
|
83
|
+
const src = routePathToVercelSrc(route.path);
|
|
84
|
+
routes.push({
|
|
85
|
+
src,
|
|
86
|
+
dest: "/index",
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// 5. Check the filesystem (static/ directory) before the catch-all.
|
|
73
91
|
// Without this, the catch-all below would intercept requests for static
|
|
74
92
|
// assets (JS, CSS, images) and send them to the serverless function.
|
|
75
93
|
routes.push({ handle: "filesystem" });
|
|
76
|
-
//
|
|
94
|
+
// 6. Fallback: rewrite all unmatched requests to the serverless function
|
|
77
95
|
// This only triggers for requests that didn't match a static file above.
|
|
78
96
|
if (manifest.mode !== "frontend") {
|
|
79
97
|
routes.push({
|
|
@@ -81,9 +99,24 @@ export function generateVercelConfig(manifest) {
|
|
|
81
99
|
dest: "/index",
|
|
82
100
|
});
|
|
83
101
|
}
|
|
102
|
+
// 7. Build overrides map for static routes.
|
|
103
|
+
// Pre-rendered HTML is written as e.g. "about.html" but the browser
|
|
104
|
+
// requests "/about" (clean URL). Vercel's filesystem handler does an
|
|
105
|
+
// exact path match, so without overrides it won't find the .html file
|
|
106
|
+
// and the request falls through to the catch-all serverless function.
|
|
107
|
+
// The overrides map tells Vercel to serve "about.html" for path "about".
|
|
108
|
+
const overrides = {};
|
|
109
|
+
for (const route of manifest.routes) {
|
|
110
|
+
if (route.renderMode === "static" && !route.hasMiddleware) {
|
|
111
|
+
const cleanPath = route.path === "/" ? "index" : route.path.replace(/^\//, "");
|
|
112
|
+
const htmlFile = cleanPath + ".html";
|
|
113
|
+
overrides[htmlFile] = { path: cleanPath };
|
|
114
|
+
}
|
|
115
|
+
}
|
|
84
116
|
return {
|
|
85
117
|
version: 3,
|
|
86
118
|
routes,
|
|
119
|
+
...(Object.keys(overrides).length > 0 ? { overrides } : {}),
|
|
87
120
|
};
|
|
88
121
|
}
|
|
89
122
|
//# sourceMappingURL=config-gen.js.map
|
package/dist/config-gen.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-gen.js","sourceRoot":"","sources":["../src/config-gen.ts"],"names":[],"mappings":"AAAA,0EAA0E;
|
|
1
|
+
{"version":3,"file":"config-gen.js","sourceRoot":"","sources":["../src/config-gen.ts"],"names":[],"mappings":"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"}
|
package/dist/function-gen.d.ts
CHANGED
|
@@ -36,6 +36,6 @@ export declare function generateVcConfig(runtime: "nodejs" | "edge", regions?: s
|
|
|
36
36
|
* function registers a platform cache adapter that delegates invalidation
|
|
37
37
|
* to Vercel's on-demand ISR revalidation API.
|
|
38
38
|
*/
|
|
39
|
-
export declare function generateServerlessFunction(manifest: AppManifest, runtime: "nodejs" | "edge"): string;
|
|
39
|
+
export declare function generateServerlessFunction(manifest: AppManifest, runtime: "nodejs" | "edge", maxBodySize: number, headerPreset: "baseline" | "none"): string;
|
|
40
40
|
export {};
|
|
41
41
|
//# sourceMappingURL=function-gen.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"function-gen.d.ts","sourceRoot":"","sources":["../src/function-gen.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD;;GAEG;AACH,UAAU,cAAc;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,QAAQ,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;GAEG;AACH,UAAU,YAAY;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,KAAK,QAAQ,GAAG,cAAc,GAAG,YAAY,CAAC;AAmF9C;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,QAAQ,GAAG,MAAM,EAC1B,OAAO,CAAC,EAAE,MAAM,EAAE,GACjB,QAAQ,CAqBV;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,WAAW,EACrB,OAAO,EAAE,QAAQ,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"function-gen.d.ts","sourceRoot":"","sources":["../src/function-gen.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD;;GAEG;AACH,UAAU,cAAc;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,QAAQ,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;GAEG;AACH,UAAU,YAAY;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,KAAK,QAAQ,GAAG,cAAc,GAAG,YAAY,CAAC;AAmF9C;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,QAAQ,GAAG,MAAM,EAC1B,OAAO,CAAC,EAAE,MAAM,EAAE,GACjB,QAAQ,CAqBV;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,WAAW,EACrB,OAAO,EAAE,QAAQ,GAAG,MAAM,EAC1B,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,UAAU,GAAG,MAAM,GAChC,MAAM,CAKR"}
|
package/dist/function-gen.js
CHANGED
|
@@ -112,27 +112,79 @@ export function generateVcConfig(runtime, regions) {
|
|
|
112
112
|
* function registers a platform cache adapter that delegates invalidation
|
|
113
113
|
* to Vercel's on-demand ISR revalidation API.
|
|
114
114
|
*/
|
|
115
|
-
export function generateServerlessFunction(manifest, runtime) {
|
|
115
|
+
export function generateServerlessFunction(manifest, runtime, maxBodySize, headerPreset) {
|
|
116
116
|
if (runtime === "edge") {
|
|
117
|
-
return generateEdgeFunction(manifest);
|
|
117
|
+
return generateEdgeFunction(manifest, maxBodySize, headerPreset);
|
|
118
118
|
}
|
|
119
|
-
return generateNodejsFunction(manifest);
|
|
119
|
+
return generateNodejsFunction(manifest, maxBodySize, headerPreset);
|
|
120
120
|
}
|
|
121
|
-
function generateNodejsFunction(manifest) {
|
|
121
|
+
function generateNodejsFunction(manifest, maxBodySize, headerPreset) {
|
|
122
122
|
const cacheAdapterSetup = generateCacheAdapterSetup(manifest);
|
|
123
123
|
return `// Auto-generated by @catmint/adapter-vercel (Node.js runtime) — do not edit
|
|
124
124
|
import * as rscEntry from "./rsc/index.js";
|
|
125
125
|
import * as ssrEntry from "./ssr/index.js";
|
|
126
|
+
import { readFile, stat } from "node:fs/promises";
|
|
127
|
+
import { join, extname } from "node:path";
|
|
128
|
+
import { fileURLToPath } from "node:url";
|
|
129
|
+
import { createHash } from "node:crypto";
|
|
130
|
+
|
|
131
|
+
function __isClientSafeErrorLike(err) {
|
|
132
|
+
return err != null && typeof err === "object" && err.constructor && err.constructor.name === "ClientSafeError" && typeof err.statusCode === "number";
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function __isRedirectErrorLike(err) {
|
|
136
|
+
return err != null && typeof err === "object" && err.constructor && err.constructor.name === "RedirectError" && typeof err.url === "string" && typeof err.status === "number";
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function __errorRef(err) {
|
|
140
|
+
var msg = (err && typeof err === "object" && err.message) ? String(err.message) : "unknown";
|
|
141
|
+
return createHash("sha256").update(msg + Date.now()).digest("hex").slice(0, 8);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const __dirname = fileURLToPath(new URL(".", import.meta.url));
|
|
145
|
+
const PRERENDERED_DIR = join(__dirname, "prerendered");
|
|
126
146
|
${cacheAdapterSetup}
|
|
127
147
|
function collectBody(req) {
|
|
148
|
+
const MAX_BODY_SIZE = ${maxBodySize};
|
|
128
149
|
return new Promise((resolve, reject) => {
|
|
129
150
|
const chunks = [];
|
|
130
|
-
|
|
151
|
+
let totalLength = 0;
|
|
152
|
+
req.on("data", (chunk) => {
|
|
153
|
+
totalLength += chunk.length;
|
|
154
|
+
if (totalLength > MAX_BODY_SIZE) {
|
|
155
|
+
req.destroy();
|
|
156
|
+
reject(new Error("Request body too large"));
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
chunks.push(chunk);
|
|
160
|
+
});
|
|
131
161
|
req.on("end", () => resolve(Buffer.concat(chunks)));
|
|
132
162
|
req.on("error", reject);
|
|
133
163
|
});
|
|
134
164
|
}
|
|
135
165
|
|
|
166
|
+
function nodeReqToWebRequest(req) {
|
|
167
|
+
const protocol = "https";
|
|
168
|
+
const host = req.headers.host || "localhost";
|
|
169
|
+
const reqUrl = new URL(req.url || "/", \`\${protocol}://\${host}\`);
|
|
170
|
+
const headers = new Headers();
|
|
171
|
+
for (const [key, value] of Object.entries(req.headers)) {
|
|
172
|
+
if (value) {
|
|
173
|
+
if (Array.isArray(value)) {
|
|
174
|
+
for (const v of value) {
|
|
175
|
+
headers.append(key, v);
|
|
176
|
+
}
|
|
177
|
+
} else {
|
|
178
|
+
headers.set(key, value);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return new Request(reqUrl.href, {
|
|
183
|
+
method: req.method || "GET",
|
|
184
|
+
headers,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
|
|
136
188
|
async function pipeWebStreamToResponse(webStream, res) {
|
|
137
189
|
const reader = webStream.getReader();
|
|
138
190
|
try {
|
|
@@ -216,13 +268,97 @@ function __catmintErrorPage(statusCode, detail) {
|
|
|
216
268
|
}
|
|
217
269
|
|
|
218
270
|
export default async function handler(req, res) {
|
|
271
|
+
${headerPreset === "baseline"
|
|
272
|
+
? ` // Baseline security headers
|
|
273
|
+
res.setHeader("X-Content-Type-Options", "nosniff");
|
|
274
|
+
res.setHeader("Referrer-Policy", "strict-origin-when-cross-origin");
|
|
275
|
+
res.setHeader("X-Frame-Options", "SAMEORIGIN");
|
|
276
|
+
`
|
|
277
|
+
: ""}
|
|
219
278
|
const url = new URL(req.url || "/", \`https://\${req.headers.host || "localhost"}\`);
|
|
220
279
|
const pathname = url.pathname;
|
|
221
280
|
const method = (req.method || "GET").toUpperCase();
|
|
222
281
|
|
|
223
282
|
try {
|
|
224
|
-
// 1.
|
|
283
|
+
// 1. Middleware execution — runs for all routes handled by this function.
|
|
284
|
+
// For RSC flight requests, run middleware against the TARGET page path
|
|
285
|
+
// (from ?path= query param), not the literal /__catmint/rsc pathname.
|
|
286
|
+
var middlewareHeaders = null;
|
|
287
|
+
if (ssrEntry.executeMiddleware) {
|
|
288
|
+
try {
|
|
289
|
+
var middlewarePath = pathname;
|
|
290
|
+
if (pathname === "/__catmint/rsc") {
|
|
291
|
+
var rscTargetPath = url.searchParams.get("path");
|
|
292
|
+
if (rscTargetPath) middlewarePath = rscTargetPath;
|
|
293
|
+
}
|
|
294
|
+
var webRequest = nodeReqToWebRequest(req);
|
|
295
|
+
var mwResult = await ssrEntry.executeMiddleware(middlewarePath, webRequest);
|
|
296
|
+
|
|
297
|
+
if (mwResult.shortCircuit) {
|
|
298
|
+
// Middleware short-circuited — return its response directly
|
|
299
|
+
res.statusCode = mwResult.shortCircuit.status;
|
|
300
|
+
mwResult.shortCircuit.headers.forEach(function(value, key) {
|
|
301
|
+
res.setHeader(key, value);
|
|
302
|
+
});
|
|
303
|
+
var scBody = await mwResult.shortCircuit.text();
|
|
304
|
+
res.end(scBody);
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Middleware passed — capture headers to merge into final response
|
|
309
|
+
if (mwResult.headers && typeof mwResult.headers.forEach === "function") {
|
|
310
|
+
middlewareHeaders = mwResult.headers;
|
|
311
|
+
}
|
|
312
|
+
} catch (err) {
|
|
313
|
+
console.error("Middleware error:", err);
|
|
314
|
+
if (!res.headersSent) {
|
|
315
|
+
res.statusCode = 500;
|
|
316
|
+
res.end("Internal Server Error");
|
|
317
|
+
}
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Helper: merge middleware headers into the response before sending.
|
|
323
|
+
function applyMiddlewareHeaders() {
|
|
324
|
+
if (middlewareHeaders) {
|
|
325
|
+
middlewareHeaders.forEach(function(value, key) {
|
|
326
|
+
res.setHeader(key, value);
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// 2. Handle server function RPC calls (/__catmint/fn/*)
|
|
225
332
|
if (pathname.startsWith("/__catmint/fn/") && ssrEntry.handleServerFn) {
|
|
333
|
+
// Enforce POST method
|
|
334
|
+
if (method !== "POST") {
|
|
335
|
+
res.statusCode = 405;
|
|
336
|
+
res.setHeader("Content-Type", "application/json");
|
|
337
|
+
res.end(JSON.stringify({ error: "Method " + method + " not allowed, expected POST" }));
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Enforce Content-Type: application/json
|
|
342
|
+
const ct = (req.headers["content-type"] || "").toLowerCase();
|
|
343
|
+
if (ct && !ct.startsWith("application/json")) {
|
|
344
|
+
res.statusCode = 415;
|
|
345
|
+
res.setHeader("Content-Type", "application/json");
|
|
346
|
+
res.end(JSON.stringify({ error: "Unsupported Content-Type, expected application/json" }));
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// Validate Origin header
|
|
351
|
+
const origin = req.headers["origin"];
|
|
352
|
+
if (origin) {
|
|
353
|
+
const expectedHost = req.headers.host || "localhost";
|
|
354
|
+
if (origin !== \`https://\${expectedHost}\` && origin !== \`http://\${expectedHost}\`) {
|
|
355
|
+
res.statusCode = 403;
|
|
356
|
+
res.setHeader("Content-Type", "application/json");
|
|
357
|
+
res.end(JSON.stringify({ error: "Origin not allowed" }));
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
226
362
|
const body = await collectBody(req);
|
|
227
363
|
let parsed;
|
|
228
364
|
try {
|
|
@@ -233,20 +369,62 @@ export default async function handler(req, res) {
|
|
|
233
369
|
res.end(JSON.stringify({ error: "Invalid JSON body" }));
|
|
234
370
|
return;
|
|
235
371
|
}
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
372
|
+
try {
|
|
373
|
+
const result = await ssrEntry.handleServerFn(pathname, parsed);
|
|
374
|
+
if (result) {
|
|
375
|
+
// Check if the result IS a ClientSafeError (returned, not thrown)
|
|
376
|
+
if (__isClientSafeErrorLike(result.result)) {
|
|
377
|
+
applyMiddlewareHeaders();
|
|
378
|
+
res.statusCode = 200;
|
|
379
|
+
res.setHeader("Content-Type", "application/json");
|
|
380
|
+
res.end(JSON.stringify({
|
|
381
|
+
__clientSafeError: true,
|
|
382
|
+
error: result.result.message,
|
|
383
|
+
statusCode: result.result.statusCode,
|
|
384
|
+
data: result.result.data,
|
|
385
|
+
}));
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
applyMiddlewareHeaders();
|
|
389
|
+
res.statusCode = 200;
|
|
390
|
+
res.setHeader("Content-Type", "application/json");
|
|
391
|
+
res.end(JSON.stringify(result.result));
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
res.statusCode = 404;
|
|
239
395
|
res.setHeader("Content-Type", "application/json");
|
|
240
|
-
res.end(JSON.stringify(
|
|
241
|
-
|
|
396
|
+
res.end(JSON.stringify({ error: "Server function not found" }));
|
|
397
|
+
} catch (err) {
|
|
398
|
+
// Always log full error server-side
|
|
399
|
+
console.error("[catmint] Server function error:", err);
|
|
400
|
+
|
|
401
|
+
// RedirectError — send redirect envelope
|
|
402
|
+
if (__isRedirectErrorLike(err)) {
|
|
403
|
+
res.statusCode = 200;
|
|
404
|
+
res.setHeader("Content-Type", "application/json");
|
|
405
|
+
res.end(JSON.stringify({ __redirect: true, url: err.url, status: err.status }));
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// ClientSafeError — developer opted in, expose to client
|
|
410
|
+
if (__isClientSafeErrorLike(err)) {
|
|
411
|
+
res.statusCode = err.statusCode;
|
|
412
|
+
res.setHeader("Content-Type", "application/json");
|
|
413
|
+
res.end(JSON.stringify({ error: err.message, data: err.data }));
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// Default: sanitize — generic message with correlation hash
|
|
418
|
+
const ref = __errorRef(err);
|
|
419
|
+
console.error("[catmint] Error reference [ref: " + ref + "] — see above for full error");
|
|
420
|
+
res.statusCode = 500;
|
|
421
|
+
res.setHeader("Content-Type", "application/json");
|
|
422
|
+
res.end(JSON.stringify({ error: "Internal Server Error [ref: " + ref + "]" }));
|
|
242
423
|
}
|
|
243
|
-
res.statusCode = 404;
|
|
244
|
-
res.setHeader("Content-Type", "application/json");
|
|
245
|
-
res.end(JSON.stringify({ error: "Server function not found" }));
|
|
246
424
|
return;
|
|
247
425
|
}
|
|
248
426
|
|
|
249
|
-
//
|
|
427
|
+
// 3. RSC flight stream for client-side navigation (/__catmint/rsc?path=...)
|
|
250
428
|
if (pathname === "/__catmint/rsc" && method === "GET" && rscEntry.render) {
|
|
251
429
|
const targetPath = url.searchParams.get("path");
|
|
252
430
|
if (!targetPath) {
|
|
@@ -258,6 +436,7 @@ export default async function handler(req, res) {
|
|
|
258
436
|
try {
|
|
259
437
|
const rscResult = await rscEntry.render(targetPath);
|
|
260
438
|
if (rscResult) {
|
|
439
|
+
applyMiddlewareHeaders();
|
|
261
440
|
res.statusCode = 200;
|
|
262
441
|
res.setHeader("Content-Type", "text/x-component; charset=utf-8");
|
|
263
442
|
res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
|
@@ -278,7 +457,7 @@ export default async function handler(req, res) {
|
|
|
278
457
|
return;
|
|
279
458
|
}
|
|
280
459
|
|
|
281
|
-
//
|
|
460
|
+
// 4. API endpoint handling
|
|
282
461
|
if (ssrEntry.hasEndpoint && ssrEntry.hasEndpoint(pathname)) {
|
|
283
462
|
const fullUrl = \`https://\${req.headers.host || "localhost"}\${req.url || "/"}\`;
|
|
284
463
|
const requestInit = {
|
|
@@ -300,6 +479,7 @@ export default async function handler(req, res) {
|
|
|
300
479
|
result.response.headers.forEach((value, key) => {
|
|
301
480
|
res.setHeader(key, value);
|
|
302
481
|
});
|
|
482
|
+
applyMiddlewareHeaders();
|
|
303
483
|
res.statusCode = result.response.status;
|
|
304
484
|
if (result.response.body) {
|
|
305
485
|
await pipeWebStreamToResponse(result.response.body, res);
|
|
@@ -315,11 +495,41 @@ export default async function handler(req, res) {
|
|
|
315
495
|
return;
|
|
316
496
|
}
|
|
317
497
|
|
|
318
|
-
//
|
|
498
|
+
// 5. Pre-rendered pages WITH middleware: serve from function bundle.
|
|
499
|
+
// These are static routes that have middleware ancestors — their HTML
|
|
500
|
+
// was pre-rendered but placed in the function directory, not in
|
|
501
|
+
// Vercel's static/ directory (to avoid bypassing middleware).
|
|
502
|
+
if (method === "GET") {
|
|
503
|
+
let prerenderedPath = pathname;
|
|
504
|
+
if (!extname(prerenderedPath)) {
|
|
505
|
+
prerenderedPath = prerenderedPath.endsWith("/")
|
|
506
|
+
? prerenderedPath + "index.html"
|
|
507
|
+
: prerenderedPath + ".html";
|
|
508
|
+
}
|
|
509
|
+
try {
|
|
510
|
+
const prFilePath = join(PRERENDERED_DIR, prerenderedPath);
|
|
511
|
+
const prStats = await stat(prFilePath);
|
|
512
|
+
if (prStats.isFile()) {
|
|
513
|
+
const content = await readFile(prFilePath);
|
|
514
|
+
applyMiddlewareHeaders();
|
|
515
|
+
res.statusCode = 200;
|
|
516
|
+
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
517
|
+
res.setHeader("Content-Length", content.byteLength);
|
|
518
|
+
res.setHeader("Cache-Control", "public, max-age=0, must-revalidate");
|
|
519
|
+
res.end(content);
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
} catch {
|
|
523
|
+
// No prerendered file — continue to RSC rendering
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
// 6. RSC → SSR page rendering pipeline
|
|
319
528
|
if (method === "GET" && rscEntry.render) {
|
|
320
529
|
const rscResult = await rscEntry.render(pathname);
|
|
321
530
|
if (rscResult) {
|
|
322
531
|
const htmlStream = await ssrEntry.renderToHtml(rscResult.stream, rscResult.headConfig);
|
|
532
|
+
applyMiddlewareHeaders();
|
|
323
533
|
res.statusCode = 200;
|
|
324
534
|
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
325
535
|
await pipeWebStreamToResponse(htmlStream, res);
|
|
@@ -327,7 +537,7 @@ export default async function handler(req, res) {
|
|
|
327
537
|
}
|
|
328
538
|
}
|
|
329
539
|
|
|
330
|
-
//
|
|
540
|
+
// 7. Fallback 404
|
|
331
541
|
await sendStatusPage(res, 404, pathname);
|
|
332
542
|
} catch (err) {
|
|
333
543
|
console.error("Serverless function error:", err);
|
|
@@ -336,12 +546,33 @@ export default async function handler(req, res) {
|
|
|
336
546
|
}
|
|
337
547
|
`;
|
|
338
548
|
}
|
|
339
|
-
function generateEdgeFunction(manifest) {
|
|
549
|
+
function generateEdgeFunction(manifest, maxBodySize, headerPreset) {
|
|
340
550
|
const cacheAdapterSetup = generateCacheAdapterSetup(manifest);
|
|
551
|
+
// Check if there are middleware-protected static routes
|
|
552
|
+
const hasMiddlewareProtected = manifest.routes.some((r) => r.hasMiddleware && r.renderMode === "static");
|
|
341
553
|
return `// Auto-generated by @catmint/adapter-vercel (Edge runtime) — do not edit
|
|
342
554
|
import * as rscEntry from "./rsc/index.js";
|
|
343
555
|
import * as ssrEntry from "./ssr/index.js";
|
|
556
|
+
${hasMiddlewareProtected ? 'import { prerenderedPages } from "./prerendered.js";' : ""}
|
|
344
557
|
${cacheAdapterSetup}
|
|
558
|
+
function __isClientSafeErrorLike(err) {
|
|
559
|
+
return err != null && typeof err === "object" && err.constructor && err.constructor.name === "ClientSafeError" && typeof err.statusCode === "number";
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
function __isRedirectErrorLike(err) {
|
|
563
|
+
return err != null && typeof err === "object" && err.constructor && err.constructor.name === "RedirectError" && typeof err.url === "string" && typeof err.status === "number";
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
async function __errorRef(err) {
|
|
567
|
+
var msg = (err && typeof err === "object" && err.message) ? String(err.message) : "unknown";
|
|
568
|
+
var data = new TextEncoder().encode(msg + Date.now());
|
|
569
|
+
var buf = await crypto.subtle.digest("SHA-256", data);
|
|
570
|
+
var arr = new Uint8Array(buf);
|
|
571
|
+
var hex = "";
|
|
572
|
+
for (var i = 0; i < arr.length; i++) hex += arr[i].toString(16).padStart(2, "0");
|
|
573
|
+
return hex.slice(0, 8);
|
|
574
|
+
}
|
|
575
|
+
|
|
345
576
|
async function statusPageResponse(statusCode, pathname) {
|
|
346
577
|
if (rscEntry.renderStatusPage && ssrEntry.renderToHtml) {
|
|
347
578
|
try {
|
|
@@ -407,37 +638,174 @@ export default async function handler(request) {
|
|
|
407
638
|
const pathname = url.pathname;
|
|
408
639
|
const method = request.method.toUpperCase();
|
|
409
640
|
|
|
641
|
+
// Helper to create responses${headerPreset === "baseline" ? " with baseline security headers" : ""}
|
|
642
|
+
function secureResponse(body, init = {}) {
|
|
643
|
+
const headers = new Headers(init.headers || {});
|
|
644
|
+
${headerPreset === "baseline"
|
|
645
|
+
? ` headers.set("X-Content-Type-Options", "nosniff");
|
|
646
|
+
headers.set("Referrer-Policy", "strict-origin-when-cross-origin");
|
|
647
|
+
headers.set("X-Frame-Options", "SAMEORIGIN");
|
|
648
|
+
`
|
|
649
|
+
: ""} return new Response(body, { ...init, headers });
|
|
650
|
+
}
|
|
651
|
+
|
|
410
652
|
try {
|
|
411
|
-
// 1.
|
|
653
|
+
// 1. Middleware execution — runs for all routes handled by this function.
|
|
654
|
+
// For RSC flight requests, run middleware against the TARGET page path
|
|
655
|
+
// (from ?path= query param), not the literal /__catmint/rsc pathname.
|
|
656
|
+
var middlewareHeaders = null;
|
|
657
|
+
if (ssrEntry.executeMiddleware) {
|
|
658
|
+
try {
|
|
659
|
+
var middlewarePath = pathname;
|
|
660
|
+
if (pathname === "/__catmint/rsc") {
|
|
661
|
+
var rscTargetPath = url.searchParams.get("path");
|
|
662
|
+
if (rscTargetPath) middlewarePath = rscTargetPath;
|
|
663
|
+
}
|
|
664
|
+
var mwResult = await ssrEntry.executeMiddleware(middlewarePath, request);
|
|
665
|
+
|
|
666
|
+
if (mwResult.shortCircuit) {
|
|
667
|
+
// Middleware short-circuited — return its response directly
|
|
668
|
+
return mwResult.shortCircuit;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
// Middleware passed — capture headers to merge into final response
|
|
672
|
+
if (mwResult.headers && typeof mwResult.headers.forEach === "function") {
|
|
673
|
+
middlewareHeaders = mwResult.headers;
|
|
674
|
+
}
|
|
675
|
+
} catch (err) {
|
|
676
|
+
console.error("Middleware error:", err);
|
|
677
|
+
return new Response("Internal Server Error", { status: 500 });
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
// Helper: create a new response with middleware headers merged in
|
|
682
|
+
function applyMiddlewareHeaders(response) {
|
|
683
|
+
if (!middlewareHeaders) return response;
|
|
684
|
+
var headers = new Headers(response.headers);
|
|
685
|
+
middlewareHeaders.forEach(function(value, key) {
|
|
686
|
+
headers.set(key, value);
|
|
687
|
+
});
|
|
688
|
+
return new Response(response.body, {
|
|
689
|
+
status: response.status,
|
|
690
|
+
headers,
|
|
691
|
+
});
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
// 2. Handle server function RPC calls (/__catmint/fn/*)
|
|
412
695
|
if (pathname.startsWith("/__catmint/fn/") && ssrEntry.handleServerFn) {
|
|
696
|
+
// Enforce POST method
|
|
697
|
+
if (method !== "POST") {
|
|
698
|
+
return secureResponse(
|
|
699
|
+
JSON.stringify({ error: "Method " + method + " not allowed, expected POST" }),
|
|
700
|
+
{ status: 405, headers: { "Content-Type": "application/json" } },
|
|
701
|
+
);
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
// Enforce Content-Type: application/json
|
|
705
|
+
const ct = (request.headers.get("content-type") || "").toLowerCase();
|
|
706
|
+
if (ct && !ct.startsWith("application/json")) {
|
|
707
|
+
return secureResponse(
|
|
708
|
+
JSON.stringify({ error: "Unsupported Content-Type, expected application/json" }),
|
|
709
|
+
{ status: 415, headers: { "Content-Type": "application/json" } },
|
|
710
|
+
);
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
// Validate Origin header
|
|
714
|
+
const origin = request.headers.get("origin");
|
|
715
|
+
if (origin) {
|
|
716
|
+
const expectedOrigin = url.origin;
|
|
717
|
+
if (origin !== expectedOrigin) {
|
|
718
|
+
return secureResponse(
|
|
719
|
+
JSON.stringify({ error: "Origin not allowed" }),
|
|
720
|
+
{ status: 403, headers: { "Content-Type": "application/json" } },
|
|
721
|
+
);
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
// Read body with size limit
|
|
726
|
+
const MAX_BODY_SIZE = ${maxBodySize};
|
|
727
|
+
const contentLength = parseInt(request.headers.get("content-length") || "0", 10);
|
|
728
|
+
if (contentLength > MAX_BODY_SIZE) {
|
|
729
|
+
return secureResponse(
|
|
730
|
+
JSON.stringify({ error: "Request body too large" }),
|
|
731
|
+
{ status: 413, headers: { "Content-Type": "application/json" } },
|
|
732
|
+
);
|
|
733
|
+
}
|
|
413
734
|
const bodyText = await request.text();
|
|
735
|
+
if (bodyText.length > MAX_BODY_SIZE) {
|
|
736
|
+
return secureResponse(
|
|
737
|
+
JSON.stringify({ error: "Request body too large" }),
|
|
738
|
+
{ status: 413, headers: { "Content-Type": "application/json" } },
|
|
739
|
+
);
|
|
740
|
+
}
|
|
414
741
|
let parsed;
|
|
415
742
|
try {
|
|
416
743
|
parsed = bodyText.length > 0 ? JSON.parse(bodyText) : undefined;
|
|
417
744
|
} catch {
|
|
418
|
-
return
|
|
745
|
+
return secureResponse(
|
|
419
746
|
JSON.stringify({ error: "Invalid JSON body" }),
|
|
420
747
|
{ status: 400, headers: { "Content-Type": "application/json" } },
|
|
421
748
|
);
|
|
422
749
|
}
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
750
|
+
try {
|
|
751
|
+
const result = await ssrEntry.handleServerFn(pathname, parsed);
|
|
752
|
+
if (result) {
|
|
753
|
+
// Check if the result IS a ClientSafeError (returned, not thrown)
|
|
754
|
+
if (__isClientSafeErrorLike(result.result)) {
|
|
755
|
+
return applyMiddlewareHeaders(secureResponse(JSON.stringify({
|
|
756
|
+
__clientSafeError: true,
|
|
757
|
+
error: result.result.message,
|
|
758
|
+
statusCode: result.result.statusCode,
|
|
759
|
+
data: result.result.data,
|
|
760
|
+
}), {
|
|
761
|
+
status: 200,
|
|
762
|
+
headers: { "Content-Type": "application/json" },
|
|
763
|
+
}));
|
|
764
|
+
}
|
|
765
|
+
return applyMiddlewareHeaders(secureResponse(JSON.stringify(result.result), {
|
|
766
|
+
status: 200,
|
|
767
|
+
headers: { "Content-Type": "application/json" },
|
|
768
|
+
}));
|
|
769
|
+
}
|
|
770
|
+
return secureResponse(
|
|
771
|
+
JSON.stringify({ error: "Server function not found" }),
|
|
772
|
+
{ status: 404, headers: { "Content-Type": "application/json" } },
|
|
773
|
+
);
|
|
774
|
+
} catch (err) {
|
|
775
|
+
// Always log full error server-side
|
|
776
|
+
console.error("[catmint] Server function error:", err);
|
|
777
|
+
|
|
778
|
+
// RedirectError — send redirect envelope
|
|
779
|
+
if (__isRedirectErrorLike(err)) {
|
|
780
|
+
return secureResponse(
|
|
781
|
+
JSON.stringify({ __redirect: true, url: err.url, status: err.status }),
|
|
782
|
+
{ status: 200, headers: { "Content-Type": "application/json" } },
|
|
783
|
+
);
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
// ClientSafeError — developer opted in, expose to client
|
|
787
|
+
if (__isClientSafeErrorLike(err)) {
|
|
788
|
+
return secureResponse(
|
|
789
|
+
JSON.stringify({ error: err.message, data: err.data }),
|
|
790
|
+
{ status: err.statusCode, headers: { "Content-Type": "application/json" } },
|
|
791
|
+
);
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
// Default: sanitize — generic message with correlation hash
|
|
795
|
+
const ref = await __errorRef(err);
|
|
796
|
+
console.error("[catmint] Error reference [ref: " + ref + "] — see above for full error");
|
|
797
|
+
return secureResponse(
|
|
798
|
+
JSON.stringify({ error: "Internal Server Error [ref: " + ref + "]" }),
|
|
799
|
+
{ status: 500, headers: { "Content-Type": "application/json" } },
|
|
800
|
+
);
|
|
429
801
|
}
|
|
430
|
-
return new Response(
|
|
431
|
-
JSON.stringify({ error: "Server function not found" }),
|
|
432
|
-
{ status: 404, headers: { "Content-Type": "application/json" } },
|
|
433
|
-
);
|
|
434
802
|
}
|
|
435
803
|
|
|
436
|
-
//
|
|
804
|
+
// 3. RSC flight stream for client-side navigation (/__catmint/rsc?path=...)
|
|
437
805
|
if (pathname === "/__catmint/rsc" && method === "GET" && rscEntry.render) {
|
|
438
806
|
const targetPath = url.searchParams.get("path");
|
|
439
807
|
if (!targetPath) {
|
|
440
|
-
return
|
|
808
|
+
return secureResponse(
|
|
441
809
|
JSON.stringify({ error: "Missing ?path= parameter" }),
|
|
442
810
|
{ status: 400, headers: { "Content-Type": "application/json" } },
|
|
443
811
|
);
|
|
@@ -445,54 +813,68 @@ export default async function handler(request) {
|
|
|
445
813
|
try {
|
|
446
814
|
const rscResult = await rscEntry.render(targetPath);
|
|
447
815
|
if (rscResult) {
|
|
448
|
-
return
|
|
816
|
+
return applyMiddlewareHeaders(secureResponse(rscResult.stream, {
|
|
449
817
|
status: 200,
|
|
450
818
|
headers: {
|
|
451
819
|
"Content-Type": "text/x-component; charset=utf-8",
|
|
452
820
|
"Cache-Control": "no-cache, no-store, must-revalidate",
|
|
453
821
|
},
|
|
454
|
-
});
|
|
822
|
+
}));
|
|
455
823
|
}
|
|
456
|
-
return
|
|
824
|
+
return secureResponse(
|
|
457
825
|
JSON.stringify({ error: "No matching route" }),
|
|
458
826
|
{ status: 404, headers: { "Content-Type": "application/json" } },
|
|
459
827
|
);
|
|
460
828
|
} catch (err) {
|
|
461
829
|
console.error("RSC navigation error:", err);
|
|
462
|
-
return
|
|
830
|
+
return secureResponse(
|
|
463
831
|
JSON.stringify({ error: "RSC navigation error" }),
|
|
464
832
|
{ status: 500, headers: { "Content-Type": "application/json" } },
|
|
465
833
|
);
|
|
466
834
|
}
|
|
467
835
|
}
|
|
468
836
|
|
|
469
|
-
//
|
|
837
|
+
// 4. API endpoint handling
|
|
470
838
|
if (ssrEntry.hasEndpoint && ssrEntry.hasEndpoint(pathname)) {
|
|
471
839
|
const result = await ssrEntry.handleEndpoint(pathname, method, request);
|
|
472
840
|
|
|
473
841
|
if (result) {
|
|
474
|
-
return result.response;
|
|
842
|
+
return applyMiddlewareHeaders(result.response);
|
|
475
843
|
}
|
|
476
844
|
|
|
477
|
-
return
|
|
845
|
+
return secureResponse(\`Method \${method} not allowed\`, {
|
|
478
846
|
status: 405,
|
|
479
847
|
headers: { "Content-Type": "text/plain" },
|
|
480
848
|
});
|
|
481
849
|
}
|
|
482
850
|
|
|
483
|
-
//
|
|
851
|
+
// 5. Pre-rendered pages WITH middleware: serve from inlined prerendered map.
|
|
852
|
+
if (method === "GET" && typeof prerenderedPages !== "undefined") {
|
|
853
|
+
const prHtml = prerenderedPages[pathname];
|
|
854
|
+
if (prHtml) {
|
|
855
|
+
return applyMiddlewareHeaders(secureResponse(prHtml, {
|
|
856
|
+
status: 200,
|
|
857
|
+
headers: {
|
|
858
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
859
|
+
"Cache-Control": "public, max-age=0, must-revalidate",
|
|
860
|
+
},
|
|
861
|
+
}));
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
// 6. RSC → SSR page rendering pipeline
|
|
484
866
|
if (method === "GET" && rscEntry.render) {
|
|
485
867
|
const rscResult = await rscEntry.render(pathname);
|
|
486
868
|
if (rscResult) {
|
|
487
869
|
const htmlStream = await ssrEntry.renderToHtml(rscResult.stream, rscResult.headConfig);
|
|
488
|
-
return
|
|
870
|
+
return applyMiddlewareHeaders(secureResponse(htmlStream, {
|
|
489
871
|
status: 200,
|
|
490
872
|
headers: { "Content-Type": "text/html; charset=utf-8" },
|
|
491
|
-
});
|
|
873
|
+
}));
|
|
492
874
|
}
|
|
493
875
|
}
|
|
494
876
|
|
|
495
|
-
//
|
|
877
|
+
// 7. Fallback 404
|
|
496
878
|
return await statusPageResponse(404, pathname);
|
|
497
879
|
} catch (err) {
|
|
498
880
|
console.error("Edge function error:", err);
|
package/dist/function-gen.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"function-gen.js","sourceRoot":"","sources":["../src/function-gen.ts"],"names":[],"mappings":"AAAA,kEAAkE;AA2BlE;;GAEG;AACH,SAAS,gBAAgB,CAAC,QAAqB;IAC7C,MAAM,WAAW,GAA6B,EAAE,CAAC;IACjD,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;QACpC,IAAI,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC;YACtB,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;gBACnC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;oBACtB,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;gBACxB,CAAC;gBACD,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACpC,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,yBAAyB,CAAC,QAAqB;IACtD,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,EAAE,YAAY,EAAE,WAAW,CAAC;IAC9D,MAAM,eAAe,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAE7D,IAAI,CAAC,WAAW,IAAI,CAAC,eAAe,EAAE,CAAC;QACrC,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,WAAW,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC/C,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAE7D,OAAO;;;;yBAIgB,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC;0BAC1B,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoCxC,CAAC;AACF,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAC9B,OAA0B,EAC1B,OAAkB;IAElB,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QACvB,MAAM,MAAM,GAAiB;YAC3B,OAAO,EAAE,MAAM;YACf,UAAU,EAAE,YAAY;SACzB,CAAC;QACF,IAAI,OAAO,EAAE,MAAM,EAAE,CAAC;YACpB,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;QAC3B,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,MAAM,GAAmB;QAC7B,OAAO,EAAE,YAAY;QACrB,OAAO,EAAE,YAAY;QACrB,YAAY,EAAE,QAAQ;KACvB,CAAC;IACF,IAAI,OAAO,EAAE,MAAM,EAAE,CAAC;QACpB,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;IAC3B,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,0BAA0B,CACxC,QAAqB,EACrB,OAA0B;
|
|
1
|
+
{"version":3,"file":"function-gen.js","sourceRoot":"","sources":["../src/function-gen.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,13 @@ export interface VercelAdapterOptions {
|
|
|
7
7
|
runtime?: "nodejs" | "edge";
|
|
8
8
|
/** Vercel regions to deploy to */
|
|
9
9
|
regions?: string[];
|
|
10
|
+
/**
|
|
11
|
+
* Maximum allowed request body size in bytes.
|
|
12
|
+
* Applies to server function RPC calls and API endpoints.
|
|
13
|
+
*
|
|
14
|
+
* @default 1_048_576 (1 MB)
|
|
15
|
+
*/
|
|
16
|
+
maxBodySize?: number;
|
|
10
17
|
}
|
|
11
18
|
/**
|
|
12
19
|
* Create a Vercel adapter for Catmint.
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,cAAc,EAGf,MAAM,gBAAgB,CAAC;AAmExB;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,0DAA0D;IAC1D,OAAO,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC5B,kCAAkC;IAClC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,OAAO,UAAU,aAAa,CACnC,OAAO,CAAC,EAAE,oBAAoB,GAC7B,cAAc,CA6MhB"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,52 @@
|
|
|
1
1
|
// @catmint/adapter-vercel — Vercel deployment adapter
|
|
2
|
-
import { join } from "node:path";
|
|
2
|
+
import { join, relative } from "node:path";
|
|
3
|
+
import { readFileSync, readdirSync, statSync, existsSync } from "node:fs";
|
|
3
4
|
import { generateVercelConfig } from "./config-gen.js";
|
|
4
5
|
import { generateServerlessFunction, generateVcConfig, } from "./function-gen.js";
|
|
6
|
+
/**
|
|
7
|
+
* Generate a JS module that exports a map of pathname → HTML string
|
|
8
|
+
* for prerendered pages. Used by edge runtimes that cannot read from
|
|
9
|
+
* the filesystem at runtime.
|
|
10
|
+
*/
|
|
11
|
+
function generatePrerenderedModule(prerenderedDir) {
|
|
12
|
+
const entries = [];
|
|
13
|
+
function walk(dir) {
|
|
14
|
+
if (!existsSync(dir))
|
|
15
|
+
return;
|
|
16
|
+
for (const entry of readdirSync(dir)) {
|
|
17
|
+
const fullPath = join(dir, entry);
|
|
18
|
+
const stat = statSync(fullPath);
|
|
19
|
+
if (stat.isDirectory()) {
|
|
20
|
+
walk(fullPath);
|
|
21
|
+
}
|
|
22
|
+
else if (entry.endsWith(".html")) {
|
|
23
|
+
const relPath = relative(prerenderedDir, fullPath);
|
|
24
|
+
let pathname = "/" + relPath.replace(/\\/g, "/");
|
|
25
|
+
if (pathname.endsWith("/index.html")) {
|
|
26
|
+
pathname = pathname.slice(0, -"/index.html".length) || "/";
|
|
27
|
+
}
|
|
28
|
+
else if (pathname.endsWith(".html")) {
|
|
29
|
+
pathname = pathname.slice(0, -".html".length);
|
|
30
|
+
}
|
|
31
|
+
const html = readFileSync(fullPath, "utf-8");
|
|
32
|
+
entries.push({ pathname, html });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
walk(prerenderedDir);
|
|
37
|
+
if (entries.length === 0) {
|
|
38
|
+
return `// No prerendered pages\nexport const prerenderedPages = {};\n`;
|
|
39
|
+
}
|
|
40
|
+
const lines = [
|
|
41
|
+
"// Auto-generated prerendered page map — do not edit",
|
|
42
|
+
"export const prerenderedPages = {",
|
|
43
|
+
];
|
|
44
|
+
for (const { pathname, html } of entries) {
|
|
45
|
+
lines.push(` ${JSON.stringify(pathname)}: ${JSON.stringify(html)},`);
|
|
46
|
+
}
|
|
47
|
+
lines.push("};");
|
|
48
|
+
return lines.join("\n") + "\n";
|
|
49
|
+
}
|
|
5
50
|
/**
|
|
6
51
|
* Create a Vercel adapter for Catmint.
|
|
7
52
|
*
|
|
@@ -20,6 +65,7 @@ import { generateServerlessFunction, generateVcConfig, } from "./function-gen.js
|
|
|
20
65
|
export default function vercelAdapter(options) {
|
|
21
66
|
const runtime = options?.runtime ?? "nodejs";
|
|
22
67
|
const regions = options?.regions;
|
|
68
|
+
const maxBodySize = options?.maxBodySize ?? 1_048_576;
|
|
23
69
|
return {
|
|
24
70
|
name: "@catmint/adapter-vercel",
|
|
25
71
|
async adapt(context) {
|
|
@@ -39,6 +85,8 @@ export default function vercelAdapter(options) {
|
|
|
39
85
|
await context.copyDir(context.clientDir, staticOutputDir);
|
|
40
86
|
context.log("@catmint/adapter-vercel: Copied client assets to static/");
|
|
41
87
|
// 3. Copy pre-rendered static pages to static/
|
|
88
|
+
// NOTE: Middleware-protected static pages are NOT copied here — they
|
|
89
|
+
// are served through the serverless function after middleware runs.
|
|
42
90
|
await context.copyDir(context.staticDir, staticOutputDir);
|
|
43
91
|
context.log("@catmint/adapter-vercel: Copied pre-rendered pages to static/");
|
|
44
92
|
// 4. Generate serverless function (only if not frontend-only mode)
|
|
@@ -52,10 +100,25 @@ export default function vercelAdapter(options) {
|
|
|
52
100
|
// import both without filename conflicts.
|
|
53
101
|
await context.copyDir(context.serverDir, join(funcDir, "ssr"));
|
|
54
102
|
await context.copyDir(rscDir, join(funcDir, "rsc"));
|
|
103
|
+
// If there are prerendered pages with middleware, handle them based
|
|
104
|
+
// on the runtime:
|
|
105
|
+
// - Node.js: copy files to function dir (served via filesystem reads)
|
|
106
|
+
// - Edge: generate a JS module with inlined HTML (no fs access at runtime)
|
|
107
|
+
if (context.prerenderedDir && existsSync(context.prerenderedDir)) {
|
|
108
|
+
if (runtime === "edge") {
|
|
109
|
+
const prerenderedModule = generatePrerenderedModule(context.prerenderedDir);
|
|
110
|
+
await context.writeFile(join(funcDir, "prerendered.js"), prerenderedModule);
|
|
111
|
+
context.log("@catmint/adapter-vercel: Generated prerendered.js module (middleware-protected, edge)");
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
await context.copyDir(context.prerenderedDir, join(funcDir, "prerendered"));
|
|
115
|
+
context.log("@catmint/adapter-vercel: Copied prerendered HTML to function (middleware-protected)");
|
|
116
|
+
}
|
|
117
|
+
}
|
|
55
118
|
// Generate the serverless function entry as handler.js.
|
|
56
119
|
// This imports from ./ssr/index.js and ./rsc/index.js and wraps
|
|
57
120
|
// them with the Vercel serverless function handler signature.
|
|
58
|
-
const functionEntry = generateServerlessFunction(manifest, runtime);
|
|
121
|
+
const functionEntry = generateServerlessFunction(manifest, runtime, maxBodySize, manifest.config.security.headerPreset);
|
|
59
122
|
await context.writeFile(join(funcDir, "handler.js"), functionEntry);
|
|
60
123
|
// Add package.json with "type": "module" so Node.js treats .js as ESM.
|
|
61
124
|
// The function directory is isolated from the project root, so without
|
|
@@ -81,6 +144,15 @@ export default function vercelAdapter(options) {
|
|
|
81
144
|
// The route function re-uses the same serverless entry and server bundle
|
|
82
145
|
await context.copyDir(context.serverDir, join(routeFuncDir, "ssr"));
|
|
83
146
|
await context.copyDir(rscDir, join(routeFuncDir, "rsc"));
|
|
147
|
+
if (context.prerenderedDir && existsSync(context.prerenderedDir)) {
|
|
148
|
+
if (runtime === "edge") {
|
|
149
|
+
const prerenderedModule = generatePrerenderedModule(context.prerenderedDir);
|
|
150
|
+
await context.writeFile(join(routeFuncDir, "prerendered.js"), prerenderedModule);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
await context.copyDir(context.prerenderedDir, join(routeFuncDir, "prerendered"));
|
|
154
|
+
}
|
|
155
|
+
}
|
|
84
156
|
await context.writeFile(join(routeFuncDir, "handler.js"), functionEntry);
|
|
85
157
|
await context.writeFile(join(routeFuncDir, "package.json"), JSON.stringify({ type: "module" }, null, 2));
|
|
86
158
|
await context.writeFile(join(routeFuncDir, ".vc-config.json"), JSON.stringify(vcConfig, null, 2));
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,sDAAsD;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,sDAAsD;AAOtD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC1E,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EACL,0BAA0B,EAC1B,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAE3B;;;;GAIG;AACH,SAAS,yBAAyB,CAAC,cAAsB;IACvD,MAAM,OAAO,GAA8C,EAAE,CAAC;IAE9D,SAAS,IAAI,CAAC,GAAW;QACvB,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,OAAO;QAC7B,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;YACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YAClC,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAChC,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;gBACvB,IAAI,CAAC,QAAQ,CAAC,CAAC;YACjB,CAAC;iBAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBACnC,MAAM,OAAO,GAAG,QAAQ,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;gBACnD,IAAI,QAAQ,GAAG,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;gBACjD,IAAI,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;oBACrC,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC;gBAC7D,CAAC;qBAAM,IAAI,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;oBACtC,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAChD,CAAC;gBACD,MAAM,IAAI,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBAC7C,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;YACnC,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,CAAC,cAAc,CAAC,CAAC;IAErB,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,gEAAgE,CAAC;IAC1E,CAAC;IAED,MAAM,KAAK,GAAG;QACZ,sDAAsD;QACtD,mCAAmC;KACpC,CAAC;IACF,KAAK,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,OAAO,EAAE,CAAC;QACzC,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxE,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AACjC,CAAC;AA+BD;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,OAAO,UAAU,aAAa,CACnC,OAA8B;IAE9B,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,QAAQ,CAAC;IAC7C,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,CAAC;IACjC,MAAM,WAAW,GAAG,OAAO,EAAE,WAAW,IAAI,SAAS,CAAC;IAEtD,OAAO;QACL,IAAI,EAAE,yBAAyB;QAC/B,KAAK,CAAC,KAAK,CAAC,OAAuB;YACjC,OAAO,CAAC,GAAG,CACT,mEAAmE,CACpE,CAAC;YAEF,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAuB,CAAC;YAEjD,sCAAsC;YACtC,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;gBACvB,yBAAyB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAC/C,CAAC;YAED,MAAM,SAAS,GAAG,IAAI,CACpB,OAAO,CAAC,SAAS,EACjB,IAAI,EACJ,IAAI,EACJ,SAAS,EACT,QAAQ,CACT,CAAC;YAEF,0BAA0B;YAC1B,MAAM,UAAU,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;YAClD,MAAM,OAAO,CAAC,SAAS,CACrB,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,EAC9B,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CACpC,CAAC;YACF,OAAO,CAAC,GAAG,CACT,+DAA+D,CAChE,CAAC;YAEF,mCAAmC;YACnC,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;YAClD,MAAM,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;YAC1D,OAAO,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC;YAExE,+CAA+C;YAC/C,qEAAqE;YACrE,oEAAoE;YACpE,MAAM,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;YAC1D,OAAO,CAAC,GAAG,CACT,+DAA+D,CAChE,CAAC;YAEF,mEAAmE;YACnE,IAAI,QAAQ,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBACjC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC;gBAE3D,4DAA4D;gBAC5D,qEAAqE;gBACrE,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;gBAEpD,kEAAkE;gBAClE,iEAAiE;gBACjE,0CAA0C;gBAC1C,MAAM,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;gBAC/D,MAAM,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;gBAEpD,oEAAoE;gBACpE,kBAAkB;gBAClB,sEAAsE;gBACtE,2EAA2E;gBAC3E,IAAI,OAAO,CAAC,cAAc,IAAI,UAAU,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;oBACjE,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;wBACvB,MAAM,iBAAiB,GAAG,yBAAyB,CACjD,OAAO,CAAC,cAAc,CACvB,CAAC;wBACF,MAAM,OAAO,CAAC,SAAS,CACrB,IAAI,CAAC,OAAO,EAAE,gBAAgB,CAAC,EAC/B,iBAAiB,CAClB,CAAC;wBACF,OAAO,CAAC,GAAG,CACT,uFAAuF,CACxF,CAAC;oBACJ,CAAC;yBAAM,CAAC;wBACN,MAAM,OAAO,CAAC,OAAO,CACnB,OAAO,CAAC,cAAc,EACtB,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,CAC7B,CAAC;wBACF,OAAO,CAAC,GAAG,CACT,qFAAqF,CACtF,CAAC;oBACJ,CAAC;gBACH,CAAC;gBAED,wDAAwD;gBACxD,gEAAgE;gBAChE,8DAA8D;gBAC9D,MAAM,aAAa,GAAG,0BAA0B,CAC9C,QAAQ,EACR,OAAO,EACP,WAAW,EACX,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CACtC,CAAC;gBACF,MAAM,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,EAAE,aAAa,CAAC,CAAC;gBAEpE,uEAAuE;gBACvE,uEAAuE;gBACvE,oEAAoE;gBACpE,MAAM,OAAO,CAAC,SAAS,CACrB,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,EAC7B,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAC5C,CAAC;gBAEF,2BAA2B;gBAC3B,MAAM,QAAQ,GAAG,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBACpD,MAAM,OAAO,CAAC,SAAS,CACrB,IAAI,CAAC,OAAO,EAAE,iBAAiB,CAAC,EAChC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAClC,CAAC;gBAEF,OAAO,CAAC,GAAG,CACT,iFAAiF,CAClF,CAAC;gBAEF,gDAAgD;gBAChD,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,EAAE,YAAY,EAAE,WAAW,CAAC;gBAC9D,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;gBAE5D,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,IAAI,WAAW,EAAE,CAAC;oBAC3C,KAAK,MAAM,KAAK,IAAI,YAAY,EAAE,CAAC;wBACjC,wDAAwD;wBACxD,2DAA2D;wBAC3D,MAAM,SAAS,GACb,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;wBAE/D,2DAA2D;wBAC3D,IAAI,SAAS,KAAK,OAAO;4BAAE,SAAS;wBAEpC,+CAA+C;wBAC/C,MAAM,YAAY,GAAG,IAAI,CACvB,SAAS,EACT,WAAW,EACX,GAAG,SAAS,OAAO,CACpB,CAAC;wBAEF,yEAAyE;wBACzE,MAAM,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC,CAAC;wBACpE,MAAM,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC,CAAC;wBACzD,IAAI,OAAO,CAAC,cAAc,IAAI,UAAU,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;4BACjE,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;gCACvB,MAAM,iBAAiB,GAAG,yBAAyB,CACjD,OAAO,CAAC,cAAc,CACvB,CAAC;gCACF,MAAM,OAAO,CAAC,SAAS,CACrB,IAAI,CAAC,YAAY,EAAE,gBAAgB,CAAC,EACpC,iBAAiB,CAClB,CAAC;4BACJ,CAAC;iCAAM,CAAC;gCACN,MAAM,OAAO,CAAC,OAAO,CACnB,OAAO,CAAC,cAAc,EACtB,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,CAClC,CAAC;4BACJ,CAAC;wBACH,CAAC;wBACD,MAAM,OAAO,CAAC,SAAS,CACrB,IAAI,CAAC,YAAY,EAAE,YAAY,CAAC,EAChC,aAAa,CACd,CAAC;wBACF,MAAM,OAAO,CAAC,SAAS,CACrB,IAAI,CAAC,YAAY,EAAE,cAAc,CAAC,EAClC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAC5C,CAAC;wBACF,MAAM,OAAO,CAAC,SAAS,CACrB,IAAI,CAAC,YAAY,EAAE,iBAAiB,CAAC,EACrC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAClC,CAAC;wBAEF,4BAA4B;wBAC5B,MAAM,eAAe,GAAoB;4BACvC,UAAU,EAAE,KAAK,CAAC,KAAK,EAAE,UAAU,IAAI,KAAK;4BAC5C,WAAW;yBACZ,CAAC;wBAEF,MAAM,OAAO,CAAC,SAAS,CACrB,IAAI,CACF,SAAS,EACT,WAAW,EACX,GAAG,SAAS,wBAAwB,CACrC,EACD,IAAI,CAAC,SAAS,CAAC,eAAe,EAAE,IAAI,EAAE,CAAC,CAAC,CACzC,CAAC;wBAEF,OAAO,CAAC,GAAG,CACT,mDAAmD,KAAK,CAAC,IAAI,UAAU,KAAK,CAAC,KAAK,EAAE,UAAU,IAAI,MAAM,IAAI,CAC7G,CAAC;oBACJ,CAAC;oBAED,OAAO,CAAC,GAAG,CACT,oCAAoC,YAAY,CAAC,MAAM,wBAAwB,CAChF,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,OAAO,CAAC,GAAG,CACT,gEAAgE,CACjE,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAS,yBAAyB,CAChC,QAAqB,EACrB,OAAuB;IAEvB,gDAAgD;IAChD,IAAI,QAAQ,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxC,OAAO,CAAC,GAAG,CACT,kFAAkF;YAChF,qFAAqF,CACxF,CAAC;IACJ,CAAC;IAED,MAAM,kBAAkB,GAAG;QACzB,OAAO;QACP,IAAI;QACJ,eAAe;QACf,SAAS;QACT,OAAO;QACP,KAAK;QACL,KAAK;QACL,KAAK;KACN,CAAC;IACF,KAAK,MAAM,EAAE,IAAI,QAAQ,CAAC,eAAe,EAAE,CAAC;QAC1C,KAAK,MAAM,SAAS,IAAI,kBAAkB,EAAE,CAAC;YAC3C,IAAI,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;gBAClC,OAAO,CAAC,GAAG,CACT,uDAAuD,EAAE,CAAC,IAAI,gBAAgB;oBAC5E,aAAa,SAAS,kDAAkD,CAC3E,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@catmint/adapter-vercel",
|
|
3
|
-
"version": "0.0.0-prealpha.
|
|
3
|
+
"version": "0.0.0-prealpha.11",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"private": false,
|
|
6
6
|
"license": "MIT",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
}
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"catmint": "0.0.0-prealpha.
|
|
17
|
+
"catmint": "0.0.0-prealpha.11"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|
|
20
20
|
"typescript": "^5.7.0"
|