@rapidrest/core 1.15.0 → 3.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 +53 -37
- 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 -55
- package/dist/lib/ClassLoader.js.map +1 -1
- package/dist/lib/FileUtils.js +120 -45
- package/dist/lib/FileUtils.js.map +1 -1
- package/dist/lib/JWTUtils.js +200 -165
- package/dist/lib/JWTUtils.js.map +1 -1
- package/dist/lib/Logger.js +32 -3
- package/dist/lib/Logger.js.map +1 -1
- package/dist/lib/MemoryStore.js +11 -10
- package/dist/lib/MemoryStore.js.map +1 -1
- package/dist/lib/MessagingUtils.js +69 -40
- package/dist/lib/MessagingUtils.js.map +1 -1
- package/dist/lib/NotificationsUtils.js +26 -8
- package/dist/lib/NotificationsUtils.js.map +1 -1
- package/dist/lib/OASUtils.js +55 -24
- package/dist/lib/OASUtils.js.map +1 -1
- package/dist/lib/ObjectFactory.js +144 -67
- package/dist/lib/ObjectFactory.js.map +1 -1
- package/dist/lib/ObjectUtils.js +18 -5
- package/dist/lib/ObjectUtils.js.map +1 -1
- package/dist/lib/RedisStore.js +129 -0
- package/dist/lib/RedisStore.js.map +1 -0
- package/dist/lib/SimpleStore.js +5 -0
- package/dist/lib/SimpleStore.js.map +1 -0
- package/dist/lib/StringUtils.js +55 -28
- package/dist/lib/StringUtils.js.map +1 -1
- package/dist/lib/TelemetryUtils.js +30 -4
- package/dist/lib/TelemetryUtils.js.map +1 -1
- package/dist/lib/UserUtils.js +4 -5
- package/dist/lib/UserUtils.js.map +1 -1
- package/dist/lib/ValidationUtils.js +10 -3
- package/dist/lib/ValidationUtils.js.map +1 -1
- package/dist/lib/index.js +1 -0
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/threads/ThreadPool.js +131 -55
- 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 +20 -7
- package/dist/types/JWTUtils.d.ts +69 -24
- package/dist/types/MemoryStore.d.ts +6 -10
- package/dist/types/MessagingUtils.d.ts +5 -1
- package/dist/types/NotificationsUtils.d.ts +22 -0
- package/dist/types/ObjectFactory.d.ts +25 -1
- package/dist/types/ObjectUtils.d.ts +4 -0
- package/dist/types/RedisStore.d.ts +26 -0
- package/dist/types/SimpleStore.d.ts +33 -0
- package/dist/types/StringUtils.d.ts +8 -0
- package/dist/types/TelemetryUtils.d.ts +10 -0
- package/dist/types/ValidationUtils.d.ts +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/threads/ThreadPool.d.ts +30 -1
- package/package.json +3 -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,14 +115,21 @@ 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
|
-
let template = fs.
|
|
132
|
+
let template = await fs.promises.readFile(srcPathFull, "utf-8");
|
|
83
133
|
let output = StringUtils.findAndReplace(template, variables);
|
|
84
134
|
let outPathFinal = path.resolve(StringUtils.findAndReplace(outPath, variables));
|
|
85
135
|
logger.info("Writing: " + outPathFinal);
|
|
@@ -95,31 +145,53 @@ export class FileUtils {
|
|
|
95
145
|
* within this directory, otherwise an error is thrown.
|
|
96
146
|
* @param {boolean} overwrite Set to `true` to overwrite an existing file at the destination. Default is `false`,
|
|
97
147
|
* matching the behavior of `writeFile`/`copyFile`. Appended after `rootDir` to preserve the existing positional
|
|
98
|
-
* call signature
|
|
148
|
+
* call signature - note this is the opposite order from `copyFile`'s `(overwrite, rootDir)`.
|
|
99
149
|
*/
|
|
100
150
|
static async copyBinaryFile(srcPath, outPath, variables = {}, rootDir, overwrite = false) {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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).`);
|
|
160
|
+
}
|
|
161
|
+
if (typeof overwrite !== "boolean") {
|
|
162
|
+
throw new TypeError(`copyBinaryFile: "overwrite" must be a boolean, got ${typeof overwrite}.`);
|
|
104
163
|
}
|
|
105
|
-
|
|
164
|
+
variables = variables ?? {};
|
|
165
|
+
let srcPathFull = path.resolve(srcPath);
|
|
166
|
+
if (!(await FileUtils.exists(srcPathFull))) {
|
|
106
167
|
throw new Error("File does not exist: " + srcPathFull);
|
|
107
168
|
}
|
|
108
|
-
let outPathFinal = path.resolve(StringUtils.findAndReplace(outPath, variables));
|
|
109
169
|
if (rootDir) {
|
|
110
|
-
FileUtils.assertContained(rootDir,
|
|
170
|
+
srcPathFull = await FileUtils.assertContained(rootDir, srcPathFull);
|
|
111
171
|
}
|
|
112
|
-
|
|
113
|
-
|
|
172
|
+
let outPathFinal = path.resolve(StringUtils.findAndReplace(outPath, variables));
|
|
173
|
+
if (rootDir) {
|
|
174
|
+
outPathFinal = await FileUtils.assertContained(rootDir, outPathFinal);
|
|
114
175
|
}
|
|
115
176
|
// Make sure the path leading to the final (template-substituted) destination exists. Must be derived from
|
|
116
177
|
// `outPathFinal`, not the raw `outPath`, otherwise the created directory can differ from the one actually
|
|
117
178
|
// written to whenever `outPath`'s directory itself contains template variables.
|
|
118
179
|
let outDirPath = path.dirname(outPathFinal);
|
|
119
|
-
if (!
|
|
180
|
+
if (!(await FileUtils.exists(outDirPath))) {
|
|
120
181
|
await mkdirp(outDirPath);
|
|
121
182
|
}
|
|
122
|
-
|
|
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;
|
|
194
|
+
}
|
|
123
195
|
}
|
|
124
196
|
/**
|
|
125
197
|
* Performs a deep copy of a directory tree at the given srcPath to the specified output directory. Performs
|
|
@@ -135,15 +207,18 @@ export class FileUtils {
|
|
|
135
207
|
* within this directory, otherwise an error is thrown.
|
|
136
208
|
*/
|
|
137
209
|
static async copyDirectory(srcPath, outPath, vars = {}, excludeFilters = [], binaryFilters = [], force = false, rootDir) {
|
|
138
|
-
|
|
210
|
+
vars = vars ?? {};
|
|
211
|
+
let templatePath = path.resolve(srcPath);
|
|
139
212
|
if (rootDir) {
|
|
140
|
-
FileUtils.assertContained(rootDir, templatePath);
|
|
213
|
+
templatePath = await FileUtils.assertContained(rootDir, templatePath);
|
|
141
214
|
}
|
|
142
|
-
let files = fs.
|
|
143
|
-
//
|
|
144
|
-
//
|
|
145
|
-
//
|
|
146
|
-
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) => {
|
|
147
222
|
let extension = path.extname(file.name);
|
|
148
223
|
if (!extension) {
|
|
149
224
|
extension = file.name;
|
|
@@ -152,13 +227,13 @@ export class FileUtils {
|
|
|
152
227
|
if (excludeFilters.indexOf(extension) === -1) {
|
|
153
228
|
let destPath = StringUtils.findAndReplace(path.join(outPath, file.name), vars);
|
|
154
229
|
if (rootDir) {
|
|
155
|
-
FileUtils.assertContained(rootDir, destPath);
|
|
230
|
+
destPath = await FileUtils.assertContained(rootDir, destPath);
|
|
156
231
|
}
|
|
157
232
|
if (file.isDirectory()) {
|
|
158
|
-
if (!
|
|
233
|
+
if (!(await FileUtils.exists(destPath))) {
|
|
159
234
|
// Recursive: `outPath` itself may not exist yet either, e.g. when directory entries are
|
|
160
235
|
// processed ahead of any file entry that would otherwise implicitly create it via mkdirp.
|
|
161
|
-
fs.
|
|
236
|
+
await fs.promises.mkdir(destPath, { recursive: true });
|
|
162
237
|
}
|
|
163
238
|
await FileUtils.copyDirectory(path.join(templatePath, file.name), destPath, vars, excludeFilters, binaryFilters, force, rootDir);
|
|
164
239
|
}
|
|
@@ -169,7 +244,7 @@ export class FileUtils {
|
|
|
169
244
|
await FileUtils.copyFile(path.join(templatePath, file.name), destPath, vars, force, rootDir);
|
|
170
245
|
}
|
|
171
246
|
}
|
|
172
|
-
}
|
|
247
|
+
}));
|
|
173
248
|
}
|
|
174
249
|
}
|
|
175
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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"}
|