@easel-sh/cli 0.1.0-alpha.12 → 0.1.0-alpha.14

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.
@@ -3,6 +3,7 @@
3
3
  * - Fetch Web Standard: export default { fetch(request) { return new Response(...); } };
4
4
  * - HTTP method exports: export function GET(request) { return new Response(...); }
5
5
  * - Node-style: export default (req, res) => { ... } with Vercel-like helpers (query, cookies, body, status, send, json, redirect).
6
+ * Uses Lambda response streaming (awslambda.streamifyResponse) so streaming Fetch responses are piped to the client.
6
7
  */
7
8
  export declare function generateHandlerWrapper(handlerFile: string): string;
8
9
  //# sourceMappingURL=handler-wrapper.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"handler-wrapper.d.ts","sourceRoot":"","sources":["../src/handler-wrapper.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAiTlE"}
1
+ {"version":3,"file":"handler-wrapper.d.ts","sourceRoot":"","sources":["../src/handler-wrapper.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CA+RlE"}
@@ -3,12 +3,14 @@
3
3
  * - Fetch Web Standard: export default { fetch(request) { return new Response(...); } };
4
4
  * - HTTP method exports: export function GET(request) { return new Response(...); }
5
5
  * - Node-style: export default (req, res) => { ... } with Vercel-like helpers (query, cookies, body, status, send, json, redirect).
6
+ * Uses Lambda response streaming (awslambda.streamifyResponse) so streaming Fetch responses are piped to the client.
6
7
  */
7
8
  export function generateHandlerWrapper(handlerFile) {
8
9
  const handlerPath = JSON.stringify("./" + handlerFile.replace(/\\/g, "/"));
9
10
  return `/* eslint-disable @typescript-eslint/no-require-imports */
10
11
 
11
12
  const { Readable } = require("stream");
13
+ const { pipeline } = require("stream/promises");
12
14
  const { EventEmitter } = require("events");
13
15
 
14
16
  const HTTP_METHODS = ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS", "HEAD"];
@@ -22,292 +24,273 @@ function getModule() {
22
24
  }
23
25
 
24
26
  function normalizeStatus(status) {
25
- // Valid HTTP status is 100-599. Response.status can be 0 for error/opaque (Fetch API).
26
27
  if (typeof status === "number" && status >= 100 && status < 600) return status;
27
- if (status === 0) return 502; // error/opaque response
28
+ if (status === 0) return 502;
28
29
  return 200;
29
30
  }
30
31
 
31
- async function responseToLambda(response) {
32
- const responseHeaders = {};
33
- response.headers.forEach((value, key) => {
34
- responseHeaders[key.toLowerCase()] = value;
32
+ function getResponseHeaders(response) {
33
+ const out = {};
34
+ response.headers.forEach(function (value, key) {
35
+ out[key.toLowerCase()] = value;
35
36
  });
36
- const body = await response.text();
37
- return {
38
- statusCode: normalizeStatus(response.status),
39
- headers: responseHeaders,
40
- body: body,
41
- };
37
+ return out;
42
38
  }
43
39
 
44
- module.exports.handler = async (event, _context) => {
40
+ function writeStreamFirstLine(responseStream, statusCode, headers) {
41
+ const line = JSON.stringify({ statusCode: statusCode, headers: headers }) + "\\n";
42
+ responseStream.write(line);
43
+ }
44
+
45
+ function writeErrorToStream(responseStream, err) {
46
+ writeStreamFirstLine(responseStream, 502, { "content-type": "application/json" });
47
+ responseStream.write(JSON.stringify({ error: err instanceof Error ? err.message : String(err) }));
48
+ responseStream.end();
49
+ }
50
+
51
+ async function writeFetchResponseToStream(responseStream, response) {
52
+ const statusCode = normalizeStatus(response.status);
53
+ const headers = getResponseHeaders(response);
54
+ writeStreamFirstLine(responseStream, statusCode, headers);
55
+
56
+ if (response.body != null && typeof response.body.getReader === "function") {
57
+ const nodeReadable = Readable.fromWeb(response.body);
58
+ var streamStartMs = Date.now();
59
+ console.log("[handler] stream body pipeline starting at " + streamStartMs + " ms");
60
+ try {
61
+ await pipeline(nodeReadable, responseStream);
62
+ var streamEndMs = Date.now();
63
+ console.log("[handler] stream body pipeline finished at " + streamEndMs + " ms (duration " + (streamEndMs - streamStartMs) + " ms)");
64
+ } catch (pipeErr) {
65
+ console.error("[handler] stream body pipeline error at " + Date.now() + " ms:", pipeErr instanceof Error ? pipeErr.message : String(pipeErr));
66
+ throw pipeErr;
67
+ }
68
+ } else {
69
+ const body = await response.text();
70
+ responseStream.write(body);
71
+ responseStream.end();
72
+ }
73
+ }
74
+
75
+ async function runStreamingHandler(event, responseStream, context) {
76
+ try {
77
+ const mod = await getModule();
78
+ const handler = mod.default !== undefined ? mod.default : mod;
79
+
80
+ const isV2 = event.requestContext && event.requestContext.http;
81
+ const method = isV2 ? event.requestContext.http.method : event.httpMethod || "GET";
82
+
83
+ const normalizedHeaders = {};
84
+ if (event.headers) {
85
+ Object.entries(event.headers).forEach(function (entry) {
86
+ const key = entry[0];
87
+ const value = entry[1];
88
+ normalizedHeaders[key.toLowerCase()] = value;
89
+ });
90
+ }
91
+
92
+ const queryParams = { ...(event.queryStringParameters || {}) };
93
+ const originalPath = normalizedHeaders["x-router-original-path"];
94
+ const pathFromEvent = isV2 ? event.rawPath || event.path || "/" : event.path || "/";
95
+ const path = (originalPath && originalPath.trim())
96
+ ? (originalPath.trim().startsWith("/") ? originalPath.trim() : "/" + originalPath.trim())
97
+ : pathFromEvent;
98
+ const host = event.headers && (event.headers.host || event.headers["host"]) || "localhost";
99
+ const url = new URL(path, "http://" + host);
100
+ Object.entries(queryParams).forEach(function (entry) {
101
+ url.searchParams.set(entry[0], entry[1]);
102
+ });
103
+
104
+ let bodyBuffer = null;
105
+ if (event.body) {
106
+ bodyBuffer = event.isBase64Encoded
107
+ ? Buffer.from(event.body, "base64")
108
+ : Buffer.from(event.body, "utf8");
109
+ }
110
+
111
+ const requestUrl = "http://" + host + url.pathname + url.search;
112
+ const webRequest = new Request(requestUrl, {
113
+ method: method,
114
+ headers: normalizedHeaders,
115
+ body: bodyBuffer && bodyBuffer.length > 0 ? bodyBuffer : undefined,
116
+ });
117
+
118
+ console.log("[handler] reconstructed request:", JSON.stringify({
119
+ method: method,
120
+ url: requestUrl,
121
+ path: url.pathname,
122
+ query: queryParams,
123
+ headers: normalizedHeaders,
124
+ bodyLength: bodyBuffer ? bodyBuffer.length : 0,
125
+ }));
126
+
127
+ if (HTTP_METHODS.includes(method) && typeof mod[method] === "function") {
128
+ const response = await Promise.resolve(mod[method](webRequest));
129
+ await writeFetchResponseToStream(responseStream, response);
130
+ return;
131
+ }
132
+
133
+ if (handler && typeof handler.fetch === "function") {
134
+ const response = await handler.fetch(webRequest, context);
135
+ await writeFetchResponseToStream(responseStream, response);
136
+ return;
137
+ }
138
+
139
+ if (typeof handler !== "function") {
140
+ throw new TypeError(
141
+ "Handler must export a function (req, res), an object with fetch(request), or named GET/POST/etc. Got: " + typeof handler
142
+ );
143
+ }
144
+
145
+ var result = await runNodeStyleHandler(handler, method, url, normalizedHeaders, queryParams, bodyBuffer);
146
+ writeStreamFirstLine(responseStream, result.statusCode || 200, result.headers);
147
+ responseStream.write(result.body || "");
148
+ responseStream.end();
149
+ } catch (err) {
150
+ writeErrorToStream(responseStream, err);
151
+ }
152
+ }
153
+
154
+ function responseToLambda(response) {
155
+ const responseHeaders = getResponseHeaders(response);
156
+ return response.text().then(function (body) {
157
+ return {
158
+ statusCode: normalizeStatus(response.status),
159
+ headers: responseHeaders,
160
+ body: body,
161
+ };
162
+ });
163
+ }
164
+
165
+ async function runBufferedHandler(event, context) {
45
166
  const mod = await getModule();
46
167
  const handler = mod.default !== undefined ? mod.default : mod;
47
-
48
168
  const isV2 = event.requestContext && event.requestContext.http;
49
169
  const method = isV2 ? event.requestContext.http.method : event.httpMethod || "GET";
50
-
51
170
  const normalizedHeaders = {};
52
171
  if (event.headers) {
53
- Object.entries(event.headers).forEach(([key, value]) => {
54
- normalizedHeaders[key.toLowerCase()] = value;
172
+ Object.entries(event.headers).forEach(function (entry) {
173
+ normalizedHeaders[entry[0].toLowerCase()] = entry[1];
55
174
  });
56
175
  }
57
-
58
176
  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
177
  const originalPath = normalizedHeaders["x-router-original-path"];
61
178
  const pathFromEvent = isV2 ? event.rawPath || event.path || "/" : event.path || "/";
62
179
  const path = (originalPath && originalPath.trim())
63
180
  ? (originalPath.trim().startsWith("/") ? originalPath.trim() : "/" + originalPath.trim())
64
181
  : pathFromEvent;
65
- const host = event.headers?.host || event.headers?.["host"] || "localhost";
182
+ const host = event.headers && (event.headers.host || event.headers["host"]) || "localhost";
66
183
  const url = new URL(path, "http://" + host);
67
- Object.entries(queryParams).forEach(([key, value]) => {
68
- url.searchParams.set(key, value);
69
- });
70
-
184
+ Object.entries(queryParams).forEach(function (entry) { url.searchParams.set(entry[0], entry[1]); });
71
185
  let bodyBuffer = null;
72
186
  if (event.body) {
73
- bodyBuffer = event.isBase64Encoded
74
- ? Buffer.from(event.body, "base64")
75
- : Buffer.from(event.body, "utf8");
187
+ bodyBuffer = event.isBase64Encoded ? Buffer.from(event.body, "base64") : Buffer.from(event.body, "utf8");
76
188
  }
77
-
78
189
  const requestUrl = "http://" + host + url.pathname + url.search;
79
190
  const webRequest = new Request(requestUrl, {
80
191
  method: method,
81
192
  headers: normalizedHeaders,
82
193
  body: bodyBuffer && bodyBuffer.length > 0 ? bodyBuffer : undefined,
83
194
  });
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
195
  if (HTTP_METHODS.includes(method) && typeof mod[method] === "function") {
97
- const response = await Promise.resolve(mod[method](webRequest));
196
+ var response = await Promise.resolve(mod[method](webRequest));
98
197
  return responseToLambda(response);
99
198
  }
100
-
101
- // Vercel/Nitro: default export with fetch(request)
102
199
  if (handler && typeof handler.fetch === "function") {
103
- const response = await handler.fetch(webRequest, _context);
200
+ var response = await handler.fetch(webRequest, context);
104
201
  return responseToLambda(response);
105
202
  }
106
-
107
- // Node-style: default export as function (req, res), with Vercel-like helpers
108
203
  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
- );
204
+ throw new TypeError("Handler must export a function (req, res), an object with fetch(request), or named GET/POST/etc. Got: " + typeof handler);
112
205
  }
206
+ return runNodeStyleHandler(handler, method, url, normalizedHeaders, queryParams, bodyBuffer);
207
+ }
113
208
 
114
- return new Promise((resolve, reject) => {
115
- let _bodyParsed = undefined;
209
+ function runNodeStyleHandler(handler, method, url, normalizedHeaders, queryParams, bodyBuffer) {
210
+ return new Promise(function (resolve, reject) {
211
+ var _bodyParsed, cookiesObj;
116
212
  function getParsedBody() {
117
213
  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");
214
+ if (!bodyBuffer || bodyBuffer.length === 0) return undefined;
215
+ var ct = (normalizedHeaders["content-type"] || "").toLowerCase();
216
+ var text = bodyBuffer.toString("utf8");
124
217
  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;
218
+ if (ct.indexOf("application/json") !== -1) return _bodyParsed = JSON.parse(text);
219
+ if (ct.indexOf("application/x-www-form-urlencoded") !== -1) return _bodyParsed = Object.fromEntries(new URLSearchParams(text));
220
+ if (ct.indexOf("text/plain") !== -1) return _bodyParsed = text;
221
+ if (ct.indexOf("application/octet-stream") !== -1) return _bodyParsed = bodyBuffer;
132
222
  } catch (e) {
133
- if (ct.includes("application/json")) throw e;
134
- _bodyParsed = undefined;
223
+ if (ct.indexOf("application/json") !== -1) throw e;
135
224
  }
136
- return _bodyParsed;
225
+ return _bodyParsed = undefined;
137
226
  }
138
-
139
- let cookiesObj = undefined;
140
227
  function getCookies() {
141
228
  if (cookiesObj !== undefined) return cookiesObj;
142
229
  cookiesObj = {};
143
- const cookieHeader = normalizedHeaders["cookie"];
230
+ var cookieHeader = normalizedHeaders["cookie"];
144
231
  if (cookieHeader) {
145
232
  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
- }
233
+ var eq = part.indexOf("=");
234
+ if (eq > 0) cookiesObj[part.slice(0, eq).trim()] = part.slice(eq + 1).trim();
152
235
  });
153
236
  }
154
237
  return cookiesObj;
155
238
  }
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
- }
239
+ var req = Object.assign(
240
+ new Readable({ read: function () { if (bodyBuffer) this.push(bodyBuffer); this.push(null); } }),
241
+ { method: method, url: url.pathname + url.search, headers: normalizedHeaders, query: queryParams }
170
242
  );
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
- let statusMessage = "";
186
- const headers = {};
187
- let body = "";
188
- let headersSent = false;
189
- let resolved = false;
190
- let _destroyed = false;
191
- let _errored = null;
192
-
243
+ Object.defineProperty(req, "body", { get: getParsedBody, set: function (v) { _bodyParsed = v; }, enumerable: true, configurable: true });
244
+ Object.defineProperty(req, "cookies", { get: getCookies, set: function (v) { cookiesObj = v; }, enumerable: true, configurable: true });
245
+ var statusCode = 200, headers = {}, body = "", headersSent = false, resolved = false;
193
246
  function finishRes() {
194
247
  if (resolved) return;
195
248
  resolved = true;
196
- const out = {};
197
- Object.entries(headers).forEach(([k, v]) => {
198
- out[k] = Array.isArray(v) ? v.join(", ") : v;
199
- });
249
+ var out = {};
250
+ Object.entries(headers).forEach(function (e) { out[e[0]] = Array.isArray(e[1]) ? e[1].join(", ") : e[1]; });
200
251
  resolve({ statusCode: statusCode || 200, headers: out, body: body });
201
252
  }
202
-
203
- const res = Object.assign(new EventEmitter(), {
204
- setHeader: (key, value) => {
205
- if (!headersSent) headers[key.toLowerCase()] = value;
206
- },
207
- getHeader: (key) => headers[key.toLowerCase()],
208
- removeHeader: (key) => { delete headers[key.toLowerCase()]; },
209
- appendHeader: (key, value) => {
253
+ var res = Object.assign(new EventEmitter(), {
254
+ setHeader: function (k, v) { if (!headersSent) headers[k.toLowerCase()] = v; },
255
+ getHeader: function (k) { return headers[k.toLowerCase()]; },
256
+ removeHeader: function (k) { delete headers[k.toLowerCase()]; },
257
+ appendHeader: function (k, v) {
210
258
  if (!headersSent) {
211
- const lowerKey = key.toLowerCase();
212
- const existing = headers[lowerKey];
213
- headers[lowerKey] = existing
214
- ? (Array.isArray(existing) ? existing.concat(value) : [existing, value])
215
- : value;
216
- }
217
- },
218
- hasHeader: (key) => key.toLowerCase() in headers,
219
- getHeaderNames: () => Object.keys(headers),
220
- writeHead: (code, responseHeaders) => {
221
- if (!headersSent) {
222
- statusCode = code;
223
- if (responseHeaders) {
224
- Object.entries(responseHeaders).forEach(([key, value]) => {
225
- headers[key.toLowerCase()] = value;
226
- });
227
- }
228
- headersSent = true;
229
- }
230
- return res;
231
- },
232
- flushHeaders: () => {
233
- if (!headersSent) headersSent = true;
234
- return res;
235
- },
236
- write: (chunk) => {
237
- if (!headersSent) headersSent = true;
238
- body += chunk.toString();
239
- return true;
240
- },
241
- end: (chunk) => {
242
- if (chunk) body += chunk.toString();
243
- if (!resolved) {
244
- finishRes();
245
- res.emit("finish");
246
- res.emit("close");
259
+ var l = k.toLowerCase();
260
+ headers[l] = headers[l] ? (Array.isArray(headers[l]) ? headers[l].concat(v) : [headers[l], v]) : v;
247
261
  }
248
262
  },
249
- destroy: (err) => {
250
- if (resolved) return res;
251
- _destroyed = true;
252
- _errored = err ?? null;
253
- res.emit("close");
254
- reject(_errored ?? new Error("Response destroyed"));
263
+ hasHeader: function (k) { return k.toLowerCase() in headers; },
264
+ getHeaderNames: function () { return Object.keys(headers); },
265
+ writeHead: function (code, h) {
266
+ if (!headersSent) { statusCode = code; if (h) Object.entries(h).forEach(function (e) { headers[e[0].toLowerCase()] = e[1]; }); headersSent = true; }
255
267
  return res;
256
268
  },
257
- flush: () => { /* no-op for compression middleware */ },
258
- status: (code) => {
259
- statusCode = code;
260
- return res;
261
- },
262
- send: (val) => {
263
- if (typeof val === "object" && val !== null && !Buffer.isBuffer(val)) {
264
- if (!headers["content-type"]) headers["content-type"] = "application/json";
265
- body = JSON.stringify(val);
266
- } else {
267
- body = val == null ? "" : String(val);
268
- }
269
- finishRes();
270
- return res;
271
- },
272
- json: (obj) => {
273
- headers["content-type"] = "application/json";
274
- body = JSON.stringify(obj);
275
- finishRes();
276
- return res;
269
+ flushHeaders: function () { headersSent = true; return res; },
270
+ write: function (chunk) { headersSent = true; body += chunk.toString(); return true; },
271
+ end: function (chunk) { if (chunk) body += chunk.toString(); if (!resolved) { finishRes(); res.emit("finish"); res.emit("close"); } },
272
+ destroy: function (err) { if (!resolved) { res.emit("close"); reject(err || new Error("Response destroyed")); } return res; },
273
+ flush: function () {},
274
+ status: function (c) { statusCode = c; return res; },
275
+ send: function (val) {
276
+ if (typeof val === "object" && val !== null && !Buffer.isBuffer(val)) { if (!headers["content-type"]) headers["content-type"] = "application/json"; body = JSON.stringify(val); }
277
+ else body = val == null ? "" : String(val);
278
+ finishRes(); return res;
277
279
  },
278
- redirect: (a, b) => {
279
- const code = typeof a === "number" ? a : 307;
280
- const loc = typeof a === "number" ? b : a;
281
- statusCode = code;
282
- headers["location"] = loc;
283
- finishRes();
284
- return res;
285
- },
286
- get writableFinished() { return resolved; },
287
- get errored() { return _errored; },
288
- get destroyed() { return _destroyed; },
289
- get statusMessage() { return statusMessage; },
290
- set statusMessage(value) { statusMessage = value; },
280
+ json: function (obj) { headers["content-type"] = "application/json"; body = JSON.stringify(obj); finishRes(); return res; },
281
+ redirect: function (a, b) { statusCode = typeof a === "number" ? a : 307; headers["location"] = typeof a === "number" ? b : a; finishRes(); return res; },
291
282
  headersSent: false,
292
283
  });
293
-
294
- Object.defineProperty(res, "statusCode", {
295
- get: () => statusCode,
296
- set: (value) => { statusCode = value; },
297
- enumerable: true,
298
- configurable: true,
299
- });
300
-
284
+ Object.defineProperty(res, "statusCode", { get: function () { return statusCode; }, set: function (v) { statusCode = v; }, enumerable: true, configurable: true });
301
285
  req.on("error", reject);
302
286
  res.on("error", reject);
303
-
304
- try {
305
- handler(req, res);
306
- } catch (error) {
307
- reject(error);
308
- }
287
+ try { handler(req, res); } catch (e) { reject(e); }
309
288
  });
310
- };
289
+ }
290
+
291
+ module.exports.handler = typeof awslambda !== "undefined" && awslambda.streamifyResponse
292
+ ? awslambda.streamifyResponse(runStreamingHandler)
293
+ : runBufferedHandler;
311
294
  `;
312
295
  }
313
296
  //# sourceMappingURL=handler-wrapper.js.map
@@ -1 +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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoS3C,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"handler-wrapper.js","sourceRoot":"","sources":["../src/handler-wrapper.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;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;;;;;;;;;;;iCAWwB,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiR3C,CAAC;AACF,CAAC"}
@@ -49,5 +49,24 @@ describe("handler-wrapper", () => {
49
49
  expect(result.statusCode).toBe(200);
50
50
  expect(result.body).toBe("ok");
51
51
  });
52
+ it("buffered path: Fetch GET returning Response with text body returns status and body", async () => {
53
+ const wrapperCode = generateHandlerWrapper("index.mjs");
54
+ fs.writeFileSync(path.join(tmpDir, "handler.js"), wrapperCode, "utf8");
55
+ fs.writeFileSync(path.join(tmpDir, "index.mjs"), `export function GET() {
56
+ return new Response("hello world", { status: 200, headers: { "content-type": "text/plain" } });
57
+ }`, "utf8");
58
+ const handler = require(path.join(tmpDir, "handler.js")).handler;
59
+ const mockEvent = {
60
+ requestContext: { http: { method: "GET" } },
61
+ headers: { host: "localhost" },
62
+ rawPath: "/",
63
+ };
64
+ const result = await handler(mockEvent, {});
65
+ expect(result).toBeDefined();
66
+ expect(result.statusCode).toBe(200);
67
+ expect(result.body).toBe("hello world");
68
+ expect(result.headers).toBeDefined();
69
+ expect(result.headers["content-type"]).toBe("text/plain");
70
+ });
52
71
  });
53
72
  //# sourceMappingURL=handler-wrapper.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"handler-wrapper.test.js","sourceRoot":"","sources":["../src/handler-wrapper.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,IAAI,MAAc,CAAC;IACnB,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAE/C,UAAU,CAAC,GAAG,EAAE;QACd,MAAM,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,uBAAuB,CAAC,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uEAAuE,EAAE,KAAK,IAAI,EAAE;QACrF,MAAM,WAAW,GAAG,sBAAsB,CAAC,WAAW,CAAC,CAAC;QACxD,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;QACvE,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,EAC9B;;;QAGE,EACF,MAAM,CACP,CAAC;QAEF,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC;QACjE,MAAM,SAAS,GAAG;YAChB,cAAc,EAAE,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE;YAC3C,OAAO,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;YAC9B,OAAO,EAAE,GAAG;SACb,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QAE5C,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;QAC7B,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;QAClF,MAAM,WAAW,GAAG,sBAAsB,CAAC,WAAW,CAAC,CAAC;QACxD,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;QACvE,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,EAC9B;;;QAGE,EACF,MAAM,CACP,CAAC;QAEF,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC;QACjE,MAAM,SAAS,GAAG;YAChB,cAAc,EAAE,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE;YAC3C,OAAO,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;YAC9B,OAAO,EAAE,GAAG;SACb,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QAE5C,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;QAC7B,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"handler-wrapper.test.js","sourceRoot":"","sources":["../src/handler-wrapper.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@easel-sh/cli",
3
- "version": "0.1.0-alpha.12",
3
+ "version": "0.1.0-alpha.14",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "cli": "./dist/cli.js"