@crowdedkingdoms/crowdyjs 9.0.0 → 10.0.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/MIGRATION.md +56 -34
- package/README.md +83 -50
- package/dist/crowdy-client.d.ts +3 -0
- package/dist/crowdy-client.d.ts.map +1 -1
- package/dist/crowdy-client.js +2 -0
- package/dist/domains/playerCodeProjects.d.ts +25 -0
- package/dist/domains/playerCodeProjects.d.ts.map +1 -0
- package/dist/domains/playerCodeProjects.js +299 -0
- package/dist/domains/playerCompute.d.ts +1 -1
- package/dist/domains/playerCompute.js +1 -1
- package/dist/generated/graphql.d.ts +792 -7
- package/dist/generated/graphql.d.ts.map +1 -1
- package/dist/generated/graphql.js +57 -0
- package/dist/index.d.ts +3 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -5
- package/dist/kit/npcs.d.ts.map +1 -1
- package/dist/kit/social.d.ts.map +1 -1
- package/dist/live-coding/rust-analysis.d.ts.map +1 -1
- package/dist/live-coding/rust-analysis.js +64 -1
- package/dist/live-coding/worker-transport.d.ts +3 -0
- package/dist/live-coding/worker-transport.d.ts.map +1 -1
- package/dist/live-coding/worker-transport.js +13 -0
- package/dist/mod-studio/controller.d.ts +188 -0
- package/dist/mod-studio/controller.d.ts.map +1 -0
- package/dist/mod-studio/controller.js +915 -0
- package/dist/mod-studio/diagnostics.d.ts +22 -0
- package/dist/mod-studio/diagnostics.d.ts.map +1 -0
- package/dist/mod-studio/diagnostics.js +141 -0
- package/dist/mod-studio/dom-shell.d.ts +55 -0
- package/dist/mod-studio/dom-shell.d.ts.map +1 -0
- package/dist/mod-studio/dom-shell.js +527 -0
- package/dist/mod-studio/editor.d.ts +17 -0
- package/dist/mod-studio/editor.d.ts.map +1 -0
- package/dist/mod-studio/editor.js +1 -0
- package/dist/mod-studio/index.d.ts +10 -0
- package/dist/mod-studio/index.d.ts.map +1 -0
- package/dist/mod-studio/index.js +9 -0
- package/dist/mod-studio/models.d.ts +149 -0
- package/dist/mod-studio/models.d.ts.map +1 -0
- package/dist/mod-studio/models.js +62 -0
- package/dist/mod-studio/monaco-editor.d.ts +16 -0
- package/dist/mod-studio/monaco-editor.d.ts.map +1 -0
- package/dist/mod-studio/monaco-editor.js +548 -0
- package/dist/mod-studio/mount.d.ts +17 -0
- package/dist/mod-studio/mount.d.ts.map +1 -0
- package/dist/mod-studio/mount.js +86 -0
- package/dist/mod-studio/starter-projects.d.ts +11 -0
- package/dist/mod-studio/starter-projects.d.ts.map +1 -0
- package/dist/mod-studio/starter-projects.js +102 -0
- package/dist/mod-studio/styles.d.ts +2 -0
- package/dist/mod-studio/styles.d.ts.map +1 -0
- package/dist/mod-studio/styles.js +14 -0
- package/dist/mod-studio/textarea-editor.d.ts +8 -0
- package/dist/mod-studio/textarea-editor.d.ts.map +1 -0
- package/dist/mod-studio/textarea-editor.js +71 -0
- package/package.json +4 -4
- package/dist/live-coding/ide.d.ts +0 -23
- package/dist/live-coding/ide.d.ts.map +0 -1
- package/dist/live-coding/ide.js +0 -514
- package/dist/live-coding/index.d.ts +0 -8
- package/dist/live-coding/index.d.ts.map +0 -1
- package/dist/live-coding/index.js +0 -7
- package/dist/live-coding/live-coding-controller.d.ts +0 -75
- package/dist/live-coding/live-coding-controller.d.ts.map +0 -1
- package/dist/live-coding/live-coding-controller.js +0 -141
- package/dist/live-coding/mount.d.ts +0 -26
- package/dist/live-coding/mount.d.ts.map +0 -1
- package/dist/live-coding/mount.js +0 -108
- package/dist/live-coding/templates.d.ts +0 -17
- package/dist/live-coding/templates.d.ts.map +0 -1
- package/dist/live-coding/templates.js +0 -59
package/dist/live-coding/ide.js
DELETED
|
@@ -1,514 +0,0 @@
|
|
|
1
|
-
import { LiveCodingController, } from './live-coding-controller.js';
|
|
2
|
-
import { mountLiveCoding, } from './mount.js';
|
|
3
|
-
import { isRecord, } from './lsp-protocol.js';
|
|
4
|
-
import { loadPlatformIndex, } from './platform-index.js';
|
|
5
|
-
import { PLAYER_CODE_TEMPLATES } from './templates.js';
|
|
6
|
-
import { acquireMonacoWorkspace, ensureMonacoServicesInitialized, } from './monaco-services.js';
|
|
7
|
-
let monacoLanguagesRegistered = false;
|
|
8
|
-
/**
|
|
9
|
-
* Lazy Monaco live-coding IDE backed only by a browser module worker and local
|
|
10
|
-
* WASM parser assets. If Monaco, Worker, or WASM startup fails, the dependency-
|
|
11
|
-
* free textarea is mounted; there is deliberately no server fallback.
|
|
12
|
-
*/
|
|
13
|
-
export async function mountLiveCodingIDE(el, options) {
|
|
14
|
-
if (!options.languageWorkerFactory && typeof Worker === 'undefined') {
|
|
15
|
-
return mountLiveCoding(el, options);
|
|
16
|
-
}
|
|
17
|
-
if (options.editorWorkerFactory) {
|
|
18
|
-
globalThis.MonacoEnvironment = { getWorker: options.editorWorkerFactory };
|
|
19
|
-
}
|
|
20
|
-
let languageWorker = null;
|
|
21
|
-
let languageClient = null;
|
|
22
|
-
let releaseWorkspace = null;
|
|
23
|
-
let teardownMountedIde = null;
|
|
24
|
-
try {
|
|
25
|
-
const platformIndex = options.platformIndex === undefined
|
|
26
|
-
? undefined
|
|
27
|
-
: loadPlatformIndex(options.platformIndex);
|
|
28
|
-
const workerTransportPromise = import('./worker-transport.js');
|
|
29
|
-
await ensureMonacoServicesInitialized();
|
|
30
|
-
const [monaco, workerTransport] = await Promise.all([
|
|
31
|
-
import('@codingame/monaco-vscode-editor-api'),
|
|
32
|
-
workerTransportPromise,
|
|
33
|
-
]);
|
|
34
|
-
if (!monacoLanguagesRegistered) {
|
|
35
|
-
monaco.languages.register({ id: 'rust', extensions: ['.rs'] });
|
|
36
|
-
installRustSyntaxHighlighting(monaco);
|
|
37
|
-
monaco.languages.register({ id: 'toml', extensions: ['.toml'] });
|
|
38
|
-
monacoLanguagesRegistered = true;
|
|
39
|
-
}
|
|
40
|
-
const templates = options.templates ?? PLAYER_CODE_TEMPLATES;
|
|
41
|
-
const root = document.createElement('div');
|
|
42
|
-
root.className = 'ck-live-coding ck-live-coding-ide';
|
|
43
|
-
root.style.cssText =
|
|
44
|
-
'display:grid;grid-template-rows:auto auto minmax(320px,1fr) auto auto;' +
|
|
45
|
-
'gap:6px;min-height:520px;';
|
|
46
|
-
const controls = document.createElement('div');
|
|
47
|
-
controls.className = 'ck-live-coding-controls';
|
|
48
|
-
const target = select(['server', 'client']);
|
|
49
|
-
const template = document.createElement('select');
|
|
50
|
-
const deploy = button('Deploy');
|
|
51
|
-
const draft = button('Deploy draft');
|
|
52
|
-
const stop = button('Stop');
|
|
53
|
-
controls.append(target, template, deploy, draft, stop);
|
|
54
|
-
const tabs = document.createElement('div');
|
|
55
|
-
tabs.className = 'ck-live-coding-tabs';
|
|
56
|
-
tabs.style.cssText = 'display:flex;gap:4px;flex-wrap:wrap;';
|
|
57
|
-
const editorHost = document.createElement('div');
|
|
58
|
-
editorHost.className = 'ck-live-coding-monaco';
|
|
59
|
-
editorHost.style.cssText = 'min-height:320px;border:1px solid #333;';
|
|
60
|
-
const problems = document.createElement('div');
|
|
61
|
-
problems.className = 'ck-live-coding-problems';
|
|
62
|
-
const status = document.createElement('pre');
|
|
63
|
-
status.className = 'ck-live-coding-status';
|
|
64
|
-
const meter = document.createElement('div');
|
|
65
|
-
meter.className = 'ck-live-coding-meter';
|
|
66
|
-
root.append(controls, tabs, editorHost, problems, status, meter);
|
|
67
|
-
el.appendChild(root);
|
|
68
|
-
const controller = new LiveCodingController({
|
|
69
|
-
...options,
|
|
70
|
-
onStatus: (value) => renderStatus(status, meter, value),
|
|
71
|
-
});
|
|
72
|
-
const workspaceLease = acquireMonacoWorkspace();
|
|
73
|
-
releaseWorkspace = workspaceLease.release;
|
|
74
|
-
const modelRootUri = workspaceLease.uri;
|
|
75
|
-
const ownsModel = (uri) => uri.toString().startsWith(`${modelRootUri}/`);
|
|
76
|
-
const editor = monaco.editor.create(editorHost, {
|
|
77
|
-
automaticLayout: true,
|
|
78
|
-
minimap: { enabled: false },
|
|
79
|
-
theme: 'vs-dark',
|
|
80
|
-
fontSize: 14,
|
|
81
|
-
tabSize: 2,
|
|
82
|
-
});
|
|
83
|
-
let models = [];
|
|
84
|
-
const languageDisposables = [];
|
|
85
|
-
const sourceJson = () => JSON.stringify(Object.fromEntries(models.map(({ path, model }) => [path, model.getValue()])));
|
|
86
|
-
const showModel = (path) => {
|
|
87
|
-
const found = models.find((entry) => entry.path === path);
|
|
88
|
-
if (found)
|
|
89
|
-
editor.setModel(found.model);
|
|
90
|
-
for (const child of Array.from(tabs.children)) {
|
|
91
|
-
child.dataset.active =
|
|
92
|
-
child.dataset.path === path ? 'true' : 'false';
|
|
93
|
-
}
|
|
94
|
-
};
|
|
95
|
-
const closeModels = () => {
|
|
96
|
-
for (const entry of models) {
|
|
97
|
-
if (entry.path.endsWith('.rs')) {
|
|
98
|
-
void languageClient
|
|
99
|
-
?.notify('textDocument/didClose', {
|
|
100
|
-
textDocument: { uri: entry.model.uri.toString() },
|
|
101
|
-
})
|
|
102
|
-
.catch(() => { });
|
|
103
|
-
}
|
|
104
|
-
entry.changeSubscription.dispose();
|
|
105
|
-
entry.model.dispose();
|
|
106
|
-
}
|
|
107
|
-
models = [];
|
|
108
|
-
};
|
|
109
|
-
const openModel = (entry) => {
|
|
110
|
-
if (!entry.path.endsWith('.rs'))
|
|
111
|
-
return;
|
|
112
|
-
void languageClient
|
|
113
|
-
?.notify('textDocument/didOpen', {
|
|
114
|
-
textDocument: {
|
|
115
|
-
uri: entry.model.uri.toString(),
|
|
116
|
-
languageId: 'rust',
|
|
117
|
-
version: entry.model.getVersionId(),
|
|
118
|
-
text: entry.model.getValue(),
|
|
119
|
-
},
|
|
120
|
-
})
|
|
121
|
-
.catch(() => { });
|
|
122
|
-
};
|
|
123
|
-
const setFiles = (sourceFilesJson) => {
|
|
124
|
-
closeModels();
|
|
125
|
-
tabs.replaceChildren();
|
|
126
|
-
const files = parseFiles(sourceFilesJson);
|
|
127
|
-
for (const [path, content] of Object.entries(files)) {
|
|
128
|
-
const uri = monaco.Uri.parse(`${modelRootUri}/${path}`);
|
|
129
|
-
const model = monaco.editor.createModel(content, path.endsWith('.rs') ? 'rust' : path.endsWith('.toml') ? 'toml' : 'plaintext', uri);
|
|
130
|
-
const entry = {
|
|
131
|
-
path,
|
|
132
|
-
model,
|
|
133
|
-
changeSubscription: { dispose: () => { } },
|
|
134
|
-
};
|
|
135
|
-
entry.changeSubscription = model.onDidChangeContent(() => {
|
|
136
|
-
if (!path.endsWith('.rs'))
|
|
137
|
-
return;
|
|
138
|
-
void languageClient
|
|
139
|
-
?.notify('textDocument/didChange', {
|
|
140
|
-
textDocument: {
|
|
141
|
-
uri: model.uri.toString(),
|
|
142
|
-
version: model.getVersionId(),
|
|
143
|
-
},
|
|
144
|
-
contentChanges: [{ text: model.getValue() }],
|
|
145
|
-
})
|
|
146
|
-
.catch(() => { });
|
|
147
|
-
});
|
|
148
|
-
models.push(entry);
|
|
149
|
-
openModel(entry);
|
|
150
|
-
const tab = button(path);
|
|
151
|
-
tab.dataset.path = path;
|
|
152
|
-
tab.addEventListener('click', () => showModel(path));
|
|
153
|
-
tabs.appendChild(tab);
|
|
154
|
-
}
|
|
155
|
-
const preferred = models.find((entry) => entry.path === 'src/lib.rs') ?? models[0];
|
|
156
|
-
if (preferred)
|
|
157
|
-
showModel(preferred.path);
|
|
158
|
-
};
|
|
159
|
-
const refreshTemplates = () => {
|
|
160
|
-
template.replaceChildren();
|
|
161
|
-
const matching = templates.filter((item) => item.target === target.value);
|
|
162
|
-
for (const item of matching)
|
|
163
|
-
template.append(new Option(item.title, item.id));
|
|
164
|
-
if (matching[0])
|
|
165
|
-
setFiles(matching[0].sourceFilesJson);
|
|
166
|
-
};
|
|
167
|
-
target.addEventListener('change', refreshTemplates);
|
|
168
|
-
template.addEventListener('change', () => {
|
|
169
|
-
const selected = templates.find((item) => item.id === template.value);
|
|
170
|
-
if (selected)
|
|
171
|
-
setFiles(selected.sourceFilesJson);
|
|
172
|
-
});
|
|
173
|
-
const doDeploy = (draftMode) => {
|
|
174
|
-
void controller
|
|
175
|
-
.deploy({
|
|
176
|
-
name: options.moduleName ?? 'scratch-mod',
|
|
177
|
-
target: target.value,
|
|
178
|
-
sourceFilesJson: sourceJson(),
|
|
179
|
-
draft: draftMode || options.draftByDefault,
|
|
180
|
-
})
|
|
181
|
-
.catch((error) => {
|
|
182
|
-
status.textContent = `error: ${error.message}`;
|
|
183
|
-
});
|
|
184
|
-
};
|
|
185
|
-
deploy.addEventListener('click', () => doDeploy(false));
|
|
186
|
-
draft.addEventListener('click', () => doDeploy(true));
|
|
187
|
-
stop.addEventListener('click', () => controller.stop());
|
|
188
|
-
const markerSubscription = monaco.editor.onDidChangeMarkers(() => {
|
|
189
|
-
const markers = monaco.editor.getModelMarkers({ owner: 'crowdy-rust' });
|
|
190
|
-
const errors = markers.filter((marker) => marker.severity === monaco.MarkerSeverity.Error).length;
|
|
191
|
-
const warnings = markers.filter((marker) => marker.severity === monaco.MarkerSeverity.Warning).length;
|
|
192
|
-
problems.textContent = `${errors} error(s) · ${warnings} warning(s)`;
|
|
193
|
-
});
|
|
194
|
-
let tornDown = false;
|
|
195
|
-
teardownMountedIde = (graceful) => {
|
|
196
|
-
if (tornDown)
|
|
197
|
-
return;
|
|
198
|
-
tornDown = true;
|
|
199
|
-
markerSubscription.dispose();
|
|
200
|
-
for (const disposable of languageDisposables)
|
|
201
|
-
disposable.dispose();
|
|
202
|
-
controller.stop();
|
|
203
|
-
closeModels();
|
|
204
|
-
if (graceful)
|
|
205
|
-
languageClient?.shutdown();
|
|
206
|
-
else
|
|
207
|
-
languageClient?.dispose();
|
|
208
|
-
editor.dispose();
|
|
209
|
-
root.remove();
|
|
210
|
-
releaseWorkspace?.();
|
|
211
|
-
releaseWorkspace = null;
|
|
212
|
-
};
|
|
213
|
-
refreshTemplates();
|
|
214
|
-
languageWorker =
|
|
215
|
-
options.languageWorkerFactory?.() ??
|
|
216
|
-
workerTransport.createDefaultRustLanguageWorker();
|
|
217
|
-
languageClient = new workerTransport.WorkerLanguageClient(languageWorker, {
|
|
218
|
-
requestTimeoutMs: options.languageRequestTimeoutMs,
|
|
219
|
-
});
|
|
220
|
-
languageDisposables.push(languageClient.onNotification('textDocument/publishDiagnostics', (params) => {
|
|
221
|
-
if (!isRecord(params) || typeof params.uri !== 'string')
|
|
222
|
-
return;
|
|
223
|
-
const model = monaco.editor.getModel(monaco.Uri.parse(params.uri));
|
|
224
|
-
if (!model)
|
|
225
|
-
return;
|
|
226
|
-
if (!isCurrentDiagnosticVersion(params.version, model.getVersionId())) {
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
229
|
-
const diagnostics = Array.isArray(params.diagnostics)
|
|
230
|
-
? params.diagnostics
|
|
231
|
-
: [];
|
|
232
|
-
monaco.editor.setModelMarkers(model, 'crowdy-rust', diagnostics.map((diagnostic) => ({
|
|
233
|
-
...toMonacoRange(diagnostic.range),
|
|
234
|
-
severity: diagnosticSeverity(monaco, diagnostic.severity),
|
|
235
|
-
message: diagnostic.message,
|
|
236
|
-
code: diagnostic.code,
|
|
237
|
-
source: diagnostic.source,
|
|
238
|
-
})));
|
|
239
|
-
}));
|
|
240
|
-
await languageClient.initialize({
|
|
241
|
-
processId: null,
|
|
242
|
-
clientInfo: { name: 'CrowdyJS Monaco', version: '1' },
|
|
243
|
-
rootUri: modelRootUri,
|
|
244
|
-
capabilities: {
|
|
245
|
-
general: { positionEncodings: ['utf-16'] },
|
|
246
|
-
textDocument: {
|
|
247
|
-
completion: {},
|
|
248
|
-
hover: { contentFormat: ['markdown', 'plaintext'] },
|
|
249
|
-
documentSymbol: {},
|
|
250
|
-
definition: {},
|
|
251
|
-
publishDiagnostics: { versionSupport: true },
|
|
252
|
-
},
|
|
253
|
-
},
|
|
254
|
-
initializationOptions: {
|
|
255
|
-
...(platformIndex === undefined
|
|
256
|
-
? {}
|
|
257
|
-
: { platformIndex }),
|
|
258
|
-
},
|
|
259
|
-
});
|
|
260
|
-
for (const entry of models)
|
|
261
|
-
openModel(entry);
|
|
262
|
-
languageDisposables.push(monaco.languages.registerCompletionItemProvider('rust', {
|
|
263
|
-
triggerCharacters: [':', '.'],
|
|
264
|
-
provideCompletionItems: async (model, position) => {
|
|
265
|
-
if (!ownsModel(model.uri))
|
|
266
|
-
return { suggestions: [] };
|
|
267
|
-
const word = model.getWordUntilPosition(position);
|
|
268
|
-
const range = {
|
|
269
|
-
startLineNumber: position.lineNumber,
|
|
270
|
-
startColumn: word.startColumn,
|
|
271
|
-
endLineNumber: position.lineNumber,
|
|
272
|
-
endColumn: position.column,
|
|
273
|
-
};
|
|
274
|
-
const response = (await languageClient?.request('textDocument/completion', lspDocumentPosition(model.uri.toString(), position)));
|
|
275
|
-
return {
|
|
276
|
-
suggestions: (response ?? []).map((item) => ({
|
|
277
|
-
label: item.label,
|
|
278
|
-
kind: completionKind(monaco, item.kind),
|
|
279
|
-
detail: item.detail,
|
|
280
|
-
documentation: item.documentation,
|
|
281
|
-
insertText: item.insertText ?? item.label,
|
|
282
|
-
range,
|
|
283
|
-
})),
|
|
284
|
-
};
|
|
285
|
-
},
|
|
286
|
-
}), monaco.languages.registerHoverProvider('rust', {
|
|
287
|
-
provideHover: async (model, position) => {
|
|
288
|
-
if (!ownsModel(model.uri))
|
|
289
|
-
return null;
|
|
290
|
-
const response = (await languageClient?.request('textDocument/hover', lspDocumentPosition(model.uri.toString(), position)));
|
|
291
|
-
if (!response)
|
|
292
|
-
return null;
|
|
293
|
-
return {
|
|
294
|
-
contents: [{ value: response.contents.value }],
|
|
295
|
-
range: response.range
|
|
296
|
-
? new monaco.Range(response.range.start.line + 1, response.range.start.character + 1, response.range.end.line + 1, response.range.end.character + 1)
|
|
297
|
-
: undefined,
|
|
298
|
-
};
|
|
299
|
-
},
|
|
300
|
-
}), monaco.languages.registerDocumentSymbolProvider('rust', {
|
|
301
|
-
provideDocumentSymbols: async (model) => {
|
|
302
|
-
if (!ownsModel(model.uri))
|
|
303
|
-
return [];
|
|
304
|
-
const response = (await languageClient?.request('textDocument/documentSymbol', { textDocument: { uri: model.uri.toString() } }));
|
|
305
|
-
return (response ?? []).map((symbol) => ({
|
|
306
|
-
name: symbol.name,
|
|
307
|
-
detail: symbol.detail ?? '',
|
|
308
|
-
kind: symbolKind(monaco, symbol.kind),
|
|
309
|
-
tags: [],
|
|
310
|
-
range: toMonacoRange(symbol.range),
|
|
311
|
-
selectionRange: toMonacoRange(symbol.selectionRange),
|
|
312
|
-
}));
|
|
313
|
-
},
|
|
314
|
-
}), monaco.languages.registerDefinitionProvider('rust', {
|
|
315
|
-
provideDefinition: async (model, position) => {
|
|
316
|
-
if (!ownsModel(model.uri))
|
|
317
|
-
return null;
|
|
318
|
-
const response = (await languageClient?.request('textDocument/definition', lspDocumentPosition(model.uri.toString(), position)));
|
|
319
|
-
if (!response)
|
|
320
|
-
return null;
|
|
321
|
-
return {
|
|
322
|
-
uri: monaco.Uri.parse(response.uri),
|
|
323
|
-
range: toMonacoRange(response.range),
|
|
324
|
-
};
|
|
325
|
-
},
|
|
326
|
-
}));
|
|
327
|
-
void controller.refreshUsage().catch(() => { });
|
|
328
|
-
return {
|
|
329
|
-
controller,
|
|
330
|
-
destroy: () => teardownMountedIde?.(true),
|
|
331
|
-
};
|
|
332
|
-
}
|
|
333
|
-
catch (error) {
|
|
334
|
-
if (teardownMountedIde) {
|
|
335
|
-
teardownMountedIde(false);
|
|
336
|
-
}
|
|
337
|
-
else {
|
|
338
|
-
languageClient?.dispose();
|
|
339
|
-
if (!languageClient)
|
|
340
|
-
languageWorker?.terminate();
|
|
341
|
-
releaseWorkspace?.();
|
|
342
|
-
releaseWorkspace = null;
|
|
343
|
-
}
|
|
344
|
-
console.warn('Browser Rust IDE unavailable; using textarea fallback', error);
|
|
345
|
-
el.replaceChildren();
|
|
346
|
-
return mountLiveCoding(el, options);
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
function installRustSyntaxHighlighting(monaco) {
|
|
350
|
-
const keywords = new Set([
|
|
351
|
-
'as', 'async', 'await', 'break', 'const', 'continue', 'crate', 'dyn',
|
|
352
|
-
'else', 'enum', 'extern', 'false', 'fn', 'for', 'if', 'impl', 'in',
|
|
353
|
-
'let', 'loop', 'match', 'mod', 'move', 'mut', 'pub', 'ref', 'return',
|
|
354
|
-
'self', 'static', 'struct', 'super', 'trait', 'true', 'type', 'unsafe',
|
|
355
|
-
'use', 'where', 'while',
|
|
356
|
-
]);
|
|
357
|
-
const types = new Set([
|
|
358
|
-
'Self', 'String', 'Vec', 'Option', 'Result', 'bool', 'char', 'str',
|
|
359
|
-
'usize', 'isize', 'u8', 'u16', 'u32', 'u64', 'u128', 'i8', 'i16',
|
|
360
|
-
'i32', 'i64', 'i128', 'f32', 'f64',
|
|
361
|
-
]);
|
|
362
|
-
const state = {
|
|
363
|
-
clone() {
|
|
364
|
-
return this;
|
|
365
|
-
},
|
|
366
|
-
equals(other) {
|
|
367
|
-
return other === this;
|
|
368
|
-
},
|
|
369
|
-
};
|
|
370
|
-
monaco.languages.setTokensProvider('rust', {
|
|
371
|
-
getInitialState: () => state,
|
|
372
|
-
tokenize: (line, currentState) => {
|
|
373
|
-
const tokens = [];
|
|
374
|
-
let index = 0;
|
|
375
|
-
while (index < line.length) {
|
|
376
|
-
const rest = line.slice(index);
|
|
377
|
-
let match;
|
|
378
|
-
if ((match = rest.match(/^\s+/u))) {
|
|
379
|
-
tokens.push({ startIndex: index, scopes: '' });
|
|
380
|
-
}
|
|
381
|
-
else if ((match = rest.match(/^\/\/.*$/u))) {
|
|
382
|
-
tokens.push({ startIndex: index, scopes: 'comment.rust' });
|
|
383
|
-
}
|
|
384
|
-
else if ((match = rest.match(/^\/\*.*?(?:\*\/|$)/u))) {
|
|
385
|
-
tokens.push({ startIndex: index, scopes: 'comment.rust' });
|
|
386
|
-
}
|
|
387
|
-
else if ((match = rest.match(/^"(?:\\.|[^"\\])*"?/u))) {
|
|
388
|
-
tokens.push({ startIndex: index, scopes: 'string.rust' });
|
|
389
|
-
}
|
|
390
|
-
else if ((match = rest.match(/^(?:0x[\da-fA-F_]+|\d[\d_]*)/u))) {
|
|
391
|
-
tokens.push({ startIndex: index, scopes: 'number.rust' });
|
|
392
|
-
}
|
|
393
|
-
else if ((match = rest.match(/^[A-Za-z_]\w*!/u))) {
|
|
394
|
-
tokens.push({ startIndex: index, scopes: 'macro.rust' });
|
|
395
|
-
}
|
|
396
|
-
else if ((match = rest.match(/^[A-Za-z_]\w*/u))) {
|
|
397
|
-
const word = match[0];
|
|
398
|
-
tokens.push({
|
|
399
|
-
startIndex: index,
|
|
400
|
-
scopes: keywords.has(word)
|
|
401
|
-
? 'keyword.rust'
|
|
402
|
-
: types.has(word)
|
|
403
|
-
? 'type.rust'
|
|
404
|
-
: 'identifier.rust',
|
|
405
|
-
});
|
|
406
|
-
}
|
|
407
|
-
else {
|
|
408
|
-
match = rest.match(/^./u);
|
|
409
|
-
tokens.push({ startIndex: index, scopes: 'delimiter.rust' });
|
|
410
|
-
}
|
|
411
|
-
index += match?.[0].length ?? 1;
|
|
412
|
-
}
|
|
413
|
-
return { tokens, endState: currentState };
|
|
414
|
-
},
|
|
415
|
-
});
|
|
416
|
-
}
|
|
417
|
-
function parseFiles(sourceFilesJson) {
|
|
418
|
-
const parsed = JSON.parse(sourceFilesJson);
|
|
419
|
-
if (!isRecord(parsed))
|
|
420
|
-
throw new Error('sourceFilesJson must be an object');
|
|
421
|
-
return Object.fromEntries(Object.entries(parsed).map(([path, value]) => {
|
|
422
|
-
if (typeof value !== 'string' ||
|
|
423
|
-
path.startsWith('/') ||
|
|
424
|
-
path.split('/').some((part) => part === '' || part === '.' || part === '..')) {
|
|
425
|
-
throw new Error(`Invalid source file ${path}`);
|
|
426
|
-
}
|
|
427
|
-
return [path, value];
|
|
428
|
-
}));
|
|
429
|
-
}
|
|
430
|
-
function lspDocumentPosition(uri, position) {
|
|
431
|
-
return {
|
|
432
|
-
textDocument: { uri },
|
|
433
|
-
position: {
|
|
434
|
-
line: position.lineNumber - 1,
|
|
435
|
-
character: position.column - 1,
|
|
436
|
-
},
|
|
437
|
-
};
|
|
438
|
-
}
|
|
439
|
-
function toMonacoRange(range) {
|
|
440
|
-
return {
|
|
441
|
-
startLineNumber: range.start.line + 1,
|
|
442
|
-
startColumn: range.start.character + 1,
|
|
443
|
-
endLineNumber: range.end.line + 1,
|
|
444
|
-
endColumn: range.end.character + 1,
|
|
445
|
-
};
|
|
446
|
-
}
|
|
447
|
-
export function isCurrentDiagnosticVersion(version, currentVersion) {
|
|
448
|
-
return (version === undefined ||
|
|
449
|
-
(Number.isSafeInteger(version) && version === currentVersion));
|
|
450
|
-
}
|
|
451
|
-
function diagnosticSeverity(monaco, severity) {
|
|
452
|
-
return severity === 1
|
|
453
|
-
? monaco.MarkerSeverity.Error
|
|
454
|
-
: severity === 2
|
|
455
|
-
? monaco.MarkerSeverity.Warning
|
|
456
|
-
: severity === 3
|
|
457
|
-
? monaco.MarkerSeverity.Info
|
|
458
|
-
: monaco.MarkerSeverity.Hint;
|
|
459
|
-
}
|
|
460
|
-
function completionKind(monaco, kind) {
|
|
461
|
-
const kinds = monaco.languages.CompletionItemKind;
|
|
462
|
-
return ({
|
|
463
|
-
3: kinds.Function,
|
|
464
|
-
5: kinds.Field,
|
|
465
|
-
6: kinds.Variable,
|
|
466
|
-
7: kinds.Class,
|
|
467
|
-
9: kinds.Module,
|
|
468
|
-
13: kinds.Enum,
|
|
469
|
-
14: kinds.Keyword,
|
|
470
|
-
15: kinds.Snippet,
|
|
471
|
-
21: kinds.Constant,
|
|
472
|
-
}[kind] ?? kinds.Text);
|
|
473
|
-
}
|
|
474
|
-
function symbolKind(monaco, kind) {
|
|
475
|
-
const kinds = monaco.languages.SymbolKind;
|
|
476
|
-
return ({
|
|
477
|
-
2: kinds.Module,
|
|
478
|
-
5: kinds.Class,
|
|
479
|
-
6: kinds.Method,
|
|
480
|
-
10: kinds.Enum,
|
|
481
|
-
11: kinds.Interface,
|
|
482
|
-
12: kinds.Function,
|
|
483
|
-
13: kinds.Variable,
|
|
484
|
-
14: kinds.Constant,
|
|
485
|
-
23: kinds.Struct,
|
|
486
|
-
}[kind] ?? kinds.Object);
|
|
487
|
-
}
|
|
488
|
-
function select(values) {
|
|
489
|
-
const element = document.createElement('select');
|
|
490
|
-
for (const value of values)
|
|
491
|
-
element.append(new Option(value, value));
|
|
492
|
-
return element;
|
|
493
|
-
}
|
|
494
|
-
function button(label) {
|
|
495
|
-
const element = document.createElement('button');
|
|
496
|
-
element.type = 'button';
|
|
497
|
-
element.textContent = label;
|
|
498
|
-
return element;
|
|
499
|
-
}
|
|
500
|
-
function renderStatus(status, meter, value) {
|
|
501
|
-
status.textContent = [
|
|
502
|
-
`[${value.target}] ${value.phase}`,
|
|
503
|
-
value.message,
|
|
504
|
-
value.compileLog,
|
|
505
|
-
]
|
|
506
|
-
.filter(Boolean)
|
|
507
|
-
.join('\n');
|
|
508
|
-
if (value.usage) {
|
|
509
|
-
meter.textContent =
|
|
510
|
-
`units ${value.usage.hourUnitsUsed}/${value.usage.unitsPerHour ?? '∞'} · ` +
|
|
511
|
-
`compiles ${value.usage.compilesThisHour}/${value.usage.maxCompilesPerHour} · ` +
|
|
512
|
-
`gate ${value.usage.gateStatus}${value.usage.gateReason ? ` (${value.usage.gateReason})` : ''}`;
|
|
513
|
-
}
|
|
514
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export { LiveCodingController, type LiveCodingControllerOptions, type LiveCodingStatus, type LiveCodingTarget, } from './live-coding-controller.js';
|
|
2
|
-
export { mountLiveCoding, type LiveCodingHandle, type MountLiveCodingOptions, } from './mount.js';
|
|
3
|
-
export { mountLiveCodingIDE, type MountLiveCodingIDEOptions, } from './ide.js';
|
|
4
|
-
export { PLAYER_CODE_TEMPLATES, templateById, type PlayerCodeTemplate, } from './templates.js';
|
|
5
|
-
export { EMBEDDED_PLATFORM_INDEX, MAX_PLATFORM_CRATES, MAX_PLATFORM_CRATE_FIELD_LENGTH, MAX_PLATFORM_INDEX_BYTES, computePlatformIndexContentHash, loadPlatformIndex, type PlatformCrate, type PlatformIndex, type PlatformSymbol, type PlatformSymbolKind, } from './platform-index.js';
|
|
6
|
-
export { DEFAULT_VFS_LIMITS, VfsLimitError, VirtualFileSystem, offsetAt, type VirtualDocument, type VirtualFileSystemLimits, } from './vfs.js';
|
|
7
|
-
export { WorkerLanguageClient, WorkerMessageReader, WorkerMessageWriter, createDefaultRustLanguageWorker, type LanguageWorkerLike, type WorkerLanguageClientOptions, } from './worker-transport.js';
|
|
8
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/live-coding/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,KAAK,2BAA2B,EAChC,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,GACtB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,eAAe,EACf,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,GAC5B,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,kBAAkB,EAClB,KAAK,yBAAyB,GAC/B,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,qBAAqB,EACrB,YAAY,EACZ,KAAK,kBAAkB,GACxB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,uBAAuB,EACvB,mBAAmB,EACnB,+BAA+B,EAC/B,wBAAwB,EACxB,+BAA+B,EAC/B,iBAAiB,EACjB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,kBAAkB,GACxB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,iBAAiB,EACjB,QAAQ,EACR,KAAK,eAAe,EACpB,KAAK,uBAAuB,GAC7B,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,+BAA+B,EAC/B,KAAK,kBAAkB,EACvB,KAAK,2BAA2B,GACjC,MAAM,uBAAuB,CAAC"}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export { LiveCodingController, } from './live-coding-controller.js';
|
|
2
|
-
export { mountLiveCoding, } from './mount.js';
|
|
3
|
-
export { mountLiveCodingIDE, } from './ide.js';
|
|
4
|
-
export { PLAYER_CODE_TEMPLATES, templateById, } from './templates.js';
|
|
5
|
-
export { EMBEDDED_PLATFORM_INDEX, MAX_PLATFORM_CRATES, MAX_PLATFORM_CRATE_FIELD_LENGTH, MAX_PLATFORM_INDEX_BYTES, computePlatformIndexContentHash, loadPlatformIndex, } from './platform-index.js';
|
|
6
|
-
export { DEFAULT_VFS_LIMITS, VfsLimitError, VirtualFileSystem, offsetAt, } from './vfs.js';
|
|
7
|
-
export { WorkerLanguageClient, WorkerMessageReader, WorkerMessageWriter, createDefaultRustLanguageWorker, } from './worker-transport.js';
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import type { PlayerComputeAPI } from '../domains/playerCompute.js';
|
|
2
|
-
import type { PlayerWalletAPI } from '../domains/playerWallet.js';
|
|
3
|
-
import { PlayerCodeBroker, type PlayerCodeBrokerOptions, type PlayerCodeGridBounds } from '../player-runtime/player-code-broker.js';
|
|
4
|
-
export type LiveCodingTarget = 'server' | 'client';
|
|
5
|
-
export interface LiveCodingStatus {
|
|
6
|
-
phase: 'idle' | 'deploying' | 'compiling' | 'compile_failed' | 'enabling' | 'running' | 'error';
|
|
7
|
-
target: LiveCodingTarget;
|
|
8
|
-
message?: string;
|
|
9
|
-
compileLog?: string | null;
|
|
10
|
-
/** Remaining-budget snapshot from playerComputeUsage, when loaded. */
|
|
11
|
-
usage?: {
|
|
12
|
-
hourUnitsUsed: string;
|
|
13
|
-
unitsPerHour: string | null;
|
|
14
|
-
compilesThisHour: number;
|
|
15
|
-
maxCompilesPerHour: number;
|
|
16
|
-
gateStatus: string;
|
|
17
|
-
gateReason: string | null;
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
export interface LiveCodingControllerOptions {
|
|
21
|
-
playerCompute: Pick<PlayerComputeAPI, 'deploy' | 'setEnabled' | 'usage' | 'runs' | 'logs' | 'versions' | 'artifactBytes'>;
|
|
22
|
-
playerWallet?: Pick<PlayerWalletAPI, 'balance'>;
|
|
23
|
-
/** BigInt scalars are strings on the wire (codegen). */
|
|
24
|
-
appId: string;
|
|
25
|
-
gridId: string;
|
|
26
|
-
grid: PlayerCodeGridBounds;
|
|
27
|
-
/** The platform glue worker asset URL for client deploys. */
|
|
28
|
-
workerUrl: string | URL;
|
|
29
|
-
/** Page-side host-call router for the broker (World Stores reads + owner effects). */
|
|
30
|
-
onHostCall: PlayerCodeBrokerOptions['onHostCall'];
|
|
31
|
-
onPresentation?: PlayerCodeBrokerOptions['onPresentation'];
|
|
32
|
-
/** Client tick cadence (ms); the worker self-drives `tick` for HUD-style mods. */
|
|
33
|
-
clientTickIntervalMs?: number;
|
|
34
|
-
onStatus?: (status: LiveCodingStatus) => void;
|
|
35
|
-
/** Poll interval for compile status (ms). */
|
|
36
|
-
pollMs?: number;
|
|
37
|
-
/** Injectable clock/sleep + broker factory for tests. */
|
|
38
|
-
sleep?: (ms: number) => Promise<void>;
|
|
39
|
-
brokerFactory?: (options: PlayerCodeBrokerOptions) => PlayerCodeBroker;
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Headless driver for the live-coding deploy loop (08), shared by the DOM
|
|
43
|
-
* panel and any custom host UI. It owns the edit -> deploy -> compile-poll ->
|
|
44
|
-
* (server) enable / (client) fetch+respawn state machine, surfaces compile
|
|
45
|
-
* feedback and the quota/wallet meters, and manages the client broker
|
|
46
|
-
* lifecycle. All IO is injected so it is unit-testable without a browser.
|
|
47
|
-
*/
|
|
48
|
-
export declare class LiveCodingController {
|
|
49
|
-
private readonly options;
|
|
50
|
-
private broker;
|
|
51
|
-
private status;
|
|
52
|
-
constructor(options: LiveCodingControllerOptions);
|
|
53
|
-
getStatus(): LiveCodingStatus;
|
|
54
|
-
private set;
|
|
55
|
-
private sleep;
|
|
56
|
-
/** Refresh the quota/wallet meter for the panel. */
|
|
57
|
-
refreshUsage(): Promise<void>;
|
|
58
|
-
/**
|
|
59
|
-
* Deploy source and run it. For server targets: deploy -> poll compile ->
|
|
60
|
-
* enable. For client targets: deploy -> poll compile -> fetch bytes ->
|
|
61
|
-
* (re)spawn the broker worker. Draft mode suppresses server egress to other
|
|
62
|
-
* sessions while iterating.
|
|
63
|
-
*/
|
|
64
|
-
deploy(input: {
|
|
65
|
-
name: string;
|
|
66
|
-
target: LiveCodingTarget;
|
|
67
|
-
sourceFilesJson: string;
|
|
68
|
-
tickHz?: number;
|
|
69
|
-
draft?: boolean;
|
|
70
|
-
}): Promise<void>;
|
|
71
|
-
private pollCompile;
|
|
72
|
-
private runClient;
|
|
73
|
-
stop(): void;
|
|
74
|
-
}
|
|
75
|
-
//# sourceMappingURL=live-coding-controller.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"live-coding-controller.d.ts","sourceRoot":"","sources":["../../src/live-coding/live-coding-controller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EACL,gBAAgB,EAChB,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EAC1B,MAAM,yCAAyC,CAAC;AAEjD,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEnD,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EACD,MAAM,GACN,WAAW,GACX,WAAW,GACX,gBAAgB,GAChB,UAAU,GACV,SAAS,GACT,OAAO,CAAC;IACZ,MAAM,EAAE,gBAAgB,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,sEAAsE;IACtE,KAAK,CAAC,EAAE;QACN,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,gBAAgB,EAAE,MAAM,CAAC;QACzB,kBAAkB,EAAE,MAAM,CAAC;QAC3B,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;KAC3B,CAAC;CACH;AAED,MAAM,WAAW,2BAA2B;IAC1C,aAAa,EAAE,IAAI,CACjB,gBAAgB,EAChB,QAAQ,GAAG,YAAY,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,eAAe,CACnF,CAAC;IACF,YAAY,CAAC,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC;IAChD,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,oBAAoB,CAAC;IAC3B,6DAA6D;IAC7D,SAAS,EAAE,MAAM,GAAG,GAAG,CAAC;IACxB,sFAAsF;IACtF,UAAU,EAAE,uBAAuB,CAAC,YAAY,CAAC,CAAC;IAClD,cAAc,CAAC,EAAE,uBAAuB,CAAC,gBAAgB,CAAC,CAAC;IAC3D,kFAAkF;IAClF,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC9C,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,uBAAuB,KAAK,gBAAgB,CAAC;CACxE;AAED;;;;;;GAMG;AACH,qBAAa,oBAAoB;IAInB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAHpC,OAAO,CAAC,MAAM,CAAiC;IAC/C,OAAO,CAAC,MAAM,CAAyD;gBAE1C,OAAO,EAAE,2BAA2B;IAEjE,SAAS,IAAI,gBAAgB;IAI7B,OAAO,CAAC,GAAG;IAKX,OAAO,CAAC,KAAK;IAMb,oDAAoD;IAC9C,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAgBnC;;;;;OAKG;IACG,MAAM,CAAC,KAAK,EAAE;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,gBAAgB,CAAC;QACzB,eAAe,EAAE,MAAM,CAAC;QACxB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,OAAO,CAAC;KACjB,GAAG,OAAO,CAAC,IAAI,CAAC;YA6CH,WAAW;YAoBX,SAAS;IA4BvB,IAAI,IAAI,IAAI;CAKb"}
|