@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,232 @@
1
+ import type { LuaExpression } from "./ast.ts";
2
+ import { LuaEnv, luaGet, luaKeys, LuaStackFrame, LuaTable } from "./runtime.ts";
3
+ import { evalExpression } from "./eval.ts";
4
+ import { asyncQuickSort } from "./util.ts";
5
+ import type { DataStore } from "../data/datastore.ts";
6
+ import type { KvPrimitives } from "../data/kv_primitives.ts";
7
+
8
+ import type { QueryCollationConfig } from "../../plug-api/types/config.ts";
9
+
10
+ import type { KvKey } from "../../plug-api/types/datastore.ts";
11
+
12
+ export function buildItemEnv(
13
+ objectVariable: string | undefined,
14
+ item: any,
15
+ env: LuaEnv,
16
+ sf: LuaStackFrame,
17
+ ): LuaEnv {
18
+ const itemEnv = new LuaEnv(env);
19
+ if (!objectVariable) {
20
+ // Inject all item keys as variables
21
+ for (const key of luaKeys(item)) {
22
+ itemEnv.setLocal(key, luaGet(item, key, sf.astCtx ?? null, sf));
23
+ }
24
+ // As well as _
25
+ itemEnv.setLocal("_", item);
26
+ } else {
27
+ itemEnv.setLocal(objectVariable, item);
28
+ }
29
+ return itemEnv;
30
+ }
31
+
32
+ export type LuaOrderBy = {
33
+ expr: LuaExpression;
34
+ desc: boolean;
35
+ };
36
+
37
+ /**
38
+ * Represents a query for a collection
39
+ */
40
+ export type LuaCollectionQuery = {
41
+ objectVariable?: string;
42
+ // The filter expression evaluated with Lua
43
+ where?: LuaExpression;
44
+ // The order by expression evaluated with Lua
45
+ orderBy?: LuaOrderBy[];
46
+ // The select expression evaluated with Lua
47
+ select?: LuaExpression;
48
+ // The limit of the query
49
+ limit?: number;
50
+ // The offset of the query
51
+ offset?: number;
52
+ // Whether to return only distinct values
53
+ distinct?: boolean;
54
+ };
55
+
56
+ export interface LuaQueryCollection {
57
+ query(
58
+ query: LuaCollectionQuery,
59
+ env: LuaEnv,
60
+ sf: LuaStackFrame,
61
+ ): Promise<any[]>;
62
+ }
63
+
64
+ /**
65
+ * Implements a query collection for a regular JavaScript array
66
+ */
67
+ export class ArrayQueryCollection<T> implements LuaQueryCollection {
68
+ constructor(private readonly array: T[]) {
69
+ }
70
+
71
+ query(
72
+ query: LuaCollectionQuery,
73
+ env: LuaEnv,
74
+ sf: LuaStackFrame,
75
+ collation?: QueryCollationConfig,
76
+ ): Promise<any[]> {
77
+ return applyQuery(this.array, query, env, sf, collation);
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Applies a given query (where, order by, limit etc.) to a set of results
83
+ */
84
+ export async function applyQuery(
85
+ results: any[],
86
+ query: LuaCollectionQuery,
87
+ env: LuaEnv,
88
+ sf: LuaStackFrame,
89
+ collation?: QueryCollationConfig,
90
+ ): Promise<any[]> {
91
+ // Shallow copy to avoid updating underlying data structures
92
+ results = results.slice();
93
+
94
+ // Filter results based on `where` clause first
95
+ if (query.where) {
96
+ const filteredResults = [];
97
+ for (const value of results) {
98
+ // Enrich value
99
+ const itemEnv = buildItemEnv(query.objectVariable, value, env, sf);
100
+ if (await evalExpression(query.where, itemEnv, sf)) {
101
+ filteredResults.push(value);
102
+ }
103
+ }
104
+ results = filteredResults;
105
+ }
106
+
107
+ // Apply `order by` next
108
+ if (query.orderBy) {
109
+ // Retrieve from config API if not passed
110
+ if (collation === undefined) {
111
+ // @ts-ignore: Hack to access client via the browser
112
+ const config = globalThis.client.config; // HACK: Shouldn't be using client here directly
113
+
114
+ collation = config.get("queryCollation", {});
115
+ }
116
+ // Both arguments are optional, so passing undefined is fine
117
+ const collator = Intl.Collator(collation?.locale, collation?.options);
118
+
119
+ results = await asyncQuickSort(results, async (a, b) => {
120
+ // Compare each orderBy clause until we find a difference
121
+ for (const { expr, desc } of query.orderBy!) {
122
+ const aEnv = buildItemEnv(query.objectVariable, a, env, sf);
123
+ const bEnv = buildItemEnv(query.objectVariable, b, env, sf);
124
+
125
+ const aVal = await evalExpression(expr, aEnv, sf);
126
+ const bVal = await evalExpression(expr, bEnv, sf);
127
+
128
+ if (
129
+ collation?.enabled &&
130
+ typeof aVal === "string" &&
131
+ typeof bVal === "string"
132
+ ) {
133
+ const order = collator.compare(aVal, bVal);
134
+ if (order != 0) {
135
+ return desc ? -order : order;
136
+ }
137
+ } else if (aVal < bVal) {
138
+ return desc ? 1 : -1;
139
+ } else if (aVal > bVal) {
140
+ return desc ? -1 : 1;
141
+ }
142
+ // If equal, continue to next orderBy clause
143
+ }
144
+ return 0; // All orderBy clauses were equal
145
+ });
146
+ }
147
+
148
+ // Apply the select
149
+ if (query.select) {
150
+ const newResult = [];
151
+ for (const item of results) {
152
+ const itemEnv = buildItemEnv(query.objectVariable, item, env, sf);
153
+ newResult.push(await evalExpression(query.select, itemEnv, sf));
154
+ }
155
+ results = newResult;
156
+ }
157
+
158
+ // Apply distinct filter (after select to filter on selected values)
159
+ if (query.distinct) {
160
+ const seen = new Set();
161
+ const distinctResult = [];
162
+
163
+ for (const item of results) {
164
+ // For non-primitive values, we use a JSON string as the key for comparison
165
+ const key = generateKey(item);
166
+
167
+ if (!seen.has(key)) {
168
+ seen.add(key);
169
+ distinctResult.push(item);
170
+ }
171
+ }
172
+
173
+ results = distinctResult;
174
+ }
175
+
176
+ // Apply the limit and offset
177
+ if (query.limit !== undefined && query.offset !== undefined) {
178
+ results = results.slice(query.offset, query.offset + query.limit);
179
+ } else if (query.limit !== undefined) {
180
+ results = results.slice(0, query.limit);
181
+ } else if (query.offset !== undefined) {
182
+ results = results.slice(query.offset);
183
+ }
184
+
185
+ return results;
186
+ }
187
+
188
+ export async function queryLua<T = any>(
189
+ kv: KvPrimitives,
190
+ prefix: KvKey,
191
+ query: LuaCollectionQuery,
192
+ env: LuaEnv,
193
+ sf: LuaStackFrame = LuaStackFrame.lostFrame,
194
+ enricher?: (key: KvKey, item: any) => any,
195
+ ): Promise<T[]> {
196
+ const results: T[] = [];
197
+ // Accumulate all results into an array
198
+ for await (
199
+ let { key, value } of kv.query({ prefix })
200
+ ) {
201
+ if (enricher) {
202
+ value = enricher(key, value);
203
+ }
204
+ results.push(value);
205
+ }
206
+
207
+ return applyQuery(results, query, env, sf);
208
+ }
209
+
210
+ function generateKey(value: any) {
211
+ if (value instanceof LuaTable) {
212
+ return JSON.stringify(value.toJS());
213
+ }
214
+ return typeof value === "object" && value !== null
215
+ ? JSON.stringify(value)
216
+ : value;
217
+ }
218
+ export class DataStoreQueryCollection implements LuaQueryCollection {
219
+ constructor(
220
+ private readonly dataStore: DataStore,
221
+ readonly prefix: string[],
222
+ ) {
223
+ }
224
+
225
+ query(
226
+ query: LuaCollectionQuery,
227
+ env: LuaEnv,
228
+ sf: LuaStackFrame,
229
+ ): Promise<any[]> {
230
+ return queryLua(this.dataStore.kv, this.prefix, query, env, sf);
231
+ }
232
+ }
@@ -0,0 +1,27 @@
1
+ // Result-or-Promise helpers
2
+
3
+ export type RP<T> = T | Promise<T>;
4
+
5
+ // Returns true when v is a Promise or a has a then function.
6
+ export function isPromise<T>(v: RP<T>): v is Promise<T> {
7
+ return v !== null &&
8
+ (typeof v === "object" || typeof v === "function") &&
9
+ typeof (v as any).then === "function";
10
+ }
11
+
12
+ export function rpThen<A, B>(v: RP<A>, f: (a: A) => RP<B>): RP<B> {
13
+ return isPromise(v) ? (v as Promise<A>).then(f) : f(v as A);
14
+ }
15
+
16
+ /**
17
+ * Collect an array of Result-or-Promise values into a single array
18
+ * avoiding Promise allocation when all inputs are synchronous.
19
+ */
20
+ export function rpAll<T>(arr: RP<T>[]): RP<T[]> {
21
+ for (let i = 0; i < arr.length; i++) {
22
+ if (isPromise(arr[i])) {
23
+ return Promise.all(arr as Promise<T>[]);
24
+ }
25
+ }
26
+ return arr as T[];
27
+ }