@dk/hipp 0.1.37 → 0.1.40

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.
Files changed (3) hide show
  1. package/README.md +6 -6
  2. package/hipp.js +34 -39
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -273,21 +273,21 @@ PERFORMANCE OF THIS SOFTWARE.
273
273
  Verify this package with [@dk/hipp](https://www.npmjs.com/package/@dk/hipp):
274
274
 
275
275
  ```bash
276
- npx @dk/hipp --verify @dk/hipp@0.1.37
276
+ npx @dk/hipp --verify @dk/hipp@0.1.40
277
277
  ```
278
278
 
279
279
  ```json
280
280
  {
281
281
  "origin": "git@github.com:dmytri/hipp.git",
282
- "tag": "v0.1.37",
283
- "revision": "3efc2c67bcb1e75b9fb3c44a2e572dba1aa1703d",
284
- "hash": "f3cae0034df0aaa5382c0d047fff684ab30354eab2a3b7f280438a95a7ef9488",
285
- "signature": "c7ck6ex7mu5OqR2JiRnlnU0nnBHoYPqQkSvKDnvhfyBGUKnOUyT/uEyxifj+UW+s3GB4m651zDauhjWsqVMIDw==",
282
+ "tag": "v0.1.40",
283
+ "revision": "53c50c6f0263dd2f24b2b195e116d4ec03c77c1f",
284
+ "hash": "af45dd66df7b54705c7c0c2a5e3bd24222727bc34668e2d89c8079175cdd1df4",
285
+ "signature": "LxM3pd+3c7lXqtLAesfEM4gx0NSso3zQchm+EBmhK4X23CScWJQeWS/VC5PdVOiDWj8KquFUMzyrOG4Hj5ViCw==",
286
286
  "name": "Dmytri Kleiner",
287
287
  "email": "dev@dmytri.to",
288
288
  "npm": "11.12.1",
289
289
  "node": "v25.8.2",
290
290
  "git": "git version 2.47.3",
291
- "hipp": "0.1.37"
291
+ "hipp": "0.1.40"
292
292
  }
293
293
  ```
package/hipp.js CHANGED
@@ -178,25 +178,24 @@ function findLastJsonBlock(readmeContent) {
178
178
  return lastValid;
179
179
  }
180
180
 
181
- function hashFiles(dir) {
182
- const entries = [];
183
- const walk = (d, prefix = '') => {
184
- const items = fs.readdirSync(d);
185
- for (const item of items.sort()) {
186
- if (item === 'node_modules' || item === '.git' || item === 'hipp.priv') continue;
187
- const full = path.join(d, item);
188
- const rel = prefix ? prefix + '/' + item : item;
189
- const stat = fs.statSync(full);
190
- if (stat.isDirectory()) {
191
- walk(full, rel);
192
- } else {
193
- const content = fs.readFileSync(full);
194
- entries.push(rel + ':' + sha256(content));
195
- }
196
- }
197
- };
198
- walk(dir);
199
- return sha256(entries.join('\n'));
181
+ function packAndHash(stageDir) {
182
+ const result = spawnSync('npm', ['pack'], {
183
+ cwd: stageDir,
184
+ encoding: 'utf8',
185
+ stdio: ['pipe', 'pipe', 'pipe'],
186
+ });
187
+
188
+ if (result.status !== 0) {
189
+ throw new Error(`npm pack failed: ${result.stderr}`);
190
+ }
191
+
192
+ const tarballName = result.stdout.trim().split('\n').pop();
193
+ const tarballPath = path.join(stageDir, tarballName);
194
+
195
+ const tarballContent = fs.readFileSync(tarballPath);
196
+ fs.unlinkSync(tarballPath);
197
+
198
+ return { tarballName, tarballHash: sha256(tarballContent) };
200
199
  }
201
200
 
202
201
  function safeStageName(name) {
@@ -456,6 +455,10 @@ async function runVerify(packageSpec) {
456
455
  fail(`❌ Failed to download tarball`);
457
456
  }
458
457
 
458
+ const npmTarballContent = fs.readFileSync(tarballPath);
459
+ const npmHash = sha256(npmTarballContent);
460
+ log.success(`📦 NPM tarball hash: ${npmHash.slice(0, 12)}...`);
461
+
459
462
  if (fs.existsSync(extractDir)) {
460
463
  fs.rmSync(extractDir, { recursive: true });
461
464
  }
@@ -528,8 +531,8 @@ async function runVerify(packageSpec) {
528
531
  const trackedFiles = getTrackedFilesFromDir(tmpDir);
529
532
  copyTrackedFilesFromDir(stageDir, tmpDir, trackedFiles);
530
533
 
531
- log.info(`📦 Computing logical hash of git files...`);
532
- const cleanHash = hashFiles(stageDir);
534
+ log.info(`📦 Packing clean git files...`);
535
+ const { tarballHash: cleanHash } = packAndHash(stageDir);
533
536
  log.success(`📦 Clean hash: ${cleanHash.slice(0, 12)}...`);
534
537
 
535
538
  log.info(`🔍 Check 2: Verifying manifest hash...`);
@@ -568,22 +571,14 @@ async function runVerify(packageSpec) {
568
571
 
569
572
  const stagedPkgPath = path.join(stageDir, 'package.json');
570
573
  const stagedPkg = JSON.parse(fs.readFileSync(stagedPkgPath, 'utf8'));
574
+ stagedPkg.version = tagVersion;
571
575
  fs.writeFileSync(stagedPkgPath, JSON.stringify(stagedPkg, null, 2) + '\n');
572
576
 
573
- const npmExtractPkgPath = path.join(packageDir, 'package.json');
574
- const npmExtractPkg = JSON.parse(fs.readFileSync(npmExtractPkgPath, 'utf8'));
575
- if (stagedPkg.version === '0.0.0') {
576
- npmExtractPkg.version = '0.0.0';
577
- fs.writeFileSync(npmExtractPkgPath, JSON.stringify(npmExtractPkg, null, 2) + '\n');
578
- }
579
-
580
- const npmExtractHash = hashFiles(packageDir);
581
- const rebuildHash = hashFiles(stageDir);
582
- log.success(`📦 NPM-extract hash: ${npmExtractHash.slice(0, 12)}...`);
583
- log.success(`📦 Git-rebuild hash: ${rebuildHash.slice(0, 12)}...`);
577
+ const { tarballHash: rebuildHash } = packAndHash(stageDir);
578
+ log.success(`📦 Rebuild hash: ${rebuildHash.slice(0, 12)}...`);
584
579
 
585
- if (rebuildHash !== npmExtractHash) {
586
- log.error(`❌ Rebuild mismatch: git ${rebuildHash.slice(0, 12)} != npm ${npmExtractHash.slice(0, 12)}`);
580
+ if (rebuildHash !== npmHash) {
581
+ log.error(`❌ Rebuild mismatch: rebuild ${rebuildHash.slice(0, 12)} != npm ${npmHash.slice(0, 12)}`);
587
582
  } else {
588
583
  log.success(`🔄 Rebuild verified`);
589
584
  results.rebuild = true;
@@ -712,9 +707,9 @@ async function run() {
712
707
 
713
708
  const { privateKey } = loadOrGenerateKeys();
714
709
 
715
- log.info(`📦 Computing logical hash...`);
716
- const logicalHash = hashFiles(stageDir);
717
- log.success(`🔒 Content hash: ${logicalHash.slice(0, 12)}...`);
710
+ log.info(`📦 Packing to compute content hash...`);
711
+ const { tarballHash } = packAndHash(stageDir);
712
+ log.success(`🔒 Content hash: ${tarballHash.slice(0, 12)}...`);
718
713
 
719
714
  const stagedReadmePath = path.join(stageDir, 'README.md');
720
715
  let stagedReadme = '';
@@ -731,14 +726,14 @@ async function run() {
731
726
  const hippPkg = JSON.parse(fs.readFileSync(hippPkgPath, 'utf8'));
732
727
  const hippVersion = hippPkg.version === '0.0.0' ? version : hippPkg.version;
733
728
  const originUrl = provenance.remoteUrl;
734
- const dataToSign = buildSignData(logicalHash, originUrl, rawTag, revision, name, email);
729
+ const dataToSign = buildSignData(tarballHash, originUrl, rawTag, revision, name, email);
735
730
  const signature = signContent(dataToSign, privateKey);
736
731
 
737
732
  const manifestJson = {
738
733
  origin: originUrl,
739
734
  tag: rawTag,
740
735
  revision: revision,
741
- hash: logicalHash,
736
+ hash: tarballHash,
742
737
  signature: signature,
743
738
  name: name,
744
739
  email: email,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dk/hipp",
3
- "version": "0.1.37",
3
+ "version": "0.1.40",
4
4
  "description": "High Integrity Package Publisher",
5
5
  "main": "hipp.js",
6
6
  "bin": {