Skip to content

fix(cli): accept import.meta without global augmentation - #59

Merged
kjanat merged 3 commits into
masterfrom
fix-importmeta-cross-runtime
Jul 16, 2026
Merged

fix(cli): accept import.meta without global augmentation#59
kjanat merged 3 commits into
masterfrom
fix-importmeta-cross-runtime

Conversation

@kjanat

@kjanat kjanat commented Jul 16, 2026

Copy link
Copy Markdown
Owner

Summary

  • let .manifest({ from }) also accept import.meta directly and normalize its URL internally
  • add isMainModule(import.meta) as a typed compatibility entrypoint guard
  • preserve and document import.meta.url and import.meta.main as the conventional forms for Node, Bun, Deno, and npm projects with normal runtime typings
  • document the compatibility forms for cross-runtime and JSR consumers whose ambient ImportMeta interface omits url and main
  • record the public change in the changelog and lock both usage styles into the docs contracts

Root cause

The existing API remains valid. In normal Node, Bun, and Deno projects, consumers should continue to use:

cli.manifest({ from: import.meta.url });
if (import.meta.main) cli.run();

The failure occurs when a consumer's TypeScript configuration leaves the ambient ImportMeta interface empty. In the motivating importmapify case, deno check reads a tsconfig.json whose explicit compilerOptions.lib replaces Deno's runtime libs, so direct import.meta.url and import.meta.main access fails with TS2339.

Global ImportMeta augmentation fixes that type check, but JSR rejects global augmentation during slow-types validation. This leaves cross-runtime JSR packages with incompatible workarounds.

DreamCLI now provides an optional compatibility path at both affected boundaries:

import { cli as dreamcli, isMainModule } from 'dreamcli';

const cli = dreamcli('importmapify')
  .manifest({ from: import.meta, files: ['package.json', 'jsr.json'] });

if (isMainModule(import.meta)) cli.run();

Existing string paths, import.meta.url, file: URL strings, and URL instances remain supported. Ordinary Node, Bun, Deno, and npm consumers do not need to migrate.

Validation

  • bunx tsc --noEmit
  • deno task check
  • deno publish --dry-run with source checks and slow types
  • bun run lint
  • bun run format:check
  • bun run meta-descriptions:check
  • bun run test: 2,883 tests across 86 files
  • focused API and docs contracts: 71 tests
  • bun run docs:build
  • bun run bd: build, attw, and publint clean
  • examples/gh: typecheck and 21 tests using the conventional forms
  • examples/pwsh-demo: typecheck using the conventional forms
  • real importmapify compatibility adoption: deno check and jsr publish --dry-run both pass without global augmentation

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds isMainModule(meta) as a public compatibility helper for detecting runtime entry modules. Extends .manifest({ from }) and related normalisation to accept ImportMeta, extracting its URL when required. Updates example CLIs to use manifest anchoring, adds integration coverage, and documents the new API and compatibility forms. Documentation inventory, TypeDoc, contract tests, and the changelog are updated.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLIBuilder.manifest
  participant normalizeFromSetting
  participant ManifestDiscovery
  CLIBuilder.manifest->>normalizeFromSetting: Receive { from: import.meta }
  normalizeFromSetting->>normalizeFromSetting: Extract import.meta.url
  normalizeFromSetting-->>CLIBuilder.manifest: Return normalised source
  CLIBuilder.manifest->>ManifestDiscovery: Discover manifest
Loading

Possibly related PRs

  • kjanat/dreamcli#9: Related documentation inventory, TypeDoc, and contract-test updates for the same exported API changes.

Poem

Arrr, import.meta charts the course,
While manifests find their source,
isMainModule guards the gate,
Docs and tests now celebrate.
Smooth sailing through the typing sea!

🚥 Pre-merge checks | ✅ 9 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Semver Version Bump Validation ⚠️ Warning Source files changed, but package.json stayed 3.0.0-rc.11 on base and HEAD; this backward-compatible API work needed a MINOR bump. Update a version file (likely package.json) to the next SemVer minor version; the PR added backward-compatible functionality, so a bump is required.
Agents.Md Documentation Updated ⚠️ Warning HEAD changes CLI interface files, but no AGENTS.md was touched; src/core/cli/AGENTS.md exists, so the required guidance update is missing. Update the relevant AGENTS.md files for the affected areas (at least src/core/cli/AGENTS.md, and any docs/examples AGENTS if applicable) in the same PR.
✅ Passed checks (9 passed)
Check name Status Explanation
Title check ✅ Passed The title is specific and matches the import.meta compatibility fix.
Description check ✅ Passed The description clearly matches the API, docs, and validation changes in the pull request.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Release Metadata Sync ✅ Passed package.json and deno.json both read 3.0.0-rc.11; CHANGELOG Unreleased compares to v3.0.0-rc.11 and latest heading is [3.0.0-rc.11].
Runtime Support Sync ✅ Passed No Node/Bun/Deno support claims changed; the PR only touches import.meta docs/tests, and all runtime-support truth surfaces remain untouched.
No Generated Docs Artifacts ✅ Passed No files under docs/.vitepress/dist/ or docs/.vitepress/cache/ were touched in the PR commit.
Changelog Update ✅ Passed PASS — source files changed, and CHANGELOG.md has Unreleased Added/Changed entries covering isMainModule(import.meta) and .manifest({ from: import.meta }).

Comment @coderabbitai help to get the list of available commands.

@pkg-pr-new

pkg-pr-new Bot commented Jul 16, 2026

Copy link
Copy Markdown

Open in StackBlitz

bun add https://pkg.pr.new/@kjanat/dreamcli@59
npm i https://pkg.pr.new/@kjanat/dreamcli@59

commit: 2429837

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 16, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
dreamcli 2429837 Commit Preview URL

Branch Preview URL
Jul 16 2026, 01:29 AM

@kjanat kjanat self-assigned this Jul 16, 2026
@kjanat kjanat added kind: bug Broken behavior or regression area: cli CLI dispatch, planning, root UX, or plugins area: config Config discovery, package metadata, and loaders cr:review Allow CodeRabbit review labels Jul 16, 2026
@kjanat
kjanat marked this pull request as ready for review July 16, 2026 01:16

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CHANGELOG.md`:
- Around line 19-26: Update the changelog entry’s compatibility example to call
isMainModule(import.meta), preserving the documented public signature
isMainModule(meta: ImportMeta) and correcting the copy-paste-inaccurate
no-argument reference.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0049d6e5-69c6-485d-b7c1-4e9fc905ad04

📥 Commits

Reviewing files that changed from the base of the PR and between 0324e9c and 2a71d59.

📒 Files selected for processing (10)
  • CHANGELOG.md
  • docs/.vitepress/data/api-index.test.ts
  • docs/.vitepress/data/docs-contract.test.ts
  • docs/.vitepress/data/typedoc.test.ts
  • docs/reference/main.md
  • examples/gh/src/main.ts
  • examples/pwsh-demo/src/main.ts
  • src/core/cli/cli-package-json.test.ts
  • src/core/cli/index.ts
  • src/index.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
  • GitHub Check: Publish Preview
  • GitHub Check: Workers Builds: dreamcli
🧰 Additional context used
📓 Path-based instructions (11)
docs/.vitepress/data/**/*.test.ts

📄 CodeRabbit inference engine (docs/AGENTS.md)

Docs tests in .vitepress/data/*.test.ts verify API inventory, docs claims, example parsing, and symbol page generation

Files:

  • docs/.vitepress/data/api-index.test.ts
  • docs/.vitepress/data/typedoc.test.ts
  • docs/.vitepress/data/docs-contract.test.ts
docs/.vitepress/data/**

📄 CodeRabbit inference engine (AGENTS.md)

Treat docs/.vitepress/data/ as shared project data; scripts import it for generated source and docs artifacts, not just documentation

Files:

  • docs/.vitepress/data/api-index.test.ts
  • docs/.vitepress/data/typedoc.test.ts
  • docs/.vitepress/data/docs-contract.test.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use tabs for indentation; single quotes for strings; semicolons at end of statements; LF line endings

Files:

  • examples/gh/src/main.ts
  • src/index.ts
  • examples/pwsh-demo/src/main.ts
  • src/core/cli/cli-package-json.test.ts
  • src/core/cli/index.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use import type for type-only imports in TypeScript
Include .ts extensions in all relative imports
Enforce strict TypeScript everywhere with exactOptionalPropertyTypes enabled; use conditional spreads for optional properties
Use explicit named re-exports only; do not use export *

Files:

  • examples/gh/src/main.ts
  • src/index.ts
  • examples/pwsh-demo/src/main.ts
  • src/core/cli/cli-package-json.test.ts
  • src/core/cli/index.ts
examples/**/*.ts

📄 CodeRabbit inference engine (examples/AGENTS.md)

examples/**/*.ts: Examples should import public package exports only, never #internals/*
Keep examples pedagogical and runnable; they double as docs content
Do not let examples drift into pseudo-internal usage that real consumers cannot copy

Files:

  • examples/gh/src/main.ts
  • examples/pwsh-demo/src/main.ts
src/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Add @module JSDoc at the top of source files; mark non-public API with @internal JSDoc annotation

Files:

  • src/index.ts
  • src/core/cli/cli-package-json.test.ts
  • src/core/cli/index.ts
src/index.ts

📄 CodeRabbit inference engine (AGENTS.md)

Keep public API factory-first: use cli(), command(), flag.*(), createOutput(), createAdapter() naming patterns

Files:

  • src/index.ts
CHANGELOG.md

📄 CodeRabbit inference engine (Custom checks)

If a version bump is detected in CHANGELOG.md, the new section header MUST match the exact new version number in the format: '## [X.Y.Z] - YYYY-MM-DD'. If NO version bump is detected, changes MUST be added under the existing '## [Unreleased]' section with descriptive entries (e.g., Added, Changed, Fixed, Removed).

Files:

  • CHANGELOG.md
**/*.test.ts

📄 CodeRabbit inference engine (AGENTS.md)

**/*.test.ts: Co-locate tests as *.test.ts files alongside source; use describe() + it() with em dash in suite titles and // === / // --- section markers
Do not use lifecycle hooks, snapshots, or module mocks in tests
Include trailing newline in output assertions

Files:

  • src/core/cli/cli-package-json.test.ts
src/core/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Do not use process.* or runtime-specific APIs in src/core/ directory; route host I/O through RuntimeAdapter, WriteFn, or ReadFn

Files:

  • src/core/cli/cli-package-json.test.ts
  • src/core/cli/index.ts
src/core/{cli,completion,output,prompt,resolve}/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Do not import through barrels when it would create cycles; use direct-file imports in cli/, completion/, output/, prompt/, resolve/, and runtime/ directories

Files:

  • src/core/cli/cli-package-json.test.ts
  • src/core/cli/index.ts
🧠 Learnings (13)
📚 Learning: 2026-02-11T11:57:27.623Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 3
File: src/core/cli/cli-completion-e2e.test.ts:9-16
Timestamp: 2026-02-11T11:57:27.623Z
Learning: Enforce explicit .ts extensions in all relative imports for TypeScript source files (enabled by allowImportingTsExtensions and noEmit in tsconfig.json). This applies to both static and dynamic imports. For each TypeScript file, update relative import paths to end with .ts (e.g., './utils/helper' -> './utils/helper.ts'). Ensure tooling (linting/eslint rules or a codemod) flags missing extensions and provides a quick fix. This guideline should cover all TypeScript files in the repo, not just a single test or module.

Applied to files:

  • examples/gh/src/main.ts
  • src/index.ts
  • examples/pwsh-demo/src/main.ts
  • src/core/cli/cli-package-json.test.ts
  • src/core/cli/index.ts
📚 Learning: 2026-04-06T11:26:04.030Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 9
File: examples/middleware.ts:2-11
Timestamp: 2026-04-06T11:26:04.030Z
Learning: In the kjanat/dreamcli repository, require the `module` JSDoc tag only for library source files under `src/` (e.g., `src/**/*.ts`). Files outside `src/` such as runnable demo/example scripts under `examples/` are not considered source code for this rule and should not be required to include `module`.

Applied to files:

  • examples/gh/src/main.ts
  • src/index.ts
  • examples/pwsh-demo/src/main.ts
  • src/core/cli/cli-package-json.test.ts
  • src/core/cli/index.ts
📚 Learning: 2026-04-06T18:24:44.371Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 9
File: docs/reference/api.md:8-8
Timestamp: 2026-04-06T18:24:44.371Z
Learning: In the kjanat/dreamcli repo, the explicit type annotation `Readonly<Record<string, string>>` applied to `const` object literals is an intentional documentation/intent pattern. Do not flag it as redundant or unnecessary (e.g., for being inferable) when reviewing TypeScript/TSX files; treat this explicitness as acceptable by design.

Applied to files:

  • examples/gh/src/main.ts
  • src/index.ts
  • examples/pwsh-demo/src/main.ts
  • src/core/cli/cli-package-json.test.ts
  • src/core/cli/index.ts
📚 Learning: 2026-04-06T18:40:01.263Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 9
File: docs/.vitepress/vite-plugins/source-artifacts.ts:62-83
Timestamp: 2026-04-06T18:40:01.263Z
Learning: For this repository, Windows is explicitly not a supported/targeted platform. During code review, do not raise issues about Windows-specific path separators or normalization differences (e.g., use of `path.sep`, handling forward-slash vs backslash, or `normalize()`-related concerns). These checks should be treated as out-of-scope because the project is intended for Linux/macOS only.

Applied to files:

  • examples/gh/src/main.ts
  • src/index.ts
  • examples/pwsh-demo/src/main.ts
  • src/core/cli/cli-package-json.test.ts
  • src/core/cli/index.ts
📚 Learning: 2026-04-06T11:25:57.444Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 9
File: examples/spinner-progress.ts:2-12
Timestamp: 2026-04-06T11:25:57.444Z
Learning: In this repo, enforce that TypeScript source files under `src/` include the required `module` JSDoc tag (where the project’s lint/review rules expect it). Do not flag missing `module` tags in files under `examples/`, since those are documentation/example scripts (e.g., `examples/*.ts`).

Applied to files:

  • src/index.ts
  • src/core/cli/cli-package-json.test.ts
  • src/core/cli/index.ts
📚 Learning: 2026-04-06T11:26:11.173Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 9
File: examples/json-mode.ts:2-15
Timestamp: 2026-04-06T11:26:11.173Z
Learning: In this repository, `module` JSDoc tags are required for TypeScript source files under `src/` (e.g., `src/**/*.ts`). Runnable demo/example scripts under `examples/` are not part of this requirement and should not be flagged for missing `module`.

Applied to files:

  • src/index.ts
  • src/core/cli/cli-package-json.test.ts
  • src/core/cli/index.ts
📚 Learning: 2026-04-06T11:28:55.224Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 9
File: docs/.vitepress/theme/index.ts:1-16
Timestamp: 2026-04-06T11:28:55.224Z
Learning: In the kjanat/dreamcli repo, enforce the `module` JSDoc tag requirement only for TypeScript source files under `src/` (i.e., `src/**/*.ts`). Do not require `module` for files under `docs/`, including anything in `docs/.vitepress/**`, since those are part of the VitePress docs pipeline.

Applied to files:

  • src/index.ts
  • src/core/cli/cli-package-json.test.ts
  • src/core/cli/index.ts
📚 Learning: 2026-02-10T16:25:08.867Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 1
File: AGENTS.md:12-12
Timestamp: 2026-02-10T16:25:08.867Z
Learning: In repository kjanat/dreamcli, prefer using the filename syntax (e.g., GOALS.md) when referencing files in Markdown documentation, and treat references that do not follow this style as non-issues. This pattern applies to all Markdown files across the project.

Applied to files:

  • CHANGELOG.md
  • docs/reference/main.md
📚 Learning: 2026-02-12T15:52:24.166Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 4
File: src/core/resolve/resolve-arg-env.test.ts:1-7
Timestamp: 2026-02-12T15:52:24.166Z
Learning: In test files, do not require the module JSDoc tag at the top. This rule applies to all test files, while non-test source files should still require the module tag. Use the pattern **/*.test.{ts,tsx} to cover all test TypeScript test files (adjust if your project uses only .ts tests).

Applied to files:

  • src/core/cli/cli-package-json.test.ts
📚 Learning: 2026-04-02T00:14:17.279Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 7
File: src/core/cli/cli.test.ts:14-14
Timestamp: 2026-04-02T00:14:17.279Z
Learning: In kjanat/dreamcli test files (src/**/*.test.ts), do not flag differences in section separator style between `// ---` and `// ===`. This style is intentionally used by the author for all section levels (including top-level sections) in tests, so separator casing/choice should not be treated as a guideline violation in code review.

Applied to files:

  • src/core/cli/cli-package-json.test.ts
📚 Learning: 2026-06-20T15:01:13.926Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 30
File: src/core/cli/cli-default.test.ts:509-531
Timestamp: 2026-06-20T15:01:13.926Z
Learning: In kjanat/dreamcli CLI tests, the “trailing newline in output assertions” rule should be enforced only for `expect(captured.stdout).toEqual([...])` assertions over the raw `stdout` array (where each `out.log()` entry should end with `\n`). Do not apply this trailing-newline requirement to substring-style assertions such as `result.stdout.join('').toContain('status:ok')`; do not flag `toContain` checks for missing trailing `\n`.

Applied to files:

  • src/core/cli/cli-package-json.test.ts
📚 Learning: 2026-06-23T16:38:50.547Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 37
File: src/core/output/output.test.ts:76-76
Timestamp: 2026-06-23T16:38:50.547Z
Learning: In this repository’s test files (`*.test.ts`), do not suggest or require em dashes (—) in `describe()` suite titles. When reviewing, treat the suite-title punctuation as a repo-specific convention: do not flag missing/absent em dashes or recommend adding them to `describe(...)` block names.

Applied to files:

  • src/core/cli/cli-package-json.test.ts
📚 Learning: 2026-04-06T20:07:00.266Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 9
File: docs/guide/runtime.md:61-61
Timestamp: 2026-04-06T20:07:00.266Z
Learning: In kjanat/dreamcli documentation, for Twoslash `ts twoslash` code blocks, use the `// ---cut---` directive to hide setup/fixture imports from the rendered output while keeping the symbols available for TypeScript type checking. Ensure fixture/setup imports (e.g., `import { regionCmd } from './docs/.vitepress/twoslash/testing-fixtures.ts'`) are placed before `// ---cut---` so they are excluded from the published docs page but still participate in type checking.

Applied to files:

  • docs/reference/main.md
🔍 Remote MCP GitHub Grep

Useful review context from public code:

  • Direct import.meta.main checks are common in JS/TS entrypoints and tests, including Bun, Node, p5.js, and Harbor code.
  • The helper-style guard isMainModule(import.meta.url) is also common in public repos such as langgenius/dify, QwenLM/qwen-code, NG-ZORRO/ng-zorro-antd, and angular/angularfire.
  • from: import.meta.url is a common pattern for module-resolution APIs; Nuxt uses it repeatedly with resolveModulePath(..., { from: import.meta.url }) and related helpers.
  • I did not find public examples of isMainModule(import.meta) or .manifest({ from: import.meta }) in the searches I ran.
🔇 Additional comments (9)
src/core/cli/index.ts (1)

801-803: LGTM!

Also applies to: 1454-1460, 1552-1569, 1578-1578, 1710-1730, 1755-1755

src/index.ts (1)

42-42: LGTM!

src/core/cli/cli-package-json.test.ts (1)

12-12: LGTM!

Also applies to: 694-705, 707-715

examples/gh/src/main.ts (1)

30-40: LGTM!

examples/pwsh-demo/src/main.ts (1)

130-130: LGTM!

docs/reference/main.md (1)

10-10: LGTM!

Also applies to: 128-130, 144-149, 165-199, 541-543

docs/.vitepress/data/docs-contract.test.ts (1)

67-75: LGTM!

Also applies to: 84-87

docs/.vitepress/data/api-index.test.ts (1)

36-40: LGTM!

docs/.vitepress/data/typedoc.test.ts (1)

25-29: LGTM!

Comment thread CHANGELOG.md Outdated
@kjanat kjanat removed the cr:review Allow CodeRabbit review label Jul 16, 2026
@kjanat
kjanat merged commit ab183e0 into master Jul 16, 2026
19 checks passed
@kjanat
kjanat deleted the fix-importmeta-cross-runtime branch July 16, 2026 01:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: cli CLI dispatch, planning, root UX, or plugins area: config Config discovery, package metadata, and loaders kind: bug Broken behavior or regression

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant