@rapidrest/core 1.14.0 → 2.0.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/lib/AlertUtils.js +71 -56
- package/dist/lib/AlertUtils.js.map +1 -1
- package/dist/lib/ApiError.js +8 -1
- package/dist/lib/ApiError.js.map +1 -1
- package/dist/lib/CacheUtils.js +23 -0
- package/dist/lib/CacheUtils.js.map +1 -0
- package/dist/lib/ClassLoader.js +48 -44
- package/dist/lib/ClassLoader.js.map +1 -1
- package/dist/lib/FileUtils.js +133 -60
- package/dist/lib/FileUtils.js.map +1 -1
- package/dist/lib/JWTUtils.js +250 -145
- package/dist/lib/JWTUtils.js.map +1 -1
- package/dist/lib/Logger.js +39 -7
- package/dist/lib/Logger.js.map +1 -1
- package/dist/lib/MemoryStore.js +8 -6
- package/dist/lib/MemoryStore.js.map +1 -1
- package/dist/lib/MessagingUtils.js +71 -35
- package/dist/lib/MessagingUtils.js.map +1 -1
- package/dist/lib/NotificationsUtils.js +60 -8
- package/dist/lib/NotificationsUtils.js.map +1 -1
- package/dist/lib/OASUtils.js +67 -18
- package/dist/lib/OASUtils.js.map +1 -1
- package/dist/lib/ObjectFactory.js +151 -63
- package/dist/lib/ObjectFactory.js.map +1 -1
- package/dist/lib/ObjectUtils.js +48 -7
- package/dist/lib/ObjectUtils.js.map +1 -1
- package/dist/lib/StringUtils.js +55 -21
- package/dist/lib/StringUtils.js.map +1 -1
- package/dist/lib/TelemetryUtils.js +41 -5
- package/dist/lib/TelemetryUtils.js.map +1 -1
- package/dist/lib/UserUtils.js +5 -6
- package/dist/lib/UserUtils.js.map +1 -1
- package/dist/lib/ValidationUtils.js +16 -4
- package/dist/lib/ValidationUtils.js.map +1 -1
- package/dist/lib/index.js +2 -0
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/threads/ThreadPool.js +198 -58
- package/dist/lib/threads/ThreadPool.js.map +1 -1
- package/dist/types/AlertUtils.d.ts +4 -0
- package/dist/types/CacheUtils.d.ts +14 -0
- package/dist/types/ClassLoader.d.ts +10 -0
- package/dist/types/FileUtils.d.ts +23 -7
- package/dist/types/JWTUtils.d.ts +88 -18
- package/dist/types/MessagingUtils.d.ts +7 -1
- package/dist/types/NotificationsUtils.d.ts +30 -0
- package/dist/types/ObjectFactory.d.ts +25 -1
- package/dist/types/ObjectUtils.d.ts +14 -0
- package/dist/types/StringUtils.d.ts +8 -0
- package/dist/types/TelemetryUtils.d.ts +19 -1
- package/dist/types/ValidationUtils.d.ts +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/threads/ThreadPool.d.ts +34 -2
- package/package.json +1 -1
package/dist/lib/FileUtils.js
CHANGED
|
@@ -13,20 +13,56 @@ const logger = Logger();
|
|
|
13
13
|
*/
|
|
14
14
|
export class FileUtils {
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
* Determines if the provided path exists on the filesystem.
|
|
17
|
+
*/
|
|
18
|
+
static async exists(target) {
|
|
19
|
+
try {
|
|
20
|
+
await fs.promises.access(target);
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Throws an error if `target` is not contained within `rootDir`. Used to prevent path traversal (e.g. `../`)
|
|
29
|
+
* from escaping an intended root when a caller opts in by providing `rootDir`.
|
|
30
|
+
*
|
|
31
|
+
* Both `rootDir` and the longest already-existing ancestor of `target` are resolved via `fs.promises.realpath`
|
|
32
|
+
* before the containment check, not just `path.resolve`. Without this, a symlink placed anywhere on disk
|
|
33
|
+
* within `target`'s existing ancestry (including `target` itself) that points outside `rootDir` would pass
|
|
34
|
+
* a purely lexical check, yet `fs.existsSync`/`fs.writeFileSync`/`fs.readFileSync` etc. would transparently
|
|
35
|
+
* follow it - defeating the containment guarantee entirely. Any remaining (not-yet-existing) trailing path
|
|
36
|
+
* segments can't be symlinks yet, so they're safely appended as literal strings.
|
|
19
37
|
*
|
|
20
|
-
* @param {string} rootDir The directory that `target` must be contained within.
|
|
21
|
-
* @param {string} target The
|
|
38
|
+
* @param {string} rootDir The directory that `target` must be contained within. Must exist.
|
|
39
|
+
* @param {string} target The path to verify.
|
|
40
|
+
* @returns The fully resolved (existing-portion realpath'd) path. Callers should use this value - not the
|
|
41
|
+
* original `target` - for the actual filesystem operation, so a symlink swapped in after this check can't
|
|
42
|
+
* reintroduce the gap it closes.
|
|
22
43
|
*/
|
|
23
|
-
static assertContained(rootDir, target) {
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
const
|
|
44
|
+
static async assertContained(rootDir, target) {
|
|
45
|
+
const rootReal = await fs.promises.realpath(path.resolve(rootDir));
|
|
46
|
+
let existingPart = path.resolve(target);
|
|
47
|
+
const remainder = [];
|
|
48
|
+
while (!(await FileUtils.exists(existingPart))) {
|
|
49
|
+
const parent = path.dirname(existingPart);
|
|
50
|
+
// `path.dirname()` of a filesystem root returns that same root, which is the only way this loop
|
|
51
|
+
// could otherwise become infinite. Not practically reachable in a real filesystem (the root itself
|
|
52
|
+
// always exists), so this is defense-in-depth rather than an expected/tested case.
|
|
53
|
+
/* v8 ignore next */
|
|
54
|
+
if (parent === existingPart)
|
|
55
|
+
break;
|
|
56
|
+
remainder.unshift(path.basename(existingPart));
|
|
57
|
+
existingPart = parent;
|
|
58
|
+
}
|
|
59
|
+
const existingReal = await fs.promises.realpath(existingPart);
|
|
60
|
+
const targetReal = remainder.length > 0 ? path.join(existingReal, ...remainder) : existingReal;
|
|
61
|
+
const rel = path.relative(rootReal, targetReal);
|
|
27
62
|
if (rel !== "" && (rel.startsWith("..") || path.isAbsolute(rel))) {
|
|
28
|
-
throw new Error(`Path "${target}" escapes the allowed root directory "${
|
|
63
|
+
throw new Error(`Path "${target}" escapes the allowed root directory "${rootReal}".`);
|
|
29
64
|
}
|
|
65
|
+
return targetReal;
|
|
30
66
|
}
|
|
31
67
|
/**
|
|
32
68
|
* Attempts to write the provided contents to the file path given. If a file already exists at the destination
|
|
@@ -44,21 +80,28 @@ export class FileUtils {
|
|
|
44
80
|
let srcPathFull = path.resolve(srcPath);
|
|
45
81
|
let outPathFull = path.resolve(outPath);
|
|
46
82
|
if (rootDir) {
|
|
47
|
-
FileUtils.assertContained(rootDir, srcPathFull);
|
|
48
|
-
FileUtils.assertContained(rootDir, outPathFull);
|
|
83
|
+
await FileUtils.assertContained(rootDir, srcPathFull);
|
|
84
|
+
outPathFull = await FileUtils.assertContained(rootDir, outPathFull);
|
|
49
85
|
}
|
|
50
|
-
let fileExists = fs.existsSync(outPathFull);
|
|
51
86
|
// Make sure the path leading to the final destination exists
|
|
52
|
-
let outDirPath = path.dirname(
|
|
53
|
-
if (!
|
|
87
|
+
let outDirPath = path.dirname(outPathFull);
|
|
88
|
+
if (!(await FileUtils.exists(outDirPath))) {
|
|
54
89
|
await mkdirp(outDirPath);
|
|
55
90
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
//
|
|
91
|
+
// Write the final output to disk. When `overwrite` is `false`, the exclusive `"wx"` flag makes the
|
|
92
|
+
// existence check and the write atomic - `fs.existsSync()` followed by a plain write would otherwise
|
|
93
|
+
// leave a window where two concurrent calls both see no existing file and one silently clobbers the
|
|
94
|
+
// other's output.
|
|
60
95
|
logger.info("Writing: " + outPathFull);
|
|
61
|
-
|
|
96
|
+
try {
|
|
97
|
+
await fs.promises.writeFile(outPathFull, contents, overwrite ? undefined : { flag: "wx" });
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
if (!overwrite && err?.code === "EEXIST") {
|
|
101
|
+
throw new Error(`File already exists at "${outPathFull}". Pass overwrite=true to replace it.`);
|
|
102
|
+
}
|
|
103
|
+
throw err;
|
|
104
|
+
}
|
|
62
105
|
}
|
|
63
106
|
/**
|
|
64
107
|
* Generates a copy of the source file at the desired output destination and performs a swap of all values of the
|
|
@@ -72,28 +115,25 @@ export class FileUtils {
|
|
|
72
115
|
* within this directory, otherwise an error is thrown.
|
|
73
116
|
*/
|
|
74
117
|
static async copyFile(srcPath, outPath, variables = {}, overwrite = false, rootDir) {
|
|
118
|
+
variables = variables ?? {};
|
|
75
119
|
let srcPathFull = path.resolve(srcPath);
|
|
120
|
+
// Containment is checked *before* existence: assertContained() already tolerates a not-yet-existing
|
|
121
|
+
// target (it walks up to the nearest existing ancestor), so checking existence first would let a path
|
|
122
|
+
// outside rootDir get a different error ("File does not exist") depending on whether it happens to
|
|
123
|
+
// exist on disk - a file-existence oracle for paths the caller is supposed to be sandboxed away from.
|
|
76
124
|
if (rootDir) {
|
|
77
|
-
|
|
125
|
+
// Re-resolved via the realpath'd return value so the subsequent read follows the *validated* path
|
|
126
|
+
// rather than the original (potentially symlinked) one.
|
|
127
|
+
srcPathFull = await FileUtils.assertContained(rootDir, srcPathFull);
|
|
78
128
|
}
|
|
79
|
-
if (!
|
|
129
|
+
if (!(await FileUtils.exists(srcPathFull))) {
|
|
80
130
|
throw new Error("File does not exist: " + srcPathFull);
|
|
81
131
|
}
|
|
82
|
-
|
|
83
|
-
let
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
let template = fs.readFileSync(srcPathFull, "utf-8");
|
|
88
|
-
if (template) {
|
|
89
|
-
let output = StringUtils.findAndReplace(template, variables);
|
|
90
|
-
let outPathFinal = path.resolve(StringUtils.findAndReplace(outPath, variables));
|
|
91
|
-
logger.info("Writing: " + outPathFinal);
|
|
92
|
-
await FileUtils.writeFile(srcPath, outPathFinal, output, overwrite, rootDir);
|
|
93
|
-
}
|
|
94
|
-
else {
|
|
95
|
-
throw new Error("Failed to read file: " + srcPathFull);
|
|
96
|
-
}
|
|
132
|
+
let template = await fs.promises.readFile(srcPathFull, "utf-8");
|
|
133
|
+
let output = StringUtils.findAndReplace(template, variables);
|
|
134
|
+
let outPathFinal = path.resolve(StringUtils.findAndReplace(outPath, variables));
|
|
135
|
+
logger.info("Writing: " + outPathFinal);
|
|
136
|
+
await FileUtils.writeFile(srcPath, outPathFinal, output, overwrite, rootDir);
|
|
97
137
|
}
|
|
98
138
|
/**
|
|
99
139
|
* Generates a copy of the source file at the desired output destination using binary copy mode.
|
|
@@ -103,25 +143,55 @@ export class FileUtils {
|
|
|
103
143
|
* @param {Map<string,string>} variables The map of variable names to values to swap. Applies to outPath only.
|
|
104
144
|
* @param {string} rootDir Optional. When provided, all resolved source and destination paths must be contained
|
|
105
145
|
* within this directory, otherwise an error is thrown.
|
|
146
|
+
* @param {boolean} overwrite Set to `true` to overwrite an existing file at the destination. Default is `false`,
|
|
147
|
+
* matching the behavior of `writeFile`/`copyFile`. Appended after `rootDir` to preserve the existing positional
|
|
148
|
+
* call signature - note this is the opposite order from `copyFile`'s `(overwrite, rootDir)`.
|
|
106
149
|
*/
|
|
107
|
-
static async copyBinaryFile(srcPath, outPath, variables = {}, rootDir) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
150
|
+
static async copyBinaryFile(srcPath, outPath, variables = {}, rootDir, overwrite = false) {
|
|
151
|
+
// `copyBinaryFile`'s `(rootDir, overwrite)` parameter order is the reverse of `copyFile`'s
|
|
152
|
+
// `(overwrite, rootDir)`. A caller that swaps them by analogy with `copyFile` would otherwise either
|
|
153
|
+
// silently disable overwrite protection (a boolean passed where `rootDir` is expected is truthy and
|
|
154
|
+
// simply fails the `typeof` check for a path) or crash confusingly deep inside `path.resolve()`, so it's
|
|
155
|
+
// rejected here with a message that explains the actual mistake.
|
|
156
|
+
if (rootDir !== undefined && typeof rootDir !== "string") {
|
|
157
|
+
throw new TypeError(`copyBinaryFile: "rootDir" must be a string, got ${typeof rootDir}. Did you mean to swap the ` +
|
|
158
|
+
`"overwrite" and "rootDir" arguments? Unlike copyFile, copyBinaryFile's signature is ` +
|
|
159
|
+
`(srcPath, outPath, variables, rootDir, overwrite).`);
|
|
111
160
|
}
|
|
112
|
-
if (
|
|
161
|
+
if (typeof overwrite !== "boolean") {
|
|
162
|
+
throw new TypeError(`copyBinaryFile: "overwrite" must be a boolean, got ${typeof overwrite}.`);
|
|
163
|
+
}
|
|
164
|
+
variables = variables ?? {};
|
|
165
|
+
let srcPathFull = path.resolve(srcPath);
|
|
166
|
+
if (!(await FileUtils.exists(srcPathFull))) {
|
|
113
167
|
throw new Error("File does not exist: " + srcPathFull);
|
|
114
168
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
if (!fs.existsSync(outDirPath)) {
|
|
118
|
-
await mkdirp(outDirPath);
|
|
169
|
+
if (rootDir) {
|
|
170
|
+
srcPathFull = await FileUtils.assertContained(rootDir, srcPathFull);
|
|
119
171
|
}
|
|
120
172
|
let outPathFinal = path.resolve(StringUtils.findAndReplace(outPath, variables));
|
|
121
173
|
if (rootDir) {
|
|
122
|
-
FileUtils.assertContained(rootDir, outPathFinal);
|
|
174
|
+
outPathFinal = await FileUtils.assertContained(rootDir, outPathFinal);
|
|
175
|
+
}
|
|
176
|
+
// Make sure the path leading to the final (template-substituted) destination exists. Must be derived from
|
|
177
|
+
// `outPathFinal`, not the raw `outPath`, otherwise the created directory can differ from the one actually
|
|
178
|
+
// written to whenever `outPath`'s directory itself contains template variables.
|
|
179
|
+
let outDirPath = path.dirname(outPathFinal);
|
|
180
|
+
if (!(await FileUtils.exists(outDirPath))) {
|
|
181
|
+
await mkdirp(outDirPath);
|
|
182
|
+
}
|
|
183
|
+
// `COPYFILE_EXCL` makes the existence check and the copy atomic when `overwrite` is `false` - a plain
|
|
184
|
+
// `fs.existsSync()` check followed by an unconditional copy would otherwise leave a window where two
|
|
185
|
+
// concurrent calls both see no existing file and one silently clobbers the other's output.
|
|
186
|
+
try {
|
|
187
|
+
await fs.promises.copyFile(srcPathFull, outPathFinal, overwrite ? 0 : fs.constants.COPYFILE_EXCL);
|
|
188
|
+
}
|
|
189
|
+
catch (err) {
|
|
190
|
+
if (!overwrite && err?.code === "EEXIST") {
|
|
191
|
+
throw new Error(`File already exists at "${outPathFinal}". Pass overwrite=true to replace it.`);
|
|
192
|
+
}
|
|
193
|
+
throw err;
|
|
123
194
|
}
|
|
124
|
-
fs.copyFileSync(srcPathFull, outPathFinal);
|
|
125
195
|
}
|
|
126
196
|
/**
|
|
127
197
|
* Performs a deep copy of a directory tree at the given srcPath to the specified output directory. Performs
|
|
@@ -137,15 +207,18 @@ export class FileUtils {
|
|
|
137
207
|
* within this directory, otherwise an error is thrown.
|
|
138
208
|
*/
|
|
139
209
|
static async copyDirectory(srcPath, outPath, vars = {}, excludeFilters = [], binaryFilters = [], force = false, rootDir) {
|
|
140
|
-
|
|
210
|
+
vars = vars ?? {};
|
|
211
|
+
let templatePath = path.resolve(srcPath);
|
|
141
212
|
if (rootDir) {
|
|
142
|
-
FileUtils.assertContained(rootDir, templatePath);
|
|
213
|
+
templatePath = await FileUtils.assertContained(rootDir, templatePath);
|
|
143
214
|
}
|
|
144
|
-
let files = fs.
|
|
145
|
-
//
|
|
146
|
-
//
|
|
147
|
-
//
|
|
148
|
-
for
|
|
215
|
+
let files = await fs.promises.readdir(templatePath, { withFileTypes: true });
|
|
216
|
+
// Copied concurrently via `Promise.all` rather than a sequentially-awaited loop, since sibling entries
|
|
217
|
+
// in the same directory are independent of one another. `Promise.all` still `await`s every entry before
|
|
218
|
+
// `copyDirectory` itself resolves and still propagates the first rejection to the caller, so this keeps
|
|
219
|
+
// the same "wait for everything, never swallow an error" guarantee a sequential loop would - it just lets
|
|
220
|
+
// independent copies overlap instead of running strictly one at a time.
|
|
221
|
+
await Promise.all(files.map(async (file) => {
|
|
149
222
|
let extension = path.extname(file.name);
|
|
150
223
|
if (!extension) {
|
|
151
224
|
extension = file.name;
|
|
@@ -154,24 +227,24 @@ export class FileUtils {
|
|
|
154
227
|
if (excludeFilters.indexOf(extension) === -1) {
|
|
155
228
|
let destPath = StringUtils.findAndReplace(path.join(outPath, file.name), vars);
|
|
156
229
|
if (rootDir) {
|
|
157
|
-
FileUtils.assertContained(rootDir, destPath);
|
|
230
|
+
destPath = await FileUtils.assertContained(rootDir, destPath);
|
|
158
231
|
}
|
|
159
232
|
if (file.isDirectory()) {
|
|
160
|
-
if (!
|
|
233
|
+
if (!(await FileUtils.exists(destPath))) {
|
|
161
234
|
// Recursive: `outPath` itself may not exist yet either, e.g. when directory entries are
|
|
162
235
|
// processed ahead of any file entry that would otherwise implicitly create it via mkdirp.
|
|
163
|
-
fs.
|
|
236
|
+
await fs.promises.mkdir(destPath, { recursive: true });
|
|
164
237
|
}
|
|
165
238
|
await FileUtils.copyDirectory(path.join(templatePath, file.name), destPath, vars, excludeFilters, binaryFilters, force, rootDir);
|
|
166
239
|
}
|
|
167
240
|
else if (binaryFilters.indexOf(extension) >= 0) {
|
|
168
|
-
await FileUtils.copyBinaryFile(path.join(templatePath, file.name), destPath, vars, rootDir);
|
|
241
|
+
await FileUtils.copyBinaryFile(path.join(templatePath, file.name), destPath, vars, rootDir, force);
|
|
169
242
|
}
|
|
170
243
|
else {
|
|
171
244
|
await FileUtils.copyFile(path.join(templatePath, file.name), destPath, vars, force, rootDir);
|
|
172
245
|
}
|
|
173
246
|
}
|
|
174
|
-
}
|
|
247
|
+
}));
|
|
175
248
|
}
|
|
176
249
|
}
|
|
177
250
|
//# sourceMappingURL=FileUtils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileUtils.js","sourceRoot":"","sources":["../../src/FileUtils.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,kDAAkD;AAClD,+EAA+E;AAC/E,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;AAExB;;;GAGG;AACF,MAAM,OAAO,SAAS;
|
|
1
|
+
{"version":3,"file":"FileUtils.js","sourceRoot":"","sources":["../../src/FileUtils.ts"],"names":[],"mappings":"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"}
|