@pie-players/pie-players-shared 0.3.48 → 0.3.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/dist/pie/initialization.js +2 -1
- package/dist/pie/initialization.js.map +1 -1
- package/dist/pie/updates.js +9 -7
- package/dist/pie/updates.js.map +1 -1
- package/dist/security/index.d.ts +1 -0
- package/dist/security/index.js +1 -0
- package/dist/security/index.js.map +1 -1
- package/dist/security/wrap-model-rich-content.d.ts +1 -0
- package/dist/security/wrap-model-rich-content.js +41 -0
- package/dist/security/wrap-model-rich-content.js.map +1 -0
- package/dist/types/index.d.ts +15 -3
- package/dist/types/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export * from "./security/index.js";
|
|
|
6
6
|
export * from "./loaders/index.js";
|
|
7
7
|
export * from "./object/index.js";
|
|
8
8
|
export * from "./pie/index.js";
|
|
9
|
-
export type { AssessmentEntity, AssessmentItemRef, AssessmentSection, ConfigEntity, Env, ItemConfig, ItemEntity, OutcomeResponse, PassageEntity, PieController, PieModel, QuestionEntity, RubricBlock, TestPart, } from "./types/index.js";
|
|
9
|
+
export type { AssessmentEntity, AssessmentItemRef, AssessmentSection, AdvancedItemConfig, ConfigEntity, ConfigResource, Env, ItemConfig, ItemEntity, ItemSession, OutcomeResponse, PassageEntity, PieController, PieContent, PieDefaultModel, PieItemElement, PieModel, QuestionEntity, RubricBlock, TestPart, } from "./types/index.js";
|
|
10
10
|
export { editorPostFix } from "./types/index.js";
|
|
11
11
|
export * from "./ui/focus-trap.js";
|
|
12
12
|
export * from "./ui/first-focusable.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,0CAA0C;AAC1C,cAAc,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,0CAA0C;AAC1C,cAAc,gBAAgB,CAAC;AAuB/B,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,iCAAiC,CAAC;AAChD,cAAc,sBAAsB,CAAC","sourcesContent":["export * from \"./config/profile.js\";\nexport * from \"./instrumentation/index.js\";\nexport * from \"./loader-config.js\";\nexport * from \"./player-strategy.js\";\nexport * from \"./security/index.js\";\nexport * from \"./loaders/index.js\";\nexport * from \"./object/index.js\";\n// Barrel export for PIE runtime utilities\nexport * from \"./pie/index.js\";\nexport type {\n\tAssessmentEntity,\n\tAssessmentItemRef,\n\tAssessmentSection,\n\tAdvancedItemConfig,\n\tConfigEntity,\n\tConfigResource,\n\tEnv,\n\tItemConfig,\n\tItemEntity,\n\tItemSession,\n\tOutcomeResponse,\n\tPassageEntity,\n\tPieController,\n\tPieContent,\n\tPieDefaultModel,\n\tPieItemElement,\n\tPieModel,\n\tQuestionEntity,\n\tRubricBlock,\n\tTestPart,\n} from \"./types/index.js\";\nexport { editorPostFix } from \"./types/index.js\";\nexport * from \"./ui/focus-trap.js\";\nexport * from \"./ui/first-focusable.js\";\nexport * from \"./ui/debug-panel-persistence.js\";\nexport * from \"./ui/safe-storage.js\";\n"]}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { BUILDER_BUNDLE_URL } from "../config/profile.js";
|
|
8
8
|
import { mergeObjectsIgnoringNullUndefined } from "../object/index.js";
|
|
9
|
+
import { wrapModelRichContent } from "../security/wrap-model-rich-content.js";
|
|
9
10
|
import { editorPostFix } from "../types/index.js";
|
|
10
11
|
import { createPieLogger, isGlobalDebugEnabled } from "./logger.js";
|
|
11
12
|
import { initializeMathRendering } from "./math-rendering.js";
|
|
@@ -68,7 +69,7 @@ const initializePieElement = (element, options) => {
|
|
|
68
69
|
role: env.role,
|
|
69
70
|
});
|
|
70
71
|
// Set model directly - server already processed it
|
|
71
|
-
element.model = model;
|
|
72
|
+
element.model = wrapModelRichContent(model);
|
|
72
73
|
}
|
|
73
74
|
else {
|
|
74
75
|
// Controller available - run client-side processing (client-player.js bundle)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initialization.js","sourceRoot":"","sources":["../../src/pie/initialization.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * PIE Initialization Module\n *\n * Bundle loading and element initialization logic.\n * This is the core of the PIE player system.\n */\n\nimport { BUILDER_BUNDLE_URL } from \"../config/profile.js\";\nimport { mergeObjectsIgnoringNullUndefined } from \"../object/index.js\";\nimport type { ConfigEntity, Env, PieModel } from \"../types/index.js\";\nimport { editorPostFix } from \"../types/index.js\";\nimport { createPieLogger, isGlobalDebugEnabled } from \"./logger.js\";\nimport { initializeMathRendering } from \"./math-rendering.js\";\nimport { pieRegistry } from \"./registry.js\";\nimport { findPieController } from \"./scoring.js\";\nimport { defineCustomElementSafely } from \"./custom-element-define.js\";\nimport { validateCustomElementTag } from \"./tag-names.js\";\nimport type {\n\tEventListeners,\n\tLoadPieElementsOptions,\n\tPieElement,\n\tPieRegistry,\n} from \"./types.js\";\nimport {\n\tBundleType,\n\tisCustomElementConstructor,\n\tisPieAvailable,\n\tStatus,\n} from \"./types.js\";\nimport { updatePieElement } from \"./updates.js\";\nimport {\n\tfindOrAddSession,\n\tgetPackageWithoutVersion,\n\tgetPieElementBundlesUrl,\n} from \"./utils.js\";\n\n// Create module-level logger (respects global debug flag - pass function for dynamic checking)\nconst logger = createPieLogger(\"pie-initialization\", () =>\n\tisGlobalDebugEnabled(),\n);\n\n// Default options for loading PIE elements\nconst defaultOptions: LoadPieElementsOptions = {\n\tbuildServiceBase: BUILDER_BUNDLE_URL,\n\tbundleType: BundleType.player, // Default to player.js (no controllers, server-processed models)\n\tenv: { mode: \"gather\", role: \"student\" },\n};\n\n// Add this to your window types\ndeclare global {\n\tinterface Window {\n\t\t_pieElementObserver?: MutationObserver;\n\t\t_pieCurrentContext?: {\n\t\t\tconfig: ConfigEntity;\n\t\t\tsession: any[];\n\t\t\tenv?: Env;\n\t\t\tcontainer?: Element | Document;\n\t\t};\n\t}\n}\n\n/**\n * Helper function to initialize a PIE element\n */\nconst initializePieElement = (\n\telement: PieElement,\n\toptions: {\n\t\tconfig: ConfigEntity;\n\t\tsession: any[];\n\t\tenv?: Env;\n\t\teventListeners?: EventListeners;\n\t},\n): void => {\n\tconst { config, session, env, eventListeners } = options;\n\tif ((element as any).__pieInitialized) {\n\t\treturn;\n\t}\n\tconst tagName = element.tagName.toLowerCase();\n\n\tlogger.debug(`[initializePieElement] Initializing ${tagName}#${element.id}`);\n\n\t// Find model for this element\n\tlet model = config?.models?.find((m) => m.id === element.id) as PieModel;\n\tif (!model) {\n\t\t// Only warn if this element is from a client-player.js bundle (where models are expected)\n\t\t// player.js bundles use server-processed models, so missing models are expected there\n\t\tconst registry = pieRegistry();\n\t\tconst registryEntry = registry[tagName];\n\n\t\tif (registryEntry && registryEntry.bundleType === BundleType.clientPlayer) {\n\t\t\tlogger.warn(\n\t\t\t\t`[initializePieElement] Model not found for PIE element ${tagName}#${element.id} (client-player.js bundle)`,\n\t\t\t);\n\t\t}\n\t\treturn;\n\t}\n\n\t// Set session (with element property for updateSession callback)\n\tconst elementSession = findOrAddSession(session, model.id, model.element);\n\telement.session = elementSession;\n\t(element as any).__pieInitialized = true;\n\tlogger.debug(\n\t\t`[initializePieElement] Session set for ${tagName}#${element.id}:`,\n\t\telementSession,\n\t);\n\n\t// Set model - use controller if available (client-player.js), or use server-processed model (player.js)\n\tconst controller = findPieController(tagName);\n\n\tif (!env) {\n\t\tlogger.error(\n\t\t\t`[initializePieElement] ❌ FATAL: No env provided for ${tagName}`,\n\t\t);\n\t\tthrow new Error(\n\t\t\t`No env provided for ${tagName}. PIE elements require an env object with mode and role.`,\n\t\t);\n\t}\n\n\tif (!controller) {\n\t\t// No controller available - using server-processed model (player.js bundle)\n\t\tlogger.debug(\n\t\t\t`[initializePieElement] ℹ️ No controller for ${tagName}, using server-processed model`,\n\t\t);\n\t\tlogger.debug(`[initializePieElement] Model already processed by server:`, {\n\t\t\tid: model.id,\n\t\t\telement: model.element,\n\t\t\thasCorrectResponse: \"correctResponse\" in model,\n\t\t\tmode: env.mode,\n\t\t\trole: env.role,\n\t\t});\n\n\t\t// Set model directly - server already processed it\n\t\telement.model = model;\n\t} else {\n\t\t// Controller available - run client-side processing (client-player.js bundle)\n\t\t// Note: updatePieElementWithRef handles controller invocation\n\t\tlogger.debug(\n\t\t\t`[initializePieElement] Controller found for ${tagName}, will invoke model() function`,\n\t\t);\n\t}\n\n\t// Add event listeners\n\tif (eventListeners) {\n\t\tObject.entries(eventListeners).forEach(([evt, fn]) => {\n\t\t\telement.addEventListener(evt as any, fn);\n\t\t});\n\t}\n};\n\nconst getEditorElementTagName = (elementTagName: string, pkg: string): string =>\n\tvalidateCustomElementTag(\n\t\telementTagName + editorPostFix,\n\t\t`editor element tag for ${pkg}`,\n\t);\n\nconst updateRegisteredElement = (\n\telementTagName: string,\n\tconfig: ConfigEntity,\n\tsession: any[],\n\toptions: LoadPieElementsOptions,\n\tomitEnv = false,\n): void => {\n\tupdatePieElement(elementTagName, {\n\t\tconfig,\n\t\tsession,\n\t\t...(omitEnv ? {} : { env: options.env }),\n\t\tcontainer: options.container,\n\t\t...(options.eventListeners?.[elementTagName] && {\n\t\t\teventListeners: options.eventListeners[elementTagName],\n\t\t}),\n\t});\n};\n\n/**\n * Shared element registration logic\n * Extracted from initializePiesFromLoadedBundle and loadPieModule to eliminate ~200 lines of duplication\n * Also fixes MutationObserver memory leak by storing latest config/session in window context\n *\n * `elementModule` may be `null`. In that case we cannot register *new*\n * tags (no element constructor source), but we can still update tags\n * that another loader (e.g. the section-player's IIFE adapter) has\n * already registered with `customElements`. This is the common case\n * when `pie-item-player` mounts inside `pie-section-player`: the\n * section player has already pre-warmed the bundle through the deep\n * `ElementLoader` primitive, so the `window.pie.default` bundle-global\n * path is not required for those tags.\n */\nconst registerPieElementsFromBundle = (\n\telementModule: any | null,\n\tconfig: ConfigEntity,\n\tsession: any[],\n\tregistry: PieRegistry,\n\toptions: LoadPieElementsOptions,\n): Promise<void>[] => {\n\tconst promises: Promise<void>[] = [];\n\tconst isNodeWithinContainer = (\n\t\tnode: Node,\n\t\tcontainer?: Element | Document,\n\t): boolean => {\n\t\tif (!container || container === document) return true;\n\t\treturn node instanceof Node && container.contains(node);\n\t};\n\n\tif (elementModule) {\n\t\tlogger.debug(\n\t\t\t\"[registerPieElementsFromBundle] Available packages in bundle:\",\n\t\t\tObject.keys(elementModule),\n\t\t);\n\t} else {\n\t\tlogger.debug(\n\t\t\t\"[registerPieElementsFromBundle] No bundle module supplied; will only update tags already registered with customElements.\",\n\t\t);\n\t}\n\tlogger.debug(\n\t\t\"[registerPieElementsFromBundle] config.elements:\",\n\t\tconfig.elements,\n\t);\n\n\t// Store latest config/session in window so MutationObserver can access current values\n\tif (typeof window !== \"undefined\") {\n\t\twindow._pieCurrentContext = {\n\t\t\tconfig,\n\t\t\tsession,\n\t\t\tenv: options.env,\n\t\t\tcontainer: options.container,\n\t\t};\n\t}\n\n\tObject.entries(config.elements).forEach(([elName, pkg]) => {\n\t\tconst elementTagName = validateCustomElementTag(\n\t\t\telName,\n\t\t\t`element tag in config.elements for ${String(pkg)}`,\n\t\t);\n\t\tlogger.debug(\n\t\t\t`[registerPieElementsFromBundle] Processing element: ${elementTagName} -> ${pkg}`,\n\t\t);\n\n\t\t// Fast path — the tag is already registered with customElements\n\t\t// (typically by the host's pre-warm pipeline). We can update its\n\t\t// session/model bindings without needing the bundle module at all.\n\t\t// This branch is also the one that runs when `elementModule` is\n\t\t// `null` because `window.pie` was missing.\n\t\tif (customElements.get(elementTagName)) {\n\t\t\tupdateRegisteredElement(elementTagName, config, session, options);\n\n\t\t\tif (options.bundleType === BundleType.editor) {\n\t\t\t\tconst editorElName = getEditorElementTagName(\n\t\t\t\t\telementTagName,\n\t\t\t\t\tString(pkg),\n\t\t\t\t);\n\t\t\t\tupdateRegisteredElement(editorElName, config, session, options, true);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// From here on we are in the \"register a new tag\" branch, which\n\t\t// requires a bundle module to read the element constructor from.\n\t\tif (!elementModule) {\n\t\t\t// A missing bundle module + an unregistered tag is *not*\n\t\t\t// always an error: in the section-player composition the\n\t\t\t// host's own `ElementLoader` may register this tag\n\t\t\t// out-of-band moments later, in which case `updatePieElement`\n\t\t\t// will pick it up on the next reactive pass via the\n\t\t\t// MutationObserver / `whenDefined` paths. Log at warn so the\n\t\t\t// transient miss is still visible during diagnostics without\n\t\t\t// printing a red stack trace for a routine timing condition.\n\t\t\tlogger.warn(\n\t\t\t\t`[registerPieElementsFromBundle] Skipping \"${elementTagName}\" — no bundle module available and the tag is not yet registered. Will bind on next update if the host's loader registers it.`,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tconst pkgStripped = getPackageWithoutVersion(pkg as string);\n\t\tlogger.debug(\n\t\t\t`[registerPieElementsFromBundle] Package without version: \"${pkgStripped}\"`,\n\t\t);\n\n\t\tconst elementData = elementModule[pkgStripped];\n\t\tlogger.debug(\n\t\t\t`[registerPieElementsFromBundle] elementData result:`,\n\t\t\telementData ? \"FOUND\" : \"UNDEFINED\",\n\t\t);\n\n\t\tif (!elementData) {\n\t\t\tlogger.error(\n\t\t\t\t`[registerPieElementsFromBundle] ❌ Package \"${pkgStripped}\" not found in bundle!`,\n\t\t\t);\n\t\t\tlogger.error(\n\t\t\t\t`[registerPieElementsFromBundle] Lookup key: \"${pkgStripped}\"`,\n\t\t\t);\n\t\t\tlogger.error(\n\t\t\t\t`[registerPieElementsFromBundle] Available packages:`,\n\t\t\t\tObject.keys(elementModule),\n\t\t\t);\n\t\t\tthrow new Error(\n\t\t\t\t`pie ${pkgStripped} not found in ${Object.keys(elementModule)}`,\n\t\t\t);\n\t\t}\n\n\t\tlogger.debug(\n\t\t\t`[registerPieElementsFromBundle] elementData for ${pkgStripped}:`,\n\t\t\t{\n\t\t\t\thasController: !!elementData.controller,\n\t\t\t\thasElement: !!elementData.Element,\n\t\t\t\thasConfig: !!elementData.config,\n\t\t\t\tcontrollerKeys: elementData.controller\n\t\t\t\t\t? Object.keys(elementData.controller)\n\t\t\t\t\t: [],\n\t\t\t\tbundleType: options.bundleType,\n\t\t\t},\n\t\t);\n\n\t\t// Validate controller presence based on bundle type\n\t\tif (!elementData.controller) {\n\t\t\tif (options.bundleType === BundleType.clientPlayer) {\n\t\t\t\tlogger.error(\n\t\t\t\t\t`[registerPieElementsFromBundle] ❌ CRITICAL: No controller found for ${pkgStripped}!`,\n\t\t\t\t);\n\t\t\t\tlogger.error(\n\t\t\t\t\t`[registerPieElementsFromBundle] Bundle type: ${options.bundleType} (controllers required)`,\n\t\t\t\t);\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`No controller found for ${pkgStripped}. client-player.js bundles MUST include controllers!`,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tlogger.debug(\n\t\t\t\t\t`[registerPieElementsFromBundle] ℹ️ No controller found for ${pkgStripped} - using server-processed models (player.js bundle)`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t{\n\t\t\t// Register the element in our registry\n\t\t\tlogger.debug(\n\t\t\t\t`[registerPieElementsFromBundle] Registering ${elName} in registry${\n\t\t\t\t\telementData.controller\n\t\t\t\t\t\t? \" with controller\"\n\t\t\t\t\t\t: \" (no controller - server-processed models)\"\n\t\t\t\t}`,\n\t\t\t);\n\t\t\tregistry[elementTagName] = {\n\t\t\t\tpackage: pkg as string,\n\t\t\t\tstatus: Status.loading,\n\t\t\t\ttagName: elementTagName,\n\t\t\t\tcontroller: elementData.controller || null,\n\t\t\t\tconfig: elementData.config,\n\t\t\t\tbundleType: options.bundleType,\n\t\t\t};\n\n\t\t\tif (isCustomElementConstructor(elementData.Element)) {\n\t\t\t\tdefineCustomElementSafely(\n\t\t\t\t\telementTagName,\n\t\t\t\t\telementData.Element,\n\t\t\t\t\t`element tag in config.elements for ${String(pkg)}`,\n\t\t\t\t);\n\n\t\t\t\t// Initialize existing elements\n\t\t\t\tconst searchRoot = options.container || document;\n\t\t\t\tconst elements = searchRoot.querySelectorAll(elementTagName);\n\t\t\t\tlogger.debug(\n\t\t\t\t\t`[registerPieElementsFromBundle] Found ${elements.length} elements for tag '${elementTagName}'`,\n\t\t\t\t);\n\n\t\t\t\telements.forEach((el) => {\n\t\t\t\t\tinitializePieElement(el as PieElement, {\n\t\t\t\t\t\tconfig,\n\t\t\t\t\t\tsession,\n\t\t\t\t\t\tenv: options.env,\n\t\t\t\t\t\teventListeners: options.eventListeners?.[elementTagName],\n\t\t\t\t\t});\n\t\t\t\t});\n\n\t\t\t\t// Update registry status\n\t\t\t\tregistry[elementTagName] = {\n\t\t\t\t\t...registry[elementTagName],\n\t\t\t\t\tstatus: Status.loaded,\n\t\t\t\t};\n\n\t\t\t\tpromises.push(\n\t\t\t\t\tcustomElements.whenDefined(elementTagName).then(() => {\n\t\t\t\t\t\tlogger.debug(\n\t\t\t\t\t\t\t\"[registerPieElementsFromBundle] defined custom PIE element: %s\",\n\t\t\t\t\t\t\telementTagName,\n\t\t\t\t\t\t);\n\t\t\t\t\t}),\n\t\t\t\t);\n\n\t\t\t\t// Setup MutationObserver that uses current context (only once)\n\t\t\t\tif (!window._pieElementObserver) {\n\t\t\t\t\twindow._pieElementObserver = new MutationObserver((mutations) => {\n\t\t\t\t\t\t// Use current context from window instead of stale closure\n\t\t\t\t\t\tconst context = window._pieCurrentContext;\n\t\t\t\t\t\tif (!context) {\n\t\t\t\t\t\t\tlogger.warn(\"[MutationObserver] No current context available\");\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tmutations.forEach((mutation) => {\n\t\t\t\t\t\t\tif (mutation.type === \"childList\") {\n\t\t\t\t\t\t\t\tmutation.addedNodes.forEach((node) => {\n\t\t\t\t\t\t\t\t\tif (node.nodeType === Node.ELEMENT_NODE) {\n\t\t\t\t\t\t\t\t\t\tif (!isNodeWithinContainer(node, context.container)) {\n\t\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tconst tagName = (node as Element).tagName.toLowerCase();\n\t\t\t\t\t\t\t\t\t\tif (registry[tagName]) {\n\t\t\t\t\t\t\t\t\t\t\tinitializePieElement(node as PieElement, {\n\t\t\t\t\t\t\t\t\t\t\t\tconfig: context.config,\n\t\t\t\t\t\t\t\t\t\t\t\tsession: context.session,\n\t\t\t\t\t\t\t\t\t\t\t\tenv: context.env,\n\t\t\t\t\t\t\t\t\t\t\t\teventListeners: options.eventListeners?.[tagName],\n\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t// Check children of added nodes\n\t\t\t\t\t\t\t\t\t\t(node as Element)\n\t\t\t\t\t\t\t\t\t\t\t.querySelectorAll(\"*\")\n\t\t\t\t\t\t\t\t\t\t\t.forEach((childNode) => {\n\t\t\t\t\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\t\t\t\t\t!isNodeWithinContainer(childNode, context.container)\n\t\t\t\t\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\tconst childTagName = childNode.tagName.toLowerCase();\n\t\t\t\t\t\t\t\t\t\t\t\tif (registry[childTagName]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tinitializePieElement(childNode as PieElement, {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tconfig: context.config,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsession: context.session,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tenv: context.env,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\teventListeners:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\toptions.eventListeners?.[childTagName],\n\t\t\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\n\t\t\t\t\twindow._pieElementObserver.observe(document.body, {\n\t\t\t\t\t\tchildList: true,\n\t\t\t\t\t\tsubtree: true,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Handle editor elements if needed\n\t\t\t\tif (options.bundleType === BundleType.editor) {\n\t\t\t\t\tif (isCustomElementConstructor(elementData.Configure)) {\n\t\t\t\t\t\tconst editorElName = getEditorElementTagName(\n\t\t\t\t\t\t\telementTagName,\n\t\t\t\t\t\t\tString(pkg),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tdefineCustomElementSafely(\n\t\t\t\t\t\t\teditorElName,\n\t\t\t\t\t\t\telementData.Configure,\n\t\t\t\t\t\t\t`editor element tag for ${String(pkg)}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tpromises.push(\n\t\t\t\t\t\t\tcustomElements.whenDefined(editorElName).then(() => {\n\t\t\t\t\t\t\t\tlogger.debug(\n\t\t\t\t\t\t\t\t\t`[registerPieElementsFromBundle] defined custom PIE editor element: ${editorElName}`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlogger.error(\n\t\t\t\t\t\t\t`[registerPieElementsFromBundle] pie.Configure for ${pkgStripped} is not a valid custom element constructor.`,\n\t\t\t\t\t\t\telementData.configure,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlogger.error(\n\t\t\t\t\t`[registerPieElementsFromBundle] pie.Element for ${pkgStripped} is not a valid custom element constructor.`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t});\n\n\treturn promises;\n};\n\n/**\n * Initialize PIE elements from a bundle that may already be loaded.\n *\n * `window.pie` is the IIFE bundle-loading global populated by\n * `loadPieModule` / `loadBundleFromString`. When the host loaded the\n * bundle through the deep `ElementLoader` primitive instead — as\n * `pie-section-player` does — the global is irrelevant: the loader\n * registers tags directly with `customElements`, so this function only\n * needs to bind models/sessions to whatever is already registered.\n *\n * Behavior:\n * - `window.pie` available → register any new tags from the bundle and\n * update bindings for already-registered tags.\n * - `window.pie` missing → fall back to the update-only path. Tags that\n * are already registered get their model/session updated; tags that\n * are not yet registered are logged at `warn` and left alone — the\n * host's loader is expected to register them imminently, after which\n * the existing `MutationObserver` / `updatePieElements` flow binds\n * them on the next reactive pass.\n *\n * The original blanket `window.pie not found; was the bundle inlined\n * correctly?` error has been removed: in the section-player + item-player\n * composition it produced a confusing red stack trace for a routine\n * timing condition that the host already handles. Genuine failures\n * (bundle not loaded by *anyone*) still surface — every unregistered tag\n * gets its own warning, and `updatePieElements` later reports any tag\n * that never resolves.\n */\nexport const initializePiesFromLoadedBundle = (\n\tconfig: ConfigEntity,\n\tsession: any[],\n\topts: LoadPieElementsOptions = {},\n): void => {\n\tconst registry = pieRegistry();\n\tconst options = mergeObjectsIgnoringNullUndefined(defaultOptions, opts);\n\n\tif (isPieAvailable(window)) {\n\t\tlogger.debug(\"[initializePiesFromLoadedBundle] window.pie available\");\n\t\tconst elementModule = window.pie.default;\n\t\tregisterPieElementsFromBundle(\n\t\t\telementModule,\n\t\t\tconfig,\n\t\t\tsession,\n\t\t\tregistry,\n\t\t\toptions,\n\t\t);\n\t\treturn;\n\t}\n\n\tlogger.debug(\n\t\t\"[initializePiesFromLoadedBundle] window.pie not present; using update-only path. Already-registered tags will be bound now; missing tags are expected to be registered by the host's loader and will bind on the next update pass.\",\n\t);\n\tregisterPieElementsFromBundle(null, config, session, registry, options);\n};\n\n/**\n * Load a PIE bundle from a URL and initialize elements\n */\nexport const loadPieModule = async (\n\tconfig: ConfigEntity,\n\tsession: any[],\n\topts: LoadPieElementsOptions = {},\n): Promise<{\n\tsession: any[];\n}> => {\n\tif (!session) {\n\t\tthrow new Error(\"session is required\");\n\t}\n\n\t// Initialize math-rendering module (required by PIE elements)\n\tawait initializeMathRendering();\n\n\tconst registry = pieRegistry();\n\tconst options = mergeObjectsIgnoringNullUndefined(defaultOptions, opts);\n\tconst url = opts.bundleUrl || getPieElementBundlesUrl(config, options);\n\tconst script = document.createElement(\"script\");\n\tscript.src = url;\n\tscript.defer = true;\n\tscript.onerror = () => {\n\t\tthrow new Error(`failed to load script: ${url}`);\n\t};\n\n\tconst loadPromise = new Promise<void>((loadResolve) => {\n\t\tscript.addEventListener(\"load\", () => {\n\t\t\tlogger.debug(\"[loadPieModule] Script loaded from:\", url);\n\t\t\tif (isPieAvailable(window)) {\n\t\t\t\tlogger.debug(\"[loadPieModule] window.pie available\");\n\t\t\t\tconst elementModule = window.pie.default;\n\n\t\t\t\t// Use shared registration logic (returns array of promises)\n\t\t\t\tconst registrationPromises = registerPieElementsFromBundle(\n\t\t\t\t\telementModule,\n\t\t\t\t\tconfig,\n\t\t\t\t\tsession,\n\t\t\t\t\tregistry,\n\t\t\t\t\toptions,\n\t\t\t\t);\n\n\t\t\t\t// Wait for all element definitions to complete\n\t\t\t\tPromise.all(registrationPromises).then(() => loadResolve());\n\t\t\t} else {\n\t\t\t\tlogger.error(\n\t\t\t\t\t\"[loadPieModule] pie var not found; is %s a proper PIE IIFE module?\",\n\t\t\t\t\turl,\n\t\t\t\t);\n\t\t\t\tloadResolve();\n\t\t\t}\n\t\t});\n\t});\n\n\tdocument.head.appendChild(script);\n\tawait loadPromise;\n\treturn { session };\n};\n\n/**\n * Load a PIE bundle from a JavaScript string into window.pie (IIFE bundles only)\n * This only registers elements and controllers - does NOT initialize them.\n * For initialization, use initializePiesFromLoadedBundle after loading.\n */\nexport const loadBundleFromString = async (bundleJs: string): Promise<void> => {\n\tawait initializeMathRendering();\n\tawait withBlobBundleUrl(\n\t\tbundleJs,\n\t\t{ stripSourceMapComment: true },\n\t\tasync (bundleUrl) => {\n\t\t\t// Create a script tag to execute the bundle\n\t\t\tconst script = document.createElement(\"script\");\n\t\t\tscript.src = bundleUrl;\n\t\t\tscript.type = \"text/javascript\"; // IIFE bundles are standard JS\n\n\t\t\t// Wait for script to load\n\t\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\t\tscript.onload = () => resolve();\n\t\t\t\tscript.onerror = () => reject(new Error(\"Failed to load bundle\"));\n\t\t\t\tdocument.head.appendChild(script);\n\t\t\t});\n\n\t\t\tlogger.debug(\"[loadBundleFromString] Bundle loaded into window.pie\");\n\t\t},\n\t);\n};\n\n/**\n * Load a PIE bundle from a JavaScript string and initialize elements\n * Convenience wrapper around loadBundleFromString + loadPieModule\n */\nexport const loadPieModuleFromString = async (\n\tbundleJs: string,\n\tconfig: ConfigEntity,\n\tsession: any[],\n\topts: LoadPieElementsOptions = {},\n): Promise<void> => {\n\tawait withBlobBundleUrl(bundleJs, {}, async (bundleUrl) => {\n\t\t// Use existing loadPieModule with the blob URL\n\t\tawait loadPieModule(config, session, { ...opts, bundleUrl });\n\t});\n};\n\nconst withBlobBundleUrl = async <T>(\n\tbundleJs: string,\n\toptions: { stripSourceMapComment?: boolean },\n\trun: (bundleUrl: string) => Promise<T>,\n): Promise<T> => {\n\tconst source = options.stripSourceMapComment\n\t\t? bundleJs.replace(/\\/\\/# sourceMappingURL=.*$/m, \"\")\n\t\t: bundleJs;\n\tconst blob = new Blob([source], { type: \"application/javascript\" });\n\tconst bundleUrl = URL.createObjectURL(blob);\n\ttry {\n\t\treturn await run(bundleUrl);\n\t} finally {\n\t\tURL.revokeObjectURL(bundleUrl);\n\t}\n};\n"]}
|
|
1
|
+
{"version":3,"file":"initialization.js","sourceRoot":"","sources":["../../src/pie/initialization.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,iCAAiC,EAAE,MAAM,oBAAoB,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAE9E,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAO1D,OAAO,EACN,UAAU,EACV,0BAA0B,EAC1B,cAAc,EACd,MAAM,GACN,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EACN,gBAAgB,EAChB,wBAAwB,EACxB,uBAAuB,GACvB,MAAM,YAAY,CAAC;AAEpB,+FAA+F;AAC/F,MAAM,MAAM,GAAG,eAAe,CAAC,oBAAoB,EAAE,GAAG,EAAE,CACzD,oBAAoB,EAAE,CACtB,CAAC;AAEF,2CAA2C;AAC3C,MAAM,cAAc,GAA2B;IAC9C,gBAAgB,EAAE,kBAAkB;IACpC,UAAU,EAAE,UAAU,CAAC,MAAM,EAAE,iEAAiE;IAChG,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE;CACxC,CAAC;AAeF;;GAEG;AACH,MAAM,oBAAoB,GAAG,CAC5B,OAAmB,EACnB,OAKC,EACM,EAAE;IACT,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC;IACzD,IAAK,OAAe,CAAC,gBAAgB,EAAE,CAAC;QACvC,OAAO;IACR,CAAC;IACD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;IAE9C,MAAM,CAAC,KAAK,CAAC,uCAAuC,OAAO,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;IAE7E,8BAA8B;IAC9B,IAAI,KAAK,GAAG,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,EAAE,CAAa,CAAC;IACzE,IAAI,CAAC,KAAK,EAAE,CAAC;QACZ,0FAA0F;QAC1F,sFAAsF;QACtF,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;QAC/B,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QAExC,IAAI,aAAa,IAAI,aAAa,CAAC,UAAU,KAAK,UAAU,CAAC,YAAY,EAAE,CAAC;YAC3E,MAAM,CAAC,IAAI,CACV,0DAA0D,OAAO,IAAI,OAAO,CAAC,EAAE,4BAA4B,CAC3G,CAAC;QACH,CAAC;QACD,OAAO;IACR,CAAC;IAED,iEAAiE;IACjE,MAAM,cAAc,GAAG,gBAAgB,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAC1E,OAAO,CAAC,OAAO,GAAG,cAAc,CAAC;IAChC,OAAe,CAAC,gBAAgB,GAAG,IAAI,CAAC;IACzC,MAAM,CAAC,KAAK,CACX,0CAA0C,OAAO,IAAI,OAAO,CAAC,EAAE,GAAG,EAClE,cAAc,CACd,CAAC;IAEF,wGAAwG;IACxG,MAAM,UAAU,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAE9C,IAAI,CAAC,GAAG,EAAE,CAAC;QACV,MAAM,CAAC,KAAK,CACX,uDAAuD,OAAO,EAAE,CAChE,CAAC;QACF,MAAM,IAAI,KAAK,CACd,uBAAuB,OAAO,0DAA0D,CACxF,CAAC;IACH,CAAC;IAED,IAAI,CAAC,UAAU,EAAE,CAAC;QACjB,4EAA4E;QAC5E,MAAM,CAAC,KAAK,CACX,+CAA+C,OAAO,gCAAgC,CACtF,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,2DAA2D,EAAE;YACzE,EAAE,EAAE,KAAK,CAAC,EAAE;YACZ,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,kBAAkB,EAAE,iBAAiB,IAAI,KAAK;YAC9C,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,IAAI,EAAE,GAAG,CAAC,IAAI;SACd,CAAC,CAAC;QAEH,mDAAmD;QACnD,OAAO,CAAC,KAAK,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAC7C,CAAC;SAAM,CAAC;QACP,8EAA8E;QAC9E,8DAA8D;QAC9D,MAAM,CAAC,KAAK,CACX,+CAA+C,OAAO,gCAAgC,CACtF,CAAC;IACH,CAAC;IAED,sBAAsB;IACtB,IAAI,cAAc,EAAE,CAAC;QACpB,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE;YACpD,OAAO,CAAC,gBAAgB,CAAC,GAAU,EAAE,EAAE,CAAC,CAAC;QAC1C,CAAC,CAAC,CAAC;IACJ,CAAC;AACF,CAAC,CAAC;AAEF,MAAM,uBAAuB,GAAG,CAAC,cAAsB,EAAE,GAAW,EAAU,EAAE,CAC/E,wBAAwB,CACvB,cAAc,GAAG,aAAa,EAC9B,0BAA0B,GAAG,EAAE,CAC/B,CAAC;AAEH,MAAM,uBAAuB,GAAG,CAC/B,cAAsB,EACtB,MAAoB,EACpB,OAAc,EACd,OAA+B,EAC/B,OAAO,GAAG,KAAK,EACR,EAAE;IACT,gBAAgB,CAAC,cAAc,EAAE;QAChC,MAAM;QACN,OAAO;QACP,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;QACxC,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,GAAG,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,cAAc,CAAC,IAAI;YAC/C,cAAc,EAAE,OAAO,CAAC,cAAc,CAAC,cAAc,CAAC;SACtD,CAAC;KACF,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,MAAM,6BAA6B,GAAG,CACrC,aAAyB,EACzB,MAAoB,EACpB,OAAc,EACd,QAAqB,EACrB,OAA+B,EACb,EAAE;IACpB,MAAM,QAAQ,GAAoB,EAAE,CAAC;IACrC,MAAM,qBAAqB,GAAG,CAC7B,IAAU,EACV,SAA8B,EACpB,EAAE;QACZ,IAAI,CAAC,SAAS,IAAI,SAAS,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QACtD,OAAO,IAAI,YAAY,IAAI,IAAI,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACzD,CAAC,CAAC;IAEF,IAAI,aAAa,EAAE,CAAC;QACnB,MAAM,CAAC,KAAK,CACX,+DAA+D,EAC/D,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAC1B,CAAC;IACH,CAAC;SAAM,CAAC;QACP,MAAM,CAAC,KAAK,CACX,0HAA0H,CAC1H,CAAC;IACH,CAAC;IACD,MAAM,CAAC,KAAK,CACX,kDAAkD,EAClD,MAAM,CAAC,QAAQ,CACf,CAAC;IAEF,sFAAsF;IACtF,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QACnC,MAAM,CAAC,kBAAkB,GAAG;YAC3B,MAAM;YACN,OAAO;YACP,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,SAAS,EAAE,OAAO,CAAC,SAAS;SAC5B,CAAC;IACH,CAAC;IAED,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,EAAE;QACzD,MAAM,cAAc,GAAG,wBAAwB,CAC9C,MAAM,EACN,sCAAsC,MAAM,CAAC,GAAG,CAAC,EAAE,CACnD,CAAC;QACF,MAAM,CAAC,KAAK,CACX,uDAAuD,cAAc,OAAO,GAAG,EAAE,CACjF,CAAC;QAEF,gEAAgE;QAChE,iEAAiE;QACjE,mEAAmE;QACnE,gEAAgE;QAChE,2CAA2C;QAC3C,IAAI,cAAc,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,CAAC;YACxC,uBAAuB,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;YAElE,IAAI,OAAO,CAAC,UAAU,KAAK,UAAU,CAAC,MAAM,EAAE,CAAC;gBAC9C,MAAM,YAAY,GAAG,uBAAuB,CAC3C,cAAc,EACd,MAAM,CAAC,GAAG,CAAC,CACX,CAAC;gBACF,uBAAuB,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;YACvE,CAAC;YACD,OAAO;QACR,CAAC;QAED,gEAAgE;QAChE,iEAAiE;QACjE,IAAI,CAAC,aAAa,EAAE,CAAC;YACpB,yDAAyD;YACzD,yDAAyD;YACzD,mDAAmD;YACnD,8DAA8D;YAC9D,oDAAoD;YACpD,6DAA6D;YAC7D,6DAA6D;YAC7D,6DAA6D;YAC7D,MAAM,CAAC,IAAI,CACV,6CAA6C,cAAc,+HAA+H,CAC1L,CAAC;YACF,OAAO;QACR,CAAC;QAED,MAAM,WAAW,GAAG,wBAAwB,CAAC,GAAa,CAAC,CAAC;QAC5D,MAAM,CAAC,KAAK,CACX,6DAA6D,WAAW,GAAG,CAC3E,CAAC;QAEF,MAAM,WAAW,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;QAC/C,MAAM,CAAC,KAAK,CACX,qDAAqD,EACrD,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CACnC,CAAC;QAEF,IAAI,CAAC,WAAW,EAAE,CAAC;YAClB,MAAM,CAAC,KAAK,CACX,8CAA8C,WAAW,wBAAwB,CACjF,CAAC;YACF,MAAM,CAAC,KAAK,CACX,gDAAgD,WAAW,GAAG,CAC9D,CAAC;YACF,MAAM,CAAC,KAAK,CACX,qDAAqD,EACrD,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAC1B,CAAC;YACF,MAAM,IAAI,KAAK,CACd,OAAO,WAAW,iBAAiB,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAC/D,CAAC;QACH,CAAC;QAED,MAAM,CAAC,KAAK,CACX,mDAAmD,WAAW,GAAG,EACjE;YACC,aAAa,EAAE,CAAC,CAAC,WAAW,CAAC,UAAU;YACvC,UAAU,EAAE,CAAC,CAAC,WAAW,CAAC,OAAO;YACjC,SAAS,EAAE,CAAC,CAAC,WAAW,CAAC,MAAM;YAC/B,cAAc,EAAE,WAAW,CAAC,UAAU;gBACrC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC;gBACrC,CAAC,CAAC,EAAE;YACL,UAAU,EAAE,OAAO,CAAC,UAAU;SAC9B,CACD,CAAC;QAEF,oDAAoD;QACpD,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,CAAC;YAC7B,IAAI,OAAO,CAAC,UAAU,KAAK,UAAU,CAAC,YAAY,EAAE,CAAC;gBACpD,MAAM,CAAC,KAAK,CACX,uEAAuE,WAAW,GAAG,CACrF,CAAC;gBACF,MAAM,CAAC,KAAK,CACX,gDAAgD,OAAO,CAAC,UAAU,yBAAyB,CAC3F,CAAC;gBACF,MAAM,IAAI,KAAK,CACd,2BAA2B,WAAW,sDAAsD,CAC5F,CAAC;YACH,CAAC;iBAAM,CAAC;gBACP,MAAM,CAAC,KAAK,CACX,8DAA8D,WAAW,qDAAqD,CAC9H,CAAC;YACH,CAAC;QACF,CAAC;QAED,CAAC;YACA,uCAAuC;YACvC,MAAM,CAAC,KAAK,CACX,+CAA+C,MAAM,eACpD,WAAW,CAAC,UAAU;gBACrB,CAAC,CAAC,kBAAkB;gBACpB,CAAC,CAAC,4CACJ,EAAE,CACF,CAAC;YACF,QAAQ,CAAC,cAAc,CAAC,GAAG;gBAC1B,OAAO,EAAE,GAAa;gBACtB,MAAM,EAAE,MAAM,CAAC,OAAO;gBACtB,OAAO,EAAE,cAAc;gBACvB,UAAU,EAAE,WAAW,CAAC,UAAU,IAAI,IAAI;gBAC1C,MAAM,EAAE,WAAW,CAAC,MAAM;gBAC1B,UAAU,EAAE,OAAO,CAAC,UAAU;aAC9B,CAAC;YAEF,IAAI,0BAA0B,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;gBACrD,yBAAyB,CACxB,cAAc,EACd,WAAW,CAAC,OAAO,EACnB,sCAAsC,MAAM,CAAC,GAAG,CAAC,EAAE,CACnD,CAAC;gBAEF,+BAA+B;gBAC/B,MAAM,UAAU,GAAG,OAAO,CAAC,SAAS,IAAI,QAAQ,CAAC;gBACjD,MAAM,QAAQ,GAAG,UAAU,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC;gBAC7D,MAAM,CAAC,KAAK,CACX,yCAAyC,QAAQ,CAAC,MAAM,sBAAsB,cAAc,GAAG,CAC/F,CAAC;gBAEF,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE;oBACvB,oBAAoB,CAAC,EAAgB,EAAE;wBACtC,MAAM;wBACN,OAAO;wBACP,GAAG,EAAE,OAAO,CAAC,GAAG;wBAChB,cAAc,EAAE,OAAO,CAAC,cAAc,EAAE,CAAC,cAAc,CAAC;qBACxD,CAAC,CAAC;gBACJ,CAAC,CAAC,CAAC;gBAEH,yBAAyB;gBACzB,QAAQ,CAAC,cAAc,CAAC,GAAG;oBAC1B,GAAG,QAAQ,CAAC,cAAc,CAAC;oBAC3B,MAAM,EAAE,MAAM,CAAC,MAAM;iBACrB,CAAC;gBAEF,QAAQ,CAAC,IAAI,CACZ,cAAc,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;oBACpD,MAAM,CAAC,KAAK,CACX,gEAAgE,EAChE,cAAc,CACd,CAAC;gBACH,CAAC,CAAC,CACF,CAAC;gBAEF,+DAA+D;gBAC/D,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE,CAAC;oBACjC,MAAM,CAAC,mBAAmB,GAAG,IAAI,gBAAgB,CAAC,CAAC,SAAS,EAAE,EAAE;wBAC/D,2DAA2D;wBAC3D,MAAM,OAAO,GAAG,MAAM,CAAC,kBAAkB,CAAC;wBAC1C,IAAI,CAAC,OAAO,EAAE,CAAC;4BACd,MAAM,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;4BAC/D,OAAO;wBACR,CAAC;wBAED,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE;4BAC9B,IAAI,QAAQ,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;gCACnC,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;oCACpC,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,YAAY,EAAE,CAAC;wCACzC,IAAI,CAAC,qBAAqB,CAAC,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;4CACrD,OAAO;wCACR,CAAC;wCACD,MAAM,OAAO,GAAI,IAAgB,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;wCACxD,IAAI,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;4CACvB,oBAAoB,CAAC,IAAkB,EAAE;gDACxC,MAAM,EAAE,OAAO,CAAC,MAAM;gDACtB,OAAO,EAAE,OAAO,CAAC,OAAO;gDACxB,GAAG,EAAE,OAAO,CAAC,GAAG;gDAChB,cAAc,EAAE,OAAO,CAAC,cAAc,EAAE,CAAC,OAAO,CAAC;6CACjD,CAAC,CAAC;wCACJ,CAAC;wCAED,gCAAgC;wCAC/B,IAAgB;6CACf,gBAAgB,CAAC,GAAG,CAAC;6CACrB,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE;4CACtB,IACC,CAAC,qBAAqB,CAAC,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,EACnD,CAAC;gDACF,OAAO;4CACR,CAAC;4CACD,MAAM,YAAY,GAAG,SAAS,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;4CACrD,IAAI,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;gDAC5B,oBAAoB,CAAC,SAAuB,EAAE;oDAC7C,MAAM,EAAE,OAAO,CAAC,MAAM;oDACtB,OAAO,EAAE,OAAO,CAAC,OAAO;oDACxB,GAAG,EAAE,OAAO,CAAC,GAAG;oDAChB,cAAc,EACb,OAAO,CAAC,cAAc,EAAE,CAAC,YAAY,CAAC;iDACvC,CAAC,CAAC;4CACJ,CAAC;wCACF,CAAC,CAAC,CAAC;oCACL,CAAC;gCACF,CAAC,CAAC,CAAC;4BACJ,CAAC;wBACF,CAAC,CAAC,CAAC;oBACJ,CAAC,CAAC,CAAC;oBAEH,MAAM,CAAC,mBAAmB,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE;wBACjD,SAAS,EAAE,IAAI;wBACf,OAAO,EAAE,IAAI;qBACb,CAAC,CAAC;gBACJ,CAAC;gBAED,mCAAmC;gBACnC,IAAI,OAAO,CAAC,UAAU,KAAK,UAAU,CAAC,MAAM,EAAE,CAAC;oBAC9C,IAAI,0BAA0B,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC;wBACvD,MAAM,YAAY,GAAG,uBAAuB,CAC3C,cAAc,EACd,MAAM,CAAC,GAAG,CAAC,CACX,CAAC;wBACF,yBAAyB,CACxB,YAAY,EACZ,WAAW,CAAC,SAAS,EACrB,0BAA0B,MAAM,CAAC,GAAG,CAAC,EAAE,CACvC,CAAC;wBACF,QAAQ,CAAC,IAAI,CACZ,cAAc,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;4BAClD,MAAM,CAAC,KAAK,CACX,sEAAsE,YAAY,EAAE,CACpF,CAAC;wBACH,CAAC,CAAC,CACF,CAAC;oBACH,CAAC;yBAAM,CAAC;wBACP,MAAM,CAAC,KAAK,CACX,qDAAqD,WAAW,6CAA6C,EAC7G,WAAW,CAAC,SAAS,CACrB,CAAC;oBACH,CAAC;gBACF,CAAC;YACF,CAAC;iBAAM,CAAC;gBACP,MAAM,CAAC,KAAK,CACX,mDAAmD,WAAW,6CAA6C,CAC3G,CAAC;YACH,CAAC;QACF,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,OAAO,QAAQ,CAAC;AACjB,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAC7C,MAAoB,EACpB,OAAc,EACd,OAA+B,EAAE,EAC1B,EAAE;IACT,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,OAAO,GAAG,iCAAiC,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;IAExE,IAAI,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5B,MAAM,CAAC,KAAK,CAAC,uDAAuD,CAAC,CAAC;QACtE,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC;QACzC,6BAA6B,CAC5B,aAAa,EACb,MAAM,EACN,OAAO,EACP,QAAQ,EACR,OAAO,CACP,CAAC;QACF,OAAO;IACR,CAAC;IAED,MAAM,CAAC,KAAK,CACX,oOAAoO,CACpO,CAAC;IACF,6BAA6B,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;AACzE,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EACjC,MAAoB,EACpB,OAAc,EACd,OAA+B,EAAE,EAG/B,EAAE;IACJ,IAAI,CAAC,OAAO,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACxC,CAAC;IAED,8DAA8D;IAC9D,MAAM,uBAAuB,EAAE,CAAC;IAEhC,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,OAAO,GAAG,iCAAiC,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;IACxE,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,IAAI,uBAAuB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvE,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IAChD,MAAM,CAAC,GAAG,GAAG,GAAG,CAAC;IACjB,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC;IACpB,MAAM,CAAC,OAAO,GAAG,GAAG,EAAE;QACrB,MAAM,IAAI,KAAK,CAAC,0BAA0B,GAAG,EAAE,CAAC,CAAC;IAClD,CAAC,CAAC;IAEF,MAAM,WAAW,GAAG,IAAI,OAAO,CAAO,CAAC,WAAW,EAAE,EAAE;QACrD,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE;YACpC,MAAM,CAAC,KAAK,CAAC,qCAAqC,EAAE,GAAG,CAAC,CAAC;YACzD,IAAI,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC5B,MAAM,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;gBACrD,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC;gBAEzC,4DAA4D;gBAC5D,MAAM,oBAAoB,GAAG,6BAA6B,CACzD,aAAa,EACb,MAAM,EACN,OAAO,EACP,QAAQ,EACR,OAAO,CACP,CAAC;gBAEF,+CAA+C;gBAC/C,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;YAC7D,CAAC;iBAAM,CAAC;gBACP,MAAM,CAAC,KAAK,CACX,oEAAoE,EACpE,GAAG,CACH,CAAC;gBACF,WAAW,EAAE,CAAC;YACf,CAAC;QACF,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,WAAW,CAAC;IAClB,OAAO,EAAE,OAAO,EAAE,CAAC;AACpB,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,KAAK,EAAE,QAAgB,EAAiB,EAAE;IAC7E,MAAM,uBAAuB,EAAE,CAAC;IAChC,MAAM,iBAAiB,CACtB,QAAQ,EACR,EAAE,qBAAqB,EAAE,IAAI,EAAE,EAC/B,KAAK,EAAE,SAAS,EAAE,EAAE;QACnB,4CAA4C;QAC5C,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAChD,MAAM,CAAC,GAAG,GAAG,SAAS,CAAC;QACvB,MAAM,CAAC,IAAI,GAAG,iBAAiB,CAAC,CAAC,+BAA+B;QAEhE,0BAA0B;QAC1B,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC3C,MAAM,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;YAChC,MAAM,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC,CAAC;YAClE,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,KAAK,CAAC,sDAAsD,CAAC,CAAC;IACtE,CAAC,CACD,CAAC;AACH,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,KAAK,EAC3C,QAAgB,EAChB,MAAoB,EACpB,OAAc,EACd,OAA+B,EAAE,EACjB,EAAE;IAClB,MAAM,iBAAiB,CAAC,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE;QACzD,+CAA+C;QAC/C,MAAM,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,KAAK,EAC9B,QAAgB,EAChB,OAA4C,EAC5C,GAAsC,EACzB,EAAE;IACf,MAAM,MAAM,GAAG,OAAO,CAAC,qBAAqB;QAC3C,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,6BAA6B,EAAE,EAAE,CAAC;QACrD,CAAC,CAAC,QAAQ,CAAC;IACZ,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,wBAAwB,EAAE,CAAC,CAAC;IACpE,MAAM,SAAS,GAAG,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IAC5C,IAAI,CAAC;QACJ,OAAO,MAAM,GAAG,CAAC,SAAS,CAAC,CAAC;IAC7B,CAAC;YAAS,CAAC;QACV,GAAG,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;IAChC,CAAC;AACF,CAAC,CAAC","sourcesContent":["/**\n * PIE Initialization Module\n *\n * Bundle loading and element initialization logic.\n * This is the core of the PIE player system.\n */\n\nimport { BUILDER_BUNDLE_URL } from \"../config/profile.js\";\nimport { mergeObjectsIgnoringNullUndefined } from \"../object/index.js\";\nimport { wrapModelRichContent } from \"../security/wrap-model-rich-content.js\";\nimport type { ConfigEntity, Env, PieModel } from \"../types/index.js\";\nimport { editorPostFix } from \"../types/index.js\";\nimport { createPieLogger, isGlobalDebugEnabled } from \"./logger.js\";\nimport { initializeMathRendering } from \"./math-rendering.js\";\nimport { pieRegistry } from \"./registry.js\";\nimport { findPieController } from \"./scoring.js\";\nimport { defineCustomElementSafely } from \"./custom-element-define.js\";\nimport { validateCustomElementTag } from \"./tag-names.js\";\nimport type {\n\tEventListeners,\n\tLoadPieElementsOptions,\n\tPieElement,\n\tPieRegistry,\n} from \"./types.js\";\nimport {\n\tBundleType,\n\tisCustomElementConstructor,\n\tisPieAvailable,\n\tStatus,\n} from \"./types.js\";\nimport { updatePieElement } from \"./updates.js\";\nimport {\n\tfindOrAddSession,\n\tgetPackageWithoutVersion,\n\tgetPieElementBundlesUrl,\n} from \"./utils.js\";\n\n// Create module-level logger (respects global debug flag - pass function for dynamic checking)\nconst logger = createPieLogger(\"pie-initialization\", () =>\n\tisGlobalDebugEnabled(),\n);\n\n// Default options for loading PIE elements\nconst defaultOptions: LoadPieElementsOptions = {\n\tbuildServiceBase: BUILDER_BUNDLE_URL,\n\tbundleType: BundleType.player, // Default to player.js (no controllers, server-processed models)\n\tenv: { mode: \"gather\", role: \"student\" },\n};\n\n// Add this to your window types\ndeclare global {\n\tinterface Window {\n\t\t_pieElementObserver?: MutationObserver;\n\t\t_pieCurrentContext?: {\n\t\t\tconfig: ConfigEntity;\n\t\t\tsession: any[];\n\t\t\tenv?: Env;\n\t\t\tcontainer?: Element | Document;\n\t\t};\n\t}\n}\n\n/**\n * Helper function to initialize a PIE element\n */\nconst initializePieElement = (\n\telement: PieElement,\n\toptions: {\n\t\tconfig: ConfigEntity;\n\t\tsession: any[];\n\t\tenv?: Env;\n\t\teventListeners?: EventListeners;\n\t},\n): void => {\n\tconst { config, session, env, eventListeners } = options;\n\tif ((element as any).__pieInitialized) {\n\t\treturn;\n\t}\n\tconst tagName = element.tagName.toLowerCase();\n\n\tlogger.debug(`[initializePieElement] Initializing ${tagName}#${element.id}`);\n\n\t// Find model for this element\n\tlet model = config?.models?.find((m) => m.id === element.id) as PieModel;\n\tif (!model) {\n\t\t// Only warn if this element is from a client-player.js bundle (where models are expected)\n\t\t// player.js bundles use server-processed models, so missing models are expected there\n\t\tconst registry = pieRegistry();\n\t\tconst registryEntry = registry[tagName];\n\n\t\tif (registryEntry && registryEntry.bundleType === BundleType.clientPlayer) {\n\t\t\tlogger.warn(\n\t\t\t\t`[initializePieElement] Model not found for PIE element ${tagName}#${element.id} (client-player.js bundle)`,\n\t\t\t);\n\t\t}\n\t\treturn;\n\t}\n\n\t// Set session (with element property for updateSession callback)\n\tconst elementSession = findOrAddSession(session, model.id, model.element);\n\telement.session = elementSession;\n\t(element as any).__pieInitialized = true;\n\tlogger.debug(\n\t\t`[initializePieElement] Session set for ${tagName}#${element.id}:`,\n\t\telementSession,\n\t);\n\n\t// Set model - use controller if available (client-player.js), or use server-processed model (player.js)\n\tconst controller = findPieController(tagName);\n\n\tif (!env) {\n\t\tlogger.error(\n\t\t\t`[initializePieElement] ❌ FATAL: No env provided for ${tagName}`,\n\t\t);\n\t\tthrow new Error(\n\t\t\t`No env provided for ${tagName}. PIE elements require an env object with mode and role.`,\n\t\t);\n\t}\n\n\tif (!controller) {\n\t\t// No controller available - using server-processed model (player.js bundle)\n\t\tlogger.debug(\n\t\t\t`[initializePieElement] ℹ️ No controller for ${tagName}, using server-processed model`,\n\t\t);\n\t\tlogger.debug(`[initializePieElement] Model already processed by server:`, {\n\t\t\tid: model.id,\n\t\t\telement: model.element,\n\t\t\thasCorrectResponse: \"correctResponse\" in model,\n\t\t\tmode: env.mode,\n\t\t\trole: env.role,\n\t\t});\n\n\t\t// Set model directly - server already processed it\n\t\telement.model = wrapModelRichContent(model);\n\t} else {\n\t\t// Controller available - run client-side processing (client-player.js bundle)\n\t\t// Note: updatePieElementWithRef handles controller invocation\n\t\tlogger.debug(\n\t\t\t`[initializePieElement] Controller found for ${tagName}, will invoke model() function`,\n\t\t);\n\t}\n\n\t// Add event listeners\n\tif (eventListeners) {\n\t\tObject.entries(eventListeners).forEach(([evt, fn]) => {\n\t\t\telement.addEventListener(evt as any, fn);\n\t\t});\n\t}\n};\n\nconst getEditorElementTagName = (elementTagName: string, pkg: string): string =>\n\tvalidateCustomElementTag(\n\t\telementTagName + editorPostFix,\n\t\t`editor element tag for ${pkg}`,\n\t);\n\nconst updateRegisteredElement = (\n\telementTagName: string,\n\tconfig: ConfigEntity,\n\tsession: any[],\n\toptions: LoadPieElementsOptions,\n\tomitEnv = false,\n): void => {\n\tupdatePieElement(elementTagName, {\n\t\tconfig,\n\t\tsession,\n\t\t...(omitEnv ? {} : { env: options.env }),\n\t\tcontainer: options.container,\n\t\t...(options.eventListeners?.[elementTagName] && {\n\t\t\teventListeners: options.eventListeners[elementTagName],\n\t\t}),\n\t});\n};\n\n/**\n * Shared element registration logic\n * Extracted from initializePiesFromLoadedBundle and loadPieModule to eliminate ~200 lines of duplication\n * Also fixes MutationObserver memory leak by storing latest config/session in window context\n *\n * `elementModule` may be `null`. In that case we cannot register *new*\n * tags (no element constructor source), but we can still update tags\n * that another loader (e.g. the section-player's IIFE adapter) has\n * already registered with `customElements`. This is the common case\n * when `pie-item-player` mounts inside `pie-section-player`: the\n * section player has already pre-warmed the bundle through the deep\n * `ElementLoader` primitive, so the `window.pie.default` bundle-global\n * path is not required for those tags.\n */\nconst registerPieElementsFromBundle = (\n\telementModule: any | null,\n\tconfig: ConfigEntity,\n\tsession: any[],\n\tregistry: PieRegistry,\n\toptions: LoadPieElementsOptions,\n): Promise<void>[] => {\n\tconst promises: Promise<void>[] = [];\n\tconst isNodeWithinContainer = (\n\t\tnode: Node,\n\t\tcontainer?: Element | Document,\n\t): boolean => {\n\t\tif (!container || container === document) return true;\n\t\treturn node instanceof Node && container.contains(node);\n\t};\n\n\tif (elementModule) {\n\t\tlogger.debug(\n\t\t\t\"[registerPieElementsFromBundle] Available packages in bundle:\",\n\t\t\tObject.keys(elementModule),\n\t\t);\n\t} else {\n\t\tlogger.debug(\n\t\t\t\"[registerPieElementsFromBundle] No bundle module supplied; will only update tags already registered with customElements.\",\n\t\t);\n\t}\n\tlogger.debug(\n\t\t\"[registerPieElementsFromBundle] config.elements:\",\n\t\tconfig.elements,\n\t);\n\n\t// Store latest config/session in window so MutationObserver can access current values\n\tif (typeof window !== \"undefined\") {\n\t\twindow._pieCurrentContext = {\n\t\t\tconfig,\n\t\t\tsession,\n\t\t\tenv: options.env,\n\t\t\tcontainer: options.container,\n\t\t};\n\t}\n\n\tObject.entries(config.elements).forEach(([elName, pkg]) => {\n\t\tconst elementTagName = validateCustomElementTag(\n\t\t\telName,\n\t\t\t`element tag in config.elements for ${String(pkg)}`,\n\t\t);\n\t\tlogger.debug(\n\t\t\t`[registerPieElementsFromBundle] Processing element: ${elementTagName} -> ${pkg}`,\n\t\t);\n\n\t\t// Fast path — the tag is already registered with customElements\n\t\t// (typically by the host's pre-warm pipeline). We can update its\n\t\t// session/model bindings without needing the bundle module at all.\n\t\t// This branch is also the one that runs when `elementModule` is\n\t\t// `null` because `window.pie` was missing.\n\t\tif (customElements.get(elementTagName)) {\n\t\t\tupdateRegisteredElement(elementTagName, config, session, options);\n\n\t\t\tif (options.bundleType === BundleType.editor) {\n\t\t\t\tconst editorElName = getEditorElementTagName(\n\t\t\t\t\telementTagName,\n\t\t\t\t\tString(pkg),\n\t\t\t\t);\n\t\t\t\tupdateRegisteredElement(editorElName, config, session, options, true);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// From here on we are in the \"register a new tag\" branch, which\n\t\t// requires a bundle module to read the element constructor from.\n\t\tif (!elementModule) {\n\t\t\t// A missing bundle module + an unregistered tag is *not*\n\t\t\t// always an error: in the section-player composition the\n\t\t\t// host's own `ElementLoader` may register this tag\n\t\t\t// out-of-band moments later, in which case `updatePieElement`\n\t\t\t// will pick it up on the next reactive pass via the\n\t\t\t// MutationObserver / `whenDefined` paths. Log at warn so the\n\t\t\t// transient miss is still visible during diagnostics without\n\t\t\t// printing a red stack trace for a routine timing condition.\n\t\t\tlogger.warn(\n\t\t\t\t`[registerPieElementsFromBundle] Skipping \"${elementTagName}\" — no bundle module available and the tag is not yet registered. Will bind on next update if the host's loader registers it.`,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tconst pkgStripped = getPackageWithoutVersion(pkg as string);\n\t\tlogger.debug(\n\t\t\t`[registerPieElementsFromBundle] Package without version: \"${pkgStripped}\"`,\n\t\t);\n\n\t\tconst elementData = elementModule[pkgStripped];\n\t\tlogger.debug(\n\t\t\t`[registerPieElementsFromBundle] elementData result:`,\n\t\t\telementData ? \"FOUND\" : \"UNDEFINED\",\n\t\t);\n\n\t\tif (!elementData) {\n\t\t\tlogger.error(\n\t\t\t\t`[registerPieElementsFromBundle] ❌ Package \"${pkgStripped}\" not found in bundle!`,\n\t\t\t);\n\t\t\tlogger.error(\n\t\t\t\t`[registerPieElementsFromBundle] Lookup key: \"${pkgStripped}\"`,\n\t\t\t);\n\t\t\tlogger.error(\n\t\t\t\t`[registerPieElementsFromBundle] Available packages:`,\n\t\t\t\tObject.keys(elementModule),\n\t\t\t);\n\t\t\tthrow new Error(\n\t\t\t\t`pie ${pkgStripped} not found in ${Object.keys(elementModule)}`,\n\t\t\t);\n\t\t}\n\n\t\tlogger.debug(\n\t\t\t`[registerPieElementsFromBundle] elementData for ${pkgStripped}:`,\n\t\t\t{\n\t\t\t\thasController: !!elementData.controller,\n\t\t\t\thasElement: !!elementData.Element,\n\t\t\t\thasConfig: !!elementData.config,\n\t\t\t\tcontrollerKeys: elementData.controller\n\t\t\t\t\t? Object.keys(elementData.controller)\n\t\t\t\t\t: [],\n\t\t\t\tbundleType: options.bundleType,\n\t\t\t},\n\t\t);\n\n\t\t// Validate controller presence based on bundle type\n\t\tif (!elementData.controller) {\n\t\t\tif (options.bundleType === BundleType.clientPlayer) {\n\t\t\t\tlogger.error(\n\t\t\t\t\t`[registerPieElementsFromBundle] ❌ CRITICAL: No controller found for ${pkgStripped}!`,\n\t\t\t\t);\n\t\t\t\tlogger.error(\n\t\t\t\t\t`[registerPieElementsFromBundle] Bundle type: ${options.bundleType} (controllers required)`,\n\t\t\t\t);\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`No controller found for ${pkgStripped}. client-player.js bundles MUST include controllers!`,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tlogger.debug(\n\t\t\t\t\t`[registerPieElementsFromBundle] ℹ️ No controller found for ${pkgStripped} - using server-processed models (player.js bundle)`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t{\n\t\t\t// Register the element in our registry\n\t\t\tlogger.debug(\n\t\t\t\t`[registerPieElementsFromBundle] Registering ${elName} in registry${\n\t\t\t\t\telementData.controller\n\t\t\t\t\t\t? \" with controller\"\n\t\t\t\t\t\t: \" (no controller - server-processed models)\"\n\t\t\t\t}`,\n\t\t\t);\n\t\t\tregistry[elementTagName] = {\n\t\t\t\tpackage: pkg as string,\n\t\t\t\tstatus: Status.loading,\n\t\t\t\ttagName: elementTagName,\n\t\t\t\tcontroller: elementData.controller || null,\n\t\t\t\tconfig: elementData.config,\n\t\t\t\tbundleType: options.bundleType,\n\t\t\t};\n\n\t\t\tif (isCustomElementConstructor(elementData.Element)) {\n\t\t\t\tdefineCustomElementSafely(\n\t\t\t\t\telementTagName,\n\t\t\t\t\telementData.Element,\n\t\t\t\t\t`element tag in config.elements for ${String(pkg)}`,\n\t\t\t\t);\n\n\t\t\t\t// Initialize existing elements\n\t\t\t\tconst searchRoot = options.container || document;\n\t\t\t\tconst elements = searchRoot.querySelectorAll(elementTagName);\n\t\t\t\tlogger.debug(\n\t\t\t\t\t`[registerPieElementsFromBundle] Found ${elements.length} elements for tag '${elementTagName}'`,\n\t\t\t\t);\n\n\t\t\t\telements.forEach((el) => {\n\t\t\t\t\tinitializePieElement(el as PieElement, {\n\t\t\t\t\t\tconfig,\n\t\t\t\t\t\tsession,\n\t\t\t\t\t\tenv: options.env,\n\t\t\t\t\t\teventListeners: options.eventListeners?.[elementTagName],\n\t\t\t\t\t});\n\t\t\t\t});\n\n\t\t\t\t// Update registry status\n\t\t\t\tregistry[elementTagName] = {\n\t\t\t\t\t...registry[elementTagName],\n\t\t\t\t\tstatus: Status.loaded,\n\t\t\t\t};\n\n\t\t\t\tpromises.push(\n\t\t\t\t\tcustomElements.whenDefined(elementTagName).then(() => {\n\t\t\t\t\t\tlogger.debug(\n\t\t\t\t\t\t\t\"[registerPieElementsFromBundle] defined custom PIE element: %s\",\n\t\t\t\t\t\t\telementTagName,\n\t\t\t\t\t\t);\n\t\t\t\t\t}),\n\t\t\t\t);\n\n\t\t\t\t// Setup MutationObserver that uses current context (only once)\n\t\t\t\tif (!window._pieElementObserver) {\n\t\t\t\t\twindow._pieElementObserver = new MutationObserver((mutations) => {\n\t\t\t\t\t\t// Use current context from window instead of stale closure\n\t\t\t\t\t\tconst context = window._pieCurrentContext;\n\t\t\t\t\t\tif (!context) {\n\t\t\t\t\t\t\tlogger.warn(\"[MutationObserver] No current context available\");\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tmutations.forEach((mutation) => {\n\t\t\t\t\t\t\tif (mutation.type === \"childList\") {\n\t\t\t\t\t\t\t\tmutation.addedNodes.forEach((node) => {\n\t\t\t\t\t\t\t\t\tif (node.nodeType === Node.ELEMENT_NODE) {\n\t\t\t\t\t\t\t\t\t\tif (!isNodeWithinContainer(node, context.container)) {\n\t\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tconst tagName = (node as Element).tagName.toLowerCase();\n\t\t\t\t\t\t\t\t\t\tif (registry[tagName]) {\n\t\t\t\t\t\t\t\t\t\t\tinitializePieElement(node as PieElement, {\n\t\t\t\t\t\t\t\t\t\t\t\tconfig: context.config,\n\t\t\t\t\t\t\t\t\t\t\t\tsession: context.session,\n\t\t\t\t\t\t\t\t\t\t\t\tenv: context.env,\n\t\t\t\t\t\t\t\t\t\t\t\teventListeners: options.eventListeners?.[tagName],\n\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t// Check children of added nodes\n\t\t\t\t\t\t\t\t\t\t(node as Element)\n\t\t\t\t\t\t\t\t\t\t\t.querySelectorAll(\"*\")\n\t\t\t\t\t\t\t\t\t\t\t.forEach((childNode) => {\n\t\t\t\t\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\t\t\t\t\t!isNodeWithinContainer(childNode, context.container)\n\t\t\t\t\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\tconst childTagName = childNode.tagName.toLowerCase();\n\t\t\t\t\t\t\t\t\t\t\t\tif (registry[childTagName]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tinitializePieElement(childNode as PieElement, {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tconfig: context.config,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsession: context.session,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tenv: context.env,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\teventListeners:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\toptions.eventListeners?.[childTagName],\n\t\t\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\n\t\t\t\t\twindow._pieElementObserver.observe(document.body, {\n\t\t\t\t\t\tchildList: true,\n\t\t\t\t\t\tsubtree: true,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Handle editor elements if needed\n\t\t\t\tif (options.bundleType === BundleType.editor) {\n\t\t\t\t\tif (isCustomElementConstructor(elementData.Configure)) {\n\t\t\t\t\t\tconst editorElName = getEditorElementTagName(\n\t\t\t\t\t\t\telementTagName,\n\t\t\t\t\t\t\tString(pkg),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tdefineCustomElementSafely(\n\t\t\t\t\t\t\teditorElName,\n\t\t\t\t\t\t\telementData.Configure,\n\t\t\t\t\t\t\t`editor element tag for ${String(pkg)}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tpromises.push(\n\t\t\t\t\t\t\tcustomElements.whenDefined(editorElName).then(() => {\n\t\t\t\t\t\t\t\tlogger.debug(\n\t\t\t\t\t\t\t\t\t`[registerPieElementsFromBundle] defined custom PIE editor element: ${editorElName}`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlogger.error(\n\t\t\t\t\t\t\t`[registerPieElementsFromBundle] pie.Configure for ${pkgStripped} is not a valid custom element constructor.`,\n\t\t\t\t\t\t\telementData.configure,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlogger.error(\n\t\t\t\t\t`[registerPieElementsFromBundle] pie.Element for ${pkgStripped} is not a valid custom element constructor.`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t});\n\n\treturn promises;\n};\n\n/**\n * Initialize PIE elements from a bundle that may already be loaded.\n *\n * `window.pie` is the IIFE bundle-loading global populated by\n * `loadPieModule` / `loadBundleFromString`. When the host loaded the\n * bundle through the deep `ElementLoader` primitive instead — as\n * `pie-section-player` does — the global is irrelevant: the loader\n * registers tags directly with `customElements`, so this function only\n * needs to bind models/sessions to whatever is already registered.\n *\n * Behavior:\n * - `window.pie` available → register any new tags from the bundle and\n * update bindings for already-registered tags.\n * - `window.pie` missing → fall back to the update-only path. Tags that\n * are already registered get their model/session updated; tags that\n * are not yet registered are logged at `warn` and left alone — the\n * host's loader is expected to register them imminently, after which\n * the existing `MutationObserver` / `updatePieElements` flow binds\n * them on the next reactive pass.\n *\n * The original blanket `window.pie not found; was the bundle inlined\n * correctly?` error has been removed: in the section-player + item-player\n * composition it produced a confusing red stack trace for a routine\n * timing condition that the host already handles. Genuine failures\n * (bundle not loaded by *anyone*) still surface — every unregistered tag\n * gets its own warning, and `updatePieElements` later reports any tag\n * that never resolves.\n */\nexport const initializePiesFromLoadedBundle = (\n\tconfig: ConfigEntity,\n\tsession: any[],\n\topts: LoadPieElementsOptions = {},\n): void => {\n\tconst registry = pieRegistry();\n\tconst options = mergeObjectsIgnoringNullUndefined(defaultOptions, opts);\n\n\tif (isPieAvailable(window)) {\n\t\tlogger.debug(\"[initializePiesFromLoadedBundle] window.pie available\");\n\t\tconst elementModule = window.pie.default;\n\t\tregisterPieElementsFromBundle(\n\t\t\telementModule,\n\t\t\tconfig,\n\t\t\tsession,\n\t\t\tregistry,\n\t\t\toptions,\n\t\t);\n\t\treturn;\n\t}\n\n\tlogger.debug(\n\t\t\"[initializePiesFromLoadedBundle] window.pie not present; using update-only path. Already-registered tags will be bound now; missing tags are expected to be registered by the host's loader and will bind on the next update pass.\",\n\t);\n\tregisterPieElementsFromBundle(null, config, session, registry, options);\n};\n\n/**\n * Load a PIE bundle from a URL and initialize elements\n */\nexport const loadPieModule = async (\n\tconfig: ConfigEntity,\n\tsession: any[],\n\topts: LoadPieElementsOptions = {},\n): Promise<{\n\tsession: any[];\n}> => {\n\tif (!session) {\n\t\tthrow new Error(\"session is required\");\n\t}\n\n\t// Initialize math-rendering module (required by PIE elements)\n\tawait initializeMathRendering();\n\n\tconst registry = pieRegistry();\n\tconst options = mergeObjectsIgnoringNullUndefined(defaultOptions, opts);\n\tconst url = opts.bundleUrl || getPieElementBundlesUrl(config, options);\n\tconst script = document.createElement(\"script\");\n\tscript.src = url;\n\tscript.defer = true;\n\tscript.onerror = () => {\n\t\tthrow new Error(`failed to load script: ${url}`);\n\t};\n\n\tconst loadPromise = new Promise<void>((loadResolve) => {\n\t\tscript.addEventListener(\"load\", () => {\n\t\t\tlogger.debug(\"[loadPieModule] Script loaded from:\", url);\n\t\t\tif (isPieAvailable(window)) {\n\t\t\t\tlogger.debug(\"[loadPieModule] window.pie available\");\n\t\t\t\tconst elementModule = window.pie.default;\n\n\t\t\t\t// Use shared registration logic (returns array of promises)\n\t\t\t\tconst registrationPromises = registerPieElementsFromBundle(\n\t\t\t\t\telementModule,\n\t\t\t\t\tconfig,\n\t\t\t\t\tsession,\n\t\t\t\t\tregistry,\n\t\t\t\t\toptions,\n\t\t\t\t);\n\n\t\t\t\t// Wait for all element definitions to complete\n\t\t\t\tPromise.all(registrationPromises).then(() => loadResolve());\n\t\t\t} else {\n\t\t\t\tlogger.error(\n\t\t\t\t\t\"[loadPieModule] pie var not found; is %s a proper PIE IIFE module?\",\n\t\t\t\t\turl,\n\t\t\t\t);\n\t\t\t\tloadResolve();\n\t\t\t}\n\t\t});\n\t});\n\n\tdocument.head.appendChild(script);\n\tawait loadPromise;\n\treturn { session };\n};\n\n/**\n * Load a PIE bundle from a JavaScript string into window.pie (IIFE bundles only)\n * This only registers elements and controllers - does NOT initialize them.\n * For initialization, use initializePiesFromLoadedBundle after loading.\n */\nexport const loadBundleFromString = async (bundleJs: string): Promise<void> => {\n\tawait initializeMathRendering();\n\tawait withBlobBundleUrl(\n\t\tbundleJs,\n\t\t{ stripSourceMapComment: true },\n\t\tasync (bundleUrl) => {\n\t\t\t// Create a script tag to execute the bundle\n\t\t\tconst script = document.createElement(\"script\");\n\t\t\tscript.src = bundleUrl;\n\t\t\tscript.type = \"text/javascript\"; // IIFE bundles are standard JS\n\n\t\t\t// Wait for script to load\n\t\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\t\tscript.onload = () => resolve();\n\t\t\t\tscript.onerror = () => reject(new Error(\"Failed to load bundle\"));\n\t\t\t\tdocument.head.appendChild(script);\n\t\t\t});\n\n\t\t\tlogger.debug(\"[loadBundleFromString] Bundle loaded into window.pie\");\n\t\t},\n\t);\n};\n\n/**\n * Load a PIE bundle from a JavaScript string and initialize elements\n * Convenience wrapper around loadBundleFromString + loadPieModule\n */\nexport const loadPieModuleFromString = async (\n\tbundleJs: string,\n\tconfig: ConfigEntity,\n\tsession: any[],\n\topts: LoadPieElementsOptions = {},\n): Promise<void> => {\n\tawait withBlobBundleUrl(bundleJs, {}, async (bundleUrl) => {\n\t\t// Use existing loadPieModule with the blob URL\n\t\tawait loadPieModule(config, session, { ...opts, bundleUrl });\n\t});\n};\n\nconst withBlobBundleUrl = async <T>(\n\tbundleJs: string,\n\toptions: { stripSourceMapComment?: boolean },\n\trun: (bundleUrl: string) => Promise<T>,\n): Promise<T> => {\n\tconst source = options.stripSourceMapComment\n\t\t? bundleJs.replace(/\\/\\/# sourceMappingURL=.*$/m, \"\")\n\t\t: bundleJs;\n\tconst blob = new Blob([source], { type: \"application/javascript\" });\n\tconst bundleUrl = URL.createObjectURL(blob);\n\ttry {\n\t\treturn await run(bundleUrl);\n\t} finally {\n\t\tURL.revokeObjectURL(bundleUrl);\n\t}\n};\n"]}
|
package/dist/pie/updates.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Functions for updating PIE elements with new models, sessions, and env.
|
|
5
5
|
*/
|
|
6
6
|
import { mergeObjectsIgnoringNullUndefined } from "../object/index.js";
|
|
7
|
+
import { wrapModelRichContent } from "../security/wrap-model-rich-content.js";
|
|
7
8
|
import { createPieLogger, isGlobalDebugEnabled } from "./logger.js";
|
|
8
9
|
import { findPieController } from "./scoring.js";
|
|
9
10
|
import { defaultPieElementOptions } from "./types.js";
|
|
@@ -92,14 +93,15 @@ const applyControllerToElement = async (element, model, elementSession, controll
|
|
|
92
93
|
element: model.element,
|
|
93
94
|
...controllerResultObject,
|
|
94
95
|
};
|
|
96
|
+
const wrappedModel = wrapModelRichContent(filteredModel);
|
|
95
97
|
logger.debug(`${logPrefix} ✅ Controller filtered model:`, {
|
|
96
|
-
id:
|
|
97
|
-
element:
|
|
98
|
-
hasCorrectResponse: "correctResponse" in
|
|
98
|
+
id: wrappedModel.id,
|
|
99
|
+
element: wrappedModel.element,
|
|
100
|
+
hasCorrectResponse: "correctResponse" in wrappedModel,
|
|
99
101
|
mode: env.mode,
|
|
100
102
|
role: env.role,
|
|
101
103
|
});
|
|
102
|
-
element.model =
|
|
104
|
+
element.model = wrappedModel;
|
|
103
105
|
element.session = elementSession;
|
|
104
106
|
}
|
|
105
107
|
catch (err) {
|
|
@@ -145,7 +147,7 @@ const updateSinglePieElement = async (pieElement, controllerLookupTag, options,
|
|
|
145
147
|
const controller = findPieController(controllerLookupTag);
|
|
146
148
|
if (!controller) {
|
|
147
149
|
logger.debug(`${logContext} ℹ️ No controller for ${controllerLookupTag}, using server-processed model`);
|
|
148
|
-
pieElement.model = model;
|
|
150
|
+
pieElement.model = wrapModelRichContent(model);
|
|
149
151
|
pieElement.session = elementSession;
|
|
150
152
|
return;
|
|
151
153
|
}
|
|
@@ -176,13 +178,13 @@ const updateSinglePieElement = async (pieElement, controllerLookupTag, options,
|
|
|
176
178
|
cause: errorMessage,
|
|
177
179
|
});
|
|
178
180
|
// Fall back to raw model on controller error
|
|
179
|
-
pieElement.model = model;
|
|
181
|
+
pieElement.model = wrapModelRichContent(model);
|
|
180
182
|
pieElement.session = elementSession;
|
|
181
183
|
}
|
|
182
184
|
}
|
|
183
185
|
else {
|
|
184
186
|
logger.debug(`${logContext} Direct model assignment for ${controllerLookupTag}#${pieElement.id} (no controller invocation requested)`);
|
|
185
|
-
pieElement.model = model;
|
|
187
|
+
pieElement.model = wrapModelRichContent(model);
|
|
186
188
|
pieElement.session = elementSession;
|
|
187
189
|
}
|
|
188
190
|
};
|
package/dist/pie/updates.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"updates.js","sourceRoot":"","sources":["../../src/pie/updates.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * PIE Updates Module\n *\n * Functions for updating PIE elements with new models, sessions, and env.\n */\n\nimport { mergeObjectsIgnoringNullUndefined } from \"../object/index.js\";\nimport type { ConfigEntity, Env, PieModel } from \"../types/index.js\";\nimport { createPieLogger, isGlobalDebugEnabled } from \"./logger.js\";\nimport { findPieController } from \"./scoring.js\";\nimport type { PieElement, UpdatePieElementOptions } from \"./types.js\";\nimport { defaultPieElementOptions } from \"./types.js\";\nimport { findOrAddSession } from \"./utils.js\";\n\n// Create module-level logger (respects global debug flag - pass function for dynamic checking)\nconst logger = createPieLogger(\"pie-updates\", () => isGlobalDebugEnabled());\n\ntype ControllerErrorDetail = {\n\tcode: \"PIE_CONTROLLER_CONTRACT_ERROR\" | \"PIE_CONTROLLER_RUNTIME_ERROR\";\n\tmessage: string;\n\telementName: string;\n\telementId: string;\n\tcontrollerShape?: string;\n\tcause?: string;\n};\n\nconst describeControllerShape = (controller: unknown): string => {\n\tif (!controller) return \"missing\";\n\tif (typeof controller === \"function\") return \"function\";\n\tif (typeof controller !== \"object\") return typeof controller;\n\tconst keys = Object.keys(controller as Record<string, unknown>);\n\tconst defaultValue = (controller as Record<string, unknown>).default;\n\tconst defaultKeys =\n\t\tdefaultValue && typeof defaultValue === \"object\"\n\t\t\t? Object.keys(defaultValue as Record<string, unknown>)\n\t\t\t: [];\n\treturn defaultKeys.length > 0\n\t\t? `object(keys=[${keys.join(\",\")}],defaultKeys=[${defaultKeys.join(\",\")}])`\n\t\t: `object(keys=[${keys.join(\",\")}])`;\n};\n\nconst resolveControllerModelFunction = (\n\tcontroller: unknown,\n):\n\t| ((model: PieModel, session: any, env: Env, updateSession: any) => unknown)\n\t| null => {\n\tif (!controller) return null;\n\tif (typeof controller === \"function\") {\n\t\treturn controller as (\n\t\t\tmodel: PieModel,\n\t\t\tsession: any,\n\t\t\tenv: Env,\n\t\t\tupdateSession: any,\n\t\t) => unknown;\n\t}\n\tif (typeof controller !== \"object\") return null;\n\tconst direct = (controller as Record<string, unknown>).model;\n\tif (typeof direct === \"function\") {\n\t\treturn (model, sessionData, env, updateSession) =>\n\t\t\t(direct as Function).call(\n\t\t\t\tcontroller,\n\t\t\t\tmodel,\n\t\t\t\tsessionData,\n\t\t\t\tenv,\n\t\t\t\tupdateSession,\n\t\t\t);\n\t}\n\tconst fromDefault = (controller as Record<string, unknown>).default;\n\tif (fromDefault && typeof fromDefault === \"object\") {\n\t\tconst nested = (fromDefault as Record<string, unknown>).model;\n\t\tif (typeof nested === \"function\") {\n\t\t\treturn (model, sessionData, env, updateSession) =>\n\t\t\t\t(nested as Function).call(\n\t\t\t\t\tfromDefault,\n\t\t\t\t\tmodel,\n\t\t\t\t\tsessionData,\n\t\t\t\t\tenv,\n\t\t\t\t\tupdateSession,\n\t\t\t\t);\n\t\t}\n\t}\n\treturn null;\n};\n\nconst emitControllerError = (\n\tpieElement: PieElement,\n\tdetail: ControllerErrorDetail,\n): void => {\n\tpieElement.dispatchEvent(\n\t\tnew CustomEvent(\"pie-controller-error\", {\n\t\t\tdetail,\n\t\t\tbubbles: true,\n\t\t\tcomposed: true,\n\t\t}),\n\t);\n};\n\n/**\n * Helper function to apply controller to element\n * Extracted to eliminate duplication and ensure consistent controller invocation\n */\nconst applyControllerToElement = async (\n\telement: PieElement,\n\tmodel: PieModel,\n\telementSession: any,\n\tcontroller: unknown,\n\tenv: Env,\n\tlogPrefix: string,\n\tonElementSessionUpdate?: (\n\t\telementId: string,\n\t\telementName: string,\n\t\tproperties: Record<string, unknown>,\n\t) => void,\n): Promise<void> => {\n\tlogger.debug(`${logPrefix} Using controller, env:`, env);\n\tlogger.debug(`${logPrefix} Model before filter:`, {\n\t\tid: model.id,\n\t\telement: model.element,\n\t\thasCorrectResponse: \"correctResponse\" in model,\n\t});\n\n\t// Create updateSession callback for controller to save derived state (e.g.\n\t// shuffle order). Mutate the in-flight element session so this render uses it,\n\t// AND propagate the write to the authoritative session via the host callback\n\t// so subsequent renders reuse it instead of regenerating it. The write-back is\n\t// keyed by the canonical model id/element (the entry findOrAddSession resolved),\n\t// which also tolerates controllers that pass an undefined id/element.\n\tconst updateSession = (id: string, _elementName: string, properties: any) => {\n\t\tlogger.debug(\n\t\t\t`${logPrefix} updateSession called for ${id} with:`,\n\t\t\tproperties,\n\t\t);\n\t\tObject.assign(elementSession, properties);\n\t\tonElementSessionUpdate?.(model.id, model.element, properties);\n\t\treturn Promise.resolve();\n\t};\n\n\ttry {\n\t\tconst modelFunction = resolveControllerModelFunction(controller);\n\t\tif (!modelFunction) {\n\t\t\tthrow new Error(\n\t\t\t\t`Controller contract mismatch: expected a model() function but received ${describeControllerShape(\n\t\t\t\t\tcontroller,\n\t\t\t\t)}`,\n\t\t\t);\n\t\t}\n\t\tconst controllerResult = await modelFunction(\n\t\t\tmodel,\n\t\t\telementSession,\n\t\t\tenv,\n\t\t\tupdateSession,\n\t\t);\n\n\t\t// Merge controller result with id and element (like server-side PieControllerExecutor does)\n\t\tconst controllerResultObject =\n\t\t\tcontrollerResult && typeof controllerResult === \"object\"\n\t\t\t\t? (controllerResult as Record<string, unknown>)\n\t\t\t\t: {};\n\t\tconst filteredModel = {\n\t\t\tid: model.id,\n\t\t\telement: model.element,\n\t\t\t...controllerResultObject,\n\t\t};\n\n\t\tlogger.debug(`${logPrefix} ✅ Controller filtered model:`, {\n\t\t\tid: filteredModel.id,\n\t\t\telement: filteredModel.element,\n\t\t\thasCorrectResponse: \"correctResponse\" in filteredModel,\n\t\t\tmode: env.mode,\n\t\t\trole: env.role,\n\t\t});\n\n\t\telement.model = filteredModel;\n\t\telement.session = elementSession;\n\t} catch (err) {\n\t\tlogger.error(`${logPrefix} ❌ Controller error:`, err);\n\t\tthrow err; // Re-throw - controller errors are fatal\n\t}\n};\n\ntype ResolvedUpdateOptions = Pick<\n\tUpdatePieElementOptions,\n\t| \"config\"\n\t| \"session\"\n\t| \"env\"\n\t| \"eventListeners\"\n\t| \"invokeControllerForModel\"\n\t| \"onElementSessionUpdate\"\n>;\n\nconst resolveAndValidateUpdateOptions = (\n\topts: UpdatePieElementOptions,\n): ResolvedUpdateOptions => {\n\tconst {\n\t\tconfig,\n\t\tsession,\n\t\tenv,\n\t\teventListeners,\n\t\tinvokeControllerForModel,\n\t\tonElementSessionUpdate,\n\t} = mergeObjectsIgnoringNullUndefined(defaultPieElementOptions, opts);\n\tif (!env) {\n\t\tthrow new Error(\"env is required\");\n\t}\n\tif (!session) {\n\t\tthrow new Error(\"session is required\");\n\t}\n\tif (!config) {\n\t\tthrow new Error(\"config is required\");\n\t}\n\treturn {\n\t\tconfig,\n\t\tsession,\n\t\tenv,\n\t\teventListeners,\n\t\tinvokeControllerForModel,\n\t\tonElementSessionUpdate,\n\t};\n};\n\nconst updateSinglePieElement = async (\n\tpieElement: PieElement,\n\tcontrollerLookupTag: string,\n\toptions: ResolvedUpdateOptions,\n\tlogContext: string,\n): Promise<void> => {\n\tconst {\n\t\tconfig,\n\t\tsession,\n\t\tenv,\n\t\teventListeners,\n\t\tinvokeControllerForModel,\n\t\tonElementSessionUpdate,\n\t} = options;\n\tconst model = config.models?.find((m) => m.id === pieElement.id) as\n\t\t| PieModel\n\t\t| undefined;\n\tif (!model) {\n\t\tlogger.error(`${logContext} Model not found for`, controllerLookupTag);\n\t\tthrow new Error(`model not found for ${controllerLookupTag}`);\n\t}\n\n\tconst elementSession = findOrAddSession(session, model.id, model.element);\n\n\t// Always attach event listeners (don't skip them for no-controller case)\n\tif (eventListeners) {\n\t\tObject.entries(eventListeners).forEach(([evt, fn]) => {\n\t\t\tpieElement.addEventListener(evt as any, fn);\n\t\t});\n\t}\n\n\tif (env && invokeControllerForModel) {\n\t\tconst controller = findPieController(controllerLookupTag);\n\t\tif (!controller) {\n\t\t\tlogger.debug(\n\t\t\t\t`${logContext} ℹ️ No controller for ${controllerLookupTag}, using server-processed model`,\n\t\t\t);\n\t\t\tpieElement.model = model;\n\t\t\tpieElement.session = elementSession;\n\t\t\treturn;\n\t\t}\n\n\t\tlogger.debug(\n\t\t\t`${logContext} Invoking controller for ${controllerLookupTag}#${pieElement.id}`,\n\t\t\t{\n\t\t\t\tmode: env.mode,\n\t\t\t\trole: env.role,\n\t\t\t\thasCorrectResponse: \"correctResponse\" in model,\n\t\t\t},\n\t\t);\n\n\t\t// Await the controller so any updateSession write-back completes before the\n\t\t// caller computes/emits the session signature; otherwise a late, async\n\t\t// shuffle write lands after the cycle that read the session and the order\n\t\t// never round-trips (PIE-631).\n\t\ttry {\n\t\t\tawait applyControllerToElement(\n\t\t\t\tpieElement,\n\t\t\t\tmodel,\n\t\t\t\telementSession,\n\t\t\t\tcontroller,\n\t\t\t\tenv,\n\t\t\t\t`${logContext}(${controllerLookupTag}#${pieElement.id})`,\n\t\t\t\tonElementSessionUpdate,\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tconst errorMessage = err instanceof Error ? err.message : String(err);\n\t\t\tconst isContractError = errorMessage.includes(\n\t\t\t\t\"Controller contract mismatch\",\n\t\t\t);\n\t\t\tlogger.error(\n\t\t\t\t`${logContext} Controller failed for ${controllerLookupTag}#${pieElement.id}:`,\n\t\t\t\terr,\n\t\t\t);\n\t\t\temitControllerError(pieElement, {\n\t\t\t\tcode: isContractError\n\t\t\t\t\t? \"PIE_CONTROLLER_CONTRACT_ERROR\"\n\t\t\t\t\t: \"PIE_CONTROLLER_RUNTIME_ERROR\",\n\t\t\t\tmessage: `${controllerLookupTag} controller failed while applying model for ${pieElement.id}. ${errorMessage}`,\n\t\t\t\telementName: controllerLookupTag,\n\t\t\t\telementId: pieElement.id,\n\t\t\t\tcontrollerShape: describeControllerShape(controller),\n\t\t\t\tcause: errorMessage,\n\t\t\t});\n\t\t\t// Fall back to raw model on controller error\n\t\t\tpieElement.model = model;\n\t\t\tpieElement.session = elementSession;\n\t\t}\n\t} else {\n\t\tlogger.debug(\n\t\t\t`${logContext} Direct model assignment for ${controllerLookupTag}#${pieElement.id} (no controller invocation requested)`,\n\t\t);\n\t\tpieElement.model = model;\n\t\tpieElement.session = elementSession;\n\t}\n};\n\n/**\n * Update a PIE element by ref (direct Element reference)\n */\nexport const updatePieElementWithRef = (\n\tel: Element,\n\topts: UpdatePieElementOptions,\n): Promise<void> => {\n\tconst options = resolveAndValidateUpdateOptions(opts);\n\tconst pieElement = el as PieElement;\n\tconst elName = pieElement.tagName.toLowerCase();\n\treturn updateSinglePieElement(\n\t\tpieElement,\n\t\telName,\n\t\toptions,\n\t\t\"[updatePieElementWithRef]\",\n\t);\n};\n\n/**\n * Update a PIE element by name (finds all matching elements in DOM)\n */\nexport const updatePieElement = (\n\telName: string,\n\topts: UpdatePieElementOptions,\n): Promise<void> => {\n\tconst options = resolveAndValidateUpdateOptions(opts);\n\tconst { container } = mergeObjectsIgnoringNullUndefined(\n\t\tdefaultPieElementOptions,\n\t\topts,\n\t);\n\t// Use container for scoped query or fallback to document for global query\n\tconst searchRoot = container || document;\n\tconst pieElements = searchRoot.querySelectorAll(elName);\n\tif (!pieElements || pieElements.length === 0) {\n\t\tlogger.debug(`no elements found for ${elName}`);\n\t\treturn Promise.resolve();\n\t}\n\treturn Promise.all(\n\t\tArray.from(pieElements, (el) =>\n\t\t\tupdateSinglePieElement(\n\t\t\t\tel as PieElement,\n\t\t\t\telName,\n\t\t\t\toptions,\n\t\t\t\t\"[updatePieElement]\",\n\t\t\t),\n\t\t),\n\t).then(() => undefined);\n};\n\n/**\n * Update all PIE elements in a config\n */\nexport const updatePieElements = (\n\tconfig: ConfigEntity,\n\tsession: any[],\n\tenv: Env,\n\tcontainer?: Element | Document,\n\tonElementSessionUpdate?: UpdatePieElementOptions[\"onElementSessionUpdate\"],\n): Promise<void> => {\n\tlogger.debug(\"[updatePieElements] Updating all elements with env:\", env);\n\treturn Promise.all(\n\t\tObject.entries(config.elements).map(([elName, _pkg]) =>\n\t\t\tupdatePieElement(elName, {\n\t\t\t\tconfig,\n\t\t\t\tsession,\n\t\t\t\tenv,\n\t\t\t\tcontainer,\n\t\t\t\tonElementSessionUpdate,\n\t\t\t}),\n\t\t),\n\t).then(() => undefined);\n};\n"]}
|
|
1
|
+
{"version":3,"file":"updates.js","sourceRoot":"","sources":["../../src/pie/updates.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * PIE Updates Module\n *\n * Functions for updating PIE elements with new models, sessions, and env.\n */\n\nimport { mergeObjectsIgnoringNullUndefined } from \"../object/index.js\";\nimport { wrapModelRichContent } from \"../security/wrap-model-rich-content.js\";\nimport type { ConfigEntity, Env, PieModel } from \"../types/index.js\";\nimport { createPieLogger, isGlobalDebugEnabled } from \"./logger.js\";\nimport { findPieController } from \"./scoring.js\";\nimport type { PieElement, UpdatePieElementOptions } from \"./types.js\";\nimport { defaultPieElementOptions } from \"./types.js\";\nimport { findOrAddSession } from \"./utils.js\";\n\n// Create module-level logger (respects global debug flag - pass function for dynamic checking)\nconst logger = createPieLogger(\"pie-updates\", () => isGlobalDebugEnabled());\n\ntype ControllerErrorDetail = {\n\tcode: \"PIE_CONTROLLER_CONTRACT_ERROR\" | \"PIE_CONTROLLER_RUNTIME_ERROR\";\n\tmessage: string;\n\telementName: string;\n\telementId: string;\n\tcontrollerShape?: string;\n\tcause?: string;\n};\n\nconst describeControllerShape = (controller: unknown): string => {\n\tif (!controller) return \"missing\";\n\tif (typeof controller === \"function\") return \"function\";\n\tif (typeof controller !== \"object\") return typeof controller;\n\tconst keys = Object.keys(controller as Record<string, unknown>);\n\tconst defaultValue = (controller as Record<string, unknown>).default;\n\tconst defaultKeys =\n\t\tdefaultValue && typeof defaultValue === \"object\"\n\t\t\t? Object.keys(defaultValue as Record<string, unknown>)\n\t\t\t: [];\n\treturn defaultKeys.length > 0\n\t\t? `object(keys=[${keys.join(\",\")}],defaultKeys=[${defaultKeys.join(\",\")}])`\n\t\t: `object(keys=[${keys.join(\",\")}])`;\n};\n\nconst resolveControllerModelFunction = (\n\tcontroller: unknown,\n):\n\t| ((model: PieModel, session: any, env: Env, updateSession: any) => unknown)\n\t| null => {\n\tif (!controller) return null;\n\tif (typeof controller === \"function\") {\n\t\treturn controller as (\n\t\t\tmodel: PieModel,\n\t\t\tsession: any,\n\t\t\tenv: Env,\n\t\t\tupdateSession: any,\n\t\t) => unknown;\n\t}\n\tif (typeof controller !== \"object\") return null;\n\tconst direct = (controller as Record<string, unknown>).model;\n\tif (typeof direct === \"function\") {\n\t\treturn (model, sessionData, env, updateSession) =>\n\t\t\t(direct as Function).call(\n\t\t\t\tcontroller,\n\t\t\t\tmodel,\n\t\t\t\tsessionData,\n\t\t\t\tenv,\n\t\t\t\tupdateSession,\n\t\t\t);\n\t}\n\tconst fromDefault = (controller as Record<string, unknown>).default;\n\tif (fromDefault && typeof fromDefault === \"object\") {\n\t\tconst nested = (fromDefault as Record<string, unknown>).model;\n\t\tif (typeof nested === \"function\") {\n\t\t\treturn (model, sessionData, env, updateSession) =>\n\t\t\t\t(nested as Function).call(\n\t\t\t\t\tfromDefault,\n\t\t\t\t\tmodel,\n\t\t\t\t\tsessionData,\n\t\t\t\t\tenv,\n\t\t\t\t\tupdateSession,\n\t\t\t\t);\n\t\t}\n\t}\n\treturn null;\n};\n\nconst emitControllerError = (\n\tpieElement: PieElement,\n\tdetail: ControllerErrorDetail,\n): void => {\n\tpieElement.dispatchEvent(\n\t\tnew CustomEvent(\"pie-controller-error\", {\n\t\t\tdetail,\n\t\t\tbubbles: true,\n\t\t\tcomposed: true,\n\t\t}),\n\t);\n};\n\n/**\n * Helper function to apply controller to element\n * Extracted to eliminate duplication and ensure consistent controller invocation\n */\nconst applyControllerToElement = async (\n\telement: PieElement,\n\tmodel: PieModel,\n\telementSession: any,\n\tcontroller: unknown,\n\tenv: Env,\n\tlogPrefix: string,\n\tonElementSessionUpdate?: (\n\t\telementId: string,\n\t\telementName: string,\n\t\tproperties: Record<string, unknown>,\n\t) => void,\n): Promise<void> => {\n\tlogger.debug(`${logPrefix} Using controller, env:`, env);\n\tlogger.debug(`${logPrefix} Model before filter:`, {\n\t\tid: model.id,\n\t\telement: model.element,\n\t\thasCorrectResponse: \"correctResponse\" in model,\n\t});\n\n\t// Create updateSession callback for controller to save derived state (e.g.\n\t// shuffle order). Mutate the in-flight element session so this render uses it,\n\t// AND propagate the write to the authoritative session via the host callback\n\t// so subsequent renders reuse it instead of regenerating it. The write-back is\n\t// keyed by the canonical model id/element (the entry findOrAddSession resolved),\n\t// which also tolerates controllers that pass an undefined id/element.\n\tconst updateSession = (id: string, _elementName: string, properties: any) => {\n\t\tlogger.debug(\n\t\t\t`${logPrefix} updateSession called for ${id} with:`,\n\t\t\tproperties,\n\t\t);\n\t\tObject.assign(elementSession, properties);\n\t\tonElementSessionUpdate?.(model.id, model.element, properties);\n\t\treturn Promise.resolve();\n\t};\n\n\ttry {\n\t\tconst modelFunction = resolveControllerModelFunction(controller);\n\t\tif (!modelFunction) {\n\t\t\tthrow new Error(\n\t\t\t\t`Controller contract mismatch: expected a model() function but received ${describeControllerShape(\n\t\t\t\t\tcontroller,\n\t\t\t\t)}`,\n\t\t\t);\n\t\t}\n\t\tconst controllerResult = await modelFunction(\n\t\t\tmodel,\n\t\t\telementSession,\n\t\t\tenv,\n\t\t\tupdateSession,\n\t\t);\n\n\t\t// Merge controller result with id and element (like server-side PieControllerExecutor does)\n\t\tconst controllerResultObject =\n\t\t\tcontrollerResult && typeof controllerResult === \"object\"\n\t\t\t\t? (controllerResult as Record<string, unknown>)\n\t\t\t\t: {};\n\t\tconst filteredModel = {\n\t\t\tid: model.id,\n\t\t\telement: model.element,\n\t\t\t...controllerResultObject,\n\t\t};\n\t\tconst wrappedModel = wrapModelRichContent(filteredModel);\n\n\t\tlogger.debug(`${logPrefix} ✅ Controller filtered model:`, {\n\t\t\tid: wrappedModel.id,\n\t\t\telement: wrappedModel.element,\n\t\t\thasCorrectResponse: \"correctResponse\" in wrappedModel,\n\t\t\tmode: env.mode,\n\t\t\trole: env.role,\n\t\t});\n\n\t\telement.model = wrappedModel;\n\t\telement.session = elementSession;\n\t} catch (err) {\n\t\tlogger.error(`${logPrefix} ❌ Controller error:`, err);\n\t\tthrow err; // Re-throw - controller errors are fatal\n\t}\n};\n\ntype ResolvedUpdateOptions = Pick<\n\tUpdatePieElementOptions,\n\t| \"config\"\n\t| \"session\"\n\t| \"env\"\n\t| \"eventListeners\"\n\t| \"invokeControllerForModel\"\n\t| \"onElementSessionUpdate\"\n>;\n\nconst resolveAndValidateUpdateOptions = (\n\topts: UpdatePieElementOptions,\n): ResolvedUpdateOptions => {\n\tconst {\n\t\tconfig,\n\t\tsession,\n\t\tenv,\n\t\teventListeners,\n\t\tinvokeControllerForModel,\n\t\tonElementSessionUpdate,\n\t} = mergeObjectsIgnoringNullUndefined(defaultPieElementOptions, opts);\n\tif (!env) {\n\t\tthrow new Error(\"env is required\");\n\t}\n\tif (!session) {\n\t\tthrow new Error(\"session is required\");\n\t}\n\tif (!config) {\n\t\tthrow new Error(\"config is required\");\n\t}\n\treturn {\n\t\tconfig,\n\t\tsession,\n\t\tenv,\n\t\teventListeners,\n\t\tinvokeControllerForModel,\n\t\tonElementSessionUpdate,\n\t};\n};\n\nconst updateSinglePieElement = async (\n\tpieElement: PieElement,\n\tcontrollerLookupTag: string,\n\toptions: ResolvedUpdateOptions,\n\tlogContext: string,\n): Promise<void> => {\n\tconst {\n\t\tconfig,\n\t\tsession,\n\t\tenv,\n\t\teventListeners,\n\t\tinvokeControllerForModel,\n\t\tonElementSessionUpdate,\n\t} = options;\n\tconst model = config.models?.find((m) => m.id === pieElement.id) as\n\t\t| PieModel\n\t\t| undefined;\n\tif (!model) {\n\t\tlogger.error(`${logContext} Model not found for`, controllerLookupTag);\n\t\tthrow new Error(`model not found for ${controllerLookupTag}`);\n\t}\n\n\tconst elementSession = findOrAddSession(session, model.id, model.element);\n\n\t// Always attach event listeners (don't skip them for no-controller case)\n\tif (eventListeners) {\n\t\tObject.entries(eventListeners).forEach(([evt, fn]) => {\n\t\t\tpieElement.addEventListener(evt as any, fn);\n\t\t});\n\t}\n\n\tif (env && invokeControllerForModel) {\n\t\tconst controller = findPieController(controllerLookupTag);\n\t\tif (!controller) {\n\t\t\tlogger.debug(\n\t\t\t\t`${logContext} ℹ️ No controller for ${controllerLookupTag}, using server-processed model`,\n\t\t\t);\n\t\t\tpieElement.model = wrapModelRichContent(model);\n\t\t\tpieElement.session = elementSession;\n\t\t\treturn;\n\t\t}\n\n\t\tlogger.debug(\n\t\t\t`${logContext} Invoking controller for ${controllerLookupTag}#${pieElement.id}`,\n\t\t\t{\n\t\t\t\tmode: env.mode,\n\t\t\t\trole: env.role,\n\t\t\t\thasCorrectResponse: \"correctResponse\" in model,\n\t\t\t},\n\t\t);\n\n\t\t// Await the controller so any updateSession write-back completes before the\n\t\t// caller computes/emits the session signature; otherwise a late, async\n\t\t// shuffle write lands after the cycle that read the session and the order\n\t\t// never round-trips (PIE-631).\n\t\ttry {\n\t\t\tawait applyControllerToElement(\n\t\t\t\tpieElement,\n\t\t\t\tmodel,\n\t\t\t\telementSession,\n\t\t\t\tcontroller,\n\t\t\t\tenv,\n\t\t\t\t`${logContext}(${controllerLookupTag}#${pieElement.id})`,\n\t\t\t\tonElementSessionUpdate,\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tconst errorMessage = err instanceof Error ? err.message : String(err);\n\t\t\tconst isContractError = errorMessage.includes(\n\t\t\t\t\"Controller contract mismatch\",\n\t\t\t);\n\t\t\tlogger.error(\n\t\t\t\t`${logContext} Controller failed for ${controllerLookupTag}#${pieElement.id}:`,\n\t\t\t\terr,\n\t\t\t);\n\t\t\temitControllerError(pieElement, {\n\t\t\t\tcode: isContractError\n\t\t\t\t\t? \"PIE_CONTROLLER_CONTRACT_ERROR\"\n\t\t\t\t\t: \"PIE_CONTROLLER_RUNTIME_ERROR\",\n\t\t\t\tmessage: `${controllerLookupTag} controller failed while applying model for ${pieElement.id}. ${errorMessage}`,\n\t\t\t\telementName: controllerLookupTag,\n\t\t\t\telementId: pieElement.id,\n\t\t\t\tcontrollerShape: describeControllerShape(controller),\n\t\t\t\tcause: errorMessage,\n\t\t\t});\n\t\t\t// Fall back to raw model on controller error\n\t\t\tpieElement.model = wrapModelRichContent(model);\n\t\t\tpieElement.session = elementSession;\n\t\t}\n\t} else {\n\t\tlogger.debug(\n\t\t\t`${logContext} Direct model assignment for ${controllerLookupTag}#${pieElement.id} (no controller invocation requested)`,\n\t\t);\n\t\tpieElement.model = wrapModelRichContent(model);\n\t\tpieElement.session = elementSession;\n\t}\n};\n\n/**\n * Update a PIE element by ref (direct Element reference)\n */\nexport const updatePieElementWithRef = (\n\tel: Element,\n\topts: UpdatePieElementOptions,\n): Promise<void> => {\n\tconst options = resolveAndValidateUpdateOptions(opts);\n\tconst pieElement = el as PieElement;\n\tconst elName = pieElement.tagName.toLowerCase();\n\treturn updateSinglePieElement(\n\t\tpieElement,\n\t\telName,\n\t\toptions,\n\t\t\"[updatePieElementWithRef]\",\n\t);\n};\n\n/**\n * Update a PIE element by name (finds all matching elements in DOM)\n */\nexport const updatePieElement = (\n\telName: string,\n\topts: UpdatePieElementOptions,\n): Promise<void> => {\n\tconst options = resolveAndValidateUpdateOptions(opts);\n\tconst { container } = mergeObjectsIgnoringNullUndefined(\n\t\tdefaultPieElementOptions,\n\t\topts,\n\t);\n\t// Use container for scoped query or fallback to document for global query\n\tconst searchRoot = container || document;\n\tconst pieElements = searchRoot.querySelectorAll(elName);\n\tif (!pieElements || pieElements.length === 0) {\n\t\tlogger.debug(`no elements found for ${elName}`);\n\t\treturn Promise.resolve();\n\t}\n\treturn Promise.all(\n\t\tArray.from(pieElements, (el) =>\n\t\t\tupdateSinglePieElement(\n\t\t\t\tel as PieElement,\n\t\t\t\telName,\n\t\t\t\toptions,\n\t\t\t\t\"[updatePieElement]\",\n\t\t\t),\n\t\t),\n\t).then(() => undefined);\n};\n\n/**\n * Update all PIE elements in a config\n */\nexport const updatePieElements = (\n\tconfig: ConfigEntity,\n\tsession: any[],\n\tenv: Env,\n\tcontainer?: Element | Document,\n\tonElementSessionUpdate?: UpdatePieElementOptions[\"onElementSessionUpdate\"],\n): Promise<void> => {\n\tlogger.debug(\"[updatePieElements] Updating all elements with env:\", env);\n\treturn Promise.all(\n\t\tObject.entries(config.elements).map(([elName, _pkg]) =>\n\t\t\tupdatePieElement(elName, {\n\t\t\t\tconfig,\n\t\t\t\tsession,\n\t\t\t\tenv,\n\t\t\t\tcontainer,\n\t\t\t\tonElementSessionUpdate,\n\t\t\t}),\n\t\t),\n\t).then(() => undefined);\n};\n"]}
|
package/dist/security/index.d.ts
CHANGED
|
@@ -2,4 +2,5 @@ export { buildAuthoringAllowList, createDefaultItemMarkupSanitizer, resetPurifie
|
|
|
2
2
|
export { parseAllowedStyleOrigins, validateExternalStyleUrl, type StyleUrlValidationError, type StyleUrlValidationOk, type StyleUrlValidationOptions, type StyleUrlValidationResult, } from "./validate-style-url.js";
|
|
3
3
|
export { resetSvgSanitizerForTesting, sanitizeSvgIcon, } from "./sanitize-svg-icon.js";
|
|
4
4
|
export { wrapOverwideImages } from "./wrap-overwide-images.js";
|
|
5
|
+
export { wrapModelRichContent } from "./wrap-model-rich-content.js";
|
|
5
6
|
export { wrapOverwideTables } from "./wrap-overwide-tables.js";
|
package/dist/security/index.js
CHANGED
|
@@ -2,5 +2,6 @@ export { buildAuthoringAllowList, createDefaultItemMarkupSanitizer, resetPurifie
|
|
|
2
2
|
export { parseAllowedStyleOrigins, validateExternalStyleUrl, } from "./validate-style-url.js";
|
|
3
3
|
export { resetSvgSanitizerForTesting, sanitizeSvgIcon, } from "./sanitize-svg-icon.js";
|
|
4
4
|
export { wrapOverwideImages } from "./wrap-overwide-images.js";
|
|
5
|
+
export { wrapModelRichContent } from "./wrap-model-rich-content.js";
|
|
5
6
|
export { wrapOverwideTables } from "./wrap-overwide-tables.js";
|
|
6
7
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/security/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,uBAAuB,EACvB,gCAAgC,EAChC,uBAAuB,EACvB,kBAAkB,GAGlB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACN,wBAAwB,EACxB,wBAAwB,GAKxB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACN,2BAA2B,EAC3B,eAAe,GACf,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC","sourcesContent":["export {\n\tbuildAuthoringAllowList,\n\tcreateDefaultItemMarkupSanitizer,\n\tresetPurifierForTesting,\n\tsanitizeItemMarkup,\n\ttype ItemMarkupSanitizer,\n\ttype SanitizeItemMarkupOptions,\n} from \"./sanitize-item-markup.js\";\nexport {\n\tparseAllowedStyleOrigins,\n\tvalidateExternalStyleUrl,\n\ttype StyleUrlValidationError,\n\ttype StyleUrlValidationOk,\n\ttype StyleUrlValidationOptions,\n\ttype StyleUrlValidationResult,\n} from \"./validate-style-url.js\";\nexport {\n\tresetSvgSanitizerForTesting,\n\tsanitizeSvgIcon,\n} from \"./sanitize-svg-icon.js\";\nexport { wrapOverwideImages } from \"./wrap-overwide-images.js\";\nexport { wrapOverwideTables } from \"./wrap-overwide-tables.js\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/security/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,uBAAuB,EACvB,gCAAgC,EAChC,uBAAuB,EACvB,kBAAkB,GAGlB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACN,wBAAwB,EACxB,wBAAwB,GAKxB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACN,2BAA2B,EAC3B,eAAe,GACf,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC","sourcesContent":["export {\n\tbuildAuthoringAllowList,\n\tcreateDefaultItemMarkupSanitizer,\n\tresetPurifierForTesting,\n\tsanitizeItemMarkup,\n\ttype ItemMarkupSanitizer,\n\ttype SanitizeItemMarkupOptions,\n} from \"./sanitize-item-markup.js\";\nexport {\n\tparseAllowedStyleOrigins,\n\tvalidateExternalStyleUrl,\n\ttype StyleUrlValidationError,\n\ttype StyleUrlValidationOk,\n\ttype StyleUrlValidationOptions,\n\ttype StyleUrlValidationResult,\n} from \"./validate-style-url.js\";\nexport {\n\tresetSvgSanitizerForTesting,\n\tsanitizeSvgIcon,\n} from \"./sanitize-svg-icon.js\";\nexport { wrapOverwideImages } from \"./wrap-overwide-images.js\";\nexport { wrapModelRichContent } from \"./wrap-model-rich-content.js\";\nexport { wrapOverwideTables } from \"./wrap-overwide-tables.js\";\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function wrapModelRichContent<T>(model: T): T;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { wrapOverwideImages } from "./wrap-overwide-images.js";
|
|
2
|
+
import { wrapOverwideTables } from "./wrap-overwide-tables.js";
|
|
3
|
+
const RICH_CONTENT_TAG_REGEX = /<(?:img|table)\b/i;
|
|
4
|
+
const SKIPPED_KEYS = new Set(["accessibilityCatalogs"]);
|
|
5
|
+
function maybeWrapRichContent(value) {
|
|
6
|
+
if (!RICH_CONTENT_TAG_REGEX.test(value))
|
|
7
|
+
return value;
|
|
8
|
+
return wrapOverwideTables(wrapOverwideImages(value));
|
|
9
|
+
}
|
|
10
|
+
function wrapValue(value, parentKey) {
|
|
11
|
+
if (parentKey && SKIPPED_KEYS.has(parentKey))
|
|
12
|
+
return value;
|
|
13
|
+
if (typeof value === "string")
|
|
14
|
+
return maybeWrapRichContent(value);
|
|
15
|
+
if (!value || typeof value !== "object")
|
|
16
|
+
return value;
|
|
17
|
+
if (Array.isArray(value)) {
|
|
18
|
+
let changed = false;
|
|
19
|
+
const next = value.map((entry) => {
|
|
20
|
+
const wrapped = wrapValue(entry);
|
|
21
|
+
if (wrapped !== entry)
|
|
22
|
+
changed = true;
|
|
23
|
+
return wrapped;
|
|
24
|
+
});
|
|
25
|
+
return changed ? next : value;
|
|
26
|
+
}
|
|
27
|
+
const record = value;
|
|
28
|
+
let changed = false;
|
|
29
|
+
const next = {};
|
|
30
|
+
for (const [key, entry] of Object.entries(record)) {
|
|
31
|
+
const wrapped = wrapValue(entry, key);
|
|
32
|
+
if (wrapped !== entry)
|
|
33
|
+
changed = true;
|
|
34
|
+
next[key] = wrapped;
|
|
35
|
+
}
|
|
36
|
+
return changed ? next : value;
|
|
37
|
+
}
|
|
38
|
+
export function wrapModelRichContent(model) {
|
|
39
|
+
return wrapValue(model);
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=wrap-model-rich-content.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wrap-model-rich-content.js","sourceRoot":"","sources":["../../src/security/wrap-model-rich-content.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE/D,MAAM,sBAAsB,GAAG,mBAAmB,CAAC;AACnD,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC;AAExD,SAAS,oBAAoB,CAAC,KAAa;IAC1C,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACtD,OAAO,kBAAkB,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC;AACtD,CAAC;AAED,SAAS,SAAS,CAAC,KAAc,EAAE,SAAkB;IACpD,IAAI,SAAS,IAAI,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC;QAAE,OAAO,KAAK,CAAC;IAC3D,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAClE,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAEtD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;YAChC,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;YACjC,IAAI,OAAO,KAAK,KAAK;gBAAE,OAAO,GAAG,IAAI,CAAC;YACtC,OAAO,OAAO,CAAC;QAChB,CAAC,CAAC,CAAC;QACH,OAAO,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;IAC/B,CAAC;IAED,MAAM,MAAM,GAAG,KAAgC,CAAC;IAChD,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,MAAM,IAAI,GAA4B,EAAE,CAAC;IACzC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACnD,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACtC,IAAI,OAAO,KAAK,KAAK;YAAE,OAAO,GAAG,IAAI,CAAC;QACtC,IAAI,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC;IACrB,CAAC;IACD,OAAO,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAI,KAAQ;IAC/C,OAAO,SAAS,CAAC,KAAK,CAAM,CAAC;AAC9B,CAAC","sourcesContent":["import { wrapOverwideImages } from \"./wrap-overwide-images.js\";\nimport { wrapOverwideTables } from \"./wrap-overwide-tables.js\";\n\nconst RICH_CONTENT_TAG_REGEX = /<(?:img|table)\\b/i;\nconst SKIPPED_KEYS = new Set([\"accessibilityCatalogs\"]);\n\nfunction maybeWrapRichContent(value: string): string {\n\tif (!RICH_CONTENT_TAG_REGEX.test(value)) return value;\n\treturn wrapOverwideTables(wrapOverwideImages(value));\n}\n\nfunction wrapValue(value: unknown, parentKey?: string): unknown {\n\tif (parentKey && SKIPPED_KEYS.has(parentKey)) return value;\n\tif (typeof value === \"string\") return maybeWrapRichContent(value);\n\tif (!value || typeof value !== \"object\") return value;\n\n\tif (Array.isArray(value)) {\n\t\tlet changed = false;\n\t\tconst next = value.map((entry) => {\n\t\t\tconst wrapped = wrapValue(entry);\n\t\t\tif (wrapped !== entry) changed = true;\n\t\t\treturn wrapped;\n\t\t});\n\t\treturn changed ? next : value;\n\t}\n\n\tconst record = value as Record<string, unknown>;\n\tlet changed = false;\n\tconst next: Record<string, unknown> = {};\n\tfor (const [key, entry] of Object.entries(record)) {\n\t\tconst wrapped = wrapValue(entry, key);\n\t\tif (wrapped !== entry) changed = true;\n\t\tnext[key] = wrapped;\n\t}\n\treturn changed ? next : value;\n}\n\nexport function wrapModelRichContent<T>(model: T): T {\n\treturn wrapValue(model) as T;\n}\n"]}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -481,10 +481,14 @@ export type BundleInfo = {
|
|
|
481
481
|
url: string;
|
|
482
482
|
hash: string;
|
|
483
483
|
};
|
|
484
|
-
|
|
484
|
+
export type ItemSession = {
|
|
485
|
+
id: string;
|
|
486
|
+
data: any[];
|
|
487
|
+
};
|
|
488
|
+
export interface PieDefaultModel {
|
|
485
489
|
[x: string]: any;
|
|
486
490
|
}
|
|
487
|
-
interface PieContent {
|
|
491
|
+
export interface PieContent {
|
|
488
492
|
id: string;
|
|
489
493
|
/**
|
|
490
494
|
* Set of elements to include in the pie, provided in the format `{'element-name': 'mpm-package-name'}`
|
|
@@ -494,11 +498,19 @@ interface PieContent {
|
|
|
494
498
|
models: PieModel[];
|
|
495
499
|
markup: string;
|
|
496
500
|
bundle?: BundleInfo;
|
|
501
|
+
resources?: ConfigResource;
|
|
497
502
|
defaultExtraModels?: {
|
|
498
503
|
[key: string]: PieDefaultModel;
|
|
499
504
|
};
|
|
500
505
|
}
|
|
501
|
-
interface
|
|
506
|
+
export interface ConfigResource {
|
|
507
|
+
stylesheets?: {
|
|
508
|
+
url: string;
|
|
509
|
+
}[];
|
|
510
|
+
containerClass?: string;
|
|
511
|
+
passageContainerClass?: string;
|
|
512
|
+
}
|
|
513
|
+
export interface AdvancedItemConfig {
|
|
502
514
|
id: string;
|
|
503
515
|
pie: PieContent;
|
|
504
516
|
passage?: PieContent;
|
package/dist/types/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * This contains copies of the data types we use in PIEOneer. These types, unlike\n * the ones in the datastore package, should not have any dependencies, and might in some\n * cases be more shallow than their originals. The main reason for these is that they should\n * be able to be used in front-end code (as well as the PIEOneer backend code).\n *\n * INCLUDING REFERENCES TO THE DATASTORE PACKAGE INSTEAD WILL MAKE PIEONEER THROW 500\n * EVERYWHERE WITHOUT ANY FURTHER EXPLANATION\n */\nexport interface BaseEntity {\n\tid?: string;\n\tcreatedAt?: Date;\n\tupdatedAt?: Date;\n}\n\nexport interface CollectionEntity extends BaseEntity {\n\tname: string;\n\torganization: string | OrganizationEntity;\n}\n\nexport interface OrganizationEntity extends BaseEntity {\n\tname: string;\n\tdefaultCollection?: string | CollectionEntity;\n}\n\nexport interface UserEntity extends BaseEntity {\n\temail: string;\n\tname?: string;\n}\n\nexport interface ClientEntity extends BaseEntity {\n\tname: string;\n\tsecret: string;\n\tuser: string | UserEntity;\n\torganization: string | OrganizationEntity;\n}\n\nexport interface AssignmentEntity extends BaseEntity {\n\torganization: string | OrganizationEntity;\n}\n\nexport interface SessionEntity extends BaseEntity {\n\titem: ItemEntity;\n\tassignment?: string | AssignmentEntity; // TODO: Remove after data is migrated\n\torganization?: string | OrganizationEntity;\n}\n\nexport enum SessionEventType {\n\tSAVE = \"save\",\n\tMODEL = \"model\",\n\tSCORE = \"score\",\n\tMANUAL_SCORE = \"manual-score\",\n}\n\nexport enum ScoreType {\n\tAUTO = \"auto\",\n\tMANUAL = \"manual\",\n}\n\nexport interface SessionScore {\n\tpoints?: number;\n\tmax?: number;\n\ttype?: ScoreType;\n\tpartialScoring?: boolean;\n\tmessage?: string;\n\terrors?: string[];\n}\n\nexport interface SessionAutoScore extends SessionScore {\n\telements?: any[];\n\textraProps?: any;\n}\n\nexport interface SessionManualScore extends SessionScore {}\n\nexport interface SessionEventEntity extends BaseEntity {\n\tsession: string | SessionEntity;\n\ttype?: SessionEventType;\n\tsaveEventId?: string;\n\tscore?: number;\n}\n\nexport enum ModeType {\n\tGATHER = \"gather\",\n\tVIEW = \"view\",\n\tEVALUATE = \"evaluate\",\n}\n\nexport interface FlatSession {\n\tid: string;\n\tassignment: AssignmentEntity;\n\titem: string;\n\tdata: any[];\n\tcreatedAt: Date;\n\tupdatedAt: Date;\n\tmode: ModeType;\n\tautoScore: SessionAutoScore;\n\tmanualScore: SessionManualScore;\n\tevents: SessionEventEntity[]; // raw events;\n}\n\nexport interface SemVerPrerelease {\n\ttag: string;\n\tversion: number;\n}\n\nexport interface SemVer {\n\tmajor: number;\n\tminor: number;\n\tpatch: number;\n\tprerelease?: SemVerPrerelease;\n}\n\nexport interface VersionEntity extends BaseEntity {\n\tbaseId: string;\n\tsignature?: string;\n\tversion: SemVer;\n}\n\nexport interface SearchMetaData {\n\t[key: string]: any;\n}\n\nexport interface SearchMetaDataEntity extends BaseEntity {\n\tsearchMetaData?: SearchMetaData;\n}\n\nexport interface ConfigElements {\n\t[key: string]: string;\n}\n\nexport interface PieModel {\n\tid: string;\n\telement: string;\n\t/**\n\t * QTI/APIP-style accessibility catalogs owned by this model's renderable fields\n\t * (prompt, choices, feedback, rationale, etc.).\n\t */\n\taccessibilityCatalogs?: AccessibilityCatalog[];\n\n\t[key: string]: any;\n}\n\nexport interface ConfigEntity {\n\tid?: string;\n\tmarkup: string;\n\telements: ConfigElements;\n\tmodels: PieModel[];\n\tconfiguration?: Record<string, any>; // NEW: Configure settings for authoring mode\n\n\t/**\n\t * QTI 3.0: Extracted accessibility catalogs from embedded SSML.\n\t * Automatically generated by SSMLExtractor when <speak> tags are found in content.\n\t */\n\textractedCatalogs?: AccessibilityCatalog[];\n\n\t[key: string]: any;\n}\n\nexport interface ConfigContainerEntity extends BaseEntity {\n\tconfig: ConfigEntity;\n}\n\nexport interface PassageEntity\n\textends VersionEntity,\n\t\tConfigContainerEntity,\n\t\tSearchMetaDataEntity {\n\tname: string;\n\t/** QTI/APIP-style accessibility catalogs owned by this passage content. */\n\taccessibilityCatalogs?: AccessibilityCatalog[];\n\tretired?: boolean;\n\tpublished?: boolean;\n\t// Search result highlights from OpenSearch (keyed by field name)\n\thighlights?: Record<string, string[]>;\n}\n\nexport interface ItemEntity\n\textends VersionEntity,\n\t\tConfigContainerEntity,\n\t\tSearchMetaDataEntity {\n\tname?: string;\n\tpassage?: string | PassageEntity;\n\t/** QTI/APIP-style accessibility catalogs owned by the item root. */\n\taccessibilityCatalogs?: AccessibilityCatalog[];\n\tretired?: boolean;\n\tpublished?: boolean;\n\tconfiguration?: any;\n\t// Search result highlights from OpenSearch (keyed by field name)\n\thighlights?: Record<string, string[]>;\n}\n\nexport interface AssignmentSessionData {\n\tassignment: AssignmentEntity;\n\tsessions: FlatSession[];\n\titems: ItemEntity[];\n\terror?: string;\n}\n\n/**\n * Metadata specifically for interpretation by clients, typically containing\n * options that are relevant for the user interface. This is not indexed for search.\n */\nexport interface SettingsMetaData {\n\t[key: string]: any;\n}\n\n/**\n * Objects that contain metadata in the settings property, which is NOT indexed for search\n * but typically only relevant for particular client cases.\n */\nexport interface SettingsMetaDataEntity {\n\tsettings?: SettingsMetaData;\n}\n\n/**\n * A reference to an item with optionally a title, settings and metadata.\n */\nexport interface QuestionEntity\n\textends SearchMetaDataEntity,\n\t\tSettingsMetaDataEntity {\n\tid?: string;\n\ttitle?: string;\n\titemVId: string;\n\titem?: ItemEntity;\n}\n\n// ============================================================================\n// QTI-aligned assessment model (QTI 2.x compatible shape)\n// ============================================================================\n\nexport type RubricBlockView =\n\t| \"author\"\n\t| \"candidate\"\n\t| \"proctor\"\n\t| \"scorer\"\n\t| \"testConstructor\"\n\t| \"tutor\";\n\nexport interface RubricBlock {\n\tidentifier?: string;\n\t/** QTI spec: space-separated list of roles; stored as an array */\n\tview: RubricBlockView[];\n\tclass?: \"stimulus\" | \"instructions\" | \"rubric\";\n\n\t/**\n\t * Versioned ID reference to the passage (when class=\"stimulus\").\n\t */\n\tpassageVId?: string;\n\n\t/**\n\t * Embedded passage entity (PIE-native approach).\n\t * The passage is rendered using the same ItemPlayer infrastructure as items.\n\t * Contains a PIE config with markup, elements, and models.\n\t */\n\tpassage?: PassageEntity;\n\n\t/**\n\t * Simple HTML content string (for basic use cases).\n\t * Alternative to the passage entity approach.\n\t */\n\tcontent?: string;\n}\n\n/**\n * QTI-aligned assessment item reference (maps to qti-assessment-item-ref).\n * References an item within a section. The item property contains the resolved\n * ItemEntity with its PIE config.\n */\nexport interface AssessmentItemRef extends SearchMetaDataEntity {\n\tid?: string;\n\tidentifier: string;\n\ttitle?: string;\n\trequired?: boolean;\n\n\t/**\n\t * Item virtual ID - stable identifier for the item across versions\n\t */\n\titemVId?: string;\n\n\t/**\n\t * Resolved item entity with PIE config.\n\t * This is populated by the client before passing to the player.\n\t */\n\titem?: ItemEntity;\n\n\t/** Item-level settings for tool requirements and customization */\n\tsettings?: ItemSettings;\n}\n\nexport interface AssessmentSection\n\textends SearchMetaDataEntity,\n\t\tSettingsMetaDataEntity {\n\tid?: string;\n\tidentifier: string;\n\ttitle?: string;\n\tvisible?: boolean;\n\trequired?: boolean;\n\t/**\n\t * QTI 3 pagination hint (`qti-assessment-section@keep-together`).\n\t *\n\t * Indicates that the delivery system SHOULD render this section's items\n\t * together rather than splitting them across pages. This is strictly a\n\t * rendering/layout hint — it does NOT disable item-level navigation,\n\t * current-item tracking, or `item-selected` events in the section player.\n\t * Paginated and keep-together sections both support Next/Back,\n\t * `getCurrentItem()`, and `item-selected` events.\n\t */\n\tkeepTogether?: boolean;\n\n\tsections?: AssessmentSection[];\n\n\t/**\n\t * QTI 3.0: Assessment item references (items in this section).\n\t * Maps to qti-assessment-item-ref in QTI 3.0 XML.\n\t */\n\tassessmentItemRefs?: AssessmentItemRef[];\n\n\t// Shared context (passages/instructions/rubrics) for this section\n\trubricBlocks?: RubricBlock[];\n\n\tsort?: string;\n}\n\nexport interface TestPart {\n\tid?: string;\n\tidentifier: string;\n\tnavigationMode: \"linear\" | \"nonlinear\";\n\tsubmissionMode: \"individual\" | \"simultaneous\";\n\tsections: AssessmentSection[];\n}\n\n// ============================================================================\n// QTI 3.0 Types\n// ============================================================================\n\nexport interface ContextDeclaration {\n\tidentifier: string;\n\tbaseType:\n\t\t| \"boolean\"\n\t\t| \"integer\"\n\t\t| \"float\"\n\t\t| \"string\"\n\t\t| \"identifier\"\n\t\t| \"point\"\n\t\t| \"pair\"\n\t\t| \"directedPair\"\n\t\t| \"duration\"\n\t\t| \"file\"\n\t\t| \"uri\";\n\tcardinality: \"single\" | \"multiple\" | \"ordered\" | \"record\";\n\tdefaultValue?: any;\n}\n\nexport interface CatalogCard {\n\tcatalog: string; // 'spoken', 'sign-language', 'braille', etc.\n\tlanguage?: string;\n\tcontent: string;\n}\n\nexport interface AccessibilityCatalog {\n\tidentifier: string;\n\tcards: CatalogCard[];\n}\n\nexport interface PersonalNeedsProfile {\n\tsupports: string[];\n\tprohibitedSupports?: string[];\n\tactivateAtInit?: string[];\n}\n\n/**\n * QTI 3.0: Reference to a shared stimulus (passage).\n * Maps to qti-assessment-stimulus-ref element.\n *\n * NOTE: Not currently used. We embed PassageEntity directly in RubricBlock instead.\n * Kept for potential future use if we need to support external stimulus references.\n */\n/*\nexport interface StimulusRef {\n\tidentifier: string;\n\thref: string;\n}\n*/\n\nexport interface AssessmentEntity extends BaseEntity, SearchMetaDataEntity {\n\tname?: string;\n\ttitle?: string;\n\tidentifier?: string;\n\tdescription?: string;\n\n\t/** Enhanced structured settings for assessment configuration */\n\tsettings?: AssessmentSettings;\n\n\t/** QTI version - '3.0' for QTI 3.0 format */\n\tqtiVersion?: \"3.0\";\n\n\t/** QTI 3.0: Context declarations (global shared variables) */\n\tcontextDeclarations?: ContextDeclaration[];\n\n\t/** QTI 3.0: Integrated APIP accessibility catalogs */\n\taccessibilityCatalogs?: AccessibilityCatalog[];\n\n\t/** QTI 3.0: Personal Needs Profile (PNP 3.0) */\n\tpersonalNeedsProfile?: PersonalNeedsProfile;\n\n\t/**\n\t * QTI 3.0: testParts structure (authoritative for QTI format).\n\t */\n\ttestParts?: TestPart[];\n\n\t/** QTI 3.0: Stimulus material references (Phase 3 - placeholder) */\n\tstimulusRefs?: any[];\n}\n\n/**\n * Enhanced settings structure for assessment configuration.\n * Provides structured fields for district policies, test administration,\n * tool configurations, and theme settings while remaining extensible.\n */\nexport interface AssessmentSettings {\n\t/** District/organization policies */\n\tdistrictPolicy?: {\n\t\tblockedTools?: string[]; // PNP support IDs that are blocked\n\t\trequiredTools?: string[]; // PNP support IDs that are required\n\t\tpolicies?: Record<string, any>;\n\t};\n\n\t/** Test administration configuration */\n\ttestAdministration?: {\n\t\tmode?: \"practice\" | \"test\" | \"benchmark\";\n\t\ttoolOverrides?: Record<string, boolean>; // Override specific PNP supports\n\t\tstartDate?: string;\n\t\tendDate?: string;\n\t};\n\n\t/** Tool-specific provider configurations */\n\ttoolConfigs?: {\n\t\t// Calculator-specific options are owned by the calculator tool package.\n\t\tcalculator?: AssessmentCalculatorConfig;\n\t\t/**\n\t\t * Text-to-speech configuration.\n\t\t *\n\t\t * Standard parameters (voice, rate, pitch) are portable across providers\n\t\t * and follow W3C Web Speech API specifications.\n\t\t *\n\t\t * Provider-specific extensions should be placed in providerOptions.\n\t\t *\n\t\t * @see https://w3c.github.io/speech-api/\n\t\t */\n\t\ttextToSpeech?: {\n\t\t\t/**\n\t\t\t * TTS provider\n\t\t\t *\n\t\t\t * @standard \"browser\" uses W3C Web Speech API\n\t\t\t * @extension \"polly\" and \"custom\" are provider-specific\n\t\t\t */\n\t\t\tprovider?: \"browser\" | \"polly\" | \"custom\";\n\n\t\t\t/**\n\t\t\t * Voice identifier (provider-specific names)\n\t\t\t *\n\t\t\t * @standard W3C Web Speech API (concept)\n\t\t\t * @example \"Joanna\" (Polly), \"en-US-Standard-A\" (Google), browser voices\n\t\t\t */\n\t\t\tvoice?: string;\n\n\t\t\t/**\n\t\t\t * Speech rate (speed multiplier)\n\t\t\t *\n\t\t\t * @standard W3C Web Speech API\n\t\t\t * @range 0.25 to 4.0\n\t\t\t * @default 1.0\n\t\t\t */\n\t\t\trate?: number;\n\n\t\t\t/**\n\t\t\t * Pitch adjustment\n\t\t\t *\n\t\t\t * @standard W3C Web Speech API\n\t\t\t * @range 0 to 2 (as multiplier)\n\t\t\t * @default 1.0\n\t\t\t */\n\t\t\tpitch?: number;\n\n\t\t\t/**\n\t\t\t * Speech Rule Engine options for generated MathML speech.\n\t\t\t *\n\t\t\t * `style` is passed to SRE directly; ClearSpeak combines multiple\n\t\t\t * preferences with \":\" (for example,\n\t\t\t * \"ImpliedTimes_MoreImpliedTimes:Paren_Silent\").\n\t\t\t *\n\t\t\t * Mirrors assessment-toolkit's SREMathSpeechOptions without importing\n\t\t\t * toolkit service types into the shared content contract package.\n\t\t\t */\n\t\t\tmathSpeech?: {\n\t\t\t\tdomain?: string;\n\t\t\t\tstyle?: string;\n\t\t\t\tengineOptions?: Record<string, unknown>;\n\t\t\t};\n\n\t\t\t/**\n\t\t\t * Provider-specific options (extensions)\n\t\t\t *\n\t\t\t * @extension Not portable across providers\n\t\t\t * @example For AWS Polly: { engine: \"neural\", region: \"us-east-1\" }\n\t\t\t * @example For Google Cloud: { audioEncoding: \"MP3\", effectsProfileId: [\"headphone-class-device\"] }\n\t\t\t */\n\t\t\tproviderOptions?: Record<string, any>;\n\t\t};\n\t\t[toolId: string]: any; // Other tool configs\n\t};\n\n\t/** Theme configuration (not in PNP) */\n\tthemeConfig?: {\n\t\tscheme?: \"default\" | \"high-contrast\" | \"dark\";\n\t\tfontSize?: number;\n\t\tfontFamily?: string;\n\t\tlineHeight?: number;\n\t\treducedMotion?: boolean;\n\t};\n\n\t/** Product-specific extensions */\n\t[key: string]: any;\n}\n\n/**\n * Calculator options exposed through assessment settings.\n * The engine is implicit (Desmos).\n */\nexport interface AssessmentCalculatorConfig {\n\ttype?: \"basic\" | \"scientific\" | \"graphing\";\n\t[key: string]: any;\n}\n\n/**\n * Item-level settings for tool requirements.\n * Used in AssessmentItemRef.settings to specify item-specific tool needs.\n */\nexport interface ItemSettings {\n\trequiredTools?: string[]; // PNP support IDs required for this item\n\trestrictedTools?: string[]; // PNP support IDs blocked for this item\n\ttoolParameters?: Record<string, any>; // Tool-specific config per item\n\n\t[key: string]: any; // Product extensions\n}\n\nexport interface SanctionedVersionEntity extends BaseEntity {\n\torganization?: string | OrganizationEntity; // if set, this is an organization specific matcher, otherwise, it's global\n\tmatch: string; // semver match expression, e.g. '1.*'\n\tpie: string; // e.g. @pie-element/calculator\n\tversion: string; // e.g. 2.14.24\n}\n\nexport enum SanctionedVersionChangeStatus {\n\tPENDING = \"pending\",\n\tIN_PROGRESS = \"in_progress\",\n\tCOMPLETED = \"completed\",\n\tFAILED = \"failed\",\n}\n\nexport interface SanctionedVersionChangeRequest {\n\tpie: string;\n\tmatch: string;\n\tversion: string;\n}\n\nexport interface SanctionedVersionChangeEntity extends BaseEntity {\n\torganization?: string | OrganizationEntity;\n\tcreatedBy: string | UserEntity;\n\tstatus: SanctionedVersionChangeStatus;\n\trequestedChanges: SanctionedVersionChangeRequest[];\n\tbeforeState: SanctionedVersionEntity[];\n\tsummary?: string;\n\tjobId: string;\n}\n\nexport type PlayerMode = \"gather\" | \"view\" | \"evaluate\" | \"author\";\n\nexport type PlayerRole = \"student\" | \"instructor\";\n\nexport interface Env {\n\tmode: PlayerMode;\n\trole: PlayerRole;\n\tpartialScoring?: boolean;\n}\n\nexport interface OutcomeResponse {\n\tid: string;\n\telement: string;\n\tscore?: number;\n\tempty?: boolean;\n\tcompleted?: boolean;\n\n\t[key: string]: any;\n}\n\nexport interface PieController {\n\tmodel(model: PieModel, sessionData: any[], env?: any): Promise<PieModel>;\n\n\toutcome(\n\t\tmodelOrSessionData: PieModel | any[],\n\t\tsessionOrEnv?: any,\n\t\tenv?: any,\n\t): Promise<OutcomeResponse>;\n\n\tscore: (config: object, session: object, env: object) => Promise<object>;\n\tcreateCorrectResponseSession: (\n\t\tconfig: object,\n\t\tenv: object,\n\t) => Promise<object>;\n\tvalidate: (model: object, config: object) => any;\n}\n\nexport interface PieItemElement {\n\t[elementName: string]: string;\n}\n\nexport type BundleInfo = {\n\turl: string;\n\thash: string;\n};\n\ninterface PieDefaultModel {\n\t// supports 'excess' properties as may be defined in pie models\n\t// https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#strict-object-literal-assignment-checking\n\t[x: string]: any;\n}\n\ninterface PieContent {\n\tid: string;\n\t/**\n\t * Set of elements to include in the pie, provided in the format `{'element-name': 'mpm-package-name'}`\n\t */\n\telements: PieItemElement;\n\n\t/** Models for each PIE included in the item */\n\tmodels: PieModel[];\n\n\tmarkup: string;\n\n\tbundle?: BundleInfo;\n\n\tdefaultExtraModels?: {\n\t\t[key: string]: PieDefaultModel;\n\t};\n}\n\ninterface AdvancedItemConfig {\n\tid: string;\n\tpie: PieContent;\n\tpassage?: PieContent;\n\tinstructorResources?: [PieContent];\n\tdefaultExtraModels?: {\n\t\t[key: string]: PieDefaultModel;\n\t};\n}\n\nexport type ItemConfig = PieContent | AdvancedItemConfig;\n\n/**\n * During the loading of elements from PIE bundles, we do a trick where we make\n * editor components available as web components by appending this to the element name.\n */\nexport const editorPostFix = \"-pie-editor--\";\n\nexport type ModelUpdatedDetail = {\n\tupdate: any;\n\treset: boolean;\n};\n\nexport class ModelUpdatedEvent extends CustomEvent<ModelUpdatedDetail> {\n\tstatic TYPE = \"model.updated\";\n\n\tconstructor(\n\t\treadonly update: any,\n\t\treadonly reset: boolean = false,\n\t) {\n\t\tsuper(ModelUpdatedEvent.TYPE, { bubbles: true, detail: { update, reset } });\n\t}\n}\n\nexport type DeleteDone = (e?: Error) => void;\n\nexport type DeleteImageDetail = {\n\tsrc: string;\n\tdone: DeleteDone;\n};\n\nexport class DeleteImageEvent extends CustomEvent<DeleteImageDetail> {\n\tstatic TYPE = \"delete.image\";\n\n\tconstructor(\n\t\treadonly src: string,\n\t\treadonly done: DeleteDone,\n\t) {\n\t\tsuper(DeleteImageEvent.TYPE, { bubbles: true, detail: { src, done } });\n\t}\n}\n\nexport interface ImageHandler {\n\tisPasted?: boolean;\n\tcancel: () => void;\n\tdone: (err?: Error, src?: string) => void;\n\tfileChosen: (file: File) => void;\n\tprogress: (percent: number, bytes: number, total: number) => void;\n}\n\nexport class InsertImageEvent extends CustomEvent<ImageHandler> {\n\tstatic TYPE = \"insert.image\";\n\n\tconstructor(readonly handler: ImageHandler) {\n\t\tsuper(InsertImageEvent.TYPE, { bubbles: true, detail: handler });\n\t}\n}\n\nexport type DeleteSoundDetail = {\n\tsrc: string;\n\tdone: DeleteDone;\n};\n\nexport class DeleteSoundEvent extends CustomEvent<DeleteSoundDetail> {\n\tstatic TYPE = \"delete.sound\";\n\n\tconstructor(\n\t\treadonly src: string,\n\t\treadonly done: DeleteDone,\n\t) {\n\t\tsuper(DeleteSoundEvent.TYPE, { bubbles: true, detail: { src, done } });\n\t}\n}\n\nexport interface SoundHandler {\n\tcancel: () => void;\n\tdone: (err?: Error, src?: string) => void;\n\tfileChosen: File;\n\tprogress: (percent: number, bytes: number, total: number) => void;\n}\n\nexport class InsertSoundEvent extends CustomEvent<SoundHandler> {\n\tstatic TYPE = \"insert.sound\";\n\n\tconstructor(readonly handler: SoundHandler) {\n\t\tsuper(InsertSoundEvent.TYPE, { bubbles: true, detail: handler });\n\t}\n}\n\nexport const isPassageEntity = (\n\tpassage: string | PassageEntity | undefined,\n): passage is PassageEntity => typeof passage === \"object\" && passage !== null;\n\nexport function isPrerelease(version: any): version is SemVer {\n\treturn (\n\t\ttypeof version === \"object\" &&\n\t\tversion !== null &&\n\t\ttypeof version.major === \"number\" &&\n\t\ttypeof version.minor === \"number\" &&\n\t\ttypeof version.patch === \"number\" &&\n\t\t!!version.prerelease && // Check if prerelease exists\n\t\ttypeof version.prerelease.tag === \"string\" &&\n\t\ttypeof version.prerelease.version === \"number\"\n\t);\n}\n\nexport function formatVersion(semVer: SemVer): string {\n\tif (!semVer) return \"\";\n\tconst base = [semVer.major, semVer.minor, semVer.patch].join(\".\");\n\tif (isPrerelease(semVer) && semVer.prerelease) {\n\t\tconst prerelease = [semVer.prerelease.tag, semVer.prerelease.version].join(\n\t\t\t\".\",\n\t\t);\n\t\treturn `${base}-${prerelease}`;\n\t}\n\treturn base;\n}\n\nexport interface PieElement extends HTMLElement {\n\tmodel: PieModel;\n\tconfiguration: any;\n\tsession: any[];\n}\n\nexport type SessionChangedDetail = {\n\tcomplete: boolean;\n\tcomponent: any;\n};\n\nexport class SessionChangedEvent extends CustomEvent<SessionChangedDetail> {\n\tstatic TYPE = \"session-changed\";\n\n\tconstructor(\n\t\treadonly component: string,\n\t\treadonly complete: boolean,\n\t) {\n\t\tsuper(SessionChangedEvent.TYPE, {\n\t\t\tbubbles: true,\n\t\t\tcomposed: true,\n\t\t\tdetail: { complete, component },\n\t\t} as any);\n\t}\n}\n\ninterface ItemCfg extends ConfigEntity {}\n\ninterface ItemWPassageCfg {\n\tpie: ItemCfg;\n\tpassage: ConfigEntity;\n}\n\nexport interface LoadResponse {\n\tjs: {\n\t\tview: string[];\n\t};\n\titem: ItemCfg | ItemWPassageCfg;\n\tsession: {\n\t\tid: string;\n\t\tdata: any[];\n\t};\n}\n\nexport interface Tracker {\n\ttrack(message: string, ...args: any[]): void;\n\n\tstart(label: string): void;\n\n\tend(label: string, metadata?: { [key: string]: any }): void;\n}\n\n/**\n * Interface for storing tracker messages with timestamps\n */\n/**\n * Interface for storing tracker messages with timestamps\n */\nexport interface TrackerMessage {\n\ttimestamp: Date;\n\tmessage: string;\n\targs: any[];\n\tformattedMessage: string; // Added formatted message with interpolated args\n}\n\n/**\n * Enhanced tracker that stores messages with timestamps\n */\nexport interface EnhancedTracker extends Tracker {\n\t/**\n\t * Get all raw tracker messages ordered by timestamp (ascending)\n\t */\n\tgetMessages(): TrackerMessage[];\n\n\t/**\n\t * Get a formatted multi-line representation of all tracker messages\n\t */\n\tgetFormattedMessages(): string;\n}\n\nexport interface ScoreResponse {\n\tsession: FlatSession;\n\tscore: SessionScore;\n\tempty?: boolean;\n\n\t[key: string]: any;\n}\n\nexport interface VersionDiff {\n\tversion: SemVer;\n\tpreviousVersion: SemVer | null;\n\tcreatedAt: Date;\n\tchanges: {\n\t\tadded: Record<string, any>;\n\t\tremoved: Record<string, any>;\n\t\tmodified: Record<\n\t\t\tstring,\n\t\t\t{\n\t\t\t\tprevious: any;\n\t\t\t\tcurrent: any;\n\t\t\t}\n\t\t>;\n\t};\n\tchangeCount: number;\n}\n\nexport interface RoleToOrganizationsMapping {\n\tid?: string;\n\trole: string;\n\torganizations: OrganizationEntity[] | string[];\n\tcreatedAt?: Date;\n\tupdatedAt?: Date;\n}\n\n// CMS Types (copied from @pie-api-aws/datastore to avoid importing server-only package)\nexport enum StandardType {\n\tROOT = 0,\n\tSUBJECT = 1,\n\tLEVEL = 2,\n\tSTANDARD = 3,\n}\n\nexport interface HierarchyInfo {\n\troot?: {\n\t\tid: string;\n\t\tguid: string;\n\t\ttitle: string;\n\t};\n\tsubject?: {\n\t\tid: string;\n\t\tguid: string;\n\t\ttitle: string;\n\t};\n\tlevel?: {\n\t\tid: string;\n\t\tguid: string;\n\t\ttitle: string;\n\t\tgrades: number[];\n\t};\n}\n\nexport interface CmsLearningStandardEntity extends BaseEntity {\n\tguid: string;\n\tabbr?: string;\n\ttype: StandardType;\n\tparentId?: string;\n\tparentGuid?: string;\n\tpath?: string;\n\tdepth: number;\n\tancestors: string[];\n\thierarchy?: HierarchyInfo;\n\ttitle?: string;\n\tdescription?: string;\n\tsequence?: string;\n\torderIndex?: number;\n\tsubjectArea?: string;\n\tsubjectName?: string;\n\tcategory?: string;\n\tabType?: string;\n\tabLabel?: string;\n\tsetName?: string;\n\tpublication?: string;\n\tadopted?: string;\n\tgrades: number[];\n\tgradeNames?: string[];\n\tproperties: Record<string, string>;\n\tstatus?: \"active\" | \"retired\" | \"deprecated\";\n\tlastModifiedAt?: Date;\n\treplacesGuid?: string;\n\treplacedByGuid?: string;\n\tdescriptionHtml?: string;\n\tlastSyncedAt?: Date;\n}\n\nexport interface ItemBankConfig {\n\tcollectionId: string;\n\tsubject?: string;\n\tgradeLevels?: number[];\n\torderIndex: number;\n}\n\nexport interface DOKDistribution {\n\tdok1?: number;\n\tdok2?: number;\n\tdok3?: number;\n\tdok4?: number;\n}\n\nexport interface AssessmentGoal {\n\tdokDistribution?: DOKDistribution;\n\tconstructedResponseCount?: number;\n\tpassageGoals?: string;\n\ttotalItemCount?: {\n\t\ttarget?: number;\n\t\tmin?: number;\n\t\tmax?: number;\n\t};\n}\n\nexport interface StudioImportMetadata {\n\tstudioAssessmentProgramId?: string;\n\tstudioPublicId?: string;\n\timportedAt?: Date;\n}\n\nexport interface CmsBlueprintEntity extends BaseEntity {\n\tname: string;\n\tdescription?: string;\n\tsubject?: string;\n\tstandardSet?: string;\n\tgradeLevels: number[];\n\tstates?: string[];\n\titemBankConfigs: ItemBankConfig[];\n\tassessmentGoal?: AssessmentGoal;\n\tclaimFramework?: \"SBAC\" | \"PARCC\" | \"STATE\" | \"CUSTOM\";\n\tclaimTargets?: string[];\n\tuseSBACClusterTarget?: boolean;\n\tclusters?: string[];\n\tstudioImportMetadata?: StudioImportMetadata;\n\toriginalPrompt?: string;\n}\n\nexport interface CmsBlueprintItemEntity extends BaseEntity {\n\tblueprintId: string;\n\tstandardGuid: string;\n\tcount: number;\n\tdetails?: string;\n\tassessmentId?: string;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * This contains copies of the data types we use in PIEOneer. These types, unlike\n * the ones in the datastore package, should not have any dependencies, and might in some\n * cases be more shallow than their originals. The main reason for these is that they should\n * be able to be used in front-end code (as well as the PIEOneer backend code).\n *\n * INCLUDING REFERENCES TO THE DATASTORE PACKAGE INSTEAD WILL MAKE PIEONEER THROW 500\n * EVERYWHERE WITHOUT ANY FURTHER EXPLANATION\n */\nexport interface BaseEntity {\n\tid?: string;\n\tcreatedAt?: Date;\n\tupdatedAt?: Date;\n}\n\nexport interface CollectionEntity extends BaseEntity {\n\tname: string;\n\torganization: string | OrganizationEntity;\n}\n\nexport interface OrganizationEntity extends BaseEntity {\n\tname: string;\n\tdefaultCollection?: string | CollectionEntity;\n}\n\nexport interface UserEntity extends BaseEntity {\n\temail: string;\n\tname?: string;\n}\n\nexport interface ClientEntity extends BaseEntity {\n\tname: string;\n\tsecret: string;\n\tuser: string | UserEntity;\n\torganization: string | OrganizationEntity;\n}\n\nexport interface AssignmentEntity extends BaseEntity {\n\torganization: string | OrganizationEntity;\n}\n\nexport interface SessionEntity extends BaseEntity {\n\titem: ItemEntity;\n\tassignment?: string | AssignmentEntity; // TODO: Remove after data is migrated\n\torganization?: string | OrganizationEntity;\n}\n\nexport enum SessionEventType {\n\tSAVE = \"save\",\n\tMODEL = \"model\",\n\tSCORE = \"score\",\n\tMANUAL_SCORE = \"manual-score\",\n}\n\nexport enum ScoreType {\n\tAUTO = \"auto\",\n\tMANUAL = \"manual\",\n}\n\nexport interface SessionScore {\n\tpoints?: number;\n\tmax?: number;\n\ttype?: ScoreType;\n\tpartialScoring?: boolean;\n\tmessage?: string;\n\terrors?: string[];\n}\n\nexport interface SessionAutoScore extends SessionScore {\n\telements?: any[];\n\textraProps?: any;\n}\n\nexport interface SessionManualScore extends SessionScore {}\n\nexport interface SessionEventEntity extends BaseEntity {\n\tsession: string | SessionEntity;\n\ttype?: SessionEventType;\n\tsaveEventId?: string;\n\tscore?: number;\n}\n\nexport enum ModeType {\n\tGATHER = \"gather\",\n\tVIEW = \"view\",\n\tEVALUATE = \"evaluate\",\n}\n\nexport interface FlatSession {\n\tid: string;\n\tassignment: AssignmentEntity;\n\titem: string;\n\tdata: any[];\n\tcreatedAt: Date;\n\tupdatedAt: Date;\n\tmode: ModeType;\n\tautoScore: SessionAutoScore;\n\tmanualScore: SessionManualScore;\n\tevents: SessionEventEntity[]; // raw events;\n}\n\nexport interface SemVerPrerelease {\n\ttag: string;\n\tversion: number;\n}\n\nexport interface SemVer {\n\tmajor: number;\n\tminor: number;\n\tpatch: number;\n\tprerelease?: SemVerPrerelease;\n}\n\nexport interface VersionEntity extends BaseEntity {\n\tbaseId: string;\n\tsignature?: string;\n\tversion: SemVer;\n}\n\nexport interface SearchMetaData {\n\t[key: string]: any;\n}\n\nexport interface SearchMetaDataEntity extends BaseEntity {\n\tsearchMetaData?: SearchMetaData;\n}\n\nexport interface ConfigElements {\n\t[key: string]: string;\n}\n\nexport interface PieModel {\n\tid: string;\n\telement: string;\n\t/**\n\t * QTI/APIP-style accessibility catalogs owned by this model's renderable fields\n\t * (prompt, choices, feedback, rationale, etc.).\n\t */\n\taccessibilityCatalogs?: AccessibilityCatalog[];\n\n\t[key: string]: any;\n}\n\nexport interface ConfigEntity {\n\tid?: string;\n\tmarkup: string;\n\telements: ConfigElements;\n\tmodels: PieModel[];\n\tconfiguration?: Record<string, any>; // NEW: Configure settings for authoring mode\n\n\t/**\n\t * QTI 3.0: Extracted accessibility catalogs from embedded SSML.\n\t * Automatically generated by SSMLExtractor when <speak> tags are found in content.\n\t */\n\textractedCatalogs?: AccessibilityCatalog[];\n\n\t[key: string]: any;\n}\n\nexport interface ConfigContainerEntity extends BaseEntity {\n\tconfig: ConfigEntity;\n}\n\nexport interface PassageEntity\n\textends VersionEntity,\n\t\tConfigContainerEntity,\n\t\tSearchMetaDataEntity {\n\tname: string;\n\t/** QTI/APIP-style accessibility catalogs owned by this passage content. */\n\taccessibilityCatalogs?: AccessibilityCatalog[];\n\tretired?: boolean;\n\tpublished?: boolean;\n\t// Search result highlights from OpenSearch (keyed by field name)\n\thighlights?: Record<string, string[]>;\n}\n\nexport interface ItemEntity\n\textends VersionEntity,\n\t\tConfigContainerEntity,\n\t\tSearchMetaDataEntity {\n\tname?: string;\n\tpassage?: string | PassageEntity;\n\t/** QTI/APIP-style accessibility catalogs owned by the item root. */\n\taccessibilityCatalogs?: AccessibilityCatalog[];\n\tretired?: boolean;\n\tpublished?: boolean;\n\tconfiguration?: any;\n\t// Search result highlights from OpenSearch (keyed by field name)\n\thighlights?: Record<string, string[]>;\n}\n\nexport interface AssignmentSessionData {\n\tassignment: AssignmentEntity;\n\tsessions: FlatSession[];\n\titems: ItemEntity[];\n\terror?: string;\n}\n\n/**\n * Metadata specifically for interpretation by clients, typically containing\n * options that are relevant for the user interface. This is not indexed for search.\n */\nexport interface SettingsMetaData {\n\t[key: string]: any;\n}\n\n/**\n * Objects that contain metadata in the settings property, which is NOT indexed for search\n * but typically only relevant for particular client cases.\n */\nexport interface SettingsMetaDataEntity {\n\tsettings?: SettingsMetaData;\n}\n\n/**\n * A reference to an item with optionally a title, settings and metadata.\n */\nexport interface QuestionEntity\n\textends SearchMetaDataEntity,\n\t\tSettingsMetaDataEntity {\n\tid?: string;\n\ttitle?: string;\n\titemVId: string;\n\titem?: ItemEntity;\n}\n\n// ============================================================================\n// QTI-aligned assessment model (QTI 2.x compatible shape)\n// ============================================================================\n\nexport type RubricBlockView =\n\t| \"author\"\n\t| \"candidate\"\n\t| \"proctor\"\n\t| \"scorer\"\n\t| \"testConstructor\"\n\t| \"tutor\";\n\nexport interface RubricBlock {\n\tidentifier?: string;\n\t/** QTI spec: space-separated list of roles; stored as an array */\n\tview: RubricBlockView[];\n\tclass?: \"stimulus\" | \"instructions\" | \"rubric\";\n\n\t/**\n\t * Versioned ID reference to the passage (when class=\"stimulus\").\n\t */\n\tpassageVId?: string;\n\n\t/**\n\t * Embedded passage entity (PIE-native approach).\n\t * The passage is rendered using the same ItemPlayer infrastructure as items.\n\t * Contains a PIE config with markup, elements, and models.\n\t */\n\tpassage?: PassageEntity;\n\n\t/**\n\t * Simple HTML content string (for basic use cases).\n\t * Alternative to the passage entity approach.\n\t */\n\tcontent?: string;\n}\n\n/**\n * QTI-aligned assessment item reference (maps to qti-assessment-item-ref).\n * References an item within a section. The item property contains the resolved\n * ItemEntity with its PIE config.\n */\nexport interface AssessmentItemRef extends SearchMetaDataEntity {\n\tid?: string;\n\tidentifier: string;\n\ttitle?: string;\n\trequired?: boolean;\n\n\t/**\n\t * Item virtual ID - stable identifier for the item across versions\n\t */\n\titemVId?: string;\n\n\t/**\n\t * Resolved item entity with PIE config.\n\t * This is populated by the client before passing to the player.\n\t */\n\titem?: ItemEntity;\n\n\t/** Item-level settings for tool requirements and customization */\n\tsettings?: ItemSettings;\n}\n\nexport interface AssessmentSection\n\textends SearchMetaDataEntity,\n\t\tSettingsMetaDataEntity {\n\tid?: string;\n\tidentifier: string;\n\ttitle?: string;\n\tvisible?: boolean;\n\trequired?: boolean;\n\t/**\n\t * QTI 3 pagination hint (`qti-assessment-section@keep-together`).\n\t *\n\t * Indicates that the delivery system SHOULD render this section's items\n\t * together rather than splitting them across pages. This is strictly a\n\t * rendering/layout hint — it does NOT disable item-level navigation,\n\t * current-item tracking, or `item-selected` events in the section player.\n\t * Paginated and keep-together sections both support Next/Back,\n\t * `getCurrentItem()`, and `item-selected` events.\n\t */\n\tkeepTogether?: boolean;\n\n\tsections?: AssessmentSection[];\n\n\t/**\n\t * QTI 3.0: Assessment item references (items in this section).\n\t * Maps to qti-assessment-item-ref in QTI 3.0 XML.\n\t */\n\tassessmentItemRefs?: AssessmentItemRef[];\n\n\t// Shared context (passages/instructions/rubrics) for this section\n\trubricBlocks?: RubricBlock[];\n\n\tsort?: string;\n}\n\nexport interface TestPart {\n\tid?: string;\n\tidentifier: string;\n\tnavigationMode: \"linear\" | \"nonlinear\";\n\tsubmissionMode: \"individual\" | \"simultaneous\";\n\tsections: AssessmentSection[];\n}\n\n// ============================================================================\n// QTI 3.0 Types\n// ============================================================================\n\nexport interface ContextDeclaration {\n\tidentifier: string;\n\tbaseType:\n\t\t| \"boolean\"\n\t\t| \"integer\"\n\t\t| \"float\"\n\t\t| \"string\"\n\t\t| \"identifier\"\n\t\t| \"point\"\n\t\t| \"pair\"\n\t\t| \"directedPair\"\n\t\t| \"duration\"\n\t\t| \"file\"\n\t\t| \"uri\";\n\tcardinality: \"single\" | \"multiple\" | \"ordered\" | \"record\";\n\tdefaultValue?: any;\n}\n\nexport interface CatalogCard {\n\tcatalog: string; // 'spoken', 'sign-language', 'braille', etc.\n\tlanguage?: string;\n\tcontent: string;\n}\n\nexport interface AccessibilityCatalog {\n\tidentifier: string;\n\tcards: CatalogCard[];\n}\n\nexport interface PersonalNeedsProfile {\n\tsupports: string[];\n\tprohibitedSupports?: string[];\n\tactivateAtInit?: string[];\n}\n\n/**\n * QTI 3.0: Reference to a shared stimulus (passage).\n * Maps to qti-assessment-stimulus-ref element.\n *\n * NOTE: Not currently used. We embed PassageEntity directly in RubricBlock instead.\n * Kept for potential future use if we need to support external stimulus references.\n */\n/*\nexport interface StimulusRef {\n\tidentifier: string;\n\thref: string;\n}\n*/\n\nexport interface AssessmentEntity extends BaseEntity, SearchMetaDataEntity {\n\tname?: string;\n\ttitle?: string;\n\tidentifier?: string;\n\tdescription?: string;\n\n\t/** Enhanced structured settings for assessment configuration */\n\tsettings?: AssessmentSettings;\n\n\t/** QTI version - '3.0' for QTI 3.0 format */\n\tqtiVersion?: \"3.0\";\n\n\t/** QTI 3.0: Context declarations (global shared variables) */\n\tcontextDeclarations?: ContextDeclaration[];\n\n\t/** QTI 3.0: Integrated APIP accessibility catalogs */\n\taccessibilityCatalogs?: AccessibilityCatalog[];\n\n\t/** QTI 3.0: Personal Needs Profile (PNP 3.0) */\n\tpersonalNeedsProfile?: PersonalNeedsProfile;\n\n\t/**\n\t * QTI 3.0: testParts structure (authoritative for QTI format).\n\t */\n\ttestParts?: TestPart[];\n\n\t/** QTI 3.0: Stimulus material references (Phase 3 - placeholder) */\n\tstimulusRefs?: any[];\n}\n\n/**\n * Enhanced settings structure for assessment configuration.\n * Provides structured fields for district policies, test administration,\n * tool configurations, and theme settings while remaining extensible.\n */\nexport interface AssessmentSettings {\n\t/** District/organization policies */\n\tdistrictPolicy?: {\n\t\tblockedTools?: string[]; // PNP support IDs that are blocked\n\t\trequiredTools?: string[]; // PNP support IDs that are required\n\t\tpolicies?: Record<string, any>;\n\t};\n\n\t/** Test administration configuration */\n\ttestAdministration?: {\n\t\tmode?: \"practice\" | \"test\" | \"benchmark\";\n\t\ttoolOverrides?: Record<string, boolean>; // Override specific PNP supports\n\t\tstartDate?: string;\n\t\tendDate?: string;\n\t};\n\n\t/** Tool-specific provider configurations */\n\ttoolConfigs?: {\n\t\t// Calculator-specific options are owned by the calculator tool package.\n\t\tcalculator?: AssessmentCalculatorConfig;\n\t\t/**\n\t\t * Text-to-speech configuration.\n\t\t *\n\t\t * Standard parameters (voice, rate, pitch) are portable across providers\n\t\t * and follow W3C Web Speech API specifications.\n\t\t *\n\t\t * Provider-specific extensions should be placed in providerOptions.\n\t\t *\n\t\t * @see https://w3c.github.io/speech-api/\n\t\t */\n\t\ttextToSpeech?: {\n\t\t\t/**\n\t\t\t * TTS provider\n\t\t\t *\n\t\t\t * @standard \"browser\" uses W3C Web Speech API\n\t\t\t * @extension \"polly\" and \"custom\" are provider-specific\n\t\t\t */\n\t\t\tprovider?: \"browser\" | \"polly\" | \"custom\";\n\n\t\t\t/**\n\t\t\t * Voice identifier (provider-specific names)\n\t\t\t *\n\t\t\t * @standard W3C Web Speech API (concept)\n\t\t\t * @example \"Joanna\" (Polly), \"en-US-Standard-A\" (Google), browser voices\n\t\t\t */\n\t\t\tvoice?: string;\n\n\t\t\t/**\n\t\t\t * Speech rate (speed multiplier)\n\t\t\t *\n\t\t\t * @standard W3C Web Speech API\n\t\t\t * @range 0.25 to 4.0\n\t\t\t * @default 1.0\n\t\t\t */\n\t\t\trate?: number;\n\n\t\t\t/**\n\t\t\t * Pitch adjustment\n\t\t\t *\n\t\t\t * @standard W3C Web Speech API\n\t\t\t * @range 0 to 2 (as multiplier)\n\t\t\t * @default 1.0\n\t\t\t */\n\t\t\tpitch?: number;\n\n\t\t\t/**\n\t\t\t * Speech Rule Engine options for generated MathML speech.\n\t\t\t *\n\t\t\t * `style` is passed to SRE directly; ClearSpeak combines multiple\n\t\t\t * preferences with \":\" (for example,\n\t\t\t * \"ImpliedTimes_MoreImpliedTimes:Paren_Silent\").\n\t\t\t *\n\t\t\t * Mirrors assessment-toolkit's SREMathSpeechOptions without importing\n\t\t\t * toolkit service types into the shared content contract package.\n\t\t\t */\n\t\t\tmathSpeech?: {\n\t\t\t\tdomain?: string;\n\t\t\t\tstyle?: string;\n\t\t\t\tengineOptions?: Record<string, unknown>;\n\t\t\t};\n\n\t\t\t/**\n\t\t\t * Provider-specific options (extensions)\n\t\t\t *\n\t\t\t * @extension Not portable across providers\n\t\t\t * @example For AWS Polly: { engine: \"neural\", region: \"us-east-1\" }\n\t\t\t * @example For Google Cloud: { audioEncoding: \"MP3\", effectsProfileId: [\"headphone-class-device\"] }\n\t\t\t */\n\t\t\tproviderOptions?: Record<string, any>;\n\t\t};\n\t\t[toolId: string]: any; // Other tool configs\n\t};\n\n\t/** Theme configuration (not in PNP) */\n\tthemeConfig?: {\n\t\tscheme?: \"default\" | \"high-contrast\" | \"dark\";\n\t\tfontSize?: number;\n\t\tfontFamily?: string;\n\t\tlineHeight?: number;\n\t\treducedMotion?: boolean;\n\t};\n\n\t/** Product-specific extensions */\n\t[key: string]: any;\n}\n\n/**\n * Calculator options exposed through assessment settings.\n * The engine is implicit (Desmos).\n */\nexport interface AssessmentCalculatorConfig {\n\ttype?: \"basic\" | \"scientific\" | \"graphing\";\n\t[key: string]: any;\n}\n\n/**\n * Item-level settings for tool requirements.\n * Used in AssessmentItemRef.settings to specify item-specific tool needs.\n */\nexport interface ItemSettings {\n\trequiredTools?: string[]; // PNP support IDs required for this item\n\trestrictedTools?: string[]; // PNP support IDs blocked for this item\n\ttoolParameters?: Record<string, any>; // Tool-specific config per item\n\n\t[key: string]: any; // Product extensions\n}\n\nexport interface SanctionedVersionEntity extends BaseEntity {\n\torganization?: string | OrganizationEntity; // if set, this is an organization specific matcher, otherwise, it's global\n\tmatch: string; // semver match expression, e.g. '1.*'\n\tpie: string; // e.g. @pie-element/calculator\n\tversion: string; // e.g. 2.14.24\n}\n\nexport enum SanctionedVersionChangeStatus {\n\tPENDING = \"pending\",\n\tIN_PROGRESS = \"in_progress\",\n\tCOMPLETED = \"completed\",\n\tFAILED = \"failed\",\n}\n\nexport interface SanctionedVersionChangeRequest {\n\tpie: string;\n\tmatch: string;\n\tversion: string;\n}\n\nexport interface SanctionedVersionChangeEntity extends BaseEntity {\n\torganization?: string | OrganizationEntity;\n\tcreatedBy: string | UserEntity;\n\tstatus: SanctionedVersionChangeStatus;\n\trequestedChanges: SanctionedVersionChangeRequest[];\n\tbeforeState: SanctionedVersionEntity[];\n\tsummary?: string;\n\tjobId: string;\n}\n\nexport type PlayerMode = \"gather\" | \"view\" | \"evaluate\" | \"author\";\n\nexport type PlayerRole = \"student\" | \"instructor\";\n\nexport interface Env {\n\tmode: PlayerMode;\n\trole: PlayerRole;\n\tpartialScoring?: boolean;\n}\n\nexport interface OutcomeResponse {\n\tid: string;\n\telement: string;\n\tscore?: number;\n\tempty?: boolean;\n\tcompleted?: boolean;\n\n\t[key: string]: any;\n}\n\nexport interface PieController {\n\tmodel(model: PieModel, sessionData: any[], env?: any): Promise<PieModel>;\n\n\toutcome(\n\t\tmodelOrSessionData: PieModel | any[],\n\t\tsessionOrEnv?: any,\n\t\tenv?: any,\n\t): Promise<OutcomeResponse>;\n\n\tscore: (config: object, session: object, env: object) => Promise<object>;\n\tcreateCorrectResponseSession: (\n\t\tconfig: object,\n\t\tenv: object,\n\t) => Promise<object>;\n\tvalidate: (model: object, config: object) => any;\n}\n\nexport interface PieItemElement {\n\t[elementName: string]: string;\n}\n\nexport type BundleInfo = {\n\turl: string;\n\thash: string;\n};\n\nexport type ItemSession = {\n\tid: string;\n\tdata: any[];\n};\n\nexport interface PieDefaultModel {\n\t// supports 'excess' properties as may be defined in pie models\n\t// https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#strict-object-literal-assignment-checking\n\t[x: string]: any;\n}\n\nexport interface PieContent {\n\tid: string;\n\t/**\n\t * Set of elements to include in the pie, provided in the format `{'element-name': 'mpm-package-name'}`\n\t */\n\telements: PieItemElement;\n\n\t/** Models for each PIE included in the item */\n\tmodels: PieModel[];\n\n\tmarkup: string;\n\n\tbundle?: BundleInfo;\n\n\tresources?: ConfigResource;\n\n\tdefaultExtraModels?: {\n\t\t[key: string]: PieDefaultModel;\n\t};\n}\n\nexport interface ConfigResource {\n\tstylesheets?: {\n\t\turl: string;\n\t}[];\n\tcontainerClass?: string;\n\tpassageContainerClass?: string;\n}\n\nexport interface AdvancedItemConfig {\n\tid: string;\n\tpie: PieContent;\n\tpassage?: PieContent;\n\tinstructorResources?: [PieContent];\n\tdefaultExtraModels?: {\n\t\t[key: string]: PieDefaultModel;\n\t};\n}\n\nexport type ItemConfig = PieContent | AdvancedItemConfig;\n\n/**\n * During the loading of elements from PIE bundles, we do a trick where we make\n * editor components available as web components by appending this to the element name.\n */\nexport const editorPostFix = \"-pie-editor--\";\n\nexport type ModelUpdatedDetail = {\n\tupdate: any;\n\treset: boolean;\n};\n\nexport class ModelUpdatedEvent extends CustomEvent<ModelUpdatedDetail> {\n\tstatic TYPE = \"model.updated\";\n\n\tconstructor(\n\t\treadonly update: any,\n\t\treadonly reset: boolean = false,\n\t) {\n\t\tsuper(ModelUpdatedEvent.TYPE, { bubbles: true, detail: { update, reset } });\n\t}\n}\n\nexport type DeleteDone = (e?: Error) => void;\n\nexport type DeleteImageDetail = {\n\tsrc: string;\n\tdone: DeleteDone;\n};\n\nexport class DeleteImageEvent extends CustomEvent<DeleteImageDetail> {\n\tstatic TYPE = \"delete.image\";\n\n\tconstructor(\n\t\treadonly src: string,\n\t\treadonly done: DeleteDone,\n\t) {\n\t\tsuper(DeleteImageEvent.TYPE, { bubbles: true, detail: { src, done } });\n\t}\n}\n\nexport interface ImageHandler {\n\tisPasted?: boolean;\n\tcancel: () => void;\n\tdone: (err?: Error, src?: string) => void;\n\tfileChosen: (file: File) => void;\n\tprogress: (percent: number, bytes: number, total: number) => void;\n}\n\nexport class InsertImageEvent extends CustomEvent<ImageHandler> {\n\tstatic TYPE = \"insert.image\";\n\n\tconstructor(readonly handler: ImageHandler) {\n\t\tsuper(InsertImageEvent.TYPE, { bubbles: true, detail: handler });\n\t}\n}\n\nexport type DeleteSoundDetail = {\n\tsrc: string;\n\tdone: DeleteDone;\n};\n\nexport class DeleteSoundEvent extends CustomEvent<DeleteSoundDetail> {\n\tstatic TYPE = \"delete.sound\";\n\n\tconstructor(\n\t\treadonly src: string,\n\t\treadonly done: DeleteDone,\n\t) {\n\t\tsuper(DeleteSoundEvent.TYPE, { bubbles: true, detail: { src, done } });\n\t}\n}\n\nexport interface SoundHandler {\n\tcancel: () => void;\n\tdone: (err?: Error, src?: string) => void;\n\tfileChosen: File;\n\tprogress: (percent: number, bytes: number, total: number) => void;\n}\n\nexport class InsertSoundEvent extends CustomEvent<SoundHandler> {\n\tstatic TYPE = \"insert.sound\";\n\n\tconstructor(readonly handler: SoundHandler) {\n\t\tsuper(InsertSoundEvent.TYPE, { bubbles: true, detail: handler });\n\t}\n}\n\nexport const isPassageEntity = (\n\tpassage: string | PassageEntity | undefined,\n): passage is PassageEntity => typeof passage === \"object\" && passage !== null;\n\nexport function isPrerelease(version: any): version is SemVer {\n\treturn (\n\t\ttypeof version === \"object\" &&\n\t\tversion !== null &&\n\t\ttypeof version.major === \"number\" &&\n\t\ttypeof version.minor === \"number\" &&\n\t\ttypeof version.patch === \"number\" &&\n\t\t!!version.prerelease && // Check if prerelease exists\n\t\ttypeof version.prerelease.tag === \"string\" &&\n\t\ttypeof version.prerelease.version === \"number\"\n\t);\n}\n\nexport function formatVersion(semVer: SemVer): string {\n\tif (!semVer) return \"\";\n\tconst base = [semVer.major, semVer.minor, semVer.patch].join(\".\");\n\tif (isPrerelease(semVer) && semVer.prerelease) {\n\t\tconst prerelease = [semVer.prerelease.tag, semVer.prerelease.version].join(\n\t\t\t\".\",\n\t\t);\n\t\treturn `${base}-${prerelease}`;\n\t}\n\treturn base;\n}\n\nexport interface PieElement extends HTMLElement {\n\tmodel: PieModel;\n\tconfiguration: any;\n\tsession: any[];\n}\n\nexport type SessionChangedDetail = {\n\tcomplete: boolean;\n\tcomponent: any;\n};\n\nexport class SessionChangedEvent extends CustomEvent<SessionChangedDetail> {\n\tstatic TYPE = \"session-changed\";\n\n\tconstructor(\n\t\treadonly component: string,\n\t\treadonly complete: boolean,\n\t) {\n\t\tsuper(SessionChangedEvent.TYPE, {\n\t\t\tbubbles: true,\n\t\t\tcomposed: true,\n\t\t\tdetail: { complete, component },\n\t\t} as any);\n\t}\n}\n\ninterface ItemCfg extends ConfigEntity {}\n\ninterface ItemWPassageCfg {\n\tpie: ItemCfg;\n\tpassage: ConfigEntity;\n}\n\nexport interface LoadResponse {\n\tjs: {\n\t\tview: string[];\n\t};\n\titem: ItemCfg | ItemWPassageCfg;\n\tsession: {\n\t\tid: string;\n\t\tdata: any[];\n\t};\n}\n\nexport interface Tracker {\n\ttrack(message: string, ...args: any[]): void;\n\n\tstart(label: string): void;\n\n\tend(label: string, metadata?: { [key: string]: any }): void;\n}\n\n/**\n * Interface for storing tracker messages with timestamps\n */\n/**\n * Interface for storing tracker messages with timestamps\n */\nexport interface TrackerMessage {\n\ttimestamp: Date;\n\tmessage: string;\n\targs: any[];\n\tformattedMessage: string; // Added formatted message with interpolated args\n}\n\n/**\n * Enhanced tracker that stores messages with timestamps\n */\nexport interface EnhancedTracker extends Tracker {\n\t/**\n\t * Get all raw tracker messages ordered by timestamp (ascending)\n\t */\n\tgetMessages(): TrackerMessage[];\n\n\t/**\n\t * Get a formatted multi-line representation of all tracker messages\n\t */\n\tgetFormattedMessages(): string;\n}\n\nexport interface ScoreResponse {\n\tsession: FlatSession;\n\tscore: SessionScore;\n\tempty?: boolean;\n\n\t[key: string]: any;\n}\n\nexport interface VersionDiff {\n\tversion: SemVer;\n\tpreviousVersion: SemVer | null;\n\tcreatedAt: Date;\n\tchanges: {\n\t\tadded: Record<string, any>;\n\t\tremoved: Record<string, any>;\n\t\tmodified: Record<\n\t\t\tstring,\n\t\t\t{\n\t\t\t\tprevious: any;\n\t\t\t\tcurrent: any;\n\t\t\t}\n\t\t>;\n\t};\n\tchangeCount: number;\n}\n\nexport interface RoleToOrganizationsMapping {\n\tid?: string;\n\trole: string;\n\torganizations: OrganizationEntity[] | string[];\n\tcreatedAt?: Date;\n\tupdatedAt?: Date;\n}\n\n// CMS Types (copied from @pie-api-aws/datastore to avoid importing server-only package)\nexport enum StandardType {\n\tROOT = 0,\n\tSUBJECT = 1,\n\tLEVEL = 2,\n\tSTANDARD = 3,\n}\n\nexport interface HierarchyInfo {\n\troot?: {\n\t\tid: string;\n\t\tguid: string;\n\t\ttitle: string;\n\t};\n\tsubject?: {\n\t\tid: string;\n\t\tguid: string;\n\t\ttitle: string;\n\t};\n\tlevel?: {\n\t\tid: string;\n\t\tguid: string;\n\t\ttitle: string;\n\t\tgrades: number[];\n\t};\n}\n\nexport interface CmsLearningStandardEntity extends BaseEntity {\n\tguid: string;\n\tabbr?: string;\n\ttype: StandardType;\n\tparentId?: string;\n\tparentGuid?: string;\n\tpath?: string;\n\tdepth: number;\n\tancestors: string[];\n\thierarchy?: HierarchyInfo;\n\ttitle?: string;\n\tdescription?: string;\n\tsequence?: string;\n\torderIndex?: number;\n\tsubjectArea?: string;\n\tsubjectName?: string;\n\tcategory?: string;\n\tabType?: string;\n\tabLabel?: string;\n\tsetName?: string;\n\tpublication?: string;\n\tadopted?: string;\n\tgrades: number[];\n\tgradeNames?: string[];\n\tproperties: Record<string, string>;\n\tstatus?: \"active\" | \"retired\" | \"deprecated\";\n\tlastModifiedAt?: Date;\n\treplacesGuid?: string;\n\treplacedByGuid?: string;\n\tdescriptionHtml?: string;\n\tlastSyncedAt?: Date;\n}\n\nexport interface ItemBankConfig {\n\tcollectionId: string;\n\tsubject?: string;\n\tgradeLevels?: number[];\n\torderIndex: number;\n}\n\nexport interface DOKDistribution {\n\tdok1?: number;\n\tdok2?: number;\n\tdok3?: number;\n\tdok4?: number;\n}\n\nexport interface AssessmentGoal {\n\tdokDistribution?: DOKDistribution;\n\tconstructedResponseCount?: number;\n\tpassageGoals?: string;\n\ttotalItemCount?: {\n\t\ttarget?: number;\n\t\tmin?: number;\n\t\tmax?: number;\n\t};\n}\n\nexport interface StudioImportMetadata {\n\tstudioAssessmentProgramId?: string;\n\tstudioPublicId?: string;\n\timportedAt?: Date;\n}\n\nexport interface CmsBlueprintEntity extends BaseEntity {\n\tname: string;\n\tdescription?: string;\n\tsubject?: string;\n\tstandardSet?: string;\n\tgradeLevels: number[];\n\tstates?: string[];\n\titemBankConfigs: ItemBankConfig[];\n\tassessmentGoal?: AssessmentGoal;\n\tclaimFramework?: \"SBAC\" | \"PARCC\" | \"STATE\" | \"CUSTOM\";\n\tclaimTargets?: string[];\n\tuseSBACClusterTarget?: boolean;\n\tclusters?: string[];\n\tstudioImportMetadata?: StudioImportMetadata;\n\toriginalPrompt?: string;\n}\n\nexport interface CmsBlueprintItemEntity extends BaseEntity {\n\tblueprintId: string;\n\tstandardGuid: string;\n\tcount: number;\n\tdetails?: string;\n\tassessmentId?: string;\n}\n"]}
|