htmlhost-cli 2.1.5 → 2.1.8
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/package.json +1 -1
- package/src/cli.mjs +1 -1
- package/src/commands/deploy.mjs +42 -19
package/package.json
CHANGED
package/src/cli.mjs
CHANGED
package/src/commands/deploy.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { readFileSync, writeFileSync, statSync, existsSync, readdirSync } from "node:fs";
|
|
1
|
+
import { readFileSync, writeFileSync, statSync, existsSync, readdirSync, mkdirSync } from "node:fs";
|
|
2
2
|
import { basename, resolve, dirname, join, extname } from "node:path";
|
|
3
3
|
import { createInterface } from "node:readline";
|
|
4
|
+
import { createHash } from "node:crypto";
|
|
4
5
|
import { post } from "../api.mjs";
|
|
5
6
|
import { ok, err, info, cyan, dim, bold, yellow, green, formatBytes, mimeFromExt } from "../ui.mjs";
|
|
6
7
|
|
|
@@ -347,6 +348,7 @@ async function deployDirectory(dirPath, { ttl, title, slug: explicitSlug, forceN
|
|
|
347
348
|
info(`Processing ${cyan(bold(String(htmlFiles.length)))} page${htmlFiles.length > 1 ? "s" : ""}…`);
|
|
348
349
|
|
|
349
350
|
const pagePayloads = [];
|
|
351
|
+
const seenPaths = new Set();
|
|
350
352
|
|
|
351
353
|
for (const file of htmlFiles) {
|
|
352
354
|
const html = readFileSync(file.filePath, "utf8");
|
|
@@ -362,6 +364,12 @@ async function deployDirectory(dirPath, { ttl, title, slug: explicitSlug, forceN
|
|
|
362
364
|
pagePath = "/" + file.relativePath.replace(/\.html$/, "");
|
|
363
365
|
}
|
|
364
366
|
|
|
367
|
+
if (seenPaths.has(pagePath)) {
|
|
368
|
+
info(`Skipping duplicate route: ${cyan(file.relativePath)} (conflicts with existing ${pagePath})`);
|
|
369
|
+
continue;
|
|
370
|
+
}
|
|
371
|
+
seenPaths.add(pagePath);
|
|
372
|
+
|
|
365
373
|
pagePayloads.push({ path: pagePath, html });
|
|
366
374
|
ok(`${cyan(file.relativePath)} → ${cyan(pagePath)}`);
|
|
367
375
|
}
|
|
@@ -377,11 +385,18 @@ async function deployDirectory(dirPath, { ttl, title, slug: explicitSlug, forceN
|
|
|
377
385
|
slug: existingSlug || undefined,
|
|
378
386
|
isNewSite: !existingSlug,
|
|
379
387
|
html: pagePayloads[0]?.html || "",
|
|
380
|
-
assets: assetFiles.map(f =>
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
388
|
+
assets: assetFiles.map(f => {
|
|
389
|
+
const buffer = readFileSync(f.filePath);
|
|
390
|
+
const hash = createHash('sha256').update(buffer).digest('hex');
|
|
391
|
+
// Store buffer on file object to avoid reading again
|
|
392
|
+
f.buffer = buffer;
|
|
393
|
+
return {
|
|
394
|
+
path: f.relativePath,
|
|
395
|
+
sizeBytes: f.size,
|
|
396
|
+
mimeType: mimeFromExt(basename(f.filePath)),
|
|
397
|
+
hash
|
|
398
|
+
};
|
|
399
|
+
})
|
|
385
400
|
};
|
|
386
401
|
|
|
387
402
|
let urlData;
|
|
@@ -397,29 +412,37 @@ async function deployDirectory(dirPath, { ttl, title, slug: explicitSlug, forceN
|
|
|
397
412
|
console.log("");
|
|
398
413
|
info(`Uploading ${cyan(bold(String(assetFiles.length)))} asset${assetFiles.length > 1 ? "s" : ""}…`);
|
|
399
414
|
|
|
415
|
+
let uploadedCount = 0;
|
|
416
|
+
let skippedCount = 0;
|
|
417
|
+
|
|
400
418
|
for (const u of uploadUrls) {
|
|
401
419
|
const file = assetFiles.find(f => f.relativePath === u.path);
|
|
402
|
-
const buffer = readFileSync(file.filePath);
|
|
403
|
-
|
|
404
|
-
const res = await fetch(u.uploadUrl, {
|
|
405
|
-
method: "PUT",
|
|
406
|
-
headers: { "Content-Type": u.mimeType },
|
|
407
|
-
body: buffer
|
|
408
|
-
});
|
|
409
420
|
|
|
410
|
-
if (
|
|
411
|
-
|
|
412
|
-
|
|
421
|
+
if (u.uploadUrl) {
|
|
422
|
+
const res = await fetch(u.uploadUrl, {
|
|
423
|
+
method: "PUT",
|
|
424
|
+
headers: { "Content-Type": u.mimeType },
|
|
425
|
+
body: file.buffer
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
if (!res.ok) {
|
|
429
|
+
err(`Failed to upload ${u.path}`);
|
|
430
|
+
process.exit(1);
|
|
431
|
+
}
|
|
432
|
+
ok(`✓ Uploaded ${cyan(u.path)} ${dim(`(${formatBytes(file.size)})`)}`);
|
|
433
|
+
uploadedCount++;
|
|
434
|
+
} else {
|
|
435
|
+
ok(`● Skipped (unchanged) ${cyan(u.path)} ${dim(`(${formatBytes(file.size)})`)}`);
|
|
436
|
+
skippedCount++;
|
|
413
437
|
}
|
|
414
438
|
|
|
415
439
|
assetPayloads.push({
|
|
416
440
|
path: u.path,
|
|
417
441
|
mimeType: u.mimeType,
|
|
418
442
|
sizeBytes: u.sizeBytes,
|
|
419
|
-
storageKey: u.storageKey
|
|
443
|
+
storageKey: u.storageKey,
|
|
444
|
+
hash: u.hash
|
|
420
445
|
});
|
|
421
|
-
|
|
422
|
-
ok(`✓ Uploaded ${cyan(u.path)} ${dim(`(${formatBytes(file.size)})`)}`);
|
|
423
446
|
}
|
|
424
447
|
|
|
425
448
|
if (!existingSlug) {
|