@dreamboard-games/sdk 0.4.0-alpha.0 → 0.4.0-alpha.2
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 +8 -1
- package/REFERENCE.md +1849 -379
- package/dist/{ResourceCounter-BTXklCEZ.d.ts → ResourceCounter-BuiNstXs.d.ts} +5 -1
- package/dist/{ThemeProvider-DvMl17Ny.d.ts → ThemeProvider-B1sIoBlX.d.ts} +1 -1
- package/dist/attributes-DbvyMbXw.d.ts +68 -0
- package/dist/authoring/index.d.ts +66 -0
- package/dist/authoring/index.js +560 -0
- package/dist/authoring/index.js.map +1 -0
- package/dist/browser-interaction.d.ts +246 -44
- package/dist/browser-interaction.js +14 -1
- package/dist/{chunk-Q5O7GPVY.js → chunk-45FI6XII.js} +630 -375
- package/dist/chunk-45FI6XII.js.map +1 -0
- package/dist/{chunk-4G7552LO.js → chunk-6JQFGSLD.js} +216 -47
- package/dist/chunk-6JQFGSLD.js.map +1 -0
- package/dist/{chunk-NBAEEHAU.js → chunk-CP35NPPY.js} +5926 -5266
- package/dist/chunk-CP35NPPY.js.map +1 -0
- package/dist/{chunk-2LDZ5C3T.js → chunk-FWVV2X74.js} +2 -2
- package/dist/{chunk-MNKDSGIA.js → chunk-HWJS3VOJ.js} +6 -2
- package/dist/chunk-HWJS3VOJ.js.map +1 -0
- package/dist/chunk-K5ZRJTZZ.js +328 -0
- package/dist/chunk-K5ZRJTZZ.js.map +1 -0
- package/dist/{chunk-U5KBV2BA.js → chunk-N6ZDIMRB.js} +444 -223
- package/dist/chunk-N6ZDIMRB.js.map +1 -0
- package/dist/chunk-O6M6PN4E.js +1225 -0
- package/dist/chunk-O6M6PN4E.js.map +1 -0
- package/dist/chunk-PF7L4BMG.js +117 -0
- package/dist/chunk-PF7L4BMG.js.map +1 -0
- package/dist/{chunk-P7F4L2FF.js → chunk-WOWFONLZ.js} +609 -1287
- package/dist/chunk-WOWFONLZ.js.map +1 -0
- package/dist/{chunk-QLG6VEMW.js → chunk-WUIVY2KE.js} +318 -21
- package/dist/chunk-WUIVY2KE.js.map +1 -0
- package/dist/chunk-ZAS2SENW.js +12 -0
- package/dist/chunk-ZAS2SENW.js.map +1 -0
- package/dist/codegen.d.ts +11 -1
- package/dist/codegen.js +1 -1
- package/dist/{components-DaIqi9QM.d.ts → components-BbWPnZCF.d.ts} +37 -70
- package/dist/{hex-board-view-UCUjMALd.d.ts → hex-board-view-Kz9Q_zsv.d.ts} +1 -1
- package/dist/index.js +2 -1
- package/dist/package-set.d.ts +2 -2
- package/dist/package-set.js +2 -1
- package/dist/player-state-Cqpyeql0.d.ts +371 -0
- package/dist/protocol-BP193lva.d.ts +267 -0
- package/dist/reducer/advanced.d.ts +2 -2
- package/dist/reducer/advanced.js +1 -1
- package/dist/reducer-contract.js +1 -1
- package/dist/reducer.d.ts +7 -7
- package/dist/reducer.js +190 -183
- package/dist/reducer.js.map +1 -1
- package/dist/runtime/primitives.d.ts +10 -9
- package/dist/runtime/primitives.js +9 -6
- package/dist/runtime/runtime-api.d.ts +2 -2
- package/dist/runtime/workspace-contract.d.ts +28 -76
- package/dist/runtime/workspace-contract.js +7 -5
- package/dist/runtime-api-BJharVaj.d.ts +198 -0
- package/dist/runtime-api-C6aWo9c0.d.ts +95 -0
- package/dist/runtime-json-CQ9QbLZ5.d.ts +5 -0
- package/dist/runtime.d.ts +80 -11
- package/dist/runtime.js +89 -445
- package/dist/runtime.js.map +1 -1
- package/dist/testing.d.ts +643 -22
- package/dist/testing.js +1371 -76
- package/dist/testing.js.map +1 -1
- package/dist/types-CYeN0wLK.d.ts +29 -0
- package/dist/{attributes-BeRyboMS.d.ts → types-DJj5MJkl.d.ts} +32 -55
- package/dist/types.d.ts +14 -7
- package/dist/ui/components.d.ts +4 -5
- package/dist/ui/components.js +19 -1
- package/dist/ui/player-state.d.ts +2 -365
- package/dist/ui/plugin-styles.css +1 -1
- package/dist/{ui-contract-BUC6iS3s.d.ts → ui-contract-CY7cxsCC.d.ts} +17 -26
- package/dist/ui.d.ts +8 -13
- package/dist/ui.js +20 -2
- package/dist/{views-B0hlW6IT.d.ts → views-fn2RuXOx.d.ts} +59 -44
- package/package.json +28 -4
- package/dist/chunk-4G7552LO.js.map +0 -1
- package/dist/chunk-MNKDSGIA.js.map +0 -1
- package/dist/chunk-NBAEEHAU.js.map +0 -1
- package/dist/chunk-P7F4L2FF.js.map +0 -1
- package/dist/chunk-Q5O7GPVY.js.map +0 -1
- package/dist/chunk-QLG6VEMW.js.map +0 -1
- package/dist/chunk-U5KBV2BA.js.map +0 -1
- package/dist/hex-color-MhOyuY-o.d.ts +0 -8
- package/dist/runtime-api-BXd70c2e.d.ts +0 -490
- /package/dist/{chunk-2LDZ5C3T.js.map → chunk-FWVV2X74.js.map} +0 -0
package/dist/runtime.js
CHANGED
|
@@ -1,490 +1,140 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createWorkspaceUIContract
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
RuntimeProvider,
|
|
7
|
-
RuntimeSemanticProjectionMarker,
|
|
8
|
-
usePluginSession
|
|
9
|
-
} from "./chunk-P7F4L2FF.js";
|
|
10
|
-
import "./chunk-2LDZ5C3T.js";
|
|
3
|
+
} from "./chunk-6JQFGSLD.js";
|
|
4
|
+
import "./chunk-WOWFONLZ.js";
|
|
5
|
+
import "./chunk-FWVV2X74.js";
|
|
11
6
|
import "./chunk-T3ZKNUZ7.js";
|
|
12
7
|
import {
|
|
13
8
|
GameSkeleton
|
|
14
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-45FI6XII.js";
|
|
15
10
|
import "./chunk-VDXOF4FW.js";
|
|
16
|
-
import
|
|
11
|
+
import {
|
|
12
|
+
PluginRuntimeBoundary,
|
|
13
|
+
createPluginRuntimeClient
|
|
14
|
+
} from "./chunk-K5ZRJTZZ.js";
|
|
15
|
+
import {
|
|
16
|
+
DREAMBOARD_PLUGIN_PROTOCOL,
|
|
17
|
+
DREAMBOARD_PLUGIN_PROTOCOL_VERSION,
|
|
18
|
+
HostToPluginEnvelopeSchema
|
|
19
|
+
} from "./chunk-O6M6PN4E.js";
|
|
20
|
+
import "./chunk-WUIVY2KE.js";
|
|
21
|
+
import "./chunk-PF7L4BMG.js";
|
|
17
22
|
import "./chunk-PZ5AY32C.js";
|
|
18
23
|
|
|
19
24
|
// src/runtime/hooks/usePluginRuntime.ts
|
|
20
25
|
import { useState, useEffect, useRef } from "react";
|
|
21
26
|
|
|
22
|
-
// src/runtime/
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
});
|
|
34
|
-
var StateSyncMessageSchema = z.object({
|
|
35
|
-
type: z.literal("state-sync"),
|
|
36
|
-
syncId: z.number(),
|
|
37
|
-
state: z.custom((data) => {
|
|
38
|
-
return typeof data === "object" && data !== null && "session" in data && "notifications" in data;
|
|
39
|
-
})
|
|
40
|
-
});
|
|
41
|
-
var ValidateInteractionResultMessageSchema = z.object({
|
|
42
|
-
type: z.literal("validate-interaction-result"),
|
|
43
|
-
messageId: z.string(),
|
|
44
|
-
result: z.object({
|
|
45
|
-
valid: z.boolean(),
|
|
46
|
-
errorCode: z.string().nullable().optional(),
|
|
47
|
-
message: z.string().nullable().optional()
|
|
48
|
-
})
|
|
49
|
-
});
|
|
50
|
-
var SubmitResultMessageSchema = z.object({
|
|
51
|
-
type: z.literal("submit-result"),
|
|
52
|
-
messageId: z.string(),
|
|
53
|
-
accepted: z.boolean(),
|
|
54
|
-
errorCode: z.string().nullable().optional(),
|
|
55
|
-
message: z.string().nullable().optional()
|
|
56
|
-
});
|
|
57
|
-
var MainToPluginMessageSchema = z.discriminatedUnion("type", [
|
|
58
|
-
InitMessageSchema,
|
|
59
|
-
PingMessageSchema,
|
|
60
|
-
StateSyncMessageSchema,
|
|
61
|
-
ValidateInteractionResultMessageSchema,
|
|
62
|
-
SubmitResultMessageSchema
|
|
63
|
-
]);
|
|
64
|
-
var mintClientActionId = () => {
|
|
65
|
-
const cryptoLike = globalThis.crypto;
|
|
66
|
-
if (cryptoLike?.randomUUID) {
|
|
67
|
-
try {
|
|
68
|
-
return cryptoLike.randomUUID();
|
|
69
|
-
} catch {
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
const rand = Math.random().toString(16).slice(2);
|
|
73
|
-
return `cid-${Date.now().toString(16)}-${rand}`;
|
|
74
|
-
};
|
|
75
|
-
var PLUGIN_RUNTIME_SINGLETON_KEY = "__dreamboardPluginRuntimeApi";
|
|
76
|
-
function createPluginRuntimeAPI(options = {}) {
|
|
77
|
-
const existingRuntime = globalThis[PLUGIN_RUNTIME_SINGLETON_KEY];
|
|
78
|
-
if (existingRuntime) {
|
|
79
|
-
existingRuntime.setDiagnosticHandler?.(options.onDiagnostic);
|
|
80
|
-
return existingRuntime;
|
|
81
|
-
}
|
|
82
|
-
let onDiagnostic = options.onDiagnostic;
|
|
83
|
-
const emitDiagnostic = (event) => {
|
|
84
|
-
if (onDiagnostic) {
|
|
85
|
-
try {
|
|
86
|
-
onDiagnostic(event);
|
|
87
|
-
return;
|
|
88
|
-
} catch {
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
switch (event.type) {
|
|
92
|
-
case "runtimeLog": {
|
|
93
|
-
const args = [event.message, ...event.details ?? []];
|
|
94
|
-
if (event.level === "warn") {
|
|
95
|
-
console.warn(...args);
|
|
96
|
-
} else if (event.level === "error") {
|
|
97
|
-
console.error(...args);
|
|
98
|
-
} else {
|
|
99
|
-
console.log(...args);
|
|
100
|
-
}
|
|
101
|
-
break;
|
|
102
|
-
}
|
|
103
|
-
case "internalError":
|
|
104
|
-
console.error(
|
|
105
|
-
`[Plugin RuntimeAPI] ${event.code}:`,
|
|
106
|
-
event.message,
|
|
107
|
-
event.stack ?? ""
|
|
108
|
-
);
|
|
109
|
-
break;
|
|
110
|
-
default: {
|
|
111
|
-
const _exhaustive = event;
|
|
112
|
-
return _exhaustive;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
};
|
|
116
|
-
let currentStateSnapshot = null;
|
|
117
|
-
const stateListeners = /* @__PURE__ */ new Set();
|
|
118
|
-
const sessionState = {
|
|
119
|
-
status: "loading",
|
|
120
|
-
sessionId: null,
|
|
121
|
-
controllablePlayerIds: [],
|
|
122
|
-
controllingPlayerId: null,
|
|
123
|
-
userId: null
|
|
124
|
-
};
|
|
125
|
-
const sessionStateListeners = /* @__PURE__ */ new Set();
|
|
126
|
-
const pendingValidations = /* @__PURE__ */ new Map();
|
|
127
|
-
let validationIdCounter = 0;
|
|
128
|
-
const pendingSubmissions = /* @__PURE__ */ new Map();
|
|
129
|
-
let submitIdCounter = 0;
|
|
130
|
-
const notifySessionStateChange = () => {
|
|
131
|
-
sessionStateListeners.forEach((listener) => {
|
|
132
|
-
try {
|
|
133
|
-
listener({ ...sessionState });
|
|
134
|
-
} catch {
|
|
135
|
-
}
|
|
136
|
-
});
|
|
137
|
-
};
|
|
138
|
-
const notifyStateListeners = () => {
|
|
139
|
-
if (!currentStateSnapshot) return;
|
|
140
|
-
const snapshot = currentStateSnapshot;
|
|
141
|
-
stateListeners.forEach((listener) => {
|
|
142
|
-
try {
|
|
143
|
-
listener(snapshot);
|
|
144
|
-
} catch {
|
|
145
|
-
}
|
|
146
|
-
});
|
|
147
|
-
};
|
|
148
|
-
const createSubmissionError = (errorCode, message) => {
|
|
149
|
-
const error = new Error(message ?? "Submission failed");
|
|
150
|
-
error.name = "SubmissionError";
|
|
151
|
-
error.errorCode = errorCode;
|
|
152
|
-
return error;
|
|
153
|
-
};
|
|
154
|
-
const submitViaParent = (payload) => new Promise((resolve, reject) => {
|
|
155
|
-
const messageId = `submit-${++submitIdCounter}`;
|
|
156
|
-
pendingSubmissions.set(messageId, { resolve, reject });
|
|
157
|
-
const clientSubmittedAtMs = Date.now();
|
|
158
|
-
if (payload.clientActionId && typeof performance !== "undefined") {
|
|
159
|
-
try {
|
|
160
|
-
performance.mark(`dreamboard.t0_click.${payload.clientActionId}`, {
|
|
161
|
-
detail: { clientActionId: payload.clientActionId }
|
|
162
|
-
});
|
|
163
|
-
} catch {
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
window.parent.postMessage(
|
|
167
|
-
{ ...payload, messageId, clientSubmittedAtMs },
|
|
168
|
-
"*"
|
|
169
|
-
);
|
|
170
|
-
setTimeout(() => {
|
|
171
|
-
const pending = pendingSubmissions.get(messageId);
|
|
172
|
-
if (!pending) {
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
pendingSubmissions.delete(messageId);
|
|
176
|
-
pending.reject(
|
|
177
|
-
createSubmissionError(
|
|
178
|
-
"submission-timeout",
|
|
179
|
-
"Submission request timed out"
|
|
180
|
-
)
|
|
181
|
-
);
|
|
182
|
-
}, 1e4);
|
|
183
|
-
});
|
|
184
|
-
const handleMessage = (event) => {
|
|
185
|
-
const rawMessage = event.data;
|
|
186
|
-
const parseResult = MainToPluginMessageSchema.safeParse(rawMessage);
|
|
187
|
-
if (!parseResult.success) {
|
|
188
|
-
if (rawMessage?.type && typeof rawMessage.type === "string") {
|
|
189
|
-
emitDiagnostic({
|
|
190
|
-
type: "runtimeLog",
|
|
191
|
-
level: "warn",
|
|
192
|
-
message: "[Plugin RuntimeAPI] Invalid message received:",
|
|
193
|
-
details: [rawMessage.type]
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
return;
|
|
197
|
-
}
|
|
198
|
-
const message = parseResult.data;
|
|
199
|
-
switch (message.type) {
|
|
200
|
-
case "init": {
|
|
201
|
-
emitDiagnostic({
|
|
202
|
-
type: "runtimeLog",
|
|
203
|
-
level: "log",
|
|
204
|
-
message: "[Plugin RuntimeAPI] Received init message"
|
|
205
|
-
});
|
|
206
|
-
sessionState.status = "ready";
|
|
207
|
-
sessionState.sessionId = message.sessionId;
|
|
208
|
-
sessionState.controllablePlayerIds = message.controllablePlayerIds;
|
|
209
|
-
sessionState.controllingPlayerId = message.controllingPlayerId;
|
|
210
|
-
sessionState.userId = message.userId;
|
|
211
|
-
notifySessionStateChange();
|
|
212
|
-
window.parent.postMessage({ type: "ready" }, "*");
|
|
213
|
-
break;
|
|
214
|
-
}
|
|
215
|
-
case "ping": {
|
|
216
|
-
window.parent.postMessage({ type: "pong" }, "*");
|
|
217
|
-
break;
|
|
218
|
-
}
|
|
219
|
-
case "state-sync": {
|
|
220
|
-
emitDiagnostic({
|
|
221
|
-
type: "runtimeLog",
|
|
222
|
-
level: "log",
|
|
223
|
-
message: "[Plugin RuntimeAPI] Received state-sync, syncId:",
|
|
224
|
-
details: [message.syncId]
|
|
225
|
-
});
|
|
226
|
-
const clientReceivedAtMs = Date.now();
|
|
227
|
-
if (typeof performance !== "undefined") {
|
|
228
|
-
try {
|
|
229
|
-
performance.mark(
|
|
230
|
-
`dreamboard.t7_state_sync_received.sync-${message.syncId}`,
|
|
231
|
-
{ detail: { syncId: message.syncId } }
|
|
232
|
-
);
|
|
233
|
-
} catch {
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
currentStateSnapshot = message.state;
|
|
237
|
-
if (message.state.session) {
|
|
238
|
-
sessionState.sessionId = message.state.session.sessionId;
|
|
239
|
-
sessionState.controllablePlayerIds = message.state.session.controllablePlayerIds;
|
|
240
|
-
sessionState.controllingPlayerId = message.state.session.controllingPlayerId;
|
|
241
|
-
sessionState.userId = message.state.session.userId;
|
|
242
|
-
sessionState.status = "ready";
|
|
243
|
-
notifySessionStateChange();
|
|
244
|
-
}
|
|
245
|
-
notifyStateListeners();
|
|
246
|
-
window.parent.postMessage(
|
|
247
|
-
{
|
|
248
|
-
type: "state-ack",
|
|
249
|
-
syncId: message.syncId,
|
|
250
|
-
clientReceivedAtMs
|
|
251
|
-
},
|
|
252
|
-
"*"
|
|
253
|
-
);
|
|
254
|
-
const schedulePostRender = () => {
|
|
255
|
-
const send = () => {
|
|
256
|
-
const clientRenderedAtMs = Date.now();
|
|
257
|
-
if (typeof performance !== "undefined") {
|
|
258
|
-
try {
|
|
259
|
-
performance.mark(
|
|
260
|
-
`dreamboard.t8_render_commit.sync-${message.syncId}`,
|
|
261
|
-
{ detail: { syncId: message.syncId } }
|
|
262
|
-
);
|
|
263
|
-
} catch {
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
window.parent.postMessage(
|
|
267
|
-
{
|
|
268
|
-
type: "state-rendered",
|
|
269
|
-
syncId: message.syncId,
|
|
270
|
-
clientReceivedAtMs,
|
|
271
|
-
clientRenderedAtMs
|
|
272
|
-
},
|
|
273
|
-
"*"
|
|
274
|
-
);
|
|
275
|
-
};
|
|
276
|
-
if (typeof requestAnimationFrame === "function") {
|
|
277
|
-
requestAnimationFrame(send);
|
|
278
|
-
} else {
|
|
279
|
-
queueMicrotask(send);
|
|
280
|
-
}
|
|
281
|
-
};
|
|
282
|
-
queueMicrotask(schedulePostRender);
|
|
283
|
-
break;
|
|
284
|
-
}
|
|
285
|
-
case "validate-interaction-result": {
|
|
286
|
-
const resolver = pendingValidations.get(message.messageId);
|
|
287
|
-
if (resolver) {
|
|
288
|
-
pendingValidations.delete(message.messageId);
|
|
289
|
-
resolver({
|
|
290
|
-
valid: message.result.valid,
|
|
291
|
-
errorCode: message.result.errorCode ?? void 0,
|
|
292
|
-
message: message.result.message ?? void 0
|
|
293
|
-
});
|
|
27
|
+
// src/runtime/browser/post-message-transport.ts
|
|
28
|
+
function createPostMessagePluginTransport(options = {}) {
|
|
29
|
+
const targetWindow = options.targetWindow ?? window;
|
|
30
|
+
const parentWindow = options.parentWindow ?? targetWindow.parent;
|
|
31
|
+
let channel = null;
|
|
32
|
+
let outboundSequence = 0;
|
|
33
|
+
return {
|
|
34
|
+
start(onMessage) {
|
|
35
|
+
const handleMessage = (event) => {
|
|
36
|
+
if (event.source !== parentWindow) {
|
|
37
|
+
return;
|
|
294
38
|
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
if (!pending) {
|
|
300
|
-
break;
|
|
39
|
+
const parseResult = HostToPluginEnvelopeSchema.safeParse(event.data);
|
|
40
|
+
if (!parseResult.success) {
|
|
41
|
+
options.onInvalidMessage?.("invalid-envelope", event.data);
|
|
42
|
+
return;
|
|
301
43
|
}
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
});
|
|
307
|
-
} catch {
|
|
44
|
+
const envelope = parseResult.data;
|
|
45
|
+
if (!channel) {
|
|
46
|
+
if (envelope.payload.type !== "runtime.init") {
|
|
47
|
+
return;
|
|
308
48
|
}
|
|
49
|
+
channel = {
|
|
50
|
+
channelId: envelope.channelId,
|
|
51
|
+
hostOrigin: event.origin,
|
|
52
|
+
hostWindow: event.source
|
|
53
|
+
};
|
|
309
54
|
}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
} else {
|
|
314
|
-
pending.reject(
|
|
315
|
-
createSubmissionError(
|
|
316
|
-
message.errorCode ?? void 0,
|
|
317
|
-
message.message ?? void 0
|
|
318
|
-
)
|
|
319
|
-
);
|
|
55
|
+
if (envelope.channelId !== channel.channelId || event.origin !== channel.hostOrigin || event.source !== channel.hostWindow) {
|
|
56
|
+
options.onInvalidMessage?.("channel-mismatch", event.data);
|
|
57
|
+
return;
|
|
320
58
|
}
|
|
321
|
-
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
};
|
|
325
|
-
window.addEventListener("message", handleMessage);
|
|
326
|
-
const sendErrorToParent = (message, code, stack) => {
|
|
327
|
-
emitDiagnostic({
|
|
328
|
-
type: "internalError",
|
|
329
|
-
code,
|
|
330
|
-
message,
|
|
331
|
-
...stack ? { stack } : {}
|
|
332
|
-
});
|
|
333
|
-
window.parent.postMessage(
|
|
334
|
-
{
|
|
335
|
-
type: "error",
|
|
336
|
-
message: stack ? `${message}
|
|
337
|
-
${stack}` : message,
|
|
338
|
-
code
|
|
339
|
-
},
|
|
340
|
-
"*"
|
|
341
|
-
);
|
|
342
|
-
};
|
|
343
|
-
window.onerror = (message, source, lineno, colno, error) => {
|
|
344
|
-
const errorMessage = typeof message === "string" ? message : error?.message || "Unknown error";
|
|
345
|
-
const location = source ? ` at ${source}:${lineno}:${colno}` : "";
|
|
346
|
-
sendErrorToParent(errorMessage + location, "UNCAUGHT_ERROR", error?.stack);
|
|
347
|
-
return false;
|
|
348
|
-
};
|
|
349
|
-
window.onunhandledrejection = (event) => {
|
|
350
|
-
const reason = event.reason;
|
|
351
|
-
const message = reason instanceof Error ? reason.message : typeof reason === "string" ? reason : JSON.stringify(reason);
|
|
352
|
-
const stack = reason instanceof Error ? reason.stack : void 0;
|
|
353
|
-
sendErrorToParent(message, "UNHANDLED_REJECTION", stack);
|
|
354
|
-
};
|
|
355
|
-
emitDiagnostic({
|
|
356
|
-
type: "runtimeLog",
|
|
357
|
-
level: "log",
|
|
358
|
-
message: "[Plugin RuntimeAPI] Initialized (state-sync architecture)"
|
|
359
|
-
});
|
|
360
|
-
const runtime = {
|
|
361
|
-
// State-sync methods
|
|
362
|
-
getSnapshot: () => currentStateSnapshot,
|
|
363
|
-
subscribeToState: (listener) => {
|
|
364
|
-
stateListeners.add(listener);
|
|
365
|
-
if (currentStateSnapshot) {
|
|
366
|
-
try {
|
|
367
|
-
listener(currentStateSnapshot);
|
|
368
|
-
} catch {
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
return () => {
|
|
372
|
-
stateListeners.delete(listener);
|
|
59
|
+
onMessage(envelope);
|
|
373
60
|
};
|
|
374
|
-
|
|
375
|
-
validateInteraction: async (playerId, interactionId, params) => {
|
|
376
|
-
return new Promise((resolve) => {
|
|
377
|
-
const messageId = `validate-${++validationIdCounter}`;
|
|
378
|
-
pendingValidations.set(messageId, resolve);
|
|
379
|
-
window.parent.postMessage(
|
|
380
|
-
{
|
|
381
|
-
type: "validate-interaction",
|
|
382
|
-
playerId,
|
|
383
|
-
interactionId,
|
|
384
|
-
params,
|
|
385
|
-
messageId
|
|
386
|
-
},
|
|
387
|
-
"*"
|
|
388
|
-
);
|
|
389
|
-
setTimeout(() => {
|
|
390
|
-
if (pendingValidations.has(messageId)) {
|
|
391
|
-
pendingValidations.delete(messageId);
|
|
392
|
-
resolve({
|
|
393
|
-
valid: false,
|
|
394
|
-
errorCode: "validation-timeout",
|
|
395
|
-
message: "Validation request timed out"
|
|
396
|
-
});
|
|
397
|
-
}
|
|
398
|
-
}, 1e4);
|
|
399
|
-
});
|
|
400
|
-
},
|
|
401
|
-
submitInteraction: async (playerId, interactionId, params) => submitViaParent({
|
|
402
|
-
type: "interaction",
|
|
403
|
-
playerId,
|
|
404
|
-
interactionId,
|
|
405
|
-
params,
|
|
406
|
-
clientActionId: mintClientActionId()
|
|
407
|
-
}),
|
|
408
|
-
getSessionState: () => ({ ...sessionState }),
|
|
409
|
-
disconnect: () => {
|
|
410
|
-
window.removeEventListener("message", handleMessage);
|
|
411
|
-
window.onerror = null;
|
|
412
|
-
window.onunhandledrejection = null;
|
|
413
|
-
sessionStateListeners.clear();
|
|
414
|
-
stateListeners.clear();
|
|
415
|
-
pendingValidations.clear();
|
|
416
|
-
pendingSubmissions.clear();
|
|
417
|
-
currentStateSnapshot = null;
|
|
418
|
-
},
|
|
419
|
-
switchPlayer: (playerId) => {
|
|
420
|
-
window.parent.postMessage({ type: "switch-player", playerId }, "*");
|
|
421
|
-
},
|
|
422
|
-
restoreHistory: (entryId) => {
|
|
423
|
-
window.parent.postMessage({ type: "restore-history", entryId }, "*");
|
|
424
|
-
},
|
|
425
|
-
setDiagnosticHandler: (handler) => {
|
|
426
|
-
onDiagnostic = handler;
|
|
427
|
-
},
|
|
428
|
-
emitDiagnostic,
|
|
429
|
-
_subscribeToSessionState: (listener) => {
|
|
430
|
-
sessionStateListeners.add(listener);
|
|
431
|
-
listener({ ...sessionState });
|
|
61
|
+
targetWindow.addEventListener("message", handleMessage);
|
|
432
62
|
return () => {
|
|
433
|
-
|
|
63
|
+
targetWindow.removeEventListener("message", handleMessage);
|
|
64
|
+
channel = null;
|
|
434
65
|
};
|
|
66
|
+
},
|
|
67
|
+
send(payload) {
|
|
68
|
+
if (!channel) {
|
|
69
|
+
throw new Error("Plugin transport is not initialized.");
|
|
70
|
+
}
|
|
71
|
+
channel.hostWindow.postMessage(
|
|
72
|
+
{
|
|
73
|
+
protocol: DREAMBOARD_PLUGIN_PROTOCOL,
|
|
74
|
+
version: DREAMBOARD_PLUGIN_PROTOCOL_VERSION,
|
|
75
|
+
channelId: channel.channelId,
|
|
76
|
+
sequence: ++outboundSequence,
|
|
77
|
+
payload
|
|
78
|
+
},
|
|
79
|
+
channel.hostOrigin
|
|
80
|
+
);
|
|
435
81
|
}
|
|
436
82
|
};
|
|
437
|
-
globalThis[PLUGIN_RUNTIME_SINGLETON_KEY] = runtime;
|
|
438
|
-
return runtime;
|
|
439
83
|
}
|
|
440
84
|
|
|
441
85
|
// src/runtime/hooks/usePluginRuntime.ts
|
|
442
|
-
function hasProjectedView(
|
|
443
|
-
|
|
86
|
+
function hasProjectedView(runtime) {
|
|
87
|
+
const frame = runtime.getFrame();
|
|
88
|
+
return frame !== null && frame.view !== null && typeof frame.view !== "undefined";
|
|
444
89
|
}
|
|
445
90
|
function usePluginRuntime(options = {}) {
|
|
446
91
|
const { timeout = 1e4, onDiagnostic } = options;
|
|
447
92
|
const [runtime] = useState(
|
|
448
|
-
() =>
|
|
93
|
+
() => createPluginRuntimeClient({
|
|
94
|
+
transport: createPostMessagePluginTransport({
|
|
95
|
+
onInvalidMessage: (reason, value) => onDiagnostic?.({
|
|
96
|
+
type: "runtimeLog",
|
|
97
|
+
level: "warn",
|
|
98
|
+
message: `[PluginRuntime] Ignored invalid host message: ${reason}`,
|
|
99
|
+
details: [value]
|
|
100
|
+
})
|
|
101
|
+
})
|
|
102
|
+
})
|
|
449
103
|
);
|
|
450
|
-
const [isReady, setIsReady] = useState(() =>
|
|
451
|
-
const snapshot = runtime.getSnapshot?.();
|
|
452
|
-
return hasProjectedView(snapshot);
|
|
453
|
-
});
|
|
104
|
+
const [isReady, setIsReady] = useState(() => hasProjectedView(runtime));
|
|
454
105
|
const [error, setError] = useState(null);
|
|
455
106
|
const hasBeenReadyRef = useRef(false);
|
|
456
107
|
if (isReady) hasBeenReadyRef.current = true;
|
|
457
108
|
useEffect(() => {
|
|
458
|
-
|
|
459
|
-
}, [
|
|
109
|
+
void onDiagnostic;
|
|
110
|
+
}, [onDiagnostic]);
|
|
460
111
|
useEffect(() => {
|
|
461
|
-
const
|
|
462
|
-
|
|
463
|
-
if (!hasProjectedView(currentSnapshot)) {
|
|
112
|
+
const markReadyFromFrame = () => {
|
|
113
|
+
if (!hasProjectedView(runtime)) {
|
|
464
114
|
return false;
|
|
465
115
|
}
|
|
466
116
|
setError(null);
|
|
467
117
|
setIsReady(true);
|
|
468
118
|
return true;
|
|
469
119
|
};
|
|
470
|
-
if (
|
|
120
|
+
if (markReadyFromFrame()) {
|
|
471
121
|
return;
|
|
472
122
|
}
|
|
473
123
|
const timeoutId = setTimeout(() => {
|
|
474
|
-
if (!
|
|
124
|
+
if (!markReadyFromFrame()) {
|
|
475
125
|
setError(
|
|
476
|
-
`Timed out waiting for the initial projected view after ${timeout}ms. Ensure the host sends a
|
|
126
|
+
`Timed out waiting for the initial projected view after ${timeout}ms. Ensure the host sends a gameplay frame with a seat view.`
|
|
477
127
|
);
|
|
478
128
|
}
|
|
479
129
|
}, timeout);
|
|
480
130
|
const pollId = setInterval(() => {
|
|
481
|
-
if (
|
|
131
|
+
if (markReadyFromFrame()) {
|
|
482
132
|
clearInterval(pollId);
|
|
483
133
|
clearTimeout(timeoutId);
|
|
484
134
|
}
|
|
485
135
|
}, 100);
|
|
486
|
-
const unsubscribe = runtime.
|
|
487
|
-
if (!hasProjectedView(
|
|
136
|
+
const unsubscribe = runtime.subscribeFrame(() => {
|
|
137
|
+
if (!hasProjectedView(runtime)) {
|
|
488
138
|
setIsReady(false);
|
|
489
139
|
return;
|
|
490
140
|
}
|
|
@@ -540,19 +190,13 @@ function PluginRuntime({
|
|
|
540
190
|
}
|
|
541
191
|
);
|
|
542
192
|
}
|
|
543
|
-
return /* @__PURE__ */ jsx(
|
|
544
|
-
}
|
|
545
|
-
function SessionScopedInteractionUiProvider({
|
|
546
|
-
children
|
|
547
|
-
}) {
|
|
548
|
-
const { controllingPlayerId } = usePluginSession();
|
|
549
|
-
return /* @__PURE__ */ jsxs(InteractionUiProvider, { children: [
|
|
550
|
-
/* @__PURE__ */ jsx(RuntimeSemanticProjectionMarker, {}),
|
|
551
|
-
children
|
|
552
|
-
] }, controllingPlayerId ?? "__no_player__");
|
|
193
|
+
return /* @__PURE__ */ jsx(PluginRuntimeBoundary, { runtime, children });
|
|
553
194
|
}
|
|
554
195
|
export {
|
|
555
196
|
PluginRuntime,
|
|
197
|
+
PluginRuntimeBoundary,
|
|
198
|
+
createPluginRuntimeClient,
|
|
199
|
+
createPostMessagePluginTransport,
|
|
556
200
|
createWorkspaceUIContract
|
|
557
201
|
};
|
|
558
202
|
//# sourceMappingURL=runtime.js.map
|