@playcademy/sdk 0.15.1-beta.2 → 0.15.1-beta.3
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.js +2 -2
- package/dist/internal.d.ts +354 -7
- package/dist/internal.js +67 -22
- package/dist/server/edge.d.ts +36 -6
- package/dist/server/edge.js +1 -1
- package/dist/server.d.ts +36 -6
- package/dist/server.js +1 -1
- package/dist/types.d.ts +31 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -580,7 +580,7 @@ async function login(baseUrl, email, password) {
|
|
|
580
580
|
async function generateSecureRandomString(length) {
|
|
581
581
|
const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
|
|
582
582
|
const randomValues = new Uint8Array(length);
|
|
583
|
-
|
|
583
|
+
crypto.getRandomValues(randomValues);
|
|
584
584
|
return [...randomValues].map((byte) => charset[byte % charset.length]).join("");
|
|
585
585
|
}
|
|
586
586
|
|
|
@@ -2391,7 +2391,7 @@ async function request({
|
|
|
2391
2391
|
return rawText && rawText.length > 0 ? rawText : undefined;
|
|
2392
2392
|
}
|
|
2393
2393
|
// src/version.ts
|
|
2394
|
-
var SDK_VERSION = "0.15.1-beta.
|
|
2394
|
+
var SDK_VERSION = "0.15.1-beta.3";
|
|
2395
2395
|
|
|
2396
2396
|
// src/clients/base.ts
|
|
2397
2397
|
class PlaycademyBaseClient {
|
package/dist/internal.d.ts
CHANGED
|
@@ -5,8 +5,8 @@ import * as _playcademy_types from '@playcademy/types';
|
|
|
5
5
|
import { GameManifest, LocalDayContext } from '@playcademy/types';
|
|
6
6
|
export { AuthenticatedUser, DeveloperStatusEnumType, DeveloperStatusResponse, DeveloperStatusValue, GameCourseMetrics, GameLeaderboardEntry, GameManifest, GameMetricComparisonKind, GameMetricComparisonMetric, GameMetricComparisonRow, GameMetricComparisonRowStatus, GameMetricsProxyResponse, GameMetricsResponse, GameMetricsUnsupportedReason, GamePlatform, GameRunMetrics, GameRunMetricsComparison, GameRunMetricsComparisonStatus, GameRunMetricsComparisonSummary, GameTimebackIntegration, GameType, GameUser, LeaderboardEntry, LeaderboardOptions, LeaderboardTimeframe, LocalDayContext, LocalDaySource, ManifestV1, ManifestV2, ManifestVersions, PopulateStudentResponse, UserEnrollment, UserInfo, UserOrganization, UserRank, UserRankResponse, UserRoleEnumType, UserScore, UserTimebackData } from '@playcademy/types';
|
|
7
7
|
import * as drizzle_orm_pg_core from 'drizzle-orm/pg-core';
|
|
8
|
-
import { z } from 'zod';
|
|
9
8
|
import { DomainValidationRecords } from '@playcademy/types/game';
|
|
9
|
+
import { z } from 'zod';
|
|
10
10
|
import { TimebackUserRole, UserEnrollment, UserOrganization, UserInfo } from '@playcademy/types/user';
|
|
11
11
|
import { AUTH_PROVIDER_IDS } from '@playcademy/constants';
|
|
12
12
|
|
|
@@ -1336,6 +1336,277 @@ declare const gameMembers: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
1336
1336
|
};
|
|
1337
1337
|
dialect: 'pg';
|
|
1338
1338
|
}>;
|
|
1339
|
+
/**
|
|
1340
|
+
* Standalone login accounts for a game's developer dashboard.
|
|
1341
|
+
*
|
|
1342
|
+
* These are NOT platform accounts — dashboard users authenticate directly
|
|
1343
|
+
* against their game's dashboard worker with credentials stored here. The
|
|
1344
|
+
* platform owns this table entirely; game devs manage rows only through the
|
|
1345
|
+
* dashboard endpoints (gated by game membership). `platformUserId` is
|
|
1346
|
+
* reserved for a future "sign in with Playcademy" grant path.
|
|
1347
|
+
*/
|
|
1348
|
+
declare const gameDashboardUsers: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
1349
|
+
name: "game_dashboard_users";
|
|
1350
|
+
schema: undefined;
|
|
1351
|
+
columns: {
|
|
1352
|
+
id: drizzle_orm_pg_core.PgColumn<{
|
|
1353
|
+
name: "id";
|
|
1354
|
+
tableName: "game_dashboard_users";
|
|
1355
|
+
dataType: "string";
|
|
1356
|
+
columnType: "PgUUID";
|
|
1357
|
+
data: string;
|
|
1358
|
+
driverParam: string;
|
|
1359
|
+
notNull: true;
|
|
1360
|
+
hasDefault: true;
|
|
1361
|
+
isPrimaryKey: true;
|
|
1362
|
+
isAutoincrement: false;
|
|
1363
|
+
hasRuntimeDefault: false;
|
|
1364
|
+
enumValues: undefined;
|
|
1365
|
+
baseColumn: never;
|
|
1366
|
+
identity: undefined;
|
|
1367
|
+
generated: undefined;
|
|
1368
|
+
}, {}, {}>;
|
|
1369
|
+
gameId: drizzle_orm_pg_core.PgColumn<{
|
|
1370
|
+
name: "game_id";
|
|
1371
|
+
tableName: "game_dashboard_users";
|
|
1372
|
+
dataType: "string";
|
|
1373
|
+
columnType: "PgUUID";
|
|
1374
|
+
data: string;
|
|
1375
|
+
driverParam: string;
|
|
1376
|
+
notNull: true;
|
|
1377
|
+
hasDefault: false;
|
|
1378
|
+
isPrimaryKey: false;
|
|
1379
|
+
isAutoincrement: false;
|
|
1380
|
+
hasRuntimeDefault: false;
|
|
1381
|
+
enumValues: undefined;
|
|
1382
|
+
baseColumn: never;
|
|
1383
|
+
identity: undefined;
|
|
1384
|
+
generated: undefined;
|
|
1385
|
+
}, {}, {}>;
|
|
1386
|
+
email: drizzle_orm_pg_core.PgColumn<{
|
|
1387
|
+
name: "email";
|
|
1388
|
+
tableName: "game_dashboard_users";
|
|
1389
|
+
dataType: "string";
|
|
1390
|
+
columnType: "PgText";
|
|
1391
|
+
data: string;
|
|
1392
|
+
driverParam: string;
|
|
1393
|
+
notNull: true;
|
|
1394
|
+
hasDefault: false;
|
|
1395
|
+
isPrimaryKey: false;
|
|
1396
|
+
isAutoincrement: false;
|
|
1397
|
+
hasRuntimeDefault: false;
|
|
1398
|
+
enumValues: [string, ...string[]];
|
|
1399
|
+
baseColumn: never;
|
|
1400
|
+
identity: undefined;
|
|
1401
|
+
generated: undefined;
|
|
1402
|
+
}, {}, {}>;
|
|
1403
|
+
displayName: drizzle_orm_pg_core.PgColumn<{
|
|
1404
|
+
name: "display_name";
|
|
1405
|
+
tableName: "game_dashboard_users";
|
|
1406
|
+
dataType: "string";
|
|
1407
|
+
columnType: "PgText";
|
|
1408
|
+
data: string;
|
|
1409
|
+
driverParam: string;
|
|
1410
|
+
notNull: false;
|
|
1411
|
+
hasDefault: false;
|
|
1412
|
+
isPrimaryKey: false;
|
|
1413
|
+
isAutoincrement: false;
|
|
1414
|
+
hasRuntimeDefault: false;
|
|
1415
|
+
enumValues: [string, ...string[]];
|
|
1416
|
+
baseColumn: never;
|
|
1417
|
+
identity: undefined;
|
|
1418
|
+
generated: undefined;
|
|
1419
|
+
}, {}, {}>;
|
|
1420
|
+
role: drizzle_orm_pg_core.PgColumn<{
|
|
1421
|
+
name: "role";
|
|
1422
|
+
tableName: "game_dashboard_users";
|
|
1423
|
+
dataType: "string";
|
|
1424
|
+
columnType: "PgEnumColumn";
|
|
1425
|
+
data: "admin" | "viewer";
|
|
1426
|
+
driverParam: string;
|
|
1427
|
+
notNull: true;
|
|
1428
|
+
hasDefault: true;
|
|
1429
|
+
isPrimaryKey: false;
|
|
1430
|
+
isAutoincrement: false;
|
|
1431
|
+
hasRuntimeDefault: false;
|
|
1432
|
+
enumValues: ["admin", "viewer"];
|
|
1433
|
+
baseColumn: never;
|
|
1434
|
+
identity: undefined;
|
|
1435
|
+
generated: undefined;
|
|
1436
|
+
}, {}, {}>;
|
|
1437
|
+
passwordHash: drizzle_orm_pg_core.PgColumn<{
|
|
1438
|
+
name: "password_hash";
|
|
1439
|
+
tableName: "game_dashboard_users";
|
|
1440
|
+
dataType: "string";
|
|
1441
|
+
columnType: "PgText";
|
|
1442
|
+
data: string;
|
|
1443
|
+
driverParam: string;
|
|
1444
|
+
notNull: false;
|
|
1445
|
+
hasDefault: false;
|
|
1446
|
+
isPrimaryKey: false;
|
|
1447
|
+
isAutoincrement: false;
|
|
1448
|
+
hasRuntimeDefault: false;
|
|
1449
|
+
enumValues: [string, ...string[]];
|
|
1450
|
+
baseColumn: never;
|
|
1451
|
+
identity: undefined;
|
|
1452
|
+
generated: undefined;
|
|
1453
|
+
}, {}, {}>;
|
|
1454
|
+
inviteTokenHash: drizzle_orm_pg_core.PgColumn<{
|
|
1455
|
+
name: "invite_token_hash";
|
|
1456
|
+
tableName: "game_dashboard_users";
|
|
1457
|
+
dataType: "string";
|
|
1458
|
+
columnType: "PgText";
|
|
1459
|
+
data: string;
|
|
1460
|
+
driverParam: string;
|
|
1461
|
+
notNull: false;
|
|
1462
|
+
hasDefault: false;
|
|
1463
|
+
isPrimaryKey: false;
|
|
1464
|
+
isAutoincrement: false;
|
|
1465
|
+
hasRuntimeDefault: false;
|
|
1466
|
+
enumValues: [string, ...string[]];
|
|
1467
|
+
baseColumn: never;
|
|
1468
|
+
identity: undefined;
|
|
1469
|
+
generated: undefined;
|
|
1470
|
+
}, {}, {}>;
|
|
1471
|
+
inviteExpiresAt: drizzle_orm_pg_core.PgColumn<{
|
|
1472
|
+
name: "invite_expires_at";
|
|
1473
|
+
tableName: "game_dashboard_users";
|
|
1474
|
+
dataType: "date";
|
|
1475
|
+
columnType: "PgTimestamp";
|
|
1476
|
+
data: Date;
|
|
1477
|
+
driverParam: string;
|
|
1478
|
+
notNull: false;
|
|
1479
|
+
hasDefault: false;
|
|
1480
|
+
isPrimaryKey: false;
|
|
1481
|
+
isAutoincrement: false;
|
|
1482
|
+
hasRuntimeDefault: false;
|
|
1483
|
+
enumValues: undefined;
|
|
1484
|
+
baseColumn: never;
|
|
1485
|
+
identity: undefined;
|
|
1486
|
+
generated: undefined;
|
|
1487
|
+
}, {}, {}>;
|
|
1488
|
+
resetTokenHash: drizzle_orm_pg_core.PgColumn<{
|
|
1489
|
+
name: "reset_token_hash";
|
|
1490
|
+
tableName: "game_dashboard_users";
|
|
1491
|
+
dataType: "string";
|
|
1492
|
+
columnType: "PgText";
|
|
1493
|
+
data: string;
|
|
1494
|
+
driverParam: string;
|
|
1495
|
+
notNull: false;
|
|
1496
|
+
hasDefault: false;
|
|
1497
|
+
isPrimaryKey: false;
|
|
1498
|
+
isAutoincrement: false;
|
|
1499
|
+
hasRuntimeDefault: false;
|
|
1500
|
+
enumValues: [string, ...string[]];
|
|
1501
|
+
baseColumn: never;
|
|
1502
|
+
identity: undefined;
|
|
1503
|
+
generated: undefined;
|
|
1504
|
+
}, {}, {}>;
|
|
1505
|
+
resetExpiresAt: drizzle_orm_pg_core.PgColumn<{
|
|
1506
|
+
name: "reset_expires_at";
|
|
1507
|
+
tableName: "game_dashboard_users";
|
|
1508
|
+
dataType: "date";
|
|
1509
|
+
columnType: "PgTimestamp";
|
|
1510
|
+
data: Date;
|
|
1511
|
+
driverParam: string;
|
|
1512
|
+
notNull: false;
|
|
1513
|
+
hasDefault: false;
|
|
1514
|
+
isPrimaryKey: false;
|
|
1515
|
+
isAutoincrement: false;
|
|
1516
|
+
hasRuntimeDefault: false;
|
|
1517
|
+
enumValues: undefined;
|
|
1518
|
+
baseColumn: never;
|
|
1519
|
+
identity: undefined;
|
|
1520
|
+
generated: undefined;
|
|
1521
|
+
}, {}, {}>;
|
|
1522
|
+
failedLoginAttempts: drizzle_orm_pg_core.PgColumn<{
|
|
1523
|
+
name: "failed_login_attempts";
|
|
1524
|
+
tableName: "game_dashboard_users";
|
|
1525
|
+
dataType: "number";
|
|
1526
|
+
columnType: "PgInteger";
|
|
1527
|
+
data: number;
|
|
1528
|
+
driverParam: string | number;
|
|
1529
|
+
notNull: true;
|
|
1530
|
+
hasDefault: true;
|
|
1531
|
+
isPrimaryKey: false;
|
|
1532
|
+
isAutoincrement: false;
|
|
1533
|
+
hasRuntimeDefault: false;
|
|
1534
|
+
enumValues: undefined;
|
|
1535
|
+
baseColumn: never;
|
|
1536
|
+
identity: undefined;
|
|
1537
|
+
generated: undefined;
|
|
1538
|
+
}, {}, {}>;
|
|
1539
|
+
lastFailedLoginAt: drizzle_orm_pg_core.PgColumn<{
|
|
1540
|
+
name: "last_failed_login_at";
|
|
1541
|
+
tableName: "game_dashboard_users";
|
|
1542
|
+
dataType: "date";
|
|
1543
|
+
columnType: "PgTimestamp";
|
|
1544
|
+
data: Date;
|
|
1545
|
+
driverParam: string;
|
|
1546
|
+
notNull: false;
|
|
1547
|
+
hasDefault: false;
|
|
1548
|
+
isPrimaryKey: false;
|
|
1549
|
+
isAutoincrement: false;
|
|
1550
|
+
hasRuntimeDefault: false;
|
|
1551
|
+
enumValues: undefined;
|
|
1552
|
+
baseColumn: never;
|
|
1553
|
+
identity: undefined;
|
|
1554
|
+
generated: undefined;
|
|
1555
|
+
}, {}, {}>;
|
|
1556
|
+
platformUserId: drizzle_orm_pg_core.PgColumn<{
|
|
1557
|
+
name: "platform_user_id";
|
|
1558
|
+
tableName: "game_dashboard_users";
|
|
1559
|
+
dataType: "string";
|
|
1560
|
+
columnType: "PgText";
|
|
1561
|
+
data: string;
|
|
1562
|
+
driverParam: string;
|
|
1563
|
+
notNull: false;
|
|
1564
|
+
hasDefault: false;
|
|
1565
|
+
isPrimaryKey: false;
|
|
1566
|
+
isAutoincrement: false;
|
|
1567
|
+
hasRuntimeDefault: false;
|
|
1568
|
+
enumValues: [string, ...string[]];
|
|
1569
|
+
baseColumn: never;
|
|
1570
|
+
identity: undefined;
|
|
1571
|
+
generated: undefined;
|
|
1572
|
+
}, {}, {}>;
|
|
1573
|
+
createdAt: drizzle_orm_pg_core.PgColumn<{
|
|
1574
|
+
name: "created_at";
|
|
1575
|
+
tableName: "game_dashboard_users";
|
|
1576
|
+
dataType: "date";
|
|
1577
|
+
columnType: "PgTimestamp";
|
|
1578
|
+
data: Date;
|
|
1579
|
+
driverParam: string;
|
|
1580
|
+
notNull: true;
|
|
1581
|
+
hasDefault: true;
|
|
1582
|
+
isPrimaryKey: false;
|
|
1583
|
+
isAutoincrement: false;
|
|
1584
|
+
hasRuntimeDefault: false;
|
|
1585
|
+
enumValues: undefined;
|
|
1586
|
+
baseColumn: never;
|
|
1587
|
+
identity: undefined;
|
|
1588
|
+
generated: undefined;
|
|
1589
|
+
}, {}, {}>;
|
|
1590
|
+
updatedAt: drizzle_orm_pg_core.PgColumn<{
|
|
1591
|
+
name: "updated_at";
|
|
1592
|
+
tableName: "game_dashboard_users";
|
|
1593
|
+
dataType: "date";
|
|
1594
|
+
columnType: "PgTimestamp";
|
|
1595
|
+
data: Date;
|
|
1596
|
+
driverParam: string;
|
|
1597
|
+
notNull: true;
|
|
1598
|
+
hasDefault: true;
|
|
1599
|
+
isPrimaryKey: false;
|
|
1600
|
+
isAutoincrement: false;
|
|
1601
|
+
hasRuntimeDefault: false;
|
|
1602
|
+
enumValues: undefined;
|
|
1603
|
+
baseColumn: never;
|
|
1604
|
+
identity: undefined;
|
|
1605
|
+
generated: undefined;
|
|
1606
|
+
}, {}, {}>;
|
|
1607
|
+
};
|
|
1608
|
+
dialect: 'pg';
|
|
1609
|
+
}>;
|
|
1339
1610
|
/**
|
|
1340
1611
|
* Custom hostnames table
|
|
1341
1612
|
*
|
|
@@ -1621,6 +1892,19 @@ declare const UpdateGameMemberRoleSchema: z.ZodObject<{
|
|
|
1621
1892
|
}, {
|
|
1622
1893
|
role: "collaborator" | "owner";
|
|
1623
1894
|
}>;
|
|
1895
|
+
declare const AddGameDashboardUserSchema: z.ZodObject<{
|
|
1896
|
+
email: z.ZodString;
|
|
1897
|
+
displayName: z.ZodOptional<z.ZodString>;
|
|
1898
|
+
role: z.ZodDefault<z.ZodOptional<z.ZodEnum<["admin", "viewer"]>>>;
|
|
1899
|
+
}, "strict", z.ZodTypeAny, {
|
|
1900
|
+
email: string;
|
|
1901
|
+
displayName?: string | undefined;
|
|
1902
|
+
role: "admin" | "viewer";
|
|
1903
|
+
}, {
|
|
1904
|
+
email: string;
|
|
1905
|
+
displayName?: string | undefined;
|
|
1906
|
+
role?: "admin" | "viewer" | undefined;
|
|
1907
|
+
}>;
|
|
1624
1908
|
|
|
1625
1909
|
type GameRow = typeof games.$inferSelect;
|
|
1626
1910
|
type BaseGame = Omit<GameRow, 'gameType' | 'deploymentUrl' | 'externalUrl'>;
|
|
@@ -1650,12 +1934,25 @@ interface GameMemberSearchResult {
|
|
|
1650
1934
|
email: string;
|
|
1651
1935
|
image: string | null;
|
|
1652
1936
|
}
|
|
1937
|
+
type GameDashboardUserRow = typeof gameDashboardUsers.$inferSelect;
|
|
1938
|
+
/** Dashboard user shape safe to return from the API (no credential material) */
|
|
1939
|
+
type GameDashboardUserSummary = Pick<GameDashboardUserRow, 'id' | 'gameId' | 'email' | 'displayName' | 'role' | 'platformUserId' | 'createdAt' | 'updatedAt'> & {
|
|
1940
|
+
/** Whether the invite is still pending (password not yet set) */
|
|
1941
|
+
pending: boolean;
|
|
1942
|
+
};
|
|
1943
|
+
/** A freshly-minted credential link: an invite for pending users, a password reset for active ones */
|
|
1944
|
+
interface GameDashboardCredentialLink {
|
|
1945
|
+
user: GameDashboardUserSummary;
|
|
1946
|
+
token: string;
|
|
1947
|
+
kind: 'invite' | 'reset';
|
|
1948
|
+
}
|
|
1653
1949
|
type GameCustomHostnameRow = typeof gameCustomHostnames.$inferSelect;
|
|
1654
1950
|
|
|
1655
1951
|
type UpsertGameMetadataInput = z.infer<typeof UpsertGameMetadataSchema>;
|
|
1656
1952
|
type PatchGameMetadataInput = z.infer<typeof PatchGameMetadataSchema>;
|
|
1657
1953
|
type AddGameMemberInput = z.infer<typeof AddGameMemberSchema>;
|
|
1658
1954
|
type UpdateGameMemberRoleInput = z.infer<typeof UpdateGameMemberRoleSchema>;
|
|
1955
|
+
type AddGameDashboardUserInput = z.input<typeof AddGameDashboardUserSchema>;
|
|
1659
1956
|
|
|
1660
1957
|
type UserRow = typeof users.$inferSelect;
|
|
1661
1958
|
|
|
@@ -2730,6 +3027,34 @@ interface IntegrationsConfig {
|
|
|
2730
3027
|
/** Queues (optional) */
|
|
2731
3028
|
queues?: Record<string, QueueConfig | boolean>;
|
|
2732
3029
|
}
|
|
3030
|
+
/**
|
|
3031
|
+
* Developer dashboard configuration.
|
|
3032
|
+
*
|
|
3033
|
+
* The dashboard is a separate app in the game's repo, deployed as a sibling
|
|
3034
|
+
* worker with `playcademy dashboard deploy`. Auth and session plumbing are
|
|
3035
|
+
* platform-managed; the dashboard app itself is just a static SPA build.
|
|
3036
|
+
*/
|
|
3037
|
+
interface DashboardConfig {
|
|
3038
|
+
/** Path to the dashboard app, relative to the config file (default: './dashboard') */
|
|
3039
|
+
directory?: string;
|
|
3040
|
+
/** Build command run inside the dashboard directory (defaults to the workspace package manager's build script) */
|
|
3041
|
+
buildCommand?: string[];
|
|
3042
|
+
/** Path to the dashboard build output, relative to the dashboard directory (default: 'dist') */
|
|
3043
|
+
buildPath?: string;
|
|
3044
|
+
/** Colors for the platform-managed login/invite page (hex); unset uses the built-in palette */
|
|
3045
|
+
theme?: DashboardThemeConfig;
|
|
3046
|
+
}
|
|
3047
|
+
/**
|
|
3048
|
+
* Login-page theming. Two seeds — a primary (button, focus, background
|
|
3049
|
+
* wash) and a secondary accent — the platform derives the full palette
|
|
3050
|
+
* from. Either may be omitted to keep that half of the built-in palette.
|
|
3051
|
+
*/
|
|
3052
|
+
interface DashboardThemeConfig {
|
|
3053
|
+
/** Primary color as a hex string, e.g. '#e0245e' */
|
|
3054
|
+
primary?: string;
|
|
3055
|
+
/** Secondary/accent color as a hex string, e.g. '#ffd166' */
|
|
3056
|
+
secondary?: string;
|
|
3057
|
+
}
|
|
2733
3058
|
/**
|
|
2734
3059
|
* Unified Playcademy configuration
|
|
2735
3060
|
* Used for playcademy.config.{js,json}
|
|
@@ -2751,6 +3076,8 @@ interface PlaycademyConfig {
|
|
|
2751
3076
|
externalUrl?: string;
|
|
2752
3077
|
/** Game platform */
|
|
2753
3078
|
platform?: 'web' | 'godot';
|
|
3079
|
+
/** Developer dashboard app (optional) — `true` uses defaults */
|
|
3080
|
+
dashboard?: DashboardConfig | boolean;
|
|
2754
3081
|
/** Integrations (database, custom routes, external services) */
|
|
2755
3082
|
integrations?: IntegrationsConfig;
|
|
2756
3083
|
}
|
|
@@ -2824,10 +3151,10 @@ interface PlaycademyServerClientState {
|
|
|
2824
3151
|
courseId?: string;
|
|
2825
3152
|
}
|
|
2826
3153
|
/**
|
|
2827
|
-
* Resource bindings for
|
|
3154
|
+
* Resource bindings for worker deployment
|
|
2828
3155
|
* Provider-agnostic abstraction for cloud resources
|
|
2829
3156
|
*/
|
|
2830
|
-
interface
|
|
3157
|
+
interface WorkerResourceBindings {
|
|
2831
3158
|
/** SQL database — `true` to request, server names it (maps to D1 on Cloudflare) */
|
|
2832
3159
|
database?: boolean | string[];
|
|
2833
3160
|
/** Key-value store — `true` to request, server names it (maps to KV on Cloudflare) */
|
|
@@ -2838,15 +3165,15 @@ interface BackendResourceBindings {
|
|
|
2838
3165
|
queues?: Record<string, QueueConfig | boolean>;
|
|
2839
3166
|
}
|
|
2840
3167
|
/**
|
|
2841
|
-
*
|
|
3168
|
+
* Worker deployment bundle for uploading to Playcademy platform
|
|
2842
3169
|
*/
|
|
2843
|
-
interface
|
|
3170
|
+
interface WorkerDeploymentBundle {
|
|
2844
3171
|
/** Bundled JavaScript code ready for deployment */
|
|
2845
3172
|
code: string;
|
|
2846
3173
|
/** Game configuration */
|
|
2847
3174
|
config: PlaycademyConfig;
|
|
2848
3175
|
/** Optional resource bindings (database, storage, etc.) */
|
|
2849
|
-
bindings?:
|
|
3176
|
+
bindings?: WorkerResourceBindings;
|
|
2850
3177
|
/** Optional schema information for database setup */
|
|
2851
3178
|
schema?: SchemaInfo;
|
|
2852
3179
|
/** Cloudflare Worker compatibility date (YYYY-MM-DD) */
|
|
@@ -2996,7 +3323,7 @@ declare class PlaycademyInternalClient extends PlaycademyBaseClient {
|
|
|
2996
3323
|
deploy: (slug: string, options: {
|
|
2997
3324
|
metadata?: UpsertGameMetadataInput;
|
|
2998
3325
|
file?: File | Blob | null;
|
|
2999
|
-
|
|
3326
|
+
worker?: WorkerDeploymentBundle;
|
|
3000
3327
|
hooks?: DevUploadHooks;
|
|
3001
3328
|
}) => Promise<Game>;
|
|
3002
3329
|
seed: (slug: string, code: string, environment?: 'local' | 'staging' | 'production', secrets?: Record<string, string>) => Promise<_playcademy_types.SeedResponse>;
|
|
@@ -3007,6 +3334,26 @@ declare class PlaycademyInternalClient extends PlaycademyBaseClient {
|
|
|
3007
3334
|
list: (slug: string) => Promise<string[]>;
|
|
3008
3335
|
delete: (slug: string, key: string) => Promise<void>;
|
|
3009
3336
|
};
|
|
3337
|
+
dashboard: {
|
|
3338
|
+
deploy: (slug: string, options: {
|
|
3339
|
+
file: File | Blob;
|
|
3340
|
+
worker: WorkerDeploymentBundle;
|
|
3341
|
+
hooks?: DevUploadHooks;
|
|
3342
|
+
}) => Promise<{
|
|
3343
|
+
url: string;
|
|
3344
|
+
deploymentId: string;
|
|
3345
|
+
}>;
|
|
3346
|
+
remove: (slug: string) => Promise<void>;
|
|
3347
|
+
users: {
|
|
3348
|
+
list: (slug: string) => Promise<GameDashboardUserSummary[]>;
|
|
3349
|
+
add: (slug: string, input: AddGameDashboardUserInput) => Promise<GameDashboardCredentialLink>;
|
|
3350
|
+
recover: (slug: string, userId: string) => Promise<GameDashboardCredentialLink>;
|
|
3351
|
+
remove: (slug: string, userId: string) => Promise<void>;
|
|
3352
|
+
};
|
|
3353
|
+
sessions: {
|
|
3354
|
+
revoke: (slug: string) => Promise<void>;
|
|
3355
|
+
};
|
|
3356
|
+
};
|
|
3010
3357
|
database: {
|
|
3011
3358
|
reset: (slug: string, schema?: {
|
|
3012
3359
|
sql: string;
|
package/dist/internal.js
CHANGED
|
@@ -580,7 +580,7 @@ async function login(baseUrl, email, password) {
|
|
|
580
580
|
async function generateSecureRandomString(length) {
|
|
581
581
|
const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
|
|
582
582
|
const randomValues = new Uint8Array(length);
|
|
583
|
-
|
|
583
|
+
crypto.getRandomValues(randomValues);
|
|
584
584
|
return [...randomValues].map((byte) => charset[byte % charset.length]).join("");
|
|
585
585
|
}
|
|
586
586
|
|
|
@@ -2262,7 +2262,18 @@ class DeployPipeline {
|
|
|
2262
2262
|
}
|
|
2263
2263
|
return uploadToken;
|
|
2264
2264
|
}
|
|
2265
|
-
async
|
|
2265
|
+
async submitGame(args) {
|
|
2266
|
+
await this.submitAndPoll(args);
|
|
2267
|
+
return this.fetchGameWithRetry(args.slug);
|
|
2268
|
+
}
|
|
2269
|
+
async submitDashboard(args) {
|
|
2270
|
+
const result = await this.submitAndPoll({ ...args, target: "dashboard" });
|
|
2271
|
+
if (!result.deploymentId) {
|
|
2272
|
+
throw new Error("Deployment completed but no deployment ID was recorded");
|
|
2273
|
+
}
|
|
2274
|
+
return { url: result.url, deploymentId: result.deploymentId };
|
|
2275
|
+
}
|
|
2276
|
+
async submitAndPoll(args) {
|
|
2266
2277
|
const { requestBody } = await this.buildRequestBody(args);
|
|
2267
2278
|
const { slug, hooks } = args;
|
|
2268
2279
|
const job = await this.client["request"](`/games/${slug}/deploy`, "POST", { body: requestBody });
|
|
@@ -2270,44 +2281,50 @@ class DeployPipeline {
|
|
|
2270
2281
|
if (!completedJob.result?.url) {
|
|
2271
2282
|
throw new Error("Deployment completed but no deployment URL was recorded");
|
|
2272
2283
|
}
|
|
2273
|
-
return
|
|
2284
|
+
return {
|
|
2285
|
+
url: completedJob.result.url,
|
|
2286
|
+
deploymentId: completedJob.result.deploymentId ?? undefined
|
|
2287
|
+
};
|
|
2274
2288
|
}
|
|
2275
2289
|
async buildRequestBody(args) {
|
|
2276
2290
|
const game2 = await this.resolveGame(args.slug, args.game);
|
|
2277
2291
|
const requestBody = {};
|
|
2292
|
+
if (args.target) {
|
|
2293
|
+
requestBody.target = args.target;
|
|
2294
|
+
}
|
|
2278
2295
|
if (args.uploadToken) {
|
|
2279
2296
|
requestBody.uploadToken = args.uploadToken;
|
|
2280
2297
|
}
|
|
2281
2298
|
if (args.metadata) {
|
|
2282
2299
|
requestBody.metadata = args.metadata;
|
|
2283
2300
|
}
|
|
2284
|
-
if (!args.
|
|
2301
|
+
if (!args.worker) {
|
|
2285
2302
|
return { game: game2, requestBody };
|
|
2286
2303
|
}
|
|
2287
|
-
const
|
|
2288
|
-
config: args.
|
|
2289
|
-
...args.
|
|
2290
|
-
...args.
|
|
2291
|
-
...args.
|
|
2292
|
-
...args.
|
|
2304
|
+
const workerFields = {
|
|
2305
|
+
config: args.worker.config,
|
|
2306
|
+
...args.worker.bindings ? { bindings: args.worker.bindings } : {},
|
|
2307
|
+
...args.worker.schema ? { schema: args.worker.schema } : {},
|
|
2308
|
+
...args.worker.compatibilityDate ? { compatibilityDate: args.worker.compatibilityDate } : {},
|
|
2309
|
+
...args.worker.compatibilityFlags?.length ? { compatibilityFlags: args.worker.compatibilityFlags } : {}
|
|
2293
2310
|
};
|
|
2294
2311
|
const inlineBody = {
|
|
2295
2312
|
...requestBody,
|
|
2296
|
-
...
|
|
2297
|
-
code: args.
|
|
2313
|
+
...workerFields,
|
|
2314
|
+
code: args.worker.code
|
|
2298
2315
|
};
|
|
2299
2316
|
if (this.serializedSize(inlineBody) <= DeployPipeline.MAX_INLINE_REQUEST_BYTES) {
|
|
2300
2317
|
return { game: game2, requestBody: inlineBody };
|
|
2301
2318
|
}
|
|
2302
2319
|
const skeletonBody = {
|
|
2303
2320
|
...requestBody,
|
|
2304
|
-
...
|
|
2321
|
+
...workerFields,
|
|
2305
2322
|
codeUploadToken: "________placeholder________"
|
|
2306
2323
|
};
|
|
2307
2324
|
if (this.serializedSize(skeletonBody) > DeployPipeline.MAX_INLINE_REQUEST_BYTES) {
|
|
2308
|
-
throw new Error("Deploy request is too large even after uploading
|
|
2325
|
+
throw new Error("Deploy request is too large even after uploading worker code");
|
|
2309
2326
|
}
|
|
2310
|
-
skeletonBody.codeUploadToken = await this.uploadCode(game2.id, args.
|
|
2327
|
+
skeletonBody.codeUploadToken = await this.uploadCode(game2.id, args.worker.code);
|
|
2311
2328
|
return { game: game2, requestBody: skeletonBody };
|
|
2312
2329
|
}
|
|
2313
2330
|
serializedSize(body) {
|
|
@@ -2325,7 +2342,7 @@ class DeployPipeline {
|
|
|
2325
2342
|
});
|
|
2326
2343
|
if (!res.ok) {
|
|
2327
2344
|
const detail = await parseS3Error(res);
|
|
2328
|
-
throw new Error(`
|
|
2345
|
+
throw new Error(`Worker code upload failed: ${detail}`);
|
|
2329
2346
|
}
|
|
2330
2347
|
return uploadToken;
|
|
2331
2348
|
}
|
|
@@ -2431,25 +2448,25 @@ function createDevNamespace(client) {
|
|
|
2431
2448
|
games: {
|
|
2432
2449
|
list: () => client["request"]("/games/accessible", "GET"),
|
|
2433
2450
|
deploy: async (slug, options) => {
|
|
2434
|
-
const { metadata, file,
|
|
2451
|
+
const { metadata, file, worker, hooks } = options;
|
|
2435
2452
|
hooks?.onEvent?.({ type: "init" });
|
|
2436
2453
|
let game2;
|
|
2437
2454
|
if (metadata) {
|
|
2438
2455
|
game2 = await client["request"](`/games/${slug}`, "PUT", {
|
|
2439
2456
|
body: metadata
|
|
2440
2457
|
});
|
|
2441
|
-
if (metadata.gameType === "external" && !file && !
|
|
2458
|
+
if (metadata.gameType === "external" && !file && !worker) {
|
|
2442
2459
|
return game2;
|
|
2443
2460
|
}
|
|
2444
2461
|
}
|
|
2445
2462
|
const uploadToken = file ? await deploy.uploadFile(file, game2?.id || slug, hooks) : undefined;
|
|
2446
|
-
if (uploadToken ||
|
|
2447
|
-
return deploy.
|
|
2463
|
+
if (uploadToken || worker) {
|
|
2464
|
+
return deploy.submitGame({ slug, game: game2, uploadToken, metadata, worker, hooks });
|
|
2448
2465
|
}
|
|
2449
2466
|
if (game2) {
|
|
2450
2467
|
return game2;
|
|
2451
2468
|
}
|
|
2452
|
-
throw new Error("No deployment actions specified (need metadata, file, or
|
|
2469
|
+
throw new Error("No deployment actions specified (need metadata, file, or worker)");
|
|
2453
2470
|
},
|
|
2454
2471
|
seed: async (slug, code, environment, secrets) => client["request"](`/games/${slug}/seed`, "POST", {
|
|
2455
2472
|
body: { code, environment, secrets }
|
|
@@ -2469,6 +2486,34 @@ function createDevNamespace(client) {
|
|
|
2469
2486
|
await client["request"](`/games/${slug}/secrets/${key}`, "DELETE");
|
|
2470
2487
|
}
|
|
2471
2488
|
},
|
|
2489
|
+
dashboard: {
|
|
2490
|
+
deploy: async (slug, options) => {
|
|
2491
|
+
const { file, worker, hooks } = options;
|
|
2492
|
+
hooks?.onEvent?.({ type: "init" });
|
|
2493
|
+
const game2 = await client["request"](`/games/${slug}`, "GET");
|
|
2494
|
+
const uploadToken = await deploy.uploadFile(file, game2.id, hooks);
|
|
2495
|
+
return deploy.submitDashboard({ slug, game: game2, uploadToken, worker, hooks });
|
|
2496
|
+
},
|
|
2497
|
+
remove: async (slug) => {
|
|
2498
|
+
await client["request"](`/games/${slug}/dashboard`, "DELETE");
|
|
2499
|
+
},
|
|
2500
|
+
users: {
|
|
2501
|
+
list: async (slug) => {
|
|
2502
|
+
const result = await client["request"](`/games/${slug}/dashboard/users`, "GET");
|
|
2503
|
+
return result.users;
|
|
2504
|
+
},
|
|
2505
|
+
add: async (slug, input) => client["request"](`/games/${slug}/dashboard/users`, "POST", { body: input }),
|
|
2506
|
+
recover: async (slug, userId) => client["request"](`/games/${slug}/dashboard/users/${userId}/recovery`, "POST"),
|
|
2507
|
+
remove: async (slug, userId) => {
|
|
2508
|
+
await client["request"](`/games/${slug}/dashboard/users/${userId}`, "DELETE");
|
|
2509
|
+
}
|
|
2510
|
+
},
|
|
2511
|
+
sessions: {
|
|
2512
|
+
revoke: async (slug) => {
|
|
2513
|
+
await client["request"](`/games/${slug}/dashboard/sessions/revoke`, "POST");
|
|
2514
|
+
}
|
|
2515
|
+
}
|
|
2516
|
+
},
|
|
2472
2517
|
database: {
|
|
2473
2518
|
reset: async (slug, schema) => client["request"](`/games/${slug}/database/reset`, "POST", {
|
|
2474
2519
|
body: { schema }
|
|
@@ -3094,7 +3139,7 @@ async function request({
|
|
|
3094
3139
|
return rawText && rawText.length > 0 ? rawText : undefined;
|
|
3095
3140
|
}
|
|
3096
3141
|
// src/version.ts
|
|
3097
|
-
var SDK_VERSION = "0.15.1-beta.
|
|
3142
|
+
var SDK_VERSION = "0.15.1-beta.3";
|
|
3098
3143
|
|
|
3099
3144
|
// src/clients/base.ts
|
|
3100
3145
|
class PlaycademyBaseClient {
|
package/dist/server/edge.d.ts
CHANGED
|
@@ -113,6 +113,34 @@ interface IntegrationsConfig {
|
|
|
113
113
|
/** Queues (optional) */
|
|
114
114
|
queues?: Record<string, QueueConfig | boolean>;
|
|
115
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* Developer dashboard configuration.
|
|
118
|
+
*
|
|
119
|
+
* The dashboard is a separate app in the game's repo, deployed as a sibling
|
|
120
|
+
* worker with `playcademy dashboard deploy`. Auth and session plumbing are
|
|
121
|
+
* platform-managed; the dashboard app itself is just a static SPA build.
|
|
122
|
+
*/
|
|
123
|
+
interface DashboardConfig {
|
|
124
|
+
/** Path to the dashboard app, relative to the config file (default: './dashboard') */
|
|
125
|
+
directory?: string;
|
|
126
|
+
/** Build command run inside the dashboard directory (defaults to the workspace package manager's build script) */
|
|
127
|
+
buildCommand?: string[];
|
|
128
|
+
/** Path to the dashboard build output, relative to the dashboard directory (default: 'dist') */
|
|
129
|
+
buildPath?: string;
|
|
130
|
+
/** Colors for the platform-managed login/invite page (hex); unset uses the built-in palette */
|
|
131
|
+
theme?: DashboardThemeConfig;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Login-page theming. Two seeds — a primary (button, focus, background
|
|
135
|
+
* wash) and a secondary accent — the platform derives the full palette
|
|
136
|
+
* from. Either may be omitted to keep that half of the built-in palette.
|
|
137
|
+
*/
|
|
138
|
+
interface DashboardThemeConfig {
|
|
139
|
+
/** Primary color as a hex string, e.g. '#e0245e' */
|
|
140
|
+
primary?: string;
|
|
141
|
+
/** Secondary/accent color as a hex string, e.g. '#ffd166' */
|
|
142
|
+
secondary?: string;
|
|
143
|
+
}
|
|
116
144
|
/**
|
|
117
145
|
* Unified Playcademy configuration
|
|
118
146
|
* Used for playcademy.config.{js,json}
|
|
@@ -134,6 +162,8 @@ interface PlaycademyConfig {
|
|
|
134
162
|
externalUrl?: string;
|
|
135
163
|
/** Game platform */
|
|
136
164
|
platform?: 'web' | 'godot';
|
|
165
|
+
/** Developer dashboard app (optional) — `true` uses defaults */
|
|
166
|
+
dashboard?: DashboardConfig | boolean;
|
|
137
167
|
/** Integrations (database, custom routes, external services) */
|
|
138
168
|
integrations?: IntegrationsConfig;
|
|
139
169
|
}
|
|
@@ -214,10 +244,10 @@ interface RequestContext {
|
|
|
214
244
|
}
|
|
215
245
|
|
|
216
246
|
/**
|
|
217
|
-
* Resource bindings for
|
|
247
|
+
* Resource bindings for worker deployment
|
|
218
248
|
* Provider-agnostic abstraction for cloud resources
|
|
219
249
|
*/
|
|
220
|
-
interface
|
|
250
|
+
interface WorkerResourceBindings {
|
|
221
251
|
/** SQL database — `true` to request, server names it (maps to D1 on Cloudflare) */
|
|
222
252
|
database?: boolean | string[];
|
|
223
253
|
/** Key-value store — `true` to request, server names it (maps to KV on Cloudflare) */
|
|
@@ -228,15 +258,15 @@ interface BackendResourceBindings {
|
|
|
228
258
|
queues?: Record<string, QueueConfig | boolean>;
|
|
229
259
|
}
|
|
230
260
|
/**
|
|
231
|
-
*
|
|
261
|
+
* Worker deployment bundle for uploading to Playcademy platform
|
|
232
262
|
*/
|
|
233
|
-
interface
|
|
263
|
+
interface WorkerDeploymentBundle {
|
|
234
264
|
/** Bundled JavaScript code ready for deployment */
|
|
235
265
|
code: string;
|
|
236
266
|
/** Game configuration */
|
|
237
267
|
config: PlaycademyConfig;
|
|
238
268
|
/** Optional resource bindings (database, storage, etc.) */
|
|
239
|
-
bindings?:
|
|
269
|
+
bindings?: WorkerResourceBindings;
|
|
240
270
|
/** Optional schema information for database setup */
|
|
241
271
|
schema?: SchemaInfo;
|
|
242
272
|
/** Cloudflare Worker compatibility date (YYYY-MM-DD) */
|
|
@@ -395,4 +425,4 @@ declare function verifyGameToken(gameToken: string, options?: {
|
|
|
395
425
|
}): Promise<VerifyGameTokenResponse>;
|
|
396
426
|
|
|
397
427
|
export { PlaycademyClient, verifyGameToken };
|
|
398
|
-
export type {
|
|
428
|
+
export type { IntegrationsConfig, PlaycademyConfig, PlaycademyServerClientConfig, PlaycademyServerClientState, QueueConfig, RequestContext, TimebackBaseConfig, TimebackCourseConfigWithOverrides, TimebackIntegrationConfig, WorkerDeploymentBundle, WorkerResourceBindings };
|
package/dist/server/edge.js
CHANGED
package/dist/server.d.ts
CHANGED
|
@@ -113,6 +113,34 @@ interface IntegrationsConfig {
|
|
|
113
113
|
/** Queues (optional) */
|
|
114
114
|
queues?: Record<string, QueueConfig | boolean>;
|
|
115
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* Developer dashboard configuration.
|
|
118
|
+
*
|
|
119
|
+
* The dashboard is a separate app in the game's repo, deployed as a sibling
|
|
120
|
+
* worker with `playcademy dashboard deploy`. Auth and session plumbing are
|
|
121
|
+
* platform-managed; the dashboard app itself is just a static SPA build.
|
|
122
|
+
*/
|
|
123
|
+
interface DashboardConfig {
|
|
124
|
+
/** Path to the dashboard app, relative to the config file (default: './dashboard') */
|
|
125
|
+
directory?: string;
|
|
126
|
+
/** Build command run inside the dashboard directory (defaults to the workspace package manager's build script) */
|
|
127
|
+
buildCommand?: string[];
|
|
128
|
+
/** Path to the dashboard build output, relative to the dashboard directory (default: 'dist') */
|
|
129
|
+
buildPath?: string;
|
|
130
|
+
/** Colors for the platform-managed login/invite page (hex); unset uses the built-in palette */
|
|
131
|
+
theme?: DashboardThemeConfig;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Login-page theming. Two seeds — a primary (button, focus, background
|
|
135
|
+
* wash) and a secondary accent — the platform derives the full palette
|
|
136
|
+
* from. Either may be omitted to keep that half of the built-in palette.
|
|
137
|
+
*/
|
|
138
|
+
interface DashboardThemeConfig {
|
|
139
|
+
/** Primary color as a hex string, e.g. '#e0245e' */
|
|
140
|
+
primary?: string;
|
|
141
|
+
/** Secondary/accent color as a hex string, e.g. '#ffd166' */
|
|
142
|
+
secondary?: string;
|
|
143
|
+
}
|
|
116
144
|
/**
|
|
117
145
|
* Unified Playcademy configuration
|
|
118
146
|
* Used for playcademy.config.{js,json}
|
|
@@ -134,6 +162,8 @@ interface PlaycademyConfig {
|
|
|
134
162
|
externalUrl?: string;
|
|
135
163
|
/** Game platform */
|
|
136
164
|
platform?: 'web' | 'godot';
|
|
165
|
+
/** Developer dashboard app (optional) — `true` uses defaults */
|
|
166
|
+
dashboard?: DashboardConfig | boolean;
|
|
137
167
|
/** Integrations (database, custom routes, external services) */
|
|
138
168
|
integrations?: IntegrationsConfig;
|
|
139
169
|
}
|
|
@@ -214,10 +244,10 @@ interface RequestContext {
|
|
|
214
244
|
}
|
|
215
245
|
|
|
216
246
|
/**
|
|
217
|
-
* Resource bindings for
|
|
247
|
+
* Resource bindings for worker deployment
|
|
218
248
|
* Provider-agnostic abstraction for cloud resources
|
|
219
249
|
*/
|
|
220
|
-
interface
|
|
250
|
+
interface WorkerResourceBindings {
|
|
221
251
|
/** SQL database — `true` to request, server names it (maps to D1 on Cloudflare) */
|
|
222
252
|
database?: boolean | string[];
|
|
223
253
|
/** Key-value store — `true` to request, server names it (maps to KV on Cloudflare) */
|
|
@@ -228,15 +258,15 @@ interface BackendResourceBindings {
|
|
|
228
258
|
queues?: Record<string, QueueConfig | boolean>;
|
|
229
259
|
}
|
|
230
260
|
/**
|
|
231
|
-
*
|
|
261
|
+
* Worker deployment bundle for uploading to Playcademy platform
|
|
232
262
|
*/
|
|
233
|
-
interface
|
|
263
|
+
interface WorkerDeploymentBundle {
|
|
234
264
|
/** Bundled JavaScript code ready for deployment */
|
|
235
265
|
code: string;
|
|
236
266
|
/** Game configuration */
|
|
237
267
|
config: PlaycademyConfig;
|
|
238
268
|
/** Optional resource bindings (database, storage, etc.) */
|
|
239
|
-
bindings?:
|
|
269
|
+
bindings?: WorkerResourceBindings;
|
|
240
270
|
/** Optional schema information for database setup */
|
|
241
271
|
schema?: SchemaInfo;
|
|
242
272
|
/** Cloudflare Worker compatibility date (YYYY-MM-DD) */
|
|
@@ -441,4 +471,4 @@ declare function verifyGameToken(gameToken: string, options?: {
|
|
|
441
471
|
}): Promise<VerifyGameTokenResponse>;
|
|
442
472
|
|
|
443
473
|
export { PlaycademyClient, verifyGameToken };
|
|
444
|
-
export type {
|
|
474
|
+
export type { DashboardConfig, IntegrationsConfig, PlaycademyConfig, PlaycademyServerClientConfig, PlaycademyServerClientState, QueueConfig, TimebackBaseConfig, TimebackCourseConfigWithOverrides, TimebackIntegrationConfig, WorkerDeploymentBundle, WorkerResourceBindings };
|
package/dist/server.js
CHANGED
package/dist/types.d.ts
CHANGED
|
@@ -6,8 +6,8 @@ export { QtiTestQuestionRef, QtiTestQuestionsResponse } from '@playcademy/types/
|
|
|
6
6
|
import { TimebackUserRole, UserEnrollment, UserOrganization, UserInfo } from '@playcademy/types/user';
|
|
7
7
|
import { AUTH_PROVIDER_IDS } from '@playcademy/constants';
|
|
8
8
|
import * as drizzle_orm_pg_core from 'drizzle-orm/pg-core';
|
|
9
|
-
import { z } from 'zod';
|
|
10
9
|
import { DomainValidationRecords } from '@playcademy/types/game';
|
|
10
|
+
import { z } from 'zod';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* OAuth 2.0 implementation for the Playcademy SDK
|
|
@@ -307,6 +307,34 @@ interface IntegrationsConfig {
|
|
|
307
307
|
/** Queues (optional) */
|
|
308
308
|
queues?: Record<string, QueueConfig | boolean>;
|
|
309
309
|
}
|
|
310
|
+
/**
|
|
311
|
+
* Developer dashboard configuration.
|
|
312
|
+
*
|
|
313
|
+
* The dashboard is a separate app in the game's repo, deployed as a sibling
|
|
314
|
+
* worker with `playcademy dashboard deploy`. Auth and session plumbing are
|
|
315
|
+
* platform-managed; the dashboard app itself is just a static SPA build.
|
|
316
|
+
*/
|
|
317
|
+
interface DashboardConfig {
|
|
318
|
+
/** Path to the dashboard app, relative to the config file (default: './dashboard') */
|
|
319
|
+
directory?: string;
|
|
320
|
+
/** Build command run inside the dashboard directory (defaults to the workspace package manager's build script) */
|
|
321
|
+
buildCommand?: string[];
|
|
322
|
+
/** Path to the dashboard build output, relative to the dashboard directory (default: 'dist') */
|
|
323
|
+
buildPath?: string;
|
|
324
|
+
/** Colors for the platform-managed login/invite page (hex); unset uses the built-in palette */
|
|
325
|
+
theme?: DashboardThemeConfig;
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Login-page theming. Two seeds — a primary (button, focus, background
|
|
329
|
+
* wash) and a secondary accent — the platform derives the full palette
|
|
330
|
+
* from. Either may be omitted to keep that half of the built-in palette.
|
|
331
|
+
*/
|
|
332
|
+
interface DashboardThemeConfig {
|
|
333
|
+
/** Primary color as a hex string, e.g. '#e0245e' */
|
|
334
|
+
primary?: string;
|
|
335
|
+
/** Secondary/accent color as a hex string, e.g. '#ffd166' */
|
|
336
|
+
secondary?: string;
|
|
337
|
+
}
|
|
310
338
|
/**
|
|
311
339
|
* Unified Playcademy configuration
|
|
312
340
|
* Used for playcademy.config.{js,json}
|
|
@@ -328,6 +356,8 @@ interface PlaycademyConfig {
|
|
|
328
356
|
externalUrl?: string;
|
|
329
357
|
/** Game platform */
|
|
330
358
|
platform?: 'web' | 'godot';
|
|
359
|
+
/** Developer dashboard app (optional) — `true` uses defaults */
|
|
360
|
+
dashboard?: DashboardConfig | boolean;
|
|
331
361
|
/** Integrations (database, custom routes, external services) */
|
|
332
362
|
integrations?: IntegrationsConfig;
|
|
333
363
|
}
|