@hyperfrontend/builder/package/jsonjson
package.json synthesis primitives — read, inherit, filter, generate exports, resolve CDN paths, synthesize the dist manifest, and write it to disk.
The subdomain ships as small, single-purpose primitives so wrappers can compose only the steps they need: readProjectPackageJson, inheritFields for selective field copy, filterWorkspaceDepsFromOutput to strip workspace-internal entries, generateExportsFromFormats to align the published exports map with the bundle-phase outputs, getCdnPaths for unpkg/jsdelivr resolution, and writeOutputPackageJson for the final emit. synthesizePackageJson is the facade that wires all of them together.
API Reference
ƒ Functions
PackageJson with bundled-dep entries stripped from dependencies. When the dist contains pre-passed copies under
_dependencies/<dep>/, those packages are no longer transitive runtime requirements — consumers get them inside the tarball. Removing them from the published dependencies field keeps the manifest honest. If filtering empties the
dependencies map, the field is removed entirely.Parameters
Returns
PackageJsonPackageJson clone.Example
Stripping bundled deps from the published dependencies map
const filtered = filterBundledDepsFromOutput(srcPkg, ['rollup', 'postject'])filterWorkspaceDepsFromOutput(pkg: PackageJson, isWorkspacePackage: IsWorkspacePackagePredicate): PackageJson
PackageJson with workspace-internal entries stripped from dependencies. peerDependencies and optionalDependencies are preserved verbatim so consumers retain optional integrations. If filtering empties the
dependencies map, the field is removed from the returned object instead of left as {}.Parameters
Returns
PackageJsonPackageJson clone.Example
Stripping `@hyperfrontend/*` deps before publishing
const filtered = filterWorkspaceDepsFromOutput(srcPkg, byPrefix('@hyperfrontend/'))generateExportsFromFormats(discovery: EntryPointDiscovery, formatOutputs: FormatOutputs, srcPkg?: PackageJson): Record<string, ExportValue>
exports field by aligning the source package.json declaration with the actual format outputs the bundle phase produced. Strategy is source-exports first: every key declared on
srcPkg.exports is mapped to a conditional export entry built from the formats that actually landed for the matching subpath. Internal modules that were built but not advertised in the source exports map are intentionally omitted from the published output. If
srcPkg has no exports field, falls back to a single root-entry export synthesized from discovery.hasRootEntry. IIFE / UMD CDN bundles are not advertised in
exports; they are reached solely through the unpkg/jsdelivr fields (see getCdnPaths).Parameters
Returns
Record<string, ExportValue>exports map suitable for the published package.json.Example
Generating exports honoring source aliases
const exports = generateExportsFromFormats(discovery, formatOutputs, srcPkg)package.json. Priority order:
- Explicit
opts.unpkg/opts.jsdelivroverrides win for their respective field. - The first UMD bundle, when one was emitted, supplies the default path.
- The first IIFE bundle is used when no UMD bundle exists.
- When no UMD or IIFE bundles were produced, returns
undefinedso callers can
Parameters
Returns
CdnPathsundefined when no CDN-eligible bundle was produced.Example
Resolving CDN paths from a UMD-only build
const cdn = getCdnPaths(formatOutputs)
// → { unpkg: './bundle/index.umd.min.js', jsdelivr: './bundle/index.umd.min.js' }PackageJson with the requested top-level fields copied from the source described by spec onto target. The merge is intentionally shallow: only fields named in
spec.fields are considered, and the original target value wins when the source field is missing or undefined. The function is a no-op (returns target unchanged) when spec is omitted, and silently returns target when the source file does not exist on disk.Parameters
Returns
PackageJsonPackageJson with inherited fields applied.Example
Inheriting `repository`, `bugs`, and `author` from the workspace root
const merged = inheritFields(srcPkg, {
from: '/abs/repo/package.json',
fields: ['repository', 'bugs', 'author'],
})package.json from the given project root. The file is required to exist; missing files surface as the standard
FS_NOT_FOUND filesystem error from project-scope.Parameters
| Name | Type | Description |
|---|---|---|
§projectRoot | string | Absolute path to the project root containing package.json. |
Returns
PackageJsonpackage.json contents typed as PackageJson.Example
Reading the source package.json before synthesizing the dist version
const srcPkg = readProjectPackageJson('/abs/libs/foo')
console.log(srcPkg.name)package.json#files allowlist. Derives
files from what the build actually emitted: the two index globs cover every entrypoint index./index.d.ts at any depth, and every surviving non-index file is named explicitly by its package-root-relative POSIX path (no <dir>/ buckets). Run after every emit phase and the orphan-prune so the walk sees exactly the tree that ships; the allowlist is then correct by construction. The root
package.json is skipped (npm always includes it) and index. files are skipped (covered by the glob); metadata files (README, LICENSE, THIRD_PARTY_LICENSES, …) are picked up by the walk only when present. The sorted positive entries are followed by JS_MAP_EXCLUDE_GLOB — a trailing negation that subtracts any JS sourcemap the index glob would otherwise ship. It must come last (npm resolves
files last-match-wins), so it is appended after the sort rather than folded into the sorted set.Parameters
| Name | Type | Description |
|---|---|---|
§outputPath | string | Absolute path to the materialized publishable output root. |
Returns
string[]package.json#files.Example
Reflecting a built library's output tree
const files = reflectFilesAllowlist(ctx.outputPath)
// => the two index globs, then 'README.md', 'models.d.ts', 'bin/hf-build.js', …, '!**/*.js.map'synthesizePackageJson(srcPkg: PackageJson, ctx: BuildContext, formatOutputs: FormatOutputs, opts?: SynthesizePackageJsonOptions): PackageJson
package.json from the source manifest, the bundle-phase outputs, and caller-supplied options. Pipeline order is: filter workspace deps → apply inherited fields → assemble the new manifest with
sideEffects: false, the regenerated exports map, and resolved main / module / types pointers; CDN fields are appended only when a UMD or IIFE bundle was emitted; the bin field is synthesized from the supplied bin declarations using deterministic naming rules; the files allowlist is forwarded verbatim when supplied. Root-pointers (
main, module, types) are removed entirely when the library has no root entry, so consumers cannot resolve a non-existent default.Parameters
| Name | Type | Description |
|---|---|---|
§srcPkg | PackageJson | Source package.json parsed from the project root. |
§ctx | BuildContext | Resolved build context (used for the entry-point discovery shape). |
§formatOutputs | FormatOutputs | Aggregated outputs collected by the bundle phase. |
§opts? | SynthesizePackageJsonOptions | Inheritance / filter / CDN-override / bin / files toggles. |
Returns
PackageJsonPackageJson ready to be written to the dist root.Example
Synthesizing the dist package.json for a library with workspace inlining
const distPkg = synthesizePackageJson(srcPkg, ctx, formatOutputs, {
inheritFieldsFrom: { from: '/abs/repo/package.json', fields: ['repository', 'bugs'] },
filterWorkspaceDepsFromOutput: true,
isWorkspacePackage: (n) => n.startsWith('@hyperfrontend/'),
bins: [{ name: 'hf-build', format: ['cjs'] }],
files: ['_dependencies/', 'bin/', 'index.*'],
})package.json to the build output directory. The file is emitted with two-space indentation (project-scope's default) and a trailing newline so the published artifact diffs cleanly against formatter-managed source files.
Parameters
Example
Writing the dist package.json
writeOutputPackageJson(ctx.outputPath, distPkg)◈ Interfaces
unpkg and jsdelivr package.json fields.Properties
filterWorkspaceDepsFromOutput?:boolean— dependencies map.inheritFieldsFrom?:InheritFromSpec— package.json onto the output.isWorkspacePackage?:IsWorkspacePackagePredicate—