i18ntk 2.3.8 → 2.5.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.
@@ -1,33 +0,0 @@
1
- const path = require('path');
2
-
3
- function isWindows(p) {
4
- return /^[a-zA-Z]:\\/.test(p);
5
- }
6
-
7
- /**
8
- * Convert an absolute path to a relative path using forward slashes.
9
- * Works with both Windows and POSIX style paths.
10
- * @param {string} base - Base directory
11
- * @param {string} target - Target path
12
- * @returns {string} Relative path
13
- */
14
- function toRelative(base, target) {
15
- const rel = isWindows(base) || isWindows(target)
16
- ? path.win32.relative(base, target)
17
- : path.posix.relative(base, target);
18
- return rel.split(/[\\/]/).join('/');
19
- }
20
-
21
- /**
22
- * Resolve an array of paths against a base directory.
23
- * Handles both Windows and POSIX style paths.
24
- * @param {string} base - Base directory
25
- * @param {string[]} paths - Paths to resolve
26
- * @returns {string[]} Resolved absolute paths
27
- */
28
- function resolvePaths(base, paths) {
29
- const resolver = isWindows(base) ? path.win32.resolve : path.posix.resolve;
30
- return paths.map(p => resolver(base, p));
31
- }
32
-
33
- module.exports = { toRelative, resolvePaths };
@@ -1,246 +0,0 @@
1
- /**
2
- * Ultra-Performance Optimizer
3
- * Advanced performance tuning utilities for i18n toolkit
4
- * Targets sub-40ms processing for 200k keys with <10MB memory
5
- */
6
-
7
- const os = require('os');
8
- const fs = require('fs');
9
- const path = require('path');
10
-
11
- class UltraPerformanceOptimizer {
12
- constructor() {
13
- this.cpuCores = os.cpus().length;
14
- this.totalMemory = os.totalmem();
15
- this.availableMemory = this.totalMemory * 0.8; // Use 80% of system memory
16
- this.optimalSettings = this.calculateOptimalSettings();
17
- }
18
-
19
- /**
20
- * Calculate optimal settings based on system resources
21
- * @returns {Object} Optimized configuration
22
- */
23
- calculateOptimalSettings() {
24
- const memoryPerKey = 50; // bytes per key (very aggressive)
25
- const maxKeysInMemory = Math.floor(this.availableMemory / memoryPerKey);
26
-
27
- return {
28
- batchSize: Math.min(2000, Math.floor(maxKeysInMemory / 100)),
29
- concurrency: Math.min(this.cpuCores * 2, 32),
30
- memoryLimit: Math.floor(this.availableMemory / 1024 / 1024 * 0.7),
31
- bufferSize: 64 * 1024,
32
- cacheStrategy: 'lru',
33
- compression: 'brotli',
34
- streaming: true,
35
- parallelProcessing: true,
36
- aggressiveGC: true,
37
- validateOnLoad: false,
38
- validateOnSave: false,
39
- skipBackup: true,
40
- minimalLogging: true
41
- };
42
- }
43
-
44
- /**
45
- * Generate ultra-performance configuration
46
- * @returns {Object} Ultra-performance config
47
- */
48
- generateUltraConfig() {
49
- return {
50
- processing: {
51
- mode: 'ultra-extreme',
52
- batchSize: this.optimalSettings.batchSize,
53
- concurrency: this.optimalSettings.concurrency,
54
- timeout: 5000,
55
- retryAttempts: 0,
56
- retryDelay: 0,
57
- maxFileSize: 1024 * 1024, // 1MB max files
58
- validateOnSave: false,
59
- validateOnLoad: false,
60
- cacheEnabled: true,
61
- cacheTTL: 300000, // 5 minutes
62
- autoBackup: false,
63
- fileFilter: "**/*.json",
64
- memoryLimit: `${this.optimalSettings.memoryLimit}MB`,
65
- garbageCollection: true,
66
- gcInterval: 500
67
- },
68
- optimization: {
69
- memoryLimit: `${this.optimalSettings.memoryLimit}MB`,
70
- localeOptimizer: true,
71
- compression: this.optimalSettings.compression,
72
- parallelProcessing: this.optimalSettings.parallelProcessing,
73
- streaming: this.optimalSettings.streaming,
74
- bufferSize: this.optimalSettings.bufferSize,
75
- aggressiveGC: this.optimalSettings.aggressiveGC,
76
- minimalLogging: this.optimalSettings.minimalLogging
77
- },
78
- filesystem: {
79
- concurrentReads: this.optimalSettings.concurrency,
80
- bufferSize: this.optimalSettings.bufferSize,
81
- cacheDirectory: '.cache-ultra',
82
- tempDirectory: '.tmp-ultra',
83
- cleanupInterval: 30000,
84
- compression: this.optimalSettings.compression
85
- }
86
- };
87
- }
88
-
89
- /**
90
- * Apply memory-efficient processing strategies
91
- * @param {Array} keys - Translation keys to process
92
- * @param {Function} processor - Processing function
93
- * @returns {Promise<Array>} Processed results
94
- */
95
- async processWithMemoryEfficiency(keys, processor) {
96
- const batchSize = this.optimalSettings.batchSize;
97
- const results = [];
98
-
99
- for (let i = 0; i < keys.length; i += batchSize) {
100
- const batch = keys.slice(i, i + batchSize);
101
- const batchResults = await this.processBatch(batch, processor);
102
- results.push(...batchResults);
103
-
104
- // Aggressive memory management
105
- if (global.gc && i % (batchSize * 10) === 0) {
106
- global.gc();
107
- }
108
- }
109
-
110
- return results;
111
- }
112
-
113
- /**
114
- * Process a single batch with parallel execution
115
- * @param {Array} batch - Batch of keys
116
- * @param {Function} processor - Processing function
117
- * @returns {Promise<Array>} Batch results
118
- */
119
- async processBatch(batch, processor) {
120
- const chunkSize = Math.ceil(batch.length / this.optimalSettings.concurrency);
121
- const chunks = [];
122
-
123
- for (let i = 0; i < batch.length; i += chunkSize) {
124
- chunks.push(batch.slice(i, i + chunkSize));
125
- }
126
-
127
- const promises = chunks.map(chunk => this.processChunk(chunk, processor));
128
- const results = await Promise.all(promises);
129
- return results.flat();
130
- }
131
-
132
- /**
133
- * Process a chunk of keys
134
- * @param {Array} chunk - Chunk of keys
135
- * @param {Function} processor - Processing function
136
- * @returns {Promise<Array>} Chunk results
137
- */
138
- async processChunk(chunk, processor) {
139
- return chunk.map(processor);
140
- }
141
-
142
- /**
143
- * Generate performance report
144
- * @param {Object} metrics - Performance metrics
145
- * @returns {Object} Formatted report
146
- */
147
- generateReport(metrics) {
148
- return {
149
- timestamp: new Date().toISOString(),
150
- system: {
151
- cpuCores: this.cpuCores,
152
- totalMemory: `${Math.floor(this.totalMemory / 1024 / 1024)}MB`,
153
- platform: os.platform(),
154
- nodeVersion: process.version
155
- },
156
- optimization: {
157
- batchSize: this.optimalSettings.batchSize,
158
- concurrency: this.optimalSettings.concurrency,
159
- memoryLimit: this.optimalSettings.memoryLimit,
160
- compression: this.optimalSettings.compression
161
- },
162
- performance: {
163
- processingTime: metrics.processingTime,
164
- memoryUsage: metrics.memoryUsage,
165
- throughput: metrics.throughput,
166
- efficiency: metrics.efficiency
167
- },
168
- recommendations: this.generateRecommendations(metrics)
169
- };
170
- }
171
-
172
- /**
173
- * Generate performance recommendations
174
- * @param {Object} metrics - Performance metrics
175
- * @returns {Array} Recommendations
176
- */
177
- generateRecommendations(metrics) {
178
- const recommendations = [];
179
-
180
- if (metrics.processingTime > 40) {
181
- recommendations.push('Consider reducing batch size for better memory locality');
182
- }
183
-
184
- if (metrics.memoryUsage > 15) {
185
- recommendations.push('Enable more aggressive garbage collection');
186
- }
187
-
188
- if (metrics.throughput < 4000000) {
189
- recommendations.push('Increase concurrency if CPU cores available');
190
- }
191
-
192
- return recommendations;
193
- }
194
-
195
- /**
196
- * Benchmark current system capabilities
197
- * @returns {Promise<Object>} Benchmark results
198
- */
199
- async benchmarkSystem() {
200
- const testKeys = Array.from({ length: 10000 }, (_, i) => `key_${i}`);
201
- const startTime = process.hrtime.bigint();
202
- const startMemory = process.memoryUsage();
203
-
204
- const results = await this.processWithMemoryEfficiency(testKeys, key => ({
205
- key,
206
- processed: true,
207
- timestamp: Date.now()
208
- }));
209
-
210
- const endTime = process.hrtime.bigint();
211
- const endMemory = process.memoryUsage();
212
-
213
- const processingTime = Number(endTime - startTime) / 1000000; // Convert to ms
214
- const memoryDelta = (endMemory.heapUsed - startMemory.heapUsed) / 1024 / 1024;
215
- const throughput = testKeys.length / (processingTime / 1000);
216
-
217
- return {
218
- processingTime,
219
- memoryUsage: Math.max(0, memoryDelta),
220
- throughput,
221
- efficiency: testKeys.length / processingTime * 1000
222
- };
223
- }
224
- }
225
-
226
- module.exports = UltraPerformanceOptimizer;
227
-
228
- // CLI usage
229
- if (require.main === module) {
230
- const optimizer = new UltraPerformanceOptimizer();
231
- optimizer.benchmarkSystem().then(metrics => {
232
- const report = optimizer.generateReport(metrics);
233
- console.log('🚀 Ultra-Performance Analysis');
234
- console.log('================================');
235
- console.log(`Processing Time: ${metrics.processingTime.toFixed(2)}ms`);
236
- console.log(`Memory Usage: ${metrics.memoryUsage.toFixed(2)}MB`);
237
- console.log(`Throughput: ${(metrics.throughput / 1000000).toFixed(2)}M keys/sec`);
238
- console.log(`Efficiency: ${metrics.efficiency.toFixed(0)} keys/ms`);
239
-
240
- console.log('\n⚙️ Optimal Settings:');
241
- console.log(JSON.stringify(optimizer.optimalSettings, null, 2));
242
-
243
- console.log('\n📊 Recommendations:');
244
- report.recommendations.forEach(rec => console.log(`- ${rec}`));
245
- });
246
- }
@@ -1,55 +0,0 @@
1
- const readline = require('readline');
2
- const { logger } = require('./logger');
3
-
4
- class Prompt {
5
- constructor() {
6
- this.rl = readline.createInterface({
7
- input: process.stdin,
8
- output: process.stdout
9
- });
10
- }
11
-
12
- close() {
13
- this.rl.close();
14
- }
15
-
16
- async question(questionText) {
17
- return new Promise((resolve) => {
18
- this.rl.question(questionText, (answer) => {
19
- resolve(answer.trim());
20
- });
21
- });
22
- }
23
-
24
- async confirm(questionText, defaultValue = false) {
25
- const answer = await this.question(`${questionText} (${defaultValue ? 'Y/n' : 'y/N'}) `);
26
- if (answer === '') return defaultValue;
27
- return /^y|yes$/i.test(answer);
28
- }
29
-
30
- async select(questionText, choices, defaultIndex = 0) {
31
- logger.log(`\n${questionText}:`);
32
- choices.forEach((choice, index) => {
33
- logger.log(` ${index + 1}. ${choice}`);
34
- });
35
-
36
- while (true) {
37
- const answer = await this.question(`\nSelect an option (1-${choices.length}): `);
38
- const selected = parseInt(answer, 10) - 1;
39
- if (!isNaN(selected) && selected >= 0 && selected < choices.length) {
40
- return selected;
41
- }
42
- logger.log('Invalid selection. Please try again.');
43
- }
44
- }
45
-
46
- async input(questionText, defaultValue = '') {
47
- const answer = await this.question(`${questionText}${defaultValue ? ` [${defaultValue}]` : ''}: `);
48
- return answer || defaultValue;
49
- }
50
- }
51
-
52
- const prompt = new Prompt();
53
- process.on('exit', () => prompt.close());
54
-
55
- module.exports = prompt;
@@ -1,76 +0,0 @@
1
- const readline = require('readline');
2
-
3
- async function promptPin({ rl, label = 'Enter 4-digit Admin PIN: ', length = 4, digitsOnly = true } = {}) {
4
- return rawMaskedPrompt(rl, label, { length, digitsOnly });
5
- }
6
-
7
- async function promptPinConfirm(rl, label1 = 'Enter new 4-digit Admin PIN: ', label2 = 'Confirm PIN: ') {
8
- const pin1 = await promptPin({ rl, label: label1 });
9
- const pin2 = await promptPin({ rl, label: label2 });
10
- if (pin1 !== pin2) throw new Error('PINs do not match');
11
- return pin1;
12
- }
13
-
14
- function rawMaskedPrompt(rl, promptText, { length = 4, digitsOnly = true } = {}) {
15
- return new Promise((resolve) => {
16
- const input = rl.input;
17
- const output = rl.output;
18
-
19
- const isRaw = input.isRaw;
20
- if (!isRaw) input.setRawMode && input.setRawMode(true);
21
-
22
- let buf = '';
23
-
24
- const onData = (chunk) => {
25
- const s = chunk.toString('utf8');
26
-
27
- if (s === '\r' || s === '\n') {
28
- if (buf.length === length) {
29
- output.write('\n');
30
- cleanup();
31
- return resolve(buf);
32
- }
33
- return;
34
- }
35
-
36
- if (s === '\u0003') {
37
- output.write('\n');
38
- cleanup();
39
- process.exit(130);
40
- }
41
-
42
- if (s === '\u0008' || s === '\u007f') {
43
- if (buf.length > 0) buf = buf.slice(0, -1);
44
- repaint();
45
- return;
46
- }
47
-
48
- const ch = s;
49
- if (digitsOnly) {
50
- if (/^\d$/.test(ch) && buf.length < length) {
51
- buf += ch;
52
- repaint();
53
- }
54
- } else if (buf.length < length) {
55
- buf += ch;
56
- repaint();
57
- }
58
- };
59
-
60
- const repaint = () => {
61
- output.cursorTo && output.cursorTo(0);
62
- output.clearLine && output.clearLine(1);
63
- output.write(promptText + '*'.repeat(buf.length));
64
- };
65
-
66
- const cleanup = () => {
67
- input.removeListener('data', onData);
68
- if (!isRaw) input.setRawMode && input.setRawMode(false);
69
- };
70
-
71
- output.write(promptText);
72
- input.on('data', onData);
73
- });
74
- }
75
-
76
- module.exports = { promptPin, promptPinConfirm };
@@ -1,40 +0,0 @@
1
- // utils/safe-json.js
2
- const fs = require('fs');
3
-
4
- function stripBOM(s) {
5
- if (typeof s === 'string' && s.charCodeAt(0) === 0xFEFF) return s.slice(1);
6
- return s;
7
- }
8
-
9
- /**
10
- * Safe JSON load with guardrails.
11
- * - Max file size (default 1MB)
12
- * - BOM stripping
13
- * - Single, typed error (no loops)
14
- */
15
- async function readJsonSafe(filePath, { maxBytes = 1_000_000 } = {}) {
16
- const buf = await fs.promises.readFile(filePath);
17
- if (buf.length === 0) {
18
- const err = new Error('Empty JSON file');
19
- err.code = 'EJSONEMPTY';
20
- err.path = filePath;
21
- throw err;
22
- }
23
- if (buf.length > maxBytes) {
24
- const err = new Error(`JSON too large (${buf.length} bytes)`);
25
- err.code = 'EJSONTOOBIG';
26
- err.path = filePath;
27
- throw err;
28
- }
29
- try {
30
- return JSON.parse(stripBOM(buf.toString('utf8')));
31
- } catch (e) {
32
- const err = new Error(`Invalid JSON`);
33
- err.code = 'EJSONPARSE';
34
- err.path = filePath;
35
- err.cause = e;
36
- throw err;
37
- }
38
- }
39
-
40
- module.exports = { readJsonSafe };