Skip to content

Export the files we publish - #2450

Merged
spaceninja merged 1 commit into
mainfrom
fix-2078-export-published-subpaths
Aug 24, 2026
Merged

Export the files we publish#2450
spaceninja merged 1 commit into
mainfrom
fix-2078-export-published-subpaths

Conversation

@spaceninja

Copy link
Copy Markdown
Member

Overview

We publish 360 files — the compiled design tokens, the Sass partials, the Twig templates, the assets — and exactly one of them could be reached through Node resolution. Defining an exports field at all encapsulates every subpath that isn't listed, and ours was a bare string pointing at the browser bundle, so requiring the design tokens failed with ERR_PACKAGE_PATH_NOT_EXPORTED. So did reading our own package.json, which tooling routinely does to a dependency.

files and exports disagreed about what our public API is, and files is the field expressing the intent — those files are deliberately published. exports now mirrors its shape, so what we ship and what a consumer can reach are the same set. Widening exports cannot break an import that already worked, and the published file list is byte-for-byte unchanged; only reachability changes.

This also adds a types condition to the main entry. Under node16/nodenext/bundler module resolution, TypeScript reads types through exports and ignores the top-level types field, so consumers on those settings were silently getting any. That was already true before this change — it is fixed here because it is the same field and the same root cause, and it seemed wrong to touch exports and knowingly leave it broken. Runtime resolution of the main entry is unchanged. Happy to split it out if you'd rather keep this to the letter of the issue.

Two things worth a reviewer's attention. First, this commits us to those paths as API, which is the real decision in the issue; the answer taken here is that files already made that commitment and exports was contradicting it. Second, main still points at the CommonJS build but exports sends require() to the ESM one, exactly as it did before — that predates this change and is left alone rather than quietly folded in.

Screenshots

Testing

Sass is unaffected in both directions, so there is nothing to check there — it compiles identically before and after, because neither the load-path route nor the pkg: importer enforces the export map for stylesheets.

  • From the repo root, run npm run build, then npm pack. A file named cloudfour-patterns-17.1.0.tgz should appear in the repo root.
  • Make a new empty folder somewhere outside the repo, and in it run npm init -y followed by npm install /full/path/to/cloudfour-patterns-17.1.0.tgz.
  • In that folder, create a file called check.js containing:
    js const tokens = require('@cloudfour/patterns/src/compiled/tokens/json/tokens.json'); console.log(Object.keys(tokens));
  • Run node check.js. It should print a list of token group names. On main this same step fails with ERR_PACKAGE_PATH_NOT_EXPORTED.
  • In the same folder, create check-manifest.js containing console.log(require('@cloudfour/patterns/package.json').version); and run it. It should print 17.1.0 rather than an error — reading a dependency's manifest is something build tools do routinely.
  • Confirm the main entry point still works: create check-main.mjs containing import * as p from '@cloudfour/patterns'; console.log(Object.keys(p)); and run it. It should list four component functions.
  • Optional, for the types change: in that same folder run npm i -D typescript, add a tsconfig.json with {"compilerOptions":{"moduleResolution":"bundler","module":"preserve","noEmit":true}}, create check.ts containing import { createElasticTextArea } from '@cloudfour/patterns'; and pass it a string: createElasticTextArea('nope');. Run npx tsc. You should get a complaint that a string isn't an HTMLTextAreaElement — meaning the type declarations were found. On main you instead get "Could not find a declaration file for module".

`exports` was a bare string, and defining `exports` at all encapsulates
every other subpath. Of the 360 files in the tarball, exactly one was
reachable through Node resolution -- `package.json` included, which
tooling routinely reads from a dependency.
`files` and `exports` disagreed about what the public API is, and `files`
is the field expressing the intent. `exports` now mirrors its shape, so
what we ship and what a consumer can reach are the same set. The
patterns are written per extension rather than as a blanket `./src/*`,
which keeps stories and tests encapsulated for a consumer resolving
against a working tree rather than an installed tarball.
Also adds a `types` condition to the main entry: under node16/nodenext/
bundler resolution TypeScript reads types through `exports` and ignores
the top-level `types` field, so those consumers were getting `any`. That
was already broken before this change; it is fixed here because it is
the same field and the same root cause. Runtime resolution of the main
entry is unchanged.
The published file list is byte-for-byte identical -- only reachability
changes.
Fixes#2078
@netlify

netlifyBot commented Aug 24, 2026

Copy link
Copy Markdown

Deploy Preview for cloudfour-patterns ready!

NameLink
🔨 Latest commitf91cec3
🔍 Latest deploy loghttps://app.netlify.com/projects/cloudfour-patterns/deploys/6a8c8c62ee085100093a1b61
😎 Deploy Previewhttps://deploy-preview-2450--cloudfour-patterns.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@changeset-bot

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: f91cec3

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
NameType
@cloudfour/patternsPatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@spaceninja
spaceninja merged commit 152ed19 into mainAug 24, 2026
8 checks passed
@spaceninja
spaceninja deleted the fix-2078-export-published-subpaths branch August 24, 2026 18:31
@github-actionsgithub-actionsBot mentioned this pull request Aug 24, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unable to require/import files other than main export in Node

1 participant

@spaceninja