Skip to content

Commit 9521059

Browse files
committed
feat(cli): add --include to override config include globs
Add a repeatable, comma-separated --include flag to the scanning commands (panda/build/dev/check, cssgen, debug, info, buildinfo) that replaces the config's include globs for a single run. Plumbed via NodeDriverOptions.include, applied to the loaded config before building the compiler (and re-applied on watch reload). Drive-by: replace deprecated z.ZodIssue with z.core.$ZodIssue.
1 parent 787af02 commit 9521059

15 files changed

Lines changed: 119 additions & 9 deletions

File tree

.changeset/cli-include-flag.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@pandacss/cli': minor
3+
'@pandacss/compiler': minor
4+
---
5+
6+
Add a `--include` flag to the scanning commands (`panda`, `build`, `dev`, `check`, `cssgen`, `debug`, `info`, `buildinfo`) to override the config's `include` globs for a single run. The flag is repeatable and accepts comma-separated values, and replaces (does not merge with) the configured globs — useful for scanning a subset of files in CI or one-off builds.

packages/cli/__tests__/buildinfo.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,15 @@ describe('buildinfo command', () => {
7676
`)
7777
})
7878

79+
it('--include narrows the scanned modules in the artifact', async () => {
80+
dir = createLibFixture()
81+
82+
const result = await runBuildinfo({ cwd: dir, logLevel: 'silent', include: ['button.tsx'] })
83+
84+
expect(result.ok).toBe(true)
85+
expect(Object.keys(readBuildInfo(dir).modules)).toEqual(['button.tsx'])
86+
})
87+
7988
it('tracks exports of recipe-consuming components with portable module keys', async () => {
8089
dir = mkdtempSync(join(tmpdir(), 'panda-cli-lib-'))
8190
writeFileSync(

packages/cli/__tests__/cli-smoke.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ describe('cli smoke', () => {
4646
4747
\`--cwd="<cwd>"\` Current working directory
4848
\`-c, --config\` Path to panda config file
49+
\`--include=<glob>\` Source file globs to scan, replacing the config include list
4950
\`-w, --watch\` Watch files and rebuild
5051
\`--outdir\` Output directory for generated files
5152
\`-o, --outfile\` Output file for extracted CSS

packages/cli/__tests__/cssgen.test.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,39 @@ describe('cssgen command', () => {
7878
})
7979
})
8080

81+
it('--include overrides a config that matches no sources', async () => {
82+
dir = createFixture(`export default {
83+
outdir: 'styled-system',
84+
include: ['no-match/**/*.tsx'],
85+
importMap: { css: ['@panda/css'] },
86+
}`)
87+
88+
const result = await runCssgen({ cwd: dir, include: ['**/*.tsx'], logLevel: 'silent' })
89+
90+
expect(result.parsed).toHaveLength(1)
91+
expect(readFileSync(join(dir, 'styled-system', 'styles.css'), 'utf8')).toContain('red')
92+
})
93+
94+
it('--include replaces the config include rather than merging', async () => {
95+
dir = createFixture()
96+
97+
const result = await runCssgen({ cwd: dir, include: ['missing/**/*.tsx'], logLevel: 'silent' })
98+
99+
expect(result.parsed).toEqual([])
100+
})
101+
102+
it('--include accepts a comma-separated glob list', async () => {
103+
dir = createFixture(`export default {
104+
outdir: 'styled-system',
105+
include: ['no-match/**/*.tsx'],
106+
importMap: { css: ['@panda/css'] },
107+
}`)
108+
109+
const result = await runCssgen({ cwd: dir, include: 'missing/**/*.tsx,**/*.tsx', logLevel: 'silent' })
110+
111+
expect(result.parsed).toHaveLength(1)
112+
})
113+
81114
it('renders human diagnostics with severity, code, and message', async () => {
82115
dir = createFixture()
83116
writeSyntaxError(dir)

packages/cli/__tests__/debug.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,19 @@ describe('debug command', () => {
3535
expect(extract.calls.length).toBeGreaterThan(0)
3636
})
3737

38+
it('--include overrides the config to extract otherwise-unscanned files', async () => {
39+
dir = createFixture(`export default {
40+
outdir: 'styled-system',
41+
include: ['no-match/**/*.tsx'],
42+
importMap: { css: ['@panda/css'] },
43+
}`)
44+
45+
const result = await runDebug({ cwd: dir, include: ['**/*.tsx'], logLevel: 'silent' })
46+
47+
expect(result.sourceCount).toBe(1)
48+
expect(existsSync(join(dir, 'styled-system', 'debug', 'App.tsx.extract.json'))).toBe(true)
49+
})
50+
3851
it('--only-config skips per-file extraction and css', async () => {
3952
dir = createFixture()
4053

packages/cli/__tests__/info.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,18 @@ describe('info command', () => {
2727
expect(JSON.parse(logs[0])).toMatchObject({ ok: true, command: 'info', sourceCount: 1, diagnostics: [] })
2828
})
2929

30+
it('--include replaces the reported source globs', async () => {
31+
// info reports the include globs (sourceCount = glob count), so an override
32+
// with two globs replaces the config's single default glob.
33+
dir = createFixture()
34+
35+
const base = await runInfo({ cwd: dir })
36+
const overridden = await runInfo({ cwd: dir, include: ['a/**/*.tsx', 'b/**/*.tsx'] })
37+
38+
expect(base.sourceCount).toBe(1)
39+
expect(overridden.sourceCount).toBe(2)
40+
})
41+
3042
it('includes timings in json output', async () => {
3143
dir = createFixture()
3244

packages/cli/src/args.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,28 @@ export function outputArgs(): ArgsDef {
2222
}
2323
}
2424

25+
export function includeArgs(): ArgsDef {
26+
return {
27+
include: {
28+
type: 'string',
29+
valueHint: 'glob',
30+
description: 'Source file globs to scan, replacing the config include list',
31+
},
32+
}
33+
}
34+
35+
/** Normalize `--include` (string, repeated array, or comma-separated) into a glob list. */
36+
export function normalizeInclude(value: unknown): string[] | undefined {
37+
if (value == null) return undefined
38+
39+
const globs = (Array.isArray(value) ? value : [value])
40+
.flatMap((entry) => String(entry).split(','))
41+
.map((entry) => entry.trim())
42+
.filter(Boolean)
43+
44+
return globs.length > 0 ? globs : undefined
45+
}
46+
2547
export function traceArgs(): ArgsDef {
2648
return {
2749
trace: { type: 'boolean', description: 'Enable compiler tracing' },
@@ -79,7 +101,7 @@ function flagName(path: PropertyKey | undefined): string {
79101
return `--${String(path).replace(/[A-Z]/g, (char) => `-${char.toLowerCase()}`)}`
80102
}
81103

82-
function formatIssue(issue: z.ZodIssue, flags: Record<string, unknown>): string {
104+
function formatIssue(issue: z.core.$ZodIssue, flags: Record<string, unknown>): string {
83105
const path = issue.path[0]
84106
const name = flagName(path)
85107
const received = path === undefined ? undefined : flags[String(path)]

packages/cli/src/commands/build.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { defineCommand, type ArgsDef } from 'citty'
2-
import { baseArgs, outputArgs, parseCliFlags, traceArgs } from '../args'
2+
import { baseArgs, includeArgs, outputArgs, parseCliFlags, traceArgs } from '../args'
33
import { isCheckClean } from '../check'
44
import { buildFlagsSchema } from '../schema'
55
import { runCommand } from '../run-command'
@@ -17,6 +17,7 @@ import { formatWatchError, startProjectWatch } from '../watch'
1717
export function buildArgs(): ArgsDef {
1818
return {
1919
...baseArgs(),
20+
...includeArgs(),
2021
watch: { type: 'boolean', description: 'Watch files and rebuild', alias: 'w' },
2122
outdir: { type: 'string', description: 'Output directory for generated files' },
2223
outfile: { type: 'string', description: 'Output file for extracted CSS', alias: 'o' },

packages/cli/src/commands/buildinfo.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { type BuildInfo, type Driver } from '@pandacss/compiler'
22
import { defineCommand } from 'citty'
33
import { mkdirSync, writeFileSync } from 'node:fs'
44
import { dirname, isAbsolute, relative } from 'node:path'
5-
import { baseArgs, outputArgs, parseCliFlags, traceArgs } from '../args'
5+
import { baseArgs, includeArgs, outputArgs, parseCliFlags, traceArgs } from '../args'
66
import { runCommand } from '../run-command'
77
import { buildinfoFlagsSchema } from '../schema'
88
import { collectParseDiagnostics, diagnosticsPass, normalizeDiagnostics } from '../diagnostics'
@@ -18,6 +18,7 @@ export const buildinfoCommand = defineCommand({
1818
},
1919
args: () => ({
2020
...baseArgs(),
21+
...includeArgs(),
2122
outfile: { type: 'string', description: "Output path, default './<outdir>/panda.buildinfo.json'", alias: 'o' },
2223
panda: { type: 'string', description: "Peer Panda version range to stamp into the artifact (default '*')" },
2324
minify: { type: 'boolean', description: 'Minify the generated JSON', alias: 'm' },

packages/cli/src/commands/cssgen.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { defineCommand } from 'citty'
22
import { type ParseFileReport, type StylesheetLayerName } from '@pandacss/compiler'
3-
import { baseArgs, outputArgs, parseCliFlags, traceArgs } from '../args'
3+
import { baseArgs, includeArgs, outputArgs, parseCliFlags, traceArgs } from '../args'
44
import { checkExpectedFiles, formatCheckSummary, isCheckClean } from '../check'
55
import { cssgenFlagsSchema } from '../schema'
66
import { runCommand } from '../run-command'
@@ -18,6 +18,7 @@ export const cssgenCommand = defineCommand({
1818
},
1919
args: () => ({
2020
...baseArgs(),
21+
...includeArgs(),
2122
watch: { type: 'boolean', description: 'Watch files and rebuild', alias: 'w' },
2223
outfile: { type: 'string', description: 'Output file for extracted CSS', alias: 'o' },
2324
splitting: { type: 'boolean', description: 'Emit split CSS files' },

0 commit comments

Comments
 (0)