Skip to content

Commit 38a0ad8

Browse files
committed
fix(build): prefer installed dependencies over Pantry
1 parent d42db79 commit 38a0ad8

4 files changed

Lines changed: 71 additions & 16 deletions

File tree

storage/framework/core/tsconfig.build.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@
2929
"@stacksjs/storage/*": ["./storage/src/*"],
3030
"@stacksjs/*": ["./*/src"],
3131
"ts-pantry": ["../../../node_modules/ts-pantry"],
32-
"*": ["../../../pantry/*"]
32+
// Bun uses these paths while building and running source. Prefer the
33+
// installed dependency graph; Pantry remains a fallback for its installs.
34+
"*": ["../../../node_modules/*", "../../../pantry/*"]
3335
},
3436
"resolveJsonModule": true,
3537
"types": ["bun"],

storage/framework/core/tsconfig.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,11 @@
4141
"Notifications/*": ["../../../app/Notifications/*"],
4242
"~/*": ["../../../*"],
4343
"@/*": ["../../../resources/*"],
44-
// Fallback for third-party packages: Pantry installs the dependency graph
45-
// into `pantry/` rather than `node_modules/`. It is listed last so it only
46-
// applies to specifiers that none of the mappings above matched.
44+
// Prefer installed third-party dependencies over a possibly older Pantry
45+
// tree. Bun applies these mappings at runtime as well as during builds.
46+
// Pantry-only installs still resolve through the second candidate.
4747
"ts-pantry": ["../../../node_modules/ts-pantry"],
48-
"*": ["../../../pantry/*"]
48+
"*": ["../../../node_modules/*", "../../../pantry/*"]
4949
},
5050
// `dtsx` emits the published `.d.ts` files, not tsc - these two only
5151
// describe intent for editors and for anyone running tsc by hand. The base

storage/framework/tsconfig.framework.json

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,18 +38,10 @@
3838
"~/*": ["../../*"],
3939
"@/*": ["../../resources/*"],
4040
"ts-pantry": ["../../node_modules/ts-pantry"],
41-
/*
42-
* Types come from the copy that actually runs.
43-
*
44-
* The `*` fallback below resolves to `pantry/`, which mirrors the
45-
* PUBLISHED framework's dependency graph - it pins ts-cloud ^0.11.4 and
46-
* carries 0.11.5. Bun resolves `node_modules` at runtime, where the
47-
* declared ^0.12.9 is installed, so the two trees disagreed about what
48-
* this package exports and the typecheck was checking against a version
49-
* no code runs.
50-
*/
41+
// Types and runtime imports must prefer installed dependencies over an
42+
// older Pantry graph. Keep Pantry available for Pantry-only installs.
5143
"@stacksjs/ts-cloud": ["../../node_modules/@stacksjs/ts-cloud"],
52-
"*": ["../../pantry/*"]
44+
"*": ["../../node_modules/*", "../../pantry/*"]
5345
}
5446
},
5547
"include": [
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { expect, it } from 'bun:test'
2+
import { copyFileSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'
3+
import { tmpdir } from 'node:os'
4+
import { dirname, join } from 'node:path'
5+
6+
const root = join(import.meta.dir, '..')
7+
const configs = [
8+
'storage/framework/tsconfig.base.json',
9+
'storage/framework/tsconfig.framework.json',
10+
'storage/framework/core/tsconfig.json',
11+
'storage/framework/core/tsconfig.build.json',
12+
]
13+
14+
it.each([
15+
'../tsconfig.build.json',
16+
'../tsconfig.json',
17+
'../../tsconfig.framework.json',
18+
])('prefers installed dependencies with %s and retains the Pantry fallback', async (extendsPath) => {
19+
const directory = mkdtempSync(join(tmpdir(), 'stacks-dependency-resolution-'))
20+
const entry = join(directory, 'storage/framework/core/example/src/index.ts')
21+
function write(path: string, contents: string): void {
22+
mkdirSync(dirname(path), { recursive: true })
23+
writeFileSync(path, contents)
24+
}
25+
async function run(...args: string[]): Promise<string> {
26+
const proc = Bun.spawn([process.execPath, `--config=${join(directory, 'bunfig.toml')}`, ...args], {
27+
cwd: directory,
28+
stdout: 'pipe',
29+
stderr: 'pipe',
30+
})
31+
const [output, errors, code] = await Promise.all([new Response(proc.stdout).text(), new Response(proc.stderr).text(), proc.exited])
32+
if (code !== 0) throw new Error(errors)
33+
return output.trim()
34+
}
35+
try {
36+
for (const config of configs) {
37+
const destination = join(directory, config)
38+
mkdirSync(dirname(destination), { recursive: true })
39+
copyFileSync(join(root, config), destination)
40+
}
41+
write(join(directory, 'bunfig.toml'), '# Isolated dependency-resolution fixture\n')
42+
write(join(directory, 'storage/framework/core/example/tsconfig.json'), JSON.stringify({ extends: extendsPath }))
43+
write(entry, "import version from 'fixture-dependency'\nconsole.log(version)\n")
44+
for (const [tree, version] of [['node_modules', 'installed'], ['pantry', 'pantry']] as const) {
45+
const dependency = join(directory, tree, 'fixture-dependency')
46+
write(join(dependency, 'package.json'), JSON.stringify({ name: 'fixture-dependency', type: 'module', exports: './index.ts' }))
47+
write(join(dependency, 'index.ts'), `export default '${version}'\n`)
48+
}
49+
50+
for (const expected of ['installed', 'pantry']) {
51+
expect(await run(entry)).toBe(expected)
52+
const bundle = join(directory, 'bundle.js')
53+
await run('build', entry, '--target=bun', '--outfile', bundle)
54+
expect(await run(bundle)).toBe(expected)
55+
rmSync(join(directory, 'node_modules'), { recursive: true, force: true })
56+
}
57+
}
58+
finally {
59+
rmSync(directory, { recursive: true, force: true })
60+
}
61+
})

0 commit comments

Comments
 (0)