i18ntk 2.4.0 → 2.5.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/CODE_OF_CONDUCT.md +133 -0
- package/CONTRIBUTING.md +41 -0
- package/FUNDING.md +5 -0
- package/README.md +62 -15
- package/SECURITY.md +52 -0
- package/main/manage/commands/FixerCommand.js +97 -97
- package/main/manage/managers/DebugMenu.js +10 -9
- package/package.json +59 -184
- package/runtime/index.js +14 -8
- package/utils/admin-auth.js +655 -576
- package/utils/config-manager.js +72 -72
- package/utils/env-manager.js +117 -26
- package/utils/i18n-helper.js +50 -49
- package/utils/json-output.js +13 -12
- package/utils/logger.js +7 -6
- package/utils/prompt-helper.js +44 -41
- package/utils/secure-errors.js +156 -154
- package/utils/security.js +235 -233
- package/utils/setup-enforcer.js +110 -109
- package/utils/terminal-icons.js +164 -163
- package/settings/i18ntk-config.json +0 -283
- package/utils/admin-pin.js +0 -520
- package/utils/arg-parser.js +0 -40
- package/utils/cli-args.js +0 -210
- package/utils/mini-commander.js +0 -179
- package/utils/missing-key-validator.js +0 -858
- package/utils/path-utils.js +0 -33
- package/utils/performance-optimizer.js +0 -246
- package/utils/prompt-new.js +0 -55
- package/utils/promptPin.js +0 -76
- package/utils/safe-json.js +0 -40
- package/utils/secure-backup.js +0 -340
- package/utils/security-check-improved.js +0 -393
- package/utils/security-config.js +0 -239
- package/utils/setup-validator.js +0 -717
- package/utils/ultra-performance-optimizer.js +0 -352
package/utils/prompt-helper.js
CHANGED
|
@@ -1,41 +1,44 @@
|
|
|
1
|
-
const { getGlobalReadline, closeGlobalReadline, ask } = require('./cli');
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
1
|
+
const { getGlobalReadline, closeGlobalReadline, ask } = require('./cli');
|
|
2
|
+
const { envManager } = require('./env-manager');
|
|
3
|
+
|
|
4
|
+
function isInteractive(opts={}) {
|
|
5
|
+
const envSilent = envManager.getBoolean('CI') ||
|
|
6
|
+
envManager.getBoolean('I18NTK_SILENT') ||
|
|
7
|
+
envManager.get('npm_config_loglevel') === 'silent';
|
|
8
|
+
if (opts.noPrompt) return false;
|
|
9
|
+
if (envSilent) return false;
|
|
10
|
+
return process.stdin.isTTY === true;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
class NoopPrompt {
|
|
14
|
+
question(_q) { return Promise.resolve(''); }
|
|
15
|
+
close() {}
|
|
16
|
+
async pressEnterToContinue() { return; }
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
class RLPrompt {
|
|
20
|
+
constructor() {
|
|
21
|
+
this.rl = getGlobalReadline();
|
|
22
|
+
this.closed = false;
|
|
23
|
+
}
|
|
24
|
+
question(q) {
|
|
25
|
+
if (this.closed) return Promise.resolve('');
|
|
26
|
+
return new Promise(res => this.rl.question(q, ans => res(ans)));
|
|
27
|
+
}
|
|
28
|
+
close() {
|
|
29
|
+
if (!this.closed) {
|
|
30
|
+
closeGlobalReadline();
|
|
31
|
+
this.closed = true;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async pressEnterToContinue(msg='\nPress Enter to continue...') {
|
|
35
|
+
if (this.closed) return;
|
|
36
|
+
await ask(msg);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function createPrompt(opts={}) {
|
|
41
|
+
return isInteractive(opts) ? new RLPrompt() : new NoopPrompt();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
module.exports = { createPrompt, isInteractive };
|
package/utils/secure-errors.js
CHANGED
|
@@ -1,154 +1,156 @@
|
|
|
1
|
-
// Secure error handling utilities
|
|
2
|
-
const crypto = require('crypto');
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
this.
|
|
12
|
-
this.
|
|
13
|
-
this.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
1
|
+
// Secure error handling utilities
|
|
2
|
+
const crypto = require('crypto');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const SecurityUtils = require('./security');
|
|
6
|
+
const { envManager } = require('./env-manager');
|
|
7
|
+
|
|
8
|
+
class SecureError extends Error {
|
|
9
|
+
constructor(message, code = 'SECURE_ERROR', details = {}) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.name = 'SecureError';
|
|
12
|
+
this.code = code;
|
|
13
|
+
this.details = details;
|
|
14
|
+
this.timestamp = new Date().toISOString();
|
|
15
|
+
this.errorId = crypto.randomBytes(8).toString('hex');
|
|
16
|
+
|
|
17
|
+
// Capture stack trace, excluding constructor call from it
|
|
18
|
+
Error.captureStackTrace(this, this.constructor);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
toJSON() {
|
|
22
|
+
return {
|
|
23
|
+
error: this.name,
|
|
24
|
+
message: this.message,
|
|
25
|
+
code: this.code,
|
|
26
|
+
errorId: this.errorId,
|
|
27
|
+
timestamp: this.timestamp
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static sanitizeError(error) {
|
|
32
|
+
if (error instanceof SecureError) {
|
|
33
|
+
return error.toJSON();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// For non-SecureError instances, return a sanitized version
|
|
37
|
+
return {
|
|
38
|
+
error: 'InternalError',
|
|
39
|
+
message: 'An internal error occurred',
|
|
40
|
+
code: 'INTERNAL_ERROR',
|
|
41
|
+
errorId: crypto.randomBytes(8).toString('hex'),
|
|
42
|
+
timestamp: new Date().toISOString()
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Common error types
|
|
48
|
+
class ValidationError extends SecureError {
|
|
49
|
+
constructor(message = 'Validation failed', details = {}) {
|
|
50
|
+
super(message, 'VALIDATION_ERROR', details);
|
|
51
|
+
this.name = 'ValidationError';
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
class SecurityError extends SecureError {
|
|
56
|
+
constructor(message = 'Security violation detected', details = {}) {
|
|
57
|
+
super(message, 'SECURITY_VIOLATION', details);
|
|
58
|
+
this.name = 'SecurityError';
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
class EncryptionError extends SecureError {
|
|
63
|
+
constructor(message = 'Encryption/decryption failed', details = {}) {
|
|
64
|
+
super(message, 'ENCRYPTION_ERROR', details);
|
|
65
|
+
this.name = 'EncryptionError';
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Secure error handler middleware
|
|
70
|
+
function secureErrorHandler(options = {}) {
|
|
71
|
+
const defaults = {
|
|
72
|
+
logErrors: envManager.get('NODE_ENV') !== 'production',
|
|
73
|
+
logFunction: console.error,
|
|
74
|
+
logFilePath: null,
|
|
75
|
+
sanitizeStack: true
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const config = { ...defaults, ...options };
|
|
79
|
+
|
|
80
|
+
// Ensure log directory exists
|
|
81
|
+
if (config.logFilePath && !SecurityUtils.safeExistsSync(path.dirname(config.logFilePath))) {
|
|
82
|
+
try {
|
|
83
|
+
fs.mkdirSync(path.dirname(config.logFilePath), { recursive: true });
|
|
84
|
+
} catch (e) {
|
|
85
|
+
console.error('Failed to create log directory:', e);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return function(error, req, res, next) {
|
|
90
|
+
// Handle specific error types
|
|
91
|
+
let statusCode = 500;
|
|
92
|
+
let response = {};
|
|
93
|
+
|
|
94
|
+
if (error instanceof ValidationError) {
|
|
95
|
+
statusCode = 400;
|
|
96
|
+
response = error.toJSON();
|
|
97
|
+
} else if (error instanceof SecurityError) {
|
|
98
|
+
statusCode = 403;
|
|
99
|
+
response = error.toJSON();
|
|
100
|
+
} else if (error instanceof EncryptionError) {
|
|
101
|
+
statusCode = 400;
|
|
102
|
+
response = error.toJSON();
|
|
103
|
+
} else {
|
|
104
|
+
// Generic error handling
|
|
105
|
+
response = SecureError.sanitizeError(error);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Log the error if enabled
|
|
109
|
+
if (config.logErrors) {
|
|
110
|
+
const logEntry = {
|
|
111
|
+
timestamp: new Date().toISOString(),
|
|
112
|
+
error: {
|
|
113
|
+
name: error.name,
|
|
114
|
+
message: error.message,
|
|
115
|
+
stack: config.sanitizeStack
|
|
116
|
+
? error.stack.split('\n').slice(0, 3).join('\n') + '\n ...'
|
|
117
|
+
: error.stack,
|
|
118
|
+
...(error.details && { details: error.details }),
|
|
119
|
+
errorId: response.errorId
|
|
120
|
+
},
|
|
121
|
+
request: req ? {
|
|
122
|
+
method: req.method,
|
|
123
|
+
url: req.originalUrl,
|
|
124
|
+
ip: req.ip,
|
|
125
|
+
userAgent: req.get('user-agent')
|
|
126
|
+
} : undefined
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
// Log to console
|
|
130
|
+
if (typeof config.logFunction === 'function') {
|
|
131
|
+
SecurityUtils.safeWriteFileSync(config.logFilePath, JSON.stringify(logEntry, null, 2));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Log to file if configured
|
|
135
|
+
if (config.logFilePath) {
|
|
136
|
+
SecurityUtils.safeWriteFileSync(
|
|
137
|
+
config.logFilePath,
|
|
138
|
+
JSON.stringify(logEntry) + '\n',
|
|
139
|
+
'utf8'
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Send response
|
|
145
|
+
res.status(statusCode).json(response);
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
module.exports = {
|
|
150
|
+
SecureError,
|
|
151
|
+
ValidationError,
|
|
152
|
+
SecurityError,
|
|
153
|
+
EncryptionError,
|
|
154
|
+
secureErrorHandler,
|
|
155
|
+
createError: (message, code, details) => new SecureError(message, code, details)
|
|
156
|
+
};
|