diff --git a/.gitignore b/.gitignore index 802ddd2f..ff7a2e19 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ node_modules npm-debug.log -dist +build diff --git a/README.md b/README.md index ecd62fa7..1a5035a4 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ Or you can import individual functions directly. Variable names of all the objec ```js var fakeIndexedDB = require('fake-indexeddb'); -var FDBKeyRange = require('fake-indexeddb/FDBKeyRange'); +var FDBKeyRange = require('fake-indexeddb/FDBKeyRange').default; // ...same code as last example, but fakeIndexedDB instead of indexedDB and FDBKeyRange instead of IDBKeyRange ``` diff --git a/TODO b/TODO index d5924c2d..74408d2b 100644 --- a/TODO +++ b/TODO @@ -4,6 +4,26 @@ binary search tree TypeScript - tslint + - re-enable disabled rules +- provide type defs to consumer +- remove eslint - all files and comments +- remove babel +- improve types + - Database.transactions + - FDBCursorWithValue any + - types.ts any + - EventTarget addEventListener callback can be null? + - FDBRequest null/any variables + - ObjectStore rawDatabase, rawIndexes + - Index rawObjectStore, transaction any + - FDBCursor source any + - FDBIndex objectStore, rawIndex any + - FDBObjectStore transaction any + - FDBTransaction db any + - circular import problems (search) - define interface in types.ts + - public APIs should accept any - errors are part of spec, not to be prevented by types? +- make sure it's still usable by normal ES5 code, not weird exports + - change target in tsconfig Run on real W3C tests @@ -15,8 +35,6 @@ open issues addDomStringListMethods - make it a class -add lib.js for 1.x compatability, and test - make sure it works in node 4 --- @@ -32,6 +50,7 @@ multiple readonly transactions should be allowed to run at the same time (but no readonly properties need to actually be readonly - done in FDBCursor +- typescript annotation is easier (like in FDBKeyRange), but not actually binding for compiled JS version share some code between Index and ObjectStore, like getValue, confirmActiveTransaction, count - similar thing between open and deleteDatabase diff --git a/package.json b/package.json index 9523ea40..8ec6c748 100644 --- a/package.json +++ b/package.json @@ -22,11 +22,12 @@ ], "main": "src/index.js", "scripts": { - "lint": "eslint 'src/**/*.js'", - "mocha": "mocha --timeout 5000 src/test/w3c src/test/fakeIndexedDB", - "build-qunit": "rm -rf dist && mkdir dist && browserify src/test/exports-qunit.js -o dist/exports-qunit.js -t [ babelify --presets [ es2015 ] ]", - "qunit": "npm run build-qunit && node-qunit-phantomjs ./src/test/indexedDBmock/index.html", - "test": "npm run lint && npm run mocha && npm run qunit" + "build": "rm -rf build && tsc", + "lint": "tslint 'src/**/*.ts' && eslint 'src/**/*.js'", + "mocha": "mocha --timeout 10000 build/test/w3c build/test/fakeIndexedDB", + "build-qunit": "browserify build/test/exports-qunit.js -o build/exports-qunit-bundle.js -t [ babelify --presets [ es2015 ] ] && cp src/test/indexedDBmock/index.html build/test/indexedDBmock/index.html", + "qunit": "npm run build-qunit && node-qunit-phantomjs build/test/indexedDBmock/index.html", + "test": "npm run lint && npm run build && npm run mocha && npm run qunit" }, "author": "Jeremy Scheff (http://dumbmatter.com/)", "license": "Apache-2.0", @@ -35,13 +36,15 @@ "setimmediate": "^1.0.5" }, "devDependencies": { + "@types/node": "^7.0.13", "babel-polyfill": "^6.23.0", "babel-preset-es2015": "^6.24.1", - "babelify": "^7.3.0", "browserify": "^14.0.0", "eslint": "^3.15.0", "mocha": "^3.2.0", "node-qunit-phantomjs": "^1.5.0", - "qunitjs": "^1.23.1" + "qunitjs": "^1.23.1", + "tslint": "^5.1.0", + "typescript": "^2.2.2" } } diff --git a/src/FDBCursor.js b/src/FDBCursor.ts similarity index 76% rename from src/FDBCursor.js rename to src/FDBCursor.ts index 108cf003..8b52fa1c 100644 --- a/src/FDBCursor.js +++ b/src/FDBCursor.ts @@ -1,12 +1,16 @@ -const structuredClone = require('./lib/structuredClone'); -const FDBKeyRange = require('./FDBKeyRange'); -const {DataError, InvalidStateError, ReadOnlyError, TransactionInactiveError} = require('./lib/errors'); -const cmp = require('./lib/cmp'); -const extractKey = require('./lib/extractKey'); -const validateKey = require('./lib/validateKey'); - -const getEffectiveObjectStore = (cursor) => { - if (cursor.source.hasOwnProperty('_rawIndex')) { +import FDBKeyRange from "./FDBKeyRange"; +import FDBRequest from "./FDBRequest"; +import cmp from "./lib/cmp"; +const {DataError, InvalidStateError, ReadOnlyError, TransactionInactiveError} = require("./lib/errors"); +import extractKey from "./lib/extractKey"; +import structuredClone from "./lib/structuredClone"; +import {FDBCursorDirection, Key, Value} from "./lib/types"; +import validateKey from "./lib/validateKey"; + +type Range = Key | FDBKeyRange | void; + +const getEffectiveObjectStore = (cursor: FDBCursor) => { + if (cursor.source.hasOwnProperty("_rawIndex")) { return cursor.source.objectStore; } return cursor.source; @@ -16,7 +20,7 @@ const getEffectiveObjectStore = (cursor) => { // range. It does not handle gt/gte distinctions, because it doesn't really matter much anyway, since for next/prev // cursor iteration it'd also have to look at values to be precise, which would be complicated. This should get us 99% // of the way there. -const makeKeyRange = (range, lowers, uppers) => { +const makeKeyRange = (range: FDBKeyRange, lowers: Array, uppers: Array) => { // Start with bounds from range let lower = range !== undefined ? range.lower : undefined; let upper = range !== undefined ? range.upper : undefined; @@ -50,21 +54,27 @@ const makeKeyRange = (range, lowers, uppers) => { if (upper !== undefined) { return FDBKeyRange.upperBound(upper); } -} +}; // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#cursor class FDBCursor { - constructor(source, range, direction = 'next', request) { - this._gotValue = false; - this._range = range; - this._position = undefined; // Key of previously returned record - this._objectStorePosition = undefined; - this._request = request; + public _request: FDBRequest | void; + + private _gotValue: boolean = false; + private _range: Range; + private _position = undefined; // Key of previously returned record + private _objectStorePosition = undefined; + private _source: any; + private _direction: FDBCursorDirection; + private _key = undefined; + private _primaryKey: Key | void = undefined; + + constructor(source: any, range: Range, direction: FDBCursorDirection = "next", request?: FDBRequest) { + this._range = range; this._source = source; this._direction = direction; - this._key = undefined; - this._primaryKey = undefined; + this._request = request; } // Read only properties @@ -82,8 +92,8 @@ class FDBCursor { } // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-steps-for-iterating-a-cursor - _iterate(key) { - const sourceIsObjectStore = !this.source.hasOwnProperty('_rawIndex'); + public _iterate(key?: Key): this | null { + const sourceIsObjectStore = !this.source.hasOwnProperty("_rawIndex"); const records = sourceIsObjectStore ? this.source._rawObjectStore.records : this.source._rawIndex.records; @@ -144,7 +154,7 @@ class FDBCursor { } } else if (this.direction === "prev") { const range = makeKeyRange(this._range, [], [key, this._position]); - for (const record of records.values(range, 'prev')) { + for (const record of records.values(range, "prev")) { if (key !== undefined) { if (cmp(record.key, key) === 1) { continue; @@ -175,7 +185,7 @@ class FDBCursor { } else if (this.direction === "prevunique") { let tempRecord; const range = makeKeyRange(this._range, [], [key, this._position]); - for (const record of records.values(range, 'prev')) { + for (const record of records.values(range, "prev")) { if (key !== undefined) { if (cmp(record.key, key) === 1) { continue; @@ -204,8 +214,11 @@ class FDBCursor { if (!foundRecord) { this._key = undefined; if (!sourceIsObjectStore) { this._objectStorePosition = undefined; } - if (this.constructor.name === 'FDBCursorWithValue') { - this.value = undefined; + + // "this instanceof FDBCursorWithValue" would be better and not require (this as any), but causes runtime + // error due to circular dependency. + if (this.constructor.name === "FDBCursorWithValue") { + (this as any).value = undefined; } result = null; } else { @@ -214,13 +227,14 @@ class FDBCursor { this._key = foundRecord.key; if (sourceIsObjectStore) { this._primaryKey = structuredClone(foundRecord.key); - if (this.constructor.name === 'FDBCursorWithValue') { - this.value = structuredClone(foundRecord.value); + if (this.constructor.name === "FDBCursorWithValue") { + (this as any).value = structuredClone(foundRecord.value); } } else { this._primaryKey = structuredClone(foundRecord.value); - if (this.constructor.name === 'FDBCursorWithValue') { - this.value = structuredClone(this.source.objectStore._rawObjectStore.getValue(foundRecord.value)); + if (this.constructor.name === "FDBCursorWithValue") { + const value = this.source.objectStore._rawObjectStore.getValue(foundRecord.value); + (this as any).value = structuredClone(value); } } this._gotValue = true; @@ -231,14 +245,14 @@ class FDBCursor { } // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#widl-IDBCursor-update-IDBRequest-any-value - update(value) { + public update(value: Value) { if (value === undefined) { throw new TypeError(); } const effectiveObjectStore = getEffectiveObjectStore(this); - const effectiveKey = this.source.hasOwnProperty('_rawIndex') ? this.primaryKey : this._position; + const effectiveKey = this.source.hasOwnProperty("_rawIndex") ? this.primaryKey : this._position; const transaction = effectiveObjectStore.transaction; - if (transaction.mode === 'readonly') { + if (transaction.mode === "readonly") { throw new ReadOnlyError(); } @@ -250,7 +264,7 @@ class FDBCursor { throw new InvalidStateError(); } - if (!this._gotValue || !this.hasOwnProperty('value')) { + if (!this._gotValue || !this.hasOwnProperty("value")) { throw new InvalidStateError(); } @@ -268,17 +282,22 @@ class FDBCursor { const record = { key: effectiveKey, - value: structuredClone(value) + value: structuredClone(value), }; return transaction._execRequestAsync({ + operation: effectiveObjectStore._rawObjectStore.storeRecord.bind( + effectiveObjectStore._rawObjectStore, + record, + false, + transaction._rollbackLog, + ), source: this, - operation: effectiveObjectStore._rawObjectStore.storeRecord.bind(effectiveObjectStore._rawObjectStore, record, false, transaction._rollbackLog) }); } // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#widl-IDBCursor-advance-void-unsigned-long-count - advance(count) { + public advance(count: number) { if (!Number.isInteger(count) || count <= 0) { throw new TypeError(); } const effectiveObjectStore = getEffectiveObjectStore(this); @@ -296,9 +315,10 @@ class FDBCursor { throw new InvalidStateError(); } - this._request.readyState = 'pending'; + if (this._request) { + this._request.readyState = "pending"; + } transaction._execRequestAsync({ - source: this.source, operation: () => { let result; for (let i = 0; i < count; i++) { @@ -311,14 +331,15 @@ class FDBCursor { } return result; }, - request: this._request + request: this._request, + source: this.source, }); this._gotValue = false; } // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#widl-IDBCursor-continue-void-any-key - continue(key) { + public continue(key?: Key) { const effectiveObjectStore = getEffectiveObjectStore(this); const transaction = effectiveObjectStore.transaction; @@ -339,28 +360,30 @@ class FDBCursor { const cmpResult = cmp(key, this._position); - if ((cmpResult <= 0 && (this.direction === 'next' || this.direction === 'nextunique')) || - (cmpResult >= 0 && (this.direction === 'prev' || this.direction === 'prevunique'))) { + if ((cmpResult <= 0 && (this.direction === "next" || this.direction === "nextunique")) || + (cmpResult >= 0 && (this.direction === "prev" || this.direction === "prevunique"))) { throw new DataError(); } } - this._request.readyState = 'pending'; + if (this._request) { + this._request.readyState = "pending"; + } transaction._execRequestAsync({ - source: this.source, operation: this._iterate.bind(this, key), - request: this._request + request: this._request, + source: this.source, }); this._gotValue = false; } - delete() { + public delete() { const effectiveObjectStore = getEffectiveObjectStore(this); - const effectiveKey = this.source.hasOwnProperty('_rawIndex') ? this.primaryKey : this._position; + const effectiveKey = this.source.hasOwnProperty("_rawIndex") ? this.primaryKey : this._position; const transaction = effectiveObjectStore.transaction; - if (transaction.mode === 'readonly') { + if (transaction.mode === "readonly") { throw new ReadOnlyError(); } @@ -372,19 +395,23 @@ class FDBCursor { throw new InvalidStateError(); } - if (!this._gotValue || !this.hasOwnProperty('value')) { + if (!this._gotValue || !this.hasOwnProperty("value")) { throw new InvalidStateError(); } return transaction._execRequestAsync({ + operation: effectiveObjectStore._rawObjectStore.deleteRecord.bind( + effectiveObjectStore._rawObjectStore, + effectiveKey, + transaction._rollbackLog, + ), source: this, - operation: effectiveObjectStore._rawObjectStore.deleteRecord.bind(effectiveObjectStore._rawObjectStore, effectiveKey, transaction._rollbackLog) }); } - toString() { - return '[object IDBCursor]'; + public toString() { + return "[object IDBCursor]"; } } -module.exports = FDBCursor; +export default FDBCursor; diff --git a/src/FDBCursorWithValue.js b/src/FDBCursorWithValue.js deleted file mode 100644 index e27bf162..00000000 --- a/src/FDBCursorWithValue.js +++ /dev/null @@ -1,15 +0,0 @@ -const FDBCursor = require('./FDBCursor'); - -class FDBCursorWithValue extends FDBCursor { - constructor(source, range, direction, request) { - super(source, range, direction, request); - - this.value = undefined; - } - - toString() { - return '[object IDBCursorWithValue]'; - } -} - -module.exports = FDBCursorWithValue; \ No newline at end of file diff --git a/src/FDBCursorWithValue.ts b/src/FDBCursorWithValue.ts new file mode 100644 index 00000000..2f749707 --- /dev/null +++ b/src/FDBCursorWithValue.ts @@ -0,0 +1,16 @@ +import FDBCursor from "./FDBCursor"; +import {FDBCursorDirection, Value} from "./lib/types"; + +class FDBCursorWithValue extends FDBCursor { + public value: Value = undefined; + + constructor(source: any, range: any, direction?: FDBCursorDirection, request?: any) { + super(source, range, direction, request); + } + + public toString() { + return "[object IDBCursorWithValue]"; + } +} + +export default FDBCursorWithValue; diff --git a/src/FDBDatabase.js b/src/FDBDatabase.js index c431b8a7..151106b7 100644 --- a/src/FDBDatabase.js +++ b/src/FDBDatabase.js @@ -1,9 +1,9 @@ -const EventTarget = require('./lib/EventTarget'); -const FDBTransaction = require('./FDBTransaction'); -const ObjectStore = require('./lib/ObjectStore'); +const EventTarget = require('./lib/EventTarget').default; +const FDBTransaction = require('./FDBTransaction').default; +const ObjectStore = require('./lib/ObjectStore').default; const {ConstraintError, InvalidAccessError, InvalidStateError, NotFoundError, TransactionInactiveError} = require('./lib/errors'); const addDomStringListMethods = require('./lib/addDomStringListMethods'); -const validateKeyPath = require('./lib/validateKeyPath'); +const validateKeyPath = require('./lib/validateKeyPath').default; const confirmActiveVersionchangeTransaction = (database) => { if (!database._runningVersionchangeTransaction) { @@ -144,8 +144,7 @@ class FDBDatabase extends EventTarget { } } - const tx = new FDBTransaction(storeNames, mode); - tx.db = this; + const tx = new FDBTransaction(storeNames, mode, this); this._rawDatabase.transactions.push(tx); this._rawDatabase.processTransactions(); // See if can start right away (async) diff --git a/src/FDBFactory.js b/src/FDBFactory.js index 674e799a..df6561d1 100644 --- a/src/FDBFactory.js +++ b/src/FDBFactory.js @@ -1,10 +1,10 @@ -const Event = require('./lib/Event'); -const Database = require('./lib/Database'); -const FDBOpenDBRequest = require('./FDBOpenDBRequest'); -const FDBDatabase = require('./FDBDatabase'); -const FDBVersionChangeEvent = require('./FDBVersionChangeEvent'); -const {AbortError, VersionError} = require('./lib/errors'); -const cmp = require('./lib/cmp'); +const FDBDatabase = require("./FDBDatabase"); +const FDBOpenDBRequest = require("./FDBOpenDBRequest").default; +const FDBVersionChangeEvent = require("./FDBVersionChangeEvent").default; +const cmp = require("./lib/cmp").default; +const Database = require("./lib/Database").default; +const {AbortError, VersionError} = require("./lib/errors"); +const Event = require("./lib/Event").default; const waitForOthersClosedDelete = (databases, name, openDatabases, cb) => { const anyOpen = openDatabases.some((openDatabase) => { @@ -38,7 +38,7 @@ const deleteDatabase = (databases, name, request, cb) => { for (const openDatabase of openDatabases) { if (!openDatabase._closePending) { - const event = new FDBVersionChangeEvent('versionchange', { + const event = new FDBVersionChangeEvent("versionchange", { oldVersion: db.version, newVersion: null }); @@ -51,7 +51,7 @@ const deleteDatabase = (databases, name, request, cb) => { }); if (request && anyOpen) { - const event = new FDBVersionChangeEvent('blocked', { + const event = new FDBVersionChangeEvent("blocked", { oldVersion: db.version, newVersion: null }); @@ -76,7 +76,7 @@ const runVersionchangeTransaction = (connection, version, request, cb) => { for (const openDatabase of openDatabases) { if (!openDatabase._closed) { - const event = new FDBVersionChangeEvent('versionchange', { + const event = new FDBVersionChangeEvent("versionchange", { oldVersion: oldVersion, newVersion: version }); @@ -89,7 +89,7 @@ const runVersionchangeTransaction = (connection, version, request, cb) => { }); if (anyOpen) { - const event = new FDBVersionChangeEvent('blocked', { + const event = new FDBVersionChangeEvent("blocked", { oldVersion: oldVersion, newVersion: version }); @@ -106,12 +106,13 @@ const runVersionchangeTransaction = (connection, version, request, cb) => { return; } -// Set the version of database to version. This change is considered part of the transaction, and so if the transaction is aborted, this change is reverted. + // Set the version of database to version. This change is considered part of the transaction, and so if the + // transaction is aborted, this change is reverted. connection._rawDatabase.version = version; connection.version = version; // Get rid of this setImmediate? - const transaction = connection.transaction(connection.objectStoreNames, 'versionchange'); + const transaction = connection.transaction(connection.objectStoreNames, "versionchange"); request.result = connection; request.transaction = transaction; @@ -120,27 +121,27 @@ const runVersionchangeTransaction = (connection, version, request, cb) => { connection.version = oldVersion; }); - const event = new FDBVersionChangeEvent('upgradeneeded', { + const event = new FDBVersionChangeEvent("upgradeneeded", { oldVersion: oldVersion, newVersion: version }); request.dispatchEvent(event); - request.readyState = 'done'; + request.readyState = "done"; - transaction.addEventListener('error', () => { + transaction.addEventListener("error", () => { connection._runningVersionchangeTransaction = false; //throw arguments[0].target.error; -//console.log('error in versionchange transaction - not sure if anything needs to be done here', e.target.error.name); +//console.log("error in versionchange transaction - not sure if anything needs to be done here", e.target.error.name); }); - transaction.addEventListener('abort', () => { + transaction.addEventListener("abort", () => { connection._runningVersionchangeTransaction = false; request.transaction = null; setImmediate(() => { cb(new AbortError()); }); }); - transaction.addEventListener('complete', () => { + transaction.addEventListener("complete", () => { connection._runningVersionchangeTransaction = false; request.transaction = null; // Let other complete event handlers run before continuing @@ -209,11 +210,11 @@ class FDBFactory { request.error = new Error(); request.error.name = err.name; - const event = new Event('error', { + const event = new Event("error", { bubbles: true, cancelable: false }); - event._eventPath = []; + event.eventPath = []; request.dispatchEvent(event); return; @@ -221,7 +222,7 @@ class FDBFactory { request.result = undefined; - const event = new FDBVersionChangeEvent('success', { + const event = new FDBVersionChangeEvent("success", { oldVersion: version, newVersion: null }); @@ -232,6 +233,7 @@ class FDBFactory { return request; } + // tslint:disable-next-line max-line-length // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#widl-IDBFactory-open-IDBOpenDBRequest-DOMString-name-unsigned-long-long-version open(name, version) { if (arguments.length > 1 && (isNaN(version) || version < 1 || version >= 9007199254740992)) { @@ -249,11 +251,11 @@ class FDBFactory { request.error = new Error(); request.error.name = err.name; - const event = new Event('error', { + const event = new Event("error", { bubbles: true, cancelable: false }); - event._eventPath = []; + event.eventPath = []; request.dispatchEvent(event); return; @@ -261,8 +263,8 @@ class FDBFactory { request.result = connection; - const event = new Event('success'); - event._eventPath = []; + const event = new Event("success"); + event.eventPath = []; request.dispatchEvent(event); }); }); @@ -271,7 +273,7 @@ class FDBFactory { } toString() { - return '[object IDBFactory]'; + return "[object IDBFactory]"; } } diff --git a/src/FDBIndex.js b/src/FDBIndex.ts similarity index 71% rename from src/FDBIndex.js rename to src/FDBIndex.ts index 732e6ebc..10e805db 100644 --- a/src/FDBIndex.js +++ b/src/FDBIndex.ts @@ -1,12 +1,13 @@ -const structuredClone = require('./lib/structuredClone'); -const FDBCursor = require('./FDBCursor'); -const FDBCursorWithValue = require('./FDBCursorWithValue'); -const FDBKeyRange = require('./FDBKeyRange'); -const FDBRequest = require('./FDBRequest'); -const {InvalidStateError, TransactionInactiveError} = require('./lib/errors'); -const validateKey = require('./lib/validateKey'); - -const confirmActiveTransaction = (index) => { +import FDBCursor from "./FDBCursor"; +import FDBCursorWithValue from "./FDBCursorWithValue"; +import FDBKeyRange from "./FDBKeyRange"; +import FDBRequest from "./FDBRequest"; +const {InvalidStateError, TransactionInactiveError} = require("./lib/errors"); +import structuredClone from "./lib/structuredClone"; +import {FDBCursorDirection, Key, KeyPath} from "./lib/types"; +import validateKey from "./lib/validateKey"; + +const confirmActiveTransaction = (index: FDBIndex) => { if (!index.objectStore.transaction._active) { throw new TransactionInactiveError(); } @@ -18,7 +19,14 @@ const confirmActiveTransaction = (index) => { // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#idl-def-IDBIndex class FDBIndex { - constructor(objectStore, rawIndex) { + public _rawIndex: any; + public name: string; + public objectStore: any; + public keyPath: KeyPath; + public multiEntry: boolean; + public unique: boolean; + + constructor(objectStore: any, rawIndex: any) { this._rawIndex = rawIndex; this.name = rawIndex.name; @@ -28,8 +36,9 @@ class FDBIndex { this.unique = rawIndex.unique; } + // tslint:disable-next-line max-line-length // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#widl-IDBIndex-openCursor-IDBRequest-any-range-IDBCursorDirection-direction - openCursor(range, direction) { + public openCursor(range: FDBKeyRange | Key | null | void, direction: FDBCursorDirection) { confirmActiveTransaction(this); if (range === null) { range = undefined; } @@ -41,18 +50,18 @@ class FDBIndex { request.source = this; request.transaction = this.objectStore.transaction; - const cursor = new FDBCursorWithValue(this, range, direction); - cursor._request = request; + const cursor = new FDBCursorWithValue(this, range, direction, request); return this.objectStore.transaction._execRequestAsync({ - source: this, operation: cursor._iterate.bind(cursor), - request: request, + request, + source: this, }); } + // tslint:disable-next-line max-line-length // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#widl-IDBIndex-openKeyCursor-IDBRequest-any-range-IDBCursorDirection-direction - openKeyCursor(range, direction) { + public openKeyCursor(range: FDBKeyRange | Key | null | void, direction: FDBCursorDirection) { confirmActiveTransaction(this); if (range === null) { range = undefined; } @@ -64,17 +73,16 @@ class FDBIndex { request.source = this; request.transaction = this.objectStore.transaction; - const cursor = new FDBCursor(this, range, direction); - cursor._request = request; + const cursor = new FDBCursor(this, range, direction, request); return this.objectStore.transaction._execRequestAsync({ - source: this, operation: cursor._iterate.bind(cursor), - request: request + request, + source: this, }); } - get(key) { + public get(key: FDBKeyRange | Key) { confirmActiveTransaction(this); if (!(key instanceof FDBKeyRange)) { @@ -82,13 +90,13 @@ class FDBIndex { } return this.objectStore.transaction._execRequestAsync({ + operation: this._rawIndex.getValue.bind(this._rawIndex, key), source: this, - operation: this._rawIndex.getValue.bind(this._rawIndex, key) }); } // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#widl-IDBIndex-getKey-IDBRequest-any-key - getKey(key) { + public getKey(key: FDBKeyRange | Key) { confirmActiveTransaction(this); if (!(key instanceof FDBKeyRange)) { @@ -96,13 +104,13 @@ class FDBIndex { } return this.objectStore.transaction._execRequestAsync({ + operation: this._rawIndex.getKey.bind(this._rawIndex, key), source: this, - operation: this._rawIndex.getKey.bind(this._rawIndex, key) }); } // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#widl-IDBIndex-count-IDBRequest-any-key - count(key) { + public count(key: FDBKeyRange | Key | null | void) { confirmActiveTransaction(this); if (key === null) { key = undefined; } @@ -111,7 +119,6 @@ class FDBIndex { } return this.objectStore.transaction._execRequestAsync({ - source: this, operation: () => { let count = 0; @@ -122,12 +129,13 @@ class FDBIndex { return count; }, + source: this, }); } - toString() { - return '[object IDBIndex]'; + public toString() { + return "[object IDBIndex]"; } } -module.exports = FDBIndex; +export default FDBIndex; diff --git a/src/FDBKeyRange.js b/src/FDBKeyRange.js deleted file mode 100644 index 4f959545..00000000 --- a/src/FDBKeyRange.js +++ /dev/null @@ -1,86 +0,0 @@ -const {DataError} = require('./lib/errors'); -const cmp = require('./lib/cmp'); -const validateKey = require('./lib/validateKey'); - -// http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#range-concept -class FDBKeyRange { - constructor() { - this.lower = undefined; - this.upper = undefined; - this.lowerOpen = undefined; - this.upperOpen = undefined; - } - - static only(value) { - if (value === undefined) { throw new TypeError(); } - validateKey(value); - const keyRange = new FDBKeyRange(); - keyRange.lower = value; - keyRange.upper = value; - keyRange.lowerOpen = false; - keyRange.upperOpen = false; - return keyRange; - } - - static lowerBound(lower, open) { - if (lower === undefined) { throw new TypeError(); } - validateKey(lower); - const keyRange = new FDBKeyRange(); - keyRange.lower = lower; - keyRange.lowerOpen = open === true ? true : false; - keyRange.upperOpen = true; - return keyRange; - } - - static upperBound(upper, open) { - if (upper === undefined) { throw new TypeError(); } - validateKey(upper); - const keyRange = new FDBKeyRange(); - keyRange.upper = upper; - keyRange.lowerOpen = true; - keyRange.upperOpen = open === true ? true : false; - return keyRange; - } - - static bound(lower, upper, lowerOpen, upperOpen) { - if (lower === undefined || upper === undefined) { throw new TypeError(); } - - const cmpResult = cmp(lower, upper); - if (cmpResult === 1 || (cmpResult === 0 && (lowerOpen || upperOpen))) { - throw new DataError(); - } - - validateKey(lower); - validateKey(upper); - const keyRange = new FDBKeyRange(); - keyRange.lower = lower; - keyRange.upper = upper; - keyRange.lowerOpen = lowerOpen === true ? true : false; - keyRange.upperOpen = upperOpen === true ? true : false; - return keyRange; - } - - static check(keyRange, key) { - if (keyRange.lower !== undefined) { - const cmpResult = cmp(keyRange.lower, key); - - if (cmpResult === 1 || (cmpResult === 0 && keyRange.lowerOpen)) { - return false; - } - } - if (keyRange.upper !== undefined) { - const cmpResult = cmp(keyRange.upper, key); - - if (cmpResult === -1 || (cmpResult === 0 && keyRange.upperOpen)) { - return false; - } - } - return true; - } - - toString() { - return '[object IDBKeyRange]'; - } -} - -module.exports = FDBKeyRange; diff --git a/src/FDBKeyRange.ts b/src/FDBKeyRange.ts new file mode 100644 index 00000000..413f973e --- /dev/null +++ b/src/FDBKeyRange.ts @@ -0,0 +1,74 @@ +import cmp from "./lib/cmp"; +const {DataError} = require("./lib/errors"); +import {Key} from "./lib/types"; +import validateKey from "./lib/validateKey"; + +// http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#range-concept +class FDBKeyRange { + public static only(value: Key) { + if (value === undefined) { throw new TypeError(); } + validateKey(value); + return new FDBKeyRange(value, value, false, false); + } + + public static lowerBound(lower: Key, open: boolean = false) { + if (lower === undefined) { throw new TypeError(); } + validateKey(lower); + return new FDBKeyRange(lower, undefined, open, true); + } + + public static upperBound(upper: Key, open: boolean = false) { + if (upper === undefined) { throw new TypeError(); } + validateKey(upper); + return new FDBKeyRange(undefined, upper, true, open); + } + + public static bound(lower: Key, upper: Key, lowerOpen: boolean = false, upperOpen: boolean = false) { + if (lower === undefined || upper === undefined) { throw new TypeError(); } + + const cmpResult = cmp(lower, upper); + if (cmpResult === 1 || (cmpResult === 0 && (lowerOpen || upperOpen))) { + throw new DataError(); + } + + validateKey(lower); + validateKey(upper); + return new FDBKeyRange(lower, upper, lowerOpen, upperOpen); + } + + public static check(keyRange: FDBKeyRange, key: Key) { + if (keyRange.lower !== undefined) { + const cmpResult = cmp(keyRange.lower, key); + + if (cmpResult === 1 || (cmpResult === 0 && keyRange.lowerOpen)) { + return false; + } + } + if (keyRange.upper !== undefined) { + const cmpResult = cmp(keyRange.upper, key); + + if (cmpResult === -1 || (cmpResult === 0 && keyRange.upperOpen)) { + return false; + } + } + return true; + } + + public readonly lower: Key | void; + public readonly upper: Key | void; + public readonly lowerOpen: boolean; + public readonly upperOpen: boolean; + + constructor(lower: Key | void, upper: Key | void, lowerOpen: boolean, upperOpen: boolean) { + this.lower = lower; + this.upper = upper; + this.lowerOpen = lowerOpen; + this.upperOpen = upperOpen; + } + + public toString() { + return "[object IDBKeyRange]"; + } +} + +export default FDBKeyRange; diff --git a/src/FDBObjectStore.js b/src/FDBObjectStore.ts similarity index 64% rename from src/FDBObjectStore.js rename to src/FDBObjectStore.ts index d8036b5e..1ec30a6f 100644 --- a/src/FDBObjectStore.js +++ b/src/FDBObjectStore.ts @@ -1,17 +1,27 @@ -const structuredClone = require('./lib/structuredClone'); -const Index = require('./lib/Index'); -const FDBCursor = require('./FDBCursor'); -const FDBCursorWithValue = require('./FDBCursorWithValue'); -const FDBIndex = require('./FDBIndex'); -const FDBKeyRange = require('./FDBKeyRange'); -const FDBRequest = require('./FDBRequest'); -const {ConstraintError, DataError, InvalidAccessError, InvalidStateError, NotFoundError, ReadOnlyError, TransactionInactiveError} = require('./lib/errors'); -const addDomStringListMethods = require('./lib/addDomStringListMethods'); -const extractKey = require('./lib/extractKey'); -const validateKey = require('./lib/validateKey'); -const validateKeyPath = require('./lib/validateKeyPath'); - -const confirmActiveTransaction = (objectStore) => { +import FDBCursor from "./FDBCursor"; +import FDBCursorWithValue from "./FDBCursorWithValue"; +import FDBIndex from "./FDBIndex"; +import FDBKeyRange from "./FDBKeyRange"; +import FDBRequest from "./FDBRequest"; +const { + ConstraintError, + DataError, + InvalidAccessError, + InvalidStateError, + NotFoundError, + ReadOnlyError, + TransactionInactiveError, +} = require("./lib/errors"); +const addDomStringListMethods = require("./lib/addDomStringListMethods"); +import extractKey from "./lib/extractKey"; +import Index from "./lib/Index"; +import ObjectStore from "./lib/ObjectStore"; +import structuredClone from "./lib/structuredClone"; +import {FDBCursorDirection, Key, KeyPath, Value} from "./lib/types"; +import validateKey from "./lib/validateKey"; +import validateKeyPath from "./lib/validateKeyPath"; + +const confirmActiveTransaction = (objectStore: FDBObjectStore) => { if (objectStore._rawObjectStore.deleted) { throw new InvalidStateError(); } @@ -21,8 +31,8 @@ const confirmActiveTransaction = (objectStore) => { } }; -const buildRecordAddPut = (objectStore, value, key) => { - if (objectStore.transaction.mode === 'readonly') { +const buildRecordAddPut = (objectStore: FDBObjectStore, value: Value, key: Key) => { + if (objectStore.transaction.mode === "readonly") { throw new ReadOnlyError(); } @@ -54,13 +64,22 @@ const buildRecordAddPut = (objectStore, value, key) => { return { key: structuredClone(key), - value: structuredClone(value) + value: structuredClone(value), }; }; // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#object-store class FDBObjectStore { - constructor(transaction, rawObjectStore) { + public _rawObjectStore: ObjectStore; + public _rawIndexesCache: {[key: string]: FDBIndex}; + + public name: string; + public keyPath: KeyPath | null; + public autoIncrement: boolean; + public transaction: any; + public indexNames: string[]; + + constructor(transaction: any, rawObjectStore: ObjectStore) { this._rawObjectStore = rawObjectStore; this._rawIndexesCache = {}; // Store the FDBIndex objects @@ -72,42 +91,51 @@ class FDBObjectStore { addDomStringListMethods(this.indexNames); } - put(value, key) { + public put(value: Value, key?: Key) { const record = buildRecordAddPut(this, value, key); return this.transaction._execRequestAsync({ + operation: this._rawObjectStore.storeRecord.bind( + this._rawObjectStore, + record, + false, + this.transaction._rollbackLog, + ), source: this, - operation: this._rawObjectStore.storeRecord.bind(this._rawObjectStore, record, false, this.transaction._rollbackLog) }); } - add(value, key) { + public add(value: Value, key?: Key) { const record = buildRecordAddPut(this, value, key); return this.transaction._execRequestAsync({ + operation: this._rawObjectStore.storeRecord.bind( + this._rawObjectStore, + record, + true, + this.transaction._rollbackLog, + ), source: this, - operation: this._rawObjectStore.storeRecord.bind(this._rawObjectStore, record, true, this.transaction._rollbackLog) }); } - delete(key) { - if (this.transaction.mode === 'readonly') { + public delete(key: Key) { + if (this.transaction.mode === "readonly") { throw new ReadOnlyError(); } confirmActiveTransaction(this); - if (!(key instanceof FDBKeyRange)) { key = structuredClone(validateKey(key)); } return this.transaction._execRequestAsync({ + operation: this._rawObjectStore.deleteRecord.bind(this._rawObjectStore, key, this.transaction._rollbackLog), source: this, - operation: this._rawObjectStore.deleteRecord.bind(this._rawObjectStore, key, this.transaction._rollbackLog) }); } - get(key) { + public get(key?: Key) { confirmActiveTransaction(this); if (!(key instanceof FDBKeyRange)) { @@ -115,24 +143,24 @@ class FDBObjectStore { } return this.transaction._execRequestAsync({ + operation: this._rawObjectStore.getValue.bind(this._rawObjectStore, key), source: this, - operation: this._rawObjectStore.getValue.bind(this._rawObjectStore, key) }); } - clear() { - if (this.transaction.mode === 'readonly') { + public clear() { + if (this.transaction.mode === "readonly") { throw new ReadOnlyError(); } confirmActiveTransaction(this); return this.transaction._execRequestAsync({ + operation: this._rawObjectStore.clear.bind(this._rawObjectStore, this.transaction._rollbackLog), source: this, - operation: this._rawObjectStore.clear.bind(this._rawObjectStore, this.transaction._rollbackLog) }); } - openCursor(range, direction) { + public openCursor(range: FDBKeyRange | Key, direction?: FDBCursorDirection) { confirmActiveTransaction(this); if (range === null) { range = undefined; } @@ -144,25 +172,28 @@ class FDBObjectStore { request.source = this; request.transaction = this.transaction; - const cursor = new FDBCursorWithValue(this, range, direction); - cursor._request = request; + const cursor = new FDBCursorWithValue(this, range, direction, request); return this.transaction._execRequestAsync({ - source: this, operation: cursor._iterate.bind(cursor), - request: request + request, + source: this, }); } + // tslint:disable-next-line max-line-length // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#widl-IDBObjectStore-createIndex-IDBIndex-DOMString-name-DOMString-sequence-DOMString--keyPath-IDBIndexParameters-optionalParameters - createIndex(name, keyPath, optionalParameters) { + public createIndex( + name: string, + keyPath: KeyPath, + optionalParameters: {multiEntry?: boolean, unique?: boolean} = {}, + ) { if (keyPath === undefined) { throw new TypeError(); } - optionalParameters = optionalParameters !== undefined ? optionalParameters : {}; const multiEntry = optionalParameters.multiEntry !== undefined ? optionalParameters.multiEntry : false; const unique = optionalParameters.unique !== undefined ? optionalParameters.unique : false; - if (this.transaction.mode !== 'versionchange') { + if (this.transaction.mode !== "versionchange") { throw new InvalidStateError(); } @@ -178,13 +209,19 @@ class FDBObjectStore { throw new InvalidAccessError(); } -// The index that is requested to be created can contain constraints on the data allowed in the index's referenced object store, such as requiring uniqueness of the values referenced by the index's keyPath. If the referenced object store already contains data which violates these constraints, this MUST NOT cause the implementation of createIndex to throw an exception or affect what it returns. The implementation MUST still create and return an IDBIndex object. Instead the implementation must queue up an operation to abort the "versionchange" transaction which was used for the createIndex call. + // The index that is requested to be created can contain constraints on the data allowed in the index's + // referenced object store, such as requiring uniqueness of the values referenced by the index's keyPath. If the + // referenced object store already contains data which violates these constraints, this MUST NOT cause the + // implementation of createIndex to throw an exception or affect what it returns. The implementation MUST still + // create and return an IDBIndex object. Instead the implementation must queue up an operation to abort the + // "versionchange" transaction which was used for the createIndex call. - this.transaction._rollbackLog.push(function (indexNames) { + const indexNames = this.indexNames.slice(); + this.transaction._rollbackLog.push(() => { this.indexNames = indexNames; addDomStringListMethods(this.indexNames); delete this._rawObjectStore.rawIndexes[name]; - }.bind(this, this.indexNames.slice())); + }); const index = new Index(this._rawObjectStore, name, keyPath, multiEntry, unique); this.indexNames.push(name); @@ -196,7 +233,7 @@ class FDBObjectStore { return new FDBIndex(this, index); } - index(name) { + public index(name: string) { if (name === undefined) { throw new TypeError(); } if (this._rawIndexesCache.hasOwnProperty(name)) { @@ -217,10 +254,10 @@ class FDBObjectStore { return index; } - deleteIndex(name) { + public deleteIndex(name: string) { if (name === undefined) { throw new TypeError(); } - if (this.transaction.mode !== 'versionchange') { + if (this.transaction.mode !== "versionchange") { throw new InvalidStateError(); } @@ -230,12 +267,13 @@ class FDBObjectStore { throw new NotFoundError(); } - this.transaction._rollbackLog.push(function (index) { + const index = this._rawObjectStore.rawIndexes[name]; + this.transaction._rollbackLog.push(() => { index.deleted = false; this._rawObjectStore.rawIndexes[name] = index; this.indexNames.push(name); this.indexNames.sort(); - }.bind(this, this._rawObjectStore.rawIndexes[name])); + }); this.indexNames = this.indexNames.filter((indexName) => { return indexName !== name; @@ -244,15 +282,15 @@ class FDBObjectStore { this._rawObjectStore.rawIndexes[name].deleted = true; // Not sure if this is supposed to happen synchronously this.transaction._execRequestAsync({ - source: this, operation: () => { delete this._rawObjectStore.rawIndexes[name]; }, + source: this, }); } // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#widl-IDBObjectStore-count-IDBRequest-any-key - count(key) { + public count(key?: Key | FDBKeyRange) { confirmActiveTransaction(this); if (key === null) { key = undefined; } @@ -261,7 +299,6 @@ class FDBObjectStore { } return this.transaction._execRequestAsync({ - source: this, operation: () => { let count = 0; @@ -272,12 +309,13 @@ class FDBObjectStore { return count; }, + source: this, }); } - toString() { - return '[object IDBObjectStore]'; + public toString() { + return "[object IDBObjectStore]"; } } -module.exports = FDBObjectStore; +export default FDBObjectStore; diff --git a/src/FDBOpenDBRequest.js b/src/FDBOpenDBRequest.js deleted file mode 100644 index 4298783f..00000000 --- a/src/FDBOpenDBRequest.js +++ /dev/null @@ -1,16 +0,0 @@ -const FDBRequest = require('./FDBRequest'); - -class FDBOpenDBRequest extends FDBRequest { - constructor() { - super(); - - this.onupgradeneeded = null; - this.onblocked = null; - } - - toString() { - return '[object IDBOpenDBRequest]'; - } -} - -module.exports = FDBOpenDBRequest; diff --git a/src/FDBOpenDBRequest.ts b/src/FDBOpenDBRequest.ts new file mode 100644 index 00000000..582b29ca --- /dev/null +++ b/src/FDBOpenDBRequest.ts @@ -0,0 +1,13 @@ +import FDBRequest from "./FDBRequest"; +import {EventCallback} from "./lib/types"; + +class FDBOpenDBRequest extends FDBRequest { + public onupgradeneeded: EventCallback | null = null; + public onblocked: EventCallback | null = null; + + public toString() { + return "[object IDBOpenDBRequest]"; + } +} + +export default FDBOpenDBRequest; diff --git a/src/FDBRequest.js b/src/FDBRequest.js deleted file mode 100644 index 136a3e67..00000000 --- a/src/FDBRequest.js +++ /dev/null @@ -1,21 +0,0 @@ -const EventTarget = require('./lib/EventTarget'); - -class FDBRequest extends EventTarget { - constructor() { - super(); - - this.result = null; - this.error = null; - this.source = null; - this.transaction = null; - this.readyState = 'pending'; - this.onsuccess = null; - this.onerror = null; - } - - toString() { - return '[object IDBRequest]'; - } -} - -module.exports = FDBRequest; diff --git a/src/FDBRequest.ts b/src/FDBRequest.ts new file mode 100644 index 00000000..c6bdf8da --- /dev/null +++ b/src/FDBRequest.ts @@ -0,0 +1,18 @@ +import EventTarget from "./lib/EventTarget"; +import {EventCallback} from "./lib/types"; + +class FDBRequest extends EventTarget { + public result: any = null; + public error: Error | null | void = null; + public source: any = null; + public transaction = null; + public readyState: "done" | "pending" = "pending"; + public onsuccess: EventCallback | null = null; + public onerror: EventCallback | null = null; + + public toString() { + return "[object IDBRequest]"; + } +} + +export default FDBRequest; diff --git a/src/FDBTransaction.js b/src/FDBTransaction.ts similarity index 68% rename from src/FDBTransaction.js rename to src/FDBTransaction.ts index 5c95d65c..a131912d 100644 --- a/src/FDBTransaction.js +++ b/src/FDBTransaction.ts @@ -1,72 +1,80 @@ -const Event = require('./lib/Event'); -const EventTarget = require('./lib/EventTarget'); -const FDBObjectStore = require('./FDBObjectStore'); -const FDBRequest = require('./FDBRequest'); -const {AbortError, InvalidStateError, NotFoundError, TransactionInactiveError} = require('./lib/errors'); +import FDBObjectStore from "./FDBObjectStore"; +import FDBRequest from "./FDBRequest"; +const {AbortError, InvalidStateError, NotFoundError, TransactionInactiveError} = require("./lib/errors"); +import Event from "./lib/Event"; +import EventTarget from "./lib/EventTarget"; +import {EventCallback, RequestObj, RollbackLog} from "./lib/types"; + +type Mode = "readonly" | "readwrite"; // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#transaction class FDBTransaction extends EventTarget { - constructor(storeNames, mode) { + public _started = false; + public _active = true; + public _finished = false; // Set true after commit or abort + public _rollbackLog: RollbackLog = []; + + public mode: Mode; + public db: any; + public error: Error | null = null; + public onabort: EventCallback | null = null; + public oncomplete: EventCallback | null = null; + public onerror: EventCallback | null = null; + + private _scope: string[]; + private _requests: RequestObj[] = []; + + constructor(storeNames: string[], mode: Mode, db: any) { super(); this._scope = storeNames; - this._started = false; - this._active = true; - this._finished = false; // Set true after commit or abort - this._requests = []; - this._rollbackLog = []; - this.mode = mode; - this.db = null; - this.error = null; - this.onabort = null; - this.oncomplete = null; - this.onerror = null; + this.db = db; } // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-steps-for-aborting-a-transaction - _abort(error) { + public _abort(errName: string | null) { for (const f of this._rollbackLog.reverse()) { f(); } - if (error !== null) { + if (errName !== null) { const e = new Error(); - e.name = error; + e.name = errName; this.error = e; } // Should this directly remove from _requests? for (const {request} of this._requests) { - if (request.readyState !== 'done') { - request.readyState = 'done'; // This will cancel execution of this request's operation + if (request.readyState !== "done") { + request.readyState = "done"; // This will cancel execution of this request's operation if (request.source) { request.result = undefined; request.error = new AbortError(); - const event = new Event('error', { + const event = new Event("error", { bubbles: true, - cancelable: true + cancelable: true, }); - event._eventPath = [this.db, this]; + event.eventPath = [this.db, this]; request.dispatchEvent(event); } } } setImmediate(() => { - const event = new Event('abort', { + const event = new Event("abort", { bubbles: true, - cancelable: false + cancelable: false, }); - event._eventPath = [this.db]; + event.eventPath = [this.db]; this.dispatchEvent(event); }); this._finished = true; } - abort() { + public abort() { if (this._finished) { throw new InvalidStateError(); } @@ -75,7 +83,7 @@ class FDBTransaction extends EventTarget { this._abort(null); } - objectStore(name) { + public objectStore(name: string) { if (this._scope.indexOf(name) < 0) { throw new NotFoundError(); } @@ -88,10 +96,10 @@ class FDBTransaction extends EventTarget { } // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-steps-for-asynchronously-executing-a-request - _execRequestAsync(obj) { + public _execRequestAsync(obj: RequestObj) { const source = obj.source; const operation = obj.operation; - let request = obj.hasOwnProperty('request') ? obj.request : null; + let request = obj.hasOwnProperty("request") ? obj.request : null; if (!this._active) { throw new TransactionInactiveError(); @@ -101,25 +109,23 @@ class FDBTransaction extends EventTarget { if (!request) { if (!source) { // Special requests like indexes that just need to run some code - request = { - readyState: 'pending' - }; + request = new FDBRequest(); } else { request = new FDBRequest(); request.source = source; - request.transaction = source.transaction; + request.transaction = (source as any).transaction; } } this._requests.push({ - request: request, - operation: operation + request, + operation, }); return request; } - _start() { + public _start() { this._started = true; // Remove from request queue - cursor ones will be added back if necessary by cursor.continue and such @@ -129,49 +135,50 @@ class FDBTransaction extends EventTarget { const r = this._requests.shift(); // This should only be false if transaction was aborted - if (r.request.readyState !== 'done') { + if (r && r.request.readyState !== "done") { request = r.request; operation = r.operation; break; } } - if (request) { + if (request && operation) { if (!request.source) { - // Special requests like indexes that just need to run some code, with error handling already built into operation + // Special requests like indexes that just need to run some code, with error handling already built into + // operation operation(); } else { let defaultAction; let event; try { const result = operation(); - request.readyState = 'done'; + request.readyState = "done"; request.result = result; request.error = undefined; // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-fire-a-success-event this._active = true; - event = new Event('success', { + event = new Event("success", { bubbles: false, - cancelable: false + cancelable: false, }); } catch (err) { - request.readyState = 'done'; + request.readyState = "done"; request.result = undefined; request.error = err; // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-fire-an-error-event this._active = true; - event = new Event('error', { + event = new Event("error", { bubbles: true, - cancelable: true + cancelable: true, }); defaultAction = this._abort.bind(this, err.name); } try { - event._eventPath = [this.db, this]; + event.eventPath = [this.db, this]; request.dispatchEvent(event); // You're supposed to set this._active to false here, but I'm skipping that. @@ -182,15 +189,15 @@ class FDBTransaction extends EventTarget { // and for any other masochists who do similar things. It doesn't seem to break // any tests or functionality, and in fact if I uncomment this line it does make // transaction/promise interactions wonky. - //this._active = false; + // this._active = false; } catch (err) { -//console.error(err); - this._abort('AbortError'); +// console.error(err); + this._abort("AbortError"); throw err; } // Default action of event - if (!event._canceled) { + if (!event.canceled) { if (defaultAction) { defaultAction(); } @@ -213,16 +220,15 @@ class FDBTransaction extends EventTarget { this._finished = true; if (!this.error) { - const event = new Event(); - event.type = 'complete'; + const event = new Event("complete"); this.dispatchEvent(event); } } } - toString() { - return '[object IDBRequest]'; + public toString() { + return "[object IDBRequest]"; } } -module.exports = FDBTransaction; +export default FDBTransaction; diff --git a/src/FDBVersionChangeEvent.js b/src/FDBVersionChangeEvent.js deleted file mode 100644 index 7373cf99..00000000 --- a/src/FDBVersionChangeEvent.js +++ /dev/null @@ -1,16 +0,0 @@ -const Event = require('./lib/Event'); - -class FDBVersionChangeEvent extends Event { - constructor(type, parameters = {}) { - super(type); - - this.oldVersion = parameters.oldVersion !== undefined ? parameters.oldVersion : 0; - this.newVersion = parameters.newVersion !== undefined ? parameters.newVersion : null; - } - - toString () { - return '[object IDBVersionChangeEvent]'; - } -} - -module.exports = FDBVersionChangeEvent; diff --git a/src/FDBVersionChangeEvent.ts b/src/FDBVersionChangeEvent.ts new file mode 100644 index 00000000..bb47ed26 --- /dev/null +++ b/src/FDBVersionChangeEvent.ts @@ -0,0 +1,22 @@ +import Event from "./lib/Event"; + +class FDBVersionChangeEvent extends Event { + public newVersion: number | null; + public oldVersion: number; + + constructor( + type: "blocked" | "upgradeneeded" | "versionchange", + parameters: {newVersion?: number, oldVersion?: number} = {}, + ) { + super(type); + + this.newVersion = parameters.newVersion !== undefined ? parameters.newVersion : null; + this.oldVersion = parameters.oldVersion !== undefined ? parameters.oldVersion : 0; + } + + public toString() { + return "[object IDBVersionChangeEvent]"; + } +} + +export default FDBVersionChangeEvent; diff --git a/src/lib/Database.js b/src/lib/Database.ts similarity index 62% rename from src/lib/Database.js rename to src/lib/Database.ts index fe4a63f8..04022930 100644 --- a/src/lib/Database.js +++ b/src/lib/Database.ts @@ -1,18 +1,21 @@ // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-database class Database { - constructor(name, version) { - this.deletePending = false; - this.transactions = []; - this.rawObjectStores = {}; - this.connections = []; + public deletePending = false; + public readonly transactions: any[] = []; + public readonly rawObjectStores = {}; + public readonly connections = []; + public readonly name: string; + public version: number; + + constructor(name: string, version: number) { this.name = name; this.version = version; this.processTransactions = this.processTransactions.bind(this); } - processTransactions() { + public processTransactions() { setImmediate(() => { const anyRunning = this.transactions.some((transaction) => { return transaction._started && !transaction._finished; @@ -26,12 +29,12 @@ class Database { if (next) { next._start(); - next.addEventListener('complete', this.processTransactions); - next.addEventListener('abort', this.processTransactions); + next.addEventListener("complete", this.processTransactions); + next.addEventListener("abort", this.processTransactions); } } }); } } -module.exports = Database; +export default Database; diff --git a/src/lib/Event.js b/src/lib/Event.js deleted file mode 100644 index 7ef9e892..00000000 --- a/src/lib/Event.js +++ /dev/null @@ -1,46 +0,0 @@ -class Event { - constructor(type, eventInitDict = {}) { - this._eventPath = []; - - // Flags - this._stopPropagation = false; - this._stopImmediatePropagation = false; - this._canceled = false; - this._initialized = true; - this._dispatch = false; - - this.type = type; - this.target = null; - this.currentTarget = null; - - this.NONE = 0; - this.CAPTURING_PHASE = 1; - this.AT_TARGET = 2; - this.BUBBLING_PHASE = 3; - this.eventPhase = this.NONE; - - this.bubbles = eventInitDict.bubbles !== undefined ? eventInitDict.bubbles : false; - this.cancelable = eventInitDict.cancelable !== undefined ? eventInitDict.cancelable : false; - this.defaultPrevented = false; - - this.isTrusted = false; - this.timestamp = Date.now(); - } - - preventDefault() { - if (this.cancelable) { - this._canceled = true; - } - } - - stopPropagation() { - this._stopPropagation = true; - } - - stopImmediatePropagation() { - this._stopPropagation = true; - this._stopImmediatePropagation = true; - } -} - -module.exports = Event; diff --git a/src/lib/Event.ts b/src/lib/Event.ts new file mode 100644 index 00000000..d48f5fb1 --- /dev/null +++ b/src/lib/Event.ts @@ -0,0 +1,56 @@ +import EventTarget from "./EventTarget"; +import {EventType} from "./types"; + +class Event { + public eventPath: EventTarget[] = []; + public type: EventType; + + public readonly NONE = 0; + public readonly CAPTURING_PHASE = 1; + public readonly AT_TARGET = 2; + public readonly BUBBLING_PHASE = 3; + + // Flags + public propagationStopped = false; + public immediatePropagationStopped = false; + public canceled = false; + public initialized = true; + public dispatched = false; + + public target: EventTarget | null = null; + public currentTarget: EventTarget | null = null; + + public eventPhase: 0 | 1 | 2 | 3 = 0; + + public defaultPrevented = false; + + public isTrusted = false; + public timestamp = Date.now(); + + public bubbles: boolean; + public cancelable: boolean; + + constructor(type: EventType, eventInitDict: {bubbles?: boolean, cancelable?: boolean} = {}) { + this.type = type; + + this.bubbles = eventInitDict.bubbles !== undefined ? eventInitDict.bubbles : false; + this.cancelable = eventInitDict.cancelable !== undefined ? eventInitDict.cancelable : false; + } + + public preventDefault() { + if (this.cancelable) { + this.canceled = true; + } + } + + public stopPropagation() { + this.propagationStopped = true; + } + + public stopImmediatePropagation() { + this.propagationStopped = true; + this.immediatePropagationStopped = true; + } +} + +export default Event; diff --git a/src/lib/EventTarget.js b/src/lib/EventTarget.js deleted file mode 100644 index b4646c7e..00000000 --- a/src/lib/EventTarget.js +++ /dev/null @@ -1,106 +0,0 @@ -const {InvalidStateError} = require('./errors'); - -const stopped = (event, listener) => { - return event._stopImmediatePropagation || - (event.eventPhase === event.CAPTURING_PHASE && listener.capture === false) || - (event.eventPhase === event.BUBBLING_PHASE && listener.capture === true); -}; - -// http://www.w3.org/TR/dom/#concept-event-listener-invoke -const invokeEventListeners = (event, obj) => { - event.currentTarget = obj; - - for (const listener of obj._listeners) { - if (event.type !== listener.type || stopped(event, listener)) { - continue; - } - - listener.callback.call(event.currentTarget, event); - } - - const callback = event.currentTarget[`on${event.type}`]; - if (callback) { - const listener = { - type: event.type, - callback, - capture: false - }; - if (!stopped(event, listener)) { - listener.callback.call(event.currentTarget, event); - } - } -}; - -class EventTarget { - constructor() { - this._listeners = []; - } - - addEventListener(type, callback, capture) { - if (callback === null) { return; } - capture = capture !== undefined ? capture : false; - - this._listeners.push({ - type: type, - callback: callback, - capture: capture - }); - } - - removeEventListener(type, callback, capture) { - capture = capture !== undefined ? capture : false; - - const i = this._listeners.findIndex((listener) => { - return listener.type === type && - listener.callback === callback && - listener.capture === capture; - }); - - this._listeners.splice(i, 1); - } - - // http://www.w3.org/TR/dom/#dispatching-events - dispatchEvent(event) { - if (event._dispatch || !event._initialized) { - throw new InvalidStateError('The object is in an invalid state.'); - } - event._isTrusted = false; - - event._dispatch = true; - event.target = this; -// NOT SURE WHEN THIS SHOULD BE SET event._eventPath = []; - - event.eventPhase = event.CAPTURING_PHASE; - for (const obj of event._eventPath) { - if (!event._stopPropagation) { - invokeEventListeners(event, obj); - } - } - - event.eventPhase = event.AT_TARGET; - if (!event._stopPropagation) { - invokeEventListeners(event, event.target); - } - - if (event.bubbles) { - event._eventPath.reverse(); - event.eventPhase = event.BUBBLING_PHASE; - for (const obj of event._eventPath) { - if (!event._stopPropagation) { - invokeEventListeners(event, obj); - } - } - } - - event._dispatch = false; - event.eventPhase = event.NONE; - event.currentTarget = null; - - if (event._canceled) { - return false; - } - return true; - } -} - -module.exports = EventTarget; diff --git a/src/lib/EventTarget.ts b/src/lib/EventTarget.ts new file mode 100644 index 00000000..9b23a831 --- /dev/null +++ b/src/lib/EventTarget.ts @@ -0,0 +1,144 @@ +const {InvalidStateError} = require("./errors"); +import Event from "./Event"; +import {EventCallback, EventType} from "./types"; + +type EventTypeProp = ( + "onabort" | + "onblocked" | + "oncomplete" | + "onerror" | + "onsuccess" | + "onupgradeneeded" | + "onversionchange" +); + +interface Listener { + callback: EventCallback; + capture: boolean; + type: EventType; +} + +const stopped = (event: Event, listener: Listener) => { + return ( + event.immediatePropagationStopped || + (event.eventPhase === event.CAPTURING_PHASE && listener.capture === false) || + (event.eventPhase === event.BUBBLING_PHASE && listener.capture === true) + ); +}; + +// http://www.w3.org/TR/dom/#concept-event-listener-invoke +const invokeEventListeners = (event: Event, obj: EventTarget) => { + event.currentTarget = obj; + + for (const listener of obj.listeners) { + if (event.type !== listener.type || stopped(event, listener)) { + continue; + } + + listener.callback.call(event.currentTarget, event); + } + + const typeToProp: {[key in EventType]: EventTypeProp} = { + abort: "onabort", + blocked: "onblocked", + complete: "oncomplete", + error: "onerror", + success: "onsuccess", + upgradeneeded: "onupgradeneeded", + versionchange: "onversionchange", + }; + const prop = typeToProp[event.type]; + if (prop === undefined) { + throw new Error(`Unknown event type: "${event.type}"`); + } + + const callback = event.currentTarget[prop]; + if (callback) { + const listener = { + callback, + capture: false, + type: event.type, + }; + if (!stopped(event, listener)) { + listener.callback.call(event.currentTarget, event); + } + } +}; + +abstract class EventTarget { + public readonly listeners: Listener[] = []; + + // These will be overridden in individual subclasses and made not readonly + public readonly onabort: EventCallback | null | void; + public readonly onblocked: EventCallback | null | void; + public readonly oncomplete: EventCallback | null | void; + public readonly onerror: EventCallback | null | void; + public readonly onsuccess: EventCallback | null | void; + public readonly onupgradeneeded: EventCallback | null | void; + public readonly onversionchange: EventCallback | null | void; + + public addEventListener(type: EventType, callback: EventCallback | null, capture = false) { + if (callback === null) { return; } + + this.listeners.push({ + callback, + capture, + type, + }); + } + + public removeEventListener(type: EventType, callback: EventCallback, capture = false) { + const i = this.listeners.findIndex((listener) => { + return listener.type === type && + listener.callback === callback && + listener.capture === capture; + }); + + this.listeners.splice(i, 1); + } + + // http://www.w3.org/TR/dom/#dispatching-events + public dispatchEvent(event: Event) { + if (event.dispatched || !event.initialized) { + throw new InvalidStateError("The object is in an invalid state."); + } + event.isTrusted = false; + + event.dispatched = true; + event.target = this; +// NOT SURE WHEN THIS SHOULD BE SET event.eventPath = []; + + event.eventPhase = event.CAPTURING_PHASE; + for (const obj of event.eventPath) { + if (!event.propagationStopped) { + invokeEventListeners(event, obj); + } + } + + event.eventPhase = event.AT_TARGET; + if (!event.propagationStopped) { + invokeEventListeners(event, event.target); + } + + if (event.bubbles) { + event.eventPath.reverse(); + event.eventPhase = event.BUBBLING_PHASE; + for (const obj of event.eventPath) { + if (!event.propagationStopped) { + invokeEventListeners(event, obj); + } + } + } + + event.dispatched = false; + event.eventPhase = event.NONE; + event.currentTarget = null; + + if (event.canceled) { + return false; + } + return true; + } +} + +export default EventTarget; diff --git a/src/lib/Index.js b/src/lib/Index.ts similarity index 75% rename from src/lib/Index.js rename to src/lib/Index.ts index dbc8d8c6..52aad13c 100644 --- a/src/lib/Index.js +++ b/src/lib/Index.ts @@ -1,16 +1,24 @@ -const RecordStore = require('./RecordStore'); -const {ConstraintError} = require('./errors'); -const extractKey = require('./extractKey'); -const validateKey = require('./validateKey'); +import RecordStore from "./RecordStore"; +const {ConstraintError} = require("./errors"); +import extractKey from "./extractKey"; +import {Key, KeyPath, Record} from "./types"; +import validateKey from "./validateKey"; // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-index class Index { - constructor(rawObjectStore, name, keyPath, multiEntry, unique) { - this.records = new RecordStore(); + public deleted = false; +// Initialized should be used to decide whether to throw an error or abort the versionchange transaction when there is a +// constraint + public initialized = false; + public readonly rawObjectStore: any; + public readonly records = new RecordStore(); + public name: string; + public readonly keyPath: KeyPath; + public multiEntry: boolean; + public unique: boolean; + + constructor(rawObjectStore: any, name: string, keyPath: KeyPath, multiEntry: boolean, unique: boolean) { this.rawObjectStore = rawObjectStore; - this.initialized = false; - this.deleted = false; -// Initialized should be used to decide whether to throw an error or abort the versionchange transaction when there is a constraint this.name = name; this.keyPath = keyPath; @@ -19,26 +27,26 @@ class Index { } // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-steps-for-retrieving-a-value-from-an-index - getKey(key) { + public getKey(key: Key) { const record = this.records.get(key); return record !== undefined ? record.value : undefined; } // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#index-referenced-value-retrieval-operation - getValue(key) { + public getValue(key: Key) { const record = this.records.get(key); return record !== undefined ? this.rawObjectStore.getValue(record.value) : undefined; } // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-steps-for-storing-a-record-into-an-object-store (step 7) - storeRecord(newRecord) { + public storeRecord(newRecord: Record) { let indexKey; try { indexKey = extractKey(this.keyPath, newRecord.value); } catch (err) { - if (err.name === 'DataError') { + if (err.name === "DataError") { // Invalid key is not an actual error, just means we do not store an entry in this index return; } @@ -53,7 +61,8 @@ class Index { return; } } else { - // remove any elements from index key that are not valid keys and remove any duplicate elements from index key such that only one instance of the duplicate value remains. + // remove any elements from index key that are not valid keys and remove any duplicate elements from index + // key such that only one instance of the duplicate value remains. const keep = []; for (const part of indexKey) { if (keep.indexOf(part) < 0) { @@ -87,25 +96,24 @@ class Index { if (!this.multiEntry || !Array.isArray(indexKey)) { this.records.add({ key: indexKey, - value: newRecord.key + value: newRecord.key, }); } else { for (const individualIndexKey of indexKey) { this.records.add({ key: individualIndexKey, - value: newRecord.key + value: newRecord.key, }); } } } - initialize(transaction) { + public initialize(transaction: any) { if (this.initialized) { throw new Error("Index already initialized"); } transaction._execRequestAsync({ - source: null, operation: () => { try { // Create index based on current value of objectstore @@ -115,12 +123,13 @@ class Index { this.initialized = true; } catch (err) { -//console.error(err); +// console.error(err); transaction._abort(err.name); } }, + source: null, }); } } -module.exports = Index; +export default Index; diff --git a/src/lib/KeyGenerator.js b/src/lib/KeyGenerator.ts similarity index 60% rename from src/lib/KeyGenerator.js rename to src/lib/KeyGenerator.ts index 503d5e7c..db246994 100644 --- a/src/lib/KeyGenerator.js +++ b/src/lib/KeyGenerator.ts @@ -1,14 +1,12 @@ -const {ConstraintError} = require('./errors'); +const {ConstraintError} = require("./errors"); const MAX_KEY = 9007199254740992; class KeyGenerator { - constructor() { -// This is kind of wrong. Should start at 1 and increment only after record is saved - this.num = 0; - } + // This is kind of wrong. Should start at 1 and increment only after record is saved + public num = 0; - next() { + public next() { if (this.num >= MAX_KEY) { throw new ConstraintError(); } @@ -18,7 +16,7 @@ class KeyGenerator { return this.num; } - setIfLarger(num) { + public setIfLarger(num: number) { if (num > MAX_KEY) { throw new ConstraintError(); } @@ -29,4 +27,4 @@ class KeyGenerator { } } -module.exports = KeyGenerator; +export default KeyGenerator; diff --git a/src/lib/ObjectStore.js b/src/lib/ObjectStore.ts similarity index 71% rename from src/lib/ObjectStore.js rename to src/lib/ObjectStore.ts index 192471fd..dd5fe7ad 100644 --- a/src/lib/ObjectStore.js +++ b/src/lib/ObjectStore.ts @@ -1,15 +1,23 @@ -const structuredClone = require('./structuredClone'); -const KeyGenerator = require('./KeyGenerator'); -const RecordStore = require('./RecordStore'); -const {ConstraintError, DataError} = require('./errors'); -const extractKey = require('./extractKey'); +import extractKey from "./extractKey"; +import KeyGenerator from "./KeyGenerator"; +import RecordStore from "./RecordStore"; +import structuredClone from "./structuredClone"; +import {Key, KeyPath, Record, RollbackLog} from "./types"; +const {ConstraintError, DataError} = require("./errors"); // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-object-store class ObjectStore { - constructor(rawDatabase, name, keyPath, autoIncrement) { + public deleted = false; + public readonly rawDatabase: any; + public readonly records = new RecordStore(); + public readonly rawIndexes: {[key: string]: any} = {}; + public name: string; + public readonly keyPath: KeyPath | null; + public readonly autoIncrement: boolean; + public readonly keyGenerator: KeyGenerator | null; + + constructor(rawDatabase: any, name: string, keyPath: KeyPath | null, autoIncrement: boolean) { this.rawDatabase = rawDatabase; - this.records = new RecordStore(); - this.rawIndexes = {}; this.keyGenerator = autoIncrement === true ? new KeyGenerator() : null; this.deleted = false; @@ -19,14 +27,14 @@ class ObjectStore { } // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-steps-for-retrieving-a-value-from-an-object-store - getValue(key) { + public getValue(key: Key) { const record = this.records.get(key); return record !== undefined ? structuredClone(record.value) : undefined; } // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-steps-for-storing-a-record-into-an-object-store - storeRecord(newRecord, noOverwrite, rollbackLog) { + public storeRecord(newRecord: Record, noOverwrite: boolean, rollbackLog: RollbackLog) { if (this.keyPath !== null) { const key = extractKey(this.keyPath, newRecord.value); if (key !== undefined) { @@ -36,9 +44,12 @@ class ObjectStore { if (this.keyGenerator !== null && newRecord.key === undefined) { if (rollbackLog) { - rollbackLog.push(function (keyGeneratorBefore) { - this.keyGenerator.num = keyGeneratorBefore; - }.bind(this, this.keyGenerator.num)); + const keyGeneratorBefore = this.keyGenerator.num; + rollbackLog.push(() => { + if (this.keyGenerator) { + this.keyGenerator.num = keyGeneratorBefore; + } + }); } newRecord.key = this.keyGenerator.next(); @@ -46,17 +57,20 @@ class ObjectStore { // Set in value if keyPath defiend but led to no key // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-steps-to-assign-a-key-to-a-value-using-a-key-path if (this.keyPath !== null) { + if (Array.isArray(this.keyPath)) { + throw new Error("Cannot have an array key path in an object store with a key generator"); + } let remainingKeyPath = this.keyPath; let object = newRecord.value; let identifier; let i = 0; // Just to run the loop at least once while (i >= 0) { - if (typeof object !== 'object') { + if (typeof object !== "object") { throw new DataError(); } - i = remainingKeyPath.indexOf('.'); + i = remainingKeyPath.indexOf("."); if (i >= 0) { identifier = remainingKeyPath.slice(0, i); remainingKeyPath = remainingKeyPath.slice(i + 1); @@ -73,7 +87,7 @@ class ObjectStore { object[identifier] = newRecord.key; } - } else if (this.keyGenerator !== null && typeof newRecord.key === 'number') { + } else if (this.keyGenerator !== null && typeof newRecord.key === "number") { this.keyGenerator.setIfLarger(newRecord.key); } @@ -102,7 +116,7 @@ class ObjectStore { } // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-steps-for-deleting-records-from-an-object-store - deleteRecord(key, rollbackLog) { + public deleteRecord(key: Key, rollbackLog: RollbackLog) { const deletedRecords = this.records.delete(key); if (rollbackLog) { @@ -118,7 +132,7 @@ class ObjectStore { } // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-steps-for-clearing-an-object-store - clear(rollbackLog) { + public clear(rollbackLog: RollbackLog) { const deletedRecords = this.records.clear(); if (rollbackLog) { @@ -134,4 +148,4 @@ class ObjectStore { } } -module.exports = ObjectStore; +export default ObjectStore; diff --git a/src/lib/RecordStore.js b/src/lib/RecordStore.ts similarity index 64% rename from src/lib/RecordStore.js rename to src/lib/RecordStore.ts index 5f8e1a3d..bb9e4a80 100644 --- a/src/lib/RecordStore.js +++ b/src/lib/RecordStore.ts @@ -1,40 +1,39 @@ -const FDBKeyRange = require('../FDBKeyRange'); -const cmp = require('./cmp'); +import FDBKeyRange from "../FDBKeyRange"; +import cmp from "./cmp"; +import {Key, Record} from "./types"; class RecordStore { - constructor() { - this._records = []; - } + private records: Record[] = []; - get(key) { + public get(key: Key) { if (key instanceof FDBKeyRange) { - return this._records.find((record) => { + return this.records.find((record) => { return FDBKeyRange.check(key, record.key); }); } - return this._records.find((record) => { + return this.records.find((record) => { return cmp(record.key, key) === 0; }); } - add(newRecord) { + public add(newRecord: Record) { // Find where to put it so it's sorted by key let i; - if (this._records.length === 0) { + if (this.records.length === 0) { i = 0; } else { - i = this._records.findIndex((record) => { + i = this.records.findIndex((record) => { return cmp(record.key, newRecord.key) === 1; }); if (i === -1) { // If no matching key, add to end - i = this._records.length; + i = this.records.length; } else { // If matching key, advance to appropriate position based on value (used in indexes) - while (i < this._records.length && cmp(this._records[i].key, newRecord.key) === 0) { - if (cmp(this._records[i].value, newRecord.value) !== -1) { + while (i < this.records.length && cmp(this.records[i].key, newRecord.key) === 0) { + if (cmp(this.records[i].value, newRecord.value) !== -1) { // Record value >= newRecord value, so insert here break; } @@ -44,15 +43,15 @@ class RecordStore { } } - this._records.splice(i, 0, newRecord); + this.records.splice(i, 0, newRecord); } - delete(key) { + public delete(key: Key) { const range = key instanceof FDBKeyRange ? key : FDBKeyRange.only(key); - const deletedRecords = []; + const deletedRecords: Record[] = []; - this._records = this._records.filter((record) => { + this.records = this.records.filter((record) => { const shouldDelete = FDBKeyRange.check(range, record.key); if (shouldDelete) { @@ -65,12 +64,12 @@ class RecordStore { return deletedRecords; } - deleteByValue(key) { + public deleteByValue(key: Key) { const range = key instanceof FDBKeyRange ? key : FDBKeyRange.only(key); - const deletedRecords = []; + const deletedRecords: Record[] = []; - this._records = this._records.filter((record) => { + this.records = this.records.filter((record) => { const shouldDelete = FDBKeyRange.check(range, record.value); if (shouldDelete) { @@ -83,27 +82,27 @@ class RecordStore { return deletedRecords; } - clear() { - const deletedRecords = this._records.slice(); - this._records = []; + public clear() { + const deletedRecords = this.records.slice(); + this.records = []; return deletedRecords; } - values(range, direction = 'next') { + public values(range?: FDBKeyRange, direction: "next" | "prev" = "next") { return { [Symbol.iterator]: () => { - let i; - if (direction === 'next') { + let i: number; + if (direction === "next") { i = 0; if (range !== undefined && range.lower !== undefined) { - while (this._records[i] !== undefined && cmp(this._records[i].key, range.lower) === -1) { + while (this.records[i] !== undefined && cmp(this.records[i].key, range.lower) === -1) { i += 1; } } } else { - i = this._records.length - 1; + i = this.records.length - 1; if (range !== undefined && range.upper !== undefined) { - while (this._records[i] !== undefined && cmp(this._records[i].key, range.upper) === 1) { + while (this.records[i] !== undefined && cmp(this.records[i].key, range.upper) === 1) { i -= 1; } } @@ -113,9 +112,9 @@ class RecordStore { next: () => { let done; let value; - if (direction === 'next') { - value = this._records[i]; - done = i >= this._records.length; + if (direction === "next") { + value = this.records[i]; + done = i >= this.records.length; i += 1; if (!done && range !== undefined && range.upper !== undefined) { @@ -125,7 +124,7 @@ class RecordStore { } } } else { - value = this._records[i]; + value = this.records[i]; done = i < 0; i -= 1; @@ -140,7 +139,7 @@ class RecordStore { return { value, done, - } + }; }, }; }, @@ -148,4 +147,4 @@ class RecordStore { } } -module.exports = RecordStore; +export default RecordStore; diff --git a/src/lib/cmp.js b/src/lib/cmp.ts similarity index 68% rename from src/lib/cmp.js rename to src/lib/cmp.ts index 579e94f2..d438c4c2 100644 --- a/src/lib/cmp.js +++ b/src/lib/cmp.ts @@ -1,25 +1,25 @@ -const {DataError} = require('./errors'); -const validateKey = require('./validateKey'); +const {DataError} = require("./errors"); +import validateKey from "./validateKey"; -const getType = (x) => { - if (typeof x === 'number') { - return 'Number'; +const getType = (x: any) => { + if (typeof x === "number") { + return "Number"; } if (x instanceof Date) { - return 'Date'; + return "Date"; } if (Array.isArray(x)) { - return 'Array'; + return "Array"; } - if (typeof x === 'string') { - return 'String'; + if (typeof x === "string") { + return "String"; } throw new DataError(); }; // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#widl-IDBFactory-cmp-short-any-first-any-second -const cmp = (first, second) => { +const cmp = (first: any, second: any): -1 | 0 | 1 => { if (second === undefined) { throw new TypeError(); } validateKey(first); @@ -29,19 +29,19 @@ const cmp = (first, second) => { const t2 = getType(second); if (t1 !== t2) { - if (t1 === 'Array') { + if (t1 === "Array") { return 1; } - if (t1 === 'String' && (t2 === 'Date' || t2 === 'Number')) { + if (t1 === "String" && (t2 === "Date" || t2 === "Number")) { return 1; } - if (t1 === 'Date' && t2 === 'Number') { + if (t1 === "Date" && t2 === "Number") { return 1; } return -1; } - if (t1 === 'Array') { + if (t1 === "Array") { const length = Math.min(first.length, second.length); for (let i = 0; i < length; i++) { const result = cmp(first[i], second[i]); @@ -60,7 +60,7 @@ const cmp = (first, second) => { return 0; } - if (t1 === 'Date') { + if (t1 === "Date") { if (first.getTime() === second.getTime()) { return 0; } @@ -72,4 +72,4 @@ const cmp = (first, second) => { return first > second ? 1 : -1; }; -module.exports = cmp; +export default cmp; diff --git a/src/lib/extractKey.js b/src/lib/extractKey.ts similarity index 59% rename from src/lib/extractKey.js rename to src/lib/extractKey.ts index d38fe546..83a33693 100644 --- a/src/lib/extractKey.js +++ b/src/lib/extractKey.ts @@ -1,33 +1,35 @@ -const structuredClone = require('./structuredClone'); -const validateKey = require('./validateKey'); +import structuredClone from "./structuredClone"; +import {Key, KeyPath, Value} from "./types"; +import validateKey from "./validateKey"; // 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, value) => { +const extractKey = (keyPath: KeyPath, value: Value) => { if (Array.isArray(keyPath)) { - const result = []; + const result: Key[] = []; - keyPath.forEach((item) => { - // 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 validateKey) - if (item !== undefined && item !== null && typeof item !== 'string' && item.toString) { - item = item.toString(); + 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(structuredClone(validateKey(extractKey(item, value)))); - }); + } return result; } - if (keyPath === '') { + if (keyPath === "") { return value; } - let remainingKeyPath = keyPath; + let remainingKeyPath: string | null = keyPath; let object = value; while (remainingKeyPath !== null) { let identifier; - const i = remainingKeyPath.indexOf('.'); + const i = remainingKeyPath.indexOf("."); if (i >= 0) { identifier = remainingKeyPath.slice(0, i); remainingKeyPath = remainingKeyPath.slice(i + 1); @@ -46,4 +48,4 @@ const extractKey = (keyPath, value) => { return object; }; -module.exports = extractKey; +export default extractKey; diff --git a/src/lib/structuredClone.js b/src/lib/structuredClone.js deleted file mode 100644 index 03e518e0..00000000 --- a/src/lib/structuredClone.js +++ /dev/null @@ -1,12 +0,0 @@ -const realisticStructuredClone = require('realistic-structured-clone'); -const {DataCloneError} = require('./errors'); - -const structuredClone = (input) => { - try { - return realisticStructuredClone(input); - } catch (err) { - throw new DataCloneError(); - } -}; - -module.exports = structuredClone; diff --git a/src/lib/structuredClone.ts b/src/lib/structuredClone.ts new file mode 100644 index 00000000..8859ce1a --- /dev/null +++ b/src/lib/structuredClone.ts @@ -0,0 +1,12 @@ +const realisticStructuredClone = require("realistic-structured-clone"); +const {DataCloneError} = require("./errors"); + +const structuredClone = (input: T): T => { + try { + return realisticStructuredClone(input); + } catch (err) { + throw new DataCloneError(); + } +}; + +export default structuredClone; diff --git a/src/lib/types.ts b/src/lib/types.ts new file mode 100644 index 00000000..ff6016e1 --- /dev/null +++ b/src/lib/types.ts @@ -0,0 +1,28 @@ +import FDBRequest from "../FDBRequest"; +import Event from "./Event"; +import EventTarget from "./EventTarget"; + +export type EventCallback = (event: Event) => void; + +export type EventType = "abort" | "blocked" | "complete" | "error" | "success" | "upgradeneeded" | "versionchange"; + +export type FDBCursorDirection = "next" | "nextunique" | "prev" | "prevunique"; + +export type KeyPath = string | string[]; + +export type Key = any; + +export type Value = any; + +export interface Record { + key: Key; + value: Key | Value; // For indexes, will be Key. For object stores, will be Value. +} + +export interface RequestObj { + operation: () => void; + request: FDBRequest; + source?: EventTarget; +} + +export type RollbackLog = Array<() => void>; diff --git a/src/lib/validateKey.js b/src/lib/validateKey.ts similarity index 76% rename from src/lib/validateKey.js rename to src/lib/validateKey.ts index 091ae02d..6e5f695f 100644 --- a/src/lib/validateKey.js +++ b/src/lib/validateKey.ts @@ -1,8 +1,8 @@ -const {DataError} = require('./errors'); +const {DataError} = require("./errors"); // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-valid-key -const validateKey = (key, seen) => { - if (typeof key === 'number') { +const validateKey = (key: any, seen?: Set) => { + if (typeof key === "number") { if (isNaN(key)) { throw new DataError(); } @@ -14,7 +14,7 @@ const validateKey = (key, seen) => { seen = seen !== undefined ? seen : new Set(); for (const x of key) { // Only need to test objects, because otherwise [0, 0] shows up as circular - if (typeof x === 'object' && seen.has(x)) { + if (typeof x === "object" && seen.has(x)) { throw new DataError(); } seen.add(x); @@ -29,11 +29,11 @@ const validateKey = (key, seen) => { throw new DataError(); } return key; - } else if (typeof key !== 'string') { + } else if (typeof key !== "string") { throw new DataError(); } return key; -} +}; -module.exports = validateKey; +export default validateKey; diff --git a/src/lib/validateKeyPath.js b/src/lib/validateKeyPath.ts similarity index 90% rename from src/lib/validateKeyPath.js rename to src/lib/validateKeyPath.ts index 1f9a2db5..7bdb4d33 100644 --- a/src/lib/validateKeyPath.js +++ b/src/lib/validateKeyPath.ts @@ -1,16 +1,27 @@ +import {KeyPath} from "./types"; + // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-valid-key-path -const validateKeyPath = (keyPath, parent) => { - // 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 extractKey) - if (keyPath !== undefined && keyPath !== null && typeof keyPath !== 'string' && keyPath.toString && (parent === 'array' || !Array.isArray(keyPath))) { +const validateKeyPath = (keyPath: KeyPath, parent?: "array" | "string") => { + // 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 extractKey) + if ( + keyPath !== undefined && + keyPath !== null && + typeof keyPath !== "string" && + keyPath.toString && + (parent === "array" || !Array.isArray(keyPath)) + ) { keyPath = keyPath.toString(); } - if (typeof keyPath === 'string') { - if (keyPath === '' && parent !== 'string') { + if (typeof keyPath === "string") { + if (keyPath === "" && parent !== "string") { return; } try { - // https://mathiasbynens.be/demo/javascript-identifier-regex for ECMAScript 5.1 / Unicode v7.0.0, with reserved words at beginning removed + // https://mathiasbynens.be/demo/javascript-identifier-regex for ECMAScript 5.1 / Unicode v7.0.0, with + // reserved words at beginning removed + // tslint:disable-next-line max-line-length const validIdentifierRegex = /^(?:[\$A-Z_a-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC])(?:[\$0-9A-Z_a-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0-\u08B2\u08E4-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D01-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D60-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA69D\uA69F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2D\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC])*$/; if (keyPath.length >= 1 && validIdentifierRegex.test(keyPath)) { return; @@ -18,24 +29,24 @@ const validateKeyPath = (keyPath, parent) => { } catch (err) { throw new SyntaxError(err.message); } - if (keyPath.indexOf(' ') >= 0) { - throw new SyntaxError('The keypath argument contains an invalid key path (no spaces allowed).'); + if (keyPath.indexOf(" ") >= 0) { + throw new SyntaxError("The keypath argument contains an invalid key path (no spaces allowed)."); } } if (Array.isArray(keyPath) && keyPath.length > 0) { if (parent) { // No nested arrays - throw new SyntaxError('The keypath argument contains an invalid key path (nested arrays).'); + throw new SyntaxError("The keypath argument contains an invalid key path (nested arrays)."); } for (const part of keyPath) { - validateKeyPath(part, 'array'); + validateKeyPath(part, "array"); } return; - } else if (typeof keyPath === 'string' && keyPath.indexOf('.') >= 0) { - keyPath = keyPath.split('.'); + } else if (typeof keyPath === "string" && keyPath.indexOf(".") >= 0) { + keyPath = keyPath.split("."); for (const part of keyPath) { - validateKeyPath(part, 'string'); + validateKeyPath(part, "string"); } return; } @@ -43,4 +54,4 @@ const validateKeyPath = (keyPath, parent) => { throw new SyntaxError(); }; -module.exports = validateKeyPath; +export default validateKeyPath; diff --git a/src/shim.js b/src/shim.js index 02714d34..1c4b6052 100644 --- a/src/shim.js +++ b/src/shim.js @@ -8,15 +8,15 @@ const globalVar = typeof window !== 'undefined' ? window : if (!globalVar.indexedDB) { globalVar.indexedDB = require('.'); - globalVar.IDBCursor = require('./FDBCursor'); - globalVar.IDBCursorWithValue = require('./FDBCursorWithValue'); + globalVar.IDBCursor = require('./FDBCursor').default; + globalVar.IDBCursorWithValue = require('./FDBCursorWithValue').default; globalVar.IDBDatabase = require('./FDBDatabase'); globalVar.IDBFactory = require('./FDBFactory'); - globalVar.IDBIndex = require('./FDBIndex'); - globalVar.IDBKeyRange = require('./FDBKeyRange'); - globalVar.IDBObjectStore = require('./FDBObjectStore'); - globalVar.IDBOpenDBRequest = require('./FDBOpenDBRequest'); - globalVar.IDBRequest = require('./FDBRequest'); - globalVar.IDBTransaction = require('./FDBTransaction'); - globalVar.IDBVersionChangeEvent = require('./FDBVersionChangeEvent'); + globalVar.IDBIndex = require('./FDBIndex').default; + globalVar.IDBKeyRange = require('./FDBKeyRange').default; + globalVar.IDBObjectStore = require('./FDBObjectStore').default; + globalVar.IDBOpenDBRequest = require('./FDBOpenDBRequest').default; + globalVar.IDBRequest = require('./FDBRequest').default; + globalVar.IDBTransaction = require('./FDBTransaction').default; + globalVar.IDBVersionChangeEvent = require('./FDBVersionChangeEvent').default; } diff --git a/src/test/exports-qunit.js b/src/test/exports-qunit.js index af2a17d1..261e7b9e 100644 --- a/src/test/exports-qunit.js +++ b/src/test/exports-qunit.js @@ -1,4 +1,4 @@ /* eslint-env browser */ window.indexedDBmock = require('..'); -window.IDBKeyRangemock = require('../FDBKeyRange'); +window.IDBKeyRangemock = require('../FDBKeyRange').default; diff --git a/src/test/indexedDBmock/index.html b/src/test/indexedDBmock/index.html index 70410e10..b35bf907 100644 --- a/src/test/indexedDBmock/index.html +++ b/src/test/indexedDBmock/index.html @@ -9,9 +9,9 @@
- - - + + + diff --git a/src/test/w3c/IDBCursor.advance.js b/src/test/w3c/IDBCursor.advance.js index 5faa8ddf..b475af67 100644 --- a/src/test/w3c/IDBCursor.advance.js +++ b/src/test/w3c/IDBCursor.advance.js @@ -1,7 +1,7 @@ var assert = require('assert'); var fakeIndexedDB = require('../..'); -var FDBCursor = require('../../FDBCursor'); -var FDBKeyRange = require('../../FDBKeyRange'); +var FDBCursor = require('../../FDBCursor').default; +var FDBKeyRange = require('../../FDBKeyRange').default; var {InvalidStateError, TransactionInactiveError} = require('../../lib/errors'); var support = require('./support'); var createdb = support.createdb; @@ -610,7 +610,6 @@ describe('W3C IDBCursor.advance Tests', function () { break; default: throw new Error("unexpected count"); - break; } }; } @@ -896,7 +895,6 @@ describe('W3C IDBCursor.advance Tests', function () { break; default: throw new Error("unexpected count"); - break; } }; } diff --git a/src/test/w3c/IDBCursor.continue.js b/src/test/w3c/IDBCursor.continue.js index 242dee35..f7c70dba 100644 --- a/src/test/w3c/IDBCursor.continue.js +++ b/src/test/w3c/IDBCursor.continue.js @@ -1,8 +1,8 @@ var assert = require('assert'); var fakeIndexedDB = require('../..'); -var FDBCursor = require('../../FDBCursor'); -var FDBCursorWithValue = require('../../FDBCursorWithValue'); -var FDBKeyRange = require('../../FDBKeyRange'); +var FDBCursor = require('../../FDBCursor').default; +var FDBCursorWithValue = require('../../FDBCursorWithValue').default; +var FDBKeyRange = require('../../FDBKeyRange').default; var {DataError, InvalidStateError, TransactionInactiveError} = require('../../lib/errors'); var support = require('./support'); var createdb = support.createdb; diff --git a/src/test/w3c/IDBCursor.delete.js b/src/test/w3c/IDBCursor.delete.js index d86a0191..8cf3fbba 100644 --- a/src/test/w3c/IDBCursor.delete.js +++ b/src/test/w3c/IDBCursor.delete.js @@ -1,5 +1,5 @@ var assert = require('assert'); -var FDBCursor = require('../../FDBCursor'); +var FDBCursor = require('../../FDBCursor').default; var {InvalidStateError, ReadOnlyError, TransactionInactiveError} = require('../../lib/errors'); var support = require('./support'); var createdb = support.createdb; diff --git a/src/test/w3c/IDBCursor.update.js b/src/test/w3c/IDBCursor.update.js index 210009cb..f20cabc8 100644 --- a/src/test/w3c/IDBCursor.update.js +++ b/src/test/w3c/IDBCursor.update.js @@ -1,5 +1,5 @@ var assert = require('assert'); -var FDBCursor = require('../../FDBCursor'); +var FDBCursor = require('../../FDBCursor').default; var {DataError, DataCloneError, InvalidStateError, ReadOnlyError, TransactionInactiveError} = require('../../lib/errors'); var support = require('./support'); var createdb = support.createdb; diff --git a/src/test/w3c/IDBCursorBehavior.js b/src/test/w3c/IDBCursorBehavior.js index 26f01f24..c1d27215 100644 --- a/src/test/w3c/IDBCursorBehavior.js +++ b/src/test/w3c/IDBCursorBehavior.js @@ -1,6 +1,6 @@ var assert = require('assert'); var fakeIndexedDB = require('../..'); -var FDBKeyRange = require('../../FDBKeyRange'); +var FDBKeyRange = require('../../FDBKeyRange').default; var support = require('./support'); var createdb = support.createdb; @@ -407,7 +407,6 @@ describe('W3C IDBCursor Behavior Tests', function () { case 511: case 611: throw new Error(cursor.key + " should be deleted and never run"); - break; } cursor.continue(); diff --git a/src/test/w3c/IDBDatabase.createObjectStore.js b/src/test/w3c/IDBDatabase.createObjectStore.js index 9537ea6b..9b1dfaf4 100644 --- a/src/test/w3c/IDBDatabase.createObjectStore.js +++ b/src/test/w3c/IDBDatabase.createObjectStore.js @@ -1,6 +1,6 @@ var assert = require('assert'); var fakeIndexedDB = require('../..'); -var FDBObjectStore = require('../../FDBObjectStore'); +var FDBObjectStore = require('../../FDBObjectStore').default; var {ConstraintError, InvalidStateError} = require('../../lib/errors'); var support = require('./support'); var createdb = support.createdb; diff --git a/src/test/w3c/IDBFactory.deleteDatabase.js b/src/test/w3c/IDBFactory.deleteDatabase.js index 30f423e7..974c3418 100644 --- a/src/test/w3c/IDBFactory.deleteDatabase.js +++ b/src/test/w3c/IDBFactory.deleteDatabase.js @@ -1,6 +1,6 @@ var assert = require('assert'); var fakeIndexedDB = require('../..'); -var FDBVersionChangeEvent = require('../../FDBVersionChangeEvent'); +var FDBVersionChangeEvent = require('../../FDBVersionChangeEvent').default; var support = require('./support'); var createdb = support.createdb; diff --git a/src/test/w3c/IDBFactory.open.js b/src/test/w3c/IDBFactory.open.js index 474579de..ebcd992c 100644 --- a/src/test/w3c/IDBFactory.open.js +++ b/src/test/w3c/IDBFactory.open.js @@ -1,8 +1,8 @@ var assert = require('assert'); var fakeIndexedDB = require('../..'); -var Event = require('../../lib/Event'); -var FDBVersionChangeEvent = require('../../FDBVersionChangeEvent'); -//var FDBTransaction = require('../../FDBTransaction'); +var Event = require('../../lib/Event').default; +var FDBVersionChangeEvent = require('../../FDBVersionChangeEvent').default; +//var FDBTransaction = require('../../FDBTransaction').default; //var {InvalidStateError} = require('../../lib/errors'); var support = require('./support'); var createdb = support.createdb; diff --git a/src/test/w3c/IDBIndex.count.js b/src/test/w3c/IDBIndex.count.js index 7046134a..2cc62cc9 100644 --- a/src/test/w3c/IDBIndex.count.js +++ b/src/test/w3c/IDBIndex.count.js @@ -1,5 +1,5 @@ var assert = require('assert'); -var FDBKeyRange = require('../../FDBKeyRange'); +var FDBKeyRange = require('../../FDBKeyRange').default; var {DataError} = require('../../lib/errors'); var support = require('./support'); var createdb = support.createdb; diff --git a/src/test/w3c/IDBIndex.get.js b/src/test/w3c/IDBIndex.get.js index df44a000..03039dad 100644 --- a/src/test/w3c/IDBIndex.get.js +++ b/src/test/w3c/IDBIndex.get.js @@ -1,5 +1,5 @@ var assert = require('assert'); -var FDBKeyRange = require('../../FDBKeyRange'); +var FDBKeyRange = require('../../FDBKeyRange').default; var {DataError, InvalidStateError, TransactionInactiveError} = require('../../lib/errors'); var support = require('./support'); var createdb = support.createdb; diff --git a/src/test/w3c/IDBIndex.getKey.js b/src/test/w3c/IDBIndex.getKey.js index a879fe9b..03d1b90b 100644 --- a/src/test/w3c/IDBIndex.getKey.js +++ b/src/test/w3c/IDBIndex.getKey.js @@ -1,5 +1,5 @@ var assert = require('assert'); -var FDBKeyRange = require('../../FDBKeyRange'); +var FDBKeyRange = require('../../FDBKeyRange').default; var {DataError, InvalidStateError, TransactionInactiveError} = require('../../lib/errors'); var support = require('./support'); var createdb = support.createdb; diff --git a/src/test/w3c/IDBKeyRange.js b/src/test/w3c/IDBKeyRange.js index ac9d8808..f95361bb 100644 --- a/src/test/w3c/IDBKeyRange.js +++ b/src/test/w3c/IDBKeyRange.js @@ -1,5 +1,5 @@ var assert = require('assert'); -var FDBKeyRange = require('../../FDBKeyRange'); +var FDBKeyRange = require('../../FDBKeyRange').default; var {DataError} = require('../../lib/errors'); describe('W3C IDBKeyRange Tests', function () { diff --git a/src/test/w3c/IDBObjectStore.add.js b/src/test/w3c/IDBObjectStore.add.js index d3452e60..ac8bdfca 100644 --- a/src/test/w3c/IDBObjectStore.add.js +++ b/src/test/w3c/IDBObjectStore.add.js @@ -1,5 +1,5 @@ var assert = require('assert'); -var FDBRequest = require('../../FDBRequest'); +var FDBRequest = require('../../FDBRequest').default; var {DataError, InvalidStateError, ReadOnlyError} = require('../../lib/errors'); var support = require('./support'); var createdb = support.createdb; diff --git a/src/test/w3c/IDBObjectStore.count.js b/src/test/w3c/IDBObjectStore.count.js index b1e0f211..69fabbe9 100644 --- a/src/test/w3c/IDBObjectStore.count.js +++ b/src/test/w3c/IDBObjectStore.count.js @@ -1,5 +1,5 @@ var assert = require('assert'); -var FDBKeyRange = require('../../FDBKeyRange'); +var FDBKeyRange = require('../../FDBKeyRange').default; var {InvalidStateError} = require('../../lib/errors'); var support = require('./support'); var createdb = support.createdb; diff --git a/src/test/w3c/IDBObjectStore.createIndex.js b/src/test/w3c/IDBObjectStore.createIndex.js index 8841c29a..bb28f272 100644 --- a/src/test/w3c/IDBObjectStore.createIndex.js +++ b/src/test/w3c/IDBObjectStore.createIndex.js @@ -1,5 +1,5 @@ var assert = require('assert'); -var FDBIndex = require('../../FDBIndex'); +var FDBIndex = require('../../FDBIndex').default; var {ConstraintError, InvalidStateError} = require('../../lib/errors'); var support = require('./support'); var createdb = support.createdb; diff --git a/src/test/w3c/IDBObjectStore.delete.js b/src/test/w3c/IDBObjectStore.delete.js index 64b48f86..bb8cc514 100644 --- a/src/test/w3c/IDBObjectStore.delete.js +++ b/src/test/w3c/IDBObjectStore.delete.js @@ -1,5 +1,5 @@ var assert = require('assert'); -var FDBKeyRange = require('../../FDBKeyRange'); +var FDBKeyRange = require('../../FDBKeyRange').default; var {InvalidStateError, ReadOnlyError} = require('../../lib/errors'); var support = require('./support'); var createdb = support.createdb; diff --git a/src/test/w3c/IDBObjectStore.get.js b/src/test/w3c/IDBObjectStore.get.js index b8878e00..85bbf89e 100644 --- a/src/test/w3c/IDBObjectStore.get.js +++ b/src/test/w3c/IDBObjectStore.get.js @@ -1,5 +1,5 @@ var assert = require('assert'); -var FDBKeyRange = require('../../FDBKeyRange'); +var FDBKeyRange = require('../../FDBKeyRange').default; var {DataError, TransactionInactiveError} = require('../../lib/errors'); var support = require('./support'); var createdb = support.createdb; diff --git a/src/test/w3c/IDBObjectStore.index.js b/src/test/w3c/IDBObjectStore.index.js index 8454dcbb..be7944e6 100644 --- a/src/test/w3c/IDBObjectStore.index.js +++ b/src/test/w3c/IDBObjectStore.index.js @@ -1,5 +1,5 @@ var assert = require('assert'); -var FDBIndex = require('../../FDBIndex'); +var FDBIndex = require('../../FDBIndex').default; var support = require('./support'); var createdb = support.createdb; diff --git a/src/test/w3c/IDBObjectStore.js b/src/test/w3c/IDBObjectStore.js index a1f2bf7e..bf96bc3e 100644 --- a/src/test/w3c/IDBObjectStore.js +++ b/src/test/w3c/IDBObjectStore.js @@ -1,6 +1,6 @@ var assert = require('assert'); -var FDBOpenDBRequest = require('../../FDBOpenDBRequest'); -var FDBTransaction = require('../../FDBTransaction'); +var FDBOpenDBRequest = require('../../FDBOpenDBRequest').default; +var FDBTransaction = require('../../FDBTransaction').default; var {InvalidStateError} = require('../../lib/errors'); var support = require('./support'); var createdb = support.createdb; diff --git a/src/test/w3c/IDBObjectStore.put.js b/src/test/w3c/IDBObjectStore.put.js index 62b40b8f..0173676e 100644 --- a/src/test/w3c/IDBObjectStore.put.js +++ b/src/test/w3c/IDBObjectStore.put.js @@ -1,5 +1,5 @@ var assert = require('assert'); -var FDBRequest = require('../../FDBRequest'); +var FDBRequest = require('../../FDBRequest').default; var {DataError, InvalidStateError, ReadOnlyError} = require('../../lib/errors'); var support = require('./support'); var createdb = support.createdb; diff --git a/src/test/w3c/IDBTransaction.abort.js b/src/test/w3c/IDBTransaction.abort.js index a9d72e54..3a351e84 100644 --- a/src/test/w3c/IDBTransaction.abort.js +++ b/src/test/w3c/IDBTransaction.abort.js @@ -1,5 +1,5 @@ var assert = require('assert'); -var FDBIndex = require('../../FDBIndex'); +var FDBIndex = require('../../FDBIndex').default; var support = require('./support'); var createdb = support.createdb; diff --git a/src/test/w3c/IDBTransaction.js b/src/test/w3c/IDBTransaction.js index 75f2155f..508901ef 100644 --- a/src/test/w3c/IDBTransaction.js +++ b/src/test/w3c/IDBTransaction.js @@ -1,7 +1,7 @@ var assert = require('assert'); var indexedDB = require('../..'); -var FDBOpenDBRequest = require('../../FDBOpenDBRequest'); -var FDBTransaction = require('../../FDBTransaction'); +var FDBOpenDBRequest = require('../../FDBOpenDBRequest').default; +var FDBTransaction = require('../../FDBTransaction').default; var {InvalidStateError} = require('../../lib/errors'); var support = require('./support'); var createdb = support.createdb; diff --git a/src/test/w3c/KeyPath.js b/src/test/w3c/KeyPath.js index 931deca7..51a1f85b 100644 --- a/src/test/w3c/KeyPath.js +++ b/src/test/w3c/KeyPath.js @@ -1,5 +1,5 @@ var assert = require('assert'); -//var FDBRequest = require('../../FDBRequest'); +//var FDBRequest = require('../../FDBRequest').default; //var {DataError} = require('../../lib/errors'); var support = require('./support'); var createdb = support.createdb; @@ -121,13 +121,13 @@ describe('W3C Key Path Tests', function () { [ [10, 20], [100, 1.337] ], "['x', {toString->'y'}] (stringifies)"); - if (false) { +/* if (false) { var myblob = Blob(["Yoda"], {type:'suprawsum'}); keypath(['length', 'type'], [ myblob ], [ 4, 'suprawsum' ], "[Blob.length, Blob.type]"); - } + }*/ // File.name and File.lastModifiedDate is not testable automatically diff --git a/src/test/w3c/KeyValidity.js b/src/test/w3c/KeyValidity.js index 231e9a27..a946b707 100644 --- a/src/test/w3c/KeyValidity.js +++ b/src/test/w3c/KeyValidity.js @@ -1,5 +1,5 @@ var assert = require('assert'); -var FDBRequest = require('../../FDBRequest'); +var FDBRequest = require('../../FDBRequest').default; var {DataError} = require('../../lib/errors'); var support = require('./support'); var createdb = support.createdb; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..30d6cd80 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "rootDir": "./src", + "outDir": "./build", + "target": "es2015", + "module": "commonjs", + "allowJs": true, + "noEmitOnError": true, + "noImplicitAny": true, + "strictNullChecks": true + }, + "exclude": [ + "node_modules", + "build" + ] +} diff --git a/tslint.json b/tslint.json new file mode 100644 index 00000000..e7c0ecbd --- /dev/null +++ b/tslint.json @@ -0,0 +1,8 @@ +{ + "extends": "tslint:latest", + "rules": { + "interface-name": [true, "never-prefix"], + "no-var-requires": false, + "variable-name": false + } +}