locai 2.6.1 → 2.7.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.
- package/README.md +23 -25
- package/dist/cli/helpers.d.ts +34 -2
- package/dist/cli/helpers.js +96 -37
- package/dist/cli.js +40 -39
- package/dist/commands/review.d.ts +33 -8
- package/dist/commands/review.js +89 -22
- package/dist/commands/translator.d.ts +4 -2
- package/dist/commands/translator.js +1 -1
- package/dist/config/index.d.ts +53 -66
- package/dist/config/index.js +2 -1
- package/dist/config/setup.d.ts +3 -2
- package/dist/config/setup.js +5 -3
- package/dist/core/adapters/android-adapter.d.ts +3 -2
- package/dist/core/adapters/android-adapter.js +12 -13
- package/dist/core/adapters/base-adapter.d.ts +13 -2
- package/dist/core/adapters/ios-adapter.d.ts +3 -2
- package/dist/core/adapters/json-adapter.d.ts +4 -3
- package/dist/core/adapters/json-adapter.js +1 -3
- package/dist/core/adapters/po-adapter.d.ts +3 -2
- package/dist/core/adapters/po-adapter.js +4 -5
- package/dist/core/adapters/properties-adapter.d.ts +3 -2
- package/dist/core/adapters/properties-adapter.js +2 -4
- package/dist/core/adapters/yaml-adapter.d.ts +4 -3
- package/dist/core/adapters/yaml-adapter.js +1 -3
- package/dist/core/context-processor.d.ts +21 -6
- package/dist/core/context-processor.js +2 -7
- package/dist/core/detection/framework-detector.js +1 -1
- package/dist/core/detection/structure-detector.js +1 -1
- package/dist/core/fallback-provider.d.ts +3 -4
- package/dist/core/fallback-provider.js +15 -21
- package/dist/core/orchestrator.d.ts +98 -26
- package/dist/core/orchestrator.js +56 -116
- package/dist/core/pipeline/Pipeline.d.ts +2 -2
- package/dist/core/pipeline/Pipeline.js +1 -3
- package/dist/core/pipeline/context.d.ts +69 -13
- package/dist/core/pipeline/context.js +1 -7
- package/dist/core/pipeline/steps/CacheReadStep.d.ts +10 -7
- package/dist/core/pipeline/steps/CacheReadStep.js +1 -12
- package/dist/core/pipeline/steps/CacheWriteStep.d.ts +2 -2
- package/dist/core/pipeline/steps/CacheWriteStep.js +1 -8
- package/dist/core/pipeline/steps/ConfidenceCheckStep.d.ts +5 -0
- package/dist/core/pipeline/steps/ConfidenceCheckStep.js +24 -44
- package/dist/core/pipeline/steps/ContextEnrichmentStep.js +3 -14
- package/dist/core/pipeline/steps/QualityCheckStep.d.ts +1 -1
- package/dist/core/pipeline/steps/QualityCheckStep.js +0 -2
- package/dist/core/pipeline/steps/ToneCheckStep.js +1 -1
- package/dist/core/pipeline/steps/TranslationStep.d.ts +13 -3
- package/dist/core/pipeline/steps/TranslationStep.js +21 -23
- package/dist/core/pipeline/steps/VectorCacheReadStep.d.ts +9 -1
- package/dist/core/pipeline/steps/VectorCacheReadStep.js +3 -5
- package/dist/core/pipeline/steps/VectorCacheWriteStep.d.ts +2 -1
- package/dist/core/pipeline/steps/VectorCacheWriteStep.js +2 -1
- package/dist/core/provider-factory.d.ts +15 -9
- package/dist/core/provider-factory.js +42 -32
- package/dist/providers/anthropic.d.ts +5 -4
- package/dist/providers/anthropic.js +3 -2
- package/dist/providers/api-types.d.ts +74 -0
- package/dist/providers/api-types.js +5 -0
- package/dist/providers/base-provider.d.ts +27 -31
- package/dist/providers/base-provider.js +22 -46
- package/dist/providers/dashscope.js +0 -2
- package/dist/providers/deepseek.js +0 -1
- package/dist/providers/gemini.js +0 -1
- package/dist/providers/openai.d.ts +3 -3
- package/dist/providers/openai.js +0 -1
- package/dist/providers/xai.js +0 -1
- package/dist/services/embedding-provider.js +4 -2
- package/dist/services/language-processor.d.ts +5 -3
- package/dist/services/language-processor.js +38 -43
- package/dist/services/source-analyzer.d.ts +24 -0
- package/dist/services/source-analyzer.js +161 -68
- package/dist/services/translation-service.d.ts +31 -13
- package/dist/services/translation-service.js +116 -71
- package/dist/services/vector-store.d.ts +15 -2
- package/dist/services/vector-store.js +14 -10
- package/dist/types/index.d.ts +31 -33
- package/dist/utils/ai-context-analyzer.d.ts +12 -3
- package/dist/utils/ai-context-analyzer.js +18 -10
- package/dist/utils/confidence-scorer.d.ts +16 -19
- package/dist/utils/confidence-scorer.js +36 -125
- package/dist/utils/error-helper.d.ts +27 -6
- package/dist/utils/error-helper.js +10 -9
- package/dist/utils/file-manager.d.ts +8 -7
- package/dist/utils/file-manager.js +22 -23
- package/dist/utils/glossary-manager.d.ts +22 -3
- package/dist/utils/glossary-manager.js +47 -28
- package/dist/utils/graceful-shutdown.d.ts +7 -1
- package/dist/utils/graceful-shutdown.js +1 -2
- package/dist/utils/input-validator.d.ts +53 -66
- package/dist/utils/input-validator.js +100 -151
- package/dist/utils/locale-paths.d.ts +7 -0
- package/dist/utils/locale-paths.js +16 -0
- package/dist/utils/logger.d.ts +8 -8
- package/dist/utils/logger.js +7 -15
- package/dist/utils/object-transformer.d.ts +20 -5
- package/dist/utils/object-transformer.js +20 -28
- package/dist/utils/progress-tracker.js +2 -3
- package/dist/utils/prompt-templates.d.ts +45 -5
- package/dist/utils/prompt-templates.js +61 -5
- package/dist/utils/quality/base-checker.d.ts +40 -18
- package/dist/utils/quality/base-checker.js +1 -2
- package/dist/utils/quality/code-block-checker.d.ts +13 -5
- package/dist/utils/quality/index.d.ts +2 -1
- package/dist/utils/quality/index.js +8 -27
- package/dist/utils/quality/length-checker.d.ts +35 -5
- package/dist/utils/quality/length-checker.js +2 -3
- package/dist/utils/quality/markdown-checker.d.ts +14 -7
- package/dist/utils/quality/special-characters-checker.d.ts +18 -1
- package/dist/utils/quality/special-characters-checker.js +0 -1
- package/dist/utils/quality/style-guide-checker.d.ts +1 -1
- package/dist/utils/quality/style-guide-checker.js +0 -2
- package/dist/utils/quality/tone-verifier.js +1 -1
- package/dist/utils/rate-limiter.d.ts +17 -1
- package/dist/utils/rate-limiter.js +12 -11
- package/dist/utils/retry-helper.d.ts +21 -3
- package/dist/utils/retry-helper.js +11 -3
- package/dist/utils/review-queue.d.ts +45 -0
- package/dist/utils/review-queue.js +53 -0
- package/dist/utils/state-manager.d.ts +12 -3
- package/dist/utils/state-manager.js +32 -7
- package/dist/utils/statistics-manager.d.ts +11 -1
- package/dist/utils/statistics-manager.js +8 -0
- package/dist/utils/ui-manager.d.ts +2 -1
- package/dist/utils/ui-manager.js +15 -1
- package/package.json +22 -17
- package/dist/commands/interactive-review.d.ts +0 -9
- package/dist/commands/interactive-review.js +0 -109
- package/dist/core/pipeline/steps/__tests__/ToneCheckStep.test.d.ts +0 -1
- package/dist/core/pipeline/steps/__tests__/ToneCheckStep.test.js +0 -100
- package/dist/utils/quality/__tests__/tone-verifier.test.d.ts +0 -1
- package/dist/utils/quality/__tests__/tone-verifier.test.js +0 -91
|
@@ -13,12 +13,28 @@ export interface ProtectedTerm {
|
|
|
13
13
|
translation: string;
|
|
14
14
|
term: string;
|
|
15
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* Advanced format: `{ "API": { translation: "API", caseSensitive: true, languages: ["de"] } }`.
|
|
18
|
+
* A non-empty `languages` list restricts the entry to those target languages.
|
|
19
|
+
*/
|
|
20
|
+
export type GlossaryEntryConfig = Partial<Omit<GlossaryEntry, "term">>;
|
|
21
|
+
/** Language-specific format: `{ "API": { tr: "API", de: "API" } }` */
|
|
22
|
+
export type LanguageTranslations = Record<string, string>;
|
|
23
|
+
/** Simple format (`{ "API": "API" }`), advanced entry, or per-language translations. */
|
|
24
|
+
export type GlossaryTermConfig = string | GlossaryEntryConfig | LanguageTranslations;
|
|
16
25
|
export interface GlossaryConfig {
|
|
17
|
-
glossary?: Record<string,
|
|
26
|
+
glossary?: Record<string, GlossaryTermConfig>;
|
|
18
27
|
enabled?: boolean;
|
|
19
28
|
caseSensitive?: boolean;
|
|
20
29
|
preserveFormatting?: boolean;
|
|
21
30
|
}
|
|
31
|
+
export interface GlossaryStats {
|
|
32
|
+
totalTerms: number;
|
|
33
|
+
enabled: boolean;
|
|
34
|
+
caseSensitive: boolean;
|
|
35
|
+
preserveFormatting: boolean;
|
|
36
|
+
terms: string[];
|
|
37
|
+
}
|
|
22
38
|
declare class GlossaryManager {
|
|
23
39
|
private glossary;
|
|
24
40
|
enabled: boolean;
|
|
@@ -38,7 +54,10 @@ declare class GlossaryManager {
|
|
|
38
54
|
*/
|
|
39
55
|
restoreTerms(translatedText: string, termMap: Map<string, ProtectedTerm>): string;
|
|
40
56
|
/**
|
|
41
|
-
* Get applicable glossary entries for language pair
|
|
57
|
+
* Get applicable glossary entries for language pair.
|
|
58
|
+
* An advanced entry with a non-empty `languages` list applies only when `targetLang` is in
|
|
59
|
+
* that list. Codes are compared as whole tags, ignoring case: `"pt-br"` matches `"pt-BR"`,
|
|
60
|
+
* but `"zh"` does not match `"zh-CN"`.
|
|
42
61
|
*/
|
|
43
62
|
getApplicableEntries(sourceLang: string, targetLang: string): GlossaryEntry[];
|
|
44
63
|
/**
|
|
@@ -60,7 +79,7 @@ declare class GlossaryManager {
|
|
|
60
79
|
/**
|
|
61
80
|
* Get statistics about glossary
|
|
62
81
|
*/
|
|
63
|
-
getStats():
|
|
82
|
+
getStats(): GlossaryStats;
|
|
64
83
|
/**
|
|
65
84
|
* Load glossary from file
|
|
66
85
|
*/
|
|
@@ -2,13 +2,26 @@
|
|
|
2
2
|
* Glossary Manager
|
|
3
3
|
* Manages brand terminology and ensures consistent translations
|
|
4
4
|
*/
|
|
5
|
+
/** An object entry with a truthy `translation` is an advanced entry ... */
|
|
6
|
+
const isEntryConfig = (config) => Boolean(config.translation);
|
|
7
|
+
/** ... any other object entry is a per-language map. */
|
|
8
|
+
const isLanguageMap = (config) => !isEntryConfig(config);
|
|
5
9
|
class GlossaryManager {
|
|
6
10
|
glossary;
|
|
7
11
|
enabled;
|
|
8
12
|
caseSensitive;
|
|
9
13
|
preserveFormatting;
|
|
10
14
|
constructor(config = {}) {
|
|
11
|
-
|
|
15
|
+
// Config files are plain JS/JSON, so a term can map to `null`; skip it instead of
|
|
16
|
+
// crashing on every translation.
|
|
17
|
+
this.glossary = {};
|
|
18
|
+
for (const [term, entry] of Object.entries(config.glossary || {})) {
|
|
19
|
+
if (entry === null) {
|
|
20
|
+
console.warn(`Warning: glossary entry "${term}" is null; skipping it.`);
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
this.glossary[term] = entry;
|
|
24
|
+
}
|
|
12
25
|
this.enabled = config.enabled !== false;
|
|
13
26
|
this.caseSensitive = config.caseSensitive !== false;
|
|
14
27
|
this.preserveFormatting = config.preserveFormatting !== false;
|
|
@@ -35,25 +48,21 @@ class GlossaryManager {
|
|
|
35
48
|
const flags = isCaseSensitive ? "g" : "gi";
|
|
36
49
|
const escapedTerm = this.escapeRegex(term);
|
|
37
50
|
const regex = new RegExp(`\\b${escapedTerm}\\b`, flags);
|
|
38
|
-
//
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
translation: preservedTranslation,
|
|
51
|
-
term: term,
|
|
52
|
-
});
|
|
53
|
-
// Replace with token
|
|
54
|
-
protectedText = protectedText.replace(match, token);
|
|
51
|
+
// Replace each whole-word match in place with its own token
|
|
52
|
+
protectedText = protectedText.replace(regex, (match) => {
|
|
53
|
+
const token = `__GLOSSARY_TOKEN_${tokenIndex}__`;
|
|
54
|
+
tokenIndex++;
|
|
55
|
+
// Preserve original formatting if needed
|
|
56
|
+
const preservedTranslation = this.preserveFormatting
|
|
57
|
+
? this.matchFormatting(match, translation)
|
|
58
|
+
: translation;
|
|
59
|
+
termMap.set(token, {
|
|
60
|
+
original: match,
|
|
61
|
+
translation: preservedTranslation,
|
|
62
|
+
term: term,
|
|
55
63
|
});
|
|
56
|
-
|
|
64
|
+
return token;
|
|
65
|
+
});
|
|
57
66
|
}
|
|
58
67
|
return { protectedText, termMap };
|
|
59
68
|
}
|
|
@@ -65,18 +74,21 @@ class GlossaryManager {
|
|
|
65
74
|
return translatedText;
|
|
66
75
|
}
|
|
67
76
|
let restoredText = translatedText;
|
|
68
|
-
// Replace tokens with translations
|
|
77
|
+
// Replace tokens with translations; a replacer function keeps `$` patterns literal
|
|
69
78
|
for (const [token, data] of termMap.entries()) {
|
|
70
|
-
restoredText = restoredText.replace(new RegExp(token, "g"), data.translation);
|
|
79
|
+
restoredText = restoredText.replace(new RegExp(token, "g"), () => data.translation);
|
|
71
80
|
}
|
|
72
81
|
return restoredText;
|
|
73
82
|
}
|
|
74
83
|
/**
|
|
75
|
-
* Get applicable glossary entries for language pair
|
|
84
|
+
* Get applicable glossary entries for language pair.
|
|
85
|
+
* An advanced entry with a non-empty `languages` list applies only when `targetLang` is in
|
|
86
|
+
* that list. Codes are compared as whole tags, ignoring case: `"pt-br"` matches `"pt-BR"`,
|
|
87
|
+
* but `"zh"` does not match `"zh-CN"`.
|
|
76
88
|
*/
|
|
77
89
|
getApplicableEntries(sourceLang, targetLang) {
|
|
78
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
79
90
|
const entries = [];
|
|
91
|
+
const target = targetLang.toLowerCase();
|
|
80
92
|
for (const [term, config] of Object.entries(this.glossary)) {
|
|
81
93
|
// Simple format: { "API": "API" }
|
|
82
94
|
if (typeof config === "string") {
|
|
@@ -86,17 +98,23 @@ class GlossaryManager {
|
|
|
86
98
|
caseSensitive: this.caseSensitive,
|
|
87
99
|
});
|
|
88
100
|
}
|
|
89
|
-
// Advanced format: { "API": { translation: "API", caseSensitive: true } }
|
|
90
|
-
else if (typeof config === "object" && config
|
|
101
|
+
// Advanced format: { "API": { translation: "API", caseSensitive: true, languages: ["de"] } }
|
|
102
|
+
else if (typeof config === "object" && isEntryConfig(config)) {
|
|
103
|
+
const { languages } = config;
|
|
104
|
+
if (Array.isArray(languages) &&
|
|
105
|
+
languages.length > 0 &&
|
|
106
|
+
!languages.some((lang) => String(lang).toLowerCase() === target)) {
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
91
109
|
entries.push({
|
|
92
110
|
term,
|
|
93
111
|
translation: config.translation,
|
|
94
112
|
caseSensitive: config.caseSensitive ?? this.caseSensitive,
|
|
95
|
-
languages
|
|
113
|
+
languages,
|
|
96
114
|
});
|
|
97
115
|
}
|
|
98
116
|
// Language-specific format
|
|
99
|
-
else if (typeof config === "object" && config[targetLang]) {
|
|
117
|
+
else if (typeof config === "object" && isLanguageMap(config) && config[targetLang]) {
|
|
100
118
|
entries.push({
|
|
101
119
|
term,
|
|
102
120
|
translation: config[targetLang],
|
|
@@ -187,7 +205,8 @@ class GlossaryManager {
|
|
|
187
205
|
return new GlossaryManager({ glossary, enabled: true });
|
|
188
206
|
}
|
|
189
207
|
catch (error) {
|
|
190
|
-
|
|
208
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
209
|
+
throw new Error(`Failed to load glossary from ${filePath}: ${message}`);
|
|
191
210
|
}
|
|
192
211
|
}
|
|
193
212
|
}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
export type ShutdownCallback = () => Promise<void> | void;
|
|
2
|
+
/** Minimal logging surface used during shutdown; satisfied by `console` and our `Logger`. */
|
|
3
|
+
export interface ShutdownLogger {
|
|
4
|
+
info(...args: unknown[]): void;
|
|
5
|
+
warn(...args: unknown[]): void;
|
|
6
|
+
error(...args: unknown[]): void;
|
|
7
|
+
}
|
|
2
8
|
export interface ShutdownOptions {
|
|
3
9
|
shutdownTimeout?: number;
|
|
4
10
|
waitForPending?: boolean;
|
|
5
|
-
logger?:
|
|
11
|
+
logger?: ShutdownLogger;
|
|
6
12
|
}
|
|
7
13
|
declare class GracefulShutdown {
|
|
8
14
|
private options;
|
|
@@ -91,7 +91,6 @@ class GracefulShutdown {
|
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
async waitForPendingOperations() {
|
|
94
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
95
94
|
const providerStatus = rateLimiter.getStatus();
|
|
96
95
|
let hasPending = false;
|
|
97
96
|
for (const [provider, status] of Object.entries(providerStatus)) {
|
|
@@ -107,7 +106,7 @@ class GracefulShutdown {
|
|
|
107
106
|
this.logger.info("Forced queue cleanup completed");
|
|
108
107
|
}
|
|
109
108
|
catch (error) {
|
|
110
|
-
this.logger.warn("Error during forced queue cleanup:", error.message);
|
|
109
|
+
this.logger.warn("Error during forced queue cleanup:", error instanceof Error ? error.message : String(error));
|
|
111
110
|
}
|
|
112
111
|
}
|
|
113
112
|
}
|
|
@@ -2,10 +2,13 @@
|
|
|
2
2
|
* Input validation utility for security and data integrity.
|
|
3
3
|
* Defines regex patterns, limits, and validation methods.
|
|
4
4
|
*/
|
|
5
|
+
import type { FileOptions } from "./file-manager.js";
|
|
6
|
+
import type { QualityRules } from "./quality/base-checker.js";
|
|
7
|
+
import type { LengthControlOptions } from "./quality/length-checker.js";
|
|
5
8
|
export interface ApiProviderConfig {
|
|
6
9
|
temperature?: number;
|
|
7
10
|
maxTokens?: number;
|
|
8
|
-
[key: string]:
|
|
11
|
+
[key: string]: unknown;
|
|
9
12
|
}
|
|
10
13
|
export interface RateLimiterProviderLimit {
|
|
11
14
|
rpm?: number;
|
|
@@ -28,17 +31,13 @@ export interface ContextConfig {
|
|
|
28
31
|
threshold?: number;
|
|
29
32
|
minConfidence?: number;
|
|
30
33
|
};
|
|
31
|
-
categories?: Record<string,
|
|
34
|
+
categories?: Record<string, unknown>;
|
|
32
35
|
}
|
|
33
36
|
export interface QualityChecksConfig {
|
|
34
|
-
rules?:
|
|
37
|
+
rules?: QualityRules;
|
|
35
38
|
enabled?: boolean;
|
|
36
39
|
autoFix?: boolean;
|
|
37
40
|
}
|
|
38
|
-
export interface LengthControlConfig {
|
|
39
|
-
mode?: "strict" | "flexible" | "exact" | "relaxed" | "smart";
|
|
40
|
-
rules?: Record<string, any>;
|
|
41
|
-
}
|
|
42
41
|
export interface AdvancedConfig {
|
|
43
42
|
timeoutMs?: number;
|
|
44
43
|
maxKeyLength?: number;
|
|
@@ -58,70 +57,78 @@ export interface AppConfig {
|
|
|
58
57
|
retryOptions?: RetryOptions;
|
|
59
58
|
context?: ContextConfig;
|
|
60
59
|
qualityChecks?: QualityChecksConfig;
|
|
61
|
-
lengthControl?:
|
|
60
|
+
lengthControl?: LengthControlOptions;
|
|
62
61
|
advanced?: AdvancedConfig;
|
|
63
|
-
fileOperations?:
|
|
62
|
+
fileOperations?: FileOptions;
|
|
64
63
|
debug?: boolean;
|
|
65
64
|
verbose?: boolean;
|
|
66
|
-
[key: string]:
|
|
65
|
+
[key: string]: unknown;
|
|
67
66
|
}
|
|
67
|
+
/** A config section that is an object but whose fields have not been validated yet */
|
|
68
|
+
type UnvalidatedSection = Record<string, unknown>;
|
|
68
69
|
declare class InputValidator {
|
|
70
|
+
/**
|
|
71
|
+
* Well-formed BCP 47 language tag, limited to the subtags locai supports:
|
|
72
|
+
* a 2-3 letter language, an optional 4-letter script and an optional
|
|
73
|
+
* 2-letter or 3-digit region (e.g. "en", "fil", "pt-BR", "zh-Hant-TW", "es-419").
|
|
74
|
+
* Matching is case-insensitive; see validateLanguageCode for canonical casing.
|
|
75
|
+
*/
|
|
69
76
|
static LANGUAGE_CODE_PATTERN: RegExp;
|
|
70
77
|
static VALID_PROVIDERS: string[];
|
|
71
78
|
static MAX_TEXT_LENGTH: number;
|
|
72
79
|
static MAX_KEY_LENGTH: number;
|
|
73
80
|
static MAX_PATH_LENGTH: number;
|
|
74
81
|
static MAX_CONFIG_DEPTH: number;
|
|
75
|
-
static DANGEROUS_PATTERNS: RegExp[];
|
|
76
|
-
private static _requestCounts?;
|
|
77
82
|
/**
|
|
78
|
-
* Validate
|
|
79
|
-
*
|
|
83
|
+
* Validate a BCP 47 language tag and return it in canonical casing:
|
|
84
|
+
* lowercase language, title-case script, uppercase region
|
|
85
|
+
* (e.g. "ZH-hant-tw" -> "zh-Hant-TW", "PT-br" -> "pt-BR").
|
|
86
|
+
* @param {unknown} langCode - Language tag to validate.
|
|
80
87
|
* @param {string} [paramName="language"] - Parameter name for error messages.
|
|
81
|
-
* @returns {string} -
|
|
88
|
+
* @returns {string} - Canonical language tag.
|
|
82
89
|
* @throws {Error} If validation fails.
|
|
83
90
|
*/
|
|
84
|
-
static validateLanguageCode(langCode:
|
|
91
|
+
static validateLanguageCode(langCode: unknown, paramName?: string): string;
|
|
85
92
|
/**
|
|
86
93
|
* Validate array of language codes.
|
|
87
|
-
* @param {
|
|
94
|
+
* @param {unknown} langCodes - Array of language codes.
|
|
88
95
|
* @param {string} [paramName="languages"] - Parameter name for errors.
|
|
89
96
|
* @returns {string[]} - Sanitized array of language codes.
|
|
90
97
|
* @throws {Error} If array is empty or contains invalid codes.
|
|
91
98
|
*/
|
|
92
|
-
static validateLanguageCodes(langCodes:
|
|
99
|
+
static validateLanguageCodes(langCodes: unknown, paramName?: string): string[];
|
|
93
100
|
/**
|
|
94
101
|
* Validate and sanitize directory path.
|
|
95
|
-
* @param {
|
|
102
|
+
* @param {unknown} dirPath - Directory path.
|
|
96
103
|
* @param {string} [paramName="directory"] - Parameter name for errors.
|
|
97
104
|
* @returns {string} - Resolved and validated absolute path.
|
|
98
105
|
* @throws {Error} If path is invalid or outside working directory.
|
|
99
106
|
*/
|
|
100
|
-
static validateDirectoryPath(dirPath:
|
|
107
|
+
static validateDirectoryPath(dirPath: unknown, paramName?: string): string;
|
|
101
108
|
/**
|
|
102
109
|
* Validate translation text.
|
|
103
|
-
* @param {
|
|
110
|
+
* @param {unknown} text - Text to validate.
|
|
104
111
|
* @param {string} [paramName="text"] - Parameter name for errors.
|
|
105
112
|
* @returns {string} - Validated text.
|
|
106
113
|
* @throws {Error} If text is invalid or too long.
|
|
107
114
|
*/
|
|
108
|
-
static validateText(text:
|
|
115
|
+
static validateText(text: unknown, paramName?: string): string;
|
|
109
116
|
/**
|
|
110
117
|
* Validate translation key.
|
|
111
|
-
* @param {
|
|
118
|
+
* @param {unknown} key - Key to validate.
|
|
112
119
|
* @param {string} [paramName="key"] - Parameter name.
|
|
113
120
|
* @returns {string} - Validated key.
|
|
114
121
|
* @throws {Error} If key is invalid, too long, or contains traversal.
|
|
115
122
|
*/
|
|
116
|
-
static validateKey(key:
|
|
123
|
+
static validateKey(key: unknown, paramName?: string): string;
|
|
117
124
|
/**
|
|
118
125
|
* Validate API provider name.
|
|
119
|
-
* @param {
|
|
126
|
+
* @param {unknown} provider - Provider name.
|
|
120
127
|
* @param {string} [fieldName="API provider"] - Parameter name.
|
|
121
128
|
* @returns {string} - Normalized provider name.
|
|
122
129
|
* @throws {Error} If provider is unknown.
|
|
123
130
|
*/
|
|
124
|
-
static validateProvider(provider:
|
|
131
|
+
static validateProvider(provider: unknown, fieldName?: string): string;
|
|
125
132
|
/**
|
|
126
133
|
* Sanitize filename to prevent path traversal.
|
|
127
134
|
* @param {string} filename - Filename to sanitize.
|
|
@@ -140,88 +147,68 @@ declare class InputValidator {
|
|
|
140
147
|
static createSafeFilePath(baseDir: string, filename: string): string;
|
|
141
148
|
/**
|
|
142
149
|
* Validate configuration object.
|
|
143
|
-
*
|
|
150
|
+
* Rewrites `source` and `targets` in place to canonical BCP 47 casing so that
|
|
151
|
+
* file lookups and per-language settings all see the same tag.
|
|
152
|
+
* @param {unknown} config - Configuration object to validate.
|
|
144
153
|
* @returns {AppConfig} - Validated configuration.
|
|
145
154
|
* @throws {Error} If configuration is invalid.
|
|
146
155
|
*/
|
|
147
|
-
static validateConfig(config:
|
|
156
|
+
static validateConfig(config: unknown): AppConfig;
|
|
148
157
|
/**
|
|
149
158
|
* Validate API config for each provider.
|
|
150
|
-
* @param {Record<string,
|
|
159
|
+
* @param {Record<string, unknown>} apiConfig - Raw API configuration object.
|
|
151
160
|
* @param {string[]} errors - Array to push errors to.
|
|
152
161
|
* @param {string[]} warnings - Array to push warnings to.
|
|
153
162
|
*/
|
|
154
|
-
static validateApiConfig(apiConfig:
|
|
163
|
+
static validateApiConfig(apiConfig: UnvalidatedSection, errors: string[], warnings: string[]): void;
|
|
155
164
|
/**
|
|
156
165
|
* Validate rate limiter configuration.
|
|
157
|
-
* @param {
|
|
166
|
+
* @param {Record<string, unknown>} rateLimiter - Raw rate limiter configuration.
|
|
158
167
|
* @param {string[]} errors - Array to push errors to.
|
|
159
168
|
* @param {string[]} warnings - Array to push warnings to.
|
|
160
169
|
*/
|
|
161
|
-
static validateRateLimiterConfig(rateLimiter:
|
|
170
|
+
static validateRateLimiterConfig(rateLimiter: UnvalidatedSection, errors: string[], _warnings: string[]): void;
|
|
162
171
|
/**
|
|
163
172
|
* Validate retry options.
|
|
164
|
-
* @param {
|
|
173
|
+
* @param {Record<string, unknown>} retryOptions - Raw retry options.
|
|
165
174
|
* @param {string[]} errors - Array to push errors to.
|
|
166
175
|
* @param {string[]} warnings - Array to push warnings to.
|
|
167
176
|
*/
|
|
168
|
-
static validateRetryOptions(retryOptions:
|
|
177
|
+
static validateRetryOptions(retryOptions: UnvalidatedSection, errors: string[], _warnings: string[]): void;
|
|
169
178
|
/**
|
|
170
179
|
* Validate context configuration.
|
|
171
|
-
* @param {
|
|
180
|
+
* @param {Record<string, unknown>} context - Raw context configuration.
|
|
172
181
|
* @param {string[]} errors - Array to push errors to.
|
|
173
182
|
* @param {string[]} warnings - Array to push warnings to.
|
|
174
183
|
*/
|
|
175
|
-
static validateContextConfig(context:
|
|
184
|
+
static validateContextConfig(context: UnvalidatedSection, errors: string[], warnings: string[]): void;
|
|
176
185
|
/**
|
|
177
186
|
* Validate quality checks configuration.
|
|
178
|
-
* @param {
|
|
187
|
+
* @param {Record<string, unknown>} qualityChecks - Raw quality checks configuration.
|
|
179
188
|
* @param {string[]} errors - Array to push errors to.
|
|
180
189
|
* @param {string[]} warnings - Array to push warnings to.
|
|
181
190
|
*/
|
|
182
|
-
static validateQualityChecks(qualityChecks:
|
|
191
|
+
static validateQualityChecks(qualityChecks: UnvalidatedSection, errors: string[], warnings: string[]): void;
|
|
183
192
|
/**
|
|
184
193
|
* Validate length control configuration.
|
|
185
|
-
* @param {
|
|
194
|
+
* @param {Record<string, unknown>} lengthControl - Raw length control configuration.
|
|
186
195
|
* @param {string[]} errors - Array to push errors to.
|
|
187
196
|
*/
|
|
188
|
-
static validateLengthControl(lengthControl:
|
|
197
|
+
static validateLengthControl(lengthControl: UnvalidatedSection, errors: string[]): void;
|
|
189
198
|
/**
|
|
190
199
|
* Validate advanced configuration.
|
|
191
|
-
* @param {
|
|
200
|
+
* @param {Record<string, unknown>} advanced - Raw advanced configuration.
|
|
192
201
|
* @param {string[]} errors - Array to push errors to.
|
|
193
202
|
*/
|
|
194
|
-
static validateAdvancedConfig(advanced:
|
|
195
|
-
/**
|
|
196
|
-
* Sanitize translation text for security.
|
|
197
|
-
* @param {string | null} text - Text to sanitize.
|
|
198
|
-
* @returns {string | null} - Sanitized text.
|
|
199
|
-
*/
|
|
200
|
-
static sanitizeTranslationText(text: string | null): string | null;
|
|
201
|
-
/**
|
|
202
|
-
* Validate API key format.
|
|
203
|
-
* @param {string} apiKey - API key to validate.
|
|
204
|
-
* @param {string} providerName - Provider name.
|
|
205
|
-
* @returns {boolean} - True if valid.
|
|
206
|
-
* @throws {Error} If key is invalid.
|
|
207
|
-
*/
|
|
208
|
-
static validateApiKeyFormat(apiKey: string, providerName: string): boolean;
|
|
203
|
+
static validateAdvancedConfig(advanced: UnvalidatedSection, errors: string[]): void;
|
|
209
204
|
/**
|
|
210
205
|
* Validate object depth to prevent circular references and deep nesting.
|
|
211
|
-
* @param {
|
|
206
|
+
* @param {unknown} obj - Object to validate.
|
|
212
207
|
* @param {number} [maxDepth=10] - Maximum depth.
|
|
213
208
|
* @param {number} [currentDepth=0] - Current depth.
|
|
214
209
|
* @returns {boolean} - True if valid.
|
|
215
210
|
* @throws {Error} If depth exceeded.
|
|
216
211
|
*/
|
|
217
|
-
static validateObjectDepth(obj:
|
|
218
|
-
/**
|
|
219
|
-
* Validate request rate for an identifier.
|
|
220
|
-
* @param {string} identifier - Identifier (e.g., user ID or IP).
|
|
221
|
-
* @param {number} [maxRequestsPerMinute=60] - Max requests per minute.
|
|
222
|
-
* @returns {boolean} - True if allowed.
|
|
223
|
-
* @throws {Error} If rate limit exceeded.
|
|
224
|
-
*/
|
|
225
|
-
static validateRequestRate(identifier: string, maxRequestsPerMinute?: number): boolean;
|
|
212
|
+
static validateObjectDepth(obj: unknown, maxDepth?: number, currentDepth?: number): boolean;
|
|
226
213
|
}
|
|
227
214
|
export default InputValidator;
|