The untrack()/persistAndProcess() pair was a per-function convention:
each update function had to remember both, a forgotten untrack would let
calling effects subscribe to input state (the bug fixed in 6a9a306e),
and a forgotten persistAndProcess would silently skip persistence and
re-validation. A single update(mutate) gateway now makes both structural,
and the scattered untrack calls (three of which were dead) are gone.
Also:
- Export inputState as Readonly<State> so writes outside the update
functions are type errors instead of comment violations.
- Share the 'codeStore' key as a constant instead of two literals.
- Reuse validatedStateOf() in processState instead of duplicating the
validated-state defaults.
- Use $state.raw for validatedCurrent: it is only ever replaced
wholesale, so deep proxying every published state was pure overhead.
The new state.svelte.test.ts pins the invariants: update functions never
make a calling effect track input state, and every mutation persists.
Vitest needed resolve.conditions=['browser'] for those tests — it was
loading Svelte's server build, where $effect is a no-op.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
57 lines
1.6 KiB
JavaScript
57 lines
1.6 KiB
JavaScript
import tailwindcss from '@tailwindcss/vite';
|
|
import { sveltekit } from '@sveltejs/kit/vite';
|
|
import { FileSystemIconLoader } from 'unplugin-icons/loaders';
|
|
import Icons from 'unplugin-icons/vite';
|
|
import { defineConfig } from 'vite';
|
|
import devtoolsJson from 'vite-plugin-devtools-json';
|
|
|
|
/**
|
|
* HMR creates state inconsistencies, so we always reload the page.
|
|
* @type {import('vite').PluginOption} PluginOption
|
|
*/
|
|
const alwaysFullReload = {
|
|
name: 'always-full-reload',
|
|
handleHotUpdate({ server }) {
|
|
server.ws.send({ type: 'full-reload' });
|
|
return [];
|
|
}
|
|
};
|
|
|
|
export default defineConfig({
|
|
plugins: [
|
|
tailwindcss(),
|
|
sveltekit(),
|
|
Icons({
|
|
compiler: 'svelte',
|
|
customCollections: {
|
|
custom: FileSystemIconLoader('./static/icons')
|
|
}
|
|
}),
|
|
alwaysFullReload,
|
|
devtoolsJson()
|
|
],
|
|
envPrefix: 'MERMAID_',
|
|
server: { port: 3000, host: true },
|
|
preview: { port: 3000, host: true },
|
|
// Vitest otherwise resolves Svelte's server build, where $effect is a no-op.
|
|
resolve: process.env.VITEST ? { conditions: ['browser'] } : undefined,
|
|
test: {
|
|
environment: 'jsdom',
|
|
// in-source testing
|
|
includeSource: ['src/**/*.{js,ts,svelte}'],
|
|
// Ignore E2E tests
|
|
exclude: [
|
|
'tests/**/*',
|
|
'**/node_modules/**',
|
|
'**/dist/**',
|
|
'**/.{idea,git,cache,output,temp}/**',
|
|
'**/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build,eslint,prettier}.config.*'
|
|
],
|
|
setupFiles: ['./src/tests/setup.ts'],
|
|
coverage: {
|
|
exclude: ['src/mocks', '.svelte-kit', 'src/**/*.test.ts'],
|
|
reporter: ['text', 'json', 'html', 'lcov']
|
|
}
|
|
}
|
|
});
|