@marko/run 0.11.0-rc.1 → 0.11.0-rc.3

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.
@@ -15,7 +15,15 @@ export type FormBodyValidatorOptions<Ctx> = {
15
15
  maxFileBytes?: number;
16
16
  onFile?(ctx: Ctx, file: Multipart): any;
17
17
  };
18
- type Schema<I, O> = [O, undefined] | [I, StandardSchemaV1.FailureResult["issues"]];
18
+ interface Empty {
19
+ }
20
+ declare const MARKO_RUN_TYPES: unique symbol;
21
+ declare global {
22
+ interface Response {
23
+ readonly [MARKO_RUN_TYPES]: void;
24
+ }
25
+ }
26
+ export type Schema<I, O> = [O, undefined] | [I, StandardSchemaV1.FailureResult["issues"]];
19
27
  type Validated<V, Default = unknown> = V extends StandardSchemaV1<infer I, infer O> ? Schema<I, O> : V extends (...args: any[]) => infer R ? R : Default;
20
28
  type Valid<V, Default = unknown> = V extends StandardSchemaV1<infer I> ? I : V extends (...args: any[]) => infer R ? R : Default;
21
29
  type HttpVerbWithoutBody = "GET" | "HEAD" | "DELETE" | "OPTIONS";
@@ -43,12 +51,12 @@ type MapTuple<T extends readonly any[], K extends keyof T[number], Value = never
43
51
  };
44
52
  type FindTuple<T extends readonly unknown[], K extends PropertyKey, V> = T extends readonly [infer H, ...infer R] ? H extends Record<K, V> ? H : FindTuple<R, K, V> : never;
45
53
  type FilterTuple<T extends readonly unknown[], K extends PropertyKey, V> = T extends readonly [infer H, ...infer R] ? H extends Record<K, V> ? [H, ...FilterTuple<R, K, V>] : FilterTuple<R, K, V> : [];
46
- type MergeTwo<A, B> = IsPlainObject<A> extends true ? IsPlainObject<B> extends true ? Simplify<Omit<A, keyof B> & B> : B : IsPlainObject<B> extends true ? B : {};
54
+ type MergeTwo<A, B> = IsPlainObject<A> extends true ? IsPlainObject<B> extends true ? Simplify<Omit<A, keyof B> & B> : B : IsPlainObject<B> extends true ? B : Empty;
47
55
  type MergeTuple<T extends readonly any[]> = T extends readonly [
48
56
  infer A,
49
57
  infer B,
50
58
  ...infer Rest
51
- ] ? MergeTuple<[MergeTwo<A, B>, ...Rest]> : T extends readonly [infer Only] ? IsPlainObject<Only> extends true ? Only : {} : {};
59
+ ] ? MergeTuple<[MergeTwo<A, B>, ...Rest]> : T extends readonly [infer Only] ? IsPlainObject<Only> extends true ? Only : Empty : Empty;
52
60
  type MergeValidators<A, B> = IsPlainObject<A> extends true ? IsPlainObject<B> extends true ? Simplify<Omit<A, keyof B> & B> : A extends Record<"validator", Validator> ? Simplify<Omit<A, "validator"> & {
53
61
  validator: B;
54
62
  }> : B : B;
@@ -70,7 +78,7 @@ export type NormalizedMeta<Meta, Verb extends HttpVerb> = IsPlainObject<Meta> ex
70
78
  [K in Verb]: NormalizedMetaObject<Meta, K>;
71
79
  }[Verb] : Meta;
72
80
  export type NormalizedMetaLookup<T> = {
73
- [K in HttpVerb]: IsPlainObject<T> extends 1 ? NormalizedMetaObject<T, K> : T;
81
+ [K in HttpVerb]: IsPlainObject<T> extends true ? NormalizedMetaObject<T, K> : T;
74
82
  };
75
83
  type NormalizedMetaFiles<Files extends readonly File[], Verb extends HttpVerb> = {
76
84
  [I in keyof Files]: NormalizedMeta<Files[I]["exports"], Verb>;
@@ -106,12 +114,12 @@ export interface RouteDef<Path extends string = string, Verb extends HttpVerb =
106
114
  {
107
115
  form: infer T;
108
116
  }
109
- ] ? T : never : undefined;
117
+ ] ? Promise<T> : never : undefined;
110
118
  json: Verb extends HttpVerbWithBody ? Options extends [
111
119
  {
112
120
  json: infer T;
113
121
  }
114
- ] ? T : never : undefined;
122
+ ] ? Promise<T> : never : undefined;
115
123
  }
116
124
  type RouteOptionsContainer<Path extends string = string, Verb extends HttpVerb = HttpVerb> = [
117
125
  Path extends keyof AppPaths ? AppPaths[Path]["verbs"][Verb extends keyof AppPaths[Path]["verbs"] ? Verb : never]["options"] : never
@@ -123,12 +131,12 @@ export interface Route<Def extends RouteDef = RouteDef, Data = any> {
123
131
  params: Def["params"];
124
132
  search: Def["search"];
125
133
  body: Fallback<Def["json"], Fallback<Def["form"], undefined>>;
126
- data: Data extends [infer T extends RouteData] ? T : RouteData;
134
+ data: Data extends [infer T extends RouteData] ? T : Empty;
127
135
  }
128
136
  type RouteFileGroupVerb<Group extends RouteFileGroup> = (Keys<Group["handler"]["exports"]> & HttpVerb) | (Group["template"] extends [] ? never : "GET");
129
- type RouteFileGroupMeta<Group extends RouteFileGroup, Verb extends HttpVerb> = Fallback<MergeTuple<NormalizedMetaFiles<Group["meta"], Verb>>, {}>;
130
- type RouteFileGroupOptions<Group extends RouteFileGroup, Verb extends HttpVerb> = MergeHandlerOptionsTuple<MapTuple<TypesFromHandlerFiles<[...Group["middleware"], Group["handler"]], Verb>, "options", {}>>;
131
- type RouteFileGroupData<Group extends RouteFileGroup, Verb extends HttpVerb> = MergeTuple<MapTuple<TypesFromHandlerFiles<[...Group["middleware"], Group["handler"]], Verb>, "data", {}>>;
137
+ type RouteFileGroupMeta<Group extends RouteFileGroup, Verb extends HttpVerb> = Fallback<MergeTuple<NormalizedMetaFiles<Group["meta"], Verb>>, Empty>;
138
+ type RouteFileGroupOptions<Group extends RouteFileGroup, Verb extends HttpVerb> = MergeHandlerOptionsTuple<MapTuple<TypesFromHandlerFiles<[...Group["middleware"], Group["handler"]], Verb>, "options", Empty>>;
139
+ type RouteFileGroupData<Group extends RouteFileGroup, Verb extends HttpVerb> = MergeTuple<MapTuple<TypesFromHandlerFiles<[...Group["middleware"], Group["handler"]], Verb>, "data", Empty>>;
132
140
  type TypesFromHandlerFiles<Files extends File[], Verb extends HttpVerb> = {
133
141
  [I in keyof Files]: TypesFromHandlerFile<Files[I], Verb>;
134
142
  };
@@ -141,32 +149,68 @@ type DefineRoute<Path extends string, Group extends RouteFileGroup> = {
141
149
  verbs: {
142
150
  [Verb in RouteFileGroupVerb<Group>]: {
143
151
  rawOptions: RouteFileGroupOptions<Group, Verb>;
144
- options: Fallback<Validation<RouteFileGroupOptions<Group, Verb>>, {}>;
152
+ options: Fallback<Validation<RouteFileGroupOptions<Group, Verb>>, Empty>;
145
153
  data: RouteFileGroupData<Group, Verb>;
146
154
  def: RouteDef<Path, Verb, RouteFileGroupMeta<Group, Verb>, Verb extends "GET" ? {
147
155
  [File in Group["partial"][number] as File["name"] & string]: File["exports"];
148
- } : {}>;
156
+ } : Empty>;
149
157
  };
150
158
  };
151
159
  };
152
- type NextHandlerResult<Data> = Typed<Promise<Response>, {
153
- data: Data;
154
- }>;
155
160
  export type DefinePaths<Groups extends Record<string, RouteFileGroup>> = {
156
161
  [Path in keyof Groups & string]: DefineRoute<Path, Groups[Path]>;
157
162
  };
158
- type HandlerFuncData<T> = T extends Typed<{}, {
163
+ type ExtractHandlerData<U> = U extends Typed<{}, {
159
164
  data: infer Data;
160
- }> ? Data : {};
161
- export interface NormalizedHandlerFunction<Ctx, Options> extends HandlerFunction<Ctx, Promise<Response>> {
165
+ }> ? Data : never;
166
+ type HandlerDataUnionKeys<U> = U extends unknown ? keyof U : never;
167
+ type HandlerDataUnionValue<U, K extends PropertyKey> = U extends unknown ? K extends keyof U ? U[K] : never : never;
168
+ type HandlerDataRequiredKeys<U> = {
169
+ [K in HandlerDataUnionKeys<U>]: [U] extends [
170
+ {
171
+ [P in K]-?: unknown;
172
+ }
173
+ ] ? K : never;
174
+ }[HandlerDataUnionKeys<U>];
175
+ type MergeHandlerData<U> = Simplify<{
176
+ [K in HandlerDataRequiredKeys<U>]: HandlerDataUnionValue<U, K>;
177
+ } & {
178
+ [K in Exclude<HandlerDataUnionKeys<U>, HandlerDataRequiredKeys<U>>]?: HandlerDataUnionValue<U, K>;
179
+ }>;
180
+ type HandlerFuncData<T> = MergeHandlerData<ExtractHandlerData<Awaited<T>>>;
181
+ export interface NormalizedHandlerFunction<Verb extends HttpVerbOrAll, Options> extends HandlerFunction<Context, Promise<Response>> {
162
182
  options: Options;
183
+ verb: Verb;
163
184
  }
164
- export type NormalizedHandler<Ctx, Verb extends HttpVerbOrAll, Return, Options> = Typed<NormalizedHandlerFunction<Ctx, Options>, HandlerTypes<Ctx, Verb, Options, Return extends readonly unknown[] ? MergeTuple<{
185
+ export type NormalizedHandler<Ctx, Verb extends HttpVerbOrAll, Return, Options> = Typed<NormalizedHandlerFunction<Verb, Options>, HandlerTypes<Ctx, Verb, Options, [
186
+ Return
187
+ ] extends [readonly unknown[]] ? MergeTuple<{
165
188
  [I in keyof Return]: HandlerFuncData<Return[I]>;
166
189
  }> : HandlerFuncData<Return>>>;
167
190
  type HandlerArray<Ctx, Return extends unknown[]> = {
168
- [K in keyof Return]: HandlerFunction<Ctx, Return[K]>;
191
+ [K in keyof Return]: {
192
+ [MARKO_RUN_TYPES]: {
193
+ options: any;
194
+ data: any;
195
+ };
196
+ } | HandlerFunction<Ctx, Return[K]>;
169
197
  };
198
+ type HandlerValueOptions<H> = H extends {
199
+ [MARKO_RUN_TYPES]: {
200
+ options: infer O;
201
+ };
202
+ } ? O : never;
203
+ type ComposedHandlerOptions<Handlers extends readonly unknown[]> = MergeHandlerOptionsTuple<{
204
+ [K in keyof Handlers]: HandlerValueOptions<Handlers[K]>;
205
+ }>;
206
+ type HandlerValueData<H> = H extends {
207
+ [MARKO_RUN_TYPES]: {
208
+ data: infer D;
209
+ };
210
+ } ? D : H extends (...args: any[]) => infer R ? HandlerFuncData<R> : Empty;
211
+ type ComposedHandlerData<Handlers extends readonly unknown[]> = MergeTuple<{
212
+ [K in keyof Handlers]: HandlerValueData<Handlers[K]>;
213
+ }>;
170
214
  type Exact<T, Shape> = T & Record<Exclude<keyof T, keyof Shape>, never>;
171
215
  type DefineHandlerOptions<Verb extends HttpVerbOrAll, Ctx> = [Verb] extends [
172
216
  HttpVerbWithoutBody
@@ -174,17 +218,17 @@ type DefineHandlerOptions<Verb extends HttpVerbOrAll, Ctx> = [Verb] extends [
174
218
  type TypesFromHandlerFilesWithLocal<Files extends File[], Verb extends HttpVerb, Id extends ID, Options> = {
175
219
  [I in keyof Files]: Files[I] extends {
176
220
  id: Id;
177
- } ? HandlerTypes<Context, Verb, Options, {}> : TypesFromHandlerFile<Files[I], Verb>;
221
+ } ? HandlerTypes<Context, Verb, Options> : TypesFromHandlerFile<Files[I], Verb>;
178
222
  };
179
223
  type RouteFileGroupOptionsWithLocal<Group extends RouteFileGroup, Verb extends HttpVerb, Id extends ID, Options> = MergeHandlerOptionsTuple<MapTuple<TypesFromHandlerFilesWithLocal<[
180
224
  ...Group["middleware"],
181
225
  Group["handler"]
182
- ], Verb, Id, Options>, "options", {}>>;
183
- type MergedRouteOptionsForFile<Path extends keyof AppPaths, Verb extends HttpVerb, Id extends ID, Options> = Fallback<Validation<RouteFileGroupOptionsWithLocal<AppPaths[Path]["files"], Verb, Id, Options>>, {}>;
226
+ ], Verb, Id, Options>, "options", Empty>>;
227
+ type MergedRouteOptionsForFile<Path extends keyof AppPaths, Verb extends HttpVerb, Id extends ID, Options> = Fallback<Validation<RouteFileGroupOptionsWithLocal<AppPaths[Path]["files"], Verb, Id, Options>>, Empty>;
184
228
  export interface RouteForFileDef<F extends File, Path extends keyof AppPaths, Verb extends HttpVerb, Options> {
185
229
  path: Path;
186
230
  method: Verb;
187
- meta: Verb extends keyof AppPaths[Path]["verbs"] ? AppPaths[Path]["verbs"][Verb]["def"]["meta"] : {};
231
+ meta: Verb extends keyof AppPaths[Path]["verbs"] ? AppPaths[Path]["verbs"][Verb]["def"]["meta"] : Empty;
188
232
  params: MergedRouteOptionsForFile<Path, Verb, F["id"], Options> extends {
189
233
  params: infer T;
190
234
  } ? T : Simplify<PathParams<Path & string>>;
@@ -193,10 +237,10 @@ export interface RouteForFileDef<F extends File, Path extends keyof AppPaths, Ve
193
237
  } ? T : undefined;
194
238
  body: Verb extends HttpVerbWithBody ? MergedRouteOptionsForFile<Path, Verb, F["id"], Options> extends {
195
239
  json: infer T;
196
- } ? T : MergedRouteOptionsForFile<Path, Verb, F["id"], Options> extends {
240
+ } ? Promise<T> : MergedRouteOptionsForFile<Path, Verb, F["id"], Options> extends {
197
241
  form: infer T;
198
- } ? T : undefined : undefined;
199
- data: GetUpstreamData<F, Path, Verb> extends [infer T extends RouteData] ? T : RouteData;
242
+ } ? Promise<T> : undefined : undefined;
243
+ data: [F & 1] extends [0] ? Partial<AppPaths[Path]["verbs"][Verb]["data"]> : GetUpstreamData<F, Path, Verb> extends [infer T extends RouteData] ? T : Empty;
200
244
  }
201
245
  type ContextForFileWithOptions<F extends File, Verb extends HttpVerbOrAll, Options> = Union<{
202
246
  [Path in PathsForFile<F>]: Union<{
@@ -204,11 +248,11 @@ type ContextForFileWithOptions<F extends File, Verb extends HttpVerbOrAll, Optio
204
248
  }>;
205
249
  }>;
206
250
  export type DefineHandler<F extends File, Verb extends HttpVerbOrAll> = {
207
- <Return>(handler: HandlerFunction<ContextForFileWithOptions<F, Verb, {}> & {}, Return>): NormalizedHandler<ContextForFileWithOptions<F, Verb, {}> & {}, Verb, Return, {}>;
208
- <const Options extends DefineHandlerOptions<Verb, ContextForFileWithOptions<F, Verb, {}> & {}>>(options: Exact<Options, DefineHandlerOptions<Verb, ContextForFileWithOptions<F, Verb, {}> & {}>>): NormalizedHandler<ContextForFileWithOptions<F, Verb, Options> & {}, Verb, {}, Options>;
209
- <const Options extends DefineHandlerOptions<Verb, ContextForFileWithOptions<F, Verb, {}> & {}>, Return>(options: Exact<Options, DefineHandlerOptions<Verb, ContextForFileWithOptions<F, Verb, {}> & {}>>, handler: HandlerFunction<ContextForFileWithOptions<F, Verb, Options> & {}, Return>): NormalizedHandler<ContextForFileWithOptions<F, Verb, Options> & {}, Verb, Return, Options>;
210
- <Return extends unknown[]>(handlers: HandlerArray<ContextForFileWithOptions<F, Verb, {}> & {}, Return>): NormalizedHandler<ContextForFileWithOptions<F, Verb, {}> & {}, Verb, Return, {}>;
211
- <const Options extends DefineHandlerOptions<Verb, ContextForFileWithOptions<F, Verb, {}> & {}>, Return extends unknown[]>(options: Exact<Options, DefineHandlerOptions<Verb, ContextForFileWithOptions<F, Verb, {}> & {}>>, handlers: HandlerArray<ContextForFileWithOptions<F, Verb, Options> & {}, Return>): NormalizedHandler<ContextForFileWithOptions<F, Verb, Options> & {}, Verb, Return, Options>;
251
+ <const Handlers extends readonly unknown[], Return extends unknown[]>(handlers: HandlerArray<ContextForFileWithOptions<F, Verb, Empty> & {}, Return> & Handlers): Typed<NormalizedHandlerFunction<Verb, ComposedHandlerOptions<Handlers>>, HandlerTypes<ContextForFileWithOptions<F, Verb, Empty> & {}, Verb, ComposedHandlerOptions<Handlers>, ComposedHandlerData<Handlers>>>;
252
+ <const Options extends DefineHandlerOptions<Verb, ContextForFileWithOptions<F, Verb, Empty> & {}>, const Handlers extends readonly unknown[], Return extends unknown[]>(options: Exact<Options, DefineHandlerOptions<Verb, ContextForFileWithOptions<F, Verb, Empty> & {}>>, handlers: HandlerArray<ContextForFileWithOptions<F, Verb, Options> & {}, Return> & Handlers): Typed<NormalizedHandlerFunction<Verb, MergeHandlerOptions<ComposedHandlerOptions<Handlers>, Options>>, HandlerTypes<ContextForFileWithOptions<F, Verb, Options> & {}, Verb, MergeHandlerOptions<ComposedHandlerOptions<Handlers>, Options>, ComposedHandlerData<Handlers>>>;
253
+ <Return>(handler: HandlerFunction<ContextForFileWithOptions<F, Verb, Empty> & {}, Return>): NormalizedHandler<ContextForFileWithOptions<F, Verb, Empty> & {}, Verb, Return, {}>;
254
+ <const Options extends DefineHandlerOptions<Verb, ContextForFileWithOptions<F, Verb, Empty> & {}>>(options: Exact<Options, DefineHandlerOptions<Verb, ContextForFileWithOptions<F, Verb, Empty> & {}>>): NormalizedHandler<ContextForFileWithOptions<F, Verb, Options> & {}, Verb, {}, Options>;
255
+ <const Options extends DefineHandlerOptions<Verb, ContextForFileWithOptions<F, Verb, Empty> & {}>, Return>(options: Exact<Options, DefineHandlerOptions<Verb, ContextForFileWithOptions<F, Verb, Empty> & {}>>, handler: HandlerFunction<ContextForFileWithOptions<F, Verb, Options> & {}, Return>): NormalizedHandler<ContextForFileWithOptions<F, Verb, Options> & {}, Verb, Return, Options>;
212
256
  };
213
257
  type TakeUntil<Arr extends any[], Id extends ID, Prev extends any[] = []> = Arr extends [infer A, ...infer Rest] ? A extends {
214
258
  id: Id;
@@ -221,10 +265,10 @@ type GetUpstreamData<F extends File, Path extends PathsForFile<F>, Verb extends
221
265
  ] : TakeUntil<[
222
266
  ...AppPaths[Path]["files"]["middleware"],
223
267
  AppPaths[Path]["files"]["handler"]
224
- ], F["id"]>, V>, "data", {}>> : {};
268
+ ], F["id"]>, V>, "data", Empty>> : Empty;
225
269
  }>
226
- ] : {};
227
- type HandlerReturnValue = void | undefined | null | Response | typeof MarkoRun.NotHandled | typeof MarkoRun.NotMatched;
270
+ ] : Empty;
271
+ type HandlerReturnValue = void | undefined | null | Response | Typed<Response, any> | typeof MarkoRun.NotHandled | typeof MarkoRun.NotMatched;
228
272
  type HandlerReturn = HandlerReturnValue | Promise<HandlerReturnValue>;
229
273
  export type HandlerFunction<Ctx = Context, Return = HandlerReturn> = (ctx: Ctx, next: NextFunction) => Return extends HandlerReturn ? Return : HandlerReturn;
230
274
  export interface HandlerOptionsWithoutBody {
@@ -270,9 +314,6 @@ type FilterContextByVerb<Ctx extends Context, Verb extends HttpVerbOrAll> = Verb
270
314
  method: Verb;
271
315
  }> : Ctx;
272
316
  type MatchedPaths<Path> = Path extends string ? Path extends keyof AppPaths ? Path : Path extends `${infer Root}*` ? keyof AppPaths & `${Root}${string}` : keyof AppPaths : Path;
273
- type AllVerbs = Union<{
274
- [Path in keyof AppPaths]: keyof AppPaths[Path]["verbs"];
275
- }>;
276
317
  type AvailableVerbs<Scope extends keyof AppPaths | object> = Scope extends string ? {
277
318
  [K in Scope]: keyof AppPaths[K]["verbs"];
278
319
  }[Scope] : Scope extends {
@@ -289,8 +330,12 @@ type AvailableVerbs<Scope extends keyof AppPaths | object> = Scope extends strin
289
330
  type ContextForPath<Path extends keyof AppPaths, Verb extends keyof AppPaths[Path]["verbs"] = keyof AppPaths[Path]["verbs"]> = Verb extends HttpVerb ? Context<Simplify<Route<AppPaths[Path]["verbs"][Verb]["def"], [
290
331
  AppPaths[Path]["verbs"][Verb]["data"]
291
332
  ]>>> : never;
292
- export type Typed<Original, Types> = Original & {
293
- [" ~types"]: Types;
333
+ export type Typed<Original, Types> = ([Original] extends [
334
+ {
335
+ readonly [MARKO_RUN_TYPES]: any;
336
+ }
337
+ ] ? Omit<Original, typeof MARKO_RUN_TYPES> : Original) & {
338
+ [MARKO_RUN_TYPES]: Types;
294
339
  };
295
340
  type VerbsForPath<Path extends keyof AppPaths, Verb extends HttpVerbOrAll = "ALL"> = Verb extends HttpVerb ? keyof AppPaths[Path]["verbs"] & Verb : keyof AppPaths[Path]["verbs"];
296
341
  export type PathsForVerb<Verb extends HttpVerbOrAll = "ALL"> = Verb extends HttpVerb ? Union<{
@@ -304,11 +349,11 @@ export type ContextForFile<F extends File, Verb extends HttpVerbOrAll = F["type"
304
349
  export type AppPaths = App extends {
305
350
  paths: infer Paths;
306
351
  } ? Paths : DefineRoutes["paths"];
307
- export interface HandlerTypes<Ctx = Context, Verb extends HttpVerbOrAll = HttpVerbOrAll, Options = HandlerOptions<Ctx>, Data = RouteData> {
352
+ export interface HandlerTypes<Ctx = Context, Verb extends HttpVerbOrAll = HttpVerbOrAll, Options = HandlerOptions<Ctx>, Data = Empty> {
308
353
  context: Ctx;
309
354
  verb: Verb;
310
355
  options: Options;
311
- data: Data extends RouteData ? Data : {};
356
+ data: Data extends RouteData ? Data : Empty;
312
357
  }
313
358
  export type Middleware<Id extends ID, Mod> = File<Id, "middleware", Mod>;
314
359
  export type Handler<Id extends ID, Mod> = File<Id, "handler", Mod>;
@@ -319,15 +364,13 @@ export type NamespaceVerb<Verb extends HttpVerbOrAll = "ALL"> = {
319
364
  href: Href<Verb>;
320
365
  };
321
366
  export type GlobalNamespace = {
322
- [Verb in HttpVerbOrAll]: NamespaceVerb<Verb>;
367
+ [Verb in HttpVerbOrAll]: DefineHandler<any, Verb>;
323
368
  } & NamespaceVerb;
324
369
  export type Namespace<F extends File> = Typed<(F["type"] extends "middleware" ? {
325
- [Verb in HttpVerbOrAll]: DefineHandler<F, Verb> & NamespaceVerb<Verb>;
370
+ [Verb in HttpVerbOrAll]: DefineHandler<F, Verb>;
326
371
  } : F["type"] extends "handler" ? {
327
- [Verb in HttpVerb]: DefineHandler<F, Verb> & NamespaceVerb<Verb>;
328
- } : {
329
- [Verb in AllVerbs]: NamespaceVerb<Verb>;
330
- }) & NamespaceVerb, {
372
+ [Verb in HttpVerb]: DefineHandler<F, Verb>;
373
+ } : Empty) & NamespaceVerb, {
331
374
  context: ContextForFile<F> & {};
332
375
  }>;
333
376
  export type DefineRoutes<Paths = void> = {
@@ -372,7 +415,9 @@ export type GetContext<Scope extends keyof AppPaths | `*` | `/${string}*` | obje
372
415
  } ? FilterContextByVerb<Ctx, Verb> : Scope extends Typed<{}, {
373
416
  context: infer Ctx extends Context;
374
417
  }> ? FilterContextByVerb<Ctx, Verb> : never;
375
- export type NextFunction = <Data extends RouteData = RouteData>(data?: Data) => NextHandlerResult<Data>;
418
+ export type NextFunction = <Data extends RouteData = Empty>(data?: Data) => Promise<Typed<Response, {
419
+ data: Data;
420
+ }>>;
376
421
  export interface App {
377
422
  }
378
423
  export interface RouteMatch<Ctx extends Context = Context> {
@@ -390,26 +435,23 @@ export interface RuntimeModule {
390
435
  match: Match;
391
436
  invoke<TPlatform extends Platform = Platform>(...args: Parameters<Invoke<TPlatform>>): ReturnType<Invoke<TPlatform>>;
392
437
  }
393
- type DefaultAPI = keyof Exclude<Marko.Renderable, Marko.Template<any, any> | Marko.Body<any, any> | string> extends "content" ? "tags" : "class";
394
438
  type TemplateAPI<T> = T extends {
395
439
  api: infer API;
396
- } ? API : DefaultAPI;
440
+ } ? API : keyof Exclude<Marko.Renderable, Marko.Template<any, any> | Marko.Body<any, any> | string> extends "content" ? "tags" : "class";
397
441
  export type LayoutInput<F extends File> = TemplateAPI<F["module"]> extends "tags" ? {
398
442
  content: Marko.Body;
399
443
  } : {
400
444
  renderBody: Marko.Body;
401
445
  };
402
- type GetProperty<Obj, Prop> = Prop extends keyof Obj ? Obj[Prop] : never;
403
- type GetRawSearchValidator<Path extends string, Verb extends HttpVerb = "GET"> = Path extends keyof AppPaths ? Verb extends keyof AppPaths[Path]["verbs"] ? GetProperty<AppPaths[Path]["verbs"][Verb]["rawOptions"], "search"> : never : never;
404
- type ParamObject<T> = {
405
- [K in keyof T]: string | number;
406
- };
446
+ type GetRawSearchValidator<Path extends string, Verb extends HttpVerb = "GET"> = Path extends keyof AppPaths ? Verb extends keyof AppPaths[Path]["verbs"] ? "search" extends keyof AppPaths[Path]["verbs"][Verb]["rawOptions"] ? AppPaths[Path]["verbs"][Verb]["rawOptions"]["search"] : never : never : never;
407
447
  export type HrefParams<Path extends `${string}/$${string}`> = {
408
448
  [Param in PathParamKeys<Path>[number]]: Path extends `${string}/$$${Param}` ? string | number | (string | number)[] : string | number;
409
449
  };
410
450
  export type HrefOptions<Path extends string = `${string}/$${string}` | `${string}/$$${string}`> = Path extends `${string}/$${string}` ? HrefParamsOptions<Path> : HrefBaseOptions<Path>;
411
451
  interface HrefBaseOptions<Path extends string> {
412
- search?: ParamObject<Valid<GetRawSearchValidator<Path>>>;
452
+ search?: {
453
+ [K in keyof Valid<GetRawSearchValidator<Path>>]: string | number;
454
+ };
413
455
  hash?: string | number;
414
456
  }
415
457
  interface HrefParamsOptions<Path extends `${string}/$${string}`> extends HrefBaseOptions<Path> {
@@ -7,9 +7,9 @@ export declare const RoutableFileTypes: {
7
7
  readonly Handler: "handler";
8
8
  readonly Layout: "layout";
9
9
  readonly Page: "page";
10
- readonly Meta: "meta";
11
10
  readonly NotFound: "404";
12
11
  readonly Error: "500";
12
+ readonly Meta: "meta";
13
13
  };
14
14
  export type RoutableFileType = ValuesOf<typeof RoutableFileTypes>;
15
15
  export type HttpVerb = (typeof httpVerbs)[number];
@@ -115,9 +115,9 @@ var RoutableFileTypes = {
115
115
  Handler: "handler",
116
116
  Layout: "layout",
117
117
  Page: "page",
118
- Meta: "meta",
119
118
  NotFound: "404",
120
- Error: "500"
119
+ Error: "500",
120
+ Meta: "meta"
121
121
  };
122
122
 
123
123
  // src/vite/utils/fs.ts
@@ -927,6 +927,7 @@ async function renderRouteTypeInfo(routes, outDir, adapter) {
927
927
  `);
928
928
  }
929
929
  }
930
+ headWriter.join();
930
931
  const fileInfoByType = /* @__PURE__ */ new Map();
931
932
  let fileIndex = 1;
932
933
  function addFile(file) {
@@ -965,6 +966,11 @@ async function renderRouteTypeInfo(routes, outDir, adapter) {
965
966
  info.id = `P${group.size + 1}`;
966
967
  info.typeName = "Template";
967
968
  break;
969
+ case RoutableFileTypes.Error:
970
+ case RoutableFileTypes.NotFound:
971
+ info.id = "";
972
+ info.typeName = "Template";
973
+ break;
968
974
  default:
969
975
  info.id = `F${fileIndex++}`;
970
976
  break;
@@ -993,14 +999,20 @@ async function renderRouteTypeInfo(routes, outDir, adapter) {
993
999
  for (const fileType of Object.values(RoutableFileTypes)) {
994
1000
  const fileGroup = fileInfoByType.get(fileType);
995
1001
  if (!fileGroup) continue;
996
- for (const info of fileGroup.values()) {
1002
+ const hasModule = fileType !== RoutableFileTypes.Meta;
1003
+ if (!hasModule) {
997
1004
  writer.writeLines("");
998
- if (info.typeName) {
1005
+ }
1006
+ for (const info of fileGroup.values()) {
1007
+ if (hasModule) {
1008
+ writer.writeLines("");
1009
+ }
1010
+ if (info.typeName && info.id) {
999
1011
  writer.writeLines(
1000
1012
  `type ${info.id} = $.${info.typeName}<"${info.id}", typeof import("${info.modulePath}")>;`
1001
1013
  );
1002
1014
  }
1003
- if (fileType === RoutableFileTypes.Meta) continue;
1015
+ if (!hasModule) continue;
1004
1016
  writer.write(`declare module "${info.modulePath}" {`);
1005
1017
  switch (fileType) {
1006
1018
  case RoutableFileTypes.Layout:
@@ -1015,10 +1027,11 @@ async function renderRouteTypeInfo(routes, outDir, adapter) {
1015
1027
  break;
1016
1028
  }
1017
1029
  if (info.typeName) {
1030
+ const id = info.id || "any";
1018
1031
  writer.write(`
1019
- const Run: $.Namespace<${info.id}>;
1032
+ const Run: $.Namespace<${id}>;
1020
1033
  namespace Run {
1021
- type Context = $.ContextForFile<${info.id}>${info.typeName === "Template" ? " & Marko.Global" : ""};
1034
+ type Context = $.ContextForFile<${id}>${info.typeName === "Template" ? " & Marko.Global" : ""};
1022
1035
  }
1023
1036
  `);
1024
1037
  }
@@ -1039,7 +1052,6 @@ async function renderRouteTypeInfo(routes, outDir, adapter) {
1039
1052
  }`);
1040
1053
  }
1041
1054
  }
1042
- headWriter.join();
1043
1055
  return writer.end();
1044
1056
  }
1045
1057
  function createRouteTrie(routes) {
@@ -72,9 +72,9 @@ var RoutableFileTypes = {
72
72
  Handler: "handler",
73
73
  Layout: "layout",
74
74
  Page: "page",
75
- Meta: "meta",
76
75
  NotFound: "404",
77
- Error: "500"
76
+ Error: "500",
77
+ Meta: "meta"
78
78
  };
79
79
 
80
80
  // src/vite/utils/fs.ts
@@ -884,6 +884,7 @@ async function renderRouteTypeInfo(routes, outDir, adapter) {
884
884
  `);
885
885
  }
886
886
  }
887
+ headWriter.join();
887
888
  const fileInfoByType = /* @__PURE__ */ new Map();
888
889
  let fileIndex = 1;
889
890
  function addFile(file) {
@@ -922,6 +923,11 @@ async function renderRouteTypeInfo(routes, outDir, adapter) {
922
923
  info.id = `P${group.size + 1}`;
923
924
  info.typeName = "Template";
924
925
  break;
926
+ case RoutableFileTypes.Error:
927
+ case RoutableFileTypes.NotFound:
928
+ info.id = "";
929
+ info.typeName = "Template";
930
+ break;
925
931
  default:
926
932
  info.id = `F${fileIndex++}`;
927
933
  break;
@@ -950,14 +956,20 @@ async function renderRouteTypeInfo(routes, outDir, adapter) {
950
956
  for (const fileType of Object.values(RoutableFileTypes)) {
951
957
  const fileGroup = fileInfoByType.get(fileType);
952
958
  if (!fileGroup) continue;
953
- for (const info of fileGroup.values()) {
959
+ const hasModule = fileType !== RoutableFileTypes.Meta;
960
+ if (!hasModule) {
954
961
  writer.writeLines("");
955
- if (info.typeName) {
962
+ }
963
+ for (const info of fileGroup.values()) {
964
+ if (hasModule) {
965
+ writer.writeLines("");
966
+ }
967
+ if (info.typeName && info.id) {
956
968
  writer.writeLines(
957
969
  `type ${info.id} = $.${info.typeName}<"${info.id}", typeof import("${info.modulePath}")>;`
958
970
  );
959
971
  }
960
- if (fileType === RoutableFileTypes.Meta) continue;
972
+ if (!hasModule) continue;
961
973
  writer.write(`declare module "${info.modulePath}" {`);
962
974
  switch (fileType) {
963
975
  case RoutableFileTypes.Layout:
@@ -972,10 +984,11 @@ async function renderRouteTypeInfo(routes, outDir, adapter) {
972
984
  break;
973
985
  }
974
986
  if (info.typeName) {
987
+ const id = info.id || "any";
975
988
  writer.write(`
976
- const Run: $.Namespace<${info.id}>;
989
+ const Run: $.Namespace<${id}>;
977
990
  namespace Run {
978
- type Context = $.ContextForFile<${info.id}>${info.typeName === "Template" ? " & Marko.Global" : ""};
991
+ type Context = $.ContextForFile<${id}>${info.typeName === "Template" ? " & Marko.Global" : ""};
979
992
  }
980
993
  `);
981
994
  }
@@ -996,7 +1009,6 @@ async function renderRouteTypeInfo(routes, outDir, adapter) {
996
1009
  }`);
997
1010
  }
998
1011
  }
999
- headWriter.join();
1000
1012
  return writer.end();
1001
1013
  }
1002
1014
  function createRouteTrie(routes) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marko/run",
3
- "version": "0.11.0-rc.1",
3
+ "version": "0.11.0-rc.3",
4
4
  "description": "The Marko application framework.",
5
5
  "keywords": [
6
6
  "marko"
@@ -46,12 +46,24 @@
46
46
  "types": "./dist/runtime/index.d.ts",
47
47
  "typesVersions": {
48
48
  "*": {
49
- "*": ["./dist/runtime/index.d.ts"],
50
- "namespace": ["./dist/runtime/namespace.d.ts"],
51
- "router": ["./dist/runtime/router.d.ts"],
52
- "vite": ["./dist/vite/index.d.ts"],
53
- "adapter/middleware": ["./dist/adapter/middleware.d.ts"],
54
- "adapter": ["./dist/adapter/index.d.ts"]
49
+ "*": [
50
+ "./dist/runtime/index.d.ts"
51
+ ],
52
+ "namespace": [
53
+ "./dist/runtime/namespace.d.ts"
54
+ ],
55
+ "router": [
56
+ "./dist/runtime/router.d.ts"
57
+ ],
58
+ "vite": [
59
+ "./dist/vite/index.d.ts"
60
+ ],
61
+ "adapter/middleware": [
62
+ "./dist/adapter/middleware.d.ts"
63
+ ],
64
+ "adapter": [
65
+ "./dist/adapter/index.d.ts"
66
+ ]
55
67
  }
56
68
  },
57
69
  "bin": {