@intactfile/cli 0.1.0 → 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/dist/index.js +43 -1
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -8,6 +8,7 @@ import { basename, dirname, extname, join, parse } from "node:path";
|
|
|
8
8
|
import { createInterface } from "node:readline";
|
|
9
9
|
import { Command } from "commander";
|
|
10
10
|
import { ApiError, balance, clearAuth, consume, EntitlementError, getToken, login as apiLogin, magic as apiMagic, recover as apiRecover, repairPath, diagnosePath, requireBusiness, setToken, UnsupportedError, } from "@intactfile/node-core";
|
|
11
|
+
import { generateRepairReportPdf } from "@intactfile/report";
|
|
11
12
|
const program = new Command();
|
|
12
13
|
program
|
|
13
14
|
.name("intactfile")
|
|
@@ -85,6 +86,34 @@ function writeResult(input, out, r) {
|
|
|
85
86
|
writeFileSync(dest, r.bytes);
|
|
86
87
|
return [dest];
|
|
87
88
|
}
|
|
89
|
+
/** Map a repair result into the report package's minimal input shape. */
|
|
90
|
+
function toReportInput(input, r) {
|
|
91
|
+
const report = r.report;
|
|
92
|
+
const num = (v) => {
|
|
93
|
+
const n = typeof v === "number" ? v : v == null ? NaN : Number(v);
|
|
94
|
+
return Number.isFinite(n) ? n : undefined;
|
|
95
|
+
};
|
|
96
|
+
const base = {
|
|
97
|
+
fileName: basename(input),
|
|
98
|
+
family: r.family,
|
|
99
|
+
outcome: report.outcome != null ? String(report.outcome) : undefined,
|
|
100
|
+
damageClass: report.damageClass != null ? String(report.damageClass) : undefined,
|
|
101
|
+
bytesIn: num(report.bytesIn),
|
|
102
|
+
bytesOut: num(report.bytesOut),
|
|
103
|
+
notes: Array.isArray(report.notes) ? report.notes.map((n) => String(n)) : undefined,
|
|
104
|
+
};
|
|
105
|
+
if (r.kind === "archive") {
|
|
106
|
+
base.files = r.files.map((f) => ({ name: f.name, status: f.status }));
|
|
107
|
+
}
|
|
108
|
+
return base;
|
|
109
|
+
}
|
|
110
|
+
/** Generate and write a white-label PDF repair report; prints the path. */
|
|
111
|
+
async function writeReportPdf(input, r, path, company) {
|
|
112
|
+
const bytes = await generateRepairReportPdf(toReportInput(input, r), company ? { company } : {});
|
|
113
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
114
|
+
writeFileSync(path, bytes);
|
|
115
|
+
console.log(`✓ Report: ${path}`);
|
|
116
|
+
}
|
|
88
117
|
/* -------------------------------- login -------------------------------- */
|
|
89
118
|
program
|
|
90
119
|
.command("login")
|
|
@@ -182,13 +211,18 @@ program
|
|
|
182
211
|
.option("-o, --out <path>", "output path (or directory for archives)")
|
|
183
212
|
.option("-r, --reference <clip>", "healthy reference clip/photo (missing-moov video, JPEG donor)")
|
|
184
213
|
.option("-p, --password <pw>", "archive password (RAR/7z)")
|
|
214
|
+
.option("--report <path.pdf>", "also write a white-label PDF repair report to this path")
|
|
215
|
+
.option("--company <name>", "company name for the white-label report header")
|
|
185
216
|
.action(async (file, opts) => {
|
|
186
217
|
try {
|
|
187
218
|
const sub = await requireBusiness();
|
|
188
219
|
if (sub.monthlyRemaining <= 0) {
|
|
189
220
|
return die("Monthly repair allowance exhausted — it resets on your billing cycle.");
|
|
190
221
|
}
|
|
191
|
-
const r = await repairPath(file, {
|
|
222
|
+
const r = await repairPath(file, {
|
|
223
|
+
referencePath: opts.reference,
|
|
224
|
+
password: opts.password,
|
|
225
|
+
});
|
|
192
226
|
printReport(r.family, r.report);
|
|
193
227
|
if (!r.usable) {
|
|
194
228
|
return die("Couldn't produce a usable result — nothing was charged.");
|
|
@@ -196,6 +230,8 @@ program
|
|
|
196
230
|
const written = writeResult(file, opts.out, r);
|
|
197
231
|
await meter();
|
|
198
232
|
console.log(`✓ Wrote:\n${written.map((w) => ` ${w}`).join("\n")}`);
|
|
233
|
+
if (opts.report)
|
|
234
|
+
await writeReportPdf(file, r, opts.report, opts.company);
|
|
199
235
|
}
|
|
200
236
|
catch (e) {
|
|
201
237
|
handle(e);
|
|
@@ -206,6 +242,8 @@ program
|
|
|
206
242
|
.command("batch <files...>")
|
|
207
243
|
.description("Repair up to 100 files (Business plan). Each is metered separately.")
|
|
208
244
|
.option("-o, --outdir <dir>", "directory to write results into")
|
|
245
|
+
.option("--report-dir <dir>", "also write a white-label PDF repair report per file into this dir")
|
|
246
|
+
.option("--company <name>", "company name for the white-label report header")
|
|
209
247
|
.action(async (files, opts) => {
|
|
210
248
|
try {
|
|
211
249
|
await requireBusiness();
|
|
@@ -234,6 +272,10 @@ program
|
|
|
234
272
|
const written = writeResult(file, out, r);
|
|
235
273
|
await meter();
|
|
236
274
|
console.log(`✓ ${basename(file)} → ${written[0] ?? "(extracted)"}`);
|
|
275
|
+
if (opts.reportDir) {
|
|
276
|
+
const pdfPath = join(opts.reportDir, `${parse(file).name}.report.pdf`);
|
|
277
|
+
await writeReportPdf(file, r, pdfPath, opts.company);
|
|
278
|
+
}
|
|
237
279
|
ok++;
|
|
238
280
|
}
|
|
239
281
|
catch (e) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intactfile/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "IntactFile CLI — repair corrupted files locally (video, ZIP/Office, PDF, JPEG, PNG, SQLite, RAR/7z). Your files never leave your machine. Business plan for repairs; diagnosis is free.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"commander": "^12.1.0",
|
|
18
|
-
"@intactfile/node-core": "0.1.0"
|
|
18
|
+
"@intactfile/node-core": "0.1.0",
|
|
19
|
+
"@intactfile/report": "0.1.0"
|
|
19
20
|
},
|
|
20
21
|
"devDependencies": {
|
|
21
22
|
"@types/node": "^22.15.0",
|