modularize repo, use pnpm, improve typechecking
This commit is contained in:
parent
aa481e4267
commit
ffd2a62c3f
6
.gitignore
vendored
6
.gitignore
vendored
@ -1,10 +1,10 @@
|
|||||||
.idea/
|
.idea/
|
||||||
.nyc_output/
|
.nyc_output/
|
||||||
dist/
|
dist/
|
||||||
|
lib/
|
||||||
|
node_modules/
|
||||||
|
|
||||||
# Even though node_modules are tracked in git,
|
tsconfig.tsbuildinfo
|
||||||
# per default we don't want them to show up in git status
|
|
||||||
node_modules
|
|
||||||
|
|
||||||
*.swp
|
*.swp
|
||||||
|
|
||||||
|
2
.yarnrc
2
.yarnrc
@ -1,2 +0,0 @@
|
|||||||
yarn-offline-mirror "./npm-packages-offline-cache"
|
|
||||||
yarn-offline-mirror-pruning true
|
|
36
Makefile
36
Makefile
@ -9,9 +9,10 @@ nyc = node_modules/nyc/bin/nyc.js
|
|||||||
|
|
||||||
include config.mk
|
include config.mk
|
||||||
|
|
||||||
.PHONY: tsc
|
.PHONY: compile
|
||||||
tsc: yarn-install
|
compile:
|
||||||
$(tsc)
|
pnpm i
|
||||||
|
pnpm run compile
|
||||||
|
|
||||||
.PHONY: dist
|
.PHONY: dist
|
||||||
dist:
|
dist:
|
||||||
@ -24,30 +25,22 @@ typedoc:
|
|||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
rm -rf dist/ config.mk
|
pnpm run clean
|
||||||
|
|
||||||
.PHONY: submodules-update
|
.PHONY: submodules-update
|
||||||
submodules-update:
|
submodules-update:
|
||||||
git submodule update --recursive --remote
|
git submodule update --recursive --remote
|
||||||
|
|
||||||
.PHONY: check
|
.PHONY: check
|
||||||
check: tsc yarn-install
|
check: compile
|
||||||
$(ava)
|
pnpm run check
|
||||||
|
|
||||||
.PHONY: coverage
|
|
||||||
coverage: tsc yarn-install
|
|
||||||
$(nyc) --all $(ava) 'build/**/*-test.js'
|
|
||||||
|
|
||||||
.PHONY: yarn-install
|
|
||||||
yarn-install:
|
|
||||||
$(yarn) install
|
|
||||||
|
|
||||||
.PHONY: webextensions
|
.PHONY: webextensions
|
||||||
webextensions: rollup
|
webextensions: rollup
|
||||||
./webextension/pack.sh
|
./webextension/pack.sh
|
||||||
|
|
||||||
.PHONY: i18n
|
.PHONY: i18n
|
||||||
i18n: yarn-install
|
i18n: compile
|
||||||
# extract translatable strings
|
# extract translatable strings
|
||||||
find $(src) \( -name '*.ts' -or -name '*.tsx' \) ! -name '*.d.ts' \
|
find $(src) \( -name '*.ts' -or -name '*.tsx' \) ! -name '*.d.ts' \
|
||||||
| xargs node $(pogen) \
|
| xargs node $(pogen) \
|
||||||
@ -75,14 +68,19 @@ warn-noprefix:
|
|||||||
@echo "no prefix configured, did you run ./configure?"
|
@echo "no prefix configured, did you run ./configure?"
|
||||||
install: warn-noprefix
|
install: warn-noprefix
|
||||||
else
|
else
|
||||||
|
install_target = $(prefix)/lib/taler-wallet-cli
|
||||||
.PHONY: install
|
.PHONY: install
|
||||||
install: tsc
|
install: # compile
|
||||||
@echo "installing to" $(prefix)
|
install -d $(install_target)/node_modules/taler-wallet-cli
|
||||||
$(yarn) global add file://$(CURDIR) --prefix $(prefix)
|
install -d $(install_target)/node_modules/taler-wallet-cli/bin
|
||||||
|
install -d $(install_target)/node_modules/taler-wallet-cli/dist
|
||||||
|
install ./packages/taler-wallet-cli/dist/taler-wallet-cli.js $(install_target)/node_modules/taler-wallet-cli/dist/
|
||||||
|
install ./packages/taler-wallet-cli/bin/taler-wallet-cli $(install_target)/node_modules/taler-wallet-cli/bin/
|
||||||
|
ln -sft $(prefix)/bin $(install_target)/node_modules/taler-wallet-cli/bin/taler-wallet-cli
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: rollup
|
.PHONY: rollup
|
||||||
rollup: yarn-install
|
rollup: compile
|
||||||
./node_modules/.bin/rollup -c
|
./node_modules/.bin/rollup -c
|
||||||
|
|
||||||
.PHONY: lint
|
.PHONY: lint
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
require('source-map-support').install();
|
|
||||||
require('../dist/node/headless/taler-wallet-cli.js')
|
|
94
package.json
94
package.json
@ -1,94 +1,8 @@
|
|||||||
{
|
{
|
||||||
"name": "taler-wallet",
|
"private": true,
|
||||||
"version": "0.6.12",
|
|
||||||
"description": "",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.12.0"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git://git.taler.net/wallet-core.git"
|
|
||||||
},
|
|
||||||
"author": "Florian Dold",
|
|
||||||
"license": "GPL-3.0",
|
|
||||||
"bin": {
|
|
||||||
"taler-wallet-cli": "./bin/taler-wallet-cli"
|
|
||||||
},
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "make tsc",
|
"compile": "pnpm run --filter '{packages}' compile",
|
||||||
"pretty": "prettier --config .prettierrc --write src",
|
"clean": "pnpm run --filter '{packages}' clean",
|
||||||
"test": "ava",
|
"pretty": "pnpm run --filter '{packages}' pretty"
|
||||||
"coverage": "nyc ava"
|
|
||||||
},
|
|
||||||
"files": [
|
|
||||||
"AUTHORS",
|
|
||||||
"README",
|
|
||||||
"COPYING",
|
|
||||||
"bin/",
|
|
||||||
"dist/node",
|
|
||||||
"src/"
|
|
||||||
],
|
|
||||||
"devDependencies": {
|
|
||||||
"@ava/typescript": "^1.1.1",
|
|
||||||
"@rollup/plugin-commonjs": "^14.0.0",
|
|
||||||
"@rollup/plugin-json": "^4.1.0",
|
|
||||||
"@rollup/plugin-node-resolve": "^8.4.0",
|
|
||||||
"@rollup/plugin-replace": "^2.3.3",
|
|
||||||
"@rollup/plugin-typescript": "^5.0.2",
|
|
||||||
"@types/chrome": "^0.0.103",
|
|
||||||
"@types/enzyme": "^3.10.5",
|
|
||||||
"@types/enzyme-adapter-react-16": "^1.0.6",
|
|
||||||
"@types/node": "^14.0.23",
|
|
||||||
"@types/react": "^16.9.6",
|
|
||||||
"@types/react-dom": "^16.9.6",
|
|
||||||
"@typescript-eslint/eslint-plugin": "^3.6.1",
|
|
||||||
"@typescript-eslint/parser": "^3.6.1",
|
|
||||||
"ava": "^3.10.1",
|
|
||||||
"enzyme": "^3.11.0",
|
|
||||||
"enzyme-adapter-react-16": "^1.15.2",
|
|
||||||
"eslint": "^7.4.0",
|
|
||||||
"eslint-config-airbnb-typescript": "^8.0.2",
|
|
||||||
"eslint-plugin-import": "^2.22.0",
|
|
||||||
"eslint-plugin-jsx-a11y": "^6.3.1",
|
|
||||||
"eslint-plugin-react": "^7.20.3",
|
|
||||||
"eslint-plugin-react-hooks": "^4.0.8",
|
|
||||||
"jed": "^1.1.1",
|
|
||||||
"moment": "^2.27.0",
|
|
||||||
"nyc": "^15.1.0",
|
|
||||||
"po2json": "^0.4.5",
|
|
||||||
"pogen": "^0.0.5",
|
|
||||||
"prettier": "^2.0.5",
|
|
||||||
"react": "^16.13.1",
|
|
||||||
"react-dom": "^16.13.1",
|
|
||||||
"rollup": "^2.21.0",
|
|
||||||
"rollup-plugin-sourcemaps": "^0.6.2",
|
|
||||||
"rollup-plugin-terser": "^6.1.0",
|
|
||||||
"source-map-resolve": "^0.6.0",
|
|
||||||
"structured-clone": "^0.2.2",
|
|
||||||
"typedoc": "^0.17.8",
|
|
||||||
"typescript": "^3.9.7"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"axios": "^0.19.2",
|
|
||||||
"big-integer": "^1.6.48",
|
|
||||||
"idb-bridge": "^0.0.15",
|
|
||||||
"qrcode-generator": "^1.4.3",
|
|
||||||
"source-map-support": "^0.5.19",
|
|
||||||
"tslib": "^2.0.0"
|
|
||||||
},
|
|
||||||
"ava": {
|
|
||||||
"files": [
|
|
||||||
"src/**/*-test.*"
|
|
||||||
],
|
|
||||||
"typescript": {
|
|
||||||
"extensions": [
|
|
||||||
"js",
|
|
||||||
"ts",
|
|
||||||
"tsx"
|
|
||||||
],
|
|
||||||
"rewritePaths": {
|
|
||||||
"src/": "dist/node/"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
This directory contains NPM packages that are used by the wallet. They are
|
|
||||||
uploaded to the registry.
|
|
4
packages/idb-bridge/.vscode/settings.json
vendored
4
packages/idb-bridge/.vscode/settings.json
vendored
@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"editor.tabSize": 2,
|
|
||||||
"typescript.tsdk": "node_modules/typescript/lib"
|
|
||||||
}
|
|
@ -2,17 +2,31 @@
|
|||||||
"name": "idb-bridge",
|
"name": "idb-bridge",
|
||||||
"version": "0.0.15",
|
"version": "0.0.15",
|
||||||
"description": "IndexedDB implementation that uses SQLite3 as storage",
|
"description": "IndexedDB implementation that uses SQLite3 as storage",
|
||||||
"main": "./build/index.js",
|
"main": "./dist/idb-bridge.js",
|
||||||
"types": "./build/index.d.ts",
|
"module": "./lib/index.js",
|
||||||
|
"types": "./lib/index.d.ts",
|
||||||
"author": "Florian Dold",
|
"author": "Florian Dold",
|
||||||
"license": "AGPL-3.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
"private": false,
|
"private": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "tsc && ava",
|
"test": "tsc && ava",
|
||||||
"build": "tsc"
|
"compile": "tsc && rollup -c",
|
||||||
|
"clean": "rimraf dist lib",
|
||||||
|
"pretty": "prettier --config ../../.prettierrc --write src"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"ava": "2.3.0",
|
"@rollup/plugin-typescript": "^5.0.2",
|
||||||
|
"ava": "^3.10.1",
|
||||||
|
"esm": "^3.2.25",
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"rollup": "^2.23.0",
|
||||||
"typescript": "^3.7.0"
|
"typescript": "^3.7.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "^14.0.27",
|
||||||
|
"tslib": "^2.0.0"
|
||||||
|
},
|
||||||
|
"ava": {
|
||||||
|
"require": ["esm"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
31
packages/idb-bridge/rollup.config.js
Normal file
31
packages/idb-bridge/rollup.config.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// rollup.config.js
|
||||||
|
import commonjs from "@rollup/plugin-commonjs";
|
||||||
|
import nodeResolve from "@rollup/plugin-node-resolve";
|
||||||
|
import json from "@rollup/plugin-json";
|
||||||
|
import builtins from "builtin-modules";
|
||||||
|
import pkg from "./package.json";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
input: "lib/index.js",
|
||||||
|
output: {
|
||||||
|
file: pkg.main,
|
||||||
|
format: "cjs",
|
||||||
|
sourcemap: true
|
||||||
|
},
|
||||||
|
external: builtins,
|
||||||
|
plugins: [
|
||||||
|
nodeResolve({
|
||||||
|
preferBuiltins: true,
|
||||||
|
}),
|
||||||
|
|
||||||
|
commonjs({
|
||||||
|
include: [/node_modules/],
|
||||||
|
extensions: [".js", ".ts"],
|
||||||
|
ignoreGlobal: false,
|
||||||
|
sourceMap: false,
|
||||||
|
}),
|
||||||
|
|
||||||
|
json(),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
@ -16,9 +16,9 @@
|
|||||||
permissions and limitations under the License.
|
permissions and limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import BridgeIDBKeyRange from "./BridgeIDBKeyRange";
|
import { BridgeIDBKeyRange } from "./BridgeIDBKeyRange";
|
||||||
import BridgeIDBObjectStore from "./BridgeIDBObjectStore";
|
import { BridgeIDBObjectStore } from "./BridgeIDBObjectStore";
|
||||||
import BridgeIDBRequest from "./BridgeIDBRequest";
|
import { BridgeIDBRequest } from "./BridgeIDBRequest";
|
||||||
import compareKeys from "./util/cmp";
|
import compareKeys from "./util/cmp";
|
||||||
import {
|
import {
|
||||||
DataError,
|
DataError,
|
||||||
@ -42,7 +42,7 @@ import {
|
|||||||
RecordStoreRequest,
|
RecordStoreRequest,
|
||||||
StoreLevel,
|
StoreLevel,
|
||||||
} from "./backend-interface";
|
} from "./backend-interface";
|
||||||
import BridgeIDBFactory from "./BridgeIDBFactory";
|
import { BridgeIDBFactory } from "./BridgeIDBFactory";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#cursor
|
* http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#cursor
|
||||||
@ -136,7 +136,8 @@ export class BridgeIDBCursor {
|
|||||||
console.log(
|
console.log(
|
||||||
`iterating cursor os=${this._objectStoreName},idx=${this._indexName}`,
|
`iterating cursor os=${this._objectStoreName},idx=${this._indexName}`,
|
||||||
);
|
);
|
||||||
BridgeIDBFactory.enableTracing && console.log("cursor type ", this.toString());
|
BridgeIDBFactory.enableTracing &&
|
||||||
|
console.log("cursor type ", this.toString());
|
||||||
const recordGetRequest: RecordGetRequest = {
|
const recordGetRequest: RecordGetRequest = {
|
||||||
direction: this.direction,
|
direction: this.direction,
|
||||||
indexName: this._indexName,
|
indexName: this._indexName,
|
||||||
@ -232,7 +233,7 @@ export class BridgeIDBCursor {
|
|||||||
|
|
||||||
const operation = async () => {
|
const operation = async () => {
|
||||||
if (BridgeIDBFactory.enableTracing) {
|
if (BridgeIDBFactory.enableTracing) {
|
||||||
console.log("updating at cursor")
|
console.log("updating at cursor");
|
||||||
}
|
}
|
||||||
const { btx } = this.source._confirmActiveTransaction();
|
const { btx } = this.source._confirmActiveTransaction();
|
||||||
await this._backend.storeRecord(btx, storeReq);
|
await this._backend.storeRecord(btx, storeReq);
|
||||||
@ -359,5 +360,3 @@ export class BridgeIDBCursor {
|
|||||||
return "[object IDBCursor]";
|
return "[object IDBCursor]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default BridgeIDBCursor;
|
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
permissions and limitations under the License.
|
permissions and limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import BridgeIDBCursor from "./BridgeIDBCursor";
|
import { BridgeIDBCursor } from "./BridgeIDBCursor";
|
||||||
import {
|
import {
|
||||||
CursorRange,
|
CursorRange,
|
||||||
CursorSource,
|
CursorSource,
|
||||||
@ -22,7 +22,7 @@ import {
|
|||||||
Value,
|
Value,
|
||||||
} from "./util/types";
|
} from "./util/types";
|
||||||
|
|
||||||
class BridgeIDBCursorWithValue extends BridgeIDBCursor {
|
export class BridgeIDBCursorWithValue extends BridgeIDBCursor {
|
||||||
get value(): Value {
|
get value(): Value {
|
||||||
return this._value;
|
return this._value;
|
||||||
}
|
}
|
||||||
@ -46,5 +46,3 @@ class BridgeIDBCursorWithValue extends BridgeIDBCursor {
|
|||||||
return "[object IDBCursorWithValue]";
|
return "[object IDBCursorWithValue]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default BridgeIDBCursorWithValue;
|
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
* permissions and limitations under the License.
|
* permissions and limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import BridgeIDBTransaction from "./BridgeIDBTransaction";
|
import { BridgeIDBTransaction } from "./BridgeIDBTransaction";
|
||||||
import {
|
import {
|
||||||
ConstraintError,
|
ConstraintError,
|
||||||
InvalidAccessError,
|
InvalidAccessError,
|
||||||
@ -61,9 +61,8 @@ const confirmActiveVersionchangeTransaction = (database: BridgeIDBDatabase) => {
|
|||||||
return transaction;
|
return transaction;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#database-interface
|
// http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#database-interface
|
||||||
class BridgeIDBDatabase extends FakeEventTarget {
|
export class BridgeIDBDatabase extends FakeEventTarget {
|
||||||
_closePending = false;
|
_closePending = false;
|
||||||
_closed = false;
|
_closed = false;
|
||||||
_runningVersionchangeTransaction = false;
|
_runningVersionchangeTransaction = false;
|
||||||
@ -152,7 +151,12 @@ class BridgeIDBDatabase extends FakeEventTarget {
|
|||||||
throw new InvalidAccessError();
|
throw new InvalidAccessError();
|
||||||
}
|
}
|
||||||
|
|
||||||
transaction._backend.createObjectStore(backendTx, name, keyPath, autoIncrement);
|
transaction._backend.createObjectStore(
|
||||||
|
backendTx,
|
||||||
|
name,
|
||||||
|
keyPath,
|
||||||
|
autoIncrement,
|
||||||
|
);
|
||||||
|
|
||||||
this._schema = this._backend.getSchema(this._backendConnection);
|
this._schema = this._backend.getSchema(this._backendConnection);
|
||||||
|
|
||||||
@ -212,7 +216,12 @@ class BridgeIDBDatabase extends FakeEventTarget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const tx = new BridgeIDBTransaction(storeNames, mode, this, backendTransaction);
|
const tx = new BridgeIDBTransaction(
|
||||||
|
storeNames,
|
||||||
|
mode,
|
||||||
|
this,
|
||||||
|
backendTransaction,
|
||||||
|
);
|
||||||
this._transactions.push(tx);
|
this._transactions.push(tx);
|
||||||
queueTask(() => tx._start());
|
queueTask(() => tx._start());
|
||||||
return tx;
|
return tx;
|
||||||
@ -236,5 +245,3 @@ class BridgeIDBDatabase extends FakeEventTarget {
|
|||||||
return "[object IDBDatabase]";
|
return "[object IDBDatabase]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default BridgeIDBDatabase;
|
|
||||||
|
@ -15,9 +15,9 @@
|
|||||||
* permissions and limitations under the License.
|
* permissions and limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import BridgeIDBDatabase from "./BridgeIDBDatabase";
|
import { BridgeIDBDatabase } from "./BridgeIDBDatabase";
|
||||||
import BridgeIDBOpenDBRequest from "./BridgeIDBOpenDBRequest";
|
import { BridgeIDBOpenDBRequest } from "./BridgeIDBOpenDBRequest";
|
||||||
import BridgeIDBVersionChangeEvent from "./BridgeIDBVersionChangeEvent";
|
import { BridgeIDBVersionChangeEvent } from "./BridgeIDBVersionChangeEvent";
|
||||||
import compareKeys from "./util/cmp";
|
import compareKeys from "./util/cmp";
|
||||||
import enforceRange from "./util/enforceRange";
|
import enforceRange from "./util/enforceRange";
|
||||||
import { AbortError, VersionError } from "./util/errors";
|
import { AbortError, VersionError } from "./util/errors";
|
||||||
@ -44,7 +44,7 @@ export class BridgeIDBFactory {
|
|||||||
|
|
||||||
queueTask(async () => {
|
queueTask(async () => {
|
||||||
const databases = await this.backend.getDatabases();
|
const databases = await this.backend.getDatabases();
|
||||||
const dbInfo = databases.find(x => x.name == name);
|
const dbInfo = databases.find((x) => x.name == name);
|
||||||
if (!dbInfo) {
|
if (!dbInfo) {
|
||||||
// Database already doesn't exist, success!
|
// Database already doesn't exist, success!
|
||||||
const event = new BridgeIDBVersionChangeEvent("success", {
|
const event = new BridgeIDBVersionChangeEvent("success", {
|
||||||
@ -219,8 +219,6 @@ export class BridgeIDBFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _anyOpen(): boolean {
|
private _anyOpen(): boolean {
|
||||||
return this.connections.some(c => !c._closed && !c._closePending);
|
return this.connections.some((c) => !c._closed && !c._closePending);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default BridgeIDBFactory;
|
|
||||||
|
@ -15,11 +15,11 @@
|
|||||||
permissions and limitations under the License.
|
permissions and limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import BridgeIDBCursor from "./BridgeIDBCursor";
|
import { BridgeIDBCursor } from "./BridgeIDBCursor";
|
||||||
import BridgeIDBCursorWithValue from "./BridgeIDBCursorWithValue";
|
import { BridgeIDBCursorWithValue } from "./BridgeIDBCursorWithValue";
|
||||||
import BridgeIDBKeyRange from "./BridgeIDBKeyRange";
|
import { BridgeIDBKeyRange } from "./BridgeIDBKeyRange";
|
||||||
import BridgeIDBObjectStore from "./BridgeIDBObjectStore";
|
import { BridgeIDBObjectStore } from "./BridgeIDBObjectStore";
|
||||||
import BridgeIDBRequest from "./BridgeIDBRequest";
|
import { BridgeIDBRequest } from "./BridgeIDBRequest";
|
||||||
import {
|
import {
|
||||||
ConstraintError,
|
ConstraintError,
|
||||||
InvalidStateError,
|
InvalidStateError,
|
||||||
@ -27,7 +27,7 @@ import {
|
|||||||
} from "./util/errors";
|
} from "./util/errors";
|
||||||
import { BridgeIDBCursorDirection, Key, KeyPath } from "./util/types";
|
import { BridgeIDBCursorDirection, Key, KeyPath } from "./util/types";
|
||||||
import valueToKey from "./util/valueToKey";
|
import valueToKey from "./util/valueToKey";
|
||||||
import BridgeIDBTransaction from "./BridgeIDBTransaction";
|
import { BridgeIDBTransaction } from "./BridgeIDBTransaction";
|
||||||
import {
|
import {
|
||||||
Schema,
|
Schema,
|
||||||
Backend,
|
Backend,
|
||||||
@ -59,15 +59,18 @@ export class BridgeIDBIndex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get keyPath(): KeyPath {
|
get keyPath(): KeyPath {
|
||||||
return this._schema.objectStores[this.objectStore.name].indexes[this._name].keyPath;
|
return this._schema.objectStores[this.objectStore.name].indexes[this._name]
|
||||||
|
.keyPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
get multiEntry(): boolean {
|
get multiEntry(): boolean {
|
||||||
return this._schema.objectStores[this.objectStore.name].indexes[this._name].multiEntry;
|
return this._schema.objectStores[this.objectStore.name].indexes[this._name]
|
||||||
|
.multiEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
get unique(): boolean {
|
get unique(): boolean {
|
||||||
return this._schema.objectStores[this.objectStore.name].indexes[this._name].unique;
|
return this._schema.objectStores[this.objectStore.name].indexes[this._name]
|
||||||
|
.unique;
|
||||||
}
|
}
|
||||||
|
|
||||||
get _backend(): Backend {
|
get _backend(): Backend {
|
||||||
@ -305,7 +308,6 @@ export class BridgeIDBIndex {
|
|||||||
operation,
|
operation,
|
||||||
source: this,
|
source: this,
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public toString() {
|
public toString() {
|
||||||
|
@ -21,7 +21,7 @@ import { Key } from "./util/types";
|
|||||||
import valueToKey from "./util/valueToKey";
|
import valueToKey from "./util/valueToKey";
|
||||||
|
|
||||||
// http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#range-concept
|
// http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#range-concept
|
||||||
class BridgeIDBKeyRange {
|
export class BridgeIDBKeyRange {
|
||||||
public static only(value: Key) {
|
public static only(value: Key) {
|
||||||
if (arguments.length === 0) {
|
if (arguments.length === 0) {
|
||||||
throw new TypeError();
|
throw new TypeError();
|
||||||
@ -128,5 +128,3 @@ class BridgeIDBKeyRange {
|
|||||||
return BridgeIDBKeyRange.only(key);
|
return BridgeIDBKeyRange.only(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default BridgeIDBKeyRange;
|
|
||||||
|
@ -15,12 +15,12 @@
|
|||||||
permissions and limitations under the License.
|
permissions and limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import BridgeIDBCursor from "./BridgeIDBCursor";
|
import { BridgeIDBCursor } from "./BridgeIDBCursor";
|
||||||
import BridgeIDBCursorWithValue from "./BridgeIDBCursorWithValue";
|
import { BridgeIDBCursorWithValue } from "./BridgeIDBCursorWithValue";
|
||||||
import BridgeIDBIndex from "./BridgeIDBIndex";
|
import { BridgeIDBIndex } from "./BridgeIDBIndex";
|
||||||
import BridgeIDBKeyRange from "./BridgeIDBKeyRange";
|
import { BridgeIDBKeyRange } from "./BridgeIDBKeyRange";
|
||||||
import BridgeIDBRequest from "./BridgeIDBRequest";
|
import { BridgeIDBRequest } from "./BridgeIDBRequest";
|
||||||
import BridgeIDBTransaction from "./BridgeIDBTransaction";
|
import { BridgeIDBTransaction } from "./BridgeIDBTransaction";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ConstraintError,
|
ConstraintError,
|
||||||
@ -44,10 +44,10 @@ import {
|
|||||||
ResultLevel,
|
ResultLevel,
|
||||||
StoreLevel,
|
StoreLevel,
|
||||||
} from "./backend-interface";
|
} from "./backend-interface";
|
||||||
import BridgeIDBFactory from "./BridgeIDBFactory";
|
import { BridgeIDBFactory } from "./BridgeIDBFactory";
|
||||||
|
|
||||||
// http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#object-store
|
// http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#object-store
|
||||||
class BridgeIDBObjectStore {
|
export class BridgeIDBObjectStore {
|
||||||
_indexesCache: Map<string, BridgeIDBIndex> = new Map();
|
_indexesCache: Map<string, BridgeIDBIndex> = new Map();
|
||||||
|
|
||||||
transaction: BridgeIDBTransaction;
|
transaction: BridgeIDBTransaction;
|
||||||
@ -455,5 +455,3 @@ class BridgeIDBObjectStore {
|
|||||||
return "[object IDBObjectStore]";
|
return "[object IDBObjectStore]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default BridgeIDBObjectStore;
|
|
||||||
|
@ -15,22 +15,20 @@
|
|||||||
permissions and limitations under the License.
|
permissions and limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import BridgeIDBRequest from "./BridgeIDBRequest";
|
import { BridgeIDBRequest } from "./BridgeIDBRequest";
|
||||||
import { EventCallback } from "./util/types";
|
import { EventCallback } from "./util/types";
|
||||||
|
|
||||||
class BridgeIDBOpenDBRequest extends BridgeIDBRequest {
|
export class BridgeIDBOpenDBRequest extends BridgeIDBRequest {
|
||||||
public onupgradeneeded: EventCallback | null = null;
|
public onupgradeneeded: EventCallback | null = null;
|
||||||
public onblocked: EventCallback | null = null;
|
public onblocked: EventCallback | null = null;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
// https://www.w3.org/TR/IndexedDB/#open-requests
|
// https://www.w3.org/TR/IndexedDB/#open-requests
|
||||||
this.source = null;
|
this.source = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public toString() {
|
public toString() {
|
||||||
return "[object IDBOpenDBRequest]";
|
return "[object IDBOpenDBRequest]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default BridgeIDBOpenDBRequest;
|
|
||||||
|
@ -15,19 +15,19 @@
|
|||||||
* permissions and limitations under the License.
|
* permissions and limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import BridgeFDBCursor from "./BridgeIDBCursor";
|
import { BridgeIDBCursor as BridgeFIBCursor } from "./BridgeIDBCursor";
|
||||||
import BridgeIDBIndex from "./BridgeIDBIndex";
|
import { BridgeIDBIndex } from "./BridgeIDBIndex";
|
||||||
import BridgeIDBObjectStore from "./BridgeIDBObjectStore";
|
import { BridgeIDBObjectStore } from "./BridgeIDBObjectStore";
|
||||||
import BridgeIDBTransaction from "./BridgeIDBTransaction";
|
import { BridgeIDBTransaction } from "./BridgeIDBTransaction";
|
||||||
import { InvalidStateError } from "./util/errors";
|
import { InvalidStateError } from "./util/errors";
|
||||||
import FakeEventTarget from "./util/FakeEventTarget";
|
import FakeEventTarget from "./util/FakeEventTarget";
|
||||||
import { EventCallback } from "./util/types";
|
import { EventCallback } from "./util/types";
|
||||||
import FakeEvent from "./util/FakeEvent";
|
import FakeEvent from "./util/FakeEvent";
|
||||||
|
|
||||||
class BridgeIDBRequest extends FakeEventTarget {
|
export class BridgeIDBRequest extends FakeEventTarget {
|
||||||
_result: any = null;
|
_result: any = null;
|
||||||
_error: Error | null | undefined = null;
|
_error: Error | null | undefined = null;
|
||||||
source: BridgeFDBCursor | BridgeIDBIndex | BridgeIDBObjectStore | null = null;
|
source: BridgeFIBCursor | BridgeIDBIndex | BridgeIDBObjectStore | null = null;
|
||||||
transaction: BridgeIDBTransaction | null = null;
|
transaction: BridgeIDBTransaction | null = null;
|
||||||
readyState: "done" | "pending" = "pending";
|
readyState: "done" | "pending" = "pending";
|
||||||
onsuccess: EventCallback | null = null;
|
onsuccess: EventCallback | null = null;
|
||||||
@ -83,5 +83,3 @@ class BridgeIDBRequest extends FakeEventTarget {
|
|||||||
this.dispatchEvent(event);
|
this.dispatchEvent(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default BridgeIDBRequest;
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import BridgeIDBDatabase from "./BridgeIDBDatabase";
|
import { BridgeIDBDatabase } from "./BridgeIDBDatabase";
|
||||||
import BridgeIDBObjectStore from "./BridgeIDBObjectStore";
|
import { BridgeIDBObjectStore } from "./BridgeIDBObjectStore";
|
||||||
import BridgeIDBRequest from "./BridgeIDBRequest";
|
import { BridgeIDBRequest } from "./BridgeIDBRequest";
|
||||||
import {
|
import {
|
||||||
AbortError,
|
AbortError,
|
||||||
InvalidStateError,
|
InvalidStateError,
|
||||||
@ -19,11 +19,10 @@ import {
|
|||||||
import queueTask from "./util/queueTask";
|
import queueTask from "./util/queueTask";
|
||||||
import openPromise from "./util/openPromise";
|
import openPromise from "./util/openPromise";
|
||||||
import { DatabaseTransaction, Backend } from "./backend-interface";
|
import { DatabaseTransaction, Backend } from "./backend-interface";
|
||||||
import { array } from "prop-types";
|
import { BridgeIDBFactory } from "./BridgeIDBFactory";
|
||||||
import BridgeIDBFactory from "./BridgeIDBFactory";
|
|
||||||
|
|
||||||
// http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#transaction
|
// http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#transaction
|
||||||
class BridgeIDBTransaction extends FakeEventTarget {
|
export class BridgeIDBTransaction extends FakeEventTarget {
|
||||||
public _state: "active" | "inactive" | "committing" | "finished" = "active";
|
public _state: "active" | "inactive" | "committing" | "finished" = "active";
|
||||||
public _started = false;
|
public _started = false;
|
||||||
public _objectStoresCache: Map<string, BridgeIDBObjectStore> = new Map();
|
public _objectStoresCache: Map<string, BridgeIDBObjectStore> = new Map();
|
||||||
@ -328,5 +327,3 @@ class BridgeIDBTransaction extends FakeEventTarget {
|
|||||||
return this._waitPromise;
|
return this._waitPromise;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default BridgeIDBTransaction;
|
|
||||||
|
@ -17,25 +17,23 @@
|
|||||||
|
|
||||||
import FakeEvent from "./util/FakeEvent";
|
import FakeEvent from "./util/FakeEvent";
|
||||||
|
|
||||||
class BridgeIDBVersionChangeEvent extends FakeEvent {
|
export class BridgeIDBVersionChangeEvent extends FakeEvent {
|
||||||
public newVersion: number | null;
|
public newVersion: number | null;
|
||||||
public oldVersion: number;
|
public oldVersion: number;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
type: "blocked" | "success" | "upgradeneeded" | "versionchange",
|
type: "blocked" | "success" | "upgradeneeded" | "versionchange",
|
||||||
parameters: { newVersion?: number | null; oldVersion?: number } = {},
|
parameters: { newVersion?: number | null; oldVersion?: number } = {},
|
||||||
) {
|
) {
|
||||||
super(type);
|
super(type);
|
||||||
|
|
||||||
this.newVersion =
|
this.newVersion =
|
||||||
parameters.newVersion !== undefined ? parameters.newVersion : null;
|
parameters.newVersion !== undefined ? parameters.newVersion : null;
|
||||||
this.oldVersion =
|
this.oldVersion =
|
||||||
parameters.oldVersion !== undefined ? parameters.oldVersion : 0;
|
parameters.oldVersion !== undefined ? parameters.oldVersion : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public toString() {
|
public toString() {
|
||||||
return "[object IDBVersionChangeEvent]";
|
return "[object IDBVersionChangeEvent]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default BridgeIDBVersionChangeEvent;
|
|
||||||
|
@ -14,15 +14,14 @@
|
|||||||
permissions and limitations under the License.
|
permissions and limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
import test from "ava";
|
import test from "ava";
|
||||||
import MemoryBackend from "./MemoryBackend";
|
import MemoryBackend from "./MemoryBackend";
|
||||||
import BridgeIDBFactory from "./BridgeIDBFactory";
|
import { BridgeIDBFactory } from "./BridgeIDBFactory";
|
||||||
import BridgeIDBRequest from "./BridgeIDBRequest";
|
import { BridgeIDBRequest } from "./BridgeIDBRequest";
|
||||||
import BridgeIDBDatabase from "./BridgeIDBDatabase";
|
import { BridgeIDBDatabase } from "./BridgeIDBDatabase";
|
||||||
import BridgeIDBTransaction from "./BridgeIDBTransaction";
|
import { BridgeIDBTransaction } from "./BridgeIDBTransaction";
|
||||||
import BridgeIDBKeyRange from "./BridgeIDBKeyRange";
|
import { BridgeIDBKeyRange } from "./BridgeIDBKeyRange";
|
||||||
import BridgeIDBCursorWithValue from "./BridgeIDBCursorWithValue";
|
import { BridgeIDBCursorWithValue } from "./BridgeIDBCursorWithValue";
|
||||||
|
|
||||||
function promiseFromRequest(request: BridgeIDBRequest): Promise<any> {
|
function promiseFromRequest(request: BridgeIDBRequest): Promise<any> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@ -48,7 +47,7 @@ function promiseFromTransaction(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
test("Spec: Example 1 Part 1", async t => {
|
test("Spec: Example 1 Part 1", async (t) => {
|
||||||
const backend = new MemoryBackend();
|
const backend = new MemoryBackend();
|
||||||
const idb = new BridgeIDBFactory(backend);
|
const idb = new BridgeIDBFactory(backend);
|
||||||
|
|
||||||
@ -69,7 +68,7 @@ test("Spec: Example 1 Part 1", async t => {
|
|||||||
t.pass();
|
t.pass();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Spec: Example 1 Part 2", async t => {
|
test("Spec: Example 1 Part 2", async (t) => {
|
||||||
const backend = new MemoryBackend();
|
const backend = new MemoryBackend();
|
||||||
const idb = new BridgeIDBFactory(backend);
|
const idb = new BridgeIDBFactory(backend);
|
||||||
|
|
||||||
@ -101,7 +100,7 @@ test("Spec: Example 1 Part 2", async t => {
|
|||||||
t.pass();
|
t.pass();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Spec: Example 1 Part 3", async t => {
|
test("Spec: Example 1 Part 3", async (t) => {
|
||||||
const backend = new MemoryBackend();
|
const backend = new MemoryBackend();
|
||||||
const idb = new BridgeIDBFactory(backend);
|
const idb = new BridgeIDBFactory(backend);
|
||||||
|
|
||||||
@ -229,7 +228,6 @@ test("Spec: Example 1 Part 3", async t => {
|
|||||||
cursor = request6.result;
|
cursor = request6.result;
|
||||||
t.is(cursor, null);
|
t.is(cursor, null);
|
||||||
|
|
||||||
|
|
||||||
const request7 = index5.openCursor(null, "prevunique");
|
const request7 = index5.openCursor(null, "prevunique");
|
||||||
await promiseFromRequest(request7);
|
await promiseFromRequest(request7);
|
||||||
cursor = request7.result;
|
cursor = request7.result;
|
||||||
@ -251,8 +249,7 @@ test("Spec: Example 1 Part 3", async t => {
|
|||||||
t.pass();
|
t.pass();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("simple deletion", async (t) => {
|
||||||
test("simple deletion", async t => {
|
|
||||||
const backend = new MemoryBackend();
|
const backend = new MemoryBackend();
|
||||||
const idb = new BridgeIDBFactory(backend);
|
const idb = new BridgeIDBFactory(backend);
|
||||||
|
|
||||||
@ -307,8 +304,7 @@ test("simple deletion", async t => {
|
|||||||
t.pass();
|
t.pass();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("export", async (t) => {
|
||||||
test("export", async t => {
|
|
||||||
const backend = new MemoryBackend();
|
const backend = new MemoryBackend();
|
||||||
const idb = new BridgeIDBFactory(backend);
|
const idb = new BridgeIDBFactory(backend);
|
||||||
|
|
||||||
@ -322,7 +318,6 @@ test("export", async t => {
|
|||||||
|
|
||||||
const db: BridgeIDBDatabase = await promiseFromRequest(request);
|
const db: BridgeIDBDatabase = await promiseFromRequest(request);
|
||||||
|
|
||||||
|
|
||||||
const tx = db.transaction("books", "readwrite");
|
const tx = db.transaction("books", "readwrite");
|
||||||
tx.oncomplete = () => {
|
tx.oncomplete = () => {
|
||||||
console.log("oncomplete called");
|
console.log("oncomplete called");
|
||||||
@ -341,10 +336,13 @@ test("export", async t => {
|
|||||||
backend2.importDump(exportedData);
|
backend2.importDump(exportedData);
|
||||||
const exportedData2 = backend2.exportDump();
|
const exportedData2 = backend2.exportDump();
|
||||||
|
|
||||||
t.assert(exportedData.databases["library"].objectStores["books"].records.length === 3);
|
t.assert(
|
||||||
|
exportedData.databases["library"].objectStores["books"].records.length ===
|
||||||
|
3,
|
||||||
|
);
|
||||||
t.deepEqual(exportedData, exportedData2);
|
t.deepEqual(exportedData, exportedData2);
|
||||||
|
|
||||||
t.is(exportedData.databases["library"].schema.databaseVersion, 42);
|
t.is(exportedData.databases["library"].schema.databaseVersion, 42);
|
||||||
t.is(exportedData2.databases["library"].schema.databaseVersion, 42);
|
t.is(exportedData2.databases["library"].schema.databaseVersion, 42);
|
||||||
t.pass();
|
t.pass();
|
||||||
});
|
});
|
||||||
|
@ -40,7 +40,7 @@ import { Key, Value, KeyPath } from "./util/types";
|
|||||||
import { StoreKeyResult, makeStoreKeyValue } from "./util/makeStoreKeyValue";
|
import { StoreKeyResult, makeStoreKeyValue } from "./util/makeStoreKeyValue";
|
||||||
import getIndexKeys from "./util/getIndexKeys";
|
import getIndexKeys from "./util/getIndexKeys";
|
||||||
import openPromise from "./util/openPromise";
|
import openPromise from "./util/openPromise";
|
||||||
import BridgeIDBKeyRange from "./BridgeIDBKeyRange";
|
import { BridgeIDBKeyRange } from "./BridgeIDBKeyRange";
|
||||||
|
|
||||||
enum TransactionLevel {
|
enum TransactionLevel {
|
||||||
Disconnected = 0,
|
Disconnected = 0,
|
||||||
@ -863,9 +863,9 @@ export class MemoryBackend implements Backend {
|
|||||||
!db.txRestrictObjectStores.includes(objectStoreName)
|
!db.txRestrictObjectStores.includes(objectStoreName)
|
||||||
) {
|
) {
|
||||||
throw Error(
|
throw Error(
|
||||||
`Not allowed to access store '${
|
`Not allowed to access store '${objectStoreName}', transaction is over ${JSON.stringify(
|
||||||
objectStoreName
|
db.txRestrictObjectStores,
|
||||||
}', transaction is over ${JSON.stringify(db.txRestrictObjectStores)}`,
|
)}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (typeof range !== "object") {
|
if (typeof range !== "object") {
|
||||||
@ -986,7 +986,7 @@ export class MemoryBackend implements Backend {
|
|||||||
throw Error("db inconsistent: expected index entry missing");
|
throw Error("db inconsistent: expected index entry missing");
|
||||||
}
|
}
|
||||||
const newPrimaryKeys = existingRecord.primaryKeys.filter(
|
const newPrimaryKeys = existingRecord.primaryKeys.filter(
|
||||||
x => compareKeys(x, primaryKey) !== 0,
|
(x) => compareKeys(x, primaryKey) !== 0,
|
||||||
);
|
);
|
||||||
if (newPrimaryKeys.length === 0) {
|
if (newPrimaryKeys.length === 0) {
|
||||||
index.modifiedData = indexData.without(indexKey);
|
index.modifiedData = indexData.without(indexKey);
|
||||||
|
@ -22,7 +22,7 @@ import {
|
|||||||
KeyPath,
|
KeyPath,
|
||||||
BridgeIDBDatabaseInfo,
|
BridgeIDBDatabaseInfo,
|
||||||
} from "./util/types";
|
} from "./util/types";
|
||||||
import BridgeIDBKeyRange from "./BridgeIDBKeyRange";
|
import { BridgeIDBKeyRange } from "./BridgeIDBKeyRange";
|
||||||
|
|
||||||
export interface ObjectStoreProperties {
|
export interface ObjectStoreProperties {
|
||||||
keyPath: KeyPath | null;
|
keyPath: KeyPath | null;
|
||||||
@ -76,7 +76,7 @@ export interface RecordGetRequest {
|
|||||||
* Last cursor position in terms of the index key.
|
* Last cursor position in terms of the index key.
|
||||||
* Can only be specified if indexName is defined and
|
* Can only be specified if indexName is defined and
|
||||||
* lastObjectStorePosition is defined.
|
* lastObjectStorePosition is defined.
|
||||||
*
|
*
|
||||||
* Must either be undefined or within range.
|
* Must either be undefined or within range.
|
||||||
*/
|
*/
|
||||||
lastIndexPosition?: Key;
|
lastIndexPosition?: Key;
|
||||||
@ -87,7 +87,7 @@ export interface RecordGetRequest {
|
|||||||
/**
|
/**
|
||||||
* If specified, the index key of the results must be
|
* If specified, the index key of the results must be
|
||||||
* greater or equal to advanceIndexKey.
|
* greater or equal to advanceIndexKey.
|
||||||
*
|
*
|
||||||
* Only applicable if indexName is specified.
|
* Only applicable if indexName is specified.
|
||||||
*/
|
*/
|
||||||
advanceIndexKey?: Key;
|
advanceIndexKey?: Key;
|
||||||
@ -144,7 +144,7 @@ export interface Backend {
|
|||||||
/**
|
/**
|
||||||
* Even though the standard interface for indexedDB doesn't require
|
* Even though the standard interface for indexedDB doesn't require
|
||||||
* the client to run deleteDatabase in a version transaction, there is
|
* the client to run deleteDatabase in a version transaction, there is
|
||||||
* implicitly one running.
|
* implicitly one running.
|
||||||
*/
|
*/
|
||||||
deleteDatabase(btx: DatabaseTransaction, name: string): Promise<void>;
|
deleteDatabase(btx: DatabaseTransaction, name: string): Promise<void>;
|
||||||
|
|
||||||
@ -152,9 +152,18 @@ export interface Backend {
|
|||||||
|
|
||||||
getSchema(db: DatabaseConnection): Schema;
|
getSchema(db: DatabaseConnection): Schema;
|
||||||
|
|
||||||
renameIndex(btx: DatabaseTransaction, objectStoreName: string, oldName: string, newName: string): void;
|
renameIndex(
|
||||||
|
btx: DatabaseTransaction,
|
||||||
|
objectStoreName: string,
|
||||||
|
oldName: string,
|
||||||
|
newName: string,
|
||||||
|
): void;
|
||||||
|
|
||||||
deleteIndex(btx: DatabaseTransaction, objectStoreName: string, indexName: string): void;
|
deleteIndex(
|
||||||
|
btx: DatabaseTransaction,
|
||||||
|
objectStoreName: string,
|
||||||
|
indexName: string,
|
||||||
|
): void;
|
||||||
|
|
||||||
rollback(btx: DatabaseTransaction): Promise<void>;
|
rollback(btx: DatabaseTransaction): Promise<void>;
|
||||||
|
|
||||||
|
736
packages/idb-bridge/src/idbtypes.ts
Normal file
736
packages/idb-bridge/src/idbtypes.ts
Normal file
@ -0,0 +1,736 @@
|
|||||||
|
/*! *****************************************************************************
|
||||||
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||||
|
this file except in compliance with the License. You may obtain a copy of the
|
||||||
|
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||||
|
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||||
|
MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||||
|
|
||||||
|
See the Apache Version 2.0 License for specific language governing permissions
|
||||||
|
and limitations under the License.
|
||||||
|
***************************************************************************** */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type declarations for IndexedDB, adapted from the TypeScript lib.dom.d.ts.
|
||||||
|
*
|
||||||
|
* Instead of ambient types, we export type declarations.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export type IDBKeyPath = string;
|
||||||
|
|
||||||
|
export interface EventListener {
|
||||||
|
(evt: Event): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EventListenerObject {
|
||||||
|
handleEvent(evt: Event): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EventListenerOptions {
|
||||||
|
capture?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AddEventListenerOptions extends EventListenerOptions {
|
||||||
|
once?: boolean;
|
||||||
|
passive?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type IDBTransactionMode = "readonly" | "readwrite" | "versionchange";
|
||||||
|
|
||||||
|
export type EventListenerOrEventListenerObject =
|
||||||
|
| EventListener
|
||||||
|
| EventListenerObject;
|
||||||
|
|
||||||
|
/** EventTarget is a DOM interface implemented by objects that can receive events and may have listeners for them. */
|
||||||
|
export interface EventTarget {
|
||||||
|
/**
|
||||||
|
* Appends an event listener for events whose type attribute value is type. The callback argument sets the callback that will be invoked when the event is dispatched.
|
||||||
|
*
|
||||||
|
* The options argument sets listener-specific options. For compatibility this can be a boolean, in which case the method behaves exactly as if the value was specified as options's capture.
|
||||||
|
*
|
||||||
|
* When set to true, options's capture prevents callback from being invoked when the event's eventPhase attribute value is BUBBLING_PHASE. When false (or not present), callback will not be invoked when event's eventPhase attribute value is CAPTURING_PHASE. Either way, callback will be invoked if event's eventPhase attribute value is AT_TARGET.
|
||||||
|
*
|
||||||
|
* When set to true, options's passive indicates that the callback will not cancel the event by invoking preventDefault(). This is used to enable performance optimizations described in § 2.8 Observing event listeners.
|
||||||
|
*
|
||||||
|
* When set to true, options's once indicates that the callback will only be invoked once after which the event listener will be removed.
|
||||||
|
*
|
||||||
|
* The event listener is appended to target's event listener list and is not appended if it has the same type, callback, and capture.
|
||||||
|
*/
|
||||||
|
addEventListener(
|
||||||
|
type: string,
|
||||||
|
listener: EventListenerOrEventListenerObject | null,
|
||||||
|
options?: boolean | AddEventListenerOptions,
|
||||||
|
): void;
|
||||||
|
/**
|
||||||
|
* Dispatches a synthetic event event to target and returns true if either event's cancelable attribute value is false or its preventDefault() method was not invoked, and false otherwise.
|
||||||
|
*/
|
||||||
|
dispatchEvent(event: Event): boolean;
|
||||||
|
/**
|
||||||
|
* Removes the event listener in target's event listener list with the same type, callback, and options.
|
||||||
|
*/
|
||||||
|
removeEventListener(
|
||||||
|
type: string,
|
||||||
|
callback: EventListenerOrEventListenerObject | null,
|
||||||
|
options?: EventListenerOptions | boolean,
|
||||||
|
): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** An event which takes place in the DOM. */
|
||||||
|
export interface Event {
|
||||||
|
/**
|
||||||
|
* Returns true or false depending on how event was initialized. True if event goes through its target's ancestors in reverse tree order, and false otherwise.
|
||||||
|
*/
|
||||||
|
readonly bubbles: boolean;
|
||||||
|
cancelBubble: boolean;
|
||||||
|
/**
|
||||||
|
* Returns true or false depending on how event was initialized. Its return value does not always carry meaning, but true can indicate that part of the operation during which event was dispatched, can be canceled by invoking the preventDefault() method.
|
||||||
|
*/
|
||||||
|
readonly cancelable: boolean;
|
||||||
|
/**
|
||||||
|
* Returns true or false depending on how event was initialized. True if event invokes listeners past a ShadowRoot node that is the root of its target, and false otherwise.
|
||||||
|
*/
|
||||||
|
readonly composed: boolean;
|
||||||
|
/**
|
||||||
|
* Returns the object whose event listener's callback is currently being invoked.
|
||||||
|
*/
|
||||||
|
readonly currentTarget: EventTarget | null;
|
||||||
|
/**
|
||||||
|
* Returns true if preventDefault() was invoked successfully to indicate cancelation, and false otherwise.
|
||||||
|
*/
|
||||||
|
readonly defaultPrevented: boolean;
|
||||||
|
/**
|
||||||
|
* Returns the event's phase, which is one of NONE, CAPTURING_PHASE, AT_TARGET, and BUBBLING_PHASE.
|
||||||
|
*/
|
||||||
|
readonly eventPhase: number;
|
||||||
|
/**
|
||||||
|
* Returns true if event was dispatched by the user agent, and false otherwise.
|
||||||
|
*/
|
||||||
|
readonly isTrusted: boolean;
|
||||||
|
returnValue: boolean;
|
||||||
|
/** @deprecated */
|
||||||
|
readonly srcElement: EventTarget | null;
|
||||||
|
/**
|
||||||
|
* Returns the object to which event is dispatched (its target).
|
||||||
|
*/
|
||||||
|
readonly target: EventTarget | null;
|
||||||
|
/**
|
||||||
|
* Returns the event's timestamp as the number of milliseconds measured relative to the time origin.
|
||||||
|
*/
|
||||||
|
readonly timeStamp: number;
|
||||||
|
/**
|
||||||
|
* Returns the type of event, e.g. "click", "hashchange", or "submit".
|
||||||
|
*/
|
||||||
|
readonly type: string;
|
||||||
|
/**
|
||||||
|
* Returns the invocation target objects of event's path (objects on which listeners will be invoked), except for any nodes in shadow trees of which the shadow root's mode is "closed" that are not reachable from event's currentTarget.
|
||||||
|
*/
|
||||||
|
composedPath(): EventTarget[];
|
||||||
|
initEvent(type: string, bubbles?: boolean, cancelable?: boolean): void;
|
||||||
|
/**
|
||||||
|
* If invoked when the cancelable attribute value is true, and while executing a listener for the event with passive set to false, signals to the operation that caused event to be dispatched that it needs to be canceled.
|
||||||
|
*/
|
||||||
|
preventDefault(): void;
|
||||||
|
/**
|
||||||
|
* Invoking this method prevents event from reaching any registered event listeners after the current one finishes running and, when dispatched in a tree, also prevents event from reaching any other objects.
|
||||||
|
*/
|
||||||
|
stopImmediatePropagation(): void;
|
||||||
|
/**
|
||||||
|
* When dispatched in a tree, invoking this method prevents event from reaching any objects other than the current object.
|
||||||
|
*/
|
||||||
|
stopPropagation(): void;
|
||||||
|
readonly AT_TARGET: number;
|
||||||
|
readonly BUBBLING_PHASE: number;
|
||||||
|
readonly CAPTURING_PHASE: number;
|
||||||
|
readonly NONE: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A type returned by some APIs which contains a list of DOMString (strings). */
|
||||||
|
export interface DOMStringList {
|
||||||
|
/**
|
||||||
|
* Returns the number of strings in strings.
|
||||||
|
*/
|
||||||
|
readonly length: number;
|
||||||
|
/**
|
||||||
|
* Returns true if strings contains string, and false otherwise.
|
||||||
|
*/
|
||||||
|
contains(string: string): boolean;
|
||||||
|
/**
|
||||||
|
* Returns the string with index index from strings.
|
||||||
|
*/
|
||||||
|
item(index: number): string | null;
|
||||||
|
[index: number]: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type BufferSource = ArrayBufferView | ArrayBuffer;
|
||||||
|
|
||||||
|
export type IDBValidKey = number | string | Date | BufferSource | IDBArrayKey;
|
||||||
|
|
||||||
|
export interface IDBIndexParameters {
|
||||||
|
multiEntry?: boolean;
|
||||||
|
unique?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IDBObjectStoreParameters {
|
||||||
|
autoIncrement?: boolean;
|
||||||
|
keyPath?: string | string[] | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EventInit {
|
||||||
|
bubbles?: boolean;
|
||||||
|
cancelable?: boolean;
|
||||||
|
composed?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IDBArrayKey extends Array<IDBValidKey> {}
|
||||||
|
|
||||||
|
export type IDBCursorDirection = "next" | "nextunique" | "prev" | "prevunique";
|
||||||
|
|
||||||
|
/** This IndexedDB API interface represents a cursor for traversing or iterating over multiple records in a database. */
|
||||||
|
export interface IDBCursor {
|
||||||
|
/**
|
||||||
|
* Returns the direction ("next", "nextunique", "prev" or "prevunique") of the cursor.
|
||||||
|
*/
|
||||||
|
readonly direction: IDBCursorDirection;
|
||||||
|
/**
|
||||||
|
* Returns the key of the cursor. Throws a "InvalidStateError" DOMException if the cursor is advancing or is finished.
|
||||||
|
*/
|
||||||
|
readonly key: IDBValidKey;
|
||||||
|
/**
|
||||||
|
* Returns the effective key of the cursor. Throws a "InvalidStateError" DOMException if the cursor is advancing or is finished.
|
||||||
|
*/
|
||||||
|
readonly primaryKey: IDBValidKey;
|
||||||
|
/**
|
||||||
|
* Returns the IDBObjectStore or IDBIndex the cursor was opened from.
|
||||||
|
*/
|
||||||
|
readonly source: IDBObjectStore | IDBIndex;
|
||||||
|
/**
|
||||||
|
* Advances the cursor through the next count records in range.
|
||||||
|
*/
|
||||||
|
advance(count: number): void;
|
||||||
|
/**
|
||||||
|
* Advances the cursor to the next record in range.
|
||||||
|
*/
|
||||||
|
continue(key?: IDBValidKey): void;
|
||||||
|
/**
|
||||||
|
* Advances the cursor to the next record in range matching or after key and primaryKey. Throws an "InvalidAccessError" DOMException if the source is not an index.
|
||||||
|
*/
|
||||||
|
continuePrimaryKey(key: IDBValidKey, primaryKey: IDBValidKey): void;
|
||||||
|
/**
|
||||||
|
* Delete the record pointed at by the cursor with a new value.
|
||||||
|
*
|
||||||
|
* If successful, request's result will be undefined.
|
||||||
|
*/
|
||||||
|
delete(): IDBRequest<undefined>;
|
||||||
|
/**
|
||||||
|
* Updated the record pointed at by the cursor with a new value.
|
||||||
|
*
|
||||||
|
* Throws a "DataError" DOMException if the effective object store uses in-line keys and the key would have changed.
|
||||||
|
*
|
||||||
|
* If successful, request's result will be the record's key.
|
||||||
|
*/
|
||||||
|
update(value: any): IDBRequest<IDBValidKey>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** This IndexedDB API interface represents a cursor for traversing or iterating over multiple records in a database. It is the same as the IDBCursor, except that it includes the value property. */
|
||||||
|
export interface IDBCursorWithValue extends IDBCursor {
|
||||||
|
/**
|
||||||
|
* Returns the cursor's current value.
|
||||||
|
*/
|
||||||
|
readonly value: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IDBDatabaseEventMap {
|
||||||
|
abort: Event;
|
||||||
|
close: Event;
|
||||||
|
error: Event;
|
||||||
|
versionchange: IDBVersionChangeEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** This IndexedDB API interface provides a connection to a database; you can use an IDBDatabase object to open a transaction on your database then create, manipulate, and delete objects (data) in that database. The interface provides the only way to get and manage versions of the database. */
|
||||||
|
export interface IDBDatabase extends EventTarget {
|
||||||
|
/**
|
||||||
|
* Returns the name of the database.
|
||||||
|
*/
|
||||||
|
readonly name: string;
|
||||||
|
/**
|
||||||
|
* Returns a list of the names of object stores in the database.
|
||||||
|
*/
|
||||||
|
readonly objectStoreNames: DOMStringList;
|
||||||
|
onabort: ((this: IDBDatabase, ev: Event) => any) | null;
|
||||||
|
onclose: ((this: IDBDatabase, ev: Event) => any) | null;
|
||||||
|
onerror: ((this: IDBDatabase, ev: Event) => any) | null;
|
||||||
|
onversionchange:
|
||||||
|
| ((this: IDBDatabase, ev: IDBVersionChangeEvent) => any)
|
||||||
|
| null;
|
||||||
|
/**
|
||||||
|
* Returns the version of the database.
|
||||||
|
*/
|
||||||
|
readonly version: number;
|
||||||
|
/**
|
||||||
|
* Closes the connection once all running transactions have finished.
|
||||||
|
*/
|
||||||
|
close(): void;
|
||||||
|
/**
|
||||||
|
* Creates a new object store with the given name and options and returns a new IDBObjectStore.
|
||||||
|
*
|
||||||
|
* Throws a "InvalidStateError" DOMException if not called within an upgrade transaction.
|
||||||
|
*/
|
||||||
|
createObjectStore(
|
||||||
|
name: string,
|
||||||
|
optionalParameters?: IDBObjectStoreParameters,
|
||||||
|
): IDBObjectStore;
|
||||||
|
/**
|
||||||
|
* Deletes the object store with the given name.
|
||||||
|
*
|
||||||
|
* Throws a "InvalidStateError" DOMException if not called within an upgrade transaction.
|
||||||
|
*/
|
||||||
|
deleteObjectStore(name: string): void;
|
||||||
|
/**
|
||||||
|
* Returns a new transaction with the given mode ("readonly" or "readwrite") and scope which can be a single object store name or an array of names.
|
||||||
|
*/
|
||||||
|
transaction(
|
||||||
|
storeNames: string | string[],
|
||||||
|
mode?: IDBTransactionMode,
|
||||||
|
): IDBTransaction;
|
||||||
|
addEventListener<K extends keyof IDBDatabaseEventMap>(
|
||||||
|
type: K,
|
||||||
|
listener: (this: IDBDatabase, ev: IDBDatabaseEventMap[K]) => any,
|
||||||
|
options?: boolean | AddEventListenerOptions,
|
||||||
|
): void;
|
||||||
|
addEventListener(
|
||||||
|
type: string,
|
||||||
|
listener: EventListenerOrEventListenerObject,
|
||||||
|
options?: boolean | AddEventListenerOptions,
|
||||||
|
): void;
|
||||||
|
removeEventListener<K extends keyof IDBDatabaseEventMap>(
|
||||||
|
type: K,
|
||||||
|
listener: (this: IDBDatabase, ev: IDBDatabaseEventMap[K]) => any,
|
||||||
|
options?: boolean | EventListenerOptions,
|
||||||
|
): void;
|
||||||
|
removeEventListener(
|
||||||
|
type: string,
|
||||||
|
listener: EventListenerOrEventListenerObject,
|
||||||
|
options?: boolean | EventListenerOptions,
|
||||||
|
): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** In the following code snippet, we make a request to open a database, and include handlers for the success and error cases. For a full working example, see our To-do Notifications app (view example live.) */
|
||||||
|
export interface IDBFactory {
|
||||||
|
/**
|
||||||
|
* Compares two values as keys. Returns -1 if key1 precedes key2, 1 if key2 precedes key1, and 0 if the keys are equal.
|
||||||
|
*
|
||||||
|
* Throws a "DataError" DOMException if either input is not a valid key.
|
||||||
|
*/
|
||||||
|
cmp(first: any, second: any): number;
|
||||||
|
/**
|
||||||
|
* Attempts to delete the named database. If the database already exists and there are open connections that don't close in response to a versionchange event, the request will be blocked until all they close. If the request is successful request's result will be null.
|
||||||
|
*/
|
||||||
|
deleteDatabase(name: string): IDBOpenDBRequest;
|
||||||
|
/**
|
||||||
|
* Attempts to open a connection to the named database with the current version, or 1 if it does not already exist. If the request is successful request's result will be the connection.
|
||||||
|
*/
|
||||||
|
open(name: string, version?: number): IDBOpenDBRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** IDBIndex interface of the IndexedDB API provides asynchronous access to an index in a database. An index is a kind of object store for looking up records in another object store, called the referenced object store. You use this interface to retrieve data. */
|
||||||
|
export interface IDBIndex {
|
||||||
|
readonly keyPath: string | string[];
|
||||||
|
readonly multiEntry: boolean;
|
||||||
|
/**
|
||||||
|
* Returns the name of the index.
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
/**
|
||||||
|
* Returns the IDBObjectStore the index belongs to.
|
||||||
|
*/
|
||||||
|
readonly objectStore: IDBObjectStore;
|
||||||
|
readonly unique: boolean;
|
||||||
|
/**
|
||||||
|
* Retrieves the number of records matching the given key or key range in query.
|
||||||
|
*
|
||||||
|
* If successful, request's result will be the count.
|
||||||
|
*/
|
||||||
|
count(key?: IDBValidKey | IDBKeyRange): IDBRequest<number>;
|
||||||
|
/**
|
||||||
|
* Retrieves the value of the first record matching the given key or key range in query.
|
||||||
|
*
|
||||||
|
* If successful, request's result will be the value, or undefined if there was no matching record.
|
||||||
|
*/
|
||||||
|
get(key: IDBValidKey | IDBKeyRange): IDBRequest<any | undefined>;
|
||||||
|
/**
|
||||||
|
* Retrieves the values of the records matching the given key or key range in query (up to count if given).
|
||||||
|
*
|
||||||
|
* If successful, request's result will be an Array of the values.
|
||||||
|
*/
|
||||||
|
getAll(
|
||||||
|
query?: IDBValidKey | IDBKeyRange | null,
|
||||||
|
count?: number,
|
||||||
|
): IDBRequest<any[]>;
|
||||||
|
/**
|
||||||
|
* Retrieves the keys of records matching the given key or key range in query (up to count if given).
|
||||||
|
*
|
||||||
|
* If successful, request's result will be an Array of the keys.
|
||||||
|
*/
|
||||||
|
getAllKeys(
|
||||||
|
query?: IDBValidKey | IDBKeyRange | null,
|
||||||
|
count?: number,
|
||||||
|
): IDBRequest<IDBValidKey[]>;
|
||||||
|
/**
|
||||||
|
* Retrieves the key of the first record matching the given key or key range in query.
|
||||||
|
*
|
||||||
|
* If successful, request's result will be the key, or undefined if there was no matching record.
|
||||||
|
*/
|
||||||
|
getKey(key: IDBValidKey | IDBKeyRange): IDBRequest<IDBValidKey | undefined>;
|
||||||
|
/**
|
||||||
|
* Opens a cursor over the records matching query, ordered by direction. If query is null, all records in index are matched.
|
||||||
|
*
|
||||||
|
* If successful, request's result will be an IDBCursorWithValue, or null if there were no matching records.
|
||||||
|
*/
|
||||||
|
openCursor(
|
||||||
|
query?: IDBValidKey | IDBKeyRange | null,
|
||||||
|
direction?: IDBCursorDirection,
|
||||||
|
): IDBRequest<IDBCursorWithValue | null>;
|
||||||
|
/**
|
||||||
|
* Opens a cursor with key only flag set over the records matching query, ordered by direction. If query is null, all records in index are matched.
|
||||||
|
*
|
||||||
|
* If successful, request's result will be an IDBCursor, or null if there were no matching records.
|
||||||
|
*/
|
||||||
|
openKeyCursor(
|
||||||
|
query?: IDBValidKey | IDBKeyRange | null,
|
||||||
|
direction?: IDBCursorDirection,
|
||||||
|
): IDBRequest<IDBCursor | null>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A key range can be a single value or a range with upper and lower bounds or endpoints. If the key range has both upper and lower bounds, then it is bounded; if it has no bounds, it is unbounded. A bounded key range can either be open (the endpoints are excluded) or closed (the endpoints are included). To retrieve all keys within a certain range, you can use the following code constructs: */
|
||||||
|
export interface IDBKeyRange {
|
||||||
|
/**
|
||||||
|
* Returns lower bound, or undefined if none.
|
||||||
|
*/
|
||||||
|
readonly lower: any;
|
||||||
|
/**
|
||||||
|
* Returns true if the lower open flag is set, and false otherwise.
|
||||||
|
*/
|
||||||
|
readonly lowerOpen: boolean;
|
||||||
|
/**
|
||||||
|
* Returns upper bound, or undefined if none.
|
||||||
|
*/
|
||||||
|
readonly upper: any;
|
||||||
|
/**
|
||||||
|
* Returns true if the upper open flag is set, and false otherwise.
|
||||||
|
*/
|
||||||
|
readonly upperOpen: boolean;
|
||||||
|
/**
|
||||||
|
* Returns true if key is included in the range, and false otherwise.
|
||||||
|
*/
|
||||||
|
includes(key: any): boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** This example shows a variety of different uses of object stores, from updating the data structure with IDBObjectStore.createIndex inside an onupgradeneeded function, to adding a new item to our object store with IDBObjectStore.add. For a full working example, see our To-do Notifications app (view example live.) */
|
||||||
|
export interface IDBObjectStore {
|
||||||
|
/**
|
||||||
|
* Returns true if the store has a key generator, and false otherwise.
|
||||||
|
*/
|
||||||
|
readonly autoIncrement: boolean;
|
||||||
|
/**
|
||||||
|
* Returns a list of the names of indexes in the store.
|
||||||
|
*/
|
||||||
|
readonly indexNames: DOMStringList;
|
||||||
|
/**
|
||||||
|
* Returns the key path of the store, or null if none.
|
||||||
|
*/
|
||||||
|
readonly keyPath: string | string[];
|
||||||
|
/**
|
||||||
|
* Returns the name of the store.
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
/**
|
||||||
|
* Returns the associated transaction.
|
||||||
|
*/
|
||||||
|
readonly transaction: IDBTransaction;
|
||||||
|
/**
|
||||||
|
* Adds or updates a record in store with the given value and key.
|
||||||
|
*
|
||||||
|
* If the store uses in-line keys and key is specified a "DataError" DOMException will be thrown.
|
||||||
|
*
|
||||||
|
* If put() is used, any existing record with the key will be replaced. If add() is used, and if a record with the key already exists the request will fail, with request's error set to a "ConstraintError" DOMException.
|
||||||
|
*
|
||||||
|
* If successful, request's result will be the record's key.
|
||||||
|
*/
|
||||||
|
add(value: any, key?: IDBValidKey): IDBRequest<IDBValidKey>;
|
||||||
|
/**
|
||||||
|
* Deletes all records in store.
|
||||||
|
*
|
||||||
|
* If successful, request's result will be undefined.
|
||||||
|
*/
|
||||||
|
clear(): IDBRequest<undefined>;
|
||||||
|
/**
|
||||||
|
* Retrieves the number of records matching the given key or key range in query.
|
||||||
|
*
|
||||||
|
* If successful, request's result will be the count.
|
||||||
|
*/
|
||||||
|
count(key?: IDBValidKey | IDBKeyRange): IDBRequest<number>;
|
||||||
|
/**
|
||||||
|
* Creates a new index in store with the given name, keyPath and options and returns a new IDBIndex. If the keyPath and options define constraints that cannot be satisfied with the data already in store the upgrade transaction will abort with a "ConstraintError" DOMException.
|
||||||
|
*
|
||||||
|
* Throws an "InvalidStateError" DOMException if not called within an upgrade transaction.
|
||||||
|
*/
|
||||||
|
createIndex(
|
||||||
|
name: string,
|
||||||
|
keyPath: string | string[],
|
||||||
|
options?: IDBIndexParameters,
|
||||||
|
): IDBIndex;
|
||||||
|
/**
|
||||||
|
* Deletes records in store with the given key or in the given key range in query.
|
||||||
|
*
|
||||||
|
* If successful, request's result will be undefined.
|
||||||
|
*/
|
||||||
|
delete(key: IDBValidKey | IDBKeyRange): IDBRequest<undefined>;
|
||||||
|
/**
|
||||||
|
* Deletes the index in store with the given name.
|
||||||
|
*
|
||||||
|
* Throws an "InvalidStateError" DOMException if not called within an upgrade transaction.
|
||||||
|
*/
|
||||||
|
deleteIndex(name: string): void;
|
||||||
|
/**
|
||||||
|
* Retrieves the value of the first record matching the given key or key range in query.
|
||||||
|
*
|
||||||
|
* If successful, request's result will be the value, or undefined if there was no matching record.
|
||||||
|
*/
|
||||||
|
get(query: IDBValidKey | IDBKeyRange): IDBRequest<any | undefined>;
|
||||||
|
/**
|
||||||
|
* Retrieves the values of the records matching the given key or key range in query (up to count if given).
|
||||||
|
*
|
||||||
|
* If successful, request's result will be an Array of the values.
|
||||||
|
*/
|
||||||
|
getAll(
|
||||||
|
query?: IDBValidKey | IDBKeyRange | null,
|
||||||
|
count?: number,
|
||||||
|
): IDBRequest<any[]>;
|
||||||
|
/**
|
||||||
|
* Retrieves the keys of records matching the given key or key range in query (up to count if given).
|
||||||
|
*
|
||||||
|
* If successful, request's result will be an Array of the keys.
|
||||||
|
*/
|
||||||
|
getAllKeys(
|
||||||
|
query?: IDBValidKey | IDBKeyRange | null,
|
||||||
|
count?: number,
|
||||||
|
): IDBRequest<IDBValidKey[]>;
|
||||||
|
/**
|
||||||
|
* Retrieves the key of the first record matching the given key or key range in query.
|
||||||
|
*
|
||||||
|
* If successful, request's result will be the key, or undefined if there was no matching record.
|
||||||
|
*/
|
||||||
|
getKey(query: IDBValidKey | IDBKeyRange): IDBRequest<IDBValidKey | undefined>;
|
||||||
|
index(name: string): IDBIndex;
|
||||||
|
/**
|
||||||
|
* Opens a cursor over the records matching query, ordered by direction. If query is null, all records in store are matched.
|
||||||
|
*
|
||||||
|
* If successful, request's result will be an IDBCursorWithValue pointing at the first matching record, or null if there were no matching records.
|
||||||
|
*/
|
||||||
|
openCursor(
|
||||||
|
query?: IDBValidKey | IDBKeyRange | null,
|
||||||
|
direction?: IDBCursorDirection,
|
||||||
|
): IDBRequest<IDBCursorWithValue | null>;
|
||||||
|
/**
|
||||||
|
* Opens a cursor with key only flag set over the records matching query, ordered by direction. If query is null, all records in store are matched.
|
||||||
|
*
|
||||||
|
* If successful, request's result will be an IDBCursor pointing at the first matching record, or null if there were no matching records.
|
||||||
|
*/
|
||||||
|
openKeyCursor(
|
||||||
|
query?: IDBValidKey | IDBKeyRange | null,
|
||||||
|
direction?: IDBCursorDirection,
|
||||||
|
): IDBRequest<IDBCursor | null>;
|
||||||
|
/**
|
||||||
|
* Adds or updates a record in store with the given value and key.
|
||||||
|
*
|
||||||
|
* If the store uses in-line keys and key is specified a "DataError" DOMException will be thrown.
|
||||||
|
*
|
||||||
|
* If put() is used, any existing record with the key will be replaced. If add() is used, and if a record with the key already exists the request will fail, with request's error set to a "ConstraintError" DOMException.
|
||||||
|
*
|
||||||
|
* If successful, request's result will be the record's key.
|
||||||
|
*/
|
||||||
|
put(value: any, key?: IDBValidKey): IDBRequest<IDBValidKey>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IDBOpenDBRequestEventMap extends IDBRequestEventMap {
|
||||||
|
blocked: Event;
|
||||||
|
upgradeneeded: IDBVersionChangeEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Also inherits methods from its parents IDBRequest and EventTarget. */
|
||||||
|
export interface IDBOpenDBRequest extends IDBRequest<IDBDatabase> {
|
||||||
|
onblocked: ((this: IDBOpenDBRequest, ev: Event) => any) | null;
|
||||||
|
onupgradeneeded:
|
||||||
|
| ((this: IDBOpenDBRequest, ev: IDBVersionChangeEvent) => any)
|
||||||
|
| null;
|
||||||
|
addEventListener<K extends keyof IDBOpenDBRequestEventMap>(
|
||||||
|
type: K,
|
||||||
|
listener: (this: IDBOpenDBRequest, ev: IDBOpenDBRequestEventMap[K]) => any,
|
||||||
|
options?: boolean | AddEventListenerOptions,
|
||||||
|
): void;
|
||||||
|
addEventListener(
|
||||||
|
type: string,
|
||||||
|
listener: EventListenerOrEventListenerObject,
|
||||||
|
options?: boolean | AddEventListenerOptions,
|
||||||
|
): void;
|
||||||
|
removeEventListener<K extends keyof IDBOpenDBRequestEventMap>(
|
||||||
|
type: K,
|
||||||
|
listener: (this: IDBOpenDBRequest, ev: IDBOpenDBRequestEventMap[K]) => any,
|
||||||
|
options?: boolean | EventListenerOptions,
|
||||||
|
): void;
|
||||||
|
removeEventListener(
|
||||||
|
type: string,
|
||||||
|
listener: EventListenerOrEventListenerObject,
|
||||||
|
options?: boolean | EventListenerOptions,
|
||||||
|
): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type IDBRequestReadyState = "done" | "pending";
|
||||||
|
|
||||||
|
export interface IDBRequestEventMap {
|
||||||
|
error: Event;
|
||||||
|
success: Event;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** An abnormal event (called an exception) which occurs as a result of calling a method or accessing a property of a web API. */
|
||||||
|
export interface DOMException {
|
||||||
|
readonly code: number;
|
||||||
|
readonly message: string;
|
||||||
|
readonly name: string;
|
||||||
|
readonly ABORT_ERR: number;
|
||||||
|
readonly DATA_CLONE_ERR: number;
|
||||||
|
readonly DOMSTRING_SIZE_ERR: number;
|
||||||
|
readonly HIERARCHY_REQUEST_ERR: number;
|
||||||
|
readonly INDEX_SIZE_ERR: number;
|
||||||
|
readonly INUSE_ATTRIBUTE_ERR: number;
|
||||||
|
readonly INVALID_ACCESS_ERR: number;
|
||||||
|
readonly INVALID_CHARACTER_ERR: number;
|
||||||
|
readonly INVALID_MODIFICATION_ERR: number;
|
||||||
|
readonly INVALID_NODE_TYPE_ERR: number;
|
||||||
|
readonly INVALID_STATE_ERR: number;
|
||||||
|
readonly NAMESPACE_ERR: number;
|
||||||
|
readonly NETWORK_ERR: number;
|
||||||
|
readonly NOT_FOUND_ERR: number;
|
||||||
|
readonly NOT_SUPPORTED_ERR: number;
|
||||||
|
readonly NO_DATA_ALLOWED_ERR: number;
|
||||||
|
readonly NO_MODIFICATION_ALLOWED_ERR: number;
|
||||||
|
readonly QUOTA_EXCEEDED_ERR: number;
|
||||||
|
readonly SECURITY_ERR: number;
|
||||||
|
readonly SYNTAX_ERR: number;
|
||||||
|
readonly TIMEOUT_ERR: number;
|
||||||
|
readonly TYPE_MISMATCH_ERR: number;
|
||||||
|
readonly URL_MISMATCH_ERR: number;
|
||||||
|
readonly VALIDATION_ERR: number;
|
||||||
|
readonly WRONG_DOCUMENT_ERR: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The request object does not initially contain any information about the result of the operation, but once information becomes available, an event is fired on the request, and the information becomes available through the properties of the IDBRequest instance. */
|
||||||
|
export interface IDBRequest<T = any> extends EventTarget {
|
||||||
|
/**
|
||||||
|
* When a request is completed, returns the error (a DOMException), or null if the request succeeded. Throws a "InvalidStateError" DOMException if the request is still pending.
|
||||||
|
*/
|
||||||
|
readonly error: DOMException | null;
|
||||||
|
onerror: ((this: IDBRequest<T>, ev: Event) => any) | null;
|
||||||
|
onsuccess: ((this: IDBRequest<T>, ev: Event) => any) | null;
|
||||||
|
/**
|
||||||
|
* Returns "pending" until a request is complete, then returns "done".
|
||||||
|
*/
|
||||||
|
readonly readyState: IDBRequestReadyState;
|
||||||
|
/**
|
||||||
|
* When a request is completed, returns the result, or undefined if the request failed. Throws a "InvalidStateError" DOMException if the request is still pending.
|
||||||
|
*/
|
||||||
|
readonly result: T;
|
||||||
|
/**
|
||||||
|
* Returns the IDBObjectStore, IDBIndex, or IDBCursor the request was made against, or null if is was an open request.
|
||||||
|
*/
|
||||||
|
readonly source: IDBObjectStore | IDBIndex | IDBCursor;
|
||||||
|
/**
|
||||||
|
* Returns the IDBTransaction the request was made within. If this as an open request, then it returns an upgrade transaction while it is running, or null otherwise.
|
||||||
|
*/
|
||||||
|
readonly transaction: IDBTransaction | null;
|
||||||
|
addEventListener<K extends keyof IDBRequestEventMap>(
|
||||||
|
type: K,
|
||||||
|
listener: (this: IDBRequest<T>, ev: IDBRequestEventMap[K]) => any,
|
||||||
|
options?: boolean | AddEventListenerOptions,
|
||||||
|
): void;
|
||||||
|
addEventListener(
|
||||||
|
type: string,
|
||||||
|
listener: EventListenerOrEventListenerObject,
|
||||||
|
options?: boolean | AddEventListenerOptions,
|
||||||
|
): void;
|
||||||
|
removeEventListener<K extends keyof IDBRequestEventMap>(
|
||||||
|
type: K,
|
||||||
|
listener: (this: IDBRequest<T>, ev: IDBRequestEventMap[K]) => any,
|
||||||
|
options?: boolean | EventListenerOptions,
|
||||||
|
): void;
|
||||||
|
removeEventListener(
|
||||||
|
type: string,
|
||||||
|
listener: EventListenerOrEventListenerObject,
|
||||||
|
options?: boolean | EventListenerOptions,
|
||||||
|
): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IDBTransactionEventMap {
|
||||||
|
abort: Event;
|
||||||
|
complete: Event;
|
||||||
|
error: Event;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IDBTransaction extends EventTarget {
|
||||||
|
/**
|
||||||
|
* Returns the transaction's connection.
|
||||||
|
*/
|
||||||
|
readonly db: IDBDatabase;
|
||||||
|
/**
|
||||||
|
* If the transaction was aborted, returns the error (a DOMException) providing the reason.
|
||||||
|
*/
|
||||||
|
readonly error: DOMException;
|
||||||
|
/**
|
||||||
|
* Returns the mode the transaction was created with ("readonly" or "readwrite"), or "versionchange" for an upgrade transaction.
|
||||||
|
*/
|
||||||
|
readonly mode: IDBTransactionMode;
|
||||||
|
/**
|
||||||
|
* Returns a list of the names of object stores in the transaction's scope. For an upgrade transaction this is all object stores in the database.
|
||||||
|
*/
|
||||||
|
readonly objectStoreNames: DOMStringList;
|
||||||
|
onabort: ((this: IDBTransaction, ev: Event) => any) | null;
|
||||||
|
oncomplete: ((this: IDBTransaction, ev: Event) => any) | null;
|
||||||
|
onerror: ((this: IDBTransaction, ev: Event) => any) | null;
|
||||||
|
/**
|
||||||
|
* Aborts the transaction. All pending requests will fail with a "AbortError" DOMException and all changes made to the database will be reverted.
|
||||||
|
*/
|
||||||
|
abort(): void;
|
||||||
|
/**
|
||||||
|
* Returns an IDBObjectStore in the transaction's scope.
|
||||||
|
*/
|
||||||
|
objectStore(name: string): IDBObjectStore;
|
||||||
|
addEventListener<K extends keyof IDBTransactionEventMap>(
|
||||||
|
type: K,
|
||||||
|
listener: (this: IDBTransaction, ev: IDBTransactionEventMap[K]) => any,
|
||||||
|
options?: boolean | AddEventListenerOptions,
|
||||||
|
): void;
|
||||||
|
addEventListener(
|
||||||
|
type: string,
|
||||||
|
listener: EventListenerOrEventListenerObject,
|
||||||
|
options?: boolean | AddEventListenerOptions,
|
||||||
|
): void;
|
||||||
|
removeEventListener<K extends keyof IDBTransactionEventMap>(
|
||||||
|
type: K,
|
||||||
|
listener: (this: IDBTransaction, ev: IDBTransactionEventMap[K]) => any,
|
||||||
|
options?: boolean | EventListenerOptions,
|
||||||
|
): void;
|
||||||
|
removeEventListener(
|
||||||
|
type: string,
|
||||||
|
listener: EventListenerOrEventListenerObject,
|
||||||
|
options?: boolean | EventListenerOptions,
|
||||||
|
): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** This IndexedDB API interface indicates that the version of the database has changed, as the result of an IDBOpenDBRequest.onupgradeneeded event handler function. */
|
||||||
|
export interface IDBVersionChangeEvent extends Event {
|
||||||
|
readonly newVersion: number | null;
|
||||||
|
readonly oldVersion: number;
|
||||||
|
}
|
@ -1,23 +1,23 @@
|
|||||||
import { BridgeIDBFactory } from "./BridgeIDBFactory";
|
import { BridgeIDBFactory } from "./BridgeIDBFactory";
|
||||||
import { BridgeIDBCursor } from "./BridgeIDBCursor";
|
import { BridgeIDBCursor } from "./BridgeIDBCursor";
|
||||||
import { BridgeIDBIndex } from "./BridgeIDBIndex";
|
import { BridgeIDBIndex } from "./BridgeIDBIndex";
|
||||||
import BridgeIDBDatabase from "./BridgeIDBDatabase";
|
import { BridgeIDBDatabase } from "./BridgeIDBDatabase";
|
||||||
import BridgeIDBKeyRange from "./BridgeIDBKeyRange";
|
import { BridgeIDBKeyRange } from "./BridgeIDBKeyRange";
|
||||||
import BridgeIDBObjectStore from "./BridgeIDBObjectStore";
|
import { BridgeIDBObjectStore } from "./BridgeIDBObjectStore";
|
||||||
import BridgeIDBOpenDBRequest from "./BridgeIDBOpenDBRequest";
|
import { BridgeIDBOpenDBRequest } from "./BridgeIDBOpenDBRequest";
|
||||||
import BridgeIDBRequest from "./BridgeIDBRequest";
|
import { BridgeIDBRequest } from "./BridgeIDBRequest";
|
||||||
import BridgeIDBTransaction from "./BridgeIDBTransaction";
|
import { BridgeIDBTransaction } from "./BridgeIDBTransaction";
|
||||||
import BridgeIDBVersionChangeEvent from "./BridgeIDBVersionChangeEvent";
|
import { BridgeIDBVersionChangeEvent } from "./BridgeIDBVersionChangeEvent";
|
||||||
|
|
||||||
export { BridgeIDBFactory, BridgeIDBCursor };
|
export { BridgeIDBFactory, BridgeIDBCursor };
|
||||||
|
|
||||||
export { MemoryBackend } from "./MemoryBackend";
|
export { MemoryBackend } from "./MemoryBackend";
|
||||||
|
|
||||||
// globalThis polyfill, see https://mathiasbynens.be/notes/globalthis
|
// globalThis polyfill, see https://mathiasbynens.be/notes/globalthis
|
||||||
(function() {
|
(function () {
|
||||||
if (typeof globalThis === "object") return;
|
if (typeof globalThis === "object") return;
|
||||||
Object.defineProperty(Object.prototype, "__magic__", {
|
Object.defineProperty(Object.prototype, "__magic__", {
|
||||||
get: function() {
|
get: function () {
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
configurable: true, // This makes it possible to `delete` the getter later.
|
configurable: true, // This makes it possible to `delete` the getter later.
|
||||||
@ -58,3 +58,6 @@ export function shimIndexedDB(factory: BridgeIDBFactory): void {
|
|||||||
// @ts-ignore: shimming
|
// @ts-ignore: shimming
|
||||||
globalThis.IDBVersionChangeEvent = BridgeIDBVersionChangeEvent;
|
globalThis.IDBVersionChangeEvent = BridgeIDBVersionChangeEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
import * as idbtypes from "./idbtypes";
|
||||||
|
export type { idbtypes };
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -24,15 +24,13 @@ SPDX-License-Identifier: MIT
|
|||||||
|
|
||||||
// Original repository: https://github.com/qwertie/btree-typescript
|
// Original repository: https://github.com/qwertie/btree-typescript
|
||||||
|
|
||||||
|
|
||||||
/** Read-only set interface (subinterface of IMapSource<K,any>).
|
/** Read-only set interface (subinterface of IMapSource<K,any>).
|
||||||
* The word "set" usually means that each item in the collection is unique
|
* The word "set" usually means that each item in the collection is unique
|
||||||
* (appears only once, based on a definition of equality used by the
|
* (appears only once, based on a definition of equality used by the
|
||||||
* collection.) Objects conforming to this interface aren't guaranteed not
|
* collection.) Objects conforming to this interface aren't guaranteed not
|
||||||
* to contain duplicates, but as an example, BTree<K,V> implements this
|
* to contain duplicates, but as an example, BTree<K,V> implements this
|
||||||
* interface and does not allow duplicates. */
|
* interface and does not allow duplicates. */
|
||||||
export interface ISetSource<K=any>
|
export interface ISetSource<K = any> {
|
||||||
{
|
|
||||||
/** Returns the number of key/value pairs in the map object. */
|
/** Returns the number of key/value pairs in the map object. */
|
||||||
size: number;
|
size: number;
|
||||||
/** Returns a boolean asserting whether the key exists in the map object or not. */
|
/** Returns a boolean asserting whether the key exists in the map object or not. */
|
||||||
@ -42,21 +40,23 @@ export interface ISetSource<K=any>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Read-only map interface (i.e. a source of key-value pairs). */
|
/** Read-only map interface (i.e. a source of key-value pairs). */
|
||||||
export interface IMapSource<K=any, V=any> extends ISetSource<K>
|
export interface IMapSource<K = any, V = any> extends ISetSource<K> {
|
||||||
{
|
|
||||||
/** Returns the number of key/value pairs in the map object. */
|
/** Returns the number of key/value pairs in the map object. */
|
||||||
size: number;
|
size: number;
|
||||||
/** Returns the value associated to the key, or undefined if there is none. */
|
/** Returns the value associated to the key, or undefined if there is none. */
|
||||||
get(key: K): V|undefined;
|
get(key: K): V | undefined;
|
||||||
/** Returns a boolean asserting whether the key exists in the map object or not. */
|
/** Returns a boolean asserting whether the key exists in the map object or not. */
|
||||||
has(key: K): boolean;
|
has(key: K): boolean;
|
||||||
/** Calls callbackFn once for each key-value pair present in the map object.
|
/** Calls callbackFn once for each key-value pair present in the map object.
|
||||||
* The ES6 Map class sends the value to the callback before the key, so
|
* The ES6 Map class sends the value to the callback before the key, so
|
||||||
* this interface must do likewise. */
|
* this interface must do likewise. */
|
||||||
forEach(callbackFn: (v:V, k:K, map:IMapSource<K,V>) => void, thisArg?: any): void;
|
forEach(
|
||||||
|
callbackFn: (v: V, k: K, map: IMapSource<K, V>) => void,
|
||||||
|
thisArg?: any,
|
||||||
|
): void;
|
||||||
|
|
||||||
/** Returns an iterator that provides all key-value pairs from the collection (as arrays of length 2). */
|
/** Returns an iterator that provides all key-value pairs from the collection (as arrays of length 2). */
|
||||||
entries(): IterableIterator<[K,V]>;
|
entries(): IterableIterator<[K, V]>;
|
||||||
/** Returns a new iterator for iterating the keys of each pair. */
|
/** Returns a new iterator for iterating the keys of each pair. */
|
||||||
keys(): IterableIterator<K>;
|
keys(): IterableIterator<K>;
|
||||||
/** Returns a new iterator for iterating the values of each pair. */
|
/** Returns a new iterator for iterating the values of each pair. */
|
||||||
@ -65,14 +65,13 @@ export interface IMapSource<K=any, V=any> extends ISetSource<K>
|
|||||||
//[Symbol.iterator](): IterableIterator<[K,V]>;
|
//[Symbol.iterator](): IterableIterator<[K,V]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Write-only set interface (the set cannot be queried, but items can be added to it.)
|
/** Write-only set interface (the set cannot be queried, but items can be added to it.)
|
||||||
* @description Note: BTree<K,V> does not officially implement this interface,
|
* @description Note: BTree<K,V> does not officially implement this interface,
|
||||||
* but BTree<K> can be used as an instance of ISetSink<K>. */
|
* but BTree<K> can be used as an instance of ISetSink<K>. */
|
||||||
export interface ISetSink<K=any>
|
export interface ISetSink<K = any> {
|
||||||
{
|
|
||||||
/** Adds the specified item to the set, if it was not in the set already. */
|
/** Adds the specified item to the set, if it was not in the set already. */
|
||||||
add(key: K): any;
|
add(key: K): any;
|
||||||
/** Returns true if an element in the map object existed and has been
|
/** Returns true if an element in the map object existed and has been
|
||||||
* removed, or false if the element did not exist. */
|
* removed, or false if the element did not exist. */
|
||||||
delete(key: K): boolean;
|
delete(key: K): boolean;
|
||||||
/** Removes everything so that the set is empty. */
|
/** Removes everything so that the set is empty. */
|
||||||
@ -80,12 +79,11 @@ export interface ISetSink<K=any>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Write-only map interface (i.e. a drain into which key-value pairs can be "sunk") */
|
/** Write-only map interface (i.e. a drain into which key-value pairs can be "sunk") */
|
||||||
export interface IMapSink<K=any, V=any>
|
export interface IMapSink<K = any, V = any> {
|
||||||
{
|
/** Returns true if an element in the map object existed and has been
|
||||||
/** Returns true if an element in the map object existed and has been
|
|
||||||
* removed, or false if the element did not exist. */
|
* removed, or false if the element did not exist. */
|
||||||
delete(key: K): boolean;
|
delete(key: K): boolean;
|
||||||
/** Sets the value for the key in the map object (the return value is
|
/** Sets the value for the key in the map object (the return value is
|
||||||
* boolean in BTree but Map returns the Map itself.) */
|
* boolean in BTree but Map returns the Map itself.) */
|
||||||
set(key: K, value: V): any;
|
set(key: K, value: V): any;
|
||||||
/** Removes all key/value pairs from the IMap object. */
|
/** Removes all key/value pairs from the IMap object. */
|
||||||
@ -95,119 +93,154 @@ export interface IMapSink<K=any, V=any>
|
|||||||
/** Set interface.
|
/** Set interface.
|
||||||
* @description Note: BTree<K,V> does not officially implement this interface,
|
* @description Note: BTree<K,V> does not officially implement this interface,
|
||||||
* but BTree<K> can be used as an instance of ISet<K>. */
|
* but BTree<K> can be used as an instance of ISet<K>. */
|
||||||
export interface ISet<K=any> extends ISetSource<K>, ISetSink<K> { }
|
export interface ISet<K = any> extends ISetSource<K>, ISetSink<K> {}
|
||||||
|
|
||||||
/** An interface compatible with ES6 Map and BTree. This interface does not
|
/** An interface compatible with ES6 Map and BTree. This interface does not
|
||||||
* describe the complete interface of either class, but merely the common
|
* describe the complete interface of either class, but merely the common
|
||||||
* interface shared by both. */
|
* interface shared by both. */
|
||||||
export interface IMap<K=any, V=any> extends IMapSource<K, V>, IMapSink<K, V> { }
|
export interface IMap<K = any, V = any>
|
||||||
|
extends IMapSource<K, V>,
|
||||||
|
IMapSink<K, V> {}
|
||||||
|
|
||||||
/** An data source that provides read-only access to a set of items called
|
/** An data source that provides read-only access to a set of items called
|
||||||
* "keys" in sorted order. This is a subinterface of ISortedMapSource. */
|
* "keys" in sorted order. This is a subinterface of ISortedMapSource. */
|
||||||
export interface ISortedSetSource<K=any> extends ISetSource<K>
|
export interface ISortedSetSource<K = any> extends ISetSource<K> {
|
||||||
{
|
|
||||||
/** Gets the lowest key in the collection. */
|
/** Gets the lowest key in the collection. */
|
||||||
minKey(): K | undefined;
|
minKey(): K | undefined;
|
||||||
/** Gets the highest key in the collection. */
|
/** Gets the highest key in the collection. */
|
||||||
maxKey(): K | undefined;
|
maxKey(): K | undefined;
|
||||||
/** Returns the next key larger than the specified key (or undefined if there is none) */
|
/** Returns the next key larger than the specified key (or undefined if there is none) */
|
||||||
nextHigherKey(key: K): K|undefined;
|
nextHigherKey(key: K): K | undefined;
|
||||||
/** Returns the next key smaller than the specified key (or undefined if there is none) */
|
/** Returns the next key smaller than the specified key (or undefined if there is none) */
|
||||||
nextLowerKey(key: K): K|undefined;
|
nextLowerKey(key: K): K | undefined;
|
||||||
/** Calls `callback` on the specified range of keys, in ascending order by key.
|
/** Calls `callback` on the specified range of keys, in ascending order by key.
|
||||||
* @param low The first key scanned will be greater than or equal to `low`.
|
* @param low The first key scanned will be greater than or equal to `low`.
|
||||||
* @param high Scanning stops when a key larger than this is reached.
|
* @param high Scanning stops when a key larger than this is reached.
|
||||||
* @param includeHigh If the `high` key is present in the map, `onFound` is called
|
* @param includeHigh If the `high` key is present in the map, `onFound` is called
|
||||||
* for that final pair if and only if this parameter is true.
|
* for that final pair if and only if this parameter is true.
|
||||||
* @param onFound A function that is called for each key pair. Because this
|
* @param onFound A function that is called for each key pair. Because this
|
||||||
* is a subinterface of ISortedMapSource, if there is a value
|
* is a subinterface of ISortedMapSource, if there is a value
|
||||||
* associated with the key, it is passed as the second parameter.
|
* associated with the key, it is passed as the second parameter.
|
||||||
* @param initialCounter Initial third argument of `onFound`. This value
|
* @param initialCounter Initial third argument of `onFound`. This value
|
||||||
* increases by one each time `onFound` is called. Default: 0
|
* increases by one each time `onFound` is called. Default: 0
|
||||||
* @returns Number of pairs found and the number of times `onFound` was called.
|
* @returns Number of pairs found and the number of times `onFound` was called.
|
||||||
*/
|
*/
|
||||||
forRange(low: K, high: K, includeHigh: boolean, onFound?: (k:K,v:any,counter:number) => void, initialCounter?: number): number;
|
forRange(
|
||||||
/** Returns a new iterator for iterating the keys of each pair in ascending order.
|
low: K,
|
||||||
|
high: K,
|
||||||
|
includeHigh: boolean,
|
||||||
|
onFound?: (k: K, v: any, counter: number) => void,
|
||||||
|
initialCounter?: number,
|
||||||
|
): number;
|
||||||
|
/** Returns a new iterator for iterating the keys of each pair in ascending order.
|
||||||
* @param firstKey: Minimum key to include in the output. */
|
* @param firstKey: Minimum key to include in the output. */
|
||||||
keys(firstKey?: K): IterableIterator<K>;
|
keys(firstKey?: K): IterableIterator<K>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** An data source that provides read-only access to items in sorted order. */
|
/** An data source that provides read-only access to items in sorted order. */
|
||||||
export interface ISortedMapSource<K=any, V=any> extends IMapSource<K, V>, ISortedSetSource<K>
|
export interface ISortedMapSource<K = any, V = any>
|
||||||
{
|
extends IMapSource<K, V>,
|
||||||
|
ISortedSetSource<K> {
|
||||||
/** Returns the next pair whose key is larger than the specified key (or undefined if there is none) */
|
/** Returns the next pair whose key is larger than the specified key (or undefined if there is none) */
|
||||||
nextHigherPair(key: K): [K,V]|undefined;
|
nextHigherPair(key: K): [K, V] | undefined;
|
||||||
/** Returns the next pair whose key is smaller than the specified key (or undefined if there is none) */
|
/** Returns the next pair whose key is smaller than the specified key (or undefined if there is none) */
|
||||||
nextLowerPair(key: K): [K,V]|undefined;
|
nextLowerPair(key: K): [K, V] | undefined;
|
||||||
/** Builds an array of pairs from the specified range of keys, sorted by key.
|
/** Builds an array of pairs from the specified range of keys, sorted by key.
|
||||||
* Each returned pair is also an array: pair[0] is the key, pair[1] is the value.
|
* Each returned pair is also an array: pair[0] is the key, pair[1] is the value.
|
||||||
* @param low The first key in the array will be greater than or equal to `low`.
|
* @param low The first key in the array will be greater than or equal to `low`.
|
||||||
* @param high This method returns when a key larger than this is reached.
|
* @param high This method returns when a key larger than this is reached.
|
||||||
* @param includeHigh If the `high` key is present in the map, its pair will be
|
* @param includeHigh If the `high` key is present in the map, its pair will be
|
||||||
* included in the output if and only if this parameter is true. Note:
|
* included in the output if and only if this parameter is true. Note:
|
||||||
* if the `low` key is present, it is always included in the output.
|
* if the `low` key is present, it is always included in the output.
|
||||||
* @param maxLength Maximum length of the returned array (default: unlimited)
|
* @param maxLength Maximum length of the returned array (default: unlimited)
|
||||||
* @description Computational complexity: O(result.length + log size)
|
* @description Computational complexity: O(result.length + log size)
|
||||||
*/
|
*/
|
||||||
getRange(low: K, high: K, includeHigh?: boolean, maxLength?: number): [K,V][];
|
getRange(
|
||||||
|
low: K,
|
||||||
|
high: K,
|
||||||
|
includeHigh?: boolean,
|
||||||
|
maxLength?: number,
|
||||||
|
): [K, V][];
|
||||||
/** Calls `callback` on the specified range of keys, in ascending order by key.
|
/** Calls `callback` on the specified range of keys, in ascending order by key.
|
||||||
* @param low The first key scanned will be greater than or equal to `low`.
|
* @param low The first key scanned will be greater than or equal to `low`.
|
||||||
* @param high Scanning stops when a key larger than this is reached.
|
* @param high Scanning stops when a key larger than this is reached.
|
||||||
* @param includeHigh If the `high` key is present in the map, `onFound` is called
|
* @param includeHigh If the `high` key is present in the map, `onFound` is called
|
||||||
* for that final pair if and only if this parameter is true.
|
* for that final pair if and only if this parameter is true.
|
||||||
* @param onFound A function that is called for each key-value pair.
|
* @param onFound A function that is called for each key-value pair.
|
||||||
* @param initialCounter Initial third argument of onFound. This value
|
* @param initialCounter Initial third argument of onFound. This value
|
||||||
* increases by one each time `onFound` is called. Default: 0
|
* increases by one each time `onFound` is called. Default: 0
|
||||||
* @returns Number of pairs found and the number of times `callback` was called.
|
* @returns Number of pairs found and the number of times `callback` was called.
|
||||||
*/
|
*/
|
||||||
forRange(low: K, high: K, includeHigh: boolean, onFound?: (k:K,v:V,counter:number) => void, initialCounter?: number): number;
|
forRange(
|
||||||
|
low: K,
|
||||||
|
high: K,
|
||||||
|
includeHigh: boolean,
|
||||||
|
onFound?: (k: K, v: V, counter: number) => void,
|
||||||
|
initialCounter?: number,
|
||||||
|
): number;
|
||||||
/** Returns an iterator that provides items in order by key.
|
/** Returns an iterator that provides items in order by key.
|
||||||
* @param firstKey: Minimum key to include in the output. */
|
* @param firstKey: Minimum key to include in the output. */
|
||||||
entries(firstKey?: K): IterableIterator<[K,V]>;
|
entries(firstKey?: K): IterableIterator<[K, V]>;
|
||||||
/** Returns a new iterator for iterating the keys of each pair in ascending order.
|
/** Returns a new iterator for iterating the keys of each pair in ascending order.
|
||||||
* @param firstKey: Minimum key to include in the output. */
|
* @param firstKey: Minimum key to include in the output. */
|
||||||
keys(firstKey?: K): IterableIterator<K>;
|
keys(firstKey?: K): IterableIterator<K>;
|
||||||
/** Returns a new iterator for iterating the values of each pair in order by key.
|
/** Returns a new iterator for iterating the values of each pair in order by key.
|
||||||
* @param firstKey: Minimum key whose associated value is included in the output. */
|
* @param firstKey: Minimum key whose associated value is included in the output. */
|
||||||
values(firstKey?: K): IterableIterator<V>;
|
values(firstKey?: K): IterableIterator<V>;
|
||||||
|
|
||||||
// This method should logically be in IMapSource but is not supported by ES6 Map
|
// This method should logically be in IMapSource but is not supported by ES6 Map
|
||||||
/** Performs a reduce operation like the `reduce` method of `Array`.
|
/** Performs a reduce operation like the `reduce` method of `Array`.
|
||||||
* It is used to combine all pairs into a single value, or perform conversions. */
|
* It is used to combine all pairs into a single value, or perform conversions. */
|
||||||
reduce<R>(callback: (previous:R,currentPair:[K,V],counter:number,tree:IMapF<K,V>) => R, initialValue: R): R;
|
reduce<R>(
|
||||||
/** Performs a reduce operation like the `reduce` method of `Array`.
|
callback: (
|
||||||
|
previous: R,
|
||||||
|
currentPair: [K, V],
|
||||||
|
counter: number,
|
||||||
|
tree: IMapF<K, V>,
|
||||||
|
) => R,
|
||||||
|
initialValue: R,
|
||||||
|
): R;
|
||||||
|
/** Performs a reduce operation like the `reduce` method of `Array`.
|
||||||
* It is used to combine all pairs into a single value, or perform conversions. */
|
* It is used to combine all pairs into a single value, or perform conversions. */
|
||||||
reduce<R>(callback: (previous:R|undefined,currentPair:[K,V],counter:number,tree:IMapF<K,V>) => R): R|undefined;
|
reduce<R>(
|
||||||
|
callback: (
|
||||||
|
previous: R | undefined,
|
||||||
|
currentPair: [K, V],
|
||||||
|
counter: number,
|
||||||
|
tree: IMapF<K, V>,
|
||||||
|
) => R,
|
||||||
|
): R | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** An interface for a set of keys (the combination of ISortedSetSource<K> and ISetSink<K>) */
|
/** An interface for a set of keys (the combination of ISortedSetSource<K> and ISetSink<K>) */
|
||||||
export interface ISortedSet<K=any> extends ISortedSetSource<K>, ISetSink<K> { }
|
export interface ISortedSet<K = any> extends ISortedSetSource<K>, ISetSink<K> {}
|
||||||
|
|
||||||
/** An interface for a sorted map (dictionary),
|
/** An interface for a sorted map (dictionary),
|
||||||
* not including functional/persistent methods. */
|
* not including functional/persistent methods. */
|
||||||
export interface ISortedMap<K=any, V=any> extends IMap<K,V>, ISortedMapSource<K, V>
|
export interface ISortedMap<K = any, V = any>
|
||||||
{
|
extends IMap<K, V>,
|
||||||
|
ISortedMapSource<K, V> {
|
||||||
// All of the following methods should be in IMap but are left out of IMap
|
// All of the following methods should be in IMap but are left out of IMap
|
||||||
// so that IMap is compatible with ES6 Map.
|
// so that IMap is compatible with ES6 Map.
|
||||||
|
|
||||||
/** Adds or overwrites a key-value pair in the sorted map.
|
/** Adds or overwrites a key-value pair in the sorted map.
|
||||||
* @param key the key is used to determine the sort order of data in the tree.
|
* @param key the key is used to determine the sort order of data in the tree.
|
||||||
* @param value data to associate with the key
|
* @param value data to associate with the key
|
||||||
* @param overwrite Whether to overwrite an existing key-value pair
|
* @param overwrite Whether to overwrite an existing key-value pair
|
||||||
* (default: true). If this is false and there is an existing
|
* (default: true). If this is false and there is an existing
|
||||||
* key-value pair then the call to this method has no effect.
|
* key-value pair then the call to this method has no effect.
|
||||||
* @returns true if a new key-value pair was added, false if the key
|
* @returns true if a new key-value pair was added, false if the key
|
||||||
* already existed. */
|
* already existed. */
|
||||||
set(key: K, value: V, overwrite?: boolean): boolean;
|
set(key: K, value: V, overwrite?: boolean): boolean;
|
||||||
/** Adds all pairs from a list of key-value pairs.
|
/** Adds all pairs from a list of key-value pairs.
|
||||||
* @param pairs Pairs to add to this tree. If there are duplicate keys,
|
* @param pairs Pairs to add to this tree. If there are duplicate keys,
|
||||||
* later pairs currently overwrite earlier ones (e.g. [[0,1],[0,7]]
|
* later pairs currently overwrite earlier ones (e.g. [[0,1],[0,7]]
|
||||||
* associates 0 with 7.)
|
* associates 0 with 7.)
|
||||||
* @param overwrite Whether to overwrite pairs that already exist (if false,
|
* @param overwrite Whether to overwrite pairs that already exist (if false,
|
||||||
* pairs[i] is ignored when the key pairs[i][0] already exists.)
|
* pairs[i] is ignored when the key pairs[i][0] already exists.)
|
||||||
* @returns The number of pairs added to the collection.
|
* @returns The number of pairs added to the collection.
|
||||||
*/
|
*/
|
||||||
setPairs(pairs: [K,V][], overwrite?: boolean): number;
|
setPairs(pairs: [K, V][], overwrite?: boolean): number;
|
||||||
/** Deletes a series of keys from the collection. */
|
/** Deletes a series of keys from the collection. */
|
||||||
deleteKeys(keys: K[]): number;
|
deleteKeys(keys: K[]): number;
|
||||||
/** Removes a range of key-value pairs from the B+ tree.
|
/** Removes a range of key-value pairs from the B+ tree.
|
||||||
@ -218,18 +251,18 @@ export interface ISortedMap<K=any, V=any> extends IMap<K,V>, ISortedMapSource<K,
|
|||||||
deleteRange(low: K, high: K, includeHigh: boolean): number;
|
deleteRange(low: K, high: K, includeHigh: boolean): number;
|
||||||
|
|
||||||
// TypeScript requires these methods of ISortedMapSource to be repeated
|
// TypeScript requires these methods of ISortedMapSource to be repeated
|
||||||
entries(firstKey?: K): IterableIterator<[K,V]>;
|
entries(firstKey?: K): IterableIterator<[K, V]>;
|
||||||
keys(firstKey?: K): IterableIterator<K>;
|
keys(firstKey?: K): IterableIterator<K>;
|
||||||
values(firstKey?: K): IterableIterator<V>;
|
values(firstKey?: K): IterableIterator<V>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** An interface for a functional set, in which the set object could be read-only
|
/** An interface for a functional set, in which the set object could be read-only
|
||||||
* but new versions of the set can be created by calling "with" or "without"
|
* but new versions of the set can be created by calling "with" or "without"
|
||||||
* methods to add or remove keys. This is a subinterface of IMapF<K,V>,
|
* methods to add or remove keys. This is a subinterface of IMapF<K,V>,
|
||||||
* so the items in the set may be referred to as "keys". */
|
* so the items in the set may be referred to as "keys". */
|
||||||
export interface ISetF<K=any> extends ISetSource<K> {
|
export interface ISetF<K = any> extends ISetSource<K> {
|
||||||
/** Returns a copy of the set with the specified key included.
|
/** Returns a copy of the set with the specified key included.
|
||||||
* @description You might wonder why this method accepts only one key
|
* @description You might wonder why this method accepts only one key
|
||||||
* instead of `...keys: K[]`. The reason is that the derived interface
|
* instead of `...keys: K[]`. The reason is that the derived interface
|
||||||
* IMapF expects the second parameter to be a value. Therefore
|
* IMapF expects the second parameter to be a value. Therefore
|
||||||
* withKeys() is provided to set multiple keys at once. */
|
* withKeys() is provided to set multiple keys at once. */
|
||||||
@ -239,91 +272,133 @@ export interface ISetF<K=any> extends ISetSource<K> {
|
|||||||
/** Returns a copy of the tree with all the keys in the specified array present.
|
/** Returns a copy of the tree with all the keys in the specified array present.
|
||||||
* @param keys The keys to add.
|
* @param keys The keys to add.
|
||||||
* @param returnThisIfUnchanged If true, the method returns `this` when
|
* @param returnThisIfUnchanged If true, the method returns `this` when
|
||||||
* all of the keys are already present in the collection. The
|
* all of the keys are already present in the collection. The
|
||||||
* default value may be true or false depending on the concrete
|
* default value may be true or false depending on the concrete
|
||||||
* implementation of the interface (in BTree, the default is false.) */
|
* implementation of the interface (in BTree, the default is false.) */
|
||||||
withKeys(keys: K[], returnThisIfUnchanged?: boolean): ISetF<K>;
|
withKeys(keys: K[], returnThisIfUnchanged?: boolean): ISetF<K>;
|
||||||
/** Returns a copy of the tree with all the keys in the specified array removed. */
|
/** Returns a copy of the tree with all the keys in the specified array removed. */
|
||||||
withoutKeys(keys: K[], returnThisIfUnchanged?: boolean): ISetF<K>;
|
withoutKeys(keys: K[], returnThisIfUnchanged?: boolean): ISetF<K>;
|
||||||
/** Returns a copy of the tree with items removed whenever the callback
|
/** Returns a copy of the tree with items removed whenever the callback
|
||||||
* function returns false.
|
* function returns false.
|
||||||
* @param callback A function to call for each item in the set.
|
* @param callback A function to call for each item in the set.
|
||||||
* The second parameter to `callback` exists because ISetF
|
* The second parameter to `callback` exists because ISetF
|
||||||
* is a subinterface of IMapF. If the object is a map, v
|
* is a subinterface of IMapF. If the object is a map, v
|
||||||
* is the value associated with the key, otherwise v could be
|
* is the value associated with the key, otherwise v could be
|
||||||
* undefined or another copy of the third parameter (counter). */
|
* undefined or another copy of the third parameter (counter). */
|
||||||
filter(callback: (k:K,v:any,counter:number) => boolean, returnThisIfUnchanged?: boolean): ISetF<K>;
|
filter(
|
||||||
|
callback: (k: K, v: any, counter: number) => boolean,
|
||||||
|
returnThisIfUnchanged?: boolean,
|
||||||
|
): ISetF<K>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** An interface for a functional map, in which the map object could be read-only
|
/** An interface for a functional map, in which the map object could be read-only
|
||||||
* but new versions of the map can be created by calling "with" or "without"
|
* but new versions of the map can be created by calling "with" or "without"
|
||||||
* methods to add or remove keys or key-value pairs.
|
* methods to add or remove keys or key-value pairs.
|
||||||
*/
|
*/
|
||||||
export interface IMapF<K=any, V=any> extends IMapSource<K, V>, ISetF<K> {
|
export interface IMapF<K = any, V = any> extends IMapSource<K, V>, ISetF<K> {
|
||||||
/** Returns a copy of the tree with the specified key set (the value is undefined). */
|
/** Returns a copy of the tree with the specified key set (the value is undefined). */
|
||||||
with(key: K): IMapF<K,V|undefined>;
|
with(key: K): IMapF<K, V | undefined>;
|
||||||
/** Returns a copy of the tree with the specified key-value pair set. */
|
/** Returns a copy of the tree with the specified key-value pair set. */
|
||||||
with<V2>(key: K, value: V2, overwrite?: boolean): IMapF<K,V|V2>;
|
with<V2>(key: K, value: V2, overwrite?: boolean): IMapF<K, V | V2>;
|
||||||
/** Returns a copy of the tree with the specified key-value pairs set. */
|
/** Returns a copy of the tree with the specified key-value pairs set. */
|
||||||
withPairs<V2>(pairs: [K,V|V2][], overwrite: boolean): IMapF<K,V|V2>;
|
withPairs<V2>(pairs: [K, V | V2][], overwrite: boolean): IMapF<K, V | V2>;
|
||||||
/** Returns a copy of the tree with all the keys in the specified array present.
|
/** Returns a copy of the tree with all the keys in the specified array present.
|
||||||
* @param keys The keys to add. If a key is already present in the tree,
|
* @param keys The keys to add. If a key is already present in the tree,
|
||||||
* neither the existing key nor the existing value is modified.
|
* neither the existing key nor the existing value is modified.
|
||||||
* @param returnThisIfUnchanged If true, the method returns `this` when
|
* @param returnThisIfUnchanged If true, the method returns `this` when
|
||||||
* all of the keys are already present in the collection. The
|
* all of the keys are already present in the collection. The
|
||||||
* default value may be true or false depending on the concrete
|
* default value may be true or false depending on the concrete
|
||||||
* implementation of the interface (in BTree, the default is false.) */
|
* implementation of the interface (in BTree, the default is false.) */
|
||||||
withKeys(keys: K[], returnThisIfUnchanged?: boolean): IMapF<K,V|undefined>;
|
withKeys(keys: K[], returnThisIfUnchanged?: boolean): IMapF<K, V | undefined>;
|
||||||
/** Returns a copy of the tree with all values altered by a callback function. */
|
/** Returns a copy of the tree with all values altered by a callback function. */
|
||||||
mapValues<R>(callback: (v:V,k:K,counter:number) => R): IMapF<K,R>;
|
mapValues<R>(callback: (v: V, k: K, counter: number) => R): IMapF<K, R>;
|
||||||
/** Performs a reduce operation like the `reduce` method of `Array`.
|
/** Performs a reduce operation like the `reduce` method of `Array`.
|
||||||
* It is used to combine all pairs into a single value, or perform conversions. */
|
* It is used to combine all pairs into a single value, or perform conversions. */
|
||||||
reduce<R>(callback: (previous:R,currentPair:[K,V],counter:number,tree:IMapF<K,V>) => R, initialValue: R): R;
|
reduce<R>(
|
||||||
/** Performs a reduce operation like the `reduce` method of `Array`.
|
callback: (
|
||||||
|
previous: R,
|
||||||
|
currentPair: [K, V],
|
||||||
|
counter: number,
|
||||||
|
tree: IMapF<K, V>,
|
||||||
|
) => R,
|
||||||
|
initialValue: R,
|
||||||
|
): R;
|
||||||
|
/** Performs a reduce operation like the `reduce` method of `Array`.
|
||||||
* It is used to combine all pairs into a single value, or perform conversions. */
|
* It is used to combine all pairs into a single value, or perform conversions. */
|
||||||
reduce<R>(callback: (previous:R|undefined,currentPair:[K,V],counter:number,tree:IMapF<K,V>) => R): R|undefined;
|
reduce<R>(
|
||||||
|
callback: (
|
||||||
|
previous: R | undefined,
|
||||||
|
currentPair: [K, V],
|
||||||
|
counter: number,
|
||||||
|
tree: IMapF<K, V>,
|
||||||
|
) => R,
|
||||||
|
): R | undefined;
|
||||||
|
|
||||||
// Update return types in ISetF
|
// Update return types in ISetF
|
||||||
without(key: K): IMapF<K,V>;
|
without(key: K): IMapF<K, V>;
|
||||||
withoutKeys(keys: K[], returnThisIfUnchanged?: boolean): IMapF<K,V>;
|
withoutKeys(keys: K[], returnThisIfUnchanged?: boolean): IMapF<K, V>;
|
||||||
/** Returns a copy of the tree with pairs removed whenever the callback
|
/** Returns a copy of the tree with pairs removed whenever the callback
|
||||||
* function returns false. */
|
* function returns false. */
|
||||||
filter(callback: (k:K,v:V,counter:number) => boolean, returnThisIfUnchanged?: boolean): IMapF<K,V>;
|
filter(
|
||||||
|
callback: (k: K, v: V, counter: number) => boolean,
|
||||||
|
returnThisIfUnchanged?: boolean,
|
||||||
|
): IMapF<K, V>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** An interface for a functional sorted set: a functional set in which the
|
/** An interface for a functional sorted set: a functional set in which the
|
||||||
* keys (items) are sorted. This is a subinterface of ISortedMapF. */
|
* keys (items) are sorted. This is a subinterface of ISortedMapF. */
|
||||||
export interface ISortedSetF<K=any> extends ISetF<K>, ISortedSetSource<K>
|
export interface ISortedSetF<K = any> extends ISetF<K>, ISortedSetSource<K> {
|
||||||
{
|
|
||||||
// TypeScript requires this method of ISortedSetSource to be repeated
|
// TypeScript requires this method of ISortedSetSource to be repeated
|
||||||
keys(firstKey?: K): IterableIterator<K>;
|
keys(firstKey?: K): IterableIterator<K>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ISortedMapF<K=any,V=any> extends ISortedSetF<K>, IMapF<K,V>, ISortedMapSource<K,V>
|
export interface ISortedMapF<K = any, V = any>
|
||||||
{
|
extends ISortedSetF<K>,
|
||||||
|
IMapF<K, V>,
|
||||||
|
ISortedMapSource<K, V> {
|
||||||
/** Returns a copy of the tree with the specified range of keys removed. */
|
/** Returns a copy of the tree with the specified range of keys removed. */
|
||||||
withoutRange(low: K, high: K, includeHigh: boolean, returnThisIfUnchanged?: boolean): ISortedMapF<K,V>;
|
withoutRange(
|
||||||
|
low: K,
|
||||||
|
high: K,
|
||||||
|
includeHigh: boolean,
|
||||||
|
returnThisIfUnchanged?: boolean,
|
||||||
|
): ISortedMapF<K, V>;
|
||||||
|
|
||||||
// TypeScript requires these methods of ISortedSetF and ISortedMapSource to be repeated
|
// TypeScript requires these methods of ISortedSetF and ISortedMapSource to be repeated
|
||||||
entries(firstKey?: K): IterableIterator<[K,V]>;
|
entries(firstKey?: K): IterableIterator<[K, V]>;
|
||||||
keys(firstKey?: K): IterableIterator<K>;
|
keys(firstKey?: K): IterableIterator<K>;
|
||||||
values(firstKey?: K): IterableIterator<V>;
|
values(firstKey?: K): IterableIterator<V>;
|
||||||
forRange(low: K, high: K, includeHigh: boolean, onFound?: (k:K,v:V,counter:number) => void, initialCounter?: number): number;
|
forRange(
|
||||||
|
low: K,
|
||||||
|
high: K,
|
||||||
|
includeHigh: boolean,
|
||||||
|
onFound?: (k: K, v: V, counter: number) => void,
|
||||||
|
initialCounter?: number,
|
||||||
|
): number;
|
||||||
|
|
||||||
// Update the return value of methods from base interfaces
|
// Update the return value of methods from base interfaces
|
||||||
with(key: K): ISortedMapF<K,V|undefined>;
|
with(key: K): ISortedMapF<K, V | undefined>;
|
||||||
with<V2>(key: K, value: V2, overwrite?: boolean): ISortedMapF<K,V|V2>;
|
with<V2>(key: K, value: V2, overwrite?: boolean): ISortedMapF<K, V | V2>;
|
||||||
withKeys(keys: K[], returnThisIfUnchanged?: boolean): ISortedMapF<K,V|undefined>;
|
withKeys(
|
||||||
withPairs<V2>(pairs: [K,V|V2][], overwrite: boolean): ISortedMapF<K,V|V2>;
|
keys: K[],
|
||||||
mapValues<R>(callback: (v:V,k:K,counter:number) => R): ISortedMapF<K,R>;
|
returnThisIfUnchanged?: boolean,
|
||||||
without(key: K): ISortedMapF<K,V>;
|
): ISortedMapF<K, V | undefined>;
|
||||||
withoutKeys(keys: K[], returnThisIfUnchanged?: boolean): ISortedMapF<K,V>;
|
withPairs<V2>(
|
||||||
filter(callback: (k:K,v:any,counter:number) => boolean, returnThisIfUnchanged?: boolean): ISortedMapF<K,V>;
|
pairs: [K, V | V2][],
|
||||||
|
overwrite: boolean,
|
||||||
|
): ISortedMapF<K, V | V2>;
|
||||||
|
mapValues<R>(callback: (v: V, k: K, counter: number) => R): ISortedMapF<K, R>;
|
||||||
|
without(key: K): ISortedMapF<K, V>;
|
||||||
|
withoutKeys(keys: K[], returnThisIfUnchanged?: boolean): ISortedMapF<K, V>;
|
||||||
|
filter(
|
||||||
|
callback: (k: K, v: any, counter: number) => boolean,
|
||||||
|
returnThisIfUnchanged?: boolean,
|
||||||
|
): ISortedMapF<K, V>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ISortedMapConstructor<K,V> {
|
export interface ISortedMapConstructor<K, V> {
|
||||||
new (entries?: [K,V][], compare?: (a: K, b: K) => number): ISortedMap<K,V>;
|
new (entries?: [K, V][], compare?: (a: K, b: K) => number): ISortedMap<K, V>;
|
||||||
|
}
|
||||||
|
export interface ISortedMapFConstructor<K, V> {
|
||||||
|
new (entries?: [K, V][], compare?: (a: K, b: K) => number): ISortedMapF<K, V>;
|
||||||
}
|
}
|
||||||
export interface ISortedMapFConstructor<K,V> {
|
|
||||||
new (entries?: [K,V][], compare?: (a: K, b: K) => number): ISortedMapF<K,V>;
|
|
||||||
}
|
|
@ -14,67 +14,64 @@
|
|||||||
permissions and limitations under the License.
|
permissions and limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
import FakeEventTarget from "./FakeEventTarget";
|
import FakeEventTarget from "./FakeEventTarget";
|
||||||
import { EventType } from "./types";
|
import { EventType } from "./types";
|
||||||
|
|
||||||
export class Event {
|
export class Event {
|
||||||
public eventPath: FakeEventTarget[] = [];
|
public eventPath: FakeEventTarget[] = [];
|
||||||
public type: EventType;
|
public type: EventType;
|
||||||
|
|
||||||
public readonly NONE = 0;
|
public readonly NONE = 0;
|
||||||
public readonly CAPTURING_PHASE = 1;
|
public readonly CAPTURING_PHASE = 1;
|
||||||
public readonly AT_TARGET = 2;
|
public readonly AT_TARGET = 2;
|
||||||
public readonly BUBBLING_PHASE = 3;
|
public readonly BUBBLING_PHASE = 3;
|
||||||
|
|
||||||
// Flags
|
// Flags
|
||||||
public propagationStopped = false;
|
public propagationStopped = false;
|
||||||
public immediatePropagationStopped = false;
|
public immediatePropagationStopped = false;
|
||||||
public canceled = false;
|
public canceled = false;
|
||||||
public initialized = true;
|
public initialized = true;
|
||||||
public dispatched = false;
|
public dispatched = false;
|
||||||
|
|
||||||
public target: FakeEventTarget | null = null;
|
public target: FakeEventTarget | null = null;
|
||||||
public currentTarget: FakeEventTarget | null = null;
|
public currentTarget: FakeEventTarget | null = null;
|
||||||
|
|
||||||
public eventPhase: 0 | 1 | 2 | 3 = 0;
|
public eventPhase: 0 | 1 | 2 | 3 = 0;
|
||||||
|
|
||||||
public defaultPrevented = false;
|
public defaultPrevented = false;
|
||||||
|
|
||||||
public isTrusted = false;
|
public isTrusted = false;
|
||||||
public timeStamp = Date.now();
|
public timeStamp = Date.now();
|
||||||
|
|
||||||
public bubbles: boolean;
|
public bubbles: boolean;
|
||||||
public cancelable: boolean;
|
public cancelable: boolean;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
type: EventType,
|
type: EventType,
|
||||||
eventInitDict: { bubbles?: boolean; cancelable?: boolean } = {},
|
eventInitDict: { bubbles?: boolean; cancelable?: boolean } = {},
|
||||||
) {
|
) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
|
||||||
this.bubbles =
|
this.bubbles =
|
||||||
eventInitDict.bubbles !== undefined ? eventInitDict.bubbles : false;
|
eventInitDict.bubbles !== undefined ? eventInitDict.bubbles : false;
|
||||||
this.cancelable =
|
this.cancelable =
|
||||||
eventInitDict.cancelable !== undefined
|
eventInitDict.cancelable !== undefined ? eventInitDict.cancelable : false;
|
||||||
? eventInitDict.cancelable
|
}
|
||||||
: false;
|
|
||||||
|
public preventDefault() {
|
||||||
|
if (this.cancelable) {
|
||||||
|
this.canceled = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public preventDefault() {
|
public stopPropagation() {
|
||||||
if (this.cancelable) {
|
this.propagationStopped = true;
|
||||||
this.canceled = true;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public stopPropagation() {
|
public stopImmediatePropagation() {
|
||||||
this.propagationStopped = true;
|
this.propagationStopped = true;
|
||||||
}
|
this.immediatePropagationStopped = true;
|
||||||
|
}
|
||||||
public stopImmediatePropagation() {
|
|
||||||
this.propagationStopped = true;
|
|
||||||
this.immediatePropagationStopped = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Event;
|
export default Event;
|
||||||
|
@ -117,7 +117,7 @@ abstract class FakeEventTarget {
|
|||||||
callback: EventCallback,
|
callback: EventCallback,
|
||||||
capture = false,
|
capture = false,
|
||||||
) {
|
) {
|
||||||
const i = this.listeners.findIndex(listener => {
|
const i = this.listeners.findIndex((listener) => {
|
||||||
return (
|
return (
|
||||||
listener.type === type &&
|
listener.type === type &&
|
||||||
listener.callback === callback &&
|
listener.callback === callback &&
|
||||||
|
@ -18,91 +18,91 @@ import { DataError } from "./errors";
|
|||||||
import valueToKey from "./valueToKey";
|
import valueToKey from "./valueToKey";
|
||||||
|
|
||||||
const getType = (x: any) => {
|
const getType = (x: any) => {
|
||||||
if (typeof x === "number") {
|
if (typeof x === "number") {
|
||||||
return "Number";
|
return "Number";
|
||||||
}
|
}
|
||||||
if (x instanceof Date) {
|
if (x instanceof Date) {
|
||||||
return "Date";
|
return "Date";
|
||||||
}
|
}
|
||||||
if (Array.isArray(x)) {
|
if (Array.isArray(x)) {
|
||||||
return "Array";
|
return "Array";
|
||||||
}
|
}
|
||||||
if (typeof x === "string") {
|
if (typeof x === "string") {
|
||||||
return "String";
|
return "String";
|
||||||
}
|
}
|
||||||
if (x instanceof ArrayBuffer) {
|
if (x instanceof ArrayBuffer) {
|
||||||
return "Binary";
|
return "Binary";
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new DataError();
|
throw new DataError();
|
||||||
};
|
};
|
||||||
|
|
||||||
// https://w3c.github.io/IndexedDB/#compare-two-keys
|
// https://w3c.github.io/IndexedDB/#compare-two-keys
|
||||||
const compareKeys = (first: any, second: any): -1 | 0 | 1 => {
|
const compareKeys = (first: any, second: any): -1 | 0 | 1 => {
|
||||||
if (second === undefined) {
|
if (second === undefined) {
|
||||||
throw new TypeError();
|
throw new TypeError();
|
||||||
|
}
|
||||||
|
|
||||||
|
first = valueToKey(first);
|
||||||
|
second = valueToKey(second);
|
||||||
|
|
||||||
|
const t1 = getType(first);
|
||||||
|
const t2 = getType(second);
|
||||||
|
|
||||||
|
if (t1 !== t2) {
|
||||||
|
if (t1 === "Array") {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
t1 === "Binary" &&
|
||||||
|
(t2 === "String" || t2 === "Date" || t2 === "Number")
|
||||||
|
) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (t1 === "String" && (t2 === "Date" || t2 === "Number")) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (t1 === "Date" && t2 === "Number") {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t1 === "Binary") {
|
||||||
|
first = new Uint8Array(first);
|
||||||
|
second = new Uint8Array(second);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t1 === "Array" || t1 === "Binary") {
|
||||||
|
const length = Math.min(first.length, second.length);
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
const result = compareKeys(first[i], second[i]);
|
||||||
|
|
||||||
|
if (result !== 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
first = valueToKey(first);
|
if (first.length > second.length) {
|
||||||
second = valueToKey(second);
|
return 1;
|
||||||
|
|
||||||
const t1 = getType(first);
|
|
||||||
const t2 = getType(second);
|
|
||||||
|
|
||||||
if (t1 !== t2) {
|
|
||||||
if (t1 === "Array") {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
t1 === "Binary" &&
|
|
||||||
(t2 === "String" || t2 === "Date" || t2 === "Number")
|
|
||||||
) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (t1 === "String" && (t2 === "Date" || t2 === "Number")) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (t1 === "Date" && t2 === "Number") {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
if (first.length < second.length) {
|
||||||
if (t1 === "Binary") {
|
return -1;
|
||||||
first = new Uint8Array(first);
|
|
||||||
second = new Uint8Array(second);
|
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (t1 === "Array" || t1 === "Binary") {
|
if (t1 === "Date") {
|
||||||
const length = Math.min(first.length, second.length);
|
if (first.getTime() === second.getTime()) {
|
||||||
for (let i = 0; i < length; i++) {
|
return 0;
|
||||||
const result = compareKeys(first[i], second[i]);
|
|
||||||
|
|
||||||
if (result !== 0) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (first.length > second.length) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (first.length < second.length) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
if (t1 === "Date") {
|
if (first === second) {
|
||||||
if (first.getTime() === second.getTime()) {
|
return 0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (first === second) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return first > second ? 1 : -1;
|
return first > second ? 1 : -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default compareKeys;
|
export default compareKeys;
|
||||||
|
@ -18,18 +18,18 @@
|
|||||||
// https://heycam.github.io/webidl/#EnforceRange
|
// https://heycam.github.io/webidl/#EnforceRange
|
||||||
|
|
||||||
const enforceRange = (
|
const enforceRange = (
|
||||||
num: number,
|
num: number,
|
||||||
type: "MAX_SAFE_INTEGER" | "unsigned long",
|
type: "MAX_SAFE_INTEGER" | "unsigned long",
|
||||||
) => {
|
) => {
|
||||||
const min = 0;
|
const min = 0;
|
||||||
const max = type === "unsigned long" ? 4294967295 : 9007199254740991;
|
const max = type === "unsigned long" ? 4294967295 : 9007199254740991;
|
||||||
|
|
||||||
if (isNaN(num) || num < min || num > max) {
|
if (isNaN(num) || num < min || num > max) {
|
||||||
throw new TypeError();
|
throw new TypeError();
|
||||||
}
|
}
|
||||||
if (num >= 0) {
|
if (num >= 0) {
|
||||||
return Math.floor(num);
|
return Math.floor(num);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default enforceRange;
|
export default enforceRange;
|
||||||
|
@ -14,117 +14,116 @@
|
|||||||
permissions and limitations under the License.
|
permissions and limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/* tslint:disable: max-classes-per-file max-line-length */
|
/* tslint:disable: max-classes-per-file max-line-length */
|
||||||
|
|
||||||
const messages = {
|
const messages = {
|
||||||
AbortError:
|
AbortError:
|
||||||
"A request was aborted, for example through a call to IDBTransaction.abort.",
|
"A request was aborted, for example through a call to IDBTransaction.abort.",
|
||||||
ConstraintError:
|
ConstraintError:
|
||||||
"A mutation operation in the transaction failed because a constraint was not satisfied. For example, an object such as an object store or index already exists and a request attempted to create a new one.",
|
"A mutation operation in the transaction failed because a constraint was not satisfied. For example, an object such as an object store or index already exists and a request attempted to create a new one.",
|
||||||
DataCloneError:
|
DataCloneError:
|
||||||
"The data being stored could not be cloned by the internal structured cloning algorithm.",
|
"The data being stored could not be cloned by the internal structured cloning algorithm.",
|
||||||
DataError: "Data provided to an operation does not meet requirements.",
|
DataError: "Data provided to an operation does not meet requirements.",
|
||||||
InvalidAccessError:
|
InvalidAccessError:
|
||||||
"An invalid operation was performed on an object. For example transaction creation attempt was made, but an empty scope was provided.",
|
"An invalid operation was performed on an object. For example transaction creation attempt was made, but an empty scope was provided.",
|
||||||
InvalidStateError:
|
InvalidStateError:
|
||||||
"An operation was called on an object on which it is not allowed or at a time when it is not allowed. Also occurs if a request is made on a source object that has been deleted or removed. Use TransactionInactiveError or ReadOnlyError when possible, as they are more specific variations of InvalidStateError.",
|
"An operation was called on an object on which it is not allowed or at a time when it is not allowed. Also occurs if a request is made on a source object that has been deleted or removed. Use TransactionInactiveError or ReadOnlyError when possible, as they are more specific variations of InvalidStateError.",
|
||||||
NotFoundError:
|
NotFoundError:
|
||||||
"The operation failed because the requested database object could not be found. For example, an object store did not exist but was being opened.",
|
"The operation failed because the requested database object could not be found. For example, an object store did not exist but was being opened.",
|
||||||
ReadOnlyError:
|
ReadOnlyError:
|
||||||
'The mutating operation was attempted in a "readonly" transaction.',
|
'The mutating operation was attempted in a "readonly" transaction.',
|
||||||
TransactionInactiveError:
|
TransactionInactiveError:
|
||||||
"A request was placed against a transaction which is currently not active, or which is finished.",
|
"A request was placed against a transaction which is currently not active, or which is finished.",
|
||||||
VersionError:
|
VersionError:
|
||||||
"An attempt was made to open a database using a lower version than the existing version.",
|
"An attempt was made to open a database using a lower version than the existing version.",
|
||||||
};
|
};
|
||||||
|
|
||||||
export class AbortError extends Error {
|
export class AbortError extends Error {
|
||||||
constructor(message = messages.AbortError) {
|
constructor(message = messages.AbortError) {
|
||||||
super();
|
super();
|
||||||
Object.setPrototypeOf(this, ConstraintError.prototype);
|
Object.setPrototypeOf(this, ConstraintError.prototype);
|
||||||
this.name = "AbortError";
|
this.name = "AbortError";
|
||||||
this.message = message;
|
this.message = message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ConstraintError extends Error {
|
export class ConstraintError extends Error {
|
||||||
constructor(message = messages.ConstraintError) {
|
constructor(message = messages.ConstraintError) {
|
||||||
super();
|
super();
|
||||||
Object.setPrototypeOf(this, ConstraintError.prototype);
|
Object.setPrototypeOf(this, ConstraintError.prototype);
|
||||||
this.name = "ConstraintError";
|
this.name = "ConstraintError";
|
||||||
this.message = message;
|
this.message = message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DataCloneError extends Error {
|
export class DataCloneError extends Error {
|
||||||
constructor(message = messages.DataCloneError) {
|
constructor(message = messages.DataCloneError) {
|
||||||
super();
|
super();
|
||||||
Object.setPrototypeOf(this, DataCloneError.prototype);
|
Object.setPrototypeOf(this, DataCloneError.prototype);
|
||||||
this.name = "DataCloneError";
|
this.name = "DataCloneError";
|
||||||
this.message = message;
|
this.message = message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DataError extends Error {
|
export class DataError extends Error {
|
||||||
constructor(message = messages.DataError) {
|
constructor(message = messages.DataError) {
|
||||||
super();
|
super();
|
||||||
Object.setPrototypeOf(this, DataError.prototype);
|
Object.setPrototypeOf(this, DataError.prototype);
|
||||||
this.name = "DataError";
|
this.name = "DataError";
|
||||||
this.message = message;
|
this.message = message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class InvalidAccessError extends Error {
|
export class InvalidAccessError extends Error {
|
||||||
constructor(message = messages.InvalidAccessError) {
|
constructor(message = messages.InvalidAccessError) {
|
||||||
super();
|
super();
|
||||||
Object.setPrototypeOf(this, InvalidAccessError.prototype);
|
Object.setPrototypeOf(this, InvalidAccessError.prototype);
|
||||||
this.name = "InvalidAccessError";
|
this.name = "InvalidAccessError";
|
||||||
this.message = message;
|
this.message = message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class InvalidStateError extends Error {
|
export class InvalidStateError extends Error {
|
||||||
constructor(message = messages.InvalidStateError) {
|
constructor(message = messages.InvalidStateError) {
|
||||||
super();
|
super();
|
||||||
Object.setPrototypeOf(this, InvalidStateError.prototype);
|
Object.setPrototypeOf(this, InvalidStateError.prototype);
|
||||||
this.name = "InvalidStateError";
|
this.name = "InvalidStateError";
|
||||||
this.message = message;
|
this.message = message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class NotFoundError extends Error {
|
export class NotFoundError extends Error {
|
||||||
constructor(message = messages.NotFoundError) {
|
constructor(message = messages.NotFoundError) {
|
||||||
super();
|
super();
|
||||||
Object.setPrototypeOf(this, NotFoundError.prototype);
|
Object.setPrototypeOf(this, NotFoundError.prototype);
|
||||||
this.name = "NotFoundError";
|
this.name = "NotFoundError";
|
||||||
this.message = message;
|
this.message = message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ReadOnlyError extends Error {
|
export class ReadOnlyError extends Error {
|
||||||
constructor(message = messages.ReadOnlyError) {
|
constructor(message = messages.ReadOnlyError) {
|
||||||
super();
|
super();
|
||||||
Object.setPrototypeOf(this, ReadOnlyError.prototype);
|
Object.setPrototypeOf(this, ReadOnlyError.prototype);
|
||||||
this.name = "ReadOnlyError";
|
this.name = "ReadOnlyError";
|
||||||
this.message = message;
|
this.message = message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TransactionInactiveError extends Error {
|
export class TransactionInactiveError extends Error {
|
||||||
constructor(message = messages.TransactionInactiveError) {
|
constructor(message = messages.TransactionInactiveError) {
|
||||||
super();
|
super();
|
||||||
Object.setPrototypeOf(this, TransactionInactiveError.prototype);
|
Object.setPrototypeOf(this, TransactionInactiveError.prototype);
|
||||||
this.name = "TransactionInactiveError";
|
this.name = "TransactionInactiveError";
|
||||||
this.message = message;
|
this.message = message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class VersionError extends Error {
|
export class VersionError extends Error {
|
||||||
constructor(message = messages.VersionError) {
|
constructor(message = messages.VersionError) {
|
||||||
super();
|
super();
|
||||||
Object.setPrototypeOf(this, VersionError.prototype);
|
Object.setPrototypeOf(this, VersionError.prototype);
|
||||||
this.name = "VersionError";
|
this.name = "VersionError";
|
||||||
this.message = message;
|
this.message = message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,23 +19,31 @@ import test from "ava";
|
|||||||
import { getIndexKeys } from "./getIndexKeys";
|
import { getIndexKeys } from "./getIndexKeys";
|
||||||
|
|
||||||
test("basics", (t) => {
|
test("basics", (t) => {
|
||||||
t.deepEqual(getIndexKeys({foo: 42}, "foo", false), [42]);
|
t.deepEqual(getIndexKeys({ foo: 42 }, "foo", false), [42]);
|
||||||
t.deepEqual(getIndexKeys({foo: {bar: 42}}, "foo.bar", false), [42]);
|
t.deepEqual(getIndexKeys({ foo: { bar: 42 } }, "foo.bar", false), [42]);
|
||||||
t.deepEqual(getIndexKeys({foo: [42, 43]}, "foo.0", false), [42]);
|
t.deepEqual(getIndexKeys({ foo: [42, 43] }, "foo.0", false), [42]);
|
||||||
t.deepEqual(getIndexKeys({foo: [42, 43]}, "foo.1", false), [43]);
|
t.deepEqual(getIndexKeys({ foo: [42, 43] }, "foo.1", false), [43]);
|
||||||
|
|
||||||
t.deepEqual(getIndexKeys([1, 2, 3], "", false), [[1, 2, 3]]);
|
t.deepEqual(getIndexKeys([1, 2, 3], "", false), [[1, 2, 3]]);
|
||||||
|
|
||||||
t.throws(() => {
|
t.throws(() => {
|
||||||
getIndexKeys({foo: 42}, "foo.bar", false);
|
getIndexKeys({ foo: 42 }, "foo.bar", false);
|
||||||
});
|
});
|
||||||
|
|
||||||
t.deepEqual(getIndexKeys({foo: 42}, "foo", true), [42]);
|
t.deepEqual(getIndexKeys({ foo: 42 }, "foo", true), [42]);
|
||||||
t.deepEqual(getIndexKeys({foo: 42, bar: 10}, ["foo", "bar"], true), [42, 10]);
|
t.deepEqual(getIndexKeys({ foo: 42, bar: 10 }, ["foo", "bar"], true), [
|
||||||
t.deepEqual(getIndexKeys({foo: 42, bar: 10}, ["foo", "bar"], false), [[42, 10]]);
|
42,
|
||||||
t.deepEqual(getIndexKeys({foo: 42, bar: 10}, ["foo", "bar", "spam"], true), [42, 10]);
|
10,
|
||||||
|
]);
|
||||||
|
t.deepEqual(getIndexKeys({ foo: 42, bar: 10 }, ["foo", "bar"], false), [
|
||||||
|
[42, 10],
|
||||||
|
]);
|
||||||
|
t.deepEqual(
|
||||||
|
getIndexKeys({ foo: 42, bar: 10 }, ["foo", "bar", "spam"], true),
|
||||||
|
[42, 10],
|
||||||
|
);
|
||||||
|
|
||||||
t.throws(() => {
|
t.throws(() => {
|
||||||
getIndexKeys({foo: 42, bar: 10}, ["foo", "bar", "spam"], false);
|
getIndexKeys({ foo: 42, bar: 10 }, ["foo", "bar", "spam"], false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -62,4 +62,4 @@ export function injectKey(keyPath: KeyPath, value: Value, key: Key): Value {
|
|||||||
return newValue;
|
return newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default injectKey;
|
export default injectKey;
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
permissions and limitations under the License.
|
permissions and limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import test from 'ava';
|
import test from "ava";
|
||||||
import { makeStoreKeyValue } from "./makeStoreKeyValue";
|
import { makeStoreKeyValue } from "./makeStoreKeyValue";
|
||||||
|
|
||||||
test("basics", (t) => {
|
test("basics", (t) => {
|
||||||
@ -26,19 +26,37 @@ test("basics", (t) => {
|
|||||||
t.is(result.value.name, "Florian");
|
t.is(result.value.name, "Florian");
|
||||||
t.is(result.value.id, 42);
|
t.is(result.value.id, 42);
|
||||||
|
|
||||||
result = makeStoreKeyValue({ name: "Florian", id: 10 }, undefined, 5, true, "id");
|
result = makeStoreKeyValue(
|
||||||
|
{ name: "Florian", id: 10 },
|
||||||
|
undefined,
|
||||||
|
5,
|
||||||
|
true,
|
||||||
|
"id",
|
||||||
|
);
|
||||||
t.is(result.updatedKeyGenerator, 11);
|
t.is(result.updatedKeyGenerator, 11);
|
||||||
t.is(result.key, 10);
|
t.is(result.key, 10);
|
||||||
t.is(result.value.name, "Florian");
|
t.is(result.value.name, "Florian");
|
||||||
t.is(result.value.id, 10);
|
t.is(result.value.id, 10);
|
||||||
|
|
||||||
result = makeStoreKeyValue({ name: "Florian", id: 5 }, undefined, 10, true, "id");
|
result = makeStoreKeyValue(
|
||||||
|
{ name: "Florian", id: 5 },
|
||||||
|
undefined,
|
||||||
|
10,
|
||||||
|
true,
|
||||||
|
"id",
|
||||||
|
);
|
||||||
t.is(result.updatedKeyGenerator, 10);
|
t.is(result.updatedKeyGenerator, 10);
|
||||||
t.is(result.key, 5);
|
t.is(result.key, 5);
|
||||||
t.is(result.value.name, "Florian");
|
t.is(result.value.name, "Florian");
|
||||||
t.is(result.value.id, 5);
|
t.is(result.value.id, 5);
|
||||||
|
|
||||||
result = makeStoreKeyValue({ name: "Florian", id: "foo" }, undefined, 10, true, "id");
|
result = makeStoreKeyValue(
|
||||||
|
{ name: "Florian", id: "foo" },
|
||||||
|
undefined,
|
||||||
|
10,
|
||||||
|
true,
|
||||||
|
"id",
|
||||||
|
);
|
||||||
t.is(result.updatedKeyGenerator, 10);
|
t.is(result.updatedKeyGenerator, 10);
|
||||||
t.is(result.key, "foo");
|
t.is(result.key, "foo");
|
||||||
t.is(result.value.name, "Florian");
|
t.is(result.value.name, "Florian");
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
permissions and limitations under the License.
|
permissions and limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
import { Value, Key, KeyPath } from "./types";
|
import { Value, Key, KeyPath } from "./types";
|
||||||
import extractKey from "./extractKey";
|
import extractKey from "./extractKey";
|
||||||
import { DataError } from "./errors";
|
import { DataError } from "./errors";
|
||||||
@ -93,7 +92,7 @@ export function makeStoreKeyValue(
|
|||||||
key: key,
|
key: key,
|
||||||
value: value,
|
value: value,
|
||||||
updatedKeyGenerator,
|
updatedKeyGenerator,
|
||||||
}
|
};
|
||||||
} else {
|
} else {
|
||||||
// (no, yes, no)
|
// (no, yes, no)
|
||||||
key = extractKey(keyPath!, value);
|
key = extractKey(keyPath!, value);
|
||||||
@ -111,7 +110,7 @@ export function makeStoreKeyValue(
|
|||||||
key: currentKeyGenerator,
|
key: currentKeyGenerator,
|
||||||
value: value,
|
value: value,
|
||||||
updatedKeyGenerator: currentKeyGenerator + 1,
|
updatedKeyGenerator: currentKeyGenerator + 1,
|
||||||
}
|
};
|
||||||
} else {
|
} else {
|
||||||
// (no, no, no)
|
// (no, no, no)
|
||||||
throw new DataError();
|
throw new DataError();
|
||||||
|
@ -14,8 +14,8 @@
|
|||||||
permissions and limitations under the License.
|
permissions and limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export function queueTask(fn: () => void) {
|
export function queueTask(fn: () => void) {
|
||||||
setImmediate(fn);
|
setImmediate(fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default queueTask;
|
export default queueTask;
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
permissions and limitations under the License.
|
permissions and limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
function structuredCloneImpl(val: any, visited: WeakMap<any, boolean>): any {
|
function structuredCloneImpl(val: any, visited: WeakMap<any, boolean>): any {
|
||||||
// FIXME: replace with real implementation!
|
// FIXME: replace with real implementation!
|
||||||
return JSON.parse(JSON.stringify(val));
|
return JSON.parse(JSON.stringify(val));
|
||||||
@ -28,4 +27,4 @@ export function structuredClone(val: any): any {
|
|||||||
return structuredCloneImpl(val, visited);
|
return structuredCloneImpl(val, visited);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default structuredClone;
|
export default structuredClone;
|
||||||
|
@ -15,11 +15,11 @@
|
|||||||
permissions and limitations under the License.
|
permissions and limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import BridgeIDBRequest from "../BridgeIDBRequest";
|
import { BridgeIDBRequest } from "../BridgeIDBRequest";
|
||||||
import BridgeIDBKeyRange from "../BridgeIDBKeyRange";
|
import { BridgeIDBKeyRange } from "../BridgeIDBKeyRange";
|
||||||
import BridgeIDBIndex from "../BridgeIDBIndex";
|
import { BridgeIDBIndex } from "../BridgeIDBIndex";
|
||||||
import BridgeIBObjectStore from "../BridgeIDBObjectStore";
|
|
||||||
import { Event } from "../util/FakeEvent";
|
import { Event } from "../util/FakeEvent";
|
||||||
|
import { BridgeIDBObjectStore } from "../BridgeIDBObjectStore";
|
||||||
|
|
||||||
interface EventInCallback extends Event {
|
interface EventInCallback extends Event {
|
||||||
target: any;
|
target: any;
|
||||||
@ -37,15 +37,18 @@ export type EventType =
|
|||||||
| "upgradeneeded"
|
| "upgradeneeded"
|
||||||
| "versionchange";
|
| "versionchange";
|
||||||
|
|
||||||
export type CursorSource = BridgeIDBIndex | BridgeIBObjectStore;
|
export type CursorSource = BridgeIDBIndex | BridgeIDBObjectStore;
|
||||||
|
|
||||||
|
|
||||||
export interface FakeDOMStringList extends Array<string> {
|
export interface FakeDOMStringList extends Array<string> {
|
||||||
contains: (value: string) => boolean;
|
contains: (value: string) => boolean;
|
||||||
item: (i: number) => string | undefined;
|
item: (i: number) => string | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type BridgeIDBCursorDirection = "next" | "nextunique" | "prev" | "prevunique";
|
export type BridgeIDBCursorDirection =
|
||||||
|
| "next"
|
||||||
|
| "nextunique"
|
||||||
|
| "prev"
|
||||||
|
| "prevunique";
|
||||||
|
|
||||||
export type KeyPath = string | string[];
|
export type KeyPath = string | string[];
|
||||||
|
|
||||||
@ -64,8 +67,8 @@ export type TransactionMode = "readonly" | "readwrite" | "versionchange";
|
|||||||
|
|
||||||
export interface BridgeIDBDatabaseInfo {
|
export interface BridgeIDBDatabaseInfo {
|
||||||
name: string;
|
name: string;
|
||||||
version: number
|
version: number;
|
||||||
};
|
}
|
||||||
|
|
||||||
export interface RequestObj {
|
export interface RequestObj {
|
||||||
operation: () => Promise<any>;
|
operation: () => Promise<any>;
|
||||||
|
File diff suppressed because one or more lines are too long
@ -62,7 +62,6 @@ function valueToKey(input: any, seen?: Set<object>): Key | Key[] {
|
|||||||
}
|
}
|
||||||
return keys;
|
return keys;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
throw new DataError();
|
throw new DataError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,21 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
"lib": ["es6"],
|
"lib": ["es6"],
|
||||||
"module": "commonjs",
|
"module": "ESNext",
|
||||||
"target": "es5",
|
"moduleResolution": "node",
|
||||||
|
"target": "ES6",
|
||||||
"noImplicitAny": true,
|
"noImplicitAny": true,
|
||||||
"outDir": "build",
|
"outDir": "lib",
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
"noEmitOnError": true,
|
"noEmitOnError": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"incremental": true,
|
"incremental": true,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"types": []
|
"rootDir": "./src",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"importHelpers": true,
|
||||||
|
"typeRoots": ["./node_modules/@types"]
|
||||||
},
|
},
|
||||||
"include": ["src/**/*"]
|
"include": ["src/**/*"]
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -5,7 +5,7 @@
|
|||||||
"author": "Florian Dold",
|
"author": "Florian Dold",
|
||||||
"license": "GPL-2.0+",
|
"license": "GPL-2.0+",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc"
|
"compile": "tsc"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"typescript": "^3.3.4000"
|
"typescript": "^3.3.4000"
|
||||||
|
@ -4,7 +4,8 @@
|
|||||||
"target": "es5",
|
"target": "es5",
|
||||||
"noImplicitAny": false,
|
"noImplicitAny": false,
|
||||||
"sourceMap": false,
|
"sourceMap": false,
|
||||||
"outDir": "bin"
|
"outDir": "bin",
|
||||||
|
"incremental": true,
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"pogen.ts"
|
"pogen.ts"
|
||||||
|
44
packages/taler-wallet-android/package.json
Normal file
44
packages/taler-wallet-android/package.json
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"name": "taler-wallet-android",
|
||||||
|
"version": "0.6.12",
|
||||||
|
"description": "",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.12.0"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git://git.taler.net/wallet-core.git"
|
||||||
|
},
|
||||||
|
"main": "dist/taler-wallet-android.js",
|
||||||
|
"author": "Florian Dold",
|
||||||
|
"license": "GPL-3.0",
|
||||||
|
"scripts": {
|
||||||
|
"compile": "rollup -c && tsc",
|
||||||
|
"pretty": "prettier --config ../../.prettierrc --write src",
|
||||||
|
"test": "tsc && ava",
|
||||||
|
"coverage": "tsc && nyc ava",
|
||||||
|
"clean": "rimraf lib dist"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"AUTHORS",
|
||||||
|
"README",
|
||||||
|
"COPYING",
|
||||||
|
"bin/",
|
||||||
|
"dist/node",
|
||||||
|
"src/"
|
||||||
|
],
|
||||||
|
"devDependencies": {
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"@rollup/plugin-commonjs": "^14.0.0",
|
||||||
|
"@rollup/plugin-json": "^4.1.0",
|
||||||
|
"@rollup/plugin-node-resolve": "^8.4.0",
|
||||||
|
"@rollup/plugin-replace": "^2.3.3",
|
||||||
|
"rollup": "^2.23.0",
|
||||||
|
"rollup-plugin-sourcemaps": "^0.6.2",
|
||||||
|
"rollup-plugin-terser": "^6.1.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"taler-wallet-core": "workspace:*",
|
||||||
|
"tslib": "^2.0.0"
|
||||||
|
}
|
||||||
|
}
|
30
packages/taler-wallet-android/rollup.config.js
Normal file
30
packages/taler-wallet-android/rollup.config.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
// rollup.config.js
|
||||||
|
import commonjs from "@rollup/plugin-commonjs";
|
||||||
|
import nodeResolve from "@rollup/plugin-node-resolve";
|
||||||
|
import json from "@rollup/plugin-json";
|
||||||
|
import builtins from "builtin-modules";
|
||||||
|
import pkg from "./package.json";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
input: "lib/index.js",
|
||||||
|
output: {
|
||||||
|
file: pkg.main,
|
||||||
|
format: "cjs",
|
||||||
|
},
|
||||||
|
external: builtins,
|
||||||
|
plugins: [
|
||||||
|
nodeResolve({
|
||||||
|
preferBuiltins: true,
|
||||||
|
}),
|
||||||
|
|
||||||
|
commonjs({
|
||||||
|
include: [/node_modules/, /dist/],
|
||||||
|
extensions: [".js", ".ts"],
|
||||||
|
ignoreGlobal: false,
|
||||||
|
sourceMap: false,
|
||||||
|
}),
|
||||||
|
|
||||||
|
json(),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
26
packages/taler-wallet-android/src/index.d.ts
vendored
Normal file
26
packages/taler-wallet-android/src/index.d.ts
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import {
|
||||||
|
HttpRequestLibrary,
|
||||||
|
HttpResponse,
|
||||||
|
HttpRequestOptions,
|
||||||
|
} from "../../taler-wallet-core/src/util/http";
|
||||||
|
export {
|
||||||
|
handleWorkerError,
|
||||||
|
handleWorkerMessage,
|
||||||
|
} from "../../taler-wallet-core/src/crypto/workers/nodeThreadWorker";
|
||||||
|
export declare class AndroidHttpLib implements HttpRequestLibrary {
|
||||||
|
private sendMessage;
|
||||||
|
useNfcTunnel: boolean;
|
||||||
|
private nodeHttpLib;
|
||||||
|
private requestId;
|
||||||
|
private requestMap;
|
||||||
|
constructor(sendMessage: (m: string) => void);
|
||||||
|
get(url: string, opt?: HttpRequestOptions): Promise<HttpResponse>;
|
||||||
|
postJson(
|
||||||
|
url: string,
|
||||||
|
body: any,
|
||||||
|
opt?: HttpRequestOptions,
|
||||||
|
): Promise<import("../../taler-wallet-core/src/util/http").HttpResponse>;
|
||||||
|
handleTunnelResponse(msg: any): void;
|
||||||
|
}
|
||||||
|
export declare function installAndroidWalletListener(): void;
|
||||||
|
//# sourceMappingURL=index.d.ts.map
|
284
packages/taler-wallet-android/src/index.js
Normal file
284
packages/taler-wallet-android/src/index.js
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
"use strict";
|
||||||
|
/*
|
||||||
|
This file is part of GNU Taler
|
||||||
|
(C) 2019 GNUnet e.V.
|
||||||
|
|
||||||
|
GNU Taler is free software; you can redistribute it and/or modify it under the
|
||||||
|
terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation; either version 3, or (at your option) any later version.
|
||||||
|
|
||||||
|
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with
|
||||||
|
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.installAndroidWalletListener = exports.AndroidHttpLib = void 0;
|
||||||
|
const tslib_1 = require("tslib");
|
||||||
|
/**
|
||||||
|
* Imports.
|
||||||
|
*/
|
||||||
|
const taler_wallet_core_1 = require("taler-wallet-core");
|
||||||
|
const promiseUtils_1 = require("../../taler-wallet-core/src/util/promiseUtils");
|
||||||
|
const fs_1 = tslib_1.__importDefault(require("fs"));
|
||||||
|
const http_1 = require("../../taler-wallet-core/src/util/http");
|
||||||
|
const NodeHttpLib_1 = require("../../taler-wallet-core/src/headless/NodeHttpLib");
|
||||||
|
const walletCoreApiHandler_1 = require("../../taler-wallet-core/src/walletCoreApiHandler");
|
||||||
|
const errors_1 = require("../../taler-wallet-core/src/operations/errors");
|
||||||
|
const TalerErrorCode_1 = require("../../taler-wallet-core/src/TalerErrorCode");
|
||||||
|
// @ts-ignore: special built-in module
|
||||||
|
//import akono = require("akono");
|
||||||
|
var nodeThreadWorker_1 = require("../../taler-wallet-core/src/crypto/workers/nodeThreadWorker");
|
||||||
|
Object.defineProperty(exports, "handleWorkerError", {
|
||||||
|
enumerable: true,
|
||||||
|
get: function () {
|
||||||
|
return nodeThreadWorker_1.handleWorkerError;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
Object.defineProperty(exports, "handleWorkerMessage", {
|
||||||
|
enumerable: true,
|
||||||
|
get: function () {
|
||||||
|
return nodeThreadWorker_1.handleWorkerMessage;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
class AndroidHttpLib {
|
||||||
|
constructor(sendMessage) {
|
||||||
|
this.sendMessage = sendMessage;
|
||||||
|
this.useNfcTunnel = false;
|
||||||
|
this.nodeHttpLib = new NodeHttpLib_1.NodeHttpLib();
|
||||||
|
this.requestId = 1;
|
||||||
|
this.requestMap = {};
|
||||||
|
}
|
||||||
|
get(url, opt) {
|
||||||
|
if (this.useNfcTunnel) {
|
||||||
|
const myId = this.requestId++;
|
||||||
|
const p = promiseUtils_1.openPromise();
|
||||||
|
this.requestMap[myId] = p;
|
||||||
|
const request = {
|
||||||
|
method: "get",
|
||||||
|
url,
|
||||||
|
};
|
||||||
|
this.sendMessage(
|
||||||
|
JSON.stringify({
|
||||||
|
type: "tunnelHttp",
|
||||||
|
request,
|
||||||
|
id: myId,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
return p.promise;
|
||||||
|
} else {
|
||||||
|
return this.nodeHttpLib.get(url, opt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
postJson(url, body, opt) {
|
||||||
|
if (this.useNfcTunnel) {
|
||||||
|
const myId = this.requestId++;
|
||||||
|
const p = promiseUtils_1.openPromise();
|
||||||
|
this.requestMap[myId] = p;
|
||||||
|
const request = {
|
||||||
|
method: "postJson",
|
||||||
|
url,
|
||||||
|
body,
|
||||||
|
};
|
||||||
|
this.sendMessage(
|
||||||
|
JSON.stringify({ type: "tunnelHttp", request, id: myId }),
|
||||||
|
);
|
||||||
|
return p.promise;
|
||||||
|
} else {
|
||||||
|
return this.nodeHttpLib.postJson(url, body, opt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handleTunnelResponse(msg) {
|
||||||
|
const myId = msg.id;
|
||||||
|
const p = this.requestMap[myId];
|
||||||
|
if (!p) {
|
||||||
|
console.error(
|
||||||
|
`no matching request for tunneled HTTP response, id=${myId}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const headers = new http_1.Headers();
|
||||||
|
if (msg.status != 0) {
|
||||||
|
const resp = {
|
||||||
|
// FIXME: pass through this URL
|
||||||
|
requestUrl: "",
|
||||||
|
headers,
|
||||||
|
status: msg.status,
|
||||||
|
json: () =>
|
||||||
|
tslib_1.__awaiter(this, void 0, void 0, function* () {
|
||||||
|
return JSON.parse(msg.responseText);
|
||||||
|
}),
|
||||||
|
text: () =>
|
||||||
|
tslib_1.__awaiter(this, void 0, void 0, function* () {
|
||||||
|
return msg.responseText;
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
p.resolve(resp);
|
||||||
|
} else {
|
||||||
|
p.reject(new Error(`unexpected HTTP status code ${msg.status}`));
|
||||||
|
}
|
||||||
|
delete this.requestMap[myId];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.AndroidHttpLib = AndroidHttpLib;
|
||||||
|
function sendAkonoMessage(ev) {
|
||||||
|
// @ts-ignore
|
||||||
|
const sendMessage = globalThis.__akono_sendMessage;
|
||||||
|
if (typeof sendMessage !== "function") {
|
||||||
|
const errMsg =
|
||||||
|
"FATAL: cannot install android wallet listener: akono functions missing";
|
||||||
|
console.error(errMsg);
|
||||||
|
throw new Error(errMsg);
|
||||||
|
}
|
||||||
|
const m = JSON.stringify(ev);
|
||||||
|
// @ts-ignore
|
||||||
|
sendMessage(m);
|
||||||
|
}
|
||||||
|
class AndroidWalletMessageHandler {
|
||||||
|
constructor() {
|
||||||
|
this.wp = promiseUtils_1.openPromise();
|
||||||
|
this.httpLib = new NodeHttpLib_1.NodeHttpLib();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Handle a request from the Android wallet.
|
||||||
|
*/
|
||||||
|
handleMessage(operation, id, args) {
|
||||||
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
||||||
|
const wrapResponse = (result) => {
|
||||||
|
return {
|
||||||
|
type: "response",
|
||||||
|
id,
|
||||||
|
operation,
|
||||||
|
result,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
switch (operation) {
|
||||||
|
case "init": {
|
||||||
|
this.walletArgs = {
|
||||||
|
notifyHandler: (notification) =>
|
||||||
|
tslib_1.__awaiter(this, void 0, void 0, function* () {
|
||||||
|
sendAkonoMessage({
|
||||||
|
type: "notification",
|
||||||
|
payload: notification,
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
persistentStoragePath: args.persistentStoragePath,
|
||||||
|
httpLib: this.httpLib,
|
||||||
|
};
|
||||||
|
const w = yield taler_wallet_core_1.getDefaultNodeWallet(
|
||||||
|
this.walletArgs,
|
||||||
|
);
|
||||||
|
this.maybeWallet = w;
|
||||||
|
w.runRetryLoop().catch((e) => {
|
||||||
|
console.error("Error during wallet retry loop", e);
|
||||||
|
});
|
||||||
|
this.wp.resolve(w);
|
||||||
|
return wrapResponse({
|
||||||
|
supported_protocol_versions: {
|
||||||
|
exchange:
|
||||||
|
taler_wallet_core_1.versions.WALLET_EXCHANGE_PROTOCOL_VERSION,
|
||||||
|
merchant:
|
||||||
|
taler_wallet_core_1.versions.WALLET_MERCHANT_PROTOCOL_VERSION,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
case "getHistory": {
|
||||||
|
return wrapResponse({ history: [] });
|
||||||
|
}
|
||||||
|
case "startTunnel": {
|
||||||
|
// this.httpLib.useNfcTunnel = true;
|
||||||
|
throw Error("not implemented");
|
||||||
|
}
|
||||||
|
case "stopTunnel": {
|
||||||
|
// this.httpLib.useNfcTunnel = false;
|
||||||
|
throw Error("not implemented");
|
||||||
|
}
|
||||||
|
case "tunnelResponse": {
|
||||||
|
// httpLib.handleTunnelResponse(msg.args);
|
||||||
|
throw Error("not implemented");
|
||||||
|
}
|
||||||
|
case "reset": {
|
||||||
|
const oldArgs = this.walletArgs;
|
||||||
|
this.walletArgs = Object.assign({}, oldArgs);
|
||||||
|
if (oldArgs && oldArgs.persistentStoragePath) {
|
||||||
|
try {
|
||||||
|
fs_1.default.unlinkSync(oldArgs.persistentStoragePath);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Error while deleting the wallet db:", e);
|
||||||
|
}
|
||||||
|
// Prevent further storage!
|
||||||
|
this.walletArgs.persistentStoragePath = undefined;
|
||||||
|
}
|
||||||
|
const wallet = yield this.wp.promise;
|
||||||
|
wallet.stop();
|
||||||
|
this.wp = promiseUtils_1.openPromise();
|
||||||
|
this.maybeWallet = undefined;
|
||||||
|
const w = yield taler_wallet_core_1.getDefaultNodeWallet(
|
||||||
|
this.walletArgs,
|
||||||
|
);
|
||||||
|
this.maybeWallet = w;
|
||||||
|
w.runRetryLoop().catch((e) => {
|
||||||
|
console.error("Error during wallet retry loop", e);
|
||||||
|
});
|
||||||
|
this.wp.resolve(w);
|
||||||
|
return wrapResponse({});
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
const wallet = yield this.wp.promise;
|
||||||
|
return yield walletCoreApiHandler_1.handleCoreApiRequest(
|
||||||
|
wallet,
|
||||||
|
operation,
|
||||||
|
id,
|
||||||
|
args,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function installAndroidWalletListener() {
|
||||||
|
const handler = new AndroidWalletMessageHandler();
|
||||||
|
const onMessage = (msgStr) =>
|
||||||
|
tslib_1.__awaiter(this, void 0, void 0, function* () {
|
||||||
|
if (typeof msgStr !== "string") {
|
||||||
|
console.error("expected string as message");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const msg = JSON.parse(msgStr);
|
||||||
|
const operation = msg.operation;
|
||||||
|
if (typeof operation !== "string") {
|
||||||
|
console.error(
|
||||||
|
"message to android wallet helper must contain operation of type string",
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const id = msg.id;
|
||||||
|
console.log(`android listener: got request for ${operation} (${id})`);
|
||||||
|
try {
|
||||||
|
const respMsg = yield handler.handleMessage(operation, id, msg.args);
|
||||||
|
console.log(
|
||||||
|
`android listener: sending success response for ${operation} (${id})`,
|
||||||
|
);
|
||||||
|
sendAkonoMessage(respMsg);
|
||||||
|
} catch (e) {
|
||||||
|
const respMsg = {
|
||||||
|
type: "error",
|
||||||
|
id,
|
||||||
|
operation,
|
||||||
|
error: errors_1.makeErrorDetails(
|
||||||
|
TalerErrorCode_1.TalerErrorCode.WALLET_UNEXPECTED_EXCEPTION,
|
||||||
|
"unexpected exception",
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
};
|
||||||
|
sendAkonoMessage(respMsg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// @ts-ignore
|
||||||
|
globalThis.__akono_onMessage = onMessage;
|
||||||
|
console.log("android wallet listener installed");
|
||||||
|
}
|
||||||
|
exports.installAndroidWalletListener = installAndroidWalletListener;
|
||||||
|
//# sourceMappingURL=index.js.map
|
1
packages/taler-wallet-android/src/index.js.map
Normal file
1
packages/taler-wallet-android/src/index.js.map
Normal file
File diff suppressed because one or more lines are too long
@ -17,57 +17,46 @@
|
|||||||
/**
|
/**
|
||||||
* Imports.
|
* Imports.
|
||||||
*/
|
*/
|
||||||
import { Wallet } from "../wallet";
|
|
||||||
import {
|
import {
|
||||||
|
Wallet,
|
||||||
getDefaultNodeWallet,
|
getDefaultNodeWallet,
|
||||||
DefaultNodeWalletArgs,
|
DefaultNodeWalletArgs,
|
||||||
} from "../headless/helpers";
|
versions,
|
||||||
import { openPromise, OpenedPromise } from "../util/promiseUtils";
|
httpLib,
|
||||||
|
nodeThreadWorker,
|
||||||
|
promiseUtil,
|
||||||
|
NodeHttpLib,
|
||||||
|
walletCoreApi,
|
||||||
|
walletNotifications,
|
||||||
|
TalerErrorCode,
|
||||||
|
makeErrorDetails,
|
||||||
|
} from "taler-wallet-core";
|
||||||
|
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import {
|
|
||||||
HttpRequestLibrary,
|
|
||||||
HttpResponse,
|
|
||||||
HttpRequestOptions,
|
|
||||||
Headers,
|
|
||||||
} from "../util/http";
|
|
||||||
import { NodeHttpLib } from "../headless/NodeHttpLib";
|
|
||||||
import { WalletNotification } from "../types/notifications";
|
|
||||||
import {
|
|
||||||
WALLET_EXCHANGE_PROTOCOL_VERSION,
|
|
||||||
WALLET_MERCHANT_PROTOCOL_VERSION,
|
|
||||||
} from "../operations/versions";
|
|
||||||
import {
|
|
||||||
handleCoreApiRequest,
|
|
||||||
CoreApiResponseSuccess,
|
|
||||||
CoreApiResponse,
|
|
||||||
CoreApiEnvelope,
|
|
||||||
} from "../walletCoreApiHandler";
|
|
||||||
import { makeErrorDetails } from "../operations/errors";
|
|
||||||
import { TalerErrorCode } from "../TalerErrorCode";
|
|
||||||
|
|
||||||
// @ts-ignore: special built-in module
|
export const handleWorkerError = nodeThreadWorker.handleWorkerError;
|
||||||
//import akono = require("akono");
|
export const handleWorkerMessage = nodeThreadWorker.handleWorkerMessage;
|
||||||
|
|
||||||
export {
|
export class AndroidHttpLib implements httpLib.HttpRequestLibrary {
|
||||||
handleWorkerError,
|
|
||||||
handleWorkerMessage,
|
|
||||||
} from "../crypto/workers/nodeThreadWorker";
|
|
||||||
|
|
||||||
export class AndroidHttpLib implements HttpRequestLibrary {
|
|
||||||
useNfcTunnel = false;
|
useNfcTunnel = false;
|
||||||
|
|
||||||
private nodeHttpLib: HttpRequestLibrary = new NodeHttpLib();
|
private nodeHttpLib: httpLib.HttpRequestLibrary = new NodeHttpLib();
|
||||||
|
|
||||||
private requestId = 1;
|
private requestId = 1;
|
||||||
|
|
||||||
private requestMap: { [id: number]: OpenedPromise<HttpResponse> } = {};
|
private requestMap: {
|
||||||
|
[id: number]: promiseUtil.OpenedPromise<httpLib.HttpResponse>;
|
||||||
|
} = {};
|
||||||
|
|
||||||
constructor(private sendMessage: (m: string) => void) {}
|
constructor(private sendMessage: (m: string) => void) {}
|
||||||
|
|
||||||
get(url: string, opt?: HttpRequestOptions): Promise<HttpResponse> {
|
get(
|
||||||
|
url: string,
|
||||||
|
opt?: httpLib.HttpRequestOptions,
|
||||||
|
): Promise<httpLib.HttpResponse> {
|
||||||
if (this.useNfcTunnel) {
|
if (this.useNfcTunnel) {
|
||||||
const myId = this.requestId++;
|
const myId = this.requestId++;
|
||||||
const p = openPromise<HttpResponse>();
|
const p = promiseUtil.openPromise<httpLib.HttpResponse>();
|
||||||
this.requestMap[myId] = p;
|
this.requestMap[myId] = p;
|
||||||
const request = {
|
const request = {
|
||||||
method: "get",
|
method: "get",
|
||||||
@ -89,11 +78,11 @@ export class AndroidHttpLib implements HttpRequestLibrary {
|
|||||||
postJson(
|
postJson(
|
||||||
url: string,
|
url: string,
|
||||||
body: any,
|
body: any,
|
||||||
opt?: HttpRequestOptions,
|
opt?: httpLib.HttpRequestOptions,
|
||||||
): Promise<import("../util/http").HttpResponse> {
|
): Promise<httpLib.HttpResponse> {
|
||||||
if (this.useNfcTunnel) {
|
if (this.useNfcTunnel) {
|
||||||
const myId = this.requestId++;
|
const myId = this.requestId++;
|
||||||
const p = openPromise<HttpResponse>();
|
const p = promiseUtil.openPromise<httpLib.HttpResponse>();
|
||||||
this.requestMap[myId] = p;
|
this.requestMap[myId] = p;
|
||||||
const request = {
|
const request = {
|
||||||
method: "postJson",
|
method: "postJson",
|
||||||
@ -117,9 +106,9 @@ export class AndroidHttpLib implements HttpRequestLibrary {
|
|||||||
`no matching request for tunneled HTTP response, id=${myId}`,
|
`no matching request for tunneled HTTP response, id=${myId}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const headers = new Headers();
|
const headers = new httpLib.Headers();
|
||||||
if (msg.status != 0) {
|
if (msg.status != 0) {
|
||||||
const resp: HttpResponse = {
|
const resp: httpLib.HttpResponse = {
|
||||||
// FIXME: pass through this URL
|
// FIXME: pass through this URL
|
||||||
requestUrl: "",
|
requestUrl: "",
|
||||||
headers,
|
headers,
|
||||||
@ -135,7 +124,7 @@ export class AndroidHttpLib implements HttpRequestLibrary {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendAkonoMessage(ev: CoreApiEnvelope): void {
|
function sendAkonoMessage(ev: walletCoreApi.CoreApiEnvelope): void {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const sendMessage = globalThis.__akono_sendMessage;
|
const sendMessage = globalThis.__akono_sendMessage;
|
||||||
if (typeof sendMessage !== "function") {
|
if (typeof sendMessage !== "function") {
|
||||||
@ -152,7 +141,7 @@ function sendAkonoMessage(ev: CoreApiEnvelope): void {
|
|||||||
class AndroidWalletMessageHandler {
|
class AndroidWalletMessageHandler {
|
||||||
walletArgs: DefaultNodeWalletArgs | undefined;
|
walletArgs: DefaultNodeWalletArgs | undefined;
|
||||||
maybeWallet: Wallet | undefined;
|
maybeWallet: Wallet | undefined;
|
||||||
wp = openPromise<Wallet>();
|
wp = promiseUtil.openPromise<Wallet>();
|
||||||
httpLib = new NodeHttpLib();
|
httpLib = new NodeHttpLib();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -162,8 +151,10 @@ class AndroidWalletMessageHandler {
|
|||||||
operation: string,
|
operation: string,
|
||||||
id: string,
|
id: string,
|
||||||
args: any,
|
args: any,
|
||||||
): Promise<CoreApiResponse> {
|
): Promise<walletCoreApi.CoreApiResponse> {
|
||||||
const wrapResponse = (result: unknown): CoreApiResponseSuccess => {
|
const wrapResponse = (
|
||||||
|
result: unknown,
|
||||||
|
): walletCoreApi.CoreApiResponseSuccess => {
|
||||||
return {
|
return {
|
||||||
type: "response",
|
type: "response",
|
||||||
id,
|
id,
|
||||||
@ -174,7 +165,9 @@ class AndroidWalletMessageHandler {
|
|||||||
switch (operation) {
|
switch (operation) {
|
||||||
case "init": {
|
case "init": {
|
||||||
this.walletArgs = {
|
this.walletArgs = {
|
||||||
notifyHandler: async (notification: WalletNotification) => {
|
notifyHandler: async (
|
||||||
|
notification: walletNotifications.WalletNotification,
|
||||||
|
) => {
|
||||||
sendAkonoMessage({ type: "notification", payload: notification });
|
sendAkonoMessage({ type: "notification", payload: notification });
|
||||||
},
|
},
|
||||||
persistentStoragePath: args.persistentStoragePath,
|
persistentStoragePath: args.persistentStoragePath,
|
||||||
@ -188,8 +181,8 @@ class AndroidWalletMessageHandler {
|
|||||||
this.wp.resolve(w);
|
this.wp.resolve(w);
|
||||||
return wrapResponse({
|
return wrapResponse({
|
||||||
supported_protocol_versions: {
|
supported_protocol_versions: {
|
||||||
exchange: WALLET_EXCHANGE_PROTOCOL_VERSION,
|
exchange: versions.WALLET_EXCHANGE_PROTOCOL_VERSION,
|
||||||
merchant: WALLET_MERCHANT_PROTOCOL_VERSION,
|
merchant: versions.WALLET_MERCHANT_PROTOCOL_VERSION,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -222,7 +215,7 @@ class AndroidWalletMessageHandler {
|
|||||||
}
|
}
|
||||||
const wallet = await this.wp.promise;
|
const wallet = await this.wp.promise;
|
||||||
wallet.stop();
|
wallet.stop();
|
||||||
this.wp = openPromise<Wallet>();
|
this.wp = promiseUtil.openPromise<Wallet>();
|
||||||
this.maybeWallet = undefined;
|
this.maybeWallet = undefined;
|
||||||
const w = await getDefaultNodeWallet(this.walletArgs);
|
const w = await getDefaultNodeWallet(this.walletArgs);
|
||||||
this.maybeWallet = w;
|
this.maybeWallet = w;
|
||||||
@ -234,7 +227,12 @@ class AndroidWalletMessageHandler {
|
|||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
const wallet = await this.wp.promise;
|
const wallet = await this.wp.promise;
|
||||||
return await handleCoreApiRequest(wallet, operation, id, args);
|
return await walletCoreApi.handleCoreApiRequest(
|
||||||
|
wallet,
|
||||||
|
operation,
|
||||||
|
id,
|
||||||
|
args,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -265,7 +263,7 @@ export function installAndroidWalletListener(): void {
|
|||||||
);
|
);
|
||||||
sendAkonoMessage(respMsg);
|
sendAkonoMessage(respMsg);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const respMsg: CoreApiResponse = {
|
const respMsg: walletCoreApi.CoreApiResponse = {
|
||||||
type: "error",
|
type: "error",
|
||||||
id,
|
id,
|
||||||
operation,
|
operation,
|
@ -1,6 +1,9 @@
|
|||||||
{
|
{
|
||||||
"compileOnSave": true,
|
"compileOnSave": true,
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
|
"declaration": true,
|
||||||
|
"declarationMap": true,
|
||||||
"target": "ES6",
|
"target": "ES6",
|
||||||
"jsx": "react",
|
"jsx": "react",
|
||||||
"reactNamespace": "React",
|
"reactNamespace": "React",
|
||||||
@ -15,14 +18,15 @@
|
|||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"strictPropertyInitialization": false,
|
"strictPropertyInitialization": false,
|
||||||
"outDir": "dist/node",
|
"outDir": "lib",
|
||||||
"noImplicitAny": true,
|
"noImplicitAny": true,
|
||||||
"noImplicitThis": true,
|
"noImplicitThis": true,
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"checkJs": true,
|
"checkJs": true,
|
||||||
"incremental": true,
|
"incremental": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"importHelpers": true
|
"importHelpers": true,
|
||||||
|
"rootDir": "./src"
|
||||||
},
|
},
|
||||||
"include": ["src/**/*"]
|
"include": ["src/**/*"]
|
||||||
}
|
}
|
7
packages/taler-wallet-cli/bin/taler-wallet-cli
Executable file
7
packages/taler-wallet-cli/bin/taler-wallet-cli
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
try {
|
||||||
|
require('source-map-support').install();
|
||||||
|
} catch (e) {
|
||||||
|
// Do nothing.
|
||||||
|
}
|
||||||
|
require('../dist/taler-wallet-cli.js')
|
48
packages/taler-wallet-cli/package.json
Normal file
48
packages/taler-wallet-cli/package.json
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"name": "taler-wallet-cli",
|
||||||
|
"version": "0.6.12",
|
||||||
|
"description": "",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.12.0"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git://git.taler.net/wallet-core.git"
|
||||||
|
},
|
||||||
|
"author": "Florian Dold",
|
||||||
|
"license": "GPL-3.0",
|
||||||
|
"main": "dist/taler-wallet-cli.js",
|
||||||
|
"bin": {
|
||||||
|
"taler-wallet-cli": "./bin/taler-wallet-cli"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"compile": "tsc && rollup -c",
|
||||||
|
"clean": "rimraf lib dist",
|
||||||
|
"pretty": "prettier --config ../../.prettierrc --write src"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"AUTHORS",
|
||||||
|
"README",
|
||||||
|
"COPYING",
|
||||||
|
"bin/",
|
||||||
|
"dist/node",
|
||||||
|
"src/"
|
||||||
|
],
|
||||||
|
"devDependencies": {
|
||||||
|
"@rollup/plugin-commonjs": "^14.0.0",
|
||||||
|
"@rollup/plugin-json": "^4.1.0",
|
||||||
|
"@rollup/plugin-node-resolve": "^8.4.0",
|
||||||
|
"@rollup/plugin-replace": "^2.3.3",
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"rollup": "^2.23.0",
|
||||||
|
"rollup-plugin-sourcemaps": "^0.6.2",
|
||||||
|
"rollup-plugin-terser": "^6.1.0",
|
||||||
|
"typedoc": "^0.17.8",
|
||||||
|
"typescript": "^3.9.7"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"source-map-support": "^0.5.19",
|
||||||
|
"taler-wallet-core": "workspace:*",
|
||||||
|
"tslib": "^2.0.0"
|
||||||
|
}
|
||||||
|
}
|
30
packages/taler-wallet-cli/rollup.config.js
Normal file
30
packages/taler-wallet-cli/rollup.config.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
// rollup.config.js
|
||||||
|
import commonjs from "@rollup/plugin-commonjs";
|
||||||
|
import nodeResolve from "@rollup/plugin-node-resolve";
|
||||||
|
import json from "@rollup/plugin-json";
|
||||||
|
import builtins from "builtin-modules";
|
||||||
|
import pkg from "./package.json";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
input: "lib/index.js",
|
||||||
|
output: {
|
||||||
|
file: pkg.main,
|
||||||
|
format: "cjs",
|
||||||
|
},
|
||||||
|
external: builtins,
|
||||||
|
plugins: [
|
||||||
|
nodeResolve({
|
||||||
|
preferBuiltins: true,
|
||||||
|
}),
|
||||||
|
|
||||||
|
commonjs({
|
||||||
|
include: [/node_modules/, /dist/],
|
||||||
|
extensions: [".js", ".ts"],
|
||||||
|
ignoreGlobal: false,
|
||||||
|
sourceMap: false,
|
||||||
|
}),
|
||||||
|
|
||||||
|
json(),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
@ -16,31 +16,24 @@
|
|||||||
|
|
||||||
import os from "os";
|
import os from "os";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import { getDefaultNodeWallet } from "./helpers";
|
|
||||||
import { Wallet } from "../wallet";
|
|
||||||
import qrcodeGenerator from "qrcode-generator";
|
|
||||||
import * as clk from "./clk";
|
|
||||||
import { BridgeIDBFactory } from "idb-bridge";
|
|
||||||
import { Logger } from "../util/logging";
|
|
||||||
import { Amounts } from "../util/amounts";
|
|
||||||
import {
|
|
||||||
decodeCrock,
|
|
||||||
setupRefreshPlanchet,
|
|
||||||
encodeCrock,
|
|
||||||
} from "../crypto/talerCrypto";
|
|
||||||
import {
|
import {
|
||||||
|
getDefaultNodeWallet,
|
||||||
|
Logger,
|
||||||
|
Amounts,
|
||||||
|
Wallet,
|
||||||
OperationFailedAndReportedError,
|
OperationFailedAndReportedError,
|
||||||
OperationFailedError,
|
OperationFailedError,
|
||||||
} from "../operations/errors";
|
time,
|
||||||
import { classifyTalerUri, TalerUriType } from "../util/taleruri";
|
taleruri,
|
||||||
import { Configuration } from "../util/talerconfig";
|
walletTypes,
|
||||||
import { setDangerousTimetravel } from "../util/time";
|
talerCrypto,
|
||||||
import { makeCodecForList, codecForString } from "../util/codec";
|
payto,
|
||||||
import { NodeHttpLib } from "./NodeHttpLib";
|
codec,
|
||||||
import * as nacl from "../crypto/primitives/nacl-fast";
|
testvectors,
|
||||||
import { addPaytoQueryParams } from "../util/payto";
|
walletCoreApi,
|
||||||
import { handleCoreApiRequest } from "../walletCoreApiHandler";
|
NodeHttpLib,
|
||||||
import { PreparePayResultType } from "../types/walletTypes";
|
} from "taler-wallet-core";
|
||||||
|
import * as clk from "./clk";
|
||||||
|
|
||||||
const logger = new Logger("taler-wallet-cli.ts");
|
const logger = new Logger("taler-wallet-cli.ts");
|
||||||
|
|
||||||
@ -56,19 +49,19 @@ async function doPay(
|
|||||||
options: { alwaysYes: boolean } = { alwaysYes: true },
|
options: { alwaysYes: boolean } = { alwaysYes: true },
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const result = await wallet.preparePayForUri(payUrl);
|
const result = await wallet.preparePayForUri(payUrl);
|
||||||
if (result.status === PreparePayResultType.InsufficientBalance) {
|
if (result.status === walletTypes.PreparePayResultType.InsufficientBalance) {
|
||||||
console.log("contract", result.contractTerms);
|
console.log("contract", result.contractTerms);
|
||||||
console.error("insufficient balance");
|
console.error("insufficient balance");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (result.status === PreparePayResultType.AlreadyConfirmed) {
|
if (result.status === walletTypes.PreparePayResultType.AlreadyConfirmed) {
|
||||||
if (result.paid) {
|
if (result.paid) {
|
||||||
console.log("already paid!");
|
console.log("already paid!");
|
||||||
} else {
|
} else {
|
||||||
console.log("payment already in progress");
|
console.log("payment already in progress");
|
||||||
}
|
}
|
||||||
|
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -106,10 +99,7 @@ async function doPay(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function applyVerbose(verbose: boolean): void {
|
function applyVerbose(verbose: boolean): void {
|
||||||
if (verbose) {
|
// TODO
|
||||||
console.log("enabled verbose logging");
|
|
||||||
BridgeIDBFactory.enableTracing = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function printVersion(): void {
|
function printVersion(): void {
|
||||||
@ -131,7 +121,7 @@ const walletCli = clk
|
|||||||
onPresentHandler: (x) => {
|
onPresentHandler: (x) => {
|
||||||
// Convert microseconds to milliseconds and do timetravel
|
// Convert microseconds to milliseconds and do timetravel
|
||||||
logger.info(`timetravelling ${x} microseconds`);
|
logger.info(`timetravelling ${x} microseconds`);
|
||||||
setDangerousTimetravel(x / 1000);
|
time.setDangerousTimetravel(x / 1000);
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.maybeOption("inhibit", ["--inhibit"], clk.STRING, {
|
.maybeOption("inhibit", ["--inhibit"], clk.STRING, {
|
||||||
@ -212,7 +202,7 @@ walletCli
|
|||||||
console.error("Invalid JSON");
|
console.error("Invalid JSON");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
const resp = await handleCoreApiRequest(
|
const resp = await walletCoreApi.handleCoreApiRequest(
|
||||||
wallet,
|
wallet,
|
||||||
args.api.operation,
|
args.api.operation,
|
||||||
"reqid-1",
|
"reqid-1",
|
||||||
@ -281,22 +271,22 @@ walletCli
|
|||||||
.action(async (args) => {
|
.action(async (args) => {
|
||||||
await withWallet(args, async (wallet) => {
|
await withWallet(args, async (wallet) => {
|
||||||
const uri: string = args.handleUri.uri;
|
const uri: string = args.handleUri.uri;
|
||||||
const uriType = classifyTalerUri(uri);
|
const uriType = taleruri.classifyTalerUri(uri);
|
||||||
switch (uriType) {
|
switch (uriType) {
|
||||||
case TalerUriType.TalerPay:
|
case taleruri.TalerUriType.TalerPay:
|
||||||
await doPay(wallet, uri, { alwaysYes: args.handleUri.autoYes });
|
await doPay(wallet, uri, { alwaysYes: args.handleUri.autoYes });
|
||||||
break;
|
break;
|
||||||
case TalerUriType.TalerTip:
|
case taleruri.TalerUriType.TalerTip:
|
||||||
{
|
{
|
||||||
const res = await wallet.getTipStatus(uri);
|
const res = await wallet.getTipStatus(uri);
|
||||||
console.log("tip status", res);
|
console.log("tip status", res);
|
||||||
await wallet.acceptTip(res.tipId);
|
await wallet.acceptTip(res.tipId);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TalerUriType.TalerRefund:
|
case taleruri.TalerUriType.TalerRefund:
|
||||||
await wallet.applyRefund(uri);
|
await wallet.applyRefund(uri);
|
||||||
break;
|
break;
|
||||||
case TalerUriType.TalerWithdraw:
|
case taleruri.TalerUriType.TalerWithdraw:
|
||||||
{
|
{
|
||||||
const withdrawInfo = await wallet.getWithdrawalDetailsForUri(uri);
|
const withdrawInfo = await wallet.getWithdrawalDetailsForUri(uri);
|
||||||
const selectedExchange = withdrawInfo.defaultExchangeBaseUrl;
|
const selectedExchange = withdrawInfo.defaultExchangeBaseUrl;
|
||||||
@ -423,7 +413,7 @@ advancedCli
|
|||||||
})
|
})
|
||||||
.action((args) => {
|
.action((args) => {
|
||||||
const enc = fs.readFileSync(0, "utf8");
|
const enc = fs.readFileSync(0, "utf8");
|
||||||
fs.writeFileSync(1, decodeCrock(enc.trim()));
|
fs.writeFileSync(1, talerCrypto.decodeCrock(enc.trim()));
|
||||||
});
|
});
|
||||||
|
|
||||||
advancedCli
|
advancedCli
|
||||||
@ -450,7 +440,7 @@ advancedCli
|
|||||||
exchange.baseUrl,
|
exchange.baseUrl,
|
||||||
Amounts.parseOrThrow(args.withdrawManually.amount),
|
Amounts.parseOrThrow(args.withdrawManually.amount),
|
||||||
);
|
);
|
||||||
const completePaytoUri = addPaytoQueryParams(acct.payto_uri, {
|
const completePaytoUri = payto.addPaytoQueryParams(acct.payto_uri, {
|
||||||
amount: args.withdrawManually.amount,
|
amount: args.withdrawManually.amount,
|
||||||
message: `Taler top-up ${reserve.reservePub}`,
|
message: `Taler top-up ${reserve.reservePub}`,
|
||||||
});
|
});
|
||||||
@ -494,17 +484,17 @@ advancedCli
|
|||||||
await withWallet(args, async (wallet) => {
|
await withWallet(args, async (wallet) => {
|
||||||
const res = await wallet.preparePayForUri(args.payPrepare.url);
|
const res = await wallet.preparePayForUri(args.payPrepare.url);
|
||||||
switch (res.status) {
|
switch (res.status) {
|
||||||
case PreparePayResultType.InsufficientBalance:
|
case walletTypes.PreparePayResultType.InsufficientBalance:
|
||||||
console.log("insufficient balance");
|
console.log("insufficient balance");
|
||||||
break;
|
break;
|
||||||
case PreparePayResultType.AlreadyConfirmed:
|
case walletTypes.PreparePayResultType.AlreadyConfirmed:
|
||||||
if (res.paid) {
|
if (res.paid) {
|
||||||
console.log("already paid!");
|
console.log("already paid!");
|
||||||
} else {
|
} else {
|
||||||
console.log("payment in progress");
|
console.log("payment in progress");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PreparePayResultType.PaymentPossible:
|
case walletTypes.PreparePayResultType.PaymentPossible:
|
||||||
console.log("payment possible");
|
console.log("payment possible");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -550,7 +540,7 @@ advancedCli
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const coinPubListCodec = makeCodecForList(codecForString);
|
const coinPubListCodec = codec.makeCodecForList(codec.codecForString);
|
||||||
|
|
||||||
advancedCli
|
advancedCli
|
||||||
.subcommand("suspendCoins", "suspend-coins", {
|
.subcommand("suspendCoins", "suspend-coins", {
|
||||||
@ -644,15 +634,7 @@ const testCli = walletCli.subcommand("testingArgs", "testing", {
|
|||||||
});
|
});
|
||||||
|
|
||||||
testCli.subcommand("vectors", "vectors").action(async (args) => {
|
testCli.subcommand("vectors", "vectors").action(async (args) => {
|
||||||
const secretSeed = nacl.randomBytes(64);
|
testvectors.printTestVectors();
|
||||||
const coinIndex = Math.ceil(Math.random() * 100);
|
|
||||||
const p = setupRefreshPlanchet(secretSeed, coinIndex);
|
|
||||||
console.log("setupRefreshPlanchet");
|
|
||||||
console.log(` (in) secret seed: ${encodeCrock(secretSeed)}`);
|
|
||||||
console.log(` (in) coin index: ${coinIndex}`);
|
|
||||||
console.log(` (out) blinding secret: ${encodeCrock(p.bks)}`);
|
|
||||||
console.log(` (out) coin priv: ${encodeCrock(p.coinPriv)}`);
|
|
||||||
console.log(` (out) coin pub: ${encodeCrock(p.coinPub)}`);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
walletCli.run();
|
walletCli.run();
|
30
packages/taler-wallet-cli/tsconfig.json
Normal file
30
packages/taler-wallet-cli/tsconfig.json
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"compileOnSave": true,
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
|
"target": "ES6",
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"sourceMap": true,
|
||||||
|
"lib": ["es6"],
|
||||||
|
"noImplicitReturns": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"strict": true,
|
||||||
|
"strictPropertyInitialization": false,
|
||||||
|
"outDir": "lib",
|
||||||
|
"noImplicitAny": true,
|
||||||
|
"noImplicitThis": true,
|
||||||
|
"incremental": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"importHelpers": true,
|
||||||
|
"rootDir": "src",
|
||||||
|
"baseUrl": "./src",
|
||||||
|
"types": ["node"]
|
||||||
|
},
|
||||||
|
"include": ["src/**/*"],
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"path": "../taler-wallet-core/"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
1
packages/taler-wallet-core/.gitignore
vendored
Normal file
1
packages/taler-wallet-core/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/lib
|
81
packages/taler-wallet-core/package.json
Normal file
81
packages/taler-wallet-core/package.json
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
{
|
||||||
|
"name": "taler-wallet-core",
|
||||||
|
"version": "0.6.12",
|
||||||
|
"description": "",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.12.0"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git://git.taler.net/wallet-core.git"
|
||||||
|
},
|
||||||
|
"author": "Florian Dold",
|
||||||
|
"license": "GPL-3.0",
|
||||||
|
"scripts": {
|
||||||
|
"compile": "tsc && rollup -c",
|
||||||
|
"pretty": "prettier --config ../../.prettierrc --write src",
|
||||||
|
"test": "tsc && ava",
|
||||||
|
"coverage": "tsc && nyc ava",
|
||||||
|
"clean": "rimraf dist lib"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"AUTHORS",
|
||||||
|
"README",
|
||||||
|
"COPYING",
|
||||||
|
"bin/",
|
||||||
|
"dist/node",
|
||||||
|
"src/"
|
||||||
|
],
|
||||||
|
"main": "./dist/taler-wallet-core.js",
|
||||||
|
"module": "./lib/index.js",
|
||||||
|
"types": "./lib/index.d.ts",
|
||||||
|
"devDependencies": {
|
||||||
|
"@ava/typescript": "^1.1.1",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^3.6.1",
|
||||||
|
"@typescript-eslint/parser": "^3.6.1",
|
||||||
|
"ava": "^3.10.1",
|
||||||
|
"eslint": "^7.4.0",
|
||||||
|
"eslint-config-airbnb-typescript": "^8.0.2",
|
||||||
|
"eslint-plugin-import": "^2.22.0",
|
||||||
|
"eslint-plugin-jsx-a11y": "^6.3.1",
|
||||||
|
"eslint-plugin-react": "^7.20.3",
|
||||||
|
"eslint-plugin-react-hooks": "^4.0.8",
|
||||||
|
"jed": "^1.1.1",
|
||||||
|
"moment": "^2.27.0",
|
||||||
|
"nyc": "^15.1.0",
|
||||||
|
"po2json": "^0.4.5",
|
||||||
|
"pogen": "workspace:*",
|
||||||
|
"prettier": "^2.0.5",
|
||||||
|
"source-map-resolve": "^0.6.0",
|
||||||
|
"structured-clone": "^0.2.2",
|
||||||
|
"typedoc": "^0.17.8",
|
||||||
|
"typescript": "^3.9.7",
|
||||||
|
"rollup": "^2.23.0",
|
||||||
|
"esm": "^3.2.25",
|
||||||
|
"rimraf": "^3.0.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "^14.0.27",
|
||||||
|
"axios": "^0.19.2",
|
||||||
|
"big-integer": "^1.6.48",
|
||||||
|
"idb-bridge": "workspace:*",
|
||||||
|
"source-map-support": "^0.5.19",
|
||||||
|
"tslib": "^2.0.0"
|
||||||
|
},
|
||||||
|
"ava": {
|
||||||
|
"require": ["esm"],
|
||||||
|
"files": [
|
||||||
|
"src/**/*-test.*"
|
||||||
|
],
|
||||||
|
"typescript": {
|
||||||
|
"extensions": [
|
||||||
|
"js",
|
||||||
|
"ts",
|
||||||
|
"tsx"
|
||||||
|
],
|
||||||
|
"rewritePaths": {
|
||||||
|
"src/": "lib/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
31
packages/taler-wallet-core/rollup.config.js
Normal file
31
packages/taler-wallet-core/rollup.config.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// rollup.config.js
|
||||||
|
import commonjs from "@rollup/plugin-commonjs";
|
||||||
|
import nodeResolve from "@rollup/plugin-node-resolve";
|
||||||
|
import json from "@rollup/plugin-json";
|
||||||
|
import builtins from "builtin-modules";
|
||||||
|
import pkg from "./package.json";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
input: "lib/index.js",
|
||||||
|
output: {
|
||||||
|
file: pkg.main,
|
||||||
|
format: "cjs",
|
||||||
|
sourcemap: false,
|
||||||
|
},
|
||||||
|
external: builtins,
|
||||||
|
plugins: [
|
||||||
|
nodeResolve({
|
||||||
|
preferBuiltins: true,
|
||||||
|
}),
|
||||||
|
|
||||||
|
commonjs({
|
||||||
|
include: [/node_modules/, /dist/],
|
||||||
|
extensions: [".js"],
|
||||||
|
ignoreGlobal: false,
|
||||||
|
sourceMap: false,
|
||||||
|
}),
|
||||||
|
|
||||||
|
json(),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
1
packages/taler-wallet-core/src/TalerErrorCode.d.ts.map
Normal file
1
packages/taler-wallet-core/src/TalerErrorCode.d.ts.map
Normal file
File diff suppressed because one or more lines are too long
@ -22,8 +22,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export enum TalerErrorCode {
|
export enum TalerErrorCode {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Special code to indicate no error (or no "code" present).
|
* Special code to indicate no error (or no "code" present).
|
||||||
* Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).
|
* Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).
|
||||||
@ -3096,5 +3094,4 @@ export enum TalerErrorCode {
|
|||||||
* (A value of 0 indicates that the error is generated client-side).
|
* (A value of 0 indicates that the error is generated client-side).
|
||||||
*/
|
*/
|
||||||
END = 9999,
|
END = 9999,
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"kdf.d.ts","sourceRoot":"","sources":["kdf.ts"],"names":[],"mappings":"AAmBA,wBAAgB,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,CAEnD;AAED,wBAAgB,IAAI,CAClB,MAAM,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,UAAU,EACrC,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,UAAU,GAClB,UAAU,CAuBZ;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,GAAG,UAAU,CAE3E;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,GAAG,UAAU,CAE3E;AAED,wBAAgB,GAAG,CACjB,YAAY,EAAE,MAAM,EACpB,GAAG,EAAE,UAAU,EACf,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,UAAU,GACf,UAAU,CAyBZ"}
|
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"nacl-fast.d.ts","sourceRoot":"","sources":["nacl-fast.ts"],"names":[],"mappings":"AA8zCA;;GAEG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,EAAE,CAAqB;IAC/B,OAAO,CAAC,EAAE,CAAqB;IAE/B,OAAO,CAAC,IAAI,CAAuB;IACnC,OAAO,CAAC,CAAC,CAAK;IACd,OAAO,CAAC,KAAK,CAAK;;IAsBlB,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS;IAuBnC,MAAM,IAAI,UAAU;CAgBrB;AAqTD,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,UAAU,CAIjD;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,GAAG,UAAU,CAOnE;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,UAAU,GAAG,UAAU,CAMzD;AAED,eAAO,MAAM,uBAAuB,KAAgC,CAAC;AACrE,eAAO,MAAM,6BAA6B,KAA0B,CAAC;AAErE,wBAAgB,IAAI,CAAC,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,GAAG,UAAU,CAOvE;AAED,wBAAgB,SAAS,CACvB,SAAS,EAAE,UAAU,EACrB,SAAS,EAAE,UAAU,GACpB,UAAU,GAAG,IAAI,CAUnB;AAED,wBAAgB,aAAa,CAC3B,GAAG,EAAE,UAAU,EACf,SAAS,EAAE,UAAU,GACpB,UAAU,CAKZ;AAED,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,UAAU,EACf,GAAG,EAAE,UAAU,EACf,SAAS,EAAE,UAAU,GACpB,OAAO,CAWT;AAED,wBAAgB,YAAY,IAAI;IAC9B,SAAS,EAAE,UAAU,CAAC;IACtB,SAAS,EAAE,UAAU,CAAC;CACvB,CAKA;AAED,wBAAgB,oCAAoC,CAClD,SAAS,EAAE,UAAU,GACpB,UAAU,CAmBZ;AAED,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,UAAU,GACpB;IACD,SAAS,EAAE,UAAU,CAAC;IACtB,SAAS,EAAE,UAAU,CAAC;CACvB,CAOA;AAED,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,UAAU,GACf;IACD,SAAS,EAAE,UAAU,CAAC;IACtB,SAAS,EAAE,UAAU,CAAC;CACvB,CAQA;AAED,eAAO,MAAM,oBAAoB,KAA6B,CAAC;AAC/D,eAAO,MAAM,oBAAoB,KAA6B,CAAC;AAC/D,eAAO,MAAM,eAAe,KAAwB,CAAC;AACrD,eAAO,MAAM,oBAAoB,KAAoB,CAAC;AAEtD,wBAAgB,IAAI,CAAC,GAAG,EAAE,UAAU,GAAG,UAAU,CAKhD;AAED,eAAO,MAAM,eAAe,KAAoB,CAAC;AAEjD,wBAAgB,MAAM,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,GAAG,OAAO,CAM5D;AAED,wBAAgB,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAEpE;AAED,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,UAAU,GACrB,UAAU,CAqBZ"}
|
@ -1912,8 +1912,8 @@ export function sign_ed25519_pk_to_curve25519(
|
|||||||
(function () {
|
(function () {
|
||||||
// Initialize PRNG if environment provides CSPRNG.
|
// Initialize PRNG if environment provides CSPRNG.
|
||||||
// If not, methods calling randombytes will throw.
|
// If not, methods calling randombytes will throw.
|
||||||
const cr =
|
// @ts-ignore-error
|
||||||
typeof self !== "undefined" ? self.crypto || (self as any).msCrypto : null;
|
const cr = typeof self !== "undefined" ? self.crypto || self.msCrypto : null;
|
||||||
if (cr && cr.getRandomValues) {
|
if (cr && cr.getRandomValues) {
|
||||||
// Browsers.
|
// Browsers.
|
||||||
const QUOTA = 65536;
|
const QUOTA = 65536;
|
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"sha256.d.ts","sourceRoot":"","sources":["sha256.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,YAAY,KAAK,CAAC;AAC/B,eAAO,MAAM,SAAS,KAAK,CAAC;AAwK5B,qBAAa,UAAU;IACrB,YAAY,EAAE,MAAM,CAAgB;IACpC,SAAS,EAAE,MAAM,CAAa;IAG9B,OAAO,CAAC,KAAK,CAAiC;IAC9C,OAAO,CAAC,IAAI,CAAkC;IAC9C,OAAO,CAAC,MAAM,CAAmC;IACjD,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,WAAW,CAAK;IAExB,QAAQ,UAAS;;IAQjB,KAAK,IAAI,IAAI;IAgBb,KAAK,IAAI,IAAI;IAiBb,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,UAAU,GAAE,MAAoB,GAAG,IAAI;IA8BhE,MAAM,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI;IAqC7B,MAAM,IAAI,UAAU;IAOpB,UAAU,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI;IAOlC,aAAa,CAAC,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI;CAQ5D;AAGD,qBAAa,IAAI;IACf,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,KAAK,CAAgC;IAE7C,SAAS,EAAE,MAAM,CAAwB;IACzC,YAAY,EAAE,MAAM,CAA2B;IAI/C,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,MAAM,CAAc;gBAEhB,GAAG,EAAE,UAAU;IAiC3B,KAAK,IAAI,IAAI;IAOb,KAAK,IAAI,IAAI;IASb,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI;IAM9B,MAAM,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI;IAW7B,MAAM,IAAI,UAAU;CAKrB;AAGD,wBAAgB,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,CAKnD;AAGD,wBAAgB,UAAU,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,GAAG,UAAU,CAKxE"}
|
@ -27,18 +27,18 @@ import {
|
|||||||
keyExchangeEcdheEddsa,
|
keyExchangeEcdheEddsa,
|
||||||
rsaBlind,
|
rsaBlind,
|
||||||
rsaUnblind,
|
rsaUnblind,
|
||||||
|
stringToBytes,
|
||||||
|
bytesToString,
|
||||||
rsaVerify,
|
rsaVerify,
|
||||||
} from "./talerCrypto";
|
} from "./talerCrypto";
|
||||||
import { sha512, kdf } from "./primitives/kdf";
|
import { sha512, kdf } from "./primitives/kdf";
|
||||||
import * as nacl from "./primitives/nacl-fast";
|
import * as nacl from "./primitives/nacl-fast";
|
||||||
|
|
||||||
test("encoding", (t) => {
|
test("encoding", (t) => {
|
||||||
const utf8decoder = new TextDecoder("utf-8");
|
|
||||||
const utf8encoder = new TextEncoder();
|
|
||||||
const s = "Hello, World";
|
const s = "Hello, World";
|
||||||
const encStr = encodeCrock(utf8encoder.encode(s));
|
const encStr = encodeCrock(stringToBytes(s));
|
||||||
const outBuf = decodeCrock(encStr);
|
const outBuf = decodeCrock(encStr);
|
||||||
const sOut = utf8decoder.decode(outBuf);
|
const sOut = bytesToString(outBuf);
|
||||||
t.deepEqual(s, sOut);
|
t.deepEqual(s, sOut);
|
||||||
});
|
});
|
||||||
|
|
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"talerCrypto.d.ts","sourceRoot":"","sources":["talerCrypto.ts"],"names":[],"mappings":"AAgBA;;GAEG;AAEH,OAAO,KAAK,IAAI,MAAM,wBAAwB,CAAC;AAgB/C,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,UAAU,CAEpD;AA6CD,wBAAgB,WAAW,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAuBrD;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,CA0BvD;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,UAAU,GAAG,UAAU,CAGhE;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,UAAU,GAAG,UAAU,CAEhE;AAED,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,UAAU,EACrB,QAAQ,EAAE,UAAU,GACnB,UAAU,CAQZ;AAED,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,UAAU,EACrB,QAAQ,EAAE,UAAU,GACnB,UAAU,CAIZ;AAwCD,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,UAAU,CAEnD;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,UAAU,GAAG,MAAM,CAEnD;AAuED,wBAAgB,QAAQ,CACtB,EAAE,EAAE,UAAU,EACd,GAAG,EAAE,UAAU,EACf,SAAS,EAAE,UAAU,GACpB,UAAU,CAOZ;AAED,wBAAgB,UAAU,CACxB,GAAG,EAAE,UAAU,EACf,SAAS,EAAE,UAAU,EACrB,GAAG,EAAE,UAAU,GACd,UAAU,CAOZ;AAED,wBAAgB,SAAS,CACvB,EAAE,EAAE,UAAU,EACd,MAAM,EAAE,UAAU,EAClB,SAAS,EAAE,UAAU,GACpB,OAAO,CAMT;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,UAAU,CAAC;IACrB,SAAS,EAAE,UAAU,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,UAAU,CAAC;IACrB,SAAS,EAAE,UAAU,CAAC;CACvB;AAED,wBAAgB,kBAAkB,IAAI,YAAY,CAIjD;AAED,wBAAgB,kBAAkB,IAAI,YAAY,CAIjD;AAED,wBAAgB,uBAAuB,IAAI,UAAU,CAEpD;AAED,wBAAgB,IAAI,CAAC,CAAC,EAAE,UAAU,GAAG,UAAU,CAE9C;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,GAAG,UAAU,CAG5E;AAED,wBAAgB,WAAW,CACzB,GAAG,EAAE,UAAU,EACf,GAAG,EAAE,UAAU,EACf,QAAQ,EAAE,UAAU,GACnB,OAAO,CAET;AAED,wBAAgB,iBAAiB,IAAI,IAAI,CAAC,SAAS,CAElD;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,UAAU,CAAC;IACpB,QAAQ,EAAE,UAAU,CAAC;IACrB,GAAG,EAAE,UAAU,CAAC;CACjB;AAED,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,UAAU,EACtB,UAAU,EAAE,MAAM,GACjB,SAAS,CAcX"}
|
@ -22,6 +22,18 @@ import * as nacl from "./primitives/nacl-fast";
|
|||||||
import bigint from "big-integer";
|
import bigint from "big-integer";
|
||||||
import { kdf } from "./primitives/kdf";
|
import { kdf } from "./primitives/kdf";
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
const decoder = new TextDecoder();
|
||||||
|
if (typeof decoder !== "object") {
|
||||||
|
throw Error("FATAL: TextDecoder not available");
|
||||||
|
}
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
const encoder = new TextEncoder();
|
||||||
|
if (typeof encoder !== "object") {
|
||||||
|
throw Error("FATAL: TextEncoder not available");
|
||||||
|
}
|
||||||
|
|
||||||
export function getRandomBytes(n: number): Uint8Array {
|
export function getRandomBytes(n: number): Uint8Array {
|
||||||
return nacl.randomBytes(n);
|
return nacl.randomBytes(n);
|
||||||
}
|
}
|
||||||
@ -192,8 +204,11 @@ function kdfMod(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function stringToBytes(s: string): Uint8Array {
|
export function stringToBytes(s: string): Uint8Array {
|
||||||
const te = new TextEncoder();
|
return encoder.encode(s);
|
||||||
return te.encode(s);
|
}
|
||||||
|
|
||||||
|
export function bytesToString(b: Uint8Array): string {
|
||||||
|
return decoder.decode(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadBigInt(arr: Uint8Array): bigint.BigInteger {
|
function loadBigInt(arr: Uint8Array): bigint.BigInteger {
|
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"cryptoApi.d.ts","sourceRoot":"","sources":["cryptoApi.ts"],"names":[],"mappings":"AAgBA;;;GAGG;AAEH;;GAEG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD,OAAO,EACL,UAAU,EACV,kBAAkB,EAClB,oBAAoB,EACpB,WAAW,EACX,OAAO,EACP,yBAAyB,EAC1B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAE9E,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,uBAAuB,EACvB,WAAW,EACZ,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,KAAK,MAAM,kBAAkB,CAAC;AAK1C;;GAEG;AACH,UAAU,WAAW;IACnB;;OAEG;IACH,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IAEvB;;OAEG;IACH,eAAe,EAAE,QAAQ,GAAG,IAAI,CAAC;IAEjC;;OAEG;IACH,sBAAsB,EAAE,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC;CAClD;AAED,UAAU,QAAQ;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,OAAO,EAAE,GAAG,CAAC;IACb,MAAM,EAAE,GAAG,CAAC;IAEZ;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;CACnB;AAQD,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,WAAW,IAAI,YAAY,CAAC;IAE5B;;;OAGG;IACH,cAAc,IAAI,MAAM,CAAC;CAC1B;AAED;;;GAGG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,UAAU,CAAe;IAEjC,OAAO,CAAC,aAAa,CAAsB;IAE3C;;OAEG;IACH,OAAO,CAAC,OAAO,CAAK;IAEpB;;OAEG;IACH,OAAO,CAAC,OAAO,CAAS;IAExB;;OAEG;IACH,gBAAgB,IAAI,IAAI;IAkBxB,IAAI,IAAI,IAAI;IAKZ;;OAEG;IACH,IAAI,CAAC,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,GAAG,IAAI;IA8B3C,kBAAkB,CAAC,EAAE,EAAE,WAAW,GAAG,IAAI;IAezC,iBAAiB,CAAC,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,GAAG,GAAG,IAAI;IA0BhD,OAAO,CAAC,QAAQ;IAehB,mBAAmB,CAAC,EAAE,EAAE,WAAW,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI;gBAsBxC,aAAa,EAAE,mBAAmB;IAkB9C,OAAO,CAAC,KAAK;IAuCb,cAAc,CACZ,GAAG,EAAE,uBAAuB,GAC3B,OAAO,CAAC,sBAAsB,CAAC;IAIlC,iBAAiB,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,WAAW,CAAC;IAIlE,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIxC,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIlD,YAAY,CAAC,KAAK,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI5E,cAAc,CACZ,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,OAAO,EACX,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC;IAInB,uBAAuB,CACrB,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,OAAO,CAAC;IAUnB,qBAAqB,CACnB,WAAW,EAAE,WAAW,GACvB,OAAO,CAAC,qBAAqB,CAAC;IAQjC,kBAAkB,IAAI,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAI5D,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIhE,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIhE,kBAAkB,CAChB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC;IAUnB,mBAAmB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC;IAI7D,oBAAoB,CAClB,eAAe,EAAE,MAAM,EACvB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,UAAU,EACpB,aAAa,EAAE,yBAAyB,EACxC,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,oBAAoB,CAAC;IAYhC,YAAY,CACV,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC;IAYlB,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;CAGzD"}
|
@ -105,27 +105,6 @@ export interface CryptoWorkerFactory {
|
|||||||
getConcurrency(): number;
|
getConcurrency(): number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class BrowserCryptoWorkerFactory implements CryptoWorkerFactory {
|
|
||||||
startWorker(): CryptoWorker {
|
|
||||||
const workerCtor = Worker;
|
|
||||||
const workerPath = "/browserWorkerEntry.js";
|
|
||||||
return new workerCtor(workerPath) as CryptoWorker;
|
|
||||||
}
|
|
||||||
|
|
||||||
getConcurrency(): number {
|
|
||||||
let concurrency = 2;
|
|
||||||
try {
|
|
||||||
// only works in the browser
|
|
||||||
// tslint:disable-next-line:no-string-literal
|
|
||||||
concurrency = (navigator as any)["hardwareConcurrency"];
|
|
||||||
concurrency = Math.max(1, Math.ceil(concurrency / 2));
|
|
||||||
} catch (e) {
|
|
||||||
concurrency = 2;
|
|
||||||
}
|
|
||||||
return concurrency;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Crypto API that interfaces manages a background crypto thread
|
* Crypto API that interfaces manages a background crypto thread
|
||||||
* for the execution of expensive operations.
|
* for the execution of expensive operations.
|
||||||
@ -189,8 +168,8 @@ export class CryptoApi {
|
|||||||
let worker: CryptoWorker;
|
let worker: CryptoWorker;
|
||||||
if (!ws.w) {
|
if (!ws.w) {
|
||||||
worker = this.workerFactory.startWorker();
|
worker = this.workerFactory.startWorker();
|
||||||
worker.onmessage = (m: MessageEvent) => this.handleWorkerMessage(ws, m);
|
worker.onmessage = (m: any) => this.handleWorkerMessage(ws, m);
|
||||||
worker.onerror = (e: ErrorEvent) => this.handleWorkerError(ws, e);
|
worker.onerror = (e: any) => this.handleWorkerError(ws, e);
|
||||||
ws.w = worker;
|
ws.w = worker;
|
||||||
} else {
|
} else {
|
||||||
worker = ws.w;
|
worker = ws.w;
|
||||||
@ -221,7 +200,7 @@ export class CryptoApi {
|
|||||||
ws.terminationTimerHandle = timer.after(15 * 1000, destroy);
|
ws.terminationTimerHandle = timer.after(15 * 1000, destroy);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleWorkerError(ws: WorkerState, e: ErrorEvent): void {
|
handleWorkerError(ws: WorkerState, e: any): void {
|
||||||
if (ws.currentWorkItem) {
|
if (ws.currentWorkItem) {
|
||||||
console.error(
|
console.error(
|
||||||
`error in worker during ${ws.currentWorkItem.operation}`,
|
`error in worker during ${ws.currentWorkItem.operation}`,
|
||||||
@ -262,7 +241,7 @@ export class CryptoApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleWorkerMessage(ws: WorkerState, msg: MessageEvent): void {
|
handleWorkerMessage(ws: WorkerState, msg: any): void {
|
||||||
const id = msg.data.id;
|
const id = msg.data.id;
|
||||||
if (typeof id !== "number") {
|
if (typeof id !== "number") {
|
||||||
console.error("rpc id must be number");
|
console.error("rpc id must be number");
|
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"cryptoImplementation.d.ts","sourceRoot":"","sources":["cryptoImplementation.ts"],"names":[],"mappings":"AAgBA;;;;;;GAMG;AAEH;;GAEG;AAEH,OAAO,EACL,UAAU,EACV,kBAAkB,EAElB,oBAAoB,EACpB,WAAW,EACX,OAAO,EAEP,yBAAyB,EAC1B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,uBAAuB,EACvB,WAAW,EACZ,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,UAAU,EAAW,MAAM,oBAAoB,CAAC;AAgGzD,qBAAa,oBAAoB;IAC/B,MAAM,CAAC,aAAa,UAAS;IAE7B;;;OAGG;IACH,cAAc,CAAC,GAAG,EAAE,uBAAuB,GAAG,sBAAsB;IAoCpE;;OAEG;IACH,iBAAiB,CAAC,KAAK,EAAE,kBAAkB,GAAG,WAAW;IAmBzD;;OAEG;IACH,mBAAmB,CAAC,IAAI,EAAE,UAAU,GAAG,aAAa;IAoBpD;;OAEG;IACH,uBAAuB,CACrB,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,GAClB,OAAO;IASV;;OAEG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO;IAarE;;OAEG;IACH,YAAY,CAAC,KAAK,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO;IAmBnE,kBAAkB,CAChB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,GAChB,OAAO;IAWV;;OAEG;IACH,kBAAkB,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE;IAQnD;;OAEG;IACH,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM;IAS9D;;OAEG;IACH,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO;IAIvD;;;OAGG;IACH,qBAAqB,CAAC,WAAW,EAAE,WAAW,GAAG,qBAAqB;IAyBtE;;OAEG;IACH,oBAAoB,CAClB,eAAe,EAAE,MAAM,EACvB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,UAAU,EACpB,aAAa,EAAE,yBAAyB,EACxC,OAAO,EAAE,UAAU,GAClB,oBAAoB;IA2HvB;;OAEG;IACH,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAK/B;;OAEG;IACH,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAIzC,YAAY,CACV,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GACb,MAAM;IAaT,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,eAAe;CAsDhD"}
|
@ -90,8 +90,7 @@ function amountToBuffer(amount: AmountJson): Uint8Array {
|
|||||||
const buffer = new ArrayBuffer(8 + 4 + 12);
|
const buffer = new ArrayBuffer(8 + 4 + 12);
|
||||||
const dvbuf = new DataView(buffer);
|
const dvbuf = new DataView(buffer);
|
||||||
const u8buf = new Uint8Array(buffer);
|
const u8buf = new Uint8Array(buffer);
|
||||||
const te = new TextEncoder();
|
const curr = stringToBytes(amount.currency);
|
||||||
const curr = te.encode(amount.currency);
|
|
||||||
dvbuf.setBigUint64(0, BigInt(amount.value));
|
dvbuf.setBigUint64(0, BigInt(amount.value));
|
||||||
dvbuf.setUint32(8, amount.fraction);
|
dvbuf.setUint32(8, amount.fraction);
|
||||||
u8buf.set(curr, 8 + 4);
|
u8buf.set(curr, 8 + 4);
|
||||||
@ -493,8 +492,7 @@ export class CryptoImplementation {
|
|||||||
* Hash a string including the zero terminator.
|
* Hash a string including the zero terminator.
|
||||||
*/
|
*/
|
||||||
hashString(str: string): string {
|
hashString(str: string): string {
|
||||||
const ts = new TextEncoder();
|
const b = stringToBytes(str + "\0");
|
||||||
const b = ts.encode(str + "\0");
|
|
||||||
return encodeCrock(hash(b));
|
return encodeCrock(hash(b));
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"cryptoWorker.d.ts","sourceRoot":"","sources":["cryptoWorker.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,WAAW,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI,CAAC;IAEhC,SAAS,IAAI,IAAI,CAAC;IAElB,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC1C,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CACzC"}
|
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"nodeThreadWorker.d.ts","sourceRoot":"","sources":["nodeThreadWorker.ts"],"names":[],"mappings":"AAgBA;;GAEG;AACH,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAiC9C;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,CA6ClD;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI,CAEhD;AAED,qBAAa,6BAA8B,YAAW,mBAAmB;IACvE,WAAW,IAAI,YAAY;IAO3B,cAAc,IAAI,MAAM;CAGzB"}
|
@ -28,8 +28,7 @@ export class SynchronousCryptoWorkerFactory implements CryptoWorkerFactory {
|
|||||||
if (typeof require === "undefined") {
|
if (typeof require === "undefined") {
|
||||||
throw Error("cannot make worker, require(...) not defined");
|
throw Error("cannot make worker, require(...) not defined");
|
||||||
}
|
}
|
||||||
const workerCtor = require("./synchronousWorker").SynchronousCryptoWorker;
|
return new SynchronousCryptoWorker();
|
||||||
return new workerCtor();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getConcurrency(): number {
|
getConcurrency(): number {
|
@ -1,5 +1,6 @@
|
|||||||
import { Stores } from "./types/dbTypes";
|
import { Stores } from "./types/dbTypes";
|
||||||
import { openDatabase, Database, Store, Index } from "./util/query";
|
import { openDatabase, Database, Store, Index } from "./util/query";
|
||||||
|
import type { idbtypes } from "idb-bridge";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Name of the Taler database. The name includes the
|
* Name of the Taler database. The name includes the
|
||||||
@ -23,11 +24,11 @@ export const WALLET_DB_MINOR_VERSION = 1;
|
|||||||
* to the taler wallet db.
|
* to the taler wallet db.
|
||||||
*/
|
*/
|
||||||
export function openTalerDatabase(
|
export function openTalerDatabase(
|
||||||
idbFactory: IDBFactory,
|
idbFactory: idbtypes.IDBFactory,
|
||||||
onVersionChange: () => void,
|
onVersionChange: () => void,
|
||||||
): Promise<IDBDatabase> {
|
): Promise<idbtypes.IDBDatabase> {
|
||||||
const onUpgradeNeeded = (
|
const onUpgradeNeeded = (
|
||||||
db: IDBDatabase,
|
db: idbtypes.IDBDatabase,
|
||||||
oldVersion: number,
|
oldVersion: number,
|
||||||
newVersion: number,
|
newVersion: number,
|
||||||
): void => {
|
): void => {
|
||||||
@ -60,6 +61,6 @@ export function openTalerDatabase(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function deleteTalerDatabase(idbFactory: IDBFactory): void {
|
export function deleteTalerDatabase(idbFactory: idbtypes.IDBFactory): void {
|
||||||
Database.deleteDatabase(idbFactory, TALER_DB_NAME);
|
Database.deleteDatabase(idbFactory, TALER_DB_NAME);
|
||||||
}
|
}
|
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"NodeHttpLib.d.ts","sourceRoot":"","sources":["NodeHttpLib.ts"],"names":[],"mappings":"AAkBA;;GAEG;AACH,OAAO,EAEL,kBAAkB,EAClB,kBAAkB,EAClB,YAAY,EACb,MAAM,cAAc,CAAC;AAMtB;;GAEG;AACH,qBAAa,WAAY,YAAW,kBAAkB;IACpD,OAAO,CAAC,QAAQ,CAA0B;IAC1C,OAAO,CAAC,iBAAiB,CAAQ;IAEjC;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;YAIvB,GAAG;IA2EX,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,YAAY,CAAC;IAIjE,QAAQ,CACZ,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,GAAG,EACT,GAAG,CAAC,EAAE,kBAAkB,GACvB,OAAO,CAAC,YAAY,CAAC;CAGzB"}
|
@ -33,6 +33,7 @@ import { Database } from "../util/query";
|
|||||||
import { NodeHttpLib } from "./NodeHttpLib";
|
import { NodeHttpLib } from "./NodeHttpLib";
|
||||||
import { Logger } from "../util/logging";
|
import { Logger } from "../util/logging";
|
||||||
import { SynchronousCryptoWorkerFactory } from "../crypto/workers/synchronousWorker";
|
import { SynchronousCryptoWorkerFactory } from "../crypto/workers/synchronousWorker";
|
||||||
|
import type { IDBFactory } from "idb-bridge/lib/idbtypes";
|
||||||
|
|
||||||
const logger = new Logger("headless/helpers.ts");
|
const logger = new Logger("headless/helpers.ts");
|
||||||
|
|
78
packages/taler-wallet-core/src/i18n/index.ts
Normal file
78
packages/taler-wallet-core/src/i18n/index.ts
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
This file is part of TALER
|
||||||
|
(C) 2016 GNUnet e.V.
|
||||||
|
|
||||||
|
TALER is free software; you can redistribute it and/or modify it under the
|
||||||
|
terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation; either version 3, or (at your option) any later version.
|
||||||
|
|
||||||
|
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with
|
||||||
|
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translation helpers for React components and template literals.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Imports.
|
||||||
|
*/
|
||||||
|
import { strings } from "./strings";
|
||||||
|
export { strings } from "./strings";
|
||||||
|
|
||||||
|
// @ts-ignore: no type decl for this library
|
||||||
|
import * as jedLib from "jed";
|
||||||
|
|
||||||
|
export let jed: any = undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up jed library for internationalization,
|
||||||
|
* based on browser language settings.
|
||||||
|
*/
|
||||||
|
export function setupI18n(lang: string): any {
|
||||||
|
lang = lang.replace("_", "-");
|
||||||
|
|
||||||
|
if (!strings[lang]) {
|
||||||
|
lang = "en-US";
|
||||||
|
console.log(`language ${lang} not found, defaulting to english`);
|
||||||
|
}
|
||||||
|
jed = new jedLib.Jed(strings[lang]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use different translations for testing. Should not be used outside
|
||||||
|
* of test cases.
|
||||||
|
*/
|
||||||
|
export function internalSetStrings(langStrings: any): void {
|
||||||
|
jed = new jedLib.Jed(langStrings);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert template strings to a msgid
|
||||||
|
*/
|
||||||
|
function toI18nString(stringSeq: ReadonlyArray<string>): string {
|
||||||
|
let s = "";
|
||||||
|
for (let i = 0; i < stringSeq.length; i++) {
|
||||||
|
s += stringSeq[i];
|
||||||
|
if (i < stringSeq.length - 1) {
|
||||||
|
s += `%${i + 1}$s`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internationalize a string template with arbitrary serialized values.
|
||||||
|
*/
|
||||||
|
export function str(stringSeq: TemplateStringsArray, ...values: any[]): string {
|
||||||
|
const s = toI18nString(stringSeq);
|
||||||
|
const tr = jed
|
||||||
|
.translate(s)
|
||||||
|
.ifPlural(1, s)
|
||||||
|
.fetch(...values);
|
||||||
|
return tr;
|
||||||
|
}
|
75
packages/taler-wallet-core/src/index.ts
Normal file
75
packages/taler-wallet-core/src/index.ts
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
This file is part of TALER
|
||||||
|
(C) 2019 GNUnet e.V.
|
||||||
|
|
||||||
|
TALER is free software; you can redistribute it and/or modify it under the
|
||||||
|
terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation; either version 3, or (at your option) any later version.
|
||||||
|
|
||||||
|
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with
|
||||||
|
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module entry point for the wallet when used as a node module.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export { Wallet } from "./wallet";
|
||||||
|
export {
|
||||||
|
getDefaultNodeWallet,
|
||||||
|
DefaultNodeWalletArgs,
|
||||||
|
} from "./headless/helpers";
|
||||||
|
export { Amounts, AmountJson } from "./util/amounts";
|
||||||
|
export { Logger } from "./util/logging";
|
||||||
|
|
||||||
|
export * as talerCrypto from "./crypto/talerCrypto";
|
||||||
|
export {
|
||||||
|
OperationFailedAndReportedError,
|
||||||
|
OperationFailedError,
|
||||||
|
makeErrorDetails,
|
||||||
|
} from "./operations/errors";
|
||||||
|
|
||||||
|
export * as walletTypes from "./types/walletTypes";
|
||||||
|
|
||||||
|
export * as talerTypes from "./types/talerTypes";
|
||||||
|
|
||||||
|
export * as walletCoreApi from "./walletCoreApiHandler";
|
||||||
|
|
||||||
|
export * as taleruri from "./util/taleruri";
|
||||||
|
|
||||||
|
export * as time from "./util/time";
|
||||||
|
|
||||||
|
export * as codec from "./util/codec";
|
||||||
|
|
||||||
|
export { NodeHttpLib } from "./headless/NodeHttpLib";
|
||||||
|
|
||||||
|
export * as payto from "./util/payto";
|
||||||
|
|
||||||
|
export * as testvectors from "./util/testvectors";
|
||||||
|
|
||||||
|
export * as versions from "./operations/versions";
|
||||||
|
|
||||||
|
export type { CryptoWorker } from "./crypto/workers/cryptoWorker";
|
||||||
|
export type { CryptoWorkerFactory } from "./crypto/workers/cryptoApi";
|
||||||
|
|
||||||
|
export * as httpLib from "./util/http";
|
||||||
|
|
||||||
|
export { TalerErrorCode } from "./TalerErrorCode";
|
||||||
|
|
||||||
|
export * as queryLib from "./util/query";
|
||||||
|
|
||||||
|
export { CryptoImplementation } from "./crypto/workers/cryptoImplementation";
|
||||||
|
|
||||||
|
export * as db from "./db";
|
||||||
|
|
||||||
|
export * as promiseUtil from "./util/promiseUtils";
|
||||||
|
|
||||||
|
export * as i18n from "./i18n";
|
||||||
|
|
||||||
|
export * as nodeThreadWorker from "./crypto/workers/nodeThreadWorker";
|
||||||
|
|
||||||
|
export * as walletNotifications from "./types/notifications";
|
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"balance.d.ts","sourceRoot":"","sources":["balance.ts"],"names":[],"mappings":"AAgBA;;GAEG;AACH,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAc9C;;GAEG;AACH,wBAAsB,4BAA4B,CAChD,EAAE,EAAE,mBAAmB,EACvB,EAAE,EAAE,iBAAiB,GACpB,OAAO,CAAC,gBAAgB,CAAC,CAqF3B;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,EAAE,EAAE,mBAAmB,GACtB,OAAO,CAAC,gBAAgB,CAAC,CAmB3B"}
|
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["errors.ts"],"names":[],"mappings":"AAgBA;;;;GAIG;AAEH;;GAEG;AACH,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD;;;GAGG;AACH,qBAAa,+BAAgC,SAAQ,KAAK;IACrC,cAAc,EAAE,qBAAqB;gBAArC,cAAc,EAAE,qBAAqB;CAMzD;AAED;;;GAGG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;IAS1B,cAAc,EAAE,qBAAqB;IARxD,MAAM,CAAC,QAAQ,CACb,EAAE,EAAE,cAAc,EAClB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,oBAAoB;gBAIJ,cAAc,EAAE,qBAAqB;CAMzD;AAED,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,cAAc,EAClB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,qBAAqB,CAOvB;AAED;;;;GAIG;AACH,wBAAsB,uBAAuB,CAAC,CAAC,EAC7C,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,SAAS,EAAE,CAAC,CAAC,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,GACrD,OAAO,CAAC,CAAC,CAAC,CAqCZ"}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user