@marko/run 0.5.13 → 0.5.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.
- package/README.md +85 -76
- package/dist/.tsbuildinfo +1 -1
- package/dist/adapter/default-entry.mjs +12 -13
- package/dist/adapter/index.cjs +470 -454
- package/dist/adapter/index.d.ts +2 -2
- package/dist/adapter/index.js +473 -457
- package/dist/adapter/load-dev-worker.mjs +5 -5
- package/dist/adapter/middleware.cjs +5 -3
- package/dist/adapter/middleware.d.ts +1 -1
- package/dist/adapter/middleware.js +5 -3
- package/dist/adapter/polyfill.d.ts +1 -1
- package/dist/cli/default.config.mjs +2 -2
- package/dist/cli/index.mjs +1290 -1264
- package/dist/runtime/index.d.ts +3 -3
- package/dist/runtime/internal.d.ts +1 -1
- package/dist/runtime/namespace.d.ts +1 -1
- package/dist/vite/codegen/index.d.ts +1 -1
- package/dist/vite/constants.d.ts +1 -1
- package/dist/vite/index.cjs +1308 -1282
- package/dist/vite/index.d.ts +2 -2
- package/dist/vite/index.js +1303 -1277
- package/dist/vite/plugin.d.ts +1 -1
- package/dist/vite/routes/vdir.d.ts +1 -1
- package/dist/vite/types.d.ts +3 -3
- package/dist/vite/utils/config.d.ts +1 -1
- package/dist/vite/utils/log.d.ts +1 -1
- package/dist/vite/utils/route.d.ts +1 -1
- package/dist/vite/utils/server.d.ts +1 -1
- package/package.json +64 -63
package/dist/vite/index.js
CHANGED
|
@@ -10,14 +10,44 @@ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot
|
|
|
10
10
|
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
11
11
|
|
|
12
12
|
// src/vite/plugin.ts
|
|
13
|
-
import
|
|
13
|
+
import markoVitePlugin from "@marko/vite";
|
|
14
|
+
import browserslist from "browserslist";
|
|
15
|
+
import { createHash } from "crypto";
|
|
16
|
+
import createDebug from "debug";
|
|
17
|
+
import { resolveToEsbuildTarget } from "esbuild-plugin-browserslist";
|
|
14
18
|
import fs3 from "fs";
|
|
15
19
|
import { glob } from "glob";
|
|
20
|
+
import path4 from "path";
|
|
16
21
|
import { fileURLToPath } from "url";
|
|
17
|
-
import browserslist from "browserslist";
|
|
18
|
-
import { resolveToEsbuildTarget } from "esbuild-plugin-browserslist";
|
|
19
22
|
import { buildErrorMessage, mergeConfig } from "vite";
|
|
20
|
-
|
|
23
|
+
|
|
24
|
+
// src/adapter/utils.ts
|
|
25
|
+
import kleur from "kleur";
|
|
26
|
+
import supporsColor from "supports-color";
|
|
27
|
+
function stripAnsi(string) {
|
|
28
|
+
return string.replace(
|
|
29
|
+
/([\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><])/g,
|
|
30
|
+
""
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
function cleanStack(stack) {
|
|
34
|
+
return stack.split(/\n/).filter((l) => /^\s*at/.test(l)).join("\n");
|
|
35
|
+
}
|
|
36
|
+
function prepareError(err) {
|
|
37
|
+
var _a;
|
|
38
|
+
return {
|
|
39
|
+
message: stripAnsi(err.message),
|
|
40
|
+
stack: stripAnsi(cleanStack(err.stack || "")),
|
|
41
|
+
id: err.id,
|
|
42
|
+
frame: stripAnsi(err.frame || ""),
|
|
43
|
+
plugin: err.plugin,
|
|
44
|
+
pluginCode: (_a = err.pluginCode) == null ? void 0 : _a.toString(),
|
|
45
|
+
loc: err.loc
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// src/vite/codegen/index.ts
|
|
50
|
+
import path from "path";
|
|
21
51
|
|
|
22
52
|
// src/vite/constants.ts
|
|
23
53
|
var markoRunFilePrefix = "__marko-run__";
|
|
@@ -34,617 +64,112 @@ var RoutableFileTypes = {
|
|
|
34
64
|
Error: "500"
|
|
35
65
|
};
|
|
36
66
|
|
|
37
|
-
// src/vite/
|
|
38
|
-
|
|
39
|
-
var
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
67
|
+
// src/vite/utils/route.ts
|
|
68
|
+
function getVerbs(route) {
|
|
69
|
+
var _a, _b;
|
|
70
|
+
const verbs = ((_b = (_a = route.handler) == null ? void 0 : _a.verbs) == null ? void 0 : _b.slice()) || [];
|
|
71
|
+
if (route.page && !verbs.includes("get")) {
|
|
72
|
+
verbs.unshift("get");
|
|
73
|
+
}
|
|
74
|
+
return verbs;
|
|
75
|
+
}
|
|
76
|
+
function hasVerb(route, verb) {
|
|
77
|
+
var _a, _b;
|
|
78
|
+
return verb === "get" && route.page || ((_b = (_a = route.handler) == null ? void 0 : _a.verbs) == null ? void 0 : _b.includes(verb));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// src/vite/codegen/writer.ts
|
|
82
|
+
function createWriter(sink, options) {
|
|
83
|
+
let buffer = "";
|
|
84
|
+
let indentLevel = 0;
|
|
85
|
+
let indentString = "";
|
|
86
|
+
let firstOpenIndex = 0;
|
|
87
|
+
const branches = [];
|
|
88
|
+
const openWriters = /* @__PURE__ */ new Map();
|
|
89
|
+
function write(data) {
|
|
90
|
+
if (!writer.__isActive) {
|
|
91
|
+
throw new Error("Cannot write to branch that has been joined");
|
|
92
|
+
}
|
|
93
|
+
if (openWriters.size) {
|
|
94
|
+
buffer += data;
|
|
58
95
|
} else {
|
|
59
|
-
|
|
60
|
-
this.source = source;
|
|
61
|
-
this.path = parent.path + (parent.path === "/" ? segment.name : `/${segment.name}`);
|
|
62
|
-
this.fullPath = parent.fullPath + (parent.fullPath === "/" ? segment.name : `/${segment.name}`);
|
|
63
|
-
if (segment.param) {
|
|
64
|
-
this.fullPath += segment.param;
|
|
65
|
-
}
|
|
66
|
-
this.segment = segment;
|
|
96
|
+
sink(data);
|
|
67
97
|
}
|
|
98
|
+
return writer;
|
|
68
99
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (param) {
|
|
83
|
-
value.path += param;
|
|
84
|
-
let index = type === "$$" ? null : value.segments.length;
|
|
85
|
-
if (!value.params) {
|
|
86
|
-
value.params = { [param]: index };
|
|
87
|
-
} else if (!(param in value.params)) {
|
|
88
|
-
value.params[param] = index;
|
|
89
|
-
}
|
|
100
|
+
const writer = {
|
|
101
|
+
__isActive: true,
|
|
102
|
+
get indent() {
|
|
103
|
+
return indentLevel;
|
|
104
|
+
},
|
|
105
|
+
set indent(value) {
|
|
106
|
+
if (options == null ? void 0 : options.indentWith) {
|
|
107
|
+
if (value < 0) {
|
|
108
|
+
value = 0;
|
|
109
|
+
}
|
|
110
|
+
if (value !== indentLevel) {
|
|
111
|
+
indentLevel = value;
|
|
112
|
+
indentString = options.indentWith.repeat(indentLevel);
|
|
90
113
|
}
|
|
91
|
-
value.segments.push(name);
|
|
92
|
-
sep = "/";
|
|
93
114
|
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
});
|
|
99
|
-
return value;
|
|
100
|
-
}
|
|
101
|
-
addDir(path5, segment) {
|
|
102
|
-
const map = segment.type === "_" ? __privateGet(this, _pathlessDirs) ?? __privateSet(this, _pathlessDirs, /* @__PURE__ */ new Map()) : __privateGet(this, _dirs) ?? __privateSet(this, _dirs, /* @__PURE__ */ new Map());
|
|
103
|
-
if (!map.has(segment.name)) {
|
|
104
|
-
const dir = new _VDir(this, segment, path5);
|
|
105
|
-
map.set(segment.name, dir);
|
|
106
|
-
return dir;
|
|
107
|
-
}
|
|
108
|
-
return map.get(segment.name);
|
|
109
|
-
}
|
|
110
|
-
addFile(file) {
|
|
111
|
-
if (!this.files) {
|
|
112
|
-
this.files = /* @__PURE__ */ new Map();
|
|
113
|
-
this.files.set(file.type, file);
|
|
114
|
-
} else if (!this.files.has(file.type)) {
|
|
115
|
-
this.files.set(file.type, file);
|
|
116
|
-
} else {
|
|
117
|
-
const existing = this.files.get(file.type);
|
|
118
|
-
if (existing !== file) {
|
|
119
|
-
throw new Error(
|
|
120
|
-
`Duplicate file type '${file.type}' added at path '${this.path}'. File '${file.importPath}' collides with '${existing.importPath}'.`
|
|
121
|
-
);
|
|
122
|
-
} else if (file.type === RoutableFileTypes.Page || file.type === RoutableFileTypes.Handler) {
|
|
123
|
-
throw new Error(
|
|
124
|
-
`Ambiguous path definition: route '${this.path}' is defined multiple times by ${file.importPath}`
|
|
125
|
-
);
|
|
115
|
+
},
|
|
116
|
+
write(data, indent = false) {
|
|
117
|
+
if (indent && indentString) {
|
|
118
|
+
write(indentString);
|
|
126
119
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
if (__privateGet(this, _pathlessDirs)) {
|
|
134
|
-
yield* __privateGet(this, _pathlessDirs).values();
|
|
135
|
-
}
|
|
136
|
-
if (__privateGet(this, _dirs)) {
|
|
137
|
-
yield* __privateGet(this, _dirs).values();
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
*[Symbol.iterator]() {
|
|
141
|
-
if (this.parent) {
|
|
142
|
-
yield* this.parent;
|
|
143
|
-
}
|
|
144
|
-
yield this;
|
|
145
|
-
}
|
|
146
|
-
static addPaths(roots, paths) {
|
|
147
|
-
const dirs = [];
|
|
148
|
-
const unique = /* @__PURE__ */ new Set();
|
|
149
|
-
for (const root of roots) {
|
|
150
|
-
for (const path5 of paths) {
|
|
151
|
-
let dir = root;
|
|
152
|
-
for (const segment of path5.segments) {
|
|
153
|
-
dir = dir.addDir(path5, segment);
|
|
120
|
+
return write(data);
|
|
121
|
+
},
|
|
122
|
+
writeLines(...lines) {
|
|
123
|
+
for (const line of lines) {
|
|
124
|
+
if (line) {
|
|
125
|
+
writer.write(line, true);
|
|
154
126
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
if (charCode === 41 && group) {
|
|
202
|
-
break;
|
|
203
|
-
} else if (charCode === 44) {
|
|
204
|
-
if (!current) {
|
|
205
|
-
segmentEnd(
|
|
206
|
-
basePaths.map((path5) => ({
|
|
207
|
-
...path5,
|
|
208
|
-
segments: path5.segments.slice()
|
|
209
|
-
})),
|
|
210
|
-
"",
|
|
211
|
-
"_",
|
|
212
|
-
pathMap
|
|
213
|
-
);
|
|
214
|
-
} else {
|
|
215
|
-
segmentEnd(current, pattern.slice(segmentStart, i), type, pathMap);
|
|
216
|
-
}
|
|
217
|
-
current = void 0;
|
|
218
|
-
type = void 0;
|
|
219
|
-
segmentStart = ++i;
|
|
220
|
-
} else if (charCode === 46) {
|
|
221
|
-
if (current) {
|
|
222
|
-
segmentEnd(current, pattern.slice(segmentStart, i), type);
|
|
223
|
-
}
|
|
224
|
-
type = void 0;
|
|
225
|
-
segmentStart = ++i;
|
|
226
|
-
} else if (charCode === 40) {
|
|
227
|
-
const groupPaths = parse2(current || basePaths, ++i);
|
|
228
|
-
if (groupPaths.length) {
|
|
229
|
-
current = groupPaths;
|
|
230
|
-
}
|
|
231
|
-
segmentStart = ++i;
|
|
232
|
-
} else {
|
|
233
|
-
if (charCode === 95) {
|
|
234
|
-
type = "_";
|
|
235
|
-
} else if (charCode === 36) {
|
|
236
|
-
type = pattern.charCodeAt(i + 1) === 36 ? "$$" : "$";
|
|
237
|
-
}
|
|
238
|
-
current ?? (current = basePaths.map((path5) => ({
|
|
239
|
-
...path5,
|
|
240
|
-
segments: path5.segments.slice()
|
|
241
|
-
})));
|
|
242
|
-
i = len;
|
|
243
|
-
for (const char of delimiters) {
|
|
244
|
-
const index = pattern.indexOf(char, segmentStart);
|
|
245
|
-
if (index >= 0 && index < i) {
|
|
246
|
-
i = index;
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
} while (i < len);
|
|
251
|
-
if (group && charCode !== 41) {
|
|
252
|
-
throw new Error(
|
|
253
|
-
`Invalid route pattern: group was not closed '${pattern.slice(
|
|
254
|
-
group
|
|
255
|
-
)}' in '${pattern}'`
|
|
256
|
-
);
|
|
257
|
-
}
|
|
258
|
-
if (!current) {
|
|
259
|
-
segmentEnd(
|
|
260
|
-
basePaths.map((path5) => ({
|
|
261
|
-
...path5,
|
|
262
|
-
segments: path5.segments.slice()
|
|
263
|
-
})),
|
|
264
|
-
"",
|
|
265
|
-
"_",
|
|
266
|
-
pathMap
|
|
267
|
-
);
|
|
268
|
-
} else {
|
|
269
|
-
segmentEnd(current, pattern.slice(segmentStart, i), type, pathMap);
|
|
270
|
-
}
|
|
271
|
-
return [...pathMap.values()];
|
|
272
|
-
}
|
|
273
|
-
function segmentEnd(paths, raw, type, map) {
|
|
274
|
-
let segment;
|
|
275
|
-
if (raw) {
|
|
276
|
-
segment = {
|
|
277
|
-
raw,
|
|
278
|
-
name: raw,
|
|
279
|
-
type
|
|
280
|
-
};
|
|
281
|
-
if (type === "$" || type === "$$") {
|
|
282
|
-
segment.name = type;
|
|
283
|
-
segment.param = raw.slice(type.length);
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
for (const path5 of paths) {
|
|
287
|
-
if (segment) {
|
|
288
|
-
if (path5.isCatchall) {
|
|
289
|
-
throw new Error(
|
|
290
|
-
`Invalid route pattern: nested segments are not allowed after a catch-all parameter. Found '.' following '${pattern.slice(
|
|
291
|
-
0,
|
|
292
|
-
i
|
|
293
|
-
)}' in '${pattern}'.`
|
|
294
|
-
);
|
|
295
|
-
}
|
|
296
|
-
path5.segments.push(segment);
|
|
297
|
-
path5.id += path5.id === "/" ? segment.name : `/${segment.name}`;
|
|
298
|
-
if (type === "$$") {
|
|
299
|
-
path5.isCatchall = true;
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
if (map) {
|
|
303
|
-
if (map.has(path5.id)) {
|
|
304
|
-
const existing = map.get(path5.id);
|
|
305
|
-
const existingExpansion = existing.segments.map((s) => s.raw).join(".");
|
|
306
|
-
const currentExpansion = path5.segments.map((s) => s.raw).join(".");
|
|
307
|
-
throw new Error(
|
|
308
|
-
`Invalid route pattern: route '${path5.id}' is ambiguous. Expansion '${currentExpansion}' collides with '${existingExpansion}' in '${pattern}'.`
|
|
309
|
-
);
|
|
310
|
-
}
|
|
311
|
-
map.set(path5.id, path5);
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
// src/vite/routes/builder.ts
|
|
318
|
-
var markoFiles = `(${RoutableFileTypes.Layout}|${RoutableFileTypes.Page}|${RoutableFileTypes.NotFound}|${RoutableFileTypes.Error})\\.(?:.*\\.)?(marko)`;
|
|
319
|
-
var nonMarkoFiles = `(${RoutableFileTypes.Middleware}|${RoutableFileTypes.Handler}|${RoutableFileTypes.Meta})\\.(?:.*\\.)?(.+)`;
|
|
320
|
-
var routeableFileRegex = new RegExp(
|
|
321
|
-
`[+](?:${markoFiles}|${nonMarkoFiles})$`,
|
|
322
|
-
"i"
|
|
323
|
-
);
|
|
324
|
-
function matchRoutableFile(filename) {
|
|
325
|
-
const match = filename.match(routeableFileRegex);
|
|
326
|
-
return match && (match[1] || match[3]).toLowerCase();
|
|
327
|
-
}
|
|
328
|
-
function isSpecialType(type) {
|
|
329
|
-
return type === RoutableFileTypes.NotFound || type === RoutableFileTypes.Error;
|
|
330
|
-
}
|
|
331
|
-
async function buildRoutes(sources) {
|
|
332
|
-
const uniqueRoutes = /* @__PURE__ */ new Map();
|
|
333
|
-
const routes = [];
|
|
334
|
-
const special = {};
|
|
335
|
-
const middlewares = /* @__PURE__ */ new Set();
|
|
336
|
-
const unusedFiles = /* @__PURE__ */ new Set();
|
|
337
|
-
const currentLayouts = /* @__PURE__ */ new Set();
|
|
338
|
-
const currentMiddleware = /* @__PURE__ */ new Set();
|
|
339
|
-
const root = new VDir();
|
|
340
|
-
const dirStack = [];
|
|
341
|
-
let basePath;
|
|
342
|
-
let importPrefix;
|
|
343
|
-
let activeDirs;
|
|
344
|
-
let isBaseDir;
|
|
345
|
-
let nextFileId = 1;
|
|
346
|
-
let nextRouteIndex = 1;
|
|
347
|
-
const walkOptions = {
|
|
348
|
-
onEnter({ name }) {
|
|
349
|
-
const prevDirStackLength = dirStack.length;
|
|
350
|
-
if (isBaseDir) {
|
|
351
|
-
isBaseDir = false;
|
|
352
|
-
if (!basePath) {
|
|
353
|
-
return;
|
|
354
|
-
}
|
|
355
|
-
name = basePath;
|
|
356
|
-
} else {
|
|
357
|
-
dirStack.push(name);
|
|
358
|
-
}
|
|
359
|
-
const previousDirs = activeDirs;
|
|
360
|
-
const paths = parseFlatRoute(name);
|
|
361
|
-
activeDirs = VDir.addPaths(previousDirs, paths);
|
|
362
|
-
return () => {
|
|
363
|
-
activeDirs = previousDirs;
|
|
364
|
-
dirStack.length = prevDirStackLength;
|
|
365
|
-
};
|
|
366
|
-
},
|
|
367
|
-
onFile({ name, path: path5 }) {
|
|
368
|
-
const match = name.match(routeableFileRegex);
|
|
369
|
-
if (!match) {
|
|
370
|
-
return;
|
|
371
|
-
}
|
|
372
|
-
const type = (match[1] || match[3]).toLowerCase();
|
|
373
|
-
if (dirStack.length && isSpecialType(type)) {
|
|
374
|
-
console.warn(
|
|
375
|
-
`Special pages '${RoutableFileTypes.NotFound}' and '${RoutableFileTypes.Error}' are only considered in the root directory - ignoring ${path5}`
|
|
376
|
-
);
|
|
377
|
-
return;
|
|
378
|
-
}
|
|
379
|
-
let dirs = activeDirs;
|
|
380
|
-
if (match.index) {
|
|
381
|
-
const paths = parseFlatRoute(name.slice(0, match.index));
|
|
382
|
-
dirs = VDir.addPaths(activeDirs, paths);
|
|
383
|
-
}
|
|
384
|
-
const dirPath = dirStack.join("/");
|
|
385
|
-
const relativePath = dirPath ? `${dirPath}/${name}` : name;
|
|
386
|
-
const file = {
|
|
387
|
-
id: String(nextFileId++),
|
|
388
|
-
name,
|
|
389
|
-
type,
|
|
390
|
-
filePath: path5,
|
|
391
|
-
relativePath,
|
|
392
|
-
importPath: `${importPrefix}/${relativePath}`,
|
|
393
|
-
verbs: type === RoutableFileTypes.Page ? ["get"] : void 0
|
|
394
|
-
};
|
|
395
|
-
for (const dir of dirs) {
|
|
396
|
-
dir.addFile(file);
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
};
|
|
400
|
-
if (!Array.isArray(sources)) {
|
|
401
|
-
sources = [sources];
|
|
402
|
-
}
|
|
403
|
-
for (const source of sources) {
|
|
404
|
-
importPrefix = source.importPrefix ? source.importPrefix.replace(/^\/+|\/+$/g, "") : "";
|
|
405
|
-
basePath = source.basePath || "";
|
|
406
|
-
activeDirs = [root];
|
|
407
|
-
isBaseDir = true;
|
|
408
|
-
await source.walker(walkOptions);
|
|
409
|
-
}
|
|
410
|
-
traverse(root);
|
|
411
|
-
return {
|
|
412
|
-
list: routes,
|
|
413
|
-
middleware: [...middlewares],
|
|
414
|
-
special
|
|
415
|
-
};
|
|
416
|
-
function traverse(dir) {
|
|
417
|
-
let middleware;
|
|
418
|
-
let layout;
|
|
419
|
-
if (dir.files) {
|
|
420
|
-
middleware = dir.files.get(RoutableFileTypes.Middleware);
|
|
421
|
-
layout = dir.files.get(RoutableFileTypes.Layout);
|
|
422
|
-
const handler = dir.files.get(RoutableFileTypes.Handler);
|
|
423
|
-
const page = dir.files.get(RoutableFileTypes.Page);
|
|
424
|
-
let hasSpecial = false;
|
|
425
|
-
if (middleware) {
|
|
426
|
-
if (currentMiddleware.has(middleware)) {
|
|
427
|
-
middleware = void 0;
|
|
428
|
-
} else {
|
|
429
|
-
currentMiddleware.add(middleware);
|
|
430
|
-
unusedFiles.add(middleware);
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
if (layout) {
|
|
434
|
-
if (currentLayouts.has(layout)) {
|
|
435
|
-
layout = void 0;
|
|
436
|
-
} else {
|
|
437
|
-
currentLayouts.add(layout);
|
|
438
|
-
unusedFiles.add(layout);
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
if (page || handler) {
|
|
442
|
-
const path5 = dir.pathInfo;
|
|
443
|
-
if (uniqueRoutes.has(path5.id)) {
|
|
444
|
-
const existing = uniqueRoutes.get(path5.id);
|
|
445
|
-
const route = routes[existing.index];
|
|
446
|
-
const existingFiles = [route.handler, route.page].filter(Boolean).map((f) => f.filePath);
|
|
447
|
-
const currentFiles = [handler, page].filter(Boolean).map((f) => f.filePath);
|
|
448
|
-
throw new Error(`Duplicate routes for path '${path5.path}' were defined. A route established by:
|
|
449
|
-
${existingFiles.join(" and ")} via '${existing.dir.path}'
|
|
450
|
-
collides with
|
|
451
|
-
${currentFiles.join(" and ")} via '${dir.path}'
|
|
452
|
-
`);
|
|
453
|
-
}
|
|
454
|
-
uniqueRoutes.set(path5.id, { dir, index: routes.length });
|
|
455
|
-
routes.push({
|
|
456
|
-
index: nextRouteIndex++,
|
|
457
|
-
key: dir.fullPath,
|
|
458
|
-
paths: [path5],
|
|
459
|
-
middleware: [...currentMiddleware],
|
|
460
|
-
layouts: page ? [...currentLayouts] : [],
|
|
461
|
-
meta: dir.files.get(RoutableFileTypes.Meta),
|
|
462
|
-
page,
|
|
463
|
-
handler,
|
|
464
|
-
entryName: `${markoRunFilePrefix}route` + (dir.path !== "/" ? dir.fullPath.replace(/\//g, ".").replace(/(%[A-Fa-f0-9]{2})+/g, "_") : "")
|
|
465
|
-
});
|
|
466
|
-
}
|
|
467
|
-
if (dir === root) {
|
|
468
|
-
for (const [type, file] of dir.files) {
|
|
469
|
-
if (isSpecialType(type)) {
|
|
470
|
-
hasSpecial = true;
|
|
471
|
-
special[type] = {
|
|
472
|
-
index: 0,
|
|
473
|
-
key: type,
|
|
474
|
-
paths: [],
|
|
475
|
-
middleware: [],
|
|
476
|
-
layouts: [...currentLayouts],
|
|
477
|
-
page: file,
|
|
478
|
-
entryName: `${markoRunFilePrefix}special.${type}`
|
|
479
|
-
};
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
if (handler || page) {
|
|
484
|
-
for (const middleware2 of currentMiddleware) {
|
|
485
|
-
middlewares.add(middleware2);
|
|
486
|
-
unusedFiles.delete(middleware2);
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
if (page || hasSpecial) {
|
|
490
|
-
for (const layout2 of currentLayouts) {
|
|
491
|
-
unusedFiles.delete(layout2);
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
if (dir.dirs) {
|
|
496
|
-
for (const child of dir.dirs()) {
|
|
497
|
-
traverse(child);
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
if (middleware) {
|
|
501
|
-
currentMiddleware.delete(middleware);
|
|
502
|
-
}
|
|
503
|
-
if (layout) {
|
|
504
|
-
currentLayouts.delete(layout);
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
// src/vite/routes/walk.ts
|
|
510
|
-
import fs from "fs";
|
|
511
|
-
import path from "path";
|
|
512
|
-
function createFSWalker(dir) {
|
|
513
|
-
return async function walkFS({
|
|
514
|
-
onEnter,
|
|
515
|
-
onFile,
|
|
516
|
-
onDir,
|
|
517
|
-
maxDepth = 50
|
|
518
|
-
}) {
|
|
519
|
-
async function walk(dir2, depth) {
|
|
520
|
-
const onExit = onEnter == null ? void 0 : onEnter(dir2);
|
|
521
|
-
if (onExit !== false) {
|
|
522
|
-
const dirs = [];
|
|
523
|
-
const entries = await fs.promises.readdir(dir2.path, {
|
|
524
|
-
withFileTypes: true
|
|
525
|
-
});
|
|
526
|
-
const prefix = dir2.path + path.sep;
|
|
527
|
-
for (const entry of entries) {
|
|
528
|
-
const walkEntry = {
|
|
529
|
-
name: entry.name,
|
|
530
|
-
path: prefix + entry.name
|
|
531
|
-
};
|
|
532
|
-
if (entry.isDirectory()) {
|
|
533
|
-
dirs.push(walkEntry);
|
|
534
|
-
} else {
|
|
535
|
-
onFile == null ? void 0 : onFile(walkEntry);
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
if ((onDir == null ? void 0 : onDir()) !== false && --depth > 0) {
|
|
539
|
-
for (const entry of dirs) {
|
|
540
|
-
await walk(entry, depth);
|
|
541
|
-
}
|
|
542
|
-
}
|
|
543
|
-
onExit == null ? void 0 : onExit();
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
await walk(
|
|
547
|
-
{
|
|
548
|
-
path: dir,
|
|
549
|
-
name: path.basename(dir)
|
|
550
|
-
},
|
|
551
|
-
maxDepth
|
|
552
|
-
);
|
|
553
|
-
};
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
// src/vite/codegen/writer.ts
|
|
557
|
-
function createWriter(sink, options) {
|
|
558
|
-
let buffer = "";
|
|
559
|
-
let indentLevel = 0;
|
|
560
|
-
let indentString = "";
|
|
561
|
-
let firstOpenIndex = 0;
|
|
562
|
-
const branches = [];
|
|
563
|
-
const openWriters = /* @__PURE__ */ new Map();
|
|
564
|
-
function write(data) {
|
|
565
|
-
if (!writer.__isActive) {
|
|
566
|
-
throw new Error("Cannot write to branch that has been joined");
|
|
567
|
-
}
|
|
568
|
-
if (openWriters.size) {
|
|
569
|
-
buffer += data;
|
|
570
|
-
} else {
|
|
571
|
-
sink(data);
|
|
572
|
-
}
|
|
573
|
-
return writer;
|
|
574
|
-
}
|
|
575
|
-
const writer = {
|
|
576
|
-
__isActive: true,
|
|
577
|
-
get indent() {
|
|
578
|
-
return indentLevel;
|
|
579
|
-
},
|
|
580
|
-
set indent(value) {
|
|
581
|
-
if (options == null ? void 0 : options.indentWith) {
|
|
582
|
-
if (value < 0) {
|
|
583
|
-
value = 0;
|
|
584
|
-
}
|
|
585
|
-
if (value !== indentLevel) {
|
|
586
|
-
indentLevel = value;
|
|
587
|
-
indentString = options.indentWith.repeat(indentLevel);
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
},
|
|
591
|
-
write(data, indent = false) {
|
|
592
|
-
if (indent && indentString) {
|
|
593
|
-
write(indentString);
|
|
594
|
-
}
|
|
595
|
-
return write(data);
|
|
596
|
-
},
|
|
597
|
-
writeLines(...lines) {
|
|
598
|
-
for (const line of lines) {
|
|
599
|
-
if (line) {
|
|
600
|
-
writer.write(line, true);
|
|
601
|
-
}
|
|
602
|
-
writer.write("\n");
|
|
603
|
-
}
|
|
604
|
-
return writer;
|
|
605
|
-
},
|
|
606
|
-
writeBlockStart(data) {
|
|
607
|
-
writer.writeLines(data).indent++;
|
|
608
|
-
return writer;
|
|
609
|
-
},
|
|
610
|
-
writeBlockEnd(data = "}") {
|
|
611
|
-
writer.indent--;
|
|
612
|
-
writer.writeLines(data);
|
|
613
|
-
return writer;
|
|
614
|
-
},
|
|
615
|
-
writeBlock(start, lines, end) {
|
|
616
|
-
return writer.writeBlockStart(start).writeLines(...lines).writeBlockEnd(end);
|
|
617
|
-
},
|
|
618
|
-
branch(name) {
|
|
619
|
-
let existing = openWriters.get(name);
|
|
620
|
-
if (existing) {
|
|
621
|
-
return existing;
|
|
622
|
-
}
|
|
623
|
-
const branch = {
|
|
624
|
-
buffer,
|
|
625
|
-
writer: createWriter(
|
|
626
|
-
(data) => {
|
|
627
|
-
branch.buffer += data;
|
|
628
|
-
},
|
|
629
|
-
{
|
|
630
|
-
...options,
|
|
631
|
-
onJoin() {
|
|
632
|
-
openWriters.delete(name);
|
|
633
|
-
for (let i = firstOpenIndex; i < branches.length; i++) {
|
|
634
|
-
const b = branches[i];
|
|
635
|
-
if (!b) {
|
|
636
|
-
continue;
|
|
637
|
-
} else if (b.writer.__isActive) {
|
|
638
|
-
break;
|
|
639
|
-
}
|
|
640
|
-
sink(b.buffer);
|
|
641
|
-
branches[i] = null;
|
|
642
|
-
firstOpenIndex++;
|
|
643
|
-
}
|
|
644
|
-
if (!openWriters.size) {
|
|
645
|
-
sink(buffer);
|
|
646
|
-
buffer = "";
|
|
647
|
-
}
|
|
127
|
+
writer.write("\n");
|
|
128
|
+
}
|
|
129
|
+
return writer;
|
|
130
|
+
},
|
|
131
|
+
writeBlockStart(data) {
|
|
132
|
+
writer.writeLines(data).indent++;
|
|
133
|
+
return writer;
|
|
134
|
+
},
|
|
135
|
+
writeBlockEnd(data = "}") {
|
|
136
|
+
writer.indent--;
|
|
137
|
+
writer.writeLines(data);
|
|
138
|
+
return writer;
|
|
139
|
+
},
|
|
140
|
+
writeBlock(start, lines, end) {
|
|
141
|
+
return writer.writeBlockStart(start).writeLines(...lines).writeBlockEnd(end);
|
|
142
|
+
},
|
|
143
|
+
branch(name) {
|
|
144
|
+
const existing = openWriters.get(name);
|
|
145
|
+
if (existing) {
|
|
146
|
+
return existing;
|
|
147
|
+
}
|
|
148
|
+
const branch = {
|
|
149
|
+
buffer,
|
|
150
|
+
writer: createWriter(
|
|
151
|
+
(data) => {
|
|
152
|
+
branch.buffer += data;
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
...options,
|
|
156
|
+
onJoin() {
|
|
157
|
+
openWriters.delete(name);
|
|
158
|
+
for (let i = firstOpenIndex; i < branches.length; i++) {
|
|
159
|
+
const b = branches[i];
|
|
160
|
+
if (!b) {
|
|
161
|
+
continue;
|
|
162
|
+
} else if (b.writer.__isActive) {
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
sink(b.buffer);
|
|
166
|
+
branches[i] = null;
|
|
167
|
+
firstOpenIndex++;
|
|
168
|
+
}
|
|
169
|
+
if (!openWriters.size) {
|
|
170
|
+
sink(buffer);
|
|
171
|
+
buffer = "";
|
|
172
|
+
}
|
|
648
173
|
}
|
|
649
174
|
}
|
|
650
175
|
)
|
|
@@ -679,9 +204,12 @@ function createWriter(sink, options) {
|
|
|
679
204
|
}
|
|
680
205
|
function createStringWriter(opts) {
|
|
681
206
|
let code = "";
|
|
682
|
-
const writer = createWriter(
|
|
683
|
-
|
|
684
|
-
|
|
207
|
+
const writer = createWriter(
|
|
208
|
+
(data) => {
|
|
209
|
+
code += data;
|
|
210
|
+
},
|
|
211
|
+
{ indentWith: " ", ...opts }
|
|
212
|
+
);
|
|
685
213
|
return Object.assign(writer, {
|
|
686
214
|
end() {
|
|
687
215
|
writer.join(true);
|
|
@@ -690,22 +218,7 @@ function createStringWriter(opts) {
|
|
|
690
218
|
});
|
|
691
219
|
}
|
|
692
220
|
|
|
693
|
-
// src/vite/utils/route.ts
|
|
694
|
-
function getVerbs(route) {
|
|
695
|
-
var _a, _b;
|
|
696
|
-
const verbs = ((_b = (_a = route.handler) == null ? void 0 : _a.verbs) == null ? void 0 : _b.slice()) || [];
|
|
697
|
-
if (route.page && !verbs.includes("get")) {
|
|
698
|
-
verbs.unshift("get");
|
|
699
|
-
}
|
|
700
|
-
return verbs;
|
|
701
|
-
}
|
|
702
|
-
function hasVerb(route, verb) {
|
|
703
|
-
var _a, _b;
|
|
704
|
-
return verb === "get" && route.page || ((_b = (_a = route.handler) == null ? void 0 : _a.verbs) == null ? void 0 : _b.includes(verb));
|
|
705
|
-
}
|
|
706
|
-
|
|
707
221
|
// src/vite/codegen/index.ts
|
|
708
|
-
import path2 from "path";
|
|
709
222
|
function renderRouteTemplate(route, getRelativePath) {
|
|
710
223
|
if (!route.page) {
|
|
711
224
|
throw new Error(`Route ${route.key} has no page to render`);
|
|
@@ -800,628 +313,1149 @@ function renderRouteEntry(route, entriesDir) {
|
|
|
800
313
|
);
|
|
801
314
|
}
|
|
802
315
|
if (page) {
|
|
803
|
-
const
|
|
316
|
+
const pageNameIndex = page.name.indexOf("+page");
|
|
317
|
+
const pageNamePrefix = pageNameIndex > 0 ? `${page.name.slice(0, pageNameIndex)}.` : "";
|
|
318
|
+
const importPath = route.layouts.length ? `./${path.posix.join(entriesDir, page.relativePath, "..", pageNamePrefix + "route.marko")}` : `./${page.importPath}`;
|
|
804
319
|
imports.writeLines(`import page from '${importPath}${serverEntryQuery}';`);
|
|
805
320
|
}
|
|
806
|
-
if (meta) {
|
|
321
|
+
if (meta) {
|
|
322
|
+
imports.writeLines(
|
|
323
|
+
`export { default as meta${index} } from './${meta.importPath}';`
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
for (const verb of verbs) {
|
|
327
|
+
writeRouteEntryHandler(writer, route, verb);
|
|
328
|
+
}
|
|
329
|
+
return writer.end();
|
|
330
|
+
}
|
|
331
|
+
function writePageResponse(writer, wrapFn) {
|
|
332
|
+
writer.writeLines(
|
|
333
|
+
`${wrapFn ? `const ${wrapFn} = () =>` : `return`} pageResponse(page, buildInput());`
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
function writeMiddleware(writer, middleware, next, wrapFn) {
|
|
337
|
+
if (wrapFn) {
|
|
338
|
+
writer.writeLines(
|
|
339
|
+
`const ${wrapFn} = () => call(${middleware}, ${next}, context);`
|
|
340
|
+
);
|
|
341
|
+
} else {
|
|
342
|
+
writer.writeLines(`return call(${middleware}, ${next}, context);`);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
function writeRouteEntryHandler(writer, route, verb) {
|
|
346
|
+
var _a;
|
|
347
|
+
const { key, index, page, handler, middleware } = route;
|
|
348
|
+
const len = middleware.length;
|
|
349
|
+
let nextName;
|
|
350
|
+
let currentName;
|
|
351
|
+
let hasBody = false;
|
|
352
|
+
writer.writeLines("");
|
|
353
|
+
if (page) {
|
|
354
|
+
writer.writeBlockStart(
|
|
355
|
+
`export async function ${verb}${index}(context, buildInput) {`
|
|
356
|
+
);
|
|
357
|
+
} else {
|
|
358
|
+
writer.writeBlockStart(`export async function ${verb}${index}(context) {`);
|
|
359
|
+
}
|
|
360
|
+
const continuations = writer.branch("cont");
|
|
361
|
+
if (page && verb === "get") {
|
|
362
|
+
currentName = "__page";
|
|
363
|
+
if ((_a = handler == null ? void 0 : handler.verbs) == null ? void 0 : _a.includes(verb)) {
|
|
364
|
+
const name = `${verb}Handler`;
|
|
365
|
+
writePageResponse(continuations, currentName);
|
|
366
|
+
if (len) {
|
|
367
|
+
nextName = currentName;
|
|
368
|
+
currentName = `__${name}`;
|
|
369
|
+
writeMiddleware(continuations, name, nextName, currentName);
|
|
370
|
+
} else {
|
|
371
|
+
writeMiddleware(writer, name, currentName);
|
|
372
|
+
hasBody = true;
|
|
373
|
+
}
|
|
374
|
+
} else if (len) {
|
|
375
|
+
writePageResponse(continuations, currentName);
|
|
376
|
+
nextName = currentName;
|
|
377
|
+
} else {
|
|
378
|
+
writePageResponse(continuations);
|
|
379
|
+
hasBody = true;
|
|
380
|
+
}
|
|
381
|
+
} else if (handler) {
|
|
382
|
+
const name = `${verb}Handler`;
|
|
383
|
+
currentName = `__${name}`;
|
|
384
|
+
nextName = "noContent";
|
|
385
|
+
if (len) {
|
|
386
|
+
writeMiddleware(continuations, name, nextName, currentName);
|
|
387
|
+
} else {
|
|
388
|
+
writeMiddleware(writer, name, nextName);
|
|
389
|
+
hasBody = true;
|
|
390
|
+
}
|
|
391
|
+
} else {
|
|
392
|
+
throw new Error(`Route ${key} has no handler for ${verb} requests`);
|
|
393
|
+
}
|
|
394
|
+
if (!hasBody) {
|
|
395
|
+
let i = len;
|
|
396
|
+
while (i--) {
|
|
397
|
+
const { id } = middleware[i];
|
|
398
|
+
const name = `mware${id}`;
|
|
399
|
+
nextName = currentName;
|
|
400
|
+
currentName = i ? `__${name}` : "";
|
|
401
|
+
writeMiddleware(continuations, name, nextName, currentName);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
continuations.join();
|
|
405
|
+
writer.writeBlockEnd("}");
|
|
406
|
+
}
|
|
407
|
+
function renderRouter(routes, entriesDir, options = {
|
|
408
|
+
trailingSlashes: "RedirectWithout"
|
|
409
|
+
}) {
|
|
410
|
+
const writer = createStringWriter();
|
|
411
|
+
writer.writeLines(`// @marko/run/router`);
|
|
412
|
+
const imports = writer.branch("imports");
|
|
413
|
+
imports.writeLines(
|
|
414
|
+
`import { NotHandled, NotMatched, createContext } from '${virtualFilePrefix}/runtime/internal';`
|
|
415
|
+
);
|
|
416
|
+
for (const route of routes.list) {
|
|
417
|
+
const verbs = getVerbs(route);
|
|
418
|
+
const names = verbs.map((verb) => `${verb}${route.index}`);
|
|
419
|
+
route.meta && names.push(`meta${route.index}`);
|
|
420
|
+
imports.writeLines(
|
|
421
|
+
`import { ${names.join(", ")} } from '${virtualFilePrefix}/${route.entryName}.js';`
|
|
422
|
+
);
|
|
423
|
+
}
|
|
424
|
+
for (const route of Object.values(routes.special)) {
|
|
425
|
+
const importPath = route.layouts.length ? `./${path.posix.join(entriesDir, route.page.relativePath, "..", `route.${route.key}.marko`)}` : `./${route.page.importPath}`;
|
|
426
|
+
imports.writeLines(
|
|
427
|
+
`import page${route.key} from '${importPath}${serverEntryQuery}';`
|
|
428
|
+
);
|
|
429
|
+
}
|
|
430
|
+
writer.writeLines(
|
|
431
|
+
`
|
|
432
|
+
globalThis.__marko_run__ = { match, fetch, invoke };
|
|
433
|
+
`
|
|
434
|
+
).writeBlockStart(`export function match(method, pathname) {`).writeLines(
|
|
435
|
+
`if (!pathname) {
|
|
436
|
+
pathname = '/';
|
|
437
|
+
} else if (pathname.charAt(0) !== '/') {
|
|
438
|
+
pathname = '/' + pathname;
|
|
439
|
+
}`
|
|
440
|
+
).writeBlockStart(`switch (method) {`);
|
|
441
|
+
for (const verb of httpVerbs) {
|
|
442
|
+
const filteredRoutes = routes.list.filter((route) => hasVerb(route, verb));
|
|
443
|
+
if (filteredRoutes.length) {
|
|
444
|
+
const trie = createRouteTrie(filteredRoutes);
|
|
445
|
+
writer.writeLines(`case '${verb.toUpperCase()}':`);
|
|
446
|
+
writer.writeBlockStart(`case '${verb.toLowerCase()}': {`);
|
|
447
|
+
writeRouterVerb(writer, trie, verb);
|
|
448
|
+
writer.writeBlockEnd("}");
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
writer.writeBlockEnd("}").writeLines("return null;").writeBlockEnd("}");
|
|
452
|
+
writer.writeLines("").writeBlockStart(
|
|
453
|
+
"export async function invoke(route, request, platform, url) {"
|
|
454
|
+
).writeLines(
|
|
455
|
+
"const [context, buildInput] = createContext(route, request, platform, url);"
|
|
456
|
+
);
|
|
457
|
+
const hasErrorPage = Boolean(routes.special[RoutableFileTypes.Error]);
|
|
458
|
+
if (hasErrorPage) {
|
|
459
|
+
writer.writeBlockStart("try {");
|
|
460
|
+
}
|
|
461
|
+
writer.writeBlockStart("if (route) {").writeBlockStart("try {").writeLines(
|
|
462
|
+
"const response = await route.handler(context, buildInput);",
|
|
463
|
+
"if (response) return response;"
|
|
464
|
+
).indent--;
|
|
465
|
+
writer.writeBlockStart("} catch (error) {").writeLines(
|
|
466
|
+
"if (error === NotHandled) return;",
|
|
467
|
+
"if (error !== NotMatched) throw error;"
|
|
468
|
+
).writeBlockEnd("}").writeBlockEnd("}");
|
|
469
|
+
if (routes.special[RoutableFileTypes.NotFound]) {
|
|
807
470
|
imports.writeLines(
|
|
808
|
-
`
|
|
471
|
+
`
|
|
472
|
+
const page404ResponseInit = {
|
|
473
|
+
status: 404,
|
|
474
|
+
headers: { "content-type": "text/html;charset=UTF-8" },
|
|
475
|
+
};`
|
|
809
476
|
);
|
|
477
|
+
writer.write(`
|
|
478
|
+
if (context.request.headers.get('Accept')?.includes('text/html')) {
|
|
479
|
+
return new Response(page404.stream(buildInput()), page404ResponseInit);
|
|
480
|
+
}
|
|
481
|
+
`);
|
|
810
482
|
}
|
|
811
|
-
|
|
812
|
-
|
|
483
|
+
writer.indent--;
|
|
484
|
+
if (hasErrorPage) {
|
|
485
|
+
imports.writeLines(`
|
|
486
|
+
const page500ResponseInit = {
|
|
487
|
+
status: 500,
|
|
488
|
+
headers: { "content-type": "text/html;charset=UTF-8" },
|
|
489
|
+
};`);
|
|
490
|
+
writer.writeBlockStart(`} catch (error) {`).writeBlockStart(
|
|
491
|
+
`if (context.request.headers.get('Accept')?.includes('text/html')) {`
|
|
492
|
+
).writeLines(
|
|
493
|
+
`return new Response(page500.stream(buildInput({ error })), page500ResponseInit);`
|
|
494
|
+
).writeBlockEnd("}").writeLines("throw error;").writeBlockEnd("}");
|
|
813
495
|
}
|
|
496
|
+
writer.writeBlockEnd("}");
|
|
497
|
+
renderFetch(writer, options);
|
|
814
498
|
return writer.end();
|
|
815
499
|
}
|
|
816
|
-
function
|
|
817
|
-
writer.
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
`
|
|
825
|
-
)
|
|
826
|
-
|
|
827
|
-
|
|
500
|
+
function renderFetch(writer, options) {
|
|
501
|
+
writer.write(`
|
|
502
|
+
export async function fetch(request, platform) {
|
|
503
|
+
try {
|
|
504
|
+
const url = new URL(request.url);
|
|
505
|
+
let { pathname } = url;`);
|
|
506
|
+
switch (options.trailingSlashes) {
|
|
507
|
+
case "RedirectWithout":
|
|
508
|
+
writer.write(`
|
|
509
|
+
if (pathname !== '/' && pathname.endsWith('/')) {
|
|
510
|
+
url.pathname = pathname.slice(0, -1);
|
|
511
|
+
return Response.redirect(url);
|
|
512
|
+
}`);
|
|
513
|
+
break;
|
|
514
|
+
case "RedirectWith":
|
|
515
|
+
writer.write(`
|
|
516
|
+
if (pathname !== '/' && !pathname.endsWith('/')) {
|
|
517
|
+
url.pathname = pathname + '/';
|
|
518
|
+
return Response.redirect(url);
|
|
519
|
+
}`);
|
|
520
|
+
break;
|
|
521
|
+
case "RewriteWithout":
|
|
522
|
+
writer.write(`
|
|
523
|
+
if (pathname !== '/' && pathname.endsWith('/')) {
|
|
524
|
+
url.pathname = pathname = pathname.slice(0, -1);
|
|
525
|
+
}`);
|
|
526
|
+
break;
|
|
527
|
+
case "RewriteWith":
|
|
528
|
+
writer.write(`
|
|
529
|
+
if (pathname !== '/' && !pathname.endsWith('/')) {
|
|
530
|
+
url.pathname = pathname = pathname + '/';
|
|
531
|
+
}`);
|
|
532
|
+
break;
|
|
533
|
+
}
|
|
534
|
+
writer.write(`
|
|
535
|
+
|
|
536
|
+
const route = match(request.method, pathname);
|
|
537
|
+
return await invoke(route, request, platform, url);
|
|
538
|
+
} catch (error) {
|
|
539
|
+
if (import.meta.env.DEV) {
|
|
540
|
+
throw error;
|
|
541
|
+
}
|
|
542
|
+
return new Response(null, {
|
|
543
|
+
status: 500
|
|
544
|
+
});
|
|
828
545
|
}
|
|
546
|
+
}`);
|
|
829
547
|
}
|
|
830
|
-
function
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
`
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
writer.writeBlockStart(`export async function ${verb}${index}(context) {`);
|
|
548
|
+
function writeRouterVerb(writer, trie, verb, level = 0, offset = 1) {
|
|
549
|
+
const { route, dynamic, catchAll } = trie;
|
|
550
|
+
let closeCount = 0;
|
|
551
|
+
if (level === 0) {
|
|
552
|
+
writer.writeLines(`const len = pathname.length;`);
|
|
553
|
+
if (route) {
|
|
554
|
+
writer.writeLines(
|
|
555
|
+
`if (len === 1) return ${renderMatch(verb, route, trie.path)}; // ${trie.path.path}`
|
|
556
|
+
);
|
|
557
|
+
} else if (trie.static || dynamic) {
|
|
558
|
+
writer.writeBlockStart(`if (len > 1) {`);
|
|
559
|
+
closeCount++;
|
|
560
|
+
}
|
|
844
561
|
}
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
562
|
+
if (trie.static || dynamic) {
|
|
563
|
+
const next = level + 1;
|
|
564
|
+
const index = `i${next}`;
|
|
565
|
+
let terminal;
|
|
566
|
+
let children;
|
|
567
|
+
writer.writeLines(`const ${index} = pathname.indexOf('/', ${offset}) + 1;`);
|
|
568
|
+
if (trie.static) {
|
|
569
|
+
for (const child of trie.static.values()) {
|
|
570
|
+
if (child.route) {
|
|
571
|
+
(terminal ?? (terminal = [])).push(child);
|
|
572
|
+
}
|
|
573
|
+
if (child.static || child.dynamic || child.catchAll) {
|
|
574
|
+
(children ?? (children = [])).push(child);
|
|
575
|
+
}
|
|
858
576
|
}
|
|
859
|
-
} else if (len) {
|
|
860
|
-
writePageResponse(continuations, currentName);
|
|
861
|
-
nextName = currentName;
|
|
862
|
-
} else {
|
|
863
|
-
writePageResponse(continuations);
|
|
864
|
-
hasBody = true;
|
|
865
577
|
}
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
578
|
+
if (terminal || (dynamic == null ? void 0 : dynamic.route)) {
|
|
579
|
+
closeCount++;
|
|
580
|
+
writer.writeBlockStart(`if (!${index} || ${index} === len) {`);
|
|
581
|
+
let value = `pathname.slice(${offset}, ${index} ? -1 : len)`;
|
|
582
|
+
if (dynamic == null ? void 0 : dynamic.route) {
|
|
583
|
+
const segment = `s${next}`;
|
|
584
|
+
writer.writeLines(`const ${segment} = decodeURIComponent(${value});`);
|
|
585
|
+
value = segment;
|
|
586
|
+
} else if (terminal == null ? void 0 : terminal.some(
|
|
587
|
+
(terminal2) => decodeURIComponent(terminal2.key) !== terminal2.key
|
|
588
|
+
)) {
|
|
589
|
+
value = `decodeURIComponent(${value})`;
|
|
590
|
+
}
|
|
591
|
+
if (terminal) {
|
|
592
|
+
const useSwitch = terminal.length > 1;
|
|
593
|
+
if (useSwitch) {
|
|
594
|
+
writer.writeBlockStart(`switch (${value}) {`);
|
|
595
|
+
}
|
|
596
|
+
for (const { key, path: path5, route: route2 } of terminal) {
|
|
597
|
+
const decodedKey = decodeURIComponent(key);
|
|
598
|
+
if (useSwitch) {
|
|
599
|
+
writer.write(`case '${decodedKey}': `, true);
|
|
600
|
+
} else {
|
|
601
|
+
writer.write(`if (${value} === '${decodedKey}') `, true);
|
|
602
|
+
}
|
|
603
|
+
writer.write(
|
|
604
|
+
`return ${renderMatch(verb, route2, path5)}; // ${path5.path}
|
|
605
|
+
`
|
|
606
|
+
);
|
|
607
|
+
}
|
|
608
|
+
if (useSwitch) {
|
|
609
|
+
writer.writeBlockEnd("}");
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
if (dynamic == null ? void 0 : dynamic.route) {
|
|
613
|
+
writer.writeLines(
|
|
614
|
+
`if (${value}) return ${renderMatch(
|
|
615
|
+
verb,
|
|
616
|
+
dynamic.route,
|
|
617
|
+
dynamic.path
|
|
618
|
+
)}; // ${dynamic.path.path}`
|
|
619
|
+
);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
if (children || (dynamic == null ? void 0 : dynamic.static) || (dynamic == null ? void 0 : dynamic.dynamic) || (dynamic == null ? void 0 : dynamic.catchAll)) {
|
|
623
|
+
if (terminal || (dynamic == null ? void 0 : dynamic.route)) {
|
|
624
|
+
writer.writeBlockEnd("} else {").indent++;
|
|
625
|
+
} else {
|
|
626
|
+
writer.writeBlockStart(`if (${index} && ${index} !== len) {`);
|
|
627
|
+
closeCount++;
|
|
628
|
+
}
|
|
629
|
+
let value = `pathname.slice(${offset}, ${index} - 1)`;
|
|
630
|
+
if ((dynamic == null ? void 0 : dynamic.static) || (dynamic == null ? void 0 : dynamic.dynamic) || (dynamic == null ? void 0 : dynamic.catchAll)) {
|
|
631
|
+
const segment = `s${next}`;
|
|
632
|
+
writer.writeLines(`const ${segment} = decodeURIComponent(${value});`);
|
|
633
|
+
value = segment;
|
|
634
|
+
} else if (children == null ? void 0 : children.some((child) => decodeURIComponent(child.key) !== child.key)) {
|
|
635
|
+
value = `decodeURIComponent(${value})`;
|
|
636
|
+
}
|
|
637
|
+
if (children) {
|
|
638
|
+
const useSwitch = children.length > 1;
|
|
639
|
+
if (useSwitch) {
|
|
640
|
+
writer.writeBlockStart(`switch (${value}) {`);
|
|
641
|
+
}
|
|
642
|
+
for (const child of children) {
|
|
643
|
+
const decodedKey = decodeURIComponent(child.key);
|
|
644
|
+
if (useSwitch) {
|
|
645
|
+
writer.writeBlockStart(`case '${decodedKey}': {`);
|
|
646
|
+
} else {
|
|
647
|
+
writer.writeBlockStart(`if (${value} === '${decodedKey}') {`);
|
|
648
|
+
}
|
|
649
|
+
const nextOffset = typeof offset === "string" ? index : offset + child.key.length + 1;
|
|
650
|
+
writeRouterVerb(writer, child, verb, next, nextOffset);
|
|
651
|
+
if (useSwitch) {
|
|
652
|
+
writer.writeBlockEnd("} break;");
|
|
653
|
+
} else {
|
|
654
|
+
writer.writeBlockEnd("}");
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
if (useSwitch) {
|
|
658
|
+
writer.writeBlockEnd("}");
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
if ((dynamic == null ? void 0 : dynamic.static) || (dynamic == null ? void 0 : dynamic.dynamic) || (dynamic == null ? void 0 : dynamic.catchAll)) {
|
|
662
|
+
writer.writeBlockStart(`if (${value}) {`);
|
|
663
|
+
writeRouterVerb(writer, dynamic, verb, next, index);
|
|
664
|
+
writer.writeBlockEnd(`}`);
|
|
665
|
+
}
|
|
875
666
|
}
|
|
876
|
-
} else {
|
|
877
|
-
throw new Error(`Route ${key} has no handler for ${verb} requests`);
|
|
878
667
|
}
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
668
|
+
while (closeCount--) {
|
|
669
|
+
writer.writeBlockEnd("}");
|
|
670
|
+
}
|
|
671
|
+
if (catchAll) {
|
|
672
|
+
writer.writeLines(
|
|
673
|
+
`return ${renderMatch(
|
|
674
|
+
verb,
|
|
675
|
+
catchAll.route,
|
|
676
|
+
catchAll.path,
|
|
677
|
+
String(offset)
|
|
678
|
+
)}; // ${catchAll.path.path}`
|
|
679
|
+
);
|
|
680
|
+
} else if (level === 0) {
|
|
681
|
+
writer.writeLines("return null;");
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
function wrapPropertyName(name) {
|
|
685
|
+
name = decodeURIComponent(name);
|
|
686
|
+
return /^[^A-Za-z_$]|[^A-Za-z0-9$_]/.test(name) ? `'${name}'` : name;
|
|
687
|
+
}
|
|
688
|
+
function renderParams(params, pathIndex) {
|
|
689
|
+
let result = "";
|
|
690
|
+
let catchAll = "";
|
|
691
|
+
let sep = "{";
|
|
692
|
+
for (const [name, index] of Object.entries(params)) {
|
|
693
|
+
if (typeof index === "number") {
|
|
694
|
+
result += `${sep} ${wrapPropertyName(name)}: s${index + 1}`;
|
|
695
|
+
sep = ",";
|
|
696
|
+
} else if (pathIndex) {
|
|
697
|
+
catchAll = name;
|
|
887
698
|
}
|
|
888
699
|
}
|
|
889
|
-
|
|
890
|
-
|
|
700
|
+
if (catchAll) {
|
|
701
|
+
result += `${sep} ${wrapPropertyName(
|
|
702
|
+
catchAll
|
|
703
|
+
)}: pathname.slice(${pathIndex})`;
|
|
704
|
+
}
|
|
705
|
+
return result ? result + " }" : "{}";
|
|
891
706
|
}
|
|
892
|
-
function
|
|
893
|
-
|
|
894
|
-
|
|
707
|
+
function renderMatch(verb, route, path5, pathIndex) {
|
|
708
|
+
const handler = `${verb}${route.index}`;
|
|
709
|
+
const params = path5.params ? renderParams(path5.params, pathIndex) : "{}";
|
|
710
|
+
const meta = route.meta ? `meta${route.index}` : "{}";
|
|
711
|
+
const pathPattern = pathToURLPatternString(path5.path);
|
|
712
|
+
return `{ handler: ${handler}, params: ${params}, meta: ${meta}, path: '${pathPattern}' }`;
|
|
713
|
+
}
|
|
714
|
+
function renderMiddleware(middleware) {
|
|
895
715
|
const writer = createStringWriter();
|
|
896
|
-
writer.writeLines(
|
|
716
|
+
writer.writeLines(
|
|
717
|
+
`// ${virtualFilePrefix}/${markoRunFilePrefix}middleware.js`
|
|
718
|
+
);
|
|
897
719
|
const imports = writer.branch("imports");
|
|
898
720
|
imports.writeLines(
|
|
899
|
-
`import {
|
|
721
|
+
`import { normalize } from '${virtualFilePrefix}/runtime/internal';`
|
|
900
722
|
);
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
const
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
`import { ${names.join(", ")} } from '${virtualFilePrefix}/${route.entryName}.js';`
|
|
907
|
-
);
|
|
723
|
+
writer.writeLines("");
|
|
724
|
+
for (const { id, importPath } of middleware) {
|
|
725
|
+
const importName = `middleware${id}`;
|
|
726
|
+
imports.writeLines(`import ${importName} from './${importPath}';`);
|
|
727
|
+
writer.writeLines(`export const mware${id} = normalize(${importName});`);
|
|
908
728
|
}
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
729
|
+
imports.join();
|
|
730
|
+
return writer.end();
|
|
731
|
+
}
|
|
732
|
+
function stripTsExtension(path5) {
|
|
733
|
+
const index = path5.lastIndexOf(".");
|
|
734
|
+
if (index !== -1) {
|
|
735
|
+
const ext = path5.slice(index + 1);
|
|
736
|
+
if (ext.toLowerCase() === "ts") {
|
|
737
|
+
return path5.slice(0, index);
|
|
738
|
+
}
|
|
914
739
|
}
|
|
740
|
+
return path5;
|
|
741
|
+
}
|
|
742
|
+
async function renderRouteTypeInfo(routes, pathPrefix = ".", adapter) {
|
|
743
|
+
var _a, _b;
|
|
744
|
+
const writer = createStringWriter();
|
|
915
745
|
writer.writeLines(
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
).writeBlockStart(`
|
|
926
|
-
|
|
927
|
-
const
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
writer.
|
|
932
|
-
|
|
933
|
-
writer.writeBlockEnd("}");
|
|
746
|
+
`/*
|
|
747
|
+
WARNING: This file is automatically generated and any changes made to it will be overwritten without warning.
|
|
748
|
+
Do NOT manually edit this file or your changes will be lost.
|
|
749
|
+
*/
|
|
750
|
+
`,
|
|
751
|
+
`import { NotHandled, NotMatched, GetPaths, PostPaths, GetablePath, GetableHref, PostablePath, PostableHref, Platform } from "@marko/run/namespace";`,
|
|
752
|
+
`import type * as Run from "@marko/run";`
|
|
753
|
+
);
|
|
754
|
+
const headWriter = writer.branch("head");
|
|
755
|
+
writer.writeLines("\n").writeBlockStart(`declare module "@marko/run" {`);
|
|
756
|
+
if (adapter && adapter.typeInfo) {
|
|
757
|
+
const platformType = await adapter.typeInfo(
|
|
758
|
+
(data) => headWriter.write(data)
|
|
759
|
+
);
|
|
760
|
+
if (platformType) {
|
|
761
|
+
writer.writeLines(`interface Platform extends ${platformType} {}
|
|
762
|
+
`);
|
|
934
763
|
}
|
|
935
764
|
}
|
|
936
|
-
|
|
937
|
-
writer.
|
|
938
|
-
|
|
939
|
-
).
|
|
940
|
-
|
|
941
|
-
)
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
765
|
+
headWriter.join();
|
|
766
|
+
writer.writeBlockStart(`interface AppData extends Run.DefineApp<{`).writeBlockStart("routes: {");
|
|
767
|
+
const routesWriter = writer.branch("routes");
|
|
768
|
+
writer.writeBlockEnd("}").writeBlockEnd(`}> {}`).writeBlockEnd(`}`);
|
|
769
|
+
const routeTypes = /* @__PURE__ */ new Map();
|
|
770
|
+
for (const route of routes.list) {
|
|
771
|
+
let routeType = "";
|
|
772
|
+
for (const path5 of route.paths) {
|
|
773
|
+
const pathType = `"${pathToURLPatternString(path5.path)}"`;
|
|
774
|
+
routeType += routeType ? " | " + pathType : pathType;
|
|
775
|
+
routesWriter.writeLines(`${pathType}: Routes["${route.key}"];`);
|
|
776
|
+
}
|
|
777
|
+
for (const file of [route.handler, route.page]) {
|
|
778
|
+
if (file) {
|
|
779
|
+
const existing = routeTypes.get(file);
|
|
780
|
+
if (!existing) {
|
|
781
|
+
routeTypes.set(file, [routeType]);
|
|
782
|
+
} else {
|
|
783
|
+
existing.push(routeType);
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
for (const files of [route.middleware, route.layouts]) {
|
|
788
|
+
if (files) {
|
|
789
|
+
for (const file of files) {
|
|
790
|
+
const existing = routeTypes.get(file);
|
|
791
|
+
if (!existing) {
|
|
792
|
+
routeTypes.set(file, [routeType]);
|
|
793
|
+
} else {
|
|
794
|
+
existing.push(routeType);
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
}
|
|
945
799
|
}
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
)
|
|
950
|
-
writer.
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
800
|
+
for (const special of Object.values(routes.special)) {
|
|
801
|
+
routeTypes.set(special.page, []);
|
|
802
|
+
}
|
|
803
|
+
routesWriter.join();
|
|
804
|
+
const handlerWriter = writer.branch("handler");
|
|
805
|
+
const middlewareWriter = writer.branch("middleware");
|
|
806
|
+
const pageWriter = writer.branch("page");
|
|
807
|
+
const layoutWriter = writer.branch("layout");
|
|
808
|
+
for (const [file, types] of routeTypes) {
|
|
809
|
+
const path5 = `${pathPrefix}/${file.relativePath}`;
|
|
810
|
+
const routeType = `Run.Routes[${types.join(" | ")}]`;
|
|
811
|
+
switch (file.type) {
|
|
812
|
+
case RoutableFileTypes.Handler:
|
|
813
|
+
writeModuleDeclaration(handlerWriter, path5, routeType);
|
|
814
|
+
break;
|
|
815
|
+
case RoutableFileTypes.Middleware:
|
|
816
|
+
writeModuleDeclaration(middlewareWriter, path5, routeType);
|
|
817
|
+
break;
|
|
818
|
+
case RoutableFileTypes.Page:
|
|
819
|
+
writeModuleDeclaration(pageWriter, path5, routeType);
|
|
820
|
+
break;
|
|
821
|
+
case RoutableFileTypes.Layout:
|
|
822
|
+
writeModuleDeclaration(
|
|
823
|
+
layoutWriter,
|
|
824
|
+
path5,
|
|
825
|
+
routeType,
|
|
826
|
+
`
|
|
827
|
+
export interface Input {
|
|
828
|
+
renderBody: Marko.Body;
|
|
829
|
+
}`
|
|
830
|
+
);
|
|
831
|
+
break;
|
|
832
|
+
case RoutableFileTypes.Error:
|
|
833
|
+
writeModuleDeclaration(
|
|
834
|
+
writer,
|
|
835
|
+
path5,
|
|
836
|
+
"globalThis.MarkoRun.Route",
|
|
837
|
+
`
|
|
838
|
+
export interface Input {
|
|
839
|
+
error: unknown;
|
|
840
|
+
}`
|
|
841
|
+
);
|
|
842
|
+
break;
|
|
843
|
+
case RoutableFileTypes.NotFound:
|
|
844
|
+
writeModuleDeclaration(writer, path5, "Run.Route");
|
|
845
|
+
break;
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
handlerWriter.join();
|
|
849
|
+
middlewareWriter.join();
|
|
850
|
+
pageWriter.join();
|
|
851
|
+
layoutWriter.join();
|
|
852
|
+
writer.writeBlockStart(`
|
|
853
|
+
type Routes = {`);
|
|
854
|
+
for (const route of routes.list) {
|
|
855
|
+
const { meta, handler, page } = route;
|
|
856
|
+
if (page || handler) {
|
|
857
|
+
const verbs = [];
|
|
858
|
+
if (page || ((_a = handler == null ? void 0 : handler.verbs) == null ? void 0 : _a.includes("get"))) {
|
|
859
|
+
verbs.push(`"get"`);
|
|
860
|
+
}
|
|
861
|
+
if ((_b = handler == null ? void 0 : handler.verbs) == null ? void 0 : _b.includes("post")) {
|
|
862
|
+
verbs.push(`"post"`);
|
|
863
|
+
}
|
|
864
|
+
let routeType = `{ verb: ${verbs.join(" | ")};`;
|
|
865
|
+
if (meta) {
|
|
866
|
+
const metaPath = stripTsExtension(`${pathPrefix}/${meta.relativePath}`);
|
|
867
|
+
let metaType = `typeof import("${metaPath}")`;
|
|
868
|
+
if (/\.(ts|js|mjs)$/.test(meta.name)) {
|
|
869
|
+
metaType += `["default"]`;
|
|
870
|
+
}
|
|
871
|
+
routeType += ` meta: ${metaType};`;
|
|
872
|
+
}
|
|
873
|
+
writer.writeLines(`"${route.key}": ${routeType} };`);
|
|
965
874
|
}
|
|
966
|
-
`);
|
|
967
|
-
}
|
|
968
|
-
writer.indent--;
|
|
969
|
-
if (hasErrorPage) {
|
|
970
|
-
imports.writeLines(`
|
|
971
|
-
const page500ResponseInit = {
|
|
972
|
-
status: 500,
|
|
973
|
-
headers: { "content-type": "text/html;charset=UTF-8" },
|
|
974
|
-
};`);
|
|
975
|
-
writer.writeBlockStart(`} catch (error) {`).writeBlockStart(
|
|
976
|
-
`if (context.request.headers.get('Accept')?.includes('text/html')) {`
|
|
977
|
-
).writeLines(
|
|
978
|
-
`return new Response(page500.stream(buildInput({ error })), page500ResponseInit);`
|
|
979
|
-
).writeBlockEnd("}").writeLines("throw error;").writeBlockEnd("}");
|
|
980
875
|
}
|
|
981
876
|
writer.writeBlockEnd("}");
|
|
982
|
-
renderFetch(writer, options);
|
|
983
877
|
return writer.end();
|
|
984
878
|
}
|
|
985
|
-
function
|
|
986
|
-
writer.write(`
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
const url = new URL(request.url);
|
|
990
|
-
let { pathname } = url;`);
|
|
991
|
-
switch (options.trailingSlashes) {
|
|
992
|
-
case "RedirectWithout":
|
|
993
|
-
writer.write(`
|
|
994
|
-
if (pathname !== '/' && pathname.endsWith('/')) {
|
|
995
|
-
url.pathname = pathname.slice(0, -1);
|
|
996
|
-
return Response.redirect(url);
|
|
997
|
-
}`);
|
|
998
|
-
break;
|
|
999
|
-
case "RedirectWith":
|
|
1000
|
-
writer.write(`
|
|
1001
|
-
if (pathname !== '/' && !pathname.endsWith('/')) {
|
|
1002
|
-
url.pathname = pathname + '/';
|
|
1003
|
-
return Response.redirect(url);
|
|
1004
|
-
}`);
|
|
1005
|
-
break;
|
|
1006
|
-
case "RewriteWithout":
|
|
1007
|
-
writer.write(`
|
|
1008
|
-
if (pathname !== '/' && pathname.endsWith('/')) {
|
|
1009
|
-
url.pathname = pathname = pathname.slice(0, -1);
|
|
1010
|
-
}`);
|
|
1011
|
-
break;
|
|
1012
|
-
case "RewriteWith":
|
|
1013
|
-
writer.write(`
|
|
1014
|
-
if (pathname !== '/' && !pathname.endsWith('/')) {
|
|
1015
|
-
url.pathname = pathname = pathname + '/';
|
|
1016
|
-
}`);
|
|
1017
|
-
break;
|
|
879
|
+
function writeModuleDeclaration(writer, path5, routeType, moduleTypes) {
|
|
880
|
+
writer.writeLines("").write(`declare module "${stripTsExtension(path5)}" {`);
|
|
881
|
+
if (moduleTypes) {
|
|
882
|
+
writer.write(moduleTypes);
|
|
1018
883
|
}
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
884
|
+
if (routeType) {
|
|
885
|
+
const isMarko = path5.endsWith(".marko");
|
|
886
|
+
writer.write(`
|
|
887
|
+
namespace MarkoRun {
|
|
888
|
+
export { NotHandled, NotMatched, GetPaths, PostPaths, GetablePath, GetableHref, PostablePath, PostableHref, Platform };
|
|
889
|
+
export type Route = ${routeType};
|
|
890
|
+
export type Context = Run.MultiRouteContext<Route>${isMarko ? " & Marko.Global" : ""};
|
|
891
|
+
export type Handler = Run.HandlerLike<Route>;
|
|
892
|
+
/** @deprecated use \`((context, next) => { ... }) satisfies MarkoRun.Handler\` instead */
|
|
893
|
+
export const route: Run.HandlerTypeFn<Route>;
|
|
894
|
+
}`);
|
|
1030
895
|
}
|
|
896
|
+
writer.writeLines(`
|
|
1031
897
|
}`);
|
|
1032
898
|
}
|
|
1033
|
-
function
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
899
|
+
function pathToURLPatternString(path5) {
|
|
900
|
+
return path5.replace(/\/\$(\$?)([^/]*)/g, (_, catchAll, name) => {
|
|
901
|
+
name = decodeURIComponent(name);
|
|
902
|
+
return catchAll ? `/:${name || "rest"}*` : `/:${name}`;
|
|
903
|
+
});
|
|
904
|
+
}
|
|
905
|
+
function createRouteTrie(routes) {
|
|
906
|
+
const root = {
|
|
907
|
+
key: ""
|
|
908
|
+
};
|
|
909
|
+
function insert(path5, route) {
|
|
910
|
+
let node = root;
|
|
911
|
+
for (const segment of path5.segments) {
|
|
912
|
+
if (segment === "$$") {
|
|
913
|
+
node.catchAll ?? (node.catchAll = { route, path: path5 });
|
|
914
|
+
return;
|
|
915
|
+
} else if (segment === "$") {
|
|
916
|
+
node = node.dynamic ?? (node.dynamic = {
|
|
917
|
+
key: ""
|
|
918
|
+
});
|
|
919
|
+
} else {
|
|
920
|
+
node.static ?? (node.static = /* @__PURE__ */ new Map());
|
|
921
|
+
let next = node.static.get(segment);
|
|
922
|
+
if (!next) {
|
|
923
|
+
next = {
|
|
924
|
+
key: segment
|
|
925
|
+
};
|
|
926
|
+
node.static.set(segment, next);
|
|
927
|
+
}
|
|
928
|
+
node = next;
|
|
929
|
+
}
|
|
1045
930
|
}
|
|
931
|
+
node.path ?? (node.path = path5);
|
|
932
|
+
node.route ?? (node.route = route);
|
|
1046
933
|
}
|
|
1047
|
-
|
|
1048
|
-
const
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
934
|
+
for (const route of routes) {
|
|
935
|
+
for (const path5 of route.paths) {
|
|
936
|
+
insert(path5, route);
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
return root;
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
// src/vite/routes/parse.ts
|
|
943
|
+
function parseFlatRoute(pattern) {
|
|
944
|
+
if (!pattern) throw new Error("Empty pattern");
|
|
945
|
+
const len = pattern.length;
|
|
946
|
+
let i = 0;
|
|
947
|
+
return parse2([
|
|
948
|
+
{
|
|
949
|
+
id: "/",
|
|
950
|
+
segments: [],
|
|
951
|
+
source: pattern
|
|
952
|
+
}
|
|
953
|
+
]);
|
|
954
|
+
function parse2(basePaths, group) {
|
|
955
|
+
const pathMap = /* @__PURE__ */ new Map();
|
|
956
|
+
const delimiters = group ? ").," : ".,";
|
|
957
|
+
let charCode;
|
|
958
|
+
let segmentStart = i;
|
|
959
|
+
let type;
|
|
960
|
+
let current;
|
|
961
|
+
do {
|
|
962
|
+
charCode = pattern.charCodeAt(i);
|
|
963
|
+
if (charCode === 41 && group) {
|
|
964
|
+
break;
|
|
965
|
+
} else if (charCode === 44) {
|
|
966
|
+
if (!current) {
|
|
967
|
+
segmentEnd(
|
|
968
|
+
basePaths.map((path5) => ({
|
|
969
|
+
...path5,
|
|
970
|
+
segments: path5.segments.slice()
|
|
971
|
+
})),
|
|
972
|
+
"",
|
|
973
|
+
"_",
|
|
974
|
+
pathMap
|
|
975
|
+
);
|
|
976
|
+
} else {
|
|
977
|
+
segmentEnd(current, pattern.slice(segmentStart, i), type, pathMap);
|
|
1057
978
|
}
|
|
1058
|
-
|
|
1059
|
-
|
|
979
|
+
current = void 0;
|
|
980
|
+
type = void 0;
|
|
981
|
+
segmentStart = ++i;
|
|
982
|
+
} else if (charCode === 46) {
|
|
983
|
+
if (current) {
|
|
984
|
+
segmentEnd(current, pattern.slice(segmentStart, i), type);
|
|
985
|
+
}
|
|
986
|
+
type = void 0;
|
|
987
|
+
segmentStart = ++i;
|
|
988
|
+
} else if (charCode === 40) {
|
|
989
|
+
const groupPaths = parse2(current || basePaths, ++i);
|
|
990
|
+
if (groupPaths.length) {
|
|
991
|
+
current = groupPaths;
|
|
992
|
+
}
|
|
993
|
+
segmentStart = ++i;
|
|
994
|
+
} else {
|
|
995
|
+
if (charCode === 95) {
|
|
996
|
+
type = "_";
|
|
997
|
+
} else if (charCode === 36) {
|
|
998
|
+
type = pattern.charCodeAt(i + 1) === 36 ? "$$" : "$";
|
|
999
|
+
}
|
|
1000
|
+
current ?? (current = basePaths.map((path5) => ({
|
|
1001
|
+
...path5,
|
|
1002
|
+
segments: path5.segments.slice()
|
|
1003
|
+
})));
|
|
1004
|
+
i = len;
|
|
1005
|
+
for (const char of delimiters) {
|
|
1006
|
+
const index = pattern.indexOf(char, segmentStart);
|
|
1007
|
+
if (index >= 0 && index < i) {
|
|
1008
|
+
i = index;
|
|
1009
|
+
}
|
|
1060
1010
|
}
|
|
1061
1011
|
}
|
|
1012
|
+
} while (i < len);
|
|
1013
|
+
if (group && charCode !== 41) {
|
|
1014
|
+
throw new Error(
|
|
1015
|
+
`Invalid route pattern: group was not closed '${pattern.slice(
|
|
1016
|
+
group
|
|
1017
|
+
)}' in '${pattern}'`
|
|
1018
|
+
);
|
|
1062
1019
|
}
|
|
1063
|
-
if (
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1020
|
+
if (!current) {
|
|
1021
|
+
segmentEnd(
|
|
1022
|
+
basePaths.map((path5) => ({
|
|
1023
|
+
...path5,
|
|
1024
|
+
segments: path5.segments.slice()
|
|
1025
|
+
})),
|
|
1026
|
+
"",
|
|
1027
|
+
"_",
|
|
1028
|
+
pathMap
|
|
1029
|
+
);
|
|
1030
|
+
} else {
|
|
1031
|
+
segmentEnd(current, pattern.slice(segmentStart, i), type, pathMap);
|
|
1032
|
+
}
|
|
1033
|
+
return [...pathMap.values()];
|
|
1034
|
+
}
|
|
1035
|
+
function segmentEnd(paths, raw, type, map) {
|
|
1036
|
+
let segment;
|
|
1037
|
+
if (raw) {
|
|
1038
|
+
segment = {
|
|
1039
|
+
raw,
|
|
1040
|
+
name: raw,
|
|
1041
|
+
type
|
|
1042
|
+
};
|
|
1043
|
+
if (type === "$" || type === "$$") {
|
|
1044
|
+
segment.name = type;
|
|
1045
|
+
segment.param = raw.slice(type.length);
|
|
1075
1046
|
}
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
} else {
|
|
1086
|
-
writer.write(`if (${value} === '${decodedKey}') `, true);
|
|
1087
|
-
}
|
|
1088
|
-
writer.write(
|
|
1089
|
-
`return ${renderMatch(verb, route2, path5)}; // ${path5.path}
|
|
1090
|
-
`
|
|
1047
|
+
}
|
|
1048
|
+
for (const path5 of paths) {
|
|
1049
|
+
if (segment) {
|
|
1050
|
+
if (path5.isCatchall) {
|
|
1051
|
+
throw new Error(
|
|
1052
|
+
`Invalid route pattern: nested segments are not allowed after a catch-all parameter. Found '.' following '${pattern.slice(
|
|
1053
|
+
0,
|
|
1054
|
+
i
|
|
1055
|
+
)}' in '${pattern}'.`
|
|
1091
1056
|
);
|
|
1092
1057
|
}
|
|
1093
|
-
|
|
1094
|
-
|
|
1058
|
+
path5.segments.push(segment);
|
|
1059
|
+
path5.id += path5.id === "/" ? segment.name : `/${segment.name}`;
|
|
1060
|
+
if (type === "$$") {
|
|
1061
|
+
path5.isCatchall = true;
|
|
1095
1062
|
}
|
|
1096
1063
|
}
|
|
1097
|
-
if (
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1064
|
+
if (map) {
|
|
1065
|
+
if (map.has(path5.id)) {
|
|
1066
|
+
const existing = map.get(path5.id);
|
|
1067
|
+
const existingExpansion = existing.segments.map((s) => s.raw).join(".");
|
|
1068
|
+
const currentExpansion = path5.segments.map((s) => s.raw).join(".");
|
|
1069
|
+
throw new Error(
|
|
1070
|
+
`Invalid route pattern: route '${path5.id}' is ambiguous. Expansion '${currentExpansion}' collides with '${existingExpansion}' in '${pattern}'.`
|
|
1071
|
+
);
|
|
1072
|
+
}
|
|
1073
|
+
map.set(path5.id, path5);
|
|
1105
1074
|
}
|
|
1106
1075
|
}
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
// src/vite/routes/vdir.ts
|
|
1080
|
+
var _dirs, _pathlessDirs;
|
|
1081
|
+
var _VDir = class _VDir {
|
|
1082
|
+
constructor(parent, segment, source) {
|
|
1083
|
+
__privateAdd(this, _dirs);
|
|
1084
|
+
__privateAdd(this, _pathlessDirs);
|
|
1085
|
+
__publicField(this, "parent");
|
|
1086
|
+
__publicField(this, "source");
|
|
1087
|
+
__publicField(this, "path");
|
|
1088
|
+
__publicField(this, "fullPath");
|
|
1089
|
+
__publicField(this, "segment");
|
|
1090
|
+
__publicField(this, "files");
|
|
1091
|
+
if (!parent || !segment) {
|
|
1092
|
+
this.parent = null;
|
|
1093
|
+
this.source = null;
|
|
1094
|
+
this.path = "/";
|
|
1095
|
+
this.fullPath = "/";
|
|
1096
|
+
this.segment = {
|
|
1097
|
+
raw: "",
|
|
1098
|
+
name: ""
|
|
1099
|
+
};
|
|
1100
|
+
} else {
|
|
1101
|
+
this.parent = parent;
|
|
1102
|
+
this.source = source;
|
|
1103
|
+
this.path = parent.path + (parent.path === "/" ? segment.name : `/${segment.name}`);
|
|
1104
|
+
this.fullPath = parent.fullPath + (parent.fullPath === "/" ? segment.name : `/${segment.name}`);
|
|
1105
|
+
if (segment.param) {
|
|
1106
|
+
this.fullPath += segment.param;
|
|
1121
1107
|
}
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1108
|
+
this.segment = segment;
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
get pathInfo() {
|
|
1112
|
+
const value = {
|
|
1113
|
+
id: "/",
|
|
1114
|
+
path: "/",
|
|
1115
|
+
segments: []
|
|
1116
|
+
};
|
|
1117
|
+
let sep = "";
|
|
1118
|
+
for (const { segment } of this) {
|
|
1119
|
+
const { type, name, param } = segment;
|
|
1120
|
+
if (name && type !== "_") {
|
|
1121
|
+
value.id += sep + (type || name);
|
|
1122
|
+
value.path += sep + name;
|
|
1123
|
+
value.isEnd = type === "$$";
|
|
1124
|
+
if (param) {
|
|
1125
|
+
value.path += param;
|
|
1126
|
+
const index = type === "$$" ? null : value.segments.length;
|
|
1127
|
+
if (!value.params) {
|
|
1128
|
+
value.params = { [param]: index };
|
|
1129
|
+
} else if (!(param in value.params)) {
|
|
1130
|
+
value.params[param] = index;
|
|
1140
1131
|
}
|
|
1141
1132
|
}
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
}
|
|
1145
|
-
}
|
|
1146
|
-
if ((dynamic == null ? void 0 : dynamic.static) || (dynamic == null ? void 0 : dynamic.dynamic) || (dynamic == null ? void 0 : dynamic.catchAll)) {
|
|
1147
|
-
writer.writeBlockStart(`if (${value}) {`);
|
|
1148
|
-
writeRouterVerb(writer, dynamic, verb, next, index);
|
|
1149
|
-
writer.writeBlockEnd(`}`);
|
|
1133
|
+
value.segments.push(name);
|
|
1134
|
+
sep = "/";
|
|
1150
1135
|
}
|
|
1151
1136
|
}
|
|
1137
|
+
Object.defineProperty(this, "pathInfo", {
|
|
1138
|
+
value,
|
|
1139
|
+
enumerable: true
|
|
1140
|
+
});
|
|
1141
|
+
return value;
|
|
1152
1142
|
}
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
verb,
|
|
1160
|
-
catchAll.route,
|
|
1161
|
-
catchAll.path,
|
|
1162
|
-
String(offset)
|
|
1163
|
-
)}; // ${catchAll.path.path}`
|
|
1164
|
-
);
|
|
1165
|
-
} else if (level === 0) {
|
|
1166
|
-
writer.writeLines("return null;");
|
|
1167
|
-
}
|
|
1168
|
-
}
|
|
1169
|
-
function wrapPropertyName(name) {
|
|
1170
|
-
name = decodeURIComponent(name);
|
|
1171
|
-
return /^[^A-Za-z_$]|[^A-Za-z0-9$_]/.test(name) ? `'${name}'` : name;
|
|
1172
|
-
}
|
|
1173
|
-
function renderParams(params, pathIndex) {
|
|
1174
|
-
let result = "";
|
|
1175
|
-
let catchAll = "";
|
|
1176
|
-
let sep = "{";
|
|
1177
|
-
for (const [name, index] of Object.entries(params)) {
|
|
1178
|
-
if (typeof index === "number") {
|
|
1179
|
-
result += `${sep} ${wrapPropertyName(name)}: s${index + 1}`;
|
|
1180
|
-
sep = ",";
|
|
1181
|
-
} else if (pathIndex) {
|
|
1182
|
-
catchAll = name;
|
|
1143
|
+
addDir(path5, segment) {
|
|
1144
|
+
const map = segment.type === "_" ? __privateGet(this, _pathlessDirs) ?? __privateSet(this, _pathlessDirs, /* @__PURE__ */ new Map()) : __privateGet(this, _dirs) ?? __privateSet(this, _dirs, /* @__PURE__ */ new Map());
|
|
1145
|
+
if (!map.has(segment.name)) {
|
|
1146
|
+
const dir = new _VDir(this, segment, path5);
|
|
1147
|
+
map.set(segment.name, dir);
|
|
1148
|
+
return dir;
|
|
1183
1149
|
}
|
|
1150
|
+
return map.get(segment.name);
|
|
1184
1151
|
}
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
}
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
`import { normalize } from '${virtualFilePrefix}/runtime/internal';`
|
|
1207
|
-
);
|
|
1208
|
-
writer.writeLines("");
|
|
1209
|
-
for (const { id, importPath } of middleware) {
|
|
1210
|
-
const importName = `middleware${id}`;
|
|
1211
|
-
imports.writeLines(`import ${importName} from './${importPath}';`);
|
|
1212
|
-
writer.writeLines(`export const mware${id} = normalize(${importName});`);
|
|
1152
|
+
addFile(file) {
|
|
1153
|
+
if (!this.files) {
|
|
1154
|
+
this.files = /* @__PURE__ */ new Map();
|
|
1155
|
+
this.files.set(file.type, file);
|
|
1156
|
+
} else if (!this.files.has(file.type)) {
|
|
1157
|
+
this.files.set(file.type, file);
|
|
1158
|
+
} else {
|
|
1159
|
+
const existing = this.files.get(file.type);
|
|
1160
|
+
if (existing !== file) {
|
|
1161
|
+
throw new Error(
|
|
1162
|
+
`Duplicate file type '${file.type}' added at path '${this.path}'. File '${file.importPath}' collides with '${existing.importPath}'.`
|
|
1163
|
+
);
|
|
1164
|
+
} else if (file.type === RoutableFileTypes.Page || file.type === RoutableFileTypes.Handler) {
|
|
1165
|
+
throw new Error(
|
|
1166
|
+
`Ambiguous path definition: route '${this.path}' is defined multiple times by ${file.importPath}`
|
|
1167
|
+
);
|
|
1168
|
+
}
|
|
1169
|
+
throw new Error(
|
|
1170
|
+
`Ambiguous path definition: file '${this.path}' is included multiple times by ${file.importPath}`
|
|
1171
|
+
);
|
|
1172
|
+
}
|
|
1213
1173
|
}
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
const ext = path5.slice(index + 1);
|
|
1221
|
-
if (ext.toLowerCase() === "ts") {
|
|
1222
|
-
return path5.slice(0, index);
|
|
1174
|
+
*dirs() {
|
|
1175
|
+
if (__privateGet(this, _pathlessDirs)) {
|
|
1176
|
+
yield* __privateGet(this, _pathlessDirs).values();
|
|
1177
|
+
}
|
|
1178
|
+
if (__privateGet(this, _dirs)) {
|
|
1179
|
+
yield* __privateGet(this, _dirs).values();
|
|
1223
1180
|
}
|
|
1224
1181
|
}
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
var _a, _b;
|
|
1229
|
-
const writer = createStringWriter();
|
|
1230
|
-
writer.writeLines(
|
|
1231
|
-
`/*
|
|
1232
|
-
WARNING: This file is automatically generated and any changes made to it will be overwritten without warning.
|
|
1233
|
-
Do NOT manually edit this file or your changes will be lost.
|
|
1234
|
-
*/
|
|
1235
|
-
`,
|
|
1236
|
-
`import { NotHandled, NotMatched, GetPaths, PostPaths, GetablePath, GetableHref, PostablePath, PostableHref, Platform } from "@marko/run/namespace";`,
|
|
1237
|
-
`import type * as Run from "@marko/run";`
|
|
1238
|
-
);
|
|
1239
|
-
const headWriter = writer.branch("head");
|
|
1240
|
-
writer.writeLines("\n").writeBlockStart(`declare module "@marko/run" {`);
|
|
1241
|
-
if (adapter && adapter.typeInfo) {
|
|
1242
|
-
const platformType = await adapter.typeInfo(
|
|
1243
|
-
(data) => headWriter.write(data)
|
|
1244
|
-
);
|
|
1245
|
-
if (platformType) {
|
|
1246
|
-
writer.writeLines(`interface Platform extends ${platformType} {}
|
|
1247
|
-
`);
|
|
1182
|
+
*[Symbol.iterator]() {
|
|
1183
|
+
if (this.parent) {
|
|
1184
|
+
yield* this.parent;
|
|
1248
1185
|
}
|
|
1186
|
+
yield this;
|
|
1249
1187
|
}
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
const pathType = `"${pathToURLPatternString(path5.path)}"`;
|
|
1259
|
-
routeType += routeType ? " | " + pathType : pathType;
|
|
1260
|
-
routesWriter.writeLines(`${pathType}: Routes["${route.key}"];`);
|
|
1261
|
-
}
|
|
1262
|
-
for (const file of [route.handler, route.page]) {
|
|
1263
|
-
if (file) {
|
|
1264
|
-
const existing = routeTypes.get(file);
|
|
1265
|
-
if (!existing) {
|
|
1266
|
-
routeTypes.set(file, [routeType]);
|
|
1267
|
-
} else {
|
|
1268
|
-
existing.push(routeType);
|
|
1188
|
+
static addPaths(roots, paths) {
|
|
1189
|
+
const dirs = [];
|
|
1190
|
+
const unique = /* @__PURE__ */ new Set();
|
|
1191
|
+
for (const root of roots) {
|
|
1192
|
+
for (const path5 of paths) {
|
|
1193
|
+
let dir = root;
|
|
1194
|
+
for (const segment of path5.segments) {
|
|
1195
|
+
dir = dir.addDir(path5, segment);
|
|
1269
1196
|
}
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
} else {
|
|
1279
|
-
existing.push(routeType);
|
|
1197
|
+
if (unique.has(dir.path)) {
|
|
1198
|
+
const sources = /* @__PURE__ */ new Set();
|
|
1199
|
+
let sourcePath = "";
|
|
1200
|
+
for (const { source } of dir) {
|
|
1201
|
+
if (source && !sources.has(source.source)) {
|
|
1202
|
+
sources.add(source.source);
|
|
1203
|
+
sourcePath += source.source + "/";
|
|
1204
|
+
}
|
|
1280
1205
|
}
|
|
1206
|
+
throw new Error(
|
|
1207
|
+
`Ambiguous directory structure: '${sourcePath}${path5.source}' defines '${dir.path}' multiple times.`
|
|
1208
|
+
);
|
|
1209
|
+
} else {
|
|
1210
|
+
unique.add(dir.path);
|
|
1211
|
+
dirs.push(dir);
|
|
1281
1212
|
}
|
|
1282
1213
|
}
|
|
1283
1214
|
}
|
|
1215
|
+
return dirs;
|
|
1284
1216
|
}
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1217
|
+
};
|
|
1218
|
+
_dirs = new WeakMap();
|
|
1219
|
+
_pathlessDirs = new WeakMap();
|
|
1220
|
+
var VDir = _VDir;
|
|
1221
|
+
|
|
1222
|
+
// src/vite/routes/builder.ts
|
|
1223
|
+
var markoFiles = `(${RoutableFileTypes.Layout}|${RoutableFileTypes.Page}|${RoutableFileTypes.NotFound}|${RoutableFileTypes.Error})\\.(?:.*\\.)?(marko)`;
|
|
1224
|
+
var nonMarkoFiles = `(${RoutableFileTypes.Middleware}|${RoutableFileTypes.Handler}|${RoutableFileTypes.Meta})\\.(?:.*\\.)?(.+)`;
|
|
1225
|
+
var routeableFileRegex = new RegExp(
|
|
1226
|
+
`[+](?:${markoFiles}|${nonMarkoFiles})$`,
|
|
1227
|
+
"i"
|
|
1228
|
+
);
|
|
1229
|
+
function matchRoutableFile(filename) {
|
|
1230
|
+
const match = filename.match(routeableFileRegex);
|
|
1231
|
+
return match && (match[1] || match[3]).toLowerCase();
|
|
1232
|
+
}
|
|
1233
|
+
function isSpecialType(type) {
|
|
1234
|
+
return type === RoutableFileTypes.NotFound || type === RoutableFileTypes.Error;
|
|
1235
|
+
}
|
|
1236
|
+
async function buildRoutes(sources) {
|
|
1237
|
+
const uniqueRoutes = /* @__PURE__ */ new Map();
|
|
1238
|
+
const routes = [];
|
|
1239
|
+
const special = {};
|
|
1240
|
+
const middlewares = /* @__PURE__ */ new Set();
|
|
1241
|
+
const unusedFiles = /* @__PURE__ */ new Set();
|
|
1242
|
+
const currentLayouts = /* @__PURE__ */ new Set();
|
|
1243
|
+
const currentMiddleware = /* @__PURE__ */ new Set();
|
|
1244
|
+
const root = new VDir();
|
|
1245
|
+
const dirStack = [];
|
|
1246
|
+
let basePath;
|
|
1247
|
+
let importPrefix;
|
|
1248
|
+
let activeDirs;
|
|
1249
|
+
let isBaseDir;
|
|
1250
|
+
let nextFileId = 1;
|
|
1251
|
+
let nextRouteIndex = 1;
|
|
1252
|
+
const walkOptions = {
|
|
1253
|
+
onEnter({ name }) {
|
|
1254
|
+
const prevDirStackLength = dirStack.length;
|
|
1255
|
+
if (isBaseDir) {
|
|
1256
|
+
isBaseDir = false;
|
|
1257
|
+
if (!basePath) {
|
|
1258
|
+
return;
|
|
1259
|
+
}
|
|
1260
|
+
name = basePath;
|
|
1261
|
+
} else {
|
|
1262
|
+
dirStack.push(name);
|
|
1263
|
+
}
|
|
1264
|
+
const previousDirs = activeDirs;
|
|
1265
|
+
const paths = parseFlatRoute(name);
|
|
1266
|
+
activeDirs = VDir.addPaths(previousDirs, paths);
|
|
1267
|
+
return () => {
|
|
1268
|
+
activeDirs = previousDirs;
|
|
1269
|
+
dirStack.length = prevDirStackLength;
|
|
1270
|
+
};
|
|
1271
|
+
},
|
|
1272
|
+
onFile({ name, path: path5 }) {
|
|
1273
|
+
const match = name.match(routeableFileRegex);
|
|
1274
|
+
if (!match) {
|
|
1275
|
+
return;
|
|
1276
|
+
}
|
|
1277
|
+
const type = (match[1] || match[3]).toLowerCase();
|
|
1278
|
+
if (dirStack.length && isSpecialType(type)) {
|
|
1279
|
+
console.warn(
|
|
1280
|
+
`Special pages '${RoutableFileTypes.NotFound}' and '${RoutableFileTypes.Error}' are only considered in the root directory - ignoring ${path5}`
|
|
1326
1281
|
);
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1282
|
+
return;
|
|
1283
|
+
}
|
|
1284
|
+
let dirs = activeDirs;
|
|
1285
|
+
if (match.index) {
|
|
1286
|
+
const paths = parseFlatRoute(name.slice(0, match.index));
|
|
1287
|
+
dirs = VDir.addPaths(activeDirs, paths);
|
|
1288
|
+
}
|
|
1289
|
+
const dirPath = dirStack.join("/");
|
|
1290
|
+
const relativePath = dirPath ? `${dirPath}/${name}` : name;
|
|
1291
|
+
const file = {
|
|
1292
|
+
id: String(nextFileId++),
|
|
1293
|
+
name,
|
|
1294
|
+
type,
|
|
1295
|
+
filePath: path5,
|
|
1296
|
+
relativePath,
|
|
1297
|
+
importPath: `${importPrefix}/${relativePath}`,
|
|
1298
|
+
verbs: type === RoutableFileTypes.Page ? ["get"] : void 0
|
|
1299
|
+
};
|
|
1300
|
+
for (const dir of dirs) {
|
|
1301
|
+
dir.addFile(file);
|
|
1302
|
+
}
|
|
1331
1303
|
}
|
|
1304
|
+
};
|
|
1305
|
+
if (!Array.isArray(sources)) {
|
|
1306
|
+
sources = [sources];
|
|
1332
1307
|
}
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1308
|
+
for (const source of sources) {
|
|
1309
|
+
importPrefix = source.importPrefix ? source.importPrefix.replace(/^\/+|\/+$/g, "") : "";
|
|
1310
|
+
basePath = source.basePath || "";
|
|
1311
|
+
activeDirs = [root];
|
|
1312
|
+
isBaseDir = true;
|
|
1313
|
+
await source.walker(walkOptions);
|
|
1314
|
+
}
|
|
1315
|
+
traverse(root);
|
|
1316
|
+
return {
|
|
1317
|
+
list: routes,
|
|
1318
|
+
middleware: [...middlewares],
|
|
1319
|
+
special
|
|
1320
|
+
};
|
|
1321
|
+
function traverse(dir) {
|
|
1322
|
+
let middleware;
|
|
1323
|
+
let layout;
|
|
1324
|
+
if (dir.files) {
|
|
1325
|
+
middleware = dir.files.get(RoutableFileTypes.Middleware);
|
|
1326
|
+
layout = dir.files.get(RoutableFileTypes.Layout);
|
|
1327
|
+
const handler = dir.files.get(RoutableFileTypes.Handler);
|
|
1328
|
+
const page = dir.files.get(RoutableFileTypes.Page);
|
|
1329
|
+
let hasSpecial = false;
|
|
1330
|
+
if (middleware) {
|
|
1331
|
+
if (currentMiddleware.has(middleware)) {
|
|
1332
|
+
middleware = void 0;
|
|
1333
|
+
} else {
|
|
1334
|
+
currentMiddleware.add(middleware);
|
|
1335
|
+
unusedFiles.add(middleware);
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
if (layout) {
|
|
1339
|
+
if (currentLayouts.has(layout)) {
|
|
1340
|
+
layout = void 0;
|
|
1341
|
+
} else {
|
|
1342
|
+
currentLayouts.add(layout);
|
|
1343
|
+
unusedFiles.add(layout);
|
|
1344
|
+
}
|
|
1345
1345
|
}
|
|
1346
|
-
if (
|
|
1347
|
-
|
|
1346
|
+
if (page || handler) {
|
|
1347
|
+
const path5 = dir.pathInfo;
|
|
1348
|
+
if (uniqueRoutes.has(path5.id)) {
|
|
1349
|
+
const existing = uniqueRoutes.get(path5.id);
|
|
1350
|
+
const route = routes[existing.index];
|
|
1351
|
+
const existingFiles = [route.handler, route.page].filter(Boolean).map((f) => f.filePath);
|
|
1352
|
+
const currentFiles = [handler, page].filter(Boolean).map((f) => f.filePath);
|
|
1353
|
+
throw new Error(`Duplicate routes for path '${path5.path}' were defined. A route established by:
|
|
1354
|
+
${existingFiles.join(" and ")} via '${existing.dir.path}'
|
|
1355
|
+
collides with
|
|
1356
|
+
${currentFiles.join(" and ")} via '${dir.path}'
|
|
1357
|
+
`);
|
|
1358
|
+
}
|
|
1359
|
+
uniqueRoutes.set(path5.id, { dir, index: routes.length });
|
|
1360
|
+
routes.push({
|
|
1361
|
+
index: nextRouteIndex++,
|
|
1362
|
+
key: dir.fullPath,
|
|
1363
|
+
paths: [path5],
|
|
1364
|
+
middleware: [...currentMiddleware],
|
|
1365
|
+
layouts: page ? [...currentLayouts] : [],
|
|
1366
|
+
meta: dir.files.get(RoutableFileTypes.Meta),
|
|
1367
|
+
page,
|
|
1368
|
+
handler,
|
|
1369
|
+
entryName: `${markoRunFilePrefix}route` + (dir.path !== "/" ? dir.fullPath.replace(/\//g, ".").replace(/(%[A-Fa-f0-9]{2})+/g, "_") : "")
|
|
1370
|
+
});
|
|
1348
1371
|
}
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1372
|
+
if (dir === root) {
|
|
1373
|
+
for (const [type, file] of dir.files) {
|
|
1374
|
+
if (isSpecialType(type)) {
|
|
1375
|
+
hasSpecial = true;
|
|
1376
|
+
special[type] = {
|
|
1377
|
+
index: 0,
|
|
1378
|
+
key: type,
|
|
1379
|
+
paths: [],
|
|
1380
|
+
middleware: [],
|
|
1381
|
+
layouts: [...currentLayouts],
|
|
1382
|
+
page: file,
|
|
1383
|
+
entryName: `${markoRunFilePrefix}special.${type}`
|
|
1384
|
+
};
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
if (handler || page) {
|
|
1389
|
+
for (const middleware2 of currentMiddleware) {
|
|
1390
|
+
middlewares.add(middleware2);
|
|
1391
|
+
unusedFiles.delete(middleware2);
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
if (page || hasSpecial) {
|
|
1395
|
+
for (const layout2 of currentLayouts) {
|
|
1396
|
+
unusedFiles.delete(layout2);
|
|
1355
1397
|
}
|
|
1356
|
-
routeType += ` meta: ${metaType};`;
|
|
1357
1398
|
}
|
|
1358
|
-
|
|
1399
|
+
}
|
|
1400
|
+
if (dir.dirs) {
|
|
1401
|
+
for (const child of dir.dirs()) {
|
|
1402
|
+
traverse(child);
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
if (middleware) {
|
|
1406
|
+
currentMiddleware.delete(middleware);
|
|
1407
|
+
}
|
|
1408
|
+
if (layout) {
|
|
1409
|
+
currentLayouts.delete(layout);
|
|
1359
1410
|
}
|
|
1360
1411
|
}
|
|
1361
|
-
writer.writeBlockEnd("}");
|
|
1362
|
-
return writer.end();
|
|
1363
|
-
}
|
|
1364
|
-
function writeModuleDeclaration(writer, path5, routeType, moduleTypes) {
|
|
1365
|
-
writer.writeLines("").write(`declare module "${stripTsExtension(path5)}" {`);
|
|
1366
|
-
if (moduleTypes) {
|
|
1367
|
-
writer.write(moduleTypes);
|
|
1368
|
-
}
|
|
1369
|
-
if (routeType) {
|
|
1370
|
-
const isMarko = path5.endsWith(".marko");
|
|
1371
|
-
writer.write(`
|
|
1372
|
-
namespace MarkoRun {
|
|
1373
|
-
export { NotHandled, NotMatched, GetPaths, PostPaths, GetablePath, GetableHref, PostablePath, PostableHref, Platform };
|
|
1374
|
-
export type Route = ${routeType};
|
|
1375
|
-
export type Context = Run.MultiRouteContext<Route>${isMarko ? " & Marko.Global" : ""};
|
|
1376
|
-
export type Handler = Run.HandlerLike<Route>;
|
|
1377
|
-
/** @deprecated use \`((context, next) => { ... }) satisfies MarkoRun.Handler\` instead */
|
|
1378
|
-
export const route: Run.HandlerTypeFn<Route>;
|
|
1379
|
-
}`);
|
|
1380
|
-
}
|
|
1381
|
-
writer.writeLines(`
|
|
1382
|
-
}`);
|
|
1383
|
-
}
|
|
1384
|
-
function pathToURLPatternString(path5) {
|
|
1385
|
-
return path5.replace(/\/\$(\$?)([^\/]*)/g, (_, catchAll, name) => {
|
|
1386
|
-
name = decodeURIComponent(name);
|
|
1387
|
-
return catchAll ? `/:${name || "rest"}*` : `/:${name}`;
|
|
1388
|
-
});
|
|
1389
1412
|
}
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1413
|
+
|
|
1414
|
+
// src/vite/routes/walk.ts
|
|
1415
|
+
import fs from "fs";
|
|
1416
|
+
import path2 from "path";
|
|
1417
|
+
function createFSWalker(dir) {
|
|
1418
|
+
return async function walkFS({
|
|
1419
|
+
onEnter,
|
|
1420
|
+
onFile,
|
|
1421
|
+
onDir,
|
|
1422
|
+
maxDepth = 50
|
|
1423
|
+
}) {
|
|
1424
|
+
async function walk(dir2, depth) {
|
|
1425
|
+
const onExit = onEnter == null ? void 0 : onEnter(dir2);
|
|
1426
|
+
if (onExit !== false) {
|
|
1427
|
+
const dirs = [];
|
|
1428
|
+
const entries = await fs.promises.readdir(dir2.path, {
|
|
1429
|
+
withFileTypes: true
|
|
1403
1430
|
});
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
key: segment
|
|
1431
|
+
const prefix = dir2.path + path2.sep;
|
|
1432
|
+
for (const entry of entries) {
|
|
1433
|
+
const walkEntry = {
|
|
1434
|
+
name: entry.name,
|
|
1435
|
+
path: prefix + entry.name
|
|
1410
1436
|
};
|
|
1411
|
-
|
|
1437
|
+
if (entry.isDirectory()) {
|
|
1438
|
+
dirs.push(walkEntry);
|
|
1439
|
+
} else {
|
|
1440
|
+
onFile == null ? void 0 : onFile(walkEntry);
|
|
1441
|
+
}
|
|
1412
1442
|
}
|
|
1413
|
-
|
|
1443
|
+
if ((onDir == null ? void 0 : onDir()) !== false && --depth > 0) {
|
|
1444
|
+
for (const entry of dirs) {
|
|
1445
|
+
await walk(entry, depth);
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
onExit == null ? void 0 : onExit();
|
|
1414
1449
|
}
|
|
1415
1450
|
}
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
}
|
|
1424
|
-
return root;
|
|
1451
|
+
await walk(
|
|
1452
|
+
{
|
|
1453
|
+
path: dir,
|
|
1454
|
+
name: path2.basename(dir)
|
|
1455
|
+
},
|
|
1456
|
+
maxDepth
|
|
1457
|
+
);
|
|
1458
|
+
};
|
|
1425
1459
|
}
|
|
1426
1460
|
|
|
1427
1461
|
// src/vite/utils/ast.ts
|
|
@@ -1480,18 +1514,32 @@ function getViteSSRExportIdentifiers(astProgramNode, exportObjectName = "__vite_
|
|
|
1480
1514
|
return result;
|
|
1481
1515
|
}
|
|
1482
1516
|
|
|
1517
|
+
// src/vite/utils/config.ts
|
|
1518
|
+
var PluginConfigKey = "__MARKO_RUN_PLUGIN_CONFIG__";
|
|
1519
|
+
var AdapterConfigKey = "__MARKO_RUN_ADAPTER_CONFIG__";
|
|
1520
|
+
function getConfig(obj, key) {
|
|
1521
|
+
return obj[key];
|
|
1522
|
+
}
|
|
1523
|
+
function setConfig(obj, key, value) {
|
|
1524
|
+
obj[key] = value;
|
|
1525
|
+
return obj;
|
|
1526
|
+
}
|
|
1527
|
+
var getExternalPluginOptions = (viteConfig) => getConfig(viteConfig, PluginConfigKey);
|
|
1528
|
+
var setExternalPluginOptions = (viteConfig, value) => setConfig(viteConfig, PluginConfigKey, value);
|
|
1529
|
+
var getExternalAdapterOptions = (viteConfig) => getConfig(viteConfig, AdapterConfigKey);
|
|
1530
|
+
|
|
1483
1531
|
// src/vite/utils/log.ts
|
|
1484
1532
|
import zlib from "node:zlib";
|
|
1533
|
+
import { Blob } from "buffer";
|
|
1485
1534
|
import Table from "cli-table3";
|
|
1486
|
-
import kleur from "kleur";
|
|
1487
1535
|
import format from "human-format";
|
|
1488
|
-
import
|
|
1536
|
+
import kleur2 from "kleur";
|
|
1489
1537
|
var HttpVerbColors = {
|
|
1490
|
-
get:
|
|
1491
|
-
post:
|
|
1492
|
-
put:
|
|
1493
|
-
delete:
|
|
1494
|
-
other:
|
|
1538
|
+
get: kleur2.green,
|
|
1539
|
+
post: kleur2.magenta,
|
|
1540
|
+
put: kleur2.cyan,
|
|
1541
|
+
delete: kleur2.red,
|
|
1542
|
+
other: kleur2.white
|
|
1495
1543
|
};
|
|
1496
1544
|
var HttpVerbOrder = {
|
|
1497
1545
|
get: 0,
|
|
@@ -1518,7 +1566,7 @@ function logRoutesTable(routes, bundle, options) {
|
|
|
1518
1566
|
headings.push("Size/GZip");
|
|
1519
1567
|
colAligns.push("right");
|
|
1520
1568
|
const table = new Table({
|
|
1521
|
-
head: headings.map((title) =>
|
|
1569
|
+
head: headings.map((title) => kleur2.bold(kleur2.white(title.toUpperCase()))),
|
|
1522
1570
|
wordWrap: true,
|
|
1523
1571
|
colAligns,
|
|
1524
1572
|
style: { compact: true }
|
|
@@ -1533,14 +1581,14 @@ function logRoutesTable(routes, bundle, options) {
|
|
|
1533
1581
|
let size = "";
|
|
1534
1582
|
const entryType = [];
|
|
1535
1583
|
if (route.handler) {
|
|
1536
|
-
entryType.push(
|
|
1584
|
+
entryType.push(kleur2.blue("handler"));
|
|
1537
1585
|
}
|
|
1538
1586
|
if (verb === "get" && route.page) {
|
|
1539
|
-
entryType.push(
|
|
1587
|
+
entryType.push(kleur2.yellow("page"));
|
|
1540
1588
|
size = prettySize(computeRouteSize(getRouteChunkName(route), bundle));
|
|
1541
1589
|
}
|
|
1542
1590
|
const row = [
|
|
1543
|
-
|
|
1591
|
+
kleur2.bold(HttpVerbColors[verb](verb.toUpperCase()))
|
|
1544
1592
|
];
|
|
1545
1593
|
if (verbs.length === 1 || firstRow) {
|
|
1546
1594
|
row.push({ rowSpan: verbs.length, content: prettyPath(path5.path) });
|
|
@@ -1555,7 +1603,7 @@ function logRoutesTable(routes, bundle, options) {
|
|
|
1555
1603
|
}
|
|
1556
1604
|
}
|
|
1557
1605
|
for (const [key, route] of Object.entries(routes.special).sort()) {
|
|
1558
|
-
const row = [
|
|
1606
|
+
const row = [kleur2.bold(kleur2.white("*")), key, kleur2.yellow("page")];
|
|
1559
1607
|
hasMiddleware && row.push("");
|
|
1560
1608
|
hasMeta && row.push("");
|
|
1561
1609
|
row.push(prettySize(computeRouteSize(getRouteChunkName(route), bundle)));
|
|
@@ -1594,41 +1642,24 @@ function computeChunkSize(chunk, bundle, seen = /* @__PURE__ */ new Set()) {
|
|
|
1594
1642
|
}
|
|
1595
1643
|
function prettySize([bytes, compBytes]) {
|
|
1596
1644
|
if (bytes <= 0) {
|
|
1597
|
-
return
|
|
1645
|
+
return kleur2.gray("0.0 kB");
|
|
1598
1646
|
}
|
|
1599
1647
|
const [size, prefix] = format(bytes, { decimals: 1 }).split(/\s+/);
|
|
1600
1648
|
const compSize = format(compBytes, { decimals: 1, prefix, unit: "B" });
|
|
1601
|
-
let str =
|
|
1602
|
-
if (compBytes < 20 * 1e3) str +=
|
|
1603
|
-
else if (compBytes < 50 * 1e3) str +=
|
|
1604
|
-
else str +=
|
|
1649
|
+
let str = kleur2.white(size) + kleur2.gray("/");
|
|
1650
|
+
if (compBytes < 20 * 1e3) str += kleur2.green(compSize);
|
|
1651
|
+
else if (compBytes < 50 * 1e3) str += kleur2.yellow(compSize);
|
|
1652
|
+
else str += kleur2.bold(kleur2.red(compSize));
|
|
1605
1653
|
return str;
|
|
1606
1654
|
}
|
|
1607
1655
|
function prettyPath(path5) {
|
|
1608
|
-
return path5.replace(/\/\$\$(.*)$/, (_, p) => "/" +
|
|
1609
|
-
}
|
|
1610
|
-
|
|
1611
|
-
// src/vite/utils/config.ts
|
|
1612
|
-
var PluginConfigKey = "__MARKO_RUN_PLUGIN_CONFIG__";
|
|
1613
|
-
var AdapterConfigKey = "__MARKO_RUN_ADAPTER_CONFIG__";
|
|
1614
|
-
function getConfig(obj, key) {
|
|
1615
|
-
return obj[key];
|
|
1616
|
-
}
|
|
1617
|
-
function setConfig(obj, key, value) {
|
|
1618
|
-
obj[key] = value;
|
|
1619
|
-
return obj;
|
|
1656
|
+
return path5.replace(/\/\$\$(.*)$/, (_, p) => "/" + kleur2.bold(kleur2.dim(`*${p}`))).replace(/\/\$([^/]+)/g, (_, p) => "/" + kleur2.bold(kleur2.dim(`:${p}`)));
|
|
1620
1657
|
}
|
|
1621
|
-
var getExternalPluginOptions = (viteConfig) => getConfig(viteConfig, PluginConfigKey);
|
|
1622
|
-
var setExternalPluginOptions = (viteConfig, value) => setConfig(viteConfig, PluginConfigKey, value);
|
|
1623
|
-
var getExternalAdapterOptions = (viteConfig) => getConfig(viteConfig, AdapterConfigKey);
|
|
1624
|
-
|
|
1625
|
-
// src/vite/plugin.ts
|
|
1626
|
-
import createDebug from "debug";
|
|
1627
1658
|
|
|
1628
1659
|
// src/vite/utils/read-once-persisted-store.ts
|
|
1660
|
+
import { promises as fs2 } from "fs";
|
|
1629
1661
|
import os from "os";
|
|
1630
1662
|
import path3 from "path";
|
|
1631
|
-
import { promises as fs2 } from "fs";
|
|
1632
1663
|
var noop = () => {
|
|
1633
1664
|
};
|
|
1634
1665
|
var tmpFile = path3.join(os.tmpdir(), "marko-run-storage.json");
|
|
@@ -1671,33 +1702,7 @@ process.once("beforeExit", (code) => {
|
|
|
1671
1702
|
}
|
|
1672
1703
|
});
|
|
1673
1704
|
|
|
1674
|
-
// src/adapter/utils.ts
|
|
1675
|
-
import supporsColor from "supports-color";
|
|
1676
|
-
import kleur2 from "kleur";
|
|
1677
|
-
function stripAnsi(string) {
|
|
1678
|
-
return string.replace(
|
|
1679
|
-
/([\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><])/g,
|
|
1680
|
-
""
|
|
1681
|
-
);
|
|
1682
|
-
}
|
|
1683
|
-
function cleanStack(stack) {
|
|
1684
|
-
return stack.split(/\n/).filter((l) => /^\s*at/.test(l)).join("\n");
|
|
1685
|
-
}
|
|
1686
|
-
function prepareError(err) {
|
|
1687
|
-
var _a;
|
|
1688
|
-
return {
|
|
1689
|
-
message: stripAnsi(err.message),
|
|
1690
|
-
stack: stripAnsi(cleanStack(err.stack || "")),
|
|
1691
|
-
id: err.id,
|
|
1692
|
-
frame: stripAnsi(err.frame || ""),
|
|
1693
|
-
plugin: err.plugin,
|
|
1694
|
-
pluginCode: (_a = err.pluginCode) == null ? void 0 : _a.toString(),
|
|
1695
|
-
loc: err.loc
|
|
1696
|
-
};
|
|
1697
|
-
}
|
|
1698
|
-
|
|
1699
1705
|
// src/vite/plugin.ts
|
|
1700
|
-
import { createHash } from "crypto";
|
|
1701
1706
|
var debug = createDebug("@marko/run");
|
|
1702
1707
|
var __dirname = path4.dirname(fileURLToPath(import.meta.url));
|
|
1703
1708
|
var PLUGIN_NAME_PREFIX = "marko-run-vite";
|
|
@@ -1729,7 +1734,7 @@ function markoRun(opts = {}) {
|
|
|
1729
1734
|
let getExportsFromFile;
|
|
1730
1735
|
let resolvedConfig;
|
|
1731
1736
|
let typesFile;
|
|
1732
|
-
|
|
1737
|
+
const seenErrors = /* @__PURE__ */ new Set();
|
|
1733
1738
|
const virtualFiles = /* @__PURE__ */ new Map();
|
|
1734
1739
|
let times = {
|
|
1735
1740
|
routesBuild: 0,
|
|
@@ -1754,32 +1759,28 @@ function markoRun(opts = {}) {
|
|
|
1754
1759
|
}
|
|
1755
1760
|
let buildVirtualFilesResult;
|
|
1756
1761
|
function buildVirtualFiles() {
|
|
1757
|
-
return buildVirtualFilesResult ?? (buildVirtualFilesResult =
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
virtualFiles.set(path4.posix.join(root, MIDDLEWARE_FILENAME), "");
|
|
1772
|
-
}
|
|
1773
|
-
virtualFiles.set(path4.posix.join(root, ROUTER_FILENAME), "");
|
|
1774
|
-
resolve(routes);
|
|
1775
|
-
} catch (err) {
|
|
1776
|
-
reject(err);
|
|
1762
|
+
return buildVirtualFilesResult ?? (buildVirtualFilesResult = (async () => {
|
|
1763
|
+
virtualFiles.clear();
|
|
1764
|
+
routes = await buildRoutes({
|
|
1765
|
+
walker: createFSWalker(resolvedRoutesDir),
|
|
1766
|
+
importPrefix: routesDir
|
|
1767
|
+
});
|
|
1768
|
+
if (!routes.list.length) {
|
|
1769
|
+
throw new Error("No routes generated");
|
|
1770
|
+
}
|
|
1771
|
+
for (const route of routes.list) {
|
|
1772
|
+
virtualFiles.set(path4.posix.join(root, `${route.entryName}.js`), "");
|
|
1773
|
+
}
|
|
1774
|
+
if (routes.middleware.length) {
|
|
1775
|
+
virtualFiles.set(path4.posix.join(root, MIDDLEWARE_FILENAME), "");
|
|
1777
1776
|
}
|
|
1778
|
-
|
|
1777
|
+
virtualFiles.set(path4.posix.join(root, ROUTER_FILENAME), "");
|
|
1778
|
+
return routes;
|
|
1779
|
+
})());
|
|
1779
1780
|
}
|
|
1780
1781
|
let renderVirtualFilesResult;
|
|
1781
1782
|
function renderVirtualFiles(context) {
|
|
1782
|
-
return renderVirtualFilesResult ?? (renderVirtualFilesResult =
|
|
1783
|
+
return renderVirtualFilesResult ?? (renderVirtualFilesResult = (async () => {
|
|
1783
1784
|
var _a;
|
|
1784
1785
|
try {
|
|
1785
1786
|
const routes2 = await buildVirtualFiles();
|
|
@@ -1787,32 +1788,40 @@ function markoRun(opts = {}) {
|
|
|
1787
1788
|
fs3.rmSync(entryFilesDir, { recursive: true });
|
|
1788
1789
|
}
|
|
1789
1790
|
for (const route of routes2.list) {
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
);
|
|
1795
|
-
route.handler.verbs = [];
|
|
1791
|
+
const { handler, page, layouts } = route;
|
|
1792
|
+
if (handler) {
|
|
1793
|
+
const exports = await getExportsFromFile(context, handler.filePath);
|
|
1794
|
+
handler.verbs = [];
|
|
1796
1795
|
for (const name of exports) {
|
|
1797
1796
|
const verb = name.toLowerCase();
|
|
1798
1797
|
if (name === verb.toUpperCase() && httpVerbs.includes(verb)) {
|
|
1799
|
-
|
|
1798
|
+
handler.verbs.push(verb);
|
|
1800
1799
|
}
|
|
1801
1800
|
}
|
|
1802
|
-
if (!
|
|
1801
|
+
if (!handler.verbs.length) {
|
|
1803
1802
|
context.warn(
|
|
1804
|
-
`Did not find any http verb exports in handler '${path4.relative(root,
|
|
1803
|
+
`Did not find any http verb exports in handler '${path4.relative(root, handler.filePath)}' - expected ${httpVerbs.map((v) => v.toUpperCase()).join(", ")}`
|
|
1805
1804
|
);
|
|
1806
1805
|
}
|
|
1807
1806
|
}
|
|
1808
|
-
if (
|
|
1809
|
-
const relativePath = path4.relative(
|
|
1807
|
+
if (page && layouts.length) {
|
|
1808
|
+
const relativePath = path4.relative(
|
|
1809
|
+
resolvedRoutesDir,
|
|
1810
|
+
page.filePath
|
|
1811
|
+
);
|
|
1810
1812
|
const routeFileDir = path4.join(entryFilesDir, relativePath, "..");
|
|
1811
|
-
const routeFileRelativePathPosix = normalizePath(
|
|
1813
|
+
const routeFileRelativePathPosix = normalizePath(
|
|
1814
|
+
path4.relative(routeFileDir, root)
|
|
1815
|
+
);
|
|
1812
1816
|
fs3.mkdirSync(routeFileDir, { recursive: true });
|
|
1817
|
+
const pageNameIndex = page.name.indexOf("+page");
|
|
1818
|
+
const pageNamePrefix = pageNameIndex > 0 ? `${page.name.slice(0, pageNameIndex)}.` : "";
|
|
1813
1819
|
fs3.writeFileSync(
|
|
1814
|
-
path4.join(routeFileDir, "route.marko"),
|
|
1815
|
-
renderRouteTemplate(
|
|
1820
|
+
path4.join(routeFileDir, pageNamePrefix + "route.marko"),
|
|
1821
|
+
renderRouteTemplate(
|
|
1822
|
+
route,
|
|
1823
|
+
(to) => path4.posix.join(routeFileRelativePathPosix, to)
|
|
1824
|
+
)
|
|
1816
1825
|
);
|
|
1817
1826
|
}
|
|
1818
1827
|
virtualFiles.set(
|
|
@@ -1821,14 +1830,23 @@ function markoRun(opts = {}) {
|
|
|
1821
1830
|
);
|
|
1822
1831
|
}
|
|
1823
1832
|
for (const route of Object.values(routes2.special)) {
|
|
1824
|
-
|
|
1825
|
-
|
|
1833
|
+
const { page, layouts, key } = route;
|
|
1834
|
+
if (page && layouts.length) {
|
|
1835
|
+
const relativePath = path4.relative(
|
|
1836
|
+
resolvedRoutesDir,
|
|
1837
|
+
page.filePath
|
|
1838
|
+
);
|
|
1826
1839
|
const routeFileDir = path4.join(entryFilesDir, relativePath, "..");
|
|
1827
|
-
const routeFileRelativePathPosix = normalizePath(
|
|
1840
|
+
const routeFileRelativePathPosix = normalizePath(
|
|
1841
|
+
path4.relative(routeFileDir, root)
|
|
1842
|
+
);
|
|
1828
1843
|
fs3.mkdirSync(routeFileDir, { recursive: true });
|
|
1829
1844
|
fs3.writeFileSync(
|
|
1830
|
-
path4.join(routeFileDir, `route.${
|
|
1831
|
-
renderRouteTemplate(
|
|
1845
|
+
path4.join(routeFileDir, `route.${key}.marko`),
|
|
1846
|
+
renderRouteTemplate(
|
|
1847
|
+
route,
|
|
1848
|
+
(to) => path4.posix.join(routeFileRelativePathPosix, to)
|
|
1849
|
+
)
|
|
1832
1850
|
);
|
|
1833
1851
|
}
|
|
1834
1852
|
}
|
|
@@ -1874,8 +1892,7 @@ function markoRun(opts = {}) {
|
|
|
1874
1892
|
`throw ${JSON.stringify(prepareError(err))}`
|
|
1875
1893
|
);
|
|
1876
1894
|
}
|
|
1877
|
-
|
|
1878
|
-
}));
|
|
1895
|
+
})());
|
|
1879
1896
|
}
|
|
1880
1897
|
return [
|
|
1881
1898
|
defaultConfigPlugin,
|
|
@@ -1920,7 +1937,9 @@ function markoRun(opts = {}) {
|
|
|
1920
1937
|
createHash("shake256", { outputLength: 4 }).update(root).digest("hex")
|
|
1921
1938
|
);
|
|
1922
1939
|
entryFilesDirPosix = normalizePath(entryFilesDir);
|
|
1923
|
-
relativeEntryFilesDirPosix = normalizePath(
|
|
1940
|
+
relativeEntryFilesDirPosix = normalizePath(
|
|
1941
|
+
path4.relative(root, entryFilesDir)
|
|
1942
|
+
);
|
|
1924
1943
|
typesDir = path4.join(root, ".marko-run");
|
|
1925
1944
|
devEntryFile = path4.join(root, "index.html");
|
|
1926
1945
|
devEntryFilePosix = normalizePath(devEntryFile);
|
|
@@ -1941,7 +1960,7 @@ function markoRun(opts = {}) {
|
|
|
1941
1960
|
entryFileNames(info) {
|
|
1942
1961
|
let name = getEntryFileName(info.facadeModuleId);
|
|
1943
1962
|
if (!name) {
|
|
1944
|
-
for (
|
|
1963
|
+
for (const id of info.moduleIds) {
|
|
1945
1964
|
name = getEntryFileName(id);
|
|
1946
1965
|
if (name) {
|
|
1947
1966
|
break;
|
|
@@ -2106,6 +2125,7 @@ function markoRun(opts = {}) {
|
|
|
2106
2125
|
},
|
|
2107
2126
|
async resolveId(importee, importer) {
|
|
2108
2127
|
if (importee === "@marko/run/router") {
|
|
2128
|
+
console.log("plugin resolveId router");
|
|
2109
2129
|
return path4.resolve(root, ROUTER_FILENAME);
|
|
2110
2130
|
} else if (importee.endsWith(".marko") && importee.includes(relativeEntryFilesDirPosix)) {
|
|
2111
2131
|
if (!importee.startsWith(root)) {
|
|
@@ -2246,7 +2266,10 @@ async function resolveAdapter(root, options, log) {
|
|
|
2246
2266
|
for (const name of dependecies) {
|
|
2247
2267
|
if (name.startsWith("@marko/run-adapter") || name.indexOf("marko-run-adapter") !== -1) {
|
|
2248
2268
|
try {
|
|
2249
|
-
const module2 = await import(
|
|
2269
|
+
const module2 = await import(
|
|
2270
|
+
/* @vite-ignore */
|
|
2271
|
+
name
|
|
2272
|
+
);
|
|
2250
2273
|
log && debug(
|
|
2251
2274
|
`Using adapter ${name} listed in your package.json dependecies`
|
|
2252
2275
|
);
|
|
@@ -2258,7 +2281,10 @@ async function resolveAdapter(root, options, log) {
|
|
|
2258
2281
|
}
|
|
2259
2282
|
}
|
|
2260
2283
|
const defaultAdapter = "@marko/run/adapter";
|
|
2261
|
-
const module = await import(
|
|
2284
|
+
const module = await import(
|
|
2285
|
+
/* @vite-ignore */
|
|
2286
|
+
defaultAdapter
|
|
2287
|
+
);
|
|
2262
2288
|
log && debug("Using default adapter");
|
|
2263
2289
|
return module.default();
|
|
2264
2290
|
}
|
|
@@ -2302,11 +2328,11 @@ var defaultConfigPlugin = {
|
|
|
2302
2328
|
};
|
|
2303
2329
|
|
|
2304
2330
|
// src/vite/utils/server.ts
|
|
2305
|
-
import net from "net";
|
|
2306
2331
|
import cp from "child_process";
|
|
2307
|
-
import { parse, config } from "dotenv";
|
|
2308
|
-
import fs4 from "fs";
|
|
2309
2332
|
import cluster from "cluster";
|
|
2333
|
+
import { config, parse } from "dotenv";
|
|
2334
|
+
import fs4 from "fs";
|
|
2335
|
+
import net from "net";
|
|
2310
2336
|
async function parseEnv(envFile) {
|
|
2311
2337
|
if (fs4.existsSync(envFile)) {
|
|
2312
2338
|
const content = await fs4.promises.readFile(envFile, "utf8");
|