@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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
useTheme
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-45FI6XII.js";
|
|
4
4
|
|
|
5
5
|
// src/ui/helpers/track-board.ts
|
|
6
6
|
function positionForLayout(layout, index, count) {
|
|
@@ -101,4 +101,4 @@ export {
|
|
|
101
101
|
parseHexColor,
|
|
102
102
|
hexColor
|
|
103
103
|
};
|
|
104
|
-
//# sourceMappingURL=chunk-
|
|
104
|
+
//# sourceMappingURL=chunk-FWVV2X74.js.map
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
GENERATED_AUTHORING_METADATA
|
|
3
|
+
} from "./chunk-ZAS2SENW.js";
|
|
4
|
+
|
|
1
5
|
// src/package-set.ts
|
|
2
|
-
var DREAMBOARD_SDK_VERSION =
|
|
6
|
+
var DREAMBOARD_SDK_VERSION = GENERATED_AUTHORING_METADATA.sdkVersion;
|
|
3
7
|
var DREAMBOARD_SDK_PACKAGES = {
|
|
4
8
|
"@dreamboard-games/sdk": DREAMBOARD_SDK_VERSION
|
|
5
9
|
};
|
|
@@ -14,4 +18,4 @@ export {
|
|
|
14
18
|
DREAMBOARD_SDK_PACKAGES,
|
|
15
19
|
DREAMBOARD_SDK_PACKAGE_SET
|
|
16
20
|
};
|
|
17
|
-
//# sourceMappingURL=chunk-
|
|
21
|
+
//# sourceMappingURL=chunk-HWJS3VOJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/package-set.ts"],"sourcesContent":["import { GENERATED_AUTHORING_METADATA } from \"./authoring/generated-metadata.js\";\n\nexport const DREAMBOARD_SDK_VERSION = GENERATED_AUTHORING_METADATA.sdkVersion;\n\nexport const DREAMBOARD_SDK_PACKAGES = {\n \"@dreamboard-games/sdk\": DREAMBOARD_SDK_VERSION,\n} as const;\n\nexport type DreamboardSdkPackageName = keyof typeof DREAMBOARD_SDK_PACKAGES;\n\nexport type DreamboardSdkPackageSet = {\n version: 1;\n sdkVersion: string;\n packages: Record<DreamboardSdkPackageName, string>;\n};\n\nexport const DREAMBOARD_SDK_PACKAGE_SET: DreamboardSdkPackageSet = {\n version: 1,\n sdkVersion: DREAMBOARD_SDK_VERSION,\n packages: DREAMBOARD_SDK_PACKAGES,\n};\n"],"mappings":";;;;;AAEO,IAAM,yBAAyB,6BAA6B;AAE5D,IAAM,0BAA0B;AAAA,EACrC,yBAAyB;AAC3B;AAUO,IAAM,6BAAsD;AAAA,EACjE,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,UAAU;AACZ;","names":[]}
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
import {
|
|
2
|
+
HostToPluginEnvelopeSchema,
|
|
3
|
+
InteractionUiProvider,
|
|
4
|
+
PluginGameplayFrameProvider,
|
|
5
|
+
PluginSessionProvider,
|
|
6
|
+
RuntimeContext,
|
|
7
|
+
RuntimeJsonSchema,
|
|
8
|
+
usePluginSession
|
|
9
|
+
} from "./chunk-O6M6PN4E.js";
|
|
10
|
+
|
|
11
|
+
// src/runtime/core/create-plugin-runtime-client.ts
|
|
12
|
+
var defaultClock = {
|
|
13
|
+
now: () => Date.now()
|
|
14
|
+
};
|
|
15
|
+
var defaultIdFactory = {
|
|
16
|
+
nextId: (prefix) => {
|
|
17
|
+
const cryptoLike = globalThis.crypto;
|
|
18
|
+
if (cryptoLike?.randomUUID) {
|
|
19
|
+
try {
|
|
20
|
+
return `${prefix}-${cryptoLike.randomUUID()}`;
|
|
21
|
+
} catch {
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return `${prefix}-${Date.now().toString(16)}-${Math.random().toString(16).slice(2)}`;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
function createSubmissionError(result) {
|
|
28
|
+
const error = new Error(result.message ?? "Submission failed");
|
|
29
|
+
error.name = "SubmissionError";
|
|
30
|
+
error.errorCode = result.errorCode;
|
|
31
|
+
return error;
|
|
32
|
+
}
|
|
33
|
+
function disconnectedValidationResult() {
|
|
34
|
+
return {
|
|
35
|
+
valid: false,
|
|
36
|
+
errorCode: "runtime-disconnected",
|
|
37
|
+
message: "Plugin runtime disconnected"
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function createPluginRuntimeClient(options) {
|
|
41
|
+
const clock = options.clock ?? defaultClock;
|
|
42
|
+
const idFactory = options.idFactory ?? defaultIdFactory;
|
|
43
|
+
const requestTimeoutMs = options.requestTimeoutMs ?? 1e4;
|
|
44
|
+
let session = null;
|
|
45
|
+
let frame = null;
|
|
46
|
+
let disconnected = false;
|
|
47
|
+
let stopTransport;
|
|
48
|
+
const sessionListeners = /* @__PURE__ */ new Set();
|
|
49
|
+
const frameListeners = /* @__PURE__ */ new Set();
|
|
50
|
+
const pendingValidations = /* @__PURE__ */ new Map();
|
|
51
|
+
const pendingSubmissions = /* @__PURE__ */ new Map();
|
|
52
|
+
const notifySession = () => {
|
|
53
|
+
for (const listener of sessionListeners) {
|
|
54
|
+
listener();
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
const notifyFrame = () => {
|
|
58
|
+
for (const listener of frameListeners) {
|
|
59
|
+
listener();
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
const currentBasis = () => {
|
|
63
|
+
if (!frame) {
|
|
64
|
+
throw new Error("Plugin runtime has not received a gameplay frame.");
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
gameVersion: frame.gameVersion,
|
|
68
|
+
actionSetVersion: frame.actionSetVersion,
|
|
69
|
+
perspectivePlayerId: frame.perspectivePlayerId
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
const sendRuntimeError = (message, code) => {
|
|
73
|
+
if (disconnected) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
options.transport.send({
|
|
77
|
+
type: "runtime.error",
|
|
78
|
+
message,
|
|
79
|
+
...code ? { code } : {}
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
const handleHostMessage = (rawMessage) => {
|
|
83
|
+
if (disconnected) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const parseResult = HostToPluginEnvelopeSchema.safeParse(rawMessage);
|
|
87
|
+
if (!parseResult.success) {
|
|
88
|
+
sendRuntimeError("Invalid host-to-plugin protocol envelope.", "invalid-envelope");
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const message = parseResult.data;
|
|
92
|
+
const clientReceivedAtMs = clock.now();
|
|
93
|
+
switch (message.payload.type) {
|
|
94
|
+
case "runtime.init": {
|
|
95
|
+
session = message.payload.session;
|
|
96
|
+
notifySession();
|
|
97
|
+
options.transport.send({ type: "runtime.ready" });
|
|
98
|
+
options.transport.send({
|
|
99
|
+
type: "runtime.ack",
|
|
100
|
+
sequence: message.sequence,
|
|
101
|
+
clientReceivedAtMs
|
|
102
|
+
});
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
case "gameplay.frame": {
|
|
106
|
+
frame = message.payload.frame;
|
|
107
|
+
notifyFrame();
|
|
108
|
+
const sendRenderedAck = () => {
|
|
109
|
+
if (disconnected) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
options.transport.send({
|
|
113
|
+
type: "runtime.ack",
|
|
114
|
+
sequence: message.sequence,
|
|
115
|
+
clientReceivedAtMs,
|
|
116
|
+
clientRenderedAtMs: clock.now()
|
|
117
|
+
});
|
|
118
|
+
};
|
|
119
|
+
if (typeof requestAnimationFrame === "function") {
|
|
120
|
+
requestAnimationFrame(sendRenderedAck);
|
|
121
|
+
} else {
|
|
122
|
+
queueMicrotask(sendRenderedAck);
|
|
123
|
+
}
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
case "interaction.validation-result": {
|
|
127
|
+
const resolve = pendingValidations.get(message.payload.requestId);
|
|
128
|
+
if (resolve) {
|
|
129
|
+
pendingValidations.delete(message.payload.requestId);
|
|
130
|
+
resolve(message.payload.result);
|
|
131
|
+
}
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
case "interaction.submit-result": {
|
|
135
|
+
const pending = pendingSubmissions.get(message.payload.requestId);
|
|
136
|
+
if (!pending) {
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
pendingSubmissions.delete(message.payload.requestId);
|
|
140
|
+
if (message.payload.result.accepted) {
|
|
141
|
+
pending.resolve();
|
|
142
|
+
} else {
|
|
143
|
+
pending.reject(createSubmissionError(message.payload.result));
|
|
144
|
+
}
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
default: {
|
|
148
|
+
const _exhaustive = message.payload;
|
|
149
|
+
return _exhaustive;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
stopTransport = options.transport.start(handleHostMessage);
|
|
154
|
+
const rejectPending = () => {
|
|
155
|
+
for (const resolve of pendingValidations.values()) {
|
|
156
|
+
resolve(disconnectedValidationResult());
|
|
157
|
+
}
|
|
158
|
+
pendingValidations.clear();
|
|
159
|
+
for (const pending of pendingSubmissions.values()) {
|
|
160
|
+
const error = new Error("Plugin runtime disconnected");
|
|
161
|
+
error.name = "SubmissionError";
|
|
162
|
+
error.errorCode = "runtime-disconnected";
|
|
163
|
+
pending.reject(error);
|
|
164
|
+
}
|
|
165
|
+
pendingSubmissions.clear();
|
|
166
|
+
};
|
|
167
|
+
return {
|
|
168
|
+
getSession: () => session,
|
|
169
|
+
subscribeSession: (listener) => {
|
|
170
|
+
sessionListeners.add(listener);
|
|
171
|
+
return () => {
|
|
172
|
+
sessionListeners.delete(listener);
|
|
173
|
+
};
|
|
174
|
+
},
|
|
175
|
+
getFrame: () => frame,
|
|
176
|
+
subscribeFrame: (listener) => {
|
|
177
|
+
frameListeners.add(listener);
|
|
178
|
+
return () => {
|
|
179
|
+
frameListeners.delete(listener);
|
|
180
|
+
};
|
|
181
|
+
},
|
|
182
|
+
validateInteraction: async (interactionId, params) => new Promise((resolve) => {
|
|
183
|
+
if (disconnected) {
|
|
184
|
+
resolve(disconnectedValidationResult());
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
let basis;
|
|
188
|
+
try {
|
|
189
|
+
basis = currentBasis();
|
|
190
|
+
} catch (error) {
|
|
191
|
+
resolve({
|
|
192
|
+
valid: false,
|
|
193
|
+
errorCode: "runtime-not-ready",
|
|
194
|
+
message: error instanceof Error ? error.message : "Plugin runtime is not ready."
|
|
195
|
+
});
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
const parsedParams = RuntimeJsonSchema.safeParse(params);
|
|
199
|
+
if (!parsedParams.success) {
|
|
200
|
+
resolve({
|
|
201
|
+
valid: false,
|
|
202
|
+
errorCode: "invalid-runtime-json",
|
|
203
|
+
message: "Interaction params must be runtime JSON."
|
|
204
|
+
});
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
const requestId = idFactory.nextId("validate");
|
|
208
|
+
pendingValidations.set(requestId, resolve);
|
|
209
|
+
options.transport.send({
|
|
210
|
+
type: "interaction.validate",
|
|
211
|
+
requestId,
|
|
212
|
+
basis,
|
|
213
|
+
interactionId,
|
|
214
|
+
params: parsedParams.data
|
|
215
|
+
});
|
|
216
|
+
setTimeout(() => {
|
|
217
|
+
if (!pendingValidations.delete(requestId)) {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
resolve({
|
|
221
|
+
valid: false,
|
|
222
|
+
errorCode: "validation-timeout",
|
|
223
|
+
message: "Validation request timed out"
|
|
224
|
+
});
|
|
225
|
+
}, requestTimeoutMs);
|
|
226
|
+
}),
|
|
227
|
+
submitInteraction: async (interactionId, params) => new Promise((resolve, reject) => {
|
|
228
|
+
if (disconnected) {
|
|
229
|
+
const error = new Error("Plugin runtime disconnected");
|
|
230
|
+
error.name = "SubmissionError";
|
|
231
|
+
error.errorCode = "runtime-disconnected";
|
|
232
|
+
reject(error);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
const parsedParams = RuntimeJsonSchema.safeParse(params);
|
|
236
|
+
if (!parsedParams.success) {
|
|
237
|
+
const error = new Error(
|
|
238
|
+
"Interaction params must be runtime JSON."
|
|
239
|
+
);
|
|
240
|
+
error.name = "SubmissionError";
|
|
241
|
+
error.errorCode = "invalid-runtime-json";
|
|
242
|
+
reject(error);
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
let basis;
|
|
246
|
+
try {
|
|
247
|
+
basis = currentBasis();
|
|
248
|
+
} catch (error) {
|
|
249
|
+
const submissionError = new Error(
|
|
250
|
+
error instanceof Error ? error.message : "Plugin runtime is not ready."
|
|
251
|
+
);
|
|
252
|
+
submissionError.name = "SubmissionError";
|
|
253
|
+
submissionError.errorCode = "runtime-not-ready";
|
|
254
|
+
reject(submissionError);
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
const requestId = idFactory.nextId("submit");
|
|
258
|
+
pendingSubmissions.set(requestId, { resolve, reject });
|
|
259
|
+
options.transport.send({
|
|
260
|
+
type: "interaction.submit",
|
|
261
|
+
requestId,
|
|
262
|
+
basis,
|
|
263
|
+
interactionId,
|
|
264
|
+
params: parsedParams.data
|
|
265
|
+
});
|
|
266
|
+
setTimeout(() => {
|
|
267
|
+
const pending = pendingSubmissions.get(requestId);
|
|
268
|
+
if (!pending) {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
pendingSubmissions.delete(requestId);
|
|
272
|
+
const error = new Error("Submission request timed out");
|
|
273
|
+
error.name = "SubmissionError";
|
|
274
|
+
error.errorCode = "submission-timeout";
|
|
275
|
+
pending.reject(error);
|
|
276
|
+
}, requestTimeoutMs);
|
|
277
|
+
}),
|
|
278
|
+
disconnect: () => {
|
|
279
|
+
disconnected = true;
|
|
280
|
+
stopTransport?.();
|
|
281
|
+
stopTransport = void 0;
|
|
282
|
+
sessionListeners.clear();
|
|
283
|
+
frameListeners.clear();
|
|
284
|
+
rejectPending();
|
|
285
|
+
session = null;
|
|
286
|
+
frame = null;
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// src/runtime/components/PluginRuntimeBoundary.tsx
|
|
292
|
+
import { useMemo } from "react";
|
|
293
|
+
import { jsx } from "react/jsx-runtime";
|
|
294
|
+
function runtimeApiFromClient(runtime) {
|
|
295
|
+
return {
|
|
296
|
+
validateInteraction: (interactionId, params) => runtime.validateInteraction(interactionId, params),
|
|
297
|
+
submitInteraction: (interactionId, params) => runtime.submitInteraction(interactionId, params),
|
|
298
|
+
getSessionState: () => {
|
|
299
|
+
const session = runtime.getSession();
|
|
300
|
+
const frame = runtime.getFrame();
|
|
301
|
+
return {
|
|
302
|
+
status: session ? "ready" : "loading",
|
|
303
|
+
sessionId: session?.sessionId ?? null,
|
|
304
|
+
controllingPlayerId: frame?.perspectivePlayerId ?? null
|
|
305
|
+
};
|
|
306
|
+
},
|
|
307
|
+
disconnect: () => runtime.disconnect()
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
function PluginRuntimeBoundary({
|
|
311
|
+
runtime,
|
|
312
|
+
children
|
|
313
|
+
}) {
|
|
314
|
+
const runtimeApi = useMemo(() => runtimeApiFromClient(runtime), [runtime]);
|
|
315
|
+
return /* @__PURE__ */ jsx(RuntimeContext.Provider, { value: runtimeApi, children: /* @__PURE__ */ jsx(PluginSessionProvider, { runtime, children: /* @__PURE__ */ jsx(PluginGameplayFrameProvider, { runtime, children: /* @__PURE__ */ jsx(SessionScopedInteractionUiProvider, { children }) }) }) });
|
|
316
|
+
}
|
|
317
|
+
function SessionScopedInteractionUiProvider({
|
|
318
|
+
children
|
|
319
|
+
}) {
|
|
320
|
+
const { controllingPlayerId } = usePluginSession();
|
|
321
|
+
return /* @__PURE__ */ jsx(InteractionUiProvider, { children }, controllingPlayerId ?? "__no_player__");
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
export {
|
|
325
|
+
createPluginRuntimeClient,
|
|
326
|
+
PluginRuntimeBoundary
|
|
327
|
+
};
|
|
328
|
+
//# sourceMappingURL=chunk-K5ZRJTZZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/runtime/core/create-plugin-runtime-client.ts","../src/runtime/components/PluginRuntimeBoundary.tsx"],"sourcesContent":["import {\n HostToPluginEnvelopeSchema,\n RuntimeJsonSchema,\n type HostToPluginEnvelope,\n type PluginGameplayFrame,\n type PluginInteractionBasis,\n type PluginSessionDescriptor,\n type SubmissionResult,\n type ValidationResult,\n} from \"@dreamboard-games/plugin-runtime-contract\";\nimport type {\n PluginRuntimeClient,\n PluginRuntimeClientOptions,\n RuntimeClock,\n RuntimeIdFactory,\n} from \"./types.js\";\n\nconst defaultClock: RuntimeClock = {\n now: () => Date.now(),\n};\n\nconst defaultIdFactory: RuntimeIdFactory = {\n nextId: (prefix) => {\n const cryptoLike = (\n globalThis as typeof globalThis & {\n crypto?: { randomUUID?: () => string };\n }\n ).crypto;\n if (cryptoLike?.randomUUID) {\n try {\n return `${prefix}-${cryptoLike.randomUUID()}`;\n } catch {\n // Fall through to deterministic-enough fallback for older test DOMs.\n }\n }\n return `${prefix}-${Date.now().toString(16)}-${Math.random()\n .toString(16)\n .slice(2)}`;\n },\n};\n\nfunction createSubmissionError(\n result: Extract<SubmissionResult, { accepted: false }>,\n): Error & { errorCode?: string } {\n const error = new Error(result.message ?? \"Submission failed\") as Error & {\n errorCode?: string;\n };\n error.name = \"SubmissionError\";\n error.errorCode = result.errorCode;\n return error;\n}\n\nfunction disconnectedValidationResult(): ValidationResult {\n return {\n valid: false,\n errorCode: \"runtime-disconnected\",\n message: \"Plugin runtime disconnected\",\n };\n}\n\nexport function createPluginRuntimeClient(\n options: PluginRuntimeClientOptions,\n): PluginRuntimeClient {\n const clock = options.clock ?? defaultClock;\n const idFactory = options.idFactory ?? defaultIdFactory;\n const requestTimeoutMs = options.requestTimeoutMs ?? 10_000;\n let session: PluginSessionDescriptor | null = null;\n let frame: PluginGameplayFrame | null = null;\n let disconnected = false;\n let stopTransport: (() => void) | undefined;\n const sessionListeners = new Set<() => void>();\n const frameListeners = new Set<() => void>();\n const pendingValidations = new Map<string, (result: ValidationResult) => void>();\n const pendingSubmissions = new Map<\n string,\n {\n resolve: () => void;\n reject: (error: Error & { errorCode?: string }) => void;\n }\n >();\n\n const notifySession = () => {\n for (const listener of sessionListeners) {\n listener();\n }\n };\n\n const notifyFrame = () => {\n for (const listener of frameListeners) {\n listener();\n }\n };\n\n const currentBasis = (): PluginInteractionBasis => {\n if (!frame) {\n throw new Error(\"Plugin runtime has not received a gameplay frame.\");\n }\n return {\n gameVersion: frame.gameVersion,\n actionSetVersion: frame.actionSetVersion,\n perspectivePlayerId: frame.perspectivePlayerId,\n };\n };\n\n const sendRuntimeError = (message: string, code?: string) => {\n if (disconnected) {\n return;\n }\n options.transport.send({\n type: \"runtime.error\",\n message,\n ...(code ? { code } : {}),\n });\n };\n\n const handleHostMessage = (rawMessage: HostToPluginEnvelope) => {\n if (disconnected) {\n return;\n }\n const parseResult = HostToPluginEnvelopeSchema.safeParse(rawMessage);\n if (!parseResult.success) {\n sendRuntimeError(\"Invalid host-to-plugin protocol envelope.\", \"invalid-envelope\");\n return;\n }\n const message = parseResult.data;\n const clientReceivedAtMs = clock.now();\n\n switch (message.payload.type) {\n case \"runtime.init\": {\n session = message.payload.session;\n notifySession();\n options.transport.send({ type: \"runtime.ready\" });\n options.transport.send({\n type: \"runtime.ack\",\n sequence: message.sequence,\n clientReceivedAtMs,\n });\n break;\n }\n case \"gameplay.frame\": {\n frame = message.payload.frame;\n notifyFrame();\n const sendRenderedAck = () => {\n if (disconnected) {\n return;\n }\n options.transport.send({\n type: \"runtime.ack\",\n sequence: message.sequence,\n clientReceivedAtMs,\n clientRenderedAtMs: clock.now(),\n });\n };\n if (typeof requestAnimationFrame === \"function\") {\n requestAnimationFrame(sendRenderedAck);\n } else {\n queueMicrotask(sendRenderedAck);\n }\n break;\n }\n case \"interaction.validation-result\": {\n const resolve = pendingValidations.get(message.payload.requestId);\n if (resolve) {\n pendingValidations.delete(message.payload.requestId);\n resolve(message.payload.result);\n }\n break;\n }\n case \"interaction.submit-result\": {\n const pending = pendingSubmissions.get(message.payload.requestId);\n if (!pending) {\n break;\n }\n pendingSubmissions.delete(message.payload.requestId);\n if (message.payload.result.accepted) {\n pending.resolve();\n } else {\n pending.reject(createSubmissionError(message.payload.result));\n }\n break;\n }\n default: {\n const _exhaustive: never = message.payload;\n return _exhaustive;\n }\n }\n };\n\n stopTransport = options.transport.start(handleHostMessage);\n\n const rejectPending = () => {\n for (const resolve of pendingValidations.values()) {\n resolve(disconnectedValidationResult());\n }\n pendingValidations.clear();\n for (const pending of pendingSubmissions.values()) {\n const error = new Error(\"Plugin runtime disconnected\") as Error & {\n errorCode?: string;\n };\n error.name = \"SubmissionError\";\n error.errorCode = \"runtime-disconnected\";\n pending.reject(error);\n }\n pendingSubmissions.clear();\n };\n\n return {\n getSession: () => session,\n subscribeSession: (listener) => {\n sessionListeners.add(listener);\n return () => {\n sessionListeners.delete(listener);\n };\n },\n getFrame: () => frame,\n subscribeFrame: (listener) => {\n frameListeners.add(listener);\n return () => {\n frameListeners.delete(listener);\n };\n },\n validateInteraction: async (interactionId, params) =>\n new Promise((resolve) => {\n if (disconnected) {\n resolve(disconnectedValidationResult());\n return;\n }\n let basis: PluginInteractionBasis;\n try {\n basis = currentBasis();\n } catch (error) {\n resolve({\n valid: false,\n errorCode: \"runtime-not-ready\",\n message:\n error instanceof Error\n ? error.message\n : \"Plugin runtime is not ready.\",\n });\n return;\n }\n const parsedParams = RuntimeJsonSchema.safeParse(params);\n if (!parsedParams.success) {\n resolve({\n valid: false,\n errorCode: \"invalid-runtime-json\",\n message: \"Interaction params must be runtime JSON.\",\n });\n return;\n }\n const requestId = idFactory.nextId(\"validate\");\n pendingValidations.set(requestId, resolve);\n options.transport.send({\n type: \"interaction.validate\",\n requestId,\n basis,\n interactionId,\n params: parsedParams.data,\n });\n setTimeout(() => {\n if (!pendingValidations.delete(requestId)) {\n return;\n }\n resolve({\n valid: false,\n errorCode: \"validation-timeout\",\n message: \"Validation request timed out\",\n });\n }, requestTimeoutMs);\n }),\n submitInteraction: async (interactionId, params) =>\n new Promise((resolve, reject) => {\n if (disconnected) {\n const error = new Error(\"Plugin runtime disconnected\") as Error & {\n errorCode?: string;\n };\n error.name = \"SubmissionError\";\n error.errorCode = \"runtime-disconnected\";\n reject(error);\n return;\n }\n const parsedParams = RuntimeJsonSchema.safeParse(params);\n if (!parsedParams.success) {\n const error = new Error(\n \"Interaction params must be runtime JSON.\",\n ) as Error & { errorCode?: string };\n error.name = \"SubmissionError\";\n error.errorCode = \"invalid-runtime-json\";\n reject(error);\n return;\n }\n let basis: PluginInteractionBasis;\n try {\n basis = currentBasis();\n } catch (error) {\n const submissionError = new Error(\n error instanceof Error\n ? error.message\n : \"Plugin runtime is not ready.\",\n ) as Error & { errorCode?: string };\n submissionError.name = \"SubmissionError\";\n submissionError.errorCode = \"runtime-not-ready\";\n reject(submissionError);\n return;\n }\n const requestId = idFactory.nextId(\"submit\");\n pendingSubmissions.set(requestId, { resolve, reject });\n options.transport.send({\n type: \"interaction.submit\",\n requestId,\n basis,\n interactionId,\n params: parsedParams.data,\n });\n setTimeout(() => {\n const pending = pendingSubmissions.get(requestId);\n if (!pending) {\n return;\n }\n pendingSubmissions.delete(requestId);\n const error = new Error(\"Submission request timed out\") as Error & {\n errorCode?: string;\n };\n error.name = \"SubmissionError\";\n error.errorCode = \"submission-timeout\";\n pending.reject(error);\n }, requestTimeoutMs);\n }),\n disconnect: () => {\n disconnected = true;\n stopTransport?.();\n stopTransport = undefined;\n sessionListeners.clear();\n frameListeners.clear();\n rejectPending();\n session = null;\n frame = null;\n },\n };\n}\n","import React, { useMemo } from \"react\";\nimport { InteractionUiProvider } from \"../context/InteractionDraftContext.js\";\nimport {\n PluginSessionProvider,\n usePluginSession,\n} from \"../context/PluginSessionContext.js\";\nimport { PluginGameplayFrameProvider } from \"../context/PluginGameplayFrameContext.js\";\nimport { RuntimeContext } from \"../context/RuntimeContext.js\";\nimport type { PluginRuntimeClient } from \"../core/types.js\";\nimport type { RuntimeAPI } from \"../types/runtime-api.js\";\n\nfunction runtimeApiFromClient(runtime: PluginRuntimeClient): RuntimeAPI {\n return {\n validateInteraction: (interactionId, params) =>\n runtime.validateInteraction(interactionId, params),\n submitInteraction: (interactionId, params) =>\n runtime.submitInteraction(interactionId, params),\n getSessionState: () => {\n const session = runtime.getSession();\n const frame = runtime.getFrame();\n return {\n status: session ? \"ready\" : \"loading\",\n sessionId: session?.sessionId ?? null,\n controllingPlayerId: frame?.perspectivePlayerId ?? null,\n };\n },\n disconnect: () => runtime.disconnect(),\n };\n}\n\nexport function PluginRuntimeBoundary({\n runtime,\n children,\n}: {\n runtime: PluginRuntimeClient;\n children: React.ReactNode;\n}) {\n const runtimeApi = useMemo(() => runtimeApiFromClient(runtime), [runtime]);\n\n return (\n <RuntimeContext.Provider value={runtimeApi}>\n <PluginSessionProvider runtime={runtime}>\n <PluginGameplayFrameProvider runtime={runtime}>\n <SessionScopedInteractionUiProvider>\n {children}\n </SessionScopedInteractionUiProvider>\n </PluginGameplayFrameProvider>\n </PluginSessionProvider>\n </RuntimeContext.Provider>\n );\n}\n\nfunction SessionScopedInteractionUiProvider({\n children,\n}: {\n children: React.ReactNode;\n}) {\n const { controllingPlayerId } = usePluginSession();\n return (\n <InteractionUiProvider key={controllingPlayerId ?? \"__no_player__\"}>\n {children}\n </InteractionUiProvider>\n );\n}\n"],"mappings":"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","names":[]}
|