Skip to content

Commit

Permalink
[chore] improved typing on core library (#1993)
Browse files Browse the repository at this point in the history
  • Loading branch information
benmccann committed Jul 22, 2021
1 parent 3240c77 commit 69b92ec
Show file tree
Hide file tree
Showing 14 changed files with 369 additions and 323 deletions.
5 changes: 5 additions & 0 deletions .changeset/sixty-rice-cough.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': patch
---

[chore] improved typing on core library
2 changes: 1 addition & 1 deletion packages/kit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"@rollup/plugin-replace": "^2.4.2",
"@types/amphtml-validator": "^1.0.1",
"@types/cookie": "^0.4.0",
"@types/globrex": "^0.1.0",
"@types/globrex": "^0.1.1",
"@types/marked": "^2.0.2",
"@types/mime": "^2.0.3",
"@types/node": "^14.14.43",
Expand Down
5 changes: 4 additions & 1 deletion packages/kit/src/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ async function get_config() {
/** @param {Error} error */
function handle_error(error) {
console.log(colors.bold().red(`> ${error.message}`));
console.log(colors.gray(error.stack));
if (error.stack) {
console.log(colors.gray(error.stack));
}
process.exit(1);
}

Expand Down Expand Up @@ -229,6 +231,7 @@ function welcome({ port, host, https, open }) {
const exposed = host !== 'localhost' && host !== '127.0.0.1';

Object.values(networkInterfaces()).forEach((interfaces) => {
if (!interfaces) return;
interfaces.forEach((details) => {
if (details.family !== 'IPv4') return;

Expand Down
22 changes: 10 additions & 12 deletions packages/kit/src/core/adapt/prerender.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { readFileSync, writeFileSync } from 'fs';
import { dirname, join, resolve as resolve_path } from 'path';
import { parse, pathToFileURL, resolve } from 'url';
import { pathToFileURL, resolve, URL } from 'url';
import { mkdirp } from '../filesystem/index.js';
import { __fetch_polyfill } from '../../install-fetch.js';
import { SVELTE_KIT } from '../constants.js';
Expand Down Expand Up @@ -54,7 +54,7 @@ const REDIRECT = 3;
* log: import('types/internal').Logger;
* config: import('types/config').ValidatedConfig;
* build_data: import('types/internal').BuildData;
* fallback: string;
* fallback?: string;
* all: boolean; // disregard `export const prerender = true`
* }} opts */
export async function prerender({ cwd, out, log, config, build_data, fallback, all }) {
Expand All @@ -75,7 +75,7 @@ export async function prerender({ cwd, out, log, config, build_data, fallback, a
read: (file) => readFileSync(join(config.kit.files.assets, file))
});

/** @type {(status: number, path: string, parent: string, verb: string) => void} */
/** @type {(status: number, path: string, parent: string | null, verb: string) => void} */
const error = config.kit.prerender.force
? (status, path, parent, verb) => {
log.error(`${status} ${path}${parent ? ` (${verb} from ${parent})` : ''}`);
Expand Down Expand Up @@ -107,7 +107,7 @@ export async function prerender({ cwd, out, log, config, build_data, fallback, a

/**
* @param {string} path
* @param {string} parent
* @param {string?} parent
*/
async function visit(path, parent) {
path = normalize(path);
Expand All @@ -129,7 +129,6 @@ export async function prerender({ cwd, out, log, config, build_data, fallback, a
},
{
prerender: {
fallback: null,
all,
dependencies
}
Expand Down Expand Up @@ -161,7 +160,7 @@ export async function prerender({ cwd, out, log, config, build_data, fallback, a

if (rendered.status === 200) {
log.info(`${rendered.status} ${path}`);
writeFileSync(file, rendered.body);
writeFileSync(file, rendered.body || '');
} else if (response_type !== OK) {
error(rendered.status, path, parent, 'linked');
}
Expand All @@ -179,7 +178,7 @@ export async function prerender({ cwd, out, log, config, build_data, fallback, a
const file = `${out}${parts.join('/')}`;
mkdirp(dirname(file));

writeFileSync(file, result.body);
if (result.body) writeFileSync(file, result.body);

if (response_type === OK) {
log.info(`${result.status} ${dependency_path}`);
Expand Down Expand Up @@ -216,12 +215,12 @@ export async function prerender({ cwd, out, log, config, build_data, fallback, a
const resolved = resolve(path, href);
if (resolved[0] !== '/') continue;

const parsed = parse(resolved);
const parsed = new URL(resolved, 'http://localhost');

const file = parsed.pathname.replace(config.kit.paths.assets, '').slice(1);
if (files.has(file)) continue;

if (parsed.query) {
if (parsed.search) {
// TODO warn that query strings have no effect on statically-exported pages
}

Expand Down Expand Up @@ -254,14 +253,13 @@ export async function prerender({ cwd, out, log, config, build_data, fallback, a
{
prerender: {
fallback,
all: false,
dependencies: null
all: false
}
}
);

const file = join(out, fallback);
mkdirp(dirname(file));
writeFileSync(file, rendered.body);
writeFileSync(file, rendered.body || '');
}
}
12 changes: 6 additions & 6 deletions packages/kit/src/core/build/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export async function build(config, { cwd = process.cwd(), runtime = '@sveltejs/
server,
static: options.manifest.assets.map((asset) => posixify(asset.file)),
entries: options.manifest.routes
.map((route) => route.type === 'page' && route.path)
.map((route) => (route.type === 'page' ? route.path : ''))
.filter(Boolean)
};
}
Expand All @@ -87,7 +87,7 @@ export async function build(config, { cwd = process.cwd(), runtime = '@sveltejs/
* build_dir: string;
* output_dir: string;
* client_entry_file: string;
* service_worker_entry_file: string;
* service_worker_entry_file: string | null;
* }} options
*/
async function build_client({
Expand Down Expand Up @@ -199,7 +199,7 @@ async function build_client({
* build_dir: string;
* output_dir: string;
* client_entry_file: string;
* service_worker_entry_file: string;
* service_worker_entry_file: string | null;
* }} options
* @param {ClientManifest} client_manifest
* @param {string} runtime
Expand All @@ -219,7 +219,7 @@ async function build_server(
runtime
) {
let hooks_file = resolve_entry(config.kit.files.hooks);
if (!fs.existsSync(hooks_file)) {
if (!hooks_file || !fs.existsSync(hooks_file)) {
hooks_file = path.resolve(cwd, `${SVELTE_KIT}/build/hooks.js`);
fs.writeFileSync(hooks_file, '');
}
Expand Down Expand Up @@ -271,7 +271,7 @@ async function build_server(
const resolved = `${output_dir}/client/${config.kit.appDir}/${url}`;
return fs.readFileSync(resolved, 'utf-8');
})
: null;
: [];

metadata_lookup[file] = {
entry: prefix + client_manifest[file].file,
Expand Down Expand Up @@ -493,7 +493,7 @@ async function build_server(
* build_dir: string;
* output_dir: string;
* client_entry_file: string;
* service_worker_entry_file: string;
* service_worker_entry_file: string | null;
* }} options
* @param {ClientManifest} client_manifest
*/
Expand Down
2 changes: 1 addition & 1 deletion packages/kit/src/core/config/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ const options = {
};

/**
* @param {string} string
* @param {string | null} string
* @param {boolean} allow_empty
* @returns {ConfigDefinition}
*/
Expand Down
148 changes: 73 additions & 75 deletions packages/kit/src/core/create_manifest_data/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,77 +92,74 @@ export default function create_manifest_data({ config, output, cwd = process.cwd
* @param {string} dir
* @param {Part[][]} parent_segments
* @param {string[]} parent_params
* @param {string[]} layout_stack // accumulated __layout.svelte components
* @param {string[]} error_stack // accumulated __error.svelte components
* @param {Array<string|undefined>} layout_stack // accumulated __layout.svelte components
* @param {Array<string|undefined>} error_stack // accumulated __error.svelte components
*/
function walk(dir, parent_segments, parent_params, layout_stack, error_stack) {
/** @type {Item[]} */
const items = fs
.readdirSync(dir)
.map((basename) => {
const resolved = path.join(dir, basename);
const file = posixify(path.relative(cwd, resolved));
const is_dir = fs.statSync(resolved).isDirectory();

const ext =
config.extensions.find((ext) => basename.endsWith(ext)) || path.extname(basename);

const name = ext ? basename.slice(0, -ext.length) : basename;

// TODO remove this after a while
['layout', 'layout.reset', 'error'].forEach((reserved) => {
if (name === `$${reserved}`) {
const prefix = posixify(path.relative(cwd, dir));
const bad = `${prefix}/$${reserved}${ext}`;
const good = `${prefix}/__${reserved}${ext}`;

throw new Error(`${bad} should be renamed ${good}`);
}
});
let items = [];
fs.readdirSync(dir).forEach((basename) => {
const resolved = path.join(dir, basename);
const file = posixify(path.relative(cwd, resolved));
const is_dir = fs.statSync(resolved).isDirectory();

if (name[0] === '_') {
if (name[1] === '_' && !specials.has(name)) {
throw new Error(`Files and directories prefixed with __ are reserved (saw ${file})`);
}
const ext = config.extensions.find((ext) => basename.endsWith(ext)) || path.extname(basename);

return null;
}
const name = ext ? basename.slice(0, -ext.length) : basename;

if (basename[0] === '.' && basename !== '.well-known') return null;
if (!is_dir && !/^(\.[a-z0-9]+)+$/i.test(ext)) return null; // filter out tmp files etc
// TODO remove this after a while
['layout', 'layout.reset', 'error'].forEach((reserved) => {
if (name === `$${reserved}`) {
const prefix = posixify(path.relative(cwd, dir));
const bad = `${prefix}/$${reserved}${ext}`;
const good = `${prefix}/__${reserved}${ext}`;

const segment = is_dir ? basename : name;

if (/\]\[/.test(segment)) {
throw new Error(`Invalid route ${file} — parameters must be separated`);
throw new Error(`${bad} should be renamed ${good}`);
}
});

if (count_occurrences('[', segment) !== count_occurrences(']', segment)) {
throw new Error(`Invalid route ${file} — brackets are unbalanced`);
if (name[0] === '_') {
if (name[1] === '_' && !specials.has(name)) {
throw new Error(`Files and directories prefixed with __ are reserved (saw ${file})`);
}

if (/.+\[\.\.\.[^\]]+\]/.test(segment) || /\[\.\.\.[^\]]+\].+/.test(segment)) {
throw new Error(`Invalid route ${file} — rest parameter must be a standalone segment`);
}
return;
}

if (basename[0] === '.' && basename !== '.well-known') return null;
if (!is_dir && !/^(\.[a-z0-9]+)+$/i.test(ext)) return null; // filter out tmp files etc

const parts = get_parts(segment, file);
const is_index = is_dir ? false : basename.startsWith('index.');
const is_page = config.extensions.indexOf(ext) !== -1;
const route_suffix = basename.slice(basename.indexOf('.'), -ext.length);

return {
basename,
ext,
parts,
file: posixify(file),
is_dir,
is_index,
is_page,
route_suffix
};
})
.filter(Boolean)
.sort(comparator);
const segment = is_dir ? basename : name;

if (/\]\[/.test(segment)) {
throw new Error(`Invalid route ${file} — parameters must be separated`);
}

if (count_occurrences('[', segment) !== count_occurrences(']', segment)) {
throw new Error(`Invalid route ${file} — brackets are unbalanced`);
}

if (/.+\[\.\.\.[^\]]+\]/.test(segment) || /\[\.\.\.[^\]]+\].+/.test(segment)) {
throw new Error(`Invalid route ${file} — rest parameter must be a standalone segment`);
}

const parts = get_parts(segment, file);
const is_index = is_dir ? false : basename.startsWith('index.');
const is_page = config.extensions.indexOf(ext) !== -1;
const route_suffix = basename.slice(basename.indexOf('.'), -ext.length);

items.push({
basename,
ext,
parts,
file: posixify(file),
is_dir,
is_index,
is_page,
route_suffix
});
});
items = items.sort(comparator);

items.forEach((item) => {
const segments = parent_segments.slice();
Expand Down Expand Up @@ -356,25 +353,26 @@ function comparator(a, b) {
* @param {string} file
*/
function get_parts(part, file) {
return part
.split(/\[(.+?\(.+?\)|.+?)\]/)
.map((str, i) => {
if (!str) return null;
const dynamic = i % 2 === 1;
/** @type {Part[]} */
const result = [];
part.split(/\[(.+?\(.+?\)|.+?)\]/).map((str, i) => {
if (!str) return;
const dynamic = i % 2 === 1;

const [, content] = dynamic ? /([^(]+)$/.exec(str) : [null, str];
const [, content] = dynamic ? /([^(]+)$/.exec(str) || [null, null] : [null, str];

if (dynamic && !/^(\.\.\.)?[a-zA-Z0-9_$]+$/.test(content)) {
throw new Error(`Invalid route ${file} — parameter name must match /^[a-zA-Z0-9_$]+$/`);
}
if (!content || (dynamic && !/^(\.\.\.)?[a-zA-Z0-9_$]+$/.test(content))) {
throw new Error(`Invalid route ${file} — parameter name must match /^[a-zA-Z0-9_$]+$/`);
}

return {
content,
dynamic,
spread: dynamic && /^\.{3}.+$/.test(content)
};
})
.filter(Boolean);
result.push({
content,
dynamic,
spread: dynamic && /^\.{3}.+$/.test(content)
});
});

return result;
}

/**
Expand Down

0 comments on commit 69b92ec

Please sign in to comment.