@dreamboard-games/cli 0.1.30-alpha.1 → 0.1.30-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.
Files changed (114) hide show
  1. package/README.md +179 -22
  2. package/dist/{chunk-C6UAT6EH.js → chunk-N7XPNNUI.js} +9 -12
  3. package/dist/chunk-N7XPNNUI.js.map +1 -0
  4. package/dist/chunk-SEGVTWSK.js +44 -0
  5. package/dist/{chunk-RS7UXJZV.js → chunk-TAQKH67O.js} +21300 -35881
  6. package/dist/chunk-TAQKH67O.js.map +1 -0
  7. package/dist/{global-config-AGFBDFYD.js → global-config-S4ZIPECE.js} +3 -3
  8. package/dist/index.js +415 -37
  9. package/dist/index.js.map +1 -1
  10. package/dist/internal.js +3 -4
  11. package/dist/{agent-verifier/keychain-backend-TNOPQV3Z.mjs → keychain-backend-HDF4TZDL.js} +2 -1
  12. package/dist/{agent-verifier/prompt-3BAINGAQ.mjs → prompt-NDV3AE5L.js} +2 -1
  13. package/package.json +6 -6
  14. package/skills/dreamboard/references/building-your-first-game.md +510 -0
  15. package/skills/dreamboard/references/cli.md +104 -0
  16. package/skills/dreamboard/references/game-interface.md +548 -0
  17. package/skills/dreamboard/references/manifest-authoring.md +597 -0
  18. package/skills/dreamboard/references/quickstart.md +66 -0
  19. package/skills/dreamboard/references/reducer.md +864 -0
  20. package/skills/dreamboard/references/rule-authoring.md +147 -0
  21. package/skills/dreamboard/references/testing.md +249 -0
  22. package/skills/dreamboard/scripts/events-extract.mjs +218 -0
  23. package/dist/agent-verifier/agent-workspace-verifier.mjs +0 -227
  24. package/dist/agent-verifier/chunk-2E5P5NWG.mjs +0 -835
  25. package/dist/agent-verifier/chunk-2GBBP27W.mjs +0 -301
  26. package/dist/agent-verifier/chunk-2QMNAVV4.mjs +0 -14522
  27. package/dist/agent-verifier/chunk-2SZHMP6F.mjs +0 -264
  28. package/dist/agent-verifier/chunk-4WD3YU2E.mjs +0 -166
  29. package/dist/agent-verifier/chunk-54TAYXUD.mjs +0 -12
  30. package/dist/agent-verifier/chunk-6A5HRJMQ.mjs +0 -3174
  31. package/dist/agent-verifier/chunk-6UUJEYDV.mjs +0 -213
  32. package/dist/agent-verifier/chunk-7653FPGJ.mjs +0 -381
  33. package/dist/agent-verifier/chunk-7E65UQLY.mjs +0 -38
  34. package/dist/agent-verifier/chunk-BVVNBJM4.mjs +0 -221
  35. package/dist/agent-verifier/chunk-CEDUHGNH.mjs +0 -74
  36. package/dist/agent-verifier/chunk-CEQ2VJWN.mjs +0 -149
  37. package/dist/agent-verifier/chunk-CFU5EWIC.mjs +0 -69
  38. package/dist/agent-verifier/chunk-CJEEA6NJ.mjs +0 -730
  39. package/dist/agent-verifier/chunk-EIQWDQWJ.mjs +0 -186
  40. package/dist/agent-verifier/chunk-EOQIV6PS.mjs +0 -649
  41. package/dist/agent-verifier/chunk-HBNDKQT5.mjs +0 -8381
  42. package/dist/agent-verifier/chunk-HJFQDSTU.mjs +0 -225
  43. package/dist/agent-verifier/chunk-JH22JNYD.mjs +0 -1681
  44. package/dist/agent-verifier/chunk-LI3ZR3BI.mjs +0 -41
  45. package/dist/agent-verifier/chunk-LM3OZLZG.mjs +0 -48
  46. package/dist/agent-verifier/chunk-MINCYHXN.mjs +0 -106
  47. package/dist/agent-verifier/chunk-MRCUP5SW.mjs +0 -128
  48. package/dist/agent-verifier/chunk-RBDDIIPM.mjs +0 -19
  49. package/dist/agent-verifier/chunk-SHUMAVAP.mjs +0 -59
  50. package/dist/agent-verifier/chunk-SYPLYRGB.mjs +0 -2812
  51. package/dist/agent-verifier/chunk-U6OJN7XS.mjs +0 -8092
  52. package/dist/agent-verifier/chunk-VYJTHSYR.mjs +0 -44
  53. package/dist/agent-verifier/chunk-XYDL7GY6.mjs +0 -10
  54. package/dist/agent-verifier/compile-5QSPIOUT.mjs +0 -313
  55. package/dist/agent-verifier/global-config-WX3ZZIVU.mjs +0 -17
  56. package/dist/agent-verifier/local-files-MTPLP62S.mjs +0 -46
  57. package/dist/agent-verifier/local-typecheck-QFYYAZOK.mjs +0 -9
  58. package/dist/agent-verifier/materialize-workspace-FKALAE2T.mjs +0 -90
  59. package/dist/agent-verifier/project-state-7GR6BQTQ.mjs +0 -32
  60. package/dist/agent-verifier/reducer-bundle-preflight-C73LEXI2.mjs +0 -23
  61. package/dist/agent-verifier/reducer-contract-preflight-22X7DSZW.mjs +0 -10
  62. package/dist/agent-verifier/reducer-native-test-harness-GMWBUISX.mjs +0 -53
  63. package/dist/agent-verifier/static-scaffold-AJMZZQWS.mjs +0 -28
  64. package/dist/agent-verifier/sync-3DUQH32H.mjs +0 -594
  65. package/dist/agent-verifier/test-P4U5INTD.mjs +0 -356
  66. package/dist/agent-verifier/testing-5K2BJYF2.mjs +0 -674
  67. package/dist/agent-verifier/workspace-codegen-JDZJRSDV.mjs +0 -11
  68. package/dist/agent-verifier/workspace-dependencies-HZ6VVS4G.mjs +0 -14
  69. package/dist/chunk-2H7UOFLK.js +0 -11
  70. package/dist/chunk-7FOO4AJI.js +0 -50
  71. package/dist/chunk-7FOO4AJI.js.map +0 -1
  72. package/dist/chunk-C6UAT6EH.js.map +0 -1
  73. package/dist/chunk-RS7UXJZV.js.map +0 -1
  74. package/dist/internal.d.ts +0 -311
  75. package/dist/keychain-backend-JHTXAKWC.js +0 -135
  76. package/dist/prompt-GMZABCJC.js +0 -756
  77. package/dist/runtime-packages/ui-host-runtime/src/actor-principal.ts +0 -71
  78. package/dist/runtime-packages/ui-host-runtime/src/browser-interaction.ts +0 -139
  79. package/dist/runtime-packages/ui-host-runtime/src/components/host-controls.tsx +0 -374
  80. package/dist/runtime-packages/ui-host-runtime/src/components/host-feedback-toaster.tsx +0 -266
  81. package/dist/runtime-packages/ui-host-runtime/src/components/host-feedback.tsx +0 -212
  82. package/dist/runtime-packages/ui-host-runtime/src/components/host-primitives.tsx +0 -271
  83. package/dist/runtime-packages/ui-host-runtime/src/components/host-session-metadata.tsx +0 -135
  84. package/dist/runtime-packages/ui-host-runtime/src/components/index.ts +0 -5
  85. package/dist/runtime-packages/ui-host-runtime/src/components/perf-overlay.tsx +0 -194
  86. package/dist/runtime-packages/ui-host-runtime/src/gameplay-authority-transport.ts +0 -626
  87. package/dist/runtime-packages/ui-host-runtime/src/host-controls.tsx +0 -1
  88. package/dist/runtime-packages/ui-host-runtime/src/host-feedback.tsx +0 -1
  89. package/dist/runtime-packages/ui-host-runtime/src/host-session-transport.ts +0 -294
  90. package/dist/runtime-packages/ui-host-runtime/src/index.ts +0 -3
  91. package/dist/runtime-packages/ui-host-runtime/src/logger.ts +0 -11
  92. package/dist/runtime-packages/ui-host-runtime/src/perf.ts +0 -324
  93. package/dist/runtime-packages/ui-host-runtime/src/plugin-bridge.ts +0 -195
  94. package/dist/runtime-packages/ui-host-runtime/src/plugin-health-check.ts +0 -138
  95. package/dist/runtime-packages/ui-host-runtime/src/plugin-messages.ts +0 -159
  96. package/dist/runtime-packages/ui-host-runtime/src/plugin-session-gateway.ts +0 -551
  97. package/dist/runtime-packages/ui-host-runtime/src/runtime/index.ts +0 -13
  98. package/dist/runtime-packages/ui-host-runtime/src/screenshot/projection-to-snapshot.ts +0 -122
  99. package/dist/runtime-packages/ui-host-runtime/src/screenshot/static-store-api.ts +0 -26
  100. package/dist/runtime-packages/ui-host-runtime/src/session-ingress-controller.ts +0 -583
  101. package/dist/runtime-packages/ui-host-runtime/src/session-ingress.ts +0 -219
  102. package/dist/runtime-packages/ui-host-runtime/src/session-live-runtime.ts +0 -117
  103. package/dist/runtime-packages/ui-host-runtime/src/session-model.ts +0 -431
  104. package/dist/runtime-packages/ui-host-runtime/src/session-projection.ts +0 -211
  105. package/dist/runtime-packages/ui-host-runtime/src/session-recovery.ts +0 -80
  106. package/dist/runtime-packages/ui-host-runtime/src/session-state-reducer.ts +0 -1034
  107. package/dist/runtime-packages/ui-host-runtime/src/sse-manager.ts +0 -416
  108. package/dist/runtime-packages/ui-host-runtime/src/unified-session-store.ts +0 -184
  109. package/dist/testing-KLSV6CPJ.js +0 -674
  110. package/dist/testing-KLSV6CPJ.js.map +0 -1
  111. /package/dist/{chunk-2H7UOFLK.js.map → chunk-SEGVTWSK.js.map} +0 -0
  112. /package/dist/{global-config-AGFBDFYD.js.map → global-config-S4ZIPECE.js.map} +0 -0
  113. /package/dist/{keychain-backend-JHTXAKWC.js.map → keychain-backend-HDF4TZDL.js.map} +0 -0
  114. /package/dist/{prompt-GMZABCJC.js.map → prompt-NDV3AE5L.js.map} +0 -0
@@ -1,649 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- toDreamboardApiError
4
- } from "./chunk-BVVNBJM4.mjs";
5
- import {
6
- createGameRevision,
7
- createProjectSourceBlobUploadSession,
8
- ensureProject,
9
- getApiVersion,
10
- getCompiledResult,
11
- getCurrentAuthUser,
12
- getJob,
13
- getProjectCompiledResult,
14
- listCompiledResults,
15
- listProjectCompiledResults,
16
- queueProjectRevisionCompile,
17
- uploadInitialProjection
18
- } from "./chunk-SYPLYRGB.mjs";
19
- import {
20
- external_exports
21
- } from "./chunk-2QMNAVV4.mjs";
22
-
23
- // ../../packages/api-client/src/source-revisions.ts
24
- var textEncoder = new TextEncoder();
25
- function bytesToHex(bytes) {
26
- return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
27
- }
28
- async function sha256Hex(bytes) {
29
- const normalizedBytes = new Uint8Array(bytes.byteLength);
30
- normalizedBytes.set(bytes);
31
- const digest = await crypto.subtle.digest(
32
- "SHA-256",
33
- normalizedBytes.buffer
34
- );
35
- return bytesToHex(new Uint8Array(digest));
36
- }
37
- function getUtf8ByteSize(content) {
38
- return textEncoder.encode(content).byteLength;
39
- }
40
- async function computeSourceContentHash(content) {
41
- return sha256Hex(textEncoder.encode(content));
42
- }
43
- async function describeSourceBlob(content) {
44
- return {
45
- contentHash: await computeSourceContentHash(content),
46
- byteSize: getUtf8ByteSize(content)
47
- };
48
- }
49
- async function materializeSourceChangeOperations(changes) {
50
- const blobsByHash = /* @__PURE__ */ new Map();
51
- const materialized = await Promise.all(
52
- Array.from(changes, async (change) => {
53
- if (change.kind === "delete") {
54
- return change;
55
- }
56
- const blob = await describeSourceBlob(change.content);
57
- const existing = blobsByHash.get(blob.contentHash);
58
- if (!existing) {
59
- blobsByHash.set(blob.contentHash, blob);
60
- }
61
- return {
62
- kind: "upsert",
63
- path: change.path,
64
- contentHash: blob.contentHash,
65
- byteSize: blob.byteSize
66
- };
67
- })
68
- );
69
- return {
70
- blobs: Array.from(blobsByHash.values()).sort(
71
- (left, right) => left.contentHash.localeCompare(right.contentHash)
72
- ),
73
- changes: materialized
74
- };
75
- }
76
- function mapUpsertBlobContentsByContentHash(localChanges, materializedChanges) {
77
- const uploadBlobs = /* @__PURE__ */ new Map();
78
- const length = Math.min(localChanges.length, materializedChanges.length);
79
- for (let index = 0; index < length; index += 1) {
80
- const localChange = localChanges[index];
81
- const materializedChange = materializedChanges[index];
82
- if (localChange?.kind !== "upsert" || materializedChange?.kind !== "upsert") {
83
- continue;
84
- }
85
- uploadBlobs.set(materializedChange.contentHash, {
86
- contentHash: materializedChange.contentHash,
87
- byteSize: materializedChange.byteSize,
88
- content: localChange.content
89
- });
90
- }
91
- return uploadBlobs;
92
- }
93
- var SourceBlobUploadError = class extends Error {
94
- status;
95
- details;
96
- constructor(status, details) {
97
- const suffix = details.trim().length > 0 ? `: ${details.trim()}` : "";
98
- super(`Failed to upload source blob (HTTP ${status}${suffix})`);
99
- this.name = "SourceBlobUploadError";
100
- this.status = status;
101
- this.details = details;
102
- }
103
- };
104
- function isDuplicateDirectUploadError(error) {
105
- if (!(error instanceof SourceBlobUploadError)) {
106
- return false;
107
- }
108
- if (error.status === 409) {
109
- return true;
110
- }
111
- const normalizedDetails = error.details.toLowerCase();
112
- return normalizedDetails.includes("duplicate") || normalizedDetails.includes("already exists") || normalizedDetails.includes("resource already exists");
113
- }
114
- async function uploadSourceBlob(uploadTarget, content) {
115
- const response = await fetch(uploadTarget.url, {
116
- method: uploadTarget.method,
117
- headers: uploadTarget.headers,
118
- body: textEncoder.encode(content)
119
- });
120
- if (response.ok) {
121
- return;
122
- }
123
- const details = await response.text().catch(() => "");
124
- throw new SourceBlobUploadError(response.status, details);
125
- }
126
- var SourceBlobSessionRequestError = class extends Error {
127
- apiError;
128
- response;
129
- constructor(message, apiError, response) {
130
- super(message);
131
- this.name = "SourceBlobSessionRequestError";
132
- this.apiError = apiError;
133
- this.response = response;
134
- }
135
- };
136
- function assertSourceBlobUploadSession(data, response) {
137
- if (!data || typeof data !== "object" || !Array.isArray(data.uploads)) {
138
- throw new SourceBlobSessionRequestError(
139
- "Source blob upload session response did not include an uploads array",
140
- data,
141
- response
142
- );
143
- }
144
- }
145
- async function confirmSourceBlobAlreadyExists(options) {
146
- const { requestUploadSession, blob } = options;
147
- const { data, error, response } = await requestUploadSession([
148
- {
149
- contentHash: blob.contentHash,
150
- byteSize: blob.byteSize
151
- }
152
- ]);
153
- if (error || !data) {
154
- throw new SourceBlobSessionRequestError(
155
- "Failed to create source blob upload session",
156
- error,
157
- response
158
- );
159
- }
160
- assertSourceBlobUploadSession(data, response);
161
- return data.uploads[0]?.status === "exists";
162
- }
163
- async function uploadSourceBlobs(options) {
164
- const { blobs, requestUploadSession } = options;
165
- const uniqueBlobs = /* @__PURE__ */ new Map();
166
- for (const blob of blobs) {
167
- const existing = uniqueBlobs.get(blob.contentHash);
168
- if (!existing) {
169
- uniqueBlobs.set(blob.contentHash, blob);
170
- continue;
171
- }
172
- if (existing.byteSize !== blob.byteSize) {
173
- throw new Error(
174
- `Source blob ${blob.contentHash} has conflicting byte sizes.`
175
- );
176
- }
177
- }
178
- if (uniqueBlobs.size === 0) {
179
- return;
180
- }
181
- const { data, error, response } = await requestUploadSession(
182
- Array.from(uniqueBlobs.values(), ({ contentHash, byteSize }) => ({
183
- contentHash,
184
- byteSize
185
- }))
186
- );
187
- if (error || !data) {
188
- throw new SourceBlobSessionRequestError(
189
- "Failed to create source blob upload session",
190
- error,
191
- response
192
- );
193
- }
194
- assertSourceBlobUploadSession(data, response);
195
- for (const upload of data.uploads) {
196
- if (upload.status !== "upload_required") {
197
- continue;
198
- }
199
- const blob = uniqueBlobs.get(upload.contentHash);
200
- if (!blob) {
201
- throw new Error(
202
- `Upload session referenced unknown source blob ${upload.contentHash}.`
203
- );
204
- }
205
- if (!upload.uploadTarget) {
206
- throw new Error(
207
- `Upload target missing for source blob ${upload.contentHash}.`
208
- );
209
- }
210
- try {
211
- await uploadSourceBlob(upload.uploadTarget, blob.content);
212
- if (!await confirmSourceBlobAlreadyExists({ requestUploadSession, blob })) {
213
- throw new Error(
214
- `Source blob ${blob.contentHash} was uploaded but not registered.`
215
- );
216
- }
217
- } catch (error2) {
218
- if (isDuplicateDirectUploadError(error2) && await confirmSourceBlobAlreadyExists({ requestUploadSession, blob })) {
219
- continue;
220
- }
221
- throw error2;
222
- }
223
- }
224
- }
225
- async function uploadProjectSourceBlobs(options) {
226
- const { projectId, blobs } = options;
227
- return uploadSourceBlobs({
228
- blobs,
229
- requestUploadSession: (uploadBlobs) => createProjectSourceBlobUploadSession({
230
- path: { projectId },
231
- body: { blobs: uploadBlobs }
232
- })
233
- });
234
- }
235
-
236
- // src/command-args.ts
237
- var CONFIG_FLAG_ARGS = {
238
- env: {
239
- type: "string",
240
- description: "Environment: local | staging | prod"
241
- },
242
- token: {
243
- type: "string",
244
- description: "Auth token (Dreamboard bearer JWT)"
245
- }
246
- };
247
-
248
- // src/flags.ts
249
- var configFlagsSchema = external_exports.object({
250
- env: external_exports.enum(["local", "staging", "prod"]).optional(),
251
- token: external_exports.string().optional()
252
- });
253
- var ruleInputFlagsSchema = external_exports.object({
254
- "rule-file": external_exports.string().optional(),
255
- rule: external_exports.string().optional()
256
- });
257
- var playerCountFlagsSchema = external_exports.object({
258
- players: external_exports.string().optional(),
259
- "player-count": external_exports.string().optional()
260
- });
261
- var newCommandArgsSchema = configFlagsSchema.extend({
262
- slug: external_exports.string().min(1),
263
- description: external_exports.string().min(1),
264
- force: external_exports.boolean().default(false)
265
- });
266
- var cloneCommandArgsSchema = configFlagsSchema.extend({
267
- slug: external_exports.string().min(1)
268
- });
269
- var queryCommandArgsSchema = configFlagsSchema.extend({
270
- title: external_exports.string().min(1)
271
- });
272
- var pullCommandArgsSchema = configFlagsSchema.extend({
273
- force: external_exports.boolean().default(false)
274
- });
275
- var syncCommandArgsSchema = configFlagsSchema.extend({
276
- force: external_exports.boolean().default(false),
277
- yes: external_exports.boolean().default(false)
278
- });
279
- var compileCommandArgsSchema = configFlagsSchema.extend({
280
- debug: external_exports.boolean().default(false),
281
- "skip-local-check": external_exports.boolean().default(false)
282
- });
283
- var statusCommandArgsSchema = configFlagsSchema.extend({
284
- json: external_exports.boolean().default(false)
285
- });
286
- var devCommandArgsSchema = configFlagsSchema.extend({
287
- seed: external_exports.string().optional(),
288
- "setup-profile": external_exports.string().optional(),
289
- players: external_exports.string().optional(),
290
- "player-count": external_exports.string().optional(),
291
- debug: external_exports.boolean().default(false),
292
- resume: external_exports.string().optional(),
293
- "from-scenario": external_exports.string().optional(),
294
- "new-session": external_exports.boolean().default(false),
295
- open: external_exports.boolean().default(false),
296
- port: external_exports.string().optional(),
297
- host: external_exports.union([external_exports.string(), external_exports.boolean()]).optional(),
298
- "allowed-host": external_exports.string().optional()
299
- });
300
- var joinCommandArgsSchema = configFlagsSchema.extend({
301
- session: external_exports.string().min(1).optional(),
302
- player: external_exports.string().min(1),
303
- "raw-events": external_exports.boolean().default(false)
304
- });
305
- var configCommandArgsSchema = configFlagsSchema.extend({
306
- action: external_exports.string().optional().default("show"),
307
- scope: external_exports.enum(["global", "workspace"]).optional().default("global")
308
- });
309
- var authCommandArgsSchema = external_exports.object({
310
- action: external_exports.enum(["set", "clear", "login", "env", "status"]),
311
- tokenValue: external_exports.string().optional(),
312
- token: external_exports.string().optional(),
313
- jwt: external_exports.boolean().optional(),
314
- env: external_exports.enum(["local", "staging", "prod"]).optional()
315
- });
316
- function parseArgs(commandName, schema, args) {
317
- const parsed = schema.safeParse(args);
318
- if (parsed.success) {
319
- return parsed.data;
320
- }
321
- const details = parsed.error.issues.map((issue) => {
322
- const field = issue.path.length > 0 ? issue.path.join(".") : "args";
323
- return `${field}: ${issue.message}`;
324
- }).join("; ");
325
- throw new Error(`Invalid arguments for '${commandName}': ${details}`);
326
- }
327
- function parseConfigFlags(args) {
328
- return parseArgs("config-flags", configFlagsSchema, args);
329
- }
330
- function parseSyncCommandArgs(args) {
331
- return parseArgs("sync", syncCommandArgsSchema, args);
332
- }
333
- function parseCompileCommandArgs(args) {
334
- return parseArgs("compile", compileCommandArgsSchema, args);
335
- }
336
-
337
- // src/utils/strings.ts
338
- import path from "path";
339
- function titleFromSlug(slug) {
340
- return slug.split("-").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
341
- }
342
- function sleep(ms) {
343
- return new Promise((resolve) => setTimeout(resolve, ms));
344
- }
345
-
346
- // src/services/api/compiled-results-api.ts
347
- var COMPILE_JOB_POLL_INTERVAL_MS = 1e3;
348
- var DEFAULT_COMPILE_JOB_WAIT_TIMEOUT_MS = 10 * 60 * 1e3;
349
- function firstNonEmpty(...values) {
350
- for (const value of values) {
351
- if (typeof value === "string" && value.trim().length > 0) {
352
- return value.trim();
353
- }
354
- }
355
- return null;
356
- }
357
- function formatTerminalCompileJobMessage(job) {
358
- const detail = firstNonEmpty(job.errorMessage, job.message);
359
- const phase = firstNonEmpty(job.phase);
360
- const prefix = `Compile ${job.status.toLowerCase()}${phase ? ` [${phase}]` : ""}`;
361
- return detail ? `${prefix}: ${detail}` : `${prefix}: job ${job.jobId} ended before a compiled result was created.`;
362
- }
363
- function compareCreatedAtDesc(left, right) {
364
- const leftTime = Date.parse(left.createdAt);
365
- const rightTime = Date.parse(right.createdAt);
366
- if (Number.isFinite(leftTime) && Number.isFinite(rightTime)) {
367
- return rightTime - leftTime;
368
- }
369
- if (Number.isFinite(rightTime)) {
370
- return 1;
371
- }
372
- if (Number.isFinite(leftTime)) {
373
- return -1;
374
- }
375
- return 0;
376
- }
377
- async function findFallbackCompiledResultForJob(options) {
378
- const { gameId, projectId, job } = options;
379
- const results = projectId ? await listProjectCompiledResults({
380
- path: { projectId },
381
- query: { limit: 100 }
382
- }) : await listCompiledResults({
383
- path: { gameId },
384
- query: { limit: 100 }
385
- });
386
- if (results.error || !results.data) {
387
- return null;
388
- }
389
- if (results.data.results.length === 0) {
390
- return null;
391
- }
392
- const jobCreatedAtMs = Date.parse(job.createdAt);
393
- const resultsCreatedAfterJob = Number.isFinite(jobCreatedAtMs) ? results.data.results.filter((result) => {
394
- const resultCreatedAtMs = Date.parse(result.createdAt);
395
- return !Number.isFinite(resultCreatedAtMs) || resultCreatedAtMs >= jobCreatedAtMs;
396
- }) : results.data.results;
397
- const candidateResults = resultsCreatedAfterJob.length > 0 ? resultsCreatedAfterJob : results.data.results;
398
- return [...candidateResults].sort(compareCreatedAtDesc)[0] ?? null;
399
- }
400
- async function getCompiledResultSdk(gameId, compiledResultId) {
401
- const { data, error, response } = await getCompiledResult({
402
- path: {
403
- gameId,
404
- compiledResultId
405
- }
406
- });
407
- if (error || !data) {
408
- throw toDreamboardApiError(
409
- error,
410
- response,
411
- "Failed to fetch compiled result"
412
- );
413
- }
414
- return data;
415
- }
416
- async function findProjectCompiledResultsForRevision(options) {
417
- const { projectId, revisionDigest } = options;
418
- const { data, error, response } = await listProjectCompiledResults({
419
- path: { projectId },
420
- query: { limit: 100 }
421
- });
422
- if (error || !data) {
423
- throw toDreamboardApiError(
424
- error,
425
- response,
426
- "Failed to list compiled results"
427
- );
428
- }
429
- return data.results.filter(
430
- (result) => {
431
- const maybeRevisionDigest = result.revisionDigest;
432
- return maybeRevisionDigest === revisionDigest || result.authoringStateId === revisionDigest;
433
- }
434
- );
435
- }
436
- async function getProjectCompiledResultSdk(projectId, compiledResultId) {
437
- const { data, error, response } = await getProjectCompiledResult({
438
- path: { projectId, compiledResultId }
439
- });
440
- if (error || !data) {
441
- throw toDreamboardApiError(
442
- error,
443
- response,
444
- "Failed to fetch compiled result"
445
- );
446
- }
447
- return data;
448
- }
449
- async function queueProjectRevisionCompileSdk(options) {
450
- const { data, error, response } = await queueProjectRevisionCompile({
451
- path: {
452
- projectId: options.projectId,
453
- revisionDigest: options.revisionDigest
454
- }
455
- });
456
- if (error || !data) {
457
- throw toDreamboardApiError(error, response, "Failed to create compile job");
458
- }
459
- return data;
460
- }
461
- async function waitForCompiledResultJobSdk(options) {
462
- const { gameId, projectId, jobId, onProgress } = options;
463
- let previousTransitionKey = null;
464
- const startedAt = Date.now();
465
- const timeoutMs = readCompileJobWaitTimeoutMs();
466
- while (Date.now() - startedAt < timeoutMs) {
467
- const {
468
- data: job,
469
- error,
470
- response
471
- } = await getJob({
472
- path: { jobId }
473
- });
474
- if (error || !job) {
475
- if (isTransientJobPollError(error, response)) {
476
- await sleep(COMPILE_JOB_POLL_INTERVAL_MS);
477
- continue;
478
- }
479
- throw toDreamboardApiError(error, response, "Failed to get job");
480
- }
481
- const transitionKey = `${job.status}:${job.phase ?? ""}`;
482
- if (transitionKey !== previousTransitionKey) {
483
- previousTransitionKey = transitionKey;
484
- onProgress?.(job);
485
- }
486
- if (job.status === "COMPLETED" || job.status === "FAILED") {
487
- const compiledResultId = job.createdCompiledResultId ?? job.createdAppScriptId;
488
- if (compiledResultId) {
489
- if (projectId) {
490
- const compiledResult2 = await getProjectCompiledResultSdk(
491
- projectId,
492
- compiledResultId
493
- );
494
- return { job, compiledResult: compiledResult2 };
495
- }
496
- const compiledResult = await getCompiledResultSdk(
497
- gameId,
498
- compiledResultId
499
- );
500
- return { job, compiledResult };
501
- }
502
- const fallbackCompiledResult = await findFallbackCompiledResultForJob({
503
- gameId,
504
- projectId,
505
- job
506
- });
507
- if (fallbackCompiledResult) {
508
- return { job, compiledResult: fallbackCompiledResult };
509
- }
510
- throw new Error(formatTerminalCompileJobMessage(job));
511
- }
512
- if (job.status === "CANCELLED" || job.status === "INTERRUPTED") {
513
- throw new Error(formatTerminalCompileJobMessage(job));
514
- }
515
- await sleep(COMPILE_JOB_POLL_INTERVAL_MS);
516
- }
517
- throw new Error(`Compile job ${jobId} did not complete in time.`);
518
- }
519
- function readCompileJobWaitTimeoutMs() {
520
- const raw = process.env.DREAMBOARD_COMPILE_WAIT_TIMEOUT_MS;
521
- if (!raw) return DEFAULT_COMPILE_JOB_WAIT_TIMEOUT_MS;
522
- const parsed = Number(raw);
523
- if (!Number.isFinite(parsed) || parsed <= 0) {
524
- return DEFAULT_COMPILE_JOB_WAIT_TIMEOUT_MS;
525
- }
526
- return parsed;
527
- }
528
- function isTransientJobPollError(error, response) {
529
- if (response) return false;
530
- if (!error) return false;
531
- if (error instanceof Error) {
532
- return isTransientJobPollMessage(error.message);
533
- }
534
- if (typeof error === "object" && error !== null && "message" in error) {
535
- return isTransientJobPollMessage(String(error.message));
536
- }
537
- return isTransientJobPollMessage(String(error));
538
- }
539
- function isTransientJobPollMessage(message) {
540
- const normalized = message.toLowerCase();
541
- return normalized.includes("fetch failed") || normalized.includes("network") || normalized.includes("timeout") || normalized.includes("econnreset") || normalized.includes("econnrefused") || normalized.includes("socket");
542
- }
543
-
544
- // src/services/api/preview-api.ts
545
- async function uploadInitialProjectionSdk(gameId, projectionJson) {
546
- const { error, response } = await uploadInitialProjection({
547
- path: { gameId },
548
- body: { projectionJson }
549
- });
550
- if (error) {
551
- throw toDreamboardApiError(
552
- error,
553
- response,
554
- "Failed to upload initial preview projection"
555
- );
556
- }
557
- }
558
-
559
- // src/services/api/source-revisions-api.ts
560
- async function uploadProjectSourceBlobsSdk(projectId, blobs) {
561
- try {
562
- await uploadProjectSourceBlobs({ projectId, blobs });
563
- } catch (error) {
564
- if (error instanceof SourceBlobSessionRequestError) {
565
- throw toDreamboardApiError(
566
- error.apiError,
567
- error.response,
568
- error.message
569
- );
570
- }
571
- throw error;
572
- }
573
- }
574
-
575
- // src/services/api/project-api.ts
576
- async function loadRemoteProjectIdentity() {
577
- const [versionResponse, userResponse] = await Promise.all([
578
- getApiVersion(),
579
- getCurrentAuthUser()
580
- ]);
581
- if (versionResponse.error || !versionResponse.data) {
582
- throw toDreamboardApiError(
583
- versionResponse.error,
584
- versionResponse.response,
585
- "Failed to resolve backend deployment identity"
586
- );
587
- }
588
- if (userResponse.error || !userResponse.data) {
589
- throw toDreamboardApiError(
590
- userResponse.error,
591
- userResponse.response,
592
- "Failed to resolve authenticated owner scope"
593
- );
594
- }
595
- const deploymentId = versionResponse.data.deploymentId;
596
- const ownerScopeId = userResponse.data.ownerScopeId;
597
- return {
598
- deploymentId,
599
- ownerScopeId,
600
- bindingKey: `${deploymentId}:${ownerScopeId}`
601
- };
602
- }
603
- async function ensureProjectSdk(options) {
604
- const { data, error, response } = await ensureProject({
605
- path: { projectId: options.projectId },
606
- body: {
607
- slug: options.slug,
608
- name: titleFromSlug(options.slug),
609
- description: options.description ?? `Dreamboard workspace for ${options.slug}.`,
610
- ...options.updateAlias ? { updateAlias: true } : {}
611
- }
612
- });
613
- if (error || !data) {
614
- throw toDreamboardApiError(error, response, "Failed to ensure project");
615
- }
616
- return data;
617
- }
618
- async function createGameRevisionSdk(options) {
619
- const { data, error, response } = await createGameRevision({
620
- path: { projectId: options.projectId },
621
- body: options.request
622
- });
623
- if (error || !data) {
624
- throw toDreamboardApiError(
625
- error,
626
- response,
627
- "Failed to create game revision"
628
- );
629
- }
630
- return data;
631
- }
632
-
633
- export {
634
- materializeSourceChangeOperations,
635
- mapUpsertBlobContentsByContentHash,
636
- CONFIG_FLAG_ARGS,
637
- parseConfigFlags,
638
- parseSyncCommandArgs,
639
- parseCompileCommandArgs,
640
- findProjectCompiledResultsForRevision,
641
- getProjectCompiledResultSdk,
642
- queueProjectRevisionCompileSdk,
643
- waitForCompiledResultJobSdk,
644
- uploadInitialProjectionSdk,
645
- uploadProjectSourceBlobsSdk,
646
- loadRemoteProjectIdentity,
647
- ensureProjectSdk,
648
- createGameRevisionSdk
649
- };