new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Bun · Runtime · all subjects

bun apis/module resolution

31 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

import.meta module information

Bun supports import.meta for accessing module metadata.

Module resolution: Bun.resolveSync

Bun provides Bun.resolveSync() for synchronously resolving module paths.

Extensions are optional but supported in imports

When importing a module, you can omit the file extension. Bun will check for matching files with various extensions. If you include an extension, Bun checks for that exact file first, and if no exact match exists, it falls back to trying the extension list appended to the full path (so ./hello.world can resolve to ./hello.world.ts).

TypeScript compatibility for .js imports matching .ts files

If you import from "*.js" or "*.jsx", Bun checks for a matching *.ts or *.tsx file. Outside node_modules, importing from "*.mjs" also matches *.mts. This follows TypeScript compiler's file extension substitution, allowing source files to reference each other by their compiled output paths. Unlike TypeScript, Bun doesn't rewrite .cjs to .cts.

Bun supports both ES modules and CommonJS modules

Bun has native support for CommonJS (require()/module.exports) and ES modules (import/export syntax). ES modules are the recommended format for new projects, but CommonJS is still supported. In Bun's JavaScript runtime, both ES modules and CommonJS modules can use require().

require() behavior with different module types

If the target module is an ES module, require() returns the module namespace object (equivalent to import *). If the target module is a CommonJS module, require() returns the module.exports object as in Node.js.

require() works with any file type

You can require() any file or package, including .ts, .tsx, .mjs, and .cjs files. Extensions are optional.

import works with any file type

You can import any file or package, including .cjs files. Extensions are optional.

Using import and require() together

In Bun, you can use both import and require() in the same file. They both work all the time, so you can mix import statements and require() calls in the same source file.

Top-level await limitation with require()

You cannot require() a file that uses top-level await, since the require() function is inherently synchronous. Use import or dynamic import() instead if your file uses top-level await.

Bun implements Node.js module resolution algorithm

Bun implements the Node.js module resolution algorithm, so you can import packages from node_modules with a bare specifier like import { stuff } from 'foo'. Bun scans up the file system for a node_modules directory containing the package.

NODE_PATH environment variable support

Bun supports NODE_PATH for additional module resolution directories. You can set it on the command line: NODE_PATH=./packages bun run src/index.js. Multiple paths use the platform's delimiter (: on Unix, ; on Windows): NODE_PATH=./packages:./lib bun run src/index.js (Unix/macOS) or NODE_PATH=./packages;./lib bun run src/index.js (Windows).

package.json exports field resolution order

When resolving a package, Bun first reads the exports field in package.json and checks conditions in this order: bun, node-addons (unless --no-addons was passed), node, require (if the importer uses require()), import (if the importer uses import), and default. Whichever condition occurs first determines the package's entrypoint.

Subpath exports and conditional imports

Bun respects subpath exports and imports in package.json. Specifying any subpath in the exports map prevents other subpaths from being importable; you can only import files that are explicitly exported. Subpath imports and conditional imports work together.

Special bun export condition for TypeScript libraries

Bun supports the special 'bun' export condition in package.json. If your library is written in TypeScript, you can publish un-transpiled TypeScript files to npm directly by specifying your package's *.ts entrypoint in the 'bun' condition. Bun will import and execute your TypeScript source files directly.

--conditions flag for package export resolution

The --conditions flag specifies the conditions to use when resolving packages from package.json exports. Both bun build and Bun's runtime support this flag: bun build --conditions='react-server' --target=bun ./app/foo/route.js or bun --conditions='react-server' ./app/foo/route.js. You can also use it programmatically with Bun.build() by passing conditions: ['react-server'] in the options.

Path re-mapping via tsconfig.json compilerOptions.paths

Bun supports import path re-mapping through TypeScript's compilerOptions.paths in tsconfig.json. You can map specifiers to files: {'config': ['./config.ts']} or use wildcard matching: {'components/*': ['components/*']}. If you aren't a TypeScript user, use jsconfig.json in your project root for the same behavior.

Node.js-style subpath imports in package.json

Bun supports Node.js-style subpath imports in package.json where mapped paths must start with #. TypeScript and editors resolve these too. You can use both compilerOptions.paths in tsconfig.json and package.json imports together. Example: {'#config': './config.ts'} or {'#components/*': './components/*'}.

import.meta properties in Bun

Bun implements the following import.meta properties: dir (absolute path to directory), dirname (alias to dir), env (alias to process.env), file (filename), path (absolute path to file), filename (alias to path), main (true if directly executed by bun run), resolve (resolve module specifier to url), and url (file:// url to current file).

import.meta.dir and import.meta.dirname

import.meta.dir returns the absolute path to the directory containing the current file, e.g. /path/to/project. This is equivalent to __dirname in CommonJS modules. import.meta.dirname is an alias to import.meta.dir for Node.js compatibility.

import.meta.file

import.meta.file returns the name of the current file, e.g. index.tsx.

import.meta.path and import.meta.filename

import.meta.path returns the absolute path to the current file, e.g. /path/to/project/index.ts. This is equivalent to __filename in CommonJS modules. import.meta.filename is an alias to import.meta.path for Node.js compatibility.

import.meta.main indicates entrypoint status

import.meta.main is true if the current file is the entrypoint to the current bun process (executed directly by bun run), and false if it's imported from another file.

import.meta.resolve resolves module specifiers

import.meta.resolve(specifier) resolves a module specifier like 'zod' or './file.tsx' to a file:// url. It is equivalent to import.meta.resolve in browsers. Example: import.meta.resolve('zod') returns 'file:///path/to/project/node_modules/zod/index.ts'.

import.meta.url file URL format

import.meta.url returns a string file:// url to the current file, e.g. file:///path/to/project/index.ts. It is equivalent to import.meta.url in browsers.

import.meta.env alias to process.env

import.meta.env is an alias to process.env, providing access to environment variables.

CommonJS module wrapping mechanism in Bun

Bun's JavaScript transpiler detects usages of module.exports and treats the file as CommonJS. The module loader wraps the transpiled module in a function: (function (module, exports, require) { // transpiled module })(module, exports, require). These variables behave like those in Node.js. An internal Map stores the exports object to handle cyclical require calls before the module is fully loaded.

CommonJS module to Synthetic Module Record conversion

Once a CommonJS module is evaluated, Bun creates a Synthetic Module Record with the default ES Module export set to module.exports and keys of the module.exports object re-exported as named exports (if module.exports is an object).

Fallback to legacy entrypoint fields

If exports is not defined in package.json, Bun falls back to legacy top-level entrypoint fields. At runtime Bun prefers main (or an implicit index.* file) when present, and uses module otherwise.

Module resolution extension check order for relative imports

For local ESM relative imports without an extension, Bun checks for files in this order: .tsx, .jsx, .mts, .ts, .mjs, .js, .cts, .cjs, .json, then the same list for index files in a subdirectory. The order varies by context: require() tries CommonJS extensions (.cts, .cjs) before ESM ones (.mts, .mjs), and imports inside node_modules try JavaScript extensions before TypeScript ones.

Bun.resolveSync() resolves module using Bun's algorithm

Bun.resolveSync(path: string, root: string): string resolves a file path or module specifier using Bun's internal module resolution algorithm. The first argument is the path to resolve, the second argument is the root directory. Throws an Error if no match is found. To resolve relative to current working directory pass process.cwd() or ".". To resolve relative to current file directory pass import.meta.dir.

Give your agent this brain