@moku-labs/web 0.5.6 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/index.cjs +1262 -89
- package/dist/index.d.cts +819 -403
- package/dist/index.d.mts +819 -403
- package/dist/index.mjs +1249 -83
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -4,7 +4,7 @@ import { BundledTheme, ThemeRegistrationAny } from "shiki";
|
|
|
4
4
|
import { Pluggable, Processor } from "unified";
|
|
5
5
|
|
|
6
6
|
//#region \0rolldown/runtime.js
|
|
7
|
-
declare namespace types_d_exports$
|
|
7
|
+
declare namespace types_d_exports$7 {
|
|
8
8
|
export { ExpectChain, LogApi, LogConfig, LogEntry, LogLevel, LogSink, LogState };
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
@@ -144,7 +144,7 @@ type LogApi = {
|
|
|
144
144
|
addSink(sink: LogSink): void; /** Clear all recorded entries while keeping registered sinks. */
|
|
145
145
|
reset(): void;
|
|
146
146
|
};
|
|
147
|
-
declare namespace types_d_exports$
|
|
147
|
+
declare namespace types_d_exports$5 {
|
|
148
148
|
export { EnvApi, EnvConfig, EnvProvider, EnvState, EnvVarSpec };
|
|
149
149
|
}
|
|
150
150
|
/**
|
|
@@ -340,7 +340,7 @@ declare const envPlugin: import("@moku-labs/core").CorePluginInstance<"env", Env
|
|
|
340
340
|
* Global framework configuration. Minimal by design — per-plugin config is
|
|
341
341
|
* resolved via `pluginConfigs`, not merged here.
|
|
342
342
|
*/
|
|
343
|
-
type Config$
|
|
343
|
+
type Config$8 = {
|
|
344
344
|
/** Runtime mode. Drives log sink defaults, content draft filtering, build minify. */mode: "production" | "development";
|
|
345
345
|
};
|
|
346
346
|
/**
|
|
@@ -375,7 +375,7 @@ type Events = {};
|
|
|
375
375
|
* });
|
|
376
376
|
* ```
|
|
377
377
|
*/
|
|
378
|
-
type Config$
|
|
378
|
+
type Config$7 = {
|
|
379
379
|
/** Human-readable site name. Used in feeds, og:site_name, and titles. MUST be non-empty. */name: string; /** Absolute base URL of the site, e.g. "https://blog.dev". MUST be a valid absolute URL (http/https). */
|
|
380
380
|
url: string; /** Default author/byline for the site. Used in feeds and article author meta. */
|
|
381
381
|
author: string; /** Short site description. Used in feeds, the default meta description, and og:description fallbacks. */
|
|
@@ -385,7 +385,7 @@ type Config$6 = {
|
|
|
385
385
|
* Public API of the site plugin — read-only accessors over frozen global
|
|
386
386
|
* site metadata, plus canonical URL construction.
|
|
387
387
|
*/
|
|
388
|
-
type Api$
|
|
388
|
+
type Api$7 = {
|
|
389
389
|
/**
|
|
390
390
|
* Returns the configured site name.
|
|
391
391
|
*
|
|
@@ -463,7 +463,7 @@ type Api$6 = {
|
|
|
463
463
|
* }
|
|
464
464
|
* ```
|
|
465
465
|
*/
|
|
466
|
-
type Config$
|
|
466
|
+
type Config$6 = {
|
|
467
467
|
readonly locales: readonly string[];
|
|
468
468
|
readonly defaultLocale: string;
|
|
469
469
|
readonly localeNames?: Record<string, string>;
|
|
@@ -474,7 +474,7 @@ type Config$5 = {
|
|
|
474
474
|
* Public API of the i18n plugin. Injected as `app.i18n` and reachable from
|
|
475
475
|
* other plugins via `ctx.require(i18nPlugin)`.
|
|
476
476
|
*/
|
|
477
|
-
type Api$
|
|
477
|
+
type Api$6 = {
|
|
478
478
|
/**
|
|
479
479
|
* Returns the configured supported locales in declared order.
|
|
480
480
|
*
|
|
@@ -542,8 +542,8 @@ type Api$5 = {
|
|
|
542
542
|
*/
|
|
543
543
|
t(locale: string, key: string): string;
|
|
544
544
|
};
|
|
545
|
-
declare namespace types_d_exports$
|
|
546
|
-
export { Api$
|
|
545
|
+
declare namespace types_d_exports$8 {
|
|
546
|
+
export { Api$5 as Api, ClientRoute, CompileInput, CompiledRoute, Config$5 as Config, ExtractRouteParams, ExtractSegmentParameter, HeadConfig$1 as HeadConfig, LayoutContext, MatcherTable, Prettify, RouteBuilder, RouteContext, RouteDefinition, RouteHandlers, RouteMap, RouteState, RouterApi, RouterConfig, RouterState, State$5 as State, TypedRoute };
|
|
547
547
|
}
|
|
548
548
|
/**
|
|
549
549
|
* Param contribution of a single path segment. `{name:?}` / `:name?` → optional;
|
|
@@ -867,13 +867,13 @@ type RouterApi = {
|
|
|
867
867
|
mode(): "ssg" | "spa" | "hybrid";
|
|
868
868
|
};
|
|
869
869
|
/** Re-export under the canonical `Config` name for the plugin-types barrel. */
|
|
870
|
-
type Config$
|
|
870
|
+
type Config$5 = RouterConfig;
|
|
871
871
|
/** Re-export under the canonical `State` name for the plugin-types barrel. */
|
|
872
|
-
type State$
|
|
872
|
+
type State$5 = RouterState;
|
|
873
873
|
/** Re-export under the canonical `Api` name for the plugin-types barrel. */
|
|
874
|
-
type Api$
|
|
875
|
-
declare namespace types_d_exports$
|
|
876
|
-
export { Api$
|
|
874
|
+
type Api$5 = RouterApi;
|
|
875
|
+
declare namespace types_d_exports$6 {
|
|
876
|
+
export { Api$4 as Api, ArticleMeta, Config$4 as Config, HeadConfig, HeadDefaults, HeadElement, ResolvedRoute, State$4 as State };
|
|
877
877
|
}
|
|
878
878
|
/**
|
|
879
879
|
* @file head plugin — type definitions skeleton
|
|
@@ -889,7 +889,7 @@ declare namespace types_d_exports$5 {
|
|
|
889
889
|
* const config: Config = { titleTemplate: "%s — Moku" };
|
|
890
890
|
* ```
|
|
891
891
|
*/
|
|
892
|
-
type Config$
|
|
892
|
+
type Config$4 = {
|
|
893
893
|
/** Title template applied to per-route titles. `%s` is replaced by the route title. */titleTemplate?: string; /** Default Open Graph image URL used when a route does not supply one. */
|
|
894
894
|
defaultOgImage?: string; /** Default Twitter card type emitted when og/twitter content is present. */
|
|
895
895
|
twitterCard?: "summary" | "summary_large_image"; /** Default Twitter site handle (e.g. `"@moku_labs"`) emitted as `twitter:site`. */
|
|
@@ -907,7 +907,7 @@ type Config$3 = {
|
|
|
907
907
|
* const state: State = { defaults: null };
|
|
908
908
|
* ```
|
|
909
909
|
*/
|
|
910
|
-
type State$
|
|
910
|
+
type State$4 = {
|
|
911
911
|
/** Normalized head defaults, assigned once in `onInit` (initially `null`). */defaults: HeadDefaults | null;
|
|
912
912
|
};
|
|
913
913
|
/**
|
|
@@ -1001,7 +1001,7 @@ type ResolvedRoute = {
|
|
|
1001
1001
|
* const html: string = api.render(route, data);
|
|
1002
1002
|
* ```
|
|
1003
1003
|
*/
|
|
1004
|
-
type Api$
|
|
1004
|
+
type Api$4 = {
|
|
1005
1005
|
/**
|
|
1006
1006
|
* Compose the final `<head>` inner HTML for a route. Pulled synchronously by `build`.
|
|
1007
1007
|
*
|
|
@@ -1015,7 +1015,7 @@ type Api$3 = {
|
|
|
1015
1015
|
*/
|
|
1016
1016
|
render(route: ResolvedRoute, data: unknown): string;
|
|
1017
1017
|
};
|
|
1018
|
-
declare namespace types_d_exports$
|
|
1018
|
+
declare namespace types_d_exports$9 {
|
|
1019
1019
|
export { COMPONENT_HOOK_NAMES, ComponentContext, ComponentDef, ComponentHooks, ComponentInstance, ExtractApi$1 as ExtractApi, PageData, ResolvedSpaConfig, SpaApi, SpaConfig, SpaContext, SpaDataReader, SpaEmitFunction, SpaEvents, SpaKernel, SpaKernelDeps, SpaRequire, SpaState };
|
|
1020
1020
|
}
|
|
1021
1021
|
/** Payload map for the events `spa` emits, used to type the kernel's `emit` closure. */
|
|
@@ -1216,7 +1216,7 @@ interface SpaKernelDeps {
|
|
|
1216
1216
|
/** Router plugin API — used for client-side route matching (`match`) + the resolved `mode`. */
|
|
1217
1217
|
router: RouterApi;
|
|
1218
1218
|
/** Head plugin API — its pure compose is reused for client head-sync. */
|
|
1219
|
-
head: Api$
|
|
1219
|
+
head: Api$4;
|
|
1220
1220
|
/**
|
|
1221
1221
|
* The OPTIONAL `data` reader. Present only when the `data` plugin is composed.
|
|
1222
1222
|
* When present (and `router.mode() !== "ssg"`), navigation first tries the client
|
|
@@ -1323,7 +1323,7 @@ type SpaApi = {
|
|
|
1323
1323
|
current(): string;
|
|
1324
1324
|
};
|
|
1325
1325
|
declare namespace types_d_exports {
|
|
1326
|
-
export { Api$
|
|
1326
|
+
export { Api$3 as Api, BuildCacheEntry, BuildEvents, BuildResult, Config$3 as Config, ExtractApi, OgFont, OgImageConfig, OgPngRenderer, PhaseContext, PhaseEmit, PhaseLog, PhaseName, PhaseRequire, RichOgInput, State$3 as State };
|
|
1327
1327
|
}
|
|
1328
1328
|
/**
|
|
1329
1329
|
* Structural extraction of a plugin instance's public API from its `_phantom`
|
|
@@ -1400,8 +1400,8 @@ type PhaseRequire = <PluginCandidate extends {
|
|
|
1400
1400
|
* ```
|
|
1401
1401
|
*/
|
|
1402
1402
|
type PhaseContext = {
|
|
1403
|
-
/** Mutable per-run build state (caches + runId). */state: State$
|
|
1404
|
-
readonly config: Readonly<Config$
|
|
1403
|
+
/** Mutable per-run build state (caches + runId). */state: State$3; /** Resolved, frozen build config. */
|
|
1404
|
+
readonly config: Readonly<Config$3>; /** Global framework config (mode, etc.). */
|
|
1405
1405
|
readonly global: Readonly<{
|
|
1406
1406
|
mode: "production" | "development";
|
|
1407
1407
|
}>; /** Resolve a depended-upon plugin instance to its public API. */
|
|
@@ -1510,7 +1510,7 @@ interface OgImageConfig {
|
|
|
1510
1510
|
* const config: Config = { outDir: "./dist", minify: true, feeds: true, sitemap: true, images: true, ogImage: false };
|
|
1511
1511
|
* ```
|
|
1512
1512
|
*/
|
|
1513
|
-
type Config$
|
|
1513
|
+
type Config$3 = {
|
|
1514
1514
|
/** Output directory for the built site. */outDir: string; /** Minify bundled CSS/JS. */
|
|
1515
1515
|
minify: boolean; /** Generate RSS/Atom/JSON feeds. */
|
|
1516
1516
|
feeds: boolean; /** Generate sitemap.xml + robots.txt. */
|
|
@@ -1551,9 +1551,9 @@ type BuildCacheEntry = Record<string, string>;
|
|
|
1551
1551
|
* const state: State = { config, manifest: null, buildCache: new Map(), runId: null, ogImageHashCache: new Map() };
|
|
1552
1552
|
* ```
|
|
1553
1553
|
*/
|
|
1554
|
-
interface State$
|
|
1554
|
+
interface State$3 {
|
|
1555
1555
|
/** Resolved, frozen config snapshot. */
|
|
1556
|
-
config: Config$
|
|
1556
|
+
config: Config$3;
|
|
1557
1557
|
/** Cached route manifest for the current run (populated in Phase 3 from router). */
|
|
1558
1558
|
manifest: RouteDefinition[] | null;
|
|
1559
1559
|
/** Per-run build artifacts (e.g. hashed CSS/JS asset paths from Phase 1). */
|
|
@@ -1600,7 +1600,7 @@ interface BuildResult {
|
|
|
1600
1600
|
* const result = await app.build.run();
|
|
1601
1601
|
* ```
|
|
1602
1602
|
*/
|
|
1603
|
-
type Api$
|
|
1603
|
+
type Api$3 = {
|
|
1604
1604
|
/**
|
|
1605
1605
|
* Run the full SSG pipeline and write the site to disk.
|
|
1606
1606
|
*
|
|
@@ -1649,7 +1649,7 @@ type Api$2 = {
|
|
|
1649
1649
|
* });
|
|
1650
1650
|
* ```
|
|
1651
1651
|
*/
|
|
1652
|
-
declare const buildPlugin: import("@moku-labs/core").PluginInstance<"build", Config$
|
|
1652
|
+
declare const buildPlugin: import("@moku-labs/core").PluginInstance<"build", Config$3, State$3, Api$3, {
|
|
1653
1653
|
"build:phase": {
|
|
1654
1654
|
phase: PhaseName;
|
|
1655
1655
|
status: "start" | "done";
|
|
@@ -1661,224 +1661,819 @@ declare const buildPlugin: import("@moku-labs/core").PluginInstance<"build", Con
|
|
|
1661
1661
|
durationMs: number;
|
|
1662
1662
|
};
|
|
1663
1663
|
}> & Record<never, never>;
|
|
1664
|
-
declare namespace types_d_exports$
|
|
1665
|
-
export { Api$
|
|
1664
|
+
declare namespace types_d_exports$4 {
|
|
1665
|
+
export { Api$2 as Api, Config$2 as Config, DeployErrorCode, DeployInitOptions, DeployResult, DeployRunOptions, InitResult, SpawnFunction, SpawnOptions, SpawnedProcess, State$2 as State, WranglerErrorKind };
|
|
1666
1666
|
}
|
|
1667
1667
|
/**
|
|
1668
|
-
*
|
|
1669
|
-
*
|
|
1670
|
-
* @example
|
|
1671
|
-
* ```ts
|
|
1672
|
-
* { contentDir: "./src/content", trustedContent: false, shikiTheme: "github-dark" }
|
|
1673
|
-
* ```
|
|
1674
|
-
*/
|
|
1675
|
-
type Config$1 = {
|
|
1676
|
-
/** Absolute or project-relative path to the content directory. Validated in onInit. */contentDir: string;
|
|
1677
|
-
/**
|
|
1678
|
-
* SECURITY GATE. When false (the default), rehype-sanitize runs as the final
|
|
1679
|
-
* pipeline step. Set true ONLY for fully author-controlled Markdown — true
|
|
1680
|
-
* disables sanitize and trusts all raw HTML.
|
|
1681
|
-
*/
|
|
1682
|
-
trustedContent: boolean; /** Additional remark plugins, concatenated AFTER framework defaults. Defaults to []. */
|
|
1683
|
-
extraRemarkPlugins?: readonly Pluggable[]; /** Additional rehype plugins, concatenated after custom transforms, before Shiki + sanitize. Defaults to []. */
|
|
1684
|
-
extraRehypePlugins?: readonly Pluggable[];
|
|
1685
|
-
/**
|
|
1686
|
-
* Shiki theme for syntax highlighting: a bundled theme NAME — typed as Shiki's
|
|
1687
|
-
* `BundledTheme` union so editors autocomplete the ~60 built-ins (default
|
|
1688
|
-
* "github-dark") — or a custom `ThemeRegistration` object. Passed straight through
|
|
1689
|
-
* to `@shikijs/rehype`'s `theme`. (Like Shiki's own theme type, an arbitrary string
|
|
1690
|
-
* still compiles via the object arm, so this is autocomplete, not typo-rejection.)
|
|
1691
|
-
*/
|
|
1692
|
-
shikiTheme?: BundledTheme | ThemeRegistrationAny; /** Author applied to articles whose frontmatter omits author. Defaults to undefined. */
|
|
1693
|
-
defaultAuthor?: string;
|
|
1694
|
-
};
|
|
1695
|
-
/**
|
|
1696
|
-
* Internal mutable state for the content plugin.
|
|
1697
|
-
*
|
|
1698
|
-
* @example
|
|
1699
|
-
* ```ts
|
|
1700
|
-
* { processor: null, articles: new Map(), slugs: null, dirtyPaths: new Set() }
|
|
1701
|
-
* ```
|
|
1702
|
-
*/
|
|
1703
|
-
type State$1 = {
|
|
1704
|
-
/** Lazily-created unified processor singleton. null until first render()/loadAll(). */processor: Processor | null; /** Article cache keyed locale -> (slug -> Article). Starts empty. */
|
|
1705
|
-
articles: Map<string, Map<string, Article>>; /** Discovered, sorted slug list cached after first disk scan. null until first discovery. */
|
|
1706
|
-
slugs: string[] | null; /** Paths marked stale by invalidate(); next loadAll() re-reads only these. Starts empty. */
|
|
1707
|
-
dirtyPaths: Set<string>;
|
|
1708
|
-
};
|
|
1709
|
-
/**
|
|
1710
|
-
* YAML frontmatter parsed from each article file.
|
|
1711
|
-
*
|
|
1712
|
-
* @example
|
|
1713
|
-
* ```ts
|
|
1714
|
-
* { title: "Hello", date: "2026-01-15", description: "Intro", tags: [], language: "en" }
|
|
1715
|
-
* ```
|
|
1668
|
+
* @file deploy plugin — type definitions.
|
|
1716
1669
|
*/
|
|
1717
|
-
type Frontmatter = {
|
|
1718
|
-
/** Article title. Required. */title: string; /** ISO 8601 date string, e.g. "2026-01-15". Required. */
|
|
1719
|
-
date: string; /** Short summary used in cards, feeds, and meta description. Required. */
|
|
1720
|
-
description: string; /** Topic tags. Required (may be empty array). */
|
|
1721
|
-
tags: string[]; /** Source language code of this file. Required. */
|
|
1722
|
-
language: string; /** Draft flag. Excluded from output in production mode. Defaults to false. */
|
|
1723
|
-
draft?: boolean; /** Author name. Falls back to config.defaultAuthor when omitted. */
|
|
1724
|
-
author?: string;
|
|
1725
|
-
};
|
|
1726
1670
|
/**
|
|
1727
|
-
*
|
|
1728
|
-
*
|
|
1729
|
-
* @example
|
|
1730
|
-
* ```ts
|
|
1731
|
-
* { slug: "hello", readingTime: 1, contentId: "hello", status: "published", wordCount: 42 }
|
|
1732
|
-
* ```
|
|
1671
|
+
* Options passed to the injected spawner — the subset of Bun.spawn's options the
|
|
1672
|
+
* plugin uses (piped stdout/stderr plus an env carrying the API token).
|
|
1733
1673
|
*/
|
|
1734
|
-
|
|
1735
|
-
/**
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1674
|
+
interface SpawnOptions {
|
|
1675
|
+
/** Capture stdout as a readable stream. */
|
|
1676
|
+
readonly stdout: "pipe";
|
|
1677
|
+
/** Capture stderr as a readable stream. */
|
|
1678
|
+
readonly stderr: "pipe";
|
|
1679
|
+
/** Subprocess environment — the API token is injected here, never via argv. */
|
|
1680
|
+
readonly env?: Record<string, string | undefined>;
|
|
1681
|
+
}
|
|
1741
1682
|
/**
|
|
1742
|
-
*
|
|
1743
|
-
*
|
|
1744
|
-
*
|
|
1745
|
-
* ```ts
|
|
1746
|
-
* { frontmatter, computed, html: "<p>…</p>", locale: "en", isFallback: false, url: "/en/hello/" }
|
|
1747
|
-
* ```
|
|
1683
|
+
* The structural subprocess handle the plugin reads back: stdout/stderr streams
|
|
1684
|
+
* plus the exit-code promise. Streams are typed `unknown` and narrowed at the read
|
|
1685
|
+
* site so this carries no Bun namespace types.
|
|
1748
1686
|
*/
|
|
1749
|
-
|
|
1750
|
-
/**
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
}
|
|
1687
|
+
interface SpawnedProcess {
|
|
1688
|
+
/** Standard output stream (narrowed to a ReadableStream at the read site). */
|
|
1689
|
+
readonly stdout: unknown;
|
|
1690
|
+
/** Standard error stream (narrowed to a ReadableStream at the read site). */
|
|
1691
|
+
readonly stderr: unknown;
|
|
1692
|
+
/** Resolves with the subprocess exit code. */
|
|
1693
|
+
readonly exited: Promise<number>;
|
|
1694
|
+
}
|
|
1757
1695
|
/**
|
|
1758
|
-
*
|
|
1759
|
-
*
|
|
1760
|
-
*
|
|
1761
|
-
* ```ts
|
|
1762
|
-
* { contentId: "hello", status: "published", title: "Hello", date: "2026-01-15", description: "Intro", tags: [], readingTime: 1, url: "/en/hello/" }
|
|
1763
|
-
* ```
|
|
1696
|
+
* The subset of Bun.spawn's signature the plugin relies on (argv array + options).
|
|
1697
|
+
* Declared structurally — with NO `import("bun")` namespace types — so it survives
|
|
1698
|
+
* `.d.ts` bundling intact and tests can supply a fake spawn without importing Bun.
|
|
1764
1699
|
*/
|
|
1765
|
-
type
|
|
1766
|
-
/** Stable content identifier. */contentId: string; /** Derived publication status. */
|
|
1767
|
-
status: "published" | "draft"; /** Article title. */
|
|
1768
|
-
title: string; /** ISO 8601 date string. */
|
|
1769
|
-
date: string; /** Short summary. */
|
|
1770
|
-
description: string; /** Topic tags. */
|
|
1771
|
-
tags: string[]; /** Reading time in minutes. */
|
|
1772
|
-
readingTime: number; /** Canonical URL for this article in this locale. */
|
|
1773
|
-
url: string;
|
|
1774
|
-
};
|
|
1700
|
+
type SpawnFunction = (cmd: string[], options: SpawnOptions) => SpawnedProcess;
|
|
1775
1701
|
/**
|
|
1776
|
-
*
|
|
1777
|
-
*
|
|
1778
|
-
* @example
|
|
1779
|
-
* ```ts
|
|
1780
|
-
* emit("content:ready", { locales: ["en"], articleCount: 3 });
|
|
1781
|
-
* ```
|
|
1702
|
+
* A deploy error `code` from the wrangler error taxonomy and preflight validators.
|
|
1782
1703
|
*/
|
|
1783
|
-
type
|
|
1784
|
-
/** All articles loaded across locales. */"content:ready": {
|
|
1785
|
-
locales: readonly string[];
|
|
1786
|
-
articleCount: number;
|
|
1787
|
-
}; /** Article paths marked stale for dev rebuild. */
|
|
1788
|
-
"content:invalidated": {
|
|
1789
|
-
paths: readonly string[];
|
|
1790
|
-
};
|
|
1791
|
-
};
|
|
1704
|
+
type DeployErrorCode = "ERR_DEPLOY_NO_WRANGLER_CONFIG" | "ERR_DEPLOY_EMPTY_OUTDIR" | "ERR_DEPLOY_TOO_MANY_FILES" | "ERR_DEPLOY_FILE_TOO_LARGE" | "ERR_DEPLOY_PATH_TRAVERSAL" | "ERR_DEPLOY_INVALID_BRANCH" | "ERR_DEPLOY_NO_TOKEN" | "ERR_DEPLOY_PROJECT_NOT_FOUND" | "ERR_DEPLOY_AUTH_EXPIRED" | "ERR_DEPLOY_AUTH" | "ERR_DEPLOY_NETWORK" | "ERR_DEPLOY_WRANGLER_FAILED" | "ERR_DEPLOY_CONFIG";
|
|
1792
1705
|
/**
|
|
1793
|
-
*
|
|
1794
|
-
*
|
|
1795
|
-
* i18n-derived locale/url helpers — so api.ts stays free of createPlugin/ctx.
|
|
1796
|
-
*
|
|
1797
|
-
* @example
|
|
1798
|
-
* ```ts
|
|
1799
|
-
* const apiContext: ContentApiContext = { state, config, global, emit, locales, defaultLocale, articleToUrl };
|
|
1800
|
-
* ```
|
|
1706
|
+
* The subset of wrangler error `code`s classifyWranglerError can produce from a
|
|
1707
|
+
* non-zero wrangler exit.
|
|
1801
1708
|
*/
|
|
1802
|
-
type
|
|
1803
|
-
/** Mutable plugin state (article cache + lazy processor). */state: State$1; /** Resolved plugin configuration. */
|
|
1804
|
-
config: Config$1; /** Global framework configuration (mode, etc.). */
|
|
1805
|
-
global: {
|
|
1806
|
-
mode: "production" | "development";
|
|
1807
|
-
}; /** Emit a registered content event. */
|
|
1808
|
-
emit: <K extends keyof ContentEvents>(event: K, payload: ContentEvents[K]) => void; /** Active locale codes from i18n. */
|
|
1809
|
-
locales: () => readonly string[]; /** Default locale code from i18n (fallback source). */
|
|
1810
|
-
defaultLocale: () => string; /** Build a canonical article URL for a locale + slug. */
|
|
1811
|
-
articleToUrl: (locale: string, slug: string) => string;
|
|
1812
|
-
};
|
|
1709
|
+
type WranglerErrorKind = Extract<DeployErrorCode, "ERR_DEPLOY_PROJECT_NOT_FOUND" | "ERR_DEPLOY_AUTH_EXPIRED" | "ERR_DEPLOY_AUTH" | "ERR_DEPLOY_NETWORK" | "ERR_DEPLOY_WRANGLER_FAILED">;
|
|
1813
1710
|
/**
|
|
1814
|
-
*
|
|
1815
|
-
*
|
|
1816
|
-
* @example
|
|
1817
|
-
* ```ts
|
|
1818
|
-
* const map = await app.content.loadAll();
|
|
1819
|
-
* ```
|
|
1711
|
+
* Configuration for the deploy plugin.
|
|
1820
1712
|
*/
|
|
1821
|
-
type
|
|
1713
|
+
type Config$2 = {
|
|
1822
1714
|
/**
|
|
1823
|
-
*
|
|
1824
|
-
*
|
|
1715
|
+
* Deploy target. Only Cloudflare Pages is supported in this version.
|
|
1716
|
+
* Defaults to `cloudflare-pages`.
|
|
1825
1717
|
*/
|
|
1826
|
-
|
|
1718
|
+
target: "cloudflare-pages";
|
|
1827
1719
|
/**
|
|
1828
|
-
*
|
|
1829
|
-
*
|
|
1830
|
-
*
|
|
1831
|
-
* @param locale - Requested locale code.
|
|
1720
|
+
* Directory (relative to project root) containing the built site to deploy.
|
|
1721
|
+
* Re-validated against cwd at run() time to block path traversal.
|
|
1722
|
+
* Defaults to `dist`.
|
|
1832
1723
|
*/
|
|
1833
|
-
|
|
1724
|
+
outDir: string;
|
|
1834
1725
|
/**
|
|
1835
|
-
*
|
|
1836
|
-
*
|
|
1837
|
-
* @param md - Raw Markdown source.
|
|
1726
|
+
* Branch treated as the Cloudflare Pages production branch.
|
|
1727
|
+
* Defaults to `main`.
|
|
1838
1728
|
*/
|
|
1839
|
-
|
|
1729
|
+
productionBranch?: string;
|
|
1840
1730
|
/**
|
|
1841
|
-
*
|
|
1842
|
-
*
|
|
1843
|
-
* @param paths - File paths to invalidate.
|
|
1731
|
+
* Substrings exempt from entropy-gated secret scrubbing in logged output.
|
|
1732
|
+
* Defaults to `["CLOUDFLARE_ACCOUNT_ID"]`.
|
|
1844
1733
|
*/
|
|
1845
|
-
|
|
1734
|
+
scrubAllowlist: string[];
|
|
1846
1735
|
/**
|
|
1847
|
-
*
|
|
1848
|
-
*
|
|
1849
|
-
* @param article - The source article.
|
|
1736
|
+
* Cloudflare compatibility date written into generated wrangler.jsonc.
|
|
1737
|
+
* Defaults to `2024-01-01`.
|
|
1850
1738
|
*/
|
|
1851
|
-
|
|
1739
|
+
compatibilityDate?: string;
|
|
1852
1740
|
/**
|
|
1853
|
-
*
|
|
1854
|
-
*
|
|
1855
|
-
* image URLs the renderer emits resolve.
|
|
1741
|
+
* Whether init() also generates a GitHub Actions workflow.
|
|
1742
|
+
* Defaults to `false`.
|
|
1856
1743
|
*/
|
|
1857
|
-
|
|
1744
|
+
ci?: boolean;
|
|
1858
1745
|
};
|
|
1859
|
-
//#endregion
|
|
1860
|
-
//#region src/plugins/content/index.d.ts
|
|
1861
1746
|
/**
|
|
1862
|
-
*
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
*
|
|
1872
|
-
*
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1747
|
+
* Result of a successful deploy.
|
|
1748
|
+
*/
|
|
1749
|
+
type DeployResult = {
|
|
1750
|
+
/** The public deployment URL (e.g. https://my-site.pages.dev). */url: string; /** Cloudflare deployment ID parsed from wrangler output. */
|
|
1751
|
+
deploymentId: string; /** The branch that was deployed. */
|
|
1752
|
+
branch: string; /** Wall-clock duration of the deploy in milliseconds. */
|
|
1753
|
+
durationMs: number;
|
|
1754
|
+
};
|
|
1755
|
+
/**
|
|
1756
|
+
* Runtime state for the deploy plugin. Created in createState() and accessed via
|
|
1757
|
+
* ctx.state. deploy declares no onStop because nothing here is a long-lived resource.
|
|
1758
|
+
*/
|
|
1759
|
+
type State$2 = {
|
|
1760
|
+
/** Result of the most recent successful deploy, or null before the first run. */lastDeployment: DeployResult | null;
|
|
1761
|
+
/**
|
|
1762
|
+
* Injectable subprocess spawner. Defaults to Bun.spawn. Swapped for a mock in
|
|
1763
|
+
* unit tests so wrangler is never actually invoked. Never reassigned at runtime.
|
|
1764
|
+
*/
|
|
1765
|
+
spawn: SpawnFunction;
|
|
1766
|
+
};
|
|
1767
|
+
/**
|
|
1768
|
+
* Options for DeployApi.run.
|
|
1769
|
+
*/
|
|
1770
|
+
type DeployRunOptions = {
|
|
1771
|
+
/**
|
|
1772
|
+
* Branch to deploy. Defaults to config.productionBranch (or "main"). Must match
|
|
1773
|
+
* /^[a-zA-Z0-9/_.-]+$/ — otherwise rejected with ERR_DEPLOY_INVALID_BRANCH.
|
|
1774
|
+
*/
|
|
1775
|
+
branch?: string;
|
|
1776
|
+
/**
|
|
1777
|
+
* Whether to run the build before deploying. When false, deploys the existing outDir.
|
|
1778
|
+
* Defaults to `true`.
|
|
1779
|
+
*/
|
|
1780
|
+
build?: boolean;
|
|
1781
|
+
};
|
|
1782
|
+
/**
|
|
1783
|
+
* Options for DeployApi.init.
|
|
1784
|
+
*/
|
|
1785
|
+
type DeployInitOptions = {
|
|
1786
|
+
/** Also generate the GitHub Actions workflow. Defaults to config.ci. */ci?: boolean; /** Drift-only mode: report differences without writing any files. Defaults to `false`. */
|
|
1787
|
+
check?: boolean;
|
|
1788
|
+
};
|
|
1789
|
+
/**
|
|
1790
|
+
* Result of an init/scaffold operation.
|
|
1791
|
+
*/
|
|
1792
|
+
type InitResult = {
|
|
1793
|
+
/** Paths written this invocation. */written: string[]; /** Paths skipped because they already exist. */
|
|
1794
|
+
skipped: string[]; /** In check mode: paths whose on-disk content differs from what would be generated. */
|
|
1795
|
+
drifted: string[];
|
|
1796
|
+
};
|
|
1797
|
+
/**
|
|
1798
|
+
* Public API of the deploy plugin (returned from the api factory).
|
|
1799
|
+
*/
|
|
1800
|
+
type Api$2 = {
|
|
1801
|
+
/**
|
|
1802
|
+
* Deploy the built outDir to Cloudflare Pages via the wrangler subprocess.
|
|
1803
|
+
* Runs preflight validators, re-validates the resolved outdir against cwd, guards
|
|
1804
|
+
* the branch argument, spawns wrangler (no shell), scrubs all subprocess output
|
|
1805
|
+
* before logging, records lastDeployment, and emits deploy:complete.
|
|
1806
|
+
*
|
|
1807
|
+
* @param options - Optional branch override and build toggle.
|
|
1808
|
+
* @returns The deploy result (url, deploymentId, branch, durationMs).
|
|
1809
|
+
* @throws {Error} With a `code` from the deploy error taxonomy on any failure.
|
|
1810
|
+
* @example
|
|
1811
|
+
* const result = await app.deploy.run();
|
|
1812
|
+
* console.log(result.url); // https://my-site.pages.dev
|
|
1813
|
+
* @example
|
|
1814
|
+
* await app.deploy.run({ branch: "preview/landing", build: false });
|
|
1815
|
+
*/
|
|
1816
|
+
run(options?: DeployRunOptions): Promise<DeployResult>;
|
|
1817
|
+
/**
|
|
1818
|
+
* Return the most recent successful deploy result, or null if none has occurred.
|
|
1819
|
+
* The returned object is read-only (a defensive snapshot).
|
|
1820
|
+
*
|
|
1821
|
+
* @returns The last DeployResult, or null.
|
|
1822
|
+
* @example
|
|
1823
|
+
* const last = app.deploy.getLastDeployment();
|
|
1824
|
+
* if (last) console.log(`Last deployed to ${last.url}`);
|
|
1825
|
+
*/
|
|
1826
|
+
getLastDeployment(): Readonly<DeployResult> | null;
|
|
1827
|
+
/**
|
|
1828
|
+
* Generate deploy scaffolding: wrangler.jsonc (slug from site.name() + outDir +
|
|
1829
|
+
* compatibilityDate) and, when ci is enabled, .github/workflows/deploy.yml. Never
|
|
1830
|
+
* overwrites an existing wrangler.jsonc. In check mode, reports drift instead of writing.
|
|
1831
|
+
*
|
|
1832
|
+
* @param options - Optional ci toggle and check (drift-only) mode.
|
|
1833
|
+
* @returns Which files were written, skipped, or would drift.
|
|
1834
|
+
* @example
|
|
1835
|
+
* const out = await app.deploy.init({ ci: true });
|
|
1836
|
+
* // out.written -> ["wrangler.jsonc", ".github/workflows/deploy.yml"]
|
|
1837
|
+
* @example
|
|
1838
|
+
* const drift = await app.deploy.init({ check: true });
|
|
1839
|
+
* if (drift.drifted.length) process.exit(1);
|
|
1840
|
+
*/
|
|
1841
|
+
init(options?: DeployInitOptions): Promise<InitResult>;
|
|
1842
|
+
};
|
|
1843
|
+
declare namespace types_d_exports$1 {
|
|
1844
|
+
export { Api$1 as Api, BuildOptions, BuildSummary, CliErrorCode, CliRenderer, Command, Config$1 as Config, DeployOptions, DeployOutcome, FileResponseFunction, PreviewOptions, ReloadInfo, ServeOptions, ServeStaticFunction, ServeStaticOptions, ServerHandle, ServerInfo, State$1 as State, WatchHandle };
|
|
1845
|
+
}
|
|
1846
|
+
/**
|
|
1847
|
+
* A cli error `code` from the config-validation and runtime taxonomy. Mirrors the
|
|
1848
|
+
* deploy plugin's coded-error pattern so every thrown value carries a stable `code`.
|
|
1849
|
+
*
|
|
1850
|
+
* @example
|
|
1851
|
+
* const code: CliErrorCode = "ERR_CLI_CONFIG";
|
|
1852
|
+
*/
|
|
1853
|
+
type CliErrorCode = "ERR_CLI_CONFIG" | "ERR_CLI_NOT_FOUND";
|
|
1854
|
+
/**
|
|
1855
|
+
* The four commands a single cli process can run. Each maps to one consumer script
|
|
1856
|
+
* (`scripts/{build,serve,preview,deploy}.ts`) and is rendered as the Panel header.
|
|
1857
|
+
*
|
|
1858
|
+
* @example
|
|
1859
|
+
* const command: Command = "build";
|
|
1860
|
+
*/
|
|
1861
|
+
type Command = "build" | "serve" | "preview" | "deploy";
|
|
1862
|
+
/**
|
|
1863
|
+
* Information rendered into the bordered server-ready panel by `serve()`/`preview()`.
|
|
1864
|
+
*
|
|
1865
|
+
* @example
|
|
1866
|
+
* const info: ServerInfo = { local: "http://localhost:4173", network: null };
|
|
1867
|
+
*/
|
|
1868
|
+
type ServerInfo = {
|
|
1869
|
+
/** The loopback URL the server is reachable at (e.g. `http://localhost:4173`). */local: string; /** The LAN URL derived from the first non-internal IPv4, or `null` when offline. */
|
|
1870
|
+
network: string | null; /** Directories `serve()` is watching for changes (omitted by `preview()`). */
|
|
1871
|
+
watching?: string[];
|
|
1872
|
+
};
|
|
1873
|
+
/**
|
|
1874
|
+
* Information rendered after a single `serve()` rebuild: which file changed plus the
|
|
1875
|
+
* fresh build summary used to print the "rebuilt N pages" line.
|
|
1876
|
+
*
|
|
1877
|
+
* @example
|
|
1878
|
+
* const info: ReloadInfo = { file: "content/post.md", pageCount: 12, durationMs: 84 };
|
|
1879
|
+
*/
|
|
1880
|
+
type ReloadInfo = {
|
|
1881
|
+
/** The changed path that triggered the rebuild. */file: string; /** Number of route pages rendered by the rebuild. */
|
|
1882
|
+
pageCount: number; /** Wall-clock duration of the rebuild in milliseconds. */
|
|
1883
|
+
durationMs: number;
|
|
1884
|
+
};
|
|
1885
|
+
/**
|
|
1886
|
+
* The Panel renderer surface — every line of terminal output flows through this so
|
|
1887
|
+
* tests can inject a line-capturing fake. Implemented by `createPanelRenderer` and
|
|
1888
|
+
* is TTY/`NO_COLOR`-aware (box-drawing + color on a TTY, plain lines otherwise).
|
|
1889
|
+
*
|
|
1890
|
+
* @example
|
|
1891
|
+
* const render: CliRenderer = createPanelRenderer();
|
|
1892
|
+
* render.header("build");
|
|
1893
|
+
*/
|
|
1894
|
+
type CliRenderer = {
|
|
1895
|
+
/**
|
|
1896
|
+
* Render the boxed `MOKU WEB` logo + command label. Called once per command (one
|
|
1897
|
+
* command = one process), so it never repeats within a run.
|
|
1898
|
+
*
|
|
1899
|
+
* @param command - The command being run, shown beside the logo.
|
|
1900
|
+
* @returns Nothing.
|
|
1901
|
+
* @example
|
|
1902
|
+
* render.header("serve");
|
|
1903
|
+
*/
|
|
1904
|
+
header(command: Command): void;
|
|
1905
|
+
/**
|
|
1906
|
+
* Render a live per-phase row from a `build:phase` event.
|
|
1907
|
+
*
|
|
1908
|
+
* @param phase - The `build:phase` payload (`{ phase, status, durationMs? }`).
|
|
1909
|
+
* @returns Nothing.
|
|
1910
|
+
* @example
|
|
1911
|
+
* render.phase({ phase: "pages", status: "done", durationMs: 12 });
|
|
1912
|
+
*/
|
|
1913
|
+
phase(phase: BuildEvents["build:phase"]): void;
|
|
1914
|
+
/**
|
|
1915
|
+
* Render the BUILD summary block from a `build:complete` event.
|
|
1916
|
+
*
|
|
1917
|
+
* @param summary - The `build:complete` payload (`{ outDir, pageCount, durationMs }`).
|
|
1918
|
+
* @returns Nothing.
|
|
1919
|
+
* @example
|
|
1920
|
+
* render.built({ outDir: "dist", pageCount: 12, durationMs: 840 });
|
|
1921
|
+
*/
|
|
1922
|
+
built(summary: BuildEvents["build:complete"]): void;
|
|
1923
|
+
/**
|
|
1924
|
+
* Render the bordered server-ready panel (Local / Network URLs + watched dirs).
|
|
1925
|
+
*
|
|
1926
|
+
* @param info - Local/Network URLs and optionally the watched directories.
|
|
1927
|
+
* @returns Nothing.
|
|
1928
|
+
* @example
|
|
1929
|
+
* render.serverReady({ local: "http://localhost:4173", network: null });
|
|
1930
|
+
*/
|
|
1931
|
+
serverReady(info: ServerInfo): void;
|
|
1932
|
+
/**
|
|
1933
|
+
* Render the post-rebuild line ("~ file" + "✓ rebuilt N pages · Xms · reloaded").
|
|
1934
|
+
*
|
|
1935
|
+
* @param info - The changed file plus the rebuild's page count and duration.
|
|
1936
|
+
* @returns Nothing.
|
|
1937
|
+
* @example
|
|
1938
|
+
* render.reload({ file: "content/a.md", pageCount: 12, durationMs: 84 });
|
|
1939
|
+
*/
|
|
1940
|
+
reload(info: ReloadInfo): void;
|
|
1941
|
+
/**
|
|
1942
|
+
* Render the deploy result panel from a `deploy:complete` event.
|
|
1943
|
+
*
|
|
1944
|
+
* @param result - The `deploy:complete` payload (`{ url, deploymentId, branch, durationMs }`).
|
|
1945
|
+
* @returns Nothing.
|
|
1946
|
+
* @example
|
|
1947
|
+
* render.deployed({ url: "https://x.pages.dev", deploymentId: "id", branch: "main", durationMs: 1200 });
|
|
1948
|
+
*/
|
|
1949
|
+
deployed(result: DeployResult): void;
|
|
1950
|
+
/**
|
|
1951
|
+
* Render a neutral informational line (e.g. the non-interactive deploy note, watch notice).
|
|
1952
|
+
*
|
|
1953
|
+
* @param message - The line to print.
|
|
1954
|
+
* @returns Nothing.
|
|
1955
|
+
* @example
|
|
1956
|
+
* render.info("watching for changes…");
|
|
1957
|
+
*/
|
|
1958
|
+
info(message: string): void;
|
|
1959
|
+
/**
|
|
1960
|
+
* Render a warning line (written to stderr).
|
|
1961
|
+
*
|
|
1962
|
+
* @param message - The warning to print.
|
|
1963
|
+
* @returns Nothing.
|
|
1964
|
+
* @example
|
|
1965
|
+
* render.warn("deploy skipped");
|
|
1966
|
+
*/
|
|
1967
|
+
warn(message: string): void;
|
|
1968
|
+
/**
|
|
1969
|
+
* Render an error line (written to stderr), optionally with a cause.
|
|
1970
|
+
*
|
|
1971
|
+
* @param message - The error summary to print.
|
|
1972
|
+
* @param cause - Optional underlying error/value to print beneath the summary.
|
|
1973
|
+
* @returns Nothing.
|
|
1974
|
+
* @example
|
|
1975
|
+
* render.error("build failed", err);
|
|
1976
|
+
*/
|
|
1977
|
+
error(message: string, cause?: unknown): void;
|
|
1978
|
+
};
|
|
1979
|
+
/**
|
|
1980
|
+
* A live directory watcher handle returned by the injectable `watch` seam. Closing
|
|
1981
|
+
* it detaches the underlying `node:fs.watch` listener.
|
|
1982
|
+
*
|
|
1983
|
+
* @example
|
|
1984
|
+
* const handle: WatchHandle = state.watch("content", onChange);
|
|
1985
|
+
* handle.close();
|
|
1986
|
+
*/
|
|
1987
|
+
type WatchHandle = {
|
|
1988
|
+
/**
|
|
1989
|
+
* Stop watching and release the underlying listener.
|
|
1990
|
+
*
|
|
1991
|
+
* @returns Nothing.
|
|
1992
|
+
* @example
|
|
1993
|
+
* handle.close();
|
|
1994
|
+
*/
|
|
1995
|
+
close(): void;
|
|
1996
|
+
};
|
|
1997
|
+
/**
|
|
1998
|
+
* A running static server handle the cli stops on teardown. Declared structurally
|
|
1999
|
+
* (no Bun namespace types) so it survives `.d.ts` bundling and tests can supply a
|
|
2000
|
+
* fake without importing Bun.
|
|
2001
|
+
*
|
|
2002
|
+
* @example
|
|
2003
|
+
* const handle: ServerHandle = state.serveStatic({ port, fetch });
|
|
2004
|
+
* handle.stop();
|
|
2005
|
+
*/
|
|
2006
|
+
type ServerHandle = {
|
|
2007
|
+
/**
|
|
2008
|
+
* Stop the server and release its socket.
|
|
2009
|
+
*
|
|
2010
|
+
* @returns Nothing.
|
|
2011
|
+
* @example
|
|
2012
|
+
* handle.stop();
|
|
2013
|
+
*/
|
|
2014
|
+
stop(): void;
|
|
2015
|
+
};
|
|
2016
|
+
/**
|
|
2017
|
+
* The subset of `Bun.serve`'s options the cli uses: a port plus a `fetch` handler.
|
|
2018
|
+
* Declared structurally so no Bun namespace type reaches the public surface.
|
|
2019
|
+
*
|
|
2020
|
+
* @example
|
|
2021
|
+
* const opts: ServeStaticOptions = { port: 4173, fetch: () => new Response("ok") };
|
|
2022
|
+
*/
|
|
2023
|
+
type ServeStaticOptions = {
|
|
2024
|
+
/** Port to bind the server to. */port: number;
|
|
2025
|
+
/**
|
|
2026
|
+
* Per-request handler returning the response (sync or async).
|
|
2027
|
+
*
|
|
2028
|
+
* @param request - The incoming request.
|
|
2029
|
+
* @returns The response (or a promise of it).
|
|
2030
|
+
* @example
|
|
2031
|
+
* fetch(req) { return new Response("ok"); }
|
|
2032
|
+
*/
|
|
2033
|
+
fetch(request: Request): Response | Promise<Response>;
|
|
2034
|
+
};
|
|
2035
|
+
/**
|
|
2036
|
+
* An injectable static-server factory (defaults to `Bun.serve`). Keeps the Bun
|
|
2037
|
+
* runtime dependency behind a structural seam so `serve()`/`preview()` never open a
|
|
2038
|
+
* real socket in tests.
|
|
2039
|
+
*
|
|
2040
|
+
* @example
|
|
2041
|
+
* const serveStatic: ServeStaticFunction = options => Bun.serve(options);
|
|
2042
|
+
*/
|
|
2043
|
+
type ServeStaticFunction = (options: ServeStaticOptions) => ServerHandle;
|
|
2044
|
+
/**
|
|
2045
|
+
* An injectable file-response factory (defaults to `new Response(Bun.file(path))`).
|
|
2046
|
+
* Maps a resolved on-disk path + status to the response body the server returns.
|
|
2047
|
+
*
|
|
2048
|
+
* @example
|
|
2049
|
+
* const fileResponse: FileResponseFunction = (path, status) => new Response(Bun.file(path), { status });
|
|
2050
|
+
*/
|
|
2051
|
+
type FileResponseFunction = (path: string, status: number) => Response;
|
|
2052
|
+
/**
|
|
2053
|
+
* Configuration for the cli plugin — the complete resolved `Config` (not a partial).
|
|
2054
|
+
* Consumers override individual fields via `pluginConfigs.cli`.
|
|
2055
|
+
*
|
|
2056
|
+
* @example
|
|
2057
|
+
* const config: Config = {
|
|
2058
|
+
* outDir: "dist", port: 4173, watchDirs: ["content", "src"],
|
|
2059
|
+
* debounceMs: 150, notFoundFile: "404.html", liveReload: true
|
|
2060
|
+
* };
|
|
2061
|
+
*/
|
|
2062
|
+
type Config$1 = {
|
|
2063
|
+
/** Build output directory; served by preview, asserted by build, rebuilt by serve. Default `"dist"`. */outDir: string; /** Default port for serve()/preview() (overridable per-call via options.port). Default `4173`. */
|
|
2064
|
+
port: number; /** Directories serve() watches for changes (recursive). Default `["content", "src"]`. */
|
|
2065
|
+
watchDirs: string[]; /** Debounce window (ms) coalescing FS-event bursts into one rebuild. Default `150`. */
|
|
2066
|
+
debounceMs: number; /** Filename build() asserts exists at outDir root (CF Pages flips to SPA mode without it). Default `"404.html"`. */
|
|
2067
|
+
notFoundFile: string; /** Inject the live-reload SSE client into HTML during serve() (never during preview()). Default `true`. */
|
|
2068
|
+
liveReload: boolean;
|
|
2069
|
+
};
|
|
2070
|
+
/**
|
|
2071
|
+
* Runtime state for the cli plugin — injectable seams so every command is testable
|
|
2072
|
+
* without real sockets/FS-watch/TTY (mirrors deploy's injectable `spawn`).
|
|
2073
|
+
*
|
|
2074
|
+
* @example
|
|
2075
|
+
* const state: State = createState();
|
|
2076
|
+
*/
|
|
2077
|
+
type State$1 = {
|
|
2078
|
+
/** Panel renderer — all terminal output flows through this. Tests inject a line-capturing fake. */render: CliRenderer;
|
|
2079
|
+
/**
|
|
2080
|
+
* Interactive y/N prompt used by deploy(). Default reads stdin (TTY); tests inject a canned answer.
|
|
2081
|
+
*
|
|
2082
|
+
* @param question - The yes/no question to display.
|
|
2083
|
+
* @returns Resolves `true` when the user answered yes.
|
|
2084
|
+
* @example
|
|
2085
|
+
* const ok = await state.confirm("Deploy dist/?");
|
|
2086
|
+
*/
|
|
2087
|
+
confirm: (question: string) => Promise<boolean>;
|
|
2088
|
+
/**
|
|
2089
|
+
* Monotonic clock for durations. Default `Date.now`; tests inject for deterministic timing.
|
|
2090
|
+
*
|
|
2091
|
+
* @returns The current time in milliseconds.
|
|
2092
|
+
* @example
|
|
2093
|
+
* const t = state.clock();
|
|
2094
|
+
*/
|
|
2095
|
+
clock: () => number;
|
|
2096
|
+
/**
|
|
2097
|
+
* Recursive directory watcher factory used by serve(). Default wraps `node:fs.watch`;
|
|
2098
|
+
* tests inject a fake emitter.
|
|
2099
|
+
*
|
|
2100
|
+
* @param dir - The directory to watch recursively.
|
|
2101
|
+
* @param onChange - Invoked on any change beneath `dir`.
|
|
2102
|
+
* @returns A handle whose `close()` detaches the watcher.
|
|
2103
|
+
* @example
|
|
2104
|
+
* const handle = state.watch("content", () => rebuild());
|
|
2105
|
+
*/
|
|
2106
|
+
watch: (dir: string, onChange: () => void) => WatchHandle; /** Static-server factory used by serve()/preview(). Default `Bun.serve`; tests inject a fake. */
|
|
2107
|
+
serveStatic: ServeStaticFunction; /** File-response factory mapping a resolved path + status to a `Response`. Default `Bun.file`. */
|
|
2108
|
+
fileResponse: FileResponseFunction;
|
|
2109
|
+
/**
|
|
2110
|
+
* LAN network-URL deriver for the server-ready panel. Default reads `node:os`
|
|
2111
|
+
* interfaces; tests inject a deterministic value.
|
|
2112
|
+
*
|
|
2113
|
+
* @param port - The port the server is bound to.
|
|
2114
|
+
* @returns The `http://<ip>:<port>` URL, or `null` when offline.
|
|
2115
|
+
* @example
|
|
2116
|
+
* const url = state.networkUrl(4173);
|
|
2117
|
+
*/
|
|
2118
|
+
networkUrl: (port: number) => string | null;
|
|
2119
|
+
};
|
|
2120
|
+
/**
|
|
2121
|
+
* Summary returned by `cli.build()` — the awaited `build.run()` result.
|
|
2122
|
+
*
|
|
2123
|
+
* @example
|
|
2124
|
+
* const summary: BuildSummary = { outDir: "dist", pageCount: 12, durationMs: 840 };
|
|
2125
|
+
*/
|
|
2126
|
+
type BuildSummary = {
|
|
2127
|
+
/** Resolved output directory the site was written to. */outDir: string; /** Number of route pages rendered. */
|
|
2128
|
+
pageCount: number; /** Total wall-clock duration of the run, in milliseconds. */
|
|
2129
|
+
durationMs: number;
|
|
2130
|
+
};
|
|
2131
|
+
/**
|
|
2132
|
+
* Outcome returned by `cli.deploy()` — either a completed deploy (with details) or a
|
|
2133
|
+
* skipped one. A skip happens only when an interactive TTY user answers "no" at the
|
|
2134
|
+
* confirm prompt (`reason: "declined"`). Non-interactive runs (CI / non-TTY) never
|
|
2135
|
+
* prompt and always proceed, so they never skip — the scripts are CI-safe.
|
|
2136
|
+
*
|
|
2137
|
+
* @example
|
|
2138
|
+
* const outcome: DeployOutcome = { deployed: false, reason: "declined" };
|
|
2139
|
+
*/
|
|
2140
|
+
type DeployOutcome = {
|
|
2141
|
+
deployed: true;
|
|
2142
|
+
url: string;
|
|
2143
|
+
deploymentId: string;
|
|
2144
|
+
branch: string;
|
|
2145
|
+
durationMs: number;
|
|
2146
|
+
} | {
|
|
2147
|
+
deployed: false;
|
|
2148
|
+
reason: "declined";
|
|
2149
|
+
};
|
|
2150
|
+
/**
|
|
2151
|
+
* Options for `cli.build()`.
|
|
2152
|
+
*
|
|
2153
|
+
* @example
|
|
2154
|
+
* await app.cli.build({ assertNotFound: false });
|
|
2155
|
+
*/
|
|
2156
|
+
type BuildOptions = {
|
|
2157
|
+
/** Assert `outDir/notFoundFile` exists after the build. Defaults to `true`. */assertNotFound?: boolean;
|
|
2158
|
+
};
|
|
2159
|
+
/**
|
|
2160
|
+
* Options for `cli.serve()`.
|
|
2161
|
+
*
|
|
2162
|
+
* @example
|
|
2163
|
+
* await app.cli.serve({ port: 3000 });
|
|
2164
|
+
*/
|
|
2165
|
+
type ServeOptions = {
|
|
2166
|
+
/** Port to bind the dev server to. Defaults to `config.port`. */port?: number; /** Reserved for opening the browser on start (not yet implemented). Defaults to `false`. */
|
|
2167
|
+
open?: boolean;
|
|
2168
|
+
};
|
|
2169
|
+
/**
|
|
2170
|
+
* Options for `cli.preview()`.
|
|
2171
|
+
*
|
|
2172
|
+
* @example
|
|
2173
|
+
* await app.cli.preview({ port: 8080 });
|
|
2174
|
+
*/
|
|
2175
|
+
type PreviewOptions = {
|
|
2176
|
+
/** Port to bind the preview server to. Defaults to `config.port`. */port?: number;
|
|
2177
|
+
};
|
|
2178
|
+
/**
|
|
2179
|
+
* Options for `cli.deploy()`.
|
|
2180
|
+
*
|
|
2181
|
+
* @example
|
|
2182
|
+
* await app.cli.deploy({ branch: "preview/x", yes: true });
|
|
2183
|
+
*/
|
|
2184
|
+
type DeployOptions = {
|
|
2185
|
+
/** Branch to deploy. Defaults to the deploy plugin's production branch. */branch?: string; /** Skip the y/N confirm and deploy immediately. Defaults to `false`. */
|
|
2186
|
+
yes?: boolean;
|
|
2187
|
+
};
|
|
2188
|
+
/**
|
|
2189
|
+
* Public API of the cli plugin (mounted at `app.cli`) — exactly four methods.
|
|
2190
|
+
*
|
|
2191
|
+
* @example
|
|
2192
|
+
* await app.cli.build();
|
|
2193
|
+
*/
|
|
2194
|
+
type Api$1 = {
|
|
2195
|
+
/**
|
|
2196
|
+
* Run the SSG build and assert the not-found page exists.
|
|
2197
|
+
*
|
|
2198
|
+
* @param options - Optional `assertNotFound` toggle (default `true`).
|
|
2199
|
+
* @returns The build summary (`outDir`, `pageCount`, `durationMs`).
|
|
2200
|
+
* @throws {Error} `ERR_CLI_NOT_FOUND` when the not-found page is missing and asserted.
|
|
2201
|
+
* @example
|
|
2202
|
+
* const summary = await app.cli.build();
|
|
2203
|
+
*/
|
|
2204
|
+
build(options?: BuildOptions): Promise<BuildSummary>;
|
|
2205
|
+
/**
|
|
2206
|
+
* Dev loop: build once, serve `dist/` in-process (live-reload injected), watch
|
|
2207
|
+
* `watchDirs`, debounced rebuild + reload. Resolves when SIGINT/SIGTERM tears down.
|
|
2208
|
+
*
|
|
2209
|
+
* @param options - Optional port override.
|
|
2210
|
+
* @returns Resolves once the server has been torn down.
|
|
2211
|
+
* @example
|
|
2212
|
+
* await app.cli.serve({ port: 3000 });
|
|
2213
|
+
*/
|
|
2214
|
+
serve(options?: ServeOptions): Promise<void>;
|
|
2215
|
+
/**
|
|
2216
|
+
* Static preview of the built `dist/` with CF-Pages clean-URL resolution. No
|
|
2217
|
+
* reload injection (mirrors production). Resolves on SIGINT/SIGTERM.
|
|
2218
|
+
*
|
|
2219
|
+
* @param options - Optional port override.
|
|
2220
|
+
* @returns Resolves once the server has been torn down.
|
|
2221
|
+
* @example
|
|
2222
|
+
* await app.cli.preview();
|
|
2223
|
+
*/
|
|
2224
|
+
preview(options?: PreviewOptions): Promise<void>;
|
|
2225
|
+
/**
|
|
2226
|
+
* Scaffold, then deploy. A y/N confirm is shown only on an interactive TTY;
|
|
2227
|
+
* non-interactive runs (CI, or any non-TTY) skip the prompt and deploy, so the
|
|
2228
|
+
* consumer scripts never block a pipeline. `options.yes` forces the skip anywhere.
|
|
2229
|
+
*
|
|
2230
|
+
* @param options - Optional branch override and `yes` flag.
|
|
2231
|
+
* @returns The deploy outcome (completed details, or `declined` if a TTY user says no).
|
|
2232
|
+
* @example
|
|
2233
|
+
* await app.cli.deploy({ branch: "preview/x", yes: true });
|
|
2234
|
+
*/
|
|
2235
|
+
deploy(options?: DeployOptions): Promise<DeployOutcome>;
|
|
2236
|
+
};
|
|
2237
|
+
//#endregion
|
|
2238
|
+
//#region src/plugins/cli/index.d.ts
|
|
2239
|
+
/**
|
|
2240
|
+
* cli plugin — the node-only developer CLI for `@moku-labs/web`. Mounts exactly four
|
|
2241
|
+
* methods at `app.cli` (`build`/`serve`/`preview`/`deploy`), each rendering through
|
|
2242
|
+
* the boxed Panel UI. Live build/deploy progress rides on hooks over the `build` and
|
|
2243
|
+
* `deploy` plugins' events; there is no argv parser and no `run()` dispatcher — the
|
|
2244
|
+
* consumer drives it from one thin script per command.
|
|
2245
|
+
*
|
|
2246
|
+
* @example Compose the CLI in a consumer app (node-only)
|
|
2247
|
+
* ```ts
|
|
2248
|
+
* import { buildPlugin, cliPlugin, createApp, deployPlugin } from "@moku-labs/web";
|
|
2249
|
+
*
|
|
2250
|
+
* const app = createApp({
|
|
2251
|
+
* plugins: [buildPlugin, deployPlugin, cliPlugin],
|
|
2252
|
+
* pluginConfigs: { cli: { outDir: "dist", port: 4173, watchDirs: ["content", "src"] } }
|
|
2253
|
+
* });
|
|
2254
|
+
* await app.start();
|
|
2255
|
+
* await app.cli.build();
|
|
2256
|
+
* ```
|
|
2257
|
+
*/
|
|
2258
|
+
declare const cliPlugin: import("@moku-labs/core").PluginInstance<"cli", Config$1, State$1, Api$1, {}> & Record<never, never>;
|
|
2259
|
+
declare namespace types_d_exports$2 {
|
|
2260
|
+
export { Api, Article, ArticleCard, ComputedFields, Config, ContentApiContext, ContentEvents, Frontmatter, State };
|
|
2261
|
+
}
|
|
2262
|
+
/**
|
|
2263
|
+
* Configuration for the content plugin.
|
|
2264
|
+
*
|
|
2265
|
+
* @example
|
|
2266
|
+
* ```ts
|
|
2267
|
+
* { contentDir: "./src/content", trustedContent: false, shikiTheme: "github-dark" }
|
|
2268
|
+
* ```
|
|
2269
|
+
*/
|
|
2270
|
+
type Config = {
|
|
2271
|
+
/** Absolute or project-relative path to the content directory. Validated in onInit. */contentDir: string;
|
|
2272
|
+
/**
|
|
2273
|
+
* SECURITY GATE. When false (the default), rehype-sanitize runs as the final
|
|
2274
|
+
* pipeline step. Set true ONLY for fully author-controlled Markdown — true
|
|
2275
|
+
* disables sanitize and trusts all raw HTML.
|
|
2276
|
+
*/
|
|
2277
|
+
trustedContent: boolean; /** Additional remark plugins, concatenated AFTER framework defaults. Defaults to []. */
|
|
2278
|
+
extraRemarkPlugins?: readonly Pluggable[]; /** Additional rehype plugins, concatenated after custom transforms, before Shiki + sanitize. Defaults to []. */
|
|
2279
|
+
extraRehypePlugins?: readonly Pluggable[];
|
|
2280
|
+
/**
|
|
2281
|
+
* Shiki theme for syntax highlighting: a bundled theme NAME — typed as Shiki's
|
|
2282
|
+
* `BundledTheme` union so editors autocomplete the ~60 built-ins (default
|
|
2283
|
+
* "github-dark") — or a custom `ThemeRegistration` object. Passed straight through
|
|
2284
|
+
* to `@shikijs/rehype`'s `theme`. (Like Shiki's own theme type, an arbitrary string
|
|
2285
|
+
* still compiles via the object arm, so this is autocomplete, not typo-rejection.)
|
|
2286
|
+
*/
|
|
2287
|
+
shikiTheme?: BundledTheme | ThemeRegistrationAny; /** Author applied to articles whose frontmatter omits author. Defaults to undefined. */
|
|
2288
|
+
defaultAuthor?: string;
|
|
2289
|
+
};
|
|
2290
|
+
/**
|
|
2291
|
+
* Internal mutable state for the content plugin.
|
|
2292
|
+
*
|
|
2293
|
+
* @example
|
|
2294
|
+
* ```ts
|
|
2295
|
+
* { processor: null, articles: new Map(), slugs: null, dirtyPaths: new Set() }
|
|
2296
|
+
* ```
|
|
2297
|
+
*/
|
|
2298
|
+
type State = {
|
|
2299
|
+
/** Lazily-created unified processor singleton. null until first render()/loadAll(). */processor: Processor | null; /** Article cache keyed locale -> (slug -> Article). Starts empty. */
|
|
2300
|
+
articles: Map<string, Map<string, Article>>; /** Discovered, sorted slug list cached after first disk scan. null until first discovery. */
|
|
2301
|
+
slugs: string[] | null; /** Paths marked stale by invalidate(); next loadAll() re-reads only these. Starts empty. */
|
|
2302
|
+
dirtyPaths: Set<string>;
|
|
2303
|
+
};
|
|
2304
|
+
/**
|
|
2305
|
+
* YAML frontmatter parsed from each article file.
|
|
2306
|
+
*
|
|
2307
|
+
* @example
|
|
2308
|
+
* ```ts
|
|
2309
|
+
* { title: "Hello", date: "2026-01-15", description: "Intro", tags: [], language: "en" }
|
|
2310
|
+
* ```
|
|
2311
|
+
*/
|
|
2312
|
+
type Frontmatter = {
|
|
2313
|
+
/** Article title. Required. */title: string; /** ISO 8601 date string, e.g. "2026-01-15". Required. */
|
|
2314
|
+
date: string; /** Short summary used in cards, feeds, and meta description. Required. */
|
|
2315
|
+
description: string; /** Topic tags. Required (may be empty array). */
|
|
2316
|
+
tags: string[]; /** Source language code of this file. Required. */
|
|
2317
|
+
language: string; /** Draft flag. Excluded from output in production mode. Defaults to false. */
|
|
2318
|
+
draft?: boolean; /** Author name. Falls back to config.defaultAuthor when omitted. */
|
|
2319
|
+
author?: string;
|
|
2320
|
+
};
|
|
2321
|
+
/**
|
|
2322
|
+
* Fields computed by the pipeline (not authored in frontmatter).
|
|
2323
|
+
*
|
|
2324
|
+
* @example
|
|
2325
|
+
* ```ts
|
|
2326
|
+
* { slug: "hello", readingTime: 1, contentId: "hello", status: "published", wordCount: 42 }
|
|
2327
|
+
* ```
|
|
2328
|
+
*/
|
|
2329
|
+
type ComputedFields = {
|
|
2330
|
+
/** Article directory name. */slug: string; /** Reading time in minutes (ceiling, minimum 1). */
|
|
2331
|
+
readingTime: number; /** Stable content identifier (slug by default). */
|
|
2332
|
+
contentId: string; /** Derived publication status. */
|
|
2333
|
+
status: "published" | "draft"; /** Word count from the source body. */
|
|
2334
|
+
wordCount: number;
|
|
2335
|
+
};
|
|
2336
|
+
/**
|
|
2337
|
+
* A fully processed, render-ready article.
|
|
2338
|
+
*
|
|
2339
|
+
* @example
|
|
2340
|
+
* ```ts
|
|
2341
|
+
* { frontmatter, computed, html: "<p>…</p>", locale: "en", isFallback: false, url: "/en/hello/" }
|
|
2342
|
+
* ```
|
|
2343
|
+
*/
|
|
2344
|
+
type Article = {
|
|
2345
|
+
/** Parsed frontmatter. */frontmatter: Frontmatter; /** Pipeline-computed metadata. */
|
|
2346
|
+
computed: ComputedFields; /** Sanitized rendered HTML body. */
|
|
2347
|
+
html: string; /** Locale this Article instance represents (the requested locale, even on fallback). */
|
|
2348
|
+
locale: string; /** True when the default-locale file was used because the requested locale was missing. */
|
|
2349
|
+
isFallback: boolean; /** Canonical URL for this article in this locale. */
|
|
2350
|
+
url: string;
|
|
2351
|
+
};
|
|
2352
|
+
/**
|
|
2353
|
+
* Lightweight projection of Article for cards/lists.
|
|
2354
|
+
*
|
|
2355
|
+
* @example
|
|
2356
|
+
* ```ts
|
|
2357
|
+
* { contentId: "hello", status: "published", title: "Hello", date: "2026-01-15", description: "Intro", tags: [], readingTime: 1, url: "/en/hello/" }
|
|
2358
|
+
* ```
|
|
2359
|
+
*/
|
|
2360
|
+
type ArticleCard = {
|
|
2361
|
+
/** Stable content identifier. */contentId: string; /** Derived publication status. */
|
|
2362
|
+
status: "published" | "draft"; /** Article title. */
|
|
2363
|
+
title: string; /** ISO 8601 date string. */
|
|
2364
|
+
date: string; /** Short summary. */
|
|
2365
|
+
description: string; /** Topic tags. */
|
|
2366
|
+
tags: string[]; /** Reading time in minutes. */
|
|
2367
|
+
readingTime: number; /** Canonical URL for this article in this locale. */
|
|
2368
|
+
url: string;
|
|
2369
|
+
};
|
|
2370
|
+
/**
|
|
2371
|
+
* Notification-only events emitted by the content plugin.
|
|
2372
|
+
*
|
|
2373
|
+
* @example
|
|
2374
|
+
* ```ts
|
|
2375
|
+
* emit("content:ready", { locales: ["en"], articleCount: 3 });
|
|
2376
|
+
* ```
|
|
2377
|
+
*/
|
|
2378
|
+
type ContentEvents = {
|
|
2379
|
+
/** All articles loaded across locales. */"content:ready": {
|
|
2380
|
+
locales: readonly string[];
|
|
2381
|
+
articleCount: number;
|
|
2382
|
+
}; /** Article paths marked stale for dev rebuild. */
|
|
2383
|
+
"content:invalidated": {
|
|
2384
|
+
paths: readonly string[];
|
|
2385
|
+
};
|
|
2386
|
+
};
|
|
2387
|
+
/**
|
|
2388
|
+
* Kernel-free domain context handed to createContentApi by the wiring harness.
|
|
2389
|
+
* Carries ctx.state (mutable escape hatch), config, global, emit, and the
|
|
2390
|
+
* i18n-derived locale/url helpers — so api.ts stays free of createPlugin/ctx.
|
|
2391
|
+
*
|
|
2392
|
+
* @example
|
|
2393
|
+
* ```ts
|
|
2394
|
+
* const apiContext: ContentApiContext = { state, config, global, emit, locales, defaultLocale, articleToUrl };
|
|
2395
|
+
* ```
|
|
2396
|
+
*/
|
|
2397
|
+
type ContentApiContext = {
|
|
2398
|
+
/** Mutable plugin state (article cache + lazy processor). */state: State; /** Resolved plugin configuration. */
|
|
2399
|
+
config: Config; /** Global framework configuration (mode, etc.). */
|
|
2400
|
+
global: {
|
|
2401
|
+
mode: "production" | "development";
|
|
2402
|
+
}; /** Emit a registered content event. */
|
|
2403
|
+
emit: <K extends keyof ContentEvents>(event: K, payload: ContentEvents[K]) => void; /** Active locale codes from i18n. */
|
|
2404
|
+
locales: () => readonly string[]; /** Default locale code from i18n (fallback source). */
|
|
2405
|
+
defaultLocale: () => string; /** Build a canonical article URL for a locale + slug. */
|
|
2406
|
+
articleToUrl: (locale: string, slug: string) => string;
|
|
2407
|
+
};
|
|
2408
|
+
/**
|
|
2409
|
+
* Public API for the content plugin.
|
|
2410
|
+
*
|
|
2411
|
+
* @example
|
|
2412
|
+
* ```ts
|
|
2413
|
+
* const map = await app.content.loadAll();
|
|
2414
|
+
* ```
|
|
2415
|
+
*/
|
|
2416
|
+
type Api = {
|
|
2417
|
+
/**
|
|
2418
|
+
* Load every article across every active locale, returning a locale-keyed
|
|
2419
|
+
* map of date-descending Article arrays. Emits content:ready.
|
|
2420
|
+
*/
|
|
2421
|
+
loadAll(): Promise<Map<string, Article[]>>;
|
|
2422
|
+
/**
|
|
2423
|
+
* Resolve and render a single article for one locale, with locale fallback.
|
|
2424
|
+
*
|
|
2425
|
+
* @param slug - Article directory name.
|
|
2426
|
+
* @param locale - Requested locale code.
|
|
2427
|
+
*/
|
|
2428
|
+
load(slug: string, locale: string): Promise<Article>;
|
|
2429
|
+
/**
|
|
2430
|
+
* Render a raw Markdown string to HTML through the full pipeline.
|
|
2431
|
+
*
|
|
2432
|
+
* @param md - Raw Markdown source.
|
|
2433
|
+
*/
|
|
2434
|
+
renderMarkdown(md: string): Promise<string>;
|
|
2435
|
+
/**
|
|
2436
|
+
* Mark file paths stale for incremental dev rebuilds. Emits content:invalidated.
|
|
2437
|
+
*
|
|
2438
|
+
* @param paths - File paths to invalidate.
|
|
2439
|
+
*/
|
|
2440
|
+
invalidate(paths: readonly string[]): void;
|
|
2441
|
+
/**
|
|
2442
|
+
* Project a full Article to a lightweight ArticleCard for list/grid rendering.
|
|
2443
|
+
*
|
|
2444
|
+
* @param article - The source article.
|
|
2445
|
+
*/
|
|
2446
|
+
articleToCard(article: Article): ArticleCard;
|
|
2447
|
+
/**
|
|
2448
|
+
* The configured content source directory (e.g. `"./content"`). Lets the build copy each
|
|
2449
|
+
* article's co-located assets (`<contentDir>/<slug>/images/`) into the output so the absolute
|
|
2450
|
+
* image URLs the renderer emits resolve.
|
|
2451
|
+
*/
|
|
2452
|
+
contentDir(): string;
|
|
2453
|
+
};
|
|
2454
|
+
//#endregion
|
|
2455
|
+
//#region src/plugins/content/index.d.ts
|
|
2456
|
+
/**
|
|
2457
|
+
* Content plugin — Markdown pipeline: discovers files, parses frontmatter, renders
|
|
2458
|
+
* to sanitized HTML (rehype-sanitize unless `trustedContent`), and exposes a
|
|
2459
|
+
* locale-keyed Article model. Depends on i18n; emits `content:ready` and
|
|
2460
|
+
* `content:invalidated`.
|
|
2461
|
+
*
|
|
2462
|
+
* @example Point at a content directory and pick a Shiki theme
|
|
2463
|
+
* ```ts
|
|
2464
|
+
* const app = createApp({
|
|
2465
|
+
* pluginConfigs: {
|
|
2466
|
+
* content: {
|
|
2467
|
+
* contentDir: "./content",
|
|
2468
|
+
* shikiTheme: "github-dark",
|
|
2469
|
+
* defaultAuthor: "Ada Lovelace"
|
|
2470
|
+
* // trustedContent: true // ONLY for fully author-controlled Markdown — disables sanitize
|
|
2471
|
+
* }
|
|
2472
|
+
* }
|
|
1878
2473
|
* });
|
|
1879
2474
|
* ```
|
|
1880
2475
|
*/
|
|
1881
|
-
declare const contentPlugin: import("@moku-labs/core").PluginInstance<"content", Config
|
|
2476
|
+
declare const contentPlugin: import("@moku-labs/core").PluginInstance<"content", Config, State, Api, {
|
|
1882
2477
|
"content:ready": {
|
|
1883
2478
|
locales: readonly string[];
|
|
1884
2479
|
articleCount: number;
|
|
@@ -1887,7 +2482,7 @@ declare const contentPlugin: import("@moku-labs/core").PluginInstance<"content",
|
|
|
1887
2482
|
paths: readonly string[];
|
|
1888
2483
|
};
|
|
1889
2484
|
}> & Record<never, never>;
|
|
1890
|
-
declare namespace types_d_exports$
|
|
2485
|
+
declare namespace types_d_exports$3 {
|
|
1891
2486
|
export { DataConfig, DataEntry, DataProvider, DataState, DataWriteSummary };
|
|
1892
2487
|
}
|
|
1893
2488
|
/**
|
|
@@ -2033,185 +2628,6 @@ type DataProvider = {
|
|
|
2033
2628
|
* ```
|
|
2034
2629
|
*/
|
|
2035
2630
|
declare const dataPlugin: import("@moku-labs/core").PluginInstance<"data", DataConfig, DataState, DataProvider, {}> & Record<never, never>;
|
|
2036
|
-
declare namespace types_d_exports$3 {
|
|
2037
|
-
export { Api, Config, DeployErrorCode, DeployInitOptions, DeployResult, DeployRunOptions, InitResult, SpawnFunction, SpawnOptions, SpawnedProcess, State, WranglerErrorKind };
|
|
2038
|
-
}
|
|
2039
|
-
/**
|
|
2040
|
-
* @file deploy plugin — type definitions.
|
|
2041
|
-
*/
|
|
2042
|
-
/**
|
|
2043
|
-
* Options passed to the injected spawner — the subset of Bun.spawn's options the
|
|
2044
|
-
* plugin uses (piped stdout/stderr plus an env carrying the API token).
|
|
2045
|
-
*/
|
|
2046
|
-
interface SpawnOptions {
|
|
2047
|
-
/** Capture stdout as a readable stream. */
|
|
2048
|
-
readonly stdout: "pipe";
|
|
2049
|
-
/** Capture stderr as a readable stream. */
|
|
2050
|
-
readonly stderr: "pipe";
|
|
2051
|
-
/** Subprocess environment — the API token is injected here, never via argv. */
|
|
2052
|
-
readonly env?: Record<string, string | undefined>;
|
|
2053
|
-
}
|
|
2054
|
-
/**
|
|
2055
|
-
* The structural subprocess handle the plugin reads back: stdout/stderr streams
|
|
2056
|
-
* plus the exit-code promise. Streams are typed `unknown` and narrowed at the read
|
|
2057
|
-
* site so this carries no Bun namespace types.
|
|
2058
|
-
*/
|
|
2059
|
-
interface SpawnedProcess {
|
|
2060
|
-
/** Standard output stream (narrowed to a ReadableStream at the read site). */
|
|
2061
|
-
readonly stdout: unknown;
|
|
2062
|
-
/** Standard error stream (narrowed to a ReadableStream at the read site). */
|
|
2063
|
-
readonly stderr: unknown;
|
|
2064
|
-
/** Resolves with the subprocess exit code. */
|
|
2065
|
-
readonly exited: Promise<number>;
|
|
2066
|
-
}
|
|
2067
|
-
/**
|
|
2068
|
-
* The subset of Bun.spawn's signature the plugin relies on (argv array + options).
|
|
2069
|
-
* Declared structurally — with NO `import("bun")` namespace types — so it survives
|
|
2070
|
-
* `.d.ts` bundling intact and tests can supply a fake spawn without importing Bun.
|
|
2071
|
-
*/
|
|
2072
|
-
type SpawnFunction = (cmd: string[], options: SpawnOptions) => SpawnedProcess;
|
|
2073
|
-
/**
|
|
2074
|
-
* A deploy error `code` from the wrangler error taxonomy and preflight validators.
|
|
2075
|
-
*/
|
|
2076
|
-
type DeployErrorCode = "ERR_DEPLOY_NO_WRANGLER_CONFIG" | "ERR_DEPLOY_EMPTY_OUTDIR" | "ERR_DEPLOY_TOO_MANY_FILES" | "ERR_DEPLOY_FILE_TOO_LARGE" | "ERR_DEPLOY_PATH_TRAVERSAL" | "ERR_DEPLOY_INVALID_BRANCH" | "ERR_DEPLOY_NO_TOKEN" | "ERR_DEPLOY_PROJECT_NOT_FOUND" | "ERR_DEPLOY_AUTH_EXPIRED" | "ERR_DEPLOY_AUTH" | "ERR_DEPLOY_NETWORK" | "ERR_DEPLOY_WRANGLER_FAILED" | "ERR_DEPLOY_CONFIG";
|
|
2077
|
-
/**
|
|
2078
|
-
* The subset of wrangler error `code`s classifyWranglerError can produce from a
|
|
2079
|
-
* non-zero wrangler exit.
|
|
2080
|
-
*/
|
|
2081
|
-
type WranglerErrorKind = Extract<DeployErrorCode, "ERR_DEPLOY_PROJECT_NOT_FOUND" | "ERR_DEPLOY_AUTH_EXPIRED" | "ERR_DEPLOY_AUTH" | "ERR_DEPLOY_NETWORK" | "ERR_DEPLOY_WRANGLER_FAILED">;
|
|
2082
|
-
/**
|
|
2083
|
-
* Configuration for the deploy plugin.
|
|
2084
|
-
*/
|
|
2085
|
-
type Config = {
|
|
2086
|
-
/**
|
|
2087
|
-
* Deploy target. Only Cloudflare Pages is supported in this version.
|
|
2088
|
-
* Defaults to `cloudflare-pages`.
|
|
2089
|
-
*/
|
|
2090
|
-
target: "cloudflare-pages";
|
|
2091
|
-
/**
|
|
2092
|
-
* Directory (relative to project root) containing the built site to deploy.
|
|
2093
|
-
* Re-validated against cwd at run() time to block path traversal.
|
|
2094
|
-
* Defaults to `dist`.
|
|
2095
|
-
*/
|
|
2096
|
-
outDir: string;
|
|
2097
|
-
/**
|
|
2098
|
-
* Branch treated as the Cloudflare Pages production branch.
|
|
2099
|
-
* Defaults to `main`.
|
|
2100
|
-
*/
|
|
2101
|
-
productionBranch?: string;
|
|
2102
|
-
/**
|
|
2103
|
-
* Substrings exempt from entropy-gated secret scrubbing in logged output.
|
|
2104
|
-
* Defaults to `["CLOUDFLARE_ACCOUNT_ID"]`.
|
|
2105
|
-
*/
|
|
2106
|
-
scrubAllowlist: string[];
|
|
2107
|
-
/**
|
|
2108
|
-
* Cloudflare compatibility date written into generated wrangler.jsonc.
|
|
2109
|
-
* Defaults to `2024-01-01`.
|
|
2110
|
-
*/
|
|
2111
|
-
compatibilityDate?: string;
|
|
2112
|
-
/**
|
|
2113
|
-
* Whether init() also generates a GitHub Actions workflow.
|
|
2114
|
-
* Defaults to `false`.
|
|
2115
|
-
*/
|
|
2116
|
-
ci?: boolean;
|
|
2117
|
-
};
|
|
2118
|
-
/**
|
|
2119
|
-
* Result of a successful deploy.
|
|
2120
|
-
*/
|
|
2121
|
-
type DeployResult = {
|
|
2122
|
-
/** The public deployment URL (e.g. https://my-site.pages.dev). */url: string; /** Cloudflare deployment ID parsed from wrangler output. */
|
|
2123
|
-
deploymentId: string; /** The branch that was deployed. */
|
|
2124
|
-
branch: string; /** Wall-clock duration of the deploy in milliseconds. */
|
|
2125
|
-
durationMs: number;
|
|
2126
|
-
};
|
|
2127
|
-
/**
|
|
2128
|
-
* Runtime state for the deploy plugin. Created in createState() and accessed via
|
|
2129
|
-
* ctx.state. deploy declares no onStop because nothing here is a long-lived resource.
|
|
2130
|
-
*/
|
|
2131
|
-
type State = {
|
|
2132
|
-
/** Result of the most recent successful deploy, or null before the first run. */lastDeployment: DeployResult | null;
|
|
2133
|
-
/**
|
|
2134
|
-
* Injectable subprocess spawner. Defaults to Bun.spawn. Swapped for a mock in
|
|
2135
|
-
* unit tests so wrangler is never actually invoked. Never reassigned at runtime.
|
|
2136
|
-
*/
|
|
2137
|
-
spawn: SpawnFunction;
|
|
2138
|
-
};
|
|
2139
|
-
/**
|
|
2140
|
-
* Options for DeployApi.run.
|
|
2141
|
-
*/
|
|
2142
|
-
type DeployRunOptions = {
|
|
2143
|
-
/**
|
|
2144
|
-
* Branch to deploy. Defaults to config.productionBranch (or "main"). Must match
|
|
2145
|
-
* /^[a-zA-Z0-9/_.-]+$/ — otherwise rejected with ERR_DEPLOY_INVALID_BRANCH.
|
|
2146
|
-
*/
|
|
2147
|
-
branch?: string;
|
|
2148
|
-
/**
|
|
2149
|
-
* Whether to run the build before deploying. When false, deploys the existing outDir.
|
|
2150
|
-
* Defaults to `true`.
|
|
2151
|
-
*/
|
|
2152
|
-
build?: boolean;
|
|
2153
|
-
};
|
|
2154
|
-
/**
|
|
2155
|
-
* Options for DeployApi.init.
|
|
2156
|
-
*/
|
|
2157
|
-
type DeployInitOptions = {
|
|
2158
|
-
/** Also generate the GitHub Actions workflow. Defaults to config.ci. */ci?: boolean; /** Drift-only mode: report differences without writing any files. Defaults to `false`. */
|
|
2159
|
-
check?: boolean;
|
|
2160
|
-
};
|
|
2161
|
-
/**
|
|
2162
|
-
* Result of an init/scaffold operation.
|
|
2163
|
-
*/
|
|
2164
|
-
type InitResult = {
|
|
2165
|
-
/** Paths written this invocation. */written: string[]; /** Paths skipped because they already exist. */
|
|
2166
|
-
skipped: string[]; /** In check mode: paths whose on-disk content differs from what would be generated. */
|
|
2167
|
-
drifted: string[];
|
|
2168
|
-
};
|
|
2169
|
-
/**
|
|
2170
|
-
* Public API of the deploy plugin (returned from the api factory).
|
|
2171
|
-
*/
|
|
2172
|
-
type Api = {
|
|
2173
|
-
/**
|
|
2174
|
-
* Deploy the built outDir to Cloudflare Pages via the wrangler subprocess.
|
|
2175
|
-
* Runs preflight validators, re-validates the resolved outdir against cwd, guards
|
|
2176
|
-
* the branch argument, spawns wrangler (no shell), scrubs all subprocess output
|
|
2177
|
-
* before logging, records lastDeployment, and emits deploy:complete.
|
|
2178
|
-
*
|
|
2179
|
-
* @param options - Optional branch override and build toggle.
|
|
2180
|
-
* @returns The deploy result (url, deploymentId, branch, durationMs).
|
|
2181
|
-
* @throws {Error} With a `code` from the deploy error taxonomy on any failure.
|
|
2182
|
-
* @example
|
|
2183
|
-
* const result = await app.deploy.run();
|
|
2184
|
-
* console.log(result.url); // https://my-site.pages.dev
|
|
2185
|
-
* @example
|
|
2186
|
-
* await app.deploy.run({ branch: "preview/landing", build: false });
|
|
2187
|
-
*/
|
|
2188
|
-
run(options?: DeployRunOptions): Promise<DeployResult>;
|
|
2189
|
-
/**
|
|
2190
|
-
* Return the most recent successful deploy result, or null if none has occurred.
|
|
2191
|
-
* The returned object is read-only (a defensive snapshot).
|
|
2192
|
-
*
|
|
2193
|
-
* @returns The last DeployResult, or null.
|
|
2194
|
-
* @example
|
|
2195
|
-
* const last = app.deploy.getLastDeployment();
|
|
2196
|
-
* if (last) console.log(`Last deployed to ${last.url}`);
|
|
2197
|
-
*/
|
|
2198
|
-
getLastDeployment(): Readonly<DeployResult> | null;
|
|
2199
|
-
/**
|
|
2200
|
-
* Generate deploy scaffolding: wrangler.jsonc (slug from site.name() + outDir +
|
|
2201
|
-
* compatibilityDate) and, when ci is enabled, .github/workflows/deploy.yml. Never
|
|
2202
|
-
* overwrites an existing wrangler.jsonc. In check mode, reports drift instead of writing.
|
|
2203
|
-
*
|
|
2204
|
-
* @param options - Optional ci toggle and check (drift-only) mode.
|
|
2205
|
-
* @returns Which files were written, skipped, or would drift.
|
|
2206
|
-
* @example
|
|
2207
|
-
* const out = await app.deploy.init({ ci: true });
|
|
2208
|
-
* // out.written -> ["wrangler.jsonc", ".github/workflows/deploy.yml"]
|
|
2209
|
-
* @example
|
|
2210
|
-
* const drift = await app.deploy.init({ check: true });
|
|
2211
|
-
* if (drift.drifted.length) process.exit(1);
|
|
2212
|
-
*/
|
|
2213
|
-
init(options?: DeployInitOptions): Promise<InitResult>;
|
|
2214
|
-
};
|
|
2215
2631
|
//#endregion
|
|
2216
2632
|
//#region src/plugins/deploy/index.d.ts
|
|
2217
2633
|
/**
|
|
@@ -2239,7 +2655,7 @@ type Api = {
|
|
|
2239
2655
|
* });
|
|
2240
2656
|
* ```
|
|
2241
2657
|
*/
|
|
2242
|
-
declare const deployPlugin: import("@moku-labs/core").PluginInstance<"deploy", Config, State, Api, {
|
|
2658
|
+
declare const deployPlugin: import("@moku-labs/core").PluginInstance<"deploy", Config$2, State$2, Api$2, {
|
|
2243
2659
|
"deploy:complete": {
|
|
2244
2660
|
url: string;
|
|
2245
2661
|
deploymentId: string;
|
|
@@ -2346,7 +2762,7 @@ declare function buildArticleHead(articleMeta: ArticleMeta, canonicalUrl: string
|
|
|
2346
2762
|
* });
|
|
2347
2763
|
* ```
|
|
2348
2764
|
*/
|
|
2349
|
-
declare const headPlugin: import("@moku-labs/core").PluginInstance<"head", Config$
|
|
2765
|
+
declare const headPlugin: import("@moku-labs/core").PluginInstance<"head", Config$4, State$4, Api$4, {}> & {
|
|
2350
2766
|
meta: typeof meta;
|
|
2351
2767
|
og: typeof og;
|
|
2352
2768
|
twitter: typeof twitter;
|
|
@@ -2377,7 +2793,7 @@ declare const headPlugin: import("@moku-labs/core").PluginInstance<"head", Confi
|
|
|
2377
2793
|
* });
|
|
2378
2794
|
* ```
|
|
2379
2795
|
*/
|
|
2380
|
-
declare const i18nPlugin: import("@moku-labs/core").PluginInstance<"i18n", Config$
|
|
2796
|
+
declare const i18nPlugin: import("@moku-labs/core").PluginInstance<"i18n", Config$6, Record<string, never>, Api$6, {}> & Record<never, never>;
|
|
2381
2797
|
//#endregion
|
|
2382
2798
|
//#region src/plugins/log/index.d.ts
|
|
2383
2799
|
/**
|
|
@@ -2467,7 +2883,7 @@ declare const routerPlugin: import("@moku-labs/core").PluginInstance<"router", R
|
|
|
2467
2883
|
* });
|
|
2468
2884
|
* ```
|
|
2469
2885
|
*/
|
|
2470
|
-
declare const sitePlugin: import("@moku-labs/core").PluginInstance<"site", Config$
|
|
2886
|
+
declare const sitePlugin: import("@moku-labs/core").PluginInstance<"site", Config$7, Record<string, never>, Api$7, {}> & Record<never, never>;
|
|
2471
2887
|
//#endregion
|
|
2472
2888
|
//#region src/plugins/spa/components.d.ts
|
|
2473
2889
|
/**
|
|
@@ -2598,10 +3014,10 @@ declare function cloudflareBindings(): EnvProvider;
|
|
|
2598
3014
|
* await app.build.run();
|
|
2599
3015
|
* ```
|
|
2600
3016
|
*/
|
|
2601
|
-
declare const createApp: <const ExtraPlugins extends readonly import("@moku-labs/core").AnyPluginInstance[] = readonly []>(options?: import("@moku-labs/core").CreateAppOptions<Config$
|
|
3017
|
+
declare const createApp: <const ExtraPlugins extends readonly import("@moku-labs/core").AnyPluginInstance[] = readonly []>(options?: import("@moku-labs/core").CreateAppOptions<Config$8, Events, (import("@moku-labs/core").PluginInstance<"site", Config$7, Record<string, never>, Api$7, {}> & Record<never, never>) | (import("@moku-labs/core").PluginInstance<"i18n", Config$6, Record<string, never>, Api$6, {}> & Record<never, never>) | (import("@moku-labs/core").PluginInstance<"router", RouterConfig, RouterState, RouterApi, {}> & {
|
|
2602
3018
|
route: typeof route;
|
|
2603
3019
|
defineRoutes: typeof defineRoutes;
|
|
2604
|
-
}) | (import("@moku-labs/core").PluginInstance<"head", Config$
|
|
3020
|
+
}) | (import("@moku-labs/core").PluginInstance<"head", Config$4, State$4, Api$4, {}> & {
|
|
2605
3021
|
meta: typeof meta;
|
|
2606
3022
|
og: typeof og;
|
|
2607
3023
|
twitter: typeof twitter;
|
|
@@ -2626,10 +3042,10 @@ declare const createApp: <const ExtraPlugins extends readonly import("@moku-labs
|
|
|
2626
3042
|
name: string;
|
|
2627
3043
|
el: Element;
|
|
2628
3044
|
};
|
|
2629
|
-
}> & Record<never, never>) | ExtraPlugins[number], [...ExtraPlugins], import("@moku-labs/core").CoreApisFromTuple<[import("@moku-labs/core").CorePluginInstance<"log", LogConfig, LogState, LogApi>, import("@moku-labs/core").CorePluginInstance<"env", EnvConfig, EnvState, EnvApi>]>> | undefined) => import("@moku-labs/core").App<Config$
|
|
3045
|
+
}> & Record<never, never>) | ExtraPlugins[number], [...ExtraPlugins], import("@moku-labs/core").CoreApisFromTuple<[import("@moku-labs/core").CorePluginInstance<"log", LogConfig, LogState, LogApi>, import("@moku-labs/core").CorePluginInstance<"env", EnvConfig, EnvState, EnvApi>]>> | undefined) => import("@moku-labs/core").App<Config$8, Events, (import("@moku-labs/core").PluginInstance<"site", Config$7, Record<string, never>, Api$7, {}> & Record<never, never>) | (import("@moku-labs/core").PluginInstance<"i18n", Config$6, Record<string, never>, Api$6, {}> & Record<never, never>) | (import("@moku-labs/core").PluginInstance<"router", RouterConfig, RouterState, RouterApi, {}> & {
|
|
2630
3046
|
route: typeof route;
|
|
2631
3047
|
defineRoutes: typeof defineRoutes;
|
|
2632
|
-
}) | (import("@moku-labs/core").PluginInstance<"head", Config$
|
|
3048
|
+
}) | (import("@moku-labs/core").PluginInstance<"head", Config$4, State$4, Api$4, {}> & {
|
|
2633
3049
|
meta: typeof meta;
|
|
2634
3050
|
og: typeof og;
|
|
2635
3051
|
twitter: typeof twitter;
|
|
@@ -2670,6 +3086,6 @@ declare const createApp: <const ExtraPlugins extends readonly import("@moku-labs
|
|
|
2670
3086
|
* const app = createApp({ plugins: [analytics] });
|
|
2671
3087
|
* ```
|
|
2672
3088
|
*/
|
|
2673
|
-
declare const createPlugin: import("@moku-labs/core").BoundCreatePluginFunction<Config$
|
|
3089
|
+
declare const createPlugin: import("@moku-labs/core").BoundCreatePluginFunction<Config$8, Events, import("@moku-labs/core").CoreApisFromTuple<[import("@moku-labs/core").CorePluginInstance<"log", LogConfig, LogState, LogApi>, import("@moku-labs/core").CorePluginInstance<"env", EnvConfig, EnvState, EnvApi>]>>;
|
|
2674
3090
|
//#endregion
|
|
2675
|
-
export { types_d_exports as Build, types_d_exports$1 as
|
|
3091
|
+
export { types_d_exports as Build, types_d_exports$1 as Cli, types_d_exports$2 as Content, types_d_exports$3 as Data, types_d_exports$4 as Deploy, types_d_exports$5 as Env, types_d_exports$6 as Head, types_d_exports$7 as Log, types_d_exports$8 as Router, types_d_exports$9 as Spa, browserEnv, buildArticleHead, buildPlugin, canonical, cliPlugin, cloudflareBindings, contentPlugin, createApp, createComponent, createPlugin, dataPlugin, defineRoutes, deployPlugin, dotenv, envPlugin, feedLink, headPlugin, hreflang, i18nPlugin, jsonLd, logPlugin, meta, og, processEnv, route, routerPlugin, sitePlugin, spaPlugin, twitter };
|