@playcademy/vite-plugin 0.1.30 → 0.1.32-alpha.1
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
CHANGED
|
@@ -41199,7 +41199,7 @@ var import_picocolors7 = __toESM(require_picocolors(), 1);
|
|
|
41199
41199
|
// package.json
|
|
41200
41200
|
var package_default = {
|
|
41201
41201
|
name: "@playcademy/vite-plugin",
|
|
41202
|
-
version: "0.1.
|
|
41202
|
+
version: "0.1.32",
|
|
41203
41203
|
type: "module",
|
|
41204
41204
|
exports: {
|
|
41205
41205
|
".": {
|
|
@@ -41236,7 +41236,7 @@ var package_default = {
|
|
|
41236
41236
|
|
|
41237
41237
|
// src/lib/backend/server.ts
|
|
41238
41238
|
import {
|
|
41239
|
-
|
|
41239
|
+
loadPlaycademyConfigAndSetWorkspace as loadConfigAndSetWorkspace,
|
|
41240
41240
|
startPlaycademyDevServer,
|
|
41241
41241
|
startPlaycademyHotReload
|
|
41242
41242
|
} from "playcademy/utils";
|
|
@@ -41306,9 +41306,9 @@ function createHotReloadCallbacks(viteConfig) {
|
|
|
41306
41306
|
}
|
|
41307
41307
|
|
|
41308
41308
|
// src/lib/backend/server.ts
|
|
41309
|
-
async function tryLoadConfig(viteConfig) {
|
|
41309
|
+
async function tryLoadConfig(viteConfig, configPath) {
|
|
41310
41310
|
try {
|
|
41311
|
-
return await
|
|
41311
|
+
return await loadConfigAndSetWorkspace(configPath);
|
|
41312
41312
|
} catch (error) {
|
|
41313
41313
|
if (error instanceof Error && !error.message.includes("Could not find")) {
|
|
41314
41314
|
viteConfig.logger.warn(`Could not load playcademy.config.js: ${error.message}`);
|
|
@@ -41337,8 +41337,8 @@ function setupHotReload(serverRef, options) {
|
|
|
41337
41337
|
return () => watcher.close();
|
|
41338
41338
|
}
|
|
41339
41339
|
async function setupCliDevServer(options) {
|
|
41340
|
-
const { preferredPort, viteConfig, platformUrl } = options;
|
|
41341
|
-
const config = await tryLoadConfig(viteConfig);
|
|
41340
|
+
const { preferredPort, viteConfig, platformUrl, configPath } = options;
|
|
41341
|
+
const config = await tryLoadConfig(viteConfig, configPath);
|
|
41342
41342
|
if (!config)
|
|
41343
41343
|
return null;
|
|
41344
41344
|
if (!needsCliDevServer(config))
|
|
@@ -41406,15 +41406,11 @@ import { stdout } from "process";
|
|
|
41406
41406
|
import { createPublicKey as createPublicKey2, createVerify, verify as verify3 } from "crypto";
|
|
41407
41407
|
import { request as request2 } from "https";
|
|
41408
41408
|
import { pipeline } from "stream";
|
|
41409
|
-
import {
|
|
41410
|
-
import {
|
|
41411
|
-
import { tmpdir } from "node:os";
|
|
41412
|
-
import { join as join5, relative } from "node:path";
|
|
41409
|
+
import { readdir as readdir2, readFile as readFile2, stat } from "node:fs/promises";
|
|
41410
|
+
import { join as join4, relative } from "node:path";
|
|
41413
41411
|
import { createHash } from "node:crypto";
|
|
41414
41412
|
import { readdir, readFile } from "node:fs/promises";
|
|
41415
41413
|
import { join as join3 } from "node:path";
|
|
41416
|
-
import { dirname as dirname2, join as join4 } from "node:path";
|
|
41417
|
-
import { fileURLToPath } from "node:url";
|
|
41418
41414
|
import crypto6 from "node:crypto";
|
|
41419
41415
|
import * as crypto7 from "node:crypto";
|
|
41420
41416
|
var __create2 = Object.create;
|
|
@@ -104543,7 +104539,7 @@ var require_event_target_shim2 = __commonJS2((exports, module2) => {
|
|
|
104543
104539
|
var CAPTURE = 1;
|
|
104544
104540
|
var BUBBLE = 2;
|
|
104545
104541
|
var ATTRIBUTE = 3;
|
|
104546
|
-
function
|
|
104542
|
+
function isObject4(x6) {
|
|
104547
104543
|
return x6 !== null && typeof x6 === "object";
|
|
104548
104544
|
}
|
|
104549
104545
|
function getListeners(eventTarget) {
|
|
@@ -104567,7 +104563,7 @@ var require_event_target_shim2 = __commonJS2((exports, module2) => {
|
|
|
104567
104563
|
return null;
|
|
104568
104564
|
},
|
|
104569
104565
|
set(listener) {
|
|
104570
|
-
if (typeof listener !== "function" && !
|
|
104566
|
+
if (typeof listener !== "function" && !isObject4(listener)) {
|
|
104571
104567
|
listener = null;
|
|
104572
104568
|
}
|
|
104573
104569
|
const listeners = getListeners(this);
|
|
@@ -104647,11 +104643,11 @@ var require_event_target_shim2 = __commonJS2((exports, module2) => {
|
|
|
104647
104643
|
if (listener == null) {
|
|
104648
104644
|
return;
|
|
104649
104645
|
}
|
|
104650
|
-
if (typeof listener !== "function" && !
|
|
104646
|
+
if (typeof listener !== "function" && !isObject4(listener)) {
|
|
104651
104647
|
throw new TypeError("'listener' should be a function or an object.");
|
|
104652
104648
|
}
|
|
104653
104649
|
const listeners = getListeners(this);
|
|
104654
|
-
const optionsIsObj =
|
|
104650
|
+
const optionsIsObj = isObject4(options);
|
|
104655
104651
|
const capture = optionsIsObj ? Boolean(options.capture) : Boolean(options);
|
|
104656
104652
|
const listenerType = capture ? CAPTURE : BUBBLE;
|
|
104657
104653
|
const newNode = {
|
|
@@ -104681,7 +104677,7 @@ var require_event_target_shim2 = __commonJS2((exports, module2) => {
|
|
|
104681
104677
|
return;
|
|
104682
104678
|
}
|
|
104683
104679
|
const listeners = getListeners(this);
|
|
104684
|
-
const capture =
|
|
104680
|
+
const capture = isObject4(options) ? Boolean(options.capture) : Boolean(options);
|
|
104685
104681
|
const listenerType = capture ? CAPTURE : BUBBLE;
|
|
104686
104682
|
let prev = null;
|
|
104687
104683
|
let node = listeners.get(eventName);
|
|
@@ -110422,7 +110418,7 @@ var init_block_senders = __esm(() => {
|
|
|
110422
110418
|
var Domains;
|
|
110423
110419
|
var DomainListResponsesV4PagePaginationArray;
|
|
110424
110420
|
var DomainBulkDeleteResponsesSinglePage;
|
|
110425
|
-
var
|
|
110421
|
+
var init_domains3 = __esm(() => {
|
|
110426
110422
|
init_pagination();
|
|
110427
110423
|
Domains = class Domains2 extends APIResource {
|
|
110428
110424
|
list(params, options) {
|
|
@@ -110528,8 +110524,8 @@ var init_settings4 = __esm(() => {
|
|
|
110528
110524
|
init_allow_policies();
|
|
110529
110525
|
init_block_senders();
|
|
110530
110526
|
init_block_senders();
|
|
110531
|
-
|
|
110532
|
-
|
|
110527
|
+
init_domains3();
|
|
110528
|
+
init_domains3();
|
|
110533
110529
|
init_impersonation_registry();
|
|
110534
110530
|
init_impersonation_registry();
|
|
110535
110531
|
init_trusted_domains();
|
|
@@ -111750,7 +111746,7 @@ var init_bulks = __esm(() => {
|
|
|
111750
111746
|
};
|
|
111751
111747
|
});
|
|
111752
111748
|
var Domains2;
|
|
111753
|
-
var
|
|
111749
|
+
var init_domains4 = __esm(() => {
|
|
111754
111750
|
init_bulks();
|
|
111755
111751
|
init_bulks();
|
|
111756
111752
|
Domains2 = class Domains22 extends APIResource {
|
|
@@ -111876,8 +111872,8 @@ var init_intel = __esm(() => {
|
|
|
111876
111872
|
init_asn3();
|
|
111877
111873
|
init_attack_surface_report();
|
|
111878
111874
|
init_attack_surface_report();
|
|
111879
|
-
|
|
111880
|
-
|
|
111875
|
+
init_domains4();
|
|
111876
|
+
init_domains4();
|
|
111881
111877
|
init_indicator_feeds();
|
|
111882
111878
|
init_indicator_feeds();
|
|
111883
111879
|
Intel = class Intel2 extends APIResource {
|
|
@@ -114616,7 +114612,7 @@ var init_page_shield = __esm(() => {
|
|
|
114616
114612
|
});
|
|
114617
114613
|
var Domains3;
|
|
114618
114614
|
var DomainListResponsesSinglePage;
|
|
114619
|
-
var
|
|
114615
|
+
var init_domains5 = __esm(() => {
|
|
114620
114616
|
init_pagination();
|
|
114621
114617
|
Domains3 = class Domains32 extends APIResource {
|
|
114622
114618
|
create(projectName, params, options) {
|
|
@@ -114712,8 +114708,8 @@ var init_deployments = __esm(() => {
|
|
|
114712
114708
|
var Projects;
|
|
114713
114709
|
var DeploymentsSinglePage;
|
|
114714
114710
|
var init_projects = __esm(() => {
|
|
114715
|
-
|
|
114716
|
-
|
|
114711
|
+
init_domains5();
|
|
114712
|
+
init_domains5();
|
|
114717
114713
|
init_deployments();
|
|
114718
114714
|
init_deployments();
|
|
114719
114715
|
init_pagination();
|
|
@@ -115249,7 +115245,7 @@ var init_managed = __esm(() => {
|
|
|
115249
115245
|
};
|
|
115250
115246
|
});
|
|
115251
115247
|
var Domains4;
|
|
115252
|
-
var
|
|
115248
|
+
var init_domains6 = __esm(() => {
|
|
115253
115249
|
init_custom5();
|
|
115254
115250
|
init_custom5();
|
|
115255
115251
|
init_managed();
|
|
@@ -115278,8 +115274,8 @@ var init_buckets = __esm(() => {
|
|
|
115278
115274
|
init_metrics();
|
|
115279
115275
|
init_sippy();
|
|
115280
115276
|
init_sippy();
|
|
115281
|
-
|
|
115282
|
-
|
|
115277
|
+
init_domains6();
|
|
115278
|
+
init_domains6();
|
|
115283
115279
|
Buckets = class Buckets2 extends APIResource {
|
|
115284
115280
|
constructor() {
|
|
115285
115281
|
super(...arguments);
|
|
@@ -118409,7 +118405,7 @@ var init_rate_limits = __esm(() => {
|
|
|
118409
118405
|
});
|
|
118410
118406
|
var Domains5;
|
|
118411
118407
|
var DomainsSinglePage;
|
|
118412
|
-
var
|
|
118408
|
+
var init_domains7 = __esm(() => {
|
|
118413
118409
|
init_pagination();
|
|
118414
118410
|
Domains5 = class Domains52 extends APIResource {
|
|
118415
118411
|
update(domainName, params, options) {
|
|
@@ -118434,8 +118430,8 @@ var init_domains5 = __esm(() => {
|
|
|
118434
118430
|
});
|
|
118435
118431
|
var Registrar;
|
|
118436
118432
|
var init_registrar = __esm(() => {
|
|
118437
|
-
|
|
118438
|
-
|
|
118433
|
+
init_domains7();
|
|
118434
|
+
init_domains7();
|
|
118439
118435
|
Registrar = class Registrar2 extends APIResource {
|
|
118440
118436
|
constructor() {
|
|
118441
118437
|
super(...arguments);
|
|
@@ -121236,7 +121232,7 @@ var init_account_settings = __esm(() => {
|
|
|
121236
121232
|
});
|
|
121237
121233
|
var Domains6;
|
|
121238
121234
|
var DomainsSinglePage2;
|
|
121239
|
-
var
|
|
121235
|
+
var init_domains8 = __esm(() => {
|
|
121240
121236
|
init_pagination();
|
|
121241
121237
|
Domains6 = class Domains62 extends APIResource {
|
|
121242
121238
|
update(params, options) {
|
|
@@ -121369,7 +121365,7 @@ var init_versions3 = __esm(() => {
|
|
|
121369
121365
|
});
|
|
121370
121366
|
var Workers;
|
|
121371
121367
|
var WorkersV4PagePaginationArray;
|
|
121372
|
-
var
|
|
121368
|
+
var init_workers3 = __esm(() => {
|
|
121373
121369
|
init_versions3();
|
|
121374
121370
|
init_versions3();
|
|
121375
121371
|
init_pagination();
|
|
@@ -121421,8 +121417,8 @@ var init_workers = __esm(() => {
|
|
|
121421
121417
|
});
|
|
121422
121418
|
var Beta;
|
|
121423
121419
|
var init_beta = __esm(() => {
|
|
121424
|
-
|
|
121425
|
-
|
|
121420
|
+
init_workers3();
|
|
121421
|
+
init_workers3();
|
|
121426
121422
|
Beta = class Beta2 extends APIResource {
|
|
121427
121423
|
constructor() {
|
|
121428
121424
|
super(...arguments);
|
|
@@ -121789,11 +121785,11 @@ var init_scripts2 = __esm(() => {
|
|
|
121789
121785
|
Scripts2.ScriptAndVersionSettings = ScriptAndVersionSettings;
|
|
121790
121786
|
});
|
|
121791
121787
|
var Workers2;
|
|
121792
|
-
var
|
|
121788
|
+
var init_workers4 = __esm(() => {
|
|
121793
121789
|
init_account_settings();
|
|
121794
121790
|
init_account_settings();
|
|
121795
|
-
|
|
121796
|
-
|
|
121791
|
+
init_domains8();
|
|
121792
|
+
init_domains8();
|
|
121797
121793
|
init_routes3();
|
|
121798
121794
|
init_routes3();
|
|
121799
121795
|
init_subdomains();
|
|
@@ -126573,7 +126569,7 @@ var init_resources3 = __esm(() => {
|
|
|
126573
126569
|
init_vectorize();
|
|
126574
126570
|
init_waiting_rooms();
|
|
126575
126571
|
init_web3();
|
|
126576
|
-
|
|
126572
|
+
init_workers4();
|
|
126577
126573
|
init_workers_for_platforms();
|
|
126578
126574
|
init_workflows();
|
|
126579
126575
|
init_zaraz();
|
|
@@ -126682,7 +126678,7 @@ var init_cloudflare = __esm(() => {
|
|
|
126682
126678
|
init_waiting_rooms();
|
|
126683
126679
|
init_web3();
|
|
126684
126680
|
init_workers_for_platforms();
|
|
126685
|
-
|
|
126681
|
+
init_workers4();
|
|
126686
126682
|
init_workflows();
|
|
126687
126683
|
init_zaraz();
|
|
126688
126684
|
init_zero_trust();
|
|
@@ -127147,7 +127143,7 @@ var require_dist_cjs2 = __commonJS2((exports, module2) => {
|
|
|
127147
127143
|
Fields: () => Fields3,
|
|
127148
127144
|
HttpRequest: () => HttpRequest,
|
|
127149
127145
|
HttpResponse: () => HttpResponse,
|
|
127150
|
-
IHttpRequest: () =>
|
|
127146
|
+
IHttpRequest: () => import_types6.HttpRequest,
|
|
127151
127147
|
getHttpHandlerExtensionConfiguration: () => getHttpHandlerExtensionConfiguration,
|
|
127152
127148
|
isValidHostname: () => isValidHostname,
|
|
127153
127149
|
resolveHttpHandlerRuntimeConfig: () => resolveHttpHandlerRuntimeConfig
|
|
@@ -127174,12 +127170,12 @@ var require_dist_cjs2 = __commonJS2((exports, module2) => {
|
|
|
127174
127170
|
httpHandler: httpHandlerExtensionConfiguration.httpHandler()
|
|
127175
127171
|
};
|
|
127176
127172
|
}, "resolveHttpHandlerRuntimeConfig");
|
|
127177
|
-
var
|
|
127173
|
+
var import_types6 = require_dist_cjs();
|
|
127178
127174
|
var Field = class {
|
|
127179
127175
|
static {
|
|
127180
127176
|
__name(this, "Field");
|
|
127181
127177
|
}
|
|
127182
|
-
constructor({ name: name4, kind: kind2 =
|
|
127178
|
+
constructor({ name: name4, kind: kind2 = import_types6.FieldPosition.HEADER, values = [] }) {
|
|
127183
127179
|
this.name = name4;
|
|
127184
127180
|
this.kind = kind2;
|
|
127185
127181
|
this.values = values;
|
|
@@ -128040,8 +128036,8 @@ var require_dist_cjs4 = __commonJS2((exports, module2) => {
|
|
|
128040
128036
|
normalizeProvider: () => normalizeProvider
|
|
128041
128037
|
});
|
|
128042
128038
|
module2.exports = __toCommonJS(src_exports);
|
|
128043
|
-
var
|
|
128044
|
-
var getSmithyContext = /* @__PURE__ */ __name((context) => context[
|
|
128039
|
+
var import_types6 = require_dist_cjs();
|
|
128040
|
+
var getSmithyContext = /* @__PURE__ */ __name((context) => context[import_types6.SMITHY_CONTEXT_KEY] || (context[import_types6.SMITHY_CONTEXT_KEY] = {}), "getSmithyContext");
|
|
128045
128041
|
var normalizeProvider = /* @__PURE__ */ __name((input) => {
|
|
128046
128042
|
if (typeof input === "function")
|
|
128047
128043
|
return input;
|
|
@@ -132057,8 +132053,8 @@ var require_dist_cjs16 = __commonJS2((exports, module2) => {
|
|
|
132057
132053
|
setFeature: () => setFeature
|
|
132058
132054
|
});
|
|
132059
132055
|
module2.exports = __toCommonJS(src_exports);
|
|
132060
|
-
var
|
|
132061
|
-
var getSmithyContext = /* @__PURE__ */ __name((context) => context[
|
|
132056
|
+
var import_types6 = require_dist_cjs();
|
|
132057
|
+
var getSmithyContext = /* @__PURE__ */ __name((context) => context[import_types6.SMITHY_CONTEXT_KEY] || (context[import_types6.SMITHY_CONTEXT_KEY] = {}), "getSmithyContext");
|
|
132062
132058
|
var import_util_middleware = require_dist_cjs4();
|
|
132063
132059
|
var resolveAuthOptions = /* @__PURE__ */ __name((candidateAuthOptions, authSchemePreference) => {
|
|
132064
132060
|
if (!authSchemePreference || authSchemePreference.length === 0) {
|
|
@@ -132294,9 +132290,9 @@ var require_dist_cjs16 = __commonJS2((exports, module2) => {
|
|
|
132294
132290
|
throw new Error("request could not be signed with `apiKey` since the `apiKey` is not defined");
|
|
132295
132291
|
}
|
|
132296
132292
|
const clonedRequest = import_protocol_http.HttpRequest.clone(httpRequest);
|
|
132297
|
-
if (signingProperties.in ===
|
|
132293
|
+
if (signingProperties.in === import_types6.HttpApiKeyAuthLocation.QUERY) {
|
|
132298
132294
|
clonedRequest.query[signingProperties.name] = identity.apiKey;
|
|
132299
|
-
} else if (signingProperties.in ===
|
|
132295
|
+
} else if (signingProperties.in === import_types6.HttpApiKeyAuthLocation.HEADER) {
|
|
132300
132296
|
clonedRequest.headers[signingProperties.name] = signingProperties.scheme ? `${signingProperties.scheme} ${identity.apiKey}` : identity.apiKey;
|
|
132301
132297
|
} else {
|
|
132302
132298
|
throw new Error("request can only be signed with `apiKey` locations `query` or `header`, but found: `" + signingProperties.in + "`");
|
|
@@ -133369,7 +133365,7 @@ var require_httpAuthSchemes = __commonJS2((exports, module2) => {
|
|
|
133369
133365
|
},
|
|
133370
133366
|
default: undefined
|
|
133371
133367
|
};
|
|
133372
|
-
var
|
|
133368
|
+
var import_client2 = require_client();
|
|
133373
133369
|
var import_core210 = require_dist_cjs16();
|
|
133374
133370
|
var import_signature_v4 = require_dist_cjs20();
|
|
133375
133371
|
var resolveAwsSdkSigV4Config = /* @__PURE__ */ __name((config2) => {
|
|
@@ -133388,7 +133384,7 @@ var require_httpAuthSchemes = __commonJS2((exports, module2) => {
|
|
|
133388
133384
|
});
|
|
133389
133385
|
const boundProvider = bindCallerConfig(config2, memoizedProvider);
|
|
133390
133386
|
if (isUserSupplied && !boundProvider.attributed) {
|
|
133391
|
-
resolvedCredentials = /* @__PURE__ */ __name(async (options) => boundProvider(options).then((creds) => (0,
|
|
133387
|
+
resolvedCredentials = /* @__PURE__ */ __name(async (options) => boundProvider(options).then((creds) => (0, import_client2.setCredentialFeature)(creds, "CREDENTIALS_CODE", "e")), "resolvedCredentials");
|
|
133392
133388
|
resolvedCredentials.memoized = boundProvider.memoized;
|
|
133393
133389
|
resolvedCredentials.configBound = boundProvider.configBound;
|
|
133394
133390
|
resolvedCredentials.attributed = true;
|
|
@@ -133930,7 +133926,7 @@ var require_dist_cjs23 = __commonJS2((exports, module2) => {
|
|
|
133930
133926
|
}
|
|
133931
133927
|
};
|
|
133932
133928
|
var import_protocols = require_protocols();
|
|
133933
|
-
var
|
|
133929
|
+
var import_types6 = require_dist_cjs();
|
|
133934
133930
|
var Command = class {
|
|
133935
133931
|
constructor() {
|
|
133936
133932
|
this.middlewareStack = (0, import_middleware_stack.constructStack)();
|
|
@@ -133962,7 +133958,7 @@ var require_dist_cjs23 = __commonJS2((exports, module2) => {
|
|
|
133962
133958
|
commandName,
|
|
133963
133959
|
inputFilterSensitiveLog,
|
|
133964
133960
|
outputFilterSensitiveLog,
|
|
133965
|
-
[
|
|
133961
|
+
[import_types6.SMITHY_CONTEXT_KEY]: {
|
|
133966
133962
|
commandInstance: this,
|
|
133967
133963
|
...smithyContext
|
|
133968
133964
|
},
|
|
@@ -134187,8 +134183,8 @@ var require_dist_cjs23 = __commonJS2((exports, module2) => {
|
|
|
134187
134183
|
}, "emitWarningIfUnsupportedVersion");
|
|
134188
134184
|
var getChecksumConfiguration = /* @__PURE__ */ __name((runtimeConfig) => {
|
|
134189
134185
|
const checksumAlgorithms = [];
|
|
134190
|
-
for (const id in
|
|
134191
|
-
const algorithmId =
|
|
134186
|
+
for (const id in import_types6.AlgorithmId) {
|
|
134187
|
+
const algorithmId = import_types6.AlgorithmId[id];
|
|
134192
134188
|
if (runtimeConfig[algorithmId] === undefined) {
|
|
134193
134189
|
continue;
|
|
134194
134190
|
}
|
|
@@ -136345,7 +136341,7 @@ var require_protocols2 = __commonJS2((exports, module2) => {
|
|
|
136345
136341
|
return this._read(schema4, data);
|
|
136346
136342
|
}
|
|
136347
136343
|
_read(schema4, value) {
|
|
136348
|
-
const
|
|
136344
|
+
const isObject4 = value !== null && typeof value === "object";
|
|
136349
136345
|
const ns = import_schema2.NormalizedSchema.of(schema4);
|
|
136350
136346
|
if (ns.isListSchema() && Array.isArray(value)) {
|
|
136351
136347
|
const listMember = ns.getValueSchema();
|
|
@@ -136357,7 +136353,7 @@ var require_protocols2 = __commonJS2((exports, module2) => {
|
|
|
136357
136353
|
}
|
|
136358
136354
|
}
|
|
136359
136355
|
return out2;
|
|
136360
|
-
} else if (ns.isMapSchema() &&
|
|
136356
|
+
} else if (ns.isMapSchema() && isObject4) {
|
|
136361
136357
|
const mapMember = ns.getValueSchema();
|
|
136362
136358
|
const out2 = {};
|
|
136363
136359
|
const sparse = !!ns.getMergedTraits().sparse;
|
|
@@ -136367,7 +136363,7 @@ var require_protocols2 = __commonJS2((exports, module2) => {
|
|
|
136367
136363
|
}
|
|
136368
136364
|
}
|
|
136369
136365
|
return out2;
|
|
136370
|
-
} else if (ns.isStructSchema() &&
|
|
136366
|
+
} else if (ns.isStructSchema() && isObject4) {
|
|
136371
136367
|
const out2 = {};
|
|
136372
136368
|
for (const [memberName, memberSchema] of ns.structIterator()) {
|
|
136373
136369
|
const fromKey = this.settings.jsonName ? memberSchema.getMergedTraits().jsonName ?? memberName : memberName;
|
|
@@ -136499,7 +136495,7 @@ var require_protocols2 = __commonJS2((exports, module2) => {
|
|
|
136499
136495
|
return this.buffer;
|
|
136500
136496
|
}
|
|
136501
136497
|
_write(schema4, value, container) {
|
|
136502
|
-
const
|
|
136498
|
+
const isObject4 = value !== null && typeof value === "object";
|
|
136503
136499
|
const ns = import_schema22.NormalizedSchema.of(schema4);
|
|
136504
136500
|
if (ns.isListSchema() && Array.isArray(value)) {
|
|
136505
136501
|
const listMember = ns.getValueSchema();
|
|
@@ -136511,7 +136507,7 @@ var require_protocols2 = __commonJS2((exports, module2) => {
|
|
|
136511
136507
|
}
|
|
136512
136508
|
}
|
|
136513
136509
|
return out2;
|
|
136514
|
-
} else if (ns.isMapSchema() &&
|
|
136510
|
+
} else if (ns.isMapSchema() && isObject4) {
|
|
136515
136511
|
const mapMember = ns.getValueSchema();
|
|
136516
136512
|
const out2 = {};
|
|
136517
136513
|
const sparse = !!ns.getMergedTraits().sparse;
|
|
@@ -136521,7 +136517,7 @@ var require_protocols2 = __commonJS2((exports, module2) => {
|
|
|
136521
136517
|
}
|
|
136522
136518
|
}
|
|
136523
136519
|
return out2;
|
|
136524
|
-
} else if (ns.isStructSchema() &&
|
|
136520
|
+
} else if (ns.isStructSchema() && isObject4) {
|
|
136525
136521
|
const out2 = {};
|
|
136526
136522
|
for (const [memberName, memberSchema] of ns.structIterator()) {
|
|
136527
136523
|
const targetKey = this.settings.jsonName ? memberSchema.getMergedTraits().jsonName ?? memberName : memberName;
|
|
@@ -143953,16 +143949,16 @@ var require_dist_cjs52 = __commonJS2((exports, module2) => {
|
|
|
143953
143949
|
var getProfileName = /* @__PURE__ */ __name((init3) => init3.profile || process.env[ENV_PROFILE] || DEFAULT_PROFILE, "getProfileName");
|
|
143954
143950
|
__reExport(src_exports, require_getSSOTokenFilepath(), module2.exports);
|
|
143955
143951
|
__reExport(src_exports, require_getSSOTokenFromFile(), module2.exports);
|
|
143956
|
-
var
|
|
143952
|
+
var import_types6 = require_dist_cjs();
|
|
143957
143953
|
var getConfigData = /* @__PURE__ */ __name((data) => Object.entries(data).filter(([key]) => {
|
|
143958
143954
|
const indexOfSeparator = key.indexOf(CONFIG_PREFIX_SEPARATOR);
|
|
143959
143955
|
if (indexOfSeparator === -1) {
|
|
143960
143956
|
return false;
|
|
143961
143957
|
}
|
|
143962
|
-
return Object.values(
|
|
143958
|
+
return Object.values(import_types6.IniSectionType).includes(key.substring(0, indexOfSeparator));
|
|
143963
143959
|
}).reduce((acc, [key, value]) => {
|
|
143964
143960
|
const indexOfSeparator = key.indexOf(CONFIG_PREFIX_SEPARATOR);
|
|
143965
|
-
const updatedKey = key.substring(0, indexOfSeparator) ===
|
|
143961
|
+
const updatedKey = key.substring(0, indexOfSeparator) === import_types6.IniSectionType.PROFILE ? key.substring(indexOfSeparator + 1) : key;
|
|
143966
143962
|
acc[updatedKey] = value;
|
|
143967
143963
|
return acc;
|
|
143968
143964
|
}, {
|
|
@@ -143992,7 +143988,7 @@ var require_dist_cjs52 = __commonJS2((exports, module2) => {
|
|
|
143992
143988
|
const matches = prefixKeyRegex.exec(sectionName);
|
|
143993
143989
|
if (matches) {
|
|
143994
143990
|
const [, prefix2, , name4] = matches;
|
|
143995
|
-
if (Object.values(
|
|
143991
|
+
if (Object.values(import_types6.IniSectionType).includes(prefix2)) {
|
|
143996
143992
|
currentSection = [prefix2, name4].join(CONFIG_PREFIX_SEPARATOR);
|
|
143997
143993
|
}
|
|
143998
143994
|
} else {
|
|
@@ -144051,7 +144047,7 @@ var require_dist_cjs52 = __commonJS2((exports, module2) => {
|
|
|
144051
144047
|
credentialsFile: parsedFiles[1]
|
|
144052
144048
|
};
|
|
144053
144049
|
}, "loadSharedConfigFiles");
|
|
144054
|
-
var getSsoSessionData = /* @__PURE__ */ __name((data) => Object.entries(data).filter(([key]) => key.startsWith(
|
|
144050
|
+
var getSsoSessionData = /* @__PURE__ */ __name((data) => Object.entries(data).filter(([key]) => key.startsWith(import_types6.IniSectionType.SSO_SESSION + CONFIG_PREFIX_SEPARATOR)).reduce((acc, [key, value]) => ({ ...acc, [key.substring(key.indexOf(CONFIG_PREFIX_SEPARATOR) + 1)]: value }), {}), "getSsoSessionData");
|
|
144055
144051
|
var import_slurpFile2 = require_slurpFile();
|
|
144056
144052
|
var swallowError2 = /* @__PURE__ */ __name(() => ({}), "swallowError");
|
|
144057
144053
|
var loadSsoSessionData = /* @__PURE__ */ __name(async (init3 = {}) => (0, import_slurpFile2.slurpFile)(init3.configFilepath ?? getConfigFilepath()).then(parseIni).then(getSsoSessionData).catch(swallowError2), "loadSsoSessionData");
|
|
@@ -144094,7 +144090,7 @@ var require_dist_cjs53 = __commonJS2((exports, module2) => {
|
|
|
144094
144090
|
var __toCommonJS = (mod) => __copyProps2(__defProp4({}, "__esModule", { value: true }), mod);
|
|
144095
144091
|
var src_exports = {};
|
|
144096
144092
|
__export4(src_exports, {
|
|
144097
|
-
loadConfig: () =>
|
|
144093
|
+
loadConfig: () => loadConfig
|
|
144098
144094
|
});
|
|
144099
144095
|
module2.exports = __toCommonJS(src_exports);
|
|
144100
144096
|
var import_property_provider = require_dist_cjs17();
|
|
@@ -144141,7 +144137,7 @@ var require_dist_cjs53 = __commonJS2((exports, module2) => {
|
|
|
144141
144137
|
}, "fromSharedConfigFiles");
|
|
144142
144138
|
var isFunction3 = /* @__PURE__ */ __name((func2) => typeof func2 === "function", "isFunction");
|
|
144143
144139
|
var fromStatic = /* @__PURE__ */ __name((defaultValue) => isFunction3(defaultValue) ? async () => await defaultValue() : (0, import_property_provider.fromStatic)(defaultValue), "fromStatic");
|
|
144144
|
-
var
|
|
144140
|
+
var loadConfig = /* @__PURE__ */ __name(({ environmentVariableSelector, configFileSelector, default: defaultValue }, configuration = {}) => {
|
|
144145
144141
|
const { signingName, logger: logger3 } = configuration;
|
|
144146
144142
|
const envOptions = { signingName, logger: logger3 };
|
|
144147
144143
|
return (0, import_property_provider.memoize)((0, import_property_provider.chain)(fromEnv(environmentVariableSelector, envOptions), fromSharedConfigFiles(configFileSelector, configuration), fromStatic(defaultValue)));
|
|
@@ -145028,7 +145024,7 @@ var require_dist_cjs57 = __commonJS2((exports, module2) => {
|
|
|
145028
145024
|
fromEnv: () => fromEnv
|
|
145029
145025
|
});
|
|
145030
145026
|
module2.exports = __toCommonJS(index_exports);
|
|
145031
|
-
var
|
|
145027
|
+
var import_client2 = require_client();
|
|
145032
145028
|
var import_property_provider = require_dist_cjs17();
|
|
145033
145029
|
var ENV_KEY = "AWS_ACCESS_KEY_ID";
|
|
145034
145030
|
var ENV_SECRET = "AWS_SECRET_ACCESS_KEY";
|
|
@@ -145053,7 +145049,7 @@ var require_dist_cjs57 = __commonJS2((exports, module2) => {
|
|
|
145053
145049
|
...credentialScope && { credentialScope },
|
|
145054
145050
|
...accountId && { accountId }
|
|
145055
145051
|
};
|
|
145056
|
-
(0,
|
|
145052
|
+
(0, import_client2.setCredentialFeature)(credentials2, "CREDENTIALS_ENV_VARS", "g");
|
|
145057
145053
|
return credentials2;
|
|
145058
145054
|
}
|
|
145059
145055
|
throw new import_property_provider.CredentialsProviderError("Unable to find environment variable credentials.", { logger: init3?.logger });
|
|
@@ -147821,11 +147817,11 @@ var require_dist_cjs66 = __commonJS2((exports, module2) => {
|
|
|
147821
147817
|
}, "validateTokenKey");
|
|
147822
147818
|
var import_shared_ini_file_loader = require_dist_cjs52();
|
|
147823
147819
|
var import_fs2 = __require2("fs");
|
|
147824
|
-
var { writeFile
|
|
147820
|
+
var { writeFile } = import_fs2.promises;
|
|
147825
147821
|
var writeSSOTokenToFile = /* @__PURE__ */ __name((id, ssoToken) => {
|
|
147826
147822
|
const tokenFilepath = (0, import_shared_ini_file_loader.getSSOTokenFilepath)(id);
|
|
147827
147823
|
const tokenString = JSON.stringify(ssoToken, null, 2);
|
|
147828
|
-
return
|
|
147824
|
+
return writeFile(tokenFilepath, tokenString);
|
|
147829
147825
|
}, "writeSSOTokenToFile");
|
|
147830
147826
|
var lastRefreshAttemptTime = /* @__PURE__ */ new Date(0);
|
|
147831
147827
|
var fromSso = /* @__PURE__ */ __name((_init = {}) => async ({ callerClientConfig } = {}) => {
|
|
@@ -147920,7 +147916,7 @@ var require_dist_cjs67 = __commonJS2((exports, module2) => {
|
|
|
147920
147916
|
var __getOwnPropNames3 = Object.getOwnPropertyNames;
|
|
147921
147917
|
var __hasOwnProp3 = Object.prototype.hasOwnProperty;
|
|
147922
147918
|
var __name = (target, value) => __defProp4(target, "name", { value, configurable: true });
|
|
147923
|
-
var
|
|
147919
|
+
var __esm5 = (fn2, res) => function __init() {
|
|
147924
147920
|
return fn2 && (res = (0, fn2[__getOwnPropNames3(fn2)[0]])(fn2 = 0)), res;
|
|
147925
147921
|
};
|
|
147926
147922
|
var __export4 = (target, all) => {
|
|
@@ -147942,7 +147938,7 @@ var require_dist_cjs67 = __commonJS2((exports, module2) => {
|
|
|
147942
147938
|
SSOClient: () => import_client_sso.SSOClient
|
|
147943
147939
|
});
|
|
147944
147940
|
var import_client_sso;
|
|
147945
|
-
var init_loadSso =
|
|
147941
|
+
var init_loadSso = __esm5({
|
|
147946
147942
|
"src/loadSso.ts"() {
|
|
147947
147943
|
import_client_sso = require_dist_cjs65();
|
|
147948
147944
|
}
|
|
@@ -147955,7 +147951,7 @@ var require_dist_cjs67 = __commonJS2((exports, module2) => {
|
|
|
147955
147951
|
});
|
|
147956
147952
|
module2.exports = __toCommonJS(index_exports);
|
|
147957
147953
|
var isSsoProfile = /* @__PURE__ */ __name((arg) => arg && (typeof arg.sso_start_url === "string" || typeof arg.sso_account_id === "string" || typeof arg.sso_session === "string" || typeof arg.sso_region === "string" || typeof arg.sso_role_name === "string"), "isSsoProfile");
|
|
147958
|
-
var
|
|
147954
|
+
var import_client2 = require_client();
|
|
147959
147955
|
var import_token_providers = require_dist_cjs66();
|
|
147960
147956
|
var import_property_provider = require_dist_cjs17();
|
|
147961
147957
|
var import_shared_ini_file_loader = require_dist_cjs52();
|
|
@@ -148040,9 +148036,9 @@ var require_dist_cjs67 = __commonJS2((exports, module2) => {
|
|
|
148040
148036
|
...accountId && { accountId }
|
|
148041
148037
|
};
|
|
148042
148038
|
if (ssoSession) {
|
|
148043
|
-
(0,
|
|
148039
|
+
(0, import_client2.setCredentialFeature)(credentials2, "CREDENTIALS_SSO", "s");
|
|
148044
148040
|
} else {
|
|
148045
|
-
(0,
|
|
148041
|
+
(0, import_client2.setCredentialFeature)(credentials2, "CREDENTIALS_SSO_LEGACY", "u");
|
|
148046
148042
|
}
|
|
148047
148043
|
return credentials2;
|
|
148048
148044
|
}, "resolveSSOCredentials");
|
|
@@ -149222,7 +149218,7 @@ var require_sts = __commonJS2((exports, module2) => {
|
|
|
149222
149218
|
};
|
|
149223
149219
|
(0, import_smithy_client6.createAggregatedClient)(commands, STS);
|
|
149224
149220
|
var import_EndpointParameters3 = require_EndpointParameters();
|
|
149225
|
-
var
|
|
149221
|
+
var import_client2 = require_client();
|
|
149226
149222
|
var ASSUME_ROLE_DEFAULT_REGION = "us-east-1";
|
|
149227
149223
|
var getAccountIdFromAssumedRoleUser = /* @__PURE__ */ __name((assumedRoleUser) => {
|
|
149228
149224
|
if (typeof assumedRoleUser?.Arn === "string") {
|
|
@@ -149274,7 +149270,7 @@ var require_sts = __commonJS2((exports, module2) => {
|
|
|
149274
149270
|
...Credentials2.CredentialScope && { credentialScope: Credentials2.CredentialScope },
|
|
149275
149271
|
...accountId && { accountId }
|
|
149276
149272
|
};
|
|
149277
|
-
(0,
|
|
149273
|
+
(0, import_client2.setCredentialFeature)(credentials2, "CREDENTIALS_STS_ASSUME_ROLE", "i");
|
|
149278
149274
|
return credentials2;
|
|
149279
149275
|
};
|
|
149280
149276
|
}, "getDefaultRoleAssumer");
|
|
@@ -149311,9 +149307,9 @@ var require_sts = __commonJS2((exports, module2) => {
|
|
|
149311
149307
|
...accountId && { accountId }
|
|
149312
149308
|
};
|
|
149313
149309
|
if (accountId) {
|
|
149314
|
-
(0,
|
|
149310
|
+
(0, import_client2.setCredentialFeature)(credentials2, "RESOLVED_ACCOUNT_ID", "T");
|
|
149315
149311
|
}
|
|
149316
|
-
(0,
|
|
149312
|
+
(0, import_client2.setCredentialFeature)(credentials2, "CREDENTIALS_STS_ASSUME_ROLE_WEB_ID", "k");
|
|
149317
149313
|
return credentials2;
|
|
149318
149314
|
};
|
|
149319
149315
|
}, "getDefaultRoleAssumerWithWebIdentity");
|
|
@@ -149373,7 +149369,7 @@ var require_dist_cjs68 = __commonJS2((exports, module2) => {
|
|
|
149373
149369
|
var import_property_provider = require_dist_cjs17();
|
|
149374
149370
|
var import_child_process = __require2("child_process");
|
|
149375
149371
|
var import_util3 = __require2("util");
|
|
149376
|
-
var
|
|
149372
|
+
var import_client2 = require_client();
|
|
149377
149373
|
var getValidatedProcessCredentials = /* @__PURE__ */ __name((profileName, data, profiles) => {
|
|
149378
149374
|
if (data.Version !== 1) {
|
|
149379
149375
|
throw Error(`Profile ${profileName} credential_process did not return Version 1.`);
|
|
@@ -149400,7 +149396,7 @@ var require_dist_cjs68 = __commonJS2((exports, module2) => {
|
|
|
149400
149396
|
...data.CredentialScope && { credentialScope: data.CredentialScope },
|
|
149401
149397
|
...accountId && { accountId }
|
|
149402
149398
|
};
|
|
149403
|
-
(0,
|
|
149399
|
+
(0, import_client2.setCredentialFeature)(credentials2, "CREDENTIALS_PROCESS", "w");
|
|
149404
149400
|
return credentials2;
|
|
149405
149401
|
}, "getValidatedProcessCredentials");
|
|
149406
149402
|
var resolveProcessCredentials = /* @__PURE__ */ __name(async (profileName, profiles, logger3) => {
|
|
@@ -149593,7 +149589,7 @@ var require_dist_cjs70 = __commonJS2((exports, module2) => {
|
|
|
149593
149589
|
});
|
|
149594
149590
|
module2.exports = __toCommonJS(index_exports);
|
|
149595
149591
|
var import_shared_ini_file_loader = require_dist_cjs52();
|
|
149596
|
-
var
|
|
149592
|
+
var import_client2 = require_client();
|
|
149597
149593
|
var import_property_provider = require_dist_cjs17();
|
|
149598
149594
|
var resolveCredentialSource = /* @__PURE__ */ __name((credentialSource, profileName, logger3) => {
|
|
149599
149595
|
const sourceProvidersMap = {
|
|
@@ -149620,7 +149616,7 @@ var require_dist_cjs70 = __commonJS2((exports, module2) => {
|
|
|
149620
149616
|
throw new import_property_provider.CredentialsProviderError(`Unsupported credential source in profile ${profileName}. Got ${credentialSource}, expected EcsContainer or Ec2InstanceMetadata or Environment.`, { logger: logger3 });
|
|
149621
149617
|
}
|
|
149622
149618
|
}, "resolveCredentialSource");
|
|
149623
|
-
var setNamedProvider = /* @__PURE__ */ __name((creds) => (0,
|
|
149619
|
+
var setNamedProvider = /* @__PURE__ */ __name((creds) => (0, import_client2.setCredentialFeature)(creds, "CREDENTIALS_PROFILE_NAMED_PROVIDER", "p"), "setNamedProvider");
|
|
149624
149620
|
var isAssumeRoleProfile = /* @__PURE__ */ __name((arg, { profile = "default", logger: logger3 } = {}) => {
|
|
149625
149621
|
return Boolean(arg) && typeof arg === "object" && typeof arg.role_arn === "string" && ["undefined", "string"].indexOf(typeof arg.role_session_name) > -1 && ["undefined", "string"].indexOf(typeof arg.external_id) > -1 && ["undefined", "string"].indexOf(typeof arg.mfa_serial) > -1 && (isAssumeRoleWithSourceProfile(arg, { profile, logger: logger3 }) || isCredentialSourceProfile(arg, { profile, logger: logger3 }));
|
|
149626
149622
|
}, "isAssumeRoleProfile");
|
|
@@ -149662,7 +149658,7 @@ var require_dist_cjs70 = __commonJS2((exports, module2) => {
|
|
|
149662
149658
|
[source_profile]: true
|
|
149663
149659
|
}, isCredentialSourceWithoutRoleArn(profiles[source_profile] ?? {})) : (await resolveCredentialSource(profileData.credential_source, profileName, options.logger)(options))();
|
|
149664
149660
|
if (isCredentialSourceWithoutRoleArn(profileData)) {
|
|
149665
|
-
return sourceCredsProvider.then((creds) => (0,
|
|
149661
|
+
return sourceCredsProvider.then((creds) => (0, import_client2.setCredentialFeature)(creds, "CREDENTIALS_PROFILE_SOURCE_PROFILE", "o"));
|
|
149666
149662
|
} else {
|
|
149667
149663
|
const params = {
|
|
149668
149664
|
RoleArn: profileData.role_arn,
|
|
@@ -149679,7 +149675,7 @@ var require_dist_cjs70 = __commonJS2((exports, module2) => {
|
|
|
149679
149675
|
params.TokenCode = await options.mfaCodeProvider(mfa_serial);
|
|
149680
149676
|
}
|
|
149681
149677
|
const sourceCreds = await sourceCredsProvider;
|
|
149682
|
-
return options.roleAssumer(sourceCreds, params).then((creds) => (0,
|
|
149678
|
+
return options.roleAssumer(sourceCreds, params).then((creds) => (0, import_client2.setCredentialFeature)(creds, "CREDENTIALS_PROFILE_SOURCE_PROFILE", "o"));
|
|
149683
149679
|
}
|
|
149684
149680
|
}, "resolveAssumeRoleCredentials");
|
|
149685
149681
|
var isCredentialSourceWithoutRoleArn = /* @__PURE__ */ __name((section) => {
|
|
@@ -149689,7 +149685,7 @@ var require_dist_cjs70 = __commonJS2((exports, module2) => {
|
|
|
149689
149685
|
var resolveProcessCredentials = /* @__PURE__ */ __name(async (options, profile) => Promise.resolve().then(() => __toESM3(require_dist_cjs68())).then(({ fromProcess }) => fromProcess({
|
|
149690
149686
|
...options,
|
|
149691
149687
|
profile
|
|
149692
|
-
})().then((creds) => (0,
|
|
149688
|
+
})().then((creds) => (0, import_client2.setCredentialFeature)(creds, "CREDENTIALS_PROFILE_PROCESS", "v"))), "resolveProcessCredentials");
|
|
149693
149689
|
var resolveSsoCredentials = /* @__PURE__ */ __name(async (profile, profileData, options = {}) => {
|
|
149694
149690
|
const { fromSSO } = await Promise.resolve().then(() => __toESM3(require_dist_cjs67()));
|
|
149695
149691
|
return fromSSO({
|
|
@@ -149699,9 +149695,9 @@ var require_dist_cjs70 = __commonJS2((exports, module2) => {
|
|
|
149699
149695
|
clientConfig: options.clientConfig
|
|
149700
149696
|
})().then((creds) => {
|
|
149701
149697
|
if (profileData.sso_session) {
|
|
149702
|
-
return (0,
|
|
149698
|
+
return (0, import_client2.setCredentialFeature)(creds, "CREDENTIALS_PROFILE_SSO", "r");
|
|
149703
149699
|
} else {
|
|
149704
|
-
return (0,
|
|
149700
|
+
return (0, import_client2.setCredentialFeature)(creds, "CREDENTIALS_PROFILE_SSO_LEGACY", "t");
|
|
149705
149701
|
}
|
|
149706
149702
|
});
|
|
149707
149703
|
}, "resolveSsoCredentials");
|
|
@@ -149716,7 +149712,7 @@ var require_dist_cjs70 = __commonJS2((exports, module2) => {
|
|
|
149716
149712
|
...profile.aws_credential_scope && { credentialScope: profile.aws_credential_scope },
|
|
149717
149713
|
...profile.aws_account_id && { accountId: profile.aws_account_id }
|
|
149718
149714
|
};
|
|
149719
|
-
return (0,
|
|
149715
|
+
return (0, import_client2.setCredentialFeature)(credentials2, "CREDENTIALS_PROFILE", "n");
|
|
149720
149716
|
}, "resolveStaticCredentials");
|
|
149721
149717
|
var isWebIdentityProfile = /* @__PURE__ */ __name((arg) => Boolean(arg) && typeof arg === "object" && typeof arg.web_identity_token_file === "string" && typeof arg.role_arn === "string" && ["undefined", "string"].indexOf(typeof arg.role_session_name) > -1, "isWebIdentityProfile");
|
|
149722
149718
|
var resolveWebIdentityCredentials = /* @__PURE__ */ __name(async (profile, options) => Promise.resolve().then(() => __toESM3(require_dist_cjs69())).then(({ fromTokenFile: fromTokenFile2 }) => fromTokenFile2({
|
|
@@ -149726,7 +149722,7 @@ var require_dist_cjs70 = __commonJS2((exports, module2) => {
|
|
|
149726
149722
|
roleAssumerWithWebIdentity: options.roleAssumerWithWebIdentity,
|
|
149727
149723
|
logger: options.logger,
|
|
149728
149724
|
parentClientConfig: options.parentClientConfig
|
|
149729
|
-
})().then((creds) => (0,
|
|
149725
|
+
})().then((creds) => (0, import_client2.setCredentialFeature)(creds, "CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN", "q"))), "resolveWebIdentityCredentials");
|
|
149730
149726
|
var resolveProfileData = /* @__PURE__ */ __name(async (profileName, profiles, options, visitedProfiles = {}, isAssumeRoleRecursiveCall = false) => {
|
|
149731
149727
|
const data = profiles[profileName];
|
|
149732
149728
|
if (Object.keys(visitedProfiles).length > 0 && isStaticCredsProfile(data)) {
|
|
@@ -168490,7 +168486,7 @@ var require_lodash2 = __commonJS2((exports, module2) => {
|
|
|
168490
168486
|
}
|
|
168491
168487
|
}
|
|
168492
168488
|
function baseKeysIn(object) {
|
|
168493
|
-
if (!
|
|
168489
|
+
if (!isObject4(object)) {
|
|
168494
168490
|
return nativeKeysIn(object);
|
|
168495
168491
|
}
|
|
168496
168492
|
var isProto = isPrototype(object), result = [];
|
|
@@ -168550,7 +168546,7 @@ var require_lodash2 = __commonJS2((exports, module2) => {
|
|
|
168550
168546
|
return !!length && (typeof value == "number" || reIsUint.test(value)) && (value > -1 && value % 1 == 0 && value < length);
|
|
168551
168547
|
}
|
|
168552
168548
|
function isIterateeCall(value, index6, object) {
|
|
168553
|
-
if (!
|
|
168549
|
+
if (!isObject4(object)) {
|
|
168554
168550
|
return false;
|
|
168555
168551
|
}
|
|
168556
168552
|
var type = typeof index6;
|
|
@@ -168586,13 +168582,13 @@ var require_lodash2 = __commonJS2((exports, module2) => {
|
|
|
168586
168582
|
return isObjectLike2(value) && isArrayLike(value);
|
|
168587
168583
|
}
|
|
168588
168584
|
function isFunction3(value) {
|
|
168589
|
-
var tag2 =
|
|
168585
|
+
var tag2 = isObject4(value) ? objectToString.call(value) : "";
|
|
168590
168586
|
return tag2 == funcTag || tag2 == genTag;
|
|
168591
168587
|
}
|
|
168592
168588
|
function isLength(value) {
|
|
168593
168589
|
return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
|
|
168594
168590
|
}
|
|
168595
|
-
function
|
|
168591
|
+
function isObject4(value) {
|
|
168596
168592
|
var type = typeof value;
|
|
168597
168593
|
return !!value && (type == "object" || type == "function");
|
|
168598
168594
|
}
|
|
@@ -168630,13 +168626,13 @@ var require_lodash3 = __commonJS2((exports, module2) => {
|
|
|
168630
168626
|
return isObjectLike2(value) && isArrayLike(value);
|
|
168631
168627
|
}
|
|
168632
168628
|
function isFunction3(value) {
|
|
168633
|
-
var tag2 =
|
|
168629
|
+
var tag2 = isObject4(value) ? objectToString.call(value) : "";
|
|
168634
168630
|
return tag2 == funcTag || tag2 == genTag;
|
|
168635
168631
|
}
|
|
168636
168632
|
function isLength(value) {
|
|
168637
168633
|
return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
|
|
168638
168634
|
}
|
|
168639
|
-
function
|
|
168635
|
+
function isObject4(value) {
|
|
168640
168636
|
var type = typeof value;
|
|
168641
168637
|
return !!value && (type == "object" || type == "function");
|
|
168642
168638
|
}
|
|
@@ -173727,7 +173723,7 @@ var REDIS_PRESENCE_KEY_PREFIX;
|
|
|
173727
173723
|
var REDIS_ONLINE_USERS_KEY;
|
|
173728
173724
|
var REDIS_POSITION_KEY_PREFIX;
|
|
173729
173725
|
var REDIS_MAP_PLAYERS_KEY_PREFIX;
|
|
173730
|
-
var
|
|
173726
|
+
var init_constants3 = __esm(() => {
|
|
173731
173727
|
HUB_PREFIX = process.env.HUB_PREFIX ?? "hub:";
|
|
173732
173728
|
MAP_PREFIX = process.env.MAP_PREFIX ?? "map_";
|
|
173733
173729
|
PRESENCE_CHANNEL_NAME = process.env.PRESENCE_CHANNEL_NAME ?? "presence";
|
|
@@ -173875,7 +173871,7 @@ var import_ioredis;
|
|
|
173875
173871
|
var client = null;
|
|
173876
173872
|
var init_client = __esm(() => {
|
|
173877
173873
|
init_src();
|
|
173878
|
-
|
|
173874
|
+
init_constants3();
|
|
173879
173875
|
import_ioredis = __toESM2(require_built3(), 1);
|
|
173880
173876
|
});
|
|
173881
173877
|
async function setUserOnline(userId, metadata2) {
|
|
@@ -173986,7 +173982,7 @@ async function updateUserNameplateBg(userId, color) {
|
|
|
173986
173982
|
}
|
|
173987
173983
|
var init_presence = __esm(() => {
|
|
173988
173984
|
init_src();
|
|
173989
|
-
|
|
173985
|
+
init_constants3();
|
|
173990
173986
|
init_client();
|
|
173991
173987
|
});
|
|
173992
173988
|
var init_redis = __esm(() => {
|
|
@@ -174031,11 +174027,11 @@ function extractTokenFromUrl(url) {
|
|
|
174031
174027
|
return null;
|
|
174032
174028
|
}
|
|
174033
174029
|
}
|
|
174034
|
-
var
|
|
174030
|
+
var init_auth3 = __esm(() => {
|
|
174035
174031
|
init_esm2();
|
|
174036
174032
|
init_src();
|
|
174037
174033
|
});
|
|
174038
|
-
function
|
|
174034
|
+
function loadConfig(options = {}) {
|
|
174039
174035
|
const rawRedisHost = process.env.REDIS_HOST || "localhost";
|
|
174040
174036
|
const rawRedisPort = parseInt(process.env.REDIS_PORT || "6379", 10);
|
|
174041
174037
|
const rawRedisPassword = process.env.REDIS_PASSWORD;
|
|
@@ -174080,7 +174076,7 @@ __export(exports_sandbox, {
|
|
|
174080
174076
|
createSandboxRealtimeServer: () => createSandboxRealtimeServer
|
|
174081
174077
|
});
|
|
174082
174078
|
async function createSandboxRealtimeServer(options = {}) {
|
|
174083
|
-
const config2 = await
|
|
174079
|
+
const config2 = await loadConfig(options);
|
|
174084
174080
|
const httpServer = http.createServer((req, res) => {
|
|
174085
174081
|
if (req.url?.endsWith(config2.healthCheckPath)) {
|
|
174086
174082
|
const body2 = JSON.stringify({
|
|
@@ -174162,7 +174158,7 @@ var init_sandbox = __esm(() => {
|
|
|
174162
174158
|
init_wrapper();
|
|
174163
174159
|
init_src();
|
|
174164
174160
|
init_infrastructure2();
|
|
174165
|
-
|
|
174161
|
+
init_auth3();
|
|
174166
174162
|
init_config4();
|
|
174167
174163
|
});
|
|
174168
174164
|
var inMemoryUsers;
|
|
@@ -174248,7 +174244,7 @@ var playerPositions;
|
|
|
174248
174244
|
var PlayerPositionService;
|
|
174249
174245
|
var init_player_position = __esm(() => {
|
|
174250
174246
|
init_src();
|
|
174251
|
-
|
|
174247
|
+
init_constants3();
|
|
174252
174248
|
init_infrastructure2();
|
|
174253
174249
|
playerPositions = new Map;
|
|
174254
174250
|
PlayerPositionService = {
|
|
@@ -174378,7 +174374,7 @@ function computeInitialChannelKey(gameId, requested) {
|
|
|
174378
174374
|
return `${HUB_PREFIX}${channel}`;
|
|
174379
174375
|
}
|
|
174380
174376
|
var init_channel_keys = __esm(() => {
|
|
174381
|
-
|
|
174377
|
+
init_constants3();
|
|
174382
174378
|
});
|
|
174383
174379
|
function ensureAuthenticated(ws) {
|
|
174384
174380
|
if (!ws.data.isAuthenticated || !ws.data.userId) {
|
|
@@ -174397,7 +174393,7 @@ function checkMatchingPlayerId(ws, payload) {
|
|
|
174397
174393
|
}
|
|
174398
174394
|
var init_websocket = __esm(() => {
|
|
174399
174395
|
init_src();
|
|
174400
|
-
|
|
174396
|
+
init_constants3();
|
|
174401
174397
|
});
|
|
174402
174398
|
function extractUserId(pathname) {
|
|
174403
174399
|
const match2 = pathname.match(/^\/presence\/([^/]+)$/);
|
|
@@ -174733,7 +174729,7 @@ async function handleWebSocketUpgrade(req, server, config2) {
|
|
|
174733
174729
|
}
|
|
174734
174730
|
var init_websocket2 = __esm(() => {
|
|
174735
174731
|
init_src();
|
|
174736
|
-
|
|
174732
|
+
init_auth3();
|
|
174737
174733
|
init_response();
|
|
174738
174734
|
});
|
|
174739
174735
|
var init_http2 = __esm(() => {
|
|
@@ -174912,7 +174908,7 @@ var init_open = __esm(() => {
|
|
|
174912
174908
|
init_src();
|
|
174913
174909
|
init_presence4();
|
|
174914
174910
|
init_services2();
|
|
174915
|
-
|
|
174911
|
+
init_constants3();
|
|
174916
174912
|
init_events();
|
|
174917
174913
|
init_infrastructure2();
|
|
174918
174914
|
init_utils13();
|
|
@@ -175136,7 +175132,7 @@ var init_websocket3 = __esm(() => {
|
|
|
175136
175132
|
init_close();
|
|
175137
175133
|
});
|
|
175138
175134
|
async function createRealtimeServer(options = {}) {
|
|
175139
|
-
const config2 =
|
|
175135
|
+
const config2 = loadConfig(options);
|
|
175140
175136
|
const { redisEnabled, positionSyncInterval } = await initializeServer(config2);
|
|
175141
175137
|
const server = Bun.serve({
|
|
175142
175138
|
port: config2.port,
|
|
@@ -178272,7 +178268,7 @@ function sql(strings, ...params) {
|
|
|
178272
178268
|
return new SQL([new StringChunk(str)]);
|
|
178273
178269
|
}
|
|
178274
178270
|
sql22.raw = raw2;
|
|
178275
|
-
function
|
|
178271
|
+
function join5(chunks, separator) {
|
|
178276
178272
|
const result = [];
|
|
178277
178273
|
for (const [i22, chunk] of chunks.entries()) {
|
|
178278
178274
|
if (i22 > 0 && separator !== undefined) {
|
|
@@ -178282,7 +178278,7 @@ function sql(strings, ...params) {
|
|
|
178282
178278
|
}
|
|
178283
178279
|
return new SQL(result);
|
|
178284
178280
|
}
|
|
178285
|
-
sql22.join =
|
|
178281
|
+
sql22.join = join5;
|
|
178286
178282
|
function identifier(value) {
|
|
178287
178283
|
return new Name(value);
|
|
178288
178284
|
}
|
|
@@ -181195,7 +181191,7 @@ class PgSelectQueryBuilderBase extends TypedQueryBuilder {
|
|
|
181195
181191
|
return (table, on) => {
|
|
181196
181192
|
const baseTableName = this.tableName;
|
|
181197
181193
|
const tableName = getTableLikeName(table);
|
|
181198
|
-
if (typeof tableName === "string" && this.config.joins?.some((
|
|
181194
|
+
if (typeof tableName === "string" && this.config.joins?.some((join5) => join5.alias === tableName)) {
|
|
181199
181195
|
throw new Error(`Alias "${tableName}" is already used in this query`);
|
|
181200
181196
|
}
|
|
181201
181197
|
if (!this.isPartialSelect) {
|
|
@@ -181700,7 +181696,7 @@ class PgUpdateBase extends QueryPromise {
|
|
|
181700
181696
|
createJoin(joinType) {
|
|
181701
181697
|
return (table, on) => {
|
|
181702
181698
|
const tableName = getTableLikeName(table);
|
|
181703
|
-
if (typeof tableName === "string" && this.config.joins.some((
|
|
181699
|
+
if (typeof tableName === "string" && this.config.joins.some((join5) => join5.alias === tableName)) {
|
|
181704
181700
|
throw new Error(`Alias "${tableName}" is already used in this query`);
|
|
181705
181701
|
}
|
|
181706
181702
|
if (typeof on === "function") {
|
|
@@ -181750,10 +181746,10 @@ class PgUpdateBase extends QueryPromise {
|
|
|
181750
181746
|
const fromFields = this.getTableLikeFields(this.config.from);
|
|
181751
181747
|
fields[tableName] = fromFields;
|
|
181752
181748
|
}
|
|
181753
|
-
for (const
|
|
181754
|
-
const tableName2 = getTableLikeName(
|
|
181755
|
-
if (typeof tableName2 === "string" && !is(
|
|
181756
|
-
const fromFields = this.getTableLikeFields(
|
|
181749
|
+
for (const join5 of this.config.joins) {
|
|
181750
|
+
const tableName2 = getTableLikeName(join5.table);
|
|
181751
|
+
if (typeof tableName2 === "string" && !is(join5.table, SQL)) {
|
|
181752
|
+
const fromFields = this.getTableLikeFields(join5.table);
|
|
181757
181753
|
fields[tableName2] = fromFields;
|
|
181758
181754
|
}
|
|
181759
181755
|
}
|
|
@@ -182754,12 +182750,17 @@ var timebackXpEvents = pgTable("timeback_xp_event", {
|
|
|
182754
182750
|
}, (table) => [uniqueIndex("timeback_xp_events_source_id_idx").on(table.source, table.sourceId)]);
|
|
182755
182751
|
var gameTimebackIntegrations = pgTable("game_timeback_integrations", {
|
|
182756
182752
|
id: uuid("id").primaryKey().defaultRandom(),
|
|
182757
|
-
gameId: uuid("game_id").notNull().
|
|
182753
|
+
gameId: uuid("game_id").notNull().references(() => games.id, { onDelete: "cascade" }),
|
|
182758
182754
|
courseId: text("course_id").notNull(),
|
|
182755
|
+
grade: integer("grade").notNull(),
|
|
182756
|
+
subject: text("subject").notNull(),
|
|
182757
|
+
totalXp: integer("total_xp"),
|
|
182759
182758
|
lastVerifiedAt: timestamp("last_verified_at", { withTimezone: true }),
|
|
182760
182759
|
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
182761
182760
|
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
182762
|
-
})
|
|
182761
|
+
}, (table) => [
|
|
182762
|
+
uniqueIndex("game_timeback_integrations_game_grade_subject_idx").on(table.gameId, table.grade, table.subject)
|
|
182763
|
+
]);
|
|
182763
182764
|
var achievementScopeEnum = pgEnum("achievement_scope", [
|
|
182764
182765
|
"daily",
|
|
182765
182766
|
"weekly",
|
|
@@ -189296,6 +189297,290 @@ var __export3 = (target, all) => {
|
|
|
189296
189297
|
set: (newValue) => all[name3] = () => newValue
|
|
189297
189298
|
});
|
|
189298
189299
|
};
|
|
189300
|
+
var __esm3 = (fn2, res) => () => (fn2 && (res = fn2(fn2 = 0)), res);
|
|
189301
|
+
var init_auth = () => {};
|
|
189302
|
+
var PLAYCADEMY_BASE_URLS;
|
|
189303
|
+
var init_domains = __esm3(() => {
|
|
189304
|
+
PLAYCADEMY_BASE_URLS = {
|
|
189305
|
+
production: "https://hub.playcademy.net",
|
|
189306
|
+
staging: "https://hub.dev.playcademy.net"
|
|
189307
|
+
};
|
|
189308
|
+
});
|
|
189309
|
+
var init_env_vars = () => {};
|
|
189310
|
+
var ITEM_SLUGS2;
|
|
189311
|
+
var CURRENCIES2;
|
|
189312
|
+
var BADGES2;
|
|
189313
|
+
var init_overworld = __esm3(() => {
|
|
189314
|
+
ITEM_SLUGS2 = {
|
|
189315
|
+
PLAYCADEMY_CREDITS: "PLAYCADEMY_CREDITS",
|
|
189316
|
+
PLAYCADEMY_XP: "PLAYCADEMY_XP",
|
|
189317
|
+
FOUNDING_MEMBER_BADGE: "FOUNDING_MEMBER_BADGE",
|
|
189318
|
+
EARLY_ADOPTER_BADGE: "EARLY_ADOPTER_BADGE",
|
|
189319
|
+
FIRST_GAME_BADGE: "FIRST_GAME_BADGE",
|
|
189320
|
+
COMMON_SWORD: "COMMON_SWORD",
|
|
189321
|
+
SMALL_HEALTH_POTION: "SMALL_HEALTH_POTION",
|
|
189322
|
+
SMALL_BACKPACK: "SMALL_BACKPACK",
|
|
189323
|
+
LAVA_LAMP: "LAVA_LAMP",
|
|
189324
|
+
BOOMBOX: "BOOMBOX",
|
|
189325
|
+
CABIN_BED: "CABIN_BED"
|
|
189326
|
+
};
|
|
189327
|
+
CURRENCIES2 = {
|
|
189328
|
+
PRIMARY: ITEM_SLUGS2.PLAYCADEMY_CREDITS,
|
|
189329
|
+
XP: ITEM_SLUGS2.PLAYCADEMY_XP
|
|
189330
|
+
};
|
|
189331
|
+
BADGES2 = {
|
|
189332
|
+
FOUNDING_MEMBER: ITEM_SLUGS2.FOUNDING_MEMBER_BADGE,
|
|
189333
|
+
EARLY_ADOPTER: ITEM_SLUGS2.EARLY_ADOPTER_BADGE,
|
|
189334
|
+
FIRST_GAME: ITEM_SLUGS2.FIRST_GAME_BADGE
|
|
189335
|
+
};
|
|
189336
|
+
});
|
|
189337
|
+
var init_timeback = () => {};
|
|
189338
|
+
var init_workers = () => {};
|
|
189339
|
+
var init_src2 = __esm3(() => {
|
|
189340
|
+
init_auth();
|
|
189341
|
+
init_domains();
|
|
189342
|
+
init_env_vars();
|
|
189343
|
+
init_overworld();
|
|
189344
|
+
init_timeback();
|
|
189345
|
+
init_workers();
|
|
189346
|
+
});
|
|
189347
|
+
var TIMEBACK_API_URLS;
|
|
189348
|
+
var TIMEBACK_AUTH_URLS;
|
|
189349
|
+
var CALIPER_API_URLS;
|
|
189350
|
+
var ONEROSTER_ENDPOINTS;
|
|
189351
|
+
var CALIPER_ENDPOINTS;
|
|
189352
|
+
var createOneRosterUrls = (baseUrl) => {
|
|
189353
|
+
const effective = baseUrl || TIMEBACK_API_URLS.production;
|
|
189354
|
+
const base = effective.replace(/\/$/, "");
|
|
189355
|
+
return {
|
|
189356
|
+
user: (userId) => `${base}${ONEROSTER_ENDPOINTS.users}/${userId}`,
|
|
189357
|
+
course: (courseId) => `${base}${ONEROSTER_ENDPOINTS.courses}/${courseId}`,
|
|
189358
|
+
componentResource: (resourceId) => `${base}${ONEROSTER_ENDPOINTS.componentResources}/${resourceId}`
|
|
189359
|
+
};
|
|
189360
|
+
};
|
|
189361
|
+
var CALIPER_CONSTANTS;
|
|
189362
|
+
var TIMEBACK_EVENT_TYPES;
|
|
189363
|
+
var TIMEBACK_ACTIONS;
|
|
189364
|
+
var TIMEBACK_TYPES;
|
|
189365
|
+
var ACTIVITY_METRIC_TYPES;
|
|
189366
|
+
var TIME_METRIC_TYPES;
|
|
189367
|
+
var TIMEBACK_SUBJECTS;
|
|
189368
|
+
var TIMEBACK_GRADE_LEVELS;
|
|
189369
|
+
var TIMEBACK_GRADE_LEVEL_LABELS;
|
|
189370
|
+
var CALIPER_SUBJECTS;
|
|
189371
|
+
var ONEROSTER_STATUS;
|
|
189372
|
+
var SCORE_STATUS;
|
|
189373
|
+
var ENV_VARS;
|
|
189374
|
+
var HTTP_DEFAULTS;
|
|
189375
|
+
var AUTH_DEFAULTS;
|
|
189376
|
+
var CACHE_DEFAULTS;
|
|
189377
|
+
var CONFIG_DEFAULTS;
|
|
189378
|
+
var DEFAULT_PLAYCADEMY_ORGANIZATION_ID;
|
|
189379
|
+
var PLAYCADEMY_DEFAULTS;
|
|
189380
|
+
var RESOURCE_DEFAULTS;
|
|
189381
|
+
var HTTP_STATUS;
|
|
189382
|
+
var ERROR_NAMES;
|
|
189383
|
+
var init_constants = __esm3(() => {
|
|
189384
|
+
init_src2();
|
|
189385
|
+
TIMEBACK_API_URLS = {
|
|
189386
|
+
production: "https://api.alpha-1edtech.ai",
|
|
189387
|
+
staging: "https://api.staging.alpha-1edtech.com"
|
|
189388
|
+
};
|
|
189389
|
+
TIMEBACK_AUTH_URLS = {
|
|
189390
|
+
production: "https://prod-beyond-timeback-api-2-idp.auth.us-east-1.amazoncognito.com",
|
|
189391
|
+
staging: "https://alpha-auth-development-idp.auth.us-west-2.amazoncognito.com"
|
|
189392
|
+
};
|
|
189393
|
+
CALIPER_API_URLS = {
|
|
189394
|
+
production: "https://caliper.alpha-1edtech.ai",
|
|
189395
|
+
staging: "https://caliper-staging.alpha-1edtech.com"
|
|
189396
|
+
};
|
|
189397
|
+
ONEROSTER_ENDPOINTS = {
|
|
189398
|
+
organizations: "/ims/oneroster/rostering/v1p2/orgs",
|
|
189399
|
+
courses: "/ims/oneroster/rostering/v1p2/courses",
|
|
189400
|
+
courseComponents: "/ims/oneroster/rostering/v1p2/courses/components",
|
|
189401
|
+
resources: "/ims/oneroster/resources/v1p2/resources",
|
|
189402
|
+
componentResources: "/ims/oneroster/rostering/v1p2/courses/component-resources",
|
|
189403
|
+
classes: "/ims/oneroster/rostering/v1p2/classes",
|
|
189404
|
+
enrollments: "/ims/oneroster/rostering/v1p2/enrollments",
|
|
189405
|
+
assessmentLineItems: "/ims/oneroster/gradebook/v1p2/assessmentLineItems",
|
|
189406
|
+
assessmentResults: "/ims/oneroster/gradebook/v1p2/assessmentResults",
|
|
189407
|
+
users: "/ims/oneroster/rostering/v1p2/users"
|
|
189408
|
+
};
|
|
189409
|
+
CALIPER_ENDPOINTS = {
|
|
189410
|
+
events: "/caliper/event",
|
|
189411
|
+
validate: "/caliper/event/validate"
|
|
189412
|
+
};
|
|
189413
|
+
CALIPER_CONSTANTS = {
|
|
189414
|
+
context: "http://purl.imsglobal.org/ctx/caliper/v1p2",
|
|
189415
|
+
profile: "TimebackProfile",
|
|
189416
|
+
dataVersion: "http://purl.imsglobal.org/ctx/caliper/v1p2"
|
|
189417
|
+
};
|
|
189418
|
+
TIMEBACK_EVENT_TYPES = {
|
|
189419
|
+
activityEvent: "ActivityEvent",
|
|
189420
|
+
timeSpentEvent: "TimeSpentEvent"
|
|
189421
|
+
};
|
|
189422
|
+
TIMEBACK_ACTIONS = {
|
|
189423
|
+
completed: "Completed",
|
|
189424
|
+
spentTime: "SpentTime"
|
|
189425
|
+
};
|
|
189426
|
+
TIMEBACK_TYPES = {
|
|
189427
|
+
user: "TimebackUser",
|
|
189428
|
+
activityContext: "TimebackActivityContext",
|
|
189429
|
+
activityMetricsCollection: "TimebackActivityMetricsCollection",
|
|
189430
|
+
timeSpentMetricsCollection: "TimebackTimeSpentMetricsCollection"
|
|
189431
|
+
};
|
|
189432
|
+
ACTIVITY_METRIC_TYPES = {
|
|
189433
|
+
totalQuestions: "totalQuestions",
|
|
189434
|
+
correctQuestions: "correctQuestions",
|
|
189435
|
+
xpEarned: "xpEarned",
|
|
189436
|
+
masteredUnits: "masteredUnits"
|
|
189437
|
+
};
|
|
189438
|
+
TIME_METRIC_TYPES = {
|
|
189439
|
+
active: "active",
|
|
189440
|
+
inactive: "inactive",
|
|
189441
|
+
waste: "waste",
|
|
189442
|
+
unknown: "unknown",
|
|
189443
|
+
antiPattern: "anti-pattern"
|
|
189444
|
+
};
|
|
189445
|
+
TIMEBACK_SUBJECTS = [
|
|
189446
|
+
"Math",
|
|
189447
|
+
"FastMath",
|
|
189448
|
+
"Science",
|
|
189449
|
+
"Social Studies",
|
|
189450
|
+
"Language",
|
|
189451
|
+
"Reading",
|
|
189452
|
+
"Vocabulary",
|
|
189453
|
+
"Writing"
|
|
189454
|
+
];
|
|
189455
|
+
TIMEBACK_GRADE_LEVELS = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
|
|
189456
|
+
TIMEBACK_GRADE_LEVEL_LABELS = {
|
|
189457
|
+
"-1": "pre-k",
|
|
189458
|
+
"0": "kindergarten",
|
|
189459
|
+
"1": "1st grade",
|
|
189460
|
+
"2": "2nd grade",
|
|
189461
|
+
"3": "3rd grade",
|
|
189462
|
+
"4": "4th grade",
|
|
189463
|
+
"5": "5th grade",
|
|
189464
|
+
"6": "6th grade",
|
|
189465
|
+
"7": "7th grade",
|
|
189466
|
+
"8": "8th grade",
|
|
189467
|
+
"9": "9th grade",
|
|
189468
|
+
"10": "10th grade",
|
|
189469
|
+
"11": "11th grade",
|
|
189470
|
+
"12": "12th grade",
|
|
189471
|
+
"13": "AP"
|
|
189472
|
+
};
|
|
189473
|
+
CALIPER_SUBJECTS = {
|
|
189474
|
+
Reading: "Reading",
|
|
189475
|
+
Language: "Language",
|
|
189476
|
+
Vocabulary: "Vocabulary",
|
|
189477
|
+
SocialStudies: "Social Studies",
|
|
189478
|
+
Writing: "Writing",
|
|
189479
|
+
Science: "Science",
|
|
189480
|
+
FastMath: "FastMath",
|
|
189481
|
+
Math: "Math",
|
|
189482
|
+
None: "None"
|
|
189483
|
+
};
|
|
189484
|
+
ONEROSTER_STATUS = {
|
|
189485
|
+
active: "active",
|
|
189486
|
+
toBeDeleted: "tobedeleted"
|
|
189487
|
+
};
|
|
189488
|
+
SCORE_STATUS = {
|
|
189489
|
+
exempt: "exempt",
|
|
189490
|
+
fullyGraded: "fully graded",
|
|
189491
|
+
notSubmitted: "not submitted",
|
|
189492
|
+
partiallyGraded: "partially graded",
|
|
189493
|
+
submitted: "submitted"
|
|
189494
|
+
};
|
|
189495
|
+
ENV_VARS = {
|
|
189496
|
+
clientId: "TIMEBACK_CLIENT_ID",
|
|
189497
|
+
clientSecret: "TIMEBACK_CLIENT_SECRET",
|
|
189498
|
+
baseUrl: "TIMEBACK_BASE_URL",
|
|
189499
|
+
environment: "TIMEBACK_ENVIRONMENT",
|
|
189500
|
+
vendorResourceId: "TIMEBACK_VENDOR_RESOURCE_ID",
|
|
189501
|
+
launchBaseUrl: "GAME_URL"
|
|
189502
|
+
};
|
|
189503
|
+
HTTP_DEFAULTS = {
|
|
189504
|
+
timeout: 30000,
|
|
189505
|
+
retries: 3,
|
|
189506
|
+
retryBackoffBase: 2
|
|
189507
|
+
};
|
|
189508
|
+
AUTH_DEFAULTS = {
|
|
189509
|
+
tokenCacheDuration: 50000
|
|
189510
|
+
};
|
|
189511
|
+
CACHE_DEFAULTS = {
|
|
189512
|
+
defaultTTL: 600000,
|
|
189513
|
+
defaultMaxSize: 500,
|
|
189514
|
+
defaultName: "TimebackCache",
|
|
189515
|
+
studentTTL: 600000,
|
|
189516
|
+
studentMaxSize: 500,
|
|
189517
|
+
assessmentTTL: 1800000,
|
|
189518
|
+
assessmentMaxSize: 200
|
|
189519
|
+
};
|
|
189520
|
+
CONFIG_DEFAULTS = {
|
|
189521
|
+
fileNames: ["timeback.config.js", "timeback.config.json"]
|
|
189522
|
+
};
|
|
189523
|
+
DEFAULT_PLAYCADEMY_ORGANIZATION_ID = process.env.TIMEBACK_ORG_SOURCE_ID || "PLAYCADEMY";
|
|
189524
|
+
PLAYCADEMY_DEFAULTS = {
|
|
189525
|
+
organization: DEFAULT_PLAYCADEMY_ORGANIZATION_ID,
|
|
189526
|
+
launchBaseUrls: PLAYCADEMY_BASE_URLS
|
|
189527
|
+
};
|
|
189528
|
+
RESOURCE_DEFAULTS = {
|
|
189529
|
+
organization: {
|
|
189530
|
+
name: "Playcademy Studios",
|
|
189531
|
+
type: "department"
|
|
189532
|
+
},
|
|
189533
|
+
course: {
|
|
189534
|
+
gradingScheme: "STANDARD",
|
|
189535
|
+
level: {
|
|
189536
|
+
elementary: "Elementary",
|
|
189537
|
+
middle: "Middle",
|
|
189538
|
+
high: "High",
|
|
189539
|
+
ap: "AP"
|
|
189540
|
+
},
|
|
189541
|
+
metadata: {
|
|
189542
|
+
goals: {
|
|
189543
|
+
dailyXp: 50,
|
|
189544
|
+
dailyLessons: 3
|
|
189545
|
+
},
|
|
189546
|
+
metrics: {
|
|
189547
|
+
totalXp: 1000,
|
|
189548
|
+
totalLessons: 50
|
|
189549
|
+
}
|
|
189550
|
+
}
|
|
189551
|
+
},
|
|
189552
|
+
component: {
|
|
189553
|
+
sortOrder: 1,
|
|
189554
|
+
prerequisiteCriteria: "ALL"
|
|
189555
|
+
},
|
|
189556
|
+
resource: {
|
|
189557
|
+
vendorId: "playcademy",
|
|
189558
|
+
roles: ["primary"],
|
|
189559
|
+
importance: "primary",
|
|
189560
|
+
metadata: {
|
|
189561
|
+
type: "interactive",
|
|
189562
|
+
toolProvider: "Playcademy",
|
|
189563
|
+
instructionalMethod: "exploratory",
|
|
189564
|
+
language: "en-US"
|
|
189565
|
+
}
|
|
189566
|
+
},
|
|
189567
|
+
componentResource: {
|
|
189568
|
+
sortOrder: 1,
|
|
189569
|
+
lessonType: "quiz"
|
|
189570
|
+
}
|
|
189571
|
+
};
|
|
189572
|
+
HTTP_STATUS = {
|
|
189573
|
+
CLIENT_ERROR_MIN: 400,
|
|
189574
|
+
CLIENT_ERROR_MAX: 500,
|
|
189575
|
+
SERVER_ERROR_MIN: 500
|
|
189576
|
+
};
|
|
189577
|
+
ERROR_NAMES = {
|
|
189578
|
+
timebackAuth: "TimebackAuthError",
|
|
189579
|
+
timebackApi: "TimebackApiError",
|
|
189580
|
+
timebackConfig: "TimebackConfigError",
|
|
189581
|
+
timebackSdk: "TimebackSDKError"
|
|
189582
|
+
};
|
|
189583
|
+
});
|
|
189299
189584
|
function deriveSourcedIds(courseId) {
|
|
189300
189585
|
return {
|
|
189301
189586
|
course: courseId,
|
|
@@ -189311,7 +189596,8 @@ __export3(exports_verify, {
|
|
|
189311
189596
|
});
|
|
189312
189597
|
async function fetchTimebackConfig(client2, courseId) {
|
|
189313
189598
|
const sourcedIds = deriveSourcedIds(courseId);
|
|
189314
|
-
const [course, component, resource, componentResource] = await Promise.all([
|
|
189599
|
+
const [org, course, component, resource, componentResource] = await Promise.all([
|
|
189600
|
+
client2.oneroster.organizations.get(PLAYCADEMY_DEFAULTS.organization),
|
|
189315
189601
|
client2.oneroster.courses.get(sourcedIds.course),
|
|
189316
189602
|
client2.oneroster.courseComponents.get(sourcedIds.component),
|
|
189317
189603
|
client2.oneroster.resources.get(sourcedIds.resource),
|
|
@@ -189319,9 +189605,9 @@ async function fetchTimebackConfig(client2, courseId) {
|
|
|
189319
189605
|
]);
|
|
189320
189606
|
return {
|
|
189321
189607
|
organization: {
|
|
189322
|
-
name:
|
|
189323
|
-
type:
|
|
189324
|
-
identifier:
|
|
189608
|
+
name: org.name,
|
|
189609
|
+
type: org.type,
|
|
189610
|
+
identifier: org.identifier || PLAYCADEMY_DEFAULTS.organization
|
|
189325
189611
|
},
|
|
189326
189612
|
course: {
|
|
189327
189613
|
title: course.title || "",
|
|
@@ -189381,145 +189667,10 @@ async function verifyTimebackResources(client2, courseId) {
|
|
|
189381
189667
|
}
|
|
189382
189668
|
};
|
|
189383
189669
|
}
|
|
189384
|
-
var init_verify5 = () => {
|
|
189385
|
-
|
|
189386
|
-
|
|
189387
|
-
|
|
189388
|
-
FOUNDING_MEMBER_BADGE: "FOUNDING_MEMBER_BADGE",
|
|
189389
|
-
EARLY_ADOPTER_BADGE: "EARLY_ADOPTER_BADGE",
|
|
189390
|
-
FIRST_GAME_BADGE: "FIRST_GAME_BADGE",
|
|
189391
|
-
COMMON_SWORD: "COMMON_SWORD",
|
|
189392
|
-
SMALL_HEALTH_POTION: "SMALL_HEALTH_POTION",
|
|
189393
|
-
SMALL_BACKPACK: "SMALL_BACKPACK",
|
|
189394
|
-
LAVA_LAMP: "LAVA_LAMP",
|
|
189395
|
-
BOOMBOX: "BOOMBOX",
|
|
189396
|
-
CABIN_BED: "CABIN_BED"
|
|
189397
|
-
};
|
|
189398
|
-
var CURRENCIES2 = {
|
|
189399
|
-
PRIMARY: ITEM_SLUGS2.PLAYCADEMY_CREDITS,
|
|
189400
|
-
XP: ITEM_SLUGS2.PLAYCADEMY_XP
|
|
189401
|
-
};
|
|
189402
|
-
var BADGES2 = {
|
|
189403
|
-
FOUNDING_MEMBER: ITEM_SLUGS2.FOUNDING_MEMBER_BADGE,
|
|
189404
|
-
EARLY_ADOPTER: ITEM_SLUGS2.EARLY_ADOPTER_BADGE,
|
|
189405
|
-
FIRST_GAME: ITEM_SLUGS2.FIRST_GAME_BADGE
|
|
189406
|
-
};
|
|
189407
|
-
var TIMEBACK_API_URLS = {
|
|
189408
|
-
production: "https://api.alpha-1edtech.ai",
|
|
189409
|
-
staging: "https://api.staging.alpha-1edtech.com"
|
|
189410
|
-
};
|
|
189411
|
-
var TIMEBACK_AUTH_URLS = {
|
|
189412
|
-
production: "https://prod-beyond-timeback-api-2-idp.auth.us-east-1.amazoncognito.com",
|
|
189413
|
-
staging: "https://alpha-auth-development-idp.auth.us-west-2.amazoncognito.com"
|
|
189414
|
-
};
|
|
189415
|
-
var CALIPER_API_URLS = {
|
|
189416
|
-
production: "https://caliper.alpha-1edtech.ai",
|
|
189417
|
-
staging: "https://caliper-staging.alpha-1edtech.com"
|
|
189418
|
-
};
|
|
189419
|
-
var ONEROSTER_ENDPOINTS = {
|
|
189420
|
-
organizations: "/ims/oneroster/rostering/v1p2/orgs",
|
|
189421
|
-
courses: "/ims/oneroster/rostering/v1p2/courses",
|
|
189422
|
-
courseComponents: "/ims/oneroster/rostering/v1p2/courses/components",
|
|
189423
|
-
resources: "/ims/oneroster/resources/v1p2/resources",
|
|
189424
|
-
componentResources: "/ims/oneroster/rostering/v1p2/courses/component-resources",
|
|
189425
|
-
classes: "/ims/oneroster/rostering/v1p2/classes",
|
|
189426
|
-
enrollments: "/ims/oneroster/rostering/v1p2/enrollments",
|
|
189427
|
-
assessmentLineItems: "/ims/oneroster/gradebook/v1p2/assessmentLineItems",
|
|
189428
|
-
assessmentResults: "/ims/oneroster/gradebook/v1p2/assessmentResults",
|
|
189429
|
-
users: "/ims/oneroster/rostering/v1p2/users"
|
|
189430
|
-
};
|
|
189431
|
-
var CALIPER_ENDPOINTS = {
|
|
189432
|
-
events: "/caliper/event",
|
|
189433
|
-
validate: "/caliper/event/validate"
|
|
189434
|
-
};
|
|
189435
|
-
var createOneRosterUrls = (baseUrl) => {
|
|
189436
|
-
const effective = baseUrl || TIMEBACK_API_URLS.production;
|
|
189437
|
-
const base = effective.replace(/\/$/, "");
|
|
189438
|
-
return {
|
|
189439
|
-
user: (userId) => `${base}${ONEROSTER_ENDPOINTS.users}/${userId}`,
|
|
189440
|
-
course: (courseId) => `${base}${ONEROSTER_ENDPOINTS.courses}/${courseId}`,
|
|
189441
|
-
componentResource: (resourceId) => `${base}${ONEROSTER_ENDPOINTS.componentResources}/${resourceId}`
|
|
189442
|
-
};
|
|
189443
|
-
};
|
|
189444
|
-
var CALIPER_CONSTANTS = {
|
|
189445
|
-
context: "http://purl.imsglobal.org/ctx/caliper/v1p2",
|
|
189446
|
-
profile: "TimebackProfile",
|
|
189447
|
-
dataVersion: "http://purl.imsglobal.org/ctx/caliper/v1p2"
|
|
189448
|
-
};
|
|
189449
|
-
var TIMEBACK_EVENT_TYPES = {
|
|
189450
|
-
activityEvent: "ActivityEvent",
|
|
189451
|
-
timeSpentEvent: "TimeSpentEvent"
|
|
189452
|
-
};
|
|
189453
|
-
var TIMEBACK_ACTIONS = {
|
|
189454
|
-
completed: "Completed",
|
|
189455
|
-
spentTime: "SpentTime"
|
|
189456
|
-
};
|
|
189457
|
-
var TIMEBACK_TYPES = {
|
|
189458
|
-
user: "TimebackUser",
|
|
189459
|
-
activityContext: "TimebackActivityContext",
|
|
189460
|
-
activityMetricsCollection: "TimebackActivityMetricsCollection",
|
|
189461
|
-
timeSpentMetricsCollection: "TimebackTimeSpentMetricsCollection"
|
|
189462
|
-
};
|
|
189463
|
-
var ACTIVITY_METRIC_TYPES = {
|
|
189464
|
-
totalQuestions: "totalQuestions",
|
|
189465
|
-
correctQuestions: "correctQuestions",
|
|
189466
|
-
xpEarned: "xpEarned",
|
|
189467
|
-
masteredUnits: "masteredUnits"
|
|
189468
|
-
};
|
|
189469
|
-
var TIME_METRIC_TYPES = {
|
|
189470
|
-
active: "active",
|
|
189471
|
-
inactive: "inactive",
|
|
189472
|
-
waste: "waste",
|
|
189473
|
-
unknown: "unknown",
|
|
189474
|
-
antiPattern: "anti-pattern"
|
|
189475
|
-
};
|
|
189476
|
-
var ONEROSTER_STATUS = {
|
|
189477
|
-
active: "active",
|
|
189478
|
-
toBeDeleted: "tobedeleted"
|
|
189479
|
-
};
|
|
189480
|
-
var SCORE_STATUS = {
|
|
189481
|
-
exempt: "exempt",
|
|
189482
|
-
fullyGraded: "fully graded",
|
|
189483
|
-
notSubmitted: "not submitted",
|
|
189484
|
-
partiallyGraded: "partially graded",
|
|
189485
|
-
submitted: "submitted"
|
|
189486
|
-
};
|
|
189487
|
-
var ENV_VARS = {
|
|
189488
|
-
clientId: "TIMEBACK_CLIENT_ID",
|
|
189489
|
-
clientSecret: "TIMEBACK_CLIENT_SECRET",
|
|
189490
|
-
baseUrl: "TIMEBACK_BASE_URL",
|
|
189491
|
-
environment: "TIMEBACK_ENVIRONMENT",
|
|
189492
|
-
vendorResourceId: "TIMEBACK_VENDOR_RESOURCE_ID",
|
|
189493
|
-
launchBaseUrl: "GAME_URL"
|
|
189494
|
-
};
|
|
189495
|
-
var HTTP_DEFAULTS = {
|
|
189496
|
-
timeout: 30000,
|
|
189497
|
-
retries: 3,
|
|
189498
|
-
retryBackoffBase: 2
|
|
189499
|
-
};
|
|
189500
|
-
var AUTH_DEFAULTS = {
|
|
189501
|
-
tokenCacheDuration: 50000
|
|
189502
|
-
};
|
|
189503
|
-
var CACHE_DEFAULTS = {
|
|
189504
|
-
defaultTTL: 600000,
|
|
189505
|
-
defaultMaxSize: 500,
|
|
189506
|
-
defaultName: "TimebackCache",
|
|
189507
|
-
studentTTL: 600000,
|
|
189508
|
-
studentMaxSize: 500,
|
|
189509
|
-
assessmentTTL: 1800000,
|
|
189510
|
-
assessmentMaxSize: 200
|
|
189511
|
-
};
|
|
189512
|
-
var HTTP_STATUS = {
|
|
189513
|
-
CLIENT_ERROR_MIN: 400,
|
|
189514
|
-
CLIENT_ERROR_MAX: 500,
|
|
189515
|
-
SERVER_ERROR_MIN: 500
|
|
189516
|
-
};
|
|
189517
|
-
var ERROR_NAMES = {
|
|
189518
|
-
timebackAuth: "TimebackAuthError",
|
|
189519
|
-
timebackApi: "TimebackApiError",
|
|
189520
|
-
timebackConfig: "TimebackConfigError",
|
|
189521
|
-
timebackSdk: "TimebackSDKError"
|
|
189522
|
-
};
|
|
189670
|
+
var init_verify5 = __esm3(() => {
|
|
189671
|
+
init_constants();
|
|
189672
|
+
});
|
|
189673
|
+
init_constants();
|
|
189523
189674
|
|
|
189524
189675
|
class TimebackError extends Error {
|
|
189525
189676
|
constructor(message22) {
|
|
@@ -190030,6 +190181,8 @@ async function updateTimebackResources(client2, courseId, config2) {
|
|
|
190030
190181
|
updateComponentResourceLink(client2, config2, sourcedIds)
|
|
190031
190182
|
]);
|
|
190032
190183
|
}
|
|
190184
|
+
init_constants();
|
|
190185
|
+
init_constants();
|
|
190033
190186
|
if (process.env.DEBUG === "true") {
|
|
190034
190187
|
process.env.TERM = "dumb";
|
|
190035
190188
|
}
|
|
@@ -190129,6 +190282,7 @@ async function getTimebackTokenResponse(config2) {
|
|
|
190129
190282
|
function getAuthUrl(environment = "production") {
|
|
190130
190283
|
return TIMEBACK_AUTH_URLS[environment];
|
|
190131
190284
|
}
|
|
190285
|
+
init_constants();
|
|
190132
190286
|
async function request({
|
|
190133
190287
|
path: path22,
|
|
190134
190288
|
baseUrl,
|
|
@@ -190234,6 +190388,7 @@ async function requestCaliper(options) {
|
|
|
190234
190388
|
baseUrl: caliperBase
|
|
190235
190389
|
});
|
|
190236
190390
|
}
|
|
190391
|
+
init_constants();
|
|
190237
190392
|
function logTimebackError(operation, error2, context) {
|
|
190238
190393
|
const errorMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
190239
190394
|
if (error2 instanceof TimebackApiError) {
|
|
@@ -190269,6 +190424,17 @@ function createOneRosterNamespace(client2) {
|
|
|
190269
190424
|
listByCourse: async (courseSourcedId) => {
|
|
190270
190425
|
const res = await client2["request"](`${ONEROSTER_ENDPOINTS.courses}/${courseSourcedId}/classes`, "GET");
|
|
190271
190426
|
return res.classes;
|
|
190427
|
+
},
|
|
190428
|
+
listByStudent: async (userSourcedId, options) => {
|
|
190429
|
+
const queryParams = new URLSearchParams;
|
|
190430
|
+
if (options?.limit)
|
|
190431
|
+
queryParams.set("limit", String(options.limit));
|
|
190432
|
+
if (options?.offset)
|
|
190433
|
+
queryParams.set("offset", String(options.offset));
|
|
190434
|
+
const endpoint = `${ONEROSTER_ENDPOINTS.users}/${userSourcedId}/classes`;
|
|
190435
|
+
const url = queryParams.toString() ? `${endpoint}?${queryParams}` : endpoint;
|
|
190436
|
+
const res = await client2["request"](url, "GET");
|
|
190437
|
+
return res.classes || [];
|
|
190272
190438
|
}
|
|
190273
190439
|
},
|
|
190274
190440
|
organizations: {
|
|
@@ -190276,7 +190442,7 @@ function createOneRosterNamespace(client2) {
|
|
|
190276
190442
|
return client2["request"](ONEROSTER_ENDPOINTS.organizations, "POST", data);
|
|
190277
190443
|
},
|
|
190278
190444
|
get: async (sourcedId) => {
|
|
190279
|
-
return client2["request"](`${ONEROSTER_ENDPOINTS.organizations}/${sourcedId}`, "GET");
|
|
190445
|
+
return client2["request"](`${ONEROSTER_ENDPOINTS.organizations}/${sourcedId}`, "GET").then((res) => res.org);
|
|
190280
190446
|
},
|
|
190281
190447
|
update: async (sourcedId, data) => {
|
|
190282
190448
|
return client2["request"](`${ONEROSTER_ENDPOINTS.organizations}/${sourcedId}`, "PUT", data);
|
|
@@ -190404,7 +190570,7 @@ function createOneRosterNamespace(client2) {
|
|
|
190404
190570
|
return client2["request"](ONEROSTER_ENDPOINTS.users, "POST", { user: data });
|
|
190405
190571
|
},
|
|
190406
190572
|
get: async (sourcedId) => {
|
|
190407
|
-
return client2["request"](`${ONEROSTER_ENDPOINTS.users}/${sourcedId}`, "GET");
|
|
190573
|
+
return client2["request"](`${ONEROSTER_ENDPOINTS.users}/${sourcedId}`, "GET").then((res) => res.user);
|
|
190408
190574
|
},
|
|
190409
190575
|
findByEmail: async (email) => {
|
|
190410
190576
|
const params = new URLSearchParams({ filter: `email='${email}'` });
|
|
@@ -190420,6 +190586,7 @@ function createOneRosterNamespace(client2) {
|
|
|
190420
190586
|
}
|
|
190421
190587
|
};
|
|
190422
190588
|
}
|
|
190589
|
+
init_constants();
|
|
190423
190590
|
function createCaliperNamespace(client2) {
|
|
190424
190591
|
const urls = createOneRosterUrls(client2.getBaseUrl());
|
|
190425
190592
|
const caliper = {
|
|
@@ -190457,7 +190624,7 @@ function createCaliperNamespace(client2) {
|
|
|
190457
190624
|
},
|
|
190458
190625
|
action: TIMEBACK_ACTIONS.completed,
|
|
190459
190626
|
object: {
|
|
190460
|
-
id:
|
|
190627
|
+
id: caliper.buildActivityUrl(data),
|
|
190461
190628
|
type: TIMEBACK_TYPES.activityContext,
|
|
190462
190629
|
subject: data.subject,
|
|
190463
190630
|
app: {
|
|
@@ -190467,7 +190634,7 @@ function createCaliperNamespace(client2) {
|
|
|
190467
190634
|
name: data.activityName
|
|
190468
190635
|
},
|
|
190469
190636
|
course: { id: urls.course(data.courseId), name: data.activityName },
|
|
190470
|
-
process:
|
|
190637
|
+
process: false
|
|
190471
190638
|
},
|
|
190472
190639
|
generated: {
|
|
190473
190640
|
id: `urn:timeback:metrics:activity-completion-${crypto.randomUUID()}`,
|
|
@@ -190493,7 +190660,8 @@ function createCaliperNamespace(client2) {
|
|
|
190493
190660
|
value: data.masteredUnits
|
|
190494
190661
|
}
|
|
190495
190662
|
] : []
|
|
190496
|
-
]
|
|
190663
|
+
],
|
|
190664
|
+
...data.extensions ? { extensions: data.extensions } : {}
|
|
190497
190665
|
}
|
|
190498
190666
|
};
|
|
190499
190667
|
return caliper.emit(event, data.sensorUrl);
|
|
@@ -190512,7 +190680,7 @@ function createCaliperNamespace(client2) {
|
|
|
190512
190680
|
},
|
|
190513
190681
|
action: TIMEBACK_ACTIONS.spentTime,
|
|
190514
190682
|
object: {
|
|
190515
|
-
id:
|
|
190683
|
+
id: caliper.buildActivityUrl(data),
|
|
190516
190684
|
type: TIMEBACK_TYPES.activityContext,
|
|
190517
190685
|
subject: data.subject,
|
|
190518
190686
|
app: {
|
|
@@ -190540,10 +190708,33 @@ function createCaliperNamespace(client2) {
|
|
|
190540
190708
|
}
|
|
190541
190709
|
};
|
|
190542
190710
|
return caliper.emit(event, data.sensorUrl);
|
|
190711
|
+
},
|
|
190712
|
+
buildActivityUrl: (data) => {
|
|
190713
|
+
const base = data.sensorUrl.replace(/\/$/, "");
|
|
190714
|
+
return `${base}/activities/${data.courseId}/${data.activityId}/${crypto.randomUUID()}`;
|
|
190543
190715
|
}
|
|
190544
190716
|
};
|
|
190545
190717
|
return caliper;
|
|
190546
190718
|
}
|
|
190719
|
+
function createEduBridgeNamespace(client2) {
|
|
190720
|
+
const enrollments = {
|
|
190721
|
+
listByUser: async (userId) => {
|
|
190722
|
+
const response = await client2["request"](`/edubridge/enrollments/user/${userId}`, "GET");
|
|
190723
|
+
return response.data;
|
|
190724
|
+
}
|
|
190725
|
+
};
|
|
190726
|
+
const analytics = {
|
|
190727
|
+
getEnrollmentFacts: async (enrollmentId) => {
|
|
190728
|
+
return client2["request"](`/edubridge/analytics/enrollment/${enrollmentId}`, "GET");
|
|
190729
|
+
}
|
|
190730
|
+
};
|
|
190731
|
+
return {
|
|
190732
|
+
enrollments,
|
|
190733
|
+
analytics
|
|
190734
|
+
};
|
|
190735
|
+
}
|
|
190736
|
+
init_constants();
|
|
190737
|
+
init_constants();
|
|
190547
190738
|
|
|
190548
190739
|
class TimebackCache {
|
|
190549
190740
|
cache = new Map;
|
|
@@ -190649,6 +190840,7 @@ class TimebackCache {
|
|
|
190649
190840
|
class TimebackCacheManager {
|
|
190650
190841
|
studentCache;
|
|
190651
190842
|
assessmentLineItemCache;
|
|
190843
|
+
resourceMasteryCache;
|
|
190652
190844
|
constructor() {
|
|
190653
190845
|
this.studentCache = new TimebackCache({
|
|
190654
190846
|
defaultTTL: CACHE_DEFAULTS.studentTTL,
|
|
@@ -190660,6 +190852,11 @@ class TimebackCacheManager {
|
|
|
190660
190852
|
maxSize: CACHE_DEFAULTS.assessmentMaxSize,
|
|
190661
190853
|
name: "AssessmentLineItemCache"
|
|
190662
190854
|
});
|
|
190855
|
+
this.resourceMasteryCache = new TimebackCache({
|
|
190856
|
+
defaultTTL: CACHE_DEFAULTS.assessmentTTL,
|
|
190857
|
+
maxSize: CACHE_DEFAULTS.assessmentMaxSize,
|
|
190858
|
+
name: "ResourceMasteryCache"
|
|
190859
|
+
});
|
|
190663
190860
|
}
|
|
190664
190861
|
getStudent(key) {
|
|
190665
190862
|
return this.studentCache.get(key);
|
|
@@ -190673,6 +190870,12 @@ class TimebackCacheManager {
|
|
|
190673
190870
|
setAssessmentLineItem(key, lineItemId) {
|
|
190674
190871
|
this.assessmentLineItemCache.set(key, lineItemId);
|
|
190675
190872
|
}
|
|
190873
|
+
getResourceMasterableUnits(key) {
|
|
190874
|
+
return this.resourceMasteryCache.get(key);
|
|
190875
|
+
}
|
|
190876
|
+
setResourceMasterableUnits(key, value) {
|
|
190877
|
+
this.resourceMasteryCache.set(key, value);
|
|
190878
|
+
}
|
|
190676
190879
|
clearAll() {
|
|
190677
190880
|
this.studentCache.clear();
|
|
190678
190881
|
this.assessmentLineItemCache.clear();
|
|
@@ -190681,18 +190884,32 @@ class TimebackCacheManager {
|
|
|
190681
190884
|
getStats() {
|
|
190682
190885
|
return {
|
|
190683
190886
|
studentCache: this.studentCache.stats(),
|
|
190684
|
-
assessmentLineItemCache: this.assessmentLineItemCache.stats()
|
|
190887
|
+
assessmentLineItemCache: this.assessmentLineItemCache.stats(),
|
|
190888
|
+
resourceMasteryCache: this.resourceMasteryCache.stats()
|
|
190685
190889
|
};
|
|
190686
190890
|
}
|
|
190687
190891
|
cleanup() {
|
|
190688
190892
|
this.studentCache.cleanup();
|
|
190689
190893
|
this.assessmentLineItemCache.cleanup();
|
|
190894
|
+
this.resourceMasteryCache.cleanup();
|
|
190690
190895
|
log32.debug("[TimebackCacheManager] Cache cleanup completed");
|
|
190691
190896
|
}
|
|
190692
190897
|
}
|
|
190693
190898
|
function kebabToTitleCase(kebabStr) {
|
|
190694
190899
|
return kebabStr.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
190695
190900
|
}
|
|
190901
|
+
init_constants();
|
|
190902
|
+
init_constants();
|
|
190903
|
+
var isObject2 = (value) => typeof value === "object" && value !== null;
|
|
190904
|
+
function isPlaycademyResourceMetadata(value) {
|
|
190905
|
+
if (!isObject2(value)) {
|
|
190906
|
+
return false;
|
|
190907
|
+
}
|
|
190908
|
+
if (!("mastery" in value) || value.mastery === undefined) {
|
|
190909
|
+
return true;
|
|
190910
|
+
}
|
|
190911
|
+
return isObject2(value.mastery);
|
|
190912
|
+
}
|
|
190696
190913
|
function validateProgressData(progressData) {
|
|
190697
190914
|
if (!progressData.subject) {
|
|
190698
190915
|
throw new ConfigurationError("subject", "Subject is required for Caliper events. Provide it in progressData.subject");
|
|
@@ -190746,36 +190963,47 @@ class ProgressRecorder {
|
|
|
190746
190963
|
cacheManager;
|
|
190747
190964
|
onerosterNamespace;
|
|
190748
190965
|
caliperNamespace;
|
|
190749
|
-
|
|
190966
|
+
edubridgeNamespace;
|
|
190967
|
+
constructor(studentResolver, cacheManager, onerosterNamespace, caliperNamespace, edubridgeNamespace) {
|
|
190750
190968
|
this.studentResolver = studentResolver;
|
|
190751
190969
|
this.cacheManager = cacheManager;
|
|
190752
190970
|
this.onerosterNamespace = onerosterNamespace;
|
|
190753
190971
|
this.caliperNamespace = caliperNamespace;
|
|
190972
|
+
this.edubridgeNamespace = edubridgeNamespace;
|
|
190754
190973
|
}
|
|
190755
190974
|
async record(courseId, studentIdentifier, progressData) {
|
|
190756
190975
|
validateProgressData(progressData);
|
|
190757
|
-
const ids =
|
|
190758
|
-
const activityId = progressData.activityId || ids.componentResource || ids.resource || "unknown-activity";
|
|
190759
|
-
const activityName = progressData.activityName || kebabToTitleCase(activityId);
|
|
190760
|
-
const classId = progressData.classId;
|
|
190761
|
-
const courseName = progressData.courseName || "Game Course";
|
|
190762
|
-
const student = await this.studentResolver.resolve(studentIdentifier, progressData.studentEmail);
|
|
190976
|
+
const { ids, activityId, activityName, courseName, student } = await this.resolveContext(courseId, studentIdentifier, progressData);
|
|
190763
190977
|
const { id: studentId, email: studentEmail } = student;
|
|
190764
190978
|
const { score, totalQuestions, correctQuestions, xpEarned, masteredUnits, attemptNumber } = progressData;
|
|
190765
|
-
const
|
|
190766
|
-
|
|
190767
|
-
if (!actualLineItemId) {
|
|
190768
|
-
actualLineItemId = await this.getOrCreateLineItem(lineItemId, activityName, classId, ids);
|
|
190769
|
-
this.cacheManager.setAssessmentLineItem(lineItemId, actualLineItemId);
|
|
190770
|
-
}
|
|
190771
|
-
let currentAttemptNumber = attemptNumber || 1;
|
|
190979
|
+
const actualLineItemId = await this.resolveAssessmentLineItem(activityId, activityName, progressData.classId, ids);
|
|
190980
|
+
const currentAttemptNumber = await this.resolveAttemptNumber(attemptNumber, score, studentId, actualLineItemId);
|
|
190772
190981
|
const isFirstAttempt = currentAttemptNumber === 1;
|
|
190773
|
-
if (!attemptNumber && score !== undefined) {
|
|
190774
|
-
currentAttemptNumber = await this.determineAttemptNumber(studentId, actualLineItemId);
|
|
190775
|
-
}
|
|
190776
190982
|
const calculatedXp = this.calculateXpForProgress(progressData, totalQuestions, correctQuestions, xpEarned, isFirstAttempt);
|
|
190983
|
+
let extensions = progressData.extensions;
|
|
190984
|
+
const completionProgress = await this.buildCompletionProgress({
|
|
190985
|
+
studentId,
|
|
190986
|
+
courseId,
|
|
190987
|
+
progressData,
|
|
190988
|
+
resourceId: ids.resource
|
|
190989
|
+
});
|
|
190990
|
+
let pctCompleteApp;
|
|
190991
|
+
let masteryAchieved = false;
|
|
190992
|
+
let scoreStatus = SCORE_STATUS.partiallyGraded;
|
|
190993
|
+
const inProgress = "false";
|
|
190994
|
+
if (completionProgress) {
|
|
190995
|
+
masteryAchieved = completionProgress.masteryAchieved;
|
|
190996
|
+
pctCompleteApp = completionProgress.pctCompleteApp;
|
|
190997
|
+
extensions = {
|
|
190998
|
+
...extensions || {},
|
|
190999
|
+
...pctCompleteApp !== undefined ? { pctCompleteApp } : {}
|
|
191000
|
+
};
|
|
191001
|
+
if (masteryAchieved) {
|
|
191002
|
+
scoreStatus = SCORE_STATUS.fullyGraded;
|
|
191003
|
+
}
|
|
191004
|
+
}
|
|
190777
191005
|
if (score !== undefined) {
|
|
190778
|
-
await this.createGradebookEntry(actualLineItemId, studentId, currentAttemptNumber, score, totalQuestions, correctQuestions, calculatedXp);
|
|
191006
|
+
await this.createGradebookEntry(actualLineItemId, studentId, currentAttemptNumber, score, totalQuestions, correctQuestions, calculatedXp, masteredUnits, scoreStatus, inProgress, progressData.appName);
|
|
190779
191007
|
} else {
|
|
190780
191008
|
log32.warn("[ProgressRecorder] Score not provided, skipping gradebook entry", {
|
|
190781
191009
|
studentId,
|
|
@@ -190783,12 +191011,151 @@ class ProgressRecorder {
|
|
|
190783
191011
|
attemptNumber: currentAttemptNumber
|
|
190784
191012
|
});
|
|
190785
191013
|
}
|
|
190786
|
-
await this.emitCaliperEvent(studentId, studentEmail, activityId, activityName, ids.course, courseName, totalQuestions, correctQuestions, calculatedXp, masteredUnits, currentAttemptNumber, progressData);
|
|
191014
|
+
await this.emitCaliperEvent(studentId, studentEmail, activityId, activityName, ids.course, courseName, totalQuestions, correctQuestions, calculatedXp, masteredUnits, currentAttemptNumber, progressData, extensions);
|
|
190787
191015
|
return {
|
|
190788
191016
|
xpAwarded: calculatedXp,
|
|
190789
|
-
attemptNumber: currentAttemptNumber
|
|
191017
|
+
attemptNumber: currentAttemptNumber,
|
|
191018
|
+
masteredUnitsApplied: progressData.masteredUnits ?? 0,
|
|
191019
|
+
pctCompleteApp,
|
|
191020
|
+
scoreStatus,
|
|
191021
|
+
inProgress
|
|
190790
191022
|
};
|
|
190791
191023
|
}
|
|
191024
|
+
async resolveContext(courseId, studentIdentifier, progressData) {
|
|
191025
|
+
const ids = deriveSourcedIds(courseId);
|
|
191026
|
+
const activityId = progressData.activityId || ids.componentResource || ids.resource || "unknown-activity";
|
|
191027
|
+
const activityName = progressData.activityName || kebabToTitleCase(activityId);
|
|
191028
|
+
const courseName = progressData.courseName || "Game Course";
|
|
191029
|
+
const student = await this.studentResolver.resolve(studentIdentifier, progressData.studentEmail);
|
|
191030
|
+
return { ids, activityId, activityName, courseName, student };
|
|
191031
|
+
}
|
|
191032
|
+
async resolveAssessmentLineItem(activityId, activityName, classId, ids) {
|
|
191033
|
+
const lineItemId = `${ids.course}-${activityId}-assessment`;
|
|
191034
|
+
let actualLineItemId = this.cacheManager.getAssessmentLineItem(lineItemId);
|
|
191035
|
+
if (!actualLineItemId) {
|
|
191036
|
+
actualLineItemId = await this.getOrCreateLineItem(lineItemId, activityName, classId, ids);
|
|
191037
|
+
this.cacheManager.setAssessmentLineItem(lineItemId, actualLineItemId);
|
|
191038
|
+
}
|
|
191039
|
+
return actualLineItemId;
|
|
191040
|
+
}
|
|
191041
|
+
async resolveAttemptNumber(providedAttemptNumber, score, studentId, lineItemId) {
|
|
191042
|
+
if (providedAttemptNumber)
|
|
191043
|
+
return providedAttemptNumber;
|
|
191044
|
+
if (score !== undefined) {
|
|
191045
|
+
return this.determineAttemptNumber(studentId, lineItemId);
|
|
191046
|
+
}
|
|
191047
|
+
return 1;
|
|
191048
|
+
}
|
|
191049
|
+
calculateXpForProgress(progressData, totalQuestions, correctQuestions, xpEarned, isFirstAttempt) {
|
|
191050
|
+
if (xpEarned !== undefined) {
|
|
191051
|
+
log32.debug("[ProgressRecorder] Using provided XP", { xpEarned });
|
|
191052
|
+
return xpEarned;
|
|
191053
|
+
}
|
|
191054
|
+
if (progressData.sessionDurationSeconds && totalQuestions && correctQuestions) {
|
|
191055
|
+
const accuracy = correctQuestions / totalQuestions;
|
|
191056
|
+
const calculatedXp = calculateXp(progressData.sessionDurationSeconds, accuracy, isFirstAttempt);
|
|
191057
|
+
log32.debug("[ProgressRecorder] Calculated XP", {
|
|
191058
|
+
durationSeconds: progressData.sessionDurationSeconds,
|
|
191059
|
+
accuracy,
|
|
191060
|
+
isFirstAttempt,
|
|
191061
|
+
calculatedXp
|
|
191062
|
+
});
|
|
191063
|
+
return calculatedXp;
|
|
191064
|
+
}
|
|
191065
|
+
return 0;
|
|
191066
|
+
}
|
|
191067
|
+
async buildCompletionProgress({
|
|
191068
|
+
studentId,
|
|
191069
|
+
courseId,
|
|
191070
|
+
progressData,
|
|
191071
|
+
resourceId
|
|
191072
|
+
}) {
|
|
191073
|
+
if (typeof progressData.masteredUnits !== "number" || progressData.masteredUnits <= 0) {
|
|
191074
|
+
return;
|
|
191075
|
+
}
|
|
191076
|
+
const masterableUnits = await this.resolveMasterableUnits(resourceId);
|
|
191077
|
+
if (!masterableUnits || masterableUnits <= 0) {
|
|
191078
|
+
log32.warn("[ProgressRecorder] No masterableUnits configured for course", {
|
|
191079
|
+
courseId,
|
|
191080
|
+
resourceId
|
|
191081
|
+
});
|
|
191082
|
+
return;
|
|
191083
|
+
}
|
|
191084
|
+
const facts = await this.fetchEnrollmentAnalyticsFacts(studentId, courseId);
|
|
191085
|
+
if (!facts) {
|
|
191086
|
+
log32.warn("[ProgressRecorder] Unable to retrieve analytics for mastery-based completion", { studentId, courseId });
|
|
191087
|
+
return;
|
|
191088
|
+
}
|
|
191089
|
+
const historicalMasteredUnits = this.sumAnalyticsMetric(facts, "masteredUnits");
|
|
191090
|
+
const totalMastered = historicalMasteredUnits + progressData.masteredUnits;
|
|
191091
|
+
const rawPct = totalMastered / masterableUnits * 100;
|
|
191092
|
+
const pctCompleteApp = Math.min(100, Math.max(0, Math.round(rawPct)));
|
|
191093
|
+
const masteryAchieved = totalMastered >= masterableUnits;
|
|
191094
|
+
return { pctCompleteApp, masteryAchieved };
|
|
191095
|
+
}
|
|
191096
|
+
async fetchEnrollmentAnalyticsFacts(studentId, courseId) {
|
|
191097
|
+
try {
|
|
191098
|
+
const enrollments = await this.edubridgeNamespace.enrollments.listByUser(studentId);
|
|
191099
|
+
const enrollment = enrollments.find((e2) => e2.course.id === courseId);
|
|
191100
|
+
if (!enrollment) {
|
|
191101
|
+
log32.warn("[ProgressRecorder] Enrollment not found for student/course", {
|
|
191102
|
+
studentId,
|
|
191103
|
+
courseId
|
|
191104
|
+
});
|
|
191105
|
+
return;
|
|
191106
|
+
}
|
|
191107
|
+
const analytics = await this.edubridgeNamespace.analytics.getEnrollmentFacts(enrollment.id);
|
|
191108
|
+
return analytics.facts;
|
|
191109
|
+
} catch (error2) {
|
|
191110
|
+
log32.error("[ProgressRecorder] Failed to load enrollment analytics facts", {
|
|
191111
|
+
studentId,
|
|
191112
|
+
courseId,
|
|
191113
|
+
error: error2
|
|
191114
|
+
});
|
|
191115
|
+
return;
|
|
191116
|
+
}
|
|
191117
|
+
}
|
|
191118
|
+
sumAnalyticsMetric(facts, metric) {
|
|
191119
|
+
if (!facts) {
|
|
191120
|
+
return 0;
|
|
191121
|
+
}
|
|
191122
|
+
let total = 0;
|
|
191123
|
+
Object.values(facts).forEach((dateFacts) => {
|
|
191124
|
+
Object.values(dateFacts).forEach((subjectFacts) => {
|
|
191125
|
+
const metrics = subjectFacts.activityMetrics;
|
|
191126
|
+
if (metrics && typeof metrics[metric] === "number") {
|
|
191127
|
+
total += metrics[metric];
|
|
191128
|
+
}
|
|
191129
|
+
});
|
|
191130
|
+
});
|
|
191131
|
+
return total;
|
|
191132
|
+
}
|
|
191133
|
+
async resolveMasterableUnits(resourceId) {
|
|
191134
|
+
if (!resourceId) {
|
|
191135
|
+
return;
|
|
191136
|
+
}
|
|
191137
|
+
const cached = this.cacheManager.getResourceMasterableUnits(resourceId);
|
|
191138
|
+
if (cached !== undefined) {
|
|
191139
|
+
return cached === null ? undefined : cached;
|
|
191140
|
+
}
|
|
191141
|
+
try {
|
|
191142
|
+
const resource = await this.onerosterNamespace.resources.get(resourceId);
|
|
191143
|
+
const playcademyMetadata = resource.metadata?.playcademy;
|
|
191144
|
+
if (!playcademyMetadata) {
|
|
191145
|
+
return;
|
|
191146
|
+
}
|
|
191147
|
+
const masterableUnits = isPlaycademyResourceMetadata(playcademyMetadata) ? playcademyMetadata.mastery?.masterableUnits : undefined;
|
|
191148
|
+
this.cacheManager.setResourceMasterableUnits(resourceId, masterableUnits ?? null);
|
|
191149
|
+
return masterableUnits;
|
|
191150
|
+
} catch (error2) {
|
|
191151
|
+
log32.error("[ProgressRecorder] Failed to fetch resource metadata for mastery config", {
|
|
191152
|
+
resourceId,
|
|
191153
|
+
error: error2
|
|
191154
|
+
});
|
|
191155
|
+
this.cacheManager.setResourceMasterableUnits(resourceId, null);
|
|
191156
|
+
return;
|
|
191157
|
+
}
|
|
191158
|
+
}
|
|
190792
191159
|
async getOrCreateLineItem(lineItemId, activityName, classId, ids) {
|
|
190793
191160
|
try {
|
|
190794
191161
|
const lineItem = await this.onerosterNamespace.assessmentLineItems.findOrCreate(lineItemId, {
|
|
@@ -190827,25 +191194,7 @@ class ProgressRecorder {
|
|
|
190827
191194
|
}
|
|
190828
191195
|
return 1;
|
|
190829
191196
|
}
|
|
190830
|
-
|
|
190831
|
-
if (xpEarned !== undefined) {
|
|
190832
|
-
log32.debug("[ProgressRecorder] Using provided XP", { xpEarned });
|
|
190833
|
-
return xpEarned;
|
|
190834
|
-
}
|
|
190835
|
-
if (progressData.sessionDurationSeconds && totalQuestions && correctQuestions) {
|
|
190836
|
-
const accuracy = correctQuestions / totalQuestions;
|
|
190837
|
-
const calculatedXp = calculateXp(progressData.sessionDurationSeconds, accuracy, isFirstAttempt);
|
|
190838
|
-
log32.debug("[ProgressRecorder] Calculated XP", {
|
|
190839
|
-
durationSeconds: progressData.sessionDurationSeconds,
|
|
190840
|
-
accuracy,
|
|
190841
|
-
isFirstAttempt,
|
|
190842
|
-
calculatedXp
|
|
190843
|
-
});
|
|
190844
|
-
return calculatedXp;
|
|
190845
|
-
}
|
|
190846
|
-
return 0;
|
|
190847
|
-
}
|
|
190848
|
-
async createGradebookEntry(lineItemId, studentId, attemptNumber, score, totalQuestions, correctQuestions, xp) {
|
|
191197
|
+
async createGradebookEntry(lineItemId, studentId, attemptNumber, score, totalQuestions, correctQuestions, xp, masteredUnits, scoreStatus, inProgress, appName) {
|
|
190849
191198
|
const resultId = `${lineItemId}:${studentId}:attempt-${attemptNumber}`;
|
|
190850
191199
|
await this.onerosterNamespace.assessmentResults.upsert(resultId, {
|
|
190851
191200
|
sourcedId: resultId,
|
|
@@ -190854,18 +191203,21 @@ class ProgressRecorder {
|
|
|
190854
191203
|
student: { sourcedId: studentId },
|
|
190855
191204
|
score,
|
|
190856
191205
|
scoreDate: new Date().toISOString(),
|
|
190857
|
-
scoreStatus
|
|
191206
|
+
scoreStatus,
|
|
191207
|
+
inProgress,
|
|
190858
191208
|
metadata: {
|
|
190859
191209
|
xp,
|
|
190860
191210
|
totalQuestions,
|
|
190861
191211
|
correctQuestions,
|
|
190862
191212
|
accuracy: totalQuestions && correctQuestions ? correctQuestions / totalQuestions * 100 : undefined,
|
|
190863
191213
|
attemptNumber,
|
|
190864
|
-
lastUpdated: new Date().toISOString()
|
|
191214
|
+
lastUpdated: new Date().toISOString(),
|
|
191215
|
+
masteredUnits,
|
|
191216
|
+
appName
|
|
190865
191217
|
}
|
|
190866
191218
|
});
|
|
190867
191219
|
}
|
|
190868
|
-
async emitCaliperEvent(studentId, studentEmail, activityId, activityName, courseId, courseName, totalQuestions, correctQuestions, xpEarned, masteredUnits, attemptNumber, progressData) {
|
|
191220
|
+
async emitCaliperEvent(studentId, studentEmail, activityId, activityName, courseId, courseName, totalQuestions, correctQuestions, xpEarned, masteredUnits, attemptNumber, progressData, extensions) {
|
|
190869
191221
|
await this.caliperNamespace.emitActivityEvent({
|
|
190870
191222
|
studentId,
|
|
190871
191223
|
studentEmail,
|
|
@@ -190880,7 +191232,8 @@ class ProgressRecorder {
|
|
|
190880
191232
|
attemptNumber,
|
|
190881
191233
|
subject: progressData.subject,
|
|
190882
191234
|
appName: progressData.appName,
|
|
190883
|
-
sensorUrl: progressData.sensorUrl
|
|
191235
|
+
sensorUrl: progressData.sensorUrl,
|
|
191236
|
+
extensions: extensions || progressData.extensions
|
|
190884
191237
|
}).catch((error2) => {
|
|
190885
191238
|
log32.error("[ProgressRecorder] Failed to emit activity event", { error: error2 });
|
|
190886
191239
|
});
|
|
@@ -194995,9 +195348,10 @@ class TimebackClient {
|
|
|
194995
195348
|
};
|
|
194996
195349
|
this.oneroster = createOneRosterNamespace(this);
|
|
194997
195350
|
this.caliper = createCaliperNamespace(this);
|
|
195351
|
+
this.edubridge = createEduBridgeNamespace(this);
|
|
194998
195352
|
this.cacheManager = new TimebackCacheManager;
|
|
194999
195353
|
this.studentResolver = new StudentResolver(this.cacheManager, this.oneroster);
|
|
195000
|
-
this.progressRecorder = new ProgressRecorder(this.studentResolver, this.cacheManager, this.oneroster, this.caliper);
|
|
195354
|
+
this.progressRecorder = new ProgressRecorder(this.studentResolver, this.cacheManager, this.oneroster, this.caliper, this.edubridge);
|
|
195001
195355
|
this.sessionRecorder = new SessionRecorder(this.studentResolver, this.caliper);
|
|
195002
195356
|
if (this.credentials) {
|
|
195003
195357
|
this._ensureAuthenticated().catch((error2) => {
|
|
@@ -195106,6 +195460,9 @@ class TimebackClient {
|
|
|
195106
195460
|
}
|
|
195107
195461
|
await this.authenticate();
|
|
195108
195462
|
}
|
|
195463
|
+
async resolveStudent(studentIdentifier, providedEmail) {
|
|
195464
|
+
return this.studentResolver.resolve(studentIdentifier, providedEmail);
|
|
195465
|
+
}
|
|
195109
195466
|
async recordProgress(courseId, studentIdentifier, progressData) {
|
|
195110
195467
|
await this._ensureAuthenticated();
|
|
195111
195468
|
return this.progressRecorder.record(courseId, studentIdentifier, progressData);
|
|
@@ -195114,6 +195471,19 @@ class TimebackClient {
|
|
|
195114
195471
|
await this._ensureAuthenticated();
|
|
195115
195472
|
return this.sessionRecorder.record(courseId, studentIdentifier, sessionData);
|
|
195116
195473
|
}
|
|
195474
|
+
async getEnrollments(studentId, options) {
|
|
195475
|
+
await this._ensureAuthenticated();
|
|
195476
|
+
const classes = await this.oneroster.classes.listByStudent(studentId, options);
|
|
195477
|
+
return classes.filter((cls) => cls.sourcedId && cls.status && cls.course?.sourcedId).map((cls) => ({
|
|
195478
|
+
sourcedId: cls.sourcedId,
|
|
195479
|
+
title: cls.title,
|
|
195480
|
+
classCode: cls.classCode ?? null,
|
|
195481
|
+
courseId: cls.course.sourcedId,
|
|
195482
|
+
status: cls.status,
|
|
195483
|
+
grades: cls.grades ?? null,
|
|
195484
|
+
subjects: cls.subjects ?? null
|
|
195485
|
+
}));
|
|
195486
|
+
}
|
|
195117
195487
|
clearCaches() {
|
|
195118
195488
|
this.cacheManager.clearAll();
|
|
195119
195489
|
}
|
|
@@ -195125,6 +195495,7 @@ class TimebackClient {
|
|
|
195125
195495
|
}
|
|
195126
195496
|
oneroster;
|
|
195127
195497
|
caliper;
|
|
195498
|
+
edubridge;
|
|
195128
195499
|
async setup(config2, options) {
|
|
195129
195500
|
return setupTimebackResources(this, config2, options);
|
|
195130
195501
|
}
|
|
@@ -195141,6 +195512,306 @@ class TimebackClient {
|
|
|
195141
195512
|
return deleteTimebackResources(this, courseId);
|
|
195142
195513
|
}
|
|
195143
195514
|
}
|
|
195515
|
+
var __esm4 = (fn2, res) => () => (fn2 && (res = fn2(fn2 = 0)), res);
|
|
195516
|
+
var init_auth2 = () => {};
|
|
195517
|
+
var PLAYCADEMY_BASE_URLS2;
|
|
195518
|
+
var init_domains2 = __esm4(() => {
|
|
195519
|
+
PLAYCADEMY_BASE_URLS2 = {
|
|
195520
|
+
production: "https://hub.playcademy.net",
|
|
195521
|
+
staging: "https://hub.dev.playcademy.net"
|
|
195522
|
+
};
|
|
195523
|
+
});
|
|
195524
|
+
var init_env_vars2 = () => {};
|
|
195525
|
+
var ITEM_SLUGS3;
|
|
195526
|
+
var CURRENCIES3;
|
|
195527
|
+
var BADGES3;
|
|
195528
|
+
var init_overworld2 = __esm4(() => {
|
|
195529
|
+
ITEM_SLUGS3 = {
|
|
195530
|
+
PLAYCADEMY_CREDITS: "PLAYCADEMY_CREDITS",
|
|
195531
|
+
PLAYCADEMY_XP: "PLAYCADEMY_XP",
|
|
195532
|
+
FOUNDING_MEMBER_BADGE: "FOUNDING_MEMBER_BADGE",
|
|
195533
|
+
EARLY_ADOPTER_BADGE: "EARLY_ADOPTER_BADGE",
|
|
195534
|
+
FIRST_GAME_BADGE: "FIRST_GAME_BADGE",
|
|
195535
|
+
COMMON_SWORD: "COMMON_SWORD",
|
|
195536
|
+
SMALL_HEALTH_POTION: "SMALL_HEALTH_POTION",
|
|
195537
|
+
SMALL_BACKPACK: "SMALL_BACKPACK",
|
|
195538
|
+
LAVA_LAMP: "LAVA_LAMP",
|
|
195539
|
+
BOOMBOX: "BOOMBOX",
|
|
195540
|
+
CABIN_BED: "CABIN_BED"
|
|
195541
|
+
};
|
|
195542
|
+
CURRENCIES3 = {
|
|
195543
|
+
PRIMARY: ITEM_SLUGS3.PLAYCADEMY_CREDITS,
|
|
195544
|
+
XP: ITEM_SLUGS3.PLAYCADEMY_XP
|
|
195545
|
+
};
|
|
195546
|
+
BADGES3 = {
|
|
195547
|
+
FOUNDING_MEMBER: ITEM_SLUGS3.FOUNDING_MEMBER_BADGE,
|
|
195548
|
+
EARLY_ADOPTER: ITEM_SLUGS3.EARLY_ADOPTER_BADGE,
|
|
195549
|
+
FIRST_GAME: ITEM_SLUGS3.FIRST_GAME_BADGE
|
|
195550
|
+
};
|
|
195551
|
+
});
|
|
195552
|
+
var init_timeback2 = () => {};
|
|
195553
|
+
var init_workers2 = () => {};
|
|
195554
|
+
var init_src3 = __esm4(() => {
|
|
195555
|
+
init_auth2();
|
|
195556
|
+
init_domains2();
|
|
195557
|
+
init_env_vars2();
|
|
195558
|
+
init_overworld2();
|
|
195559
|
+
init_timeback2();
|
|
195560
|
+
init_workers2();
|
|
195561
|
+
});
|
|
195562
|
+
var TIMEBACK_API_URLS2;
|
|
195563
|
+
var TIMEBACK_AUTH_URLS2;
|
|
195564
|
+
var CALIPER_API_URLS2;
|
|
195565
|
+
var ONEROSTER_ENDPOINTS2;
|
|
195566
|
+
var CALIPER_ENDPOINTS2;
|
|
195567
|
+
var CALIPER_CONSTANTS2;
|
|
195568
|
+
var TIMEBACK_EVENT_TYPES2;
|
|
195569
|
+
var TIMEBACK_ACTIONS2;
|
|
195570
|
+
var TIMEBACK_TYPES2;
|
|
195571
|
+
var ACTIVITY_METRIC_TYPES2;
|
|
195572
|
+
var TIME_METRIC_TYPES2;
|
|
195573
|
+
var TIMEBACK_SUBJECTS2;
|
|
195574
|
+
var TIMEBACK_GRADE_LEVELS2;
|
|
195575
|
+
var TIMEBACK_GRADE_LEVEL_LABELS2;
|
|
195576
|
+
var CALIPER_SUBJECTS2;
|
|
195577
|
+
var ONEROSTER_STATUS2;
|
|
195578
|
+
var SCORE_STATUS2;
|
|
195579
|
+
var ENV_VARS2;
|
|
195580
|
+
var HTTP_DEFAULTS2;
|
|
195581
|
+
var AUTH_DEFAULTS2;
|
|
195582
|
+
var CACHE_DEFAULTS2;
|
|
195583
|
+
var CONFIG_DEFAULTS2;
|
|
195584
|
+
var DEFAULT_PLAYCADEMY_ORGANIZATION_ID2;
|
|
195585
|
+
var PLAYCADEMY_DEFAULTS2;
|
|
195586
|
+
var RESOURCE_DEFAULTS2;
|
|
195587
|
+
var HTTP_STATUS2;
|
|
195588
|
+
var ERROR_NAMES2;
|
|
195589
|
+
var init_constants2 = __esm4(() => {
|
|
195590
|
+
init_src3();
|
|
195591
|
+
TIMEBACK_API_URLS2 = {
|
|
195592
|
+
production: "https://api.alpha-1edtech.ai",
|
|
195593
|
+
staging: "https://api.staging.alpha-1edtech.com"
|
|
195594
|
+
};
|
|
195595
|
+
TIMEBACK_AUTH_URLS2 = {
|
|
195596
|
+
production: "https://prod-beyond-timeback-api-2-idp.auth.us-east-1.amazoncognito.com",
|
|
195597
|
+
staging: "https://alpha-auth-development-idp.auth.us-west-2.amazoncognito.com"
|
|
195598
|
+
};
|
|
195599
|
+
CALIPER_API_URLS2 = {
|
|
195600
|
+
production: "https://caliper.alpha-1edtech.ai",
|
|
195601
|
+
staging: "https://caliper-staging.alpha-1edtech.com"
|
|
195602
|
+
};
|
|
195603
|
+
ONEROSTER_ENDPOINTS2 = {
|
|
195604
|
+
organizations: "/ims/oneroster/rostering/v1p2/orgs",
|
|
195605
|
+
courses: "/ims/oneroster/rostering/v1p2/courses",
|
|
195606
|
+
courseComponents: "/ims/oneroster/rostering/v1p2/courses/components",
|
|
195607
|
+
resources: "/ims/oneroster/resources/v1p2/resources",
|
|
195608
|
+
componentResources: "/ims/oneroster/rostering/v1p2/courses/component-resources",
|
|
195609
|
+
classes: "/ims/oneroster/rostering/v1p2/classes",
|
|
195610
|
+
enrollments: "/ims/oneroster/rostering/v1p2/enrollments",
|
|
195611
|
+
assessmentLineItems: "/ims/oneroster/gradebook/v1p2/assessmentLineItems",
|
|
195612
|
+
assessmentResults: "/ims/oneroster/gradebook/v1p2/assessmentResults",
|
|
195613
|
+
users: "/ims/oneroster/rostering/v1p2/users"
|
|
195614
|
+
};
|
|
195615
|
+
CALIPER_ENDPOINTS2 = {
|
|
195616
|
+
events: "/caliper/event",
|
|
195617
|
+
validate: "/caliper/event/validate"
|
|
195618
|
+
};
|
|
195619
|
+
CALIPER_CONSTANTS2 = {
|
|
195620
|
+
context: "http://purl.imsglobal.org/ctx/caliper/v1p2",
|
|
195621
|
+
profile: "TimebackProfile",
|
|
195622
|
+
dataVersion: "http://purl.imsglobal.org/ctx/caliper/v1p2"
|
|
195623
|
+
};
|
|
195624
|
+
TIMEBACK_EVENT_TYPES2 = {
|
|
195625
|
+
activityEvent: "ActivityEvent",
|
|
195626
|
+
timeSpentEvent: "TimeSpentEvent"
|
|
195627
|
+
};
|
|
195628
|
+
TIMEBACK_ACTIONS2 = {
|
|
195629
|
+
completed: "Completed",
|
|
195630
|
+
spentTime: "SpentTime"
|
|
195631
|
+
};
|
|
195632
|
+
TIMEBACK_TYPES2 = {
|
|
195633
|
+
user: "TimebackUser",
|
|
195634
|
+
activityContext: "TimebackActivityContext",
|
|
195635
|
+
activityMetricsCollection: "TimebackActivityMetricsCollection",
|
|
195636
|
+
timeSpentMetricsCollection: "TimebackTimeSpentMetricsCollection"
|
|
195637
|
+
};
|
|
195638
|
+
ACTIVITY_METRIC_TYPES2 = {
|
|
195639
|
+
totalQuestions: "totalQuestions",
|
|
195640
|
+
correctQuestions: "correctQuestions",
|
|
195641
|
+
xpEarned: "xpEarned",
|
|
195642
|
+
masteredUnits: "masteredUnits"
|
|
195643
|
+
};
|
|
195644
|
+
TIME_METRIC_TYPES2 = {
|
|
195645
|
+
active: "active",
|
|
195646
|
+
inactive: "inactive",
|
|
195647
|
+
waste: "waste",
|
|
195648
|
+
unknown: "unknown",
|
|
195649
|
+
antiPattern: "anti-pattern"
|
|
195650
|
+
};
|
|
195651
|
+
TIMEBACK_SUBJECTS2 = [
|
|
195652
|
+
"Math",
|
|
195653
|
+
"FastMath",
|
|
195654
|
+
"Science",
|
|
195655
|
+
"Social Studies",
|
|
195656
|
+
"Language",
|
|
195657
|
+
"Reading",
|
|
195658
|
+
"Vocabulary",
|
|
195659
|
+
"Writing"
|
|
195660
|
+
];
|
|
195661
|
+
TIMEBACK_GRADE_LEVELS2 = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
|
|
195662
|
+
TIMEBACK_GRADE_LEVEL_LABELS2 = {
|
|
195663
|
+
"-1": "pre-k",
|
|
195664
|
+
"0": "kindergarten",
|
|
195665
|
+
"1": "1st grade",
|
|
195666
|
+
"2": "2nd grade",
|
|
195667
|
+
"3": "3rd grade",
|
|
195668
|
+
"4": "4th grade",
|
|
195669
|
+
"5": "5th grade",
|
|
195670
|
+
"6": "6th grade",
|
|
195671
|
+
"7": "7th grade",
|
|
195672
|
+
"8": "8th grade",
|
|
195673
|
+
"9": "9th grade",
|
|
195674
|
+
"10": "10th grade",
|
|
195675
|
+
"11": "11th grade",
|
|
195676
|
+
"12": "12th grade",
|
|
195677
|
+
"13": "AP"
|
|
195678
|
+
};
|
|
195679
|
+
CALIPER_SUBJECTS2 = {
|
|
195680
|
+
Reading: "Reading",
|
|
195681
|
+
Language: "Language",
|
|
195682
|
+
Vocabulary: "Vocabulary",
|
|
195683
|
+
SocialStudies: "Social Studies",
|
|
195684
|
+
Writing: "Writing",
|
|
195685
|
+
Science: "Science",
|
|
195686
|
+
FastMath: "FastMath",
|
|
195687
|
+
Math: "Math",
|
|
195688
|
+
None: "None"
|
|
195689
|
+
};
|
|
195690
|
+
ONEROSTER_STATUS2 = {
|
|
195691
|
+
active: "active",
|
|
195692
|
+
toBeDeleted: "tobedeleted"
|
|
195693
|
+
};
|
|
195694
|
+
SCORE_STATUS2 = {
|
|
195695
|
+
exempt: "exempt",
|
|
195696
|
+
fullyGraded: "fully graded",
|
|
195697
|
+
notSubmitted: "not submitted",
|
|
195698
|
+
partiallyGraded: "partially graded",
|
|
195699
|
+
submitted: "submitted"
|
|
195700
|
+
};
|
|
195701
|
+
ENV_VARS2 = {
|
|
195702
|
+
clientId: "TIMEBACK_CLIENT_ID",
|
|
195703
|
+
clientSecret: "TIMEBACK_CLIENT_SECRET",
|
|
195704
|
+
baseUrl: "TIMEBACK_BASE_URL",
|
|
195705
|
+
environment: "TIMEBACK_ENVIRONMENT",
|
|
195706
|
+
vendorResourceId: "TIMEBACK_VENDOR_RESOURCE_ID",
|
|
195707
|
+
launchBaseUrl: "GAME_URL"
|
|
195708
|
+
};
|
|
195709
|
+
HTTP_DEFAULTS2 = {
|
|
195710
|
+
timeout: 30000,
|
|
195711
|
+
retries: 3,
|
|
195712
|
+
retryBackoffBase: 2
|
|
195713
|
+
};
|
|
195714
|
+
AUTH_DEFAULTS2 = {
|
|
195715
|
+
tokenCacheDuration: 50000
|
|
195716
|
+
};
|
|
195717
|
+
CACHE_DEFAULTS2 = {
|
|
195718
|
+
defaultTTL: 600000,
|
|
195719
|
+
defaultMaxSize: 500,
|
|
195720
|
+
defaultName: "TimebackCache",
|
|
195721
|
+
studentTTL: 600000,
|
|
195722
|
+
studentMaxSize: 500,
|
|
195723
|
+
assessmentTTL: 1800000,
|
|
195724
|
+
assessmentMaxSize: 200
|
|
195725
|
+
};
|
|
195726
|
+
CONFIG_DEFAULTS2 = {
|
|
195727
|
+
fileNames: ["timeback.config.js", "timeback.config.json"]
|
|
195728
|
+
};
|
|
195729
|
+
DEFAULT_PLAYCADEMY_ORGANIZATION_ID2 = process.env.TIMEBACK_ORG_SOURCE_ID || "PLAYCADEMY";
|
|
195730
|
+
PLAYCADEMY_DEFAULTS2 = {
|
|
195731
|
+
organization: DEFAULT_PLAYCADEMY_ORGANIZATION_ID2,
|
|
195732
|
+
launchBaseUrls: PLAYCADEMY_BASE_URLS2
|
|
195733
|
+
};
|
|
195734
|
+
RESOURCE_DEFAULTS2 = {
|
|
195735
|
+
organization: {
|
|
195736
|
+
name: "Playcademy Studios",
|
|
195737
|
+
type: "department"
|
|
195738
|
+
},
|
|
195739
|
+
course: {
|
|
195740
|
+
gradingScheme: "STANDARD",
|
|
195741
|
+
level: {
|
|
195742
|
+
elementary: "Elementary",
|
|
195743
|
+
middle: "Middle",
|
|
195744
|
+
high: "High",
|
|
195745
|
+
ap: "AP"
|
|
195746
|
+
},
|
|
195747
|
+
metadata: {
|
|
195748
|
+
goals: {
|
|
195749
|
+
dailyXp: 50,
|
|
195750
|
+
dailyLessons: 3
|
|
195751
|
+
},
|
|
195752
|
+
metrics: {
|
|
195753
|
+
totalXp: 1000,
|
|
195754
|
+
totalLessons: 50
|
|
195755
|
+
}
|
|
195756
|
+
}
|
|
195757
|
+
},
|
|
195758
|
+
component: {
|
|
195759
|
+
sortOrder: 1,
|
|
195760
|
+
prerequisiteCriteria: "ALL"
|
|
195761
|
+
},
|
|
195762
|
+
resource: {
|
|
195763
|
+
vendorId: "playcademy",
|
|
195764
|
+
roles: ["primary"],
|
|
195765
|
+
importance: "primary",
|
|
195766
|
+
metadata: {
|
|
195767
|
+
type: "interactive",
|
|
195768
|
+
toolProvider: "Playcademy",
|
|
195769
|
+
instructionalMethod: "exploratory",
|
|
195770
|
+
language: "en-US"
|
|
195771
|
+
}
|
|
195772
|
+
},
|
|
195773
|
+
componentResource: {
|
|
195774
|
+
sortOrder: 1,
|
|
195775
|
+
lessonType: "quiz"
|
|
195776
|
+
}
|
|
195777
|
+
};
|
|
195778
|
+
HTTP_STATUS2 = {
|
|
195779
|
+
CLIENT_ERROR_MIN: 400,
|
|
195780
|
+
CLIENT_ERROR_MAX: 500,
|
|
195781
|
+
SERVER_ERROR_MIN: 500
|
|
195782
|
+
};
|
|
195783
|
+
ERROR_NAMES2 = {
|
|
195784
|
+
timebackAuth: "TimebackAuthError",
|
|
195785
|
+
timebackApi: "TimebackApiError",
|
|
195786
|
+
timebackConfig: "TimebackConfigError",
|
|
195787
|
+
timebackSdk: "TimebackSDKError"
|
|
195788
|
+
};
|
|
195789
|
+
});
|
|
195790
|
+
init_constants2();
|
|
195791
|
+
var isObject3 = (value) => typeof value === "object" && value !== null;
|
|
195792
|
+
var SUBJECT_VALUES = TIMEBACK_SUBJECTS2;
|
|
195793
|
+
var GRADE_VALUES = TIMEBACK_GRADE_LEVELS2;
|
|
195794
|
+
function isCourseMetadata(value) {
|
|
195795
|
+
return isObject3(value);
|
|
195796
|
+
}
|
|
195797
|
+
function isResourceMetadata(value) {
|
|
195798
|
+
return isObject3(value);
|
|
195799
|
+
}
|
|
195800
|
+
function isPlaycademyResourceMetadata2(value) {
|
|
195801
|
+
if (!isObject3(value)) {
|
|
195802
|
+
return false;
|
|
195803
|
+
}
|
|
195804
|
+
if (!("mastery" in value) || value.mastery === undefined) {
|
|
195805
|
+
return true;
|
|
195806
|
+
}
|
|
195807
|
+
return isObject3(value.mastery);
|
|
195808
|
+
}
|
|
195809
|
+
function isTimebackSubject(value) {
|
|
195810
|
+
return typeof value === "string" && SUBJECT_VALUES.includes(value);
|
|
195811
|
+
}
|
|
195812
|
+
function isTimebackGrade(value) {
|
|
195813
|
+
return typeof value === "number" && Number.isInteger(value) && GRADE_VALUES.includes(value);
|
|
195814
|
+
}
|
|
195144
195815
|
var UUID_REGEX = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
|
195145
195816
|
function isValidUUID(value) {
|
|
195146
195817
|
if (!value || typeof value !== "string") {
|
|
@@ -195417,6 +196088,32 @@ async function getTimebackClient() {
|
|
|
195417
196088
|
}
|
|
195418
196089
|
return timebackClient;
|
|
195419
196090
|
}
|
|
196091
|
+
function buildResourceMetadata({
|
|
196092
|
+
baseMetadata,
|
|
196093
|
+
subject,
|
|
196094
|
+
grade,
|
|
196095
|
+
totalXp,
|
|
196096
|
+
masterableUnits
|
|
196097
|
+
}) {
|
|
196098
|
+
const normalizedBaseMetadata = isResourceMetadata(baseMetadata) ? baseMetadata : undefined;
|
|
196099
|
+
const metadata2 = {
|
|
196100
|
+
...normalizedBaseMetadata || {}
|
|
196101
|
+
};
|
|
196102
|
+
metadata2.subject = subject;
|
|
196103
|
+
metadata2.grades = [grade];
|
|
196104
|
+
metadata2.xp = totalXp;
|
|
196105
|
+
if (masterableUnits !== undefined && masterableUnits !== null) {
|
|
196106
|
+
const existingPlaycademy = isPlaycademyResourceMetadata2(metadata2.playcademy) ? metadata2.playcademy : undefined;
|
|
196107
|
+
metadata2.playcademy = {
|
|
196108
|
+
...existingPlaycademy || {},
|
|
196109
|
+
mastery: {
|
|
196110
|
+
...existingPlaycademy?.mastery || {},
|
|
196111
|
+
masterableUnits
|
|
196112
|
+
}
|
|
196113
|
+
};
|
|
196114
|
+
}
|
|
196115
|
+
return metadata2;
|
|
196116
|
+
}
|
|
195420
196117
|
var AchievementCompletionType;
|
|
195421
196118
|
((AchievementCompletionType2) => {
|
|
195422
196119
|
AchievementCompletionType2["TIME_PLAYED_SESSION"] = "time_played_session";
|
|
@@ -195940,6 +196637,246 @@ var AchievementService = {
|
|
|
195940
196637
|
generateAchievementMessage
|
|
195941
196638
|
};
|
|
195942
196639
|
|
|
196640
|
+
class DiscordEmbedBuilder {
|
|
196641
|
+
embed = {};
|
|
196642
|
+
setTitle(title) {
|
|
196643
|
+
this.embed.title = title;
|
|
196644
|
+
return this;
|
|
196645
|
+
}
|
|
196646
|
+
setDescription(description) {
|
|
196647
|
+
this.embed.description = description;
|
|
196648
|
+
return this;
|
|
196649
|
+
}
|
|
196650
|
+
setUrl(url) {
|
|
196651
|
+
this.embed.url = url;
|
|
196652
|
+
return this;
|
|
196653
|
+
}
|
|
196654
|
+
setColor(color) {
|
|
196655
|
+
this.embed.color = color;
|
|
196656
|
+
return this;
|
|
196657
|
+
}
|
|
196658
|
+
setTimestamp(date4) {
|
|
196659
|
+
this.embed.timestamp = (date4 || new Date).toISOString();
|
|
196660
|
+
return this;
|
|
196661
|
+
}
|
|
196662
|
+
setAuthor(name4, options) {
|
|
196663
|
+
this.embed.author = {
|
|
196664
|
+
name: name4,
|
|
196665
|
+
url: options?.url,
|
|
196666
|
+
icon_url: options?.iconUrl
|
|
196667
|
+
};
|
|
196668
|
+
return this;
|
|
196669
|
+
}
|
|
196670
|
+
setFooter(text5, iconUrl) {
|
|
196671
|
+
this.embed.footer = {
|
|
196672
|
+
text: text5,
|
|
196673
|
+
icon_url: iconUrl
|
|
196674
|
+
};
|
|
196675
|
+
return this;
|
|
196676
|
+
}
|
|
196677
|
+
setThumbnail(url) {
|
|
196678
|
+
this.embed.thumbnail = { url };
|
|
196679
|
+
return this;
|
|
196680
|
+
}
|
|
196681
|
+
setImage(url) {
|
|
196682
|
+
this.embed.image = { url };
|
|
196683
|
+
return this;
|
|
196684
|
+
}
|
|
196685
|
+
addField(name4, value, inline = false) {
|
|
196686
|
+
if (!this.embed.fields) {
|
|
196687
|
+
this.embed.fields = [];
|
|
196688
|
+
}
|
|
196689
|
+
this.embed.fields.push({ name: name4, value, inline });
|
|
196690
|
+
return this;
|
|
196691
|
+
}
|
|
196692
|
+
addFields(...fields) {
|
|
196693
|
+
for (const field of fields) {
|
|
196694
|
+
this.addField(field.name, field.value, field.inline);
|
|
196695
|
+
}
|
|
196696
|
+
return this;
|
|
196697
|
+
}
|
|
196698
|
+
build() {
|
|
196699
|
+
return this.embed;
|
|
196700
|
+
}
|
|
196701
|
+
static create() {
|
|
196702
|
+
return new DiscordEmbedBuilder;
|
|
196703
|
+
}
|
|
196704
|
+
}
|
|
196705
|
+
|
|
196706
|
+
class DiscordClient {
|
|
196707
|
+
config;
|
|
196708
|
+
constructor(config2) {
|
|
196709
|
+
if (!config2.url) {
|
|
196710
|
+
throw new Error("Discord webhook URL is required");
|
|
196711
|
+
}
|
|
196712
|
+
if (!config2.url.startsWith("https://discord.com/api/webhooks/")) {
|
|
196713
|
+
throw new Error("Invalid Discord webhook URL format");
|
|
196714
|
+
}
|
|
196715
|
+
this.config = config2;
|
|
196716
|
+
}
|
|
196717
|
+
async send(message22) {
|
|
196718
|
+
const payload = {
|
|
196719
|
+
content: message22,
|
|
196720
|
+
username: this.config.username,
|
|
196721
|
+
avatar_url: this.config.avatarUrl
|
|
196722
|
+
};
|
|
196723
|
+
await this.sendPayload(payload);
|
|
196724
|
+
}
|
|
196725
|
+
async sendEmbed(embed) {
|
|
196726
|
+
const payload = {
|
|
196727
|
+
embeds: [embed],
|
|
196728
|
+
username: this.config.username,
|
|
196729
|
+
avatar_url: this.config.avatarUrl
|
|
196730
|
+
};
|
|
196731
|
+
await this.sendPayload(payload);
|
|
196732
|
+
}
|
|
196733
|
+
async sendEmbeds(embeds) {
|
|
196734
|
+
if (embeds.length > 10) {
|
|
196735
|
+
throw new Error("Discord allows maximum 10 embeds per message");
|
|
196736
|
+
}
|
|
196737
|
+
const payload = {
|
|
196738
|
+
embeds,
|
|
196739
|
+
username: this.config.username,
|
|
196740
|
+
avatar_url: this.config.avatarUrl
|
|
196741
|
+
};
|
|
196742
|
+
await this.sendPayload(payload);
|
|
196743
|
+
}
|
|
196744
|
+
async sendWithEmbeds(message22, embeds) {
|
|
196745
|
+
const payload = {
|
|
196746
|
+
content: message22,
|
|
196747
|
+
embeds,
|
|
196748
|
+
username: this.config.username,
|
|
196749
|
+
avatar_url: this.config.avatarUrl
|
|
196750
|
+
};
|
|
196751
|
+
await this.sendPayload(payload);
|
|
196752
|
+
}
|
|
196753
|
+
async sendRich(message22) {
|
|
196754
|
+
const builder = new DiscordEmbedBuilder;
|
|
196755
|
+
if (message22.title)
|
|
196756
|
+
builder.setTitle(message22.title);
|
|
196757
|
+
if (message22.description)
|
|
196758
|
+
builder.setDescription(message22.description);
|
|
196759
|
+
if (message22.url)
|
|
196760
|
+
builder.setUrl(message22.url);
|
|
196761
|
+
if (message22.color) {
|
|
196762
|
+
const color = typeof message22.color === "string" ? parseInt(message22.color.replace("#", ""), 16) : message22.color;
|
|
196763
|
+
builder.setColor(color);
|
|
196764
|
+
}
|
|
196765
|
+
if (message22.author) {
|
|
196766
|
+
builder.setAuthor(message22.author.name, {
|
|
196767
|
+
url: message22.author.url,
|
|
196768
|
+
iconUrl: message22.author.iconUrl
|
|
196769
|
+
});
|
|
196770
|
+
}
|
|
196771
|
+
if (message22.fields) {
|
|
196772
|
+
for (const field of message22.fields) {
|
|
196773
|
+
builder.addField(field.name, field.value, field.inline);
|
|
196774
|
+
}
|
|
196775
|
+
}
|
|
196776
|
+
if (message22.footer) {
|
|
196777
|
+
builder.setFooter(message22.footer.text, message22.footer.iconUrl);
|
|
196778
|
+
}
|
|
196779
|
+
if (message22.timestamp) {
|
|
196780
|
+
const date4 = message22.timestamp instanceof Date ? message22.timestamp : new Date(message22.timestamp);
|
|
196781
|
+
builder.setTimestamp(date4);
|
|
196782
|
+
}
|
|
196783
|
+
if (message22.thumbnail) {
|
|
196784
|
+
builder.setThumbnail(message22.thumbnail.url);
|
|
196785
|
+
}
|
|
196786
|
+
if (message22.image) {
|
|
196787
|
+
builder.setImage(message22.image.url);
|
|
196788
|
+
}
|
|
196789
|
+
await this.sendEmbed(builder.build());
|
|
196790
|
+
}
|
|
196791
|
+
async sendPayload(payload) {
|
|
196792
|
+
const response = await fetch(this.config.url, {
|
|
196793
|
+
method: "POST",
|
|
196794
|
+
headers: {
|
|
196795
|
+
"Content-Type": "application/json"
|
|
196796
|
+
},
|
|
196797
|
+
body: JSON.stringify(payload)
|
|
196798
|
+
});
|
|
196799
|
+
if (!response.ok) {
|
|
196800
|
+
const errorText = await response.text().catch(() => "Unknown error");
|
|
196801
|
+
throw new Error(`Discord webhook request failed: ${response.status} ${response.statusText} - ${errorText}`);
|
|
196802
|
+
}
|
|
196803
|
+
}
|
|
196804
|
+
getRedactedUrl() {
|
|
196805
|
+
const parts2 = this.config.url.split("/");
|
|
196806
|
+
const token = parts2[parts2.length - 1];
|
|
196807
|
+
return `${token?.slice(0, 9)}...`;
|
|
196808
|
+
}
|
|
196809
|
+
}
|
|
196810
|
+
var DiscordColors = {
|
|
196811
|
+
DEFAULT: 0,
|
|
196812
|
+
WHITE: 16777215,
|
|
196813
|
+
AQUA: 1752220,
|
|
196814
|
+
GREEN: 5763719,
|
|
196815
|
+
BLUE: 3447003,
|
|
196816
|
+
YELLOW: 16705372,
|
|
196817
|
+
PURPLE: 10181046,
|
|
196818
|
+
LUMINOUS_VIVID_PINK: 15277667,
|
|
196819
|
+
FUCHSIA: 15418782,
|
|
196820
|
+
GOLD: 15844367,
|
|
196821
|
+
ORANGE: 15105570,
|
|
196822
|
+
RED: 15548997,
|
|
196823
|
+
GREY: 9807270,
|
|
196824
|
+
NAVY: 3426654,
|
|
196825
|
+
DARK_AQUA: 1146986,
|
|
196826
|
+
DARK_GREEN: 2067276,
|
|
196827
|
+
DARK_BLUE: 2123412,
|
|
196828
|
+
DARK_PURPLE: 7419530,
|
|
196829
|
+
DARK_VIVID_PINK: 11342935,
|
|
196830
|
+
DARK_GOLD: 12745742,
|
|
196831
|
+
DARK_ORANGE: 11027200,
|
|
196832
|
+
DARK_RED: 10038562,
|
|
196833
|
+
DARK_GREY: 9936031,
|
|
196834
|
+
DARKER_GREY: 8359053,
|
|
196835
|
+
LIGHT_GREY: 12370112,
|
|
196836
|
+
DARK_NAVY: 2899536,
|
|
196837
|
+
BLURPLE: 5793266,
|
|
196838
|
+
GREYPLE: 10070709,
|
|
196839
|
+
DARK_BUT_NOT_BLACK: 2895667,
|
|
196840
|
+
NOT_QUITE_BLACK: 2303786
|
|
196841
|
+
};
|
|
196842
|
+
init_src();
|
|
196843
|
+
function getDiscordClient() {
|
|
196844
|
+
const webhookUrl = process.env.DISCORD_WEBHOOK_PLATFORM;
|
|
196845
|
+
if (!webhookUrl) {
|
|
196846
|
+
log2.debug("[API] Discord webhook not configured, skipping notification");
|
|
196847
|
+
return null;
|
|
196848
|
+
}
|
|
196849
|
+
return new DiscordClient({
|
|
196850
|
+
url: webhookUrl,
|
|
196851
|
+
username: "Playcademy Platform",
|
|
196852
|
+
avatarUrl: process.env.DISCORD_WEBHOOK_AVATAR_URL
|
|
196853
|
+
});
|
|
196854
|
+
}
|
|
196855
|
+
function getEnvironment() {
|
|
196856
|
+
const stage = process.env.SST_STAGE;
|
|
196857
|
+
return stage === "production" ? "production" : stage === "dev" ? "staging" : "test";
|
|
196858
|
+
}
|
|
196859
|
+
async function sendDeveloperApplicationAlert(user) {
|
|
196860
|
+
const discord = getDiscordClient();
|
|
196861
|
+
if (!discord)
|
|
196862
|
+
return;
|
|
196863
|
+
const embed = new DiscordEmbedBuilder().setTitle("\uD83C\uDFAE New Developer Application").setDescription(`A user has applied for developer status (**${getEnvironment()}**).`).setColor(DiscordColors.GREEN).addField("User ID", user.id, true).addField("Email", user.email || "Not provided", true).setFooter("Playcademy Developer Platform").setTimestamp().build();
|
|
196864
|
+
await discord.sendEmbed(embed);
|
|
196865
|
+
log2.debug("[API] Discord notification sent successfully", {
|
|
196866
|
+
userId: user.id
|
|
196867
|
+
});
|
|
196868
|
+
}
|
|
196869
|
+
async function sendGameDeletionAlert(game) {
|
|
196870
|
+
const discord = getDiscordClient();
|
|
196871
|
+
if (!discord)
|
|
196872
|
+
return;
|
|
196873
|
+
const embed = new DiscordEmbedBuilder().setTitle("\uD83D\uDDD1️ Game Deleted").setDescription(`**${game.displayName || game.slug}** has been deleted (**${getEnvironment()}**).`).setColor(DiscordColors.ORANGE).addField("Slug", game.slug, true).addField("Developer", game.developer.email || game.developer.id, true).setFooter("Playcademy Developer Platform").setTimestamp().build();
|
|
196874
|
+
await discord.sendEmbed(embed);
|
|
196875
|
+
log2.debug("[API] Discord game deletion notification sent", {
|
|
196876
|
+
slug: game.slug
|
|
196877
|
+
});
|
|
196878
|
+
}
|
|
196879
|
+
|
|
195943
196880
|
class JwtBaseError extends Error {
|
|
195944
196881
|
}
|
|
195945
196882
|
|
|
@@ -197862,7 +198799,6 @@ function normalizeDeploymentOptions(options) {
|
|
|
197862
198799
|
assets: options?.bindings?.assets ?? false
|
|
197863
198800
|
},
|
|
197864
198801
|
assetsPath: options?.assetsPath,
|
|
197865
|
-
assetsZip: options?.assetsZip,
|
|
197866
198802
|
keepAssets: options?.keepAssets
|
|
197867
198803
|
};
|
|
197868
198804
|
}
|
|
@@ -197909,34 +198845,6 @@ var CUSTOM_DOMAINS_KV_NAME = "cademy-custom-domains";
|
|
|
197909
198845
|
var DEFAULT_COMPATIBILITY_DATE2 = new Date().toISOString().slice(0, 10);
|
|
197910
198846
|
var GAME_WORKER_DOMAIN_PRODUCTION = GAME_WORKER_DOMAINS.production;
|
|
197911
198847
|
var GAME_WORKER_DOMAIN_STAGING = GAME_WORKER_DOMAINS.staging;
|
|
197912
|
-
var esbuild = __toESM2(require_main(), 1);
|
|
197913
|
-
async function bundleWorker(filePath) {
|
|
197914
|
-
const result = await esbuild.build({
|
|
197915
|
-
entryPoints: [filePath],
|
|
197916
|
-
bundle: true,
|
|
197917
|
-
format: "esm",
|
|
197918
|
-
platform: "browser",
|
|
197919
|
-
target: "es2022",
|
|
197920
|
-
write: false,
|
|
197921
|
-
minify: false,
|
|
197922
|
-
sourcemap: false,
|
|
197923
|
-
logLevel: "error"
|
|
197924
|
-
});
|
|
197925
|
-
if (!result.outputFiles?.[0]) {
|
|
197926
|
-
throw new Error(`No output generated for worker ${filePath}`);
|
|
197927
|
-
}
|
|
197928
|
-
return result.outputFiles[0].text;
|
|
197929
|
-
}
|
|
197930
|
-
var _cachedStubWorker = null;
|
|
197931
|
-
async function getStubWorkerCode() {
|
|
197932
|
-
if (_cachedStubWorker) {
|
|
197933
|
-
return _cachedStubWorker;
|
|
197934
|
-
}
|
|
197935
|
-
const currentDir = dirname2(fileURLToPath(import.meta.url));
|
|
197936
|
-
const workerPath = join4(currentDir, "stub-worker.ts");
|
|
197937
|
-
_cachedStubWorker = await bundleWorker(workerPath);
|
|
197938
|
-
return _cachedStubWorker;
|
|
197939
|
-
}
|
|
197940
198848
|
|
|
197941
198849
|
class CloudflareProvider {
|
|
197942
198850
|
client;
|
|
@@ -197978,7 +198886,7 @@ class CloudflareProvider {
|
|
|
197978
198886
|
async function scanDirectory(dir) {
|
|
197979
198887
|
const entries = await readdir2(dir, { withFileTypes: true });
|
|
197980
198888
|
for (const entry of entries) {
|
|
197981
|
-
const fullPath =
|
|
198889
|
+
const fullPath = join4(dir, entry.name);
|
|
197982
198890
|
if (entry.isDirectory()) {
|
|
197983
198891
|
if (await scanDirectory(fullPath))
|
|
197984
198892
|
return true;
|
|
@@ -198000,7 +198908,7 @@ class CloudflareProvider {
|
|
|
198000
198908
|
async resolveAssetBasePath(dirPath) {
|
|
198001
198909
|
const entries = await readdir2(dirPath, { withFileTypes: true });
|
|
198002
198910
|
if (entries.length === 1 && entries[0]?.isDirectory()) {
|
|
198003
|
-
const unwrappedPath =
|
|
198911
|
+
const unwrappedPath = join4(dirPath, entries[0].name);
|
|
198004
198912
|
log2.debug("[CloudflareProvider] Unwrapping wrapper directory", {
|
|
198005
198913
|
wrapper: entries[0].name
|
|
198006
198914
|
});
|
|
@@ -198011,7 +198919,7 @@ class CloudflareProvider {
|
|
|
198011
198919
|
async uploadFilesToR2(dir, baseDir, bucketName) {
|
|
198012
198920
|
const entries = await readdir2(dir, { withFileTypes: true });
|
|
198013
198921
|
for (const entry of entries) {
|
|
198014
|
-
const fullPath =
|
|
198922
|
+
const fullPath = join4(dir, entry.name);
|
|
198015
198923
|
if (entry.isDirectory()) {
|
|
198016
198924
|
await this.uploadFilesToR2(fullPath, baseDir, bucketName);
|
|
198017
198925
|
} else {
|
|
@@ -198034,38 +198942,15 @@ class CloudflareProvider {
|
|
|
198034
198942
|
async deploy(deploymentId, code, env2, options) {
|
|
198035
198943
|
const opts = normalizeDeploymentOptions(options);
|
|
198036
198944
|
const isFirstDeploy = env2.PLAYCADEMY_API_KEY !== undefined;
|
|
198037
|
-
const hasAssets = !!
|
|
198038
|
-
let finalCode = code ?? "";
|
|
198945
|
+
const hasAssets = !!opts.assetsPath;
|
|
198039
198946
|
if (!code) {
|
|
198040
|
-
|
|
198041
|
-
log2.debug("[CloudflareProvider] Fetching existing script", {
|
|
198042
|
-
deploymentId,
|
|
198043
|
-
namespace: this.config.dispatchNamespace
|
|
198044
|
-
});
|
|
198045
|
-
finalCode = await this.client.workers.getScriptContent(this.config.dispatchNamespace, deploymentId);
|
|
198046
|
-
} catch {
|
|
198047
|
-
log2.debug("[CloudflareProvider] No existing script, using stub worker", {
|
|
198048
|
-
deploymentId
|
|
198049
|
-
});
|
|
198050
|
-
finalCode = await getStubWorkerCode();
|
|
198051
|
-
}
|
|
198947
|
+
throw new Error(`No worker code provided for deployment. Frontend-only deployments should include a stub worker from the CLI.`);
|
|
198052
198948
|
}
|
|
198949
|
+
const finalCode = code;
|
|
198053
198950
|
if (opts.keepAssets === undefined) {
|
|
198054
198951
|
opts.keepAssets = true;
|
|
198055
198952
|
}
|
|
198056
|
-
|
|
198057
|
-
let finalAssetsPath = opts.assetsPath;
|
|
198058
|
-
if (opts.assetsZip && !opts.assetsPath) {
|
|
198059
|
-
tempDir = join5(tmpdir(), `playcademy-assets-${Date.now()}`);
|
|
198060
|
-
finalAssetsPath = join5(tempDir, "dist");
|
|
198061
|
-
await mkdir(finalAssetsPath, { recursive: true });
|
|
198062
|
-
await writeFile(join5(tempDir, "temp.zip"), opts.assetsZip);
|
|
198063
|
-
execSync(`unzip -q ${join5(tempDir, "temp.zip")} -d ${finalAssetsPath}`);
|
|
198064
|
-
log2.debug("[CloudflareProvider] Extracted ZIP to temp directory", {
|
|
198065
|
-
tempDir,
|
|
198066
|
-
size: opts.assetsZip.length
|
|
198067
|
-
});
|
|
198068
|
-
}
|
|
198953
|
+
const finalAssetsPath = opts.assetsPath;
|
|
198069
198954
|
log2.info("[CloudflareProvider] Deploying worker to dispatch namespace", {
|
|
198070
198955
|
deploymentId,
|
|
198071
198956
|
namespace: this.config.dispatchNamespace,
|
|
@@ -198194,10 +199079,6 @@ class CloudflareProvider {
|
|
|
198194
199079
|
error: error2
|
|
198195
199080
|
});
|
|
198196
199081
|
throw new Error(`Failed to deploy to Cloudflare Workers for Platforms: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
198197
|
-
} finally {
|
|
198198
|
-
if (tempDir) {
|
|
198199
|
-
await rm(tempDir, { recursive: true, force: true }).catch(() => {});
|
|
198200
|
-
}
|
|
198201
199082
|
}
|
|
198202
199083
|
}
|
|
198203
199084
|
async delete(deploymentId, options) {
|
|
@@ -198277,6 +199158,7 @@ class CloudflareProvider {
|
|
|
198277
199158
|
});
|
|
198278
199159
|
}
|
|
198279
199160
|
}
|
|
199161
|
+
var esbuild = __toESM2(require_main(), 1);
|
|
198280
199162
|
init_src();
|
|
198281
199163
|
var cloudflareProvider = null;
|
|
198282
199164
|
function getCloudflareProvider() {
|
|
@@ -198537,6 +199419,21 @@ var logger3 = {
|
|
|
198537
199419
|
warn: (msg) => getLogger().warn(msg),
|
|
198538
199420
|
error: (msg) => getLogger().error(msg)
|
|
198539
199421
|
};
|
|
199422
|
+
function detectTimebackCourses() {
|
|
199423
|
+
const coursePattern = /^SANDBOX_TIMEBACK_COURSE_(\d+)_([A-Z_]+)$/i;
|
|
199424
|
+
const courses = [];
|
|
199425
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
199426
|
+
const match2 = key.match(coursePattern);
|
|
199427
|
+
if (match2 && value) {
|
|
199428
|
+
const gradeStr = match2[1];
|
|
199429
|
+
const subjectStr = match2[2];
|
|
199430
|
+
const grade = parseInt(gradeStr, 10);
|
|
199431
|
+
const subject = subjectStr.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join("");
|
|
199432
|
+
courses.push({ grade, subject, courseId: value });
|
|
199433
|
+
}
|
|
199434
|
+
}
|
|
199435
|
+
return courses;
|
|
199436
|
+
}
|
|
198540
199437
|
async function seedCoreGames(db) {
|
|
198541
199438
|
const now2 = new Date;
|
|
198542
199439
|
const coreGames = [
|
|
@@ -198561,18 +199458,26 @@ async function seedCoreGames(db) {
|
|
|
198561
199458
|
console.error(`Error seeding core game '${gameData.slug}':`, error2);
|
|
198562
199459
|
}
|
|
198563
199460
|
}
|
|
198564
|
-
if (
|
|
198565
|
-
|
|
198566
|
-
|
|
198567
|
-
|
|
198568
|
-
|
|
198569
|
-
|
|
198570
|
-
|
|
198571
|
-
|
|
198572
|
-
|
|
198573
|
-
|
|
198574
|
-
|
|
198575
|
-
|
|
199461
|
+
if (hasTimebackCredentials()) {
|
|
199462
|
+
const courses = detectTimebackCourses();
|
|
199463
|
+
if (courses.length > 0) {
|
|
199464
|
+
for (const course of courses) {
|
|
199465
|
+
try {
|
|
199466
|
+
await db.insert(gameTimebackIntegrations).values({
|
|
199467
|
+
id: crypto.randomUUID(),
|
|
199468
|
+
gameId: CORE_GAME_UUIDS.PLAYGROUND,
|
|
199469
|
+
courseId: course.courseId,
|
|
199470
|
+
grade: course.grade,
|
|
199471
|
+
subject: course.subject,
|
|
199472
|
+
totalXp: null,
|
|
199473
|
+
lastVerifiedAt: null,
|
|
199474
|
+
createdAt: now2,
|
|
199475
|
+
updatedAt: now2
|
|
199476
|
+
}).onConflictDoNothing();
|
|
199477
|
+
} catch (error2) {
|
|
199478
|
+
console.error(`Error seeding TimeBack integration for playground (${course.subject} grade ${course.grade}):`, error2);
|
|
199479
|
+
}
|
|
199480
|
+
}
|
|
198576
199481
|
}
|
|
198577
199482
|
}
|
|
198578
199483
|
}
|
|
@@ -198603,18 +199508,23 @@ async function seedCurrentProjectGame(db, project) {
|
|
|
198603
199508
|
updatedAt: now2
|
|
198604
199509
|
};
|
|
198605
199510
|
const [newGame] = await db.insert(games).values(gameRecord).returning();
|
|
198606
|
-
if (
|
|
198607
|
-
|
|
198608
|
-
|
|
198609
|
-
|
|
198610
|
-
|
|
198611
|
-
|
|
198612
|
-
|
|
198613
|
-
|
|
198614
|
-
|
|
198615
|
-
|
|
198616
|
-
|
|
198617
|
-
|
|
199511
|
+
if (hasTimebackCredentials()) {
|
|
199512
|
+
const courses = detectTimebackCourses();
|
|
199513
|
+
if (courses.length > 0) {
|
|
199514
|
+
for (const course of courses) {
|
|
199515
|
+
await db.insert(gameTimebackIntegrations).values({
|
|
199516
|
+
id: crypto.randomUUID(),
|
|
199517
|
+
gameId: newGame.id,
|
|
199518
|
+
courseId: course.courseId,
|
|
199519
|
+
grade: course.grade,
|
|
199520
|
+
subject: course.subject,
|
|
199521
|
+
totalXp: null,
|
|
199522
|
+
lastVerifiedAt: null,
|
|
199523
|
+
createdAt: now2,
|
|
199524
|
+
updatedAt: now2
|
|
199525
|
+
}).onConflictDoNothing();
|
|
199526
|
+
}
|
|
199527
|
+
}
|
|
198618
199528
|
}
|
|
198619
199529
|
return newGame;
|
|
198620
199530
|
} catch (error2) {
|
|
@@ -198942,6 +199852,12 @@ async function applyForDeveloperStatus(ctx) {
|
|
|
198942
199852
|
userId: user.id,
|
|
198943
199853
|
newStatus: "pending"
|
|
198944
199854
|
});
|
|
199855
|
+
sendDeveloperApplicationAlert(fullUser).catch((error2) => {
|
|
199856
|
+
log2.error("[API] Failed to send Discord notification for developer application", {
|
|
199857
|
+
userId: user.id,
|
|
199858
|
+
error: error2 instanceof Error ? error2.message : String(error2)
|
|
199859
|
+
});
|
|
199860
|
+
});
|
|
198945
199861
|
} catch (error2) {
|
|
198946
199862
|
log2.error(`Error updating developer status for user ${user.id}:`, {
|
|
198947
199863
|
error: error2
|
|
@@ -203654,6 +204570,67 @@ var NotificationStatsSchema = exports_external2.object({
|
|
|
203654
204570
|
startDate: exports_external2.date().optional(),
|
|
203655
204571
|
endDate: exports_external2.date().optional()
|
|
203656
204572
|
});
|
|
204573
|
+
var InsertTimebackDailyXpSchema = createInsertSchema(timebackDailyXp, {
|
|
204574
|
+
xp: exports_external2.number().min(0, "XP must be a non-negative number"),
|
|
204575
|
+
date: exports_external2.date()
|
|
204576
|
+
}).omit({ createdAt: true, updatedAt: true });
|
|
204577
|
+
var SelectTimebackDailyXpSchema = createSelectSchema(timebackDailyXp);
|
|
204578
|
+
var UpdateTimebackDailyXpSchema = createUpdateSchema(timebackDailyXp, {
|
|
204579
|
+
xp: exports_external2.number().min(0, "XP must be a non-negative number")
|
|
204580
|
+
}).omit({ userId: true, createdAt: true });
|
|
204581
|
+
var UpdateTimebackXpRequestSchema = exports_external2.object({
|
|
204582
|
+
xp: exports_external2.number().min(0, "XP must be a non-negative number"),
|
|
204583
|
+
userTimestamp: exports_external2.string().datetime().optional()
|
|
204584
|
+
});
|
|
204585
|
+
var TimebackDateQuerySchema = exports_external2.object({
|
|
204586
|
+
date: exports_external2.string().datetime().optional()
|
|
204587
|
+
});
|
|
204588
|
+
var TimebackHistoryQuerySchema = exports_external2.object({
|
|
204589
|
+
startDate: exports_external2.string().date().optional(),
|
|
204590
|
+
endDate: exports_external2.string().date().optional()
|
|
204591
|
+
});
|
|
204592
|
+
var InsertTimebackXpEventSchema = createInsertSchema(timebackXpEvents, {
|
|
204593
|
+
occurredAt: exports_external2.date(),
|
|
204594
|
+
xpDelta: exports_external2.number()
|
|
204595
|
+
}).omit({ createdAt: true, updatedAt: true });
|
|
204596
|
+
var SelectTimebackXpEventSchema = createSelectSchema(timebackXpEvents);
|
|
204597
|
+
var InsertGameTimebackIntegrationSchema = createInsertSchema(gameTimebackIntegrations, {
|
|
204598
|
+
gameId: exports_external2.string().uuid(),
|
|
204599
|
+
courseId: exports_external2.string().min(1),
|
|
204600
|
+
grade: exports_external2.number().int(),
|
|
204601
|
+
subject: exports_external2.string().min(1),
|
|
204602
|
+
totalXp: exports_external2.number().int().positive().optional()
|
|
204603
|
+
}).omit({ id: true, createdAt: true, updatedAt: true });
|
|
204604
|
+
var SelectGameTimebackIntegrationSchema = createSelectSchema(gameTimebackIntegrations);
|
|
204605
|
+
var UpdateGameTimebackIntegrationSchema = createUpdateSchema(gameTimebackIntegrations, {
|
|
204606
|
+
courseId: exports_external2.string().min(1).optional(),
|
|
204607
|
+
totalXp: exports_external2.number().int().positive().optional(),
|
|
204608
|
+
lastVerifiedAt: exports_external2.date().optional()
|
|
204609
|
+
}).omit({ id: true, gameId: true, grade: true, subject: true, createdAt: true });
|
|
204610
|
+
var EndActivityRequestSchema = exports_external2.object({
|
|
204611
|
+
gameId: exports_external2.string().uuid(),
|
|
204612
|
+
studentId: exports_external2.string().min(1),
|
|
204613
|
+
activityData: exports_external2.object({
|
|
204614
|
+
activityId: exports_external2.string().min(1),
|
|
204615
|
+
activityName: exports_external2.string().optional(),
|
|
204616
|
+
grade: exports_external2.number().int(),
|
|
204617
|
+
subject: exports_external2.string().min(1),
|
|
204618
|
+
appName: exports_external2.string().optional(),
|
|
204619
|
+
sensorUrl: exports_external2.string().url().optional(),
|
|
204620
|
+
courseId: exports_external2.string().optional(),
|
|
204621
|
+
courseName: exports_external2.string().optional(),
|
|
204622
|
+
studentEmail: exports_external2.string().email().optional()
|
|
204623
|
+
}),
|
|
204624
|
+
scoreData: exports_external2.object({
|
|
204625
|
+
correctQuestions: exports_external2.number().int().min(0),
|
|
204626
|
+
totalQuestions: exports_external2.number().int().min(0)
|
|
204627
|
+
}),
|
|
204628
|
+
timingData: exports_external2.object({
|
|
204629
|
+
durationSeconds: exports_external2.number().positive()
|
|
204630
|
+
}),
|
|
204631
|
+
xpEarned: exports_external2.number().optional(),
|
|
204632
|
+
masteredUnits: exports_external2.number().nonnegative().optional()
|
|
204633
|
+
});
|
|
203657
204634
|
init_src();
|
|
203658
204635
|
async function submitScore(ctx) {
|
|
203659
204636
|
const { user, params, request: request3 } = ctx;
|
|
@@ -203821,6 +204798,26 @@ async function getUserAllScores(ctx) {
|
|
|
203821
204798
|
throw ApiError.internal("Failed to fetch user scores");
|
|
203822
204799
|
}
|
|
203823
204800
|
}
|
|
204801
|
+
async function getUserScores(ctx) {
|
|
204802
|
+
const user = ctx.user;
|
|
204803
|
+
if (!user) {
|
|
204804
|
+
throw ApiError.unauthorized("Must be logged in to view user scores");
|
|
204805
|
+
}
|
|
204806
|
+
const { params, url } = ctx;
|
|
204807
|
+
const gameId = params.gameId;
|
|
204808
|
+
const userId = params.userId;
|
|
204809
|
+
if (!gameId || !userId) {
|
|
204810
|
+
throw ApiError.badRequest("Game ID and User ID are required");
|
|
204811
|
+
}
|
|
204812
|
+
const limit2 = Math.min(Number(url.searchParams.get("limit") || "10"), 100);
|
|
204813
|
+
const db = getDatabase();
|
|
204814
|
+
try {
|
|
204815
|
+
const scores = await db.select().from(gameScores).where(and(eq(gameScores.gameId, gameId), eq(gameScores.userId, userId))).orderBy(desc(gameScores.achievedAt)).limit(limit2);
|
|
204816
|
+
return scores;
|
|
204817
|
+
} catch {
|
|
204818
|
+
throw ApiError.internal("Failed to fetch user scores");
|
|
204819
|
+
}
|
|
204820
|
+
}
|
|
203824
204821
|
init_src();
|
|
203825
204822
|
async function getUserLevel(ctx) {
|
|
203826
204823
|
const user = ctx.user;
|
|
@@ -204464,7 +205461,7 @@ async function deleteGame(ctx) {
|
|
|
204464
205461
|
const db = getDatabase();
|
|
204465
205462
|
const gameToDelete = await db.query.games.findFirst({
|
|
204466
205463
|
where: eq(games.id, gameId),
|
|
204467
|
-
columns: { id: true, slug: true }
|
|
205464
|
+
columns: { id: true, slug: true, displayName: true }
|
|
204468
205465
|
});
|
|
204469
205466
|
if (!gameToDelete || !gameToDelete.slug) {
|
|
204470
205467
|
throw ApiError.notFound("Game not found for deletion");
|
|
@@ -204486,6 +205483,16 @@ async function deleteGame(ctx) {
|
|
|
204486
205483
|
hadActiveDeployment: !!activeDeployment,
|
|
204487
205484
|
customDomainsCount: customDomains.length
|
|
204488
205485
|
});
|
|
205486
|
+
sendGameDeletionAlert({
|
|
205487
|
+
slug: gameToDelete.slug,
|
|
205488
|
+
displayName: gameToDelete.displayName,
|
|
205489
|
+
developer: {
|
|
205490
|
+
id: user.id,
|
|
205491
|
+
email: user.email
|
|
205492
|
+
}
|
|
205493
|
+
}).catch((err2) => {
|
|
205494
|
+
log2.warn("[API] Failed to send Discord game deletion notification", { err: err2 });
|
|
205495
|
+
});
|
|
204489
205496
|
if (activeDeployment?.provider === "cloudflare") {
|
|
204490
205497
|
try {
|
|
204491
205498
|
const cloudflare2 = getCloudflareProvider();
|
|
@@ -206049,6 +207056,26 @@ gameScoresRouter.post("/:gameId/scores", async (c3) => {
|
|
|
206049
207056
|
return c3.json(createUnknownErrorResponse(error2), 500);
|
|
206050
207057
|
}
|
|
206051
207058
|
});
|
|
207059
|
+
gameScoresRouter.get("/:gameId/users/:userId/scores", async (c3) => {
|
|
207060
|
+
const gameId = c3.req.param("gameId");
|
|
207061
|
+
const userId = c3.req.param("userId");
|
|
207062
|
+
const ctx = {
|
|
207063
|
+
user: c3.get("user"),
|
|
207064
|
+
params: { gameId, userId },
|
|
207065
|
+
url: new URL(c3.req.url),
|
|
207066
|
+
request: c3.req.raw
|
|
207067
|
+
};
|
|
207068
|
+
try {
|
|
207069
|
+
const result = await getUserScores(ctx);
|
|
207070
|
+
return c3.json(result, 200);
|
|
207071
|
+
} catch (error2) {
|
|
207072
|
+
if (error2 instanceof ApiError) {
|
|
207073
|
+
return c3.json(createErrorResponse(error2), error2.statusCode);
|
|
207074
|
+
}
|
|
207075
|
+
console.error("Error in getUserScores:", error2);
|
|
207076
|
+
return c3.json(createUnknownErrorResponse(error2), 500);
|
|
207077
|
+
}
|
|
207078
|
+
});
|
|
206052
207079
|
init_src();
|
|
206053
207080
|
async function startGameSession(ctx) {
|
|
206054
207081
|
const user = ctx.user;
|
|
@@ -208785,39 +209812,21 @@ async function endActivity(ctx) {
|
|
|
208785
209812
|
throw ApiError.unauthorized("Must be logged in to end activity");
|
|
208786
209813
|
}
|
|
208787
209814
|
log2.debug("[API] Ending activity", { userId: user.id });
|
|
208788
|
-
|
|
208789
|
-
|
|
208790
|
-
|
|
208791
|
-
|
|
208792
|
-
} catch (error2) {
|
|
208793
|
-
log2.error("[API] Failed to parse request body:", { error: error2 });
|
|
208794
|
-
throw ApiError.badRequest("Invalid JSON body");
|
|
208795
|
-
}
|
|
208796
|
-
const { gameId, studentId, activityData, scoreData, timingData, xpEarned } = request3;
|
|
208797
|
-
if (!activityData?.activityId) {
|
|
208798
|
-
throw ApiError.badRequest("activityId is required");
|
|
208799
|
-
}
|
|
208800
|
-
if (typeof scoreData?.correctQuestions !== "number" || typeof scoreData?.totalQuestions !== "number") {
|
|
208801
|
-
throw ApiError.badRequest("correctQuestions and totalQuestions are required");
|
|
208802
|
-
}
|
|
208803
|
-
if (typeof timingData?.durationSeconds !== "number") {
|
|
208804
|
-
throw ApiError.badRequest("durationSeconds is required");
|
|
209815
|
+
const requestBody = await ctx.request.json();
|
|
209816
|
+
const validation2 = EndActivityRequestSchema.safeParse(requestBody);
|
|
209817
|
+
if (!validation2.success) {
|
|
209818
|
+
throw ApiError.badRequest(formatValidationErrors(validation2.error));
|
|
208805
209819
|
}
|
|
209820
|
+
const { gameId, studentId, activityData, scoreData, timingData, xpEarned, masteredUnits } = validation2.data;
|
|
209821
|
+
await verifyGameAccessById(gameId, user);
|
|
208806
209822
|
const db = getDatabase();
|
|
208807
|
-
const
|
|
208808
|
-
where: eq(games.id, gameId)
|
|
208809
|
-
});
|
|
208810
|
-
if (!game) {
|
|
208811
|
-
throw ApiError.notFound("Game not found");
|
|
208812
|
-
}
|
|
208813
|
-
if (user.role !== "admin" && game.developerId !== user.id) {
|
|
208814
|
-
throw ApiError.forbidden("You do not own this game");
|
|
208815
|
-
}
|
|
209823
|
+
const { grade, subject } = activityData;
|
|
208816
209824
|
const integration = await db.query.gameTimebackIntegrations.findFirst({
|
|
208817
|
-
where: eq(
|
|
209825
|
+
where: (table14, { eq: eq3, and: and3 }) => and3(eq3(table14.gameId, gameId), eq3(table14.grade, grade), eq3(table14.subject, subject))
|
|
208818
209826
|
});
|
|
208819
209827
|
if (!integration) {
|
|
208820
|
-
|
|
209828
|
+
log2.error("[API] No TimeBack integration found", { gameId, grade, subject });
|
|
209829
|
+
throw ApiError.notFound(`No TimeBack integration found for this game (grade ${grade}, subject ${subject}). Run setup first.`);
|
|
208821
209830
|
}
|
|
208822
209831
|
const client2 = await getTimebackClient();
|
|
208823
209832
|
try {
|
|
@@ -208828,6 +209837,7 @@ async function endActivity(ctx) {
|
|
|
208828
209837
|
correctQuestions: scoreData.correctQuestions,
|
|
208829
209838
|
sessionDurationSeconds: timingData.durationSeconds,
|
|
208830
209839
|
xpEarned,
|
|
209840
|
+
masteredUnits,
|
|
208831
209841
|
activityId: activityData.activityId,
|
|
208832
209842
|
activityName: activityData.activityName,
|
|
208833
209843
|
subject: activityData.subject,
|
|
@@ -208835,8 +209845,11 @@ async function endActivity(ctx) {
|
|
|
208835
209845
|
sensorUrl: activityData.sensorUrl,
|
|
208836
209846
|
courseId: activityData.courseId,
|
|
208837
209847
|
courseName: activityData.courseName,
|
|
208838
|
-
studentEmail: activityData.studentEmail
|
|
209848
|
+
studentEmail: activityData.studentEmail,
|
|
209849
|
+
courseTotalXp: integration.totalXp
|
|
208839
209850
|
});
|
|
209851
|
+
const studentData = await client2.resolveStudent(studentId);
|
|
209852
|
+
const studentEmail = studentData.email;
|
|
208840
209853
|
await client2.recordSessionEnd(integration.courseId, studentId, {
|
|
208841
209854
|
activeTimeSeconds: timingData.durationSeconds,
|
|
208842
209855
|
activityId: activityData.activityId,
|
|
@@ -208852,17 +209865,26 @@ async function endActivity(ctx) {
|
|
|
208852
209865
|
gameId,
|
|
208853
209866
|
courseId: integration.courseId,
|
|
208854
209867
|
studentId,
|
|
209868
|
+
studentEmail,
|
|
208855
209869
|
activityId: activityData.activityId,
|
|
208856
209870
|
score: scorePercentage,
|
|
208857
209871
|
durationSeconds: timingData.durationSeconds,
|
|
208858
209872
|
attemptNumber: result.attemptNumber,
|
|
208859
209873
|
isFirstAttempt: result.attemptNumber === 1,
|
|
208860
|
-
xpAwarded: result.xpAwarded
|
|
209874
|
+
xpAwarded: result.xpAwarded,
|
|
209875
|
+
masteredUnits,
|
|
209876
|
+
pctCompleteApp: result.pctCompleteApp,
|
|
209877
|
+
scoreStatus: result.scoreStatus,
|
|
209878
|
+
inProgress: result.inProgress
|
|
208861
209879
|
});
|
|
208862
209880
|
return {
|
|
208863
209881
|
status: "ok",
|
|
208864
209882
|
courseId: integration.courseId,
|
|
208865
|
-
xpAwarded: result.xpAwarded
|
|
209883
|
+
xpAwarded: result.xpAwarded,
|
|
209884
|
+
masteredUnits: result.masteredUnitsApplied,
|
|
209885
|
+
pctCompleteApp: result.pctCompleteApp,
|
|
209886
|
+
scoreStatus: result.scoreStatus,
|
|
209887
|
+
inProgress: result.inProgress
|
|
208866
209888
|
};
|
|
208867
209889
|
} catch (error2) {
|
|
208868
209890
|
logTimebackError2("end activity", error2, {
|
|
@@ -208888,68 +209910,160 @@ async function setupTimebackIntegration(ctx) {
|
|
|
208888
209910
|
log2.error("Failed to parse request body:", { error: error2 });
|
|
208889
209911
|
throw ApiError.badRequest("Invalid JSON body");
|
|
208890
209912
|
}
|
|
208891
|
-
const { gameId,
|
|
209913
|
+
const { gameId, courses, baseConfig, verbose } = request3;
|
|
208892
209914
|
log2.debug("[API] TimeBack setup request", {
|
|
208893
209915
|
gameId,
|
|
208894
|
-
|
|
209916
|
+
courseCount: courses.length
|
|
208895
209917
|
});
|
|
209918
|
+
await verifyGameAccessById(gameId, user);
|
|
208896
209919
|
const db = getDatabase();
|
|
208897
|
-
const
|
|
208898
|
-
where: eq(games.id, gameId)
|
|
208899
|
-
});
|
|
208900
|
-
if (!game) {
|
|
208901
|
-
throw ApiError.notFound("Game not found");
|
|
208902
|
-
}
|
|
208903
|
-
if (user.role !== "admin" && game.developerId !== user.id) {
|
|
208904
|
-
throw ApiError.forbidden("You do not own this game");
|
|
208905
|
-
}
|
|
208906
|
-
const existing = await db.query.gameTimebackIntegrations.findFirst({
|
|
209920
|
+
const existing = await db.query.gameTimebackIntegrations.findMany({
|
|
208907
209921
|
where: eq(gameTimebackIntegrations.gameId, gameId)
|
|
208908
209922
|
});
|
|
208909
209923
|
const client2 = await getTimebackClient();
|
|
208910
|
-
|
|
208911
|
-
|
|
208912
|
-
|
|
208913
|
-
|
|
208914
|
-
|
|
208915
|
-
|
|
208916
|
-
|
|
208917
|
-
|
|
208918
|
-
|
|
208919
|
-
|
|
208920
|
-
|
|
208921
|
-
|
|
208922
|
-
|
|
208923
|
-
|
|
208924
|
-
|
|
208925
|
-
|
|
208926
|
-
|
|
209924
|
+
const integrations = [];
|
|
209925
|
+
const verboseData = [];
|
|
209926
|
+
for (const courseConfig of courses) {
|
|
209927
|
+
const {
|
|
209928
|
+
subject,
|
|
209929
|
+
grade,
|
|
209930
|
+
title,
|
|
209931
|
+
courseCode,
|
|
209932
|
+
level,
|
|
209933
|
+
metadata: metadata2,
|
|
209934
|
+
totalXp: derivedTotalXp,
|
|
209935
|
+
masterableUnits: derivedMasterableUnits
|
|
209936
|
+
} = courseConfig;
|
|
209937
|
+
if (!isTimebackSubject(subject)) {
|
|
209938
|
+
log2.error("[API] Invalid subject in TimeBack request", { subject });
|
|
209939
|
+
throw ApiError.badRequest(`Invalid subject "${subject}" provided for course "${title}".`);
|
|
209940
|
+
}
|
|
209941
|
+
if (!isTimebackGrade(grade)) {
|
|
209942
|
+
log2.error("[API] Invalid grade in TimeBack request", { grade });
|
|
209943
|
+
throw ApiError.badRequest(`Invalid grade "${grade}" provided for course "${title}".`);
|
|
209944
|
+
}
|
|
209945
|
+
const courseSubject = subject;
|
|
209946
|
+
const courseGrade = grade;
|
|
209947
|
+
const courseMetadata = isCourseMetadata(metadata2) ? metadata2 : undefined;
|
|
209948
|
+
const totalXp = derivedTotalXp ?? courseMetadata?.metrics?.totalXp;
|
|
209949
|
+
const masterableUnits = derivedMasterableUnits ?? (isPlaycademyResourceMetadata2(courseMetadata?.playcademy) ? courseMetadata?.playcademy?.mastery?.masterableUnits : undefined);
|
|
209950
|
+
if (typeof totalXp !== "number") {
|
|
209951
|
+
log2.error("[API] Missing totalXp in course metadata", { gameId, grade, subject, title });
|
|
209952
|
+
throw ApiError.badRequest(`Course "${title}" (grade ${grade}, subject ${subject}) is missing \`metadata.metrics.totalXp\``);
|
|
209953
|
+
}
|
|
209954
|
+
const suffix = baseConfig.component.titleSuffix || "";
|
|
209955
|
+
const applySuffix = (text5) => suffix ? `${text5} ${suffix}` : text5;
|
|
209956
|
+
const fullConfig = {
|
|
209957
|
+
organization: baseConfig.organization,
|
|
209958
|
+
course: {
|
|
209959
|
+
title,
|
|
209960
|
+
subjects: [courseSubject],
|
|
209961
|
+
grades: [courseGrade],
|
|
209962
|
+
courseCode,
|
|
209963
|
+
level,
|
|
209964
|
+
gradingScheme: "STANDARD",
|
|
209965
|
+
metadata: metadata2
|
|
209966
|
+
},
|
|
209967
|
+
component: {
|
|
209968
|
+
...baseConfig.component,
|
|
209969
|
+
title: applySuffix(baseConfig.component.title || `${title} Activities`)
|
|
209970
|
+
},
|
|
209971
|
+
resource: {
|
|
209972
|
+
...baseConfig.resource,
|
|
209973
|
+
title: applySuffix(baseConfig.resource.title || `${title} Game`),
|
|
209974
|
+
metadata: buildResourceMetadata({
|
|
209975
|
+
baseMetadata: baseConfig.resource.metadata,
|
|
209976
|
+
subject: courseSubject,
|
|
209977
|
+
grade: courseGrade,
|
|
209978
|
+
totalXp,
|
|
209979
|
+
masterableUnits
|
|
209980
|
+
})
|
|
209981
|
+
},
|
|
209982
|
+
componentResource: {
|
|
209983
|
+
...baseConfig.componentResource,
|
|
209984
|
+
title: applySuffix(baseConfig.componentResource.title || "")
|
|
209985
|
+
}
|
|
208927
209986
|
};
|
|
208928
|
-
|
|
208929
|
-
|
|
208930
|
-
|
|
208931
|
-
|
|
208932
|
-
|
|
208933
|
-
|
|
208934
|
-
|
|
208935
|
-
|
|
208936
|
-
|
|
208937
|
-
|
|
208938
|
-
|
|
208939
|
-
|
|
208940
|
-
|
|
208941
|
-
|
|
208942
|
-
|
|
209987
|
+
const existingIntegration = existing.find((i4) => i4.grade === grade && i4.subject === subject);
|
|
209988
|
+
if (existingIntegration) {
|
|
209989
|
+
try {
|
|
209990
|
+
await client2.update(existingIntegration.courseId, fullConfig);
|
|
209991
|
+
} catch (error2) {
|
|
209992
|
+
logTimebackError2("update", error2, {
|
|
209993
|
+
gameId,
|
|
209994
|
+
grade,
|
|
209995
|
+
subject,
|
|
209996
|
+
courseId: existingIntegration.courseId
|
|
209997
|
+
});
|
|
209998
|
+
throw error2;
|
|
209999
|
+
}
|
|
210000
|
+
const [updated] = await db.update(gameTimebackIntegrations).set({
|
|
210001
|
+
totalXp,
|
|
210002
|
+
updatedAt: new Date
|
|
210003
|
+
}).where(eq(gameTimebackIntegrations.id, existingIntegration.id)).returning();
|
|
210004
|
+
if (!updated) {
|
|
210005
|
+
log2.error("[API] Failed to update TimeBack integration record", {
|
|
210006
|
+
gameId,
|
|
210007
|
+
grade,
|
|
210008
|
+
subject,
|
|
210009
|
+
integrationId: existingIntegration.id
|
|
210010
|
+
});
|
|
210011
|
+
throw ApiError.internal("Failed to update TimeBack integration record");
|
|
210012
|
+
}
|
|
210013
|
+
integrations.push(updated);
|
|
210014
|
+
log2.info("[API] Updated TimeBack course", {
|
|
210015
|
+
gameId,
|
|
210016
|
+
courseId: updated.courseId,
|
|
210017
|
+
grade,
|
|
210018
|
+
subject
|
|
210019
|
+
});
|
|
210020
|
+
} else {
|
|
210021
|
+
let result;
|
|
210022
|
+
try {
|
|
210023
|
+
result = await client2.setup(fullConfig, { verbose });
|
|
210024
|
+
} catch (error2) {
|
|
210025
|
+
logTimebackError2("setup", error2, { gameId, grade, subject });
|
|
210026
|
+
throw error2;
|
|
210027
|
+
}
|
|
210028
|
+
const integrationData = {
|
|
210029
|
+
gameId,
|
|
210030
|
+
courseId: result.courseId,
|
|
210031
|
+
grade,
|
|
210032
|
+
subject,
|
|
210033
|
+
totalXp
|
|
210034
|
+
};
|
|
210035
|
+
const [integration] = await db.insert(gameTimebackIntegrations).values(integrationData).returning();
|
|
210036
|
+
if (!integration) {
|
|
210037
|
+
log2.error("[API] Failed to create TimeBack integration record", {
|
|
210038
|
+
gameId,
|
|
210039
|
+
grade,
|
|
210040
|
+
subject,
|
|
210041
|
+
courseId: result.courseId
|
|
210042
|
+
});
|
|
210043
|
+
throw ApiError.internal("Failed to create TimeBack integration record");
|
|
210044
|
+
}
|
|
210045
|
+
integrations.push(integration);
|
|
210046
|
+
if (verbose && result.verboseData) {
|
|
210047
|
+
verboseData.push({
|
|
210048
|
+
integration,
|
|
210049
|
+
config: result.verboseData
|
|
210050
|
+
});
|
|
210051
|
+
}
|
|
210052
|
+
log2.info("[API] Created TimeBack course", {
|
|
210053
|
+
gameId,
|
|
210054
|
+
courseId: integration.courseId,
|
|
210055
|
+
grade,
|
|
210056
|
+
subject
|
|
210057
|
+
});
|
|
210058
|
+
}
|
|
208943
210059
|
}
|
|
208944
210060
|
log2.info("[API] Created TimeBack integration", {
|
|
208945
210061
|
gameId,
|
|
208946
|
-
|
|
208947
|
-
...result.verboseData && { verbose: result.verboseData }
|
|
210062
|
+
courseCount: integrations.length
|
|
208948
210063
|
});
|
|
208949
210064
|
return {
|
|
208950
|
-
|
|
208951
|
-
|
|
208952
|
-
...result.verboseData && { verbose: result.verboseData }
|
|
210065
|
+
integrations,
|
|
210066
|
+
...verbose && verboseData.length > 0 && { verbose: verboseData }
|
|
208953
210067
|
};
|
|
208954
210068
|
}
|
|
208955
210069
|
async function getTimebackIntegration(ctx) {
|
|
@@ -208961,21 +210075,13 @@ async function getTimebackIntegration(ctx) {
|
|
|
208961
210075
|
if (!gameId) {
|
|
208962
210076
|
throw ApiError.badRequest("Missing gameId parameter");
|
|
208963
210077
|
}
|
|
208964
|
-
log2.debug("[API] Getting TimeBack
|
|
210078
|
+
log2.debug("[API] Getting TimeBack integrations", { userId: user.id, gameId });
|
|
210079
|
+
await verifyGameAccessById(gameId, user);
|
|
208965
210080
|
const db = getDatabase();
|
|
208966
|
-
const
|
|
208967
|
-
where: eq(games.id, gameId)
|
|
208968
|
-
});
|
|
208969
|
-
if (!game) {
|
|
208970
|
-
throw ApiError.notFound("Game not found");
|
|
208971
|
-
}
|
|
208972
|
-
if (user.role !== "admin" && game.developerId !== user.id) {
|
|
208973
|
-
throw ApiError.forbidden("You do not own this game");
|
|
208974
|
-
}
|
|
208975
|
-
const integration = await db.query.gameTimebackIntegrations.findFirst({
|
|
210081
|
+
const integrations = await db.query.gameTimebackIntegrations.findMany({
|
|
208976
210082
|
where: eq(gameTimebackIntegrations.gameId, gameId)
|
|
208977
210083
|
});
|
|
208978
|
-
return
|
|
210084
|
+
return integrations;
|
|
208979
210085
|
}
|
|
208980
210086
|
async function verifyTimebackIntegration(ctx) {
|
|
208981
210087
|
const user = ctx.user;
|
|
@@ -208987,39 +210093,40 @@ async function verifyTimebackIntegration(ctx) {
|
|
|
208987
210093
|
throw ApiError.badRequest("Missing gameId parameter");
|
|
208988
210094
|
}
|
|
208989
210095
|
log2.debug("[API] Verifying TimeBack integration", { userId: user.id, gameId });
|
|
210096
|
+
await verifyGameAccessById(gameId, user);
|
|
208990
210097
|
const db = getDatabase();
|
|
208991
|
-
const
|
|
208992
|
-
where: eq(games.id, gameId)
|
|
208993
|
-
});
|
|
208994
|
-
if (!game) {
|
|
208995
|
-
throw ApiError.notFound("Game not found");
|
|
208996
|
-
}
|
|
208997
|
-
if (user.role !== "admin" && game.developerId !== user.id) {
|
|
208998
|
-
log2.error("[API] User does not own game", { userId: user.id, gameId });
|
|
208999
|
-
throw ApiError.forbidden("You do not own this game");
|
|
209000
|
-
}
|
|
209001
|
-
const integration = await db.query.gameTimebackIntegrations.findFirst({
|
|
210098
|
+
const integrations = await db.query.gameTimebackIntegrations.findMany({
|
|
209002
210099
|
where: eq(gameTimebackIntegrations.gameId, gameId)
|
|
209003
210100
|
});
|
|
209004
|
-
if (
|
|
210101
|
+
if (integrations.length === 0) {
|
|
210102
|
+
log2.error("[API] No TimeBack integration found", { gameId });
|
|
209005
210103
|
throw ApiError.notFound("No TimeBack integration found for this game");
|
|
209006
210104
|
}
|
|
209007
210105
|
const client2 = await getTimebackClient();
|
|
209008
|
-
const
|
|
209009
|
-
const
|
|
209010
|
-
|
|
209011
|
-
|
|
209012
|
-
|
|
209013
|
-
|
|
210106
|
+
const now2 = new Date;
|
|
210107
|
+
const results = await Promise.all(integrations.map(async (integration) => {
|
|
210108
|
+
const resources = await client2.verify(integration.courseId);
|
|
210109
|
+
const resourceValues = Object.values(resources);
|
|
210110
|
+
const allFound = resourceValues.every((r3) => r3.found);
|
|
210111
|
+
const errors3 = Object.entries(resources).filter(([_5, r3]) => !r3.found).map(([name4]) => `${name4} not found`);
|
|
210112
|
+
const status = allFound ? "success" : "error";
|
|
210113
|
+
return {
|
|
210114
|
+
integration: { ...integration, lastVerifiedAt: now2 },
|
|
210115
|
+
resources,
|
|
210116
|
+
status,
|
|
210117
|
+
...errors3.length > 0 && { errors: errors3 }
|
|
210118
|
+
};
|
|
210119
|
+
}));
|
|
210120
|
+
await db.update(gameTimebackIntegrations).set({ lastVerifiedAt: now2 }).where(eq(gameTimebackIntegrations.gameId, gameId));
|
|
210121
|
+
const overallSuccess = results.every((r3) => r3.status === "success");
|
|
210122
|
+
log2.info("[API] Verified TimeBack integrations", {
|
|
209014
210123
|
gameId,
|
|
209015
|
-
|
|
209016
|
-
status:
|
|
210124
|
+
courseCount: integrations.length,
|
|
210125
|
+
status: overallSuccess ? "success" : "error"
|
|
209017
210126
|
});
|
|
209018
210127
|
return {
|
|
209019
|
-
status:
|
|
209020
|
-
|
|
209021
|
-
resources,
|
|
209022
|
-
...errors3.length > 0 && { errors: errors3 }
|
|
210128
|
+
status: overallSuccess ? "success" : "error",
|
|
210129
|
+
results
|
|
209023
210130
|
};
|
|
209024
210131
|
}
|
|
209025
210132
|
async function getTimebackConfig(ctx) {
|
|
@@ -209032,20 +210139,13 @@ async function getTimebackConfig(ctx) {
|
|
|
209032
210139
|
throw ApiError.badRequest("Missing gameId parameter");
|
|
209033
210140
|
}
|
|
209034
210141
|
log2.debug("[API] Getting TimeBack config", { userId: user.id, gameId });
|
|
210142
|
+
await verifyGameAccessById(gameId, user);
|
|
209035
210143
|
const db = getDatabase();
|
|
209036
|
-
const game = await db.query.games.findFirst({
|
|
209037
|
-
where: eq(games.id, gameId)
|
|
209038
|
-
});
|
|
209039
|
-
if (!game) {
|
|
209040
|
-
throw ApiError.notFound("Game not found");
|
|
209041
|
-
}
|
|
209042
|
-
if (user.role !== "admin" && game.developerId !== user.id) {
|
|
209043
|
-
throw ApiError.forbidden("You do not own this game");
|
|
209044
|
-
}
|
|
209045
210144
|
const integration = await db.query.gameTimebackIntegrations.findFirst({
|
|
209046
210145
|
where: eq(gameTimebackIntegrations.gameId, gameId)
|
|
209047
210146
|
});
|
|
209048
210147
|
if (!integration) {
|
|
210148
|
+
log2.error("[API] No TimeBack integration found", { gameId });
|
|
209049
210149
|
throw ApiError.notFound("No TimeBack integration found for this game");
|
|
209050
210150
|
}
|
|
209051
210151
|
const client2 = await getTimebackClient();
|
|
@@ -209060,34 +210160,40 @@ async function deleteTimebackIntegration(ctx) {
|
|
|
209060
210160
|
if (!gameId) {
|
|
209061
210161
|
throw ApiError.badRequest("Missing gameId parameter");
|
|
209062
210162
|
}
|
|
209063
|
-
log2.debug("[API] Deleting TimeBack
|
|
210163
|
+
log2.debug("[API] Deleting TimeBack integrations", { userId: user.id, gameId });
|
|
210164
|
+
await verifyGameAccessById(gameId, user);
|
|
209064
210165
|
const db = getDatabase();
|
|
209065
|
-
const
|
|
209066
|
-
where: eq(games.id, gameId)
|
|
209067
|
-
});
|
|
209068
|
-
if (!game) {
|
|
209069
|
-
throw ApiError.notFound("Game not found");
|
|
209070
|
-
}
|
|
209071
|
-
if (user.role !== "admin" && game.developerId !== user.id) {
|
|
209072
|
-
throw ApiError.forbidden("You do not own this game");
|
|
209073
|
-
}
|
|
209074
|
-
const integration = await db.query.gameTimebackIntegrations.findFirst({
|
|
210166
|
+
const integrations = await db.query.gameTimebackIntegrations.findMany({
|
|
209075
210167
|
where: eq(gameTimebackIntegrations.gameId, gameId)
|
|
209076
210168
|
});
|
|
209077
|
-
if (
|
|
210169
|
+
if (integrations.length === 0) {
|
|
210170
|
+
log2.error("[API] No TimeBack integrations found", { gameId });
|
|
209078
210171
|
throw ApiError.notFound("No TimeBack integration found for this game");
|
|
209079
210172
|
}
|
|
209080
210173
|
const client2 = await getTimebackClient();
|
|
209081
|
-
|
|
209082
|
-
|
|
209083
|
-
|
|
209084
|
-
|
|
209085
|
-
|
|
210174
|
+
for (const integration of integrations) {
|
|
210175
|
+
try {
|
|
210176
|
+
await client2.cleanup(integration.courseId);
|
|
210177
|
+
log2.info("[API] Cleaned up TimeBack course", {
|
|
210178
|
+
gameId,
|
|
210179
|
+
courseId: integration.courseId,
|
|
210180
|
+
grade: integration.grade,
|
|
210181
|
+
subject: integration.subject
|
|
210182
|
+
});
|
|
210183
|
+
} catch (error2) {
|
|
210184
|
+
logTimebackError2("cleanup", error2, {
|
|
210185
|
+
gameId,
|
|
210186
|
+
courseId: integration.courseId,
|
|
210187
|
+
grade: integration.grade,
|
|
210188
|
+
subject: integration.subject
|
|
210189
|
+
});
|
|
210190
|
+
throw error2;
|
|
210191
|
+
}
|
|
209086
210192
|
}
|
|
209087
|
-
await db.delete(gameTimebackIntegrations).where(eq(gameTimebackIntegrations.
|
|
209088
|
-
log2.info("[API] Deleted TimeBack
|
|
210193
|
+
await db.delete(gameTimebackIntegrations).where(eq(gameTimebackIntegrations.gameId, gameId));
|
|
210194
|
+
log2.info("[API] Deleted TimeBack integrations", {
|
|
209089
210195
|
gameId,
|
|
209090
|
-
|
|
210196
|
+
coursesDeleted: integrations.length
|
|
209091
210197
|
});
|
|
209092
210198
|
}
|
|
209093
210199
|
init_src();
|
|
@@ -209218,6 +210324,41 @@ async function getTimeBackXpHistory(ctx) {
|
|
|
209218
210324
|
throw ApiError.internal("Failed to get TimeBack XP history", error2);
|
|
209219
210325
|
}
|
|
209220
210326
|
}
|
|
210327
|
+
init_src();
|
|
210328
|
+
async function getStudentEnrollments(ctx) {
|
|
210329
|
+
const user = ctx.user;
|
|
210330
|
+
if (!user) {
|
|
210331
|
+
throw ApiError.unauthorized("Must be logged in to get enrollments");
|
|
210332
|
+
}
|
|
210333
|
+
const timebackId = ctx.params.timebackId;
|
|
210334
|
+
if (!timebackId) {
|
|
210335
|
+
throw ApiError.badRequest("Missing timebackId parameter");
|
|
210336
|
+
}
|
|
210337
|
+
log2.debug("[API] Getting student enrollments", { userId: user.id, timebackId });
|
|
210338
|
+
const client2 = await getTimebackClient();
|
|
210339
|
+
const classes = await client2.getEnrollments(timebackId, { limit: 100 });
|
|
210340
|
+
const courseIds = classes.map((cls) => cls.courseId).filter((id) => Boolean(id));
|
|
210341
|
+
if (courseIds.length === 0) {
|
|
210342
|
+
return { enrollments: [] };
|
|
210343
|
+
}
|
|
210344
|
+
const db = getDatabase();
|
|
210345
|
+
const integrations = await db.query.gameTimebackIntegrations.findMany({
|
|
210346
|
+
where: inArray(gameTimebackIntegrations.courseId, courseIds)
|
|
210347
|
+
});
|
|
210348
|
+
const enrollments = integrations.map((integration) => ({
|
|
210349
|
+
gameId: integration.gameId,
|
|
210350
|
+
grade: integration.grade,
|
|
210351
|
+
subject: integration.subject,
|
|
210352
|
+
courseId: integration.courseId
|
|
210353
|
+
}));
|
|
210354
|
+
log2.info("[API] Retrieved student enrollments", {
|
|
210355
|
+
userId: user.id,
|
|
210356
|
+
timebackId,
|
|
210357
|
+
totalClasses: classes.length,
|
|
210358
|
+
mappedEnrollments: enrollments.length
|
|
210359
|
+
});
|
|
210360
|
+
return { enrollments };
|
|
210361
|
+
}
|
|
209221
210362
|
var timebackRouter = new Hono2;
|
|
209222
210363
|
timebackRouter.post("/populate-student", async (c3) => {
|
|
209223
210364
|
return c3.json({
|
|
@@ -209408,6 +210549,25 @@ timebackRouter.post("/end-activity", async (c3) => {
|
|
|
209408
210549
|
return c3.json(createUnknownErrorResponse(error2), 500);
|
|
209409
210550
|
}
|
|
209410
210551
|
});
|
|
210552
|
+
timebackRouter.get("/enrollments/:studentId", async (c3) => {
|
|
210553
|
+
const studentId = c3.req.param("studentId");
|
|
210554
|
+
const ctx = {
|
|
210555
|
+
user: c3.get("user"),
|
|
210556
|
+
params: { studentId },
|
|
210557
|
+
url: new URL(c3.req.url),
|
|
210558
|
+
request: c3.req.raw
|
|
210559
|
+
};
|
|
210560
|
+
try {
|
|
210561
|
+
const result = await getStudentEnrollments(ctx);
|
|
210562
|
+
return c3.json(result);
|
|
210563
|
+
} catch (error2) {
|
|
210564
|
+
if (error2 instanceof ApiError) {
|
|
210565
|
+
return c3.json(createErrorResponse(error2), error2.statusCode);
|
|
210566
|
+
}
|
|
210567
|
+
console.error("Error in getStudentEnrollments:", error2);
|
|
210568
|
+
return c3.json(createUnknownErrorResponse(error2), 500);
|
|
210569
|
+
}
|
|
210570
|
+
});
|
|
209411
210571
|
init_src();
|
|
209412
210572
|
async function createLtiSession(userId) {
|
|
209413
210573
|
const db = getDatabase();
|
|
@@ -210378,7 +211538,8 @@ async function configurePlatformMode(server, viteConfig, options) {
|
|
|
210378
211538
|
const backend = await setupCliDevServer({
|
|
210379
211539
|
preferredPort: options.preferredBackendPort,
|
|
210380
211540
|
viteConfig,
|
|
210381
|
-
platformUrl: sandbox.baseUrl
|
|
211541
|
+
platformUrl: sandbox.baseUrl,
|
|
211542
|
+
configPath: options.configPath
|
|
210382
211543
|
});
|
|
210383
211544
|
serverState.backend = backend;
|
|
210384
211545
|
if (sandbox.project) {
|
|
@@ -210401,11 +211562,12 @@ async function configurePlatformMode(server, viteConfig, options) {
|
|
|
210401
211562
|
|
|
210402
211563
|
// src/server/standalone-mode.ts
|
|
210403
211564
|
var import_picocolors6 = __toESM(require_picocolors(), 1);
|
|
210404
|
-
async function configureStandaloneMode(server, viteConfig,
|
|
211565
|
+
async function configureStandaloneMode(server, viteConfig, options) {
|
|
210405
211566
|
const backend = await setupCliDevServer({
|
|
210406
|
-
preferredPort,
|
|
211567
|
+
preferredPort: options.preferredPort,
|
|
210407
211568
|
viteConfig,
|
|
210408
|
-
platformUrl: undefined
|
|
211569
|
+
platformUrl: undefined,
|
|
211570
|
+
configPath: options.configPath
|
|
210409
211571
|
});
|
|
210410
211572
|
if (!backend) {
|
|
210411
211573
|
viteConfig.logger.error("Failed to start backend server");
|
|
@@ -210425,25 +211587,85 @@ async function configureStandaloneMode(server, viteConfig, preferredPort) {
|
|
|
210425
211587
|
}
|
|
210426
211588
|
|
|
210427
211589
|
// src/server/mode-switcher.ts
|
|
211590
|
+
var { bold: bold3, cyan: cyan3, dim: dim4, green: green3, red } = import_picocolors7.default;
|
|
211591
|
+
function formatTimestamp2() {
|
|
211592
|
+
const now2 = new Date;
|
|
211593
|
+
const hours = now2.getHours();
|
|
211594
|
+
const minutes = now2.getMinutes().toString().padStart(2, "0");
|
|
211595
|
+
const seconds = now2.getSeconds().toString().padStart(2, "0");
|
|
211596
|
+
const ampm = hours >= 12 ? "PM" : "AM";
|
|
211597
|
+
const displayHours = hours % 12 || 12;
|
|
211598
|
+
return dim4(`${displayHours}:${minutes}:${seconds} ${ampm}`);
|
|
211599
|
+
}
|
|
210428
211600
|
async function toggleMode(options) {
|
|
210429
211601
|
const currentMode = getCurrentMode();
|
|
210430
211602
|
const newMode = currentMode === "platform" ? "standalone" : "platform";
|
|
210431
211603
|
const viteServer = getViteServerRef();
|
|
210432
211604
|
if (!viteServer) {
|
|
210433
|
-
options.viteConfig.logger.error("[
|
|
211605
|
+
options.viteConfig.logger.error(`${formatTimestamp2()} ${red(bold3("[playcademy]"))} ${red("Cannot toggle mode: no Vite server reference")}`);
|
|
210434
211606
|
return;
|
|
210435
211607
|
}
|
|
210436
211608
|
await cleanupServers();
|
|
210437
211609
|
await new Promise((resolve2) => setTimeout(resolve2, 100));
|
|
210438
211610
|
setCurrentMode(newMode);
|
|
210439
211611
|
if (newMode === "standalone") {
|
|
210440
|
-
await configureStandaloneMode(viteServer, options.viteConfig,
|
|
211612
|
+
await configureStandaloneMode(viteServer, options.viteConfig, {
|
|
211613
|
+
preferredPort: options.platformModeOptions.preferredBackendPort,
|
|
211614
|
+
configPath: options.platformModeOptions.configPath
|
|
211615
|
+
});
|
|
210441
211616
|
} else {
|
|
210442
211617
|
await configurePlatformMode(viteServer, options.viteConfig, options.platformModeOptions);
|
|
210443
211618
|
}
|
|
210444
|
-
options.viteConfig.logger.info(`
|
|
210445
|
-
|
|
210446
|
-
|
|
211619
|
+
options.viteConfig.logger.info(`${formatTimestamp2()} ${cyan3(bold3("[playcademy]"))} ${green3("switched to")} ${green3(bold3(newMode))} ${green3("mode")}`);
|
|
211620
|
+
}
|
|
211621
|
+
|
|
211622
|
+
// src/server/recreate-sandbox-database.ts
|
|
211623
|
+
var import_picocolors8 = __toESM(require_picocolors(), 1);
|
|
211624
|
+
var { bold: bold4, cyan: cyan4, dim: dim5, green: green4, red: red2, yellow } = import_picocolors8.default;
|
|
211625
|
+
function formatTimestamp3() {
|
|
211626
|
+
const now2 = new Date;
|
|
211627
|
+
const hours = now2.getHours();
|
|
211628
|
+
const minutes = now2.getMinutes().toString().padStart(2, "0");
|
|
211629
|
+
const seconds = now2.getSeconds().toString().padStart(2, "0");
|
|
211630
|
+
const ampm = hours >= 12 ? "PM" : "AM";
|
|
211631
|
+
const displayHours = hours % 12 || 12;
|
|
211632
|
+
return dim5(`${displayHours}:${minutes}:${seconds} ${ampm}`);
|
|
211633
|
+
}
|
|
211634
|
+
async function recreateSandboxDatabase(options) {
|
|
211635
|
+
const currentMode = getCurrentMode();
|
|
211636
|
+
const viteServer = getViteServerRef();
|
|
211637
|
+
if (!viteServer) {
|
|
211638
|
+
options.viteConfig.logger.error(`${formatTimestamp3()} ${red2(bold4("[playcademy]"))} ${dim5("(sandbox)")} ${red2("Cannot recreate sandbox database: no Vite server reference")}`);
|
|
211639
|
+
return;
|
|
211640
|
+
}
|
|
211641
|
+
if (currentMode !== "platform") {
|
|
211642
|
+
options.viteConfig.logger.warn(`${formatTimestamp3()} ${yellow(bold4("[playcademy]"))} ${dim5("(sandbox)")} ${yellow("can only recreate sandbox database in platform mode (m + enter)")}`);
|
|
211643
|
+
return;
|
|
211644
|
+
}
|
|
211645
|
+
options.viteConfig.logger.info(`${formatTimestamp3()} ${cyan4(bold4("[playcademy]"))} ${dim5("(sandbox)")} recreating database...`);
|
|
211646
|
+
if (serverState.sandbox) {
|
|
211647
|
+
serverState.sandbox.cleanup();
|
|
211648
|
+
serverState.sandbox = null;
|
|
211649
|
+
}
|
|
211650
|
+
await new Promise((resolve2) => setTimeout(resolve2, 100));
|
|
211651
|
+
const sandbox = await startSandbox(options.viteConfig, options.platformModeOptions.startSandbox, {
|
|
211652
|
+
verbose: options.platformModeOptions.verbose,
|
|
211653
|
+
logLevel: options.platformModeOptions.logLevel,
|
|
211654
|
+
customUrl: options.platformModeOptions.sandboxUrl,
|
|
211655
|
+
quiet: true,
|
|
211656
|
+
recreateDb: true,
|
|
211657
|
+
seed: options.platformModeOptions.seed,
|
|
211658
|
+
memoryOnly: options.platformModeOptions.memoryOnly,
|
|
211659
|
+
databasePath: options.platformModeOptions.databasePath,
|
|
211660
|
+
realtimeEnabled: options.platformModeOptions.realtimeEnabled,
|
|
211661
|
+
realtimePort: options.platformModeOptions.realtimePort
|
|
211662
|
+
});
|
|
211663
|
+
serverState.sandbox = sandbox;
|
|
211664
|
+
if (sandbox.project && serverState.backend) {
|
|
211665
|
+
const gameUrl = `http://localhost:${serverState.backend.port}`;
|
|
211666
|
+
devServerMiddleware(viteServer, sandbox, gameUrl, options.platformModeOptions.showBadge);
|
|
211667
|
+
}
|
|
211668
|
+
options.viteConfig.logger.info(`${formatTimestamp3()} ${cyan4(bold4("[playcademy]"))} ${dim5("(sandbox)")} ${green4("database recreated")}`);
|
|
210447
211669
|
}
|
|
210448
211670
|
|
|
210449
211671
|
// src/hooks/configure-server.ts
|
|
@@ -210471,10 +211693,14 @@ async function configureServerHook(server, context) {
|
|
|
210471
211693
|
realtimeEnabled: context.options.realtimeEnabled,
|
|
210472
211694
|
realtimePort: context.options.realtimePort,
|
|
210473
211695
|
showBadge: context.options.showBadge,
|
|
210474
|
-
preferredBackendPort: preferredPort
|
|
211696
|
+
preferredBackendPort: preferredPort,
|
|
211697
|
+
configPath: context.options.configPath
|
|
210475
211698
|
};
|
|
210476
211699
|
if (context.options.mode === "standalone") {
|
|
210477
|
-
await configureStandaloneMode(server, context.viteConfig,
|
|
211700
|
+
await configureStandaloneMode(server, context.viteConfig, {
|
|
211701
|
+
preferredPort,
|
|
211702
|
+
configPath: context.options.configPath
|
|
211703
|
+
});
|
|
210478
211704
|
} else {
|
|
210479
211705
|
await configurePlatformMode(server, context.viteConfig, platformModeOptions);
|
|
210480
211706
|
}
|
|
@@ -210494,6 +211720,16 @@ async function configureServerHook(server, context) {
|
|
|
210494
211720
|
platformModeOptions
|
|
210495
211721
|
});
|
|
210496
211722
|
}
|
|
211723
|
+
},
|
|
211724
|
+
{
|
|
211725
|
+
key: "d",
|
|
211726
|
+
description: "recreate sandbox database",
|
|
211727
|
+
action: async () => {
|
|
211728
|
+
await recreateSandboxDatabase({
|
|
211729
|
+
viteConfig: context.viteConfig,
|
|
211730
|
+
platformModeOptions
|
|
211731
|
+
});
|
|
211732
|
+
}
|
|
210497
211733
|
}
|
|
210498
211734
|
]
|
|
210499
211735
|
});
|
|
@@ -210529,6 +211765,7 @@ function resolveOptions(options) {
|
|
|
210529
211765
|
const shellOptions = options.shell ?? {};
|
|
210530
211766
|
const realtimeOptions = sandboxOptions.realtime ?? {};
|
|
210531
211767
|
return {
|
|
211768
|
+
configPath: options.configPath,
|
|
210532
211769
|
mode: options.mode ?? "platform",
|
|
210533
211770
|
autoZip: exportOptions.autoZip ?? true,
|
|
210534
211771
|
sandboxUrl: sandboxOptions.url ?? `http://localhost:${DEFAULT_PORTS4.SANDBOX}`,
|