@torpor/build 0.4.13 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -2
- package/dist/Jsonify-Dg6gChd3.d.mts +10 -0
- package/dist/Jsonify-Dg6gChd3.d.mts.map +1 -0
- package/dist/ParseRouteParams-DBmqlmLh.d.mts +42 -0
- package/dist/ParseRouteParams-DBmqlmLh.d.mts.map +1 -0
- package/dist/{RouteType-B6BMOyYw.mjs → Router-C4ADUfhv.mjs} +30 -42
- package/dist/Router-C4ADUfhv.mjs.map +1 -0
- package/dist/{Server-CF5wDJp6.d.mts → Server-C_IKav_e.d.mts} +44 -16
- package/dist/Server-C_IKav_e.d.mts.map +1 -0
- package/dist/{ServerEvent-CxPwA4lH.mjs → ServerEvent-Dljn5i7A.mjs} +37 -11
- package/dist/ServerEvent-Dljn5i7A.mjs.map +1 -0
- package/dist/Site-CMa153FA.d.mts +565 -0
- package/dist/Site-CMa153FA.d.mts.map +1 -0
- package/dist/StandardSchema-D28L8_zZ.d.mts +100 -0
- package/dist/StandardSchema-D28L8_zZ.d.mts.map +1 -0
- package/dist/TypedResponse-6lznqN4U.d.mts +22 -0
- package/dist/TypedResponse-6lznqN4U.d.mts.map +1 -0
- package/dist/{_page-BQs4WvCO.mjs → _page-4cQKs_Dn.mjs} +3 -5
- package/dist/_page-4cQKs_Dn.mjs.map +1 -0
- package/dist/bin/index.d.mts +1 -1
- package/dist/bin/index.js +15 -11
- package/dist/bin/index.js.map +1 -1
- package/dist/flattenHeaders-C_YYLdOq.mjs +114 -0
- package/dist/flattenHeaders-C_YYLdOq.mjs.map +1 -0
- package/dist/form.d.mts +35 -0
- package/dist/form.d.mts.map +1 -0
- package/dist/form.mjs +48 -0
- package/dist/form.mjs.map +1 -0
- package/dist/index.d.mts +72 -156
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +164 -32
- package/dist/index.mjs.map +1 -1
- package/dist/nav.d.mts +58 -5
- package/dist/nav.d.mts.map +1 -1
- package/dist/nav.mjs +116 -38
- package/dist/nav.mjs.map +1 -1
- package/dist/openapi.d.mts +144 -0
- package/dist/openapi.d.mts.map +1 -0
- package/dist/openapi.mjs +2 -0
- package/dist/pathTrie-D4Ax2Mu9.mjs +160 -0
- package/dist/pathTrie-D4Ax2Mu9.mjs.map +1 -0
- package/dist/plugin-D8Www11B.mjs +202 -0
- package/dist/plugin-D8Www11B.mjs.map +1 -0
- package/dist/{response-C5TtAsh1.mjs → response-Bg4w2S1q.mjs} +16 -39
- package/dist/response-Bg4w2S1q.mjs.map +1 -0
- package/dist/response.d.mts +309 -289
- package/dist/response.d.mts.map +1 -1
- package/dist/response.mjs +3 -4
- package/dist/run.d.mts +11 -4
- package/dist/run.d.mts.map +1 -1
- package/dist/run.mjs +2 -8
- package/dist/runOpenApi-BUi1RH1l.mjs +1381 -0
- package/dist/runOpenApi-BUi1RH1l.mjs.map +1 -0
- package/dist/schema.d.mts +32 -0
- package/dist/schema.d.mts.map +1 -0
- package/dist/schema.mjs +2 -0
- package/dist/server.d.mts +10 -8
- package/dist/server.d.mts.map +1 -1
- package/dist/server.mjs +132 -4
- package/dist/server.mjs.map +1 -0
- package/dist/state.d.mts.map +1 -1
- package/dist/state.mjs +2 -3
- package/dist/test.d.mts +8 -10
- package/dist/test.d.mts.map +1 -1
- package/dist/test.mjs +286 -82
- package/dist/test.mjs.map +1 -1
- package/dist/{seeOther-B4Yhu9iq.mjs → unprocessable-DAZbrDeR.mjs} +34 -13
- package/dist/unprocessable-DAZbrDeR.mjs.map +1 -0
- package/dist/validate-Ok4krlkX.mjs +40 -0
- package/dist/validate-Ok4krlkX.mjs.map +1 -0
- package/package.json +28 -17
- package/src/bin/index.ts +13 -2
- package/src/dev.ts +10 -0
- package/src/form/formDataToRecord.ts +23 -0
- package/src/form/readForm.ts +71 -0
- package/src/form.ts +4 -0
- package/src/index.ts +53 -1
- package/src/nav/api.test-d.ts +79 -0
- package/src/nav/api.ts +104 -0
- package/src/nav/formSubmit.ts +18 -4
- package/src/nav/navigate.ts +40 -15
- package/src/nav/route.ts +38 -0
- package/src/nav.ts +3 -1
- package/src/openapi/docsHtml.ts +25 -0
- package/src/openapi/document.ts +154 -0
- package/src/openapi/plugin.ts +78 -0
- package/src/openapi/types.ts +82 -0
- package/src/openapi.ts +14 -0
- package/src/response/TypedResponse.ts +17 -0
- package/src/response/badRequest.ts +14 -2
- package/src/response/created.ts +13 -2
- package/src/response/found.ts +2 -2
- package/src/response/movedPermanently.ts +2 -2
- package/src/response/notModified.ts +2 -2
- package/src/response/ok.ts +13 -4
- package/src/response/response.ts +4 -4
- package/src/response/unprocessable.ts +14 -2
- package/src/run/depCache.ts +175 -0
- package/src/run/devPlugin.ts +128 -0
- package/src/run/prepareTemplate.ts +6 -3
- package/src/run/run.ts +63 -39
- package/src/run/runBuild.ts +63 -12
- package/src/run/runDev.ts +146 -58
- package/src/run/runOpenApi.ts +52 -0
- package/src/run/runPreview.ts +17 -26
- package/src/run/staleTorpCopies.ts +100 -0
- package/src/run.ts +2 -1
- package/src/schema.ts +7 -0
- package/src/server/CookieHelper.ts +17 -7
- package/src/server/Server.ts +54 -30
- package/src/server/ServerEvent.ts +24 -1
- package/src/server/connect/connectMiddleware.ts +44 -40
- package/src/server/connect/flattenHeaders.ts +1 -23
- package/src/server/connect/requestToNodeMessage.ts +6 -3
- package/src/server/types/MiddlewareFunction.ts +18 -4
- package/src/site/Router.ts +52 -41
- package/src/site/Site.ts +184 -10
- package/src/site/checkLayoutSlots.ts +114 -0
- package/src/site/checkRoutes.ts +435 -0
- package/src/site/clientEntry.ts +22 -9
- package/src/site/layoutSlots.ts +53 -0
- package/src/site/manifest.ts +125 -6
- package/src/site/serverEntry.ts +352 -133
- package/src/state/$page.ts +2 -1
- package/src/state/$serverPage.ts +22 -0
- package/src/test/runTest.ts +306 -118
- package/src/types/Adapter.ts +12 -0
- package/src/types/Jsonify.ts +20 -0
- package/src/types/PageData.test-d.ts +136 -0
- package/src/types/PageData.ts +35 -0
- package/src/types/PageEndPoint.ts +25 -9
- package/src/types/PageForm.test-d.ts +78 -0
- package/src/types/PageForm.ts +29 -0
- package/src/types/PageLoadEvent.ts +16 -4
- package/src/types/PageLoadReturn.ts +13 -0
- package/src/types/PageProps.ts +14 -0
- package/src/types/PageServerAction.ts +8 -2
- package/src/types/PageServerEndPoint.test-d.ts +105 -0
- package/src/types/PageServerEndPoint.ts +99 -5
- package/src/types/PageServerLoad.ts +11 -3
- package/src/types/ParseRouteParams.test-d.ts +84 -0
- package/src/types/ParseRouteParams.ts +64 -0
- package/src/types/Route.ts +20 -1
- package/src/types/RouteHandler.ts +8 -1
- package/src/types/ServerEndPoint.test-d.ts +77 -0
- package/src/types/ServerEndPoint.ts +148 -16
- package/src/types/ServerHook.ts +10 -3
- package/src/types/ServerLoadEvent.ts +48 -3
- package/src/types/ServerRequest.ts +10 -2
- package/src/types/SitePlugin.ts +24 -0
- package/src/types/StandardSchema.ts +109 -0
- package/src/utils/pathToRegex.ts +4 -2
- package/src/utils/pathTrie.ts +182 -0
- package/src/utils/searchParamsToRecord.ts +18 -0
- package/src/utils/torporPackages.ts +150 -0
- package/src/utils/tsconfigAliases.ts +90 -0
- package/src/validation/ValidationError.ts +18 -0
- package/src/validation/endpoint.ts +83 -0
- package/src/validation/validate.ts +26 -0
- package/dist/RouteType-B6BMOyYw.mjs.map +0 -1
- package/dist/Server-CF5wDJp6.d.mts.map +0 -1
- package/dist/ServerEvent-CxPwA4lH.mjs.map +0 -1
- package/dist/Site-DgC6WWn1.d.mts +0 -78
- package/dist/Site-DgC6WWn1.d.mts.map +0 -1
- package/dist/_page-BQs4WvCO.mjs.map +0 -1
- package/dist/connectMiddleware-D7nehjj3.mjs +0 -252
- package/dist/connectMiddleware-D7nehjj3.mjs.map +0 -1
- package/dist/pathToRegex-TUAMc3zS.mjs +0 -11
- package/dist/pathToRegex-TUAMc3zS.mjs.map +0 -1
- package/dist/response-C5TtAsh1.mjs.map +0 -1
- package/dist/run-DiZgkMnG.mjs +0 -332
- package/dist/run-DiZgkMnG.mjs.map +0 -1
- package/dist/seeOther-B4Yhu9iq.mjs.map +0 -1
- package/src/server/Routerx.ts +0 -72
- package/src/server/connect/bufferToArrayBuffer.ts +0 -8
- package/src/server/connect/readableToBuffer.ts +0 -16
package/README.md
CHANGED
|
@@ -4,8 +4,6 @@ A framework for building sites and apps with Torpor.
|
|
|
4
4
|
|
|
5
5
|
Built on top of [Vite](https://vite.dev).
|
|
6
6
|
|
|
7
|
-
🚧 WARNING: WORK IN PROGRESS 🚧
|
|
8
|
-
|
|
9
7
|
## Installation
|
|
10
8
|
|
|
11
9
|
Use `npm` (or your preferred package manager) to create a starter project:
|
|
@@ -17,6 +15,26 @@ npm install
|
|
|
17
15
|
npm run dev
|
|
18
16
|
```
|
|
19
17
|
|
|
18
|
+
## Features
|
|
19
|
+
|
|
20
|
+
- Configure the `Site` class in your `site.config.ts` with routes and adapters
|
|
21
|
+
- Setup code-based routing (with `site.addRoute`)
|
|
22
|
+
- Or file-based routing (with `site.addRouteFolder`)
|
|
23
|
+
- Pages and API endpoints, with layouts and error pages
|
|
24
|
+
- A `tb` command line interface:
|
|
25
|
+
- `tb --dev` -- start the dev server
|
|
26
|
+
- `tb --build` -- create a production build
|
|
27
|
+
- `tb --preview` -- preview the production build
|
|
28
|
+
- `tb --openapi [outFile]` -- generate an OpenAPI document
|
|
29
|
+
- Adapters for deployment targets -- see
|
|
30
|
+
[@torpor/adapter-node](../adapters/adapter-node) and
|
|
31
|
+
[@torpor/adapter-cloudflare](../adapters/adapter-cloudflare)
|
|
32
|
+
- Schema validation for endpoints (`@torpor/build/schema`)
|
|
33
|
+
- Form helpers (`@torpor/build/form`) and client side navigation helpers
|
|
34
|
+
(`@torpor/build/nav`)
|
|
35
|
+
- `$page` state for pages (`@torpor/build/state`) and response helpers
|
|
36
|
+
(`@torpor/build/response`)
|
|
37
|
+
|
|
20
38
|
## Folder structure
|
|
21
39
|
|
|
22
40
|
- /src
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
//#region src/types/Jsonify.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* The JSON-serialized form of a type: what a value looks like after a
|
|
4
|
+
* JSON.stringify / JSON.parse round trip. Dates become strings, functions and
|
|
5
|
+
* undefined properties are dropped.
|
|
6
|
+
*/
|
|
7
|
+
type Jsonify<T> = T extends string | number | boolean | null ? T : T extends undefined | ((...args: any[]) => any) ? never : T extends Date ? string : T extends Array<infer Item> ? Array<Jsonify<Item>> : T extends object ? { [Key in keyof T as T[Key] extends undefined | ((...args: any[]) => any) ? never : Key]: Jsonify<T[Key]>; } : T;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { Jsonify as t };
|
|
10
|
+
//# sourceMappingURL=Jsonify-Dg6gChd3.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Jsonify-Dg6gChd3.d.mts","names":[],"sources":["../src/types/Jsonify.ts"],"mappings":";;;;;;KAKY,QAAQ,KAAK,6CACtB,IACA,2BAA2B,+BAE1B,UAAU,gBAET,UAAU,YAAY,QACrB,MAAM,QAAQ,SACd,sBAEE,aAAa,KAAK,EAAE,8BAA8B,+BAEhD,MAAM,QAAQ,EAAE,WAEnB"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
//#region src/types/ParseRouteParams.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Extracts the params object from a route path string.
|
|
4
|
+
*
|
|
5
|
+
* Dynamic segments (`[id]`) and splat segments (`[...path]`) become string
|
|
6
|
+
* properties; static segments are ignored. For example:
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* type Params = ParseRouteParams<"/posts/[id]/comments/[commentId]">;
|
|
10
|
+
* // { id: string; commentId: string }
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
type ParseRouteParams<Route extends string> = ParseSegments<Route, unknown>;
|
|
14
|
+
type ParseSegments<Route extends string, Params> = Route extends `${infer Head}/${infer Rest}` ? ParseSegments<Rest, ParseSegment<Head, Params>> : ParseSegment<Route, Params>;
|
|
15
|
+
type ParseSegment<Segment extends string, Params> = Segment extends `[...${infer Name}]` ? Params & { [Key in Name]: string; } : Segment extends `[${infer Name}]` ? Params & { [Key in Name]: string; } : Params;
|
|
16
|
+
/**
|
|
17
|
+
* Resolves the params for a route annotation: the parsed params for a literal
|
|
18
|
+
* route path, or a loose record when no route (or a non-literal string) is
|
|
19
|
+
* given.
|
|
20
|
+
*/
|
|
21
|
+
type RouteParamsOf<Route extends string | undefined> = string extends Route ? Record<string, string> : Route extends string ? ParseRouteParams<Route> : Record<string, string>;
|
|
22
|
+
/**
|
|
23
|
+
* Validates an inferred params object against a route's params shape:
|
|
24
|
+
* resolves to the params type when its keys are exactly the route's keys, and
|
|
25
|
+
* `never` when keys are missing or extra — so wrong keys error at the call
|
|
26
|
+
* site (excess property checks are skipped for deferred conditional rest
|
|
27
|
+
* tuples, but assignability to `never` can't be).
|
|
28
|
+
*/
|
|
29
|
+
type ExactRouteParams<Params, Shape> = Params extends Shape ? [Exclude<keyof Params, keyof Shape>] extends [never] ? Params : never : never;
|
|
30
|
+
/**
|
|
31
|
+
* The arguments for building a route path: nothing for static routes, or the
|
|
32
|
+
* route's params object for dynamic routes.
|
|
33
|
+
*/
|
|
34
|
+
type RouteArgs<Route extends string> = string extends Route ? [params?: Record<string, string>] : keyof ParseRouteParams<Route> extends never ? [] : [params: ParseRouteParams<Route>];
|
|
35
|
+
/**
|
|
36
|
+
* RouteArgs for an optional route annotation, defaulting to a single optional
|
|
37
|
+
* loose params object.
|
|
38
|
+
*/
|
|
39
|
+
type RouteArgsOf<Route extends string | undefined> = Route extends string ? RouteArgs<Route> : [params?: Record<string, string>];
|
|
40
|
+
//#endregion
|
|
41
|
+
export { RouteParamsOf as a, RouteArgsOf as i, ParseRouteParams as n, RouteArgs as r, ExactRouteParams as t };
|
|
42
|
+
//# sourceMappingURL=ParseRouteParams-DBmqlmLh.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ParseRouteParams-DBmqlmLh.d.mts","names":[],"sources":["../src/types/ParseRouteParams.ts"],"mappings":";;;;;;;;;;;;KAWY,iBAAiB,wBAAwB,cAAc;KAE9D,cAAc,sBAAsB,UAAU,uBAAuB,cAAc,SACrF,cAAc,MAAM,aAAa,MAAM,WACvC,aAAa,OAAO;KAElB,aAAa,wBAAwB,UAAU,6BAA6B,UAC9E,YAAY,OAAO,mBACnB,0BAA0B,UACzB,YAAY,OAAO,mBACnB;;;;;;KAOQ,cAAc,mDAAmD,QAC1E,yBACA,uBACC,iBAAiB,SACjB;;;;;;;;KASQ,iBAAiB,QAAQ,SAAS,eAAe,SACzD,cAAc,cAAc,0BAC5B;;;;;KAQQ,UAAU,uCAAuC,SACzD,SAAS,gCACJ,iBAAiB,6BAErB,QAAQ,iBAAiB;;;;;KAMlB,YAAY,oCAAoC,uBACzD,UAAU,UACT,SAAS"}
|
|
@@ -1,49 +1,44 @@
|
|
|
1
|
-
import { t as
|
|
2
|
-
|
|
1
|
+
import { t as PathTrie } from "./pathTrie-D4Ax2Mu9.mjs";
|
|
3
2
|
//#region src/site/Router.ts
|
|
4
3
|
/**
|
|
5
4
|
* A router that handles file routes with layouts, hooks, etc.
|
|
6
5
|
*/
|
|
7
6
|
var Router = class {
|
|
8
7
|
routes = [];
|
|
8
|
+
#trie = new PathTrie();
|
|
9
9
|
constructor() {}
|
|
10
10
|
addPages(routes) {
|
|
11
|
-
for (let r of routes) this.
|
|
12
|
-
path: r.path,
|
|
13
|
-
type: r.type,
|
|
14
|
-
endPoint: r.endPoint,
|
|
15
|
-
subFolder: r.subFolder
|
|
16
|
-
}));
|
|
17
|
-
this.#sortRoutes();
|
|
11
|
+
for (let r of routes) this.addPage(r.path, r.type, r.endPoint, r.subFolder);
|
|
18
12
|
return this;
|
|
19
13
|
}
|
|
20
14
|
addPage(path, type, endPoint, subFolder) {
|
|
21
|
-
|
|
15
|
+
let route = new Route(path, {
|
|
22
16
|
path,
|
|
23
17
|
type,
|
|
24
18
|
endPoint,
|
|
25
19
|
subFolder
|
|
26
|
-
})
|
|
20
|
+
});
|
|
21
|
+
this.routes.push(route);
|
|
22
|
+
this.#trie.insert(path, route);
|
|
27
23
|
this.#sortRoutes();
|
|
28
24
|
return this;
|
|
29
25
|
}
|
|
30
26
|
match(path, query) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
27
|
+
let found = this.#trie.match(path);
|
|
28
|
+
if (found) {
|
|
29
|
+
let route = found.value;
|
|
30
|
+
if (!route.handler.loaded) this.#loadHandler(route.handler, route.path);
|
|
31
|
+
return {
|
|
32
|
+
handler: route.handler,
|
|
33
|
+
params: found.params,
|
|
34
|
+
query
|
|
35
|
+
};
|
|
41
36
|
}
|
|
42
37
|
}
|
|
43
38
|
#loadHandler(handler, path) {
|
|
44
39
|
handler.layouts = this.#findLayouts(path, handler);
|
|
45
40
|
handler.serverEndPoint = this.#findServer(path);
|
|
46
|
-
handler.
|
|
41
|
+
handler.serverHooks = this.#findServerHooks(handler);
|
|
47
42
|
}
|
|
48
43
|
#findLayouts(path, handler) {
|
|
49
44
|
let layouts = [];
|
|
@@ -66,11 +61,17 @@ var Router = class {
|
|
|
66
61
|
const serverRoute = this.routes.find((r) => r.path === serverPath);
|
|
67
62
|
return serverRoute && serverRoute.handler.endPoint;
|
|
68
63
|
}
|
|
69
|
-
#
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
64
|
+
#findServerHooks(handler) {
|
|
65
|
+
const hooks = [];
|
|
66
|
+
let parts = handler.path.replace(/\/~server$/, "").split("/");
|
|
67
|
+
let basePath = "";
|
|
68
|
+
for (let i = 0; i < parts.length; i++) {
|
|
69
|
+
if (i > 0) basePath += "/" + parts[i];
|
|
70
|
+
const hookPath = basePath + "/_hook/~server";
|
|
71
|
+
const hookRoute = this.routes.find((r) => r.path === hookPath);
|
|
72
|
+
if (hookRoute && hookRoute.handler.subFolder === handler.subFolder) hooks.push(hookRoute.handler.endPoint);
|
|
73
|
+
}
|
|
74
|
+
return hooks.length ? hooks : void 0;
|
|
74
75
|
}
|
|
75
76
|
#sortRoutes() {
|
|
76
77
|
this.routes = this.routes.sort((a, b) => {
|
|
@@ -83,26 +84,13 @@ var Router = class {
|
|
|
83
84
|
};
|
|
84
85
|
var Route = class {
|
|
85
86
|
path;
|
|
86
|
-
regex;
|
|
87
87
|
handler;
|
|
88
88
|
constructor(path, handler) {
|
|
89
89
|
this.path = path;
|
|
90
|
-
this.regex = pathToRegex(path);
|
|
91
90
|
this.handler = handler;
|
|
92
91
|
}
|
|
93
92
|
};
|
|
94
|
-
|
|
95
93
|
//#endregion
|
|
96
|
-
|
|
97
|
-
const PAGE_ROUTE = 0;
|
|
98
|
-
const PAGE_SERVER_ROUTE = 1;
|
|
99
|
-
const SERVER_ROUTE = 3;
|
|
100
|
-
const LAYOUT_ROUTE = 4;
|
|
101
|
-
const LAYOUT_SERVER_ROUTE = 5;
|
|
102
|
-
const HOOK_ROUTE = 6;
|
|
103
|
-
const HOOK_SERVER_ROUTE = 7;
|
|
104
|
-
const ERROR_ROUTE = 8;
|
|
94
|
+
export { Router as t };
|
|
105
95
|
|
|
106
|
-
//#
|
|
107
|
-
export { LAYOUT_SERVER_ROUTE as a, SERVER_ROUTE as c, LAYOUT_ROUTE as i, Router as l, HOOK_ROUTE as n, PAGE_ROUTE as o, HOOK_SERVER_ROUTE as r, PAGE_SERVER_ROUTE as s, ERROR_ROUTE as t };
|
|
108
|
-
//# sourceMappingURL=RouteType-B6BMOyYw.mjs.map
|
|
96
|
+
//# sourceMappingURL=Router-C4ADUfhv.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Router-C4ADUfhv.mjs","names":["#trie","#sortRoutes","#loadHandler","#findLayouts","#findServer","#findServerHooks"],"sources":["../src/site/Router.ts"],"sourcesContent":["import type LayoutHandler from \"../types/LayoutHandler\";\nimport type ManifestRoute from \"../types/ManifestRoute\";\nimport type RouteHandler from \"../types/RouteHandler\";\nimport PathTrie from \"../utils/pathTrie\";\n\n/**\n * A router that handles file routes with layouts, hooks, etc.\n */\nexport default class Router {\n\troutes: Route[] = [];\n\t// Match index for the routes above. The routes list is kept for\n\t// introspection (layouts/hooks lookup, client nav, tests); the trie is\n\t// what `match` walks.\n\t#trie = new PathTrie<Route>();\n\n\tconstructor() {}\n\n\t//add(path: string, file: string) {\n\t//\t// TODO: Call the specific addX method based on the file path\n\t//\tthis.addPage(route, file);\n\t//}\n\n\taddPages(routes: ManifestRoute[]): this {\n\t\tfor (let r of routes) {\n\t\t\tthis.addPage(r.path, r.type, r.endPoint, r.subFolder);\n\t\t}\n\t\treturn this;\n\t}\n\n\t// TODO: Allow calling with the endpoint itself, so that you can setup an app with no scaffold\n\taddPage(path: string, type: number, endPoint: () => Promise<any>, subFolder?: string): this {\n\t\tlet route = new Route(path, {\n\t\t\tpath,\n\t\t\ttype,\n\t\t\tendPoint,\n\t\t\tsubFolder,\n\t\t});\n\t\tthis.routes.push(route);\n\t\tthis.#trie.insert(path, route);\n\t\tthis.#sortRoutes();\n\t\treturn this;\n\t}\n\n\t/*\n\tloadPage(ev: ServerEvent, file: string): Response {\n\t\tlet page = this.pages.get(file);\n\t\tif (!page) {\n\t\t\tpage = {};\n\t\t\tthis.pages.set(file, page);\n\t\t}\n\t}\n\t*/\n\n\tmatch(path: string, query: URLSearchParams): RouteMatch | undefined {\n\t\tlet found = this.#trie.match(path);\n\t\tif (found) {\n\t\t\tlet route = found.value;\n\t\t\t// Lazy load server endpoints and layouts\n\t\t\tif (!route.handler.loaded) {\n\t\t\t\tthis.#loadHandler(route.handler, route.path);\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\thandler: route.handler,\n\t\t\t\tparams: found.params,\n\t\t\t\tquery,\n\t\t\t};\n\t\t}\n\t}\n\n\t#loadHandler(handler: RouteHandler, path: string) {\n\t\thandler.layouts = this.#findLayouts(path, handler);\n\t\thandler.serverEndPoint = this.#findServer(path);\n\t\thandler.serverHooks = this.#findServerHooks(handler);\n\t}\n\n\t#findLayouts(path: string, handler: RouteHandler): LayoutHandler[] | undefined {\n\t\tlet layouts: LayoutHandler[] = [];\n\t\tlet parts = path\n\t\t\t// Strip the trailing`~/server` (so we don't look for `~/server/_layout`\n\t\t\t// which will never exist)\n\t\t\t.replace(/\\/~server$/, \"\")\n\t\t\t// The path will always start with / so splitting e.g. `/first/second`\n\t\t\t// will result in ['', 'first', 'second'] and checks for `/_layout`,\n\t\t\t// `/first/_layout` and `/second/_layout`\n\t\t\t.split(\"/\");\n\t\tlet basePath = \"\";\n\t\tfor (let i = 0; i < parts.length; i++) {\n\t\t\tif (i > 0) {\n\t\t\t\tbasePath += \"/\" + parts[i];\n\t\t\t}\n\t\t\tconst layoutPath = basePath + \"/_layout\";\n\t\t\tconst layoutRoute = this.routes.find((r) => r.path === layoutPath);\n\t\t\tif (layoutRoute && layoutRoute.handler.subFolder === handler.subFolder) {\n\t\t\t\tlayouts.push({\n\t\t\t\t\tpath: layoutPath,\n\t\t\t\t\tendPoint: layoutRoute.handler.endPoint,\n\t\t\t\t\tserverEndPoint: this.#findServer(layoutPath),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn layouts.length ? layouts : undefined;\n\t}\n\n\t#findServer(path: string): (() => Promise<any>) | undefined {\n\t\tconst serverPath = path.replace(/\\/$/, \"\") + \"/~server\";\n\t\tconst serverRoute = this.routes.find((r) => r.path === serverPath);\n\t\treturn serverRoute && serverRoute.handler.endPoint;\n\t}\n\n\t#findServerHooks(handler: RouteHandler): (() => Promise<any>)[] | undefined {\n\t\t// Collect the hooks from the root down to the route path, like\n\t\t// layouts. Only hooks with the same subFolder are included, so that\n\t\t// e.g. an `api` set of routes can have its own hooks\n\t\tconst hooks: (() => Promise<any>)[] = [];\n\t\tlet parts = handler.path\n\t\t\t// Strip the trailing `~server` (so we don't look for\n\t\t\t// `~server/_hook/~server` which will never exist)\n\t\t\t.replace(/\\/~server$/, \"\")\n\t\t\t// The path will always start with / so splitting e.g.\n\t\t\t// `/first/second` will result in ['', 'first', 'second'] and\n\t\t\t// checks for `/_hook/~server`, `/first/_hook/~server` and\n\t\t\t// `/second/_hook/~server`\n\t\t\t.split(\"/\");\n\t\tlet basePath = \"\";\n\t\tfor (let i = 0; i < parts.length; i++) {\n\t\t\tif (i > 0) {\n\t\t\t\tbasePath += \"/\" + parts[i];\n\t\t\t}\n\t\t\tconst hookPath = basePath + \"/_hook/~server\";\n\t\t\tconst hookRoute = this.routes.find((r) => r.path === hookPath);\n\t\t\tif (hookRoute && hookRoute.handler.subFolder === handler.subFolder) {\n\t\t\t\thooks.push(hookRoute.handler.endPoint);\n\t\t\t}\n\t\t}\n\t\treturn hooks.length ? hooks : undefined;\n\t}\n\n\t// HACK: We're doing this here as well as in Site, so that you can use the\n\t// Router externally without Site\n\t#sortRoutes() {\n\t\tthis.routes = this.routes.sort((a, b) => {\n\t\t\t// Sort [param]s after paths\n\t\t\t// There might be a quicker/easier way to do this\n\t\t\tfor (let i = 0; i < Math.min(a.path.length, b.path.length); i++) {\n\t\t\t\tif (a.path[i] === \"[\" && b.path[i] !== \"[\") {\n\t\t\t\t\treturn 1;\n\t\t\t\t} else if (b.path[i] === \"[\" && a.path[i] !== \"[\") {\n\t\t\t\t\treturn -1;\n\t\t\t\t} else if (a.path[i] === b.path[i]) {\n\t\t\t\t\t// Keep going...\n\t\t\t\t} else {\n\t\t\t\t\treturn a.path[i].localeCompare(b.path[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn a.path.length - b.path.length;\n\t\t});\n\t}\n}\n\nclass Route {\n\tpath: string;\n\thandler: RouteHandler;\n\n\tconstructor(path: string, handler: RouteHandler) {\n\t\tthis.path = path;\n\t\tthis.handler = handler;\n\t}\n}\n\ninterface RouteMatch {\n\thandler: RouteHandler;\n\tparams?: Record<string, string>;\n\tquery: URLSearchParams;\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { SerializeOptions } from "cookie";
|
|
2
|
-
|
|
3
2
|
//#region src/server/CookieHelper.d.ts
|
|
4
3
|
declare class CookieHelper {
|
|
5
4
|
request: Request;
|
|
@@ -22,50 +21,79 @@ declare class HeaderHelper {
|
|
|
22
21
|
//#endregion
|
|
23
22
|
//#region src/server/ServerEvent.d.ts
|
|
24
23
|
declare class ServerEvent {
|
|
24
|
+
#private;
|
|
25
25
|
request: Request;
|
|
26
26
|
response: Response | undefined | void;
|
|
27
|
+
/**
|
|
28
|
+
* Set when the route handler (or a middleware enter hook) threw an
|
|
29
|
+
* error. Exit hooks can return a Response to handle it; if none does,
|
|
30
|
+
* the error is rethrown to the caller.
|
|
31
|
+
*/
|
|
32
|
+
error: unknown;
|
|
27
33
|
params?: Record<string, string>;
|
|
28
34
|
adapter: any;
|
|
29
35
|
cookies: CookieHelper;
|
|
30
36
|
headers: HeaderHelper;
|
|
31
|
-
|
|
37
|
+
/** The request URL, parsed lazily. */
|
|
38
|
+
get url(): URL;
|
|
39
|
+
constructor(request: Request, params?: Record<string, string>, url?: URL);
|
|
32
40
|
addHeaders(): void;
|
|
41
|
+
/**
|
|
42
|
+
* Reads the request body as JSON.
|
|
43
|
+
*/
|
|
44
|
+
json(): Promise<unknown>;
|
|
33
45
|
}
|
|
34
46
|
//#endregion
|
|
35
47
|
//#region src/server/types/MiddlewareFunction.d.ts
|
|
36
|
-
type MiddlewareFunction =
|
|
48
|
+
type MiddlewareFunction = {
|
|
49
|
+
/**
|
|
50
|
+
* Called before the route handler. Middleware are run in the order they
|
|
51
|
+
* were added. Return a Response to short-circuit the request; the
|
|
52
|
+
* remaining middleware and the route handler are then skipped.
|
|
53
|
+
*/
|
|
54
|
+
enter?: (ev: ServerEvent) => Response | void | Promise<Response | void>;
|
|
55
|
+
/**
|
|
56
|
+
* Called after the route handler (even if it threw), in reverse order.
|
|
57
|
+
* Return a Response to replace the response. Middleware that were skipped
|
|
58
|
+
* by a short-circuit don't get their exit hook run.
|
|
59
|
+
*
|
|
60
|
+
* If the route handler (or a later enter hook) threw, the error is
|
|
61
|
+
* available as `ev.error`; returning a Response handles the error and
|
|
62
|
+
* stops it from propagating.
|
|
63
|
+
*/
|
|
64
|
+
exit?: (ev: ServerEvent) => Response | void | Promise<Response | void>;
|
|
65
|
+
};
|
|
37
66
|
//#endregion
|
|
38
67
|
//#region src/server/types/ServerFunction.d.ts
|
|
39
68
|
type ServerFunction = (e: ServerEvent) => Response | undefined | void | Promise<Response | undefined | void>;
|
|
40
69
|
//#endregion
|
|
41
70
|
//#region src/server/Server.d.ts
|
|
42
71
|
/**
|
|
43
|
-
* A Fetch API Request/Response server.
|
|
44
|
-
*/
|
|
72
|
+
* A Fetch API Request/Response server.
|
|
73
|
+
*/
|
|
45
74
|
declare class Server {
|
|
46
75
|
#private;
|
|
47
76
|
routes: RouteHandler[];
|
|
48
77
|
middleware: MiddlewareFunction[];
|
|
49
78
|
constructor();
|
|
50
79
|
/**
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
80
|
+
* The standard Fetch API method that should work in any runtime (including
|
|
81
|
+
* Node with polyfills).
|
|
82
|
+
* @returns
|
|
83
|
+
*/
|
|
55
84
|
fetch: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
|
|
56
85
|
/**
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
86
|
+
* Adds a server function at a route path.
|
|
87
|
+
* @param path The route path pattern.
|
|
88
|
+
* @param fn The function to call when the pattern is matched.
|
|
89
|
+
* @returns
|
|
90
|
+
*/
|
|
62
91
|
add(path: string, fn: ServerFunction): Server;
|
|
63
92
|
match(path: string): Match | undefined;
|
|
64
93
|
use(...fn: MiddlewareFunction[]): Server;
|
|
65
94
|
}
|
|
66
95
|
declare class RouteHandler {
|
|
67
96
|
path: string;
|
|
68
|
-
regex: RegExp;
|
|
69
97
|
fn: ServerFunction;
|
|
70
98
|
constructor(path: string, fn: ServerFunction);
|
|
71
99
|
}
|
|
@@ -75,4 +103,4 @@ interface Match {
|
|
|
75
103
|
}
|
|
76
104
|
//#endregion
|
|
77
105
|
export { CookieHelper as a, HeaderHelper as i, MiddlewareFunction as n, ServerEvent as r, Server as t };
|
|
78
|
-
//# sourceMappingURL=Server-
|
|
106
|
+
//# sourceMappingURL=Server-C_IKav_e.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Server-C_IKav_e.d.mts","names":[],"sources":["../src/server/CookieHelper.ts","../src/server/HeaderHelper.ts","../src/server/ServerEvent.ts","../src/server/types/MiddlewareFunction.ts","../src/server/types/ServerFunction.ts","../src/server/Server.ts"],"mappings":";;cAEqB;EACpB,SAAS;EACT,SAAS;EAET,YAAY,SAAS;EAIrB,IAAI;EAaJ,IAAI,cAAc,eAAe,UAAU;EAU3C,OAAO,cAAc,UAAU;;;;cCjCX;EACpB,SAAS;EACT,SAAS;EAET,YAAY,SAAS;EAIrB,IAAI;EASJ,IAAI,cAAc;EAIlB,OAAO;;;;cClBa;;EACpB,SAAS;EACT,UAAU;;;;;;EAMV;EAEA,SAAS;EAET;EAEA,SAAS;EACT,SAAS;;MAOL,OAAO;EAIX,YAAY,SAAS,SAAS,SAAS,wBAAwB,MAAM;EAYrE;;;;EAiBA,QAAQ;;;;KCxDJ;;;;;;EAMJ,SAAS,IAAI,gBAAgB,kBAAkB,QAAQ;;;;;;;;;;EAUvD,QAAQ,IAAI,gBAAgB,kBAAkB,QAAQ;;;;KChBlD,kBACJ,GAAG,gBACC,8BAA8B,QAAQ;;;;;;cCItB;;EAEpB,QAAQ;EAIR,YAAY;EAEZ;;;;;;EAUA,QAAe,OAAO,cAAc,KAAK,OAAO,gBAAc,QAAQ;;;;;;;EAsEtE,IAAI,cAAc,IAAI,iBAAiB;EAQvC,MAAM,eAAe;EAarB,OAAO,IAAI,uBAAuB;;cAyB7B;EACL;EACA,IAAI;EAEJ,YAAY,cAAc,IAAI;;UAkBrB;EACT,IAAI;EACJ,SAAS"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { parseCookie, stringifySetCookie } from "cookie";
|
|
3
2
|
//#region src/server/CookieHelper.ts
|
|
4
3
|
var CookieHelper = class {
|
|
5
4
|
request;
|
|
@@ -8,23 +7,33 @@ var CookieHelper = class {
|
|
|
8
7
|
this.request = request;
|
|
9
8
|
}
|
|
10
9
|
get(name) {
|
|
11
|
-
if (this.cookies.has(name)) return
|
|
12
|
-
return
|
|
10
|
+
if (this.cookies.has(name)) return parseCookie(this.cookies.get(name))[name];
|
|
11
|
+
return parseCookie(this.request.headers.get("Cookie") ?? "")[name];
|
|
13
12
|
}
|
|
14
13
|
set(name, value, options) {
|
|
15
14
|
options ??= {};
|
|
16
15
|
options.httpOnly ??= true;
|
|
17
16
|
options.secure ??= true;
|
|
18
17
|
options.sameSite ??= "lax";
|
|
19
|
-
this.cookies.set(name,
|
|
18
|
+
this.cookies.set(name, stringifySetCookie({
|
|
19
|
+
name,
|
|
20
|
+
value,
|
|
21
|
+
...options
|
|
22
|
+
}));
|
|
20
23
|
}
|
|
21
24
|
delete(name, options) {
|
|
22
25
|
options ??= {};
|
|
26
|
+
options.httpOnly ??= true;
|
|
27
|
+
options.secure ??= true;
|
|
28
|
+
options.sameSite ??= "lax";
|
|
23
29
|
options.expires = /* @__PURE__ */ new Date(0);
|
|
24
|
-
this.cookies.set(name,
|
|
30
|
+
this.cookies.set(name, stringifySetCookie({
|
|
31
|
+
name,
|
|
32
|
+
value: "",
|
|
33
|
+
...options
|
|
34
|
+
}));
|
|
25
35
|
}
|
|
26
36
|
};
|
|
27
|
-
|
|
28
37
|
//#endregion
|
|
29
38
|
//#region src/server/HeaderHelper.ts
|
|
30
39
|
var HeaderHelper = class {
|
|
@@ -44,19 +53,30 @@ var HeaderHelper = class {
|
|
|
44
53
|
this.headers.delete(name);
|
|
45
54
|
}
|
|
46
55
|
};
|
|
47
|
-
|
|
48
56
|
//#endregion
|
|
49
57
|
//#region src/server/ServerEvent.ts
|
|
50
58
|
var ServerEvent = class {
|
|
51
59
|
request;
|
|
52
60
|
response;
|
|
61
|
+
/**
|
|
62
|
+
* Set when the route handler (or a middleware enter hook) threw an
|
|
63
|
+
* error. Exit hooks can return a Response to handle it; if none does,
|
|
64
|
+
* the error is rethrown to the caller.
|
|
65
|
+
*/
|
|
66
|
+
error;
|
|
53
67
|
params;
|
|
54
68
|
adapter;
|
|
55
69
|
cookies;
|
|
56
70
|
headers;
|
|
57
|
-
|
|
71
|
+
#url;
|
|
72
|
+
/** The request URL, parsed lazily. */
|
|
73
|
+
get url() {
|
|
74
|
+
return this.#url ??= new URL(this.request.url);
|
|
75
|
+
}
|
|
76
|
+
constructor(request, params, url) {
|
|
58
77
|
this.request = request;
|
|
59
78
|
this.params = params;
|
|
79
|
+
this.#url = url;
|
|
60
80
|
this.cookies = new CookieHelper(request);
|
|
61
81
|
this.headers = new HeaderHelper(request);
|
|
62
82
|
this.adapter = globalThis.adapter;
|
|
@@ -66,8 +86,14 @@ var ServerEvent = class {
|
|
|
66
86
|
for (let cookie of this.cookies.cookies.values()) this.response.headers.append("set-cookie", cookie);
|
|
67
87
|
for (let header of this.headers.headers.entries()) this.response.headers.append(header[0], header[1]);
|
|
68
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Reads the request body as JSON.
|
|
91
|
+
*/
|
|
92
|
+
json() {
|
|
93
|
+
return this.request.json();
|
|
94
|
+
}
|
|
69
95
|
};
|
|
70
|
-
|
|
71
96
|
//#endregion
|
|
72
97
|
export { HeaderHelper as n, CookieHelper as r, ServerEvent as t };
|
|
73
|
-
|
|
98
|
+
|
|
99
|
+
//# sourceMappingURL=ServerEvent-Dljn5i7A.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ServerEvent-Dljn5i7A.mjs","names":["#url"],"sources":["../src/server/CookieHelper.ts","../src/server/HeaderHelper.ts","../src/server/ServerEvent.ts"],"sourcesContent":["import { type SerializeOptions, parseCookie, stringifySetCookie } from \"cookie\";\n\nexport default class CookieHelper {\n\trequest: Request;\n\tcookies: Map<string, string> = new Map();\n\n\tconstructor(request: Request) {\n\t\tthis.request = request;\n\t}\n\n\tget(name: string): string | undefined {\n\t\t// If it's been set, return the value from the map\n\t\tif (this.cookies.has(name)) {\n\t\t\t// The stored value is a serialized Set-Cookie header; pull the\n\t\t\t// \"name=value\" prefix off and re-parse to get just the value\n\t\t\treturn parseCookie(this.cookies.get(name)!)[name];\n\t\t}\n\n\t\t// Otherwise, return the value from the `cookie` header\n\t\tconst header = this.request.headers.get(\"Cookie\");\n\t\treturn parseCookie(header ?? \"\")[name];\n\t}\n\n\tset(name: string, value: string, options?: SerializeOptions): void {\n\t\t// Set a cookie header with some default values for security\n\t\toptions ??= {};\n\t\toptions.httpOnly ??= true;\n\t\toptions.secure ??= true;\n\t\toptions.sameSite ??= \"lax\";\n\n\t\tthis.cookies.set(name, stringifySetCookie({ name, value, ...options }));\n\t}\n\n\tdelete(name: string, options?: SerializeOptions): void {\n\t\t// Set a cookie header with an empty value and an immediate expiry date.\n\t\t// Apply the same secure defaults as `set` so a previously-set Secure\n\t\t// cookie is actually overridden by the deletion.\n\t\toptions ??= {};\n\t\toptions.httpOnly ??= true;\n\t\toptions.secure ??= true;\n\t\toptions.sameSite ??= \"lax\";\n\t\toptions.expires = new Date(0);\n\n\t\tthis.cookies.set(name, stringifySetCookie({ name, value: \"\", ...options }));\n\t}\n}\n","export default class HeaderHelper {\n\trequest: Request;\n\theaders: Map<string, string> = new Map();\n\n\tconstructor(request: Request) {\n\t\tthis.request = request;\n\t}\n\n\tget(name: string): string | undefined {\n\t\t// If it's been set, return the updated value\n\t\tif (this.headers.has(name)) {\n\t\t\treturn this.headers.get(name);\n\t\t}\n\t\t// Otherwise, return the value from the header\n\t\treturn this.request.headers.get(name) ?? undefined;\n\t}\n\n\tset(name: string, value: string): void {\n\t\tthis.headers.set(name, value);\n\t}\n\n\tdelete(name: string): void {\n\t\tthis.headers.delete(name);\n\t}\n}\n","import CookieHelper from \"./CookieHelper\";\nimport HeaderHelper from \"./HeaderHelper\";\n\nexport default class ServerEvent {\n\trequest: Request;\n\tresponse: Response | undefined | void;\n\t/**\n\t * Set when the route handler (or a middleware enter hook) threw an\n\t * error. Exit hooks can return a Response to handle it; if none does,\n\t * the error is rethrown to the caller.\n\t */\n\terror: unknown;\n\t// TODO: Should we cast types??\n\tparams?: Record<string, string>;\n\n\tadapter: any;\n\n\tcookies: CookieHelper;\n\theaders: HeaderHelper;\n\n\t// Parsed once per request; Server.fetch passes the URL it already needed\n\t// for matching so it isn't parsed twice\n\t#url: URL | undefined;\n\n\t/** The request URL, parsed lazily. */\n\tget url(): URL {\n\t\treturn (this.#url ??= new URL(this.request.url));\n\t}\n\n\tconstructor(request: Request, params?: Record<string, string>, url?: URL) {\n\t\tthis.request = request;\n\t\tthis.params = params;\n\t\tthis.#url = url;\n\t\tthis.cookies = new CookieHelper(request);\n\t\tthis.headers = new HeaderHelper(request);\n\n\t\t// Adapters may have added the `adapter` property to globalThis\n\t\t// @ts-ignore\n\t\tthis.adapter = globalThis.adapter;\n\t}\n\n\taddHeaders(): void {\n\t\tif (!this.response) {\n\t\t\tthrow new Error(\"Response not created yet\");\n\t\t}\n\n\t\tfor (let cookie of this.cookies.cookies.values()) {\n\t\t\tthis.response.headers.append(\"set-cookie\", cookie);\n\t\t}\n\n\t\tfor (let header of this.headers.headers.entries()) {\n\t\t\tthis.response.headers.append(header[0], header[1]);\n\t\t}\n\t}\n\n\t/**\n\t * Reads the request body as JSON.\n\t */\n\tjson(): Promise<unknown> {\n\t\treturn this.request.json();\n\t}\n}\n"],"mappings":";;AAEA,IAAqB,eAArB,MAAkC;CACjC;CACA,0BAA+B,IAAI,IAAI;CAEvC,YAAY,SAAkB;EAC7B,KAAK,UAAU;CAChB;CAEA,IAAI,MAAkC;EAErC,IAAI,KAAK,QAAQ,IAAI,IAAI,GAGxB,OAAO,YAAY,KAAK,QAAQ,IAAI,IAAI,CAAE,CAAC,CAAC;EAK7C,OAAO,YADQ,KAAK,QAAQ,QAAQ,IAAI,QAChB,KAAK,EAAE,CAAC,CAAC;CAClC;CAEA,IAAI,MAAc,OAAe,SAAkC;EAElE,YAAY,CAAC;EACb,QAAQ,aAAa;EACrB,QAAQ,WAAW;EACnB,QAAQ,aAAa;EAErB,KAAK,QAAQ,IAAI,MAAM,mBAAmB;GAAE;GAAM;GAAO,GAAG;EAAQ,CAAC,CAAC;CACvE;CAEA,OAAO,MAAc,SAAkC;EAItD,YAAY,CAAC;EACb,QAAQ,aAAa;EACrB,QAAQ,WAAW;EACnB,QAAQ,aAAa;EACrB,QAAQ,0BAAU,IAAI,KAAK,CAAC;EAE5B,KAAK,QAAQ,IAAI,MAAM,mBAAmB;GAAE;GAAM,OAAO;GAAI,GAAG;EAAQ,CAAC,CAAC;CAC3E;AACD;;;AC7CA,IAAqB,eAArB,MAAkC;CACjC;CACA,0BAA+B,IAAI,IAAI;CAEvC,YAAY,SAAkB;EAC7B,KAAK,UAAU;CAChB;CAEA,IAAI,MAAkC;EAErC,IAAI,KAAK,QAAQ,IAAI,IAAI,GACxB,OAAO,KAAK,QAAQ,IAAI,IAAI;EAG7B,OAAO,KAAK,QAAQ,QAAQ,IAAI,IAAI,KAAK,KAAA;CAC1C;CAEA,IAAI,MAAc,OAAqB;EACtC,KAAK,QAAQ,IAAI,MAAM,KAAK;CAC7B;CAEA,OAAO,MAAoB;EAC1B,KAAK,QAAQ,OAAO,IAAI;CACzB;AACD;;;ACrBA,IAAqB,cAArB,MAAiC;CAChC;CACA;;;;;;CAMA;CAEA;CAEA;CAEA;CACA;CAIA;;CAGA,IAAI,MAAW;EACd,OAAQ,KAAKA,SAAS,IAAI,IAAI,KAAK,QAAQ,GAAG;CAC/C;CAEA,YAAY,SAAkB,QAAiC,KAAW;EACzE,KAAK,UAAU;EACf,KAAK,SAAS;EACd,KAAKA,OAAO;EACZ,KAAK,UAAU,IAAI,aAAa,OAAO;EACvC,KAAK,UAAU,IAAI,aAAa,OAAO;EAIvC,KAAK,UAAU,WAAW;CAC3B;CAEA,aAAmB;EAClB,IAAI,CAAC,KAAK,UACT,MAAM,IAAI,MAAM,0BAA0B;EAG3C,KAAK,IAAI,UAAU,KAAK,QAAQ,QAAQ,OAAO,GAC9C,KAAK,SAAS,QAAQ,OAAO,cAAc,MAAM;EAGlD,KAAK,IAAI,UAAU,KAAK,QAAQ,QAAQ,QAAQ,GAC/C,KAAK,SAAS,QAAQ,OAAO,OAAO,IAAI,OAAO,EAAE;CAEnD;;;;CAKA,OAAyB;EACxB,OAAO,KAAK,QAAQ,KAAK;CAC1B;AACD"}
|