diff --git a/.eslintrc b/.eslintrc
index 1101f09..961180e 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -12,6 +12,7 @@
},
"rules": {
"no-unused-vars": "warn",
- "@typescript-eslint/no-unused-vars": "warn"
+ "@typescript-eslint/no-unused-vars": "warn",
+ "@typescript-eslint/no-explicit-any": "error"
}
}
diff --git a/README.md b/README.md
index 32aa6ce..67bbd19 100644
--- a/README.md
+++ b/README.md
@@ -6,10 +6,11 @@
[](https://badge.fury.io/js/az-queue-consumer)

[](https://www.codefactor.io/repository/github/aarontravass/az-queue-consumer)
+
-Azure Queue Consumer is a simple consumer that allows you to handle queue messages without having to worry about setting up the azure framework.
+Azure Queue Consumer is a simple, typescript first consumer that allows you to handle queue messages without having to worry about setting up the azure framework.
## Installation
diff --git a/package.json b/package.json
index 2dce583..f873f3a 100644
--- a/package.json
+++ b/package.json
@@ -19,8 +19,8 @@
},
"scripts": {
"build": "parcel build",
- "format:check": "prettier --check src/**",
- "format:fix": "prettier --write src/**",
+ "format:check": "prettier --check src/** tests/**",
+ "format:fix": "prettier --write src/** tests/**",
"lint:check": "eslint src/** --ext=ts",
"lint:fix": "eslint src/** --fix --ext=ts",
"prepare": "husky install",
@@ -43,6 +43,7 @@
"@azure/storage-queue": "^12.14.0"
},
"devDependencies": {
+ "@azure/identity": "^4.0.0",
"@commitlint/cli": "^17.6.7",
"@commitlint/config-conventional": "^17.6.7",
"@parcel/packager-ts": "^2.10.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 0f666d1..b44ecc1 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -10,6 +10,9 @@ dependencies:
version: 12.14.0
devDependencies:
+ '@azure/identity':
+ specifier: ^4.0.0
+ version: 4.0.0
'@commitlint/cli':
specifier: ^17.6.7
version: 17.6.7
@@ -82,7 +85,6 @@ packages:
engines: {node: '>=12.0.0'}
dependencies:
tslib: 2.6.0
- dev: false
/@azure/core-auth@1.4.0:
resolution: {integrity: sha512-HFrcTgmuSuukRf/EdPmqBrc5l6Q5Uu+2TbuhaKbgaCpP2TfAeiNaQPAadxO+CYBRHGUzIDteMAjFspFLDLnKVQ==}
@@ -92,6 +94,30 @@ packages:
tslib: 2.6.0
dev: false
+ /@azure/core-auth@1.5.0:
+ resolution: {integrity: sha512-udzoBuYG1VBoHVohDTrvKjyzel34zt77Bhp7dQntVGGD0ehVq48owENbBG8fIgkHRNUBQH5k1r0hpoMu5L8+kw==}
+ engines: {node: '>=14.0.0'}
+ dependencies:
+ '@azure/abort-controller': 1.1.0
+ '@azure/core-util': 1.3.2
+ tslib: 2.6.0
+ dev: true
+
+ /@azure/core-client@1.7.3:
+ resolution: {integrity: sha512-kleJ1iUTxcO32Y06dH9Pfi9K4U+Tlb111WXEnbt7R/ne+NLRwppZiTGJuTD5VVoxTMK5NTbEtm5t2vcdNCFe2g==}
+ engines: {node: '>=14.0.0'}
+ dependencies:
+ '@azure/abort-controller': 1.1.0
+ '@azure/core-auth': 1.5.0
+ '@azure/core-rest-pipeline': 1.13.0
+ '@azure/core-tracing': 1.0.1
+ '@azure/core-util': 1.3.2
+ '@azure/logger': 1.0.4
+ tslib: 2.6.0
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
/@azure/core-http@3.0.2:
resolution: {integrity: sha512-o1wR9JrmoM0xEAa0Ue7Sp8j+uJvmqYaGoHOCT5qaVYmvgmnZDC0OvQimPA/JR3u77Sz6D1y3Xmk1y69cDU9q9A==}
engines: {node: '>=14.0.0'}
@@ -121,6 +147,22 @@ packages:
tslib: 2.6.0
dev: false
+ /@azure/core-rest-pipeline@1.13.0:
+ resolution: {integrity: sha512-a62aP/wppgmnfIkJLfcB4ssPBcH94WzrzPVJ3tlJt050zX4lfmtnvy95D3igDo3f31StO+9BgPrzvkj4aOxnoA==}
+ engines: {node: '>=18.0.0'}
+ dependencies:
+ '@azure/abort-controller': 1.1.0
+ '@azure/core-auth': 1.5.0
+ '@azure/core-tracing': 1.0.1
+ '@azure/core-util': 1.3.2
+ '@azure/logger': 1.0.4
+ http-proxy-agent: 5.0.0
+ https-proxy-agent: 5.0.1
+ tslib: 2.6.0
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
/@azure/core-tracing@1.0.0-preview.13:
resolution: {integrity: sha512-KxDlhXyMlh2Jhj2ykX6vNEU0Vou4nHr025KoSEiz7cS3BNiHNaZcdECk/DmLkEB0as5T7b/TpRcehJ5yV6NeXQ==}
engines: {node: '>=12.0.0'}
@@ -129,20 +171,68 @@ packages:
tslib: 2.6.0
dev: false
+ /@azure/core-tracing@1.0.1:
+ resolution: {integrity: sha512-I5CGMoLtX+pI17ZdiFJZgxMJApsK6jjfm85hpgp3oazCdq5Wxgh4wMr7ge/TTWW1B5WBuvIOI1fMU/FrOAMKrw==}
+ engines: {node: '>=12.0.0'}
+ dependencies:
+ tslib: 2.6.0
+ dev: true
+
/@azure/core-util@1.3.2:
resolution: {integrity: sha512-2bECOUh88RvL1pMZTcc6OzfobBeWDBf5oBbhjIhT1MV9otMVWCzpOJkkiKtrnO88y5GGBelgY8At73KGAdbkeQ==}
engines: {node: '>=14.0.0'}
dependencies:
'@azure/abort-controller': 1.1.0
tslib: 2.6.0
- dev: false
+
+ /@azure/identity@4.0.0:
+ resolution: {integrity: sha512-gtPYxIL0kI39Dw4t3HvlbfhOdXqKD2MqDgynlklF0j728j51dcKgRo6FLX0QzpBw/1gGfLxjMXqq3nKOSQ2lmA==}
+ engines: {node: '>=18.0.0'}
+ dependencies:
+ '@azure/abort-controller': 1.1.0
+ '@azure/core-auth': 1.5.0
+ '@azure/core-client': 1.7.3
+ '@azure/core-rest-pipeline': 1.13.0
+ '@azure/core-tracing': 1.0.1
+ '@azure/core-util': 1.3.2
+ '@azure/logger': 1.0.4
+ '@azure/msal-browser': 3.6.0
+ '@azure/msal-node': 2.6.0
+ events: 3.3.0
+ jws: 4.0.0
+ open: 8.4.2
+ stoppable: 1.1.0
+ tslib: 2.6.0
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
/@azure/logger@1.0.4:
resolution: {integrity: sha512-ustrPY8MryhloQj7OWGe+HrYx+aoiOxzbXTtgblbV3xwCqpzUK36phH3XNHQKj3EPonyFUuDTfR3qFhTEAuZEg==}
engines: {node: '>=14.0.0'}
dependencies:
tslib: 2.6.0
- dev: false
+
+ /@azure/msal-browser@3.6.0:
+ resolution: {integrity: sha512-FrFBJXRJMyWXjAjg4cUNZwEKktzfzD/YD9+S1kj2ors67hKoveam4aL0bZuCZU/jTiHTn0xDQGQh2ksCMXTXtA==}
+ engines: {node: '>=0.8.0'}
+ dependencies:
+ '@azure/msal-common': 14.5.0
+ dev: true
+
+ /@azure/msal-common@14.5.0:
+ resolution: {integrity: sha512-Gx5rZbiZV/HiZ2nEKfjfAF/qDdZ4/QWxMvMo2jhIFVz528dVKtaZyFAOtsX2Ak8+TQvRsGCaEfuwJFuXB6tu1A==}
+ engines: {node: '>=0.8.0'}
+ dev: true
+
+ /@azure/msal-node@2.6.0:
+ resolution: {integrity: sha512-RWAWCYYrSldIYC47oWtofIun41e6SB9TBYgGYsezq6ednagwo9ZRFyRsvl1NabmdTkdDDXRAABIdveeN2Gtd8w==}
+ engines: {node: 16|| 18 || 20}
+ dependencies:
+ '@azure/msal-common': 14.5.0
+ jsonwebtoken: 9.0.2
+ uuid: 8.3.2
+ dev: true
/@azure/storage-queue@12.14.0:
resolution: {integrity: sha512-1j6uxhzCcbEDVPOTNWIJ5CsLzOAU5U/bXgGZeT25fy6IghFTC1JlPGALez2CWJ9fBVj6AmSnsiBXL/77iXhSpg==}
@@ -2006,6 +2096,11 @@ packages:
resolution: {integrity: sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==}
dev: true
+ /@tootallnate/once@2.0.0:
+ resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==}
+ engines: {node: '>= 10'}
+ dev: true
+
/@trysound/sax@0.2.0:
resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==}
engines: {node: '>=10.13.0'}
@@ -2295,6 +2390,15 @@ packages:
hasBin: true
dev: true
+ /agent-base@6.0.2:
+ resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
+ engines: {node: '>= 6.0.0'}
+ dependencies:
+ debug: 4.3.4
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
/ajv@6.12.6:
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
dependencies:
@@ -2418,6 +2522,10 @@ packages:
update-browserslist-db: 1.0.11(browserslist@4.21.9)
dev: true
+ /buffer-equal-constant-time@1.0.1:
+ resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==}
+ dev: true
+
/buffer-from@1.1.2:
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
dev: true
@@ -2715,6 +2823,11 @@ packages:
titleize: 3.0.0
dev: true
+ /define-lazy-prop@2.0.0:
+ resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==}
+ engines: {node: '>=8'}
+ dev: true
+
/define-lazy-prop@3.0.0:
resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==}
engines: {node: '>=12'}
@@ -2803,6 +2916,12 @@ packages:
engines: {node: '>=6'}
dev: true
+ /ecdsa-sig-formatter@1.0.11:
+ resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==}
+ dependencies:
+ safe-buffer: 5.2.1
+ dev: true
+
/electron-to-chromium@1.4.468:
resolution: {integrity: sha512-6M1qyhaJOt7rQtNti1lBA0GwclPH+oKCmsra/hkcWs5INLxfXXD/dtdnaKUYQu/pjOBP/8Osoe4mAcNvvzoFag==}
dev: true
@@ -3023,6 +3142,11 @@ packages:
engines: {node: '>=0.10.0'}
dev: true
+ /events@3.3.0:
+ resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==}
+ engines: {node: '>=0.8.x'}
+ dev: true
+
/execa@5.1.1:
resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
engines: {node: '>=10'}
@@ -3348,6 +3472,27 @@ packages:
entities: 3.0.1
dev: true
+ /http-proxy-agent@5.0.0:
+ resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==}
+ engines: {node: '>= 6'}
+ dependencies:
+ '@tootallnate/once': 2.0.0
+ agent-base: 6.0.2
+ debug: 4.3.4
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /https-proxy-agent@5.0.1:
+ resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==}
+ engines: {node: '>= 6'}
+ dependencies:
+ agent-base: 6.0.2
+ debug: 4.3.4
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
/human-signals@2.1.0:
resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
engines: {node: '>=10.17.0'}
@@ -3584,6 +3729,52 @@ packages:
engines: {'0': node >= 0.2.0}
dev: true
+ /jsonwebtoken@9.0.2:
+ resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==}
+ engines: {node: '>=12', npm: '>=6'}
+ dependencies:
+ jws: 3.2.2
+ lodash.includes: 4.3.0
+ lodash.isboolean: 3.0.3
+ lodash.isinteger: 4.0.4
+ lodash.isnumber: 3.0.3
+ lodash.isplainobject: 4.0.6
+ lodash.isstring: 4.0.1
+ lodash.once: 4.1.1
+ ms: 2.1.2
+ semver: 7.5.4
+ dev: true
+
+ /jwa@1.4.1:
+ resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==}
+ dependencies:
+ buffer-equal-constant-time: 1.0.1
+ ecdsa-sig-formatter: 1.0.11
+ safe-buffer: 5.2.1
+ dev: true
+
+ /jwa@2.0.0:
+ resolution: {integrity: sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==}
+ dependencies:
+ buffer-equal-constant-time: 1.0.1
+ ecdsa-sig-formatter: 1.0.11
+ safe-buffer: 5.2.1
+ dev: true
+
+ /jws@3.2.2:
+ resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==}
+ dependencies:
+ jwa: 1.4.1
+ safe-buffer: 5.2.1
+ dev: true
+
+ /jws@4.0.0:
+ resolution: {integrity: sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==}
+ dependencies:
+ jwa: 2.0.0
+ safe-buffer: 5.2.1
+ dev: true
+
/kind-of@6.0.3:
resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
engines: {node: '>=0.10.0'}
@@ -3741,14 +3932,34 @@ packages:
resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==}
dev: true
+ /lodash.includes@4.3.0:
+ resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==}
+ dev: true
+
+ /lodash.isboolean@3.0.3:
+ resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==}
+ dev: true
+
/lodash.isfunction@3.0.9:
resolution: {integrity: sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==}
dev: true
+ /lodash.isinteger@4.0.4:
+ resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==}
+ dev: true
+
+ /lodash.isnumber@3.0.3:
+ resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==}
+ dev: true
+
/lodash.isplainobject@4.0.6:
resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
dev: true
+ /lodash.isstring@4.0.1:
+ resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==}
+ dev: true
+
/lodash.kebabcase@4.1.1:
resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==}
dev: true
@@ -3761,6 +3972,10 @@ packages:
resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==}
dev: true
+ /lodash.once@4.1.1:
+ resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==}
+ dev: true
+
/lodash.snakecase@4.1.1:
resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==}
dev: true
@@ -4056,6 +4271,15 @@ packages:
mimic-fn: 4.0.0
dev: true
+ /open@8.4.2:
+ resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==}
+ engines: {node: '>=12'}
+ dependencies:
+ define-lazy-prop: 2.0.0
+ is-docker: 2.2.1
+ is-wsl: 2.2.0
+ dev: true
+
/open@9.1.0:
resolution: {integrity: sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==}
engines: {node: '>=14.16'}
@@ -4562,6 +4786,11 @@ packages:
resolution: {integrity: sha512-Rz6yejtVyWnVjC1RFvNmYL10kgjC49EOghxWn0RFqlCHGFpQx+Xe7yW3I4ceK1SGrWIGMjD5Kbue8W/udkbMJg==}
dev: true
+ /stoppable@1.1.0:
+ resolution: {integrity: sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==}
+ engines: {node: '>=4', npm: '>=6'}
+ dev: true
+
/string-width@4.2.3:
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
engines: {node: '>=8'}
@@ -4865,7 +5094,6 @@ packages:
/uuid@8.3.2:
resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==}
hasBin: true
- dev: false
/v8-compile-cache-lib@3.0.1:
resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
diff --git a/src/errors.ts b/src/errors.ts
new file mode 100644
index 0000000..8c83f2c
--- /dev/null
+++ b/src/errors.ts
@@ -0,0 +1,19 @@
+export class QueueError extends Error {
+ code: string
+ message: string
+ constructor(code: string, message: string) {
+ super(`${code}:${message}`)
+ this.code = code
+ this.message = message
+ }
+}
+
+export class QueueConnectionError extends Error {
+ code: string
+ message: string
+ constructor(code: string, message: string) {
+ super(`${code}:${message}`)
+ this.code = code
+ this.message = message
+ }
+}
diff --git a/src/index.ts b/src/index.ts
index 4abf25f..9a595f2 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,12 +1,17 @@
import { DequeuedMessageItem, QueueClient, QueueServiceClient } from '@azure/storage-queue'
-import { HandlerFunction, QueueError, QueueOptions } from './utils'
+import { QueueConnectionError, QueueError } from './errors'
import { QueueEventEmitter } from './events'
-
-type QueueConnection = string | QueueServiceClient
+import { HandlerFunction, QueueOptions, QueueConnection } from './types'
/**
* The Main Queue Consumer class
* @class
+ * @example
+ * import { AzureQueueConsumer } from 'az-queue-consumer';
+ * const queueName = // queue name;
+ * const connectionString = // storage account connection string;
+ * const listener = new AzureQueueConsumer(queueName, connectionString, (message) => { // do something with the message });
+ * listener.listen();
*/
export class AzureQueueConsumer extends QueueEventEmitter {
#options: QueueOptions
@@ -39,9 +44,7 @@ export class AzureQueueConsumer extends QueueEventEmitter {
#createQueueAsync = async () => {
await this.#queueClient
.createIfNotExists()
- .then((res) => {
- this.emit('queue::ready', res)
- })
+ .then((res) => this.emit('queue::ready', res))
.catch((er) => {
throw new QueueError(er.code, er.message)
})
@@ -73,7 +76,7 @@ export class AzureQueueConsumer extends QueueEventEmitter {
if (error.code === 'REQUEST_SEND_ERROR') this.#pollingTime += 5
return
})
- .then((_) => {
+ .then(() => {
if (!this.#shouldShutdown) setTimeout(this.listen.bind(this), this.#pollingTime * 1000)
else this.removeAllListeners()
})
@@ -86,9 +89,9 @@ export class AzureQueueConsumer extends QueueEventEmitter {
#deleteMessages = async (messages: DequeuedMessageItem[]) => {
for (const message of messages) {
this.emit('message::preDelete', message.messageId, message.popReceipt)
- await this.#queueClient.deleteMessage(message.messageId, message.popReceipt).then((res) => {
- this.emit('message::afterDelete', res)
- })
+ await this.#queueClient
+ .deleteMessage(message.messageId, message.popReceipt)
+ .then((res) => this.emit('message::afterDelete', res))
}
}
@@ -108,8 +111,12 @@ export class AzureQueueConsumer extends QueueEventEmitter {
queueServiceClient = QueueServiceClient.fromConnectionString(connection, {
retryOptions: { maxTries: this.#options.maxTries }
})
- } else {
+ } else if ('connectionString' in connection && 'credential' in connection) {
+ queueServiceClient = new QueueServiceClient(connection.queueUrl, connection.credential)
+ } else if (connection instanceof QueueServiceClient) {
queueServiceClient = connection
+ } else {
+ throw new QueueConnectionError('INVALID_CONNECTION', 'Queue Connection provided was invalid')
}
return queueServiceClient.getQueueClient(queueName)
}
diff --git a/src/types.ts b/src/types.ts
new file mode 100644
index 0000000..03d4d7e
--- /dev/null
+++ b/src/types.ts
@@ -0,0 +1,62 @@
+import {
+ AnonymousCredential,
+ DequeuedMessageItem,
+ QueueServiceClient,
+ StorageSharedKeyCredential
+} from '@azure/storage-queue'
+
+/**
+ * QueueOptions interface
+ * @interface
+ */
+export interface QueueOptions {
+ /**
+ * Polling time in seconds
+ * @default 10
+ */
+ pollingTime: number
+ /**
+ * Maximum number of times to try
+ * @default 4
+ */
+ maxTries?: number
+ /**
+ * Number of messages to receieve
+ * @default 1
+ */
+ numberOfMessages?: number
+}
+
+/**
+ * @type {Function}
+ * @param {DequeuedMessageItem[]} messages
+ */
+export type HandlerFunction = (messages: DequeuedMessageItem[]) => void | Promise
+
+/**
+ * Azure Credential Type which is used to initialize `QueueServiceClient`
+ * @example
+ * new QueueServiceClient(AzureCredential.connectionString, AzureCredential.credential)
+ * @type {object}
+ * @property {string} connectionString - Account Connection String
+ * @property {object} credential - instance of Azure Credentials. Can be `DefaultAzureCredential`, `StorageSharedKeyCredential`, etc.
+ */
+
+export type AzureCredential = {
+ /**
+ * URL of your queue
+ * @example
+ * `https://{accountName}.blob.core.windows.net`
+ */
+ queueUrl: string
+ /**
+ * Instance of Credential class which holds the authorization needed
+ * @example
+ * new DefaultAzureCredential() or
+ * new AnonymousCredential() or
+ * new StorageSharedKeyCredential(account, accountKey)
+ */
+ credential: StorageSharedKeyCredential | AnonymousCredential
+}
+
+export type QueueConnection = string | QueueServiceClient | AzureCredential
diff --git a/src/utils.ts b/src/utils.ts
deleted file mode 100644
index e83fc9e..0000000
--- a/src/utils.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-import { DequeuedMessageItem } from '@azure/storage-queue'
-
-/**
- * QueueOptions interface
- * @interface
- */
-export interface QueueOptions {
- /**
- * Polling time in seconds
- * @default 10
- */
- pollingTime: number
- /**
- * Maximum number of times to try
- * @default 4
- */
- maxTries?: number
- /**
- * Number of messages to receieve
- * @default 1
- */
- numberOfMessages?: number
-}
-
-export class QueueError extends Error {
- code: string
- message: string
- constructor(code: string, message: string) {
- super(`${code}:${message}`)
- this.code = code
- this.message = message
- }
-}
-
-/**
- * @type {Function}
- * @param {DequeuedMessageItem[]} messages
- */
-export type HandlerFunction = (messages: DequeuedMessageItem[]) => void
diff --git a/tests/consumer.test.ts b/tests/consumer.test.ts
index ec3acef..bc3abca 100644
--- a/tests/consumer.test.ts
+++ b/tests/consumer.test.ts
@@ -50,7 +50,7 @@ describe('azure queue tests', () => {
const errorToThrow = { code: 'code', message: 'message' }
try {
- vi.spyOn(QueueServiceClient, 'fromConnectionString').mockImplementation((..._args: string[]) => {
+ vi.spyOn(QueueServiceClient, 'fromConnectionString').mockImplementation((...args: unknown) => {
const getQueueClient = vi.fn(() => {
const createIfNotExists = vi.fn(() => new Promise((resolve, reject) => reject(errorToThrow)))
@@ -59,12 +59,20 @@ describe('azure queue tests', () => {
return { getQueueClient }
})
- const k = new AzureQueueConsumer('test', 'https://test.com', (...args) => {})
+ new AzureQueueConsumer('test', 'https://test.com', (...args) => {})
await flushPromises()
} catch (error) {
console.error(error)
}
})
+ describe('Queue Connection tests', () => {
+ it('should throw an error if connection is invalid', () => {
+ expect.assertions(1)
+ expect(() => new AzureQueueConsumer('test', ['hello'], (arg) => {})).toThrowError(
+ 'Queue Connection provided was invalid'
+ )
+ })
+ })
})
describe('listener tests', () => {
it('should test for queue message', async () => {