brustjs 0.1.50-alpha → 0.1.52-alpha
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/package.json +39 -15
- package/runtime/cache-sync.ts +291 -0
- package/runtime/cache.ts +4 -0
- package/runtime/cli/dev.ts +7 -0
- package/runtime/cli/native-routes-emit.ts +147 -1
- package/runtime/config.ts +42 -0
- package/runtime/index.d.ts +63 -0
- package/runtime/index.js +57 -52
- package/runtime/index.ts +108 -9
- package/runtime/native/runtime.ts +220 -7
- package/runtime/render/fragment.ts +87 -0
- package/runtime/routes.ts +225 -48
- package/runtime/templates.ts +47 -0
- package/runtime/treaty.ts +24 -1
- package/types/action-error.d.ts +18 -0
- package/types/cache-sync.d.ts +42 -0
- package/types/cache.d.ts +20 -0
- package/types/cli/help.d.ts +28 -0
- package/types/cli/jinja-staleness.d.ts +14 -0
- package/types/cli/native-routes-emit.d.ts +217 -0
- package/types/cli/new.d.ts +30 -0
- package/types/cli/templates.d.ts +39 -0
- package/types/client/index.d.ts +14 -0
- package/types/config.d.ts +42 -0
- package/types/cookies.d.ts +25 -0
- package/types/create.d.ts +1 -0
- package/types/css/build.d.ts +11 -0
- package/types/css/component-build.d.ts +17 -0
- package/types/css/component-loader.d.ts +8 -0
- package/types/css/manifest.d.ts +21 -0
- package/types/css/process-modules.d.ts +31 -0
- package/types/css/route-deps.d.ts +20 -0
- package/types/css/scan-imports.d.ts +13 -0
- package/types/css.d.ts +16 -0
- package/types/define-actions.d.ts +133 -0
- package/types/dev/client.d.ts +8 -0
- package/types/dev/coordinator.d.ts +33 -0
- package/types/dev/inject.d.ts +6 -0
- package/types/dev/jinja-reload.d.ts +7 -0
- package/types/dev/tui.d.ts +35 -0
- package/types/dev/watcher.d.ts +34 -0
- package/types/dev/worker-registry.d.ts +17 -0
- package/types/dev/ws-channel.d.ts +39 -0
- package/types/generator.d.ts +23 -0
- package/types/index.d.ts +222 -0
- package/types/islands/brust-page.d.ts +74 -0
- package/types/islands/build.d.ts +49 -0
- package/types/islands/chunk-id.d.ts +10 -0
- package/types/islands/importmap.d.ts +2 -0
- package/types/islands/island.d.ts +65 -0
- package/types/islands/isr-jsx.d.ts +31 -0
- package/types/islands/native-render.d.ts +89 -0
- package/types/loader-cache.d.ts +18 -0
- package/types/mcp/extractor.d.ts +14 -0
- package/types/mcp/manifest.d.ts +23 -0
- package/types/mcp/schema.d.ts +19 -0
- package/types/mcp/server.d.ts +15 -0
- package/types/md/emit.d.ts +72 -0
- package/types/md/render.d.ts +80 -0
- package/types/md/routes.d.ts +119 -0
- package/types/md/scan.d.ts +34 -0
- package/types/md/slug.d.ts +1 -0
- package/types/native/build.d.ts +30 -0
- package/types/native/index.d.ts +2 -0
- package/types/native/runtime.d.ts +52 -0
- package/types/navigation/active-nav.d.ts +2 -0
- package/types/navigation/index.d.ts +5 -0
- package/types/navigation/navigate.d.ts +14 -0
- package/types/navigation/react.d.ts +15 -0
- package/types/navigation/store.d.ts +44 -0
- package/types/render/fragment.d.ts +20 -0
- package/types/render/inject-action-prefix.d.ts +9 -0
- package/types/render/inject-css-link.d.ts +8 -0
- package/types/render/inject-dev-client.d.ts +6 -0
- package/types/render/inject-generator.d.ts +7 -0
- package/types/render/inject-store.d.ts +9 -0
- package/types/render/stream.d.ts +45 -0
- package/types/request-context.d.ts +16 -0
- package/types/routes.d.ts +506 -0
- package/types/sse/handler.d.ts +22 -0
- package/types/standard-schema.d.ts +31 -0
- package/types/store/define-store.d.ts +31 -0
- package/types/store/index.d.ts +5 -0
- package/types/store/react.d.ts +2 -0
- package/types/store/serialize.d.ts +5 -0
- package/types/store/server-context.d.ts +4 -0
- package/types/store/signal.d.ts +18 -0
- package/types/templates.d.ts +18 -0
- package/types/treaty.d.ts +70 -0
- package/types/ws/handler.d.ts +26 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type NavState } from './store.ts';
|
|
2
|
+
/** Watch the navigation state from a React island.
|
|
3
|
+
*
|
|
4
|
+
* ```tsx
|
|
5
|
+
* import { useNav } from 'brustjs/client'
|
|
6
|
+
* function Crumb() {
|
|
7
|
+
* const { path, phase } = useNav()
|
|
8
|
+
* return <span>{phase === 'loading' ? 'Loading…' : path}</span>
|
|
9
|
+
* }
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* The third arg (server snapshot) is the same getter — on the server the store
|
|
13
|
+
* holds its idle defaults (no `location`), so SSR renders the idle state and the
|
|
14
|
+
* client hydrates the real one on mount. */
|
|
15
|
+
export declare function useNav(): NavState;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type Signal } from '../store/signal.ts';
|
|
2
|
+
export type NavPhase = 'idle' | 'loading' | 'success' | 'error';
|
|
3
|
+
export interface NavState {
|
|
4
|
+
path: string;
|
|
5
|
+
search: string;
|
|
6
|
+
phase: NavPhase;
|
|
7
|
+
error: Error | null;
|
|
8
|
+
from: string | null;
|
|
9
|
+
to: string | null;
|
|
10
|
+
}
|
|
11
|
+
export interface NavStore {
|
|
12
|
+
path: Signal<string>;
|
|
13
|
+
search: Signal<string>;
|
|
14
|
+
phase: Signal<NavPhase>;
|
|
15
|
+
error: Signal<Error | null>;
|
|
16
|
+
from: Signal<string | null>;
|
|
17
|
+
to: Signal<string | null>;
|
|
18
|
+
}
|
|
19
|
+
type BeforeCb = (e: {
|
|
20
|
+
from: string;
|
|
21
|
+
to: string;
|
|
22
|
+
}) => void;
|
|
23
|
+
type NavCb = (e: NavState) => void;
|
|
24
|
+
type ErrorCb = (e: {
|
|
25
|
+
to: string;
|
|
26
|
+
error: Error;
|
|
27
|
+
}) => void;
|
|
28
|
+
export declare const nav: NavStore;
|
|
29
|
+
export declare function getNavState(): NavState;
|
|
30
|
+
export declare function subscribe(cb: NavCb): () => void;
|
|
31
|
+
export declare function onBeforeNavigate(cb: BeforeCb): () => void;
|
|
32
|
+
export declare function onNavigate(cb: NavCb): () => void;
|
|
33
|
+
export declare function onNavigateError(cb: ErrorCb): () => void;
|
|
34
|
+
export declare function __navInit(path: string, search: string): void;
|
|
35
|
+
export declare function __navStart(toPath: string, _toSearch: string): void;
|
|
36
|
+
export declare function __navCommit(toPath: string, toSearch: string): void;
|
|
37
|
+
export declare function __navError(toPath: string, error: unknown): void;
|
|
38
|
+
/** Register the SPA navigator implementation (bootstrap's swap). Last-write-wins;
|
|
39
|
+
* re-registration with the same closure (HMR / multiple chunks) is idempotent. */
|
|
40
|
+
export declare function registerNavigator(fn: (url: URL, replace: boolean) => Promise<void>): void;
|
|
41
|
+
/** @internal — the registered navigator, or null when no islands bootstrap loaded. */
|
|
42
|
+
export declare function _getNavigator(): ((url: URL, replace: boolean) => Promise<void>) | null;
|
|
43
|
+
export declare function __resetNavForTest(): void;
|
|
44
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type ComponentType, type ReactNode } from 'react';
|
|
2
|
+
/** Render a React element to a single HTML string, awaiting all Suspense
|
|
3
|
+
* boundaries via onAllReady. Used by navigationBranch — renderToString
|
|
4
|
+
* would only capture the shell + fallbacks, while renderBranchStreaming
|
|
5
|
+
* is for the streaming render path. */
|
|
6
|
+
export declare function renderToAwaitedString(element: ReactNode): Promise<string>;
|
|
7
|
+
export interface RenderFragmentOpts {
|
|
8
|
+
/** Request cookies visible to cookies()/session helpers inside the tree. */
|
|
9
|
+
cookies?: Record<string, string>;
|
|
10
|
+
}
|
|
11
|
+
/** Render a component to an HTML string with framework contexts scoped:
|
|
12
|
+
* request scope (cookies) ∘ request cache (cachedFetch/dedupe) ∘ store
|
|
13
|
+
* context (fresh per call — no cross-call leakage; concurrency-safe via
|
|
14
|
+
* AsyncLocalStorage). Suspense supported — the promise resolves when the
|
|
15
|
+
* whole tree is ready, never with fallbacks. Static HTML only: no island
|
|
16
|
+
* hydration markers/scripts (an `<Island>` inside the fragment SSRs its
|
|
17
|
+
* component but ships no hydration), no head/CSS collection, no streaming.
|
|
18
|
+
* Native/jinja fragments are served by `templates.render` instead.
|
|
19
|
+
* Errors reject with the component's error — no error-boundary semantics. */
|
|
20
|
+
export declare function renderFragment<P extends object>(Component: ComponentType<P>, props: P, opts?: RenderFragmentOpts): Promise<string>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** @internal — used by tests to reset the warn-once flag. */
|
|
2
|
+
export declare function _resetWarnedForTests(): void;
|
|
3
|
+
/** Splice `snippet` (a full `<script>…</script>`) into `body` immediately
|
|
4
|
+
* before the first `</head>` (case-insensitive on the four ASCII letters
|
|
5
|
+
* only). Returns the original body untouched if `snippet` is null/empty or if
|
|
6
|
+
* `</head>` is absent. */
|
|
7
|
+
export declare function injectActionPrefix(body: Uint8Array, snippet: string | null): Uint8Array;
|
|
8
|
+
export declare function configureActionPrefixSnippet(s: string | null): void;
|
|
9
|
+
export declare function getActionPrefixSnippet(): string | null;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** @internal — used by the unit test suite to reset the warn-once flag. */
|
|
2
|
+
export declare function _resetWarnedForTests(): void;
|
|
3
|
+
/** Splice `<link rel="stylesheet" href="...">` tags into `body` immediately
|
|
4
|
+
* before the first occurrence of `</head>` (case-insensitive). Returns the
|
|
5
|
+
* original body untouched if `hrefs` is empty or if `</head>` is absent
|
|
6
|
+
* (warns once in the latter case). Renderer calls this on the first chunk
|
|
7
|
+
* only — see spec S"SSR <link> injection". */
|
|
8
|
+
export declare function injectCssLink(body: Uint8Array, hrefs: readonly string[]): Uint8Array;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** @internal — used by tests to reset the warn-once flag. */
|
|
2
|
+
export declare function _resetWarnedForTests(): void;
|
|
3
|
+
/** Splice `snippet` into `body` immediately before the first `</head>`
|
|
4
|
+
* (case-insensitive on the four ASCII letters only). Returns the original body
|
|
5
|
+
* untouched if `snippet` is null/empty or if `</head>` is absent. */
|
|
6
|
+
export declare function injectDevClient(body: Uint8Array, snippet: string | null): Uint8Array;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Seed from generator.json at boot (main + worker). null → no injection. */
|
|
2
|
+
export declare function configureGeneratorMeta(meta: string | null): void;
|
|
3
|
+
export declare function getGeneratorMeta(): string | null;
|
|
4
|
+
/** Splice `metaTag` immediately before the first `</head>` (case-insensitive).
|
|
5
|
+
* No </head> in the chunk, empty tag, or an existing generator meta → body
|
|
6
|
+
* returned untouched. Byte-level (no decode) — safe with multibyte content. */
|
|
7
|
+
export declare function injectGeneratorMeta(body: Uint8Array, metaTag: string | null): Uint8Array;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** @internal — used by tests to reset the warn-once flag. */
|
|
2
|
+
export declare function _resetWarnedForTests(): void;
|
|
3
|
+
/** Build the combined `<script type="application/json">` blob for every touched
|
|
4
|
+
* store. Returns '' when the snapshot is null/empty. */
|
|
5
|
+
export declare function buildStoreScripts(snap: Record<string, Record<string, unknown>> | null): string;
|
|
6
|
+
/** Splice the store snapshot `<script>`(s) into `body` immediately before the
|
|
7
|
+
* first `</head>`. Returns the original body untouched if the snapshot is
|
|
8
|
+
* null/empty or if `</head>` is absent. */
|
|
9
|
+
export declare function injectBrustStore(body: Uint8Array, snap: Record<string, Record<string, unknown>> | null): Uint8Array;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { type ReactNode, type ComponentType } from 'react';
|
|
2
|
+
export interface RenderBranchStreamingArgs {
|
|
3
|
+
element: ReactNode;
|
|
4
|
+
/** The render's SAB sub-view (whole buffer at slots=1). All chunk encodes
|
|
5
|
+
* write at offset 0 of this view → automatically the slot's base. */
|
|
6
|
+
view: Uint8Array;
|
|
7
|
+
/** The render slot index, passed to every napi.renderChunk* call so Rust
|
|
8
|
+
* reads/writes the matching SAB sub-region. Default 0 (single-slot path). */
|
|
9
|
+
slot?: number;
|
|
10
|
+
workerId: bigint;
|
|
11
|
+
napi: {
|
|
12
|
+
renderChunk: (workerId: bigint, slot: number, len: number, sabBytes: Uint8Array) => Promise<void>;
|
|
13
|
+
renderChunkFinal: (workerId: bigint, slot: number, len: number, sabBytes: Uint8Array) => Promise<void>;
|
|
14
|
+
};
|
|
15
|
+
errorBoundary: ComponentType<{
|
|
16
|
+
error: Error;
|
|
17
|
+
}>;
|
|
18
|
+
/** Status for the successful (non-error) render. Default 200. Used by
|
|
19
|
+
* middleware-wrapped routes that want to set a non-200 status before
|
|
20
|
+
* the component runs (e.g. 201 from a server action redirect). */
|
|
21
|
+
status?: number;
|
|
22
|
+
/** Extra response headers injected by middleware (e.g. `x-render-ms`).
|
|
23
|
+
* Merged into the meta envelope's `headers` map. */
|
|
24
|
+
headers?: Record<string, string>;
|
|
25
|
+
/** The matched route's fullPath (e.g. '/' or '/blog/{slug}'). Used to
|
|
26
|
+
* combine global CSS hrefs with per-route CSS hrefs before injection. */
|
|
27
|
+
routePath?: string;
|
|
28
|
+
/** Per-request store snapshot collected after loaders run. Injected as a
|
|
29
|
+
* `<script data-brust-store="…">` blob before `</head>` (buffering) or into
|
|
30
|
+
* the streaming first-chunk prepend. Null/undefined → no injection. */
|
|
31
|
+
storeSnapshot?: Record<string, Record<string, unknown>> | null;
|
|
32
|
+
/** Inject the islands importmap + bootstrap even when no <Island> rendered.
|
|
33
|
+
* SSG fallback shells need the bootstrap (client takeover runtime) on pages
|
|
34
|
+
* that may have zero real islands. */
|
|
35
|
+
forceIslands?: boolean;
|
|
36
|
+
}
|
|
37
|
+
/** JSON.stringify the per-chunk meta. Defaults match the renderToString
|
|
38
|
+
* path so single-chunk responses keep their existing wire shape. */
|
|
39
|
+
export declare function makeMeta(opts: {
|
|
40
|
+
status: number;
|
|
41
|
+
streaming: boolean;
|
|
42
|
+
contentType?: string;
|
|
43
|
+
headers?: Record<string, string>;
|
|
44
|
+
}): string;
|
|
45
|
+
export declare function renderBranchStreaming(args: RenderBranchStreamingArgs): Promise<void>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
interface RequestScope {
|
|
2
|
+
ctx: Map<string, unknown>;
|
|
3
|
+
reqCookies: Record<string, string>;
|
|
4
|
+
setCookies: string[];
|
|
5
|
+
}
|
|
6
|
+
/** Open a per-request scope. `reqCookies` is the parsed incoming Cookie header
|
|
7
|
+
* (BrustRequest.cookies). Staged Set-Cookie strings accumulate in `setCookies`
|
|
8
|
+
* and are flushed by routes.ts onto the response headers. */
|
|
9
|
+
export declare function runInRequestScope<T>(reqCookies: Record<string, string>, fn: () => T): T;
|
|
10
|
+
/** Per-request scratch Map for apps building request-scoped state on top of the
|
|
11
|
+
* module-global store. Throws when called outside a request scope. */
|
|
12
|
+
export declare function getRequestContext(): Map<string, unknown>;
|
|
13
|
+
/** Internal — the active scope (or undefined). Used by cookies.ts and the
|
|
14
|
+
* routes.ts flush. Not re-exported from the package entry. */
|
|
15
|
+
export declare function __scope(): RequestScope | undefined;
|
|
16
|
+
export {};
|