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