@bobfrankston/freezepak
v0.1.5
Published
Freeze/unfreeze node_modules — replace symlinks/junctions with real copies for portable deployment
Maintainers
Readme
freezepak
Freeze and unfreeze node_modules dependencies for portable deployment.
Problem
When you use local file: dependencies during development, npm creates symlinks (Linux/Mac) or junctions (Windows) in node_modules pointing back to the source directories. This is great for development — changes are reflected immediately — but these links break when you copy or deploy the project to another machine.
Solution
freezepak --freeze replaces every symlink/junction in node_modules with a real copy of the target directory. The project becomes fully self-contained and portable. It also adds a preinstall guard to package.json that blocks npm install from accidentally restoring the links and undoing the freeze.
freezepak --unfreeze removes the guard and runs npm install to restore normal linked dependencies.
Installation
npm install -g @bobfrankston/freezepakCLI Usage
freezepak [path] --freeze # Replace links with real copies
freezepak [path] --unfreeze # Restore links via npm install
freezepak [path] --pack # Freeze, pack to .tgz, then unfreeze
freezepak -v # Show versionThe optional path argument specifies the project directory (defaults to the current directory).
Library Usage
freezepak can also be imported and used programmatically:
import { freezepak, freezeDependencies, unfreezeDependencies } from '@bobfrankston/freezepak';
// Freeze, create .tgz archive, then unfreeze — returns path to .tgz
const tgzPath: string = freezepak('/path/to/project');
// Freeze only (replace symlinks/junctions with real copies)
freezeDependencies('/path/to/project');
// Unfreeze only (remove guard, run npm install to restore links)
unfreezeDependencies('/path/to/project');Idempotency
Both operations are idempotent — safe to run multiple times:
--freezeskips entries that are already real directories (not links). Running freeze twice on the same project just reports 0 frozen packages the second time. The preinstall guard is overwritten with the same value.--unfreezechecks for the preinstall guard before acting. If there's no guard (already unfrozen), it reports "nothing to unfreeze" and exits without runningnpm install.
Reversibility
The dependencies field in package.json is never modified — your file: paths remain intact. This is what makes unfreeze possible: npm install reads those paths and recreates the links. The only package.json change is the preinstall guard in scripts, which unfreeze removes.
How it works
Freeze
- Walks
node_modules(including@scope/directories) - For each entry, checks if it's a symlink or junction (comparing
realpathSyncto the entry path) - If linked: removes the link, copies the real target directory in its place via
fs.cpSync - Saves any existing
preinstallscript asfrozen-preinstall - Sets
preinstallto a guard that blocksnpm installwith an error message
Unfreeze
- Restores the original
preinstallscript (if one was saved asfrozen-preinstall), or removes the guard entirely - Runs
npm installwhich reads the preservedfile:paths independenciesand recreates proper symlinks/junctions
License
MIT
