@playcademy/sdk 0.0.8 → 0.1.0
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 +829 -75
- package/dist/index.js +660 -240
- package/dist/server.d.ts +309 -16
- package/dist/server.js +321 -5
- package/dist/types.d.ts +991 -253
- package/package.json +13 -10
package/dist/index.js
CHANGED
|
@@ -11,10 +11,19 @@ var __export = (target, all) => {
|
|
|
11
11
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
12
12
|
|
|
13
13
|
// ../logger/src/index.ts
|
|
14
|
-
var
|
|
14
|
+
var hasProcess = () => {
|
|
15
|
+
return typeof process !== "undefined";
|
|
16
|
+
}, isBrowser = () => {
|
|
15
17
|
const g = globalThis;
|
|
16
18
|
return typeof g.window !== "undefined" && typeof g.document !== "undefined";
|
|
17
|
-
}, colors,
|
|
19
|
+
}, colors, shouldUseColor = () => {
|
|
20
|
+
const preference = (process.env.LOG_COLOR ?? "auto").toLowerCase();
|
|
21
|
+
if (preference === "always")
|
|
22
|
+
return true;
|
|
23
|
+
if (preference === "never")
|
|
24
|
+
return false;
|
|
25
|
+
return Boolean(process.stdout && process.stdout.isTTY && true);
|
|
26
|
+
}, getLevelColor = (level) => {
|
|
18
27
|
switch (level) {
|
|
19
28
|
case "debug":
|
|
20
29
|
return colors.blue;
|
|
@@ -38,7 +47,7 @@ var isBrowser = () => {
|
|
|
38
47
|
}
|
|
39
48
|
}, logOnServer = (level, message, context) => {
|
|
40
49
|
const consoleMethod = getConsoleMethod(level);
|
|
41
|
-
if (
|
|
50
|
+
if (shouldUseColor()) {
|
|
42
51
|
const timestamp = new Date().toISOString();
|
|
43
52
|
const levelColor = getLevelColor(level);
|
|
44
53
|
const levelUpper = level.toUpperCase().padEnd(5);
|
|
@@ -48,7 +57,10 @@ var isBrowser = () => {
|
|
|
48
57
|
} else {
|
|
49
58
|
consoleMethod(`${coloredPrefix} ${message}`);
|
|
50
59
|
}
|
|
51
|
-
} else {
|
|
60
|
+
} else {
|
|
61
|
+
const formatted = formatLog(level, message, context);
|
|
62
|
+
consoleMethod(formatted);
|
|
63
|
+
}
|
|
52
64
|
}, getConsoleMethod = (level) => {
|
|
53
65
|
switch (level) {
|
|
54
66
|
case "debug":
|
|
@@ -62,8 +74,22 @@ var isBrowser = () => {
|
|
|
62
74
|
default:
|
|
63
75
|
return console.log;
|
|
64
76
|
}
|
|
77
|
+
}, formatLog = (level, message, context) => {
|
|
78
|
+
const timestamp = new Date().toISOString();
|
|
79
|
+
const logEntry = {
|
|
80
|
+
timestamp,
|
|
81
|
+
level: level.toUpperCase(),
|
|
82
|
+
message,
|
|
83
|
+
...context && Object.keys(context).length > 0 && { context }
|
|
84
|
+
};
|
|
85
|
+
if (true) {
|
|
86
|
+
return JSON.stringify(logEntry, null, 2);
|
|
87
|
+
}
|
|
88
|
+
return JSON.stringify(logEntry);
|
|
65
89
|
}, performLog = (level, message, context) => {
|
|
66
|
-
if (level === "debug" &&
|
|
90
|
+
if (level === "debug" && hasProcess() && process.env.PLAYCADEMY_EMBEDDED) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
67
93
|
if (isBrowser()) {
|
|
68
94
|
logInBrowser(level, message, context);
|
|
69
95
|
} else {
|
|
@@ -91,6 +117,85 @@ var init_src = __esm(() => {
|
|
|
91
117
|
log = createLogger();
|
|
92
118
|
});
|
|
93
119
|
|
|
120
|
+
// src/core/auth/strategies.ts
|
|
121
|
+
class ApiKeyAuth {
|
|
122
|
+
apiKey;
|
|
123
|
+
constructor(apiKey) {
|
|
124
|
+
this.apiKey = apiKey;
|
|
125
|
+
}
|
|
126
|
+
getToken() {
|
|
127
|
+
return this.apiKey;
|
|
128
|
+
}
|
|
129
|
+
getType() {
|
|
130
|
+
return "apiKey";
|
|
131
|
+
}
|
|
132
|
+
getHeaders() {
|
|
133
|
+
return { "x-api-key": this.apiKey };
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
class SessionAuth {
|
|
138
|
+
sessionToken;
|
|
139
|
+
constructor(sessionToken) {
|
|
140
|
+
this.sessionToken = sessionToken;
|
|
141
|
+
}
|
|
142
|
+
getToken() {
|
|
143
|
+
return this.sessionToken;
|
|
144
|
+
}
|
|
145
|
+
getType() {
|
|
146
|
+
return "session";
|
|
147
|
+
}
|
|
148
|
+
getHeaders() {
|
|
149
|
+
return { Authorization: `Bearer ${this.sessionToken}` };
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
class GameJwtAuth {
|
|
154
|
+
gameToken;
|
|
155
|
+
constructor(gameToken) {
|
|
156
|
+
this.gameToken = gameToken;
|
|
157
|
+
}
|
|
158
|
+
getToken() {
|
|
159
|
+
return this.gameToken;
|
|
160
|
+
}
|
|
161
|
+
getType() {
|
|
162
|
+
return "gameJwt";
|
|
163
|
+
}
|
|
164
|
+
getHeaders() {
|
|
165
|
+
return { Authorization: `Bearer ${this.gameToken}` };
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
class NoAuth {
|
|
170
|
+
getToken() {
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
getType() {
|
|
174
|
+
return "session";
|
|
175
|
+
}
|
|
176
|
+
getHeaders() {
|
|
177
|
+
return {};
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
function createAuthStrategy(token, tokenType) {
|
|
181
|
+
if (!token) {
|
|
182
|
+
return new NoAuth;
|
|
183
|
+
}
|
|
184
|
+
if (tokenType === "apiKey") {
|
|
185
|
+
return new ApiKeyAuth(token);
|
|
186
|
+
}
|
|
187
|
+
if (tokenType === "session") {
|
|
188
|
+
return new SessionAuth(token);
|
|
189
|
+
}
|
|
190
|
+
if (tokenType === "gameJwt") {
|
|
191
|
+
return new GameJwtAuth(token);
|
|
192
|
+
}
|
|
193
|
+
if (token.startsWith("cademy")) {
|
|
194
|
+
return new ApiKeyAuth(token);
|
|
195
|
+
}
|
|
196
|
+
return new GameJwtAuth(token);
|
|
197
|
+
}
|
|
198
|
+
|
|
94
199
|
// src/core/auth/utils.ts
|
|
95
200
|
function openPopupWindow(url, name = "auth-popup", width = 500, height = 600) {
|
|
96
201
|
const left = window.screenX + (window.outerWidth - width) / 2;
|
|
@@ -146,9 +251,14 @@ function createAuthNamespace(client) {
|
|
|
146
251
|
return {
|
|
147
252
|
login: async (credentials) => {
|
|
148
253
|
try {
|
|
149
|
-
const response = await client["request"]("/auth/
|
|
150
|
-
client.setToken(response.token);
|
|
151
|
-
return {
|
|
254
|
+
const response = await client["request"]("/auth/sign-in/email", "POST", credentials);
|
|
255
|
+
client.setToken(response.token, "session");
|
|
256
|
+
return {
|
|
257
|
+
success: true,
|
|
258
|
+
token: response.token,
|
|
259
|
+
user: response.user,
|
|
260
|
+
expiresAt: response.expiresAt
|
|
261
|
+
};
|
|
152
262
|
} catch (error) {
|
|
153
263
|
return {
|
|
154
264
|
success: false,
|
|
@@ -157,8 +267,29 @@ function createAuthNamespace(client) {
|
|
|
157
267
|
}
|
|
158
268
|
},
|
|
159
269
|
logout: async () => {
|
|
160
|
-
|
|
270
|
+
try {
|
|
271
|
+
await client["request"]("/auth/sign-out", "POST");
|
|
272
|
+
} catch {}
|
|
161
273
|
client.setToken(null);
|
|
274
|
+
},
|
|
275
|
+
apiKeys: {
|
|
276
|
+
create: async (options) => {
|
|
277
|
+
return client["request"]("/dev/api-keys", "POST", {
|
|
278
|
+
name: options?.name || `SDK Key - ${new Date().toISOString()}`,
|
|
279
|
+
expiresIn: options?.expiresIn !== undefined ? options.expiresIn : null,
|
|
280
|
+
permissions: options?.permissions || {
|
|
281
|
+
games: ["read", "write", "delete"],
|
|
282
|
+
users: ["read:self", "write:self"],
|
|
283
|
+
dev: ["read", "write"]
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
},
|
|
287
|
+
list: async () => {
|
|
288
|
+
return client["request"]("/auth/api-key/list", "GET");
|
|
289
|
+
},
|
|
290
|
+
revoke: async (keyId) => {
|
|
291
|
+
await client["request"]("/auth/api-key/revoke", "POST", { id: keyId });
|
|
292
|
+
}
|
|
162
293
|
}
|
|
163
294
|
};
|
|
164
295
|
}
|
|
@@ -733,10 +864,25 @@ function createTTLCache(options) {
|
|
|
733
864
|
}
|
|
734
865
|
|
|
735
866
|
// src/core/request.ts
|
|
867
|
+
function checkDevWarnings(data) {
|
|
868
|
+
if (!data || typeof data !== "object")
|
|
869
|
+
return;
|
|
870
|
+
const response = data;
|
|
871
|
+
const warningType = response.__playcademyDevWarning;
|
|
872
|
+
if (!warningType)
|
|
873
|
+
return;
|
|
874
|
+
switch (warningType) {
|
|
875
|
+
case "timeback-disabled":
|
|
876
|
+
console.warn("%c⚠️ TimeBack Disabled in Dev", "background: #f59e0b; color: white; padding: 4px 8px; border-radius: 3px; font-weight: bold", `
|
|
877
|
+
` + (response.__playcademyDevMessage || "TimeBack is disabled in local development"));
|
|
878
|
+
break;
|
|
879
|
+
default:
|
|
880
|
+
console.warn(`[Playcademy Dev Warning] ${warningType}`);
|
|
881
|
+
}
|
|
882
|
+
}
|
|
736
883
|
async function request({
|
|
737
884
|
path,
|
|
738
885
|
baseUrl,
|
|
739
|
-
token,
|
|
740
886
|
method = "GET",
|
|
741
887
|
body,
|
|
742
888
|
extraHeaders = {}
|
|
@@ -750,8 +896,6 @@ async function request({
|
|
|
750
896
|
payload = JSON.stringify(body);
|
|
751
897
|
headers["Content-Type"] = "application/json";
|
|
752
898
|
}
|
|
753
|
-
if (token)
|
|
754
|
-
headers["Authorization"] = `Bearer ${token}`;
|
|
755
899
|
const res = await fetch(url, {
|
|
756
900
|
method,
|
|
757
901
|
headers,
|
|
@@ -770,7 +914,9 @@ async function request({
|
|
|
770
914
|
const contentType = res.headers.get("content-type") ?? "";
|
|
771
915
|
if (contentType.includes("application/json")) {
|
|
772
916
|
try {
|
|
773
|
-
|
|
917
|
+
const parsed = await res.json();
|
|
918
|
+
checkDevWarnings(parsed);
|
|
919
|
+
return parsed;
|
|
774
920
|
} catch (err) {
|
|
775
921
|
if (err instanceof SyntaxError)
|
|
776
922
|
return;
|
|
@@ -819,7 +965,7 @@ function createGamesNamespace(client) {
|
|
|
819
965
|
const promise = client["request"](`/games/${gameIdOrSlug}`, "GET");
|
|
820
966
|
return gameFetchCache.get(gameIdOrSlug, async () => {
|
|
821
967
|
const baseGameData = await promise;
|
|
822
|
-
if (baseGameData.gameType === "hosted" && baseGameData.assetBundleBase !== null) {
|
|
968
|
+
if (baseGameData.gameType === "hosted" && baseGameData.assetBundleBase !== null && baseGameData.assetBundleBase !== "") {
|
|
823
969
|
const manifestData = await fetchManifest(baseGameData.assetBundleBase);
|
|
824
970
|
return { ...baseGameData, manifest: manifestData };
|
|
825
971
|
}
|
|
@@ -1009,153 +1155,155 @@ function createDevNamespace(client) {
|
|
|
1009
1155
|
}
|
|
1010
1156
|
},
|
|
1011
1157
|
games: {
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
if (hooks?.onEvent) {
|
|
1024
|
-
await new Promise((resolve, reject) => {
|
|
1025
|
-
const xhr = new XMLHttpRequest;
|
|
1026
|
-
xhr.open("PUT", initiateResponse.presignedUrl, true);
|
|
1027
|
-
const contentType = file.type || "application/octet-stream";
|
|
1028
|
-
try {
|
|
1029
|
-
xhr.setRequestHeader("Content-Type", contentType);
|
|
1030
|
-
} catch {}
|
|
1031
|
-
xhr.upload.onprogress = (event) => {
|
|
1032
|
-
if (event.lengthComputable) {
|
|
1033
|
-
const percent = event.loaded / event.total;
|
|
1034
|
-
hooks.onEvent?.({
|
|
1035
|
-
type: "s3Progress",
|
|
1036
|
-
loaded: event.loaded,
|
|
1037
|
-
total: event.total,
|
|
1038
|
-
percent
|
|
1039
|
-
});
|
|
1040
|
-
}
|
|
1041
|
-
};
|
|
1042
|
-
xhr.onload = () => {
|
|
1043
|
-
if (xhr.status >= 200 && xhr.status < 300)
|
|
1044
|
-
resolve();
|
|
1045
|
-
else
|
|
1046
|
-
reject(new Error(`File upload failed: ${xhr.status} ${xhr.statusText}`));
|
|
1047
|
-
};
|
|
1048
|
-
xhr.onerror = () => reject(new Error("File upload failed: network error"));
|
|
1049
|
-
xhr.send(file);
|
|
1158
|
+
deploy: {
|
|
1159
|
+
frontend: async (slug, metadata, file, hooks) => {
|
|
1160
|
+
hooks?.onEvent?.({ type: "init" });
|
|
1161
|
+
const game = await client["request"](`/games/${slug}`, "PUT", metadata);
|
|
1162
|
+
if (metadata.gameType === "external" || file === null) {
|
|
1163
|
+
return game;
|
|
1164
|
+
}
|
|
1165
|
+
const fileName = file instanceof File ? file.name : "game.zip";
|
|
1166
|
+
const initiateResponse = await client["request"]("/games/uploads/initiate/", "POST", {
|
|
1167
|
+
fileName,
|
|
1168
|
+
gameId: game.id
|
|
1050
1169
|
});
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1170
|
+
if (hooks?.onEvent && typeof XMLHttpRequest !== "undefined") {
|
|
1171
|
+
await new Promise((resolve, reject) => {
|
|
1172
|
+
const xhr = new XMLHttpRequest;
|
|
1173
|
+
xhr.open("PUT", initiateResponse.presignedUrl, true);
|
|
1174
|
+
const contentType = file.type || "application/octet-stream";
|
|
1175
|
+
try {
|
|
1176
|
+
xhr.setRequestHeader("Content-Type", contentType);
|
|
1177
|
+
} catch {}
|
|
1178
|
+
xhr.upload.onprogress = (event) => {
|
|
1179
|
+
if (event.lengthComputable) {
|
|
1180
|
+
const percent = event.loaded / event.total;
|
|
1181
|
+
hooks.onEvent?.({
|
|
1182
|
+
type: "s3Progress",
|
|
1183
|
+
loaded: event.loaded,
|
|
1184
|
+
total: event.total,
|
|
1185
|
+
percent
|
|
1186
|
+
});
|
|
1187
|
+
}
|
|
1188
|
+
};
|
|
1189
|
+
xhr.onload = () => {
|
|
1190
|
+
if (xhr.status >= 200 && xhr.status < 300)
|
|
1191
|
+
resolve();
|
|
1192
|
+
else
|
|
1193
|
+
reject(new Error(`File upload failed: ${xhr.status} ${xhr.statusText}`));
|
|
1194
|
+
};
|
|
1195
|
+
xhr.onerror = () => reject(new Error("File upload failed: network error"));
|
|
1196
|
+
xhr.send(file);
|
|
1197
|
+
});
|
|
1198
|
+
} else {
|
|
1199
|
+
const uploadResponse = await fetch(initiateResponse.presignedUrl, {
|
|
1200
|
+
method: "PUT",
|
|
1201
|
+
body: file,
|
|
1202
|
+
headers: {
|
|
1203
|
+
"Content-Type": file.type || "application/octet-stream"
|
|
1204
|
+
}
|
|
1205
|
+
});
|
|
1206
|
+
if (!uploadResponse.ok) {
|
|
1207
|
+
throw new Error(`File upload failed: ${uploadResponse.status} ${uploadResponse.statusText}`);
|
|
1057
1208
|
}
|
|
1209
|
+
}
|
|
1210
|
+
const finalizeUrl = `${client.baseUrl}/games/uploads/finalize/`;
|
|
1211
|
+
const authToken = client.getToken();
|
|
1212
|
+
const tokenType = client.getTokenType();
|
|
1213
|
+
const headers = {
|
|
1214
|
+
"Content-Type": "application/json"
|
|
1215
|
+
};
|
|
1216
|
+
if (authToken) {
|
|
1217
|
+
if (tokenType === "apiKey") {
|
|
1218
|
+
headers["x-api-key"] = authToken;
|
|
1219
|
+
} else {
|
|
1220
|
+
headers["Authorization"] = `Bearer ${authToken}`;
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
const finalizeResponse = await fetch(finalizeUrl, {
|
|
1224
|
+
method: "POST",
|
|
1225
|
+
headers,
|
|
1226
|
+
body: JSON.stringify({
|
|
1227
|
+
tempS3Key: initiateResponse.tempS3Key,
|
|
1228
|
+
gameId: initiateResponse.gameId,
|
|
1229
|
+
version: initiateResponse.version,
|
|
1230
|
+
slug,
|
|
1231
|
+
metadata,
|
|
1232
|
+
originalFileName: fileName
|
|
1233
|
+
}),
|
|
1234
|
+
credentials: "omit"
|
|
1058
1235
|
});
|
|
1059
|
-
if (!
|
|
1060
|
-
|
|
1236
|
+
if (!finalizeResponse.ok) {
|
|
1237
|
+
const errText = await finalizeResponse.text().catch(() => "");
|
|
1238
|
+
throw new Error(`Finalize request failed: ${finalizeResponse.status} ${finalizeResponse.statusText}${errText ? ` - ${errText}` : ""}`);
|
|
1061
1239
|
}
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
const anyClient = client;
|
|
1065
|
-
try {
|
|
1066
|
-
return typeof anyClient.getBaseUrl === "function" ? anyClient.getBaseUrl() : "/api";
|
|
1067
|
-
} catch {
|
|
1068
|
-
return "/api";
|
|
1240
|
+
if (!finalizeResponse.body) {
|
|
1241
|
+
throw new Error("Finalize response body missing");
|
|
1069
1242
|
}
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
version: initiateResponse.version,
|
|
1083
|
-
slug,
|
|
1084
|
-
metadata,
|
|
1085
|
-
originalFileName: fileName
|
|
1086
|
-
}),
|
|
1087
|
-
credentials: "omit"
|
|
1088
|
-
});
|
|
1089
|
-
if (!finalizeResponse.ok) {
|
|
1090
|
-
const errText = await finalizeResponse.text().catch(() => "");
|
|
1091
|
-
throw new Error(`Finalize request failed: ${finalizeResponse.status} ${finalizeResponse.statusText}${errText ? ` - ${errText}` : ""}`);
|
|
1092
|
-
}
|
|
1093
|
-
if (!finalizeResponse.body) {
|
|
1094
|
-
throw new Error("Finalize response body missing");
|
|
1095
|
-
}
|
|
1096
|
-
hooks?.onEvent?.({ type: "finalizeStart" });
|
|
1097
|
-
let sawAnyServerEvent = false;
|
|
1098
|
-
const reader = finalizeResponse.body.pipeThrough(new TextDecoderStream).getReader();
|
|
1099
|
-
let buffer = "";
|
|
1100
|
-
while (true) {
|
|
1101
|
-
const { done, value } = await reader.read();
|
|
1102
|
-
if (done) {
|
|
1103
|
-
if (!sawAnyServerEvent) {
|
|
1104
|
-
hooks?.onClose?.();
|
|
1105
|
-
hooks?.onEvent?.({ type: "close" });
|
|
1243
|
+
hooks?.onEvent?.({ type: "finalizeStart" });
|
|
1244
|
+
let sawAnyServerEvent = false;
|
|
1245
|
+
const reader = finalizeResponse.body.pipeThrough(new TextDecoderStream).getReader();
|
|
1246
|
+
let buffer = "";
|
|
1247
|
+
while (true) {
|
|
1248
|
+
const { done, value } = await reader.read();
|
|
1249
|
+
if (done) {
|
|
1250
|
+
if (!sawAnyServerEvent) {
|
|
1251
|
+
hooks?.onClose?.();
|
|
1252
|
+
hooks?.onEvent?.({ type: "close" });
|
|
1253
|
+
}
|
|
1254
|
+
break;
|
|
1106
1255
|
}
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
let eolIndex;
|
|
1111
|
-
while ((eolIndex = buffer.indexOf(`
|
|
1256
|
+
buffer += value;
|
|
1257
|
+
let eolIndex;
|
|
1258
|
+
while ((eolIndex = buffer.indexOf(`
|
|
1112
1259
|
|
|
1113
1260
|
`)) >= 0) {
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
hooks?.onEvent?.({
|
|
1125
|
-
type: "finalizeProgress",
|
|
1126
|
-
percent,
|
|
1127
|
-
currentFileLabel: eventData.currentFileLabel || ""
|
|
1128
|
-
});
|
|
1129
|
-
} else if (eventType === "status") {
|
|
1130
|
-
sawAnyServerEvent = true;
|
|
1131
|
-
if (eventData.message) {
|
|
1261
|
+
const message = buffer.slice(0, eolIndex);
|
|
1262
|
+
buffer = buffer.slice(eolIndex + 2);
|
|
1263
|
+
const eventLine = message.match(/^event: (.*)$/m);
|
|
1264
|
+
const dataLine = message.match(/^data: (.*)$/m);
|
|
1265
|
+
if (eventLine && dataLine) {
|
|
1266
|
+
const eventType = eventLine[1];
|
|
1267
|
+
const eventData = JSON.parse(dataLine[1]);
|
|
1268
|
+
if (eventType === "uploadProgress") {
|
|
1269
|
+
sawAnyServerEvent = true;
|
|
1270
|
+
const percent = (eventData.value ?? 0) / 100;
|
|
1132
1271
|
hooks?.onEvent?.({
|
|
1133
|
-
type: "
|
|
1134
|
-
|
|
1272
|
+
type: "finalizeProgress",
|
|
1273
|
+
percent,
|
|
1274
|
+
currentFileLabel: eventData.currentFileLabel || ""
|
|
1135
1275
|
});
|
|
1276
|
+
} else if (eventType === "status") {
|
|
1277
|
+
sawAnyServerEvent = true;
|
|
1278
|
+
if (eventData.message) {
|
|
1279
|
+
hooks?.onEvent?.({
|
|
1280
|
+
type: "finalizeStatus",
|
|
1281
|
+
message: eventData.message
|
|
1282
|
+
});
|
|
1283
|
+
}
|
|
1284
|
+
} else if (eventType === "complete") {
|
|
1285
|
+
sawAnyServerEvent = true;
|
|
1286
|
+
reader.cancel();
|
|
1287
|
+
return eventData;
|
|
1288
|
+
} else if (eventType === "error") {
|
|
1289
|
+
sawAnyServerEvent = true;
|
|
1290
|
+
reader.cancel();
|
|
1291
|
+
throw new Error(eventData.message);
|
|
1136
1292
|
}
|
|
1137
|
-
} else if (eventType === "complete") {
|
|
1138
|
-
sawAnyServerEvent = true;
|
|
1139
|
-
reader.cancel();
|
|
1140
|
-
return eventData;
|
|
1141
|
-
} else if (eventType === "error") {
|
|
1142
|
-
sawAnyServerEvent = true;
|
|
1143
|
-
reader.cancel();
|
|
1144
|
-
throw new Error(eventData.message);
|
|
1145
1293
|
}
|
|
1146
1294
|
}
|
|
1147
1295
|
}
|
|
1296
|
+
throw new Error("Upload completed but no final game data received");
|
|
1297
|
+
},
|
|
1298
|
+
backend: async (slug, bundle) => {
|
|
1299
|
+
return client["request"](`/games/${slug}/backend/deploy`, "POST", bundle);
|
|
1148
1300
|
}
|
|
1149
|
-
throw new Error("Upload completed but no final game data received");
|
|
1150
1301
|
},
|
|
1151
|
-
|
|
1302
|
+
upsert: async (slug, metadata) => {
|
|
1303
|
+
return client.dev.games.deploy.frontend(slug, metadata, null);
|
|
1304
|
+
},
|
|
1152
1305
|
delete: (gameId) => client["request"](`/games/${gameId}`, "DELETE")
|
|
1153
1306
|
},
|
|
1154
|
-
keys: {
|
|
1155
|
-
create: (label) => client["request"](`/dev/keys`, "POST", { label }),
|
|
1156
|
-
list: () => client["request"](`/dev/keys`, "GET"),
|
|
1157
|
-
revoke: (keyId) => client["request"](`/dev/keys/${keyId}`, "DELETE")
|
|
1158
|
-
},
|
|
1159
1307
|
items: {
|
|
1160
1308
|
create: (gameId, slug, itemData) => client["request"](`/games/${gameId}/items`, "POST", {
|
|
1161
1309
|
slug,
|
|
@@ -1191,9 +1339,17 @@ function createDevNamespace(client) {
|
|
|
1191
1339
|
|
|
1192
1340
|
// src/core/namespaces/maps.ts
|
|
1193
1341
|
function createMapsNamespace(client) {
|
|
1342
|
+
const mapDataCache = createTTLCache({
|
|
1343
|
+
ttl: 5 * 60 * 1000,
|
|
1344
|
+
keyPrefix: "maps.data"
|
|
1345
|
+
});
|
|
1346
|
+
const mapElementsCache = createTTLCache({
|
|
1347
|
+
ttl: 60 * 1000,
|
|
1348
|
+
keyPrefix: "maps.elements"
|
|
1349
|
+
});
|
|
1194
1350
|
return {
|
|
1195
|
-
get: (identifier) => client["request"](`/maps/${identifier}`, "GET"),
|
|
1196
|
-
elements: (mapId) => client["request"](`/map/elements?mapId=${mapId}`, "GET"),
|
|
1351
|
+
get: (identifier, options) => mapDataCache.get(identifier, () => client["request"](`/maps/${identifier}`, "GET"), options),
|
|
1352
|
+
elements: (mapId, options) => mapElementsCache.get(mapId, () => client["request"](`/map/elements?mapId=${mapId}`, "GET"), options),
|
|
1197
1353
|
objects: {
|
|
1198
1354
|
list: (mapId) => client["request"](`/maps/${mapId}/objects`, "GET"),
|
|
1199
1355
|
create: (mapId, objectData) => client["request"](`/maps/${mapId}/objects`, "POST", objectData),
|
|
@@ -1201,6 +1357,7 @@ function createMapsNamespace(client) {
|
|
|
1201
1357
|
}
|
|
1202
1358
|
};
|
|
1203
1359
|
}
|
|
1360
|
+
var init_maps = () => {};
|
|
1204
1361
|
|
|
1205
1362
|
// src/core/namespaces/admin.ts
|
|
1206
1363
|
function createAdminNamespace(client) {
|
|
@@ -1320,6 +1477,7 @@ var init_levels = () => {};
|
|
|
1320
1477
|
|
|
1321
1478
|
// ../data/src/domains/game/table.ts
|
|
1322
1479
|
import {
|
|
1480
|
+
boolean,
|
|
1323
1481
|
jsonb,
|
|
1324
1482
|
pgEnum,
|
|
1325
1483
|
pgTable,
|
|
@@ -1329,7 +1487,7 @@ import {
|
|
|
1329
1487
|
uuid,
|
|
1330
1488
|
varchar
|
|
1331
1489
|
} from "drizzle-orm/pg-core";
|
|
1332
|
-
var gamePlatformEnum, gameBootModeEnum, gameTypeEnum, games, gameSessions, gameStates;
|
|
1490
|
+
var gamePlatformEnum, gameBootModeEnum, gameTypeEnum, games, gameSessions, gameStates, deploymentProviderEnum, gameBackendDeployments;
|
|
1333
1491
|
var init_table = __esm(() => {
|
|
1334
1492
|
init_table3();
|
|
1335
1493
|
init_table4();
|
|
@@ -1368,12 +1526,23 @@ var init_table = __esm(() => {
|
|
|
1368
1526
|
data: jsonb("data").default("{}"),
|
|
1369
1527
|
updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow()
|
|
1370
1528
|
}, (table) => [uniqueIndex("unique_user_game_idx").on(table.userId, table.gameId)]);
|
|
1529
|
+
deploymentProviderEnum = pgEnum("deployment_provider", ["cloudflare", "aws"]);
|
|
1530
|
+
gameBackendDeployments = pgTable("game_backend_deployments", {
|
|
1531
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
1532
|
+
gameId: uuid("game_id").notNull().references(() => games.id, { onDelete: "cascade" }),
|
|
1533
|
+
deploymentId: text("deployment_id").notNull(),
|
|
1534
|
+
provider: deploymentProviderEnum("provider").notNull(),
|
|
1535
|
+
url: text("url").notNull(),
|
|
1536
|
+
codeHash: text("code_hash"),
|
|
1537
|
+
isActive: boolean("is_active").notNull().default(false),
|
|
1538
|
+
deployedAt: timestamp("deployed_at", { withTimezone: true }).notNull().defaultNow()
|
|
1539
|
+
});
|
|
1371
1540
|
});
|
|
1372
1541
|
|
|
1373
1542
|
// ../data/src/domains/inventory/table.ts
|
|
1374
1543
|
import { relations, sql } from "drizzle-orm";
|
|
1375
1544
|
import {
|
|
1376
|
-
boolean,
|
|
1545
|
+
boolean as boolean2,
|
|
1377
1546
|
integer,
|
|
1378
1547
|
jsonb as jsonb2,
|
|
1379
1548
|
pgEnum as pgEnum2,
|
|
@@ -1408,7 +1577,7 @@ var init_table2 = __esm(() => {
|
|
|
1408
1577
|
displayName: text2("display_name").notNull(),
|
|
1409
1578
|
description: text2("description"),
|
|
1410
1579
|
type: itemTypeEnum("type").notNull().default("other"),
|
|
1411
|
-
isPlaceable:
|
|
1580
|
+
isPlaceable: boolean2("is_placeable").default(false).notNull(),
|
|
1412
1581
|
imageUrl: text2("image_url"),
|
|
1413
1582
|
metadata: jsonb2("metadata").default({}),
|
|
1414
1583
|
createdAt: timestamp2("created_at").defaultNow().notNull()
|
|
@@ -1427,7 +1596,7 @@ var init_table2 = __esm(() => {
|
|
|
1427
1596
|
id: uuid2("id").primaryKey().defaultRandom(),
|
|
1428
1597
|
itemId: uuid2("item_id").notNull().references(() => items.id, { onDelete: "cascade" }),
|
|
1429
1598
|
symbol: text2("symbol"),
|
|
1430
|
-
isPrimary:
|
|
1599
|
+
isPrimary: boolean2("is_primary").default(false).notNull(),
|
|
1431
1600
|
createdAt: timestamp2("created_at").defaultNow().notNull(),
|
|
1432
1601
|
updatedAt: timestamp2("updated_at", { withTimezone: true }).defaultNow().$onUpdate(() => new Date)
|
|
1433
1602
|
}, (table) => [uniqueIndex2("currency_item_id_idx").on(table.itemId)]);
|
|
@@ -1438,7 +1607,7 @@ var init_table2 = __esm(() => {
|
|
|
1438
1607
|
price: integer("price").notNull(),
|
|
1439
1608
|
sellBackPercentage: integer("sell_back_percentage"),
|
|
1440
1609
|
stock: integer("stock"),
|
|
1441
|
-
isActive:
|
|
1610
|
+
isActive: boolean2("is_active").default(true).notNull(),
|
|
1442
1611
|
availableFrom: timestamp2("available_from", { withTimezone: true }),
|
|
1443
1612
|
availableUntil: timestamp2("available_until", { withTimezone: true }),
|
|
1444
1613
|
createdAt: timestamp2("created_at").defaultNow().notNull(),
|
|
@@ -1572,7 +1741,7 @@ var init_table3 = __esm(() => {
|
|
|
1572
1741
|
|
|
1573
1742
|
// ../data/src/domains/user/table.ts
|
|
1574
1743
|
import { relations as relations3 } from "drizzle-orm";
|
|
1575
|
-
import { boolean as
|
|
1744
|
+
import { boolean as boolean3, pgEnum as pgEnum4, pgTable as pgTable4, text as text4, timestamp as timestamp4, uniqueIndex as uniqueIndex4 } from "drizzle-orm/pg-core";
|
|
1576
1745
|
var userRoleEnum, developerStatusEnum, users, accounts, sessions, verification, ssoProvider, usersRelations;
|
|
1577
1746
|
var init_table4 = __esm(() => {
|
|
1578
1747
|
init_table3();
|
|
@@ -1584,11 +1753,11 @@ var init_table4 = __esm(() => {
|
|
|
1584
1753
|
username: text4("username").unique(),
|
|
1585
1754
|
email: text4("email").notNull().unique(),
|
|
1586
1755
|
timebackId: text4("timeback_id").unique(),
|
|
1587
|
-
emailVerified:
|
|
1756
|
+
emailVerified: boolean3("email_verified").notNull().default(false),
|
|
1588
1757
|
image: text4("image"),
|
|
1589
1758
|
role: userRoleEnum("role").notNull().default("player"),
|
|
1590
1759
|
developerStatus: developerStatusEnum("developer_status").notNull().default("none"),
|
|
1591
|
-
characterCreated:
|
|
1760
|
+
characterCreated: boolean3("character_created").notNull().default(false),
|
|
1592
1761
|
createdAt: timestamp4("created_at", {
|
|
1593
1762
|
mode: "date",
|
|
1594
1763
|
withTimezone: true
|
|
@@ -1677,16 +1846,32 @@ var init_table4 = __esm(() => {
|
|
|
1677
1846
|
});
|
|
1678
1847
|
|
|
1679
1848
|
// ../data/src/domains/developer/table.ts
|
|
1680
|
-
import { pgTable as pgTable5, text as text5, timestamp as timestamp5, uuid as uuid4
|
|
1681
|
-
var
|
|
1849
|
+
import { boolean as boolean4, integer as integer3, pgTable as pgTable5, text as text5, timestamp as timestamp5, uuid as uuid4 } from "drizzle-orm/pg-core";
|
|
1850
|
+
var apikey;
|
|
1682
1851
|
var init_table5 = __esm(() => {
|
|
1683
1852
|
init_table4();
|
|
1684
|
-
|
|
1853
|
+
apikey = pgTable5("api_key", {
|
|
1685
1854
|
id: uuid4("id").primaryKey().defaultRandom(),
|
|
1855
|
+
name: text5("name"),
|
|
1856
|
+
start: text5("start"),
|
|
1857
|
+
prefix: text5("prefix"),
|
|
1858
|
+
key: text5("key").notNull(),
|
|
1686
1859
|
userId: text5("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1860
|
+
refillInterval: integer3("refill_interval"),
|
|
1861
|
+
refillAmount: integer3("refill_amount"),
|
|
1862
|
+
lastRefillAt: timestamp5("last_refill_at", { withTimezone: true }),
|
|
1863
|
+
enabled: boolean4("enabled").notNull().default(true),
|
|
1864
|
+
rateLimitEnabled: boolean4("rate_limit_enabled").notNull().default(false),
|
|
1865
|
+
rateLimitTimeWindow: integer3("rate_limit_time_window"),
|
|
1866
|
+
rateLimitMax: integer3("rate_limit_max"),
|
|
1867
|
+
requestCount: integer3("request_count").notNull().default(0),
|
|
1868
|
+
remaining: integer3("remaining"),
|
|
1869
|
+
lastRequest: timestamp5("last_request", { withTimezone: true }),
|
|
1870
|
+
expiresAt: timestamp5("expires_at", { withTimezone: true }),
|
|
1871
|
+
createdAt: timestamp5("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
1872
|
+
updatedAt: timestamp5("updated_at", { withTimezone: true }).notNull().defaultNow(),
|
|
1873
|
+
permissions: text5("permissions"),
|
|
1874
|
+
metadata: text5("metadata")
|
|
1690
1875
|
});
|
|
1691
1876
|
});
|
|
1692
1877
|
|
|
@@ -1694,7 +1879,7 @@ var init_table5 = __esm(() => {
|
|
|
1694
1879
|
import { relations as relations4 } from "drizzle-orm";
|
|
1695
1880
|
import {
|
|
1696
1881
|
doublePrecision as doublePrecision2,
|
|
1697
|
-
integer as
|
|
1882
|
+
integer as integer4,
|
|
1698
1883
|
pgTable as pgTable6,
|
|
1699
1884
|
text as text6,
|
|
1700
1885
|
timestamp as timestamp6,
|
|
@@ -1706,7 +1891,7 @@ var init_table6 = __esm(() => {
|
|
|
1706
1891
|
init_table4();
|
|
1707
1892
|
userLevels = pgTable6("user_levels", {
|
|
1708
1893
|
userId: text6("user_id").primaryKey().references(() => users.id, { onDelete: "cascade" }),
|
|
1709
|
-
currentLevel:
|
|
1894
|
+
currentLevel: integer4("current_level").notNull().default(1),
|
|
1710
1895
|
currentXp: doublePrecision2("current_xp").notNull().default(0),
|
|
1711
1896
|
totalXP: doublePrecision2("total_xp").notNull().default(0),
|
|
1712
1897
|
lastLevelUpAt: timestamp6("last_level_up_at", { withTimezone: true }),
|
|
@@ -1715,9 +1900,9 @@ var init_table6 = __esm(() => {
|
|
|
1715
1900
|
});
|
|
1716
1901
|
levelConfigs = pgTable6("level_configs", {
|
|
1717
1902
|
id: uuid5("id").primaryKey().defaultRandom(),
|
|
1718
|
-
level:
|
|
1719
|
-
xpRequired:
|
|
1720
|
-
creditsReward:
|
|
1903
|
+
level: integer4("level").notNull().unique(),
|
|
1904
|
+
xpRequired: integer4("xp_required").notNull(),
|
|
1905
|
+
creditsReward: integer4("credits_reward").notNull().default(0),
|
|
1721
1906
|
createdAt: timestamp6("created_at").defaultNow().notNull()
|
|
1722
1907
|
}, (table) => [uniqueIndex5("unique_level_config_idx").on(table.level)]);
|
|
1723
1908
|
userLevelsRelations = relations4(userLevels, ({ one }) => ({
|
|
@@ -1730,7 +1915,7 @@ var init_table6 = __esm(() => {
|
|
|
1730
1915
|
|
|
1731
1916
|
// ../data/src/domains/leaderboard/table.ts
|
|
1732
1917
|
import { relations as relations5 } from "drizzle-orm";
|
|
1733
|
-
import { index as index2, integer as
|
|
1918
|
+
import { index as index2, integer as integer5, jsonb as jsonb4, pgTable as pgTable7, text as text7, timestamp as timestamp7, uuid as uuid6 } from "drizzle-orm/pg-core";
|
|
1734
1919
|
var gameScores, gameScoresRelations;
|
|
1735
1920
|
var init_table7 = __esm(() => {
|
|
1736
1921
|
init_table();
|
|
@@ -1739,7 +1924,7 @@ var init_table7 = __esm(() => {
|
|
|
1739
1924
|
id: uuid6("id").primaryKey().defaultRandom(),
|
|
1740
1925
|
userId: text7("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
|
|
1741
1926
|
gameId: uuid6("game_id").notNull().references(() => games.id, { onDelete: "cascade" }),
|
|
1742
|
-
score:
|
|
1927
|
+
score: integer5("score").notNull(),
|
|
1743
1928
|
metadata: jsonb4("metadata").default("{}"),
|
|
1744
1929
|
achievedAt: timestamp7("achieved_at", { withTimezone: true }).defaultNow().notNull(),
|
|
1745
1930
|
sessionId: uuid6("session_id").references(() => gameSessions.id, { onDelete: "set null" })
|
|
@@ -1766,22 +1951,22 @@ var init_table7 = __esm(() => {
|
|
|
1766
1951
|
|
|
1767
1952
|
// ../data/src/domains/sprite/table.ts
|
|
1768
1953
|
import { relations as relations6 } from "drizzle-orm";
|
|
1769
|
-
import { integer as
|
|
1954
|
+
import { integer as integer6, pgTable as pgTable8, timestamp as timestamp8, uuid as uuid7, varchar as varchar3 } from "drizzle-orm/pg-core";
|
|
1770
1955
|
var spriteTemplates, spriteSheets, spriteTemplatesRelations, spriteSheetsRelations;
|
|
1771
1956
|
var init_table8 = __esm(() => {
|
|
1772
1957
|
spriteTemplates = pgTable8("sprite_templates", {
|
|
1773
1958
|
id: uuid7("id").primaryKey().defaultRandom(),
|
|
1774
|
-
slug:
|
|
1775
|
-
url:
|
|
1959
|
+
slug: varchar3("slug", { length: 64 }).notNull().unique(),
|
|
1960
|
+
url: varchar3("url", { length: 255 }).notNull(),
|
|
1776
1961
|
createdAt: timestamp8("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
1777
1962
|
updatedAt: timestamp8("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
1778
1963
|
});
|
|
1779
1964
|
spriteSheets = pgTable8("sprite_sheets", {
|
|
1780
1965
|
id: uuid7("id").primaryKey().defaultRandom(),
|
|
1781
1966
|
templateId: uuid7("template_id").notNull().references(() => spriteTemplates.id, { onDelete: "cascade" }),
|
|
1782
|
-
width:
|
|
1783
|
-
height:
|
|
1784
|
-
url:
|
|
1967
|
+
width: integer6("width").notNull(),
|
|
1968
|
+
height: integer6("height").notNull(),
|
|
1969
|
+
url: varchar3("url", { length: 255 }).notNull(),
|
|
1785
1970
|
createdAt: timestamp8("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
1786
1971
|
updatedAt: timestamp8("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
1787
1972
|
});
|
|
@@ -1799,14 +1984,14 @@ var init_table8 = __esm(() => {
|
|
|
1799
1984
|
// ../data/src/domains/character/table.ts
|
|
1800
1985
|
import { relations as relations7 } from "drizzle-orm";
|
|
1801
1986
|
import {
|
|
1802
|
-
integer as
|
|
1987
|
+
integer as integer7,
|
|
1803
1988
|
pgEnum as pgEnum5,
|
|
1804
1989
|
pgTable as pgTable9,
|
|
1805
1990
|
text as text8,
|
|
1806
1991
|
timestamp as timestamp9,
|
|
1807
1992
|
uniqueIndex as uniqueIndex6,
|
|
1808
1993
|
uuid as uuid8,
|
|
1809
|
-
varchar as
|
|
1994
|
+
varchar as varchar4
|
|
1810
1995
|
} from "drizzle-orm/pg-core";
|
|
1811
1996
|
var characterComponentTypeEnum, characterComponents, playerCharacters, playerCharacterAccessories, characterComponentsRelations, playerCharactersRelations, playerCharacterAccessoriesRelations;
|
|
1812
1997
|
var init_table9 = __esm(() => {
|
|
@@ -1822,12 +2007,12 @@ var init_table9 = __esm(() => {
|
|
|
1822
2007
|
characterComponents = pgTable9("character_components", {
|
|
1823
2008
|
id: uuid8("id").primaryKey().defaultRandom(),
|
|
1824
2009
|
componentType: characterComponentTypeEnum("component_type").notNull(),
|
|
1825
|
-
slug:
|
|
1826
|
-
displayName:
|
|
1827
|
-
slot:
|
|
2010
|
+
slug: varchar4("slug", { length: 128 }).notNull().unique(),
|
|
2011
|
+
displayName: varchar4("display_name", { length: 128 }).notNull(),
|
|
2012
|
+
slot: varchar4("slot", { length: 64 }).notNull(),
|
|
1828
2013
|
spriteSheetId: uuid8("sprite_sheet_id").notNull().references(() => spriteSheets.id, { onDelete: "cascade" }),
|
|
1829
|
-
unlockLevel:
|
|
1830
|
-
variant:
|
|
2014
|
+
unlockLevel: integer7("unlock_level").notNull().default(0),
|
|
2015
|
+
variant: integer7("variant").notNull().default(0),
|
|
1831
2016
|
createdAt: timestamp9("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
1832
2017
|
updatedAt: timestamp9("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
1833
2018
|
});
|
|
@@ -1845,7 +2030,7 @@ var init_table9 = __esm(() => {
|
|
|
1845
2030
|
id: uuid8("id").primaryKey().defaultRandom(),
|
|
1846
2031
|
playerCharacterId: uuid8("player_character_id").notNull().references(() => playerCharacters.id, { onDelete: "cascade" }),
|
|
1847
2032
|
accessoryComponentId: uuid8("accessory_component_id").notNull().references(() => characterComponents.id, { onDelete: "cascade" }),
|
|
1848
|
-
slot:
|
|
2033
|
+
slot: varchar4("slot", { length: 64 }).notNull(),
|
|
1849
2034
|
equippedAt: timestamp9("equipped_at", { withTimezone: true }).notNull().defaultNow(),
|
|
1850
2035
|
updatedAt: timestamp9("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
1851
2036
|
}, (table) => [
|
|
@@ -1895,8 +2080,9 @@ var init_table9 = __esm(() => {
|
|
|
1895
2080
|
|
|
1896
2081
|
// ../data/src/domains/timeback/table.ts
|
|
1897
2082
|
import { doublePrecision as doublePrecision3, pgTable as pgTable10, text as text9, timestamp as timestamp10, uniqueIndex as uniqueIndex7, uuid as uuid9 } from "drizzle-orm/pg-core";
|
|
1898
|
-
var timebackDailyXp, timebackXpEvents;
|
|
2083
|
+
var timebackDailyXp, timebackXpEvents, gameTimebackIntegrations;
|
|
1899
2084
|
var init_table10 = __esm(() => {
|
|
2085
|
+
init_table();
|
|
1900
2086
|
init_table4();
|
|
1901
2087
|
timebackDailyXp = pgTable10("timeback_daily_xp", {
|
|
1902
2088
|
userId: text9("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
|
|
@@ -1917,14 +2103,22 @@ var init_table10 = __esm(() => {
|
|
|
1917
2103
|
createdAt: timestamp10("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
1918
2104
|
updatedAt: timestamp10("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
1919
2105
|
}, (table) => [uniqueIndex7("timeback_xp_events_source_id_idx").on(table.source, table.sourceId)]);
|
|
2106
|
+
gameTimebackIntegrations = pgTable10("game_timeback_integrations", {
|
|
2107
|
+
id: uuid9("id").primaryKey().defaultRandom(),
|
|
2108
|
+
gameId: uuid9("game_id").notNull().unique().references(() => games.id, { onDelete: "cascade" }),
|
|
2109
|
+
courseId: text9("course_id").notNull(),
|
|
2110
|
+
lastVerifiedAt: timestamp10("last_verified_at", { withTimezone: true }),
|
|
2111
|
+
createdAt: timestamp10("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
2112
|
+
updatedAt: timestamp10("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
2113
|
+
});
|
|
1920
2114
|
});
|
|
1921
2115
|
|
|
1922
2116
|
// ../data/src/domains/achievement/table.ts
|
|
1923
2117
|
import { relations as relations8 } from "drizzle-orm";
|
|
1924
2118
|
import {
|
|
1925
|
-
boolean as
|
|
2119
|
+
boolean as boolean5,
|
|
1926
2120
|
index as index3,
|
|
1927
|
-
integer as
|
|
2121
|
+
integer as integer8,
|
|
1928
2122
|
jsonb as jsonb5,
|
|
1929
2123
|
pgEnum as pgEnum6,
|
|
1930
2124
|
pgTable as pgTable11,
|
|
@@ -1932,45 +2126,55 @@ import {
|
|
|
1932
2126
|
timestamp as timestamp11,
|
|
1933
2127
|
uniqueIndex as uniqueIndex8,
|
|
1934
2128
|
uuid as uuid10,
|
|
1935
|
-
varchar as
|
|
2129
|
+
varchar as varchar5
|
|
1936
2130
|
} from "drizzle-orm/pg-core";
|
|
1937
|
-
var
|
|
2131
|
+
var achievementScopeEnum, achievements, userAchievementProgress, userAchievementClaims, userAchievementProgressRelations, userAchievementClaimsRelations;
|
|
1938
2132
|
var init_table11 = __esm(() => {
|
|
1939
2133
|
init_table4();
|
|
1940
|
-
|
|
2134
|
+
achievementScopeEnum = pgEnum6("achievement_scope", [
|
|
2135
|
+
"daily",
|
|
2136
|
+
"weekly",
|
|
2137
|
+
"monthly",
|
|
2138
|
+
"yearly",
|
|
2139
|
+
"game",
|
|
2140
|
+
"global",
|
|
2141
|
+
"map",
|
|
2142
|
+
"level",
|
|
2143
|
+
"event"
|
|
2144
|
+
]);
|
|
1941
2145
|
achievements = pgTable11("achievements", {
|
|
1942
|
-
id:
|
|
1943
|
-
title:
|
|
2146
|
+
id: varchar5("id", { length: 255 }).primaryKey(),
|
|
2147
|
+
title: varchar5("title", { length: 255 }).notNull(),
|
|
1944
2148
|
description: text10("description"),
|
|
1945
|
-
|
|
1946
|
-
rewardCredits:
|
|
1947
|
-
|
|
1948
|
-
completionType:
|
|
2149
|
+
scope: achievementScopeEnum("scope").notNull(),
|
|
2150
|
+
rewardCredits: integer8("reward_credits").notNull().default(0),
|
|
2151
|
+
limit: integer8("limit").notNull().default(1),
|
|
2152
|
+
completionType: varchar5("completion_type", { length: 50 }).notNull(),
|
|
1949
2153
|
completionConfig: jsonb5("completion_config").notNull().default({}),
|
|
1950
|
-
|
|
1951
|
-
active:
|
|
2154
|
+
target: jsonb5("target").notNull().default({}),
|
|
2155
|
+
active: boolean5("active").notNull().default(true),
|
|
1952
2156
|
createdAt: timestamp11("created_at", { withTimezone: true }).defaultNow(),
|
|
1953
2157
|
updatedAt: timestamp11("updated_at", { withTimezone: true }).defaultNow()
|
|
1954
2158
|
});
|
|
1955
2159
|
userAchievementProgress = pgTable11("user_achievement_progress", {
|
|
1956
2160
|
id: uuid10("id").primaryKey().defaultRandom(),
|
|
1957
2161
|
userId: text10("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
|
|
1958
|
-
achievementId:
|
|
1959
|
-
|
|
2162
|
+
achievementId: varchar5("achievement_id", { length: 255 }).notNull().references(() => achievements.id, { onDelete: "cascade" }),
|
|
2163
|
+
scopeKey: text10("scope_key").notNull(),
|
|
1960
2164
|
progress: jsonb5("progress").notNull().default({}),
|
|
1961
2165
|
updatedAt: timestamp11("updated_at", { withTimezone: true }).defaultNow().notNull()
|
|
1962
2166
|
}, (table) => [
|
|
1963
|
-
index3("user_achievement_progress_idx").on(table.userId, table.achievementId, table.
|
|
2167
|
+
index3("user_achievement_progress_idx").on(table.userId, table.achievementId, table.scopeKey)
|
|
1964
2168
|
]);
|
|
1965
2169
|
userAchievementClaims = pgTable11("user_achievement_claims", {
|
|
1966
2170
|
id: uuid10("id").primaryKey().defaultRandom(),
|
|
1967
2171
|
userId: text10("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
|
|
1968
|
-
achievementId:
|
|
1969
|
-
|
|
1970
|
-
rewardCredits:
|
|
2172
|
+
achievementId: varchar5("achievement_id", { length: 255 }).notNull().references(() => achievements.id, { onDelete: "cascade" }),
|
|
2173
|
+
scopeKey: text10("scope_key").notNull(),
|
|
2174
|
+
rewardCredits: integer8("reward_credits").notNull(),
|
|
1971
2175
|
createdAt: timestamp11("created_at", { withTimezone: true }).defaultNow().notNull()
|
|
1972
2176
|
}, (table) => [
|
|
1973
|
-
uniqueIndex8("user_achievement_claims_unique").on(table.userId, table.achievementId, table.
|
|
2177
|
+
uniqueIndex8("user_achievement_claims_unique").on(table.userId, table.achievementId, table.scopeKey)
|
|
1974
2178
|
]);
|
|
1975
2179
|
userAchievementProgressRelations = relations8(userAchievementProgress, ({ one }) => ({
|
|
1976
2180
|
user: one(users, {
|
|
@@ -1994,6 +2198,58 @@ var init_table11 = __esm(() => {
|
|
|
1994
2198
|
}));
|
|
1995
2199
|
});
|
|
1996
2200
|
|
|
2201
|
+
// ../data/src/domains/notification/table.ts
|
|
2202
|
+
import { relations as relations9 } from "drizzle-orm";
|
|
2203
|
+
import { index as index4, jsonb as jsonb6, pgEnum as pgEnum7, pgTable as pgTable12, text as text11, timestamp as timestamp12, uuid as uuid11, varchar as varchar6 } from "drizzle-orm/pg-core";
|
|
2204
|
+
var notificationPriorityEnum, notificationStatusEnum, notifications, notificationsRelations;
|
|
2205
|
+
var init_table12 = __esm(() => {
|
|
2206
|
+
init_table4();
|
|
2207
|
+
notificationPriorityEnum = pgEnum7("notification_priority", [
|
|
2208
|
+
"low",
|
|
2209
|
+
"normal",
|
|
2210
|
+
"high",
|
|
2211
|
+
"urgent"
|
|
2212
|
+
]);
|
|
2213
|
+
notificationStatusEnum = pgEnum7("notification_status", [
|
|
2214
|
+
"pending",
|
|
2215
|
+
"delivered",
|
|
2216
|
+
"seen",
|
|
2217
|
+
"clicked",
|
|
2218
|
+
"dismissed",
|
|
2219
|
+
"expired"
|
|
2220
|
+
]);
|
|
2221
|
+
notifications = pgTable12("notifications", {
|
|
2222
|
+
id: uuid11("id").primaryKey().defaultRandom(),
|
|
2223
|
+
userId: text11("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
|
|
2224
|
+
type: varchar6("type", { length: 50 }).notNull(),
|
|
2225
|
+
title: varchar6("title", { length: 255 }).notNull(),
|
|
2226
|
+
message: text11("message").notNull(),
|
|
2227
|
+
data: jsonb6("data").notNull().default({}),
|
|
2228
|
+
priority: notificationPriorityEnum("priority").notNull().default("normal"),
|
|
2229
|
+
status: notificationStatusEnum("status").notNull().default("pending"),
|
|
2230
|
+
createdAt: timestamp12("created_at", { withTimezone: true }).defaultNow().notNull(),
|
|
2231
|
+
deliveredAt: timestamp12("delivered_at", { withTimezone: true }),
|
|
2232
|
+
seenAt: timestamp12("seen_at", { withTimezone: true }),
|
|
2233
|
+
clickedAt: timestamp12("clicked_at", { withTimezone: true }),
|
|
2234
|
+
expiresAt: timestamp12("expires_at", { withTimezone: true }),
|
|
2235
|
+
method: varchar6("method", { length: 50 }),
|
|
2236
|
+
clickUrl: text11("click_url"),
|
|
2237
|
+
metadata: jsonb6("metadata").notNull().default({})
|
|
2238
|
+
}, (table) => [
|
|
2239
|
+
index4("notifications_user_id_idx").on(table.userId),
|
|
2240
|
+
index4("notifications_status_idx").on(table.status),
|
|
2241
|
+
index4("notifications_type_idx").on(table.type),
|
|
2242
|
+
index4("notifications_created_at_idx").on(table.createdAt),
|
|
2243
|
+
index4("notifications_user_status_idx").on(table.userId, table.status)
|
|
2244
|
+
]);
|
|
2245
|
+
notificationsRelations = relations9(notifications, ({ one }) => ({
|
|
2246
|
+
user: one(users, {
|
|
2247
|
+
fields: [notifications.userId],
|
|
2248
|
+
references: [users.id]
|
|
2249
|
+
})
|
|
2250
|
+
}));
|
|
2251
|
+
});
|
|
2252
|
+
|
|
1997
2253
|
// ../data/src/tables.index.ts
|
|
1998
2254
|
var init_tables_index = __esm(() => {
|
|
1999
2255
|
init_table4();
|
|
@@ -2007,10 +2263,11 @@ var init_tables_index = __esm(() => {
|
|
|
2007
2263
|
init_table9();
|
|
2008
2264
|
init_table10();
|
|
2009
2265
|
init_table11();
|
|
2266
|
+
init_table12();
|
|
2010
2267
|
});
|
|
2011
2268
|
|
|
2012
2269
|
// ../data/src/constants.ts
|
|
2013
|
-
var ITEM_SLUGS, CURRENCIES, BADGES,
|
|
2270
|
+
var ITEM_SLUGS, CURRENCIES, BADGES, INTERACTION_TYPE;
|
|
2014
2271
|
var init_constants = __esm(() => {
|
|
2015
2272
|
init_tables_index();
|
|
2016
2273
|
ITEM_SLUGS = {
|
|
@@ -2035,12 +2292,6 @@ var init_constants = __esm(() => {
|
|
|
2035
2292
|
EARLY_ADOPTER: ITEM_SLUGS.EARLY_ADOPTER_BADGE,
|
|
2036
2293
|
FIRST_GAME: ITEM_SLUGS.FIRST_GAME_BADGE
|
|
2037
2294
|
};
|
|
2038
|
-
ACHIEVEMENT_COMPLETION_TYPES = [
|
|
2039
|
-
"time_played_session",
|
|
2040
|
-
"interaction",
|
|
2041
|
-
"leaderboard_rank"
|
|
2042
|
-
];
|
|
2043
|
-
ACHIEVEMENT_COMPLETION_TYPE = Object.fromEntries(ACHIEVEMENT_COMPLETION_TYPES.map((value) => [value, value]));
|
|
2044
2295
|
INTERACTION_TYPE = Object.fromEntries(interactionTypeEnum.enumValues.map((value) => [value, value]));
|
|
2045
2296
|
});
|
|
2046
2297
|
|
|
@@ -2514,9 +2765,60 @@ function createAchievementsNamespace(client) {
|
|
|
2514
2765
|
}
|
|
2515
2766
|
var init_achievements = () => {};
|
|
2516
2767
|
|
|
2768
|
+
// src/constants.ts
|
|
2769
|
+
var CURRENCIES2, BADGES2, AuthProvider, TIMEBACK_ROUTES;
|
|
2770
|
+
var init_constants2 = __esm(() => {
|
|
2771
|
+
CURRENCIES2 = {
|
|
2772
|
+
PRIMARY: "PLAYCADEMY_CREDITS",
|
|
2773
|
+
XP: "PLAYCADEMY_XP"
|
|
2774
|
+
};
|
|
2775
|
+
BADGES2 = {
|
|
2776
|
+
FOUNDING_MEMBER: "FOUNDING_MEMBER_BADGE",
|
|
2777
|
+
EARLY_ADOPTER: "EARLY_ADOPTER_BADGE",
|
|
2778
|
+
FIRST_GAME: "FIRST_GAME_BADGE"
|
|
2779
|
+
};
|
|
2780
|
+
AuthProvider = {
|
|
2781
|
+
TIMEBACK: "TIMEBACK"
|
|
2782
|
+
};
|
|
2783
|
+
TIMEBACK_ROUTES = {
|
|
2784
|
+
PROGRESS: "/api/integrations/timeback/progress",
|
|
2785
|
+
SESSION_END: "/api/integrations/timeback/session-end",
|
|
2786
|
+
AWARD_XP: "/api/integrations/timeback/award-xp"
|
|
2787
|
+
};
|
|
2788
|
+
});
|
|
2789
|
+
|
|
2517
2790
|
// src/core/namespaces/timeback.ts
|
|
2518
2791
|
function createTimebackNamespace(client) {
|
|
2519
2792
|
return {
|
|
2793
|
+
recordProgress: (progressData) => {
|
|
2794
|
+
return client["requestGameBackend"](TIMEBACK_ROUTES.PROGRESS, "POST", { progressData });
|
|
2795
|
+
},
|
|
2796
|
+
recordSessionEnd: (sessionData) => {
|
|
2797
|
+
return client["requestGameBackend"](TIMEBACK_ROUTES.SESSION_END, "POST", { sessionData });
|
|
2798
|
+
},
|
|
2799
|
+
awardXP: (xpAmount, metadata) => {
|
|
2800
|
+
return client["requestGameBackend"](TIMEBACK_ROUTES.AWARD_XP, "POST", {
|
|
2801
|
+
xpAmount,
|
|
2802
|
+
metadata
|
|
2803
|
+
});
|
|
2804
|
+
},
|
|
2805
|
+
management: {
|
|
2806
|
+
setup: (request2) => {
|
|
2807
|
+
return client["request"]("/timeback/setup", "POST", request2);
|
|
2808
|
+
},
|
|
2809
|
+
verify: (gameId) => {
|
|
2810
|
+
return client["request"](`/timeback/verify/${gameId}`, "GET");
|
|
2811
|
+
},
|
|
2812
|
+
cleanup: (gameId) => {
|
|
2813
|
+
return client["request"](`/timeback/integrations/${gameId}`, "DELETE");
|
|
2814
|
+
},
|
|
2815
|
+
get: (gameId) => {
|
|
2816
|
+
return client["request"](`/timeback/integrations/${gameId}`, "GET");
|
|
2817
|
+
},
|
|
2818
|
+
getConfig: (gameId) => {
|
|
2819
|
+
return client["request"](`/timeback/config/${gameId}`, "GET");
|
|
2820
|
+
}
|
|
2821
|
+
},
|
|
2520
2822
|
xp: {
|
|
2521
2823
|
today: async (options) => {
|
|
2522
2824
|
const params = new URLSearchParams;
|
|
@@ -2559,6 +2861,104 @@ function createTimebackNamespace(client) {
|
|
|
2559
2861
|
}
|
|
2560
2862
|
};
|
|
2561
2863
|
}
|
|
2864
|
+
var init_timeback = __esm(() => {
|
|
2865
|
+
init_constants2();
|
|
2866
|
+
});
|
|
2867
|
+
|
|
2868
|
+
// src/core/namespaces/notifications.ts
|
|
2869
|
+
function createNotificationsNamespace(client) {
|
|
2870
|
+
const notificationsListCache = createTTLCache({
|
|
2871
|
+
ttl: 5 * 1000,
|
|
2872
|
+
keyPrefix: "notifications.list"
|
|
2873
|
+
});
|
|
2874
|
+
const notificationStatsCache = createTTLCache({
|
|
2875
|
+
ttl: 30 * 1000,
|
|
2876
|
+
keyPrefix: "notifications.stats"
|
|
2877
|
+
});
|
|
2878
|
+
return {
|
|
2879
|
+
list: async (queryOptions, cacheOptions) => {
|
|
2880
|
+
const params = new URLSearchParams;
|
|
2881
|
+
if (queryOptions?.status)
|
|
2882
|
+
params.append("status", queryOptions.status);
|
|
2883
|
+
if (queryOptions?.type)
|
|
2884
|
+
params.append("type", queryOptions.type);
|
|
2885
|
+
if (queryOptions?.limit)
|
|
2886
|
+
params.append("limit", String(queryOptions.limit));
|
|
2887
|
+
if (queryOptions?.offset)
|
|
2888
|
+
params.append("offset", String(queryOptions.offset));
|
|
2889
|
+
const qs = params.toString();
|
|
2890
|
+
const path = qs ? `/notifications?${qs}` : "/notifications";
|
|
2891
|
+
const cacheKey = qs ? `list-${qs}` : "list";
|
|
2892
|
+
return notificationsListCache.get(cacheKey, () => client["request"](path, "GET"), cacheOptions);
|
|
2893
|
+
},
|
|
2894
|
+
markAsSeen: async (notificationId) => {
|
|
2895
|
+
const result = await client["request"](`/notifications/${notificationId}/status`, "PATCH", {
|
|
2896
|
+
id: notificationId,
|
|
2897
|
+
status: "seen"
|
|
2898
|
+
});
|
|
2899
|
+
notificationsListCache.clear();
|
|
2900
|
+
return result;
|
|
2901
|
+
},
|
|
2902
|
+
markAsClicked: async (notificationId) => {
|
|
2903
|
+
const result = await client["request"](`/notifications/${notificationId}/status`, "PATCH", {
|
|
2904
|
+
id: notificationId,
|
|
2905
|
+
status: "clicked"
|
|
2906
|
+
});
|
|
2907
|
+
notificationsListCache.clear();
|
|
2908
|
+
return result;
|
|
2909
|
+
},
|
|
2910
|
+
dismiss: async (notificationId) => {
|
|
2911
|
+
const result = await client["request"](`/notifications/${notificationId}/status`, "PATCH", {
|
|
2912
|
+
id: notificationId,
|
|
2913
|
+
status: "dismissed"
|
|
2914
|
+
});
|
|
2915
|
+
notificationsListCache.clear();
|
|
2916
|
+
return result;
|
|
2917
|
+
},
|
|
2918
|
+
stats: {
|
|
2919
|
+
get: async (queryOptions, cacheOptions) => {
|
|
2920
|
+
const user = await client.users.me();
|
|
2921
|
+
const params = new URLSearchParams;
|
|
2922
|
+
if (queryOptions?.from)
|
|
2923
|
+
params.append("from", queryOptions.from);
|
|
2924
|
+
if (queryOptions?.to)
|
|
2925
|
+
params.append("to", queryOptions.to);
|
|
2926
|
+
const qs = params.toString();
|
|
2927
|
+
const path = qs ? `/notifications/stats/${user.id}?${qs}` : `/notifications/stats/${user.id}`;
|
|
2928
|
+
const cacheKey = qs ? `stats-${qs}` : "stats";
|
|
2929
|
+
return notificationStatsCache.get(cacheKey, () => client["request"](path, "GET"), cacheOptions);
|
|
2930
|
+
}
|
|
2931
|
+
}
|
|
2932
|
+
};
|
|
2933
|
+
}
|
|
2934
|
+
var init_notifications = () => {};
|
|
2935
|
+
|
|
2936
|
+
// src/core/namespaces/backend.ts
|
|
2937
|
+
function createBackendNamespace(client) {
|
|
2938
|
+
function normalizePath(path) {
|
|
2939
|
+
return path.startsWith("/") ? path : `/${path}`;
|
|
2940
|
+
}
|
|
2941
|
+
return {
|
|
2942
|
+
async get(path, headers) {
|
|
2943
|
+
return client["requestGameBackend"](normalizePath(path), "GET", undefined, headers);
|
|
2944
|
+
},
|
|
2945
|
+
async post(path, body, headers) {
|
|
2946
|
+
return client["requestGameBackend"](normalizePath(path), "POST", body, headers);
|
|
2947
|
+
},
|
|
2948
|
+
async put(path, body, headers) {
|
|
2949
|
+
return client["requestGameBackend"](normalizePath(path), "PUT", body, headers);
|
|
2950
|
+
},
|
|
2951
|
+
async patch(path, body, headers) {
|
|
2952
|
+
return client["requestGameBackend"](normalizePath(path), "PATCH", body, headers);
|
|
2953
|
+
},
|
|
2954
|
+
async delete(path, headers) {
|
|
2955
|
+
return client["requestGameBackend"](normalizePath(path), "DELETE", undefined, headers);
|
|
2956
|
+
},
|
|
2957
|
+
async request(path, method, body, headers) {
|
|
2958
|
+
return client["requestGameBackend"](normalizePath(path), method, body, headers);
|
|
2959
|
+
}
|
|
2960
|
+
};
|
|
2961
|
+
}
|
|
2562
2962
|
|
|
2563
2963
|
// src/core/namespaces/index.ts
|
|
2564
2964
|
var init_namespaces = __esm(() => {
|
|
@@ -2566,12 +2966,15 @@ var init_namespaces = __esm(() => {
|
|
|
2566
2966
|
init_runtime();
|
|
2567
2967
|
init_games();
|
|
2568
2968
|
init_users();
|
|
2969
|
+
init_maps();
|
|
2569
2970
|
init_levels();
|
|
2570
2971
|
init_credits();
|
|
2571
2972
|
init_character();
|
|
2572
2973
|
init_sprites();
|
|
2573
2974
|
init_realtime();
|
|
2574
2975
|
init_achievements();
|
|
2976
|
+
init_timeback();
|
|
2977
|
+
init_notifications();
|
|
2575
2978
|
});
|
|
2576
2979
|
|
|
2577
2980
|
// src/core/static/init.ts
|
|
@@ -2600,6 +3003,9 @@ function buildAllowedOrigins(explicit) {
|
|
|
2600
3003
|
return ref ? [ref] : [];
|
|
2601
3004
|
}
|
|
2602
3005
|
function isOriginAllowed(origin, allowlist) {
|
|
3006
|
+
if (window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1") {
|
|
3007
|
+
return true;
|
|
3008
|
+
}
|
|
2603
3009
|
if (!allowlist || allowlist.length === 0) {
|
|
2604
3010
|
console.error("[Playcademy SDK] No allowed origins configured. Consider passing allowedParentOrigins explicitly to init().");
|
|
2605
3011
|
return false;
|
|
@@ -2643,7 +3049,8 @@ async function waitForPlaycademyInit(allowedParentOrigins) {
|
|
|
2643
3049
|
function createStandaloneConfig() {
|
|
2644
3050
|
console.warn("[Playcademy SDK] Standalone mode detected, creating mock context for local development");
|
|
2645
3051
|
const mockConfig = {
|
|
2646
|
-
baseUrl: "
|
|
3052
|
+
baseUrl: "http://localhost:4321",
|
|
3053
|
+
gameUrl: "http://localhost:8788",
|
|
2647
3054
|
token: "mock-game-token-for-local-dev",
|
|
2648
3055
|
gameId: "mock-game-id-from-template",
|
|
2649
3056
|
realtimeUrl: undefined
|
|
@@ -2662,6 +3069,7 @@ async function init(options) {
|
|
|
2662
3069
|
}
|
|
2663
3070
|
const client = new PlaycademyClient({
|
|
2664
3071
|
baseUrl: config.baseUrl,
|
|
3072
|
+
gameUrl: config.gameUrl,
|
|
2665
3073
|
token: config.token,
|
|
2666
3074
|
gameId: config.gameId,
|
|
2667
3075
|
autoStartSession: window.self !== window.top
|
|
@@ -2739,7 +3147,8 @@ var init_client = __esm(() => {
|
|
|
2739
3147
|
init_static();
|
|
2740
3148
|
PlaycademyClient = class PlaycademyClient {
|
|
2741
3149
|
baseUrl;
|
|
2742
|
-
|
|
3150
|
+
gameUrl;
|
|
3151
|
+
authStrategy;
|
|
2743
3152
|
gameId;
|
|
2744
3153
|
config;
|
|
2745
3154
|
listeners = {};
|
|
@@ -2747,16 +3156,11 @@ var init_client = __esm(() => {
|
|
|
2747
3156
|
authContext;
|
|
2748
3157
|
initPayload;
|
|
2749
3158
|
constructor(config) {
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
this.gameId = undefined;
|
|
2754
|
-
} else {
|
|
2755
|
-
this.baseUrl = config.baseUrl || "/api";
|
|
2756
|
-
this.token = config.token;
|
|
2757
|
-
this.gameId = config.gameId;
|
|
2758
|
-
}
|
|
3159
|
+
this.baseUrl = config?.baseUrl?.endsWith("/api") ? config.baseUrl : `${config?.baseUrl}/api`;
|
|
3160
|
+
this.gameUrl = config?.gameUrl;
|
|
3161
|
+
this.gameId = config?.gameId;
|
|
2759
3162
|
this.config = config || {};
|
|
3163
|
+
this.authStrategy = createAuthStrategy(config?.token ?? null, config?.tokenType);
|
|
2760
3164
|
this._detectAuthContext();
|
|
2761
3165
|
this._initializeInternalSession().catch(() => {});
|
|
2762
3166
|
}
|
|
@@ -2765,18 +3169,30 @@ var init_client = __esm(() => {
|
|
|
2765
3169
|
const isBrowser2 = typeof window !== "undefined";
|
|
2766
3170
|
return isRelative && isBrowser2 ? `${window.location.origin}${this.baseUrl}` : this.baseUrl;
|
|
2767
3171
|
}
|
|
3172
|
+
getGameBackendUrl() {
|
|
3173
|
+
if (!this.gameUrl) {
|
|
3174
|
+
throw new PlaycademyError("Game backend URL not configured. gameUrl must be set to use game backend features.");
|
|
3175
|
+
}
|
|
3176
|
+
const isRelative = this.gameUrl.startsWith("/");
|
|
3177
|
+
const isBrowser2 = typeof window !== "undefined";
|
|
3178
|
+
const effectiveGameUrl = isRelative && isBrowser2 ? `${window.location.origin}${this.gameUrl}` : this.gameUrl;
|
|
3179
|
+
return `${effectiveGameUrl}/api`;
|
|
3180
|
+
}
|
|
2768
3181
|
ping() {
|
|
2769
3182
|
return "pong";
|
|
2770
3183
|
}
|
|
2771
|
-
setToken(token) {
|
|
2772
|
-
this.
|
|
2773
|
-
this.emit("authChange", { token
|
|
3184
|
+
setToken(token, tokenType) {
|
|
3185
|
+
this.authStrategy = createAuthStrategy(token, tokenType);
|
|
3186
|
+
this.emit("authChange", { token });
|
|
3187
|
+
}
|
|
3188
|
+
getTokenType() {
|
|
3189
|
+
return this.authStrategy.getType();
|
|
2774
3190
|
}
|
|
2775
3191
|
getToken() {
|
|
2776
|
-
return this.
|
|
3192
|
+
return this.authStrategy.getToken();
|
|
2777
3193
|
}
|
|
2778
3194
|
isAuthenticated() {
|
|
2779
|
-
return
|
|
3195
|
+
return this.authStrategy.getToken() !== null;
|
|
2780
3196
|
}
|
|
2781
3197
|
onAuthChange(callback) {
|
|
2782
3198
|
this.on("authChange", (payload) => callback(payload.token));
|
|
@@ -2794,13 +3210,28 @@ var init_client = __esm(() => {
|
|
|
2794
3210
|
});
|
|
2795
3211
|
}
|
|
2796
3212
|
async request(path, method, body, headers) {
|
|
2797
|
-
const effectiveHeaders = {
|
|
3213
|
+
const effectiveHeaders = {
|
|
3214
|
+
...headers,
|
|
3215
|
+
...this.authStrategy.getHeaders()
|
|
3216
|
+
};
|
|
2798
3217
|
return request({
|
|
2799
3218
|
path,
|
|
2800
3219
|
method,
|
|
2801
3220
|
body,
|
|
2802
3221
|
baseUrl: this.baseUrl,
|
|
2803
|
-
|
|
3222
|
+
extraHeaders: effectiveHeaders
|
|
3223
|
+
});
|
|
3224
|
+
}
|
|
3225
|
+
async requestGameBackend(path, method, body, headers) {
|
|
3226
|
+
const effectiveHeaders = {
|
|
3227
|
+
...headers,
|
|
3228
|
+
...this.authStrategy.getHeaders()
|
|
3229
|
+
};
|
|
3230
|
+
return request({
|
|
3231
|
+
path,
|
|
3232
|
+
method,
|
|
3233
|
+
body,
|
|
3234
|
+
baseUrl: this.getGameBackendUrl(),
|
|
2804
3235
|
extraHeaders: effectiveHeaders
|
|
2805
3236
|
});
|
|
2806
3237
|
}
|
|
@@ -2852,6 +3283,8 @@ var init_client = __esm(() => {
|
|
|
2852
3283
|
sprites = createSpritesNamespace(this);
|
|
2853
3284
|
realtime = createRealtimeNamespace(this);
|
|
2854
3285
|
achievements = createAchievementsNamespace(this);
|
|
3286
|
+
notifications = createNotificationsNamespace(this);
|
|
3287
|
+
backend = createBackendNamespace(this);
|
|
2855
3288
|
static init = init;
|
|
2856
3289
|
static login = login2;
|
|
2857
3290
|
static identity = identity;
|
|
@@ -2861,20 +3294,7 @@ var init_client = __esm(() => {
|
|
|
2861
3294
|
// src/index.ts
|
|
2862
3295
|
init_client();
|
|
2863
3296
|
init_messaging();
|
|
2864
|
-
|
|
2865
|
-
// src/constants.ts
|
|
2866
|
-
var CURRENCIES2 = {
|
|
2867
|
-
PRIMARY: "PLAYCADEMY_CREDITS",
|
|
2868
|
-
XP: "PLAYCADEMY_XP"
|
|
2869
|
-
};
|
|
2870
|
-
var BADGES2 = {
|
|
2871
|
-
FOUNDING_MEMBER: "FOUNDING_MEMBER_BADGE",
|
|
2872
|
-
EARLY_ADOPTER: "EARLY_ADOPTER_BADGE",
|
|
2873
|
-
FIRST_GAME: "FIRST_GAME_BADGE"
|
|
2874
|
-
};
|
|
2875
|
-
var AuthProvider = {
|
|
2876
|
-
TIMEBACK: "TIMEBACK"
|
|
2877
|
-
};
|
|
3297
|
+
init_constants2();
|
|
2878
3298
|
export {
|
|
2879
3299
|
messaging,
|
|
2880
3300
|
PlaycademyClient,
|