From 8881394bc11fea507e330a4c507ef304fe456c42 Mon Sep 17 00:00:00 2001 From: Alex <12097569+nialexsan@users.noreply.github.com> Date: Tue, 7 Nov 2023 08:08:24 -0500 Subject: [PATCH] Release typescript resolve conflict (#1801) * Nialexsan/add types (#1710) * switch to uuid from @onflow/utils-uid * create tsconfigs * typedefs in ts * types for actor util * types for address util * Revert "switch to uuid from @onflow/utils-uid" This reverts commit 2a15ef5d2d8f14a2302f2783d5ad8bef5a3f0ee8. * PKG -- [util-actor] converted to ts * updated tsconfig * fixed ts types generation * Resolve circular dependency * ts rlp * change type location * more types * build types during regular build * fix tests * VSN -- [root] Changeset * Merge remote-tracking branch 'origin/master' into nialexsan/add-types * Revert "Resolve circular dependency" This reverts commit 36efc7d3957b4952a7e2caea3113716f6204f5a0. * update lock * VSN -- [root] changeset * Implement typescript for several branches & adjust configuration (#1750) Implements typescript support for: @onflow/rlp, @onflow/util-uid, @onflow/util-template, @onflow/util-logger, @onflow/util-invariant, @onflow/util-encode-key, @onflow/util-address * Convert @onflow/types to TS (#1760) * [WIP] Convert @onflow/types to TS * stash * kind of working * fix package.json * fix dictionary * fix tests * stash * strong type tests * remove any * rename * changeset * PKG -- [util-actor] Enhance TS support (#1761) * PKG -- [util-actor] Enhance TS support * rename handlerfnmap * PKG -- [types] Simplify generics for @onflow/types (#1772) * PKG -- [types] Simplify generics * Fix array * Fix Array * PKG -- [config] Convert @onflow/config to TS (#1731) * PKG -- [config] Add TypeScript * Changeset * fixup * Remove unnecessary generic from util-actor * remove non null assertions --------- Co-authored-by: Alex <12097569+nialexsan@users.noreply.github.com> * Fix JSDoc type generation (#1780) * restore changeset * align packages * pre typescript * any type for config * update package lock * Update packages/util-logger/src/util-logger.ts * fix config type * use any type * exit pre * revert changes to changelogs --------- Co-authored-by: Jordan Ribbink --- .changeset/fifty-buttons-serve.md | 5 + .changeset/fluffy-yaks-allow.md | 5 + .changeset/giant-ducks-tickle.md | 11 + .changeset/hip-radios-behave.md | 21 + .changeset/pre.json | 33 + .changeset/tough-fishes-live.md | 5 + .changeset/wise-apples-leave.md | 5 + package-lock.json | 2066 ++++++++++++++--- package.json | 7 +- packages/config/.babelrc | 6 +- packages/config/.eslintrc.json | 18 +- packages/config/package.json | 21 +- .../src/{config.test.js => config.test.ts} | 16 +- packages/config/src/{config.js => config.ts} | 137 +- .../utils.test.js => src/utils/utils.test.ts} | 10 +- packages/config/src/utils/utils.ts | 222 ++ packages/config/tsconfig.json | 19 +- packages/config/utils/utils.js | 171 -- packages/fcl-bundle/package.json | 6 +- .../fcl-bundle/src/build/get-input-options.js | 42 +- packages/fcl-bundle/tsconfig.json | 11 + packages/fcl-wc/package.json | 12 +- packages/fcl-wc/tsconfig.json | 11 + packages/fcl/package.json | 30 +- packages/fcl/src/current-user/index.js | 351 +-- ...cl-react-native.js => fcl-react-native.ts} | 0 packages/fcl/src/{fcl.js => fcl.ts} | 5 +- packages/rlp/.babelrc | 6 +- packages/rlp/.eslintrc.json | 30 + packages/rlp/package.json | 13 +- .../rlp/src/{index.test.js => index.test.ts} | 0 packages/rlp/src/{index.js => index.ts} | 91 +- packages/rlp/tsconfig.json | 11 + packages/sdk/.babelrc | 3 +- packages/sdk/package.json | 25 +- .../sdk/src/resolve/resolve-accounts.test.js | 4 +- .../sdk/src/resolve/resolve-arguments.test.js | 2 +- .../src/resolve/resolve-signatures.test.js | 2 +- packages/sdk/src/sdk.test.js | 2 +- packages/sdk/src/{sdk.js => sdk.ts} | 6 +- packages/sdk/tsconfig.json | 19 +- packages/transport-grpc/package.json | 14 +- packages/transport-grpc/tsconfig.json | 11 + packages/transport-http/package.json | 18 +- packages/transport-http/tsconfig.json | 11 + packages/typedefs/package.json | 9 +- packages/typedefs/src/index.js | 117 - packages/typedefs/src/index.ts | 290 +++ packages/typedefs/tsconfig.json | 16 +- packages/types/.babelrc | 6 +- packages/types/.eslintrc.json | 34 + packages/types/package.json | 21 +- packages/types/src/types.test.js | 249 -- packages/types/src/types.test.ts | 251 ++ packages/types/src/{types.js => types.ts} | 404 ++-- packages/types/tsconfig.json | 11 + packages/util-actor/.babelrc | 3 +- packages/util-actor/.eslintrc.json | 23 + packages/util-actor/jest.config.ts | 8 + packages/util-actor/package.json | 16 +- packages/util-actor/src/index.js | 205 -- .../src/{index.test.js => index.test.ts} | 23 +- packages/util-actor/src/index.ts | 310 +++ packages/util-actor/src/mailbox/index.js | 22 - .../mailbox/{index.test.js => index.test.ts} | 20 +- packages/util-actor/src/mailbox/index.ts | 26 + packages/util-actor/tsconfig.json | 11 + packages/util-address/.babelrc | 6 +- packages/util-address/.eslintrc.json | 18 +- packages/util-address/package.json | 19 +- packages/util-address/src/index.js | 28 - .../src/{index.test.js => index.test.ts} | 0 packages/util-address/src/index.ts | 28 + packages/util-address/tsconfig.json | 16 +- packages/util-encode-key/.babelrc | 6 +- packages/util-encode-key/.eslintrc.json | 18 +- packages/util-encode-key/package.json | 23 +- ...{index.test.js.snap => index.test.ts.snap} | 0 .../src/{index.test.js => index.test.ts} | 16 +- .../src/{index.js => index.ts} | 44 +- packages/util-encode-key/tsconfig.json | 16 +- packages/util-invariant/.eslintrc.json | 20 + packages/util-invariant/package.json | 15 +- .../src/{index.test.js => index.test.ts} | 0 .../util-invariant/src/{index.js => index.ts} | 15 +- packages/util-invariant/tsconfig.json | 11 + packages/util-logger/.babelrc | 6 +- packages/util-logger/.eslintrc.json | 20 + packages/util-logger/package.json | 13 +- packages/util-logger/src/util-logger.js | 151 -- ...til-logger.test.js => util-logger.test.ts} | 0 packages/util-logger/src/util-logger.ts | 162 ++ packages/util-logger/tsconfig.json | 11 + packages/util-semver/package.json | 2 +- packages/util-template/.babelrc | 6 +- packages/util-template/.eslintrc.json | 20 + packages/util-template/package.json | 16 +- ...ate.test.js.snap => template.test.ts.snap} | 2 +- packages/util-template/src/template.js | 46 - .../{template.test.js => template.test.ts} | 24 +- packages/util-template/src/template.ts | 67 + packages/util-template/tsconfig.json | 12 + packages/util-uid/.babelrc | 6 +- packages/util-uid/.eslintrc.json | 20 + packages/util-uid/package.json | 13 +- packages/util-uid/src/util-uid.js | 13 - packages/util-uid/src/util-uid.test.js | 5 - packages/util-uid/src/util-uid.test.ts | 12 + packages/util-uid/src/util-uid.ts | 13 + packages/util-uid/tsconfig.json | 11 + tsconfig.json | 21 + 111 files changed, 4393 insertions(+), 2167 deletions(-) create mode 100644 .changeset/fifty-buttons-serve.md create mode 100644 .changeset/fluffy-yaks-allow.md create mode 100644 .changeset/giant-ducks-tickle.md create mode 100644 .changeset/hip-radios-behave.md create mode 100644 .changeset/pre.json create mode 100644 .changeset/tough-fishes-live.md create mode 100644 .changeset/wise-apples-leave.md rename packages/config/src/{config.test.js => config.test.ts} (95%) rename packages/config/src/{config.js => config.ts} (67%) rename packages/config/{utils/utils.test.js => src/utils/utils.test.ts} (96%) create mode 100644 packages/config/src/utils/utils.ts delete mode 100644 packages/config/utils/utils.js create mode 100644 packages/fcl-bundle/tsconfig.json create mode 100644 packages/fcl-wc/tsconfig.json rename packages/fcl/src/{fcl-react-native.js => fcl-react-native.ts} (100%) rename packages/fcl/src/{fcl.js => fcl.ts} (90%) create mode 100644 packages/rlp/.eslintrc.json rename packages/rlp/src/{index.test.js => index.test.ts} (100%) rename packages/rlp/src/{index.js => index.ts} (80%) create mode 100644 packages/rlp/tsconfig.json rename packages/sdk/src/{sdk.js => sdk.ts} (97%) create mode 100644 packages/transport-grpc/tsconfig.json create mode 100644 packages/transport-http/tsconfig.json delete mode 100644 packages/typedefs/src/index.js create mode 100644 packages/typedefs/src/index.ts create mode 100644 packages/types/.eslintrc.json delete mode 100644 packages/types/src/types.test.js create mode 100644 packages/types/src/types.test.ts rename packages/types/src/{types.js => types.ts} (58%) create mode 100644 packages/types/tsconfig.json create mode 100644 packages/util-actor/.eslintrc.json create mode 100644 packages/util-actor/jest.config.ts delete mode 100644 packages/util-actor/src/index.js rename packages/util-actor/src/{index.test.js => index.test.ts} (86%) create mode 100644 packages/util-actor/src/index.ts delete mode 100644 packages/util-actor/src/mailbox/index.js rename packages/util-actor/src/mailbox/{index.test.js => index.test.ts} (51%) create mode 100644 packages/util-actor/src/mailbox/index.ts create mode 100644 packages/util-actor/tsconfig.json delete mode 100644 packages/util-address/src/index.js rename packages/util-address/src/{index.test.js => index.test.ts} (100%) create mode 100644 packages/util-address/src/index.ts rename packages/util-encode-key/src/__snapshots__/{index.test.js.snap => index.test.ts.snap} (100%) rename packages/util-encode-key/src/{index.test.js => index.test.ts} (69%) rename packages/util-encode-key/src/{index.js => index.ts} (76%) create mode 100644 packages/util-invariant/.eslintrc.json rename packages/util-invariant/src/{index.test.js => index.test.ts} (100%) rename packages/util-invariant/src/{index.js => index.ts} (55%) create mode 100644 packages/util-invariant/tsconfig.json create mode 100644 packages/util-logger/.eslintrc.json delete mode 100644 packages/util-logger/src/util-logger.js rename packages/util-logger/src/{util-logger.test.js => util-logger.test.ts} (100%) create mode 100644 packages/util-logger/src/util-logger.ts create mode 100644 packages/util-logger/tsconfig.json create mode 100644 packages/util-template/.eslintrc.json rename packages/util-template/src/__snapshots__/{template.test.js.snap => template.test.ts.snap} (94%) delete mode 100644 packages/util-template/src/template.js rename packages/util-template/src/{template.test.js => template.test.ts} (72%) create mode 100644 packages/util-template/src/template.ts create mode 100644 packages/util-template/tsconfig.json create mode 100644 packages/util-uid/.eslintrc.json delete mode 100644 packages/util-uid/src/util-uid.js delete mode 100644 packages/util-uid/src/util-uid.test.js create mode 100644 packages/util-uid/src/util-uid.test.ts create mode 100644 packages/util-uid/src/util-uid.ts create mode 100644 packages/util-uid/tsconfig.json create mode 100644 tsconfig.json diff --git a/.changeset/fifty-buttons-serve.md b/.changeset/fifty-buttons-serve.md new file mode 100644 index 000000000..31966c74d --- /dev/null +++ b/.changeset/fifty-buttons-serve.md @@ -0,0 +1,5 @@ +--- +"@onflow/fcl-bundle": minor +--- + +Switched to rollup-plugin-typescript2 diff --git a/.changeset/fluffy-yaks-allow.md b/.changeset/fluffy-yaks-allow.md new file mode 100644 index 000000000..dd6cc2c28 --- /dev/null +++ b/.changeset/fluffy-yaks-allow.md @@ -0,0 +1,5 @@ +--- +"@onflow/types": minor +--- + +Convert @onflow/types to TypeScript diff --git a/.changeset/giant-ducks-tickle.md b/.changeset/giant-ducks-tickle.md new file mode 100644 index 000000000..c93bc0d3f --- /dev/null +++ b/.changeset/giant-ducks-tickle.md @@ -0,0 +1,11 @@ +--- +"@onflow/util-encode-key": minor +"@onflow/util-invariant": minor +"@onflow/util-template": minor +"@onflow/util-address": minor +"@onflow/util-logger": minor +"@onflow/util-uid": minor +"@onflow/rlp": minor +--- + +Convert to Typescript diff --git a/.changeset/hip-radios-behave.md b/.changeset/hip-radios-behave.md new file mode 100644 index 000000000..96891888c --- /dev/null +++ b/.changeset/hip-radios-behave.md @@ -0,0 +1,21 @@ +--- +"@onflow/util-encode-key": minor +"@onflow/transport-grpc": minor +"@onflow/transport-http": minor +"@onflow/util-invariant": minor +"@onflow/util-template": minor +"@onflow/util-address": minor +"@onflow/util-logger": minor +"@onflow/fcl-bundle": minor +"@onflow/util-actor": minor +"@onflow/typedefs": minor +"@onflow/util-uid": minor +"@onflow/config": minor +"@onflow/fcl-wc": minor +"@onflow/types": minor +"@onflow/fcl": minor +"@onflow/rlp": minor +"@onflow/sdk": minor +--- + +TS build diff --git a/.changeset/pre.json b/.changeset/pre.json new file mode 100644 index 000000000..17708f11b --- /dev/null +++ b/.changeset/pre.json @@ -0,0 +1,33 @@ +{ + "mode": "exit", + "tag": "typescript", + "initialVersions": { + "@onflow/config": "1.1.2", + "@onflow/fcl": "1.7.0", + "@onflow/fcl-bundle": "1.3.1", + "@onflow/fcl-wc": "4.0.0", + "@onflow/protobuf": "1.2.1", + "@onflow/rlp": "1.1.0", + "@onflow/sdk": "1.2.3", + "@onflow/transport-grpc": "1.2.2", + "@onflow/transport-http": "1.7.2", + "@onflow/typedefs": "1.1.1", + "@onflow/types": "1.1.0", + "@onflow/util-actor": "1.2.0", + "@onflow/util-address": "1.1.0", + "@onflow/util-encode-key": "1.1.0", + "@onflow/util-invariant": "1.1.0", + "@onflow/util-logger": "1.2.2", + "@onflow/util-semver": "1.0.0", + "@onflow/util-template": "1.1.0", + "@onflow/util-uid": "1.1.0" + }, + "changesets": [ + "fifty-buttons-serve", + "fluffy-yaks-allow", + "giant-ducks-tickle", + "hip-radios-behave", + "tough-fishes-live", + "wise-apples-leave" + ] +} diff --git a/.changeset/tough-fishes-live.md b/.changeset/tough-fishes-live.md new file mode 100644 index 000000000..02a1a5d22 --- /dev/null +++ b/.changeset/tough-fishes-live.md @@ -0,0 +1,5 @@ +--- +"@onflow/config": minor +--- + +Add Typescript to @onflow/config diff --git a/.changeset/wise-apples-leave.md b/.changeset/wise-apples-leave.md new file mode 100644 index 000000000..efbbef93e --- /dev/null +++ b/.changeset/wise-apples-leave.md @@ -0,0 +1,5 @@ +--- +"@onflow/util-actor": minor +--- + +Enhance TS support for @onflow/util-actor diff --git a/package-lock.json b/package-lock.json index f1bcdc64b..a99a790d8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,17 +9,21 @@ "./packages/*" ], "devDependencies": { + "@babel/preset-typescript": "^7.22.5", "@changesets/changelog-github": "^0.4.4", "@changesets/cli": "^2.21.1", + "@types/jest": "^29.5.3", "@types/node": "^18.11.18", "jest": "^29.5.0", "jest-environment-jsdom": "^29.5.0", "lerna": "^6.6.2", - "prettier": "^2.6.2" + "prettier": "^2.6.2", + "ts-jest": "^29.1.1" } }, "node_modules/@aashutoshrathi/word-wrap": { "version": "1.2.6", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -170,13 +174,14 @@ "license": "ISC" }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.22.9", - "license": "MIT", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.15.tgz", + "integrity": "sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", "@babel/helper-environment-visitor": "^7.22.5", "@babel/helper-function-name": "^7.22.5", - "@babel/helper-member-expression-to-functions": "^7.22.5", + "@babel/helper-member-expression-to-functions": "^7.22.15", "@babel/helper-optimise-call-expression": "^7.22.5", "@babel/helper-replace-supers": "^7.22.9", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", @@ -234,8 +239,9 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.5", - "license": "MIT", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "engines": { "node": ">=6.9.0" } @@ -272,40 +278,43 @@ } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.22.5", - "license": "MIT", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", + "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.5", - "license": "MIT", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.22.5", - "license": "MIT", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", + "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-optimise-call-expression": { @@ -394,15 +403,17 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.5", - "license": "MIT", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.22.5", - "license": "MIT", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", + "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", "engines": { "node": ">=6.9.0" } @@ -801,7 +812,6 @@ }, "node_modules/@babel/plugin-syntax-jsx": { "version": "7.22.5", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -901,7 +911,6 @@ }, "node_modules/@babel/plugin-syntax-typescript": { "version": "7.22.5", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1132,10 +1141,11 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.22.5", - "license": "MIT", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.0.tgz", + "integrity": "sha512-32Xzss14/UVc7k9g775yMIvkVK8xwKE0DPdP5JTapr3+Z9w4tzeOuLNY6BXDQR6BdnzIlXnCGAzsk/ICHBLVWQ==", "dependencies": { - "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.0", "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-simple-access": "^7.22.5" }, @@ -1361,6 +1371,23 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.22.15.tgz", + "integrity": "sha512-1uirS0TnijxvQLnlv5wQBwOX3E1wCFX7ITv+9pBV2wKEk4K+M5tqDaoNXnTH8tjEIYHLO98MwiTWO04Ggz4XuA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-typescript": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-transform-unicode-escapes": { "version": "7.18.10", "license": "MIT", @@ -1496,6 +1523,24 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/preset-typescript": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.23.2.tgz", + "integrity": "sha512-u4UJc1XsS1GhIGteM8rnGiIvf9rJpiVgMEeCnwlLA7WJPC+jcXWJAGxYmeqs5hOZD8BbAfnV5ezBOxQbb4OUxA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.15", + "@babel/plugin-syntax-jsx": "^7.22.5", + "@babel/plugin-transform-modules-commonjs": "^7.23.0", + "@babel/plugin-transform-typescript": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/regjsgen": { "version": "0.8.0", "license": "MIT" @@ -1549,11 +1594,12 @@ } }, "node_modules/@babel/types": { - "version": "7.22.5", - "license": "MIT", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", "dependencies": { "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, "engines": { @@ -1930,6 +1976,7 @@ }, "node_modules/@es-joy/jsdoccomment": { "version": "0.36.1", + "dev": true, "license": "MIT", "dependencies": { "comment-parser": "1.3.1", @@ -1942,6 +1989,7 @@ }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", + "dev": true, "license": "MIT", "dependencies": { "eslint-visitor-keys": "^3.3.0" @@ -1955,6 +2003,7 @@ }, "node_modules/@eslint-community/regexpp": { "version": "4.6.2", + "dev": true, "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" @@ -1962,6 +2011,7 @@ }, "node_modules/@eslint/eslintrc": { "version": "2.1.2", + "dev": true, "license": "MIT", "dependencies": { "ajv": "^6.12.4", @@ -1983,10 +2033,12 @@ }, "node_modules/@eslint/eslintrc/node_modules/argparse": { "version": "2.0.1", + "dev": true, "license": "Python-2.0" }, "node_modules/@eslint/eslintrc/node_modules/js-yaml": { "version": "4.1.0", + "dev": true, "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -1996,8 +2048,10 @@ } }, "node_modules/@eslint/js": { - "version": "8.47.0", - "license": "MIT", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.52.0.tgz", + "integrity": "sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==", + "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } @@ -2008,10 +2062,12 @@ "license": "MIT" }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.10", - "license": "Apache-2.0", + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", + "@humanwhocodes/object-schema": "^2.0.1", "debug": "^4.1.1", "minimatch": "^3.0.5" }, @@ -2021,6 +2077,7 @@ }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", + "dev": true, "license": "Apache-2.0", "engines": { "node": ">=12.22" @@ -2031,8 +2088,10 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "license": "BSD-3-Clause" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "dev": true }, "node_modules/@hutson/parse-repository-url": { "version": "3.0.2", @@ -3679,6 +3738,7 @@ }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", + "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", @@ -3690,6 +3750,7 @@ }, "node_modules/@nodelib/fs.stat": { "version": "2.0.5", + "dev": true, "license": "MIT", "engines": { "node": ">= 8" @@ -3697,6 +3758,7 @@ }, "node_modules/@nodelib/fs.walk": { "version": "1.2.8", + "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", @@ -5159,6 +5221,16 @@ "@types/istanbul-lib-report": "*" } }, + "node_modules/@types/jest": { + "version": "29.5.7", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.7.tgz", + "integrity": "sha512-HLyetab6KVPSiF+7pFcUyMeLsx25LDNDemw9mGsJBkai/oouwrjTycocSDYopMEwFhN2Y4s9oPyOCZNofgSt2g==", + "dev": true, + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, "node_modules/@types/jsdom": { "version": "20.0.1", "dev": true, @@ -5240,121 +5312,383 @@ "dev": true, "license": "MIT" }, - "node_modules/@walletconnect/core": { - "version": "2.8.1", - "license": "Apache-2.0", + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.9.1", + "dev": true, + "license": "MIT", "dependencies": { - "@walletconnect/heartbeat": "1.2.1", - "@walletconnect/jsonrpc-provider": "1.0.13", - "@walletconnect/jsonrpc-types": "1.0.3", - "@walletconnect/jsonrpc-utils": "1.0.8", - "@walletconnect/jsonrpc-ws-connection": "^1.0.11", - "@walletconnect/keyvaluestorage": "^1.0.2", - "@walletconnect/logger": "^2.0.1", - "@walletconnect/relay-api": "^1.0.9", - "@walletconnect/relay-auth": "^1.0.4", - "@walletconnect/safe-json": "^1.0.2", - "@walletconnect/time": "^1.0.2", - "@walletconnect/types": "2.8.1", - "@walletconnect/utils": "2.8.1", - "events": "^3.3.0", - "lodash.isequal": "4.5.0", - "uint8arrays": "^3.1.0" + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.9.1", + "@typescript-eslint/type-utils": "6.9.1", + "@typescript-eslint/utils": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@walletconnect/core/node_modules/@walletconnect/safe-json": { - "version": "1.0.2", - "license": "MIT", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/lru-cache": { + "version": "6.0.0", + "dev": true, + "license": "ISC", "dependencies": { - "tslib": "1.14.1" + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@walletconnect/core/node_modules/tslib": { - "version": "1.14.1", - "license": "0BSD" - }, - "node_modules/@walletconnect/environment": { - "version": "1.0.1", - "license": "MIT", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.5.4", + "dev": true, + "license": "ISC", "dependencies": { - "tslib": "1.14.1" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@walletconnect/environment/node_modules/tslib": { - "version": "1.14.1", - "license": "0BSD" - }, - "node_modules/@walletconnect/events": { - "version": "1.0.1", - "license": "MIT", + "node_modules/@typescript-eslint/parser": { + "version": "6.9.1", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "keyvaluestorage-interface": "^1.0.0", - "tslib": "1.14.1" + "@typescript-eslint/scope-manager": "6.9.1", + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/typescript-estree": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@walletconnect/events/node_modules/tslib": { - "version": "1.14.1", - "license": "0BSD" - }, - "node_modules/@walletconnect/heartbeat": { - "version": "1.2.1", + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.9.1", + "dev": true, "license": "MIT", "dependencies": { - "@walletconnect/events": "^1.0.1", - "@walletconnect/time": "^1.0.2", - "tslib": "1.14.1" + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@walletconnect/heartbeat/node_modules/tslib": { - "version": "1.14.1", - "license": "0BSD" - }, - "node_modules/@walletconnect/jsonrpc-provider": { - "version": "1.0.13", + "node_modules/@typescript-eslint/type-utils": { + "version": "6.9.1", + "dev": true, "license": "MIT", "dependencies": { - "@walletconnect/jsonrpc-utils": "^1.0.8", - "@walletconnect/safe-json": "^1.0.2", - "tslib": "1.14.1" + "@typescript-eslint/typescript-estree": "6.9.1", + "@typescript-eslint/utils": "6.9.1", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@walletconnect/jsonrpc-provider/node_modules/@walletconnect/safe-json": { - "version": "1.0.2", + "node_modules/@typescript-eslint/types": { + "version": "6.9.1", + "dev": true, "license": "MIT", - "dependencies": { - "tslib": "1.14.1" + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@walletconnect/jsonrpc-provider/node_modules/tslib": { - "version": "1.14.1", - "license": "0BSD" - }, - "node_modules/@walletconnect/jsonrpc-types": { - "version": "1.0.3", - "license": "MIT", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.9.1", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "keyvaluestorage-interface": "^1.0.0", - "tslib": "1.14.1" + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@walletconnect/jsonrpc-types/node_modules/tslib": { - "version": "1.14.1", - "license": "0BSD" - }, - "node_modules/@walletconnect/jsonrpc-utils": { - "version": "1.0.8", - "license": "MIT", + "node_modules/@typescript-eslint/typescript-estree/node_modules/lru-cache": { + "version": "6.0.0", + "dev": true, + "license": "ISC", "dependencies": { - "@walletconnect/environment": "^1.0.1", - "@walletconnect/jsonrpc-types": "^1.0.3", - "tslib": "1.14.1" + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@walletconnect/jsonrpc-utils/node_modules/tslib": { - "version": "1.14.1", - "license": "0BSD" - }, - "node_modules/@walletconnect/jsonrpc-ws-connection": { + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.5.4", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "6.9.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.9.1", + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/typescript-estree": "6.9.1", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/lru-cache": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.5.4", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.9.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "6.9.1", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/@walletconnect/core": { + "version": "2.8.1", + "license": "Apache-2.0", + "dependencies": { + "@walletconnect/heartbeat": "1.2.1", + "@walletconnect/jsonrpc-provider": "1.0.13", + "@walletconnect/jsonrpc-types": "1.0.3", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/jsonrpc-ws-connection": "^1.0.11", + "@walletconnect/keyvaluestorage": "^1.0.2", + "@walletconnect/logger": "^2.0.1", + "@walletconnect/relay-api": "^1.0.9", + "@walletconnect/relay-auth": "^1.0.4", + "@walletconnect/safe-json": "^1.0.2", + "@walletconnect/time": "^1.0.2", + "@walletconnect/types": "2.8.1", + "@walletconnect/utils": "2.8.1", + "events": "^3.3.0", + "lodash.isequal": "4.5.0", + "uint8arrays": "^3.1.0" + } + }, + "node_modules/@walletconnect/core/node_modules/@walletconnect/safe-json": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/core/node_modules/tslib": { + "version": "1.14.1", + "license": "0BSD" + }, + "node_modules/@walletconnect/environment": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/environment/node_modules/tslib": { + "version": "1.14.1", + "license": "0BSD" + }, + "node_modules/@walletconnect/events": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "keyvaluestorage-interface": "^1.0.0", + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/events/node_modules/tslib": { + "version": "1.14.1", + "license": "0BSD" + }, + "node_modules/@walletconnect/heartbeat": { + "version": "1.2.1", + "license": "MIT", + "dependencies": { + "@walletconnect/events": "^1.0.1", + "@walletconnect/time": "^1.0.2", + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/heartbeat/node_modules/tslib": { + "version": "1.14.1", + "license": "0BSD" + }, + "node_modules/@walletconnect/jsonrpc-provider": { + "version": "1.0.13", + "license": "MIT", + "dependencies": { + "@walletconnect/jsonrpc-utils": "^1.0.8", + "@walletconnect/safe-json": "^1.0.2", + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/jsonrpc-provider/node_modules/@walletconnect/safe-json": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/jsonrpc-provider/node_modules/tslib": { + "version": "1.14.1", + "license": "0BSD" + }, + "node_modules/@walletconnect/jsonrpc-types": { + "version": "1.0.3", + "license": "MIT", + "dependencies": { + "keyvaluestorage-interface": "^1.0.0", + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/jsonrpc-types/node_modules/tslib": { + "version": "1.14.1", + "license": "0BSD" + }, + "node_modules/@walletconnect/jsonrpc-utils": { + "version": "1.0.8", + "license": "MIT", + "dependencies": { + "@walletconnect/environment": "^1.0.1", + "@walletconnect/jsonrpc-types": "^1.0.3", + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/jsonrpc-utils/node_modules/tslib": { + "version": "1.14.1", + "license": "0BSD" + }, + "node_modules/@walletconnect/jsonrpc-ws-connection": { "version": "1.0.11", "license": "MIT", "dependencies": { @@ -5779,6 +6113,7 @@ }, "node_modules/acorn-jsx": { "version": "5.3.2", + "dev": true, "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" @@ -5835,6 +6170,7 @@ }, "node_modules/ajv": { "version": "6.12.6", + "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -6387,6 +6723,7 @@ }, "node_modules/brace-expansion": { "version": "1.1.11", + "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -6446,6 +6783,17 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/bs-logger": { + "version": "0.2.6", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/bser": { "version": "2.1.1", "dev": true, @@ -6578,6 +6926,7 @@ }, "node_modules/callsites": { "version": "3.1.0", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -6838,6 +7187,7 @@ }, "node_modules/comment-parser": { "version": "1.3.1", + "dev": true, "license": "MIT", "engines": { "node": ">= 12.0.0" @@ -6874,6 +7224,7 @@ }, "node_modules/concat-map": { "version": "0.0.1", + "dev": true, "license": "MIT" }, "node_modules/concat-stream": { @@ -7595,6 +7946,7 @@ }, "node_modules/cross-spawn": { "version": "7.0.3", + "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -7794,6 +8146,7 @@ }, "node_modules/deep-is": { "version": "0.1.4", + "dev": true, "license": "MIT" }, "node_modules/deepmerge": { @@ -7933,6 +8286,7 @@ }, "node_modules/doctrine": { "version": "3.0.0", + "dev": true, "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" @@ -8294,16 +8648,19 @@ } }, "node_modules/eslint": { - "version": "8.47.0", - "license": "MIT", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz", + "integrity": "sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==", + "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "^8.47.0", - "@humanwhocodes/config-array": "^0.11.10", + "@eslint/js": "8.52.0", + "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -8403,6 +8760,7 @@ }, "node_modules/eslint-scope": { "version": "7.2.2", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", @@ -8417,6 +8775,7 @@ }, "node_modules/eslint-visitor-keys": { "version": "3.4.3", + "dev": true, "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -8427,6 +8786,7 @@ }, "node_modules/eslint/node_modules/ansi-styles": { "version": "4.3.0", + "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -8440,10 +8800,12 @@ }, "node_modules/eslint/node_modules/argparse": { "version": "2.0.1", + "dev": true, "license": "Python-2.0" }, "node_modules/eslint/node_modules/chalk": { "version": "4.1.2", + "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", @@ -8458,6 +8820,7 @@ }, "node_modules/eslint/node_modules/color-convert": { "version": "2.0.1", + "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -8468,10 +8831,12 @@ }, "node_modules/eslint/node_modules/color-name": { "version": "1.1.4", + "dev": true, "license": "MIT" }, "node_modules/eslint/node_modules/escape-string-regexp": { "version": "4.0.0", + "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -8482,6 +8847,7 @@ }, "node_modules/eslint/node_modules/find-up": { "version": "5.0.0", + "dev": true, "license": "MIT", "dependencies": { "locate-path": "^6.0.0", @@ -8496,6 +8862,7 @@ }, "node_modules/eslint/node_modules/glob-parent": { "version": "6.0.2", + "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.3" @@ -8506,6 +8873,7 @@ }, "node_modules/eslint/node_modules/has-flag": { "version": "4.0.0", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -8513,6 +8881,7 @@ }, "node_modules/eslint/node_modules/js-yaml": { "version": "4.1.0", + "dev": true, "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -8523,6 +8892,7 @@ }, "node_modules/eslint/node_modules/locate-path": { "version": "6.0.0", + "dev": true, "license": "MIT", "dependencies": { "p-locate": "^5.0.0" @@ -8536,6 +8906,7 @@ }, "node_modules/eslint/node_modules/p-limit": { "version": "3.1.0", + "dev": true, "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" @@ -8549,6 +8920,7 @@ }, "node_modules/eslint/node_modules/p-locate": { "version": "5.0.0", + "dev": true, "license": "MIT", "dependencies": { "p-limit": "^3.0.2" @@ -8562,6 +8934,7 @@ }, "node_modules/eslint/node_modules/supports-color": { "version": "7.2.0", + "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -8572,6 +8945,7 @@ }, "node_modules/espree": { "version": "9.6.1", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "acorn": "^8.9.0", @@ -8599,6 +8973,7 @@ }, "node_modules/esquery": { "version": "1.5.0", + "dev": true, "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" @@ -8609,6 +8984,7 @@ }, "node_modules/esrecurse": { "version": "4.3.0", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" @@ -8619,6 +8995,7 @@ }, "node_modules/estraverse": { "version": "5.3.0", + "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=4.0" @@ -8731,6 +9108,7 @@ }, "node_modules/fast-deep-equal": { "version": "3.1.3", + "dev": true, "license": "MIT" }, "node_modules/fast-glob": { @@ -8750,10 +9128,12 @@ }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", + "dev": true, "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", + "dev": true, "license": "MIT" }, "node_modules/fast-redact": { @@ -8773,6 +9153,7 @@ }, "node_modules/fastq": { "version": "1.15.0", + "dev": true, "license": "ISC", "dependencies": { "reusify": "^1.0.4" @@ -8802,6 +9183,7 @@ }, "node_modules/file-entry-cache": { "version": "6.0.1", + "dev": true, "license": "MIT", "dependencies": { "flat-cache": "^3.0.4" @@ -8868,6 +9250,21 @@ "node": ">=0.10.0" } }, + "node_modules/find-cache-dir": { + "version": "3.3.2", + "license": "MIT", + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, "node_modules/find-up": { "version": "4.1.0", "license": "MIT", @@ -8898,6 +9295,7 @@ }, "node_modules/flat-cache": { "version": "3.0.4", + "dev": true, "license": "MIT", "dependencies": { "flatted": "^3.1.0", @@ -8909,6 +9307,7 @@ }, "node_modules/flatted": { "version": "3.2.7", + "dev": true, "license": "ISC" }, "node_modules/follow-redirects": { @@ -9677,6 +10076,7 @@ }, "node_modules/globals": { "version": "13.21.0", + "dev": true, "license": "MIT", "dependencies": { "type-fest": "^0.20.2" @@ -9738,7 +10138,6 @@ }, "node_modules/graceful-fs": { "version": "4.2.10", - "dev": true, "license": "ISC" }, "node_modules/grapheme-splitter": { @@ -9748,6 +10147,7 @@ }, "node_modules/graphemer": { "version": "1.4.0", + "dev": true, "license": "MIT" }, "node_modules/growly": { @@ -9992,6 +10392,7 @@ }, "node_modules/ignore": { "version": "5.2.4", + "dev": true, "license": "MIT", "engines": { "node": ">= 4" @@ -10029,6 +10430,7 @@ }, "node_modules/import-fresh": { "version": "3.3.0", + "dev": true, "license": "MIT", "dependencies": { "parent-module": "^1.0.0", @@ -10043,6 +10445,7 @@ }, "node_modules/import-fresh/node_modules/resolve-from": { "version": "4.0.0", + "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -10068,6 +10471,7 @@ }, "node_modules/imurmurhash": { "version": "0.1.4", + "dev": true, "license": "MIT", "engines": { "node": ">=0.8.19" @@ -10404,6 +10808,7 @@ }, "node_modules/is-extglob": { "version": "2.1.1", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -10426,6 +10831,7 @@ }, "node_modules/is-glob": { "version": "4.0.3", + "dev": true, "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" @@ -10502,6 +10908,7 @@ }, "node_modules/is-path-inside": { "version": "3.0.3", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -10696,6 +11103,7 @@ }, "node_modules/isexe": { "version": "2.0.0", + "dev": true, "license": "ISC" }, "node_modules/isobject": { @@ -12467,6 +12875,7 @@ }, "node_modules/jsdoc-type-pratt-parser": { "version": "3.1.0", + "dev": true, "license": "MIT", "engines": { "node": ">=12.0.0" @@ -12558,10 +12967,12 @@ }, "node_modules/json-schema-traverse": { "version": "0.4.1", + "dev": true, "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", + "dev": true, "license": "MIT" }, "node_modules/json-stringify-nice": { @@ -13084,6 +13495,7 @@ }, "node_modules/levn": { "version": "0.4.1", + "dev": true, "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", @@ -13536,8 +13948,14 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", + "dev": true, "license": "MIT" }, "node_modules/lodash.startcase": { @@ -13655,7 +14073,6 @@ }, "node_modules/make-dir": { "version": "3.1.0", - "dev": true, "license": "MIT", "dependencies": { "semver": "^6.0.0" @@ -13669,7 +14086,6 @@ }, "node_modules/make-dir/node_modules/semver": { "version": "6.3.0", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -13678,9 +14094,7 @@ "node_modules/make-error": { "version": "1.3.6", "dev": true, - "license": "ISC", - "optional": true, - "peer": true + "license": "ISC" }, "node_modules/make-fetch-happen": { "version": "11.1.1", @@ -13927,6 +14341,7 @@ }, "node_modules/minimatch": { "version": "3.1.2", + "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -14214,6 +14629,7 @@ }, "node_modules/natural-compare": { "version": "1.4.0", + "dev": true, "license": "MIT" }, "node_modules/negotiator": { @@ -15241,6 +15657,7 @@ }, "node_modules/optionator": { "version": "0.9.3", + "dev": true, "license": "MIT", "dependencies": { "@aashutoshrathi/word-wrap": "^1.2.3", @@ -15696,6 +16113,7 @@ }, "node_modules/parent-module": { "version": "1.0.1", + "dev": true, "license": "MIT", "dependencies": { "callsites": "^3.0.0" @@ -15792,6 +16210,7 @@ }, "node_modules/path-is-absolute": { "version": "1.0.1", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -15799,6 +16218,7 @@ }, "node_modules/path-key": { "version": "3.1.1", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -15913,7 +16333,6 @@ }, "node_modules/pkg-dir": { "version": "4.2.0", - "dev": true, "license": "MIT", "dependencies": { "find-up": "^4.0.0" @@ -16032,6 +16451,7 @@ }, "node_modules/prelude-ls": { "version": "1.2.1", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.8.0" @@ -16193,6 +16613,7 @@ }, "node_modules/punycode": { "version": "2.3.0", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -16842,6 +17263,7 @@ }, "node_modules/reusify": { "version": "1.0.4", + "dev": true, "license": "MIT", "engines": { "iojs": ">=1.0.0", @@ -16850,6 +17272,7 @@ }, "node_modules/rimraf": { "version": "3.0.2", + "dev": true, "license": "ISC", "dependencies": { "glob": "^7.1.3" @@ -16863,6 +17286,7 @@ }, "node_modules/rimraf/node_modules/glob": { "version": "7.2.3", + "dev": true, "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", @@ -16892,6 +17316,84 @@ "fsevents": "~2.3.2" } }, + "node_modules/rollup-plugin-typescript2": { + "version": "0.35.0", + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^4.1.2", + "find-cache-dir": "^3.3.2", + "fs-extra": "^10.0.0", + "semver": "^7.3.7", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "rollup": ">=1.26.3", + "typescript": ">=2.4.0" + } + }, + "node_modules/rollup-plugin-typescript2/node_modules/@rollup/pluginutils": { + "version": "4.2.1", + "license": "MIT", + "dependencies": { + "estree-walker": "^2.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/rollup-plugin-typescript2/node_modules/fs-extra": { + "version": "10.1.0", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/rollup-plugin-typescript2/node_modules/jsonfile": { + "version": "6.1.0", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/rollup-plugin-typescript2/node_modules/lru-cache": { + "version": "6.0.0", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/rollup-plugin-typescript2/node_modules/semver": { + "version": "7.5.4", + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/rollup-plugin-typescript2/node_modules/universalify": { + "version": "2.0.1", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/run-async": { "version": "2.4.1", "dev": true, @@ -16902,6 +17404,7 @@ }, "node_modules/run-parallel": { "version": "1.2.0", + "dev": true, "funding": [ { "type": "github", @@ -17026,6 +17529,7 @@ }, "node_modules/shebang-command": { "version": "2.0.0", + "dev": true, "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" @@ -17036,6 +17540,7 @@ }, "node_modules/shebang-regex": { "version": "3.0.0", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -17394,10 +17899,12 @@ }, "node_modules/spdx-exceptions": { "version": "2.3.0", + "dev": true, "license": "CC-BY-3.0" }, "node_modules/spdx-expression-parse": { "version": "3.0.1", + "dev": true, "license": "MIT", "dependencies": { "spdx-exceptions": "^2.1.0", @@ -17406,6 +17913,7 @@ }, "node_modules/spdx-license-ids": { "version": "3.0.12", + "dev": true, "license": "CC0-1.0" }, "node_modules/split": { @@ -17621,6 +18129,7 @@ }, "node_modules/strip-json-comments": { "version": "3.1.1", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -17837,6 +18346,7 @@ }, "node_modules/text-table": { "version": "0.2.0", + "dev": true, "license": "MIT" }, "node_modules/thread-stream": { @@ -17942,6 +18452,92 @@ "node": ">=8" } }, + "node_modules/ts-api-utils": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16.13.0" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/ts-jest": { + "version": "29.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^29.0.0", + "json5": "^2.2.3", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "^7.5.3", + "yargs-parser": "^21.0.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, + "node_modules/ts-jest/node_modules/lru-cache": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-jest/node_modules/semver": { + "version": "7.5.4", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-jest/node_modules/yargs-parser": { + "version": "21.1.1", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/ts-node": { "version": "10.9.1", "dev": true, @@ -18188,6 +18784,7 @@ }, "node_modules/type-check": { "version": "0.4.0", + "dev": true, "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" @@ -18206,6 +18803,7 @@ }, "node_modules/type-fest": { "version": "0.20.2", + "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" @@ -18234,9 +18832,7 @@ }, "node_modules/typescript": { "version": "5.1.6", - "dev": true, "license": "Apache-2.0", - "optional": true, "peer": true, "bin": { "tsc": "bin/tsc", @@ -18392,6 +18988,7 @@ }, "node_modules/uri-js": { "version": "4.4.1", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" @@ -18598,6 +19195,7 @@ }, "node_modules/which": { "version": "2.0.2", + "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -18966,6 +19564,7 @@ }, "node_modules/yocto-queue": { "version": "0.1.0", + "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -18976,23 +19575,55 @@ }, "packages/config": { "name": "@onflow/config", - "version": "1.1.2", + "version": "1.2.0-typescript.0", "license": "Apache-2.0", "dependencies": { "@babel/runtime": "^7.18.6", - "@onflow/util-actor": "^1.2.0", + "@onflow/util-actor": "^1.3.0-typescript.0", + "@onflow/util-invariant": "^1.2.0-typescript.0", + "@onflow/util-logger": "^1.3.0-typescript.0", "eslint": "^8.34.0", "eslint-plugin-jsdoc": "^40.0.0" }, "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1", + "@babel/preset-typescript": "^7.22.11", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", "@types/estree": "^1.0.1", + "@types/jest": "^29.5.4", + "@typescript-eslint/eslint-plugin": "^6.5.0", + "@typescript-eslint/parser": "^6.5.0", + "eslint": "^8.48.0", + "eslint-plugin-jsdoc": "^46.5.1", "jest": "^29.5.0", "typescript": "^4.9.5" } }, + "packages/config/node_modules/@es-joy/jsdoccomment": { + "version": "0.40.1", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.40.1.tgz", + "integrity": "sha512-YORCdZSusAlBrFpZ77pJjc5r1bQs5caPWtAu+WWmiSo+8XaUzseapVrfAtiRFbQWnrBxxLLEwF6f6ZG/UgCQCg==", + "dev": true, + "dependencies": { + "comment-parser": "1.4.0", + "esquery": "^1.5.0", + "jsdoc-type-pratt-parser": "~4.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "packages/config/node_modules/comment-parser": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.0.tgz", + "integrity": "sha512-QLyTNiZ2KDOibvFPlZ6ZngVsZ/0gYnE6uTXi5aoDg8ed3AkJAz4sEje3Y8a29hQ1s6A99MZXe47fLAXQ1rTqaw==", + "dev": true, + "engines": { + "node": ">= 12.0.0" + } + }, "packages/config/node_modules/escape-string-regexp": { "version": "4.0.0", + "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -19002,27 +19633,42 @@ } }, "packages/config/node_modules/eslint-plugin-jsdoc": { - "version": "40.0.1", - "license": "BSD-3-Clause", + "version": "46.8.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-46.8.2.tgz", + "integrity": "sha512-5TSnD018f3tUJNne4s4gDWQflbsgOycIKEUBoCLn6XtBMgNHxQFmV8vVxUtiPxAQq8lrX85OaSG/2gnctxw9uQ==", + "dev": true, "dependencies": { - "@es-joy/jsdoccomment": "~0.36.1", - "comment-parser": "1.3.1", + "@es-joy/jsdoccomment": "~0.40.1", + "are-docs-informative": "^0.0.2", + "comment-parser": "1.4.0", "debug": "^4.3.4", "escape-string-regexp": "^4.0.0", - "esquery": "^1.4.0", - "semver": "^7.3.8", + "esquery": "^1.5.0", + "is-builtin-module": "^3.2.1", + "semver": "^7.5.4", "spdx-expression-parse": "^3.0.1" }, "engines": { - "node": "^14 || ^16 || ^17 || ^18 || ^19" + "node": ">=16" }, "peerDependencies": { "eslint": "^7.0.0 || ^8.0.0" } }, + "packages/config/node_modules/jsdoc-type-pratt-parser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz", + "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==", + "dev": true, + "engines": { + "node": ">=12.0.0" + } + }, "packages/config/node_modules/lru-cache": { "version": "6.0.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -19031,8 +19677,10 @@ } }, "packages/config/node_modules/semver": { - "version": "7.3.8", - "license": "ISC", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -19057,27 +19705,27 @@ }, "packages/fcl": { "name": "@onflow/fcl", - "version": "1.6.0", + "version": "1.8.0-typescript.0", "license": "Apache-2.0", "dependencies": { "@babel/runtime": "^7.18.6", - "@onflow/config": "^1.1.2", + "@onflow/config": "^1.2.0-typescript.0", "@onflow/interaction": "0.0.11", - "@onflow/rlp": "^1.1.0", - "@onflow/sdk": "^1.2.2", - "@onflow/types": "^1.1.0", - "@onflow/util-actor": "^1.2.0", - "@onflow/util-address": "^1.1.0", - "@onflow/util-invariant": "^1.1.0", - "@onflow/util-logger": "^1.2.2", + "@onflow/rlp": "^1.2.0-typescript.0", + "@onflow/sdk": "^1.3.0-typescript.0", + "@onflow/types": "^1.2.0-typescript.0", + "@onflow/util-actor": "^1.3.0-typescript.0", + "@onflow/util-address": "^1.2.0-typescript.0", + "@onflow/util-invariant": "^1.2.0-typescript.0", + "@onflow/util-logger": "^1.3.0-typescript.0", "@onflow/util-semver": "^1.0.0", - "@onflow/util-template": "^1.1.0", - "@onflow/util-uid": "^1.1.0", + "@onflow/util-template": "^1.2.0-typescript.0", + "@onflow/util-uid": "^1.2.0-typescript.0", "cross-fetch": "^3.1.6" }, "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1", - "@onflow/typedefs": "^1.1.1", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", + "@onflow/typedefs": "^1.2.0-typescript.0", "@types/estree": "^1.0.1", "@types/node": "^18.13.0", "eslint": "^8.35.0", @@ -19113,11 +19761,12 @@ }, "packages/fcl-bundle": { "name": "@onflow/fcl-bundle", - "version": "1.3.1", + "version": "1.4.0-typescript.0", "license": "Apache-2.0", "dependencies": { "@babel/plugin-transform-runtime": "^7.18.2", "@babel/preset-env": "^7.18.2", + "@babel/preset-typescript": "^7.22.5", "@rollup/plugin-babel": "^6.0.3", "@rollup/plugin-commonjs": "^25.0.2", "@rollup/plugin-node-resolve": "^15.1.0", @@ -19126,7 +19775,8 @@ "builtin-modules": "^3.3.0", "commander": "^9.3.0", "lodash": "^4.17.21", - "rollup": "^2.75.5" + "rollup": "^2.75.5", + "rollup-plugin-typescript2": "^0.35.0" }, "bin": { "fcl-bundle": "src/cli.js" @@ -19141,25 +19791,25 @@ }, "packages/fcl-wc": { "name": "@onflow/fcl-wc", - "version": "4.0.0-accounts.1", + "version": "5.0.0-typescript.0", "license": "Apache-2.0", "dependencies": { "@babel/runtime": "^7.18.9", - "@onflow/config": "^1.1.2", - "@onflow/util-invariant": "^1.1.0", - "@onflow/util-logger": "^1.2.2", + "@onflow/config": "^1.2.0-typescript.0", + "@onflow/util-invariant": "^1.2.0-typescript.0", + "@onflow/util-logger": "^1.3.0-typescript.0", "@walletconnect/modal": "^2.4.7", "@walletconnect/sign-client": "^2.8.1", "@walletconnect/types": "^2.8.1", "@walletconnect/utils": "^2.8.1" }, "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", "better-sqlite3": "^7.6.2", "jest": "^29.5.0" }, "peerDependencies": { - "@onflow/fcl": "^1.6.0" + "@onflow/fcl": "^1.8.0-typescript.0" } }, "packages/fcl/node_modules/eslint-plugin-jsdoc": { @@ -19698,65 +20348,45 @@ }, "packages/rlp": { "name": "@onflow/rlp", - "version": "1.1.0", + "version": "1.2.0-typescript.0", "license": "MPL-2.0", "dependencies": { "@babel/runtime": "^7.18.6", "buffer": "^6.0.3" }, "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1-alpha.0", + "@babel/preset-typescript": "^7.22.5", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", + "@types/jest": "^29.5.3", + "@typescript-eslint/eslint-plugin": "^6.4.0", + "@typescript-eslint/parser": "^6.4.0", + "eslint": "^8.47.0", + "eslint-plugin-jsdoc": "^46.4.6", "jest": "^29.5.0" } }, - "packages/sdk": { - "name": "@onflow/sdk", - "version": "1.2.2", - "license": "Apache-2.0", + "packages/rlp/node_modules/@es-joy/jsdoccomment": { + "version": "0.40.1", + "dev": true, + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.18.6", - "@onflow/config": "^1.1.1", - "@onflow/rlp": "^1.1.0", - "@onflow/transport-http": "^1.7.1", - "@onflow/util-actor": "^1.2.0", - "@onflow/util-address": "^1.1.0", - "@onflow/util-invariant": "^1.1.0", - "@onflow/util-logger": "^1.2.1", - "@onflow/util-template": "^1.1.0", - "deepmerge": "^4.2.2", - "sha3": "^2.1.4", - "uuid": "^9.0.1" + "comment-parser": "1.4.0", + "esquery": "^1.5.0", + "jsdoc-type-pratt-parser": "~4.0.0" }, - "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1", - "@onflow/typedefs": "^1.1.1", - "eslint": "^8.35.0", - "eslint-plugin-jsdoc": "^40.0.1", - "jest": "^29.5.0", - "typescript": "^4.9.5" + "engines": { + "node": ">=16" } }, - "packages/sdk/node_modules/eslint-plugin-jsdoc": { - "version": "40.0.1", + "packages/rlp/node_modules/comment-parser": { + "version": "1.4.0", "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@es-joy/jsdoccomment": "~0.36.1", - "comment-parser": "1.3.1", - "debug": "^4.3.4", - "escape-string-regexp": "^4.0.0", - "esquery": "^1.4.0", - "semver": "^7.3.8", - "spdx-expression-parse": "^3.0.1" - }, + "license": "MIT", "engines": { - "node": "^14 || ^16 || ^17 || ^18 || ^19" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "node": ">= 12.0.0" } }, - "packages/sdk/node_modules/eslint-plugin-jsdoc/node_modules/escape-string-regexp": { + "packages/rlp/node_modules/escape-string-regexp": { "version": "4.0.0", "dev": true, "license": "MIT", @@ -19767,16 +20397,129 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/sdk/node_modules/eslint-plugin-jsdoc/node_modules/semver": { - "version": "7.3.8", + "packages/rlp/node_modules/eslint-plugin-jsdoc": { + "version": "46.8.2", "dev": true, - "license": "ISC", + "license": "BSD-3-Clause", "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, + "@es-joy/jsdoccomment": "~0.40.1", + "are-docs-informative": "^0.0.2", + "comment-parser": "1.4.0", + "debug": "^4.3.4", + "escape-string-regexp": "^4.0.0", + "esquery": "^1.5.0", + "is-builtin-module": "^3.2.1", + "semver": "^7.5.4", + "spdx-expression-parse": "^3.0.1" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "packages/rlp/node_modules/jsdoc-type-pratt-parser": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, + "packages/rlp/node_modules/lru-cache": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "packages/rlp/node_modules/semver": { + "version": "7.5.4", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "packages/sdk": { + "name": "@onflow/sdk", + "version": "1.3.0-typescript.0", + "license": "Apache-2.0", + "dependencies": { + "@babel/runtime": "^7.18.6", + "@onflow/config": "^1.2.0-typescript.0", + "@onflow/rlp": "^1.2.0-typescript.0", + "@onflow/transport-http": "^1.8.0-typescript.0", + "@onflow/util-actor": "^1.3.0-typescript.0", + "@onflow/util-address": "^1.2.0-typescript.0", + "@onflow/util-invariant": "^1.2.0-typescript.0", + "@onflow/util-logger": "^1.3.0-typescript.0", + "@onflow/util-template": "^1.2.0-typescript.0", + "deepmerge": "^4.2.2", + "sha3": "^2.1.4", + "uuid": "^9.0.1" + }, + "devDependencies": { + "@onflow/fcl-bundle": "^1.4.0-typescript.0", + "@onflow/typedefs": "^1.2.0-typescript.0", + "eslint": "^8.35.0", + "eslint-plugin-jsdoc": "^40.0.1", + "jest": "^29.5.0", + "typescript": "^4.9.5" + } + }, + "packages/sdk/node_modules/eslint-plugin-jsdoc": { + "version": "40.0.1", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@es-joy/jsdoccomment": "~0.36.1", + "comment-parser": "1.3.1", + "debug": "^4.3.4", + "escape-string-regexp": "^4.0.0", + "esquery": "^1.4.0", + "semver": "^7.3.8", + "spdx-expression-parse": "^3.0.1" + }, + "engines": { + "node": "^14 || ^16 || ^17 || ^18 || ^19" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "packages/sdk/node_modules/eslint-plugin-jsdoc/node_modules/escape-string-regexp": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/sdk/node_modules/eslint-plugin-jsdoc/node_modules/semver": { + "version": "7.3.8", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, "engines": { "node": ">=10" } @@ -19806,33 +20549,32 @@ }, "packages/sdk/node_modules/uuid": { "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" ], + "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } }, "packages/transport-grpc": { "name": "@onflow/transport-grpc", - "version": "1.2.2-accounts.0", + "version": "1.3.0-typescript.0", "license": "Apache-2.0", "dependencies": { "@babel/runtime": "^7.18.6", "@improbable-eng/grpc-web": "^0.14.0", "@improbable-eng/grpc-web-node-http-transport": "^0.14.0", "@onflow/protobuf": "^1.2.1", - "@onflow/rlp": "^1.1.0", - "@onflow/util-address": "^1.1.0", - "@onflow/util-invariant": "^1.1.0", - "@onflow/util-template": "^1.1.0" + "@onflow/rlp": "^1.2.0-typescript.0", + "@onflow/util-address": "^1.2.0-typescript.0", + "@onflow/util-invariant": "^1.2.0-typescript.0", + "@onflow/util-template": "^1.2.0-typescript.0" }, "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1", - "@onflow/sdk": "^1.2.2", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", + "@onflow/sdk": "^1.3.0-typescript.0", "jest": "^29.5.0" } }, @@ -19860,34 +20602,34 @@ }, "packages/transport-http": { "name": "@onflow/transport-http", - "version": "1.7.1", + "version": "1.8.0-typescript.0", "license": "Apache-2.0", "dependencies": { "@babel/runtime": "^7.18.6", - "@onflow/util-address": "^1.1.0", - "@onflow/util-invariant": "^1.1.0", - "@onflow/util-logger": "^1.2.1", - "@onflow/util-template": "^1.1.0", + "@onflow/util-address": "^1.2.0-typescript.0", + "@onflow/util-invariant": "^1.2.0-typescript.0", + "@onflow/util-logger": "^1.3.0-typescript.0", + "@onflow/util-template": "^1.2.0-typescript.0", "abort-controller": "^3.0.0", "cross-fetch": "^3.1.6" }, "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1", - "@onflow/rlp": "^1.1.0", - "@onflow/sdk": "^1.2.2", - "@onflow/types": "^1.1.0", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", + "@onflow/rlp": "^1.2.0-typescript.0", + "@onflow/sdk": "^1.3.0-typescript.0", + "@onflow/types": "^1.2.0-typescript.0", "jest": "^29.5.0" } }, "packages/typedefs": { "name": "@onflow/typedefs", - "version": "1.1.1", + "version": "1.2.0-typescript.0", "license": "Apache-2.0", "dependencies": { "@babel/runtime": "^7.18.6" }, "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", "@types/node": "^18.13.0", "eslint": "^8.33.0", "eslint-plugin-jsdoc": "^39.7.5", @@ -19910,47 +20652,24 @@ }, "packages/types": { "name": "@onflow/types", - "version": "1.1.0", - "license": "Apache-2.0", - "dependencies": { - "@babel/runtime": "^7.18.6" - }, - "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1-alpha.0", - "jest": "^29.5.0" - } - }, - "packages/util-actor": { - "name": "@onflow/util-actor", - "version": "1.2.0", + "version": "1.2.0-typescript.0", "license": "Apache-2.0", "dependencies": { "@babel/runtime": "^7.18.6", - "queue-microtask": "1.2.3" + "@onflow/util-logger": "^1.3.0-typescript.0" }, "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1-alpha.0", + "@babel/preset-typescript": "^7.22.5", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", + "@types/jest": "^29.5.3", + "@typescript-eslint/eslint-plugin": "^6.4.0", + "@typescript-eslint/parser": "^6.4.0", + "eslint": "^8.47.0", + "eslint-plugin-jsdoc": "^46.4.6", "jest": "^29.5.0" } }, - "packages/util-address": { - "name": "@onflow/util-address", - "version": "1.1.0", - "license": "Apache-2.0", - "dependencies": { - "@babel/runtime": "^7.18.6" - }, - "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1-alpha.0", - "@onflow/types": "^1.1.0", - "@types/node": "^18.13.0", - "eslint": "^8.33.0", - "eslint-plugin-jsdoc": "^39.7.5", - "jest": "^29.5.0", - "typescript": "^4.9.5" - } - }, - "packages/util-address/node_modules/@es-joy/jsdoccomment": { + "packages/types/node_modules/@es-joy/jsdoccomment": { "version": "0.40.1", "dev": true, "license": "MIT", @@ -19963,7 +20682,22 @@ "node": ">=16" } }, - "packages/util-address/node_modules/comment-parser": { + "packages/types/node_modules/@onflow/util-logger": { + "version": "1.3.0", + "license": "Apache-2.0", + "dependencies": { + "@babel/runtime": "^7.18.6" + }, + "peerDependencies": { + "@onflow/util-config": ">1.1.1" + }, + "peerDependenciesMeta": { + "@onflow/util-config": { + "optional": true + } + } + }, + "packages/types/node_modules/comment-parser": { "version": "1.4.0", "dev": true, "license": "MIT", @@ -19971,7 +20705,7 @@ "node": ">= 12.0.0" } }, - "packages/util-address/node_modules/escape-string-regexp": { + "packages/types/node_modules/escape-string-regexp": { "version": "4.0.0", "dev": true, "license": "MIT", @@ -19982,7 +20716,7 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/util-address/node_modules/eslint-plugin-jsdoc": { + "packages/types/node_modules/eslint-plugin-jsdoc": { "version": "46.4.6", "dev": true, "license": "BSD-3-Clause", @@ -20004,7 +20738,7 @@ "eslint": "^7.0.0 || ^8.0.0" } }, - "packages/util-address/node_modules/jsdoc-type-pratt-parser": { + "packages/types/node_modules/jsdoc-type-pratt-parser": { "version": "4.0.0", "dev": true, "license": "MIT", @@ -20012,7 +20746,7 @@ "node": ">=12.0.0" } }, - "packages/util-address/node_modules/lru-cache": { + "packages/types/node_modules/lru-cache": { "version": "6.0.0", "dev": true, "license": "ISC", @@ -20023,7 +20757,7 @@ "node": ">=10" } }, - "packages/util-address/node_modules/semver": { + "packages/types/node_modules/semver": { "version": "7.5.4", "dev": true, "license": "ISC", @@ -20037,38 +20771,26 @@ "node": ">=10" } }, - "packages/util-address/node_modules/typescript": { - "version": "4.9.5", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "packages/util-encode-key": { - "name": "@onflow/util-encode-key", - "version": "1.1.0", + "packages/util-actor": { + "name": "@onflow/util-actor", + "version": "1.3.0-typescript.0", "license": "Apache-2.0", "dependencies": { "@babel/runtime": "^7.18.6", - "@onflow/rlp": "^1.1.0", - "@onflow/util-invariant": "^1.1.0" + "queue-microtask": "1.2.3" }, "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1-alpha.0", - "@onflow/types": "^1.1.0", - "@types/node": "^18.13.0", - "eslint": "^8.33.0", - "eslint-plugin-jsdoc": "^39.8.0", - "jest": "^29.5.0", - "typescript": "^4.9.5" + "@babel/preset-typescript": "^7.22.5", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", + "@types/jest": "^29.5.3", + "@typescript-eslint/eslint-plugin": "^6.4.0", + "@typescript-eslint/parser": "^6.4.0", + "eslint": "^8.47.0", + "eslint-plugin-jsdoc": "^46.4.6", + "jest": "^29.5.0" } }, - "packages/util-encode-key/node_modules/@es-joy/jsdoccomment": { + "packages/util-actor/node_modules/@es-joy/jsdoccomment": { "version": "0.40.1", "dev": true, "license": "MIT", @@ -20081,7 +20803,7 @@ "node": ">=16" } }, - "packages/util-encode-key/node_modules/comment-parser": { + "packages/util-actor/node_modules/comment-parser": { "version": "1.4.0", "dev": true, "license": "MIT", @@ -20089,7 +20811,7 @@ "node": ">= 12.0.0" } }, - "packages/util-encode-key/node_modules/escape-string-regexp": { + "packages/util-actor/node_modules/escape-string-regexp": { "version": "4.0.0", "dev": true, "license": "MIT", @@ -20100,8 +20822,8 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/util-encode-key/node_modules/eslint-plugin-jsdoc": { - "version": "46.4.6", + "packages/util-actor/node_modules/eslint-plugin-jsdoc": { + "version": "46.5.1", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -20122,7 +20844,7 @@ "eslint": "^7.0.0 || ^8.0.0" } }, - "packages/util-encode-key/node_modules/jsdoc-type-pratt-parser": { + "packages/util-actor/node_modules/jsdoc-type-pratt-parser": { "version": "4.0.0", "dev": true, "license": "MIT", @@ -20130,7 +20852,7 @@ "node": ">=12.0.0" } }, - "packages/util-encode-key/node_modules/lru-cache": { + "packages/util-actor/node_modules/lru-cache": { "version": "6.0.0", "dev": true, "license": "ISC", @@ -20141,7 +20863,7 @@ "node": ">=10" } }, - "packages/util-encode-key/node_modules/semver": { + "packages/util-actor/node_modules/semver": { "version": "7.5.4", "dev": true, "license": "ISC", @@ -20155,86 +20877,704 @@ "node": ">=10" } }, - "packages/util-encode-key/node_modules/typescript": { - "version": "4.9.5", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "packages/util-invariant": { - "name": "@onflow/util-invariant", - "version": "1.1.0", + "packages/util-address": { + "name": "@onflow/util-address", + "version": "1.2.0-typescript.0", "license": "Apache-2.0", "dependencies": { "@babel/runtime": "^7.18.6" }, "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1-alpha.0", - "@onflow/types": "^1.1.0", - "jest": "^29.5.0" + "@babel/preset-typescript": "^7.22.5", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", + "@onflow/types": "^1.2.0-typescript.0", + "@types/jest": "^29.5.3", + "@types/node": "^18.13.0", + "@typescript-eslint/eslint-plugin": "^6.4.0", + "@typescript-eslint/parser": "^6.4.0", + "eslint": "^8.47.0", + "eslint-plugin-jsdoc": "^46.4.6", + "jest": "^29.5.0", + "typescript": "^4.9.5" } }, - "packages/util-logger": { - "name": "@onflow/util-logger", - "version": "1.2.2", - "license": "Apache-2.0", + "packages/util-address/node_modules/@es-joy/jsdoccomment": { + "version": "0.40.1", + "dev": true, + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.18.6" - }, - "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1", - "jest": "^29.5.0" - }, - "peerDependencies": { - "@onflow/util-config": ">1.1.1" + "comment-parser": "1.4.0", + "esquery": "^1.5.0", + "jsdoc-type-pratt-parser": "~4.0.0" }, - "peerDependenciesMeta": { - "@onflow/util-config": { - "optional": true - } + "engines": { + "node": ">=16" } }, - "packages/util-semver": { - "name": "@onflow/util-semver", - "version": "1.0.0", - "license": "Apache-2.0", - "dependencies": { - "@babel/runtime": "^7.18.6" + "packages/util-address/node_modules/comment-parser": { + "version": "1.4.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12.0.0" + } + }, + "packages/util-address/node_modules/escape-string-regexp": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" }, - "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1", - "jest": "^29.5.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/util-template": { - "name": "@onflow/util-template", - "version": "1.1.0", + "packages/util-address/node_modules/eslint-plugin-jsdoc": { + "version": "46.4.6", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@es-joy/jsdoccomment": "~0.40.1", + "are-docs-informative": "^0.0.2", + "comment-parser": "1.4.0", + "debug": "^4.3.4", + "escape-string-regexp": "^4.0.0", + "esquery": "^1.5.0", + "is-builtin-module": "^3.2.1", + "semver": "^7.5.4", + "spdx-expression-parse": "^3.0.1" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "packages/util-address/node_modules/jsdoc-type-pratt-parser": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, + "packages/util-address/node_modules/lru-cache": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "packages/util-address/node_modules/semver": { + "version": "7.5.4", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "packages/util-address/node_modules/typescript": { + "version": "4.9.5", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "packages/util-encode-key": { + "name": "@onflow/util-encode-key", + "version": "1.2.0-typescript.0", + "license": "Apache-2.0", + "dependencies": { + "@babel/runtime": "^7.18.6", + "@onflow/rlp": "^1.2.0-typescript.0", + "@onflow/util-invariant": "^1.2.0-typescript.0" + }, + "devDependencies": { + "@babel/preset-typescript": "^7.22.5", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", + "@onflow/types": "^1.2.0-typescript.0", + "@types/jest": "^29.5.3", + "@types/node": "^18.13.0", + "@typescript-eslint/eslint-plugin": "^6.4.0", + "@typescript-eslint/parser": "^6.4.0", + "eslint": "^8.47.0", + "eslint-plugin-jsdoc": "^46.4.6", + "jest": "^29.5.0", + "typescript": "^4.9.5" + } + }, + "packages/util-encode-key/node_modules/@es-joy/jsdoccomment": { + "version": "0.40.1", + "dev": true, + "license": "MIT", + "dependencies": { + "comment-parser": "1.4.0", + "esquery": "^1.5.0", + "jsdoc-type-pratt-parser": "~4.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "packages/util-encode-key/node_modules/comment-parser": { + "version": "1.4.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12.0.0" + } + }, + "packages/util-encode-key/node_modules/escape-string-regexp": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/util-encode-key/node_modules/eslint-plugin-jsdoc": { + "version": "46.4.6", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@es-joy/jsdoccomment": "~0.40.1", + "are-docs-informative": "^0.0.2", + "comment-parser": "1.4.0", + "debug": "^4.3.4", + "escape-string-regexp": "^4.0.0", + "esquery": "^1.5.0", + "is-builtin-module": "^3.2.1", + "semver": "^7.5.4", + "spdx-expression-parse": "^3.0.1" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "packages/util-encode-key/node_modules/jsdoc-type-pratt-parser": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, + "packages/util-encode-key/node_modules/lru-cache": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "packages/util-encode-key/node_modules/semver": { + "version": "7.5.4", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "packages/util-encode-key/node_modules/typescript": { + "version": "4.9.5", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "packages/util-invariant": { + "name": "@onflow/util-invariant", + "version": "1.2.0-typescript.0", + "license": "Apache-2.0", + "dependencies": { + "@babel/runtime": "^7.18.6" + }, + "devDependencies": { + "@babel/preset-typescript": "^7.22.5", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", + "@onflow/types": "^1.2.0-typescript.0", + "@types/jest": "^29.5.3", + "@typescript-eslint/eslint-plugin": "^6.4.0", + "@typescript-eslint/parser": "^6.4.0", + "eslint": "^8.47.0", + "eslint-plugin-jsdoc": "^46.4.6", + "jest": "^29.5.0" + } + }, + "packages/util-invariant/node_modules/@es-joy/jsdoccomment": { + "version": "0.40.1", + "dev": true, + "license": "MIT", + "dependencies": { + "comment-parser": "1.4.0", + "esquery": "^1.5.0", + "jsdoc-type-pratt-parser": "~4.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "packages/util-invariant/node_modules/comment-parser": { + "version": "1.4.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12.0.0" + } + }, + "packages/util-invariant/node_modules/escape-string-regexp": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/util-invariant/node_modules/eslint-plugin-jsdoc": { + "version": "46.8.2", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@es-joy/jsdoccomment": "~0.40.1", + "are-docs-informative": "^0.0.2", + "comment-parser": "1.4.0", + "debug": "^4.3.4", + "escape-string-regexp": "^4.0.0", + "esquery": "^1.5.0", + "is-builtin-module": "^3.2.1", + "semver": "^7.5.4", + "spdx-expression-parse": "^3.0.1" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "packages/util-invariant/node_modules/jsdoc-type-pratt-parser": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, + "packages/util-invariant/node_modules/lru-cache": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "packages/util-invariant/node_modules/semver": { + "version": "7.5.4", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "packages/util-logger": { + "name": "@onflow/util-logger", + "version": "1.3.0-typescript.0", + "license": "Apache-2.0", + "dependencies": { + "@babel/runtime": "^7.18.6" + }, + "devDependencies": { + "@babel/preset-typescript": "^7.22.5", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", + "@types/jest": "^29.5.3", + "@typescript-eslint/eslint-plugin": "^6.4.0", + "@typescript-eslint/parser": "^6.4.0", + "eslint": "^8.47.0", + "eslint-plugin-jsdoc": "^46.4.6", + "jest": "^29.5.0" + }, + "peerDependencies": { + "@onflow/util-config": ">1.1.1" + }, + "peerDependenciesMeta": { + "@onflow/util-config": { + "optional": true + } + } + }, + "packages/util-logger/node_modules/@es-joy/jsdoccomment": { + "version": "0.40.1", + "dev": true, + "license": "MIT", + "dependencies": { + "comment-parser": "1.4.0", + "esquery": "^1.5.0", + "jsdoc-type-pratt-parser": "~4.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "packages/util-logger/node_modules/comment-parser": { + "version": "1.4.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12.0.0" + } + }, + "packages/util-logger/node_modules/escape-string-regexp": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/util-logger/node_modules/eslint-plugin-jsdoc": { + "version": "46.8.2", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@es-joy/jsdoccomment": "~0.40.1", + "are-docs-informative": "^0.0.2", + "comment-parser": "1.4.0", + "debug": "^4.3.4", + "escape-string-regexp": "^4.0.0", + "esquery": "^1.5.0", + "is-builtin-module": "^3.2.1", + "semver": "^7.5.4", + "spdx-expression-parse": "^3.0.1" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "packages/util-logger/node_modules/jsdoc-type-pratt-parser": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, + "packages/util-logger/node_modules/lru-cache": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "packages/util-logger/node_modules/semver": { + "version": "7.5.4", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "packages/util-semver": { + "name": "@onflow/util-semver", + "version": "1.0.0", "license": "Apache-2.0", "dependencies": { "@babel/runtime": "^7.18.6" }, "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1-alpha.0", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", + "jest": "^29.5.0" + } + }, + "packages/util-template": { + "name": "@onflow/util-template", + "version": "1.2.0-typescript.0", + "license": "Apache-2.0", + "dependencies": { + "@babel/runtime": "^7.18.6", + "@onflow/util-logger": "^1.3.0-typescript.0" + }, + "devDependencies": { + "@babel/preset-typescript": "^7.22.5", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", + "@types/jest": "^29.5.3", + "@typescript-eslint/eslint-plugin": "^6.4.0", + "@typescript-eslint/parser": "^6.4.0", + "eslint": "^8.47.0", + "eslint-plugin-jsdoc": "^46.4.6", "jest": "^29.5.0" } }, + "packages/util-template/node_modules/@es-joy/jsdoccomment": { + "version": "0.40.1", + "dev": true, + "license": "MIT", + "dependencies": { + "comment-parser": "1.4.0", + "esquery": "^1.5.0", + "jsdoc-type-pratt-parser": "~4.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "packages/util-template/node_modules/@onflow/util-logger": { + "version": "1.3.0", + "license": "Apache-2.0", + "dependencies": { + "@babel/runtime": "^7.18.6" + }, + "peerDependencies": { + "@onflow/util-config": ">1.1.1" + }, + "peerDependenciesMeta": { + "@onflow/util-config": { + "optional": true + } + } + }, + "packages/util-template/node_modules/comment-parser": { + "version": "1.4.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12.0.0" + } + }, + "packages/util-template/node_modules/escape-string-regexp": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/util-template/node_modules/eslint-plugin-jsdoc": { + "version": "46.8.2", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@es-joy/jsdoccomment": "~0.40.1", + "are-docs-informative": "^0.0.2", + "comment-parser": "1.4.0", + "debug": "^4.3.4", + "escape-string-regexp": "^4.0.0", + "esquery": "^1.5.0", + "is-builtin-module": "^3.2.1", + "semver": "^7.5.4", + "spdx-expression-parse": "^3.0.1" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "packages/util-template/node_modules/jsdoc-type-pratt-parser": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, + "packages/util-template/node_modules/lru-cache": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "packages/util-template/node_modules/semver": { + "version": "7.5.4", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "packages/util-uid": { "name": "@onflow/util-uid", - "version": "1.1.0", + "version": "1.2.0-typescript.0", "license": "Apache-2.0", "dependencies": { "@babel/runtime": "^7.18.6" }, "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1-alpha.0", + "@babel/preset-typescript": "^7.22.5", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", + "@types/jest": "^29.5.3", + "@typescript-eslint/eslint-plugin": "^6.4.0", + "@typescript-eslint/parser": "^6.4.0", + "eslint": "^8.47.0", + "eslint-plugin-jsdoc": "^46.4.6", "jest": "^29.5.0" } + }, + "packages/util-uid/node_modules/@es-joy/jsdoccomment": { + "version": "0.40.1", + "dev": true, + "license": "MIT", + "dependencies": { + "comment-parser": "1.4.0", + "esquery": "^1.5.0", + "jsdoc-type-pratt-parser": "~4.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "packages/util-uid/node_modules/comment-parser": { + "version": "1.4.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12.0.0" + } + }, + "packages/util-uid/node_modules/escape-string-regexp": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/util-uid/node_modules/eslint-plugin-jsdoc": { + "version": "46.8.2", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@es-joy/jsdoccomment": "~0.40.1", + "are-docs-informative": "^0.0.2", + "comment-parser": "1.4.0", + "debug": "^4.3.4", + "escape-string-regexp": "^4.0.0", + "esquery": "^1.5.0", + "is-builtin-module": "^3.2.1", + "semver": "^7.5.4", + "spdx-expression-parse": "^3.0.1" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "packages/util-uid/node_modules/jsdoc-type-pratt-parser": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, + "packages/util-uid/node_modules/lru-cache": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "packages/util-uid/node_modules/semver": { + "version": "7.5.4", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } } } } diff --git a/package.json b/package.json index 7bfe3842e..1e457e04c 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "./packages/*" ], "scripts": { - "build": "lerna run build:types && lerna run build", + "build": "lerna run build", "start": "npm run build && lerna run start --parallel", "test": "jest", "release": "npm run build && npm run changeset publish", @@ -11,12 +11,15 @@ }, "name": "fcl-js", "devDependencies": { + "@babel/preset-typescript": "^7.22.5", "@changesets/changelog-github": "^0.4.4", "@changesets/cli": "^2.21.1", + "@types/jest": "^29.5.3", "@types/node": "^18.11.18", "jest": "^29.5.0", "jest-environment-jsdom": "^29.5.0", "lerna": "^6.6.2", - "prettier": "^2.6.2" + "prettier": "^2.6.2", + "ts-jest": "^29.1.1" } } diff --git a/packages/config/.babelrc b/packages/config/.babelrc index 67fc2886b..d766c90b2 100644 --- a/packages/config/.babelrc +++ b/packages/config/.babelrc @@ -1,7 +1,3 @@ { - "presets": [ - [ - "@babel/preset-env" - ] - ] + "presets": [["@babel/preset-env"], "@babel/preset-typescript"] } diff --git a/packages/config/.eslintrc.json b/packages/config/.eslintrc.json index b5e57f0a6..79f65ebf2 100644 --- a/packages/config/.eslintrc.json +++ b/packages/config/.eslintrc.json @@ -6,22 +6,18 @@ "node": true }, "extends": [ - "plugin:jsdoc/recommended" - ], - "plugins": [ - "jsdoc" + "plugin:jsdoc/recommended-typescript", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended" ], + "plugins": ["jsdoc", "@typescript-eslint"], + "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": "latest", "sourceType": "module" }, "ignorePatterns": ["**/dist/"], "rules": { - "jsdoc/require-jsdoc": [ - "error", - { - "publicOnly": true - } - ] + "@typescript-eslint/no-explicit-any": "off" } -} \ No newline at end of file +} diff --git a/packages/config/package.json b/packages/config/package.json index 2dd2ebbc1..90d81b597 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -1,6 +1,6 @@ { "name": "@onflow/config", - "version": "1.1.2", + "version": "1.2.0-typescript.0", "description": "Config for FCL-JS", "license": "Apache-2.0", "author": "Dapper Labs ", @@ -13,28 +13,35 @@ "url": "https://github.com/onflow/flow-js-sdk/issues" }, "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1", + "@babel/preset-typescript": "^7.22.11", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", "@types/estree": "^1.0.1", + "@types/jest": "^29.5.4", + "@typescript-eslint/eslint-plugin": "^6.5.0", + "@typescript-eslint/parser": "^6.5.0", + "eslint": "^8.48.0", + "eslint-plugin-jsdoc": "^46.5.1", "jest": "^29.5.0", "typescript": "^4.9.5" }, - "source": "src/config.js", + "source": "src/config.ts", "main": "dist/config.js", "module": "dist/config.module.js", "unpkg": "dist/config.umd.js", - "types": "types/src/config.d.ts", + "types": "dist/config.d.ts", "scripts": { "prepublishOnly": "npm test && npm run build", "test": "jest", "build": "npm run lint && fcl-bundle", - "build:types": "tsc", "test:watch": "jest --watch", "start": "fcl-bundle --watch", - "lint": "eslint ." + "lint": "eslint src" }, "dependencies": { "@babel/runtime": "^7.18.6", - "@onflow/util-actor": "^1.2.0", + "@onflow/util-actor": "^1.3.0-typescript.0", + "@onflow/util-invariant": "^1.2.0-typescript.0", + "@onflow/util-logger": "^1.3.0-typescript.0", "eslint": "^8.34.0", "eslint-plugin-jsdoc": "^40.0.0" } diff --git a/packages/config/src/config.test.js b/packages/config/src/config.test.ts similarity index 95% rename from packages/config/src/config.test.js rename to packages/config/src/config.test.ts index f385ccfa0..417686cc9 100644 --- a/packages/config/src/config.test.js +++ b/packages/config/src/config.test.ts @@ -1,6 +1,6 @@ import {config, clearConfig} from "./config" -const idle = () => new Promise(resolve => setTimeout(resolve), 0) +const idle = () => new Promise(resolve => setTimeout(resolve, 0)) describe("config()", () => { beforeEach(async () => { @@ -33,7 +33,7 @@ describe("config()", () => { }) test("update", async () => { - config().update("config.test.t", v => v + v) + config().update("config.test.t", (v: number) => v + v) expect(await config().get("config.test.t")).toBe("tt") }) @@ -60,7 +60,7 @@ describe("config()", () => { unsub() await idle() - config().update("config.test.y", v => v + v) + config().update("config.test.y", (v: number) => v + v) await idle() @@ -138,7 +138,7 @@ describe("config()", () => { beforeEach(() => config({A: A, B: B, C: C, D: D})) afterEach(clearConfig) - const examples = [ + const examples: ([any, string[]] | [any])[] = [ [FALLBACK], [A, ["A"]], [FALLBACK, ["B"]], @@ -148,7 +148,7 @@ describe("config()", () => { [FALLBACK, ["MISSING", "B"]], ] - for (let [i, [want, from]] of examples.entries()) { + for (const [i, [want, from]] of examples.entries()) { test(`Example ${i}: ${from} -> ${want}`, async () => { expect(await config.first(from, FALLBACK)).toBe(want) }) @@ -157,9 +157,9 @@ describe("config()", () => { describe("load method", () => { describe("with a set network", () => { - beforeEach(async () => { + beforeEach(() => { // Just picked a random network. Behavior might differ based on network selection at a future date. - await config().put("flow.network", "emulator") + config().put("flow.network", "emulator") }) describe("flow.json v1", () => { @@ -225,7 +225,7 @@ describe("config()", () => { describe("with an array of configs loaded", () => { beforeEach(async () => { - let secondFlowJSON = { + const secondFlowJSON = { accounts: {}, contracts: { ThirdContract: { diff --git a/packages/config/src/config.js b/packages/config/src/config.ts similarity index 67% rename from packages/config/src/config.js rename to packages/config/src/config.ts index f294a6a8a..1711c0b6d 100644 --- a/packages/config/src/config.js +++ b/packages/config/src/config.ts @@ -4,10 +4,11 @@ import { subscriber, SUBSCRIBE, UNSUBSCRIBE, + ActorHandlers, } from "@onflow/util-actor" import * as logger from "@onflow/util-logger" import {invariant} from "@onflow/util-invariant" -import {getContracts, cleanNetwork, anyHasPrivateKeys} from "../utils/utils" +import {getContracts, cleanNetwork, anyHasPrivateKeys} from "./utils/utils" // Inject config into logger to break circular dependency logger.setConfig(config) @@ -22,9 +23,9 @@ const CLEAR = "CLEAR_CONFIG" const WHERE = "WHERE_CONFIG" const UPDATED = "CONFIG/UPDATED" -const identity = v => v +const identity = (v: T) => v -const HANDLERS = { +const HANDLERS: ActorHandlers = { [PUT]: (ctx, _letter, {key, value}) => { if (key == null) throw new Error("Missing 'key' for config/put.") ctx.put(key, value) @@ -47,9 +48,9 @@ const HANDLERS = { ctx.delete(key) ctx.broadcast(UPDATED, {...ctx.all()}) }, - [CLEAR]: (ctx, letter) => { - let keys = Object.keys(ctx.all()) - for (let key of keys) ctx.delete(key) + [CLEAR]: ctx => { + const keys = Object.keys(ctx.all()) + for (const key of keys) ctx.delete(key) ctx.broadcast(UPDATED, {...ctx.all()}) }, [WHERE]: (ctx, letter, {pattern}) => { @@ -69,117 +70,123 @@ spawn(HANDLERS, NAME) /** * @description Adds a key-value pair to the config - * @param {string} key - The key to add - * @param {*} value - The value to add - * @returns {Promise} - The current config + * @param key - The key to add + * @param value - The value to add + * @returns The config object */ -function put(key, value) { +function put(key: string, value: T) { send(NAME, PUT, {key, value}) return config() } /** * @description Gets a key-value pair with a fallback from the config - * @param {string} key - The key to add - * @param {*} [fallback] - The fallback value to return if key is not found - * @returns {Promise<*>} - The value found at key or fallback + * @param key - The key to add + * @param fallback - The fallback value to return if key is not found + * @returns The value found at key or fallback */ -function get(key, fallback) { +function get(key: string, fallback?: T): Promise { return send(NAME, GET, {key, fallback}, {expectReply: true, timeout: 10}) } /** * @description Returns the first non null config value or the fallback - * @param {string[]} wants - The keys to search for - * @param {*} fallback - The fallback value to return if key is not found - * @returns {Promise<*>} - The value found at key or fallback + * @param wants - The keys to search for + * @param fallback - The fallback value to return if key is not found + * @returns The value found at key or fallback */ -async function first(wants = [], fallback) { +async function first(wants: string[] = [], fallback: T): Promise { if (!wants.length) return fallback const [head, ...rest] = wants - const ret = await get(head) + const ret = await get(head) if (ret == null) return first(rest, fallback) return ret } /** * @description Returns the current config - * @returns {Promise} - The current config + * @returns The config object */ -function all() { +function all(): Promise> { return send(NAME, GET_ALL, null, {expectReply: true, timeout: 10}) } /** * @description Updates a key-value pair in the config - * @param {string} key - The key to update - * @param {Function} fn - The function to update the value with - * @returns {Promise} - The current config + * @param key - The key to update + * @param fn - The function to update the value with + * @returns The config object */ -function update(key, fn = identity) { +function update(key: string, fn: (x: T) => T = identity) { send(NAME, UPDATE, {key, fn}) return config() } /** * @description Deletes a key-value pair from the config - * @param {string} key - The key to delete - * @returns {Promise} - The current config + * @param key - The key to delete + * @returns The config object */ -function _delete(key) { +function _delete(key: string) { send(NAME, DELETE, {key}) return config() } /** * @description Returns a subset of the config based on a pattern - * @param {string} pattern - The pattern to match keys against - * @returns {Promise} - The subset of the config + * @param pattern - The pattern to match keys against + * @returns The subset of the config */ -function where(pattern) { +function where(pattern: RegExp): Promise> { return send(NAME, WHERE, {pattern}, {expectReply: true, timeout: 10}) } /** * @description Subscribes to config updates - * @param {Function} callback - The callback to call when config is updated - * @returns {Function} - The unsubscribe function + * @param callback - The callback to call when config is updated + * @returns The unsubscribe function */ -function subscribe(callback) { +function subscribe( + callback: ( + config: Record | null, + error: Error | null + ) => void +): () => void { return subscriber(NAME, () => spawn(HANDLERS, NAME), callback) } /** * @description Clears the config - * @returns {void} */ -export function clearConfig() { - return send(NAME, CLEAR) +export async function clearConfig(): Promise { + await send(NAME, CLEAR) } /** * @description Resets the config to a previous state - * @param {object} oldConfig - The previous config state - * @returns {Promise} - The current config + * @param oldConfig - The previous config state + * @returns The config object */ -function resetConfig(oldConfig) { - return clearConfig().then(config(oldConfig)) +async function resetConfig(oldConfig: Record) { + return clearConfig().then(() => config(oldConfig)) } /** * @description Takes in flow.json or array of flow.json files and creates contract placeholders - * @param {object|object[]} data - The flow.json or array of flow.json files - * @returns {void} + * @param data - The data to load + * @param data.flowJSON - The flow.json or array of flow.json files */ -async function load(data) { - const network = await get("flow.network") +async function load(data: { + flowJSON: Record | Record[] +}) { + const network: string = await get("flow.network") const cleanedNetwork = cleanNetwork(network) const {flowJSON} = data invariant(Boolean(flowJSON), "config.load -- 'flowJSON' must be defined") invariant( - cleanedNetwork, + !!cleanedNetwork, `Flow Network Required -- In order for FCL to load your contracts please define "flow.network" to "emulator", "local", "testnet", or "mainnet" in your config. See more here: https://developers.flow.com/tools/fcl-js/reference/configure-fcl` ) @@ -232,12 +239,12 @@ async function load(data) { } } -// eslint-disable-next-line jsdoc/require-returns /** * @description Sets the config - * @param {object} [values] - The values to set + * @param values - The values to set + * @returns The config object */ -function config(values) { +function config(values?: Record) { if (values != null && typeof values === "object") { Object.keys(values).map(d => put(d, values[d])) } @@ -269,18 +276,22 @@ config.load = load export {config} -const noop = v => v -function overload(opts = {}, callback = noop) { - return new Promise(async (resolve, reject) => { - const oldConfig = await all() - try { - config(opts) - var result = await callback(await all()) - await resetConfig(oldConfig) - resolve(result) - } catch (error) { - await resetConfig(oldConfig) - reject(error) - } - }) +/** + * @description Temporarily overloads the config with the given values and calls the callback + * @param values - The values to overload the config with + * @param callback - The callback to call with the overloaded config + * @returns The result of the callback + */ +async function overload( + values: Record, + callback: (oldConfig: Record) => T +) { + const oldConfig = await all() + try { + config(values) + const result = await callback(await all()) + return result + } finally { + await resetConfig(oldConfig) + } } diff --git a/packages/config/utils/utils.test.js b/packages/config/src/utils/utils.test.ts similarity index 96% rename from packages/config/utils/utils.test.js rename to packages/config/src/utils/utils.test.ts index 74f2e59c7..8c056b6c0 100644 --- a/packages/config/utils/utils.test.js +++ b/packages/config/src/utils/utils.test.ts @@ -1,8 +1,8 @@ -import {getContracts, anyHasPrivateKeys} from "./utils" +import {getContracts, anyHasPrivateKeys, FlowJson} from "./utils" describe("getContracts", () => { test("it should gather contract aliases for flow.json", () => { - const flowJSON = { + const flowJSON: FlowJson = { networks: { emulator: "127.0.0.1:3569", mainnet: "access.mainnet.nodes.onflow.org:9000", @@ -139,8 +139,8 @@ describe("anyHasPrivateKeys", () => { address: "f8d6e0586b0a20c7", key: { type: "file", - location: "./emulator.key" - } + location: "./emulator.key", + }, }, }, } @@ -157,7 +157,7 @@ describe("anyHasPrivateKeys", () => { accounts: { "emulator-account": { address: "f8d6e0586b0a20c7", - key: "ba68d45a5acaa52f3cacf4ad3a64d9523e0ce0ae3addb1ee6805385b380b7646" + key: "ba68d45a5acaa52f3cacf4ad3a64d9523e0ce0ae3addb1ee6805385b380b7646", }, }, } diff --git a/packages/config/src/utils/utils.ts b/packages/config/src/utils/utils.ts new file mode 100644 index 000000000..b9509525a --- /dev/null +++ b/packages/config/src/utils/utils.ts @@ -0,0 +1,222 @@ +type FlowNetwork = "emulator" | "testnet" | "mainnet" +export interface FlowJson { + networks?: { + [key in FlowNetwork]?: string + } + accounts?: { + [key: string]: { + address: string + key?: string | object + } + } + contracts?: { + [key: string]: { + source: string + aliases: { + [key in FlowNetwork]?: string + } + } + } + deployments?: { + [key in FlowNetwork]?: { + [contract: string]: string[] + } + } +} + +const pipe = + (...funcs: ((v: any) => any)[]) => + (v: any) => { + return funcs.reduce((res, func) => { + return func(res) + }, v) + } + +/*** + * Merge multiple functions returning objects into one object. + * @param funcs - Functions to merge + * @return Merged object + */ +const mergePipe = + (...funcs: ((v: any) => any)[]) => + (v: any) => { + return funcs.reduce((res, func) => { + return {...res, ...func(v)} + }, {}) + } + +/** + * @description Object check + * @param value - Value to check + * @returns Is object status + */ +const isObject = (value: T): boolean => + value && typeof value === "object" && !Array.isArray(value) + +/** + * @description Deep merge multiple objects. + * @param target - Target object + * @param sources - Source objects + * @returns Merged object + */ +const mergeDeep = (target: any, ...sources: any[]): any => { + if (!sources.length) return target + const source = sources.shift() + + if (isObject(target) && isObject(source)) { + for (const key in source) { + if (isObject(source[key])) { + if (!target[key]) Object.assign(target, {[key]: {}}) + mergeDeep(target[key], source[key]) + } else { + Object.assign(target, {[key]: source[key]}) + } + } + } + + return mergeDeep(target, ...sources) +} + +/** + * @description Support if/then/else behavior in a function way. + * @param testFn - Function to test + * @param posCond - Function to run if testFn is true + * @param negCond - Function to run it testFn is false + * @returns Function that returns the result of posCond or negCond + */ +export const ifElse = + (testFn: (v: T) => U, posCond: (v: T) => U, negCond: (v: T) => U) => + (v: T) => + testFn(v) ? posCond(v) : negCond(v) + +/** + * @description Deep merge multiple Flow JSON. + * @param value - Flow JSON or array of Flow JSONs + * @returns Merged Flow JSON + */ +const mergeFlowJSONs = (value: FlowJson | FlowJson[]) => + Array.isArray(value) ? mergeDeep({}, ...value) : value + +/** + * @description Filter out contracts section of flow.json. + * @param obj - Flow JSON + * @returns Contracts section of Flow JSON + */ +const filterContracts = (obj: FlowJson) => (obj.contracts ? obj.contracts : {}) + +/** + * @description Gathers contract addresses by network + * @param network - Network to gather addresses for + * @returns Contract names by addresses mapping e.g { "HelloWorld": "0x123" } + */ +const mapContractAliasesToNetworkAddress = + (network: string) => (contracts: Record) => { + return Object.entries(contracts).reduce((c, [key, value]) => { + const networkContractAlias = value?.aliases?.[network] + if (networkContractAlias) { + c[key] = networkContractAlias + } + + return c + }, {} as Record) + } + +const mapDeploymentsToNetworkAddress = + (network: FlowNetwork) => + ({ + deployments = {}, + accounts = {}, + }: Pick) => { + const networkDeployment = deployments?.[network] + if (!networkDeployment) return {} + + return Object.entries(networkDeployment).reduce((c, [key, value]) => { + // Resolve account address + const accountAddress = accounts[key]?.address + if (!accountAddress) return c + + // Create an object assigning the address to the contract name. + return value.reduce((c, contract) => { + return {...c, [contract]: accountAddress} + }, {}) + }, {}) + } + +/** + * @description Take in flow.json files and return contract to address mapping by network + * @param jsons - Flow JSON or array of Flow JSONs + * @param network - Network to gather addresses for + * @returns Contract names by addresses mapping e.g { "HelloWorld": "0x123" } + */ +export const getContracts = ( + jsons: FlowJson | FlowJson[], + network: FlowNetwork +) => { + return pipe( + mergeFlowJSONs, + mergePipe( + mapDeploymentsToNetworkAddress(network), + pipe(filterContracts, mapContractAliasesToNetworkAddress(network)) + ) + )(jsons) +} + +/** + * @description Checks if string is hexidecimal + * @param str - String to check + * @returns Is hexidecimal status + */ +const isHexidecimal = (str: unknown) => { + // Check that it is a string + if (typeof str !== "string") return false + return /^[0-9A-Fa-f]+$/.test(str) +} + +/** + * @description Checks flow.json file for private keys + * @param flowJSON - Flow JSON + * @returns Has private keys status + */ +const hasPrivateKeys = (flowJSON: FlowJson) => { + return Object.entries(flowJSON?.accounts ?? []).reduce( + (hasPrivateKey, [, value]) => { + if (hasPrivateKey) return true + return ( + value && + Object.prototype.hasOwnProperty.call(value, "key") && + isHexidecimal(value?.key) + ) + }, + false + ) +} + +/** + * @description Take in flow.json or array of flow.json files and checks for private keys + * @param value - Flow JSON or array of Flow JSONs + * @returns Has private keys status + */ +export const anyHasPrivateKeys = (value: FlowJson | FlowJson[]) => { + if (Array.isArray(value)) return value.some(hasPrivateKeys) + return hasPrivateKeys(value) +} + +/** + * @description Format network to always be 'emulator', 'testnet', or 'mainnet' + * @param network - Network to format + * @returns Formatted network name (either 'emulator', 'testnet', or 'mainnet') + */ +export const cleanNetwork = (network: string): FlowNetwork => { + const cleanedNetwork = + network?.toLowerCase() === "local" ? "emulator" : network?.toLowerCase() + if ( + cleanedNetwork === "emulator" || + cleanedNetwork === "testnet" || + cleanedNetwork === "mainnet" + ) + return cleanedNetwork + + throw new Error( + `Invalid network "${network}". Must be one of "emulator", "local", "testnet", or "mainnet"` + ) +} diff --git a/packages/config/tsconfig.json b/packages/config/tsconfig.json index ef17eba8e..ac6917898 100644 --- a/packages/config/tsconfig.json +++ b/packages/config/tsconfig.json @@ -1,24 +1,11 @@ { + "extends": "../../tsconfig", // Change this to match your project "include": ["src/**/*"], - "exclude": [ - "src/**/*.test.js", - ], "compilerOptions": { - // Tells TypeScript to read JS files, as - // normally they are ignored as source files - "allowJs": true, - // Generate d.ts files - "declaration": true, - // This compiler run should - // only output d.ts files - "emitDeclarationOnly": true, // Types should go into this directory. // Removing this would place the .d.ts files // next to the .js files - "outDir": "types", - // go to js file when using IDE functions like - // "Go to Definition" in VSCode - "declarationMap": false, + "outDir": "types" } -} \ No newline at end of file +} diff --git a/packages/config/utils/utils.js b/packages/config/utils/utils.js deleted file mode 100644 index 23ac51ed4..000000000 --- a/packages/config/utils/utils.js +++ /dev/null @@ -1,171 +0,0 @@ -const pipe = - (...funcs) => - v => { - return funcs.reduce((res, func) => { - return func(res) - }, v) - } - -/*** - * Merge multiple functions returning objects into one object. - * @param {...function(*): object} funcs - Functions to merge - * @return {object} - Merged object - */ -const mergePipe = - (...funcs) => - v => { - return funcs.reduce((res, func) => { - return {...res, ...func(v)} - }, {}) - } - -/** - * @description Object check - * @param {*} value - Value to check - * @returns {boolean} - Is object status - */ -const isObject = value => - value && typeof value === "object" && !Array.isArray(value) - -/** - * @description Deep merge multiple objects. - * @param {object} target - Target object - * @param {...object[]} sources - Source objects - * @returns {object} - Merged object - */ -const mergeDeep = (target, ...sources) => { - if (!sources.length) return target - const source = sources.shift() - - if (isObject(target) && isObject(source)) { - for (const key in source) { - if (isObject(source[key])) { - if (!target[key]) Object.assign(target, {[key]: {}}) - mergeDeep(target[key], source[key]) - } else { - Object.assign(target, {[key]: source[key]}) - } - } - } - - return mergeDeep(target, ...sources) -} - -/** - * @description Support if/then/else behavior in a function way. - * @param {function(object): boolean} testFn - Function to test - * @param {function(object): *} posCond - Function to run if testFn is true - * @param {function(object): *} negCond - Function to run it testFn is false - * @returns {function(*): *} - Function that returns the result of posCond or negCond - */ -export const ifElse = (testFn, posCond, negCond) => obj => - testFn(obj) ? posCond(obj) : negCond(obj) - -/** - * @description Deep merge multiple Flow JSON. - * @param {object|object[]} value - Flow JSON or array of Flow JSONs - * @returns {object} - Merged Flow JSON - */ -const mergeFlowJSONs = value => - Array.isArray(value) ? mergeDeep({}, ...value) : value - -/** - * @description Filter out contracts section of flow.json. - * @param {object|object[]} obj - Flow JSON or array of Flow JSONs - * @returns {object} - Contracts section of Flow JSON - */ -const filterContracts = obj => (obj.contracts ? obj.contracts : {}) - -/** - * @description Gathers contract addresses by network - * @param {string} network - Network to gather addresses for - * @returns {object} - Contract names by addresses mapping e.g { "HelloWorld": "0x123" } - */ -const mapContractAliasesToNetworkAddress = network => contracts => { - return Object.entries(contracts).reduce((c, [key, value]) => { - const networkContractAlias = value?.aliases?.[network] - if (networkContractAlias) { - c[key] = networkContractAlias - } - - return c - }, {}) -} - -const mapDeploymentsToNetworkAddress = - network => - ({deployments = {}, accounts = {}}) => { - const networkDeployment = deployments?.[network] - if (!networkDeployment) return {} - - return Object.entries(networkDeployment).reduce((c, [key, value]) => { - // Resolve account address - const accountAddress = accounts[key]?.address - if (!accountAddress) return c - - // Create an object assigning the address to the contract name. - return value.reduce((c, contract) => { - return {...c, [contract]: accountAddress} - }, {}) - }, {}) - } - -/** - * @description Take in flow.json files and return contract to address mapping by network - * @param {object|object[]} jsons - Flow JSON or array of Flow JSONs - * @param {string} network - Network to gather addresses for - * @returns {object} - Contract names by addresses mapping e.g { "HelloWorld": "0x123" } - */ -export const getContracts = (jsons, network) => { - return pipe( - mergeFlowJSONs, - mergePipe( - mapDeploymentsToNetworkAddress(network), - pipe(filterContracts, mapContractAliasesToNetworkAddress(network)) - ) - )(jsons) -} - -/** - * @description Checks if string is hexidecimal - * @param {string} str - String to check - * @returns {boolean} - Is hexidecimal status - */ -const isHexidecimal = str => { - // Check that it is a string - if (typeof str !== "string") return false - return /^[0-9A-Fa-f]+$/.test(str) -} - -/** - * @description Checks flow.json file for private keys - * @param {object} flowJSON - Flow JSON - * @returns {boolean} - Has private keys status - */ -const hasPrivateKeys = flowJSON => { - return Object.entries(flowJSON?.accounts).reduce( - (hasPrivateKey, [key, value]) => { - if (hasPrivateKey) return true - return value?.hasOwnProperty("key") && isHexidecimal(value?.key) - }, - false - ) -} - -/** - * @description Take in flow.json or array of flow.json files and checks for private keys - * @param {object|object[]} value - Flow JSON or array of Flow JSONs - * @returns {boolean} - Has private keys status - */ -export const anyHasPrivateKeys = value => { - if (isObject(value)) return hasPrivateKeys(value) - return value.some(hasPrivateKeys) -} - -/** - * @description Format network to always be 'emulator', 'testnet', or 'mainnet' - * @param {string} network - Network to format - * @returns {string} - Formatted network name (either 'emulator', 'testnet', or 'mainnet') - */ -export const cleanNetwork = network => - network?.toLowerCase() === "local" ? "emulator" : network?.toLowerCase() diff --git a/packages/fcl-bundle/package.json b/packages/fcl-bundle/package.json index 8da987fa7..ac6580793 100644 --- a/packages/fcl-bundle/package.json +++ b/packages/fcl-bundle/package.json @@ -1,6 +1,6 @@ { "name": "@onflow/fcl-bundle", - "version": "1.3.1", + "version": "1.4.0-typescript.0", "description": "FCL Bundler Tool", "license": "Apache-2.0", "author": "Dapper Labs ", @@ -15,6 +15,7 @@ "dependencies": { "@babel/plugin-transform-runtime": "^7.18.2", "@babel/preset-env": "^7.18.2", + "@babel/preset-typescript": "^7.22.5", "@rollup/plugin-babel": "^6.0.3", "@rollup/plugin-commonjs": "^25.0.2", "@rollup/plugin-node-resolve": "^15.1.0", @@ -23,7 +24,8 @@ "builtin-modules": "^3.3.0", "commander": "^9.3.0", "lodash": "^4.17.21", - "rollup": "^2.75.5" + "rollup": "^2.75.5", + "rollup-plugin-typescript2": "^0.35.0" }, "bin": { "fcl-bundle": "src/cli.js" diff --git a/packages/fcl-bundle/src/build/get-input-options.js b/packages/fcl-bundle/src/build/get-input-options.js index e3906a391..0f01d0f21 100644 --- a/packages/fcl-bundle/src/build/get-input-options.js +++ b/packages/fcl-bundle/src/build/get-input-options.js @@ -4,7 +4,9 @@ const commonjs = require("@rollup/plugin-commonjs") const replace = require("@rollup/plugin-replace") const {nodeResolve} = require("@rollup/plugin-node-resolve") const {babel} = require("@rollup/plugin-babel") -const terser = require('@rollup/plugin-terser') +const terser = require("@rollup/plugin-terser") +const typescript = require("rollup-plugin-typescript2") +const {DEFAULT_EXTENSIONS} = require("@babel/core") const builtinModules = require("builtin-modules") @@ -15,12 +17,17 @@ const SUPPRESSED_WARNING_CODES = [ ] module.exports = function getInputOptions(package, build) { + // ensure that that package has the required dependencies if (!package.dependencies["@babel/runtime"]) { throw new Error( `${package.name} is missing required @babel/runtime dependency. Please add this to the package.json and try again.` ) } + // determine if we are building typescript + const source = build.source + const isTypeScript = source.endsWith(".ts") + const babelRuntimeVersion = package.dependencies["@babel/runtime"].replace( /^[^0-9]*/, "" @@ -43,7 +50,11 @@ module.exports = function getInputOptions(package, build) { }, false)) // exclude peer dependencies - const resolveOnly = [new RegExp(`^(?!${Object.keys(package.peerDependencies || {}).join("|")}).*`)] + const resolveOnly = [ + new RegExp( + `^(?!${Object.keys(package.peerDependencies || {}).join("|")}).*` + ), + ] let options = { input: build.source, @@ -53,19 +64,33 @@ module.exports = function getInputOptions(package, build) { console.warn(message.toString()) }, plugins: [ - replace({ - preventAssignment: true, - PACKAGE_CURRENT_VERSION: JSON.stringify(package.version), - }), - commonjs(), nodeResolve({ browser: true, preferBuiltins: build.type !== "umd", resolveOnly, }), + commonjs(), + isTypeScript && + typescript({ + clean: true, + include: [ + "*.ts+(|x)", + "**/*.ts+(|x)", + "**/*.cts", + "**/*.mts", + "*.js+(|x)", + "**/*.js+(|x)", + "**/*.cjs", + "**/*.mjs", + ], + }), + replace({ + preventAssignment: true, + PACKAGE_CURRENT_VERSION: JSON.stringify(package.version), + }), babel({ babelHelpers: "runtime", - presets: [["@babel/preset-env"]], + presets: ["@babel/preset-env", "@babel/preset-typescript"], plugins: [ [ "@babel/plugin-transform-runtime", @@ -75,6 +100,7 @@ module.exports = function getInputOptions(package, build) { ], ], sourceMaps: true, + extensions: [...DEFAULT_EXTENSIONS, ".ts", ".tsx"], }), /\.min\.js$/.test(build.entry) && terser({ diff --git a/packages/fcl-bundle/tsconfig.json b/packages/fcl-bundle/tsconfig.json new file mode 100644 index 000000000..88be905eb --- /dev/null +++ b/packages/fcl-bundle/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig", + // Change this to match your project + "include": ["src/**/*"], + "compilerOptions": { + // Types should go into this directory. + // Removing this would place the .d.ts files + // next to the .js files + "outDir": "types", + } +} \ No newline at end of file diff --git a/packages/fcl-wc/package.json b/packages/fcl-wc/package.json index 6cd00fbd5..8e0dbfffc 100644 --- a/packages/fcl-wc/package.json +++ b/packages/fcl-wc/package.json @@ -1,6 +1,6 @@ { "name": "@onflow/fcl-wc", - "version": "4.0.0", + "version": "5.0.0-typescript.0", "description": "WalletConnect adapter for FCL", "license": "Apache-2.0", "author": "Dapper Labs ", @@ -25,21 +25,21 @@ "start": "fcl-bundle --watch" }, "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", "better-sqlite3": "^7.6.2", "jest": "^29.5.0" }, "dependencies": { "@babel/runtime": "^7.18.9", - "@onflow/config": "^1.1.2", - "@onflow/util-invariant": "^1.1.0", - "@onflow/util-logger": "^1.2.2", + "@onflow/config": "^1.2.0-typescript.0", + "@onflow/util-invariant": "^1.2.0-typescript.0", + "@onflow/util-logger": "^1.3.0-typescript.0", "@walletconnect/modal": "^2.4.7", "@walletconnect/sign-client": "^2.8.1", "@walletconnect/types": "^2.8.1", "@walletconnect/utils": "^2.8.1" }, "peerDependencies": { - "@onflow/fcl": "^1.6.0" + "@onflow/fcl": "^1.8.0-typescript.0" } } diff --git a/packages/fcl-wc/tsconfig.json b/packages/fcl-wc/tsconfig.json new file mode 100644 index 000000000..88be905eb --- /dev/null +++ b/packages/fcl-wc/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig", + // Change this to match your project + "include": ["src/**/*"], + "compilerOptions": { + // Types should go into this directory. + // Removing this would place the .d.ts files + // next to the .js files + "outDir": "types", + } +} \ No newline at end of file diff --git a/packages/fcl/package.json b/packages/fcl/package.json index 7a6314f4a..6b65e8343 100644 --- a/packages/fcl/package.json +++ b/packages/fcl/package.json @@ -1,6 +1,6 @@ { "name": "@onflow/fcl", - "version": "1.7.0", + "version": "1.8.0-typescript.0", "description": "Flow Client Library", "license": "Apache-2.0", "author": "Dapper Labs ", @@ -19,8 +19,8 @@ } }, "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1", - "@onflow/typedefs": "^1.1.1", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", + "@onflow/typedefs": "^1.2.0-typescript.0", "@types/estree": "^1.0.1", "@types/node": "^18.13.0", "eslint": "^8.35.0", @@ -30,12 +30,12 @@ "typescript": "^4.9.5" }, "source": { - "src/fcl.js": { + "src/fcl.ts": { "cjs": "./dist/fcl.js", "esm": "./dist/fcl.module.js", "umd": "./dist/fcl.umd.min.js" }, - "src/fcl-react-native.js": { + "src/fcl-react-native.ts": { "cjs": "./dist/fcl-react-native.js", "esm": "./dist/fcl-react-native.module.js", "umd": "./dist/fcl-react-native.umd.min.js" @@ -58,18 +58,18 @@ }, "dependencies": { "@babel/runtime": "^7.18.6", - "@onflow/config": "^1.1.2", + "@onflow/config": "^1.2.0-typescript.0", "@onflow/interaction": "0.0.11", - "@onflow/rlp": "^1.1.0", - "@onflow/sdk": "^1.2.3", - "@onflow/types": "^1.1.0", - "@onflow/util-actor": "^1.2.0", - "@onflow/util-address": "^1.1.0", - "@onflow/util-invariant": "^1.1.0", - "@onflow/util-logger": "^1.2.2", + "@onflow/rlp": "^1.2.0-typescript.0", + "@onflow/sdk": "^1.3.0-typescript.0", + "@onflow/types": "^1.2.0-typescript.0", + "@onflow/util-actor": "^1.3.0-typescript.0", + "@onflow/util-address": "^1.2.0-typescript.0", + "@onflow/util-invariant": "^1.2.0-typescript.0", + "@onflow/util-logger": "^1.3.0-typescript.0", "@onflow/util-semver": "^1.0.0", - "@onflow/util-template": "^1.1.0", - "@onflow/util-uid": "^1.1.0", + "@onflow/util-template": "^1.2.0-typescript.0", + "@onflow/util-uid": "^1.2.0-typescript.0", "cross-fetch": "^3.1.6" }, "peerDependencies": { diff --git a/packages/fcl/src/current-user/index.js b/packages/fcl/src/current-user/index.js index 6cc83b0dc..20c2e1399 100644 --- a/packages/fcl/src/current-user/index.js +++ b/packages/fcl/src/current-user/index.js @@ -150,81 +150,83 @@ const makeConfig = async ({discoveryAuthnInclude, discoveryFeaturesSuggested}) = * @param {object} [opts.platform] - platform that runs the function * @param {object} [opts.service] - Optional service to use for authentication * @param {boolean} [opts.redir=false] - Optional flag to allow window to stay open after authentication - * @returns {Promise} - User object + * @returns {function(*)Promise} - User object */ -const getAuthenticate = ({platform}) => async ({service, redir = false} = {}) => { - if ( - service && - !service?.provider?.is_installed && - service?.provider?.requires_install - ) { - window.location.href = service?.provider?.install_link - return - } +const getAuthenticate = + ({platform}) => + async ({service, redir = false} = {}) => { + if ( + service && + !service?.provider?.is_installed && + service?.provider?.requires_install + ) { + window.location.href = service?.provider?.install_link + return + } - return new Promise(async (resolve, reject) => { - spawnCurrentUser() - const opts = {redir} - const user = await snapshot() - const discoveryService = await getDiscoveryService(service) - const refreshService = serviceOfType(user.services, "authn-refresh") - let accountProofData - - if (user.loggedIn) { - if (refreshService) { - try { - const response = await execService({ - service: refreshService, - msg: accountProofData, - opts, - platform, - }) - send(NAME, SET_CURRENT_USER, await buildUser(response)) - } catch (error) { - log({ - title: `${error.name} Could not refresh wallet authentication.`, - message: error.message, - level: LEVELS.error, - }) - } finally { - return resolve(await snapshot()) + return new Promise(async (resolve, reject) => { + spawnCurrentUser() + const opts = {redir} + const user = await snapshot() + const discoveryService = await getDiscoveryService(service) + const refreshService = serviceOfType(user.services, "authn-refresh") + let accountProofData + + if (user.loggedIn) { + if (refreshService) { + try { + const response = await execService({ + service: refreshService, + msg: accountProofData, + opts, + platform, + }) + send(NAME, SET_CURRENT_USER, await buildUser(response)) + } catch (error) { + log({ + title: `${error.name} Could not refresh wallet authentication.`, + message: error.message, + level: LEVELS.error, + }) + } finally { + return resolve(await snapshot()) + } + } else { + return resolve(user) } - } else { - return resolve(user) } - } - try { - accountProofData = await getAccountProofData() - } catch (error) { - log({ - title: `${error.name} On Authentication: Could not resolve account proof data.`, - message: error.message, - level: LEVELS.error, - }) - return reject(error) - } + try { + accountProofData = await getAccountProofData() + } catch (error) { + log({ + title: `${error.name} On Authentication: Could not resolve account proof data.`, + message: error.message, + level: LEVELS.error, + }) + return reject(error) + } - try { - const response = await execService({ - service: discoveryService, - msg: accountProofData, - config: await makeConfig(discoveryService), - opts, - platform, - }) - send(NAME, SET_CURRENT_USER, await buildUser(response)) - } catch (error) { - log({ - title: `${error} On Authentication`, - message: error, - level: LEVELS.error, - }) - } finally { - resolve(await snapshot()) - } - }) -} + try { + const response = await execService({ + service: discoveryService, + msg: accountProofData, + config: await makeConfig(discoveryService), + opts, + platform, + }) + send(NAME, SET_CURRENT_USER, await buildUser(response)) + } catch (error) { + log({ + title: `${error} On Authentication`, + message: error, + level: LEVELS.error, + }) + } finally { + resolve(await snapshot()) + } + }) + } /** * @description - Unauthenticate a user @@ -243,98 +245,102 @@ const normalizePreAuthzResponse = authz => ({ authorization: (authz || {}).authorization || [], }) -const getResolvePreAuthz = ({platform}) => (authz) => { - const resp = normalizePreAuthzResponse(authz) - const axs = [] - - if (resp.proposer != null) axs.push(["PROPOSER", resp.proposer]) - for (let az of resp.payer || []) axs.push(["PAYER", az]) - for (let az of resp.authorization || []) axs.push(["AUTHORIZER", az]) - - var result = axs.map(([role, az]) => ({ - tempId: [az.identity.address, az.identity.keyId].join("|"), - addr: az.identity.address, - keyId: az.identity.keyId, - signingFunction(signable) { - return execService({service: az, msg: signable, platform}) - }, - role: { - proposer: role === "PROPOSER", - payer: role === "PAYER", - authorizer: role === "AUTHORIZER", - }, - })) - return result -} +const getResolvePreAuthz = + ({platform}) => + authz => { + const resp = normalizePreAuthzResponse(authz) + const axs = [] + + if (resp.proposer != null) axs.push(["PROPOSER", resp.proposer]) + for (let az of resp.payer || []) axs.push(["PAYER", az]) + for (let az of resp.authorization || []) axs.push(["AUTHORIZER", az]) + + var result = axs.map(([role, az]) => ({ + tempId: [az.identity.address, az.identity.keyId].join("|"), + addr: az.identity.address, + keyId: az.identity.keyId, + signingFunction(signable) { + return execService({service: az, msg: signable, platform}) + }, + role: { + proposer: role === "PROPOSER", + payer: role === "PAYER", + authorizer: role === "AUTHORIZER", + }, + })) + return result + } /** * @description * Produces the needed authorization details for the current user to submit transactions to Flow * It defines a signing function that connects to a user's wallet provider to produce signatures to submit transactions. - * + * * @param {object} ops - running options * @param {string} ops.platform - platform that runs the function * @param {object} account - Account object * @returns {Promise} - Account object with signing function */ -const getAuthorization = ({platform}) => async (account) => { - spawnCurrentUser() +const getAuthorization = + ({platform}) => + async account => { + spawnCurrentUser() - return { - ...account, - tempId: "CURRENT_USER", - async resolve(account, preSignable) { - const user = await getAuthenticate({platform})({redir: true}) - const authz = serviceOfType(user.services, "authz") - const preAuthz = serviceOfType(user.services, "pre-authz") - - if (preAuthz) - return getResolvePreAuthz({platform})( - await execService({ - service: preAuthz, - msg: preSignable, - platform, - }) - ) - if (authz) { - let windowRef - if (isMobile() && authz.method === "WC/RPC") { - windowRef = window.open("", "_blank") - } - return { - ...account, - tempId: "CURRENT_USER", - resolve: null, - addr: sansPrefix(authz.identity.address), - keyId: authz.identity.keyId, - sequenceNum: null, - signature: null, - async signingFunction(signable) { - return normalizeCompositeSignature( - await execService({ - service: authz, - msg: signable, - opts: { - includeOlderJsonRpcCall: true, - windowRef, - }, - platform, - }) - ) - }, + return { + ...account, + tempId: "CURRENT_USER", + async resolve(account, preSignable) { + const user = await getAuthenticate({platform})({redir: true}) + const authz = serviceOfType(user.services, "authz") + const preAuthz = serviceOfType(user.services, "pre-authz") + + if (preAuthz) + return getResolvePreAuthz({platform})( + await execService({ + service: preAuthz, + msg: preSignable, + platform, + }) + ) + if (authz) { + let windowRef + if (isMobile() && authz.method === "WC/RPC") { + windowRef = window.open("", "_blank") + } + return { + ...account, + tempId: "CURRENT_USER", + resolve: null, + addr: sansPrefix(authz.identity.address), + keyId: authz.identity.keyId, + sequenceNum: null, + signature: null, + async signingFunction(signable) { + return normalizeCompositeSignature( + await execService({ + service: authz, + msg: signable, + opts: { + includeOlderJsonRpcCall: true, + windowRef, + }, + platform, + }) + ) + }, + } } - } - throw new Error( - "No Authz or PreAuthz Service configured for CURRENT_USER" - ) - }, + throw new Error( + "No Authz or PreAuthz Service configured for CURRENT_USER" + ) + }, + } } -} /** * @description * The callback passed to subscribe will be called when the user authenticates and un-authenticates, making it easy to update the UI accordingly. - * + * * @param {Function} callback - Callback function * @returns {Function} - Unsubscribe function */ @@ -373,15 +379,17 @@ async function info() { /** * @description - Resolves the current user as an argument - * + * * @param {object} ops - running options * @param {string} ops.platform - platform that runs the function * @returns {Promise} */ -const getResolveArgument = ({platform}) => async () => { - const {addr} = await getAuthenticate({platform})() - return arg(withPrefix(addr), t.Address) -} +const getResolveArgument = + ({platform}) => + async () => { + const {addr} = await getAuthenticate({platform})() + return arg(withPrefix(addr), t.Address) + } const makeSignable = msg => { invariant(/^[0-9a-f]+$/i.test(msg), "Message must be a hex string") @@ -396,33 +404,34 @@ const makeSignable = msg => { * @param {string} msg - Message to sign * @returns {Promise} - Array of CompositeSignatures */ -const getSignUserMessage = ({platform}) => async (msg) => { - spawnCurrentUser() - const user = await getAuthenticate({platform})({redir: true}) +const getSignUserMessage = + ({platform}) => + async msg => { + spawnCurrentUser() + const user = await getAuthenticate({platform})({redir: true}) - const signingService = serviceOfType(user.services, "user-signature") + const signingService = serviceOfType(user.services, "user-signature") - invariant( - signingService, - "Current user must have authorized a signing service." - ) + invariant( + signingService, + "Current user must have authorized a signing service." + ) - try { - const response = await execService({ - service: signingService, - msg: makeSignable(msg), - platform, - }) - if (Array.isArray(response)) { - return response.map(compSigs => normalizeCompositeSignature(compSigs)) - } else { - return [normalizeCompositeSignature(response)] + try { + const response = await execService({ + service: signingService, + msg: makeSignable(msg), + platform, + }) + if (Array.isArray(response)) { + return response.map(compSigs => normalizeCompositeSignature(compSigs)) + } else { + return [normalizeCompositeSignature(response)] + } + } catch (error) { + return error } - } catch (error) { - return error } -} - const getCurrentUser = ({platform}) => { let currentUser = () => { diff --git a/packages/fcl/src/fcl-react-native.js b/packages/fcl/src/fcl-react-native.ts similarity index 100% rename from packages/fcl/src/fcl-react-native.js rename to packages/fcl/src/fcl-react-native.ts diff --git a/packages/fcl/src/fcl.js b/packages/fcl/src/fcl.ts similarity index 90% rename from packages/fcl/src/fcl.js rename to packages/fcl/src/fcl.ts index 2b3677330..aad1d821a 100644 --- a/packages/fcl/src/fcl.js +++ b/packages/fcl/src/fcl.ts @@ -1,10 +1,11 @@ -export * from './shared-exports'; +export * from "./shared-exports" import {getMutate} from "./exec/mutate" + export const mutate = getMutate({platform: "web"}) import {getCurrentUser} from "./current-user" -const currentUser = getCurrentUser({platform:"web"}) +const currentUser = getCurrentUser({platform: "web"}) export {currentUser} diff --git a/packages/rlp/.babelrc b/packages/rlp/.babelrc index 67fc2886b..d766c90b2 100644 --- a/packages/rlp/.babelrc +++ b/packages/rlp/.babelrc @@ -1,7 +1,3 @@ { - "presets": [ - [ - "@babel/preset-env" - ] - ] + "presets": [["@babel/preset-env"], "@babel/preset-typescript"] } diff --git a/packages/rlp/.eslintrc.json b/packages/rlp/.eslintrc.json new file mode 100644 index 000000000..815f845bc --- /dev/null +++ b/packages/rlp/.eslintrc.json @@ -0,0 +1,30 @@ +{ + "env": { + "browser": true, + "es2021": true, + "jest": true, + "node": true + }, + "extends": [ + "plugin:jsdoc/recommended-typescript", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended" + ], + "plugins": ["jsdoc", "@typescript-eslint"], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": "latest", + "sourceType": "module" + }, + "rules": { + "jsdoc/require-jsdoc": 0, + "jsdoc/tag-lines": 0, + "jsdoc/require-param-description": 0, + "jsdoc/require-param": 0, + "jsdoc/valid-types": 0, + "jsdoc/require-returns-description": 0, + "jsdoc/require-returns": 0, + "@typescript-eslint/no-explicit-any": "off" + }, + "ignorePatterns": ["**/dist/"] +} diff --git a/packages/rlp/package.json b/packages/rlp/package.json index 8ef472694..3b26b4158 100644 --- a/packages/rlp/package.json +++ b/packages/rlp/package.json @@ -1,6 +1,6 @@ { "name": "@onflow/rlp", - "version": "1.1.0", + "version": "1.2.0-typescript.0", "description": "Port of ethereumjs/rlp", "license": "MPL-2.0", "author": "Dapper Labs ", @@ -13,13 +13,20 @@ "url": "https://github.com/onflow/flow-js-sdk/issues" }, "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1-alpha.0", + "@babel/preset-typescript": "^7.22.5", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", + "@types/jest": "^29.5.3", + "@typescript-eslint/eslint-plugin": "^6.4.0", + "@typescript-eslint/parser": "^6.4.0", + "eslint": "^8.47.0", + "eslint-plugin-jsdoc": "^46.4.6", "jest": "^29.5.0" }, - "source": "src/index.js", + "source": "src/index.ts", "main": "dist/rlp.js", "module": "dist/rlp.module.js", "unpkg": "dist/rlp.umd.js", + "types": "dist/index.d.ts", "scripts": { "prepublishOnly": "npm test && npm run build", "test": "jest", diff --git a/packages/rlp/src/index.test.js b/packages/rlp/src/index.test.ts similarity index 100% rename from packages/rlp/src/index.test.js rename to packages/rlp/src/index.test.ts diff --git a/packages/rlp/src/index.js b/packages/rlp/src/index.ts similarity index 80% rename from packages/rlp/src/index.js rename to packages/rlp/src/index.ts index 3bd3a4d29..1ed6933f2 100644 --- a/packages/rlp/src/index.js +++ b/packages/rlp/src/index.ts @@ -2,6 +2,15 @@ import {Buffer} from "buffer" export {Buffer} +type EncodeInput = + | Buffer + | string + | number + | Uint8Array + | null + | undefined + | EncodeInput[] + /** * Built on top of rlp library, removing the BN dependency for the flow. * Package : https://github.com/ethereumjs/rlp @@ -10,22 +19,22 @@ export {Buffer} * ethereumjs/rlp is licensed under the * Mozilla Public License 2.0 * Permissions of this weak copyleft license are conditioned on making available source code of licensed files and modifications of those files under the same license (or in certain cases, one of the GNU licenses). Copyright and license notices must be preserved. Contributors provide an express grant of patent rights. However, a larger work using the licensed work may be distributed under different terms and without source code for files added in the larger work. - **/ + */ /** * @param input - will be converted to buffer * @returns returns buffer of encoded data - **/ -export function encode(input) { + */ +export function encode(input: EncodeInput): Buffer { if (Array.isArray(input)) { - var output = [] - for (var i = 0; i < input.length; i++) { + const output = [] + for (let i = 0; i < input.length; i++) { output.push(encode(input[i])) } - var buf = Buffer.concat(output) + const buf = Buffer.concat(output) return Buffer.concat([encodeLength(buf.length, 192), buf]) } else { - var inputBuf = toBuffer(input) + const inputBuf = toBuffer(input) return inputBuf.length === 1 && inputBuf[0] < 128 ? inputBuf : Buffer.concat([encodeLength(inputBuf.length, 128), inputBuf]) @@ -37,19 +46,19 @@ export function encode(input) { * @param v The value to parse * @param base The base to parse the integer into */ -function safeParseInt(v, base) { +function safeParseInt(v: string, base: number): number { if (v.slice(0, 2) === "00") { throw new Error("invalid RLP: extra zeros") } return parseInt(v, base) } -function encodeLength(len, offset) { +function encodeLength(len: number, offset: number): Buffer { if (len < 56) { return Buffer.from([len + offset]) } else { - var hexLength = intToHex(len) - var lLength = hexLength.length / 2 - var firstByte = intToHex(offset + 55 + lLength) + const hexLength = intToHex(len) + const lLength = hexLength.length / 2 + const firstByte = intToHex(offset + 55 + lLength) return Buffer.from(firstByte + hexLength, "hex") } } @@ -62,22 +71,22 @@ function encodeLength(len, offset) { * ethereumjs/rlp is licensed under the * Mozilla Public License 2.0 * Permissions of this weak copyleft license are conditioned on making available source code of licensed files and modifications of those files under the same license (or in certain cases, one of the GNU licenses). Copyright and license notices must be preserved. Contributors provide an express grant of patent rights. However, a larger work using the licensed work may be distributed under different terms and without source code for files added in the larger work. - **/ + */ /** * @param input - will be converted to buffer * @param stream Is the input a stream (false by default) * @returns returns buffer of encoded data - **/ -export function decode(input, stream) { + */ +export function decode(input: Buffer | Uint8Array, stream?: boolean): Buffer { if (stream === void 0) { stream = false } if (!input || input.length === 0) { return Buffer.from([]) } - var inputBuffer = toBuffer(input) - var decoded = _decode(inputBuffer) + const inputBuffer = toBuffer(input) + const decoded = _decode(inputBuffer) if (stream) { return decoded } @@ -92,12 +101,15 @@ export function decode(input, stream) { * @param input * @returns The length of the input or an empty Buffer if no input */ -export function getLength(input) { - if (!input || input.length === 0) { - return Buffer.from([]) +export function getLength( + input: Buffer | Uint8Array | null | undefined | string | number +): number { + const inputBuffer = toBuffer(input) + if (inputBuffer.length === 0) { + return 0 } - var inputBuffer = toBuffer(input) - var firstByte = inputBuffer[0] + + const firstByte = inputBuffer[0] if (firstByte <= 0x7f) { return inputBuffer.length } else if (firstByte <= 0xb7) { @@ -109,17 +121,20 @@ export function getLength(input) { return firstByte - 0xbf } else { // a list over 55 bytes long - var llength = firstByte - 0xf6 - var length = safeParseInt(inputBuffer.slice(1, llength).toString("hex"), 16) + const llength = firstByte - 0xf6 + const length = safeParseInt( + inputBuffer.slice(1, llength).toString("hex"), + 16 + ) return llength + length } } /** Decode an input with RLP */ -function _decode(input) { - var length, llength, data, innerRemainder, d - var decoded = [] - var firstByte = input[0] +function _decode(input: Buffer | Uint8Array): any { + let length, llength, data, innerRemainder, d + const decoded = [] + const firstByte = input[0] if (firstByte <= 0x7f) { // a single byte whose value is in the [0x00, 0x7f] range, that byte is its own RLP encoding. return { @@ -171,7 +186,7 @@ function _decode(input) { // a list over 55 bytes long llength = firstByte - 0xf6 length = safeParseInt(input.slice(1, llength).toString("hex"), 16) - var totalLength = llength + length + const totalLength = llength + length if (totalLength > input.length) { throw new Error("invalid rlp: total length is larger than the data") } @@ -191,36 +206,38 @@ function _decode(input) { } } /** Check if a string is prefixed by 0x */ -function isHexPrefixed(str) { +function isHexPrefixed(str: string) { return str.slice(0, 2) === "0x" } /** Removes 0x from a given String */ -function stripHexPrefix(str) { +function stripHexPrefix(str: string) { if (typeof str !== "string") { return str } return isHexPrefixed(str) ? str.slice(2) : str } /** Transform an integer into its hexadecimal value */ -function intToHex(integer) { +function intToHex(integer: number) { if (integer < 0) { throw new Error("Invalid integer as argument, must be unsigned!") } - var hex = integer.toString(16) + const hex = integer.toString(16) return hex.length % 2 ? "0" + hex : hex } /** Pad a string to be even */ -function padToEven(a) { +function padToEven(a: string) { return a.length % 2 ? "0" + a : a } /** Transform an integer into a Buffer */ -function intToBuffer(integer) { - var hex = intToHex(integer) +function intToBuffer(integer: number) { + const hex = intToHex(integer) return Buffer.from(hex, "hex") } /** Transform anything into a Buffer */ -export function toBuffer(v) { +export function toBuffer( + v: Buffer | string | number | Uint8Array | null | undefined +) { if (!Buffer.isBuffer(v)) { if (typeof v === "string") { if (isHexPrefixed(v)) { diff --git a/packages/rlp/tsconfig.json b/packages/rlp/tsconfig.json new file mode 100644 index 000000000..ac6917898 --- /dev/null +++ b/packages/rlp/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig", + // Change this to match your project + "include": ["src/**/*"], + "compilerOptions": { + // Types should go into this directory. + // Removing this would place the .d.ts files + // next to the .js files + "outDir": "types" + } +} diff --git a/packages/sdk/.babelrc b/packages/sdk/.babelrc index 779f5464f..1e3225d50 100644 --- a/packages/sdk/.babelrc +++ b/packages/sdk/.babelrc @@ -5,6 +5,7 @@ { "useBuiltIns": false } - ] + ], + "@babel/preset-typescript" ] } diff --git a/packages/sdk/package.json b/packages/sdk/package.json index bdb95abfa..ec29f38c2 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@onflow/sdk", - "version": "1.2.3", + "version": "1.3.0-typescript.0", "description": "Flow SDK", "license": "Apache-2.0", "author": "Dapper Labs ", @@ -18,14 +18,14 @@ } }, "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1", - "@onflow/typedefs": "^1.1.1", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", + "@onflow/typedefs": "^1.2.0-typescript.0", "eslint": "^8.35.0", "eslint-plugin-jsdoc": "^40.0.1", "jest": "^29.5.0", "typescript": "^4.9.5" }, - "source": "src/sdk.js", + "source": "src/sdk.ts", "main": "dist/sdk.js", "module": "dist/sdk.module.js", "unpkg": "dist/sdk.umd.js", @@ -35,21 +35,20 @@ "prepublishOnly": "npm test && npm run build", "test": "jest", "build": "npm run lint && fcl-bundle", - "build:types": "tsc", "test:watch": "jest --watch", "start": "fcl-bundle --watch", "lint": "eslint ." }, "dependencies": { "@babel/runtime": "^7.18.6", - "@onflow/config": "^1.1.1", - "@onflow/rlp": "^1.1.0", - "@onflow/transport-http": "^1.7.2", - "@onflow/util-actor": "^1.2.0", - "@onflow/util-address": "^1.1.0", - "@onflow/util-invariant": "^1.1.0", - "@onflow/util-logger": "^1.2.1", - "@onflow/util-template": "^1.1.0", + "@onflow/config": "^1.2.0-typescript.0", + "@onflow/rlp": "^1.2.0-typescript.0", + "@onflow/transport-http": "^1.8.0-typescript.0", + "@onflow/util-actor": "^1.3.0-typescript.0", + "@onflow/util-address": "^1.2.0-typescript.0", + "@onflow/util-invariant": "^1.2.0-typescript.0", + "@onflow/util-logger": "^1.3.0-typescript.0", + "@onflow/util-template": "^1.2.0-typescript.0", "deepmerge": "^4.2.2", "sha3": "^2.1.4", "uuid": "^9.0.1" diff --git a/packages/sdk/src/resolve/resolve-accounts.test.js b/packages/sdk/src/resolve/resolve-accounts.test.js index c370bb93d..0f4017874 100644 --- a/packages/sdk/src/resolve/resolve-accounts.test.js +++ b/packages/sdk/src/resolve/resolve-accounts.test.js @@ -7,8 +7,8 @@ import { payer, limit, authorizations, -} from "../sdk.js" -import {buildPreSignable, resolveAccounts} from "./resolve-accounts" +} from "../sdk" +import {buildPreSignable} from "./resolve-accounts" test("Voucher in PreSignable", async () => { const authz = { diff --git a/packages/sdk/src/resolve/resolve-arguments.test.js b/packages/sdk/src/resolve/resolve-arguments.test.js index 79ec830c4..ebf30cea7 100644 --- a/packages/sdk/src/resolve/resolve-arguments.test.js +++ b/packages/sdk/src/resolve/resolve-arguments.test.js @@ -1,4 +1,4 @@ -import {resolveArguments} from "../sdk.js" +import {resolveArguments} from "../sdk" describe("resolveArguments", () => { const argID = "28948a11n4" diff --git a/packages/sdk/src/resolve/resolve-signatures.test.js b/packages/sdk/src/resolve/resolve-signatures.test.js index 5bbc888f7..30465ad7e 100644 --- a/packages/sdk/src/resolve/resolve-signatures.test.js +++ b/packages/sdk/src/resolve/resolve-signatures.test.js @@ -8,7 +8,7 @@ import { payer, limit, authorizations, -} from "../sdk.js" +} from "../sdk" const signingFunction = jest.fn(() => ({ addr: "foo", diff --git a/packages/sdk/src/sdk.test.js b/packages/sdk/src/sdk.test.js index a86d9ddf8..9ee3543eb 100644 --- a/packages/sdk/src/sdk.test.js +++ b/packages/sdk/src/sdk.test.js @@ -10,7 +10,7 @@ import { payer, authorization, VERSION, -} from "./sdk.js" +} from "./sdk" test("fcl.VERSION needs to match version in package.json", () => { expect(VERSION).toBe("TESTVERSION") diff --git a/packages/sdk/src/sdk.js b/packages/sdk/src/sdk.ts similarity index 97% rename from packages/sdk/src/sdk.js rename to packages/sdk/src/sdk.ts index 6e0f2adc9..9a4decc99 100644 --- a/packages/sdk/src/sdk.js +++ b/packages/sdk/src/sdk.ts @@ -83,7 +83,7 @@ export {resolveVoucherIntercept} from "./resolve/resolve-voucher-intercept.js" export {config} from "@onflow/config" // Deprecated -export const params = params => +export const params = (params: never) => logger.log.deprecate({ pkg: "FCL/SDK", message: `The params builder has been removed from the Flow JS-SDK/FCL.`, @@ -91,7 +91,7 @@ export const params = params => "https://github.com/onflow/flow-js-sdk/blob/master/packages/sdk/TRANSITIONS.md#0001-deprecate-params", level: logger.LEVELS.error, }) -export const param = params => +export const param = (params: never) => logger.log.deprecate({ pkg: "FCL/SDK", message: `The param builder has been removed from the Flow JS-SDK/FCL.`, @@ -103,4 +103,4 @@ export const param = params => import * as TestUtils from "./test-utils" export {TestUtils} -export {VERSION} from "./VERSION" \ No newline at end of file +export {VERSION} from "./VERSION" diff --git a/packages/sdk/tsconfig.json b/packages/sdk/tsconfig.json index ef17eba8e..ac6917898 100644 --- a/packages/sdk/tsconfig.json +++ b/packages/sdk/tsconfig.json @@ -1,24 +1,11 @@ { + "extends": "../../tsconfig", // Change this to match your project "include": ["src/**/*"], - "exclude": [ - "src/**/*.test.js", - ], "compilerOptions": { - // Tells TypeScript to read JS files, as - // normally they are ignored as source files - "allowJs": true, - // Generate d.ts files - "declaration": true, - // This compiler run should - // only output d.ts files - "emitDeclarationOnly": true, // Types should go into this directory. // Removing this would place the .d.ts files // next to the .js files - "outDir": "types", - // go to js file when using IDE functions like - // "Go to Definition" in VSCode - "declarationMap": false, + "outDir": "types" } -} \ No newline at end of file +} diff --git a/packages/transport-grpc/package.json b/packages/transport-grpc/package.json index 5689cc493..1711a0b76 100644 --- a/packages/transport-grpc/package.json +++ b/packages/transport-grpc/package.json @@ -1,6 +1,6 @@ { "name": "@onflow/transport-grpc", - "version": "1.2.2", + "version": "1.3.0-typescript.0", "description": "Flow SDK GRPC Transport Module", "license": "Apache-2.0", "author": "Dapper Labs ", @@ -13,8 +13,8 @@ "url": "https://github.com/onflow/flow-js-sdk/issues" }, "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1", - "@onflow/sdk": "^1.2.3", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", + "@onflow/sdk": "^1.3.0-typescript.0", "jest": "^29.5.0" }, "source": "src/sdk-send-grpc.js", @@ -34,9 +34,9 @@ "@improbable-eng/grpc-web": "^0.14.0", "@improbable-eng/grpc-web-node-http-transport": "^0.14.0", "@onflow/protobuf": "^1.2.1", - "@onflow/rlp": "^1.1.0", - "@onflow/util-address": "^1.1.0", - "@onflow/util-invariant": "^1.1.0", - "@onflow/util-template": "^1.1.0" + "@onflow/rlp": "^1.2.0-typescript.0", + "@onflow/util-address": "^1.2.0-typescript.0", + "@onflow/util-invariant": "^1.2.0-typescript.0", + "@onflow/util-template": "^1.2.0-typescript.0" } } diff --git a/packages/transport-grpc/tsconfig.json b/packages/transport-grpc/tsconfig.json new file mode 100644 index 000000000..88be905eb --- /dev/null +++ b/packages/transport-grpc/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig", + // Change this to match your project + "include": ["src/**/*"], + "compilerOptions": { + // Types should go into this directory. + // Removing this would place the .d.ts files + // next to the .js files + "outDir": "types", + } +} \ No newline at end of file diff --git a/packages/transport-http/package.json b/packages/transport-http/package.json index 222dc0345..1940fde3b 100644 --- a/packages/transport-http/package.json +++ b/packages/transport-http/package.json @@ -1,6 +1,6 @@ { "name": "@onflow/transport-http", - "version": "1.7.2", + "version": "1.8.0-typescript.0", "description": "Flow SDK HTTP Transport Module", "license": "Apache-2.0", "author": "Dapper Labs ", @@ -13,10 +13,10 @@ "url": "https://github.com/onflow/flow-js-sdk/issues" }, "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1", - "@onflow/rlp": "^1.1.0", - "@onflow/sdk": "^1.2.3", - "@onflow/types": "^1.1.0", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", + "@onflow/rlp": "^1.2.0-typescript.0", + "@onflow/sdk": "^1.3.0-typescript.0", + "@onflow/types": "^1.2.0-typescript.0", "jest": "^29.5.0" }, "source": "src/sdk-send-http.js", @@ -33,10 +33,10 @@ }, "dependencies": { "@babel/runtime": "^7.18.6", - "@onflow/util-address": "^1.1.0", - "@onflow/util-invariant": "^1.1.0", - "@onflow/util-logger": "^1.2.1", - "@onflow/util-template": "^1.1.0", + "@onflow/util-address": "^1.2.0-typescript.0", + "@onflow/util-invariant": "^1.2.0-typescript.0", + "@onflow/util-logger": "^1.3.0-typescript.0", + "@onflow/util-template": "^1.2.0-typescript.0", "abort-controller": "^3.0.0", "cross-fetch": "^3.1.6" } diff --git a/packages/transport-http/tsconfig.json b/packages/transport-http/tsconfig.json new file mode 100644 index 000000000..88be905eb --- /dev/null +++ b/packages/transport-http/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig", + // Change this to match your project + "include": ["src/**/*"], + "compilerOptions": { + // Types should go into this directory. + // Removing this would place the .d.ts files + // next to the .js files + "outDir": "types", + } +} \ No newline at end of file diff --git a/packages/typedefs/package.json b/packages/typedefs/package.json index fbe513cf7..ffb6d1f5c 100644 --- a/packages/typedefs/package.json +++ b/packages/typedefs/package.json @@ -1,6 +1,6 @@ { "name": "@onflow/typedefs", - "version": "1.1.1", + "version": "1.2.0-typescript.0", "description": "Flow JS Type Defs", "license": "Apache-2.0", "author": "Dapper Labs ", @@ -13,7 +13,7 @@ "url": "https://github.com/onflow/flow-js-sdk/issues" }, "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", "@types/node": "^18.13.0", "eslint": "^8.33.0", "eslint-plugin-jsdoc": "^39.7.5", @@ -21,16 +21,15 @@ "jest-esm-transformer": "1.0.0", "typescript": "^4.9.5" }, - "source": "src/index.js", + "source": "src/index.ts", "main": "dist/typedefs.js", "module": "dist/typedefs.module.js", "unpkg": "dist/typedefs.umd.js", - "types": "types/index.d.ts", + "types": "dist/index.d.ts", "scripts": { "prepublishOnly": "npm test && npm run build", "test": "jest", "build": "npm run lint && fcl-bundle", - "build:types": "tsc", "test:watch": "jest --watch", "start": "fcl-bundle --watch", "lint": "eslint ." diff --git a/packages/typedefs/src/index.js b/packages/typedefs/src/index.js deleted file mode 100644 index f08314863..000000000 --- a/packages/typedefs/src/index.js +++ /dev/null @@ -1,117 +0,0 @@ -/** - * @typedef {object} Account - * @property {string} address - The address of the account - * @property {number} balance - The FLOW balance of the account in 10^8 - * @property {number} code - The code of any Cadence contracts stored in the account - * @property {object} contracts - An object with keys as the contract name deployed and the value as the the cadence string - * @property {object} keys - Any contracts deployed to this account - */ - -/** - * @typedef {object} Block - * @property {string} id - The id of the block - * @property {string} parentId - The id of the parent block - * @property {number} height - The height of the block - * @property {object} timestamp - Time related fields - * @property {CollectionGuarantee} collectionGuarantees - Contains the ids of collections included in the block - * @property {object} blockSeals - The details of which nodes executed and sealed the blocks - * @property {Array} signatures - The cryptographic signature of the block - */ - -/** - * @typedef {object} CollectionGuarantee - * @property {string} collectionId - The id of the block - * @property {Array} signatures - All signatures - */ - -/** - * @typedef {object} CompositeSignature - * @property {string} f_type - A type identifier used internally by FCL - * @property {string} f_vsn - FCL protocol version - * @property {string} addr - Flow Address (sans prefix) - * @property {number} keyId - Key ID - * @property {string} signature - Signature as a hex string - */ - -/** - * @typedef {object} CurrentUser - * @property {string} [addr] - The public address of the current user - * @property {string} [cid] - A wallet specified content identifier for user metadata - * @property {number} [expiresAt] - A wallet specified time-frame for a valid session - * @property {string} f_type - A type identifier used internally by FCL - * @property {string} f_vsn - FCL protocol version - * @property {boolean} [loggedIn] - Whether or not the current user is logged in - * @property {Array} services - A list of trusted services that express ways of interacting with the current user's identity - */ - -/** - * @typedef {object} Event - * @property {string} blockId - ID of the block that contains the event. - * @property {number} blockHeight - Height of the block that contains the event. - * @property {string} blockTimestamp - The timestamp of when the block was sealed in a DateString format. eg. '2021-06-25T13:42:04.227Z' - * @property {string} type - A string containing the event name. - * @property {string} transactionId - Can be used to query transaction information, eg. via a Flow block explorer. - * @property {number} transactionIndex - Used to prevent replay attacks. - * @property {number} eventIndex - Used to prevent replay attacks. - * @property {any} data - The data emitted from the event. - */ - -/** - * @typedef {object} Key - * @property {number} sequenceNumber - Sequence number of key used by the proposer of this transaction - * @property {number} keyId - The ID of the key in the account used by the proposer of this transaction - * @property {string} address - The address of the proposer of this transaction - */ - -/** - * @typedef {object} Service - * @property {string} f_type - A type identifier used internally by FCL - * @property {string} f_vsn - FCL protocol version - * @property {string} type - Service type - * @property {string} method - Service method - * @property {string} [uid] - Service uid - * @property {string} endpoint - Service endpoint - * @property {Provider} provider - Service provider object - */ - -/** - * @typedef {object} Signature - * @property {string} sequenceNumber - Sequence number of the key used to perform this signature. - * @property {number} keyId - ID of the key in the account used to perform this signature. - * @property {string} signature - The signature represented as a hex string. - */ - -/** - * @typedef {object} Transaction - * @property {string} script - The Cadence code used to execute this transaction. - * @property {Array} args - The JSON-CDC encoded arguments passed in to the transaction. - * @property {string} referenceBlockId - The reference block id for this transaction. - * @property {number} gasLimit - The gas limit for the transaction. - * @property {Key} proposalKey - The key used by the proposer of this transaction. - * @property {string} sequenceNumber - Sequence number of the key used by the proposer of this transaction. - * @property {number} keyId - The ID of the key in the account used by the proposer of this transaction. - * @property {string} address - The address of the proposer of this transaction. - * @property {string} payer - Address of the payer of the transaction. - * @property {string} proposer - Address of the proposer of this transaction. - * @property {Array} authorizers - Array of addresses of authorizers of this transaction. - * @property {Array} payloadSignatures - The payload signatures for the transaction. - * @property {Array} envelopeSignatures - The envelope signatures for the transaction. - */ - -/** - * @typedef {object} TransactionStatus - * @property {string} blockId - The ID of the Block the transaction is included in. - * @property {number} status - The status code of the transaction. - * @property {string} statusString - The status as as descriptive text (e.g. "FINALIZED"). - * @property {string} errorMessage - The error message of the transaction. - * @property {Array} events - The events for this result. - */ - -/** - * @typedef {object} Provider - * @property {string} name - Provider name. - * @todo fill the rest - */ - -// Needed for bundler to export this file -exports.unused = {} diff --git a/packages/typedefs/src/index.ts b/packages/typedefs/src/index.ts new file mode 100644 index 000000000..5971369c2 --- /dev/null +++ b/packages/typedefs/src/index.ts @@ -0,0 +1,290 @@ +export type Account = { + /** + * - The address of the account + */ + address: string + /** + * - The FLOW balance of the account in 10^8 + */ + balance: number + /** + * - The code of any Cadence contracts stored in the account + */ + code: number + /** + * - An object with keys as the contract name deployed and the value as the the cadence string + */ + contracts: object + /** + * - Any contracts deployed to this account + */ + keys: object +} +export type Block = { + /** + * - The id of the block + */ + id: string + /** + * - The id of the parent block + */ + parentId: string + /** + * - The height of the block + */ + height: number + /** + * - Time related fields + */ + timestamp: object + /** + * - Contains the ids of collections included in the block + */ + collectionGuarantees: CollectionGuarantee + /** + * - The details of which nodes executed and sealed the blocks + */ + blockSeals: object + /** + * - The cryptographic signature of the block + */ + signatures: Array +} +export type CollectionGuarantee = { + /** + * - The id of the block + */ + collectionId: string + /** + * - All signatures + */ + signatures: Array +} +export type CompositeSignature = { + /** + * - A type identifier used internally by FCL + */ + f_type: string + /** + * - FCL protocol version + */ + f_vsn: string + /** + * - Flow Address (sans prefix) + */ + addr: string + /** + * - Key ID + */ + keyId: number + /** + * - Signature as a hex string + */ + signature: string +} +export type CurrentUser = { + /** + * - The public address of the current user + */ + addr?: string + /** + * - A wallet specified content identifier for user metadata + */ + cid?: string + /** + * - A wallet specified time-frame for a valid session + */ + expiresAt?: number + /** + * - A type identifier used internally by FCL + */ + f_type: string + /** + * - FCL protocol version + */ + f_vsn: string + /** + * - Whether or not the current user is logged in + */ + loggedIn?: boolean + /** + * - A list of trusted services that express ways of interacting with the current user's identity + */ + services: Array +} +export type Event = { + /** + * - ID of the block that contains the event. + */ + blockId: string + /** + * - Height of the block that contains the event. + */ + blockHeight: number + /** + * - The timestamp of when the block was sealed in a DateString format. eg. '2021-06-25T13:42:04.227Z' + */ + blockTimestamp: string + /** + * - A string containing the event name. + */ + type: string + /** + * - Can be used to query transaction information, eg. via a Flow block explorer. + */ + transactionId: string + /** + * - Used to prevent replay attacks. + */ + transactionIndex: number + /** + * - Used to prevent replay attacks. + */ + eventIndex: number + /** + * - The data emitted from the event. + */ + data: any +} +export type Key = { + /** + * - Sequence number of key used by the proposer of this transaction + */ + sequenceNumber: number + /** + * - The ID of the key in the account used by the proposer of this transaction + */ + keyId: number + /** + * - The address of the proposer of this transaction + */ + address: string +} +export type Service = { + /** + * - A type identifier used internally by FCL + */ + f_type: string + /** + * - FCL protocol version + */ + f_vsn: string + /** + * - Service type + */ + type: string + /** + * - Service method + */ + method: string + /** + * - Service uid + */ + uid?: string + /** + * - Service endpoint + */ + endpoint: string + /** + * - Service provider object + */ + provider: Provider + + params: Record +} +export type Signature = { + /** + * - Sequence number of the key used to perform this signature. + */ + sequenceNumber: string + /** + * - ID of the key in the account used to perform this signature. + */ + keyId: number + /** + * - The signature represented as a hex string. + */ + signature: string +} +export type Transaction = { + /** + * - The Cadence code used to execute this transaction. + */ + script: string + /** + * - The JSON-CDC encoded arguments passed in to the transaction. + */ + args: Array + /** + * - The reference block id for this transaction. + */ + referenceBlockId: string + /** + * - The gas limit for the transaction. + */ + gasLimit: number + /** + * - The key used by the proposer of this transaction. + */ + proposalKey: Key + /** + * - Sequence number of the key used by the proposer of this transaction. + */ + sequenceNumber: string + /** + * - The ID of the key in the account used by the proposer of this transaction. + */ + keyId: number + /** + * - The address of the proposer of this transaction. + */ + address: string + /** + * - Address of the payer of the transaction. + */ + payer: string + /** + * - Address of the proposer of this transaction. + */ + proposer: string + /** + * - Array of addresses of authorizers of this transaction. + */ + authorizers: Array + /** + * - The payload signatures for the transaction. + */ + payloadSignatures: Array + /** + * - The envelope signatures for the transaction. + */ + envelopeSignatures: Array +} +export type TransactionStatus = { + /** + * - The ID of the Block the transaction is included in. + */ + blockId: string + /** + * - The status code of the transaction. + */ + status: number + /** + * - The status as as descriptive text (e.g. "FINALIZED"). + */ + statusString: string + /** + * - The error message of the transaction. + */ + errorMessage: string + /** + * - The events for this result. + */ + events: Array +} +export type Provider = { + /** + * - Provider name. + */ + name: string +} diff --git a/packages/typedefs/tsconfig.json b/packages/typedefs/tsconfig.json index 6bfcb0e73..88be905eb 100644 --- a/packages/typedefs/tsconfig.json +++ b/packages/typedefs/tsconfig.json @@ -1,25 +1,11 @@ { + "extends": "../../tsconfig", // Change this to match your project "include": ["src/**/*"], - "exclude": [ - "src/**/*.test.js", - ], "compilerOptions": { - "types" : ["node"], - // Tells TypeScript to read JS files, as - // normally they are ignored as source files - "allowJs": true, - // Generate d.ts files - "declaration": true, - // This compiler run should - // only output d.ts files - "emitDeclarationOnly": true, // Types should go into this directory. // Removing this would place the .d.ts files // next to the .js files "outDir": "types", - // go to js file when using IDE functions like - // "Go to Definition" in VSCode - "declarationMap": false, } } \ No newline at end of file diff --git a/packages/types/.babelrc b/packages/types/.babelrc index 67fc2886b..d766c90b2 100644 --- a/packages/types/.babelrc +++ b/packages/types/.babelrc @@ -1,7 +1,3 @@ { - "presets": [ - [ - "@babel/preset-env" - ] - ] + "presets": [["@babel/preset-env"], "@babel/preset-typescript"] } diff --git a/packages/types/.eslintrc.json b/packages/types/.eslintrc.json new file mode 100644 index 000000000..c9e88a7fc --- /dev/null +++ b/packages/types/.eslintrc.json @@ -0,0 +1,34 @@ +{ + "env": { + "browser": true, + "es2021": true, + "jest": true, + "node": true + }, + "extends": [ + "plugin:jsdoc/recommended-typescript", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended" + ], + "plugins": ["jsdoc", "@typescript-eslint"], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": "latest", + "sourceType": "module" + }, + "ignorePatterns": ["**/dist/"], + "overrides": [ + { + "files": ["**/*.test.ts"], + "env": { + "jest": true + }, + "rules": { + "jsdoc/require-jsdoc": 0 + } + } + ], + "rules": { + "@typescript-eslint/no-explicit-any": 0 + } +} diff --git a/packages/types/package.json b/packages/types/package.json index 25df43c88..5ac0b5228 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@onflow/types", - "version": "1.1.0", + "version": "1.2.0-typescript.0", "description": "Utilities to transform javascript values into Cadence understandable values", "license": "Apache-2.0", "author": "Dapper Labs ", @@ -13,21 +13,30 @@ "url": "https://github.com/onflow/flow-js-sdk/issues" }, "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1-alpha.0", + "@babel/preset-typescript": "^7.22.5", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", + "@types/jest": "^29.5.3", + "@typescript-eslint/eslint-plugin": "^6.4.0", + "@typescript-eslint/parser": "^6.4.0", + "eslint": "^8.47.0", + "eslint-plugin-jsdoc": "^46.4.6", "jest": "^29.5.0" }, - "source": "src/types.js", + "source": "src/types.ts", "main": "dist/types.js", "module": "dist/types.module.js", "unpkg": "dist/types.umd.js", + "types": "dist/types.d.ts", "scripts": { "prepublishOnly": "npm test && npm run build", "test": "jest", - "build": "fcl-bundle", + "build": " npm run lint && fcl-bundle", "test:watch": "jest --watch", - "start": "fcl-bundle --watch" + "start": "fcl-bundle --watch", + "lint": "eslint src" }, "dependencies": { - "@babel/runtime": "^7.18.6" + "@babel/runtime": "^7.18.6", + "@onflow/util-logger": "^1.3.0-typescript.0" } } diff --git a/packages/types/src/types.test.js b/packages/types/src/types.test.js deleted file mode 100644 index 36a57df3b..000000000 --- a/packages/types/src/types.test.js +++ /dev/null @@ -1,249 +0,0 @@ -import * as t from "./types.js" -;[ - [t.Identity, 0, 0, 0], - [t.Identity, "a", "a", "a"], - [t.Identity, null, null, null], - [t.Int, "1", {type: "Int", value: "1"}, "1"], - [t.UInt, "1", {type: "UInt", value: "1"}, "1"], - [t.Int8, "8", {type: "Int8", value: "8"}, "8"], - [t.UInt8, "8", {type: "UInt8", value: "8"}, "8"], - [t.Int16, "16", {type: "Int16", value: "16"}, "16"], - [t.UInt16, "16", {type: "UInt16", value: "16"}, "16"], - [t.Int32, "32", {type: "Int32", value: "32"}, "32"], - [t.UInt32, "32", {type: "UInt32", value: "32"}, "32"], - [t.Int64, "64", {type: "Int64", value: "64"}, "64"], - [t.UInt64, "64", {type: "UInt64", value: "64"}, "64"], - [t.Int128, "128", {type: "Int128", value: "128"}, "128"], - [t.UInt128, "128", {type: "UInt128", value: "128"}, "128"], - [t.Int256, "256", {type: "Int256", value: "256"}, "256"], - [t.UInt256, "256", {type: "UInt256", value: "256"}, "256"], - [t.Word8, "8", {type: "Word8", value: "8"}, "8"], - [t.Word16, "16", {type: "Word16", value: "16"}, "16"], - [t.Word32, "32", {type: "Word32", value: "32"}, "32"], - [t.Word64, "64", {type: "Word64", value: "64"}, "64"], - [t.UFix64, "64", {type: "UFix64", value: "64"}, "64", true], - [t.Fix64, "64", {type: "Fix64", value: "64"}, "64", true], - [ - t.UFix64, - "64.000000001", - {type: "UFix64", value: "64.000000001"}, - "64.000000001", - true, - ], - [ - t.Fix64, - "64.000000001", - {type: "Fix64", value: "64.000000001"}, - "64.000000001", - true, - ], - [t.UFix64, "64.0", {type: "UFix64", value: "64.00000000"}, "64.0", false], - [t.Fix64, "64.0", {type: "Fix64", value: "64.00000000"}, "64.0", false], - [ - t.String, - "Go with the Flow", - {type: "String", value: "Go with the Flow"}, - "Go with the Flow", - ], - [t.Character, "c", {type: "Character", value: "c"}, "c"], - [t.Bool, true, {type: "Bool", value: true}, true], - [t.Address, "0x1", {type: "Address", value: "0x1"}, "0x1"], - [t.Void, null, {type: "Void"}, null], - [t.Optional(t.String), null, {type: "Optional", value: null}, null], - [ - t.Optional(t.String), - "test", - {type: "Optional", value: {type: "String", value: "test"}}, - "test", - ], - [ - t.Reference, - {address: "0x01", type: "0x01.CryptoKitty"}, - {type: "Reference", value: {address: "0x01", type: "0x01.CryptoKitty"}}, - {address: "0x01", type: "0x01.CryptoKitty"}, - ], - [ - t.Array(t.String), - ["test"], - {type: "Array", value: [{type: "String", value: "test"}]}, - ["test"], - ], - [ - t.Array([t.String, t.String]), - ["test1", "test2"], - { - type: "Array", - value: [ - {type: "String", value: "test1"}, - {type: "String", value: "test2"}, - ], - }, - ["test1", "test2"], - ], - [ - t.Dictionary([ - {key: t.Int, value: t.String}, - {key: t.Int, value: t.String}, - ]), - [ - {key: "1", value: "one"}, - {key: "2", value: "two"}, - ], - { - type: "Dictionary", - value: [ - {key: {type: "Int", value: "1"}, value: {type: "String", value: "one"}}, - {key: {type: "Int", value: "2"}, value: {type: "String", value: "two"}}, - ], - }, - [ - {key: "1", value: "one"}, - {key: "2", value: "two"}, - ], - ], - [ - t.Dictionary({key: t.Int, value: t.String}), - {key: "1", value: "one"}, - { - type: "Dictionary", - value: [ - {key: {type: "Int", value: "1"}, value: {type: "String", value: "one"}}, - ], - }, - {key: "1", value: "one"}, - ], - [ - t.Struct("0x01.Jeffysaur", [{value: t.String}]), - { - fields: [{name: "Jeffysaur_Name", value: "Mr Jeff The Dinosaur"}], - }, - { - type: "Struct", - value: { - id: "0x01.Jeffysaur", - fields: [ - { - name: "Jeffysaur_Name", - value: {type: "String", value: "Mr Jeff The Dinosaur"}, - }, - ], - }, - }, - { - fields: [{name: "Jeffysaur_Name", value: "Mr Jeff The Dinosaur"}], - }, - ], - [ - t.Enum("0x01.SuperEnum", [{value: t.String}]), - { - fields: [{name: "SuperKey1", value: "SuperValue1"}], - }, - { - type: "Enum", - value: { - id: "0x01.SuperEnum", - fields: [ - { - name: "SuperKey1", - value: {type: "String", value: "SuperValue1"}, - }, - ], - }, - }, - { - fields: [{name: "SuperKey1", value: "SuperValue1"}], - }, - ], - [ - t.Event("0x01.JeffWroteSomeJS", [{value: t.String}]), - { - fields: [{name: "wasTheCodeClean?", value: "absolutely"}], - }, - { - type: "Event", - value: { - id: "0x01.JeffWroteSomeJS", - fields: [ - { - name: "wasTheCodeClean?", - value: {type: "String", value: "absolutely"}, - }, - ], - }, - }, - { - fields: [{name: "wasTheCodeClean?", value: "absolutely"}], - }, - ], - [ - t.Resource("0x01.Jeffysaur", [{value: t.String}]), - { - fields: [{name: "Jeffysaur_Name", value: "Mr Jeff The Dinosaur"}], - }, - { - type: "Resource", - value: { - id: "0x01.Jeffysaur", - fields: [ - { - name: "Jeffysaur_Name", - value: {type: "String", value: "Mr Jeff The Dinosaur"}, - }, - ], - }, - }, - { - fields: [{name: "Jeffysaur_Name", value: "Mr Jeff The Dinosaur"}], - }, - ], - [ - t.Path, - { - domain: "public", - identifier: "flowTokenVault", - }, - { - type: "Path", - value: { - domain: "public", - identifier: "flowTokenVault", - }, - }, - { - domain: "public", - identifier: "flowTokenVault", - }, - ], - [ - t.Path, - { - domain: "notValidDomain", - identifier: "flowTokenVault", - }, - { - type: "Path", - value: { - domain: "notValidDomain", - identifier: "flowTokenVault", - }, - }, - { - domain: "notValidDomain", - identifier: "flowTokenVault", - }, - true, - ], -].forEach(([cast, input, asArgument, asInjection, shouldError = false]) => { - describe(cast.label, () => { - test(`t.${cast.label}.asArgument(${input})`, () => { - if (shouldError) { - expect(() => cast.asArgument(input)).toThrow() - } else { - expect(cast.asArgument(input)).toStrictEqual(asArgument) - } - }) - test(`t.${cast.label}.asInjection(${input})`, () => { - expect(cast.asInjection(input)).toStrictEqual(asInjection) - }) - }) -}) diff --git a/packages/types/src/types.test.ts b/packages/types/src/types.test.ts new file mode 100644 index 000000000..3e725adb6 --- /dev/null +++ b/packages/types/src/types.test.ts @@ -0,0 +1,251 @@ +import * as t from "./types" + +registerTest([t.Int, "1", {type: "Int", value: "1"}, "1"]) +registerTest([t.UInt, "1", {type: "UInt", value: "1"}, "1"]) +registerTest([t.Int8, "8", {type: "Int8", value: "8"}, "8"]) +registerTest([t.UInt8, "8", {type: "UInt8", value: "8"}, "8"]) +registerTest([t.Int16, "16", {type: "Int16", value: "16"}, "16"]) +registerTest([t.UInt16, "16", {type: "UInt16", value: "16"}, "16"]) +registerTest([t.Int32, "32", {type: "Int32", value: "32"}, "32"]) +registerTest([t.UInt32, "32", {type: "UInt32", value: "32"}, "32"]) +registerTest([t.Int64, "64", {type: "Int64", value: "64"}, "64"]) +registerTest([t.UInt64, "64", {type: "UInt64", value: "64"}, "64"]) +registerTest([t.Int128, "128", {type: "Int128", value: "128"}, "128"]) +registerTest([t.UInt128, "128", {type: "UInt128", value: "128"}, "128"]) +registerTest([t.Int256, "256", {type: "Int256", value: "256"}, "256"]) +registerTest([t.UInt256, "256", {type: "UInt256", value: "256"}, "256"]) +registerTest([t.Word8, "8", {type: "Word8", value: "8"}, "8"]) +registerTest([t.Word16, "16", {type: "Word16", value: "16"}, "16"]) +registerTest([t.Word32, "32", {type: "Word32", value: "32"}, "32"]) +registerTest([t.Word64, "64", {type: "Word64", value: "64"}, "64"]) +registerTest([t.UFix64, "64", {type: "UFix64", value: "64"}, "64", true]) +registerTest([t.Fix64, "64", {type: "Fix64", value: "64"}, "64", true]) +registerTest([ + t.UFix64, + "64.000000001", + {type: "UFix64", value: "64.000000001"}, + "64.000000001", + true, +]) +registerTest([ + t.Fix64, + "64.000000001", + {type: "Fix64", value: "64.000000001"}, + "64.000000001", + true, +]) +registerTest([ + t.UFix64, + "64.0", + {type: "UFix64", value: "64.00000000"}, + "64.0", + false, +]) +registerTest([ + t.Fix64, + "64.0", + {type: "Fix64", value: "64.00000000"}, + "64.0", + false, +]) +registerTest([ + t.String, + "Go with the Flow", + {type: "String", value: "Go with the Flow"}, + "Go with the Flow", +]) +registerTest([t.Character, "c", {type: "Character", value: "c"}, "c"]) +registerTest([t.Bool, true, {type: "Bool", value: true}, true]) +registerTest([t.Address, "0x1", {type: "Address", value: "0x1"}, "0x1"]) +registerTest([t.Void, null, {type: "Void", value: null}, null]) +registerTest([ + t.Optional(t.String), + null, + {type: "Optional", value: null}, + null, +]) +registerTest([ + t.Optional(t.String), + "test", + {type: "Optional", value: {type: "String", value: "test"}}, + "test", +]) +registerTest([ + t.Reference, + {address: "0x01", type: "0x01.CryptoKitty"}, + {type: "Reference", value: {address: "0x01", type: "0x01.CryptoKitty"}}, + {address: "0x01", type: "0x01.CryptoKitty"}, +]) +registerTest([ + t.Array(t.String), + ["test"], + {type: "Array", value: [{type: "String", value: "test"}]}, + ["test"], +]) +registerTest([ + t.Array([t.String, t.String]), + ["test1", "test2"], + { + type: "Array", + value: [ + {type: "String", value: "test1"}, + {type: "String", value: "test2"}, + ], + }, + ["test1", "test2"], +]) +registerTest([ + t.Dictionary([ + {key: t.Int, value: t.String}, + {key: t.Int, value: t.String}, + ]), + [ + {key: "1", value: "one"}, + {key: "2", value: "two"}, + ], + { + type: "Dictionary", + value: [ + {key: {type: "Int", value: "1"}, value: {type: "String", value: "one"}}, + {key: {type: "Int", value: "2"}, value: {type: "String", value: "two"}}, + ], + }, + [ + {key: "1", value: "one"}, + {key: "2", value: "two"}, + ], +]) +registerTest([ + t.Dictionary({key: t.Int, value: t.String}), + {key: "1", value: "one"}, + { + type: "Dictionary", + value: [ + {key: {type: "Int", value: "1"}, value: {type: "String", value: "one"}}, + ], + }, + {key: "1", value: "one"}, +]) +registerTest([ + t.Struct("0x01.Jeffysaur", [{value: t.String}]), + {fields: [{name: "Jeffysaur_Name", value: "Mr Jeff The Dinosaur"}]}, + { + type: "Struct", + value: { + id: "0x01.Jeffysaur", + fields: [ + { + name: "Jeffysaur_Name", + value: {type: "String", value: "Mr Jeff The Dinosaur"}, + }, + ], + }, + }, + {fields: [{name: "Jeffysaur_Name", value: "Mr Jeff The Dinosaur"}]}, +]) +registerTest([ + t.Enum("0x01.SuperEnum", [{value: t.String}]), + {fields: [{name: "SuperKey1", value: "SuperValue1"}]}, + { + type: "Enum", + value: { + id: "0x01.SuperEnum", + fields: [ + {name: "SuperKey1", value: {type: "String", value: "SuperValue1"}}, + ], + }, + }, + {fields: [{name: "SuperKey1", value: "SuperValue1"}]}, +]) +registerTest([ + t.Event("0x01.JeffWroteSomeJS", [{value: t.String}]), + {fields: [{name: "wasTheCodeClean?", value: "absolutely"}]}, + { + type: "Event", + value: { + id: "0x01.JeffWroteSomeJS", + fields: [ + { + name: "wasTheCodeClean?", + value: {type: "String", value: "absolutely"}, + }, + ], + }, + }, + {fields: [{name: "wasTheCodeClean?", value: "absolutely"}]}, +]) +registerTest([ + t.Resource("0x01.Jeffysaur", [{value: t.String}]), + {fields: [{name: "Jeffysaur_Name", value: "Mr Jeff The Dinosaur"}]}, + { + type: "Resource", + value: { + id: "0x01.Jeffysaur", + fields: [ + { + name: "Jeffysaur_Name", + value: {type: "String", value: "Mr Jeff The Dinosaur"}, + }, + ], + }, + }, + {fields: [{name: "Jeffysaur_Name", value: "Mr Jeff The Dinosaur"}]}, +]) +registerTest([ + t.Path, + { + domain: "public" as "storage" | "private" | "public", + identifier: "flowTokenVault", + }, + {type: "Path", value: {domain: "public", identifier: "flowTokenVault"}}, + { + domain: "public" as "storage" | "private" | "public", + identifier: "flowTokenVault", + }, +]) +registerTest([ + t.Path, + { + domain: "notValidDomain" as "storage" | "private" | "public", + identifier: "flowTokenVault", + }, + { + type: "Path", + value: { + domain: "notValidDomain" as "storage" | "private" | "public", + identifier: "flowTokenVault", + }, + }, + { + domain: "notValidDomain" as "storage" | "private" | "public", + identifier: "flowTokenVault", + }, + true, +]) + +function registerTest([ + cast, + input, + asArgument, + asInjection, + shouldError = false, +]: readonly [ + t.TypeDescriptor>, + X, + t.JsonCdc, + X, + boolean? +]) { + describe(cast.label, () => { + test(`t.${cast.label}.asArgument(${input})`, () => { + if (shouldError) { + expect(() => cast.asArgument(input)).toThrow() + } else { + expect(cast.asArgument(input)).toStrictEqual(asArgument) + } + }) + test(`t.${cast.label}.asInjection(${input})`, () => { + expect(cast.asInjection(input)).toStrictEqual(asInjection) + }) + }) +} diff --git a/packages/types/src/types.js b/packages/types/src/types.ts similarity index 58% rename from packages/types/src/types.js rename to packages/types/src/types.ts index 543887322..cc392f607 100644 --- a/packages/types/src/types.js +++ b/packages/types/src/types.ts @@ -1,24 +1,75 @@ -import {log, LEVELS} from "@onflow/util-logger" +import {log} from "@onflow/util-logger" -const type = (label, asArgument, asInjection) => ({ +export type JsonCdc = { + type: L + value: T +} + +type JsonCdcLabel> = X extends JsonCdc< + infer L, + unknown +> + ? L + : never + +export interface TypeDescriptor> { + label: JsonCdcLabel + asArgument: (x: T) => V + asInjection: (x: T) => T +} + +type TypeDescriptorInput< + X extends TypeDescriptor> +> = X extends TypeDescriptor> ? T : never + +export interface PathValue { + domain: "storage" | "private" | "public" + identifier: string +} + +export interface ReferenceValue { + type: string + address: string +} + +/** + * Creates a type descriptor for a given type + * @param label - The label for the type + * @param asArgument - A function that converts the type to a JsonCdcType + * @param asInjection - A function which returns the argument as is + * @returns A type descriptor + * @internal + */ +const typedef = >( + label: JsonCdcLabel, + asArgument: (x: T) => V, + asInjection: (x: T) => T +): TypeDescriptor => ({ label, asArgument, - asInjection, + asInjection: (x: T) => { + log.deprecate({ + pkg: "@onflow/types", + subject: `Passing in ${label} as value for ${label}`, + message: `Going forward, use ${label} as value for ${label}.`, + }) + return asInjection(x) + }, }) -const isArray = d => Array.isArray(d) -const isObj = d => typeof d === "object" -const isNull = d => d == null -const isBoolean = d => typeof d === "boolean" -const isNumber = d => typeof d === "number" -const isInteger = d => Number.isInteger(d) -const isString = d => typeof d === "string" +const isArray = (d: unknown): d is T[] => Array.isArray(d) +const isObj = (d: unknown): d is object => typeof d === "object" +const isNull = (d: unknown): d is null | undefined => d == null +const isBoolean = (d: unknown): d is boolean => typeof d === "boolean" +const isNumber = (d: unknown): d is number => typeof d === "number" +const isInteger = (d: unknown): d is number => Number.isInteger(d) +const isString = (d: unknown): d is string => typeof d === "string" -const throwTypeError = msg => { +const throwTypeError = (msg: unknown): never => { throw new Error("Type Error: " + msg) } -const numberValuesDeprecationNotice = type => { +const numberValuesDeprecationNotice = (type: string) => { log.deprecate({ pkg: "@onflow/types", subject: `Passing in Number as value for ${type}`, @@ -28,15 +79,30 @@ const numberValuesDeprecationNotice = type => { }) } -export const Identity = type( - "Identity", - v => v, - v => v -) +let identityDeprecationShown = false +/** + * @deprecated will be removed in v2.0.0 + */ +export const Identity = { + label: "Identity", + asArgument: (v: T) => { + if (!identityDeprecationShown) { + log.deprecate({ + pkg: "@onflow/types", + subject: "Identity", + message: + "Identity type is deprecated and will be removed in v2.0.0. Please remove it from your code.", + }) + identityDeprecationShown = true + } + return v + }, + asInjection: (v: T) => v, +} -export const UInt = type( +export const UInt = typedef( "UInt", - v => { + (v: number | string) => { if (isNumber(v) && isInteger(v)) { numberValuesDeprecationNotice("UInt") return { @@ -50,14 +116,14 @@ export const UInt = type( value: v, } } - throwTypeError("Expected Positive Integer for type Unsigned Int") + return throwTypeError("Expected Positive Integer for type Unsigned Int") }, v => v ) -export const Int = type( +export const Int = typedef( "Int", - v => { + (v: number | string) => { if (isNumber(v) && isInteger(v)) { numberValuesDeprecationNotice("Int") return { @@ -71,14 +137,14 @@ export const Int = type( value: v, } } - throwTypeError("Expected Integer for type Int") + return throwTypeError("Expected Integer for type Int") }, v => v ) -export const UInt8 = type( +export const UInt8 = typedef( "UInt8", - v => { + (v: number | string) => { if (isNumber(v) && isInteger(v)) { numberValuesDeprecationNotice("UInt8") return { @@ -92,14 +158,14 @@ export const UInt8 = type( value: v, } } - throwTypeError("Expected integer for UInt8") + return throwTypeError("Expected integer for UInt8") }, v => v ) -export const Int8 = type( +export const Int8 = typedef( "Int8", - v => { + (v: number | string) => { if (isNumber(v) && isInteger(v)) { numberValuesDeprecationNotice("Int8") return { @@ -113,14 +179,14 @@ export const Int8 = type( value: v, } } - throwTypeError("Expected positive integer for Int8") + return throwTypeError("Expected positive integer for Int8") }, v => v ) -export const UInt16 = type( +export const UInt16 = typedef( "UInt16", - v => { + (v: number | string) => { if (isNumber(v) && isInteger(v)) { numberValuesDeprecationNotice("UInt16") return { @@ -134,14 +200,14 @@ export const UInt16 = type( value: v, } } - throwTypeError("Expected integer for UInt16") + return throwTypeError("Expected integer for UInt16") }, v => v ) -export const Int16 = type( +export const Int16 = typedef( "Int16", - v => { + (v: number | string) => { if (isNumber(v) && isInteger(v)) { numberValuesDeprecationNotice("Int16") return { @@ -155,14 +221,14 @@ export const Int16 = type( value: v, } } - throwTypeError("Expected positive integer for Int16") + return throwTypeError("Expected positive integer for Int16") }, v => v ) -export const UInt32 = type( +export const UInt32 = typedef( "UInt32", - v => { + (v: number | string) => { if (isNumber(v) && isInteger(v)) { numberValuesDeprecationNotice("UInt32") return { @@ -176,14 +242,14 @@ export const UInt32 = type( value: v, } } - throwTypeError("Expected integer for UInt32") + return throwTypeError("Expected integer for UInt32") }, v => v ) -export const Int32 = type( +export const Int32 = typedef( "Int32", - v => { + (v: number | string) => { if (isNumber(v) && isInteger(v)) { numberValuesDeprecationNotice("Int32") return { @@ -197,14 +263,14 @@ export const Int32 = type( value: v, } } - throwTypeError("Expected positive integer for Int32") + return throwTypeError("Expected positive integer for Int32") }, v => v ) -export const UInt64 = type( +export const UInt64 = typedef( "UInt64", - v => { + (v: number | string) => { if (isNumber(v) && isInteger(v)) { numberValuesDeprecationNotice("UInt64") return { @@ -218,14 +284,14 @@ export const UInt64 = type( value: v, } } - throwTypeError("Expected integer for UInt64") + return throwTypeError("Expected integer for UInt64") }, v => v ) -export const Int64 = type( +export const Int64 = typedef( "Int64", - v => { + (v: number | string) => { if (isNumber(v) && isInteger(v)) { numberValuesDeprecationNotice("Int64") return { @@ -239,14 +305,14 @@ export const Int64 = type( value: v, } } - throwTypeError("Expected positive integer for Int64") + return throwTypeError("Expected positive integer for Int64") }, v => v ) -export const UInt128 = type( +export const UInt128 = typedef( "UInt128", - v => { + (v: number | string) => { if (isNumber(v) && isInteger(v)) { numberValuesDeprecationNotice("UInt128") return { @@ -260,14 +326,14 @@ export const UInt128 = type( value: v, } } - throwTypeError("Expected integer for UInt128") + return throwTypeError("Expected integer for UInt128") }, v => v ) -export const Int128 = type( +export const Int128 = typedef( "Int128", - v => { + (v: number | string) => { if (isNumber(v) && isInteger(v)) { numberValuesDeprecationNotice("Int128") return { @@ -281,14 +347,14 @@ export const Int128 = type( value: v, } } - throwTypeError("Expected positive integer for Int128") + return throwTypeError("Expected positive integer for Int128") }, v => v ) -export const UInt256 = type( +export const UInt256 = typedef( "UInt256", - v => { + (v: number | string) => { if (isNumber(v) && isInteger(v)) { numberValuesDeprecationNotice("UInt256") return { @@ -302,14 +368,14 @@ export const UInt256 = type( value: v, } } - throwTypeError("Expected integer for UInt256") + return throwTypeError("Expected integer for UInt256") }, v => v ) -export const Int256 = type( +export const Int256 = typedef( "Int256", - v => { + (v: number | string) => { if (isNumber(v) && isInteger(v)) { numberValuesDeprecationNotice("Int256") return { @@ -323,14 +389,14 @@ export const Int256 = type( value: v, } } - throwTypeError("Expected integer for Int256") + return throwTypeError("Expected integer for Int256") }, v => v ) -export const Word8 = type( +export const Word8 = typedef( "Word8", - v => { + (v: number | string) => { if (isNumber(v) && isInteger(v)) { numberValuesDeprecationNotice("Word8") return { @@ -344,14 +410,14 @@ export const Word8 = type( value: v, } } - throwTypeError("Expected positive number for Word8") + return throwTypeError("Expected positive number for Word8") }, v => v ) -export const Word16 = type( +export const Word16 = typedef( "Word16", - v => { + (v: number | string) => { if (isNumber(v) && isInteger(v)) { numberValuesDeprecationNotice("Word16") return { @@ -365,14 +431,14 @@ export const Word16 = type( value: v, } } - throwTypeError("Expected positive number for Word16") + return throwTypeError("Expected positive number for Word16") }, v => v ) -export const Word32 = type( +export const Word32 = typedef( "Word32", - v => { + (v: number | string) => { if (isNumber(v) && isInteger(v)) { numberValuesDeprecationNotice("Word32") return { @@ -386,14 +452,14 @@ export const Word32 = type( value: v, } } - throwTypeError("Expected positive number for Word32") + return throwTypeError("Expected positive number for Word32") }, v => v ) -export const Word64 = type( +export const Word64 = typedef( "Word64", - v => { + (v: number | string) => { if (isNumber(v) && isInteger(v)) { numberValuesDeprecationNotice("Word64") return { @@ -407,7 +473,7 @@ export const Word64 = type( value: v, } } - throwTypeError("Expected positive number for Word64") + return throwTypeError("Expected positive number for Word64") }, v => v ) @@ -421,18 +487,18 @@ const UFix64AndFix64NumberDeprecationNotice = () => { }) } -export const UFix64 = type( +export const UFix64 = typedef( "UFix64", - v => { + (v: number | string) => { if (isString(v)) { const vParts = v.split(".") if (vParts.length !== 2) { - throwTypeError( + return throwTypeError( `Expected one decimal but found ${vParts.length} in the [U]Fix64 value. Find out more about [U]Fix64 types here: https://docs.onflow.org/cadence/json-cadence-spec/#fixed-point-numbers` ) } if (vParts[1].length == 0 || vParts[1].length > 8) { - throwTypeError( + return throwTypeError( `Expected at least one digit, and at most 8 digits following the decimal of the [U]Fix64 value but found ${vParts[1].length} digits. Find out more about [U]Fix64 types here: https://docs.onflow.org/cadence/json-cadence-spec/#fixed-point-numbers` ) } @@ -452,23 +518,23 @@ export const UFix64 = type( value: v.toString(), } } - throwTypeError("Expected String for UFix64") + return throwTypeError("Expected String for UFix64") }, v => v ) -export const Fix64 = type( +export const Fix64 = typedef( "Fix64", - v => { + (v: number | string) => { if (isString(v)) { const vParts = v.split(".") if (vParts.length !== 2) { - throwTypeError( + return throwTypeError( `Expected one decimal but found ${vParts.length} in the [U]Fix64 value. Find out more about [U]Fix64 types here: https://docs.onflow.org/cadence/json-cadence-spec/#fixed-point-numbers` ) } if (vParts[1].length == 0 || vParts[1].length > 8) { - throwTypeError( + return throwTypeError( `Expected at least one digit, and at most 8 digits following the decimal of the [U]Fix64 value but found ${vParts[1].length} digits. Find out more about [U]Fix64 types here: https://docs.onflow.org/cadence/json-cadence-spec/#fixed-point-numbers` ) } @@ -488,102 +554,109 @@ export const Fix64 = type( value: v.toString(), } } - throwTypeError("Expected String for Fix64") + return throwTypeError("Expected String for Fix64") }, v => v ) -export const String = type( +export const String = typedef( "String", - v => { + (v: string) => { if (isString(v)) return { type: "String", value: v, } - throwTypeError("Expected String for type String") + return throwTypeError("Expected String for type String") }, v => v ) -export const Character = type( +export const Character = typedef( "Character", - v => { + (v: string) => { if (isString(v)) return { type: "Character", value: v, } - throwTypeError("Expected Character for type Character") + return throwTypeError("Expected Character for type Character") }, v => v ) -export const Bool = type( +export const Bool = typedef( "Bool", - v => { + (v: boolean) => { if (isBoolean(v)) return { type: "Bool", value: v, } - throwTypeError("Expected Boolean for type Bool") + return throwTypeError("Expected Boolean for type Bool") }, v => v ) -export const Address = type( +export const Address = typedef( "Address", - v => { + (v: string) => { if (isString(v)) return { type: "Address", value: v, } - throwTypeError("Expected Address for type Address") + return throwTypeError("Expected Address for type Address") }, v => v ) -export const Void = type( +export const Void = typedef( "Void", - v => { + (v?: null) => { if (!v || isNull(v)) return { type: "Void", + value: null, } - throwTypeError("Expected Void for type Void") + return throwTypeError("Expected Void for type Void") }, v => v ) -export const Optional = children => - type( +export const Optional = < + T extends TypeDescriptor> +>( + children: T +) => + typedef( "Optional", - v => ({ + (v?: TypeDescriptorInput | null) => ({ type: "Optional", value: isNull(v) ? null : children.asArgument(v), }), v => v ) -export const Reference = type( +export const Reference = typedef( "Reference", - v => { + (v: ReferenceValue) => { if (isObj(v)) return { type: "Reference", value: v, } - throwTypeError("Expected Object for type Reference") + return throwTypeError("Expected Object for type Reference") }, v => v ) -export const _Array = (children = []) => - type( +export const _Array = >>( + children: T[] | T = [] +) => + typedef( "Array", - v => { + (v: TypeDescriptorInput[]) => { return { type: "Array", value: isArray(children) @@ -596,39 +669,65 @@ export const _Array = (children = []) => export {_Array as Array} -export const Dictionary = (children = []) => - type( +export const Dictionary = < + K extends TypeDescriptor>, + V extends TypeDescriptor> +>( + children: + | { + key: K + value: V + }[] + | { + key: K + value: V + } = [] +) => + typedef( "Dictionary", - v => { + ( + v: + | {key: TypeDescriptorInput; value: TypeDescriptorInput}[] + | {key: TypeDescriptorInput; value: TypeDescriptorInput} + ) => { + const vIsArray = isArray(v) + const childrenIsArray = isArray(children) + if (isObj(v)) return { type: "Dictionary", - value: isArray(children) - ? children.map((c, i) => ({ - key: c.key.asArgument(v[i].key), - value: c.value.asArgument(v[i].value), - })) - : isArray(v) - ? v.map(x => ({ - key: children.key.asArgument(x.key), - value: children.value.asArgument(x.value), - })) - : [ - { - key: children.key.asArgument(v.key), - value: children.value.asArgument(v.value), - }, - ], + value: + childrenIsArray && vIsArray + ? children.map((c, i) => ({ + key: c.key.asArgument(v[i].key), + value: c.value.asArgument(v[i].value), + })) + : vIsArray && !childrenIsArray + ? v.map(x => ({ + key: children.key.asArgument(x.key), + value: children.value.asArgument(x.value), + })) + : !vIsArray && !childrenIsArray + ? [ + { + key: children.key.asArgument(v.key), + value: children.value.asArgument(v.value), + }, + ] + : throwTypeError("Invalid arguments for Dictionary."), } - throwTypeError("Expected Object for type Dictionary") + return throwTypeError("Expected Object for type Dictionary") }, v => v ) -export const Event = (id, fields = []) => - type( +export const Event = >>( + id: string, + fields: {value: V}[] | {value: V} = [] +) => + typedef( "Event", - v => { + (v: {fields: {name: string; value: TypeDescriptorInput}[]}) => { if (isObj(v)) return { type: "Event", @@ -645,15 +744,20 @@ export const Event = (id, fields = []) => })), }, } - throwTypeError("Expected Object for type Event") + return throwTypeError("Expected Object for type Event") }, v => v ) -export const Resource = (id, fields = []) => - type( +export const Resource = < + V extends TypeDescriptor> +>( + id: string, + fields: {value: V}[] | {value: V} = [] +) => + typedef( "Resource", - v => { + (v: {fields: {name: string; value: TypeDescriptorInput}[]}) => { if (isObj(v)) return { type: "Resource", @@ -670,15 +774,18 @@ export const Resource = (id, fields = []) => })), }, } - throwTypeError("Expected Object for type Resource") + return throwTypeError("Expected Object for type Resource") }, v => v ) -export const Struct = (id, fields = []) => - type( +export const Struct = >>( + id: string, + fields: {value: V}[] | {value: V} = [] +) => + typedef( "Struct", - v => { + (v: {fields: {name: string; value: TypeDescriptorInput}[]}) => { if (isObj(v)) return { type: "Struct", @@ -695,15 +802,18 @@ export const Struct = (id, fields = []) => })), }, } - throwTypeError("Expected Object for type Struct") + return throwTypeError("Expected Object for type Struct") }, v => v ) -export const Enum = (id, fields = []) => - type( +export const Enum = >>( + id: string, + fields: {value: V}[] | {value: V} = [] +) => + typedef( "Enum", - v => { + (v: {fields: {name: string; value: TypeDescriptorInput}[]}) => { if (isObj(v)) return { type: "Enum", @@ -720,17 +830,17 @@ export const Enum = (id, fields = []) => })), }, } - throwTypeError("Expected Object for type Enum") + return throwTypeError("Expected Object for type Enum") }, v => v ) -export const Path = type( +export const Path = typedef( "Path", - v => { + (v: PathValue) => { if (isObj(v)) { if (!isString(v.domain)) { - throwTypeError( + return throwTypeError( `Expected a string for the Path domain but found ${v.domain}. Find out more about the Path type here: https://docs.onflow.org/cadence/json-cadence-spec/#path` ) } @@ -742,13 +852,13 @@ export const Path = type( v.domain === "public" ) ) { - throwTypeError( + return throwTypeError( `Expected either "storage", "private" or "public" as the Path domain but found ${v.domain}. Find out more about the Path type here: https://docs.onflow.org/cadence/json-cadence-spec/#path` ) } if (!isString(v.identifier)) { - throwTypeError( + return throwTypeError( `Expected a string for the Path identifier but found ${v.identifier}. Find out more about the Path type here: https://docs.onflow.org/cadence/json-cadence-spec/#path` ) } @@ -761,7 +871,7 @@ export const Path = type( }, } } - throwTypeError("Expected Object for type Path") + return throwTypeError("Expected Object for type Path") }, v => v ) diff --git a/packages/types/tsconfig.json b/packages/types/tsconfig.json new file mode 100644 index 000000000..88be905eb --- /dev/null +++ b/packages/types/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig", + // Change this to match your project + "include": ["src/**/*"], + "compilerOptions": { + // Types should go into this directory. + // Removing this would place the .d.ts files + // next to the .js files + "outDir": "types", + } +} \ No newline at end of file diff --git a/packages/util-actor/.babelrc b/packages/util-actor/.babelrc index 67fc2886b..f57936a43 100644 --- a/packages/util-actor/.babelrc +++ b/packages/util-actor/.babelrc @@ -2,6 +2,7 @@ "presets": [ [ "@babel/preset-env" - ] + ], + "@babel/preset-typescript" ] } diff --git a/packages/util-actor/.eslintrc.json b/packages/util-actor/.eslintrc.json new file mode 100644 index 000000000..e26aed124 --- /dev/null +++ b/packages/util-actor/.eslintrc.json @@ -0,0 +1,23 @@ +{ + "env": { + "browser": true, + "es2021": true, + "jest": true, + "node": true + }, + "extends": [ + "plugin:jsdoc/recommended-typescript", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended" + ], + "plugins": ["jsdoc", "@typescript-eslint"], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": "latest", + "sourceType": "module" + }, + "rules": { + "@typescript-eslint/no-explicit-any": "off" + }, + "ignorePatterns": ["**/dist/"] +} diff --git a/packages/util-actor/jest.config.ts b/packages/util-actor/jest.config.ts new file mode 100644 index 000000000..22291c790 --- /dev/null +++ b/packages/util-actor/jest.config.ts @@ -0,0 +1,8 @@ +import type {Config} from 'jest'; + +const config: Config = { + verbose: true, + preset: "ts-jest", +}; + +export default config; \ No newline at end of file diff --git a/packages/util-actor/package.json b/packages/util-actor/package.json index ce51944fd..0f00374a8 100644 --- a/packages/util-actor/package.json +++ b/packages/util-actor/package.json @@ -1,6 +1,6 @@ { "name": "@onflow/util-actor", - "version": "1.2.0", + "version": "1.3.0-typescript.0", "description": "A mechanism for forcing order/transitions of scoped async state", "license": "Apache-2.0", "author": "Dapper Labs ", @@ -13,22 +13,30 @@ "url": "https://github.com/onflow/flow-js-sdk/issues" }, "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1-alpha.0", + "@babel/preset-typescript": "^7.22.5", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", + "@types/jest": "^29.5.3", + "@typescript-eslint/eslint-plugin": "^6.4.0", + "@typescript-eslint/parser": "^6.4.0", + "eslint": "^8.47.0", + "eslint-plugin-jsdoc": "^46.4.6", "jest": "^29.5.0" }, "dependencies": { "@babel/runtime": "^7.18.6", "queue-microtask": "1.2.3" }, - "source": "src/index.js", + "source": "src/index.ts", "main": "dist/actor.js", "module": "dist/actor.module.js", "unpkg": "dist/actor.umd.js", + "types": "dist/index.d.ts", "scripts": { "prepublishOnly": "npm test && npm run build", "test": "jest", "build": "fcl-bundle", "test:watch": "jest --watch", - "start": "fcl-bundle --watch" + "start": "fcl-bundle --watch", + "lint": "eslint src --ext .ts" } } diff --git a/packages/util-actor/src/index.js b/packages/util-actor/src/index.js deleted file mode 100644 index d697091dd..000000000 --- a/packages/util-actor/src/index.js +++ /dev/null @@ -1,205 +0,0 @@ -import {mailbox as createMailbox} from "./mailbox" -import queueMicrotask from "queue-microtask" - -export const INIT = "INIT" -export const SUBSCRIBE = "SUBSCRIBE" -export const UNSUBSCRIBE = "UNSUBSCRIBE" -export const UPDATED = "UPDATED" -export const SNAPSHOT = "SNAPSHOT" -export const EXIT = "EXIT" -export const TERMINATE = "TERMINATE" - -const root = - (typeof self === "object" && self.self === self && self) || - (typeof global === "object" && global.global === global && global) || - (typeof window === "object" && window.window === window && window) - -root.FCL_REGISTRY = root.FCL_REGISTRY == null ? {} : root.FCL_REGISTRY -var pid = 0b0 - -const DEFAULT_TIMEOUT = 5000 -const DEFAULT_TAG = "---" -export const send = (addr, tag, data, opts = {}) => - new Promise((reply, reject) => { - const expectReply = opts.expectReply || false - const timeout = opts.timeout != null ? opts.timeout : DEFAULT_TIMEOUT - - if (expectReply && timeout) { - setTimeout( - () => - reject(new Error(`Timeout: ${timeout}ms passed without a response.`)), - timeout - ) - } - - const payload = { - to: addr, - from: opts.from, - tag, - data, - timeout, - reply, - reject, - } - - try { - root.FCL_REGISTRY[addr] && - root.FCL_REGISTRY[addr].mailbox.deliver(payload) - if (!expectReply) reply(true) - } catch (error) { - console.error( - "FCL.Actor -- Could Not Deliver Message", - payload, - root.FCL_REGISTRY[addr], - error - ) - } - }) - -export const kill = addr => { - delete root.FCL_REGISTRY[addr] -} - -const fromHandlers = - (handlers = {}) => - async ctx => { - if (typeof handlers[INIT] === "function") await handlers[INIT](ctx) - __loop: while (1) { - const letter = await ctx.receive() - try { - if (letter.tag === EXIT) { - if (typeof handlers[TERMINATE] === "function") { - await handlers[TERMINATE](ctx, letter, letter.data || {}) - } - break __loop - } - await handlers[letter.tag](ctx, letter, letter.data || {}) - } catch (error) { - console.error(`${ctx.self()} Error`, letter, error) - } finally { - continue __loop - } - } - } - -export const spawn = (fn, addr = null) => { - if (addr == null) addr = ++pid - if (root.FCL_REGISTRY[addr] != null) return addr - - root.FCL_REGISTRY[addr] = { - addr, - mailbox: createMailbox(), - subs: new Set(), - kvs: {}, - error: null, - } - - const ctx = { - self: () => addr, - receive: () => root.FCL_REGISTRY[addr].mailbox.receive(), - send: (to, tag, data, opts = {}) => { - opts.from = addr - return send(to, tag, data, opts) - }, - sendSelf: (tag, data, opts) => { - if (root.FCL_REGISTRY[addr]) send(addr, tag, data, opts) - }, - broadcast: (tag, data, opts = {}) => { - opts.from = addr - for (let to of root.FCL_REGISTRY[addr].subs) send(to, tag, data, opts) - }, - subscribe: sub => sub != null && root.FCL_REGISTRY[addr].subs.add(sub), - unsubscribe: sub => sub != null && root.FCL_REGISTRY[addr].subs.delete(sub), - subscriberCount: () => root.FCL_REGISTRY[addr].subs.size, - hasSubs: () => !!root.FCL_REGISTRY[addr].subs.size, - put: (key, value) => { - if (key != null) root.FCL_REGISTRY[addr].kvs[key] = value - }, - get: (key, fallback) => { - const value = root.FCL_REGISTRY[addr].kvs[key] - return value == null ? fallback : value - }, - delete: key => { - delete root.FCL_REGISTRY[addr].kvs[key] - }, - update: (key, fn) => { - if (key != null) - root.FCL_REGISTRY[addr].kvs[key] = fn(root.FCL_REGISTRY[addr].kvs[key]) - }, - keys: () => { - return Object.keys(root.FCL_REGISTRY[addr].kvs) - }, - all: () => { - return root.FCL_REGISTRY[addr].kvs - }, - where: pattern => { - return Object.keys(root.FCL_REGISTRY[addr].kvs).reduce((acc, key) => { - return pattern.test(key) - ? {...acc, [key]: root.FCL_REGISTRY[addr].kvs[key]} - : acc - }, {}) - }, - merge: (data = {}) => { - Object.keys(data).forEach( - key => (root.FCL_REGISTRY[addr].kvs[key] = data[key]) - ) - }, - fatalError: error => { - root.FCL_REGISTRY[addr].error = error - for (let to of root.FCL_REGISTRY[addr].subs) send(to, UPDATED) - }, - } - - if (typeof fn === "object") fn = fromHandlers(fn) - - queueMicrotask(async () => { - await fn(ctx) - kill(addr) - }) - - return addr -} - -// Returns an unsubscribe function -// A SUBSCRIBE handler will need to be created to handle the subscription event -// -// [SUBSCRIBE]: (ctx, letter) => { -// ctx.subscribe(letter.from) -// ctx.send(letter.from, UPDATED, ctx.all()) -// } -// -export function subscriber(address, spawnFn, callback) { - spawnFn(address) - const EXIT = "@EXIT" - const self = spawn(async ctx => { - ctx.send(address, SUBSCRIBE) - while (1) { - const letter = await ctx.receive() - const error = root.FCL_REGISTRY[address].error - if (letter.tag === EXIT) { - ctx.send(address, UNSUBSCRIBE) - return - } - if (error) { - callback(null, error) - ctx.send(address, UNSUBSCRIBE) - return - } - - callback(letter.data, null) - } - }) - return () => send(self, EXIT) -} - -// Returns a promise that returns a result -// A SNAPSHOT handler will need to be created to handle the snapshot event -// -// [SNAPSHOT]: (ctx, letter) => { -// letter.reply(ctx.all()) -// } -// -export function snapshoter(address, spawnFn) { - spawnFn(address) - return send(address, SNAPSHOT, null, {expectReply: true, timeout: 0}) -} diff --git a/packages/util-actor/src/index.test.js b/packages/util-actor/src/index.test.ts similarity index 86% rename from packages/util-actor/src/index.test.js rename to packages/util-actor/src/index.test.ts index 5efce9f47..7bc79608c 100644 --- a/packages/util-actor/src/index.test.js +++ b/packages/util-actor/src/index.test.ts @@ -1,4 +1,4 @@ -import {spawn, send, kill} from "./" +import {spawn, send, kill, ActorContext} from "./" const COUNT = "COUNT" const DUMP = "DUMP" @@ -8,7 +8,7 @@ const UPDATED = "UPDATED" const SUBSCRIBE = "SUBSCRIBE" const UNSUBSCRIBE = "UNSUBSCRIBE" -const counterLogic = async ctx => { +const counterLogic = async (ctx: ActorContext) => { ctx.put(COUNT, 0) __loop: while (1) { @@ -18,7 +18,7 @@ const counterLogic = async ctx => { switch (letter.tag) { case SUBSCRIBE: ctx.subscribe(letter.from) - ctx.send(letter.from, UPDATED, ctx.get(COUNT, 0)) + ctx.send(letter.from!, UPDATED, ctx.get(COUNT, 0)) continue __loop case UNSUBSCRIBE: @@ -44,11 +44,12 @@ const counterLogic = async ctx => { } } -const counter = name => spawn(counterLogic, name) -const dump = addr => send(addr, DUMP, null, {expectReply: true, timeout: 100}) -const inc = (addr, delta = 1) => send(addr, INC, {delta}) +const counter = (name: string) => spawn(counterLogic, name) +const dump = (addr: string) => + send(addr, DUMP, null, {expectReply: true, timeout: 100}) +const inc = (addr: string, delta = 1) => send(addr, INC, {delta}) -const subscribe = (addr, callback) => { +const subscribe = (addr: string, callback: (data: any) => void) => { const EXIT = "@EXIT" const self = spawn(async ctx => { ctx.send(addr, SUBSCRIBE) @@ -72,13 +73,13 @@ const idle = async () => new Promise(resolve => setTimeout(resolve, 0)) describe("golden path", () => { describe("init, send, receive", () => { test("rpc initial value", async () => { - const c = counter() + const c = counter("") expect(await dump(c)).toBe(0) kill(c) }) test("send message and rpc value", async () => { - const c = counter() + const c = counter("value") inc(c, 5) expect(await dump(c)).toBe(5) kill(c) @@ -152,8 +153,8 @@ describe("golden path", () => { test("actors with same name only spawn once", async () => { const fn = jest.fn() - const c1 = spawn(fn, "foo") - const c2 = spawn(fn, "foo") + const c1 = spawn(fn, 0) + const c2 = spawn(fn, 0) await idle() expect(c1).toBe(c2) diff --git a/packages/util-actor/src/index.ts b/packages/util-actor/src/index.ts new file mode 100644 index 000000000..dd9f8ad2f --- /dev/null +++ b/packages/util-actor/src/index.ts @@ -0,0 +1,310 @@ +import {mailbox as createMailbox, type IMailbox} from "./mailbox" + +// eslint-disable-next-line @typescript-eslint/no-var-requires +const queueMicrotask = require("queue-microtask") + +export const INIT = "INIT" +export const SUBSCRIBE = "SUBSCRIBE" +export const UNSUBSCRIBE = "UNSUBSCRIBE" +export const UPDATED = "UPDATED" +export const SNAPSHOT = "SNAPSHOT" +export const EXIT = "EXIT" +export const TERMINATE = "TERMINATE" +const DUMP = "DUMP" +const INC = "INC" +const KEYS = "KEYS" + +interface IRegistryRecord { + addr: string + mailbox: IMailbox + subs: Set + kvs: Record + error: any +} +interface IRoot { + FCL_REGISTRY: Record | null +} + +export type ActorContext = ReturnType + +export type Letter = { + to: string + from?: string + tag: string + data: any + timeout: number + reply: (data: any) => void + reject: (error: any) => void +} +export type HandlerFn = ( + ctx: ActorContext, + letter: Letter, + data: any +) => Promise | void +export type SpawnFn = (address?: string) => void +export interface ActorHandlers { + [INIT]?: (ctx: ActorContext) => Promise | void + [SUBSCRIBE]?: HandlerFn + [UNSUBSCRIBE]?: HandlerFn + [UPDATED]?: HandlerFn + [SNAPSHOT]?: HandlerFn + [EXIT]?: HandlerFn + [TERMINATE]?: HandlerFn + [DUMP]?: HandlerFn + [INC]?: HandlerFn + [KEYS]?: HandlerFn + [key: string]: HandlerFn | undefined +} + +const root: IRoot = (typeof self === "object" && + self.self === self && + (self as unknown as IRoot)) || + (typeof global === "object" && + global.global === global && + (global as unknown as IRoot)) || + (typeof window === "object" && + window.window === window && + (window as unknown as IRoot)) || {FCL_REGISTRY: null} + +root.FCL_REGISTRY = root.FCL_REGISTRY == null ? {} : root.FCL_REGISTRY + +const FCL_REGISTRY = root.FCL_REGISTRY +let pid = 0b0 + +const DEFAULT_TIMEOUT = 5000 + +export function send( + addr: string, + tag: string, + data?: Record | null, + opts?: {expectReply?: true; timeout?: number; from?: string} +): Promise +export function send( + addr: string, + tag: string, + data?: Record | null, + opts?: {expectReply?: false; timeout?: number; from?: string} +): Promise +export function send( + addr: string, + tag: string, + data?: Record | null, + opts: {expectReply?: boolean; timeout?: number; from?: string} = { + expectReply: false, + } +): Promise { + return new Promise((resolve, reject) => { + const expectReply = opts.expectReply || false + const timeout = opts.timeout != null ? opts.timeout : DEFAULT_TIMEOUT + + if (expectReply && timeout) { + setTimeout( + () => + reject(new Error(`Timeout: ${timeout}ms passed without a response.`)), + timeout + ) + } + + const payload = { + to: addr, + from: opts.from, + tag, + data, + timeout, + reply: resolve, + reject, + } + + try { + if (FCL_REGISTRY[addr]) { + FCL_REGISTRY[addr].mailbox.deliver(payload) + } + if (!expectReply) { + resolve(true) + } + } catch (error) { + console.error( + "FCL.Actor -- Could Not Deliver Message", + payload, + FCL_REGISTRY[addr], + error + ) + reject(error) + } + }) +} + +export const kill = (addr: string) => { + delete FCL_REGISTRY[addr] +} + +const fromHandlers = + (handlers: Handlers) => + async (ctx: ActorContext) => { + if (typeof handlers[INIT] === "function") await handlers[INIT](ctx) + __loop: while (1) { + const letter = await ctx.receive() + try { + if (letter.tag === EXIT) { + if (typeof handlers[TERMINATE] === "function") { + await handlers[TERMINATE](ctx, letter, letter.data || {}) + } + break __loop + } + await handlers[letter.tag as any]?.(ctx, letter, letter.data || {}) + } catch (error) { + console.error(`${ctx.self()} Error`, letter, error) + } finally { + continue __loop + } + } + } + +const parseAddr = (addr: string | number | null): string => { + if (addr == null) { + return String(++pid) + } + return String(addr) +} + +export const spawn = ( + fnOrHandlers: ((ctx: ActorContext) => Promise) | Handlers, + rawAddr: string | number | null = null +) => { + const addr = parseAddr(rawAddr) + if (FCL_REGISTRY[addr] != null) return addr + + FCL_REGISTRY[addr] = { + addr, + mailbox: createMailbox(), + subs: new Set(), + kvs: {}, + error: null, + } + + const ctx = createCtx(addr) + + let fn: (ctx: ActorContext) => Promise + if (typeof fnOrHandlers === "object") + fn = fromHandlers(fnOrHandlers) + else fn = fnOrHandlers + + queueMicrotask(async () => { + await fn(ctx) + kill(addr) + }) + + return addr +} + +const createCtx = (addr: string) => ({ + self: () => addr, + receive: () => FCL_REGISTRY[addr].mailbox.receive(), + send: ( + to: string | null | undefined, + tag: string, + data?: any, + opts: Record = {} + ) => { + if (to == null) return + opts.from = addr + return send(to, tag, data, opts) + }, + sendSelf: (tag: string, data?: any, opts: Record = {}) => { + if (FCL_REGISTRY[addr]) send(addr, tag, data, opts) + }, + broadcast: (tag: string, data: any, opts: Record = {}) => { + opts.from = addr + for (const to of FCL_REGISTRY[addr].subs) send(to, tag, data, opts) + }, + subscribe: (sub?: string | null) => + sub != null && FCL_REGISTRY[addr].subs.add(sub), + unsubscribe: (sub?: string | null) => + sub != null && FCL_REGISTRY[addr].subs.delete(sub), + subscriberCount: () => FCL_REGISTRY[addr].subs.size, + hasSubs: () => !!FCL_REGISTRY[addr].subs.size, + put: (key: string, value: T) => { + if (key != null) FCL_REGISTRY[addr].kvs[key] = value + }, + get: (key: string, fallback: T | undefined = undefined) => { + const value = FCL_REGISTRY[addr].kvs[key] + return value == null ? fallback : value + }, + delete: (key: string) => { + delete FCL_REGISTRY[addr].kvs[key] + }, + update: (key: string, fn: (x: T) => U) => { + if (key != null) + FCL_REGISTRY[addr].kvs[key] = fn(FCL_REGISTRY[addr].kvs[key]) + }, + keys: () => { + return Object.keys(FCL_REGISTRY[addr].kvs) + }, + all: () => { + return FCL_REGISTRY[addr].kvs + }, + where: (pattern: RegExp) => { + return Object.keys(FCL_REGISTRY[addr].kvs).reduce((acc, key) => { + return pattern.test(key) + ? {...acc, [key]: FCL_REGISTRY[addr].kvs[key]} + : acc + }, {}) + }, + merge: (data: Record = {}) => { + Object.keys(data).forEach(key => (FCL_REGISTRY[addr].kvs[key] = data[key])) + }, + fatalError: (error: Error) => { + FCL_REGISTRY[addr].error = error + for (const to of FCL_REGISTRY[addr].subs) send(to, UPDATED) + }, +}) + +// Returns an unsubscribe function +// A SUBSCRIBE handler will need to be created to handle the subscription event +// +// [SUBSCRIBE]: (ctx, letter) => { +// ctx.subscribe(letter.from) +// ctx.send(letter.from, UPDATED, ctx.all()) +// } +// +export function subscriber( + address: string, + spawnFn: SpawnFn, + callback: (data: T | null, error: Error | null) => void +) { + spawnFn(address) + const self = spawn(async (ctx: ActorContext) => { + ctx.send(address, SUBSCRIBE) + while (1) { + const letter = await ctx.receive() + const error = FCL_REGISTRY[address].error + if (letter.tag === EXIT) { + ctx.send(address, UNSUBSCRIBE) + return + } + if (error) { + callback(null, error) + ctx.send(address, UNSUBSCRIBE) + return + } + + callback(letter.data, null) + } + }) + return () => send(self, EXIT) +} + +// Returns a promise that returns a result +// A SNAPSHOT handler will need to be created to handle the snapshot event +// +// [SNAPSHOT]: (ctx, letter) => { +// letter.reply(ctx.all()) +// } +// +export function snapshoter(address: string, spawnFn: SpawnFn) { + spawnFn(address) + return send(address, SNAPSHOT, null, { + expectReply: true, + timeout: 0, + }) +} diff --git a/packages/util-actor/src/mailbox/index.js b/packages/util-actor/src/mailbox/index.js deleted file mode 100644 index ca1cd6be9..000000000 --- a/packages/util-actor/src/mailbox/index.js +++ /dev/null @@ -1,22 +0,0 @@ -export const mailbox = () => { - const queue = [] - var next - - return { - async deliver(msg) { - queue.push(msg) - if (next) { - next(queue.shift()) - next = undefined - } - }, - - receive() { - return new Promise(function innerReceive(resolve) { - const msg = queue.shift() - if (msg) return resolve(msg) - next = resolve - }) - }, - } -} diff --git a/packages/util-actor/src/mailbox/index.test.js b/packages/util-actor/src/mailbox/index.test.ts similarity index 51% rename from packages/util-actor/src/mailbox/index.test.js rename to packages/util-actor/src/mailbox/index.test.ts index 4d5a84c6a..cc85aa2dd 100644 --- a/packages/util-actor/src/mailbox/index.test.js +++ b/packages/util-actor/src/mailbox/index.test.ts @@ -9,8 +9,8 @@ test("send and receive", async () => { test("first in -- first out", async () => { const m = genMailbox() const msgx = ["A", "B", "C", "D", "E", "F"] - for (let msg of msgx) m.deliver(msg) - for (let msg of msgx) expect(await m.receive()).toBe(msg) + for (const msg of msgx) m.deliver(msg) + for (const msg of msgx) expect(await m.receive()).toBe(msg) }) test("many mailboxes", async () => { @@ -24,13 +24,13 @@ test("many mailboxes", async () => { const m3x = ["X", "Y", "Z"] const m4x = ["7", "8", "9"] - for (let msg of m1x) m1.deliver(msg) - for (let msg of m2x) m2.deliver(msg) - for (let msg of m3x) m3.deliver(msg) - for (let msg of m4x) m4.deliver(msg) + for (const msg of m1x) m1.deliver(msg) + for (const msg of m2x) m2.deliver(msg) + for (const msg of m3x) m3.deliver(msg) + for (const msg of m4x) m4.deliver(msg) - for (let msg of m1x) expect(await m1.receive()).toBe(msg) - for (let msg of m2x) expect(await m2.receive()).toBe(msg) - for (let msg of m3x) expect(await m3.receive()).toBe(msg) - for (let msg of m4x) expect(await m4.receive()).toBe(msg) + for (const msg of m1x) expect(await m1.receive()).toBe(msg) + for (const msg of m2x) expect(await m2.receive()).toBe(msg) + for (const msg of m3x) expect(await m3.receive()).toBe(msg) + for (const msg of m4x) expect(await m4.receive()).toBe(msg) }) diff --git a/packages/util-actor/src/mailbox/index.ts b/packages/util-actor/src/mailbox/index.ts new file mode 100644 index 000000000..4d9d4b715 --- /dev/null +++ b/packages/util-actor/src/mailbox/index.ts @@ -0,0 +1,26 @@ +export interface IMailbox { + deliver(msg: T): Promise + receive(): Promise +} +export const mailbox = (): IMailbox => { + const queue: T[] = [] + let next: ((msg: T) => void) | undefined + + return { + async deliver(msg: T) { + queue.push(msg) + if (next) { + next(queue.shift() as T) + next = undefined + } + }, + + receive(): Promise { + return new Promise(function innerReceive(resolve) { + const msg = queue.shift() + if (msg) return resolve(msg) + next = resolve + }) + }, + } +} diff --git a/packages/util-actor/tsconfig.json b/packages/util-actor/tsconfig.json new file mode 100644 index 000000000..ac6917898 --- /dev/null +++ b/packages/util-actor/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig", + // Change this to match your project + "include": ["src/**/*"], + "compilerOptions": { + // Types should go into this directory. + // Removing this would place the .d.ts files + // next to the .js files + "outDir": "types" + } +} diff --git a/packages/util-address/.babelrc b/packages/util-address/.babelrc index 67fc2886b..d766c90b2 100644 --- a/packages/util-address/.babelrc +++ b/packages/util-address/.babelrc @@ -1,7 +1,3 @@ { - "presets": [ - [ - "@babel/preset-env" - ] - ] + "presets": [["@babel/preset-env"], "@babel/preset-typescript"] } diff --git a/packages/util-address/.eslintrc.json b/packages/util-address/.eslintrc.json index b5e57f0a6..79f65ebf2 100644 --- a/packages/util-address/.eslintrc.json +++ b/packages/util-address/.eslintrc.json @@ -6,22 +6,18 @@ "node": true }, "extends": [ - "plugin:jsdoc/recommended" - ], - "plugins": [ - "jsdoc" + "plugin:jsdoc/recommended-typescript", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended" ], + "plugins": ["jsdoc", "@typescript-eslint"], + "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": "latest", "sourceType": "module" }, "ignorePatterns": ["**/dist/"], "rules": { - "jsdoc/require-jsdoc": [ - "error", - { - "publicOnly": true - } - ] + "@typescript-eslint/no-explicit-any": "off" } -} \ No newline at end of file +} diff --git a/packages/util-address/package.json b/packages/util-address/package.json index 19242e4e0..622f4b940 100644 --- a/packages/util-address/package.json +++ b/packages/util-address/package.json @@ -1,6 +1,6 @@ { "name": "@onflow/util-address", - "version": "1.1.0", + "version": "1.2.0-typescript.0", "description": "Flow JS SDK Util -- Address", "license": "Apache-2.0", "author": "Dapper Labs ", @@ -13,24 +13,27 @@ "url": "https://github.com/onflow/flow-js-sdk/issues" }, "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1-alpha.0", - "@onflow/types": "^1.1.0", + "@babel/preset-typescript": "^7.22.5", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", + "@onflow/types": "^1.2.0-typescript.0", + "@types/jest": "^29.5.3", "@types/node": "^18.13.0", - "eslint": "^8.33.0", - "eslint-plugin-jsdoc": "^39.7.5", + "@typescript-eslint/eslint-plugin": "^6.4.0", + "@typescript-eslint/parser": "^6.4.0", + "eslint": "^8.47.0", + "eslint-plugin-jsdoc": "^46.4.6", "jest": "^29.5.0", "typescript": "^4.9.5" }, - "source": "src/index.js", + "source": "src/index.ts", "main": "dist/util-address.js", "module": "dist/util-address.module.js", "unpkg": "dist/util-address.umd.js", - "types": "types/index.d.ts", + "types": "dist/index.d.ts", "scripts": { "prepublishOnly": "npm test && npm run build", "test": "jest", "build": "npm run lint && fcl-bundle", - "build:types": "tsc", "test:watch": "jest --watch", "start": "fcl-bundle --watch", "lint": "eslint ." diff --git a/packages/util-address/src/index.js b/packages/util-address/src/index.js deleted file mode 100644 index 38d51151d..000000000 --- a/packages/util-address/src/index.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * @description Removes 0x from address if present - * @param {string} address - Flow address - * @returns {string} - Flow address without 0x prefix - */ - export function sansPrefix(address) { - if (address == null) return null - return address.replace(/^0x/, "").replace(/^Fx/, "") -} - -/** - * @description Adds 0x to address if not already present - * @param {string} address - Flow address - * @returns {string} - Flow address with 0x prefix - */ -export function withPrefix(address) { - if (address == null) return null - return "0x" + sansPrefix(address) -} - -/** - * @description Adds 0x to address if not already present - * @param {string} address - Flow address - * @returns {string} - Flow address with 0x prefix - */ -export function display(address) { - return withPrefix(address) -} diff --git a/packages/util-address/src/index.test.js b/packages/util-address/src/index.test.ts similarity index 100% rename from packages/util-address/src/index.test.js rename to packages/util-address/src/index.test.ts diff --git a/packages/util-address/src/index.ts b/packages/util-address/src/index.ts new file mode 100644 index 000000000..33e05de1a --- /dev/null +++ b/packages/util-address/src/index.ts @@ -0,0 +1,28 @@ +/** + * @description Removes 0x from address if present + * @param address - Flow address + * @returns Flow address without 0x prefix + */ +export function sansPrefix(address: string | null): string | null { + if (address == null) return null + return address.replace(/^0x/, "").replace(/^Fx/, "") +} + +/** + * @description Adds 0x to address if not already present + * @param address - Flow address + * @returns Flow address with 0x prefix + */ +export function withPrefix(address: string | null): string | null { + if (address == null) return null + return "0x" + sansPrefix(address) +} + +/** + * @description Adds 0x to address if not already present + * @param address - Flow address + * @returns Flow address with 0x prefix + */ +export function display(address: string | null): string | null { + return withPrefix(address) +} diff --git a/packages/util-address/tsconfig.json b/packages/util-address/tsconfig.json index 6bfcb0e73..88be905eb 100644 --- a/packages/util-address/tsconfig.json +++ b/packages/util-address/tsconfig.json @@ -1,25 +1,11 @@ { + "extends": "../../tsconfig", // Change this to match your project "include": ["src/**/*"], - "exclude": [ - "src/**/*.test.js", - ], "compilerOptions": { - "types" : ["node"], - // Tells TypeScript to read JS files, as - // normally they are ignored as source files - "allowJs": true, - // Generate d.ts files - "declaration": true, - // This compiler run should - // only output d.ts files - "emitDeclarationOnly": true, // Types should go into this directory. // Removing this would place the .d.ts files // next to the .js files "outDir": "types", - // go to js file when using IDE functions like - // "Go to Definition" in VSCode - "declarationMap": false, } } \ No newline at end of file diff --git a/packages/util-encode-key/.babelrc b/packages/util-encode-key/.babelrc index 67fc2886b..d766c90b2 100644 --- a/packages/util-encode-key/.babelrc +++ b/packages/util-encode-key/.babelrc @@ -1,7 +1,3 @@ { - "presets": [ - [ - "@babel/preset-env" - ] - ] + "presets": [["@babel/preset-env"], "@babel/preset-typescript"] } diff --git a/packages/util-encode-key/.eslintrc.json b/packages/util-encode-key/.eslintrc.json index b5e57f0a6..79f65ebf2 100644 --- a/packages/util-encode-key/.eslintrc.json +++ b/packages/util-encode-key/.eslintrc.json @@ -6,22 +6,18 @@ "node": true }, "extends": [ - "plugin:jsdoc/recommended" - ], - "plugins": [ - "jsdoc" + "plugin:jsdoc/recommended-typescript", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended" ], + "plugins": ["jsdoc", "@typescript-eslint"], + "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": "latest", "sourceType": "module" }, "ignorePatterns": ["**/dist/"], "rules": { - "jsdoc/require-jsdoc": [ - "error", - { - "publicOnly": true - } - ] + "@typescript-eslint/no-explicit-any": "off" } -} \ No newline at end of file +} diff --git a/packages/util-encode-key/package.json b/packages/util-encode-key/package.json index 8e8012eb7..14d6f2f4d 100644 --- a/packages/util-encode-key/package.json +++ b/packages/util-encode-key/package.json @@ -1,6 +1,6 @@ { "name": "@onflow/util-encode-key", - "version": "1.1.0", + "version": "1.2.0-typescript.0", "description": "Flow JS SDK Util -- Encode Key", "license": "Apache-2.0", "author": "Dapper Labs ", @@ -13,31 +13,34 @@ "url": "https://github.com/onflow/flow-js-sdk/issues" }, "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1-alpha.0", - "@onflow/types": "^1.1.0", + "@babel/preset-typescript": "^7.22.5", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", + "@onflow/types": "^1.2.0-typescript.0", + "@types/jest": "^29.5.3", "@types/node": "^18.13.0", - "eslint": "^8.33.0", - "eslint-plugin-jsdoc": "^39.8.0", + "@typescript-eslint/eslint-plugin": "^6.4.0", + "@typescript-eslint/parser": "^6.4.0", + "eslint": "^8.47.0", + "eslint-plugin-jsdoc": "^46.4.6", "jest": "^29.5.0", "typescript": "^4.9.5" }, - "source": "src/index.js", + "source": "src/index.ts", "main": "dist/util-encode-key.js", "module": "dist/util-encode-key.module.js", "unpkg": "dist/util-encode-key.umd.js", - "types": "types/index.d.ts", + "types": "dist/index.d.ts", "scripts": { "prepublishOnly": "npm test && npm run build", "test": "jest", "build": "npm run lint && fcl-bundle", - "build:types": "tsc", "test:watch": "jest --watch", "start": "fcl-bundle --watch", "lint": "eslint ." }, "dependencies": { "@babel/runtime": "^7.18.6", - "@onflow/rlp": "^1.1.0", - "@onflow/util-invariant": "^1.1.0" + "@onflow/rlp": "^1.2.0-typescript.0", + "@onflow/util-invariant": "^1.2.0-typescript.0" } } diff --git a/packages/util-encode-key/src/__snapshots__/index.test.js.snap b/packages/util-encode-key/src/__snapshots__/index.test.ts.snap similarity index 100% rename from packages/util-encode-key/src/__snapshots__/index.test.js.snap rename to packages/util-encode-key/src/__snapshots__/index.test.ts.snap diff --git a/packages/util-encode-key/src/index.test.js b/packages/util-encode-key/src/index.test.ts similarity index 69% rename from packages/util-encode-key/src/index.test.js rename to packages/util-encode-key/src/index.test.ts index fed721890..220e69b7b 100644 --- a/packages/util-encode-key/src/index.test.js +++ b/packages/util-encode-key/src/index.test.ts @@ -1,10 +1,4 @@ -import { - encodeKey, - ECDSA_P256, - ECDSA_secp256k1, - SHA2_256, - SHA3_256, -} from "./index.js" +import {encodeKey, ECDSA_P256, ECDSA_secp256k1, SHA2_256, SHA3_256} from "./" const PUBLIC_KEYS = [ "0bfcd8790c3ce88f3fac9d4bd23514f48bf0cdd1f6c3c8bdf87b11489b1bbeca1ef805ec2ee76451e9bdb265284f78febaeacbc8b0827e0a7baafee4e655d0b5", @@ -18,10 +12,10 @@ const HASHINGS = [SHA2_256, SHA3_256] const WEIGHTS = [0, 32, 512, 1000] -for (let [key_index, key] of PUBLIC_KEYS.entries()) { - for (let [curve_index, curve] of CURVES.entries()) { - for (let [hash_index, hash] of HASHINGS.entries()) { - for (let [weight_index, weight] of WEIGHTS.entries()) { +for (const [key_index, key] of PUBLIC_KEYS.entries()) { + for (const [curve_index, curve] of CURVES.entries()) { + for (const [hash_index, hash] of HASHINGS.entries()) { + for (const [weight_index, weight] of WEIGHTS.entries()) { test(`key:${key_index} curve:${curve_index} hash:${hash_index} weight:${weight_index}`, () => { expect(encodeKey(key, curve, hash, weight)).toMatchSnapshot() }) diff --git a/packages/util-encode-key/src/index.js b/packages/util-encode-key/src/index.ts similarity index 76% rename from packages/util-encode-key/src/index.js rename to packages/util-encode-key/src/index.ts index 6c6b98b5b..9ba359091 100644 --- a/packages/util-encode-key/src/index.js +++ b/packages/util-encode-key/src/index.ts @@ -3,48 +3,23 @@ import {encode} from "@onflow/rlp" // Curves -/** - * @type {number} - */ export const ECDSA_P256 = 2 - -/** - * @type {number} - */ export const ECDSA_secp256k1 = 3 - -/** - * @type {Set} - * @private - */ const VALID_CURVES = new Set([ECDSA_P256, ECDSA_secp256k1]) // Hashing -/** - * @type {number} - */ export const SHA2_256 = 1 - -/** - * @type {number} - */ export const SHA3_256 = 3 - -/** - * @type {Set} - * @private - */ const VALID_HASHINGS = new Set([SHA2_256, SHA3_256]) /** * Encodes a key into a hex string - * - * @param {string} key - The key to encode (DER Hex) - * @param {number} curve - The curve Flow needs to use with your key [ECDSA_P256|ECDSA_secp256k1] - * @param {number} hash - The hashing algorythm Flow needs to use with your key [SHA2_256|SHA3_256] - * @param {number} weight - The weight you want this key to have [Range: 0..1000] - * @returns {string} - The encoded key + * @param key - The key to encode (DER Hex) + * @param curve - The curve Flow needs to use with your key [ECDSA_P256|ECDSA_secp256k1] + * @param hash - The hashing algorythm Flow needs to use with your key [SHA2_256|SHA3_256] + * @param weight - The weight you want this key to have [Range: 0..1000] + * @returns The encoded key * @throws {Error} - Throws if the key is not a string * @throws {Error} - Throws if the key is not in the correct format * @throws {Error} - Throws if the curve is not a number @@ -56,7 +31,12 @@ const VALID_HASHINGS = new Set([SHA2_256, SHA3_256]) * import {encodeKey, ECDSA_P256, SHA3_256} from "@onflow/util-encode-key" * encodeKey("aabbccdd", ECDSA_P256, SHA3_256, 1000) // => "aabbccdd0201000" */ -export function encodeKey(key, curve, hash, weight = 1000) { +export function encodeKey( + key: string, + curve: number, + hash: number, + weight = 1000 +): string { invariant( typeof key === "string", "encodeKey(key, curve, hash, weight) -- invalid key (expecting type of string)" @@ -87,4 +67,4 @@ export function encodeKey(key, curve, hash, weight = 1000) { ) return encode([Buffer.from(key, "hex"), curve, hash, weight]).toString("hex") -} \ No newline at end of file +} diff --git a/packages/util-encode-key/tsconfig.json b/packages/util-encode-key/tsconfig.json index 6bfcb0e73..88be905eb 100644 --- a/packages/util-encode-key/tsconfig.json +++ b/packages/util-encode-key/tsconfig.json @@ -1,25 +1,11 @@ { + "extends": "../../tsconfig", // Change this to match your project "include": ["src/**/*"], - "exclude": [ - "src/**/*.test.js", - ], "compilerOptions": { - "types" : ["node"], - // Tells TypeScript to read JS files, as - // normally they are ignored as source files - "allowJs": true, - // Generate d.ts files - "declaration": true, - // This compiler run should - // only output d.ts files - "emitDeclarationOnly": true, // Types should go into this directory. // Removing this would place the .d.ts files // next to the .js files "outDir": "types", - // go to js file when using IDE functions like - // "Go to Definition" in VSCode - "declarationMap": false, } } \ No newline at end of file diff --git a/packages/util-invariant/.eslintrc.json b/packages/util-invariant/.eslintrc.json new file mode 100644 index 000000000..e80c057f5 --- /dev/null +++ b/packages/util-invariant/.eslintrc.json @@ -0,0 +1,20 @@ +{ + "env": { + "browser": true, + "es2021": true, + "jest": true, + "node": true + }, + "extends": [ + "plugin:jsdoc/recommended-typescript", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended" + ], + "plugins": ["jsdoc", "@typescript-eslint"], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": "latest", + "sourceType": "module" + }, + "ignorePatterns": ["**/dist/"] +} diff --git a/packages/util-invariant/package.json b/packages/util-invariant/package.json index c005edc92..efd0890dc 100644 --- a/packages/util-invariant/package.json +++ b/packages/util-invariant/package.json @@ -1,6 +1,6 @@ { "name": "@onflow/util-invariant", - "version": "1.1.0", + "version": "1.2.0-typescript.0", "description": "Flow JS SDK Util -- Invariant", "license": "Apache-2.0", "author": "Dapper Labs ", @@ -13,14 +13,21 @@ "url": "https://github.com/onflow/flow-js-sdk/issues" }, "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1-alpha.0", - "@onflow/types": "^1.1.0", + "@babel/preset-typescript": "^7.22.5", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", + "@onflow/types": "^1.2.0-typescript.0", + "@types/jest": "^29.5.3", + "@typescript-eslint/eslint-plugin": "^6.4.0", + "@typescript-eslint/parser": "^6.4.0", + "eslint": "^8.47.0", + "eslint-plugin-jsdoc": "^46.4.6", "jest": "^29.5.0" }, - "source": "src/index.js", + "source": "src/index.ts", "main": "dist/util-invariant.js", "module": "dist/util-invariant.module.js", "unpkg": "dist/util-invariant.umd.js", + "types": "dist/index.d.ts", "scripts": { "prepublishOnly": "npm test && npm run build", "test": "jest", diff --git a/packages/util-invariant/src/index.test.js b/packages/util-invariant/src/index.test.ts similarity index 100% rename from packages/util-invariant/src/index.test.js rename to packages/util-invariant/src/index.test.ts diff --git a/packages/util-invariant/src/index.js b/packages/util-invariant/src/index.ts similarity index 55% rename from packages/util-invariant/src/index.js rename to packages/util-invariant/src/index.ts index d453e9406..0fedc85b2 100644 --- a/packages/util-invariant/src/index.js +++ b/packages/util-invariant/src/index.ts @@ -1,17 +1,16 @@ /** * Asserts fact is true, otherwise throw an error with invariant message - * @param {boolean} fact - * @param {string} msg - * @param {Array} rest - * @returns {void} + * @param fact + * @param msg + * @param rest */ -export function invariant(fact, msg, ...rest) { +export function invariant(fact: boolean, msg: string, ...rest: any[]) { if (!fact) { const error = new Error(`INVARIANT ${msg}`) error.stack = error.stack - .split("\n") - .filter(d => !/at invariant/.test(d)) - .join("\n") + ?.split("\n") + ?.filter(d => !/at invariant/.test(d)) + ?.join("\n") console.error("\n\n---\n\n", error, "\n\n", ...rest, "\n\n---\n\n") throw error } diff --git a/packages/util-invariant/tsconfig.json b/packages/util-invariant/tsconfig.json new file mode 100644 index 000000000..88be905eb --- /dev/null +++ b/packages/util-invariant/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig", + // Change this to match your project + "include": ["src/**/*"], + "compilerOptions": { + // Types should go into this directory. + // Removing this would place the .d.ts files + // next to the .js files + "outDir": "types", + } +} \ No newline at end of file diff --git a/packages/util-logger/.babelrc b/packages/util-logger/.babelrc index 67fc2886b..d766c90b2 100644 --- a/packages/util-logger/.babelrc +++ b/packages/util-logger/.babelrc @@ -1,7 +1,3 @@ { - "presets": [ - [ - "@babel/preset-env" - ] - ] + "presets": [["@babel/preset-env"], "@babel/preset-typescript"] } diff --git a/packages/util-logger/.eslintrc.json b/packages/util-logger/.eslintrc.json new file mode 100644 index 000000000..e80c057f5 --- /dev/null +++ b/packages/util-logger/.eslintrc.json @@ -0,0 +1,20 @@ +{ + "env": { + "browser": true, + "es2021": true, + "jest": true, + "node": true + }, + "extends": [ + "plugin:jsdoc/recommended-typescript", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended" + ], + "plugins": ["jsdoc", "@typescript-eslint"], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": "latest", + "sourceType": "module" + }, + "ignorePatterns": ["**/dist/"] +} diff --git a/packages/util-logger/package.json b/packages/util-logger/package.json index 7d5fe9a75..b5e36d800 100644 --- a/packages/util-logger/package.json +++ b/packages/util-logger/package.json @@ -1,6 +1,6 @@ { "name": "@onflow/util-logger", - "version": "1.2.2", + "version": "1.3.0-typescript.0", "description": "Logger for FCL-JS", "license": "Apache-2.0", "author": "Dapper Labs ", @@ -13,13 +13,20 @@ "url": "https://github.com/onflow/flow-js-sdk/issues" }, "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1", + "@babel/preset-typescript": "^7.22.5", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", + "@types/jest": "^29.5.3", + "@typescript-eslint/eslint-plugin": "^6.4.0", + "@typescript-eslint/parser": "^6.4.0", + "eslint": "^8.47.0", + "eslint-plugin-jsdoc": "^46.4.6", "jest": "^29.5.0" }, - "source": "src/util-logger.js", + "source": "src/util-logger.ts", "main": "dist/util-logger.js", "module": "dist/util-logger.module.js", "unpkg": "dist/util-logger.umd.js", + "types": "dist/util-logger.d.ts", "scripts": { "prepublishOnly": "npm test && npm run build", "test": "jest", diff --git a/packages/util-logger/src/util-logger.js b/packages/util-logger/src/util-logger.js deleted file mode 100644 index 489cbd11f..000000000 --- a/packages/util-logger/src/util-logger.js +++ /dev/null @@ -1,151 +0,0 @@ -// Config dependency injected into logger to break circular dependency -let config = null -export const setConfig = _config => { - config = _config -} - -/** - * The levels of the logger - * - * @typedef {Object} LEVELS - * @property {number} debug - The debug level - * @property {number} info - The info level - * @property {number} log - The log level - * @property {number} warn - The warn level - * @property {number} error - The error level - * - */ -export const LEVELS = Object.freeze({ - debug: 5, - info: 4, - log: 3, - warn: 2, - error: 1, -}) - -/** - * Builds a message formatted for the logger - * - * @param {Object} options - The options for the log - * @param {string} options.title - The title of the log - * @param {string} options.message - The message of the log - * @returns {Array} - The message formatted for the logger - * - * @example - * buildLoggerMessageArgs({ title: "My Title", message: "My Message" }) - */ -const buildLoggerMessageArgs = ({title, message}) => { - return [ - ` - %c${title} - ============================ - - ${message} - - ============================ - ` - .replace(/\n[^\S\r\n]+/g, "\n") - .trim(), - , - "font-weight:bold;font-family:monospace;", - ] -} - -/** - * Logs messages based on the level of the message and the level set in the config - * - * @param {Object} options - The options for the log - * @param {string} options.title - The title of the log - * @param {string} options.message - The message of the log - * @param {number} options.level - The level of the log - * @param {boolean} options.always - Whether to always show the log - * @returns {Promise} - * - * @example - * log({ title: "My Title", message: "My Message", level: LEVELS.warn, always: false }) - * - */ -export const log = async ({title, message, level, always = false}) => { - const configLoggerLevel = - (await config?.()?.get("logger.level")) ?? LEVELS.warn - - // If config level is below message level then don't show it - if (!always && configLoggerLevel < level) return - - const loggerMessageArgs = buildLoggerMessageArgs({title, message}) - - switch (level) { - case LEVELS.debug: - console.debug(...loggerMessageArgs) - break - case LEVELS.info: - console.info(...loggerMessageArgs) - break - case LEVELS.warn: - console.warn(...loggerMessageArgs) - break - case LEVELS.error: - console.error(...loggerMessageArgs) - break - default: - console.log(...loggerMessageArgs) - } -} - -/** - * Logs a deprecation notice - * - * @param {Object} options - The options for the log - * @param {string} options.pkg - The package that is being deprecated - * @param {string} options.subject - The subject of the deprecation - * @param {string} options.transition - The transition path for the deprecation - * @param {number} options.level - The level of the log - * @param {string} options.message - The message of the log - * @param {Function} options.callback - A callback to run after the log - * @returns {Promise} - * - * @example - * log.deprecate({ pkg: "@onflow/fcl", subject: "Some item", transition: "https://github.com/onflow/flow-js-sdk", message: "Descriptive message", level: LEVELS.warn, callback: () => {} }) - * - */ -log.deprecate = ({ - pkg, - subject, - transition, - level = LEVELS.warn, - message = "", - callback = null, -}) => { - const capitalizeFirstLetter = string => { - return string.charAt(0).toUpperCase() + string.slice(1) - } - - const logMessage = () => - log({ - title: `${pkg ? pkg + " " : ""}Deprecation Notice`, - message: ` - ${ - subject - ? `${capitalizeFirstLetter( - subject - )} is deprecated and will cease to work in future releases${ - pkg ? " of " + pkg : "" - }.` - : "" - }${message ? "\n" + message : ""}${ - transition - ? `\nYou can learn more (including a guide on common transition paths) here: ${transition}` - : "" - } - `.trim(), - level, - }) - - if (typeof callback === "function") { - return async (...args) => { - await logMessage() - return await callback(...args) - } - } - return logMessage() -} diff --git a/packages/util-logger/src/util-logger.test.js b/packages/util-logger/src/util-logger.test.ts similarity index 100% rename from packages/util-logger/src/util-logger.test.js rename to packages/util-logger/src/util-logger.test.ts diff --git a/packages/util-logger/src/util-logger.ts b/packages/util-logger/src/util-logger.ts new file mode 100644 index 000000000..d6c3e2552 --- /dev/null +++ b/packages/util-logger/src/util-logger.ts @@ -0,0 +1,162 @@ +interface IConfig { + get: (key: string) => T; +} + +type Config = IConfig & (() => IConfig) | null + +// Config dependency injected into logger to break circular dependency +let config: Config = null +export const setConfig = (_config: any) => { + config = _config +} + +/** + * The levels of the logger + */ +export enum LEVELS { + debug = 5, + info = 4, + log = 3, + warn = 2, + error = 1, +} + +/** + * Builds a message formatted for the logger + * @param options - The options for the log + * @param options.title - The title of the log + * @param options.message - The message of the log + * @returns The message formatted for the logger + * @example + * buildLoggerMessageArgs({ title: "My Title", message: "My Message" }) + */ +const buildLoggerMessageArgs = (options: { + title: string + message: string +}): string[] => { + const {title, message} = options + return [ + ` + %c${title} + ============================ + + ${message} + + ============================ + ` + .replace(/\n[^\S\r\n]+/g, "\n") + .trim(), + "font-weight:bold;font-family:monospace;", + ] +} + +/** + * Logs messages based on the level of the message and the level set in the config + * @param options - The options for the log + * @param options.title - The title of the log + * @param options.message - The message of the log + * @param options.level - The level of the log + * @param options.always - Whether to always show the log + * @example + * log({ title: "My Title", message: "My Message", level: LEVELS.warn, always: false }) + */ +export const log = async (options: { + title: string + message: string + level: number + always?: boolean +}) => { + const {title, message, level, always} = options + const configLoggerLevel = (await config?.()?.get("logger.level")) ?? LEVELS.warn + + // If config level is below message level then don't show it + if (!always && configLoggerLevel < level) return + + const loggerMessageArgs = buildLoggerMessageArgs({title, message}) + + switch (level) { + case LEVELS.debug: + console.debug(...loggerMessageArgs) + break + case LEVELS.info: + console.info(...loggerMessageArgs) + break + case LEVELS.warn: + console.warn(...loggerMessageArgs) + break + case LEVELS.error: + console.error(...loggerMessageArgs) + break + default: + console.log(...loggerMessageArgs) + } +} + +/** + * Logs a deprecation notice. If a callback is provided this function returns a function that will call the callback and log the deprecation notice, otherwise it just logs the deprecation notice. + * @param options - The options for the log + * @param options.pkg - The package that is being deprecated + * @param options.subject - The subject of the deprecation + * @param options.transition - The transition path for the deprecation + * @param options.level - The level of the log + * @param options.message - The message of the log + * @param options.callback - A callback to run after the log + * @returns A function that will call the callback and log the deprecation notice if the callback is provided + * @example + * // Logs a deprecation notice + * log.deprecate({ pkg: "@onflow/fcl", subject: "Some item", transition: "https://github.com/onflow/flow-js-sdk", message: "Descriptive message", level: LEVELS.warn, callback: () => {} }) + * @example + * function someFunction() { ... } + * const deprecatedFunction = log.deprecate({ pkg: "@onflow/fcl", subject: "Some item", transition: "https://github.com/foo/bar/TRANSITIONS.md", message: "Descriptive message", level: LEVELS.warn, callback: someFunction }) + * deprecatedFunction() // Calls someFunction and logs the deprecation notice + */ +log.deprecate = (options: { + pkg?: string + subject?: string + transition?: string + level?: number + message?: string + callback?: (...args: T[]) => U +}): ((...args: T[]) => Promise) | Promise => { + const { + pkg, + subject, + transition, + level = LEVELS.warn, + message = "", + callback = null, + } = options + + const capitalizeFirstLetter = (str: string) => { + return str.charAt(0).toUpperCase() + str.slice(1) + } + + const logMessage = () => + log({ + title: `${pkg ? pkg + " " : ""}Deprecation Notice`, + message: ` + ${ + subject + ? `${capitalizeFirstLetter( + subject + )} is deprecated and will cease to work in future releases${ + pkg ? " of " + pkg : "" + }.` + : "" + }${message ? "\n" + message : ""}${ + transition + ? `\nYou can learn more (including a guide on common transition paths) here: ${transition}` + : "" + } + `.trim(), + level, + }) + + if (typeof callback === "function") { + return async (...args: T[]) => { + await logMessage() + return await callback(...args) + } + } + return logMessage() +} diff --git a/packages/util-logger/tsconfig.json b/packages/util-logger/tsconfig.json new file mode 100644 index 000000000..88be905eb --- /dev/null +++ b/packages/util-logger/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig", + // Change this to match your project + "include": ["src/**/*"], + "compilerOptions": { + // Types should go into this directory. + // Removing this would place the .d.ts files + // next to the .js files + "outDir": "types", + } +} \ No newline at end of file diff --git a/packages/util-semver/package.json b/packages/util-semver/package.json index 47dfe67f7..b24246f31 100644 --- a/packages/util-semver/package.json +++ b/packages/util-semver/package.json @@ -13,7 +13,7 @@ "start": "fcl-bundle --watch" }, "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", "jest": "^29.5.0" }, "dependencies": { diff --git a/packages/util-template/.babelrc b/packages/util-template/.babelrc index 67fc2886b..d766c90b2 100644 --- a/packages/util-template/.babelrc +++ b/packages/util-template/.babelrc @@ -1,7 +1,3 @@ { - "presets": [ - [ - "@babel/preset-env" - ] - ] + "presets": [["@babel/preset-env"], "@babel/preset-typescript"] } diff --git a/packages/util-template/.eslintrc.json b/packages/util-template/.eslintrc.json new file mode 100644 index 000000000..e80c057f5 --- /dev/null +++ b/packages/util-template/.eslintrc.json @@ -0,0 +1,20 @@ +{ + "env": { + "browser": true, + "es2021": true, + "jest": true, + "node": true + }, + "extends": [ + "plugin:jsdoc/recommended-typescript", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended" + ], + "plugins": ["jsdoc", "@typescript-eslint"], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": "latest", + "sourceType": "module" + }, + "ignorePatterns": ["**/dist/"] +} diff --git a/packages/util-template/package.json b/packages/util-template/package.json index 87a72afe9..8f51aeeee 100644 --- a/packages/util-template/package.json +++ b/packages/util-template/package.json @@ -1,6 +1,6 @@ { "name": "@onflow/util-template", - "version": "1.1.0", + "version": "1.2.0-typescript.0", "description": "Template Literal used for Cadence Interop", "license": "Apache-2.0", "author": "Dapper Labs ", @@ -13,13 +13,20 @@ "url": "https://github.com/onflow/flow-js-sdk/issues" }, "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1-alpha.0", + "@babel/preset-typescript": "^7.22.5", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", + "@types/jest": "^29.5.3", + "@typescript-eslint/eslint-plugin": "^6.4.0", + "@typescript-eslint/parser": "^6.4.0", + "eslint": "^8.47.0", + "eslint-plugin-jsdoc": "^46.4.6", "jest": "^29.5.0" }, - "source": "src/template.js", + "source": "src/template.ts", "main": "dist/template.js", "module": "dist/template.module.js", "unpkg": "dist/template.umd.js", + "types": "dist/template.d.ts", "scripts": { "prepublishOnly": "npm test && npm run build", "test": "jest", @@ -28,6 +35,7 @@ "start": "fcl-bundle --watch" }, "dependencies": { - "@babel/runtime": "^7.18.6" + "@babel/runtime": "^7.18.6", + "@onflow/util-logger": "^1.3.0-typescript.0" } } diff --git a/packages/util-template/src/__snapshots__/template.test.js.snap b/packages/util-template/src/__snapshots__/template.test.ts.snap similarity index 94% rename from packages/util-template/src/__snapshots__/template.test.js.snap rename to packages/util-template/src/__snapshots__/template.test.ts.snap index 5a768939f..614f991a9 100644 --- a/packages/util-template/src/__snapshots__/template.test.js.snap +++ b/packages/util-template/src/__snapshots__/template.test.ts.snap @@ -10,7 +10,7 @@ exports[`template interop function template(template\`\${o=>o.a}\`)(o) -> 'abc' exports[`template interop function template\`\${o=>o.a}\`(o) -> 'abc' 1`] = `"abc"`; -exports[`template interop more template template(template\`x\${template\`y\${o => o.a}\`}\`)(o) -> 'xyabc' 1`] = `"xyabc"`; +exports[`template interop more template template(template\`x\${template\`y\${(_o: typeof o) => _o.a}\`}\`)(o) -> 'xyabc' 1`] = `"xyabc"`; exports[`template interop more template template\`x\${template\`y\${o=>o.a}\`}\`(o) => 'xyabc' 1`] = `"xyabc"`; diff --git a/packages/util-template/src/template.js b/packages/util-template/src/template.js deleted file mode 100644 index e064dab37..000000000 --- a/packages/util-template/src/template.js +++ /dev/null @@ -1,46 +0,0 @@ -import {log} from "@onflow/util-logger" - -export function interleave(a = [], b = [], c = []) { - if (!a.length && !b.length) return c - if (!a.length) return c - if (!b.length) return [...c, a[0]] - - const [aHead, ...aRest] = a - const [bHead, ...bRest] = b - - if (aHead !== undefined) c.push(aHead) - if (bHead !== undefined) c.push(bHead) - - return interleave(aRest, bRest, c) -} - -function recApply(d) { - return function (arg1) { - if (typeof arg1 === "function") { - log.deprecate({ - pkg: "FCL/SDK", - subject: "Interopolation of functions into template literals", - transition: - "https://github.com/onflow/flow-js-sdk/blob/master/packages/sdk/TRANSITIONS.md#0001-deprecate-params", - }) - return recApply(d)(arg1(d)) - } - return String(arg1) - } -} - -/** - * @param {(string|Array.<*>)} head - * @param {Array.<*>} rest - * @returns {{function(): string}} - */ -export function template(head, ...rest) { - if (typeof head === "string") return () => head - if (Array.isArray(head)) { - return d => - interleave(head, rest.map(recApply(d))) - .join("") - .trim() - } - return head -} diff --git a/packages/util-template/src/template.test.js b/packages/util-template/src/template.test.ts similarity index 72% rename from packages/util-template/src/template.test.js rename to packages/util-template/src/template.test.ts index 6014f676c..dac1be6cb 100644 --- a/packages/util-template/src/template.test.js +++ b/packages/util-template/src/template.test.ts @@ -23,14 +23,14 @@ describe("interleave", () => { }) }) -const _ = (msg, a, b) => { +const _ = (msg: string, a: unknown, b?: unknown) => { if (b == null) { test(msg, () => expect(a).toMatchSnapshot()) } else { test(msg, () => expect(a).toBe(b)) } } -const t = v => typeof v +const t = (v: T) => typeof v describe("template", () => { describe("input type vs output type", () => { @@ -52,10 +52,10 @@ describe("template", () => { describe("interop function", () => { const o = {a: "abc"} - _("template`${o=>o.a}`(o) -> 'abc'", template`${o => o.a}`(o)) + _("template`${o=>o.a}`(o) -> 'abc'", template`${(_o: typeof o) => _o.a}`(o)) _( "template(template`${o=>o.a}`)(o) -> 'abc'", - template(template`${o => o.a}`)(o) + template(template`${(_o: typeof o) => _o.a}`)(o) ) }) @@ -63,20 +63,20 @@ describe("template", () => { const o = {a: "abc"} _( "template`x${template`y${o=>o.a}`}`(o) => 'xyabc'", - template`x${template`y${o => o.a}`}`(o) + template`x${template`y${(_o: typeof o) => _o.a}`}`(o) ) _( "template`x${template`y${template`z${o=>o.a}`}`}`(o) => 'xyabc'", - template`x${template`y${template`z${o => o.a}`}`}`(o) + template`x${template`y${template`z${(_o: typeof o) => _o.a}`}`}`(o) ) _( - "template(template`x${template`y${o => o.a}`}`)(o) -> 'xyabc'", - template(template`x${template`y${o => o.a}`}`)(o) + "template(template`x${template`y${(_o: typeof o) => _o.a}`}`)(o) -> 'xyabc'", + template(template`x${template`y${(_o: typeof o) => _o.a}`}`)(o) ) }) describe("interop nested functions", () => { - const fn = a => b => c => d => e => f => f.a + const fn = () => () => () => () => () => (f: typeof o) => f.a const o = {a: "abc"} _("template`${fn}`(o) -> 'abc'", template`${fn}`(o)) }) @@ -88,8 +88,10 @@ describe("template", () => { describe("object can have non string values", () => { const data = {a: 1, b: NaN, c: undefined, d: null, e: false, f: true} - const tx = template`a:${o => o.a}|b:${o => o.b}|c:${o => o.c}|d:${o => - o.d}|e:${o => o.e}|f:${o => o.f}` + const tx = template`a:${(o: typeof data) => o.a}|b:${(o: typeof data) => + o.b}|c:${(o: typeof data) => o.c}|d:${(o: typeof data) => o.d}|e:${( + o: typeof data + ) => o.e}|f:${(o: typeof data) => o.f}` _("template(data)", tx(data), "a:1|b:NaN|c:undefined|d:null|e:false|f:true") }) }) diff --git a/packages/util-template/src/template.ts b/packages/util-template/src/template.ts new file mode 100644 index 000000000..e2a68ae2e --- /dev/null +++ b/packages/util-template/src/template.ts @@ -0,0 +1,67 @@ +import {log} from "@onflow/util-logger" + +/** + * Interleaves two arrays + * @param a - The first array + * @param b - The second array + * @param c - The target array + * @returns The interleaved array + */ +export function interleave( + a: A[] = [], + b: B[] = [], + c: (A | B)[] = [] +): (A | B)[] { + if (!a.length && !b.length) return c + if (!a.length) return c + if (!b.length) { + c.push(...a) + return c + } + + const [aHead, ...aRest] = a + const [bHead, ...bRest] = b + + if (aHead !== undefined) c.push(aHead) + if (bHead !== undefined) c.push(bHead) + + return interleave(aRest, bRest, c) +} + +/** + * Recursively apply a value to a function + * @param d - The value to apply + * @returns A function that takes a function and applies the value to it + */ +function recApply(d: T): (x: U) => string { + return function (arg1) { + if (typeof arg1 === "function") { + log.deprecate({ + pkg: "FCL/SDK", + subject: "Interopolation of functions into template literals", + transition: + "https://github.com/onflow/flow-js-sdk/blob/master/packages/sdk/TRANSITIONS.md#0001-deprecate-params", + }) + return recApply(d)(arg1(d)) + } + return String(arg1) + } +} + +/** + * Creates a template function + * @param head - A string, template string array, or template function + * @param rest - The rest of the arguments + * @returns A template function + */ +export function template( + head: string | TemplateStringsArray | ((x?: unknown) => string), + ...rest: unknown[] +): (x?: unknown) => string { + if (typeof head === "string") return () => head + if (typeof head === "function") return head + return (x: unknown) => + interleave([...head], rest.map(recApply(x))) + .join("") + .trim() +} diff --git a/packages/util-template/tsconfig.json b/packages/util-template/tsconfig.json new file mode 100644 index 000000000..4ec7af1fd --- /dev/null +++ b/packages/util-template/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig", + // Change this to match your project + "include": ["src/**/*"], + "compilerOptions": { + // Types should go into this directory. + // Removing this would place the .d.ts files + // next to the .js files + "outDir": "types" + }, + "exclude": ["src/__snapshots__"] +} diff --git a/packages/util-uid/.babelrc b/packages/util-uid/.babelrc index 67fc2886b..d766c90b2 100644 --- a/packages/util-uid/.babelrc +++ b/packages/util-uid/.babelrc @@ -1,7 +1,3 @@ { - "presets": [ - [ - "@babel/preset-env" - ] - ] + "presets": [["@babel/preset-env"], "@babel/preset-typescript"] } diff --git a/packages/util-uid/.eslintrc.json b/packages/util-uid/.eslintrc.json new file mode 100644 index 000000000..e80c057f5 --- /dev/null +++ b/packages/util-uid/.eslintrc.json @@ -0,0 +1,20 @@ +{ + "env": { + "browser": true, + "es2021": true, + "jest": true, + "node": true + }, + "extends": [ + "plugin:jsdoc/recommended-typescript", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended" + ], + "plugins": ["jsdoc", "@typescript-eslint"], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": "latest", + "sourceType": "module" + }, + "ignorePatterns": ["**/dist/"] +} diff --git a/packages/util-uid/package.json b/packages/util-uid/package.json index bd6fb3856..8d637b79e 100644 --- a/packages/util-uid/package.json +++ b/packages/util-uid/package.json @@ -1,6 +1,6 @@ { "name": "@onflow/util-uid", - "version": "1.1.0", + "version": "1.2.0-typescript.0", "description": "Utilities to generate Unique Identifiers", "license": "Apache-2.0", "author": "Dapper Labs ", @@ -13,13 +13,20 @@ "url": "https://github.com/onflow/flow-js-sdk/issues" }, "devDependencies": { - "@onflow/fcl-bundle": "^1.3.1-alpha.0", + "@babel/preset-typescript": "^7.22.5", + "@onflow/fcl-bundle": "^1.4.0-typescript.0", + "@types/jest": "^29.5.3", + "@typescript-eslint/eslint-plugin": "^6.4.0", + "@typescript-eslint/parser": "^6.4.0", + "eslint": "^8.47.0", + "eslint-plugin-jsdoc": "^46.4.6", "jest": "^29.5.0" }, - "source": "src/util-uid.js", + "source": "src/util-uid.ts", "main": "dist/util-uid.js", "module": "dist/util-uid.module.js", "unpkg": "dist/util-uid.umd.js", + "types": "dist/util-uid.d.ts", "scripts": { "prepublishOnly": "npm test && npm run build", "test": "jest", diff --git a/packages/util-uid/src/util-uid.js b/packages/util-uid/src/util-uid.js deleted file mode 100644 index 878d61dd8..000000000 --- a/packages/util-uid/src/util-uid.js +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Generates a unique identifier - * @returns {string} - */ -var HEX = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" -var T = HEX.length - -export function uid() { - var str = "", - num = 32 - while (num--) str += HEX[(Math.random() * T) | 0] - return str -} diff --git a/packages/util-uid/src/util-uid.test.js b/packages/util-uid/src/util-uid.test.js deleted file mode 100644 index 0fbcb9ae6..000000000 --- a/packages/util-uid/src/util-uid.test.js +++ /dev/null @@ -1,5 +0,0 @@ -import {uid} from "./util-uid.js" - -test("placeholder", () => { - expect(uid()).not.toBe(1) -}) diff --git a/packages/util-uid/src/util-uid.test.ts b/packages/util-uid/src/util-uid.test.ts new file mode 100644 index 000000000..637cbe4f6 --- /dev/null +++ b/packages/util-uid/src/util-uid.test.ts @@ -0,0 +1,12 @@ +import {uid} from "./util-uid" + +test("it should generate a unique 32 character alphanumeric string", () => { + const set = new Set() + for (let i = 0; i < 1000; i++) { + const id = uid() + expect(id).toMatch(/^[a-zA-Z0-9]{32}$/) + expect(set.has(id)).toBe(false) + set.add(id) + } + expect(set.size).toBe(1000) +}) diff --git a/packages/util-uid/src/util-uid.ts b/packages/util-uid/src/util-uid.ts new file mode 100644 index 000000000..651251ef7 --- /dev/null +++ b/packages/util-uid/src/util-uid.ts @@ -0,0 +1,13 @@ +const HEX = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" +const T = HEX.length + +/** + * Generates a random unique identifier + * @returns 32 character alphanumeric string + */ +export function uid(): string { + let str = "", + num = 32 + while (num--) str += HEX[(Math.random() * T) | 0] + return str +} diff --git a/packages/util-uid/tsconfig.json b/packages/util-uid/tsconfig.json new file mode 100644 index 000000000..88be905eb --- /dev/null +++ b/packages/util-uid/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig", + // Change this to match your project + "include": ["src/**/*"], + "compilerOptions": { + // Types should go into this directory. + // Removing this would place the .d.ts files + // next to the .js files + "outDir": "types", + } +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..244c48d2e --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,21 @@ +{ + // Change this to match your project + "exclude": ["**/*.test.ts", "**/*.test.js"], + "compilerOptions": { + "moduleResolution": "NodeNext", + "target": "ES2015", + "types": ["node", "jest"], + // Tells TypeScript to read JS files, as + // normally they are ignored as source files + "allowJs": true, + // Generate d.ts files + "declaration": true, + // This compiler run should + // only output d.ts files + "emitDeclarationOnly": true, + // go to js file when using IDE functions like + // "Go to Definition" in VSCode + "declarationMap": false, + "strict": true + } +}