Skip to main content

sv

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 { 
const transforms: {
    script(cb: (file: {
        ast: Program;
        comments: Comments;
        content: string;
        js: typeof index_d_exports$3;
    }) => void | false, options?: TransformOptions): (content: string) => string;
    svelte(cb: (file: {
        ast: AST.Root;
        content: string;
        svelte: typeof index_d_exports$4;
        js: typeof index_d_exports$3;
    }) => void | false, options?: TransformOptions): (content: string) => string;
    ... 6 more ...;
    text(cb: (file: {
        content: string;
        text: typeof text_d_exports;
    }) => string | false): TransformFn;
}

File transform primitives that know their format.

sv-utils = what to do to content, sv = where and when to do it.

Each transform wraps: parse -> callback({ast/data, utils}) -> generateCode(). The parser choice is baked into the transform type - you can't accidentally parse a vite config as svelte because you never call a parser yourself.

Transforms are curried: call with the callback to get a (content: string) => string function that plugs directly into sv.file().

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

// use with sv.file() - curried form plugs in directly
sv.file(files.viteConfig, transforms.script(({ ast, js }) => {
  js.vite.addPlugin(ast, { code: 'kitRoutes()' });
}));

// standalone usage / testing
const result = transforms.script(({ ast, js }) => {
  js.imports.addDefault(ast, { as: 'foo', from: 'foo' });
})(fileContent);
transforms
} from '@sveltejs/sv-utils';
import { function defineAddon<const Id extends string, Args extends OptionDefinition>(config: Addon<Args, Id>): Addon<Args, Id>

The entry point for your addon, It will hold every thing! (options, setup, run, nextSteps, ...)

defineAddon
, function defineAddonOptions(): OptionBuilder<{}>

Options for an addon.

Will be prompted to the user if there are not answered by args when calling the cli.

const options = defineAddonOptions()
  .add('demo', {
	question: `demo? ${color.optional('(a cool one!)')}`
	type: string | boolean | number | select | multiselect,
	default: true,
  })
  .build();

To define by args, you can do

npx sv add <addon>=<option1>:<value1>+<option2>:<value2>
defineAddonOptions
} from 'sv';
export default defineAddon<"my-addon", {}>(config: Addon<{}, "my-addon">): Addon<{}, "my-addon">

The entry point for your addon, It will hold every thing! (options, setup, run, nextSteps, ...)

defineAddon
({
id: "my-addon"id: 'my-addon', options: {}options: function defineAddonOptions(): OptionBuilder<{}>

Options for an addon.

Will be prompted to the user if there are not answered by args when calling the cli.

const options = defineAddonOptions()
  .add('demo', {
	question: `demo? ${color.optional('(a cool one!)')}`
	type: string | boolean | number | select | multiselect,
	default: true,
  })
  .build();

To define by args, you can do

npx sv add <addon>=<option1>:<value1>+<option2>:<value2>
defineAddonOptions
().function build(): {}build(),
// called before run — declare dependencies and environment requirements
setup?: ((workspace: Workspace & {
    dependsOn: (name: keyof OfficialAddons) => void;
    unsupported: (reason: string) => void;
    runsAfter: (name: keyof OfficialAddons) => void;
}) => MaybePromise<...>) | undefined
setup
: ({ dependsOn: (name: keyof OfficialAddons) => void

On what official addons does this addon depend on?

dependsOn
, unsupported: (reason: string) => void

Why is this addon not supported?

unsupported
, isKit: booleanisKit }) => {
if (!isKit: booleanisKit) unsupported: (reason: string) => void

Why is this addon not supported?

unsupported
('Requires SvelteKit');
dependsOn: (name: keyof OfficialAddons) => void

On what official addons does this addon depend on?

dependsOn
('eslint');
}, // the actual work — add files, edit files, declare dependencies
run: (workspace: Workspace & {
    options: OptionValues<{}>;
    sv: SvApi;
    cancel: (reason: string) => void;
}) => MaybePromise<void>
run
: ({ sv: SvApisv, options: OptionValues<{}>

Add-on options

options
, cancel: (reason: string) => void

Cancel the addon at any time!

cancel
}) => {
// add a dependency sv: SvApisv.devDependency: (pkg: string, version: string) => voiddevDependency('my-lib', '^1.0.0'); // create or edit files using transforms from @sveltejs/sv-utils sv: SvApisv.file: (path: string, edit: (content: string) => string | false) => void

Edit a file in the workspace. (will create it if it doesn't exist)

Return false from the callback to abort - the original content is returned unchanged.

file
('src/lib/foo.ts', (content: stringcontent) => {
return 'export const foo = true;'; }); sv: SvApisv.file: (path: string, edit: (content: string) => string | false) => void

Edit a file in the workspace. (will create it if it doesn't exist)

Return false from the callback to abort - the original content is returned unchanged.

file
(
'src/routes/+page.svelte',
const transforms: {
    script(cb: (file: {
        ast: Program;
        comments: Comments;
        content: string;
        js: typeof index_d_exports$3;
    }) => void | false, options?: TransformOptions): (content: string) => string;
    svelte(cb: (file: {
        ast: AST.Root;
        content: string;
        svelte: typeof index_d_exports$4;
        js: typeof index_d_exports$3;
    }) => void | false, options?: TransformOptions): (content: string) => string;
    ... 6 more ...;
    text(cb: (file: {
        content: string;
        text: typeof text_d_exports;
    }) => string | false): TransformFn;
}

File transform primitives that know their format.

sv-utils = what to do to content, sv = where and when to do it.

Each transform wraps: parse -> callback({ast/data, utils}) -> generateCode(). The parser choice is baked into the transform type - you can't accidentally parse a vite config as svelte because you never call a parser yourself.

Transforms are curried: call with the callback to get a (content: string) => string function that plugs directly into sv.file().

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

// use with sv.file() - curried form plugs in directly
sv.file(files.viteConfig, transforms.script(({ ast, js }) => {
  js.vite.addPlugin(ast, { code: 'kitRoutes()' });
}));

// standalone usage / testing
const result = transforms.script(({ ast, js }) => {
  js.imports.addDefault(ast, { as: 'foo', from: 'foo' });
})(fileContent);
transforms
.
function svelte(cb: (file: {
    ast: AST.Root;
    content: string;
    svelte: typeof index_d_exports$4;
    js: typeof index_d_exports$3;
}) => void | false, options?: TransformOptions): (content: string) => string

Transform a Svelte component file.

Return false from the callback to abort - the original content is returned unchanged.

svelte
(({ ast: AST.Rootast, svelte: typeof index_d_exports$4svelte }) => {
svelte: typeof index_d_exports$4svelte.
index_d_exports$4.addFragment(ast: AST.Root, content: string, options?: {
    mode?: "append" | "prepend";
}): void
export index_d_exports$4.addFragment
addFragment
(ast: AST.Rootast, '<p>Hello!</p>');
}) ); // cancel at any point if something is wrong // cancel('reason'); }, // displayed after the add-on runs
nextSteps?: ((workspace: Workspace & {
    options: OptionValues<{}>;
}) => string[]) | undefined
nextSteps
: ({ options: OptionValues<{}>options }) => ['Run `npm run dev` to get started']
});

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

defineAddonOptions

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

import { function defineAddonOptions(): OptionBuilder<{}>

Options for an addon.

Will be prompted to the user if there are not answered by args when calling the cli.

const options = defineAddonOptions()
  .add('demo', {
	question: `demo? ${color.optional('(a cool one!)')}`
	type: string | boolean | number | select | multiselect,
	default: true,
  })
  .build();

To define by args, you can do

npx sv add <addon>=<option1>:<value1>+<option2>:<value2>
defineAddonOptions
} from 'sv';
const
const options: {
    database: {
        readonly question: "Which database?";
        readonly type: "select";
        readonly default: "postgresql";
        readonly options: [{
            readonly value: "postgresql";
        }, {
            readonly value: "mysql";
        }, {
            readonly value: "sqlite";
        }];
    };
    docker: {
        readonly question: "Add a docker-compose file?";
        readonly type: "boolean";
        readonly default: false;
        readonly condition: (opts: OptionValues<Record<"database", {
            readonly question: "Which database?";
            readonly type: "select";
            readonly default: "postgresql";
            readonly options: [{
                readonly value: "postgresql";
            }, {
                readonly value: "mysql";
            }, {
                readonly value: "sqlite";
            }];
        }> & Record<...>>) => boolean;
    };
}
options
= function defineAddonOptions(): OptionBuilder<{}>

Options for an addon.

Will be prompted to the user if there are not answered by args when calling the cli.

const options = defineAddonOptions()
  .add('demo', {
	question: `demo? ${color.optional('(a cool one!)')}`
	type: string | boolean | number | select | multiselect,
	default: true,
  })
  .build();

To define by args, you can do

npx sv add <addon>=<option1>:<value1>+<option2>:<value2>
defineAddonOptions
()
.
add<"database", {
    readonly question: "Which database?";
    readonly type: "select";
    readonly default: "postgresql";
    readonly options: [{
        readonly value: "postgresql";
    }, {
        readonly value: "mysql";
    }, {
        readonly value: "sqlite";
    }];
}>(key: "database", question: {
    readonly question: "Which database?";
    readonly type: "select";
    readonly default: "postgresql";
    readonly options: [{
        readonly value: "postgresql";
    }, {
        readonly value: "mysql";
    }, {
        readonly value: "sqlite";
    }];
}): OptionBuilder<Record<"database", {
    readonly question: "Which database?";
    readonly type: "select";
    readonly default: "postgresql";
    readonly options: [{
        readonly value: "postgresql";
    }, {
        readonly value: "mysql";
    }, {
        readonly value: "sqlite";
    }];
}>>

This type is a bit complex, but in usage, it's quite simple!

The idea is to add() options one by one, with the key and the question.

  .add('demo', {
	question: 'Do you want to add a demo?',
	type: 'boolean',  // string, number, select, multiselect
	default: true,
	// condition: (o) => o.previousOption === 'ok',
  })
add
('database', {
question: "Which database?"question: 'Which database?', type: "select"type: 'select', default: "postgresql"default: 'postgresql',
options: [{
    readonly value: "postgresql";
}, {
    readonly value: "mysql";
}, {
    readonly value: "sqlite";
}]
options
: [
{ value: "postgresql"value: 'postgresql' }, { value: "mysql"value: 'mysql' }, { value: "sqlite"value: 'sqlite' } ] }) .
add<"docker", {
    readonly question: "Add a docker-compose file?";
    readonly type: "boolean";
    readonly default: false;
    readonly condition: (opts: OptionValues<Record<"database", {
        readonly question: "Which database?";
        readonly type: "select";
        readonly default: "postgresql";
        readonly options: [{
            readonly value: "postgresql";
        }, {
            readonly value: "mysql";
        }, {
            readonly value: "sqlite";
        }];
    }> & Record<"docker", any>>) => boolean;
}>(key: "docker", question: {
    readonly question: "Add a docker-compose file?";
    readonly type: "boolean";
    readonly default: false;
    readonly condition: (opts: OptionValues<Record<"database", {
        readonly question: "Which database?";
        readonly type: "select";
        readonly default: "postgresql";
        readonly options: [{
            readonly value: "postgresql";
        }, {
            readonly value: "mysql";
        }, {
            readonly value: "sqlite";
        }];
    }> & Record<"docker", any>>) => boolean;
}): OptionBuilder<...>

This type is a bit complex, but in usage, it's quite simple!

The idea is to add() options one by one, with the key and the question.

  .add('demo', {
	question: 'Do you want to add a demo?',
	type: 'boolean',  // string, number, select, multiselect
	default: true,
	// condition: (o) => o.previousOption === 'ok',
  })
add
('docker', {
question: "Add a docker-compose file?"question: 'Add a docker-compose file?', type: "boolean"type: 'boolean', default: falsedefault: false, // only ask when database is not sqlite
condition: (opts: OptionValues<Record<"database", {
    readonly question: "Which database?";
    readonly type: "select";
    readonly default: "postgresql";
    readonly options: [{
        readonly value: "postgresql";
    }, {
        readonly value: "mysql";
    }, {
        readonly value: "sqlite";
    }];
}> & Record<"docker", any>>) => boolean
condition
: (
opts: OptionValues<Record<"database", {
    readonly question: "Which database?";
    readonly type: "select";
    readonly default: "postgresql";
    readonly options: [{
        readonly value: "postgresql";
    }, {
        readonly value: "mysql";
    }, {
        readonly value: "sqlite";
    }];
}> & Record<"docker", any>>
opts
) =>
opts: OptionValues<Record<"database", {
    readonly question: "Which database?";
    readonly type: "select";
    readonly default: "postgresql";
    readonly options: [{
        readonly value: "postgresql";
    }, {
        readonly value: "mysql";
    }, {
        readonly value: "sqlite";
    }];
}> & Record<"docker", any>>
opts
.database: "postgresql" | "mysql" | "sqlite"database !== 'sqlite'
}) .
function build(): {
    database: {
        readonly question: "Which database?";
        readonly type: "select";
        readonly default: "postgresql";
        readonly options: [{
            readonly value: "postgresql";
        }, {
            readonly value: "mysql";
        }, {
            readonly value: "sqlite";
        }];
    };
    docker: {
        readonly question: "Add a docker-compose file?";
        readonly type: "boolean";
        readonly default: false;
        readonly condition: (opts: OptionValues<Record<"database", {
            readonly question: "Which database?";
            readonly type: "select";
            readonly default: "postgresql";
            readonly options: [{
                readonly value: "postgresql";
            }, {
                readonly value: "mysql";
            }, {
                readonly value: "sqlite";
            }];
        }> & Record<...>>) => boolean;
    };
}
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 { function create(cwd: string, options: Options): voidcreate } from 'sv';

function create(cwd: string, options: Options): voidcreate('./my-app', {
	name: stringname: 'my-app',
	template: "minimal" | "demo" | "library" | "addon" | "svelte"template: 'minimal',
	types: "typescript" | "checkjs" | "none"types: 'typescript'
});

add

Programmatically run add-ons against an existing project.

import { 
function add<Addons extends AddonMap>({ addons, cwd, options, packageManager }: InstallOptions<Addons>): Promise<ReturnType<({ loadedAddons, workspace, setupResults, options }: ApplyAddonOptions) => Promise<{
    filesToFormat: string[];
    pnpmBuildDependencies: string[];
    status: Record<string, string[] | "success">;
}>>>
add
, const officialAddons: OfficialAddonsofficialAddons } from 'sv';
await
add<{
    prettier: Addon<any, string>;
}>({ addons, cwd, options, packageManager }: InstallOptions<{
    prettier: Addon<any, string>;
}>): Promise<ReturnType<({ loadedAddons, workspace, setupResults, options }: ApplyAddonOptions) => Promise<{
    filesToFormat: string[];
    pnpmBuildDependencies: string[];
    status: Record<string, string[] | "success">;
}>>>
add
({
cwd: stringcwd: './my-app',
addons: {
    prettier: Addon<any, string>;
}
addons
: { prettier: Addon<any, string>prettier: const officialAddons: OfficialAddonsofficialAddons.prettier: Addon<any, string>prettier },
options: OptionMap<{
    prettier: Addon<any, string>;
}>
options
: { prettier: {}prettier: {} },
packageManager?: AgentName | undefinedpackageManager: 'npm' });

Modifier cette page sur Github llms.txt

précédent suivant