mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-05 23:37:25 +00:00
docs(chord): plugins import each other by name
This commit is contained in:
parent
112a8b46f3
commit
56cae78234
3 changed files with 16 additions and 13 deletions
|
|
@ -2063,6 +2063,13 @@ validation and copies the v2 kernel added around Delta.
|
|||
and TUI, decided point by point; the slice 10 components are its inside. Inputs from the owner: user management is
|
||||
part of it ("user management will also need to be a thing we support"), and app shapes without workers (server and
|
||||
clients only: "a chat app doesn't need workers").
|
||||
- **Plugins import each other by name (owner, 2026-10-31: "i like it"; changes 7c's cross-plugin rule):**
|
||||
`import { Notes } from "@app/notes/contract"` resolves to the discovered plugin named `@app/notes`, its file
|
||||
`contract.ts`, wherever its directory is (any root), copied into the importer's script as before (contracts and
|
||||
side-effect-free files only; they may import only host packages and files of their own plugin); a missing plugin is
|
||||
a build error naming it; relative paths into another plugin's directory are refused. Owner's notes for the app kit
|
||||
pass: third-party plugins need the imported plugins' sources or types for type checking (publishing each plugin to
|
||||
npm works but is unpleasant); plugins should be testable on their own, with their dependencies mocked.
|
||||
- **A plugin's npm dependencies are bundled; external only by opt-in (owner, 2026-10-29: "explicit opt in + (a)"):**
|
||||
a plugin's `dependencies` are installed into its own `node_modules` (`npm install --ignore-scripts`) and bundled into
|
||||
each facet that imports them (host packages, its `peerDependencies`, stay external and are passed in). On Node a
|
||||
|
|
|
|||
|
|
@ -490,7 +490,7 @@ A search plugin wants to search the notes. It **imports the contract** and asks
|
|||
|
||||
```ts
|
||||
// plugins/search/worker.ts
|
||||
import { Notes } from "../notes/contract.ts"; // copied into search's script: contracts only
|
||||
import { Notes } from "@app/notes/contract"; // another plugin, by its name: copied into search's script
|
||||
|
||||
host.serve(Search, ({ project }, principal, self) => {
|
||||
const notes = self.get(Notes, { project }); // a dependency: Search goes live once Notes is
|
||||
|
|
@ -499,12 +499,10 @@ host.serve(Search, ({ project }, principal, self) => {
|
|||
});
|
||||
```
|
||||
|
||||
:::review | Proposed: importing another plugin by name
|
||||
Today another plugin's file is imported by relative path, which works only when both plugins sit in the same root. A
|
||||
plugin in the user's root cannot reach one the app ships in `src/plugins` that way. Proposed (not decided): import by
|
||||
plugin name, `import { Notes } from "@app/notes/contract"`, resolved to the discovered plugin of that name wherever its
|
||||
directory is.
|
||||
:::
|
||||
|
||||
A plugin imports another plugin by its **name**, never by a path: `@app/notes/contract` is the file `contract.ts` of
|
||||
whichever discovered plugin is named `@app/notes`, in any root. The file is copied into the importer's script, so only
|
||||
contracts and other side-effect-free files belong there; a missing plugin is a build error naming it.
|
||||
|
||||
`self.get` in a factory declares a dependency: Chord makes `Search` live only once `Notes` is, and if the notes
|
||||
plugin is missing, `Search` waits with a clear reason ("waiting for notes: not served here") instead of failing.
|
||||
|
|
|
|||
|
|
@ -465,18 +465,16 @@ evaluates them with its own modules (a worker's from <code>workerMain</code>
|
|||
<section class="chapter" id="together"><header class="opener"><div class="numeral">VII</div><h2>Plugins Using Plugins</h2><p class="lede">Two ways one plugin uses another, and the one it may not.</p></header>
|
||||
<p class="dropcap">A search plugin wants to search the notes. It <strong>imports the contract</strong> and asks for the object:</p>
|
||||
<pre><code><span class="tk-c">// plugins/search/worker.ts</span>
|
||||
<span class="tk-k">import</span> { <span class="tk-t">Notes</span> } <span class="tk-k">from</span> <span class="tk-s">"../notes/contract.ts"</span>; <span class="tk-c">// copied into search's script: contracts only</span>
|
||||
<span class="tk-k">import</span> { <span class="tk-t">Notes</span> } <span class="tk-k">from</span> <span class="tk-s">"@app/notes/contract"</span>; <span class="tk-c">// another plugin, by its name: copied into search's script</span>
|
||||
|
||||
host.<span class="tk-f">serve</span>(<span class="tk-t">Search</span>, ({ project }, principal, self) => {
|
||||
<span class="tk-k">const</span> notes = self.<span class="tk-f">get</span>(<span class="tk-t">Notes</span>, { project }); <span class="tk-c">// a dependency: Search goes live once Notes is</span>
|
||||
<span class="tk-k">const</span> index = self.<span class="tk-f">derive</span>([notes.list], ([list]) => <span class="tk-f">buildIndex</span>(list.items));
|
||||
<span class="tk-k">return</span> { variant: <span class="tk-s">"main"</span>, members: { find: <span class="tk-k">async</span> ({ q }) => <span class="tk-f">lookup</span>(index.value, q) } };
|
||||
});</code></pre>
|
||||
<div class="note review"><b class="tag">Proposed: importing another plugin by name</b><p>Today another plugin's file is imported by relative path, which works only when both plugins sit in the same root. A
|
||||
plugin in the user's root cannot reach one the app ships in <code>src/plugins</code> that way. Proposed (not decided): import by
|
||||
plugin name, <code>import { Notes } from "@app/notes/contract"</code>, resolved to the discovered plugin of that name wherever its
|
||||
directory is.</p>
|
||||
</div>
|
||||
<p>A plugin imports another plugin by its <strong>name</strong>, never by a path: <code>@app/notes/contract</code> is the file <code>contract.ts</code> of
|
||||
whichever discovered plugin is named <code>@app/notes</code>, in any root. The file is copied into the importer's script, so only
|
||||
contracts and other side-effect-free files belong there; a missing plugin is a build error naming it.</p>
|
||||
<p><code>self.get</code> in a factory declares a dependency: Chord makes <code>Search</code> live only once <code>Notes</code> is, and if the notes
|
||||
plugin is missing, <code>Search</code> waits with a clear reason ("waiting for notes: not served here") instead of failing.</p>
|
||||
<p>The other way is a <strong>registry</strong>: an extension point one plugin defines and others contribute to. The app's core
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue