drizzle-team / drizzle-team/drizzle-orm

schema config silently ignores negation patterns ("!") in array entries

Open
#5,379 1 comment 1 reaction 0 assignees View on GitHub
Dominant language
TypeScript
Stars
35.8k
Forks
1.6k
Avg merge
2d 7h
Merged PRs (30d)
4

Description

## What version of `drizzle-kit` are you using?

0.31.8 (drizzle-orm 0.44.7)

## Describe the Bug

The `schema` field in `drizzle.config.ts` silently ignores glob negation patterns (`!` prefix) when passed as array entries. The [docs](https://orm.drizzle.team/docs/drizzle-config-file) show the schema field accepts `string | string[]` with glob support, but negation patterns are treated as literal file paths that match nothing — they don't actually exclude files.

### Config

```ts
export default {
schema: [
"./src/db/schema/*.ts",
"!./src/db/schema/index.ts", // intended to exclude — silently ignored
"!./src/db/schema/mastra.ts", // intended to exclude — silently ignored
],
// ...
};
```

### Expected behavior

`mastra.ts` and `index.ts` should be excluded from schema scanning.

### Actual behavior

All `.ts` files in `./src/db/schema/` are scanned, including `mastra.ts` and `index.ts`. The `!`-prefixed entries silently match zero files and have no effect.

## Root Cause

Looking at `src/serializer/index.ts` in the drizzle-kit source, the `prepareFilenames` function processes each array entry independently via `glob.sync()`:

```js
prepareFilenames = (path) => {
if (typeof path === "string") {
path = [path];
}
const result = path.reduce((result2, cur) => {
const globbed = glob.sync(`${prefix}${cur}`);
globbed.forEach((it) => {
// ... add to result set
});
return result2;
}, new Set());
// ...
};
```

Each entry calls `glob.sync()` separately. The `glob` library (v8) does not treat `!` as a negation operator in standalone calls — it treats it as a literal character, matching zero files. Negation only works when passed via the `ignore` option or when using libraries like `globby` that handle `!` patterns across multiple entries.

## Suggested Fix

Either:

1. **Split positive and negative patterns** — extract `!`-prefixed entries and pass them as the `ignore` option to `glob.sync()`:
```js
const positive = path.filter(p => !p.startsWith('!'));
const negative = path.filter(p => p.startsWith('!')).map(p => p.slice(1));

positive.reduce((result, cur) => {
const globbed = glob.sync(cur, { ignore: negative });
// ...
}, new Set());
```

2. **Switch to `globby`** or use `glob`'s built-in `ignore` option, which is the standard way to handle negation in Node.js glob libraries.

3. **At minimum, warn the user** if a `!`-prefixed pattern matches zero files, since right now it fails silently.

## Use Case

This matters for projects using libraries that create their own tables at runtime (e.g., Mastra). We need to exclude their schema definitions from `drizzle-kit push` to avoid conflicts with tables the library already manages. Currently there's no way to exclude specific files from a glob-based schema config without restructuring the directory layout.

Contributor guide

Open the contributing guide

Research direction

Start in src/serializer/index.ts at prepareFilenames and inspect how schema array entries reach glob.sync(). Reproduce the behavior with the configuration shown, then add coverage for excluding index.ts and mastra.ts while preserving positive matches. Done means negated entries affect schema scanning instead of silently matching nothing, with a warning if that is the chosen behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
nodejs, typescript
Domain
tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.