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,217 @@
|
|
|
1
|
+
/** Gather transitive component sources starting from a page source file.
|
|
2
|
+
*
|
|
3
|
+
* BFS/DFS over local imports reachable from `pageSourcePath`:
|
|
4
|
+
* - Reads each file's source text and adds it to `sources[ident]`.
|
|
5
|
+
* - Recursively follows local imports in each visited file.
|
|
6
|
+
* - Deduplicates by resolved path to handle cycles.
|
|
7
|
+
* - `mergedImports` is the union of every visited file's `scanImports`, with
|
|
8
|
+
* the page's own imports taking precedence on a conflicting ident.
|
|
9
|
+
*
|
|
10
|
+
* Throws when the same ident resolves to two different absolute paths (across
|
|
11
|
+
* two different importing files) — that would be ambiguous for the Rust
|
|
12
|
+
* compiler. */
|
|
13
|
+
export declare function gatherComponentSources(pageSourcePath: string): {
|
|
14
|
+
sources: Record<string, string>;
|
|
15
|
+
mergedImports: Map<string, ResolvedImport>;
|
|
16
|
+
};
|
|
17
|
+
/** T2 / B1 fix — gather component sources for an ENTIRE native chain.
|
|
18
|
+
*
|
|
19
|
+
* The leaf of a composed chain is a bare fragment that no longer imports its
|
|
20
|
+
* ancestors, so seeding `gatherComponentSources` from the leaf alone would
|
|
21
|
+
* leave every ancestor's source ABSENT — `<AppLayout native>` would then
|
|
22
|
+
* silently soft-fall to an SsrComponent (React render) and break native. This
|
|
23
|
+
* unions `gatherComponentSources` over EVERY chain component's resolved source
|
|
24
|
+
* file (resolved name→file via the entry's `importMap`), then injects each
|
|
25
|
+
* chain component's OWN source keyed by its ident.
|
|
26
|
+
*
|
|
27
|
+
* Returns the merged `sources` map and `mergedImports` (ident→absolute path).
|
|
28
|
+
* Post-condition: `sources` has a key for every chain component name. Throws if
|
|
29
|
+
* a chain component name can't be resolved to a source file via `importMap`. */
|
|
30
|
+
export declare function gatherChainSources(chainNames: string[], importMap: Map<string, string>): {
|
|
31
|
+
sources: Record<string, string>;
|
|
32
|
+
mergedImports: Map<string, ResolvedImport>;
|
|
33
|
+
};
|
|
34
|
+
/** T2 — build the synthetic wrapper SOURCE STRING for a native route chain.
|
|
35
|
+
*
|
|
36
|
+
* Given the component identifiers parent→leaf (e.g. `['AppLayout', 'Leaf']`),
|
|
37
|
+
* emit a default-exported function whose body nests every component, leaf
|
|
38
|
+
* innermost, with the `native` attribute on EVERY tag:
|
|
39
|
+
*
|
|
40
|
+
* export default function Leaf__chain() { return <AppLayout native><Leaf native/></AppLayout>; }
|
|
41
|
+
*
|
|
42
|
+
* Load-bearing details:
|
|
43
|
+
* - `export default function` is required — the Rust compiler's
|
|
44
|
+
* `find_default_export` only matches that exact form.
|
|
45
|
+
* - `native` on every tag — without it a nested component lowers to an
|
|
46
|
+
* SsrComponent (React render) instead of being inlined into the chain.
|
|
47
|
+
* - The leaf tag is self-closing; each ancestor wraps the next via `<Outlet/>`
|
|
48
|
+
* inside the ancestor's own source (the compiler substitutes the children
|
|
49
|
+
* slot for `<Outlet/>`).
|
|
50
|
+
*
|
|
51
|
+
* The wrapper function name is `${leafName}__chain` — purely cosmetic (the
|
|
52
|
+
* compiler keys off the default export, not the name). */
|
|
53
|
+
export declare function buildChainWrapperSource(chainNames: string[]): string;
|
|
54
|
+
/** Count opening `<main>` tags in a compiled template. SPA navigation extracts
|
|
55
|
+
* the FIRST `<main>…</main>` block (routes.ts), so a composed native template
|
|
56
|
+
* must contain exactly one `<main>` — the layout owns it and leaf fragments must
|
|
57
|
+
* not add their own. More than one silently truncates the SPA-nav payload. */
|
|
58
|
+
export declare function countMainTags(template: string): number;
|
|
59
|
+
/** Dev-only: splice the /_brust/dev WS client `<script>` into a compiled native
|
|
60
|
+
* template so `native: true` (jinja) routes auto-reload like React-SSR routes.
|
|
61
|
+
*
|
|
62
|
+
* Native routes render Rust-side on the fast lane, bypassing the React renderer
|
|
63
|
+
* that injects the dev client (runtime/render/stream.ts) — so without this the
|
|
64
|
+
* browser on a native page never opens the dev WS and can never auto-reload.
|
|
65
|
+
*
|
|
66
|
+
* Inserted before the first `</head>` when the page has one (a `<BrustPage>`
|
|
67
|
+
* shell); otherwise appended (bare-fragment pages like a plain `<div>`). The
|
|
68
|
+
* browser executes the module script in either position. Gated on `BRUST_DEV`
|
|
69
|
+
* so `brust build` never bakes it into production templates.
|
|
70
|
+
*
|
|
71
|
+
* Exported for the md emit step (runtime/md/emit.ts), which bakes the same tag
|
|
72
|
+
* under its `withDevClient` option — md pages render Rust-side too, so without
|
|
73
|
+
* it they never auto-reload in dev. */
|
|
74
|
+
export declare function injectDevClientIntoTemplate(template: string): string;
|
|
75
|
+
/** Bake the directive runtime loader into a native template iff it uses any
|
|
76
|
+
* x-data directive. Idempotent. Wrapped in {% raw %} for symmetry with the islands
|
|
77
|
+
* bootstrap bake (the tag has no {{ }} but the wrap is harmless + consistent). */
|
|
78
|
+
export declare function bakeDirectivesIfUsed(template: string, force?: boolean): string;
|
|
79
|
+
/** Sub-project J — build pass that turns user's `pages/<Name>.tsx` files into
|
|
80
|
+
* `.brust/jinja/<Name>.jinja` templates. Invoked from `brust build` and
|
|
81
|
+
* `brust dev` after the user's routes are flattened.
|
|
82
|
+
*
|
|
83
|
+
* Limitations (spec S7 + S13.10):
|
|
84
|
+
* - Regex-based import scanner — handles `import Name from './path'` only.
|
|
85
|
+
* Full swc AST + re-export chain support deferred to v2.x.
|
|
86
|
+
* - Dev mode does NOT hot-reload templates on .tsx edit. Boot-only; restart
|
|
87
|
+
* required. Deferred per spec S12.
|
|
88
|
+
*/
|
|
89
|
+
export interface NativeRouteEmitOpts {
|
|
90
|
+
/** User's routes entry file (absolute path). Scanned for ImportDeclarations
|
|
91
|
+
* to resolve each native: true route's Component to its source .tsx. */
|
|
92
|
+
entryFile: string;
|
|
93
|
+
/** Flat routes array; only entries with `nativeTemplate` are emitted. The
|
|
94
|
+
* runtime objects are full FlatRoutes — `chain` (parent→leaf route nodes,
|
|
95
|
+
* each carrying its `Component`) drives T2 native-chain composition. */
|
|
96
|
+
flatRoutes: {
|
|
97
|
+
nativeTemplate?: string;
|
|
98
|
+
/** Chain nodes parent→leaf. A leaf carrying `__mdSource` is a markdown
|
|
99
|
+
* page (runtime/md/routes.ts) — emitted by `emitMdTemplates`, NOT here. */
|
|
100
|
+
chain?: Array<{
|
|
101
|
+
Component?: {
|
|
102
|
+
name?: string;
|
|
103
|
+
};
|
|
104
|
+
__mdSource?: unknown;
|
|
105
|
+
}>;
|
|
106
|
+
}[];
|
|
107
|
+
/** `.brust/jinja` absolute output dir. Created if missing. */
|
|
108
|
+
outDir: string;
|
|
109
|
+
/** Repo root. Retained for call-site compatibility; native compilation now
|
|
110
|
+
* goes through the napi addon's `compileJsx`, not a target/ binary. */
|
|
111
|
+
repoRoot: string;
|
|
112
|
+
/** Dev-loop incremental compile (R14). When true, each route's resolved
|
|
113
|
+
* compileJsx inputs (route source + every transitively imported local source
|
|
114
|
+
* + the lucide/directive/component-source env) are content-hashed and memoized
|
|
115
|
+
* for the lifetime of the process; an unchanged route SKIPS compileJsx and the
|
|
116
|
+
* sidecar rewrites (the previous emit's outputs are already on disk) but still
|
|
117
|
+
* appears in the returned manifest. ANY error in hashing falls back to a full
|
|
118
|
+
* compile — correctness over speed. Set only by `brust dev`'s emit calls;
|
|
119
|
+
* `brust build` stays full-fidelity (default false → no memo read OR write,
|
|
120
|
+
* and any stale memo entry for the route is dropped). */
|
|
121
|
+
incremental?: boolean;
|
|
122
|
+
/** TEST SEAM — replaces the canonical-input hasher so tests can prove the
|
|
123
|
+
* hash-failure → compile-all fallback. Never set outside tests. */
|
|
124
|
+
hashInputsForTest?: (canonicalInputs: string) => string;
|
|
125
|
+
}
|
|
126
|
+
/** Per-route emit outcome counts for `emitNativeTemplates` — testability seam
|
|
127
|
+
* for the dev-loop incremental memo (R14). `compiled + skipped` = routes
|
|
128
|
+
* emitted (routes dropped for a missing import count in neither). */
|
|
129
|
+
export interface NativeEmitStats {
|
|
130
|
+
compiled: number;
|
|
131
|
+
skipped: number;
|
|
132
|
+
}
|
|
133
|
+
/** Clear the incremental memo (test isolation). */
|
|
134
|
+
export declare function resetNativeEmitMemo(): void;
|
|
135
|
+
/** Write `<Name>.components.json` and `<Name>.factory.ts` for a native route
|
|
136
|
+
* that has SSR components. Also scans each SSR component's source for Island
|
|
137
|
+
* `component={X}` references and returns those identifiers so the build step
|
|
138
|
+
* can ensure their JS chunks are built.
|
|
139
|
+
*
|
|
140
|
+
* Both artifacts use PROJECT-RELATIVE paths, never the build machine's absolute
|
|
141
|
+
* path: `components.json` stores `sourcePath` relative to the project root
|
|
142
|
+
* (cwd); `.factory.ts` imports relative to its own location (`.brust/jinja/`).
|
|
143
|
+
* `enriched` keeps the ABSOLUTE path internally for the build-time island scan
|
|
144
|
+
* below (`readFileSync`).
|
|
145
|
+
*
|
|
146
|
+
* Exported for the md emit step (runtime/md/emit.ts), whose chained wrappers
|
|
147
|
+
* can carry layout SSR components and need the same sidecar emission. */
|
|
148
|
+
export declare function emitComponentArtifacts(jinjaPath: string, componentsJsonStr: string, pageImports: Map<string, ResolvedImport>, routeName: string): {
|
|
149
|
+
islandIdsFromComponents: string[];
|
|
150
|
+
};
|
|
151
|
+
export declare function emitNativeTemplates(opts: NativeRouteEmitOpts): Promise<NativeEmitStats>;
|
|
152
|
+
/** A resolved import reference, capturing the import FORM so the SSR factory can
|
|
153
|
+
* regenerate the correct `import` statement. Used only by the SSR-component path
|
|
154
|
+
* (`gatherComponentSources`/`gatherChainSources` → `emitComponentArtifacts` /
|
|
155
|
+
* `reconcileIslandManifest`), NOT by `scanImports` (which stays local-default
|
|
156
|
+
* string-valued for the two external callers in islands/native build). */
|
|
157
|
+
export interface ResolvedImport {
|
|
158
|
+
/** Module specifier: an ABSOLUTE file path for local imports, or the verbatim
|
|
159
|
+
* bare specifier for package imports. */
|
|
160
|
+
spec: string;
|
|
161
|
+
/** true ⇒ `spec` is a package/bare specifier (keep verbatim; do not
|
|
162
|
+
* readFileSync/relativize/recurse). */
|
|
163
|
+
bare: boolean;
|
|
164
|
+
/** How the symbol was imported, so the factory regenerates the right import. */
|
|
165
|
+
kind: 'default' | 'named' | 'namespace';
|
|
166
|
+
/** For `named`, the exported name (may differ from the local alias). */
|
|
167
|
+
imported?: string;
|
|
168
|
+
}
|
|
169
|
+
/** Scan ALL import forms in `file` and resolve each local-name binding to a
|
|
170
|
+
* {@link ResolvedImport}. Unlike {@link scanImports} (default-local only, kept
|
|
171
|
+
* stable for external callers), this:
|
|
172
|
+
* - parses default / `* as ns` / `{ a, b as c }` / mixed `d, { a }` forms;
|
|
173
|
+
* - keeps package/bare specifiers verbatim (`bare:true`) instead of skipping
|
|
174
|
+
* them — the SSR path needs them to regenerate `import` lines and to SSR
|
|
175
|
+
* third-party components (e.g. lucide-react icons).
|
|
176
|
+
*
|
|
177
|
+
* Returns `Map<localName, ResolvedImport>` (localName = the in-source identifier
|
|
178
|
+
* used in JSX). Namespace imports are recorded parse-only (the Rust compiler
|
|
179
|
+
* rejects member-expression elements, so `<Ns.Member/>` isn't renderable yet). */
|
|
180
|
+
export declare function scanImportRefs(file: string): Map<string, ResolvedImport>;
|
|
181
|
+
/** Extract static SVG node data for every `lucide-react` icon imported by
|
|
182
|
+
* `file`, keyed by its in-source local name.
|
|
183
|
+
*
|
|
184
|
+
* For each lucide import (`entry.bare && entry.spec === 'lucide-react'`), the
|
|
185
|
+
* icon's exported name (`imported` for named/aliased, the local name for a
|
|
186
|
+
* default import) is kebab-cased to locate `lucide-react/dist/esm/icons/
|
|
187
|
+
* <kebab>.mjs`, whose `__iconNode` array is reshaped into the JSON the Rust
|
|
188
|
+
* compiler deserializes: `{ cls, node: [[tag, [[attr,val],…]], …] }`. The
|
|
189
|
+
* lucide-internal `key` attr is stripped and all attr values are coerced to
|
|
190
|
+
* strings. An unresolvable icon name is silently omitted. */
|
|
191
|
+
export declare function extractLucideIcons(file: string): Promise<Record<string, string>>;
|
|
192
|
+
/** Scan the entry file's `import Name from './path'` declarations and build a
|
|
193
|
+
* map of localName -> resolved absolute path (DEFAULT-LOCAL only — package
|
|
194
|
+
* specifiers skipped). Extension resolution tries `.tsx`, `.ts`, `/index.tsx`,
|
|
195
|
+
* `/index.ts` in order. Kept string-valued + default-local for the external
|
|
196
|
+
* callers in islands/build.ts + native/build.ts; the SSR-component path uses the
|
|
197
|
+
* richer {@link scanImportRefs} instead. */
|
|
198
|
+
export declare function scanImports(entryFile: string): Map<string, string>;
|
|
199
|
+
/** Reconcile the raw `<Name>.islands.json` jsx-rustc emitted against the page's
|
|
200
|
+
* own imports, then bake the importmap+bootstrap into the `.jinja`.
|
|
201
|
+
*
|
|
202
|
+
* Pure-ish & synchronous (fs only) so it unit-tests deterministically:
|
|
203
|
+
* 1. If `islandsJsonPath` is absent → no-op (the route has no islands; the
|
|
204
|
+
* `.jinja` stays byte-identical).
|
|
205
|
+
* 2. Resolve every entry's `sourcePath` from the page's `import <component>
|
|
206
|
+
* from "..."` (else throw).
|
|
207
|
+
* 3. Enrich each entry with that absolute `sourcePath` and rewrite the
|
|
208
|
+
* `.islands.json`.
|
|
209
|
+
* 4. Append `{% raw %}…{% endraw %}`-wrapped bootstrap to the `.jinja`. The raw
|
|
210
|
+
* block keeps the importmap's literal `}}`/`{{` inert through minijinja's
|
|
211
|
+
* boot-time compile. The md emit step passes `bakeBootstrap: false` and bakes
|
|
212
|
+
* once itself at the END of its pipeline (the append here has no `includes()`
|
|
213
|
+
* guard, so a second pass over the same template would double-bake).
|
|
214
|
+
*/
|
|
215
|
+
export declare function reconcileIslandManifest(jinjaPath: string, islandsJsonPath: string, pageImports: Map<string, ResolvedImport>, routeName: string, options?: {
|
|
216
|
+
bakeBootstrap?: boolean;
|
|
217
|
+
}): void;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type EmittedFile, type TemplateDef } from './templates.ts';
|
|
2
|
+
export interface ParsedNewArgs {
|
|
3
|
+
projectName: string;
|
|
4
|
+
targetDir: string;
|
|
5
|
+
template?: string;
|
|
6
|
+
yes: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare function parseArgs(args: string[]): ParsedNewArgs;
|
|
9
|
+
export interface BrustRef {
|
|
10
|
+
kind: 'file' | 'version';
|
|
11
|
+
spec: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function resolveBrustRef(startDir?: string): BrustRef;
|
|
14
|
+
export interface CopyTemplateOpts {
|
|
15
|
+
templateDir: string;
|
|
16
|
+
targetDir: string;
|
|
17
|
+
substitutions: Record<string, string>;
|
|
18
|
+
exclude?: Set<string>;
|
|
19
|
+
extraFiles?: EmittedFile[];
|
|
20
|
+
}
|
|
21
|
+
export declare function copyTemplate(opts: CopyTemplateOpts): Promise<void>;
|
|
22
|
+
export interface SelectTemplateOpts {
|
|
23
|
+
explicit?: string;
|
|
24
|
+
yes: boolean;
|
|
25
|
+
isTTY: boolean;
|
|
26
|
+
read?: (label: string) => string | null;
|
|
27
|
+
print?: (s: string) => void;
|
|
28
|
+
}
|
|
29
|
+
export declare function selectTemplate(opts: SelectTemplateOpts): TemplateDef;
|
|
30
|
+
export declare function runNew(args: string[]): Promise<void>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface ScaffoldCtx {
|
|
2
|
+
projectName: string;
|
|
3
|
+
/** Raw brust dep spec, e.g. "file:/abs/path" or "^0.1.16-alpha". */
|
|
4
|
+
brustSpec: string;
|
|
5
|
+
}
|
|
6
|
+
export interface EmittedFile {
|
|
7
|
+
/** POSIX-relative destination path under the project root. */
|
|
8
|
+
relPath: string;
|
|
9
|
+
content: string;
|
|
10
|
+
}
|
|
11
|
+
export interface TemplateDef {
|
|
12
|
+
name: string;
|
|
13
|
+
title: string;
|
|
14
|
+
description: string;
|
|
15
|
+
sourceDir: string;
|
|
16
|
+
/**
|
|
17
|
+
* POSIX-relative paths (from sourceDir) to skip when copying. Matching uses
|
|
18
|
+
* the SOURCE entry name (pre-`renameForEmit`), so to exclude an emitted
|
|
19
|
+
* `.gitignore` you list its source name `_gitignore`, not `.gitignore`.
|
|
20
|
+
*/
|
|
21
|
+
exclude: Set<string>;
|
|
22
|
+
/** Files the source tree lacks, generated at scaffold time. */
|
|
23
|
+
extraFiles?: (ctx: ScaffoldCtx) => EmittedFile[];
|
|
24
|
+
}
|
|
25
|
+
export declare const DEFAULT_TEMPLATE = "minimal";
|
|
26
|
+
/**
|
|
27
|
+
* Walk up from `startDir` to the directory of the nearest package.json whose
|
|
28
|
+
* `name === 'brustjs'`. Single source of truth for locating the brust package
|
|
29
|
+
* root (consumed by both `resolveBrustRef` and pokedex template resolution).
|
|
30
|
+
* Works in the source tree (repo root) and a published install
|
|
31
|
+
* (`node_modules/brustjs`). Throws if no such package.json is found.
|
|
32
|
+
*/
|
|
33
|
+
export declare function findBrustPackageRoot(startDir?: string): string;
|
|
34
|
+
/**
|
|
35
|
+
* Build the template registry fresh per call so a missing/corrupt install
|
|
36
|
+
* surfaces as a thrown error at invocation time (not import time).
|
|
37
|
+
*/
|
|
38
|
+
export declare function listTemplates(): TemplateDef[];
|
|
39
|
+
export declare function getTemplate(name: string): TemplateDef | undefined;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Browser-only client helpers. This module is loaded by hydrated island
|
|
2
|
+
* bundles. It intentionally does NOT import from runtime/routes.ts or
|
|
3
|
+
* runtime/index.ts — those pull in React and server-side surface that the
|
|
4
|
+
* client doesn't need.
|
|
5
|
+
*/
|
|
6
|
+
export declare class BrustActionError extends Error {
|
|
7
|
+
readonly status: number;
|
|
8
|
+
readonly payload: unknown;
|
|
9
|
+
constructor(message: string, status: number, payload: unknown);
|
|
10
|
+
}
|
|
11
|
+
export { client } from '../treaty.ts';
|
|
12
|
+
export type { TreatyResponse, ClientOptions } from '../treaty.ts';
|
|
13
|
+
export { useStore } from '../store/react.ts';
|
|
14
|
+
export { useNav } from '../navigation/react.ts';
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export interface BrustConfig {
|
|
2
|
+
/** Host/address to bind on. Default `localhost`. Accepts a hostname
|
|
3
|
+
* (resolved Rust-side) or a literal IP such as `0.0.0.0` / `127.0.0.1`. */
|
|
4
|
+
host: string;
|
|
5
|
+
/** TCP port to bind on. Default 1337. */
|
|
6
|
+
port: number;
|
|
7
|
+
/** Bun Worker count for render dispatch. Default `availableParallelism()`. */
|
|
8
|
+
workers: number;
|
|
9
|
+
/** L1 response-cache capacity (entries). Undefined → Rust default of 1000. */
|
|
10
|
+
cacheMaxEntries?: number;
|
|
11
|
+
/** L2 page-cache capacity (entries). Undefined → Rust default of 1000. */
|
|
12
|
+
cachePageMaxEntries?: number;
|
|
13
|
+
/** R9 cross-process cache invalidation: redis/dragonfly URL. Absent →
|
|
14
|
+
* feature disabled (current single-process behavior). */
|
|
15
|
+
cacheSyncUrl?: string;
|
|
16
|
+
/** Pub/sub channel for cache invalidation. Undefined → module default
|
|
17
|
+
* (`brust:cache:invalidate`). */
|
|
18
|
+
cacheSyncChannel?: string;
|
|
19
|
+
}
|
|
20
|
+
/** Caller-supplied fallbacks (e.g. `brust.run({ address, port })`) applied
|
|
21
|
+
* BELOW env + TOML but ABOVE the framework defaults. */
|
|
22
|
+
export interface ConfigDefaults {
|
|
23
|
+
host?: string;
|
|
24
|
+
port?: number;
|
|
25
|
+
}
|
|
26
|
+
export declare class BrustConfigError extends Error {
|
|
27
|
+
readonly file: string | null;
|
|
28
|
+
constructor(message: string, file: string | null);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Resolve Brust configuration. Precedence (low → high):
|
|
32
|
+
* framework defaults < caller `defaults` < TOML < env.
|
|
33
|
+
*
|
|
34
|
+
* - Framework defaults: { host: 'localhost', port: 1337, workers: availableParallelism() }
|
|
35
|
+
* - Caller `defaults`: e.g. `brust.run({ address, port })` — app-level fallbacks
|
|
36
|
+
* that fill in only when neither TOML nor env specify the value (so a
|
|
37
|
+
* `brust dev --port` / BRUST_PORT still wins over code).
|
|
38
|
+
* - TOML: brust.toml at `cwd` (missing file is fine — only a present file with
|
|
39
|
+
* wrong shape is an error). `[server] address` / `port`.
|
|
40
|
+
* - Env: BRUST_ADDR, BRUST_PORT, BRUST_WORKERS override either source.
|
|
41
|
+
*/
|
|
42
|
+
export declare function loadConfig(cwd?: string, defaults?: ConfigDefaults): Promise<BrustConfig>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface CookieOptions {
|
|
2
|
+
maxAge?: number;
|
|
3
|
+
expires?: Date;
|
|
4
|
+
path?: string;
|
|
5
|
+
domain?: string;
|
|
6
|
+
secure?: boolean;
|
|
7
|
+
httpOnly?: boolean;
|
|
8
|
+
sameSite?: 'Strict' | 'Lax' | 'None';
|
|
9
|
+
}
|
|
10
|
+
/** Serialize a single Set-Cookie value. The value is URL-encoded; attributes
|
|
11
|
+
* are appended in a stable order. Mirrors the standard cookie attribute names.
|
|
12
|
+
*
|
|
13
|
+
* Hardening: the name is validated as an RFC 6265 token, and the final line is
|
|
14
|
+
* asserted CRLF-free — so a stray `\r\n` in a name/path/domain (which are NOT
|
|
15
|
+
* URL-encoded, unlike the value) can't smuggle an extra response header. */
|
|
16
|
+
export declare function serializeCookie(name: string, value: string, opts?: CookieOptions): string;
|
|
17
|
+
/** Per-request cookie helper. `get` reads the incoming request cookies; `set`
|
|
18
|
+
* and `delete` stage a Set-Cookie onto the active request scope, flushed onto
|
|
19
|
+
* the response by routes.ts. Outside a request scope, `set`/`delete` are no-ops
|
|
20
|
+
* (dev-warn under BRUST_DEV). */
|
|
21
|
+
export declare const cookies: {
|
|
22
|
+
get(name: string): string | undefined;
|
|
23
|
+
set(name: string, value: string, opts?: CookieOptions): void;
|
|
24
|
+
delete(name: string, opts?: Pick<CookieOptions, "path" | "domain">): void;
|
|
25
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { runNew } from './cli/new.ts';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface BuildCssOptions {
|
|
2
|
+
/** Absolute path to the entry CSS file (typically <scanRoot>/app.css). */
|
|
3
|
+
entry: string;
|
|
4
|
+
/** Absolute path to the output directory. Created if missing. */
|
|
5
|
+
outDir: string;
|
|
6
|
+
}
|
|
7
|
+
export interface CssBuildResult {
|
|
8
|
+
outDir: string;
|
|
9
|
+
files: string[];
|
|
10
|
+
}
|
|
11
|
+
export declare function buildCss(opts: BuildCssOptions): Promise<CssBuildResult>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { processCssFile } from './process-modules.ts';
|
|
2
|
+
import { type RouteForCss } from './route-deps.ts';
|
|
3
|
+
import { type ComponentCssManifest } from './manifest.ts';
|
|
4
|
+
export interface BuildComponentCssOptions {
|
|
5
|
+
/** Absolute path to the user's app dir (where Home.tsx lives). */
|
|
6
|
+
scanRoot: string;
|
|
7
|
+
/** Absolute path under which chunk files + manifest are written. */
|
|
8
|
+
outDir: string;
|
|
9
|
+
/** Optional Tailwind compiler (for @apply resolution). */
|
|
10
|
+
tailwindCompile: Parameters<typeof processCssFile>[0]['tailwindCompile'];
|
|
11
|
+
/** Routes to map to CSS chunks. */
|
|
12
|
+
routes: RouteForCss[];
|
|
13
|
+
}
|
|
14
|
+
/** Run the full component CSS pipeline: scan → process → emit chunks +
|
|
15
|
+
* .d.ts + manifest. Returns the in-memory manifest for callers (brust.run)
|
|
16
|
+
* that need to register the Bun.plugin immediately. */
|
|
17
|
+
export declare function buildComponentCss(opts: BuildComponentCssOptions): Promise<ComponentCssManifest>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { BunPlugin } from 'bun';
|
|
2
|
+
import type { ComponentCssManifest } from './manifest.ts';
|
|
3
|
+
/** Build a Bun.plugin that resolves component CSS imports.
|
|
4
|
+
* - .module.css → `export default <name-map>` (JS, baked from manifest)
|
|
5
|
+
* - .css → empty JS (side-effect; real CSS already on disk)
|
|
6
|
+
*
|
|
7
|
+
* Register once per isolate (brust.run main + each worker). */
|
|
8
|
+
export declare function cssLoaderPlugin(manifest: ComponentCssManifest): BunPlugin;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** Per-CSS-file entry. Side-effect imports (.css) have exports:null;
|
|
2
|
+
* CSS Modules (.module.css) have a flat name→hashed-name map. */
|
|
3
|
+
export interface ComponentCssModuleEntry {
|
|
4
|
+
/** Absolute URL path served by Rust (e.g. /_brust/css/components/<sha>.css). */
|
|
5
|
+
chunk: string;
|
|
6
|
+
/** Original class name → hashed class name. null for non-module .css. */
|
|
7
|
+
exports: Record<string, string> | null;
|
|
8
|
+
}
|
|
9
|
+
export interface ComponentCssManifest {
|
|
10
|
+
version: 1;
|
|
11
|
+
/** Absolute filesystem path of the source .css file → entry. */
|
|
12
|
+
modules: Record<string, ComponentCssModuleEntry>;
|
|
13
|
+
/** Route.fullPath → ordered, deduplicated chunk href list. */
|
|
14
|
+
routeChunks: Record<string, string[]>;
|
|
15
|
+
}
|
|
16
|
+
/** Read + validate. Returns null when the file doesn't exist (project has
|
|
17
|
+
* no component CSS — treated as a no-op everywhere). Throws on malformed
|
|
18
|
+
* JSON or version mismatch. */
|
|
19
|
+
export declare function readComponentCssManifest(absolutePath: string): Promise<ComponentCssManifest | null>;
|
|
20
|
+
/** Write to disk. Creates the parent directory if needed. */
|
|
21
|
+
export declare function writeComponentCssManifest(absolutePath: string, manifest: ComponentCssManifest): Promise<void>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface ProcessCssOptions {
|
|
2
|
+
/** Absolute path; Lightning CSS uses this to derive [hash] in cssModules pattern. */
|
|
3
|
+
filename: string;
|
|
4
|
+
/** Source CSS text. */
|
|
5
|
+
source: string;
|
|
6
|
+
/** True iff this file is a .module.css. */
|
|
7
|
+
isModule: boolean;
|
|
8
|
+
/** Optional Tailwind compiler. When set, source is piped through it FIRST
|
|
9
|
+
* so @apply directives resolve before module class rewriting. Null when
|
|
10
|
+
* Tailwind isn't available. */
|
|
11
|
+
tailwindCompile: {
|
|
12
|
+
build(candidates: string[]): string;
|
|
13
|
+
sources: {
|
|
14
|
+
base: string;
|
|
15
|
+
pattern: string;
|
|
16
|
+
negated: boolean;
|
|
17
|
+
}[];
|
|
18
|
+
} | null;
|
|
19
|
+
}
|
|
20
|
+
export interface ProcessCssResult {
|
|
21
|
+
/** Compiled CSS bytes. */
|
|
22
|
+
code: Uint8Array;
|
|
23
|
+
/** null for non-module files; original→hashed name map for .module.css. */
|
|
24
|
+
exports: Record<string, string> | null;
|
|
25
|
+
}
|
|
26
|
+
/** Pipe a CSS file through Tailwind (if available) then Lightning CSS.
|
|
27
|
+
* For .module.css, class names are hashed via Lightning's default
|
|
28
|
+
* pattern `[local]_[hash]` where [hash] is file-derived (~6 chars).
|
|
29
|
+
* Two classes in the same file share the suffix; two files with the same
|
|
30
|
+
* class name get different hashes. */
|
|
31
|
+
export declare function processCssFile(opts: ProcessCssOptions): Promise<ProcessCssResult>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { CssDep } from './scan-imports.ts';
|
|
2
|
+
export interface RouteForCss {
|
|
3
|
+
/** Route.fullPath (e.g. '/' or '/blog/{slug}'). */
|
|
4
|
+
fullPath: string;
|
|
5
|
+
/** Absolute source files of the route's component CHAIN (root layout → leaf).
|
|
6
|
+
* computeRouteChunks walks the local import graph from each and unions the
|
|
7
|
+
* CSS deps it finds — so a layout's co-located `.module.css` links to every
|
|
8
|
+
* route under it, and a leaf's links only to that route. */
|
|
9
|
+
componentSources: string[];
|
|
10
|
+
}
|
|
11
|
+
/** Build the route → CSS chunk hrefs map.
|
|
12
|
+
*
|
|
13
|
+
* For each route, BFS the LOCAL import graph rooted at the route's component
|
|
14
|
+
* chain (via {@link scanImports}, same default-import walk islands use) and
|
|
15
|
+
* collect the CSS deps of every reachable file. This means a `.module.css`
|
|
16
|
+
* co-located with the component that imports it is enough — no need to also
|
|
17
|
+
* import it in routes.tsx. Chunks are deduplicated and sorted per route. */
|
|
18
|
+
export declare function computeRouteChunks(routes: RouteForCss[], scan: Map<string, CssDep[]>, modules: Record<string, {
|
|
19
|
+
chunk: string;
|
|
20
|
+
}>): Record<string, string[]>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface CssDep {
|
|
2
|
+
/** Absolute path to the .css or .module.css file. */
|
|
3
|
+
path: string;
|
|
4
|
+
/** True iff the file ends with `.module.css`. */
|
|
5
|
+
isModule: boolean;
|
|
6
|
+
/** Default-import binding name (e.g. `styles` for `import styles from ...`).
|
|
7
|
+
* null for side-effect imports (`import './foo.css'`). */
|
|
8
|
+
importedName: string | null;
|
|
9
|
+
}
|
|
10
|
+
/** Walk `scanRoot` recursively, parse every TS/TSX file with the TypeScript
|
|
11
|
+
* compiler API, return a map of source file → CSS deps. Files outside
|
|
12
|
+
* scanRoot, inside ignored dirs, or test files are skipped. */
|
|
13
|
+
export declare function scanCssImports(scanRoot: string): Promise<Map<string, CssDep[]>>;
|
package/types/css.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Configure the list of stylesheet hrefs that the renderer should
|
|
2
|
+
* inject into the SSR HTML before </head>. Replaces any previous list.
|
|
3
|
+
* Called from brust.run() main and worker branches (both need to know
|
|
4
|
+
* so the per-worker renderer can inject). */
|
|
5
|
+
export declare function configureCssEnabled(hrefs: readonly string[]): void;
|
|
6
|
+
/** Returns the configured hrefs as a defensive copy. */
|
|
7
|
+
export declare function getCssHrefs(): readonly string[];
|
|
8
|
+
/** Set the CSS hrefs to inject for a specific route. Replaces any previous
|
|
9
|
+
* list for that route. Called from brust.run() main after the component
|
|
10
|
+
* manifest loads. Keys are route.fullPath strings (e.g. '/' or '/blog/{slug}'). */
|
|
11
|
+
export declare function configureCssHrefsForRoute(routePath: string, hrefs: readonly string[]): void;
|
|
12
|
+
/** Returns the CSS hrefs for a specific route, or [] when none configured.
|
|
13
|
+
* Defensive copy on the way out. */
|
|
14
|
+
export declare function getCssHrefsForRoute(routePath: string): readonly string[];
|
|
15
|
+
/** @internal — used by the unit test suite to wipe both global and per-route state. */
|
|
16
|
+
export declare function _resetCssForTests(): void;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import type { BrustRequest, Middleware } from './routes.ts';
|
|
2
|
+
import type { StandardSchemaV1, InferOutput } from './standard-schema.ts';
|
|
3
|
+
declare const RESPOND: unique symbol;
|
|
4
|
+
export interface ActionResponseSentinel {
|
|
5
|
+
readonly [RESPOND]: true;
|
|
6
|
+
status: number;
|
|
7
|
+
body: unknown;
|
|
8
|
+
headers?: Record<string, string>;
|
|
9
|
+
}
|
|
10
|
+
export declare function isRespondSentinel(v: unknown): v is ActionResponseSentinel;
|
|
11
|
+
export declare function makeRespond(): (body: unknown, init?: {
|
|
12
|
+
status?: number;
|
|
13
|
+
headers?: Record<string, string>;
|
|
14
|
+
}) => ActionResponseSentinel;
|
|
15
|
+
export interface ActionContext<Body = unknown, Params = Record<string, string>, Query = Record<string, string>> {
|
|
16
|
+
req: BrustRequest;
|
|
17
|
+
body: Body;
|
|
18
|
+
params: Params;
|
|
19
|
+
query: Query;
|
|
20
|
+
headers: Record<string, string>;
|
|
21
|
+
respond: (body: unknown, init?: {
|
|
22
|
+
status?: number;
|
|
23
|
+
headers?: Record<string, string>;
|
|
24
|
+
}) => ActionResponseSentinel;
|
|
25
|
+
}
|
|
26
|
+
type Handler<B, P, Q, R> = (ctx: ActionContext<B, P, Q>) => R | Promise<R>;
|
|
27
|
+
export interface EndpointOptions {
|
|
28
|
+
body?: StandardSchemaV1;
|
|
29
|
+
query?: StandardSchemaV1;
|
|
30
|
+
middleware?: Middleware[];
|
|
31
|
+
/** Build-time MCP tool description (read by the manifest extractor). */
|
|
32
|
+
description?: string;
|
|
33
|
+
/** Declared domain errors, keyed by code. Each value is a StandardSchema for
|
|
34
|
+
* the error's `data` payload. TYPE-ONLY: flows into the treaty client's typed
|
|
35
|
+
* error union; the runtime ignores it (handlers throw `ActionError`). */
|
|
36
|
+
errors?: Record<string, StandardSchemaV1>;
|
|
37
|
+
}
|
|
38
|
+
export interface EndpointDef {
|
|
39
|
+
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD';
|
|
40
|
+
path: string;
|
|
41
|
+
handler: (ctx: ActionContext) => unknown;
|
|
42
|
+
body?: StandardSchemaV1;
|
|
43
|
+
query?: StandardSchemaV1;
|
|
44
|
+
middleware: Middleware[];
|
|
45
|
+
}
|
|
46
|
+
type ParamKeys<P extends string> = P extends `${string}{${infer K}}${infer Rest}` ? (K extends `*${infer C}` ? C : K) | ParamKeys<Rest> : never;
|
|
47
|
+
type Params<P extends string> = [ParamKeys<P>] extends [never] ? Record<string, string> : {
|
|
48
|
+
[K in ParamKeys<P>]: string;
|
|
49
|
+
};
|
|
50
|
+
type BodyOf<O> = O extends {
|
|
51
|
+
body: infer S;
|
|
52
|
+
} ? S extends StandardSchemaV1 ? InferOutput<S> : unknown : unknown;
|
|
53
|
+
type QueryOf<O> = O extends {
|
|
54
|
+
query: infer S;
|
|
55
|
+
} ? S extends StandardSchemaV1 ? InferOutput<S> : unknown : Record<string, string>;
|
|
56
|
+
/** Discriminated error union derived from `opts.errors`. Each declared code maps
|
|
57
|
+
* to `{ code; message; data }` where `data` is the schema's inferred output. */
|
|
58
|
+
type ErrorOf<O> = O extends {
|
|
59
|
+
errors: infer E;
|
|
60
|
+
} ? {
|
|
61
|
+
[K in keyof E & string]: {
|
|
62
|
+
code: K;
|
|
63
|
+
message: string;
|
|
64
|
+
data: E[K] extends StandardSchemaV1 ? InferOutput<E[K]> : unknown;
|
|
65
|
+
};
|
|
66
|
+
}[keyof E & string] : never;
|
|
67
|
+
export type EndpointEntry = {
|
|
68
|
+
input: unknown;
|
|
69
|
+
output: unknown;
|
|
70
|
+
error: unknown;
|
|
71
|
+
};
|
|
72
|
+
export type EndpointMap = Record<string, Partial<Record<EndpointDef['method'], EndpointEntry>>>;
|
|
73
|
+
export declare function isValidEndpointPath(p: string): boolean;
|
|
74
|
+
export interface ActionsBuilder<Acc extends EndpointMap = {}> {
|
|
75
|
+
endpoints: EndpointDef[];
|
|
76
|
+
use(mw: Middleware): ActionsBuilder<Acc>;
|
|
77
|
+
get<P extends string, O extends EndpointOptions, R>(path: P, handler: Handler<BodyOf<O>, Params<P>, QueryOf<O>, R>, opts?: O): ActionsBuilder<Acc & {
|
|
78
|
+
[K in P]: {
|
|
79
|
+
GET: {
|
|
80
|
+
input: QueryOf<O>;
|
|
81
|
+
output: Awaited<R>;
|
|
82
|
+
error: ErrorOf<O>;
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
}>;
|
|
86
|
+
post<P extends string, O extends EndpointOptions, R>(path: P, handler: Handler<BodyOf<O>, Params<P>, QueryOf<O>, R>, opts?: O): ActionsBuilder<Acc & {
|
|
87
|
+
[K in P]: {
|
|
88
|
+
POST: {
|
|
89
|
+
input: BodyOf<O>;
|
|
90
|
+
output: Awaited<R>;
|
|
91
|
+
error: ErrorOf<O>;
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
}>;
|
|
95
|
+
put<P extends string, O extends EndpointOptions, R>(path: P, handler: Handler<BodyOf<O>, Params<P>, QueryOf<O>, R>, opts?: O): ActionsBuilder<Acc & {
|
|
96
|
+
[K in P]: {
|
|
97
|
+
PUT: {
|
|
98
|
+
input: BodyOf<O>;
|
|
99
|
+
output: Awaited<R>;
|
|
100
|
+
error: ErrorOf<O>;
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
}>;
|
|
104
|
+
patch<P extends string, O extends EndpointOptions, R>(path: P, handler: Handler<BodyOf<O>, Params<P>, QueryOf<O>, R>, opts?: O): ActionsBuilder<Acc & {
|
|
105
|
+
[K in P]: {
|
|
106
|
+
PATCH: {
|
|
107
|
+
input: BodyOf<O>;
|
|
108
|
+
output: Awaited<R>;
|
|
109
|
+
error: ErrorOf<O>;
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
}>;
|
|
113
|
+
delete<P extends string, O extends EndpointOptions, R>(path: P, handler: Handler<BodyOf<O>, Params<P>, QueryOf<O>, R>, opts?: O): ActionsBuilder<Acc & {
|
|
114
|
+
[K in P]: {
|
|
115
|
+
DELETE: {
|
|
116
|
+
input: BodyOf<O>;
|
|
117
|
+
output: Awaited<R>;
|
|
118
|
+
error: ErrorOf<O>;
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
}>;
|
|
122
|
+
head<P extends string, O extends EndpointOptions, R>(path: P, handler: Handler<BodyOf<O>, Params<P>, QueryOf<O>, R>, opts?: O): ActionsBuilder<Acc & {
|
|
123
|
+
[K in P]: {
|
|
124
|
+
HEAD: {
|
|
125
|
+
input: QueryOf<O>;
|
|
126
|
+
output: Awaited<R>;
|
|
127
|
+
error: ErrorOf<O>;
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
}>;
|
|
131
|
+
}
|
|
132
|
+
export declare function defineActions(): ActionsBuilder;
|
|
133
|
+
export { RESPOND };
|