@playcademy/sdk 0.3.7-beta.1 → 0.3.7-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +12 -0
- package/dist/internal.d.ts +2 -0
- package/dist/internal.js +14 -1
- package/dist/server/edge.d.ts +701 -0
- package/dist/server/edge.js +323 -0
- package/dist/server.d.ts +61 -46
- package/dist/server.js +222 -189
- package/package.json +6 -1
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __export = (target, all) => {
|
|
3
|
+
for (var name in all)
|
|
4
|
+
__defProp(target, name, {
|
|
5
|
+
get: all[name],
|
|
6
|
+
enumerable: true,
|
|
7
|
+
configurable: true,
|
|
8
|
+
set: (newValue) => all[name] = () => newValue
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
12
|
+
|
|
13
|
+
// src/core/guards.ts
|
|
14
|
+
var VALID_GRADES = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
|
|
15
|
+
var VALID_SUBJECTS = [
|
|
16
|
+
"Reading",
|
|
17
|
+
"Language",
|
|
18
|
+
"Vocabulary",
|
|
19
|
+
"Social Studies",
|
|
20
|
+
"Writing",
|
|
21
|
+
"Science",
|
|
22
|
+
"FastMath",
|
|
23
|
+
"Math",
|
|
24
|
+
"None"
|
|
25
|
+
];
|
|
26
|
+
function isValidGrade(value) {
|
|
27
|
+
return typeof value === "number" && Number.isInteger(value) && VALID_GRADES.includes(value);
|
|
28
|
+
}
|
|
29
|
+
function isValidSubject(value) {
|
|
30
|
+
return typeof value === "string" && VALID_SUBJECTS.includes(value);
|
|
31
|
+
}
|
|
32
|
+
// src/server/namespaces/timeback.ts
|
|
33
|
+
function createTimebackNamespace(client) {
|
|
34
|
+
function enrichActivityData(data) {
|
|
35
|
+
return {
|
|
36
|
+
...data,
|
|
37
|
+
appName: data.appName || client.config.name
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
endActivity: async (studentId, payload) => {
|
|
42
|
+
if (!isValidGrade(payload.activityData.grade)) {
|
|
43
|
+
throw new Error("activityData.grade must be a valid grade level (-1 to 13)");
|
|
44
|
+
}
|
|
45
|
+
if (!isValidSubject(payload.activityData.subject)) {
|
|
46
|
+
throw new Error("activityData.subject must be a valid subject");
|
|
47
|
+
}
|
|
48
|
+
const enrichedActivityData = enrichActivityData(payload.activityData);
|
|
49
|
+
return client["request"]("/api/timeback/end-activity", "POST", {
|
|
50
|
+
gameId: client.gameId,
|
|
51
|
+
studentId,
|
|
52
|
+
activityData: enrichedActivityData,
|
|
53
|
+
scoreData: payload.scoreData,
|
|
54
|
+
timingData: payload.timingData,
|
|
55
|
+
xpEarned: payload.xpEarned,
|
|
56
|
+
masteredUnits: payload.masteredUnits,
|
|
57
|
+
extensions: payload.extensions
|
|
58
|
+
});
|
|
59
|
+
},
|
|
60
|
+
getStudentXp: async (studentId, options) => {
|
|
61
|
+
const hasGrade = options?.grade !== undefined;
|
|
62
|
+
const hasSubject = options?.subject !== undefined;
|
|
63
|
+
if (hasGrade !== hasSubject) {
|
|
64
|
+
throw new Error("Both grade and subject must be provided together");
|
|
65
|
+
}
|
|
66
|
+
if (hasGrade && !isValidGrade(options.grade)) {
|
|
67
|
+
throw new Error(`Invalid grade: ${options.grade}. Valid grades: ${VALID_GRADES.join(", ")}`);
|
|
68
|
+
}
|
|
69
|
+
if (hasSubject && !isValidSubject(options.subject)) {
|
|
70
|
+
throw new Error(`Invalid subject: ${options.subject}. Valid subjects: ${VALID_SUBJECTS.join(", ")}`);
|
|
71
|
+
}
|
|
72
|
+
const params = new URLSearchParams;
|
|
73
|
+
params.set("gameId", client.gameId);
|
|
74
|
+
if (options?.grade !== undefined) {
|
|
75
|
+
params.set("grade", String(options.grade));
|
|
76
|
+
}
|
|
77
|
+
if (options?.subject) {
|
|
78
|
+
params.set("subject", options.subject);
|
|
79
|
+
}
|
|
80
|
+
if (options?.include?.length) {
|
|
81
|
+
params.set("include", options.include.join(","));
|
|
82
|
+
}
|
|
83
|
+
const queryString = params.toString();
|
|
84
|
+
const endpoint = `/api/timeback/student-xp/${studentId}?${queryString}`;
|
|
85
|
+
return client["request"](endpoint, "GET");
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
// src/core/errors.ts
|
|
90
|
+
class PlaycademyError extends Error {
|
|
91
|
+
constructor(message) {
|
|
92
|
+
super(message);
|
|
93
|
+
this.name = "PlaycademyError";
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
class ApiError extends Error {
|
|
98
|
+
code;
|
|
99
|
+
details;
|
|
100
|
+
rawBody;
|
|
101
|
+
status;
|
|
102
|
+
constructor(status, code, message, details, rawBody) {
|
|
103
|
+
super(message);
|
|
104
|
+
this.name = "ApiError";
|
|
105
|
+
this.status = status;
|
|
106
|
+
this.code = code;
|
|
107
|
+
this.details = details;
|
|
108
|
+
this.rawBody = rawBody;
|
|
109
|
+
Object.setPrototypeOf(this, ApiError.prototype);
|
|
110
|
+
}
|
|
111
|
+
static fromResponse(status, statusText, body) {
|
|
112
|
+
if (body && typeof body === "object" && "error" in body) {
|
|
113
|
+
const errorBody = body;
|
|
114
|
+
const err = errorBody.error;
|
|
115
|
+
if (err && typeof err === "object") {
|
|
116
|
+
return new ApiError(status, err.code ?? statusCodeToErrorCode(status), err.message ?? statusText, err.details, body);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return new ApiError(status, statusCodeToErrorCode(status), statusText, undefined, body);
|
|
120
|
+
}
|
|
121
|
+
is(code) {
|
|
122
|
+
return this.code === code;
|
|
123
|
+
}
|
|
124
|
+
isClientError() {
|
|
125
|
+
return this.status >= 400 && this.status < 500;
|
|
126
|
+
}
|
|
127
|
+
isServerError() {
|
|
128
|
+
return this.status >= 500;
|
|
129
|
+
}
|
|
130
|
+
isRetryable() {
|
|
131
|
+
return this.isServerError() || this.code === "TOO_MANY_REQUESTS" || this.code === "RATE_LIMITED" || this.code === "TIMEOUT";
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
function statusCodeToErrorCode(status) {
|
|
135
|
+
switch (status) {
|
|
136
|
+
case 400: {
|
|
137
|
+
return "BAD_REQUEST";
|
|
138
|
+
}
|
|
139
|
+
case 401: {
|
|
140
|
+
return "UNAUTHORIZED";
|
|
141
|
+
}
|
|
142
|
+
case 403: {
|
|
143
|
+
return "FORBIDDEN";
|
|
144
|
+
}
|
|
145
|
+
case 404: {
|
|
146
|
+
return "NOT_FOUND";
|
|
147
|
+
}
|
|
148
|
+
case 405: {
|
|
149
|
+
return "METHOD_NOT_ALLOWED";
|
|
150
|
+
}
|
|
151
|
+
case 409: {
|
|
152
|
+
return "CONFLICT";
|
|
153
|
+
}
|
|
154
|
+
case 410: {
|
|
155
|
+
return "GONE";
|
|
156
|
+
}
|
|
157
|
+
case 412: {
|
|
158
|
+
return "PRECONDITION_FAILED";
|
|
159
|
+
}
|
|
160
|
+
case 413: {
|
|
161
|
+
return "PAYLOAD_TOO_LARGE";
|
|
162
|
+
}
|
|
163
|
+
case 422: {
|
|
164
|
+
return "VALIDATION_FAILED";
|
|
165
|
+
}
|
|
166
|
+
case 429: {
|
|
167
|
+
return "TOO_MANY_REQUESTS";
|
|
168
|
+
}
|
|
169
|
+
case 500: {
|
|
170
|
+
return "INTERNAL_ERROR";
|
|
171
|
+
}
|
|
172
|
+
case 501: {
|
|
173
|
+
return "NOT_IMPLEMENTED";
|
|
174
|
+
}
|
|
175
|
+
case 503: {
|
|
176
|
+
return "SERVICE_UNAVAILABLE";
|
|
177
|
+
}
|
|
178
|
+
case 504: {
|
|
179
|
+
return "TIMEOUT";
|
|
180
|
+
}
|
|
181
|
+
default: {
|
|
182
|
+
return status >= 500 ? "INTERNAL_ERROR" : "BAD_REQUEST";
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
function extractApiErrorInfo(error) {
|
|
187
|
+
if (!(error instanceof ApiError)) {
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
return {
|
|
191
|
+
status: error.status,
|
|
192
|
+
code: error.code,
|
|
193
|
+
message: error.message,
|
|
194
|
+
...error.details !== undefined && { details: error.details }
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// src/server/request.ts
|
|
199
|
+
async function makeApiRequest(baseUrl, apiToken, endpoint, method = "GET", body) {
|
|
200
|
+
const url = `${baseUrl}${endpoint}`;
|
|
201
|
+
const headers = new Headers;
|
|
202
|
+
headers.set("Content-Type", "application/json");
|
|
203
|
+
headers.set("x-api-key", apiToken);
|
|
204
|
+
const options = {
|
|
205
|
+
method,
|
|
206
|
+
headers
|
|
207
|
+
};
|
|
208
|
+
if (body && (method === "POST" || method === "PUT")) {
|
|
209
|
+
options.body = JSON.stringify(body);
|
|
210
|
+
}
|
|
211
|
+
const response = await fetch(url, options);
|
|
212
|
+
if (!response.ok) {
|
|
213
|
+
let errorBody;
|
|
214
|
+
try {
|
|
215
|
+
errorBody = await response.json();
|
|
216
|
+
} catch {
|
|
217
|
+
try {
|
|
218
|
+
errorBody = await response.text();
|
|
219
|
+
} catch {}
|
|
220
|
+
}
|
|
221
|
+
throw ApiError.fromResponse(response.status, response.statusText, errorBody);
|
|
222
|
+
}
|
|
223
|
+
return await response.json();
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// src/server/client-base.ts
|
|
227
|
+
class PlaycademyClient {
|
|
228
|
+
state;
|
|
229
|
+
constructor(state) {
|
|
230
|
+
this.state = state;
|
|
231
|
+
}
|
|
232
|
+
static async init(config) {
|
|
233
|
+
const { apiKey, baseUrl, gameId } = config;
|
|
234
|
+
if (!apiKey || typeof apiKey !== "string") {
|
|
235
|
+
throw new Error("[Playcademy SDK] apiKey is required");
|
|
236
|
+
}
|
|
237
|
+
if (!config.config) {
|
|
238
|
+
throw new Error("[Playcademy SDK] config is required in edge environments. " + "Pass config directly, or use PlaycademyClient from @playcademy/sdk/server " + "for filesystem-based config loading.");
|
|
239
|
+
}
|
|
240
|
+
const envBaseUrl = typeof process !== "undefined" ? process.env?.PLAYCADEMY_BASE_URL : undefined;
|
|
241
|
+
const finalBaseUrl = baseUrl || envBaseUrl || "https://hub.playcademy.net";
|
|
242
|
+
const state = {
|
|
243
|
+
apiKey,
|
|
244
|
+
baseUrl: finalBaseUrl,
|
|
245
|
+
gameId: gameId || "",
|
|
246
|
+
config: config.config
|
|
247
|
+
};
|
|
248
|
+
const client = new PlaycademyClient(state);
|
|
249
|
+
if (!gameId) {
|
|
250
|
+
await client.fetchGameId();
|
|
251
|
+
}
|
|
252
|
+
return client;
|
|
253
|
+
}
|
|
254
|
+
async fetchGameId() {
|
|
255
|
+
throw new Error("[Playcademy SDK] gameId is required. Please provide it in the config or implement gameId fetching.");
|
|
256
|
+
}
|
|
257
|
+
async request(path, method = "GET", body) {
|
|
258
|
+
return makeApiRequest(this.state.baseUrl, this.state.apiKey, path, method, body);
|
|
259
|
+
}
|
|
260
|
+
get gameId() {
|
|
261
|
+
return this.state.gameId;
|
|
262
|
+
}
|
|
263
|
+
get config() {
|
|
264
|
+
return this.state.config;
|
|
265
|
+
}
|
|
266
|
+
timeback = createTimebackNamespace(this);
|
|
267
|
+
}
|
|
268
|
+
// src/server/utils/verify-game-token.ts
|
|
269
|
+
async function verifyGameToken(gameToken, options) {
|
|
270
|
+
if (!gameToken || typeof gameToken !== "string") {
|
|
271
|
+
throw new Error("[Playcademy SDK] gameToken must be a non-empty string");
|
|
272
|
+
}
|
|
273
|
+
const baseUrl = options?.baseUrl || process.env.PLAYCADEMY_BASE_URL || process.env.PUBLIC_PLAYCADEMY_BASE_URL || process.env.NEXT_PUBLIC_PLAYCADEMY_BASE_URL;
|
|
274
|
+
if (!baseUrl) {
|
|
275
|
+
throw new Error(`[Playcademy SDK] PLAYCADEMY_BASE_URL is not set
|
|
276
|
+
Please set the PLAYCADEMY_BASE_URL environment variable`);
|
|
277
|
+
}
|
|
278
|
+
try {
|
|
279
|
+
const response = await fetch(`${baseUrl}/api/games/verify`, {
|
|
280
|
+
method: "POST",
|
|
281
|
+
headers: {
|
|
282
|
+
"Content-Type": "application/json"
|
|
283
|
+
},
|
|
284
|
+
body: JSON.stringify({ token: gameToken })
|
|
285
|
+
});
|
|
286
|
+
if (!response.ok) {
|
|
287
|
+
let errorMessage = "Unknown error";
|
|
288
|
+
try {
|
|
289
|
+
const data = await response.json();
|
|
290
|
+
const errorField = data.error || data.message;
|
|
291
|
+
if (typeof errorField === "string") {
|
|
292
|
+
errorMessage = errorField;
|
|
293
|
+
} else if (errorField && typeof errorField === "object") {
|
|
294
|
+
const errorObj = errorField;
|
|
295
|
+
if ("message" in errorObj && typeof errorObj.message === "string") {
|
|
296
|
+
errorMessage = errorObj.message;
|
|
297
|
+
if ("code" in errorObj && typeof errorObj.code === "string") {
|
|
298
|
+
errorMessage = `[${errorObj.code}] ${errorMessage}`;
|
|
299
|
+
}
|
|
300
|
+
} else {
|
|
301
|
+
errorMessage = JSON.stringify(errorField);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
} catch {
|
|
305
|
+
errorMessage = response.statusText || "Unknown error";
|
|
306
|
+
}
|
|
307
|
+
throw new Error(`[Playcademy SDK] Token verification failed: ${response.status} ${errorMessage}`);
|
|
308
|
+
}
|
|
309
|
+
const result = await response.json();
|
|
310
|
+
return result;
|
|
311
|
+
} catch (error) {
|
|
312
|
+
if (error instanceof Error) {
|
|
313
|
+
throw error;
|
|
314
|
+
}
|
|
315
|
+
throw new Error("[Playcademy SDK] Token verification failed: Network error", {
|
|
316
|
+
cause: error
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
export {
|
|
321
|
+
verifyGameToken,
|
|
322
|
+
PlaycademyClient
|
|
323
|
+
};
|
package/dist/server.d.ts
CHANGED
|
@@ -545,6 +545,8 @@ interface BackendDeploymentBundle {
|
|
|
545
545
|
bindings?: BackendResourceBindings;
|
|
546
546
|
/** Optional schema information for database setup */
|
|
547
547
|
schema?: SchemaInfo;
|
|
548
|
+
/** Optional Cloudflare Worker compatibility flags */
|
|
549
|
+
compatibilityFlags?: string[];
|
|
548
550
|
}
|
|
549
551
|
|
|
550
552
|
/**
|
|
@@ -567,72 +569,39 @@ interface UserInfo {
|
|
|
567
569
|
/**
|
|
568
570
|
* Server-side Playcademy client for recording student activity to TimeBack.
|
|
569
571
|
*
|
|
570
|
-
* This client
|
|
571
|
-
*
|
|
572
|
+
* This client works in any edge runtime. Config must be provided directly
|
|
573
|
+
* via the `config` option — there is no filesystem-based config discovery.
|
|
572
574
|
*
|
|
573
575
|
* @example
|
|
574
576
|
* ```typescript
|
|
575
|
-
* // Initialize the client (loads config automatically)
|
|
576
577
|
* const client = await PlaycademyClient.init({
|
|
577
|
-
* apiKey:
|
|
578
|
+
* apiKey: env.PLAYCADEMY_API_KEY,
|
|
579
|
+
* gameId: env.GAME_ID,
|
|
580
|
+
* config: { name: 'My Game', integrations: { timeback: {...} } }
|
|
578
581
|
* })
|
|
579
582
|
*
|
|
580
|
-
*
|
|
581
|
-
* await client.timeback.endActivity(studentId, {
|
|
582
|
-
* activityData: { activityId: 'math-quiz-1' },
|
|
583
|
-
* scoreData: { correctQuestions: 17, totalQuestions: 20, accuracy: 0.85 },
|
|
584
|
-
* timingData: { durationSeconds: 300 },
|
|
585
|
-
* xpEarned: 5
|
|
586
|
-
* })
|
|
583
|
+
* await client.timeback.endActivity(studentId, { ... })
|
|
587
584
|
* ```
|
|
588
585
|
*/
|
|
589
|
-
declare class PlaycademyClient {
|
|
586
|
+
declare class PlaycademyClient$1 {
|
|
590
587
|
private state;
|
|
591
|
-
|
|
592
|
-
* Private constructor. Use PlaycademyClient.init() to create instances.
|
|
593
|
-
*
|
|
594
|
-
* @param state - Internal client state
|
|
595
|
-
* @private
|
|
596
|
-
*/
|
|
597
|
-
private constructor();
|
|
588
|
+
protected constructor(state: PlaycademyServerClientState);
|
|
598
589
|
/**
|
|
599
590
|
* Initialize a new PlaycademyClient instance.
|
|
600
591
|
*
|
|
601
|
-
*
|
|
602
|
-
*
|
|
592
|
+
* Requires `config` to be provided directly. For automatic config file
|
|
593
|
+
* discovery from the filesystem, use `PlaycademyClient` from `@playcademy/sdk/server`.
|
|
603
594
|
*
|
|
604
595
|
* @param config - Client configuration options
|
|
605
596
|
* @param config.apiKey - Playcademy API key for authentication
|
|
597
|
+
* @param config.config - Game configuration object (required)
|
|
606
598
|
* @param config.gameId - Optional game ID (will be fetched from API if not provided)
|
|
607
|
-
* @param config.configPath - Optional path to playcademy.config.js (auto-discovered if not provided)
|
|
608
599
|
* @param config.baseUrl - Optional base URL for Playcademy API (defaults to production)
|
|
609
600
|
* @returns Promise resolving to initialized PlaycademyClient instance
|
|
610
601
|
* @throws {Error} If apiKey is missing or invalid
|
|
611
|
-
* @throws {Error} If config
|
|
612
|
-
* @throws {Error} If TimeBack integration is not set up for the game
|
|
613
|
-
*
|
|
614
|
-
* @example
|
|
615
|
-
* ```typescript
|
|
616
|
-
* // Basic initialization with API key
|
|
617
|
-
* const client = await PlaycademyClient.init({
|
|
618
|
-
* apiKey: process.env.PLAYCADEMY_API_KEY,
|
|
619
|
-
* gameId: 'my-math-game'
|
|
620
|
-
* })
|
|
621
|
-
*
|
|
622
|
-
* // With custom config path
|
|
623
|
-
* const client = await PlaycademyClient.init({
|
|
624
|
-
* apiKey: process.env.PLAYCADEMY_API_KEY,
|
|
625
|
-
* configPath: './custom-config.js'
|
|
626
|
-
* })
|
|
627
|
-
*
|
|
628
|
-
* // With custom base URL (for development)
|
|
629
|
-
* const client = await PlaycademyClient.init({
|
|
630
|
-
* apiKey: process.env.PLAYCADEMY_API_KEY,
|
|
631
|
-
* baseUrl: 'http://localhost:3000'
|
|
632
|
-
* })
|
|
633
|
-
* ```
|
|
602
|
+
* @throws {Error} If config is not provided
|
|
634
603
|
*/
|
|
635
|
-
static init(config: PlaycademyServerClientConfig): Promise<PlaycademyClient>;
|
|
604
|
+
static init(config: PlaycademyServerClientConfig): Promise<PlaycademyClient$1>;
|
|
636
605
|
private fetchGameId;
|
|
637
606
|
/**
|
|
638
607
|
* Makes an authenticated HTTP request to the API.
|
|
@@ -670,6 +639,52 @@ declare class PlaycademyClient {
|
|
|
670
639
|
};
|
|
671
640
|
}
|
|
672
641
|
|
|
642
|
+
/**
|
|
643
|
+
* @fileoverview Server-side Playcademy Client (Node.js)
|
|
644
|
+
*
|
|
645
|
+
* Extends the edge-safe base client with filesystem-based config discovery.
|
|
646
|
+
* This is the version exported from `@playcademy/sdk/server` — it supports
|
|
647
|
+
* both explicit config and automatic `playcademy.config.js` loading from disk.
|
|
648
|
+
*
|
|
649
|
+
* For edge runtimes without filesystem access, use the base client from
|
|
650
|
+
* `./client-base` (re-exported via `./edge`).
|
|
651
|
+
*/
|
|
652
|
+
|
|
653
|
+
/**
|
|
654
|
+
* Server-side Playcademy client for recording student activity to TimeBack.
|
|
655
|
+
*
|
|
656
|
+
* Extends the edge-safe base with automatic playcademy.config.js loading
|
|
657
|
+
* from the filesystem. Works in Node.js and other environments with `fs` access.
|
|
658
|
+
*
|
|
659
|
+
* @example
|
|
660
|
+
* ```typescript
|
|
661
|
+
* // With automatic config discovery (Node.js only)
|
|
662
|
+
* const client = await PlaycademyClient.init({
|
|
663
|
+
* apiKey: process.env.PLAYCADEMY_API_KEY,
|
|
664
|
+
* gameId: 'my-math-game'
|
|
665
|
+
* })
|
|
666
|
+
*
|
|
667
|
+
* // With explicit config (works everywhere)
|
|
668
|
+
* const client = await PlaycademyClient.init({
|
|
669
|
+
* apiKey: process.env.PLAYCADEMY_API_KEY,
|
|
670
|
+
* gameId: 'my-math-game',
|
|
671
|
+
* config: { name: 'My Game', integrations: { timeback: {...} } }
|
|
672
|
+
* })
|
|
673
|
+
* ```
|
|
674
|
+
*/
|
|
675
|
+
declare class PlaycademyClient extends PlaycademyClient$1 {
|
|
676
|
+
/**
|
|
677
|
+
* Initialize a new PlaycademyClient instance.
|
|
678
|
+
*
|
|
679
|
+
* If `config` is not provided, loads playcademy.config.js from the current
|
|
680
|
+
* directory (or specified path). This filesystem access requires Node.js.
|
|
681
|
+
*
|
|
682
|
+
* @param config - Client configuration options
|
|
683
|
+
* @returns Promise resolving to initialized PlaycademyClient instance
|
|
684
|
+
*/
|
|
685
|
+
static init(config: PlaycademyServerClientConfig): Promise<PlaycademyClient>;
|
|
686
|
+
}
|
|
687
|
+
|
|
673
688
|
/**
|
|
674
689
|
* @fileoverview Game Token Verification Utilities
|
|
675
690
|
*
|