Compare commits
No commits in common. "master" and "v1.1.1" have entirely different histories.
42
changelog.md
42
changelog.md
@ -1,47 +1,5 @@
|
||||
# Changelog
|
||||
|
||||
## 2025-03-15 - 2.3.0 - feat(platformservice)
|
||||
Add AIBridge module and refactor service file paths for improved module organization
|
||||
|
||||
- Added new AIBridge class in ts/aibridge/classes.aibridge.ts.
|
||||
- Renamed letter service file from ts/letter/letterservice.ts to ts/letter/classes.letterservice.ts and updated its index.
|
||||
- Updated platformservice.ts to import letter and SMS services from new paths.
|
||||
- Renamed SMS service file from ts/sms/smsservice.ts to ts/sms/classes.smsservice.ts and updated its index accordingly.
|
||||
|
||||
## 2025-03-15 - 2.2.1 - fix(platformservice)
|
||||
Refactor module structure to update import paths and file organization
|
||||
|
||||
- Removed obsolete file 'ts/classes.platformservice.ts' and updated references to use 'ts/platformservice.ts'.
|
||||
- Updated import paths in PlatformServiceDb, EmailService, and other modules to use new file structure.
|
||||
- Renamed and moved files in the email, mta, letter, and sms directories to align with new module layout.
|
||||
- Fixed references to external modules (e.g. '@serve.zone/interfaces', '@push.rocks/*', etc.) to reflect the updated paths.
|
||||
|
||||
## 2025-03-15 - 2.2.0 - feat(plugins)
|
||||
Add smartproxy support by including the @push.rocks/smartproxy dependency and exporting it in the plugins module.
|
||||
|
||||
- Added '@push.rocks/smartproxy' dependency version '^4.1.0' to package.json
|
||||
- Updated ts/plugins.ts to export the smartproxy module alongside other push.rocks modules
|
||||
|
||||
## 2025-03-15 - 2.1.0 - feat(MTA)
|
||||
Update readme with detailed Mail Transfer Agent usage and examples
|
||||
|
||||
- Added a comprehensive MTA section with usage examples including SMTP server setup, DKIM signing/verification, SPF/DMARC support, and API integration
|
||||
- Expanded the conclusion to highlight MTA capabilities alongside email, SMS, letter, and AI services
|
||||
|
||||
## 2025-03-15 - 2.0.0 - BREAKING CHANGE(platformservice)
|
||||
Remove deprecated AIBridge module and update email service to use the MTA connector; update dependency versions and adjust build scripts in package.json.
|
||||
|
||||
- Completely remove the aibridge module files (aibridge.classes.aibridge.ts, aibridge.classes.aibridgedb.ts, aibridge.classes.openaibridge.ts, aibridge.paths.ts, aibridge.plugins.ts, and index.ts) as they are no longer needed.
|
||||
- Switch the email service from using MailgunConnector to the new MTA connector for sending emails.
|
||||
- Update dependency versions for @serve.zone/interfaces, @tsclass/tsclass, letterxpress, and uuid in package.json.
|
||||
- Enhance the build script in package.json and add pnpm configuration.
|
||||
|
||||
## 2025-03-15 - 1.1.2 - fix(mta)
|
||||
Expose HttpResponse.statusCode and add explicit generic type annotations in DNSManager cache retrieval
|
||||
|
||||
- Changed HttpResponse.statusCode from private to public to allow external access and inspection
|
||||
- Added explicit generic type parameters in getFromCache calls for lookupMx and lookupTxt to enhance type safety
|
||||
|
||||
## 2025-03-15 - 1.1.1 - fix(paths)
|
||||
Update directory paths to use a dedicated 'data' directory and add ensureDirectories function for proper directory creation.
|
||||
|
||||
|
25
package.json
25
package.json
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@serve.zone/platformservice",
|
||||
"private": true,
|
||||
"version": "2.3.0",
|
||||
"version": "1.1.1",
|
||||
"description": "A multifaceted platform service handling mail, SMS, letter delivery, and AI services.",
|
||||
"main": "dist_ts/index.js",
|
||||
"typings": "dist_ts/index.d.ts",
|
||||
@ -12,7 +12,6 @@
|
||||
"test": "(tstest test/)",
|
||||
"start": "(node --max_old_space_size=250 ./cli.js)",
|
||||
"startTs": "(node cli.ts.js)",
|
||||
"build": "(tsbuild tsfolders --allowimplicitany)",
|
||||
"localPublish": ""
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -23,11 +22,12 @@
|
||||
"@push.rocks/tapbundle": "^5.0.22"
|
||||
},
|
||||
"dependencies": {
|
||||
"@anthropic-ai/sdk": "^0.18.0",
|
||||
"@api.global/typedrequest": "^3.0.19",
|
||||
"@api.global/typedserver": "^3.0.27",
|
||||
"@api.global/typedsocket": "^3.0.0",
|
||||
"@apiclient.xyz/cloudflare": "^6.0.3",
|
||||
"@apiclient.xyz/letterxpress": "^1.0.20",
|
||||
"@apiclient.xyz/letterxpress": "^1.0.17",
|
||||
"@push.rocks/projectinfo": "^5.0.1",
|
||||
"@push.rocks/qenv": "^6.0.5",
|
||||
"@push.rocks/smartdata": "^5.0.7",
|
||||
@ -36,17 +36,15 @@
|
||||
"@push.rocks/smartmail": "^1.0.24",
|
||||
"@push.rocks/smartpath": "^5.0.5",
|
||||
"@push.rocks/smartpromise": "^4.0.3",
|
||||
"@push.rocks/smartproxy": "^4.1.0",
|
||||
"@push.rocks/smartrequest": "^2.0.21",
|
||||
"@push.rocks/smartrule": "^2.0.1",
|
||||
"@push.rocks/smartrx": "^3.0.7",
|
||||
"@push.rocks/smartstate": "^2.0.0",
|
||||
"@serve.zone/interfaces": "^4.12.1",
|
||||
"@tsclass/tsclass": "^5.0.0",
|
||||
"@types/mailparser": "^3.4.5",
|
||||
"@serve.zone/interfaces": "^1.0.47",
|
||||
"@tsclass/tsclass": "^4.0.52",
|
||||
"mailauth": "^4.6.5",
|
||||
"mailparser": "^3.6.9",
|
||||
"uuid": "^11.1.0"
|
||||
"openai": "^4.29.2",
|
||||
"uuid": "^9.0.1"
|
||||
},
|
||||
"keywords": [
|
||||
"mail service",
|
||||
@ -69,12 +67,5 @@
|
||||
"rule management",
|
||||
"SMTP STARTTLS",
|
||||
"DNS management"
|
||||
],
|
||||
"pnpm": {
|
||||
"onlyBuiltDependencies": [
|
||||
"esbuild",
|
||||
"mongodb-memory-server",
|
||||
"puppeteer"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
441
pnpm-lock.yaml
generated
441
pnpm-lock.yaml
generated
@ -8,6 +8,9 @@ importers:
|
||||
|
||||
.:
|
||||
dependencies:
|
||||
'@anthropic-ai/sdk':
|
||||
specifier: ^0.18.0
|
||||
version: 0.18.0
|
||||
'@api.global/typedrequest':
|
||||
specifier: ^3.0.19
|
||||
version: 3.1.10
|
||||
@ -21,8 +24,8 @@ importers:
|
||||
specifier: ^6.0.3
|
||||
version: 6.0.3
|
||||
'@apiclient.xyz/letterxpress':
|
||||
specifier: ^1.0.20
|
||||
version: 1.0.20(typescript@5.7.3)
|
||||
specifier: ^1.0.17
|
||||
version: 1.0.19(typescript@5.7.3)
|
||||
'@push.rocks/projectinfo':
|
||||
specifier: ^5.0.1
|
||||
version: 5.0.2
|
||||
@ -47,15 +50,9 @@ importers:
|
||||
'@push.rocks/smartpromise':
|
||||
specifier: ^4.0.3
|
||||
version: 4.2.3
|
||||
'@push.rocks/smartproxy':
|
||||
specifier: ^4.1.0
|
||||
version: 4.1.0
|
||||
'@push.rocks/smartrequest':
|
||||
specifier: ^2.0.21
|
||||
version: 2.0.23
|
||||
'@push.rocks/smartrule':
|
||||
specifier: ^2.0.1
|
||||
version: 2.0.1
|
||||
'@push.rocks/smartrx':
|
||||
specifier: ^3.0.7
|
||||
version: 3.0.7
|
||||
@ -63,23 +60,23 @@ importers:
|
||||
specifier: ^2.0.0
|
||||
version: 2.0.19
|
||||
'@serve.zone/interfaces':
|
||||
specifier: ^4.12.1
|
||||
version: 4.12.1
|
||||
specifier: ^1.0.47
|
||||
version: 1.1.2
|
||||
'@tsclass/tsclass':
|
||||
specifier: ^5.0.0
|
||||
version: 5.0.0
|
||||
'@types/mailparser':
|
||||
specifier: ^3.4.5
|
||||
version: 3.4.5
|
||||
specifier: ^4.0.52
|
||||
version: 4.4.4
|
||||
mailauth:
|
||||
specifier: ^4.6.5
|
||||
version: 4.8.2
|
||||
mailparser:
|
||||
specifier: ^3.6.9
|
||||
version: 3.7.2
|
||||
openai:
|
||||
specifier: ^4.29.2
|
||||
version: 4.87.3(ws@8.18.1)(zod@3.24.2)
|
||||
uuid:
|
||||
specifier: ^11.1.0
|
||||
version: 11.1.0
|
||||
specifier: ^9.0.1
|
||||
version: 9.0.1
|
||||
devDependencies:
|
||||
'@git.zone/tsbuild':
|
||||
specifier: ^2.1.17
|
||||
@ -99,6 +96,9 @@ importers:
|
||||
|
||||
packages:
|
||||
|
||||
'@anthropic-ai/sdk@0.18.0':
|
||||
resolution: {integrity: sha512-3XsWEn/4nPGRd4AdSguugbSDFy6Z2AWTNOeI3iK+aV22+w23+vY9CEb3Hiy0kvKIQuxSmZz/+5WKC8nPWy8gVg==}
|
||||
|
||||
'@api.global/typedrequest-interfaces@2.0.2':
|
||||
resolution: {integrity: sha512-D+mkr4IiUZ/eUgrdp5jXjBKOW/iuMcl0z2ZLQsLLypKX/psFGD3viZJ58FNRa+/1OSM38JS5wFyoWl8oPEFLrw==}
|
||||
|
||||
@ -117,8 +117,8 @@ packages:
|
||||
'@apiclient.xyz/cloudflare@6.0.3':
|
||||
resolution: {integrity: sha512-NOPHFrKVxfkrRn9lVBLCdo0Ibm08PuaJe3A1K6TmXWxgbeJSqGkgVMGRwLilnol/062v6/1w2ZFO6f3fAxk5Gw==}
|
||||
|
||||
'@apiclient.xyz/letterxpress@1.0.20':
|
||||
resolution: {integrity: sha512-dPkuUa+wi0IG/NmIuCfdz0VMYYFKNQyZSDVMJXAHZPu3YzHf2xHr45n3VxwP5wZur+NG/+6pneoOnyzUosIKmw==}
|
||||
'@apiclient.xyz/letterxpress@1.0.19':
|
||||
resolution: {integrity: sha512-+TGKZ0Xq3yoxXxLNn+WLvI0zKSRZPN0t9hpgNcqehVZ7srcRdDvVewsXOL6NJVXdUByy3yfP99yMaW+9rXYnkA==}
|
||||
|
||||
'@apiglobal/typedrequest-interfaces@2.0.1':
|
||||
resolution: {integrity: sha512-Oi7pNU4vKo5UvcCJmqkH43Us237Ws/Pp/WDYnwnonRnTmIMd+6QjNfN/gXcPnP6tbamk8r8Xzcz9mgnSDM2ysw==}
|
||||
@ -754,48 +754,15 @@ packages:
|
||||
'@pdf-lib/upng@1.0.1':
|
||||
resolution: {integrity: sha512-dQK2FUMQtowVP00mtIksrlZhdFXQZPC+taih1q4CvPZ5vqdxR/LKBaFg0oAfzd1GlHZXXSPdQfzQnt+ViGvEIQ==}
|
||||
|
||||
'@peculiar/asn1-cms@2.3.15':
|
||||
resolution: {integrity: sha512-B+DoudF+TCrxoJSTjjcY8Mmu+lbv8e7pXGWrhNp2/EGJp9EEcpzjBCar7puU57sGifyzaRVM03oD5L7t7PghQg==}
|
||||
|
||||
'@peculiar/asn1-csr@2.3.15':
|
||||
resolution: {integrity: sha512-caxAOrvw2hUZpxzhz8Kp8iBYKsHbGXZPl2KYRMIPvAfFateRebS3136+orUpcVwHRmpXWX2kzpb6COlIrqCumA==}
|
||||
|
||||
'@peculiar/asn1-ecc@2.3.15':
|
||||
resolution: {integrity: sha512-/HtR91dvgog7z/WhCVdxZJ/jitJuIu8iTqiyWVgRE9Ac5imt2sT/E4obqIVGKQw7PIy+X6i8lVBoT6wC73XUgA==}
|
||||
|
||||
'@peculiar/asn1-pfx@2.3.15':
|
||||
resolution: {integrity: sha512-E3kzQe3J2xV9DP6SJS4X6/N1e4cYa2xOAK46VtvpaRk8jlheNri8v0rBezKFVPB1rz/jW8npO+u1xOvpATFMWg==}
|
||||
|
||||
'@peculiar/asn1-pkcs8@2.3.15':
|
||||
resolution: {integrity: sha512-/PuQj2BIAw1/v76DV1LUOA6YOqh/UvptKLJHtec/DQwruXOCFlUo7k6llegn8N5BTeZTWMwz5EXruBw0Q10TMg==}
|
||||
|
||||
'@peculiar/asn1-pkcs9@2.3.15':
|
||||
resolution: {integrity: sha512-yiZo/1EGvU1KiQUrbcnaPGWc0C7ElMMskWn7+kHsCFm+/9fU0+V1D/3a5oG0Jpy96iaXggQpA9tzdhnYDgjyFg==}
|
||||
|
||||
'@peculiar/asn1-rsa@2.3.15':
|
||||
resolution: {integrity: sha512-p6hsanvPhexRtYSOHihLvUUgrJ8y0FtOM97N5UEpC+VifFYyZa0iZ5cXjTkZoDwxJ/TTJ1IJo3HVTB2JJTpXvg==}
|
||||
|
||||
'@peculiar/asn1-schema@2.3.13':
|
||||
resolution: {integrity: sha512-3Xq3a01WkHRZL8X04Zsfg//mGaA21xlL4tlVn4v2xGT0JStiztATRkMwa5b+f/HXmY2smsiLXYK46Gwgzvfg3g==}
|
||||
|
||||
'@peculiar/asn1-schema@2.3.15':
|
||||
resolution: {integrity: sha512-QPeD8UA8axQREpgR5UTAfu2mqQmm97oUqahDtNdBcfj3qAnoXzFdQW+aNf/tD2WVXF8Fhmftxoj0eMIT++gX2w==}
|
||||
|
||||
'@peculiar/asn1-x509-attr@2.3.15':
|
||||
resolution: {integrity: sha512-TWJVJhqc+IS4MTEML3l6W1b0sMowVqdsnI4dnojg96LvTuP8dga9f76fjP07MUuss60uSyT2ckoti/2qHXA10A==}
|
||||
|
||||
'@peculiar/asn1-x509-logotype@2.3.13':
|
||||
resolution: {integrity: sha512-+atb0ws0Svr5wtuLyPvb4K/4fZKOv3Di2Zxl3wREqfeEvMQ/n+iQKWYplfZG9gcw5CuHVJjmfY6tHkIEryHCPQ==}
|
||||
|
||||
'@peculiar/asn1-x509@2.3.13':
|
||||
resolution: {integrity: sha512-PfeLQl2skXmxX2/AFFCVaWU8U6FKW1Db43mgBhShCOFS1bVxqtvusq1hVjfuEcuSQGedrLdCSvTgabluwN/M9A==}
|
||||
|
||||
'@peculiar/asn1-x509@2.3.15':
|
||||
resolution: {integrity: sha512-0dK5xqTqSLaxv1FHXIcd4Q/BZNuopg+u1l23hT9rOmQ1g4dNtw0g/RnEi+TboB0gOwGtrWn269v27cMgchFIIg==}
|
||||
|
||||
'@peculiar/x509@1.12.3':
|
||||
resolution: {integrity: sha512-+Mzq+W7cNEKfkNZzyLl6A6ffqc3r21HGZUezgfKxpZrkORfOqgRXnS80Zu0IV6a9Ue9QBJeKD7kN0iWfc3bhRQ==}
|
||||
|
||||
'@pkgjs/parseargs@0.11.0':
|
||||
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
|
||||
engines: {node: '>=14'}
|
||||
@ -856,6 +823,9 @@ packages:
|
||||
'@push.rocks/smartbucket@3.3.7':
|
||||
resolution: {integrity: sha512-RiOuEtwHJ+HFbV1nlZgh5VuMvP6PXElX6rVe7OSQsyNCBybRQa/d1qDic92+2Ejx852DGeHlyREELQCxd/a/7w==}
|
||||
|
||||
'@push.rocks/smartbuffer@2.0.3':
|
||||
resolution: {integrity: sha512-5AcGbnuRSaF2Iyn3a1JNbNtDw0/xEaS6AOL2uTTtWqBJQQf088GFKS0/8Gn7TJiCnX+N+KOEGwi+5BAQKvcZeQ==}
|
||||
|
||||
'@push.rocks/smartbuffer@3.0.4':
|
||||
resolution: {integrity: sha512-TLfhx/JD61YC8XGO9TI6Ux6US38R14HaIM84QT8hZZod8axfXrg+h8xA8tMUBpSV8PXsQy9LzxmOq0Il1fmDXw==}
|
||||
|
||||
@ -970,9 +940,6 @@ packages:
|
||||
'@push.rocks/smartpromise@4.2.3':
|
||||
resolution: {integrity: sha512-Ycg/TJR+tMt+S3wSFurOpEoW6nXv12QBtKXgBcjMZ4RsdO28geN46U09osPn9N9WuwQy1PkmTV5J/V4F9U8qEw==}
|
||||
|
||||
'@push.rocks/smartproxy@4.1.0':
|
||||
resolution: {integrity: sha512-yNTS+9mbBsO09+RXY7o9SUact9xXqwFFvQfLDz2QK4L/2L5RjFMEnqElmBdHx/vU2Vbv1JexiJiM73aa9XzwCQ==}
|
||||
|
||||
'@push.rocks/smartpuppeteer@2.0.5':
|
||||
resolution: {integrity: sha512-yK/qSeWVHIGWRp3c8S5tfdGP6WCKllZC4DR8d8CQlEjszOSBmHtlTdyyqOMBZ/BA4kd+eU5f3A1r4K2tGYty1g==}
|
||||
|
||||
@ -982,9 +949,6 @@ packages:
|
||||
'@push.rocks/smartrouter@1.3.2':
|
||||
resolution: {integrity: sha512-JtkxClN4CaHXMSeLDNvfWPwiVEPdEoQVSX2ee3gLgbXNO9dt9hvXdIhFrnFeLwyeA6M8nJdb9SqjrjZroYJsxw==}
|
||||
|
||||
'@push.rocks/smartrule@2.0.1':
|
||||
resolution: {integrity: sha512-8oYEnS9z+NgCAcUtXPMguYyZpHqA/ROp0bxVQwUaHDwa3YzzA8jHIXvA94hk3sxvkk0xmIpp4UhBEelzIwwJow==}
|
||||
|
||||
'@push.rocks/smartrx@3.0.7':
|
||||
resolution: {integrity: sha512-qCWy0s3RLAgGSnaw/Gu0BNaJ59CsI6RK5OJDCCqxc7P2X/S755vuLtnAR5/0dEjdhCHXHX9ytPZx+o9g/CNiyA==}
|
||||
|
||||
@ -1185,8 +1149,8 @@ packages:
|
||||
'@selderee/plugin-htmlparser2@0.11.0':
|
||||
resolution: {integrity: sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==}
|
||||
|
||||
'@serve.zone/interfaces@4.12.1':
|
||||
resolution: {integrity: sha512-M1ZfXmhlo3OyTtmhYWmQIVzd/AwTM5ANMHSuoZDuddq7K0UwmdYJNjRUK7nR1g4PucwFzpbMgUuXQSkhBJfvAw==}
|
||||
'@serve.zone/interfaces@1.1.2':
|
||||
resolution: {integrity: sha512-ajHArBX7iJcUPYjYoO1rx78Mz5IzHIKzxt34kWKk5fSDrOkAoNwk0P/zpm0JZ6ClQy7/maOHTiSsNpdbBNvhQg==}
|
||||
|
||||
'@sideway/address@4.1.5':
|
||||
resolution: {integrity: sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==}
|
||||
@ -1441,9 +1405,6 @@ packages:
|
||||
'@tsclass/tsclass@4.4.4':
|
||||
resolution: {integrity: sha512-YZOAF+u+r4u5rCev2uUd1KBTBdfyFdtDmcv4wuN+864lMccbdfRICR3SlJwCfYS1lbeV3QNLYGD30wjRXgvCJA==}
|
||||
|
||||
'@tsclass/tsclass@5.0.0':
|
||||
resolution: {integrity: sha512-2X66VCk0Oe1L01j6GQHC6F9Gj7lpZPPSUTDNax7e29lm4OqBTyAzTR3ePR8coSbWBwsmRV8awLRSrSI+swlqWA==}
|
||||
|
||||
'@types/accepts@1.3.7':
|
||||
resolution: {integrity: sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ==}
|
||||
|
||||
@ -1574,9 +1535,6 @@ packages:
|
||||
'@types/koa@2.15.0':
|
||||
resolution: {integrity: sha512-7QFsywoE5URbuVnG3loe03QXuGajrnotr3gQkXcEBShORai23MePfFYdhz90FEtBBpkyIYQbVD+evKtloCgX3g==}
|
||||
|
||||
'@types/mailparser@3.4.5':
|
||||
resolution: {integrity: sha512-EPERBp7fLeFZh7tS2X36MF7jawUx3Y6/0rXciZah3CTYgwLi3e0kpGUJ6FOmUabgzis/U1g+3/JzrVWbWIOGjg==}
|
||||
|
||||
'@types/mdast@4.0.4':
|
||||
resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
|
||||
|
||||
@ -1595,9 +1553,15 @@ packages:
|
||||
'@types/ms@2.1.0':
|
||||
resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
|
||||
|
||||
'@types/node-fetch@2.6.12':
|
||||
resolution: {integrity: sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==}
|
||||
|
||||
'@types/node-forge@1.3.11':
|
||||
resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==}
|
||||
|
||||
'@types/node@18.19.80':
|
||||
resolution: {integrity: sha512-kEWeMwMeIvxYkeg1gTc01awpwLbfMRZXdIhwRcakd/KlK53jmRC26LqcbIt7fnAQTu5GzlnWmzA3H6+l1u6xxQ==}
|
||||
|
||||
'@types/node@22.13.10':
|
||||
resolution: {integrity: sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==}
|
||||
|
||||
@ -1723,14 +1687,14 @@ packages:
|
||||
resolution: {integrity: sha512-84E1025aUSjvZU1j17eCTwV7m5Zg3cZHErV3+CaJM9JPCesZwLraIa0ONIQ9w4KLgcDgJFw9UnJ0LbFf42h6tg==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
|
||||
abort-controller@3.0.0:
|
||||
resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
|
||||
engines: {node: '>=6.5'}
|
||||
|
||||
accepts@1.3.8:
|
||||
resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
acme-client@5.4.0:
|
||||
resolution: {integrity: sha512-mORqg60S8iML6XSmVjqjGHJkINrCGLMj2QvDmFzI9vIlv1RGlyjmw3nrzaINJjkNsYXC41XhhD5pfy7CtuGcbA==}
|
||||
engines: {node: '>= 16'}
|
||||
|
||||
agent-base@6.0.2:
|
||||
resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
|
||||
engines: {node: '>= 6.0.0'}
|
||||
@ -1817,9 +1781,6 @@ packages:
|
||||
resolution: {integrity: sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
axios@1.8.3:
|
||||
resolution: {integrity: sha512-iP4DebzoNlP/YN2dpwCgb8zoCmhtkajzS48JvwmkSkXvPI3DHc7m+XYL5tGnSlJtR6nImXZmdCuN5aP8dh1d8A==}
|
||||
|
||||
b4a@1.6.7:
|
||||
resolution: {integrity: sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==}
|
||||
|
||||
@ -1854,6 +1815,9 @@ packages:
|
||||
bare-events:
|
||||
optional: true
|
||||
|
||||
base-64@0.1.0:
|
||||
resolution: {integrity: sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA==}
|
||||
|
||||
base64-js@1.5.1:
|
||||
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
||||
|
||||
@ -1984,6 +1948,9 @@ packages:
|
||||
character-entities@2.0.2:
|
||||
resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==}
|
||||
|
||||
charenc@0.0.2:
|
||||
resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==}
|
||||
|
||||
chokidar@4.0.3:
|
||||
resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
|
||||
engines: {node: '>= 14.16.0'}
|
||||
@ -2138,6 +2105,9 @@ packages:
|
||||
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
|
||||
engines: {node: '>= 8'}
|
||||
|
||||
crypt@0.0.2:
|
||||
resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==}
|
||||
|
||||
crypto-random-string@5.0.0:
|
||||
resolution: {integrity: sha512-KWjTXWwxFd6a94m5CdRGW/t82Tr8DoBc9dNnPCAbFI1EBweN6v1tv8y4Y1m7ndkp/nkIBRxUxAzpaBnR2k3bcQ==}
|
||||
engines: {node: '>=14.16'}
|
||||
@ -2276,6 +2246,9 @@ packages:
|
||||
resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==}
|
||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||
|
||||
digest-fetch@1.3.0:
|
||||
resolution: {integrity: sha512-CGJuv6iKNM7QyZlM2T3sPAdZWd/p9zQiRNS9G+9COUCwzWFTs0Xp8NF5iePx7wtvhDykReiRRrSeNb4oMmB8lA==}
|
||||
|
||||
dijkstrajs@1.0.3:
|
||||
resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==}
|
||||
|
||||
@ -2450,6 +2423,10 @@ packages:
|
||||
resolution: {integrity: sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
event-target-shim@5.0.1:
|
||||
resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
eventemitter3@4.0.7:
|
||||
resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==}
|
||||
|
||||
@ -2574,6 +2551,9 @@ packages:
|
||||
resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
form-data-encoder@1.7.2:
|
||||
resolution: {integrity: sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==}
|
||||
|
||||
form-data-encoder@2.1.4:
|
||||
resolution: {integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==}
|
||||
engines: {node: '>= 14.17'}
|
||||
@ -2586,6 +2566,10 @@ packages:
|
||||
resolution: {integrity: sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs=}
|
||||
engines: {node: '>=0.4.x'}
|
||||
|
||||
formdata-node@4.4.1:
|
||||
resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==}
|
||||
engines: {node: '>= 12.20'}
|
||||
|
||||
forwarded@0.2.0:
|
||||
resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
|
||||
engines: {node: '>= 0.6'}
|
||||
@ -2877,6 +2861,9 @@ packages:
|
||||
is-arrayish@0.3.2:
|
||||
resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==}
|
||||
|
||||
is-buffer@1.1.6:
|
||||
resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==}
|
||||
|
||||
is-deflate@1.0.0:
|
||||
resolution: {integrity: sha1-yGKQHDwWH7CdrHzcfnhPgOmPLxQ=}
|
||||
|
||||
@ -3250,6 +3237,9 @@ packages:
|
||||
engines: {node: '>=10.13.0'}
|
||||
hasBin: true
|
||||
|
||||
md5@2.3.0:
|
||||
resolution: {integrity: sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==}
|
||||
|
||||
mdast-util-find-and-replace@3.0.2:
|
||||
resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==}
|
||||
|
||||
@ -3555,6 +3545,19 @@ packages:
|
||||
no-case@2.3.2:
|
||||
resolution: {integrity: sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==}
|
||||
|
||||
node-domexception@1.0.0:
|
||||
resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
|
||||
engines: {node: '>=10.5.0'}
|
||||
|
||||
node-fetch@2.7.0:
|
||||
resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
|
||||
engines: {node: 4.x || >=6.0.0}
|
||||
peerDependencies:
|
||||
encoding: ^0.1.0
|
||||
peerDependenciesMeta:
|
||||
encoding:
|
||||
optional: true
|
||||
|
||||
node-forge@1.3.1:
|
||||
resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==}
|
||||
engines: {node: '>= 6.13.0'}
|
||||
@ -3615,6 +3618,18 @@ packages:
|
||||
resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
openai@4.87.3:
|
||||
resolution: {integrity: sha512-d2D54fzMuBYTxMW8wcNmhT1rYKcTfMJ8t+4KjH2KtvYenygITiGBgHoIrzHwnDQWW+C5oCA+ikIR2jgPCFqcKQ==}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
ws: ^8.18.0
|
||||
zod: ^3.23.8
|
||||
peerDependenciesMeta:
|
||||
ws:
|
||||
optional: true
|
||||
zod:
|
||||
optional: true
|
||||
|
||||
p-cancelable@3.0.0:
|
||||
resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==}
|
||||
engines: {node: '>=12.20'}
|
||||
@ -3910,9 +3925,6 @@ packages:
|
||||
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
|
||||
engines: {node: '>= 14.18.0'}
|
||||
|
||||
reflect-metadata@0.2.2:
|
||||
resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==}
|
||||
|
||||
regenerator-runtime@0.14.1:
|
||||
resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
|
||||
|
||||
@ -4291,6 +4303,9 @@ packages:
|
||||
resolution: {integrity: sha512-lbDrTLVsHhOMljPscd0yitpozq7Ga2M5Cvez5AjGg8GASBjtt6iERCAJ93yommPmz62fb45oFIXHEZ3u9bfJEA==}
|
||||
engines: {node: '>=14.16'}
|
||||
|
||||
tr46@0.0.3:
|
||||
resolution: {integrity: sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=}
|
||||
|
||||
tr46@3.0.0:
|
||||
resolution: {integrity: sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==}
|
||||
engines: {node: '>=12'}
|
||||
@ -4328,10 +4343,6 @@ packages:
|
||||
engines: {node: '>=18.0.0'}
|
||||
hasBin: true
|
||||
|
||||
tsyringe@4.8.0:
|
||||
resolution: {integrity: sha512-YB1FG+axdxADa3ncEtRnQCFq/M0lALGLxSZeVNbTU8NqhOVc51nnv2CISTcvc1kyv6EGPtXVr0v6lWeDxiijOA==}
|
||||
engines: {node: '>= 6.0.0'}
|
||||
|
||||
turndown-plugin-gfm@1.0.2:
|
||||
resolution: {integrity: sha512-vwz9tfvF7XN/jE0dGoBei3FXWuvll78ohzCZQuOb+ZjWrs3a0XhQVomJEb2Qh4VHTPNRO4GPZh0V7VRbiWwkRg==}
|
||||
|
||||
@ -4374,6 +4385,9 @@ packages:
|
||||
resolution: {integrity: sha512-ZPtzy0hu4cZjv3z5NW9gfKnNLjoz4y6uv4HlelAjDK7sY/xOkKZv9xK/WQpcsBB3jEybChz9DPC2U/+cusjJVQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
undici-types@5.26.5:
|
||||
resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
|
||||
|
||||
undici-types@6.20.0:
|
||||
resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==}
|
||||
|
||||
@ -4428,10 +4442,6 @@ packages:
|
||||
resolution: {integrity: sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=}
|
||||
engines: {node: '>= 0.4.0'}
|
||||
|
||||
uuid@11.1.0:
|
||||
resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==}
|
||||
hasBin: true
|
||||
|
||||
uuid@9.0.1:
|
||||
resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==}
|
||||
hasBin: true
|
||||
@ -4446,6 +4456,17 @@ packages:
|
||||
vfile@6.0.3:
|
||||
resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
|
||||
|
||||
web-streams-polyfill@3.3.3:
|
||||
resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==}
|
||||
engines: {node: '>= 8'}
|
||||
|
||||
web-streams-polyfill@4.0.0-beta.3:
|
||||
resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==}
|
||||
engines: {node: '>= 14'}
|
||||
|
||||
webidl-conversions@3.0.1:
|
||||
resolution: {integrity: sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=}
|
||||
|
||||
webidl-conversions@7.0.0:
|
||||
resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==}
|
||||
engines: {node: '>=12'}
|
||||
@ -4462,6 +4483,9 @@ packages:
|
||||
resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
whatwg-url@5.0.0:
|
||||
resolution: {integrity: sha1-lmRU6HZUYuN2RNNib2dCzotwll0=}
|
||||
|
||||
which-module@2.0.1:
|
||||
resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==}
|
||||
|
||||
@ -4602,6 +4626,20 @@ packages:
|
||||
|
||||
snapshots:
|
||||
|
||||
'@anthropic-ai/sdk@0.18.0':
|
||||
dependencies:
|
||||
'@types/node': 18.19.80
|
||||
'@types/node-fetch': 2.6.12
|
||||
abort-controller: 3.0.0
|
||||
agentkeepalive: 4.6.0
|
||||
digest-fetch: 1.3.0
|
||||
form-data-encoder: 1.7.2
|
||||
formdata-node: 4.4.1
|
||||
node-fetch: 2.7.0
|
||||
web-streams-polyfill: 3.3.3
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
|
||||
'@api.global/typedrequest-interfaces@2.0.2': {}
|
||||
|
||||
'@api.global/typedrequest-interfaces@3.0.19': {}
|
||||
@ -4692,15 +4730,15 @@ snapshots:
|
||||
'@pushrocks/smartstring': 4.0.7
|
||||
'@tsclass/tsclass': 4.4.4
|
||||
|
||||
'@apiclient.xyz/letterxpress@1.0.20(typescript@5.7.3)':
|
||||
'@apiclient.xyz/letterxpress@1.0.19(typescript@5.7.3)':
|
||||
dependencies:
|
||||
'@design.estate/dees-document': 1.6.9(typescript@5.7.3)
|
||||
'@push.rocks/smartbuffer': 3.0.4
|
||||
'@push.rocks/smartbuffer': 2.0.3
|
||||
'@push.rocks/smarthash': 3.0.4
|
||||
'@push.rocks/smartpromise': 4.2.3
|
||||
'@push.rocks/smartrequest': 2.0.23
|
||||
'@push.rocks/smartrx': 3.0.7
|
||||
'@tsclass/tsclass': 5.0.0
|
||||
'@tsclass/tsclass': 4.4.4
|
||||
transitivePeerDependencies:
|
||||
- '@nuxt/kit'
|
||||
- bare-buffer
|
||||
@ -5754,81 +5792,12 @@ snapshots:
|
||||
dependencies:
|
||||
pako: 1.0.11
|
||||
|
||||
'@peculiar/asn1-cms@2.3.15':
|
||||
dependencies:
|
||||
'@peculiar/asn1-schema': 2.3.15
|
||||
'@peculiar/asn1-x509': 2.3.15
|
||||
'@peculiar/asn1-x509-attr': 2.3.15
|
||||
asn1js: 3.0.5
|
||||
tslib: 2.8.1
|
||||
|
||||
'@peculiar/asn1-csr@2.3.15':
|
||||
dependencies:
|
||||
'@peculiar/asn1-schema': 2.3.15
|
||||
'@peculiar/asn1-x509': 2.3.15
|
||||
asn1js: 3.0.5
|
||||
tslib: 2.8.1
|
||||
|
||||
'@peculiar/asn1-ecc@2.3.15':
|
||||
dependencies:
|
||||
'@peculiar/asn1-schema': 2.3.15
|
||||
'@peculiar/asn1-x509': 2.3.15
|
||||
asn1js: 3.0.5
|
||||
tslib: 2.8.1
|
||||
|
||||
'@peculiar/asn1-pfx@2.3.15':
|
||||
dependencies:
|
||||
'@peculiar/asn1-cms': 2.3.15
|
||||
'@peculiar/asn1-pkcs8': 2.3.15
|
||||
'@peculiar/asn1-rsa': 2.3.15
|
||||
'@peculiar/asn1-schema': 2.3.15
|
||||
asn1js: 3.0.5
|
||||
tslib: 2.8.1
|
||||
|
||||
'@peculiar/asn1-pkcs8@2.3.15':
|
||||
dependencies:
|
||||
'@peculiar/asn1-schema': 2.3.15
|
||||
'@peculiar/asn1-x509': 2.3.15
|
||||
asn1js: 3.0.5
|
||||
tslib: 2.8.1
|
||||
|
||||
'@peculiar/asn1-pkcs9@2.3.15':
|
||||
dependencies:
|
||||
'@peculiar/asn1-cms': 2.3.15
|
||||
'@peculiar/asn1-pfx': 2.3.15
|
||||
'@peculiar/asn1-pkcs8': 2.3.15
|
||||
'@peculiar/asn1-schema': 2.3.15
|
||||
'@peculiar/asn1-x509': 2.3.15
|
||||
'@peculiar/asn1-x509-attr': 2.3.15
|
||||
asn1js: 3.0.5
|
||||
tslib: 2.8.1
|
||||
|
||||
'@peculiar/asn1-rsa@2.3.15':
|
||||
dependencies:
|
||||
'@peculiar/asn1-schema': 2.3.15
|
||||
'@peculiar/asn1-x509': 2.3.15
|
||||
asn1js: 3.0.5
|
||||
tslib: 2.8.1
|
||||
|
||||
'@peculiar/asn1-schema@2.3.13':
|
||||
dependencies:
|
||||
asn1js: 3.0.5
|
||||
pvtsutils: 1.3.6
|
||||
tslib: 2.8.1
|
||||
|
||||
'@peculiar/asn1-schema@2.3.15':
|
||||
dependencies:
|
||||
asn1js: 3.0.5
|
||||
pvtsutils: 1.3.6
|
||||
tslib: 2.8.1
|
||||
|
||||
'@peculiar/asn1-x509-attr@2.3.15':
|
||||
dependencies:
|
||||
'@peculiar/asn1-schema': 2.3.15
|
||||
'@peculiar/asn1-x509': 2.3.15
|
||||
asn1js: 3.0.5
|
||||
tslib: 2.8.1
|
||||
|
||||
'@peculiar/asn1-x509-logotype@2.3.13':
|
||||
dependencies:
|
||||
'@peculiar/asn1-schema': 2.3.13
|
||||
@ -5844,27 +5813,6 @@ snapshots:
|
||||
pvtsutils: 1.3.6
|
||||
tslib: 2.8.1
|
||||
|
||||
'@peculiar/asn1-x509@2.3.15':
|
||||
dependencies:
|
||||
'@peculiar/asn1-schema': 2.3.15
|
||||
asn1js: 3.0.5
|
||||
pvtsutils: 1.3.6
|
||||
tslib: 2.8.1
|
||||
|
||||
'@peculiar/x509@1.12.3':
|
||||
dependencies:
|
||||
'@peculiar/asn1-cms': 2.3.15
|
||||
'@peculiar/asn1-csr': 2.3.15
|
||||
'@peculiar/asn1-ecc': 2.3.15
|
||||
'@peculiar/asn1-pkcs9': 2.3.15
|
||||
'@peculiar/asn1-rsa': 2.3.15
|
||||
'@peculiar/asn1-schema': 2.3.13
|
||||
'@peculiar/asn1-x509': 2.3.13
|
||||
pvtsutils: 1.3.6
|
||||
reflect-metadata: 0.2.2
|
||||
tslib: 2.8.1
|
||||
tsyringe: 4.8.0
|
||||
|
||||
'@pkgjs/parseargs@0.11.0':
|
||||
optional: true
|
||||
|
||||
@ -6013,6 +5961,10 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- aws-crt
|
||||
|
||||
'@push.rocks/smartbuffer@2.0.3':
|
||||
dependencies:
|
||||
uint8array-extras: 1.4.0
|
||||
|
||||
'@push.rocks/smartbuffer@3.0.4':
|
||||
dependencies:
|
||||
uint8array-extras: 1.4.0
|
||||
@ -6321,25 +6273,6 @@ snapshots:
|
||||
|
||||
'@push.rocks/smartpromise@4.2.3': {}
|
||||
|
||||
'@push.rocks/smartproxy@4.1.0':
|
||||
dependencies:
|
||||
'@push.rocks/lik': 6.1.0
|
||||
'@push.rocks/smartdelay': 3.0.5
|
||||
'@push.rocks/smartpromise': 4.2.3
|
||||
'@push.rocks/smartrequest': 2.0.23
|
||||
'@push.rocks/smartstring': 4.0.15
|
||||
'@tsclass/tsclass': 5.0.0
|
||||
'@types/minimatch': 5.1.2
|
||||
'@types/ws': 8.18.0
|
||||
acme-client: 5.4.0
|
||||
minimatch: 10.0.1
|
||||
pretty-ms: 9.2.0
|
||||
ws: 8.18.1
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- supports-color
|
||||
- utf-8-validate
|
||||
|
||||
'@push.rocks/smartpuppeteer@2.0.5(typescript@5.7.3)':
|
||||
dependencies:
|
||||
'@push.rocks/smartdelay': 3.0.5
|
||||
@ -6366,8 +6299,6 @@ snapshots:
|
||||
'@push.rocks/smartrx': 3.0.7
|
||||
path-to-regexp: 8.2.0
|
||||
|
||||
'@push.rocks/smartrule@2.0.1': {}
|
||||
|
||||
'@push.rocks/smartrx@3.0.7':
|
||||
dependencies:
|
||||
'@push.rocks/smartpromise': 4.2.3
|
||||
@ -6771,7 +6702,7 @@ snapshots:
|
||||
domhandler: 5.0.3
|
||||
selderee: 0.11.0
|
||||
|
||||
'@serve.zone/interfaces@4.12.1':
|
||||
'@serve.zone/interfaces@1.1.2':
|
||||
dependencies:
|
||||
'@api.global/typedrequest-interfaces': 3.0.19
|
||||
'@push.rocks/smartlog-interfaces': 3.0.2
|
||||
@ -7144,10 +7075,6 @@ snapshots:
|
||||
dependencies:
|
||||
type-fest: 4.37.0
|
||||
|
||||
'@tsclass/tsclass@5.0.0':
|
||||
dependencies:
|
||||
type-fest: 4.37.0
|
||||
|
||||
'@types/accepts@1.3.7':
|
||||
dependencies:
|
||||
'@types/node': 22.13.10
|
||||
@ -7320,11 +7247,6 @@ snapshots:
|
||||
'@types/koa-compose': 3.2.8
|
||||
'@types/node': 22.13.10
|
||||
|
||||
'@types/mailparser@3.4.5':
|
||||
dependencies:
|
||||
'@types/node': 22.13.10
|
||||
iconv-lite: 0.6.3
|
||||
|
||||
'@types/mdast@4.0.4':
|
||||
dependencies:
|
||||
'@types/unist': 3.0.3
|
||||
@ -7339,10 +7261,19 @@ snapshots:
|
||||
|
||||
'@types/ms@2.1.0': {}
|
||||
|
||||
'@types/node-fetch@2.6.12':
|
||||
dependencies:
|
||||
'@types/node': 18.19.80
|
||||
form-data: 4.0.2
|
||||
|
||||
'@types/node-forge@1.3.11':
|
||||
dependencies:
|
||||
'@types/node': 22.13.10
|
||||
|
||||
'@types/node@18.19.80':
|
||||
dependencies:
|
||||
undici-types: 5.26.5
|
||||
|
||||
'@types/node@22.13.10':
|
||||
dependencies:
|
||||
undici-types: 6.20.0
|
||||
@ -7527,21 +7458,15 @@ snapshots:
|
||||
- supports-color
|
||||
- utf-8-validate
|
||||
|
||||
abort-controller@3.0.0:
|
||||
dependencies:
|
||||
event-target-shim: 5.0.1
|
||||
|
||||
accepts@1.3.8:
|
||||
dependencies:
|
||||
mime-types: 2.1.35
|
||||
negotiator: 0.6.3
|
||||
|
||||
acme-client@5.4.0:
|
||||
dependencies:
|
||||
'@peculiar/x509': 1.12.3
|
||||
asn1js: 3.0.5
|
||||
axios: 1.8.3(debug@4.4.0)
|
||||
debug: 4.4.0
|
||||
node-forge: 1.3.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
agent-base@6.0.2:
|
||||
dependencies:
|
||||
debug: 4.4.0
|
||||
@ -7613,14 +7538,6 @@ snapshots:
|
||||
|
||||
axe-core@4.10.3: {}
|
||||
|
||||
axios@1.8.3(debug@4.4.0):
|
||||
dependencies:
|
||||
follow-redirects: 1.15.9(debug@4.4.0)
|
||||
form-data: 4.0.2
|
||||
proxy-from-env: 1.1.0
|
||||
transitivePeerDependencies:
|
||||
- debug
|
||||
|
||||
b4a@1.6.7: {}
|
||||
|
||||
bail@2.0.2: {}
|
||||
@ -7654,6 +7571,8 @@ snapshots:
|
||||
bare-events: 2.5.4
|
||||
optional: true
|
||||
|
||||
base-64@0.1.0: {}
|
||||
|
||||
base64-js@1.5.1: {}
|
||||
|
||||
base64id@2.0.0: {}
|
||||
@ -7805,6 +7724,8 @@ snapshots:
|
||||
|
||||
character-entities@2.0.2: {}
|
||||
|
||||
charenc@0.0.2: {}
|
||||
|
||||
chokidar@4.0.3:
|
||||
dependencies:
|
||||
readdirp: 4.1.2
|
||||
@ -7950,6 +7871,8 @@ snapshots:
|
||||
shebang-command: 2.0.0
|
||||
which: 2.0.2
|
||||
|
||||
crypt@0.0.2: {}
|
||||
|
||||
crypto-random-string@5.0.0:
|
||||
dependencies:
|
||||
type-fest: 2.19.0
|
||||
@ -8046,6 +7969,11 @@ snapshots:
|
||||
|
||||
diff-sequences@29.6.3: {}
|
||||
|
||||
digest-fetch@1.3.0:
|
||||
dependencies:
|
||||
base-64: 0.1.0
|
||||
md5: 2.3.0
|
||||
|
||||
dijkstrajs@1.0.3: {}
|
||||
|
||||
dir-glob@3.0.1:
|
||||
@ -8258,6 +8186,8 @@ snapshots:
|
||||
|
||||
etag@1.8.1: {}
|
||||
|
||||
event-target-shim@5.0.1: {}
|
||||
|
||||
eventemitter3@4.0.7: {}
|
||||
|
||||
execa@5.1.1:
|
||||
@ -8438,6 +8368,8 @@ snapshots:
|
||||
cross-spawn: 7.0.6
|
||||
signal-exit: 4.1.0
|
||||
|
||||
form-data-encoder@1.7.2: {}
|
||||
|
||||
form-data-encoder@2.1.4: {}
|
||||
|
||||
form-data@4.0.2:
|
||||
@ -8449,6 +8381,11 @@ snapshots:
|
||||
|
||||
format@0.2.2: {}
|
||||
|
||||
formdata-node@4.4.1:
|
||||
dependencies:
|
||||
node-domexception: 1.0.0
|
||||
web-streams-polyfill: 4.0.0-beta.3
|
||||
|
||||
forwarded@0.2.0: {}
|
||||
|
||||
fresh@0.5.2: {}
|
||||
@ -8811,6 +8748,8 @@ snapshots:
|
||||
|
||||
is-arrayish@0.3.2: {}
|
||||
|
||||
is-buffer@1.1.6: {}
|
||||
|
||||
is-deflate@1.0.0: {}
|
||||
|
||||
is-docker@2.2.1: {}
|
||||
@ -9226,6 +9165,12 @@ snapshots:
|
||||
|
||||
md5-file@5.0.0: {}
|
||||
|
||||
md5@2.3.0:
|
||||
dependencies:
|
||||
charenc: 0.0.2
|
||||
crypt: 0.0.2
|
||||
is-buffer: 1.1.6
|
||||
|
||||
mdast-util-find-and-replace@3.0.2:
|
||||
dependencies:
|
||||
'@types/mdast': 4.0.4
|
||||
@ -9700,6 +9645,12 @@ snapshots:
|
||||
dependencies:
|
||||
lower-case: 1.1.4
|
||||
|
||||
node-domexception@1.0.0: {}
|
||||
|
||||
node-fetch@2.7.0:
|
||||
dependencies:
|
||||
whatwg-url: 5.0.0
|
||||
|
||||
node-forge@1.3.1: {}
|
||||
|
||||
nodemailer@6.9.16: {}
|
||||
@ -9748,6 +9699,21 @@ snapshots:
|
||||
is-docker: 2.2.1
|
||||
is-wsl: 2.2.0
|
||||
|
||||
openai@4.87.3(ws@8.18.1)(zod@3.24.2):
|
||||
dependencies:
|
||||
'@types/node': 18.19.80
|
||||
'@types/node-fetch': 2.6.12
|
||||
abort-controller: 3.0.0
|
||||
agentkeepalive: 4.6.0
|
||||
form-data-encoder: 1.7.2
|
||||
formdata-node: 4.4.1
|
||||
node-fetch: 2.7.0
|
||||
optionalDependencies:
|
||||
ws: 8.18.1
|
||||
zod: 3.24.2
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
|
||||
p-cancelable@3.0.0: {}
|
||||
|
||||
p-event@4.2.0:
|
||||
@ -10065,8 +10031,6 @@ snapshots:
|
||||
|
||||
readdirp@4.1.2: {}
|
||||
|
||||
reflect-metadata@0.2.2: {}
|
||||
|
||||
regenerator-runtime@0.14.1: {}
|
||||
|
||||
registry-auth-token@5.1.0:
|
||||
@ -10545,6 +10509,8 @@ snapshots:
|
||||
'@tokenizer/token': 0.3.0
|
||||
ieee754: 1.2.1
|
||||
|
||||
tr46@0.0.3: {}
|
||||
|
||||
tr46@3.0.0:
|
||||
dependencies:
|
||||
punycode: 2.3.1
|
||||
@ -10574,10 +10540,6 @@ snapshots:
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
|
||||
tsyringe@4.8.0:
|
||||
dependencies:
|
||||
tslib: 1.14.1
|
||||
|
||||
turndown-plugin-gfm@1.0.2: {}
|
||||
|
||||
turndown@7.2.0:
|
||||
@ -10605,6 +10567,8 @@ snapshots:
|
||||
|
||||
uint8array-extras@1.4.0: {}
|
||||
|
||||
undici-types@5.26.5: {}
|
||||
|
||||
undici-types@6.20.0: {}
|
||||
|
||||
undici@5.28.4:
|
||||
@ -10663,8 +10627,6 @@ snapshots:
|
||||
|
||||
utils-merge@1.0.1: {}
|
||||
|
||||
uuid@11.1.0: {}
|
||||
|
||||
uuid@9.0.1: {}
|
||||
|
||||
vary@1.1.2: {}
|
||||
@ -10679,6 +10641,12 @@ snapshots:
|
||||
'@types/unist': 3.0.3
|
||||
vfile-message: 4.0.2
|
||||
|
||||
web-streams-polyfill@3.3.3: {}
|
||||
|
||||
web-streams-polyfill@4.0.0-beta.3: {}
|
||||
|
||||
webidl-conversions@3.0.1: {}
|
||||
|
||||
webidl-conversions@7.0.0: {}
|
||||
|
||||
whatwg-mimetype@3.0.0: {}
|
||||
@ -10693,6 +10661,11 @@ snapshots:
|
||||
tr46: 5.1.0
|
||||
webidl-conversions: 7.0.0
|
||||
|
||||
whatwg-url@5.0.0:
|
||||
dependencies:
|
||||
tr46: 0.0.3
|
||||
webidl-conversions: 3.0.1
|
||||
|
||||
which-module@2.0.1: {}
|
||||
|
||||
which@2.0.2:
|
||||
|
78
readme.md
78
readme.md
@ -103,81 +103,6 @@ async function sendLetter() {
|
||||
sendLetter();
|
||||
```
|
||||
|
||||
### Mail Transfer Agent (MTA)
|
||||
|
||||
The platform includes a robust Mail Transfer Agent (MTA) for enterprise-grade email handling with complete control over the email delivery process:
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
API[API Clients] --> ApiManager
|
||||
SMTP[External SMTP Servers] <--> SMTPServer
|
||||
|
||||
subgraph "MTA Service"
|
||||
MtaService[MTA Service] --> SMTPServer[SMTP Server]
|
||||
MtaService --> EmailSendJob[Email Send Job]
|
||||
MtaService --> DnsManager[DNS Manager]
|
||||
MtaService --> DkimCreator[DKIM Creator]
|
||||
ApiManager[API Manager] --> MtaService
|
||||
end
|
||||
|
||||
subgraph "External Services"
|
||||
DnsManager <--> DNS[DNS Servers]
|
||||
EmailSendJob <--> MXServers[MX Servers]
|
||||
end
|
||||
```
|
||||
|
||||
The MTA service provides:
|
||||
- Complete SMTP server for receiving emails
|
||||
- DKIM signing and verification
|
||||
- SPF and DMARC support
|
||||
- DNS record management
|
||||
- Retry logic with queue processing
|
||||
- TLS encryption
|
||||
|
||||
Here's how to use the MTA service:
|
||||
|
||||
```ts
|
||||
import { MtaService, Email } from '@serve.zone/platformservice';
|
||||
|
||||
async function useMtaService() {
|
||||
// Initialize MTA service
|
||||
const mtaService = new MtaService(platformService);
|
||||
await mtaService.start();
|
||||
|
||||
// Send an email
|
||||
const email = new Email({
|
||||
from: 'sender@yourdomain.com',
|
||||
to: 'recipient@example.com',
|
||||
subject: 'Hello World',
|
||||
text: 'This is a test email',
|
||||
html: '<p>This is a <b>test</b> email</p>',
|
||||
attachments: [] // Optional attachments
|
||||
});
|
||||
|
||||
const emailId = await mtaService.send(email);
|
||||
console.log(`Email queued with ID: ${emailId}`);
|
||||
|
||||
// Check email status
|
||||
const status = mtaService.getEmailStatus(emailId);
|
||||
console.log(`Email status: ${status.status}`);
|
||||
|
||||
// Set up API for external access
|
||||
const apiManager = new ApiManager(mtaService);
|
||||
await apiManager.start(3000);
|
||||
console.log('MTA API running on port 3000');
|
||||
}
|
||||
|
||||
useMtaService();
|
||||
```
|
||||
|
||||
The MTA provides key advantages for applications requiring:
|
||||
- High-volume email sending
|
||||
- Compliance with email authentication standards
|
||||
- Detailed delivery tracking
|
||||
- Custom email handling logic
|
||||
- Multi-domain email management
|
||||
- Complete control over email infrastructure
|
||||
|
||||
### Leveraging AI Services
|
||||
|
||||
The platform also integrates AI functionalities, allowing for innovative use cases like generating content, analyzing text, or automating responses:
|
||||
@ -197,4 +122,5 @@ useAiService();
|
||||
|
||||
### Conclusion
|
||||
|
||||
The `@serve.zone/platformservice` offers a robust set of features for modern application requirements, including but not limited to communication and AI services. By following the examples above, developers can integrate these services into their applications, harnessing the power of email, SMS, letters, MTA capabilities, and artificial intelligence seamlessly.
|
||||
The `@serve.zone/platformservice` offers a robust set of features for modern application requirements, including but not limited to communication and AI services. By following the examples above, developers can integrate these services into their applications, harnessing the power of email, SMS, letters, and artificial intelligence seamlessly.
|
||||
undefined
|
@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@serve.zone/platformservice',
|
||||
version: '2.3.0',
|
||||
version: '1.1.1',
|
||||
description: 'A multifaceted platform service handling mail, SMS, letter delivery, and AI services.'
|
||||
}
|
||||
|
50
ts/aibridge/aibridge.classes.aibridge.ts
Normal file
50
ts/aibridge/aibridge.classes.aibridge.ts
Normal file
@ -0,0 +1,50 @@
|
||||
import * as plugins from './aibridge.plugins.js';
|
||||
import * as paths from './aibridge.paths.js';
|
||||
import { AiBridgeDb } from './aibridge.classes.aibridgedb.js';
|
||||
import { OpenAiBridge } from './aibridge.classes.openaibridge.js';
|
||||
|
||||
export class AiBridge {
|
||||
public projectinfo: plugins.projectinfo.ProjectInfo;
|
||||
public serverInstance: plugins.loleServiceserver.ServiceServer;
|
||||
public serviceQenv = new plugins.qenv.Qenv('./', './.nogit');
|
||||
public aibridgeDb: AiBridgeDb;
|
||||
|
||||
public openAiBridge: OpenAiBridge;
|
||||
|
||||
public typedrouter = new plugins.typedrequest.TypedRouter();
|
||||
|
||||
public async start() {
|
||||
this.aibridgeDb = new AiBridgeDb(this);
|
||||
await this.aibridgeDb.start();
|
||||
this.projectinfo = new plugins.projectinfo.ProjectInfo(paths.packageDir);
|
||||
this.openAiBridge = new OpenAiBridge(this);
|
||||
await this.openAiBridge.start();
|
||||
|
||||
// server
|
||||
this.serverInstance = new plugins.loleServiceserver.ServiceServer({
|
||||
serviceDomain: 'aibridge.lossless.one',
|
||||
serviceName: 'aibridge',
|
||||
serviceVersion: this.projectinfo.npm.version,
|
||||
addCustomRoutes: async (serverArg) => {
|
||||
// any custom route configs go here
|
||||
},
|
||||
});
|
||||
|
||||
// lets implemenet the actual typedrequest functions
|
||||
this.typedrouter.addTypedHandler<plugins.lointAiBridge.requests.IReq_Chat>(new plugins.typedrequest.TypedHandler('chat', async reqArg => {
|
||||
const resultChat = await this.openAiBridge.chat(reqArg.chat.systemMessage, reqArg.chat.messages[reqArg.chat.messages.length - 1].content, reqArg.chat.messages);
|
||||
return {
|
||||
chat: reqArg.chat,
|
||||
latestMessage: resultChat.message.content,
|
||||
}
|
||||
}))
|
||||
|
||||
await this.serverInstance.start();
|
||||
this.serverInstance.typedServer.typedrouter.addTypedRouter(this.typedrouter);
|
||||
}
|
||||
|
||||
public async stop() {
|
||||
await this.serverInstance.stop();
|
||||
await this.aibridgeDb.stop();
|
||||
}
|
||||
}
|
25
ts/aibridge/aibridge.classes.aibridgedb.ts
Normal file
25
ts/aibridge/aibridge.classes.aibridgedb.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import * as plugins from './aibridge.plugins.js';
|
||||
import { AiBridge } from './aibridge.classes.aibridge.js';
|
||||
|
||||
export class AiBridgeDb {
|
||||
public smartdataDb: plugins.smartdata.SmartdataDb;
|
||||
public aibridgeRef: AiBridge;
|
||||
|
||||
constructor(aibridgeRefArg: AiBridge) {
|
||||
this.aibridgeRef = aibridgeRefArg;
|
||||
}
|
||||
|
||||
public async start() {
|
||||
this.smartdataDb = new plugins.smartdata.SmartdataDb({
|
||||
mongoDbUser: await this.aibridgeRef.serviceQenv.getEnvVarOnDemand('MONGO_DB_USER'),
|
||||
mongoDbName: await this.aibridgeRef.serviceQenv.getEnvVarOnDemand('MONGO_DB_NAME'),
|
||||
mongoDbPass: await this.aibridgeRef.serviceQenv.getEnvVarOnDemand('MONGO_DB_PASS'),
|
||||
mongoDbUrl: await this.aibridgeRef.serviceQenv.getEnvVarOnDemand('MONGO_DB_URL'),
|
||||
});
|
||||
await this.smartdataDb.init();
|
||||
}
|
||||
|
||||
public async stop() {
|
||||
await this.smartdataDb.close();
|
||||
}
|
||||
}
|
58
ts/aibridge/aibridge.classes.openaibridge.ts
Normal file
58
ts/aibridge/aibridge.classes.openaibridge.ts
Normal file
@ -0,0 +1,58 @@
|
||||
import { AiBridge } from './aibridge.classes.aibridge.js';
|
||||
import * as plugins from './aibridge.plugins.js';
|
||||
import * as paths from './aibridge.paths.js';
|
||||
|
||||
export class OpenAiBridge {
|
||||
public aiBridgeRef: AiBridge;
|
||||
public openAiApiClient: plugins.openai.default;
|
||||
constructor(aiBridgeRefArg: AiBridge) {
|
||||
this.aiBridgeRef = aiBridgeRefArg;
|
||||
}
|
||||
|
||||
public async start() {
|
||||
const openAiToken = await this.aiBridgeRef.serviceQenv.getEnvVarOnDemand('OPENAI_TOKEN');
|
||||
this.openAiApiClient = new plugins.openai.default({
|
||||
apiKey: openAiToken,
|
||||
dangerouslyAllowBrowser: true,
|
||||
});
|
||||
}
|
||||
|
||||
public async stop() {}
|
||||
|
||||
public async chat(
|
||||
systemMessage: string,
|
||||
userMessage: string,
|
||||
messageHistory: {
|
||||
role: 'assistant' | 'user';
|
||||
content: string;
|
||||
}[]
|
||||
) {
|
||||
const result = await this.openAiApiClient.chat.completions.create({
|
||||
model: 'gpt-4-turbo-preview',
|
||||
messages: [
|
||||
{ role: 'system', content: systemMessage },
|
||||
...messageHistory,
|
||||
{ role: 'user', content: userMessage },
|
||||
],
|
||||
});
|
||||
return {
|
||||
message: result.choices[0].message,
|
||||
};
|
||||
}
|
||||
|
||||
public async audio(messageArg: string) {
|
||||
const done = plugins.smartpromise.defer();
|
||||
const result = await this.openAiApiClient.audio.speech.create({
|
||||
model: 'tts-1-hd',
|
||||
input: messageArg,
|
||||
voice: 'nova',
|
||||
response_format: 'mp3',
|
||||
speed: 1,
|
||||
});
|
||||
const stream = result.body.pipe(plugins.smartfile.fsStream.createWriteStream(plugins.path.join(paths.nogitDir, 'output.mp3')));
|
||||
stream.on('finish', () => {
|
||||
done.resolve();
|
||||
});
|
||||
return done.promise;
|
||||
}
|
||||
}
|
16
ts/aibridge/aibridge.paths.ts
Normal file
16
ts/aibridge/aibridge.paths.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import * as plugins from './aibridge.plugins.js';
|
||||
|
||||
export const packageDir = plugins.path.join(
|
||||
plugins.smartpath.get.dirnameFromImportMetaUrl(import.meta.url),
|
||||
'../'
|
||||
);
|
||||
|
||||
export const assetsDir = plugins.path.join(
|
||||
packageDir,
|
||||
'./assets/'
|
||||
);
|
||||
|
||||
export const nogitDir = plugins.path.join(
|
||||
packageDir,
|
||||
'./.nogit/'
|
||||
);
|
32
ts/aibridge/aibridge.plugins.ts
Normal file
32
ts/aibridge/aibridge.plugins.ts
Normal file
@ -0,0 +1,32 @@
|
||||
// node native
|
||||
import * as path from 'path';
|
||||
|
||||
export { path };
|
||||
|
||||
// @losslessone_private scope
|
||||
import * as loleServiceserver from '@losslessone_private/lole-serviceserver';
|
||||
import * as lointAiBridge from '@losslessone_private/loint-aibridge';
|
||||
|
||||
export { loleServiceserver, lointAiBridge };
|
||||
|
||||
// apiglobal scope
|
||||
import * as typedrequest from '@api.global/typedrequest';
|
||||
|
||||
export {
|
||||
typedrequest,
|
||||
}
|
||||
|
||||
// pushrocks scope
|
||||
import * as projectinfo from '@push.rocks/projectinfo';
|
||||
import * as qenv from '@push.rocks/qenv';
|
||||
import * as smartdata from '@push.rocks/smartdata';
|
||||
import * as smartfile from '@push.rocks/smartfile';
|
||||
import * as smartpath from '@push.rocks/smartpath';
|
||||
import * as smartpromise from '@push.rocks/smartpromise';
|
||||
|
||||
export { projectinfo, qenv, smartdata, smartfile, smartpath, smartpromise };
|
||||
|
||||
// thirdparty scope
|
||||
import * as antrophic from '@anthropic-ai/sdk';
|
||||
import * as openai from 'openai';
|
||||
export { antrophic as anthropic, openai };
|
@ -1,3 +0,0 @@
|
||||
export class AIBridge {
|
||||
|
||||
}
|
17
ts/aibridge/index.ts
Normal file
17
ts/aibridge/index.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { AiBridge } from './aibridge.classes.aibridge.js';
|
||||
|
||||
export {
|
||||
AiBridge,
|
||||
}
|
||||
|
||||
let aibridgeInstance: AiBridge;
|
||||
export const runCli = async () => {
|
||||
aibridgeInstance = new AiBridge();
|
||||
await aibridgeInstance.start();
|
||||
};
|
||||
|
||||
export const stop = async () => {
|
||||
if (aibridgeInstance) {
|
||||
await aibridgeInstance.stop();
|
||||
}
|
||||
};
|
@ -1,10 +1,10 @@
|
||||
import * as plugins from './plugins.js';
|
||||
import * as paths from './paths.js';
|
||||
import { PlatformServiceDb } from './classes.platformservicedb.js'
|
||||
import { EmailService } from './email/classes.emailservice.js';
|
||||
import { SmsService } from './sms/classes.smsservice.js';
|
||||
import { EmailService } from './email/email.classes.emailservice.js';
|
||||
import { SmsService } from './sms/smsservice.js';
|
||||
import { LetterService } from './letter/classes.letterservice.js';
|
||||
import { MtaService } from './mta/classes.mta.js';
|
||||
import { MtaService } from './mta/mta.classes.mta.js';
|
||||
|
||||
export class SzPlatformService {
|
||||
public projectinfo: plugins.projectinfo.ProjectInfo;
|
@ -1,5 +1,5 @@
|
||||
import * as plugins from './plugins.js';
|
||||
import { SzPlatformService } from './platformservice.js';
|
||||
import { SzPlatformService } from './classes.platformservice.js';
|
||||
|
||||
|
||||
|
||||
|
@ -1,87 +0,0 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
import { EmailService } from './classes.emailservice.js';
|
||||
import { logger } from '../logger.js';
|
||||
|
||||
export class ApiManager {
|
||||
public emailRef: EmailService;
|
||||
public typedRouter = new plugins.typedrequest.TypedRouter();
|
||||
|
||||
constructor(emailRefArg: EmailService) {
|
||||
this.emailRef = emailRefArg;
|
||||
this.emailRef.typedrouter.addTypedRouter(this.typedRouter);
|
||||
|
||||
// Register API endpoints
|
||||
this.registerApiEndpoints();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register API endpoints for email functionality
|
||||
*/
|
||||
private registerApiEndpoints() {
|
||||
// Register the SendEmail endpoint
|
||||
this.typedRouter.addTypedHandler<plugins.servezoneInterfaces.platformservice.mta.IRequest_SendEmail>(
|
||||
new plugins.typedrequest.TypedHandler('sendEmail', async (requestData) => {
|
||||
const mailToSend = new plugins.smartmail.Smartmail({
|
||||
body: requestData.body,
|
||||
from: requestData.from,
|
||||
subject: requestData.title,
|
||||
});
|
||||
|
||||
if (requestData.attachments) {
|
||||
for (const attachment of requestData.attachments) {
|
||||
mailToSend.addAttachment(
|
||||
await plugins.smartfile.SmartFile.fromString(
|
||||
attachment.name,
|
||||
attachment.binaryAttachmentString,
|
||||
'binary'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Send email through the service which will route to the appropriate connector
|
||||
const emailId = await this.emailRef.sendEmail(mailToSend, requestData.to, {});
|
||||
|
||||
logger.log(
|
||||
'info',
|
||||
`sent an email to ${requestData.to} with subject '${mailToSend.getSubject()}'`,
|
||||
{
|
||||
eventType: 'sentEmail',
|
||||
email: {
|
||||
to: requestData.to,
|
||||
subject: mailToSend.getSubject(),
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
responseId: emailId,
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
// Add endpoint to check email status
|
||||
this.typedRouter.addTypedHandler<{ emailId: string }>(
|
||||
new plugins.typedrequest.TypedHandler('checkEmailStatus', async (requestData) => {
|
||||
// If MTA is enabled, use it to check status
|
||||
if (this.emailRef.mtaConnector) {
|
||||
const status = await this.emailRef.mtaConnector.checkEmailStatus(requestData.emailId);
|
||||
return status;
|
||||
}
|
||||
|
||||
// For Mailgun, we don't have a status check implementation currently
|
||||
return {
|
||||
status: 'unknown',
|
||||
details: { message: 'Status tracking not available for current provider' }
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
// Add statistics endpoint
|
||||
this.typedRouter.addTypedHandler<void>(
|
||||
new plugins.typedrequest.TypedHandler('getEmailStats', async () => {
|
||||
return this.emailRef.getStats();
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
@ -1,169 +0,0 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
import { EmailService } from './classes.emailservice.js';
|
||||
import { logger } from '../logger.js';
|
||||
|
||||
// Import MTA classes
|
||||
import {
|
||||
MtaService,
|
||||
Email as MtaEmail,
|
||||
type IEmailOptions,
|
||||
DeliveryStatus,
|
||||
type IAttachment
|
||||
} from '../mta/index.js';
|
||||
|
||||
export class MtaConnector {
|
||||
public emailRef: EmailService;
|
||||
private mtaService: MtaService;
|
||||
|
||||
constructor(emailRefArg: EmailService, mtaService?: MtaService) {
|
||||
this.emailRef = emailRefArg;
|
||||
this.mtaService = mtaService || this.emailRef.mtaService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an email using the MTA service
|
||||
* @param smartmail The email to send
|
||||
* @param toAddresses Recipients (comma-separated or array)
|
||||
* @param options Additional options
|
||||
*/
|
||||
public async sendEmail(
|
||||
smartmail: plugins.smartmail.Smartmail<>,
|
||||
toAddresses: string | string[],
|
||||
options: any = {}
|
||||
): Promise<string> {
|
||||
try {
|
||||
// Process recipients
|
||||
const toArray = Array.isArray(toAddresses)
|
||||
? toAddresses
|
||||
: toAddresses.split(',').map(addr => addr.trim());
|
||||
|
||||
// Map SmartMail attachments to MTA attachments
|
||||
const attachments: IAttachment[] = smartmail.attachments.map(attachment => {
|
||||
return {
|
||||
filename: attachment.parsedPath.base,
|
||||
content: Buffer.from(attachment.contentBuffer),
|
||||
contentType: (attachment as any)?.getContentType?.() || 'application/octet-stream' // TODO: revisit after smartfile has been updated
|
||||
};
|
||||
});
|
||||
|
||||
// Create MTA Email
|
||||
const mtaEmail = new MtaEmail({
|
||||
from: smartmail.options.from,
|
||||
to: toArray,
|
||||
subject: smartmail.getSubject(),
|
||||
text: smartmail.getBody(false), // Plain text version
|
||||
html: smartmail.getBody(true), // HTML version
|
||||
attachments
|
||||
});
|
||||
|
||||
// Send using MTA
|
||||
const emailId = await this.mtaService.send(mtaEmail);
|
||||
|
||||
logger.log('info', `Email sent via MTA to ${toAddresses}`, {
|
||||
eventType: 'sentEmail',
|
||||
provider: 'mta',
|
||||
emailId,
|
||||
to: toAddresses
|
||||
});
|
||||
|
||||
return emailId;
|
||||
} catch (error) {
|
||||
logger.log('error', `Failed to send email via MTA: ${error.message}`, {
|
||||
eventType: 'emailError',
|
||||
provider: 'mta',
|
||||
error: error.message
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve and process an incoming email
|
||||
* For MTA, this would handle an email already received by the SMTP server
|
||||
* @param emailData The raw email data or identifier
|
||||
*/
|
||||
public async receiveEmail(emailData: string): Promise<plugins.smartmail.Smartmail<>> {
|
||||
try {
|
||||
// In a real implementation, this would retrieve an email from the MTA storage
|
||||
// For now, we can use a simplified approach:
|
||||
|
||||
// Parse the email (assuming emailData is a raw email or a file path)
|
||||
const parsedEmail = await plugins.mailparser.simpleParser(emailData);
|
||||
|
||||
// Create a Smartmail from the parsed email
|
||||
const smartmail = new plugins.smartmail.Smartmail({
|
||||
from: parsedEmail.from?.text || '',
|
||||
subject: parsedEmail.subject || '',
|
||||
body: parsedEmail.html || parsedEmail.text || '',
|
||||
creationObjectRef: {
|
||||
From: parsedEmail.from?.text || '',
|
||||
To: parsedEmail.to?.text || '',
|
||||
Subject: parsedEmail.subject || ''
|
||||
}
|
||||
});
|
||||
|
||||
// Add attachments if present
|
||||
if (parsedEmail.attachments && parsedEmail.attachments.length > 0) {
|
||||
for (const attachment of parsedEmail.attachments) {
|
||||
smartmail.addAttachment(
|
||||
await plugins.smartfile.SmartFile.fromBuffer(
|
||||
attachment.filename || 'attachment',
|
||||
attachment.content
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return smartmail;
|
||||
} catch (error) {
|
||||
logger.log('error', `Failed to receive email via MTA: ${error.message}`, {
|
||||
eventType: 'emailError',
|
||||
provider: 'mta',
|
||||
error: error.message
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the status of a sent email
|
||||
* @param emailId The email ID to check
|
||||
*/
|
||||
public async checkEmailStatus(emailId: string): Promise<{
|
||||
status: string;
|
||||
details?: any;
|
||||
}> {
|
||||
try {
|
||||
const status = this.mtaService.getEmailStatus(emailId);
|
||||
|
||||
if (!status) {
|
||||
return {
|
||||
status: 'unknown',
|
||||
details: { message: 'Email not found' }
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
status: status.status,
|
||||
details: {
|
||||
attempts: status.attempts,
|
||||
lastAttempt: status.lastAttempt,
|
||||
nextAttempt: status.nextAttempt,
|
||||
error: status.error?.message
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
logger.log('error', `Failed to check email status: ${error.message}`, {
|
||||
eventType: 'emailError',
|
||||
provider: 'mta',
|
||||
emailId,
|
||||
error: error.message
|
||||
});
|
||||
|
||||
return {
|
||||
status: 'error',
|
||||
details: { message: error.message }
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -1,131 +0,0 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
import * as paths from '../paths.js';
|
||||
import { MtaConnector } from './classes.connector.mta.js';
|
||||
import { RuleManager } from './classes.rulemanager.js';
|
||||
import { ApiManager } from './classes.apimanager.js';
|
||||
import { logger } from '../logger.js';
|
||||
import type { SzPlatformService } from '../platformservice.js';
|
||||
|
||||
// Import MTA service
|
||||
import { MtaService, type IMtaConfig } from '../mta/index.js';
|
||||
|
||||
export interface IEmailConstructorOptions {
|
||||
useMta?: boolean;
|
||||
mtaConfig?: IMtaConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Email service with support for both Mailgun and local MTA
|
||||
*/
|
||||
export class EmailService {
|
||||
public platformServiceRef: SzPlatformService;
|
||||
|
||||
// typedrouter
|
||||
public typedrouter = new plugins.typedrequest.TypedRouter();
|
||||
|
||||
// connectors
|
||||
public mtaConnector: MtaConnector;
|
||||
public qenv = new plugins.qenv.Qenv('./', '.nogit/');
|
||||
|
||||
// MTA service
|
||||
public mtaService: MtaService;
|
||||
|
||||
// services
|
||||
public apiManager: ApiManager;
|
||||
public ruleManager: RuleManager;
|
||||
|
||||
// configuration
|
||||
private config: IEmailConstructorOptions;
|
||||
|
||||
constructor(platformServiceRefArg: SzPlatformService, options: IEmailConstructorOptions = {}) {
|
||||
this.platformServiceRef = platformServiceRefArg;
|
||||
this.platformServiceRef.typedrouter.addTypedRouter(this.typedrouter);
|
||||
|
||||
// Set default options
|
||||
this.config = {
|
||||
useMta: options.useMta ?? true,
|
||||
mtaConfig: options.mtaConfig || {}
|
||||
};
|
||||
|
||||
if (this.config.useMta) {
|
||||
// Initialize MTA service
|
||||
this.mtaService = new MtaService(platformServiceRefArg, this.config.mtaConfig);
|
||||
// Initialize MTA connector
|
||||
this.mtaConnector = new MtaConnector(this);
|
||||
}
|
||||
|
||||
// Initialize API manager and rule manager
|
||||
this.apiManager = new ApiManager(this);
|
||||
this.ruleManager = new RuleManager(this);
|
||||
|
||||
// Set up MTA SMTP server webhook if using MTA
|
||||
if (this.config.useMta) {
|
||||
// The MTA SMTP server will handle incoming emails directly
|
||||
// through its SMTP protocol. No additional webhook needed.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the email service
|
||||
*/
|
||||
public async start() {
|
||||
// Initialize rule manager
|
||||
await this.ruleManager.init();
|
||||
|
||||
// Start MTA service if enabled
|
||||
if (this.config.useMta && this.mtaService) {
|
||||
await this.mtaService.start();
|
||||
logger.log('success', 'Started MTA service');
|
||||
}
|
||||
|
||||
logger.log('success', `Started email service`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the email service
|
||||
*/
|
||||
public async stop() {
|
||||
// Stop MTA service if it's running
|
||||
if (this.config.useMta && this.mtaService) {
|
||||
await this.mtaService.stop();
|
||||
logger.log('info', 'Stopped MTA service');
|
||||
}
|
||||
|
||||
logger.log('info', 'Stopped email service');
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an email using the configured provider (Mailgun or MTA)
|
||||
* @param email The email to send
|
||||
* @param to Recipient(s)
|
||||
* @param options Additional options
|
||||
*/
|
||||
public async sendEmail(
|
||||
email: plugins.smartmail.Smartmail<>,
|
||||
to: string | string[],
|
||||
options: any = {}
|
||||
): Promise<string> {
|
||||
// Determine which connector to use
|
||||
if (this.config.useMta && this.mtaConnector) {
|
||||
return this.mtaConnector.sendEmail(email, to, options);
|
||||
} else {
|
||||
throw new Error('No email provider configured');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get email service statistics
|
||||
*/
|
||||
public getStats() {
|
||||
const stats: any = {
|
||||
activeProviders: []
|
||||
};
|
||||
|
||||
if (this.config.useMta) {
|
||||
stats.activeProviders.push('mta');
|
||||
stats.mta = this.mtaService.getStats();
|
||||
}
|
||||
|
||||
return stats;
|
||||
}
|
||||
}
|
@ -1,177 +0,0 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
import { EmailService } from './classes.emailservice.js';
|
||||
import { logger } from '../logger.js';
|
||||
|
||||
export class RuleManager {
|
||||
public emailRef: EmailService;
|
||||
public smartruleInstance = new plugins.smartrule.SmartRule<
|
||||
plugins.smartmail.Smartmail<any>
|
||||
>();
|
||||
|
||||
constructor(emailRefArg: EmailService) {
|
||||
this.emailRef = emailRefArg;
|
||||
|
||||
// Register MTA handler for incoming emails if MTA is enabled
|
||||
if (this.emailRef.mtaService) {
|
||||
this.setupMtaIncomingHandler();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up handler for incoming emails via MTA's SMTP server
|
||||
*/
|
||||
private setupMtaIncomingHandler() {
|
||||
// The original MtaService doesn't have a direct callback for incoming emails,
|
||||
// but we can modify this approach based on how you prefer to integrate.
|
||||
// One option would be to extend the MtaService to add an event emitter.
|
||||
|
||||
// For now, we'll use a directory watcher as an example
|
||||
// This would watch the directory where MTA saves incoming emails
|
||||
const incomingDir = this.emailRef.mtaService['receivedEmailsDir'] || './received';
|
||||
|
||||
// Simple file watcher (in real implementation, use proper file watching)
|
||||
// This is just conceptual - would need modification to work with your specific setup
|
||||
this.watchIncomingEmails(incomingDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Watch directory for incoming emails (conceptual implementation)
|
||||
*/
|
||||
private watchIncomingEmails(directory: string) {
|
||||
console.log(`Watching for incoming emails in: ${directory}`);
|
||||
|
||||
// Conceptual - in a real implementation, set up proper file watching
|
||||
// or modify the MTA to emit events when emails are received
|
||||
|
||||
/*
|
||||
// Example using a file watcher:
|
||||
const watcher = plugins.fs.watch(directory, async (eventType, filename) => {
|
||||
if (eventType === 'rename' && filename.endsWith('.eml')) {
|
||||
const filePath = plugins.path.join(directory, filename);
|
||||
await this.handleMtaIncomingEmail(filePath);
|
||||
}
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle incoming email received via MTA
|
||||
*/
|
||||
public async handleMtaIncomingEmail(emailPath: string) {
|
||||
try {
|
||||
// Process the email file
|
||||
const fetchedSmartmail = await this.emailRef.mtaConnector.receiveEmail(emailPath);
|
||||
|
||||
console.log('=======================');
|
||||
console.log('Received a mail via MTA:');
|
||||
console.log(`From: ${fetchedSmartmail.options.creationObjectRef.From}`);
|
||||
console.log(`To: ${fetchedSmartmail.options.creationObjectRef.To}`);
|
||||
console.log(`Subject: ${fetchedSmartmail.options.creationObjectRef.Subject}`);
|
||||
console.log('^^^^^^^^^^^^^^^^^^^^^^^');
|
||||
|
||||
logger.log(
|
||||
'info',
|
||||
`email from ${fetchedSmartmail.options.creationObjectRef.From} to ${fetchedSmartmail.options.creationObjectRef.To} with subject '${fetchedSmartmail.options.creationObjectRef.Subject}'`,
|
||||
{
|
||||
eventType: 'receivedEmail',
|
||||
provider: 'mta',
|
||||
email: {
|
||||
from: fetchedSmartmail.options.creationObjectRef.From,
|
||||
to: fetchedSmartmail.options.creationObjectRef.To,
|
||||
subject: fetchedSmartmail.options.creationObjectRef.Subject,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
// Process with rules
|
||||
this.smartruleInstance.makeDecision(fetchedSmartmail);
|
||||
} catch (error) {
|
||||
logger.log('error', `Failed to process incoming MTA email: ${error.message}`, {
|
||||
eventType: 'emailError',
|
||||
provider: 'mta',
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public async init() {
|
||||
// Setup email rules
|
||||
await this.createForwards();
|
||||
}
|
||||
|
||||
/**
|
||||
* creates the default forwards
|
||||
*/
|
||||
public async createForwards() {
|
||||
const forwards: { originalToAddress: string[]; forwardedToAddress: string[] }[] = [];
|
||||
console.log(`${forwards.length} forward rules configured:`);
|
||||
for (const forward of forwards) {
|
||||
console.log(forward);
|
||||
}
|
||||
|
||||
for (const forward of forwards) {
|
||||
this.smartruleInstance.createRule(
|
||||
10,
|
||||
async (smartmailArg) => {
|
||||
const matched = forward.originalToAddress.reduce<boolean>((prevValue, currentValue) => {
|
||||
return smartmailArg.options.creationObjectRef.To.includes(currentValue) || prevValue;
|
||||
}, false);
|
||||
if (matched) {
|
||||
console.log('Forward rule matched');
|
||||
console.log(forward);
|
||||
return 'apply-continue';
|
||||
} else {
|
||||
return 'continue';
|
||||
}
|
||||
},
|
||||
async (smartmailArg: plugins.smartmail.Smartmail<any>) => {
|
||||
forward.forwardedToAddress.map(async (toArg) => {
|
||||
const forwardedSmartMail = new plugins.smartmail.Smartmail({
|
||||
body:
|
||||
`
|
||||
<div style="background: #CCC; padding: 10px; border-radius: 3px;">
|
||||
<div><b>Original Sender:</b></div>
|
||||
<div>${smartmailArg.options.creationObjectRef.From}</div>
|
||||
<div><b>Original Recipient:</b></div>
|
||||
<div>${smartmailArg.options.creationObjectRef.To}</div>
|
||||
<div><b>Forwarded to:</b></div>
|
||||
<div>${forward.forwardedToAddress.reduce<string>((pVal, cVal) => {
|
||||
return `${pVal ? pVal + ', ' : ''}${cVal}`;
|
||||
}, null)}</div>
|
||||
<div><b>Subject:</b></div>
|
||||
<div>${smartmailArg.getSubject()}</div>
|
||||
<div><b>The original body can be found below.</b></div>
|
||||
</div>
|
||||
` + smartmailArg.getBody(),
|
||||
from: 'forwarder@mail.lossless.one',
|
||||
subject: `Forwarded mail for '${smartmailArg.options.creationObjectRef.To}'`,
|
||||
});
|
||||
for (const attachment of smartmailArg.attachments) {
|
||||
forwardedSmartMail.addAttachment(attachment);
|
||||
}
|
||||
|
||||
// Use the EmailService's sendEmail method to send with the appropriate provider
|
||||
await this.emailRef.sendEmail(forwardedSmartMail, toArg);
|
||||
|
||||
console.log(`forwarded mail to ${toArg}`);
|
||||
logger.log(
|
||||
'info',
|
||||
`email from ${
|
||||
smartmailArg.options.creationObjectRef.From
|
||||
} to ${toArg} with subject '${smartmailArg.getSubject()}'`,
|
||||
{
|
||||
eventType: 'forwardedEmail',
|
||||
email: {
|
||||
from: smartmailArg.options.creationObjectRef.From,
|
||||
to: smartmailArg.options.creationObjectRef.To,
|
||||
forwardedTo: toArg,
|
||||
subject: smartmailArg.options.creationObjectRef.Subject,
|
||||
},
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
51
ts/email/email.classes.apimanager.ts
Normal file
51
ts/email/email.classes.apimanager.ts
Normal file
@ -0,0 +1,51 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
import { EmailService } from './email.classes.emailservice.js';
|
||||
import { logger } from '../logger.js';
|
||||
|
||||
export class ApiManager {
|
||||
public emailRef: EmailService;
|
||||
|
||||
public typedRouter = new plugins.typedrequest.TypedRouter();
|
||||
|
||||
constructor(emailRefArg: EmailService) {
|
||||
this.emailRef = emailRefArg;
|
||||
this.emailRef.typedrouter.addTypedRouter(this.typedRouter);
|
||||
this.typedRouter.addTypedHandler<plugins.servezoneInterfaces.platformservice.mta.IRequest_SendEmail>(
|
||||
new plugins.typedrequest.TypedHandler('sendEmail', async (requestData) => {
|
||||
const mailToSend = new plugins.smartmail.Smartmail({
|
||||
body: requestData.body,
|
||||
from: requestData.from,
|
||||
subject: requestData.title,
|
||||
});
|
||||
|
||||
if (requestData.attachments) {
|
||||
for (const attachment of requestData.attachments) {
|
||||
mailToSend.addAttachment(
|
||||
await plugins.smartfile.SmartFile.fromString(
|
||||
attachment.name,
|
||||
attachment.binaryAttachmentString,
|
||||
'binary'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
await this.emailRef.mailgunConnector.sendEmail(mailToSend, requestData.to, {});
|
||||
logger.log(
|
||||
'info',
|
||||
`send an email to ${requestData.to} with subject '${mailToSend.getSubject()}'`,
|
||||
{
|
||||
eventType: 'sentEmail',
|
||||
email: {
|
||||
to: requestData.to,
|
||||
subject: mailToSend.getSubject(),
|
||||
},
|
||||
}
|
||||
);
|
||||
return {
|
||||
responseId: 'abc', // TODO: generate proper response id
|
||||
};
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
30
ts/email/email.classes.connector.mailgun.ts
Normal file
30
ts/email/email.classes.connector.mailgun.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import * as plugins from './email.plugins.js';
|
||||
import { EmailService } from './email.classes.emailservice.js';
|
||||
|
||||
export class MailgunConnector {
|
||||
public emailRef: EmailService;
|
||||
public mailgunAccount: plugins.mailgun.MailgunAccount;
|
||||
|
||||
constructor(emailRefArg: EmailService) {
|
||||
this.emailRef = emailRefArg;
|
||||
this.mailgunAccount = new plugins.mailgun.MailgunAccount({
|
||||
apiToken: this.emailRef.qenv.getEnvVarOnDemand('MAILGUN_API_TOKEN'),
|
||||
region: 'eu',
|
||||
});
|
||||
this.mailgunAccount.addSmtpCredentials(
|
||||
this.emailRef.qenv.getEnvVarOnDemand('MAILGUN_SMTP_CREDENTIALS')
|
||||
);
|
||||
}
|
||||
|
||||
public async sendEmail(
|
||||
smartMailArg: plugins.smartmail.Smartmail<any>,
|
||||
toArg: string,
|
||||
dataArg: any = {}
|
||||
) {
|
||||
this.mailgunAccount.sendSmartMail(smartMailArg, toArg, dataArg);
|
||||
}
|
||||
|
||||
public async receiveEmail(messageUrl: string) {
|
||||
return await this.mailgunAccount.retrieveSmartMailFromMessageUrl(messageUrl);
|
||||
}
|
||||
}
|
53
ts/email/email.classes.emailservice.ts
Normal file
53
ts/email/email.classes.emailservice.ts
Normal file
@ -0,0 +1,53 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
import * as paths from '../paths.js';
|
||||
import { MailgunConnector } from './email.classes.connector.mailgun.js';
|
||||
import { RuleManager } from './email.classes.rulemanager.js';
|
||||
import { ApiManager } from './email.classes.apimanager.js';
|
||||
import { logger } from '../logger.js';
|
||||
import type { SzPlatformService } from '../classes.platformservice.js';
|
||||
|
||||
|
||||
export interface IEmailConstructorOptions {
|
||||
mailgunApiKey: string;
|
||||
}
|
||||
|
||||
export class EmailService {
|
||||
public platformServiceRef: SzPlatformService;
|
||||
|
||||
// typedrouter
|
||||
public typedrouter = new plugins.typedrequest.TypedRouter();
|
||||
|
||||
// connectors
|
||||
public mailgunConnector: MailgunConnector;
|
||||
public qenv = new plugins.qenv.Qenv('./', '.nogit/');
|
||||
|
||||
// server
|
||||
public apiManager = new ApiManager(this);
|
||||
public ruleManager: RuleManager;
|
||||
|
||||
constructor(platformServiceRefArg: SzPlatformService) {
|
||||
this.platformServiceRef = platformServiceRefArg;
|
||||
this.platformServiceRef.typedrouter.addTypedRouter(this.typedrouter);
|
||||
this.mailgunConnector = new MailgunConnector(this);
|
||||
this.ruleManager = new RuleManager(this);
|
||||
this.platformServiceRef.typedserver.server.addRoute(
|
||||
'/mailgun-notify',
|
||||
new plugins.typedserver.servertools.Handler('POST', async (req, res) => {
|
||||
console.log('Got a mailgun email notification');
|
||||
res.status(200);
|
||||
res.end();
|
||||
this.ruleManager.handleNotification(req.body);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
public async start() {
|
||||
await this.ruleManager.init();
|
||||
logger.log('success', `Started email service`);
|
||||
}
|
||||
|
||||
public async stop() {
|
||||
}
|
||||
|
||||
|
||||
}
|
137
ts/email/email.classes.rulemanager.ts
Normal file
137
ts/email/email.classes.rulemanager.ts
Normal file
@ -0,0 +1,137 @@
|
||||
import * as plugins from './email.plugins.js';
|
||||
import { EmailService } from './email.classes.emailservice.js';
|
||||
import { logger } from './email.logging.js';
|
||||
|
||||
export class RuleManager {
|
||||
public emailRef: EmailService;
|
||||
public smartruleInstance = new plugins.smartrule.SmartRule<
|
||||
plugins.smartmail.Smartmail<plugins.mailgun.IMailgunMessage>
|
||||
>();
|
||||
|
||||
constructor(emailRefArg: EmailService) {
|
||||
this.emailRef = emailRefArg;
|
||||
}
|
||||
|
||||
public async handleNotification(notification: plugins.mailgun.IMailgunNotification) {
|
||||
console.log(notification['message-url']);
|
||||
|
||||
// basic checks here
|
||||
// none for now
|
||||
|
||||
const fetchedSmartmail = await this.emailRef.mailgunConnector.receiveEmail(
|
||||
notification['message-url']
|
||||
);
|
||||
console.log('=======================');
|
||||
console.log('Received a mail:');
|
||||
console.log(`From: ${fetchedSmartmail.options.creationObjectRef.From}`);
|
||||
console.log(`To: ${fetchedSmartmail.options.creationObjectRef.To}`);
|
||||
console.log(`Subject: ${fetchedSmartmail.options.creationObjectRef.Subject}`);
|
||||
console.log('^^^^^^^^^^^^^^^^^^^^^^^');
|
||||
|
||||
logger.log(
|
||||
'info',
|
||||
`email from ${fetchedSmartmail.options.creationObjectRef.From} to ${fetchedSmartmail.options.creationObjectRef.To} with subject '${fetchedSmartmail.options.creationObjectRef.Subject}'`,
|
||||
{
|
||||
eventType: 'receivedEmail',
|
||||
email: {
|
||||
from: fetchedSmartmail.options.creationObjectRef.From,
|
||||
to: fetchedSmartmail.options.creationObjectRef.To,
|
||||
subject: fetchedSmartmail.options.creationObjectRef.Subject,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
this.smartruleInstance.makeDecision(fetchedSmartmail);
|
||||
}
|
||||
|
||||
public async init() {
|
||||
// lets forward stuff
|
||||
await this.createForwards();
|
||||
}
|
||||
|
||||
/**
|
||||
* creates the default forwards
|
||||
*/
|
||||
public async createForwards() {
|
||||
const forwards: { originalToAddress: string[]; forwardedToAddress: string[] }[] = [
|
||||
{
|
||||
originalToAddress: ['bot@mail.nevermind.group'],
|
||||
forwardedToAddress: ['phil@metadata.company', 'dominik@metadata.company'],
|
||||
},
|
||||
{
|
||||
originalToAddress: ['legal@mail.lossless.com'],
|
||||
forwardedToAddress: ['phil@lossless.com'],
|
||||
},
|
||||
{
|
||||
originalToAddress: ['christine.nyamwaro@mail.lossless.com', 'christine@nyamwaro.com'],
|
||||
forwardedToAddress: ['phil@lossless.com'],
|
||||
},
|
||||
];
|
||||
console.log(`${forwards.length} forward rules configured:`);
|
||||
for (const forward of forwards) {
|
||||
console.log(forward);
|
||||
}
|
||||
|
||||
for (const forward of forwards) {
|
||||
this.smartruleInstance.createRule(
|
||||
10,
|
||||
async (smartmailArg) => {
|
||||
const matched = forward.originalToAddress.reduce<boolean>((prevValue, currentValue) => {
|
||||
return smartmailArg.options.creationObjectRef.To.includes(currentValue) || prevValue;
|
||||
}, false);
|
||||
if (matched) {
|
||||
console.log('Forward rule matched');
|
||||
console.log(forward);
|
||||
return 'apply-continue';
|
||||
} else {
|
||||
return 'continue';
|
||||
}
|
||||
},
|
||||
async (smartmailArg: plugins.smartmail.Smartmail<plugins.mailgun.IMailgunMessage>) => {
|
||||
forward.forwardedToAddress.map(async (toArg) => {
|
||||
const forwardedSmartMail = new plugins.smartmail.Smartmail({
|
||||
body:
|
||||
`
|
||||
<div style="background: #CCC; padding: 10px; border-radius: 3px;">
|
||||
<div><b>Original Sender:</b></div>
|
||||
<div>${smartmailArg.options.creationObjectRef.From}</div>
|
||||
<div><b>Original Recipient:</b></div>
|
||||
<div>${smartmailArg.options.creationObjectRef.To}</div>
|
||||
<div><b>Forwarded to:</b></div>
|
||||
<div>${forward.forwardedToAddress.reduce<string>((pVal, cVal) => {
|
||||
return `${pVal ? pVal + ', ' : ''}${cVal}`;
|
||||
}, null)}</div>
|
||||
<div><b>Subject:</b></div>
|
||||
<div>${smartmailArg.getSubject()}</div>
|
||||
<div><b>The original body can be found below.</b></div>
|
||||
</div>
|
||||
` + smartmailArg.getBody(),
|
||||
from: 'forwarder@mail.lossless.one',
|
||||
subject: `Forwarded mail for '${smartmailArg.options.creationObjectRef.To}'`,
|
||||
});
|
||||
for (const attachment of smartmailArg.attachments) {
|
||||
forwardedSmartMail.addAttachment(attachment);
|
||||
}
|
||||
await this.emailRef.mailgunConnector.sendEmail(forwardedSmartMail, toArg);
|
||||
console.log(`forwarded mail to ${toArg}`);
|
||||
logger.log(
|
||||
'info',
|
||||
`email from ${
|
||||
smartmailArg.options.creationObjectRef.From
|
||||
} to phil@lossless.com with subject '${smartmailArg.getSubject()}'`,
|
||||
{
|
||||
eventType: 'forwardedEmail',
|
||||
email: {
|
||||
from: smartmailArg.options.creationObjectRef.From,
|
||||
to: smartmailArg.options.creationObjectRef.To,
|
||||
forwardedTo: toArg,
|
||||
subject: smartmailArg.options.creationObjectRef.Subject,
|
||||
},
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
import * as plugins from './email.plugins.js';
|
||||
|
||||
export class TemplateManager {
|
||||
public smartmailDefault = new plugins.smartmail.Smartmail({
|
@ -1,4 +1,4 @@
|
||||
export * from './00_commitinfo_data.js';
|
||||
import { SzPlatformService } from './platformservice.js';
|
||||
import { SzPlatformService } from './classes.platformservice.js';
|
||||
|
||||
export const runCli = async () => {}
|
@ -1,4 +1,4 @@
|
||||
import type { SzPlatformService } from '../platformservice.js';
|
||||
import type { SzPlatformService } from '../classes.platformservice.js';
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
export interface ILetterConstructorOptions {
|
||||
|
@ -1 +0,0 @@
|
||||
export * from './classes.letterservice.js';
|
@ -1,7 +1,8 @@
|
||||
export * from './classes.dkimcreator.js';
|
||||
export * from './classes.emailsignjob.js';
|
||||
export * from './classes.dkimverifier.js';
|
||||
export * from './classes.mta.js';
|
||||
export * from './classes.smtpserver.js';
|
||||
export * from './classes.emailsendjob.js';
|
||||
export * from './classes.email.js';
|
||||
export * from './mta.classes.dkimcreator.js';
|
||||
export * from './mta.classes.emailsignjob.js';
|
||||
export * from './mta.classes.dkimverifier.js';
|
||||
export * from './mta.classes.mta.js';
|
||||
export * from './mta.classes.smtpserver.js';
|
||||
export * from './mta.classes.emailsendjob.js';
|
||||
export * from './mta.classes.mta.js';
|
||||
export * from './mta.classes.email.js';
|
||||
|
@ -1,9 +1,9 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
import { Email } from './classes.email.js';
|
||||
import type { IEmailOptions } from './classes.email.js';
|
||||
import { DeliveryStatus } from './classes.emailsendjob.js';
|
||||
import type { MtaService } from './classes.mta.js';
|
||||
import type { IDnsRecord } from './classes.dnsmanager.js';
|
||||
import { Email } from './mta.classes.email.js';
|
||||
import type { IEmailOptions } from './mta.classes.email.js';
|
||||
import { DeliveryStatus } from './mta.classes.emailsendjob.js';
|
||||
import type { MtaService } from './mta.classes.mta.js';
|
||||
import type { IDnsRecord } from './mta.classes.dnsmanager.js';
|
||||
|
||||
/**
|
||||
* Authentication options for API requests
|
||||
@ -141,7 +141,7 @@ class HttpResponse {
|
||||
private headers: Record<string, string> = {
|
||||
'Content-Type': 'application/json'
|
||||
};
|
||||
public statusCode: number = 200;
|
||||
private statusCode: number = 200;
|
||||
|
||||
constructor(private res: any) {}
|
||||
|
@ -1,8 +1,8 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
import * as paths from '../paths.js';
|
||||
|
||||
import { Email } from './classes.email.js';
|
||||
import type { MtaService } from './classes.mta.js';
|
||||
import { Email } from './mta.classes.email.js';
|
||||
import type { MtaService } from './mta.classes.mta.js';
|
||||
|
||||
const readFile = plugins.util.promisify(plugins.fs.readFile);
|
||||
const writeFile = plugins.util.promisify(plugins.fs.writeFile);
|
@ -1,5 +1,5 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
import { MtaService } from './classes.mta.js';
|
||||
import { MtaService } from './mta.classes.mta.js';
|
||||
|
||||
class DKIMVerifier {
|
||||
public mtaRef: MtaService;
|
@ -71,7 +71,7 @@ export class DNSManager {
|
||||
const cacheKey = `mx:${domain}`;
|
||||
|
||||
// Check cache first
|
||||
const cached = this.getFromCache<plugins.dns.MxRecord[]>(cacheKey);
|
||||
const cached = this.getFromCache(cacheKey);
|
||||
if (cached) {
|
||||
return cached;
|
||||
}
|
||||
@ -103,7 +103,7 @@ export class DNSManager {
|
||||
const cacheKey = `txt:${domain}`;
|
||||
|
||||
// Check cache first
|
||||
const cached = this.getFromCache<string[][]>(cacheKey);
|
||||
const cached = this.getFromCache(cacheKey);
|
||||
if (cached) {
|
||||
return cached;
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
import * as paths from '../paths.js';
|
||||
import { Email } from './classes.email.js';
|
||||
import { EmailSignJob } from './classes.emailsignjob.js';
|
||||
import type { MtaService } from './classes.mta.js';
|
||||
import { Email } from './mta.classes.email.js';
|
||||
import { EmailSignJob } from './mta.classes.emailsignjob.js';
|
||||
import type { MtaService } from './mta.classes.mta.js';
|
||||
|
||||
// Configuration options for email sending
|
||||
export interface IEmailSendOptions {
|
@ -1,14 +1,14 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
import * as paths from '../paths.js';
|
||||
|
||||
import { Email } from './classes.email.js';
|
||||
import { EmailSendJob, DeliveryStatus } from './classes.emailsendjob.js';
|
||||
import { DKIMCreator } from './classes.dkimcreator.js';
|
||||
import { DKIMVerifier } from './classes.dkimverifier.js';
|
||||
import { SMTPServer, type ISmtpServerOptions } from './classes.smtpserver.js';
|
||||
import { DNSManager } from './classes.dnsmanager.js';
|
||||
import { ApiManager } from './classes.apimanager.js';
|
||||
import type { SzPlatformService } from '../platformservice.js';
|
||||
import { Email } from './mta.classes.email.js';
|
||||
import { EmailSendJob, DeliveryStatus } from './mta.classes.emailsendjob.js';
|
||||
import { DKIMCreator } from './mta.classes.dkimcreator.js';
|
||||
import { DKIMVerifier } from './mta.classes.dkimverifier.js';
|
||||
import { SMTPServer, type ISmtpServerOptions } from './mta.classes.smtpserver.js';
|
||||
import { DNSManager } from './mta.classes.dnsmanager.js';
|
||||
import { ApiManager } from './mta.classes.apimanager.js';
|
||||
import type { SzPlatformService } from '../classes.platformservice.js';
|
||||
|
||||
/**
|
||||
* Configuration options for the MTA service
|
@ -1,7 +1,7 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
import * as paths from '../paths.js';
|
||||
import { Email } from './classes.email.js';
|
||||
import type { MtaService } from './classes.mta.js';
|
||||
import { Email } from './mta.classes.email.js';
|
||||
import type { MtaService } from './mta.classes.mta.js';
|
||||
|
||||
export interface ISmtpServerOptions {
|
||||
port: number;
|
@ -45,13 +45,11 @@ import * as smartfile from '@push.rocks/smartfile';
|
||||
import * as smartlog from '@push.rocks/smartlog';
|
||||
import * as smartmail from '@push.rocks/smartmail';
|
||||
import * as smartpath from '@push.rocks/smartpath';
|
||||
import * as smartproxy from '@push.rocks/smartproxy';
|
||||
import * as smartpromise from '@push.rocks/smartpromise';
|
||||
import * as smartrequest from '@push.rocks/smartrequest';
|
||||
import * as smartrule from '@push.rocks/smartrule';
|
||||
import * as smartrx from '@push.rocks/smartrx';
|
||||
|
||||
export { projectinfo, qenv, smartdata, smartfile, smartlog, smartmail, smartpath, smartproxy, smartpromise, smartrequest, smartrule, smartrx };
|
||||
export { projectinfo, qenv, smartdata, smartfile, smartlog, smartmail, smartpath, smartpromise, smartrequest, smartrx };
|
||||
|
||||
// apiclient.xyz scope
|
||||
import * as letterxpress from '@apiclient.xyz/letterxpress';
|
||||
|
@ -1 +1 @@
|
||||
export * from './classes.smsservice.js';
|
||||
export * from './smsservice.js';
|
@ -1,7 +1,7 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
import * as paths from '../paths.js';
|
||||
import { logger } from '../logger.js';
|
||||
import type { SzPlatformService } from '../platformservice.js';
|
||||
import type { SzPlatformService } from '../classes.platformservice.js';
|
||||
|
||||
export interface ISmsConstructorOptions {
|
||||
apiGatewayApiToken: string;
|
@ -1,7 +1,6 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"useDefineForClassFields": false,
|
||||
"target": "ES2022",
|
||||
"module": "NodeNext",
|
||||
|
Loading…
x
Reference in New Issue
Block a user