gcf-common-lib 0.11.0 → 0.13.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/index.js +102 -58
- package/index.ts +50 -16
- package/package.json +10 -8
- package/tsconfig.json +1 -0
- package/utils.js +16 -5
package/index.js
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
2
11
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
13
|
};
|
|
@@ -7,8 +16,8 @@ exports.GcfCommon = exports.storage = exports.pubSub = void 0;
|
|
|
7
16
|
const pubsub_1 = require("@google-cloud/pubsub");
|
|
8
17
|
const secret_manager_1 = require("@google-cloud/secret-manager");
|
|
9
18
|
const storage_1 = require("@google-cloud/storage");
|
|
10
|
-
const isEmpty_1 = __importDefault(require("lodash
|
|
11
|
-
const noop_1 = __importDefault(require("lodash
|
|
19
|
+
const isEmpty_1 = __importDefault(require("lodash/isEmpty"));
|
|
20
|
+
const noop_1 = __importDefault(require("lodash/noop"));
|
|
12
21
|
const utils_1 = require("./utils");
|
|
13
22
|
exports.pubSub = new pubsub_1.PubSub();
|
|
14
23
|
exports.storage = new storage_1.Storage();
|
|
@@ -21,68 +30,103 @@ class GcfCommon {
|
|
|
21
30
|
* @param handler
|
|
22
31
|
* @param timeout Seconds
|
|
23
32
|
*/
|
|
24
|
-
static
|
|
25
|
-
return
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
33
|
+
static process(event, context, handler, timeout = 535) {
|
|
34
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
35
|
+
return Promise.race([
|
|
36
|
+
(0, utils_1.timeoutAfter)(timeout),
|
|
37
|
+
handler(event, context),
|
|
38
|
+
])
|
|
39
|
+
.then((res) => __awaiter(this, void 0, void 0, function* () {
|
|
40
|
+
// console.log('res:', res);
|
|
41
|
+
yield this.publish(event, context, res !== null && res !== void 0 ? res : {});
|
|
42
|
+
}))
|
|
43
|
+
.catch((err) => __awaiter(this, void 0, void 0, function* () {
|
|
44
|
+
var _a, _b;
|
|
45
|
+
const fname = (_b = (_a = process === null || process === void 0 ? void 0 : process.env) === null || _a === void 0 ? void 0 : _a.K_SERVICE) !== null && _b !== void 0 ? _b : 'UNKNOWN';
|
|
46
|
+
const response = {
|
|
47
|
+
error: {
|
|
48
|
+
name: err.name,
|
|
49
|
+
message: `GCF [${fname}]: ${err.message}`,
|
|
50
|
+
stack: err.stack,
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
const attr = {
|
|
54
|
+
error: {
|
|
55
|
+
name: err.name,
|
|
56
|
+
message: `GCF [${fname}]: ${err.message}`,
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
yield this.publish(event, context, response, attr).catch(noop_1.default);
|
|
60
|
+
throw err;
|
|
61
|
+
}));
|
|
44
62
|
});
|
|
45
63
|
}
|
|
46
|
-
static
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
64
|
+
static publish(event, context, json, attributes) {
|
|
65
|
+
var _a, _b;
|
|
66
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
67
|
+
const topic = yield this.getTopic(event, context);
|
|
68
|
+
console.log('publish:', topic === null || topic === void 0 ? void 0 : topic.name, json);
|
|
69
|
+
if (topic) {
|
|
70
|
+
return yield topic.publishMessage({
|
|
71
|
+
json,
|
|
72
|
+
attributes: Object.assign(Object.assign({}, attributes), { requestId: (_b = (_a = event) === null || _a === void 0 ? void 0 : _a.attributes) === null || _b === void 0 ? void 0 : _b.requestId, type: 'response', response: true }),
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
});
|
|
51
76
|
}
|
|
52
|
-
static
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
77
|
+
static getTopic(event, context) {
|
|
78
|
+
var _a, _b, _c, _d, _e, _f;
|
|
79
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
80
|
+
/** t_{GUID}__{YYYY-MM-DD} */
|
|
81
|
+
let topicName;
|
|
82
|
+
if ((context === null || context === void 0 ? void 0 : context.eventType) === 'google.storage.object.finalize') {
|
|
83
|
+
const gsEvent = event;
|
|
84
|
+
topicName = (_a = gsEvent === null || gsEvent === void 0 ? void 0 : gsEvent.metadata) === null || _a === void 0 ? void 0 : _a.topic;
|
|
85
|
+
if (!topicName && ((_b = context === null || context === void 0 ? void 0 : context.resource) === null || _b === void 0 ? void 0 : _b.type) === 'storage#object') {
|
|
86
|
+
const file = exports.storage.bucket(gsEvent.bucket).file(gsEvent.name);
|
|
87
|
+
const [meta] = yield file.getMetadata();
|
|
88
|
+
topicName = (_c = meta === null || meta === void 0 ? void 0 : meta.metadata) === null || _c === void 0 ? void 0 : _c.topic;
|
|
89
|
+
console.log('topic:', topicName);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
else if ((context === null || context === void 0 ? void 0 : context.eventType) === 'google.pubsub.topic.publish') {
|
|
93
|
+
const psEvent = event;
|
|
94
|
+
topicName = (_e = (_d = psEvent.attributes) === null || _d === void 0 ? void 0 : _d.topic) !== null && _e !== void 0 ? _e : (_f = psEvent.data) === null || _f === void 0 ? void 0 : _f.topic;
|
|
95
|
+
}
|
|
96
|
+
if (topicName && !(0, isEmpty_1.default)(topicName)) {
|
|
97
|
+
const topic = exports.pubSub.topic(topicName);
|
|
98
|
+
yield topic.setMetadata({ labels: { date: topicName.split('__')[1] } });
|
|
99
|
+
return topic;
|
|
100
|
+
}
|
|
101
|
+
});
|
|
66
102
|
}
|
|
67
|
-
static
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
103
|
+
static getOptions(event, context) {
|
|
104
|
+
var _a, _b, _c, _d, _e;
|
|
105
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
106
|
+
if ((_a = event === null || event === void 0 ? void 0 : event.metadata) === null || _a === void 0 ? void 0 : _a.options) {
|
|
107
|
+
return JSON.parse((_c = (_b = event === null || event === void 0 ? void 0 : event.metadata) === null || _b === void 0 ? void 0 : _b.options) !== null && _c !== void 0 ? _c : '{}');
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
const file = exports.storage.bucket(event.bucket).file(event.name);
|
|
111
|
+
const [meta] = yield file.getMetadata();
|
|
112
|
+
return JSON.parse((_e = (_d = meta === null || meta === void 0 ? void 0 : meta.metadata) === null || _d === void 0 ? void 0 : _d.options) !== null && _e !== void 0 ? _e : '{}');
|
|
113
|
+
}
|
|
114
|
+
});
|
|
76
115
|
}
|
|
77
|
-
static
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
116
|
+
static getSecret(name, version) {
|
|
117
|
+
var _a, _b;
|
|
118
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
119
|
+
const projectId = yield secretClient.getProjectId();
|
|
120
|
+
const secretName = `projects/${projectId}/secrets/${name}`;
|
|
121
|
+
const secretVersion = `${secretName}/versions/${version !== null && version !== void 0 ? version : 'latest'}`;
|
|
122
|
+
const [response] = yield secretClient.accessSecretVersion({ name: secretVersion });
|
|
123
|
+
return (_b = (_a = response === null || response === void 0 ? void 0 : response.payload) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.toString();
|
|
124
|
+
});
|
|
83
125
|
}
|
|
84
|
-
static
|
|
85
|
-
return
|
|
126
|
+
static getSecrets(names, versions) {
|
|
127
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
128
|
+
return Promise.all(names.map((name, idx) => __awaiter(this, void 0, void 0, function* () { return this.getSecret(name, versions === null || versions === void 0 ? void 0 : versions[idx]); })));
|
|
129
|
+
});
|
|
86
130
|
}
|
|
87
131
|
}
|
|
88
132
|
exports.GcfCommon = GcfCommon;
|
package/index.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {PubSub} from "@google-cloud/pubsub";
|
|
2
2
|
import {SecretManagerServiceClient} from "@google-cloud/secret-manager";
|
|
3
3
|
import {File, Storage} from "@google-cloud/storage";
|
|
4
|
-
import isEmpty from "lodash
|
|
5
|
-
import noop from "lodash
|
|
4
|
+
import isEmpty from "lodash/isEmpty";
|
|
5
|
+
import noop from "lodash/noop";
|
|
6
6
|
import {timeoutAfter} from "./utils";
|
|
7
7
|
|
|
8
|
-
export type
|
|
8
|
+
export type TGSEvent = {
|
|
9
9
|
bucket: string;
|
|
10
10
|
contentType: string;
|
|
11
11
|
crc32c: string;
|
|
@@ -26,14 +26,22 @@ export type TEvent = {
|
|
|
26
26
|
updated: string;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
export type TPSEvent = {
|
|
30
|
+
'@type': string; // 'type.googleapis.com/google.pubsub.v1.PubsubMessage'
|
|
31
|
+
attributes?: { [k: string]: any };
|
|
32
|
+
data?: string | { [k: string]: any };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export type TEvent = TGSEvent | TPSEvent;
|
|
36
|
+
|
|
29
37
|
export type TContext = {
|
|
30
38
|
eventId: string;
|
|
31
39
|
timestamp: string;
|
|
32
|
-
eventType:
|
|
40
|
+
eventType: 'google.storage.object.finalize' | 'google.pubsub.topic.publish';
|
|
33
41
|
resource: {
|
|
34
|
-
service:
|
|
42
|
+
service: 'storage.googleapis.com' | 'pubsub.googleapis.com';
|
|
35
43
|
name: string;
|
|
36
|
-
type: string; // 'storage#object'
|
|
44
|
+
type: string; // 'storage#object' | 'type.googleapis.com/google.pubsub.v1.PubsubMessage'
|
|
37
45
|
}
|
|
38
46
|
}
|
|
39
47
|
|
|
@@ -81,28 +89,54 @@ export class GcfCommon {
|
|
|
81
89
|
stack: err.stack,
|
|
82
90
|
},
|
|
83
91
|
};
|
|
84
|
-
|
|
92
|
+
const attr = {
|
|
93
|
+
error: {
|
|
94
|
+
name: err.name,
|
|
95
|
+
message: `GCF [${fname}]: ${err.message}`,
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
await this.publish(event, context, response, attr).catch(noop);
|
|
85
99
|
throw err;
|
|
86
100
|
})
|
|
87
101
|
;
|
|
88
102
|
}
|
|
89
103
|
|
|
90
|
-
static async publish(event: TEvent, context: TContext, json: TResponse) {
|
|
104
|
+
static async publish(event: TEvent, context: TContext, json: TResponse, attributes?: any) {
|
|
91
105
|
const topic = await this.getTopic(event, context);
|
|
92
106
|
console.log('publish:', topic?.name, json);
|
|
93
|
-
|
|
107
|
+
|
|
108
|
+
if (topic) {
|
|
109
|
+
return await topic.publishMessage({
|
|
110
|
+
json,
|
|
111
|
+
attributes: {
|
|
112
|
+
...attributes,
|
|
113
|
+
requestId: (event as TPSEvent)?.attributes?.requestId,
|
|
114
|
+
type: 'response',
|
|
115
|
+
response: true,
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
}
|
|
94
119
|
}
|
|
95
120
|
|
|
96
121
|
static async getTopic(event: TEvent, context: TContext) {
|
|
97
122
|
|
|
98
123
|
/** t_{GUID}__{YYYY-MM-DD} */
|
|
99
|
-
let topicName: string | undefined
|
|
124
|
+
let topicName: string | undefined;
|
|
100
125
|
|
|
101
|
-
if (
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
topicName =
|
|
105
|
-
|
|
126
|
+
if (context?.eventType === 'google.storage.object.finalize') {
|
|
127
|
+
const gsEvent = event as TGSEvent;
|
|
128
|
+
|
|
129
|
+
topicName = gsEvent?.metadata?.topic;
|
|
130
|
+
|
|
131
|
+
if (!topicName && context?.resource?.type === 'storage#object') {
|
|
132
|
+
const file: File = storage.bucket(gsEvent.bucket).file(gsEvent.name);
|
|
133
|
+
const [meta] = await file.getMetadata();
|
|
134
|
+
topicName = meta?.metadata?.topic;
|
|
135
|
+
console.log('topic:', topicName);
|
|
136
|
+
}
|
|
137
|
+
} else if (context?.eventType === 'google.pubsub.topic.publish') {
|
|
138
|
+
const psEvent = event as TPSEvent;
|
|
139
|
+
topicName = psEvent.attributes?.topic ?? (psEvent.data as any)?.topic;
|
|
106
140
|
}
|
|
107
141
|
|
|
108
142
|
if (topicName && !isEmpty(topicName)) {
|
|
@@ -112,7 +146,7 @@ export class GcfCommon {
|
|
|
112
146
|
}
|
|
113
147
|
}
|
|
114
148
|
|
|
115
|
-
static async getOptions(event:
|
|
149
|
+
static async getOptions(event: TGSEvent, context: TContext) {
|
|
116
150
|
if (event?.metadata?.options) {
|
|
117
151
|
return JSON.parse(event?.metadata?.options ?? '{}');
|
|
118
152
|
} else {
|
package/package.json
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gcf-common-lib",
|
|
3
3
|
"description": "",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.13.0",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
7
7
|
"branches": [
|
|
8
8
|
"master"
|
|
9
9
|
]
|
|
10
10
|
},
|
|
11
|
-
"engines": {
|
|
11
|
+
"engines": {
|
|
12
|
+
"node": "14",
|
|
13
|
+
"npm": "8"
|
|
14
|
+
},
|
|
12
15
|
"scripts": {
|
|
13
16
|
"test": "echo \"Error: no test specified\" || exit 0"
|
|
14
17
|
},
|
|
@@ -17,16 +20,15 @@
|
|
|
17
20
|
"url": "https://github.com/TopTechnologies/gcf-common.git"
|
|
18
21
|
},
|
|
19
22
|
"dependencies": {
|
|
20
|
-
"@google-cloud/pubsub": "^2.
|
|
21
|
-
"@google-cloud/secret-manager": "^3.
|
|
22
|
-
"@google-cloud/storage": "^5.18.
|
|
23
|
-
"lodash
|
|
23
|
+
"@google-cloud/pubsub": "^2.19.0",
|
|
24
|
+
"@google-cloud/secret-manager": "^3.11.0",
|
|
25
|
+
"@google-cloud/storage": "^5.18.2",
|
|
26
|
+
"lodash": "^4.17.21"
|
|
24
27
|
},
|
|
25
28
|
"devDependencies": {
|
|
26
29
|
"@tsconfig/node14": "^1.0.1",
|
|
27
|
-
"@types/lodash
|
|
30
|
+
"@types/lodash": "^4.14.179"
|
|
28
31
|
},
|
|
29
|
-
"keywords": [],
|
|
30
32
|
"author": "alert83@gmail.com",
|
|
31
33
|
"license": "MIT"
|
|
32
34
|
}
|
package/tsconfig.json
CHANGED
package/utils.js
CHANGED
|
@@ -1,15 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
2
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
12
|
exports.A1ToColNum = exports.A1ToIndex = exports.colNumToA1 = exports.indexToA1 = exports.timeoutAfter = void 0;
|
|
4
13
|
/**
|
|
5
14
|
*
|
|
6
15
|
* @param seconds Google function timeout limit (max: 9 min)
|
|
7
16
|
*/
|
|
8
|
-
|
|
9
|
-
return
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
17
|
+
function timeoutAfter(seconds = 540) {
|
|
18
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
19
|
+
return new Promise((resolve, reject) => {
|
|
20
|
+
setTimeout(() => {
|
|
21
|
+
reject(new Error(`${seconds} seconds timeout exceeded`));
|
|
22
|
+
}, seconds * 1000);
|
|
23
|
+
});
|
|
13
24
|
});
|
|
14
25
|
}
|
|
15
26
|
exports.timeoutAfter = timeoutAfter;
|