Skip to content

ObjectLogger file destination silently no-ops in ESM builds #3110

Description

@os-zhuang

Symptom

createLogger({ file: '/path/to.log' }) never creates or writes the log file when @objectstack/core/logger is consumed from an ESM entrypoint (which is what os serve / os dev run — the workspace is type: module). The same config works from a CJS consumer.

Repro (against built dist, Node v25)

// probe.mjsimport{createLogger}from'@objectstack/core/logger';importfsfrom'node:fs';constl=createLogger({format: 'pretty',file: '/tmp/probe.log'});l.info('esm file probe');awaitl.destroy();console.log('file exists:',fs.existsSync('/tmp/probe.log'));// → false

Root cause

openFileStream() in packages/core/src/logger.ts does a lazy require('fs') ("Lazy require to avoid bundling issues" — the module is deliberately browser-safe for @objectstack/client). tsup/esbuild compiles that to the __require shim in the ESM output (dist/logger.js), which throwsDynamic require of "fs" is not supported at runtime; the surrounding try { … } catch { /* ignore — file logging is optional */ } swallows it, so file logging silently never activates. The CJS output (dist/logger.cjs) is unaffected because real require exists there.

Suggested fix

Keep the module browser-safe but stop relying on bundled require:

  • process.getBuiltinModule?.('node:fs') (Node ≥22.3, sync, already behind the existing typeof process !== 'undefined' guard and try/catch for older runtimes), or
  • createRequire(import.meta.url) via a tsup shims-style banner, or an async import('node:fs').

Also consider logging a one-line warning instead of the bare catch {} when a file destination was explicitly configured but could not be opened — the current silence is exactly how this went unnoticed.

Found while fixing NO_COLOR/TTY handling in the same file (the fix PR keeps the file path plain-text but does not touch this).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions