@playcademy/sdk 0.2.2 → 0.2.4

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/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import * as drizzle_orm_pg_core from 'drizzle-orm/pg-core';
2
- import * as _playcademy_timeback_types from '@playcademy/timeback/types';
3
2
  import { AUTH_PROVIDER_IDS } from '@playcademy/constants';
4
3
 
5
4
  /**
@@ -8,22 +7,146 @@ import { AUTH_PROVIDER_IDS } from '@playcademy/constants';
8
7
  declare class PlaycademyError extends Error {
9
8
  constructor(message: string);
10
9
  }
10
+ /**
11
+ * Error codes returned by the API.
12
+ * These map to specific error types and HTTP status codes.
13
+ */
14
+ type ApiErrorCode = 'BAD_REQUEST' | 'UNAUTHORIZED' | 'FORBIDDEN' | 'ACCESS_DENIED' | 'NOT_FOUND' | 'METHOD_NOT_ALLOWED' | 'CONFLICT' | 'ALREADY_EXISTS' | 'GONE' | 'PRECONDITION_FAILED' | 'PAYLOAD_TOO_LARGE' | 'VALIDATION_FAILED' | 'TOO_MANY_REQUESTS' | 'RATE_LIMITED' | 'EXPIRED' | 'INTERNAL' | 'INTERNAL_ERROR' | 'NOT_IMPLEMENTED' | 'SERVICE_UNAVAILABLE' | 'TIMEOUT' | string;
15
+ /**
16
+ * Structure of error response bodies returned by API endpoints.
17
+ *
18
+ * @example
19
+ * ```json
20
+ * {
21
+ * "error": {
22
+ * "code": "NOT_FOUND",
23
+ * "message": "Item not found",
24
+ * "details": { "identifier": "abc123" }
25
+ * }
26
+ * }
27
+ * ```
28
+ */
29
+ interface ErrorResponseBody {
30
+ error?: {
31
+ code?: string;
32
+ message?: string;
33
+ details?: unknown;
34
+ };
35
+ }
36
+ /**
37
+ * API error thrown when a request fails.
38
+ *
39
+ * Contains structured error information from the API response:
40
+ * - `status` - HTTP status code (e.g., 404)
41
+ * - `code` - API error code (e.g., "NOT_FOUND")
42
+ * - `message` - Human-readable error message
43
+ * - `details` - Optional additional error context
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * try {
48
+ * await client.games.get('nonexistent')
49
+ * } catch (error) {
50
+ * if (error instanceof ApiError) {
51
+ * console.log(error.status) // 404
52
+ * console.log(error.code) // "NOT_FOUND"
53
+ * console.log(error.message) // "Game not found"
54
+ * console.log(error.details) // { identifier: "nonexistent" }
55
+ * }
56
+ * }
57
+ * ```
58
+ */
11
59
  declare class ApiError extends Error {
12
- status: number;
13
- details: unknown;
14
- constructor(status: number, message: string, details: unknown);
60
+ readonly status: number;
61
+ /**
62
+ * API error code (e.g., "NOT_FOUND", "VALIDATION_FAILED").
63
+ * Use this for programmatic error handling.
64
+ */
65
+ readonly code: ApiErrorCode;
66
+ /**
67
+ * Additional error context from the API.
68
+ * Structure varies by error type (e.g., validation errors include field details).
69
+ */
70
+ readonly details: unknown;
71
+ /**
72
+ * Raw response body for debugging.
73
+ * @internal
74
+ */
75
+ readonly rawBody: unknown;
76
+ constructor(
77
+ /** HTTP status code */
78
+ status: number,
79
+ /** API error code */
80
+ code: ApiErrorCode,
81
+ /** Human-readable error message */
82
+ message: string,
83
+ /** Additional error context */
84
+ details?: unknown,
85
+ /** Raw response body */
86
+ rawBody?: unknown);
87
+ /**
88
+ * Create an ApiError from an HTTP response.
89
+ * Parses the structured error response from the API.
90
+ *
91
+ * @internal
92
+ */
93
+ static fromResponse(status: number, statusText: string, body: unknown): ApiError;
94
+ /**
95
+ * Check if this is a specific error type.
96
+ *
97
+ * @example
98
+ * ```typescript
99
+ * if (error.is('NOT_FOUND')) {
100
+ * // Handle not found
101
+ * } else if (error.is('VALIDATION_FAILED')) {
102
+ * // Handle validation error
103
+ * }
104
+ * ```
105
+ */
106
+ is(code: ApiErrorCode): boolean;
107
+ /**
108
+ * Check if this is a client error (4xx).
109
+ */
110
+ isClientError(): boolean;
111
+ /**
112
+ * Check if this is a server error (5xx).
113
+ */
114
+ isServerError(): boolean;
115
+ /**
116
+ * Check if this error is retryable.
117
+ * Server errors and rate limits are typically retryable.
118
+ */
119
+ isRetryable(): boolean;
15
120
  }
16
121
  /**
17
- * Extract useful error information from an API error
18
- * Useful for displaying errors to users in a friendly way
122
+ * Extracted error information for display purposes.
19
123
  */
20
124
  interface ApiErrorInfo {
125
+ /** HTTP status code */
21
126
  status: number;
22
- statusText: string;
23
- error?: string;
24
- message?: string;
127
+ /** API error code */
128
+ code: ApiErrorCode;
129
+ /** Human-readable error message */
130
+ message: string;
131
+ /** Additional error context */
25
132
  details?: unknown;
26
133
  }
134
+ /**
135
+ * Extract useful error information from an API error.
136
+ * Useful for displaying errors to users in a friendly way.
137
+ *
138
+ * @example
139
+ * ```typescript
140
+ * try {
141
+ * await client.shop.purchase(itemId)
142
+ * } catch (error) {
143
+ * const info = extractApiErrorInfo(error)
144
+ * if (info) {
145
+ * showToast(`Error: ${info.message}`)
146
+ * }
147
+ * }
148
+ * ```
149
+ */
27
150
  declare function extractApiErrorInfo(error: unknown): ApiErrorInfo | null;
28
151
 
29
152
  /**
@@ -255,217 +378,151 @@ declare function parseOAuthState(state: string): {
255
378
  data?: Record<string, string>;
256
379
  };
257
380
 
258
- declare const users: drizzle_orm_pg_core.PgTableWithColumns<{
259
- name: "user";
260
- schema: undefined;
261
- columns: {
262
- id: drizzle_orm_pg_core.PgColumn<{
263
- name: "id";
264
- tableName: "user";
265
- dataType: "string";
266
- columnType: "PgText";
267
- data: string;
268
- driverParam: string;
269
- notNull: true;
270
- hasDefault: true;
271
- isPrimaryKey: true;
272
- isAutoincrement: false;
273
- hasRuntimeDefault: true;
274
- enumValues: [string, ...string[]];
275
- baseColumn: never;
276
- identity: undefined;
277
- generated: undefined;
278
- }, {}, {}>;
279
- name: drizzle_orm_pg_core.PgColumn<{
280
- name: "name";
281
- tableName: "user";
282
- dataType: "string";
283
- columnType: "PgText";
284
- data: string;
285
- driverParam: string;
286
- notNull: true;
287
- hasDefault: false;
288
- isPrimaryKey: false;
289
- isAutoincrement: false;
290
- hasRuntimeDefault: false;
291
- enumValues: [string, ...string[]];
292
- baseColumn: never;
293
- identity: undefined;
294
- generated: undefined;
295
- }, {}, {}>;
296
- username: drizzle_orm_pg_core.PgColumn<{
297
- name: "username";
298
- tableName: "user";
299
- dataType: "string";
300
- columnType: "PgText";
301
- data: string;
302
- driverParam: string;
303
- notNull: false;
304
- hasDefault: false;
305
- isPrimaryKey: false;
306
- isAutoincrement: false;
307
- hasRuntimeDefault: false;
308
- enumValues: [string, ...string[]];
309
- baseColumn: never;
310
- identity: undefined;
311
- generated: undefined;
312
- }, {}, {}>;
313
- email: drizzle_orm_pg_core.PgColumn<{
314
- name: "email";
315
- tableName: "user";
316
- dataType: "string";
317
- columnType: "PgText";
318
- data: string;
319
- driverParam: string;
320
- notNull: true;
321
- hasDefault: false;
322
- isPrimaryKey: false;
323
- isAutoincrement: false;
324
- hasRuntimeDefault: false;
325
- enumValues: [string, ...string[]];
326
- baseColumn: never;
327
- identity: undefined;
328
- generated: undefined;
329
- }, {}, {}>;
330
- timebackId: drizzle_orm_pg_core.PgColumn<{
331
- name: "timeback_id";
332
- tableName: "user";
333
- dataType: "string";
334
- columnType: "PgText";
335
- data: string;
336
- driverParam: string;
337
- notNull: false;
338
- hasDefault: false;
339
- isPrimaryKey: false;
340
- isAutoincrement: false;
341
- hasRuntimeDefault: false;
342
- enumValues: [string, ...string[]];
343
- baseColumn: never;
344
- identity: undefined;
345
- generated: undefined;
346
- }, {}, {}>;
347
- emailVerified: drizzle_orm_pg_core.PgColumn<{
348
- name: "email_verified";
349
- tableName: "user";
350
- dataType: "boolean";
351
- columnType: "PgBoolean";
352
- data: boolean;
353
- driverParam: boolean;
354
- notNull: true;
355
- hasDefault: true;
356
- isPrimaryKey: false;
357
- isAutoincrement: false;
358
- hasRuntimeDefault: false;
359
- enumValues: undefined;
360
- baseColumn: never;
361
- identity: undefined;
362
- generated: undefined;
363
- }, {}, {}>;
364
- image: drizzle_orm_pg_core.PgColumn<{
365
- name: "image";
366
- tableName: "user";
367
- dataType: "string";
368
- columnType: "PgText";
369
- data: string;
370
- driverParam: string;
371
- notNull: false;
372
- hasDefault: false;
373
- isPrimaryKey: false;
374
- isAutoincrement: false;
375
- hasRuntimeDefault: false;
376
- enumValues: [string, ...string[]];
377
- baseColumn: never;
378
- identity: undefined;
379
- generated: undefined;
380
- }, {}, {}>;
381
- role: drizzle_orm_pg_core.PgColumn<{
382
- name: "role";
383
- tableName: "user";
384
- dataType: "string";
385
- columnType: "PgEnumColumn";
386
- data: "admin" | "player" | "developer";
387
- driverParam: string;
388
- notNull: true;
389
- hasDefault: true;
390
- isPrimaryKey: false;
391
- isAutoincrement: false;
392
- hasRuntimeDefault: false;
393
- enumValues: ["admin", "player", "developer"];
394
- baseColumn: never;
395
- identity: undefined;
396
- generated: undefined;
397
- }, {}, {}>;
398
- developerStatus: drizzle_orm_pg_core.PgColumn<{
399
- name: "developer_status";
400
- tableName: "user";
401
- dataType: "string";
402
- columnType: "PgEnumColumn";
403
- data: "none" | "pending" | "approved";
404
- driverParam: string;
405
- notNull: true;
406
- hasDefault: true;
407
- isPrimaryKey: false;
408
- isAutoincrement: false;
409
- hasRuntimeDefault: false;
410
- enumValues: ["none", "pending", "approved"];
411
- baseColumn: never;
412
- identity: undefined;
413
- generated: undefined;
414
- }, {}, {}>;
415
- characterCreated: drizzle_orm_pg_core.PgColumn<{
416
- name: "character_created";
417
- tableName: "user";
418
- dataType: "boolean";
419
- columnType: "PgBoolean";
420
- data: boolean;
421
- driverParam: boolean;
422
- notNull: true;
423
- hasDefault: true;
424
- isPrimaryKey: false;
425
- isAutoincrement: false;
426
- hasRuntimeDefault: false;
427
- enumValues: undefined;
428
- baseColumn: never;
429
- identity: undefined;
430
- generated: undefined;
431
- }, {}, {}>;
432
- createdAt: drizzle_orm_pg_core.PgColumn<{
433
- name: "created_at";
434
- tableName: "user";
435
- dataType: "date";
436
- columnType: "PgTimestamp";
437
- data: Date;
438
- driverParam: string;
439
- notNull: true;
440
- hasDefault: false;
441
- isPrimaryKey: false;
442
- isAutoincrement: false;
443
- hasRuntimeDefault: false;
444
- enumValues: undefined;
445
- baseColumn: never;
446
- identity: undefined;
447
- generated: undefined;
448
- }, {}, {}>;
449
- updatedAt: drizzle_orm_pg_core.PgColumn<{
450
- name: "updated_at";
451
- tableName: "user";
452
- dataType: "date";
453
- columnType: "PgTimestamp";
454
- data: Date;
455
- driverParam: string;
456
- notNull: true;
457
- hasDefault: false;
458
- isPrimaryKey: false;
459
- isAutoincrement: false;
460
- hasRuntimeDefault: false;
461
- enumValues: undefined;
462
- baseColumn: never;
463
- identity: undefined;
464
- generated: undefined;
465
- }, {}, {}>;
466
- };
467
- dialect: "pg";
468
- }>;
381
+ /** Permitted HTTP verbs */
382
+ type Method = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
383
+
384
+ /**
385
+ * User Types
386
+ *
387
+ * Enums, DTOs and API response types. Database row types are in @playcademy/data/types.
388
+ *
389
+ * @module types/user
390
+ */
391
+ type UserRoleEnumType = 'admin' | 'player' | 'developer';
392
+ type DeveloperStatusEnumType = 'none' | 'pending' | 'approved';
393
+ type TimebackUserRole = 'administrator' | 'aide' | 'guardian' | 'parent' | 'proctor' | 'relative' | 'student' | 'teacher';
394
+ type TimebackOrgType = 'department' | 'school' | 'district' | 'local' | 'state' | 'national';
395
+ interface UserEnrollment {
396
+ gameId?: string;
397
+ courseId: string;
398
+ grade: number;
399
+ subject: string;
400
+ orgId?: string;
401
+ }
402
+ interface UserOrganization {
403
+ id: string;
404
+ name: string | null;
405
+ type: TimebackOrgType | string;
406
+ isPrimary: boolean;
407
+ }
408
+ interface TimebackStudentProfile {
409
+ role: TimebackUserRole;
410
+ organizations: UserOrganization[];
411
+ }
412
+ interface UserTimebackData extends TimebackStudentProfile {
413
+ id: string;
414
+ enrollments: UserEnrollment[];
415
+ }
416
+ /**
417
+ * OpenID Connect UserInfo claims (NOT a database row).
418
+ */
419
+ interface UserInfo {
420
+ sub: string;
421
+ email: string;
422
+ name: string | null;
423
+ email_verified?: boolean;
424
+ given_name?: string;
425
+ family_name?: string;
426
+ issuer?: string;
427
+ lti_roles?: unknown;
428
+ lti_context?: unknown;
429
+ lti_resource_link?: unknown;
430
+ timeback_id?: string;
431
+ }
432
+ /**
433
+ * Authenticated user for API responses.
434
+ * Differs from UserRow: omits timebackId, adds hasTimebackAccount and timeback.
435
+ */
436
+ interface AuthenticatedUser {
437
+ id: string;
438
+ email: string;
439
+ emailVerified: boolean;
440
+ name: string | null;
441
+ image: string | null;
442
+ username: string | null;
443
+ role: UserRoleEnumType;
444
+ developerStatus: DeveloperStatusEnumType;
445
+ characterCreated: boolean;
446
+ createdAt: Date;
447
+ updatedAt: Date;
448
+ hasTimebackAccount: boolean;
449
+ timeback?: UserTimebackData;
450
+ }
451
+
452
+ /**
453
+ * Valid Caliper subject values.
454
+ * Matches OneRoster subjects, with "None" as a Caliper-specific fallback.
455
+ */
456
+ type CaliperSubject = 'Reading' | 'Language' | 'Vocabulary' | 'Social Studies' | 'Writing' | 'Science' | 'FastMath' | 'Math' | 'None';
457
+
458
+ /**
459
+ * TimeBack Client SDK DTOs
460
+ *
461
+ * Data transfer objects for the TimeBack client SDK including
462
+ * progress tracking, session management, and activity completion.
463
+ *
464
+ * Note: TimebackClientConfig lives in @playcademy/timeback as it's
465
+ * SDK configuration, not a DTO.
466
+ *
467
+ * @module types/timeback/client
468
+ */
469
+
470
+ /**
471
+ * Activity data for ending an activity
472
+ */
473
+ interface ActivityData {
474
+ /** Unique activity identifier (required) */
475
+ activityId: string;
476
+ /** Grade level for this activity (required for multi-grade course routing) */
477
+ grade: number;
478
+ /** Subject area (required for multi-grade course routing) */
479
+ subject: CaliperSubject;
480
+ /** Activity display name (optional) */
481
+ activityName?: string;
482
+ /** Course identifier (auto-filled from config if not provided) */
483
+ courseId?: string;
484
+ /** Course display name (auto-filled from config if not provided) */
485
+ courseName?: string;
486
+ /** Student email address (optional) */
487
+ studentEmail?: string;
488
+ /** Application name for Caliper events (defaults to 'Game') */
489
+ appName?: string;
490
+ /** Sensor URL for Caliper events (defaults to baseUrl) */
491
+ sensorUrl?: string;
492
+ }
493
+ /**
494
+ * Score data with optional XP override for ending an activity
495
+ */
496
+ interface EndActivityScoreData {
497
+ /** Number of questions answered correctly */
498
+ correctQuestions: number;
499
+ /** Total number of questions */
500
+ totalQuestions: number;
501
+ /** Optional XP override - bypasses automatic XP calculation */
502
+ xpAwarded?: number;
503
+ /** Number of learning units mastered */
504
+ masteredUnits?: number;
505
+ }
506
+
507
+ /**
508
+ * TimeBack API Request/Response Types
509
+ *
510
+ * Types for TimeBack API endpoints including XP tracking,
511
+ * setup, verification, and activity completion.
512
+ *
513
+ * @module types/timeback/api
514
+ */
515
+
516
+ interface EndActivityResponse {
517
+ status: 'ok';
518
+ courseId: string;
519
+ xpAwarded: number;
520
+ masteredUnits?: number;
521
+ pctCompleteApp?: number;
522
+ scoreStatus?: string;
523
+ inProgress?: string;
524
+ }
525
+
469
526
  declare const items: drizzle_orm_pg_core.PgTableWithColumns<{
470
527
  name: "items";
471
528
  schema: undefined;
@@ -560,7 +617,7 @@ declare const items: drizzle_orm_pg_core.PgTableWithColumns<{
560
617
  tableName: "items";
561
618
  dataType: "string";
562
619
  columnType: "PgEnumColumn";
563
- data: "currency" | "badge" | "trophy" | "collectible" | "consumable" | "unlock" | "upgrade" | "accessory" | "other";
620
+ data: "accessory" | "badge" | "collectible" | "consumable" | "currency" | "other" | "trophy" | "unlock" | "upgrade";
564
621
  driverParam: string;
565
622
  notNull: true;
566
623
  hasDefault: true;
@@ -735,108 +792,13 @@ declare const inventoryItems: drizzle_orm_pg_core.PgTableWithColumns<{
735
792
  };
736
793
  dialect: "pg";
737
794
  }>;
738
- type Item = typeof items.$inferSelect;
739
- type InventoryItem = typeof inventoryItems.$inferSelect;
740
795
 
741
- type User = typeof users.$inferSelect;
742
- /**
743
- * TimeBack enrollment information for a game.
744
- */
745
- type UserEnrollment = {
746
- gameId?: string;
747
- courseId: string;
748
- grade: number;
749
- subject: string;
750
- orgId?: string;
751
- };
752
- /**
753
- * TimeBack user role (matches OneRoster spec).
754
- */
755
- type TimebackUserRole = 'administrator' | 'aide' | 'guardian' | 'parent' | 'proctor' | 'relative' | 'student' | 'teacher';
756
- /**
757
- * Organization type (matches OneRoster spec).
758
- */
759
- type TimebackOrgType = 'department' | 'school' | 'district' | 'local' | 'state' | 'national';
760
- /**
761
- * TimeBack organization data for a user.
762
- * Represents schools, districts, or other educational organizations.
763
- */
764
- type UserOrganization = {
765
- /** Organization ID (OneRoster sourcedId) */
766
- id: string;
767
- /** Organization name */
768
- name: string | null;
769
- /** Organization type (school, district, etc.) */
770
- type: TimebackOrgType | string;
771
- /** Whether this is the user's primary organization */
772
- isPrimary: boolean;
773
- };
774
- /**
775
- * TimeBack student profile (role + organizations).
776
- * Subset of UserTimebackData returned by OneRoster API.
777
- */
778
- type TimebackStudentProfile = {
779
- /** User's primary role in TimeBack (student, parent, teacher, etc.) */
780
- role: TimebackUserRole;
781
- /** User's organizations (schools/districts) */
782
- organizations: UserOrganization[];
783
- };
784
- /**
785
- * TimeBack-related data for a user.
786
- */
787
- type UserTimebackData = TimebackStudentProfile & {
788
- /** User's TimeBack ID (sourcedId) */
789
- id: string;
790
- /** Course enrollments */
791
- enrollments: UserEnrollment[];
792
- };
793
- /**
794
- * User data with authentication provider information.
795
- * Returned by the /users/me endpoint with additional auth context.
796
- */
797
- type AuthenticatedUser = Omit<User, 'timebackId'> & {
798
- /** Whether the user authenticated via Timeback SSO */
799
- hasTimebackAccount: boolean;
800
- /** TimeBack data (id, role, enrollments, organizations) - only present if user has a timeback account */
801
- timeback?: UserTimebackData;
802
- };
803
- /**
804
- * Basic user information in the shape of the claims from identity providers
805
- */
806
- interface UserInfo {
807
- /** Unique user identifier (sub claim from JWT) */
808
- sub: string;
809
- /** User's email address */
810
- email: string;
811
- /** User's display name */
812
- name: string;
813
- /** Whether the email has been verified */
814
- email_verified: boolean;
815
- /** Optional given name (first name) */
816
- given_name?: string;
817
- /** Optional family name (last name) */
818
- family_name?: string;
819
- /** TimeBack student ID (if user has TimeBack integration) */
820
- timeback_id?: string;
821
- /** Additional user attributes from the identity provider */
822
- [key: string]: unknown;
823
- }
824
- type InventoryItemWithItem = Omit<InventoryItem, 'itemId'> & {
825
- item: Item;
826
- };
827
- type EndActivityResponse = {
828
- status: 'ok';
829
- courseId: string;
830
- xpAwarded: number;
831
- masteredUnits?: number;
832
- pctCompleteApp?: number;
833
- scoreStatus?: string;
834
- inProgress?: string;
796
+ type ItemRow = typeof items.$inferSelect;
797
+ type InventoryItemRow = typeof inventoryItems.$inferSelect;
798
+ type InventoryItemWithItem = InventoryItemRow & {
799
+ item: ItemRow;
835
800
  };
836
801
 
837
- /** Permitted HTTP verbs */
838
- type Method = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
839
-
840
802
  /**
841
803
  * Auto-initializes a PlaycademyClient with context from the environment.
842
804
  * Works in both iframe mode (production/development) and standalone mode (local dev).
@@ -1036,9 +998,6 @@ declare abstract class PlaycademyBaseClient {
1036
998
  * Initializes connection monitoring if enabled.
1037
999
  */
1038
1000
  private _initializeConnectionMonitor;
1039
- /**
1040
- * Initializes an internal game session for automatic session management.
1041
- */
1042
1001
  private _initializeInternalSession;
1043
1002
  /**
1044
1003
  * Current user data and inventory management.
@@ -1082,8 +1041,8 @@ declare class PlaycademyClient extends PlaycademyBaseClient {
1082
1041
  */
1083
1042
  runtime: {
1084
1043
  getGameToken: (gameId: string, options?: {
1085
- apply?: boolean;
1086
- }) => Promise<GameTokenResponse>;
1044
+ apply?: boolean | undefined;
1045
+ } | undefined) => Promise<GameTokenResponse>;
1087
1046
  exit: () => Promise<void>;
1088
1047
  onInit: (handler: (context: GameContextPayload) => void) => void;
1089
1048
  onTokenRefresh: (handler: (data: {
@@ -1107,7 +1066,7 @@ declare class PlaycademyClient extends PlaycademyBaseClient {
1107
1066
  getListenerCounts: () => Record<string, number>;
1108
1067
  assets: {
1109
1068
  url(pathOrStrings: string | TemplateStringsArray, ...values: unknown[]): string;
1110
- fetch: (path: string, options?: RequestInit) => Promise<Response>;
1069
+ fetch: (path: string, options?: RequestInit | undefined) => Promise<Response>;
1111
1070
  json: <T = unknown>(path: string) => Promise<T>;
1112
1071
  blob: (path: string) => Promise<Blob>;
1113
1072
  text: (path: string) => Promise<string>;
@@ -1130,10 +1089,10 @@ declare class PlaycademyClient extends PlaycademyBaseClient {
1130
1089
  */
1131
1090
  timeback: {
1132
1091
  readonly user: TimebackUser;
1133
- startActivity: (metadata: _playcademy_timeback_types.ActivityData) => void;
1092
+ startActivity: (metadata: ActivityData) => void;
1134
1093
  pauseActivity: () => void;
1135
1094
  resumeActivity: () => void;
1136
- endActivity: (data: _playcademy_timeback_types.EndActivityScoreData) => Promise<EndActivityResponse>;
1095
+ endActivity: (data: EndActivityScoreData) => Promise<EndActivityResponse>;
1137
1096
  };
1138
1097
  /**
1139
1098
  * Playcademy Credits (platform currency) management.
@@ -1150,7 +1109,7 @@ declare class PlaycademyClient extends PlaycademyBaseClient {
1150
1109
  * - `submit(gameId, score, metadata?)` - Record a game score
1151
1110
  */
1152
1111
  scores: {
1153
- submit: (gameId: string, score: number, metadata?: Record<string, unknown>) => Promise<ScoreSubmission>;
1112
+ submit: (gameId: string, score: number, metadata?: Record<string, unknown> | undefined) => Promise<ScoreSubmission>;
1154
1113
  };
1155
1114
  /**
1156
1115
  * Realtime multiplayer authentication.
@@ -1167,13 +1126,13 @@ declare class PlaycademyClient extends PlaycademyBaseClient {
1167
1126
  * - Routes are relative to your game's deployment (e.g., '/hello' → your-game.playcademy.gg/api/hello)
1168
1127
  */
1169
1128
  backend: {
1170
- get<T = unknown>(path: string, headers?: Record<string, string>): Promise<T>;
1171
- post<T = unknown>(path: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
1172
- put<T = unknown>(path: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
1173
- patch<T = unknown>(path: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
1174
- delete<T = unknown>(path: string, headers?: Record<string, string>): Promise<T>;
1175
- request<T = unknown>(path: string, method: Method, body?: unknown, headers?: Record<string, string>): Promise<T>;
1176
- download(path: string, method?: Method, body?: unknown, headers?: Record<string, string>): Promise<Response>;
1129
+ get<T = unknown>(path: string, headers?: Record<string, string> | undefined): Promise<T>;
1130
+ post<T = unknown>(path: string, body?: unknown, headers?: Record<string, string> | undefined): Promise<T>;
1131
+ put<T = unknown>(path: string, body?: unknown, headers?: Record<string, string> | undefined): Promise<T>;
1132
+ patch<T = unknown>(path: string, body?: unknown, headers?: Record<string, string> | undefined): Promise<T>;
1133
+ delete<T = unknown>(path: string, headers?: Record<string, string> | undefined): Promise<T>;
1134
+ request<T = unknown>(path: string, method: Method, body?: unknown, headers?: Record<string, string> | undefined): Promise<T>;
1135
+ download(path: string, method?: Method, body?: unknown, headers?: Record<string, string> | undefined): Promise<Response>;
1177
1136
  url(pathOrStrings: string | TemplateStringsArray, ...values: unknown[]): string;
1178
1137
  };
1179
1138
  /** Auto-initializes a PlaycademyClient with context from the environment */
@@ -1189,8 +1148,8 @@ declare class PlaycademyClient extends PlaycademyBaseClient {
1189
1148
  /**
1190
1149
  * Type definitions for the game timeback namespace.
1191
1150
  *
1192
- * Re-exports core types from @playcademy/data for SDK consumers,
1193
- * plus SDK-specific types like TimebackInitContext.
1151
+ * SDK-specific types like TimebackInitContext that wrap the core types
1152
+ * from @playcademy/types/user (which are re-exported via types/data.ts).
1194
1153
  */
1195
1154
 
1196
1155
  /**
@@ -1501,6 +1460,8 @@ type DevUploadEvent = {
1501
1460
  } | {
1502
1461
  type: 'finalizeStatus';
1503
1462
  message: string;
1463
+ } | {
1464
+ type: 'complete';
1504
1465
  } | {
1505
1466
  type: 'close';
1506
1467
  };
@@ -2248,4 +2209,4 @@ declare class PlaycademyMessaging {
2248
2209
  declare const messaging: PlaycademyMessaging;
2249
2210
 
2250
2211
  export { ApiError, ConnectionManager, ConnectionMonitor, MessageEvents, PlaycademyClient, PlaycademyError, extractApiErrorInfo, messaging };
2251
- export type { ApiErrorInfo, ConnectionMonitorConfig, ConnectionState, ConnectionStatePayload, DevUploadEvent, DevUploadHooks, DisconnectContext, DisconnectHandler, DisplayAlertPayload };
2212
+ export type { ApiErrorCode, ApiErrorInfo, ConnectionMonitorConfig, ConnectionState, ConnectionStatePayload, DevUploadEvent, DevUploadHooks, DisconnectContext, DisconnectHandler, DisplayAlertPayload, ErrorResponseBody };