diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml index 10cae9d6..a4c13f94 100644 --- a/.github/workflows/gh-pages.yml +++ b/.github/workflows/gh-pages.yml @@ -9,11 +9,10 @@ jobs: build-and-deploy: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 with: node-version: 16 - registry-url: https://registry.npmjs.org/ - name: Install and Build working-directory: ./docs diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index 9589cf03..bb1c1978 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -8,9 +8,9 @@ jobs: publish-npm: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - - uses: actions/setup-node@v2 + - uses: actions/setup-node@v3 with: node-version: 16 registry-url: https://registry.npmjs.org/ diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a12fbf33..ccde30e3 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -15,14 +15,10 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-node@v2 with: - node-version: 14 - registry-url: https://registry.npmjs.org/ + node-version: 16 - name: Install dependencies - - run: | - npm i -g npm@7 --registry=https://registry.npmjs.org - npm ci + run: npm ci - name: Lint run: | diff --git a/examples/browser/.browserslistrc b/examples/browser/.browserslistrc new file mode 100644 index 00000000..969bb8e5 --- /dev/null +++ b/examples/browser/.browserslistrc @@ -0,0 +1 @@ +defaults and supports es6-module diff --git a/examples/browser/package-lock.json b/examples/browser/package-lock.json index 46824851..4dac24f7 100644 --- a/examples/browser/package-lock.json +++ b/examples/browser/package-lock.json @@ -16,7 +16,7 @@ "redux-saga": "^1.2.1" }, "devDependencies": { - "@swc/core": "^1.3.11", + "@swc/core": "^1.3.35", "@types/react": "^17.0.40", "@types/react-dom": "^17.0.13", "css-loader": "^6.7.1", @@ -280,14 +280,11 @@ } }, "node_modules/@swc/core": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.11.tgz", - "integrity": "sha512-lnCnnnNCsnbrhW/gwkoN0sAeIqOyoHLS4ZB20xmPJjKVfvTnJrAcNnLSiwlYdcoUSFqT2GYZjUAG6usEzRQASA==", + "version": "1.3.35", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.35.tgz", + "integrity": "sha512-KmiBin0XSVzJhzX19zTiCqmLslZ40Cl7zqskJcTDeIrRhfgKdiAsxzYUanJgMJIRjYtl9Kcg1V/Ip2o2wL8v3w==", "dev": true, "hasInstallScript": true, - "bin": { - "swcx": "run_swcx.js" - }, "engines": { "node": ">=10" }, @@ -296,70 +293,22 @@ "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "@swc/core-android-arm-eabi": "1.3.11", - "@swc/core-android-arm64": "1.3.11", - "@swc/core-darwin-arm64": "1.3.11", - "@swc/core-darwin-x64": "1.3.11", - "@swc/core-freebsd-x64": "1.3.11", - "@swc/core-linux-arm-gnueabihf": "1.3.11", - "@swc/core-linux-arm64-gnu": "1.3.11", - "@swc/core-linux-arm64-musl": "1.3.11", - "@swc/core-linux-x64-gnu": "1.3.11", - "@swc/core-linux-x64-musl": "1.3.11", - "@swc/core-win32-arm64-msvc": "1.3.11", - "@swc/core-win32-ia32-msvc": "1.3.11", - "@swc/core-win32-x64-msvc": "1.3.11" - } - }, - "node_modules/@swc/core-android-arm-eabi": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@swc/core-android-arm-eabi/-/core-android-arm-eabi-1.3.11.tgz", - "integrity": "sha512-LC9JlMcdFmTU94KKmQkJKaPSeVmYTfVm2rKGESMiFrgIjopXL/Zeg+XHA97ucnh5iUMkWIpXAMzSOaVRs33K5g==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "dependencies": { - "@swc/wasm": "1.2.122" - }, - "engines": { - "node": ">=10" + "@swc/core-darwin-arm64": "1.3.35", + "@swc/core-darwin-x64": "1.3.35", + "@swc/core-linux-arm-gnueabihf": "1.3.35", + "@swc/core-linux-arm64-gnu": "1.3.35", + "@swc/core-linux-arm64-musl": "1.3.35", + "@swc/core-linux-x64-gnu": "1.3.35", + "@swc/core-linux-x64-musl": "1.3.35", + "@swc/core-win32-arm64-msvc": "1.3.35", + "@swc/core-win32-ia32-msvc": "1.3.35", + "@swc/core-win32-x64-msvc": "1.3.35" } }, - "node_modules/@swc/core-android-arm64": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@swc/core-android-arm64/-/core-android-arm64-1.3.11.tgz", - "integrity": "sha512-M7FamR3kFpVTyTw73FzKcOZmS7/TWHX75eqtwBTaU9fW4shf0KTLr/h9DnMxNKAnwUMeub/lqlINUe5EKFIKwQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "dependencies": { - "@swc/wasm": "1.2.130" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-android-arm64/node_modules/@swc/wasm": { - "version": "1.2.130", - "resolved": "https://registry.npmjs.org/@swc/wasm/-/wasm-1.2.130.tgz", - "integrity": "sha512-rNcJsBxS70+pv8YUWwf5fRlWX6JoY/HJc25HD/F8m6Kv7XhJdqPPMhyX6TKkUBPAG7TWlZYoxa+rHAjPy4Cj3Q==", - "dev": true, - "optional": true - }, "node_modules/@swc/core-darwin-arm64": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.11.tgz", - "integrity": "sha512-LOoiw3uQDuoKBLW3Mn8p6wIccpYjAoDI3ROdto4MksLQSraHMufXY8bqqncfVuy1750XZmC1qnU39RC3yihPfA==", + "version": "1.3.35", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.35.tgz", + "integrity": "sha512-zQUFkHx4gZpu0uo2IspvPnKsz8bsdXd5bC33xwjtoAI1cpLerDyqo4v2zIahEp+FdKZjyVsLHtfJiQiA1Qka3A==", "cpu": [ "arm64" ], @@ -373,9 +322,9 @@ } }, "node_modules/@swc/core-darwin-x64": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.11.tgz", - "integrity": "sha512-ycjrEbWmpU8MTDdVLdf76ClxQCSTfNqSoP59hieLzhmXpXUa7Oy4sN/v6WSQgp4I1euGs1Wp5kPU5hH5f7XBJQ==", + "version": "1.3.35", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.35.tgz", + "integrity": "sha512-oOSkSGWtALovaw22lNevKD434OQTPf8X+dVPvPMrJXJpJ34dWDlFWpLntoc+arvKLNZ7LQmTuk8rR1hkrAY7cw==", "cpu": [ "x64" ], @@ -388,36 +337,10 @@ "node": ">=10" } }, - "node_modules/@swc/core-freebsd-x64": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@swc/core-freebsd-x64/-/core-freebsd-x64-1.3.11.tgz", - "integrity": "sha512-02uqYktPp6WmZfZ2Crc/yIVOcgANtjo8ciHcT7yLHvz7v+S7gx1I2tyNGUFtTX5hcR2IFNGrL8Yj4DvpTABFHg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "dependencies": { - "@swc/wasm": "1.2.130" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-freebsd-x64/node_modules/@swc/wasm": { - "version": "1.2.130", - "resolved": "https://registry.npmjs.org/@swc/wasm/-/wasm-1.2.130.tgz", - "integrity": "sha512-rNcJsBxS70+pv8YUWwf5fRlWX6JoY/HJc25HD/F8m6Kv7XhJdqPPMhyX6TKkUBPAG7TWlZYoxa+rHAjPy4Cj3Q==", - "dev": true, - "optional": true - }, "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.11.tgz", - "integrity": "sha512-nZ2T/gPFncsIiFGhVeVY9vRCTX0hTdqso8OEvFhSwRfRvcEYOpb/rhMG09are7YoB44GMiku5tSzEiNmvT3GuQ==", + "version": "1.3.35", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.35.tgz", + "integrity": "sha512-Yie8k00O6O8BCATS/xeKStquV4OYSskUGRDXBQVDw1FrE23PHaSeHCgg4q6iNZjJzXCOJbaTCKnYoIDn9DMf7A==", "cpu": [ "arm" ], @@ -426,24 +349,14 @@ "os": [ "linux" ], - "dependencies": { - "@swc/wasm": "1.2.130" - }, "engines": { "node": ">=10" } }, - "node_modules/@swc/core-linux-arm-gnueabihf/node_modules/@swc/wasm": { - "version": "1.2.130", - "resolved": "https://registry.npmjs.org/@swc/wasm/-/wasm-1.2.130.tgz", - "integrity": "sha512-rNcJsBxS70+pv8YUWwf5fRlWX6JoY/HJc25HD/F8m6Kv7XhJdqPPMhyX6TKkUBPAG7TWlZYoxa+rHAjPy4Cj3Q==", - "dev": true, - "optional": true - }, "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.11.tgz", - "integrity": "sha512-EWEd8NnGwhykEDFIet/r4Fcfr6805ecnBniHZWmG8UVYUp5tz7LYEMZesxCxa0+aGVpCmxHL5/Cdk1uEIrVIzg==", + "version": "1.3.35", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.35.tgz", + "integrity": "sha512-Zlv3WHa/4x2p51HSvjUWXHfSe1Gl2prqImUZJc8NZOlj75BFzVuR0auhQ+LbwvIQ3gaA1LODX9lyS9wXL3yjxA==", "cpu": [ "arm64" ], @@ -457,9 +370,9 @@ } }, "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.11.tgz", - "integrity": "sha512-ms7CLj2+8sfTM2QnnwqDheYRky9rgPpX2hXmc0KltX+AiSAs7WURjn2JwXWkaICDzXL+djennfswxSspJ53knw==", + "version": "1.3.35", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.35.tgz", + "integrity": "sha512-u6tCYsrSyZ8U+4jLMA/O82veBfLy2aUpn51WxQaeH7wqZGy9TGSJXoO8vWxARQ6b72vjsnKDJHP4MD8hFwcctg==", "cpu": [ "arm64" ], @@ -473,9 +386,9 @@ } }, "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.11.tgz", - "integrity": "sha512-Fq5/QEY0IbzpIrqlvQT59aMf+nLk//esL3Aj4nvZdsvF4iZaD2oHtXW+/MBi0i1HV9OBWApGZMygYNVS0uVZkQ==", + "version": "1.3.35", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.35.tgz", + "integrity": "sha512-Dtxf2IbeH7XlNhP1Qt2/MvUPkpEbn7hhGfpSRs4ot8D3Vf5QEX4S/QtC1OsFWuciiYgHAT1Ybjt4xZic9DSkmA==", "cpu": [ "x64" ], @@ -489,9 +402,9 @@ } }, "node_modules/@swc/core-linux-x64-musl": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.11.tgz", - "integrity": "sha512-S/KoEgRHwGhs7VunHiz4jLrnFOJvqZe391j2MiYN1p2EThoGI3rvwcUoHkoxLCXVuDbi4E91qodOheaMGetWNA==", + "version": "1.3.35", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.35.tgz", + "integrity": "sha512-4XavNJ60GprjpTiESCu5daJUnmErixPAqDitJSMu4TV32LNIE8G00S9pDLXinDTW1rgcGtQdq1NLkNRmwwovtg==", "cpu": [ "x64" ], @@ -505,9 +418,9 @@ } }, "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.11.tgz", - "integrity": "sha512-fFby7KOQIxolR6w4Gie8MSkgQ3ee6j3r7A6PX4ekzu+509QsZogLPZnWFTJ8WFo7ui0tx/ocA5X8BV4ZNBVlKQ==", + "version": "1.3.35", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.35.tgz", + "integrity": "sha512-dNGfKCUSX2M4qVyaS80Lyos0FkXyHRCvrdQ2Y4Hrg3FVokiuw3yY6fLohpUfQ5ws3n2A39dh7jGDeh34+l0sGA==", "cpu": [ "arm64" ], @@ -516,24 +429,14 @@ "os": [ "win32" ], - "dependencies": { - "@swc/wasm": "1.2.130" - }, "engines": { "node": ">=10" } }, - "node_modules/@swc/core-win32-arm64-msvc/node_modules/@swc/wasm": { - "version": "1.2.130", - "resolved": "https://registry.npmjs.org/@swc/wasm/-/wasm-1.2.130.tgz", - "integrity": "sha512-rNcJsBxS70+pv8YUWwf5fRlWX6JoY/HJc25HD/F8m6Kv7XhJdqPPMhyX6TKkUBPAG7TWlZYoxa+rHAjPy4Cj3Q==", - "dev": true, - "optional": true - }, "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.11.tgz", - "integrity": "sha512-fii7Y33S9Z5oZ/BTsXa8Ou/RZ4T/ZsAOFpG7mMvifpdAP6LVWdhLoNy7SeeEHTEAWGcWNA/FslA6p2WETvEEfA==", + "version": "1.3.35", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.35.tgz", + "integrity": "sha512-ChuPSrDR+JBf7S7dEKPicnG8A3bM0uWPsW2vG+V2wH4iNfNxKVemESHosmYVeEZXqMpomNMvLyeHep1rjRsc0Q==", "cpu": [ "ia32" ], @@ -542,24 +445,14 @@ "os": [ "win32" ], - "dependencies": { - "@swc/wasm": "1.2.130" - }, "engines": { "node": ">=10" } }, - "node_modules/@swc/core-win32-ia32-msvc/node_modules/@swc/wasm": { - "version": "1.2.130", - "resolved": "https://registry.npmjs.org/@swc/wasm/-/wasm-1.2.130.tgz", - "integrity": "sha512-rNcJsBxS70+pv8YUWwf5fRlWX6JoY/HJc25HD/F8m6Kv7XhJdqPPMhyX6TKkUBPAG7TWlZYoxa+rHAjPy4Cj3Q==", - "dev": true, - "optional": true - }, "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.11.tgz", - "integrity": "sha512-cDF4qBQLf3U0KypnLn3T1HtE12QmEplPGjWs2Xd/hzVkjsPixVR8XIgLlczsj7Pk7Of7VDnUDLIl52aIdgTm8w==", + "version": "1.3.35", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.35.tgz", + "integrity": "sha512-/RvphT4WfuGfIK84Ha0dovdPrKB1bW/mc+dtdmhv2E3EGkNc5FoueNwYmXWRimxnU7X0X7IkcRhyKB4G5DeAmg==", "cpu": [ "x64" ], @@ -572,13 +465,6 @@ "node": ">=10" } }, - "node_modules/@swc/wasm": { - "version": "1.2.122", - "resolved": "https://registry.npmjs.org/@swc/wasm/-/wasm-1.2.122.tgz", - "integrity": "sha512-sM1VCWQxmNhFtdxME+8UXNyPNhxNu7zdb6ikWpz0YKAQQFRGT5ThZgJrubEpah335SUToNg8pkdDF7ibVCjxbQ==", - "dev": true, - "optional": true - }, "node_modules/@types/body-parser": { "version": "1.19.2", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", @@ -5599,184 +5485,90 @@ } }, "@swc/core": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.11.tgz", - "integrity": "sha512-lnCnnnNCsnbrhW/gwkoN0sAeIqOyoHLS4ZB20xmPJjKVfvTnJrAcNnLSiwlYdcoUSFqT2GYZjUAG6usEzRQASA==", - "dev": true, - "requires": { - "@swc/core-android-arm-eabi": "1.3.11", - "@swc/core-android-arm64": "1.3.11", - "@swc/core-darwin-arm64": "1.3.11", - "@swc/core-darwin-x64": "1.3.11", - "@swc/core-freebsd-x64": "1.3.11", - "@swc/core-linux-arm-gnueabihf": "1.3.11", - "@swc/core-linux-arm64-gnu": "1.3.11", - "@swc/core-linux-arm64-musl": "1.3.11", - "@swc/core-linux-x64-gnu": "1.3.11", - "@swc/core-linux-x64-musl": "1.3.11", - "@swc/core-win32-arm64-msvc": "1.3.11", - "@swc/core-win32-ia32-msvc": "1.3.11", - "@swc/core-win32-x64-msvc": "1.3.11" - } - }, - "@swc/core-android-arm-eabi": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@swc/core-android-arm-eabi/-/core-android-arm-eabi-1.3.11.tgz", - "integrity": "sha512-LC9JlMcdFmTU94KKmQkJKaPSeVmYTfVm2rKGESMiFrgIjopXL/Zeg+XHA97ucnh5iUMkWIpXAMzSOaVRs33K5g==", + "version": "1.3.35", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.35.tgz", + "integrity": "sha512-KmiBin0XSVzJhzX19zTiCqmLslZ40Cl7zqskJcTDeIrRhfgKdiAsxzYUanJgMJIRjYtl9Kcg1V/Ip2o2wL8v3w==", "dev": true, - "optional": true, "requires": { - "@swc/wasm": "1.2.122" - } - }, - "@swc/core-android-arm64": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@swc/core-android-arm64/-/core-android-arm64-1.3.11.tgz", - "integrity": "sha512-M7FamR3kFpVTyTw73FzKcOZmS7/TWHX75eqtwBTaU9fW4shf0KTLr/h9DnMxNKAnwUMeub/lqlINUe5EKFIKwQ==", - "dev": true, - "optional": true, - "requires": { - "@swc/wasm": "1.2.130" - }, - "dependencies": { - "@swc/wasm": { - "version": "1.2.130", - "resolved": "https://registry.npmjs.org/@swc/wasm/-/wasm-1.2.130.tgz", - "integrity": "sha512-rNcJsBxS70+pv8YUWwf5fRlWX6JoY/HJc25HD/F8m6Kv7XhJdqPPMhyX6TKkUBPAG7TWlZYoxa+rHAjPy4Cj3Q==", - "dev": true, - "optional": true - } + "@swc/core-darwin-arm64": "1.3.35", + "@swc/core-darwin-x64": "1.3.35", + "@swc/core-linux-arm-gnueabihf": "1.3.35", + "@swc/core-linux-arm64-gnu": "1.3.35", + "@swc/core-linux-arm64-musl": "1.3.35", + "@swc/core-linux-x64-gnu": "1.3.35", + "@swc/core-linux-x64-musl": "1.3.35", + "@swc/core-win32-arm64-msvc": "1.3.35", + "@swc/core-win32-ia32-msvc": "1.3.35", + "@swc/core-win32-x64-msvc": "1.3.35" } }, "@swc/core-darwin-arm64": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.11.tgz", - "integrity": "sha512-LOoiw3uQDuoKBLW3Mn8p6wIccpYjAoDI3ROdto4MksLQSraHMufXY8bqqncfVuy1750XZmC1qnU39RC3yihPfA==", + "version": "1.3.35", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.35.tgz", + "integrity": "sha512-zQUFkHx4gZpu0uo2IspvPnKsz8bsdXd5bC33xwjtoAI1cpLerDyqo4v2zIahEp+FdKZjyVsLHtfJiQiA1Qka3A==", "dev": true, "optional": true }, "@swc/core-darwin-x64": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.11.tgz", - "integrity": "sha512-ycjrEbWmpU8MTDdVLdf76ClxQCSTfNqSoP59hieLzhmXpXUa7Oy4sN/v6WSQgp4I1euGs1Wp5kPU5hH5f7XBJQ==", + "version": "1.3.35", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.35.tgz", + "integrity": "sha512-oOSkSGWtALovaw22lNevKD434OQTPf8X+dVPvPMrJXJpJ34dWDlFWpLntoc+arvKLNZ7LQmTuk8rR1hkrAY7cw==", "dev": true, "optional": true }, - "@swc/core-freebsd-x64": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@swc/core-freebsd-x64/-/core-freebsd-x64-1.3.11.tgz", - "integrity": "sha512-02uqYktPp6WmZfZ2Crc/yIVOcgANtjo8ciHcT7yLHvz7v+S7gx1I2tyNGUFtTX5hcR2IFNGrL8Yj4DvpTABFHg==", - "dev": true, - "optional": true, - "requires": { - "@swc/wasm": "1.2.130" - }, - "dependencies": { - "@swc/wasm": { - "version": "1.2.130", - "resolved": "https://registry.npmjs.org/@swc/wasm/-/wasm-1.2.130.tgz", - "integrity": "sha512-rNcJsBxS70+pv8YUWwf5fRlWX6JoY/HJc25HD/F8m6Kv7XhJdqPPMhyX6TKkUBPAG7TWlZYoxa+rHAjPy4Cj3Q==", - "dev": true, - "optional": true - } - } - }, "@swc/core-linux-arm-gnueabihf": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.11.tgz", - "integrity": "sha512-nZ2T/gPFncsIiFGhVeVY9vRCTX0hTdqso8OEvFhSwRfRvcEYOpb/rhMG09are7YoB44GMiku5tSzEiNmvT3GuQ==", + "version": "1.3.35", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.35.tgz", + "integrity": "sha512-Yie8k00O6O8BCATS/xeKStquV4OYSskUGRDXBQVDw1FrE23PHaSeHCgg4q6iNZjJzXCOJbaTCKnYoIDn9DMf7A==", "dev": true, - "optional": true, - "requires": { - "@swc/wasm": "1.2.130" - }, - "dependencies": { - "@swc/wasm": { - "version": "1.2.130", - "resolved": "https://registry.npmjs.org/@swc/wasm/-/wasm-1.2.130.tgz", - "integrity": "sha512-rNcJsBxS70+pv8YUWwf5fRlWX6JoY/HJc25HD/F8m6Kv7XhJdqPPMhyX6TKkUBPAG7TWlZYoxa+rHAjPy4Cj3Q==", - "dev": true, - "optional": true - } - } + "optional": true }, "@swc/core-linux-arm64-gnu": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.11.tgz", - "integrity": "sha512-EWEd8NnGwhykEDFIet/r4Fcfr6805ecnBniHZWmG8UVYUp5tz7LYEMZesxCxa0+aGVpCmxHL5/Cdk1uEIrVIzg==", + "version": "1.3.35", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.35.tgz", + "integrity": "sha512-Zlv3WHa/4x2p51HSvjUWXHfSe1Gl2prqImUZJc8NZOlj75BFzVuR0auhQ+LbwvIQ3gaA1LODX9lyS9wXL3yjxA==", "dev": true, "optional": true }, "@swc/core-linux-arm64-musl": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.11.tgz", - "integrity": "sha512-ms7CLj2+8sfTM2QnnwqDheYRky9rgPpX2hXmc0KltX+AiSAs7WURjn2JwXWkaICDzXL+djennfswxSspJ53knw==", + "version": "1.3.35", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.35.tgz", + "integrity": "sha512-u6tCYsrSyZ8U+4jLMA/O82veBfLy2aUpn51WxQaeH7wqZGy9TGSJXoO8vWxARQ6b72vjsnKDJHP4MD8hFwcctg==", "dev": true, "optional": true }, "@swc/core-linux-x64-gnu": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.11.tgz", - "integrity": "sha512-Fq5/QEY0IbzpIrqlvQT59aMf+nLk//esL3Aj4nvZdsvF4iZaD2oHtXW+/MBi0i1HV9OBWApGZMygYNVS0uVZkQ==", + "version": "1.3.35", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.35.tgz", + "integrity": "sha512-Dtxf2IbeH7XlNhP1Qt2/MvUPkpEbn7hhGfpSRs4ot8D3Vf5QEX4S/QtC1OsFWuciiYgHAT1Ybjt4xZic9DSkmA==", "dev": true, "optional": true }, "@swc/core-linux-x64-musl": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.11.tgz", - "integrity": "sha512-S/KoEgRHwGhs7VunHiz4jLrnFOJvqZe391j2MiYN1p2EThoGI3rvwcUoHkoxLCXVuDbi4E91qodOheaMGetWNA==", + "version": "1.3.35", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.35.tgz", + "integrity": "sha512-4XavNJ60GprjpTiESCu5daJUnmErixPAqDitJSMu4TV32LNIE8G00S9pDLXinDTW1rgcGtQdq1NLkNRmwwovtg==", "dev": true, "optional": true }, "@swc/core-win32-arm64-msvc": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.11.tgz", - "integrity": "sha512-fFby7KOQIxolR6w4Gie8MSkgQ3ee6j3r7A6PX4ekzu+509QsZogLPZnWFTJ8WFo7ui0tx/ocA5X8BV4ZNBVlKQ==", + "version": "1.3.35", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.35.tgz", + "integrity": "sha512-dNGfKCUSX2M4qVyaS80Lyos0FkXyHRCvrdQ2Y4Hrg3FVokiuw3yY6fLohpUfQ5ws3n2A39dh7jGDeh34+l0sGA==", "dev": true, - "optional": true, - "requires": { - "@swc/wasm": "1.2.130" - }, - "dependencies": { - "@swc/wasm": { - "version": "1.2.130", - "resolved": "https://registry.npmjs.org/@swc/wasm/-/wasm-1.2.130.tgz", - "integrity": "sha512-rNcJsBxS70+pv8YUWwf5fRlWX6JoY/HJc25HD/F8m6Kv7XhJdqPPMhyX6TKkUBPAG7TWlZYoxa+rHAjPy4Cj3Q==", - "dev": true, - "optional": true - } - } + "optional": true }, "@swc/core-win32-ia32-msvc": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.11.tgz", - "integrity": "sha512-fii7Y33S9Z5oZ/BTsXa8Ou/RZ4T/ZsAOFpG7mMvifpdAP6LVWdhLoNy7SeeEHTEAWGcWNA/FslA6p2WETvEEfA==", - "dev": true, - "optional": true, - "requires": { - "@swc/wasm": "1.2.130" - }, - "dependencies": { - "@swc/wasm": { - "version": "1.2.130", - "resolved": "https://registry.npmjs.org/@swc/wasm/-/wasm-1.2.130.tgz", - "integrity": "sha512-rNcJsBxS70+pv8YUWwf5fRlWX6JoY/HJc25HD/F8m6Kv7XhJdqPPMhyX6TKkUBPAG7TWlZYoxa+rHAjPy4Cj3Q==", - "dev": true, - "optional": true - } - } - }, - "@swc/core-win32-x64-msvc": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.11.tgz", - "integrity": "sha512-cDF4qBQLf3U0KypnLn3T1HtE12QmEplPGjWs2Xd/hzVkjsPixVR8XIgLlczsj7Pk7Of7VDnUDLIl52aIdgTm8w==", + "version": "1.3.35", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.35.tgz", + "integrity": "sha512-ChuPSrDR+JBf7S7dEKPicnG8A3bM0uWPsW2vG+V2wH4iNfNxKVemESHosmYVeEZXqMpomNMvLyeHep1rjRsc0Q==", "dev": true, "optional": true }, - "@swc/wasm": { - "version": "1.2.122", - "resolved": "https://registry.npmjs.org/@swc/wasm/-/wasm-1.2.122.tgz", - "integrity": "sha512-sM1VCWQxmNhFtdxME+8UXNyPNhxNu7zdb6ikWpz0YKAQQFRGT5ThZgJrubEpah335SUToNg8pkdDF7ibVCjxbQ==", + "@swc/core-win32-x64-msvc": { + "version": "1.3.35", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.35.tgz", + "integrity": "sha512-/RvphT4WfuGfIK84Ha0dovdPrKB1bW/mc+dtdmhv2E3EGkNc5FoueNwYmXWRimxnU7X0X7IkcRhyKB4G5DeAmg==", "dev": true, "optional": true }, diff --git a/examples/browser/package.json b/examples/browser/package.json index 49518b6a..d2f76021 100644 --- a/examples/browser/package.json +++ b/examples/browser/package.json @@ -18,7 +18,7 @@ "redux-saga": "^1.2.1" }, "devDependencies": { - "@swc/core": "^1.3.11", + "@swc/core": "^1.3.35", "@types/react": "^17.0.40", "@types/react-dom": "^17.0.13", "css-loader": "^6.7.1", diff --git a/examples/browser/src/di/app.ts b/examples/browser/src/di/app.ts index 8b312198..d8f5d6ad 100644 --- a/examples/browser/src/di/app.ts +++ b/examples/browser/src/di/app.ts @@ -2,7 +2,7 @@ import { createApplication, Resolve } from '@sima-land/isomorph/di'; import { sauce } from '@sima-land/isomorph/http-client/sauce'; import { PresetBrowser } from '@sima-land/isomorph/preset/browser'; import { KnownToken } from '@sima-land/isomorph/tokens'; -import { Api, Config } from '../types'; +import { HttpApi, Config } from '../types'; import { TOKEN } from './tokens'; export function ExampleApp() { @@ -25,7 +25,7 @@ export function provideConfig(resolve: Resolve): Config { }; } -export function provideApi(resolve: Resolve): Api { +export function provideApi(resolve: Resolve): HttpApi { const knownHosts = resolve(KnownToken.Http.Api.knownHosts); const createClient = resolve(KnownToken.Http.Client.factory); const client = sauce(createClient({ baseURL: knownHosts.get('simaV3') })); diff --git a/examples/browser/src/di/tokens.ts b/examples/browser/src/di/tokens.ts index 503c4a8b..5025449e 100644 --- a/examples/browser/src/di/tokens.ts +++ b/examples/browser/src/di/tokens.ts @@ -1,7 +1,7 @@ import { createToken } from '@sima-land/isomorph/di'; -import type { Api, Config } from '../types'; +import type { HttpApi, Config } from '../types'; export const TOKEN = { config: createToken('app/config'), - api: createToken('app/api'), + api: createToken('app/api'), } as const; diff --git a/examples/browser/src/sagas/index.ts b/examples/browser/src/sagas/index.ts index cc673e7f..a256ba8a 100644 --- a/examples/browser/src/sagas/index.ts +++ b/examples/browser/src/sagas/index.ts @@ -1,10 +1,10 @@ import { call, put, takeLatest } from 'redux-saga/effects'; -import { Api } from '../types'; +import { HttpApi } from '../types'; import { User } from '../reducers/user'; import { Currency } from '../reducers/currency'; export interface SagaOptions { - api: Api; + api: HttpApi; } export function* rootSaga(options: SagaOptions): Generator { diff --git a/examples/browser/src/types.ts b/examples/browser/src/types.ts index d9f3399c..6b033083 100644 --- a/examples/browser/src/types.ts +++ b/examples/browser/src/types.ts @@ -5,7 +5,7 @@ export interface Config extends BaseConfig { devtoolsEnabled: boolean; } -export interface Api { +export interface HttpApi { getUser(): Promise>; getCurrencies(): Promise>; } diff --git a/examples/browser/webpack.config.js b/examples/browser/webpack.config.js index a9b93727..2ad0b6be 100644 --- a/examples/browser/webpack.config.js +++ b/examples/browser/webpack.config.js @@ -8,6 +8,7 @@ const env = createConfigSource(); module.exports = { mode: 'development', + devtool: 'source-map', target: 'web', entry: './src/index.tsx', output: { diff --git a/src/config/index.ts b/src/config/index.ts new file mode 100644 index 00000000..4dc74f78 --- /dev/null +++ b/src/config/index.ts @@ -0,0 +1,3 @@ +export { ConfigSource, BaseConfig } from './types'; +export { createConfigSource } from './source'; +export { createBaseConfig } from './base'; diff --git a/src/config/node.ts b/src/config/node.ts deleted file mode 100644 index 04c52ef9..00000000 --- a/src/config/node.ts +++ /dev/null @@ -1,30 +0,0 @@ -import type { ConfigSource } from './types'; -import { Env } from '@humanwhocodes/env'; -import { config } from 'dotenv'; -import path from 'path'; - -declare const __ISOMORPH_ENV__: unknown; - -/** - * Возвращает новый источник конфигурации для Node.js. - * @return Источник. - */ -export function createConfigSource(): ConfigSource { - const envName = process.env.NODE_ENV; - - // подключаем соответствующий среде файл со значениями по умолчанию - if (envName) { - config({ path: path.resolve(process.cwd(), `./.env.${envName}`) }); - } - - // после подключения env-файла формируем источник данных окружения - const source: Record = { ...process.env }; - - // докидываем зашиваемые переменные окружения - // @todo возможно стоит делать так чтобы переменные из process.env имели приоритет - if (typeof __ISOMORPH_ENV__ !== 'undefined') { - Object.assign(source, __ISOMORPH_ENV__); - } - - return new Env(source); -} diff --git a/src/config/browser.ts b/src/config/source.ts similarity index 56% rename from src/config/browser.ts rename to src/config/source.ts index aff7031c..d0f06a3c 100644 --- a/src/config/browser.ts +++ b/src/config/source.ts @@ -3,16 +3,21 @@ import { Env } from '@humanwhocodes/env'; declare const __ISOMORPH_ENV__: unknown; +interface Dictionary { + readonly [key: string]: string | undefined; +} + /** - * Возвращает новый источник конфигурации для браузера. + * Возвращает новый источник конфигурации. + * @param options Опции. * @return Источник. */ -export function createConfigSource(): ConfigSource { - const source: Record = {}; +export function createConfigSource({ environment }: { environment: Dictionary }): ConfigSource { + const source: Dictionary = {}; - // докидываем process если он предоставлен сборкой + // берем все переменные из предоставленной среды if (typeof process !== 'undefined') { - Object.assign(source, process.env); + Object.assign(source, environment); } // докидываем зашиваемые переменные окружения diff --git a/src/di/__test__/application.test.ts b/src/di/__test__/application.test.ts index 0be6fa64..3bb188de 100644 --- a/src/di/__test__/application.test.ts +++ b/src/di/__test__/application.test.ts @@ -1,5 +1,5 @@ import { createApplication, CURRENT_APP } from '../application'; -import { AlreadyBoundError } from '../errors'; +import { AlreadyBoundError, CircularDependencyError } from '../errors'; import { createPreset } from '../preset'; import { createToken } from '../token'; @@ -57,11 +57,11 @@ describe('Application', () => { expect(() => { app.bind(token).toValue(23); - }).not.toThrow(new AlreadyBoundError(token)); + }).not.toThrow(); expect(() => { app.bind(token).toValue(34); - }).toThrow(new AlreadyBoundError(token)); + }).toThrow(new AlreadyBoundError(token, 'Application')); }); it('should handle presets', () => { @@ -181,7 +181,39 @@ describe('Application', () => { expect(spy).toBeCalledWith(17); }); - // @todo Проверка рекурсии не работает, надо починить и зафиксировать тестами + it('should properly handle circular dependencies', () => { + const TOKEN = { + config: createToken('config'), + logger: createToken('logger'), + } as const; + + const app = createApplication(); + + app.bind(TOKEN.config).toProvider(resolve => { + const logger = resolve(TOKEN.logger); + + logger.info('Config created'); + + return { + appName: 'test app', + }; + }); + + app.bind(TOKEN.logger).toProvider(resolve => { + const config = resolve(TOKEN.config); + + return { + info(message: any) { + // eslint-disable-next-line no-console + console.log(config.appName, message); + }, + }; + }); + + expect(() => app.get(TOKEN.config)).toThrow( + new CircularDependencyError([TOKEN.config, TOKEN.logger, TOKEN.config], 'Application'), + ); + }); it('should throw exception properly when component not found in parent app too', () => { const TOKEN = { @@ -208,4 +240,19 @@ describe('Application', () => { child.get(TOKEN.client); }).toThrow('Nothing bound to Token(config)'); }); + + it('should get component from cache', () => { + const app = createApplication(); + const token = createToken<{ id: number }>('foo'); + + const value = { id: 123 }; + app.bind(token).toValue(value); + + const first = app.get(token); + const second = app.get(token); + + expect(Object.is(value, first)).toBe(true); + expect(Object.is(value, second)).toBe(true); + expect(Object.is(first, second)).toBe(true); + }); }); diff --git a/src/di/__test__/container.test.ts b/src/di/__test__/container.test.ts index 628c8536..06c8bbec 100644 --- a/src/di/__test__/container.test.ts +++ b/src/di/__test__/container.test.ts @@ -1,5 +1,5 @@ import { createContainer } from '../container'; -import { AlreadyBoundError, CircularDependencyError } from '../errors'; +import { AlreadyBoundError, CircularDependencyError, NothingBoundError } from '../errors'; import { createToken } from '../token'; describe('Container', () => { @@ -91,4 +91,13 @@ describe('Container', () => { container.get(TOKEN.bar); }).toThrow(new CircularDependencyError([TOKEN.bar, TOKEN.foo, TOKEN.baz, TOKEN.bar])); }); + + it('should throw error when nothing boud to token', () => { + const container = createContainer(); + const token = createToken('test'); + + expect(() => { + container.get(token); + }).toThrow(new NothingBoundError(token)); + }); }); diff --git a/src/di/__test__/errors.test.ts b/src/di/__test__/errors.test.ts index 28e0af42..26415bcb 100644 --- a/src/di/__test__/errors.test.ts +++ b/src/di/__test__/errors.test.ts @@ -2,25 +2,55 @@ import { AlreadyBoundError, CircularDependencyError, NothingBoundError } from '. import { createToken } from '../token'; describe('NothingBoundError', () => { + const token = createToken('something'); + it('should show message properly', () => { - const error = new NothingBoundError(createToken('some-component')); - expect(error.message).toBe('Nothing bound to Token(some-component)'); + const error = new NothingBoundError(token); + + expect(error.message).toBe('Nothing bound to Token(something) in [unknown container]'); + }); + + it('should handle name', () => { + const error = new NothingBoundError(token, 'MyContainer'); + + expect(error.message).toBe('Nothing bound to Token(something) in MyContainer'); }); }); describe('AlreadyBoundError', () => { + const token = createToken('hello'); + it('should show message properly', () => { - const error = new AlreadyBoundError(createToken('some-component')); - expect(error.message).toBe('Cannot rebind token, already bound: Token(some-component)'); + const error = new AlreadyBoundError(token); + + expect(error.message).toBe( + 'Cannot rebind token in [unknown container], already bound: Token(hello)', + ); + }); + + it('should handle name', () => { + const error = new AlreadyBoundError(token, 'ServerApp'); + + expect(error.message).toBe('Cannot rebind token in ServerApp, already bound: Token(hello)'); }); }); describe('CircularDependencyError', () => { + const trace = [createToken('A'), createToken('B'), createToken('A')]; + it('should show message properly', () => { - const trace = [createToken('foo'), createToken('bar'), createToken('baz')]; const error = new CircularDependencyError(trace); + + expect(error.message).toBe( + 'Circular dependency found in [unknown container], trace: Token(A) >> Token(B) >> Token(A)', + ); + }); + + it('should handle name', () => { + const error = new CircularDependencyError(trace, 'BrowserApp'); + expect(error.message).toBe( - 'Circular dependency found, trace: Symbol(foo) >> Symbol(bar) >> Symbol(baz)', + 'Circular dependency found in BrowserApp, trace: Token(A) >> Token(B) >> Token(A)', ); }); }); diff --git a/src/di/application.ts b/src/di/application.ts index c705470c..385bb25b 100644 --- a/src/di/application.ts +++ b/src/di/application.ts @@ -1,17 +1,7 @@ /* eslint-disable require-jsdoc, jsdoc/require-jsdoc */ -import type { - Application, - Container, - Provider, - Resolve, - Token, - Binding, - ExtractType, - Preset, -} from './types'; -import { AlreadyBoundError, NothingBoundError } from './errors'; +import type { Application, Provider, Token, Binding, ExtractType, Preset } from './types'; +import { AlreadyBoundError, CircularDependencyError, NothingBoundError } from './errors'; import { createToken } from './token'; -import { createContainer } from './container'; /** * Токен, с помощью которого можно достать из приложения само приложение. @@ -22,72 +12,94 @@ export const CURRENT_APP = createToken('application/self'); * Реализация Application. */ class ApplicationImplementation implements Application { - private container?: Container; - private parent?: Application; + /** Родительское приложение. */ + private parent?: ApplicationImplementation; + + /** Зарегистрированные пресеты. */ private presets: Preset[]; - private providers: Map, Provider>; + + /** Зарегистрированные провайдеры. */ + private providers: Map>; + + /** Инициализированные компоненты (синглтоны). */ + private components: Map; + + /** Инициализировано ли приложение. */ + private initialized: boolean; constructor() { this.providers = new Map(); + this.components = new Map(); this.presets = []; + this.initialized = false; + } + + toString() { + return 'Application'; } bind(token: Token): Binding { - if (this.providers.has(token)) { - throw new AlreadyBoundError(token); + if (this.providers.has(token._key)) { + throw new AlreadyBoundError(token, this.toString()); } return { toValue: value => { - this.providers.set(token, () => value); + this.providers.set(token._key, () => value); }, toProvider: provider => { - this.providers.set(token, provider); + this.providers.set(token._key, provider); }, }; } get(token: Token): T { - try { - return this.getContainer().get(token); - } catch (error) { - if (error instanceof NothingBoundError && error.token === token && this.parent) { - return this.parent.get(token); - } else { - throw error; + if (!this.initialized) { + this.bind(CURRENT_APP).toValue(this); + + for (const preset of this.presets) { + preset.apply(this); } - } - } - private getContainer(): Container { - if (!this.container) { - this.container = this.configureContainer(); + this.initialized = true; } - return this.container; + return this.resolve(token, []); } - private configureContainer(): Container { - const container = createContainer(); + protected resolve(token: Token, chain: Token[]): T { + const nextChain = () => [...chain, token]; - container.set(CURRENT_APP, () => this); + if (chain.includes(token)) { + throw new CircularDependencyError(nextChain(), this.toString()); + } - for (const preset of this.presets) { - preset.apply(this); + if (this.components.has(token._key)) { + return this.components.get(token._key) as T; } - const resolve: Resolve = token => this.get(token); + if (this.providers.has(token._key)) { + const provider = this.providers.get(token._key) as Provider; + + const component = provider(otherToken => this.resolve(otherToken, nextChain())); + + // ВАЖНО: всегда как singleton + this.components.set(token._key, component); - for (const [token, provider] of this.providers) { - container.set(token, () => provider(resolve)); + return component as T; + } + + if (this.parent) { + // ВАЖНО: передаём именно chain а не nextChain() + return this.parent.resolve(token, chain); } - return container; + throw new NothingBoundError(token, this.toString()); } - attach(parent: Application): void { + attach(parent: ApplicationImplementation): void { if (this.parent) { - throw Error('Cannot reattach application'); + throw new Error('Cannot reattach application'); } this.parent = parent; diff --git a/src/di/errors.ts b/src/di/errors.ts index 66bfdd14..68562376 100644 --- a/src/di/errors.ts +++ b/src/di/errors.ts @@ -4,14 +4,15 @@ import type { Token } from './types'; * Ошибка, сообщающая, что в контейнере нет сервиса по заданному ключу. */ export class NothingBoundError extends Error { - public readonly token: Token; + public readonly token: Token; /** * Конструктор. * @param token Токен. + * @param containerName Имя контейнера. */ - constructor(token: Token) { - super(`Nothing bound to ${String(token)}`); + constructor(token: Token, containerName?: string) { + super(`Nothing bound to ${String(token)} in ${display(containerName)}`); this.name = 'NothingBoundError'; this.token = token; } @@ -24,9 +25,10 @@ export class AlreadyBoundError extends Error { /** * Конструктор. * @param token Токен. + * @param containerName Имя контейнера. */ - constructor(token: Token) { - super(`Cannot rebind token, already bound: ${String(token)}`); + constructor(token: Token, containerName?: string) { + super(`Cannot rebind token in ${display(containerName)}, already bound: ${String(token)}`); this.name = 'AlreadyBoundError'; } } @@ -38,10 +40,20 @@ export class CircularDependencyError extends Error { /** * Конструктор. * @param trace Список токенов, в котором обнаружен цикл. + * @param containerName Имя контейнера. */ - constructor(trace: Token[]) { - const names = trace.map(token => String(token._key)).join(' >> '); - super(`Circular dependency found, trace: ${names}`); + constructor(trace: Token[], containerName?: string) { + const names = trace.map(String).join(' >> '); + super(`Circular dependency found in ${display(containerName)}, trace: ${names}`); this.name = 'CircularDependencyError'; } } + +/** + * Вернёт переданное имя контейнера или заглушку. + * @param containerName Имя. + * @return Имя или заглушка. + */ +function display(containerName?: string) { + return containerName ?? '[unknown container]'; +} diff --git a/src/preset/browser/index.ts b/src/preset/browser/index.ts index 12ee7d96..761612bd 100644 --- a/src/preset/browser/index.ts +++ b/src/preset/browser/index.ts @@ -1,7 +1,7 @@ /* eslint-disable require-jsdoc, jsdoc/require-jsdoc */ import { createPreset, Resolve, Preset } from '../../di'; import { KnownToken } from '../../tokens'; -import { createConfigSource } from '../../config/browser'; +import { ConfigSource, createConfigSource } from '../../config'; import { Logger, createLogger } from '../../log'; import { createSentryHandler } from '../../log/handler/sentry'; import { @@ -25,7 +25,7 @@ import { export function PresetBrowser(): Preset { return createPreset([ - [KnownToken.Config.source, createConfigSource], + [KnownToken.Config.source, provideConfigSource], [KnownToken.Config.base, provideBaseConfig], [KnownToken.logger, provideLogger], [KnownToken.sagaMiddleware, provideSagaMiddleware], @@ -36,6 +36,12 @@ export function PresetBrowser(): Preset { ]); } +export function provideConfigSource(): ConfigSource { + return createConfigSource({ + environment: process.env, + }); +} + export function provideLogger(resolve: Resolve): Logger { const source = resolve(KnownToken.Config.source); diff --git a/src/preset/node/index.ts b/src/preset/node/index.ts index b0b95b5a..78074405 100644 --- a/src/preset/node/index.ts +++ b/src/preset/node/index.ts @@ -1,4 +1,5 @@ /* eslint-disable require-jsdoc, jsdoc/require-jsdoc */ +import path from 'path'; import type { Logger, LoggerEventHandler } from '../../log/types'; import type { Tracer } from '@opentelemetry/api'; import type { DefaultMiddleware } from '../../http-server/types'; @@ -9,7 +10,7 @@ import { SpanExporter, } from '@opentelemetry/sdk-trace-base'; import { KnownToken } from '../../tokens'; -import { createConfigSource } from '../../config/node'; +import { ConfigSource, createConfigSource } from '../../config'; import { createLogger } from '../../log'; import { createPinoHandler } from '../../log/handler/pino'; import { createSentryHandler } from '../../log/handler/sentry'; @@ -36,6 +37,7 @@ import { HttpApiHostPool } from '../parts/utils'; import { provideBaseConfig } from '../parts/providers'; import pino from 'pino'; import PinoPretty from 'pino-pretty'; +import { config as applyDotenv } from 'dotenv'; /** * Возвращает preset с зависимостями по умолчанию для frontend-микросервисов на Node.js. @@ -43,7 +45,7 @@ import PinoPretty from 'pino-pretty'; */ export function PresetNode(): Preset { return createPreset([ - [KnownToken.Config.source, createConfigSource], + [KnownToken.Config.source, provideConfigSource], [KnownToken.Config.base, provideBaseConfig], [KnownToken.logger, provideLogger], [KnownToken.Tracing.tracer, provideTracer], @@ -59,6 +61,19 @@ export function PresetNode(): Preset { ]); } +export function provideConfigSource(): ConfigSource { + const envName = process.env.NODE_ENV; + + // подключаем соответствующий среде файл со значениями по умолчанию + if (envName) { + applyDotenv({ path: path.resolve(process.cwd(), `./.env.${envName}`) }); + } + + return createConfigSource({ + environment: process.env, + }); +} + export function provideLogger(resolve: Resolve): Logger { const logger = createLogger();