Rewrote some navigation stuff based on new parser
This commit is contained in:
parent
16bf0d866d
commit
07453d638b
@ -3,13 +3,13 @@ import {MarkdownTree, nodeAtPos, parse, render} from "../tree";
|
|||||||
|
|
||||||
export function markdownSyscalls(): SysCallMapping {
|
export function markdownSyscalls(): SysCallMapping {
|
||||||
return {
|
return {
|
||||||
parse(ctx, text: string): MarkdownTree {
|
"markdown.parse": (ctx, text: string): MarkdownTree => {
|
||||||
return parse(text);
|
return parse(text);
|
||||||
},
|
},
|
||||||
nodeAtPos(ctx, mdTree: MarkdownTree, pos: number): MarkdownTree | null {
|
"markdown.nodeAtPos": (ctx, mdTree: MarkdownTree, pos: number): MarkdownTree | null => {
|
||||||
return nodeAtPos(mdTree, pos);
|
return nodeAtPos(mdTree, pos);
|
||||||
},
|
},
|
||||||
render(ctx, mdTree: MarkdownTree): string {
|
"markdown.render": (ctx, mdTree: MarkdownTree): string => {
|
||||||
return render(mdTree);
|
return render(mdTree);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -8,7 +8,7 @@ export async function parse(text: string): Promise<MarkdownTree> {
|
|||||||
export async function nodeAtPos(
|
export async function nodeAtPos(
|
||||||
mdTree: MarkdownTree,
|
mdTree: MarkdownTree,
|
||||||
pos: number
|
pos: number
|
||||||
): Promise<any | null> {
|
): Promise<MarkdownTree | null> {
|
||||||
return syscall("markdown.nodeAtPos", mdTree, pos);
|
return syscall("markdown.nodeAtPos", mdTree, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,11 +10,7 @@ import {System} from "../system";
|
|||||||
import {EndpointHook, EndpointHookT} from "../hooks/endpoint";
|
import {EndpointHook, EndpointHookT} from "../hooks/endpoint";
|
||||||
import {safeRun} from "../util";
|
import {safeRun} from "../util";
|
||||||
import knex from "knex";
|
import knex from "knex";
|
||||||
import {
|
import {ensureTable, storeSyscalls} from "../syscalls/store.knex_node";
|
||||||
ensureTable,
|
|
||||||
storeReadSyscalls,
|
|
||||||
storeWriteSyscalls,
|
|
||||||
} from "../syscalls/store.knex_node";
|
|
||||||
import {fetchSyscalls} from "../syscalls/fetch.node";
|
import {fetchSyscalls} from "../syscalls/fetch.node";
|
||||||
import {EventHook, EventHookT} from "../hooks/event";
|
import {EventHook, EventHookT} from "../hooks/event";
|
||||||
import {eventSyscalls} from "../syscalls/event";
|
import {eventSyscalls} from "../syscalls/event";
|
||||||
@ -55,16 +51,11 @@ safeRun(async () => {
|
|||||||
system.addHook(new NodeCronHook());
|
system.addHook(new NodeCronHook());
|
||||||
let eventHook = new EventHook();
|
let eventHook = new EventHook();
|
||||||
system.addHook(eventHook);
|
system.addHook(eventHook);
|
||||||
system.registerSyscalls("event", [], eventSyscalls(eventHook));
|
system.registerSyscalls([], eventSyscalls(eventHook));
|
||||||
system.addHook(new EndpointHook(app, ""));
|
system.addHook(new EndpointHook(app, ""));
|
||||||
system.registerSyscalls("shell", [], shellSyscalls("."));
|
system.registerSyscalls([], shellSyscalls("."));
|
||||||
system.registerSyscalls("fetch", [], fetchSyscalls());
|
system.registerSyscalls([], fetchSyscalls());
|
||||||
system.registerSyscalls(
|
system.registerSyscalls([], storeSyscalls(db, "item"));
|
||||||
"store",
|
|
||||||
[],
|
|
||||||
storeWriteSyscalls(db, "item"),
|
|
||||||
storeReadSyscalls(db, "item")
|
|
||||||
);
|
|
||||||
app.listen(args.port, () => {
|
app.listen(args.port, () => {
|
||||||
console.log(`Plugbox server listening on port ${args.port}`);
|
console.log(`Plugbox server listening on port ${args.port}`);
|
||||||
});
|
});
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { createSandbox } from "./environments/node_sandbox";
|
import {createSandbox} from "./environments/node_sandbox";
|
||||||
import { expect, test } from "@jest/globals";
|
import {expect, test} from "@jest/globals";
|
||||||
import { System } from "./system";
|
import {System} from "./system";
|
||||||
|
|
||||||
test("Run a Node sandbox", async () => {
|
test("Run a Node sandbox", async () => {
|
||||||
let system = new System("server");
|
let system = new System("server");
|
||||||
system.registerSyscalls("", [], {
|
system.registerSyscalls([], {
|
||||||
addNumbers: (ctx, a, b) => {
|
addNumbers: (ctx, a, b) => {
|
||||||
return a + b;
|
return a + b;
|
||||||
},
|
},
|
||||||
@ -12,12 +12,12 @@ test("Run a Node sandbox", async () => {
|
|||||||
throw new Error("#fail");
|
throw new Error("#fail");
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
system.registerSyscalls("", ["restricted"], {
|
system.registerSyscalls(["restricted"], {
|
||||||
restrictedSyscall: () => {
|
restrictedSyscall: () => {
|
||||||
return "restricted";
|
return "restricted";
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
system.registerSyscalls("", ["dangerous"], {
|
system.registerSyscalls(["dangerous"], {
|
||||||
dangerousSyscall: () => {
|
dangerousSyscall: () => {
|
||||||
return "yay";
|
return "yay";
|
||||||
},
|
},
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { SysCallMapping } from "../system";
|
import {SysCallMapping} from "../system";
|
||||||
import { EventHook } from "../hooks/event";
|
import {EventHook} from "../hooks/event";
|
||||||
|
|
||||||
export function eventSyscalls(eventHook: EventHook): SysCallMapping {
|
export function eventSyscalls(eventHook: EventHook): SysCallMapping {
|
||||||
return {
|
return {
|
||||||
async dispatch(ctx, eventName: string, data: any) {
|
"event.dispatch": async(ctx, eventName: string, data: any) => {
|
||||||
return eventHook.dispatchEvent(eventName, data);
|
return eventHook.dispatchEvent(eventName, data);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import fetch, { RequestInfo, RequestInit } from "node-fetch";
|
import fetch, {RequestInfo, RequestInit} from "node-fetch";
|
||||||
import { SysCallMapping } from "../system";
|
import {SysCallMapping} from "../system";
|
||||||
|
|
||||||
export function fetchSyscalls(): SysCallMapping {
|
export function fetchSyscalls(): SysCallMapping {
|
||||||
return {
|
return {
|
||||||
async json(ctx, url: RequestInfo, init: RequestInit) {
|
"fetch.json": async (ctx, url: RequestInfo, init: RequestInit) => {
|
||||||
let resp = await fetch(url, init);
|
let resp = await fetch(url, init);
|
||||||
return resp.json();
|
return resp.json();
|
||||||
},
|
},
|
||||||
async text(ctx, url: RequestInfo, init: RequestInit) {
|
"fetch.text": async(ctx, url: RequestInfo, init: RequestInit) => {
|
||||||
let resp = await fetch(url, init);
|
let resp = await fetch(url, init);
|
||||||
return resp.text();
|
return resp.text();
|
||||||
},
|
},
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { promisify } from "util";
|
import {promisify} from "util";
|
||||||
import { execFile } from "child_process";
|
import {execFile} from "child_process";
|
||||||
import type { SysCallMapping } from "../system";
|
import type {SysCallMapping} from "../system";
|
||||||
|
|
||||||
const execFilePromise = promisify(execFile);
|
const execFilePromise = promisify(execFile);
|
||||||
|
|
||||||
export default function (cwd: string): SysCallMapping {
|
export default function (cwd: string): SysCallMapping {
|
||||||
return {
|
return {
|
||||||
run: async (
|
"shell.run": async (
|
||||||
ctx,
|
ctx,
|
||||||
cmd: string,
|
cmd: string,
|
||||||
args: string[]
|
args: string[]
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import { createSandbox } from "../environments/node_sandbox";
|
import {createSandbox} from "../environments/node_sandbox";
|
||||||
import { expect, test } from "@jest/globals";
|
import {expect, test} from "@jest/globals";
|
||||||
import { System } from "../system";
|
import {System} from "../system";
|
||||||
import { storeSyscalls } from "./store.dexie_browser";
|
import {storeSyscalls} from "./store.dexie_browser";
|
||||||
|
|
||||||
// For testing in node.js
|
// For testing in node.js
|
||||||
require("fake-indexeddb/auto");
|
require("fake-indexeddb/auto");
|
||||||
|
|
||||||
test("Test store", async () => {
|
test("Test store", async () => {
|
||||||
let system = new System("server");
|
let system = new System("server");
|
||||||
system.registerSyscalls("store", [], storeSyscalls("test", "test"));
|
system.registerSyscalls([], storeSyscalls("test", "test"));
|
||||||
let plug = await system.load(
|
let plug = await system.load(
|
||||||
"test",
|
"test",
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import Dexie from "dexie";
|
import Dexie from "dexie";
|
||||||
import { SysCallMapping } from "../system";
|
import {SysCallMapping} from "../system";
|
||||||
|
|
||||||
export type KV = {
|
export type KV = {
|
||||||
key: string;
|
key: string;
|
||||||
@ -17,26 +17,26 @@ export function storeSyscalls(
|
|||||||
const items = db.table(tableName);
|
const items = db.table(tableName);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
async delete(ctx, key: string) {
|
"store.delete": async (ctx, key: string) => {
|
||||||
await items.delete(key);
|
await items.delete(key);
|
||||||
},
|
},
|
||||||
|
|
||||||
async deletePrefix(ctx, prefix: string) {
|
"store.deletePrefix": async (ctx, prefix: string) => {
|
||||||
await items.where("key").startsWith(prefix).delete();
|
await items.where("key").startsWith(prefix).delete();
|
||||||
},
|
},
|
||||||
|
|
||||||
async deleteAll() {
|
"store.deleteAll": async () => {
|
||||||
await items.clear();
|
await items.clear();
|
||||||
},
|
},
|
||||||
|
|
||||||
async set(ctx, key: string, value: any) {
|
"store.set": async (ctx, key: string, value: any) => {
|
||||||
await items.put({
|
await items.put({
|
||||||
key,
|
key,
|
||||||
value,
|
value,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
async batchSet(ctx, kvs: KV[]) {
|
"store.batchSet": async (ctx, kvs: KV[]) => {
|
||||||
await items.bulkPut(
|
await items.bulkPut(
|
||||||
kvs.map(({ key, value }) => ({
|
kvs.map(({ key, value }) => ({
|
||||||
key,
|
key,
|
||||||
@ -45,17 +45,17 @@ export function storeSyscalls(
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
async get(ctx, key: string): Promise<any | null> {
|
"store.get": async (ctx, key: string): Promise<any | null> => {
|
||||||
let result = await items.get({
|
let result = await items.get({
|
||||||
key,
|
key,
|
||||||
});
|
});
|
||||||
return result ? result.value : null;
|
return result ? result.value : null;
|
||||||
},
|
},
|
||||||
|
|
||||||
async queryPrefix(
|
"store.queryPrefix": async (
|
||||||
ctx,
|
ctx,
|
||||||
keyPrefix: string
|
keyPrefix: string
|
||||||
): Promise<{ key: string; value: any }[]> {
|
): Promise<{ key: string; value: any }[]> => {
|
||||||
let results = await items.where("key").startsWith(keyPrefix).toArray();
|
let results = await items.where("key").startsWith(keyPrefix).toArray();
|
||||||
return results.map((result) => ({
|
return results.map((result) => ({
|
||||||
key: result.key,
|
key: result.key,
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
import { createSandbox } from "../environments/node_sandbox";
|
import {createSandbox} from "../environments/node_sandbox";
|
||||||
import { expect, test } from "@jest/globals";
|
import {expect, test} from "@jest/globals";
|
||||||
import { System } from "../system";
|
import {System} from "../system";
|
||||||
import {
|
import {ensureTable, storeSyscalls} from "./store.knex_node";
|
||||||
ensureTable,
|
|
||||||
storeReadSyscalls,
|
|
||||||
storeWriteSyscalls,
|
|
||||||
} from "./store.knex_node";
|
|
||||||
import knex from "knex";
|
import knex from "knex";
|
||||||
import fs from "fs/promises";
|
import fs from "fs/promises";
|
||||||
|
|
||||||
@ -19,12 +15,7 @@ test("Test store", async () => {
|
|||||||
});
|
});
|
||||||
await ensureTable(db, "test_table");
|
await ensureTable(db, "test_table");
|
||||||
let system = new System("server");
|
let system = new System("server");
|
||||||
system.registerSyscalls(
|
system.registerSyscalls([], storeSyscalls(db, "test_table"));
|
||||||
"store",
|
|
||||||
[],
|
|
||||||
storeWriteSyscalls(db, "test_table"),
|
|
||||||
storeReadSyscalls(db, "test_table")
|
|
||||||
);
|
|
||||||
let plug = await system.load(
|
let plug = await system.load(
|
||||||
"test",
|
"test",
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Knex } from "knex";
|
import {Knex} from "knex";
|
||||||
import { SysCallMapping } from "../system";
|
import {SysCallMapping} from "../system";
|
||||||
|
|
||||||
type Item = {
|
type Item = {
|
||||||
page: string;
|
page: string;
|
||||||
@ -23,21 +23,21 @@ export async function ensureTable(db: Knex<any, unknown>, tableName: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function storeWriteSyscalls(
|
export function storeSyscalls(
|
||||||
db: Knex<any, unknown>,
|
db: Knex<any, unknown>,
|
||||||
tableName: string
|
tableName: string
|
||||||
): SysCallMapping {
|
): SysCallMapping {
|
||||||
const apiObj: SysCallMapping = {
|
const apiObj: SysCallMapping = {
|
||||||
delete: async (ctx, key: string) => {
|
"store.delete": async (ctx, key: string) => {
|
||||||
await db<Item>(tableName).where({ key }).del();
|
await db<Item>(tableName).where({ key }).del();
|
||||||
},
|
},
|
||||||
deletePrefix: async (ctx, prefix: string) => {
|
"store.deletePrefix": async (ctx, prefix: string) => {
|
||||||
return db<Item>(tableName).andWhereLike("key", `${prefix}%`).del();
|
return db<Item>(tableName).andWhereLike("key", `${prefix}%`).del();
|
||||||
},
|
},
|
||||||
deleteAll: async (ctx) => {
|
"store.deleteAll": async (ctx) => {
|
||||||
await db<Item>(tableName).del();
|
await db<Item>(tableName).del();
|
||||||
},
|
},
|
||||||
set: async (ctx, key: string, value: any) => {
|
"store.set": async (ctx, key: string, value: any) => {
|
||||||
let changed = await db<Item>(tableName)
|
let changed = await db<Item>(tableName)
|
||||||
.where({ key })
|
.where({ key })
|
||||||
.update("value", JSON.stringify(value));
|
.update("value", JSON.stringify(value));
|
||||||
@ -49,26 +49,17 @@ export function storeWriteSyscalls(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
// TODO: Optimize
|
// TODO: Optimize
|
||||||
batchSet: async (ctx, kvs: KV[]) => {
|
"store.batchSet": async (ctx, kvs: KV[]) => {
|
||||||
for (let { key, value } of kvs) {
|
for (let { key, value } of kvs) {
|
||||||
await apiObj.set(ctx, key, value);
|
await apiObj["store.set"](ctx, key, value);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
batchDelete: async (ctx, keys: string[]) => {
|
"store.batchDelete": async (ctx, keys: string[]) => {
|
||||||
for (let key of keys) {
|
for (let key of keys) {
|
||||||
await apiObj.delete(ctx, key);
|
await apiObj["store.delete"](ctx, key);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
"store.get": async (ctx, key: string): Promise<any | null> => {
|
||||||
return apiObj;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function storeReadSyscalls(
|
|
||||||
db: Knex<any, unknown>,
|
|
||||||
tableName: string
|
|
||||||
): SysCallMapping {
|
|
||||||
return {
|
|
||||||
get: async (ctx, key: string): Promise<any | null> => {
|
|
||||||
let result = await db<Item>(tableName).where({ key }).select("value");
|
let result = await db<Item>(tableName).where({ key }).select("value");
|
||||||
if (result.length) {
|
if (result.length) {
|
||||||
return JSON.parse(result[0].value);
|
return JSON.parse(result[0].value);
|
||||||
@ -76,7 +67,7 @@ export function storeReadSyscalls(
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
queryPrefix: async (ctx, prefix: string) => {
|
"store.queryPrefix": async (ctx, prefix: string) => {
|
||||||
return (
|
return (
|
||||||
await db<Item>(tableName)
|
await db<Item>(tableName)
|
||||||
.andWhereLike("key", `${prefix}%`)
|
.andWhereLike("key", `${prefix}%`)
|
||||||
@ -87,4 +78,5 @@ export function storeReadSyscalls(
|
|||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
return apiObj;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Hook, Manifest, RuntimeEnvironment } from "./types";
|
import {Hook, Manifest, RuntimeEnvironment} from "./types";
|
||||||
import { EventEmitter } from "../common/event";
|
import {EventEmitter} from "../common/event";
|
||||||
import { SandboxFactory } from "./sandbox";
|
import {SandboxFactory} from "./sandbox";
|
||||||
import { Plug } from "./plug";
|
import {Plug} from "./plug";
|
||||||
|
|
||||||
export interface SysCallMapping {
|
export interface SysCallMapping {
|
||||||
[key: string]: (ctx: SyscallContext, ...args: any) => Promise<any> | any;
|
[key: string]: (ctx: SyscallContext, ...args: any) => Promise<any> | any;
|
||||||
@ -29,31 +29,32 @@ type Syscall = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export class System<HookT> extends EventEmitter<SystemEvents<HookT>> {
|
export class System<HookT> extends EventEmitter<SystemEvents<HookT>> {
|
||||||
|
readonly runtimeEnv: RuntimeEnvironment;
|
||||||
protected plugs = new Map<string, Plug<HookT>>();
|
protected plugs = new Map<string, Plug<HookT>>();
|
||||||
protected registeredSyscalls = new Map<string, Syscall>();
|
protected registeredSyscalls = new Map<string, Syscall>();
|
||||||
protected enabledHooks = new Set<Hook<HookT>>();
|
protected enabledHooks = new Set<Hook<HookT>>();
|
||||||
|
|
||||||
readonly runtimeEnv: RuntimeEnvironment;
|
|
||||||
|
|
||||||
constructor(env: RuntimeEnvironment) {
|
constructor(env: RuntimeEnvironment) {
|
||||||
super();
|
super();
|
||||||
this.runtimeEnv = env;
|
this.runtimeEnv = env;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get loadedPlugs(): Map<string, Plug<HookT>> {
|
||||||
|
return this.plugs;
|
||||||
|
}
|
||||||
|
|
||||||
addHook(feature: Hook<HookT>) {
|
addHook(feature: Hook<HookT>) {
|
||||||
this.enabledHooks.add(feature);
|
this.enabledHooks.add(feature);
|
||||||
feature.apply(this);
|
feature.apply(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
registerSyscalls(
|
registerSyscalls(
|
||||||
namespace: string,
|
|
||||||
requiredCapabilities: string[],
|
requiredCapabilities: string[],
|
||||||
...registrationObjects: SysCallMapping[]
|
...registrationObjects: SysCallMapping[]
|
||||||
) {
|
) {
|
||||||
for (const registrationObject of registrationObjects) {
|
for (const registrationObject of registrationObjects) {
|
||||||
for (let [name, callback] of Object.entries(registrationObject)) {
|
for (let [name, callback] of Object.entries(registrationObject)) {
|
||||||
const callName = namespace ? `${namespace}.${name}` : name;
|
this.registeredSyscalls.set(name, {
|
||||||
this.registeredSyscalls.set(callName, {
|
|
||||||
requiredPermissions: requiredCapabilities,
|
requiredPermissions: requiredCapabilities,
|
||||||
callback,
|
callback,
|
||||||
});
|
});
|
||||||
@ -116,10 +117,6 @@ export class System<HookT> extends EventEmitter<SystemEvents<HookT>> {
|
|||||||
this.plugs.delete(name);
|
this.plugs.delete(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
get loadedPlugs(): Map<string, Plug<HookT>> {
|
|
||||||
return this.plugs;
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON(): SystemJSON<HookT> {
|
toJSON(): SystemJSON<HookT> {
|
||||||
let plugJSON: { [key: string]: Manifest<HookT> } = {};
|
let plugJSON: { [key: string]: Manifest<HookT> } = {};
|
||||||
for (let [name, plug] of this.plugs) {
|
for (let [name, plug] of this.plugs) {
|
||||||
|
@ -1,62 +1,54 @@
|
|||||||
import {ClickEvent} from "../../webapp/app_event";
|
import {ClickEvent} from "../../webapp/app_event";
|
||||||
import {updateMaterializedQueriesCommand} from "./materialized_queries";
|
import {updateMaterializedQueriesCommand} from "./materialized_queries";
|
||||||
import {
|
import {getCursor, getText, navigate as navigateTo, openUrl,} from "plugos-silverbullet-syscall/editor";
|
||||||
getSyntaxNodeAtPos,
|
|
||||||
getSyntaxNodeUnderCursor,
|
|
||||||
getText,
|
|
||||||
navigate as navigateTo,
|
|
||||||
openUrl,
|
|
||||||
} from "plugos-silverbullet-syscall/editor";
|
|
||||||
import {taskToggleAtPos} from "../tasks/task";
|
import {taskToggleAtPos} from "../tasks/task";
|
||||||
import {nodeAtPos, parse} from "plugos-silverbullet-syscall/markdown";
|
import {nodeAtPos, parse} from "plugos-silverbullet-syscall/markdown";
|
||||||
|
import type {MarkdownTree} from "../../common/tree";
|
||||||
|
|
||||||
const materializedQueryPrefix = /<!--\s*#query\s+/;
|
const materializedQueryPrefix = /<!--\s*#query\s+/;
|
||||||
|
|
||||||
async function actionClickOrActionEnter(syntaxNode: any) {
|
async function actionClickOrActionEnter(mdTree: MarkdownTree | null) {
|
||||||
if (!syntaxNode) {
|
if (!mdTree) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log("Attempting to navigate based on syntax node", syntaxNode);
|
console.log("Attempting to navigate based on syntax node", mdTree);
|
||||||
switch (syntaxNode.name) {
|
switch (mdTree.type) {
|
||||||
case "WikiLinkPage":
|
case "WikiLinkPage":
|
||||||
let pageLink = syntaxNode.text;
|
let pageLink = mdTree.children![0].text!;
|
||||||
let pos = 0;
|
let pos = "0";
|
||||||
if (pageLink.includes("@")) {
|
if (pageLink.includes("@")) {
|
||||||
[pageLink, pos] = syntaxNode.text.split("@");
|
[pageLink, pos] = pageLink.split("@");
|
||||||
}
|
}
|
||||||
await navigateTo(pageLink, +pos);
|
await navigateTo(pageLink, +pos);
|
||||||
break;
|
break;
|
||||||
case "URL":
|
case "URL":
|
||||||
await openUrl(syntaxNode.text);
|
await openUrl(mdTree.children![0].text!);
|
||||||
break;
|
break;
|
||||||
case "CommentBlock":
|
case "CommentBlock":
|
||||||
if (syntaxNode.text.match(materializedQueryPrefix)) {
|
if (mdTree.children![0].text!.match(materializedQueryPrefix)) {
|
||||||
await updateMaterializedQueriesCommand();
|
await updateMaterializedQueriesCommand();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "Link":
|
case "Link":
|
||||||
// Markdown link: [bla](URLHERE) needs extraction
|
await openUrl(mdTree.children![4].children![0].text!);
|
||||||
let match = /\[[^\\]+\]\(([^\)]+)\)/.exec(syntaxNode.text);
|
|
||||||
if (match) {
|
|
||||||
await openUrl(match[1]);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case "TaskMarker":
|
case "TaskMarker":
|
||||||
await taskToggleAtPos(syntaxNode.from + 1);
|
await taskToggleAtPos(mdTree.from + 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function linkNavigate() {
|
export async function linkNavigate() {
|
||||||
await actionClickOrActionEnter(await getSyntaxNodeUnderCursor());
|
let mdTree = await parse(await getText());
|
||||||
|
let newNode = await nodeAtPos(mdTree, await getCursor());
|
||||||
|
await actionClickOrActionEnter(newNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function clickNavigate(event: ClickEvent) {
|
export async function clickNavigate(event: ClickEvent) {
|
||||||
if (event.ctrlKey || event.metaKey) {
|
if (event.ctrlKey || event.metaKey) {
|
||||||
let syntaxNode = await getSyntaxNodeAtPos(event.pos);
|
|
||||||
let mdTree = await parse(await getText());
|
let mdTree = await parse(await getText());
|
||||||
let newNode = await nodeAtPos(mdTree, event.pos);
|
let newNode = await nodeAtPos(mdTree, event.pos);
|
||||||
console.log("New node", newNode);
|
console.log("New node", newNode);
|
||||||
await actionClickOrActionEnter(syntaxNode);
|
await actionClickOrActionEnter(newNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,13 +51,13 @@ export class ExpressServer {
|
|||||||
useNullAsDefault: true,
|
useNullAsDefault: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
system.registerSyscalls("shell", ["shell"], shellSyscalls(rootPath));
|
system.registerSyscalls(["shell"], shellSyscalls(rootPath));
|
||||||
system.addHook(new NodeCronHook());
|
system.addHook(new NodeCronHook());
|
||||||
|
|
||||||
system.registerSyscalls("index", [], pageIndexSyscalls(this.db));
|
system.registerSyscalls([], pageIndexSyscalls(this.db));
|
||||||
system.registerSyscalls("space", [], spaceSyscalls(this.storage));
|
system.registerSyscalls([], spaceSyscalls(this.storage));
|
||||||
system.registerSyscalls("event", [], eventSyscalls(this.eventHook));
|
system.registerSyscalls([], eventSyscalls(this.eventHook));
|
||||||
system.registerSyscalls("markdown", [], markdownSyscalls());
|
system.registerSyscalls([], markdownSyscalls());
|
||||||
system.addHook(new EndpointHook(app, "/_"));
|
system.addHook(new EndpointHook(app, "/_"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
import { Knex } from "knex";
|
import {Knex} from "knex";
|
||||||
import { SysCallMapping } from "../../plugos/system";
|
import {SysCallMapping} from "../../plugos/system";
|
||||||
|
|
||||||
import {
|
import {ensureTable, storeSyscalls,} from "../../plugos/syscalls/store.knex_node";
|
||||||
ensureTable,
|
|
||||||
storeReadSyscalls,
|
|
||||||
storeWriteSyscalls,
|
|
||||||
} from "../../plugos/syscalls/store.knex_node";
|
|
||||||
|
|
||||||
type IndexItem = {
|
type IndexItem = {
|
||||||
page: string;
|
page: string;
|
||||||
@ -52,39 +48,38 @@ export async function ensurePageIndexTable(db: Knex<any, unknown>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function pageIndexSyscalls(db: Knex<any, unknown>): SysCallMapping {
|
export function pageIndexSyscalls(db: Knex<any, unknown>): SysCallMapping {
|
||||||
const readCalls = storeReadSyscalls(db, "page_index");
|
const storeCalls = storeSyscalls(db, "page_index");
|
||||||
const writeCalls = storeWriteSyscalls(db, "page_index");
|
|
||||||
const apiObj: SysCallMapping = {
|
const apiObj: SysCallMapping = {
|
||||||
set: async (ctx, page: string, key: string, value: any) => {
|
"index.set": async (ctx, page: string, key: string, value: any) => {
|
||||||
await writeCalls.set(ctx, pageKey(page, key), value);
|
await storeCalls["store.set"](ctx, pageKey(page, key), value);
|
||||||
await writeCalls.set(ctx, globalKey(page, key), value);
|
await storeCalls["store.set"](ctx, globalKey(page, key), value);
|
||||||
},
|
},
|
||||||
batchSet: async (ctx, page: string, kvs: KV[]) => {
|
"index.batchSet": async (ctx, page: string, kvs: KV[]) => {
|
||||||
for (let { key, value } of kvs) {
|
for (let { key, value } of kvs) {
|
||||||
await apiObj.set(ctx, page, key, value);
|
await apiObj["index.set"](ctx, page, key, value);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
delete: async (ctx, page: string, key: string) => {
|
"index.delete": async (ctx, page: string, key: string) => {
|
||||||
await writeCalls.delete(ctx, pageKey(page, key));
|
await storeCalls["store.delete"](ctx, pageKey(page, key));
|
||||||
await writeCalls.delete(ctx, globalKey(page, key));
|
await storeCalls["store.delete"](ctx, globalKey(page, key));
|
||||||
},
|
},
|
||||||
get: async (ctx, page: string, key: string) => {
|
"index.get": async (ctx, page: string, key: string) => {
|
||||||
return readCalls.get(ctx, pageKey(page, key));
|
return storeCalls["store.get"](ctx, pageKey(page, key));
|
||||||
},
|
},
|
||||||
scanPrefixForPage: async (ctx, page: string, prefix: string) => {
|
"index.scanPrefixForPage": async (ctx, page: string, prefix: string) => {
|
||||||
return (await readCalls.queryPrefix(ctx, pageKey(page, prefix))).map(
|
return (
|
||||||
({ key, value }: { key: string; value: any }) => {
|
await storeCalls["store.queryPrefix"](ctx, pageKey(page, prefix))
|
||||||
|
).map(({ key, value }: { key: string; value: any }) => {
|
||||||
const { key: pageKey } = unpackPageKey(key);
|
const { key: pageKey } = unpackPageKey(key);
|
||||||
return {
|
return {
|
||||||
page,
|
page,
|
||||||
key: pageKey,
|
key: pageKey,
|
||||||
value,
|
value,
|
||||||
};
|
};
|
||||||
}
|
});
|
||||||
);
|
|
||||||
},
|
},
|
||||||
scanPrefixGlobal: async (ctx, prefix: string) => {
|
"index.scanPrefixGlobal": async (ctx, prefix: string) => {
|
||||||
return (await readCalls.queryPrefix(ctx, `k~${prefix}`)).map(
|
return (await storeCalls["store.queryPrefix"](ctx, `k~${prefix}`)).map(
|
||||||
({ key, value }: { key: string; value: any }) => {
|
({ key, value }: { key: string; value: any }) => {
|
||||||
const { page, key: pageKey } = unpackGlobalKey(key);
|
const { page, key: pageKey } = unpackGlobalKey(key);
|
||||||
return {
|
return {
|
||||||
@ -95,22 +90,22 @@ export function pageIndexSyscalls(db: Knex<any, unknown>): SysCallMapping {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
clearPageIndexForPage: async (ctx, page: string) => {
|
"index.clearPageIndexForPage": async (ctx, page: string) => {
|
||||||
await apiObj.deletePrefixForPage(ctx, page, "");
|
await apiObj["index.deletePrefixForPage"](ctx, page, "");
|
||||||
},
|
},
|
||||||
deletePrefixForPage: async (ctx, page: string, prefix: string) => {
|
"index.deletePrefixForPage": async (ctx, page: string, prefix: string) => {
|
||||||
// Collect all global keys for this page to delete
|
// Collect all global keys for this page to delete
|
||||||
let keysToDelete = (
|
let keysToDelete = (
|
||||||
await readCalls.queryPrefix(ctx, pageKey(page, prefix))
|
await storeCalls["store.queryPrefix"](ctx, pageKey(page, prefix))
|
||||||
).map(({ key }: { key: string; value: string }) =>
|
).map(({ key }: { key: string; value: string }) =>
|
||||||
globalKey(page, unpackPageKey(key).key)
|
globalKey(page, unpackPageKey(key).key)
|
||||||
);
|
);
|
||||||
// Delete all page keys
|
// Delete all page keys
|
||||||
await writeCalls.deletePrefix(ctx, pageKey(page, prefix));
|
await storeCalls["store.deletePrefix"](ctx, pageKey(page, prefix));
|
||||||
await writeCalls.batchDelete(ctx, keysToDelete);
|
await storeCalls["store.batchDelete"](ctx, keysToDelete);
|
||||||
},
|
},
|
||||||
clearPageIndex: async (ctx) => {
|
"index.clearPageIndex": async (ctx) => {
|
||||||
await writeCalls.deleteAll(ctx);
|
await storeCalls["store.deleteAll"](ctx);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
return apiObj;
|
return apiObj;
|
||||||
|
@ -1,22 +1,26 @@
|
|||||||
import { PageMeta } from "../../common/types";
|
import {PageMeta} from "../../common/types";
|
||||||
import { SysCallMapping } from "../../plugos/system";
|
import {SysCallMapping} from "../../plugos/system";
|
||||||
import { Storage } from "../disk_storage";
|
import {Storage} from "../disk_storage";
|
||||||
|
|
||||||
export default (storage: Storage): SysCallMapping => {
|
export default (storage: Storage): SysCallMapping => {
|
||||||
return {
|
return {
|
||||||
listPages: (ctx): Promise<PageMeta[]> => {
|
"space.listPages": (ctx): Promise<PageMeta[]> => {
|
||||||
return storage.listPages();
|
return storage.listPages();
|
||||||
},
|
},
|
||||||
readPage: async (
|
"space.readPage": async (
|
||||||
ctx,
|
ctx,
|
||||||
name: string
|
name: string
|
||||||
): Promise<{ text: string; meta: PageMeta }> => {
|
): Promise<{ text: string; meta: PageMeta }> => {
|
||||||
return storage.readPage(name);
|
return storage.readPage(name);
|
||||||
},
|
},
|
||||||
writePage: async (ctx, name: string, text: string): Promise<PageMeta> => {
|
"space.writePage": async (
|
||||||
|
ctx,
|
||||||
|
name: string,
|
||||||
|
text: string
|
||||||
|
): Promise<PageMeta> => {
|
||||||
return storage.writePage(name, text);
|
return storage.writePage(name, text);
|
||||||
},
|
},
|
||||||
deletePage: async (ctx, name: string) => {
|
"space.deletePage": async (ctx, name: string) => {
|
||||||
return storage.deletePage(name);
|
return storage.deletePage(name);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -47,7 +47,6 @@ import {CompleterHook} from "./hooks/completer";
|
|||||||
import {pasteLinkExtension} from "./editor_paste";
|
import {pasteLinkExtension} from "./editor_paste";
|
||||||
import {markdownSyscalls} from "../common/syscalls/markdown";
|
import {markdownSyscalls} from "../common/syscalls/markdown";
|
||||||
|
|
||||||
|
|
||||||
class PageState {
|
class PageState {
|
||||||
scrollTop: number;
|
scrollTop: number;
|
||||||
selection: EditorSelection;
|
selection: EditorSelection;
|
||||||
@ -61,11 +60,9 @@ class PageState {
|
|||||||
const saveInterval = 2000;
|
const saveInterval = 2000;
|
||||||
|
|
||||||
export class Editor implements AppEventDispatcher {
|
export class Editor implements AppEventDispatcher {
|
||||||
private system = new System<SilverBulletHooks>("client");
|
|
||||||
readonly commandHook: CommandHook;
|
readonly commandHook: CommandHook;
|
||||||
readonly slashCommandHook: SlashCommandHook;
|
readonly slashCommandHook: SlashCommandHook;
|
||||||
readonly completerHook: CompleterHook;
|
readonly completerHook: CompleterHook;
|
||||||
|
|
||||||
openPages = new Map<string, PageState>();
|
openPages = new Map<string, PageState>();
|
||||||
editorView?: EditorView;
|
editorView?: EditorView;
|
||||||
viewState: AppViewState;
|
viewState: AppViewState;
|
||||||
@ -73,6 +70,8 @@ export class Editor implements AppEventDispatcher {
|
|||||||
space: Space;
|
space: Space;
|
||||||
pageNavigator: PathPageNavigator;
|
pageNavigator: PathPageNavigator;
|
||||||
eventHook: EventHook;
|
eventHook: EventHook;
|
||||||
|
saveTimeout: any;
|
||||||
|
private system = new System<SilverBulletHooks>("client");
|
||||||
|
|
||||||
constructor(space: Space, parent: Element) {
|
constructor(space: Space, parent: Element) {
|
||||||
this.space = space;
|
this.space = space;
|
||||||
@ -110,11 +109,15 @@ export class Editor implements AppEventDispatcher {
|
|||||||
});
|
});
|
||||||
this.pageNavigator = new PathPageNavigator();
|
this.pageNavigator = new PathPageNavigator();
|
||||||
|
|
||||||
this.system.registerSyscalls("editor", [], editorSyscalls(this));
|
this.system.registerSyscalls([], editorSyscalls(this));
|
||||||
this.system.registerSyscalls("space", [], spaceSyscalls(this));
|
this.system.registerSyscalls([], spaceSyscalls(this));
|
||||||
this.system.registerSyscalls("index", [], indexerSyscalls(this.space));
|
this.system.registerSyscalls([], indexerSyscalls(this.space));
|
||||||
this.system.registerSyscalls("system", [], systemSyscalls(this.space));
|
this.system.registerSyscalls([], systemSyscalls(this.space));
|
||||||
this.system.registerSyscalls("markdown", [], markdownSyscalls());
|
this.system.registerSyscalls([], markdownSyscalls());
|
||||||
|
}
|
||||||
|
|
||||||
|
get currentPage(): string | undefined {
|
||||||
|
return this.viewState.currentPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
async init() {
|
async init() {
|
||||||
@ -180,8 +183,6 @@ export class Editor implements AppEventDispatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
saveTimeout: any;
|
|
||||||
|
|
||||||
async save(immediate: boolean = false): Promise<void> {
|
async save(immediate: boolean = false): Promise<void> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (!this.viewState.unsavedChanges) {
|
if (!this.viewState.unsavedChanges) {
|
||||||
@ -236,10 +237,6 @@ export class Editor implements AppEventDispatcher {
|
|||||||
return this.eventHook.dispatchEvent(name, data);
|
return this.eventHook.dispatchEvent(name, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
get currentPage(): string | undefined {
|
|
||||||
return this.viewState.currentPage;
|
|
||||||
}
|
|
||||||
|
|
||||||
createEditorState(pageName: string, text: string): EditorState {
|
createEditorState(pageName: string, text: string): EditorState {
|
||||||
let commandKeyBindings: KeyBinding[] = [];
|
let commandKeyBindings: KeyBinding[] = [];
|
||||||
for (let def of this.commandHook.editorCommands.values()) {
|
for (let def of this.commandHook.editorCommands.values()) {
|
||||||
|
@ -28,37 +28,37 @@ function ensureAnchor(expr: any, start: boolean) {
|
|||||||
|
|
||||||
export function editorSyscalls(editor: Editor): SysCallMapping {
|
export function editorSyscalls(editor: Editor): SysCallMapping {
|
||||||
return {
|
return {
|
||||||
getCurrentPage: (): string => {
|
"editor.getCurrentPage": (): string => {
|
||||||
return editor.currentPage!;
|
return editor.currentPage!;
|
||||||
},
|
},
|
||||||
getText: () => {
|
"editor.getText": () => {
|
||||||
return editor.editorView?.state.sliceDoc();
|
return editor.editorView?.state.sliceDoc();
|
||||||
},
|
},
|
||||||
getCursor: (): number => {
|
"editor.getCursor": (): number => {
|
||||||
return editor.editorView!.state.selection.main.from;
|
return editor.editorView!.state.selection.main.from;
|
||||||
},
|
},
|
||||||
save: async () => {
|
"editor.save": async () => {
|
||||||
return editor.save(true);
|
return editor.save(true);
|
||||||
},
|
},
|
||||||
navigate: async (ctx, name: string, pos: number) => {
|
"editor.navigate": async (ctx, name: string, pos: number) => {
|
||||||
await editor.navigate(name, pos);
|
await editor.navigate(name, pos);
|
||||||
},
|
},
|
||||||
reloadPage: async (ctx) => {
|
"editor.reloadPage": async (ctx) => {
|
||||||
await editor.reloadPage();
|
await editor.reloadPage();
|
||||||
},
|
},
|
||||||
openUrl: async (ctx, url: string) => {
|
"editor.openUrl": async (ctx, url: string) => {
|
||||||
window.open(url, "_blank")!.focus();
|
window.open(url, "_blank")!.focus();
|
||||||
},
|
},
|
||||||
flashNotification: (ctx, message: string) => {
|
"editor.flashNotification": (ctx, message: string) => {
|
||||||
editor.flashNotification(message);
|
editor.flashNotification(message);
|
||||||
},
|
},
|
||||||
showRhs: (ctx, html: string) => {
|
"editor.showRhs": (ctx, html: string) => {
|
||||||
editor.viewDispatch({
|
editor.viewDispatch({
|
||||||
type: "show-rhs",
|
type: "show-rhs",
|
||||||
html: html,
|
html: html,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
insertAtPos: (ctx, text: string, pos: number) => {
|
"editor.insertAtPos": (ctx, text: string, pos: number) => {
|
||||||
editor.editorView!.dispatch({
|
editor.editorView!.dispatch({
|
||||||
changes: {
|
changes: {
|
||||||
insert: text,
|
insert: text,
|
||||||
@ -66,7 +66,7 @@ export function editorSyscalls(editor: Editor): SysCallMapping {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
replaceRange: (ctx, from: number, to: number, text: string) => {
|
"editor.replaceRange": (ctx, from: number, to: number, text: string) => {
|
||||||
editor.editorView!.dispatch({
|
editor.editorView!.dispatch({
|
||||||
changes: {
|
changes: {
|
||||||
insert: text,
|
insert: text,
|
||||||
@ -75,14 +75,14 @@ export function editorSyscalls(editor: Editor): SysCallMapping {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
moveCursor: (ctx, pos: number) => {
|
"editor.moveCursor": (ctx, pos: number) => {
|
||||||
editor.editorView!.dispatch({
|
editor.editorView!.dispatch({
|
||||||
selection: {
|
selection: {
|
||||||
anchor: pos,
|
anchor: pos,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
insertAtCursor: (ctx, text: string) => {
|
"editor.insertAtCursor": (ctx, text: string) => {
|
||||||
let editorView = editor.editorView!;
|
let editorView = editor.editorView!;
|
||||||
let from = editorView.state.selection.main.from;
|
let from = editorView.state.selection.main.from;
|
||||||
editorView.dispatch({
|
editorView.dispatch({
|
||||||
@ -95,7 +95,7 @@ export function editorSyscalls(editor: Editor): SysCallMapping {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
getSyntaxNodeUnderCursor: (): SyntaxNode | undefined => {
|
"editor.getSyntaxNodeUnderCursor": (): SyntaxNode | undefined => {
|
||||||
const editorState = editor.editorView!.state;
|
const editorState = editor.editorView!.state;
|
||||||
let selection = editorState.selection.main;
|
let selection = editorState.selection.main;
|
||||||
if (selection.empty) {
|
if (selection.empty) {
|
||||||
@ -110,13 +110,13 @@ export function editorSyscalls(editor: Editor): SysCallMapping {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getLineUnderCursor: (): string => {
|
"editor.getLineUnderCursor": (): string => {
|
||||||
const editorState = editor.editorView!.state;
|
const editorState = editor.editorView!.state;
|
||||||
let selection = editorState.selection.main;
|
let selection = editorState.selection.main;
|
||||||
let line = editorState.doc.lineAt(selection.from);
|
let line = editorState.doc.lineAt(selection.from);
|
||||||
return editorState.sliceDoc(line.from, line.to);
|
return editorState.sliceDoc(line.from, line.to);
|
||||||
},
|
},
|
||||||
matchBefore: (
|
"editor.matchBefore": (
|
||||||
ctx,
|
ctx,
|
||||||
regexp: string
|
regexp: string
|
||||||
): { from: number; to: number; text: string } | null => {
|
): { from: number; to: number; text: string } | null => {
|
||||||
@ -135,7 +135,7 @@ export function editorSyscalls(editor: Editor): SysCallMapping {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
getSyntaxNodeAtPos: (ctx, pos: number): SyntaxNode | undefined => {
|
"editor.getSyntaxNodeAtPos": (ctx, pos: number): SyntaxNode | undefined => {
|
||||||
const editorState = editor.editorView!.state;
|
const editorState = editor.editorView!.state;
|
||||||
let node = syntaxTree(editorState).resolveInner(pos);
|
let node = syntaxTree(editorState).resolveInner(pos);
|
||||||
if (node) {
|
if (node) {
|
||||||
@ -147,10 +147,14 @@ export function editorSyscalls(editor: Editor): SysCallMapping {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dispatch: (ctx, change: Transaction) => {
|
"editor.dispatch": (ctx, change: Transaction) => {
|
||||||
editor.editorView!.dispatch(change);
|
editor.editorView!.dispatch(change);
|
||||||
},
|
},
|
||||||
prompt: (ctx, message: string, defaultValue = ""): string | null => {
|
"editor.prompt": (
|
||||||
|
ctx,
|
||||||
|
message: string,
|
||||||
|
defaultValue = ""
|
||||||
|
): string | null => {
|
||||||
return prompt(message, defaultValue);
|
return prompt(message, defaultValue);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -5,13 +5,13 @@ import {transportSyscalls} from "../../plugos/syscalls/transport";
|
|||||||
export function indexerSyscalls(space: Space): SysCallMapping {
|
export function indexerSyscalls(space: Space): SysCallMapping {
|
||||||
return transportSyscalls(
|
return transportSyscalls(
|
||||||
[
|
[
|
||||||
"scanPrefixForPage",
|
"index.scanPrefixForPage",
|
||||||
"scanPrefixGlobal",
|
"index.scanPrefixGlobal",
|
||||||
"get",
|
"index.get",
|
||||||
"set",
|
"index.set",
|
||||||
"batchSet",
|
"index.batchSet",
|
||||||
"delete",
|
"index.delete",
|
||||||
],
|
],
|
||||||
(ctx, name, ...args) => space.remoteSyscall(ctx.plug, `index.${name}`, args)
|
(ctx, name, ...args) => space.remoteSyscall(ctx.plug, name, args)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -4,19 +4,23 @@ import {PageMeta} from "../../common/types";
|
|||||||
|
|
||||||
export function spaceSyscalls(editor: Editor): SysCallMapping {
|
export function spaceSyscalls(editor: Editor): SysCallMapping {
|
||||||
return {
|
return {
|
||||||
listPages: async (): Promise<PageMeta[]> => {
|
"space.listPages": async (): Promise<PageMeta[]> => {
|
||||||
return [...(await editor.space.listPages())];
|
return [...(await editor.space.listPages())];
|
||||||
},
|
},
|
||||||
readPage: async (
|
"space.readPage": async (
|
||||||
ctx,
|
ctx,
|
||||||
name: string
|
name: string
|
||||||
): Promise<{ text: string; meta: PageMeta }> => {
|
): Promise<{ text: string; meta: PageMeta }> => {
|
||||||
return await editor.space.readPage(name);
|
return await editor.space.readPage(name);
|
||||||
},
|
},
|
||||||
writePage: async (ctx, name: string, text: string): Promise<PageMeta> => {
|
"space.writePage": async (
|
||||||
|
ctx,
|
||||||
|
name: string,
|
||||||
|
text: string
|
||||||
|
): Promise<PageMeta> => {
|
||||||
return await editor.space.writePage(name, text);
|
return await editor.space.writePage(name, text);
|
||||||
},
|
},
|
||||||
deletePage: async (ctx, name: string) => {
|
"space.deletePage": async (ctx, name: string) => {
|
||||||
// If we're deleting the current page, navigate to the start page
|
// If we're deleting the current page, navigate to the start page
|
||||||
if (editor.currentPage === name) {
|
if (editor.currentPage === name) {
|
||||||
await editor.navigate("start");
|
await editor.navigate("start");
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
import { SysCallMapping } from "../../plugos/system";
|
import {SysCallMapping} from "../../plugos/system";
|
||||||
import { Space } from "../space";
|
import {Space} from "../space";
|
||||||
|
|
||||||
export function systemSyscalls(space: Space): SysCallMapping {
|
export function systemSyscalls(space: Space): SysCallMapping {
|
||||||
return {
|
return {
|
||||||
async invokeFunctionOnServer(ctx, name: string, ...args: any[]) {
|
"system.invokeFunctionOnServer": async (
|
||||||
|
ctx,
|
||||||
|
name: string,
|
||||||
|
...args: any[]
|
||||||
|
) => {
|
||||||
if (!ctx.plug) {
|
if (!ctx.plug) {
|
||||||
throw Error("No plug associated with context");
|
throw Error("No plug associated with context");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user