@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.
- package/README.md +38 -25
- package/client/asset_bundle/bundle.ts +0 -1
- package/client/config.ts +343 -0
- package/client/markdown_parser/constants.ts +3 -1
- package/client/plugos/hooks/command.ts +0 -5
- package/client/plugos/hooks/event.ts +0 -6
- package/client/plugos/hooks/mq.ts +0 -3
- package/client/plugos/hooks/slash_command.ts +1 -7
- package/client/plugos/hooks/syscall.ts +24 -14
- package/client/plugos/manifest_cache.ts +0 -32
- package/client/plugos/plug.ts +0 -3
- package/client/plugos/plug_compile.ts +3 -13
- package/client/plugos/sandboxes/worker_sandbox.ts +19 -9
- package/client/plugos/syscalls/asset.ts +61 -23
- package/client/plugos/syscalls/clientStore.ts +32 -6
- package/client/plugos/syscalls/client_code_widget.ts +9 -4
- package/client/plugos/syscalls/code_widget.ts +26 -11
- package/client/plugos/syscalls/config.ts +146 -30
- package/client/plugos/syscalls/datastore.ts +146 -40
- package/client/plugos/syscalls/editor.ts +1518 -722
- package/client/plugos/syscalls/event.ts +44 -13
- package/client/plugos/syscalls/fetch.ts +120 -83
- package/client/plugos/syscalls/icon.ts +46 -0
- package/client/plugos/syscalls/index.ts +267 -121
- package/client/plugos/syscalls/jsonschema.ts +107 -9
- package/client/plugos/syscalls/language.ts +38 -12
- package/client/plugos/syscalls/markdown.ts +166 -50
- package/client/plugos/syscalls/mq.ts +92 -20
- package/client/plugos/syscalls/navigator.ts +143 -0
- package/client/plugos/syscalls/schema_introspection.ts +33 -0
- package/client/plugos/syscalls/search.ts +44 -0
- package/client/plugos/syscalls/service_registry.ts +74 -20
- package/client/plugos/syscalls/shell.ts +51 -21
- package/client/plugos/syscalls/space.ts +412 -113
- package/client/plugos/syscalls/sync.ts +103 -20
- package/client/plugos/syscalls/system.ts +274 -139
- package/client/plugos/system.ts +28 -10
- package/client/plugos/worker_runtime.ts +0 -2
- package/client/space_lua/aggregates.ts +0 -16
- package/client/space_lua/api_documentation.ts +107 -0
- package/client/space_lua/ast.ts +13 -5
- package/client/space_lua/ast_narrow.ts +0 -5
- package/client/space_lua/budget.ts +113 -0
- package/client/space_lua/budget_ui.ts +49 -0
- package/client/space_lua/eval.ts +125 -92
- package/client/space_lua/labels.ts +0 -4
- package/client/space_lua/numeric.ts +0 -5
- package/client/space_lua/parse.ts +243 -125
- package/client/space_lua/pretty_print.ts +128 -54
- package/client/space_lua/quarantine.ts +127 -0
- package/client/space_lua/query_collection.ts +7 -51
- package/client/space_lua/query_env.ts +0 -2
- package/client/space_lua/render_lua_markdown.ts +2 -7
- package/client/space_lua/render_widget.ts +173 -0
- package/client/space_lua/runtime.ts +133 -92
- package/client/space_lua/stdlib/crypto.ts +8 -3
- package/client/space_lua/stdlib/encoding.ts +27 -9
- package/client/space_lua/stdlib/format.ts +0 -12
- package/client/space_lua/stdlib/js.ts +136 -23
- package/client/space_lua/stdlib/load.ts +24 -16
- package/client/space_lua/stdlib/math.ts +331 -133
- package/client/space_lua/stdlib/net.ts +57 -13
- package/client/space_lua/stdlib/os.ts +111 -54
- package/client/space_lua/stdlib/pattern.ts +10 -15
- package/client/space_lua/stdlib/space_lua.ts +344 -21
- package/client/space_lua/stdlib/string.ts +282 -104
- package/client/space_lua/stdlib/string_pack.ts +58 -22
- package/client/space_lua/stdlib/table.ts +195 -45
- package/client/space_lua/stdlib.ts +354 -125
- package/client/space_lua/syscalls.ts +270 -0
- package/client/space_lua/tonumber.ts +0 -9
- package/dist/plug-compile.js +2 -3
- package/package.json +15 -5
- package/plug-api/lib/async.ts +1 -6
- package/plug-api/lib/collation.ts +22 -0
- package/plug-api/lib/crypto.ts +16 -15
- package/plug-api/lib/dates.ts +33 -0
- package/plug-api/lib/fuzzy.ts +282 -0
- package/plug-api/lib/json.ts +0 -6
- package/plug-api/lib/limited_map.ts +0 -2
- package/plug-api/lib/link_write.ts +27 -0
- package/plug-api/{ui → lib}/panel_styles.ts +4 -3
- package/plug-api/lib/ref.ts +124 -5
- package/plug-api/lib/resolve.ts +0 -1
- package/plug-api/lib/resolve_path.ts +290 -0
- package/plug-api/lib/shortcut.ts +17 -1
- package/plug-api/lib/tags.ts +0 -3
- package/plug-api/lib/transclusion.ts +28 -1
- package/plug-api/lib/tree.ts +0 -5
- package/plug-api/lib/yaml.ts +3 -42
- package/plug-api/syscall.ts +1 -5
- package/plug-api/syscalls/config.ts +7 -5
- package/plug-api/syscalls/editor.ts +70 -208
- package/plug-api/syscalls/icon.ts +18 -0
- package/plug-api/syscalls/index.ts +39 -5
- package/plug-api/syscalls/jsonschema.ts +9 -0
- package/plug-api/syscalls/lua.ts +7 -0
- package/plug-api/syscalls/search.ts +11 -0
- package/plug-api/syscalls/shell.ts +0 -1
- package/plug-api/syscalls/space.ts +122 -5
- package/plug-api/syscalls/sync.ts +23 -2
- package/plug-api/syscalls/system.ts +53 -0
- package/plug-api/syscalls.ts +2 -0
- package/plug-api/system_mock.ts +15 -2
- package/plug-api/types/client.ts +4 -3
- package/plug-api/types/datastore.ts +11 -2
- package/plug-api/types/index.ts +62 -1
- package/plug-api/types/manifest.ts +22 -4
- package/plug-api/types/profile.ts +13 -0
- package/plug-api/types/revisions.ts +67 -0
- package/plug-api/ui/cx.ts +1 -3
- package/plug-api/ui/description.ts +64 -0
- package/plug-api/ui/hover.ts +69 -0
- package/plug-api/ui/index.ts +61 -2
- package/plug-api/ui/scroll.ts +30 -0
- package/plug-api/ui/slugify.ts +44 -0
- package/plug-api/ui/tree_model.ts +263 -0
- package/plug-api/ui/tree_types.ts +66 -0
- package/plug-api/ui/use_fit_collapse.ts +67 -0
- package/plugs/builtin_plugs.ts +0 -1
- package/plugs/index/types.ts +9 -0
- package/client/plugos/syscalls/lua.ts +0 -81
- package/plug-api/lib/memory_cache.ts +0 -21
|
@@ -1,160 +1,306 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
LuaCollectionQuery,
|
|
4
|
-
LuaQueryCollection,
|
|
5
|
-
} from "../../space_lua/query_collection.ts";
|
|
1
|
+
import type { ObjectValue } from "@silverbulletmd/silverbullet/type/index";
|
|
2
|
+
import type { Client } from "../../client.ts";
|
|
6
3
|
|
|
7
4
|
import {
|
|
8
5
|
type ObjectIndex,
|
|
9
6
|
ObjectValidationError,
|
|
10
7
|
} from "../../data/object_index.ts";
|
|
11
|
-
import type {
|
|
12
|
-
|
|
8
|
+
import type {
|
|
9
|
+
LuaCollectionQuery,
|
|
10
|
+
LuaQueryCollection,
|
|
11
|
+
} from "../../space_lua/query_collection.ts";
|
|
13
12
|
import type { LuaTable } from "../../space_lua/runtime.ts";
|
|
13
|
+
import type { SysCallMapping } from "../system.ts";
|
|
14
|
+
import { describeSchemas, tagSchema } from "./schema_introspection.ts";
|
|
14
15
|
|
|
15
16
|
export function indexSyscalls(
|
|
16
17
|
objectIndex: ObjectIndex,
|
|
17
18
|
client: Client,
|
|
18
19
|
): SysCallMapping {
|
|
19
20
|
return {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
"index.tag": {
|
|
22
|
+
callback: (_ctx, tagName: string): LuaQueryCollection => {
|
|
23
|
+
return objectIndex.objectsWithTag(tagName);
|
|
24
|
+
},
|
|
25
|
+
description: "Returns objects carrying a tag as a query collection.",
|
|
26
|
+
signatures: ["index.tag(tagName)"],
|
|
23
27
|
},
|
|
24
28
|
// Alias for tag
|
|
25
|
-
"index.objects":
|
|
26
|
-
|
|
29
|
+
"index.objects": {
|
|
30
|
+
callback: (_ctx, tagName: string): LuaQueryCollection => {
|
|
31
|
+
return objectIndex.objectsWithTag(tagName);
|
|
32
|
+
},
|
|
33
|
+
description: "Returns objects carrying a tag as a query collection.",
|
|
34
|
+
signatures: ["index.objects(tagName)"],
|
|
35
|
+
},
|
|
36
|
+
"index.pages": {
|
|
37
|
+
callback: (_ctx, tagName?: string): LuaQueryCollection => {
|
|
38
|
+
return objectIndex.rootTaggedObjects("page", tagName);
|
|
39
|
+
},
|
|
40
|
+
description:
|
|
41
|
+
"Returns all pages, optionally filtered by an additional tag, as a query collection.",
|
|
42
|
+
signatures: ["index.pages(tagName?)"],
|
|
43
|
+
},
|
|
44
|
+
"index.subPages": {
|
|
45
|
+
callback: (_ctx, pageName: string): LuaQueryCollection => {
|
|
46
|
+
return objectIndex.subPages(pageName);
|
|
47
|
+
},
|
|
48
|
+
description:
|
|
49
|
+
"Returns pages nested below a page name as a query collection.",
|
|
50
|
+
signatures: ["index.subPages(pageName)"],
|
|
27
51
|
},
|
|
28
|
-
"index.
|
|
29
|
-
|
|
52
|
+
"index.documents": {
|
|
53
|
+
callback: (): LuaQueryCollection => {
|
|
54
|
+
return objectIndex.objectsWithTag("document");
|
|
55
|
+
},
|
|
56
|
+
description: "Returns all indexed documents as a query collection.",
|
|
30
57
|
},
|
|
31
|
-
"index.
|
|
32
|
-
|
|
58
|
+
"index.links": {
|
|
59
|
+
callback: (): LuaQueryCollection => {
|
|
60
|
+
return objectIndex.objectsWithTag("link");
|
|
61
|
+
},
|
|
62
|
+
description: "Returns all indexed links as a query collection.",
|
|
33
63
|
},
|
|
34
|
-
"index.
|
|
35
|
-
|
|
64
|
+
"index.relations": {
|
|
65
|
+
callback: (_ctx, kind?: string): LuaQueryCollection => {
|
|
66
|
+
return objectIndex.relations(kind);
|
|
67
|
+
},
|
|
68
|
+
description:
|
|
69
|
+
"Returns all indexed relations, optionally filtered by kind, as a query collection.",
|
|
70
|
+
signatures: ["index.relations(kind?)"],
|
|
36
71
|
},
|
|
37
|
-
"index.
|
|
38
|
-
|
|
72
|
+
"index.contentPages": {
|
|
73
|
+
callback: (_ctx, tagName?: string): LuaQueryCollection => {
|
|
74
|
+
return objectIndex.contentPages(tagName);
|
|
75
|
+
},
|
|
76
|
+
description:
|
|
77
|
+
"Returns non-meta pages, optionally filtered by an additional tag, as a query collection.",
|
|
78
|
+
signatures: ["index.contentPages(tagName?)"],
|
|
39
79
|
},
|
|
40
|
-
"index.
|
|
41
|
-
|
|
80
|
+
"index.metaPages": {
|
|
81
|
+
callback: (): LuaQueryCollection => {
|
|
82
|
+
return objectIndex.metaPages();
|
|
83
|
+
},
|
|
84
|
+
description: "Returns all meta pages as a query collection.",
|
|
42
85
|
},
|
|
43
|
-
"index.
|
|
44
|
-
|
|
86
|
+
"index.tasks": {
|
|
87
|
+
callback: (_ctx, tagName?: string): LuaQueryCollection => {
|
|
88
|
+
return objectIndex.rootTaggedObjects("task", tagName);
|
|
89
|
+
},
|
|
90
|
+
description:
|
|
91
|
+
"Returns all tasks, optionally filtered by an additional tag, as a query collection.",
|
|
92
|
+
signatures: ["index.tasks(tagName?)"],
|
|
45
93
|
},
|
|
46
|
-
"index.
|
|
47
|
-
|
|
94
|
+
"index.headers": {
|
|
95
|
+
callback: (_ctx, tagName?: string): LuaQueryCollection => {
|
|
96
|
+
return objectIndex.rootTaggedObjects("header", tagName);
|
|
97
|
+
},
|
|
98
|
+
description:
|
|
99
|
+
"Returns all headers, optionally filtered by an additional tag, as a query collection.",
|
|
100
|
+
signatures: ["index.headers(tagName?)"],
|
|
48
101
|
},
|
|
49
|
-
"index.
|
|
50
|
-
|
|
102
|
+
"index.items": {
|
|
103
|
+
callback: (_ctx, tagName?: string): LuaQueryCollection => {
|
|
104
|
+
return objectIndex.rootTaggedObjects("item", tagName);
|
|
105
|
+
},
|
|
106
|
+
description:
|
|
107
|
+
"Returns all list items, optionally filtered by an additional tag, as a query collection.",
|
|
108
|
+
signatures: ["index.items(tagName?)"],
|
|
51
109
|
},
|
|
52
|
-
"index.
|
|
53
|
-
|
|
110
|
+
"index.paragraphs": {
|
|
111
|
+
callback: (_ctx, tagName?: string): LuaQueryCollection => {
|
|
112
|
+
return objectIndex.rootTaggedObjects("paragraph", tagName);
|
|
113
|
+
},
|
|
114
|
+
description:
|
|
115
|
+
"Returns indexed paragraphs, optionally filtered by an additional tag, as a query collection.",
|
|
116
|
+
signatures: ["index.paragraphs(tagName?)"],
|
|
54
117
|
},
|
|
55
|
-
"index.
|
|
56
|
-
|
|
118
|
+
"index.tables": {
|
|
119
|
+
callback: (_ctx, tagName?: string): LuaQueryCollection => {
|
|
120
|
+
return objectIndex.rootTaggedObjects("table", tagName);
|
|
121
|
+
},
|
|
122
|
+
description:
|
|
123
|
+
"Returns indexed table rows, optionally filtered by an additional tag, as a query collection.",
|
|
124
|
+
signatures: ["index.tables(tagName?)"],
|
|
57
125
|
},
|
|
58
|
-
"index.
|
|
59
|
-
|
|
126
|
+
"index.tags": {
|
|
127
|
+
callback: (): LuaQueryCollection => {
|
|
128
|
+
return objectIndex.objectsWithTag("tag");
|
|
129
|
+
},
|
|
130
|
+
description: "Returns all indexed tag objects as a query collection.",
|
|
60
131
|
},
|
|
61
|
-
"index.
|
|
62
|
-
|
|
132
|
+
"index.describeSchema": {
|
|
133
|
+
callback: (): Record<string, unknown> => {
|
|
134
|
+
return describeSchemas(client.config.get(["tags"], {}));
|
|
135
|
+
},
|
|
136
|
+
description:
|
|
137
|
+
"Returns raw JSON Schemas for every configured tag that declares one.",
|
|
63
138
|
},
|
|
64
|
-
"index.
|
|
65
|
-
|
|
139
|
+
"index.tagSchema": {
|
|
140
|
+
callback: (_ctx, tagName: string): unknown | null => {
|
|
141
|
+
return tagSchema(client.config.get(["tags"], {}), tagName);
|
|
142
|
+
},
|
|
143
|
+
description:
|
|
144
|
+
"Returns the raw JSON Schema for a tag, or nil when none is declared.",
|
|
145
|
+
signatures: ["index.tagSchema(tagName)"],
|
|
66
146
|
},
|
|
67
|
-
"index.
|
|
68
|
-
|
|
147
|
+
"index.isAvailable": {
|
|
148
|
+
callback: (): Promise<boolean> => objectIndex.isIndexAvailable(),
|
|
149
|
+
description: `Whether a full indexing pass has ever completed for this space. False on a fresh client, and for as long as the first index takes on a large one: every object query answers with whatever has been indexed so far, which is nothing to begin with. Code that must work in that window reads the space directly instead.`,
|
|
150
|
+
returns: [
|
|
151
|
+
{ type: "boolean", description: "Whether the index can be trusted." },
|
|
152
|
+
],
|
|
69
153
|
},
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
154
|
+
"index.aspiringPages": {
|
|
155
|
+
callback: (): LuaQueryCollection => {
|
|
156
|
+
return objectIndex.aspiringPages();
|
|
157
|
+
},
|
|
158
|
+
description:
|
|
159
|
+
"Returns linked but not yet created pages as a query collection.",
|
|
73
160
|
},
|
|
74
|
-
"index.
|
|
75
|
-
|
|
161
|
+
"index.ambiguousLinks": {
|
|
162
|
+
callback: (): LuaQueryCollection => {
|
|
163
|
+
return objectIndex.ambiguousLinks();
|
|
164
|
+
},
|
|
165
|
+
description:
|
|
166
|
+
"Returns links whose page name matches more than one page as a query collection.",
|
|
76
167
|
},
|
|
77
|
-
"index.
|
|
78
|
-
|
|
168
|
+
"index.aggregates": {
|
|
169
|
+
callback: (): LuaQueryCollection => {
|
|
170
|
+
return objectIndex.aggregates();
|
|
171
|
+
},
|
|
172
|
+
description: "Returns stored aggregate records as a query collection.",
|
|
79
173
|
},
|
|
80
|
-
"index.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
174
|
+
"index.ensureFullIndex": {
|
|
175
|
+
callback: () => {
|
|
176
|
+
return objectIndex.ensureFullIndex(client.space);
|
|
177
|
+
},
|
|
178
|
+
description:
|
|
179
|
+
"Ensures the complete object index is available and current.",
|
|
86
180
|
},
|
|
87
|
-
"index.
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
181
|
+
"index.reindexSpace": {
|
|
182
|
+
callback: () => {
|
|
183
|
+
return objectIndex.reindexSpace(client.space);
|
|
184
|
+
},
|
|
185
|
+
description: "Rebuilds the object index for the entire space.",
|
|
186
|
+
},
|
|
187
|
+
"index.indexObjects": {
|
|
188
|
+
callback: (_ctx, page: string, objects: ObjectValue[]): Promise<void> => {
|
|
189
|
+
return objectIndex.indexObjects(page, objects);
|
|
190
|
+
},
|
|
191
|
+
description: "Indexes a collection of objects for a page.",
|
|
192
|
+
signatures: ["index.indexObjects(page, objects)"],
|
|
193
|
+
},
|
|
194
|
+
"index.validateObjects": {
|
|
195
|
+
callback: async (
|
|
196
|
+
_ctx,
|
|
197
|
+
page: string,
|
|
198
|
+
objects: ObjectValue[],
|
|
199
|
+
): Promise<{ error: string; object: ObjectValue } | null> => {
|
|
200
|
+
try {
|
|
201
|
+
await objectIndex.validateObjects(page, objects);
|
|
202
|
+
return null;
|
|
203
|
+
} catch (e: any) {
|
|
204
|
+
if (e instanceof ObjectValidationError) {
|
|
205
|
+
return {
|
|
206
|
+
error: e.message,
|
|
207
|
+
object: e.object,
|
|
208
|
+
};
|
|
209
|
+
} else {
|
|
210
|
+
throw e;
|
|
211
|
+
}
|
|
103
212
|
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
},
|
|
121
|
-
"index.
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
)
|
|
213
|
+
},
|
|
214
|
+
description:
|
|
215
|
+
"Validates objects for a page and returns the first validation error, if any.",
|
|
216
|
+
signatures: ["index.validateObjects(page, objects)"],
|
|
217
|
+
},
|
|
218
|
+
"index.previewProcessedObjects": {
|
|
219
|
+
callback: (
|
|
220
|
+
_ctx,
|
|
221
|
+
page: string,
|
|
222
|
+
objects: ObjectValue[],
|
|
223
|
+
): Promise<{ tag: string; object: ObjectValue }[]> => {
|
|
224
|
+
return objectIndex.previewProcessedObjects(page, objects);
|
|
225
|
+
},
|
|
226
|
+
description:
|
|
227
|
+
"Runs the indexing pipeline without writing and returns processed tag/object pairs.",
|
|
228
|
+
signatures: ["index.previewProcessedObjects(page, objects)"],
|
|
229
|
+
},
|
|
230
|
+
"index.getObjectByRef": {
|
|
231
|
+
callback: (
|
|
232
|
+
_ctx,
|
|
233
|
+
page: string,
|
|
234
|
+
tag: string,
|
|
235
|
+
ref: string,
|
|
236
|
+
): Promise<ObjectValue | undefined> => {
|
|
237
|
+
return objectIndex.getObjectByRef(page, tag, ref);
|
|
238
|
+
},
|
|
239
|
+
description:
|
|
240
|
+
"Returns an indexed object identified by page, tag, and reference.",
|
|
241
|
+
signatures: ["index.getObjectByRef(page, tag, ref)"],
|
|
242
|
+
},
|
|
243
|
+
"index.queryLuaObjects": {
|
|
244
|
+
callback: (
|
|
245
|
+
_ctx,
|
|
246
|
+
tag: string,
|
|
247
|
+
query: LuaCollectionQuery,
|
|
248
|
+
scopedVariables?: Record<string, any>,
|
|
249
|
+
): Promise<ObjectValue[]> => {
|
|
250
|
+
return objectIndex.queryLuaObjects(
|
|
251
|
+
client.clientSystem.spaceLuaEnv.env,
|
|
252
|
+
tag,
|
|
253
|
+
query,
|
|
254
|
+
scopedVariables,
|
|
255
|
+
);
|
|
256
|
+
},
|
|
257
|
+
description:
|
|
258
|
+
"Executes a structured Lua collection query against indexed objects.",
|
|
259
|
+
signatures: ["index.queryLuaObjects(tag, query, scopedVariables?)"],
|
|
133
260
|
},
|
|
134
261
|
|
|
135
|
-
"index.
|
|
136
|
-
_ctx,
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
262
|
+
"index.clearFileIndex": {
|
|
263
|
+
callback: (_ctx, path: string): Promise<void> =>
|
|
264
|
+
objectIndex.clearFileIndex(path),
|
|
265
|
+
description:
|
|
266
|
+
"Drops every indexed object belonging to a file, so a re-index replaces them rather than merging on top.",
|
|
267
|
+
signatures: ["index.clearFileIndex(path)"],
|
|
268
|
+
},
|
|
269
|
+
"index.deleteObject": {
|
|
270
|
+
callback: (
|
|
271
|
+
_ctx,
|
|
272
|
+
page: string,
|
|
273
|
+
tag: string,
|
|
274
|
+
ref: string,
|
|
275
|
+
): Promise<void> => {
|
|
276
|
+
return objectIndex.deleteObject(page, tag, ref);
|
|
277
|
+
},
|
|
278
|
+
description:
|
|
279
|
+
"Deletes an indexed object identified by page, tag, and reference.",
|
|
280
|
+
signatures: ["index.deleteObject(page, tag, ref)"],
|
|
281
|
+
},
|
|
282
|
+
"lua:index.defineTag": {
|
|
283
|
+
callback: (_ctx, tagDef: LuaTable) => {
|
|
284
|
+
// Using 'lua:' prefix to _not_ convert tagDef to a JS version (but keep original LuaTable)
|
|
285
|
+
if (!tagDef.has("name")) {
|
|
286
|
+
throw new Error("A tag name is required");
|
|
287
|
+
}
|
|
288
|
+
const currentTag = client.config.get(
|
|
289
|
+
["tags", tagDef.get("name")],
|
|
290
|
+
null,
|
|
291
|
+
);
|
|
292
|
+
if (!currentTag) {
|
|
293
|
+
client.config.set(["tags", tagDef.get("name")], {
|
|
294
|
+
name: tagDef.get("name"),
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
client.config.set(
|
|
298
|
+
["tags", tagDef.get("name"), "metatable"],
|
|
299
|
+
tagDef.get("metatable"),
|
|
300
|
+
);
|
|
301
|
+
},
|
|
302
|
+
description: "Defines or updates a tag and its Lua metatable.",
|
|
303
|
+
signatures: ["index.defineTag(tagDefinition)"],
|
|
158
304
|
},
|
|
159
305
|
};
|
|
160
306
|
}
|
|
@@ -2,7 +2,6 @@ import type { SysCallMapping } from "../system.ts";
|
|
|
2
2
|
import { type OutputUnit, Validator, format } from "@cfworker/json-schema";
|
|
3
3
|
import { stripFunctions } from "../util.ts";
|
|
4
4
|
|
|
5
|
-
// Register custom formats
|
|
6
5
|
format.email = (data: string) => data.includes("@");
|
|
7
6
|
format["page-ref"] = (data: string) =>
|
|
8
7
|
data.startsWith("[[") && data.endsWith("]]");
|
|
@@ -75,17 +74,116 @@ export function validateSchema(schema: any): undefined | string {
|
|
|
75
74
|
return;
|
|
76
75
|
}
|
|
77
76
|
|
|
77
|
+
/**
|
|
78
|
+
* Best-effort: infer a JSON Schema (draft 2020-12) from the *shape* of a single
|
|
79
|
+
* sample value. Types are guessed from one example, so the result is a hint,
|
|
80
|
+
* not a contract — the top-level schema is marked `"x-inferred": true`.
|
|
81
|
+
*
|
|
82
|
+
* Useful when a tag/object type has no declared schema but an example object
|
|
83
|
+
* exists and you want a plausible schema for it.
|
|
84
|
+
*/
|
|
85
|
+
export function inferFromObject(value: any): any {
|
|
86
|
+
const schema = inferSchemaNode(value);
|
|
87
|
+
schema["$schema"] = "https://json-schema.org/draft/2020-12/schema";
|
|
88
|
+
schema["x-inferred"] = true;
|
|
89
|
+
return schema;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Infer a bare JSON Schema node for a value, recursing into arrays/objects. */
|
|
93
|
+
function inferSchemaNode(value: any): any {
|
|
94
|
+
if (value === null || value === undefined) {
|
|
95
|
+
return { type: "null" };
|
|
96
|
+
}
|
|
97
|
+
if (Array.isArray(value)) {
|
|
98
|
+
const node: any = { type: "array" };
|
|
99
|
+
if (value.length > 0) {
|
|
100
|
+
node.items = inferSchemaNode(value[0]);
|
|
101
|
+
}
|
|
102
|
+
return node;
|
|
103
|
+
}
|
|
104
|
+
switch (typeof value) {
|
|
105
|
+
case "boolean":
|
|
106
|
+
return { type: "boolean" };
|
|
107
|
+
case "number":
|
|
108
|
+
return { type: Number.isInteger(value) ? "integer" : "number" };
|
|
109
|
+
case "string":
|
|
110
|
+
return { type: "string" };
|
|
111
|
+
case "object": {
|
|
112
|
+
const properties: Record<string, any> = {};
|
|
113
|
+
for (const [k, v] of Object.entries(value)) {
|
|
114
|
+
properties[k] = inferSchemaNode(v);
|
|
115
|
+
}
|
|
116
|
+
return { type: "object", properties };
|
|
117
|
+
}
|
|
118
|
+
default:
|
|
119
|
+
// functions, symbols, bigint, … — not representable in JSON Schema.
|
|
120
|
+
return {};
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
78
124
|
export function jsonschemaSyscalls(): SysCallMapping {
|
|
79
125
|
return {
|
|
80
|
-
"jsonschema.validateObject":
|
|
81
|
-
_ctx,
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
126
|
+
"jsonschema.validateObject": {
|
|
127
|
+
callback: (_ctx, schema: any, object: any): undefined | string => {
|
|
128
|
+
return validateObject(schema, object);
|
|
129
|
+
},
|
|
130
|
+
description: "Validates a value against a JSON Schema.",
|
|
131
|
+
parameters: [
|
|
132
|
+
{
|
|
133
|
+
name: "schema",
|
|
134
|
+
type: "table",
|
|
135
|
+
description: "JSON Schema to apply.",
|
|
136
|
+
},
|
|
137
|
+
{ name: "object", description: "Value to validate." },
|
|
138
|
+
],
|
|
139
|
+
returns: [
|
|
140
|
+
{
|
|
141
|
+
type: "string",
|
|
142
|
+
description: "Validation error, or nil when valid.",
|
|
143
|
+
},
|
|
144
|
+
],
|
|
145
|
+
examples: [
|
|
146
|
+
{
|
|
147
|
+
code: 'local schema = {type = "object", properties = {name = {type = "string"}}, required = {"name"}}\nlocal err = jsonschema.validateObject(schema, {name = "John"})',
|
|
148
|
+
},
|
|
149
|
+
],
|
|
150
|
+
},
|
|
151
|
+
"jsonschema.validateSchema": {
|
|
152
|
+
callback: (_ctx, schema: any): undefined | string => {
|
|
153
|
+
return validateSchema(schema);
|
|
154
|
+
},
|
|
155
|
+
description:
|
|
156
|
+
"Checks whether a JSON Schema has a supported top-level shape.",
|
|
157
|
+
parameters: [{ name: "schema", description: "JSON Schema to validate." }],
|
|
158
|
+
returns: [
|
|
159
|
+
{ type: "string", description: "Schema error, or nil when valid." },
|
|
160
|
+
],
|
|
161
|
+
examples: [
|
|
162
|
+
{
|
|
163
|
+
code: 'local err = jsonschema.validateSchema({type = "object"})',
|
|
164
|
+
},
|
|
165
|
+
],
|
|
86
166
|
},
|
|
87
|
-
"jsonschema.
|
|
88
|
-
|
|
167
|
+
"jsonschema.inferFromObject": {
|
|
168
|
+
callback: (_ctx, object: any): any => {
|
|
169
|
+
return inferFromObject(object);
|
|
170
|
+
},
|
|
171
|
+
description:
|
|
172
|
+
"Infers a best-effort draft 2020-12 JSON Schema from a sample value.",
|
|
173
|
+
parameters: [
|
|
174
|
+
{
|
|
175
|
+
name: "object",
|
|
176
|
+
description: "Sample value whose shape is inferred.",
|
|
177
|
+
},
|
|
178
|
+
],
|
|
179
|
+
returns: [
|
|
180
|
+
{ type: "table", description: "Inferred schema marked x-inferred." },
|
|
181
|
+
],
|
|
182
|
+
examples: [
|
|
183
|
+
{
|
|
184
|
+
code: 'local schema = jsonschema.inferFromObject({name = "Widget", count = 3})',
|
|
185
|
+
},
|
|
186
|
+
],
|
|
89
187
|
},
|
|
90
188
|
};
|
|
91
189
|
}
|
|
@@ -9,19 +9,45 @@ import {
|
|
|
9
9
|
|
|
10
10
|
export function languageSyscalls(): SysCallMapping {
|
|
11
11
|
return {
|
|
12
|
-
"language.parseLanguage":
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
12
|
+
"language.parseLanguage": {
|
|
13
|
+
callback: async (
|
|
14
|
+
_ctx,
|
|
15
|
+
language: string,
|
|
16
|
+
code: string,
|
|
17
|
+
): Promise<ParseTree> => {
|
|
18
|
+
const lang = languageFor(language) ?? (await loadLanguageFor(language));
|
|
19
|
+
if (!lang) {
|
|
20
|
+
throw new Error(`Unknown language ${language}`);
|
|
21
|
+
}
|
|
22
|
+
return parse(lang, code);
|
|
23
|
+
},
|
|
24
|
+
description: "Parses code using a supported fenced-code-block language.",
|
|
25
|
+
parameters: [
|
|
26
|
+
{
|
|
27
|
+
name: "language",
|
|
28
|
+
type: "string",
|
|
29
|
+
description: "Language name or alias.",
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: "code",
|
|
33
|
+
type: "string",
|
|
34
|
+
description: "Source code to parse.",
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
returns: [{ type: "table", description: "Parsed syntax tree." }],
|
|
38
|
+
examples: [
|
|
39
|
+
{
|
|
40
|
+
code: 'local tree = language.parseLanguage("javascript", "const answer = 42")',
|
|
41
|
+
},
|
|
42
|
+
],
|
|
22
43
|
},
|
|
23
|
-
"language.listLanguages":
|
|
24
|
-
|
|
44
|
+
"language.listLanguages": {
|
|
45
|
+
callback: (): string[] => {
|
|
46
|
+
return allLanguageNames;
|
|
47
|
+
},
|
|
48
|
+
description: "Lists all supported fenced-code-block languages.",
|
|
49
|
+
returns: [{ type: "table", description: "Supported language names." }],
|
|
50
|
+
examples: [{ code: "local languages = language.listLanguages()" }],
|
|
25
51
|
},
|
|
26
52
|
};
|
|
27
53
|
}
|