Skip to main content

sv-utils

Le paquet @sveltejs/sv-utils est actuellement expérimental. Son API peut encore évoluer.

Le paquet @sveltejs/sv-utils est un utilitaire d’add-on pour parser, transformer, et générer du code dans les add-ons.

npm install -D @sveltejs/sv-utils

transforms

transforms est une collection de fonction conscientes des parsers vous permettant de modifier les fichiers via un AST. Elle accepte un callback. La valeur de retour est conçue pour être passée directement à sv.file(). Le choix du parser est inclus dans le type de transformation — vous ne pouvez pas parser accidentellement une configuration Vite en tant que fichier Svelte, car vous n’appelez jamais un parser vous-même.

Chaque transformation injecte les utilitaires pertinents dans le callback, de sorte que vous n’avez besoin que d’un import :

import { transforms } from '@sveltejs/sv-utils';

transforms.script(/* ... */);
transforms.svelte(/* ... */);
// ...

transforms.script

Transforme un fichier JavaScript/TypeScript. Le callback reçoit { ast, comments, content, js }.

import { transforms } from '@sveltejs/sv-utils';

sv.file(
	file.viteConfig,
	transforms.script(({ ast, js }) => {
		js.imports.addDefault(ast, { as: 'foo', from: 'foo' });
		js.vite.addPlugin(ast, { code: 'foo()' });
	})
);

transforms.svelte

Transforme un composant Svelte. Le callback reçoit { ast, content, svelte, js }.

import { transforms } from '@sveltejs/sv-utils';

sv.file(
	layoutPath,
	transforms.svelte(({ ast, svelte }) => {
		svelte.addFragment(ast, '<Foo />');
	})
);

transforms.svelteScript

Transforme un composant Svelte avec un bloc <script> garanti. Passez { language } en tant que premier argument. Le callback reçoit { ast, content, svelte, js } où ast.instance est toujours non nul.

import { transforms } from '@sveltejs/sv-utils';

sv.file(
	layoutPath,
	transforms.svelteScript({ language: 'ts' }, ({ ast, svelte, js }) => {
		js.imports.addDefault(ast.instance.content, { as: 'Foo', from: './Foo.svelte' });
		svelte.addFragment(ast, '<Foo />');
	})
);

transforms.css

Transforme une fichier CSS. Le callback reçoit { ast, content, css }.

import { transforms } from '@sveltejs/sv-utils';

sv.file(
	file.stylesheet,
	transforms.css(({ ast, css }) => {
		css.addAtRule(ast, { name: 'import', params: "'tailwindcss'" });
	})
);

transforms.json

Transforme un fichier JSON. Mute l’objet data directement. Le callback reçoit { data, content, json }.

import { transforms } from '@sveltejs/sv-utils';

sv.file(
	file.typeConfig,
	transforms.json(({ data }) => {
		data.compilerOptions ??= {};
		data.compilerOptions.strict = true;
	})
);

transforms.yaml / transforms.toml

Similaire à transforms.json, pour les fichiers YAML et TOML, respectivement. Le callback reçoit { data, content }.

transforms.text

Transforme un fichier texte brut (.env, .gitignore, etc.). Aucun parser — une string en entrée, une string en sortie. Le callback reçoit { content, text }.

import { transforms } from '@sveltejs/sv-utils';

sv.file(
	'.env',
	transforms.text(({ content }) => {
		return content + '\nDATABASE_URL="file:local.db"';
	})
);

Annuler une transformation

Renvoyez false depuis n’importe quel callback pour annuler la transformation — le contenu original est renvoyé inchangé.

import { transforms } from '@sveltejs/sv-utils';

sv.file(
	'eslint.config.js',
	transforms.script(({ ast, js }) => {
		const { value: existing } = js.exports.createDefault(ast, { fallback: myConfig });
		if (existing !== myConfig) {
			// la configuration existe déjà, on n'y touche pas
			return false;
		}
		// ... on continue de modifier l'ast
	})
);

Usage standalone & tests

Les transformations sont des fonctions curry — appelez-les avec un callback, puis appliquez-les sur votre contenu :

import { transforms } from '@sveltejs/sv-utils';

const transform = transforms.script(({ ast, js }) => {
	js.imports.addDefault(ast, { as: 'foo', from: 'foo' });
});
const result = transform('export default {}');

Composabilité

Pour les cas nécessitant d’utiliser à la fois des transformations et des éditions brutes, utilisez sv.file avec un callback de contenu, puis invoquer la transformation curryfiée manuellement :

sv.file(path, (content) => {
	// curryfication
	const transform = transforms.script(({ ast, js }) => {
		js.imports.addDefault(ast, { as: 'foo', from: 'bar' });
	});

	// manipulation du parser
	content = transform(content);

	// manipulation brute de string
	content = content.replace('foo', 'baz');

	return content;
});

Les add-ons peuvent également exporter des fonctions de transformations réutilisables :

import { transforms } from '@sveltejs/sv-utils';

// ré-utilisable — exportez-la depuis votre paquet
export const addFooImport = transforms.svelte(({ ast, svelte, js }) => {
	svelte.ensureScript(ast, { language });
	js.imports.addDefault(ast.instance.content, { as: 'Foo', from: './Foo.svelte' });
});
sv.file('+page.svelte', addFooImport);
sv.file('index.svelte', addFooImport);

Parsers (bas-niveau)

transforms devrait convenir à la plupart des besoins (par ex. parsing conditionnel, gestion d’erreur autour du parser). Si ce n’est pas le cas pour vous, parse est une API bas-niveau à laquelle vous pouvez accéder :

import { parse } from '@sveltejs/sv-utils';

const { ast, generateCode } = parse.script(content);
const { ast, generateCode } = parse.svelte(content);
const { ast, generateCode } = parse.css(content);
const { data, generateCode } = parse.json(content);
const { data, generateCode } = parse.yaml(content);
const { data, generateCode } = parse.toml(content);
const { ast, generateCode } = parse.html(content);

Outillage de langage

Les utilitaires de namespace pour la manipulation d’AST :

  • js.* - imports, exports, objets, tableaux, variables, fonctions, utilitaires de configuration Vite, utilitaires SvelteKit
  • css.* - règles, déclarations, at-rules, imports
  • svelte.* - ensureScript, addSlot, addFragment
  • json.* - arrayUpsert, packageScriptsUpsert
  • html.* - manipulation d’attributs
  • text.* - insertion de lignes dans les fichiers bruts (.env, .gitignore)

Configuration de Svelte

La configuration de Svelte/kit peut se définir à deux endroits : directement fournie au plugin sveltekit() dans le fichier vite.config.{js,ts}, ou en tant qu’export par défaut dans un fichier séparé svelte.config.{js,ts}. Les projets créés par sv gardent leur configuration dans le fichier vite.config.js et ne fournissent pas de svelte.config.js.

svelteConfig permet au add-ons de lire et de modifier cette configuration peu importe sa position — l’argument sveltekit() dans vite.config.{js,ts}, ou l’export par défaut svelte.config.{js,ts} — sans avoir besoin de la connaître.

svelteConfig.edit

Vous gérez les options par nom, et l’utilitaire les écrit chacune au bon endroit, de sorte que vous n’avez pas besoin de gérer l’imbrication de kit vous-même. Les options se trouvant au niveau de Svelte (compilerOptions, preprocess, extensions, vitePlugin) se trouvent dans l’objet de configuration ; tout le reste (adapter, alias, files, typescript, …) est une option de SvelteKit, ce qui implique qu’elles sont aplaties dans l’argument de sveltekit() dans une configuration Vite, ou imbriqués sous kit dans un svelte.config.

import { svelteConfig } from '@sveltejs/sv-utils';

// dans le `run({ sv, cwd })` d'un add-on
svelteConfig.edit({ sv, cwd }, ({ ast, property, override, js }) => {
	// l'option du niveau svelte — récupère ou crée sa valeur, puis la mute sur place :
	js.array.append(property('extensions', { fallback: js.array.create() }), '.svx');

	// l'option kit — positionnée automatiquement, pas de gestion de l'étage `kit` :
	js.imports.addDefault(ast, { from: '@sveltejs/adapter-node', as: 'adapter' });
	override({
		adapter: js.functions.createCall({ name: 'adapter', args: [], useIdentifiers: true })
	});
});
  • property(name, { fallback }) — récupère ou crée la valeur d’une option pour ensuite la muter sur place (tableaux, objets imbriqués).
  • override(props, { dropLeadingComments }) — définit ou remplace des options dropLeadingComments supprime un commentaire considéré comme devenu inutile (par ex. la note sur adapter-auto lorsque vous changez d’adaptateur).

Cette méthode écrit dans sv.file, de sorte que la modification est suivi comme n’importe quelle autre. Si le projet n’a aucun fichier de configuration, un svelte.config.js est créé.

svelteConfig.find / svelteConfig.read

Les blocs de construction de plus bas niveau, les deux lisant des fichiers potentiels au travers d’un read(path) injecté (renvoie le contenu du fichier ou null) de sorte que la détection reste statique — la configuration n’est jamais exécutée :

  • svelteConfig.find(read) — renvoie { path, kind } ou null (kind vaut 'vite' ou 'svelte'; svelte.config gagne lorsque les deux sont présents).
  • svelteConfig.read(read) — localise et parse en une passe, renvoyant { location, config, kit } (les expressions de l’objet) ou null.

Utilitaires de gestion de paquets

pnpm.allowBuilds

Renvoie une transformation pour pnpm-workspace.yaml qui ajoute des paquets à la config “allow builds”. À utiliser avec sv.files lorsque le projet utilise pnpm.

L’utilitaire détecte la version de pnpm actuellement installée via pnpm --version :

  • pnpm >= 11: écrit dans la map unifiée allowBuilds ({ pkg: true }), en migrant toute liste onlyBuiltDependencies vers la map.
  • pnpm < 11: écrit dans la liste onlyBuiltDependencies legacy.
import { pnpm } from '@sveltejs/sv-utils';

if (packageManager === 'pnpm') {
	sv.file(file.findUp('pnpm-workspace.yaml'), pnpm.allowBuilds('my-native-dep'));
}

Modifier cette page sur Github llms.txt

précédent suivant