@marko/run 0.10.0 → 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 +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 +279 -27
- package/dist/runtime/internal.d.ts +8 -4
- package/dist/runtime/internal.js +276 -27
- 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 +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 +13 -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,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) {
|
|
@@ -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,27 +156,113 @@ 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) {
|
|
@@ -150,16 +304,26 @@ function createContext(route, request, platform, url = new URL(request.url)) {
|
|
|
150
304
|
);
|
|
151
305
|
}
|
|
152
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);
|
|
153
314
|
}
|
|
154
|
-
async function call(handler, next, context) {
|
|
315
|
+
async function call(handler, next, context, data) {
|
|
155
316
|
let response;
|
|
317
|
+
if (data) {
|
|
318
|
+
Object.assign(context.data, data);
|
|
319
|
+
}
|
|
156
320
|
if (!process.env.NODE_ENV || process.env.NODE_ENV === "development") {
|
|
157
321
|
let nextCallCount = 0;
|
|
158
322
|
let didThrow = false;
|
|
159
323
|
try {
|
|
160
|
-
response = await handler(context, () => {
|
|
324
|
+
response = await handler(context, (d) => {
|
|
161
325
|
nextCallCount++;
|
|
162
|
-
return next();
|
|
326
|
+
return next(d);
|
|
163
327
|
});
|
|
164
328
|
} catch (error) {
|
|
165
329
|
didThrow = true;
|
|
@@ -198,14 +362,14 @@ async function call(handler, next, context) {
|
|
|
198
362
|
function compose(handlers) {
|
|
199
363
|
const len = handlers.length;
|
|
200
364
|
if (!len) {
|
|
201
|
-
return
|
|
365
|
+
return passthroughHandler;
|
|
202
366
|
} else if (len === 1) {
|
|
203
367
|
return handlers[0];
|
|
204
368
|
}
|
|
205
369
|
return (context, next) => {
|
|
206
370
|
let i = 0;
|
|
207
|
-
return (function nextHandler() {
|
|
208
|
-
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);
|
|
209
373
|
})();
|
|
210
374
|
};
|
|
211
375
|
}
|
|
@@ -226,6 +390,87 @@ function normalizeHandler(obj) {
|
|
|
226
390
|
}
|
|
227
391
|
return passthrough;
|
|
228
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
|
+
}
|
|
229
474
|
function stripResponseBodySync(response) {
|
|
230
475
|
return response.body ? new Response(null, response) : response;
|
|
231
476
|
}
|
|
@@ -234,6 +479,7 @@ function stripResponseBody(response) {
|
|
|
234
479
|
}
|
|
235
480
|
function passthrough() {
|
|
236
481
|
}
|
|
482
|
+
var passthroughHandler = (_ctx, next) => next();
|
|
237
483
|
function noContent() {
|
|
238
484
|
return new Response(null, {
|
|
239
485
|
status: 204
|
|
@@ -251,12 +497,15 @@ export {
|
|
|
251
497
|
call,
|
|
252
498
|
compose,
|
|
253
499
|
createContext,
|
|
500
|
+
mergeOptions,
|
|
254
501
|
noContent,
|
|
255
502
|
normalizeHandler,
|
|
256
503
|
getMetaDataLookup as normalizeMeta,
|
|
504
|
+
normalizeValidator,
|
|
257
505
|
notHandled,
|
|
258
506
|
notMatched,
|
|
259
507
|
passthrough,
|
|
508
|
+
render,
|
|
260
509
|
stripResponseBody,
|
|
261
510
|
stripResponseBodySync
|
|
262
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>>;
|