@rapidrest/core 1.0.1
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/LICENSE +23 -0
- package/README.rst +37 -0
- package/dist/lib/AlertUtils.js +239 -0
- package/dist/lib/AlertUtils.js.map +1 -0
- package/dist/lib/ApiError.js +34 -0
- package/dist/lib/ApiError.js.map +1 -0
- package/dist/lib/ClassLoader.js +159 -0
- package/dist/lib/ClassLoader.js.map +1 -0
- package/dist/lib/FileUtils.js +190 -0
- package/dist/lib/FileUtils.js.map +1 -0
- package/dist/lib/JWTUtils.js +111 -0
- package/dist/lib/JWTUtils.js.map +1 -0
- package/dist/lib/Logger.js +28 -0
- package/dist/lib/Logger.js.map +1 -0
- package/dist/lib/MessagingUtils.js +218 -0
- package/dist/lib/MessagingUtils.js.map +1 -0
- package/dist/lib/NotificationsUtils.js +52 -0
- package/dist/lib/NotificationsUtils.js.map +1 -0
- package/dist/lib/OASUtils.js +207 -0
- package/dist/lib/OASUtils.js.map +1 -0
- package/dist/lib/ObjectFactory.js +302 -0
- package/dist/lib/ObjectFactory.js.map +1 -0
- package/dist/lib/ObjectUtils.js +49 -0
- package/dist/lib/ObjectUtils.js.map +1 -0
- package/dist/lib/StringUtils.js +104 -0
- package/dist/lib/StringUtils.js.map +1 -0
- package/dist/lib/TelemetryUtils.js +159 -0
- package/dist/lib/TelemetryUtils.js.map +1 -0
- package/dist/lib/UserUtils.js +138 -0
- package/dist/lib/UserUtils.js.map +1 -0
- package/dist/lib/ValidationUtils.js +130 -0
- package/dist/lib/ValidationUtils.js.map +1 -0
- package/dist/lib/decorators/ObjectDecorators.js +95 -0
- package/dist/lib/decorators/ObjectDecorators.js.map +1 -0
- package/dist/lib/decorators/index.js +2 -0
- package/dist/lib/decorators/index.js.map +1 -0
- package/dist/lib/index.js +18 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/sleep.js +15 -0
- package/dist/lib/sleep.js.map +1 -0
- package/dist/lib/threads/ThreadLogger.js +43 -0
- package/dist/lib/threads/ThreadLogger.js.map +1 -0
- package/dist/lib/threads/ThreadPool.js +270 -0
- package/dist/lib/threads/ThreadPool.js.map +1 -0
- package/dist/lib/threads/ThreadWorker.js +25 -0
- package/dist/lib/threads/ThreadWorker.js.map +1 -0
- package/dist/lib/threads/ThreadWorkerEntry.js +77 -0
- package/dist/lib/threads/ThreadWorkerEntry.js.map +1 -0
- package/dist/lib/threads/index.js +3 -0
- package/dist/lib/threads/index.js.map +1 -0
- package/dist/types/AlertUtils.d.ts +132 -0
- package/dist/types/ApiError.d.ts +13 -0
- package/dist/types/ClassLoader.d.ts +87 -0
- package/dist/types/FileUtils.d.ts +46 -0
- package/dist/types/JWTUtils.d.ts +139 -0
- package/dist/types/Logger.d.ts +7 -0
- package/dist/types/MessagingUtils.d.ts +77 -0
- package/dist/types/NotificationsUtils.d.ts +32 -0
- package/dist/types/OASUtils.d.ts +54 -0
- package/dist/types/ObjectFactory.d.ts +77 -0
- package/dist/types/ObjectUtils.d.ts +17 -0
- package/dist/types/StringUtils.d.ts +52 -0
- package/dist/types/TelemetryUtils.d.ts +84 -0
- package/dist/types/UserUtils.d.ts +61 -0
- package/dist/types/ValidationUtils.d.ts +66 -0
- package/dist/types/decorators/ObjectDecorators.d.ts +55 -0
- package/dist/types/decorators/index.d.ts +1 -0
- package/dist/types/index.d.ts +17 -0
- package/dist/types/sleep.d.ts +5 -0
- package/dist/types/threads/ThreadLogger.d.ts +15 -0
- package/dist/types/threads/ThreadPool.d.ts +115 -0
- package/dist/types/threads/ThreadWorker.d.ts +41 -0
- package/dist/types/threads/ThreadWorkerEntry.d.ts +1 -0
- package/dist/types/threads/index.d.ts +2 -0
- package/docs/Makefile +20 -0
- package/docs/conf.py +58 -0
- package/docs/index.rst +17 -0
- package/docs/make.bat +35 -0
- package/docs/reference/@rapidrest/namespaces/ObjectDecorators/README.md +21 -0
- package/docs/reference/@rapidrest/namespaces/ObjectDecorators/functions/Config.md +47 -0
- package/docs/reference/@rapidrest/namespaces/ObjectDecorators/functions/Destroy.md +27 -0
- package/docs/reference/@rapidrest/namespaces/ObjectDecorators/functions/Init.md +33 -0
- package/docs/reference/@rapidrest/namespaces/ObjectDecorators/functions/Inject.md +45 -0
- package/docs/reference/@rapidrest/namespaces/ObjectDecorators/functions/Logger.md +27 -0
- package/docs/reference/@rapidrest/namespaces/ObjectDecorators/functions/Nullable.md +27 -0
- package/docs/reference/@rapidrest/namespaces/ObjectDecorators/functions/Validator.md +39 -0
- package/docs/reference/@rapidrest/namespaces/ObjectDecorators/type-aliases/ValidatorFunction.md +31 -0
- package/docs/reference/README.md +73 -0
- package/docs/reference/classes/AlertUtils.md +158 -0
- package/docs/reference/classes/ApiError.md +263 -0
- package/docs/reference/classes/ClassLoader.md +224 -0
- package/docs/reference/classes/Event.md +109 -0
- package/docs/reference/classes/EventUtils.md +123 -0
- package/docs/reference/classes/FileUtils.md +193 -0
- package/docs/reference/classes/JWTUtils.md +91 -0
- package/docs/reference/classes/MessagingUtils.md +145 -0
- package/docs/reference/classes/OASUtils.md +213 -0
- package/docs/reference/classes/ObjectFactory.md +274 -0
- package/docs/reference/classes/ObjectUtils.md +60 -0
- package/docs/reference/classes/StringUtils.md +169 -0
- package/docs/reference/classes/ThreadPool.md +249 -0
- package/docs/reference/classes/ThreadWorker.md +91 -0
- package/docs/reference/classes/UserUtils.md +239 -0
- package/docs/reference/classes/ValidationUtils.md +294 -0
- package/docs/reference/enumerations/AlertPriority.md +61 -0
- package/docs/reference/enumerations/JWTUtilsCompressionMethods.md +21 -0
- package/docs/reference/enumerations/WorkerMessageType.md +43 -0
- package/docs/reference/functions/sleep.md +25 -0
- package/docs/reference/interfaces/Alert.md +101 -0
- package/docs/reference/interfaces/AlertAttachment.md +51 -0
- package/docs/reference/interfaces/AlertClose.md +31 -0
- package/docs/reference/interfaces/AlertUtilsAttachmentOptions.md +42 -0
- package/docs/reference/interfaces/AlertUtilsOptions.md +41 -0
- package/docs/reference/interfaces/InstanceOptions.md +35 -0
- package/docs/reference/interfaces/JWTPayload.md +143 -0
- package/docs/reference/interfaces/JWTUser.md +55 -0
- package/docs/reference/interfaces/JWTUtilsConfig.md +45 -0
- package/docs/reference/interfaces/JWTUtilsPayloadKeyOptions.md +68 -0
- package/docs/reference/interfaces/JWTUtilsPayloadOptions.md +40 -0
- package/docs/reference/interfaces/JWTUtilsPayloadPasswordOptions.md +78 -0
- package/docs/reference/interfaces/NewEvent.md +25 -0
- package/docs/reference/interfaces/OriginSettings.md +25 -0
- package/docs/reference/interfaces/SlackConfig.md +33 -0
- package/docs/reference/interfaces/SmtpAuth.md +25 -0
- package/docs/reference/interfaces/SmtpConfig.md +41 -0
- package/docs/reference/interfaces/Template.md +81 -0
- package/docs/reference/interfaces/TemplateMapBase.md +13 -0
- package/docs/reference/interfaces/TwilioConfig.md +33 -0
- package/docs/reference/interfaces/WorkerMessage.md +31 -0
- package/docs/reference/interfaces/WorkerOptions.md +61 -0
- package/docs/reference/type-aliases/BooleanFunc.md +23 -0
- package/docs/reference/type-aliases/TemplateMap.md +17 -0
- package/docs/reference/type-aliases/WorkerCallback.md +31 -0
- package/docs/reference/variables/Logger.md +21 -0
- package/package.json +96 -0
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2020-2026 Jean-Philippe Steinmetz
|
|
3
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
4
|
+
import child_process from "child_process";
|
|
5
|
+
import fs from "fs";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import { StringUtils } from "./StringUtils.js";
|
|
8
|
+
import { mkdirp } from "mkdirp";
|
|
9
|
+
import { Logger } from "./Logger.js";
|
|
10
|
+
const logger = Logger();
|
|
11
|
+
const readline = require("readline");
|
|
12
|
+
/**
|
|
13
|
+
* Utility functions for working with files.
|
|
14
|
+
* @author Jean-Philippe Steinmetz
|
|
15
|
+
*/
|
|
16
|
+
export class FileUtils {
|
|
17
|
+
/**
|
|
18
|
+
* Attempts to write the provided contents to the file path given. If a file already exists the user is prompted to
|
|
19
|
+
* allow the file to be overwritten or merged. In the case of a merge, srcPath is used as a baseline in order to
|
|
20
|
+
* perform a 3-way merge.
|
|
21
|
+
*
|
|
22
|
+
* @param {string} srcPath The baseline template file to use during a merge.
|
|
23
|
+
* @param {string} outPath The destination file path to be written.
|
|
24
|
+
* @param {any} contents The contents of the file to write.
|
|
25
|
+
* @param {boolean} overwrite Set to `true` to overwite the file and not perform a merge.
|
|
26
|
+
*/
|
|
27
|
+
static async writeFile(srcPath, outPath, contents, overwrite = false) {
|
|
28
|
+
let srcPathFull = path.resolve(srcPath);
|
|
29
|
+
let outPathFull = path.resolve(outPath);
|
|
30
|
+
let fileExists = fs.existsSync(outPathFull);
|
|
31
|
+
// Make sure the path leading to the final destination exists
|
|
32
|
+
let outDirPath = path.dirname(outPath);
|
|
33
|
+
if (!fs.existsSync(outDirPath)) {
|
|
34
|
+
await mkdirp(outDirPath);
|
|
35
|
+
}
|
|
36
|
+
if (fileExists && !overwrite) {
|
|
37
|
+
// Prompt for user action
|
|
38
|
+
let invalidResponse = false;
|
|
39
|
+
while (invalidResponse) {
|
|
40
|
+
let response = await new Promise((resolve, reject) => {
|
|
41
|
+
try {
|
|
42
|
+
readline("Overwrite existing file: " + outPath + "? [Y]es, [N]o, [M]erge: ", (answer) => {
|
|
43
|
+
resolve(answer);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
reject(err);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
response = response.toLocaleLowerCase();
|
|
51
|
+
if (response.length > 0) {
|
|
52
|
+
if (response[0] === "y" || response[0] === "n" || response[0] === "m") {
|
|
53
|
+
if (response[0] === "n") {
|
|
54
|
+
// Immediately exit, no point in continuing
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
overwrite = response[0] === "y";
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
logger.info("Invalid input: " + response);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
logger.info("Invalid input: " + response);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (!fileExists || overwrite) {
|
|
69
|
+
// Write the final output to disk
|
|
70
|
+
logger.info("Writing: " + outPathFull);
|
|
71
|
+
fs.writeFileSync(outPathFull, contents);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
// Attempt to merge the results
|
|
75
|
+
let tmpPath = path.resolve(outPathFull + ".new");
|
|
76
|
+
fs.writeFileSync(tmpPath, contents);
|
|
77
|
+
// Attempt to merge the updated version of the file with the original.
|
|
78
|
+
let mergedPath = path.resolve(outPathFull + ".merged");
|
|
79
|
+
let success = true;
|
|
80
|
+
try {
|
|
81
|
+
let { stdout, stderr } = child_process.exec("kdiff3 " +
|
|
82
|
+
srcPathFull +
|
|
83
|
+
" " +
|
|
84
|
+
outPathFull +
|
|
85
|
+
" " +
|
|
86
|
+
tmpPath +
|
|
87
|
+
' -m --auto --cs "ShowInfoDialogs=0" --cs "LineEndStyle=0" -o ' +
|
|
88
|
+
mergedPath);
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
success = false;
|
|
92
|
+
}
|
|
93
|
+
// Read back in the newly merged file so we can replace write a new generated date
|
|
94
|
+
let merged = fs.readFileSync(mergedPath, "utf-8");
|
|
95
|
+
merged = merged.replace(new RegExp("^// Last Generated.*$", "g"), "// Last Generated: " + new Date());
|
|
96
|
+
// Write the merged copy to the final destination and clean up temporary files
|
|
97
|
+
logger.info("Writing: " + outPathFull);
|
|
98
|
+
fs.writeFileSync(outPathFull, merged);
|
|
99
|
+
fs.unlinkSync(mergedPath);
|
|
100
|
+
fs.unlinkSync(tmpPath);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Generates a copy of the source file at the desired output destination and performs a swap of all values of the
|
|
105
|
+
* variables specified.
|
|
106
|
+
*
|
|
107
|
+
* @param {string} srcPath The source file to copy.
|
|
108
|
+
* @param {string} outPath The destination file to generate.
|
|
109
|
+
* @param {any} variables The map of variable names to values to swap.
|
|
110
|
+
*/
|
|
111
|
+
static async copyFile(srcPath, outPath, variables = {}, overwrite = false) {
|
|
112
|
+
let srcPathFull = path.resolve(srcPath);
|
|
113
|
+
if (!fs.existsSync(srcPathFull)) {
|
|
114
|
+
throw new Error("File does not exist: " + srcPathFull);
|
|
115
|
+
}
|
|
116
|
+
// Make sure the path leading to the final destination exists
|
|
117
|
+
let outDirPath = path.dirname(outPath);
|
|
118
|
+
if (!fs.existsSync(outDirPath)) {
|
|
119
|
+
await mkdirp(outDirPath);
|
|
120
|
+
}
|
|
121
|
+
let template = fs.readFileSync(srcPathFull, "utf-8");
|
|
122
|
+
if (template) {
|
|
123
|
+
let output = StringUtils.findAndReplace(template, variables);
|
|
124
|
+
let outPathFinal = path.resolve(StringUtils.findAndReplace(outPath, variables));
|
|
125
|
+
logger.info("Writing: " + outPathFinal);
|
|
126
|
+
await FileUtils.writeFile(srcPath, outPathFinal, output, overwrite);
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
throw new Error("Failed to read file: " + srcPathFull);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Generates a copy of the source file at the desired output destination using binary copy mode.
|
|
134
|
+
*
|
|
135
|
+
* @param {string} srcPath The source file to copy.
|
|
136
|
+
* @param {string} outPath The destination file to generate.
|
|
137
|
+
* @param {Map<string,string>} variables The map of variable names to values to swap. Applies to outPath only.
|
|
138
|
+
*/
|
|
139
|
+
static async copyBinaryFile(srcPath, outPath, variables = {}) {
|
|
140
|
+
let srcPathFull = path.resolve(srcPath);
|
|
141
|
+
if (!fs.existsSync(srcPathFull)) {
|
|
142
|
+
throw new Error("File does not exist: " + srcPathFull);
|
|
143
|
+
}
|
|
144
|
+
// Make sure the path leading to the final destination exists
|
|
145
|
+
let outDirPath = path.resolve(path.dirname(outPath));
|
|
146
|
+
if (!fs.existsSync(outDirPath)) {
|
|
147
|
+
await mkdirp(outDirPath);
|
|
148
|
+
}
|
|
149
|
+
let outPathFinal = path.resolve(StringUtils.findAndReplace(outPath, variables));
|
|
150
|
+
fs.copyFileSync(srcPathFull, outPathFinal);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Performs a deep copy of a directory tree at the given srcPath to the specified output directory. Performs
|
|
154
|
+
* template replacement for all variables given and skips any files in the specified filter.
|
|
155
|
+
*
|
|
156
|
+
* @param {string} srcPath The path to the source directory to copy files from.
|
|
157
|
+
* @param {string} outPath The path to the destination directory to copy files to.
|
|
158
|
+
* @param {any} vars The map of template variables to perform replacement on.
|
|
159
|
+
* @param {array} excludeFilters The list of file extension filters to exclude during the copy process.
|
|
160
|
+
* @param {array} binaryFilters The list of file extension filters to copy as binary only.
|
|
161
|
+
* @param {boolean} force Set to `true` to force writing over any existing files.
|
|
162
|
+
*/
|
|
163
|
+
static async copyDirectory(srcPath, outPath, vars = {}, excludeFilters = [], binaryFilters = [], force = false) {
|
|
164
|
+
const templatePath = path.resolve(srcPath);
|
|
165
|
+
let files = fs.readdirSync(templatePath, { withFileTypes: true });
|
|
166
|
+
files.forEach(async (file) => {
|
|
167
|
+
let extension = path.extname(file.name);
|
|
168
|
+
if (!extension) {
|
|
169
|
+
extension = file.name;
|
|
170
|
+
}
|
|
171
|
+
extension = extension.replace(".", "");
|
|
172
|
+
if (excludeFilters.indexOf(extension) === -1) {
|
|
173
|
+
let destPath = StringUtils.findAndReplace(path.join(outPath, file.name), vars);
|
|
174
|
+
if (file.isDirectory()) {
|
|
175
|
+
if (!fs.existsSync(destPath)) {
|
|
176
|
+
fs.mkdirSync(destPath);
|
|
177
|
+
}
|
|
178
|
+
await FileUtils.copyDirectory(path.join(templatePath, file.name), destPath, vars, excludeFilters, binaryFilters, force);
|
|
179
|
+
}
|
|
180
|
+
else if (binaryFilters.indexOf(extension) >= 0) {
|
|
181
|
+
await FileUtils.copyBinaryFile(path.join(templatePath, file.name), destPath, vars);
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
await FileUtils.copyFile(path.join(templatePath, file.name), destPath, vars, force);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=FileUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileUtils.js","sourceRoot":"","sources":["../../src/FileUtils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2020-2026 Jean-Philippe Steinmetz
|
|
3
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
4
|
+
import crypto from "crypto";
|
|
5
|
+
import jwt from "jsonwebtoken";
|
|
6
|
+
import zlib from "zlib";
|
|
7
|
+
/**
|
|
8
|
+
* Describes the different types of support compression methods for JWT payloads.
|
|
9
|
+
*/
|
|
10
|
+
export var JWTUtilsCompressionMethods;
|
|
11
|
+
(function (JWTUtilsCompressionMethods) {
|
|
12
|
+
/** Uses the zlib compression method. */
|
|
13
|
+
JWTUtilsCompressionMethods["ZLIB"] = "zlib";
|
|
14
|
+
})(JWTUtilsCompressionMethods || (JWTUtilsCompressionMethods = {}));
|
|
15
|
+
/**
|
|
16
|
+
* Utility class for working with Json Web Token (JWT) authentication tokens.
|
|
17
|
+
*
|
|
18
|
+
* @author Jean-Philippe Steinmetz <rapidrests@gmail.com>
|
|
19
|
+
*/
|
|
20
|
+
export class JWTUtils {
|
|
21
|
+
/**
|
|
22
|
+
* Generates a new JWT token for the given config and user object. The user object must be a valid RapidREST
|
|
23
|
+
* user.
|
|
24
|
+
*
|
|
25
|
+
* @param config The JWT configuration to use when generating the token.
|
|
26
|
+
* @param user The user to encode into the token's payload.
|
|
27
|
+
* @param data Additional data to include the token's payload.
|
|
28
|
+
*/
|
|
29
|
+
static createToken(config, user, data) {
|
|
30
|
+
// Validate the required config options
|
|
31
|
+
if (!config.secret) {
|
|
32
|
+
throw new Error("Invalid configuration provided.");
|
|
33
|
+
}
|
|
34
|
+
// Validate the user object
|
|
35
|
+
if (!user || !user.uid) {
|
|
36
|
+
throw new Error("Invalid or null user object provided.");
|
|
37
|
+
}
|
|
38
|
+
let payload = { profile: JSON.stringify(user), ...data };
|
|
39
|
+
// Encrypt the profile if desired
|
|
40
|
+
if (config.payload && config.payload.encrypt) {
|
|
41
|
+
const payloadOptions = config.payload;
|
|
42
|
+
if (payloadOptions.private_key) {
|
|
43
|
+
const keyOptions = payloadOptions;
|
|
44
|
+
const encrypted = crypto.privateEncrypt(keyOptions.private_key, Buffer.from(payload.profile));
|
|
45
|
+
payload.profile = encrypted.toString("base64");
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
const pwOtions = payloadOptions;
|
|
49
|
+
const iv = Buffer.from(pwOtions.iv);
|
|
50
|
+
const key = crypto.scryptSync(pwOtions.password, "salt", 24);
|
|
51
|
+
const cipher = crypto.createCipheriv(pwOtions.algorithm, key, iv);
|
|
52
|
+
let encrypted = cipher.update(payload.profile, "utf8", "base64");
|
|
53
|
+
encrypted += cipher.final("base64");
|
|
54
|
+
payload.profile = encrypted;
|
|
55
|
+
}
|
|
56
|
+
payload.encryption = true;
|
|
57
|
+
}
|
|
58
|
+
// Compress the profile if desired
|
|
59
|
+
if (config.payload && config.payload.compress) {
|
|
60
|
+
if (config.payload.compress === JWTUtilsCompressionMethods.ZLIB) {
|
|
61
|
+
const buf = Buffer.from(payload.profile, "utf-8");
|
|
62
|
+
payload.profile = zlib.gzipSync(buf).toString("base64");
|
|
63
|
+
payload.compression = "zlib";
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return jwt.sign(payload, config.secret, config.options);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Decodes the given JWT authentication token using the provided configuration. If the token is not valid an
|
|
70
|
+
* error is thrown with the reason. Returns the encoded user object payload upon success.
|
|
71
|
+
*
|
|
72
|
+
* @param config The JWT configuration to use when validating the token.
|
|
73
|
+
* @param token The JWT token to validate.
|
|
74
|
+
* @returns The data encoded in the token's payload.
|
|
75
|
+
*/
|
|
76
|
+
static decodeToken(config, token) {
|
|
77
|
+
// Decode the token
|
|
78
|
+
let payload = jwt.verify(token, config.secret, config.options);
|
|
79
|
+
// Validate the payload
|
|
80
|
+
if (!payload || !payload.profile) {
|
|
81
|
+
throw new Error("Token is invalid or missing data.");
|
|
82
|
+
}
|
|
83
|
+
// Decompress the payload if desired
|
|
84
|
+
if (payload.compression === JWTUtilsCompressionMethods.ZLIB) {
|
|
85
|
+
const buf = Buffer.from(payload.profile, "base64");
|
|
86
|
+
payload.profile = zlib.gunzipSync(buf).toString("utf-8");
|
|
87
|
+
}
|
|
88
|
+
// Decrypt the payload if desired
|
|
89
|
+
if (payload.encryption && config.payload && config.payload.encrypt) {
|
|
90
|
+
const payloadOptions = config.payload;
|
|
91
|
+
if (payloadOptions.private_key) {
|
|
92
|
+
const keyOptions = payloadOptions;
|
|
93
|
+
const decrypted = crypto.privateDecrypt(keyOptions.private_key, Buffer.from(payload.profile));
|
|
94
|
+
payload.profile = decrypted.toString("utf8");
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
const pwOtions = payloadOptions;
|
|
98
|
+
const iv = Buffer.from(payloadOptions.iv);
|
|
99
|
+
const key = crypto.scryptSync(payloadOptions.password, "salt", 24);
|
|
100
|
+
const decipher = crypto.createDecipheriv(payloadOptions.algorithm, key, iv);
|
|
101
|
+
let decrypted = decipher.update(payload.profile, "base64", "utf8");
|
|
102
|
+
decrypted += decipher.final("utf8");
|
|
103
|
+
payload.profile = decrypted;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// Make sure the profile is an parsed
|
|
107
|
+
payload.profile = JSON.parse(payload.profile);
|
|
108
|
+
return payload;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=JWTUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"JWTUtils.js","sourceRoot":"","sources":["../../src/JWTUtils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2020-2026 Jean-Philippe Steinmetz
|
|
3
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
4
|
+
const winston = require("winston");
|
|
5
|
+
const { format, transports } = winston;
|
|
6
|
+
const { combine, timestamp, printf } = format;
|
|
7
|
+
const logFormat = printf((info) => {
|
|
8
|
+
return `${info.timestamp} ${info.level}: ${info.message}`;
|
|
9
|
+
});
|
|
10
|
+
/**
|
|
11
|
+
* Creates a new logger with the specified level and file name to output logs to.
|
|
12
|
+
*
|
|
13
|
+
* @param level The logging level to create the logger with.
|
|
14
|
+
* @param file The name (without an extension) of the file to output logs to.
|
|
15
|
+
*/
|
|
16
|
+
export const Logger = function (level = "debug", file = undefined) {
|
|
17
|
+
const transport = [new transports.Console()];
|
|
18
|
+
if (file) {
|
|
19
|
+
transport.push(new winston.transports.File({ filename: file + "error.log", level: "error" }));
|
|
20
|
+
transport.push(new winston.transports.File({ filename: file + ".log" }));
|
|
21
|
+
}
|
|
22
|
+
return winston.createLogger({
|
|
23
|
+
level,
|
|
24
|
+
format: combine(format.splat(), format.simple(), format.colorize(), timestamp(), logFormat),
|
|
25
|
+
transports: transport,
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=Logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Logger.js","sourceRoot":"","sources":["../../src/Logger.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,kDAAkD;AAClD,+EAA+E;AAC/E,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;AACnC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC;AACvC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;AAC9C,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,IAAS,EAAE,EAAE;IACnC,OAAO,GAAG,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC;AAC9D,CAAC,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,MAAM,GAAQ,UAAS,QAAgB,OAAO,EAAE,OAA2B,SAAS;IAC7F,MAAM,SAAS,GAAU,CAAC,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC;IACpD,IAAI,IAAI,EAAE,CAAC;QACP,SAAS,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,GAAG,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;QAC9F,SAAS,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,GAAG,MAAM,EAAE,CAAC,CAAC,CAAC;IAC7E,CAAC;IAED,OAAO,OAAO,CAAC,YAAY,CAAC;QACxB,KAAK;QACL,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE,MAAM,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,EAAE,SAAS,CAAC;QAC3F,UAAU,EAAE,SAAS;KACxB,CAAC,CAAC;AACP,CAAC,CAAC"}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
11
|
+
// Copyright (C) 2020-2026 Jean-Philippe Steinmetz
|
|
12
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
13
|
+
import handlebars from "handlebars";
|
|
14
|
+
import { Config, Init, Logger } from "./decorators/ObjectDecorators.js";
|
|
15
|
+
/**
|
|
16
|
+
* Simple utility class for sending templated messages via e-mail, SMS and more.
|
|
17
|
+
*/
|
|
18
|
+
export class MessagingUtils {
|
|
19
|
+
slackApps = [];
|
|
20
|
+
slackConfigs = [];
|
|
21
|
+
smtpConfig;
|
|
22
|
+
twilio;
|
|
23
|
+
twilioConfig = null;
|
|
24
|
+
templates = {};
|
|
25
|
+
logger;
|
|
26
|
+
async init() {
|
|
27
|
+
if (this.slackConfigs.length > 0) {
|
|
28
|
+
try {
|
|
29
|
+
const { App } = await import("@slack/bolt");
|
|
30
|
+
if (!App) {
|
|
31
|
+
throw new Error("Failed to import @slack/bolt. Did you add it to your project?");
|
|
32
|
+
}
|
|
33
|
+
for (const slackConfig of this.slackConfigs) {
|
|
34
|
+
if (!slackConfig.token || !slackConfig.signingSecret) {
|
|
35
|
+
throw new Error("Slack token or signingSecret is not set.");
|
|
36
|
+
}
|
|
37
|
+
const app = new App({
|
|
38
|
+
token: slackConfig.token,
|
|
39
|
+
signingSecret: slackConfig.signingSecret,
|
|
40
|
+
});
|
|
41
|
+
this.slackApps.push(app);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
this.logger?.error("Unable to setup slack notifications");
|
|
46
|
+
this.logger?.debug(error);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (this.smtpConfig) {
|
|
50
|
+
try {
|
|
51
|
+
const nodemailer = await import("nodemailer");
|
|
52
|
+
if (!nodemailer) {
|
|
53
|
+
throw new Error("Failed to import nodemailer. Did you add it to your project?");
|
|
54
|
+
}
|
|
55
|
+
if (!this.smtpConfig.host) {
|
|
56
|
+
throw new Error("No host specified in SMTP configuration.");
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
this.logger?.error("Unable to setup email notifications");
|
|
61
|
+
this.logger?.debug(error);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (this.twilioConfig) {
|
|
65
|
+
try {
|
|
66
|
+
if (!this.twilioConfig.accountSid || !this.twilioConfig.token) {
|
|
67
|
+
throw new Error("Twilio accountSid or token is not set.");
|
|
68
|
+
}
|
|
69
|
+
const twilio = await import("twilio");
|
|
70
|
+
if (!twilio) {
|
|
71
|
+
throw new Error("Failed to import twilio. Did you add it to your project?");
|
|
72
|
+
}
|
|
73
|
+
this.twilio = twilio(this.twilioConfig.accountSid, this.twilioConfig.token, this.twilioConfig.options);
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
this.logger?.error("Unable to setup twilio notifications");
|
|
77
|
+
this.logger?.debug(error);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Sends an email using the given template name and variables.
|
|
83
|
+
* @param templateName The name of the email template to send.
|
|
84
|
+
* @param templateVars The map of variables to inject into the template.
|
|
85
|
+
* @param options The map of additional options to pass into the sendMail function.
|
|
86
|
+
* @returns
|
|
87
|
+
*/
|
|
88
|
+
async sendEmail(templateName, templateVars, options = {}) {
|
|
89
|
+
if (!this.smtpConfig) {
|
|
90
|
+
throw new Error("E-mail is not configured.");
|
|
91
|
+
}
|
|
92
|
+
if (!this.templates[templateName]) {
|
|
93
|
+
throw new Error(`No template found with name ${templateName}`);
|
|
94
|
+
}
|
|
95
|
+
const tplConfig = this.templates[templateName];
|
|
96
|
+
if (!tplConfig.enabled || !tplConfig.subject) {
|
|
97
|
+
return undefined;
|
|
98
|
+
}
|
|
99
|
+
// Create the plain text template
|
|
100
|
+
let message = null;
|
|
101
|
+
if (tplConfig.text) {
|
|
102
|
+
const template = handlebars.compile(tplConfig.text);
|
|
103
|
+
message = template(templateVars);
|
|
104
|
+
}
|
|
105
|
+
// Create the HTML template
|
|
106
|
+
let htmlMessage = null;
|
|
107
|
+
if (tplConfig.html) {
|
|
108
|
+
const template = handlebars.compile(tplConfig.html);
|
|
109
|
+
htmlMessage = template(templateVars);
|
|
110
|
+
}
|
|
111
|
+
const subjectTemplate = handlebars.compile(tplConfig.subject);
|
|
112
|
+
const subject = subjectTemplate(templateVars);
|
|
113
|
+
// Send the e-mail to the user
|
|
114
|
+
const nodemailer = await import("nodemailer");
|
|
115
|
+
const transporter = nodemailer.createTransport(this.smtpConfig);
|
|
116
|
+
if (!this.templates?.from?.email) {
|
|
117
|
+
this.logger?.warn("Unable to send email missing from.email in message template");
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
const result = await transporter.sendMail({
|
|
121
|
+
from: this.templates.from.email,
|
|
122
|
+
...tplConfig.email_options,
|
|
123
|
+
...options,
|
|
124
|
+
subject,
|
|
125
|
+
text: message,
|
|
126
|
+
html: htmlMessage,
|
|
127
|
+
});
|
|
128
|
+
return result;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Sends an Slack message using the given template name and variables.
|
|
132
|
+
* @param templateName The name of the Slack template to send.
|
|
133
|
+
* @param templateVars The map of variables to inject into the template.
|
|
134
|
+
* @returns
|
|
135
|
+
*/
|
|
136
|
+
async sendSlack(templateName, templateVars) {
|
|
137
|
+
if (this.slackApps.length === 0) {
|
|
138
|
+
throw new Error("Slack is not configured.");
|
|
139
|
+
}
|
|
140
|
+
if (!this.templates[templateName]) {
|
|
141
|
+
throw new Error(`No template found with name ${templateName}`);
|
|
142
|
+
}
|
|
143
|
+
const tplConfig = this.templates[templateName];
|
|
144
|
+
if (!tplConfig.enabled || !tplConfig.slack_channel || !tplConfig.slack_text) {
|
|
145
|
+
return undefined;
|
|
146
|
+
}
|
|
147
|
+
// Create the sms template
|
|
148
|
+
const template = handlebars.compile(tplConfig.slack_text);
|
|
149
|
+
const message = template(templateVars);
|
|
150
|
+
const result = [];
|
|
151
|
+
// Send the slack message to the desired channel
|
|
152
|
+
for (const app of this.slackApps) {
|
|
153
|
+
const res = await app.client.chat.postMessage({
|
|
154
|
+
channel: tplConfig.slack_channel,
|
|
155
|
+
text: message,
|
|
156
|
+
});
|
|
157
|
+
result.push(res);
|
|
158
|
+
}
|
|
159
|
+
return result;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Sends an SMS using the given template name and variables.
|
|
163
|
+
* @param templateName The name of the SMS template to send.
|
|
164
|
+
* @param templateVars The map of variables to inject into the template.
|
|
165
|
+
* @param options The map of additional options to pass into the sendMail function.
|
|
166
|
+
* @returns
|
|
167
|
+
*/
|
|
168
|
+
async sendSMS(templateName, templateVars, options = {}) {
|
|
169
|
+
if (!this.twilio) {
|
|
170
|
+
throw new Error("Twilio is not configured.");
|
|
171
|
+
}
|
|
172
|
+
if (!this.templates[templateName]) {
|
|
173
|
+
throw new Error(`No template found with name ${templateName}`);
|
|
174
|
+
}
|
|
175
|
+
const tplConfig = this.templates[templateName];
|
|
176
|
+
if (!tplConfig.enabled || !tplConfig.sms) {
|
|
177
|
+
return undefined;
|
|
178
|
+
}
|
|
179
|
+
// Create the sms template
|
|
180
|
+
const template = handlebars.compile(tplConfig.sms);
|
|
181
|
+
const message = template(templateVars);
|
|
182
|
+
// Send the message to the user
|
|
183
|
+
const result = await this.twilio.messages.create({
|
|
184
|
+
from: this.templates.from.sms,
|
|
185
|
+
...tplConfig.sms_options,
|
|
186
|
+
...options,
|
|
187
|
+
body: message,
|
|
188
|
+
});
|
|
189
|
+
return result;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
__decorate([
|
|
193
|
+
Config("slack", []),
|
|
194
|
+
__metadata("design:type", Array)
|
|
195
|
+
], MessagingUtils.prototype, "slackConfigs", void 0);
|
|
196
|
+
__decorate([
|
|
197
|
+
Config("smtp_config", null),
|
|
198
|
+
__metadata("design:type", Object)
|
|
199
|
+
], MessagingUtils.prototype, "smtpConfig", void 0);
|
|
200
|
+
__decorate([
|
|
201
|
+
Config("twilio", null),
|
|
202
|
+
__metadata("design:type", Object)
|
|
203
|
+
], MessagingUtils.prototype, "twilioConfig", void 0);
|
|
204
|
+
__decorate([
|
|
205
|
+
Config("message_templates", {}),
|
|
206
|
+
__metadata("design:type", Object)
|
|
207
|
+
], MessagingUtils.prototype, "templates", void 0);
|
|
208
|
+
__decorate([
|
|
209
|
+
Logger,
|
|
210
|
+
__metadata("design:type", Object)
|
|
211
|
+
], MessagingUtils.prototype, "logger", void 0);
|
|
212
|
+
__decorate([
|
|
213
|
+
Init,
|
|
214
|
+
__metadata("design:type", Function),
|
|
215
|
+
__metadata("design:paramtypes", []),
|
|
216
|
+
__metadata("design:returntype", Promise)
|
|
217
|
+
], MessagingUtils.prototype, "init", null);
|
|
218
|
+
//# sourceMappingURL=MessagingUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MessagingUtils.js","sourceRoot":"","sources":["../../src/MessagingUtils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2020-2026 Jean-Philippe Steinmetz
|
|
3
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
4
|
+
/**
|
|
5
|
+
* Utility functions for sending push notifications to registered clients.
|
|
6
|
+
*
|
|
7
|
+
* @author Jean-Philippe Steinmetz
|
|
8
|
+
*/
|
|
9
|
+
export class NotificationUtils {
|
|
10
|
+
/** The redis client to use for broadcasting messages. */
|
|
11
|
+
redis;
|
|
12
|
+
/**
|
|
13
|
+
* Initializes the utility using the given redis connection.
|
|
14
|
+
*
|
|
15
|
+
* @param {any} redis The redis connection to publish to.
|
|
16
|
+
*/
|
|
17
|
+
constructor(redis) {
|
|
18
|
+
if (!redis) {
|
|
19
|
+
throw new Error("redis argument is required.");
|
|
20
|
+
}
|
|
21
|
+
this.redis = redis;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Broadcasts a given message to all users.
|
|
25
|
+
*
|
|
26
|
+
* @param {any} type The type of message being sent.
|
|
27
|
+
* @param {string} action The action performed on the data (if applicable).
|
|
28
|
+
* @param {string} data The contents of the message to send.
|
|
29
|
+
*/
|
|
30
|
+
broadcastMessage(type, action, data) {
|
|
31
|
+
void this.redis?.publish("allusers", JSON.stringify({ type, action, data }));
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Sends a given message to the room or user with the specified uid(s).
|
|
35
|
+
*
|
|
36
|
+
* @param {string} uids The universally unique identifier of the room or user to send the message to.
|
|
37
|
+
* @param {string} type The type of message being sent.
|
|
38
|
+
* @param {string} action The action performed on the data (if applicable).
|
|
39
|
+
* @param {string} data The contents of the message to send to the room or user.
|
|
40
|
+
*/
|
|
41
|
+
sendMessage(uids, type, action, data) {
|
|
42
|
+
if (Array.isArray(uids)) {
|
|
43
|
+
for (const uid of uids) {
|
|
44
|
+
void this.redis?.publish(uid, JSON.stringify({ type, action, data }));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
void this.redis?.publish(uids, JSON.stringify({ type, action, data }));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=NotificationsUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NotificationsUtils.js","sourceRoot":"","sources":["../../src/NotificationsUtils.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,kDAAkD;AAClD,+EAA+E;AAC/E;;;;GAIG;AACH,MAAM,OAAO,iBAAiB;IAC1B,yDAAyD;IACjD,KAAK,CAAM;IAEnB;;;;OAIG;IACH,YAAY,KAAU;QAClB,IAAI,CAAC,KAAK,EAAE,CAAC;YACT,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACnD,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACvB,CAAC;IAED;;;;;;OAMG;IACI,gBAAgB,CAAC,IAAS,EAAE,MAAc,EAAE,IAAS;QACxD,KAAK,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACjF,CAAC;IAED;;;;;;;OAOG;IACI,WAAW,CAAC,IAAuB,EAAE,IAAY,EAAE,MAAc,EAAE,IAAS;QAC/E,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACtB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACrB,KAAK,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YAC1E,CAAC;QACL,CAAC;aAAM,CAAC;YACJ,KAAK,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAC3E,CAAC;IACL,CAAC;CACJ"}
|