@puzzmo/sdk 0.0.7 → 1.0.1

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 (75) hide show
  1. package/README.md +80 -260
  2. package/dist/createSimulator-9IxV0l3_.js +2749 -0
  3. package/dist/createSimulator-9IxV0l3_.js.map +1 -0
  4. package/dist/createSimulator-DxhvbnJB.cjs +1428 -0
  5. package/dist/createSimulator-DxhvbnJB.cjs.map +1 -0
  6. package/dist/index.cjs +2 -2
  7. package/dist/index.cjs.map +1 -1
  8. package/dist/index.d.ts +3 -13
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +267 -14
  11. package/dist/index.js.map +1 -1
  12. package/dist/objectSpread2-C4RR_HMd.cjs +1 -0
  13. package/dist/objectSpread2-CJo2CZQ6.js +76 -0
  14. package/dist/sdk.d.ts +61 -0
  15. package/dist/sdk.d.ts.map +1 -0
  16. package/dist/simulator/createSimulator.d.ts +41 -0
  17. package/dist/simulator/createSimulator.d.ts.map +1 -0
  18. package/dist/simulator/fixtures.d.ts +18 -0
  19. package/dist/simulator/fixtures.d.ts.map +1 -0
  20. package/dist/simulator/index.cjs +1 -0
  21. package/dist/simulator/index.d.ts +3 -0
  22. package/dist/simulator/index.d.ts.map +1 -0
  23. package/dist/simulator/index.js +2 -0
  24. package/dist/simulator/messaging.d.ts +12 -0
  25. package/dist/simulator/messaging.d.ts.map +1 -0
  26. package/dist/simulator/standalone.cjs +2 -0
  27. package/dist/simulator/standalone.cjs.map +1 -0
  28. package/dist/simulator/standalone.d.ts +7 -0
  29. package/dist/simulator/standalone.d.ts.map +1 -0
  30. package/dist/simulator/standalone.js +19 -0
  31. package/dist/simulator/standalone.js.map +1 -0
  32. package/dist/simulator/state.d.ts +12 -0
  33. package/dist/simulator/state.d.ts.map +1 -0
  34. package/dist/simulator/styles.d.ts +2 -0
  35. package/dist/simulator/styles.d.ts.map +1 -0
  36. package/dist/simulator/types.d.ts +72 -0
  37. package/dist/simulator/types.d.ts.map +1 -0
  38. package/dist/simulator/views/AuthView.d.ts +3 -0
  39. package/dist/simulator/views/AuthView.d.ts.map +1 -0
  40. package/dist/simulator/views/CheckpointsView.d.ts +3 -0
  41. package/dist/simulator/views/CheckpointsView.d.ts.map +1 -0
  42. package/dist/simulator/views/CtrlView.d.ts +3 -0
  43. package/dist/simulator/views/CtrlView.d.ts.map +1 -0
  44. package/dist/simulator/views/DataView.d.ts +3 -0
  45. package/dist/simulator/views/DataView.d.ts.map +1 -0
  46. package/dist/simulator/views/DoneView.d.ts +3 -0
  47. package/dist/simulator/views/DoneView.d.ts.map +1 -0
  48. package/dist/simulator/views/FeaturesView.d.ts +4 -0
  49. package/dist/simulator/views/FeaturesView.d.ts.map +1 -0
  50. package/dist/simulator/views/MsgsView.d.ts +6 -0
  51. package/dist/simulator/views/MsgsView.d.ts.map +1 -0
  52. package/dist/simulator/views/ThemeView.d.ts +3 -0
  53. package/dist/simulator/views/ThemeView.d.ts.map +1 -0
  54. package/dist/simulator/views/ThumbView.d.ts +6 -0
  55. package/dist/simulator/views/ThumbView.d.ts.map +1 -0
  56. package/dist/simulator/views/index.d.ts +10 -0
  57. package/dist/simulator/views/index.d.ts.map +1 -0
  58. package/dist/themes.d.ts +46 -0
  59. package/dist/themes.d.ts.map +1 -0
  60. package/dist/types.d.ts +232 -0
  61. package/dist/types.d.ts.map +1 -0
  62. package/dist/vite.cjs +11 -0
  63. package/dist/vite.cjs.map +1 -0
  64. package/dist/vite.d.ts +16 -0
  65. package/dist/vite.d.ts.map +1 -0
  66. package/dist/vite.js +45 -0
  67. package/dist/vite.js.map +1 -0
  68. package/dist/workshop.d.ts +7 -175
  69. package/dist/workshop.d.ts.map +1 -1
  70. package/package.json +21 -19
  71. package/dist/index.iife.js +0 -2
  72. package/dist/index.iife.js.map +0 -1
  73. package/dist/index.umd.js +0 -2
  74. package/dist/index.umd.js.map +0 -1
  75. package/dist/puzzmoSDK.d.ts +0 -237
package/dist/index.js CHANGED
@@ -1,17 +1,270 @@
1
- class s extends Error {
2
- constructor(o, t, e) {
3
- super(t), this.type = o, this.originalError = e, this.name = "WorkshopImportError";
4
- }
1
+ import { n as e, t } from "./objectSpread2-CJo2CZQ6.js";
2
+ function n(e) {
3
+ let t = e >= 3600 * 1e3;
4
+ return new Date(e).toISOString().slice(t ? 11 : 14, -1).split(".")[0];
5
5
  }
6
- function l(r) {
7
- return {
8
- hello: () => {
9
- console.log("Hello from Puzzmo SDK!", r);
10
- }
11
- };
6
+ function r(e = 0, t = 0) {
7
+ let r = e, i = t, a = 0, o, s, c, l = () => {
8
+ var e;
9
+ if (s === void 0) return r + i;
10
+ if (o !== void 0) return o;
11
+ let t = ((e = c) == null ? performance.now() : e) - s - a;
12
+ return r + i + t;
13
+ };
14
+ return {
15
+ _init: () => {
16
+ s === void 0 && (s = performance.now(), c = void 0);
17
+ },
18
+ _pause: () => {
19
+ c !== void 0 || s === void 0 || (c = performance.now());
20
+ },
21
+ _resume: () => {
22
+ c !== void 0 && (a += performance.now() - c, c = void 0);
23
+ },
24
+ _reset: (e = 0, t = 0) => {
25
+ r = e, i = t, a = 0, o = void 0, s = void 0, c = void 0;
26
+ },
27
+ _conclude: () => {
28
+ if (c !== void 0) {
29
+ o = l();
30
+ return;
31
+ }
32
+ if (s === void 0) {
33
+ o = r + i;
34
+ return;
35
+ }
36
+ o = l();
37
+ },
38
+ timeMs: () => l(),
39
+ timeSecs: () => l() / 1e3,
40
+ addedTimeMs: () => i,
41
+ addedTimeSecs: () => i / 1e3,
42
+ timeWithoutPenaltySecs: () => (l() - i) / 1e3,
43
+ addPenalty: (e) => {
44
+ i += e;
45
+ },
46
+ isPaused: () => c !== void 0 || s === void 0,
47
+ isRunning: () => s !== void 0 && c === void 0,
48
+ display: () => {
49
+ let e = l() - i;
50
+ return [n(Math.max(0, e)), i === 0 ? "" : n(i)];
51
+ }
52
+ };
12
53
  }
13
- export {
14
- s as WorkshopImportError,
15
- l as createPuzzmoSDK
54
+ function i() {
55
+ let e = /* @__PURE__ */ new Map();
56
+ return typeof window < "u" && window.addEventListener("message", (t) => {
57
+ var n;
58
+ if (!(!(t == null || (n = t.data) == null) && n.type)) return;
59
+ let r = t.data.type, i = e.get(r);
60
+ if (i) {
61
+ var a, o;
62
+ let e = (a = (o = t.data.data) == null ? t.data.json : o) == null ? {} : a;
63
+ r !== "TIMER_TICK" && r !== "TIMER_SYNC" && console.log("[Puzzmo SDK] received:", r, e), i.forEach((t) => t(e));
64
+ }
65
+ }), {
66
+ sendMessage: (e, t) => {
67
+ var n, r;
68
+ let i = {
69
+ type: e,
70
+ json: t,
71
+ _: "p",
72
+ __: "mp",
73
+ private: !0
74
+ };
75
+ "parent" in window && window.parent !== window && window.parent.postMessage(i, "*"), window.postMessage(i, "*"), "webkit" in window && !((n = window.webkit) == null || (n = n.messageHandlers) == null) && n.app && window.webkit.messageHandlers.app.postMessage(i), "puzzmoMessageString" in window && window.puzzmoMessageString(JSON.stringify(i)), "ReactNativeWebView" in window && (r = window.ReactNativeWebView) != null && r.postMessage && window.ReactNativeWebView.postMessage(JSON.stringify(i)), e !== "TIMER_TICK" && e !== "TIMER_SYNC" && console.log("[Puzzmo SDK] sent:", e, t);
76
+ },
77
+ onMessage: (t, n) => (e.has(t) || e.set(t, /* @__PURE__ */ new Set()), e.get(t).add(n), () => {
78
+ var r;
79
+ (r = e.get(t)) == null || r.delete(n);
80
+ })
81
+ };
82
+ }
83
+ var a = i();
84
+ /** Creates a Puzzmo SDK instance for communicating with the Puzzmo host */
85
+ const o = (n = {}) => {
86
+ let i = null, o = null, s = () => {
87
+ var e;
88
+ return i == null || (e = i.startOrFindGameplay) == null ? void 0 : e.gamePlayed;
89
+ }, c = () => {
90
+ var e, t;
91
+ return (e = (t = s()) == null ? void 0 : t.id) == null ? null : e;
92
+ }, l = () => {
93
+ var e, t;
94
+ return (e = (t = s()) == null ? void 0 : t.puzzle.puzzle) == null ? null : e;
95
+ }, u = () => {
96
+ var e, t;
97
+ return (e = (t = s()) == null ? void 0 : t.boardState) == null ? null : e;
98
+ }, d = () => {
99
+ var e;
100
+ return (e = i == null ? void 0 : i.theme) == null ? null : e;
101
+ }, f = () => {
102
+ var e, t;
103
+ return (e = (t = s()) == null ? void 0 : t.completed) == null ? !1 : e;
104
+ }, p = /* @__PURE__ */ new Map(), m = r(), h = null, g = null, _ = () => {
105
+ h || (h = setInterval(() => {
106
+ if (m.isPaused()) return;
107
+ let [e, t] = m.display();
108
+ a.sendMessage("TIMER_TICK", { display: [e, t] });
109
+ }, 500), g = setInterval(() => {
110
+ m.isPaused() || a.sendMessage("TIMER_SYNC", Math.floor(m.timeWithoutPenaltySecs()));
111
+ }, 1e4));
112
+ }, v = () => {
113
+ h && (clearInterval(h), h = null), g && (clearInterval(g), g = null);
114
+ }, y = (e, t) => {
115
+ let n = p.get(e);
116
+ n && n.forEach((e) => e(t));
117
+ };
118
+ return a.onMessage("START_GAME", () => {
119
+ m._init(), _(), y("start");
120
+ }), a.onMessage("PAUSE_GAME", () => {
121
+ m._pause(), y("pause");
122
+ }), a.onMessage("RESUME_GAME", () => {
123
+ m._resume(), y("resume");
124
+ }), a.onMessage("SETTINGS_UPDATE", (e) => y("settingsUpdate", e)), a.onMessage("RETRY_PUZZLE", () => {
125
+ m._reset(), v(), y("retry");
126
+ }), a.onMessage("READY_DATA", (e) => {
127
+ var t;
128
+ let n = e;
129
+ i = n;
130
+ let r = (t = n.startOrFindGameplay) == null ? void 0 : t.gamePlayed;
131
+ if (r) {
132
+ var a, s;
133
+ let e = ((a = r.elapsedTimeSecs) == null ? 0 : a) * 1e3, t = ((s = r.additionalTimeAddedSecs) == null ? 0 : s) * 1e3;
134
+ m._reset(e, t);
135
+ }
136
+ o && (o(n), o = null);
137
+ }), {
138
+ timer: {
139
+ timeMs: () => m.timeMs(),
140
+ timeSecs: () => m.timeSecs(),
141
+ addedTimeMs: () => m.addedTimeMs(),
142
+ addedTimeSecs: () => m.addedTimeSecs(),
143
+ timeWithoutPenaltySecs: () => m.timeWithoutPenaltySecs(),
144
+ display: () => m.display(),
145
+ addPenalty: (e) => m.addPenalty(e),
146
+ isPaused: () => m.isPaused(),
147
+ isRunning: () => m.isRunning()
148
+ },
149
+ gameReady: function() {
150
+ var t = e(function* () {
151
+ var e;
152
+ if (a.sendMessage("READY", {}), l()) return {
153
+ puzzleString: l(),
154
+ boardState: u(),
155
+ theme: d(),
156
+ completed: f(),
157
+ readyData: i
158
+ };
159
+ let t = (e = n.timeout) == null ? 5e3 : e;
160
+ yield new Promise((e, n) => {
161
+ o = e, setTimeout(() => {
162
+ o && (o = null, n(/* @__PURE__ */ Error(`Timeout waiting for READY_DATA after ${t}ms`)));
163
+ }, t);
164
+ });
165
+ let r = l();
166
+ if (!r) throw Error("READY_DATA received but no puzzle data found");
167
+ return {
168
+ puzzleString: r,
169
+ boardState: u(),
170
+ theme: d(),
171
+ completed: f(),
172
+ readyData: i
173
+ };
174
+ });
175
+ return function() {
176
+ return t.apply(this, arguments);
177
+ };
178
+ }(),
179
+ gameLoaded: (e = {}) => {
180
+ a.sendMessage("READY_GAME_LOADED", {
181
+ state: e,
182
+ gameRuntimeContract: "1.0",
183
+ embedRuntimeContract: "1.0"
184
+ });
185
+ },
186
+ on: (e, t) => (p.has(e) || p.set(e, /* @__PURE__ */ new Set()), p.get(e).add(t), () => {
187
+ var n;
188
+ (n = p.get(e)) == null || n.delete(t);
189
+ }),
190
+ off: (e, t) => {
191
+ var n;
192
+ (n = p.get(e)) == null || n.delete(t);
193
+ },
194
+ updateGameState: (e, t) => {
195
+ var n, r;
196
+ let i = c();
197
+ i && a.sendMessage("UPLOAD_NEW_GAME_STATE", {
198
+ id: i,
199
+ input: {
200
+ boardState: e,
201
+ elapsedTimeSecs: (n = t == null ? void 0 : t.elapsedTimeSecs) == null ? m.timeWithoutPenaltySecs() : n,
202
+ additionalTimeAddedSecs: (r = t == null ? void 0 : t.additionalTimeAddedSecs) == null ? m.addedTimeSecs() : r,
203
+ hintsUsed: t == null ? void 0 : t.hintsUsed,
204
+ resetsUsed: t == null ? void 0 : t.resetsUsed,
205
+ metric1: 0,
206
+ metric2: 0,
207
+ metric3: 0,
208
+ metric4: 0,
209
+ metricStrings: [],
210
+ collabUserReferences: []
211
+ }
212
+ });
213
+ },
214
+ gameCompleted: (e, n) => {
215
+ var r, i, o, s, l;
216
+ m._conclude(), v();
217
+ let u = t(t({}, e), {}, {
218
+ elapsedTimeSecs: (r = e.elapsedTimeSecs) == null ? m.timeWithoutPenaltySecs() : r,
219
+ additionalTimeAddedSecs: (i = e.additionalTimeAddedSecs) == null ? m.addedTimeSecs() : i
220
+ }), d = (o = n == null ? void 0 : n.deeds) == null ? [] : o;
221
+ d.push({
222
+ id: "points",
223
+ value: e.pointsAwarded
224
+ }), d.push({
225
+ id: "time",
226
+ value: Math.round((s = u.elapsedTimeSecs) == null ? 0 : s) + Math.round((l = u.additionalTimeAddedSecs) == null ? 0 : l)
227
+ });
228
+ let f = c();
229
+ f && a.sendMessage("GAME_COMPLETED", {
230
+ id: f,
231
+ input: u,
232
+ config: n
233
+ });
234
+ },
235
+ showCompletionScreen: (e, t, n = !0) => {
236
+ a.sendMessage("SHOW_GAME_COMPLETE_SCREEN", {
237
+ results: e,
238
+ showRetry: n,
239
+ gameplay: t
240
+ });
241
+ },
242
+ hitCheckpoint: (e, t, n) => {
243
+ var r;
244
+ if (!c()) return;
245
+ let i = (r = u()) == null ? "" : r, o = {
246
+ elapsedTimeSecs: m.timeWithoutPenaltySecs(),
247
+ additionalTimeAddedSecs: m.addedTimeSecs()
248
+ };
249
+ a.sendMessage("HIT_CHECKPOINT", {
250
+ checkpointName: e,
251
+ gameplay: {
252
+ inputStr: i,
253
+ play: o
254
+ },
255
+ checkpointConfig: t,
256
+ augConfig: n == null ? {} : n
257
+ });
258
+ },
259
+ _hostAPI: a
260
+ };
261
+ };
262
+ /** Custom error class for workshop import failures */
263
+ var s = class extends Error {
264
+ constructor(e, t, n) {
265
+ super(t), this.type = e, this.originalError = n, this.name = "WorkshopImportError";
266
+ }
16
267
  };
17
- //# sourceMappingURL=index.js.map
268
+ export { s as WorkshopImportError, o as createPuzzmoSDK };
269
+
270
+ //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/workshop.ts","../src/index.ts"],"sourcesContent":["import type { GameSettingsUIComponents } from \"@puzzmo-com/shared/hostAPI\";\n\n/**\n * Severity level for validation issues.\n *\n * - `error`: Critical issue that prevents puzzle from being valid\n * - `warning`: Issue that should be addressed but doesn't prevent usage\n * - `info`: Informational message about the puzzle\n */\nexport type ValidationLevel = \"error\" | \"warning\" | \"info\";\n\n/** Represents a single validation issue found during puzzle validation. */\nexport interface ValidationIssue {\n /** Severity level of this validation issue */\n level: ValidationLevel;\n /** Human-readable description of the issue */\n message: string;\n /** Line number in the puzzle data where the issue occurs (1-indexed, optional) */\n line?: number;\n /**\n * Column position in the puzzle data where the issue occurs (1-indexed,\n * optional)\n */\n col?: number;\n /** Length of the problematic text segment for highlighting (optional) */\n length?: number;\n}\n\n/**\n * Complete validation report for a puzzle. Contains the overall validation\n * status and any issues found.\n */\nexport interface ValidationReport {\n /** Whether the puzzle passed validation without errors */\n success: boolean;\n /** Array of validation issues found (errors, warnings, and info messages) */\n issues: ValidationIssue[];\n}\n\n/**\n * Types of errors that can occur during puzzle import.\n *\n * - `invalid_format`: The file format is not supported or recognized\n * - `parsing_error`: The file format is valid but parsing failed\n * - `unknown`: An unexpected error occurred during import\n */\nexport type ImportErrorType = \"invalid_format\" | \"parsing_error\" | \"unknown\";\n\n/**\n * Custom error class for workshop import failures. Thrown by the `onImport`\n * function when a puzzle cannot be imported.\n *\n * @example\n *\n * ```typescript\n * throw new WorkshopImportError(\n * \"invalid_format\",\n * \"Unsupported file extension: .xyz\",\n * );\n * ```\n */\nexport class WorkshopImportError extends Error {\n constructor(\n /** The category of import error */\n public type: ImportErrorType,\n /** Human-readable error message */\n message: string,\n /** Optional underlying error that caused the import to fail */\n public originalError?: unknown,\n ) {\n super(message);\n this.name = \"WorkshopImportError\";\n }\n}\n\n/**\n * Result of a successful puzzle import operation. Contains the converted puzzle\n * data and optional metadata.\n */\nexport interface ImportResult {\n /**\n * The converted puzzle data in the target format (e.g., XD format for\n * crosswords)\n */\n data: string;\n /** Optional validation warnings about the imported puzzle */\n warnings?: ValidationIssue[];\n /** Optional puzzle title extracted from the import file */\n title?: string;\n /** Optional list of puzzle authors */\n authors?: string[];\n /** Optional list of puzzle editors */\n editors?: string[];\n}\n\n/**\n * Main interface for a Workshop bundle. Workshop bundles are dynamically loaded\n * modules that provide game-specific functionality for puzzle validation and\n * import.\n *\n * @example\n *\n * ```typescript\n * // In your workshop bundle (e.g., games/crossword/src/workshop/index.ts)\n * export const validator = {\n * validate(data: string): ValidationReport {\n * // Custom validation logic\n * return { success: true, issues: [] };\n * },\n * };\n *\n * export const importer = {\n * async onImport(\n * filename: string,\n * contents: string | ArrayBuffer,\n * ): Promise<ImportResult> {\n * // Custom import logic\n * return { data: convertedData };\n * },\n * };\n * ```\n */\nexport interface WorkshopBundle {\n /** Required validator for puzzle data validation */\n validator: {\n /**\n * Validates puzzle data and returns a report of issues.\n *\n * @param data - The raw puzzle data string to validate\n *\n * @returns Validation report with success status and any issues found\n */\n validate(data: string): Promise<ValidationReport> | ValidationReport;\n };\n /** Optional importer for converting external puzzle file formats */\n importer?: {\n /**\n * Imports a puzzle file and converts it to the game's native format. Should\n * throw `WorkshopImportError` for known failure cases.\n *\n * @param filename - Name of the file being imported\n * @param contents - Raw file contents (string for\n * text files, ArrayBuffer for binary)\n *\n * @returns Import result with converted data and optional metadata\n *\n * @throws {WorkshopImportError} For invalid or unsupported files\n */\n onImport(\n filename: string,\n contents: string | ArrayBuffer,\n ): Promise<ImportResult> | ImportResult;\n };\n /**\n * Optional settings configuration for embed customization in Workshop. Allows\n * Workshop to render a settings form for configuring embed overrides.\n */\n settings?: {\n /** UI component definitions for rendering the settings form */\n components: GameSettingsUIComponents[];\n /** Default values for all settings */\n defaults: Record<string, unknown>;\n };\n /**\n * Optional per-queue editor settings declaration. Shown on the queue page and\n * passed to editor.mount() as config.settings.\n */\n editorSettings?: {\n /** UI component definitions for rendering the editor settings form */\n components: GameSettingsUIComponents[];\n /** Default values for all settings */\n defaults: Record<string, unknown>;\n };\n\n editor?: {\n /** Called when first visiting a puzzle page. */\n mount: (\n element: HTMLElement,\n config: {\n puzzleString: string;\n onChange: (puzzleString: string) => void;\n theme: \"light\" | \"dark\";\n width: number;\n height: number;\n /**\n * Optional function for making chat completions from the editor (e.g.,\n * for AI-assisted puzzle editing). This needs to be enabled for a team\n * explicitly.\n */\n chatCompletion?: (prompt: string) => Promise<string>;\n /**\n * Optional function for fetching URLs from the editor (e.g., for\n * fetching article content). This needs to be enabled for a team\n * explicitly.\n */\n fetchURL?: (url: string) => Promise<{ status: number; body: string }>;\n /**\n * Pre-configured editor settings values from the queue's\n * editorSettings.\n */\n settings?: Record<string, unknown>;\n },\n ) => Promise<{\n unmount: () => void;\n /**\n * Called whenever the puzzle string is updated in the editor from the\n * outside, or when the theme or dimensions update. Workshop will rely on\n * validator to reject / accept updates.\n */\n update: (config: {\n puzzleString?: string;\n theme?: \"light\" | \"dark\";\n width?: number;\n height?: number;\n }) => void;\n }>;\n };\n}\n","import { GameConfig } from \"./puzzmoSDK\";\n\n// Export the auto-generated public SDK types\nexport type * from \"./puzzmoSDK\";\n\n// Export workshop types\nexport * from \"./workshop\";\n\n/**\n * Creates a Puzzmo SDK instance\n *\n * @param config - Configuration options\n *\n * @returns A Puzzmo SDK instance\n */\nexport function createPuzzmoSDK(config: GameConfig) {\n return {\n hello: () => {\n console.log(\"Hello from Puzzmo SDK!\", config);\n },\n };\n}\n\nexport type PuzzmoSDK = ReturnType<typeof createPuzzmoSDK>;\n"],"names":["WorkshopImportError","type","message","originalError","createPuzzmoSDK","config"],"mappings":"AA6DO,MAAMA,UAA4B,MAAM;AAAA,EAC7C,YAESC,GAEPC,GAEOC,GACP;AACA,UAAMD,CAAO,GANN,KAAA,OAAAD,GAIA,KAAA,gBAAAE,GAGP,KAAK,OAAO;AAAA,EACd;AACF;AC1DO,SAASC,EAAgBC,GAAoB;AAClD,SAAO;AAAA,IACL,OAAO,MAAM;AACX,cAAQ,IAAI,0BAA0BA,CAAM;AAAA,IAC9C;AAAA,EAAA;AAEJ;"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/sdk.ts","../src/workshop.ts"],"sourcesContent":["import type {\n MessagesSentFromEmbed,\n MessagesReceived,\n GamePlay,\n AugmentationConfig,\n CheckpointConfig,\n Theme,\n Deed,\n} from \"./types\"\n\nexport type SDK = ReturnType<typeof createPuzzmoSDK>\n\nexport interface PuzzmoSDKOptions {\n /** Optional timeout in ms to wait for READY_DATA (default: 5000) */\n timeout?: number\n}\n\ntype SupportedOutgoingMessages = Pick<\n MessagesSentFromEmbed,\n | \"READY\"\n | \"READY_GAME_LOADED\"\n | \"GAME_COMPLETED\"\n | \"SHOW_GAME_COMPLETE_SCREEN\"\n | \"TIMER_TICK\"\n | \"TIMER_SYNC\"\n | \"UPLOAD_NEW_GAME_STATE\"\n | \"HIT_CHECKPOINT\"\n>\n\ntype SupportedIncomingMessages = Pick<\n MessagesReceived,\n \"READY_DATA\" | \"START_GAME\" | \"PAUSE_GAME\" | \"RESUME_GAME\" | \"SETTINGS_UPDATE\" | \"RETRY_PUZZLE\"\n>\n\ntype MessageHandler<T extends keyof SupportedIncomingMessages> = (data: SupportedIncomingMessages[T]) => void\n\nexport type SDKEventMap = {\n start: void\n pause: void\n resume: void\n retry: void\n settingsUpdate: any\n}\n\nexport type SDKEventType = keyof SDKEventMap\n\nexport interface SDKTimer {\n /** Get elapsed time in milliseconds */\n timeMs: () => number\n /** Get elapsed time in seconds */\n timeSecs: () => number\n /** Get added/penalty time in milliseconds */\n addedTimeMs: () => number\n /** Get added/penalty time in seconds */\n addedTimeSecs: () => number\n /** Get elapsed time without penalties in seconds */\n timeWithoutPenaltySecs: () => number\n /** Get formatted display strings [elapsed, added] */\n display: () => [string, string]\n /** Add penalty time in milliseconds */\n addPenalty: (ms: number) => void\n /** Check if timer is paused */\n isPaused: () => boolean\n /** Check if timer has been started */\n isRunning: () => boolean\n}\n\nfunction formatTime(timeMs: number): string {\n const isAnHourOrMore = timeMs >= 60 * 60 * 1000\n return new Date(timeMs)\n .toISOString()\n .slice(isAnHourOrMore ? 11 : 14, -1)\n .split(\".\")[0]\n}\n\nfunction createTimer(\n initialTimeMs = 0,\n initialAddedTimeMs = 0,\n): SDKTimer & {\n _init: () => void\n _pause: () => void\n _resume: () => void\n _reset: (initialTimeMs?: number, initialAddedTimeMs?: number) => void\n _conclude: () => void\n} {\n let baseTime = initialTimeMs\n let addedTime = initialAddedTimeMs\n let pausedTime = 0\n let concludeTime: number | undefined\n\n let startDate: number | undefined = undefined\n let pausedDate: number | undefined = undefined\n\n const getTime = (): number => {\n if (startDate === undefined) return baseTime + addedTime\n if (concludeTime !== undefined) return concludeTime\n const now = pausedDate ?? performance.now()\n const elapsed = now - startDate - pausedTime\n return baseTime + addedTime + elapsed\n }\n\n return {\n _init: () => {\n if (startDate === undefined) {\n startDate = performance.now()\n pausedDate = undefined\n }\n },\n _pause: () => {\n if (pausedDate !== undefined || startDate === undefined) return\n pausedDate = performance.now()\n },\n _resume: () => {\n if (pausedDate === undefined) return\n pausedTime += performance.now() - pausedDate\n pausedDate = undefined\n },\n _reset: (newInitialTimeMs = 0, newInitialAddedTimeMs = 0) => {\n baseTime = newInitialTimeMs\n addedTime = newInitialAddedTimeMs\n pausedTime = 0\n concludeTime = undefined\n startDate = undefined\n pausedDate = undefined\n },\n _conclude: () => {\n if (pausedDate !== undefined) {\n concludeTime = getTime()\n return\n }\n if (startDate === undefined) {\n concludeTime = baseTime + addedTime\n return\n }\n concludeTime = getTime()\n },\n timeMs: () => getTime(),\n timeSecs: () => getTime() / 1000,\n addedTimeMs: () => addedTime,\n addedTimeSecs: () => addedTime / 1000,\n timeWithoutPenaltySecs: () => (getTime() - addedTime) / 1000,\n addPenalty: (ms: number) => {\n addedTime += ms\n },\n isPaused: () => pausedDate !== undefined || startDate === undefined,\n isRunning: () => startDate !== undefined && pausedDate === undefined,\n display: () => {\n const elapsed = getTime() - addedTime\n const elapsedStr = formatTime(Math.max(0, elapsed))\n const addedStr = addedTime === 0 ? \"\" : formatTime(addedTime)\n return [elapsedStr, addedStr]\n },\n }\n}\n\nfunction createHostAPI() {\n const messageHandlers = new Map<string, Set<(data: any) => void>>()\n\n const sendMessage = <T extends keyof SupportedOutgoingMessages>(type: T, json: SupportedOutgoingMessages[T]) => {\n const message = { type, json, _: \"p\", __: \"mp\", private: true }\n\n if (\"parent\" in window && window.parent !== window)\n window.parent.postMessage(message, \"*\")\n\n window.postMessage(message, \"*\")\n\n if (\"webkit\" in window && (window as any).webkit?.messageHandlers?.app)\n (window as any).webkit.messageHandlers.app.postMessage(message)\n\n if (\"puzzmoMessageString\" in window)\n (window as any).puzzmoMessageString(JSON.stringify(message))\n\n if (\"ReactNativeWebView\" in window && (window as any).ReactNativeWebView?.postMessage)\n (window as any).ReactNativeWebView.postMessage(JSON.stringify(message))\n\n if (type !== \"TIMER_TICK\" && type !== \"TIMER_SYNC\")\n console.log(\"[Puzzmo SDK] sent:\", type, json)\n }\n\n const onMessage = <T extends keyof SupportedIncomingMessages>(type: T, handler: MessageHandler<T>) => {\n if (!messageHandlers.has(type))\n messageHandlers.set(type, new Set())\n messageHandlers.get(type)!.add(handler)\n\n return () => {\n messageHandlers.get(type)?.delete(handler)\n }\n }\n\n if (typeof window !== \"undefined\") {\n window.addEventListener(\"message\", (event) => {\n if (!event?.data?.type) return\n const msgType = event.data.type as string\n const handlers = messageHandlers.get(msgType)\n if (handlers) {\n const msgData = event.data.data ?? event.data.json ?? {}\n if (msgType !== \"TIMER_TICK\" && msgType !== \"TIMER_SYNC\")\n console.log(\"[Puzzmo SDK] received:\", msgType, msgData)\n handlers.forEach((handler) => handler(msgData))\n }\n })\n }\n\n return { sendMessage, onMessage }\n}\n\nconst hostAPI = createHostAPI()\n\n/** Creates a Puzzmo SDK instance for communicating with the Puzzmo host */\nexport const createPuzzmoSDK = (options: PuzzmoSDKOptions = {}) => {\n let readyData: MessagesReceived[\"READY_DATA\"] | null = null\n let readyDataResolve: ((data: MessagesReceived[\"READY_DATA\"]) => void) | null = null\n\n const getGameplay = () => readyData?.startOrFindGameplay?.gamePlayed\n const getGameplayID = () => getGameplay()?.id ?? null\n const getPuzzleString = () => getGameplay()?.puzzle.puzzle ?? null\n const getBoardState = () => getGameplay()?.boardState ?? null\n const getTheme = () => readyData?.theme ?? null\n const getCompleted = () => getGameplay()?.completed ?? false\n\n const eventListeners = new Map<SDKEventType, Set<(data?: any) => void>>()\n\n const internalTimer = createTimer()\n let timerTickInterval: ReturnType<typeof setInterval> | null = null\n let timerSyncInterval: ReturnType<typeof setInterval> | null = null\n\n const startTimerIntervals = () => {\n if (timerTickInterval) return\n\n timerTickInterval = setInterval(() => {\n if (internalTimer.isPaused()) return\n const [elapsed, added] = internalTimer.display()\n hostAPI.sendMessage(\"TIMER_TICK\", { display: [elapsed, added] })\n }, 500)\n\n timerSyncInterval = setInterval(() => {\n if (internalTimer.isPaused()) return\n hostAPI.sendMessage(\"TIMER_SYNC\", Math.floor(internalTimer.timeWithoutPenaltySecs()))\n }, 10000)\n }\n\n const stopTimerIntervals = () => {\n if (timerTickInterval) {\n clearInterval(timerTickInterval)\n timerTickInterval = null\n }\n if (timerSyncInterval) {\n clearInterval(timerSyncInterval)\n timerSyncInterval = null\n }\n }\n\n const emit = <T extends SDKEventType>(event: T, data?: SDKEventMap[T]) => {\n const listeners = eventListeners.get(event)\n if (listeners) listeners.forEach((listener) => listener(data))\n }\n\n hostAPI.onMessage(\"START_GAME\", () => {\n internalTimer._init()\n startTimerIntervals()\n emit(\"start\")\n })\n\n hostAPI.onMessage(\"PAUSE_GAME\", () => {\n internalTimer._pause()\n emit(\"pause\")\n })\n\n hostAPI.onMessage(\"RESUME_GAME\", () => {\n internalTimer._resume()\n emit(\"resume\")\n })\n\n hostAPI.onMessage(\"SETTINGS_UPDATE\", (data) => emit(\"settingsUpdate\", data))\n\n hostAPI.onMessage(\"RETRY_PUZZLE\", () => {\n internalTimer._reset()\n stopTimerIntervals()\n emit(\"retry\")\n })\n\n hostAPI.onMessage(\"READY_DATA\", (data) => {\n const bootstrapData = data as MessagesReceived[\"READY_DATA\"]\n readyData = bootstrapData\n\n const gamePlayed = bootstrapData.startOrFindGameplay?.gamePlayed\n if (gamePlayed) {\n const existingTime = (gamePlayed.elapsedTimeSecs ?? 0) * 1000\n const existingAddedTime = (gamePlayed.additionalTimeAddedSecs ?? 0) * 1000\n internalTimer._reset(existingTime, existingAddedTime)\n }\n\n if (readyDataResolve) {\n readyDataResolve(bootstrapData)\n readyDataResolve = null\n }\n })\n\n const timer: SDKTimer = {\n timeMs: () => internalTimer.timeMs(),\n timeSecs: () => internalTimer.timeSecs(),\n addedTimeMs: () => internalTimer.addedTimeMs(),\n addedTimeSecs: () => internalTimer.addedTimeSecs(),\n timeWithoutPenaltySecs: () => internalTimer.timeWithoutPenaltySecs(),\n display: () => internalTimer.display(),\n addPenalty: (ms: number) => internalTimer.addPenalty(ms),\n isPaused: () => internalTimer.isPaused(),\n isRunning: () => internalTimer.isRunning(),\n }\n\n return {\n timer,\n\n gameReady: async (): Promise<{\n puzzleString: string\n boardState: string | null\n theme: Theme | null\n completed: boolean\n readyData: MessagesReceived[\"READY_DATA\"] | null\n }> => {\n hostAPI.sendMessage(\"READY\", {})\n\n if (getPuzzleString()) {\n return {\n puzzleString: getPuzzleString()!,\n boardState: getBoardState(),\n theme: getTheme(),\n completed: getCompleted(),\n readyData,\n }\n }\n\n const timeout = options.timeout ?? 5000\n const readyDataPromise = new Promise<MessagesReceived[\"READY_DATA\"]>((resolve, reject) => {\n readyDataResolve = resolve\n setTimeout(() => {\n if (readyDataResolve) {\n readyDataResolve = null\n reject(new Error(`Timeout waiting for READY_DATA after ${timeout}ms`))\n }\n }, timeout)\n })\n\n await readyDataPromise\n\n const puzzleString = getPuzzleString()\n if (!puzzleString) throw new Error(\"READY_DATA received but no puzzle data found\")\n\n return {\n puzzleString,\n boardState: getBoardState(),\n theme: getTheme(),\n completed: getCompleted(),\n readyData,\n }\n },\n\n gameLoaded: (state: any = {}) => {\n hostAPI.sendMessage(\"READY_GAME_LOADED\", {\n state,\n gameRuntimeContract: \"1.0\",\n embedRuntimeContract: \"1.0\",\n })\n },\n\n on: <T extends SDKEventType>(event: T, listener: (data?: SDKEventMap[T]) => void): (() => void) => {\n if (!eventListeners.has(event))\n eventListeners.set(event, new Set())\n eventListeners.get(event)!.add(listener)\n return () => {\n eventListeners.get(event)?.delete(listener)\n }\n },\n\n off: <T extends SDKEventType>(event: T, listener: (data?: SDKEventMap[T]) => void) => {\n eventListeners.get(event)?.delete(listener)\n },\n\n updateGameState: (inputString: string, play?: Partial<GamePlay>) => {\n const gameplayID = getGameplayID()\n if (!gameplayID) return\n\n hostAPI.sendMessage(\"UPLOAD_NEW_GAME_STATE\", {\n id: gameplayID,\n input: {\n boardState: inputString,\n elapsedTimeSecs: play?.elapsedTimeSecs ?? internalTimer.timeWithoutPenaltySecs(),\n additionalTimeAddedSecs: play?.additionalTimeAddedSecs ?? internalTimer.addedTimeSecs(),\n hintsUsed: play?.hintsUsed,\n resetsUsed: play?.resetsUsed,\n metric1: 0,\n metric2: 0,\n metric3: 0,\n metric4: 0,\n metricStrings: [],\n collabUserReferences: [],\n },\n })\n },\n\n gameCompleted: (play: Partial<GamePlay>, config?: AugmentationConfig) => {\n internalTimer._conclude()\n stopTimerIntervals()\n\n const finalPlay: Partial<GamePlay> = {\n ...play,\n elapsedTimeSecs: play.elapsedTimeSecs ?? internalTimer.timeWithoutPenaltySecs(),\n additionalTimeAddedSecs: play.additionalTimeAddedSecs ?? internalTimer.addedTimeSecs(),\n }\n\n const deeds: Deed[] = (config?.deeds as any) ?? []\n deeds.push({ id: \"points\", value: play.pointsAwarded })\n deeds.push({\n id: \"time\",\n value: Math.round(finalPlay.elapsedTimeSecs ?? 0) + Math.round(finalPlay.additionalTimeAddedSecs ?? 0),\n })\n\n const gameplayID = getGameplayID()\n if (gameplayID) {\n hostAPI.sendMessage(\"GAME_COMPLETED\", {\n id: gameplayID,\n input: finalPlay,\n config,\n })\n }\n },\n\n showCompletionScreen: (results: any[], gameplay: GamePlay, showRetry = true) => {\n hostAPI.sendMessage(\"SHOW_GAME_COMPLETE_SCREEN\", {\n results,\n showRetry,\n gameplay,\n })\n },\n\n hitCheckpoint: (checkpointName: string, checkpointConfig: CheckpointConfig, config?: AugmentationConfig) => {\n const gameplayID = getGameplayID()\n if (!gameplayID) return\n\n const inputStr = getBoardState() ?? \"\"\n const play: Partial<GamePlay> = {\n elapsedTimeSecs: internalTimer.timeWithoutPenaltySecs(),\n additionalTimeAddedSecs: internalTimer.addedTimeSecs(),\n }\n\n hostAPI.sendMessage(\"HIT_CHECKPOINT\", {\n checkpointName,\n gameplay: { inputStr, play },\n checkpointConfig,\n augConfig: config ?? {},\n })\n },\n\n _hostAPI: hostAPI,\n }\n}\n","/** Severity level for validation issues */\nexport type ValidationLevel = \"error\" | \"warning\" | \"info\"\n\n/** Represents a single validation issue found during puzzle validation */\nexport interface ValidationIssue {\n level: ValidationLevel\n message: string\n line?: number\n col?: number\n length?: number\n}\n\n/** Complete validation report for a puzzle */\nexport interface ValidationReport {\n success: boolean\n issues: ValidationIssue[]\n}\n\nexport type ImportErrorType = \"invalid_format\" | \"parsing_error\" | \"unknown\"\n\n/** Custom error class for workshop import failures */\nexport class WorkshopImportError extends Error {\n constructor(\n public type: ImportErrorType,\n message: string,\n public originalError?: unknown,\n ) {\n super(message)\n this.name = \"WorkshopImportError\"\n }\n}\n\n/** Result of a successful puzzle import operation */\nexport interface ImportResult {\n data: string\n warnings?: ValidationIssue[]\n title?: string\n authors?: string[]\n editors?: string[]\n}\n\n/** Main interface for a Workshop bundle */\nexport interface WorkshopBundle {\n validator: {\n validate(data: string): Promise<ValidationReport> | ValidationReport\n }\n importer?: {\n onImport(filename: string, contents: string | ArrayBuffer): Promise<ImportResult> | ImportResult\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ function e(e,t,n,r,i,a,o){try{var s=e[a](o),c=s.value}catch(e){n(e);return}s.done?t(c):Promise.resolve(c).then(r,i)}function t(t){return function(){var n=this,r=arguments;return new Promise(function(i,a){var o=t.apply(n,r);function s(t){e(o,i,a,s,c,`next`,t)}function c(t){e(o,i,a,s,c,`throw`,t)}s(void 0)})}}function n(e){"@babel/helpers - typeof";return n=typeof Symbol==`function`&&typeof Symbol.iterator==`symbol`?function(e){return typeof e}:function(e){return e&&typeof Symbol==`function`&&e.constructor===Symbol&&e!==Symbol.prototype?`symbol`:typeof e},n(e)}function r(e,t){if(n(e)!=`object`||!e)return e;var r=e[Symbol.toPrimitive];if(r!==void 0){var i=r.call(e,t||`default`);if(n(i)!=`object`)return i;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(t===`string`?String:Number)(e)}function i(e){var t=r(e,`string`);return n(t)==`symbol`?t:t+``}function a(e,t,n){return(t=i(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function s(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]==null?{}:arguments[t];t%2?o(Object(n),!0).forEach(function(t){a(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):o(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return t}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return s}});
@@ -0,0 +1,76 @@
1
+ function e(e, t, n, r, i, a, o) {
2
+ try {
3
+ var s = e[a](o), c = s.value;
4
+ } catch (e) {
5
+ n(e);
6
+ return;
7
+ }
8
+ s.done ? t(c) : Promise.resolve(c).then(r, i);
9
+ }
10
+ function t(t) {
11
+ return function() {
12
+ var n = this, r = arguments;
13
+ return new Promise(function(i, a) {
14
+ var o = t.apply(n, r);
15
+ function s(t) {
16
+ e(o, i, a, s, c, "next", t);
17
+ }
18
+ function c(t) {
19
+ e(o, i, a, s, c, "throw", t);
20
+ }
21
+ s(void 0);
22
+ });
23
+ };
24
+ }
25
+ function n(e) {
26
+ "@babel/helpers - typeof";
27
+ return n = typeof Symbol == "function" && typeof Symbol.iterator == "symbol" ? function(e) {
28
+ return typeof e;
29
+ } : function(e) {
30
+ return e && typeof Symbol == "function" && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e;
31
+ }, n(e);
32
+ }
33
+ function r(e, t) {
34
+ if (n(e) != "object" || !e) return e;
35
+ var r = e[Symbol.toPrimitive];
36
+ if (r !== void 0) {
37
+ var i = r.call(e, t || "default");
38
+ if (n(i) != "object") return i;
39
+ throw TypeError("@@toPrimitive must return a primitive value.");
40
+ }
41
+ return (t === "string" ? String : Number)(e);
42
+ }
43
+ function i(e) {
44
+ var t = r(e, "string");
45
+ return n(t) == "symbol" ? t : t + "";
46
+ }
47
+ function a(e, t, n) {
48
+ return (t = i(t)) in e ? Object.defineProperty(e, t, {
49
+ value: n,
50
+ enumerable: !0,
51
+ configurable: !0,
52
+ writable: !0
53
+ }) : e[t] = n, e;
54
+ }
55
+ function o(e, t) {
56
+ var n = Object.keys(e);
57
+ if (Object.getOwnPropertySymbols) {
58
+ var r = Object.getOwnPropertySymbols(e);
59
+ t && (r = r.filter(function(t) {
60
+ return Object.getOwnPropertyDescriptor(e, t).enumerable;
61
+ })), n.push.apply(n, r);
62
+ }
63
+ return n;
64
+ }
65
+ function s(e) {
66
+ for (var t = 1; t < arguments.length; t++) {
67
+ var n = arguments[t] == null ? {} : arguments[t];
68
+ t % 2 ? o(Object(n), !0).forEach(function(t) {
69
+ a(e, t, n[t]);
70
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(n)) : o(Object(n)).forEach(function(t) {
71
+ Object.defineProperty(e, t, Object.getOwnPropertyDescriptor(n, t));
72
+ });
73
+ }
74
+ return e;
75
+ }
76
+ export { t as n, s as t };
package/dist/sdk.d.ts ADDED
@@ -0,0 +1,61 @@
1
+ import type { MessagesSentFromEmbed, MessagesReceived, GamePlay, AugmentationConfig, CheckpointConfig, Theme } from "./types";
2
+ export type SDK = ReturnType<typeof createPuzzmoSDK>;
3
+ export interface PuzzmoSDKOptions {
4
+ /** Optional timeout in ms to wait for READY_DATA (default: 5000) */
5
+ timeout?: number;
6
+ }
7
+ type SupportedOutgoingMessages = Pick<MessagesSentFromEmbed, "READY" | "READY_GAME_LOADED" | "GAME_COMPLETED" | "SHOW_GAME_COMPLETE_SCREEN" | "TIMER_TICK" | "TIMER_SYNC" | "UPLOAD_NEW_GAME_STATE" | "HIT_CHECKPOINT">;
8
+ type SupportedIncomingMessages = Pick<MessagesReceived, "READY_DATA" | "START_GAME" | "PAUSE_GAME" | "RESUME_GAME" | "SETTINGS_UPDATE" | "RETRY_PUZZLE">;
9
+ type MessageHandler<T extends keyof SupportedIncomingMessages> = (data: SupportedIncomingMessages[T]) => void;
10
+ export type SDKEventMap = {
11
+ start: void;
12
+ pause: void;
13
+ resume: void;
14
+ retry: void;
15
+ settingsUpdate: any;
16
+ };
17
+ export type SDKEventType = keyof SDKEventMap;
18
+ export interface SDKTimer {
19
+ /** Get elapsed time in milliseconds */
20
+ timeMs: () => number;
21
+ /** Get elapsed time in seconds */
22
+ timeSecs: () => number;
23
+ /** Get added/penalty time in milliseconds */
24
+ addedTimeMs: () => number;
25
+ /** Get added/penalty time in seconds */
26
+ addedTimeSecs: () => number;
27
+ /** Get elapsed time without penalties in seconds */
28
+ timeWithoutPenaltySecs: () => number;
29
+ /** Get formatted display strings [elapsed, added] */
30
+ display: () => [string, string];
31
+ /** Add penalty time in milliseconds */
32
+ addPenalty: (ms: number) => void;
33
+ /** Check if timer is paused */
34
+ isPaused: () => boolean;
35
+ /** Check if timer has been started */
36
+ isRunning: () => boolean;
37
+ }
38
+ /** Creates a Puzzmo SDK instance for communicating with the Puzzmo host */
39
+ export declare const createPuzzmoSDK: (options?: PuzzmoSDKOptions) => {
40
+ timer: SDKTimer;
41
+ gameReady: () => Promise<{
42
+ puzzleString: string;
43
+ boardState: string | null;
44
+ theme: Theme | null;
45
+ completed: boolean;
46
+ readyData: MessagesReceived["READY_DATA"] | null;
47
+ }>;
48
+ gameLoaded: (state?: any) => void;
49
+ on: <T extends SDKEventType>(event: T, listener: (data?: SDKEventMap[T]) => void) => (() => void);
50
+ off: <T extends SDKEventType>(event: T, listener: (data?: SDKEventMap[T]) => void) => void;
51
+ updateGameState: (inputString: string, play?: Partial<GamePlay>) => void;
52
+ gameCompleted: (play: Partial<GamePlay>, config?: AugmentationConfig) => void;
53
+ showCompletionScreen: (results: any[], gameplay: GamePlay, showRetry?: boolean) => void;
54
+ hitCheckpoint: (checkpointName: string, checkpointConfig: CheckpointConfig, config?: AugmentationConfig) => void;
55
+ _hostAPI: {
56
+ sendMessage: <T extends keyof SupportedOutgoingMessages>(type: T, json: SupportedOutgoingMessages[T]) => void;
57
+ onMessage: <T extends keyof SupportedIncomingMessages>(type: T, handler: MessageHandler<T>) => () => void;
58
+ };
59
+ };
60
+ export {};
61
+ //# sourceMappingURL=sdk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../src/sdk.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Simulator - A development UI for testing games with the Puzzmo Proto SDK.
3
+ *
4
+ * This script simulates the Puzzmo host environment by:
5
+ * - Listening for READY messages from the game
6
+ * - Sending READY_DATA with puzzle data
7
+ * - Providing UI controls for START_GAME, PAUSE_GAME, RESUME_GAME, RETRY_PUZZLE
8
+ *
9
+ * Usage in index.html:
10
+ * ```html
11
+ * <script type="module">
12
+ * import { createSimulator } from "@puzzmo/sdk/simulator"
13
+ * createSimulator({ puzzlePath: "./sample-puzzle.json", autoStart: true })
14
+ * </script>
15
+ * ```
16
+ *
17
+ * With fixtures (recommended for multiple puzzles):
18
+ * ```html
19
+ * <script type="module">
20
+ * import { createSimulator } from "@puzzmo/sdk/simulator"
21
+ * const fixtures = import.meta.glob("./fixtures/puzzles/**\/*.json", { eager: true })
22
+ * createSimulator({ fixtures })
23
+ * </script>
24
+ * ```
25
+ * The fixtures folder structure should be: fixtures/puzzles/{category}/{puzzle}.json
26
+ * This will show dropdowns in the Ctrl tab to select category and puzzle.
27
+ */
28
+ import type { SimulatorConfig, FixtureImports } from "./types";
29
+ export type { SimulatorConfig, FixtureImports };
30
+ interface SimulatorInstance {
31
+ updateFixtures: (fixtures: FixtureImports) => void;
32
+ sendToGame: (type: any, data: any) => void;
33
+ loadPuzzle: () => Promise<any>;
34
+ }
35
+ /**
36
+ * Creates the Simulator UI and message handling.
37
+ * If called multiple times, updates the existing instance with new settings (e.g., fixtures).
38
+ */
39
+ declare function createSimulator(config?: SimulatorConfig): SimulatorInstance;
40
+ export { createSimulator };
41
+ //# sourceMappingURL=createSimulator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createSimulator.d.ts","sourceRoot":"","sources":["../../src/simulator/createSimulator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,KAAK,EAAE,eAAe,EAA4D,cAAc,EAAE,MAAM,SAAS,CAAA;AAkBxH,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,CAAA;AAM/C,UAAU,iBAAiB;IACzB,cAAc,EAAE,CAAC,QAAQ,EAAE,cAAc,KAAK,IAAI,CAAA;IAClD,UAAU,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,KAAK,IAAI,CAAA;IAC1C,UAAU,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,CAAA;CAC/B;AAGD;;;GAGG;AACH,iBAAS,eAAe,CAAC,MAAM,GAAE,eAAoB,GAAG,iBAAiB,CAogBxE;AAED,OAAO,EAAE,eAAe,EAAE,CAAA"}
@@ -0,0 +1,18 @@
1
+ import type { FixtureImports } from "./types";
2
+ /**
3
+ * Parse fixture imports into a structured format: { category: { filename: data } }
4
+ */
5
+ export declare function parseFixtures(fixtures: FixtureImports): Map<string, Map<string, any>>;
6
+ /**
7
+ * Render fixture selector HTML
8
+ */
9
+ export declare function renderFixtureSelector(categories: string[], selectedCategory: string | null): string;
10
+ /**
11
+ * Update puzzle select options based on selected category
12
+ */
13
+ export declare function updatePuzzleOptions(puzzleSelect: HTMLSelectElement, fixtures: Map<string, Map<string, any>>, category: string, selectedPuzzle: string | null): string | null;
14
+ /**
15
+ * Get puzzle data from fixtures
16
+ */
17
+ export declare function getFixturePuzzle(fixtures: Map<string, Map<string, any>>, category: string | null, puzzle: string | null): any | null;
18
+ //# sourceMappingURL=fixtures.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../../src/simulator/fixtures.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAE7C;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,cAAc,GAAG,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAgCrF;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAiBnG;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,iBAAiB,EAC/B,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,EACvC,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,GAAG,IAAI,GAC5B,MAAM,GAAG,IAAI,CAiBf;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,CAGpI"}
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../createSimulator-DxhvbnJB.cjs`);exports.createSimulator=e.t;
@@ -0,0 +1,3 @@
1
+ export { createSimulator } from "./createSimulator";
2
+ export type { SimulatorConfig, FixtureImports } from "./types";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/simulator/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA"}
@@ -0,0 +1,2 @@
1
+ import { t as e } from "../createSimulator-9IxV0l3_.js";
2
+ export { e as createSimulator };
@@ -0,0 +1,12 @@
1
+ import type { MessagesReceived } from "../types";
2
+ import type { MessageLogEntry } from "./types";
3
+ export interface MessageLogger {
4
+ log: (type: string, data: any, direction: "in" | "out") => void;
5
+ clear: () => void;
6
+ getLog: () => MessageLogEntry[];
7
+ }
8
+ export declare function createMessageLogger(onLog?: (entry: MessageLogEntry) => void): MessageLogger;
9
+ export declare function sendToGame(type: keyof MessagesReceived, data: any, logger?: MessageLogger): void;
10
+ export type MessageHandler = (type: string, data: any) => void;
11
+ export declare function createMessageListener(handler: MessageHandler, logger?: MessageLogger): () => void;
12
+ //# sourceMappingURL=messaging.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messaging.d.ts","sourceRoot":"","sources":["../../src/simulator/messaging.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAChD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAE9C,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,GAAG,KAAK,KAAK,IAAI,CAAA;IAC/D,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,MAAM,EAAE,MAAM,eAAe,EAAE,CAAA;CAChC;AAED,wBAAgB,mBAAmB,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,GAAG,aAAa,CA0B3F;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,gBAAgB,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,IAAI,CAIhG;AAED,MAAM,MAAM,cAAc,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,IAAI,CAAA;AAE9D,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,MAAM,IAAI,CAqBjG"}
@@ -0,0 +1,2 @@
1
+ const e=require(`../createSimulator-DxhvbnJB.cjs`);var t=()=>{var t;e.t((t=window.SIMULATOR_CONFIG)==null?{}:t)};document.readyState===`loading`?document.addEventListener(`DOMContentLoaded`,t):t();
2
+ //# sourceMappingURL=standalone.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"standalone.cjs","names":[],"sources":["../../src/simulator/standalone.ts"],"sourcesContent":["/**\n * Standalone entry point for the simulator.\n *\n * Use as an IIFE script tag for non-Vite setups:\n * ```html\n * <script>\n * window.SIMULATOR_CONFIG = { puzzlePath: \"./sample-puzzle.json\" }\n * </script>\n * <script src=\"path/to/simulator/standalone.iife.js\"></script>\n * ```\n */\nimport { createSimulator } from \"./createSimulator\"\nimport type { SimulatorConfig } from \"./types\"\n\ndeclare global {\n interface Window {\n SIMULATOR_CONFIG?: SimulatorConfig\n }\n}\n\nconst init = () => {\n const config = window.SIMULATOR_CONFIG ?? {}\n createSimulator(config)\n}\n\nif (document.readyState === \"loading\") {\n document.addEventListener(\"DOMContentLoaded\", init)\n} else {\n init()\n}\n"],"mappings":"mDAoBA,IAAM,MAAa,OAEjB,EAAA,GAAA,EADe,OAAO,mBAAA,KAAoB,EAAE,CAAtB,EACC,EAGrB,SAAS,aAAe,UAC1B,SAAS,iBAAiB,mBAAoB,EAAK,CAEnD,GAAM"}
@@ -0,0 +1,7 @@
1
+ import type { SimulatorConfig } from "./types";
2
+ declare global {
3
+ interface Window {
4
+ SIMULATOR_CONFIG?: SimulatorConfig;
5
+ }
6
+ }
7
+ //# sourceMappingURL=standalone.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"standalone.d.ts","sourceRoot":"","sources":["../../src/simulator/standalone.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAE9C,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,gBAAgB,CAAC,EAAE,eAAe,CAAA;KACnC;CACF"}