chore: use `@sveltejs/config` for options validation

config
Rich Harris 1 month ago
parent 98e8b635fa
commit 08e8163d89

@ -0,0 +1,5 @@
---
'svelte': patch
---
chore: use `@sveltejs/config` package for options validation

@ -170,6 +170,7 @@
"@jridgewell/remapping": "^2.3.4",
"@jridgewell/sourcemap-codec": "^1.5.0",
"@sveltejs/acorn-typescript": "^1.0.5",
"@sveltejs/config": "file:../../../config",
"@types/estree": "^1.0.5",
"@types/trusted-types": "^2.0.7",
"acorn": "^8.12.1",

@ -23,6 +23,7 @@ export { print } from './print/index.js';
export function compile(source, options) {
source = remove_bom(source);
state.reset({ warning: options.warningFilter, filename: options.filename });
const validated = validate_component_options(options, '');
let parsed = _parse(source);

@ -1,13 +1,9 @@
/** @import { Validator } from '@sveltejs/config/validate' */
/** @import { ModuleCompileOptions, ValidatedModuleCompileOptions, CompileOptions, ValidatedCompileOptions } from '#compiler' */
import { string, boolean, object, validator, ValidateError } from '@sveltejs/config/validate';
import * as e from './errors.js';
import * as w from './warnings.js';
/**
* @template [Input=any]
* @template [Output=Input]
* @typedef {(input: Input, keypath: string) => Required<Output>} Validator
*/
const common_options = {
filename: string('(unknown)'),
@ -27,7 +23,7 @@ const common_options = {
dev: boolean(false),
generate: validator('client', (input, keypath) => {
generate: validator(/** @type {string | false} */ ('client'), (input, keypath) => {
if (input === 'dom' || input === 'ssr') {
warn_once(w.options_renamed_ssr_dom);
return input === 'dom' ? 'client' : 'server';
@ -38,7 +34,7 @@ const common_options = {
throw_error(`${keypath} must be "client", "server" or false`);
}
return input;
return /** @type {'client' | 'server' | false} */ (input);
}),
warningFilter: fun(() => true),
@ -52,6 +48,7 @@ const component_options = {
accessors: deprecate(w.options_deprecated_accessors, boolean(false)),
css: validator('external', (input) => {
// @ts-expect-error
if (input === true || input === false) {
throw_error(
'The boolean options have been removed from the css option. Use "external" instead of false and "injected" instead of true'
@ -149,7 +146,7 @@ const component_options = {
)
};
export const validate_module_options =
const module_options_validator =
/** @type {Validator<ModuleCompileOptions, ValidatedModuleCompileOptions>} */ (
object({
...common_options,
@ -157,8 +154,8 @@ export const validate_module_options =
})
);
export const validate_component_options =
/** @type {Validator<CompileOptions, ValidatedCompileOptions>} */ (
const component_options_validator =
/** @type {Validator<CompileOptions, Omit<ValidatedCompileOptions, 'customElementOptions'>>} */ (
object({
...common_options,
...component_options
@ -166,8 +163,39 @@ export const validate_component_options =
);
/**
* @param {ModuleCompileOptions} options
*/
export function validate_module_options(options) {
try {
return module_options_validator(options);
} catch (e) {
if (e instanceof ValidateError) {
throw_error(e.message);
}
throw e;
}
}
/**
* @param {CompileOptions} options
*/
export function validate_component_options(options) {
try {
return component_options_validator(options);
} catch (e) {
if (e instanceof ValidateError) {
throw_error(e.message);
}
throw e;
}
}
/**
* @template T
* @param {string} msg
* @returns {Validator}
* @returns {Validator<T>}
*/
function removed(msg) {
return (input) => {
@ -189,8 +217,9 @@ function warn_once(fn) {
}
/**
* @template T
* @param {(node: null) => void} fn
* @returns {Validator}
* @returns {Validator<T>}
*/
function warn_removed(fn) {
return (input) => {
@ -200,9 +229,10 @@ function warn_removed(fn) {
}
/**
* @template T
* @param {(node: null) => void} fn
* @param {Validator} validator
* @returns {Validator}
* @param {Validator<T>} validator
* @returns {Validator<T>}
*/
function deprecate(fn, validator) {
return (input, keypath) => {
@ -212,84 +242,9 @@ function deprecate(fn, validator) {
}
/**
* @param {Record<string, Validator>} children
* @param {boolean} [allow_unknown]
* @returns {Validator}
*/
function object(children, allow_unknown = false) {
return (input, keypath) => {
/** @type {Record<string, any>} */
const output = {};
if ((input && typeof input !== 'object') || Array.isArray(input)) {
throw_error(`${keypath} should be an object`);
}
for (const key in input) {
if (!(key in children)) {
if (allow_unknown) {
output[key] = input[key];
} else {
e.options_unrecognised(null, `${keypath ? `${keypath}.${key}` : key}`);
}
}
}
for (const key in children) {
const validator = children[key];
output[key] = validator(input && input[key], keypath ? `${keypath}.${key}` : key);
}
return output;
};
}
/**
* @param {any} fallback
* @param {(value: any, keypath: string) => any} fn
* @returns {Validator}
*/
function validator(fallback, fn) {
return (input, keypath) => {
return input === undefined ? fallback : fn(input, keypath);
};
}
/**
* @param {string | undefined} fallback
* @param {boolean} allow_empty
* @returns {Validator}
*/
function string(fallback, allow_empty = true) {
return validator(fallback, (input, keypath) => {
if (typeof input !== 'string') {
throw_error(`${keypath} should be a string, if specified`);
}
if (!allow_empty && input === '') {
throw_error(`${keypath} cannot be empty`);
}
return input;
});
}
/**
* @param {boolean | undefined} fallback
* @returns {Validator}
*/
function boolean(fallback) {
return validator(fallback, (input, keypath) => {
if (typeof input !== 'boolean') {
throw_error(`${keypath} should be true or false, if specified`);
}
return input;
});
}
/**
* @param {Array<boolean | string | number>} options
* @returns {Validator}
* @template {boolean | string | number} T
* @param {T[]} options
* @returns {Validator<T>}
*/
function list(options, fallback = options[0]) {
return validator(fallback, (input, keypath) => {
@ -307,7 +262,7 @@ function list(options, fallback = options[0]) {
/**
* @param {(...args: any) => any} fallback
* @returns {Validator}
* @returns {Validator<(...args: any) => any>}
*/
function fun(fallback) {
return validator(fallback, (input, keypath) => {

@ -77,6 +77,9 @@ importers:
'@sveltejs/acorn-typescript':
specifier: ^1.0.5
version: 1.0.5(acorn@8.15.0)
'@sveltejs/config':
specifier: file:../../../config
version: file:../config
'@types/estree':
specifier: ^1.0.5
version: 1.0.8
@ -891,6 +894,9 @@ packages:
peerDependencies:
acorn: ^8.9.0
'@sveltejs/config@file:../config':
resolution: {directory: ../config, type: directory}
'@sveltejs/eslint-config@9.0.0':
resolution: {integrity: sha512-3u9VUYlU0Mc/8Bhc7eRAPgJuUBMaKHzoE8r50WrnVujoxBLW4zfPckR/BFGGNeVUh0F7QGAtxGkV/5pL6CE1Ng==}
peerDependencies:
@ -3167,6 +3173,8 @@ snapshots:
dependencies:
acorn: 8.15.0
'@sveltejs/config@file:../config': {}
'@sveltejs/eslint-config@9.0.0(@eslint/js@10.0.1(eslint@10.0.0))(@stylistic/eslint-plugin-js@1.8.0(eslint@10.0.0))(eslint-config-prettier@9.1.0(eslint@10.0.0))(eslint-plugin-n@17.24.0(eslint@10.0.0)(typescript@5.5.4))(eslint-plugin-svelte@3.15.0(eslint@10.0.0)(svelte@packages+svelte))(eslint@10.0.0)(typescript-eslint@8.56.0(eslint@10.0.0)(typescript@5.5.4))(typescript@5.5.4)':
dependencies:
'@eslint/js': 10.0.1(eslint@10.0.0)

Loading…
Cancel
Save