@palamedes/core-node
v2.2.0
Published
Thin Node.js wrapper around the Palamedes Rust core
Maintainers
Readme
@palamedes/core-node
The Node.js wrapper around Palamedes' native core.
Use this package when you are building tooling on top of Palamedes and want
direct access to the careful parts of the system: PO/FCL catalog updates,
audits, metadata validation, .po parsing, MDX analysis, extraction, and macro
transformation.
The public catalog model is source-string-first: message + context is the
semantic identity, while compact lookup keys remain internal compile/runtime
details.
When To Use This Package
Reach for @palamedes/core-node when you are:
- building custom tooling around Palamedes
- integrating the native transform or extractor outside the first-party plugins
- working on Palamedes internals
If you are integrating Palamedes into an app, you usually want one of these instead:
Installation
pnpm add @palamedes/core-nodeSee Platform support before installing the native binding. It is the authoritative list of published targets, Linux libc variants, unsupported Node processes, and recovery steps.
Example
import {
combineCatalogFiles,
getNativeInfo,
mergeCatalogFilesThreeWay,
parsePo,
updateCatalogFile,
} from "@palamedes/core-node";
const info = getNativeInfo();
const po = parsePo(`
msgid ""
msgstr ""
"Language: en\\n"
`);
updateCatalogFile({
targetPath: "src/locales/en.po",
locale: "en",
sourceLocale: "en",
clean: false,
po: { lineBreaks: "off" },
messages: [{ message: "Hello {name}", extractedComments: [], origins: [] }],
});
combineCatalogFiles({
inputPaths: ["src/locales/de.po", "incoming/de.po"],
outputPath: "src/locales/de.po",
format: "po",
sourceLocale: "en",
});
mergeCatalogFilesThreeWay({
ancestorPath: "git/base/de.po",
oursPath: "src/locales/de.po",
theirsPath: "incoming/de.po",
outputPath: "src/locales/de.po",
format: "po",
sourceLocale: "en",
conflictStrategy: "useFirst",
});
combineCatalogFiles({
inputPaths: ["src/locales/de.fcl", "incoming/de.fcl"],
outputPath: "src/locales/de.fcl",
format: "fcl",
sourceLocale: "en",
});
console.log(info.palamedesVersion);
console.log(po.headers.Language);checkTranslationTargets({ targets: patches, checks: { boundaryWhitespace: true,
metadataLeakage: true } }) provides read-only, opt-in review warnings before
patch writeback. The same native checks run during auditCatalogs through
checks.targetText. Results group candidate identity, checked text, and UTF-8 byte spans;
see target-text review
for source-aware exemptions and span semantics.
Available APIs
getNativeInfo()parsePo(source)updateCatalogFile(request)updateCatalogFileAsync(request, taskOptions?)parseCatalog(request)listTranslationCandidates(request)applyTranslationPatches(request)applyTranslationPatchesAsync(request, taskOptions?)isTranslationPatchWriteError(error)auditCatalogs(config, options?)checkTranslationTargets(request)inspectCatalogMachineTranslations(config, options?)inspectCatalogMachineTranslationsAsync(config, options?, taskOptions?: AsyncTaskOptions)deriveMessageMetadata(message, context?)normalizeMessageMetadata(input)validateMessageMetadata(input)combineCatalogs(request)combineCatalogFiles(request)mergeCatalogsThreeWay(request)mergeCatalogFilesThreeWay(request)compileCatalogArtifact(config, resourcePath)compileCatalogArtifactAsync(config, resourcePath, taskOptions?)compileCatalogArtifactSelected(config, resourcePath, compiledIds)compileCatalogArtifactSelectedAsync(config, resourcePath, compiledIds, taskOptions?)compileCatalogModule(config, resourcePath, options)compileCatalogModuleAsync(config, resourcePath, options, taskOptions?)renderCatalogModule(messages)extractMessagesNative(source, filename, mdxOptions?)analyzeSourceNative(source, filename, options?)analyzeMdxNative(source, filename, options?)extractCatalogMessagesFromFiles(request)extractCatalogMessagesFromFilesAsync(request, taskOptions?)transformMacrosNative(source, filename, options?)
analyzeMdxNative() and transformMacrosNative() omit authored source-message
metadata by default. Pass includeSourceMetadata: true when generated runtime
code must retain it for diagnostics. The v1 keepSourceFallbacks name throws a
migration error, as does the removed inverse option stripMessageField.
assertNoRemovedPalamedesOptions(options, names) throws the shared v2
migration error when an options object still sets one of the named removed
options. The first-party adapters use it so every surface reports the same
message.
inspectCatalogMachineTranslations() and its Async variant inspect stored
PO/FCL machine claims without rewriting files. They expose Ferrocat
current/stale/absent/invalid counters and identity/status details.
Integrity does not verify authorship or translation quality; malformed metadata
may be rejected or discarded before review. See the
inspection API.
Catalog operations use Ferrocat for parsing, updates, audits, ICU authoring diagnostics, metadata validation, and deterministic combine workflows. That keeps custom tooling close to the same semantics used by the official CLI and framework plugins.
updateCatalogFile() accepts an optional PO output control through po:
lineBreaks ("auto" or "off"). Catalog order is not configurable —
Ferrocat sorts PO and FCL catalogs by message and then context using the CLDR
root order that Intl.Collator("en-US") produces. PO options are rejected for
FCL updates.
The wrapper exposes lowercase public format values ("po" and "fcl") while
mapping to the native Ferrocat-backed API internally.
analyzeMdxNative uses the same FerroMark-backed semantic workflow as native
catalog extraction. It returns extracted messages, structured source-ranged
diagnostics, React or Solid JSX, compiled message IDs, and a source map.
analyzeSourceNative is the shared JS, TS, JSX, TSX, and MDX authoring entry
point. It returns extracted messages plus deterministic diagnostics with a
stable code, lowercase severity, filename, exact UTF-8 byte range, one-based
line and Unicode-scalar column, actionable help, and an optional related range.
The recommended placeholderOnly rule defaults to "warning"; the narrower
emptyComponentOnly rule defaults to "off"; and the readability-oriented
preferTransInJsx suggestion defaults to "info". All three accept "off",
"info", "warning", or "error" through options.rules. The JSX rule never
treats t as invalid and the initial diagnostic does not auto-fix imports or
unsafe attribute, restricted-element, or non-render rewrites.
compileCatalogModule(config, resourcePath, options) is the direct module
rendering API used by the first-party Vite, Next, and Remix .po loaders. Pass
the artifact config, the resource path, and options such as locale, pseudoLocale,
and failOnMissing. Invalid or unsupported ICU always fails in development and
production; the removed failOnCompileError option throws a migration error. The generated module contains one map
of constant strings and executable message functions lowered from Ferrocat's
AST, so valid dynamic messages need neither ICU parsing nor AST interpretation
in the browser.
Use the Async variants for file reads, catalog writes, and catalog
compilation on a server or build-tool event loop. They preserve the synchronous
result and error shapes, but schedule one owned operation on Node's shared
libuv worker pool. The first-party Vite and Next loaders await these variants;
the Remix synchronous module hook keeps the compatible synchronous API.
The six async APIs accept an optional { signal } task-options object. Aborting
the signal rejects work that is still queued for a libuv worker with an
AbortError; native work that has already started finishes normally. When
custom tooling starts many independent operations, still limit its own
concurrency instead of creating an unbounded Promise.all fan-out. The libuv
pool is shared with other Node filesystem and native work;
UV_THREADPOOL_SIZE remains Node's process-level control.
Concurrent compileCatalogArtifactSelectedAsync() calls for the same catalog
and configuration are coordinated before they enter the worker pool. The first
call performs an initial native build; callers that arrived while it was
running wait in JavaScript and only enter native code after the cache is warm.
If that initial build fails, waiting callers retry one at a time so cancellation
or a selected-ID compilation error from one caller does not reject another.
Independent catalogs can still compile concurrently.
This build coordination is process-wide. The CommonJS and ESM entry points,
and multiple copies of the package, share one coordinator through a
globalThis holder. The synchronous compileCatalogArtifactSelected() API
uses ready native cache entries, but if a matching async build is in flight it
compiles its request independently. This can duplicate cold-build work, but it
never waits on an in-flight worker-pool build or parks the Node.js event loop.
Event-loop-sensitive integrations should still use the async API for
concurrent builds.
Async catalog mutations targeting the same resolved file are also serialized
process-wide, including calls across the CommonJS and ESM entry points and
across updateCatalogFileAsync and applyTranslationPatchesAsync. Mutations
of different files can still run concurrently. Separate Node.js processes and
concurrent synchronous mutations must coordinate access themselves.
renderCatalogModule(messages) exposes that same canonical native generator
for compatibility helpers and custom integrations that already have a compiled
message map.
Related Packages
palamedes is part of the Ferramenta family — A family of Rust tools.
Siblings: ferroni — Oniguruma-compatible regex engine · ferriki — Shiki-compatible syntax highlighting · ferromark — Markdown to HTML with a secure default and every GFM extension included. · ferrolex — Spell checking for text and code · ferrocat — Translation catalog engine · ferrovia — SVGO-compatible SVG optimizer · ferralk — Glob matching and parallel filesystem walking · ferrugo — PDF previews for untrusted files.
License
MIT OR Apache-2.0 © 2026 Sebastian Software
