hackwriter 0.0.11 → 0.0.13
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/README.md +29 -59
- package/dist/agent/CompactionPrompt.d.ts +0 -7
- package/dist/agent/CompactionPrompt.d.ts.map +1 -1
- package/dist/agent/CompactionPrompt.js +1 -1
- package/dist/agent/CompactionPrompt.js.map +1 -1
- package/dist/agent/ConversationContext.d.ts +9 -0
- package/dist/agent/ConversationContext.d.ts.map +1 -1
- package/dist/agent/ConversationContext.js +16 -1
- package/dist/agent/ConversationContext.js.map +1 -1
- package/dist/agent/ModelFactory.d.ts.map +1 -1
- package/dist/agent/ModelFactory.js +4 -1
- package/dist/agent/ModelFactory.js.map +1 -1
- package/dist/cli.js +38 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +73 -22
- package/dist/commands/setup.js.map +1 -1
- package/dist/config/ConfigSchema.d.ts +2 -36
- package/dist/config/ConfigSchema.d.ts.map +1 -1
- package/dist/config/ConfigSchema.js +5 -11
- package/dist/config/ConfigSchema.js.map +1 -1
- package/dist/config/ConfigurationLoader.d.ts.map +1 -1
- package/dist/config/ConfigurationLoader.js +41 -6
- package/dist/config/ConfigurationLoader.js.map +1 -1
- package/dist/config/HackMDConfigLoader.d.ts +20 -0
- package/dist/config/HackMDConfigLoader.d.ts.map +1 -0
- package/dist/config/HackMDConfigLoader.js +51 -0
- package/dist/config/HackMDConfigLoader.js.map +1 -0
- package/dist/config/OpenAIDiscovery.d.ts.map +1 -1
- package/dist/config/OpenAIDiscovery.js +4 -1
- package/dist/config/OpenAIDiscovery.js.map +1 -1
- package/dist/config/ProviderRegistry.d.ts +2 -3
- package/dist/config/ProviderRegistry.d.ts.map +1 -1
- package/dist/config/ProviderRegistry.js +0 -6
- package/dist/config/ProviderRegistry.js.map +1 -1
- package/dist/config/constants.d.ts +6 -6
- package/dist/config/constants.d.ts.map +1 -1
- package/dist/config/constants.js +7 -8
- package/dist/config/constants.js.map +1 -1
- package/dist/mcp/MCPClient.d.ts +13 -2
- package/dist/mcp/MCPClient.d.ts.map +1 -1
- package/dist/mcp/MCPClient.js +58 -7
- package/dist/mcp/MCPClient.js.map +1 -1
- package/dist/mcp/MCPToolAdapter.d.ts +2 -1
- package/dist/mcp/MCPToolAdapter.d.ts.map +1 -1
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/messaging/MessageBus.d.ts +6 -1
- package/dist/messaging/MessageBus.d.ts.map +1 -1
- package/dist/messaging/MessageBus.js +6 -0
- package/dist/messaging/MessageBus.js.map +1 -1
- package/dist/tools/base/Tool.d.ts +0 -1
- package/dist/tools/base/Tool.d.ts.map +1 -1
- package/dist/tools/base/Tool.js.map +1 -1
- package/dist/tools/file/ListFilesTool.d.ts.map +1 -1
- package/dist/tools/file/ListFilesTool.js +10 -8
- package/dist/tools/file/ListFilesTool.js.map +1 -1
- package/dist/tools/file/ReadFileTool.d.ts.map +1 -1
- package/dist/tools/file/ReadFileTool.js +9 -8
- package/dist/tools/file/ReadFileTool.js.map +1 -1
- package/dist/tools/file/WriteFileTool.d.ts.map +1 -1
- package/dist/tools/file/WriteFileTool.js +9 -7
- package/dist/tools/file/WriteFileTool.js.map +1 -1
- package/dist/ui/shell/InteractiveShell.d.ts +6 -1
- package/dist/ui/shell/InteractiveShell.d.ts.map +1 -1
- package/dist/ui/shell/InteractiveShell.js +10 -0
- package/dist/ui/shell/InteractiveShell.js.map +1 -1
- package/dist/utils/AsyncPackageLoader.d.ts +29 -0
- package/dist/utils/AsyncPackageLoader.d.ts.map +1 -0
- package/dist/utils/AsyncPackageLoader.js +56 -0
- package/dist/utils/AsyncPackageLoader.js.map +1 -0
- package/dist/utils/BatchWriter.d.ts +42 -0
- package/dist/utils/BatchWriter.d.ts.map +1 -0
- package/dist/utils/BatchWriter.js +130 -0
- package/dist/utils/BatchWriter.js.map +1 -0
- package/dist/utils/Logger.d.ts.map +1 -1
- package/dist/utils/Logger.js +14 -4
- package/dist/utils/Logger.js.map +1 -1
- package/dist/utils/PathValidator.d.ts +35 -0
- package/dist/utils/PathValidator.d.ts.map +1 -0
- package/dist/utils/PathValidator.js +70 -0
- package/dist/utils/PathValidator.js.map +1 -0
- package/dist/utils/RateLimiter.d.ts +3 -1
- package/dist/utils/RateLimiter.d.ts.map +1 -1
- package/dist/utils/RateLimiter.js +9 -24
- package/dist/utils/RateLimiter.js.map +1 -1
- package/dist/utils/ResourceManager.d.ts +7 -0
- package/dist/utils/ResourceManager.d.ts.map +1 -0
- package/dist/utils/ResourceManager.js +2 -0
- package/dist/utils/ResourceManager.js.map +1 -0
- package/dist/utils/RetryPolicy.d.ts +29 -0
- package/dist/utils/RetryPolicy.d.ts.map +1 -0
- package/dist/utils/RetryPolicy.js +73 -0
- package/dist/utils/RetryPolicy.js.map +1 -0
- package/dist/utils/SensitiveDataRedactor.d.ts +40 -0
- package/dist/utils/SensitiveDataRedactor.d.ts.map +1 -0
- package/dist/utils/SensitiveDataRedactor.js +122 -0
- package/dist/utils/SensitiveDataRedactor.js.map +1 -0
- package/dist/utils/SlidingWindowRateLimiter.d.ts +36 -0
- package/dist/utils/SlidingWindowRateLimiter.d.ts.map +1 -0
- package/dist/utils/SlidingWindowRateLimiter.js +74 -0
- package/dist/utils/SlidingWindowRateLimiter.js.map +1 -0
- package/package.json +5 -3
package/dist/utils/Logger.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
+
import { SensitiveDataRedactor } from './SensitiveDataRedactor.js';
|
|
2
3
|
export class Logger {
|
|
3
4
|
static level = 'silent';
|
|
4
5
|
static setLevel(level) {
|
|
@@ -38,19 +39,28 @@ export class Logger {
|
|
|
38
39
|
if (Logger.level === 'silent') {
|
|
39
40
|
return;
|
|
40
41
|
}
|
|
41
|
-
|
|
42
|
+
// Sanitize error message before logging
|
|
43
|
+
const sanitizedMessage = SensitiveDataRedactor.redactString(message);
|
|
44
|
+
Logger.log(category, sanitizedMessage, undefined, {
|
|
42
45
|
category: chalk.red,
|
|
43
46
|
message: chalk.red,
|
|
44
47
|
});
|
|
45
48
|
if (error !== undefined) {
|
|
46
49
|
if (error instanceof Error) {
|
|
47
|
-
|
|
50
|
+
// Sanitize error stack and message
|
|
51
|
+
const sanitizedStack = SensitiveDataRedactor.redactString(error.stack ?? error.message);
|
|
52
|
+
console.log(chalk.red(sanitizedStack));
|
|
48
53
|
}
|
|
49
54
|
else if (typeof error === 'object' && error !== null) {
|
|
50
|
-
|
|
55
|
+
// Redact sensitive fields from error objects
|
|
56
|
+
const redactedError = SensitiveDataRedactor.redact(error);
|
|
57
|
+
console.log(chalk.red(JSON.stringify(redactedError, null, 2)));
|
|
51
58
|
}
|
|
52
59
|
else if (typeof error === 'string' || typeof error === 'number' || typeof error === 'boolean') {
|
|
53
|
-
|
|
60
|
+
const sanitizedError = typeof error === 'string'
|
|
61
|
+
? SensitiveDataRedactor.redactString(error)
|
|
62
|
+
: String(error);
|
|
63
|
+
console.log(chalk.red(sanitizedError));
|
|
54
64
|
}
|
|
55
65
|
}
|
|
56
66
|
}
|
package/dist/utils/Logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Logger.js","sourceRoot":"","sources":["../../src/utils/Logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"Logger.js","sourceRoot":"","sources":["../../src/utils/Logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAInE,MAAM,OAAO,MAAM;IACT,MAAM,CAAC,KAAK,GAAa,QAAQ,CAAC;IAE1C,MAAM,CAAC,QAAQ,CAAC,KAAe;QAC7B,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC;IACvB,CAAC;IAED,MAAM,CAAC,QAAQ;QACb,OAAO,MAAM,CAAC,KAAK,CAAC;IACtB,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,QAAgB,EAAE,OAAe,EAAE,IAAc;QAC5D,IAAI,MAAM,CAAC,KAAK,KAAK,OAAO,EAAE,CAAC;YAC7B,OAAO;QACT,CAAC;QAED,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE;YAClC,QAAQ,EAAE,KAAK,CAAC,IAAI;YACpB,OAAO,EAAE,KAAK,CAAC,KAAK;SACrB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,QAAgB,EAAE,OAAe,EAAE,IAAc;QAC3D,IAAI,MAAM,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,OAAO;QACT,CAAC;QAED,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE;YAClC,QAAQ,EAAE,KAAK,CAAC,IAAI;YACpB,OAAO,EAAE,KAAK,CAAC,KAAK;SACrB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,QAAgB,EAAE,OAAe,EAAE,IAAc;QAC3D,IAAI,MAAM,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,OAAO;QACT,CAAC;QAED,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE;YAClC,QAAQ,EAAE,KAAK,CAAC,MAAM;YACtB,OAAO,EAAE,KAAK,CAAC,MAAM;SACtB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,QAAgB,EAAE,OAAe,EAAE,KAAe;QAC7D,IAAI,MAAM,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,OAAO;QACT,CAAC;QAED,wCAAwC;QACxC,MAAM,gBAAgB,GAAG,qBAAqB,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QAErE,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,gBAAgB,EAAE,SAAS,EAAE;YAChD,QAAQ,EAAE,KAAK,CAAC,GAAG;YACnB,OAAO,EAAE,KAAK,CAAC,GAAG;SACnB,CAAC,CAAC;QAEH,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;gBAC3B,mCAAmC;gBACnC,MAAM,cAAc,GAAG,qBAAqB,CAAC,YAAY,CAAC,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;gBACxF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC;YACzC,CAAC;iBAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBACvD,6CAA6C;gBAC7C,MAAM,aAAa,GAAG,qBAAqB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC1D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YACjE,CAAC;iBAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;gBAChG,MAAM,cAAc,GAAG,OAAO,KAAK,KAAK,QAAQ;oBAC9C,CAAC,CAAC,qBAAqB,CAAC,YAAY,CAAC,KAAK,CAAC;oBAC3C,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAClB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC;YACzC,CAAC;QACH,CAAC;IACH,CAAC;IAEO,MAAM,CAAC,GAAG,CAChB,QAAgB,EAChB,OAAe,EACf,IAAa,EACb,MAGC;QAED,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACtE,MAAM,iBAAiB,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,CAAC,CAAC;QAC3D,MAAM,kBAAkB,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAEjD,OAAO,CAAC,GAAG,CAAC,GAAG,kBAAkB,IAAI,iBAAiB,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAErF,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;gBAC9C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YACzD,CAAC;iBAAM,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC7F,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACxC,CAAC;QACH,CAAC;IACH,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security error for path validation failures
|
|
3
|
+
*/
|
|
4
|
+
export declare class SecurityError extends Error {
|
|
5
|
+
readonly path?: string | undefined;
|
|
6
|
+
readonly violation?: string | undefined;
|
|
7
|
+
constructor(message: string, path?: string | undefined, violation?: string | undefined);
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* PathValidator provides security validation for file paths
|
|
11
|
+
* to prevent path traversal attacks and ensure paths stay within allowed boundaries
|
|
12
|
+
*/
|
|
13
|
+
export declare class PathValidator {
|
|
14
|
+
/**
|
|
15
|
+
* Validate a file path for security
|
|
16
|
+
* @param filePath - The path to validate
|
|
17
|
+
* @param allowedDirs - Optional array of allowed base directories
|
|
18
|
+
* @returns The normalized absolute path
|
|
19
|
+
* @throws SecurityError if path is invalid or contains traversal sequences
|
|
20
|
+
*/
|
|
21
|
+
static validate(filePath: string, allowedDirs?: string[]): string;
|
|
22
|
+
/**
|
|
23
|
+
* Normalize and resolve a path to absolute form
|
|
24
|
+
* @param filePath - The path to normalize
|
|
25
|
+
* @returns Absolute path with all relative references resolved
|
|
26
|
+
*/
|
|
27
|
+
static normalize(filePath: string): string;
|
|
28
|
+
/**
|
|
29
|
+
* Check if path contains traversal sequences
|
|
30
|
+
* @param filePath - The path to check
|
|
31
|
+
* @returns true if path contains '..' sequences
|
|
32
|
+
*/
|
|
33
|
+
static hasTraversal(filePath: string): boolean;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=PathValidator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PathValidator.d.ts","sourceRoot":"","sources":["../../src/utils/PathValidator.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,qBAAa,aAAc,SAAQ,KAAK;aAGpB,IAAI,CAAC,EAAE,MAAM;aACb,SAAS,CAAC,EAAE,MAAM;gBAFlC,OAAO,EAAE,MAAM,EACC,IAAI,CAAC,EAAE,MAAM,YAAA,EACb,SAAS,CAAC,EAAE,MAAM,YAAA;CAKrC;AAED;;;GAGG;AACH,qBAAa,aAAa;IACxB;;;;;;OAMG;IACH,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM;IA2CjE;;;;OAIG;IACH,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAI1C;;;;OAIG;IACH,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;CAK/C"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { resolve, dirname, relative, isAbsolute } from 'path';
|
|
2
|
+
/**
|
|
3
|
+
* Security error for path validation failures
|
|
4
|
+
*/
|
|
5
|
+
export class SecurityError extends Error {
|
|
6
|
+
path;
|
|
7
|
+
violation;
|
|
8
|
+
constructor(message, path, violation) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.path = path;
|
|
11
|
+
this.violation = violation;
|
|
12
|
+
this.name = 'SecurityError';
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* PathValidator provides security validation for file paths
|
|
17
|
+
* to prevent path traversal attacks and ensure paths stay within allowed boundaries
|
|
18
|
+
*/
|
|
19
|
+
export class PathValidator {
|
|
20
|
+
/**
|
|
21
|
+
* Validate a file path for security
|
|
22
|
+
* @param filePath - The path to validate
|
|
23
|
+
* @param allowedDirs - Optional array of allowed base directories
|
|
24
|
+
* @returns The normalized absolute path
|
|
25
|
+
* @throws SecurityError if path is invalid or contains traversal sequences
|
|
26
|
+
*/
|
|
27
|
+
static validate(filePath, allowedDirs) {
|
|
28
|
+
if (!filePath || filePath.trim() === '') {
|
|
29
|
+
throw new SecurityError('File path cannot be empty', filePath, 'empty_path');
|
|
30
|
+
}
|
|
31
|
+
// Normalize the path to resolve any relative references
|
|
32
|
+
const normalized = this.normalize(filePath);
|
|
33
|
+
// Check for path traversal after normalization
|
|
34
|
+
if (this.hasTraversal(filePath)) {
|
|
35
|
+
throw new SecurityError('Path traversal is not allowed for security reasons', filePath, 'path_traversal');
|
|
36
|
+
}
|
|
37
|
+
// If allowed directories are specified, verify the path is within them
|
|
38
|
+
if (allowedDirs && allowedDirs.length > 0) {
|
|
39
|
+
const isWithinAllowed = allowedDirs.some(allowedDir => {
|
|
40
|
+
const resolvedAllowed = resolve(allowedDir);
|
|
41
|
+
const relativePath = relative(resolvedAllowed, normalized);
|
|
42
|
+
// Path is within allowed dir if relative path doesn't start with '..'
|
|
43
|
+
return relativePath && !relativePath.startsWith('..') && !isAbsolute(relativePath);
|
|
44
|
+
});
|
|
45
|
+
if (!isWithinAllowed) {
|
|
46
|
+
throw new SecurityError(`Path is outside allowed directories`, filePath, 'outside_allowed_dirs');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return normalized;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Normalize and resolve a path to absolute form
|
|
53
|
+
* @param filePath - The path to normalize
|
|
54
|
+
* @returns Absolute path with all relative references resolved
|
|
55
|
+
*/
|
|
56
|
+
static normalize(filePath) {
|
|
57
|
+
return resolve(filePath);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Check if path contains traversal sequences
|
|
61
|
+
* @param filePath - The path to check
|
|
62
|
+
* @returns true if path contains '..' sequences
|
|
63
|
+
*/
|
|
64
|
+
static hasTraversal(filePath) {
|
|
65
|
+
// Check for '..' in the path
|
|
66
|
+
const normalized = dirname(filePath);
|
|
67
|
+
return normalized.includes('..');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=PathValidator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PathValidator.js","sourceRoot":"","sources":["../../src/utils/PathValidator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAE9D;;GAEG;AACH,MAAM,OAAO,aAAc,SAAQ,KAAK;IAGpB;IACA;IAHlB,YACE,OAAe,EACC,IAAa,EACb,SAAkB;QAElC,KAAK,CAAC,OAAO,CAAC,CAAC;QAHC,SAAI,GAAJ,IAAI,CAAS;QACb,cAAS,GAAT,SAAS,CAAS;QAGlC,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,OAAO,aAAa;IACxB;;;;;;OAMG;IACH,MAAM,CAAC,QAAQ,CAAC,QAAgB,EAAE,WAAsB;QACtD,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YACxC,MAAM,IAAI,aAAa,CACrB,2BAA2B,EAC3B,QAAQ,EACR,YAAY,CACb,CAAC;QACJ,CAAC;QAED,wDAAwD;QACxD,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAE5C,+CAA+C;QAC/C,IAAI,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,aAAa,CACrB,oDAAoD,EACpD,QAAQ,EACR,gBAAgB,CACjB,CAAC;QACJ,CAAC;QAED,uEAAuE;QACvE,IAAI,WAAW,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1C,MAAM,eAAe,GAAG,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE;gBACpD,MAAM,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;gBAC5C,MAAM,YAAY,GAAG,QAAQ,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;gBAE3D,sEAAsE;gBACtE,OAAO,YAAY,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;YACrF,CAAC,CAAC,CAAC;YAEH,IAAI,CAAC,eAAe,EAAE,CAAC;gBACrB,MAAM,IAAI,aAAa,CACrB,qCAAqC,EACrC,QAAQ,EACR,sBAAsB,CACvB,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,SAAS,CAAC,QAAgB;QAC/B,OAAO,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC3B,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,YAAY,CAAC,QAAgB;QAClC,6BAA6B;QAC7B,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;QACrC,OAAO,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;CACF"}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Rate limiter using sliding window algorithm
|
|
3
3
|
* Prevents excessive API calls within a time window
|
|
4
|
+
*
|
|
5
|
+
* @deprecated Use SlidingWindowRateLimiter directly for better performance
|
|
4
6
|
*/
|
|
5
7
|
export declare class RateLimiter {
|
|
6
8
|
private maxRequests;
|
|
7
9
|
private windowMs;
|
|
8
|
-
private
|
|
10
|
+
private limiter;
|
|
9
11
|
/**
|
|
10
12
|
* @param maxRequests - Maximum number of requests allowed
|
|
11
13
|
* @param windowMs - Time window in milliseconds
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RateLimiter.d.ts","sourceRoot":"","sources":["../../src/utils/RateLimiter.ts"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"RateLimiter.d.ts","sourceRoot":"","sources":["../../src/utils/RateLimiter.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,qBAAa,WAAW;IAQpB,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,QAAQ;IARlB,OAAO,CAAC,OAAO,CAA2B;IAE1C;;;OAGG;gBAEO,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM;IAK1B;;;OAGG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAI9B;;OAEG;IACH,UAAU,IAAI,OAAO;IAIrB;;OAEG;IACH,QAAQ,IAAI;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE;IAI9D;;OAEG;IACH,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SlidingWindowRateLimiter } from './SlidingWindowRateLimiter.js';
|
|
2
2
|
/**
|
|
3
3
|
* Rate limiter using sliding window algorithm
|
|
4
4
|
* Prevents excessive API calls within a time window
|
|
5
|
+
*
|
|
6
|
+
* @deprecated Use SlidingWindowRateLimiter directly for better performance
|
|
5
7
|
*/
|
|
6
8
|
export class RateLimiter {
|
|
7
9
|
maxRequests;
|
|
8
10
|
windowMs;
|
|
9
|
-
|
|
11
|
+
limiter;
|
|
10
12
|
/**
|
|
11
13
|
* @param maxRequests - Maximum number of requests allowed
|
|
12
14
|
* @param windowMs - Time window in milliseconds
|
|
@@ -14,49 +16,32 @@ export class RateLimiter {
|
|
|
14
16
|
constructor(maxRequests, windowMs) {
|
|
15
17
|
this.maxRequests = maxRequests;
|
|
16
18
|
this.windowMs = windowMs;
|
|
19
|
+
this.limiter = new SlidingWindowRateLimiter(maxRequests, windowMs);
|
|
17
20
|
}
|
|
18
21
|
/**
|
|
19
22
|
* Acquire permission to make a request
|
|
20
23
|
* Will wait if rate limit is exceeded
|
|
21
24
|
*/
|
|
22
25
|
async acquire() {
|
|
23
|
-
|
|
24
|
-
// Remove requests outside the current window
|
|
25
|
-
this.requests = this.requests.filter(t => now - t < this.windowMs);
|
|
26
|
-
if (this.requests.length >= this.maxRequests) {
|
|
27
|
-
const oldestRequest = this.requests[0];
|
|
28
|
-
const waitTime = this.windowMs - (now - oldestRequest);
|
|
29
|
-
Logger.debug('RateLimiter', `Rate limit reached, waiting ${waitTime}ms`, { maxRequests: this.maxRequests, windowMs: this.windowMs });
|
|
30
|
-
await new Promise(resolve => setTimeout(resolve, waitTime));
|
|
31
|
-
return this.acquire(); // Retry after waiting
|
|
32
|
-
}
|
|
33
|
-
this.requests.push(now);
|
|
26
|
+
return this.limiter.acquire();
|
|
34
27
|
}
|
|
35
28
|
/**
|
|
36
29
|
* Check if a request can be made without waiting
|
|
37
30
|
*/
|
|
38
31
|
canAcquire() {
|
|
39
|
-
|
|
40
|
-
this.requests = this.requests.filter(t => now - t < this.windowMs);
|
|
41
|
-
return this.requests.length < this.maxRequests;
|
|
32
|
+
return this.limiter.canAcquire();
|
|
42
33
|
}
|
|
43
34
|
/**
|
|
44
35
|
* Get current usage statistics
|
|
45
36
|
*/
|
|
46
37
|
getStats() {
|
|
47
|
-
|
|
48
|
-
this.requests = this.requests.filter(t => now - t < this.windowMs);
|
|
49
|
-
return {
|
|
50
|
-
current: this.requests.length,
|
|
51
|
-
max: this.maxRequests,
|
|
52
|
-
windowMs: this.windowMs,
|
|
53
|
-
};
|
|
38
|
+
return this.limiter.getStats();
|
|
54
39
|
}
|
|
55
40
|
/**
|
|
56
41
|
* Reset the rate limiter
|
|
57
42
|
*/
|
|
58
43
|
reset() {
|
|
59
|
-
this.
|
|
44
|
+
this.limiter.reset();
|
|
60
45
|
}
|
|
61
46
|
}
|
|
62
47
|
//# sourceMappingURL=RateLimiter.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RateLimiter.js","sourceRoot":"","sources":["../../src/utils/RateLimiter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"RateLimiter.js","sourceRoot":"","sources":["../../src/utils/RateLimiter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAEzE;;;;;GAKG;AACH,MAAM,OAAO,WAAW;IAQZ;IACA;IARF,OAAO,CAA2B;IAE1C;;;OAGG;IACH,YACU,WAAmB,EACnB,QAAgB;QADhB,gBAAW,GAAX,WAAW,CAAQ;QACnB,aAAQ,GAAR,QAAQ,CAAQ;QAExB,IAAI,CAAC,OAAO,GAAG,IAAI,wBAAwB,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IACrE,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,OAAO;QACX,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,UAAU;QACR,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;IACnC,CAAC;IAED;;OAEG;IACH,QAAQ;QACN,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;IACjC,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResourceManager.d.ts","sourceRoot":"","sources":["../../src/utils/ResourceManager.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACjC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResourceManager.js","sourceRoot":"","sources":["../../src/utils/ResourceManager.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface RetryOptions {
|
|
2
|
+
maxRetries: number;
|
|
3
|
+
initialDelayMs: number;
|
|
4
|
+
maxDelayMs: number;
|
|
5
|
+
backoffMultiplier: number;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* RetryPolicy provides configurable retry logic with exponential backoff.
|
|
9
|
+
* Useful for handling transient failures in network operations.
|
|
10
|
+
*/
|
|
11
|
+
export declare class RetryPolicy {
|
|
12
|
+
private readonly options;
|
|
13
|
+
constructor(options?: Partial<RetryOptions>);
|
|
14
|
+
/**
|
|
15
|
+
* Execute function with retry logic
|
|
16
|
+
* @param fn - Function to execute
|
|
17
|
+
* @returns Result of the function
|
|
18
|
+
* @throws Last error if all retries fail
|
|
19
|
+
*/
|
|
20
|
+
execute<T>(fn: () => Promise<T>): Promise<T>;
|
|
21
|
+
/**
|
|
22
|
+
* Calculate delay for retry attempt with exponential backoff and jitter
|
|
23
|
+
* @param attempt - Current attempt number (1-indexed)
|
|
24
|
+
* @returns Delay in milliseconds
|
|
25
|
+
*/
|
|
26
|
+
getDelay(attempt: number): number;
|
|
27
|
+
private sleep;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=RetryPolicy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RetryPolicy.d.ts","sourceRoot":"","sources":["../../src/utils/RetryPolicy.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED;;;GAGG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;gBAE3B,OAAO,GAAE,OAAO,CAAC,YAAY,CAAM;IAS/C;;;;;OAKG;IACG,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAoClD;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAgBjC,OAAO,CAAC,KAAK;CAGd"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { Logger } from "./Logger.js";
|
|
2
|
+
/**
|
|
3
|
+
* RetryPolicy provides configurable retry logic with exponential backoff.
|
|
4
|
+
* Useful for handling transient failures in network operations.
|
|
5
|
+
*/
|
|
6
|
+
export class RetryPolicy {
|
|
7
|
+
options;
|
|
8
|
+
constructor(options = {}) {
|
|
9
|
+
this.options = {
|
|
10
|
+
maxRetries: options.maxRetries ?? 3,
|
|
11
|
+
initialDelayMs: options.initialDelayMs ?? 1000,
|
|
12
|
+
maxDelayMs: options.maxDelayMs ?? 10000,
|
|
13
|
+
backoffMultiplier: options.backoffMultiplier ?? 2,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Execute function with retry logic
|
|
18
|
+
* @param fn - Function to execute
|
|
19
|
+
* @returns Result of the function
|
|
20
|
+
* @throws Last error if all retries fail
|
|
21
|
+
*/
|
|
22
|
+
async execute(fn) {
|
|
23
|
+
let lastError;
|
|
24
|
+
let attempt = 0;
|
|
25
|
+
while (attempt <= this.options.maxRetries) {
|
|
26
|
+
try {
|
|
27
|
+
if (attempt > 0) {
|
|
28
|
+
Logger.debug("RetryPolicy", `Retry attempt ${attempt}/${this.options.maxRetries}`);
|
|
29
|
+
}
|
|
30
|
+
return await fn();
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
34
|
+
attempt++;
|
|
35
|
+
if (attempt > this.options.maxRetries) {
|
|
36
|
+
Logger.error("RetryPolicy", `All ${this.options.maxRetries} retries failed`, {
|
|
37
|
+
error: lastError.message,
|
|
38
|
+
});
|
|
39
|
+
throw lastError;
|
|
40
|
+
}
|
|
41
|
+
const delay = this.getDelay(attempt);
|
|
42
|
+
Logger.debug("RetryPolicy", `Waiting ${delay}ms before retry`, {
|
|
43
|
+
attempt,
|
|
44
|
+
maxRetries: this.options.maxRetries,
|
|
45
|
+
error: lastError.message,
|
|
46
|
+
});
|
|
47
|
+
await this.sleep(delay);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// This should never be reached, but TypeScript needs it
|
|
51
|
+
throw lastError ?? new Error("Retry failed with unknown error");
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Calculate delay for retry attempt with exponential backoff and jitter
|
|
55
|
+
* @param attempt - Current attempt number (1-indexed)
|
|
56
|
+
* @returns Delay in milliseconds
|
|
57
|
+
*/
|
|
58
|
+
getDelay(attempt) {
|
|
59
|
+
// Exponential backoff: initialDelay * (multiplier ^ (attempt - 1))
|
|
60
|
+
const exponentialDelay = this.options.initialDelayMs * Math.pow(this.options.backoffMultiplier, attempt - 1);
|
|
61
|
+
// Cap at maxDelay
|
|
62
|
+
const cappedDelay = Math.min(exponentialDelay, this.options.maxDelayMs);
|
|
63
|
+
// Add jitter (±20%) to prevent thundering herd
|
|
64
|
+
const jitter = cappedDelay * 0.2 * (Math.random() * 2 - 1);
|
|
65
|
+
const delayWithJitter = Math.max(0, cappedDelay + jitter);
|
|
66
|
+
// Ensure minimum delay of 1 second
|
|
67
|
+
return Math.max(1000, delayWithJitter);
|
|
68
|
+
}
|
|
69
|
+
sleep(ms) {
|
|
70
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=RetryPolicy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RetryPolicy.js","sourceRoot":"","sources":["../../src/utils/RetryPolicy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SensitiveDataRedactor provides utilities to redact sensitive information
|
|
3
|
+
* from logs, error messages, and other outputs to prevent credential leaks
|
|
4
|
+
*/
|
|
5
|
+
export declare class SensitiveDataRedactor {
|
|
6
|
+
/**
|
|
7
|
+
* Default list of sensitive key patterns
|
|
8
|
+
*/
|
|
9
|
+
private static readonly DEFAULT_SENSITIVE_KEYS;
|
|
10
|
+
/**
|
|
11
|
+
* Regex patterns to detect sensitive data in strings
|
|
12
|
+
*/
|
|
13
|
+
private static readonly SENSITIVE_PATTERNS;
|
|
14
|
+
/**
|
|
15
|
+
* Redact sensitive fields from an object
|
|
16
|
+
* @param obj - The object to redact
|
|
17
|
+
* @param sensitiveKeys - Optional custom list of sensitive keys
|
|
18
|
+
* @returns A new object with sensitive values redacted
|
|
19
|
+
*/
|
|
20
|
+
static redact(obj: unknown, sensitiveKeys?: string[]): unknown;
|
|
21
|
+
/**
|
|
22
|
+
* Redact API keys and tokens from strings
|
|
23
|
+
* @param text - The text to redact
|
|
24
|
+
* @returns Text with sensitive patterns replaced
|
|
25
|
+
*/
|
|
26
|
+
static redactString(text: string): string;
|
|
27
|
+
/**
|
|
28
|
+
* Clear sensitive data from memory
|
|
29
|
+
* Overwrites sensitive values with empty strings and deletes properties
|
|
30
|
+
* @param obj - The object to clear
|
|
31
|
+
*/
|
|
32
|
+
static clearMemory(obj: Record<string, unknown>): void;
|
|
33
|
+
/**
|
|
34
|
+
* Check if a key name appears to be sensitive
|
|
35
|
+
* @param key - The key name to check
|
|
36
|
+
* @returns true if the key appears sensitive
|
|
37
|
+
*/
|
|
38
|
+
static isSensitiveKey(key: string): boolean;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=SensitiveDataRedactor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SensitiveDataRedactor.d.ts","sourceRoot":"","sources":["../../src/utils/SensitiveDataRedactor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,qBAAqB;IAChC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,sBAAsB,CAkB5C;IAEF;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAIxC;IAEF;;;;;OAKG;IACH,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,aAAa,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO;IAqC9D;;;;OAIG;IACH,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAezC;;;;OAIG;IACH,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IA0BtD;;;;OAIG;IACH,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;CAK5C"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SensitiveDataRedactor provides utilities to redact sensitive information
|
|
3
|
+
* from logs, error messages, and other outputs to prevent credential leaks
|
|
4
|
+
*/
|
|
5
|
+
export class SensitiveDataRedactor {
|
|
6
|
+
/**
|
|
7
|
+
* Default list of sensitive key patterns
|
|
8
|
+
*/
|
|
9
|
+
static DEFAULT_SENSITIVE_KEYS = [
|
|
10
|
+
'apiKey',
|
|
11
|
+
'api_key',
|
|
12
|
+
'API_KEY',
|
|
13
|
+
'token',
|
|
14
|
+
'accessToken',
|
|
15
|
+
'access_token',
|
|
16
|
+
'apiToken',
|
|
17
|
+
'api_token',
|
|
18
|
+
'password',
|
|
19
|
+
'PASSWORD',
|
|
20
|
+
'secret',
|
|
21
|
+
'SECRET',
|
|
22
|
+
'credential',
|
|
23
|
+
'CREDENTIAL',
|
|
24
|
+
'auth',
|
|
25
|
+
'authorization',
|
|
26
|
+
'bearer',
|
|
27
|
+
];
|
|
28
|
+
/**
|
|
29
|
+
* Regex patterns to detect sensitive data in strings
|
|
30
|
+
*/
|
|
31
|
+
static SENSITIVE_PATTERNS = [
|
|
32
|
+
/sk-[a-zA-Z0-9]{20,}/g, // API keys like sk-ant-xxx
|
|
33
|
+
/Bearer\s+[a-zA-Z0-9_\-.]+/gi, // Bearer tokens
|
|
34
|
+
/[a-zA-Z0-9]{32,}/g, // Long alphanumeric strings (potential tokens)
|
|
35
|
+
];
|
|
36
|
+
/**
|
|
37
|
+
* Redact sensitive fields from an object
|
|
38
|
+
* @param obj - The object to redact
|
|
39
|
+
* @param sensitiveKeys - Optional custom list of sensitive keys
|
|
40
|
+
* @returns A new object with sensitive values redacted
|
|
41
|
+
*/
|
|
42
|
+
static redact(obj, sensitiveKeys) {
|
|
43
|
+
const keys = sensitiveKeys ?? this.DEFAULT_SENSITIVE_KEYS;
|
|
44
|
+
if (obj === null || obj === undefined) {
|
|
45
|
+
return obj;
|
|
46
|
+
}
|
|
47
|
+
if (typeof obj !== 'object') {
|
|
48
|
+
return obj;
|
|
49
|
+
}
|
|
50
|
+
if (Array.isArray(obj)) {
|
|
51
|
+
return obj.map(item => this.redact(item, sensitiveKeys));
|
|
52
|
+
}
|
|
53
|
+
const redacted = {};
|
|
54
|
+
const record = obj;
|
|
55
|
+
for (const [key, value] of Object.entries(record)) {
|
|
56
|
+
// Check if key matches sensitive patterns
|
|
57
|
+
const isSensitive = keys.some(sensitiveKey => key.toLowerCase().includes(sensitiveKey.toLowerCase()));
|
|
58
|
+
if (isSensitive) {
|
|
59
|
+
redacted[key] = '[REDACTED]';
|
|
60
|
+
}
|
|
61
|
+
else if (typeof value === 'object' && value !== null) {
|
|
62
|
+
// Recursively redact nested objects
|
|
63
|
+
redacted[key] = this.redact(value, sensitiveKeys);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
redacted[key] = value;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return redacted;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Redact API keys and tokens from strings
|
|
73
|
+
* @param text - The text to redact
|
|
74
|
+
* @returns Text with sensitive patterns replaced
|
|
75
|
+
*/
|
|
76
|
+
static redactString(text) {
|
|
77
|
+
if (!text) {
|
|
78
|
+
return text;
|
|
79
|
+
}
|
|
80
|
+
let redacted = text;
|
|
81
|
+
// Apply each pattern
|
|
82
|
+
for (const pattern of this.SENSITIVE_PATTERNS) {
|
|
83
|
+
redacted = redacted.replace(pattern, '[REDACTED]');
|
|
84
|
+
}
|
|
85
|
+
return redacted;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Clear sensitive data from memory
|
|
89
|
+
* Overwrites sensitive values with empty strings and deletes properties
|
|
90
|
+
* @param obj - The object to clear
|
|
91
|
+
*/
|
|
92
|
+
static clearMemory(obj) {
|
|
93
|
+
if (!obj || typeof obj !== 'object') {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const keys = this.DEFAULT_SENSITIVE_KEYS;
|
|
97
|
+
for (const key of Object.keys(obj)) {
|
|
98
|
+
const isSensitive = keys.some(sensitiveKey => key.toLowerCase().includes(sensitiveKey.toLowerCase()));
|
|
99
|
+
if (isSensitive) {
|
|
100
|
+
// Overwrite with empty string first
|
|
101
|
+
if (typeof obj[key] === 'string') {
|
|
102
|
+
obj[key] = '';
|
|
103
|
+
}
|
|
104
|
+
// Then delete the property
|
|
105
|
+
delete obj[key];
|
|
106
|
+
}
|
|
107
|
+
else if (typeof obj[key] === 'object' && obj[key] !== null) {
|
|
108
|
+
// Recursively clear nested objects
|
|
109
|
+
this.clearMemory(obj[key]);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Check if a key name appears to be sensitive
|
|
115
|
+
* @param key - The key name to check
|
|
116
|
+
* @returns true if the key appears sensitive
|
|
117
|
+
*/
|
|
118
|
+
static isSensitiveKey(key) {
|
|
119
|
+
return this.DEFAULT_SENSITIVE_KEYS.some(sensitiveKey => key.toLowerCase().includes(sensitiveKey.toLowerCase()));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=SensitiveDataRedactor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SensitiveDataRedactor.js","sourceRoot":"","sources":["../../src/utils/SensitiveDataRedactor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optimized rate limiter using sliding window algorithm
|
|
3
|
+
* More efficient than filtering entire array on every request
|
|
4
|
+
*/
|
|
5
|
+
export declare class SlidingWindowRateLimiter {
|
|
6
|
+
private maxRequests;
|
|
7
|
+
private windowMs;
|
|
8
|
+
private requests;
|
|
9
|
+
/**
|
|
10
|
+
* @param maxRequests - Maximum number of requests allowed
|
|
11
|
+
* @param windowMs - Time window in milliseconds
|
|
12
|
+
*/
|
|
13
|
+
constructor(maxRequests: number, windowMs: number);
|
|
14
|
+
/**
|
|
15
|
+
* Acquire permission to make a request
|
|
16
|
+
* Will wait if rate limit is exceeded
|
|
17
|
+
*/
|
|
18
|
+
acquire(): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Check if a request can be made without waiting
|
|
21
|
+
*/
|
|
22
|
+
canAcquire(): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Get current usage statistics
|
|
25
|
+
*/
|
|
26
|
+
getStats(): {
|
|
27
|
+
current: number;
|
|
28
|
+
max: number;
|
|
29
|
+
windowMs: number;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Reset the rate limiter
|
|
33
|
+
*/
|
|
34
|
+
reset(): void;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=SlidingWindowRateLimiter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SlidingWindowRateLimiter.d.ts","sourceRoot":"","sources":["../../src/utils/SlidingWindowRateLimiter.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,qBAAa,wBAAwB;IAQjC,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,QAAQ;IARlB,OAAO,CAAC,QAAQ,CAAgB;IAEhC;;;OAGG;gBAEO,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM;IAG1B;;;OAGG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA2B9B;;OAEG;IACH,UAAU,IAAI,OAAO;IAYrB;;OAEG;IACH,QAAQ,IAAI;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE;IAgB9D;;OAEG;IACH,KAAK,IAAI,IAAI;CAGd"}
|