i18nsmith 0.1.8 → 0.2.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/build.mjs +16 -10
- package/dist/commands/audit.d.ts +3 -0
- package/dist/commands/audit.d.ts.map +1 -0
- package/dist/commands/backup.d.ts +6 -0
- package/dist/commands/backup.d.ts.map +1 -0
- package/dist/commands/check.d.ts +3 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/config.d.ts +3 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/debug-patterns.d.ts +3 -0
- package/dist/commands/debug-patterns.d.ts.map +1 -0
- package/dist/commands/debug-patterns.test.d.ts +2 -0
- package/dist/commands/debug-patterns.test.d.ts.map +1 -0
- package/dist/commands/diagnose.d.ts +3 -0
- package/dist/commands/diagnose.d.ts.map +1 -0
- package/dist/commands/init.d.ts +8 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.test.d.ts +2 -0
- package/dist/commands/init.test.d.ts.map +1 -0
- package/dist/commands/install-hooks.d.ts +3 -0
- package/dist/commands/install-hooks.d.ts.map +1 -0
- package/dist/commands/preflight.d.ts +7 -0
- package/dist/commands/preflight.d.ts.map +1 -0
- package/dist/commands/preflight.test.d.ts +5 -0
- package/dist/commands/preflight.test.d.ts.map +1 -0
- package/dist/commands/rename.d.ts +6 -0
- package/dist/commands/rename.d.ts.map +1 -0
- package/dist/commands/review.d.ts +4 -0
- package/dist/commands/review.d.ts.map +1 -0
- package/dist/commands/review.test.d.ts +2 -0
- package/dist/commands/review.test.d.ts.map +1 -0
- package/dist/commands/scaffold-adapter.d.ts +3 -0
- package/dist/commands/scaffold-adapter.d.ts.map +1 -0
- package/dist/commands/scaffold-adapter.test.d.ts +2 -0
- package/dist/commands/scaffold-adapter.test.d.ts.map +1 -0
- package/dist/commands/scan.d.ts +3 -0
- package/dist/commands/scan.d.ts.map +1 -0
- package/dist/commands/sync-seed.test.d.ts +2 -0
- package/dist/commands/sync-seed.test.d.ts.map +1 -0
- package/dist/commands/sync.d.ts +3 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/transform.d.ts +3 -0
- package/dist/commands/transform.d.ts.map +1 -0
- package/dist/commands/translate/csv-handler.d.ts +21 -0
- package/dist/commands/translate/csv-handler.d.ts.map +1 -0
- package/dist/commands/translate/executor.d.ts +31 -0
- package/dist/commands/translate/executor.d.ts.map +1 -0
- package/dist/commands/translate/index.d.ts +10 -0
- package/dist/commands/translate/index.d.ts.map +1 -0
- package/dist/commands/translate/reporter.d.ts +29 -0
- package/dist/commands/translate/reporter.d.ts.map +1 -0
- package/dist/commands/translate/types.d.ts +52 -0
- package/dist/commands/translate/types.d.ts.map +1 -0
- package/dist/commands/translate.d.ts +7 -0
- package/dist/commands/translate.d.ts.map +1 -0
- package/dist/commands/translate.test.d.ts +2 -0
- package/dist/commands/translate.test.d.ts.map +1 -0
- package/dist/e2e.test.d.ts +6 -0
- package/dist/e2e.test.d.ts.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1121 -387
- package/dist/integration.test.d.ts +6 -0
- package/dist/integration.test.d.ts.map +1 -0
- package/dist/test-helpers/ensure-cli-built.d.ts +2 -0
- package/dist/test-helpers/ensure-cli-built.d.ts.map +1 -0
- package/dist/utils/diagnostics-exit.d.ts +12 -0
- package/dist/utils/diagnostics-exit.d.ts.map +1 -0
- package/dist/utils/diagnostics-exit.test.d.ts +2 -0
- package/dist/utils/diagnostics-exit.test.d.ts.map +1 -0
- package/dist/utils/diff-utils.d.ts +4 -0
- package/dist/utils/diff-utils.d.ts.map +1 -0
- package/dist/utils/diff-utils.test.d.ts +2 -0
- package/dist/utils/diff-utils.test.d.ts.map +1 -0
- package/dist/utils/exit-codes.d.ts +142 -0
- package/dist/utils/exit-codes.d.ts.map +1 -0
- package/dist/utils/package-manager.d.ts +4 -0
- package/dist/utils/package-manager.d.ts.map +1 -0
- package/dist/utils/pkg.d.ts +3 -0
- package/dist/utils/pkg.d.ts.map +1 -0
- package/dist/utils/preview.d.ts +13 -0
- package/dist/utils/preview.d.ts.map +1 -0
- package/dist/utils/provider-injector.d.ts +36 -0
- package/dist/utils/provider-injector.d.ts.map +1 -0
- package/dist/utils/provider-injector.test.d.ts +2 -0
- package/dist/utils/provider-injector.test.d.ts.map +1 -0
- package/dist/utils/scaffold.d.ts +20 -0
- package/dist/utils/scaffold.d.ts.map +1 -0
- package/package.json +3 -2
- package/src/commands/debug-patterns.test.ts +6 -1
- package/src/commands/rename.ts +35 -3
- package/src/commands/review.test.ts +12 -0
- package/src/commands/review.ts +228 -0
- package/src/commands/sync-seed.test.ts +9 -3
- package/src/commands/sync.ts +104 -10
- package/src/commands/transform.ts +31 -4
- package/src/commands/translate/index.ts +23 -3
- package/src/commands/translate/types.ts +2 -0
- package/src/commands/translate.test.ts +9 -3
- package/src/e2e.test.ts +3 -11
- package/src/index.ts +2 -0
- package/src/integration.test.ts +12 -1
- package/src/test-helpers/ensure-cli-built.ts +32 -0
- package/src/utils/preview.ts +126 -0
- package/dist/index.js.map +0 -7
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { stat } from 'fs/promises';
|
|
2
|
+
|
|
3
|
+
const DEFAULT_MAX_ATTEMPTS = 20;
|
|
4
|
+
const DEFAULT_DELAY_MS = 300;
|
|
5
|
+
const MIN_FILE_SIZE_BYTES = 1024;
|
|
6
|
+
|
|
7
|
+
function sleep(ms: number) {
|
|
8
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export async function ensureCliBuilt(cliPath: string): Promise<void> {
|
|
12
|
+
const maxAttempts = Number(process.env.I18NSMITH_TEST_CLI_ATTEMPTS ?? DEFAULT_MAX_ATTEMPTS);
|
|
13
|
+
const delayMs = Number(process.env.I18NSMITH_TEST_CLI_DELAY_MS ?? DEFAULT_DELAY_MS);
|
|
14
|
+
|
|
15
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
16
|
+
try {
|
|
17
|
+
const stats = await stat(cliPath);
|
|
18
|
+
if (stats.size >= MIN_FILE_SIZE_BYTES) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
} catch {
|
|
22
|
+
// ignore and retry
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
await sleep(delayMs);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
throw new Error(
|
|
29
|
+
`CLI not found at ${cliPath} after ${maxAttempts} attempts. ` +
|
|
30
|
+
"Ensure 'pnpm build' completes successfully before running tests."
|
|
31
|
+
);
|
|
32
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { spawn } from 'child_process';
|
|
4
|
+
|
|
5
|
+
export interface PreviewPayload<TSummary> {
|
|
6
|
+
type: string;
|
|
7
|
+
version: number;
|
|
8
|
+
command: string;
|
|
9
|
+
args: string[];
|
|
10
|
+
timestamp: string;
|
|
11
|
+
summary: TSummary;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type PreviewKind = 'sync' | 'transform' | 'rename-key' | 'translate';
|
|
15
|
+
|
|
16
|
+
export async function writePreviewFile<TSummary>(
|
|
17
|
+
kind: PreviewKind,
|
|
18
|
+
summary: TSummary,
|
|
19
|
+
outputPath: string
|
|
20
|
+
): Promise<string> {
|
|
21
|
+
const resolvedPath = path.resolve(process.cwd(), outputPath);
|
|
22
|
+
const payload: PreviewPayload<TSummary> = {
|
|
23
|
+
type: `${kind}-preview`,
|
|
24
|
+
version: 1,
|
|
25
|
+
command: buildCommandString(),
|
|
26
|
+
args: process.argv.slice(2),
|
|
27
|
+
timestamp: new Date().toISOString(),
|
|
28
|
+
summary,
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
await fs.mkdir(path.dirname(resolvedPath), { recursive: true });
|
|
32
|
+
await fs.writeFile(resolvedPath, JSON.stringify(payload, null, 2), 'utf8');
|
|
33
|
+
return resolvedPath;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export async function readPreviewFile<TSummary>(
|
|
37
|
+
expectedKind: PreviewKind,
|
|
38
|
+
previewPath: string
|
|
39
|
+
): Promise<PreviewPayload<TSummary>> {
|
|
40
|
+
const resolved = path.resolve(process.cwd(), previewPath);
|
|
41
|
+
const raw = await fs.readFile(resolved, 'utf8');
|
|
42
|
+
const payload = JSON.parse(raw) as PreviewPayload<TSummary>;
|
|
43
|
+
if (!payload?.type?.startsWith(`${expectedKind}-preview`)) {
|
|
44
|
+
throw new Error(`Preview kind mismatch. Expected ${expectedKind}, got ${payload?.type ?? 'unknown'}.`);
|
|
45
|
+
}
|
|
46
|
+
if (!Array.isArray(payload.args) || payload.args.length === 0) {
|
|
47
|
+
throw new Error('Preview file is missing recorded CLI arguments.');
|
|
48
|
+
}
|
|
49
|
+
return payload;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export async function applyPreviewFile(
|
|
53
|
+
expectedKind: PreviewKind,
|
|
54
|
+
previewPath: string,
|
|
55
|
+
extraArgs: string[] = []
|
|
56
|
+
): Promise<void> {
|
|
57
|
+
const payload = await readPreviewFile(expectedKind, previewPath);
|
|
58
|
+
const sanitizedArgs = sanitizePreviewArgs(payload.args);
|
|
59
|
+
const [command, ...rest] = sanitizedArgs;
|
|
60
|
+
if (!command) {
|
|
61
|
+
throw new Error('Preview file does not include the original command.');
|
|
62
|
+
}
|
|
63
|
+
if (command !== expectedKind) {
|
|
64
|
+
throw new Error(`Preview command mismatch. Expected ${expectedKind}, got ${command}.`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const replayArgs = [command, ...rest];
|
|
68
|
+
if (!replayArgs.some((arg) => arg === '--write' || arg.startsWith('--write='))) {
|
|
69
|
+
replayArgs.push('--write');
|
|
70
|
+
}
|
|
71
|
+
for (const extra of extraArgs) {
|
|
72
|
+
if (!replayArgs.includes(extra)) {
|
|
73
|
+
replayArgs.push(extra);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
console.log(`Applying preview from ${path.relative(process.cwd(), path.resolve(previewPath))}…`);
|
|
78
|
+
await spawnCli(replayArgs);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function sanitizePreviewArgs(args: string[]): string[] {
|
|
82
|
+
const sanitized: string[] = [];
|
|
83
|
+
for (let i = 0; i < args.length; i++) {
|
|
84
|
+
const token = args[i];
|
|
85
|
+
if (token === '--preview-output') {
|
|
86
|
+
i += 1;
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
if (token?.startsWith('--preview-output=')) {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
sanitized.push(token);
|
|
93
|
+
}
|
|
94
|
+
return sanitized;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function spawnCli(args: string[]): Promise<void> {
|
|
98
|
+
const entry = process.argv[1];
|
|
99
|
+
if (!entry) {
|
|
100
|
+
return Promise.reject(new Error('Unable to determine CLI entry point for preview apply.'));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return new Promise((resolve, reject) => {
|
|
104
|
+
const child = spawn(process.argv[0], [entry, ...args], {
|
|
105
|
+
stdio: 'inherit',
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
child.on('exit', (code) => {
|
|
109
|
+
if (code === 0) {
|
|
110
|
+
resolve();
|
|
111
|
+
} else {
|
|
112
|
+
reject(new Error(`Preview apply command exited with code ${code ?? 'unknown'}`));
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
child.on('error', (error) => {
|
|
117
|
+
reject(error);
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function buildCommandString(): string {
|
|
123
|
+
// Ignore the node + script path, keep user arguments only
|
|
124
|
+
const args = process.argv.slice(2);
|
|
125
|
+
return args.length ? `i18nsmith ${args.join(' ')}` : 'i18nsmith';
|
|
126
|
+
}
|