service-call-library-dev 0.1.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/dist/index.cjs +1122 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +92 -0
- package/dist/index.d.ts +92 -0
- package/dist/index.js +1094 -0
- package/dist/index.js.map +1 -0
- package/package.json +45 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1094 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __esm = (fn, res) => function __init() {
|
|
5
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
6
|
+
};
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
12
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
13
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
14
|
+
if (decorator = decorators[i])
|
|
15
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
16
|
+
if (kind && result) __defProp(target, key, result);
|
|
17
|
+
return result;
|
|
18
|
+
};
|
|
19
|
+
var __decorateParam = (index, decorator) => (target, key) => decorator(target, key, index);
|
|
20
|
+
|
|
21
|
+
// src/logging/logger.service.ts
|
|
22
|
+
import winston from "winston";
|
|
23
|
+
var LoggerService;
|
|
24
|
+
var init_logger_service = __esm({
|
|
25
|
+
"src/logging/logger.service.ts"() {
|
|
26
|
+
"use strict";
|
|
27
|
+
LoggerService = class {
|
|
28
|
+
static {
|
|
29
|
+
this.logger = winston.createLogger({
|
|
30
|
+
level: process.env.LOG_LEVEL ?? "info",
|
|
31
|
+
format: winston.format.combine(
|
|
32
|
+
winston.format.timestamp(),
|
|
33
|
+
winston.format.errors({ stack: true }),
|
|
34
|
+
winston.format.json()
|
|
35
|
+
),
|
|
36
|
+
transports: [new winston.transports.Console()]
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
static info(message, meta) {
|
|
40
|
+
this.logger.info(message, meta);
|
|
41
|
+
}
|
|
42
|
+
static error(message, meta) {
|
|
43
|
+
this.logger.error(message, meta);
|
|
44
|
+
}
|
|
45
|
+
static warn(message, meta) {
|
|
46
|
+
this.logger.warn(message, meta);
|
|
47
|
+
}
|
|
48
|
+
static debug(message, meta) {
|
|
49
|
+
this.logger.debug(message, meta);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// src/utils/zookeeperConfig.ts
|
|
56
|
+
var getZooKeeperConfig;
|
|
57
|
+
var init_zookeeperConfig = __esm({
|
|
58
|
+
"src/utils/zookeeperConfig.ts"() {
|
|
59
|
+
"use strict";
|
|
60
|
+
getZooKeeperConfig = () => {
|
|
61
|
+
const config = {
|
|
62
|
+
connectionString: process.env.ZOOKEEPER_CONNECTION_STRING,
|
|
63
|
+
infraPath: process.env.ZOOKEEPER_INFRA_PATH,
|
|
64
|
+
servicePath: process.env.ZOOKEEPER_SERVICE_PATH,
|
|
65
|
+
user: process.env.ZOOKEEPER_USER,
|
|
66
|
+
password: process.env.ZOOKEEPER_PASSWORD
|
|
67
|
+
};
|
|
68
|
+
if (!config.connectionString) {
|
|
69
|
+
throw new Error("ZOOKEEPER_CONNECTION_STRING is required");
|
|
70
|
+
}
|
|
71
|
+
return config;
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// src/utils/zookeeperCrypto.ts
|
|
77
|
+
import crypto from "crypto";
|
|
78
|
+
import * as fs from "fs";
|
|
79
|
+
import * as path from "path";
|
|
80
|
+
var LOG_PREFIX, INFRA_VALUE_REGEX, parseInfraValue, getPrivateKeyPath, decryptWithAlias, getServicePrivateKeyPath, decryptWithPrivateKey;
|
|
81
|
+
var init_zookeeperCrypto = __esm({
|
|
82
|
+
"src/utils/zookeeperCrypto.ts"() {
|
|
83
|
+
"use strict";
|
|
84
|
+
init_logger_service();
|
|
85
|
+
LOG_PREFIX = "[ZK] ";
|
|
86
|
+
INFRA_VALUE_REGEX = /^devEnc:([A-Za-z0-9+/=_-]+):([A-Za-z0-9-_]+)$/;
|
|
87
|
+
parseInfraValue = (value) => {
|
|
88
|
+
const match = value.match(INFRA_VALUE_REGEX);
|
|
89
|
+
if (!match) return null;
|
|
90
|
+
return {
|
|
91
|
+
prefix: "devEnc",
|
|
92
|
+
encryptedData: match[1],
|
|
93
|
+
alias: match[2]
|
|
94
|
+
};
|
|
95
|
+
};
|
|
96
|
+
getPrivateKeyPath = (alias) => {
|
|
97
|
+
const baseDir = process.env.PRIVATE_KEY_DIR || path.join(process.cwd(), "keys");
|
|
98
|
+
return path.join(baseDir, `private_key_${alias}.pem`);
|
|
99
|
+
};
|
|
100
|
+
decryptWithAlias = (encryptedData, alias) => {
|
|
101
|
+
try {
|
|
102
|
+
const privateKeyPath = getPrivateKeyPath(alias);
|
|
103
|
+
if (!fs.existsSync(privateKeyPath)) {
|
|
104
|
+
throw new Error(`Private key file not found for alias '${alias}': ${privateKeyPath}`);
|
|
105
|
+
}
|
|
106
|
+
const privateKey = fs.readFileSync(privateKeyPath, "utf8");
|
|
107
|
+
const buffer = Buffer.from(encryptedData, "base64");
|
|
108
|
+
const attempts = [
|
|
109
|
+
{
|
|
110
|
+
key: privateKey,
|
|
111
|
+
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
|
|
112
|
+
oaepHash: "sha256"
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
key: privateKey,
|
|
116
|
+
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
|
|
117
|
+
oaepHash: "sha1"
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
key: privateKey,
|
|
121
|
+
padding: crypto.constants.RSA_PKCS1_PADDING
|
|
122
|
+
}
|
|
123
|
+
];
|
|
124
|
+
let lastError = null;
|
|
125
|
+
for (const options of attempts) {
|
|
126
|
+
try {
|
|
127
|
+
const out = crypto.privateDecrypt(options, buffer);
|
|
128
|
+
return out.toString("utf-8");
|
|
129
|
+
} catch (error) {
|
|
130
|
+
lastError = error;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
LoggerService.error(`${LOG_PREFIX}RSA decryption failed with alias '${alias}'`, {
|
|
134
|
+
error: lastError
|
|
135
|
+
});
|
|
136
|
+
throw new Error(`Decryption failed for alias '${alias}'`);
|
|
137
|
+
} catch (error) {
|
|
138
|
+
LoggerService.error(`${LOG_PREFIX}failed to decrypt with alias '${alias}'`, {
|
|
139
|
+
error: error?.message || error
|
|
140
|
+
});
|
|
141
|
+
throw new Error(`Decryption failed for alias '${alias}': ${error.message}`);
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
getServicePrivateKeyPath = () => {
|
|
145
|
+
const baseDir = process.env.PRIVATE_KEY_DIR || path.join(process.cwd(), "keys");
|
|
146
|
+
return path.join(baseDir, "private.pem");
|
|
147
|
+
};
|
|
148
|
+
decryptWithPrivateKey = (encryptedData) => {
|
|
149
|
+
try {
|
|
150
|
+
const privateKeyPath = getServicePrivateKeyPath();
|
|
151
|
+
if (!fs.existsSync(privateKeyPath)) {
|
|
152
|
+
throw new Error(`Private key file not found: ${privateKeyPath}`);
|
|
153
|
+
}
|
|
154
|
+
const privateKey = fs.readFileSync(privateKeyPath, "utf8");
|
|
155
|
+
const buffer = Buffer.from(encryptedData, "base64");
|
|
156
|
+
const attempts = [
|
|
157
|
+
{
|
|
158
|
+
key: privateKey,
|
|
159
|
+
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
|
|
160
|
+
oaepHash: "sha256"
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
key: privateKey,
|
|
164
|
+
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
|
|
165
|
+
oaepHash: "sha1"
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
key: privateKey,
|
|
169
|
+
padding: crypto.constants.RSA_PKCS1_PADDING
|
|
170
|
+
}
|
|
171
|
+
];
|
|
172
|
+
let lastError = null;
|
|
173
|
+
for (const options of attempts) {
|
|
174
|
+
try {
|
|
175
|
+
const out = crypto.privateDecrypt(options, buffer);
|
|
176
|
+
return out.toString("utf-8");
|
|
177
|
+
} catch (error) {
|
|
178
|
+
lastError = error;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
LoggerService.error(`${LOG_PREFIX}RSA decryption failed with private.pem`, {
|
|
182
|
+
error: lastError
|
|
183
|
+
});
|
|
184
|
+
throw new Error("All decryption attempts failed");
|
|
185
|
+
} catch (error) {
|
|
186
|
+
LoggerService.error(`${LOG_PREFIX}failed to decrypt with private.pem`, {
|
|
187
|
+
error: error?.message || error
|
|
188
|
+
});
|
|
189
|
+
throw new Error(`Decryption failed: ${error.message}`);
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
// src/utils/zookeeper.ts
|
|
196
|
+
var zookeeper_exports = {};
|
|
197
|
+
__export(zookeeper_exports, {
|
|
198
|
+
default: () => zookeeper_default,
|
|
199
|
+
registerRestartCallback: () => registerRestartCallback
|
|
200
|
+
});
|
|
201
|
+
import zookeeper from "node-zookeeper-client";
|
|
202
|
+
import * as process2 from "process";
|
|
203
|
+
var SESSION_TIMEOUT, CONNECT_TIMEOUT, LOG_PREFIX2, isInfraDataBeingProcessed, isServiceDataBeingProcessed, hasLoadedInfraOnce, hasLoadedServiceOnce, currentClient, connectWatchdog, hasInfraPath, hasServicePath, restartCallback, registerRestartCallback, processEnvironmentData, decryptInfraValue, decryptServiceValue, handleZooKeeperData, connectToPath, cleanupClient, startZooKeeperClient, zookeeper_default;
|
|
204
|
+
var init_zookeeper = __esm({
|
|
205
|
+
"src/utils/zookeeper.ts"() {
|
|
206
|
+
"use strict";
|
|
207
|
+
init_zookeeperConfig();
|
|
208
|
+
init_zookeeperCrypto();
|
|
209
|
+
SESSION_TIMEOUT = 3e7;
|
|
210
|
+
CONNECT_TIMEOUT = 1e7;
|
|
211
|
+
LOG_PREFIX2 = "[ZK] ";
|
|
212
|
+
isInfraDataBeingProcessed = false;
|
|
213
|
+
isServiceDataBeingProcessed = false;
|
|
214
|
+
hasLoadedInfraOnce = false;
|
|
215
|
+
hasLoadedServiceOnce = false;
|
|
216
|
+
currentClient = null;
|
|
217
|
+
connectWatchdog = null;
|
|
218
|
+
hasInfraPath = false;
|
|
219
|
+
hasServicePath = false;
|
|
220
|
+
restartCallback = null;
|
|
221
|
+
registerRestartCallback = (callback) => {
|
|
222
|
+
restartCallback = callback;
|
|
223
|
+
};
|
|
224
|
+
processEnvironmentData = (data, isInfraPath) => {
|
|
225
|
+
const pathType = isInfraPath ? "infra" : "service";
|
|
226
|
+
const lines = data.split("\n");
|
|
227
|
+
let processedCount = 0;
|
|
228
|
+
let encryptedCount = 0;
|
|
229
|
+
let errorCount = 0;
|
|
230
|
+
const errors = [];
|
|
231
|
+
for (const line of lines) {
|
|
232
|
+
if (!line.trim()) continue;
|
|
233
|
+
const firstEqualIndex = line.indexOf("=");
|
|
234
|
+
if (firstEqualIndex === -1) continue;
|
|
235
|
+
const key = line.slice(0, firstEqualIndex).trim();
|
|
236
|
+
const value = line.slice(firstEqualIndex + 1).trim();
|
|
237
|
+
if (!key || value.length === 0) continue;
|
|
238
|
+
try {
|
|
239
|
+
if (value.startsWith("devEnc:") && isInfraPath) {
|
|
240
|
+
encryptedCount++;
|
|
241
|
+
let decryptedValue = decryptInfraValue(value);
|
|
242
|
+
decryptedValue = decryptedValue.replace(/(\r?\n)$/, "");
|
|
243
|
+
process2.env[key] = decryptedValue;
|
|
244
|
+
} else if (value.startsWith("devEnc:")) {
|
|
245
|
+
encryptedCount++;
|
|
246
|
+
let decryptedValue = decryptServiceValue(value);
|
|
247
|
+
decryptedValue = decryptedValue.replace(/(\r?\n)$/, "");
|
|
248
|
+
process2.env[key] = decryptedValue;
|
|
249
|
+
} else {
|
|
250
|
+
process2.env[key] = value;
|
|
251
|
+
}
|
|
252
|
+
processedCount++;
|
|
253
|
+
} catch (error) {
|
|
254
|
+
errorCount++;
|
|
255
|
+
errors.push({
|
|
256
|
+
key,
|
|
257
|
+
error: error?.message || "Unknown decryption error"
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
if (errorCount > 0) {
|
|
262
|
+
console.log(
|
|
263
|
+
JSON.stringify({
|
|
264
|
+
type: "ZK",
|
|
265
|
+
message: `${LOG_PREFIX2}errors processing environment variables`,
|
|
266
|
+
pathType,
|
|
267
|
+
processedCount,
|
|
268
|
+
encryptedCount,
|
|
269
|
+
errorCount,
|
|
270
|
+
errors: errors.slice(0, 10),
|
|
271
|
+
totalErrors: errors.length,
|
|
272
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
273
|
+
})
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
decryptInfraValue = (value) => {
|
|
278
|
+
const encryptedValue = parseInfraValue(value);
|
|
279
|
+
if (!encryptedValue) {
|
|
280
|
+
throw new Error("Invalid encrypted value format");
|
|
281
|
+
}
|
|
282
|
+
const decryptedValue = decryptWithAlias(
|
|
283
|
+
encryptedValue.encryptedData,
|
|
284
|
+
encryptedValue.alias
|
|
285
|
+
);
|
|
286
|
+
return decryptedValue;
|
|
287
|
+
};
|
|
288
|
+
decryptServiceValue = (value) => {
|
|
289
|
+
const cleanValue = value.replace("devEnc:", "");
|
|
290
|
+
const encryptedValue = decryptWithPrivateKey(cleanValue);
|
|
291
|
+
return encryptedValue;
|
|
292
|
+
};
|
|
293
|
+
handleZooKeeperData = (client, zkPath, isInfraPath, resolve, reject) => {
|
|
294
|
+
const pathType = isInfraPath ? "infra" : "service";
|
|
295
|
+
const isBeingProcessed = isInfraPath ? isInfraDataBeingProcessed : isServiceDataBeingProcessed;
|
|
296
|
+
if (isBeingProcessed) return;
|
|
297
|
+
if (isInfraPath) {
|
|
298
|
+
isInfraDataBeingProcessed = true;
|
|
299
|
+
} else {
|
|
300
|
+
isServiceDataBeingProcessed = true;
|
|
301
|
+
}
|
|
302
|
+
client.getData(
|
|
303
|
+
zkPath,
|
|
304
|
+
(event) => {
|
|
305
|
+
if (event.type === zookeeper.Event.NODE_DATA_CHANGED) {
|
|
306
|
+
console.log(
|
|
307
|
+
JSON.stringify({
|
|
308
|
+
type: "ZK",
|
|
309
|
+
message: `${LOG_PREFIX2}Config changed detected, restarting application`,
|
|
310
|
+
pathType: isInfraPath ? "infra" : "service",
|
|
311
|
+
path: zkPath,
|
|
312
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
313
|
+
})
|
|
314
|
+
);
|
|
315
|
+
if (restartCallback) {
|
|
316
|
+
restartCallback().catch((error) => {
|
|
317
|
+
console.log(
|
|
318
|
+
JSON.stringify({
|
|
319
|
+
type: "ZK",
|
|
320
|
+
message: `${LOG_PREFIX2}Error during restart`,
|
|
321
|
+
error: {
|
|
322
|
+
message: error?.message || "Unknown error",
|
|
323
|
+
stack: error?.stack
|
|
324
|
+
},
|
|
325
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
326
|
+
})
|
|
327
|
+
);
|
|
328
|
+
process2.exit(0);
|
|
329
|
+
});
|
|
330
|
+
} else {
|
|
331
|
+
console.log(
|
|
332
|
+
JSON.stringify({
|
|
333
|
+
type: "ZK",
|
|
334
|
+
message: `${LOG_PREFIX2}No restart callback registered, exiting process`,
|
|
335
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
336
|
+
})
|
|
337
|
+
);
|
|
338
|
+
process2.exit(0);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
},
|
|
342
|
+
(error, data) => {
|
|
343
|
+
if (isInfraPath) {
|
|
344
|
+
isInfraDataBeingProcessed = false;
|
|
345
|
+
} else {
|
|
346
|
+
isServiceDataBeingProcessed = false;
|
|
347
|
+
}
|
|
348
|
+
if (error) {
|
|
349
|
+
const errorMsg = `${LOG_PREFIX2}getData failed for ${pathType} path: ${zkPath}`;
|
|
350
|
+
console.log(
|
|
351
|
+
JSON.stringify({
|
|
352
|
+
type: "ZK",
|
|
353
|
+
message: errorMsg,
|
|
354
|
+
pathType,
|
|
355
|
+
path: zkPath,
|
|
356
|
+
error: {
|
|
357
|
+
message: error?.message || "Unknown error",
|
|
358
|
+
code: error?.code,
|
|
359
|
+
name: error?.name,
|
|
360
|
+
stack: error?.stack,
|
|
361
|
+
errno: error?.errno
|
|
362
|
+
},
|
|
363
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
364
|
+
})
|
|
365
|
+
);
|
|
366
|
+
reject(new Error(errorMsg));
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
if (!data) {
|
|
370
|
+
reject(
|
|
371
|
+
new Error(
|
|
372
|
+
`${LOG_PREFIX2}No data received for ${pathType} path: ${zkPath}`
|
|
373
|
+
)
|
|
374
|
+
);
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
try {
|
|
378
|
+
const rawData = data.toString("utf8");
|
|
379
|
+
processEnvironmentData(rawData, isInfraPath);
|
|
380
|
+
if (isInfraPath) {
|
|
381
|
+
hasInfraPath = true;
|
|
382
|
+
} else {
|
|
383
|
+
hasServicePath = true;
|
|
384
|
+
}
|
|
385
|
+
if (isInfraPath) {
|
|
386
|
+
if (!hasLoadedInfraOnce) {
|
|
387
|
+
hasLoadedInfraOnce = true;
|
|
388
|
+
console.log(
|
|
389
|
+
JSON.stringify({
|
|
390
|
+
type: "ZK",
|
|
391
|
+
message: `${LOG_PREFIX2}loaded infra environment variables`,
|
|
392
|
+
path: zkPath
|
|
393
|
+
})
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
} else {
|
|
397
|
+
if (!hasLoadedServiceOnce) {
|
|
398
|
+
hasLoadedServiceOnce = true;
|
|
399
|
+
console.log(
|
|
400
|
+
JSON.stringify({
|
|
401
|
+
type: "ZK",
|
|
402
|
+
message: `${LOG_PREFIX2}loaded service environment variables`,
|
|
403
|
+
path: zkPath
|
|
404
|
+
})
|
|
405
|
+
);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
if (hasInfraPath && hasServicePath) {
|
|
409
|
+
resolve();
|
|
410
|
+
}
|
|
411
|
+
} catch (error2) {
|
|
412
|
+
const errorMsg = `${LOG_PREFIX2}error processing data for ${pathType} path: ${zkPath}`;
|
|
413
|
+
console.log(
|
|
414
|
+
JSON.stringify({
|
|
415
|
+
type: "ZK",
|
|
416
|
+
message: errorMsg,
|
|
417
|
+
pathType,
|
|
418
|
+
path: zkPath,
|
|
419
|
+
error: {
|
|
420
|
+
message: error2?.message || "Unknown error",
|
|
421
|
+
code: error2?.code,
|
|
422
|
+
name: error2?.name,
|
|
423
|
+
stack: error2?.stack
|
|
424
|
+
},
|
|
425
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
426
|
+
})
|
|
427
|
+
);
|
|
428
|
+
reject(new Error(errorMsg));
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
);
|
|
432
|
+
};
|
|
433
|
+
connectToPath = (client, zkPath, isInfraPath, resolve, reject) => {
|
|
434
|
+
const pathType = isInfraPath ? "infra" : "service";
|
|
435
|
+
client.exists(
|
|
436
|
+
zkPath,
|
|
437
|
+
() => {
|
|
438
|
+
},
|
|
439
|
+
(error, stat) => {
|
|
440
|
+
if (error) {
|
|
441
|
+
const errorMsg = `${LOG_PREFIX2}exists check failed for ${pathType} path: ${zkPath}`;
|
|
442
|
+
console.log(
|
|
443
|
+
JSON.stringify({
|
|
444
|
+
type: "ZK",
|
|
445
|
+
message: errorMsg,
|
|
446
|
+
pathType,
|
|
447
|
+
path: zkPath,
|
|
448
|
+
error: {
|
|
449
|
+
message: error?.message || "Unknown error",
|
|
450
|
+
code: error?.code,
|
|
451
|
+
name: error?.name,
|
|
452
|
+
stack: error?.stack,
|
|
453
|
+
errno: error?.errno
|
|
454
|
+
},
|
|
455
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
456
|
+
})
|
|
457
|
+
);
|
|
458
|
+
reject(new Error(errorMsg));
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
if (stat) {
|
|
462
|
+
handleZooKeeperData(client, zkPath, isInfraPath, resolve, reject);
|
|
463
|
+
} else {
|
|
464
|
+
const errorMsg = `${LOG_PREFIX2}path does not exist: ${zkPath}`;
|
|
465
|
+
console.log(
|
|
466
|
+
JSON.stringify({
|
|
467
|
+
type: "ZK",
|
|
468
|
+
message: errorMsg,
|
|
469
|
+
pathType,
|
|
470
|
+
path: zkPath,
|
|
471
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
472
|
+
})
|
|
473
|
+
);
|
|
474
|
+
reject(new Error(errorMsg));
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
);
|
|
478
|
+
};
|
|
479
|
+
cleanupClient = () => {
|
|
480
|
+
try {
|
|
481
|
+
if (currentClient?.close) currentClient.close();
|
|
482
|
+
} catch (e) {
|
|
483
|
+
if (e?.message) {
|
|
484
|
+
console.log(
|
|
485
|
+
JSON.stringify({
|
|
486
|
+
type: "ZK",
|
|
487
|
+
message: `${LOG_PREFIX2}error closing client`,
|
|
488
|
+
error: {
|
|
489
|
+
message: e?.message,
|
|
490
|
+
stack: e?.stack
|
|
491
|
+
},
|
|
492
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
493
|
+
})
|
|
494
|
+
);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
currentClient = null;
|
|
498
|
+
if (connectWatchdog) {
|
|
499
|
+
clearTimeout(connectWatchdog);
|
|
500
|
+
connectWatchdog = null;
|
|
501
|
+
}
|
|
502
|
+
};
|
|
503
|
+
startZooKeeperClient = () => {
|
|
504
|
+
return new Promise((resolve, reject) => {
|
|
505
|
+
let resolved = false;
|
|
506
|
+
const safeResolve = () => {
|
|
507
|
+
if (!resolved) {
|
|
508
|
+
resolved = true;
|
|
509
|
+
resolve();
|
|
510
|
+
}
|
|
511
|
+
};
|
|
512
|
+
try {
|
|
513
|
+
const config = getZooKeeperConfig();
|
|
514
|
+
console.log(
|
|
515
|
+
JSON.stringify({
|
|
516
|
+
type: "ZK",
|
|
517
|
+
message: `${LOG_PREFIX2}initializing`,
|
|
518
|
+
config: {
|
|
519
|
+
connectionString: config.connectionString,
|
|
520
|
+
infraPath: config.infraPath,
|
|
521
|
+
servicePath: config.servicePath,
|
|
522
|
+
hasAuth: !!(config.user && config.password),
|
|
523
|
+
user: config.user || null,
|
|
524
|
+
sessionTimeout: SESSION_TIMEOUT
|
|
525
|
+
}
|
|
526
|
+
})
|
|
527
|
+
);
|
|
528
|
+
cleanupClient();
|
|
529
|
+
hasInfraPath = false;
|
|
530
|
+
hasServicePath = false;
|
|
531
|
+
hasLoadedInfraOnce = false;
|
|
532
|
+
hasLoadedServiceOnce = false;
|
|
533
|
+
isInfraDataBeingProcessed = false;
|
|
534
|
+
isServiceDataBeingProcessed = false;
|
|
535
|
+
const client = zookeeper.createClient(config.connectionString, {
|
|
536
|
+
sessionTimeout: SESSION_TIMEOUT,
|
|
537
|
+
retries: 0
|
|
538
|
+
// No retries - fail fast
|
|
539
|
+
});
|
|
540
|
+
currentClient = client;
|
|
541
|
+
if (config.user && config.password) {
|
|
542
|
+
client.addAuthInfo(
|
|
543
|
+
"digest",
|
|
544
|
+
Buffer.from(`${config.user}:${config.password}`)
|
|
545
|
+
);
|
|
546
|
+
}
|
|
547
|
+
connectWatchdog = setTimeout(() => {
|
|
548
|
+
if (currentClient === client) {
|
|
549
|
+
cleanupClient();
|
|
550
|
+
const errorMsg = `${LOG_PREFIX2}Connection timeout after ${CONNECT_TIMEOUT}ms`;
|
|
551
|
+
console.log(
|
|
552
|
+
JSON.stringify({
|
|
553
|
+
type: "ZK",
|
|
554
|
+
message: errorMsg,
|
|
555
|
+
config: {
|
|
556
|
+
connectionString: config.connectionString
|
|
557
|
+
},
|
|
558
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
559
|
+
})
|
|
560
|
+
);
|
|
561
|
+
reject(new Error(errorMsg));
|
|
562
|
+
}
|
|
563
|
+
}, CONNECT_TIMEOUT);
|
|
564
|
+
client.on("connected", () => {
|
|
565
|
+
console.log(
|
|
566
|
+
JSON.stringify({
|
|
567
|
+
type: "ZK",
|
|
568
|
+
message: `${LOG_PREFIX2}connected`,
|
|
569
|
+
config: {
|
|
570
|
+
connectionString: config.connectionString,
|
|
571
|
+
infraPath: config.infraPath,
|
|
572
|
+
servicePath: config.servicePath,
|
|
573
|
+
user: config.user,
|
|
574
|
+
password: config.password
|
|
575
|
+
}
|
|
576
|
+
})
|
|
577
|
+
);
|
|
578
|
+
if (connectWatchdog) {
|
|
579
|
+
clearTimeout(connectWatchdog);
|
|
580
|
+
connectWatchdog = null;
|
|
581
|
+
}
|
|
582
|
+
connectToPath(client, config.infraPath, true, safeResolve, reject);
|
|
583
|
+
connectToPath(client, config.servicePath, false, safeResolve, reject);
|
|
584
|
+
});
|
|
585
|
+
client.on("disconnected", () => {
|
|
586
|
+
console.log(
|
|
587
|
+
JSON.stringify({
|
|
588
|
+
type: "ZK",
|
|
589
|
+
message: `${LOG_PREFIX2}disconnected`,
|
|
590
|
+
config: {
|
|
591
|
+
connectionString: config.connectionString
|
|
592
|
+
}
|
|
593
|
+
})
|
|
594
|
+
);
|
|
595
|
+
cleanupClient();
|
|
596
|
+
reject(new Error(`${LOG_PREFIX2}Disconnected from ZooKeeper`));
|
|
597
|
+
});
|
|
598
|
+
client.on("expired", () => {
|
|
599
|
+
console.log(
|
|
600
|
+
JSON.stringify({
|
|
601
|
+
type: "ZK",
|
|
602
|
+
message: `${LOG_PREFIX2}session expired`,
|
|
603
|
+
config: {
|
|
604
|
+
connectionString: config.connectionString
|
|
605
|
+
}
|
|
606
|
+
})
|
|
607
|
+
);
|
|
608
|
+
cleanupClient();
|
|
609
|
+
reject(new Error(`${LOG_PREFIX2}ZooKeeper session expired`));
|
|
610
|
+
});
|
|
611
|
+
client.on("error", (error) => {
|
|
612
|
+
console.log(
|
|
613
|
+
JSON.stringify({
|
|
614
|
+
type: "ZK",
|
|
615
|
+
message: `${LOG_PREFIX2}error`,
|
|
616
|
+
error: {
|
|
617
|
+
message: error?.message || "Unknown error",
|
|
618
|
+
code: error?.code,
|
|
619
|
+
name: error?.name,
|
|
620
|
+
stack: error?.stack,
|
|
621
|
+
errno: error?.errno,
|
|
622
|
+
syscall: error?.syscall,
|
|
623
|
+
address: error?.address,
|
|
624
|
+
port: error?.port
|
|
625
|
+
},
|
|
626
|
+
config: {
|
|
627
|
+
connectionString: config.connectionString
|
|
628
|
+
},
|
|
629
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
630
|
+
})
|
|
631
|
+
);
|
|
632
|
+
cleanupClient();
|
|
633
|
+
reject(
|
|
634
|
+
new Error(
|
|
635
|
+
`${LOG_PREFIX2}ZooKeeper error: ${error?.message || "Unknown error"}`
|
|
636
|
+
)
|
|
637
|
+
);
|
|
638
|
+
});
|
|
639
|
+
client.connect();
|
|
640
|
+
} catch (error) {
|
|
641
|
+
const config = getZooKeeperConfig();
|
|
642
|
+
console.log(
|
|
643
|
+
JSON.stringify({
|
|
644
|
+
type: "ZK",
|
|
645
|
+
message: `${LOG_PREFIX2}initialization failed`,
|
|
646
|
+
error: {
|
|
647
|
+
message: error?.message || "Unknown error",
|
|
648
|
+
code: error?.code,
|
|
649
|
+
name: error?.name,
|
|
650
|
+
stack: error?.stack,
|
|
651
|
+
errno: error?.errno,
|
|
652
|
+
syscall: error?.syscall
|
|
653
|
+
},
|
|
654
|
+
config: {
|
|
655
|
+
connectionString: config.connectionString,
|
|
656
|
+
infraPath: config.infraPath,
|
|
657
|
+
servicePath: config.servicePath,
|
|
658
|
+
hasAuth: !!(config.user && config.password)
|
|
659
|
+
},
|
|
660
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
661
|
+
})
|
|
662
|
+
);
|
|
663
|
+
cleanupClient();
|
|
664
|
+
reject(
|
|
665
|
+
new Error(
|
|
666
|
+
`${LOG_PREFIX2}Initialization exception: ${error?.message || "Unknown error"}`
|
|
667
|
+
)
|
|
668
|
+
);
|
|
669
|
+
}
|
|
670
|
+
});
|
|
671
|
+
};
|
|
672
|
+
zookeeper_default = startZooKeeperClient;
|
|
673
|
+
}
|
|
674
|
+
});
|
|
675
|
+
|
|
676
|
+
// src/index.ts
|
|
677
|
+
import "reflect-metadata";
|
|
678
|
+
|
|
679
|
+
// src/inversify.container.ts
|
|
680
|
+
import { Container } from "inversify";
|
|
681
|
+
|
|
682
|
+
// src/configs/redis-client.ts
|
|
683
|
+
init_logger_service();
|
|
684
|
+
import { createClient } from "redis";
|
|
685
|
+
var RedisClient = class _RedisClient {
|
|
686
|
+
constructor() {
|
|
687
|
+
this.reconnectAttempts = 0;
|
|
688
|
+
this.maxReconnectAttempts = 2;
|
|
689
|
+
this.connectPromise = null;
|
|
690
|
+
this.client = createClient({
|
|
691
|
+
socket: {
|
|
692
|
+
host: process.env.REDIS_HOST ?? "127.0.0.1",
|
|
693
|
+
port: Number(process.env.REDIS_PORT) || 6379,
|
|
694
|
+
reconnectStrategy: (retries) => {
|
|
695
|
+
this.reconnectAttempts = retries;
|
|
696
|
+
if (retries > this.maxReconnectAttempts) {
|
|
697
|
+
LoggerService.error("Redis reconnect attempts exceeded", {
|
|
698
|
+
retries,
|
|
699
|
+
host: process.env.REDIS_HOST ?? "127.0.0.1",
|
|
700
|
+
port: Number(process.env.REDIS_PORT) || 6379
|
|
701
|
+
});
|
|
702
|
+
return new Error("Redis reconnect attempts exceeded");
|
|
703
|
+
}
|
|
704
|
+
return 1e3;
|
|
705
|
+
}
|
|
706
|
+
},
|
|
707
|
+
password: process.env.REDIS_PASSWORD || void 0
|
|
708
|
+
});
|
|
709
|
+
this.client.on("error", (err) => {
|
|
710
|
+
LoggerService.error("Redis error", {
|
|
711
|
+
error: err?.message || err,
|
|
712
|
+
reconnectAttempts: this.reconnectAttempts
|
|
713
|
+
});
|
|
714
|
+
});
|
|
715
|
+
this.client.on("connect", () => {
|
|
716
|
+
LoggerService.info("Redis connected", {
|
|
717
|
+
host: process.env.REDIS_HOST ?? "127.0.0.1",
|
|
718
|
+
port: Number(process.env.REDIS_PORT) || 6379
|
|
719
|
+
});
|
|
720
|
+
});
|
|
721
|
+
}
|
|
722
|
+
static getInstance() {
|
|
723
|
+
if (!_RedisClient.instance) {
|
|
724
|
+
_RedisClient.instance = new _RedisClient();
|
|
725
|
+
}
|
|
726
|
+
return _RedisClient.instance;
|
|
727
|
+
}
|
|
728
|
+
async connect() {
|
|
729
|
+
if (this.client.isOpen) {
|
|
730
|
+
return this.client;
|
|
731
|
+
}
|
|
732
|
+
if (!this.connectPromise) {
|
|
733
|
+
this.connectPromise = this.client.connect().catch((err) => {
|
|
734
|
+
LoggerService.error("Redis initial connect error", {
|
|
735
|
+
error: err?.message || err
|
|
736
|
+
});
|
|
737
|
+
this.connectPromise = null;
|
|
738
|
+
throw err;
|
|
739
|
+
});
|
|
740
|
+
}
|
|
741
|
+
return await this.connectPromise;
|
|
742
|
+
}
|
|
743
|
+
getClient() {
|
|
744
|
+
return this.client;
|
|
745
|
+
}
|
|
746
|
+
async disconnect() {
|
|
747
|
+
if (this.client.isOpen) {
|
|
748
|
+
await this.client.quit();
|
|
749
|
+
LoggerService.info("Redis disconnected");
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
isConnected() {
|
|
753
|
+
return this.client.isOpen;
|
|
754
|
+
}
|
|
755
|
+
};
|
|
756
|
+
var redis_client_default = RedisClient.getInstance();
|
|
757
|
+
|
|
758
|
+
// src/modules/cache/cacheService.ts
|
|
759
|
+
import { injectable } from "inversify";
|
|
760
|
+
var CacheService = class {
|
|
761
|
+
constructor() {
|
|
762
|
+
this.client = redis_client_default.getClient();
|
|
763
|
+
}
|
|
764
|
+
async setValue(key, value, ttlInSeconds) {
|
|
765
|
+
const payload = JSON.stringify(value);
|
|
766
|
+
if (ttlInSeconds && ttlInSeconds > 0) {
|
|
767
|
+
await this.client.setEx(key, ttlInSeconds, payload);
|
|
768
|
+
return;
|
|
769
|
+
}
|
|
770
|
+
const result = await this.client.set(key, payload);
|
|
771
|
+
return result === null ? void 0 : result;
|
|
772
|
+
}
|
|
773
|
+
async getValue(key) {
|
|
774
|
+
const result = await this.client.get(key);
|
|
775
|
+
return result ? JSON.parse(result) : null;
|
|
776
|
+
}
|
|
777
|
+
async deleteValue(key) {
|
|
778
|
+
await this.client.del(key);
|
|
779
|
+
}
|
|
780
|
+
async hSet(key, hash) {
|
|
781
|
+
return this.client.hSet(key, hash);
|
|
782
|
+
}
|
|
783
|
+
async hmGet(key, ...fields) {
|
|
784
|
+
return this.client.hmGet(key, fields);
|
|
785
|
+
}
|
|
786
|
+
async hGetAll(key) {
|
|
787
|
+
return this.client.hGetAll(key);
|
|
788
|
+
}
|
|
789
|
+
async expire(key, ttlSeconds) {
|
|
790
|
+
return this.client.expire(key, ttlSeconds);
|
|
791
|
+
}
|
|
792
|
+
async sAdd(key, ...members) {
|
|
793
|
+
return this.client.sAdd(key, members);
|
|
794
|
+
}
|
|
795
|
+
async sMembers(key) {
|
|
796
|
+
return this.client.sMembers(key);
|
|
797
|
+
}
|
|
798
|
+
async sRem(key, ...members) {
|
|
799
|
+
return this.client.sRem(key, members);
|
|
800
|
+
}
|
|
801
|
+
async sCard(key) {
|
|
802
|
+
return this.client.sCard(key);
|
|
803
|
+
}
|
|
804
|
+
async del(...keys) {
|
|
805
|
+
return this.client.del(keys);
|
|
806
|
+
}
|
|
807
|
+
multi() {
|
|
808
|
+
return this.client.multi();
|
|
809
|
+
}
|
|
810
|
+
};
|
|
811
|
+
CacheService = __decorateClass([
|
|
812
|
+
injectable()
|
|
813
|
+
], CacheService);
|
|
814
|
+
|
|
815
|
+
// src/modules/cache/cacheController.ts
|
|
816
|
+
import { inject, injectable as injectable2 } from "inversify";
|
|
817
|
+
|
|
818
|
+
// src/inversify.types.ts
|
|
819
|
+
var TYPES = {
|
|
820
|
+
CacheService: /* @__PURE__ */ Symbol.for("CacheService"),
|
|
821
|
+
CacheController: /* @__PURE__ */ Symbol.for("CacheController"),
|
|
822
|
+
SsoController: /* @__PURE__ */ Symbol.for("SsoController"),
|
|
823
|
+
SsoService: /* @__PURE__ */ Symbol.for("SsoService")
|
|
824
|
+
};
|
|
825
|
+
|
|
826
|
+
// src/types/cache.types.ts
|
|
827
|
+
var REQUIRED_BIN_NAMES = ["bin1", "bin2", "bin3", "bin4", "bin5"];
|
|
828
|
+
|
|
829
|
+
// src/modules/cache/cacheController.ts
|
|
830
|
+
var SET_NAME_PREFIX = process.env.SCRIPT_SET_NAME_PREFIX ?? "scriptSet";
|
|
831
|
+
var DEFAULT_EXPIRE_TIME_MS = Number(
|
|
832
|
+
process.env.SCRIPT_PUT_CACHE_EXPIRE_TIME_MS ?? 6e5
|
|
833
|
+
);
|
|
834
|
+
var CacheController = class {
|
|
835
|
+
constructor(cacheService) {
|
|
836
|
+
this.cacheService = cacheService;
|
|
837
|
+
}
|
|
838
|
+
async putScriptRecord(setName, key, record, ttlSeconds) {
|
|
839
|
+
for (const bin of REQUIRED_BIN_NAMES) {
|
|
840
|
+
if (typeof record[bin] === "undefined") {
|
|
841
|
+
throw new Error(`Field ${bin} is required`);
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
const safeRecord = {};
|
|
845
|
+
for (const bin of REQUIRED_BIN_NAMES) {
|
|
846
|
+
const value = record[bin];
|
|
847
|
+
if (typeof value !== "string") {
|
|
848
|
+
throw new Error(`Invalid value for ${bin}`);
|
|
849
|
+
}
|
|
850
|
+
safeRecord[bin] = value;
|
|
851
|
+
}
|
|
852
|
+
const redisKey = `${setName}:${key}`;
|
|
853
|
+
const ttl = typeof ttlSeconds === "number" ? ttlSeconds : Math.floor(DEFAULT_EXPIRE_TIME_MS / 1e3);
|
|
854
|
+
const multi = this.cacheService.multi();
|
|
855
|
+
const entries = Object.entries(safeRecord);
|
|
856
|
+
if (!entries.length) {
|
|
857
|
+
throw new Error("No record found to store in Redis");
|
|
858
|
+
}
|
|
859
|
+
for (const [field, value] of entries) {
|
|
860
|
+
multi.hSet(redisKey, field, value);
|
|
861
|
+
}
|
|
862
|
+
if (ttl > 0) {
|
|
863
|
+
multi.expire(redisKey, ttl);
|
|
864
|
+
}
|
|
865
|
+
for (const bin of REQUIRED_BIN_NAMES) {
|
|
866
|
+
const value = safeRecord[bin];
|
|
867
|
+
if (value) {
|
|
868
|
+
multi.sAdd(`index:${setName}:${bin}:${value}`, redisKey);
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
multi.sAdd(`set:${setName}:keys`, redisKey);
|
|
872
|
+
await multi.exec();
|
|
873
|
+
return { redisKey, ttl };
|
|
874
|
+
}
|
|
875
|
+
async getScriptRecord(setName, key) {
|
|
876
|
+
const redisKey = `${setName}:${key}`;
|
|
877
|
+
const values = await this.cacheService.hmGet(redisKey, ...REQUIRED_BIN_NAMES);
|
|
878
|
+
if (!values || values.every((v) => v === null)) {
|
|
879
|
+
return null;
|
|
880
|
+
}
|
|
881
|
+
const record = {};
|
|
882
|
+
REQUIRED_BIN_NAMES.forEach((bin, i) => {
|
|
883
|
+
record[bin] = values[i];
|
|
884
|
+
});
|
|
885
|
+
return record;
|
|
886
|
+
}
|
|
887
|
+
async equalScriptRecordsWithIndex(setName, binName, value) {
|
|
888
|
+
const indexKey = this.buildIndexKey(setName, binName, value);
|
|
889
|
+
const redisKeys = await this.cacheService.sMembers(indexKey);
|
|
890
|
+
if (!redisKeys.length) {
|
|
891
|
+
return [];
|
|
892
|
+
}
|
|
893
|
+
const multi = this.cacheService.multi();
|
|
894
|
+
for (const key of redisKeys) {
|
|
895
|
+
multi.hGetAll(key);
|
|
896
|
+
}
|
|
897
|
+
const responses = await multi.exec();
|
|
898
|
+
if (!responses) {
|
|
899
|
+
throw new Error("Pipeline execution failed");
|
|
900
|
+
}
|
|
901
|
+
return responses.map((record, idx) => {
|
|
902
|
+
const formattedRecord = {};
|
|
903
|
+
REQUIRED_BIN_NAMES.forEach((bin) => {
|
|
904
|
+
formattedRecord[bin] = record[bin] ?? null;
|
|
905
|
+
});
|
|
906
|
+
return {
|
|
907
|
+
redisKey: redisKeys[idx],
|
|
908
|
+
record: formattedRecord
|
|
909
|
+
};
|
|
910
|
+
});
|
|
911
|
+
}
|
|
912
|
+
async countScriptRecordsWithIndex(setName, binName, value) {
|
|
913
|
+
return this.cacheService.sCard(this.buildIndexKey(setName, binName, value));
|
|
914
|
+
}
|
|
915
|
+
async deleteScriptRecord(setName, key) {
|
|
916
|
+
const redisKey = `${setName}:${key}`;
|
|
917
|
+
const hash = await this.cacheService.hGetAll(redisKey);
|
|
918
|
+
if (!hash || !Object.keys(hash).length) {
|
|
919
|
+
return false;
|
|
920
|
+
}
|
|
921
|
+
const multi = this.cacheService.multi();
|
|
922
|
+
multi.del(redisKey);
|
|
923
|
+
for (const bin of REQUIRED_BIN_NAMES) {
|
|
924
|
+
const value = hash[bin];
|
|
925
|
+
if (value) {
|
|
926
|
+
multi.sRem(this.buildIndexKey(setName, bin, value), redisKey);
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
multi.sRem(`set:${setName}:keys`, redisKey);
|
|
930
|
+
await multi.exec();
|
|
931
|
+
return true;
|
|
932
|
+
}
|
|
933
|
+
async createBaseStructureForScript(totalSets = 5) {
|
|
934
|
+
const multi = this.cacheService.multi();
|
|
935
|
+
for (let s = 1; s <= totalSets; s++) {
|
|
936
|
+
const setName = `${SET_NAME_PREFIX}${s}`;
|
|
937
|
+
const keyStr = `${setName}_key`;
|
|
938
|
+
const redisKey = `${setName}:${keyStr}`;
|
|
939
|
+
const hashMap = {};
|
|
940
|
+
for (const bin of REQUIRED_BIN_NAMES) {
|
|
941
|
+
hashMap[bin] = "DUMMY";
|
|
942
|
+
}
|
|
943
|
+
for (const [field, val] of Object.entries(hashMap)) {
|
|
944
|
+
multi.hSet(redisKey, field, val);
|
|
945
|
+
}
|
|
946
|
+
multi.sAdd(`set:${setName}:keys`, redisKey);
|
|
947
|
+
for (const bin of REQUIRED_BIN_NAMES) {
|
|
948
|
+
multi.sAdd(this.buildIndexKey(setName, bin, hashMap[bin]), redisKey);
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
await multi.exec();
|
|
952
|
+
}
|
|
953
|
+
async setValue(key, value, ttlInSeconds) {
|
|
954
|
+
return this.cacheService.setValue(key, value, ttlInSeconds);
|
|
955
|
+
}
|
|
956
|
+
async getValue(key) {
|
|
957
|
+
return this.cacheService.getValue(key);
|
|
958
|
+
}
|
|
959
|
+
async deleteValue(key) {
|
|
960
|
+
await this.cacheService.deleteValue(key);
|
|
961
|
+
}
|
|
962
|
+
buildIndexKey(setName, binName, value) {
|
|
963
|
+
return `index:${setName}:${binName}:${value}`;
|
|
964
|
+
}
|
|
965
|
+
};
|
|
966
|
+
CacheController = __decorateClass([
|
|
967
|
+
injectable2(),
|
|
968
|
+
__decorateParam(0, inject(TYPES.CacheService))
|
|
969
|
+
], CacheController);
|
|
970
|
+
|
|
971
|
+
// src/modules/sso/sso.controller.ts
|
|
972
|
+
import { inject as inject2, injectable as injectable3 } from "inversify";
|
|
973
|
+
var SsoController = class {
|
|
974
|
+
constructor(ssoService) {
|
|
975
|
+
this.ssoService = ssoService;
|
|
976
|
+
}
|
|
977
|
+
async getUserByAccesstoken(AccessToken) {
|
|
978
|
+
const getData = await this.ssoService.getUserByAccesstoken(AccessToken);
|
|
979
|
+
return getData;
|
|
980
|
+
}
|
|
981
|
+
async getUserByIdentity(identity, identityType) {
|
|
982
|
+
return await this.ssoService.getUserByIdentity(identity, identityType);
|
|
983
|
+
}
|
|
984
|
+
};
|
|
985
|
+
SsoController = __decorateClass([
|
|
986
|
+
injectable3(),
|
|
987
|
+
__decorateParam(0, inject2(TYPES.SsoService))
|
|
988
|
+
], SsoController);
|
|
989
|
+
|
|
990
|
+
// src/modules/sso/sso.service.ts
|
|
991
|
+
import { injectable as injectable4 } from "inversify";
|
|
992
|
+
var SsoService = class {
|
|
993
|
+
async getUserByAccesstoken(AccessToken) {
|
|
994
|
+
let data = null;
|
|
995
|
+
try {
|
|
996
|
+
const response = await fetch(`${process.env.SsoUrl}/users`, {
|
|
997
|
+
method: "GET",
|
|
998
|
+
headers: {
|
|
999
|
+
"accept": "application/json",
|
|
1000
|
+
"Accept-Language": "en",
|
|
1001
|
+
"Authorization": `Bearer ${AccessToken}`
|
|
1002
|
+
}
|
|
1003
|
+
});
|
|
1004
|
+
data = await response.json();
|
|
1005
|
+
if (!response.ok) {
|
|
1006
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
1007
|
+
}
|
|
1008
|
+
return {
|
|
1009
|
+
data,
|
|
1010
|
+
error: false,
|
|
1011
|
+
errorMessage: ""
|
|
1012
|
+
};
|
|
1013
|
+
} catch (error) {
|
|
1014
|
+
return {
|
|
1015
|
+
data,
|
|
1016
|
+
error: true,
|
|
1017
|
+
errorMessage: error.message
|
|
1018
|
+
};
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
async getUserByIdentity(identity, identityType) {
|
|
1022
|
+
const url = `http://sso-sandbox.sandpod.ir/social/POD/users/${identity}?identityType=${identityType}`;
|
|
1023
|
+
try {
|
|
1024
|
+
const response = await fetch(url, {
|
|
1025
|
+
method: "GET",
|
|
1026
|
+
headers: {
|
|
1027
|
+
"accept": "application/json",
|
|
1028
|
+
"Accept-Language": "en",
|
|
1029
|
+
"Authorization": `Bearer ${process.env.AuthToken}`
|
|
1030
|
+
}
|
|
1031
|
+
});
|
|
1032
|
+
const data = JSON.parse(await response.text());
|
|
1033
|
+
if (!response.ok) {
|
|
1034
|
+
throw new Error(`HTTP error! status: ${response.status} and error is ${data}`);
|
|
1035
|
+
}
|
|
1036
|
+
return {
|
|
1037
|
+
data,
|
|
1038
|
+
error: false,
|
|
1039
|
+
errorMessage: ""
|
|
1040
|
+
};
|
|
1041
|
+
} catch (error) {
|
|
1042
|
+
return {
|
|
1043
|
+
data: null,
|
|
1044
|
+
error: true,
|
|
1045
|
+
errorMessage: error
|
|
1046
|
+
};
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
};
|
|
1050
|
+
SsoService = __decorateClass([
|
|
1051
|
+
injectable4()
|
|
1052
|
+
], SsoService);
|
|
1053
|
+
|
|
1054
|
+
// src/inversify.container.ts
|
|
1055
|
+
function createContainer(_options = {}) {
|
|
1056
|
+
const container = new Container();
|
|
1057
|
+
container.bind(TYPES.CacheService).to(CacheService).inSingletonScope();
|
|
1058
|
+
container.bind(TYPES.SsoService).to(SsoService).inSingletonScope();
|
|
1059
|
+
container.bind(TYPES.CacheController).to(CacheController).inSingletonScope();
|
|
1060
|
+
container.bind(TYPES.SsoController).to(SsoController).inSingletonScope();
|
|
1061
|
+
return container;
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
// src/service-call-library.ts
|
|
1065
|
+
var ServiceCallLibrary = class {
|
|
1066
|
+
constructor(options = {}) {
|
|
1067
|
+
this.ready = null;
|
|
1068
|
+
this.container = createContainer(options);
|
|
1069
|
+
this.ssoController = this.container.get(TYPES.SsoController);
|
|
1070
|
+
this.cacheController = this.container.get(TYPES.CacheController);
|
|
1071
|
+
}
|
|
1072
|
+
async init() {
|
|
1073
|
+
if (!this.ready) {
|
|
1074
|
+
this.ready = this.bootstrap();
|
|
1075
|
+
}
|
|
1076
|
+
await this.ready;
|
|
1077
|
+
}
|
|
1078
|
+
async bootstrap() {
|
|
1079
|
+
await redis_client_default.connect();
|
|
1080
|
+
const { default: initZookeeper } = await Promise.resolve().then(() => (init_zookeeper(), zookeeper_exports));
|
|
1081
|
+
await initZookeeper();
|
|
1082
|
+
}
|
|
1083
|
+
get sso() {
|
|
1084
|
+
return this.ssoController;
|
|
1085
|
+
}
|
|
1086
|
+
get cache() {
|
|
1087
|
+
return this.cacheController;
|
|
1088
|
+
}
|
|
1089
|
+
};
|
|
1090
|
+
export {
|
|
1091
|
+
ServiceCallLibrary,
|
|
1092
|
+
TYPES
|
|
1093
|
+
};
|
|
1094
|
+
//# sourceMappingURL=index.js.map
|