i18ntk 1.7.2 → 1.7.5
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 +151 -97
- package/main/i18ntk-analyze.js +18 -16
- package/main/i18ntk-autorun.js +66 -8
- package/main/i18ntk-fixer.js +653 -0
- package/main/i18ntk-init.js +1 -1
- package/main/i18ntk-manage.js +44 -41
- package/main/i18ntk-summary.js +8 -2
- package/main/i18ntk-ui.js +0 -1
- package/main/i18ntk-validate.js +3 -2
- package/package.json +36 -11
- package/scripts/fixer.test.js +90 -0
- package/scripts/test-runner.js +2 -1
- package/settings/i18ntk-config.json +8 -1
- package/settings/initialization.json +3 -3
- package/ui-locales/de.json +67 -1
- package/ui-locales/en.json +67 -1
- package/ui-locales/es.json +67 -1
- package/ui-locales/fr.json +67 -1
- package/ui-locales/ja.json +67 -1
- package/ui-locales/ru.json +67 -1
- package/ui-locales/zh.json +67 -1
- package/utils/config-helper.js +102 -31
- package/utils/security-check.js +125 -14
- package/utils/security.js +2 -1
package/README.md
CHANGED
|
@@ -2,18 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|

|
|
4
4
|
|
|
5
|
-
**Version:** 1.7.
|
|
6
|
-
**Last Updated:** 2025-08-
|
|
5
|
+
**Version:** 1.7.5
|
|
6
|
+
**Last Updated:** 2025-08-11
|
|
7
7
|
**GitHub Repository:** [vladnoskv/i18ntk](https://github.com/vladnoskv/i18ntk)
|
|
8
8
|
|
|
9
|
-
[](https://www.npmjs.com/package/i18ntk) [](https://badge.fury.io/js/i18ntk) [](https://nodejs.org/) [](https://www.npmjs.com/package/i18ntk) [](https://github.com/vladnoskv/i18ntk)
|
|
10
|
-
[](https://socket.dev/npm/package/i18ntk/overview/1.7.2)
|
|
9
|
+
[](https://www.npmjs.com/package/i18ntk) [](https://badge.fury.io/js/i18ntk) [](https://nodejs.org/) [](https://www.npmjs.com/package/i18ntk) [](https://socket.dev/npm/package/i18ntk/overview/1.7.5) [](https://github.com/vladnoskv/i18ntk)
|
|
11
10
|
|
|
12
11
|
**🚀 The fastest way to manage translations across any framework or vanilla JavaScript projects**
|
|
13
12
|
|
|
14
13
|
**Framework Support:** Auto-detects popular libraries (React i18next, Vue i18n, i18next, Nuxt i18n, Svelte i18n) or works without a framework. i18ntk manages translation files and validation—it does NOT implement translation logic like i18next or Vue i18n.
|
|
15
14
|
|
|
16
|
-
> **v1.7.
|
|
15
|
+
> **v1.7.5** – **CRITICAL SECURITY FIXES** - Zero shell access vulnerabilities eliminated. NEW Interactive Translation Fixer Tool with custom placeholder markers, selective language/file fixing, mass fix capabilities, and 7-language UI support; enhanced security logging, flexible 4-6 digit PIN authentication, configuration stability improvements, and CI/CD silent mode support; maintains 97% speed improvement.
|
|
17
16
|
|
|
18
17
|
## 🚀 Quick Start
|
|
19
18
|
|
|
@@ -30,32 +29,63 @@ i18ntk complete --source ./src
|
|
|
30
29
|
i18ntk validate --source ./locales
|
|
31
30
|
```
|
|
32
31
|
|
|
32
|
+
---
|
|
33
|
+
|
|
33
34
|
## ⚡ Performance
|
|
34
35
|
|
|
35
|
-
| Mode
|
|
36
|
-
|
|
37
|
-
| **Ultra
|
|
38
|
-
| **Extreme**
|
|
39
|
-
| Ultra
|
|
40
|
-
| Optimized
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
- **
|
|
49
|
-
- **
|
|
50
|
-
- **
|
|
51
|
-
- **
|
|
52
|
-
- **
|
|
53
|
-
- **
|
|
54
|
-
- **
|
|
55
|
-
- **
|
|
56
|
-
- **
|
|
57
|
-
|
|
58
|
-
|
|
36
|
+
| Mode | Time (200k keys) | Memory | Package Size |
|
|
37
|
+
| ----------------- | ---------------- | ------ | ------------ |
|
|
38
|
+
| **Ultra‑Extreme** | **15.38ms** | 1.62MB | 115KB–830KB |
|
|
39
|
+
| **Extreme** | 38.90ms | 0.61MB | 115KB–830KB |
|
|
40
|
+
| Ultra | 336.8ms | 0.64MB | Configurable |
|
|
41
|
+
| Optimized | 847.9ms | 0.45MB | Full package |
|
|
42
|
+
|
|
43
|
+
> Benchmarks are internal; actual results vary by CPU, filesystem, and dataset.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 🎯 Highlights
|
|
48
|
+
|
|
49
|
+
- **NEW in 1.7.5:** Security‑hardened codebase: zero shell execution in production.
|
|
50
|
+
- **Interactive Translation Fixer:** `i18ntk fixer` with guided flows and custom marker detection.
|
|
51
|
+
- **Ultra‑Extreme performance:** 97% speed improvement — **15.38ms** for 200k keys.
|
|
52
|
+
- **Security & Privacy:** PIN protection with AES‑256‑GCM; strict path and input validation.
|
|
53
|
+
- **Sizing tools:** Interactive locale optimizer (up to **86%** size reduction) and reports.
|
|
54
|
+
- **Zero dependencies:** Lightweight, production‑ready.
|
|
55
|
+
- **Watch helper:** Optional `--watch` keeps translations in sync.
|
|
56
|
+
- **Framework‑agnostic:** Works with React, Vue, Svelte, Nuxt, i18next, or plain JSON.
|
|
57
|
+
- **Scale:** Linear scaling up to 5M keys/second with ultra‑extreme settings.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 🛡️ Security in 1.7.5
|
|
62
|
+
|
|
63
|
+
### Summary
|
|
64
|
+
|
|
65
|
+
- **Zero Shell Access:** Removed `execSync`, `spawnSync`, and related calls from production paths.
|
|
66
|
+
- **Direct FS APIs:** Replaced shell calls with safe `fs`/`path` operations.
|
|
67
|
+
- **Path Safety:** Normalization + traversal prevention on all file inputs.
|
|
68
|
+
- **Input Validation:** Sanitization on CLI flags and config values.
|
|
69
|
+
- **Session Security:** PIN‑protected admin operations, session timeout, exponential backoff.
|
|
70
|
+
- **Encrypted Backups:** AES‑256‑GCM for stored PIN and backups.
|
|
71
|
+
|
|
72
|
+
### Before → After
|
|
73
|
+
|
|
74
|
+
| Area | Before (risk) | After (1.7.5) |
|
|
75
|
+
| --------------------- | ---------------------------- | --------------------------------- |
|
|
76
|
+
| Shell execution | Possible via `child_process` | **Removed entirely** |
|
|
77
|
+
| File ops | Mixed shell + Node | **Node fs/path only** |
|
|
78
|
+
| Input & path handling | Inconsistent in edge cases | **Validated + normalized** |
|
|
79
|
+
| Admin controls | Optional PIN | **PIN + cooldown + timeout** |
|
|
80
|
+
| Backups | Plain backups possible | **AES‑256‑GCM encrypted backups** |
|
|
81
|
+
|
|
82
|
+
> **Verification tip:** `grep -R "child_process" node_modules/i18ntk` should return nothing in 1.7.5 production code.
|
|
83
|
+
|
|
84
|
+
**Backward compatibility:** No breaking changes expected; commands and outputs are unchanged except for safer internals.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## 📸 Screenshots
|
|
59
89
|
|
|
60
90
|
| **Logo & Branding** | **Framework Detection** |
|
|
61
91
|
|:-------------------:|:----------------------:|
|
|
@@ -71,24 +101,27 @@ i18ntk validate --source ./locales
|
|
|
71
101
|
|
|
72
102
|
## 📊 Commands
|
|
73
103
|
|
|
74
|
-
| Command
|
|
75
|
-
|
|
76
|
-
| `init`
|
|
77
|
-
| `analyze`
|
|
78
|
-
| `complete` | Generate translations
|
|
79
|
-
| `validate` | Check translation quality
|
|
80
|
-
| `sync`
|
|
81
|
-
| `usage`
|
|
82
|
-
| `doctor`
|
|
83
|
-
| `sizing`
|
|
104
|
+
| Command | Purpose | Example |
|
|
105
|
+
| ---------- | ------------------------------- | ---------------------------------------- |
|
|
106
|
+
| `init` | Setup project | `i18ntk init --interactive` |
|
|
107
|
+
| `analyze` | Find missing translations | `i18ntk analyze --source ./src` |
|
|
108
|
+
| `complete` | Generate translations | `i18ntk complete --config=ultra-extreme` |
|
|
109
|
+
| `validate` | Check translation quality | `i18ntk validate --strict` |
|
|
110
|
+
| `sync` | Sync across languages | `i18ntk sync --languages en,es,fr` |
|
|
111
|
+
| `usage` | Analyze usage patterns | `i18ntk usage --format=json` |
|
|
112
|
+
| `doctor` | Diagnose configuration issues | `i18ntk doctor` |
|
|
113
|
+
| `sizing` | Optimize package size | `i18ntk sizing --interactive` |
|
|
114
|
+
| `fixer` | Fix broken translations/markers | `i18ntk fixer --interactive` |
|
|
115
|
+
|
|
116
|
+
---
|
|
84
117
|
|
|
85
118
|
## 🔧 Configuration
|
|
86
119
|
|
|
87
|
-
|
|
120
|
+
Create `settings/i18ntk-config.json` (auto‑generated by `init`):
|
|
88
121
|
|
|
89
122
|
```json
|
|
90
123
|
{
|
|
91
|
-
"version": "1.7.
|
|
124
|
+
"version": "1.7.5",
|
|
92
125
|
"sourceDir": "./locales",
|
|
93
126
|
"outputDir": "./i18ntk-reports",
|
|
94
127
|
"defaultLanguage": "en",
|
|
@@ -116,21 +149,57 @@ Configuration is managed through the `settings/i18ntk-config.json` file:
|
|
|
116
149
|
|
|
117
150
|
### Environment Variables
|
|
118
151
|
|
|
119
|
-
You can override
|
|
152
|
+
You can override paths with environment variables:
|
|
153
|
+
|
|
154
|
+
| Variable | Overrides | Description |
|
|
155
|
+
| --------------------- | ------------- | ------------------------------------ |
|
|
156
|
+
| `I18NTK_PROJECT_ROOT` | `projectRoot` | Base project directory |
|
|
157
|
+
| `I18NTK_SOURCE_DIR` | `sourceDir` | Location of source translation files |
|
|
158
|
+
| `I18NTK_I18N_DIR` | `i18nDir` | Working i18n directory |
|
|
159
|
+
| `I18NTK_OUTPUT_DIR` | `outputDir` | Output directory for reports |
|
|
160
|
+
|
|
161
|
+
**Precedence:** CLI flags ⟶ environment vars ⟶ config file defaults.
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## 🔧 Translation Fixer (1.7.4+)
|
|
166
|
+
|
|
167
|
+
Interactive tool to locate and repair placeholders such as `{{NOT_TRANSLATED}}`, `__UNTRANSLATED__`, or custom markers.
|
|
120
168
|
|
|
121
|
-
|
|
122
|
-
|----------|-----------|-------------|
|
|
123
|
-
| `I18NTK_PROJECT_ROOT` | `projectRoot` | Base project directory |
|
|
124
|
-
| `I18NTK_SOURCE_DIR` | `sourceDir` | Location of source translation files |
|
|
125
|
-
| `I18NTK_I18N_DIR` | `i18nDir` | Working i18n directory |
|
|
126
|
-
| `I18NTK_OUTPUT_DIR` | `outputDir` | Output directory for generated reports |
|
|
169
|
+
**Examples:**
|
|
127
170
|
|
|
128
|
-
|
|
171
|
+
```bash
|
|
172
|
+
# Guided mode
|
|
173
|
+
i18ntk fixer --interactive
|
|
174
|
+
|
|
175
|
+
# Fix specific languages with custom markers
|
|
176
|
+
i18ntk fixer --languages en,es,fr --markers "{{NOT_TRANSLATED}},__MISSING__"
|
|
177
|
+
|
|
178
|
+
# Target a directory + auto-fix with reporting
|
|
179
|
+
i18ntk fixer --source ./src/locales --auto-fix --report
|
|
180
|
+
|
|
181
|
+
# Detect custom placeholder styles
|
|
182
|
+
i18ntk fixer --markers "TODO_TRANSLATE,PLACEHOLDER_TEXT,MISSING_TRANSLATION"
|
|
183
|
+
|
|
184
|
+
# Fix all available languages (default markers)
|
|
185
|
+
i18ntk fixer --languages all
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
**Interactive flow:**
|
|
129
189
|
|
|
130
|
-
|
|
190
|
+
- Welcome & help panel
|
|
191
|
+
- Marker configuration (built‑in + custom)
|
|
192
|
+
- Language and directory selection
|
|
193
|
+
- Preview & confirmation
|
|
194
|
+
- Real‑time progress + stats
|
|
195
|
+
- Report generation (before/after, per‑file, per‑language)
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## 🌍 Locale Size Optimizer
|
|
131
200
|
|
|
132
201
|
```bash
|
|
133
|
-
# Interactive
|
|
202
|
+
# Interactive selection
|
|
134
203
|
node scripts/locale-optimizer.js --interactive
|
|
135
204
|
|
|
136
205
|
# Keep specific languages
|
|
@@ -139,49 +208,46 @@ node scripts/locale-optimizer.js --keep en,es,de
|
|
|
139
208
|
# Restore all languages
|
|
140
209
|
node scripts/locale-optimizer.js --restore
|
|
141
210
|
|
|
142
|
-
#
|
|
211
|
+
# List sizes
|
|
143
212
|
node scripts/locale-optimizer.js --list
|
|
144
213
|
```
|
|
145
214
|
|
|
215
|
+
> **Result:** Reduce UI locale bundle size by up to **86%** (e.g., 830.4KB → 115.3KB for English‑only).
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
146
219
|
## 🏗️ Integration Examples
|
|
147
220
|
|
|
148
221
|
### React
|
|
149
|
-
|
|
150
|
-
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
# Extract from React components
|
|
151
225
|
i18ntk extract --source ./src --framework react
|
|
226
|
+
```
|
|
152
227
|
|
|
153
|
-
|
|
228
|
+
```js
|
|
229
|
+
// i18next setup (example)
|
|
154
230
|
import i18n from './i18n';
|
|
231
|
+
import i18next from 'i18next';
|
|
155
232
|
i18next.init({ resources: i18n, lng: 'en' });
|
|
156
233
|
```
|
|
157
234
|
|
|
158
235
|
### Vue
|
|
159
|
-
|
|
160
|
-
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
# Extract from Vue components
|
|
161
239
|
i18ntk extract --source ./src --framework vue
|
|
240
|
+
```
|
|
162
241
|
|
|
163
|
-
|
|
242
|
+
```js
|
|
243
|
+
// vue-i18n setup (example)
|
|
164
244
|
import { createI18n } from 'vue-i18n';
|
|
165
245
|
const i18n = createI18n({ locale: 'en', messages: translations });
|
|
166
246
|
```
|
|
167
247
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
- **Admin PIN Protection**: AES-256-GCM encryption with 30-min sessions
|
|
171
|
-
- **Advanced Input Sanitization**: Comprehensive path traversal prevention
|
|
172
|
-
- **Zero-Trust Architecture**: All inputs validated and sanitized
|
|
173
|
-
- **Session Management**: Automatic timeout & cleanup with exponential backoff
|
|
174
|
-
- **File Validation**: Safe file operations with permission checks
|
|
175
|
-
- **Edge Case Security**: Robust handling of security edge cases
|
|
176
|
-
- **Encrypted Backups**: AES-256 encrypted backup storage
|
|
177
|
-
|
|
178
|
-
### 🎯 **NEW INTERACTIVE LOCALE OPTIMIZER** - up to 86% Package Size Reduction
|
|
179
|
-
|
|
180
|
-
- **Package Size**: 830.4KB → 115.3KB (86% reduction for English only)
|
|
181
|
-
- **Smart Management**: Interactive selection with automatic backups
|
|
182
|
-
- **Zero Breaking Changes**: Safe restoration from backups
|
|
248
|
+
---
|
|
183
249
|
|
|
184
|
-
##
|
|
250
|
+
## 📁 Project Structure for local package development
|
|
185
251
|
|
|
186
252
|
```
|
|
187
253
|
your-project/
|
|
@@ -198,30 +264,18 @@ your-project/
|
|
|
198
264
|
|
|
199
265
|
## 🚨 Important Notes
|
|
200
266
|
|
|
201
|
-
-
|
|
202
|
-
- **
|
|
203
|
-
-
|
|
204
|
-
-
|
|
205
|
-
- **All improvements applied automatically** on update
|
|
206
|
-
|
|
267
|
+
- Locale files are **auto‑backed up** before optimization.
|
|
268
|
+
- Prefer the **interactive optimizer** for safe locale management.
|
|
269
|
+
- Versions **prior to 1.7.1** are deprecated.
|
|
270
|
+
- Upgrades apply improvements automatically; no migration steps required for 1.7.5.
|
|
207
271
|
|
|
208
|
-
|
|
209
|
-
- ✅ Ultra-extreme performance improvements
|
|
210
|
-
- ✅ Enhanced security with PIN protection
|
|
211
|
-
- ✅ Comprehensive backup & recovery
|
|
212
|
-
- ✅ Edge case handling
|
|
213
|
-
- ✅ Memory optimization
|
|
214
|
-
- ✅ Advanced configuration management
|
|
215
|
-
|
|
216
|
-
#### Breaking Changes
|
|
217
|
-
- **None** - 1.6.3 is fully backward compatible
|
|
272
|
+
---
|
|
218
273
|
|
|
219
|
-
##
|
|
274
|
+
## 🤝 Contributing & Support
|
|
220
275
|
|
|
221
|
-
- **Issues
|
|
222
|
-
- **
|
|
223
|
-
- **
|
|
224
|
-
- **Version
|
|
225
|
-
---
|
|
276
|
+
- **Issues:** [GitHub Issues](https://github.com/vladnoskv/i18ntk/issues)
|
|
277
|
+
- **Docs:** `./docs` (full walkthroughs and examples)
|
|
278
|
+
- **Benchmarks:** `./benchmarks/results`
|
|
279
|
+
- **Version:** `i18ntk --version`
|
|
226
280
|
|
|
227
|
-
**Made for the global
|
|
281
|
+
**Made for the global dev community.** ❤️
|
package/main/i18ntk-analyze.js
CHANGED
|
@@ -189,25 +189,26 @@ class I18nAnalyzer {
|
|
|
189
189
|
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
190
190
|
issues.push(...this.analyzeTranslationIssues(value, sourceObj, fullKey));
|
|
191
191
|
} else if (typeof value === 'string') {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
192
|
+
const markers = this.config.notTranslatedMarkers || [this.config.notTranslatedMarker];
|
|
193
|
+
if (markers.some(m => value === m)) {
|
|
194
|
+
issues.push({
|
|
195
|
+
type: 'not_translated',
|
|
196
|
+
key: fullKey,
|
|
197
|
+
value,
|
|
197
198
|
sourceValue: sourceValue || 'N/A'
|
|
198
199
|
});
|
|
199
200
|
} else if (value === '') {
|
|
200
|
-
issues.push({
|
|
201
|
-
type: 'empty_value',
|
|
202
|
-
key: fullKey,
|
|
203
|
-
value,
|
|
201
|
+
issues.push({
|
|
202
|
+
type: 'empty_value',
|
|
203
|
+
key: fullKey,
|
|
204
|
+
value,
|
|
204
205
|
sourceValue: sourceValue || 'N/A'
|
|
205
206
|
});
|
|
206
|
-
} else if (value.includes(
|
|
207
|
-
issues.push({
|
|
208
|
-
type: 'partial_translation',
|
|
209
|
-
key: fullKey,
|
|
210
|
-
value,
|
|
207
|
+
} else if (markers.some(m => value.includes(m))) {
|
|
208
|
+
issues.push({
|
|
209
|
+
type: 'partial_translation',
|
|
210
|
+
key: fullKey,
|
|
211
|
+
value,
|
|
211
212
|
sourceValue: sourceValue || 'N/A'
|
|
212
213
|
});
|
|
213
214
|
} else if (sourceValue && value === sourceValue) {
|
|
@@ -232,14 +233,15 @@ class I18nAnalyzer {
|
|
|
232
233
|
let empty = 0;
|
|
233
234
|
let partial = 0;
|
|
234
235
|
|
|
236
|
+
const markers = this.config.notTranslatedMarkers || [this.config.notTranslatedMarker];
|
|
235
237
|
const count = (item) => {
|
|
236
238
|
if (typeof item === 'string') {
|
|
237
239
|
total++;
|
|
238
|
-
if (item ===
|
|
240
|
+
if (markers.some(m => item === m)) {
|
|
239
241
|
notTranslated++;
|
|
240
242
|
} else if (item === '') {
|
|
241
243
|
empty++;
|
|
242
|
-
} else if (item.includes(
|
|
244
|
+
} else if (markers.some(m => item.includes(m))) {
|
|
243
245
|
partial++;
|
|
244
246
|
} else {
|
|
245
247
|
translated++;
|
package/main/i18ntk-autorun.js
CHANGED
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
|
|
13
13
|
const fs = require('fs');
|
|
14
14
|
const path = require('path');
|
|
15
|
-
const { spawnSync } = require('child_process');
|
|
16
15
|
const { loadTranslations, t } = require('../utils/i18n-helper');
|
|
17
16
|
loadTranslations(process.env.I18NTK_LANG);
|
|
18
17
|
const { getUnifiedConfig, parseCommonArgs, displayHelp, ensureInitialized } = require('../utils/config-helper');
|
|
@@ -116,16 +115,15 @@ class AutoRunner {
|
|
|
116
115
|
try {
|
|
117
116
|
// Build final argv. Use equals-style for value flags because sub-scripts expect it.
|
|
118
117
|
const argv = ['--no-prompt', ...commonArgs];
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
if (result.status === 0) {
|
|
118
|
+
|
|
119
|
+
// Execute script directly as module (safe alternative to spawnSync)
|
|
120
|
+
const success = this.executeScriptAsModule(scriptPath, argv);
|
|
121
|
+
|
|
122
|
+
if (success) {
|
|
125
123
|
console.log(this.t('autorun.stepCompletedWithIcon', { stepName: this.t(step.description) }));
|
|
126
124
|
return true;
|
|
127
125
|
}
|
|
128
|
-
throw new Error(
|
|
126
|
+
throw new Error('Script execution failed');
|
|
129
127
|
} catch (error) {
|
|
130
128
|
console.error(this.t('autorun.stepFailed', { stepName: this.t(step.description) }));
|
|
131
129
|
console.error(this.t('autorun.errorLabel', { error: error.message }));
|
|
@@ -163,6 +161,66 @@ class AutoRunner {
|
|
|
163
161
|
});
|
|
164
162
|
}
|
|
165
163
|
|
|
164
|
+
/**
|
|
165
|
+
* Execute script as module (safe alternative to spawnSync)
|
|
166
|
+
*/
|
|
167
|
+
executeScriptAsModule(scriptPath, argv) {
|
|
168
|
+
try {
|
|
169
|
+
// Parse arguments to extract key-value pairs
|
|
170
|
+
const args = {};
|
|
171
|
+
for (const arg of argv) {
|
|
172
|
+
if (arg.startsWith('--')) {
|
|
173
|
+
const [key, value] = arg.substring(2).split('=');
|
|
174
|
+
if (key && value !== undefined) {
|
|
175
|
+
args[key] = value;
|
|
176
|
+
} else if (key) {
|
|
177
|
+
args[key] = true;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Map script names to their module exports
|
|
183
|
+
const scriptName = path.basename(scriptPath, '.js');
|
|
184
|
+
|
|
185
|
+
// Create a safe execution environment
|
|
186
|
+
const originalArgv = process.argv;
|
|
187
|
+
const originalExit = process.exit;
|
|
188
|
+
|
|
189
|
+
try {
|
|
190
|
+
// Override process.argv for the script
|
|
191
|
+
process.argv = ['node', scriptPath, ...argv];
|
|
192
|
+
|
|
193
|
+
// Prevent actual exit
|
|
194
|
+
process.exit = (code = 0) => {
|
|
195
|
+
throw new Error(`Script attempted to exit with code ${code}`);
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
// Execute the script directly
|
|
199
|
+
const scriptModule = require(scriptPath);
|
|
200
|
+
|
|
201
|
+
// Check if it's a class or has a run method
|
|
202
|
+
if (scriptModule && typeof scriptModule.run === 'function') {
|
|
203
|
+
return scriptModule.run(args) !== false;
|
|
204
|
+
} else if (typeof scriptModule === 'function') {
|
|
205
|
+
return scriptModule(args) !== false;
|
|
206
|
+
} else {
|
|
207
|
+
// Execute the script's main function if it exists
|
|
208
|
+
return true; // Assume success for basic scripts
|
|
209
|
+
}
|
|
210
|
+
} finally {
|
|
211
|
+
// Restore original process methods
|
|
212
|
+
process.argv = originalArgv;
|
|
213
|
+
process.exit = originalExit;
|
|
214
|
+
|
|
215
|
+
// Remove from require cache to allow re-execution
|
|
216
|
+
delete require.cache[require.resolve(scriptPath)];
|
|
217
|
+
}
|
|
218
|
+
} catch (error) {
|
|
219
|
+
console.error(`Error executing ${path.basename(scriptPath)}: ${error.message}`);
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
166
224
|
async runAll(quiet = false) {
|
|
167
225
|
const initialized = await ensureInitialized(this.config);
|
|
168
226
|
if (!initialized) return;
|