Skip to content

chore: migrate package to ESM (chalk 5 / plist 5 / citty 0.2)#30

Merged
riglar merged 3 commits into
devfrom
chore/esm-migration
Jun 22, 2026
Merged

chore: migrate package to ESM (chalk 5 / plist 5 / citty 0.2)#30
riglar merged 3 commits into
devfrom
chore/esm-migration

Conversation

@riglar

@riglar riglar commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

What

Converts the CLI from CommonJS to ESM, which unblocks the three ESM-only major deps that were held back in #28.

  • package.json: "type": "module"
  • tsconfig.json: module/moduleResolutionnodenext, esModuleInterop: true
  • Explicit .js extensions on all relative import/export/dynamic-import specifiers (required under NodeNext), preserving file-over-directory resolution — ./types./types.js (the file src/types.ts), not the src/types/index.ts barrel
  • CJS interop rewrites:
    • chalk → default import (chalk 5 is ESM)
    • node-stream-zip → default import at all three sites
    • getCliVersion() reads package.json via JSON.parse(readFileSync(new URL('../../package.json', import.meta.url))) instead of require() (keeps it out of the tsc rootDir)
  • Bumped chalk ^5.6.2, plist ^5.0.0, citty ^0.2.2; dropped @types/plist (plist 5 bundles its own types)
  • Renamed eslint.config.jseslint.config.cjs (flat config stays CJS)

This branch also merges in origin/dev (PR #29, unified CLI output).

Gotcha worth flagging

node-stream-zip's module.exports is a single function with .async hanging off it. A namespace import (import * as StreamZip) yields { default, 'module.exports' } with no .async, so new StreamZip.async(...) throws is not a constructor at runtime. Must be a default import. Typecheck does not catch this — only the test suite did. Other bare-package namespace imports (js-yaml, yazl, tar, tus-js-client, @clack/prompts, bplist-parser, plist) are fine: cjs-module-lexer detects their named exports.

Validation

build ✓ · typecheck (src + test) ✓ · lint 0 errors ✓ · 147 tests passing ✓ · CLI --version/--help + MCP tools/list smoke ✓

🤖 Generated with Claude Code

riglar and others added 2 commits June 22, 2026 15:01
Convert the CLI from CommonJS to ESM ("type": "module", tsconfig
module/moduleResolution nodenext), which unblocks the three ESM-only
deps held back in #28: chalk 5, plist 5, citty 0.2.

- Add explicit .js extensions to all relative import/export/dynamic-import
  specifiers (required under NodeNext), preserving file-over-directory
  resolution (./types -> ./types.js, the file, not the barrel).
- Rewrite CJS interop sites: chalk/StreamZip default imports; read
  package.json version via fs + import.meta.url instead of require().
- node-stream-zip is a single-function CJS export, so its three import
  sites must use a default import — a namespace import yields no .async.
- Drop @types/plist (plist 5 bundles its own types).
- Rename eslint.config.js -> eslint.config.cjs (flat config stays CJS).

Validated: build, typecheck (src+test), lint (0 errors), 147 tests,
and CLI/MCP smoke runs all green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
# Conflicts:
#	src/commands/cloud.ts
#	src/commands/list.ts
#	src/commands/live.ts
#	src/commands/login.ts
#	src/commands/logout.ts
#	src/commands/status.ts
#	src/commands/switch-org.ts
#	src/commands/upgrade.ts
#	src/commands/upload.ts
#	src/commands/whoami.ts
#	src/services/results-polling.service.ts
@claude

claude Bot commented Jun 22, 2026

Copy link
Copy Markdown

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

CI (Node 22) failed with "node-apk does not provide an export named
'Apk'". Both node-apk and bplist-parser are CJS with no exports map, so
named imports rely on cjs-module-lexer's named-export detection — which
is Node-version-dependent (Node 25 detects them, Node 22 does not).

Switch to default-import + destructure, which relies only on the
guaranteed `default = module.exports` interop and works on every Node
version. plist stays a named import (it's genuine ESM).

Verified under Node 22: unit suite (incl. APK metadata extraction) loads
and passes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@riglar riglar merged commit 72402ae into dev Jun 22, 2026
6 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