@kestack/kabuki 0.0.0 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +156 -33
- package/dist/core/actor/actor.d.ts +24 -13
- package/dist/core/actor/actor.d.ts.map +1 -1
- package/dist/core/actor/actor.js +37 -26
- package/dist/core/actor/index.d.ts +2 -2
- package/dist/core/actor/index.d.ts.map +1 -1
- package/dist/core/actor/types.d.ts +91 -47
- package/dist/core/actor/types.d.ts.map +1 -1
- package/dist/core/history/history.d.ts +11 -3
- package/dist/core/history/history.d.ts.map +1 -1
- package/dist/core/history/history.js +106 -27
- package/dist/core/history/replay.d.ts +2 -0
- package/dist/core/history/replay.d.ts.map +1 -1
- package/dist/core/history/replay.js +1 -0
- package/dist/core/history/saved.d.ts +1 -1
- package/dist/core/history/saved.d.ts.map +1 -1
- package/dist/core/history/saved.js +13 -9
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/snapshot/invoke.d.ts +2 -3
- package/dist/core/snapshot/invoke.d.ts.map +1 -1
- package/dist/core/snapshot/invoke.js +42 -49
- package/dist/core/snapshot/restore.js +8 -7
- package/dist/core/snapshot/tree.d.ts +1 -1
- package/dist/core/snapshot/tree.d.ts.map +1 -1
- package/dist/core/snapshot/tree.js +1 -1
- package/dist/react/app.d.ts +30 -3
- package/dist/react/app.d.ts.map +1 -1
- package/dist/react/app.js +119 -40
- package/dist/react/drawn.d.ts +1 -1
- package/dist/react/drawn.d.ts.map +1 -1
- package/dist/react/drawn.js +2 -1
- package/dist/react/index.d.ts +3 -0
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +2 -0
- package/dist/react/lazy.d.ts +30 -0
- package/dist/react/lazy.d.ts.map +1 -0
- package/dist/react/lazy.js +56 -0
- package/dist/react/live.d.ts +7 -0
- package/dist/react/live.d.ts.map +1 -0
- package/dist/react/live.js +13 -0
- package/dist/react/view.d.ts +26 -6
- package/dist/react/view.d.ts.map +1 -1
- package/dist/react/view.js +17 -5
- package/dist/routing/adapter/adapter.d.ts +38 -0
- package/dist/routing/adapter/adapter.d.ts.map +1 -0
- package/dist/routing/adapter/adapter.js +10 -0
- package/dist/routing/adapter/browser/browser.d.ts +8 -0
- package/dist/routing/adapter/browser/browser.d.ts.map +1 -0
- package/dist/routing/adapter/browser/browser.js +33 -0
- package/dist/routing/adapter/browser/index.d.ts +2 -0
- package/dist/routing/adapter/browser/index.d.ts.map +1 -0
- package/dist/routing/adapter/browser/index.js +1 -0
- package/dist/routing/adapter/index.d.ts +3 -0
- package/dist/routing/adapter/index.d.ts.map +1 -0
- package/dist/routing/adapter/index.js +1 -0
- package/dist/routing/adapter/tanstack/index.d.ts +3 -0
- package/dist/routing/adapter/tanstack/index.d.ts.map +1 -0
- package/dist/routing/adapter/tanstack/index.js +1 -0
- package/dist/routing/adapter/tanstack/tanstack.d.ts +27 -0
- package/dist/routing/adapter/tanstack/tanstack.d.ts.map +1 -0
- package/dist/routing/adapter/tanstack/tanstack.js +38 -0
- package/dist/routing/capability/cache.d.ts +12 -0
- package/dist/routing/capability/cache.d.ts.map +1 -0
- package/dist/routing/capability/cache.js +170 -0
- package/dist/routing/capability/index.d.ts +6 -0
- package/dist/routing/capability/index.d.ts.map +1 -0
- package/dist/routing/capability/index.js +3 -0
- package/dist/routing/capability/loading.d.ts +82 -0
- package/dist/routing/capability/loading.d.ts.map +1 -0
- package/dist/routing/capability/loading.js +53 -0
- package/dist/routing/capability/navigation.d.ts +66 -0
- package/dist/routing/capability/navigation.d.ts.map +1 -0
- package/dist/routing/capability/navigation.js +65 -0
- package/dist/routing/index.d.ts +10 -0
- package/dist/routing/index.d.ts.map +1 -0
- package/dist/routing/index.js +4 -0
- package/dist/routing/page/index.d.ts +5 -0
- package/dist/routing/page/index.d.ts.map +1 -0
- package/dist/routing/page/index.js +2 -0
- package/dist/routing/page/page.d.ts +151 -0
- package/dist/routing/page/page.d.ts.map +1 -0
- package/dist/routing/page/page.js +121 -0
- package/dist/routing/page/status.d.ts +121 -0
- package/dist/routing/page/status.d.ts.map +1 -0
- package/dist/routing/page/status.js +69 -0
- package/dist/routing/route/index.d.ts +11 -0
- package/dist/routing/route/index.d.ts.map +1 -0
- package/dist/routing/route/index.js +6 -0
- package/dist/routing/route/loader.d.ts +98 -0
- package/dist/routing/route/loader.d.ts.map +1 -0
- package/dist/routing/route/loader.js +17 -0
- package/dist/routing/route/metadata.d.ts +44 -0
- package/dist/routing/route/metadata.d.ts.map +1 -0
- package/dist/routing/route/metadata.js +53 -0
- package/dist/routing/route/node.d.ts +162 -0
- package/dist/routing/route/node.d.ts.map +1 -0
- package/dist/routing/route/node.js +3 -0
- package/dist/routing/route/places.d.ts +15 -0
- package/dist/routing/route/places.d.ts.map +1 -0
- package/dist/routing/route/places.js +87 -0
- package/dist/routing/route/route.d.ts +53 -0
- package/dist/routing/route/route.d.ts.map +1 -0
- package/dist/routing/route/route.js +148 -0
- package/dist/routing/route/url.d.ts +13 -0
- package/dist/routing/route/url.d.ts.map +1 -0
- package/dist/routing/route/url.js +79 -0
- package/dist/routing/route/values.d.ts +12 -0
- package/dist/routing/route/values.d.ts.map +1 -0
- package/dist/routing/route/values.js +47 -0
- package/dist/routing/router/context.d.ts +123 -0
- package/dist/routing/router/context.d.ts.map +1 -0
- package/dist/routing/router/context.js +156 -0
- package/dist/routing/router/data.d.ts +117 -0
- package/dist/routing/router/data.d.ts.map +1 -0
- package/dist/routing/router/data.js +247 -0
- package/dist/routing/router/define.d.ts +52 -0
- package/dist/routing/router/define.d.ts.map +1 -0
- package/dist/routing/router/define.js +48 -0
- package/dist/routing/router/frame.d.ts +10 -0
- package/dist/routing/router/frame.d.ts.map +1 -0
- package/dist/routing/router/frame.js +10 -0
- package/dist/routing/router/index.d.ts +7 -0
- package/dist/routing/router/index.d.ts.map +1 -0
- package/dist/routing/router/index.js +3 -0
- package/dist/routing/router/router.d.ts +165 -0
- package/dist/routing/router/router.d.ts.map +1 -0
- package/dist/routing/router/router.js +801 -0
- package/dist/routing/routing.d.ts +72 -0
- package/dist/routing/routing.d.ts.map +1 -0
- package/dist/routing/routing.js +53 -0
- package/dist/routing/scroll/index.d.ts +4 -0
- package/dist/routing/scroll/index.d.ts.map +1 -0
- package/dist/routing/scroll/index.js +2 -0
- package/dist/routing/scroll/script.d.ts +6 -0
- package/dist/routing/scroll/script.d.ts.map +1 -0
- package/dist/routing/scroll/script.js +52 -0
- package/dist/routing/scroll/scroll.d.ts +75 -0
- package/dist/routing/scroll/scroll.d.ts.map +1 -0
- package/dist/routing/scroll/scroll.js +201 -0
- package/dist/routing/scroll/selector.d.ts +14 -0
- package/dist/routing/scroll/selector.d.ts.map +1 -0
- package/dist/routing/scroll/selector.js +40 -0
- package/dist/routing/scroll/session.d.ts +6 -0
- package/dist/routing/scroll/session.d.ts.map +1 -0
- package/dist/routing/scroll/session.js +23 -0
- package/dist/start/client/client.d.ts +11 -0
- package/dist/start/client/client.d.ts.map +1 -0
- package/dist/start/client/client.js +24 -0
- package/dist/start/client/index.d.ts +3 -0
- package/dist/start/client/index.d.ts.map +1 -0
- package/dist/start/client/index.js +2 -0
- package/dist/start/client/rpc.d.ts +14 -0
- package/dist/start/client/rpc.d.ts.map +1 -0
- package/dist/start/client/rpc.js +70 -0
- package/dist/start/common/app.d.ts +66 -0
- package/dist/start/common/app.d.ts.map +1 -0
- package/dist/start/common/app.js +23 -0
- package/dist/start/common/common.d.ts +26 -0
- package/dist/start/common/common.d.ts.map +1 -0
- package/dist/start/common/common.js +19 -0
- package/dist/start/common/document.d.ts +44 -0
- package/dist/start/common/document.d.ts.map +1 -0
- package/dist/start/common/document.js +58 -0
- package/dist/start/common/index.d.ts +9 -0
- package/dist/start/common/index.d.ts.map +1 -0
- package/dist/start/common/index.js +5 -0
- package/dist/start/common/page.d.ts +67 -0
- package/dist/start/common/page.d.ts.map +1 -0
- package/dist/start/common/page.js +29 -0
- package/dist/start/common/wire.d.ts +37 -0
- package/dist/start/common/wire.d.ts.map +1 -0
- package/dist/start/common/wire.js +73 -0
- package/dist/start/platform/cloudflare/cloudflare.d.ts +8 -0
- package/dist/start/platform/cloudflare/cloudflare.d.ts.map +1 -0
- package/dist/start/platform/cloudflare/cloudflare.js +31 -0
- package/dist/start/platform/cloudflare/index.d.ts +2 -0
- package/dist/start/platform/cloudflare/index.d.ts.map +1 -0
- package/dist/start/platform/cloudflare/index.js +1 -0
- package/dist/start/platform/index.d.ts +2 -0
- package/dist/start/platform/index.d.ts.map +1 -0
- package/dist/start/platform/index.js +1 -0
- package/dist/start/platform/platform.d.ts +31 -0
- package/dist/start/platform/platform.d.ts.map +1 -0
- package/dist/start/platform/platform.js +13 -0
- package/dist/start/server/cache.d.ts +4 -0
- package/dist/start/server/cache.d.ts.map +1 -0
- package/dist/start/server/cache.js +26 -0
- package/dist/start/server/draw.d.ts +10 -0
- package/dist/start/server/draw.d.ts.map +1 -0
- package/dist/start/server/draw.js +75 -0
- package/dist/start/server/index.d.ts +3 -0
- package/dist/start/server/index.d.ts.map +1 -0
- package/dist/start/server/index.js +2 -0
- package/dist/start/server/layers.d.ts +97 -0
- package/dist/start/server/layers.d.ts.map +1 -0
- package/dist/start/server/layers.js +37 -0
- package/dist/start/server/respond.d.ts +15 -0
- package/dist/start/server/respond.d.ts.map +1 -0
- package/dist/start/server/respond.js +35 -0
- package/dist/start/server/rpc.d.ts +11 -0
- package/dist/start/server/rpc.d.ts.map +1 -0
- package/dist/start/server/rpc.js +51 -0
- package/dist/start/server/server.d.ts +13 -0
- package/dist/start/server/server.d.ts.map +1 -0
- package/dist/start/server/server.js +138 -0
- package/dist/start/server/tiers.d.ts +14 -0
- package/dist/start/server/tiers.d.ts.map +1 -0
- package/dist/start/server/tiers.js +31 -0
- package/dist/start/vite/dev.d.ts +5 -0
- package/dist/start/vite/dev.d.ts.map +1 -0
- package/dist/start/vite/dev.js +56 -0
- package/dist/start/vite/entries.d.ts +27 -0
- package/dist/start/vite/entries.d.ts.map +1 -0
- package/dist/start/vite/entries.js +66 -0
- package/dist/start/vite/files.d.ts +22 -0
- package/dist/start/vite/files.d.ts.map +1 -0
- package/dist/start/vite/files.js +23 -0
- package/dist/start/vite/index.d.ts +2 -0
- package/dist/start/vite/index.d.ts.map +1 -0
- package/dist/start/vite/index.js +1 -0
- package/dist/start/vite/lazy.d.ts +4 -0
- package/dist/start/vite/lazy.d.ts.map +1 -0
- package/dist/start/vite/lazy.js +30 -0
- package/dist/start/vite/manifest.d.ts +18 -0
- package/dist/start/vite/manifest.d.ts.map +1 -0
- package/dist/start/vite/manifest.js +42 -0
- package/dist/start/vite/styles.d.ts +7 -0
- package/dist/start/vite/styles.d.ts.map +1 -0
- package/dist/start/vite/styles.js +58 -0
- package/dist/start/vite/vite.d.ts +11 -0
- package/dist/start/vite/vite.d.ts.map +1 -0
- package/dist/start/vite/vite.js +217 -0
- package/package.json +53 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/start/platform/cloudflare/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { cloudflare, serve } from './cloudflare.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/start/platform/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** Where static pages are kept, by a key Start makes from the build id and the URL. */
|
|
2
|
+
export interface PageCache {
|
|
3
|
+
readonly match: (key: Request) => Promise<Response | undefined>;
|
|
4
|
+
readonly put: (key: Request, response: Response) => Promise<void>;
|
|
5
|
+
}
|
|
6
|
+
/** What a platform hands Start with each request. */
|
|
7
|
+
export interface Host {
|
|
8
|
+
/** Its bindings and secrets: what the Loaders' Layers are made from. */
|
|
9
|
+
readonly env: unknown;
|
|
10
|
+
/** Where static pages are kept; with none, every page is drawn. */
|
|
11
|
+
readonly cache?: PageCache;
|
|
12
|
+
}
|
|
13
|
+
/** What Start answers requests with, on any platform. */
|
|
14
|
+
export interface Handler {
|
|
15
|
+
readonly fetch: (request: Request, host: Host) => Promise<Response>;
|
|
16
|
+
}
|
|
17
|
+
/** What the Vite plugin needs to know of a platform to build for it. */
|
|
18
|
+
export interface Platform {
|
|
19
|
+
readonly name: string;
|
|
20
|
+
/** The conditions the server build resolves its dependencies with. */
|
|
21
|
+
readonly conditions: ReadonlyArray<string>;
|
|
22
|
+
/**
|
|
23
|
+
* The adapter function the server entry wraps Start's `Handler` in, by
|
|
24
|
+
* module and export: the entry default-exports `serve(handler)`.
|
|
25
|
+
*/
|
|
26
|
+
readonly serve: {
|
|
27
|
+
readonly from: string;
|
|
28
|
+
readonly name: string;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=platform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../../../src/start/platform/platform.ts"],"names":[],"mappings":"AAaA,uFAAuF;AACvF,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAC;IAChE,QAAQ,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnE;AAED,qDAAqD;AACrD,MAAM,WAAW,IAAI;IACnB,wEAAwE;IACxE,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,mEAAmE;IACnE,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC;CAC5B;AAED,yDAAyD;AACzD,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;CACrE;AAED,wEAAwE;AACxE,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC3C;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAClE"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Where Start runs: the port every platform's adapter fills, each in a
|
|
3
|
+
* folder of its own under this one, imported from its own subpath, so a
|
|
4
|
+
* build carries only the adapter it names.
|
|
5
|
+
*
|
|
6
|
+
* - At build time, the Vite plugin reads a `Platform`: how to resolve the
|
|
7
|
+
* server's dependencies, and which adapter function turns Start's
|
|
8
|
+
* `Handler` into what the platform runs.
|
|
9
|
+
* - At run time, that adapter function hands every request to the
|
|
10
|
+
* `Handler` with a `Host`: the platform's env and, if it has one, a
|
|
11
|
+
* `PageCache`.
|
|
12
|
+
*/
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { PageCache } from '../platform/index.ts';
|
|
2
|
+
/** The page at `url` for this build: from the Cache if it is there, else drawn and, if it may be `shared`, put there. */
|
|
3
|
+
export declare const kept: (cache: PageCache | undefined, shared: string, build: string, url: URL, draw: () => Promise<Response>) => Promise<Response>;
|
|
4
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/start/server/cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAUtD,yHAAyH;AACzH,eAAO,MAAM,IAAI,UACR,SAAS,GAAG,SAAS,UACpB,MAAM,SACP,MAAM,OACR,GAAG,QACF,MAAM,OAAO,CAAC,QAAQ,CAAC,KAC5B,OAAO,CAAC,QAAQ,CAiBlB,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Static pages kept in the platform's Cache, under a key with the build id,
|
|
3
|
+
* so each is drawn once per deploy per data center. The first drawing is
|
|
4
|
+
* kept before it is sent, so the next request finds it, and goes out with
|
|
5
|
+
* the same Cache-Control as when it was drawn. With no Cache, as in dev or
|
|
6
|
+
* in Node, every page is drawn.
|
|
7
|
+
*/
|
|
8
|
+
/** The page at `url` for this build: from the Cache if it is there, else drawn and, if it may be `shared`, put there. */
|
|
9
|
+
export const kept = async (cache, shared, build, url, draw) => {
|
|
10
|
+
if (!cache)
|
|
11
|
+
return draw();
|
|
12
|
+
const key = new Request(`${url.origin}/_kabuki/cache/${encodeURIComponent(build)}${url.pathname}${url.search}`);
|
|
13
|
+
const hit = await cache.match(key);
|
|
14
|
+
// A zone's Browser Cache TTL raises the max-age of what comes out of the
|
|
15
|
+
// Cache: the browser must still ask again, so a deploy is seen at once.
|
|
16
|
+
if (hit) {
|
|
17
|
+
const response = new Response(hit.body, hit);
|
|
18
|
+
response.headers.set('cache-control', shared);
|
|
19
|
+
return response;
|
|
20
|
+
}
|
|
21
|
+
const response = await draw();
|
|
22
|
+
if (response.headers.get('cache-control') !== shared)
|
|
23
|
+
return response;
|
|
24
|
+
await cache.put(key, response.clone());
|
|
25
|
+
return response;
|
|
26
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Known } from '../../routing/page/index.ts';
|
|
2
|
+
import type { Build, DocumentType, ServedApp } from '../common/index.ts';
|
|
3
|
+
/** What one drawing starts from: the Route and what its server-drawn places start from, by dotted name. */
|
|
4
|
+
export interface At {
|
|
5
|
+
readonly route: unknown;
|
|
6
|
+
readonly known?: Readonly<Record<string, Known>>;
|
|
7
|
+
}
|
|
8
|
+
/** Draws the app at a Route as a whole HTML page; throws if anything in it fails to draw. */
|
|
9
|
+
export declare const drawer: (app: ServedApp, Document: DocumentType, build: Build) => (at: At) => Promise<string>;
|
|
10
|
+
//# sourceMappingURL=draw.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"draw.d.ts","sourceRoot":"","sources":["../../../src/start/server/draw.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAGzD,OAAO,KAAK,EAEV,KAAK,EACL,YAAY,EAEZ,SAAS,EACV,MAAM,oBAAoB,CAAC;AAe5B,2GAA2G;AAC3G,MAAM,WAAW,EAAE;IACjB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;CAClD;AA+CD,6FAA6F;AAC7F,eAAO,MAAM,MAAM,QACZ,SAAS,YACJ,YAAY,SACf,KAAK,UAQM,EAAE,KAAG,OAAO,CAAC,MAAM,CA6CtC,CAAC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { renderToReadableStream } from 'react-dom/server';
|
|
3
|
+
import { Layer } from 'effect';
|
|
4
|
+
import { History } from '../../core/index.js';
|
|
5
|
+
import { toReact } from '../../react/index.js';
|
|
6
|
+
import { tagsOf } from '../../routing/route/index.js';
|
|
7
|
+
import { PageContext, serialize } from '../common/index.js';
|
|
8
|
+
/** The data among what places start from, by dotted name: what the Metadata is worked out from. */
|
|
9
|
+
const dataOf = (known = {}) => Object.fromEntries(Object.entries(known).flatMap(([name, each]) => each._tag === 'Ready' ? [[name, each.data]] : []));
|
|
10
|
+
const attribute = (value) => value.replace(/&/g, '&').replace(/"/g, '"').replace(/</g, '<');
|
|
11
|
+
/** The files of a lazy View, by its id: in dev, its module itself. */
|
|
12
|
+
const filesOf = (build, id) => build.views === null
|
|
13
|
+
? { script: `${build.base}${id}`, styles: [], preloads: [] }
|
|
14
|
+
: build.views[id];
|
|
15
|
+
/** The tags that load the lazy Views a drawing drew, less what the entry loads already. */
|
|
16
|
+
const lazyTags = (build, ids) => {
|
|
17
|
+
const seen = new Set([
|
|
18
|
+
build.entry.script,
|
|
19
|
+
...build.entry.styles,
|
|
20
|
+
...build.entry.preloads,
|
|
21
|
+
]);
|
|
22
|
+
const once = (href) => !seen.has(href) && seen.add(href);
|
|
23
|
+
let tags = '';
|
|
24
|
+
for (const id of ids) {
|
|
25
|
+
const files = filesOf(build, id);
|
|
26
|
+
if (!files)
|
|
27
|
+
continue;
|
|
28
|
+
for (const href of files.styles.filter(once))
|
|
29
|
+
tags += `<link rel="stylesheet" href="${attribute(href)}">`;
|
|
30
|
+
for (const href of files.preloads.filter(once))
|
|
31
|
+
tags += `<link rel="modulepreload" href="${attribute(href)}">`;
|
|
32
|
+
seen.add(files.script);
|
|
33
|
+
tags += `<link rel="modulepreload" href="${attribute(files.script)}" data-kabuki-view="${attribute(id)}">`;
|
|
34
|
+
}
|
|
35
|
+
return tags;
|
|
36
|
+
};
|
|
37
|
+
/** The script that puts the page's scroll back before the app hydrates, where the Router restores it. */
|
|
38
|
+
const scrollOf = (app, route) => {
|
|
39
|
+
const scroll = app.restoreScroll?.(route);
|
|
40
|
+
return scroll ? { scroll } : {};
|
|
41
|
+
};
|
|
42
|
+
/** Draws the app at a Route as a whole HTML page; throws if anything in it fails to draw. */
|
|
43
|
+
export const drawer = (app, Document, build) => {
|
|
44
|
+
const App = toReact(app.actor, app.view, Layer.empty);
|
|
45
|
+
return async (at) => {
|
|
46
|
+
const history = History.make(app.actor, { input: at });
|
|
47
|
+
const saved = History.restored(app.actor, history.snapshotAt(null), 0).save();
|
|
48
|
+
const metadata = app.routes.metadata(at.route, dataOf(at.known));
|
|
49
|
+
const page = {
|
|
50
|
+
entry: build.entry,
|
|
51
|
+
head: build.head,
|
|
52
|
+
saved,
|
|
53
|
+
drawn: { at: Date.now(), build: build.id },
|
|
54
|
+
...scrollOf(app, at.route),
|
|
55
|
+
};
|
|
56
|
+
const views = new Set();
|
|
57
|
+
const failures = [];
|
|
58
|
+
const stream = await renderToReadableStream(_jsx(PageContext, { value: {
|
|
59
|
+
...serialize(page),
|
|
60
|
+
metadata: { title: metadata.title, tags: tagsOf(metadata) },
|
|
61
|
+
}, children: _jsx(Document, { children: _jsx(App, { saved: saved, onLazyView: (view) => {
|
|
62
|
+
if (view.id !== undefined)
|
|
63
|
+
views.add(view.id);
|
|
64
|
+
} }) }) }), { onError: (error) => void failures.push(error) });
|
|
65
|
+
await stream.allReady;
|
|
66
|
+
const html = await new Response(stream).text();
|
|
67
|
+
if (failures.length > 0)
|
|
68
|
+
throw failures[0];
|
|
69
|
+
const head = html.indexOf('</head>');
|
|
70
|
+
const whole = head < 0
|
|
71
|
+
? html
|
|
72
|
+
: `${html.slice(0, head)}${lazyTags(build, views)}${html.slice(head)}`;
|
|
73
|
+
return whole.startsWith('<!DOCTYPE') ? whole : `<!DOCTYPE html>${whole}`;
|
|
74
|
+
};
|
|
75
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/start/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { Context } from 'effect';
|
|
2
|
+
import type { Effect, Layer } from 'effect';
|
|
3
|
+
import type { LoadError, StaticOf } from '../../routing/route/index.ts';
|
|
4
|
+
/** One place's Loader, as `Routes.loaders` types it. */
|
|
5
|
+
export type AnyLoader = (params: never, request: Request) => Effect.Effect<unknown, LoadError, any>;
|
|
6
|
+
type AnyLoaders = Readonly<Record<string, AnyLoader>>;
|
|
7
|
+
declare const ResponseHeaders_base: Context.ServiceClass<ResponseHeaders, "@kestack/kabuki/start/ResponseHeaders", {
|
|
8
|
+
readonly append: (name: string, value: string) => Effect.Effect<void>;
|
|
9
|
+
}>;
|
|
10
|
+
/**
|
|
11
|
+
* Headers for the response to the request being answered, as a refreshed
|
|
12
|
+
* session's `set-cookie`: for the visitor Layer and the dynamic and client
|
|
13
|
+
* Loaders, never a static one, whose page is kept for everyone.
|
|
14
|
+
*/
|
|
15
|
+
export declare class ResponseHeaders extends ResponseHeaders_base {
|
|
16
|
+
}
|
|
17
|
+
/** The tiers as Start makes them: each a function of what it is made from. */
|
|
18
|
+
export interface Tiers {
|
|
19
|
+
/** Made once, the first time it is needed, and kept: clients of bindings, config, caches. */
|
|
20
|
+
readonly instance?: (env: any) => Layer.Layer<any, unknown, never>;
|
|
21
|
+
/** Made for each request that loads, from the env alone: what must not outlive a request, like a database connection. */
|
|
22
|
+
readonly request?: (env: any) => Layer.Layer<any, unknown, never>;
|
|
23
|
+
/** Made for each request that loads a dynamic or client place, from the env and the request itself: who is signed in. */
|
|
24
|
+
readonly visitor?: (from: {
|
|
25
|
+
readonly env: any;
|
|
26
|
+
readonly request: Request;
|
|
27
|
+
}) => Layer.Layer<any, unknown, never>;
|
|
28
|
+
}
|
|
29
|
+
declare const LOADERS: unique symbol;
|
|
30
|
+
/** The Loaders and what they Require: what `src/loaders.server` default-exports. */
|
|
31
|
+
export interface StartLoaders<L = AnyLoaders> {
|
|
32
|
+
readonly [LOADERS]: true;
|
|
33
|
+
readonly loaders: L;
|
|
34
|
+
readonly tiers: Tiers;
|
|
35
|
+
}
|
|
36
|
+
/** What the Loaders of `L` named `K` Require. */
|
|
37
|
+
type ServicesOf<L, K extends keyof L> = {
|
|
38
|
+
[P in K]-?: L[P] extends (...args: never) => Effect.Effect<any, any, infer R> ? R : never;
|
|
39
|
+
}[K];
|
|
40
|
+
type Names<L> = keyof L & string;
|
|
41
|
+
/** What the static places' Loaders Require. */
|
|
42
|
+
type StaticNeeds<L> = ServicesOf<L, StaticOf<L> & Names<L>>;
|
|
43
|
+
/** What the dynamic and client places' Loaders Require. */
|
|
44
|
+
type LaterNeeds<L> = ServicesOf<L, Exclude<Names<L>, StaticOf<L>>>;
|
|
45
|
+
/** What is missing, named, if anything is. */
|
|
46
|
+
type Missing<Need, Given, Says extends string> = [
|
|
47
|
+
Exclude<Need, Given>
|
|
48
|
+
] extends [never] ? unknown : {
|
|
49
|
+
readonly [K in Says]: Exclude<Need, Given>;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* The Loaders, checked against the tiers: each Requirement no tier they
|
|
53
|
+
* may use gives is a property they miss, named by what Requires it.
|
|
54
|
+
*/
|
|
55
|
+
type Covered<L, I, R, V> = Missing<StaticNeeds<L>, I | R, 'static Loaders Require what no instance or request Layer gives'> & Missing<LaterNeeds<L>, I | R | V | ResponseHeaders, 'dynamic and client Loaders Require what no Layer gives'>;
|
|
56
|
+
/**
|
|
57
|
+
* The tiers given so far, with what each gives: `I`, `R` and `V`. Each
|
|
58
|
+
* tier is checked as it is given against those before it; the Loaders,
|
|
59
|
+
* last, against all of them.
|
|
60
|
+
*/
|
|
61
|
+
export interface LayersOf<Env, I, R, V> {
|
|
62
|
+
/** Made once, from the env, the first time it is needed, and kept for every request: it Requires nothing. */
|
|
63
|
+
readonly instance: <Given>(make: (env: Env) => Layer.Layer<Given, unknown, never>) => LayersOf<Env, Given, R, V>;
|
|
64
|
+
/** Made for each request that loads, from the env: it may Require what the instance tier gives. */
|
|
65
|
+
readonly request: <Given>(make: (env: Env) => Layer.Layer<Given, unknown, I>) => LayersOf<Env, I, Given, V>;
|
|
66
|
+
/**
|
|
67
|
+
* Made for each request that loads a dynamic or client place, from the
|
|
68
|
+
* env and the request: it may Require what the instance and request
|
|
69
|
+
* tiers give, and `ResponseHeaders`.
|
|
70
|
+
*/
|
|
71
|
+
readonly visitor: <Given>(make: (from: {
|
|
72
|
+
readonly env: Env;
|
|
73
|
+
readonly request: Request;
|
|
74
|
+
}) => Layer.Layer<Given, unknown, I | R | ResponseHeaders>) => LayersOf<Env, I, R, Given>;
|
|
75
|
+
/** The Loaders, checked against every tier: what `src/loaders.server` default-exports. */
|
|
76
|
+
readonly loaders: <const L extends AnyLoaders>(loaders: L & Covered<L, I, R, V>) => StartLoaders<L>;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* The Loaders' Layers, a tier at a time, the env typed as the platform
|
|
80
|
+
* gives it: `Start.layers<WorkerEnv>().instance(…).request(…).visitor(…)
|
|
81
|
+
* .loaders(loaders)`. Every tier is optional; `.loaders` ends it.
|
|
82
|
+
*/
|
|
83
|
+
export declare const layers: <Env = unknown>() => LayersOf<Env, never, never, never>;
|
|
84
|
+
/** What `src/loaders.server` default-exports, if there is one: `Start.layers()…loaders(…)`, and nothing else, so it is checked. */
|
|
85
|
+
export declare const loadersOf: (exported: unknown) => StartLoaders;
|
|
86
|
+
/**
|
|
87
|
+
* Start, as `src/loaders.server` writes it: `Start.layers()`, the Loaders
|
|
88
|
+
* with what they Require on the server, in three tiers, a call each; and
|
|
89
|
+
* `Start.ResponseHeaders`, what a dynamic or client Loader adds headers to
|
|
90
|
+
* its response with.
|
|
91
|
+
*/
|
|
92
|
+
export declare const Start: {
|
|
93
|
+
layers: typeof layers;
|
|
94
|
+
ResponseHeaders: typeof ResponseHeaders;
|
|
95
|
+
};
|
|
96
|
+
export {};
|
|
97
|
+
//# sourceMappingURL=layers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layers.d.ts","sourceRoot":"","sources":["../../../src/start/server/layers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Context } from 'effect';
|
|
2
|
+
import { branded, refused } from '../common/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Headers for the response to the request being answered, as a refreshed
|
|
5
|
+
* session's `set-cookie`: for the visitor Layer and the dynamic and client
|
|
6
|
+
* Loaders, never a static one, whose page is kept for everyone.
|
|
7
|
+
*/
|
|
8
|
+
export class ResponseHeaders extends Context.Service()('@kestack/kabuki/start/ResponseHeaders') {
|
|
9
|
+
}
|
|
10
|
+
const LOADERS = Symbol.for('@kestack/kabuki/start/loaders');
|
|
11
|
+
const layersOf = (tiers) => ({
|
|
12
|
+
instance: (make) => layersOf({ ...tiers, instance: make }),
|
|
13
|
+
request: (make) => layersOf({ ...tiers, request: make }),
|
|
14
|
+
visitor: (make) => layersOf({ ...tiers, visitor: make }),
|
|
15
|
+
loaders: (loaders) => ({ [LOADERS]: true, loaders, tiers }),
|
|
16
|
+
});
|
|
17
|
+
/**
|
|
18
|
+
* The Loaders' Layers, a tier at a time, the env typed as the platform
|
|
19
|
+
* gives it: `Start.layers<WorkerEnv>().instance(…).request(…).visitor(…)
|
|
20
|
+
* .loaders(loaders)`. Every tier is optional; `.loaders` ends it.
|
|
21
|
+
*/
|
|
22
|
+
export const layers = () => layersOf({});
|
|
23
|
+
/** What `src/loaders.server` default-exports, if there is one: `Start.layers()…loaders(…)`, and nothing else, so it is checked. */
|
|
24
|
+
export const loadersOf = (exported) => {
|
|
25
|
+
if (exported === undefined)
|
|
26
|
+
return { [LOADERS]: true, loaders: {}, tiers: {} };
|
|
27
|
+
if (branded(exported, LOADERS))
|
|
28
|
+
return exported;
|
|
29
|
+
throw refused('src/loaders.server', 'Start.layers().loaders(Routes.loaders({ … }))');
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Start, as `src/loaders.server` writes it: `Start.layers()`, the Loaders
|
|
33
|
+
* with what they Require on the server, in three tiers, a call each; and
|
|
34
|
+
* `Start.ResponseHeaders`, what a dynamic or client Loader adds headers to
|
|
35
|
+
* its response with.
|
|
36
|
+
*/
|
|
37
|
+
export const Start = { layers, ResponseHeaders };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** A page every server-drawn place of which is static: the same for everyone until the next deploy. */
|
|
2
|
+
export declare const SHARED = "public, max-age=0, s-maxage=31536000, no-transform";
|
|
3
|
+
/** A page drawn for this request alone. */
|
|
4
|
+
export declare const PRIVATE = "private, no-store, no-transform";
|
|
5
|
+
export declare const html: (body: string, status: number, cache: string) => Response;
|
|
6
|
+
/** A URL that is not written as its Route is, a redirect in the Routes, or a Loader's permanent Redirect: for good. */
|
|
7
|
+
export declare const permanent: (location: string) => Response;
|
|
8
|
+
/** A Loader's Redirect: it depends on the request, so it is neither permanent nor kept. */
|
|
9
|
+
export declare const found: (location: string) => Response;
|
|
10
|
+
export declare const notAllowed: () => Response;
|
|
11
|
+
/** What a page that could not be drawn answers: nothing about why, which is logged. */
|
|
12
|
+
export declare const broken: () => Response;
|
|
13
|
+
/** The answer to a `HEAD`: a `GET`'s, without its body. */
|
|
14
|
+
export declare const headOf: (response: Response) => Response;
|
|
15
|
+
//# sourceMappingURL=respond.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"respond.d.ts","sourceRoot":"","sources":["../../../src/start/server/respond.ts"],"names":[],"mappings":"AAWA,uGAAuG;AACvG,eAAO,MAAM,MAAM,uDAAuD,CAAC;AAC3E,2CAA2C;AAC3C,eAAO,MAAM,OAAO,oCAAoC,CAAC;AAEzD,eAAO,MAAM,IAAI,SAAU,MAAM,UAAU,MAAM,SAAS,MAAM,aAO5D,CAAC;AAEL,uHAAuH;AACvH,eAAO,MAAM,SAAS,aAAc,MAAM,aACkB,CAAC;AAE7D,2FAA2F;AAC3F,eAAO,MAAM,KAAK,aAAc,MAAM,aAIlC,CAAC;AAEL,eAAO,MAAM,UAAU,gBAC+C,CAAC;AAEvE,uFAAuF;AACvF,eAAO,MAAM,MAAM,gBAKhB,CAAC;AAEJ,2DAA2D;AAC3D,eAAO,MAAM,MAAM,aAAc,QAAQ,aAIrC,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The responses Start sends besides a drawn page's own, and how long each
|
|
3
|
+
* may be kept.
|
|
4
|
+
*/
|
|
5
|
+
/*
|
|
6
|
+
* Every page is `no-transform`: the browser hydrates the whole Document, so
|
|
7
|
+
* it must get it as drawn. Edge rewriting, as Cloudflare's injected Web
|
|
8
|
+
* Analytics beacon, email obfuscation or Rocket Loader, would change it.
|
|
9
|
+
*/
|
|
10
|
+
/** A page every server-drawn place of which is static: the same for everyone until the next deploy. */
|
|
11
|
+
export const SHARED = 'public, max-age=0, s-maxage=31536000, no-transform';
|
|
12
|
+
/** A page drawn for this request alone. */
|
|
13
|
+
export const PRIVATE = 'private, no-store, no-transform';
|
|
14
|
+
export const html = (body, status, cache) => new Response(body, {
|
|
15
|
+
status,
|
|
16
|
+
headers: {
|
|
17
|
+
'content-type': 'text/html; charset=utf-8',
|
|
18
|
+
'cache-control': cache,
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
/** A URL that is not written as its Route is, a redirect in the Routes, or a Loader's permanent Redirect: for good. */
|
|
22
|
+
export const permanent = (location) => new Response(null, { status: 308, headers: { location } });
|
|
23
|
+
/** A Loader's Redirect: it depends on the request, so it is neither permanent nor kept. */
|
|
24
|
+
export const found = (location) => new Response(null, {
|
|
25
|
+
status: 302,
|
|
26
|
+
headers: { location, 'cache-control': PRIVATE },
|
|
27
|
+
});
|
|
28
|
+
export const notAllowed = () => new Response(null, { status: 405, headers: { allow: 'GET, HEAD' } });
|
|
29
|
+
/** What a page that could not be drawn answers: nothing about why, which is logged. */
|
|
30
|
+
export const broken = () => html('<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><title>Something went wrong</title></head><body><h1>Something went wrong</h1><p>This page could not be drawn. Try again in a moment.</p></body></html>', 500, PRIVATE);
|
|
31
|
+
/** The answer to a `HEAD`: a `GET`'s, without its body. */
|
|
32
|
+
export const headOf = (response) => new Response(null, {
|
|
33
|
+
status: response.status,
|
|
34
|
+
headers: response.headers,
|
|
35
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Stream } from 'effect';
|
|
2
|
+
import type { Outcome } from '../../routing/route/index.ts';
|
|
3
|
+
import type { RoutesOnWire, Wanted } from '../common/index.ts';
|
|
4
|
+
/**
|
|
5
|
+
* The server's side: reads the places a request asks for, then streams a
|
|
6
|
+
* line per place as `each` answers it. `open` makes what the Loaders run
|
|
7
|
+
* with before the answer starts, so the headers it adds go out with it; the
|
|
8
|
+
* stream it hands back runs inside that. A malformed ask is a `400`.
|
|
9
|
+
*/
|
|
10
|
+
export declare const answer: (routes: RoutesOnWire, request: Request, open: (wanted: ReadonlyArray<Wanted>) => Promise<Stream.Stream<readonly [string, Outcome]>>) => Promise<Response>;
|
|
11
|
+
//# sourceMappingURL=rpc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rpc.d.ts","sourceRoot":"","sources":["../../../src/start/server/rpc.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC5D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAE5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAoB/D;;;;;GAKG;AACH,eAAO,MAAM,MAAM,WACT,YAAY,WACX,OAAO,QACV,CACJ,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,KAC1B,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,KACtD,OAAO,CAAC,QAAQ,CAsClB,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Cause, Effect, Exit, Fiber, Stream } from 'effect';
|
|
2
|
+
import { NDJSON, loadable, readAsk, writeLine } from '../common/index.js';
|
|
3
|
+
/*
|
|
4
|
+
* The Loader RPC, answered: the places a request asks for read with their
|
|
5
|
+
* Schemas, their Loaders run at once, and each line written as its place is
|
|
6
|
+
* done. The protocol is `common/wire.ts`.
|
|
7
|
+
*/
|
|
8
|
+
const json = (body, status) => new Response(JSON.stringify(body), {
|
|
9
|
+
status,
|
|
10
|
+
headers: {
|
|
11
|
+
'content-type': 'application/json',
|
|
12
|
+
'cache-control': 'private, no-store',
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
const reason = (error) => error.cause instanceof Error ? error.cause.message : 'the ask is not JSON';
|
|
16
|
+
/**
|
|
17
|
+
* The server's side: reads the places a request asks for, then streams a
|
|
18
|
+
* line per place as `each` answers it. `open` makes what the Loaders run
|
|
19
|
+
* with before the answer starts, so the headers it adds go out with it; the
|
|
20
|
+
* stream it hands back runs inside that. A malformed ask is a `400`.
|
|
21
|
+
*/
|
|
22
|
+
export const answer = async (routes, request, open) => {
|
|
23
|
+
const places = loadable(routes);
|
|
24
|
+
let wanted;
|
|
25
|
+
try {
|
|
26
|
+
wanted = readAsk(places, await request.json());
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
return json({ error: reason({ cause: error }) }, 400);
|
|
30
|
+
}
|
|
31
|
+
const lines = await open(wanted);
|
|
32
|
+
const encoder = new TextEncoder();
|
|
33
|
+
let running;
|
|
34
|
+
const body = new ReadableStream({
|
|
35
|
+
start: (controller) => {
|
|
36
|
+
running = Effect.runFork(Stream.runForEach(lines, ([name, outcome]) => Effect.sync(() => controller.enqueue(encoder.encode(`${JSON.stringify(writeLine(routes, places, { name, outcome }))}\n`)))));
|
|
37
|
+
running.addObserver((exit) => {
|
|
38
|
+
if (Exit.isSuccess(exit))
|
|
39
|
+
return controller.close();
|
|
40
|
+
const { cause } = exit;
|
|
41
|
+
if (!Cause.hasInterruptsOnly(cause))
|
|
42
|
+
controller.error(Cause.squash(cause));
|
|
43
|
+
});
|
|
44
|
+
},
|
|
45
|
+
// The browser went away: the Loaders still running stop.
|
|
46
|
+
cancel: () => running ? Effect.runPromise(Fiber.interrupt(running)) : undefined,
|
|
47
|
+
});
|
|
48
|
+
return new Response(body, {
|
|
49
|
+
headers: { 'content-type': NDJSON, 'cache-control': 'private, no-store' },
|
|
50
|
+
});
|
|
51
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Build, StartApp } from '../common/index.ts';
|
|
2
|
+
import type { Handler } from '../platform/index.ts';
|
|
3
|
+
import type { StartLoaders } from './layers.ts';
|
|
4
|
+
export interface ServerOptions {
|
|
5
|
+
/** What `src/app` default-exports: `Start.app(…)`. */
|
|
6
|
+
readonly app: StartApp;
|
|
7
|
+
/** What `src/loaders.server` default-exports: `Start.layers()…loaders(…)`; none if no place has an Input. */
|
|
8
|
+
readonly loaders?: StartLoaders;
|
|
9
|
+
/** What the Vite plugin knows of the build. */
|
|
10
|
+
readonly build: Build;
|
|
11
|
+
}
|
|
12
|
+
export declare const server: (options: ServerOptions) => Handler;
|
|
13
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/start/server/server.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAU,MAAM,oBAAoB,CAAC;AAClE,OAAO,KAAK,EAAE,OAAO,EAAQ,MAAM,sBAAsB,CAAC;AAK1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AA0ChD,MAAM,WAAW,aAAa;IAC5B,sDAAsD;IACtD,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC;IACvB,6GAA6G;IAC7G,QAAQ,CAAC,OAAO,CAAC,EAAE,YAAY,CAAC;IAChC,+CAA+C;IAC/C,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;CACvB;AAgBD,eAAO,MAAM,MAAM,YAAa,aAAa,KAAG,OAkM/C,CAAC"}
|