gcf-common-lib 0.34.0 → 0.35.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/eslint.config.mjs +7 -9
- package/package.json +3 -3
- package/src/index.js +36 -37
- package/src/index.ts +43 -56
- package/tsconfig.json +3 -1
package/eslint.config.mjs
CHANGED
|
@@ -1,20 +1,18 @@
|
|
|
1
|
+
import { defineConfig } from 'eslint/config';
|
|
1
2
|
import globals from 'globals';
|
|
2
|
-
import
|
|
3
|
+
import js from '@eslint/js';
|
|
3
4
|
import tseslint from 'typescript-eslint';
|
|
4
5
|
import eslintPluginUnicorn from 'eslint-plugin-unicorn';
|
|
5
6
|
import pluginPromise from 'eslint-plugin-promise';
|
|
6
|
-
// import pluginLodash from 'eslint-plugin-lodash';
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
export default [
|
|
8
|
+
export default defineConfig([
|
|
10
9
|
{ files: ['**/*.{js,mjs,cjs,ts}'] },
|
|
11
10
|
{ files: ['**/*.js'], languageOptions: { sourceType: 'commonjs' } },
|
|
12
|
-
{ languageOptions: { globals: globals.node } },
|
|
13
|
-
|
|
14
|
-
|
|
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,
|
|
15
14
|
eslintPluginUnicorn.configs.recommended,
|
|
16
15
|
pluginPromise.configs['flat/recommended'],
|
|
17
|
-
// pluginLodash.configs.recommended,
|
|
18
16
|
{
|
|
19
17
|
rules: {
|
|
20
18
|
'block-scoped-var': 'error',
|
|
@@ -30,4 +28,4 @@ export default [
|
|
|
30
28
|
// 'rxjs/no-implicit-any-catch': 'off',
|
|
31
29
|
},
|
|
32
30
|
},
|
|
33
|
-
];
|
|
31
|
+
]);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gcf-common-lib",
|
|
3
3
|
"description": "",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.35.0",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
7
7
|
"branches": [
|
|
@@ -23,12 +23,10 @@
|
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@google-cloud/pubsub": "^4.10.0",
|
|
25
25
|
"@google-cloud/storage": "^7.15.2",
|
|
26
|
-
"@tsconfig/node20": "^20.1.4",
|
|
27
26
|
"@types/amqplib": "^0.10.7",
|
|
28
27
|
"@types/bluebird": "^3.5.42",
|
|
29
28
|
"@types/express": "^4.17.21",
|
|
30
29
|
"@types/lodash": "^4.17.16",
|
|
31
|
-
"@types/node": "^20.17.23",
|
|
32
30
|
"amqplib": "^0.10.5",
|
|
33
31
|
"bluebird": "^3.7.2",
|
|
34
32
|
"lodash": "^4.17.21",
|
|
@@ -37,6 +35,8 @@
|
|
|
37
35
|
"rxjs": "^7.8.2"
|
|
38
36
|
},
|
|
39
37
|
"devDependencies": {
|
|
38
|
+
"@tsconfig/node20": "^20.1.4",
|
|
39
|
+
"@types/node": "^20.17.23",
|
|
40
40
|
"@eslint/js": "^9.21.0",
|
|
41
41
|
"eslint": "^9.21.0",
|
|
42
42
|
"eslint-plugin-lodash": "^8.0.0",
|
package/src/index.js
CHANGED
|
@@ -45,7 +45,6 @@ const storage_1 = require("@google-cloud/storage");
|
|
|
45
45
|
const isEmpty_1 = __importDefault(require("lodash/isEmpty"));
|
|
46
46
|
const mapValues_1 = __importDefault(require("lodash/mapValues"));
|
|
47
47
|
const noop_1 = __importDefault(require("lodash/noop"));
|
|
48
|
-
const rxjs_1 = require("rxjs");
|
|
49
48
|
const amqp_helper_1 = require("./amqp-helper");
|
|
50
49
|
const utils_1 = require("./utils");
|
|
51
50
|
exports.Storage = __importStar(require("@google-cloud/storage"));
|
|
@@ -58,28 +57,29 @@ __exportStar(require("./mongo-helper"), exports);
|
|
|
58
57
|
__exportStar(require("./amqp-helper"), exports);
|
|
59
58
|
exports.pubSub = new pubsub_1.PubSub();
|
|
60
59
|
exports.storage = new storage_1.Storage();
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
constructor() { }
|
|
64
|
-
static amqpOptions = {
|
|
60
|
+
exports.GcfCommon = {
|
|
61
|
+
amqpOptions: {
|
|
65
62
|
assertExchange: { durable: true, autoDelete: false },
|
|
66
63
|
assertOptions: { durable: true, autoDelete: true, expires: (0, utils_1.ms)({ d: 1 }) },
|
|
67
64
|
publishOptions: { persistent: true },
|
|
68
|
-
}
|
|
69
|
-
|
|
65
|
+
},
|
|
66
|
+
async process(payload, handler) {
|
|
70
67
|
const asyncHandler = async (p) => await handler(p);
|
|
71
|
-
return
|
|
68
|
+
// return firstValueFrom(
|
|
69
|
+
// defer(() => from(asyncHandler({ ...payload }))).pipe(first(), timeout({ first: ms({ s: timeoutSec }) })),
|
|
70
|
+
// )
|
|
71
|
+
return asyncHandler({ ...payload })
|
|
72
72
|
.then(async (res) => {
|
|
73
73
|
// console.log('res:', res);
|
|
74
|
-
await
|
|
74
|
+
await exports.GcfCommon.response({ ...payload }, res).catch(noop_1.default);
|
|
75
75
|
return res;
|
|
76
76
|
})
|
|
77
77
|
.catch(async (error) => {
|
|
78
|
-
await
|
|
78
|
+
await exports.GcfCommon.response({ ...payload }, exports.GcfCommon.buildResponse(error), { error: '1' }).catch(noop_1.default);
|
|
79
79
|
throw error;
|
|
80
80
|
});
|
|
81
|
-
}
|
|
82
|
-
|
|
81
|
+
},
|
|
82
|
+
buildResponse(error) {
|
|
83
83
|
return {
|
|
84
84
|
error: {
|
|
85
85
|
name: error.name,
|
|
@@ -87,16 +87,16 @@ class GcfCommon {
|
|
|
87
87
|
stack: error.stack,
|
|
88
88
|
},
|
|
89
89
|
};
|
|
90
|
-
}
|
|
91
|
-
|
|
90
|
+
},
|
|
91
|
+
async response(payload, json, attributes) {
|
|
92
92
|
// console.time('safeGetAttributes');
|
|
93
|
-
// const { topic, exchange, queue, consumer_id, request_id, app_id, env } = await
|
|
93
|
+
// const { topic, exchange, queue, consumer_id, request_id, app_id, env } = await GcfCommon.safeGetAttributes(
|
|
94
94
|
// event,
|
|
95
95
|
// context,
|
|
96
96
|
// ['consumer_id', 'topic', 'exchange', 'queue'],
|
|
97
97
|
// );
|
|
98
98
|
// console.timeEnd('safeGetAttributes');
|
|
99
|
-
const { topic, exchange, queue, consumer_id, request_id, app_id, env } =
|
|
99
|
+
const { topic, exchange, queue, consumer_id, request_id, app_id, env } = exports.GcfCommon.getMetadataOrAttribute(payload);
|
|
100
100
|
//
|
|
101
101
|
console.time('publish');
|
|
102
102
|
if (topic && !(0, isEmpty_1.default)(topic)) {
|
|
@@ -115,27 +115,27 @@ class GcfCommon {
|
|
|
115
115
|
if (exchange && !(0, isEmpty_1.default)(exchange)) {
|
|
116
116
|
console.log('send:', exchange, queue, app_id, env, json, attributes);
|
|
117
117
|
await amqp_helper_1.AmqpHelper.withAmqpCh(async (ch) => {
|
|
118
|
-
await ch.assertExchange(exchange, 'direct',
|
|
118
|
+
await ch.assertExchange(exchange, 'direct', exports.GcfCommon.amqpOptions.assertExchange);
|
|
119
119
|
await amqp_helper_1.AmqpHelper.publishAmqp(ch, exchange, queue ?? '', json ?? {}, {
|
|
120
|
-
...
|
|
120
|
+
...exports.GcfCommon.amqpOptions.publishOptions,
|
|
121
121
|
correlationId: request_id,
|
|
122
122
|
});
|
|
123
|
-
},
|
|
123
|
+
}, exports.GcfCommon.amqpOptions.url);
|
|
124
124
|
}
|
|
125
125
|
else if (queue && !(0, isEmpty_1.default)(queue)) {
|
|
126
126
|
console.log('send:', queue, app_id, env, json, attributes);
|
|
127
127
|
await amqp_helper_1.AmqpHelper.withAmqpCh(async (ch) => {
|
|
128
|
-
// await ch.assertQueue(queue,
|
|
128
|
+
// await ch.assertQueue(queue, GcfCommon.amqpOptions.assertOptions);
|
|
129
129
|
await amqp_helper_1.AmqpHelper.publishAmqp(ch, undefined, queue, json ?? {}, {
|
|
130
|
-
...
|
|
130
|
+
...exports.GcfCommon.amqpOptions.publishOptions,
|
|
131
131
|
correlationId: request_id,
|
|
132
132
|
});
|
|
133
|
-
},
|
|
133
|
+
}, exports.GcfCommon.amqpOptions.url);
|
|
134
134
|
}
|
|
135
135
|
console.timeEnd('publish');
|
|
136
|
-
}
|
|
137
|
-
//
|
|
138
|
-
// let metaOrAttr =
|
|
136
|
+
},
|
|
137
|
+
// async safeGetAttributes<E = TEvent>(event: E, context: TContext, props: string[]) {
|
|
138
|
+
// let metaOrAttr = GcfCommon.getMetadataOrAttribute(event, context);
|
|
139
139
|
// // const everyPropIsNil = props.map(prop => get(metaOrAttr, prop)).every(v => isNil(v));
|
|
140
140
|
//
|
|
141
141
|
// const someProp = props.map(prop => get(metaOrAttr, prop)).some(v => !isNil(v));
|
|
@@ -154,13 +154,13 @@ class GcfCommon {
|
|
|
154
154
|
// app_id: metaOrAttr.app_id,
|
|
155
155
|
// request_id: metaOrAttr.request_id,
|
|
156
156
|
// } as TMetadataOrAttributes;
|
|
157
|
-
// }
|
|
158
|
-
|
|
159
|
-
// const { options } = await
|
|
160
|
-
const { options } =
|
|
157
|
+
// },
|
|
158
|
+
async getOptions(payload) {
|
|
159
|
+
// const { options } = await GcfCommon.safeGetAttributes(event, context, ['options']);
|
|
160
|
+
const { options } = exports.GcfCommon.getMetadataOrAttribute(payload);
|
|
161
161
|
return (0, utils_1.safeJsonParse)(options, {});
|
|
162
|
-
}
|
|
163
|
-
|
|
162
|
+
},
|
|
163
|
+
getMetadataOrAttribute(payload) {
|
|
164
164
|
let metadataOrAttribute;
|
|
165
165
|
if (payload?.context) {
|
|
166
166
|
switch (payload?.context?.eventType) {
|
|
@@ -177,13 +177,12 @@ class GcfCommon {
|
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
179
|
else if (payload?.request) {
|
|
180
|
-
metadataOrAttribute =
|
|
180
|
+
metadataOrAttribute = exports.GcfCommon.getRequestMessage(payload.request)?.attributes;
|
|
181
181
|
}
|
|
182
182
|
// console.log('metadataOrAttribute:', metadataOrAttribute);
|
|
183
183
|
return metadataOrAttribute ?? {};
|
|
184
|
-
}
|
|
185
|
-
|
|
184
|
+
},
|
|
185
|
+
getRequestMessage(request) {
|
|
186
186
|
return request.body.message;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
exports.GcfCommon = GcfCommon;
|
|
187
|
+
},
|
|
188
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -5,7 +5,6 @@ import { Request } from 'express';
|
|
|
5
5
|
import isEmpty from 'lodash/isEmpty';
|
|
6
6
|
import mapValues from 'lodash/mapValues';
|
|
7
7
|
import noop from 'lodash/noop';
|
|
8
|
-
import { defer, first, firstValueFrom, from, timeout } from 'rxjs';
|
|
9
8
|
import { AmqpHelper } from './amqp-helper';
|
|
10
9
|
import { TEvent, TGSEvent, TMetadataOrAttributes, TPayload, TPSEvent, TResponse } from './types';
|
|
11
10
|
import { ms, safeJsonParse } from './utils';
|
|
@@ -22,43 +21,43 @@ export * from './amqp-helper';
|
|
|
22
21
|
|
|
23
22
|
export const pubSub = new PubSub();
|
|
24
23
|
export const storage = new Storage();
|
|
25
|
-
// export const secretClient = new SecretManagerServiceClient();
|
|
26
24
|
|
|
27
|
-
export
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
export const GcfCommon = {
|
|
26
|
+
amqpOptions: {
|
|
27
|
+
assertExchange: { durable: true, autoDelete: false },
|
|
28
|
+
assertOptions: { durable: true, autoDelete: true, expires: ms({ d: 1 }) },
|
|
29
|
+
publishOptions: { persistent: true },
|
|
30
|
+
} as {
|
|
31
31
|
url?: string;
|
|
32
32
|
assertExchange?: Options.AssertExchange;
|
|
33
33
|
assertOptions?: Options.AssertQueue;
|
|
34
34
|
publishOptions?: Options.Publish;
|
|
35
|
-
}
|
|
36
|
-
assertExchange: { durable: true, autoDelete: false },
|
|
37
|
-
assertOptions: { durable: true, autoDelete: true, expires: ms({ d: 1 }) },
|
|
38
|
-
publishOptions: { persistent: true },
|
|
39
|
-
};
|
|
35
|
+
},
|
|
40
36
|
|
|
41
|
-
|
|
37
|
+
async process<T extends TResponse, E = TEvent>(
|
|
42
38
|
payload: TPayload<E>,
|
|
43
39
|
handler: (p: TPayload<E>) => Promise<any> | any,
|
|
44
|
-
timeoutSec = 535,
|
|
40
|
+
// timeoutSec = 535,
|
|
45
41
|
) {
|
|
46
42
|
const asyncHandler = async (p: TPayload<E>) => await handler(p);
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
)
|
|
43
|
+
|
|
44
|
+
// return firstValueFrom(
|
|
45
|
+
// defer(() => from(asyncHandler({ ...payload }))).pipe(first(), timeout({ first: ms({ s: timeoutSec }) })),
|
|
46
|
+
// )
|
|
47
|
+
|
|
48
|
+
return asyncHandler({ ...payload })
|
|
50
49
|
.then(async res => {
|
|
51
50
|
// console.log('res:', res);
|
|
52
|
-
await
|
|
51
|
+
await GcfCommon.response({ ...payload }, res as T).catch(noop);
|
|
53
52
|
return res;
|
|
54
53
|
})
|
|
55
54
|
.catch(async (error: Error) => {
|
|
56
|
-
await
|
|
55
|
+
await GcfCommon.response({ ...payload }, GcfCommon.buildResponse(error), { error: '1' }).catch(noop);
|
|
57
56
|
throw error;
|
|
58
57
|
});
|
|
59
|
-
}
|
|
58
|
+
},
|
|
60
59
|
|
|
61
|
-
|
|
60
|
+
buildResponse(error: Error) {
|
|
62
61
|
return {
|
|
63
62
|
error: {
|
|
64
63
|
name: error.name,
|
|
@@ -66,18 +65,18 @@ export class GcfCommon {
|
|
|
66
65
|
stack: error.stack,
|
|
67
66
|
},
|
|
68
67
|
} as TResponse;
|
|
69
|
-
}
|
|
68
|
+
},
|
|
70
69
|
|
|
71
|
-
|
|
70
|
+
async response<E = TEvent>(payload: TPayload<E>, json?: TResponse, attributes?: Dict<any>) {
|
|
72
71
|
// console.time('safeGetAttributes');
|
|
73
|
-
// const { topic, exchange, queue, consumer_id, request_id, app_id, env } = await
|
|
72
|
+
// const { topic, exchange, queue, consumer_id, request_id, app_id, env } = await GcfCommon.safeGetAttributes(
|
|
74
73
|
// event,
|
|
75
74
|
// context,
|
|
76
75
|
// ['consumer_id', 'topic', 'exchange', 'queue'],
|
|
77
76
|
// );
|
|
78
77
|
// console.timeEnd('safeGetAttributes');
|
|
79
78
|
|
|
80
|
-
const { topic, exchange, queue, consumer_id, request_id, app_id, env } =
|
|
79
|
+
const { topic, exchange, queue, consumer_id, request_id, app_id, env } = GcfCommon.getMetadataOrAttribute(payload);
|
|
81
80
|
|
|
82
81
|
//
|
|
83
82
|
|
|
@@ -100,28 +99,28 @@ export class GcfCommon {
|
|
|
100
99
|
if (exchange && !isEmpty(exchange)) {
|
|
101
100
|
console.log('send:', exchange, queue, app_id, env, json, attributes);
|
|
102
101
|
await AmqpHelper.withAmqpCh(async ch => {
|
|
103
|
-
await ch.assertExchange(exchange, 'direct',
|
|
102
|
+
await ch.assertExchange(exchange, 'direct', GcfCommon.amqpOptions.assertExchange);
|
|
104
103
|
await AmqpHelper.publishAmqp(ch, exchange, queue ?? '', json ?? {}, {
|
|
105
|
-
...
|
|
104
|
+
...GcfCommon.amqpOptions.publishOptions,
|
|
106
105
|
correlationId: request_id,
|
|
107
106
|
});
|
|
108
|
-
},
|
|
107
|
+
}, GcfCommon.amqpOptions.url as string);
|
|
109
108
|
} else if (queue && !isEmpty(queue)) {
|
|
110
109
|
console.log('send:', queue, app_id, env, json, attributes);
|
|
111
110
|
await AmqpHelper.withAmqpCh(async ch => {
|
|
112
|
-
// await ch.assertQueue(queue,
|
|
111
|
+
// await ch.assertQueue(queue, GcfCommon.amqpOptions.assertOptions);
|
|
113
112
|
await AmqpHelper.publishAmqp(ch, undefined, queue, json ?? {}, {
|
|
114
|
-
...
|
|
113
|
+
...GcfCommon.amqpOptions.publishOptions,
|
|
115
114
|
correlationId: request_id,
|
|
116
115
|
});
|
|
117
|
-
},
|
|
116
|
+
}, GcfCommon.amqpOptions.url as string);
|
|
118
117
|
}
|
|
119
118
|
|
|
120
119
|
console.timeEnd('publish');
|
|
121
|
-
}
|
|
120
|
+
},
|
|
122
121
|
|
|
123
|
-
//
|
|
124
|
-
// let metaOrAttr =
|
|
122
|
+
// async safeGetAttributes<E = TEvent>(event: E, context: TContext, props: string[]) {
|
|
123
|
+
// let metaOrAttr = GcfCommon.getMetadataOrAttribute(event, context);
|
|
125
124
|
// // const everyPropIsNil = props.map(prop => get(metaOrAttr, prop)).every(v => isNil(v));
|
|
126
125
|
//
|
|
127
126
|
// const someProp = props.map(prop => get(metaOrAttr, prop)).some(v => !isNil(v));
|
|
@@ -140,15 +139,15 @@ export class GcfCommon {
|
|
|
140
139
|
// app_id: metaOrAttr.app_id,
|
|
141
140
|
// request_id: metaOrAttr.request_id,
|
|
142
141
|
// } as TMetadataOrAttributes;
|
|
143
|
-
// }
|
|
142
|
+
// },
|
|
144
143
|
|
|
145
|
-
|
|
146
|
-
// const { options } = await
|
|
147
|
-
const { options } =
|
|
144
|
+
async getOptions(payload: TPayload): Promise<Dict<any>> {
|
|
145
|
+
// const { options } = await GcfCommon.safeGetAttributes(event, context, ['options']);
|
|
146
|
+
const { options } = GcfCommon.getMetadataOrAttribute(payload);
|
|
148
147
|
return safeJsonParse(options as any, {} as any);
|
|
149
|
-
}
|
|
148
|
+
},
|
|
150
149
|
|
|
151
|
-
|
|
150
|
+
getMetadataOrAttribute<E = TEvent>(payload: TPayload<E>) {
|
|
152
151
|
let metadataOrAttribute: TMetadataOrAttributes | undefined;
|
|
153
152
|
|
|
154
153
|
if (payload?.context) {
|
|
@@ -165,27 +164,15 @@ export class GcfCommon {
|
|
|
165
164
|
}
|
|
166
165
|
}
|
|
167
166
|
} else if (payload?.request) {
|
|
168
|
-
metadataOrAttribute =
|
|
167
|
+
metadataOrAttribute = GcfCommon.getRequestMessage(payload.request)?.attributes;
|
|
169
168
|
}
|
|
170
169
|
|
|
171
170
|
// console.log('metadataOrAttribute:', metadataOrAttribute);
|
|
172
171
|
|
|
173
172
|
return metadataOrAttribute ?? {};
|
|
174
|
-
}
|
|
173
|
+
},
|
|
175
174
|
|
|
176
|
-
|
|
175
|
+
getRequestMessage(request: Request) {
|
|
177
176
|
return request.body.message as { attributes: TMetadataOrAttributes; data: string; json?: Dict<any> };
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// static async getSecret(name: string, version?: string) {
|
|
181
|
-
// const projectId = await secretClient.getProjectId();
|
|
182
|
-
// const secretName = `projects/${projectId}/secrets/${name}`;
|
|
183
|
-
// const secretVersion = `${secretName}/versions/${version ?? 'latest'}`;
|
|
184
|
-
// const [response] = await secretClient.accessSecretVersion({ name: secretVersion });
|
|
185
|
-
// return response?.payload?.data?.toString();
|
|
186
|
-
// }
|
|
187
|
-
//
|
|
188
|
-
// static async getSecrets(names: string[], versions?: string[]) {
|
|
189
|
-
// return Promise.all(names.map(async (name, idx) => this.getSecret(name, versions?.[idx]).catch(noop)));
|
|
190
|
-
// }
|
|
191
|
-
}
|
|
177
|
+
},
|
|
178
|
+
};
|