drizzle-team / drizzle-team/drizzle-orm
schema config silently ignores negation patterns ("!") in array entries
- 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
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