@saidksi/localizer-cli 0.1.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/LICENSE +21 -0
- package/README.md +99 -0
- package/dist/bin/localize.d.ts +3 -0
- package/dist/bin/localize.d.ts.map +1 -0
- package/dist/bin/localize.js +7 -0
- package/dist/bin/localize.js.map +1 -0
- package/dist/commands/add-lang.d.ts +3 -0
- package/dist/commands/add-lang.d.ts.map +1 -0
- package/dist/commands/add-lang.js +103 -0
- package/dist/commands/add-lang.js.map +1 -0
- package/dist/commands/audit.d.ts +3 -0
- package/dist/commands/audit.d.ts.map +1 -0
- package/dist/commands/audit.js +174 -0
- package/dist/commands/audit.js.map +1 -0
- package/dist/commands/diff.d.ts +3 -0
- package/dist/commands/diff.d.ts.map +1 -0
- package/dist/commands/diff.js +76 -0
- package/dist/commands/diff.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +427 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/rewrite.d.ts +3 -0
- package/dist/commands/rewrite.d.ts.map +1 -0
- package/dist/commands/rewrite.js +140 -0
- package/dist/commands/rewrite.js.map +1 -0
- package/dist/commands/run.d.ts +3 -0
- package/dist/commands/run.d.ts.map +1 -0
- package/dist/commands/run.js +324 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/scan.d.ts +3 -0
- package/dist/commands/scan.d.ts.map +1 -0
- package/dist/commands/scan.js +121 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/commands/status.d.ts +3 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +128 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/translate.d.ts +3 -0
- package/dist/commands/translate.d.ts.map +1 -0
- package/dist/commands/translate.js +233 -0
- package/dist/commands/translate.js.map +1 -0
- package/dist/commands/validate.d.ts +3 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +121 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +46 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/config.d.ts +30 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +94 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/diff.d.ts +10 -0
- package/dist/utils/diff.d.ts.map +1 -0
- package/dist/utils/diff.js +31 -0
- package/dist/utils/diff.js.map +1 -0
- package/dist/utils/json.d.ts +3 -0
- package/dist/utils/json.d.ts.map +1 -0
- package/dist/utils/json.js +15 -0
- package/dist/utils/json.js.map +1 -0
- package/dist/utils/logger.d.ts +28 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +48 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/prompt.d.ts +18 -0
- package/dist/utils/prompt.d.ts.map +1 -0
- package/dist/utils/prompt.js +65 -0
- package/dist/utils/prompt.js.map +1 -0
- package/dist/utils/reporter.d.ts +17 -0
- package/dist/utils/reporter.d.ts.map +1 -0
- package/dist/utils/reporter.js +87 -0
- package/dist/utils/reporter.js.map +1 -0
- package/package.json +62 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../src/utils/json.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,wBAAgB,WAAW,CACzB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,MAAM,SAAK,GACV,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAWxB"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Flatten a nested JSON object to { "dot.notation.key": "value" } pairs. */
|
|
2
|
+
export function flattenJson(obj, prefix = "") {
|
|
3
|
+
const result = {};
|
|
4
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
5
|
+
const fullKey = prefix ? `${prefix}.${k}` : k;
|
|
6
|
+
if (typeof v === "object" && v !== null && !Array.isArray(v)) {
|
|
7
|
+
Object.assign(result, flattenJson(v, fullKey));
|
|
8
|
+
}
|
|
9
|
+
else if (typeof v === "string") {
|
|
10
|
+
result[fullKey] = v;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return result;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.js","sourceRoot":"","sources":["../../src/utils/json.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,MAAM,UAAU,WAAW,CACzB,GAA4B,EAC5B,MAAM,GAAG,EAAE;IAEX,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9C,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7D,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAA4B,EAAE,OAAO,CAAC,CAAC,CAAC;QAC5E,CAAC;aAAM,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;YACjC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export declare const logger: {
|
|
2
|
+
success: (msg: string) => void;
|
|
3
|
+
error: (msg: string) => void;
|
|
4
|
+
warn: (msg: string) => void;
|
|
5
|
+
info: (msg: string) => void;
|
|
6
|
+
dim: (msg: string) => void;
|
|
7
|
+
blank: () => void;
|
|
8
|
+
raw: (msg: string) => void;
|
|
9
|
+
/** Pipeline step header: [1/4] Scanning... */
|
|
10
|
+
step: (n: number, total: number, msg: string) => void;
|
|
11
|
+
/** Indented detail line below a step */
|
|
12
|
+
detail: (msg: string) => void;
|
|
13
|
+
/** Bold section header */
|
|
14
|
+
header: (msg: string) => void;
|
|
15
|
+
/** Fatal error — prints message and exits with code 1 */
|
|
16
|
+
fatal: (msg: string) => never;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Render a coverage bar for the validate / status command output.
|
|
20
|
+
*
|
|
21
|
+
* progressBar("fr", 100, 312, 0)
|
|
22
|
+
* → " fr ████████████████████ 100% (312 keys)"
|
|
23
|
+
*
|
|
24
|
+
* progressBar("ar", 57, 312, 134)
|
|
25
|
+
* → " ar ███████████░░░░░░░░░ 57% (178 keys) ← 134 missing"
|
|
26
|
+
*/
|
|
27
|
+
export declare function progressBar(lang: string, percent: number, totalKeys: number, missingCount: number): string;
|
|
28
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,MAAM;mBACF,MAAM;iBACN,MAAM;gBACN,MAAM;gBACN,MAAM;eACN,MAAM;;eAEN,MAAM;IAErB,8CAA8C;cACpC,MAAM,SAAS,MAAM,OAAO,MAAM;IAG5C,wCAAwC;kBAC1B,MAAM;IAEpB,0BAA0B;kBACZ,MAAM;IAEpB,yDAAyD;iBAC5C,MAAM,KAAG,KAAK;CAI5B,CAAC;AAQF;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,GACnB,MAAM,CAcR"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
// ─── Core output helpers ──────────────────────────────────────────────────────
|
|
3
|
+
export const logger = {
|
|
4
|
+
success: (msg) => console.log(chalk.green(" ✔"), msg),
|
|
5
|
+
error: (msg) => console.error(chalk.red(" ✖"), msg),
|
|
6
|
+
warn: (msg) => console.warn(chalk.yellow(" ⚠"), msg),
|
|
7
|
+
info: (msg) => console.log(chalk.blue(" ℹ"), msg),
|
|
8
|
+
dim: (msg) => console.log(chalk.dim(` ${msg}`)),
|
|
9
|
+
blank: () => console.log(),
|
|
10
|
+
raw: (msg) => console.log(msg),
|
|
11
|
+
/** Pipeline step header: [1/4] Scanning... */
|
|
12
|
+
step: (n, total, msg) => console.log(chalk.cyan(`\n [${n}/${total}]`), chalk.bold(msg)),
|
|
13
|
+
/** Indented detail line below a step */
|
|
14
|
+
detail: (msg) => console.log(` ${msg}`),
|
|
15
|
+
/** Bold section header */
|
|
16
|
+
header: (msg) => console.log(chalk.bold(`\n${msg}`)),
|
|
17
|
+
/** Fatal error — prints message and exits with code 1 */
|
|
18
|
+
fatal: (msg) => {
|
|
19
|
+
console.error(chalk.red.bold("\n Error:"), msg);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
// ─── Coverage progress bar ────────────────────────────────────────────────────
|
|
24
|
+
const BAR_WIDTH = 20;
|
|
25
|
+
const FILLED = "█";
|
|
26
|
+
const EMPTY = "░";
|
|
27
|
+
/**
|
|
28
|
+
* Render a coverage bar for the validate / status command output.
|
|
29
|
+
*
|
|
30
|
+
* progressBar("fr", 100, 312, 0)
|
|
31
|
+
* → " fr ████████████████████ 100% (312 keys)"
|
|
32
|
+
*
|
|
33
|
+
* progressBar("ar", 57, 312, 134)
|
|
34
|
+
* → " ar ███████████░░░░░░░░░ 57% (178 keys) ← 134 missing"
|
|
35
|
+
*/
|
|
36
|
+
export function progressBar(lang, percent, totalKeys, missingCount) {
|
|
37
|
+
const filled = Math.round((percent / 100) * BAR_WIDTH);
|
|
38
|
+
const bar = FILLED.repeat(filled) + EMPTY.repeat(BAR_WIDTH - filled);
|
|
39
|
+
const pct = `${percent}%`.padStart(4);
|
|
40
|
+
const langPad = lang.padEnd(6);
|
|
41
|
+
const presentKeys = totalKeys - missingCount;
|
|
42
|
+
const keyInfo = `(${presentKeys} keys)`;
|
|
43
|
+
const missing = missingCount > 0
|
|
44
|
+
? chalk.yellow(` ← ${missingCount} missing`)
|
|
45
|
+
: chalk.green(" ✔");
|
|
46
|
+
return ` ${langPad} ${bar} ${pct} ${keyInfo}${missing}`;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface SelectChoice<T extends string = string> {
|
|
2
|
+
name: string;
|
|
3
|
+
value: T;
|
|
4
|
+
description?: string;
|
|
5
|
+
}
|
|
6
|
+
/** Free-text input with optional default value. */
|
|
7
|
+
export declare function promptInput(message: string, defaultValue?: string): Promise<string>;
|
|
8
|
+
/** Yes/No confirmation, defaults to No (safe default). */
|
|
9
|
+
export declare function promptConfirm(message: string, defaultValue?: boolean): Promise<boolean>;
|
|
10
|
+
/** Single-selection list. */
|
|
11
|
+
export declare function promptSelect<T extends string>(message: string, choices: SelectChoice<T>[]): Promise<T>;
|
|
12
|
+
/** Multi-selection checkbox list. */
|
|
13
|
+
export declare function promptMultiselect<T extends string>(message: string, choices: SelectChoice<T>[]): Promise<T[]>;
|
|
14
|
+
/** Masked password / API key input. */
|
|
15
|
+
export declare function promptSecret(message: string): Promise<string>;
|
|
16
|
+
/** Ask "Apply these changes? (y/N)" — used by rewrite + run commands. */
|
|
17
|
+
export declare function promptApplyChanges(file: string): Promise<boolean>;
|
|
18
|
+
//# sourceMappingURL=prompt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/utils/prompt.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,CAAC,CAAC;IACT,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,mDAAmD;AACnD,wBAAsB,WAAW,CAC/B,OAAO,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,MAAM,CAAC,CAQjB;AAED,0DAA0D;AAC1D,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,YAAY,UAAQ,GACnB,OAAO,CAAC,OAAO,CAAC,CAQlB;AAED,6BAA6B;AAC7B,wBAAsB,YAAY,CAAC,CAAC,SAAS,MAAM,EACjD,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,GACzB,OAAO,CAAC,CAAC,CAAC,CAYZ;AAED,qCAAqC;AACrC,wBAAsB,iBAAiB,CAAC,CAAC,SAAS,MAAM,EACtD,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,GACzB,OAAO,CAAC,CAAC,EAAE,CAAC,CAYd;AAED,uCAAuC;AACvC,wBAAsB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAQnE;AAID,yEAAyE;AACzE,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAEvE"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import prompts from "prompts";
|
|
2
|
+
/** Free-text input with optional default value. */
|
|
3
|
+
export async function promptInput(message, defaultValue) {
|
|
4
|
+
const response = await prompts({
|
|
5
|
+
type: 'text',
|
|
6
|
+
name: 'value',
|
|
7
|
+
message,
|
|
8
|
+
initial: defaultValue,
|
|
9
|
+
});
|
|
10
|
+
return response.value || '';
|
|
11
|
+
}
|
|
12
|
+
/** Yes/No confirmation, defaults to No (safe default). */
|
|
13
|
+
export async function promptConfirm(message, defaultValue = false) {
|
|
14
|
+
const response = await prompts({
|
|
15
|
+
type: 'confirm',
|
|
16
|
+
name: 'value',
|
|
17
|
+
message,
|
|
18
|
+
initial: defaultValue,
|
|
19
|
+
});
|
|
20
|
+
return response.value || false;
|
|
21
|
+
}
|
|
22
|
+
/** Single-selection list. */
|
|
23
|
+
export async function promptSelect(message, choices) {
|
|
24
|
+
const response = await prompts({
|
|
25
|
+
type: 'select',
|
|
26
|
+
name: 'value',
|
|
27
|
+
message,
|
|
28
|
+
choices: choices.map((c) => ({
|
|
29
|
+
title: c.name,
|
|
30
|
+
value: c.value,
|
|
31
|
+
description: c.description,
|
|
32
|
+
})),
|
|
33
|
+
});
|
|
34
|
+
return response.value;
|
|
35
|
+
}
|
|
36
|
+
/** Multi-selection checkbox list. */
|
|
37
|
+
export async function promptMultiselect(message, choices) {
|
|
38
|
+
const response = await prompts({
|
|
39
|
+
type: 'multiselect',
|
|
40
|
+
name: 'value',
|
|
41
|
+
message,
|
|
42
|
+
choices: choices.map((c) => ({
|
|
43
|
+
title: c.name,
|
|
44
|
+
value: c.value,
|
|
45
|
+
description: c.description,
|
|
46
|
+
})),
|
|
47
|
+
});
|
|
48
|
+
return response.value;
|
|
49
|
+
}
|
|
50
|
+
/** Masked password / API key input. */
|
|
51
|
+
export async function promptSecret(message) {
|
|
52
|
+
const response = await prompts({
|
|
53
|
+
type: 'password',
|
|
54
|
+
name: 'value',
|
|
55
|
+
message,
|
|
56
|
+
mask: '*',
|
|
57
|
+
});
|
|
58
|
+
return response.value || '';
|
|
59
|
+
}
|
|
60
|
+
// ─── Convenience ─────────────────────────────────────────────────────────────
|
|
61
|
+
/** Ask "Apply these changes? (y/N)" — used by rewrite + run commands. */
|
|
62
|
+
export async function promptApplyChanges(file) {
|
|
63
|
+
return promptConfirm(`Apply changes to ${file}?`, false);
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/utils/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAY9B,mDAAmD;AACnD,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,OAAe,EACf,YAAqB;IAErB,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC;QAC7B,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,OAAO;QACb,OAAO;QACP,OAAO,EAAE,YAAY;KACtB,CAAC,CAAC;IACH,OAAO,QAAQ,CAAC,KAAK,IAAI,EAAE,CAAC;AAC9B,CAAC;AAED,0DAA0D;AAC1D,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,OAAe,EACf,YAAY,GAAG,KAAK;IAEpB,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC;QAC7B,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,OAAO;QACb,OAAO;QACP,OAAO,EAAE,YAAY;KACtB,CAAC,CAAC;IACH,OAAO,QAAQ,CAAC,KAAK,IAAI,KAAK,CAAC;AACjC,CAAC;AAED,6BAA6B;AAC7B,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,OAAe,EACf,OAA0B;IAE1B,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC;QAC7B,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,OAAO;QACb,OAAO;QACP,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC3B,KAAK,EAAE,CAAC,CAAC,IAAI;YACb,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,WAAW,EAAE,CAAC,CAAC,WAAW;SAC3B,CAAC,CAAC;KACJ,CAAC,CAAC;IACH,OAAO,QAAQ,CAAC,KAAU,CAAC;AAC7B,CAAC;AAED,qCAAqC;AACrC,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,OAAe,EACf,OAA0B;IAE1B,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC;QAC7B,IAAI,EAAE,aAAa;QACnB,IAAI,EAAE,OAAO;QACb,OAAO;QACP,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC3B,KAAK,EAAE,CAAC,CAAC,IAAI;YACb,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,WAAW,EAAE,CAAC,CAAC,WAAW;SAC3B,CAAC,CAAC;KACJ,CAAC,CAAC;IACH,OAAO,QAAQ,CAAC,KAAY,CAAC;AAC/B,CAAC;AAED,uCAAuC;AACvC,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAe;IAChD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC;QAC7B,IAAI,EAAE,UAAU;QAChB,IAAI,EAAE,OAAO;QACb,OAAO;QACP,IAAI,EAAE,GAAG;KACV,CAAC,CAAC;IACH,OAAO,QAAQ,CAAC,KAAK,IAAI,EAAE,CAAC;AAC9B,CAAC;AAED,gFAAgF;AAEhF,yEAAyE;AACzE,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,IAAY;IACnD,OAAO,aAAa,CAAC,oBAAoB,IAAI,GAAG,EAAE,KAAK,CAAC,CAAC;AAC3D,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ScanReport } from "@saidksi/localizer-core";
|
|
2
|
+
/**
|
|
3
|
+
* Write any serializable value to a JSON report file.
|
|
4
|
+
* Used by audit --output, scan --output, diff --output.
|
|
5
|
+
*/
|
|
6
|
+
export declare function writeReport(outputPath: string, data: unknown): Promise<void>;
|
|
7
|
+
/**
|
|
8
|
+
* Write a ScanReport to disk with metadata.
|
|
9
|
+
* Auto-generates filename if outputPath is a directory.
|
|
10
|
+
* Auto-creates .localize/scan/ if needed.
|
|
11
|
+
* Prompts for confirmation if file exists.
|
|
12
|
+
*
|
|
13
|
+
* Transforms results to be grouped by file with relative paths,
|
|
14
|
+
* and removes column/surroundingCode fields.
|
|
15
|
+
*/
|
|
16
|
+
export declare function writeScanReport(outputPath: string, report: ScanReport, sourceFilePath?: string, cwd?: string): Promise<string>;
|
|
17
|
+
//# sourceMappingURL=reporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../../src/utils/reporter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAoC,MAAM,yBAAyB,CAAC;AAK5F;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,OAAO,GACZ,OAAO,CAAC,IAAI,CAAC,CAGf;AAwBD;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CACnC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,UAAU,EAClB,cAAc,CAAC,EAAE,MAAM,EACvB,GAAG,SAAgB,GAClB,OAAO,CAAC,MAAM,CAAC,CAsDjB"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { writeFile, mkdir, access } from "fs/promises";
|
|
2
|
+
import { resolve, basename, relative } from "path";
|
|
3
|
+
import { promptConfirm } from "./prompt.js";
|
|
4
|
+
// ─── JSON report writer ───────────────────────────────────────────────────────
|
|
5
|
+
/**
|
|
6
|
+
* Write any serializable value to a JSON report file.
|
|
7
|
+
* Used by audit --output, scan --output, diff --output.
|
|
8
|
+
*/
|
|
9
|
+
export async function writeReport(outputPath, data) {
|
|
10
|
+
const absolute = resolve(outputPath);
|
|
11
|
+
await writeFile(absolute, JSON.stringify(data, null, 2) + "\n", "utf-8");
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Check if a file exists.
|
|
15
|
+
*/
|
|
16
|
+
async function fileExists(filePath) {
|
|
17
|
+
try {
|
|
18
|
+
await access(filePath);
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Generate filename from a file or directory path.
|
|
27
|
+
* E.g., "src/pages/Login.tsx" → "login-scan.json"
|
|
28
|
+
* E.g., "src/pages" → "pages-scan.json"
|
|
29
|
+
*/
|
|
30
|
+
function generateScanFileName(filePath) {
|
|
31
|
+
const name = basename(filePath).replace(/\.(tsx?|jsx?)$/, "");
|
|
32
|
+
return `${name.toLowerCase()}-scan.json`;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Write a ScanReport to disk with metadata.
|
|
36
|
+
* Auto-generates filename if outputPath is a directory.
|
|
37
|
+
* Auto-creates .localize/scan/ if needed.
|
|
38
|
+
* Prompts for confirmation if file exists.
|
|
39
|
+
*
|
|
40
|
+
* Transforms results to be grouped by file with relative paths,
|
|
41
|
+
* and removes column/surroundingCode fields.
|
|
42
|
+
*/
|
|
43
|
+
export async function writeScanReport(outputPath, report, sourceFilePath, cwd = process.cwd()) {
|
|
44
|
+
const scanDir = resolve(cwd, ".localize", "scan");
|
|
45
|
+
await mkdir(scanDir, { recursive: true });
|
|
46
|
+
// If outputPath is just a flag with no value, auto-generate filename
|
|
47
|
+
let finalPath = resolve(scanDir, sourceFilePath ? generateScanFileName(sourceFilePath) : "scan-report.json");
|
|
48
|
+
// If outputPath is explicitly provided, use it (resolve relative to .localize/scan/)
|
|
49
|
+
if (outputPath && outputPath !== "true") {
|
|
50
|
+
finalPath = resolve(scanDir, outputPath);
|
|
51
|
+
}
|
|
52
|
+
// Check if file exists and prompt for confirmation
|
|
53
|
+
if (await fileExists(finalPath)) {
|
|
54
|
+
const overwrite = await promptConfirm(`File ${basename(finalPath)} already exists. Overwrite?`, false);
|
|
55
|
+
if (!overwrite) {
|
|
56
|
+
throw new Error("Aborted — file not overwritten.");
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Group results by file (with relative paths) and remove column/surroundingCode
|
|
60
|
+
const resultsByFile = {};
|
|
61
|
+
for (const result of report.results) {
|
|
62
|
+
// Convert to relative path with forward slashes (cross-platform)
|
|
63
|
+
const displayPath = relative(cwd, result.file).replace(/\\/g, "/");
|
|
64
|
+
if (!resultsByFile[displayPath]) {
|
|
65
|
+
resultsByFile[displayPath] = [];
|
|
66
|
+
}
|
|
67
|
+
resultsByFile[displayPath].push({
|
|
68
|
+
line: result.line,
|
|
69
|
+
value: result.value,
|
|
70
|
+
context: result.context,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
// Add metadata to the report
|
|
74
|
+
const reportWithMetadata = {
|
|
75
|
+
metadata: {
|
|
76
|
+
generatedAt: new Date().toISOString(),
|
|
77
|
+
totalStrings: report.results.length,
|
|
78
|
+
uniqueStrings: new Set(report.results.map((r) => r.value)).size,
|
|
79
|
+
untranslatedStrings: report.results.filter((r) => !r.alreadyTranslated).length,
|
|
80
|
+
filesScanned: Object.keys(resultsByFile).length,
|
|
81
|
+
},
|
|
82
|
+
results: resultsByFile,
|
|
83
|
+
};
|
|
84
|
+
await writeFile(finalPath, JSON.stringify(reportWithMetadata, null, 2) + "\n", "utf-8");
|
|
85
|
+
return finalPath;
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=reporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reporter.js","sourceRoot":"","sources":["../../src/utils/reporter.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@saidksi/localizer-cli",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "CLI tool for automating i18n workflows in JavaScript/TypeScript projects with localizer",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"localize": "dist/bin/localize.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "dist/index.js",
|
|
10
|
+
"types": "dist/index.d.ts",
|
|
11
|
+
"files": ["dist", "bin"],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsc && chmod +x dist/bin/localize.js",
|
|
14
|
+
"dev": "tsc --watch",
|
|
15
|
+
"test": "vitest run",
|
|
16
|
+
"test:watch": "vitest",
|
|
17
|
+
"test:coverage": "vitest run --coverage",
|
|
18
|
+
"lint": "tsc --noEmit",
|
|
19
|
+
"clean": "rm -rf dist"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"i18n",
|
|
23
|
+
"internationalization",
|
|
24
|
+
"localization",
|
|
25
|
+
"cli",
|
|
26
|
+
"automation",
|
|
27
|
+
"typescript"
|
|
28
|
+
],
|
|
29
|
+
"author": "SaidKSI",
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"packageManager": "pnpm@10.33.0",
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "https://github.com/SaidKSI/localize-cli.git"
|
|
35
|
+
},
|
|
36
|
+
"bugs": {
|
|
37
|
+
"url": "https://github.com/SaidKSI/localize-cli/issues"
|
|
38
|
+
},
|
|
39
|
+
"homepage": "https://github.com/SaidKSI/localize-cli#readme",
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@saidksi/localizer-core": "^0.1.1",
|
|
45
|
+
"commander": "^11.1.0",
|
|
46
|
+
"cosmiconfig": "^8.3.6",
|
|
47
|
+
"chalk": "^5.3.0",
|
|
48
|
+
"ora": "^8.1.0",
|
|
49
|
+
"prompts": "^2.4.2"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@types/node": "^22.0.0",
|
|
53
|
+
"@types/prompts": "^2.4.9",
|
|
54
|
+
"@vitest/coverage-v8": "^2.1.0",
|
|
55
|
+
"typescript": "^5.5.0",
|
|
56
|
+
"vitest": "^2.1.0"
|
|
57
|
+
},
|
|
58
|
+
"engines": {
|
|
59
|
+
"node": ">=20.0.0",
|
|
60
|
+
"pnpm": ">=8.0.0"
|
|
61
|
+
}
|
|
62
|
+
}
|