UNPKG

@empirica/core

Version:
1 lines 57.4 kB
{"version":3,"sources":["../src/player/index.ts","../src/shared/attributes.ts","../src/utils/console.ts","../src/shared/globals.ts","../src/player/provider.ts","../src/shared/scopes.ts","../src/player/scopes.ts","../src/player/steps.ts","../src/player/utils.ts"],"sourcesContent":["export { Attribute, Attributes } from \"../shared/attributes\";\nexport type {\n AttributeChange,\n AttributeOptions,\n AttributeUpdate,\n} from \"../shared/attributes\";\nexport { Globals } from \"../shared/globals\";\nexport type { Constructor } from \"../shared/helpers\";\nexport type {\n AttributeInput,\n ScopeConstructor,\n ScopeUpdate,\n ScopeIdent,\n Scope as SharedScope,\n} from \"../shared/scopes\";\nexport type { Json, JsonArray, JsonValue } from \"../utils/json\";\nexport { TajribaProvider } from \"./provider\";\nexport type { ParticipantUpdate } from \"./provider\";\nexport { Scope, Scopes } from \"./scopes\";\nexport { Step, Steps } from \"./steps\";\nexport type { Epoch, StepChange, StepTick, StepUpdate } from \"./steps\";\nexport {\n createNewParticipant,\n isDevelopment,\n isProduction,\n isTest,\n} from \"./utils\";\nimport \"./index.css\";\n","import { SetAttributeInput } from \"@empirica/tajriba\";\nimport { BehaviorSubject, Observable } from \"rxjs\";\nimport { error, trace } from \"../utils/console\";\nimport { JsonValue } from \"../utils/json\";\n\nexport interface AttributeChange {\n /** deleted is true with the attribute was deleted. */\n deleted?: boolean;\n /** deletedAt is the time when the Attribute was deleted. int64 Date + Time\n * value given in Epoch with ns precision */\n deletedAt?: number;\n /** createdAt is the time the Attribute was created. int64 Date + Time\n * value given in Epoch with ns precision */\n createdAt?: string;\n /** id is the identifier for the Attribute. */\n id: string;\n /** index is the index of the attribute if the value is a vector. */\n index?: number | null;\n /** isNew is true if the Attribute was just created. */\n isNew?: boolean;\n /** key is the attribute key being updated. */\n key: string;\n /** nodeID is the identifier for the Attribute's Node. */\n nodeID?: string;\n /** node is the Attribute's Node. */\n node?: {\n __typename: \"Scope\";\n id: string;\n kind?: string;\n name?: string;\n };\n /** value is the value of the updated attribute. */\n val?: string | null;\n /** vector indicates whether the value is a vector. */\n vector: boolean;\n /** version is the version number of this Attribute, starting at 1. */\n version: number;\n}\n\nexport interface AttributeUpdate {\n attribute: AttributeChange;\n removed: boolean;\n}\n\nexport class Attributes {\n protected attrs = new Map<string, Map<string, Attribute>>();\n protected updates = new Map<string, Map<string, AttributeChange | boolean>>();\n\n constructor(\n attributesObs: Observable<AttributeUpdate>,\n donesObs: Observable<string[]>,\n readonly setAttributes: (input: SetAttributeInput[]) => Promise<unknown>\n ) {\n attributesObs.subscribe({\n next: ({ attribute, removed }) => {\n this.update(attribute, removed);\n },\n });\n\n donesObs.subscribe({\n next: (scopeIDs) => {\n this.next(scopeIDs);\n },\n });\n }\n\n attribute(scopeID: string, key: string): Attribute {\n let scopeMap = this.attrs.get(scopeID);\n if (!scopeMap) {\n scopeMap = new Map();\n this.attrs.set(scopeID, scopeMap);\n }\n\n let attr = scopeMap.get(key);\n if (!attr) {\n attr = new Attribute(this.setAttributes, scopeID, key);\n scopeMap.set(key, attr);\n }\n\n return attr;\n }\n\n attributes(scopeID: string): Attribute[] {\n let scopeMap = this.attrs.get(scopeID);\n if (!scopeMap) {\n scopeMap = new Map();\n this.attrs.set(scopeID, scopeMap);\n }\n\n return Array.from(scopeMap.values());\n }\n\n attributePeek(scopeID: string, key: string): Attribute | undefined {\n let scopeUpdateMap = this.updates.get(scopeID);\n if (scopeUpdateMap) {\n const updated = scopeUpdateMap.get(key);\n if (updated) {\n if (typeof updated === \"boolean\") {\n return;\n } else {\n if (!updated.val) {\n return;\n } else {\n const attr = new Attribute(this.setAttributes, scopeID, key);\n attr._update(updated);\n return attr;\n }\n }\n }\n }\n\n let scopeMap = this.attrs.get(scopeID);\n if (!scopeMap) {\n return;\n }\n\n let attr = scopeMap.get(key);\n if (!attr) {\n return;\n }\n\n if (attr.value === undefined) {\n return;\n }\n\n return attr;\n }\n\n nextAttributeValue(scopeID: string, key: string): JsonValue | undefined {\n const attr = this.attributePeek(scopeID, key);\n if (!attr) {\n return;\n }\n\n return attr.value;\n }\n\n private update(attr: AttributeChange, removed: boolean) {\n let nodeID = attr.nodeID;\n if (!nodeID) {\n if (!attr.node?.id) {\n error(`new attribute without node ID`);\n return;\n }\n nodeID = attr.node.id;\n }\n\n let scopeMap = this.updates.get(nodeID);\n if (!scopeMap) {\n scopeMap = new Map();\n this.updates.set(nodeID, scopeMap);\n }\n\n if (removed) {\n scopeMap.set(attr.key, true);\n } else {\n let key = attr.key;\n if (attr.index !== undefined && attr.index !== null) {\n key = `${key}[${attr.index}]`;\n }\n scopeMap.set(key, attr);\n }\n }\n\n scopeWasUpdated(scopeID?: string): boolean {\n if (!scopeID) {\n return false;\n }\n\n return this.updates.has(scopeID);\n }\n\n protected next(scopeIDs: string[]) {\n for (const [scopeID, attrs] of this.updates) {\n if (!scopeIDs.includes(scopeID)) {\n continue;\n }\n\n let scopeMap = this.attrs.get(scopeID);\n\n if (!scopeMap) {\n scopeMap = new Map();\n this.attrs.set(scopeID, scopeMap);\n }\n\n for (const [key, attrOrDel] of attrs) {\n if (typeof attrOrDel === \"boolean\") {\n let attr = scopeMap.get(key);\n if (attr) {\n attr._update(undefined);\n }\n } else {\n let attr = scopeMap.get(attrOrDel.key);\n if (!attr) {\n attr = new Attribute(this.setAttributes, scopeID, attrOrDel.key);\n scopeMap.set(attrOrDel.key, attr);\n }\n\n attr._update(attrOrDel);\n }\n }\n }\n\n for (const scopeID of scopeIDs) {\n this.updates.delete(scopeID);\n }\n }\n}\n\nexport interface AttributeOptions {\n /**\n * Private indicates the attribute will not be visible to other Participants.\n */\n private: boolean;\n /**\n * Protected indicates the attribute will not be updatable by other\n * Participants.\n */\n protected: boolean;\n /** Immutable creates an Attribute that cannot be updated. */\n immutable: boolean;\n /** ephemeral indicates the Attribute should not be persisted. Ephemeral\n * Attributes are not stored in the database and are only synced to the\n * connected clients. An ephemeral Attribute cannot become non-ephemeral and\n * vice versa. */\n ephemeral: boolean;\n /**\n * Index, only used if the Attribute is a vector, indicates which index to\n * update the value at.\n */\n index: number | null;\n /**\n * Append, only used if the Attribute is a vector, indicates to append the\n * attribute to the vector.\n */\n append: boolean | null;\n}\n\nexport class Attribute {\n private attr?: AttributeChange;\n private attrs?: Attribute[];\n\n private val = new BehaviorSubject<JsonValue | undefined>(undefined);\n private serVal?: string;\n\n constructor(\n private setAttributes: (input: SetAttributeInput[]) => Promise<unknown>,\n readonly scopeID: string,\n readonly key: string\n ) {}\n\n get id() {\n return this.attr?.id;\n }\n\n get createdAt() {\n return this.attr ? new Date(this.attr!.createdAt!) : null;\n }\n\n get obs(): Observable<JsonValue | undefined> {\n return this.val;\n }\n\n get value() {\n return this.val.getValue();\n }\n\n get nodeID() {\n return this.scopeID;\n }\n\n // items returns the attribute changes for the current attribute, if it is a\n // vector. Otherwise it returns null;\n get items() {\n if (!this.attrs) {\n return null;\n }\n\n return this.attrs;\n }\n\n set(value: JsonValue, ao?: Partial<AttributeOptions>) {\n const attrProps = this._prepSet(value, ao);\n if (!attrProps) {\n return;\n }\n\n this.setAttributes([attrProps]);\n trace(`SET ${this.key} = ${value} (${this.scopeID})`);\n }\n\n _prepSet(\n value: JsonValue,\n ao?: Partial<AttributeOptions>,\n item?: boolean\n ): SetAttributeInput | undefined {\n if (ao?.append !== undefined && ao!.index !== undefined) {\n error(`cannot set both append and index`);\n\n throw new Error(`cannot set both append and index`);\n }\n\n const serVal = JSON.stringify(value);\n\n if (!item && (ao?.index !== undefined || ao?.append)) {\n let index = ao!.index || 0;\n if (ao?.append) {\n index = this.attrs?.length || 0;\n }\n\n if (!this.attrs) {\n this.attrs = [];\n }\n\n // if (index + 1 > (this.attrs?.length || 0)) {\n // this.attrs.length = index! + 1;\n // }\n\n if (!this.attrs[index]) {\n this.attrs[index] = new Attribute(\n this.setAttributes,\n this.scopeID,\n this.key\n );\n } else {\n const existing = this.attrs[index];\n if (existing && existing.serVal === serVal) {\n return;\n }\n }\n\n this.attrs![index]!._prepSet(value, ao, true);\n const v = this._recalcVectorVal();\n this.val.next(v);\n } else {\n if (this.serVal === serVal) {\n return;\n }\n\n this.val.next(value);\n }\n\n this.serVal = serVal;\n\n const attrProps: SetAttributeInput = {\n key: this.key,\n nodeID: this.scopeID,\n val: serVal,\n };\n\n if (ao) {\n // TODO Fix this. Should check if compatible with existing attribute and\n // only set fields set on ao.\n attrProps.private = ao.private;\n attrProps.protected = ao.protected;\n attrProps.immutable = ao.immutable;\n attrProps.ephemeral = ao.ephemeral;\n attrProps.append = ao.append;\n attrProps.index = ao.index;\n }\n\n return attrProps;\n }\n\n private _recalcVectorVal(): JsonValue {\n return this.attrs!.map((a) =>\n !a || a.val == undefined ? null : a.value || null\n );\n }\n\n // internal only\n _update(attr?: AttributeChange, item?: boolean) {\n if (attr && this.attr && this.attr.id === attr.id) {\n return;\n }\n\n if (attr && attr.vector && !item) {\n // TODO check if is vector\n\n if (attr.index === undefined) {\n error(`vector attribute missing index`);\n return;\n }\n\n if (this.attrs == undefined) {\n this.attrs = [];\n }\n\n while (this.attrs.length < attr.index! + 1) {\n const newAttr = new Attribute(\n this.setAttributes,\n this.scopeID,\n this.key\n );\n this.attrs.push(newAttr);\n }\n\n const newAttr = new Attribute(this.setAttributes, this.scopeID, this.key);\n newAttr._update(attr, true);\n this.attrs[attr.index!] = newAttr;\n const value = this._recalcVectorVal();\n this.val.next(value);\n\n return;\n }\n\n this.attr = attr;\n this.serVal = attr?.val === undefined || attr?.val === null ? \"\" : attr.val;\n let value: JsonValue | undefined = undefined;\n if (this.attr?.val) {\n value = JSON.parse(this.attr.val);\n }\n this.val.next(value);\n }\n}\n","/* c8 ignore start */\n\nconst isBrowser =\n typeof window !== \"undefined\" && typeof window.document !== \"undefined\";\n\nenum Color {\n Bold = 1,\n\n Black = 30,\n Red,\n Green,\n Yellow,\n Blue,\n Magenta,\n Cyan,\n White,\n\n DarkGray = 90,\n}\n\nexport type LogLine = { level: string; args: any[] };\nexport class LogsMock {\n public logs: LogLine[] = [];\n\n log(line: LogLine) {\n this.logs.push(line);\n }\n\n clear() {\n this.logs = [];\n }\n}\n\nlet logsMock: LogsMock | undefined;\nexport function captureLogs(cb: () => void): LogLine[] {\n const lm = mockLogging();\n cb();\n const ret = lm.logs;\n stopMockLogging();\n\n return ret;\n}\n\nexport async function captureLogsAsync(\n cb: () => Promise<void>\n): Promise<LogLine[]> {\n const lm = mockLogging();\n await cb();\n const ret = lm.logs;\n stopMockLogging();\n\n return ret;\n}\n\nexport function mockLogging() {\n if (!logsMock) {\n logsMock = new LogsMock();\n }\n\n return logsMock;\n}\n\nexport function stopMockLogging() {\n logsMock = undefined;\n}\n\nconst colorHex = {\n [Color.Bold]: \"font-weight: bold\",\n [Color.Black]: \"color: #000000\",\n [Color.Red]: \"color: #cc0000\",\n [Color.Green]: \"color: #4e9a06\",\n [Color.Yellow]: \"color: #c4a000\",\n [Color.Blue]: \"color: #729fcf\",\n [Color.Magenta]: \"color: #75507b\",\n [Color.Cyan]: \"color: #06989a\",\n [Color.White]: \"color: #d3d7cf\",\n [Color.DarkGray]: \"color: #555753\",\n};\n\nexport const levels: { [key: string]: number } = {\n trace: 0,\n debug: 1,\n log: 2,\n info: 2,\n warn: 3,\n error: 4,\n};\n\nconst reversLevels: { [key: number]: string } = {};\nfor (const key in levels) {\n reversLevels[levels[key]!] = key;\n}\n\nlet currentLevel = 2;\n\nexport function setLogLevel(level: keyof typeof levels) {\n const lvl = levels[level];\n if (lvl === undefined) {\n return;\n }\n\n currentLevel = lvl;\n}\n\nfunction formatConsoleDate(date: Date, level: string[]) {\n var hour = date.getHours();\n var minutes = date.getMinutes();\n var seconds = date.getSeconds();\n var milliseconds = date.getMilliseconds();\n\n const str =\n (hour < 10 ? \"0\" + hour : hour) +\n \":\" +\n (minutes < 10 ? \"0\" + minutes : minutes) +\n \":\" +\n (seconds < 10 ? \"0\" + seconds : seconds) +\n \".\" +\n (\"00\" + milliseconds).slice(-3);\n\n if (isBrowser) {\n const ts = colorize(str, Color.DarkGray).concat(level);\n return [ts[0] + \" \" + level[0], ts[1], level[1]];\n }\n\n return colorize(str, Color.DarkGray).concat(level);\n}\n\nconst createLogger = (lvl: number, level: string[]) => {\n return (...args: any[]) => {\n if (lvl < currentLevel) {\n return;\n }\n\n if (logsMock) {\n logsMock.log({ level: reversLevels[lvl]!, args: args });\n\n return;\n }\n\n if (args.length === 1) {\n switch (typeof args[0]) {\n case \"string\":\n for (const line of args[0].split(\"\\n\")) {\n console.log(...formatConsoleDate(new Date(), level).concat(line));\n }\n return;\n\n case \"object\":\n if (args[0] instanceof Error) {\n const error = args[0] as Error;\n const prettyErr =\n error.name +\n \": \" +\n error.message.replace(new RegExp(`^${error.name}[: ]*`), \"\") +\n \"\\n\" +\n (error.stack || \"\")\n .split(\"\\n\")\n .map((line) => line.trim())\n .map((line) => {\n if (line.startsWith(error.name + \": \" + error.message))\n return null;\n\n if (line.startsWith(\"at\")) {\n return \" \" + line;\n }\n\n return line;\n })\n .filter(Boolean)\n .join(\"\\n\");\n\n for (const line of prettyErr.split(\"\\n\")) {\n console.log(...formatConsoleDate(new Date(), level).concat(line));\n }\n\n return;\n }\n }\n }\n\n console.log(...formatConsoleDate(new Date(), level).concat(args));\n };\n};\n\nfunction colorize(s: string, ...cc: Color[]): string[] {\n if (isBrowser) {\n const attr = [];\n for (const c of cc) {\n attr.push(colorHex[c]);\n }\n\n return [`%c${s}`, attr.join(\"; \")];\n }\n\n let out = \"\";\n for (const c of cc) {\n out += `\\x1b[${c}m`;\n }\n out += `${s}\\x1b[0m`;\n\n return [out];\n}\n\nexport const trace = createLogger(0, colorize(\"TRC\", Color.Magenta));\nexport const debug = createLogger(1, colorize(\"DBG\", Color.Yellow));\nexport const log = createLogger(2, colorize(\"LOG\", Color.Yellow));\nexport const info = createLogger(2, colorize(\"INF\", Color.Green));\nexport const warn = createLogger(3, colorize(\"WRN\", Color.Cyan));\nexport const error = createLogger(4, colorize(\"ERR\", Color.Red, Color.Bold));\n\n// export {\n// trace,\n// debug,\n// log,\n// info,\n// warn,\n// error,\n// };\n\n// export function warn(...args: string[]) {}\n","import { SubAttributesPayload } from \"@empirica/tajriba\";\nimport { BehaviorSubject, Observable } from \"rxjs\";\nimport { JsonValue } from \"../utils/json\";\n\nexport class Globals {\n protected attrs = new Map<string, BehaviorSubject<JsonValue | undefined>>();\n private updates = new Map<string, JsonValue | undefined>();\n public self: BehaviorSubject<Globals | undefined>;\n\n constructor(globals: Observable<SubAttributesPayload>) {\n this.self = new BehaviorSubject<Globals | undefined>(undefined);\n\n globals.subscribe({\n next: ({ attribute, done }) => {\n if (attribute) {\n let val = undefined;\n if (attribute.val) {\n val = JSON.parse(attribute.val);\n }\n\n this.updates.set(attribute.key, val);\n }\n\n if (done) {\n for (const [key, val] of this.updates) {\n this.obs(key).next(val);\n }\n\n this.updates.clear();\n\n if (this.self) {\n this.self.next(this);\n }\n }\n },\n });\n }\n\n get(key: string): JsonValue | undefined {\n const o = this.attrs.get(key);\n if (o) {\n return o.getValue();\n }\n\n return undefined;\n }\n\n obs(key: string) {\n let o = this.attrs.get(key);\n if (!o) {\n o = new BehaviorSubject<JsonValue | undefined>(undefined);\n this.attrs.set(key, o);\n }\n\n return o;\n }\n}\n","import {\n ChangePayload,\n ParticipantChange,\n SetAttributeInput,\n SubAttributesPayload,\n} from \"@empirica/tajriba\";\nimport { Observable, Subject, groupBy } from \"rxjs\";\nimport { AttributeChange, AttributeUpdate } from \"../shared/attributes\";\nimport { ScopeIdent, ScopeUpdate } from \"../shared/scopes\";\nimport { trace } from \"../utils/console\";\nimport { StepChange, StepUpdate } from \"./steps\";\n\nexport interface ParticipantUpdate {\n participant: ParticipantChange;\n removed: boolean;\n}\n\nexport class TajribaProvider {\n public scopes = new Subject<ScopeUpdate>();\n public attributes = new Subject<AttributeUpdate>();\n public participants = new Subject<ParticipantUpdate>();\n public steps = new Subject<StepUpdate>();\n public dones = new Subject<string[]>();\n\n constructor(\n changes: Observable<ChangePayload>,\n readonly globals: Observable<SubAttributesPayload>,\n readonly setAttributes: (input: SetAttributeInput[]) => Promise<any>\n ) {\n let scopeIDs: string[] = [];\n changes.pipe(groupBy((chg) => chg?.change?.__typename)).subscribe({\n next: (group) => {\n switch (group.key) {\n case \"ScopeChange\":\n group.subscribe({\n next: (msg) => {\n if (\n !msg.change ||\n msg.removed === null ||\n msg.removed === undefined\n ) {\n trace(\"AttributeChange empty\");\n } else {\n this.scopes.next({\n scope: <ScopeIdent>msg.change,\n removed: msg.removed,\n });\n }\n\n if (msg.done) {\n this.dones.next(scopeIDs);\n }\n },\n });\n\n break;\n case \"AttributeChange\":\n group.subscribe({\n next: (msg) => {\n if (\n !msg.change ||\n msg.removed === null ||\n msg.removed === undefined\n ) {\n trace(\"AttributeChange empty\");\n } else {\n const atChange = <AttributeChange>msg.change;\n scopeIDs.push(atChange.nodeID || atChange.node!.id);\n this.attributes.next({\n attribute: atChange,\n removed: msg.removed,\n });\n }\n\n if (msg.done) {\n this.dones.next(scopeIDs);\n scopeIDs = [];\n }\n },\n });\n\n break;\n case \"ParticipantChange\":\n group.subscribe({\n next: (msg) => {\n if (\n !msg.change ||\n msg.removed === null ||\n msg.removed === undefined\n ) {\n trace(\"ParticipantChange empty\");\n } else {\n this.participants.next({\n participant: <ParticipantChange>msg.change,\n removed: msg.removed,\n });\n }\n\n if (msg.done) {\n this.dones.next([]);\n }\n },\n });\n\n break;\n case \"StepChange\":\n group.subscribe({\n next: (msg) => {\n if (\n !msg.change ||\n msg.removed === null ||\n msg.removed === undefined\n ) {\n trace(\"StepChange empty\");\n } else {\n this.steps.next({\n step: <StepChange>msg.change,\n removed: msg.removed,\n });\n }\n\n if (msg.done) {\n this.dones.next([]);\n }\n },\n });\n\n break;\n default:\n group.subscribe({\n next: (change) => {\n if (change.done) {\n this.dones.next([]);\n }\n },\n });\n\n break;\n }\n },\n });\n }\n}\n","import { BehaviorSubject, Observable } from \"rxjs\";\nimport { Attribute, AttributeOptions, Attributes } from \"../shared/attributes\";\nimport { Constructor } from \"../shared/helpers\";\nimport { warn } from \"../utils/console\";\nimport { JsonValue } from \"../utils/json\";\n\nexport type Attributable = {\n get: (key: string) => JsonValue | undefined;\n getAttribute: (key: string) => Attribute | undefined;\n set: (key: string, value: JsonValue, ao?: Partial<AttributeOptions>) => void;\n append: (\n key: string,\n value: JsonValue,\n ao?: Partial<AttributeOptions>\n ) => void;\n};\n\nexport interface ScopeIdent {\n id: string;\n kind: string;\n}\n\nexport interface ScopeUpdate {\n scope: ScopeIdent;\n removed: boolean;\n}\n\nexport type ScopeConstructor<\n Context,\n Kinds extends { [key: string]: ScopeConstructor<Context, Kinds> }\n> = Constructor<Scope<Context, Kinds>>;\n\nexport class Scopes<\n Context,\n Kinds extends { [key: string]: ScopeConstructor<Context, Kinds> },\n Skope extends Scope<Context, Kinds> = Scope<Context, Kinds>\n> {\n protected scopes = new Map<string, BehaviorSubject<Skope>>();\n // newScopes is used to track scopes that have appeared for the first time.\n protected newScopes = new Map<string, boolean>();\n protected scopesByKind = new Map<keyof Kinds, Map<string, Skope>>();\n protected kindUpdated = new Set<keyof Kinds>();\n\n constructor(\n scopesObs: Observable<ScopeUpdate>,\n donesObs: Observable<string[]>,\n protected ctx: Context,\n protected kinds: Kinds,\n protected attributes: Attributes\n ) {\n scopesObs.subscribe({\n next: ({ scope, removed }) => {\n this.update(scope, removed);\n },\n });\n\n donesObs.subscribe({\n next: (scopeIDs) => {\n this.next(scopeIDs);\n },\n });\n }\n\n scope(id: string): Skope | undefined {\n return this.scopes.get(id)?.getValue();\n }\n\n scopeObs(id: string): Observable<Skope> | undefined {\n return this.scopes.get(id);\n }\n\n byKind<T extends Skope>(kind: keyof Kinds) {\n let map = this.scopesByKind.get(kind);\n if (!map) {\n map = new Map();\n this.scopesByKind.set(kind, map);\n }\n\n return map! as Map<string, T>;\n }\n\n kindWasUpdated(kind: keyof Kinds): boolean {\n return this.kindUpdated.has(kind);\n }\n\n protected next(scopeIDs: string[]) {\n this.kindUpdated.clear();\n for (const [_, scopeSubject] of this.scopes) {\n const scope = scopeSubject.getValue();\n if (\n (scope._updated || this.attributes.scopeWasUpdated(scope.id)) &&\n scopeIDs.includes(scope.id)\n ) {\n scope._updated = false;\n scopeSubject.next(scope);\n }\n }\n }\n\n protected update(scope: ScopeIdent, removed: boolean) {\n const existing = this.scopes.get(scope.id)?.getValue();\n\n if (removed) {\n if (!existing) {\n warn(\"scopes: missing scope on removal\", scope.id, scope.kind);\n\n return;\n }\n\n existing._deleted = true;\n existing._updated = true;\n this.scopes.delete(scope.id);\n\n if (!scope.kind) {\n warn(\"scopes: scope missing kind on scope on removal\");\n\n return;\n }\n\n const kind = scope.kind as keyof Kinds;\n\n // Using ! because scopes by kind must exist, since this scope was found.\n this.scopesByKind.get(kind)!.delete(scope.id);\n\n this.kindUpdated.add(kind);\n\n return;\n }\n\n if (existing) {\n existing._deleted = false;\n return;\n }\n\n if (!scope.kind) {\n warn(\"scopes: scope missing kind on scope\");\n\n return;\n }\n\n const kind = scope.kind as keyof Kinds;\n const scopeClass = this.kinds[kind];\n if (!scopeClass) {\n warn(`scopes: unknown scope kind: ${scope.kind}`);\n\n return;\n }\n\n const obj = this.create(scopeClass, scope);\n const subj = new BehaviorSubject(obj);\n this.scopes.set(scope.id, subj);\n this.newScopes.set(scope.id, true);\n\n let skm = this.scopesByKind.get(kind);\n if (!skm) {\n skm = new Map();\n this.scopesByKind.set(kind, skm);\n }\n\n skm.set(scope.id, obj);\n\n obj._updated = true;\n this.kindUpdated.add(kind);\n }\n\n protected create(\n scopeClass: ScopeConstructor<Context, Kinds>,\n scope: ScopeIdent\n ) {\n return new scopeClass!(this.ctx, scope, this.attributes) as Skope;\n }\n}\n\nexport type AttributeInput = {\n key: string;\n value: JsonValue;\n ao?: Partial<AttributeOptions>;\n};\n\nexport class Scope<\n Context,\n Kinds extends { [key: string]: ScopeConstructor<Context, Kinds> }\n> {\n /**\n * @internal\n */\n _deleted = false;\n\n /**\n * @internal\n */\n _updated = false;\n\n constructor(\n /**\n * @internal\n */\n readonly ctx: Context,\n /**\n * @internal\n */\n readonly scope: ScopeIdent,\n /**\n * @internal\n */\n protected attributes: Attributes\n ) {}\n\n get id() {\n return this.scope.id;\n }\n\n /**\n * @internal\n */\n get kind() {\n // Using ! because we don't allow scopes without kind\n return this.scope.kind!;\n }\n\n get(key: string): JsonValue | undefined {\n return this.attributes.attribute(this.scope.id, key).value;\n }\n\n getAttribute(key: string): Attribute | undefined {\n return this.attributes.attribute(this.scope.id, key);\n }\n\n obs(key: string): Observable<JsonValue | undefined> {\n return this.attributes.attribute(this.scope.id, key).obs;\n }\n\n set(values: AttributeInput[]): void;\n set(key: string, value: JsonValue, ao?: Partial<AttributeOptions>): void;\n set(\n keyOrAttributes: string | AttributeInput[],\n value?: JsonValue,\n ao?: Partial<AttributeOptions>\n ) {\n if (typeof keyOrAttributes === \"string\") {\n if (value === undefined) {\n value = null;\n }\n\n return this.attributes\n .attribute(this.scope.id, keyOrAttributes)\n .set(value, ao);\n }\n\n const nextProps = [];\n for (const attr of keyOrAttributes) {\n const at = this.attributes\n .attribute(this.scope.id, attr.key)\n ._prepSet(attr.value, attr.ao);\n if (!at) {\n continue;\n }\n\n nextProps.push(at);\n }\n\n if (nextProps.length === 0) {\n return;\n }\n\n this.attributes.setAttributes(nextProps);\n }\n\n append(key: string, value: JsonValue, ao?: Partial<AttributeOptions>) {\n if (!ao) {\n ao = {};\n }\n ao.append = true;\n\n return this.attributes.attribute(this.scope.id, key).set(value, ao);\n }\n\n inspect() {\n const attrs = this.attributes.attributes(this.scope.id);\n\n const out: { [key: string]: JsonValue | undefined } = {};\n for (const attr of attrs) {\n out[attr.key] = attr.value;\n }\n\n return out;\n }\n\n /**\n * @internal\n */\n hasUpdated() {\n return this._updated || this.attributes.scopeWasUpdated(this.id);\n }\n}\n","import { Observable } from \"rxjs\";\nimport { Attributes } from \"../shared/attributes\";\nimport {\n Scope as SharedScope,\n ScopeConstructor,\n ScopeIdent,\n Scopes as SharedScopes,\n ScopeUpdate,\n} from \"../shared/scopes\";\nimport { Steps } from \"./steps\";\n\nexport class Scopes<\n Context,\n Kinds extends { [key: string]: ScopeConstructor<Context, Kinds> }\n> extends SharedScopes<Context, Kinds, Scope<Context, Kinds>> {\n constructor(\n scopesObs: Observable<ScopeUpdate>,\n donesObs: Observable<string[]>,\n ctx: Context,\n kinds: Kinds,\n attributes: Attributes,\n private steps: Steps\n ) {\n super(scopesObs, donesObs, ctx, kinds, attributes);\n }\n\n protected create(\n scopeClass: ScopeConstructor<Context, Kinds>,\n scope: ScopeIdent\n ) {\n return new scopeClass!(\n this.ctx,\n scope,\n this,\n this.attributes,\n this.steps\n ) as Scope<Context, Kinds>;\n }\n}\n\nexport class Scope<\n Context,\n Kinds extends { [key: string]: ScopeConstructor<Context, Kinds> }\n> extends SharedScope<Context, Kinds> {\n constructor(\n ctx: Context,\n scope: ScopeIdent,\n readonly scopes: Scopes<Context, Kinds>,\n attributes: Attributes,\n private steps: Steps\n ) {\n super(ctx, scope, attributes);\n }\n\n scopeByKey(key: string) {\n const id = this.get(key);\n if (!id || typeof id !== \"string\") {\n return;\n }\n\n return this.scopes.scope(id);\n }\n\n protected ticker(id: string) {\n return this.steps.step(id);\n }\n\n protected tickerByKey(key: string) {\n const id = this.get(key);\n if (!id || typeof id !== \"string\") {\n return;\n }\n\n return this.ticker(id);\n }\n}\n","import { BehaviorSubject, map, Observable } from \"rxjs\";\n\nexport interface StepChange {\n id: string;\n running: boolean;\n elapsed?: number;\n remaining?: number;\n}\n\nexport interface StepUpdate {\n step: StepChange;\n removed: boolean;\n}\n\nexport interface StepTick {\n started: boolean;\n ended: boolean;\n elapsed: number;\n remaining: number;\n duration: number;\n}\n\ntype schds = {\n cb: (args: void) => void;\n from: number;\n dur: number;\n};\n\nlet scheduled: schds[] = [];\n\nexport let mockNow: number | null = null;\nexport function setNow(now: number) {\n if (mockNow && mockNow > now) {\n if (now === 0) {\n // This is a reset scheduled should be empty\n scheduled = [];\n /* c8 ignore next 3 */\n } else {\n throw \"time must move forward\";\n }\n }\n\n mockNow = now;\n\n const rescheduled: schds[] = [];\n for (const s of scheduled) {\n if (mockNow >= s.from + s.dur) {\n s.cb();\n } else {\n rescheduled.push(s);\n }\n }\n\n scheduled = rescheduled;\n}\n\nfunction pnow() {\n if (mockNow !== null) {\n return mockNow;\n } else {\n // TODO sync time\n return performance.now();\n }\n}\n\nfunction timeout(callback: (args: void) => void, ms: number) {\n if (mockNow !== null) {\n const schd = {\n cb: callback,\n from: mockNow,\n dur: ms,\n };\n scheduled.push(schd);\n } else {\n setTimeout(callback, ms);\n }\n}\n\n// The number of milliseconds elapsed since January 1, 1970 00:00:00 UTC, with\n// leap seconds ignored.\nexport type Epoch = number;\n\nexport class Step {\n private running = false;\n private ticker = new BehaviorSubject<StepTick | undefined>(undefined);\n private startAt: number = 0;\n private endAt: number = 0;\n\n constructor(step: StepChange, ticker: Observable<DOMHighResTimeStamp>) {\n ticker.pipe(map(this.recalc.bind(this))).subscribe({\n next: (val) => {\n this.ticker.next(val);\n },\n });\n\n this._update(step);\n }\n\n private recalc(t: DOMHighResTimeStamp) {\n if (!this.running) {\n return undefined;\n }\n\n return {\n started: t >= this.startAt,\n ended: t >= this.endAt,\n elapsed: Math.round(t - this.startAt),\n remaining: Math.round(this.endAt - t),\n duration: this.endAt - this.startAt,\n } as StepTick;\n }\n\n obs(): Observable<StepTick | undefined> {\n return this.ticker;\n }\n\n get current() {\n return this.recalc(pnow());\n }\n\n // internal only\n _update(step: StepChange) {\n if (!step.running) {\n this.running = false;\n this.ticker.next(undefined);\n\n return;\n }\n\n if (\n step.elapsed === null ||\n step.remaining === null ||\n step.elapsed === undefined ||\n step.remaining === undefined\n ) {\n this.running = false;\n\n return;\n }\n\n const now = pnow();\n\n this.startAt = now - step.elapsed * 1000;\n this.endAt = now + step.remaining * 1000;\n this.running = step.elapsed >= 0 && step.remaining >= 0;\n\n this.ticker.next(this.recalc(now));\n }\n\n // internal only\n _stop() {\n this.running = false;\n this.ticker.next(undefined);\n }\n}\n\nexport class Steps {\n private steps = new Map<string, Step>();\n private updates = new Map<string, StepChange | boolean>();\n private _hadUpdates = false;\n\n private ticker: BehaviorSubject<Epoch>;\n\n constructor(stepsObs: Observable<StepUpdate>, donesObs: Observable<void>) {\n stepsObs.subscribe({\n next: ({ step, removed }) => {\n this.update(step, removed);\n },\n });\n\n donesObs.subscribe({\n next: () => {\n this.next();\n },\n });\n\n this.ticker = new BehaviorSubject<Epoch>(Math.floor(pnow()));\n const controller = new AbortController();\n timerInterval(1000, controller.signal, (t) => {\n this.ticker.next(t);\n });\n }\n\n step(stepID: string): Step | undefined {\n return this.steps.get(stepID);\n }\n\n hadUpdates() {\n const hadUpdates = this._hadUpdates;\n this._hadUpdates = false;\n\n return hadUpdates;\n }\n\n private update(step: StepChange, removed: boolean) {\n if (removed) {\n this.updates.set(step.id, true);\n } else {\n this.updates.set(step.id, step);\n }\n\n this._hadUpdates = true;\n }\n\n private next() {\n for (const [id, stepOrDel] of this.updates) {\n let step = this.steps.get(id);\n if (typeof stepOrDel === \"boolean\") {\n if (step) {\n step._stop();\n this.steps.delete(id);\n }\n } else {\n if (!step) {\n step = new Step(stepOrDel, this.ticker);\n this.steps.set(id, step);\n }\n\n step._update(stepOrDel);\n }\n }\n\n this.updates.clear();\n }\n}\n\n/* c8 ignore next 6 */\nexport const root: any =\n typeof self === \"object\" && self.self == self\n ? self\n : typeof global === \"object\" && global.global == global\n ? global\n : {};\n\n// nodejs support\nif (!root[\"requestAnimationFrame\"]) {\n type timecb = (t: DOMHighResTimeStamp) => void;\n root[\"requestAnimationFrame\"] = (cb: timecb) => cb(pnow());\n}\n\n// Inspiration:\n// https://www.youtube.com/watch?v=MCi6AZMkxcU\n// https://gist.github.com/jakearchibald/cb03f15670817001b1157e62a076fe95\nfunction timerInterval(\n ms: number = 1000,\n signal: AbortSignal,\n callback: (time: number) => void\n) {\n // Performance should be available in Nodejs 10+.\n // Get the last rounded second, which will go negative, but that's fine, since\n // it will immediately send out its first tick, then be on the second.\n const start = Math.floor(pnow() / 1000) * 1000;\n\n function frame(time: number) {\n /* c8 ignore next */\n if (signal.aborted) return;\n callback(time);\n scheduleFrame(time);\n }\n\n function scheduleFrame(time: number) {\n const elapsed = time - start;\n const roundedElapsed = Math.round(elapsed / ms) * ms;\n const targetNext = start + roundedElapsed + ms;\n const delay = targetNext - pnow();\n timeout(() => requestAnimationFrame(frame), delay);\n }\n\n scheduleFrame(start);\n}\n\n// export function useAnimationInterval(\n// ms: number,\n// callback: (time: number) => void\n// ) {\n// const callbackRef = React.useRef(callback);\n// React.useEffect(() => {\n// callbackRef.current = callback;\n// }, [callback]);\n\n// React.useEffect(() => {\n// const controller = new AbortController();\n// animationInterval(ms, controller.signal, callbackRef.current);\n// return () => controller.abort();\n// }, [ms]);\n// }\n","export const isDevelopment = process.env.NODE_ENV === \"development\";\nexport const isProduction = process.env.NODE_ENV === \"production\";\nexport const isTest = process.env.NODE_ENV === \"test\";\n\nexport const createNewParticipant = (key = \"participantKey\") => {\n const url = new URL(document.location.href);\n url.searchParams.set(key, new Date().getTime().toString());\n window.open(url.href, \"_blank\")?.focus();\n};\n"],"mappings":"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