Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,5 @@
"linked": [],
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": ["community-addon-template"]
"updateInternalDependencies": "patch"
}
4 changes: 0 additions & 4 deletions community-addon-template/.gitignore

This file was deleted.

33 changes: 0 additions & 33 deletions community-addon-template/src/index.js

This file was deleted.

34 changes: 0 additions & 34 deletions community-addon-template/tests/custom-addon.test.ts

This file was deleted.

5 changes: 0 additions & 5 deletions community-addon-template/tests/fixtures/+page.svelte

This file was deleted.

5 changes: 0 additions & 5 deletions community-addon-template/tests/fixtures/App.svelte

This file was deleted.

1 change: 1 addition & 0 deletions documentation/docs/20-commands/10-sv-create.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Which project template to use:
- `minimal` — barebones scaffolding for your new app
- `demo` — showcase app with a word guessing game that works without JavaScript
- `library` — template for a Svelte library, set up with `svelte-package`
- `addon` — template for a community add-on, ready to be tested & published

### `--types <option>`

Expand Down
3 changes: 1 addition & 2 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ export default [
'packages/sv/lib/create/scripts/**/*',
'packages/sv/lib/create/templates/**/*',
'packages/sv/lib/cli/tests/snapshots/*',
'packages/sv/lib/**/tests/**/{output,input}.ts',
'community-addon-template/tests/*'
'packages/sv/lib/**/tests/**/{output,input}.ts'
]
}
];
3 changes: 1 addition & 2 deletions packages/sv/lib/addons/_tests/_setup/global.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { fileURLToPath } from 'node:url';
import { setup, type ProjectVariant } from 'sv/testing';
import { setup, variants, type ProjectVariant } from '../../../testing.ts';
import type { TestProject } from 'vitest/node';
import process from 'node:process';
import { exec } from 'tinyexec';

const TEST_DIR = fileURLToPath(new URL('../../../../.test-output/addons/', import.meta.url));
const variants: ProjectVariant[] = ['kit-js', 'kit-ts', 'vite-js', 'vite-ts'];
const CI = Boolean(process.env.CI);

export default async function ({ provide }: TestProject) {
Expand Down
16 changes: 9 additions & 7 deletions packages/sv/lib/cli/add/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ export const add = new Command('add')
.option('--no-git-check', 'even if some files are dirty, no prompt will be shown')
.option('--no-install', 'skip installing dependencies')
.addOption(installOption)
//.option('--community [add-on...]', 'community addons to install')
// TODO JYC: remove the flag
.option('--community [add-on...]', 'community addons to install')
.configureHelp({
...common.helpConfig,
formatHelp(cmd, helper) {
Expand Down Expand Up @@ -580,7 +581,7 @@ export async function runAddonsApply({
workspace,
addonSetupResults,
addons: addonMap,
options: answersOfficial
options: { ...answersOfficial, ...answersCommunity }
});

const addonSuccess: string[] = [];
Expand Down Expand Up @@ -847,11 +848,12 @@ async function resolveCommunityAddons(cwd: string, community: string[]) {
});
p.log.message(packageInfos.join('\n'));

const confirm = await p.confirm({ message: 'Would you like to continue?' });
if (confirm !== true) {
p.cancel('Operation cancelled.');
process.exit(1);
}
// TODO JYC: remove for testing for now
// const confirm = await p.confirm({ message: 'Would you like to continue?' });
// if (confirm !== true) {
// p.cancel('Operation cancelled.');
// process.exit(1);
// }

start('Downloading community add-on packages');
const details = await Promise.all(pkgs.map(async (opts) => downloadPackage(opts)));
Expand Down
11 changes: 6 additions & 5 deletions packages/sv/lib/cli/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,9 @@ async function createProject(cwd: ProjectPath, options: Options) {
options: templates.map((t) => ({ label: t.title, value: t.name, hint: t.description }))
});
},
language: () => {
language: (o) => {
if (options.types) return Promise.resolve(options.types);
if (o.results.template === 'addon') return Promise.resolve('none');
return p.select<LanguageType>({
message: 'Add type checking with TypeScript?',
initialValue: 'typescript',
Expand Down Expand Up @@ -218,10 +219,10 @@ async function createProject(cwd: ProjectPath, options: Options) {
const workspace = await createVirtualWorkspace({
cwd: projectPath,
template,
type: language
type: language as LanguageType
});

if (options.addOns || options.add.length > 0) {
if (options.template !== 'addon' && (options.addOns || options.add.length > 0)) {
const addons = options.add.reduce(addonArgsHandler, []);
sanitizedAddonsMap = sanitizeAddons(addons).reduce<Record<string, string[] | undefined>>(
(acc, curr) => {
Expand Down Expand Up @@ -251,7 +252,7 @@ async function createProject(cwd: ProjectPath, options: Options) {
createKit(projectPath, {
name: projectName,
template,
types: language
types: language as LanguageType
});

if (options.fromPlayground) {
Expand All @@ -263,7 +264,7 @@ async function createProject(cwd: ProjectPath, options: Options) {
let addOnNextSteps: string[] = [];
let argsFormattedAddons: string[] = [];
let addOnFilesToFormat: string[] = [];
if (options.addOns || options.add.length > 0) {
if (options.template !== 'addon' && (options.addOns || options.add.length > 0)) {
const {
nextSteps,
argsFormattedAddons: argsFormatted,
Expand Down
43 changes: 36 additions & 7 deletions packages/sv/lib/cli/tests/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import fs from 'node:fs';
import { parseJson } from '../../core/tooling/index.ts';

const monoRepoPath = path.resolve(__dirname, '..', '..', '..', '..', '..');
const svBinPath = path.resolve(monoRepoPath, 'packages', 'sv', 'dist', 'bin.mjs');

beforeAll(() => {
const testOutputCliPath = path.resolve(monoRepoPath, '.test-output', 'cli');
Expand Down Expand Up @@ -36,15 +37,19 @@ describe('cli', () => {
'mcp=ide:claude-code,cursor,gemini,opencode,vscode,other+setup:local'
// 'storybook' // No storybook addon during tests!
]
},
{
projectName: 'hello',
template: 'addon',
args: ['--no-add-ons']
}
];

it.for(testCases)(
'should create a new project with name $projectName',
{ timeout: 10_000 },
{ timeout: 40_000 },
async (testCase) => {
const { projectName, args } = testCase;
const svBinPath = path.resolve(monoRepoPath, 'packages', 'sv', 'dist', 'bin.mjs');
const { projectName, args, template = 'minimal' } = testCase;
const testOutputPath = path.resolve(monoRepoPath, '.test-output', 'cli', projectName);

const result = await exec(
Expand All @@ -54,17 +59,16 @@ describe('cli', () => {
'create',
testOutputPath,
'--template',
'minimal',
'--types',
'ts',
template,
...(template === 'addon' ? ['--no-types'] : ['--types', 'ts']),
'--no-install',
...args
],
{ nodeOptions: { stdio: 'pipe' } }
);

// cli finished well
expect(result.exitCode).toBe(0);
expect(result.exitCode, `Error with cli: '${result.stderr}'`).toBe(0);

// test output path exists
expect(fs.existsSync(testOutputPath)).toBe(true);
Expand Down Expand Up @@ -105,6 +109,31 @@ describe('cli', () => {
`file "${relativeFile}" does not match snapshot`
);
}

if (template === 'addon') {
// replace sv version in package.json for tests
const packageJsonPath = path.resolve(testOutputPath, 'package.json');
const packageJson = parseJson(fs.readFileSync(packageJsonPath, 'utf-8'));
packageJson.dependencies['sv'] = 'file:../../../packages/sv';
fs.writeFileSync(
packageJsonPath,
JSON.stringify(packageJson, null, 3).replaceAll(' ', '\t')
);

const cmds = [
// list of cmds to test
['i'],
['run', 'demo-create'],
['run', 'demo-add'],
['run', 'test']
];
for (const cmd of cmds) {
const res = await exec('npm', cmd, {
nodeOptions: { stdio: 'pipe', cwd: testOutputPath }
});
expect(res.exitCode, `Error addon test: '${cmd}' -> ${res.stderr}`).toBe(0);
}
}
}
);
});
26 changes: 26 additions & 0 deletions packages/sv/lib/cli/tests/snapshots/hello/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
node_modules
demo/

# Output
.output
.vercel
.netlify
.wrangler
/.svelte-kit
/build
/dist

# OS
.DS_Store
Thumbs.db

# Env
.env
.env.*
!.env.example
!.env.test

# Vite
vite.config.js.timestamp-*
vite.config.ts.timestamp-*

Original file line number Diff line number Diff line change
@@ -1,21 +1,14 @@
# community-addon-template
# sv community addon: hello

> [!IMPORTANT]
> Community add-ons are currently not supported. Please see [#184](https://github.com/sveltejs/cli/issues/184) for details.

> [!IMPORTANT]
> This template's dependencies may not be up-to-date; be sure to update them to the latest!
> If you get stuck, check out the [implementations of official add-ons](https://github.com/sveltejs/cli/tree/main/packages/add-ons).

The add-on template for community add-ons for [`sv`](https://github.com/sveltejs/cli).
> If you get stuck, check out the [implementations of official add-ons](https://github.com/sveltejs/cli/tree/main/packages/addons).

## Cloning the template

Use [`degit`](https://github.com/Rich-Harris/degit) to clone the template:

```shell
npx degit sveltejs/cli/community-addon-template addon-name
```
created with [`sv`](https://svelte.dev/docs/cli/sv-create#Options-template-name).

## Using the add-on

Expand All @@ -24,15 +17,15 @@ To run the add-on, we'll first need a project to apply it to.
Create the project with the following script:

```shell
npm run create-temp
npm run demo-create
```

This will create a SvelteKit project in the `temp` directory.
This will create a SvelteKit project in the `demo` directory.

To execute the add-on, run:

```shell
npm start
npm run demo-add
```

## Sharing your add-on
Expand All @@ -48,11 +41,9 @@ Your published add-on can now be used by anyone!
To execute the newly published package with `sv`, run:

```shell
npx sv add --community npm:addon-package-name
npx sv add npm:hello
```

After that, feel free to open a pull request to [`sv`](https://github.com/sveltejs/cli) and add your add-on to the [community list](/community-addons/).

## Things to be aware of

Community add-ons are **not permitted** to have any external dependencies outside of `sv`. If the use of a dependency is absolutely necessary, then they can be bundled using a bundler of your choosing (e.g. Rollup, Rolldown, tsup, etc.).
Loading
Loading