stigmergy 1.0.94 → 1.0.97
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 +20 -0
- package/bin/stigmergy +37 -12
- package/docs/HASH_TABLE.md +83 -0
- package/docs/WEATHER_PROCESSOR_API.md +230 -0
- package/docs/best_practices.md +135 -0
- package/docs/development_guidelines.md +392 -0
- package/docs/http-request-handler.md +289 -0
- package/docs/json-parser.md +102 -0
- package/docs/requirements_specification.md +148 -0
- package/docs/rest_client.md +144 -0
- package/docs/system_design.md +314 -0
- package/docs/tdd_implementation_plan.md +384 -0
- package/docs/test_report.md +49 -0
- package/examples/calculator-example.js +72 -0
- package/examples/encryption-example.js +67 -0
- package/examples/json-parser-example.js +120 -0
- package/examples/json-validation-example.js +64 -0
- package/examples/rest-client-example.js +52 -0
- package/examples/rest_client_example.js +54 -0
- package/package.json +26 -21
- package/scripts/post-deployment-config.js +9 -2
- package/src/auth.js +173 -0
- package/src/auth_command.js +208 -0
- package/src/calculator.js +313 -0
- package/src/core/cli_help_analyzer.js +674 -563
- package/src/core/cli_parameter_handler.js +127 -0
- package/src/core/cli_tools.js +89 -0
- package/src/core/error_handler.js +406 -0
- package/src/core/memory_manager.js +83 -0
- package/src/core/rest_client.js +160 -0
- package/src/core/smart_router.js +146 -0
- package/src/data_encryption.js +143 -0
- package/src/data_structures.js +440 -0
- package/src/deploy.js +56 -0
- package/src/index.js +9 -9
- package/src/main.js +889 -752
- package/src/main_english.js +1305 -977
- package/src/main_fixed.js +1172 -0
- package/src/utils.js +916 -0
- package/src/weatherProcessor.js +228 -0
- package/test/calculator.test.js +215 -0
- package/test/collision-test.js +26 -0
- package/test/csv-processing-test.js +36 -0
- package/test/e2e/claude-cli-test.js +128 -0
- package/test/e2e/collaboration-test.js +75 -0
- package/test/e2e/comprehensive-test.js +431 -0
- package/test/e2e/error-handling-test.js +90 -0
- package/test/e2e/individual-tool-test.js +143 -0
- package/test/e2e/other-cli-test.js +130 -0
- package/test/e2e/qoder-cli-test.js +128 -0
- package/test/e2e/run-e2e-tests.js +73 -0
- package/test/e2e/test-data.js +88 -0
- package/test/e2e/test-utils.js +222 -0
- package/test/encryption-simple-test.js +110 -0
- package/test/encryption.test.js +129 -0
- package/test/hash-table-demo.js +33 -0
- package/test/hash-table-test.js +26 -0
- package/test/hash_table_test.js +114 -0
- package/test/json-parser-test.js +161 -0
- package/test/json-validation-test.js +164 -0
- package/test/rest-client-test.js +56 -0
- package/test/rest_client.test.js +85 -0
- package/test/unit/calculator-full.test.js +191 -0
- package/test/unit/calculator-simple.test.js +96 -0
- package/test/unit/calculator.test.js +97 -0
- package/test/unit/cli_parameter_handler.test.js +116 -0
- package/test/weather-processor.test.js +104 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple REST API Client
|
|
3
|
+
* Provides basic HTTP methods for interacting with REST APIs
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
class RestClient {
|
|
7
|
+
/**
|
|
8
|
+
* Create a new REST client
|
|
9
|
+
* @param {string} baseURL - The base URL for API requests
|
|
10
|
+
* @param {Object} defaultHeaders - Default headers to include in all requests
|
|
11
|
+
*/
|
|
12
|
+
constructor(baseURL = "", defaultHeaders = {}) {
|
|
13
|
+
this.baseURL = baseURL;
|
|
14
|
+
this.defaultHeaders = {
|
|
15
|
+
"Content-Type": "application/json",
|
|
16
|
+
...defaultHeaders,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Make an HTTP request
|
|
22
|
+
* @param {string} method - HTTP method (GET, POST, PUT, DELETE, etc.)
|
|
23
|
+
* @param {string} url - Request URL (will be appended to baseURL)
|
|
24
|
+
* @param {Object} options - Request options
|
|
25
|
+
* @returns {Promise<Object>} Response data
|
|
26
|
+
*/
|
|
27
|
+
async request(method, url, options = {}) {
|
|
28
|
+
const { headers = {}, body = null, params = {}, timeout = 10000 } = options;
|
|
29
|
+
|
|
30
|
+
// Construct full URL
|
|
31
|
+
let fullURL = this.baseURL + url;
|
|
32
|
+
|
|
33
|
+
// Add query parameters
|
|
34
|
+
if (Object.keys(params).length > 0) {
|
|
35
|
+
const queryParams = new URLSearchParams(params);
|
|
36
|
+
fullURL += (fullURL.includes("?") ? "&" : "?") + queryParams.toString();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Merge headers
|
|
40
|
+
const mergedHeaders = {
|
|
41
|
+
...this.defaultHeaders,
|
|
42
|
+
...headers,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// Prepare fetch options
|
|
46
|
+
const fetchOptions = {
|
|
47
|
+
method,
|
|
48
|
+
headers: mergedHeaders,
|
|
49
|
+
timeout,
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// Add body for methods that support it
|
|
53
|
+
if (body && ["POST", "PUT", "PATCH", "DELETE"].includes(method)) {
|
|
54
|
+
fetchOptions.body =
|
|
55
|
+
typeof body === "object" ? JSON.stringify(body) : body;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
const response = await fetch(fullURL, fetchOptions);
|
|
60
|
+
const contentType = response.headers.get("content-type");
|
|
61
|
+
|
|
62
|
+
let data;
|
|
63
|
+
if (contentType && contentType.includes("application/json")) {
|
|
64
|
+
data = await response.json();
|
|
65
|
+
} else {
|
|
66
|
+
data = await response.text();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (!response.ok) {
|
|
70
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
status: response.status,
|
|
75
|
+
statusText: response.statusText,
|
|
76
|
+
headers: Object.fromEntries(response.headers.entries()),
|
|
77
|
+
data,
|
|
78
|
+
};
|
|
79
|
+
} catch (error) {
|
|
80
|
+
throw new Error(`Request failed: ${error.message}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Make a GET request
|
|
86
|
+
* @param {string} url - Request URL
|
|
87
|
+
* @param {Object} options - Request options
|
|
88
|
+
* @returns {Promise<Object>} Response data
|
|
89
|
+
*/
|
|
90
|
+
async get(url, options = {}) {
|
|
91
|
+
return this.request("GET", url, options);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Make a POST request
|
|
96
|
+
* @param {string} url - Request URL
|
|
97
|
+
* @param {Object} data - Data to send in request body
|
|
98
|
+
* @param {Object} options - Request options
|
|
99
|
+
* @returns {Promise<Object>} Response data
|
|
100
|
+
*/
|
|
101
|
+
async post(url, data, options = {}) {
|
|
102
|
+
return this.request("POST", url, { ...options, body: data });
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Make a PUT request
|
|
107
|
+
* @param {string} url - Request URL
|
|
108
|
+
* @param {Object} data - Data to send in request body
|
|
109
|
+
* @param {Object} options - Request options
|
|
110
|
+
* @returns {Promise<Object>} Response data
|
|
111
|
+
*/
|
|
112
|
+
async put(url, data, options = {}) {
|
|
113
|
+
return this.request("PUT", url, { ...options, body: data });
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Make a PATCH request
|
|
118
|
+
* @param {string} url - Request URL
|
|
119
|
+
* @param {Object} data - Data to send in request body
|
|
120
|
+
* @param {Object} options - Request options
|
|
121
|
+
* @returns {Promise<Object>} Response data
|
|
122
|
+
*/
|
|
123
|
+
async patch(url, data, options = {}) {
|
|
124
|
+
return this.request("PATCH", url, { ...options, body: data });
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Make a DELETE request
|
|
129
|
+
* @param {string} url - Request URL
|
|
130
|
+
* @param {Object} options - Request options
|
|
131
|
+
* @returns {Promise<Object>} Response data
|
|
132
|
+
*/
|
|
133
|
+
async delete(url, options = {}) {
|
|
134
|
+
return this.request("DELETE", url, options);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Set default headers
|
|
139
|
+
* @param {Object} headers - Headers to set as default
|
|
140
|
+
*/
|
|
141
|
+
setDefaultHeaders(headers) {
|
|
142
|
+
this.defaultHeaders = {
|
|
143
|
+
...this.defaultHeaders,
|
|
144
|
+
...headers,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Set authorization header
|
|
150
|
+
* @param {string} token - Authorization token
|
|
151
|
+
* @param {string} type - Authorization type (Bearer, Basic, etc.)
|
|
152
|
+
*/
|
|
153
|
+
setAuthorization(token, type = "Bearer") {
|
|
154
|
+
this.setDefaultHeaders({
|
|
155
|
+
Authorization: `${type} ${token}`,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
module.exports = RestClient;
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
const CLIHelpAnalyzer = require("./cli_help_analyzer");
|
|
2
|
+
const { CLI_TOOLS, validateCLITool } = require("./cli_tools");
|
|
3
|
+
const { errorHandler, ERROR_TYPES } = require("./error_handler");
|
|
4
|
+
|
|
5
|
+
class SmartRouter {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.tools = CLI_TOOLS;
|
|
8
|
+
try {
|
|
9
|
+
this.analyzer = new CLIHelpAnalyzer();
|
|
10
|
+
this.analyzer.setCLITools(this.tools);
|
|
11
|
+
} catch (error) {
|
|
12
|
+
errorHandler.logError(error, "ERROR", "SmartRouter.constructor");
|
|
13
|
+
throw error;
|
|
14
|
+
}
|
|
15
|
+
this.routeKeywords = [
|
|
16
|
+
"use",
|
|
17
|
+
"help",
|
|
18
|
+
"please",
|
|
19
|
+
"write",
|
|
20
|
+
"generate",
|
|
21
|
+
"explain",
|
|
22
|
+
"analyze",
|
|
23
|
+
"translate",
|
|
24
|
+
"code",
|
|
25
|
+
"article",
|
|
26
|
+
];
|
|
27
|
+
this.defaultTool = "claude";
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Initialize the smart router
|
|
32
|
+
*/
|
|
33
|
+
async initialize() {
|
|
34
|
+
await this.analyzer.initialize();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Check if input should be routed to a specific CLI tool
|
|
39
|
+
*/
|
|
40
|
+
shouldRoute(userInput) {
|
|
41
|
+
return this.routeKeywords.some((keyword) =>
|
|
42
|
+
userInput.toLowerCase().includes(keyword.toLowerCase()),
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Perform smart routing based on user input and CLI patterns
|
|
48
|
+
*/
|
|
49
|
+
async smartRoute(userInput) {
|
|
50
|
+
const input = userInput.trim();
|
|
51
|
+
|
|
52
|
+
// First try to detect tool-specific keywords
|
|
53
|
+
for (const [toolName, toolInfo] of Object.entries(this.tools)) {
|
|
54
|
+
try {
|
|
55
|
+
// Validate tool configuration
|
|
56
|
+
validateCLITool(toolName);
|
|
57
|
+
|
|
58
|
+
// Get CLI pattern for this tool
|
|
59
|
+
let cliPattern = await this.analyzer.getCLIPattern(toolName);
|
|
60
|
+
|
|
61
|
+
// If we don't have a pattern, try to analyze the CLI
|
|
62
|
+
if (!cliPattern) {
|
|
63
|
+
try {
|
|
64
|
+
cliPattern = await this.analyzer.analyzeCLI(toolName);
|
|
65
|
+
} catch (error) {
|
|
66
|
+
console.warn(`Failed to analyze ${toolName}:`, error.message);
|
|
67
|
+
// Continue with next tool
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Check if input contains any of the tool's keywords or subcommands
|
|
73
|
+
const keywords = this.extractKeywords(toolName, cliPattern);
|
|
74
|
+
for (const keyword of keywords) {
|
|
75
|
+
if (input.toLowerCase().includes(keyword.toLowerCase())) {
|
|
76
|
+
// Extract clean parameters
|
|
77
|
+
const cleanInput = input
|
|
78
|
+
.replace(new RegExp(`.*${keyword}\\s*`, "gi"), "")
|
|
79
|
+
.replace(/^(use|please|help|using|with)\s*/i, "")
|
|
80
|
+
.trim();
|
|
81
|
+
return { tool: toolName, prompt: cleanInput };
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
} catch (error) {
|
|
85
|
+
await errorHandler.logError(
|
|
86
|
+
error,
|
|
87
|
+
"WARN",
|
|
88
|
+
`SmartRouter.smartRoute.${toolName}`,
|
|
89
|
+
);
|
|
90
|
+
// Continue with next tool
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Default routing
|
|
96
|
+
const cleanInput = input
|
|
97
|
+
.replace(/^(use|please|help|using|with)\s*/i, "")
|
|
98
|
+
.trim();
|
|
99
|
+
return { tool: this.defaultTool, prompt: cleanInput };
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Extract keywords for a tool from its CLI patterns
|
|
104
|
+
*/
|
|
105
|
+
extractKeywords(toolName, cliPattern) {
|
|
106
|
+
const keywords = [toolName];
|
|
107
|
+
|
|
108
|
+
// Add tool-specific keywords
|
|
109
|
+
const toolSpecificKeywords = {
|
|
110
|
+
claude: ["claude", "anthropic"],
|
|
111
|
+
gemini: ["gemini", "google"],
|
|
112
|
+
qwen: ["qwen", "alibaba", "tongyi"],
|
|
113
|
+
iflow: ["iflow", "workflow", "intelligent"],
|
|
114
|
+
qodercli: ["qoder", "code"],
|
|
115
|
+
codebuddy: ["codebuddy", "buddy", "assistant"],
|
|
116
|
+
copilot: ["copilot", "github", "gh"],
|
|
117
|
+
codex: ["codex", "openai", "gpt"],
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
if (toolSpecificKeywords[toolName]) {
|
|
121
|
+
keywords.push(...toolSpecificKeywords[toolName]);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Add subcommands from CLI pattern if available
|
|
125
|
+
if (cliPattern && cliPattern.patterns && cliPattern.patterns.subcommands) {
|
|
126
|
+
cliPattern.patterns.subcommands.forEach((subcommand) => {
|
|
127
|
+
if (subcommand.name) {
|
|
128
|
+
keywords.push(subcommand.name);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Add commands from CLI pattern if available
|
|
134
|
+
if (cliPattern && cliPattern.patterns && cliPattern.patterns.commands) {
|
|
135
|
+
cliPattern.patterns.commands.forEach((command) => {
|
|
136
|
+
if (command.name && command.name !== toolName) {
|
|
137
|
+
keywords.push(command.name);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return [...new Set(keywords)]; // Remove duplicates
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
module.exports = SmartRouter;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data encryption utilities for the Stigmergy CLI
|
|
3
|
+
* Provides secure data encryption and decryption functions using AES-256-GCM
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const crypto = require("crypto");
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Encrypts data using AES-256-GCM authenticated encryption
|
|
10
|
+
*
|
|
11
|
+
* This function provides secure symmetric encryption with authentication.
|
|
12
|
+
* It generates a random initialization vector for each encryption operation
|
|
13
|
+
* and returns the encrypted data along with the IV and authentication tag.
|
|
14
|
+
*
|
|
15
|
+
* @param {string|Buffer} data - The plaintext data to encrypt
|
|
16
|
+
* @param {string|Buffer} secretKey - The secret key for encryption (must be 32 bytes for AES-256)
|
|
17
|
+
* @returns {Object} Object containing encrypted data, IV, and authentication tag
|
|
18
|
+
* @throws {Error} If encryption fails due to invalid inputs or cryptographic errors
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* const crypto = require('crypto');
|
|
22
|
+
* const secretKey = crypto.randomBytes(32); // 256-bit key
|
|
23
|
+
* const plaintext = "Secret message";
|
|
24
|
+
* const encryptedObj = encryptData(plaintext, secretKey);
|
|
25
|
+
* console.log(encryptedObj);
|
|
26
|
+
* // Output: {
|
|
27
|
+
* // encryptedData: 'a3f5b7c8...',
|
|
28
|
+
* // iv: 'MjRkOGZj...',
|
|
29
|
+
* // authTag: 'YzQyNTgx...'
|
|
30
|
+
* // }
|
|
31
|
+
*/
|
|
32
|
+
function encryptData(data, secretKey) {
|
|
33
|
+
// Validate inputs
|
|
34
|
+
if (!data) {
|
|
35
|
+
throw new Error("Data to encrypt cannot be empty");
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!secretKey) {
|
|
39
|
+
throw new Error("Secret key is required");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Generate a random initialization vector
|
|
43
|
+
const iv = crypto.randomBytes(16);
|
|
44
|
+
|
|
45
|
+
// Create cipher using AES-256-GCM
|
|
46
|
+
const cipher = crypto.createCipherGCM("aes-256-gcm", secretKey, iv);
|
|
47
|
+
|
|
48
|
+
// Encrypt the data
|
|
49
|
+
let encrypted;
|
|
50
|
+
if (typeof data === "string") {
|
|
51
|
+
encrypted = cipher.update(data, "utf8", "hex");
|
|
52
|
+
} else {
|
|
53
|
+
encrypted = cipher.update(data);
|
|
54
|
+
encrypted = encrypted.toString("hex");
|
|
55
|
+
}
|
|
56
|
+
cipher.final();
|
|
57
|
+
|
|
58
|
+
// Get the authentication tag
|
|
59
|
+
const authTag = cipher.getAuthTag();
|
|
60
|
+
|
|
61
|
+
// Return encrypted data with IV and auth tag
|
|
62
|
+
return {
|
|
63
|
+
encryptedData: encrypted,
|
|
64
|
+
iv: iv.toString("base64"),
|
|
65
|
+
authTag: authTag.toString("base64"),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Decrypts data using AES-256-GCM authenticated decryption
|
|
71
|
+
*
|
|
72
|
+
* This function decrypts data that was encrypted with encryptData().
|
|
73
|
+
* It requires the encrypted data object containing the encrypted data,
|
|
74
|
+
* initialization vector, and authentication tag.
|
|
75
|
+
*
|
|
76
|
+
* @param {Object} encryptedObj - Object containing encrypted data, IV, and auth tag
|
|
77
|
+
* @param {string|Buffer} secretKey - The secret key used for encryption
|
|
78
|
+
* @returns {string} The decrypted plaintext data
|
|
79
|
+
* @throws {Error} If decryption fails due to invalid inputs, tampered data, or cryptographic errors
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* const decrypted = decryptData(encryptedObj, secretKey);
|
|
83
|
+
* console.log(decrypted); // "Secret message"
|
|
84
|
+
*/
|
|
85
|
+
function decryptData(encryptedObj, secretKey) {
|
|
86
|
+
// Validate inputs
|
|
87
|
+
if (
|
|
88
|
+
!encryptedObj ||
|
|
89
|
+
!encryptedObj.encryptedData ||
|
|
90
|
+
!encryptedObj.iv ||
|
|
91
|
+
!encryptedObj.authTag
|
|
92
|
+
) {
|
|
93
|
+
throw new Error("Invalid encrypted object");
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (!secretKey) {
|
|
97
|
+
throw new Error("Secret key is required");
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Decode base64 encoded values
|
|
101
|
+
const iv = Buffer.from(encryptedObj.iv, "base64");
|
|
102
|
+
const authTag = Buffer.from(encryptedObj.authTag, "base64");
|
|
103
|
+
|
|
104
|
+
// Create decipher using AES-256-GCM
|
|
105
|
+
const decipher = crypto.createDecipherGCM("aes-256-gcm", secretKey, iv);
|
|
106
|
+
|
|
107
|
+
// Set the authentication tag
|
|
108
|
+
decipher.setAuthTag(authTag);
|
|
109
|
+
|
|
110
|
+
// Decrypt the data
|
|
111
|
+
let decrypted;
|
|
112
|
+
if (typeof encryptedObj.encryptedData === "string") {
|
|
113
|
+
decrypted = decipher.update(encryptedObj.encryptedData, "hex", "utf8");
|
|
114
|
+
} else {
|
|
115
|
+
decrypted = decipher.update(encryptedObj.encryptedData);
|
|
116
|
+
decrypted = decrypted.toString("utf8");
|
|
117
|
+
}
|
|
118
|
+
decipher.final();
|
|
119
|
+
|
|
120
|
+
return decrypted;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Generates a cryptographically secure random key
|
|
125
|
+
*
|
|
126
|
+
* This function generates a random key suitable for AES-256 encryption.
|
|
127
|
+
*
|
|
128
|
+
* @param {number} [length=32] - Length of the key in bytes (32 bytes = 256 bits)
|
|
129
|
+
* @returns {Buffer} A cryptographically secure random key
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* const key = generateKey(); // 32-byte key for AES-256
|
|
133
|
+
* const shortKey = generateKey(16); // 16-byte key for AES-128
|
|
134
|
+
*/
|
|
135
|
+
function generateKey(length = 32) {
|
|
136
|
+
return crypto.randomBytes(length);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
module.exports = {
|
|
140
|
+
encryptData,
|
|
141
|
+
decryptData,
|
|
142
|
+
generateKey,
|
|
143
|
+
};
|