Color mode

This page is part of Plugins in Depth and covers dependencies, plugin context, and lifecycle.

Dependencies, context, and lifecycle

3-1. Dependency / capability

ts
definePlugin({
  name: "consumer",
  provides: ["example.output"],
  requires: ["content.graph"],
  optional: ["example.optional"],
});
Field Meaning
provides capabilities this plugin offers
requires mandatory capabilities
optional capabilities used when present

The resolver places providers before consumers:

Diagram source
text
flowchart LR
    Provider["Provider<br/>provides: content.graph"]
    Consumer["Consumer<br/>requires: content.graph"]
 
    Provider --> Consumer

The following states are configuration errors:

  • a required capability is missing
  • a provider is duplicated
  • there is a dependency cycle

order is only a base ordering before dependency resolution. Unrelated plugins keep their input order as much as possible. Prefer the capability contract over raw order when dependencies exist.

3-2. validateOptions

TypeScript types do not fully guarantee runtime values after the config file executes. Plugins that need it provide validateOptions. A validator must have no side effects — no filesystem scanning, no builds, no cache writes, and no modification of external state. Return problems as structured issues so config validation can display them together.

text
Options
   ↓
validateOptions
   ↓
Structured Issues
   ↓
riebeckite check

3-3. Plugin context

ts
type PluginContext = {
  config?: ResolvedRiebeckiteConfig;
  contentIndex: Map<string, string>;
  diagnostics: Diagnostic[];
  cache: PluginCache;
  output: GeneratedOutputSink;
  logger: Logger;
  tracer: Tracer;
  contentSource?: ContentSource;
};

Depending on the hook, slug, markdown, content, manifest, entries, and location input are added. Prefer receiving framework services from the context over creating global singletons.

3-4. Lifecycle

setup, buildStart, onConfigResolved, content processing, and buildEnd run once per ContentManager. buildEnd receives the completed manifest after diagnostics have been collected and is the only terminal build hook. dispose frees acquired resources and runs in reverse resolved order. Named lifecycle and content hook failures identify the plugin, hook, and original cause. Other hook families follow resolved plugin order.

Diagram source
text
flowchart LR
    Setup["setup"]
    Start["buildStart"]
    Work["Build / Content Processing"]
    End["buildEnd"]
    Dispose["dispose"]
 
    Setup --> Start
    Start --> Work
    Work --> End
    End --> Dispose

3-5. Content pipeline stages

Diagram source
text
flowchart TD
    Config["Config Resolved"]
    Loaded["Content Loaded"]
    Location["Public Location Resolved"]
    Parsed["Post Parsed"]
    Processed["Post Processed"]
    Graph["Content Graph"]
    Manifest["Manifest Created"]
 
    Config --> Location
    Location --> Loaded
    Loaded --> Parsed
    Parsed --> Processed
    Processed --> Graph
    Graph --> Manifest
text
setup → buildStart → config resolved → public locations resolved
→ content loaded → Markdown/HTML pipeline → post parsed → post processed
→ content graph → manifest created → diagnostics → build end

The representative hooks are:

text
onConfigResolved
onContentLoaded
onPostParsed
onPostProcessed
onManifestCreated

Use only the hooks you actually need. Do not reconstruct later-stage information in earlier stages. For example, avoid rebuilding information that already exists in the Manifest inside onContentLoaded.

History

1 changesCollapseExpand
1 + ---
2 + title: Dependencies, context, and lifecycle
3 + sidebar:
4 + label: Dependencies, context, and lifecycle
5 + order: 10
6 + ---
7 +
8 + This page is part of [Plugins in Depth](../plugin-system.md) and covers dependencies, plugin context, and lifecycle.
9 +
10 + # Dependencies, context, and lifecycle
11 +
12 + ## 3-1. Dependency / capability
13 +
14 + ```ts
15 + definePlugin({
16 + name: "consumer",
17 + provides: ["example.output"],
18 + requires: ["content.graph"],
19 + optional: ["example.optional"],
20 + });
21 + ```
22 +
23 + | Field | Meaning |
24 + | --- | --- |
25 + | `provides` | capabilities this plugin offers |
26 + | `requires` | mandatory capabilities |
27 + | `optional` | capabilities used when present |
28 +
29 + The resolver places providers before consumers:
30 +
31 + ```mermaid
32 + flowchart LR
33 + Provider["Provider<br/>provides: content.graph"]
34 + Consumer["Consumer<br/>requires: content.graph"]
35 +
36 + Provider --> Consumer
37 + ```
38 +
39 + The following states are configuration errors:
40 +
41 + - a required capability is missing
42 + - a provider is duplicated
43 + - there is a dependency cycle
44 +
45 + `order` is only a base ordering before dependency resolution. Unrelated plugins keep their input order as much as possible. Prefer the capability contract over raw `order` when dependencies exist.
46 +
47 + ## 3-2. validateOptions
48 +
49 + TypeScript types do not fully guarantee runtime values after the config file executes. Plugins that need it provide `validateOptions`. A validator must **have no side effects** — no filesystem scanning, no builds, no cache writes, and no modification of external state. Return problems as structured issues so config validation can display them together.
50 +
51 + ```text
52 + Options
53 + ↓
54 + validateOptions
55 + ↓
56 + Structured Issues
57 + ↓
58 + riebeckite check
59 + ```
60 +
61 + ## 3-3. Plugin context
62 +
63 + ```ts
64 + type PluginContext = {
65 + config?: ResolvedRiebeckiteConfig;
66 + contentIndex: Map<string, string>;
67 + diagnostics: Diagnostic[];
68 + cache: PluginCache;
69 + output: GeneratedOutputSink;
70 + logger: Logger;
71 + tracer: Tracer;
72 + contentSource?: ContentSource;
73 + };
74 + ```
75 +
76 + Depending on the hook, `slug`, `markdown`, `content`, `manifest`, `entries`, and location input are added. Prefer receiving framework services from the context over creating global singletons.
77 +
78 + ## 3-4. Lifecycle
79 +
80 + `setup`, `buildStart`, `onConfigResolved`, content processing, and `buildEnd` run once per `ContentManager`. `buildEnd` receives the completed manifest after diagnostics have been collected and is the only terminal build hook. `dispose` frees acquired resources and runs in reverse resolved order. Named lifecycle and content hook failures identify the plugin, hook, and original cause. Other hook families follow resolved plugin order.
81 +
82 + ```mermaid
83 + flowchart LR
84 + Setup["setup"]
85 + Start["buildStart"]
86 + Work["Build / Content Processing"]
87 + End["buildEnd"]
88 + Dispose["dispose"]
89 +
90 + Setup --> Start
91 + Start --> Work
92 + Work --> End
93 + End --> Dispose
94 + ```
95 +
96 + ## 3-5. Content pipeline stages
97 +
98 + ```mermaid
99 + flowchart TD
100 + Config["Config Resolved"]
101 + Loaded["Content Loaded"]
102 + Location["Public Location Resolved"]
103 + Parsed["Post Parsed"]
104 + Processed["Post Processed"]
105 + Graph["Content Graph"]
106 + Manifest["Manifest Created"]
107 +
108 + Config --> Location
109 + Location --> Loaded
110 + Loaded --> Parsed
111 + Parsed --> Processed
112 + Processed --> Graph
113 + Graph --> Manifest
114 + ```
115 +
116 + ```text
117 + setup → buildStart → config resolved → public locations resolved
118 + → content loaded → Markdown/HTML pipeline → post parsed → post processed
119 + → content graph → manifest created → diagnostics → build end
120 + ```
121 +
122 + The representative hooks are:
123 +
124 + ```text
125 + onConfigResolved
126 + onContentLoaded
127 + onPostParsed
128 + onPostProcessed
129 + onManifestCreated
130 + ```
131 +
132 + Use only the hooks you actually need. Do not reconstruct later-stage information in earlier stages. For example, avoid rebuilding information that already exists in the Manifest inside `onContentLoaded`.
133 +