Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5cea8436c1 | ||
|
|
dac8fa7d98 | ||
|
|
7a6534d1a9 | ||
|
|
d5aee62bf4 | ||
|
|
0bfdedd4ba | ||
|
|
c5761b99e9 | ||
|
|
42d9ab68d9 | ||
|
|
fd0650dcac | ||
|
|
ddb3dabe69 | ||
|
|
b96a228273 | ||
|
|
781e26d896 | ||
|
|
f7392138ee | ||
|
|
5eb6fc1bf3 | ||
|
|
7dc685bbec | ||
|
|
4915ac50f8 | ||
|
|
d724ad85c5 |
@@ -1,5 +1,12 @@
|
||||
# @thirdweb-dev/auth
|
||||
|
||||
## 3.2.16
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`c5761b99`](https://github.com/thirdweb-dev/js/commit/c5761b99e9797772481506e90cbfa5c35a05bd1d), [`b96a2282`](https://github.com/thirdweb-dev/js/commit/b96a2282730582b684cc96802649a96851af5220)]:
|
||||
- @thirdweb-dev/wallets@1.0.12
|
||||
|
||||
## 3.2.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/auth",
|
||||
"version": "3.2.15",
|
||||
"version": "3.2.16",
|
||||
"main": "dist/thirdweb-dev-auth.cjs.js",
|
||||
"module": "dist/thirdweb-dev-auth.esm.js",
|
||||
"browser": {
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"name": "Kroma Sepolia",
|
||||
"title": "Kroma Testnet Sepolia",
|
||||
"chainId": 2358,
|
||||
"shortName": "kroma-sepolia",
|
||||
"chain": "ETH",
|
||||
"networkId": 2358,
|
||||
"nativeCurrency": {
|
||||
"name": "Sepolia Ether",
|
||||
"symbol": "ETH",
|
||||
"decimals": 18
|
||||
},
|
||||
"rpc": [
|
||||
"https://kroma-sepolia.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://api.sepolia.kroma.network"
|
||||
],
|
||||
"faucets": [],
|
||||
"infoURL": "https://kroma.network",
|
||||
"icon": {
|
||||
"url": "ipfs://QmcYafk2je5rMqgnFPDZJTaLi6dgFgq96vmX2Li6DX441B",
|
||||
"width": 320,
|
||||
"height": 320,
|
||||
"format": "svg"
|
||||
},
|
||||
"explorers": [
|
||||
{
|
||||
"name": "blockscout",
|
||||
"url": "https://blockscout.sepolia.kroma.network",
|
||||
"icon": {
|
||||
"url": "ipfs://QmcYafk2je5rMqgnFPDZJTaLi6dgFgq96vmX2Li6DX441B",
|
||||
"width": 320,
|
||||
"height": 320,
|
||||
"format": "svg"
|
||||
},
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
"parent": {
|
||||
"type": "L2",
|
||||
"chain": "eip155-11155111",
|
||||
"bridges": [
|
||||
{
|
||||
"url": "https://kroma.network/bridge"
|
||||
}
|
||||
]
|
||||
},
|
||||
"testnet": true,
|
||||
"slug": "kroma-sepolia"
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,36 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"name": "EgonCoin Mainnet",
|
||||
"chain": "EGON",
|
||||
"icon": {
|
||||
"url": "ipfs://QmNZiMmzMQYjyGtNSghtzLg4UooYhDgMQsa677DAP5KsBg",
|
||||
"width": 512,
|
||||
"height": 512,
|
||||
"format": "png"
|
||||
},
|
||||
"rpc": [
|
||||
"https://egoncoin.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://rpc.egcscan.com"
|
||||
],
|
||||
"faucets": [
|
||||
"https://faucet.egcscan.com"
|
||||
],
|
||||
"nativeCurrency": {
|
||||
"name": "EgonCoin",
|
||||
"symbol": "EGON",
|
||||
"decimals": 18
|
||||
},
|
||||
"infoURL": "https://egcscan.com",
|
||||
"shortName": "EGONm",
|
||||
"chainId": 271,
|
||||
"networkId": 271,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "EgonCoin Mainnet",
|
||||
"url": "https://egcscan.com",
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
"testnet": false,
|
||||
"slug": "egoncoin"
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,36 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"name": "EgonCoin Testnet",
|
||||
"chain": "EGON",
|
||||
"icon": {
|
||||
"url": "ipfs://QmNZiMmzMQYjyGtNSghtzLg4UooYhDgMQsa677DAP5KsBg",
|
||||
"width": 512,
|
||||
"height": 512,
|
||||
"format": "png"
|
||||
},
|
||||
"rpc": [
|
||||
"https://egoncoin-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://rpctest.egcscan.com"
|
||||
],
|
||||
"faucets": [
|
||||
"https://faucet.egcscan.com"
|
||||
],
|
||||
"nativeCurrency": {
|
||||
"name": "EgonCoin",
|
||||
"symbol": "EGON",
|
||||
"decimals": 18
|
||||
},
|
||||
"infoURL": "https://egcscan.com",
|
||||
"shortName": "EGONt",
|
||||
"chainId": 271271,
|
||||
"networkId": 271271,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "EgonCoin Testnet",
|
||||
"url": "https://testnet.egcscan.com",
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
"testnet": true,
|
||||
"slug": "egoncoin-testnet"
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,36 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"name": "SenjePowers Mainnet",
|
||||
"chain": "SPC",
|
||||
"icon": {
|
||||
"url": "ipfs://QmcpyTj4hUyHJZ2VmSdkXFpPpRcNKRP1VxMs7Cp1anymNy",
|
||||
"width": 504,
|
||||
"height": 495,
|
||||
"format": "png"
|
||||
},
|
||||
"rpc": [
|
||||
"https://senjepowers.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://rpc.senjepowersscan.com"
|
||||
],
|
||||
"faucets": [
|
||||
"https://faucet.senjepowersscan.com"
|
||||
],
|
||||
"nativeCurrency": {
|
||||
"name": "SenjePowers",
|
||||
"symbol": "SPC",
|
||||
"decimals": 18
|
||||
},
|
||||
"infoURL": "https://senjepowersscan.com",
|
||||
"shortName": "SPCm",
|
||||
"chainId": 3699,
|
||||
"networkId": 3699,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "SenjePowers",
|
||||
"url": "https://senjepowersscan.com",
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
"testnet": false,
|
||||
"slug": "senjepowers"
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,37 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"name": "Toronet Testnet",
|
||||
"chain": "Toronet",
|
||||
"icon": {
|
||||
"url": "ipfs://QmciSvgLatP6jhgdazuiyD3fSrhipfAN7wC943v1qxcrpv",
|
||||
"width": 846,
|
||||
"height": 733,
|
||||
"format": "png"
|
||||
},
|
||||
"rpc": [
|
||||
"https://toronet-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"http://testnet.toronet.org/rpc"
|
||||
],
|
||||
"faucets": [],
|
||||
"nativeCurrency": {
|
||||
"name": "Toro",
|
||||
"symbol": "TORO",
|
||||
"decimals": 18
|
||||
},
|
||||
"infoURL": "https://toronet.org",
|
||||
"shortName": "ToronetTestnet",
|
||||
"chainId": 54321,
|
||||
"networkId": 54321,
|
||||
"ens": {
|
||||
"registry": "0x059C474f26D65B0458F9da10A649a7322aB02C09"
|
||||
},
|
||||
"explorers": [
|
||||
{
|
||||
"name": "toronet_explorer",
|
||||
"url": "https://testnet.toronet.org",
|
||||
"standard": "none"
|
||||
}
|
||||
],
|
||||
"testnet": true,
|
||||
"slug": "toronet-testnet"
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,34 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"name": "Bitrock Mainnet",
|
||||
"chain": "Bitrock",
|
||||
"icon": {
|
||||
"url": "ipfs://QmfXZCAh3HWS2bJroUStN9TieL4QA9QArMotie3X4pwBfj",
|
||||
"width": 72,
|
||||
"height": 72,
|
||||
"format": "svg"
|
||||
},
|
||||
"rpc": [
|
||||
"https://bitrock.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://connect.bit-rock.io"
|
||||
],
|
||||
"faucets": [],
|
||||
"nativeCurrency": {
|
||||
"name": "BITROCK",
|
||||
"symbol": "BROCK",
|
||||
"decimals": 18
|
||||
},
|
||||
"infoURL": "https://bit-rock.io",
|
||||
"shortName": "bitrock",
|
||||
"chainId": 7171,
|
||||
"networkId": 7171,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "Bitrock Explorer",
|
||||
"url": "https://scan.bit-rock.io",
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
"testnet": false,
|
||||
"slug": "bitrock"
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,36 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"name": "Bitrock Testnet",
|
||||
"chain": "Bitrock",
|
||||
"icon": {
|
||||
"url": "ipfs://QmfXZCAh3HWS2bJroUStN9TieL4QA9QArMotie3X4pwBfj",
|
||||
"width": 72,
|
||||
"height": 72,
|
||||
"format": "svg"
|
||||
},
|
||||
"rpc": [
|
||||
"https://bitrock-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://testnet.bit-rock.io"
|
||||
],
|
||||
"faucets": [
|
||||
"https://faucet.bit-rock.io"
|
||||
],
|
||||
"nativeCurrency": {
|
||||
"name": "BITROCK",
|
||||
"symbol": "BROCK",
|
||||
"decimals": 18
|
||||
},
|
||||
"infoURL": "https://bit-rock.io",
|
||||
"shortName": "tbitrock",
|
||||
"chainId": 7771,
|
||||
"networkId": 7771,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "Bitrock Testnet Explorer",
|
||||
"url": "https://testnetscan.bit-rock.io",
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
"testnet": true,
|
||||
"slug": "bitrock-testnet"
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,37 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"name": "Toronet Mainnet",
|
||||
"chain": "Toronet",
|
||||
"icon": {
|
||||
"url": "ipfs://QmciSvgLatP6jhgdazuiyD3fSrhipfAN7wC943v1qxcrpv",
|
||||
"width": 846,
|
||||
"height": 733,
|
||||
"format": "png"
|
||||
},
|
||||
"rpc": [
|
||||
"https://toronet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"http://toronet.org/rpc"
|
||||
],
|
||||
"faucets": [],
|
||||
"nativeCurrency": {
|
||||
"name": "Toro",
|
||||
"symbol": "TORO",
|
||||
"decimals": 18
|
||||
},
|
||||
"infoURL": "https://toronet.org",
|
||||
"shortName": "Toronet",
|
||||
"chainId": 77777,
|
||||
"networkId": 77777,
|
||||
"ens": {
|
||||
"registry": "0x1f45a71f4aAD769E27c969c4359E0e250C67165c"
|
||||
},
|
||||
"explorers": [
|
||||
{
|
||||
"name": "toronet_explorer",
|
||||
"url": "https://toronet.org/explorer",
|
||||
"standard": "none"
|
||||
}
|
||||
],
|
||||
"testnet": false,
|
||||
"slug": "toronet"
|
||||
} as const satisfies Chain;
|
||||
@@ -1,5 +1,12 @@
|
||||
# thirdweb
|
||||
|
||||
## 0.10.37
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`dac8fa7d`](https://github.com/thirdweb-dev/js/commit/dac8fa7d98b6952acf8d13e173099889c1d47da8)]:
|
||||
- @thirdweb-dev/sdk@3.10.36
|
||||
|
||||
## 0.10.36
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "thirdweb",
|
||||
"main": "dist/cli/index.js",
|
||||
"version": "0.10.36",
|
||||
"version": "0.10.37",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/cli",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# @thirdweb-dev/react-core
|
||||
|
||||
## 3.14.16
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1356](https://github.com/thirdweb-dev/js/pull/1356) [`7a6534d1`](https://github.com/thirdweb-dev/js/commit/7a6534d1a98cab1eb47cf88d13e2b7ec04037e42) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Fix useOwnedNFT enabled state
|
||||
|
||||
- Updated dependencies [[`dac8fa7d`](https://github.com/thirdweb-dev/js/commit/dac8fa7d98b6952acf8d13e173099889c1d47da8), [`c5761b99`](https://github.com/thirdweb-dev/js/commit/c5761b99e9797772481506e90cbfa5c35a05bd1d), [`b96a2282`](https://github.com/thirdweb-dev/js/commit/b96a2282730582b684cc96802649a96851af5220)]:
|
||||
- @thirdweb-dev/sdk@3.10.36
|
||||
- @thirdweb-dev/wallets@1.0.12
|
||||
|
||||
## 3.14.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react-core",
|
||||
"version": "3.14.15",
|
||||
"version": "3.14.16",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-core",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -256,7 +256,7 @@ export function useOwnedNFTs<TContract extends NFTContract>(
|
||||
invariant(false, "Unknown NFT type");
|
||||
},
|
||||
{
|
||||
enabled: !!erc721 || (!!erc1155 && !!ownerWalletAddress),
|
||||
enabled: (!!erc721 || !!erc1155) && !!ownerWalletAddress,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# @thirdweb-dev/react-native-compat
|
||||
|
||||
## 0.2.35
|
||||
|
||||
## 0.2.34
|
||||
|
||||
## 0.2.33
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react-native-compat",
|
||||
"description": "Shims for Thirdweb in React Native Projects",
|
||||
"version": "0.2.34",
|
||||
"version": "0.2.35",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-native-compat",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# @thirdweb-dev/react-native
|
||||
|
||||
## 0.2.35
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`7a6534d1`](https://github.com/thirdweb-dev/js/commit/7a6534d1a98cab1eb47cf88d13e2b7ec04037e42), [`dac8fa7d`](https://github.com/thirdweb-dev/js/commit/dac8fa7d98b6952acf8d13e173099889c1d47da8), [`c5761b99`](https://github.com/thirdweb-dev/js/commit/c5761b99e9797772481506e90cbfa5c35a05bd1d), [`b96a2282`](https://github.com/thirdweb-dev/js/commit/b96a2282730582b684cc96802649a96851af5220)]:
|
||||
- @thirdweb-dev/react-core@3.14.16
|
||||
- @thirdweb-dev/sdk@3.10.36
|
||||
- @thirdweb-dev/wallets@1.0.12
|
||||
|
||||
## 0.2.34
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react-native",
|
||||
"version": "0.2.34",
|
||||
"version": "0.2.35",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-native",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
# @thirdweb-dev/react
|
||||
|
||||
## 3.14.16
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1350](https://github.com/thirdweb-dev/js/pull/1350) [`b96a2282`](https://github.com/thirdweb-dev/js/commit/b96a2282730582b684cc96802649a96851af5220) Thanks [@MananTank](https://github.com/MananTank)! - Disable autofocus for the Paper/Magic email/phone input in Connect Wallet Modal to avoid keyboard popup on mobile
|
||||
|
||||
- Updated dependencies [[`7a6534d1`](https://github.com/thirdweb-dev/js/commit/7a6534d1a98cab1eb47cf88d13e2b7ec04037e42), [`dac8fa7d`](https://github.com/thirdweb-dev/js/commit/dac8fa7d98b6952acf8d13e173099889c1d47da8), [`c5761b99`](https://github.com/thirdweb-dev/js/commit/c5761b99e9797772481506e90cbfa5c35a05bd1d), [`b96a2282`](https://github.com/thirdweb-dev/js/commit/b96a2282730582b684cc96802649a96851af5220)]:
|
||||
- @thirdweb-dev/react-core@3.14.16
|
||||
- @thirdweb-dev/sdk@3.10.36
|
||||
- @thirdweb-dev/wallets@1.0.12
|
||||
|
||||
## 3.14.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react",
|
||||
"version": "3.14.15",
|
||||
"version": "3.14.16",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -43,6 +43,7 @@ export function InputSelectionUI(props: {
|
||||
}}
|
||||
>
|
||||
<Input
|
||||
tabIndex={-1}
|
||||
placeholder={props.placeholder}
|
||||
variant="secondary"
|
||||
type={props.type}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import type { WalletOptions, WalletConfig } from "@thirdweb-dev/react-core";
|
||||
import { MetaMaskWallet, assertWindowEthereum } from "@thirdweb-dev/wallets";
|
||||
import {
|
||||
MetaMaskWallet,
|
||||
getInjectedMetamaskProvider,
|
||||
} from "@thirdweb-dev/wallets";
|
||||
import { MetamaskConnectUI } from "./MetamaskConnectUI";
|
||||
|
||||
type MetamaskWalletOptions = {
|
||||
@@ -27,10 +30,7 @@ export const metamaskWallet = (
|
||||
},
|
||||
connectUI: MetamaskConnectUI,
|
||||
isInstalled() {
|
||||
if (assertWindowEthereum(globalThis.window)) {
|
||||
return globalThis.window.ethereum.isMetaMask;
|
||||
}
|
||||
return false;
|
||||
return !!getInjectedMetamaskProvider();
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @thirdweb-dev/sdk
|
||||
|
||||
## 3.10.36
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1357](https://github.com/thirdweb-dev/js/pull/1357) [`dac8fa7d`](https://github.com/thirdweb-dev/js/commit/dac8fa7d98b6952acf8d13e173099889c1d47da8) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Fix getOwned not showing last owned NFT for OpenEdition contracts
|
||||
|
||||
## 3.10.35
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/sdk",
|
||||
"version": "3.10.35",
|
||||
"version": "3.10.36",
|
||||
"description": "The main thirdweb SDK.",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/sdk",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -87,12 +87,18 @@ export class Erc721Supply implements DetectableFeature {
|
||||
*/
|
||||
public async allOwners() {
|
||||
let totalCount: BigNumber;
|
||||
let startTokenId = BigNumber.from(0);
|
||||
if (hasFunction<OpenEditionERC721>("startTokenId", this.contractWrapper)) {
|
||||
startTokenId = await this.contractWrapper.readContract.startTokenId();
|
||||
}
|
||||
try {
|
||||
totalCount = await this.erc721.totalClaimedSupply();
|
||||
} catch (e) {
|
||||
totalCount = await this.totalCount();
|
||||
}
|
||||
|
||||
totalCount = totalCount.add(startTokenId);
|
||||
|
||||
// TODO use multicall3 if available
|
||||
// TODO can't call toNumber() here, this can be a very large number
|
||||
return (
|
||||
|
||||
@@ -1,5 +1,33 @@
|
||||
# @thirdweb-dev/service-utils
|
||||
|
||||
## 0.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#1345](https://github.com/thirdweb-dev/js/pull/1345) [`5eb6fc1b`](https://github.com/thirdweb-dev/js/commit/5eb6fc1bf309a34167bf1f27fe5b09a3ae781219) Thanks [@jnsdls](https://github.com/jnsdls)! - expose separate entrypoints for cloudflare workers and node projects
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1342](https://github.com/thirdweb-dev/js/pull/1342) [`4915ac50`](https://github.com/thirdweb-dev/js/commit/4915ac50f8ffd90cd965636905f73d1c99cbda29) Thanks [@jnsdls](https://github.com/jnsdls)! - add relayer service definition
|
||||
|
||||
- [#1340](https://github.com/thirdweb-dev/js/pull/1340) [`d724ad85`](https://github.com/thirdweb-dev/js/commit/d724ad85c52f6da341a248fbe62d85a99c1b65d0) Thanks [@jnsdls](https://github.com/jnsdls)! - fix use endpoint
|
||||
|
||||
- [#1354](https://github.com/thirdweb-dev/js/pull/1354) [`0bfdedd4`](https://github.com/thirdweb-dev/js/commit/0bfdedd4ba6ce9b42f9636303027b4421eb68d65) Thanks [@assimovt](https://github.com/assimovt)! - Fix enforceAuth param
|
||||
|
||||
- [#1355](https://github.com/thirdweb-dev/js/pull/1355) [`d5aee62b`](https://github.com/thirdweb-dev/js/commit/d5aee62bf41e45b5fed3061d4338d4a279a27c38) Thanks [@assimovt](https://github.com/assimovt)! - Remove unused type
|
||||
|
||||
- [#1349](https://github.com/thirdweb-dev/js/pull/1349) [`ddb3dabe`](https://github.com/thirdweb-dev/js/commit/ddb3dabe694be96d2de4c01c53d8c6fc6b9e211d) Thanks [@assimovt](https://github.com/assimovt)! - Allow target addresses array and fix api url stringy
|
||||
|
||||
- [#1351](https://github.com/thirdweb-dev/js/pull/1351) [`fd0650dc`](https://github.com/thirdweb-dev/js/commit/fd0650dcacfa6bf4a3fa479934046957eef8cf94) Thanks [@farhanW3](https://github.com/farhanW3)! - Fixed Node Service Url formation
|
||||
|
||||
- [#1353](https://github.com/thirdweb-dev/js/pull/1353) [`42d9ab68`](https://github.com/thirdweb-dev/js/commit/42d9ab68d949bc6788f628042d916a1c5e660b16) Thanks [@assimovt](https://github.com/assimovt)! - Allow to skip auth for backwards compat
|
||||
|
||||
- [#1347](https://github.com/thirdweb-dev/js/pull/1347) [`781e26d8`](https://github.com/thirdweb-dev/js/commit/781e26d89632ef421bec2914d4e3abcc17d96816) Thanks [@assimovt](https://github.com/assimovt)! - Authorize service bundle
|
||||
|
||||
- [#1343](https://github.com/thirdweb-dev/js/pull/1343) [`7dc685bb`](https://github.com/thirdweb-dev/js/commit/7dc685bbece749030e85a9f6d5aafa48d3ab8a74) Thanks [@nessup](https://github.com/nessup)! - Add missing type to ApiKey
|
||||
|
||||
- [#1346](https://github.com/thirdweb-dev/js/pull/1346) [`f7392138`](https://github.com/thirdweb-dev/js/commit/f7392138eeda55a6557b26a6c957d5b6b90b645c) Thanks [@assimovt](https://github.com/assimovt)! - fix api url extraction from URL in fetchKeyMetadataFromApi
|
||||
|
||||
## 0.1.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"main": "dist/thirdweb-dev-service-utils-cf-worker.cjs.js",
|
||||
"module": "dist/thirdweb-dev-service-utils-cf-worker.esm.js"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"main": "dist/thirdweb-dev-service-utils-node.cjs.js",
|
||||
"module": "dist/thirdweb-dev-service-utils-node.esm.js"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/service-utils",
|
||||
"version": "0.1.0",
|
||||
"version": "0.2.0",
|
||||
"main": "dist/thirdweb-dev-service-utils.cjs.js",
|
||||
"module": "dist/thirdweb-dev-service-utils.esm.js",
|
||||
"exports": {
|
||||
@@ -8,6 +8,14 @@
|
||||
"module": "./dist/thirdweb-dev-service-utils.esm.js",
|
||||
"default": "./dist/thirdweb-dev-service-utils.cjs.js"
|
||||
},
|
||||
"./node": {
|
||||
"module": "./node/dist/thirdweb-dev-service-utils-node.esm.js",
|
||||
"default": "./node/dist/thirdweb-dev-service-utils-node.cjs.js"
|
||||
},
|
||||
"./cf-worker": {
|
||||
"module": "./cf-worker/dist/thirdweb-dev-service-utils-cf-worker.esm.js",
|
||||
"default": "./cf-worker/dist/thirdweb-dev-service-utils-cf-worker.cjs.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/pay",
|
||||
@@ -17,29 +25,32 @@
|
||||
},
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"files": [
|
||||
"dist/"
|
||||
"dist/",
|
||||
"node/",
|
||||
"cf-worker/"
|
||||
],
|
||||
"preconstruct": {
|
||||
"entrypoints": [
|
||||
"index.ts"
|
||||
"index.ts",
|
||||
"cf-worker/index.ts",
|
||||
"node/index.ts"
|
||||
],
|
||||
"exports": true
|
||||
},
|
||||
"sideEffects": false,
|
||||
"devDependencies": {
|
||||
"@cloudflare/workers-types": "^4.20230710.0",
|
||||
"@preconstruct/cli": "^2.8.1",
|
||||
"@thirdweb-dev/tsconfig": "workspace:*",
|
||||
"@types/jest": "^29.5.2",
|
||||
"@types/node": "^20.4.1",
|
||||
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
||||
"@typescript-eslint/parser": "^6.0.0",
|
||||
"eslint": "^8.44.0",
|
||||
"eslint-config-prettier": "^8.8.0",
|
||||
"lint-staged": "^13.2.3",
|
||||
"prettier": "^3.0.0",
|
||||
"sort-package-json": "^2.5.1",
|
||||
"ts-node": "^10.9.1",
|
||||
"@preconstruct/cli": "^2.7.0",
|
||||
"@thirdweb-dev/tsconfig": "workspace:*",
|
||||
"eslint-config-thirdweb": "workspace:*",
|
||||
"jest": "^29.4.3",
|
||||
"prettier": "^3.0.0",
|
||||
"typescript": "^5.1.6"
|
||||
},
|
||||
"scripts": {
|
||||
@@ -48,6 +59,7 @@
|
||||
"fix": "eslint src/ --fix",
|
||||
"clean": "rm -rf dist/",
|
||||
"build": "tsc && preconstruct build",
|
||||
"push": "yalc push"
|
||||
"push": "yalc push",
|
||||
"test": "jest"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,253 +0,0 @@
|
||||
import {
|
||||
ApiKey,
|
||||
ApiResponse,
|
||||
ServiceConfiguration,
|
||||
AuthorizationResponse,
|
||||
AuthorizationValidations,
|
||||
AuthorizeCFWorkerOptions,
|
||||
AuthorizeNodeServiceOptions,
|
||||
AuthOptions,
|
||||
} from "./types";
|
||||
|
||||
export async function authorizeCFWorkerService(
|
||||
options: AuthorizeCFWorkerOptions,
|
||||
) {
|
||||
const { kvStore, ctx, authOptions, serviceConfig, validations } = options;
|
||||
const { clientId } = authOptions;
|
||||
|
||||
let cachedKey;
|
||||
|
||||
// first, check if the key is in KV
|
||||
try {
|
||||
const kvKey = await kvStore.get(clientId);
|
||||
if (kvKey) {
|
||||
cachedKey = JSON.parse(kvKey) as ApiKey;
|
||||
}
|
||||
} catch (err) {
|
||||
// ignore JSON parse, assuming not valid
|
||||
}
|
||||
|
||||
const updateKv = async (keyData: ApiKey) => {
|
||||
kvStore.put(clientId as string, JSON.stringify(keyData), {
|
||||
expirationTtl: serviceConfig.cacheTtl || 60,
|
||||
});
|
||||
};
|
||||
|
||||
return authorize({
|
||||
authOptions,
|
||||
serviceConfig: {
|
||||
...serviceConfig,
|
||||
cachedKey,
|
||||
onRefetchComplete: (keyData: ApiKey) => {
|
||||
ctx.waitUntil(updateKv(keyData));
|
||||
},
|
||||
},
|
||||
validations,
|
||||
});
|
||||
}
|
||||
|
||||
export async function authorizeNodeService(
|
||||
options: AuthorizeNodeServiceOptions,
|
||||
) {
|
||||
const { authOptions, serviceConfig, validations } = options;
|
||||
|
||||
return authorize({
|
||||
authOptions,
|
||||
serviceConfig,
|
||||
validations,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Authorizes a request for a given client ID
|
||||
*
|
||||
* @returns The Promise AuthorizationResponse
|
||||
*/
|
||||
async function authorize(options: {
|
||||
authOptions: AuthOptions;
|
||||
serviceConfig: ServiceConfiguration;
|
||||
validations: AuthorizationValidations;
|
||||
}): Promise<AuthorizationResponse> {
|
||||
try {
|
||||
const { authOptions, serviceConfig, validations } = options;
|
||||
const { clientId } = authOptions;
|
||||
const { apiUrl, scope, serviceKey, cachedKey, onRefetchComplete } =
|
||||
serviceConfig;
|
||||
|
||||
let keyData = cachedKey;
|
||||
|
||||
// no cached key, re-fetch from API
|
||||
if (!keyData) {
|
||||
const response = await fetch(
|
||||
`${apiUrl}/v1/keys/use/?scope=${scope}&clientId=${clientId}`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"x-service-api-key": serviceKey,
|
||||
"content-type": "application/json",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const apiResponse = (await response.json()) as ApiResponse;
|
||||
|
||||
if (!response.ok) {
|
||||
const { error } = apiResponse;
|
||||
|
||||
return {
|
||||
authorized: false,
|
||||
errorMessage: error.message,
|
||||
errorCode: error.code || "",
|
||||
statusCode: error.statusCode || 401,
|
||||
};
|
||||
}
|
||||
|
||||
keyData = apiResponse.data as ApiKey;
|
||||
|
||||
if (onRefetchComplete) {
|
||||
onRefetchComplete(keyData);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Run validations
|
||||
//
|
||||
const authResponse = authAccess(authOptions, keyData);
|
||||
|
||||
if (!authResponse?.authorized) {
|
||||
return authResponse;
|
||||
}
|
||||
|
||||
const authzResponse = authzServices(validations, keyData, scope);
|
||||
|
||||
if (!authzResponse?.authorized) {
|
||||
return authzResponse;
|
||||
}
|
||||
// FIXME: validate bundleId
|
||||
|
||||
return {
|
||||
authorized: true,
|
||||
data: keyData,
|
||||
};
|
||||
} catch (err) {
|
||||
console.error("Failed to authorize this key.", err);
|
||||
|
||||
return {
|
||||
authorized: false,
|
||||
errorMessage: "Internal error",
|
||||
errorCode: "INTERNAL_ERROR",
|
||||
statusCode: 500,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function authAccess(authOptions: AuthOptions, apiKey: ApiKey) {
|
||||
const { origin, secretHash: providedSecretHash } = authOptions;
|
||||
const { domains, secretHash } = apiKey;
|
||||
|
||||
if (providedSecretHash) {
|
||||
if (secretHash !== providedSecretHash) {
|
||||
return {
|
||||
authorized: false,
|
||||
errorMessage: "The secret is invalid.",
|
||||
errorCode: "SECRET_INVALID",
|
||||
statusCode: 401,
|
||||
};
|
||||
}
|
||||
return {
|
||||
authorized: true,
|
||||
};
|
||||
}
|
||||
|
||||
// validate domains
|
||||
if (origin) {
|
||||
if (
|
||||
// find matching domain, or if all domains allowed
|
||||
domains.find((d) => {
|
||||
if (d === "*") {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the allowedDomain has a wildcard,
|
||||
// we'll check that the ending of our domain matches the wildcard
|
||||
if (d.startsWith("*.")) {
|
||||
const domainRoot = d.slice(2);
|
||||
return origin.endsWith(domainRoot);
|
||||
}
|
||||
|
||||
// If there's no wildcard, we'll check for an exact match
|
||||
return d === origin;
|
||||
})
|
||||
) {
|
||||
return {
|
||||
authorized: true,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
authorized: false,
|
||||
errorMessage: "The origin is not authorized for this key.",
|
||||
errorCode: "ORIGIN_UNAUTHORIZED",
|
||||
statusCode: 401,
|
||||
};
|
||||
}
|
||||
|
||||
// FIXME: validate bundle id
|
||||
return {
|
||||
authorized: false,
|
||||
errorMessage: "The keys are invalid.",
|
||||
errorCode: "UNAUTHORIZED",
|
||||
statusCode: 401,
|
||||
};
|
||||
}
|
||||
|
||||
function authzServices(
|
||||
validations: AuthorizationValidations,
|
||||
apiKey: ApiKey,
|
||||
scope: string,
|
||||
) {
|
||||
const { services } = apiKey;
|
||||
const { serviceTargetAddresses, serviceAction } = validations;
|
||||
|
||||
// validate services
|
||||
const service = services.find((srv) => srv.name === scope);
|
||||
if (!service) {
|
||||
return {
|
||||
authorized: false,
|
||||
errorMessage: `The service "${scope}" is not authorized for this key.`,
|
||||
errorCode: "SERVICE_UNAUTHORIZED",
|
||||
statusCode: 403,
|
||||
};
|
||||
}
|
||||
|
||||
// validate service actions
|
||||
if (serviceAction) {
|
||||
if (!service.actions.includes(serviceAction)) {
|
||||
return {
|
||||
authorized: false,
|
||||
errorMessage: `The service "${scope}" action "${serviceAction}" is not authorized for this key.`,
|
||||
errorCode: "SERVICE_ACTION_UNAUTHORIZED",
|
||||
statusCode: 403,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// validate service target addresses
|
||||
if (
|
||||
serviceTargetAddresses &&
|
||||
!service.targetAddresses.find(
|
||||
(addr) => addr === "*" || serviceTargetAddresses.includes(addr),
|
||||
)
|
||||
) {
|
||||
return {
|
||||
authorized: false,
|
||||
errorMessage: `The service "${scope}" target address is not authorized for this key.`,
|
||||
errorCode: "SERVICE_TARGET_ADDRESS_UNAUTHORIZED",
|
||||
statusCode: 403,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
authorized: true,
|
||||
};
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
import { KVNamespace, ExecutionContext } from "@cloudflare/workers-types";
|
||||
import { ServiceName } from "../types";
|
||||
|
||||
export interface AuthOptions {
|
||||
clientId: string;
|
||||
secretHash?: string;
|
||||
bundleId?: string;
|
||||
origin?: string;
|
||||
}
|
||||
|
||||
export interface AuthorizeCFWorkerOptions {
|
||||
ctx: ExecutionContext;
|
||||
kvStore: KVNamespace<string>;
|
||||
authOptions: AuthOptions;
|
||||
serviceConfig: ServiceConfiguration;
|
||||
validations: AuthorizationValidations;
|
||||
}
|
||||
|
||||
export interface AuthorizeNodeServiceOptions {
|
||||
authOptions: AuthOptions;
|
||||
serviceConfig: ServiceConfiguration;
|
||||
validations: AuthorizationValidations;
|
||||
}
|
||||
|
||||
export interface ServiceConfiguration {
|
||||
apiUrl: string;
|
||||
scope: ServiceName;
|
||||
serviceKey: string;
|
||||
cachedKey?: ApiKey;
|
||||
cacheTtl?: number;
|
||||
onRefetchComplete?: (key: ApiKey) => void;
|
||||
}
|
||||
|
||||
export interface AuthorizationValidations {
|
||||
serviceTargetAddresses?: string[];
|
||||
serviceAction?: string;
|
||||
}
|
||||
|
||||
export interface AuthorizationResponse {
|
||||
authorized: boolean;
|
||||
errorMessage?: string;
|
||||
errorCode?: string;
|
||||
statusCode?: number;
|
||||
data?: ApiKey;
|
||||
}
|
||||
|
||||
export interface ApiResponse {
|
||||
data: ApiKey | null;
|
||||
error: {
|
||||
code: string;
|
||||
statusCode: number;
|
||||
message: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface ApiKey {
|
||||
id: string;
|
||||
key: string;
|
||||
secretHash: string;
|
||||
walletAddresses: string[];
|
||||
domains: string[];
|
||||
bundleIds: string[];
|
||||
services: {
|
||||
name: string;
|
||||
targetAddresses: string[];
|
||||
actions: string[];
|
||||
}[];
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
import type { ExecutionContext, KVNamespace } from "@cloudflare/workers-types";
|
||||
import type { ApiKeyMetadata, CoreServiceConfig } from "../core/api";
|
||||
import { authorize } from "../core/authorize";
|
||||
|
||||
import type { Request } from "@cloudflare/workers-types";
|
||||
import type { AuthorizationInput } from "../core/authorize";
|
||||
import type { AuthorizationResult } from "../core/authorize/types";
|
||||
import type { CoreAuthInput } from "../core/types";
|
||||
|
||||
export * from "../core/services";
|
||||
|
||||
type WorkerServiceConfig = CoreServiceConfig & {
|
||||
kvStore: KVNamespace;
|
||||
ctx: ExecutionContext;
|
||||
cacheTtlSeconds?: number;
|
||||
};
|
||||
|
||||
const DEFAULT_CACHE_TTL_SECONDS = 60;
|
||||
|
||||
type AuthInput = CoreAuthInput & {
|
||||
req: Request;
|
||||
};
|
||||
|
||||
export async function authorizeWorker(
|
||||
authInput: AuthInput,
|
||||
serviceConfig: WorkerServiceConfig,
|
||||
): Promise<AuthorizationResult> {
|
||||
let authData;
|
||||
try {
|
||||
authData = await extractAuthorizationData(authInput);
|
||||
} catch (e) {
|
||||
if (e instanceof Error && e.message === "KEY_CONFLICT") {
|
||||
return {
|
||||
authorized: false,
|
||||
status: 400,
|
||||
errorMessage: "Please pass either a client id or a secret key.",
|
||||
errorCode: "KEY_CONFLICT",
|
||||
};
|
||||
}
|
||||
return {
|
||||
authorized: false,
|
||||
status: 500,
|
||||
errorMessage: "Internal Server Error",
|
||||
errorCode: "INTERNAL_SERVER_ERROR",
|
||||
};
|
||||
}
|
||||
|
||||
return await authorize(authData, serviceConfig, {
|
||||
get: async (clientId: string) => serviceConfig.kvStore.get(clientId),
|
||||
put: (clientId: string, apiKeyMeta: ApiKeyMetadata) =>
|
||||
serviceConfig.ctx.waitUntil(
|
||||
serviceConfig.kvStore.put(
|
||||
clientId,
|
||||
JSON.stringify({
|
||||
updatedAt: Date.now(),
|
||||
apiKeyMeta,
|
||||
}),
|
||||
{
|
||||
expirationTtl:
|
||||
serviceConfig.cacheTtlSeconds &&
|
||||
serviceConfig.cacheTtlSeconds >= DEFAULT_CACHE_TTL_SECONDS
|
||||
? serviceConfig.cacheTtlSeconds
|
||||
: DEFAULT_CACHE_TTL_SECONDS,
|
||||
},
|
||||
),
|
||||
),
|
||||
cacheTtlSeconds: serviceConfig.cacheTtlSeconds ?? DEFAULT_CACHE_TTL_SECONDS,
|
||||
});
|
||||
}
|
||||
|
||||
async function extractAuthorizationData(
|
||||
authInput: AuthInput,
|
||||
): Promise<AuthorizationInput> {
|
||||
const requestUrl = new URL(authInput.req.url);
|
||||
const headers = authInput.req.headers;
|
||||
const secretKey = headers.get("x-secret-key");
|
||||
|
||||
// prefer clientId that is explicitly passed in
|
||||
let clientId = authInput.clientId ?? null;
|
||||
|
||||
if (!clientId) {
|
||||
// next preference is clientId from header
|
||||
clientId = headers.get("x-client-id");
|
||||
}
|
||||
|
||||
// next preference is search param
|
||||
if (!clientId) {
|
||||
clientId = requestUrl.searchParams.get("clientId");
|
||||
}
|
||||
// bundle id from header is first preference
|
||||
let bundleId = headers.get("x-bundle-id");
|
||||
|
||||
// next preference is search param
|
||||
if (!bundleId) {
|
||||
bundleId = requestUrl.searchParams.get("bundleId");
|
||||
}
|
||||
|
||||
let origin = headers.get("origin");
|
||||
// if origin header is not available we'll fall back to referrer;
|
||||
if (!origin) {
|
||||
origin = headers.get("referer");
|
||||
}
|
||||
// if we have an origin at this point, normalize it
|
||||
if (origin) {
|
||||
try {
|
||||
origin = new URL(origin).hostname;
|
||||
} catch (e) {
|
||||
console.warn("failed to parse origin", origin, e);
|
||||
}
|
||||
}
|
||||
|
||||
// handle if we a secret key is passed in the headers
|
||||
let secretKeyHash: string | null = null;
|
||||
if (secretKey) {
|
||||
// hash the secret key
|
||||
secretKeyHash = await hashSecretKey(secretKey);
|
||||
// derive the client id from the secret key hash
|
||||
const derivedClientId = deriveClientIdFromSecretKeyHash(secretKeyHash);
|
||||
// if we already have a client id passed in we need to make sure they match
|
||||
if (clientId && clientId !== derivedClientId) {
|
||||
throw new Error("KEY_CONFLICT");
|
||||
}
|
||||
// otherwise set the client id to the derived client id (client id based off of secret key)
|
||||
clientId = derivedClientId;
|
||||
}
|
||||
|
||||
return {
|
||||
secretKey,
|
||||
clientId,
|
||||
origin,
|
||||
bundleId,
|
||||
secretKeyHash,
|
||||
targetAddress: authInput.targetAddress,
|
||||
};
|
||||
}
|
||||
|
||||
export async function hashSecretKey(secretKey: string) {
|
||||
return bufferToHex(
|
||||
await crypto.subtle.digest("SHA-256", new TextEncoder().encode(secretKey)),
|
||||
);
|
||||
}
|
||||
|
||||
export function deriveClientIdFromSecretKeyHash(secretKeyHash: string) {
|
||||
return secretKeyHash.slice(0, 32);
|
||||
}
|
||||
|
||||
function bufferToHex(buffer: ArrayBuffer) {
|
||||
return [...new Uint8Array(buffer)]
|
||||
.map((x) => x.toString(16).padStart(2, "0"))
|
||||
.join("");
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import type { ServiceName } from "./services";
|
||||
|
||||
export type CoreServiceConfig = {
|
||||
enforceAuth: boolean;
|
||||
apiUrl: string;
|
||||
serviceScope: ServiceName;
|
||||
serviceApiKey: string;
|
||||
serviceAction?: string;
|
||||
};
|
||||
|
||||
export type ApiKeyMetadata = {
|
||||
id: string;
|
||||
key: string;
|
||||
creatorWalletAddress: string;
|
||||
secretHash: string;
|
||||
walletAddresses: string[];
|
||||
domains: string[];
|
||||
bundleIds: string[];
|
||||
services: {
|
||||
name: string;
|
||||
targetAddresses: string[];
|
||||
actions: string[];
|
||||
}[];
|
||||
};
|
||||
|
||||
export type ApiResponse = {
|
||||
data: ApiKeyMetadata | null;
|
||||
error: {
|
||||
code: string;
|
||||
statusCode: number;
|
||||
message: string;
|
||||
};
|
||||
};
|
||||
|
||||
export async function fetchKeyMetadataFromApi(
|
||||
clientId: string,
|
||||
config: CoreServiceConfig,
|
||||
): Promise<ApiResponse> {
|
||||
const { apiUrl, serviceScope, serviceApiKey } = config;
|
||||
const url = `${apiUrl}/v1/keys/use?clientId=${clientId}&scope=${serviceScope}`;
|
||||
const response = await fetch(url, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"x-service-api-key": serviceApiKey,
|
||||
"content-type": "application/json",
|
||||
},
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(
|
||||
`Error fetching key metadata from API: ${response.statusText}`,
|
||||
);
|
||||
}
|
||||
return (await response.json()) as ApiResponse;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import { authorize } from ".";
|
||||
import { CoreServiceConfig } from "../api";
|
||||
|
||||
const validServiceConfig: CoreServiceConfig = {
|
||||
apiUrl: "https://api.example.com",
|
||||
serviceScope: "storage",
|
||||
serviceApiKey: "service key",
|
||||
enforceAuth: false,
|
||||
};
|
||||
|
||||
describe("authorizeClient", () => {
|
||||
it("should skip authorization if auth not enforced and no credentials", async () => {
|
||||
const result = (await authorize(
|
||||
{
|
||||
secretKey: null,
|
||||
clientId: null,
|
||||
origin: null,
|
||||
bundleId: null,
|
||||
secretKeyHash: null,
|
||||
},
|
||||
validServiceConfig,
|
||||
)) as any;
|
||||
|
||||
expect(result.authorized).toBe(true);
|
||||
expect(result.apiKeyMeta).toEqual(null);
|
||||
});
|
||||
|
||||
it("should continue authorization if auth enforced", async () => {
|
||||
const result = (await authorize(
|
||||
{
|
||||
secretKey: null,
|
||||
clientId: null,
|
||||
origin: null,
|
||||
bundleId: null,
|
||||
secretKeyHash: null,
|
||||
},
|
||||
{ ...validServiceConfig, enforceAuth: true },
|
||||
)) as any;
|
||||
|
||||
expect(result.authorized).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,97 @@
|
||||
import { ApiKeyMetadata } from "../api";
|
||||
import { ClientAuthorizationPayload, authorizeClient } from "./client";
|
||||
|
||||
describe("authorizeClient", () => {
|
||||
const validApiKeyMeta: ApiKeyMetadata = {
|
||||
id: "1",
|
||||
key: "your-api-key",
|
||||
creatorWalletAddress: "creator-address",
|
||||
secretHash: "secret-hash",
|
||||
walletAddresses: [],
|
||||
domains: ["example.com", "*.example.com"],
|
||||
bundleIds: ["com.example.app"],
|
||||
services: [],
|
||||
};
|
||||
|
||||
const validAuthOptions: ClientAuthorizationPayload = {
|
||||
secretKeyHash: "secret-hash",
|
||||
bundleId: null,
|
||||
origin: "example.com",
|
||||
};
|
||||
|
||||
it("should authorize client with valid secret key", () => {
|
||||
const result = authorizeClient(validAuthOptions, validApiKeyMeta) as any;
|
||||
expect(result.authorized).toBe(true);
|
||||
expect(result.apiKeyMeta).toEqual(validApiKeyMeta);
|
||||
});
|
||||
|
||||
it("should authorize client with matching wildcard domain", () => {
|
||||
const authOptionsWithWildcardDomain: ClientAuthorizationPayload = {
|
||||
secretKeyHash: null,
|
||||
bundleId: null,
|
||||
origin: "sub.example.com",
|
||||
};
|
||||
|
||||
const result = authorizeClient(
|
||||
authOptionsWithWildcardDomain,
|
||||
validApiKeyMeta,
|
||||
) as any;
|
||||
expect(result.authorized).toBe(true);
|
||||
expect(result.apiKeyMeta).toEqual(validApiKeyMeta);
|
||||
});
|
||||
|
||||
it("should not authorize client with non-matching bundle id", () => {
|
||||
const authOptionsWithBundleId: ClientAuthorizationPayload = {
|
||||
secretKeyHash: null,
|
||||
bundleId: "com.foo.bar",
|
||||
origin: null,
|
||||
};
|
||||
|
||||
const result = authorizeClient(
|
||||
authOptionsWithBundleId,
|
||||
validApiKeyMeta,
|
||||
) as any;
|
||||
expect(result.authorized).toBe(false);
|
||||
expect(result.errorMessage).toBe(
|
||||
"The bundle is not authorized for this key.",
|
||||
);
|
||||
expect(result.errorCode).toBe("BUNDLE_UNAUTHORIZED");
|
||||
expect(result.status).toBe(401);
|
||||
});
|
||||
|
||||
it("should not authorize client with invalid secret key", () => {
|
||||
const authOptionsWithInvalidSecret: ClientAuthorizationPayload = {
|
||||
secretKeyHash: "invalid-secret-hash",
|
||||
bundleId: null,
|
||||
origin: null,
|
||||
};
|
||||
|
||||
const result = authorizeClient(
|
||||
authOptionsWithInvalidSecret,
|
||||
validApiKeyMeta,
|
||||
) as any;
|
||||
expect(result.authorized).toBe(false);
|
||||
expect(result.errorMessage).toBe("The secret is invalid.");
|
||||
expect(result.errorCode).toBe("SECRET_INVALID");
|
||||
expect(result.status).toBe(401);
|
||||
});
|
||||
|
||||
it("should not authorize client with unauthorized origin", () => {
|
||||
const authOptionsWithUnauthorizedOrigin: ClientAuthorizationPayload = {
|
||||
secretKeyHash: null,
|
||||
bundleId: null,
|
||||
origin: "unauthorized.com",
|
||||
};
|
||||
|
||||
const result = authorizeClient(
|
||||
authOptionsWithUnauthorizedOrigin,
|
||||
validApiKeyMeta,
|
||||
) as any;
|
||||
expect(result.authorized).toBe(false);
|
||||
expect(result.errorMessage).toBe(
|
||||
"The origin is not authorized for this key.",
|
||||
);
|
||||
expect(result.errorCode).toBe("ORIGIN_UNAUTHORIZED");
|
||||
expect(result.status).toBe(401);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,98 @@
|
||||
import type { ApiKeyMetadata } from "../api";
|
||||
import type { AuthorizationResult } from "./types";
|
||||
|
||||
export type ClientAuthorizationPayload = {
|
||||
secretKeyHash: string | null;
|
||||
bundleId: string | null;
|
||||
origin: string | null;
|
||||
};
|
||||
|
||||
export function authorizeClient(
|
||||
authOptions: ClientAuthorizationPayload,
|
||||
apiKeyMeta: ApiKeyMetadata,
|
||||
): AuthorizationResult {
|
||||
const { origin, bundleId, secretKeyHash: providedSecretHash } = authOptions;
|
||||
const { domains, bundleIds, secretHash } = apiKeyMeta;
|
||||
|
||||
if (providedSecretHash) {
|
||||
if (secretHash !== providedSecretHash) {
|
||||
return {
|
||||
authorized: false,
|
||||
errorMessage: "The secret is invalid.",
|
||||
errorCode: "SECRET_INVALID",
|
||||
status: 401,
|
||||
};
|
||||
}
|
||||
return {
|
||||
authorized: true,
|
||||
apiKeyMeta,
|
||||
};
|
||||
}
|
||||
|
||||
// validate domains
|
||||
if (origin) {
|
||||
if (
|
||||
// find matching domain, or if all domains allowed
|
||||
domains.find((d) => {
|
||||
if (d === "*") {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the allowedDomain has a wildcard,
|
||||
// we'll check that the ending of our domain matches the wildcard
|
||||
if (d.startsWith("*.")) {
|
||||
const domainRoot = d.slice(2);
|
||||
return origin.endsWith(domainRoot);
|
||||
}
|
||||
|
||||
// If there's no wildcard, we'll check for an exact match
|
||||
return d === origin;
|
||||
})
|
||||
) {
|
||||
return {
|
||||
authorized: true,
|
||||
apiKeyMeta,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
authorized: false,
|
||||
errorMessage: "The origin is not authorized for this key.",
|
||||
errorCode: "ORIGIN_UNAUTHORIZED",
|
||||
status: 401,
|
||||
};
|
||||
}
|
||||
|
||||
// validate bundleId
|
||||
if (bundleId) {
|
||||
if (
|
||||
// find matching bundle id, or if all bundles allowed
|
||||
bundleIds.find((b) => {
|
||||
if (b === "*") {
|
||||
return true;
|
||||
}
|
||||
|
||||
return b === bundleId;
|
||||
})
|
||||
) {
|
||||
return {
|
||||
authorized: true,
|
||||
apiKeyMeta,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
authorized: false,
|
||||
errorMessage: "The bundle is not authorized for this key.",
|
||||
errorCode: "BUNDLE_UNAUTHORIZED",
|
||||
status: 401,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
authorized: false,
|
||||
errorMessage: "The keys are invalid.",
|
||||
errorCode: "UNAUTHORIZED",
|
||||
status: 401,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
import {
|
||||
ApiKeyMetadata,
|
||||
CoreServiceConfig,
|
||||
fetchKeyMetadataFromApi,
|
||||
} from "../api";
|
||||
import { authorizeClient } from "./client";
|
||||
import { authorizeService } from "./service";
|
||||
import { AuthorizationResult } from "./types";
|
||||
|
||||
export type AuthorizationInput = {
|
||||
secretKey: string | null;
|
||||
clientId: string | null;
|
||||
origin: string | null;
|
||||
bundleId: string | null;
|
||||
secretKeyHash: string | null;
|
||||
targetAddress?: string | string[];
|
||||
};
|
||||
|
||||
type CacheOptions = {
|
||||
get: (clientId: string) => Promise<string | null>;
|
||||
put: (clientId: string, data: ApiKeyMetadata) => Promise<void> | void;
|
||||
cacheTtlSeconds: number;
|
||||
};
|
||||
|
||||
type CacheWithPossibleTtl =
|
||||
| {
|
||||
apiKeyMeta: ApiKeyMetadata;
|
||||
updatedAt: number;
|
||||
}
|
||||
| ApiKeyMetadata;
|
||||
|
||||
export async function authorize(
|
||||
authData: AuthorizationInput,
|
||||
serviceConfig: CoreServiceConfig,
|
||||
cacheOptions?: CacheOptions,
|
||||
): Promise<AuthorizationResult> {
|
||||
const { clientId, targetAddress, secretKeyHash } = authData;
|
||||
const { enforceAuth } = serviceConfig;
|
||||
|
||||
// BACKWARDS COMPAT: if auth not enforced and
|
||||
// we don't have auth credentials bypass
|
||||
if (!enforceAuth && !clientId && !secretKeyHash) {
|
||||
return {
|
||||
authorized: true,
|
||||
apiKeyMeta: null,
|
||||
};
|
||||
}
|
||||
|
||||
// if we don't have a client id at this point we can't authorize
|
||||
if (!clientId) {
|
||||
return {
|
||||
authorized: false,
|
||||
status: 401,
|
||||
errorMessage: "Missing clientId or secretKey.",
|
||||
errorCode: "MISSING_KEY",
|
||||
};
|
||||
}
|
||||
|
||||
let apiKeyMeta: ApiKeyMetadata | null = null;
|
||||
// if we have cache options we want to check the cache first
|
||||
if (cacheOptions) {
|
||||
try {
|
||||
const cachedKey = await cacheOptions.get(clientId);
|
||||
if (cachedKey) {
|
||||
const parsed = JSON.parse(cachedKey) as CacheWithPossibleTtl;
|
||||
if ("updatedAt" in parsed) {
|
||||
// we want to compare the updatedAt time to the current time
|
||||
// if the difference is greater than the cacheTtl we want to ignore the cached data
|
||||
const now = Date.now();
|
||||
const diff = now - parsed.updatedAt;
|
||||
const cacheTtl = cacheOptions.cacheTtlSeconds * 1000;
|
||||
// only if the diff is less than the cacheTtl do we want to use the cached key
|
||||
if (diff < cacheTtl * 1000) {
|
||||
apiKeyMeta = parsed.apiKeyMeta;
|
||||
}
|
||||
} else {
|
||||
apiKeyMeta = parsed;
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
// ignore errors, proceed as if not in cache
|
||||
}
|
||||
}
|
||||
|
||||
// if we don't have a cached key, fetch from the API
|
||||
if (!apiKeyMeta) {
|
||||
try {
|
||||
const { data, error } = await fetchKeyMetadataFromApi(
|
||||
clientId,
|
||||
serviceConfig,
|
||||
);
|
||||
if (error) {
|
||||
return {
|
||||
authorized: false,
|
||||
errorCode: error.code,
|
||||
errorMessage: error.message,
|
||||
status: error.statusCode,
|
||||
};
|
||||
} else if (!data) {
|
||||
return {
|
||||
authorized: false,
|
||||
errorCode: "NO_KEY",
|
||||
errorMessage: "No error but also no key returned.",
|
||||
status: 500,
|
||||
};
|
||||
}
|
||||
// if we have a key for sure then assign it
|
||||
apiKeyMeta = data;
|
||||
|
||||
// cache the retrieved key if we have cache options
|
||||
if (cacheOptions) {
|
||||
// we await this always because it can be a promise or not
|
||||
await cacheOptions.put(clientId, data);
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn("failed to fetch key metadata from api", err);
|
||||
return {
|
||||
authorized: false,
|
||||
status: 500,
|
||||
errorMessage: "Failed to fetch key metadata.",
|
||||
errorCode: "FAILED_TO_FETCH_KEY",
|
||||
};
|
||||
}
|
||||
}
|
||||
if (!apiKeyMeta) {
|
||||
return {
|
||||
authorized: false,
|
||||
status: 401,
|
||||
errorMessage: "Key is invalid.",
|
||||
errorCode: "INVALID_KEY",
|
||||
};
|
||||
}
|
||||
// now we can validate the key itself
|
||||
const clientAuth = authorizeClient(authData, apiKeyMeta);
|
||||
|
||||
if (!clientAuth.authorized) {
|
||||
return {
|
||||
errorCode: clientAuth.errorCode,
|
||||
authorized: false,
|
||||
status: 401,
|
||||
errorMessage: clientAuth.errorMessage,
|
||||
};
|
||||
}
|
||||
|
||||
// if we've made it this far we need to check service specific authorization
|
||||
const serviceAuth = authorizeService(apiKeyMeta, serviceConfig, {
|
||||
targetAddress,
|
||||
});
|
||||
|
||||
if (!serviceAuth.authorized) {
|
||||
return {
|
||||
errorCode: serviceAuth.errorCode,
|
||||
authorized: false,
|
||||
status: 403,
|
||||
errorMessage: serviceAuth.errorMessage,
|
||||
};
|
||||
}
|
||||
|
||||
// if we reach this point we are authorized!
|
||||
return {
|
||||
authorized: true,
|
||||
apiKeyMeta,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
import { ApiKeyMetadata, CoreServiceConfig } from "../api";
|
||||
import { ServiceAuthorizationPayload, authorizeService } from "./service";
|
||||
|
||||
describe("authorizeService", () => {
|
||||
const validApiKeyMeta: ApiKeyMetadata = {
|
||||
id: "1",
|
||||
key: "your-api-key",
|
||||
creatorWalletAddress: "creator-address",
|
||||
secretHash: "secret-hash",
|
||||
walletAddresses: [],
|
||||
domains: [],
|
||||
bundleIds: [],
|
||||
services: [
|
||||
{
|
||||
name: "storage",
|
||||
targetAddresses: ["target1", "target2"],
|
||||
actions: ["action1", "action2"],
|
||||
},
|
||||
{
|
||||
name: "service2",
|
||||
targetAddresses: ["target3"],
|
||||
actions: ["action3"],
|
||||
},
|
||||
{
|
||||
name: "bundler",
|
||||
targetAddresses: ["*"],
|
||||
actions: ["action3"],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const validServiceConfig: CoreServiceConfig = {
|
||||
apiUrl: "https://api.example.com",
|
||||
serviceScope: "storage",
|
||||
serviceApiKey: "service-api-key",
|
||||
serviceAction: "action1",
|
||||
enforceAuth: true,
|
||||
};
|
||||
|
||||
const validBundlerServiceConfig: CoreServiceConfig = {
|
||||
apiUrl: "https://api.example.com",
|
||||
serviceScope: "bundler",
|
||||
serviceApiKey: "service-api-key",
|
||||
enforceAuth: true,
|
||||
};
|
||||
|
||||
it("should authorize service with valid service scope and action", () => {
|
||||
const result = authorizeService(validApiKeyMeta, validServiceConfig) as any;
|
||||
expect(result.authorized).toBe(true);
|
||||
expect(result.apiKeyMeta).toEqual(validApiKeyMeta);
|
||||
});
|
||||
|
||||
it("should authorize service with valid target address", () => {
|
||||
const validAuthorizationPayload: ServiceAuthorizationPayload = {
|
||||
targetAddress: "target2",
|
||||
};
|
||||
|
||||
const result = authorizeService(
|
||||
validApiKeyMeta,
|
||||
validServiceConfig,
|
||||
validAuthorizationPayload,
|
||||
) as any;
|
||||
expect(result.authorized).toBe(true);
|
||||
expect(result.apiKeyMeta).toEqual(validApiKeyMeta);
|
||||
});
|
||||
|
||||
it("should not authorize service with unauthorized service scope", () => {
|
||||
const invalidServiceConfig: CoreServiceConfig = {
|
||||
apiUrl: "https://api.example.com",
|
||||
serviceScope: "rpc",
|
||||
serviceApiKey: "service-api-key",
|
||||
serviceAction: "action1",
|
||||
enforceAuth: true,
|
||||
};
|
||||
|
||||
const result = authorizeService(
|
||||
validApiKeyMeta,
|
||||
invalidServiceConfig,
|
||||
) as any;
|
||||
expect(result.authorized).toBe(false);
|
||||
expect(result.errorMessage).toBe(
|
||||
'The service "rpc" is not authorized for this key.',
|
||||
);
|
||||
expect(result.errorCode).toBe("SERVICE_UNAUTHORIZED");
|
||||
expect(result.status).toBe(403);
|
||||
});
|
||||
|
||||
it("should not authorize service with unauthorized service action", () => {
|
||||
const invalidServiceConfig: CoreServiceConfig = {
|
||||
apiUrl: "https://api.example.com",
|
||||
serviceScope: "storage",
|
||||
serviceApiKey: "service-api-key",
|
||||
serviceAction: "unauthorized-action",
|
||||
enforceAuth: true,
|
||||
};
|
||||
|
||||
const result = authorizeService(
|
||||
validApiKeyMeta,
|
||||
invalidServiceConfig,
|
||||
) as any;
|
||||
expect(result.authorized).toBe(false);
|
||||
expect(result.errorMessage).toBe(
|
||||
'The service "storage" action "unauthorized-action" is not authorized for this key.',
|
||||
);
|
||||
expect(result.errorCode).toBe("SERVICE_ACTION_UNAUTHORIZED");
|
||||
expect(result.status).toBe(403);
|
||||
});
|
||||
|
||||
it("should not authorize service with unauthorized target address", () => {
|
||||
const invalidAuthorizationPayload: ServiceAuthorizationPayload = {
|
||||
targetAddress: "unauthorized-target",
|
||||
};
|
||||
|
||||
const result = authorizeService(
|
||||
validApiKeyMeta,
|
||||
validServiceConfig,
|
||||
invalidAuthorizationPayload,
|
||||
) as any;
|
||||
expect(result.authorized).toBe(false);
|
||||
expect(result.errorMessage).toBe(
|
||||
'The service "storage" target address is not authorized for this key.',
|
||||
);
|
||||
expect(result.errorCode).toBe("SERVICE_TARGET_ADDRESS_UNAUTHORIZED");
|
||||
expect(result.status).toBe(403);
|
||||
});
|
||||
|
||||
it("should not authorize service with unauthorized target addresses", () => {
|
||||
const invalidAuthorizationPayload: ServiceAuthorizationPayload = {
|
||||
targetAddress: ["target1", "target2", "target3"],
|
||||
};
|
||||
|
||||
const result = authorizeService(
|
||||
validApiKeyMeta,
|
||||
validServiceConfig,
|
||||
invalidAuthorizationPayload,
|
||||
) as any;
|
||||
expect(result.authorized).toBe(false);
|
||||
expect(result.errorMessage).toBe(
|
||||
'The service "storage" target address is not authorized for this key.',
|
||||
);
|
||||
expect(result.errorCode).toBe("SERVICE_TARGET_ADDRESS_UNAUTHORIZED");
|
||||
expect(result.status).toBe(403);
|
||||
});
|
||||
|
||||
it("should authorize bundler service with * target addresses", () => {
|
||||
const authorizationPayload: ServiceAuthorizationPayload = {
|
||||
targetAddress: ["target1", "target2"],
|
||||
};
|
||||
|
||||
const result = authorizeService(
|
||||
validApiKeyMeta,
|
||||
validBundlerServiceConfig,
|
||||
authorizationPayload,
|
||||
) as any;
|
||||
expect(result.authorized).toBe(true);
|
||||
expect(result.apiKeyMeta).toEqual(validApiKeyMeta);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,66 @@
|
||||
import { ApiKeyMetadata, CoreServiceConfig } from "../api";
|
||||
import { AuthorizationResult } from "./types";
|
||||
|
||||
export type ServiceAuthorizationPayload = { targetAddress?: string | string[] };
|
||||
|
||||
export function authorizeService(
|
||||
apiKeyMetadata: ApiKeyMetadata,
|
||||
serviceConfig: CoreServiceConfig,
|
||||
authorizationPayload?: ServiceAuthorizationPayload,
|
||||
): AuthorizationResult {
|
||||
const { services } = apiKeyMetadata;
|
||||
// validate services
|
||||
const service = services.find(
|
||||
(srv) => srv.name === serviceConfig.serviceScope,
|
||||
);
|
||||
if (!service) {
|
||||
return {
|
||||
authorized: false,
|
||||
errorMessage: `The service "${serviceConfig.serviceScope}" is not authorized for this key.`,
|
||||
errorCode: "SERVICE_UNAUTHORIZED",
|
||||
status: 403,
|
||||
};
|
||||
}
|
||||
|
||||
// validate service actions
|
||||
if (serviceConfig.serviceAction) {
|
||||
const isActionAllowed = service.actions.includes(
|
||||
serviceConfig.serviceAction,
|
||||
);
|
||||
if (!isActionAllowed) {
|
||||
return {
|
||||
authorized: false,
|
||||
errorMessage: `The service "${serviceConfig.serviceScope}" action "${serviceConfig.serviceAction}" is not authorized for this key.`,
|
||||
errorCode: "SERVICE_ACTION_UNAUTHORIZED",
|
||||
status: 403,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// validate service target addresses
|
||||
// the service has to pass in the target address for this to be validated
|
||||
if (authorizationPayload?.targetAddress) {
|
||||
const checkedAddresses = Array.isArray(authorizationPayload.targetAddress)
|
||||
? authorizationPayload.targetAddress
|
||||
: [authorizationPayload.targetAddress];
|
||||
|
||||
const allAllowed = service.targetAddresses.includes("*");
|
||||
|
||||
if (
|
||||
!allAllowed &&
|
||||
checkedAddresses.some((ta) => !service.targetAddresses.includes(ta))
|
||||
) {
|
||||
return {
|
||||
authorized: false,
|
||||
errorMessage: `The service "${serviceConfig.serviceScope}" target address is not authorized for this key.`,
|
||||
errorCode: "SERVICE_TARGET_ADDRESS_UNAUTHORIZED",
|
||||
status: 403,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
authorized: true,
|
||||
apiKeyMeta: apiKeyMetadata,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import { ApiKeyMetadata } from "../api";
|
||||
|
||||
export type AuthorizationResult =
|
||||
| {
|
||||
authorized: true;
|
||||
apiKeyMeta: ApiKeyMetadata | null;
|
||||
}
|
||||
| {
|
||||
authorized: false;
|
||||
status: number;
|
||||
errorMessage: string;
|
||||
errorCode: string;
|
||||
};
|
||||
@@ -1,7 +1,5 @@
|
||||
export const SERVICE_NAMES = ["bundler", "rpc", "storage"] as const;
|
||||
|
||||
export const SERVICES: Service[] = [
|
||||
{
|
||||
export const SERVICE_DEFINITIONS = {
|
||||
storage: {
|
||||
name: "storage",
|
||||
title: "Storage",
|
||||
description: "IPFS Upload and Download",
|
||||
@@ -18,33 +16,46 @@ export const SERVICES: Service[] = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
rpc: {
|
||||
name: "rpc",
|
||||
title: "RPC",
|
||||
description: "Accelerated RPC Edge",
|
||||
// all actions allowed
|
||||
actions: [],
|
||||
},
|
||||
{
|
||||
bundler: {
|
||||
name: "bundler",
|
||||
title: "Smart Wallets",
|
||||
description: "Bundler & Paymaster services",
|
||||
// all actions allowed
|
||||
actions: [],
|
||||
},
|
||||
];
|
||||
relayer: {
|
||||
name: "relayer",
|
||||
title: "Gasless Relayer",
|
||||
description: "Enable gasless transactions",
|
||||
// all actions allowed
|
||||
actions: [],
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const SERVICE_NAMES = Object.keys(
|
||||
SERVICE_DEFINITIONS,
|
||||
) as (keyof typeof SERVICE_DEFINITIONS)[];
|
||||
|
||||
export const SERVICES = Object.values(SERVICE_DEFINITIONS);
|
||||
|
||||
export type ServiceName = (typeof SERVICE_NAMES)[number];
|
||||
|
||||
export interface ServiceAction {
|
||||
export type ServiceAction = {
|
||||
name: string;
|
||||
title: string;
|
||||
description?: string;
|
||||
}
|
||||
};
|
||||
|
||||
export interface Service {
|
||||
name: ServiceName;
|
||||
title: string;
|
||||
description?: string;
|
||||
actions: ServiceAction[];
|
||||
export type Service =
|
||||
(typeof SERVICE_DEFINITIONS)[keyof typeof SERVICE_DEFINITIONS];
|
||||
|
||||
export function getServiceByName(name: ServiceName) {
|
||||
return SERVICE_DEFINITIONS[name];
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
export type CoreAuthInput = {
|
||||
// for passing it from the subdomain or path or other service specific things
|
||||
clientId?: string;
|
||||
// for passing in the address target in RPC or bundler services
|
||||
targetAddress?: string | string[];
|
||||
};
|
||||
@@ -1,8 +1,2 @@
|
||||
import { SERVICES } from "./types";
|
||||
|
||||
export function getServiceByName(name: string) {
|
||||
return SERVICES.find((srv) => srv.name === name);
|
||||
}
|
||||
|
||||
export * from "./types";
|
||||
export * from "./auth";
|
||||
// only exports the public service definitions
|
||||
export * from "./core/services";
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
import type { IncomingHttpHeaders, IncomingMessage } from "node:http";
|
||||
import { createHash } from "node:crypto";
|
||||
import type { AuthorizationInput } from "../core/authorize";
|
||||
import type { CoreServiceConfig } from "../core/api";
|
||||
import { authorize } from "../core/authorize";
|
||||
import type { AuthorizationResult } from "../core/authorize/types";
|
||||
import type { CoreAuthInput } from "../core/types";
|
||||
|
||||
export * from "../core/services";
|
||||
|
||||
type NodeServiceConfig = CoreServiceConfig;
|
||||
|
||||
export type AuthInput = CoreAuthInput & {
|
||||
req: IncomingMessage;
|
||||
};
|
||||
|
||||
export async function authorizeNode(
|
||||
authInput: AuthInput,
|
||||
serviceConfig: NodeServiceConfig,
|
||||
): Promise<AuthorizationResult> {
|
||||
let authData;
|
||||
try {
|
||||
authData = extractAuthorizationData(authInput);
|
||||
} catch (e) {
|
||||
if (e instanceof Error && e.message === "KEY_CONFLICT") {
|
||||
return {
|
||||
authorized: false,
|
||||
status: 400,
|
||||
errorMessage: "Please pass either a client id or a secret key.",
|
||||
errorCode: "KEY_CONFLICT",
|
||||
};
|
||||
}
|
||||
return {
|
||||
authorized: false,
|
||||
status: 500,
|
||||
errorMessage: "Internal Server Error",
|
||||
errorCode: "INTERNAL_SERVER_ERROR",
|
||||
};
|
||||
}
|
||||
|
||||
return await authorize(authData, serviceConfig);
|
||||
}
|
||||
|
||||
function getHeader(
|
||||
headers: IncomingHttpHeaders,
|
||||
headerName: string,
|
||||
): string | null {
|
||||
const header = headers[headerName];
|
||||
if (Array.isArray(header)) {
|
||||
return header[0];
|
||||
}
|
||||
return header ?? null;
|
||||
}
|
||||
|
||||
export function extractAuthorizationData(
|
||||
authInput: AuthInput,
|
||||
): AuthorizationInput {
|
||||
let requestUrl;
|
||||
|
||||
try {
|
||||
requestUrl = new URL(
|
||||
authInput.req.url || "",
|
||||
`http://${authInput.req.headers.host}`,
|
||||
);
|
||||
} catch (error) {
|
||||
console.log("** Node URL Error **", error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
const headers = authInput.req.headers;
|
||||
const secretKey = getHeader(headers, "x-secret-key");
|
||||
// prefer clientId that is explicitly passed in
|
||||
let clientId = authInput.clientId ?? null;
|
||||
|
||||
if (!clientId) {
|
||||
// next preference is clientId from header
|
||||
clientId = getHeader(headers, "x-client-id");
|
||||
}
|
||||
|
||||
// next preference is search param
|
||||
if (!clientId) {
|
||||
clientId = requestUrl.searchParams.get("clientId");
|
||||
}
|
||||
// bundle id from header is first preference
|
||||
let bundleId = getHeader(headers, "x-bundle-id");
|
||||
|
||||
// next preference is search param
|
||||
if (!bundleId) {
|
||||
bundleId = requestUrl.searchParams.get("bundleId");
|
||||
}
|
||||
|
||||
let origin = getHeader(headers, "origin");
|
||||
// if origin header is not available we'll fall back to referrer;
|
||||
if (!origin) {
|
||||
origin = getHeader(headers, "referer");
|
||||
}
|
||||
// if we have an origin at this point, normalize it
|
||||
if (origin) {
|
||||
try {
|
||||
origin = new URL(origin).hostname;
|
||||
} catch (e) {
|
||||
console.warn("failed to parse origin", origin, e);
|
||||
}
|
||||
}
|
||||
|
||||
// handle if we a secret key is passed in the headers
|
||||
let secretKeyHash: string | null = null;
|
||||
if (secretKey) {
|
||||
// hash the secret key
|
||||
secretKeyHash = hashSecretKey(secretKey);
|
||||
// derive the client id from the secret key hash
|
||||
const derivedClientId = deriveClientIdFromSecretKeyHash(secretKeyHash);
|
||||
// if we already have a client id passed in we need to make sure they match
|
||||
if (clientId && clientId !== derivedClientId) {
|
||||
throw new Error("KEY_CONFLICT");
|
||||
}
|
||||
// otherwise set the client id to the derived client id (client id based off of secret key)
|
||||
clientId = derivedClientId;
|
||||
}
|
||||
|
||||
return {
|
||||
secretKeyHash,
|
||||
secretKey,
|
||||
clientId,
|
||||
origin,
|
||||
bundleId,
|
||||
targetAddress: authInput.targetAddress,
|
||||
};
|
||||
}
|
||||
|
||||
export function hashSecretKey(secretKey: string) {
|
||||
return createHash("sha256").update(secretKey).digest("hex");
|
||||
}
|
||||
|
||||
export function deriveClientIdFromSecretKeyHash(secretKeyHash: string) {
|
||||
return secretKeyHash.slice(0, 32);
|
||||
}
|
||||
@@ -1,5 +1,14 @@
|
||||
# @thirdweb-dev/unity-js-bridge
|
||||
|
||||
## 0.2.53
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`dac8fa7d`](https://github.com/thirdweb-dev/js/commit/dac8fa7d98b6952acf8d13e173099889c1d47da8), [`c5761b99`](https://github.com/thirdweb-dev/js/commit/c5761b99e9797772481506e90cbfa5c35a05bd1d), [`b96a2282`](https://github.com/thirdweb-dev/js/commit/b96a2282730582b684cc96802649a96851af5220)]:
|
||||
- @thirdweb-dev/sdk@3.10.36
|
||||
- @thirdweb-dev/wallets@1.0.12
|
||||
- @thirdweb-dev/auth@3.2.16
|
||||
|
||||
## 0.2.52
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/unity-js-bridge",
|
||||
"version": "0.2.52",
|
||||
"version": "0.2.53",
|
||||
"main": "dist/thirdweb-unity-bridge.js",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/unity-js-bridge",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
# @thirdweb-dev/wallets
|
||||
|
||||
## 1.0.12
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1352](https://github.com/thirdweb-dev/js/pull/1352) [`c5761b99`](https://github.com/thirdweb-dev/js/commit/c5761b99e9797772481506e90cbfa5c35a05bd1d) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Switch to seed based local wallets for faster encryption
|
||||
|
||||
- [#1350](https://github.com/thirdweb-dev/js/pull/1350) [`b96a2282`](https://github.com/thirdweb-dev/js/commit/b96a2282730582b684cc96802649a96851af5220) Thanks [@MananTank](https://github.com/MananTank)! - Improved Injected Metamask detection - Do not consider Phantom provider as MetaMask
|
||||
|
||||
- Updated dependencies [[`dac8fa7d`](https://github.com/thirdweb-dev/js/commit/dac8fa7d98b6952acf8d13e173099889c1d47da8)]:
|
||||
- @thirdweb-dev/sdk@3.10.36
|
||||
|
||||
## 1.0.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/wallets",
|
||||
"version": "1.0.11",
|
||||
"version": "1.0.12",
|
||||
"main": "dist/thirdweb-dev-wallets.cjs.js",
|
||||
"module": "dist/thirdweb-dev-wallets.esm.js",
|
||||
"types": "dist/thirdweb-dev-wallets.cjs.d.ts",
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
import { Ethereum } from "../injected/types";
|
||||
import { assertWindowEthereum } from "../../utils/assertWindowEthereum";
|
||||
|
||||
export function getInjectedMetamaskProvider(): Ethereum | undefined {
|
||||
if (typeof window === "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
function getReady(ethereum?: Ethereum): Ethereum | undefined {
|
||||
const isMetaMask = !!ethereum?.isMetaMask;
|
||||
|
||||
if (!isMetaMask) {
|
||||
return;
|
||||
}
|
||||
// Brave tries to make itself look like MetaMask
|
||||
// Could also try RPC `web3_clientVersion` if following is unreliable
|
||||
if (ethereum.isBraveWallet && !ethereum._events && !ethereum._state) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ethereum.isPhantom) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ethereum.isAvalanche) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ethereum.isBitKeep) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ethereum.isMathWallet) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ethereum.isZerion) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ethereum.isKuCoinWallet) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ethereum.isPortal) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ethereum.isTokenPocket) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ethereum.isTokenary) {
|
||||
return;
|
||||
}
|
||||
|
||||
return ethereum;
|
||||
}
|
||||
|
||||
if (assertWindowEthereum(globalThis.window)) {
|
||||
if (globalThis.window.ethereum?.providers) {
|
||||
return globalThis.window.ethereum.providers.find(getReady);
|
||||
}
|
||||
|
||||
return getReady(globalThis.window.ethereum);
|
||||
}
|
||||
}
|
||||
@@ -5,12 +5,11 @@ import {
|
||||
RpcError,
|
||||
UserRejectedRequestError,
|
||||
} from "../../../lib/wagmi-core/errors";
|
||||
import { assertWindowEthereum } from "../../utils/assertWindowEthereum";
|
||||
import { walletIds } from "../../constants/walletIds";
|
||||
import { InjectedConnector, InjectedConnectorOptions } from "../injected";
|
||||
import { Ethereum } from "../injected/types";
|
||||
import type { Chain } from "@thirdweb-dev/chains";
|
||||
import { utils } from "ethers";
|
||||
import { getInjectedMetamaskProvider } from "./getInjectedMetamaskProvider";
|
||||
|
||||
export type MetaMaskConnectorOptions = Pick<
|
||||
InjectedConnectorOptions,
|
||||
@@ -37,46 +36,7 @@ export class MetaMaskConnector extends InjectedConnector {
|
||||
name: "MetaMask",
|
||||
shimDisconnect: true,
|
||||
shimChainChangedDisconnect: true,
|
||||
getProvider() {
|
||||
function getReady(ethereum?: Ethereum) {
|
||||
const isMetaMask = !!ethereum?.isMetaMask;
|
||||
if (!isMetaMask) {
|
||||
return;
|
||||
}
|
||||
// Brave tries to make itself look like MetaMask
|
||||
// Could also try RPC `web3_clientVersion` if following is unreliable
|
||||
if (ethereum.isBraveWallet && !ethereum._events && !ethereum._state) {
|
||||
return;
|
||||
}
|
||||
if (ethereum.isAvalanche) {
|
||||
return;
|
||||
}
|
||||
if (ethereum.isKuCoinWallet) {
|
||||
return;
|
||||
}
|
||||
if (ethereum.isPortal) {
|
||||
return;
|
||||
}
|
||||
if (ethereum.isTokenPocket) {
|
||||
return;
|
||||
}
|
||||
if (ethereum.isTokenary) {
|
||||
return;
|
||||
}
|
||||
return ethereum;
|
||||
}
|
||||
|
||||
if (typeof window === "undefined") {
|
||||
return;
|
||||
}
|
||||
if (assertWindowEthereum(globalThis.window)) {
|
||||
if (globalThis.window.ethereum?.providers) {
|
||||
return globalThis.window.ethereum.providers.find(getReady);
|
||||
}
|
||||
|
||||
return getReady(globalThis.window.ethereum);
|
||||
}
|
||||
},
|
||||
getProvider: getInjectedMetamaskProvider,
|
||||
};
|
||||
|
||||
const options = {
|
||||
|
||||
@@ -44,3 +44,4 @@ export type { Chain } from "@thirdweb-dev/chains";
|
||||
|
||||
// export the window ethereum util
|
||||
export { assertWindowEthereum } from "./utils/assertWindowEthereum";
|
||||
export { getInjectedMetamaskProvider } from "./connectors/metamask/getInjectedMetamaskProvider";
|
||||
|
||||
@@ -94,7 +94,8 @@ export class LocalWallet extends AbstractClientWallet<
|
||||
if (this.ethersWallet) {
|
||||
throw new Error("wallet is already initialized");
|
||||
}
|
||||
this.ethersWallet = Wallet.createRandom();
|
||||
const random = utils.randomBytes(32);
|
||||
this.ethersWallet = new Wallet(random);
|
||||
return this.ethersWallet.address;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import type { WalletConnectConnector as WalletConnectConnectorType } from "../connectors/wallet-connect";
|
||||
import type { QRModalOptions } from "../connectors/wallet-connect/qrModalOptions";
|
||||
import { Connector, WagmiAdapter } from "../interfaces/connector";
|
||||
import { assertWindowEthereum } from "../utils/assertWindowEthereum";
|
||||
import { AbstractClientWallet, WalletOptions } from "./base";
|
||||
import type { MetaMaskConnector as MetamaskConnectorType } from "../connectors/metamask";
|
||||
import { walletIds } from "../constants/walletIds";
|
||||
import { TW_WC_PROJECT_ID } from "../constants/wc";
|
||||
import { getInjectedMetamaskProvider } from "../connectors/metamask/getInjectedMetamaskProvider";
|
||||
|
||||
type MetamaskAdditionalOptions = {
|
||||
/**
|
||||
@@ -63,12 +63,7 @@ export class MetaMaskWallet extends AbstractClientWallet<MetamaskAdditionalOptio
|
||||
|
||||
constructor(options: MetamaskWalletOptions) {
|
||||
super(MetaMaskWallet.id, options);
|
||||
|
||||
if (assertWindowEthereum(globalThis.window)) {
|
||||
this.isInjected = !!globalThis.window.ethereum?.isMetaMask;
|
||||
} else {
|
||||
this.isInjected = false;
|
||||
}
|
||||
this.isInjected = !!getInjectedMetamaskProvider();
|
||||
}
|
||||
|
||||
protected async getConnector(): Promise<Connector> {
|
||||
|
||||
Generated
+269
-291
@@ -1,5 +1,9 @@
|
||||
lockfileVersion: '6.0'
|
||||
|
||||
settings:
|
||||
autoInstallPeers: true
|
||||
excludeLinksFromLockfile: false
|
||||
|
||||
overrides:
|
||||
cross-fetch@>=3.0.0 <3.1.5: '>=3.1.5'
|
||||
got@<11.8.5: '>=11.8.5'
|
||||
@@ -156,7 +160,7 @@ importers:
|
||||
version: link:../eslint-config-thirdweb
|
||||
eslint-plugin-import:
|
||||
specifier: ^2.26.0
|
||||
version: 2.27.5(@typescript-eslint/[email protected])(eslint[email protected])(eslint@8.43.0)
|
||||
version: 2.27.5(@typescript-eslint/[email protected])([email protected])
|
||||
eslint-plugin-inclusive-language:
|
||||
specifier: ^2.2.0
|
||||
version: 2.2.0
|
||||
@@ -219,7 +223,7 @@ importers:
|
||||
version: link:../eslint-config-thirdweb
|
||||
jest:
|
||||
specifier: ^29.4.3
|
||||
version: 29.5.0(@types/[email protected])([email protected])
|
||||
version: 29.5.0(@types/[email protected])
|
||||
plop:
|
||||
specifier: ^3.1.2
|
||||
version: 3.1.2
|
||||
@@ -600,7 +604,7 @@ importers:
|
||||
version: 0.0.3([email protected])
|
||||
eslint-plugin-import:
|
||||
specifier: ^2.26.0
|
||||
version: 2.27.5(@typescript-eslint/[email protected])(eslint[email protected])(eslint@8.43.0)
|
||||
version: 2.27.5(@typescript-eslint/[email protected])([email protected])
|
||||
eslint-plugin-inclusive-language:
|
||||
specifier: ^2.2.0
|
||||
version: 2.2.0
|
||||
@@ -724,7 +728,7 @@ importers:
|
||||
version: 0.0.3([email protected])
|
||||
eslint-plugin-import:
|
||||
specifier: ^2.26.0
|
||||
version: 2.27.5(@typescript-eslint/[email protected])(eslint[email protected])(eslint@8.43.0)
|
||||
version: 2.27.5(@typescript-eslint/[email protected])([email protected])
|
||||
eslint-plugin-inclusive-language:
|
||||
specifier: ^2.2.0
|
||||
version: 2.2.0
|
||||
@@ -864,7 +868,7 @@ importers:
|
||||
version: link:../eslint-config-thirdweb
|
||||
eslint-plugin-import:
|
||||
specifier: ^2.26.0
|
||||
version: 2.27.5(@typescript-eslint/[email protected])(eslint[email protected])(eslint@8.43.0)
|
||||
version: 2.27.5(@typescript-eslint/[email protected])([email protected])
|
||||
eslint-plugin-inclusive-language:
|
||||
specifier: ^2.2.0
|
||||
version: 2.2.0
|
||||
@@ -879,7 +883,7 @@ importers:
|
||||
version: 47.0.14(@babel/[email protected])
|
||||
jest:
|
||||
specifier: ^29.4.3
|
||||
version: 29.5.0(@types/[email protected])([email protected])
|
||||
version: 29.5.0(@types/[email protected])
|
||||
prettier:
|
||||
specifier: ^2.8.8
|
||||
version: 2.8.8
|
||||
@@ -1085,7 +1089,7 @@ importers:
|
||||
version: 0.0.3([email protected])
|
||||
eslint-plugin-import:
|
||||
specifier: ^2.26.0
|
||||
version: 2.27.5(@typescript-eslint/[email protected])(eslint[email protected])(eslint@8.43.0)
|
||||
version: 2.27.5(@typescript-eslint/[email protected])([email protected])
|
||||
eslint-plugin-inclusive-language:
|
||||
specifier: ^2.2.0
|
||||
version: 2.2.0
|
||||
@@ -1126,11 +1130,14 @@ importers:
|
||||
specifier: ^4.20230710.0
|
||||
version: 4.20230710.0
|
||||
'@preconstruct/cli':
|
||||
specifier: ^2.7.0
|
||||
version: 2.7.0
|
||||
specifier: ^2.8.1
|
||||
version: 2.8.1
|
||||
'@thirdweb-dev/tsconfig':
|
||||
specifier: workspace:*
|
||||
version: link:../tw-tsconfig
|
||||
'@types/jest':
|
||||
specifier: ^29.5.2
|
||||
version: 29.5.2
|
||||
'@types/node':
|
||||
specifier: ^20.4.1
|
||||
version: 20.4.1
|
||||
@@ -1149,18 +1156,12 @@ importers:
|
||||
eslint-config-thirdweb:
|
||||
specifier: workspace:*
|
||||
version: link:../eslint-config-thirdweb
|
||||
lint-staged:
|
||||
specifier: ^13.2.3
|
||||
version: 13.2.3
|
||||
jest:
|
||||
specifier: ^29.4.3
|
||||
version: 29.5.0(@types/[email protected])
|
||||
prettier:
|
||||
specifier: ^3.0.0
|
||||
version: 3.0.0
|
||||
sort-package-json:
|
||||
specifier: ^2.5.1
|
||||
version: 2.5.1
|
||||
ts-node:
|
||||
specifier: ^10.9.1
|
||||
version: 10.9.1(@types/[email protected])([email protected])
|
||||
typescript:
|
||||
specifier: ^5.1.6
|
||||
version: 5.1.6
|
||||
@@ -2756,16 +2757,6 @@ packages:
|
||||
'@babel/core': 7.22.5
|
||||
'@babel/helper-plugin-utils': 7.22.5
|
||||
|
||||
/@babel/[email protected](@babel/[email protected]):
|
||||
resolution: {integrity: sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.22.5
|
||||
'@babel/helper-plugin-utils': 7.22.5
|
||||
dev: true
|
||||
|
||||
/@babel/[email protected](@babel/[email protected]):
|
||||
resolution: {integrity: sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
@@ -7281,6 +7272,52 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@preconstruct/[email protected]:
|
||||
resolution: {integrity: sha512-PX5w+au06iY/QaT+9RLmRlIfavRCRoMTC/krwtNrgPEnubR9e6P+QlywrKmwiEvkzbR9AEzGnRZL8uNRDDMzrQ==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.22.5
|
||||
'@babel/core': 7.22.5
|
||||
'@babel/helper-module-imports': 7.22.5
|
||||
'@babel/runtime': 7.22.5
|
||||
'@preconstruct/hook': 0.4.0
|
||||
'@rollup/plugin-alias': 3.1.9([email protected])
|
||||
'@rollup/plugin-commonjs': 15.1.0([email protected])
|
||||
'@rollup/plugin-json': 4.1.0([email protected])
|
||||
'@rollup/plugin-node-resolve': 11.2.1([email protected])
|
||||
'@rollup/plugin-replace': 2.4.2([email protected])
|
||||
builtin-modules: 3.3.0
|
||||
chalk: 4.1.2
|
||||
dataloader: 2.2.2
|
||||
detect-indent: 6.1.0
|
||||
enquirer: 2.3.6
|
||||
estree-walker: 2.0.2
|
||||
fast-deep-equal: 2.0.1
|
||||
fast-glob: 3.2.12
|
||||
fs-extra: 9.1.0
|
||||
is-ci: 2.0.0
|
||||
is-reference: 1.2.1
|
||||
jest-worker: 26.6.2
|
||||
magic-string: 0.30.0
|
||||
meow: 7.1.1
|
||||
ms: 2.1.3
|
||||
normalize-path: 3.0.0
|
||||
npm-packlist: 2.2.2
|
||||
p-limit: 3.1.0
|
||||
parse-glob: 3.0.4
|
||||
parse-json: 5.2.0
|
||||
quick-lru: 5.1.1
|
||||
resolve: 1.22.1
|
||||
resolve-from: 5.0.0
|
||||
rollup: 2.79.1
|
||||
semver: 7.5.3
|
||||
terser: 5.18.2
|
||||
v8-compile-cache: 2.3.0
|
||||
zod: 3.21.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@preconstruct/[email protected]:
|
||||
resolution: {integrity: sha512-a7mrlPTM3tAFJyz43qb4pPVpUx8j8TzZBFsNFqcKcE/sEakNXRlQAuCT4RGZRf9dQiiUnBahzSIWawU4rENl+Q==}
|
||||
dependencies:
|
||||
@@ -11037,6 +11074,7 @@ packages:
|
||||
typescript: 5.1.6
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/[email protected]([email protected])([email protected]):
|
||||
resolution: {integrity: sha512-pHWlc3alg2oSMGwsU/Is8hbm3XFbcrb6P5wIxcQW9NsYBfnrubl/GhVVD/Jm/t8HXhA2WncoIRfBtnCgRGV96Q==}
|
||||
@@ -12148,13 +12186,6 @@ packages:
|
||||
dependencies:
|
||||
acorn: 8.10.0
|
||||
|
||||
/[email protected]([email protected]):
|
||||
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
||||
peerDependencies:
|
||||
acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||
dependencies:
|
||||
acorn: 8.8.2
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==}
|
||||
dependencies:
|
||||
@@ -12647,11 +12678,6 @@ packages:
|
||||
resolution: {integrity: sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==}
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==}
|
||||
|
||||
@@ -14049,22 +14075,6 @@ packages:
|
||||
resolution: {integrity: sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
slice-ansi: 3.0.0
|
||||
string-width: 4.2.3
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
dependencies:
|
||||
slice-ansi: 5.0.0
|
||||
string-width: 5.1.2
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==}
|
||||
engines: {node: '>= 10'}
|
||||
@@ -14223,11 +14233,6 @@ packages:
|
||||
typical: 5.2.0
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==}
|
||||
engines: {node: '>=14'}
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==}
|
||||
|
||||
@@ -15172,20 +15177,10 @@ packages:
|
||||
resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==}
|
||||
engines: {node: '>=12.20'}
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-1aXUEPdfGdzVPFpzGJJNgq9o81bGg1s09uxTWsqBlo9PI332uyJRQq13+LK/UN4JfxJbFdCXonUFQ9R/p7yCtw==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==}
|
||||
dev: false
|
||||
@@ -16019,7 +16014,7 @@ packages:
|
||||
eslint: 8.44.0
|
||||
eslint-import-resolver-node: 0.3.7
|
||||
eslint-import-resolver-typescript: 3.5.3([email protected])([email protected])
|
||||
eslint-plugin-import: 2.27.5(@typescript-eslint/[email protected])([email protected])([email protected]3.0)
|
||||
eslint-plugin-import: 2.27.5(@typescript-eslint/[email protected])([email protected])([email protected]4.0)
|
||||
eslint-plugin-jsx-a11y: 6.7.1([email protected])
|
||||
eslint-plugin-react: 7.32.2([email protected])
|
||||
eslint-plugin-react-hooks: 4.6.0([email protected])
|
||||
@@ -16090,7 +16085,7 @@ packages:
|
||||
confusing-browser-globals: 1.0.11
|
||||
eslint: 8.44.0
|
||||
eslint-plugin-flowtype: 8.0.3(@babel/[email protected])(@babel/[email protected])([email protected])
|
||||
eslint-plugin-import: 2.27.5(@typescript-eslint/[email protected])([email protected])([email protected]3.0)
|
||||
eslint-plugin-import: 2.27.5(@typescript-eslint/[email protected])([email protected])([email protected]4.0)
|
||||
eslint-plugin-jest: 25.7.0(@typescript-eslint/[email protected])([email protected])([email protected])([email protected])
|
||||
eslint-plugin-jsx-a11y: 6.7.1([email protected])
|
||||
eslint-plugin-react: 7.32.2([email protected])
|
||||
@@ -16142,6 +16137,7 @@ packages:
|
||||
synckit: 0.8.5
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/[email protected]([email protected])([email protected]):
|
||||
resolution: {integrity: sha512-njRcKYBc3isE42LaTcJNVANR3R99H9bAxBDMNDr2W7yq5gYPxbU3MkdhsQukxZ/Xg9C2vcyLlDsbKfRDg0QvCQ==}
|
||||
@@ -16153,7 +16149,7 @@ packages:
|
||||
debug: 4.3.4([email protected])
|
||||
enhanced-resolve: 5.12.0
|
||||
eslint: 8.44.0
|
||||
eslint-plugin-import: 2.27.5(@typescript-eslint/[email protected])([email protected])([email protected]3.0)
|
||||
eslint-plugin-import: 2.27.5(@typescript-eslint/[email protected])([email protected])([email protected]4.0)
|
||||
get-tsconfig: 4.4.0
|
||||
globby: 13.1.3
|
||||
is-core-module: 2.11.0
|
||||
@@ -16191,6 +16187,37 @@ packages:
|
||||
eslint-import-resolver-typescript: 3.5.3([email protected])([email protected])
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/[email protected](@typescript-eslint/[email protected])([email protected])([email protected])([email protected]):
|
||||
resolution: {integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==}
|
||||
engines: {node: '>=4'}
|
||||
peerDependencies:
|
||||
'@typescript-eslint/parser': '*'
|
||||
eslint: '*'
|
||||
eslint-import-resolver-node: '*'
|
||||
eslint-import-resolver-typescript: '*'
|
||||
eslint-import-resolver-webpack: '*'
|
||||
peerDependenciesMeta:
|
||||
'@typescript-eslint/parser':
|
||||
optional: true
|
||||
eslint:
|
||||
optional: true
|
||||
eslint-import-resolver-node:
|
||||
optional: true
|
||||
eslint-import-resolver-typescript:
|
||||
optional: true
|
||||
eslint-import-resolver-webpack:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/parser': 5.60.1([email protected])([email protected])
|
||||
debug: 3.2.7
|
||||
eslint: 8.44.0
|
||||
eslint-import-resolver-node: 0.3.7
|
||||
eslint-import-resolver-typescript: 3.5.3([email protected])([email protected])
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/[email protected]([email protected]):
|
||||
resolution: {integrity: sha512-U5OjauLSVcXvlh2La3ptPwIs6JwLPJKP20OQdTDBe2oh0cHvBeEwhQ8mjFrEoCMdQdmMdrSBkSRLG3gLxFjK3A==}
|
||||
@@ -16278,6 +16305,73 @@ packages:
|
||||
- eslint-import-resolver-typescript
|
||||
- eslint-import-resolver-webpack
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/[email protected](@typescript-eslint/[email protected])([email protected])([email protected]):
|
||||
resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==}
|
||||
engines: {node: '>=4'}
|
||||
peerDependencies:
|
||||
'@typescript-eslint/parser': '*'
|
||||
eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8
|
||||
peerDependenciesMeta:
|
||||
'@typescript-eslint/parser':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/parser': 5.60.1([email protected])([email protected])
|
||||
array-includes: 3.1.6
|
||||
array.prototype.flat: 1.3.1
|
||||
array.prototype.flatmap: 1.3.1
|
||||
debug: 3.2.7
|
||||
doctrine: 2.1.0
|
||||
eslint: 8.44.0
|
||||
eslint-import-resolver-node: 0.3.7
|
||||
eslint-module-utils: 2.7.4(@typescript-eslint/[email protected])([email protected])([email protected])([email protected])
|
||||
has: 1.0.3
|
||||
is-core-module: 2.11.0
|
||||
is-glob: 4.0.3
|
||||
minimatch: 3.1.2
|
||||
object.values: 1.1.6
|
||||
resolve: 1.22.1
|
||||
semver: 7.5.3
|
||||
tsconfig-paths: 3.14.2
|
||||
transitivePeerDependencies:
|
||||
- eslint-import-resolver-typescript
|
||||
- eslint-import-resolver-webpack
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/[email protected](@typescript-eslint/[email protected])([email protected]):
|
||||
resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==}
|
||||
engines: {node: '>=4'}
|
||||
peerDependencies:
|
||||
'@typescript-eslint/parser': '*'
|
||||
eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8
|
||||
peerDependenciesMeta:
|
||||
'@typescript-eslint/parser':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/parser': 5.60.1([email protected])([email protected])
|
||||
array-includes: 3.1.6
|
||||
array.prototype.flat: 1.3.1
|
||||
array.prototype.flatmap: 1.3.1
|
||||
debug: 3.2.7
|
||||
doctrine: 2.1.0
|
||||
eslint: 8.43.0
|
||||
eslint-import-resolver-node: 0.3.7
|
||||
eslint-module-utils: 2.7.4(@typescript-eslint/[email protected])([email protected])([email protected])([email protected])
|
||||
has: 1.0.3
|
||||
is-core-module: 2.11.0
|
||||
is-glob: 4.0.3
|
||||
minimatch: 3.1.2
|
||||
object.values: 1.1.6
|
||||
resolve: 1.22.1
|
||||
semver: 7.5.3
|
||||
tsconfig-paths: 3.14.2
|
||||
transitivePeerDependencies:
|
||||
- eslint-import-resolver-typescript
|
||||
- eslint-import-resolver-webpack
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-RzPeSjuw1NYiTSQyFzYl2uTDgiPQWDUmFCiGAMCITmXN627DsWZ9rR4KNzrb8vnk/gLL5qdYr8oxh44xsrcO5Q==}
|
||||
@@ -16323,7 +16417,7 @@ packages:
|
||||
'@typescript-eslint/eslint-plugin': 5.60.1(@typescript-eslint/[email protected])([email protected])([email protected])
|
||||
'@typescript-eslint/utils': 5.60.1([email protected])([email protected])
|
||||
eslint: 8.43.0
|
||||
jest: 29.5.0(@types/[email protected])([email protected])
|
||||
jest: 29.5.0(@types/[email protected])
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
- typescript
|
||||
@@ -16647,8 +16741,8 @@ packages:
|
||||
resolution: {integrity: sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
dependencies:
|
||||
acorn: 8.8.2
|
||||
acorn-jsx: 5.3.2(acorn@8.8.2)
|
||||
acorn: 8.10.0
|
||||
acorn-jsx: 5.3.2(acorn@8.10.0)
|
||||
eslint-visitor-keys: 3.4.1
|
||||
|
||||
/[email protected]:
|
||||
@@ -16967,21 +17061,6 @@ packages:
|
||||
signal-exit: 3.0.7
|
||||
strip-final-newline: 2.0.0
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==}
|
||||
engines: {node: ^14.18.0 || ^16.14.0 || >=18.0.0}
|
||||
dependencies:
|
||||
cross-spawn: 7.0.3
|
||||
get-stream: 6.0.1
|
||||
human-signals: 4.3.1
|
||||
is-stream: 3.0.0
|
||||
merge-stream: 2.0.0
|
||||
npm-run-path: 5.1.0
|
||||
onetime: 6.0.0
|
||||
signal-exit: 3.0.7
|
||||
strip-final-newline: 3.0.0
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw==}
|
||||
dev: true
|
||||
@@ -17875,11 +17954,6 @@ packages:
|
||||
resolution: {integrity: sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==}
|
||||
engines: {node: '>=12'}
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -17915,10 +17989,6 @@ packages:
|
||||
resolution: {integrity: sha512-7yetJWqbS9sbn0vIfliPsFgoXMKn/YMF+Wuiog97x+urnSRRRZ7xB+uVkwGKzRgq9CDFfMQnE9ruL5DHv9c6Xg==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-LF8VeHeR7v+wAbXqfgRlTSX/1BJR9Q1vEMR8JAz1cEg6GX07+zyj3sAdDvYjj/xnlIfVuGgj4qBei1K3hKH+PA==}
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-ab1S1g1EbO7YzauaJLkgLp7DZVAqj9M/dvKlTt8DkXA2tiOIcSMrlVI2J1RZyB5iJVccEscjGn+kpOG9788MHA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -18612,11 +18682,6 @@ packages:
|
||||
resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
|
||||
engines: {node: '>=10.17.0'}
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==}
|
||||
engines: {node: '>=14.18.0'}
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==}
|
||||
dependencies:
|
||||
@@ -18977,11 +19042,6 @@ packages:
|
||||
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==}
|
||||
engines: {node: '>=12'}
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==}
|
||||
dev: false
|
||||
@@ -19105,11 +19165,6 @@ packages:
|
||||
engines: {node: '>=10'}
|
||||
dev: false
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==}
|
||||
engines: {node: '>=12'}
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -19175,11 +19230,6 @@ packages:
|
||||
resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -19523,6 +19573,34 @@ packages:
|
||||
- utf-8-validate
|
||||
dev: false
|
||||
|
||||
/[email protected](@types/[email protected]):
|
||||
resolution: {integrity: sha512-L1KcP1l4HtfwdxXNFCL5bmUbLQiKrakMUriBEcc1Vfz6gx31ORKdreuWvmQVBit+1ss9NNR3yxjwfwzZNdQXJw==}
|
||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0
|
||||
peerDependenciesMeta:
|
||||
node-notifier:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@jest/core': 29.5.0([email protected])
|
||||
'@jest/test-result': 29.5.0
|
||||
'@jest/types': 29.5.0
|
||||
chalk: 4.1.2
|
||||
exit: 0.1.2
|
||||
graceful-fs: 4.2.11
|
||||
import-local: 3.1.0
|
||||
jest-config: 29.5.0(@types/[email protected])([email protected])
|
||||
jest-util: 29.5.0
|
||||
jest-validate: 29.5.0
|
||||
prompts: 2.4.2
|
||||
yargs: 17.7.2
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- supports-color
|
||||
- ts-node
|
||||
dev: true
|
||||
|
||||
/[email protected](@types/[email protected])([email protected]):
|
||||
resolution: {integrity: sha512-L1KcP1l4HtfwdxXNFCL5bmUbLQiKrakMUriBEcc1Vfz6gx31ORKdreuWvmQVBit+1ss9NNR3yxjwfwzZNdQXJw==}
|
||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||
@@ -19551,6 +19629,34 @@ packages:
|
||||
- ts-node
|
||||
dev: true
|
||||
|
||||
/[email protected](@types/[email protected]):
|
||||
resolution: {integrity: sha512-L1KcP1l4HtfwdxXNFCL5bmUbLQiKrakMUriBEcc1Vfz6gx31ORKdreuWvmQVBit+1ss9NNR3yxjwfwzZNdQXJw==}
|
||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0
|
||||
peerDependenciesMeta:
|
||||
node-notifier:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@jest/core': 29.5.0([email protected])
|
||||
'@jest/test-result': 29.5.0
|
||||
'@jest/types': 29.5.0
|
||||
chalk: 4.1.2
|
||||
exit: 0.1.2
|
||||
graceful-fs: 4.2.11
|
||||
import-local: 3.1.0
|
||||
jest-config: 29.5.0(@types/[email protected])([email protected])
|
||||
jest-util: 29.5.0
|
||||
jest-validate: 29.5.0
|
||||
prompts: 2.4.2
|
||||
yargs: 17.7.2
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- supports-color
|
||||
- ts-node
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==}
|
||||
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
|
||||
@@ -20197,7 +20303,7 @@ packages:
|
||||
'@babel/core': 7.22.5
|
||||
'@babel/generator': 7.22.5
|
||||
'@babel/plugin-syntax-jsx': 7.22.5(@babel/[email protected])
|
||||
'@babel/plugin-syntax-typescript': 7.20.0(@babel/[email protected])
|
||||
'@babel/plugin-syntax-typescript': 7.22.5(@babel/[email protected])
|
||||
'@babel/traverse': 7.22.5
|
||||
'@babel/types': 7.22.5
|
||||
'@jest/expect-utils': 29.5.0
|
||||
@@ -20403,6 +20509,26 @@ packages:
|
||||
- utf-8-validate
|
||||
dev: false
|
||||
|
||||
/[email protected](@types/[email protected]):
|
||||
resolution: {integrity: sha512-juMg3he2uru1QoXX078zTa7pO85QyB9xajZc6bU+d9yEGwrKX6+vGmJQ3UdVZsvTEUARIdObzH68QItim6OSSQ==}
|
||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0
|
||||
peerDependenciesMeta:
|
||||
node-notifier:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@jest/core': 29.5.0([email protected])
|
||||
'@jest/types': 29.5.0
|
||||
import-local: 3.1.0
|
||||
jest-cli: 29.5.0(@types/[email protected])
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- supports-color
|
||||
- ts-node
|
||||
dev: true
|
||||
|
||||
/[email protected](@types/[email protected])([email protected]):
|
||||
resolution: {integrity: sha512-juMg3he2uru1QoXX078zTa7pO85QyB9xajZc6bU+d9yEGwrKX6+vGmJQ3UdVZsvTEUARIdObzH68QItim6OSSQ==}
|
||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||
@@ -20423,6 +20549,26 @@ packages:
|
||||
- ts-node
|
||||
dev: true
|
||||
|
||||
/[email protected](@types/[email protected]):
|
||||
resolution: {integrity: sha512-juMg3he2uru1QoXX078zTa7pO85QyB9xajZc6bU+d9yEGwrKX6+vGmJQ3UdVZsvTEUARIdObzH68QItim6OSSQ==}
|
||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0
|
||||
peerDependenciesMeta:
|
||||
node-notifier:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@jest/core': 29.5.0([email protected])
|
||||
'@jest/types': 29.5.0
|
||||
import-local: 3.1.0
|
||||
jest-cli: 29.5.0(@types/[email protected])
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- supports-color
|
||||
- ts-node
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-dZ6Ra7u1G8c4Letq/B5EzAxj4tLFHL+cGtdpR+PVm4yzPDj+lCk+AbivWt1eOM+ikzkowtyV7qSqX6qr3t71Ww==}
|
||||
|
||||
@@ -20859,48 +21005,6 @@ packages:
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-zVVEXLuQIhr1Y7R7YAWx4TZLdvuzk7DnmrsTNL0fax6Z3jrpFcas+vKbzxhhvp6TA55m1SQuWkpzI1qbfDZbAg==}
|
||||
engines: {node: ^14.13.1 || >=16.0.0}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
chalk: 5.2.0
|
||||
cli-truncate: 3.1.0
|
||||
commander: 10.0.1
|
||||
debug: 4.3.4([email protected])
|
||||
execa: 7.1.1
|
||||
lilconfig: 2.1.0
|
||||
listr2: 5.0.8
|
||||
micromatch: 4.0.5
|
||||
normalize-path: 3.0.0
|
||||
object-inspect: 1.12.3
|
||||
pidtree: 0.6.0
|
||||
string-argv: 0.3.1
|
||||
yaml: 2.3.1
|
||||
transitivePeerDependencies:
|
||||
- enquirer
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-mC73LitKHj9w6v30nLNGPetZIlfpUniNSsxxrbaPcWOjDb92SHPzJPi/t+v1YC/lxKz/AJ9egOjww0qUuFxBpA==}
|
||||
engines: {node: ^14.13.1 || >=16.0.0}
|
||||
peerDependencies:
|
||||
enquirer: '>= 2.3.0 < 3'
|
||||
peerDependenciesMeta:
|
||||
enquirer:
|
||||
optional: true
|
||||
dependencies:
|
||||
cli-truncate: 2.1.0
|
||||
colorette: 2.0.19
|
||||
log-update: 4.0.0
|
||||
p-map: 4.0.0
|
||||
rfdc: 1.3.0
|
||||
rxjs: 7.8.0
|
||||
through: 2.3.8
|
||||
wrap-ansi: 7.0.0
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-6ZgxBR9KNroqKb6+htkyBwD90XGRiqKDHVrW/Eh0EZ+l+iC+u+v+w3/BA5NGi4nizAVHGYvQBHUDuSmLjPp7NQ==}
|
||||
dependencies:
|
||||
@@ -21103,16 +21207,6 @@ packages:
|
||||
is-unicode-supported: 1.3.0
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==}
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
ansi-escapes: 4.3.2
|
||||
cli-cursor: 3.1.0
|
||||
slice-ansi: 4.0.0
|
||||
wrap-ansi: 6.2.0
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-/3ER20CTTbahrCrpYfPn7Xavv9diBROZpoXGVZDWMw4b/X4uuUwAC0ki85tgsdMRONURyIJbcOvS94QsUBYPbQ==}
|
||||
hasBin: true
|
||||
@@ -21809,11 +21903,6 @@ packages:
|
||||
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==}
|
||||
engines: {node: '>=12'}
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==}
|
||||
engines: {node: '>=4'}
|
||||
@@ -22477,13 +22566,6 @@ packages:
|
||||
dependencies:
|
||||
path-key: 3.1.1
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
dependencies:
|
||||
path-key: 4.0.0
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
|
||||
dependencies:
|
||||
@@ -22731,13 +22813,6 @@ packages:
|
||||
dependencies:
|
||||
mimic-fn: 2.1.0
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==}
|
||||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
mimic-fn: 4.0.0
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -23146,11 +23221,6 @@ packages:
|
||||
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==}
|
||||
engines: {node: '>=12'}
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
|
||||
|
||||
@@ -23212,12 +23282,6 @@ packages:
|
||||
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
|
||||
engines: {node: '>=8.6'}
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==}
|
||||
engines: {node: '>=0.10'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -25424,10 +25488,6 @@ packages:
|
||||
resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
|
||||
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==}
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-R5KMKHnPAQaZMqLOsyuyUmcIjSeDm+73eoqQpaXA7AZ22BL+6C+1mcUscgOsNd8WVlJuvlgAPsegcx7pjlV0Dg==}
|
||||
hasBin: true
|
||||
@@ -25965,32 +26025,6 @@ packages:
|
||||
astral-regex: 1.0.0
|
||||
is-fullwidth-code-point: 2.0.0
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
ansi-styles: 4.3.0
|
||||
astral-regex: 2.0.0
|
||||
is-fullwidth-code-point: 3.0.0
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==}
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
ansi-styles: 4.3.0
|
||||
astral-regex: 2.0.0
|
||||
is-fullwidth-code-point: 3.0.0
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==}
|
||||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
ansi-styles: 6.2.1
|
||||
is-fullwidth-code-point: 4.0.0
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-8mo9bslnBO3tr5PEVFzMPIWwWnipGS0xVbYf65zxDqfNwmzYn1LpiKNrR6DlClusuvo+hDHd1zKpmfAe83NQSQ==}
|
||||
engines: {node: '>=8.0.0'}
|
||||
@@ -26146,23 +26180,6 @@ packages:
|
||||
lodash: 4.17.21
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==}
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-vx/KoZxm8YNMUqdlw7SGTfqR5pqZ/sUfgOuRtDILiOy/3AvzhAibyUe2cY3OpLs3oRSow9up4yLVtQaM24rbDQ==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
detect-indent: 7.0.1
|
||||
detect-newline: 4.0.0
|
||||
get-stdin: 9.0.0
|
||||
git-hooks-list: 3.1.0
|
||||
globby: 13.1.3
|
||||
is-plain-obj: 4.1.0
|
||||
sort-object-keys: 1.1.3
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==}
|
||||
dev: false
|
||||
@@ -26596,11 +26613,6 @@ packages:
|
||||
resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==}
|
||||
engines: {node: '>=12'}
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==}
|
||||
engines: {node: '>=6.5.0', npm: '>=3'}
|
||||
@@ -27278,37 +27290,6 @@ packages:
|
||||
yn: 3.1.1
|
||||
dev: true
|
||||
|
||||
/[email protected](@types/[email protected])([email protected]):
|
||||
resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
'@swc/core': '>=1.2.50'
|
||||
'@swc/wasm': '>=1.2.50'
|
||||
'@types/node': '*'
|
||||
typescript: '>=2.7'
|
||||
peerDependenciesMeta:
|
||||
'@swc/core':
|
||||
optional: true
|
||||
'@swc/wasm':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@cspotcode/source-map-support': 0.8.1
|
||||
'@tsconfig/node10': 1.0.9
|
||||
'@tsconfig/node12': 1.0.11
|
||||
'@tsconfig/node14': 1.0.3
|
||||
'@tsconfig/node16': 1.0.3
|
||||
'@types/node': 20.4.1
|
||||
acorn: 8.8.2
|
||||
acorn-walk: 8.2.0
|
||||
arg: 4.1.3
|
||||
create-require: 1.1.1
|
||||
diff: 4.0.2
|
||||
make-error: 1.3.6
|
||||
typescript: 5.1.6
|
||||
v8-compile-cache-lib: 3.0.1
|
||||
yn: 3.1.1
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==}
|
||||
dependencies:
|
||||
@@ -29131,6 +29112,7 @@ packages:
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==}
|
||||
engines: {node: '>= 14'}
|
||||
dev: false
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==}
|
||||
@@ -29269,7 +29251,3 @@ packages:
|
||||
version: 5.4.7
|
||||
engines: {node: '>=0.11'}
|
||||
dev: true
|
||||
|
||||
settings:
|
||||
autoInstallPeers: true
|
||||
excludeLinksFromLockfile: false
|
||||
|
||||
@@ -60,6 +60,10 @@
|
||||
"inputs": ["package.json"],
|
||||
"dependsOn": ["^build"]
|
||||
},
|
||||
"@thirdweb-dev/service-utils#build": {
|
||||
"outputs": ["dist/**", "cf-worker/**", "node/**"],
|
||||
"dependsOn": ["^build"]
|
||||
},
|
||||
"test": {
|
||||
"outputs": [],
|
||||
"inputs": ["src/**", "test/**"],
|
||||
|
||||
Reference in New Issue
Block a user