diff --git a/.changeset/brave-paws-cheer.md b/.changeset/brave-paws-cheer.md new file mode 100644 index 000000000000..a72752892ca4 --- /dev/null +++ b/.changeset/brave-paws-cheer.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': minor +--- + +feat: add warning for mistyped route filenames diff --git a/packages/kit/src/core/sync/create_manifest_data/index.js b/packages/kit/src/core/sync/create_manifest_data/index.js index 06426dad5655..d5f8dd1cde6a 100644 --- a/packages/kit/src/core/sync/create_manifest_data/index.js +++ b/packages/kit/src/core/sync/create_manifest_data/index.js @@ -1,5 +1,6 @@ import fs from 'node:fs'; import path from 'node:path'; +import colors from 'kleur'; import mime from 'mime'; import { list_files, runtime_directory } from '../../utils.js'; import { posixify } from '../../../utils/filesystem.js'; @@ -201,8 +202,31 @@ function create_routes_and_nodes(cwd, config, fallback) { // process files first for (const file of files) { if (file.is_dir) continue; - if (!file.name.startsWith('+')) continue; - if (!valid_extensions.find((ext) => file.name.endsWith(ext))) continue; + + const ext = valid_extensions.find((ext) => file.name.endsWith(ext)); + if (!ext) continue; + + if (!file.name.startsWith('+')) { + const name = file.name.slice(0, -ext.length); + // check if it is a valid route filename but missing the + prefix + const typo = + /^(?:(page(?:@(.*))?)|(layout(?:@(.*))?)|(error))$/.test(name) || + /^(?:(server)|(page(?:(@[a-zA-Z0-9_-]*))?(\.server)?)|(layout(?:(@[a-zA-Z0-9_-]*))?(\.server)?))$/.test( + name + ); + if (typo) { + console.log( + colors + .bold() + .yellow( + `Missing route file prefix. Did you mean +${file.name}?` + + ` at ${path.join(dir, file.name)}` + ) + ); + } + + continue; + } if (file.name.endsWith('.d.ts')) { let name = file.name.slice(0, -5); diff --git a/packages/kit/src/core/sync/write_client_manifest.js b/packages/kit/src/core/sync/write_client_manifest.js index 623dbf468f0f..7e65baf2caf4 100644 --- a/packages/kit/src/core/sync/write_client_manifest.js +++ b/packages/kit/src/core/sync/write_client_manifest.js @@ -1,6 +1,8 @@ +import path from 'node:path'; import { relative_path, resolve_entry } from '../../utils/filesystem.js'; import { s } from '../../utils/misc.js'; import { dedent, write_if_changed } from './utils.js'; +import colors from 'kleur'; /** * Writes the client manifest to disk. The manifest is used to power the router. It contains the @@ -108,6 +110,18 @@ export function write_client_manifest(kit, manifest_data, output, metadata) { const hooks_file = resolve_entry(kit.files.hooks.client); + const typo = resolve_entry('src/+hooks.client'); + if (typo) { + console.log( + colors + .bold() + .yellow( + `Unexpected + prefix. Did you mean ${typo.split('/').at(-1)?.slice(1)}?` + + ` at ${path.resolve(typo)}` + ) + ); + } + write_if_changed( `${output}/app.js`, dedent` diff --git a/packages/kit/src/core/sync/write_server.js b/packages/kit/src/core/sync/write_server.js index 71ff99aac3c5..976417f504f7 100644 --- a/packages/kit/src/core/sync/write_server.js +++ b/packages/kit/src/core/sync/write_server.js @@ -1,4 +1,3 @@ -import fs from 'node:fs'; import path from 'node:path'; import { hash } from '../../runtime/hash.js'; import { posixify, resolve_entry } from '../../utils/filesystem.js'; @@ -6,6 +5,7 @@ import { s } from '../../utils/misc.js'; import { load_error_page, load_template } from '../config/index.js'; import { runtime_directory } from '../utils.js'; import { write_if_changed } from './utils.js'; +import colors from 'kleur'; /** * @param {{ @@ -76,8 +76,19 @@ export { set_assets, set_building, set_private_env, set_public_env }; * @param {string} output */ export function write_server(config, output) { - // TODO the casting shouldn't be necessary — investigate - const hooks_file = /** @type {string} */ (resolve_entry(config.kit.files.hooks.server)); + const hooks_file = resolve_entry(config.kit.files.hooks.server); + + 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) { @@ -88,7 +99,7 @@ export function write_server(config, output) { `${output}/server/internal.js`, server_template({ config, - hooks: fs.existsSync(hooks_file) ? relative(hooks_file) : null, + hooks: hooks_file ? relative(hooks_file) : null, has_service_worker: config.kit.serviceWorker.register && !!resolve_entry(config.kit.files.serviceWorker), runtime_directory: relative(runtime_directory),