gcf-common-lib 0.23.15 → 0.23.16

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "gcf-common-lib",
3
3
  "description": "",
4
- "version": "0.23.15",
4
+ "version": "0.23.16",
5
5
  "publishConfig": {
6
6
  "access": "public",
7
7
  "branches": [
@@ -20,7 +20,7 @@
20
20
  "dependencies": {
21
21
  "@google-cloud/pubsub": "^3.3.0",
22
22
  "@google-cloud/secret-manager": "^4.2.1",
23
- "@google-cloud/storage": "^6.9.3",
23
+ "@google-cloud/storage": "^6.9.4",
24
24
  "lodash": "^4.17.21",
25
25
  "moment": "^2.29.4",
26
26
  "mongodb": "^4.14.0",
@@ -29,8 +29,8 @@
29
29
  "devDependencies": {
30
30
  "@tsconfig/node14": "^1.0.3",
31
31
  "@types/lodash": "^4.14.191",
32
- "@types/node": "^14.18.36"
32
+ "@types/node": "^14.18.37"
33
33
  },
34
34
  "author": "alert83@gmail.com",
35
- "license": "MIT"
35
+ "license": ""
36
36
  }
package/src/index.js CHANGED
@@ -14,12 +14,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.GcfCommon = exports.secretClient = exports.storage = exports.pubSub = void 0;
16
16
  const pubsub_1 = require("@google-cloud/pubsub");
17
- const fromPairs_1 = __importDefault(require("lodash/fromPairs"));
18
17
  const isEmpty_1 = __importDefault(require("lodash/isEmpty"));
19
18
  const noop_1 = __importDefault(require("lodash/noop"));
20
19
  const utils_1 = require("./utils");
21
20
  const storage_1 = require("@google-cloud/storage");
22
21
  const secret_manager_1 = require("@google-cloud/secret-manager");
22
+ const lodash_1 = require("lodash");
23
23
  exports.pubSub = new pubsub_1.PubSub();
24
24
  exports.storage = new storage_1.Storage();
25
25
  exports.secretClient = new secret_manager_1.SecretManagerServiceClient();
@@ -55,64 +55,60 @@ class GcfCommon {
55
55
  }
56
56
  static publish(event, context, json, attributes) {
57
57
  return __awaiter(this, void 0, void 0, function* () {
58
- const { topic, requestId, env } = yield this.getTopic(event, context);
59
- console.log('publish:', topic, env, json, attributes);
58
+ const { topic, appId, env, requestId } = yield this.getTopic(event, context);
60
59
  if (!(0, isEmpty_1.default)(topic)) {
60
+ console.log('publish:', topic, appId, env, json, attributes);
61
61
  return exports.pubSub.topic(topic).publishMessage({
62
62
  json: json !== null && json !== void 0 ? json : {},
63
- attributes: Object.assign(Object.assign({}, (0, fromPairs_1.default)(Object.entries(attributes !== null && attributes !== void 0 ? attributes : {}).map(([k, v]) => [k, '' + v]))), { env: env !== null && env !== void 0 ? env : '', requestId: requestId !== null && requestId !== void 0 ? requestId : '', type: 'response', response: '1' }),
63
+ attributes: Object.assign(Object.assign({}, (0, lodash_1.mapValues)(attributes !== null && attributes !== void 0 ? attributes : {}, (v) => '' + v)), { requestId: requestId !== null && requestId !== void 0 ? requestId : '', appId: appId !== null && appId !== void 0 ? appId : '', env: env !== null && env !== void 0 ? env : '', type: 'response', response: '1' }),
64
64
  });
65
65
  }
66
66
  });
67
67
  }
68
68
  static getTopic(event, context) {
69
- var _a, _b, _c, _d;
69
+ var _a, _b;
70
70
  return __awaiter(this, void 0, void 0, function* () {
71
- /** t_{GUID}__{YYYY-MM-DD} */
72
- let topic;
73
- let requestId;
74
- let env;
75
- switch (context === null || context === void 0 ? void 0 : context.eventType) {
76
- case 'google.storage.object.finalize': {
71
+ let { topic, appId, env, requestId } = this.getMetadata(event, context);
72
+ if (!topic && ((_a = context === null || context === void 0 ? void 0 : context.resource) === null || _a === void 0 ? void 0 : _a.type) === 'storage#object') {
73
+ if ((context === null || context === void 0 ? void 0 : context.eventType) === 'google.storage.object.finalize') {
77
74
  const gsEvent = event;
78
- ({ topic, requestId, env } = (_a = gsEvent === null || gsEvent === void 0 ? void 0 : gsEvent.metadata) !== null && _a !== void 0 ? _a : {});
79
- if (!topic && ((_b = context === null || context === void 0 ? void 0 : context.resource) === null || _b === void 0 ? void 0 : _b.type) === 'storage#object') {
80
- const [meta] = yield exports.storage.bucket(gsEvent.bucket).file(gsEvent.name).getMetadata();
81
- ({ topic, requestId, env } = (_c = meta === null || meta === void 0 ? void 0 : meta.metadata) !== null && _c !== void 0 ? _c : {});
82
- }
83
- break;
84
- }
85
- case 'google.pubsub.topic.publish': {
86
- const psEvent = event;
87
- ({ topic, requestId, env } = (_d = psEvent === null || psEvent === void 0 ? void 0 : psEvent.attributes) !== null && _d !== void 0 ? _d : {});
88
- break;
75
+ const [meta] = yield exports.storage.bucket(gsEvent.bucket).file(gsEvent.name).getMetadata();
76
+ ({ topic, appId, env, requestId } = (_b = meta === null || meta === void 0 ? void 0 : meta.metadata) !== null && _b !== void 0 ? _b : {});
89
77
  }
90
78
  }
91
- return { topic, requestId, env };
79
+ return { topic, appId, env, requestId };
92
80
  });
93
81
  }
94
82
  static getOptions(event, context) {
95
- var _a, _b, _c, _d, _e, _f, _g;
83
+ var _a;
96
84
  return __awaiter(this, void 0, void 0, function* () {
97
- switch (context === null || context === void 0 ? void 0 : context.eventType) {
98
- case 'google.storage.object.finalize': {
85
+ let { options } = this.getMetadata(event, context);
86
+ if (!options) {
87
+ if ((context === null || context === void 0 ? void 0 : context.eventType) === 'google.storage.object.finalize') {
99
88
  const gsEvent = event;
100
- if ((_a = gsEvent === null || gsEvent === void 0 ? void 0 : gsEvent.metadata) === null || _a === void 0 ? void 0 : _a.options) {
101
- return JSON.parse((_c = (_b = gsEvent === null || gsEvent === void 0 ? void 0 : gsEvent.metadata) === null || _b === void 0 ? void 0 : _b.options) !== null && _c !== void 0 ? _c : '{}');
102
- }
103
- else {
104
- const file = exports.storage.bucket(gsEvent.bucket).file(gsEvent.name);
105
- const [meta] = yield file.getMetadata();
106
- 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 : '{}');
107
- }
108
- }
109
- case 'google.pubsub.topic.publish': {
110
- const psEvent = event;
111
- return JSON.parse((_g = (_f = psEvent === null || psEvent === void 0 ? void 0 : psEvent.attributes) === null || _f === void 0 ? void 0 : _f.options) !== null && _g !== void 0 ? _g : '{}');
89
+ const [meta] = yield exports.storage.bucket(gsEvent.bucket).file(gsEvent.name).getMetadata();
90
+ options = (_a = meta === null || meta === void 0 ? void 0 : meta.metadata) === null || _a === void 0 ? void 0 : _a.options;
112
91
  }
113
92
  }
93
+ return JSON.parse(options !== null && options !== void 0 ? options : '{}');
114
94
  });
115
95
  }
96
+ static getMetadata(event, context) {
97
+ let metadata;
98
+ switch (context === null || context === void 0 ? void 0 : context.eventType) {
99
+ case 'google.storage.object.finalize': {
100
+ const gsEvent = event;
101
+ metadata = gsEvent === null || gsEvent === void 0 ? void 0 : gsEvent.metadata;
102
+ break;
103
+ }
104
+ case 'google.pubsub.topic.publish': {
105
+ const psEvent = event;
106
+ metadata = psEvent === null || psEvent === void 0 ? void 0 : psEvent.attributes;
107
+ break;
108
+ }
109
+ }
110
+ return metadata !== null && metadata !== void 0 ? metadata : {};
111
+ }
116
112
  static getSecret(name, version) {
117
113
  var _a, _b;
118
114
  return __awaiter(this, void 0, void 0, function* () {
package/src/index.ts CHANGED
@@ -1,73 +1,13 @@
1
1
  import { PubSub } from '@google-cloud/pubsub';
2
- import fromPairs from 'lodash/fromPairs';
3
2
  import isEmpty from 'lodash/isEmpty';
4
3
  import noop from 'lodash/noop';
5
4
  import { timeoutAfter } from './utils';
6
- import { File, Storage } from '@google-cloud/storage';
5
+ import { Storage } from '@google-cloud/storage';
7
6
  import { SecretManagerServiceClient } from '@google-cloud/secret-manager';
7
+ import { TContext, TEvent, TGSEvent, TMetadata, TPSEvent, TResponse } from './types';
8
+ import { mapValues } from 'lodash';
8
9
  import Dict = NodeJS.Dict;
9
10
 
10
- export type TGSEvent = {
11
- bucket: string;
12
- contentType: string;
13
- crc32c: string;
14
- etag: string;
15
- generation: string;
16
- id: string;
17
- kind: string; // 'storage#object'
18
- md5Hash: string;
19
- mediaLink: string;
20
- metadata: {
21
- // [key: string]: string,
22
- topic: string;
23
- requestId: string;
24
- env: string;
25
- options?: any;
26
- };
27
- metageneration: string;
28
- name: string;
29
- selfLink: string;
30
- size: string;
31
- storageClass: string;
32
- timeCreated: string;
33
- timeStorageClassUpdated: string;
34
- updated: string;
35
- };
36
-
37
- export type TPSEvent = {
38
- '@type': string; // 'type.googleapis.com/google.pubsub.v1.PubsubMessage'
39
- attributes?: {
40
- // [k: string]: string,
41
- topic: string;
42
- requestId: string;
43
- env: string;
44
- options?: any;
45
- };
46
- data?: string | Dict<any>;
47
- };
48
-
49
- export type TEvent = TGSEvent | TPSEvent;
50
-
51
- export type TContext = {
52
- eventId: string;
53
- timestamp: string;
54
- eventType: 'google.storage.object.finalize' | 'google.pubsub.topic.publish';
55
- resource: {
56
- service: 'storage.googleapis.com' | 'pubsub.googleapis.com';
57
- type: 'storage#object' | 'type.googleapis.com/google.pubsub.v1.PubsubMessage';
58
- name: string;
59
- };
60
- };
61
-
62
- export type TResponse = {
63
- [prop: string]: any;
64
- error?: {
65
- name: string;
66
- message: string;
67
- stack?: string;
68
- };
69
- };
70
-
71
11
  export const pubSub = new PubSub();
72
12
  export const storage = new Storage();
73
13
  export const secretClient = new SecretManagerServiceClient();
@@ -106,16 +46,17 @@ export class GcfCommon {
106
46
  }
107
47
 
108
48
  static async publish(event: TEvent, context: TContext, json?: TResponse, attributes?: Dict<any>) {
109
- const { topic, requestId, env } = await this.getTopic(event, context);
110
- console.log('publish:', topic, env, json, attributes);
49
+ const { topic, appId, env, requestId } = await this.getTopic(event, context);
111
50
 
112
51
  if (!isEmpty(topic)) {
52
+ console.log('publish:', topic, appId, env, json, attributes);
113
53
  return pubSub.topic(topic as string).publishMessage({
114
54
  json: json ?? {},
115
55
  attributes: {
116
- ...fromPairs(Object.entries(attributes ?? {}).map(([k, v]) => [k, '' + v])),
117
- env: env ?? '',
56
+ ...mapValues(attributes ?? {}, (v) => '' + v),
118
57
  requestId: requestId ?? '',
58
+ appId: appId ?? '',
59
+ env: env ?? '',
119
60
  type: 'response',
120
61
  response: '1',
121
62
  },
@@ -124,48 +65,50 @@ export class GcfCommon {
124
65
  }
125
66
 
126
67
  static async getTopic(event: TEvent, context: TContext) {
127
- /** t_{GUID}__{YYYY-MM-DD} */
128
- let topic: string | undefined;
129
- let requestId: string | undefined;
130
- let env: string | undefined;
68
+ let { topic, appId, env, requestId } = this.getMetadata(event, context);
131
69
 
132
- switch (context?.eventType) {
133
- case 'google.storage.object.finalize': {
70
+ if (!topic && context?.resource?.type === 'storage#object') {
71
+ if (context?.eventType === 'google.storage.object.finalize') {
134
72
  const gsEvent = event as TGSEvent;
135
- ({ topic, requestId, env } = gsEvent?.metadata ?? {});
136
- if (!topic && context?.resource?.type === 'storage#object') {
137
- const [meta] = await storage.bucket(gsEvent.bucket).file(gsEvent.name).getMetadata();
138
- ({ topic, requestId, env } = meta?.metadata ?? {});
139
- }
140
- break;
141
- }
142
- case 'google.pubsub.topic.publish': {
143
- const psEvent = event as TPSEvent;
144
- ({ topic, requestId, env } = psEvent?.attributes ?? ({} as any));
145
- break;
73
+ const [meta] = await storage.bucket(gsEvent.bucket).file(gsEvent.name).getMetadata();
74
+ ({ topic, appId, env, requestId } = meta?.metadata ?? {});
146
75
  }
147
76
  }
148
77
 
149
- return { topic, requestId, env };
78
+ return { topic, appId, env, requestId };
150
79
  }
151
80
 
152
81
  static async getOptions(event: TEvent, context: TContext): Promise<Dict<any>> {
82
+ let { options } = this.getMetadata(event, context);
83
+
84
+ if (!options) {
85
+ if (context?.eventType === 'google.storage.object.finalize') {
86
+ const gsEvent = event as TGSEvent;
87
+ const [meta] = await storage.bucket(gsEvent.bucket).file(gsEvent.name).getMetadata();
88
+ options = meta?.metadata?.options;
89
+ }
90
+ }
91
+
92
+ return JSON.parse(options ?? '{}');
93
+ }
94
+
95
+ static getMetadata(event: TEvent, context: TContext) {
96
+ let metadata: TMetadata | undefined;
97
+
153
98
  switch (context?.eventType) {
154
99
  case 'google.storage.object.finalize': {
155
100
  const gsEvent = event as TGSEvent;
156
- if (gsEvent?.metadata?.options) {
157
- return JSON.parse(gsEvent?.metadata?.options ?? '{}');
158
- } else {
159
- const file: File = storage.bucket(gsEvent.bucket).file(gsEvent.name);
160
- const [meta] = await file.getMetadata();
161
- return JSON.parse(meta?.metadata?.options ?? '{}');
162
- }
101
+ metadata = gsEvent?.metadata;
102
+ break;
163
103
  }
164
104
  case 'google.pubsub.topic.publish': {
165
105
  const psEvent = event as TPSEvent;
166
- return JSON.parse(psEvent?.attributes?.options ?? '{}');
106
+ metadata = psEvent?.attributes;
107
+ break;
167
108
  }
168
109
  }
110
+
111
+ return metadata ?? {};
169
112
  }
170
113
 
171
114
  static async getSecret(name: string, version?: string) {
package/src/types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/src/types.ts ADDED
@@ -0,0 +1,58 @@
1
+ import Dict = NodeJS.Dict;
2
+
3
+ export type TMetadata = {
4
+ topic?: string; // response topic [t_{GUID}__{YYYY-MM-DD}]
5
+ requestId?: string; // for rpc response [GUID]
6
+ env?: string; // app environment
7
+ appId?: string; // app id
8
+ options?: string;
9
+ }
10
+
11
+ export type TGSEvent = {
12
+ bucket: string;
13
+ contentType: string;
14
+ crc32c: string;
15
+ etag: string;
16
+ generation: string;
17
+ id: string;
18
+ kind: string; // 'storage#object'
19
+ md5Hash: string;
20
+ mediaLink: string;
21
+ metadata: TMetadata;
22
+ metageneration: string;
23
+ name: string;
24
+ selfLink: string;
25
+ size: string;
26
+ storageClass: string;
27
+ timeCreated: string;
28
+ timeStorageClassUpdated: string;
29
+ updated: string;
30
+ };
31
+
32
+ export type TPSEvent = {
33
+ '@type': string; // 'type.googleapis.com/google.pubsub.v1.PubsubMessage'
34
+ attributes?: TMetadata;
35
+ data?: string | Dict<any>;
36
+ };
37
+
38
+ export type TEvent = TGSEvent | TPSEvent;
39
+
40
+ export type TContext = {
41
+ eventId: string;
42
+ timestamp: string;
43
+ eventType: 'google.storage.object.finalize' | 'google.pubsub.topic.publish';
44
+ resource: {
45
+ service: 'storage.googleapis.com' | 'pubsub.googleapis.com';
46
+ type: 'storage#object' | 'type.googleapis.com/google.pubsub.v1.PubsubMessage';
47
+ name: string;
48
+ };
49
+ };
50
+
51
+ export type TResponse = {
52
+ [prop: string]: any;
53
+ error?: {
54
+ name: string;
55
+ message: string;
56
+ stack?: string;
57
+ };
58
+ };
package/src/utils.js CHANGED
@@ -9,21 +9,27 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.A1ToColNum = exports.colNumToA1 = exports.A1ToIndex = exports.indexToA1 = exports.timeoutAfter = void 0;
12
+ exports.A1ToColNum = exports.colNumToA1 = exports.A1ToIndex = exports.indexToA1 = exports.delay = exports.timeoutAfter = void 0;
13
13
  /**
14
14
  *
15
- * @param seconds Google function timeout limit (max: 9 min)
15
+ * @param seconds Google function v1 timeout limit (max: 9 min)
16
16
  */
17
17
  function timeoutAfter(seconds = 540) {
18
18
  return __awaiter(this, void 0, void 0, function* () {
19
19
  return new Promise((resolve, reject) => {
20
- setTimeout(() => {
21
- reject(new Error(`${seconds} seconds timeout exceeded`));
22
- }, seconds * 1000);
20
+ setTimeout(() => reject(new Error(`${seconds} seconds timeout exceeded`)), seconds * 1000);
23
21
  });
24
22
  });
25
23
  }
26
24
  exports.timeoutAfter = timeoutAfter;
25
+ function delay(seconds) {
26
+ return __awaiter(this, void 0, void 0, function* () {
27
+ return new Promise((resolve, reject) => {
28
+ setTimeout(() => resolve(undefined), seconds * 1000);
29
+ });
30
+ });
31
+ }
32
+ exports.delay = delay;
27
33
  //
28
34
  function indexToA1(idx) {
29
35
  return colNumToA1(idx + 1);
package/src/utils.ts CHANGED
@@ -1,12 +1,16 @@
1
1
  /**
2
2
  *
3
- * @param seconds Google function timeout limit (max: 9 min)
3
+ * @param seconds Google function v1 timeout limit (max: 9 min)
4
4
  */
5
5
  export async function timeoutAfter(seconds: number = 540) {
6
6
  return new Promise<undefined>((resolve, reject) => {
7
- setTimeout(() => {
8
- reject(new Error(`${seconds} seconds timeout exceeded`));
9
- }, seconds * 1000);
7
+ setTimeout(() => reject(new Error(`${seconds} seconds timeout exceeded`)), seconds * 1000);
8
+ });
9
+ }
10
+
11
+ export async function delay(seconds: number) {
12
+ return new Promise<undefined>((resolve, reject) => {
13
+ setTimeout(() => resolve(undefined), seconds * 1000);
10
14
  });
11
15
  }
12
16