Skip to content

Commit c622c19

Browse files
chore: merge #755 deterministic root reservations
Refs #686 #694 Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2 parents dd3d196 + 6bab638 commit c622c19

12 files changed

Lines changed: 908 additions & 31 deletions

‎e2e/landing-zero-runtime.spec.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,13 +148,13 @@ test.describe('Landing Page - Zero Runtime Validation', () => {
148148

149149
expect(headingClasses.length).toBeGreaterThan(1)
150150
const atomicClasses = headingClasses.filter((className) =>
151-
/^(?:[a-z][a-z0-9_]{0,2}-)?[a-z0-9_]{1,3}$/i.test(className),
151+
/^(?:[a-z]-)?[a-z0-9_]{1,3}$/i.test(className),
152152
)
153153
expect(atomicClasses.length).toBeGreaterThan(1)
154154
expect(
155155
headingClasses.every(
156156
(className) =>
157-
/^(?:[a-z][a-z0-9_]{0,2}-)?[a-z0-9_]{1,3}$/i.test(className) ||
157+
/^(?:[a-z]-)?[a-z0-9_]{1,3}$/i.test(className) ||
158158
/^typo-[a-z0-9]+$/i.test(className),
159159
),
160160
`Expected compact base-37 classes, received: ${headingClasses.join(' ')}`,
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import { resolve } from 'node:path'
2+
3+
import { expect, it } from 'bun:test'
4+
import { type Plugin, resolveConfig } from 'vite'
5+
6+
import {
7+
type AssetsManifest,
8+
getPluginApi,
9+
vitePluginRscMinimal,
10+
} from '../../../../apps/landing/node_modules/@vitejs/plugin-rsc/dist/plugin.js'
11+
import { productionFixture } from './production-fixture'
12+
13+
it.each([true, false])(
14+
'removes dead proxy preloads from actual landing plugin with entry group=%s',
15+
async (withEntry) => {
16+
// Given actual config plugins and typed entry/reference asset dependencies.
17+
const root = resolve(import.meta.dir, '../../../../apps/landing')
18+
const config = await resolveConfig(
19+
{ root, configLoader: 'bundle' },
20+
'build',
21+
)
22+
const apiPlugin = vitePluginRscMinimal()
23+
const cleanup = config.plugins.find(
24+
(p) => p.name === 'landing:omit-devup-css-proxy-preloads',
25+
)
26+
if (!cleanup) throw new TypeError('Expected actual landing cleanup')
27+
let api: ReturnType<typeof getPluginApi>
28+
const entry = {
29+
js: ['/assets/devup-ui.css-DEAD.js', '/assets/main.js'],
30+
css: ['/assets/devup-ui.css'],
31+
}
32+
const reference = {
33+
js: [
34+
'/assets/devup-ui-7.css-DEAD.js',
35+
'/assets/card.js',
36+
'/assets/vendor-devup-ui.css-LIVE.js',
37+
],
38+
css: ['/assets/card.css'],
39+
}
40+
const assets = {
41+
clientEntryUrl: '/assets/main.js',
42+
...(withEntry ? { clientEntryDeps: entry } : {}),
43+
clientReferenceDeps: { card: reference },
44+
serverResources: { page: { css: ['/assets/server.css'] } },
45+
} satisfies AssetsManifest
46+
const provider: Plugin = {
47+
name: 'test:provide-rsc-assets',
48+
configResolved(miniConfig) {
49+
api = getPluginApi(miniConfig)
50+
},
51+
generateBundle: {
52+
order: 'pre',
53+
handler() {
54+
if (!api) throw new TypeError('Expected public MINI build RSC API')
55+
api.manager.buildAssetsManifest = assets
56+
},
57+
},
58+
}
59+
const fixture = await productionFixture()
60+
try {
61+
const main = await fixture.file(
62+
'app/src/main.js',
63+
'export const value=1;',
64+
)
65+
// When Vite supplies a genuine client hook context in a tiny normal build.
66+
const output = await fixture.run(false, [], {
67+
plugins: [apiPlugin, cleanup, provider],
68+
build: { write: false, lib: { entry: main, formats: ['es'] } },
69+
})
70+
// Then only dead JS preloads disappear; ordinary JS, CSS and metadata remain.
71+
expect(output.some((item) => item.type === 'chunk')).toBe(true)
72+
expect(reference.js).toEqual([
73+
'/assets/card.js',
74+
'/assets/vendor-devup-ui.css-LIVE.js',
75+
])
76+
expect(reference.css).toEqual(['/assets/card.css'])
77+
expect(entry.js).toEqual(
78+
withEntry
79+
? ['/assets/main.js']
80+
: ['/assets/devup-ui.css-DEAD.js', '/assets/main.js'],
81+
)
82+
expect(entry.css).toEqual(['/assets/devup-ui.css'])
83+
expect(assets.clientEntryUrl).toBe('/assets/main.js')
84+
expect(assets.serverResources).toEqual({
85+
page: { css: ['/assets/server.css'] },
86+
})
87+
expect(api?.manager.buildAssetsManifest).toBe(assets)
88+
} finally {
89+
await fixture.close()
90+
}
91+
},
92+
30000,
93+
)

‎packages/vite-plugin/src/__tests__/nonphysical-arrival-native.test.ts‎

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,6 @@ it('subtracts a learned physical arrival when a fresh native generation promotes
5858
await fixture.run(false, [provider])
5959
expect(await fixture.learned()).toContain(physical)
6060
// When the same actual source joins the next native generation's scan roots.
61-
await fixture.file(
62-
'app/src/main.js',
63-
"export {cls} from '../../outside/view.js';",
64-
)
6561
await fixture.run(false, [], {
6662
plugins: [
6763
DevupUI({ sourceDirs: [`${fixture.directory}/outside`] }),

‎packages/vite-plugin/src/__tests__/nonphysical-modules.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ it('keeps existing direct and recursive extraction filenames consistent across q
128128
await realpath(await mkdtemp(join(tmpdir(), 'devup-v1-current-id-')))
129129
).replaceAll('\\', '/')
130130
const entry = join(root, 'src/main.ts')
131-
const style = `${root}/z-style.ts`
131+
const style = `${root}/a-style.ts`
132132
const constant = `${root}/src/constant.ts`
133133
const direct: {
134134
readonly id: string

‎packages/vite-plugin/src/__tests__/production-entry-reservation.test.ts‎

Lines changed: 104 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
1-
import { createNonphysicalIdStore } from '@devup-ui/plugin-utils'
1+
import { symlink } from 'node:fs/promises'
2+
3+
import {
4+
createNonphysicalIdStore,
5+
resolveSourceDirs,
6+
} from '@devup-ui/plugin-utils'
27
import { expect, it } from 'bun:test'
38
import { resolveConfig, type UserConfig } from 'vite'
49

510
import {
611
prepareProductionManifest,
712
type ProductionOptions,
813
} from '../production-manifest'
14+
import { productionRootSources } from '../production-root-sources'
915
import { productionFixture } from './production-fixture'
1016

1117
it.each([
@@ -20,7 +26,7 @@ it.each([
2026
'html',
2127
'html-mixed',
2228
] as const)(
23-
'reserves input closure while preserving legacy inventory when input=%s',
29+
'reserves roots and input closure while preserving legacy inventory when input=%s',
2430
async (form) => {
2531
// Given exact inputs outside sourceDirs and an unrelated configured search file.
2632
const fixture = await productionFixture()
@@ -129,16 +135,17 @@ it.each([
129135
options,
130136
(inputs) => observed.push(...inputs.fileDependencies),
131137
)
132-
// Then ordinary HTML retains 919 inventory, while scripts reserve only reached candidates.
138+
// Then ordinary HTML retains 919 inventory, while scripts also reserve configured roots.
133139
const legacy = form === 'html' || form === 'html-mixed'
134140
const expected =
135141
form === 'virtual'
136-
? []
142+
? [unused]
137143
: [
138144
entry,
139145
view,
140146
...(form === 'mdx' ? [mdx] : []),
141-
...(legacy ? [unused, tooling] : []),
147+
unused,
148+
...(legacy ? [tooling] : []),
142149
]
143150
const context = manifest.contexts.find(
144151
({ context }) => context === 'client',
@@ -149,7 +156,7 @@ it.each([
149156
'virtual:learned.js',
150157
])
151158
expect(context?.scan).not.toContain('virtual:learned.js')
152-
if (!legacy) expect(context?.scan).not.toContain(unused)
159+
expect(context?.scan).toContain(unused)
153160
if (form !== 'virtual')
154161
expect(observed).toContain(
155162
entry.replaceAll('/', process.platform === 'win32' ? '\\' : '/'),
@@ -159,3 +166,94 @@ it.each([
159166
}
160167
},
161168
)
169+
170+
it('censuses explicit roots and includes without test, output or automatic package inventories', async () => {
171+
// Given default roots, explicit overrides, linked siblings and an included package.
172+
const fixture = await productionFixture()
173+
const source = await fixture.file('app/src/view.js', 'export {};')
174+
const app = await fixture.file('app/app/page.js', 'export {};')
175+
const configured = await fixture.file('app/custom/view.js', 'export {};')
176+
const included = await fixture.file(
177+
'app/node_modules/included/src/view.js',
178+
'export {};',
179+
)
180+
await fixture.file(
181+
'app/node_modules/included/package.json',
182+
'{"name":"included"}',
183+
)
184+
for (const name of '__tests__ tests test __fixtures__ fixtures dist build out coverage .next tooling scripts generated'.split(
185+
' ',
186+
))
187+
await fixture.file(`app/src/${name}/view.js`, 'export {};')
188+
for (const name of 'view.test.tsx view.spec.js types.d.ts types.d.mts types.d.cts'.split(
189+
' ',
190+
))
191+
await fixture.file(`app/src/${name}`, 'export {};')
192+
await fixture.file('app/node_modules/included/dist/unused.js', 'export {};')
193+
await fixture.file(
194+
'app/node_modules/included/fixtures/unused.js',
195+
'export {};',
196+
)
197+
await fixture.file(
198+
'app/node_modules/@devup-ui/tooling/package.json',
199+
'{"main":"index.js"}',
200+
)
201+
await fixture.file(
202+
'app/node_modules/@devup-ui/tooling/index.js',
203+
'export {};',
204+
)
205+
const outside = await fixture.file('outside/view.js', 'export {};')
206+
for (const name of ['first', 'second'])
207+
await symlink(
208+
`${fixture.directory}/outside`,
209+
`${fixture.root}/src/${name}`,
210+
'junction',
211+
)
212+
await symlink(
213+
`${fixture.root}/src`,
214+
`${fixture.directory}/outside/cycle`,
215+
'junction',
216+
)
217+
await symlink(
218+
`${fixture.root}/src/fixtures`,
219+
`${fixture.root}/src/blocked`,
220+
'junction',
221+
)
222+
try {
223+
// When the same private census uses default roots or explicit sourceDirs.
224+
const options = {
225+
cwd: fixture.root,
226+
exclude: [`${fixture.root}/src/generated`],
227+
includeMdx: ['.mdx'],
228+
}
229+
const defaults = productionRootSources(
230+
{ ...options, roots: resolveSourceDirs(fixture.root) },
231+
['included'],
232+
)
233+
const override = productionRootSources(
234+
{ ...options, roots: resolveSourceDirs(fixture.root, ['custom']) },
235+
[],
236+
)
237+
// Then lexical aliases survive cycles; excluded census sources never join either set.
238+
const paths = defaults.map(({ path }) => path.replaceAll('\\', '/')).sort()
239+
expect(paths).toEqual(
240+
[
241+
source,
242+
app,
243+
included,
244+
`${fixture.root}/src/first/view.js`,
245+
`${fixture.root}/src/second/view.js`,
246+
].sort(),
247+
)
248+
expect(
249+
defaults.filter(
250+
({ realPath }) => realPath.replaceAll('\\', '/') === outside,
251+
),
252+
).toHaveLength(2)
253+
expect(override.map(({ path }) => path.replaceAll('\\', '/'))).toEqual([
254+
configured,
255+
])
256+
} finally {
257+
await fixture.close()
258+
}
259+
})

‎packages/vite-plugin/src/__tests__/production-extracted-numbering-native.test.ts‎

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ function fileIds(): string[] {
1313
}
1414

1515
it.each([false, true])(
16-
'reserves only extracted identities when native inputs reach dist and test modules with singleCss=%s',
16+
'reserves root candidates and reached dist and test modules with singleCss=%s',
1717
async (singleCss) => {
1818
// Given an independently specified cohort and four unreachable counterexamples.
1919
const fixture = await productionFixture()
@@ -45,9 +45,27 @@ it.each([false, true])(
4545
'app/node_modules/@devup-ui/tooling/package.json',
4646
'{"name":"@devup-ui/tooling","type":"module","main":"index.js"}',
4747
)
48+
const unused = await fixture.file(
49+
'app/src/aaa-unused.js',
50+
"import {css} from '@devup-ui/react'; import 'foreign-poison'; import '@devup-editor/root-only'; export const unused=css({zIndex:99});",
51+
)
52+
await fixture.file(
53+
'app/node_modules/foreign-poison/package.json',
54+
'{broken',
55+
)
56+
await fixture.file(
57+
'app/node_modules/@devup-editor/root-only/package.json',
58+
'{"name":"@devup-editor/root-only","exports":"./dist/style.js"}',
59+
)
60+
const rootOnly = await fixture.file(
61+
'app/node_modules/@devup-editor/root-only/dist/style.js',
62+
"import {css} from '@devup-ui/react'; export const rootOnly=css({zIndex:88});",
63+
)
4864
const negatives = []
4965
for (const path of [
50-
'app/src/aaa-unused.js',
66+
'app/src/fixtures/unused.js',
67+
'app/src/tooling/unused.js',
68+
'app/src/dist/unused.js',
5169
'app/node_modules/@devup-ui/tooling/index.js',
5270
'app/node_modules/@devup-ui/fixture/dist/unused.js',
5371
])
@@ -64,6 +82,7 @@ it.each([false, true])(
6482
),
6583
)
6684
const expected = [main, tokens, rank, reached, dist, page].sort()
85+
const reservedExpected = [...expected, unused, rootOnly].sort()
6786
const seeds: string[][] = []
6887
const completed: string[][] = []
6988
const original = NonphysicalModules.prototype.extract
@@ -120,6 +139,7 @@ it.each([false, true])(
120139
expect(js).toContain(rule?.[1] ?? 'missing-class')
121140
}
122141
expect(css).not.toContain('z-index:99')
142+
expect(css).not.toContain('z-index:88')
123143
expect(js).not.toContain('@devup-ui/react')
124144
const roots = [...new Set(direct.mock.calls.map(([, id]) => id))].sort()
125145
const returns = recursive.mock.calls.flatMap(([, result]) => {
@@ -160,13 +180,13 @@ it.each([false, true])(
160180
stylingAndRecursion: 'passed',
161181
}),
162182
)
163-
expect(reserved).toEqual(expected)
164-
expect(seeds[0]).toEqual(expected)
183+
expect(reserved).toEqual(reservedExpected)
184+
expect(seeds[0]).toEqual(reservedExpected)
165185
const numbers: unknown = JSON.parse(wasm.exportFileMap())
166186
if (numbers === null || typeof numbers !== 'object')
167187
throw new TypeError('Expected real numbering object')
168188
expect(Object.getOwnPropertyDescriptor(numbers, page)?.value).toBe(
169-
expected.filter((id) => id < page).length,
189+
reservedExpected.filter((id) => id < page).length,
170190
)
171191
for (const id of negatives)
172192
expect(Object.getOwnPropertyDescriptor(numbers, id)).toBeUndefined()

‎packages/vite-plugin/src/__tests__/production-manifest.test.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,9 @@ it('reserves all configured contexts while keeping scan authority separate from
126126
'app/src/docs.mdx',
127127
'# Reserved documentation',
128128
)
129-
const accepted: string[] = []
130-
const imports = ["import './imports.js';"]
131-
const rejected = [entry, plain, markdown]
129+
const accepted: string[] = [markdown]
130+
const imports = ["import './imports.js'; import './docs.mdx';"]
131+
const rejected = [entry, plain]
132132
for (const name of ['included', 'excluded'])
133133
await fixture.file(
134134
`app/node_modules/${name}/package.json`,

0 commit comments

Comments
 (0)