Skip to content

feat: dedicated ide config command#13

Merged
stevensJourney merged 2 commits intomainfrom
feat-ide-config
Mar 4, 2026
Merged

feat: dedicated ide config command#13
stevensJourney merged 2 commits intomainfrom
feat-ide-config

Conversation

@stevensJourney
Copy link
Collaborator

Previously, IDE configuration was tucked away as a --vscode flag on the init cloud and init self-hosted commands. When a user scaffolded a new project they could optionally pass --vscode to have the CLI write a .vscode/settings.json that taught the YAML language server about the !env custom tag. It worked, but it was narrow: a one-shot flag buried in the scaffolding flow, only reachable at project creation time, and only aware of VSCode. If a user skipped it, or wanted to re-run it later, or used a different editor, there was no good path forward.

This PR improves IDE configuration. IDE configuration is promoted to a first-class, named command: powersync configure ide. Running it starts an interactive prompt that asks which IDE you are using, then applies the right configuration for that editor. For VSCode today, that means merging yaml.customTags into .vscode/settings.json, scanning the workspace for known PowerSync config files, and prepending yaml-language-server schema comments to any that are missing them — so schema validation and autocompletion light up immediately. It also prints a summary of what changed and recommends installing the Red Hat YAML extension.

Because the configurator for each IDE is registered as a simple function behind an IdeConfigurator type, adding support for other editors in the future is a matter of writing a new function and dropping it into the registry, no changes to the command itself required.

The --vscode flag has been removed from both init commands, and the old write-vscode-settings-for-yaml-env helper is deleted. In their place, the init output now surfaces a tip pointing users to powersync configure ide.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR promotes IDE configuration from a one-off --vscode init flag to a dedicated interactive command (powersync configure ide) that can be run at any time, and removes the old VSCode-specific helper/flag plumbing from the init flows.

Changes:

  • Added powersync configure ide command with an IDE configurator registry (currently VSCode).
  • Implemented VSCode configurator to merge yaml.customTags into .vscode/settings.json and prepend yaml-language-server schema comments to known config files.
  • Removed --vscode from powersync init cloud / powersync init self-hosted, and updated init output/docs to point users to the new command.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.

Show a summary per file
File Description
cli/src/commands/init/self-hosted.ts Removes --vscode flag usage and prints a tip for powersync configure ide.
cli/src/commands/init/cloud.ts Removes --vscode flag usage and prints a tip for powersync configure ide.
cli/src/commands/configure/index.ts Adds a (hidden) configure command entrypoint directing users to subcommands.
cli/src/commands/configure/ide.ts Adds interactive configure ide command, workspace scan, and configurator dispatch.
cli/src/api/write-vscode-settings-for-yaml-env.ts Deletes old VSCode settings writer helper.
cli/src/api/ide/configure-vscode-ide.ts Adds VSCode IDE configurator: settings merge + schema comment patching + guidance output.
cli/README.md Documents configure ide and removes --vscode from init command docs.
Comments suppressed due to low confidence (3)

cli/src/commands/configure/ide.ts:38

  • findLinkedProjectDirs only inspects immediate subdirectories of cwd, so running powersync configure ide from inside an existing PowerSync project (where cli.yaml is in the current directory) will produce projectDirs = [] and skip patching service.yaml/sync-config.yaml/cli.yaml in that project. Consider first checking whether cwd/cli.yaml is a valid PowerSync project and including cwd in the returned list (in addition to scanning subdirectories).
/**
 * Scans the current working directory for subdirectories that contain a valid
 * PowerSync cli.yaml. Returns their absolute paths.
 */
function findLinkedProjectDirs(cwd: string): string[] {
  const projectDirs: string[] = [];

  for (const entry of readdirSync(cwd)) {
    const entryPath = join(cwd, entry);
    try {
      if (!statSync(entryPath).isDirectory()) continue;
    } catch {
      continue;
    }

    try {
      const doc = parseYamlFile(join(entryPath, CLI_FILENAME));
      CLIConfig.decode(doc.contents?.toJSON());
      projectDirs.push(entryPath);
    } catch {
      // Not a valid PowerSync project — skip.
    }
  }

  return projectDirs;

cli/src/commands/configure/ide.ts:66

  • This command always prompts via @inquirer/prompts without a non-interactive fallback. In non-TTY contexts (CI, redirected stdin) inquirer prompts typically throw or hang; other commands in this repo guard prompts with process.stdin.isTTY. Consider adding a --ide flag (e.g. --ide=vscode) or, at minimum, detect !process.stdin.isTTY and print an actionable message / exit cleanly instead of prompting.
    const ide = await select({
      choices: [
        { name: 'VSCode', value: 'vscode' },
        { name: 'Exit', value: 'exit' }
      ],
      message: 'Select your IDE to configure (only VSCode is supported for now):'
    });

    if (ide === 'exit') return;

    const projectDirs = findLinkedProjectDirs(process.cwd());
    const configurator = IDE_CONFIGURATORS[ide];
    configurator(process.cwd(), projectDirs, (msg) => this.log(msg));

cli/src/api/ide/configure-vscode-ide.ts:53

  • settings['yaml.customTags'] is assumed to be a string[] via a cast. If the user has an unexpected type in settings.json (e.g. a string or object), spreading it into new Set([...currentTags, ...VSCODE_YAML_TAGS]) can behave incorrectly (e.g. string becomes characters). Consider validating that the existing value is an array of strings before merging, and otherwise default to [] (or log that the existing value was ignored).
  let settings: Record<string, unknown> = {};
  if (existsSync(settingsPath)) {
    try {
      const raw = readFileSync(settingsPath, 'utf8');
      settings = JSON.parse(raw) as Record<string, unknown>;
    } catch {
      // If invalid JSON, overwrite with our settings.
    }
  }

  const currentTags = (settings['yaml.customTags'] ?? []) as string[];
  settings['yaml.customTags'] = [...new Set([...currentTags, ...VSCODE_YAML_TAGS])];
  mkdirSync(vscodeDir, { recursive: true });
  writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n', 'utf8');

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@stevensJourney stevensJourney marked this pull request as ready for review March 4, 2026 08:45
@stevensJourney stevensJourney merged commit 5d035b7 into main Mar 4, 2026
6 checks passed
@stevensJourney stevensJourney deleted the feat-ide-config branch March 4, 2026 09:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants