@marko/run 0.10.0 → 0.11.0-rc.2
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/dist/.tsbuildinfo +1 -1
- package/dist/adapter/index.cjs +5 -4
- package/dist/adapter/index.js +7 -4
- package/dist/cli/index.mjs +524 -167
- package/dist/runtime/client.cjs +65 -0
- package/dist/runtime/client.d.ts +1 -0
- package/dist/runtime/client.js +59 -0
- package/dist/runtime/index.d.ts +9 -4
- package/dist/runtime/internal.cjs +315 -28
- package/dist/runtime/internal.d.ts +9 -4
- package/dist/runtime/internal.js +311 -28
- package/dist/runtime/legacy-types.d.ts +60 -0
- package/dist/runtime/namespace.d.ts +2 -1
- package/dist/runtime/router.d.ts +1 -1
- package/dist/runtime/thenable.d.ts +11 -0
- package/dist/runtime/types.d.ts +411 -100
- package/dist/runtime/url-builder.cjs +96 -0
- package/dist/runtime/url-builder.d.ts +6 -0
- package/dist/runtime/url-builder.js +61 -0
- package/dist/vite/codegen/index.d.ts +1 -1
- package/dist/vite/constants.d.ts +3 -3
- package/dist/vite/index.cjs +522 -167
- package/dist/vite/index.js +524 -167
- package/dist/vite/utils/href-replace.d.ts +44 -0
- package/dist/vite/utils/meta-data.d.ts +2 -2
- package/package.json +25 -23
package/dist/runtime/internal.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
// src/runtime/internal.ts
|
|
2
|
+
import { URLSearchParams as URLSearchParams2 } from "node:url";
|
|
3
|
+
import { parseFormData } from "@remix-run/form-data-parser";
|
|
4
|
+
|
|
1
5
|
// src/vite/constants.ts
|
|
2
6
|
var httpVerbs = [
|
|
3
7
|
"get",
|
|
@@ -9,6 +13,83 @@ var httpVerbs = [
|
|
|
9
13
|
"options"
|
|
10
14
|
];
|
|
11
15
|
|
|
16
|
+
// src/runtime/thenable.ts
|
|
17
|
+
var kPromise = /* @__PURE__ */ Symbol("promise");
|
|
18
|
+
var kReadFn = /* @__PURE__ */ Symbol("read fn");
|
|
19
|
+
function thenFn(resolve, reject) {
|
|
20
|
+
return (this[kPromise] || (this[kPromise] = this[kReadFn]())).then(resolve, reject);
|
|
21
|
+
}
|
|
22
|
+
function catchFn(reject) {
|
|
23
|
+
return (this[kPromise] || (this[kPromise] = this[kReadFn]())).catch(reject);
|
|
24
|
+
}
|
|
25
|
+
function finallyFn(resolve) {
|
|
26
|
+
return (this[kPromise] || (this[kPromise] = this[kReadFn]())).finally(resolve);
|
|
27
|
+
}
|
|
28
|
+
function thenable(fn) {
|
|
29
|
+
return {
|
|
30
|
+
[kPromise]: null,
|
|
31
|
+
[kReadFn]: fn,
|
|
32
|
+
then: thenFn,
|
|
33
|
+
catch: catchFn,
|
|
34
|
+
finally: finallyFn
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// src/runtime/url-builder.ts
|
|
39
|
+
var encode = encodeURIComponent;
|
|
40
|
+
var pathParts = /* @__PURE__ */ new Map();
|
|
41
|
+
function parsePathParts(path) {
|
|
42
|
+
let parts = pathParts.get(path);
|
|
43
|
+
if (!parts) {
|
|
44
|
+
let lastEnd = 0;
|
|
45
|
+
let paramStart;
|
|
46
|
+
pathParts.set(path, parts = [[]]);
|
|
47
|
+
while (lastEnd >= 0 && (paramStart = path.indexOf("/$", lastEnd) + 1)) {
|
|
48
|
+
parts.push(path.slice(lastEnd, paramStart++));
|
|
49
|
+
if (path.charAt(paramStart) === "$") {
|
|
50
|
+
paramStart++;
|
|
51
|
+
lastEnd = -1;
|
|
52
|
+
} else {
|
|
53
|
+
lastEnd = path.indexOf("/", paramStart);
|
|
54
|
+
}
|
|
55
|
+
parts[0].push(path.slice(paramStart, lastEnd < 0 ? void 0 : lastEnd));
|
|
56
|
+
}
|
|
57
|
+
parts.push(lastEnd >= 0 ? path.slice(lastEnd) : "");
|
|
58
|
+
}
|
|
59
|
+
return parts;
|
|
60
|
+
}
|
|
61
|
+
function joinHref(path, options) {
|
|
62
|
+
let result = path;
|
|
63
|
+
if (options.search) {
|
|
64
|
+
const query = "" + new URLSearchParams(options.search);
|
|
65
|
+
if (query) result += "?" + query;
|
|
66
|
+
}
|
|
67
|
+
if (options.hash) result += "#" + encode(options.hash);
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
function href(path, ...[options]) {
|
|
71
|
+
return options ? "params" in options ? ((parts) => href_keys(parts, options, ...parts[0]))(
|
|
72
|
+
parsePathParts(path)
|
|
73
|
+
) : joinHref(path, options) : path;
|
|
74
|
+
}
|
|
75
|
+
function href_path(strings, ...params) {
|
|
76
|
+
let i = 0;
|
|
77
|
+
let j = 0;
|
|
78
|
+
let result = strings[i++];
|
|
79
|
+
if (!result || Array.isArray(result)) result = strings[i++];
|
|
80
|
+
while (i < strings.length) {
|
|
81
|
+
const param = params[j++];
|
|
82
|
+
result += (Array.isArray(param) ? param.map(encode).join("/") : encode(param)) + strings[i++];
|
|
83
|
+
}
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
86
|
+
function href_values(strings, options, ...params) {
|
|
87
|
+
return joinHref(href_path(strings, ...params), options);
|
|
88
|
+
}
|
|
89
|
+
function href_keys(strings, options, ...keys) {
|
|
90
|
+
return href_values(strings, options, ...keys.map((k) => options.params[k]));
|
|
91
|
+
}
|
|
92
|
+
|
|
12
93
|
// src/vite/utils/meta-data.ts
|
|
13
94
|
var verbKeys = new Set(httpVerbs.map((v) => v.toUpperCase()));
|
|
14
95
|
function isObject(obj) {
|
|
@@ -56,10 +137,17 @@ var pageResponseInit = {
|
|
|
56
137
|
};
|
|
57
138
|
globalThis.MarkoRun ?? (globalThis.MarkoRun = {
|
|
58
139
|
NotHandled,
|
|
59
|
-
NotMatched
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
140
|
+
NotMatched
|
|
141
|
+
});
|
|
142
|
+
globalThis.Run ?? (globalThis.Run = {
|
|
143
|
+
href,
|
|
144
|
+
ALL: createDefineHandler("ALL"),
|
|
145
|
+
...Object.fromEntries(
|
|
146
|
+
httpVerbs.map((v) => {
|
|
147
|
+
const verb = v.toUpperCase();
|
|
148
|
+
return [v.toUpperCase(), createDefineHandler(verb)];
|
|
149
|
+
})
|
|
150
|
+
)
|
|
63
151
|
});
|
|
64
152
|
var toReadable = (rendered) => {
|
|
65
153
|
toReadable = rendered.toReadable ? (rendered2) => rendered2.toReadable() : (rendered2) => {
|
|
@@ -88,27 +176,98 @@ var toReadable = (rendered) => {
|
|
|
88
176
|
};
|
|
89
177
|
return toReadable(rendered);
|
|
90
178
|
};
|
|
91
|
-
function
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
meta = route.meta;
|
|
97
|
-
params = route.params;
|
|
98
|
-
path = route.path;
|
|
99
|
-
} else {
|
|
100
|
-
meta = {};
|
|
101
|
-
params = {};
|
|
102
|
-
path = "";
|
|
179
|
+
function searchParamsToObject(params) {
|
|
180
|
+
const obj = {};
|
|
181
|
+
for (const [key, value] of params) {
|
|
182
|
+
const prev = obj[key];
|
|
183
|
+
obj[key] = prev ? Array.isArray(prev) ? [...prev, value] : [prev, value] : value;
|
|
103
184
|
}
|
|
104
|
-
return
|
|
105
|
-
|
|
185
|
+
return obj;
|
|
186
|
+
}
|
|
187
|
+
async function readBodyWithLimit(request, maxBytes) {
|
|
188
|
+
if (maxBytes < 0) {
|
|
189
|
+
return await request.text();
|
|
190
|
+
}
|
|
191
|
+
const contentLength = request.headers.get("content-length");
|
|
192
|
+
if (contentLength !== null && Number(contentLength) > maxBytes) {
|
|
193
|
+
throw new Error("Request body too large");
|
|
194
|
+
}
|
|
195
|
+
if (!request.body) {
|
|
196
|
+
throw new Error("Missing request body");
|
|
197
|
+
}
|
|
198
|
+
const reader = request.body.getReader();
|
|
199
|
+
const bytes = new Uint8Array(maxBytes);
|
|
200
|
+
let receivedBytes = 0;
|
|
201
|
+
try {
|
|
202
|
+
while (true) {
|
|
203
|
+
const { done, value } = await reader.read();
|
|
204
|
+
if (done) break;
|
|
205
|
+
if (receivedBytes + value.byteLength > maxBytes) {
|
|
206
|
+
await reader.cancel();
|
|
207
|
+
throw new Error("Request body too large");
|
|
208
|
+
}
|
|
209
|
+
bytes.set(value, receivedBytes);
|
|
210
|
+
receivedBytes += value.byteLength;
|
|
211
|
+
}
|
|
212
|
+
} finally {
|
|
213
|
+
reader.releaseLock();
|
|
214
|
+
}
|
|
215
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(
|
|
216
|
+
bytes.subarray(0, receivedBytes)
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
async function readBody(route, context) {
|
|
220
|
+
const { request } = context;
|
|
221
|
+
const contentType = request.headers.get("Content-Type");
|
|
222
|
+
if (contentType == null ? void 0 : contentType.includes("application/json")) {
|
|
223
|
+
const { maxBytes: maxBytes2, validator: validator2 } = route.options.json;
|
|
224
|
+
const json = maxBytes2 < 0 ? await request.json() : JSON.parse(await readBodyWithLimit(request, maxBytes2));
|
|
225
|
+
return validator2 ? validator2(json) : json;
|
|
226
|
+
}
|
|
227
|
+
const { maxBytes, maxParts, maxFiles, maxFileBytes, onFile, validator } = route.options.form;
|
|
228
|
+
const data = searchParamsToObject(
|
|
229
|
+
(contentType == null ? void 0 : contentType.includes("multipart/form-data")) ? await parseFormData(
|
|
230
|
+
request,
|
|
231
|
+
{
|
|
232
|
+
maxParts,
|
|
233
|
+
maxFiles,
|
|
234
|
+
maxFileSize: maxFileBytes,
|
|
235
|
+
maxTotalSize: maxBytes
|
|
236
|
+
},
|
|
237
|
+
onFile ? (file) => onFile(context, file) : void 0
|
|
238
|
+
) : new URLSearchParams2(await readBodyWithLimit(request, maxBytes))
|
|
239
|
+
);
|
|
240
|
+
return validator && validator(data);
|
|
241
|
+
}
|
|
242
|
+
function createContext(route, request, platform, url = new URL(request.url)) {
|
|
243
|
+
const context = {
|
|
244
|
+
route: (route == null ? void 0 : route.path) || "",
|
|
106
245
|
method: request.method,
|
|
246
|
+
meta: (route == null ? void 0 : route.meta) || {},
|
|
247
|
+
get params() {
|
|
248
|
+
const value = route ? route.options.params ? route.options.params(route.params) : route.params : {};
|
|
249
|
+
Object.defineProperty(context, "params", {
|
|
250
|
+
configurable: true,
|
|
251
|
+
enumerable: true,
|
|
252
|
+
value
|
|
253
|
+
});
|
|
254
|
+
return value;
|
|
255
|
+
},
|
|
256
|
+
get search() {
|
|
257
|
+
const search = searchParamsToObject(url.searchParams);
|
|
258
|
+
const value = (route == null ? void 0 : route.options.search) ? route.options.search(search) : search;
|
|
259
|
+
Object.defineProperty(context, "search", {
|
|
260
|
+
configurable: true,
|
|
261
|
+
enumerable: true,
|
|
262
|
+
value
|
|
263
|
+
});
|
|
264
|
+
return value;
|
|
265
|
+
},
|
|
266
|
+
body: route && request.body ? thenable(() => readBody(route, context)) : void 0,
|
|
267
|
+
data: {},
|
|
107
268
|
url,
|
|
269
|
+
request,
|
|
108
270
|
platform,
|
|
109
|
-
meta,
|
|
110
|
-
params,
|
|
111
|
-
route: path,
|
|
112
271
|
serializedGlobals,
|
|
113
272
|
parent: parentContextLookup.get(request),
|
|
114
273
|
async fetch(resource, init) {
|
|
@@ -150,16 +309,37 @@ function createContext(route, request, platform, url = new URL(request.url)) {
|
|
|
150
309
|
);
|
|
151
310
|
}
|
|
152
311
|
};
|
|
312
|
+
return context;
|
|
313
|
+
}
|
|
314
|
+
function render(context, template, input, data) {
|
|
315
|
+
if (data) {
|
|
316
|
+
Object.assign(context.data, data);
|
|
317
|
+
}
|
|
318
|
+
return context.render(template, input);
|
|
153
319
|
}
|
|
154
|
-
|
|
320
|
+
var handlerMethod = /* @__PURE__ */ new WeakMap();
|
|
321
|
+
async function call(handler, next, context, data) {
|
|
155
322
|
let response;
|
|
323
|
+
if (data) {
|
|
324
|
+
Object.assign(context.data, data);
|
|
325
|
+
}
|
|
326
|
+
let method = handlerMethod.get(handler);
|
|
327
|
+
if (method === void 0) {
|
|
328
|
+
handlerMethod.set(
|
|
329
|
+
handler,
|
|
330
|
+
method = "verb" in handler && handler.verb !== "ALL" ? handler.verb : false
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
if (method && method !== context.method) {
|
|
334
|
+
return next(data);
|
|
335
|
+
}
|
|
156
336
|
if (!process.env.NODE_ENV || process.env.NODE_ENV === "development") {
|
|
157
337
|
let nextCallCount = 0;
|
|
158
338
|
let didThrow = false;
|
|
159
339
|
try {
|
|
160
|
-
response = await handler(context, () => {
|
|
340
|
+
response = await handler(context, (d) => {
|
|
161
341
|
nextCallCount++;
|
|
162
|
-
return next();
|
|
342
|
+
return next(d);
|
|
163
343
|
});
|
|
164
344
|
} catch (error) {
|
|
165
345
|
didThrow = true;
|
|
@@ -193,19 +373,19 @@ async function call(handler, next, context) {
|
|
|
193
373
|
if (response === null || response === NotMatched || response === NotHandled) {
|
|
194
374
|
throw response || NotMatched;
|
|
195
375
|
}
|
|
196
|
-
return response || next();
|
|
376
|
+
return response || next(data);
|
|
197
377
|
}
|
|
198
378
|
function compose(handlers) {
|
|
199
379
|
const len = handlers.length;
|
|
200
380
|
if (!len) {
|
|
201
|
-
return
|
|
381
|
+
return passthroughHandler;
|
|
202
382
|
} else if (len === 1) {
|
|
203
383
|
return handlers[0];
|
|
204
384
|
}
|
|
205
385
|
return (context, next) => {
|
|
206
386
|
let i = 0;
|
|
207
|
-
return (function nextHandler() {
|
|
208
|
-
return i < len ? call(handlers[i++], nextHandler, context) : next();
|
|
387
|
+
return (function nextHandler(data) {
|
|
388
|
+
return i < len ? call(handlers[i++], nextHandler, context, data) : next(data);
|
|
209
389
|
})();
|
|
210
390
|
};
|
|
211
391
|
}
|
|
@@ -226,6 +406,104 @@ function normalizeHandler(obj) {
|
|
|
226
406
|
}
|
|
227
407
|
return passthrough;
|
|
228
408
|
}
|
|
409
|
+
function assertHandlerVerb(verb, handler) {
|
|
410
|
+
if ("verb" in handler && handler.verb !== verb) {
|
|
411
|
+
throw new Error(
|
|
412
|
+
`Expected verb ${verb} but handler was defined with Run.${handler.verb}`
|
|
413
|
+
);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
function createDefineHandler(verb) {
|
|
417
|
+
return (optionsOrHandlers, handlers) => {
|
|
418
|
+
let handler;
|
|
419
|
+
if (typeof optionsOrHandlers === "function") {
|
|
420
|
+
assertHandlerVerb(verb, optionsOrHandlers);
|
|
421
|
+
handler = optionsOrHandlers;
|
|
422
|
+
handler.options ?? (handler.options = {});
|
|
423
|
+
} else if (Array.isArray(optionsOrHandlers)) {
|
|
424
|
+
for (const h of optionsOrHandlers) assertHandlerVerb(verb, h);
|
|
425
|
+
handler = compose(optionsOrHandlers);
|
|
426
|
+
handler.options = mergeOptions(...optionsOrHandlers);
|
|
427
|
+
} else if (typeof handlers === "function") {
|
|
428
|
+
assertHandlerVerb(verb, handlers);
|
|
429
|
+
handler = handlers;
|
|
430
|
+
handler.options = mergeOptions(handlers, optionsOrHandlers);
|
|
431
|
+
} else if (Array.isArray(handlers)) {
|
|
432
|
+
for (const h of handlers) assertHandlerVerb(verb, h);
|
|
433
|
+
handler = compose(handlers);
|
|
434
|
+
handler.options = mergeOptions(...handlers, optionsOrHandlers);
|
|
435
|
+
} else {
|
|
436
|
+
handler = passthroughHandler;
|
|
437
|
+
handler.options = optionsOrHandlers;
|
|
438
|
+
}
|
|
439
|
+
handler.verb = verb;
|
|
440
|
+
return handler;
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
function normalizeValidator(validator) {
|
|
444
|
+
return validator && typeof validator !== "function" ? (input) => {
|
|
445
|
+
const result = validator["~standard"].validate(input);
|
|
446
|
+
if (result instanceof Promise) {
|
|
447
|
+
throw new TypeError("Schema validation must be synchronous");
|
|
448
|
+
}
|
|
449
|
+
return result.issues ? [input, result.issues] : [result.value, void 0];
|
|
450
|
+
} : validator;
|
|
451
|
+
}
|
|
452
|
+
var defaultMaxBytes = 1024 * 1024;
|
|
453
|
+
var defaultMaxParts = 1e3;
|
|
454
|
+
var defaultMaxFiles = 20;
|
|
455
|
+
function mergeOptions(...arr) {
|
|
456
|
+
const merged = {};
|
|
457
|
+
for (const item of arr) {
|
|
458
|
+
let options;
|
|
459
|
+
if (typeof item === "object") {
|
|
460
|
+
options = item;
|
|
461
|
+
} else if ("options" in item) {
|
|
462
|
+
options = item.options;
|
|
463
|
+
} else {
|
|
464
|
+
continue;
|
|
465
|
+
}
|
|
466
|
+
for (const k in options) {
|
|
467
|
+
const key = k;
|
|
468
|
+
const option = options[key];
|
|
469
|
+
if (typeof option === "object" && typeof merged[key] === "object") {
|
|
470
|
+
Object.assign(merged[key], option);
|
|
471
|
+
} else if (option) {
|
|
472
|
+
merged[key] = option;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
const result = {
|
|
477
|
+
params: normalizeValidator(merged.params),
|
|
478
|
+
search: normalizeValidator(merged.search)
|
|
479
|
+
};
|
|
480
|
+
if (merged.json) {
|
|
481
|
+
const { maxBytes = defaultMaxBytes, validator } = typeof merged.json === "function" || "~standard" in merged.json ? { validator: merged.json } : merged.json;
|
|
482
|
+
result.json = {
|
|
483
|
+
maxBytes,
|
|
484
|
+
validator: normalizeValidator(validator)
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
if (merged.form) {
|
|
488
|
+
const {
|
|
489
|
+
maxBytes,
|
|
490
|
+
maxFiles = defaultMaxFiles,
|
|
491
|
+
maxFileBytes = defaultMaxBytes,
|
|
492
|
+
maxParts = defaultMaxParts,
|
|
493
|
+
onFile,
|
|
494
|
+
validator
|
|
495
|
+
} = typeof merged.form === "function" || "~standard" in merged.form ? { validator: merged.form } : merged.form;
|
|
496
|
+
result.form = {
|
|
497
|
+
maxBytes: maxBytes ?? maxFiles * maxFileBytes,
|
|
498
|
+
maxFileBytes,
|
|
499
|
+
maxFiles,
|
|
500
|
+
maxParts,
|
|
501
|
+
onFile,
|
|
502
|
+
validator: normalizeValidator(validator)
|
|
503
|
+
};
|
|
504
|
+
}
|
|
505
|
+
return result;
|
|
506
|
+
}
|
|
229
507
|
function stripResponseBodySync(response) {
|
|
230
508
|
return response.body ? new Response(null, response) : response;
|
|
231
509
|
}
|
|
@@ -234,6 +512,7 @@ function stripResponseBody(response) {
|
|
|
234
512
|
}
|
|
235
513
|
function passthrough() {
|
|
236
514
|
}
|
|
515
|
+
var passthroughHandler = (_ctx, next) => next();
|
|
237
516
|
function noContent() {
|
|
238
517
|
return new Response(null, {
|
|
239
518
|
status: 204
|
|
@@ -248,15 +527,19 @@ function notMatched() {
|
|
|
248
527
|
export {
|
|
249
528
|
NotHandled,
|
|
250
529
|
NotMatched,
|
|
530
|
+
assertHandlerVerb,
|
|
251
531
|
call,
|
|
252
532
|
compose,
|
|
253
533
|
createContext,
|
|
534
|
+
mergeOptions,
|
|
254
535
|
noContent,
|
|
255
536
|
normalizeHandler,
|
|
256
537
|
getMetaDataLookup as normalizeMeta,
|
|
538
|
+
normalizeValidator,
|
|
257
539
|
notHandled,
|
|
258
540
|
notMatched,
|
|
259
541
|
passthrough,
|
|
542
|
+
render,
|
|
260
543
|
stripResponseBody,
|
|
261
544
|
stripResponseBodySync
|
|
262
545
|
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { AppPaths, Context, HttpVerb, NextFunction, NormalizedMeta, PathsForVerb, Route as NewRoute, RouteDef } from "./types";
|
|
2
|
+
type OneOrMany<T> = T | T[];
|
|
3
|
+
type NoParams = {};
|
|
4
|
+
type AllKeys<T> = T extends T ? keyof T : never;
|
|
5
|
+
type Simplify<T> = T extends unknown ? {
|
|
6
|
+
[K in keyof T]: T[K];
|
|
7
|
+
} : never;
|
|
8
|
+
type SuperSet<T, U extends T> = T & {
|
|
9
|
+
[K in AllKeys<U> as K extends keyof T ? never : K]?: never;
|
|
10
|
+
};
|
|
11
|
+
type SuperSets<T, U extends T, K extends keyof T> = Omit<T, K> & {
|
|
12
|
+
[P in K]: Simplify<SuperSet<T[P], U[P]>>;
|
|
13
|
+
};
|
|
14
|
+
type Union<T> = T[keyof T];
|
|
15
|
+
type MigrateContext<T extends Route> = Context<NewRoute<RouteDef<T["path"], T["method"], T["meta"]>>>;
|
|
16
|
+
export type Awaitable<T> = Promise<T> | T;
|
|
17
|
+
export type MultiRouteContext<TRoute extends Route, _Preserved extends TRoute = TRoute> = TRoute extends any ? MigrateContext<Simplify<SuperSets<TRoute, _Preserved, "params">>> : never;
|
|
18
|
+
export type ParamsObject = Record<string, string>;
|
|
19
|
+
export type InputObject = Record<PropertyKey, any>;
|
|
20
|
+
export type HandlerLike<TRoute extends Route = AnyRoute, Verb extends HttpVerb = HttpVerb> = Awaitable<OneOrMany<RouteHandler<TRoute, Verb>>>;
|
|
21
|
+
export type RouteHandlerResult = Response | typeof MarkoRun.NotHandled | typeof MarkoRun.NotMatched | null | void;
|
|
22
|
+
export type RouteHandler<TRoute extends Route = AnyRoute, Verb extends HttpVerb = HttpVerb> = (context: MultiRouteContext<Extract<TRoute, {
|
|
23
|
+
method: Verb;
|
|
24
|
+
}>>, next: NextFunction) => Awaitable<RouteHandlerResult>;
|
|
25
|
+
export interface Route<Params extends ParamsObject = ParamsObject, Meta = any, Path extends string = string, Verb extends HttpVerb = HttpVerb> {
|
|
26
|
+
path: Path;
|
|
27
|
+
params: Params;
|
|
28
|
+
meta: NormalizedMeta<Meta, Verb>;
|
|
29
|
+
method: Verb;
|
|
30
|
+
}
|
|
31
|
+
type Member<T, U> = T extends T ? (U extends T ? T : never) : never;
|
|
32
|
+
type PathParamKeys<Path extends string> = Path extends `${infer _}$${infer Param}/${infer Rest}` ? [Unescape<Param>, ...PathParamKeys<Rest>] : Path extends `${infer _}$$${infer Param}` ? [Unescape<Param>] : Path extends `${infer _}$${infer Param}` ? [Unescape<Param>] : [];
|
|
33
|
+
type Unescape<Escaped extends string> = Escaped extends `\`${infer Value}\`` ? Value : Escaped;
|
|
34
|
+
type PathParams<Path extends string, Keys extends string[] = PathParamKeys<Path>> = 0 extends Keys["length"] ? NoParams : {
|
|
35
|
+
[K in Keys[number]]: string;
|
|
36
|
+
};
|
|
37
|
+
type Segments<T extends string, Acc extends string[] = []> = T extends "" ? Acc : T extends `${infer Left}/${infer Rest}` ? Segments<Rest, [...Acc, Left]> : [...Acc, T];
|
|
38
|
+
type GTE<A extends any[], B extends any[]> = A["length"] extends B["length"] ? 1 : A extends [infer _Ha, ...infer Ta] ? B extends [infer _Hb, ...infer Tb] ? GTE<Ta, Tb> : 1 : 0;
|
|
39
|
+
type MatchSegments<A extends string, B extends string> = A extends `${infer P}/${string}*` ? 1 extends GTE<Segments<B>, Segments<P>> ? `${P}/${string}` : never : Segments<B>["length"] extends Segments<A>["length"] ? A : never;
|
|
40
|
+
type PathPattern<T extends string> = T extends `${infer Left}/\${${string}}/${infer Rest}` ? PathPattern<`${Left}/${string}/${Rest}`> : T extends `${infer Left}/\${...${string}}` ? PathPattern<`${Left}/${string}*`> : T extends `${infer Left}/\${${string}}` ? PathPattern<`${Left}/${string}`> : T;
|
|
41
|
+
type ValidatePath<Paths extends string, Path extends string> = Paths | (Path extends `/${string}` ? MatchSegments<Member<PathPattern<Paths>, Path>, Path> : Path);
|
|
42
|
+
type ValidateHref<Paths extends string, Href extends string> = Href extends `${infer P}#${infer H}?${infer Q}` ? `${ValidatePath<Paths, P>}#${H}?${Q}` : Href extends `${infer P}?${infer Q}` ? `${ValidatePath<Paths, P>}?${Q}` : Href extends `${infer P}#${infer H}` ? `${ValidatePath<Paths, P>}#${H}` : ValidatePath<Paths, Href>;
|
|
43
|
+
export interface AppData {
|
|
44
|
+
}
|
|
45
|
+
export type Routes = [AppPaths] extends [never] ? Record<string, Route> : {
|
|
46
|
+
[Path in keyof AppPaths]: Union<{
|
|
47
|
+
[V in HttpVerb]: Route<PathParams<Path>, V extends keyof AppPaths[Path]["verbs"] ? AppPaths[Path]["verbs"][V]["def"]["meta"] : {}, Path, V>;
|
|
48
|
+
}>;
|
|
49
|
+
};
|
|
50
|
+
export type AnyRoute = Routes[keyof Routes];
|
|
51
|
+
export type HandlerTypeFn<TRoute extends Route = AnyRoute> = [
|
|
52
|
+
AppPaths
|
|
53
|
+
] extends [never] ? <T extends HandlerLike<TRoute>>(handler: T) => T : <Params extends ParamsObject = ParamsObject, Meta = any, T extends HandlerLike<Route<Params, Meta>> = HandlerLike<Route<Params, Meta>>>(handler: T) => T;
|
|
54
|
+
export type GetPaths = PathsForVerb<"GET">;
|
|
55
|
+
export type PostPaths = PathsForVerb<"POST">;
|
|
56
|
+
export type GetablePath<T extends string> = ValidatePath<GetPaths, T>;
|
|
57
|
+
export type GetableHref<T extends string> = ValidateHref<GetPaths, T>;
|
|
58
|
+
export type PostablePath<T extends string> = ValidatePath<PostPaths, T>;
|
|
59
|
+
export type PostableHref<T extends string> = ValidateHref<PostPaths, T>;
|
|
60
|
+
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export declare const NotHandled: unique symbol;
|
|
2
2
|
export declare const NotMatched: unique symbol;
|
|
3
|
-
export type { GetableHref, GetablePath, GetPaths,
|
|
3
|
+
export type { GetableHref, GetablePath, GetPaths, PostableHref, PostablePath, PostPaths, } from "./legacy-types";
|
|
4
|
+
export type { Platform, HttpVerb as Verb } from "./types";
|
package/dist/runtime/router.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export declare const fetch: <TPlatform extends import("./types").Platform = import("./types").Platform>(request: Request, platform: TPlatform) => ReturnType<import("./types").Fetch<TPlatform>>;
|
|
2
2
|
export declare const match: import("./types").Match;
|
|
3
|
-
export declare const invoke: <TPlatform extends import("./types").Platform = import("./types").Platform>(route: import("./types").
|
|
3
|
+
export declare const invoke: <TPlatform extends import("./types").Platform = import("./types").Platform>(route: import("./types").RouteMatch<import("./types").Context<import("./types").Route<import("./types").RouteDef<string, import("./types").HttpVerb, any, Record<string, any>, [any]>, any>>> | null, request: Request, platform: TPlatform) => ReturnType<import("./types").Invoke<TPlatform>>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
declare const kPromise: unique symbol;
|
|
2
|
+
declare const kReadFn: unique symbol;
|
|
3
|
+
export interface Thenable<T = any> extends Promise<T> {
|
|
4
|
+
[kPromise]: null | Promise<T>;
|
|
5
|
+
[kReadFn]: () => Promise<T>;
|
|
6
|
+
then: Promise<T>["then"];
|
|
7
|
+
catch: Promise<T>["catch"];
|
|
8
|
+
finally: Promise<T>["finally"];
|
|
9
|
+
}
|
|
10
|
+
export default function thenable<T>(fn: () => Promise<T>): Thenable<T>;
|
|
11
|
+
export {};
|