Skip to content

hooks files are "skipped" if a folder with the same name exists #13100

@paoloricciuti

Description

@paoloricciuti

Describe the bug

If you have a hooks.server.ts or hooks.ts and you create a folder with the same name (hooks.server or more commonly hooks) the respective file will be "ignored" during the server generation.

This is because here

export function write_server(config, output) {
const server_hooks_file = resolve_entry(config.kit.files.hooks.server);
const universal_hooks_file = resolve_entry(config.kit.files.hooks.universal);
const typo = resolve_entry('src/+hooks.server');
if (typo) {
console.log(
colors
.bold()
.yellow(
`Unexpected + prefix. Did you mean ${typo.split('/').at(-1)?.slice(1)}?` +
` at ${path.resolve(typo)}`
)
);
}
/** @param {string} file */
function relative(file) {
return posixify(path.relative(`${output}/server`, file));
}
write_if_changed(
`${output}/server/internal.js`,
server_template({
config,
server_hooks: server_hooks_file ? relative(server_hooks_file) : null,
universal_hooks: universal_hooks_file ? relative(universal_hooks_file) : null,
has_service_worker:
config.kit.serviceWorker.register && !!resolve_entry(config.kit.files.serviceWorker),
runtime_directory: relative(runtime_directory),
template: load_template(process.cwd(), config),
error_page: load_error_page(config)
})
);
}

we call resolve_entry with config.kit.files.hooks.server and config.kit.files.hooks.universal which by default are src/hooks.server and src/hooks. However inside resolve_entry we check if it's a directory and if it's a directory we resolve index on that directory

export function resolve_entry(entry) {
if (fs.existsSync(entry)) {
const stats = fs.statSync(entry);
if (stats.isDirectory()) {
return resolve_entry(path.join(entry, 'index'));
}
return entry;
} else {
const dir = path.dirname(entry);
if (fs.existsSync(dir)) {
const base = path.basename(entry);
const files = fs.readdirSync(dir);
const found = files.find((file) => file.replace(/\.(js|ts)$/, '') === base);
if (found) return path.join(dir, found);
}
}
return null;
}

What we should do is probably check also for the file and if there's a file AND a directory give precedence to the file.

Reproduction

  1. go here
  2. check that only the hooks.server.ts handle function is logging to the terminal
  3. delete the hooks folder
  4. check that now also the reroute function is logging to the console
  5. optionally create a folder named hooks.server (you need to refresh the page for it to take fully effect...bug in sveltelab sorry 😅)
  6. check that now no hook is logged

Logs

No response

System Info

System:
    OS: Linux 5.0 undefined
    CPU: (8) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 0 Bytes / 0 Bytes
    Shell: 1.0 - /bin/jsh
  Binaries:
    Node: 18.20.3 - /usr/local/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 10.2.3 - /usr/local/bin/npm
    pnpm: 8.15.6 - /usr/local/bin/pnpm
  npmPackages:
    @sveltejs/adapter-auto: ^3.0.0 => 3.3.1 
    @sveltejs/kit: ^2.5.27 => 2.9.0 
    @sveltejs/vite-plugin-svelte: ^4.0.0 => 4.0.2 
    svelte: ^5.0.0 => 5.4.0 
    vite: ^5.4.4 => 5.4.11

Severity

serious, but I can work around it

Additional Information

This can be very hard to debug.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions