aboutsummaryrefslogtreecommitdiff
path: root/packages/idb-bridge/src/util/extractKey.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/idb-bridge/src/util/extractKey.ts')
-rw-r--r--packages/idb-bridge/src/util/extractKey.ts55
1 files changed, 55 insertions, 0 deletions
diff --git a/packages/idb-bridge/src/util/extractKey.ts b/packages/idb-bridge/src/util/extractKey.ts
new file mode 100644
index 000000000..fd14c5a64
--- /dev/null
+++ b/packages/idb-bridge/src/util/extractKey.ts
@@ -0,0 +1,55 @@
+import { Key, KeyPath, Value } from "./types";
+import valueToKey from "./valueToKey";
+
+// http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-steps-for-extracting-a-key-from-a-value-using-a-key-path
+const extractKey = (keyPath: KeyPath, value: Value) => {
+ if (Array.isArray(keyPath)) {
+ const result: Key[] = [];
+
+ for (let item of keyPath) {
+ // This doesn't make sense to me based on the spec, but it is needed to pass the W3C KeyPath tests (see same
+ // comment in validateKeyPath)
+ if (
+ item !== undefined &&
+ item !== null &&
+ typeof item !== "string" &&
+ (item as any).toString
+ ) {
+ item = (item as any).toString();
+ }
+ result.push(valueToKey(extractKey(item, value)));
+ }
+
+ return result;
+ }
+
+ if (keyPath === "") {
+ return value;
+ }
+
+ let remainingKeyPath: string | null = keyPath;
+ let object = value;
+
+ while (remainingKeyPath !== null) {
+ let identifier;
+
+ const i = remainingKeyPath.indexOf(".");
+ if (i >= 0) {
+ identifier = remainingKeyPath.slice(0, i);
+ remainingKeyPath = remainingKeyPath.slice(i + 1);
+ } else {
+ identifier = remainingKeyPath;
+ remainingKeyPath = null;
+ }
+
+ if (!object.hasOwnProperty(identifier)) {
+ return;
+ }
+
+ object = object[identifier];
+ }
+
+ return object;
+};
+
+export default extractKey;