@silverbulletmd/silverbullet 2.9.0 → 2.11.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 (123) hide show
  1. package/README.md +38 -25
  2. package/client/asset_bundle/bundle.ts +0 -1
  3. package/client/config.ts +343 -0
  4. package/client/markdown_parser/constants.ts +3 -1
  5. package/client/plugos/hooks/command.ts +0 -5
  6. package/client/plugos/hooks/event.ts +0 -6
  7. package/client/plugos/hooks/mq.ts +0 -3
  8. package/client/plugos/hooks/slash_command.ts +1 -7
  9. package/client/plugos/hooks/syscall.ts +24 -14
  10. package/client/plugos/manifest_cache.ts +0 -32
  11. package/client/plugos/plug.ts +0 -3
  12. package/client/plugos/plug_compile.ts +3 -13
  13. package/client/plugos/sandboxes/worker_sandbox.ts +19 -9
  14. package/client/plugos/syscalls/asset.ts +61 -23
  15. package/client/plugos/syscalls/clientStore.ts +32 -6
  16. package/client/plugos/syscalls/client_code_widget.ts +9 -4
  17. package/client/plugos/syscalls/code_widget.ts +26 -11
  18. package/client/plugos/syscalls/config.ts +146 -30
  19. package/client/plugos/syscalls/datastore.ts +146 -40
  20. package/client/plugos/syscalls/editor.ts +1518 -722
  21. package/client/plugos/syscalls/event.ts +44 -13
  22. package/client/plugos/syscalls/fetch.ts +120 -83
  23. package/client/plugos/syscalls/icon.ts +46 -0
  24. package/client/plugos/syscalls/index.ts +267 -121
  25. package/client/plugos/syscalls/jsonschema.ts +107 -9
  26. package/client/plugos/syscalls/language.ts +38 -12
  27. package/client/plugos/syscalls/markdown.ts +166 -50
  28. package/client/plugos/syscalls/mq.ts +92 -20
  29. package/client/plugos/syscalls/navigator.ts +143 -0
  30. package/client/plugos/syscalls/schema_introspection.ts +33 -0
  31. package/client/plugos/syscalls/search.ts +44 -0
  32. package/client/plugos/syscalls/service_registry.ts +74 -20
  33. package/client/plugos/syscalls/shell.ts +51 -21
  34. package/client/plugos/syscalls/space.ts +412 -113
  35. package/client/plugos/syscalls/sync.ts +103 -20
  36. package/client/plugos/syscalls/system.ts +274 -139
  37. package/client/plugos/system.ts +28 -10
  38. package/client/plugos/worker_runtime.ts +0 -2
  39. package/client/space_lua/aggregates.ts +0 -16
  40. package/client/space_lua/api_documentation.ts +107 -0
  41. package/client/space_lua/ast.ts +13 -5
  42. package/client/space_lua/ast_narrow.ts +0 -5
  43. package/client/space_lua/budget.ts +113 -0
  44. package/client/space_lua/budget_ui.ts +49 -0
  45. package/client/space_lua/eval.ts +125 -92
  46. package/client/space_lua/labels.ts +0 -4
  47. package/client/space_lua/numeric.ts +0 -5
  48. package/client/space_lua/parse.ts +243 -125
  49. package/client/space_lua/pretty_print.ts +128 -54
  50. package/client/space_lua/quarantine.ts +127 -0
  51. package/client/space_lua/query_collection.ts +7 -51
  52. package/client/space_lua/query_env.ts +0 -2
  53. package/client/space_lua/render_lua_markdown.ts +2 -7
  54. package/client/space_lua/render_widget.ts +173 -0
  55. package/client/space_lua/runtime.ts +133 -92
  56. package/client/space_lua/stdlib/crypto.ts +8 -3
  57. package/client/space_lua/stdlib/encoding.ts +27 -9
  58. package/client/space_lua/stdlib/format.ts +0 -12
  59. package/client/space_lua/stdlib/js.ts +136 -23
  60. package/client/space_lua/stdlib/load.ts +24 -16
  61. package/client/space_lua/stdlib/math.ts +331 -133
  62. package/client/space_lua/stdlib/net.ts +57 -13
  63. package/client/space_lua/stdlib/os.ts +111 -54
  64. package/client/space_lua/stdlib/pattern.ts +10 -15
  65. package/client/space_lua/stdlib/space_lua.ts +344 -21
  66. package/client/space_lua/stdlib/string.ts +282 -104
  67. package/client/space_lua/stdlib/string_pack.ts +58 -22
  68. package/client/space_lua/stdlib/table.ts +195 -45
  69. package/client/space_lua/stdlib.ts +354 -125
  70. package/client/space_lua/syscalls.ts +270 -0
  71. package/client/space_lua/tonumber.ts +0 -9
  72. package/dist/plug-compile.js +2 -3
  73. package/package.json +15 -5
  74. package/plug-api/lib/async.ts +1 -6
  75. package/plug-api/lib/collation.ts +22 -0
  76. package/plug-api/lib/crypto.ts +16 -15
  77. package/plug-api/lib/dates.ts +33 -0
  78. package/plug-api/lib/fuzzy.ts +282 -0
  79. package/plug-api/lib/json.ts +0 -6
  80. package/plug-api/lib/limited_map.ts +0 -2
  81. package/plug-api/lib/link_write.ts +27 -0
  82. package/plug-api/{ui → lib}/panel_styles.ts +4 -3
  83. package/plug-api/lib/ref.ts +124 -5
  84. package/plug-api/lib/resolve.ts +0 -1
  85. package/plug-api/lib/resolve_path.ts +290 -0
  86. package/plug-api/lib/shortcut.ts +17 -1
  87. package/plug-api/lib/tags.ts +0 -3
  88. package/plug-api/lib/transclusion.ts +28 -1
  89. package/plug-api/lib/tree.ts +0 -5
  90. package/plug-api/lib/yaml.ts +3 -42
  91. package/plug-api/syscall.ts +1 -5
  92. package/plug-api/syscalls/config.ts +7 -5
  93. package/plug-api/syscalls/editor.ts +70 -208
  94. package/plug-api/syscalls/icon.ts +18 -0
  95. package/plug-api/syscalls/index.ts +39 -5
  96. package/plug-api/syscalls/jsonschema.ts +9 -0
  97. package/plug-api/syscalls/lua.ts +7 -0
  98. package/plug-api/syscalls/search.ts +11 -0
  99. package/plug-api/syscalls/shell.ts +0 -1
  100. package/plug-api/syscalls/space.ts +122 -5
  101. package/plug-api/syscalls/sync.ts +23 -2
  102. package/plug-api/syscalls/system.ts +53 -0
  103. package/plug-api/syscalls.ts +2 -0
  104. package/plug-api/system_mock.ts +15 -2
  105. package/plug-api/types/client.ts +4 -3
  106. package/plug-api/types/datastore.ts +11 -2
  107. package/plug-api/types/index.ts +62 -1
  108. package/plug-api/types/manifest.ts +22 -4
  109. package/plug-api/types/profile.ts +13 -0
  110. package/plug-api/types/revisions.ts +67 -0
  111. package/plug-api/ui/cx.ts +1 -3
  112. package/plug-api/ui/description.ts +64 -0
  113. package/plug-api/ui/hover.ts +69 -0
  114. package/plug-api/ui/index.ts +61 -2
  115. package/plug-api/ui/scroll.ts +30 -0
  116. package/plug-api/ui/slugify.ts +44 -0
  117. package/plug-api/ui/tree_model.ts +263 -0
  118. package/plug-api/ui/tree_types.ts +66 -0
  119. package/plug-api/ui/use_fit_collapse.ts +67 -0
  120. package/plugs/builtin_plugs.ts +0 -1
  121. package/plugs/index/types.ts +9 -0
  122. package/client/plugos/syscalls/lua.ts +0 -81
  123. package/plug-api/lib/memory_cache.ts +0 -21
@@ -9,25 +9,56 @@ export function eventSyscalls(
9
9
  client: Client,
10
10
  ): SysCallMapping {
11
11
  return {
12
- "event.dispatch": (_ctx, eventName: string, data: any) => {
13
- return eventHook.dispatchEvent(eventName, data);
12
+ "event.dispatch": {
13
+ callback: (_ctx, eventName: string, data: any) => {
14
+ return eventHook.dispatchEvent(eventName, data);
15
+ },
16
+ description:
17
+ "Dispatches an event and collects responses from its listeners.",
18
+ parameters: [
19
+ { name: "eventName", type: "string", description: "Event name." },
20
+ { name: "data", description: "Event payload." },
21
+ ],
22
+ returns: [{ type: "table", description: "Listener responses." }],
23
+ examples: [
24
+ {
25
+ code: 'local responses = event.dispatch("data.request", {id = 123})',
26
+ },
27
+ ],
14
28
  },
15
- "event.listEvents": () => {
16
- return eventHook.listEvents();
29
+ "event.listEvents": {
30
+ callback: () => {
31
+ return eventHook.listEvents();
32
+ },
33
+ description: "Lists all event names that currently have listeners.",
34
+ returns: [{ type: "table", description: "Registered event names." }],
17
35
  },
18
36
  /**
19
37
  * Define a Lua event listener
20
38
  */
21
- "event.listen": (_ctx, def: EventSubscription) => {
22
- // console.log("Registering Lua event listener: ", def.name);
23
- client.config.insert(
24
- ["eventListeners", def.name],
25
- async (...args: any[]) => {
26
- // Convert return value to JS
27
- const val = await def.run(...args);
28
- return luaValueToJS(val, LuaStackFrame.lostFrame);
39
+ "event.listen": {
40
+ callback: (_ctx, def: EventSubscription) => {
41
+ client.config.insert(
42
+ ["eventListeners", def.name],
43
+ async (...args: any[]) => {
44
+ const val = await def.run(...args);
45
+ return luaValueToJS(val, LuaStackFrame.lostFrame);
46
+ },
47
+ );
48
+ },
49
+ description: "Registers a Space Lua listener on the event bus.",
50
+ parameters: [
51
+ {
52
+ name: "listener",
53
+ type: "table",
54
+ description: "Listener definition with name and run callback.",
55
+ },
56
+ ],
57
+ examples: [
58
+ {
59
+ code: 'event.listen { name = "my-event", run = function(e) print(e.data) end }',
29
60
  },
30
- );
61
+ ],
31
62
  },
32
63
  };
33
64
  }
@@ -15,98 +15,135 @@ import { fsEndpoint } from "../../spaces/constants.ts";
15
15
  export function sandboxFetchSyscalls(client: Client): SysCallMapping {
16
16
  return {
17
17
  // For use in Lua
18
- "http.request": async (
19
- _ctx,
20
- url: string,
21
- options: ProxyFetchRequest = {},
22
- ): Promise<ProxyFetchResponse> => {
23
- console.warn("Deprecated: use net.proxyFetch() instead");
24
- // JSONify any non-serializable body
25
- if (
26
- options?.body &&
27
- typeof options.body !== "string" &&
28
- !(options.body instanceof Uint8Array)
29
- ) {
30
- options.body = JSON.stringify(options.body);
31
- }
32
- const fetchOptions = options
33
- ? {
34
- method: options.method,
35
- headers: {} as Record<string, string>,
36
- body: options.body,
37
- }
38
- : {};
18
+ "http.request": {
19
+ callback: async (
20
+ _ctx,
21
+ url: string,
22
+ options: ProxyFetchRequest = {},
23
+ ): Promise<ProxyFetchResponse> => {
24
+ console.warn("Deprecated: use net.proxyFetch() instead");
25
+ if (
26
+ options?.body &&
27
+ typeof options.body !== "string" &&
28
+ !(options.body instanceof Uint8Array)
29
+ ) {
30
+ options.body = JSON.stringify(options.body);
31
+ }
32
+ const fetchOptions = options
33
+ ? {
34
+ method: options.method,
35
+ headers: {} as Record<string, string>,
36
+ body: options.body,
37
+ }
38
+ : {};
39
39
 
40
- fetchOptions.headers = buildProxyHeaders(options?.headers);
40
+ fetchOptions.headers = buildProxyHeaders(options?.headers);
41
41
 
42
- const resp = await client.httpSpacePrimitives.authenticatedFetch(
43
- buildProxyUrl(client, url),
44
- fetchOptions,
45
- );
46
- // Do sensible things with the body based on the content type
47
- // Read as ArrayBuffer first to safely handle empty responses (e.g.
48
- // PUT/DELETE returning 204 with Content-Type: application/json).
49
- // resp.arrayBuffer() never throws on an empty body, whereas
50
- // resp.json() would throw a SyntaxError.
51
- const rawBytes = new Uint8Array(await resp.arrayBuffer());
52
- let body: any;
53
- const contentTypeHeader =
54
- options.responseEncoding ||
55
- resp.headers.get("x-proxy-header-content-type");
56
- const statusCode = +(resp.headers.get("x-proxy-status-code") || "200");
57
- if (rawBytes.length === 0) {
58
- body = null;
59
- } else if (contentTypeHeader?.startsWith("application/json")) {
60
- body = JSON.parse(new TextDecoder().decode(rawBytes));
61
- } else if (
62
- contentTypeHeader?.startsWith("application/xml") ||
63
- contentTypeHeader?.startsWith("text/")
64
- ) {
65
- body = new TextDecoder().decode(rawBytes);
66
- } else {
67
- body = rawBytes;
68
- }
69
- return {
70
- ok: resp.ok,
71
- status: statusCode,
72
- headers: extractProxyHeaders(resp.headers),
73
- body: body,
74
- };
42
+ const resp = await client.httpSpacePrimitives.authenticatedFetch(
43
+ buildProxyUrl(client, url),
44
+ fetchOptions,
45
+ );
46
+ // Read as ArrayBuffer first to safely handle empty responses (e.g.
47
+ // PUT/DELETE returning 204 with Content-Type: application/json).
48
+ // resp.arrayBuffer() never throws on an empty body, whereas
49
+ // resp.json() would throw a SyntaxError.
50
+ const rawBytes = new Uint8Array(await resp.arrayBuffer());
51
+ let body: any;
52
+ const contentTypeHeader =
53
+ options.responseEncoding ||
54
+ resp.headers.get("x-proxy-header-content-type");
55
+ const statusCode = +(resp.headers.get("x-proxy-status-code") || "200");
56
+ if (rawBytes.length === 0) {
57
+ body = null;
58
+ } else if (contentTypeHeader?.startsWith("application/json")) {
59
+ body = JSON.parse(new TextDecoder().decode(rawBytes));
60
+ } else if (
61
+ contentTypeHeader?.startsWith("application/xml") ||
62
+ contentTypeHeader?.startsWith("text/")
63
+ ) {
64
+ body = new TextDecoder().decode(rawBytes);
65
+ } else {
66
+ body = rawBytes;
67
+ }
68
+ return {
69
+ ok: resp.ok,
70
+ status: statusCode,
71
+ headers: extractProxyHeaders(resp.headers),
72
+ body: body,
73
+ };
74
+ },
75
+ description:
76
+ "Performs an authenticated HTTP request through the server proxy.",
77
+ parameters: [
78
+ { name: "url", type: "string", description: "Target URL." },
79
+ {
80
+ name: "options",
81
+ type: "table",
82
+ description: "Method, headers, body, and response encoding.",
83
+ optional: true,
84
+ },
85
+ ],
86
+ returns: [
87
+ {
88
+ type: "table",
89
+ description: "Status, headers, and decoded response body.",
90
+ },
91
+ ],
92
+ deprecated: "Use net.proxyFetch instead.",
93
+ see: "API/net#net.proxyFetch(url, options?)",
75
94
  },
76
- "sandboxFetch.fetch": async (
77
- _ctx,
78
- url: string,
79
- options?: ProxyFetchRequest64,
80
- ): Promise<ProxyFetchResponse64> => {
81
- // console.log("Got sandbox fetch ", url, op);
82
- const fetchOptions = options
83
- ? {
84
- method: options.method,
85
- headers: options.headers,
86
- body: options.base64Body && base64Decode(options.base64Body),
87
- }
88
- : {};
89
- fetchOptions.headers = buildProxyHeaders(options?.headers);
90
- const resp = await client.httpSpacePrimitives.authenticatedFetch(
91
- buildProxyUrl(client, url),
92
- // Casting to any due to TypeScript fetch type limitations
93
- fetchOptions as any,
94
- );
95
- const statusCode = +(resp.headers.get("x-proxy-status-code") || "200");
96
- const body = await resp.arrayBuffer();
97
- return {
98
- ok: resp.ok,
99
- status: statusCode,
100
- headers: extractProxyHeaders(resp.headers),
101
- base64Body: base64Encode(new Uint8Array(body)),
102
- };
95
+ "sandboxFetch.fetch": {
96
+ callback: async (
97
+ _ctx,
98
+ url: string,
99
+ options?: ProxyFetchRequest64,
100
+ ): Promise<ProxyFetchResponse64> => {
101
+ const fetchOptions = options
102
+ ? {
103
+ method: options.method,
104
+ headers: options.headers,
105
+ body: options.base64Body && base64Decode(options.base64Body),
106
+ }
107
+ : {};
108
+ fetchOptions.headers = buildProxyHeaders(options?.headers);
109
+ const resp = await client.httpSpacePrimitives.authenticatedFetch(
110
+ buildProxyUrl(client, url),
111
+ // Casting to any due to TypeScript fetch type limitations
112
+ fetchOptions as any,
113
+ );
114
+ const statusCode = +(resp.headers.get("x-proxy-status-code") || "200");
115
+ const body = await resp.arrayBuffer();
116
+ return {
117
+ ok: resp.ok,
118
+ status: statusCode,
119
+ headers: extractProxyHeaders(resp.headers),
120
+ base64Body: base64Encode(new Uint8Array(body)),
121
+ };
122
+ },
123
+ description:
124
+ "Performs an authenticated proxied fetch for a plug sandbox.",
125
+ parameters: [
126
+ { name: "url", type: "string", description: "Target URL." },
127
+ {
128
+ name: "options",
129
+ type: "table",
130
+ description: "Method, headers, and base64-encoded body.",
131
+ optional: true,
132
+ },
133
+ ],
134
+ returns: [
135
+ {
136
+ type: "table",
137
+ description: "Status, headers, and base64-encoded response body.",
138
+ },
139
+ ],
140
+ see: "API/http",
103
141
  },
104
142
  };
105
143
  }
106
144
 
107
145
  function buildProxyUrl(client: Client, url: string) {
108
146
  url = url.replace(/^https?:\/\//, "");
109
- // Strip off the /.fs and replace with /.proxy
110
147
  return (
111
148
  client.httpSpacePrimitives.url.slice(0, -fsEndpoint.length) +
112
149
  "/.proxy/" +
@@ -0,0 +1,46 @@
1
+ import { resolveFeatherIcons } from "../../lib/feather_icons.ts";
2
+ import type { SysCallMapping } from "../system.ts";
3
+
4
+ export function iconSyscalls(): SysCallMapping {
5
+ return {
6
+ "icon.feather": {
7
+ callback: (_ctx, name: string): string | null => {
8
+ if (!name) return null;
9
+ return resolveFeatherIcons([name])[name] ?? null;
10
+ },
11
+ description:
12
+ "Renders a Feather icon to SVG markup by name, or nil when the name isn't a Feather icon. The markup carries no color of its own (`currentColor`) and a default 24x24 size, both of which CSS at the injection site can override.",
13
+ parameters: [
14
+ {
15
+ name: "name",
16
+ type: "string",
17
+ description: "A Feather icon name, e.g. `trash-2`.",
18
+ },
19
+ ],
20
+ returns: [
21
+ {
22
+ type: "string",
23
+ description: "The icon's SVG markup, or nil when unknown.",
24
+ },
25
+ ],
26
+ examples: [{ code: 'local lock = icon.feather("lock")' }],
27
+ },
28
+ "icon.resolveFeather": {
29
+ callback: (_ctx, names: string[]): Record<string, string> => {
30
+ return resolveFeatherIcons(names ?? []);
31
+ },
32
+ description:
33
+ "Renders a batch of Feather icons to SVG markup in one round trip, so panels can show icons without bundling the icon set themselves. Unknown names are omitted from the result. The markup carries no color of its own (`currentColor`) and a default 24x24 size, both of which CSS at the injection site can override.",
34
+ parameters: [
35
+ {
36
+ name: "names",
37
+ type: "table",
38
+ description: "Feather icon names, e.g. `trash-2`.",
39
+ },
40
+ ],
41
+ returns: [
42
+ { type: "table", description: "Map of icon name to SVG markup." },
43
+ ],
44
+ },
45
+ };
46
+ }