@hozu/runtime-server 0.11.0 → 0.13.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/dist/app.d.ts.map +1 -1
- package/dist/app.js +3 -2
- package/dist/app.js.map +1 -1
- package/dist/bus.d.ts +31 -0
- package/dist/bus.d.ts.map +1 -0
- package/dist/bus.js +73 -0
- package/dist/bus.js.map +1 -0
- package/dist/cache.d.ts +7 -1
- package/dist/cache.d.ts.map +1 -1
- package/dist/cache.js +10 -12
- package/dist/cache.js.map +1 -1
- package/dist/dev-effects.d.ts +14 -0
- package/dist/dev-effects.d.ts.map +1 -0
- package/dist/dev-effects.js +41 -0
- package/dist/dev-effects.js.map +1 -0
- package/dist/dev-trace.d.ts +21 -0
- package/dist/dev-trace.d.ts.map +1 -0
- package/dist/dev-trace.js +86 -0
- package/dist/dev-trace.js.map +1 -0
- package/dist/fn-modules.d.ts +22 -0
- package/dist/fn-modules.d.ts.map +1 -0
- package/dist/fn-modules.js +127 -0
- package/dist/fn-modules.js.map +1 -0
- package/dist/handler.d.ts +18 -1
- package/dist/handler.d.ts.map +1 -1
- package/dist/handler.js +99 -22
- package/dist/handler.js.map +1 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/render.d.ts +2 -2
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +13 -19
- package/dist/render.js.map +1 -1
- package/dist/security.d.ts +5 -0
- package/dist/security.d.ts.map +1 -1
- package/dist/security.js +24 -0
- package/dist/security.js.map +1 -1
- package/dist/static.d.ts +2 -2
- package/dist/static.d.ts.map +1 -1
- package/dist/static.js +5 -4
- package/dist/static.js.map +1 -1
- package/package.json +6 -6
- package/dist/compile.d.ts +0 -43
- package/dist/compile.d.ts.map +0 -1
- package/dist/compile.js +0 -170
- package/dist/compile.js.map +0 -1
- package/dist/widgets.d.ts +0 -3
- package/dist/widgets.d.ts.map +0 -1
- package/dist/widgets.js +0 -10
- package/dist/widgets.js.map +0 -1
package/dist/app.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC/C,OAAO,
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC/C,OAAO,EAAe,KAAK,WAAW,EAAgB,KAAK,QAAQ,EAAE,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAA;AACzG,OAAO,EAAE,KAAK,WAAW,EAAiB,MAAM,YAAY,CAAA;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAEhD,QAAA,MAAM,GAAG,eAAyB,CAAA;AAElC,MAAM,WAAW,UACf,SAAQ,IAAI,CACV,cAAc,EACd,OAAO,GAAG,QAAQ,GAAG,YAAY,GAAG,KAAK,GAAG,UAAU,GAAG,UAAU,GAAG,QAAQ,GAAG,QAAQ,CAC1F;IACD,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,CAAC,eAAe,CAAC,CAAA;CAC9D;AAED,MAAM,WAAW,GAAG;IAClB,QAAQ,CAAC,CAAC,GAAG,CAAC,EAAE,UAAU,CAAA;CAC3B;AAED,MAAM,WAAW,OAAO;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;IACxC,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,MAAM,CAAC,EAAE,YAAY,CAAA;IACrB,MAAM,CAAC,EAAE,UAAU,GAAG,IAAI,CAAA;IAC1B,UAAU,CAAC,EAAE,eAAe,GAAG,IAAI,CAAA;IACnC,MAAM,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAA;IACxB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAA;IAChD,OAAO,CAAC,EAAE,YAAY,CAAA;IACtB,GAAG,CAAC,EAAE,UAAU,CAAA;IAChB,OAAO,CAAC,EAAE,WAAW,CAAA;CACtB;AAED,eAAO,MAAM,GAAG,YAAa,UAAU,KAAG,GAAwC,CAAA;AAElF,eAAO,MAAM,YAAY,UAAW,OAAO,KAAG,UAAU,GAAG,IACkC,CAAA;AAE7F,eAAO,MAAM,YAAY,MAAO,GAAG,KAAG,OAAkD,CAAA;AAExF,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,GAAE,OAAY,GAAG,cAAc,CAQ5E"}
|
package/dist/app.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { buildProject } from '@hozu/core/ir';
|
|
1
|
+
import { appModuleOf, buildProject } from '@hozu/core/ir';
|
|
2
2
|
import { resolverSetOf } from '@hozu/data';
|
|
3
3
|
const APP = Symbol.for('hozu.app');
|
|
4
4
|
export const app = (options) => Object.freeze({ [APP]: options });
|
|
@@ -10,6 +10,7 @@ export function appHandlerOptions(a, host = {}) {
|
|
|
10
10
|
sources: host.dev !== undefined,
|
|
11
11
|
...(host.manifest ? { manifest: host.manifest } : {}),
|
|
12
12
|
});
|
|
13
|
-
|
|
13
|
+
const dev = host.dev ? { dev: { ...host.dev, app: host.dev.app ?? appModuleOf(projectOfApp(a)) } } : {};
|
|
14
|
+
return { ...options, ...host, ...dev, build };
|
|
14
15
|
}
|
|
15
16
|
//# sourceMappingURL=app.js.map
|
package/dist/app.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AACA,OAAO,EAAoB,YAAY,EAAgC,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAoB,YAAY,EAAgC,MAAM,eAAe,CAAA;AACzG,OAAO,EAAoB,aAAa,EAAE,MAAM,YAAY,CAAA;AAM5D,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;AA2BlC,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,OAAmB,EAAO,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,CAAC,CAAA;AAElF,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,KAAc,EAAqB,EAAE,CAChE,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,CAAE,KAAsB,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;AAE7F,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAM,EAAW,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,CAAA;AAExF,MAAM,UAAU,iBAAiB,CAAC,CAAM,EAAE,IAAI,GAAY,EAAE;IAC1D,MAAM,EAAE,UAAU,EAAE,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAA;IAC5C,MAAM,KAAK,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE;QAC1C,OAAO,EAAE,IAAI,CAAC,GAAG,KAAK,SAAS;QAC/B,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACtD,CAAC,CAAA;IACF,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;IACvG,OAAO,EAAE,GAAG,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,GAAG,EAAE,KAAK,EAAE,CAAA;AAC/C,CAAC"}
|
package/dist/bus.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Carries invalidated tags between the instances of one app (ADR 0050 B). Tags, never data: an instance that
|
|
3
|
+
* receives tags drops its own pages and entries and pushes to its own live clients. Delivery is at least once and
|
|
4
|
+
* unordered; dropping a tag twice is harmless.
|
|
5
|
+
*/
|
|
6
|
+
export interface InvalidationBus {
|
|
7
|
+
publish(tags: string[]): void | Promise<void>;
|
|
8
|
+
subscribe(onTags: (tags: string[]) => void): () => void;
|
|
9
|
+
/** For a transport that receives over the app's own HTTP: answers `POST /_hozu/invalidate`. */
|
|
10
|
+
accept?(request: Request): Promise<Response>;
|
|
11
|
+
}
|
|
12
|
+
/** One process: nothing to tell. */
|
|
13
|
+
export declare function localBus(): InvalidationBus;
|
|
14
|
+
export interface HttpBusOptions {
|
|
15
|
+
/** The base URL of every instance, including this one and the app's base path: `http://10.0.0.2:3000`. */
|
|
16
|
+
peers: string[];
|
|
17
|
+
/** Shared by every instance; at least 32 characters. */
|
|
18
|
+
secret: string;
|
|
19
|
+
/** Reports a peer that stayed unreachable after the retries. */
|
|
20
|
+
onError?: (error: unknown, peer: string) => void;
|
|
21
|
+
/** Delays between attempts, in milliseconds. */
|
|
22
|
+
retries?: number[];
|
|
23
|
+
fetch?: typeof fetch;
|
|
24
|
+
now?: () => number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Signed `POST /_hozu/invalidate` to every peer (HMAC-SHA256 over the body, which carries a timestamp; messages
|
|
28
|
+
* older than 30 s or from the future are refused). Zero dependencies: Web Crypto and `fetch`.
|
|
29
|
+
*/
|
|
30
|
+
export declare function httpBus({ peers, secret, onError, retries, fetch: send, now, }: HttpBusOptions): InvalidationBus;
|
|
31
|
+
//# sourceMappingURL=bus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bus.d.ts","sourceRoot":"","sources":["../src/bus.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7C,SAAS,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,GAAG,MAAM,IAAI,CAAA;IACvD,+FAA+F;IAC/F,MAAM,CAAC,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;CAC7C;AAED,oCAAoC;AACpC,wBAAgB,QAAQ,IAAI,eAAe,CAE1C;AAED,MAAM,WAAW,cAAc;IAC7B,0GAA0G;IAC1G,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,wDAAwD;IACxD,MAAM,EAAE,MAAM,CAAA;IACd,gEAAgE;IAChE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAChD,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAA;IACpB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CACnB;AAQD;;;GAGG;AACH,wBAAgB,OAAO,CAAC,EACtB,KAAK,EACL,MAAM,EACN,OAAiF,EACjF,OAAsB,EACtB,KAAK,EAAE,IAAY,EACnB,GAAc,GACf,EAAE,cAAc,GAAG,eAAe,CA2DlC"}
|
package/dist/bus.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/** One process: nothing to tell. */
|
|
2
|
+
export function localBus() {
|
|
3
|
+
return { publish: () => { }, subscribe: () => () => { } };
|
|
4
|
+
}
|
|
5
|
+
const WINDOW_MS = 30_000;
|
|
6
|
+
const encoder = new TextEncoder();
|
|
7
|
+
const hex = (bytes) => [...new Uint8Array(bytes)].map((b) => b.toString(16).padStart(2, '0')).join('');
|
|
8
|
+
/**
|
|
9
|
+
* Signed `POST /_hozu/invalidate` to every peer (HMAC-SHA256 over the body, which carries a timestamp; messages
|
|
10
|
+
* older than 30 s or from the future are refused). Zero dependencies: Web Crypto and `fetch`.
|
|
11
|
+
*/
|
|
12
|
+
export function httpBus({ peers, secret, onError = (error, peer) => console.error('[hozu] invalidation bus:', peer, error), retries = [100, 1_000], fetch: send = fetch, now = Date.now, }) {
|
|
13
|
+
if (secret.length < 32)
|
|
14
|
+
throw new Error('httpBus needs a secret of at least 32 characters');
|
|
15
|
+
const id = crypto.randomUUID();
|
|
16
|
+
const key = crypto.subtle.importKey('raw', encoder.encode(secret), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign', 'verify']);
|
|
17
|
+
const sign = async (body) => hex(await crypto.subtle.sign('HMAC', await key, encoder.encode(body)));
|
|
18
|
+
const listeners = new Set();
|
|
19
|
+
const wait = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
20
|
+
async function deliver(peer, body, signature) {
|
|
21
|
+
const url = `${peer.replace(/\/$/, '')}/_hozu/invalidate`;
|
|
22
|
+
for (let attempt = 0;; attempt++) {
|
|
23
|
+
try {
|
|
24
|
+
const response = await send(url, {
|
|
25
|
+
method: 'POST',
|
|
26
|
+
headers: { 'content-type': 'application/json', 'x-hozu-signature': signature },
|
|
27
|
+
body,
|
|
28
|
+
});
|
|
29
|
+
if (response.ok)
|
|
30
|
+
return;
|
|
31
|
+
throw new Error(`${url} answered ${response.status}`);
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
const delay = retries[attempt];
|
|
35
|
+
if (delay === undefined)
|
|
36
|
+
return onError(error, peer);
|
|
37
|
+
await wait(delay);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
async publish(tags) {
|
|
43
|
+
if (!tags.length)
|
|
44
|
+
return;
|
|
45
|
+
const body = JSON.stringify({ tags, at: now(), from: id });
|
|
46
|
+
const signature = await sign(body);
|
|
47
|
+
await Promise.all(peers.map((peer) => deliver(peer, body, signature)));
|
|
48
|
+
},
|
|
49
|
+
subscribe(onTags) {
|
|
50
|
+
listeners.add(onTags);
|
|
51
|
+
return () => listeners.delete(onTags);
|
|
52
|
+
},
|
|
53
|
+
async accept(request) {
|
|
54
|
+
if (request.method !== 'POST')
|
|
55
|
+
return new Response(null, { status: 405, headers: { allow: 'POST' } });
|
|
56
|
+
const body = await request.text();
|
|
57
|
+
const signature = request.headers.get('x-hozu-signature') ?? '';
|
|
58
|
+
const given = new Uint8Array(signature.match(/../g)?.map((b) => Number.parseInt(b, 16)) ?? []);
|
|
59
|
+
const valid = /^[0-9a-f]{64}$/.test(signature) &&
|
|
60
|
+
(await crypto.subtle.verify('HMAC', await key, given, encoder.encode(body)));
|
|
61
|
+
if (!valid)
|
|
62
|
+
return new Response('Invalid signature', { status: 403 });
|
|
63
|
+
const message = JSON.parse(body);
|
|
64
|
+
if (Math.abs(now() - message.at) > WINDOW_MS)
|
|
65
|
+
return new Response('Expired message', { status: 403 });
|
|
66
|
+
if (message.from !== id)
|
|
67
|
+
for (const listener of listeners)
|
|
68
|
+
listener(message.tags);
|
|
69
|
+
return new Response(null, { status: 204 });
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=bus.js.map
|
package/dist/bus.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bus.js","sourceRoot":"","sources":["../src/bus.ts"],"names":[],"mappings":"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"}
|
package/dist/cache.d.ts
CHANGED
|
@@ -10,6 +10,12 @@ export interface PageCache {
|
|
|
10
10
|
get(key: string): Promise<CachedPage | undefined>;
|
|
11
11
|
set(key: string, page: CachedPage): Promise<void>;
|
|
12
12
|
deleteTags(tags: string[]): Promise<number>;
|
|
13
|
+
/** Pages now cached and pages dropped to stay within a bound, for `server.stats()`; optional. */
|
|
14
|
+
readonly size?: number;
|
|
15
|
+
readonly evictions?: number;
|
|
13
16
|
}
|
|
14
|
-
|
|
17
|
+
/** The default page cache: at most `maxPages` pages, least recently used first out (ADR 0050 D1). */
|
|
18
|
+
export declare function memoryCache({ maxPages }?: {
|
|
19
|
+
maxPages?: number;
|
|
20
|
+
}): PageCache;
|
|
15
21
|
//# sourceMappingURL=cache.d.ts.map
|
package/dist/cache.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,EAAE,EAAE,MAAM,CAAA;IACV,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,EAAE,CAAA;CACf;AAED,MAAM,WAAW,SAAS;IACxB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAA;IACjD,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACjD,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAC3C,iGAAiG;IACjG,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAC5B;AAED,qGAAqG;AACrG,wBAAgB,WAAW,CAAC,EAAE,QAAgB,EAAE,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,SAAS,CAavF"}
|
package/dist/cache.js
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { Lru } from '@hozu/data';
|
|
2
|
+
/** The default page cache: at most `maxPages` pages, least recently used first out (ADR 0050 D1). */
|
|
3
|
+
export function memoryCache({ maxPages = 5_000 } = {}) {
|
|
4
|
+
const pages = new Lru(maxPages);
|
|
3
5
|
return {
|
|
4
6
|
get: async (key) => pages.get(key),
|
|
5
|
-
set: async (key, page) =>
|
|
6
|
-
|
|
7
|
+
set: async (key, page) => pages.set(key, page, page.tags),
|
|
8
|
+
deleteTags: async (tags) => pages.deleteTags(tags),
|
|
9
|
+
get size() {
|
|
10
|
+
return pages.size;
|
|
7
11
|
},
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
for (const [key, page] of pages)
|
|
11
|
-
if (tags.some((t) => page.tags.includes(t))) {
|
|
12
|
-
pages.delete(key);
|
|
13
|
-
count++;
|
|
14
|
-
}
|
|
15
|
-
return count;
|
|
12
|
+
get evictions() {
|
|
13
|
+
return pages.evictions;
|
|
16
14
|
},
|
|
17
15
|
};
|
|
18
16
|
}
|
package/dist/cache.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,YAAY,CAAA;AAoBhC,qGAAqG;AACrG,MAAM,UAAU,WAAW,CAAC,EAAE,QAAQ,GAAG,KAAK,EAAE,GAA0B,EAAE;IAC1E,MAAM,KAAK,GAAG,IAAI,GAAG,CAAa,QAAQ,CAAC,CAAA;IAC3C,OAAO;QACL,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;QAClC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC;QACzD,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC;QAClD,IAAI,IAAI;YACN,OAAO,KAAK,CAAC,IAAI,CAAA;QACnB,CAAC;QACD,IAAI,SAAS;YACX,OAAO,KAAK,CAAC,SAAS,CAAA;QACxB,CAAC;KACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { DevEffect, DevOptions, ProjectIR } from '@hozu/core/ir';
|
|
2
|
+
/** Fills in where each effect is implemented: its `implement(...)` in the app module, or its `fetch.ts` export. */
|
|
3
|
+
export declare function implementedAt(effects: DevEffect[] | null, dev: DevOptions, fetches: Record<string, string>, readFile: ((file: string) => Promise<Uint8Array>) | undefined): Promise<DevEffect[] | null>;
|
|
4
|
+
/** An endpoint for the DevTools API drawer: its declared method, path and input. */
|
|
5
|
+
export interface DevEndpoint {
|
|
6
|
+
ref: string;
|
|
7
|
+
method: 'GET' | 'POST';
|
|
8
|
+
path: string;
|
|
9
|
+
input: unknown;
|
|
10
|
+
raw: boolean;
|
|
11
|
+
mode: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function projectEndpoints(ir: ProjectIR): DevEndpoint[];
|
|
14
|
+
//# sourceMappingURL=dev-effects.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-effects.d.ts","sourceRoot":"","sources":["../src/dev-effects.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAIrE,mHAAmH;AACnH,wBAAsB,aAAa,CACjC,OAAO,EAAE,SAAS,EAAE,GAAG,IAAI,EAC3B,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,QAAQ,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,SAAS,GAC5D,OAAO,CAAC,SAAS,EAAE,GAAG,IAAI,CAAC,CA6B7B;AAED,oFAAoF;AACpF,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,KAAK,GAAG,MAAM,CAAA;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,OAAO,CAAA;IACd,GAAG,EAAE,OAAO,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,SAAS,GAAG,WAAW,EAAE,CAW7D"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const literal = (s) => s.replace(/[$]/g, '\\$&');
|
|
2
|
+
/** Fills in where each effect is implemented: its `implement(...)` in the app module, or its `fetch.ts` export. */
|
|
3
|
+
export async function implementedAt(effects, dev, fetches, readFile) {
|
|
4
|
+
if (!effects || !readFile)
|
|
5
|
+
return effects;
|
|
6
|
+
const texts = new Map();
|
|
7
|
+
const lines = (file) => {
|
|
8
|
+
let text = texts.get(file);
|
|
9
|
+
if (!text) {
|
|
10
|
+
text = readFile(file)
|
|
11
|
+
.then((bytes) => new TextDecoder().decode(bytes).split('\n'))
|
|
12
|
+
.catch(() => null);
|
|
13
|
+
texts.set(file, text);
|
|
14
|
+
}
|
|
15
|
+
return text;
|
|
16
|
+
};
|
|
17
|
+
const relative = (file) => file.startsWith(`${dev.root}/`) ? file.slice(dev.root.length + 1) : file;
|
|
18
|
+
return Promise.all(effects.map(async (e) => {
|
|
19
|
+
const dot = e.ref.indexOf('.');
|
|
20
|
+
const sym = literal(e.ref.slice(dot + 1));
|
|
21
|
+
const file = e.runs === 'server' ? dev.app : fetches[e.ref.slice(0, dot)];
|
|
22
|
+
if (!file)
|
|
23
|
+
return e;
|
|
24
|
+
const pattern = e.runs === 'server'
|
|
25
|
+
? new RegExp(`implement\\(\\s*(?:[\\w$]+\\.)?${sym}\\b`)
|
|
26
|
+
: new RegExp(`export const ${sym}\\b`);
|
|
27
|
+
const at = (await lines(file))?.findIndex((l) => pattern.test(l)) ?? -1;
|
|
28
|
+
return at < 0 ? e : { ...e, implemented: { file: relative(file), line: at + 1, column: 1 } };
|
|
29
|
+
}));
|
|
30
|
+
}
|
|
31
|
+
export function projectEndpoints(ir) {
|
|
32
|
+
return Object.values(ir.features).flatMap((f) => Object.entries(f.endpoints).map(([sym, e]) => ({
|
|
33
|
+
ref: `${f.id}.${sym}`,
|
|
34
|
+
method: e.method,
|
|
35
|
+
path: ir.http.basePath + e.path,
|
|
36
|
+
input: e.raw ? null : (f.schemas[e.input] ?? null),
|
|
37
|
+
raw: e.raw === true,
|
|
38
|
+
mode: e.mode,
|
|
39
|
+
})));
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=dev-effects.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-effects.js","sourceRoot":"","sources":["../src/dev-effects.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** An outgoing request made while developing (ADR 0050 G): what an effect really sent and got back. */
|
|
2
|
+
export interface TraceEntry {
|
|
3
|
+
id: number;
|
|
4
|
+
method: string;
|
|
5
|
+
url: string;
|
|
6
|
+
requestHeaders: [string, string][];
|
|
7
|
+
requestBody: string | null;
|
|
8
|
+
status: number | null;
|
|
9
|
+
responseHeaders: [string, string][];
|
|
10
|
+
responseBody: string | null;
|
|
11
|
+
ms: number;
|
|
12
|
+
error: string | null;
|
|
13
|
+
}
|
|
14
|
+
/** Wraps `fetch` once, in development only, keeping the last 200 outgoing requests. */
|
|
15
|
+
export declare function traceFetch(): void;
|
|
16
|
+
/** The requests after `after` (an id), and the last id so far. */
|
|
17
|
+
export declare const traced: (after: number) => {
|
|
18
|
+
last: number;
|
|
19
|
+
entries: TraceEntry[];
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=dev-trace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-trace.d.ts","sourceRoot":"","sources":["../src/dev-trace.ts"],"names":[],"mappings":"AAAA,uGAAuG;AACvG,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;IACX,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAA;IAClC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAA;IACnC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACrB;AAaD,uFAAuF;AACvF,wBAAgB,UAAU,SA+CzB;AA0BD,kEAAkE;AAClE,eAAO,MAAM,MAAM,UAAW,MAAM;IAAQ,IAAI;IAAY,OAAO;CAAwC,CAAA"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
const LIMIT = 200;
|
|
2
|
+
const BODY = 8_000;
|
|
3
|
+
const entries = [];
|
|
4
|
+
let next = 1;
|
|
5
|
+
let installed = false;
|
|
6
|
+
const cut = (text) => text === null ? null : text.length > BODY ? `${text.slice(0, BODY)}… (${text.length} characters)` : text;
|
|
7
|
+
const textual = (type) => !type || /json|text|xml|urlencoded|javascript/.test(type);
|
|
8
|
+
/** Wraps `fetch` once, in development only, keeping the last 200 outgoing requests. */
|
|
9
|
+
export function traceFetch() {
|
|
10
|
+
if (installed)
|
|
11
|
+
return;
|
|
12
|
+
installed = true;
|
|
13
|
+
const original = globalThis.fetch;
|
|
14
|
+
globalThis.fetch = async (input, init) => {
|
|
15
|
+
const request = new Request(input, init);
|
|
16
|
+
const entry = {
|
|
17
|
+
id: next++,
|
|
18
|
+
method: request.method,
|
|
19
|
+
url: request.url,
|
|
20
|
+
requestHeaders: [...request.headers],
|
|
21
|
+
requestBody: request.body
|
|
22
|
+
? cut(await request
|
|
23
|
+
.clone()
|
|
24
|
+
.text()
|
|
25
|
+
.catch(() => null))
|
|
26
|
+
: null,
|
|
27
|
+
status: null,
|
|
28
|
+
responseHeaders: [],
|
|
29
|
+
responseBody: null,
|
|
30
|
+
ms: 0,
|
|
31
|
+
error: null,
|
|
32
|
+
};
|
|
33
|
+
const started = performance.now();
|
|
34
|
+
const done = () => {
|
|
35
|
+
entry.ms = Math.round(performance.now() - started);
|
|
36
|
+
entries.push(entry);
|
|
37
|
+
if (entries.length > LIMIT)
|
|
38
|
+
entries.shift();
|
|
39
|
+
};
|
|
40
|
+
let response;
|
|
41
|
+
try {
|
|
42
|
+
response = await original(request);
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
entry.error = error instanceof Error ? error.message : String(error);
|
|
46
|
+
done();
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
entry.status = response.status;
|
|
50
|
+
entry.responseHeaders = [...response.headers];
|
|
51
|
+
done();
|
|
52
|
+
void capture(response.clone()).then((body) => {
|
|
53
|
+
entry.responseBody = body;
|
|
54
|
+
});
|
|
55
|
+
return response;
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/** At most BODY characters of a textual body, read beside the caller; a stream is never waited for. */
|
|
59
|
+
async function capture(response) {
|
|
60
|
+
const type = response.headers.get('content-type');
|
|
61
|
+
if (!textual(type) || /event-stream/.test(type ?? '')) {
|
|
62
|
+
void response.body?.cancel().catch(() => { });
|
|
63
|
+
return `(${type ?? 'body'})`;
|
|
64
|
+
}
|
|
65
|
+
const reader = response.body?.getReader();
|
|
66
|
+
if (!reader)
|
|
67
|
+
return null;
|
|
68
|
+
const decoder = new TextDecoder();
|
|
69
|
+
let text = '';
|
|
70
|
+
try {
|
|
71
|
+
while (text.length <= BODY) {
|
|
72
|
+
const { done, value } = await reader.read();
|
|
73
|
+
if (done)
|
|
74
|
+
break;
|
|
75
|
+
text += decoder.decode(value, { stream: true });
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return cut(text) || null;
|
|
80
|
+
}
|
|
81
|
+
void reader.cancel().catch(() => { });
|
|
82
|
+
return cut(text);
|
|
83
|
+
}
|
|
84
|
+
/** The requests after `after` (an id), and the last id so far. */
|
|
85
|
+
export const traced = (after) => ({ last: next - 1, entries: entries.filter((e) => e.id > after) });
|
|
86
|
+
//# sourceMappingURL=dev-trace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-trace.js","sourceRoot":"","sources":["../src/dev-trace.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type BuildResult, type ProjectIR } from '@hozu/core/ir';
|
|
2
|
+
/** One browser module of `fn` implementations (ADR 0050 C). */
|
|
3
|
+
export interface FnModule {
|
|
4
|
+
path: string;
|
|
5
|
+
source: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Framework builtins (`%…` operators, `#…` formats and messages, which server lowering may add to an island) share
|
|
9
|
+
* one module that every island page loads; a feature's `fn`s go in its own.
|
|
10
|
+
*/
|
|
11
|
+
export declare const moduleOfFn: (ref: string) => string;
|
|
12
|
+
/** Every `fn` reference in an IR value: `{ fn, arg }` values and `{ op: 'fn', fn, arg }` guards. */
|
|
13
|
+
export declare function fnRefs(value: unknown, out?: Set<string>): Set<string>;
|
|
14
|
+
/** The `fn`s the browser can call: those in machines and in views bound to a machine. */
|
|
15
|
+
export declare function clientFns(ir: ProjectIR): Set<string>;
|
|
16
|
+
/** The routes and endpoints an island can reach: `ui.link(route | endpoint, …)` values in nodes and machines (ADR 0050 E). */
|
|
17
|
+
export declare function linkTargets(value: unknown, out?: Set<string>): Set<string>;
|
|
18
|
+
/** The fn modules a page's islands can call: its machine-bound views and their machines, plus builtins. */
|
|
19
|
+
export declare function modulesOfPage(ir: ProjectIR, views: string[], available: Record<string, string>): string[];
|
|
20
|
+
/** The browser `fn` modules of a build, by module name, at content-hashed paths under `/_hozu/f/`. */
|
|
21
|
+
export declare function fnModules(build: BuildResult): Record<string, FnModule>;
|
|
22
|
+
//# sourceMappingURL=fn-modules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fn-modules.d.ts","sourceRoot":"","sources":["../src/fn-modules.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAY,KAAK,SAAS,EAAE,MAAM,eAAe,CAAA;AAE1E,+DAA+D;AAC/D,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;;GAGG;AACH,eAAO,MAAM,UAAU,QAAS,MAAM,WAAkE,CAAA;AAExG,oGAAoG;AACpG,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,cAAoB,GAAG,GAAG,CAAC,MAAM,CAAC,CAQ3E;AAED,yFAAyF;AACzF,wBAAgB,SAAS,CAAC,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,CASpD;AAED,8HAA8H;AAC9H,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,cAAoB,GAAG,GAAG,CAAC,MAAM,CAAC,CAShF;AAID,2GAA2G;AAC3G,wBAAgB,aAAa,CAAC,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,EAAE,CAqBzG;AA2BD,sGAAsG;AACtG,wBAAgB,SAAS,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CActE"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { hashJson } from '@hozu/core/ir';
|
|
2
|
+
/**
|
|
3
|
+
* Framework builtins (`%…` operators, `#…` formats and messages, which server lowering may add to an island) share
|
|
4
|
+
* one module that every island page loads; a feature's `fn`s go in its own.
|
|
5
|
+
*/
|
|
6
|
+
export const moduleOfFn = (ref) => (/^[%#]/.test(ref) ? 'hozu' : ref.slice(0, ref.indexOf('.')));
|
|
7
|
+
/** Every `fn` reference in an IR value: `{ fn, arg }` values and `{ op: 'fn', fn, arg }` guards. */
|
|
8
|
+
export function fnRefs(value, out = new Set()) {
|
|
9
|
+
if (Array.isArray(value))
|
|
10
|
+
for (const v of value)
|
|
11
|
+
fnRefs(v, out);
|
|
12
|
+
else if (value && typeof value === 'object') {
|
|
13
|
+
const o = value;
|
|
14
|
+
if (typeof o.fn === 'string' && 'arg' in o)
|
|
15
|
+
out.add(o.fn);
|
|
16
|
+
for (const v of Object.values(o))
|
|
17
|
+
fnRefs(v, out);
|
|
18
|
+
}
|
|
19
|
+
return out;
|
|
20
|
+
}
|
|
21
|
+
/** The `fn`s the browser can call: those in machines and in views bound to a machine. */
|
|
22
|
+
export function clientFns(ir) {
|
|
23
|
+
const out = new Set();
|
|
24
|
+
for (const f of Object.values(ir.features)) {
|
|
25
|
+
if (f.machine)
|
|
26
|
+
fnRefs(f.machine, out);
|
|
27
|
+
for (const view of Object.values(f.views))
|
|
28
|
+
if (view.machine)
|
|
29
|
+
fnRefs(view.root, out);
|
|
30
|
+
for (const q of Object.values(f.queries))
|
|
31
|
+
if (q.runs !== 'server')
|
|
32
|
+
fnRefs(q.tags, out);
|
|
33
|
+
for (const m of Object.values(f.mutations))
|
|
34
|
+
if (m.runs !== 'server')
|
|
35
|
+
fnRefs(m.invalidates, out);
|
|
36
|
+
}
|
|
37
|
+
return out;
|
|
38
|
+
}
|
|
39
|
+
/** The routes and endpoints an island can reach: `ui.link(route | endpoint, …)` values in nodes and machines (ADR 0050 E). */
|
|
40
|
+
export function linkTargets(value, out = new Set()) {
|
|
41
|
+
if (Array.isArray(value))
|
|
42
|
+
for (const v of value)
|
|
43
|
+
linkTargets(v, out);
|
|
44
|
+
else if (value && typeof value === 'object') {
|
|
45
|
+
const o = value;
|
|
46
|
+
if (typeof o.link === 'string' && 'params' in o)
|
|
47
|
+
out.add(o.link);
|
|
48
|
+
if (typeof o.endpoint === 'string' && 'input' in o)
|
|
49
|
+
out.add(o.endpoint);
|
|
50
|
+
for (const v of Object.values(o))
|
|
51
|
+
linkTargets(v, out);
|
|
52
|
+
}
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
const routeModules = new WeakMap();
|
|
56
|
+
/** The fn modules a page's islands can call: its machine-bound views and their machines, plus builtins. */
|
|
57
|
+
export function modulesOfPage(ir, views, available) {
|
|
58
|
+
const memo = routeModules.get(ir) ?? new Map();
|
|
59
|
+
routeModules.set(ir, memo);
|
|
60
|
+
const key = views.join(' ');
|
|
61
|
+
let names = memo.get(key);
|
|
62
|
+
if (!names) {
|
|
63
|
+
const refs = new Set();
|
|
64
|
+
for (const ref of views) {
|
|
65
|
+
const dot = ref.indexOf('.');
|
|
66
|
+
const feature = ir.features[ref.slice(0, dot)];
|
|
67
|
+
const view = feature?.views[ref.slice(dot + 1)];
|
|
68
|
+
if (!feature || !view?.machine)
|
|
69
|
+
continue;
|
|
70
|
+
fnRefs(view.root, refs);
|
|
71
|
+
fnRefs(ir.features[view.machine]?.machine ?? null, refs);
|
|
72
|
+
for (const q of Object.values(feature.queries))
|
|
73
|
+
if (q.runs !== 'server')
|
|
74
|
+
fnRefs(q.tags, refs);
|
|
75
|
+
for (const m of Object.values(feature.mutations))
|
|
76
|
+
if (m.runs !== 'server')
|
|
77
|
+
fnRefs(m.invalidates, refs);
|
|
78
|
+
}
|
|
79
|
+
names = [...new Set(['hozu', ...[...refs].map(moduleOfFn)])].sort();
|
|
80
|
+
memo.set(key, names);
|
|
81
|
+
}
|
|
82
|
+
return names.flatMap((n) => (available[n] ? [available[n]] : []));
|
|
83
|
+
}
|
|
84
|
+
const expressionOf = (impl) => {
|
|
85
|
+
const source = String(impl);
|
|
86
|
+
return /^(async\s+)?(function\b|\(|[A-Za-z_$][\w$]*\s*=>)/.test(source) ? source : `function ${source}`;
|
|
87
|
+
};
|
|
88
|
+
function moduleSource(build, refs) {
|
|
89
|
+
const helpers = new Map();
|
|
90
|
+
const clashing = new Set();
|
|
91
|
+
for (const ref of refs)
|
|
92
|
+
for (const [name, src] of Object.entries(build.bindings.fnHelpers[ref] ?? {})) {
|
|
93
|
+
const seen = helpers.get(name);
|
|
94
|
+
if (seen === undefined)
|
|
95
|
+
helpers.set(name, src);
|
|
96
|
+
else if (seen !== src)
|
|
97
|
+
clashing.add(name);
|
|
98
|
+
}
|
|
99
|
+
const shared = [...helpers].filter(([name]) => !clashing.has(name));
|
|
100
|
+
const entries = refs.map((ref) => {
|
|
101
|
+
const own = Object.entries(build.bindings.fnHelpers[ref] ?? {}).filter(([name]) => clashing.has(name));
|
|
102
|
+
const expression = expressionOf(build.bindings.fns[ref]);
|
|
103
|
+
if (!own.length)
|
|
104
|
+
return ` ${JSON.stringify(ref)}: ${expression},`;
|
|
105
|
+
const locals = own.map(([name, src]) => `const ${name} = ${src};`).join(' ');
|
|
106
|
+
return ` ${JSON.stringify(ref)}: (() => { ${locals} return ${expression} })(),`;
|
|
107
|
+
});
|
|
108
|
+
return `${shared.map(([name, src]) => `const ${name} = ${src};\n`).join('')}export const fns = {\n${entries.join('\n')}\n}\n`;
|
|
109
|
+
}
|
|
110
|
+
/** The browser `fn` modules of a build, by module name, at content-hashed paths under `/_hozu/f/`. */
|
|
111
|
+
export function fnModules(build) {
|
|
112
|
+
const groups = new Map();
|
|
113
|
+
const builtins = Object.keys(build.bindings.fns).filter((ref) => moduleOfFn(ref) === 'hozu');
|
|
114
|
+
for (const ref of [...new Set([...clientFns(build.ir), ...builtins])].sort()) {
|
|
115
|
+
if (!(ref in build.bindings.fns))
|
|
116
|
+
continue;
|
|
117
|
+
const name = moduleOfFn(ref);
|
|
118
|
+
groups.set(name, [...(groups.get(name) ?? []), ref]);
|
|
119
|
+
}
|
|
120
|
+
const out = {};
|
|
121
|
+
for (const [name, refs] of groups) {
|
|
122
|
+
const source = moduleSource(build, refs);
|
|
123
|
+
out[name] = { path: `/_hozu/f/${name}-${hashJson(source).slice(0, 10)}.js`, source };
|
|
124
|
+
}
|
|
125
|
+
return out;
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=fn-modules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fn-modules.js","sourceRoot":"","sources":["../src/fn-modules.ts"],"names":[],"mappings":"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"}
|
package/dist/handler.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { TagUse } from '@hozu/core';
|
|
2
2
|
import { type BuildResult, type DevOptions, type ImageSet, type Manifest } from '@hozu/core/ir';
|
|
3
|
-
import { type FetchLoader, type OnError, type ResolverSet } from '@hozu/data';
|
|
3
|
+
import { type DataCache, type FetchLoader, type OnError, type ResolverSet } from '@hozu/data';
|
|
4
4
|
import { type App, type AppHost } from './app.ts';
|
|
5
|
+
import { type InvalidationBus } from './bus.ts';
|
|
5
6
|
import { type PageCache } from './cache.ts';
|
|
6
7
|
import { type ComponentBundle, type Stylesheet } from './render.ts';
|
|
7
8
|
import { type RenderModule } from './rendered.ts';
|
|
@@ -17,6 +18,12 @@ export interface HandlerOptions {
|
|
|
17
18
|
onError?: OnError;
|
|
18
19
|
csp?: CspSources | false;
|
|
19
20
|
cache?: PageCache;
|
|
21
|
+
/** Public query results (ADR 0050 A); by default `memoryDataCache()`. */
|
|
22
|
+
dataCache?: DataCache;
|
|
23
|
+
/** Tells the other instances which tags were invalidated (ADR 0050 B); by default `localBus()`. */
|
|
24
|
+
bus?: InvalidationBus;
|
|
25
|
+
/** Seconds after which `'static'` public data and pages are read again, as a safety net when bus messages can be lost; off by default. */
|
|
26
|
+
staticTtl?: number;
|
|
20
27
|
readFile?: (file: string) => Promise<Uint8Array>;
|
|
21
28
|
manifest?: Manifest;
|
|
22
29
|
images?: ImageSet | null;
|
|
@@ -40,6 +47,16 @@ export interface OgCard {
|
|
|
40
47
|
export interface Handler {
|
|
41
48
|
fetch(request: Request): Promise<Response>;
|
|
42
49
|
revalidate(tags: TagUse[]): Promise<Revalidated>;
|
|
50
|
+
/** Cache sizes and evictions, for monitoring (ADR 0050 A). */
|
|
51
|
+
stats(): ServerStats;
|
|
52
|
+
}
|
|
53
|
+
export interface ServerStats {
|
|
54
|
+
dataEntries: number;
|
|
55
|
+
pages: number | null;
|
|
56
|
+
evictions: {
|
|
57
|
+
data: number;
|
|
58
|
+
pages: number | null;
|
|
59
|
+
};
|
|
43
60
|
}
|
|
44
61
|
export interface Revalidated {
|
|
45
62
|
entries: number;
|
package/dist/handler.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../src/handler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACxC,OAAO,EACL,KAAK,WAAW,EAGhB,KAAK,UAAU,EAOf,KAAK,QAAQ,EAGb,KAAK,QAAQ,
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../src/handler.ts"],"names":[],"mappings":"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"}
|