@silverbulletmd/silverbullet 2.9.0 → 2.10.0

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 (63) hide show
  1. package/README.md +36 -23
  2. package/client/plugos/hooks/syscall.ts +24 -10
  3. package/client/plugos/syscalls/asset.ts +61 -23
  4. package/client/plugos/syscalls/clientStore.ts +32 -6
  5. package/client/plugos/syscalls/client_code_widget.ts +9 -4
  6. package/client/plugos/syscalls/code_widget.ts +26 -11
  7. package/client/plugos/syscalls/config.ts +146 -30
  8. package/client/plugos/syscalls/datastore.ts +146 -40
  9. package/client/plugos/syscalls/editor.ts +1432 -711
  10. package/client/plugos/syscalls/event.ts +46 -13
  11. package/client/plugos/syscalls/fetch.ts +123 -82
  12. package/client/plugos/syscalls/index.ts +242 -116
  13. package/client/plugos/syscalls/jsonschema.ts +107 -8
  14. package/client/plugos/syscalls/language.ts +38 -12
  15. package/client/plugos/syscalls/markdown.ts +166 -50
  16. package/client/plugos/syscalls/mq.ts +93 -20
  17. package/client/plugos/syscalls/schema_introspection.ts +33 -0
  18. package/client/plugos/syscalls/service_registry.ts +74 -20
  19. package/client/plugos/syscalls/shell.ts +51 -20
  20. package/client/plugos/syscalls/space.ts +169 -113
  21. package/client/plugos/syscalls/sync.ts +50 -19
  22. package/client/plugos/syscalls/system.ts +236 -139
  23. package/client/plugos/system.ts +21 -5
  24. package/client/space_lua/api_documentation.ts +107 -0
  25. package/client/space_lua/ast.ts +13 -0
  26. package/client/space_lua/eval.ts +12 -4
  27. package/client/space_lua/parse.ts +243 -108
  28. package/client/space_lua/pretty_print.ts +128 -54
  29. package/client/space_lua/query_collection.ts +4 -4
  30. package/client/space_lua/render_widget.ts +156 -0
  31. package/client/space_lua/runtime.ts +83 -22
  32. package/client/space_lua/stdlib/crypto.ts +8 -3
  33. package/client/space_lua/stdlib/encoding.ts +27 -9
  34. package/client/space_lua/stdlib/js.ts +137 -22
  35. package/client/space_lua/stdlib/load.ts +24 -15
  36. package/client/space_lua/stdlib/math.ts +323 -118
  37. package/client/space_lua/stdlib/net.ts +57 -9
  38. package/client/space_lua/stdlib/os.ts +111 -44
  39. package/client/space_lua/stdlib/space_lua.ts +344 -20
  40. package/client/space_lua/stdlib/string.ts +282 -104
  41. package/client/space_lua/stdlib/string_pack.ts +58 -19
  42. package/client/space_lua/stdlib/table.ts +195 -40
  43. package/client/space_lua/stdlib.ts +335 -93
  44. package/client/space_lua/syscalls.ts +270 -0
  45. package/dist/plug-compile.js +1 -1
  46. package/package.json +3 -3
  47. package/plug-api/lib/ref.ts +96 -0
  48. package/plug-api/lib/shortcut.ts +2 -1
  49. package/plug-api/syscalls/config.ts +5 -3
  50. package/plug-api/syscalls/editor.ts +16 -0
  51. package/plug-api/syscalls/index.ts +17 -1
  52. package/plug-api/syscalls/jsonschema.ts +9 -0
  53. package/plug-api/syscalls/lua.ts +7 -0
  54. package/plug-api/syscalls/shell.ts +0 -1
  55. package/plug-api/syscalls/system.ts +7 -0
  56. package/plug-api/system_mock.ts +2 -2
  57. package/plug-api/types/index.ts +52 -1
  58. package/plug-api/types/manifest.ts +22 -4
  59. package/plug-api/ui/cx.ts +1 -3
  60. package/plug-api/ui/index.ts +3 -0
  61. package/plug-api/ui/panel_styles.ts +4 -3
  62. package/plug-api/ui/slugify.ts +44 -0
  63. package/client/plugos/syscalls/lua.ts +0 -81
@@ -10,130 +10,186 @@ import type {
10
10
 
11
11
  export function spaceReadSyscalls(client: Client): SysCallMapping {
12
12
  return {
13
- "space.listPages": (): Promise<PageMeta[]> => {
14
- return client.space.fetchPageList();
15
- },
16
- "space.readPage": async (_ctx, name: string): Promise<string> => {
17
- return (await client.space.readPage(name)).text;
18
- },
19
- "space.readPageWithMeta": (
20
- _ctx,
21
- name: string,
22
- ): Promise<{ text: string; meta: PageMeta }> => {
23
- return client.space.readPage(name);
24
- },
25
- "space.readRef": async (_ctx, ref: string | Ref): Promise<string> => {
26
- if (typeof ref === "string") {
27
- ref = parseToRef(ref)!;
28
- if (!ref) {
29
- throw new Error(`Invalid ref: ${ref}`);
13
+ "space.listPages": {
14
+ callback: (): Promise<PageMeta[]> => client.space.fetchPageList(),
15
+ description: "Lists all pages in the space.",
16
+ },
17
+ "space.readPage": {
18
+ callback: async (_ctx, name: string): Promise<string> =>
19
+ (await client.space.readPage(name)).text,
20
+ description: "Reads a page and returns its Markdown text.",
21
+ signatures: ["space.readPage(name)"],
22
+ },
23
+ "space.readPageWithMeta": {
24
+ callback: (
25
+ _ctx,
26
+ name: string,
27
+ ): Promise<{ text: string; meta: PageMeta }> =>
28
+ client.space.readPage(name),
29
+ description:
30
+ "Reads a page and returns both its Markdown text and metadata.",
31
+ signatures: ["space.readPageWithMeta(name)"],
32
+ },
33
+ "space.readRef": {
34
+ callback: async (_ctx, ref: string | Ref): Promise<string> => {
35
+ if (typeof ref === "string") {
36
+ ref = parseToRef(ref)!;
37
+ if (!ref) {
38
+ throw new Error(`Invalid ref: ${ref}`);
39
+ }
30
40
  }
31
- }
32
- return (await client.space.readRef(ref)).text;
33
- },
34
- "space.pageExists": (_ctx, name: string): boolean => {
35
- return client.clientSystem.allKnownFiles.has(`${name}.md`);
36
- },
37
- "space.getPageMeta": (_ctx, name: string): Promise<PageMeta> => {
38
- return client.space.getPageMeta(name);
39
- },
40
- "space.listPlugs": (): Promise<FileMeta[]> => {
41
- return client.space.listPlugs();
42
- },
43
- "space.listDocuments": async (): Promise<DocumentMeta[]> => {
44
- return await client.space.fetchDocumentList();
45
- },
46
- "space.readDocument": async (_ctx, name: string): Promise<Uint8Array> => {
47
- return (await client.space.readDocument(name)).data;
48
- },
49
- "space.getDocumentMeta": async (
50
- _ctx,
51
- name: string,
52
- ): Promise<DocumentMeta> => {
53
- return await client.space.getDocumentMeta(name);
41
+ return (await client.space.readRef(ref)).text;
42
+ },
43
+ description:
44
+ "Reads the text addressed by a page, header, or position reference.",
45
+ signatures: ["space.readRef(ref)"],
46
+ },
47
+ "space.pageExists": {
48
+ callback: (_ctx, name: string): boolean =>
49
+ client.clientSystem.allKnownFiles.has(`${name}.md`),
50
+ description: "Checks whether a page exists in the space.",
51
+ signatures: ["space.pageExists(name)"],
52
+ },
53
+ "space.getPageMeta": {
54
+ callback: (_ctx, name: string): Promise<PageMeta> =>
55
+ client.space.getPageMeta(name),
56
+ description: "Returns metadata for a page.",
57
+ signatures: ["space.getPageMeta(name)"],
58
+ },
59
+ "space.listPlugs": {
60
+ callback: (): Promise<FileMeta[]> => client.space.listPlugs(),
61
+ description: "Lists all plug files in the space.",
62
+ },
63
+ "space.listDocuments": {
64
+ callback: async (): Promise<DocumentMeta[]> =>
65
+ await client.space.fetchDocumentList(),
66
+ description: "Lists all non-page documents in the space.",
67
+ },
68
+ "space.readDocument": {
69
+ callback: async (_ctx, name: string): Promise<Uint8Array> =>
70
+ (await client.space.readDocument(name)).data,
71
+ description: "Reads a document as binary data.",
72
+ signatures: ["space.readDocument(name)"],
73
+ },
74
+ "space.getDocumentMeta": {
75
+ callback: async (_ctx, name: string): Promise<DocumentMeta> =>
76
+ await client.space.getDocumentMeta(name),
77
+ description: "Returns metadata for a document.",
78
+ signatures: ["space.getDocumentMeta(name)"],
54
79
  },
55
80
  // DEPRECATED, please use document versions instead, left here for backwards compatibility
56
- "space.listAttachments": async (): Promise<DocumentMeta[]> => {
57
- return await client.space.fetchDocumentList();
58
- },
59
- "space.readAttachment": async (_ctx, name: string): Promise<Uint8Array> => {
60
- return (await client.space.readDocument(name)).data;
61
- },
62
- "space.getAttachmentMeta": async (
63
- _ctx,
64
- name: string,
65
- ): Promise<DocumentMeta> => {
66
- return await client.space.getDocumentMeta(name);
81
+ "space.listAttachments": {
82
+ callback: async (): Promise<DocumentMeta[]> =>
83
+ await client.space.fetchDocumentList(),
84
+ description: "Deprecated alias for space.listDocuments.",
85
+ deprecated: "Use space.listDocuments instead.",
86
+ },
87
+ "space.readAttachment": {
88
+ callback: async (_ctx, name: string): Promise<Uint8Array> =>
89
+ (await client.space.readDocument(name)).data,
90
+ description: "Deprecated alias for space.readDocument.",
91
+ deprecated: "Use space.readDocument instead.",
92
+ signatures: ["space.readAttachment(name)"],
93
+ },
94
+ "space.getAttachmentMeta": {
95
+ callback: async (_ctx, name: string): Promise<DocumentMeta> =>
96
+ await client.space.getDocumentMeta(name),
97
+ description: "Deprecated alias for space.getDocumentMeta.",
98
+ deprecated: "Use space.getDocumentMeta instead.",
99
+ signatures: ["space.getAttachmentMeta(name)"],
67
100
  },
68
101
  // FS
69
- "space.listFiles": (): Promise<FileMeta[]> => {
70
- return client.space.spacePrimitives.fetchFileList();
71
- },
72
- "space.getFileMeta": (_ctx, name: string): Promise<FileMeta> => {
73
- return client.space.spacePrimitives.getFileMeta(name);
74
- },
75
- "space.readFile": async (_ctx, name: string): Promise<Uint8Array> => {
76
- return (await client.space.spacePrimitives.readFile(name)).data;
77
- },
78
- "space.readFileWithMeta": async (
79
- _ctx,
80
- name: string,
81
- ): Promise<{ data: Uint8Array; meta: FileMeta }> => {
82
- return await client.space.spacePrimitives.readFile(name);
83
- },
84
- "space.fileExists": async (_ctx, name: string): Promise<boolean> => {
85
- // If a full sync has successfully completed (so we know what files exist)
86
- // and we have a snapshot, let's use the snapshot
87
- if (
88
- client.fullSyncCompleted &&
89
- !client.eventedSpacePrimitives.isSnapshotEmpty()
90
- ) {
91
- return !!client.eventedSpacePrimitives.getSnapshot()[name];
92
- }
93
- try {
94
- await client.space.spacePrimitives.getFileMeta(name);
95
- // If this returned the file exists
96
- return true;
97
- } catch {
98
- // Assumption: any error means the file does not exist
99
- return false;
100
- }
102
+ "space.listFiles": {
103
+ callback: (): Promise<FileMeta[]> =>
104
+ client.space.spacePrimitives.fetchFileList(),
105
+ description: "Lists every file in the space.",
106
+ },
107
+ "space.getFileMeta": {
108
+ callback: (_ctx, name: string): Promise<FileMeta> =>
109
+ client.space.spacePrimitives.getFileMeta(name),
110
+ description: "Returns metadata for an arbitrary space file.",
111
+ signatures: ["space.getFileMeta(name)"],
112
+ },
113
+ "space.readFile": {
114
+ callback: async (_ctx, name: string): Promise<Uint8Array> =>
115
+ (await client.space.spacePrimitives.readFile(name)).data,
116
+ description: "Reads an arbitrary space file as binary data.",
117
+ signatures: ["space.readFile(name)"],
118
+ },
119
+ "space.readFileWithMeta": {
120
+ callback: async (
121
+ _ctx,
122
+ name: string,
123
+ ): Promise<{ data: Uint8Array; meta: FileMeta }> =>
124
+ await client.space.spacePrimitives.readFile(name),
125
+ description: "Reads an arbitrary space file together with its metadata.",
126
+ signatures: ["space.readFileWithMeta(name)"],
127
+ },
128
+ "space.fileExists": {
129
+ callback: async (_ctx, name: string): Promise<boolean> => {
130
+ // If a full sync has successfully completed (so we know what files exist)
131
+ // and we have a snapshot, let's use the snapshot
132
+ if (
133
+ client.fullSyncCompleted &&
134
+ !client.eventedSpacePrimitives.isSnapshotEmpty()
135
+ ) {
136
+ return !!client.eventedSpacePrimitives.getSnapshot()[name];
137
+ }
138
+ try {
139
+ await client.space.spacePrimitives.getFileMeta(name);
140
+ // If this returned the file exists
141
+ return true;
142
+ } catch {
143
+ // Assumption: any error means the file does not exist
144
+ return false;
145
+ }
146
+ },
147
+ description: "Checks whether an arbitrary file exists in the space.",
148
+ signatures: ["space.fileExists(name)"],
101
149
  },
102
150
  };
103
151
  }
104
152
 
105
153
  export function spaceWriteSyscalls(editor: Client): SysCallMapping {
106
154
  return {
107
- "space.writePage": (
108
- _ctx,
109
- name: string,
110
- text: string,
111
- ): Promise<PageMeta> => {
112
- return editor.space.writePage(name, text);
113
- },
114
- "space.deletePage": async (_ctx, name: string) => {
115
- console.log("Deleting page");
116
- await editor.space.deletePage(name);
117
- },
118
- "space.writeDocument": (
119
- _ctx,
120
- name: string,
121
- data: Uint8Array,
122
- ): Promise<DocumentMeta> => {
123
- return editor.space.writeDocument(name, data);
124
- },
125
- "space.deleteDocument": async (_ctx, name: string) => {
126
- await editor.space.deleteDocument(name);
127
- },
128
- "space.writeFile": (
129
- _ctx,
130
- name: string,
131
- data: Uint8Array,
132
- ): Promise<FileMeta> => {
133
- return editor.space.spacePrimitives.writeFile(name, data);
134
- },
135
- "space.deleteFile": (_ctx, name: string) => {
136
- return editor.space.spacePrimitives.deleteFile(name);
155
+ "space.writePage": {
156
+ callback: (_ctx, name: string, text: string): Promise<PageMeta> =>
157
+ editor.space.writePage(name, text),
158
+ description: "Writes Markdown text to a page and returns its metadata.",
159
+ signatures: ["space.writePage(name, text)"],
160
+ },
161
+ "space.deletePage": {
162
+ callback: async (_ctx, name: string) => {
163
+ console.log("Deleting page");
164
+ await editor.space.deletePage(name);
165
+ },
166
+ description: "Deletes a page from the space.",
167
+ signatures: ["space.deletePage(name)"],
168
+ },
169
+ "space.writeDocument": {
170
+ callback: (_ctx, name: string, data: Uint8Array): Promise<DocumentMeta> =>
171
+ editor.space.writeDocument(name, data),
172
+ description: "Writes binary document data and returns its metadata.",
173
+ signatures: ["space.writeDocument(name, data)"],
174
+ },
175
+ "space.deleteDocument": {
176
+ callback: async (_ctx, name: string) => {
177
+ await editor.space.deleteDocument(name);
178
+ },
179
+ description: "Deletes a document from the space.",
180
+ signatures: ["space.deleteDocument(name)"],
181
+ },
182
+ "space.writeFile": {
183
+ callback: (_ctx, name: string, data: Uint8Array): Promise<FileMeta> =>
184
+ editor.space.spacePrimitives.writeFile(name, data),
185
+ description: "Writes an arbitrary binary file and returns its metadata.",
186
+ signatures: ["space.writeFile(name, data)"],
187
+ },
188
+ "space.deleteFile": {
189
+ callback: (_ctx, name: string) =>
190
+ editor.space.spacePrimitives.deleteFile(name),
191
+ description: "Deletes an arbitrary file from the space.",
192
+ signatures: ["space.deleteFile(name)"],
137
193
  },
138
194
  };
139
195
  }
@@ -60,27 +60,58 @@ export function syncSyscalls(client: Client): SysCallMapping {
60
60
  }
61
61
 
62
62
  return {
63
- "sync.hasInitialSyncCompleted": (): boolean => {
64
- return client.fullSyncCompleted;
63
+ "sync.hasInitialSyncCompleted": {
64
+ callback: (): boolean => {
65
+ return client.fullSyncCompleted;
66
+ },
67
+ description:
68
+ "Checks whether the initial client synchronization has completed.",
69
+ returns: [
70
+ { type: "boolean", description: "Whether initial sync is complete." },
71
+ ],
65
72
  },
66
- "sync.performFileSync": async (_ctx, path: string): Promise<void> => {
67
- await client.postServiceWorkerMessage({
68
- type: "perform-file-sync",
69
- path,
70
- });
71
- // postServiceWorkerMessage returns silently if no SW, so only wait if SW is active
72
- const registration = await navigator.serviceWorker.getRegistration();
73
- if (registration?.active) {
74
- return waitForServiceWorkerActivation(path);
75
- }
73
+ "sync.performFileSync": {
74
+ callback: async (_ctx, path: string): Promise<void> => {
75
+ await client.postServiceWorkerMessage({
76
+ type: "perform-file-sync",
77
+ path,
78
+ });
79
+ // postServiceWorkerMessage returns silently if no SW, so only wait if SW is active
80
+ const registration = await navigator.serviceWorker.getRegistration();
81
+ if (registration?.active) {
82
+ return waitForServiceWorkerActivation(path);
83
+ }
84
+ },
85
+ description:
86
+ "Prioritizes a file for immediate synchronization and waits for completion.",
87
+ parameters: [
88
+ {
89
+ name: "path",
90
+ type: "string",
91
+ description: "Space-relative file path.",
92
+ },
93
+ ],
94
+ examples: [{ code: 'sync.performFileSync("notes/important.md")' }],
76
95
  },
77
- "sync.performSpaceSync": async (): Promise<number> => {
78
- await client.postServiceWorkerMessage({ type: "perform-space-sync" });
79
- const registration = await navigator.serviceWorker.getRegistration();
80
- if (registration?.active) {
81
- return waitForServiceWorkerActivation();
82
- }
83
- return 0;
96
+ "sync.performSpaceSync": {
97
+ callback: async (): Promise<number> => {
98
+ await client.postServiceWorkerMessage({ type: "perform-space-sync" });
99
+ const registration = await navigator.serviceWorker.getRegistration();
100
+ if (registration?.active) {
101
+ return waitForServiceWorkerActivation();
102
+ }
103
+ return 0;
104
+ },
105
+ description:
106
+ "Starts an immediate full-space synchronization and waits for completion.",
107
+ returns: [
108
+ {
109
+ type: "number",
110
+ description:
111
+ "Number of sync operations, or zero without an active worker.",
112
+ },
113
+ ],
114
+ examples: [{ code: "local changes = sync.performSpaceSync()" }],
84
115
  },
85
116
  };
86
117
  }