v0.8.5: Extension composability — slots, contributes, lib.require relaxation
All checks were successful
CI/CD / detect-changes (pull_request) Successful in 5s
CI/CD / test-runners (pull_request) Has been skipped
CI/CD / e2e-smoke (pull_request) Has been skipped
CI/CD / test-frontend (pull_request) Successful in 6s
CI/CD / test-go-pg (pull_request) Successful in 2m42s
CI/CD / test-sqlite (pull_request) Successful in 2m58s
CI/CD / build-and-deploy (pull_request) Successful in 1m33s
All checks were successful
CI/CD / detect-changes (pull_request) Successful in 5s
CI/CD / test-runners (pull_request) Has been skipped
CI/CD / e2e-smoke (pull_request) Has been skipped
CI/CD / test-frontend (pull_request) Successful in 6s
CI/CD / test-go-pg (pull_request) Successful in 2m42s
CI/CD / test-sqlite (pull_request) Successful in 2m58s
CI/CD / build-and-deploy (pull_request) Successful in 1m33s
Manifest declarations for slots (host surfaces declare injection points) and contributes (extensions declare UI contributions). lib.require() relaxed from library-only to any package with exports. Admin slots aggregation endpoint. SDK renderAll() helper. 7 new tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -68,10 +68,66 @@ Only `manifest.json` is required. All other directories are optional and include
|
||||
| `db_tables` | Table definitions with columns and indexes |
|
||||
| `settings` | User-configurable settings with type, label, description, default |
|
||||
| `hooks` | Event bus subscription patterns |
|
||||
| `exports` | Functions exported by library packages |
|
||||
| `exports` | Functions exported for cross-package calls via `lib.require()` |
|
||||
| `depends` | Array of package IDs this package depends on |
|
||||
| `slots` | Named UI injection points (host surfaces declare these) |
|
||||
| `contributes` | Slot contributions this package injects into other surfaces |
|
||||
| `capabilities` | Environment requirements: `{"required": [...], "optional": [...]}` |
|
||||
| `schema_version` | Integer for additive schema migrations |
|
||||
|
||||
## Composability: Slots and Contributions
|
||||
|
||||
Packages compose with each other through named UI injection points (**slots**) and **contributions**.
|
||||
|
||||
### Declaring Slots (Host Surfaces)
|
||||
|
||||
Surfaces declare slots where other extensions can inject UI:
|
||||
|
||||
```json
|
||||
{
|
||||
"slots": {
|
||||
"toolbar-actions": {
|
||||
"description": "Toolbar action buttons",
|
||||
"context": {
|
||||
"noteId": "string — current note ID",
|
||||
"getContent": "function — returns note body text"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Slot names are namespaced at runtime as `{package-id}:{slot-name}` (e.g., `notes:toolbar-actions`). The `context` field documents what data the slot provides — it is not enforced at runtime.
|
||||
|
||||
### Contributing to Slots
|
||||
|
||||
Extensions declare which slots they inject into:
|
||||
|
||||
```json
|
||||
{
|
||||
"contributes": {
|
||||
"notes:toolbar-actions": {
|
||||
"label": "Dictate",
|
||||
"icon": "🎤",
|
||||
"description": "Voice-to-text dictation"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Contributing extensions can be installed before or after their host surface — the coupling is soft. The admin can view all slots and their contributors at `GET /api/v1/admin/slots`.
|
||||
|
||||
### Cross-Package Function Calls
|
||||
|
||||
Any package that declares `exports` can be called via `lib.require()`, not just library-type packages. The caller must declare the target in its `depends` array:
|
||||
|
||||
```json
|
||||
{
|
||||
"depends": ["image-gen"],
|
||||
"permissions": ["api.http"]
|
||||
}
|
||||
```
|
||||
|
||||
## Package Lifecycle
|
||||
|
||||
1. **Install**: Upload a `.pkg` file via Admin > Packages or `POST /api/v1/admin/packages/install`. The kernel extracts the archive, creates database tables, and registers routes.
|
||||
|
||||
Reference in New Issue
Block a user