@silverbulletmd/silverbullet 2.4.2 → 2.6.1

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.
Files changed (97) hide show
  1. package/README.md +19 -4
  2. package/client/asset_bundle/bundle.ts +3 -9
  3. package/client/data/datastore.ts +4 -5
  4. package/client/markdown_parser/constants.ts +5 -4
  5. package/client/plugos/hooks/code_widget.ts +3 -8
  6. package/client/plugos/hooks/command.ts +8 -8
  7. package/client/plugos/hooks/document_editor.ts +10 -15
  8. package/client/plugos/hooks/event.ts +33 -36
  9. package/client/plugos/hooks/mq.ts +17 -17
  10. package/client/plugos/hooks/plug_namespace.ts +3 -8
  11. package/client/plugos/hooks/slash_command.ts +13 -28
  12. package/client/plugos/hooks/syscall.ts +3 -3
  13. package/client/plugos/manifest_cache.ts +22 -15
  14. package/client/plugos/plug.ts +2 -6
  15. package/client/plugos/plug_compile.ts +79 -78
  16. package/client/plugos/protocol.ts +28 -28
  17. package/client/plugos/proxy_fetch.ts +7 -6
  18. package/client/plugos/sandboxes/web_worker_sandbox.ts +1 -1
  19. package/client/plugos/sandboxes/worker_sandbox.ts +18 -18
  20. package/client/plugos/syscalls/asset.ts +1 -3
  21. package/client/plugos/syscalls/code_widget.ts +1 -3
  22. package/client/plugos/syscalls/config.ts +1 -5
  23. package/client/plugos/syscalls/datastore.ts +1 -1
  24. package/client/plugos/syscalls/editor.ts +72 -69
  25. package/client/plugos/syscalls/event.ts +9 -12
  26. package/client/plugos/syscalls/fetch.ts +31 -23
  27. package/client/plugos/syscalls/index.ts +10 -1
  28. package/client/plugos/syscalls/jsonschema.ts +72 -32
  29. package/client/plugos/syscalls/language.ts +9 -5
  30. package/client/plugos/syscalls/markdown.ts +29 -7
  31. package/client/plugos/syscalls/mq.ts +4 -12
  32. package/client/plugos/syscalls/service_registry.ts +1 -4
  33. package/client/plugos/syscalls/shell.ts +2 -5
  34. package/client/plugos/syscalls/space.ts +1 -1
  35. package/client/plugos/syscalls/sync.ts +69 -60
  36. package/client/plugos/syscalls/system.ts +2 -3
  37. package/client/plugos/system.ts +6 -12
  38. package/client/plugos/worker_runtime.ts +12 -33
  39. package/client/space_lua/aggregates.ts +782 -0
  40. package/client/space_lua/ast.ts +42 -8
  41. package/client/space_lua/ast_narrow.ts +4 -2
  42. package/client/space_lua/eval.ts +886 -575
  43. package/client/space_lua/labels.ts +7 -12
  44. package/client/space_lua/liq_null.ts +6 -0
  45. package/client/space_lua/numeric.ts +5 -8
  46. package/client/space_lua/parse.ts +346 -120
  47. package/client/space_lua/query_collection.ts +926 -82
  48. package/client/space_lua/query_env.ts +26 -0
  49. package/client/space_lua/render_lua_markdown.ts +369 -0
  50. package/client/space_lua/rp.ts +5 -4
  51. package/client/space_lua/runtime.ts +288 -155
  52. package/client/space_lua/stdlib/format.ts +53 -39
  53. package/client/space_lua/stdlib/js.ts +3 -7
  54. package/client/space_lua/stdlib/load.ts +1 -3
  55. package/client/space_lua/stdlib/math.ts +84 -58
  56. package/client/space_lua/stdlib/net.ts +27 -17
  57. package/client/space_lua/stdlib/os.ts +81 -85
  58. package/client/space_lua/stdlib/pattern.ts +695 -0
  59. package/client/space_lua/stdlib/prng.ts +148 -0
  60. package/client/space_lua/stdlib/space_lua.ts +17 -23
  61. package/client/space_lua/stdlib/string.ts +102 -190
  62. package/client/space_lua/stdlib/string_pack.ts +490 -0
  63. package/client/space_lua/stdlib/table.ts +76 -16
  64. package/client/space_lua/stdlib.ts +53 -39
  65. package/client/space_lua/tonumber.ts +82 -42
  66. package/client/space_lua/util.ts +53 -15
  67. package/dist/plug-compile.js +55 -98
  68. package/package.json +27 -20
  69. package/plug-api/constants.ts +0 -32
  70. package/plug-api/lib/async.ts +20 -7
  71. package/plug-api/lib/crypto.ts +16 -17
  72. package/plug-api/lib/dates.ts +15 -7
  73. package/plug-api/lib/json.ts +11 -5
  74. package/plug-api/lib/limited_map.ts +1 -1
  75. package/plug-api/lib/native_fetch.ts +2 -0
  76. package/plug-api/lib/ref.ts +23 -23
  77. package/plug-api/lib/resolve.ts +7 -11
  78. package/plug-api/lib/tags.ts +13 -4
  79. package/plug-api/lib/transclusion.ts +10 -21
  80. package/plug-api/lib/tree.ts +165 -45
  81. package/plug-api/lib/yaml.ts +35 -25
  82. package/plug-api/syscalls/asset.ts +1 -1
  83. package/plug-api/syscalls/config.ts +1 -4
  84. package/plug-api/syscalls/editor.ts +15 -15
  85. package/plug-api/syscalls/jsonschema.ts +1 -3
  86. package/plug-api/syscalls/lua.ts +3 -9
  87. package/plug-api/syscalls/mq.ts +1 -4
  88. package/plug-api/syscalls/shell.ts +4 -1
  89. package/plug-api/syscalls/space.ts +3 -10
  90. package/plug-api/syscalls/system.ts +1 -4
  91. package/plug-api/syscalls/yaml.ts +2 -6
  92. package/plug-api/system_mock.ts +0 -1
  93. package/plug-api/types/client.ts +16 -1
  94. package/plug-api/types/event.ts +6 -4
  95. package/plug-api/types/manifest.ts +8 -9
  96. package/plugs/builtin_plugs.ts +2 -2
  97. package/client/plugos/sandboxes/deno_worker_sandbox.ts +0 -6
package/README.md CHANGED
@@ -2,6 +2,7 @@
2
2
  ![Docker Pulls](https://img.shields.io/docker/pulls/zefhemel/silverbullet)
3
3
  ![GitHub Downloads (all assets, all releases)](https://img.shields.io/github/downloads/silverbulletmd/silverbullet/total)
4
4
  ![GitHub contributors](https://img.shields.io/github/contributors/silverbulletmd/silverbullet)
5
+ [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/silverbulletmd/silverbullet)
5
6
 
6
7
  # SilverBullet
7
8
  SilverBullet is a Programmable, Private, Browser-based, Open Source, Self Hosted, Personal Knowledge Management Platform.
@@ -22,7 +23,7 @@ And if you are comfortable **programming** a little bit — now we’re really t
22
23
  Check out the [instructions](https://silverbullet.md/Install).
23
24
 
24
25
  ## Developing SilverBullet
25
- SilverBullet's frontend is written in [TypeScript](https://www.typescriptlang.org/) and built on top of the excellent [CodeMirror 6](https://codemirror.net/) editor component. Additional UI is built using [Preact](https://preactjs.com). [ESBuild](https://esbuild.github.io)) running through Deno is used to build both the front-end.
26
+ SilverBullet's frontend is written in [TypeScript](https://www.typescriptlang.org/) and built on top of the excellent [CodeMirror 6](https://codemirror.net/) editor component. Additional UI is built using [Preact](https://preactjs.com). [ESBuild](https://esbuild.github.io) is used to build the frontend.
26
27
 
27
28
  The server backend is written in Go.
28
29
 
@@ -43,9 +44,15 @@ If you're considering contributing changes, be aware of the [LLM use policy](htt
43
44
  * `website/`: silverbullet.md website content
44
45
 
45
46
  ### Requirements
46
- * [Deno](https://deno.com/): Used to build the frontend and plugs
47
+ * [Node.js](https://nodejs.org/) 24+ and npm 10+: Used to build the frontend and plugs
47
48
  * [Go](https://go.dev/): Used to build the backend
48
49
 
50
+ The project includes `.nvmrc` and `.node-version` files. If you use [nvm](https://github.com/nvm-sh/nvm) or another Node version manager, it will automatically use the correct Node.js version:
51
+
52
+ ```shell
53
+ nvm use # If using nvm
54
+ ```
55
+
49
56
  It's convenient to also install [air](https://github.com/air-verse/air) for development, this will automatically rebuild both the frontend and backend when changes are made:
50
57
 
51
58
  ```shell
@@ -53,7 +60,13 @@ go install github.com/air-verse/air@latest
53
60
  ```
54
61
  Make sure your `$GOPATH/bin` is in your $PATH.
55
62
 
56
- To build everything and run the server:
63
+ First, install dependencies:
64
+
65
+ ```shell
66
+ make setup
67
+ ```
68
+
69
+ To build everything and run the server (which automatically restarts upon file changing):
57
70
 
58
71
  ```shell
59
72
  air <PATH-TO-YOUR-SPACE>
@@ -82,10 +95,12 @@ make check
82
95
  make fmt
83
96
  # Run all tests
84
97
  make test
98
+ # Run benchmarks
99
+ make bench
85
100
  ```
86
101
 
87
102
  ### Build a docker container
88
- Note, you do not need Deno nor Go locally installed for this to work:
103
+ Note, you do not need Node.js nor Go locally installed for this to work:
89
104
 
90
105
  ```shell
91
106
  docker build -t silverbullet .
@@ -23,9 +23,7 @@ export class AssetBundle {
23
23
  return Object.keys(this.bundle);
24
24
  }
25
25
 
26
- readFileSync(
27
- path: string,
28
- ): Uint8Array {
26
+ readFileSync(path: string): Uint8Array {
29
27
  const content = this.bundle[path];
30
28
  if (!content) {
31
29
  throw new Error(`No such file ${path}`);
@@ -42,15 +40,11 @@ export class AssetBundle {
42
40
  return content.data;
43
41
  }
44
42
 
45
- readTextFileSync(
46
- path: string,
47
- ): string {
43
+ readTextFileSync(path: string): string {
48
44
  return new TextDecoder().decode(this.readFileSync(path));
49
45
  }
50
46
 
51
- getMimeType(
52
- path: string,
53
- ): string {
47
+ getMimeType(path: string): string {
54
48
  const entry = this.bundle[path];
55
49
  if (!entry) {
56
50
  throw new Error(`No such file ${path}`);
@@ -4,6 +4,7 @@ import {
4
4
  } from "../space_lua/query_collection.ts";
5
5
  import { LuaEnv, LuaStackFrame } from "../space_lua/runtime.ts";
6
6
  import type { KvPrimitives, KvQueryOptions } from "./kv_primitives.ts";
7
+ import type { Config } from "../config.ts";
7
8
 
8
9
  import type { KV, KvKey } from "../../plug-api/types/datastore.ts";
9
10
 
@@ -12,10 +13,7 @@ import type { KV, KvKey } from "../../plug-api/types/datastore.ts";
12
13
  * in a more user-friendly way
13
14
  */
14
15
  export class DataStore {
15
- constructor(
16
- readonly kv: KvPrimitives,
17
- ) {
18
- }
16
+ constructor(readonly kv: KvPrimitives) {}
19
17
 
20
18
  async get<T = any>(key: KvKey): Promise<T | null> {
21
19
  return (await this.batchGet([key]))[0];
@@ -79,7 +77,8 @@ export class DataStore {
79
77
  env: LuaEnv = new LuaEnv(),
80
78
  sf: LuaStackFrame = LuaStackFrame.lostFrame,
81
79
  enricher?: (key: KvKey, item: any) => any,
80
+ config?: Config,
82
81
  ): Promise<T[]> {
83
- return queryLua(this.kv, prefix, query, env, sf, enricher);
82
+ return queryLua(this.kv, prefix, query, env, sf, enricher, config);
84
83
  }
85
84
  }
@@ -1,13 +1,14 @@
1
1
  export const wikiLinkRegex =
2
2
  /(?<leadingTrivia>!?\[\[)(?<stringRef>.*?)(?:\|(?<alias>.*?))?(?<trailingTrivia>\]\])/g;
3
- export const mdLinkRegex = /!?\[(?<title>[^\]]*)\]\((?<url>.+)\)/g;
3
+ export const mdLinkRegex =
4
+ /!?\[(?<title>[^\]\\]*(?:\\.[^\]\\]*)*)\]\((?<url>.+)\)/g;
4
5
  export const tagRegex =
5
6
  /#(?:(?:\d*[^\d\s!@#$%^&*(),.?":{}|<>\\][^\s!@#$%^&*(),.?":{}|<>\\]*)|(?:<[^>\n]+>))/;
6
7
  export const nakedUrlRegex =
7
- /(^https?:\/\/([-a-zA-Z0-9@:%_\+~#=]|(?:[.](?!(\s|$)))){1,256})(([-a-zA-Z0-9(@:%_\+~#?&=\/]|(?:[.,:;)](?!(\s|$))))*)/;
8
+ /(^https?:\/\/([-a-zA-Z0-9@:%_+~#=]|(?:[.](?!(\s|$)))){1,256})(([-a-zA-Z0-9(@:%_+~#?&=/]|(?:[.,:;)](?!(\s|$))))*)/;
8
9
  export const frontmatterQuotesRegex = /["'].*["']/g;
9
10
  export const frontmatterUrlRegex = /([a-zA-Z][a-zA-Z0-9+.-]*:\/\/[^\s"']+)/g;
10
11
  export const frontmatterWikiLinkRegex =
11
12
  /(?<leadingTrivia>!?\[\[)(?<stringRef>.*?)(?:\|(?<alias>.*?))?(?<trailingTrivia>\]\])/g;
12
- export const frontmatterMailtoRegex = /(mailto:[^@\s]+@[^@\s"']+)/ig;
13
- export const pWikiLinkRegex = new RegExp("^" + wikiLinkRegex.source); // Modified regex used only in parser
13
+ export const frontmatterMailtoRegex = /(mailto:[^@\s]+@[^@\s"']+)/gi;
14
+ export const pWikiLinkRegex = new RegExp(`^${wikiLinkRegex.source}`); // Modified regex used only in parser
@@ -7,17 +7,12 @@ export class CodeWidgetHook implements Hook<CodeWidgetT> {
7
7
  codeWidgetCallbacks = new Map<string, CodeWidgetCallback>();
8
8
  codeWidgetModes = new Map<string, "markdown" | "iframe">();
9
9
 
10
- constructor() {
11
- }
12
-
13
10
  collectAllCodeWidgets(system: System<CodeWidgetT>) {
14
11
  this.codeWidgetCallbacks.clear();
15
12
  for (const plug of system.loadedPlugs.values()) {
16
- for (
17
- const [name, functionDef] of Object.entries(
18
- plug.manifest!.functions,
19
- )
20
- ) {
13
+ for (const [name, functionDef] of Object.entries(
14
+ plug.manifest!.functions,
15
+ )) {
21
16
  if (!functionDef.codeWidget) {
22
17
  continue;
23
18
  }
@@ -5,8 +5,10 @@ import { throttle } from "@silverbulletmd/silverbullet/lib/async";
5
5
  import type { Command, CommandHookEvents } from "../../types/command.ts";
6
6
  import type { CommandHookT } from "@silverbulletmd/silverbullet/type/manifest";
7
7
 
8
- export class CommandHook extends EventEmitter<CommandHookEvents>
9
- implements Hook<CommandHookT> {
8
+ export class CommandHook
9
+ extends EventEmitter<CommandHookEvents>
10
+ implements Hook<CommandHookT>
11
+ {
10
12
  system?: System<CommandHookT>;
11
13
  public throttledBuildAllCommandsAndEmit = throttle(() => {
12
14
  this.buildAllCommandsAndEmit();
@@ -30,11 +32,9 @@ export class CommandHook extends EventEmitter<CommandHookEvents>
30
32
  return commands;
31
33
  }
32
34
  for (const plug of this.system.loadedPlugs.values()) {
33
- for (
34
- const [name, functionDef] of Object.entries(
35
- plug.manifest!.functions,
36
- )
37
- ) {
35
+ for (const [name, functionDef] of Object.entries(
36
+ plug.manifest!.functions,
37
+ )) {
38
38
  if (!functionDef.command) {
39
39
  continue;
40
40
  }
@@ -46,7 +46,7 @@ export class CommandHook extends EventEmitter<CommandHookEvents>
46
46
  commands.set(cmd.name, {
47
47
  ...cmd,
48
48
  run: (args?: string[]) => {
49
- return plug.invoke(name, [cmd, ...args ?? []]);
49
+ return plug.invoke(name, [cmd, ...(args ?? [])]);
50
50
  },
51
51
  });
52
52
  }
@@ -9,17 +9,12 @@ export class DocumentEditorHook implements Hook<DocumentEditorT> {
9
9
  { extensions: string[]; callback: DocumentEditorCallback }
10
10
  >();
11
11
 
12
- constructor() {
13
- }
14
-
15
12
  collectAllDocumentEditors(system: System<DocumentEditorT>) {
16
13
  this.documentEditors.clear();
17
14
  for (const plug of system.loadedPlugs.values()) {
18
- for (
19
- const [name, functionDef] of Object.entries(
20
- plug.manifest!.functions,
21
- )
22
- ) {
15
+ for (const [name, functionDef] of Object.entries(
16
+ plug.manifest!.functions,
17
+ )) {
23
18
  if (!functionDef.editor) {
24
19
  continue;
25
20
  }
@@ -28,9 +23,9 @@ export class DocumentEditorHook implements Hook<DocumentEditorT> {
28
23
  ? functionDef.editor
29
24
  : [functionDef.editor];
30
25
 
31
- const conflict = Array.from(this.documentEditors.entries()).find((
32
- [_, { extensions }],
33
- ) => keys.some((key) => extensions.includes(key)));
26
+ const conflict = Array.from(this.documentEditors.entries()).find(
27
+ ([_, { extensions }]) => keys.some((key) => extensions.includes(key)),
28
+ );
34
29
 
35
30
  if (conflict) {
36
31
  console.log(
@@ -40,10 +35,10 @@ export class DocumentEditorHook implements Hook<DocumentEditorT> {
40
35
  );
41
36
  }
42
37
 
43
- this.documentEditors.set(
44
- name,
45
- { extensions: keys, callback: () => plug.invoke(name, []) },
46
- );
38
+ this.documentEditors.set(name, {
39
+ extensions: keys,
40
+ callback: () => plug.invoke(name, []),
41
+ });
47
42
  }
48
43
  }
49
44
  }
@@ -1,4 +1,3 @@
1
- // deno-lint-ignore-file ban-types
2
1
  import type { Manifest } from "../types.ts";
3
2
  import type { System } from "../system.ts";
4
3
  import type { EventHookI } from "../eventhook.ts";
@@ -12,8 +11,7 @@ export class EventHook implements EventHookI {
12
11
  private system?: System<EventHookT>;
13
12
  private localListeners: Map<string, ((...args: any[]) => any)[]> = new Map();
14
13
 
15
- constructor(readonly config?: Config) {
16
- }
14
+ constructor(readonly config?: Config) {}
17
15
 
18
16
  addLocalListener(eventName: string, callback: (...args: any[]) => any) {
19
17
  if (!this.localListeners.has(eventName)) {
@@ -74,29 +72,28 @@ export class EventHook implements EventHookI {
74
72
  const promises: Promise<any>[] = [];
75
73
  for (const plug of this.system.loadedPlugs.values()) {
76
74
  const manifest = plug.manifest;
77
- for (
78
- const [name, functionDef] of Object.entries(
79
- manifest!.functions,
80
- )
81
- ) {
75
+ for (const [name, functionDef] of Object.entries(manifest!.functions)) {
82
76
  if (functionDef.events) {
83
77
  for (const event of functionDef.events) {
84
78
  if (
85
- event === eventName || eventNameToRegex(event).test(eventName)
79
+ event === eventName ||
80
+ eventNameToRegex(event).test(eventName)
86
81
  ) {
87
82
  // Only dispatch functions that can run in this environment
88
83
  if (plug.canInvoke(name)) {
89
84
  // Queue the promise
90
- promises.push((async () => {
91
- try {
92
- return await plug.invoke(name, args);
93
- } catch (e: any) {
94
- console.error(
95
- `Error dispatching event ${eventName} to ${plug.manifest.name}.${name}: ${e.message}`,
96
- );
97
- throw e;
98
- }
99
- })());
85
+ promises.push(
86
+ (async () => {
87
+ try {
88
+ return await plug.invoke(name, args);
89
+ } catch (e: any) {
90
+ console.error(
91
+ `Error dispatching event ${eventName} to ${plug.manifest.name}.${name}: ${e.message}`,
92
+ );
93
+ throw e;
94
+ }
95
+ })(),
96
+ );
100
97
  }
101
98
  }
102
99
  }
@@ -109,9 +106,11 @@ export class EventHook implements EventHookI {
109
106
  if (eventNameToRegex(name).test(eventName)) {
110
107
  for (const localListener of localListeners) {
111
108
  // Queue the promise
112
- promises.push((async () => {
113
- return await Promise.resolve(localListener(...args));
114
- })());
109
+ promises.push(
110
+ (async () => {
111
+ return await Promise.resolve(localListener(...args));
112
+ })(),
113
+ );
115
114
  }
116
115
  }
117
116
  }
@@ -125,15 +124,17 @@ export class EventHook implements EventHookI {
125
124
  for (const [name, listeners] of Object.entries(configListeners)) {
126
125
  if (eventNameToRegex(name).test(eventName)) {
127
126
  for (const listener of listeners) {
128
- promises.push((async () => {
129
- return await Promise.resolve(
130
- listener({
131
- name: eventName,
132
- // Most events have a single argument, so let's optimize for that, otherwise pass all arguments as an array
133
- data: args.length === 1 ? args[0] : args,
134
- }),
135
- );
136
- })());
127
+ promises.push(
128
+ (async () => {
129
+ return await Promise.resolve(
130
+ listener({
131
+ name: eventName,
132
+ // Most events have a single argument, so let's optimize for that, otherwise pass all arguments as an array
133
+ data: args.length === 1 ? args[0] : args,
134
+ }),
135
+ );
136
+ })(),
137
+ );
137
138
  }
138
139
  }
139
140
  }
@@ -167,11 +168,7 @@ export class EventHook implements EventHookI {
167
168
 
168
169
  validateManifest(manifest: Manifest<EventHookT>): string[] {
169
170
  const errors = [];
170
- for (
171
- const [_, functionDef] of Object.entries(
172
- manifest.functions || {},
173
- )
174
- ) {
171
+ for (const [_, functionDef] of Object.entries(manifest.functions || {})) {
175
172
  if (functionDef.events && !Array.isArray(functionDef.events)) {
176
173
  errors.push("'events' key must be an array of strings");
177
174
  }
@@ -1,4 +1,3 @@
1
- // deno-lint-ignore-file ban-types
2
1
  import type { Hook, Manifest } from "../types.ts";
3
2
  import type { System } from "../system.ts";
4
3
  import { throttle } from "@silverbulletmd/silverbullet/lib/async";
@@ -10,13 +9,11 @@ import type {
10
9
  } from "@silverbulletmd/silverbullet/type/datastore";
11
10
  import type { Config } from "../../config.ts";
12
11
 
13
- export type MQListenerSpec =
14
- & MQSubscribeOptions
15
- & {
16
- queue: string;
17
- autoAck?: boolean;
18
- run: Function;
19
- };
12
+ export type MQListenerSpec = MQSubscribeOptions & {
13
+ queue: string;
14
+ autoAck?: boolean;
15
+ run: Function;
16
+ };
20
17
 
21
18
  export class MQHook implements Hook<MQHookT> {
22
19
  subscriptions: QueueWorker[] = [];
@@ -28,8 +25,7 @@ export class MQHook implements Hook<MQHookT> {
28
25
  private system: System<MQHookT>,
29
26
  readonly mq: DataStoreMQ,
30
27
  readonly config: Config,
31
- ) {
32
- }
28
+ ) {}
33
29
 
34
30
  apply(system: System<MQHookT>): void {
35
31
  this.system = system;
@@ -57,11 +53,9 @@ export class MQHook implements Hook<MQHookT> {
57
53
  if (!plug.manifest) {
58
54
  continue;
59
55
  }
60
- for (
61
- const [name, functionDef] of Object.entries(
62
- plug.manifest.functions,
63
- )
64
- ) {
56
+ for (const [name, functionDef] of Object.entries(
57
+ plug.manifest.functions,
58
+ )) {
65
59
  if (!functionDef.mqSubscriptions) {
66
60
  continue;
67
61
  }
@@ -79,7 +73,10 @@ export class MQHook implements Hook<MQHookT> {
79
73
  try {
80
74
  await plug.invoke(name, [messages]);
81
75
  if (subscriptionDef.autoAck) {
82
- await this.mq.batchAck(queue, messages.map((m) => m.id));
76
+ await this.mq.batchAck(
77
+ queue,
78
+ messages.map((m) => m.id),
79
+ );
83
80
  }
84
81
  } catch (e: any) {
85
82
  console.error(
@@ -118,7 +115,10 @@ export class MQHook implements Hook<MQHookT> {
118
115
  try {
119
116
  await listener.run(messages);
120
117
  if (listener.autoAck) {
121
- await this.mq.batchAck(queue, messages.map((m) => m.id));
118
+ await this.mq.batchAck(
119
+ queue,
120
+ messages.map((m) => m.id),
121
+ );
122
122
  }
123
123
  } catch (e: any) {
124
124
  console.error(
@@ -15,9 +15,6 @@ type SpaceFunction = {
15
15
  export class PlugNamespaceHook implements Hook<PlugNamespaceHookT> {
16
16
  spaceFunctions: SpaceFunction[] = [];
17
17
 
18
- constructor() {
19
- }
20
-
21
18
  apply(system: System<PlugNamespaceHookT>): void {
22
19
  system.on({
23
20
  plugLoaded: () => {
@@ -33,11 +30,9 @@ export class PlugNamespaceHook implements Hook<PlugNamespaceHookT> {
33
30
  this.spaceFunctions = [];
34
31
  for (const plug of system.loadedPlugs.values()) {
35
32
  if (plug.manifest?.functions) {
36
- for (
37
- const [funcName, funcDef] of Object.entries(
38
- plug.manifest.functions,
39
- )
40
- ) {
33
+ for (const [funcName, funcDef] of Object.entries(
34
+ plug.manifest.functions,
35
+ )) {
41
36
  if (funcDef.pageNamespace) {
42
37
  this.spaceFunctions.push({
43
38
  operation: funcDef.pageNamespace.operation,
@@ -15,7 +15,7 @@ import type {
15
15
  SlashCompletions,
16
16
  } from "@silverbulletmd/silverbullet/type/client";
17
17
 
18
- const slashCommandRegexp = /([^\w:]|^)\/[\w#\-]*/;
18
+ const slashCommandRegexp = /([^\w:]|^)\/[\w#-]*/;
19
19
 
20
20
  export class SlashCommandHook implements Hook<SlashCommandHookT> {
21
21
  slashCommands: SlashCommand[] = [];
@@ -23,8 +23,7 @@ export class SlashCommandHook implements Hook<SlashCommandHookT> {
23
23
  this.buildAllCommands();
24
24
  }, 200);
25
25
 
26
- constructor(private client: Client) {
27
- }
26
+ constructor(private client: Client) {}
28
27
 
29
28
  buildAllCommands() {
30
29
  const clientSystem = this.client.clientSystem;
@@ -32,11 +31,9 @@ export class SlashCommandHook implements Hook<SlashCommandHookT> {
32
31
 
33
32
  this.slashCommands = [];
34
33
  for (const plug of system.loadedPlugs.values()) {
35
- for (
36
- const [name, functionDef] of Object.entries(
37
- plug.manifest!.functions,
38
- )
39
- ) {
34
+ for (const [name, functionDef] of Object.entries(
35
+ plug.manifest!.functions,
36
+ )) {
40
37
  if (!functionDef.slashCommand) {
41
38
  continue;
42
39
  }
@@ -50,14 +47,9 @@ export class SlashCommandHook implements Hook<SlashCommandHookT> {
50
47
  }
51
48
  }
52
49
  // Iterate over script defined slash commands
53
- for (
54
- const command of Object.values(
55
- this.client.config.get<Record<string, SlashCommand>>(
56
- "slashCommands",
57
- {},
58
- ),
59
- )
60
- ) {
50
+ for (const command of Object.values(
51
+ this.client.config.get<Record<string, SlashCommand>>("slashCommands", {}),
52
+ )) {
61
53
  this.slashCommands.push(command);
62
54
  }
63
55
  }
@@ -88,14 +80,14 @@ export class SlashCommandHook implements Hook<SlashCommandHookT> {
88
80
  if (
89
81
  def.onlyContexts &&
90
82
  !def.onlyContexts.some((context) =>
91
- parentNodes.some((node) => node.startsWith(context))
83
+ parentNodes.some((node) => node.startsWith(context)),
92
84
  )
93
85
  ) {
94
86
  continue;
95
87
  }
96
88
  if (
97
- def.exceptContexts && def.exceptContexts.some(
98
- (context) => parentNodes.some((node) => node.startsWith(context)),
89
+ def.exceptContexts?.some((context) =>
90
+ parentNodes.some((node) => node.startsWith(context)),
99
91
  )
100
92
  ) {
101
93
  continue;
@@ -123,17 +115,10 @@ export class SlashCommandHook implements Hook<SlashCommandHookT> {
123
115
  }
124
116
 
125
117
  const slashCompletions: CompletionResult | SlashCompletions | null =
126
- await this.client
127
- .completeWithEvent(
128
- ctx,
129
- "slash:complete",
130
- );
118
+ await this.client.completeWithEvent(ctx, "slash:complete");
131
119
 
132
120
  if (slashCompletions) {
133
- for (
134
- const slashCompletion of slashCompletions
135
- .options as SlashCompletionOption[]
136
- ) {
121
+ for (const slashCompletion of slashCompletions.options as SlashCompletionOption[]) {
137
122
  options.push({
138
123
  label: slashCompletion.label,
139
124
  detail: slashCompletion.detail,
@@ -17,9 +17,9 @@ export class SyscallHook implements Hook<SyscallHookT> {
17
17
  for (const plug of system.loadedPlugs.values()) {
18
18
  const syscalls: SysCallMapping = {};
19
19
 
20
- for (
21
- const [name, functionDef] of Object.entries(plug.manifest!.functions)
22
- ) {
20
+ for (const [name, functionDef] of Object.entries(
21
+ plug.manifest!.functions,
22
+ )) {
23
23
  if (!functionDef.syscall) {
24
24
  continue;
25
25
  }
@@ -11,38 +11,45 @@ export interface ManifestCache<T> {
11
11
  }
12
12
 
13
13
  export class KVPrimitivesManifestCache<T> implements ManifestCache<T> {
14
- constructor(private kv: KvPrimitives, private manifestPrefix: string) {
15
- }
14
+ constructor(
15
+ private kv: KvPrimitives,
16
+ private manifestPrefix: string,
17
+ ) {}
16
18
 
17
19
  async getManifest(
18
20
  plug: Plug<T>,
19
21
  cacheKey: string,
20
22
  cacheHash: number,
21
23
  ): Promise<Manifest<T>> {
22
- const [cached] = await this.kv.batchGet([[
23
- this.manifestPrefix,
24
- cacheKey,
25
- ]]);
24
+ const [cached] = await this.kv.batchGet([[this.manifestPrefix, cacheKey]]);
26
25
  if (cached && cached.hash === cacheHash) {
27
26
  // console.log("Using KV cached manifest for", plug.name);
28
27
  return cached.manifest;
29
28
  }
30
29
  await plug.sandbox.init();
31
30
  const manifest = plug.sandbox.manifest!;
32
- await this.kv.batchSet([{
33
- key: [this.manifestPrefix, cacheKey],
34
- // Deliverately removing the assets from the manifest to preserve space, will be re-added upon load of actual worker
35
- value: { manifest: { ...manifest, assets: undefined }, hash: cacheHash },
36
- }]);
31
+ await this.kv.batchSet([
32
+ {
33
+ key: [this.manifestPrefix, cacheKey],
34
+ // Deliverately removing the assets from the manifest to preserve space, will be re-added upon load of actual worker
35
+ value: {
36
+ manifest: { ...manifest, assets: undefined },
37
+ hash: cacheHash,
38
+ },
39
+ },
40
+ ]);
37
41
  return manifest;
38
42
  }
39
43
  }
40
44
 
41
45
  export class InMemoryManifestCache<T> implements ManifestCache<T> {
42
- private cache = new Map<string, {
43
- manifest: Manifest<T>;
44
- hash: number;
45
- }>();
46
+ private cache = new Map<
47
+ string,
48
+ {
49
+ manifest: Manifest<T>;
50
+ hash: number;
51
+ }
52
+ >();
46
53
 
47
54
  async getManifest(
48
55
  plug: Plug<T>,
@@ -26,10 +26,7 @@ export class Plug<HookT> {
26
26
  cacheHash: number,
27
27
  sandboxFactory: SandboxFactory<HookT>,
28
28
  ): Promise<Plug<HookT>> {
29
- const plug = new Plug(
30
- system,
31
- sandboxFactory,
32
- );
29
+ const plug = new Plug(system, sandboxFactory);
33
30
 
34
31
  // Retrieve the manifest, which may either come from a cache or be loaded from the worker
35
32
  plug.manifest = await system.options.manifestCache!.getManifest(
@@ -70,7 +67,6 @@ export class Plug<HookT> {
70
67
  const sandbox = this.sandbox!;
71
68
  if (funDef.redirect) {
72
69
  // Function redirect, look up
73
- // deno-lint-ignore no-this-alias
74
70
  let plug: Plug<HookT> | undefined = this;
75
71
  if (funDef.redirect.indexOf(".") !== -1) {
76
72
  const [plugName, functionName] = funDef.redirect.split(".");
@@ -84,7 +80,7 @@ export class Plug<HookT> {
84
80
  }
85
81
  return plug.invoke(name, args);
86
82
  }
87
- if (!await this.canInvoke(name)) {
83
+ if (!(await this.canInvoke(name))) {
88
84
  throw new Error(
89
85
  `Function ${name} is not available in ${this.runtimeEnv}`,
90
86
  );