@silverbulletmd/silverbullet 2.4.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 (117) hide show
  1. package/LICENSE.md +18 -0
  2. package/README.md +98 -0
  3. package/client/asset_bundle/bundle.ts +95 -0
  4. package/client/data/datastore.ts +85 -0
  5. package/client/data/kv_primitives.ts +25 -0
  6. package/client/markdown_parser/constants.ts +13 -0
  7. package/client/plugos/event.ts +36 -0
  8. package/client/plugos/eventhook.ts +8 -0
  9. package/client/plugos/hooks/code_widget.ts +59 -0
  10. package/client/plugos/hooks/command.ts +104 -0
  11. package/client/plugos/hooks/document_editor.ts +77 -0
  12. package/client/plugos/hooks/event.ts +187 -0
  13. package/client/plugos/hooks/mq.ts +154 -0
  14. package/client/plugos/hooks/plug_namespace.ts +85 -0
  15. package/client/plugos/hooks/slash_command.ts +192 -0
  16. package/client/plugos/hooks/syscall.ts +66 -0
  17. package/client/plugos/manifest_cache.ts +67 -0
  18. package/client/plugos/plug.ts +99 -0
  19. package/client/plugos/plug_compile.ts +202 -0
  20. package/client/plugos/protocol.ts +40 -0
  21. package/client/plugos/proxy_fetch.ts +53 -0
  22. package/client/plugos/sandboxes/deno_worker_sandbox.ts +6 -0
  23. package/client/plugos/sandboxes/sandbox.ts +14 -0
  24. package/client/plugos/sandboxes/web_worker_sandbox.ts +17 -0
  25. package/client/plugos/sandboxes/worker_sandbox.ts +132 -0
  26. package/client/plugos/syscalls/asset.ts +35 -0
  27. package/client/plugos/syscalls/clientStore.ts +21 -0
  28. package/client/plugos/syscalls/client_code_widget.ts +12 -0
  29. package/client/plugos/syscalls/code_widget.ts +24 -0
  30. package/client/plugos/syscalls/config.ts +46 -0
  31. package/client/plugos/syscalls/datastore.ts +89 -0
  32. package/client/plugos/syscalls/editor.ts +673 -0
  33. package/client/plugos/syscalls/event.ts +36 -0
  34. package/client/plugos/syscalls/fetch.ts +128 -0
  35. package/client/plugos/syscalls/index.ts +102 -0
  36. package/client/plugos/syscalls/jsonschema.ts +69 -0
  37. package/client/plugos/syscalls/language.ts +23 -0
  38. package/client/plugos/syscalls/lua.ts +58 -0
  39. package/client/plugos/syscalls/markdown.ts +84 -0
  40. package/client/plugos/syscalls/mq.ts +52 -0
  41. package/client/plugos/syscalls/service_registry.ts +43 -0
  42. package/client/plugos/syscalls/shell.ts +39 -0
  43. package/client/plugos/syscalls/space.ts +139 -0
  44. package/client/plugos/syscalls/sync.ts +77 -0
  45. package/client/plugos/syscalls/system.ts +150 -0
  46. package/client/plugos/system.ts +201 -0
  47. package/client/plugos/types.ts +60 -0
  48. package/client/plugos/util.ts +14 -0
  49. package/client/plugos/worker_runtime.ts +195 -0
  50. package/client/space_lua/ast.ts +328 -0
  51. package/client/space_lua/ast_narrow.ts +81 -0
  52. package/client/space_lua/eval.ts +2478 -0
  53. package/client/space_lua/labels.ts +416 -0
  54. package/client/space_lua/numeric.ts +240 -0
  55. package/client/space_lua/parse.ts +1522 -0
  56. package/client/space_lua/query_collection.ts +232 -0
  57. package/client/space_lua/rp.ts +27 -0
  58. package/client/space_lua/runtime.ts +1702 -0
  59. package/client/space_lua/stdlib/crypto.ts +10 -0
  60. package/client/space_lua/stdlib/encoding.ts +19 -0
  61. package/client/space_lua/stdlib/format.ts +770 -0
  62. package/client/space_lua/stdlib/js.ts +73 -0
  63. package/client/space_lua/stdlib/load.ts +52 -0
  64. package/client/space_lua/stdlib/math.ts +193 -0
  65. package/client/space_lua/stdlib/net.ts +113 -0
  66. package/client/space_lua/stdlib/os.ts +368 -0
  67. package/client/space_lua/stdlib/space_lua.ts +153 -0
  68. package/client/space_lua/stdlib/string.ts +286 -0
  69. package/client/space_lua/stdlib/table.ts +401 -0
  70. package/client/space_lua/stdlib.ts +489 -0
  71. package/client/space_lua/tonumber.ts +501 -0
  72. package/client/space_lua/util.ts +96 -0
  73. package/dist/plug-compile.js +1513 -0
  74. package/package.json +120 -0
  75. package/plug-api/constants.ts +42 -0
  76. package/plug-api/lib/async.ts +162 -0
  77. package/plug-api/lib/crypto.ts +202 -0
  78. package/plug-api/lib/dates.ts +13 -0
  79. package/plug-api/lib/json.ts +136 -0
  80. package/plug-api/lib/limited_map.ts +72 -0
  81. package/plug-api/lib/memory_cache.ts +21 -0
  82. package/plug-api/lib/native_fetch.ts +6 -0
  83. package/plug-api/lib/ref.ts +275 -0
  84. package/plug-api/lib/resolve.ts +90 -0
  85. package/plug-api/lib/tags.ts +15 -0
  86. package/plug-api/lib/transclusion.ts +122 -0
  87. package/plug-api/lib/tree.ts +232 -0
  88. package/plug-api/lib/yaml.ts +284 -0
  89. package/plug-api/syscall.ts +15 -0
  90. package/plug-api/syscalls/asset.ts +36 -0
  91. package/plug-api/syscalls/client_store.ts +33 -0
  92. package/plug-api/syscalls/code_widget.ts +8 -0
  93. package/plug-api/syscalls/config.ts +58 -0
  94. package/plug-api/syscalls/datastore.ts +96 -0
  95. package/plug-api/syscalls/editor.ts +517 -0
  96. package/plug-api/syscalls/event.ts +47 -0
  97. package/plug-api/syscalls/index.ts +77 -0
  98. package/plug-api/syscalls/jsonschema.ts +25 -0
  99. package/plug-api/syscalls/language.ts +23 -0
  100. package/plug-api/syscalls/lua.ts +20 -0
  101. package/plug-api/syscalls/markdown.ts +38 -0
  102. package/plug-api/syscalls/mq.ts +79 -0
  103. package/plug-api/syscalls/shell.ts +14 -0
  104. package/plug-api/syscalls/space.ts +212 -0
  105. package/plug-api/syscalls/sync.ts +28 -0
  106. package/plug-api/syscalls/system.ts +102 -0
  107. package/plug-api/syscalls/yaml.ts +28 -0
  108. package/plug-api/syscalls.ts +21 -0
  109. package/plug-api/system_mock.ts +89 -0
  110. package/plug-api/types/client.ts +116 -0
  111. package/plug-api/types/config.ts +22 -0
  112. package/plug-api/types/datastore.ts +28 -0
  113. package/plug-api/types/event.ts +27 -0
  114. package/plug-api/types/index.ts +56 -0
  115. package/plug-api/types/manifest.ts +98 -0
  116. package/plug-api/types/namespace.ts +6 -0
  117. package/plugs/builtin_plugs.ts +14 -0
@@ -0,0 +1,128 @@
1
+ import type { SysCallMapping } from "../system.ts";
2
+ import type {
3
+ ProxyFetchRequest,
4
+ ProxyFetchRequest64,
5
+ ProxyFetchResponse,
6
+ ProxyFetchResponse64,
7
+ } from "../proxy_fetch.ts";
8
+ import type { Client } from "../../client.ts";
9
+ import {
10
+ base64Decode,
11
+ base64Encode,
12
+ } from "@silverbulletmd/silverbullet/lib/crypto";
13
+ import { fsEndpoint } from "../../spaces/constants.ts";
14
+
15
+ export function sandboxFetchSyscalls(
16
+ client: Client,
17
+ ): SysCallMapping {
18
+ return {
19
+ // For use in Lua
20
+ "http.request": async (
21
+ _ctx,
22
+ url: string,
23
+ options: ProxyFetchRequest = {},
24
+ ): Promise<ProxyFetchResponse> => {
25
+ console.warn("Deprecated: use net.proxyFetch() instead");
26
+ // JSONify any non-serializable body
27
+ if (
28
+ options?.body && typeof options.body !== "string" &&
29
+ !(options.body instanceof Uint8Array)
30
+ ) {
31
+ options.body = JSON.stringify(options.body);
32
+ }
33
+ const fetchOptions = options
34
+ ? {
35
+ method: options.method,
36
+ headers: {} as Record<string, string>,
37
+ body: options.body,
38
+ }
39
+ : {};
40
+
41
+ fetchOptions.headers = buildProxyHeaders(options?.headers);
42
+
43
+ const resp = await client.httpSpacePrimitives.authenticatedFetch(
44
+ buildProxyUrl(client, url),
45
+ fetchOptions,
46
+ );
47
+ // Do sensible things with the body based on the content type
48
+ let body: any;
49
+ const contentTypeHeader = options.responseEncoding ||
50
+ resp.headers.get("x-proxy-header-content-type");
51
+ const statusCode = +(resp.headers.get("x-proxy-status-code") || "200");
52
+ if (contentTypeHeader?.startsWith("application/json")) {
53
+ body = await resp.json();
54
+ } else if (
55
+ contentTypeHeader?.startsWith("application/xml") ||
56
+ contentTypeHeader?.startsWith("text/")
57
+ ) {
58
+ body = await resp.text();
59
+ } else {
60
+ body = new Uint8Array(await resp.arrayBuffer());
61
+ }
62
+ return {
63
+ ok: resp.ok,
64
+ status: statusCode,
65
+ headers: extractProxyHeaders(resp.headers),
66
+ body: body,
67
+ };
68
+ },
69
+ "sandboxFetch.fetch": async (
70
+ _ctx,
71
+ url: string,
72
+ options?: ProxyFetchRequest64,
73
+ ): Promise<ProxyFetchResponse64> => {
74
+ // console.log("Got sandbox fetch ", url, op);
75
+ const fetchOptions = options
76
+ ? {
77
+ method: options.method,
78
+ headers: options.headers,
79
+ body: options.base64Body && base64Decode(options.base64Body),
80
+ }
81
+ : {};
82
+ fetchOptions.headers = buildProxyHeaders(options?.headers);
83
+ const resp = await client.httpSpacePrimitives.authenticatedFetch(
84
+ buildProxyUrl(client, url),
85
+ // Casting this to any because of weird Deno typing
86
+ fetchOptions as any,
87
+ );
88
+ const statusCode = +(resp.headers.get("x-proxy-status-code") || "200");
89
+ const body = await resp.arrayBuffer();
90
+ return {
91
+ ok: resp.ok,
92
+ status: statusCode,
93
+ headers: extractProxyHeaders(resp.headers),
94
+ base64Body: base64Encode(new Uint8Array(body)),
95
+ };
96
+ },
97
+ };
98
+ }
99
+
100
+ function buildProxyUrl(client: Client, url: string) {
101
+ url = url.replace(/^https?:\/\//, "");
102
+ // Strip off the /.fs and replace with /.proxy
103
+ return client.httpSpacePrimitives.url.slice(0, -fsEndpoint.length) +
104
+ "/.proxy/" + url;
105
+ }
106
+
107
+ function buildProxyHeaders(headers?: Record<string, any>): Record<string, any> {
108
+ const newHeaders: Record<string, any> = { "X-Proxy-Request": "true" };
109
+ if (!headers) {
110
+ return newHeaders;
111
+ }
112
+ for (const [key, value] of Object.entries(headers)) {
113
+ newHeaders[`X-Proxy-Header-${key}`] = value;
114
+ }
115
+ return newHeaders;
116
+ }
117
+
118
+ function extractProxyHeaders(
119
+ headers: Headers,
120
+ ): Record<string, any> {
121
+ const newHeaders: Record<string, any> = {};
122
+ for (const [key, value] of headers.entries()) {
123
+ if (key.toLowerCase().startsWith("x-proxy-header-")) {
124
+ newHeaders[key.slice("x-proxy-header-".length)] = value;
125
+ }
126
+ }
127
+ return newHeaders;
128
+ }
@@ -0,0 +1,102 @@
1
+ import type { SysCallMapping } from "../system.ts";
2
+ import type {
3
+ LuaCollectionQuery,
4
+ LuaQueryCollection,
5
+ } from "../../space_lua/query_collection.ts";
6
+
7
+ import {
8
+ type ObjectIndex,
9
+ ObjectValidationError,
10
+ } from "../../data/object_index.ts";
11
+ import type { ObjectValue } from "@silverbulletmd/silverbullet/type/index";
12
+ import type { Client } from "../../client.ts";
13
+ import type { LuaTable } from "../../space_lua/runtime.ts";
14
+
15
+ export function indexSyscalls(
16
+ objectIndex: ObjectIndex,
17
+ client: Client,
18
+ ): SysCallMapping {
19
+ return {
20
+ "index.tag": (_ctx, tagName: string): LuaQueryCollection => {
21
+ return objectIndex.tag(tagName);
22
+ },
23
+ "index.ensureFullIndex": (_ctx) => {
24
+ return objectIndex.ensureFullIndex(client.space);
25
+ },
26
+ "index.reindexSpace": () => {
27
+ return objectIndex.reindexSpace(client.space);
28
+ },
29
+ "index.indexObjects": (
30
+ _ctx,
31
+ page: string,
32
+ objects: ObjectValue[],
33
+ ): Promise<void> => {
34
+ return objectIndex.indexObjects(page, objects);
35
+ },
36
+ "index.validateObjects": async (
37
+ _ctx,
38
+ page: string,
39
+ objects: ObjectValue[],
40
+ ): Promise<{ error: string; object: ObjectValue } | null> => {
41
+ try {
42
+ await objectIndex.validateObjects(page, objects);
43
+ return null;
44
+ } catch (e: any) {
45
+ if (e instanceof ObjectValidationError) {
46
+ return {
47
+ error: e.message,
48
+ object: e.object,
49
+ };
50
+ } else {
51
+ throw e;
52
+ }
53
+ }
54
+ },
55
+ "index.getObjectByRef": (
56
+ _ctx,
57
+ page: string,
58
+ tag: string,
59
+ ref: string,
60
+ ): Promise<ObjectValue | undefined> => {
61
+ return objectIndex.getObjectByRef(ref, page, tag);
62
+ },
63
+ "index.queryLuaObjects": (
64
+ _ctx,
65
+ tag: string,
66
+ query: LuaCollectionQuery,
67
+ scopedVariables?: Record<string, any>,
68
+ ): Promise<ObjectValue[]> => {
69
+ return objectIndex.queryLuaObjects(
70
+ client.clientSystem.spaceLuaEnv.env,
71
+ tag,
72
+ query,
73
+ scopedVariables,
74
+ );
75
+ },
76
+
77
+ "index.deleteObject": (
78
+ _ctx,
79
+ page: string,
80
+ tag: string,
81
+ ref: string,
82
+ ): Promise<void> => {
83
+ return objectIndex.deleteObject(page, tag, ref);
84
+ },
85
+ "lua:index.defineTag": (_ctx, tagDef: LuaTable) => {
86
+ // Using 'lua:' prefix to _not_ convert tagDef to a JS version (but keep original LuaTable)
87
+ if (!tagDef.has("name")) {
88
+ throw new Error("A tag name is required");
89
+ }
90
+ const currentTag = client.config.get(["tags", tagDef.get("name")], null);
91
+ if (!currentTag) {
92
+ client.config.set(["tags", tagDef.get("name")], {
93
+ name: tagDef.get("name"),
94
+ });
95
+ }
96
+ client.config.set(
97
+ ["tags", tagDef.get("name"), "metatable"],
98
+ tagDef.get("metatable"),
99
+ );
100
+ },
101
+ };
102
+ }
@@ -0,0 +1,69 @@
1
+ import type { SysCallMapping } from "../system.ts";
2
+ import { Ajv, type ValidateFunction } from "ajv";
3
+
4
+ const ajv = new Ajv();
5
+
6
+ ajv.addFormat("email", {
7
+ validate: (data: string) => {
8
+ // TODO: Implement email validation
9
+ return data.includes("@");
10
+ },
11
+ async: false,
12
+ });
13
+
14
+ ajv.addFormat("page-ref", {
15
+ validate: (data: string) => {
16
+ return data.startsWith("[[") && data.endsWith("]]");
17
+ },
18
+ async: false,
19
+ });
20
+
21
+ const schemaCache = new Map<string, ValidateFunction>();
22
+
23
+ export function validateObject(schema: any, object: any): undefined | string {
24
+ try {
25
+ const schemaKey = JSON.stringify(schema);
26
+ if (!schemaCache.has(schemaKey)) {
27
+ const validate = ajv.compile(schema);
28
+ schemaCache.set(schemaKey, validate);
29
+ }
30
+ const validate = schemaCache.get(schemaKey)!;
31
+ if (validate(object)) {
32
+ return;
33
+ } else {
34
+ let text = ajv.errorsText(validate.errors);
35
+ text = text.replaceAll("/", ".");
36
+ text = text.replace(/^data[\.\s]/, "");
37
+ return text;
38
+ }
39
+ } catch (e: any) {
40
+ return e.message;
41
+ }
42
+ }
43
+
44
+ export function validateSchema(schema: any): undefined | string {
45
+ const valid = ajv.validateSchema(schema);
46
+ if (valid) {
47
+ return;
48
+ } else {
49
+ return ajv.errorsText(ajv.errors);
50
+ }
51
+ }
52
+
53
+ export function jsonschemaSyscalls(): SysCallMapping {
54
+ return {
55
+ "jsonschema.validateObject": (
56
+ _ctx,
57
+ schema: any,
58
+ object: any,
59
+ ): undefined | string => {
60
+ return validateObject(schema, object);
61
+ },
62
+ "jsonschema.validateSchema": (
63
+ _ctx,
64
+ schema: any,
65
+ ): undefined | string => {
66
+ return validateSchema(schema);
67
+ },
68
+ };
69
+ }
@@ -0,0 +1,23 @@
1
+ import type { SysCallMapping } from "../system.ts";
2
+ import { parse } from "../../markdown_parser/parse_tree.ts";
3
+ import type { ParseTree } from "@silverbulletmd/silverbullet/lib/tree";
4
+ import { builtinLanguages, languageFor } from "../../languages.ts";
5
+
6
+ export function languageSyscalls(): SysCallMapping {
7
+ return {
8
+ "language.parseLanguage": (
9
+ _ctx,
10
+ language: string,
11
+ code: string,
12
+ ): ParseTree => {
13
+ const lang = languageFor(language);
14
+ if (!lang) {
15
+ throw new Error(`Unknown language ${language}`);
16
+ }
17
+ return parse(lang, code);
18
+ },
19
+ "language.listLanguages": (): string[] => {
20
+ return Object.keys(builtinLanguages);
21
+ },
22
+ };
23
+ }
@@ -0,0 +1,58 @@
1
+ import type { SysCallMapping } from "../system.ts";
2
+ import { evalExpression } from "../../space_lua/eval.ts";
3
+ import { parse, parseExpressionString } from "../../space_lua/parse.ts";
4
+ import {
5
+ LuaStackFrame,
6
+ luaToString,
7
+ luaValueToJS,
8
+ } from "../../space_lua/runtime.ts";
9
+ import { buildThreadLocalEnv } from "../../space_lua_api.ts";
10
+ import { isSendable } from "../util.ts";
11
+ import type { LuaBlock, LuaExpression } from "../../space_lua/ast.ts";
12
+ import type { ClientSystem } from "../../client_system.ts";
13
+
14
+ export function luaSyscalls(clientSystem: ClientSystem): SysCallMapping {
15
+ return {
16
+ "lua.parse": (_ctx, code: string): LuaBlock => {
17
+ return parse(code);
18
+ },
19
+ "lua.parseExpression": (_ctx, expression: string): LuaExpression => {
20
+ return parseExpressionString(expression);
21
+ },
22
+ /**
23
+ * Evaluates a Lua expression and returns the result as a JavaScript value
24
+ * @param _ctx
25
+ * @param expression
26
+ * @returns
27
+ */
28
+ "lua.evalExpression": async (_ctx, expression: string) => {
29
+ try {
30
+ const ast = parseExpressionString(expression);
31
+ const env = await buildThreadLocalEnv(
32
+ clientSystem.system,
33
+ clientSystem.spaceLuaEnv.env,
34
+ );
35
+ const sf = new LuaStackFrame(env, null);
36
+ const luaResult = await evalExpression(
37
+ ast,
38
+ clientSystem.spaceLuaEnv.env,
39
+ sf,
40
+ );
41
+ const jsResult = luaValueToJS(luaResult, sf);
42
+ if (isSendable(jsResult)) {
43
+ return jsResult;
44
+ } else {
45
+ // This may evaluate to e.g. a function, which is not sendable, in this case we'll console.warn and return a stringified version of the result
46
+ console.warn(
47
+ "Lua eval result is not sendable, returning stringified version",
48
+ jsResult,
49
+ );
50
+ return luaToString(luaResult);
51
+ }
52
+ } catch (e: any) {
53
+ console.error("Lua eval error: ", e.message, e.sf?.astCtx);
54
+ throw e;
55
+ }
56
+ },
57
+ };
58
+ }
@@ -0,0 +1,84 @@
1
+ import type { SysCallMapping } from "../system.ts";
2
+ import { parse } from "../../markdown_parser/parse_tree.ts";
3
+ import {
4
+ type ParseTree,
5
+ renderToText,
6
+ } from "@silverbulletmd/silverbullet/lib/tree";
7
+ import { extendedMarkdownLanguage } from "../../markdown_parser/parser.ts";
8
+ import {
9
+ expandMarkdown,
10
+ type MarkdownExpandOptions,
11
+ } from "../../markdown_renderer/inline.ts";
12
+ import type { Client } from "../../client.ts";
13
+ import {
14
+ type MarkdownRenderOptions,
15
+ renderMarkdownToHtml,
16
+ } from "../../markdown_renderer/markdown_render.ts";
17
+ import {
18
+ jsonToMDTable,
19
+ refCellTransformer,
20
+ } from "../../markdown_renderer/result_render.ts";
21
+
22
+ export function markdownSyscalls(client: Client): SysCallMapping {
23
+ return {
24
+ "markdown.parseMarkdown": (_ctx, text: string): ParseTree => {
25
+ return parse(extendedMarkdownLanguage, text);
26
+ },
27
+ "markdown.renderParseTree": (_ctx, tree: ParseTree): string => {
28
+ return renderToText(tree);
29
+ },
30
+ "markdown.expandMarkdown": async (
31
+ _ctx,
32
+ treeOrText: ParseTree | string,
33
+ options?: MarkdownExpandOptions,
34
+ ): Promise<ParseTree | string> => {
35
+ const outputString = typeof treeOrText === "string";
36
+ if (typeof treeOrText === "string") {
37
+ treeOrText = parse(extendedMarkdownLanguage, treeOrText);
38
+ }
39
+ const result = await expandMarkdownWithClient(
40
+ client,
41
+ treeOrText,
42
+ options,
43
+ );
44
+ if (outputString) {
45
+ return renderToText(result);
46
+ } else {
47
+ return result;
48
+ }
49
+ },
50
+ "markdown.markdownToHtml": async (
51
+ _ctx,
52
+ text: string,
53
+ options: MarkdownRenderOptions = {},
54
+ ) => {
55
+ let mdTree = parse(extendedMarkdownLanguage, text);
56
+ if (options.expand) {
57
+ mdTree = await expandMarkdownWithClient(client, mdTree);
58
+ }
59
+ return renderMarkdownToHtml(mdTree, options);
60
+ },
61
+ "markdown.objectsToTable": (
62
+ _ctx,
63
+ data: any[],
64
+ options: { renderCell?: (val: any, key: string) => Promise<any> | any } =
65
+ {},
66
+ ) => {
67
+ return jsonToMDTable(data, options.renderCell || refCellTransformer);
68
+ },
69
+ };
70
+ }
71
+
72
+ function expandMarkdownWithClient(
73
+ client: Client,
74
+ tree: ParseTree,
75
+ options?: MarkdownExpandOptions,
76
+ ) {
77
+ return expandMarkdown(
78
+ client.space,
79
+ client.currentName(),
80
+ tree,
81
+ client.clientSystem.spaceLuaEnv,
82
+ options,
83
+ );
84
+ }
@@ -0,0 +1,52 @@
1
+ import type { DataStoreMQ } from "../../data/mq.datastore.ts";
2
+ import type { MQListenerSpec } from "../hooks/mq.ts";
3
+ import type { SysCallMapping } from "../system.ts";
4
+
5
+ export type EventSubscription = MQListenerSpec & {
6
+ run: (...args: any[]) => Promise<any>;
7
+ };
8
+
9
+ export function mqSyscalls(
10
+ mq: DataStoreMQ,
11
+ ): SysCallMapping {
12
+ return {
13
+ /**
14
+ * Define a Lua event listener
15
+ */
16
+ "mq.subscribe": (
17
+ _ctx,
18
+ def: MQListenerSpec,
19
+ ) => {
20
+ def.autoAck = def.autoAck != false;
21
+ // console.log("Registering Lua event listener: ", def.name);
22
+ client.config.insert([
23
+ "mqSubscriptions",
24
+ def.queue,
25
+ ], def);
26
+ },
27
+ "mq.send": (_ctx, queue: string, body: any) => {
28
+ return mq.send(queue, body);
29
+ },
30
+ "mq.batchSend": (_ctx, queue: string, bodies: any[]) => {
31
+ return mq.batchSend(queue, bodies);
32
+ },
33
+ "mq.ack": (_ctx, queue: string, id: string) => {
34
+ return mq.ack(queue, id);
35
+ },
36
+ "mq.batchAck": (_ctx, queue: string, ids: string[]) => {
37
+ return mq.batchAck(queue, ids);
38
+ },
39
+ "mq.flushQueue": (_ctx, queue: string) => {
40
+ return mq.flushQueue(queue);
41
+ },
42
+ "mq.flushAllQueues": () => {
43
+ return mq.flushAllQueues();
44
+ },
45
+ "mq.getQueueStats": (_ctx, queue: string) => {
46
+ return mq.getQueueStats(queue);
47
+ },
48
+ "mq.awaitEmptyQueue": (_ctx, queue: string) => {
49
+ return mq.awaitEmptyQueue(queue);
50
+ },
51
+ };
52
+ }
@@ -0,0 +1,43 @@
1
+ import type {
2
+ ServiceMatch,
3
+ ServiceRegistry,
4
+ ServiceSpec,
5
+ } from "../../service_registry.ts";
6
+ import type { SysCallMapping } from "../system.ts";
7
+
8
+ export function serviceRegistrySyscalls(
9
+ serviceRegistry: ServiceRegistry,
10
+ ): SysCallMapping {
11
+ return {
12
+ /**
13
+ * Define a Lua event listener
14
+ */
15
+ "service.define": (
16
+ _ctx,
17
+ def: ServiceSpec,
18
+ ) => {
19
+ return serviceRegistry.define(def);
20
+ },
21
+ "service.discover": (
22
+ _ctx,
23
+ selector: string,
24
+ data: any,
25
+ ): Promise<ServiceMatch[]> => {
26
+ return serviceRegistry.discover(selector, data);
27
+ },
28
+ "service.invoke": (
29
+ _ctx,
30
+ service: ServiceMatch,
31
+ data: any,
32
+ ): Promise<any> => {
33
+ return serviceRegistry.invoke(service, data);
34
+ },
35
+ "service.invokeBestMatch": (
36
+ _ctx,
37
+ selector: string,
38
+ data: any,
39
+ ): Promise<any> => {
40
+ return serviceRegistry.invokeBestMatch(selector, data);
41
+ },
42
+ };
43
+ }
@@ -0,0 +1,39 @@
1
+ import type { SysCallMapping } from "../system.ts";
2
+ import type { Client } from "../../client.ts";
3
+ import { fsEndpoint } from "../../spaces/constants.ts";
4
+
5
+ export function shellSyscalls(
6
+ client: Client,
7
+ ): SysCallMapping {
8
+ return {
9
+ "shell.run": async (
10
+ _ctx,
11
+ cmd: string,
12
+ args: string[],
13
+ stdin?: string,
14
+ ): Promise<{ stdout: string; stderr: string; code: number }> => {
15
+ if (!client.httpSpacePrimitives) {
16
+ throw new Error("Not supported in fully local mode");
17
+ }
18
+ const resp = client.httpSpacePrimitives.authenticatedFetch(
19
+ buildShellUrl(client),
20
+ {
21
+ method: "POST",
22
+ body: JSON.stringify({
23
+ cmd,
24
+ args,
25
+ stdin,
26
+ }),
27
+ },
28
+ );
29
+ const { code, stderr, stdout } = await (await resp).json();
30
+ return { code, stderr, stdout };
31
+ },
32
+ };
33
+ }
34
+
35
+ function buildShellUrl(client: Client) {
36
+ // Strip off the /.fs and replace with /.shell
37
+ return client.httpSpacePrimitives.url.slice(0, -fsEndpoint.length) +
38
+ "/.shell";
39
+ }