Skip to content

Commit 379efa8

Browse files
WolfieLeaderKyleAMathewsclaude
authored
Readability: sync/async cleanup, DRY, type safety, config fixes (#55)
* fix: DRY for discover skills, auto organize imports, remove async for sync functions * chore: looser ESLint, allow T[] for simple use, import order warns and no error, and make the config type safe * chore: remove outDir (dist is the default), noEmit true we use tsdown for compilation (therefore no need for declaration) * chore: ESLint config looser, both array styles are accepted * chore: auto imports and DRY in tests * fix: cmdList is not async anymore * chore: async fix, type narrowing, dynamic import for existing function * chore: format and lint * docs: changeset for this patch * Revert eslint scope creep and fix review consistency gaps - Revert unrelated eslint.config.js changes (array-type, import/order) - Remove remaining async/await from 9 scanner tests - Use mockFetchNotOk() and requireFirstSkill() in staleness test - Remove redundant non-null assertions in skills test - Remove unnecessary await in scanIntentsOrFail Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Update changeset to cover all PR changes Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Kyle Mathews <mathews.kyle@gmail.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent b808071 commit 379efa8

10 files changed

Lines changed: 140 additions & 151 deletions

File tree

.changeset/neat-pots-melt.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@tanstack/intent': patch
3+
---
4+
5+
Make `scanForIntents` and `scanLibrary` synchronous instead of returning Promises for purely synchronous work. Clean up unnecessary async/await throughout source and tests, extract DRY test helpers, and improve type narrowing.

packages/intent/src/cli.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ async function scanIntentsOrFail(): Promise<ScanResult> {
3535
const { scanForIntents } = await import('./scanner.js')
3636

3737
try {
38-
return await scanForIntents()
38+
return scanForIntents()
3939
} catch (err) {
4040
fail((err as Error).message)
4141
}

packages/intent/src/intent-library.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ import type { LibraryScanResult } from './library-scanner.js'
99
// Commands
1010
// ---------------------------------------------------------------------------
1111

12-
async function cmdList(): Promise<void> {
12+
function cmdList(): void {
1313
let result: LibraryScanResult
1414
try {
15-
result = await scanLibrary(process.argv[1]!)
15+
result = scanLibrary(process.argv[1]!)
1616
} catch (err) {
1717
console.error((err as Error).message)
1818
process.exit(1)
@@ -90,7 +90,7 @@ const command = process.argv[2]
9090
switch (command) {
9191
case 'list':
9292
case undefined:
93-
await cmdList()
93+
cmdList()
9494
break
9595
case 'install':
9696
cmdInstall()

packages/intent/src/library-scanner.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,10 @@ function discoverSkills(skillsDir: string): Array<SkillEntry> {
101101
// Main scanner
102102
// ---------------------------------------------------------------------------
103103

104-
export async function scanLibrary(
104+
export function scanLibrary(
105105
scriptPath: string,
106106
_projectRoot?: string,
107-
): Promise<LibraryScanResult> {
107+
): LibraryScanResult {
108108
const packages: Array<LibraryPackage> = []
109109
const warnings: Array<string> = []
110110
const visited = new Set<string>()

packages/intent/src/scanner.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ function toVersionConflict(
318318
// Main scanner
319319
// ---------------------------------------------------------------------------
320320

321-
export async function scanForIntents(root?: string): Promise<ScanResult> {
321+
export function scanForIntents(root?: string): ScanResult {
322322
const projectRoot = root ?? process.cwd()
323323
const packageManager = detectPackageManager(projectRoot)
324324
const nodeModulesDir = join(projectRoot, 'node_modules')

packages/intent/tests/library-scanner.test.ts

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ afterEach(() => {
5353
// ---------------------------------------------------------------------------
5454

5555
describe('scanLibrary', () => {
56-
it('returns the home package with its skills', async () => {
56+
it('returns the home package with its skills', () => {
5757
const pkgDir = createDir(root, 'node_modules', '@tanstack', 'router')
5858
writeJson(join(pkgDir, 'package.json'), {
5959
name: '@tanstack/router',
@@ -67,7 +67,7 @@ describe('scanLibrary', () => {
6767
description: 'File-based route definitions',
6868
})
6969

70-
const result = await scanLibrary(scriptPath(pkgDir), root)
70+
const result = scanLibrary(scriptPath(pkgDir), root)
7171

7272
expect(result.warnings).toEqual([])
7373
expect(result.packages).toHaveLength(1)
@@ -81,7 +81,7 @@ describe('scanLibrary', () => {
8181
)
8282
})
8383

84-
it('includes the full path to each SKILL.md', async () => {
84+
it('includes the full path to each SKILL.md', () => {
8585
const pkgDir = createDir(root, 'node_modules', '@tanstack', 'router')
8686
writeJson(join(pkgDir, 'package.json'), {
8787
name: '@tanstack/router',
@@ -91,13 +91,13 @@ describe('scanLibrary', () => {
9191
const skillDir = createDir(pkgDir, 'skills', 'routing')
9292
writeSkillMd(skillDir, { name: 'routing', description: 'Routing patterns' })
9393

94-
const result = await scanLibrary(scriptPath(pkgDir), root)
94+
const result = scanLibrary(scriptPath(pkgDir), root)
9595

9696
const skill = result.packages[0]!.skills[0]!
9797
expect(skill.path).toBe(join(pkgDir, 'skills', 'routing', 'SKILL.md'))
9898
})
9999

100-
it('recursively discovers deps with tanstack-intent keyword', async () => {
100+
it('recursively discovers deps with tanstack-intent keyword', () => {
101101
// Home package: @tanstack/router, depends on @tanstack/query
102102
const routerDir = createDir(root, 'node_modules', '@tanstack', 'router')
103103
writeJson(join(routerDir, 'package.json'), {
@@ -127,7 +127,7 @@ describe('scanLibrary', () => {
127127
description: 'Query and mutation patterns',
128128
})
129129

130-
const result = await scanLibrary(scriptPath(routerDir), root)
130+
const result = scanLibrary(scriptPath(routerDir), root)
131131

132132
expect(result.warnings).toEqual([])
133133
expect(result.packages).toHaveLength(2)
@@ -141,7 +141,7 @@ describe('scanLibrary', () => {
141141
expect(query.skills[0]!.description).toBe('Query and mutation patterns')
142142
})
143143

144-
it('discovers deps via peerDependencies', async () => {
144+
it('discovers deps via peerDependencies', () => {
145145
const pkgDir = createDir(root, 'node_modules', '@tanstack', 'router')
146146
writeJson(join(pkgDir, 'package.json'), {
147147
name: '@tanstack/router',
@@ -159,13 +159,13 @@ describe('scanLibrary', () => {
159159
const querySkill = createDir(queryDir, 'skills', 'fetching')
160160
writeSkillMd(querySkill, { name: 'fetching', description: 'Fetching' })
161161

162-
const result = await scanLibrary(scriptPath(pkgDir), root)
162+
const result = scanLibrary(scriptPath(pkgDir), root)
163163

164164
const names = result.packages.map((p) => p.name)
165165
expect(names).toContain('@tanstack/query')
166166
})
167167

168-
it('skips deps without tanstack-intent keyword or bin.intent', async () => {
168+
it('skips deps without tanstack-intent keyword or bin.intent', () => {
169169
const pkgDir = createDir(root, 'node_modules', '@tanstack', 'router')
170170
writeJson(join(pkgDir, 'package.json'), {
171171
name: '@tanstack/router',
@@ -183,13 +183,13 @@ describe('scanLibrary', () => {
183183
const reactSkill = createDir(reactDir, 'skills', 'hooks')
184184
writeSkillMd(reactSkill, { name: 'hooks', description: 'React hooks' })
185185

186-
const result = await scanLibrary(scriptPath(pkgDir), root)
186+
const result = scanLibrary(scriptPath(pkgDir), root)
187187

188188
const names = result.packages.map((p) => p.name)
189189
expect(names).not.toContain('react')
190190
})
191191

192-
it('follows deps with legacy bin.intent (backwards compat)', async () => {
192+
it('follows deps with legacy bin.intent (backwards compat)', () => {
193193
const pkgDir = createDir(root, 'node_modules', '@tanstack', 'router')
194194
writeJson(join(pkgDir, 'package.json'), {
195195
name: '@tanstack/router',
@@ -210,13 +210,13 @@ describe('scanLibrary', () => {
210210
const querySkill = createDir(queryDir, 'skills', 'fetching')
211211
writeSkillMd(querySkill, { name: 'fetching', description: 'Fetching' })
212212

213-
const result = await scanLibrary(scriptPath(pkgDir), root)
213+
const result = scanLibrary(scriptPath(pkgDir), root)
214214

215215
const names = result.packages.map((p) => p.name)
216216
expect(names).toContain('@tanstack/query')
217217
})
218218

219-
it('skips deps with other keywords but not tanstack-intent', async () => {
219+
it('skips deps with other keywords but not tanstack-intent', () => {
220220
const pkgDir = createDir(root, 'node_modules', '@tanstack', 'router')
221221
writeJson(join(pkgDir, 'package.json'), {
222222
name: '@tanstack/router',
@@ -234,13 +234,13 @@ describe('scanLibrary', () => {
234234
const libSkill = createDir(libDir, 'skills', 'core')
235235
writeSkillMd(libSkill, { name: 'core', description: 'Core patterns' })
236236

237-
const result = await scanLibrary(scriptPath(pkgDir), root)
237+
const result = scanLibrary(scriptPath(pkgDir), root)
238238

239239
const names = result.packages.map((p) => p.name)
240240
expect(names).not.toContain('some-lib')
241241
})
242242

243-
it('handles packages with no skills/ directory', async () => {
243+
it('handles packages with no skills/ directory', () => {
244244
const pkgDir = createDir(root, 'node_modules', '@tanstack', 'router')
245245
writeJson(join(pkgDir, 'package.json'), {
246246
name: '@tanstack/router',
@@ -249,13 +249,13 @@ describe('scanLibrary', () => {
249249
})
250250
// No skills/ directory
251251

252-
const result = await scanLibrary(scriptPath(pkgDir), root)
252+
const result = scanLibrary(scriptPath(pkgDir), root)
253253

254254
expect(result.packages).toHaveLength(1)
255255
expect(result.packages[0]!.skills).toEqual([])
256256
})
257257

258-
it('does not visit the same package twice (cycle detection)', async () => {
258+
it('does not visit the same package twice (cycle detection)', () => {
259259
// router -> query -> router (circular)
260260
const routerDir = createDir(root, 'node_modules', '@tanstack', 'router')
261261
writeJson(join(routerDir, 'package.json'), {
@@ -273,15 +273,15 @@ describe('scanLibrary', () => {
273273
dependencies: { '@tanstack/router': '^1.0.0' }, // circular back
274274
})
275275

276-
const result = await scanLibrary(scriptPath(routerDir), root)
276+
const result = scanLibrary(scriptPath(routerDir), root)
277277

278278
// Each package appears exactly once
279279
const names = result.packages.map((p) => p.name)
280280
expect(names).toHaveLength(2)
281281
expect(new Set(names).size).toBe(2)
282282
})
283283

284-
it('discovers sub-skills within a package', async () => {
284+
it('discovers sub-skills within a package', () => {
285285
const pkgDir = createDir(root, 'node_modules', '@tanstack', 'router')
286286
writeJson(join(pkgDir, 'package.json'), {
287287
name: '@tanstack/router',
@@ -299,7 +299,7 @@ describe('scanLibrary', () => {
299299
description: 'Nested route patterns',
300300
})
301301

302-
const result = await scanLibrary(scriptPath(pkgDir), root)
302+
const result = scanLibrary(scriptPath(pkgDir), root)
303303

304304
const skills = result.packages[0]!.skills
305305
expect(skills).toHaveLength(2)
@@ -308,10 +308,10 @@ describe('scanLibrary', () => {
308308
expect(names).toContain('routing/nested-routes')
309309
})
310310

311-
it('returns a warning when home package.json cannot be found', async () => {
311+
it('returns a warning when home package.json cannot be found', () => {
312312
const fakeScript = join(root, 'nowhere', 'bin', 'intent.js')
313313

314-
const result = await scanLibrary(fakeScript, root)
314+
const result = scanLibrary(fakeScript, root)
315315

316316
expect(result.packages).toEqual([])
317317
expect(result.warnings).toHaveLength(1)

0 commit comments

Comments
 (0)