@marko/run 0.1.15 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,60 +1,19 @@
1
1
  // src/adapter/polyfill.ts
2
- import { ReadableStream as ReadableStream2, TransformStream, WritableStream } from "stream/web";
3
- import { webcrypto as crypto } from "crypto";
4
- import { fetch, Response, Request as Request2, Headers, FormData, File } from "undici";
5
- import { OutgoingMessage } from "http";
6
- var globals = {
7
- crypto,
8
- fetch,
9
- Response,
10
- Request: Request2,
11
- Headers,
12
- ReadableStream: ReadableStream2,
13
- TransformStream,
14
- WritableStream,
15
- FormData,
16
- File
17
- };
18
- if (typeof OutgoingMessage.prototype.appendHeader !== "function") {
19
- const messageHeaders = /* @__PURE__ */ new WeakMap();
20
- OutgoingMessage.prototype.appendHeader = function(name, value) {
21
- let headers = messageHeaders.get(this);
22
- if (!headers) {
23
- headers = /* @__PURE__ */ new Map();
24
- messageHeaders.set(this, headers);
25
- }
26
- const key = name.toLowerCase();
27
- let existing = headers.get(key);
28
- if (existing) {
29
- if (Array.isArray(existing)) {
30
- existing.push(value);
31
- } else {
32
- existing = [existing, value];
33
- }
34
- this.setHeader(name, existing);
35
- headers.set(key, existing);
36
- } else {
37
- this.setHeader(name, value);
38
- headers.set(key, value);
39
- }
40
- return this;
41
- };
42
- }
43
- function installPolyfills() {
44
- for (const name in globals) {
45
- if (!(name in globalThis)) {
46
- Object.defineProperty(globalThis, name, {
47
- enumerable: true,
48
- configurable: true,
49
- writable: true,
50
- value: globals[name]
51
- });
52
- }
53
- }
54
- }
2
+ import * as webStream from "stream/web";
3
+ import { webcrypto } from "crypto";
4
+ import * as undici from "undici";
5
+ globalThis.crypto ?? (globalThis.crypto = webcrypto);
6
+ globalThis.fetch ?? (globalThis.fetch = undici.fetch);
7
+ globalThis.Response ?? (globalThis.Response = undici.Response);
8
+ globalThis.Request ?? (globalThis.Request = undici.Request);
9
+ globalThis.Headers ?? (globalThis.Headers = undici.Headers);
10
+ globalThis.ReadableStream ?? (globalThis.ReadableStream = webStream.ReadableStream);
11
+ globalThis.TransformStream ?? (globalThis.TransformStream = webStream.TransformStream);
12
+ globalThis.WritableStream ?? (globalThis.WritableStream = webStream.WritableStream);
13
+ globalThis.FormData ?? (globalThis.FormData = undici.FormData);
14
+ globalThis.File ?? (globalThis.File = undici.File);
55
15
 
56
16
  // src/adapter/middleware.ts
57
- installPolyfills();
58
17
  function getForwardedHeader(req, name) {
59
18
  const value = req.headers["x-forwarded-" + name];
60
19
  if (value) {
@@ -65,10 +24,9 @@ function getForwardedHeader(req, name) {
65
24
  return value[0];
66
25
  }
67
26
  }
68
- function getOrigin(req, protocol, host, trustProxy) {
69
- var _a;
70
- protocol ?? (protocol = req.protocol || trustProxy && getForwardedHeader(req, "proto") || ((_a = req.socket) == null ? void 0 : _a.encrypted) && "https" || "http");
71
- host ?? (host = trustProxy && getForwardedHeader(req, "host") || req.headers.host);
27
+ function getOrigin(req, trustProxy) {
28
+ const protocol = req.protocol || trustProxy && getForwardedHeader(req, "proto") || (req.socket.encrypted ? "https" : "http");
29
+ let host = req.headers.host || trustProxy && getForwardedHeader(req, "host");
72
30
  if (!host) {
73
31
  if (process.env.NODE_ENV !== "production") {
74
32
  host = "localhost";
@@ -86,70 +44,116 @@ function getOrigin(req, protocol, host, trustProxy) {
86
44
  var inExpiresDateRgs = /Expires\s*=\s*(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun)\s*$/i;
87
45
  function setResponseHeaders(response, res) {
88
46
  for (const [key, value] of response.headers) {
89
- if (key === "set-cookie") {
90
- let sepIndex = value.indexOf(",") + 1;
91
- if (!sepIndex) {
92
- res.setHeader(key, value);
47
+ if (key !== "set-cookie") {
48
+ res.setHeader(key, value);
49
+ }
50
+ }
51
+ const setCookies = getSetCookie(response.headers);
52
+ if (setCookies == null ? void 0 : setCookies.length) {
53
+ res.setHeader("set-cookie", setCookies);
54
+ }
55
+ }
56
+ var getSetCookie = Headers.prototype.getSetCookie ? getSetCookie_platform : getSetCookie_fallback;
57
+ function getSetCookie_platform(headers) {
58
+ return headers.getSetCookie();
59
+ }
60
+ function getSetCookie_fallback(headers) {
61
+ const value = headers.get("set-cookie");
62
+ if (!value)
63
+ return void 0;
64
+ let sepIndex = value.indexOf(",") + 1;
65
+ if (!sepIndex)
66
+ return value;
67
+ let index = 0;
68
+ let setCookie = void 0;
69
+ let setCookies = void 0;
70
+ do {
71
+ const valuePart = value.slice(index, sepIndex - 1);
72
+ if (!inExpiresDateRgs.test(valuePart)) {
73
+ if (setCookies) {
74
+ setCookies.push(valuePart);
75
+ } else if (setCookie) {
76
+ setCookies = [setCookie, valuePart];
93
77
  } else {
94
- let index = 0;
95
- do {
96
- const valuePart = value.slice(index, sepIndex - 1);
97
- if (!inExpiresDateRgs.test(valuePart)) {
98
- res.appendHeader(key, valuePart);
99
- index = sepIndex;
100
- }
101
- sepIndex = value.indexOf(",", sepIndex) + 1;
102
- } while (sepIndex);
103
- res.appendHeader(key, value.slice(index));
78
+ setCookie = valuePart;
104
79
  }
105
- } else {
106
- res.setHeader(key, value);
80
+ index = sepIndex;
81
+ while (value.charCodeAt(index) === 32)
82
+ index++;
107
83
  }
84
+ sepIndex = value.indexOf(",", sepIndex) + 1;
85
+ } while (sepIndex);
86
+ if (index) {
87
+ const valuePart = value.slice(index);
88
+ if (setCookies) {
89
+ setCookies.push(valuePart);
90
+ return setCookies;
91
+ }
92
+ return [setCookie, valuePart];
108
93
  }
94
+ return value;
109
95
  }
110
96
  function createMiddleware(fetch2, options = {}) {
111
- const { trustProxy = process.env.TRUST_PROXY === "1", devServer } = options;
112
- let { origin = process.env.ORIGIN } = options;
113
- let protocol;
114
- let host;
115
- if (origin) {
116
- ({ protocol, host } = new URL(origin));
117
- protocol = protocol.slice(0, -1);
118
- }
97
+ const {
98
+ origin = process.env.ORIGIN,
99
+ trustProxy = process.env.TRUST_PROXY === "1",
100
+ devServer
101
+ } = options;
119
102
  return async (req, res, next) => {
120
- origin ?? (origin = getOrigin(req, protocol, host, trustProxy));
121
- const url = new URL(req.url, origin);
103
+ const controller = new AbortController();
104
+ const { signal } = controller;
105
+ const url = new URL(req.url, origin || getOrigin(req, trustProxy));
122
106
  const ip = req.ip || trustProxy && getForwardedHeader(req, "for") || req.socket.remoteAddress || "";
123
107
  const headers = req.headers;
124
- const body = req.method === "GET" || req.method === "HEAD" ? void 0 : req.socket ? req : new ReadableStream({
125
- start(controller) {
126
- req.on("data", (chunk) => controller.enqueue(chunk));
127
- req.on("end", () => controller.close());
128
- req.on("error", (err) => controller.error(err));
129
- }
130
- });
108
+ req.on("error", onError);
109
+ res.on("error", onError);
110
+ req.socket.on("error", onError);
111
+ function onError(err) {
112
+ req.off("error", onError);
113
+ res.off("error", onError);
114
+ req.socket.off("error", onError);
115
+ controller.abort(err);
116
+ }
117
+ if (process.env.NODE_ENV !== "production" && devServer) {
118
+ devServer.ws.on("connection", function onConnection(ws) {
119
+ devServer.ws.off("connection", onConnection);
120
+ if (signal.aborted) {
121
+ sendError();
122
+ } else {
123
+ signal.addEventListener("abort", sendError);
124
+ }
125
+ function sendError() {
126
+ const { message, stack = "" } = signal.reason;
127
+ ws.send(
128
+ JSON.stringify({
129
+ type: "error",
130
+ err: { message, stack }
131
+ })
132
+ );
133
+ }
134
+ });
135
+ } else {
136
+ signal.addEventListener("abort", () => {
137
+ if (!res.destroyed && res.socket) {
138
+ res.socket.destroySoon();
139
+ }
140
+ });
141
+ }
131
142
  const request = new Request(url, {
132
143
  method: req.method,
133
144
  headers,
134
- body,
135
- duplex: "half"
145
+ body: req.method === "GET" || req.method === "HEAD" ? void 0 : req,
146
+ duplex: "half",
147
+ signal
136
148
  });
137
149
  const response = await fetch2(request, {
138
150
  ip,
139
151
  request: req,
140
- response: res,
141
- setCookie(cookie) {
142
- res.appendHeader("set-cookie", cookie);
143
- }
152
+ response: res
144
153
  });
145
154
  if (!response) {
146
155
  if (next) {
147
156
  next();
148
- } else {
149
- res.statusCode = 404;
150
- res.setHeader("content-length", "0");
151
- res.end();
152
- return;
153
157
  }
154
158
  return;
155
159
  }
@@ -161,57 +165,34 @@ function createMiddleware(fetch2, options = {}) {
161
165
  }
162
166
  res.end();
163
167
  return;
164
- }
165
- const reader = response.body.getReader();
166
- if (res.destroyed) {
167
- reader.cancel();
168
+ } else if (res.destroyed) {
169
+ controller.abort(new Error("Response stream destroyed"));
168
170
  return;
169
171
  }
170
- res.on("close", cancel);
171
- res.on("error", cancel);
172
- write();
173
- function cancel(error) {
174
- res.off("close", cancel);
175
- res.off("error", cancel);
176
- reader.cancel(error).catch(() => {
177
- });
178
- if (error) {
179
- if (process.env.NODE_ENV !== "production" && devServer) {
180
- res.end();
181
- devServer.ws.send({
182
- type: "error",
183
- err: { message: error.message, stack: error.stack || "" }
184
- });
185
- } else {
186
- res.destroy(error);
187
- }
188
- }
189
- }
190
- async function write() {
191
- try {
192
- while (true) {
193
- const { done, value } = await reader.read();
194
- if (done) {
195
- res.end();
196
- return;
197
- } else if (!res.write(value)) {
198
- res.once("drain", write);
199
- return;
200
- } else if (res.flush) {
201
- res.flush();
202
- }
203
- }
204
- } catch (err) {
205
- const error = err instanceof Error ? err : new Error("Error while writing to node response", {
206
- cause: err
207
- });
208
- cancel(error);
172
+ writeResponse(response.body.getReader(), res, controller);
173
+ };
174
+ }
175
+ async function writeResponse(reader, res, controller) {
176
+ try {
177
+ while (!controller.signal.aborted) {
178
+ const { done, value } = await reader.read();
179
+ if (done) {
180
+ res.end();
181
+ return;
182
+ } else if (!res.write(value)) {
183
+ res.once("drain", () => writeResponse(reader, res, controller));
184
+ return;
185
+ } else if (res.flush) {
186
+ res.flush();
209
187
  }
210
188
  }
211
- };
189
+ } catch (err) {
190
+ controller.abort(err);
191
+ }
212
192
  }
213
193
  export {
214
194
  createMiddleware,
215
195
  getOrigin,
196
+ getSetCookie_fallback,
216
197
  setResponseHeaders
217
198
  };
@@ -1,6 +1,6 @@
1
- declare module 'http' {
2
- interface OutgoingMessage {
3
- appendHeader(this: OutgoingMessage, name: string, value: string): this;
1
+ declare global {
2
+ interface Headers {
3
+ getSetCookie: () => string[];
4
4
  }
5
5
  }
6
- export declare function installPolyfills(): void;
6
+ export {};
@@ -1,4 +1,28 @@
1
1
  #!/usr/bin/env node
2
+ var __defProp = Object.defineProperty;
3
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
+ var __publicField = (obj, key, value) => {
5
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
6
+ return value;
7
+ };
8
+ var __accessCheck = (obj, member, msg) => {
9
+ if (!member.has(obj))
10
+ throw TypeError("Cannot " + msg);
11
+ };
12
+ var __privateGet = (obj, member, getter) => {
13
+ __accessCheck(obj, member, "read from private field");
14
+ return getter ? getter.call(obj) : member.get(obj);
15
+ };
16
+ var __privateAdd = (obj, member, value) => {
17
+ if (member.has(obj))
18
+ throw TypeError("Cannot add the same private member more than once");
19
+ member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
20
+ };
21
+ var __privateSet = (obj, member, value, setter) => {
22
+ __accessCheck(obj, member, "write to private field");
23
+ setter ? setter.call(obj, value) : member.set(obj, value);
24
+ return value;
25
+ };
2
26
 
3
27
  // src/cli/index.ts
4
28
  import sade from "sade";
@@ -48,11 +72,154 @@ var RoutableFileTypes = {
48
72
  Error: "500"
49
73
  };
50
74
 
75
+ // src/vite/routes/vdir.ts
76
+ var _dirs, _pathlessDirs;
77
+ var _VDir = class {
78
+ constructor(parent, segment, source) {
79
+ __privateAdd(this, _dirs, void 0);
80
+ __privateAdd(this, _pathlessDirs, void 0);
81
+ __publicField(this, "parent");
82
+ __publicField(this, "source");
83
+ __publicField(this, "path");
84
+ __publicField(this, "fullPath");
85
+ __publicField(this, "segment");
86
+ __publicField(this, "files");
87
+ if (!parent || !segment) {
88
+ this.parent = null;
89
+ this.source = null;
90
+ this.path = "/";
91
+ this.fullPath = "/";
92
+ this.segment = {
93
+ raw: "",
94
+ name: ""
95
+ };
96
+ } else {
97
+ this.parent = parent;
98
+ this.source = source;
99
+ this.path = parent.path + (parent.path === "/" ? segment.name : `/${segment.name}`);
100
+ this.fullPath = parent.fullPath + (parent.fullPath === "/" ? segment.name : `/${segment.name}`);
101
+ if (segment.param) {
102
+ this.fullPath += segment.param;
103
+ }
104
+ this.segment = segment;
105
+ }
106
+ }
107
+ get pathInfo() {
108
+ const value = {
109
+ id: "/",
110
+ path: "/",
111
+ segments: []
112
+ };
113
+ let sep = "";
114
+ for (const { segment } of this) {
115
+ const { type, name, param } = segment;
116
+ if (name && type !== "_") {
117
+ value.id += sep + (type || name);
118
+ value.path += sep + name;
119
+ value.isEnd = type === "$$";
120
+ if (param) {
121
+ value.path += param;
122
+ let index = type === "$$" ? null : value.segments.length;
123
+ if (!value.params) {
124
+ value.params = { [param]: index };
125
+ } else if (!(param in value.params)) {
126
+ value.params[param] = index;
127
+ }
128
+ }
129
+ value.segments.push(name);
130
+ sep = "/";
131
+ }
132
+ }
133
+ Object.defineProperty(this, "pathInfo", {
134
+ value,
135
+ enumerable: true
136
+ });
137
+ return value;
138
+ }
139
+ addDir(path4, segment) {
140
+ const map = segment.type === "_" ? __privateGet(this, _pathlessDirs) ?? __privateSet(this, _pathlessDirs, /* @__PURE__ */ new Map()) : __privateGet(this, _dirs) ?? __privateSet(this, _dirs, /* @__PURE__ */ new Map());
141
+ if (!map.has(segment.name)) {
142
+ const dir = new _VDir(this, segment, path4);
143
+ map.set(segment.name, dir);
144
+ return dir;
145
+ }
146
+ return map.get(segment.name);
147
+ }
148
+ addFile(file) {
149
+ if (!this.files) {
150
+ this.files = /* @__PURE__ */ new Map();
151
+ this.files.set(file.type, file);
152
+ } else if (!this.files.has(file.type)) {
153
+ this.files.set(file.type, file);
154
+ } else {
155
+ const existing = this.files.get(file.type);
156
+ if (existing !== file) {
157
+ throw new Error(
158
+ `Duplicate file type '${file.type}' added at path '${this.path}'. File '${file.filePath}' collides with '${existing.filePath}'.`
159
+ );
160
+ } else if (file.type === RoutableFileTypes.Page || file.type === RoutableFileTypes.Handler) {
161
+ throw new Error(
162
+ `Ambiguous path definition: route '${this.path}' is defined multiple times by ${file.filePath}`
163
+ );
164
+ }
165
+ throw new Error(
166
+ `Ambiguous path definition: file '${this.path}' is included multiple times by ${file.filePath}`
167
+ );
168
+ }
169
+ }
170
+ *dirs() {
171
+ if (__privateGet(this, _pathlessDirs)) {
172
+ yield* __privateGet(this, _pathlessDirs).values();
173
+ }
174
+ if (__privateGet(this, _dirs)) {
175
+ yield* __privateGet(this, _dirs).values();
176
+ }
177
+ }
178
+ *[Symbol.iterator]() {
179
+ if (this.parent) {
180
+ yield* this.parent;
181
+ }
182
+ yield this;
183
+ }
184
+ static addPaths(roots, paths) {
185
+ const dirs = [];
186
+ const unique = /* @__PURE__ */ new Set();
187
+ for (const root of roots) {
188
+ for (const path4 of paths) {
189
+ let dir = root;
190
+ for (const segment of path4.segments) {
191
+ dir = dir.addDir(path4, segment);
192
+ }
193
+ if (unique.has(dir.path)) {
194
+ const sources = /* @__PURE__ */ new Set();
195
+ let sourcePath = "";
196
+ for (const { source } of dir) {
197
+ if (source && !sources.has(source.source)) {
198
+ sources.add(source.source);
199
+ sourcePath += source.source + "/";
200
+ }
201
+ }
202
+ throw new Error(
203
+ `Ambiguous directory structure: '${sourcePath}${path4.source}' defines '${dir.path}' multiple times.`
204
+ );
205
+ } else {
206
+ unique.add(dir.path);
207
+ dirs.push(dir);
208
+ }
209
+ }
210
+ }
211
+ return dirs;
212
+ }
213
+ };
214
+ var VDir = _VDir;
215
+ _dirs = new WeakMap();
216
+ _pathlessDirs = new WeakMap();
217
+
51
218
  // src/vite/routes/builder.ts
52
219
  var markoFiles = `(${RoutableFileTypes.Layout}|${RoutableFileTypes.Page}|${RoutableFileTypes.NotFound}|${RoutableFileTypes.Error})\\.(?:.*\\.)?(marko)`;
53
220
  var nonMarkoFiles = `(${RoutableFileTypes.Middleware}|${RoutableFileTypes.Handler}|${RoutableFileTypes.Meta})\\.(?:.*\\.)?(.+)`;
54
221
  var routeableFileRegex = new RegExp(
55
- `^[+](?:${markoFiles}|${nonMarkoFiles})$`,
222
+ `[+](?:${markoFiles}|${nonMarkoFiles})$`,
56
223
  "i"
57
224
  );
58
225