Expose syscalls in space script via globals (no more syscall calls)

pull/1013/head
Zef Hemel 2024-08-07 11:09:56 +02:00
parent 6b69449d05
commit e29352556b
3 changed files with 24 additions and 18 deletions

View File

@ -3,6 +3,7 @@ import type { ParseTree } from "../plug-api/lib/tree.ts";
import type { ScriptObject } from "../plugs/index/script.ts";
import type { AppCommand, CommandDef } from "$lib/command.ts";
import { Intl, Temporal, toTemporalInstant } from "@js-temporal/polyfill";
import * as syscalls from "@silverbulletmd/silverbullet/syscalls";
// @ts-ignore: Temporal polyfill
Date.prototype.toTemporalInstant = toTemporalInstant;
@ -95,15 +96,23 @@ export class ScriptEnvironment {
// Internal API
evalScript(script: string, system: System<any>) {
try {
const syscallArgs = [];
const syscallValues = [];
for (const [tl, value] of Object.entries(syscalls)) {
syscallArgs.push(tl);
syscallValues.push(value);
}
const fn = Function(
"silverbullet",
"syscall",
...syscallArgs,
script,
);
fn.call(
{},
this,
(name: string, ...args: any[]) => system.syscall({}, name, args),
...syscallValues,
);
} catch (e: any) {
throw new Error(
@ -113,6 +122,10 @@ export class ScriptEnvironment {
}
async loadFromSystem(system: System<any>) {
// Install global syscall function on globalThis
(globalThis as any).syscall = (name: string, ...args: any[]) =>
system.syscall({}, name, args);
if (!system.loadedPlugs.has("index")) {
console.warn("Index plug not found, skipping loading space scripts");
return;

View File

@ -11,4 +11,7 @@ if (typeof self === "undefined") {
};
}
export const syscall = (globalThis as any).syscall;
// Late binding syscall
export function syscall(name: string, ...args: any[]) {
return (globalThis as any).syscall(name, ...args);
}

View File

@ -36,7 +36,7 @@ Depending on where code is run (client or server), a slightly different JavaScri
* `silverbullet.registerCommand(def, callback)`: registers a custom command (see [[#Custom commands]]).
* `silverbullet.registerEventListener`: registers an event listener (see [[#Custom event listeners]]).
* `silverbullet.registerAttributeExtractor(def, callback)`: registers a custom attribute extractor.
* `syscall(name, args...)`: invoke a syscall (see [[#Syscalls]]).
* Various SilverBullet syscalls, see [[#Syscalls]]
Many standard JavaScript APIs are available, such as:
@ -59,7 +59,7 @@ Even though a [[Functions#readPage(name)]] function already exist, you could imp
```space-script
silverbullet.registerFunction({name: "myReadPage"}, async (name) => {
const pageContent = await syscall("space.readPage", name);
const pageContent = await space.readPage(name);
return pageContent;
})
```
@ -79,7 +79,7 @@ Here is an example of defining a custom command using space script:
```space-script
silverbullet.registerCommand({name: "My First Command"}, async () => {
await syscall("editor.flashNotification", "Hello there!");
await editor.flashNotification("Hello there!");
});
```
@ -123,7 +123,7 @@ silverbullet.registerEventListener({name: "task:stateChange"}, async (event) =>
const {from, to, newState} = event.data;
if(newState !== " ") {
// Now dispatch an editor change to add the completion date at the end of the task
await syscall("editor.dispatch", {
await editor.dispatch({
changes: {
from: to, // insert at the end of the task
insert: " ✅ " + Temporal.Now.plainDateISO().toString(),
@ -204,7 +204,7 @@ Note that indexing happens on every page save. You have to run {[Space: Reindex]
## Example
Lets say you want to use the syntax `✅ 2024-02-27` in a task to signify when that task was completed and strip it from the task name. Heres an example:
* [x] Ive done this ✅ 2024-02-27
* [x] Ive done this ✅ 2024-08-07
The following attribute extractor will accomplish this:
@ -236,16 +236,6 @@ Result:
# Syscalls
The primary way to interact with the SilverBullet environment is using “syscalls”. Syscalls expose SilverBullet functionality largely available both on the client and server in a safe way.
In your space script, a syscall is invoked via `syscall(name, arg1, arg2)` and usually returns a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) with the result.
In your space script, all syscalls are exposed via the global environment, and all return a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) with the result.
Here are all available syscalls:
```template
{{#each @module in {syscall select replace(name, /\.\w+$/, "") as name}}}
## {{@module.name}}
{{#each {syscall where @module.name = replace(name, /\.\w+$/, "")}}}
* `{{name}}`
{{/each}}
{{/each}}
```
[A full list of syscall are documented here](https://jsr.io/@silverbulletmd/silverbullet/doc/syscalls/~)