{"version":3,"file":"index.cjs","sources":["../src/errors.ts","../src/utils.ts","../src/index.ts"],"sourcesContent":["/** When a trial type is accidentally undefined. */\nexport class UndefinedTypeError extends Error {\n  /**\n   * Inform user that one of their timeline trial objects is missing the type\n   * parameter.\n   *\n   * @param object - Timeline object with a type key whose value is\n   *   null/undefined.\n   */\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  public constructor(object: Record<string, any>) {\n    super(\n      `A trial object in the timeline has an undefined type. Maybe the type name is misspelled, or the plugin you want to use is not supported. Object: ${JSON.stringify(object)}.`,\n    );\n  }\n}\n\n/** When a timeline element is incorrectly formatted. */\nexport class UndefinedTimelineError extends Error {\n  /**\n   * Inform user that one of the elements on their timeline is formatted\n   * incorrectly.\n   *\n   * @param el - Element in the timeline. Likely a timeline node with an\n   *   incorrect timeline value, or trial object with missing type key/value.\n   */\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  public constructor(el: any) {\n    super(\n      `An element in the timeline is not structured correctly or is missing required information. It may be a timeline node with a timeline array that is the wrong type or missing/undefined, or a trial object with a missing type. Element: ${JSON.stringify(el)}`,\n    );\n  }\n}\n\n/**\n * Error when the jsPsych instance is not accessible in the on data update\n * callback closure.\n */\nexport class NoJsPsychInstanceError extends Error {\n  /**\n   * Error when the jsPsych instance is not available in the on data update\n   * callback closure. The instance needs to be passed into the actual\n   * on_data_update callback in order to get all of the experiment data.\n   */\n  public constructor() {\n    super(\"No jsPsych instance available for on_data_update.\");\n    this.name = \"NoJsPsychInstanceError\";\n  }\n}\n","import Api from \"@lookit/data\";\nimport { JsPsychExpData, LookitWindow } from \"@lookit/data/dist/types\";\nimport chsTemplates from \"@lookit/templates\";\nimport { DataCollection, JsPsych } from \"jspsych\";\nimport { NoJsPsychInstanceError } from \"./errors\";\nimport { UserFuncOnDataUpdate, UserFuncOnFinish } from \"./types\";\n\ndeclare let window: LookitWindow;\n\n/**\n * Function that returns a function to be used in place of jsPsych's option\n * \"on_data_update\". \"userFunc\" should be the user's implementation of\n * \"on_data_update\". Since this is the data that is returned from each trial,\n * this function will get the collected trial data and append the current data\n * point.\n *\n * @param jsPsychInstance - JsPsych instance\n * @param responseUuid - Response UUID.\n * @param userFunc - \"on data update\" function provided by researcher.\n * @returns On data update function.\n */\nexport const on_data_update = (\n  jsPsychInstance: JsPsych | undefined | null,\n  responseUuid: string,\n  userFunc?: UserFuncOnDataUpdate,\n) => {\n  return async function (data: JsPsychExpData) {\n    if (!jsPsychInstance || !jsPsychInstance.data) {\n      throw new NoJsPsychInstanceError();\n    }\n\n    await Api.updateResponse(responseUuid, {\n      exp_data: jsPsychInstance.data.get().values() as JsPsychExpData[],\n    });\n    await Api.finish();\n\n    // Don't call the function if not defined by user.\n    if (typeof userFunc === \"function\") {\n      userFunc(data);\n    }\n  };\n};\n\n/**\n * Function that returns a function to be used in place of jsPsych's option\n * \"on_finish\". \"userFunc\" should be the user's implementation of \"on_finish\".\n * Since this is point where the experiment has ended, the function will set\n * \"completed\" to true and overwrites all experiment data with the full set of\n * collected data. Once the user function has been ran, this will redirect to\n * the study's exit url.\n *\n * @param jsPsychInstance - JsPsych instance\n * @param responseUuid - Response UUID.\n * @param userFunc - \"on finish\" function provided by the researcher.\n * @returns On finish function.\n */\nexport const on_finish = (\n  jsPsychInstance: JsPsych | undefined | null,\n  responseUuid: string,\n  userFunc?: UserFuncOnFinish,\n) => {\n  return async function (data: DataCollection) {\n    // add loading animation while data/video saving finishes\n    if (!jsPsychInstance || !jsPsychInstance.getDisplayElement) {\n      throw new NoJsPsychInstanceError();\n    }\n    jsPsychInstance.getDisplayElement().innerHTML =\n      chsTemplates.loadingAnimation();\n\n    const exp_data: JsPsychExpData[] = data.values();\n\n    const { exit_url } = window.chs.study.attributes;\n\n    // Don't call the function if not defined by user.\n    if (typeof userFunc === \"function\") {\n      userFunc(data);\n    }\n\n    try {\n      await Api.updateResponse(responseUuid, {\n        exp_data,\n        completed: true,\n      });\n      await Api.finish();\n      if (window.chs.pendingUploads) {\n        await Promise.allSettled(\n          window.chs.pendingUploads.map((u) => u.promise),\n        );\n      }\n      if (exit_url) {\n        let url: URL;\n        try {\n          url = new URL(exit_url);\n        } catch {\n          try {\n            url = new URL(`https://${exit_url}`);\n          } catch {\n            url = new URL(window.location.origin);\n          }\n        }\n        const hash_child_id = window.chs.response.attributes.hash_child_id;\n        if (hash_child_id) url.searchParams.set(\"child\", hash_child_id);\n        url.searchParams.set(\"response\", window.chs.response.id);\n        window.location.replace(url.toString());\n      }\n    } catch (err) {\n      console.error(\n        \"Error while finishing the experiment and saving data/video: \",\n        err,\n      );\n    }\n  };\n};\n","import { JsPsychExpData } from \"@lookit/data/dist/types\";\nimport type { DataCollection, JsPsych as JsPsychType } from \"jspsych\";\nimport * as jspsychModule from \"jspsych\";\nimport type { TimelineArray } from \"jspsych/src/timeline\";\nimport { UndefinedTimelineError, UndefinedTypeError } from \"./errors\";\nimport type {\n  ChsJsPsych,\n  ChsTimelineArray,\n  ChsTimelineDescription,\n  ChsTrialDescription,\n  JsPsychOptions,\n} from \"./types\";\nimport { on_data_update, on_finish } from \"./utils\";\n\n/**\n * Checks if the given description is a timeline array or description (node),\n * both of which might contain trial descriptions. Modified from\n * isTimelineDescription in jspsych/src/timeline to exclude trial descriptions\n * with nested timelines (jsPsych returns true for trial description objects\n * that have a \"type\" property and a nested timelines, but we need to return\n * false.)\n *\n * @param description - The description array or object to check.\n * @returns True if the description is a timeline array or timeline description\n *   (object with \"timeline\" key but no \"type\" key), otherwise false.\n */\nconst isTimelineNodeArray = (\n  description: ChsTrialDescription | ChsTimelineDescription | ChsTimelineArray,\n) => {\n  return (\n    (Boolean((description as ChsTimelineDescription).timeline) ||\n      Array.isArray(description)) &&\n    !(description as ChsTimelineDescription).type\n  );\n};\n\n/**\n * Checks if the description is an object that contains a \"type\" key, whose\n * value is a plugin class. Returns true even when the trial object contains a\n * nested timeline. Modified from isTrialDescription in jspsych/src/timeline to\n * return true for trial descriptions with nested timelines.\n *\n * @param description - The description object to check.\n * @returns True if the description is an object with a \"type\" property,\n *   otherwise false.\n */\nconst isTrialWithType = (\n  description: ChsTrialDescription | ChsTimelineDescription,\n) => {\n  return (\n    typeof description === \"object\" &&\n    !isTimelineNodeArray(\n      description as ChsTrialDescription | ChsTimelineDescription,\n    )\n  );\n};\n\n/**\n * Function that returns a function to replace jsPsych's initJsPsych.\n *\n * @param responseUuid - Response UUID.\n * @returns InitJsPsych function.\n */\nconst lookitInitJsPsych = (responseUuid: string) => {\n  return function (opts?: JsPsychOptions): ChsJsPsych {\n    // Omit on_data_update from user-defined options that will be passed into origInitJsPsych.\n    // We are using a closure in the on_data_update function so that we can reference the jsPsych instance,\n    // and the user-defined function will be passed in through that closure.\n    const {\n      on_data_update: userOnDataUpdate,\n      on_finish: userOnFinish,\n      ...otherOpts\n    } = opts || {};\n\n    // Create a placeholder for the instance - needed for use in the onDataUpdate closure.\n    let jsPsychInstance: JsPsychType | null = null;\n\n    /**\n     * Closure to return the on_data_update function, with the actual instance,\n     * once the instance is created.\n     *\n     * @param args - Arguments passed to onDataUpdate\n     * @returns The on_data_update function to be used\n     */\n    const onDataUpdate = (...args: [JsPsychExpData]) => {\n      // Call the custom CHS on_data_update fn with the jsPsych instance, response UUID,\n      // and the user-defined on_data_update function if it exists.\n      // No checks for jsPsychInstance here because on_data_update handles that.\n      return on_data_update(\n        jsPsychInstance,\n        responseUuid,\n        userOnDataUpdate,\n      )(...args);\n    };\n\n    /**\n     * Closure to return the (experiment) on_finish function, with the actual\n     * instance, once the instance is created.\n     *\n     * @param args - Arguments passed to onFinish\n     * @returns The on_finish function to be used\n     */\n    const onFinish = (...args: [DataCollection]) => {\n      // Call the custom CHS on_finish fn with the jsPsych instance, response UUID,\n      // and the user-defined on_finish function if it exists.\n      // No checks for jsPsychInstance here because on_finish handles that.\n      return on_finish(jsPsychInstance, responseUuid, userOnFinish)(...args);\n    };\n\n    // Create the jsPsych instance and pass in the callbacks\n    const jsPsych = jspsychModule.initJsPsych({\n      ...otherOpts,\n      on_data_update: onDataUpdate,\n      on_finish: onFinish,\n    });\n\n    // Now set the instance variable to the actual instance, so that it is referenced inside onDataUpdate.\n    jsPsychInstance = jsPsych;\n\n    const origJsPsychRun = jsPsych.run;\n\n    const lookitJsPsych = jsPsych as ChsJsPsych;\n\n    /**\n     * Overriding default jsPsych run function. This will allow us to\n     * check/alter the timeline before running an experiment.\n     *\n     * @param timeline - Array of jsPsych trials (descriptions) and/or timeline\n     *   nodes (descriptions).\n     * @returns Original jsPsych run function.\n     */\n    lookitJsPsych.run = async function (timeline: ChsTimelineArray) {\n      /**\n       * Iterate over a timeline and recursively locate any trial descriptions\n       * (objects with a \"type\" key, whose value is a plugin class). For each\n       * trial description, call the callback function that receives the trial\n       * description as an argument.\n       *\n       * @param timeline - CHS versions of the jsPsych timeline array or\n       *   timeline description\n       * @param callback - Callback function that handles each plugin class,\n       *   which receives as an argument the plugin class from the trial\n       *   description \"type\".\n       * @returns Timeline array\n       */\n      const handleTrialTypes = (\n        timeline: ChsTimelineArray | ChsTimelineDescription,\n        callback: (trial: ChsTrialDescription) => void,\n      ): ChsTimelineArray => {\n        return timeline.map(\n          (\n            el: ChsTimelineDescription | ChsTrialDescription | ChsTimelineArray,\n          ) => {\n            // First check for timeline descriptions: arrays or objects with 'timeline' key that do not also have a 'type' key.\n            if (\n              isTimelineNodeArray(\n                el as\n                  | ChsTrialDescription\n                  | ChsTimelineDescription\n                  | ChsTimelineArray,\n              )\n            ) {\n              if (Array.isArray(el)) {\n                return handleTrialTypes(el as ChsTimelineArray, callback);\n              } else if (\"timeline\" in el && Array.isArray(el.timeline)) {\n                const chsTimelineDescription: ChsTimelineDescription = {\n                  ...el,\n                  timeline: handleTrialTypes(\n                    el.timeline as ChsTimelineArray,\n                    callback,\n                  ),\n                };\n                return chsTimelineDescription;\n              } else {\n                throw new UndefinedTimelineError(el);\n              }\n            } else if (\n              isTrialWithType(\n                el as ChsTimelineDescription | ChsTrialDescription,\n              )\n            ) {\n              // Now handle objects with a 'type' key. This includes trial descriptions with nested timelines, as long as they include a plugin type.\n              if (\n                el !== null &&\n                \"type\" in el &&\n                el.type !== null &&\n                el.type !== undefined\n              ) {\n                const chsTrialDescription =\n                  el as unknown as ChsTrialDescription;\n                callback(chsTrialDescription);\n                return chsTrialDescription;\n              } else {\n                throw new UndefinedTypeError(el);\n              }\n            } else {\n              throw new UndefinedTimelineError(el);\n            }\n          },\n        ) as ChsTimelineArray;\n      };\n\n      // This function takes the CHS-typed timeline passed to our modified jsPsych.run and modifies it by adding data from the chsData function in each trial type.\n      const modifiedTimeline: ChsTimelineArray = handleTrialTypes(\n        timeline as ChsTimelineArray,\n        (trial) => {\n          if (\"type\" in trial) {\n            if (trial.type?.chsData) {\n              trial.data = { ...trial.data, ...trial.type.chsData() };\n            }\n            if (\n              (trial.type as { info?: { name?: string } })?.info?.name ===\n              \"assent-video\"\n            ) {\n              const originalOnFinish = trial.on_finish;\n              /**\n               * Wrapped on_finish that aborts the experiment when the child's\n               * assent response is false.\n               *\n               * @param data - Trial data including the response value.\n               */\n              trial.on_finish = (data: Record<string, unknown>) => {\n                originalOnFinish?.(data);\n                if (data[\"response\"] === false) {\n                  jsPsych.abortExperiment();\n                }\n              };\n            }\n          }\n        },\n      );\n\n      // Convert the CHS-typed timeline array back to the jsPsych-type version for compatibility with the original jsPsych.run function.\n      return await origJsPsychRun(modifiedTimeline as TimelineArray);\n    };\n\n    return lookitJsPsych;\n  };\n};\n\nexport default lookitInitJsPsych;\n"],"names":["jspsychModule","timeline"],"mappings":"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"}