@playcademy/sdk 0.0.1-beta.5 → 0.0.1-beta.6

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/dist/bus.d.ts ADDED
@@ -0,0 +1,37 @@
1
+ import type { GameContextPayload } from './types';
2
+ export declare enum BusEvents {
3
+ INIT = "PLAYCADEMY_INIT",
4
+ TOKEN_REFRESH = "PLAYCADEMY_TOKEN_REFRESH",
5
+ PAUSE = "PLAYCADEMY_PAUSE",
6
+ RESUME = "PLAYCADEMY_RESUME",
7
+ FORCE_EXIT = "PLAYCADEMY_FORCE_EXIT",
8
+ OVERLAY = "PLAYCADEMY_OVERLAY",
9
+ READY = "PLAYCADEMY_READY",
10
+ EXIT = "PLAYCADEMY_EXIT",
11
+ TELEMETRY = "PLAYCADEMY_TELEMETRY"
12
+ }
13
+ type BusHandler<T = unknown> = (payload: T) => void;
14
+ export type BusEventMap = {
15
+ [BusEvents.INIT]: GameContextPayload;
16
+ [BusEvents.TOKEN_REFRESH]: {
17
+ token: string;
18
+ exp: number;
19
+ };
20
+ [BusEvents.PAUSE]: void;
21
+ [BusEvents.RESUME]: void;
22
+ [BusEvents.FORCE_EXIT]: void;
23
+ [BusEvents.OVERLAY]: boolean;
24
+ [BusEvents.READY]: void;
25
+ [BusEvents.EXIT]: void;
26
+ [BusEvents.TELEMETRY]: {
27
+ fps: number;
28
+ mem: number;
29
+ };
30
+ };
31
+ interface Bus {
32
+ emit<K extends BusEvents>(type: K, payload: BusEventMap[K]): void;
33
+ on<K extends BusEvents>(type: K, handler: BusHandler<BusEventMap[K]>): void;
34
+ off<K extends BusEvents>(type: K, handler: BusHandler<BusEventMap[K]>): void;
35
+ }
36
+ export declare const bus: Bus;
37
+ export {};
@@ -0,0 +1,144 @@
1
+ import { type Method } from './request';
2
+ import type { Game, GameWithManifest, UpsertGameMetadataInput, InsertReward, UpdateReward } from '@playcademy/types';
3
+ import type { GameState, InventoryItemWithReward, ClientConfig, ClientEvents, LoginResponse, GameTokenResponse, StartSessionResponse, InventoryMutationResponse, DeveloperStatusValue } from '../types';
4
+ export declare class PlaycademyClient {
5
+ private baseUrl;
6
+ private token?;
7
+ private gameId?;
8
+ private listeners;
9
+ private internalClientSessionId?;
10
+ constructor(config: ClientConfig);
11
+ private _initializeInternalSession;
12
+ getBaseUrl(): string;
13
+ on<E extends keyof ClientEvents>(event: E, callback: (payload: ClientEvents[E]) => void): void;
14
+ private emit;
15
+ setToken(token: string | null): void;
16
+ onAuthChange(callback: (token: string | null) => void): void;
17
+ protected request<T>(path: string, method: Method, body?: unknown, headers?: Record<string, string>): Promise<T>;
18
+ private _ensureGameId;
19
+ auth: {
20
+ logout: () => Promise<void>;
21
+ };
22
+ runtime: {
23
+ getGameToken: (gameId: string, options?: {
24
+ apply?: boolean;
25
+ }) => Promise<GameTokenResponse>;
26
+ exit: () => Promise<void>;
27
+ };
28
+ games: {
29
+ fetch: (gameIdOrSlug: string) => Promise<GameWithManifest>;
30
+ list: () => Promise<Array<Game>>;
31
+ saveState: (state: Record<string, unknown>) => Promise<void>;
32
+ loadState: () => Promise<GameState>;
33
+ startSession: (gameId?: string) => Promise<StartSessionResponse>;
34
+ endSession: (sessionId: string, gameId?: string) => Promise<void>;
35
+ };
36
+ users: {
37
+ me: () => Promise<{
38
+ id: string;
39
+ createdAt: Date;
40
+ updatedAt: Date;
41
+ name: string;
42
+ username: string | null;
43
+ email: string;
44
+ emailVerified: boolean;
45
+ image: string | null;
46
+ role: "admin" | "player" | "developer";
47
+ developerStatus: "none" | "pending" | "approved";
48
+ }>;
49
+ inventory: {
50
+ get: () => Promise<InventoryItemWithReward[]>;
51
+ add: (rewardId: string, qty: number) => Promise<InventoryMutationResponse>;
52
+ spend: (rewardId: string, qty: number) => Promise<InventoryMutationResponse>;
53
+ };
54
+ };
55
+ dev: {
56
+ auth: {
57
+ applyForDeveloper: () => Promise<void>;
58
+ getDeveloperStatus: () => Promise<DeveloperStatusValue>;
59
+ };
60
+ games: {
61
+ upsert: (slug: string, metadata: UpsertGameMetadataInput, file: File | Blob) => Promise<Game>;
62
+ update: (gameId: string, props: Partial<Game>) => Promise<void>;
63
+ delete: (gameId: string) => Promise<void>;
64
+ };
65
+ keys: {
66
+ createKey: (gameId: string, label?: string) => Promise<{
67
+ id: string;
68
+ createdAt: Date;
69
+ userId: string;
70
+ label: string | null;
71
+ keyHash: string;
72
+ }>;
73
+ listKeys: (gameId: string) => Promise<{
74
+ id: string;
75
+ createdAt: Date;
76
+ userId: string;
77
+ label: string | null;
78
+ keyHash: string;
79
+ }[]>;
80
+ revokeKey: (keyId: string) => Promise<void>;
81
+ };
82
+ };
83
+ maps: {
84
+ elements: (mapId: string) => Promise<{
85
+ id: string;
86
+ metadata: ({
87
+ description?: string | undefined;
88
+ sourceTiledObjects?: Record<string, unknown>[] | undefined;
89
+ } & {
90
+ [k: string]: unknown;
91
+ }) | null;
92
+ mapId: string | null;
93
+ elementSlug: string;
94
+ interactionType: "game_entry" | "game_registry" | "info" | "teleport" | "door_in" | "door_out" | "npc_interaction" | "quest_trigger";
95
+ gameId: string | null;
96
+ }[]>;
97
+ };
98
+ admin: {
99
+ games: {
100
+ pauseGame: (gameId: string) => Promise<void>;
101
+ resumeGame: (gameId: string) => Promise<void>;
102
+ };
103
+ rewards: {
104
+ createReward: (props: InsertReward) => Promise<{
105
+ id: string;
106
+ displayName: string;
107
+ metadata: unknown;
108
+ internalName: string;
109
+ description: string | null;
110
+ type: "currency" | "badge" | "trophy" | "unlock" | "upgrade" | "other";
111
+ }>;
112
+ getReward: (rewardId: string) => Promise<{
113
+ id: string;
114
+ displayName: string;
115
+ metadata: unknown;
116
+ internalName: string;
117
+ description: string | null;
118
+ type: "currency" | "badge" | "trophy" | "unlock" | "upgrade" | "other";
119
+ }>;
120
+ listRewards: () => Promise<{
121
+ id: string;
122
+ displayName: string;
123
+ metadata: unknown;
124
+ internalName: string;
125
+ description: string | null;
126
+ type: "currency" | "badge" | "trophy" | "unlock" | "upgrade" | "other";
127
+ }[]>;
128
+ updateReward: (rewardId: string, props: UpdateReward) => Promise<{
129
+ id: string;
130
+ displayName: string;
131
+ metadata: unknown;
132
+ internalName: string;
133
+ description: string | null;
134
+ type: "currency" | "badge" | "trophy" | "unlock" | "upgrade" | "other";
135
+ }>;
136
+ deleteReward: (rewardId: string) => Promise<void>;
137
+ };
138
+ };
139
+ telemetry: {
140
+ pushMetrics: (metrics: Record<string, number>) => Promise<void>;
141
+ };
142
+ ping(): string;
143
+ static login(baseUrl: string, email: string, password: string): Promise<LoginResponse>;
144
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Base error class for Cademy SDK specific errors.
3
+ */
4
+ export declare class PlaycademyError extends Error {
5
+ constructor(message: string);
6
+ }
7
+ export declare class ApiError extends Error {
8
+ status: number;
9
+ details: unknown;
10
+ constructor(status: number, message: string, details: unknown);
11
+ }
@@ -0,0 +1,24 @@
1
+ import type { ManifestV1 } from '@playcademy/types';
2
+ /** Permitted HTTP verbs */
3
+ export type Method = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
4
+ export interface RequestOptions {
5
+ path: string;
6
+ baseUrl: string;
7
+ token?: string | null;
8
+ method?: Method;
9
+ body?: unknown;
10
+ extraHeaders?: Record<string, string>;
11
+ }
12
+ /**
13
+ * Thin wrapper around `fetch` that:
14
+ * • attaches Bearer token if provided
15
+ * • stringifies JSON bodies and sets Content‑Type
16
+ * • passes FormData untouched so the browser adds multipart boundary
17
+ * • normalises non‑2xx responses into ApiError
18
+ * • auto‑parses JSON responses, falls back to text/void
19
+ */
20
+ export declare function request<T = unknown>({ path, baseUrl, token, method, body, extraHeaders, }: RequestOptions): Promise<T>;
21
+ /**
22
+ * Fetches, parses, and validates the playcademy.manifest.json file from a given base URL.
23
+ */
24
+ export declare function fetchManifest(assetBundleBase: string): Promise<ManifestV1>;
@@ -0,0 +1,7 @@
1
+ import { PlaycademyClient } from './core/client';
2
+ /** For Node, SSR, dashboards, etc. */
3
+ export { PlaycademyClient } from './core/client';
4
+ /** Factory for code running *inside* the CADEMY loader (games) */
5
+ export declare function initFromWindow(): Promise<PlaycademyClient>;
6
+ export { bus, BusEvents } from './bus';
7
+ export { PlaycademyError } from './core/errors';
@@ -0,0 +1,363 @@
1
+ // src/bus.ts
2
+ var BusEvents;
3
+ ((BusEvents2) => {
4
+ BusEvents2["INIT"] = "PLAYCADEMY_INIT";
5
+ BusEvents2["TOKEN_REFRESH"] = "PLAYCADEMY_TOKEN_REFRESH";
6
+ BusEvents2["PAUSE"] = "PLAYCADEMY_PAUSE";
7
+ BusEvents2["RESUME"] = "PLAYCADEMY_RESUME";
8
+ BusEvents2["FORCE_EXIT"] = "PLAYCADEMY_FORCE_EXIT";
9
+ BusEvents2["OVERLAY"] = "PLAYCADEMY_OVERLAY";
10
+ BusEvents2["READY"] = "PLAYCADEMY_READY";
11
+ BusEvents2["EXIT"] = "PLAYCADEMY_EXIT";
12
+ BusEvents2["TELEMETRY"] = "PLAYCADEMY_TELEMETRY";
13
+ })(BusEvents ||= {});
14
+ var busListeners = new Map;
15
+ var bus = {
16
+ emit(type, payload) {
17
+ window.dispatchEvent(new CustomEvent(type, { detail: payload }));
18
+ },
19
+ on(type, handler) {
20
+ const listener = (event) => handler(event.detail);
21
+ if (!busListeners.has(type)) {
22
+ busListeners.set(type, new Map);
23
+ }
24
+ busListeners.get(type).set(handler, listener);
25
+ window.addEventListener(type, listener);
26
+ },
27
+ off(type, handler) {
28
+ const typeListeners = busListeners.get(type);
29
+ if (!typeListeners || !typeListeners.has(handler)) {
30
+ return;
31
+ }
32
+ const actualListener = typeListeners.get(handler);
33
+ window.removeEventListener(type, actualListener);
34
+ typeListeners.delete(handler);
35
+ if (typeListeners.size === 0) {
36
+ busListeners.delete(type);
37
+ }
38
+ }
39
+ };
40
+
41
+ // src/core/errors.ts
42
+ class PlaycademyError extends Error {
43
+ constructor(message) {
44
+ super(message);
45
+ this.name = "PlaycademyError";
46
+ }
47
+ }
48
+
49
+ class ApiError extends Error {
50
+ status;
51
+ details;
52
+ constructor(status, message, details) {
53
+ super(`${status} ${message}`);
54
+ this.status = status;
55
+ this.details = details;
56
+ Object.setPrototypeOf(this, ApiError.prototype);
57
+ }
58
+ }
59
+
60
+ // src/core/request.ts
61
+ async function request({
62
+ path,
63
+ baseUrl,
64
+ token,
65
+ method = "GET",
66
+ body,
67
+ extraHeaders = {}
68
+ }) {
69
+ const url = baseUrl.replace(/\/$/, "") + (path.startsWith("/") ? path : `/${path}`);
70
+ const headers = { ...extraHeaders };
71
+ let payload;
72
+ if (body instanceof FormData) {
73
+ payload = body;
74
+ } else if (body !== undefined && body !== null) {
75
+ payload = JSON.stringify(body);
76
+ headers["Content-Type"] = "application/json";
77
+ }
78
+ if (token)
79
+ headers["Authorization"] = `Bearer ${token}`;
80
+ const res = await fetch(url, {
81
+ method,
82
+ headers,
83
+ body: payload,
84
+ credentials: "omit"
85
+ });
86
+ if (!res.ok) {
87
+ const errorBody = await res.clone().json().catch(() => res.text().catch(() => {
88
+ return;
89
+ })) ?? undefined;
90
+ throw new ApiError(res.status, res.statusText, errorBody);
91
+ }
92
+ if (res.status === 204)
93
+ return;
94
+ const contentType = res.headers.get("content-type") ?? "";
95
+ if (contentType.includes("application/json")) {
96
+ return await res.json();
97
+ }
98
+ return await res.text();
99
+ }
100
+ async function fetchManifest(assetBundleBase) {
101
+ const manifestUrl = `${assetBundleBase.replace(/\/$/, "")}/playcademy.manifest.json`;
102
+ try {
103
+ const response = await fetch(manifestUrl);
104
+ if (!response.ok) {
105
+ console.error(`[fetchManifest] Failed to fetch manifest from ${manifestUrl}. Status: ${response.status}`);
106
+ throw new PlaycademyError(`Failed to fetch manifest: ${response.status} ${response.statusText}`);
107
+ }
108
+ return await response.json();
109
+ } catch (error) {
110
+ if (error instanceof PlaycademyError) {
111
+ throw error;
112
+ }
113
+ console.error(`[fetchManifest] Error fetching or parsing manifest from ${manifestUrl}:`, error);
114
+ throw new PlaycademyError("Failed to load or parse game manifest");
115
+ }
116
+ }
117
+
118
+ // src/core/client.ts
119
+ class PlaycademyClient {
120
+ baseUrl;
121
+ token;
122
+ gameId;
123
+ listeners = {};
124
+ internalClientSessionId;
125
+ constructor(config) {
126
+ this.baseUrl = config.baseUrl;
127
+ this.token = config.token;
128
+ this.gameId = config.gameId;
129
+ if (this.gameId) {
130
+ this._initializeInternalSession().catch((error) => {
131
+ console.error("[SDK] Background initialization of auto-session failed:", error);
132
+ });
133
+ }
134
+ }
135
+ async _initializeInternalSession() {
136
+ if (!this.gameId || this.internalClientSessionId) {
137
+ return;
138
+ }
139
+ try {
140
+ const response = await this.games.startSession(this.gameId);
141
+ this.internalClientSessionId = response.sessionId;
142
+ } catch (error) {
143
+ console.error("[SDK] Auto-starting session failed for game", this.gameId, error);
144
+ }
145
+ }
146
+ getBaseUrl() {
147
+ const isRelative = this.baseUrl.startsWith("/");
148
+ const isBrowser = typeof window !== "undefined";
149
+ return isRelative && isBrowser ? `${window.location.origin}${this.baseUrl}` : this.baseUrl;
150
+ }
151
+ on(event, callback) {
152
+ this.listeners[event] = this.listeners[event] ?? [];
153
+ this.listeners[event].push(callback);
154
+ }
155
+ emit(event, payload) {
156
+ (this.listeners[event] ?? []).forEach((listener) => {
157
+ listener(payload);
158
+ });
159
+ }
160
+ setToken(token) {
161
+ this.token = token ?? undefined;
162
+ this.emit("authChange", { token: this.token ?? null });
163
+ }
164
+ onAuthChange(callback) {
165
+ this.on("authChange", (payload) => callback(payload.token));
166
+ }
167
+ async request(path, method, body, headers) {
168
+ const effectiveHeaders = { ...headers };
169
+ return request({
170
+ path,
171
+ method,
172
+ body,
173
+ baseUrl: this.baseUrl,
174
+ token: this.token,
175
+ extraHeaders: effectiveHeaders
176
+ });
177
+ }
178
+ _ensureGameId() {
179
+ if (!this.gameId) {
180
+ throw new PlaycademyError("This operation requires a gameId, but none was provided when initializing the client.");
181
+ }
182
+ return this.gameId;
183
+ }
184
+ auth = {
185
+ logout: async () => {
186
+ await this.request(`/auth/logout`, "DELETE");
187
+ this.setToken(null);
188
+ }
189
+ };
190
+ runtime = {
191
+ getGameToken: async (gameId, options) => {
192
+ const res = await this.request(`/games/${gameId}/token`, "POST");
193
+ if (options?.apply) {
194
+ this.setToken(res.token);
195
+ }
196
+ return res;
197
+ },
198
+ exit: async () => {
199
+ if (this.internalClientSessionId && this.gameId) {
200
+ try {
201
+ await this.games.endSession(this.internalClientSessionId, this.gameId);
202
+ } catch (error) {
203
+ console.error("[SDK] Failed to auto-end session:", this.internalClientSessionId, error);
204
+ }
205
+ }
206
+ bus.emit("PLAYCADEMY_EXIT" /* EXIT */, undefined);
207
+ }
208
+ };
209
+ games = {
210
+ fetch: async (gameIdOrSlug) => {
211
+ const baseGameData = await this.request(`/games/${gameIdOrSlug}`, "GET");
212
+ const manifestData = await fetchManifest(baseGameData.assetBundleBase);
213
+ return {
214
+ ...baseGameData,
215
+ manifest: manifestData
216
+ };
217
+ },
218
+ list: () => this.request("/games", "GET"),
219
+ saveState: async (state) => {
220
+ const gameId = this._ensureGameId();
221
+ await this.request(`/games/${gameId}/state`, "POST", state);
222
+ },
223
+ loadState: async () => {
224
+ const gameId = this._ensureGameId();
225
+ return this.request(`/games/${gameId}/state`, "GET");
226
+ },
227
+ startSession: async (gameId) => {
228
+ const idToUse = gameId ?? this._ensureGameId();
229
+ return this.request(`/games/${idToUse}/sessions`, "POST", {});
230
+ },
231
+ endSession: async (sessionId, gameId) => {
232
+ const effectiveGameIdToEnd = gameId ?? this._ensureGameId();
233
+ if (this.internalClientSessionId && sessionId === this.internalClientSessionId && effectiveGameIdToEnd === this.gameId) {
234
+ this.internalClientSessionId = undefined;
235
+ }
236
+ await this.request(`/games/${effectiveGameIdToEnd}/sessions/${sessionId}/end`, "POST");
237
+ }
238
+ };
239
+ users = {
240
+ me: async () => {
241
+ return this.request("/users/me", "GET");
242
+ },
243
+ inventory: {
244
+ get: async () => this.request(`/inventory`, "GET"),
245
+ add: async (rewardId, qty) => {
246
+ const res = await this.request(`/inventory/add`, "POST", { rewardId, qty });
247
+ this.emit("inventoryChange", {
248
+ rewardId,
249
+ delta: qty,
250
+ newTotal: res.newTotal
251
+ });
252
+ return res;
253
+ },
254
+ spend: async (rewardId, qty) => {
255
+ const res = await this.request(`/inventory/spend`, "POST", { rewardId, qty });
256
+ this.emit("inventoryChange", {
257
+ rewardId,
258
+ delta: -qty,
259
+ newTotal: res.newTotal
260
+ });
261
+ return res;
262
+ }
263
+ }
264
+ };
265
+ dev = {
266
+ auth: {
267
+ applyForDeveloper: () => this.request("/dev/apply", "POST"),
268
+ getDeveloperStatus: async () => {
269
+ const response = await this.request("/dev/status", "GET");
270
+ return response.status;
271
+ }
272
+ },
273
+ games: {
274
+ upsert: (slug, metadata, file) => {
275
+ const form = new FormData;
276
+ form.append("metadata", JSON.stringify(metadata));
277
+ form.append("file", file);
278
+ return this.request(`/games/${slug}`, "PUT", form);
279
+ },
280
+ update: (gameId, props) => this.request(`/games/${gameId}`, "PATCH", props),
281
+ delete: (gameId) => this.request(`/games/${gameId}`, "DELETE")
282
+ },
283
+ keys: {
284
+ createKey: (gameId, label) => this.request(`/dev/games/${gameId}/keys`, "POST", { label }),
285
+ listKeys: (gameId) => this.request(`/dev/games/${gameId}/keys`, "GET"),
286
+ revokeKey: (keyId) => this.request(`/dev/keys/${keyId}`, "DELETE")
287
+ }
288
+ };
289
+ maps = {
290
+ elements: (mapId) => this.request(`/map/elements?mapId=${mapId}`, "GET")
291
+ };
292
+ admin = {
293
+ games: {
294
+ pauseGame: (gameId) => this.request(`/admin/games/${gameId}/pause`, "POST"),
295
+ resumeGame: (gameId) => this.request(`/admin/games/${gameId}/resume`, "POST")
296
+ },
297
+ rewards: {
298
+ createReward: (props) => this.request("/rewards", "POST", props),
299
+ getReward: (rewardId) => this.request(`/rewards/${rewardId}`, "GET"),
300
+ listRewards: () => this.request("/rewards", "GET"),
301
+ updateReward: (rewardId, props) => this.request(`/rewards/${rewardId}`, "PATCH", props),
302
+ deleteReward: (rewardId) => this.request(`/rewards/${rewardId}`, "DELETE")
303
+ }
304
+ };
305
+ telemetry = {
306
+ pushMetrics: (metrics) => this.request(`/telemetry/metrics`, "POST", metrics)
307
+ };
308
+ ping() {
309
+ return "pong";
310
+ }
311
+ static async login(baseUrl, email, password) {
312
+ let url = baseUrl;
313
+ if (baseUrl.startsWith("/") && typeof window !== "undefined") {
314
+ url = window.location.origin + baseUrl;
315
+ }
316
+ url = url + "/auth/login";
317
+ const response = await fetch(url, {
318
+ method: "POST",
319
+ headers: {
320
+ "Content-Type": "application/json"
321
+ },
322
+ body: JSON.stringify({ email, password })
323
+ });
324
+ if (!response.ok) {
325
+ try {
326
+ const errorData = await response.json();
327
+ const errorMessage = errorData && errorData.message ? String(errorData.message) : response.statusText;
328
+ throw new PlaycademyError(errorMessage);
329
+ } catch (error) {
330
+ console.error("[SDK] Failed to parse error response JSON, using status text instead:", error);
331
+ throw new PlaycademyError(response.statusText);
332
+ }
333
+ }
334
+ return response.json();
335
+ }
336
+ }
337
+
338
+ // src/runtime.ts
339
+ async function initFromWindow() {
340
+ if (typeof window === "undefined") {
341
+ throw new Error("initFromWindow must run in a browser context");
342
+ }
343
+ const preloaded = window.PLAYCADEMY;
344
+ const config = preloaded?.token ? preloaded : await new Promise((resolve) => bus.on("PLAYCADEMY_INIT" /* INIT */, resolve));
345
+ const client = new PlaycademyClient({
346
+ baseUrl: config.baseUrl,
347
+ token: config.token,
348
+ gameId: config.gameId
349
+ });
350
+ bus.on("PLAYCADEMY_TOKEN_REFRESH" /* TOKEN_REFRESH */, ({ token }) => client.setToken(token));
351
+ bus.emit("PLAYCADEMY_READY" /* READY */, undefined);
352
+ if (import.meta.env?.MODE === "development") {
353
+ window.PLAYCADEMY_CLIENT = client;
354
+ }
355
+ return client;
356
+ }
357
+ export {
358
+ initFromWindow,
359
+ bus,
360
+ PlaycademyError,
361
+ PlaycademyClient,
362
+ BusEvents
363
+ };
@@ -0,0 +1,43 @@
1
+ import type { User, InventoryItemWithReward, Game, DeveloperKey, DeveloperStatusResponse, MapElement, Reward, InsertReward, ManifestV1, UpdateReward } from '@playcademy/types';
2
+ export interface ClientConfig {
3
+ baseUrl: string;
4
+ token?: string;
5
+ gameId?: string;
6
+ }
7
+ export interface ClientEvents {
8
+ authChange: {
9
+ token: string | null;
10
+ };
11
+ inventoryChange: {
12
+ rewardId: string;
13
+ delta: number;
14
+ newTotal: number;
15
+ };
16
+ }
17
+ export type GameContextPayload = {
18
+ token: string;
19
+ baseUrl: string;
20
+ gameId: string;
21
+ };
22
+ export type EventListeners = {
23
+ [E in keyof ClientEvents]?: Array<(payload: ClientEvents[E]) => void>;
24
+ };
25
+ export type GameWithManifest = Game & {
26
+ manifest: ManifestV1;
27
+ };
28
+ export type DeveloperStatusValue = DeveloperStatusResponse['status'];
29
+ export type GameState = Record<string, unknown>;
30
+ export type LoginResponse = {
31
+ token: string;
32
+ };
33
+ export type GameTokenResponse = {
34
+ token: string;
35
+ exp: number;
36
+ };
37
+ export type StartSessionResponse = {
38
+ sessionId: string;
39
+ };
40
+ export type InventoryMutationResponse = {
41
+ newTotal: number;
42
+ };
43
+ export type { User, InventoryItemWithReward, Game, ManifestV1, DeveloperKey, DeveloperStatusResponse, MapElement, Reward, InsertReward, UpdateReward, };
package/dist/types.js ADDED
File without changes
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@playcademy/sdk",
3
3
  "type": "module",
4
- "version": "0.0.1-beta.5",
4
+ "version": "0.0.1-beta.6",
5
5
  "exports": {
6
6
  ".": {
7
7
  "import": "./dist/runtime.js",
@@ -14,6 +14,9 @@
14
14
  "types": "./dist/types.d.ts"
15
15
  }
16
16
  },
17
+ "files": [
18
+ "dist"
19
+ ],
17
20
  "main": "dist/runtime.js",
18
21
  "module": "dist/runtime.js",
19
22
  "scripts": {