gcf-common-lib 0.35.0 → 0.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/npm-publish.yml +39 -36
- package/.junie/guidelines.md +108 -0
- package/.prettierrc +10 -10
- package/CODE_OF_CONDUCT.md +13 -0
- package/CONTRIBUTING.md +60 -0
- package/LICENSE +21 -0
- package/README.md +110 -1
- package/docs/plan.md +211 -0
- package/docs/tasks.md +88 -0
- package/eslint.config.mjs +31 -31
- package/package.json +63 -52
- package/src/{amqp-helper.ts → amqp-helper.ts.old} +52 -52
- package/src/index.js +191 -188
- package/src/index.ts +177 -178
- package/src/mongo-helper.js +42 -42
- package/src/mongo-helper.ts +51 -51
- package/src/mongo-lock.js +86 -86
- package/src/mongo-lock.ts +99 -99
- package/src/types.js +2 -2
- package/src/types.ts +84 -84
- package/src/utils.js +105 -84
- package/src/utils.ts +110 -88
- package/test/gcf-common.process.test.js +63 -0
- package/test/gcf-common.process.test.ts +65 -0
- package/test/metadata.test.js +77 -0
- package/test/metadata.test.ts +78 -0
- package/test/sample.test.js +12 -0
- package/test/test.js +30 -25
- package/test/test.ts +32 -26
- package/test/ts-tests.test.js +8 -0
- package/test/utils.test.js +43 -0
- package/test/utils.test.ts +47 -0
- package/tsconfig.json +7 -7
- package/src/amqp-helper.js +0 -44
package/docs/tasks.md
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Improvement Tasks Checklist
|
|
2
|
+
|
|
3
|
+
Note: Each item is actionable and ordered to minimize risk: start with repo hygiene and tests, then architecture and code-level refactors, followed by observability and CI.
|
|
4
|
+
|
|
5
|
+
1. [x] Documentation and repository metadata
|
|
6
|
+
- [x] Expand README with project overview, installation, quick start, and usage examples for Pub/Sub and AMQP flows.
|
|
7
|
+
- [x] Add API documentation for GcfCommon, AmqpHelper, MongoHelper, and utils (function signatures and examples).
|
|
8
|
+
- [x] Add CONTRIBUTING.md (dev setup, coding standards, testing, release process) and CODE_OF_CONDUCT.md if desired.
|
|
9
|
+
- [x] Set a valid SPDX license in package.json and add a LICENSE file.
|
|
10
|
+
- [x] Fill in meaningful package.json description and keywords.
|
|
11
|
+
|
|
12
|
+
2. [ ] Testing strategy and coverage
|
|
13
|
+
- [x] Make tests runnable without transpilation by default: convert or add JS tests under test/*.test.js for pure utilities and core flows.
|
|
14
|
+
- [x] Gate any network-dependent tests behind environment flags and skip by default in CI.
|
|
15
|
+
- [x] Add unit tests for src/utils.ts (ms, sec, A1 conversions, safeJsonParse edge cases).
|
|
16
|
+
- [x] Add unit tests for GcfCommon.process(...) that avoid network I/O (no topic/exchange/queue), including error path and buildResponse.
|
|
17
|
+
- [x] Add tests for getMetadataOrAttribute(...) across GCS, Pub/Sub, and HTTP request payloads.
|
|
18
|
+
- [x] If keeping TS tests, add loader support (e.g., tsx) and an npm script: "test:ts": "node --test --import tsx .\\test\\**/*.ts".
|
|
19
|
+
- [x] Add coverage reporting with c8 and an npm script: "test:coverage".
|
|
20
|
+
|
|
21
|
+
3. [ ] Build and packaging
|
|
22
|
+
- [ ] Decide on distribution model: TS-only consumers vs emitting JS. Document decision in README.
|
|
23
|
+
- [ ] If emitting JS: add tsconfig.build.json (noEmit: false, outDir: dist) and update scripts (build, clean, prepare) and package exports.
|
|
24
|
+
- [ ] If TS-only: add "types" entry and proper "exports" map pointing to source types; document that consumers need a TS-aware build.
|
|
25
|
+
- [ ] Validate that main/exports/types interop works for both ESM/CJS consumers.
|
|
26
|
+
|
|
27
|
+
4. [ ] Architectural separation of concerns
|
|
28
|
+
- [ ] Extract transport publishing from GcfCommon.response into dedicated transport modules (PubSubTransport, AmqpTransport) behind a common interface.
|
|
29
|
+
- [ ] Extract metadata/attributes parsing into a separate utility with explicit type guards.
|
|
30
|
+
- [ ] Keep GcfCommon.process focused on orchestration (handler execution, timeout, and delegating response publishing).
|
|
31
|
+
|
|
32
|
+
5. [ ] Reliability: retries, timeouts, and backoff
|
|
33
|
+
- [ ] Implement configurable retries with exponential backoff for Pub/Sub publishes and AMQP publishes (with max attempts and jitter).
|
|
34
|
+
- [ ] Add a configurable timeout to GcfCommon.process using AbortController or a Promise.race helper (remove/comment RxJS-based approach entirely or move behind a feature flag).
|
|
35
|
+
- [ ] Ensure idempotency considerations (e.g., correlationId/request_id usage) are documented and supported.
|
|
36
|
+
|
|
37
|
+
6. [ ] Logging and observability
|
|
38
|
+
- [ ] Replace console.log with a minimal logger interface supporting levels (debug/info/warn/error) and structured context (request_id, app_id, env).
|
|
39
|
+
- [ ] Add debug logs around metadata extraction and transport selection; avoid logging sensitive data (redaction rules).
|
|
40
|
+
- [ ] Provide hooks to integrate with external loggers or APM (e.g., OpenTelemetry) without hard dependency.
|
|
41
|
+
|
|
42
|
+
7. [ ] Input validation and typing
|
|
43
|
+
- [ ] Validate and normalize metadata/attributes (coerce to strings where required; verify topic/exchange/queue formats).
|
|
44
|
+
- [ ] Make GcfCommon.getOptions generic: getOptions<T = Dict<any>>(...): Promise<T> with runtime validation of JSON shape (optional schema param).
|
|
45
|
+
- [ ] Tighten TResponse typing (readonly where possible); consider branded types for identifiers (RequestId, ConsumerId).
|
|
46
|
+
|
|
47
|
+
8. [ ] AMQP helper modernization
|
|
48
|
+
- [ ] Replace Bluebird disposers with async/await and try/finally; keep confirm channel variant where needed.
|
|
49
|
+
- [ ] Add connection URL validation and explicit error messages when amqpOptions.url is missing.
|
|
50
|
+
- [ ] Support configurable prefetch and confirm mode via options.
|
|
51
|
+
- [ ] Implement publish backpressure handling and retries with reconnection on channel/connection errors.
|
|
52
|
+
|
|
53
|
+
9. [ ] Mongo client lifecycle and locking
|
|
54
|
+
- [ ] Review MongoHelper.withMongoClient to avoid global client leaks; either manage a shared client with health checks or expose a close method.
|
|
55
|
+
- [ ] Add ping/healthcheck and resilience to transient network errors.
|
|
56
|
+
- [ ] Deprecate MongoLock class formally (already annotated) and document a recommended alternative (e.g., using findOneAndUpdate with TTL index).
|
|
57
|
+
|
|
58
|
+
10. [ ] Dead code and comments cleanup
|
|
59
|
+
- [ ] Remove or finalize the commented-out RxJS timeout code in GcfCommon.
|
|
60
|
+
- [ ] Remove the commented safeGetAttributes path or implement a proper version that fetches Storage metadata when needed.
|
|
61
|
+
- [ ] Add JSDoc for public APIs and rationale where behavior is non-obvious.
|
|
62
|
+
|
|
63
|
+
11. [ ] Pub/Sub specifics and payload handling
|
|
64
|
+
- [ ] Validate attribute sizes and JSON payload limits; document constraints.
|
|
65
|
+
- [ ] Consider enabling message ordering and document how to set ordering keys when needed.
|
|
66
|
+
- [ ] Ensure attributes are consistently strings; add a helper for attribute coercion.
|
|
67
|
+
|
|
68
|
+
12. [ ] Security and configuration
|
|
69
|
+
- [ ] Centralize configuration (AMQP URL, Pub/Sub project/topic defaults) with environment variable support and a typed config loader.
|
|
70
|
+
- [ ] Redact sensitive fields in logs and propagate only safe metadata to responses.
|
|
71
|
+
- [ ] Run "npm audit" regularly; schedule dependency update checks (e.g., weekly).
|
|
72
|
+
|
|
73
|
+
13. [ ] Linting, formatting, and scripts
|
|
74
|
+
- [ ] Add npm scripts: "lint", "lint:fix", "format", and ensure Prettier integration.
|
|
75
|
+
- [ ] Consider enabling additional ESLint rules suitable for this repo (promise rules, no-floating-promises) while keeping pragmatism.
|
|
76
|
+
- [ ] Configure EditorConfig to enforce CRLF and common conventions.
|
|
77
|
+
|
|
78
|
+
14. [ ] Continuous Integration
|
|
79
|
+
- [ ] Add GitHub Actions workflow: Node 20.x matrix to run lint, type-check, and unit tests (JS tests only by default).
|
|
80
|
+
- [ ] Cache npm and enable problem matchers for faster feedback.
|
|
81
|
+
|
|
82
|
+
15. [ ] Examples and developer experience
|
|
83
|
+
- [ ] Provide an examples/ directory with a minimal handler using GcfCommon.process demonstrating no-network and networked responses.
|
|
84
|
+
- [ ] Document how to stub response publishing in tests and how to configure amqpOptions at runtime.
|
|
85
|
+
|
|
86
|
+
16. [ ] Versioning and release process
|
|
87
|
+
- [ ] Adopt semantic versioning explicitly; add CHANGELOG and automate release notes generation (e.g., via GitHub Releases).
|
|
88
|
+
- [ ] Document any planned breaking changes from architectural refactors and provide migration guidance.
|
package/eslint.config.mjs
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
import { defineConfig } from 'eslint/config';
|
|
2
|
-
import globals from 'globals';
|
|
3
|
-
import js from '@eslint/js';
|
|
4
|
-
import tseslint from 'typescript-eslint';
|
|
5
|
-
import eslintPluginUnicorn from 'eslint-plugin-unicorn';
|
|
6
|
-
import pluginPromise from 'eslint-plugin-promise';
|
|
7
|
-
|
|
8
|
-
export default defineConfig([
|
|
9
|
-
{ files: ['**/*.{js,mjs,cjs,ts}'] },
|
|
10
|
-
{ files: ['**/*.js'], languageOptions: { sourceType: 'commonjs' } },
|
|
11
|
-
{ files: ['**/*.{js,mjs,cjs,ts}'], languageOptions: { globals: globals.node } },
|
|
12
|
-
{ files: ['**/*.{js,mjs,cjs,ts}'], plugins: { js }, extends: ['js/recommended'] },
|
|
13
|
-
tseslint.configs.recommended,
|
|
14
|
-
eslintPluginUnicorn.configs.recommended,
|
|
15
|
-
pluginPromise.configs['flat/recommended'],
|
|
16
|
-
{
|
|
17
|
-
rules: {
|
|
18
|
-
'block-scoped-var': 'error',
|
|
19
|
-
'no-loop-func': 'error',
|
|
20
|
-
//
|
|
21
|
-
'@typescript-eslint/no-explicit-any': 'off',
|
|
22
|
-
'@typescript-eslint/no-unused-vars': 'off',
|
|
23
|
-
'@typescript-eslint/no-empty-function': 'off',
|
|
24
|
-
'@typescript-eslint/no-empty-interface': 'off',
|
|
25
|
-
//
|
|
26
|
-
'unicorn/prevent-abbreviations': 'off',
|
|
27
|
-
// 'lodash/prefer-lodash-method': 'off',
|
|
28
|
-
// 'rxjs/no-implicit-any-catch': 'off',
|
|
29
|
-
},
|
|
30
|
-
},
|
|
31
|
-
]);
|
|
1
|
+
import { defineConfig } from 'eslint/config';
|
|
2
|
+
import globals from 'globals';
|
|
3
|
+
import js from '@eslint/js';
|
|
4
|
+
import tseslint from 'typescript-eslint';
|
|
5
|
+
import eslintPluginUnicorn from 'eslint-plugin-unicorn';
|
|
6
|
+
import pluginPromise from 'eslint-plugin-promise';
|
|
7
|
+
|
|
8
|
+
export default defineConfig([
|
|
9
|
+
{ files: ['**/*.{js,mjs,cjs,ts}'] },
|
|
10
|
+
{ files: ['**/*.js'], languageOptions: { sourceType: 'commonjs' } },
|
|
11
|
+
{ files: ['**/*.{js,mjs,cjs,ts}'], languageOptions: { globals: globals.node } },
|
|
12
|
+
{ files: ['**/*.{js,mjs,cjs,ts}'], plugins: { js }, extends: ['js/recommended'] },
|
|
13
|
+
tseslint.configs.recommended,
|
|
14
|
+
eslintPluginUnicorn.configs.recommended,
|
|
15
|
+
pluginPromise.configs['flat/recommended'],
|
|
16
|
+
{
|
|
17
|
+
rules: {
|
|
18
|
+
'block-scoped-var': 'error',
|
|
19
|
+
'no-loop-func': 'error',
|
|
20
|
+
//
|
|
21
|
+
'@typescript-eslint/no-explicit-any': 'off',
|
|
22
|
+
'@typescript-eslint/no-unused-vars': 'off',
|
|
23
|
+
'@typescript-eslint/no-empty-function': 'off',
|
|
24
|
+
'@typescript-eslint/no-empty-interface': 'off',
|
|
25
|
+
//
|
|
26
|
+
'unicorn/prevent-abbreviations': 'off',
|
|
27
|
+
// 'lodash/prefer-lodash-method': 'off',
|
|
28
|
+
// 'rxjs/no-implicit-any-catch': 'off',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
]);
|
package/package.json
CHANGED
|
@@ -1,52 +1,63 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "gcf-common-lib",
|
|
3
|
-
"description": "",
|
|
4
|
-
"version": "0.
|
|
5
|
-
"publishConfig": {
|
|
6
|
-
"access": "public",
|
|
7
|
-
"branches": [
|
|
8
|
-
"master"
|
|
9
|
-
]
|
|
10
|
-
},
|
|
11
|
-
"engines": {
|
|
12
|
-
"node": ">=20"
|
|
13
|
-
},
|
|
14
|
-
"main": "src/index",
|
|
15
|
-
"scripts": {
|
|
16
|
-
"build": "tsc",
|
|
17
|
-
"test": "node --test
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
"@
|
|
39
|
-
"@types/
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "gcf-common-lib",
|
|
3
|
+
"description": "Common helpers for Google Cloud Functions: Pub/Sub publishing, Mongo helpers, and utilities for Node 20+ (TypeScript).",
|
|
4
|
+
"version": "0.36.0",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public",
|
|
7
|
+
"branches": [
|
|
8
|
+
"master"
|
|
9
|
+
]
|
|
10
|
+
},
|
|
11
|
+
"engines": {
|
|
12
|
+
"node": ">=20"
|
|
13
|
+
},
|
|
14
|
+
"main": "src/index",
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsc",
|
|
17
|
+
"test": "node --test .\\test\\sample.test.js",
|
|
18
|
+
"test:ts": "node --test --import tsx .\\test",
|
|
19
|
+
"test:coverage": "c8 --reporter=text --reporter=html node --test .\\test\\sample.test.js"
|
|
20
|
+
},
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/TopTechnologies/gcf-common.git"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"node",
|
|
27
|
+
"typescript",
|
|
28
|
+
"google-cloud-functions",
|
|
29
|
+
"gcf",
|
|
30
|
+
"pubsub",
|
|
31
|
+
"mongodb",
|
|
32
|
+
"utilities"
|
|
33
|
+
],
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@google-cloud/pubsub": "^5.2.0",
|
|
36
|
+
"@google-cloud/storage": "^7.18.0",
|
|
37
|
+
"@types/bluebird": "^3.5.42",
|
|
38
|
+
"@types/express": "^4.17.25",
|
|
39
|
+
"@types/lodash": "^4.17.21",
|
|
40
|
+
"bluebird": "^3.7.2",
|
|
41
|
+
"lodash": "^4.17.21",
|
|
42
|
+
"moment": "^2.30.1",
|
|
43
|
+
"mongodb": "^6.21.0",
|
|
44
|
+
"rxjs": "^7.8.2"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@tsconfig/node20": "^20.1.8",
|
|
48
|
+
"@types/node": "^20.19.27",
|
|
49
|
+
"@eslint/js": "^9.21.0",
|
|
50
|
+
"eslint": "^9.21.0",
|
|
51
|
+
"eslint-plugin-lodash": "^8.0.0",
|
|
52
|
+
"eslint-plugin-promise": "^7.2.1",
|
|
53
|
+
"eslint-plugin-unicorn": "^57.0.0",
|
|
54
|
+
"globals": "^15.15.0",
|
|
55
|
+
"prettier": "^3.7.4",
|
|
56
|
+
"typescript-eslint": "^8.25.0",
|
|
57
|
+
"typescript": "^5.8.3",
|
|
58
|
+
"tsx": "^4.16.2",
|
|
59
|
+
"c8": "^9.1.0"
|
|
60
|
+
},
|
|
61
|
+
"author": "alert83@gmail.com",
|
|
62
|
+
"license": "MIT"
|
|
63
|
+
}
|
|
@@ -1,52 +1,52 @@
|
|
|
1
|
-
import { Channel, ChannelModel, ConfirmChannel, connect, Options } from 'amqplib';
|
|
2
|
-
import Bluebird from 'bluebird';
|
|
3
|
-
import Dict = NodeJS.Dict;
|
|
4
|
-
|
|
5
|
-
export const AmqpHelper = {
|
|
6
|
-
async withAmqpConn(fn: (channelModel: ChannelModel) => Promise<any>, url: string) {
|
|
7
|
-
function withDisposer() {
|
|
8
|
-
return Bluebird.method(async () => {
|
|
9
|
-
const amqpConn = await connect(url);
|
|
10
|
-
amqpConn.on('close', () => console.info('Amqp connection closed!'));
|
|
11
|
-
return amqpConn;
|
|
12
|
-
})().disposer((channelModel, promise) => channelModel.close());
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
return Bluebird.using(withDisposer(), channelModel => fn(channelModel));
|
|
16
|
-
},
|
|
17
|
-
|
|
18
|
-
async withAmqpCh(fn: (ch: Channel) => Promise<any>, url: string, useConfirmChannel = false, prefetch = 1) {
|
|
19
|
-
return AmqpHelper.withAmqpConn(async channelModel => {
|
|
20
|
-
function withDisposer() {
|
|
21
|
-
return Bluebird.method(async () => {
|
|
22
|
-
const ch = useConfirmChannel ? await channelModel.createConfirmChannel() : await channelModel.createChannel();
|
|
23
|
-
await ch.prefetch(prefetch);
|
|
24
|
-
return ch;
|
|
25
|
-
})().disposer((ch, promise) => ch.close());
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return Bluebird.using(withDisposer(), ch => fn(ch));
|
|
29
|
-
}, url);
|
|
30
|
-
},
|
|
31
|
-
|
|
32
|
-
async publishAmqp(
|
|
33
|
-
ch: Channel,
|
|
34
|
-
exchange: string | undefined,
|
|
35
|
-
routingKey: string,
|
|
36
|
-
json: Dict<any>,
|
|
37
|
-
options?: Options.Publish,
|
|
38
|
-
) {
|
|
39
|
-
const payload = Buffer.from(JSON.stringify(json));
|
|
40
|
-
const keepSending = exchange
|
|
41
|
-
? ch.publish(exchange, routingKey, payload, options)
|
|
42
|
-
: ch.sendToQueue(routingKey, payload, options);
|
|
43
|
-
if (!keepSending) await new Promise<void>(resolve => ch.once('drain', () => resolve()));
|
|
44
|
-
},
|
|
45
|
-
|
|
46
|
-
async sendToQueueConfAmqp(ch: ConfirmChannel, queue: string, json: Dict<any>, options?: Options.Publish) {
|
|
47
|
-
const payload = Buffer.from(JSON.stringify(json));
|
|
48
|
-
await new Promise((resolve, reject) =>
|
|
49
|
-
ch.sendToQueue(queue, payload, options, (err, ok) => (err ? reject(err) : resolve(ok))),
|
|
50
|
-
);
|
|
51
|
-
},
|
|
52
|
-
};
|
|
1
|
+
import { Channel, ChannelModel, ConfirmChannel, connect, Options } from 'amqplib';
|
|
2
|
+
import Bluebird from 'bluebird';
|
|
3
|
+
import Dict = NodeJS.Dict;
|
|
4
|
+
|
|
5
|
+
export const AmqpHelper = {
|
|
6
|
+
async withAmqpConn(fn: (channelModel: ChannelModel) => Promise<any>, url: string) {
|
|
7
|
+
function withDisposer() {
|
|
8
|
+
return Bluebird.method(async () => {
|
|
9
|
+
const amqpConn = await connect(url);
|
|
10
|
+
amqpConn.on('close', () => console.info('Amqp connection closed!'));
|
|
11
|
+
return amqpConn;
|
|
12
|
+
})().disposer((channelModel, promise) => channelModel.close());
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return Bluebird.using(withDisposer(), channelModel => fn(channelModel));
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
async withAmqpCh(fn: (ch: Channel) => Promise<any>, url: string, useConfirmChannel = false, prefetch = 1) {
|
|
19
|
+
return AmqpHelper.withAmqpConn(async channelModel => {
|
|
20
|
+
function withDisposer() {
|
|
21
|
+
return Bluebird.method(async () => {
|
|
22
|
+
const ch = useConfirmChannel ? await channelModel.createConfirmChannel() : await channelModel.createChannel();
|
|
23
|
+
await ch.prefetch(prefetch);
|
|
24
|
+
return ch;
|
|
25
|
+
})().disposer((ch, promise) => ch.close());
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return Bluebird.using(withDisposer(), ch => fn(ch));
|
|
29
|
+
}, url);
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
async publishAmqp(
|
|
33
|
+
ch: Channel,
|
|
34
|
+
exchange: string | undefined,
|
|
35
|
+
routingKey: string,
|
|
36
|
+
json: Dict<any>,
|
|
37
|
+
options?: Options.Publish,
|
|
38
|
+
) {
|
|
39
|
+
const payload = Buffer.from(JSON.stringify(json));
|
|
40
|
+
const keepSending = exchange
|
|
41
|
+
? ch.publish(exchange, routingKey, payload, options)
|
|
42
|
+
: ch.sendToQueue(routingKey, payload, options);
|
|
43
|
+
if (!keepSending) await new Promise<void>(resolve => ch.once('drain', () => resolve()));
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
async sendToQueueConfAmqp(ch: ConfirmChannel, queue: string, json: Dict<any>, options?: Options.Publish) {
|
|
47
|
+
const payload = Buffer.from(JSON.stringify(json));
|
|
48
|
+
await new Promise((resolve, reject) =>
|
|
49
|
+
ch.sendToQueue(queue, payload, options, (err, ok) => (err ? reject(err) : resolve(ok))),
|
|
50
|
+
);
|
|
51
|
+
},
|
|
52
|
+
};
|