gcf-common-lib 0.7.0 → 0.9.2

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 CHANGED
@@ -8,225 +8,93 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
- var __generator = (this && this.__generator) || function (thisArg, body) {
12
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
- function verb(n) { return function (v) { return step([n, v]); }; }
15
- function step(op) {
16
- if (f) throw new TypeError("Generator is already executing.");
17
- while (_) try {
18
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
- if (y = 0, t) op = [op[0] & 2, t.value];
20
- switch (op[0]) {
21
- case 0: case 1: t = op; break;
22
- case 4: _.label++; return { value: op[1], done: false };
23
- case 5: _.label++; y = op[1]; op = [0]; continue;
24
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
- default:
26
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
- if (t[2]) _.ops.pop();
31
- _.trys.pop(); continue;
32
- }
33
- op = body.call(thisArg, _);
34
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
- }
37
- };
38
11
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.GcfCommon = void 0;
40
- var storage_1 = require("@google-cloud/storage");
41
- var pubsub_1 = require("@google-cloud/pubsub");
42
- var lodash_1 = require("lodash");
43
- var GcfCommon = /** @class */ (function () {
44
- function GcfCommon() {
45
- }
46
- /**
47
- *
48
- * @param {!Object} event Event payload.
49
- * @param {!Object} context Metadata for the event.
50
- * @param handler
51
- * @param timeout Seconds
52
- */
53
- GcfCommon.process = function (event, context, handler, timeout) {
54
- if (timeout === void 0) { timeout = 535; }
55
- return __awaiter(this, void 0, void 0, function () {
56
- var _this = this;
57
- return __generator(this, function (_a) {
58
- return [2 /*return*/, Promise.race([
59
- this.delay(535),
60
- handler(event, context),
61
- ])
62
- .then(function (res) { return __awaiter(_this, void 0, void 0, function () {
63
- return __generator(this, function (_a) {
64
- switch (_a.label) {
65
- case 0:
66
- // console.log('res:', res);
67
- return [4 /*yield*/, this.publish(event, context, res !== null && res !== void 0 ? res : {})];
68
- case 1:
69
- // console.log('res:', res);
70
- _a.sent();
71
- return [2 /*return*/];
72
- }
73
- });
74
- }); })
75
- .catch(function (err) { return __awaiter(_this, void 0, void 0, function () {
76
- var fname, dataJSON;
77
- var _a, _b;
78
- return __generator(this, function (_c) {
79
- switch (_c.label) {
80
- case 0:
81
- 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';
82
- dataJSON = { error: { name: err.name, message: "GCF [" + fname + "]: " + err.message, stack: err.stack } };
83
- return [4 /*yield*/, this.publish(event, context, dataJSON).catch(lodash_1.noop)];
84
- case 1:
85
- _c.sent();
86
- throw err;
87
- }
88
- });
89
- }); })];
90
- });
12
+ exports.GcfCommon = exports.storage = exports.pubSub = void 0;
13
+ const pubsub_1 = require("@google-cloud/pubsub");
14
+ const secret_manager_1 = require("@google-cloud/secret-manager");
15
+ const storage_1 = require("@google-cloud/storage");
16
+ const lodash_1 = require("lodash");
17
+ const utils_1 = require("./utils");
18
+ exports.pubSub = new pubsub_1.PubSub();
19
+ exports.storage = new storage_1.Storage();
20
+ const secretClient = new secret_manager_1.SecretManagerServiceClient();
21
+ class GcfCommon {
22
+ static process(event, context, handler, timeout = 535) {
23
+ return __awaiter(this, void 0, void 0, function* () {
24
+ return Promise.race([
25
+ (0, utils_1.timeoutAfter)(timeout),
26
+ handler(event, context),
27
+ ])
28
+ .then((res) => __awaiter(this, void 0, void 0, function* () {
29
+ yield this.publish(event, context, res !== null && res !== void 0 ? res : {});
30
+ }))
31
+ .catch((err) => __awaiter(this, void 0, void 0, function* () {
32
+ var _a, _b;
33
+ 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';
34
+ const response = {
35
+ error: {
36
+ name: err.name,
37
+ message: `GCF [${fname}]: ${err.message}`,
38
+ stack: err.stack,
39
+ },
40
+ };
41
+ yield this.publish(event, context, response).catch(lodash_1.noop);
42
+ throw err;
43
+ }));
91
44
  });
92
- };
93
- /**
94
- *
95
- * @param {!Object} event Event payload.
96
- * @param {!Object} context Metadata for the event.
97
- * @param json
98
- */
99
- GcfCommon.publish = function (event, context, json) {
100
- return __awaiter(this, void 0, void 0, function () {
101
- var topic;
102
- return __generator(this, function (_a) {
103
- switch (_a.label) {
104
- case 0: return [4 /*yield*/, this.getTopic(event, context)];
105
- case 1:
106
- topic = _a.sent();
107
- console.log('publish:', topic === null || topic === void 0 ? void 0 : topic.name, json);
108
- if (!topic) return [3 /*break*/, 3];
109
- return [4 /*yield*/, topic.publishMessage({ json: json })];
110
- case 2: return [2 /*return*/, _a.sent()];
111
- case 3: return [2 /*return*/];
112
- }
113
- });
45
+ }
46
+ static publish(event, context, json) {
47
+ return __awaiter(this, void 0, void 0, function* () {
48
+ const topic = yield this.getTopic(event, context);
49
+ console.log('publish:', topic === null || topic === void 0 ? void 0 : topic.name, json);
50
+ if (topic)
51
+ return yield topic.publishMessage({ json });
114
52
  });
115
- };
116
- /**
117
- *
118
- * @param {!Object} event Event payload.
119
- * @param {!Object} context Metadata for the event.
120
- */
121
- GcfCommon.getTopic = function (event, context) {
53
+ }
54
+ static getTopic(event, context) {
122
55
  var _a, _b, _c;
123
- return __awaiter(this, void 0, void 0, function () {
124
- var pubSub, topicName, storage, file, meta, topic;
125
- return __generator(this, function (_d) {
126
- switch (_d.label) {
127
- case 0:
128
- pubSub = new pubsub_1.PubSub();
129
- topicName = (_a = event === null || event === void 0 ? void 0 : event.metadata) === null || _a === void 0 ? void 0 : _a.topic;
130
- if (!(!topicName && ((_b = context === null || context === void 0 ? void 0 : context.resource) === null || _b === void 0 ? void 0 : _b.type) === 'storage#object')) return [3 /*break*/, 2];
131
- storage = new storage_1.Storage();
132
- file = storage.bucket(event.bucket).file(event.name);
133
- return [4 /*yield*/, file.getMetadata()];
134
- case 1:
135
- meta = (_d.sent())[0];
136
- topicName = (_c = meta === null || meta === void 0 ? void 0 : meta.metadata) === null || _c === void 0 ? void 0 : _c.topic;
137
- console.log('topic:', topicName);
138
- _d.label = 2;
139
- case 2:
140
- if (!!(0, lodash_1.isEmpty)(topicName)) return [3 /*break*/, 4];
141
- topic = pubSub.topic(topicName);
142
- return [4 /*yield*/, topic.setMetadata({ labels: { date: topicName.split('__')[1] } })];
143
- case 3:
144
- _d.sent();
145
- return [2 /*return*/, topic];
146
- case 4: return [2 /*return*/];
147
- }
148
- });
56
+ return __awaiter(this, void 0, void 0, function* () {
57
+ let topicName = (_a = event === null || event === void 0 ? void 0 : event.metadata) === null || _a === void 0 ? void 0 : _a.topic;
58
+ if (!topicName && ((_b = context === null || context === void 0 ? void 0 : context.resource) === null || _b === void 0 ? void 0 : _b.type) === 'storage#object') {
59
+ const file = exports.storage.bucket(event.bucket).file(event.name);
60
+ const [meta] = yield file.getMetadata();
61
+ topicName = (_c = meta === null || meta === void 0 ? void 0 : meta.metadata) === null || _c === void 0 ? void 0 : _c.topic;
62
+ console.log('topic:', topicName);
63
+ }
64
+ if (topicName && !(0, lodash_1.isEmpty)(topicName)) {
65
+ const topic = exports.pubSub.topic(topicName);
66
+ yield topic.setMetadata({ labels: { date: topicName.split('__')[1] } });
67
+ return topic;
68
+ }
149
69
  });
150
- };
151
- /**
152
- *
153
- * @param {!Object} event Event payload.
154
- * @param {!Object} context Metadata for the event.
155
- */
156
- GcfCommon.getOptions = function (event, context) {
70
+ }
71
+ static getOptions(event, context) {
157
72
  var _a, _b, _c, _d, _e;
158
- return __awaiter(this, void 0, void 0, function () {
159
- var storage, file, meta;
160
- return __generator(this, function (_f) {
161
- switch (_f.label) {
162
- case 0:
163
- if (!((_a = event === null || event === void 0 ? void 0 : event.metadata) === null || _a === void 0 ? void 0 : _a.options)) return [3 /*break*/, 1];
164
- return [2 /*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 : '{}')];
165
- case 1:
166
- storage = new storage_1.Storage();
167
- file = storage.bucket(event.bucket).file(event.name);
168
- return [4 /*yield*/, file.getMetadata()];
169
- case 2:
170
- meta = (_f.sent())[0];
171
- return [2 /*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 : '{}')];
172
- }
173
- });
174
- });
175
- };
176
- /**
177
- *
178
- * @param s Google function time limit (max: 9 min)
179
- */
180
- GcfCommon.delay = function (s) {
181
- if (s === void 0) { s = 540; }
182
- return __awaiter(this, void 0, void 0, function () {
183
- return __generator(this, function (_a) {
184
- return [2 /*return*/, new Promise(function (resolve, reject) {
185
- setTimeout(function () {
186
- reject(new Error(s + " seconds timeout exceeded"));
187
- }, s * 1000);
188
- })];
189
- });
190
- });
191
- };
192
- //
193
- GcfCommon.indexToA1 = function (idx) {
194
- return this.colNumToA1(idx + 1);
195
- };
196
- GcfCommon.colNumToA1 = function (columnNumber) {
197
- var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
198
- // To store result (Excel column name)
199
- var charIdxArr = [];
200
- while (columnNumber > 0) {
201
- // Find remainder
202
- var rem = columnNumber % chars.length;
203
- // If remainder is 0, then a
204
- // 'Z' must be there in output
205
- if (rem === 0) {
206
- charIdxArr.push(chars.length - 1);
207
- columnNumber = Math.floor(columnNumber / chars.length) - 1;
73
+ return __awaiter(this, void 0, void 0, function* () {
74
+ if ((_a = event === null || event === void 0 ? void 0 : event.metadata) === null || _a === void 0 ? void 0 : _a.options) {
75
+ 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 : '{}');
208
76
  }
209
- else { // If remainder is non-zero
210
- charIdxArr.push(rem - 1);
211
- columnNumber = Math.floor(columnNumber / chars.length);
77
+ else {
78
+ const file = exports.storage.bucket(event.bucket).file(event.name);
79
+ const [meta] = yield file.getMetadata();
80
+ 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 : '{}');
212
81
  }
213
- }
214
- // Reverse the string and print result
215
- return charIdxArr.reverse().map(function (n) { return chars[n]; }).join('');
216
- };
217
- GcfCommon.A1ToIndex = function (value) {
218
- return this.A1ToColNum(value) - 1;
219
- };
220
- GcfCommon.A1ToColNum = function (value) {
221
- var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
222
- var result = 0;
223
- // tslint:disable-next-line:prefer-for-of
224
- for (var i = 0; i < value.length; i++) {
225
- result *= chars.length;
226
- result += chars.indexOf(value[i]) + 1;
227
- }
228
- return result;
229
- };
230
- return GcfCommon;
231
- }());
82
+ });
83
+ }
84
+ static getSecret(name, version) {
85
+ var _a, _b;
86
+ return __awaiter(this, void 0, void 0, function* () {
87
+ const projectId = yield secretClient.getProjectId();
88
+ const secretName = `projects/${projectId}/secrets/${name}`;
89
+ const secretVersion = `${secretName}/versions/${version !== null && version !== void 0 ? version : 'latest'}`;
90
+ const [response] = yield secretClient.accessSecretVersion({ name: secretVersion });
91
+ 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();
92
+ });
93
+ }
94
+ static getSecrets(names, versions) {
95
+ return __awaiter(this, void 0, void 0, function* () {
96
+ 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]); })));
97
+ });
98
+ }
99
+ }
232
100
  exports.GcfCommon = GcfCommon;
package/index.ts CHANGED
@@ -1,19 +1,70 @@
1
- import {File, Storage} from '@google-cloud/storage';
2
- import {PubSub, Topic} from '@google-cloud/pubsub';
1
+ import {PubSub} from "@google-cloud/pubsub";
2
+ import {SecretManagerServiceClient} from "@google-cloud/secret-manager";
3
+ import {File, Storage} from "@google-cloud/storage";
3
4
  import {isEmpty, noop} from 'lodash';
5
+ import {timeoutAfter} from "./utils";
6
+
7
+ export type TEvent = {
8
+ bucket: string;
9
+ contentType: string;
10
+ crc32c: string;
11
+ etag: string;
12
+ generation: string;
13
+ id: string;
14
+ kind: string; // 'storage#object'
15
+ md5Hash: string;
16
+ mediaLink: string;
17
+ metadata: { [key: string]: string, topic: string, options?: any };
18
+ metageneration: string;
19
+ name: string;
20
+ selfLink: string;
21
+ size: string;
22
+ storageClass: string;
23
+ timeCreated: string;
24
+ timeStorageClassUpdated: string;
25
+ updated: string;
26
+ }
27
+
28
+ export type TContext = {
29
+ eventId: string;
30
+ timestamp: string;
31
+ eventType: string; // 'google.storage.object.finalize'
32
+ resource: {
33
+ service: string; // 'storage.googleapis.com'
34
+ name: string;
35
+ type: string; // 'storage#object'
36
+ }
37
+ }
38
+
39
+ export type TResponse = {
40
+ error?: {
41
+ name: string,
42
+ message: string,
43
+ stack?: string,
44
+ }
45
+ }
46
+
47
+ export const pubSub = new PubSub();
48
+ export const storage = new Storage();
49
+ const secretClient = new SecretManagerServiceClient();
4
50
 
5
51
  export class GcfCommon {
6
52
 
7
53
  /**
8
54
  *
9
- * @param {!Object} event Event payload.
10
- * @param {!Object} context Metadata for the event.
55
+ * @param {!TEvent} event Event payload.
56
+ * @param {!TContext} context Metadata for the event.
11
57
  * @param handler
12
58
  * @param timeout Seconds
13
59
  */
14
- static async process(event, context, handler: (event, context) => Promise<any>, timeout = 535) {
60
+ static async process<T>(
61
+ event: TEvent,
62
+ context: TContext,
63
+ handler: (event: TEvent, context: TContext) => Promise<T>,
64
+ timeout = 535,
65
+ ) {
15
66
  return Promise.race([
16
- this.delay(535),
67
+ timeoutAfter(timeout),
17
68
  handler(event, context),
18
69
  ])
19
70
  .then(async (res: any) => {
@@ -22,122 +73,63 @@ export class GcfCommon {
22
73
  })
23
74
  .catch(async (err: Error) => {
24
75
  const fname = process?.env?.K_SERVICE ?? 'UNKNOWN';
25
- const dataJSON = {error: {name: err.name, message: `GCF [${fname}]: ${err.message}`, stack: err.stack}};
26
- await this.publish(event, context, dataJSON).catch(noop);
76
+ const response: TResponse = {
77
+ error: {
78
+ name: err.name,
79
+ message: `GCF [${fname}]: ${err.message}`,
80
+ stack: err.stack,
81
+ },
82
+ };
83
+ await this.publish(event, context, response).catch(noop);
27
84
  throw err;
28
85
  })
29
86
  ;
30
87
  }
31
88
 
32
- /**
33
- *
34
- * @param {!Object} event Event payload.
35
- * @param {!Object} context Metadata for the event.
36
- * @param json
37
- */
38
- static async publish(event, context, json) {
89
+ static async publish(event: TEvent, context: TContext, json: TResponse) {
39
90
  const topic = await this.getTopic(event, context);
40
91
  console.log('publish:', topic?.name, json);
41
92
  if (topic) return await topic.publishMessage({json});
42
93
  }
43
94
 
44
- /**
45
- *
46
- * @param {!Object} event Event payload.
47
- * @param {!Object} context Metadata for the event.
48
- */
49
- static async getTopic(event, context): Promise<Topic | undefined> {
50
- const pubSub = new PubSub();
95
+ static async getTopic(event: TEvent, context: TContext) {
51
96
 
52
97
  /** t_{GUID}__{YYYY-MM-DD} */
53
98
  let topicName: string | undefined = event?.metadata?.topic;
54
99
 
55
100
  if (!topicName && context?.resource?.type === 'storage#object') {
56
- const storage = new Storage();
57
101
  const file: File = storage.bucket(event.bucket).file(event.name);
58
102
  const [meta] = await file.getMetadata();
59
103
  topicName = meta?.metadata?.topic;
60
104
  console.log('topic:', topicName);
61
105
  }
62
106
 
63
- if (!isEmpty(topicName)) {
107
+ if (topicName && !isEmpty(topicName)) {
64
108
  const topic = pubSub.topic(topicName);
65
109
  await topic.setMetadata({labels: {date: topicName.split('__')[1]}});
66
110
  return topic;
67
111
  }
68
112
  }
69
113
 
70
- /**
71
- *
72
- * @param {!Object} event Event payload.
73
- * @param {!Object} context Metadata for the event.
74
- */
75
- static async getOptions(event, context) {
114
+ static async getOptions(event: TEvent, context: TContext) {
76
115
  if (event?.metadata?.options) {
77
116
  return JSON.parse(event?.metadata?.options ?? '{}');
78
117
  } else {
79
- const storage = new Storage();
80
118
  const file: File = storage.bucket(event.bucket).file(event.name);
81
119
  const [meta] = await file.getMetadata();
82
120
  return JSON.parse(meta?.metadata?.options ?? '{}');
83
121
  }
84
122
  }
85
123
 
86
- /**
87
- *
88
- * @param s Google function time limit (max: 9 min)
89
- */
90
- static async delay(s: number = 540) {
91
- return new Promise<undefined>((resolve, reject) => {
92
- setTimeout(() => {
93
- reject(new Error(`${s} seconds timeout exceeded`));
94
- }, s * 1000);
95
- });
96
- }
97
-
98
- //
99
-
100
- static indexToA1(idx: number) {
101
- return this.colNumToA1(idx + 1);
102
- }
103
-
104
- static colNumToA1(columnNumber: number) {
105
- const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
106
-
107
- // To store result (Excel column name)
108
- const charIdxArr: number[] = [];
109
-
110
- while (columnNumber > 0) {
111
- // Find remainder
112
- const rem = columnNumber % chars.length;
113
-
114
- // If remainder is 0, then a
115
- // 'Z' must be there in output
116
- if (rem === 0) {
117
- charIdxArr.push(chars.length - 1);
118
- columnNumber = Math.floor(columnNumber / chars.length) - 1;
119
- } else { // If remainder is non-zero
120
- charIdxArr.push(rem - 1);
121
- columnNumber = Math.floor(columnNumber / chars.length);
122
- }
123
- }
124
-
125
- // Reverse the string and print result
126
- return charIdxArr.reverse().map((n) => chars[n]).join('');
127
- }
128
-
129
- static A1ToIndex(value: string) {
130
- return this.A1ToColNum(value) - 1;
124
+ static async getSecret(name: string, version?: string) {
125
+ const projectId = await secretClient.getProjectId();
126
+ const secretName = `projects/${projectId}/secrets/${name}`;
127
+ const secretVersion = `${secretName}/versions/${version ?? 'latest'}`;
128
+ const [response] = await secretClient.accessSecretVersion({name: secretVersion});
129
+ return response?.payload?.data?.toString();
131
130
  }
132
131
 
133
- static A1ToColNum(value: string) {
134
- const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
135
- let result = 0;
136
- // tslint:disable-next-line:prefer-for-of
137
- for (let i = 0; i < value.length; i++) {
138
- result *= chars.length;
139
- result += chars.indexOf(value[i]) + 1;
140
- }
141
- return result;
132
+ static async getSecrets(names: string[], versions?: string[]) {
133
+ return Promise.all(names.map(async (name, idx) => this.getSecret(name, versions?.[idx])));
142
134
  }
143
135
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "gcf-common-lib",
3
3
  "description": "",
4
- "version": "0.7.0",
4
+ "version": "0.9.2",
5
5
  "publishConfig": {
6
6
  "access": "public",
7
7
  "branches": [
@@ -18,10 +18,12 @@
18
18
  },
19
19
  "dependencies": {
20
20
  "@google-cloud/pubsub": "^2.18.4",
21
+ "@google-cloud/secret-manager": "^3.10.1",
21
22
  "@google-cloud/storage": "^5.17.0",
22
23
  "lodash": "^4.17.21"
23
24
  },
24
25
  "devDependencies": {
26
+ "@tsconfig/node14": "^1.0.1",
25
27
  "@types/lodash": "^4.14.178"
26
28
  },
27
29
  "keywords": [],
package/tsconfig.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "$schema": "http://json.schemastore.org/tsconfig",
3
+ "extends": "@tsconfig/node14/tsconfig.json",
4
+ "compilerOptions": {
5
+ "allowJs": false,
6
+ "removeComments": true,
7
+ "esModuleInterop": true,
8
+ "allowSyntheticDefaultImports": true,
9
+ "isolatedModules": false,
10
+ "emitDecoratorMetadata": true,
11
+ "experimentalDecorators": true,
12
+ "module": "commonjs",
13
+ "moduleResolution": "node",
14
+ "target": "ES6",
15
+ "typeRoots": [
16
+ "node_modules/@types"
17
+ ],
18
+ "lib": [
19
+ "ES2018",
20
+ "ES2019",
21
+ "ES2020",
22
+ "ES2021",
23
+ "ESNext"
24
+ ],
25
+ "types": [],
26
+ "plugins": []
27
+ },
28
+ "exclude": [
29
+ "node_modules/**",
30
+ "**/*.d.ts"
31
+ ]
32
+ }
package/utils.js ADDED
@@ -0,0 +1,57 @@
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
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.A1ToColNum = exports.A1ToIndex = exports.colNumToA1 = exports.indexToA1 = exports.timeoutAfter = void 0;
13
+ function timeoutAfter(seconds = 540) {
14
+ return __awaiter(this, void 0, void 0, function* () {
15
+ return new Promise((resolve, reject) => {
16
+ setTimeout(() => {
17
+ reject(new Error(`${seconds} seconds timeout exceeded`));
18
+ }, seconds * 1000);
19
+ });
20
+ });
21
+ }
22
+ exports.timeoutAfter = timeoutAfter;
23
+ function indexToA1(idx) {
24
+ return colNumToA1(idx + 1);
25
+ }
26
+ exports.indexToA1 = indexToA1;
27
+ function colNumToA1(columnNumber) {
28
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
29
+ const charIdxArr = [];
30
+ while (columnNumber > 0) {
31
+ const rem = columnNumber % chars.length;
32
+ if (rem === 0) {
33
+ charIdxArr.push(chars.length - 1);
34
+ columnNumber = Math.floor(columnNumber / chars.length) - 1;
35
+ }
36
+ else {
37
+ charIdxArr.push(rem - 1);
38
+ columnNumber = Math.floor(columnNumber / chars.length);
39
+ }
40
+ }
41
+ return charIdxArr.reverse().map((n) => chars[n]).join('');
42
+ }
43
+ exports.colNumToA1 = colNumToA1;
44
+ function A1ToIndex(value) {
45
+ return A1ToColNum(value) - 1;
46
+ }
47
+ exports.A1ToIndex = A1ToIndex;
48
+ function A1ToColNum(value) {
49
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
50
+ let result = 0;
51
+ for (let i = 0; i < value.length; i++) {
52
+ result *= chars.length;
53
+ result += chars.indexOf(value[i]) + 1;
54
+ }
55
+ return result;
56
+ }
57
+ exports.A1ToColNum = A1ToColNum;
package/utils.ts ADDED
@@ -0,0 +1,57 @@
1
+ /**
2
+ *
3
+ * @param seconds Google function timeout limit (max: 9 min)
4
+ */
5
+ export async function timeoutAfter(seconds: number = 540) {
6
+ return new Promise<undefined>((resolve, reject) => {
7
+ setTimeout(() => {
8
+ reject(new Error(`${seconds} seconds timeout exceeded`));
9
+ }, seconds * 1000);
10
+ });
11
+ }
12
+
13
+ //
14
+
15
+ export function indexToA1(idx: number) {
16
+ return colNumToA1(idx + 1);
17
+ }
18
+
19
+ export function colNumToA1(columnNumber: number) {
20
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
21
+
22
+ // To store result (Excel column name)
23
+ const charIdxArr: number[] = [];
24
+
25
+ while (columnNumber > 0) {
26
+ // Find remainder
27
+ const rem = columnNumber % chars.length;
28
+
29
+ // If remainder is 0, then a
30
+ // 'Z' must be there in output
31
+ if (rem === 0) {
32
+ charIdxArr.push(chars.length - 1);
33
+ columnNumber = Math.floor(columnNumber / chars.length) - 1;
34
+ } else { // If remainder is non-zero
35
+ charIdxArr.push(rem - 1);
36
+ columnNumber = Math.floor(columnNumber / chars.length);
37
+ }
38
+ }
39
+
40
+ // Reverse the string and print result
41
+ return charIdxArr.reverse().map((n) => chars[n]).join('');
42
+ }
43
+
44
+ export function A1ToIndex(value: string) {
45
+ return A1ToColNum(value) - 1;
46
+ }
47
+
48
+ export function A1ToColNum(value: string) {
49
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
50
+ let result = 0;
51
+ // tslint:disable-next-line:prefer-for-of
52
+ for (let i = 0; i < value.length; i++) {
53
+ result *= chars.length;
54
+ result += chars.indexOf(value[i]) + 1;
55
+ }
56
+ return result;
57
+ }