Skip to content
Closed
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
581d72a
implement `import.meta.glob`
RiskyMH Jul 29, 2025
5812103
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 29, 2025
2f9ff3f
docs
RiskyMH Jul 29, 2025
6a60b82
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 29, 2025
e0bd157
fix ci
RiskyMH Jul 29, 2025
5ddea5c
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 29, 2025
61f2d9e
fix --splitting
RiskyMH Jul 29, 2025
6894f8a
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 29, 2025
892a20d
maybe fix things
RiskyMH Jul 30, 2025
65d491e
Merge branch 'main' into riskymh/import.meta.glob
RiskyMH Jul 30, 2025
8150288
Update import-meta-glob.test.ts
RiskyMH Jul 30, 2025
6cd626a
Update no-validate-exceptions.txt
RiskyMH Jul 30, 2025
5083f26
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 30, 2025
18bf62d
support `await import('./script.js', { with: { type: 'text' } });`
RiskyMH Jul 30, 2025
e86f0c6
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 30, 2025
642fb9d
fix: strip import options when bundling with applied loader
RiskyMH Jul 30, 2025
ddb56e8
Merge branch 'main' into riskymh/import.meta.glob
RiskyMH Jul 30, 2025
ce1756a
Update js_printer.zig
RiskyMH Jul 30, 2025
ccaef4b
Merge branch 'main' of https://github.com/oven-sh/bun into riskymh/im…
RiskyMH Aug 2, 2025
95bd24e
Merge branch 'main' into riskymh/import.meta.glob
RiskyMH Aug 6, 2025
ed3f2d6
updates
RiskyMH Aug 7, 2025
fe18872
Merge branch 'main' into riskymh/import.meta.glob
RiskyMH Aug 7, 2025
8ba8e96
Merge branch 'main' into riskymh/import.meta.glob
Jarred-Sumner Aug 14, 2025
f530a16
Merge origin/main into riskymh/import.meta.glob
RiskyMH Sep 13, 2025
0e5c48b
fix some things
RiskyMH Sep 13, 2025
b69193c
base option too
RiskyMH Sep 13, 2025
72cb84c
semi better
RiskyMH Sep 13, 2025
7236daa
upd types
RiskyMH Sep 14, 2025
c431a72
.
RiskyMH Sep 14, 2025
490c551
Merge branch 'main' into riskymh/import.meta.glob
RiskyMH Oct 10, 2025
4c7e8f0
fix asan ci
RiskyMH Oct 14, 2025
533011d
Merge branch 'main' into riskymh/import.meta.glob
RiskyMH Oct 14, 2025
69d9f83
update
RiskyMH Oct 15, 2025
8a6710f
Merge remote-tracking branch 'origin/main' into riskymh/import.meta.glob
RiskyMH Oct 15, 2025
bd38223
[autofix.ci] apply automated fixes
autofix-ci[bot] Oct 15, 2025
abcfcd5
negative patterns
RiskyMH Oct 15, 2025
caa0dda
Merge remote-tracking branch 'origin/main' into riskymh/import.meta.glob
RiskyMH Dec 1, 2025
bb81ebd
add import.meta.glob to new docs location
RiskyMH Dec 1, 2025
a6ecf14
fix: use ArrayListUnmanaged for Zig 0.15 compatibility
RiskyMH Dec 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions docs/api/import-meta.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import.meta.main; // `true` if this file is directly executed by `bun run`
// `false` otherwise

import.meta.resolve("zod"); // => "file:///path/to/project/node_modules/zod/index.js"

import.meta.glob("./src/*.ts"); // => { "./src/a.ts": () => import("./src/a.ts"), ... }
```

{% table %}
Expand Down Expand Up @@ -66,4 +68,17 @@ import.meta.resolve("zod"); // => "file:///path/to/project/node_modules/zod/inde
- `import.meta.url`
- A `string` url to the current file, e.g. `file:///path/to/project/index.ts`. Equivalent to [`import.meta.url` in browsers](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import.meta#url)

---

- `import.meta.glob`
- Import multiple modules using glob patterns. Returns an object mapping file paths to lazy-loading functions.

```ts
const modules = import.meta.glob("./src/*.ts");
// const modules = {
// './src/a.ts': () => import('./src/a.ts'),
// './src/b.ts': () => import('./src/b.ts'),
// }
```

{% /table %}
113 changes: 113 additions & 0 deletions packages/bun-types/globals.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1344,13 +1344,126 @@ interface ImportMeta {
*/
main: boolean;

/**
* Import multiple modules using glob patterns.
* Inspired by [Vite's `import.meta.glob`](https://vite.dev/guide/features.html#glob-import).
*
* @param pattern - A glob pattern or array of glob patterns to match files
* @param options - Options for how imports are handled
* @returns An object mapping file paths to dynamic import functions
*
* @example
* const modules = import.meta.glob('./src/*.ts')
* const module = await modules['./src/foo.ts']()
*
* // equivalent to
* const modules = {
* './src/foo.ts': () => import('./src/foo.ts'),
* './src/bar.ts': () => import('./src/bar.ts'),
* }
* const module = await modules['./src/foo.ts']()
*/
glob<Eager extends boolean = false, TModule = unknown>(
Comment thread
RiskyMH marked this conversation as resolved.
Resolved
pattern: string | string[],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It seems like we support multiple patterns, but it's not 100% clear how to use that, perhaps some docs would be neat?

options?: ImportMetaGlobOptions<Eager>,
): Eager extends true ? Record<string, TModule> : Record<string, () => Promise<TModule>>;
Comment thread
RiskyMH marked this conversation as resolved.
Resolved
glob<TModule = unknown>(
pattern: string | string[],
options?: ImportMetaGlobOptions<false>,
): Record<string, () => Promise<TModule>>;
glob<TModule = unknown>(pattern: string | string[], options?: ImportMetaGlobOptions<true>): Record<string, TModule>;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved

Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
/** Alias of `import.meta.dir`. Exists for Node.js compatibility */
dirname: string;

/** Alias of `import.meta.path`. Exists for Node.js compatibility */
filename: string;
}

interface ImportMetaGlobOptions<Eager extends boolean = false> {
// todo:
// /**
// * If true, imports all modules eagerly as if they were top level imports.
// * If false (default), returns functions that import modules lazily with dynamic imports.
// *
// * @example
// * const eager = import.meta.glob('./src/*.ts', { eager: true })
// * const normal = import.meta.glob('./src/*.ts', { eager: false })
// *
// * // equivalent to
// * import * as __modules_foo from './src/foo.ts'
// * import * as __modules_bar from './src/bar.ts'
// *
// * const eager = {
// * './src/foo.ts': __modules_foo,
// * './src/bar.ts': __modules_bar,
// * }
// * const normal = {
// * './src/foo.ts': () => import('./src/foo.ts'),
// * './src/bar.ts': () => import('./src/bar.ts'),
// * }
// */
// eager?: Eager;
/** Right now Bun doesn't support eager mode */
eager?: false;
Comment on lines +1384 to +1408

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Docs could use a little bit of love, imo.

Also, why expose this if it is not currently supported?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Realized I didn't leave a very helpful message when I said they could use a little bit more love. What I'm specifically referring to is:

  • the docs could offer an example that is a "birds-eye view" of the function, and does not assume that the user has a mental model of "code transformation" if you will
  • perhaps the docs could explain what "eager" loading means in terms of how it impacts the execution of the module
  • perhaps you might want to remove the (synchronously) since I think it just aliases the word eagerly and doesn't necessarily shed much light on the concept (imo)

My opinions -- feel free to disagree

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I mean, the docs are basically written the same way as vite. But yeah dynamic imports may be confusing. I dont really know of a better way to describe the limbo land of not proper import but a function that returns promise of imported file.

Comment thread
RiskyMH marked this conversation as resolved.
Resolved
/**
* Specify a named export to import from matched modules.
* If not specified, imports the entire module.
*
* @example
* const modules = import.meta.glob('./src/*.ts', { import: 'default' })
*
* // equivalent to
* const modules = {
* './src/bar.ts': () => import('./src/bar.ts').then((m) => m.default),
* './src/foo.ts': () => import('./src/foo.ts').then((m) => m.default),
* }
*/
import?: "default" | (string & {});
/**
* Add a query string to the end of the "generated" dynamic import.
*
* @example
* const modules = import.meta.glob('./assets/*.txt', { query: '?something' })
*
* // equivalent to
* const modules = {
* './assets/file.txt': () => import('./assets/file.txt?something'),
* }
*/
query?: string;
/**
* Import attributes to pass to the import statement.
* This is like the standard way to specify import options to a normal dynamic import.
*
* @example
* const modules = import.meta.glob('./assets/*.txt', { with: { type: 'text' } })
*
* // equivalent to
* const modules = {
* './assets/file.txt': () => import('./assets/file.txt', { with: { type: 'text' } }),
* }
*/
with?: ImportAttributes;
/**
* The base path to prepend to the imports.
* Basically changing the "cwd" of the directory to scan.
*
* @example
* const modules = import.meta.glob('./*.txt', { base: '../public' })
*
* // equivalent to
* const modules = {
* './file.txt': () => import('../public/file.txt'),
* }
*/
base?: string;
}

interface ImportAttributes {
type: "css" | "file" | "json" | "jsonc" | "toml" | "yaml" | "txt" | "text" | "html" | (string & {});
}

/**
* NodeJS-style `require` function
*
Expand Down
2 changes: 2 additions & 0 deletions src/ast/E.zig
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,8 @@ pub const Special = union(enum) {
hot_accept_visited,
/// Prints the resolved specifier string for an import record.
resolved_specifier_string: ImportRecord.Index,
/// `import.meta.glob`
import_meta_glob,
};

pub const Call = struct {
Expand Down
Loading