@playcademy/vite-plugin 0.1.32 → 0.1.34
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 +1777 -481
- package/dist/server/mode-switcher.d.ts +1 -6
- package/dist/server/platform-mode.d.ts +1 -14
- package/dist/server/recreate-sandbox-database.d.ts +14 -0
- package/dist/server/standalone-mode.d.ts +2 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/internal.d.ts +34 -0
- package/dist/types/options.d.ts +16 -0
- package/package.json +2 -2
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.33",
|
|
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))
|
|
@@ -104539,7 +104539,7 @@ var require_event_target_shim2 = __commonJS2((exports, module2) => {
|
|
|
104539
104539
|
var CAPTURE = 1;
|
|
104540
104540
|
var BUBBLE = 2;
|
|
104541
104541
|
var ATTRIBUTE = 3;
|
|
104542
|
-
function
|
|
104542
|
+
function isObject4(x6) {
|
|
104543
104543
|
return x6 !== null && typeof x6 === "object";
|
|
104544
104544
|
}
|
|
104545
104545
|
function getListeners(eventTarget) {
|
|
@@ -104563,7 +104563,7 @@ var require_event_target_shim2 = __commonJS2((exports, module2) => {
|
|
|
104563
104563
|
return null;
|
|
104564
104564
|
},
|
|
104565
104565
|
set(listener) {
|
|
104566
|
-
if (typeof listener !== "function" && !
|
|
104566
|
+
if (typeof listener !== "function" && !isObject4(listener)) {
|
|
104567
104567
|
listener = null;
|
|
104568
104568
|
}
|
|
104569
104569
|
const listeners = getListeners(this);
|
|
@@ -104643,11 +104643,11 @@ var require_event_target_shim2 = __commonJS2((exports, module2) => {
|
|
|
104643
104643
|
if (listener == null) {
|
|
104644
104644
|
return;
|
|
104645
104645
|
}
|
|
104646
|
-
if (typeof listener !== "function" && !
|
|
104646
|
+
if (typeof listener !== "function" && !isObject4(listener)) {
|
|
104647
104647
|
throw new TypeError("'listener' should be a function or an object.");
|
|
104648
104648
|
}
|
|
104649
104649
|
const listeners = getListeners(this);
|
|
104650
|
-
const optionsIsObj =
|
|
104650
|
+
const optionsIsObj = isObject4(options);
|
|
104651
104651
|
const capture = optionsIsObj ? Boolean(options.capture) : Boolean(options);
|
|
104652
104652
|
const listenerType = capture ? CAPTURE : BUBBLE;
|
|
104653
104653
|
const newNode = {
|
|
@@ -104677,7 +104677,7 @@ var require_event_target_shim2 = __commonJS2((exports, module2) => {
|
|
|
104677
104677
|
return;
|
|
104678
104678
|
}
|
|
104679
104679
|
const listeners = getListeners(this);
|
|
104680
|
-
const capture =
|
|
104680
|
+
const capture = isObject4(options) ? Boolean(options.capture) : Boolean(options);
|
|
104681
104681
|
const listenerType = capture ? CAPTURE : BUBBLE;
|
|
104682
104682
|
let prev = null;
|
|
104683
104683
|
let node = listeners.get(eventName);
|
|
@@ -110418,7 +110418,7 @@ var init_block_senders = __esm(() => {
|
|
|
110418
110418
|
var Domains;
|
|
110419
110419
|
var DomainListResponsesV4PagePaginationArray;
|
|
110420
110420
|
var DomainBulkDeleteResponsesSinglePage;
|
|
110421
|
-
var
|
|
110421
|
+
var init_domains3 = __esm(() => {
|
|
110422
110422
|
init_pagination();
|
|
110423
110423
|
Domains = class Domains2 extends APIResource {
|
|
110424
110424
|
list(params, options) {
|
|
@@ -110524,8 +110524,8 @@ var init_settings4 = __esm(() => {
|
|
|
110524
110524
|
init_allow_policies();
|
|
110525
110525
|
init_block_senders();
|
|
110526
110526
|
init_block_senders();
|
|
110527
|
-
|
|
110528
|
-
|
|
110527
|
+
init_domains3();
|
|
110528
|
+
init_domains3();
|
|
110529
110529
|
init_impersonation_registry();
|
|
110530
110530
|
init_impersonation_registry();
|
|
110531
110531
|
init_trusted_domains();
|
|
@@ -111746,7 +111746,7 @@ var init_bulks = __esm(() => {
|
|
|
111746
111746
|
};
|
|
111747
111747
|
});
|
|
111748
111748
|
var Domains2;
|
|
111749
|
-
var
|
|
111749
|
+
var init_domains4 = __esm(() => {
|
|
111750
111750
|
init_bulks();
|
|
111751
111751
|
init_bulks();
|
|
111752
111752
|
Domains2 = class Domains22 extends APIResource {
|
|
@@ -111872,8 +111872,8 @@ var init_intel = __esm(() => {
|
|
|
111872
111872
|
init_asn3();
|
|
111873
111873
|
init_attack_surface_report();
|
|
111874
111874
|
init_attack_surface_report();
|
|
111875
|
-
|
|
111876
|
-
|
|
111875
|
+
init_domains4();
|
|
111876
|
+
init_domains4();
|
|
111877
111877
|
init_indicator_feeds();
|
|
111878
111878
|
init_indicator_feeds();
|
|
111879
111879
|
Intel = class Intel2 extends APIResource {
|
|
@@ -114612,7 +114612,7 @@ var init_page_shield = __esm(() => {
|
|
|
114612
114612
|
});
|
|
114613
114613
|
var Domains3;
|
|
114614
114614
|
var DomainListResponsesSinglePage;
|
|
114615
|
-
var
|
|
114615
|
+
var init_domains5 = __esm(() => {
|
|
114616
114616
|
init_pagination();
|
|
114617
114617
|
Domains3 = class Domains32 extends APIResource {
|
|
114618
114618
|
create(projectName, params, options) {
|
|
@@ -114708,8 +114708,8 @@ var init_deployments = __esm(() => {
|
|
|
114708
114708
|
var Projects;
|
|
114709
114709
|
var DeploymentsSinglePage;
|
|
114710
114710
|
var init_projects = __esm(() => {
|
|
114711
|
-
|
|
114712
|
-
|
|
114711
|
+
init_domains5();
|
|
114712
|
+
init_domains5();
|
|
114713
114713
|
init_deployments();
|
|
114714
114714
|
init_deployments();
|
|
114715
114715
|
init_pagination();
|
|
@@ -115245,7 +115245,7 @@ var init_managed = __esm(() => {
|
|
|
115245
115245
|
};
|
|
115246
115246
|
});
|
|
115247
115247
|
var Domains4;
|
|
115248
|
-
var
|
|
115248
|
+
var init_domains6 = __esm(() => {
|
|
115249
115249
|
init_custom5();
|
|
115250
115250
|
init_custom5();
|
|
115251
115251
|
init_managed();
|
|
@@ -115274,8 +115274,8 @@ var init_buckets = __esm(() => {
|
|
|
115274
115274
|
init_metrics();
|
|
115275
115275
|
init_sippy();
|
|
115276
115276
|
init_sippy();
|
|
115277
|
-
|
|
115278
|
-
|
|
115277
|
+
init_domains6();
|
|
115278
|
+
init_domains6();
|
|
115279
115279
|
Buckets = class Buckets2 extends APIResource {
|
|
115280
115280
|
constructor() {
|
|
115281
115281
|
super(...arguments);
|
|
@@ -118405,7 +118405,7 @@ var init_rate_limits = __esm(() => {
|
|
|
118405
118405
|
});
|
|
118406
118406
|
var Domains5;
|
|
118407
118407
|
var DomainsSinglePage;
|
|
118408
|
-
var
|
|
118408
|
+
var init_domains7 = __esm(() => {
|
|
118409
118409
|
init_pagination();
|
|
118410
118410
|
Domains5 = class Domains52 extends APIResource {
|
|
118411
118411
|
update(domainName, params, options) {
|
|
@@ -118430,8 +118430,8 @@ var init_domains5 = __esm(() => {
|
|
|
118430
118430
|
});
|
|
118431
118431
|
var Registrar;
|
|
118432
118432
|
var init_registrar = __esm(() => {
|
|
118433
|
-
|
|
118434
|
-
|
|
118433
|
+
init_domains7();
|
|
118434
|
+
init_domains7();
|
|
118435
118435
|
Registrar = class Registrar2 extends APIResource {
|
|
118436
118436
|
constructor() {
|
|
118437
118437
|
super(...arguments);
|
|
@@ -121232,7 +121232,7 @@ var init_account_settings = __esm(() => {
|
|
|
121232
121232
|
});
|
|
121233
121233
|
var Domains6;
|
|
121234
121234
|
var DomainsSinglePage2;
|
|
121235
|
-
var
|
|
121235
|
+
var init_domains8 = __esm(() => {
|
|
121236
121236
|
init_pagination();
|
|
121237
121237
|
Domains6 = class Domains62 extends APIResource {
|
|
121238
121238
|
update(params, options) {
|
|
@@ -121365,7 +121365,7 @@ var init_versions3 = __esm(() => {
|
|
|
121365
121365
|
});
|
|
121366
121366
|
var Workers;
|
|
121367
121367
|
var WorkersV4PagePaginationArray;
|
|
121368
|
-
var
|
|
121368
|
+
var init_workers3 = __esm(() => {
|
|
121369
121369
|
init_versions3();
|
|
121370
121370
|
init_versions3();
|
|
121371
121371
|
init_pagination();
|
|
@@ -121417,8 +121417,8 @@ var init_workers = __esm(() => {
|
|
|
121417
121417
|
});
|
|
121418
121418
|
var Beta;
|
|
121419
121419
|
var init_beta = __esm(() => {
|
|
121420
|
-
|
|
121421
|
-
|
|
121420
|
+
init_workers3();
|
|
121421
|
+
init_workers3();
|
|
121422
121422
|
Beta = class Beta2 extends APIResource {
|
|
121423
121423
|
constructor() {
|
|
121424
121424
|
super(...arguments);
|
|
@@ -121785,11 +121785,11 @@ var init_scripts2 = __esm(() => {
|
|
|
121785
121785
|
Scripts2.ScriptAndVersionSettings = ScriptAndVersionSettings;
|
|
121786
121786
|
});
|
|
121787
121787
|
var Workers2;
|
|
121788
|
-
var
|
|
121788
|
+
var init_workers4 = __esm(() => {
|
|
121789
121789
|
init_account_settings();
|
|
121790
121790
|
init_account_settings();
|
|
121791
|
-
|
|
121792
|
-
|
|
121791
|
+
init_domains8();
|
|
121792
|
+
init_domains8();
|
|
121793
121793
|
init_routes3();
|
|
121794
121794
|
init_routes3();
|
|
121795
121795
|
init_subdomains();
|
|
@@ -126569,7 +126569,7 @@ var init_resources3 = __esm(() => {
|
|
|
126569
126569
|
init_vectorize();
|
|
126570
126570
|
init_waiting_rooms();
|
|
126571
126571
|
init_web3();
|
|
126572
|
-
|
|
126572
|
+
init_workers4();
|
|
126573
126573
|
init_workers_for_platforms();
|
|
126574
126574
|
init_workflows();
|
|
126575
126575
|
init_zaraz();
|
|
@@ -126678,7 +126678,7 @@ var init_cloudflare = __esm(() => {
|
|
|
126678
126678
|
init_waiting_rooms();
|
|
126679
126679
|
init_web3();
|
|
126680
126680
|
init_workers_for_platforms();
|
|
126681
|
-
|
|
126681
|
+
init_workers4();
|
|
126682
126682
|
init_workflows();
|
|
126683
126683
|
init_zaraz();
|
|
126684
126684
|
init_zero_trust();
|
|
@@ -127143,7 +127143,7 @@ var require_dist_cjs2 = __commonJS2((exports, module2) => {
|
|
|
127143
127143
|
Fields: () => Fields3,
|
|
127144
127144
|
HttpRequest: () => HttpRequest,
|
|
127145
127145
|
HttpResponse: () => HttpResponse,
|
|
127146
|
-
IHttpRequest: () =>
|
|
127146
|
+
IHttpRequest: () => import_types6.HttpRequest,
|
|
127147
127147
|
getHttpHandlerExtensionConfiguration: () => getHttpHandlerExtensionConfiguration,
|
|
127148
127148
|
isValidHostname: () => isValidHostname,
|
|
127149
127149
|
resolveHttpHandlerRuntimeConfig: () => resolveHttpHandlerRuntimeConfig
|
|
@@ -127170,12 +127170,12 @@ var require_dist_cjs2 = __commonJS2((exports, module2) => {
|
|
|
127170
127170
|
httpHandler: httpHandlerExtensionConfiguration.httpHandler()
|
|
127171
127171
|
};
|
|
127172
127172
|
}, "resolveHttpHandlerRuntimeConfig");
|
|
127173
|
-
var
|
|
127173
|
+
var import_types6 = require_dist_cjs();
|
|
127174
127174
|
var Field = class {
|
|
127175
127175
|
static {
|
|
127176
127176
|
__name(this, "Field");
|
|
127177
127177
|
}
|
|
127178
|
-
constructor({ name: name4, kind: kind2 =
|
|
127178
|
+
constructor({ name: name4, kind: kind2 = import_types6.FieldPosition.HEADER, values = [] }) {
|
|
127179
127179
|
this.name = name4;
|
|
127180
127180
|
this.kind = kind2;
|
|
127181
127181
|
this.values = values;
|
|
@@ -128036,8 +128036,8 @@ var require_dist_cjs4 = __commonJS2((exports, module2) => {
|
|
|
128036
128036
|
normalizeProvider: () => normalizeProvider
|
|
128037
128037
|
});
|
|
128038
128038
|
module2.exports = __toCommonJS(src_exports);
|
|
128039
|
-
var
|
|
128040
|
-
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");
|
|
128041
128041
|
var normalizeProvider = /* @__PURE__ */ __name((input) => {
|
|
128042
128042
|
if (typeof input === "function")
|
|
128043
128043
|
return input;
|
|
@@ -132053,8 +132053,8 @@ var require_dist_cjs16 = __commonJS2((exports, module2) => {
|
|
|
132053
132053
|
setFeature: () => setFeature
|
|
132054
132054
|
});
|
|
132055
132055
|
module2.exports = __toCommonJS(src_exports);
|
|
132056
|
-
var
|
|
132057
|
-
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");
|
|
132058
132058
|
var import_util_middleware = require_dist_cjs4();
|
|
132059
132059
|
var resolveAuthOptions = /* @__PURE__ */ __name((candidateAuthOptions, authSchemePreference) => {
|
|
132060
132060
|
if (!authSchemePreference || authSchemePreference.length === 0) {
|
|
@@ -132290,9 +132290,9 @@ var require_dist_cjs16 = __commonJS2((exports, module2) => {
|
|
|
132290
132290
|
throw new Error("request could not be signed with `apiKey` since the `apiKey` is not defined");
|
|
132291
132291
|
}
|
|
132292
132292
|
const clonedRequest = import_protocol_http.HttpRequest.clone(httpRequest);
|
|
132293
|
-
if (signingProperties.in ===
|
|
132293
|
+
if (signingProperties.in === import_types6.HttpApiKeyAuthLocation.QUERY) {
|
|
132294
132294
|
clonedRequest.query[signingProperties.name] = identity.apiKey;
|
|
132295
|
-
} else if (signingProperties.in ===
|
|
132295
|
+
} else if (signingProperties.in === import_types6.HttpApiKeyAuthLocation.HEADER) {
|
|
132296
132296
|
clonedRequest.headers[signingProperties.name] = signingProperties.scheme ? `${signingProperties.scheme} ${identity.apiKey}` : identity.apiKey;
|
|
132297
132297
|
} else {
|
|
132298
132298
|
throw new Error("request can only be signed with `apiKey` locations `query` or `header`, but found: `" + signingProperties.in + "`");
|
|
@@ -133365,7 +133365,7 @@ var require_httpAuthSchemes = __commonJS2((exports, module2) => {
|
|
|
133365
133365
|
},
|
|
133366
133366
|
default: undefined
|
|
133367
133367
|
};
|
|
133368
|
-
var
|
|
133368
|
+
var import_client2 = require_client();
|
|
133369
133369
|
var import_core210 = require_dist_cjs16();
|
|
133370
133370
|
var import_signature_v4 = require_dist_cjs20();
|
|
133371
133371
|
var resolveAwsSdkSigV4Config = /* @__PURE__ */ __name((config2) => {
|
|
@@ -133384,7 +133384,7 @@ var require_httpAuthSchemes = __commonJS2((exports, module2) => {
|
|
|
133384
133384
|
});
|
|
133385
133385
|
const boundProvider = bindCallerConfig(config2, memoizedProvider);
|
|
133386
133386
|
if (isUserSupplied && !boundProvider.attributed) {
|
|
133387
|
-
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");
|
|
133388
133388
|
resolvedCredentials.memoized = boundProvider.memoized;
|
|
133389
133389
|
resolvedCredentials.configBound = boundProvider.configBound;
|
|
133390
133390
|
resolvedCredentials.attributed = true;
|
|
@@ -133926,7 +133926,7 @@ var require_dist_cjs23 = __commonJS2((exports, module2) => {
|
|
|
133926
133926
|
}
|
|
133927
133927
|
};
|
|
133928
133928
|
var import_protocols = require_protocols();
|
|
133929
|
-
var
|
|
133929
|
+
var import_types6 = require_dist_cjs();
|
|
133930
133930
|
var Command = class {
|
|
133931
133931
|
constructor() {
|
|
133932
133932
|
this.middlewareStack = (0, import_middleware_stack.constructStack)();
|
|
@@ -133958,7 +133958,7 @@ var require_dist_cjs23 = __commonJS2((exports, module2) => {
|
|
|
133958
133958
|
commandName,
|
|
133959
133959
|
inputFilterSensitiveLog,
|
|
133960
133960
|
outputFilterSensitiveLog,
|
|
133961
|
-
[
|
|
133961
|
+
[import_types6.SMITHY_CONTEXT_KEY]: {
|
|
133962
133962
|
commandInstance: this,
|
|
133963
133963
|
...smithyContext
|
|
133964
133964
|
},
|
|
@@ -134183,8 +134183,8 @@ var require_dist_cjs23 = __commonJS2((exports, module2) => {
|
|
|
134183
134183
|
}, "emitWarningIfUnsupportedVersion");
|
|
134184
134184
|
var getChecksumConfiguration = /* @__PURE__ */ __name((runtimeConfig) => {
|
|
134185
134185
|
const checksumAlgorithms = [];
|
|
134186
|
-
for (const id in
|
|
134187
|
-
const algorithmId =
|
|
134186
|
+
for (const id in import_types6.AlgorithmId) {
|
|
134187
|
+
const algorithmId = import_types6.AlgorithmId[id];
|
|
134188
134188
|
if (runtimeConfig[algorithmId] === undefined) {
|
|
134189
134189
|
continue;
|
|
134190
134190
|
}
|
|
@@ -136341,7 +136341,7 @@ var require_protocols2 = __commonJS2((exports, module2) => {
|
|
|
136341
136341
|
return this._read(schema4, data);
|
|
136342
136342
|
}
|
|
136343
136343
|
_read(schema4, value) {
|
|
136344
|
-
const
|
|
136344
|
+
const isObject4 = value !== null && typeof value === "object";
|
|
136345
136345
|
const ns = import_schema2.NormalizedSchema.of(schema4);
|
|
136346
136346
|
if (ns.isListSchema() && Array.isArray(value)) {
|
|
136347
136347
|
const listMember = ns.getValueSchema();
|
|
@@ -136353,7 +136353,7 @@ var require_protocols2 = __commonJS2((exports, module2) => {
|
|
|
136353
136353
|
}
|
|
136354
136354
|
}
|
|
136355
136355
|
return out2;
|
|
136356
|
-
} else if (ns.isMapSchema() &&
|
|
136356
|
+
} else if (ns.isMapSchema() && isObject4) {
|
|
136357
136357
|
const mapMember = ns.getValueSchema();
|
|
136358
136358
|
const out2 = {};
|
|
136359
136359
|
const sparse = !!ns.getMergedTraits().sparse;
|
|
@@ -136363,7 +136363,7 @@ var require_protocols2 = __commonJS2((exports, module2) => {
|
|
|
136363
136363
|
}
|
|
136364
136364
|
}
|
|
136365
136365
|
return out2;
|
|
136366
|
-
} else if (ns.isStructSchema() &&
|
|
136366
|
+
} else if (ns.isStructSchema() && isObject4) {
|
|
136367
136367
|
const out2 = {};
|
|
136368
136368
|
for (const [memberName, memberSchema] of ns.structIterator()) {
|
|
136369
136369
|
const fromKey = this.settings.jsonName ? memberSchema.getMergedTraits().jsonName ?? memberName : memberName;
|
|
@@ -136495,7 +136495,7 @@ var require_protocols2 = __commonJS2((exports, module2) => {
|
|
|
136495
136495
|
return this.buffer;
|
|
136496
136496
|
}
|
|
136497
136497
|
_write(schema4, value, container) {
|
|
136498
|
-
const
|
|
136498
|
+
const isObject4 = value !== null && typeof value === "object";
|
|
136499
136499
|
const ns = import_schema22.NormalizedSchema.of(schema4);
|
|
136500
136500
|
if (ns.isListSchema() && Array.isArray(value)) {
|
|
136501
136501
|
const listMember = ns.getValueSchema();
|
|
@@ -136507,7 +136507,7 @@ var require_protocols2 = __commonJS2((exports, module2) => {
|
|
|
136507
136507
|
}
|
|
136508
136508
|
}
|
|
136509
136509
|
return out2;
|
|
136510
|
-
} else if (ns.isMapSchema() &&
|
|
136510
|
+
} else if (ns.isMapSchema() && isObject4) {
|
|
136511
136511
|
const mapMember = ns.getValueSchema();
|
|
136512
136512
|
const out2 = {};
|
|
136513
136513
|
const sparse = !!ns.getMergedTraits().sparse;
|
|
@@ -136517,7 +136517,7 @@ var require_protocols2 = __commonJS2((exports, module2) => {
|
|
|
136517
136517
|
}
|
|
136518
136518
|
}
|
|
136519
136519
|
return out2;
|
|
136520
|
-
} else if (ns.isStructSchema() &&
|
|
136520
|
+
} else if (ns.isStructSchema() && isObject4) {
|
|
136521
136521
|
const out2 = {};
|
|
136522
136522
|
for (const [memberName, memberSchema] of ns.structIterator()) {
|
|
136523
136523
|
const targetKey = this.settings.jsonName ? memberSchema.getMergedTraits().jsonName ?? memberName : memberName;
|
|
@@ -143949,16 +143949,16 @@ var require_dist_cjs52 = __commonJS2((exports, module2) => {
|
|
|
143949
143949
|
var getProfileName = /* @__PURE__ */ __name((init3) => init3.profile || process.env[ENV_PROFILE] || DEFAULT_PROFILE, "getProfileName");
|
|
143950
143950
|
__reExport(src_exports, require_getSSOTokenFilepath(), module2.exports);
|
|
143951
143951
|
__reExport(src_exports, require_getSSOTokenFromFile(), module2.exports);
|
|
143952
|
-
var
|
|
143952
|
+
var import_types6 = require_dist_cjs();
|
|
143953
143953
|
var getConfigData = /* @__PURE__ */ __name((data) => Object.entries(data).filter(([key]) => {
|
|
143954
143954
|
const indexOfSeparator = key.indexOf(CONFIG_PREFIX_SEPARATOR);
|
|
143955
143955
|
if (indexOfSeparator === -1) {
|
|
143956
143956
|
return false;
|
|
143957
143957
|
}
|
|
143958
|
-
return Object.values(
|
|
143958
|
+
return Object.values(import_types6.IniSectionType).includes(key.substring(0, indexOfSeparator));
|
|
143959
143959
|
}).reduce((acc, [key, value]) => {
|
|
143960
143960
|
const indexOfSeparator = key.indexOf(CONFIG_PREFIX_SEPARATOR);
|
|
143961
|
-
const updatedKey = key.substring(0, indexOfSeparator) ===
|
|
143961
|
+
const updatedKey = key.substring(0, indexOfSeparator) === import_types6.IniSectionType.PROFILE ? key.substring(indexOfSeparator + 1) : key;
|
|
143962
143962
|
acc[updatedKey] = value;
|
|
143963
143963
|
return acc;
|
|
143964
143964
|
}, {
|
|
@@ -143988,7 +143988,7 @@ var require_dist_cjs52 = __commonJS2((exports, module2) => {
|
|
|
143988
143988
|
const matches = prefixKeyRegex.exec(sectionName);
|
|
143989
143989
|
if (matches) {
|
|
143990
143990
|
const [, prefix2, , name4] = matches;
|
|
143991
|
-
if (Object.values(
|
|
143991
|
+
if (Object.values(import_types6.IniSectionType).includes(prefix2)) {
|
|
143992
143992
|
currentSection = [prefix2, name4].join(CONFIG_PREFIX_SEPARATOR);
|
|
143993
143993
|
}
|
|
143994
143994
|
} else {
|
|
@@ -144047,7 +144047,7 @@ var require_dist_cjs52 = __commonJS2((exports, module2) => {
|
|
|
144047
144047
|
credentialsFile: parsedFiles[1]
|
|
144048
144048
|
};
|
|
144049
144049
|
}, "loadSharedConfigFiles");
|
|
144050
|
-
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");
|
|
144051
144051
|
var import_slurpFile2 = require_slurpFile();
|
|
144052
144052
|
var swallowError2 = /* @__PURE__ */ __name(() => ({}), "swallowError");
|
|
144053
144053
|
var loadSsoSessionData = /* @__PURE__ */ __name(async (init3 = {}) => (0, import_slurpFile2.slurpFile)(init3.configFilepath ?? getConfigFilepath()).then(parseIni).then(getSsoSessionData).catch(swallowError2), "loadSsoSessionData");
|
|
@@ -144090,7 +144090,7 @@ var require_dist_cjs53 = __commonJS2((exports, module2) => {
|
|
|
144090
144090
|
var __toCommonJS = (mod) => __copyProps2(__defProp4({}, "__esModule", { value: true }), mod);
|
|
144091
144091
|
var src_exports = {};
|
|
144092
144092
|
__export4(src_exports, {
|
|
144093
|
-
loadConfig: () =>
|
|
144093
|
+
loadConfig: () => loadConfig
|
|
144094
144094
|
});
|
|
144095
144095
|
module2.exports = __toCommonJS(src_exports);
|
|
144096
144096
|
var import_property_provider = require_dist_cjs17();
|
|
@@ -144137,7 +144137,7 @@ var require_dist_cjs53 = __commonJS2((exports, module2) => {
|
|
|
144137
144137
|
}, "fromSharedConfigFiles");
|
|
144138
144138
|
var isFunction3 = /* @__PURE__ */ __name((func2) => typeof func2 === "function", "isFunction");
|
|
144139
144139
|
var fromStatic = /* @__PURE__ */ __name((defaultValue) => isFunction3(defaultValue) ? async () => await defaultValue() : (0, import_property_provider.fromStatic)(defaultValue), "fromStatic");
|
|
144140
|
-
var
|
|
144140
|
+
var loadConfig = /* @__PURE__ */ __name(({ environmentVariableSelector, configFileSelector, default: defaultValue }, configuration = {}) => {
|
|
144141
144141
|
const { signingName, logger: logger3 } = configuration;
|
|
144142
144142
|
const envOptions = { signingName, logger: logger3 };
|
|
144143
144143
|
return (0, import_property_provider.memoize)((0, import_property_provider.chain)(fromEnv(environmentVariableSelector, envOptions), fromSharedConfigFiles(configFileSelector, configuration), fromStatic(defaultValue)));
|
|
@@ -145024,7 +145024,7 @@ var require_dist_cjs57 = __commonJS2((exports, module2) => {
|
|
|
145024
145024
|
fromEnv: () => fromEnv
|
|
145025
145025
|
});
|
|
145026
145026
|
module2.exports = __toCommonJS(index_exports);
|
|
145027
|
-
var
|
|
145027
|
+
var import_client2 = require_client();
|
|
145028
145028
|
var import_property_provider = require_dist_cjs17();
|
|
145029
145029
|
var ENV_KEY = "AWS_ACCESS_KEY_ID";
|
|
145030
145030
|
var ENV_SECRET = "AWS_SECRET_ACCESS_KEY";
|
|
@@ -145049,7 +145049,7 @@ var require_dist_cjs57 = __commonJS2((exports, module2) => {
|
|
|
145049
145049
|
...credentialScope && { credentialScope },
|
|
145050
145050
|
...accountId && { accountId }
|
|
145051
145051
|
};
|
|
145052
|
-
(0,
|
|
145052
|
+
(0, import_client2.setCredentialFeature)(credentials2, "CREDENTIALS_ENV_VARS", "g");
|
|
145053
145053
|
return credentials2;
|
|
145054
145054
|
}
|
|
145055
145055
|
throw new import_property_provider.CredentialsProviderError("Unable to find environment variable credentials.", { logger: init3?.logger });
|
|
@@ -147916,7 +147916,7 @@ var require_dist_cjs67 = __commonJS2((exports, module2) => {
|
|
|
147916
147916
|
var __getOwnPropNames3 = Object.getOwnPropertyNames;
|
|
147917
147917
|
var __hasOwnProp3 = Object.prototype.hasOwnProperty;
|
|
147918
147918
|
var __name = (target, value) => __defProp4(target, "name", { value, configurable: true });
|
|
147919
|
-
var
|
|
147919
|
+
var __esm5 = (fn2, res) => function __init() {
|
|
147920
147920
|
return fn2 && (res = (0, fn2[__getOwnPropNames3(fn2)[0]])(fn2 = 0)), res;
|
|
147921
147921
|
};
|
|
147922
147922
|
var __export4 = (target, all) => {
|
|
@@ -147938,7 +147938,7 @@ var require_dist_cjs67 = __commonJS2((exports, module2) => {
|
|
|
147938
147938
|
SSOClient: () => import_client_sso.SSOClient
|
|
147939
147939
|
});
|
|
147940
147940
|
var import_client_sso;
|
|
147941
|
-
var init_loadSso =
|
|
147941
|
+
var init_loadSso = __esm5({
|
|
147942
147942
|
"src/loadSso.ts"() {
|
|
147943
147943
|
import_client_sso = require_dist_cjs65();
|
|
147944
147944
|
}
|
|
@@ -147951,7 +147951,7 @@ var require_dist_cjs67 = __commonJS2((exports, module2) => {
|
|
|
147951
147951
|
});
|
|
147952
147952
|
module2.exports = __toCommonJS(index_exports);
|
|
147953
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");
|
|
147954
|
-
var
|
|
147954
|
+
var import_client2 = require_client();
|
|
147955
147955
|
var import_token_providers = require_dist_cjs66();
|
|
147956
147956
|
var import_property_provider = require_dist_cjs17();
|
|
147957
147957
|
var import_shared_ini_file_loader = require_dist_cjs52();
|
|
@@ -148036,9 +148036,9 @@ var require_dist_cjs67 = __commonJS2((exports, module2) => {
|
|
|
148036
148036
|
...accountId && { accountId }
|
|
148037
148037
|
};
|
|
148038
148038
|
if (ssoSession) {
|
|
148039
|
-
(0,
|
|
148039
|
+
(0, import_client2.setCredentialFeature)(credentials2, "CREDENTIALS_SSO", "s");
|
|
148040
148040
|
} else {
|
|
148041
|
-
(0,
|
|
148041
|
+
(0, import_client2.setCredentialFeature)(credentials2, "CREDENTIALS_SSO_LEGACY", "u");
|
|
148042
148042
|
}
|
|
148043
148043
|
return credentials2;
|
|
148044
148044
|
}, "resolveSSOCredentials");
|
|
@@ -149218,7 +149218,7 @@ var require_sts = __commonJS2((exports, module2) => {
|
|
|
149218
149218
|
};
|
|
149219
149219
|
(0, import_smithy_client6.createAggregatedClient)(commands, STS);
|
|
149220
149220
|
var import_EndpointParameters3 = require_EndpointParameters();
|
|
149221
|
-
var
|
|
149221
|
+
var import_client2 = require_client();
|
|
149222
149222
|
var ASSUME_ROLE_DEFAULT_REGION = "us-east-1";
|
|
149223
149223
|
var getAccountIdFromAssumedRoleUser = /* @__PURE__ */ __name((assumedRoleUser) => {
|
|
149224
149224
|
if (typeof assumedRoleUser?.Arn === "string") {
|
|
@@ -149270,7 +149270,7 @@ var require_sts = __commonJS2((exports, module2) => {
|
|
|
149270
149270
|
...Credentials2.CredentialScope && { credentialScope: Credentials2.CredentialScope },
|
|
149271
149271
|
...accountId && { accountId }
|
|
149272
149272
|
};
|
|
149273
|
-
(0,
|
|
149273
|
+
(0, import_client2.setCredentialFeature)(credentials2, "CREDENTIALS_STS_ASSUME_ROLE", "i");
|
|
149274
149274
|
return credentials2;
|
|
149275
149275
|
};
|
|
149276
149276
|
}, "getDefaultRoleAssumer");
|
|
@@ -149307,9 +149307,9 @@ var require_sts = __commonJS2((exports, module2) => {
|
|
|
149307
149307
|
...accountId && { accountId }
|
|
149308
149308
|
};
|
|
149309
149309
|
if (accountId) {
|
|
149310
|
-
(0,
|
|
149310
|
+
(0, import_client2.setCredentialFeature)(credentials2, "RESOLVED_ACCOUNT_ID", "T");
|
|
149311
149311
|
}
|
|
149312
|
-
(0,
|
|
149312
|
+
(0, import_client2.setCredentialFeature)(credentials2, "CREDENTIALS_STS_ASSUME_ROLE_WEB_ID", "k");
|
|
149313
149313
|
return credentials2;
|
|
149314
149314
|
};
|
|
149315
149315
|
}, "getDefaultRoleAssumerWithWebIdentity");
|
|
@@ -149369,7 +149369,7 @@ var require_dist_cjs68 = __commonJS2((exports, module2) => {
|
|
|
149369
149369
|
var import_property_provider = require_dist_cjs17();
|
|
149370
149370
|
var import_child_process = __require2("child_process");
|
|
149371
149371
|
var import_util3 = __require2("util");
|
|
149372
|
-
var
|
|
149372
|
+
var import_client2 = require_client();
|
|
149373
149373
|
var getValidatedProcessCredentials = /* @__PURE__ */ __name((profileName, data, profiles) => {
|
|
149374
149374
|
if (data.Version !== 1) {
|
|
149375
149375
|
throw Error(`Profile ${profileName} credential_process did not return Version 1.`);
|
|
@@ -149396,7 +149396,7 @@ var require_dist_cjs68 = __commonJS2((exports, module2) => {
|
|
|
149396
149396
|
...data.CredentialScope && { credentialScope: data.CredentialScope },
|
|
149397
149397
|
...accountId && { accountId }
|
|
149398
149398
|
};
|
|
149399
|
-
(0,
|
|
149399
|
+
(0, import_client2.setCredentialFeature)(credentials2, "CREDENTIALS_PROCESS", "w");
|
|
149400
149400
|
return credentials2;
|
|
149401
149401
|
}, "getValidatedProcessCredentials");
|
|
149402
149402
|
var resolveProcessCredentials = /* @__PURE__ */ __name(async (profileName, profiles, logger3) => {
|
|
@@ -149589,7 +149589,7 @@ var require_dist_cjs70 = __commonJS2((exports, module2) => {
|
|
|
149589
149589
|
});
|
|
149590
149590
|
module2.exports = __toCommonJS(index_exports);
|
|
149591
149591
|
var import_shared_ini_file_loader = require_dist_cjs52();
|
|
149592
|
-
var
|
|
149592
|
+
var import_client2 = require_client();
|
|
149593
149593
|
var import_property_provider = require_dist_cjs17();
|
|
149594
149594
|
var resolveCredentialSource = /* @__PURE__ */ __name((credentialSource, profileName, logger3) => {
|
|
149595
149595
|
const sourceProvidersMap = {
|
|
@@ -149616,7 +149616,7 @@ var require_dist_cjs70 = __commonJS2((exports, module2) => {
|
|
|
149616
149616
|
throw new import_property_provider.CredentialsProviderError(`Unsupported credential source in profile ${profileName}. Got ${credentialSource}, expected EcsContainer or Ec2InstanceMetadata or Environment.`, { logger: logger3 });
|
|
149617
149617
|
}
|
|
149618
149618
|
}, "resolveCredentialSource");
|
|
149619
|
-
var setNamedProvider = /* @__PURE__ */ __name((creds) => (0,
|
|
149619
|
+
var setNamedProvider = /* @__PURE__ */ __name((creds) => (0, import_client2.setCredentialFeature)(creds, "CREDENTIALS_PROFILE_NAMED_PROVIDER", "p"), "setNamedProvider");
|
|
149620
149620
|
var isAssumeRoleProfile = /* @__PURE__ */ __name((arg, { profile = "default", logger: logger3 } = {}) => {
|
|
149621
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 }));
|
|
149622
149622
|
}, "isAssumeRoleProfile");
|
|
@@ -149658,7 +149658,7 @@ var require_dist_cjs70 = __commonJS2((exports, module2) => {
|
|
|
149658
149658
|
[source_profile]: true
|
|
149659
149659
|
}, isCredentialSourceWithoutRoleArn(profiles[source_profile] ?? {})) : (await resolveCredentialSource(profileData.credential_source, profileName, options.logger)(options))();
|
|
149660
149660
|
if (isCredentialSourceWithoutRoleArn(profileData)) {
|
|
149661
|
-
return sourceCredsProvider.then((creds) => (0,
|
|
149661
|
+
return sourceCredsProvider.then((creds) => (0, import_client2.setCredentialFeature)(creds, "CREDENTIALS_PROFILE_SOURCE_PROFILE", "o"));
|
|
149662
149662
|
} else {
|
|
149663
149663
|
const params = {
|
|
149664
149664
|
RoleArn: profileData.role_arn,
|
|
@@ -149675,7 +149675,7 @@ var require_dist_cjs70 = __commonJS2((exports, module2) => {
|
|
|
149675
149675
|
params.TokenCode = await options.mfaCodeProvider(mfa_serial);
|
|
149676
149676
|
}
|
|
149677
149677
|
const sourceCreds = await sourceCredsProvider;
|
|
149678
|
-
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"));
|
|
149679
149679
|
}
|
|
149680
149680
|
}, "resolveAssumeRoleCredentials");
|
|
149681
149681
|
var isCredentialSourceWithoutRoleArn = /* @__PURE__ */ __name((section) => {
|
|
@@ -149685,7 +149685,7 @@ var require_dist_cjs70 = __commonJS2((exports, module2) => {
|
|
|
149685
149685
|
var resolveProcessCredentials = /* @__PURE__ */ __name(async (options, profile) => Promise.resolve().then(() => __toESM3(require_dist_cjs68())).then(({ fromProcess }) => fromProcess({
|
|
149686
149686
|
...options,
|
|
149687
149687
|
profile
|
|
149688
|
-
})().then((creds) => (0,
|
|
149688
|
+
})().then((creds) => (0, import_client2.setCredentialFeature)(creds, "CREDENTIALS_PROFILE_PROCESS", "v"))), "resolveProcessCredentials");
|
|
149689
149689
|
var resolveSsoCredentials = /* @__PURE__ */ __name(async (profile, profileData, options = {}) => {
|
|
149690
149690
|
const { fromSSO } = await Promise.resolve().then(() => __toESM3(require_dist_cjs67()));
|
|
149691
149691
|
return fromSSO({
|
|
@@ -149695,9 +149695,9 @@ var require_dist_cjs70 = __commonJS2((exports, module2) => {
|
|
|
149695
149695
|
clientConfig: options.clientConfig
|
|
149696
149696
|
})().then((creds) => {
|
|
149697
149697
|
if (profileData.sso_session) {
|
|
149698
|
-
return (0,
|
|
149698
|
+
return (0, import_client2.setCredentialFeature)(creds, "CREDENTIALS_PROFILE_SSO", "r");
|
|
149699
149699
|
} else {
|
|
149700
|
-
return (0,
|
|
149700
|
+
return (0, import_client2.setCredentialFeature)(creds, "CREDENTIALS_PROFILE_SSO_LEGACY", "t");
|
|
149701
149701
|
}
|
|
149702
149702
|
});
|
|
149703
149703
|
}, "resolveSsoCredentials");
|
|
@@ -149712,7 +149712,7 @@ var require_dist_cjs70 = __commonJS2((exports, module2) => {
|
|
|
149712
149712
|
...profile.aws_credential_scope && { credentialScope: profile.aws_credential_scope },
|
|
149713
149713
|
...profile.aws_account_id && { accountId: profile.aws_account_id }
|
|
149714
149714
|
};
|
|
149715
|
-
return (0,
|
|
149715
|
+
return (0, import_client2.setCredentialFeature)(credentials2, "CREDENTIALS_PROFILE", "n");
|
|
149716
149716
|
}, "resolveStaticCredentials");
|
|
149717
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");
|
|
149718
149718
|
var resolveWebIdentityCredentials = /* @__PURE__ */ __name(async (profile, options) => Promise.resolve().then(() => __toESM3(require_dist_cjs69())).then(({ fromTokenFile: fromTokenFile2 }) => fromTokenFile2({
|
|
@@ -149722,7 +149722,7 @@ var require_dist_cjs70 = __commonJS2((exports, module2) => {
|
|
|
149722
149722
|
roleAssumerWithWebIdentity: options.roleAssumerWithWebIdentity,
|
|
149723
149723
|
logger: options.logger,
|
|
149724
149724
|
parentClientConfig: options.parentClientConfig
|
|
149725
|
-
})().then((creds) => (0,
|
|
149725
|
+
})().then((creds) => (0, import_client2.setCredentialFeature)(creds, "CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN", "q"))), "resolveWebIdentityCredentials");
|
|
149726
149726
|
var resolveProfileData = /* @__PURE__ */ __name(async (profileName, profiles, options, visitedProfiles = {}, isAssumeRoleRecursiveCall = false) => {
|
|
149727
149727
|
const data = profiles[profileName];
|
|
149728
149728
|
if (Object.keys(visitedProfiles).length > 0 && isStaticCredsProfile(data)) {
|
|
@@ -168486,7 +168486,7 @@ var require_lodash2 = __commonJS2((exports, module2) => {
|
|
|
168486
168486
|
}
|
|
168487
168487
|
}
|
|
168488
168488
|
function baseKeysIn(object) {
|
|
168489
|
-
if (!
|
|
168489
|
+
if (!isObject4(object)) {
|
|
168490
168490
|
return nativeKeysIn(object);
|
|
168491
168491
|
}
|
|
168492
168492
|
var isProto = isPrototype(object), result = [];
|
|
@@ -168546,7 +168546,7 @@ var require_lodash2 = __commonJS2((exports, module2) => {
|
|
|
168546
168546
|
return !!length && (typeof value == "number" || reIsUint.test(value)) && (value > -1 && value % 1 == 0 && value < length);
|
|
168547
168547
|
}
|
|
168548
168548
|
function isIterateeCall(value, index6, object) {
|
|
168549
|
-
if (!
|
|
168549
|
+
if (!isObject4(object)) {
|
|
168550
168550
|
return false;
|
|
168551
168551
|
}
|
|
168552
168552
|
var type = typeof index6;
|
|
@@ -168582,13 +168582,13 @@ var require_lodash2 = __commonJS2((exports, module2) => {
|
|
|
168582
168582
|
return isObjectLike2(value) && isArrayLike(value);
|
|
168583
168583
|
}
|
|
168584
168584
|
function isFunction3(value) {
|
|
168585
|
-
var tag2 =
|
|
168585
|
+
var tag2 = isObject4(value) ? objectToString.call(value) : "";
|
|
168586
168586
|
return tag2 == funcTag || tag2 == genTag;
|
|
168587
168587
|
}
|
|
168588
168588
|
function isLength(value) {
|
|
168589
168589
|
return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
|
|
168590
168590
|
}
|
|
168591
|
-
function
|
|
168591
|
+
function isObject4(value) {
|
|
168592
168592
|
var type = typeof value;
|
|
168593
168593
|
return !!value && (type == "object" || type == "function");
|
|
168594
168594
|
}
|
|
@@ -168626,13 +168626,13 @@ var require_lodash3 = __commonJS2((exports, module2) => {
|
|
|
168626
168626
|
return isObjectLike2(value) && isArrayLike(value);
|
|
168627
168627
|
}
|
|
168628
168628
|
function isFunction3(value) {
|
|
168629
|
-
var tag2 =
|
|
168629
|
+
var tag2 = isObject4(value) ? objectToString.call(value) : "";
|
|
168630
168630
|
return tag2 == funcTag || tag2 == genTag;
|
|
168631
168631
|
}
|
|
168632
168632
|
function isLength(value) {
|
|
168633
168633
|
return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
|
|
168634
168634
|
}
|
|
168635
|
-
function
|
|
168635
|
+
function isObject4(value) {
|
|
168636
168636
|
var type = typeof value;
|
|
168637
168637
|
return !!value && (type == "object" || type == "function");
|
|
168638
168638
|
}
|
|
@@ -173723,7 +173723,7 @@ var REDIS_PRESENCE_KEY_PREFIX;
|
|
|
173723
173723
|
var REDIS_ONLINE_USERS_KEY;
|
|
173724
173724
|
var REDIS_POSITION_KEY_PREFIX;
|
|
173725
173725
|
var REDIS_MAP_PLAYERS_KEY_PREFIX;
|
|
173726
|
-
var
|
|
173726
|
+
var init_constants3 = __esm(() => {
|
|
173727
173727
|
HUB_PREFIX = process.env.HUB_PREFIX ?? "hub:";
|
|
173728
173728
|
MAP_PREFIX = process.env.MAP_PREFIX ?? "map_";
|
|
173729
173729
|
PRESENCE_CHANNEL_NAME = process.env.PRESENCE_CHANNEL_NAME ?? "presence";
|
|
@@ -173871,7 +173871,7 @@ var import_ioredis;
|
|
|
173871
173871
|
var client = null;
|
|
173872
173872
|
var init_client = __esm(() => {
|
|
173873
173873
|
init_src();
|
|
173874
|
-
|
|
173874
|
+
init_constants3();
|
|
173875
173875
|
import_ioredis = __toESM2(require_built3(), 1);
|
|
173876
173876
|
});
|
|
173877
173877
|
async function setUserOnline(userId, metadata2) {
|
|
@@ -173982,7 +173982,7 @@ async function updateUserNameplateBg(userId, color) {
|
|
|
173982
173982
|
}
|
|
173983
173983
|
var init_presence = __esm(() => {
|
|
173984
173984
|
init_src();
|
|
173985
|
-
|
|
173985
|
+
init_constants3();
|
|
173986
173986
|
init_client();
|
|
173987
173987
|
});
|
|
173988
173988
|
var init_redis = __esm(() => {
|
|
@@ -174027,11 +174027,11 @@ function extractTokenFromUrl(url) {
|
|
|
174027
174027
|
return null;
|
|
174028
174028
|
}
|
|
174029
174029
|
}
|
|
174030
|
-
var
|
|
174030
|
+
var init_auth3 = __esm(() => {
|
|
174031
174031
|
init_esm2();
|
|
174032
174032
|
init_src();
|
|
174033
174033
|
});
|
|
174034
|
-
function
|
|
174034
|
+
function loadConfig(options = {}) {
|
|
174035
174035
|
const rawRedisHost = process.env.REDIS_HOST || "localhost";
|
|
174036
174036
|
const rawRedisPort = parseInt(process.env.REDIS_PORT || "6379", 10);
|
|
174037
174037
|
const rawRedisPassword = process.env.REDIS_PASSWORD;
|
|
@@ -174076,7 +174076,7 @@ __export(exports_sandbox, {
|
|
|
174076
174076
|
createSandboxRealtimeServer: () => createSandboxRealtimeServer
|
|
174077
174077
|
});
|
|
174078
174078
|
async function createSandboxRealtimeServer(options = {}) {
|
|
174079
|
-
const config2 = await
|
|
174079
|
+
const config2 = await loadConfig(options);
|
|
174080
174080
|
const httpServer = http.createServer((req, res) => {
|
|
174081
174081
|
if (req.url?.endsWith(config2.healthCheckPath)) {
|
|
174082
174082
|
const body2 = JSON.stringify({
|
|
@@ -174158,7 +174158,7 @@ var init_sandbox = __esm(() => {
|
|
|
174158
174158
|
init_wrapper();
|
|
174159
174159
|
init_src();
|
|
174160
174160
|
init_infrastructure2();
|
|
174161
|
-
|
|
174161
|
+
init_auth3();
|
|
174162
174162
|
init_config4();
|
|
174163
174163
|
});
|
|
174164
174164
|
var inMemoryUsers;
|
|
@@ -174244,7 +174244,7 @@ var playerPositions;
|
|
|
174244
174244
|
var PlayerPositionService;
|
|
174245
174245
|
var init_player_position = __esm(() => {
|
|
174246
174246
|
init_src();
|
|
174247
|
-
|
|
174247
|
+
init_constants3();
|
|
174248
174248
|
init_infrastructure2();
|
|
174249
174249
|
playerPositions = new Map;
|
|
174250
174250
|
PlayerPositionService = {
|
|
@@ -174374,7 +174374,7 @@ function computeInitialChannelKey(gameId, requested) {
|
|
|
174374
174374
|
return `${HUB_PREFIX}${channel}`;
|
|
174375
174375
|
}
|
|
174376
174376
|
var init_channel_keys = __esm(() => {
|
|
174377
|
-
|
|
174377
|
+
init_constants3();
|
|
174378
174378
|
});
|
|
174379
174379
|
function ensureAuthenticated(ws) {
|
|
174380
174380
|
if (!ws.data.isAuthenticated || !ws.data.userId) {
|
|
@@ -174393,7 +174393,7 @@ function checkMatchingPlayerId(ws, payload) {
|
|
|
174393
174393
|
}
|
|
174394
174394
|
var init_websocket = __esm(() => {
|
|
174395
174395
|
init_src();
|
|
174396
|
-
|
|
174396
|
+
init_constants3();
|
|
174397
174397
|
});
|
|
174398
174398
|
function extractUserId(pathname) {
|
|
174399
174399
|
const match2 = pathname.match(/^\/presence\/([^/]+)$/);
|
|
@@ -174729,7 +174729,7 @@ async function handleWebSocketUpgrade(req, server, config2) {
|
|
|
174729
174729
|
}
|
|
174730
174730
|
var init_websocket2 = __esm(() => {
|
|
174731
174731
|
init_src();
|
|
174732
|
-
|
|
174732
|
+
init_auth3();
|
|
174733
174733
|
init_response();
|
|
174734
174734
|
});
|
|
174735
174735
|
var init_http2 = __esm(() => {
|
|
@@ -174908,7 +174908,7 @@ var init_open = __esm(() => {
|
|
|
174908
174908
|
init_src();
|
|
174909
174909
|
init_presence4();
|
|
174910
174910
|
init_services2();
|
|
174911
|
-
|
|
174911
|
+
init_constants3();
|
|
174912
174912
|
init_events();
|
|
174913
174913
|
init_infrastructure2();
|
|
174914
174914
|
init_utils13();
|
|
@@ -175132,7 +175132,7 @@ var init_websocket3 = __esm(() => {
|
|
|
175132
175132
|
init_close();
|
|
175133
175133
|
});
|
|
175134
175134
|
async function createRealtimeServer(options = {}) {
|
|
175135
|
-
const config2 =
|
|
175135
|
+
const config2 = loadConfig(options);
|
|
175136
175136
|
const { redisEnabled, positionSyncInterval } = await initializeServer(config2);
|
|
175137
175137
|
const server = Bun.serve({
|
|
175138
175138
|
port: config2.port,
|
|
@@ -182750,12 +182750,17 @@ var timebackXpEvents = pgTable("timeback_xp_event", {
|
|
|
182750
182750
|
}, (table) => [uniqueIndex("timeback_xp_events_source_id_idx").on(table.source, table.sourceId)]);
|
|
182751
182751
|
var gameTimebackIntegrations = pgTable("game_timeback_integrations", {
|
|
182752
182752
|
id: uuid("id").primaryKey().defaultRandom(),
|
|
182753
|
-
gameId: uuid("game_id").notNull().
|
|
182753
|
+
gameId: uuid("game_id").notNull().references(() => games.id, { onDelete: "cascade" }),
|
|
182754
182754
|
courseId: text("course_id").notNull(),
|
|
182755
|
+
grade: integer("grade").notNull(),
|
|
182756
|
+
subject: text("subject").notNull(),
|
|
182757
|
+
totalXp: integer("total_xp"),
|
|
182755
182758
|
lastVerifiedAt: timestamp("last_verified_at", { withTimezone: true }),
|
|
182756
182759
|
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
182757
182760
|
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
182758
|
-
})
|
|
182761
|
+
}, (table) => [
|
|
182762
|
+
uniqueIndex("game_timeback_integrations_game_grade_subject_idx").on(table.gameId, table.grade, table.subject)
|
|
182763
|
+
]);
|
|
182759
182764
|
var achievementScopeEnum = pgEnum("achievement_scope", [
|
|
182760
182765
|
"daily",
|
|
182761
182766
|
"weekly",
|
|
@@ -189292,6 +189297,290 @@ var __export3 = (target, all) => {
|
|
|
189292
189297
|
set: (newValue) => all[name3] = () => newValue
|
|
189293
189298
|
});
|
|
189294
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
|
+
});
|
|
189295
189584
|
function deriveSourcedIds(courseId) {
|
|
189296
189585
|
return {
|
|
189297
189586
|
course: courseId,
|
|
@@ -189307,7 +189596,8 @@ __export3(exports_verify, {
|
|
|
189307
189596
|
});
|
|
189308
189597
|
async function fetchTimebackConfig(client2, courseId) {
|
|
189309
189598
|
const sourcedIds = deriveSourcedIds(courseId);
|
|
189310
|
-
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),
|
|
189311
189601
|
client2.oneroster.courses.get(sourcedIds.course),
|
|
189312
189602
|
client2.oneroster.courseComponents.get(sourcedIds.component),
|
|
189313
189603
|
client2.oneroster.resources.get(sourcedIds.resource),
|
|
@@ -189315,9 +189605,9 @@ async function fetchTimebackConfig(client2, courseId) {
|
|
|
189315
189605
|
]);
|
|
189316
189606
|
return {
|
|
189317
189607
|
organization: {
|
|
189318
|
-
name:
|
|
189319
|
-
type:
|
|
189320
|
-
identifier:
|
|
189608
|
+
name: org.name,
|
|
189609
|
+
type: org.type,
|
|
189610
|
+
identifier: org.identifier || PLAYCADEMY_DEFAULTS.organization
|
|
189321
189611
|
},
|
|
189322
189612
|
course: {
|
|
189323
189613
|
title: course.title || "",
|
|
@@ -189377,145 +189667,10 @@ async function verifyTimebackResources(client2, courseId) {
|
|
|
189377
189667
|
}
|
|
189378
189668
|
};
|
|
189379
189669
|
}
|
|
189380
|
-
var init_verify5 = () => {
|
|
189381
|
-
|
|
189382
|
-
|
|
189383
|
-
|
|
189384
|
-
FOUNDING_MEMBER_BADGE: "FOUNDING_MEMBER_BADGE",
|
|
189385
|
-
EARLY_ADOPTER_BADGE: "EARLY_ADOPTER_BADGE",
|
|
189386
|
-
FIRST_GAME_BADGE: "FIRST_GAME_BADGE",
|
|
189387
|
-
COMMON_SWORD: "COMMON_SWORD",
|
|
189388
|
-
SMALL_HEALTH_POTION: "SMALL_HEALTH_POTION",
|
|
189389
|
-
SMALL_BACKPACK: "SMALL_BACKPACK",
|
|
189390
|
-
LAVA_LAMP: "LAVA_LAMP",
|
|
189391
|
-
BOOMBOX: "BOOMBOX",
|
|
189392
|
-
CABIN_BED: "CABIN_BED"
|
|
189393
|
-
};
|
|
189394
|
-
var CURRENCIES2 = {
|
|
189395
|
-
PRIMARY: ITEM_SLUGS2.PLAYCADEMY_CREDITS,
|
|
189396
|
-
XP: ITEM_SLUGS2.PLAYCADEMY_XP
|
|
189397
|
-
};
|
|
189398
|
-
var BADGES2 = {
|
|
189399
|
-
FOUNDING_MEMBER: ITEM_SLUGS2.FOUNDING_MEMBER_BADGE,
|
|
189400
|
-
EARLY_ADOPTER: ITEM_SLUGS2.EARLY_ADOPTER_BADGE,
|
|
189401
|
-
FIRST_GAME: ITEM_SLUGS2.FIRST_GAME_BADGE
|
|
189402
|
-
};
|
|
189403
|
-
var TIMEBACK_API_URLS = {
|
|
189404
|
-
production: "https://api.alpha-1edtech.ai",
|
|
189405
|
-
staging: "https://api.staging.alpha-1edtech.com"
|
|
189406
|
-
};
|
|
189407
|
-
var TIMEBACK_AUTH_URLS = {
|
|
189408
|
-
production: "https://prod-beyond-timeback-api-2-idp.auth.us-east-1.amazoncognito.com",
|
|
189409
|
-
staging: "https://alpha-auth-development-idp.auth.us-west-2.amazoncognito.com"
|
|
189410
|
-
};
|
|
189411
|
-
var CALIPER_API_URLS = {
|
|
189412
|
-
production: "https://caliper.alpha-1edtech.ai",
|
|
189413
|
-
staging: "https://caliper-staging.alpha-1edtech.com"
|
|
189414
|
-
};
|
|
189415
|
-
var ONEROSTER_ENDPOINTS = {
|
|
189416
|
-
organizations: "/ims/oneroster/rostering/v1p2/orgs",
|
|
189417
|
-
courses: "/ims/oneroster/rostering/v1p2/courses",
|
|
189418
|
-
courseComponents: "/ims/oneroster/rostering/v1p2/courses/components",
|
|
189419
|
-
resources: "/ims/oneroster/resources/v1p2/resources",
|
|
189420
|
-
componentResources: "/ims/oneroster/rostering/v1p2/courses/component-resources",
|
|
189421
|
-
classes: "/ims/oneroster/rostering/v1p2/classes",
|
|
189422
|
-
enrollments: "/ims/oneroster/rostering/v1p2/enrollments",
|
|
189423
|
-
assessmentLineItems: "/ims/oneroster/gradebook/v1p2/assessmentLineItems",
|
|
189424
|
-
assessmentResults: "/ims/oneroster/gradebook/v1p2/assessmentResults",
|
|
189425
|
-
users: "/ims/oneroster/rostering/v1p2/users"
|
|
189426
|
-
};
|
|
189427
|
-
var CALIPER_ENDPOINTS = {
|
|
189428
|
-
events: "/caliper/event",
|
|
189429
|
-
validate: "/caliper/event/validate"
|
|
189430
|
-
};
|
|
189431
|
-
var createOneRosterUrls = (baseUrl) => {
|
|
189432
|
-
const effective = baseUrl || TIMEBACK_API_URLS.production;
|
|
189433
|
-
const base = effective.replace(/\/$/, "");
|
|
189434
|
-
return {
|
|
189435
|
-
user: (userId) => `${base}${ONEROSTER_ENDPOINTS.users}/${userId}`,
|
|
189436
|
-
course: (courseId) => `${base}${ONEROSTER_ENDPOINTS.courses}/${courseId}`,
|
|
189437
|
-
componentResource: (resourceId) => `${base}${ONEROSTER_ENDPOINTS.componentResources}/${resourceId}`
|
|
189438
|
-
};
|
|
189439
|
-
};
|
|
189440
|
-
var CALIPER_CONSTANTS = {
|
|
189441
|
-
context: "http://purl.imsglobal.org/ctx/caliper/v1p2",
|
|
189442
|
-
profile: "TimebackProfile",
|
|
189443
|
-
dataVersion: "http://purl.imsglobal.org/ctx/caliper/v1p2"
|
|
189444
|
-
};
|
|
189445
|
-
var TIMEBACK_EVENT_TYPES = {
|
|
189446
|
-
activityEvent: "ActivityEvent",
|
|
189447
|
-
timeSpentEvent: "TimeSpentEvent"
|
|
189448
|
-
};
|
|
189449
|
-
var TIMEBACK_ACTIONS = {
|
|
189450
|
-
completed: "Completed",
|
|
189451
|
-
spentTime: "SpentTime"
|
|
189452
|
-
};
|
|
189453
|
-
var TIMEBACK_TYPES = {
|
|
189454
|
-
user: "TimebackUser",
|
|
189455
|
-
activityContext: "TimebackActivityContext",
|
|
189456
|
-
activityMetricsCollection: "TimebackActivityMetricsCollection",
|
|
189457
|
-
timeSpentMetricsCollection: "TimebackTimeSpentMetricsCollection"
|
|
189458
|
-
};
|
|
189459
|
-
var ACTIVITY_METRIC_TYPES = {
|
|
189460
|
-
totalQuestions: "totalQuestions",
|
|
189461
|
-
correctQuestions: "correctQuestions",
|
|
189462
|
-
xpEarned: "xpEarned",
|
|
189463
|
-
masteredUnits: "masteredUnits"
|
|
189464
|
-
};
|
|
189465
|
-
var TIME_METRIC_TYPES = {
|
|
189466
|
-
active: "active",
|
|
189467
|
-
inactive: "inactive",
|
|
189468
|
-
waste: "waste",
|
|
189469
|
-
unknown: "unknown",
|
|
189470
|
-
antiPattern: "anti-pattern"
|
|
189471
|
-
};
|
|
189472
|
-
var ONEROSTER_STATUS = {
|
|
189473
|
-
active: "active",
|
|
189474
|
-
toBeDeleted: "tobedeleted"
|
|
189475
|
-
};
|
|
189476
|
-
var SCORE_STATUS = {
|
|
189477
|
-
exempt: "exempt",
|
|
189478
|
-
fullyGraded: "fully graded",
|
|
189479
|
-
notSubmitted: "not submitted",
|
|
189480
|
-
partiallyGraded: "partially graded",
|
|
189481
|
-
submitted: "submitted"
|
|
189482
|
-
};
|
|
189483
|
-
var ENV_VARS = {
|
|
189484
|
-
clientId: "TIMEBACK_CLIENT_ID",
|
|
189485
|
-
clientSecret: "TIMEBACK_CLIENT_SECRET",
|
|
189486
|
-
baseUrl: "TIMEBACK_BASE_URL",
|
|
189487
|
-
environment: "TIMEBACK_ENVIRONMENT",
|
|
189488
|
-
vendorResourceId: "TIMEBACK_VENDOR_RESOURCE_ID",
|
|
189489
|
-
launchBaseUrl: "GAME_URL"
|
|
189490
|
-
};
|
|
189491
|
-
var HTTP_DEFAULTS = {
|
|
189492
|
-
timeout: 30000,
|
|
189493
|
-
retries: 3,
|
|
189494
|
-
retryBackoffBase: 2
|
|
189495
|
-
};
|
|
189496
|
-
var AUTH_DEFAULTS = {
|
|
189497
|
-
tokenCacheDuration: 50000
|
|
189498
|
-
};
|
|
189499
|
-
var CACHE_DEFAULTS = {
|
|
189500
|
-
defaultTTL: 600000,
|
|
189501
|
-
defaultMaxSize: 500,
|
|
189502
|
-
defaultName: "TimebackCache",
|
|
189503
|
-
studentTTL: 600000,
|
|
189504
|
-
studentMaxSize: 500,
|
|
189505
|
-
assessmentTTL: 1800000,
|
|
189506
|
-
assessmentMaxSize: 200
|
|
189507
|
-
};
|
|
189508
|
-
var HTTP_STATUS = {
|
|
189509
|
-
CLIENT_ERROR_MIN: 400,
|
|
189510
|
-
CLIENT_ERROR_MAX: 500,
|
|
189511
|
-
SERVER_ERROR_MIN: 500
|
|
189512
|
-
};
|
|
189513
|
-
var ERROR_NAMES = {
|
|
189514
|
-
timebackAuth: "TimebackAuthError",
|
|
189515
|
-
timebackApi: "TimebackApiError",
|
|
189516
|
-
timebackConfig: "TimebackConfigError",
|
|
189517
|
-
timebackSdk: "TimebackSDKError"
|
|
189518
|
-
};
|
|
189670
|
+
var init_verify5 = __esm3(() => {
|
|
189671
|
+
init_constants();
|
|
189672
|
+
});
|
|
189673
|
+
init_constants();
|
|
189519
189674
|
|
|
189520
189675
|
class TimebackError extends Error {
|
|
189521
189676
|
constructor(message22) {
|
|
@@ -190026,6 +190181,8 @@ async function updateTimebackResources(client2, courseId, config2) {
|
|
|
190026
190181
|
updateComponentResourceLink(client2, config2, sourcedIds)
|
|
190027
190182
|
]);
|
|
190028
190183
|
}
|
|
190184
|
+
init_constants();
|
|
190185
|
+
init_constants();
|
|
190029
190186
|
if (process.env.DEBUG === "true") {
|
|
190030
190187
|
process.env.TERM = "dumb";
|
|
190031
190188
|
}
|
|
@@ -190125,6 +190282,7 @@ async function getTimebackTokenResponse(config2) {
|
|
|
190125
190282
|
function getAuthUrl(environment = "production") {
|
|
190126
190283
|
return TIMEBACK_AUTH_URLS[environment];
|
|
190127
190284
|
}
|
|
190285
|
+
init_constants();
|
|
190128
190286
|
async function request({
|
|
190129
190287
|
path: path22,
|
|
190130
190288
|
baseUrl,
|
|
@@ -190230,6 +190388,7 @@ async function requestCaliper(options) {
|
|
|
190230
190388
|
baseUrl: caliperBase
|
|
190231
190389
|
});
|
|
190232
190390
|
}
|
|
190391
|
+
init_constants();
|
|
190233
190392
|
function logTimebackError(operation, error2, context) {
|
|
190234
190393
|
const errorMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
190235
190394
|
if (error2 instanceof TimebackApiError) {
|
|
@@ -190265,6 +190424,17 @@ function createOneRosterNamespace(client2) {
|
|
|
190265
190424
|
listByCourse: async (courseSourcedId) => {
|
|
190266
190425
|
const res = await client2["request"](`${ONEROSTER_ENDPOINTS.courses}/${courseSourcedId}/classes`, "GET");
|
|
190267
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 || [];
|
|
190268
190438
|
}
|
|
190269
190439
|
},
|
|
190270
190440
|
organizations: {
|
|
@@ -190272,7 +190442,7 @@ function createOneRosterNamespace(client2) {
|
|
|
190272
190442
|
return client2["request"](ONEROSTER_ENDPOINTS.organizations, "POST", data);
|
|
190273
190443
|
},
|
|
190274
190444
|
get: async (sourcedId) => {
|
|
190275
|
-
return client2["request"](`${ONEROSTER_ENDPOINTS.organizations}/${sourcedId}`, "GET");
|
|
190445
|
+
return client2["request"](`${ONEROSTER_ENDPOINTS.organizations}/${sourcedId}`, "GET").then((res) => res.org);
|
|
190276
190446
|
},
|
|
190277
190447
|
update: async (sourcedId, data) => {
|
|
190278
190448
|
return client2["request"](`${ONEROSTER_ENDPOINTS.organizations}/${sourcedId}`, "PUT", data);
|
|
@@ -190400,7 +190570,7 @@ function createOneRosterNamespace(client2) {
|
|
|
190400
190570
|
return client2["request"](ONEROSTER_ENDPOINTS.users, "POST", { user: data });
|
|
190401
190571
|
},
|
|
190402
190572
|
get: async (sourcedId) => {
|
|
190403
|
-
return client2["request"](`${ONEROSTER_ENDPOINTS.users}/${sourcedId}`, "GET");
|
|
190573
|
+
return client2["request"](`${ONEROSTER_ENDPOINTS.users}/${sourcedId}`, "GET").then((res) => res.user);
|
|
190404
190574
|
},
|
|
190405
190575
|
findByEmail: async (email) => {
|
|
190406
190576
|
const params = new URLSearchParams({ filter: `email='${email}'` });
|
|
@@ -190416,6 +190586,7 @@ function createOneRosterNamespace(client2) {
|
|
|
190416
190586
|
}
|
|
190417
190587
|
};
|
|
190418
190588
|
}
|
|
190589
|
+
init_constants();
|
|
190419
190590
|
function createCaliperNamespace(client2) {
|
|
190420
190591
|
const urls = createOneRosterUrls(client2.getBaseUrl());
|
|
190421
190592
|
const caliper = {
|
|
@@ -190453,7 +190624,7 @@ function createCaliperNamespace(client2) {
|
|
|
190453
190624
|
},
|
|
190454
190625
|
action: TIMEBACK_ACTIONS.completed,
|
|
190455
190626
|
object: {
|
|
190456
|
-
id:
|
|
190627
|
+
id: caliper.buildActivityUrl(data),
|
|
190457
190628
|
type: TIMEBACK_TYPES.activityContext,
|
|
190458
190629
|
subject: data.subject,
|
|
190459
190630
|
app: {
|
|
@@ -190463,7 +190634,7 @@ function createCaliperNamespace(client2) {
|
|
|
190463
190634
|
name: data.activityName
|
|
190464
190635
|
},
|
|
190465
190636
|
course: { id: urls.course(data.courseId), name: data.activityName },
|
|
190466
|
-
process:
|
|
190637
|
+
process: false
|
|
190467
190638
|
},
|
|
190468
190639
|
generated: {
|
|
190469
190640
|
id: `urn:timeback:metrics:activity-completion-${crypto.randomUUID()}`,
|
|
@@ -190489,7 +190660,8 @@ function createCaliperNamespace(client2) {
|
|
|
190489
190660
|
value: data.masteredUnits
|
|
190490
190661
|
}
|
|
190491
190662
|
] : []
|
|
190492
|
-
]
|
|
190663
|
+
],
|
|
190664
|
+
...data.extensions ? { extensions: data.extensions } : {}
|
|
190493
190665
|
}
|
|
190494
190666
|
};
|
|
190495
190667
|
return caliper.emit(event, data.sensorUrl);
|
|
@@ -190508,7 +190680,7 @@ function createCaliperNamespace(client2) {
|
|
|
190508
190680
|
},
|
|
190509
190681
|
action: TIMEBACK_ACTIONS.spentTime,
|
|
190510
190682
|
object: {
|
|
190511
|
-
id:
|
|
190683
|
+
id: caliper.buildActivityUrl(data),
|
|
190512
190684
|
type: TIMEBACK_TYPES.activityContext,
|
|
190513
190685
|
subject: data.subject,
|
|
190514
190686
|
app: {
|
|
@@ -190536,10 +190708,33 @@ function createCaliperNamespace(client2) {
|
|
|
190536
190708
|
}
|
|
190537
190709
|
};
|
|
190538
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()}`;
|
|
190539
190715
|
}
|
|
190540
190716
|
};
|
|
190541
190717
|
return caliper;
|
|
190542
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();
|
|
190543
190738
|
|
|
190544
190739
|
class TimebackCache {
|
|
190545
190740
|
cache = new Map;
|
|
@@ -190645,6 +190840,7 @@ class TimebackCache {
|
|
|
190645
190840
|
class TimebackCacheManager {
|
|
190646
190841
|
studentCache;
|
|
190647
190842
|
assessmentLineItemCache;
|
|
190843
|
+
resourceMasteryCache;
|
|
190648
190844
|
constructor() {
|
|
190649
190845
|
this.studentCache = new TimebackCache({
|
|
190650
190846
|
defaultTTL: CACHE_DEFAULTS.studentTTL,
|
|
@@ -190656,6 +190852,11 @@ class TimebackCacheManager {
|
|
|
190656
190852
|
maxSize: CACHE_DEFAULTS.assessmentMaxSize,
|
|
190657
190853
|
name: "AssessmentLineItemCache"
|
|
190658
190854
|
});
|
|
190855
|
+
this.resourceMasteryCache = new TimebackCache({
|
|
190856
|
+
defaultTTL: CACHE_DEFAULTS.assessmentTTL,
|
|
190857
|
+
maxSize: CACHE_DEFAULTS.assessmentMaxSize,
|
|
190858
|
+
name: "ResourceMasteryCache"
|
|
190859
|
+
});
|
|
190659
190860
|
}
|
|
190660
190861
|
getStudent(key) {
|
|
190661
190862
|
return this.studentCache.get(key);
|
|
@@ -190669,6 +190870,12 @@ class TimebackCacheManager {
|
|
|
190669
190870
|
setAssessmentLineItem(key, lineItemId) {
|
|
190670
190871
|
this.assessmentLineItemCache.set(key, lineItemId);
|
|
190671
190872
|
}
|
|
190873
|
+
getResourceMasterableUnits(key) {
|
|
190874
|
+
return this.resourceMasteryCache.get(key);
|
|
190875
|
+
}
|
|
190876
|
+
setResourceMasterableUnits(key, value) {
|
|
190877
|
+
this.resourceMasteryCache.set(key, value);
|
|
190878
|
+
}
|
|
190672
190879
|
clearAll() {
|
|
190673
190880
|
this.studentCache.clear();
|
|
190674
190881
|
this.assessmentLineItemCache.clear();
|
|
@@ -190677,18 +190884,32 @@ class TimebackCacheManager {
|
|
|
190677
190884
|
getStats() {
|
|
190678
190885
|
return {
|
|
190679
190886
|
studentCache: this.studentCache.stats(),
|
|
190680
|
-
assessmentLineItemCache: this.assessmentLineItemCache.stats()
|
|
190887
|
+
assessmentLineItemCache: this.assessmentLineItemCache.stats(),
|
|
190888
|
+
resourceMasteryCache: this.resourceMasteryCache.stats()
|
|
190681
190889
|
};
|
|
190682
190890
|
}
|
|
190683
190891
|
cleanup() {
|
|
190684
190892
|
this.studentCache.cleanup();
|
|
190685
190893
|
this.assessmentLineItemCache.cleanup();
|
|
190894
|
+
this.resourceMasteryCache.cleanup();
|
|
190686
190895
|
log32.debug("[TimebackCacheManager] Cache cleanup completed");
|
|
190687
190896
|
}
|
|
190688
190897
|
}
|
|
190689
190898
|
function kebabToTitleCase(kebabStr) {
|
|
190690
190899
|
return kebabStr.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
190691
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
|
+
}
|
|
190692
190913
|
function validateProgressData(progressData) {
|
|
190693
190914
|
if (!progressData.subject) {
|
|
190694
190915
|
throw new ConfigurationError("subject", "Subject is required for Caliper events. Provide it in progressData.subject");
|
|
@@ -190742,36 +190963,47 @@ class ProgressRecorder {
|
|
|
190742
190963
|
cacheManager;
|
|
190743
190964
|
onerosterNamespace;
|
|
190744
190965
|
caliperNamespace;
|
|
190745
|
-
|
|
190966
|
+
edubridgeNamespace;
|
|
190967
|
+
constructor(studentResolver, cacheManager, onerosterNamespace, caliperNamespace, edubridgeNamespace) {
|
|
190746
190968
|
this.studentResolver = studentResolver;
|
|
190747
190969
|
this.cacheManager = cacheManager;
|
|
190748
190970
|
this.onerosterNamespace = onerosterNamespace;
|
|
190749
190971
|
this.caliperNamespace = caliperNamespace;
|
|
190972
|
+
this.edubridgeNamespace = edubridgeNamespace;
|
|
190750
190973
|
}
|
|
190751
190974
|
async record(courseId, studentIdentifier, progressData) {
|
|
190752
190975
|
validateProgressData(progressData);
|
|
190753
|
-
const ids =
|
|
190754
|
-
const activityId = progressData.activityId || ids.componentResource || ids.resource || "unknown-activity";
|
|
190755
|
-
const activityName = progressData.activityName || kebabToTitleCase(activityId);
|
|
190756
|
-
const classId = progressData.classId;
|
|
190757
|
-
const courseName = progressData.courseName || "Game Course";
|
|
190758
|
-
const student = await this.studentResolver.resolve(studentIdentifier, progressData.studentEmail);
|
|
190976
|
+
const { ids, activityId, activityName, courseName, student } = await this.resolveContext(courseId, studentIdentifier, progressData);
|
|
190759
190977
|
const { id: studentId, email: studentEmail } = student;
|
|
190760
190978
|
const { score, totalQuestions, correctQuestions, xpEarned, masteredUnits, attemptNumber } = progressData;
|
|
190761
|
-
const
|
|
190762
|
-
|
|
190763
|
-
if (!actualLineItemId) {
|
|
190764
|
-
actualLineItemId = await this.getOrCreateLineItem(lineItemId, activityName, classId, ids);
|
|
190765
|
-
this.cacheManager.setAssessmentLineItem(lineItemId, actualLineItemId);
|
|
190766
|
-
}
|
|
190767
|
-
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);
|
|
190768
190981
|
const isFirstAttempt = currentAttemptNumber === 1;
|
|
190769
|
-
if (!attemptNumber && score !== undefined) {
|
|
190770
|
-
currentAttemptNumber = await this.determineAttemptNumber(studentId, actualLineItemId);
|
|
190771
|
-
}
|
|
190772
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
|
+
}
|
|
190773
191005
|
if (score !== undefined) {
|
|
190774
|
-
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);
|
|
190775
191007
|
} else {
|
|
190776
191008
|
log32.warn("[ProgressRecorder] Score not provided, skipping gradebook entry", {
|
|
190777
191009
|
studentId,
|
|
@@ -190779,12 +191011,151 @@ class ProgressRecorder {
|
|
|
190779
191011
|
attemptNumber: currentAttemptNumber
|
|
190780
191012
|
});
|
|
190781
191013
|
}
|
|
190782
|
-
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);
|
|
190783
191015
|
return {
|
|
190784
191016
|
xpAwarded: calculatedXp,
|
|
190785
|
-
attemptNumber: currentAttemptNumber
|
|
191017
|
+
attemptNumber: currentAttemptNumber,
|
|
191018
|
+
masteredUnitsApplied: progressData.masteredUnits ?? 0,
|
|
191019
|
+
pctCompleteApp,
|
|
191020
|
+
scoreStatus,
|
|
191021
|
+
inProgress
|
|
190786
191022
|
};
|
|
190787
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
|
+
}
|
|
190788
191159
|
async getOrCreateLineItem(lineItemId, activityName, classId, ids) {
|
|
190789
191160
|
try {
|
|
190790
191161
|
const lineItem = await this.onerosterNamespace.assessmentLineItems.findOrCreate(lineItemId, {
|
|
@@ -190823,25 +191194,7 @@ class ProgressRecorder {
|
|
|
190823
191194
|
}
|
|
190824
191195
|
return 1;
|
|
190825
191196
|
}
|
|
190826
|
-
|
|
190827
|
-
if (xpEarned !== undefined) {
|
|
190828
|
-
log32.debug("[ProgressRecorder] Using provided XP", { xpEarned });
|
|
190829
|
-
return xpEarned;
|
|
190830
|
-
}
|
|
190831
|
-
if (progressData.sessionDurationSeconds && totalQuestions && correctQuestions) {
|
|
190832
|
-
const accuracy = correctQuestions / totalQuestions;
|
|
190833
|
-
const calculatedXp = calculateXp(progressData.sessionDurationSeconds, accuracy, isFirstAttempt);
|
|
190834
|
-
log32.debug("[ProgressRecorder] Calculated XP", {
|
|
190835
|
-
durationSeconds: progressData.sessionDurationSeconds,
|
|
190836
|
-
accuracy,
|
|
190837
|
-
isFirstAttempt,
|
|
190838
|
-
calculatedXp
|
|
190839
|
-
});
|
|
190840
|
-
return calculatedXp;
|
|
190841
|
-
}
|
|
190842
|
-
return 0;
|
|
190843
|
-
}
|
|
190844
|
-
async createGradebookEntry(lineItemId, studentId, attemptNumber, score, totalQuestions, correctQuestions, xp) {
|
|
191197
|
+
async createGradebookEntry(lineItemId, studentId, attemptNumber, score, totalQuestions, correctQuestions, xp, masteredUnits, scoreStatus, inProgress, appName) {
|
|
190845
191198
|
const resultId = `${lineItemId}:${studentId}:attempt-${attemptNumber}`;
|
|
190846
191199
|
await this.onerosterNamespace.assessmentResults.upsert(resultId, {
|
|
190847
191200
|
sourcedId: resultId,
|
|
@@ -190850,18 +191203,21 @@ class ProgressRecorder {
|
|
|
190850
191203
|
student: { sourcedId: studentId },
|
|
190851
191204
|
score,
|
|
190852
191205
|
scoreDate: new Date().toISOString(),
|
|
190853
|
-
scoreStatus
|
|
191206
|
+
scoreStatus,
|
|
191207
|
+
inProgress,
|
|
190854
191208
|
metadata: {
|
|
190855
191209
|
xp,
|
|
190856
191210
|
totalQuestions,
|
|
190857
191211
|
correctQuestions,
|
|
190858
191212
|
accuracy: totalQuestions && correctQuestions ? correctQuestions / totalQuestions * 100 : undefined,
|
|
190859
191213
|
attemptNumber,
|
|
190860
|
-
lastUpdated: new Date().toISOString()
|
|
191214
|
+
lastUpdated: new Date().toISOString(),
|
|
191215
|
+
masteredUnits,
|
|
191216
|
+
appName
|
|
190861
191217
|
}
|
|
190862
191218
|
});
|
|
190863
191219
|
}
|
|
190864
|
-
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) {
|
|
190865
191221
|
await this.caliperNamespace.emitActivityEvent({
|
|
190866
191222
|
studentId,
|
|
190867
191223
|
studentEmail,
|
|
@@ -190876,7 +191232,8 @@ class ProgressRecorder {
|
|
|
190876
191232
|
attemptNumber,
|
|
190877
191233
|
subject: progressData.subject,
|
|
190878
191234
|
appName: progressData.appName,
|
|
190879
|
-
sensorUrl: progressData.sensorUrl
|
|
191235
|
+
sensorUrl: progressData.sensorUrl,
|
|
191236
|
+
extensions: extensions || progressData.extensions
|
|
190880
191237
|
}).catch((error2) => {
|
|
190881
191238
|
log32.error("[ProgressRecorder] Failed to emit activity event", { error: error2 });
|
|
190882
191239
|
});
|
|
@@ -194991,9 +195348,10 @@ class TimebackClient {
|
|
|
194991
195348
|
};
|
|
194992
195349
|
this.oneroster = createOneRosterNamespace(this);
|
|
194993
195350
|
this.caliper = createCaliperNamespace(this);
|
|
195351
|
+
this.edubridge = createEduBridgeNamespace(this);
|
|
194994
195352
|
this.cacheManager = new TimebackCacheManager;
|
|
194995
195353
|
this.studentResolver = new StudentResolver(this.cacheManager, this.oneroster);
|
|
194996
|
-
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);
|
|
194997
195355
|
this.sessionRecorder = new SessionRecorder(this.studentResolver, this.caliper);
|
|
194998
195356
|
if (this.credentials) {
|
|
194999
195357
|
this._ensureAuthenticated().catch((error2) => {
|
|
@@ -195102,6 +195460,9 @@ class TimebackClient {
|
|
|
195102
195460
|
}
|
|
195103
195461
|
await this.authenticate();
|
|
195104
195462
|
}
|
|
195463
|
+
async resolveStudent(studentIdentifier, providedEmail) {
|
|
195464
|
+
return this.studentResolver.resolve(studentIdentifier, providedEmail);
|
|
195465
|
+
}
|
|
195105
195466
|
async recordProgress(courseId, studentIdentifier, progressData) {
|
|
195106
195467
|
await this._ensureAuthenticated();
|
|
195107
195468
|
return this.progressRecorder.record(courseId, studentIdentifier, progressData);
|
|
@@ -195110,6 +195471,19 @@ class TimebackClient {
|
|
|
195110
195471
|
await this._ensureAuthenticated();
|
|
195111
195472
|
return this.sessionRecorder.record(courseId, studentIdentifier, sessionData);
|
|
195112
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
|
+
}
|
|
195113
195487
|
clearCaches() {
|
|
195114
195488
|
this.cacheManager.clearAll();
|
|
195115
195489
|
}
|
|
@@ -195121,6 +195495,7 @@ class TimebackClient {
|
|
|
195121
195495
|
}
|
|
195122
195496
|
oneroster;
|
|
195123
195497
|
caliper;
|
|
195498
|
+
edubridge;
|
|
195124
195499
|
async setup(config2, options) {
|
|
195125
195500
|
return setupTimebackResources(this, config2, options);
|
|
195126
195501
|
}
|
|
@@ -195137,6 +195512,306 @@ class TimebackClient {
|
|
|
195137
195512
|
return deleteTimebackResources(this, courseId);
|
|
195138
195513
|
}
|
|
195139
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
|
+
}
|
|
195140
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}$/;
|
|
195141
195816
|
function isValidUUID(value) {
|
|
195142
195817
|
if (!value || typeof value !== "string") {
|
|
@@ -195413,6 +196088,32 @@ async function getTimebackClient() {
|
|
|
195413
196088
|
}
|
|
195414
196089
|
return timebackClient;
|
|
195415
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
|
+
}
|
|
195416
196117
|
var AchievementCompletionType;
|
|
195417
196118
|
((AchievementCompletionType2) => {
|
|
195418
196119
|
AchievementCompletionType2["TIME_PLAYED_SESSION"] = "time_played_session";
|
|
@@ -195936,6 +196637,246 @@ var AchievementService = {
|
|
|
195936
196637
|
generateAchievementMessage
|
|
195937
196638
|
};
|
|
195938
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
|
+
|
|
195939
196880
|
class JwtBaseError extends Error {
|
|
195940
196881
|
}
|
|
195941
196882
|
|
|
@@ -198478,6 +199419,21 @@ var logger3 = {
|
|
|
198478
199419
|
warn: (msg) => getLogger().warn(msg),
|
|
198479
199420
|
error: (msg) => getLogger().error(msg)
|
|
198480
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
|
+
}
|
|
198481
199437
|
async function seedCoreGames(db) {
|
|
198482
199438
|
const now2 = new Date;
|
|
198483
199439
|
const coreGames = [
|
|
@@ -198502,18 +199458,26 @@ async function seedCoreGames(db) {
|
|
|
198502
199458
|
console.error(`Error seeding core game '${gameData.slug}':`, error2);
|
|
198503
199459
|
}
|
|
198504
199460
|
}
|
|
198505
|
-
if (
|
|
198506
|
-
|
|
198507
|
-
|
|
198508
|
-
|
|
198509
|
-
|
|
198510
|
-
|
|
198511
|
-
|
|
198512
|
-
|
|
198513
|
-
|
|
198514
|
-
|
|
198515
|
-
|
|
198516
|
-
|
|
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
|
+
}
|
|
198517
199481
|
}
|
|
198518
199482
|
}
|
|
198519
199483
|
}
|
|
@@ -198544,18 +199508,23 @@ async function seedCurrentProjectGame(db, project) {
|
|
|
198544
199508
|
updatedAt: now2
|
|
198545
199509
|
};
|
|
198546
199510
|
const [newGame] = await db.insert(games).values(gameRecord).returning();
|
|
198547
|
-
if (
|
|
198548
|
-
|
|
198549
|
-
|
|
198550
|
-
|
|
198551
|
-
|
|
198552
|
-
|
|
198553
|
-
|
|
198554
|
-
|
|
198555
|
-
|
|
198556
|
-
|
|
198557
|
-
|
|
198558
|
-
|
|
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
|
+
}
|
|
198559
199528
|
}
|
|
198560
199529
|
return newGame;
|
|
198561
199530
|
} catch (error2) {
|
|
@@ -198883,6 +199852,12 @@ async function applyForDeveloperStatus(ctx) {
|
|
|
198883
199852
|
userId: user.id,
|
|
198884
199853
|
newStatus: "pending"
|
|
198885
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
|
+
});
|
|
198886
199861
|
} catch (error2) {
|
|
198887
199862
|
log2.error(`Error updating developer status for user ${user.id}:`, {
|
|
198888
199863
|
error: error2
|
|
@@ -203595,6 +204570,67 @@ var NotificationStatsSchema = exports_external2.object({
|
|
|
203595
204570
|
startDate: exports_external2.date().optional(),
|
|
203596
204571
|
endDate: exports_external2.date().optional()
|
|
203597
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
|
+
});
|
|
203598
204634
|
init_src();
|
|
203599
204635
|
async function submitScore(ctx) {
|
|
203600
204636
|
const { user, params, request: request3 } = ctx;
|
|
@@ -203762,6 +204798,26 @@ async function getUserAllScores(ctx) {
|
|
|
203762
204798
|
throw ApiError.internal("Failed to fetch user scores");
|
|
203763
204799
|
}
|
|
203764
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
|
+
}
|
|
203765
204821
|
init_src();
|
|
203766
204822
|
async function getUserLevel(ctx) {
|
|
203767
204823
|
const user = ctx.user;
|
|
@@ -204405,7 +205461,7 @@ async function deleteGame(ctx) {
|
|
|
204405
205461
|
const db = getDatabase();
|
|
204406
205462
|
const gameToDelete = await db.query.games.findFirst({
|
|
204407
205463
|
where: eq(games.id, gameId),
|
|
204408
|
-
columns: { id: true, slug: true }
|
|
205464
|
+
columns: { id: true, slug: true, displayName: true }
|
|
204409
205465
|
});
|
|
204410
205466
|
if (!gameToDelete || !gameToDelete.slug) {
|
|
204411
205467
|
throw ApiError.notFound("Game not found for deletion");
|
|
@@ -204427,6 +205483,16 @@ async function deleteGame(ctx) {
|
|
|
204427
205483
|
hadActiveDeployment: !!activeDeployment,
|
|
204428
205484
|
customDomainsCount: customDomains.length
|
|
204429
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
|
+
});
|
|
204430
205496
|
if (activeDeployment?.provider === "cloudflare") {
|
|
204431
205497
|
try {
|
|
204432
205498
|
const cloudflare2 = getCloudflareProvider();
|
|
@@ -205990,6 +207056,26 @@ gameScoresRouter.post("/:gameId/scores", async (c3) => {
|
|
|
205990
207056
|
return c3.json(createUnknownErrorResponse(error2), 500);
|
|
205991
207057
|
}
|
|
205992
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
|
+
});
|
|
205993
207079
|
init_src();
|
|
205994
207080
|
async function startGameSession(ctx) {
|
|
205995
207081
|
const user = ctx.user;
|
|
@@ -208726,39 +209812,21 @@ async function endActivity(ctx) {
|
|
|
208726
209812
|
throw ApiError.unauthorized("Must be logged in to end activity");
|
|
208727
209813
|
}
|
|
208728
209814
|
log2.debug("[API] Ending activity", { userId: user.id });
|
|
208729
|
-
|
|
208730
|
-
|
|
208731
|
-
|
|
208732
|
-
|
|
208733
|
-
} catch (error2) {
|
|
208734
|
-
log2.error("[API] Failed to parse request body:", { error: error2 });
|
|
208735
|
-
throw ApiError.badRequest("Invalid JSON body");
|
|
208736
|
-
}
|
|
208737
|
-
const { gameId, studentId, activityData, scoreData, timingData, xpEarned } = request3;
|
|
208738
|
-
if (!activityData?.activityId) {
|
|
208739
|
-
throw ApiError.badRequest("activityId is required");
|
|
208740
|
-
}
|
|
208741
|
-
if (typeof scoreData?.correctQuestions !== "number" || typeof scoreData?.totalQuestions !== "number") {
|
|
208742
|
-
throw ApiError.badRequest("correctQuestions and totalQuestions are required");
|
|
208743
|
-
}
|
|
208744
|
-
if (typeof timingData?.durationSeconds !== "number") {
|
|
208745
|
-
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));
|
|
208746
209819
|
}
|
|
209820
|
+
const { gameId, studentId, activityData, scoreData, timingData, xpEarned, masteredUnits } = validation2.data;
|
|
209821
|
+
await verifyGameAccessById(gameId, user);
|
|
208747
209822
|
const db = getDatabase();
|
|
208748
|
-
const
|
|
208749
|
-
where: eq(games.id, gameId)
|
|
208750
|
-
});
|
|
208751
|
-
if (!game) {
|
|
208752
|
-
throw ApiError.notFound("Game not found");
|
|
208753
|
-
}
|
|
208754
|
-
if (user.role !== "admin" && game.developerId !== user.id) {
|
|
208755
|
-
throw ApiError.forbidden("You do not own this game");
|
|
208756
|
-
}
|
|
209823
|
+
const { grade, subject } = activityData;
|
|
208757
209824
|
const integration = await db.query.gameTimebackIntegrations.findFirst({
|
|
208758
|
-
where: eq(
|
|
209825
|
+
where: (table14, { eq: eq3, and: and3 }) => and3(eq3(table14.gameId, gameId), eq3(table14.grade, grade), eq3(table14.subject, subject))
|
|
208759
209826
|
});
|
|
208760
209827
|
if (!integration) {
|
|
208761
|
-
|
|
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.`);
|
|
208762
209830
|
}
|
|
208763
209831
|
const client2 = await getTimebackClient();
|
|
208764
209832
|
try {
|
|
@@ -208769,6 +209837,7 @@ async function endActivity(ctx) {
|
|
|
208769
209837
|
correctQuestions: scoreData.correctQuestions,
|
|
208770
209838
|
sessionDurationSeconds: timingData.durationSeconds,
|
|
208771
209839
|
xpEarned,
|
|
209840
|
+
masteredUnits,
|
|
208772
209841
|
activityId: activityData.activityId,
|
|
208773
209842
|
activityName: activityData.activityName,
|
|
208774
209843
|
subject: activityData.subject,
|
|
@@ -208776,8 +209845,11 @@ async function endActivity(ctx) {
|
|
|
208776
209845
|
sensorUrl: activityData.sensorUrl,
|
|
208777
209846
|
courseId: activityData.courseId,
|
|
208778
209847
|
courseName: activityData.courseName,
|
|
208779
|
-
studentEmail: activityData.studentEmail
|
|
209848
|
+
studentEmail: activityData.studentEmail,
|
|
209849
|
+
courseTotalXp: integration.totalXp
|
|
208780
209850
|
});
|
|
209851
|
+
const studentData = await client2.resolveStudent(studentId);
|
|
209852
|
+
const studentEmail = studentData.email;
|
|
208781
209853
|
await client2.recordSessionEnd(integration.courseId, studentId, {
|
|
208782
209854
|
activeTimeSeconds: timingData.durationSeconds,
|
|
208783
209855
|
activityId: activityData.activityId,
|
|
@@ -208793,17 +209865,26 @@ async function endActivity(ctx) {
|
|
|
208793
209865
|
gameId,
|
|
208794
209866
|
courseId: integration.courseId,
|
|
208795
209867
|
studentId,
|
|
209868
|
+
studentEmail,
|
|
208796
209869
|
activityId: activityData.activityId,
|
|
208797
209870
|
score: scorePercentage,
|
|
208798
209871
|
durationSeconds: timingData.durationSeconds,
|
|
208799
209872
|
attemptNumber: result.attemptNumber,
|
|
208800
209873
|
isFirstAttempt: result.attemptNumber === 1,
|
|
208801
|
-
xpAwarded: result.xpAwarded
|
|
209874
|
+
xpAwarded: result.xpAwarded,
|
|
209875
|
+
masteredUnits,
|
|
209876
|
+
pctCompleteApp: result.pctCompleteApp,
|
|
209877
|
+
scoreStatus: result.scoreStatus,
|
|
209878
|
+
inProgress: result.inProgress
|
|
208802
209879
|
});
|
|
208803
209880
|
return {
|
|
208804
209881
|
status: "ok",
|
|
208805
209882
|
courseId: integration.courseId,
|
|
208806
|
-
xpAwarded: result.xpAwarded
|
|
209883
|
+
xpAwarded: result.xpAwarded,
|
|
209884
|
+
masteredUnits: result.masteredUnitsApplied,
|
|
209885
|
+
pctCompleteApp: result.pctCompleteApp,
|
|
209886
|
+
scoreStatus: result.scoreStatus,
|
|
209887
|
+
inProgress: result.inProgress
|
|
208807
209888
|
};
|
|
208808
209889
|
} catch (error2) {
|
|
208809
209890
|
logTimebackError2("end activity", error2, {
|
|
@@ -208829,68 +209910,160 @@ async function setupTimebackIntegration(ctx) {
|
|
|
208829
209910
|
log2.error("Failed to parse request body:", { error: error2 });
|
|
208830
209911
|
throw ApiError.badRequest("Invalid JSON body");
|
|
208831
209912
|
}
|
|
208832
|
-
const { gameId,
|
|
209913
|
+
const { gameId, courses, baseConfig, verbose } = request3;
|
|
208833
209914
|
log2.debug("[API] TimeBack setup request", {
|
|
208834
209915
|
gameId,
|
|
208835
|
-
|
|
209916
|
+
courseCount: courses.length
|
|
208836
209917
|
});
|
|
209918
|
+
await verifyGameAccessById(gameId, user);
|
|
208837
209919
|
const db = getDatabase();
|
|
208838
|
-
const
|
|
208839
|
-
where: eq(games.id, gameId)
|
|
208840
|
-
});
|
|
208841
|
-
if (!game) {
|
|
208842
|
-
throw ApiError.notFound("Game not found");
|
|
208843
|
-
}
|
|
208844
|
-
if (user.role !== "admin" && game.developerId !== user.id) {
|
|
208845
|
-
throw ApiError.forbidden("You do not own this game");
|
|
208846
|
-
}
|
|
208847
|
-
const existing = await db.query.gameTimebackIntegrations.findFirst({
|
|
209920
|
+
const existing = await db.query.gameTimebackIntegrations.findMany({
|
|
208848
209921
|
where: eq(gameTimebackIntegrations.gameId, gameId)
|
|
208849
209922
|
});
|
|
208850
209923
|
const client2 = await getTimebackClient();
|
|
208851
|
-
|
|
208852
|
-
|
|
208853
|
-
|
|
208854
|
-
|
|
208855
|
-
|
|
208856
|
-
|
|
208857
|
-
|
|
208858
|
-
|
|
208859
|
-
|
|
208860
|
-
|
|
208861
|
-
|
|
208862
|
-
|
|
208863
|
-
|
|
208864
|
-
|
|
208865
|
-
|
|
208866
|
-
|
|
208867
|
-
|
|
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
|
+
}
|
|
208868
209986
|
};
|
|
208869
|
-
|
|
208870
|
-
|
|
208871
|
-
|
|
208872
|
-
|
|
208873
|
-
|
|
208874
|
-
|
|
208875
|
-
|
|
208876
|
-
|
|
208877
|
-
|
|
208878
|
-
|
|
208879
|
-
|
|
208880
|
-
|
|
208881
|
-
|
|
208882
|
-
|
|
208883
|
-
|
|
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
|
+
}
|
|
208884
210059
|
}
|
|
208885
210060
|
log2.info("[API] Created TimeBack integration", {
|
|
208886
210061
|
gameId,
|
|
208887
|
-
|
|
208888
|
-
...result.verboseData && { verbose: result.verboseData }
|
|
210062
|
+
courseCount: integrations.length
|
|
208889
210063
|
});
|
|
208890
210064
|
return {
|
|
208891
|
-
|
|
208892
|
-
|
|
208893
|
-
...result.verboseData && { verbose: result.verboseData }
|
|
210065
|
+
integrations,
|
|
210066
|
+
...verbose && verboseData.length > 0 && { verbose: verboseData }
|
|
208894
210067
|
};
|
|
208895
210068
|
}
|
|
208896
210069
|
async function getTimebackIntegration(ctx) {
|
|
@@ -208902,21 +210075,13 @@ async function getTimebackIntegration(ctx) {
|
|
|
208902
210075
|
if (!gameId) {
|
|
208903
210076
|
throw ApiError.badRequest("Missing gameId parameter");
|
|
208904
210077
|
}
|
|
208905
|
-
log2.debug("[API] Getting TimeBack
|
|
210078
|
+
log2.debug("[API] Getting TimeBack integrations", { userId: user.id, gameId });
|
|
210079
|
+
await verifyGameAccessById(gameId, user);
|
|
208906
210080
|
const db = getDatabase();
|
|
208907
|
-
const
|
|
208908
|
-
where: eq(games.id, gameId)
|
|
208909
|
-
});
|
|
208910
|
-
if (!game) {
|
|
208911
|
-
throw ApiError.notFound("Game not found");
|
|
208912
|
-
}
|
|
208913
|
-
if (user.role !== "admin" && game.developerId !== user.id) {
|
|
208914
|
-
throw ApiError.forbidden("You do not own this game");
|
|
208915
|
-
}
|
|
208916
|
-
const integration = await db.query.gameTimebackIntegrations.findFirst({
|
|
210081
|
+
const integrations = await db.query.gameTimebackIntegrations.findMany({
|
|
208917
210082
|
where: eq(gameTimebackIntegrations.gameId, gameId)
|
|
208918
210083
|
});
|
|
208919
|
-
return
|
|
210084
|
+
return integrations;
|
|
208920
210085
|
}
|
|
208921
210086
|
async function verifyTimebackIntegration(ctx) {
|
|
208922
210087
|
const user = ctx.user;
|
|
@@ -208928,39 +210093,40 @@ async function verifyTimebackIntegration(ctx) {
|
|
|
208928
210093
|
throw ApiError.badRequest("Missing gameId parameter");
|
|
208929
210094
|
}
|
|
208930
210095
|
log2.debug("[API] Verifying TimeBack integration", { userId: user.id, gameId });
|
|
210096
|
+
await verifyGameAccessById(gameId, user);
|
|
208931
210097
|
const db = getDatabase();
|
|
208932
|
-
const
|
|
208933
|
-
where: eq(games.id, gameId)
|
|
208934
|
-
});
|
|
208935
|
-
if (!game) {
|
|
208936
|
-
throw ApiError.notFound("Game not found");
|
|
208937
|
-
}
|
|
208938
|
-
if (user.role !== "admin" && game.developerId !== user.id) {
|
|
208939
|
-
log2.error("[API] User does not own game", { userId: user.id, gameId });
|
|
208940
|
-
throw ApiError.forbidden("You do not own this game");
|
|
208941
|
-
}
|
|
208942
|
-
const integration = await db.query.gameTimebackIntegrations.findFirst({
|
|
210098
|
+
const integrations = await db.query.gameTimebackIntegrations.findMany({
|
|
208943
210099
|
where: eq(gameTimebackIntegrations.gameId, gameId)
|
|
208944
210100
|
});
|
|
208945
|
-
if (
|
|
210101
|
+
if (integrations.length === 0) {
|
|
210102
|
+
log2.error("[API] No TimeBack integration found", { gameId });
|
|
208946
210103
|
throw ApiError.notFound("No TimeBack integration found for this game");
|
|
208947
210104
|
}
|
|
208948
210105
|
const client2 = await getTimebackClient();
|
|
208949
|
-
const
|
|
208950
|
-
const
|
|
208951
|
-
|
|
208952
|
-
|
|
208953
|
-
|
|
208954
|
-
|
|
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", {
|
|
208955
210123
|
gameId,
|
|
208956
|
-
|
|
208957
|
-
status:
|
|
210124
|
+
courseCount: integrations.length,
|
|
210125
|
+
status: overallSuccess ? "success" : "error"
|
|
208958
210126
|
});
|
|
208959
210127
|
return {
|
|
208960
|
-
status:
|
|
208961
|
-
|
|
208962
|
-
resources,
|
|
208963
|
-
...errors3.length > 0 && { errors: errors3 }
|
|
210128
|
+
status: overallSuccess ? "success" : "error",
|
|
210129
|
+
results
|
|
208964
210130
|
};
|
|
208965
210131
|
}
|
|
208966
210132
|
async function getTimebackConfig(ctx) {
|
|
@@ -208973,20 +210139,13 @@ async function getTimebackConfig(ctx) {
|
|
|
208973
210139
|
throw ApiError.badRequest("Missing gameId parameter");
|
|
208974
210140
|
}
|
|
208975
210141
|
log2.debug("[API] Getting TimeBack config", { userId: user.id, gameId });
|
|
210142
|
+
await verifyGameAccessById(gameId, user);
|
|
208976
210143
|
const db = getDatabase();
|
|
208977
|
-
const game = await db.query.games.findFirst({
|
|
208978
|
-
where: eq(games.id, gameId)
|
|
208979
|
-
});
|
|
208980
|
-
if (!game) {
|
|
208981
|
-
throw ApiError.notFound("Game not found");
|
|
208982
|
-
}
|
|
208983
|
-
if (user.role !== "admin" && game.developerId !== user.id) {
|
|
208984
|
-
throw ApiError.forbidden("You do not own this game");
|
|
208985
|
-
}
|
|
208986
210144
|
const integration = await db.query.gameTimebackIntegrations.findFirst({
|
|
208987
210145
|
where: eq(gameTimebackIntegrations.gameId, gameId)
|
|
208988
210146
|
});
|
|
208989
210147
|
if (!integration) {
|
|
210148
|
+
log2.error("[API] No TimeBack integration found", { gameId });
|
|
208990
210149
|
throw ApiError.notFound("No TimeBack integration found for this game");
|
|
208991
210150
|
}
|
|
208992
210151
|
const client2 = await getTimebackClient();
|
|
@@ -209001,34 +210160,40 @@ async function deleteTimebackIntegration(ctx) {
|
|
|
209001
210160
|
if (!gameId) {
|
|
209002
210161
|
throw ApiError.badRequest("Missing gameId parameter");
|
|
209003
210162
|
}
|
|
209004
|
-
log2.debug("[API] Deleting TimeBack
|
|
210163
|
+
log2.debug("[API] Deleting TimeBack integrations", { userId: user.id, gameId });
|
|
210164
|
+
await verifyGameAccessById(gameId, user);
|
|
209005
210165
|
const db = getDatabase();
|
|
209006
|
-
const
|
|
209007
|
-
where: eq(games.id, gameId)
|
|
209008
|
-
});
|
|
209009
|
-
if (!game) {
|
|
209010
|
-
throw ApiError.notFound("Game not found");
|
|
209011
|
-
}
|
|
209012
|
-
if (user.role !== "admin" && game.developerId !== user.id) {
|
|
209013
|
-
throw ApiError.forbidden("You do not own this game");
|
|
209014
|
-
}
|
|
209015
|
-
const integration = await db.query.gameTimebackIntegrations.findFirst({
|
|
210166
|
+
const integrations = await db.query.gameTimebackIntegrations.findMany({
|
|
209016
210167
|
where: eq(gameTimebackIntegrations.gameId, gameId)
|
|
209017
210168
|
});
|
|
209018
|
-
if (
|
|
210169
|
+
if (integrations.length === 0) {
|
|
210170
|
+
log2.error("[API] No TimeBack integrations found", { gameId });
|
|
209019
210171
|
throw ApiError.notFound("No TimeBack integration found for this game");
|
|
209020
210172
|
}
|
|
209021
210173
|
const client2 = await getTimebackClient();
|
|
209022
|
-
|
|
209023
|
-
|
|
209024
|
-
|
|
209025
|
-
|
|
209026
|
-
|
|
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
|
+
}
|
|
209027
210192
|
}
|
|
209028
|
-
await db.delete(gameTimebackIntegrations).where(eq(gameTimebackIntegrations.
|
|
209029
|
-
log2.info("[API] Deleted TimeBack
|
|
210193
|
+
await db.delete(gameTimebackIntegrations).where(eq(gameTimebackIntegrations.gameId, gameId));
|
|
210194
|
+
log2.info("[API] Deleted TimeBack integrations", {
|
|
209030
210195
|
gameId,
|
|
209031
|
-
|
|
210196
|
+
coursesDeleted: integrations.length
|
|
209032
210197
|
});
|
|
209033
210198
|
}
|
|
209034
210199
|
init_src();
|
|
@@ -209159,6 +210324,41 @@ async function getTimeBackXpHistory(ctx) {
|
|
|
209159
210324
|
throw ApiError.internal("Failed to get TimeBack XP history", error2);
|
|
209160
210325
|
}
|
|
209161
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
|
+
}
|
|
209162
210362
|
var timebackRouter = new Hono2;
|
|
209163
210363
|
timebackRouter.post("/populate-student", async (c3) => {
|
|
209164
210364
|
return c3.json({
|
|
@@ -209349,6 +210549,25 @@ timebackRouter.post("/end-activity", async (c3) => {
|
|
|
209349
210549
|
return c3.json(createUnknownErrorResponse(error2), 500);
|
|
209350
210550
|
}
|
|
209351
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
|
+
});
|
|
209352
210571
|
init_src();
|
|
209353
210572
|
async function createLtiSession(userId) {
|
|
209354
210573
|
const db = getDatabase();
|
|
@@ -210319,7 +211538,8 @@ async function configurePlatformMode(server, viteConfig, options) {
|
|
|
210319
211538
|
const backend = await setupCliDevServer({
|
|
210320
211539
|
preferredPort: options.preferredBackendPort,
|
|
210321
211540
|
viteConfig,
|
|
210322
|
-
platformUrl: sandbox.baseUrl
|
|
211541
|
+
platformUrl: sandbox.baseUrl,
|
|
211542
|
+
configPath: options.configPath
|
|
210323
211543
|
});
|
|
210324
211544
|
serverState.backend = backend;
|
|
210325
211545
|
if (sandbox.project) {
|
|
@@ -210342,11 +211562,12 @@ async function configurePlatformMode(server, viteConfig, options) {
|
|
|
210342
211562
|
|
|
210343
211563
|
// src/server/standalone-mode.ts
|
|
210344
211564
|
var import_picocolors6 = __toESM(require_picocolors(), 1);
|
|
210345
|
-
async function configureStandaloneMode(server, viteConfig,
|
|
211565
|
+
async function configureStandaloneMode(server, viteConfig, options) {
|
|
210346
211566
|
const backend = await setupCliDevServer({
|
|
210347
|
-
preferredPort,
|
|
211567
|
+
preferredPort: options.preferredPort,
|
|
210348
211568
|
viteConfig,
|
|
210349
|
-
platformUrl: undefined
|
|
211569
|
+
platformUrl: undefined,
|
|
211570
|
+
configPath: options.configPath
|
|
210350
211571
|
});
|
|
210351
211572
|
if (!backend) {
|
|
210352
211573
|
viteConfig.logger.error("Failed to start backend server");
|
|
@@ -210366,25 +211587,85 @@ async function configureStandaloneMode(server, viteConfig, preferredPort) {
|
|
|
210366
211587
|
}
|
|
210367
211588
|
|
|
210368
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
|
+
}
|
|
210369
211600
|
async function toggleMode(options) {
|
|
210370
211601
|
const currentMode = getCurrentMode();
|
|
210371
211602
|
const newMode = currentMode === "platform" ? "standalone" : "platform";
|
|
210372
211603
|
const viteServer = getViteServerRef();
|
|
210373
211604
|
if (!viteServer) {
|
|
210374
|
-
options.viteConfig.logger.error("[
|
|
211605
|
+
options.viteConfig.logger.error(`${formatTimestamp2()} ${red(bold3("[playcademy]"))} ${red("Cannot toggle mode: no Vite server reference")}`);
|
|
210375
211606
|
return;
|
|
210376
211607
|
}
|
|
210377
211608
|
await cleanupServers();
|
|
210378
211609
|
await new Promise((resolve2) => setTimeout(resolve2, 100));
|
|
210379
211610
|
setCurrentMode(newMode);
|
|
210380
211611
|
if (newMode === "standalone") {
|
|
210381
|
-
await configureStandaloneMode(viteServer, options.viteConfig,
|
|
211612
|
+
await configureStandaloneMode(viteServer, options.viteConfig, {
|
|
211613
|
+
preferredPort: options.platformModeOptions.preferredBackendPort,
|
|
211614
|
+
configPath: options.platformModeOptions.configPath
|
|
211615
|
+
});
|
|
210382
211616
|
} else {
|
|
210383
211617
|
await configurePlatformMode(viteServer, options.viteConfig, options.platformModeOptions);
|
|
210384
211618
|
}
|
|
210385
|
-
options.viteConfig.logger.info(`
|
|
210386
|
-
|
|
210387
|
-
|
|
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")}`);
|
|
210388
211669
|
}
|
|
210389
211670
|
|
|
210390
211671
|
// src/hooks/configure-server.ts
|
|
@@ -210412,10 +211693,14 @@ async function configureServerHook(server, context) {
|
|
|
210412
211693
|
realtimeEnabled: context.options.realtimeEnabled,
|
|
210413
211694
|
realtimePort: context.options.realtimePort,
|
|
210414
211695
|
showBadge: context.options.showBadge,
|
|
210415
|
-
preferredBackendPort: preferredPort
|
|
211696
|
+
preferredBackendPort: preferredPort,
|
|
211697
|
+
configPath: context.options.configPath
|
|
210416
211698
|
};
|
|
210417
211699
|
if (context.options.mode === "standalone") {
|
|
210418
|
-
await configureStandaloneMode(server, context.viteConfig,
|
|
211700
|
+
await configureStandaloneMode(server, context.viteConfig, {
|
|
211701
|
+
preferredPort,
|
|
211702
|
+
configPath: context.options.configPath
|
|
211703
|
+
});
|
|
210419
211704
|
} else {
|
|
210420
211705
|
await configurePlatformMode(server, context.viteConfig, platformModeOptions);
|
|
210421
211706
|
}
|
|
@@ -210435,6 +211720,16 @@ async function configureServerHook(server, context) {
|
|
|
210435
211720
|
platformModeOptions
|
|
210436
211721
|
});
|
|
210437
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
|
+
}
|
|
210438
211733
|
}
|
|
210439
211734
|
]
|
|
210440
211735
|
});
|
|
@@ -210470,6 +211765,7 @@ function resolveOptions(options) {
|
|
|
210470
211765
|
const shellOptions = options.shell ?? {};
|
|
210471
211766
|
const realtimeOptions = sandboxOptions.realtime ?? {};
|
|
210472
211767
|
return {
|
|
211768
|
+
configPath: options.configPath,
|
|
210473
211769
|
mode: options.mode ?? "platform",
|
|
210474
211770
|
autoZip: exportOptions.autoZip ?? true,
|
|
210475
211771
|
sandboxUrl: sandboxOptions.url ?? `http://localhost:${DEFAULT_PORTS4.SANDBOX}`,
|