@crowdedkingdoms/crowdyjs 8.17.0 → 8.19.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 +7 -0
- package/dist/domains/marketplace.d.ts +7 -1
- package/dist/domains/marketplace.d.ts.map +1 -1
- package/dist/domains/marketplace.js +10 -1
- package/dist/domains/playerCompute.d.ts +7 -1
- package/dist/domains/playerCompute.d.ts.map +1 -1
- package/dist/domains/playerCompute.js +10 -1
- package/dist/generated/graphql.d.ts +117 -16
- package/dist/generated/graphql.d.ts.map +1 -1
- package/dist/generated/graphql.js +10 -8
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/kit/npcs.d.ts.map +1 -1
- package/dist/kit/social.d.ts.map +1 -1
- package/dist/live-coding/ide.d.ts +16 -0
- package/dist/live-coding/ide.d.ts.map +1 -0
- package/dist/live-coding/ide.js +399 -0
- package/dist/live-coding/live-coding-controller.d.ts +2 -0
- package/dist/live-coding/live-coding-controller.d.ts.map +1 -1
- package/dist/live-coding/live-coding-controller.js +1 -0
- package/dist/player-runtime/glue-runtime.d.ts +92 -0
- package/dist/player-runtime/glue-runtime.d.ts.map +1 -0
- package/dist/player-runtime/glue-runtime.js +222 -0
- package/dist/player-runtime/glue-sab.d.ts +55 -0
- package/dist/player-runtime/glue-sab.d.ts.map +1 -0
- package/dist/player-runtime/glue-sab.js +79 -0
- package/dist/player-runtime/player-code-broker.d.ts +16 -0
- package/dist/player-runtime/player-code-broker.d.ts.map +1 -1
- package/dist/player-runtime/player-code-broker.js +38 -3
- package/dist/player-runtime/player-glue-worker.d.ts +26 -54
- package/dist/player-runtime/player-glue-worker.d.ts.map +1 -1
- package/dist/player-runtime/player-glue-worker.js +130 -111
- package/package.json +10 -3
|
@@ -1,127 +1,146 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
2
|
+
* Browser Web Worker entry for browser-target player WASM (player compute
|
|
3
|
+
* P3/P5). This is the ONLY platform code that shares an execution context
|
|
4
|
+
* with an untrusted player module. It is intentionally thin: the auditable
|
|
5
|
+
* runtime + ABI marshalling live in [glue-runtime.ts] and the synchronous
|
|
6
|
+
* host-call transport in [glue-sab.ts]; this file only wires them to the
|
|
7
|
+
* worker message loop.
|
|
7
8
|
*
|
|
8
9
|
* - it instantiates the gas-injected player artifact with an import table
|
|
9
|
-
* that exposes ONLY
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* Host calls are synchronous from the guest's perspective. In a worker that
|
|
19
|
-
* is realized with a SharedArrayBuffer control block plus Atomics.wait: the
|
|
20
|
-
* guest's import stub writes the request, wakes the page, and blocks until
|
|
21
|
-
* the broker writes the reply. The message/really-shared plumbing lives in
|
|
22
|
-
* buildImportObject / the init handler below; the pure, testable pieces
|
|
23
|
-
* (budget parsing, host-fn table) are exported.
|
|
10
|
+
* that exposes ONLY `ck.*` + inert wasi stubs (nothing else importable),
|
|
11
|
+
* - it never has the DOM, `window`, auth tokens, `fetch`, or third-party
|
|
12
|
+
* `importScripts`,
|
|
13
|
+
* - `ck.host_call` blocks the worker on a SharedArrayBuffer while the
|
|
14
|
+
* page-side broker services the (async) server-authorized call and writes
|
|
15
|
+
* the reply back, so the guest sees a synchronous gateway,
|
|
16
|
+
* - it enforces a per-dispatch wall-clock watchdog and reports traps to the
|
|
17
|
+
* broker, which owns the local circuit breaker.
|
|
24
18
|
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
19
|
+
* Re-exports the pure helpers + the runtime so tests and bundlers can use
|
|
20
|
+
* them without touching worker globals.
|
|
27
21
|
*/
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
'container_get',
|
|
32
|
-
'containers_list',
|
|
33
|
-
'container_delete',
|
|
34
|
-
'property_set',
|
|
35
|
-
'model_invoke',
|
|
36
|
-
'user_state_get',
|
|
37
|
-
'user_state_set',
|
|
38
|
-
'grid_state_get',
|
|
39
|
-
'grid_state_set',
|
|
40
|
-
'chunk_get',
|
|
41
|
-
'voxels_list',
|
|
42
|
-
'actors_list',
|
|
43
|
-
'actors_list_radius',
|
|
44
|
-
'voxel_set',
|
|
45
|
-
'emit_spatial',
|
|
46
|
-
'hud_set',
|
|
47
|
-
'overlay_draw',
|
|
48
|
-
'grid_permission_check',
|
|
49
|
-
];
|
|
50
|
-
/** Parse the fuel budget the broker forwards; undefined/invalid => unbounded (server still meters). */
|
|
51
|
-
export function parseFuelBudget(raw) {
|
|
52
|
-
if (raw == null)
|
|
53
|
-
return null;
|
|
54
|
-
try {
|
|
55
|
-
const v = BigInt(raw);
|
|
56
|
-
return v > 0n ? v : null;
|
|
57
|
-
}
|
|
58
|
-
catch {
|
|
59
|
-
return null;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
22
|
+
import { GlueRuntime, GLUE_HOST_FUNCTIONS, parseFuelBudget, runWithWatchdog, } from './glue-runtime.js';
|
|
23
|
+
import { createGlueSab, armGlueRequest, waitAndReadGlueReply, } from './glue-sab.js';
|
|
24
|
+
export { GlueRuntime, GLUE_HOST_FUNCTIONS, parseFuelBudget, runWithWatchdog, };
|
|
62
25
|
/**
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
* cap already bounds, belt-and-suspenders). Pure and unit-testable.
|
|
26
|
+
* Wire the glue runtime to a worker-like message port. Exported (not just
|
|
27
|
+
* run at import) so the Node integration test can drive the identical wiring
|
|
28
|
+
* over a `worker_threads` port.
|
|
67
29
|
*/
|
|
68
|
-
export
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
30
|
+
export function startGlueWorker(port) {
|
|
31
|
+
let runtime = null;
|
|
32
|
+
let sab = null;
|
|
33
|
+
let hostCallId = 0;
|
|
34
|
+
let watchdogMs = 250;
|
|
35
|
+
let ticking = false;
|
|
36
|
+
const post = (message) => port.postMessage(message);
|
|
37
|
+
// Synchronous gateway: post the request (so the page can see it), then
|
|
38
|
+
// block on the SAB until the broker writes the reply.
|
|
39
|
+
const hostCallSync = (reqBytes) => {
|
|
40
|
+
if (!sab)
|
|
41
|
+
throw new Error('host-call transport not initialized');
|
|
42
|
+
let parsed;
|
|
43
|
+
try {
|
|
44
|
+
parsed = JSON.parse(new TextDecoder().decode(reqBytes));
|
|
77
45
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
46
|
+
catch {
|
|
47
|
+
throw new Error('host_call request was not valid JSON');
|
|
48
|
+
}
|
|
49
|
+
const id = ++hostCallId;
|
|
50
|
+
armGlueRequest(sab);
|
|
51
|
+
post({
|
|
52
|
+
type: 'hostcall',
|
|
53
|
+
id,
|
|
54
|
+
fn: parsed.fn,
|
|
55
|
+
args: parsed.args ?? {},
|
|
56
|
+
reply: sab.sab,
|
|
57
|
+
});
|
|
58
|
+
return waitAndReadGlueReply(sab);
|
|
59
|
+
};
|
|
60
|
+
const onInit = async (init) => {
|
|
61
|
+
watchdogMs = init.watchdogMs ?? 250;
|
|
62
|
+
void parseFuelBudget(init.fuelPerDispatch);
|
|
63
|
+
sab = createGlueSab();
|
|
64
|
+
runtime = new GlueRuntime({
|
|
65
|
+
hostCallSync,
|
|
66
|
+
onLog: (level, message) => post({ type: 'log', level, message }),
|
|
67
|
+
});
|
|
68
|
+
try {
|
|
69
|
+
await runtime.instantiate(init.artifact);
|
|
70
|
+
const initResult = await runWithWatchdog(() => runtime.init(), watchdogMs);
|
|
71
|
+
report(initResult);
|
|
72
|
+
if ((init.tickIntervalMs ?? 0) > 0)
|
|
73
|
+
startTicking(init.tickIntervalMs);
|
|
74
|
+
post({ type: 'ready' });
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
post({ type: 'trap', reason: 'trap', detail: err.message });
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
const report = (result) => {
|
|
81
|
+
if (result.ok)
|
|
82
|
+
post({ type: 'dispatch-ok' });
|
|
83
|
+
else
|
|
84
|
+
post({ type: 'trap', reason: result.reason, detail: result.detail });
|
|
85
|
+
};
|
|
86
|
+
const startTicking = (intervalMs) => {
|
|
87
|
+
if (ticking)
|
|
88
|
+
return;
|
|
89
|
+
ticking = true;
|
|
90
|
+
let last = Date.now();
|
|
91
|
+
const loop = () => {
|
|
92
|
+
if (!ticking || !runtime)
|
|
93
|
+
return;
|
|
94
|
+
const nowT = Date.now();
|
|
95
|
+
const dt = nowT - last;
|
|
96
|
+
last = nowT;
|
|
97
|
+
void runWithWatchdog(() => runtime.tick(dt), watchdogMs).then(report);
|
|
98
|
+
setTimeout(loop, intervalMs);
|
|
105
99
|
};
|
|
100
|
+
setTimeout(loop, intervalMs);
|
|
101
|
+
};
|
|
102
|
+
const handle = (data) => {
|
|
103
|
+
if (!data || typeof data !== 'object')
|
|
104
|
+
return;
|
|
105
|
+
const msg = data;
|
|
106
|
+
if (msg.type === 'init')
|
|
107
|
+
void onInit(msg);
|
|
108
|
+
else if (msg.type === 'tick' && runtime) {
|
|
109
|
+
void runWithWatchdog(() => runtime.tick(typeof msg.dtMs === 'number' ? msg.dtMs : 0), watchdogMs).then(report);
|
|
110
|
+
}
|
|
111
|
+
else if (msg.type === 'invoke' && runtime) {
|
|
112
|
+
const payload = msg.payload instanceof Uint8Array ? msg.payload : new Uint8Array(0);
|
|
113
|
+
try {
|
|
114
|
+
const out = runtime.invoke(payload);
|
|
115
|
+
post({ type: 'invoke-result', id: msg.id, ok: true, payload: out });
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
post({
|
|
119
|
+
type: 'invoke-result',
|
|
120
|
+
id: msg.id,
|
|
121
|
+
ok: false,
|
|
122
|
+
error: err.message,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
else if (msg.type === 'stop') {
|
|
127
|
+
ticking = false;
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
if (port.addEventListener) {
|
|
131
|
+
port.addEventListener('message', (e) => handle(e.data));
|
|
132
|
+
}
|
|
133
|
+
else if (port.on) {
|
|
134
|
+
port.on('message', (d) => handle(d));
|
|
106
135
|
}
|
|
107
|
-
return { ck };
|
|
108
136
|
}
|
|
137
|
+
// Auto-start when loaded as a real browser Web Worker (has addEventListener,
|
|
138
|
+
// no window). Guarded so importing for the pure helpers never touches globals.
|
|
109
139
|
if (typeof self !== 'undefined' &&
|
|
110
140
|
typeof self.addEventListener === 'function' &&
|
|
111
141
|
typeof self.window === 'undefined') {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
return;
|
|
116
|
-
if (data.type === 'init') {
|
|
117
|
-
const init = data;
|
|
118
|
-
// The synchronous host-call bridge (SharedArrayBuffer + Atomics) is set
|
|
119
|
-
// up here from init.fuelPerDispatch/watchdogMs; instantiation uses
|
|
120
|
-
// buildImportObject so the guest sees only ck.* host functions.
|
|
121
|
-
void parseFuelBudget(init.fuelPerDispatch);
|
|
122
|
-
void (init.watchdogMs ?? 250);
|
|
123
|
-
self.postMessage?.({ type: 'ready' });
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
142
|
+
startGlueWorker({
|
|
143
|
+
addEventListener: self.addEventListener.bind(self),
|
|
144
|
+
postMessage: (m) => self.postMessage?.(m),
|
|
126
145
|
});
|
|
127
146
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crowdedkingdoms/crowdyjs",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.19.0",
|
|
4
4
|
"description": "Client SDK for Crowded Kingdoms GraphQL API with UDP proxy support",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -70,11 +70,18 @@
|
|
|
70
70
|
"@graphql-tools/merge": "^9.1.10",
|
|
71
71
|
"@types/node": "^22.10.7",
|
|
72
72
|
"typescript": "^5.7.3",
|
|
73
|
-
"ws": "^8.
|
|
73
|
+
"ws": "^8.21.1"
|
|
74
74
|
},
|
|
75
75
|
"dependencies": {
|
|
76
|
+
"@codingame/monaco-vscode-editor-api": "25.1.2",
|
|
76
77
|
"@graphql-typed-document-node/core": "^3.2.0",
|
|
78
|
+
"dompurify": "3.4.12",
|
|
77
79
|
"graphql": "^16.13.2",
|
|
78
|
-
"graphql-ws": "^6.0.8"
|
|
80
|
+
"graphql-ws": "^6.0.8",
|
|
81
|
+
"monaco-languageclient": "10.7.0",
|
|
82
|
+
"vscode-ws-jsonrpc": "3.5.0"
|
|
83
|
+
},
|
|
84
|
+
"overrides": {
|
|
85
|
+
"dompurify": "$dompurify"
|
|
79
86
|
}
|
|
80
87
|
}
|