Skip to content

feat: expose the extractor as a library - #23

Merged
korsvanloon merged 1 commit into
mainfrom
feat/importable-api
Aug 11, 2026
Merged

feat: expose the extractor as a library#23
korsvanloon merged 1 commit into
mainfrom
feat/importable-api

Conversation

@korsvanloon

Copy link
Copy Markdown
Contributor

The package ships dist/index.js today — tsdown already builds src/index.ts as an entry — but declares only a bin, so nothing can import it. This makes the extractor usable as a library.

Motivation: Evolve's storefront needs to combine extracted labels from a project's own source with the default messages its installed feature packages ship, then decide the output itself. That needs the extraction step without the read-merge-write around it.

Changes

exports map. Points at the already-built dist/index.js / dist/index.d.ts.

buildLabels({ input, source, fallback, onFile }) returns the label tree and writes nothing:

import { buildLabels } from "@labdigital/intl-extractor";

const labels = await buildLabels({
  input: "./src",
  source: existingLabels,
  fallback: (path) => `[${path.at(-1)}]`,
});

processFiles is now the read-merge-write wrapper around it, unchanged in behaviour.

A fallback option for a label with no entry in the source. It receives the full key path (["Cart", "nested", "deep"]) and defaults to the last segment — exactly what was hardcoded before, so existing output is unchanged. We want [label] rather than label, because a key like free has free as a plausible English translation and nothing could then tell a finished string from an untouched one.

onFile so the library stays silent and the CLI keeps its per-file logging.

Two fixes, easy to drop if you'd rather they were separate

  • processFiles did not await its writeFile, so the process could exit before the write flushed.
  • Its if (!sourceFile) "no existing source file found" branch was unreachable — readFile throws on a missing file, so the CLI errored instead of building from scratch. Now it reads through a try, and an empty file is treated as no labels rather than a JSON parse error.

Testing

Existing snapshot tests pass unchanged, which is the evidence the refactor preserved behaviour. Added coverage for the default fallback, a custom fallback and the paths it receives, source values winning over the fallback, and buildLabels returning without writing.

18 tests pass; pnpm check is clean.

Declare an exports map so the package can be imported, add buildLabels()
which returns the tree without writing, and make the placeholder for an
unknown label configurable via a fallback receiving the full key path.

Also await the write in processFiles, and make its 'no existing source
file' branch reachable — readFile threw before it could be hit.
@korsvanloon
korsvanloon merged commit 563b04b into main Aug 11, 2026
4 checks passed
Sign up for free to 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.

1 participant