Skip to content
5 changes: 5 additions & 0 deletions .changeset/brown-peas-shop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"sv": patch
---

chore: don't select `devtools-json` by default
25 changes: 19 additions & 6 deletions documentation/docs/30-add-ons/60-devtools-json.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,26 @@
title: devtools-json
---

`devtools-json` is essentially a vite plugin [vite-plugin-devtools-json](https://github.com/ChromeDevTools/vite-plugin-devtools-json/) for generating the Chrome DevTools project settings file on-the-fly in the devserver.
The `devtools-json` add-on installs [`vite-plugin-devtools-json`](https://github.com/ChromeDevTools/vite-plugin-devtools-json/), which is a Vite plugin for generating a Chromium DevTools project settings file on-the-fly in the development server. This file is served from `/.well-known/appspecific/com.chrome.devtools.json` and tells Chromium browsers where your project's source code lives so that you can use [the workspaces feature](https://developer.chrome.com/docs/devtools/workspaces) to edit source files in the browser.

It will prevent this server log:
> [!NOTE]
> Installing the plugin enables the feature for all users connecting to the dev server with a Chromium browser, and allows the browser to read and write all files within the directory. If using Chrome's AI Assistance feature, this may also result in data being sent to Google.

```sh
Not found: /.well-known/appspecific/com.chrome.devtools.json
```
You can prevent the request from being issued on your machine by disabling the feature in your browser. You can do this in Chrome by visiting `chrome://flags` and disabling the "DevTools Project Settings". You may also be interested in disabling "DevTools Automatic Workspace Folders" since it’s closely related.

You can also prevent the web server from issuing a notice regarding the incoming request for all developers of your application by handling the request yourself. For example, you can create a file named `.well-known/appspecific/com.chrome.devtools.json` with the contents `"Go away, Chrome DevTools!"` or you can add logic to respond to the request in your [`handle`](https://svelte.dev/docs/kit/hooks#Server-hooks-handle) hook:

```js
/// file: src/hooks.server.js
import { dev } from '$app/environment';

export function handle({ event, resolve }) {
if (dev && event.url.pathname === '/.well-known/appspecific/com.chrome.devtools.json') {
return new Response(undefined, { status: 404 });
}

return resolve(event);
}

## Usage

Expand All @@ -18,4 +31,4 @@ npx sv add devtools-json

## What you get

- the `vite` plugin added to your vite plugin options.
- `vite-plugin-devtools-json` added to your Vite plugin options
7 changes: 0 additions & 7 deletions packages/addons/devtools-json/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,6 @@ export default defineAddon({
homepage: 'https://github.com/ChromeDevTools/vite-plugin-devtools-json',
options: {},

setup: ({ defaultSelection }) => {
defaultSelection({
create: true,
add: false
});
},

run: ({ sv, typescript }) => {
const ext = typescript ? 'ts' : 'js';

Expand Down
13 changes: 3 additions & 10 deletions packages/cli/commands/add/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,16 +201,15 @@ export const add = new Command('add')

common.runCommand(async () => {
const selectedAddonIds = selectedAddons.map(({ id }) => id);
const { nextSteps } = await runAddCommand(options, selectedAddonIds, 'add');
const { nextSteps } = await runAddCommand(options, selectedAddonIds);
if (nextSteps) p.note(nextSteps, 'Next steps', { format: (line: string) => line });
});
});

type SelectedAddon = { type: 'official' | 'community'; addon: AddonWithoutExplicitArgs };
export async function runAddCommand(
options: Options,
selectedAddonIds: string[],
from: 'create' | 'add'
selectedAddonIds: string[]
): Promise<{ nextSteps?: string; packageManager?: AgentName | null }> {
const selectedAddons: SelectedAddon[] = selectedAddonIds.map((id) => ({
type: 'official',
Expand Down Expand Up @@ -391,11 +390,6 @@ export async function runAddCommand(
const setups = selectedAddons.length ? selectedAddons.map(({ addon }) => addon) : officialAddons;
const addonSetupResults = setupAddons(setups, workspace);

// get all addons that have been marked to be preselected
const initialValues = Object.entries(addonSetupResults)
.filter(([_, value]) => value.defaultSelection[from] === true)
.map(([key]) => key);

// prompt which addons to apply
if (selectedAddons.length === 0) {
const addonOptions = officialAddons
Expand All @@ -410,8 +404,7 @@ export async function runAddCommand(
const selected = await p.multiselect({
message: `What would you like to add to your project? ${pc.dim('(use arrow keys / space bar)')}`,
options: addonOptions,
required: false,
initialValues
required: false
});
if (p.isCancel(selected)) {
p.cancel('Operation cancelled.');
Expand Down
3 changes: 1 addition & 2 deletions packages/cli/commands/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,7 @@ async function createProject(cwd: ProjectPath, options: Options) {
community: [],
addons: {}
},
[],
'create'
[]
);
packageManager = pm;
addOnNextSteps = nextSteps;
Expand Down
8 changes: 2 additions & 6 deletions packages/cli/lib/install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,7 @@ export function setupAddons(
const setupResult: AddonSetupResult = {
unsupported: [],
dependsOn: [],
runsAfter: [],
defaultSelection: { create: false, add: false }
runsAfter: []
};
addon.setup?.({
...workspace,
Expand All @@ -100,10 +99,7 @@ export function setupAddons(
setupResult.runsAfter.push(name);
},
unsupported: (reason) => setupResult.unsupported.push(reason),
runsAfter: (name) => setupResult.runsAfter.push(name),
defaultSelection: (defaultSelection) => {
setupResult.defaultSelection = defaultSelection;
}
runsAfter: (name) => setupResult.runsAfter.push(name)
});
addonSetupResults[addon.id] = setupResult;
}
Expand Down
8 changes: 1 addition & 7 deletions packages/core/addon/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ export type Addon<Args extends OptionDefinition> = {
dependsOn: (name: string) => void;
unsupported: (reason: string) => void;
runsAfter: (addonName: string) => void;
defaultSelection: (args: { create: boolean; add: boolean }) => void;
}
) => MaybePromise<void>;
run: (workspace: Workspace<Args> & { sv: SvApi }) => MaybePromise<void>;
Expand All @@ -61,12 +60,7 @@ export function defineAddon<Args extends OptionDefinition>(config: Addon<Args>):
return config;
}

export type AddonSetupResult = {
dependsOn: string[];
unsupported: string[];
runsAfter: string[];
defaultSelection: { create: boolean; add: boolean };
};
export type AddonSetupResult = { dependsOn: string[]; unsupported: string[]; runsAfter: string[] };

export type AddonWithoutExplicitArgs = Addon<Record<string, Question>>;
export type AddonConfigWithoutExplicitArgs = Addon<Record<string, Question>>;
Expand Down