Package packing
flog pack creates a deterministic npm-compatible .tgz independently of
publishing. A later publish operation can upload this exact artifact without
repacking it.
flog pack
flog pack ./packages/core --destination ./artifacts
flog pack --workspace @primate/core
flog pack --workspace ./packages/core/package.json
flog pack --workspace './packages/**'
flog pack --recursive
--workspace accepts an exact package name, workspace directory, file owned by
a workspace, or workspace path glob. Exact and glob selectors cannot be mixed,
and aliases or overlapping globs that select a workspace twice are errors.
Relative paths resolve from the selected package/project directory. Recursive
packing considers every workspace package. A private package requested by an
exact selector is an error. In a multi-workspace glob selection, private
packages matched by a broad path glob (or by plain --recursive) are
intentionally omitted and reported by package name and importer path. A broad
selection that matches only private packages is an error rather than a
successful empty pack.
Flog validates every selected manifest before running lifecycle scripts or
creating output, so a later invalid selection cannot leave earlier artifacts.
Inspection#
--dry-run computes the complete artifact and metadata without writing the
tarball. It still runs pack lifecycle scripts. --json writes a schema-versioned
report to standard output. Its packages array includes:
- package name and version;
- artifact filename and written path;
- packed and unpacked sizes;
- SHA-1 registry shasum and SHA-512 SRI integrity;
- sorted file paths, sizes, and modes;
- the exact final packed manifest.
The report's omitted array records each intentionally excluded workspace with
its name, importer, and reason (private). Both arrays are always present,
including when empty. Human output prints the same omission evidence before the
packed package details.
Lifecycle script output goes to standard error so JSON output remains valid.
Lifecycle order#
For each package, flog runs exact lifecycle events in this order:
prepackprepare- create and, unless dry-running, safely replace the artifact
postpack
These are operation lifecycle events, so flog does not synthesize additional
preprepack or postprepack hooks around them. Workspace packages are packed
sequentially in deterministic path order, and the first failure stops further
work.
File selection#
Flog honors the package's files allowlist, including negated patterns, and
.npmignore rules with .gitignore as the root fallback. When files is
present, its root allowlist takes precedence over root ignore rules, while
nested .npmignore files still apply within their directories. Git metadata,
dependency trees, lock files, package-manager configuration, existing
tarballs, and other npm hard exclusions are never packed.
package.json, root README and license files, main, and bin targets are
mandatory regardless of allowlist or ignore rules. Bin targets receive mode
0755; other files receive mode 0644. A publish directory inherits its
package license, and a workspace package without one inherits the workspace
root license.
Symbolic links are rejected rather than followed, preventing package contents from escaping the selected source directory.
Packed manifests#
Packed manifests retain unknown fields but are encoded with deterministic key
ordering. workspace: dependencies in dependencies, optional dependencies,
peer dependencies, and development dependencies are converted using local
workspace versions:
workspace:*becomes the exact version;workspace:^andworkspace:~preserve their operators;- explicit workspace ranges lose the protocol prefix after verification that the local version satisfies the range.
Missing targets, missing target versions, incompatible explicit ranges,
directly selected private packages, and any remaining workspace: value are
errors.
Packing performs the conversion; publication additionally compares the result with registry baselines and the complete workspace release closure. See workspace release sets.
publishConfig.directory selects a relative package content directory. The
packed manifest removes that local-only directory setting and applies supported
publish overrides for main, module, browser, types, typings,
exports, imports, and bin.
Tar entries use stable ordering, normalized ownership and modes, npm's portable
timestamp, and a deterministic gzip header. Scoped artifact names use npm's
scope-package-version.tgz form.