hasher.ts
Overview
The [hasher.ts](/projects/291/68807) file provides functionality to generate a cryptographic hash that represents the content of key components within the project’s source tree. This hash is primarily used to uniquely identify the state of the project files that contribute to the final build image (referred to as the "base"). By hashing selected files and directories, the system can detect changes efficiently, which is useful for cache invalidation, build optimization, or integrity verification.
The core feature of this file is the asynchronous function `getBaseHash`, which computes a SHA-1 hash over specific selected files and directories, including configuration files at the root, package source files, common coinstack code, and coinstack dependencies. It leverages the `folder-hash` package to recursively hash folder contents with precise include/exclude filters, and Node.js’s native `crypto` module for hashing.
Detailed Explanation
Imports
import { createHash } from 'crypto'
import { hashElement } from 'folder-hash'
createHash: Node.js built-in module function to create hash digests.hashElement: Function fromfolder-hashpackage to recursively hash folder contents based on filter options.
Constants
const rootDir = `${__dirname}/../..`
const nodeDir = `${__dirname}/../../node`
rootDir: The project root directory, assumed two levels above the location of this file.nodeDir: Thenodedirectory inside the project root, specifically targeted for hashing packages and coinstack source.
Function: getBaseHash
export const getBaseHash = async (): Promise<string>
Purpose
Computes a SHA-1 hash string representing the current state of the build-related files and directories, effectively summarizing the base build context.
Parameters
None
Returns
Promise<string>: A promise resolving to a hexadecimal string of the SHA-1 digest.
Implementation Details
Initialize SHA-1 Hash Context
Uses Node.js
createHash('sha1')to create a hash object that will be updated incrementally.
Hash Root-Level Unchained Files
Calls
hashElementonrootDir.Filters:
Excludes all folders and files by default (
folders.exclude: ['.*', '*']).Includes only specific files:
package.json,lerna.json,yarn.lock,Dockerfile.node.
Updates the SHA-1 hash with the resulting folder hash.
Hash Contents of Packages
Targets
${nodeDir}/packages.Includes all folders except hidden (
.*),dist,node_modules, andpulumi.Includes files with extensions
.ts,.json, andDockerfile.Updates the SHA-1 hash with this packages hash.
Hash Common Coinstack Code
Targets
${nodeDir}/coinstacks/common.Same folder and file filters as packages.
Updates the SHA-1 hash with the common coinstack hash.
Hash Coinstacks Dependencies
Targets
${nodeDir}/coinstacks.Includes all folders except hidden,
common,dist,node_modules, andpulumi.Includes only
package.jsonfiles.Updates the SHA-1 hash with the dependencies hash.
Return Final Hash
Calls
hash.digest('hex')to produce the final hexadecimal string.
Usage Example
import { getBaseHash } from './hasher'
async function main() {
const baseHash = await getBaseHash()
console.log('Current base hash:', baseHash)
}
main()
This snippet will print the unique hash representing the current state of the base build files.
Important Implementation Notes
Selective Inclusion/Exclusion: The file carefully chooses which files and folders to hash, ignoring build artifacts (
dist), dependencies (node_modules), and hidden files/folders (.*). This ensures the hash reflects only source files and critical configuration, avoiding noise from generated content or dependencies.Use of
folder-hash: Instead of hashing files individually,hashElementcomputes a combined hash of directory contents recursively with given filters. This approach provides a consistent, order-independent hash of complex folder structures.Incremental Hashing: The SHA-1 hash is updated sequentially with each folder hash, combining all relevant parts of the project into a single hash result.
SHA-1 Algorithm: While SHA-1 is not recommended for cryptographic security, it remains adequate for build cache keys or change detection due to speed and reasonable collision resistance in this context.
Interaction with Other Parts of the System
Build System / CI Pipelines: The hash produced by
getBaseHashis likely used by build scripts or continuous integration workflows to detect source changes and decide whether to rebuild or reuse cached artifacts.Docker Image Building: Given references to
Dockerfile.nodeand Dockerfiles within packages and coinstacks, this hash may help identify when to rebuild Docker images or layers.Project Structure: The file relies on a specific directory layout — a root directory, a
nodedirectory withpackagesandcoinstackssubdirectories — consistent with a monorepo or modular project setup.External Dependency: Uses
folder-hashpackage, so it must be installed and maintained alongside the project dependencies.
Mermaid Diagram: Class / Function Structure
Since this file contains a single exported asynchronous function without any classes, the diagram below illustrates the functional flow and relationships between the hashing steps within `getBaseHash`.
flowchart TD
A[getBaseHash()]
A --> B[hash rootDir files]
B --> C[hash packages directory]
C --> D[hash coinstacks/common directory]
D --> E[hash coinstacks dependencies]
E --> F[combine all hashes]
F --> G[return SHA-1 digest string]
Summary
The [hasher.ts](/projects/291/68807) file is a utility module responsible for creating a composite SHA-1 hash that captures the state of critical source files and configuration within the project. This hash aids in build optimization by detecting changes relevant to the base build image. It uses recursive folder hashing with precise include/exclude rules to ensure accurate and meaningful hashing, and exposes a single asynchronous function `getBaseHash` for external use.