mrkeyoor.com_
Sat 08 Aug 20:59 UTC
npmUtilsupdated 08 Aug 2026

clone-stats

clone-stats is a one-function CommonJS package for copying Node.js fs.Stats objects while keeping methods such as isFile(), isDirectory(), and isSymbolicLink(). It creates a new fs.Stats instance and assigns every enumerable property from the source. The package exists because spreading a Stats object into a plain object copies its data but loses its prototype methods. It has no runtime dependencies, but its implementation now rests on a deprecated Node constructor and does not correctly support BigInt stats.

Verdict

Keep it only where an old dependency already expects its exact behavior. New code should avoid it because the implementation invokes a deprecated Node constructor and fails on BigInt stats, the main modern variation of the object it claims to clone.

API stability4/5The public API has one call shape, require('clone-stats')(stats), and version 1.0.0 has not changed since 2016. That makes existing behavior predictable, but it is stability by inactivity rather than an actively managed compatibility promise. The input contract is only described as fs.Stats, with no handling guarantee for BigIntStats, subclasses, invalid inputs, or future Node changes.
Docs2/5The README clearly states the single purpose and shows the exported signature, so a reader can use the happy path in seconds. It does not show a complete fs.stat example, explain that the copy is shallow, document CommonJS and TypeScript limitations, discuss BigIntStats, or warn that direct fs.Stats construction is deprecated. The repository tests are the only detailed behavioral specification.
Maintenance1/5The latest npm release is 1.0.0 from May 2016, and the repository's last push was June 2024 without a corresponding release. The package is not formally deprecated or archived, but the code now triggers Node's DEP0180 warning and has no published fix. Its tiny scope reduces ordinary bug surface, yet the unaddressed runtime deprecation is directly in its only function.
Ecosystem3/5The package recorded 4,841,402 npm downloads from July 31 through August 6, 2026, largely because build-tool dependency trees still pull it in. It has no plugins, declarations, or extension API, and the GitHub repository has 11 stars. High transitive installation volume should not be mistaken for broad direct adoption or a living integration ecosystem.

Use it if

  • You maintain an older CommonJS dependency that already uses clone-stats and only passes ordinary number-based fs.Stats values
  • You need a mutable copy of a classic fs.stat result while preserving the familiar fs.Stats predicate methods
  • You need bug-compatible behavior with vinyl or another older build-pipeline package that historically depended on this exact module
Skip it if

Setup reality

Installation is only npm install clone-stats, and there are no runtime dependencies, peer dependencies, native builds, configuration files, credentials, or environment variables. The export is CommonJS: require('clone-stats') returns the cloning function. An ESM project can usually default-import the CommonJS package through Node interoperability, but there is no exports map and no native named export. The important surprise is runtime compatibility, not installation. The implementation calls new fs.Stats(), which produces a DEP0180 deprecation warning on Node 22. It then copies Object.keys(stats), so non-enumerable properties, symbol properties, a custom subclass prototype, and property descriptors are not preserved. Do not feed it results created with { bigint: true }; those are BigIntStats objects, while the replacement is ordinary Stats. The copied BigInt mode fields can make isFile() and related methods throw a mixed-number-type error. There are no bundled TypeScript declarations, so typed projects must add a local declaration or keep the call behind a small typed wrapper. The package performs no validation: null, undefined, or a plain lookalike either throws or produces a Stats instance with incomplete fields. Treat it as a compatibility shim for ordinary results from fs.stat, fs.lstat, or their synchronous forms, not as a general clone utility and not as a future-facing filesystem abstraction.

Patterns

Clone a synchronous file statclone-sync-stat

const fs = require('node:fs')
const cloneStats = require('clone-stats')

const original = fs.statSync('report.pdf')
const copy = cloneStats(original)

console.log(copy.size, copy.isFile())

Use only ordinary number-based stats. On current Node, the clone operation may emit DEP0180 because the package constructs fs.Stats directly.

Clone a callback-based stat resultclone-async-stat

const fs = require('node:fs')
const cloneStats = require('clone-stats')

fs.stat('uploads/photo.jpg', (error, stats) => {
  if (error) throw error
  const snapshot = cloneStats(stats)
  console.log(snapshot.mtime)
})

clone-stats itself is synchronous. It only copies the result passed by fs.stat and does not change filesystem error handling.

Clone a promise-based stat resultclone-promise-stat

import { stat } from 'node:fs/promises'
import cloneStats from 'clone-stats'

const original = await stat('package.json')
const copy = cloneStats(original)
console.log(copy.isFile())

The package is CommonJS. Node ESM default-import interoperability normally supplies the exported function, but the package has no exports map or native ESM build.

Keep Stats predicate methodspreserve-predicates

const plain = { ...original }
const cloned = cloneStats(original)

console.log(typeof plain.isDirectory)  // undefined
console.log(cloned.isDirectory())      // boolean

This prototype preservation is the package's entire reason to exist. Object spread and Object.assign({}, stats) produce plain objects without Stats methods.

Change copied scalar fields without changing the sourcemutate-copy

const original = fs.statSync('asset.css')
const copy = cloneStats(original)

copy.mtime = new Date(0)
copy.size = 0

console.log(original.size !== copy.size)

Built-in Stats fields are scalar values or Date objects. Reassigning a top-level field is independent, but mutating a shared nested object or Date in place can still affect both objects.

Clone symlink-aware lstat metadatacopy-lstat

const original = fs.lstatSync('current')
const copy = cloneStats(original)

if (copy.isSymbolicLink()) {
  console.log('current is a symlink')
}

Use lstat when the link itself matters. fs.stat follows a symbolic link before clone-stats sees the result.

Reject non-Stats inputs before cloningguard-input

const fs = require('node:fs')

function safeCloneStats(value) {
  if (!(value instanceof fs.Stats)) {
    throw new TypeError('Expected fs.Stats')
  }
  return cloneStats(value)
}

The package does no input validation. Object.keys(null) throws, while a plain object can silently become an incomplete Stats instance.

Keep BigInt stats out of clone-statsavoid-bigint

const precise = fs.statSync('archive.tar', { bigint: true })

// Do not pass precise to cloneStats. Keep the original, or copy
// the fields into an application-owned data shape instead.
const snapshot = { size: precise.size, mtimeNs: precise.mtimeNs }

BigIntStats uses different internal mode arithmetic. clone-stats replaces its prototype with ordinary Stats, so predicates can throw Cannot mix BigInt and other types.

Declare the untyped CommonJS module locallyadd-types

// types/clone-stats.d.ts
declare module 'clone-stats' {
  import type { Stats } from 'node:fs'
  function cloneStats(stats: Stats): Stats
  export = cloneStats
}

The package ships no TypeScript declarations. This narrow declaration deliberately excludes BigIntStats because the implementation does not handle it correctly.

Prefer an application-owned metadata snapshotsnapshot-fields

const stats = await fs.promises.stat('video.mp4')
const snapshot = {
  size: stats.size,
  mode: stats.mode,
  modifiedAt: stats.mtime.toISOString(),
  kind: stats.isFile() ? 'file' : 'other',
}

For serialization, caching, or worker messages, a plain explicit shape is safer than cloning a runtime-specific Stats instance and makes Date conversion intentional.

Alternatives

PackageRegistryPick it when
clonenpmUse for general object graphs when prototype preservation and circular-reference handling matter more than a tiny Stats-only helper
lodash.clonedeepnpmUse when the real requirement is a familiar general-purpose deep copy, after verifying how your special object types behave
rfdcnpmUse for fast deep cloning of ordinary data objects, with its proto option only when inherited enumerable properties are intentionally needed