@easel-sh/cli 0.1.0-alpha.0 → 0.1.0-alpha.10

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.
Files changed (37) hide show
  1. package/dist/cli.js +9 -4
  2. package/dist/cli.js.map +1 -1
  3. package/dist/commands/create-lambda-gateway.d.ts.map +1 -1
  4. package/dist/commands/create-lambda-gateway.js +3 -181
  5. package/dist/commands/create-lambda-gateway.js.map +1 -1
  6. package/dist/commands/generate-manifest.d.ts.map +1 -1
  7. package/dist/commands/generate-manifest.js +14 -1
  8. package/dist/commands/generate-manifest.js.map +1 -1
  9. package/dist/commands/package-functions.d.ts.map +1 -1
  10. package/dist/commands/package-functions.js +73 -202
  11. package/dist/commands/package-functions.js.map +1 -1
  12. package/dist/commands/upload-manifest.d.ts.map +1 -1
  13. package/dist/commands/upload-manifest.js +1 -1
  14. package/dist/commands/upload-manifest.js.map +1 -1
  15. package/dist/commands/upload-static.d.ts +2 -0
  16. package/dist/commands/upload-static.d.ts.map +1 -1
  17. package/dist/commands/upload-static.js +49 -21
  18. package/dist/commands/upload-static.js.map +1 -1
  19. package/dist/handler-wrapper.d.ts +8 -0
  20. package/dist/handler-wrapper.d.ts.map +1 -0
  21. package/dist/handler-wrapper.js +288 -0
  22. package/dist/handler-wrapper.js.map +1 -0
  23. package/dist/handler-wrapper.test.d.ts +2 -0
  24. package/dist/handler-wrapper.test.d.ts.map +1 -0
  25. package/dist/handler-wrapper.test.js +53 -0
  26. package/dist/handler-wrapper.test.js.map +1 -0
  27. package/dist/utils/types.d.ts +30 -0
  28. package/dist/utils/types.d.ts.map +1 -1
  29. package/dist/utils/vercel-config.d.ts +7 -1
  30. package/dist/utils/vercel-config.d.ts.map +1 -1
  31. package/dist/utils/vercel-config.js +19 -0
  32. package/dist/utils/vercel-config.js.map +1 -1
  33. package/dist/utils.d.ts +4 -1
  34. package/dist/utils.d.ts.map +1 -1
  35. package/dist/utils.js +65 -10
  36. package/dist/utils.js.map +1 -1
  37. package/package.json +5 -3
@@ -0,0 +1,288 @@
1
+ /**
2
+ * Handler wrapper compatible with Vercel Node.js runtime:
3
+ * - Fetch Web Standard: export default { fetch(request) { return new Response(...); } };
4
+ * - HTTP method exports: export function GET(request) { return new Response(...); }
5
+ * - Node-style: export default (req, res) => { ... } with Vercel-like helpers (query, cookies, body, status, send, json, redirect).
6
+ */
7
+ export function generateHandlerWrapper(handlerFile) {
8
+ const handlerPath = JSON.stringify("./" + handlerFile.replace(/\\/g, "/"));
9
+ return `/* eslint-disable @typescript-eslint/no-require-imports */
10
+
11
+ const { Readable } = require("stream");
12
+ const { EventEmitter } = require("events");
13
+
14
+ const HTTP_METHODS = ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS", "HEAD"];
15
+
16
+ let userModulePromise = null;
17
+ function getModule() {
18
+ if (!userModulePromise) {
19
+ userModulePromise = import(${handlerPath}).then(function (m) { return m || {}; });
20
+ }
21
+ return userModulePromise;
22
+ }
23
+
24
+ function normalizeStatus(status) {
25
+ // Valid HTTP status is 100-599. Response.status can be 0 for error/opaque (Fetch API).
26
+ if (typeof status === "number" && status >= 100 && status < 600) return status;
27
+ if (status === 0) return 502; // error/opaque response
28
+ return 200;
29
+ }
30
+
31
+ async function responseToLambda(response) {
32
+ const responseHeaders = {};
33
+ response.headers.forEach((value, key) => {
34
+ responseHeaders[key.toLowerCase()] = value;
35
+ });
36
+ const body = await response.text();
37
+ return {
38
+ statusCode: normalizeStatus(response.status),
39
+ headers: responseHeaders,
40
+ body: body,
41
+ };
42
+ }
43
+
44
+ module.exports.handler = async (event, _context) => {
45
+ const mod = await getModule();
46
+ const handler = mod.default !== undefined ? mod.default : mod;
47
+
48
+ const isV2 = event.requestContext && event.requestContext.http;
49
+ const method = isV2 ? event.requestContext.http.method : event.httpMethod || "GET";
50
+
51
+ const normalizedHeaders = {};
52
+ if (event.headers) {
53
+ Object.entries(event.headers).forEach(([key, value]) => {
54
+ normalizedHeaders[key.toLowerCase()] = value;
55
+ });
56
+ }
57
+
58
+ const queryParams = { ...(event.queryStringParameters || {}) };
59
+ // Prefer original client path from router when present so Lambda sees the same URL the client requested (event.rawPath may be wrong if event was built by API Gateway or an older gateway)
60
+ const originalPath = normalizedHeaders["x-router-original-path"];
61
+ const pathFromEvent = isV2 ? event.rawPath || event.path || "/" : event.path || "/";
62
+ const path = (originalPath && originalPath.trim())
63
+ ? (originalPath.trim().startsWith("/") ? originalPath.trim() : "/" + originalPath.trim())
64
+ : pathFromEvent;
65
+ const host = event.headers?.host || event.headers?.["host"] || "localhost";
66
+ const url = new URL(path, "http://" + host);
67
+ Object.entries(queryParams).forEach(([key, value]) => {
68
+ url.searchParams.set(key, value);
69
+ });
70
+
71
+ let bodyBuffer = null;
72
+ if (event.body) {
73
+ bodyBuffer = event.isBase64Encoded
74
+ ? Buffer.from(event.body, "base64")
75
+ : Buffer.from(event.body, "utf8");
76
+ }
77
+
78
+ const requestUrl = "http://" + host + url.pathname + url.search;
79
+ const webRequest = new Request(requestUrl, {
80
+ method: method,
81
+ headers: normalizedHeaders,
82
+ body: bodyBuffer && bodyBuffer.length > 0 ? bodyBuffer : undefined,
83
+ });
84
+
85
+ const requestDetails = {
86
+ method: method,
87
+ url: requestUrl,
88
+ path: url.pathname,
89
+ query: queryParams,
90
+ headers: normalizedHeaders,
91
+ bodyLength: bodyBuffer ? bodyBuffer.length : 0,
92
+ };
93
+ console.log("[handler] reconstructed request:", JSON.stringify(requestDetails));
94
+
95
+ // Vercel: named method export (e.g. export function GET(request) { ... })
96
+ if (HTTP_METHODS.includes(method) && typeof mod[method] === "function") {
97
+ const response = await Promise.resolve(mod[method](webRequest));
98
+ return responseToLambda(response);
99
+ }
100
+
101
+ // Vercel/Nitro: default export with fetch(request)
102
+ if (handler && typeof handler.fetch === "function") {
103
+ const response = await handler.fetch(webRequest, _context);
104
+ return responseToLambda(response);
105
+ }
106
+
107
+ // Node-style: default export as function (req, res), with Vercel-like helpers
108
+ if (typeof handler !== "function") {
109
+ throw new TypeError(
110
+ "Handler must export a function (req, res), an object with fetch(request), or named GET/POST/etc. Got: " + typeof handler
111
+ );
112
+ }
113
+
114
+ return new Promise((resolve, reject) => {
115
+ let _bodyParsed = undefined;
116
+ function getParsedBody() {
117
+ if (_bodyParsed !== undefined) return _bodyParsed;
118
+ if (!bodyBuffer || bodyBuffer.length === 0) {
119
+ _bodyParsed = undefined;
120
+ return _bodyParsed;
121
+ }
122
+ const ct = (normalizedHeaders["content-type"] || "").toLowerCase();
123
+ const text = bodyBuffer.toString("utf8");
124
+ try {
125
+ if (ct.includes("application/json")) _bodyParsed = JSON.parse(text);
126
+ else if (ct.includes("application/x-www-form-urlencoded")) {
127
+ _bodyParsed = Object.fromEntries(new URLSearchParams(text));
128
+ }
129
+ else if (ct.includes("text/plain")) _bodyParsed = text;
130
+ else if (ct.includes("application/octet-stream")) _bodyParsed = bodyBuffer;
131
+ else _bodyParsed = undefined;
132
+ } catch (e) {
133
+ if (ct.includes("application/json")) throw e;
134
+ _bodyParsed = undefined;
135
+ }
136
+ return _bodyParsed;
137
+ }
138
+
139
+ let cookiesObj = undefined;
140
+ function getCookies() {
141
+ if (cookiesObj !== undefined) return cookiesObj;
142
+ cookiesObj = {};
143
+ const cookieHeader = normalizedHeaders["cookie"];
144
+ if (cookieHeader) {
145
+ cookieHeader.split(";").forEach(function (part) {
146
+ const eq = part.indexOf("=");
147
+ if (eq > 0) {
148
+ const key = part.slice(0, eq).trim();
149
+ const val = part.slice(eq + 1).trim();
150
+ cookiesObj[key] = val;
151
+ }
152
+ });
153
+ }
154
+ return cookiesObj;
155
+ }
156
+
157
+ const req = Object.assign(
158
+ new Readable({
159
+ read() {
160
+ if (bodyBuffer) this.push(bodyBuffer);
161
+ this.push(null);
162
+ },
163
+ }),
164
+ {
165
+ method: method,
166
+ url: url.pathname + url.search,
167
+ headers: normalizedHeaders,
168
+ query: queryParams,
169
+ }
170
+ );
171
+ Object.defineProperty(req, "body", {
172
+ get: getParsedBody,
173
+ set: function (val) { _bodyParsed = val; },
174
+ enumerable: true,
175
+ configurable: true,
176
+ });
177
+ Object.defineProperty(req, "cookies", {
178
+ get: getCookies,
179
+ set: function (val) { cookiesObj = val; },
180
+ enumerable: true,
181
+ configurable: true,
182
+ });
183
+
184
+ let statusCode = 200;
185
+ const headers = {};
186
+ let body = "";
187
+ let headersSent = false;
188
+ let resolved = false;
189
+
190
+ function finishRes() {
191
+ if (resolved) return;
192
+ resolved = true;
193
+ const out = {};
194
+ Object.entries(headers).forEach(([k, v]) => {
195
+ out[k] = Array.isArray(v) ? v.join(", ") : v;
196
+ });
197
+ resolve({ statusCode: statusCode || 200, headers: out, body: body });
198
+ }
199
+
200
+ const res = Object.assign(new EventEmitter(), {
201
+ setHeader: (key, value) => {
202
+ if (!headersSent) headers[key.toLowerCase()] = value;
203
+ },
204
+ getHeader: (key) => headers[key.toLowerCase()],
205
+ removeHeader: (key) => { delete headers[key.toLowerCase()]; },
206
+ appendHeader: (key, value) => {
207
+ if (!headersSent) {
208
+ const lowerKey = key.toLowerCase();
209
+ const existing = headers[lowerKey];
210
+ headers[lowerKey] = existing
211
+ ? (Array.isArray(existing) ? existing.concat(value) : [existing, value])
212
+ : value;
213
+ }
214
+ },
215
+ hasHeader: (key) => key.toLowerCase() in headers,
216
+ getHeaderNames: () => Object.keys(headers),
217
+ writeHead: (code, responseHeaders) => {
218
+ if (!headersSent) {
219
+ statusCode = code;
220
+ if (responseHeaders) {
221
+ Object.entries(responseHeaders).forEach(([key, value]) => {
222
+ headers[key.toLowerCase()] = value;
223
+ });
224
+ }
225
+ headersSent = true;
226
+ }
227
+ return res;
228
+ },
229
+ write: (chunk) => {
230
+ if (!headersSent) headersSent = true;
231
+ body += chunk.toString();
232
+ return true;
233
+ },
234
+ end: (chunk) => {
235
+ if (chunk) body += chunk.toString();
236
+ finishRes();
237
+ },
238
+ status: (code) => {
239
+ statusCode = code;
240
+ return res;
241
+ },
242
+ send: (val) => {
243
+ if (typeof val === "object" && val !== null && !Buffer.isBuffer(val)) {
244
+ if (!headers["content-type"]) headers["content-type"] = "application/json";
245
+ body = JSON.stringify(val);
246
+ } else {
247
+ body = val == null ? "" : String(val);
248
+ }
249
+ finishRes();
250
+ return res;
251
+ },
252
+ json: (obj) => {
253
+ headers["content-type"] = "application/json";
254
+ body = JSON.stringify(obj);
255
+ finishRes();
256
+ return res;
257
+ },
258
+ redirect: (a, b) => {
259
+ const code = typeof a === "number" ? a : 307;
260
+ const loc = typeof a === "number" ? b : a;
261
+ statusCode = code;
262
+ headers["location"] = loc;
263
+ finishRes();
264
+ return res;
265
+ },
266
+ headersSent: false,
267
+ });
268
+
269
+ Object.defineProperty(res, "statusCode", {
270
+ get: () => statusCode,
271
+ set: (value) => { statusCode = value; },
272
+ enumerable: true,
273
+ configurable: true,
274
+ });
275
+
276
+ req.on("error", reject);
277
+ res.on("error", reject);
278
+
279
+ try {
280
+ handler(req, res);
281
+ } catch (error) {
282
+ reject(error);
283
+ }
284
+ });
285
+ };
286
+ `;
287
+ }
288
+ //# sourceMappingURL=handler-wrapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler-wrapper.js","sourceRoot":"","sources":["../src/handler-wrapper.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,WAAmB;IACxD,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;IAC3E,OAAO;;;;;;;;;;iCAUwB,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2Q3C,CAAC;AACF,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=handler-wrapper.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler-wrapper.test.d.ts","sourceRoot":"","sources":["../src/handler-wrapper.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,53 @@
1
+ import { createRequire } from "node:module";
2
+ import fs from "node:fs";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
6
+ import { generateHandlerWrapper } from "./handler-wrapper.js";
7
+ describe("handler-wrapper", () => {
8
+ let tmpDir;
9
+ const require = createRequire(import.meta.url);
10
+ beforeEach(() => {
11
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "handler-wrapper-test-"));
12
+ });
13
+ afterEach(() => {
14
+ fs.rmSync(tmpDir, { recursive: true, force: true });
15
+ });
16
+ it("allows assigning to req.cookies without throwing (Node-style handler)", async () => {
17
+ const wrapperCode = generateHandlerWrapper("index.mjs");
18
+ fs.writeFileSync(path.join(tmpDir, "handler.js"), wrapperCode, "utf8");
19
+ fs.writeFileSync(path.join(tmpDir, "index.mjs"), `export default function (req, res) {
20
+ req.cookies = {};
21
+ res.end("ok");
22
+ }`, "utf8");
23
+ const handler = require(path.join(tmpDir, "handler.js")).handler;
24
+ const mockEvent = {
25
+ requestContext: { http: { method: "GET" } },
26
+ headers: { host: "localhost" },
27
+ rawPath: "/",
28
+ };
29
+ const result = await handler(mockEvent, {});
30
+ expect(result).toBeDefined();
31
+ expect(result.statusCode).toBe(200);
32
+ expect(result.body).toBe("ok");
33
+ });
34
+ it("allows assigning to req.body without throwing (Node-style handler)", async () => {
35
+ const wrapperCode = generateHandlerWrapper("index.mjs");
36
+ fs.writeFileSync(path.join(tmpDir, "handler.js"), wrapperCode, "utf8");
37
+ fs.writeFileSync(path.join(tmpDir, "index.mjs"), `export default function (req, res) {
38
+ req.body = {};
39
+ res.end("ok");
40
+ }`, "utf8");
41
+ const handler = require(path.join(tmpDir, "handler.js")).handler;
42
+ const mockEvent = {
43
+ requestContext: { http: { method: "GET" } },
44
+ headers: { host: "localhost" },
45
+ rawPath: "/",
46
+ };
47
+ const result = await handler(mockEvent, {});
48
+ expect(result).toBeDefined();
49
+ expect(result.statusCode).toBe(200);
50
+ expect(result.body).toBe("ok");
51
+ });
52
+ });
53
+ //# sourceMappingURL=handler-wrapper.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler-wrapper.test.js","sourceRoot":"","sources":["../src/handler-wrapper.test.ts"],"names":[],"mappings":"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"}
@@ -27,11 +27,41 @@ export interface FileManifestEntry {
27
27
  contentType?: string;
28
28
  }
29
29
  export type FileManifestItem = string | FileManifestEntry;
30
+ /** Build Output API image format */
31
+ export type ImageFormat = "image/avif" | "image/webp";
32
+ /** Remote pattern for image optimization (regex for hostname, pathname, etc.) */
33
+ export interface RemotePattern {
34
+ protocol?: "http" | "https";
35
+ hostname: string;
36
+ port?: string;
37
+ pathname?: string;
38
+ search?: string;
39
+ }
40
+ /** Local pattern for image optimization (regex for pathname, search) */
41
+ export interface LocalPattern {
42
+ pathname?: string;
43
+ search?: string;
44
+ }
45
+ /** Images config from .vercel/output/config.json (Build Output API) */
46
+ export interface ImagesConfig {
47
+ sizes: number[];
48
+ domains: string[];
49
+ remotePatterns?: RemotePattern[];
50
+ localPatterns?: LocalPattern[];
51
+ qualities?: number[];
52
+ minimumCacheTTL?: number;
53
+ formats?: ImageFormat[];
54
+ dangerouslyAllowSVG?: boolean;
55
+ contentSecurityPolicy?: string;
56
+ contentDispositionType?: string;
57
+ }
30
58
  export interface DeploymentManifest {
31
59
  routes: Route[];
32
60
  fileManifest: FileManifestItem[];
33
61
  resourceManifest: string[];
34
62
  resourceHashes?: Record<string, string>;
63
+ fileHashes?: Record<string, string>;
64
+ images?: ImagesConfig;
35
65
  version?: string;
36
66
  createdAt?: string;
37
67
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/utils/types.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,KAAK;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC;IACZ,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC;IAChB,MAAM,CAAC,EAAE;QACP,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAClC,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,QAAQ,CAAC,EAAE;QACT,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,UAAU,CAAC,EAAE,GAAG,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,iBAAiB,CAAC;AAE1D,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,YAAY,EAAE,gBAAgB,EAAE,CAAC;IACjC,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/utils/types.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,KAAK;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC;IACZ,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC;IAChB,MAAM,CAAC,EAAE;QACP,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAClC,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,QAAQ,CAAC,EAAE;QACT,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,UAAU,CAAC,EAAE,GAAG,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,iBAAiB,CAAC;AAE1D,oCAAoC;AACpC,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,YAAY,CAAC;AAEtD,iFAAiF;AACjF,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wEAAwE;AACxE,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,uEAAuE;AACvE,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,cAAc,CAAC,EAAE,aAAa,EAAE,CAAC;IACjC,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;IACxB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,YAAY,EAAE,gBAAgB,EAAE,CAAC;IACjC,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}
@@ -1,4 +1,4 @@
1
- import type { Route } from './types.js';
1
+ import type { Route, ImagesConfig } from "./types.js";
2
2
  export interface FileOverride {
3
3
  path?: string;
4
4
  contentType?: string;
@@ -6,6 +6,7 @@ export interface FileOverride {
6
6
  export interface VercelConfig {
7
7
  routes?: VercelRoute[];
8
8
  overrides?: Record<string, FileOverride>;
9
+ images?: ImagesConfig;
9
10
  [key: string]: any;
10
11
  }
11
12
  export interface VercelRoute {
@@ -53,6 +54,11 @@ export declare function parseOverrides(configPath: string): Record<string, {
53
54
  path?: string;
54
55
  contentType?: string;
55
56
  }>;
57
+ /**
58
+ * Parse images config from config.json (Build Output API).
59
+ * Returns undefined if file missing or images property not defined.
60
+ */
61
+ export declare function parseImagesConfig(configPath: string): ImagesConfig | undefined;
56
62
  /**
57
63
  * Scan static files directory to build file manifest
58
64
  */
@@ -1 +1 @@
1
- {"version":3,"file":"vercel-config.d.ts","sourceRoot":"","sources":["../../src/utils/vercel-config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,WAAW,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACzC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAC3B,OAAO,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAC/B,MAAM,CAAC,EAAE;QACP,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAClC,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,QAAQ,CAAC,EAAE;QACT,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,UAAU,CAAC,EAAE,eAAe,EAAE,CAAC;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,GAAG,CAAC;IACZ,IAAI,CAAC,EAAE,GAAG,CAAC;CACZ;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,KAAK,EAAE,CAa7D;AA0ED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,MAAM,GACjB,MAAM,CAAC,MAAM,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CASzD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CA0B7D"}
1
+ {"version":3,"file":"vercel-config.d.ts","sourceRoot":"","sources":["../../src/utils/vercel-config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEtD,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,WAAW,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACzC,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAC3B,OAAO,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAC/B,MAAM,CAAC,EAAE;QACP,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAClC,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,QAAQ,CAAC,EAAE;QACT,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,UAAU,CAAC,EAAE,eAAe,EAAE,CAAC;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,GAAG,CAAC;IACZ,IAAI,CAAC,EAAE,GAAG,CAAC;CACZ;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,KAAK,EAAE,CAa7D;AA0ED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,MAAM,GACjB,MAAM,CAAC,MAAM,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CASzD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,GACjB,YAAY,GAAG,SAAS,CAkB1B;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CA0B7D"}
@@ -92,6 +92,25 @@ export function parseOverrides(configPath) {
92
92
  const config = JSON.parse(configContent);
93
93
  return config.overrides || {};
94
94
  }
95
+ /**
96
+ * Parse images config from config.json (Build Output API).
97
+ * Returns undefined if file missing or images property not defined.
98
+ */
99
+ export function parseImagesConfig(configPath) {
100
+ if (!fs.existsSync(configPath)) {
101
+ return undefined;
102
+ }
103
+ const configContent = fs.readFileSync(configPath, "utf8");
104
+ const config = JSON.parse(configContent);
105
+ if (!config.images || typeof config.images !== "object") {
106
+ return undefined;
107
+ }
108
+ const img = config.images;
109
+ if (!Array.isArray(img.sizes) || !Array.isArray(img.domains)) {
110
+ return undefined;
111
+ }
112
+ return img;
113
+ }
95
114
  /**
96
115
  * Scan static files directory to build file manifest
97
116
  */
@@ -1 +1 @@
1
- {"version":3,"file":"vercel-config.js","sourceRoot":"","sources":["../../src/utils/vercel-config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"vercel-config.js","sourceRoot":"","sources":["../../src/utils/vercel-config.ts"],"names":[],"mappings":"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"}
package/dist/utils.d.ts CHANGED
@@ -3,7 +3,10 @@
3
3
  * Handles cases where the path points to:
4
4
  * - .vercel/output (use as-is)
5
5
  * - .vercel (append 'output')
6
- * - project root or other (append '.vercel/output')
6
+ * - .next/output (use as-is)
7
+ * - .next (append 'output')
8
+ * - project root or other (check for .vercel/output first, then .next/output)
9
+ * Expands leading ~ to homedir so build steps using ~/workspace write to the correct location.
7
10
  */
8
11
  export declare function resolveVercelOutputDir(inputDir: string): string;
9
12
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAOA;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAc/D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAyC1C;AAED,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,YAAY,EAAE,CA0I1E;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAgE7D"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AASA;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAkC/D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAyC1C;AAED,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,YAAY,EAAE,CA0I1E;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAmG7D"}
package/dist/utils.js CHANGED
@@ -1,28 +1,55 @@
1
1
  import * as fs from 'fs';
2
2
  import * as path from 'path';
3
+ import * as os from "os";
3
4
  import * as crypto from 'crypto';
4
5
  import { fileURLToPath } from 'url';
6
+ import { generateHandlerWrapper } from "./handler-wrapper.js";
5
7
  /**
6
8
  * Resolve the Vercel output directory from a given path
7
9
  * Handles cases where the path points to:
8
10
  * - .vercel/output (use as-is)
9
11
  * - .vercel (append 'output')
10
- * - project root or other (append '.vercel/output')
12
+ * - .next/output (use as-is)
13
+ * - .next (append 'output')
14
+ * - project root or other (check for .vercel/output first, then .next/output)
15
+ * Expands leading ~ to homedir so build steps using ~/workspace write to the correct location.
11
16
  */
12
17
  export function resolveVercelOutputDir(inputDir) {
13
- const resolvedDir = path.resolve(inputDir);
18
+ const expandedDir = inputDir === "~" || inputDir.startsWith("~/") || inputDir.startsWith("~\\")
19
+ ? path.join(os.homedir(), inputDir.slice(1))
20
+ : inputDir;
21
+ const resolvedDir = path.resolve(expandedDir);
14
22
  const normalized = resolvedDir.replace(/\\/g, '/'); // Normalize for cross-platform
15
23
  if (normalized.endsWith('/.vercel/output') || normalized.endsWith('\\.vercel\\output')) {
16
24
  // Already pointing to .vercel/output, use as-is
17
25
  return resolvedDir;
18
26
  }
27
+ else if (normalized.endsWith('/.next/output') || normalized.endsWith('\\.next\\output')) {
28
+ // Already pointing to .next/output, use as-is
29
+ return resolvedDir;
30
+ }
19
31
  else if (normalized.endsWith('/.vercel') || normalized.endsWith('\\.vercel')) {
20
32
  // Points to .vercel directory, append 'output'
21
33
  return path.join(resolvedDir, 'output');
22
34
  }
35
+ else if (normalized.endsWith('/.next') || normalized.endsWith('\\.next')) {
36
+ // Points to .next directory, append 'output'
37
+ return path.join(resolvedDir, 'output');
38
+ }
23
39
  else {
24
- // Points to project root or something else, append '.vercel/output'
25
- return path.join(resolvedDir, '.vercel', 'output');
40
+ // Points to project root or something else, check for .vercel/output first, then .next/output
41
+ const vercelOutputPath = path.join(resolvedDir, '.vercel', 'output');
42
+ const nextOutputPath = path.join(resolvedDir, '.next', 'output');
43
+ if (fs.existsSync(vercelOutputPath)) {
44
+ return vercelOutputPath;
45
+ }
46
+ else if (fs.existsSync(nextOutputPath)) {
47
+ return nextOutputPath;
48
+ }
49
+ else {
50
+ // Default to .vercel/output if neither exists (for backwards compatibility)
51
+ return vercelOutputPath;
52
+ }
26
53
  }
27
54
  }
28
55
  /**
@@ -201,7 +228,7 @@ export function scanFunctions(dir, baseDir) {
201
228
  * Similar to the bash script: uses sorted file names and contents
202
229
  */
203
230
  export function hashFunctionDirectory(funcDir) {
204
- const hash = crypto.createHash('sha256');
231
+ const hash = crypto.createHash("sha256");
205
232
  const files = [];
206
233
  function walkDir(dir, baseDir) {
207
234
  if (!fs.existsSync(dir)) {
@@ -209,12 +236,15 @@ export function hashFunctionDirectory(funcDir) {
209
236
  }
210
237
  const entries = fs.readdirSync(dir, { withFileTypes: true });
211
238
  // Sort entries by name for deterministic ordering
212
- entries.sort((a, b) => a.name.localeCompare(b.name, 'en', { numeric: true }));
239
+ entries.sort((a, b) => a.name.localeCompare(b.name, "en", { numeric: true }));
213
240
  for (const entry of entries) {
214
241
  const fullPath = path.join(dir, entry.name);
215
242
  const relativePath = path.relative(baseDir, fullPath);
216
243
  // Skip .DS_Store and __MACOSX
217
- if (entry.name === '.DS_Store' || entry.name === '__MACOSX' || relativePath.includes('/.DS_Store') || relativePath.includes('/__MACOSX')) {
244
+ if (entry.name === ".DS_Store" ||
245
+ entry.name === "__MACOSX" ||
246
+ relativePath.includes("/.DS_Store") ||
247
+ relativePath.includes("/__MACOSX")) {
218
248
  continue;
219
249
  }
220
250
  if (entry.isFile()) {
@@ -249,15 +279,40 @@ export function hashFunctionDirectory(funcDir) {
249
279
  }
250
280
  // Walk the directory and collect all files
251
281
  walkDir(funcDir, funcDir);
282
+ // Include the injected handler wrapper in the hash so that changes to the wrapper
283
+ // (e.g. dynamic import for ESM) produce fresh hashes and deployments.
284
+ let handlerFile = "handler.js";
285
+ const vcConfigPath = path.join(funcDir, ".vc-config.json");
286
+ if (fs.existsSync(vcConfigPath)) {
287
+ try {
288
+ const vcConfig = JSON.parse(fs.readFileSync(vcConfigPath, "utf8"));
289
+ if (vcConfig.handler) {
290
+ handlerFile = vcConfig.handler;
291
+ }
292
+ }
293
+ catch {
294
+ // Use default handler file if config is missing or invalid
295
+ }
296
+ }
297
+ const wrapperContent = Buffer.from(generateHandlerWrapper(handlerFile), "utf8");
298
+ // Replace any existing handler.js in the dir with our wrapper (zip contents match hash)
299
+ const normalized = (p) => p.split(path.sep).join("/");
300
+ const filtered = files.filter((f) => normalized(f.path) !== "handler.js");
301
+ filtered.push({ path: "handler.js", content: wrapperContent });
302
+ files.length = 0;
303
+ files.push(...filtered);
252
304
  // Sort files by path for deterministic ordering
253
- files.sort((a, b) => a.path.localeCompare(b.path, 'en', { numeric: true }));
305
+ files.sort((a, b) => a.path.localeCompare(b.path, "en", { numeric: true }));
254
306
  // Create a deterministic representation
255
307
  // Format: path:size:content_hash\n
256
308
  for (const file of files) {
257
- const fileHash = crypto.createHash('sha256').update(file.content).digest('hex');
309
+ const fileHash = crypto
310
+ .createHash("sha256")
311
+ .update(file.content)
312
+ .digest("hex");
258
313
  const line = `${file.path}:${file.content.length}:${fileHash}\n`;
259
314
  hash.update(line);
260
315
  }
261
- return hash.digest('hex');
316
+ return hash.digest("hex");
262
317
  }
263
318
  //# sourceMappingURL=utils.js.map