@palamedes/core-node
v1.25.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);Available APIs
getNativeInfo()parsePo(source)updateCatalogFile(request)updateCatalogFileAsync(request, taskOptions?)parseCatalog(request)listTranslationCandidates(request)applyTranslationPatches(request)applyTranslationPatchesAsync(request, taskOptions?)isTranslationPatchWriteError(error)auditCatalogs(config, options?)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
fallbacks by default. Pass keepSourceFallbacks: true when generated runtime
code must retain them. stripMessageField remains a deprecated inverse option
for macro-transform compatibility.
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,
failOnMissing, and failOnCompileError. 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 applies within one loaded JavaScript module instance.
Loading both the CommonJS and ESM entry points, or loading multiple copies of
the package, creates independent coordinators. The synchronous
compileCatalogArtifactSelected() API also bypasses the JavaScript coordinator.
If it races an in-flight native build for the same cache key, it can wait for
that build and block the Node.js event loop. Event-loop-sensitive integrations
should use the async API and avoid mixing package instances for concurrent
same-key builds.
Async catalog mutations targeting the same resolved file are also serialized
within one loaded JavaScript module instance, including calls across
updateCatalogFileAsync and applyTranslationPatchesAsync. Mutations of
different files can still run concurrently. Loading both package formats or
multiple package copies creates independent mutation queues. Separate module
instances, 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 — Rust-native developer tools that keep the APIs the ecosystem already knows.
Siblings: ferroni · ferriki · ferromark · ferrolex · ferrocat · ferrovia · ferralk · ferrugo.
License
MIT OR Apache-2.0 © 2026 Sebastian Software
