Skip to content

Latest commit

 

History

History
278 lines (201 loc) · 10.3 KB

File metadata and controls

278 lines (201 loc) · 10.3 KB

Contributing to vscode-npmx

Thank you for your interest in contributing! ❤️ This document provides guidelines and instructions for contributing.

Important

Please be respectful and constructive in all interactions. We aim to maintain a welcoming environment for all contributors. 👉 Read more

Goals

The goal of this project is to build useful editor extensions around npmx.dev, making it easier for developers to manage npm packages within their editors. Currently, the VS Code extension is the primary package.

Table of Contents

Getting started

Prerequisites

Setup

  1. fork and clone the repository
  2. install dependencies:
pnpm install
  1. start the development server:
pnpm dev
  1. Press F5 to open the VS Code debugger and start the extension in a new VS Code window.

Development workflow

Available commands

# Development (run from extensions/vscode/)
pnpm dev              # Start development server
pnpm build            # Production build
pnpm package          # Save extension as vsix file

# Code Quality (run from root)
pnpm lint             # Run linter (ESLint)
pnpm lint:fix         # Auto-fix lint issues
pnpm typecheck        # TypeScript type checking (tsgo)

# Testing (run from root)
pnpm test             # Run tests

Project structure

This project is organized as a monorepo using pnpm workspaces:

extensions/
└── vscode/                  # VS Code extension (thin client)
    ├── src/
    │   ├── commands/        # Command handlers (vscode API only, no reactive-vscode)
    │   ├── providers/       # VS Code provider registrations
    │   ├── utils/           # Extension-specific utilities
    │   ├── client.ts        # Language client setup
    │   ├── index.ts         # Extension entry point
    │   ├── request.ts       # Request handling
    │   └── state.ts         # State management
    └── tests/
packages/
├── shared/                  # Shared code across packages
│   └── src/
│       ├── commands.ts      # Command identifiers
│       ├── constants.ts     # Shared constants
│       ├── meta.ts          # Auto-generated extension metadata
│       ├── protocol.ts      # LSP protocol definitions
│       └── types.ts         # Shared types
├── language-core/           # Core logic (extractors, API clients, workspace)
│   └── src/
│       ├── api/             # API clients (package, replacement, vulnerability)
│       ├── extractors/      # File parsers (JSON, YAML)
│       ├── utils/           # Core utilities (with colocated tests)
│       ├── workspace.ts     # Workspace context resolution
│       └── types.ts         # Core types
├── language-service/        # Language service plugins (Volar)
│   └── src/
│       ├── plugins/         # Service plugins
│       │   ├── diagnostics/ # Diagnostic rules (with colocated tests)
│       │   ├── catalog.ts   # Catalog resolution
│       │   ├── document-link.ts
│       │   ├── hover.ts
│       │   └── version-completion.ts
│       └── utils/           # Service utilities (with colocated tests)
└── language-server/         # Language server (Volar)
    └── src/
        ├── server.ts        # Server setup
        └── workspace.ts     # Server workspace handling
playground/                  # Playground for testing
res/                         # Assets (e.g. marketplace icon)

Key concepts

  • Extractor – Parses a supported file (package.json, pnpm-workspace.yaml, .yarnrc.yml) and extracts dependency information with AST ranges. Each file format has its own extractor in packages/language-core/src/extractors/.
  • WorkspaceContext – Holds per-workspace-folder state: detected package manager, resolved catalogs, and memoized dependency info. Created lazily and invalidated when workspace-level files change.
  • ResolvedDependencyInfo – A dependency with its protocol resolved (e.g., catalog: → actual version, npm:alias@version → underlying package). Plugins consume resolved dependencies instead of raw AST data.
  • Plugin – A Volar language service plugin (hover, completion, diagnostics, etc.) in packages/language-service/ that operates on resolved dependencies.

Code style

When committing changes, try to keep an eye out for unintended formatting updates. These can make a pull request look noisier than it really is and slow down the review process. Sometimes IDEs automatically reformat files on save, which can unintentionally introduce extra changes.

If you want to get ahead of any formatting issues, you can also run pnpm lint:fix before committing to fix formatting across the whole project.

TypeScript

  • We care about good types – never cast things to any 💪
  • Validate rather than just assert

Import order

Tip

This will be fixed by eslint.

  1. Type imports first (import type { ... })
  2. Internal aliases (#constants, #state, #utils/, #core/, #composables/, #types/, etc.)
  3. External packages (including node:)
  4. Relative imports (./, ../)
  5. No blank lines between groups
import type { PackageVersionsInfoWithMetadata } from 'fast-npm-meta'
import { logger } from '#state'
import { getVersions } from 'fast-npm-meta'
import { memoize } from '../memoize'

Naming conventions

Type Convention Example
Files/Folders kebab-case package-json.ts, pnpm-workspace-yaml.ts
Test files kebab-case + .test memoize.test.ts
Functions camelCase fetchPackage, formatDate
Constants SCREAMING_SNAKE_CASE NPM_REGISTRY, ALLOWED_TAGS
Types/Interfaces PascalCase NpmSearchResponse, Extractor, ValidNode

Testing

Unit tests

Write unit tests for core functionality using Vitest:

import { describe, expect, it } from 'vitest'

describe('featureName', () => {
  it('should handle expected case', () => {
    expect(result).toBe(expected)
  })
})

Submitting changes

Before submitting

  1. ensure your code follows the style guidelines
  2. run linting: pnpm lint:fix
  3. run type checking: pnpm typecheck
  4. run tests: pnpm test
  5. write or update tests for your changes

Pull request process

  1. create a feature branch from main
  2. make your changes with clear, descriptive commits
  3. push your branch and open a pull request
  4. ensure CI checks pass (lint, type check, tests)
  5. request review from maintainers

Commit messages and PR titles

Write clear, concise PR titles that explain the "why" behind changes.

We use Conventional Commits. Since we squash on merge, the PR title becomes the commit message in main, so it's important to get it right.

Format: type(scope): description

Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert

Scopes (optional): docs, utils, deps

Examples:

  • fix: resolve search pagination issue
  • feat: add package version comparison
  • chore(deps): update vite to v6

Note

The subject must start with a lowercase letter. Individual commit messages within your PR don't need to follow this format since they'll be squashed.

PR descriptions

If your pull request directly addresses an open issue, use the following inside your PR description.

Resolves | Fixes | Closes: #xxx

Replace #xxx with either a URL to the issue, or the number of the issue. For example:

Fixes:#123

or

Closes https://github.com/npmx-dev/vscode-npmx/issues/123

This provides the following benefits:

  • it links the pull request to the issue (the merge icon will appear in the issue), so everybody can see there is an open PR
  • when the pull request is merged, the linked issue is automatically closed

Pre-commit hooks

The project uses nano-staged with husky to automatically lint files on commit.

Using AI

You're welcome to use AI tools to help you contribute. But there are two important ground rules:

1. Never let an LLM speak for you

When you write a comment, issue, or PR description, use your own words. Grammar and spelling don't matter – real connection does. AI-generated summaries tend to be long-winded, dense, and often inaccurate. Simplicity is an art. The goal is not to sound impressive, but to communicate clearly.

2. Never let an LLM think for you

Feel free to use AI to write code, tests, or point you in the right direction. But always understand what it's written before contributing it. Take personal responsibility for your contributions. Don't say "ChatGPT says..." – tell us what you think.

For more context, see Using AI in open source.

Questions?

If you have questions or need help, feel free to open an issue for discussion or join our Discord server.

License

By contributing to vscode-npmx, you agree that your contributions will be licensed under the MIT License.