CLI • API

sv

On this page

sv exposes a programmatic API for creating projects and running add-ons.

defineAddon

Creates an add-on definition. See create your own for a full guide.

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

export default defineAddon({
	id: 'my-addon',
	options: defineAddonOptions().build(),

	// called before run - declare dependencies, environment requirements, and dynamic options
	setup: ({ dependsOn, unsupported, addOption, isKit }) => {
		if (!isKit) unsupported('Requires SvelteKit');
		dependsOn('eslint');

		// dynamically add options based on workspace state or fetched data
		addOption('theme', {
			question: 'Which theme?',
			type: 'select',
			default: 'dark',
			options: [{ value: 'dark' }, { value: 'light' }]
		});
	},

	// the actual work — add files, edit files, declare dependencies
	run: ({ sv, options, cancel }) => {
		// add a dependency
		sv.devDependency('my-lib', '^1.0.0');

		// create or edit files using transforms from @sveltejs/sv-utils
		sv.file('src/lib/foo.ts', (content) => {
			return 'export const foo = true;';
		});

		sv.file(
			'src/routes/+page.svelte',
			transforms.svelte(({ ast, svelte }) => {
				svelte.addFragment(ast, '<p>Hello!</p>');
			})
		);

		// cancel at any point if something is wrong
		// cancel('reason');
	},

	// displayed after the add-on runs
	nextSteps: ({ options }) => ['Run `npm run dev` to get started']
});

The sv object in run provides file, dependency, devDependency, and execute. For file transforms (AST-based editing of scripts, Svelte components, CSS, JSON, etc.) and package manager helpers, see @sveltejs/sv-utils.

Typed dynamic options

If your add-on adds options dynamically in setup (e.g. from a fetch), you can pass a type parameter to defineAddon to get strong typing for those options:

import { defineAddon, defineAddonOptions } from 'sv';
// cut
const addon = defineAddon<{ theme: string }>()({
	id: 'my-addon',
	options: defineAddonOptions().build(),
	setup: ({ addOption }) => {
		addOption('theme', {
			question: 'Which theme?',
			type: 'string',
			default: 'dark'
		});
	},
	run: ({ options }) => {
		options.theme; // string
	}
});

The type parameter maps value types (boolean, string, number) to question definitions. Without it, defineAddon stays strict and only allows statically defined options.

defineAddonOptions

Builder for add-on options. Chained with .add() and finalized with .build().

import { defineAddonOptions } from 'sv';

const options = defineAddonOptions()
	.add('database', {
		question: 'Which database?',
		type: 'select',
		default: 'postgresql',
		options: [
			{ value: 'postgresql' },
			{ value: 'mysql' },
			{ value: 'sqlite' }
		]
	})
	.add('docker', {
		question: 'Add a docker-compose file?',
		type: 'boolean',
		default: false,
		// only ask when database is not sqlite
		condition: (opts) => opts.database !== 'sqlite'
	})
	.build();

Options are asked in order. The condition callback receives the answers collected so far — return false to skip the question (its value will be undefined).

create

Programmatically create a new Svelte project.

import { create } from 'sv';

create({
	cwd: './my-app',
	name: 'my-app',
	template: 'minimal',
	types: 'typescript'
});

add

Programmatically run add-ons against an existing project.

import { add, officialAddons } from 'sv';

await add({
	cwd: './my-app',
	addons: { prettier: officialAddons.prettier },
	options: { prettier: {} },
	packageManager: 'npm'
});