@silverbulletmd/silverbullet 2.4.2 → 2.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -4
- package/client/markdown_parser/constants.ts +2 -2
- package/client/plugos/hooks/code_widget.ts +0 -3
- package/client/plugos/hooks/document_editor.ts +0 -3
- package/client/plugos/hooks/event.ts +1 -1
- package/client/plugos/hooks/mq.ts +1 -1
- package/client/plugos/hooks/plug_namespace.ts +0 -3
- package/client/plugos/hooks/slash_command.ts +2 -2
- package/client/plugos/plug.ts +0 -1
- package/client/plugos/plug_compile.ts +28 -29
- package/client/plugos/proxy_fetch.ts +1 -1
- package/client/plugos/sandboxes/web_worker_sandbox.ts +1 -1
- package/client/plugos/sandboxes/worker_sandbox.ts +2 -3
- package/client/plugos/syscalls/editor.ts +12 -12
- package/client/plugos/syscalls/fetch.ts +1 -1
- package/client/plugos/syscalls/jsonschema.ts +1 -1
- package/client/plugos/syscalls/mq.ts +1 -1
- package/client/plugos/syscalls/space.ts +1 -1
- package/client/plugos/system.ts +2 -2
- package/client/plugos/worker_runtime.ts +8 -30
- package/client/space_lua/aggregates.ts +209 -0
- package/client/space_lua/ast.ts +24 -2
- package/client/space_lua/eval.ts +58 -53
- package/client/space_lua/labels.ts +1 -1
- package/client/space_lua/parse.ts +117 -12
- package/client/space_lua/query_collection.ts +850 -70
- package/client/space_lua/query_env.ts +26 -0
- package/client/space_lua/runtime.ts +47 -17
- package/client/space_lua/stdlib/format.ts +19 -19
- package/client/space_lua/stdlib/math.ts +73 -48
- package/client/space_lua/stdlib/net.ts +2 -2
- package/client/space_lua/stdlib/os.ts +5 -0
- package/client/space_lua/stdlib/pattern.ts +702 -0
- package/client/space_lua/stdlib/prng.ts +145 -0
- package/client/space_lua/stdlib/space_lua.ts +3 -8
- package/client/space_lua/stdlib/string.ts +103 -181
- package/client/space_lua/stdlib/string_pack.ts +486 -0
- package/client/space_lua/stdlib/table.ts +73 -9
- package/client/space_lua/stdlib.ts +38 -14
- package/client/space_lua/tonumber.ts +3 -2
- package/client/space_lua/util.ts +43 -9
- package/dist/plug-compile.js +23 -69
- package/dist/worker_runtime_bundle.js +233 -0
- package/package.json +10 -5
- package/plug-api/constants.ts +0 -32
- package/plug-api/lib/async.ts +2 -2
- package/plug-api/lib/crypto.ts +11 -11
- package/plug-api/lib/json.ts +1 -1
- package/plug-api/lib/limited_map.ts +1 -1
- package/plug-api/lib/native_fetch.ts +2 -0
- package/plug-api/lib/ref.ts +5 -5
- package/plug-api/lib/transclusion.ts +5 -5
- package/plug-api/lib/tree.ts +50 -2
- package/plug-api/lib/yaml.ts +10 -10
- package/plug-api/syscalls/editor.ts +1 -1
- package/plug-api/system_mock.ts +0 -1
- package/client/plugos/sandboxes/deno_worker_sandbox.ts +0 -6
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
getMetatable,
|
|
2
3
|
type ILuaFunction,
|
|
3
4
|
isILuaFunction,
|
|
4
5
|
isLuaTable,
|
|
@@ -17,6 +18,7 @@ import {
|
|
|
17
18
|
luaToString,
|
|
18
19
|
luaTypeOf,
|
|
19
20
|
type LuaValue,
|
|
21
|
+
singleResult,
|
|
20
22
|
} from "./runtime.ts";
|
|
21
23
|
import { stringApi } from "./stdlib/string.ts";
|
|
22
24
|
import { tableApi } from "./stdlib/table.ts";
|
|
@@ -32,6 +34,7 @@ import { luaLoad } from "./stdlib/load.ts";
|
|
|
32
34
|
import { cryptoApi } from "./stdlib/crypto.ts";
|
|
33
35
|
import { netApi } from "./stdlib/net.ts";
|
|
34
36
|
import { isTaggedFloat, makeLuaFloat } from "./numeric.ts";
|
|
37
|
+
import { isPromise } from "./rp.ts";
|
|
35
38
|
|
|
36
39
|
const printFunction = new LuaBuiltinFunction(async (_sf, ...args) => {
|
|
37
40
|
console.log(
|
|
@@ -121,23 +124,41 @@ export const eachFunction = new LuaBuiltinFunction(
|
|
|
121
124
|
},
|
|
122
125
|
);
|
|
123
126
|
|
|
124
|
-
const unpackFunction = new LuaBuiltinFunction(async (sf, t: LuaTable) => {
|
|
125
|
-
const values: LuaValue[] = [];
|
|
126
|
-
for (let i = 1; i <= (t as any).length; i++) {
|
|
127
|
-
values.push(await luaGet(t, i, sf.astCtx ?? null, sf));
|
|
128
|
-
}
|
|
129
|
-
return new LuaMultiRes(values);
|
|
130
|
-
});
|
|
131
|
-
|
|
132
127
|
const typeFunction = new LuaBuiltinFunction(
|
|
133
128
|
(_sf, value: LuaValue): string | Promise<string> => {
|
|
134
129
|
return luaTypeOf(value);
|
|
135
130
|
},
|
|
136
131
|
);
|
|
137
132
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
133
|
+
// tostring() checks `__tostring` metamethod first (with live SF), then
|
|
134
|
+
// falls back to the default `luaToString` representation.
|
|
135
|
+
const tostringFunction = new LuaBuiltinFunction(
|
|
136
|
+
(sf, value: any): string | Promise<string> => {
|
|
137
|
+
const mt = getMetatable(value, sf);
|
|
138
|
+
if (mt) {
|
|
139
|
+
const mm = mt.rawGet("__tostring");
|
|
140
|
+
if (mm !== undefined && mm !== null) {
|
|
141
|
+
const ctx = sf.astCtx ?? {};
|
|
142
|
+
const r = luaCall(mm, [value], ctx as any, sf);
|
|
143
|
+
const unwrap = (v: any): string => {
|
|
144
|
+
const s = singleResult(v);
|
|
145
|
+
if (typeof s !== "string") {
|
|
146
|
+
throw new LuaRuntimeError(
|
|
147
|
+
"'__tostring' must return a string",
|
|
148
|
+
sf,
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
return s;
|
|
152
|
+
};
|
|
153
|
+
if (isPromise(r)) {
|
|
154
|
+
return (r as Promise<any>).then(unwrap);
|
|
155
|
+
}
|
|
156
|
+
return unwrap(r);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return luaToString(value);
|
|
160
|
+
},
|
|
161
|
+
);
|
|
141
162
|
|
|
142
163
|
const tonumberFunction = new LuaBuiltinFunction(
|
|
143
164
|
(sf, value: LuaValue, base?: number) => {
|
|
@@ -255,7 +276,7 @@ const setmetatableFunction = new LuaBuiltinFunction(
|
|
|
255
276
|
|
|
256
277
|
const rawlenFunction = new LuaBuiltinFunction(
|
|
257
278
|
(_sf, value: LuaValue) => {
|
|
258
|
-
return luaLen(value, _sf);
|
|
279
|
+
return luaLen(value, _sf, true);
|
|
259
280
|
},
|
|
260
281
|
);
|
|
261
282
|
|
|
@@ -429,7 +450,7 @@ const nextFunction = new LuaBuiltinFunction(
|
|
|
429
450
|
const someFunction = new LuaBuiltinFunction(async (_sf, value: any) => {
|
|
430
451
|
switch (await luaTypeOf(value)) {
|
|
431
452
|
case "number":
|
|
432
|
-
if (!isFinite(value)) return null;
|
|
453
|
+
if (!Number.isFinite(value)) return null;
|
|
433
454
|
break;
|
|
434
455
|
case "string":
|
|
435
456
|
if (value.trim() === "") return null;
|
|
@@ -446,13 +467,16 @@ export function luaBuildStandardEnv() {
|
|
|
446
467
|
const env = new LuaEnv();
|
|
447
468
|
// _G global
|
|
448
469
|
env.set("_G", env);
|
|
470
|
+
// Lua version string - for now it signals Lua 5.4 compatibility with
|
|
471
|
+
// selective 5.5 features; kept non-standard so callers can distinguish
|
|
472
|
+
// Space Lua from a plain Lua runtime.
|
|
473
|
+
env.set("_VERSION", "Lua 5.4+");
|
|
449
474
|
// Top-level builtins
|
|
450
475
|
env.set("print", printFunction);
|
|
451
476
|
env.set("assert", assertFunction);
|
|
452
477
|
env.set("type", typeFunction);
|
|
453
478
|
env.set("tostring", tostringFunction);
|
|
454
479
|
env.set("tonumber", tonumberFunction);
|
|
455
|
-
env.set("unpack", unpackFunction);
|
|
456
480
|
env.set("select", selectFunction);
|
|
457
481
|
env.set("next", nextFunction);
|
|
458
482
|
// Iterators
|
|
@@ -283,7 +283,7 @@ function parseDecFloat(s: string): { ok: boolean; value: number } {
|
|
|
283
283
|
return { ok: false, value: 0 };
|
|
284
284
|
}
|
|
285
285
|
|
|
286
|
-
const result = sign * (hasExp ? val *
|
|
286
|
+
const result = sign * (hasExp ? val * 10 ** exp : val);
|
|
287
287
|
return { ok: true, value: result };
|
|
288
288
|
}
|
|
289
289
|
|
|
@@ -434,7 +434,7 @@ function parseHexFloat(s: string): { ok: boolean; value: number } {
|
|
|
434
434
|
}
|
|
435
435
|
|
|
436
436
|
const frac = fracVal === 0 ? 0 : (fracVal / fracScale);
|
|
437
|
-
const result = sign * (intVal + frac) *
|
|
437
|
+
const result = sign * (intVal + frac) * 2 ** (expSign * exp);
|
|
438
438
|
return { ok: true, value: result };
|
|
439
439
|
}
|
|
440
440
|
|
|
@@ -460,6 +460,7 @@ export function luaToNumberDetailed(
|
|
|
460
460
|
}
|
|
461
461
|
|
|
462
462
|
{
|
|
463
|
+
// biome-ignore lint/correctness/useParseIntRadix: local parseInt function, not global
|
|
463
464
|
const parsed = parseInt(s);
|
|
464
465
|
if (parsed.ok) {
|
|
465
466
|
const v = parsed.value;
|
package/client/space_lua/util.ts
CHANGED
|
@@ -14,9 +14,8 @@ export function evalPromiseValues(vals: any[]): Promise<any[]> | any[] {
|
|
|
14
14
|
}
|
|
15
15
|
if (promises.length === 0) {
|
|
16
16
|
return promiseResults;
|
|
17
|
-
} else {
|
|
18
|
-
return Promise.all(promises).then(() => promiseResults);
|
|
19
17
|
}
|
|
18
|
+
return Promise.all(promises).then(() => promiseResults);
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
/**
|
|
@@ -36,18 +35,19 @@ async function getPivot(
|
|
|
36
35
|
if (await compare(x, y) < 0) {
|
|
37
36
|
if (await compare(y, z) < 0) {
|
|
38
37
|
return y;
|
|
39
|
-
}
|
|
38
|
+
}
|
|
39
|
+
if (await compare(z, x) < 0) {
|
|
40
40
|
return x;
|
|
41
|
-
} else {
|
|
42
|
-
return z;
|
|
43
41
|
}
|
|
44
|
-
|
|
42
|
+
return z;
|
|
43
|
+
}
|
|
44
|
+
if (await compare(y, z) > 0) {
|
|
45
45
|
return y;
|
|
46
|
-
}
|
|
46
|
+
}
|
|
47
|
+
if (await compare(z, x) > 0) {
|
|
47
48
|
return x;
|
|
48
|
-
} else {
|
|
49
|
-
return z;
|
|
50
49
|
}
|
|
50
|
+
return z;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
/**
|
|
@@ -94,3 +94,37 @@ export async function asyncQuickSort(
|
|
|
94
94
|
}
|
|
95
95
|
return arr;
|
|
96
96
|
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* iterative async merge sort
|
|
100
|
+
* @param arr tagged array of { val, idx } elements
|
|
101
|
+
* @param compare async comparator returning <0, 0, or >0
|
|
102
|
+
*/
|
|
103
|
+
export async function asyncMergeSort(
|
|
104
|
+
arr: { val: any; idx: number }[],
|
|
105
|
+
compare: (
|
|
106
|
+
a: { val: any; idx: number },
|
|
107
|
+
b: { val: any; idx: number },
|
|
108
|
+
) => Promise<number>,
|
|
109
|
+
): Promise<void> {
|
|
110
|
+
const n = arr.length;
|
|
111
|
+
if (n <= 1) return;
|
|
112
|
+
const work = new Array(n);
|
|
113
|
+
|
|
114
|
+
for (let size = 1; size < n; size *= 2) {
|
|
115
|
+
for (let left = 0; left < n; left += 2 * size) {
|
|
116
|
+
const mid = Math.min(left + size, n);
|
|
117
|
+
const right = Math.min(left + 2 * size, n);
|
|
118
|
+
|
|
119
|
+
let i = left, j = mid, k = left;
|
|
120
|
+
while (i < mid && j < right) {
|
|
121
|
+
const cmp = await compare(arr[i], arr[j]);
|
|
122
|
+
if (cmp <= 0) work[k++] = arr[i++];
|
|
123
|
+
else work[k++] = arr[j++];
|
|
124
|
+
}
|
|
125
|
+
while (i < mid) work[k++] = arr[i++];
|
|
126
|
+
while (j < right) work[k++] = arr[j++];
|
|
127
|
+
for (let m = left; m < right; m++) arr[m] = work[m];
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
package/dist/plug-compile.js
CHANGED
|
@@ -4,64 +4,14 @@
|
|
|
4
4
|
import { Command } from "commander";
|
|
5
5
|
|
|
6
6
|
// version.ts
|
|
7
|
-
var version = "2.
|
|
7
|
+
var version = "2.5.3";
|
|
8
8
|
|
|
9
9
|
// client/plugos/plug_compile.ts
|
|
10
10
|
import * as path from "node:path";
|
|
11
11
|
import { readFile as readFile2, writeFile, mkdtemp, rm, mkdir } from "node:fs/promises";
|
|
12
12
|
import { tmpdir } from "node:os";
|
|
13
13
|
import * as YAML from "js-yaml";
|
|
14
|
-
|
|
15
|
-
// build_deps.ts
|
|
16
14
|
import * as esbuild from "esbuild";
|
|
17
|
-
import { readFileSync } from "node:fs";
|
|
18
|
-
import { resolve, dirname } from "node:path";
|
|
19
|
-
import { fileURLToPath } from "node:url";
|
|
20
|
-
var __filename = fileURLToPath(import.meta.url);
|
|
21
|
-
var __dirname = dirname(__filename);
|
|
22
|
-
function denoPlugin(options) {
|
|
23
|
-
const configPath = options?.configPath || resolve(__dirname, "deno.json");
|
|
24
|
-
const denoConfig = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
25
|
-
const imports = denoConfig.imports || {};
|
|
26
|
-
return {
|
|
27
|
-
name: "deno-resolver",
|
|
28
|
-
setup(build) {
|
|
29
|
-
build.onResolve({ filter: /^file:\/\// }, (args) => {
|
|
30
|
-
const filePath = args.path.replace(/^file:\/\//, "");
|
|
31
|
-
return { path: filePath };
|
|
32
|
-
});
|
|
33
|
-
build.onResolve({ filter: /^@silverbulletmd\/silverbullet\// }, (args) => {
|
|
34
|
-
const importPath = args.path;
|
|
35
|
-
if (imports[importPath]) {
|
|
36
|
-
const resolvedPath = resolve(__dirname, imports[importPath]);
|
|
37
|
-
return { path: resolvedPath };
|
|
38
|
-
}
|
|
39
|
-
return null;
|
|
40
|
-
});
|
|
41
|
-
build.onResolve({ filter: /.*/ }, (args) => {
|
|
42
|
-
if (args.path.startsWith(".") || args.path.startsWith("/")) {
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
const importPath = args.path;
|
|
46
|
-
if (imports[importPath]) {
|
|
47
|
-
let mapped = imports[importPath];
|
|
48
|
-
if (mapped.startsWith("npm:")) {
|
|
49
|
-
return { path: mapped.replace(/^npm:/, ""), external: true };
|
|
50
|
-
}
|
|
51
|
-
if (mapped.startsWith("jsr:")) {
|
|
52
|
-
return { path: args.path, external: true };
|
|
53
|
-
}
|
|
54
|
-
if (mapped.startsWith("http://") || mapped.startsWith("https://")) {
|
|
55
|
-
return { path: args.path, external: true };
|
|
56
|
-
}
|
|
57
|
-
const resolvedPath = resolve(__dirname, mapped);
|
|
58
|
-
return { path: resolvedPath };
|
|
59
|
-
}
|
|
60
|
-
return null;
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
15
|
|
|
66
16
|
// client/asset_bundle/builder.ts
|
|
67
17
|
import picomatch from "picomatch";
|
|
@@ -1365,7 +1315,19 @@ async function bundleAssets(rootPath, patterns) {
|
|
|
1365
1315
|
}
|
|
1366
1316
|
|
|
1367
1317
|
// client/plugos/plug_compile.ts
|
|
1368
|
-
|
|
1318
|
+
import { existsSync } from "node:fs";
|
|
1319
|
+
var currentDir = import.meta.dirname;
|
|
1320
|
+
var bundledPath = path.join(currentDir, "worker_runtime_bundle.js");
|
|
1321
|
+
var sourcePath = path.join(currentDir, "../../dist/worker_runtime_bundle.js");
|
|
1322
|
+
var workerRuntimeBundlePath = existsSync(bundledPath) ? bundledPath : sourcePath;
|
|
1323
|
+
var workerRuntimePlugin = {
|
|
1324
|
+
name: "worker-runtime",
|
|
1325
|
+
setup(build2) {
|
|
1326
|
+
build2.onResolve({ filter: /^worker-runtime$/ }, () => ({
|
|
1327
|
+
path: workerRuntimeBundlePath
|
|
1328
|
+
}));
|
|
1329
|
+
}
|
|
1330
|
+
};
|
|
1369
1331
|
async function compileManifest(manifestPath, destPath, options = {}) {
|
|
1370
1332
|
const rootPath = path.dirname(manifestPath);
|
|
1371
1333
|
const manifestContent = await readFile2(manifestPath, "utf-8");
|
|
@@ -1382,7 +1344,7 @@ async function compileManifest(manifestPath, destPath, options = {}) {
|
|
|
1382
1344
|
manifest.functions = {};
|
|
1383
1345
|
}
|
|
1384
1346
|
const jsFile = `
|
|
1385
|
-
import { setupMessageListener } from "
|
|
1347
|
+
import { setupMessageListener } from "worker-runtime";
|
|
1386
1348
|
|
|
1387
1349
|
// Imports
|
|
1388
1350
|
${Object.entries(manifest.functions).map(([funcName, def]) => {
|
|
@@ -1391,7 +1353,7 @@ ${Object.entries(manifest.functions).map(([funcName, def]) => {
|
|
|
1391
1353
|
}
|
|
1392
1354
|
let [filePath, jsFunctionName] = def.path.split(":");
|
|
1393
1355
|
filePath = path.join(rootPath, filePath);
|
|
1394
|
-
return `import {${jsFunctionName} as ${funcName}} from "
|
|
1356
|
+
return `import {${jsFunctionName} as ${funcName}} from "${// Replacing \ with / for Windows
|
|
1395
1357
|
path.resolve(filePath).replaceAll(
|
|
1396
1358
|
"\\",
|
|
1397
1359
|
"\\\\"
|
|
@@ -1432,18 +1394,14 @@ setupMessageListener(functionMapping, manifest, self.postMessage);
|
|
|
1432
1394
|
outfile: outFile,
|
|
1433
1395
|
metafile: options.info,
|
|
1434
1396
|
treeShaking: true,
|
|
1435
|
-
plugins: [
|
|
1436
|
-
denoPlugin({
|
|
1437
|
-
configPath: options.configPath && path.resolve(process.cwd(), options.configPath)
|
|
1438
|
-
})
|
|
1439
|
-
]
|
|
1397
|
+
plugins: [workerRuntimePlugin]
|
|
1440
1398
|
});
|
|
1441
1399
|
if (options.info) {
|
|
1442
1400
|
const text = await esbuild.analyzeMetafile(result.metafile);
|
|
1443
1401
|
console.log("Bundle info for", manifestPath, text);
|
|
1444
1402
|
}
|
|
1445
1403
|
let jsCode = await readFile2(outFile, "utf-8");
|
|
1446
|
-
jsCode =
|
|
1404
|
+
jsCode = patchBundledJS(jsCode);
|
|
1447
1405
|
await writeFile(outFile, jsCode, "utf-8");
|
|
1448
1406
|
await rm(tempDir, { recursive: true, force: true });
|
|
1449
1407
|
console.log(`Plug ${manifest.name} written to ${outFile}.`);
|
|
@@ -1478,18 +1436,16 @@ async function compileManifests(manifestFiles, dist, options = {}) {
|
|
|
1478
1436
|
}
|
|
1479
1437
|
await buildAll();
|
|
1480
1438
|
}
|
|
1481
|
-
function
|
|
1439
|
+
function patchBundledJS(code) {
|
|
1482
1440
|
return code.replaceAll("/(?<=\\n)/", "/()/");
|
|
1483
1441
|
}
|
|
1484
|
-
async function plugCompileCommand({ dist, debug, info
|
|
1442
|
+
async function plugCompileCommand({ dist, debug, info }, ...manifestPaths) {
|
|
1485
1443
|
await compileManifests(
|
|
1486
1444
|
manifestPaths,
|
|
1487
1445
|
dist,
|
|
1488
1446
|
{
|
|
1489
1447
|
debug,
|
|
1490
|
-
info
|
|
1491
|
-
runtimeUrl,
|
|
1492
|
-
configPath: config
|
|
1448
|
+
info
|
|
1493
1449
|
}
|
|
1494
1450
|
);
|
|
1495
1451
|
esbuild.stop();
|
|
@@ -1498,14 +1454,12 @@ async function plugCompileCommand({ dist, debug, info, config, runtimeUrl }, ...
|
|
|
1498
1454
|
|
|
1499
1455
|
// bin/plug-compile.ts
|
|
1500
1456
|
var program = new Command();
|
|
1501
|
-
program.name("plug-compile").description("Bundle (compile) one or more plug manifests").version(version).usage("<options> <manifest paths>").argument("<manifestPaths...>", "One or more .plug.yaml manifest files").option("--debug", "Do not minify code", false).option("--info", "Print out size info per function", false).option("-w, --watch", "Watch for changes and rebuild", false).option("--dist <path>", "Folder to put the resulting .plug.json file into", ".").
|
|
1457
|
+
program.name("plug-compile").description("Bundle (compile) one or more plug manifests").version(version).usage("<options> <manifest paths>").argument("<manifestPaths...>", "One or more .plug.yaml manifest files").option("--debug", "Do not minify code", false).option("--info", "Print out size info per function", false).option("-w, --watch", "Watch for changes and rebuild", false).option("--dist <path>", "Folder to put the resulting .plug.json file into", ".").action(async (manifestPaths, options) => {
|
|
1502
1458
|
await plugCompileCommand(
|
|
1503
1459
|
{
|
|
1504
1460
|
dist: options.dist,
|
|
1505
1461
|
debug: options.debug,
|
|
1506
|
-
info: options.info
|
|
1507
|
-
config: options.config,
|
|
1508
|
-
runtimeUrl: options.runtimeUrl
|
|
1462
|
+
info: options.info
|
|
1509
1463
|
},
|
|
1510
1464
|
...manifestPaths
|
|
1511
1465
|
);
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
// plug-api/lib/crypto.ts
|
|
2
|
+
function base64Decode(s) {
|
|
3
|
+
const binString = atob(s);
|
|
4
|
+
const len = binString.length;
|
|
5
|
+
const bytes = new Uint8Array(len);
|
|
6
|
+
for (let i = 0; i < len; i++) {
|
|
7
|
+
bytes[i] = binString.charCodeAt(i);
|
|
8
|
+
}
|
|
9
|
+
return bytes;
|
|
10
|
+
}
|
|
11
|
+
function base64Encode(buffer) {
|
|
12
|
+
if (typeof buffer === "string") {
|
|
13
|
+
buffer = new TextEncoder().encode(buffer);
|
|
14
|
+
}
|
|
15
|
+
let binary = "";
|
|
16
|
+
const len = buffer.byteLength;
|
|
17
|
+
for (let i = 0; i < len; i++) {
|
|
18
|
+
binary += String.fromCharCode(buffer[i]);
|
|
19
|
+
}
|
|
20
|
+
return btoa(binary);
|
|
21
|
+
}
|
|
22
|
+
var fixedCounter = new Uint8Array(16);
|
|
23
|
+
|
|
24
|
+
// client/lib/logger.ts
|
|
25
|
+
var Logger = class {
|
|
26
|
+
constructor(prefix = "", maxCaptureSize = 1e3) {
|
|
27
|
+
this.prefix = prefix;
|
|
28
|
+
this.maxCaptureSize = maxCaptureSize;
|
|
29
|
+
this.prefix = prefix;
|
|
30
|
+
this.originalConsole = {
|
|
31
|
+
log: console.log.bind(console),
|
|
32
|
+
info: console.info.bind(console),
|
|
33
|
+
warn: console.warn.bind(console),
|
|
34
|
+
error: console.error.bind(console),
|
|
35
|
+
debug: console.debug.bind(console)
|
|
36
|
+
};
|
|
37
|
+
this.patchConsole();
|
|
38
|
+
}
|
|
39
|
+
originalConsole;
|
|
40
|
+
logBuffer = [];
|
|
41
|
+
patchConsole() {
|
|
42
|
+
const createPatchedMethod = (level) => {
|
|
43
|
+
return (...args) => {
|
|
44
|
+
const prefixedArgs = this.prefix ? [this.prefix, ...args] : args;
|
|
45
|
+
this.originalConsole[level](...prefixedArgs);
|
|
46
|
+
this.captureLog(level, args);
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
console.log = createPatchedMethod("log");
|
|
50
|
+
console.info = createPatchedMethod("info");
|
|
51
|
+
console.warn = createPatchedMethod("warn");
|
|
52
|
+
console.error = createPatchedMethod("error");
|
|
53
|
+
console.debug = createPatchedMethod("debug");
|
|
54
|
+
}
|
|
55
|
+
captureLog(level, args) {
|
|
56
|
+
const entry = {
|
|
57
|
+
level,
|
|
58
|
+
timestamp: Date.now(),
|
|
59
|
+
message: args.map((arg) => {
|
|
60
|
+
if (typeof arg === "string") {
|
|
61
|
+
return arg;
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
return JSON.stringify(arg);
|
|
65
|
+
} catch {
|
|
66
|
+
return String(arg);
|
|
67
|
+
}
|
|
68
|
+
}).join(" ")
|
|
69
|
+
};
|
|
70
|
+
this.logBuffer.push(entry);
|
|
71
|
+
if (this.logBuffer.length > this.maxCaptureSize) {
|
|
72
|
+
this.logBuffer.shift();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Posts all buffered logs to a server endpoint
|
|
77
|
+
*/
|
|
78
|
+
async postToServer(logEndpoint, source) {
|
|
79
|
+
const logs = this.logBuffer;
|
|
80
|
+
if (logs.length > 0) {
|
|
81
|
+
const logCopy = [...this.logBuffer];
|
|
82
|
+
this.logBuffer = [];
|
|
83
|
+
try {
|
|
84
|
+
const resp = await fetch(logEndpoint, {
|
|
85
|
+
method: "POST",
|
|
86
|
+
headers: {
|
|
87
|
+
"Content-Type": "application/json"
|
|
88
|
+
},
|
|
89
|
+
body: JSON.stringify(logCopy.map((entry) => ({ ...entry, source })))
|
|
90
|
+
});
|
|
91
|
+
if (!resp.ok) {
|
|
92
|
+
throw new Error("Failed to post logs to server");
|
|
93
|
+
}
|
|
94
|
+
} catch (e) {
|
|
95
|
+
console.warn("Could not post logs to server", e.message);
|
|
96
|
+
this.logBuffer.unshift(...logCopy);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
var globalLogger;
|
|
102
|
+
function initLogger(prefix = "") {
|
|
103
|
+
globalLogger = new Logger(prefix);
|
|
104
|
+
return globalLogger;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// client/plugos/worker_runtime.ts
|
|
108
|
+
var workerPostMessage = (_msg) => {
|
|
109
|
+
throw new Error("Not initialized yet");
|
|
110
|
+
};
|
|
111
|
+
var runningAsWebWorker = typeof window === "undefined" && // @ts-expect-error: globalThis
|
|
112
|
+
typeof globalThis.WebSocketPair === "undefined";
|
|
113
|
+
var pendingRequests = /* @__PURE__ */ new Map();
|
|
114
|
+
var syscallReqId = 0;
|
|
115
|
+
if (runningAsWebWorker) {
|
|
116
|
+
globalThis.syscall = async (name, ...args) => {
|
|
117
|
+
return await new Promise((resolve, reject) => {
|
|
118
|
+
syscallReqId++;
|
|
119
|
+
pendingRequests.set(syscallReqId, { resolve, reject });
|
|
120
|
+
workerPostMessage({
|
|
121
|
+
type: "sys",
|
|
122
|
+
id: syscallReqId,
|
|
123
|
+
name,
|
|
124
|
+
args
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function setupMessageListener(functionMapping, manifest, postMessageFn) {
|
|
130
|
+
if (!runningAsWebWorker) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
workerPostMessage = postMessageFn;
|
|
134
|
+
self.addEventListener("message", (event) => {
|
|
135
|
+
(async () => {
|
|
136
|
+
const data = event.data;
|
|
137
|
+
switch (data.type) {
|
|
138
|
+
case "inv":
|
|
139
|
+
{
|
|
140
|
+
const fn = functionMapping[data.name];
|
|
141
|
+
if (!fn) {
|
|
142
|
+
throw new Error(`Function not loaded: ${data.name}`);
|
|
143
|
+
}
|
|
144
|
+
try {
|
|
145
|
+
const result = await Promise.resolve(fn(...data.args || []));
|
|
146
|
+
workerPostMessage({
|
|
147
|
+
type: "invr",
|
|
148
|
+
id: data.id,
|
|
149
|
+
result
|
|
150
|
+
});
|
|
151
|
+
} catch (e) {
|
|
152
|
+
console.error(
|
|
153
|
+
"An exception was thrown as a result of invoking function",
|
|
154
|
+
data.name,
|
|
155
|
+
"error:",
|
|
156
|
+
e.message
|
|
157
|
+
);
|
|
158
|
+
workerPostMessage({
|
|
159
|
+
type: "invr",
|
|
160
|
+
id: data.id,
|
|
161
|
+
error: e.message
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
break;
|
|
166
|
+
case "sysr":
|
|
167
|
+
{
|
|
168
|
+
const syscallId = data.id;
|
|
169
|
+
const lookup = pendingRequests.get(syscallId);
|
|
170
|
+
if (!lookup) {
|
|
171
|
+
throw Error("Invalid request id");
|
|
172
|
+
}
|
|
173
|
+
pendingRequests.delete(syscallId);
|
|
174
|
+
if (data.error) {
|
|
175
|
+
lookup.reject(new Error(data.error));
|
|
176
|
+
} else {
|
|
177
|
+
lookup.resolve(data.result);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
})().catch(console.error);
|
|
183
|
+
});
|
|
184
|
+
workerPostMessage({
|
|
185
|
+
type: "manifest",
|
|
186
|
+
manifest
|
|
187
|
+
});
|
|
188
|
+
initLogger(`[${manifest.name} plug]`);
|
|
189
|
+
}
|
|
190
|
+
async function sandboxFetch(reqInfo, options) {
|
|
191
|
+
if (typeof reqInfo !== "string") {
|
|
192
|
+
const body = new Uint8Array(await reqInfo.arrayBuffer());
|
|
193
|
+
const encodedBody = body.length > 0 ? base64Encode(body) : void 0;
|
|
194
|
+
options = {
|
|
195
|
+
method: reqInfo.method,
|
|
196
|
+
headers: Object.fromEntries(reqInfo.headers.entries()),
|
|
197
|
+
base64Body: encodedBody
|
|
198
|
+
};
|
|
199
|
+
reqInfo = reqInfo.url;
|
|
200
|
+
}
|
|
201
|
+
return syscall("sandboxFetch.fetch", reqInfo, options);
|
|
202
|
+
}
|
|
203
|
+
globalThis.nativeFetch = globalThis.fetch;
|
|
204
|
+
function monkeyPatchFetch() {
|
|
205
|
+
globalThis.fetch = async (reqInfo, init) => {
|
|
206
|
+
const encodedBody = init?.body ? base64Encode(
|
|
207
|
+
new Uint8Array(await new Response(init.body).arrayBuffer())
|
|
208
|
+
) : void 0;
|
|
209
|
+
const r = await sandboxFetch(
|
|
210
|
+
reqInfo,
|
|
211
|
+
init && {
|
|
212
|
+
method: init.method,
|
|
213
|
+
headers: init.headers,
|
|
214
|
+
base64Body: encodedBody
|
|
215
|
+
}
|
|
216
|
+
);
|
|
217
|
+
return new Response(
|
|
218
|
+
r.base64Body ? base64Decode(r.base64Body) : null,
|
|
219
|
+
{
|
|
220
|
+
status: r.status,
|
|
221
|
+
headers: r.headers
|
|
222
|
+
}
|
|
223
|
+
);
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
if (runningAsWebWorker) {
|
|
227
|
+
monkeyPatchFetch();
|
|
228
|
+
}
|
|
229
|
+
export {
|
|
230
|
+
monkeyPatchFetch,
|
|
231
|
+
sandboxFetch,
|
|
232
|
+
setupMessageListener
|
|
233
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@silverbulletmd/silverbullet",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A self-hosted, web-based note taking app",
|
|
6
6
|
"publishConfig": {
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"./lib/tags": "./plug-api/lib/tags.ts",
|
|
22
22
|
"./lib/transclusion": "./plug-api/lib/transclusion.ts",
|
|
23
23
|
"./lib/native_fetch": "./plug-api/lib/native_fetch.ts",
|
|
24
|
+
"./lib/query_expression": "./plug-api/lib/query_expression.ts",
|
|
24
25
|
"./type/client": "./plug-api/types/client.ts",
|
|
25
26
|
"./type/config": "./plug-api/types/config.ts",
|
|
26
27
|
"./type/manifest": "./plug-api/types/manifest.ts",
|
|
@@ -46,16 +47,18 @@
|
|
|
46
47
|
"!client/space_lua/**/*.bench.ts",
|
|
47
48
|
"client/markdown_parser/constants.ts",
|
|
48
49
|
"plugs/builtin_plugs.ts",
|
|
49
|
-
"dist/plug-compile.js"
|
|
50
|
+
"dist/plug-compile.js",
|
|
51
|
+
"dist/worker_runtime_bundle.js"
|
|
50
52
|
],
|
|
51
53
|
"scripts": {
|
|
52
|
-
"build": "npm run build:plugs && npm run build:client",
|
|
54
|
+
"build": "tsx build_worker_runtime.ts && npm run build:plugs && npm run build:client",
|
|
53
55
|
"build:plugs": "tsx build_plugs_libraries.ts",
|
|
54
56
|
"build:client": "tsx build_client.ts",
|
|
55
|
-
"build:plug-compile": "tsx build_plug_compile.ts",
|
|
57
|
+
"build:plug-compile": "tsx build_worker_runtime.ts && tsx build_plug_compile.ts",
|
|
56
58
|
"prepublishOnly": "npm run build:plug-compile",
|
|
57
59
|
"test": "vitest run",
|
|
58
60
|
"check": "tsc --noEmit",
|
|
61
|
+
"lint": "biome lint .",
|
|
59
62
|
"bench": "vitest bench"
|
|
60
63
|
},
|
|
61
64
|
"dependencies": {
|
|
@@ -102,6 +105,7 @@
|
|
|
102
105
|
"turndown": "7.2.2"
|
|
103
106
|
},
|
|
104
107
|
"devDependencies": {
|
|
108
|
+
"@biomejs/biome": "2.4.6",
|
|
105
109
|
"@preact/preset-vite": "^2.10.3",
|
|
106
110
|
"@types/gitignore-parser": "^0.0.3",
|
|
107
111
|
"@types/js-yaml": "^4.0.9",
|
|
@@ -115,6 +119,7 @@
|
|
|
115
119
|
"vitest": "^4.0.18"
|
|
116
120
|
},
|
|
117
121
|
"engines": {
|
|
118
|
-
"node": ">=
|
|
122
|
+
"node": ">=24.13.0",
|
|
123
|
+
"npm": ">=10.0.0"
|
|
119
124
|
}
|
|
120
125
|
}
|