Skip to content

feat: folder hash#16

Merged
brunozoric merged 4 commits into
mainfrom
bruno/feat/folder-hash
May 25, 2026
Merged

feat: folder hash#16
brunozoric merged 4 commits into
mainfrom
bruno/feat/folder-hash

Conversation

@brunozoric
Copy link
Copy Markdown
Contributor

@brunozoric brunozoric commented May 25, 2026

Summary

Add HashFolderTool to @webiny/stdlib/node as a zero-dependency replacement for the unmaintained folder-hash library.

  • Deterministic SHA-256 folder hashing: walks the directory tree, hashes each file, sorts by relative path, combines into a single digest
  • Two methods: hash (sync) and hashAsync (parallel I/O via Promise.all)
  • Supports excludeFolders and excludeFiles options to skip build artifacts (dist, node_modules, tsbuildinfo, etc.)
  • Returns HashFolderResult object ({ hash: string }) for future extensibility
  • Three consumption modes: DI abstraction (HashFolderTool/HashFolderToolFeature), factory (createHashFolderTool), standalone functions (hashFolder/hashFolderAsync)
  • Full test coverage with 23 tests covering determinism, excludes, renames, empty folders, order-independence, and sync/async parity

Usage

const { hash } = hashFolder(workspacePackage.packageFolder, {
    excludeFolders: ["dist", "lib", "node_modules"],
    excludeFiles: ["tsconfig.build.tsbuildinfo"]
});

Test plan

  • All 365 tests pass (342 existing + 23 new)
  • 100% coverage on HashFolderTool implementation
  • No regressions in existing tests
  • Pre-commit chain clean (yarn, adio, format, lint, typecheck, build, test:coverage)

brunozoric and others added 4 commits May 25, 2026 08:29
Replaces the unmaintained folder-hash library with a zero-dependency
implementation using node:crypto and node:fs. Walks a directory tree,
hashes each file with SHA-256, sorts by relative path for deterministic
ordering, then produces a single combined hex digest. Supports
excludeFolders and excludeFiles options to skip build artifacts.

Exports: DI abstraction (HashFolderTool/HashFolderToolFeature),
factory (createHashFolderTool), and standalone function (hashFolder).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
hash() uses readdirSync/readFileSync for simple synchronous usage.
hashAsync() reads files and recurses into subdirectories concurrently
via Promise.all for better throughput on large directory trees.
Both methods produce identical deterministic SHA-256 digests.

Standalone exports: hashFolder (sync), hashFolderAsync (async).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Methods now return { hash: string } instead of a bare string,
making the return type extensible for future metadata (file count,
total size, etc.) without a breaking API change.

Also adds changeset for the patch release.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@brunozoric brunozoric self-assigned this May 25, 2026
@brunozoric brunozoric merged commit 36d941e into main May 25, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant