Services
Using built-in services
List the services you use and the scopes you need. Sensitive scopes need a justification, keyed by the permission behind them.
"uses": { "monster.notch.timer/timer@1": ["read", "control"] },
"justifications": { "timer:control": "Starts a focus session for the picked task." }
import { notch } from "@notch-monster/plugin-sdk";
import { SERVICES } from "@notch-monster/plugin-sdk/protocol";
const timer = notch.service(SERVICES.timer);
if (await timer.available()) await timer.start({ minutes: 25 });
timer.on("changed", async () => render(await timer.get()));
| Service | read |
write / control |
|---|---|---|
SERVICES.timer |
get() |
start({ minutes?, mode?, task? }), pause(), resume(), reset(), skip(), extend({ minutes }) |
SERVICES.tasks |
list({ day? }), get({ id }) |
add({ title, day? }), complete({ id }), setCurrent({ id }) |
SERVICES.notes |
current(), pages() |
append({ text }), newPage({ text? }) |
SERVICES.media |
get() |
control({ action }) |
Each built-in service raises a changed event.
Providing a service
Any plugin can offer services. Declare them in provides, keyed
<name>@<major>. Other plugins reach them as <your id>/<name>@<major>.
"provides": {
"reading-list@1": {
"scopes": {
"read": { "text": "See your reading list" },
"write": { "text": "Add to your reading list", "sensitive": true }
},
"methods": { "list": "read", "add": "write" },
"events": { "changed": "read" }
}
}
The app runs your service frame: your entry page loaded with
?view=service, hidden. It starts when someone calls and stops a minute
after the last call. Register handlers before ready():
if (new URLSearchParams(location.search).get("view") === "service") {
notch.provide("reading-list@1", {
list: async () => (await notch.storage.plugin.get("items")) ?? [],
add: async ({ title }, caller) => {
// caller: { id, name } of the plugin asking
await notch.emit("reading-list@1", "changed", {});
return { ok: true };
},
});
}
await notch.ready();
A handler’s return value (or thrown error) is the caller’s answer. Each
call has 15 seconds. Consumers list your service in uses the same way as
a built-in one: "uses": { "com.example.reader/reading-list@1": ["read"] }.
Limits: 8 services per plugin; 8 scopes, 32 methods and 16 events per service; scope text up to 80 characters. For a breaking change, bump the major version and keep the old one for a while.