feat: raw amqplib exchange publishing for inter-plugin RPC — v1.7.0
This commit is contained in:
parent
acc8c3178d
commit
4efaa25452
|
|
@ -1,33 +1,45 @@
|
|||
{
|
||||
"name": "erp-plugin-sdk",
|
||||
"version": "1.0.0",
|
||||
"name": "@erp/plugin-sdk",
|
||||
"version": "1.5.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "erp-plugin-sdk",
|
||||
"version": "1.0.0",
|
||||
"name": "@erp/plugin-sdk",
|
||||
"version": "1.5.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"uuid": "^9.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"create-erp-plugin": "dist/cli/index.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nestjs/common": "^11.1.23",
|
||||
"@nestjs/core": "^11.1.23",
|
||||
"@nestjs/microservices": "^11.1.23",
|
||||
"@types/amqplib": "^0.10.8",
|
||||
"@types/node": "^25.9.1",
|
||||
"@types/react": "^19.2.15",
|
||||
"@types/uuid": "^9.0.8",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"rxjs": "^7.8.2",
|
||||
"typescript": "^6.0.3",
|
||||
"uuid": "^9.0.1"
|
||||
"typescript": "^6.0.3"
|
||||
},
|
||||
"bin": {
|
||||
"create-erp-plugin": "dist/cli/index.js"
|
||||
"peerDependencies": {
|
||||
"@nestjs/common": "^10.0.0 || ^11.0.0",
|
||||
"@nestjs/core": "^10.0.0 || ^11.0.0",
|
||||
"@nestjs/microservices": "^10.0.0 || ^11.0.0",
|
||||
"amqplib": "^0.10.3",
|
||||
"reflect-metadata": "^0.1.12 || ^0.2.0",
|
||||
"rxjs": "^7.8.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@borewit/text-codec": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@borewit/text-codec/-/text-codec-0.2.2.tgz",
|
||||
"integrity": "sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
|
|
@ -38,6 +50,7 @@
|
|||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz",
|
||||
"integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
|
|
@ -47,6 +60,7 @@
|
|||
"version": "11.1.23",
|
||||
"resolved": "https://registry.npmjs.org/@nestjs/common/-/common-11.1.23.tgz",
|
||||
"integrity": "sha512-qKgEqwQXHIVu8TwiISmgbTrGHAFBsseP86KNolBZwAiHQryinJ5FPiDpp0ZJBBryY+WEMnsqaCa4TSxVuQEWug==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"file-type": "21.3.4",
|
||||
|
|
@ -78,6 +92,7 @@
|
|||
"version": "11.1.23",
|
||||
"resolved": "https://registry.npmjs.org/@nestjs/core/-/core-11.1.23.tgz",
|
||||
"integrity": "sha512-Yd+mVFUilw4A6PzV7tyfiW+zrG2wmRXnFZVmNQA+fl1N0k6km4bhhNboxjLu//dzl+XiZI5AsOHHOTegzvOgNQ==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
|
@ -119,6 +134,7 @@
|
|||
"version": "11.1.23",
|
||||
"resolved": "https://registry.npmjs.org/@nestjs/microservices/-/microservices-11.1.23.tgz",
|
||||
"integrity": "sha512-iVPp3u274Xx6XAEbKPWDCzUHP6wlt7L7RXUIyIpf3caJ3ldFh/dG3uyHva1lgjHG+ukz+XCXafl1cx352TPW0w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"iterare": "1.2.1",
|
||||
|
|
@ -177,6 +193,7 @@
|
|||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@nuxt/opencollective/-/opencollective-0.4.1.tgz",
|
||||
"integrity": "sha512-GXD3wy50qYbxCJ652bDrDzgMr3NFEkIS374+IgFQKkCvk9yiYcLvX2XDYr7UyQxf4wK0e+yqDYRubZ0DtOxnmQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"consola": "^3.2.3"
|
||||
|
|
@ -193,6 +210,7 @@
|
|||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.4.1.tgz",
|
||||
"integrity": "sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"debug": "^4.4.3",
|
||||
|
|
@ -210,12 +228,24 @@
|
|||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz",
|
||||
"integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/amqplib": {
|
||||
"version": "0.10.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/amqplib/-/amqplib-0.10.8.tgz",
|
||||
"integrity": "sha512-vtDp8Pk1wsE/AuQ8/Rgtm6KUZYqcnTgNvEHwzCkX8rL7AGsC6zqAfKAAJhUZXFhM/Pp++tbnUHiam/8vVpPztA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "25.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.1.tgz",
|
||||
"integrity": "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": ">=7.24.0 <7.24.7"
|
||||
|
|
@ -225,6 +255,7 @@
|
|||
"version": "19.2.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.15.tgz",
|
||||
"integrity": "sha512-eRwcGNHve+E8qtEQSSRl6urh+rFop4v8gm6O8rGv25CodbvFdLjA1vVQ1KkiFE0w0UPOnb8tDiFKL5lp0rtY5Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"csstype": "^3.2.2"
|
||||
|
|
@ -234,12 +265,35 @@
|
|||
"version": "9.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz",
|
||||
"integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/amqplib": {
|
||||
"version": "0.10.9",
|
||||
"resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.10.9.tgz",
|
||||
"integrity": "sha512-jwSftI4QjS3mizvnSnOrPGYiUnm1vI2OP1iXeOUz5pb74Ua0nbf6nPyyTzuiCLEE3fMpaJORXh2K/TQ08H5xGA==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"buffer-more-ints": "~1.0.0",
|
||||
"url-parse": "~1.5.10"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/buffer-more-ints": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz",
|
||||
"integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/consola": {
|
||||
"version": "3.4.2",
|
||||
"resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz",
|
||||
"integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^14.18.0 || >=16.10.0"
|
||||
|
|
@ -249,12 +303,14 @@
|
|||
"version": "3.2.3",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
|
||||
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.4.3",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
||||
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "^2.1.3"
|
||||
|
|
@ -272,12 +328,14 @@
|
|||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
|
||||
"integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/file-type": {
|
||||
"version": "21.3.4",
|
||||
"resolved": "https://registry.npmjs.org/file-type/-/file-type-21.3.4.tgz",
|
||||
"integrity": "sha512-Ievi/yy8DS3ygGvT47PjSfdFoX+2isQueoYP1cntFW1JLYAuS4GD7NUPGg4zv2iZfV52uDyk5w5Z0TdpRS6Q1g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@tokenizer/inflate": "^0.4.1",
|
||||
|
|
@ -296,6 +354,7 @@
|
|||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
|
|
@ -316,6 +375,7 @@
|
|||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/iterare/-/iterare-1.2.1.tgz",
|
||||
"integrity": "sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
|
|
@ -325,6 +385,7 @@
|
|||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/load-esm/-/load-esm-1.0.3.tgz",
|
||||
"integrity": "sha512-v5xlu8eHD1+6r8EHTg6hfmO97LN8ugKtiXcy5e6oN72iD2r6u0RPfLl6fxM+7Wnh2ZRq15o0russMst44WauPA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
|
|
@ -344,28 +405,46 @@
|
|||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/path-to-regexp": {
|
||||
"version": "8.4.2",
|
||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.2.tgz",
|
||||
"integrity": "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/express"
|
||||
}
|
||||
},
|
||||
"node_modules/querystringify": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
|
||||
"integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/reflect-metadata": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz",
|
||||
"integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/requires-port": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
||||
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/rxjs": {
|
||||
"version": "7.8.2",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
|
||||
"integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"tslib": "^2.1.0"
|
||||
|
|
@ -375,6 +454,7 @@
|
|||
"version": "10.3.5",
|
||||
"resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.3.5.tgz",
|
||||
"integrity": "sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@tokenizer/token": "^0.3.0"
|
||||
|
|
@ -391,6 +471,7 @@
|
|||
"version": "6.1.2",
|
||||
"resolved": "https://registry.npmjs.org/token-types/-/token-types-6.1.2.tgz",
|
||||
"integrity": "sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@borewit/text-codec": "^0.2.1",
|
||||
|
|
@ -409,12 +490,14 @@
|
|||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||
"dev": true,
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz",
|
||||
"integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
|
|
@ -428,6 +511,7 @@
|
|||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/uid/-/uid-2.0.2.tgz",
|
||||
"integrity": "sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lukeed/csprng": "^1.0.0"
|
||||
|
|
@ -440,6 +524,7 @@
|
|||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.5.0.tgz",
|
||||
"integrity": "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
|
|
@ -452,8 +537,20 @@
|
|||
"version": "7.24.6",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz",
|
||||
"integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/url-parse": {
|
||||
"version": "1.5.10",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
|
||||
"integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"querystringify": "^2.1.1",
|
||||
"requires-port": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/uuid": {
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@erp/plugin-sdk",
|
||||
"version": "1.4.0",
|
||||
"version": "1.7.0",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"bin": {
|
||||
|
|
@ -19,7 +19,10 @@
|
|||
"author": "",
|
||||
"license": "ISC",
|
||||
"description": "ERP Plugin SDK — build micro-frontend/backend plugins for the ERP platform",
|
||||
"files": ["dist/", "README.md"],
|
||||
"files": [
|
||||
"dist/",
|
||||
"README.md"
|
||||
],
|
||||
"publishConfig": {
|
||||
"registry": "https://gitea.ss.3w.com.ua/api/packages/erp/npm/"
|
||||
},
|
||||
|
|
@ -30,6 +33,7 @@
|
|||
"@nestjs/common": "^10.0.0 || ^11.0.0",
|
||||
"@nestjs/core": "^10.0.0 || ^11.0.0",
|
||||
"@nestjs/microservices": "^10.0.0 || ^11.0.0",
|
||||
"amqplib": "^0.10.3",
|
||||
"reflect-metadata": "^0.1.12 || ^0.2.0",
|
||||
"rxjs": "^7.8.2"
|
||||
},
|
||||
|
|
@ -37,6 +41,7 @@
|
|||
"@nestjs/common": "^11.1.23",
|
||||
"@nestjs/core": "^11.1.23",
|
||||
"@nestjs/microservices": "^11.1.23",
|
||||
"@types/amqplib": "^0.10.8",
|
||||
"@types/node": "^25.9.1",
|
||||
"@types/react": "^19.2.15",
|
||||
"@types/uuid": "^9.0.8",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { Transport, MicroserviceOptions, RmqOptions } from '@nestjs/microservices';
|
||||
import * as amqp from 'amqplib';
|
||||
|
||||
export const getRabbitMQOptions = (queueName: string, url?: string, pluginId?: string): MicroserviceOptions => {
|
||||
const routingKeys: string[] = ['#'];
|
||||
|
|
@ -36,3 +37,29 @@ export const getRabbitMQClientOptions = (url?: string) => {
|
|||
},
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Bind a queue to the system_events exchange with the given routing keys.
|
||||
* NestJS 10's ServerRMQ does not automatically bind queues to exchanges,
|
||||
* so this must be called after app.startAllMicroservices().
|
||||
* NestJS 11+ handles this automatically via the exchange/routingKey options.
|
||||
*/
|
||||
export async function setupQueueBindings(
|
||||
queueName: string,
|
||||
routingKeys: string[],
|
||||
url?: string,
|
||||
): Promise<void> {
|
||||
const rmqUrl = url || process.env.RABBITMQ_URL || 'amqp://localhost:5672';
|
||||
const conn = await amqp.connect(rmqUrl);
|
||||
try {
|
||||
const channel = await conn.createChannel();
|
||||
await channel.assertExchange('system_events', 'topic', { durable: true });
|
||||
await channel.assertQueue(queueName, { durable: true });
|
||||
for (const key of routingKeys) {
|
||||
await channel.bindQueue(queueName, 'system_events', key);
|
||||
}
|
||||
await channel.close();
|
||||
} finally {
|
||||
await conn.close().catch(() => {});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { SystemEvent } from '../interfaces/communication';
|
|||
import { v4 as uuidv4 } from 'uuid';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as amqp from 'amqplib';
|
||||
import { requestContext } from '../interceptors/request-context.interceptor';
|
||||
|
||||
@Injectable()
|
||||
|
|
@ -182,14 +183,38 @@ export class CoreService {
|
|||
*
|
||||
* Інші плагіни теж отримують подію (через # binding), але за конвенцією
|
||||
* мають ігнорувати події з префіксом plugin.<чужойId>.
|
||||
*
|
||||
* IMPORTANT: Uses raw amqplib to publish to system_events exchange (not ClientProxy),
|
||||
* because NestJS 10 ClientRMQ ignores the exchange option and sends directly to a queue.
|
||||
*/
|
||||
async emitToPlugin(pluginId: string, pattern: string, payload: any): Promise<void> {
|
||||
await this.emit(`plugin.${pluginId}.${pattern}`, payload);
|
||||
const routingKey = `plugin.${pluginId}.${pattern}`;
|
||||
const event: SystemEvent = {
|
||||
eventId: uuidv4(),
|
||||
pattern: routingKey,
|
||||
payload,
|
||||
source: this.serviceName,
|
||||
timestamp: Date.now(),
|
||||
};
|
||||
try {
|
||||
const conn = await amqp.connect(this.getRMQUrl());
|
||||
const ch = await conn.createChannel();
|
||||
ch.publish('system_events', routingKey, Buffer.from(JSON.stringify(event)), {
|
||||
persistent: true,
|
||||
contentType: 'application/json',
|
||||
});
|
||||
await ch.close();
|
||||
await conn.close();
|
||||
this.logger.log(`[emitToPlugin] Published to ${routingKey}`);
|
||||
} catch (err: any) {
|
||||
this.logger.error(`[emitToPlugin] Failed for ${routingKey}: ${err.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* RPC-виклик до іншого плагіна з очікуванням відповіді.
|
||||
* Використовує NestJS RabbitMQ RPC (send / @MessagePattern).
|
||||
* Публікує в system_events exchange (raw amqplib, not ClientProxy).
|
||||
* Цільовий плагін має обробити запит через @MessagePattern('plugin.<pluginId>.<pattern>').
|
||||
*
|
||||
* @param pluginId — ID цільового плагіна
|
||||
|
|
@ -204,17 +229,58 @@ export class CoreService {
|
|||
payload: any,
|
||||
timeoutMs: number = 5000,
|
||||
): Promise<T | null> {
|
||||
const routingKey = `plugin.${pluginId}.${pattern}`;
|
||||
const correlationId = uuidv4();
|
||||
try {
|
||||
return await firstValueFrom(
|
||||
this.client.send(`plugin.${pluginId}.${pattern}`, payload).pipe(rxTimeout(timeoutMs)),
|
||||
{ defaultValue: null },
|
||||
);
|
||||
const conn = await amqp.connect(this.getRMQUrl());
|
||||
const ch = await conn.createChannel();
|
||||
const replyQueue = await ch.assertQueue('', { exclusive: true, autoDelete: true });
|
||||
|
||||
const msg = {
|
||||
id: correlationId,
|
||||
pattern: routingKey,
|
||||
data: payload,
|
||||
};
|
||||
|
||||
ch.publish('system_events', routingKey, Buffer.from(JSON.stringify(msg)), {
|
||||
correlationId,
|
||||
replyTo: replyQueue.queue,
|
||||
persistent: true,
|
||||
contentType: 'application/json',
|
||||
});
|
||||
|
||||
const result = await new Promise<T | null>((resolve) => {
|
||||
const timer = setTimeout(() => {
|
||||
this.logger.warn(`[requestPlugin] Timeout for ${routingKey}`);
|
||||
resolve(null);
|
||||
}, timeoutMs);
|
||||
|
||||
ch.consume(replyQueue.queue, (rmqMsg) => {
|
||||
if (rmqMsg && rmqMsg.properties.correlationId === correlationId) {
|
||||
clearTimeout(timer);
|
||||
try {
|
||||
const parsed = JSON.parse(rmqMsg.content.toString());
|
||||
resolve(parsed.response ?? parsed);
|
||||
} catch {
|
||||
resolve(null);
|
||||
}
|
||||
}
|
||||
}, { noAck: true });
|
||||
});
|
||||
|
||||
await ch.close();
|
||||
await conn.close();
|
||||
return result;
|
||||
} catch (err: any) {
|
||||
this.logger.error(`[requestPlugin] failed for ${pluginId}/${pattern}: ${err.message}`);
|
||||
this.logger.error(`[requestPlugin] Failed for ${routingKey}: ${err.message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private getRMQUrl(): string {
|
||||
return process.env.RABBITMQ_URL || 'amqp://localhost:5672';
|
||||
}
|
||||
|
||||
async emit<T>(pattern: string, payload: T): Promise<void> {
|
||||
const event: SystemEvent<T> = {
|
||||
eventId: uuidv4(),
|
||||
|
|
|
|||
Loading…
Reference in New Issue