@vesk/runtime 0.2.8 → 0.2.10
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 +69 -2
- package/dist/md.d.ts +3 -1
- package/dist/md.d.ts.map +1 -1
- package/dist/md.js +175 -15
- package/dist/request.d.ts +28 -0
- package/dist/request.d.ts.map +1 -1
- package/dist/request.js +70 -0
- package/dist/resource.d.ts +5 -0
- package/dist/resource.d.ts.map +1 -1
- package/dist/resource.js +71 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @vesk/runtime
|
|
2
2
|
|
|
3
|
-
Vesk runtime — reactivity engine, block lifecycle, DOM operations, hydration, routing,
|
|
3
|
+
Vesk runtime — reactivity engine, block lifecycle, DOM operations, hydration, routing, server APIs, streaming resources and markdown.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -13,11 +13,78 @@ npm install @vesk/runtime
|
|
|
13
13
|
```js
|
|
14
14
|
// Client
|
|
15
15
|
import { track, effect, derived } from '@vesk/runtime';
|
|
16
|
+
import { Md } from '@vesk/runtime';
|
|
17
|
+
import { useFetch } from '@vesk/runtime';
|
|
16
18
|
|
|
17
19
|
// Server
|
|
18
|
-
import {
|
|
20
|
+
import { VeskResponse, VeskRequest } from '@vesk/runtime/server';
|
|
19
21
|
```
|
|
20
22
|
|
|
23
|
+
## Reactivity — TrackDecl
|
|
24
|
+
|
|
25
|
+
```vsk
|
|
26
|
+
component Counter {
|
|
27
|
+
const &[count] = track(0)
|
|
28
|
+
<button onClick={() => count++}>{count}</button>
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Outside `.vsk` (plain JS): `const count = track(0)` → `get(count)` / `set(count, 1)` / `peek(count)`. Inside `.vsk` with `&` the cell is auto-tracked — read/write `count` directly.
|
|
33
|
+
|
|
34
|
+
## useFetch
|
|
35
|
+
|
|
36
|
+
`useFetch` / `createResource` return a thenable `Resource<T>` (`loading`/`error`/`data`, `refresh()`/`abort()`, `into?`). SSR data is stashed in `__vsk_ssr_data` and `resolveSsrResources()`.
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
const posts = useFetch<Post[]>('/api/posts');
|
|
40
|
+
if (posts.loading) return <p>Loading…</p>;
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Helpers: `.json(url)` / `.text(url)` / `.arrayBuffer(url)` / `.stream(urlOrFn, opts)`.
|
|
44
|
+
|
|
45
|
+
### useFetch.stream — progressive streaming
|
|
46
|
+
|
|
47
|
+
Streams `res.body` chunk-by-chunk into a tracked cell so `<Md>` re-renders as data arrives. `urlOrFn` may be a provider `() => string` re-evaluated on every fetch/`refresh()` (so a tracked `docPath` propagates without recreating the resource).
|
|
48
|
+
|
|
49
|
+
```vsk
|
|
50
|
+
component Docs {
|
|
51
|
+
const &[docPath] = track('welcome') // API param — no .md needed
|
|
52
|
+
const &[doc] = track('')
|
|
53
|
+
const res = useFetch.stream(() => '/api/docs/' + docPath, { into: doc, key: 'doc' })
|
|
54
|
+
<select onchange={(e) => { docPath = (e.target as HTMLSelectElement).value; res.refresh() }}>
|
|
55
|
+
<option value="welcome">Welcome</option>
|
|
56
|
+
</select>
|
|
57
|
+
<Md content={doc} css />
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Plain JS (no `&`): `const docPath = track('welcome'); useFetch.stream(() => '/api/docs/' + get(docPath), { into: doc })`.
|
|
62
|
+
|
|
63
|
+
## Md
|
|
64
|
+
|
|
65
|
+
Tokenizer-based Markdown → HTML (GFM tables, task lists, highlighted code, heading anchors, autolinks). `content` is polymorphic:
|
|
66
|
+
|
|
67
|
+
- **String:** `<Md content="# Hello" />`
|
|
68
|
+
- **Tracked cell:** `const &[live] = track('# hi')` → `<Md content={live} css />` (live re-renders)
|
|
69
|
+
- **Streamed:** `const &[doc] = track('')` + `useFetch.stream(..., { into: doc })` → `<Md content={doc} />`
|
|
70
|
+
- **Public file path** (needs `.md` + leading `/`): `<Md content="/welcome.md" css />`, `"/game.md"`, `"/docs/guide.md"` under `public/`. Missing files render the path literally (never blank).
|
|
71
|
+
|
|
72
|
+
```vsk
|
|
73
|
+
component Page {
|
|
74
|
+
const &[pubPath] = track('/game.md')
|
|
75
|
+
<Md content={pubPath} css />
|
|
76
|
+
<Md content="/welcome.md" css />
|
|
77
|
+
<Md content="/missing.md" css /> // → renders "/missing.md" literally
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
// helper APIs
|
|
83
|
+
import { renderMarkdown, MD_BASE_CSS, sanitizeUrl } from '@vesk/runtime';
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
`VeskResponse.stream(readable)` creates a chunked `ReadableStream` response (`Transfer-Encoding: chunked`).
|
|
87
|
+
|
|
21
88
|
## License
|
|
22
89
|
|
|
23
90
|
MIT
|
package/dist/md.d.ts
CHANGED
|
@@ -85,7 +85,9 @@ export declare function setMdConsoleWarnings(enabled: boolean): void;
|
|
|
85
85
|
/** Drains the collected passthrough samples (for build-time summaries). */
|
|
86
86
|
export declare function drainMdHtmlWarnings(): MdHtmlWarning[];
|
|
87
87
|
export interface MdProps {
|
|
88
|
-
/** Markdown source — a plain string
|
|
88
|
+
/** Markdown source — a plain string, a tracked cell (reactive on client), a
|
|
89
|
+
* streamed resource (useFetch.stream — re-renders per chunk), or an
|
|
90
|
+
* absolute public markdown path (runtime-loaded from the app's public dir). */
|
|
89
91
|
content?: string | {
|
|
90
92
|
get: () => string;
|
|
91
93
|
};
|
package/dist/md.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"md.d.ts","sourceRoot":"","sources":["../src/md.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"md.d.ts","sourceRoot":"","sources":["../src/md.ts"],"names":[],"mappings":"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"}
|
package/dist/md.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { effect } from '@vesk/runtime/src/ripple-blocks';
|
|
2
|
+
import { tracked, get, set } from '@vesk/runtime/src/ripple-runtime';
|
|
3
|
+
import { getSsrData, setSsrData } from '@vesk/runtime/src/resource';
|
|
2
4
|
// =============================================================
|
|
3
5
|
// Markdown rendering for <Md content={...} />.
|
|
4
6
|
//
|
|
@@ -11,9 +13,10 @@ import { effect } from '@vesk/runtime/src/ripple-blocks';
|
|
|
11
13
|
// chrome, heading anchors, autolinks, hard breaks) and can be tuned
|
|
12
14
|
// via props (css / lineNumbers / copy / highlight / ids / autolink).
|
|
13
15
|
//
|
|
14
|
-
// `content` accepts a plain string
|
|
15
|
-
//
|
|
16
|
-
//
|
|
16
|
+
// `content` accepts a plain string, a tracked cell, a useFetch.stream()
|
|
17
|
+
// resource, or an absolute public markdown path (runtime-loaded) —
|
|
18
|
+
// cells/resources are unwrapped for rendering and, on the client,
|
|
19
|
+
// subscribed so the rendered markdown updates reactively.
|
|
17
20
|
// =============================================================
|
|
18
21
|
/** Unwraps tracked cells passed as props (compiler emits the cell itself). */
|
|
19
22
|
function unwrapMaybeCell(v) {
|
|
@@ -2177,6 +2180,126 @@ function wireCopyHandlers(root) {
|
|
|
2177
2180
|
function mdIsSSR() {
|
|
2178
2181
|
return typeof document === 'undefined';
|
|
2179
2182
|
}
|
|
2183
|
+
// =============================================================
|
|
2184
|
+
// Runtime markdown-file loading (public/*.md) + streaming support
|
|
2185
|
+
//
|
|
2186
|
+
// When `content` resolves to an absolute public markdown path
|
|
2187
|
+
// (e.g. "/docs/guide.md"), <Md> loads the FILE at runtime:
|
|
2188
|
+
// - server: adapter-installed `__vsk_md_read_file` hook reads it,
|
|
2189
|
+
// constrained to the public dir + `.md` suffixes (returns null
|
|
2190
|
+
// outside those bounds), and the content is stashed in
|
|
2191
|
+
// `__vsk_ssr_data` for hydration so there is no flash.
|
|
2192
|
+
// - client: `fetch(path)` with a per-path cache cell; while loading
|
|
2193
|
+
// (or if the file does not exist) the path itself is rendered as
|
|
2194
|
+
// literal markdown text.
|
|
2195
|
+
// `content` may also be a streaming-resource result (useFetch.stream),
|
|
2196
|
+
// whose `.into` cell is subscribed so chunks re-render progressively.
|
|
2197
|
+
// =============================================================
|
|
2198
|
+
/** Tokenizer endsWith (no regex, mirrors compiler rule). */
|
|
2199
|
+
function stringEndsWith(s, suffix) {
|
|
2200
|
+
if (suffix.length > s.length)
|
|
2201
|
+
return false;
|
|
2202
|
+
for (let i = 0; i < suffix.length; i++) {
|
|
2203
|
+
if (s[s.length - suffix.length + i] !== suffix[i])
|
|
2204
|
+
return false;
|
|
2205
|
+
}
|
|
2206
|
+
return true;
|
|
2207
|
+
}
|
|
2208
|
+
function isPublicMarkdownPath(v) {
|
|
2209
|
+
if (typeof v !== 'string')
|
|
2210
|
+
return false;
|
|
2211
|
+
const s = v;
|
|
2212
|
+
if (s.length < 2 || s.charCodeAt(0) !== 47)
|
|
2213
|
+
return false; // '/'
|
|
2214
|
+
if (s.charCodeAt(1) === 47)
|
|
2215
|
+
return false; // '//'
|
|
2216
|
+
for (let i = 0; i < s.length; i++) {
|
|
2217
|
+
const c = s.charCodeAt(i);
|
|
2218
|
+
if (c === 63 || c === 35 || c === 92)
|
|
2219
|
+
return false; // ? # \
|
|
2220
|
+
}
|
|
2221
|
+
const lower = s.toLowerCase();
|
|
2222
|
+
return stringEndsWith(lower, '.md') || stringEndsWith(lower, '.markdown');
|
|
2223
|
+
}
|
|
2224
|
+
const mdPathCache = new Map();
|
|
2225
|
+
const mdPathCells = new Map();
|
|
2226
|
+
const mdPathInflight = new Set();
|
|
2227
|
+
function getMdPathCell(path) {
|
|
2228
|
+
let cell = mdPathCells.get(path);
|
|
2229
|
+
if (!cell) {
|
|
2230
|
+
cell = tracked(undefined);
|
|
2231
|
+
mdPathCells.set(path, cell);
|
|
2232
|
+
}
|
|
2233
|
+
return cell;
|
|
2234
|
+
}
|
|
2235
|
+
function ensureMdPathLoaded(path) {
|
|
2236
|
+
if (mdPathCache.has(path) || mdPathInflight.has(path))
|
|
2237
|
+
return;
|
|
2238
|
+
const ssr = getSsrData('md:' + path);
|
|
2239
|
+
if (typeof ssr === 'string') {
|
|
2240
|
+
mdPathCache.set(path, ssr);
|
|
2241
|
+
return;
|
|
2242
|
+
}
|
|
2243
|
+
mdPathInflight.add(path);
|
|
2244
|
+
fetch(path)
|
|
2245
|
+
.then((r) => (r.ok ? r.text() : Promise.reject(r)))
|
|
2246
|
+
.then((text) => {
|
|
2247
|
+
mdPathCache.set(path, text);
|
|
2248
|
+
set(getMdPathCell(path), text);
|
|
2249
|
+
})
|
|
2250
|
+
.catch(() => {
|
|
2251
|
+
mdPathCache.set(path, null);
|
|
2252
|
+
set(getMdPathCell(path), null);
|
|
2253
|
+
})
|
|
2254
|
+
.finally(() => {
|
|
2255
|
+
mdPathInflight.delete(path);
|
|
2256
|
+
});
|
|
2257
|
+
}
|
|
2258
|
+
function readServerMdPath(path) {
|
|
2259
|
+
const hook = globalThis.__vsk_md_read_file;
|
|
2260
|
+
if (typeof hook !== 'function')
|
|
2261
|
+
return null;
|
|
2262
|
+
try {
|
|
2263
|
+
const out = hook(path);
|
|
2264
|
+
if (typeof out === 'string')
|
|
2265
|
+
return out;
|
|
2266
|
+
}
|
|
2267
|
+
catch {
|
|
2268
|
+
/* read errors fall through to literal rendering */
|
|
2269
|
+
}
|
|
2270
|
+
return null;
|
|
2271
|
+
}
|
|
2272
|
+
/**
|
|
2273
|
+
* Resolves a raw content value to the markdown SOURCE that should be
|
|
2274
|
+
* rendered. Non-path values pass through; public markdown paths are read
|
|
2275
|
+
* on the server (SSR) or resolved from cache while loading on the client.
|
|
2276
|
+
*/
|
|
2277
|
+
function resolveMdSource(value) {
|
|
2278
|
+
const s = String(value ?? '');
|
|
2279
|
+
if (!isPublicMarkdownPath(s))
|
|
2280
|
+
return s;
|
|
2281
|
+
if (mdIsSSR()) {
|
|
2282
|
+
const content = readServerMdPath(s);
|
|
2283
|
+
if (content !== null) {
|
|
2284
|
+
setSsrData('md:' + s, content);
|
|
2285
|
+
return content;
|
|
2286
|
+
}
|
|
2287
|
+
return s;
|
|
2288
|
+
}
|
|
2289
|
+
ensureMdPathLoaded(s);
|
|
2290
|
+
const cached = mdPathCache.get(s);
|
|
2291
|
+
return cached === undefined || cached === null ? s : cached;
|
|
2292
|
+
}
|
|
2293
|
+
/** Extracts the streaming target cell from a useFetch.stream() resource. */
|
|
2294
|
+
function streamCellFrom(rawContent) {
|
|
2295
|
+
if (rawContent === null || typeof rawContent !== 'object')
|
|
2296
|
+
return null;
|
|
2297
|
+
const into = rawContent.into;
|
|
2298
|
+
if (into !== null && typeof into === 'object' && typeof into.get === 'function') {
|
|
2299
|
+
return into;
|
|
2300
|
+
}
|
|
2301
|
+
return null;
|
|
2302
|
+
}
|
|
2180
2303
|
function buildHtml(content, props) {
|
|
2181
2304
|
// Per-instance props override the process-wide policy from vesk.config.ts.
|
|
2182
2305
|
const global = getMdPolicy();
|
|
@@ -2223,8 +2346,10 @@ function buildHtml(content, props) {
|
|
|
2223
2346
|
*/
|
|
2224
2347
|
export function Md(props, _registry, hydrate) {
|
|
2225
2348
|
const rawContent = props.content;
|
|
2226
|
-
const
|
|
2227
|
-
const
|
|
2349
|
+
const streamTarget = streamCellFrom(rawContent);
|
|
2350
|
+
const contentCell = streamTarget ?? rawContent;
|
|
2351
|
+
const content = String(unwrapMaybeCell(contentCell) ?? '');
|
|
2352
|
+
const html = buildHtml(resolveMdSource(content), props);
|
|
2228
2353
|
const classNameRaw = props.className != null ? String(props.className) : props.class != null ? String(props.class) : '';
|
|
2229
2354
|
const themeClass = props.theme === 'dark' ? ' vesk-md-dark' : '';
|
|
2230
2355
|
const className = `vesk-md${themeClass}${classNameRaw ? ' ' + classNameRaw : ''}`;
|
|
@@ -2239,9 +2364,11 @@ export function Md(props, _registry, hydrate) {
|
|
|
2239
2364
|
if (propFg && propFg !== 'none')
|
|
2240
2365
|
wrapperParts.push(`--md-code-fg:${propFg}`);
|
|
2241
2366
|
const wrapperStyle = wrapperParts.length > 0 ? escapeHtml(wrapperParts.join(';')) : '';
|
|
2242
|
-
// A tracked `content` cell
|
|
2243
|
-
// client (per-keystroke live
|
|
2244
|
-
|
|
2367
|
+
// A tracked `content` cell (or a streaming resource's `into` cell)
|
|
2368
|
+
// re-renders the markdown reactively on the client (per-keystroke live
|
|
2369
|
+
// editing and progressive stream chunks work without any extra wiring).
|
|
2370
|
+
const reactive = isCell(contentCell);
|
|
2371
|
+
const pathMode = isPublicMarkdownPath(content);
|
|
2245
2372
|
if (mdIsSSR()) {
|
|
2246
2373
|
const attrs = className ? ` class="${escapeHtml(className)}"` : '';
|
|
2247
2374
|
const styleAttr = style || wrapperStyle ? ` style="${[wrapperStyle, style.split('"').join('"')].filter(Boolean).join(';')}"` : '';
|
|
@@ -2254,12 +2381,25 @@ export function Md(props, _registry, hydrate) {
|
|
|
2254
2381
|
if (existing)
|
|
2255
2382
|
el = existing;
|
|
2256
2383
|
}
|
|
2257
|
-
|
|
2384
|
+
const claimed = !!el.parentNode;
|
|
2385
|
+
if (pathMode && claimed) {
|
|
2386
|
+
// Retention: the SSR render already shows this path's rendered
|
|
2387
|
+
// file (or the literal path). Only overwrite when the client has
|
|
2388
|
+
// authoritative content (hydrated ssr data / cache); otherwise
|
|
2389
|
+
// trust the markup until the client load resolves.
|
|
2390
|
+
el.setAttribute('data-vsk-md-ssr', '1');
|
|
2391
|
+
if (mdPathCache.has(content))
|
|
2392
|
+
el.innerHTML = html;
|
|
2393
|
+
}
|
|
2394
|
+
else {
|
|
2395
|
+
el.innerHTML = html;
|
|
2396
|
+
}
|
|
2258
2397
|
el.className = className;
|
|
2259
2398
|
el.style.cssText = [wrapperStyle, style].filter(Boolean).join(';');
|
|
2260
2399
|
wireCopyHandlers(el);
|
|
2261
|
-
if (reactive)
|
|
2262
|
-
subscribeContent(el,
|
|
2400
|
+
if (reactive || pathMode) {
|
|
2401
|
+
subscribeContent(el, contentCell, props, pathMode && claimed ? { trustInitialSsr: true, initialValue: content } : undefined);
|
|
2402
|
+
}
|
|
2263
2403
|
// When the element came from SSR it is already in the document —
|
|
2264
2404
|
// return an empty fragment. When the walker handed us a FRESH
|
|
2265
2405
|
// element (dynamic branch that had no SSR markup), hand the element
|
|
@@ -2273,14 +2413,34 @@ export function Md(props, _registry, hydrate) {
|
|
|
2273
2413
|
div.className = className;
|
|
2274
2414
|
div.style.cssText = [wrapperStyle, style].filter(Boolean).join(';');
|
|
2275
2415
|
wireCopyHandlers(div);
|
|
2276
|
-
if (reactive)
|
|
2277
|
-
subscribeContent(div,
|
|
2416
|
+
if (reactive || pathMode)
|
|
2417
|
+
subscribeContent(div, contentCell, props);
|
|
2278
2418
|
return div;
|
|
2279
2419
|
}
|
|
2280
|
-
function subscribeContent(el, rawContent, props) {
|
|
2420
|
+
function subscribeContent(el, rawContent, props, opts) {
|
|
2421
|
+
const trust = opts?.trustInitialSsr === true;
|
|
2422
|
+
const initial = opts?.initialValue;
|
|
2423
|
+
let ran = false;
|
|
2281
2424
|
effect(() => {
|
|
2282
2425
|
const value = String(unwrapMaybeCell(rawContent) ?? '');
|
|
2283
|
-
|
|
2426
|
+
if (isPublicMarkdownPath(value)) {
|
|
2427
|
+
const known = getSsrData('md:' + value) !== undefined || mdPathCache.has(value);
|
|
2428
|
+
ensureMdPathLoaded(value);
|
|
2429
|
+
const cell = getMdPathCell(value);
|
|
2430
|
+
get(cell);
|
|
2431
|
+
if (trust && !ran && value === initial && !known) {
|
|
2432
|
+
// Keep the SSR-rendered file visible while the client load is
|
|
2433
|
+
// in flight (or the path stays a literal on not-found).
|
|
2434
|
+
ran = true;
|
|
2435
|
+
return;
|
|
2436
|
+
}
|
|
2437
|
+
ran = true;
|
|
2438
|
+
el.innerHTML = buildHtml(resolveMdSource(value), props);
|
|
2439
|
+
wireCopyHandlers(el);
|
|
2440
|
+
return;
|
|
2441
|
+
}
|
|
2442
|
+
ran = true;
|
|
2443
|
+
el.innerHTML = buildHtml(resolveMdSource(value), props);
|
|
2284
2444
|
wireCopyHandlers(el);
|
|
2285
2445
|
});
|
|
2286
2446
|
}
|
package/dist/request.d.ts
CHANGED
|
@@ -104,6 +104,32 @@ export declare class VeskRequest extends ServerRequest {
|
|
|
104
104
|
_parsedUrl: URL | null;
|
|
105
105
|
__security?: Record<string, unknown>;
|
|
106
106
|
constructor(input: string | URL, init?: RequestInit);
|
|
107
|
+
/**
|
|
108
|
+
* The request's host header (honoring `x-forwarded-host` when
|
|
109
|
+
* setTrustProxy() is enabled). Falls back to the parsed URL host.
|
|
110
|
+
*/
|
|
111
|
+
get host(): string;
|
|
112
|
+
/** Absolute origin (`protocol://host`) — the base for resolving relative URLs. */
|
|
113
|
+
get origin(): string;
|
|
114
|
+
/**
|
|
115
|
+
* Resolves a possibly-relative URL against this request's own origin.
|
|
116
|
+
* Absolute URLs (scheme or protocol-relative `//`) pass through untouched.
|
|
117
|
+
* Used by the runtime SSR fetcher (`resolveFetchUrl`) to make in-app
|
|
118
|
+
* fetches (e.g. `/api/...`) work during server rendering.
|
|
119
|
+
*/
|
|
120
|
+
resolveUrl(url: string): string;
|
|
121
|
+
/** locals map accessors so <VeskRequest> can double as the middleware ctx. */
|
|
122
|
+
set(key: string, value: unknown): void;
|
|
123
|
+
get(key: string): unknown;
|
|
124
|
+
/**
|
|
125
|
+
* Wraps an inbound platform `Request` (from dev/prod/platform handlers)
|
|
126
|
+
* into a VeskRequest carrying the same method, headers and cookie store.
|
|
127
|
+
* Params/locals can be seeded so useParams()/useRequest() work in renders.
|
|
128
|
+
*/
|
|
129
|
+
static from(request: Request, init?: {
|
|
130
|
+
params?: Record<string, string>;
|
|
131
|
+
locals?: Record<string, unknown>;
|
|
132
|
+
}): VeskRequest;
|
|
107
133
|
get parsedUrl(): URL;
|
|
108
134
|
get query(): Record<string, string>;
|
|
109
135
|
set query(v: Record<string, string>);
|
|
@@ -163,6 +189,8 @@ declare class _VeskResponse extends ServerResponse {
|
|
|
163
189
|
static rewrite(url: string): _VeskResponse;
|
|
164
190
|
static next(): _VeskResponse;
|
|
165
191
|
static html(html: string, init?: ResponseInit): _VeskResponse;
|
|
192
|
+
/** Chunked streaming response over a `ReadableStream` body (SSE, file streams, …). */
|
|
193
|
+
static stream(readable: ReadableStream, init?: ResponseInit): _VeskResponse;
|
|
166
194
|
}
|
|
167
195
|
export declare const VeskResponse: typeof _VeskResponse & ((body?: unknown, init?: ResponseInit) => VeskResponseInstance);
|
|
168
196
|
export declare function applyRequestSecurity(request: VeskRequest, response: VeskResponseInstance): void;
|
package/dist/request.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../src/request.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../src/request.ts"],"names":[],"mappings":"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"}
|
package/dist/request.js
CHANGED
|
@@ -307,6 +307,22 @@ export class VeskRequest extends ServerRequest {
|
|
|
307
307
|
this._body = null;
|
|
308
308
|
this._bodyPromise = null;
|
|
309
309
|
this._parsedUrl = null;
|
|
310
|
+
const cookieHeader = this.headers?.get('cookie') || '';
|
|
311
|
+
if (cookieHeader) {
|
|
312
|
+
for (const part of cookieHeader.split(';')) {
|
|
313
|
+
const eq = part.indexOf('=');
|
|
314
|
+
if (eq > 0) {
|
|
315
|
+
const name = part.slice(0, eq).trim();
|
|
316
|
+
const val = part.slice(eq + 1).trim();
|
|
317
|
+
try {
|
|
318
|
+
this._cookies[name] = decodeURIComponent(val);
|
|
319
|
+
}
|
|
320
|
+
catch {
|
|
321
|
+
this._cookies[name] = val;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
310
326
|
Object.defineProperty(this, 'body', {
|
|
311
327
|
get: () => {
|
|
312
328
|
if (!this._bodyPromise) {
|
|
@@ -318,6 +334,56 @@ export class VeskRequest extends ServerRequest {
|
|
|
318
334
|
enumerable: true,
|
|
319
335
|
});
|
|
320
336
|
}
|
|
337
|
+
/**
|
|
338
|
+
* The request's host header (honoring `x-forwarded-host` when
|
|
339
|
+
* setTrustProxy() is enabled). Falls back to the parsed URL host.
|
|
340
|
+
*/
|
|
341
|
+
get host() {
|
|
342
|
+
const trust = this._security.trustProxy === true;
|
|
343
|
+
const fwd = trust ? this.headers?.get('x-forwarded-host') : undefined;
|
|
344
|
+
const header = typeof fwd === 'string' && fwd ? fwd : (this.headers?.get('host') || '');
|
|
345
|
+
if (header)
|
|
346
|
+
return header;
|
|
347
|
+
return this.parsedUrl.host || 'localhost';
|
|
348
|
+
}
|
|
349
|
+
/** Absolute origin (`protocol://host`) — the base for resolving relative URLs. */
|
|
350
|
+
get origin() {
|
|
351
|
+
return `${this.protocol}://${this.host}`;
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Resolves a possibly-relative URL against this request's own origin.
|
|
355
|
+
* Absolute URLs (scheme or protocol-relative `//`) pass through untouched.
|
|
356
|
+
* Used by the runtime SSR fetcher (`resolveFetchUrl`) to make in-app
|
|
357
|
+
* fetches (e.g. `/api/...`) work during server rendering.
|
|
358
|
+
*/
|
|
359
|
+
resolveUrl(url) {
|
|
360
|
+
if (/^[a-z][a-z0-9+.-]*:/i.test(url) || url.startsWith('//'))
|
|
361
|
+
return url;
|
|
362
|
+
return new URL(url, this.origin).href;
|
|
363
|
+
}
|
|
364
|
+
/** locals map accessors so <VeskRequest> can double as the middleware ctx. */
|
|
365
|
+
set(key, value) {
|
|
366
|
+
this._locals[key] = value;
|
|
367
|
+
}
|
|
368
|
+
get(key) {
|
|
369
|
+
return this._locals[key];
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Wraps an inbound platform `Request` (from dev/prod/platform handlers)
|
|
373
|
+
* into a VeskRequest carrying the same method, headers and cookie store.
|
|
374
|
+
* Params/locals can be seeded so useParams()/useRequest() work in renders.
|
|
375
|
+
*/
|
|
376
|
+
static from(request, init) {
|
|
377
|
+
const vreq = new VeskRequest(request instanceof Request ? request.url : String(request), {
|
|
378
|
+
method: request.method,
|
|
379
|
+
headers: request.headers,
|
|
380
|
+
});
|
|
381
|
+
if (init?.params)
|
|
382
|
+
vreq._params = { ...init.params };
|
|
383
|
+
if (init?.locals)
|
|
384
|
+
vreq._locals = { ...init.locals };
|
|
385
|
+
return vreq;
|
|
386
|
+
}
|
|
321
387
|
get parsedUrl() {
|
|
322
388
|
if (!this._parsedUrl) {
|
|
323
389
|
this._parsedUrl = new URL(this.url);
|
|
@@ -534,6 +600,10 @@ class _VeskResponse extends ServerResponse {
|
|
|
534
600
|
headers: { 'Content-Type': 'text/html; charset=utf-8', ...init?.headers },
|
|
535
601
|
});
|
|
536
602
|
}
|
|
603
|
+
/** Chunked streaming response over a `ReadableStream` body (SSE, file streams, …). */
|
|
604
|
+
static stream(readable, init) {
|
|
605
|
+
return new _VeskResponse(readable, init);
|
|
606
|
+
}
|
|
537
607
|
}
|
|
538
608
|
export const VeskResponse = new Proxy(_VeskResponse, {
|
|
539
609
|
apply(target, _thisArg, args) {
|
package/dist/resource.d.ts
CHANGED
|
@@ -35,6 +35,7 @@ export interface SsrDataSink {
|
|
|
35
35
|
clear(): void;
|
|
36
36
|
}
|
|
37
37
|
export declare function setSsrSink(sink: SsrDataSink | null): void;
|
|
38
|
+
export declare function getSsrData(key: string): unknown;
|
|
38
39
|
export declare function setSsrData(key: string, value: unknown): void;
|
|
39
40
|
export declare function clearSsrData(): void;
|
|
40
41
|
export declare function mutate(key: string, data?: unknown): void;
|
|
@@ -44,6 +45,10 @@ export declare namespace useFetch {
|
|
|
44
45
|
var text: <T = string>(url: string, options?: Omit<UseFetchOptions<T>, "body">) => Resource<T>;
|
|
45
46
|
var json: <T = unknown>(url: string, options?: Omit<UseFetchOptions<T>, "body">) => Resource<T>;
|
|
46
47
|
var arrayBuffer: <T = ArrayBuffer>(url: string, options?: Omit<UseFetchOptions<T>, "body">) => Resource<T>;
|
|
48
|
+
var stream: (urlOrFn: string | (() => string), options?: Omit<UseFetchOptions<string>, "body"> & {
|
|
49
|
+
into?: Tracked<string>;
|
|
50
|
+
onChunk?: (chunk: string, total: string) => void;
|
|
51
|
+
}) => Resource<string>;
|
|
47
52
|
}
|
|
48
53
|
export declare function resolveSsrResources(): Promise<Record<string, unknown>>;
|
|
49
54
|
//# sourceMappingURL=resource.d.ts.map
|
package/dist/resource.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["../src/resource.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAQhE,MAAM,WAAW,QAAQ,CAAC,CAAC,CAAE,SAAQ,WAAW,CAAC,CAAC,CAAC;IAClD,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,CAAC,GAAG,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,KAAK,EAAE,MAAM,IAAI,CAAC;CAClB;AAED,MAAM,WAAW,eAAe,CAAC,CAAC,CAAE,SAAQ,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC;IACpE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gGAAgG;IAChG,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,qBAAa,SAAU,SAAQ,KAAK;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;gBACP,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;CAM9C;AAED,qBAAa,YAAa,SAAQ,KAAK;gBAC1B,OAAO,EAAE,MAAM;CAI3B;AAKD,MAAM,WAAW,WAAW;IAC3B,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IACvC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;IACtC,QAAQ,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,KAAK,IAAI,IAAI,CAAC;CACd;AAID,wBAAgB,UAAU,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,GAAG,IAAI,CAEzD;
|
|
1
|
+
{"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["../src/resource.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAQhE,MAAM,WAAW,QAAQ,CAAC,CAAC,CAAE,SAAQ,WAAW,CAAC,CAAC,CAAC;IAClD,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,CAAC,GAAG,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,KAAK,EAAE,MAAM,IAAI,CAAC;CAClB;AAED,MAAM,WAAW,eAAe,CAAC,CAAC,CAAE,SAAQ,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC;IACpE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gGAAgG;IAChG,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,qBAAa,SAAU,SAAQ,KAAK;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;gBACP,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;CAM9C;AAED,qBAAa,YAAa,SAAQ,KAAK;gBAC1B,OAAO,EAAE,MAAM;CAI3B;AAKD,MAAM,WAAW,WAAW;IAC3B,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IACvC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;IACtC,QAAQ,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,KAAK,IAAI,IAAI,CAAC;CACd;AAID,wBAAgB,UAAU,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,GAAG,IAAI,CAEzD;AA2CD,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAM/C;AAsBD,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAQ5D;AAED,wBAAgB,YAAY,IAAI,IAAI,CAOnC;AA0VD,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAyBxD;AA2CD,wBAAgB,cAAc,CAAC,CAAC,EAC/B,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,GAAG,CAAC,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,OAAO,EACd,OAAO,GAAE,eAAe,CAAC,CAAC,CAAM,GAC9B,QAAQ,CAAC,CAAC,CAAC,CAsDb;AAED,wBAAgB,QAAQ,CAAC,CAAC,GAAG,OAAO,EACnC,OAAO,EAAE,MAAM,GAAG,CAAC,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC,EACpC,OAAO,GAAE,eAAe,CAAC,CAAC,CAAM,GAC9B,QAAQ,CAAC,CAAC,CAAC,CAOb;yBAVe,QAAQ;eAYP,CAAC,gBAAgB,MAAM,YAAY,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,KAAG,QAAQ,CAAC,CAAC,CAAC;eAKjF,CAAC,iBAAiB,MAAM,YAAY,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,KAAG,QAAQ,CAAC,CAAC,CAAC;sBAK3E,CAAC,qBAAqB,MAAM,YAAY,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,KAAG,QAAQ,CAAC,CAAC,CAAC;0BAepG,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,YACtB,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,GAAG;QAAE,IAAI,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,KAC5H,QAAQ,CAAC,MAAM,CAAC;;AAiBnB,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAU5E"}
|
package/dist/resource.js
CHANGED
|
@@ -46,7 +46,7 @@ function getRegistry() {
|
|
|
46
46
|
g().__vsk_fetch_registry = map;
|
|
47
47
|
return map;
|
|
48
48
|
}
|
|
49
|
-
function getSsrData(key) {
|
|
49
|
+
export function getSsrData(key) {
|
|
50
50
|
const sink = ssrSink;
|
|
51
51
|
if (sink)
|
|
52
52
|
return sink.get(key);
|
|
@@ -156,10 +156,16 @@ function buildRequestInit(options) {
|
|
|
156
156
|
function resolveFetchUrl(url) {
|
|
157
157
|
if (/^[a-z][a-z0-9+.-]*:/i.test(url) || url.startsWith('//'))
|
|
158
158
|
return url;
|
|
159
|
-
const
|
|
159
|
+
const ctx = g().__vesk_request;
|
|
160
|
+
const resolver = ctx && typeof ctx.resolveUrl === 'function'
|
|
161
|
+
? ctx.resolveUrl
|
|
162
|
+
: null;
|
|
163
|
+
if (resolver)
|
|
164
|
+
return resolver(url);
|
|
165
|
+
const reqUrl = ctx?.url;
|
|
160
166
|
const base = typeof reqUrl === 'string' && /^https?:\/\//i.test(reqUrl)
|
|
161
167
|
? reqUrl
|
|
162
|
-
:
|
|
168
|
+
: globalThis.__vesk_ssr_base_url || '';
|
|
163
169
|
if (base)
|
|
164
170
|
return new URL(url, base).href;
|
|
165
171
|
return url;
|
|
@@ -237,6 +243,43 @@ async function runFetcher(handle, timeout) {
|
|
|
237
243
|
function sleep(ms) {
|
|
238
244
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
239
245
|
}
|
|
246
|
+
/**
|
|
247
|
+
* Reads a streaming `Response` body chunk by chunk (TextDecoder) and
|
|
248
|
+
* progressively fans the running total into a tracked cell via `into`.
|
|
249
|
+
* Falls back to `res.text()` when the body has no readable stream.
|
|
250
|
+
* Returns the fully consumed string so `settle` records the final value.
|
|
251
|
+
*/
|
|
252
|
+
function streamText(res, into, onChunk) {
|
|
253
|
+
const decoder = new TextDecoder();
|
|
254
|
+
let total = '';
|
|
255
|
+
const emit = (text) => {
|
|
256
|
+
if (!text)
|
|
257
|
+
return;
|
|
258
|
+
total += text;
|
|
259
|
+
if (into)
|
|
260
|
+
setInto(into, total);
|
|
261
|
+
if (onChunk)
|
|
262
|
+
onChunk(text, total);
|
|
263
|
+
};
|
|
264
|
+
const body = res.body;
|
|
265
|
+
if (body && typeof body.getReader === 'function') {
|
|
266
|
+
const reader = body.getReader();
|
|
267
|
+
return (async () => {
|
|
268
|
+
for (;;) {
|
|
269
|
+
const { done, value } = await reader.read();
|
|
270
|
+
if (done)
|
|
271
|
+
break;
|
|
272
|
+
emit(decoder.decode(value, { stream: true }));
|
|
273
|
+
}
|
|
274
|
+
emit(decoder.decode());
|
|
275
|
+
return total;
|
|
276
|
+
})();
|
|
277
|
+
}
|
|
278
|
+
return res.text().then((text) => {
|
|
279
|
+
emit(text);
|
|
280
|
+
return total;
|
|
281
|
+
});
|
|
282
|
+
}
|
|
240
283
|
function settle(handle, data) {
|
|
241
284
|
if (handle.block !== null && is_destroyed(handle.block))
|
|
242
285
|
return;
|
|
@@ -522,6 +565,31 @@ useFetch.arrayBuffer = (url, options) => useFetch(() => doFetch(resolveFetchUrl(
|
|
|
522
565
|
...options,
|
|
523
566
|
key: options?.key ?? url,
|
|
524
567
|
});
|
|
568
|
+
/**
|
|
569
|
+
* Streaming fetch: consumes the response body chunk by chunk and reacts
|
|
570
|
+
* progressively. Each decoded chunk updates the target tracked cell (`into`),
|
|
571
|
+
* so anything subscribed to that cell (e.g. `<Md content={doc} />` or a
|
|
572
|
+
* plain `{doc}` interpolation) re-renders as data arrives. `url` may be a
|
|
573
|
+
* provider function — it is re-evaluated on every fetch (including `refresh`),
|
|
574
|
+
* so switching a tracked path propagates without recreating the resource.
|
|
575
|
+
*/
|
|
576
|
+
useFetch.stream = (urlOrFn, options) => {
|
|
577
|
+
const streamInto = options?.into;
|
|
578
|
+
const streamOnChunk = options?.onChunk;
|
|
579
|
+
const fetcher = (signal) => {
|
|
580
|
+
const url = typeof urlOrFn === 'function' ? urlOrFn() : urlOrFn;
|
|
581
|
+
const init = buildRequestInit(options ?? {});
|
|
582
|
+
return doFetch(resolveFetchUrl(url), signal ? { ...init, signal } : init).then(async (res) => {
|
|
583
|
+
if (!res.ok)
|
|
584
|
+
throw new HttpError(res.status, res.statusText);
|
|
585
|
+
return streamText(res, streamInto, streamOnChunk);
|
|
586
|
+
});
|
|
587
|
+
};
|
|
588
|
+
const key = options?.key ?? (typeof urlOrFn === 'string' ? urlOrFn : undefined);
|
|
589
|
+
const resource = useFetch(fetcher, { ...options, key });
|
|
590
|
+
resource.into = streamInto;
|
|
591
|
+
return resource;
|
|
592
|
+
};
|
|
525
593
|
export async function resolveSsrResources() {
|
|
526
594
|
const sink = ssrSink;
|
|
527
595
|
if (sink)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vesk/runtime",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.10",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Vesk runtime — reactivity, blocks, DOM operations, hydration",
|
|
6
6
|
"main": "./dist/index-client.js",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"./package.json": "./package.json"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@vesk/compiler": "^0.2.
|
|
29
|
+
"@vesk/compiler": "^0.2.10"
|
|
30
30
|
},
|
|
31
31
|
"scripts": {
|
|
32
32
|
"typecheck": "tsc --noEmit",
|