@takazudo/zfb 0.1.0-next.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/LICENSE +21 -0
- package/README.md +207 -0
- package/bin/zfb.mjs +61 -0
- package/dist/config.d.ts +542 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +24 -0
- package/dist/config.js.map +1 -0
- package/dist/content.d.ts +231 -0
- package/dist/content.d.ts.map +1 -0
- package/dist/content.js +449 -0
- package/dist/content.js.map +1 -0
- package/dist/frontmatter.d.ts +23 -0
- package/dist/frontmatter.d.ts.map +1 -0
- package/dist/frontmatter.js +142 -0
- package/dist/frontmatter.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/island.d.ts +121 -0
- package/dist/island.d.ts.map +1 -0
- package/dist/island.js +273 -0
- package/dist/island.js.map +1 -0
- package/dist/jsx-types.d.ts +37 -0
- package/dist/jsx-types.d.ts.map +1 -0
- package/dist/jsx-types.js +12 -0
- package/dist/jsx-types.js.map +1 -0
- package/dist/paginate.d.ts +43 -0
- package/dist/paginate.d.ts.map +1 -0
- package/dist/paginate.js +44 -0
- package/dist/paginate.js.map +1 -0
- package/dist/plugins.d.ts +259 -0
- package/dist/plugins.d.ts.map +1 -0
- package/dist/plugins.js +42 -0
- package/dist/plugins.js.map +1 -0
- package/dist/runtime.d.ts +101 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +454 -0
- package/dist/runtime.js.map +1 -0
- package/dist/types.d.ts +27 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +33 -0
- package/dist/types.js.map +1 -0
- package/package.json +98 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structural JSX element (VNode). Framework-agnostic: both Preact and React
|
|
3
|
+
* produce objects that satisfy this shape when a JSX element is rendered.
|
|
4
|
+
*
|
|
5
|
+
* The `props` bag may itself contain `children` (nested VNodes) as well as
|
|
6
|
+
* HTML attribute values (strings, numbers, booleans). All fields are widened
|
|
7
|
+
* to `unknown` so the type stays opaque to callers that don't know which
|
|
8
|
+
* framework produced the value.
|
|
9
|
+
*
|
|
10
|
+
* `type` accepts BOTH function components (call signature) AND class
|
|
11
|
+
* components (construct signature). Preact and React both expose
|
|
12
|
+
* `ComponentType = FunctionComponent | ComponentClass`, and the JSX runtime
|
|
13
|
+
* stores either on `.type`. Without the construct signature, valid Preact
|
|
14
|
+
* `<MyComponent />` expressions fail to assign to `VNode` at the framework
|
|
15
|
+
* boundary (e.g. inside `<Island>` children) — even though class components
|
|
16
|
+
* are rare in modern Preact, the `ComponentType` union includes them.
|
|
17
|
+
*/
|
|
18
|
+
export type VNodeObject = {
|
|
19
|
+
readonly type: string | ((...args: unknown[]) => unknown) | (new (...args: unknown[]) => unknown);
|
|
20
|
+
readonly props: Readonly<Record<string, unknown>>;
|
|
21
|
+
readonly key: unknown;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* A renderable JSX node: a primitive, `null`, `undefined`, an array, or a
|
|
25
|
+
* structured VNode object.
|
|
26
|
+
*
|
|
27
|
+
* This union covers every value both Preact and React treat as valid
|
|
28
|
+
* `children`. Importantly it does **not** reference any framework-specific
|
|
29
|
+
* type, so packages that depend on `zfb` need not install a React / Preact
|
|
30
|
+
* `@types` package to satisfy this type.
|
|
31
|
+
*/
|
|
32
|
+
export type VNode = string | number | boolean | null | undefined | bigint | VNodeArray | VNodeObject;
|
|
33
|
+
export interface VNodeArray extends ReadonlyArray<VNode> {
|
|
34
|
+
}
|
|
35
|
+
/** @deprecated Use `VNode` instead. */
|
|
36
|
+
export type ReactNode = VNode;
|
|
37
|
+
//# sourceMappingURL=jsx-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsx-types.d.ts","sourceRoot":"","sources":["../src/jsx-types.ts"],"names":[],"mappings":"AAWA;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,CAAC;IAClG,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAClD,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,MAAM,KAAK,GACb,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,SAAS,GACT,MAAM,GACN,UAAU,GACV,WAAW,CAAC;AAEhB,MAAM,WAAW,UAAW,SAAQ,aAAa,CAAC,KAAK,CAAC;CAAG;AAK3D,uCAAuC;AACvC,MAAM,MAAM,SAAS,GAAG,KAAK,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Lightweight ambient JSX types so the public Island wrapper does not
|
|
2
|
+
// hard-depend on either preact or react as a runtime/types dependency.
|
|
3
|
+
//
|
|
4
|
+
// BCI-4: `IslandProps.children` is now typed as `VNode` (a structural union)
|
|
5
|
+
// rather than the old `ReactNode` alias, so non-React frameworks can
|
|
6
|
+
// implement `IslandProps` without any React type dependency at the type level.
|
|
7
|
+
//
|
|
8
|
+
// Both Preact and React's `children` accept this structural union; the build
|
|
9
|
+
// is type-erased so the actual rendering happens in the user's app under
|
|
10
|
+
// whichever framework adapter they chose.
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=jsx-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsx-types.js","sourceRoot":"","sources":["../src/jsx-types.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,uEAAuE;AACvE,EAAE;AACF,6EAA6E;AAC7E,qEAAqE;AACrE,+EAA+E;AAC/E,EAAE;AACF,6EAA6E;AAC7E,yEAAyE;AACzE,0CAA0C"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/** Options accepted by [`paginate`]. */
|
|
2
|
+
export type PaginateOptions<K extends string = string> = {
|
|
3
|
+
/** Items per page. Must be a positive integer (>= 1). */
|
|
4
|
+
pageSize: number;
|
|
5
|
+
/** Name of the dynamic param to fill (e.g. `"page"` for `[page].tsx`). */
|
|
6
|
+
param: K;
|
|
7
|
+
};
|
|
8
|
+
/** One page of paginated results. The shape consumed by the page component. */
|
|
9
|
+
export type PaginatedPage<T> = {
|
|
10
|
+
/** Items belonging to this page. */
|
|
11
|
+
data: T[];
|
|
12
|
+
/** 1-based page number. */
|
|
13
|
+
page: number;
|
|
14
|
+
/** Total number of pages (>= 1). */
|
|
15
|
+
lastPage: number;
|
|
16
|
+
/** Items per page (echoed for convenience). */
|
|
17
|
+
pageSize: number;
|
|
18
|
+
/** Total item count across all pages. */
|
|
19
|
+
total: number;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Route entry returned by [`paginate`], one per page.
|
|
23
|
+
*
|
|
24
|
+
* The `K` generic carries the literal param name through, so consumers
|
|
25
|
+
* accessing e.g. `route.params.page` get `string` rather than
|
|
26
|
+
* `string | undefined` under `noUncheckedIndexedAccess`.
|
|
27
|
+
*/
|
|
28
|
+
export type PaginateRoute<T, K extends string = string> = {
|
|
29
|
+
params: Record<K, string>;
|
|
30
|
+
props: {
|
|
31
|
+
page: PaginatedPage<T>;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Slice `items` into pages of `opts.pageSize` and produce one route entry
|
|
36
|
+
* per page. The `param` option names the dynamic segment to fill — for
|
|
37
|
+
* `pages/blog/page/[page].tsx` pass `param: "page"`.
|
|
38
|
+
*
|
|
39
|
+
* Always emits at least one route. An empty input list yields a single
|
|
40
|
+
* empty page so the index route still renders rather than 404ing.
|
|
41
|
+
*/
|
|
42
|
+
export declare function paginate<T, K extends string = string>(items: readonly T[], opts: PaginateOptions<K>): PaginateRoute<T, K>[];
|
|
43
|
+
//# sourceMappingURL=paginate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paginate.d.ts","sourceRoot":"","sources":["../src/paginate.ts"],"names":[],"mappings":"AAOA,wCAAwC;AACxC,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI;IACvD,yDAAyD;IACzD,QAAQ,EAAE,MAAM,CAAC;IACjB,0EAA0E;IAC1E,KAAK,EAAE,CAAC,CAAC;CACV,CAAC;AAEF,+EAA+E;AAC/E,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI;IAC7B,oCAAoC;IACpC,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI;IACxD,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAC1B,KAAK,EAAE;QAAE,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC,CAAA;KAAE,CAAC;CACnC,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,EACnD,KAAK,EAAE,SAAS,CAAC,EAAE,EACnB,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC,GACvB,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAgCvB"}
|
package/dist/paginate.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// `zfb/paginate` — paginate an array of items into per-page route entries.
|
|
2
|
+
//
|
|
3
|
+
// Mirrors the shape of Astro's `paginate()` so the bundled basic-blog template can
|
|
4
|
+
// emit one route per page from a `paths()` export. The renderer treats
|
|
5
|
+
// each returned object as `{ params, props }`, the same convention used
|
|
6
|
+
// elsewhere by the routing engine.
|
|
7
|
+
/**
|
|
8
|
+
* Slice `items` into pages of `opts.pageSize` and produce one route entry
|
|
9
|
+
* per page. The `param` option names the dynamic segment to fill — for
|
|
10
|
+
* `pages/blog/page/[page].tsx` pass `param: "page"`.
|
|
11
|
+
*
|
|
12
|
+
* Always emits at least one route. An empty input list yields a single
|
|
13
|
+
* empty page so the index route still renders rather than 404ing.
|
|
14
|
+
*/
|
|
15
|
+
export function paginate(items, opts) {
|
|
16
|
+
if (!Number.isInteger(opts.pageSize) || opts.pageSize < 1) {
|
|
17
|
+
throw new RangeError(`paginate: pageSize must be an integer >= 1, got ${String(opts.pageSize)}`);
|
|
18
|
+
}
|
|
19
|
+
if (typeof opts.param !== "string" || opts.param.length === 0) {
|
|
20
|
+
throw new TypeError(`paginate: param must be a non-empty string, got ${JSON.stringify(opts.param)}`);
|
|
21
|
+
}
|
|
22
|
+
const pageSize = opts.pageSize;
|
|
23
|
+
const total = items.length;
|
|
24
|
+
const lastPage = Math.max(1, Math.ceil(total / pageSize));
|
|
25
|
+
const routes = [];
|
|
26
|
+
for (let page = 1; page <= lastPage; page++) {
|
|
27
|
+
const start = (page - 1) * pageSize;
|
|
28
|
+
const slice = items.slice(start, start + pageSize);
|
|
29
|
+
routes.push({
|
|
30
|
+
params: { [opts.param]: String(page) },
|
|
31
|
+
props: {
|
|
32
|
+
page: {
|
|
33
|
+
data: slice,
|
|
34
|
+
page,
|
|
35
|
+
lastPage,
|
|
36
|
+
pageSize,
|
|
37
|
+
total,
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
return routes;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=paginate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paginate.js","sourceRoot":"","sources":["../src/paginate.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,EAAE;AACF,mFAAmF;AACnF,uEAAuE;AACvE,wEAAwE;AACxE,mCAAmC;AAoCnC;;;;;;;GAOG;AACH,MAAM,UAAU,QAAQ,CACtB,KAAmB,EACnB,IAAwB;IAExB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,GAAG,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,UAAU,CAClB,mDAAmD,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAC3E,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9D,MAAM,IAAI,SAAS,CACjB,mDAAmD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAChF,CAAC;IACJ,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;IAC/B,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC;IAC3B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC;IAC1D,MAAM,MAAM,GAA0B,EAAE,CAAC;IACzC,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,IAAI,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAC;QAC5C,MAAM,KAAK,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC;QACpC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,QAAQ,CAAC,CAAC;QACnD,MAAM,CAAC,IAAI,CAAC;YACV,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,EAAuB;YAC3D,KAAK,EAAE;gBACL,IAAI,EAAE;oBACJ,IAAI,EAAE,KAAK;oBACX,IAAI;oBACJ,QAAQ;oBACR,QAAQ;oBACR,KAAK;iBACN;aACF;SACF,CAAC,CAAC;IACL,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger handed to every plugin hook. The Rust side wraps `tracing` so
|
|
3
|
+
* the same lines show up alongside the rest of the build's structured
|
|
4
|
+
* logs. Hooks should prefer this over `console.log`.
|
|
5
|
+
*/
|
|
6
|
+
export type ZfbPluginLogger = {
|
|
7
|
+
info(msg: string): void;
|
|
8
|
+
warn(msg: string): void;
|
|
9
|
+
error(msg: string): void;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* One emitted route in the `postBuild` route manifest (#262).
|
|
13
|
+
* Present on `ctx.routes.routes` so a `postBuild` plugin can iterate
|
|
14
|
+
* every URL the build produced (e.g. to write a `sitemap.xml`).
|
|
15
|
+
*/
|
|
16
|
+
export type ZfbRouteEntry = {
|
|
17
|
+
/** Emitted URL path, e.g. `/`, `/blog/hello/`, `/sitemap.xml`. */
|
|
18
|
+
url: string;
|
|
19
|
+
/** Path under `outDir`, e.g. `index.html`, `blog/hello/index.html`, `sitemap.xml`. */
|
|
20
|
+
output: string;
|
|
21
|
+
/** File extension: `html`, `xml`, `rss`, `txt`, `json`, … */
|
|
22
|
+
extension: string;
|
|
23
|
+
/** Source page module relative to the project root, e.g. `pages/blog/[slug].tsx`. */
|
|
24
|
+
source: string;
|
|
25
|
+
/**
|
|
26
|
+
* `true` when the page is prerendered to disk (default / SSG); `false`
|
|
27
|
+
* when the page exports `prerender = false` and is served by the
|
|
28
|
+
* runtime adapter (SSR — no on-disk artifact under `outDir`).
|
|
29
|
+
*
|
|
30
|
+
* Indexes that enumerate on-disk URLs (sitemap.xml, search-index.json,
|
|
31
|
+
* etc.) should filter `r.prerender !== false` to avoid surfacing SSR
|
|
32
|
+
* routes that have no static output.
|
|
33
|
+
*/
|
|
34
|
+
prerender: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Bound route parameters. Absent for static routes.
|
|
37
|
+
* Dynamic (`[slug]`) params are string scalars; catchall (`[...rest]`)
|
|
38
|
+
* params are string arrays.
|
|
39
|
+
*/
|
|
40
|
+
params?: Record<string, string | string[]>;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* The route manifest exposed on `ctx.routes` during a `postBuild` callback
|
|
44
|
+
* (#262). Sorted by `url` for byte-stable output across runs.
|
|
45
|
+
*/
|
|
46
|
+
export type ZfbRouteManifest = {
|
|
47
|
+
routes: ZfbRouteEntry[];
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Context passed to `preBuild` and `postBuild`. `outDir` is the
|
|
51
|
+
* resolved absolute path of the configured `outDir` (default
|
|
52
|
+
* `<projectRoot>/dist`). `projectRoot` is the directory containing
|
|
53
|
+
* `zfb.config.ts`.
|
|
54
|
+
*
|
|
55
|
+
* `routes` is **only present on `postBuild`** calls; it is `undefined`
|
|
56
|
+
* on `preBuild`. This is intentional: the route manifest is not
|
|
57
|
+
* available until the build finishes writing `dist/` (#262).
|
|
58
|
+
*/
|
|
59
|
+
export type ZfbBuildHookContext = {
|
|
60
|
+
/** Project root — the directory containing `zfb.config.ts`. */
|
|
61
|
+
projectRoot: string;
|
|
62
|
+
/** Resolved absolute path of the build output directory. */
|
|
63
|
+
outDir: string;
|
|
64
|
+
/** The full loaded `ZfbConfig` (data-only view). */
|
|
65
|
+
config: import("./config.js").ZfbConfig;
|
|
66
|
+
/** Plugin-specific options block, copied verbatim from the matching `PluginConfig.options`. */
|
|
67
|
+
options: Record<string, unknown>;
|
|
68
|
+
/** Logger that wraps the Rust-side `tracing` subscriber. */
|
|
69
|
+
logger: ZfbPluginLogger;
|
|
70
|
+
/**
|
|
71
|
+
* All routes emitted by this build, sorted by URL (#262).
|
|
72
|
+
* Present only on `postBuild` calls; `undefined` on `preBuild`.
|
|
73
|
+
*/
|
|
74
|
+
routes?: ZfbRouteManifest;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* A request handed to a `devMiddleware` handler. Subset of the Node
|
|
78
|
+
* `http.IncomingMessage` surface intentionally — the dev server is
|
|
79
|
+
* Rust-side `axum`, not Node, so we expose only what survives a JSON
|
|
80
|
+
* envelope hop.
|
|
81
|
+
*/
|
|
82
|
+
export type ZfbDevMiddlewareRequest = {
|
|
83
|
+
method: string;
|
|
84
|
+
url: string;
|
|
85
|
+
/** Lower-cased header names → first value. */
|
|
86
|
+
headers: Record<string, string>;
|
|
87
|
+
/** Raw request body; absent for GET/HEAD. UTF-8 only — binary is out of scope for v1 dev plugins. */
|
|
88
|
+
body?: string;
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Response returned by a `devMiddleware` handler. All fields optional
|
|
92
|
+
* except `status`. `body` may be a string (UTF-8) or a base64-encoded
|
|
93
|
+
* binary payload (set `bodyEncoding` to `"base64"` in that case).
|
|
94
|
+
*/
|
|
95
|
+
export type ZfbDevMiddlewareResponse = {
|
|
96
|
+
status: number;
|
|
97
|
+
headers?: Record<string, string>;
|
|
98
|
+
body?: string;
|
|
99
|
+
bodyEncoding?: "utf8" | "base64";
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* Handler signature for a `devMiddleware` registration. The `next` callback
|
|
103
|
+
* is reserved for future composition; v1 plugins should produce a response
|
|
104
|
+
* directly. Returning `undefined` from the handler signals "I did not handle
|
|
105
|
+
* this request" — the dev server then falls through to its built-in routes
|
|
106
|
+
* (the page cache, /__zfb/livereload.js, etc.).
|
|
107
|
+
*/
|
|
108
|
+
export type ZfbDevMiddlewareHandler = (req: ZfbDevMiddlewareRequest) => Promise<ZfbDevMiddlewareResponse | undefined> | ZfbDevMiddlewareResponse | undefined;
|
|
109
|
+
/**
|
|
110
|
+
* Context passed to `devMiddleware`. The `register` callback installs
|
|
111
|
+
* one handler per URL path prefix. `path` is matched as an exact prefix
|
|
112
|
+
* — a registration on `/doc-history` matches `/doc-history` and
|
|
113
|
+
* `/doc-history/foo`, but NOT `/doc-historyx`.
|
|
114
|
+
*/
|
|
115
|
+
export type ZfbDevMiddlewareContext = {
|
|
116
|
+
projectRoot: string;
|
|
117
|
+
config: import("./config.js").ZfbConfig;
|
|
118
|
+
options: Record<string, unknown>;
|
|
119
|
+
logger: ZfbPluginLogger;
|
|
120
|
+
/** Register an HTTP handler at `path`. Calling twice on the same path overwrites. */
|
|
121
|
+
register(path: string, handler: ZfbDevMiddlewareHandler): void;
|
|
122
|
+
};
|
|
123
|
+
/**
|
|
124
|
+
* Loader signature for a virtual-module registration. Must return the
|
|
125
|
+
* **complete ESM module source text** as a string — the bundler /
|
|
126
|
+
* embedded V8 host feeds the returned string in as the module's
|
|
127
|
+
* source verbatim. The loader is invoked **exactly once per build**
|
|
128
|
+
* (and once per `zfb dev` host boot) the first time any consumer
|
|
129
|
+
* imports the registered specifier; subsequent imports of the same
|
|
130
|
+
* specifier re-use the memoised result.
|
|
131
|
+
*
|
|
132
|
+
* Example:
|
|
133
|
+
*
|
|
134
|
+
* ```ts
|
|
135
|
+
* addVirtualModule("virtual:my-data", () =>
|
|
136
|
+
* `export default ${JSON.stringify(myJson)}`,
|
|
137
|
+
* );
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
140
|
+
export type ZfbVirtualModuleLoader = () => string | Promise<string>;
|
|
141
|
+
/**
|
|
142
|
+
* Context passed to the new `setup` hook (#255). Runs once per host
|
|
143
|
+
* boot, in `Config.plugins` declaration order, **before** `preBuild`.
|
|
144
|
+
*
|
|
145
|
+
* `ctx.command` tells the plugin which lifecycle is active so it can
|
|
146
|
+
* gate dev-only registrations:
|
|
147
|
+
*
|
|
148
|
+
* ```ts
|
|
149
|
+
* setup({ command, injectRoute }) {
|
|
150
|
+
* if (command === "dev") {
|
|
151
|
+
* injectRoute("/api/dev/x", "./scripts/dev-x.ts");
|
|
152
|
+
* }
|
|
153
|
+
* }
|
|
154
|
+
* ```
|
|
155
|
+
*
|
|
156
|
+
* The hook's surface is intentionally **closed**: only
|
|
157
|
+
* `injectRoute`, `addVirtualModule`, `addAlias`. There is no
|
|
158
|
+
* `addRemarkPlugin` / `addRehypePlugin` / `addMarkdownVisitor` — by
|
|
159
|
+
* design (see the concept doc for the rationale).
|
|
160
|
+
*/
|
|
161
|
+
export type ZfbSetupContext = {
|
|
162
|
+
/**
|
|
163
|
+
* Active zfb command. `"build"` during `zfb build`; `"dev"` during
|
|
164
|
+
* `zfb dev`. Gates `injectRoute` (calling it during `"build"` is an
|
|
165
|
+
* error — see [`injectRoute`](#injectRoute)).
|
|
166
|
+
*/
|
|
167
|
+
command: "build" | "dev";
|
|
168
|
+
/** Project root — the directory containing `zfb.config.ts`. */
|
|
169
|
+
projectRoot: string;
|
|
170
|
+
/** The full loaded `ZfbConfig` (data-only view). */
|
|
171
|
+
config: import("./config.js").ZfbConfig;
|
|
172
|
+
/** Plugin-specific options block, copied verbatim from `PluginConfig.options`. */
|
|
173
|
+
options: Record<string, unknown>;
|
|
174
|
+
/** Logger that wraps the Rust-side `tracing` subscriber. */
|
|
175
|
+
logger: ZfbPluginLogger;
|
|
176
|
+
/**
|
|
177
|
+
* Register an import alias. **Exact-match-only in v1**:
|
|
178
|
+
* `addAlias("@/foo", "./src/foo.tsx")` rewrites `import "@/foo"`
|
|
179
|
+
* but does NOT match `import "@/foo/bar"`. Prefix-matching is
|
|
180
|
+
* explicitly deferred to v2 — switch to one bare alias per file
|
|
181
|
+
* until then.
|
|
182
|
+
*
|
|
183
|
+
* `to` is resolved relative to the project root. Two plugins
|
|
184
|
+
* registering the same `from` with different `to` raises
|
|
185
|
+
* `AliasConflict` and aborts the build.
|
|
186
|
+
*/
|
|
187
|
+
addAlias(from: string, to: string): void;
|
|
188
|
+
/**
|
|
189
|
+
* Register a virtual module. `specifier` is a bare import
|
|
190
|
+
* specifier (recommended `virtual:` prefix, not enforced).
|
|
191
|
+
* `loader` returns the complete ESM source text as a string and
|
|
192
|
+
* runs **exactly once per build** at first import.
|
|
193
|
+
*
|
|
194
|
+
* Two plugins registering the same `specifier` raises
|
|
195
|
+
* `VirtualModuleConflict` and aborts the build.
|
|
196
|
+
*/
|
|
197
|
+
addVirtualModule(specifier: string, loader: ZfbVirtualModuleLoader): void;
|
|
198
|
+
/**
|
|
199
|
+
* Register a synthetic page route. The dev server routes the
|
|
200
|
+
* matched URL into the page rendering pipeline as if `entrypoint`
|
|
201
|
+
* were a `pages/<...>.tsx` file. `pattern` uses the same grammar
|
|
202
|
+
* as `pages/` filenames (`/blog/[slug]`, `/api/dev/x`,
|
|
203
|
+
* `/docs/[...rest]`).
|
|
204
|
+
*
|
|
205
|
+
* **Dev-only.** Calling `injectRoute` when `ctx.command === "build"`
|
|
206
|
+
* raises `InjectRouteInBuildMode` and aborts the build — synthetic
|
|
207
|
+
* routes during a static build would invite SSR-shaped pages that
|
|
208
|
+
* conflict with `output: 'static'`.
|
|
209
|
+
*
|
|
210
|
+
* Two plugins registering the same `pattern` raises
|
|
211
|
+
* `InjectRouteConflict`.
|
|
212
|
+
*/
|
|
213
|
+
injectRoute(pattern: string, entrypoint: string): void;
|
|
214
|
+
};
|
|
215
|
+
/**
|
|
216
|
+
* The plugin-module shape. `name` is informational (the resolved module
|
|
217
|
+
* specifier wins for identification on the Rust side) and helps the
|
|
218
|
+
* plugin self-identify in logs.
|
|
219
|
+
*
|
|
220
|
+
* Four optional hooks; declaration-order matters when multiple plugins
|
|
221
|
+
* touch the same surface. Each hook is independent — a plugin may
|
|
222
|
+
* declare any subset:
|
|
223
|
+
*
|
|
224
|
+
* - `setup` (#255) — register virtual modules, aliases, injected
|
|
225
|
+
* routes. Runs once at host boot, before `preBuild`.
|
|
226
|
+
* - `preBuild` — file-generation work that downstream stages will
|
|
227
|
+
* see. Runs once per `zfb build` and once per `zfb dev` boot.
|
|
228
|
+
* - `postBuild` — finalisation work that runs after `dist/` has been
|
|
229
|
+
* written.
|
|
230
|
+
* - `devMiddleware` — register HTTP handlers for ad-hoc dev-only
|
|
231
|
+
* URLs. Per-request dispatch, distinct from `injectRoute` (which
|
|
232
|
+
* goes through the page renderer).
|
|
233
|
+
*/
|
|
234
|
+
export type ZfbPlugin = {
|
|
235
|
+
/** Plugin display name; surfaces in error / log lines. */
|
|
236
|
+
name: string;
|
|
237
|
+
setup?(ctx: ZfbSetupContext): Promise<void> | void;
|
|
238
|
+
preBuild?(ctx: ZfbBuildHookContext): Promise<void> | void;
|
|
239
|
+
postBuild?(ctx: ZfbBuildHookContext): Promise<void> | void;
|
|
240
|
+
devMiddleware?(ctx: ZfbDevMiddlewareContext): Promise<void> | void;
|
|
241
|
+
};
|
|
242
|
+
/**
|
|
243
|
+
* Identity helper that types the supplied object as a [`ZfbPlugin`].
|
|
244
|
+
* Use as the default export of a plugin module so editors surface
|
|
245
|
+
* field-level types and typos surface at compile time.
|
|
246
|
+
*
|
|
247
|
+
* ```ts
|
|
248
|
+
* import { definePlugin } from "@takazudo/zfb/plugins";
|
|
249
|
+
*
|
|
250
|
+
* export default definePlugin({
|
|
251
|
+
* name: "my-plugin",
|
|
252
|
+
* async preBuild({ outDir, logger }) {
|
|
253
|
+
* logger.info(`generating index into ${outDir}`);
|
|
254
|
+
* },
|
|
255
|
+
* });
|
|
256
|
+
* ```
|
|
257
|
+
*/
|
|
258
|
+
export declare function definePlugin(plugin: ZfbPlugin): ZfbPlugin;
|
|
259
|
+
//# sourceMappingURL=plugins.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugins.d.ts","sourceRoot":"","sources":["../src/plugins.ts"],"names":[],"mappings":"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"}
|
package/dist/plugins.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// `zfb/plugins` — TypeScript helper for the zfb plugin lifecycle.
|
|
2
|
+
//
|
|
3
|
+
// A plugin is a JS module whose default export is a [`ZfbPlugin`] object.
|
|
4
|
+
// `zfb.config.ts` references plugins by `name` (npm bare specifier or a
|
|
5
|
+
// `./`-relative path); the zfb config loader resolves each `name` to an
|
|
6
|
+
// absolute module specifier and the Rust-side plugin host loads the
|
|
7
|
+
// module via dynamic `import()` and dispatches the lifecycle hooks.
|
|
8
|
+
//
|
|
9
|
+
// Sub 3 / issue #108 — initial drop. Three optional hooks: `preBuild`,
|
|
10
|
+
// `postBuild`, `devMiddleware`. Astro-migration epic #253 / sub-issue
|
|
11
|
+
// #255 adds a fourth: `setup`, which runs once before `preBuild` and
|
|
12
|
+
// lets plugins register virtual modules, import aliases, and dev-only
|
|
13
|
+
// injected routes. None of the hooks see real Node IPC objects across
|
|
14
|
+
// the boundary; everything is JSON-friendly.
|
|
15
|
+
//
|
|
16
|
+
// ## Inline functions are NOT supported
|
|
17
|
+
//
|
|
18
|
+
// `PluginConfig` (in `./config.ts`) carries only data. A user cannot
|
|
19
|
+
// inline a function in `zfb.config.ts` — the config goes through a
|
|
20
|
+
// JSON round-trip and any function value would be silently dropped.
|
|
21
|
+
// Plugins must live in their own module (npm package or local file)
|
|
22
|
+
// and be referenced by `name`.
|
|
23
|
+
/**
|
|
24
|
+
* Identity helper that types the supplied object as a [`ZfbPlugin`].
|
|
25
|
+
* Use as the default export of a plugin module so editors surface
|
|
26
|
+
* field-level types and typos surface at compile time.
|
|
27
|
+
*
|
|
28
|
+
* ```ts
|
|
29
|
+
* import { definePlugin } from "@takazudo/zfb/plugins";
|
|
30
|
+
*
|
|
31
|
+
* export default definePlugin({
|
|
32
|
+
* name: "my-plugin",
|
|
33
|
+
* async preBuild({ outDir, logger }) {
|
|
34
|
+
* logger.info(`generating index into ${outDir}`);
|
|
35
|
+
* },
|
|
36
|
+
* });
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export function definePlugin(plugin) {
|
|
40
|
+
return plugin;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=plugins.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugins.js","sourceRoot":"","sources":["../src/plugins.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,EAAE;AACF,0EAA0E;AAC1E,wEAAwE;AACxE,wEAAwE;AACxE,oEAAoE;AACpE,oEAAoE;AACpE,EAAE;AACF,uEAAuE;AACvE,sEAAsE;AACtE,qEAAqE;AACrE,sEAAsE;AACtE,sEAAsE;AACtE,6CAA6C;AAC7C,EAAE;AACF,wCAAwC;AACxC,EAAE;AACF,qEAAqE;AACrE,mEAAmE;AACnE,oEAAoE;AACpE,oEAAoE;AACpE,+BAA+B;AAmQ/B;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,YAAY,CAAC,MAAiB;IAC5C,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { type When } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Schedule a hydration `fire` callback for `target` according to `when`.
|
|
4
|
+
*
|
|
5
|
+
* Returns a `cancel` function that aborts the scheduling if it has not
|
|
6
|
+
* fired yet. After firing, calling `cancel` is a no-op. If the helper
|
|
7
|
+
* cannot find the relevant browser API (e.g. running in pure Node with no
|
|
8
|
+
* polyfill), it falls back to firing synchronously so server-side smoke
|
|
9
|
+
* tests still observe the call.
|
|
10
|
+
*/
|
|
11
|
+
export declare function scheduleHydrate(target: Element, when: When | string | undefined, fire: () => void): () => void;
|
|
12
|
+
/**
|
|
13
|
+
* The shape of the default export each per-island bundle ships.
|
|
14
|
+
*
|
|
15
|
+
* `mode === "hydrate"` is used for SSR'd islands, `"render"` for
|
|
16
|
+
* SSR-skip islands.
|
|
17
|
+
*/
|
|
18
|
+
type IslandMount = (props: Record<string, unknown>, element: Element, mode: "hydrate" | "render") => void;
|
|
19
|
+
type IslandUnmount = (element: Element) => void;
|
|
20
|
+
interface IslandModule {
|
|
21
|
+
mount?: IslandMount;
|
|
22
|
+
default?: IslandMount;
|
|
23
|
+
unmount?: IslandUnmount;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Map of `componentName → island descriptor` baked into the runtime entry.
|
|
27
|
+
*
|
|
28
|
+
* Two descriptor shapes are accepted so the same `mountIslands` runtime
|
|
29
|
+
* handles both bundling strategies the build emits:
|
|
30
|
+
*
|
|
31
|
+
* 1. `string` — a per-island bundle URL. The runtime fetches it via
|
|
32
|
+
* dynamic `import()` and reads `mount` / `default` off the loaded
|
|
33
|
+
* module. Used by the per-island bundling path
|
|
34
|
+
* (`bundle_per_island` / `render_runtime_entry_source`).
|
|
35
|
+
*
|
|
36
|
+
* 2. `IslandModule` — an inline module-shaped object whose `mount` (or
|
|
37
|
+
* `default`) is called directly. Used by the shared-bundle path
|
|
38
|
+
* (`render_shared_bundle_entry_source`): every island's source code
|
|
39
|
+
* is already in the same bundle, so the synthesised entry can hand
|
|
40
|
+
* the runtime the constructed mount functions inline without a
|
|
41
|
+
* second HTTP fetch. This preserves the one-request shared-bundle
|
|
42
|
+
* contract while giving up nothing on hydration semantics
|
|
43
|
+
* (zudolab/zudo-doc#1355 wave 6).
|
|
44
|
+
*/
|
|
45
|
+
export type IslandManifestValue = string | IslandModule;
|
|
46
|
+
export type IslandManifest = Readonly<Record<string, IslandManifestValue>>;
|
|
47
|
+
/**
|
|
48
|
+
* Walk the DOM and mount every `[data-zfb-island]` / `[data-zfb-island-skip-ssr]`
|
|
49
|
+
* element using `manifest`.
|
|
50
|
+
*
|
|
51
|
+
* No-op when `document` is undefined (SSR, edge runtime). Safe to call
|
|
52
|
+
* multiple times: each element is mounted at most once thanks to the
|
|
53
|
+
* `mounted` WeakSet guard.
|
|
54
|
+
*
|
|
55
|
+
* The manifest is captured at module level so `mountNewIslands()` can re-use
|
|
56
|
+
* it after an SPA body swap without needing the caller to re-supply it.
|
|
57
|
+
*/
|
|
58
|
+
export declare function mountIslands(manifest: IslandManifest): void;
|
|
59
|
+
/**
|
|
60
|
+
* Re-walk the current document body and mount any new island markers introduced
|
|
61
|
+
* by an SPA body swap. Uses the manifest captured by the previous `mountIslands`
|
|
62
|
+
* call — no manifest arg required.
|
|
63
|
+
*
|
|
64
|
+
* The caller (client-router `router.ts`) invokes this after `swap()` + `runScripts()`
|
|
65
|
+
* and before dispatching `zfb:page-load`, per W1B §12.2 contract.
|
|
66
|
+
*
|
|
67
|
+
* No-op when called before `mountIslands` (capturedManifest is null) or when
|
|
68
|
+
* `document` is undefined.
|
|
69
|
+
*/
|
|
70
|
+
export declare function mountNewIslands(): void;
|
|
71
|
+
/**
|
|
72
|
+
* Cancel deferred-hydration callbacks for all islands in the old body before a
|
|
73
|
+
* swap. Prevents idle / visibility callbacks from running against orphan elements
|
|
74
|
+
* after `swapBodyElement` removes them from the live document. (W1B §12.5)
|
|
75
|
+
*
|
|
76
|
+
* Call this on `zfb:before-swap` (or equivalently, in the router's swap sequence
|
|
77
|
+
* before `swap()` mutates the DOM). Fire-and-forget; safe to call if nothing is
|
|
78
|
+
* pending.
|
|
79
|
+
*/
|
|
80
|
+
export declare function cancelPendingIslands(): void;
|
|
81
|
+
/**
|
|
82
|
+
* Unmount all currently-mounted islands within `root` (default: `document.body`).
|
|
83
|
+
*
|
|
84
|
+
* Walks `root` for `[data-zfb-island]` and `[data-zfb-island-skip-ssr]` elements,
|
|
85
|
+
* looks up each element's unmount thunk in the `mounted` WeakMap, calls it (which
|
|
86
|
+
* triggers `render(null, element)` for Preact or `root.unmount()` for React), and
|
|
87
|
+
* removes the entry from the map so `mountNewIslands()` can re-mount later.
|
|
88
|
+
*
|
|
89
|
+
* Call this before `swapBodyElement(...)` so the OLD body's islands receive proper
|
|
90
|
+
* framework lifecycle cleanup (useEffect teardowns, etc.) before being discarded.
|
|
91
|
+
*
|
|
92
|
+
* No-op for elements not in the `mounted` map (e.g. never-mounted or already cleaned up).
|
|
93
|
+
*/
|
|
94
|
+
export declare function unmountIslands(root?: ParentNode): void;
|
|
95
|
+
/**
|
|
96
|
+
* Test-only seam. Replace the module dynamic-import with a fake.
|
|
97
|
+
* Returns the previous implementation so tests can restore it.
|
|
98
|
+
*/
|
|
99
|
+
export declare function __setIslandImporterForTests(impl: (url: string) => Promise<IslandModule>): (url: string) => Promise<IslandModule>;
|
|
100
|
+
export {};
|
|
101
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAe,KAAK,IAAI,EAAE,MAAM,YAAY,CAAC;AAkBpD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,OAAO,EACf,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,EAC/B,IAAI,EAAE,MAAM,IAAI,GACf,MAAM,IAAI,CAcZ;AAoHD;;;;;GAKG;AACH,KAAK,WAAW,GAAG,CACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,SAAS,GAAG,QAAQ,KACvB,IAAI,CAAC;AAEV,KAAK,aAAa,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;AAEhD,UAAU,YAAY;IACpB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,YAAY,CAAC;AACxD,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAAC;AA8B3E;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,CAwB3D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAmBtC;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAK3C;AAiMD;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,IAAI,GAAE,UAA0B,GAAG,IAAI,CAUrE;AAqCD;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,CAAC,GAC3C,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,CAAC,CAIxC"}
|