{"version":3,"file":"IdentityRegistry.mjs","sourceRoot":"","sources":["../../src/IdentityRegistry.ts"],"names":[],"mappings":"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","sourcesContent":["import Map from '@dojo/shim/Map';\nimport WeakMap from '@dojo/shim/WeakMap';\nimport { Iterable, IterableIterator } from '@dojo/shim/iterator';\nimport { Handle } from './interfaces';\nimport '@dojo/shim/Symbol';\nimport List from './List';\n\nconst noop = () => {};\n\ninterface Entry<V> {\n\treadonly handle: Handle;\n\treadonly value: V;\n}\n\ninterface State<V extends object> {\n\treadonly entryMap: Map<Identity, Entry<V>>;\n\treadonly idMap: WeakMap<V, Identity>;\n}\n\nconst privateStateMap = new WeakMap<IdentityRegistry<any>, State<any>>();\n\nfunction getState<V extends object>(instance: IdentityRegistry<V>): State<V> {\n\treturn privateStateMap.get(instance)!;\n}\n\n/**\n * Registry identities can be strings or symbols. Note that the empty string is allowed.\n */\nexport type Identity = string | symbol;\n\n/**\n * A registry of values, mapped by identities.\n */\nexport default class IdentityRegistry<V extends object> implements Iterable<[Identity, V]> {\n\tconstructor() {\n\t\tprivateStateMap.set(this, {\n\t\t\tentryMap: new Map<Identity, Entry<V>>(),\n\t\t\tidMap: new WeakMap<V, Identity>()\n\t\t});\n\t}\n\n\t/**\n\t * Look up a value by its identifier.\n\t *\n\t * Throws if no value has been registered for the given identifier.\n\t *\n\t * @param id The identifier\n\t * @return The value\n\t */\n\tget(id: Identity): V {\n\t\tconst entry = getState(this).entryMap.get(id);\n\t\tif (!entry) {\n\t\t\tthrow new Error(`Could not find a value for identity '${id.toString()}'`);\n\t\t}\n\n\t\treturn entry.value;\n\t}\n\n\t/**\n\t * Determine whether the value has been registered.\n\t * @param value The value\n\t * @return `true` if the value has been registered, `false` otherwise\n\t */\n\tcontains(value: V): boolean {\n\t\treturn getState(this).idMap.has(value);\n\t}\n\n\t/**\n\t * Remove from the registry the value for a given identifier.\n\t * @param id The identifier\n\t * @return `true` if the value was removed, `false` otherwise\n\t */\n\tdelete(id: Identity): boolean {\n\t\tconst entry = getState(this).entryMap.get(id);\n\t\tif (!entry) {\n\t\t\treturn false;\n\t\t}\n\n\t\tentry.handle.destroy();\n\t\treturn true;\n\t}\n\n\t/**\n\t * Determine whether a value has been registered for the given identifier.\n\t * @param id The identifier\n\t * @return `true` if a value has been registered, `false` otherwise\n\t */\n\thas(id: Identity): boolean {\n\t\treturn getState(this).entryMap.has(id);\n\t}\n\n\t/**\n\t * Look up the identifier for which the given value has been registered.\n\t *\n\t * Throws if the value hasn't been registered.\n\t *\n\t * @param value The value\n\t * @return The identifier otherwise\n\t */\n\tidentify(value: V): Identity | undefined {\n\t\tif (!this.contains(value)) {\n\t\t\tthrow new Error('Could not identify non-registered value');\n\t\t}\n\n\t\treturn getState(this).idMap.get(value);\n\t}\n\n\t/**\n\t * Register a new value with a new identity.\n\t *\n\t * Throws if a different value has already been registered for the given identity,\n\t * or if the value has already been registered with a different identity.\n\t *\n\t * @param id The identifier\n\t * @param value The value\n\t * @return A handle for deregistering the value. Note that when called repeatedly with\n\t *   the same identifier and value combination, the same handle is returned\n\t */\n\tregister(id: Identity, value: V): Handle {\n\t\tconst entryMap = getState<V>(this).entryMap;\n\t\tconst existingEntry = entryMap.get(id);\n\t\tif (existingEntry && existingEntry.value !== value) {\n\t\t\tconst str = id.toString();\n\t\t\tthrow new Error(`A value has already been registered for the given identity (${str})`);\n\t\t}\n\n\t\tconst existingId = this.contains(value) ? this.identify(value) : null;\n\t\tif (existingId && existingId !== id) {\n\t\t\tconst str = existingId.toString();\n\t\t\tthrow new Error(`The value has already been registered with a different identity (${str})`);\n\t\t}\n\n\t\t// Adding the same value with the same id is a noop, return the original handle.\n\t\tif (existingEntry && existingId) {\n\t\t\treturn existingEntry.handle;\n\t\t}\n\n\t\tconst handle = {\n\t\t\tdestroy: () => {\n\t\t\t\thandle.destroy = noop;\n\t\t\t\tgetState(this).entryMap.delete(id);\n\t\t\t}\n\t\t};\n\n\t\tentryMap.set(id, { handle, value });\n\t\tgetState(this).idMap.set(value, id);\n\n\t\treturn handle;\n\t}\n\n\tentries(): IterableIterator<[Identity, V]> {\n\t\tconst values = new List<[Identity, V]>();\n\n\t\tgetState(this).entryMap.forEach((value: Entry<V>, key: Identity) => {\n\t\t\tvalues.add([key, value.value]);\n\t\t});\n\n\t\treturn values.values();\n\t}\n\n\tvalues(): IterableIterator<V> {\n\t\tconst values = new List<V>();\n\n\t\tgetState(this).entryMap.forEach((value: Entry<V>, key: Identity) => {\n\t\t\tvalues.add(value.value);\n\t\t});\n\n\t\treturn values.values();\n\t}\n\n\tids(): IterableIterator<Identity> {\n\t\treturn getState(this).entryMap.keys();\n\t}\n\n\t[Symbol.iterator](): IterableIterator<[Identity, V]> {\n\t\treturn this.entries();\n\t}\n}\n"]}