@marko/run 0.9.7 → 0.11.0-rc.1
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 +7 -6
- package/dist/adapter/index.js +9 -6
- package/dist/adapter/middleware.cjs +2 -2
- package/dist/adapter/middleware.js +2 -2
- package/dist/adapter/utils.d.ts +4 -4
- package/dist/cli/index.mjs +580 -204
- 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 +285 -38
- package/dist/runtime/internal.d.ts +8 -4
- package/dist/runtime/internal.js +282 -38
- 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/types.d.ts +393 -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 +577 -203
- package/dist/vite/index.js +579 -203
- package/dist/vite/utils/href-replace.d.ts +44 -0
- package/dist/vite/utils/log.d.ts +1 -1
- package/dist/vite/utils/meta-data.d.ts +2 -2
- package/package.json +25 -35
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,61 @@ var httpVerbs = [
|
|
|
9
13
|
"options"
|
|
10
14
|
];
|
|
11
15
|
|
|
16
|
+
// src/runtime/url-builder.ts
|
|
17
|
+
var encode = encodeURIComponent;
|
|
18
|
+
var pathParts = /* @__PURE__ */ new Map();
|
|
19
|
+
function parsePathParts(path) {
|
|
20
|
+
let parts = pathParts.get(path);
|
|
21
|
+
if (!parts) {
|
|
22
|
+
let lastEnd = 0;
|
|
23
|
+
let paramStart;
|
|
24
|
+
pathParts.set(path, parts = [[]]);
|
|
25
|
+
while (lastEnd >= 0 && (paramStart = path.indexOf("/$", lastEnd) + 1)) {
|
|
26
|
+
parts.push(path.slice(lastEnd, paramStart++));
|
|
27
|
+
if (path.charAt(paramStart) === "$") {
|
|
28
|
+
paramStart++;
|
|
29
|
+
lastEnd = -1;
|
|
30
|
+
} else {
|
|
31
|
+
lastEnd = path.indexOf("/", paramStart);
|
|
32
|
+
}
|
|
33
|
+
parts[0].push(path.slice(paramStart, lastEnd < 0 ? void 0 : lastEnd));
|
|
34
|
+
}
|
|
35
|
+
parts.push(lastEnd >= 0 ? path.slice(lastEnd) : "");
|
|
36
|
+
}
|
|
37
|
+
return parts;
|
|
38
|
+
}
|
|
39
|
+
function joinHref(path, options) {
|
|
40
|
+
let result = path;
|
|
41
|
+
if (options.search) {
|
|
42
|
+
const query = "" + new URLSearchParams(options.search);
|
|
43
|
+
if (query) result += "?" + query;
|
|
44
|
+
}
|
|
45
|
+
if (options.hash) result += "#" + encode(options.hash);
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
function href(path, ...[options]) {
|
|
49
|
+
return options ? "params" in options ? ((parts) => href_keys(parts, options, ...parts[0]))(
|
|
50
|
+
parsePathParts(path)
|
|
51
|
+
) : joinHref(path, options) : path;
|
|
52
|
+
}
|
|
53
|
+
function href_path(strings, ...params) {
|
|
54
|
+
let i = 0;
|
|
55
|
+
let j = 0;
|
|
56
|
+
let result = strings[i++];
|
|
57
|
+
if (!result || Array.isArray(result)) result = strings[i++];
|
|
58
|
+
while (i < strings.length) {
|
|
59
|
+
const param = params[j++];
|
|
60
|
+
result += (Array.isArray(param) ? param.map(encode).join("/") : encode(param)) + strings[i++];
|
|
61
|
+
}
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
function href_values(strings, options, ...params) {
|
|
65
|
+
return joinHref(href_path(strings, ...params), options);
|
|
66
|
+
}
|
|
67
|
+
function href_keys(strings, options, ...keys) {
|
|
68
|
+
return href_values(strings, options, ...keys.map((k) => options.params[k]));
|
|
69
|
+
}
|
|
70
|
+
|
|
12
71
|
// src/vite/utils/meta-data.ts
|
|
13
72
|
var verbKeys = new Set(httpVerbs.map((v) => v.toUpperCase()));
|
|
14
73
|
function isObject(obj) {
|
|
@@ -42,10 +101,10 @@ function getMetaDataLookup(data) {
|
|
|
42
101
|
}
|
|
43
102
|
|
|
44
103
|
// src/runtime/internal.ts
|
|
45
|
-
var NotHandled = Symbol(
|
|
104
|
+
var NotHandled = /* @__PURE__ */ Symbol(
|
|
46
105
|
"marko-run not handled"
|
|
47
106
|
);
|
|
48
|
-
var NotMatched = Symbol(
|
|
107
|
+
var NotMatched = /* @__PURE__ */ Symbol(
|
|
49
108
|
"marko-run not matched"
|
|
50
109
|
);
|
|
51
110
|
var parentContextLookup = /* @__PURE__ */ new WeakMap();
|
|
@@ -56,11 +115,20 @@ var pageResponseInit = {
|
|
|
56
115
|
};
|
|
57
116
|
globalThis.MarkoRun ?? (globalThis.MarkoRun = {
|
|
58
117
|
NotHandled,
|
|
59
|
-
NotMatched
|
|
60
|
-
route(handler) {
|
|
61
|
-
return handler;
|
|
62
|
-
}
|
|
118
|
+
NotMatched
|
|
63
119
|
});
|
|
120
|
+
if (!globalThis.Run) {
|
|
121
|
+
const namespace = {
|
|
122
|
+
href
|
|
123
|
+
};
|
|
124
|
+
for (const v of [...httpVerbs, "all"]) {
|
|
125
|
+
const verb = v.toUpperCase();
|
|
126
|
+
const def = createDefineHandler();
|
|
127
|
+
def.href = href;
|
|
128
|
+
namespace[verb] = def;
|
|
129
|
+
}
|
|
130
|
+
globalThis.Run = namespace;
|
|
131
|
+
}
|
|
64
132
|
var toReadable = (rendered) => {
|
|
65
133
|
toReadable = rendered.toReadable ? (rendered2) => rendered2.toReadable() : (rendered2) => {
|
|
66
134
|
let cancelled = false;
|
|
@@ -88,39 +156,120 @@ var toReadable = (rendered) => {
|
|
|
88
156
|
};
|
|
89
157
|
return toReadable(rendered);
|
|
90
158
|
};
|
|
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 = "";
|
|
159
|
+
function searchParamsToObject(params) {
|
|
160
|
+
const obj = {};
|
|
161
|
+
for (const [key, value] of params) {
|
|
162
|
+
const prev = obj[key];
|
|
163
|
+
obj[key] = prev ? Array.isArray(prev) ? [...prev, value] : [prev, value] : value;
|
|
103
164
|
}
|
|
104
|
-
return
|
|
105
|
-
|
|
165
|
+
return obj;
|
|
166
|
+
}
|
|
167
|
+
async function readBodyWithLimit(request, maxBytes) {
|
|
168
|
+
if (maxBytes < 0) {
|
|
169
|
+
return await request.text();
|
|
170
|
+
}
|
|
171
|
+
const contentLength = request.headers.get("content-length");
|
|
172
|
+
if (contentLength !== null && Number(contentLength) > maxBytes) {
|
|
173
|
+
throw new Error("Request body too large");
|
|
174
|
+
}
|
|
175
|
+
if (!request.body) {
|
|
176
|
+
throw new Error("Missing request body");
|
|
177
|
+
}
|
|
178
|
+
const reader = request.body.getReader();
|
|
179
|
+
const bytes = new Uint8Array(maxBytes);
|
|
180
|
+
let receivedBytes = 0;
|
|
181
|
+
try {
|
|
182
|
+
while (true) {
|
|
183
|
+
const { done, value } = await reader.read();
|
|
184
|
+
if (done) break;
|
|
185
|
+
if (receivedBytes + value.byteLength > maxBytes) {
|
|
186
|
+
await reader.cancel();
|
|
187
|
+
throw new Error("Request body too large");
|
|
188
|
+
}
|
|
189
|
+
bytes.set(value, receivedBytes);
|
|
190
|
+
receivedBytes += value.byteLength;
|
|
191
|
+
}
|
|
192
|
+
} finally {
|
|
193
|
+
reader.releaseLock();
|
|
194
|
+
}
|
|
195
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(
|
|
196
|
+
bytes.subarray(0, receivedBytes)
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
function createContext(route, request, platform, url = new URL(request.url)) {
|
|
200
|
+
const context = {
|
|
201
|
+
route: (route == null ? void 0 : route.path) || "",
|
|
106
202
|
method: request.method,
|
|
203
|
+
meta: (route == null ? void 0 : route.meta) || {},
|
|
204
|
+
get params() {
|
|
205
|
+
const value = route ? route.options.params ? route.options.params(route.params) : route.params : {};
|
|
206
|
+
Object.defineProperty(context, "params", {
|
|
207
|
+
configurable: true,
|
|
208
|
+
enumerable: true,
|
|
209
|
+
value
|
|
210
|
+
});
|
|
211
|
+
return value;
|
|
212
|
+
},
|
|
213
|
+
get search() {
|
|
214
|
+
const search = searchParamsToObject(url.searchParams);
|
|
215
|
+
const value = (route == null ? void 0 : route.options.search) ? route.options.search(search) : search;
|
|
216
|
+
Object.defineProperty(context, "search", {
|
|
217
|
+
configurable: true,
|
|
218
|
+
enumerable: true,
|
|
219
|
+
value
|
|
220
|
+
});
|
|
221
|
+
return value;
|
|
222
|
+
},
|
|
223
|
+
body: route && request.body ? async () => {
|
|
224
|
+
const contentType = request.headers.get("Content-Type");
|
|
225
|
+
let value;
|
|
226
|
+
if (contentType == null ? void 0 : contentType.includes("application/json")) {
|
|
227
|
+
const { maxBytes, validator } = route.options.json;
|
|
228
|
+
const json = maxBytes < 0 ? await request.json() : JSON.parse(await readBodyWithLimit(request, maxBytes));
|
|
229
|
+
value = validator ? validator(json) : json;
|
|
230
|
+
} else {
|
|
231
|
+
const {
|
|
232
|
+
maxBytes,
|
|
233
|
+
maxParts,
|
|
234
|
+
maxFiles,
|
|
235
|
+
maxFileBytes,
|
|
236
|
+
onFile,
|
|
237
|
+
validator
|
|
238
|
+
} = route.options.form;
|
|
239
|
+
const data = searchParamsToObject(
|
|
240
|
+
(contentType == null ? void 0 : contentType.includes("multipart/form-data")) ? await parseFormData(
|
|
241
|
+
request,
|
|
242
|
+
{
|
|
243
|
+
maxParts,
|
|
244
|
+
maxFiles,
|
|
245
|
+
maxFileSize: maxFileBytes,
|
|
246
|
+
maxTotalSize: maxBytes
|
|
247
|
+
},
|
|
248
|
+
onFile ? (file) => onFile(context, file) : void 0
|
|
249
|
+
) : new URLSearchParams2(
|
|
250
|
+
await readBodyWithLimit(request, maxBytes)
|
|
251
|
+
)
|
|
252
|
+
);
|
|
253
|
+
value = validator ? validator(data) : validator;
|
|
254
|
+
}
|
|
255
|
+
Object.defineProperty(context, "body", {
|
|
256
|
+
configurable: true,
|
|
257
|
+
enumerable: true,
|
|
258
|
+
value
|
|
259
|
+
});
|
|
260
|
+
return value;
|
|
261
|
+
} : void 0,
|
|
262
|
+
data: {},
|
|
107
263
|
url,
|
|
264
|
+
request,
|
|
108
265
|
platform,
|
|
109
|
-
meta,
|
|
110
|
-
params,
|
|
111
|
-
route: path,
|
|
112
266
|
serializedGlobals,
|
|
113
267
|
parent: parentContextLookup.get(request),
|
|
114
268
|
async fetch(resource, init) {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
url2 = new URL(request2.url);
|
|
120
|
-
} else {
|
|
121
|
-
url2 = typeof resource === "string" ? new URL(resource, this.url) : resource;
|
|
122
|
-
request2 = new Request(url2, init);
|
|
123
|
-
}
|
|
269
|
+
const request2 = new Request(
|
|
270
|
+
typeof resource === "string" ? new URL(resource, this.url) : resource,
|
|
271
|
+
init
|
|
272
|
+
);
|
|
124
273
|
parentContextLookup.set(request2, this);
|
|
125
274
|
return await globalThis.__marko_run__.fetch(request2, this.platform) || new Response(null, { status: 404 });
|
|
126
275
|
},
|
|
@@ -155,16 +304,26 @@ function createContext(route, request, platform, url = new URL(request.url)) {
|
|
|
155
304
|
);
|
|
156
305
|
}
|
|
157
306
|
};
|
|
307
|
+
return context;
|
|
308
|
+
}
|
|
309
|
+
function render(context, template, input, data) {
|
|
310
|
+
if (data) {
|
|
311
|
+
Object.assign(context.data, data);
|
|
312
|
+
}
|
|
313
|
+
return context.render(template, input);
|
|
158
314
|
}
|
|
159
|
-
async function call(handler, next, context) {
|
|
315
|
+
async function call(handler, next, context, data) {
|
|
160
316
|
let response;
|
|
317
|
+
if (data) {
|
|
318
|
+
Object.assign(context.data, data);
|
|
319
|
+
}
|
|
161
320
|
if (!process.env.NODE_ENV || process.env.NODE_ENV === "development") {
|
|
162
321
|
let nextCallCount = 0;
|
|
163
322
|
let didThrow = false;
|
|
164
323
|
try {
|
|
165
|
-
response = await handler(context, () => {
|
|
324
|
+
response = await handler(context, (d) => {
|
|
166
325
|
nextCallCount++;
|
|
167
|
-
return next();
|
|
326
|
+
return next(d);
|
|
168
327
|
});
|
|
169
328
|
} catch (error) {
|
|
170
329
|
didThrow = true;
|
|
@@ -203,14 +362,14 @@ async function call(handler, next, context) {
|
|
|
203
362
|
function compose(handlers) {
|
|
204
363
|
const len = handlers.length;
|
|
205
364
|
if (!len) {
|
|
206
|
-
return
|
|
365
|
+
return passthroughHandler;
|
|
207
366
|
} else if (len === 1) {
|
|
208
367
|
return handlers[0];
|
|
209
368
|
}
|
|
210
369
|
return (context, next) => {
|
|
211
370
|
let i = 0;
|
|
212
|
-
return (function nextHandler() {
|
|
213
|
-
return i < len ? call(handlers[i++], nextHandler, context) : next();
|
|
371
|
+
return (function nextHandler(data) {
|
|
372
|
+
return i < len ? call(handlers[i++], nextHandler, context, data) : next(data);
|
|
214
373
|
})();
|
|
215
374
|
};
|
|
216
375
|
}
|
|
@@ -231,6 +390,87 @@ function normalizeHandler(obj) {
|
|
|
231
390
|
}
|
|
232
391
|
return passthrough;
|
|
233
392
|
}
|
|
393
|
+
function createDefineHandler() {
|
|
394
|
+
return (optionsOrHandlers, handlers) => {
|
|
395
|
+
let handler;
|
|
396
|
+
if (typeof optionsOrHandlers === "function") {
|
|
397
|
+
handler = optionsOrHandlers;
|
|
398
|
+
handler.options = {};
|
|
399
|
+
} else if (Array.isArray(optionsOrHandlers)) {
|
|
400
|
+
handler = compose(optionsOrHandlers);
|
|
401
|
+
handler.options = {};
|
|
402
|
+
} else if (typeof handlers === "function") {
|
|
403
|
+
handler = handlers;
|
|
404
|
+
handler.options = optionsOrHandlers;
|
|
405
|
+
} else if (Array.isArray(handlers)) {
|
|
406
|
+
handler = compose(handlers);
|
|
407
|
+
handler.options = optionsOrHandlers;
|
|
408
|
+
} else {
|
|
409
|
+
handler = passthroughHandler;
|
|
410
|
+
handler.options = optionsOrHandlers;
|
|
411
|
+
}
|
|
412
|
+
return handler;
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
function normalizeValidator(validator) {
|
|
416
|
+
return validator && typeof validator !== "function" ? (input) => {
|
|
417
|
+
const result = validator["~standard"].validate(input);
|
|
418
|
+
if (result instanceof Promise) {
|
|
419
|
+
throw new TypeError("Schema validation must be synchronous");
|
|
420
|
+
}
|
|
421
|
+
return result.issues ? [input, result.issues] : [result.value, void 0];
|
|
422
|
+
} : validator;
|
|
423
|
+
}
|
|
424
|
+
var defaultMaxBytes = 1024 * 1024;
|
|
425
|
+
var defaultMaxParts = 1e3;
|
|
426
|
+
var defaultMaxFiles = 20;
|
|
427
|
+
function mergeOptions(...fns) {
|
|
428
|
+
const merged = {};
|
|
429
|
+
for (const fn of fns) {
|
|
430
|
+
if (typeof fn === "function" && "options" in fn) {
|
|
431
|
+
const { options } = fn;
|
|
432
|
+
for (const k in options) {
|
|
433
|
+
const key = k;
|
|
434
|
+
const option = options[key];
|
|
435
|
+
if (typeof option === "object" && typeof merged[key] === "object") {
|
|
436
|
+
Object.assign(merged[key], option);
|
|
437
|
+
} else if (option) {
|
|
438
|
+
merged[key] = option;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
const result = {
|
|
444
|
+
params: normalizeValidator(merged.params),
|
|
445
|
+
search: normalizeValidator(merged.search)
|
|
446
|
+
};
|
|
447
|
+
if (merged.json) {
|
|
448
|
+
const { maxBytes = defaultMaxBytes, validator } = typeof merged.json === "function" || "~standard" in merged.json ? { validator: merged.json } : merged.json;
|
|
449
|
+
result.json = {
|
|
450
|
+
maxBytes,
|
|
451
|
+
validator: normalizeValidator(validator)
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
if (merged.form) {
|
|
455
|
+
const {
|
|
456
|
+
maxBytes,
|
|
457
|
+
maxFiles = defaultMaxFiles,
|
|
458
|
+
maxFileBytes = defaultMaxBytes,
|
|
459
|
+
maxParts = defaultMaxParts,
|
|
460
|
+
onFile,
|
|
461
|
+
validator
|
|
462
|
+
} = typeof merged.form === "function" || "~standard" in merged.form ? { validator: merged.form } : merged.form;
|
|
463
|
+
result.form = {
|
|
464
|
+
maxBytes: maxBytes ?? maxFiles * maxFileBytes,
|
|
465
|
+
maxFileBytes,
|
|
466
|
+
maxFiles,
|
|
467
|
+
maxParts,
|
|
468
|
+
onFile,
|
|
469
|
+
validator: normalizeValidator(validator)
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
return result;
|
|
473
|
+
}
|
|
234
474
|
function stripResponseBodySync(response) {
|
|
235
475
|
return response.body ? new Response(null, response) : response;
|
|
236
476
|
}
|
|
@@ -239,6 +479,7 @@ function stripResponseBody(response) {
|
|
|
239
479
|
}
|
|
240
480
|
function passthrough() {
|
|
241
481
|
}
|
|
482
|
+
var passthroughHandler = (_ctx, next) => next();
|
|
242
483
|
function noContent() {
|
|
243
484
|
return new Response(null, {
|
|
244
485
|
status: 204
|
|
@@ -256,12 +497,15 @@ export {
|
|
|
256
497
|
call,
|
|
257
498
|
compose,
|
|
258
499
|
createContext,
|
|
500
|
+
mergeOptions,
|
|
259
501
|
noContent,
|
|
260
502
|
normalizeHandler,
|
|
261
503
|
getMetaDataLookup as normalizeMeta,
|
|
504
|
+
normalizeValidator,
|
|
262
505
|
notHandled,
|
|
263
506
|
notMatched,
|
|
264
507
|
passthrough,
|
|
508
|
+
render,
|
|
265
509
|
stripResponseBody,
|
|
266
510
|
stripResponseBodySync
|
|
267
511
|
};
|
|
@@ -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>>;
|