mirror of
https://github.com/vercel/workflow.git
synced 2026-09-14 19:59:43 +08:00
37ed0493e1
Instead of accessing private files from SvelteKit, we use @sveltejs/load-config to load the Svelte config (that package also knows about checking Vite config). The deadlock is avoided by having a module-level Set to see if we're currently recursing or not. This is necessary for SvelteKit 3 since there the config lives exclusively in the vite config, and the previous logic did not handle that. This also uncovered that we're needlessly rebuilding the generated files in sub builds/workers (SvelteKit, at least below 3, starts off secondary builds; and some things are done in workers), which a new file cache now checks. Picked from stable branch PR #3474 Signed-off-by: Simon Holthausen <simon.holthausen@vercel.com> Co-authored-by: Peter Wielander <mittgfu@gmail.com>
148 lines
4.4 KiB
TypeScript
148 lines
4.4 KiB
TypeScript
import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';
|
|
import { tmpdir } from 'node:os';
|
|
import { join } from 'node:path';
|
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
const mocks = vi.hoisted(() => ({
|
|
build: vi.fn<() => Promise<void>>(),
|
|
builderConfigs: [] as Array<Record<string, unknown>>,
|
|
loadConfig: vi.fn(),
|
|
}));
|
|
|
|
vi.mock('@sveltejs/load-config', () => ({
|
|
loadConfig: mocks.loadConfig,
|
|
}));
|
|
|
|
vi.mock('@workflow/builders', () => ({
|
|
createBuildQueue: () => (fn: () => Promise<void>) => fn(),
|
|
}));
|
|
|
|
vi.mock('@workflow/rollup', () => ({
|
|
workflowTransformPlugin: () => ({ name: 'workflow:transform' }),
|
|
}));
|
|
|
|
vi.mock('@workflow/vite', () => ({
|
|
workflowHotUpdatePlugin: () => ({ name: 'workflow:hot-update' }),
|
|
}));
|
|
|
|
vi.mock('./builder.js', () => ({
|
|
SvelteKitBuilder: class {
|
|
constructor(config: Record<string, unknown>) {
|
|
mocks.builderConfigs.push(config);
|
|
}
|
|
|
|
build = mocks.build;
|
|
},
|
|
}));
|
|
|
|
import { workflowPlugin } from './plugin.js';
|
|
|
|
const originalWorkingDir = process.cwd();
|
|
let workingDir: string;
|
|
|
|
beforeEach(async () => {
|
|
workingDir = await mkdtemp(join(tmpdir(), 'workflow-sveltekit-'));
|
|
process.chdir(workingDir);
|
|
workingDir = process.cwd(); // MacOS: resolves symlink of generated /var/folders/... through to /private/var/folders/...
|
|
mocks.build.mockResolvedValue(undefined);
|
|
});
|
|
|
|
afterEach(async () => {
|
|
process.chdir(originalWorkingDir);
|
|
await rm(workingDir, { force: true, recursive: true });
|
|
vi.clearAllMocks();
|
|
mocks.builderConfigs.length = 0;
|
|
});
|
|
|
|
describe('workflowPlugin', () => {
|
|
it('loads svelte.config.js directly and uses the default routes directory', async () => {
|
|
const configPath = join(workingDir, 'svelte.config.js');
|
|
await writeFile(configPath, 'export default {};');
|
|
mocks.loadConfig.mockResolvedValue({
|
|
config: {},
|
|
configFilePath: configPath,
|
|
configSource: 'svelte',
|
|
});
|
|
|
|
const [plugins] = workflowPlugin();
|
|
await plugins;
|
|
|
|
expect(mocks.loadConfig).toHaveBeenCalledWith(configPath, {
|
|
traverse: false,
|
|
});
|
|
expect(mocks.builderConfigs).toEqual([
|
|
{ routesDir: join(workingDir, 'src/routes'), workingDir },
|
|
]);
|
|
expect(mocks.build).toHaveBeenCalledOnce();
|
|
});
|
|
|
|
it('loads routes from the SvelteKit Vite plugin without recursing', async () => {
|
|
const routesDir = join(workingDir, 'app/routes');
|
|
let nestedPlugins: ReturnType<typeof workflowPlugin> | undefined;
|
|
mocks.loadConfig.mockImplementation(async () => {
|
|
nestedPlugins = workflowPlugin();
|
|
return {
|
|
config: { kit: { files: { routes: routesDir } } },
|
|
configFilePath: join(workingDir, 'vite.config.ts'),
|
|
configSource: 'vite',
|
|
};
|
|
});
|
|
|
|
const [plugins] = workflowPlugin();
|
|
await plugins;
|
|
|
|
expect(nestedPlugins).toEqual([]);
|
|
expect(mocks.loadConfig).toHaveBeenCalledWith(workingDir, {
|
|
traverse: false,
|
|
});
|
|
expect(mocks.builderConfigs).toEqual([{ routesDir, workingDir }]);
|
|
expect(mocks.build).toHaveBeenCalledOnce();
|
|
});
|
|
|
|
it('reuses routes generated by another Vite config context', async () => {
|
|
const routesDir = join(workingDir, 'app/routes');
|
|
await mkdir(join(workingDir, 'node_modules/.cache/workflow'), {
|
|
recursive: true,
|
|
});
|
|
await mkdir(join(routesDir, '.well-known/workflow/v1/flow'), {
|
|
recursive: true,
|
|
});
|
|
await writeFile(
|
|
join(workingDir, 'node_modules/.cache/workflow/sveltekit-build.json'),
|
|
JSON.stringify({ pid: process.pid, routesDir })
|
|
);
|
|
await writeFile(
|
|
join(routesDir, '.well-known/workflow/v1/flow/+server.js'),
|
|
''
|
|
);
|
|
|
|
const [plugins] = workflowPlugin();
|
|
await plugins;
|
|
|
|
expect(mocks.loadConfig).not.toHaveBeenCalled();
|
|
expect(mocks.builderConfigs).toEqual([{ routesDir, workingDir }]);
|
|
expect(mocks.build).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('passes source map options to the builder', async () => {
|
|
const configPath = join(workingDir, 'svelte.config.js');
|
|
await writeFile(configPath, 'export default {};');
|
|
mocks.loadConfig.mockResolvedValue({
|
|
config: {},
|
|
configFilePath: configPath,
|
|
configSource: 'svelte',
|
|
});
|
|
|
|
const [plugins] = workflowPlugin({ sourcemap: 'external' });
|
|
await plugins;
|
|
|
|
expect(mocks.builderConfigs).toEqual([
|
|
{
|
|
routesDir: join(workingDir, 'src/routes'),
|
|
workingDir,
|
|
sourcemap: 'external',
|
|
},
|
|
]);
|
|
});
|
|
});
|