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
43 changes: 43 additions & 0 deletions .claude/rules/architecture/client-codegen.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
paths:
- src/clients/**/*
- src/graphql/**/*
---

# Client Code Generation

**NEVER manually edit generated client code** under the auto-generated directories listed below.
These clients are produced from OpenAPI specs and should only be changed via spec/patch updates and
regeneration.

## OpenAPI (REST) Clients

OpenAPI specs typically come from upstream services — don't edit them directly. To adjust generated
output, add a `.patch` file to `src/clients/sidecar-openapi-specs/patches/` (applied automatically
during `npx gulp apigen`).

To regenerate clients after spec or patch changes:

1. Run `npx gulp apigen`
2. Commit both any new/updated spec files AND corresponding `.patch` files

## GraphQL

- Uses `gql.tada` for type-safe queries
- Schema at `src/graphql/sidecar.graphql`
- Generated types at `src/graphql/sidecarGraphQL.d.ts` (auto-generated, do not edit)
- Query definitions live alongside the code that uses them

## Auto-Generated Directories and Files (never edit)

- `src/clients/sidecar/`
- `src/clients/schemaRegistryRest/`
- `src/clients/kafkaRest/`
- `src/clients/docker/`
- `src/clients/flinkSql/`
- `src/clients/flinkComputePool/`
- `src/clients/flinkArtifacts/`
- `src/clients/flinkWorkspaces/`
- `src/clients/scaffoldingService/`
- `src/clients/medusa/`
- `src/graphql/sidecarGraphQL.d.ts`
36 changes: 36 additions & 0 deletions .claude/rules/architecture/connection-types.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
paths:
- src/authn/**/*
- src/authz/**/*
- src/directConnect*
- src/directConnections/**/*
---

# Connection Types

The extension supports three connection types, each with different resource loading strategies.

## CCLOUD (Confluent Cloud)

- Uses `CCloudResourceLoader` with GraphQL queries to the sidecar
- OAuth authentication: sign-in/sign-out actions manage tokens
- Access to Environments, Kafka clusters, Schema registries, Flink resources
- Auth flows in `src/authn/`

## LOCAL (Docker-based)

- Uses `LocalResourceLoader` with Docker engine API
- Automatically detects local Kafka/SR containers
- No authentication required
- Docker integration in `src/docker/`

## DIRECT (TCP connections)

- Uses `DirectResourceLoader` with manual connection configuration
- Supports custom brokers and schema registry URLs
- Optional SASL authentication
- Configuration UI via webview form (`src/webview/direct-connect-form.*`)
- Connection management in `src/directConnect*` and `src/directConnections/`

Each connection type has its own ResourceLoader implementation managing the specific connection
details and API calls. See the resource-loaders rule for the class hierarchy.
19 changes: 19 additions & 0 deletions .claude/rules/architecture/extension-settings.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
paths:
- src/extensionSettings/**/*
---

# Extension Settings Pattern

## Defining Settings

- Define settings in `src/extensionSettings/constants.ts` as `ExtensionSetting<T>` instances
- Must match `package.json`'s `contributes.configuration` sections exactly
- Access current value via `.value` property — automatically syncs with VS Code configuration
- Changes handled by `src/extensionSettings/listener.ts`

## Adding a New Setting

1. Add the configuration entry to `package.json` under `contributes.configuration`
2. Create an `ExtensionSetting<T>` instance in `src/extensionSettings/constants.ts`
3. If the setting needs side effects on change, add a handler in `listener.ts`
35 changes: 35 additions & 0 deletions .claude/rules/architecture/resource-loaders.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
paths:
- src/loaders/**/*
---

# Resource Loader Pattern

Abstract layer for loading resources from different connection types.

## Class Hierarchy

```
ResourceLoader (abstract base at src/loaders/resourceLoader.ts)
└── CachingResourceLoader (intermediate abstract at src/loaders/cachingResourceLoader.ts)
├── CCloudResourceLoader - Confluent Cloud via OAuth
├── LocalResourceLoader - Local Docker-based Kafka/SR
└── DirectResourceLoader - Direct TCP connections
```

## Key Design Points

- **CachingResourceLoader** encapsulates caching of environments, Kafka clusters, schema registries,
and topics
- Generic types (`EnvironmentType`, `KafkaClusterType`, `SchemaRegistryType`) are defined at the
CachingResourceLoader level
- **Registry pattern**: `ResourceLoader.getInstance(connectionId)` for lookup by connection ID
- Constructed during extension activation in `constructResourceLoaderSingletons()`
- Uses **GraphQL** to query the sidecar for resource metadata

## Adding a New Resource Type

1. Add the abstract loading method to `CachingResourceLoader`
2. Implement in each concrete loader (CCloud, Local, Direct)
3. Add caching if the resource is frequently accessed
4. Register in the singleton construction during activation
37 changes: 37 additions & 0 deletions .claude/rules/architecture/sidecar-pattern.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
paths:
- src/sidecar/**/*
---

# Sidecar Process Pattern

The extension uses a separate `ide-sidecar` process for all heavy operations (REST, GraphQL,
WebSocket APIs). The sidecar is a shared backend also consumed by the IntelliJ plugin.

## Key Components

- **SidecarManager** (`src/sidecar/sidecarManager.ts`): singleton managing the sidecar process
lifecycle (start, stop, health checks)
- **SidecarHandle** (`src/sidecar/sidecarHandle.ts`): short-lived client for individual operations
- **WebsocketManager** (`src/sidecar/websocketManager.ts`): persistent WebSocket connection for
real-time updates (topic messages, Flink statement results, etc.)

## Critical Pattern

Always use short-lived handles: `await getSidecar()` → use handle → discard. Never store a handle
long-term. This enables automatic reconnection and proper resource management.

```typescript
// correct: short-lived handle
const sidecar = await getSidecar();
const result = await sidecar.someOperation();

// wrong: storing handle as instance variable for reuse
this.sidecar = await getSidecar(); // don't do this
```

## Communication Protocols

- **REST**: OpenAPI-generated clients in `src/clients/` (auto-generated, never edit)
- **GraphQL**: `gql.tada` typed queries, schema at `src/graphql/sidecar.graphql`
- **WebSocket**: streaming data (topic consumption, Flink results) via WebsocketManager
38 changes: 38 additions & 0 deletions .claude/rules/architecture/view-providers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
paths:
- src/viewProviders/**/*
- src/panelProviders/**/*
---

# View Provider Architecture

Tree views extend `BaseViewProvider` or `ParentedBaseViewProvider`:

## Base Classes

- **BaseViewProvider** (`src/viewProviders/baseModels/base.ts`): abstract base for all tree views
with built-in search/filter capability
- **ParentedBaseViewProvider** (`src/viewProviders/baseModels/parentedBase.ts`): for parent-child
resource hierarchies (e.g., Topics under a Kafka Cluster)

## Main View Providers

| Provider | Purpose |
| ----------------------------- | ------------------------------------ |
| `ResourceViewProvider` | Environments, Kafka clusters, SRs |
| `TopicViewProvider` | Topics within selected Kafka cluster |
| `SchemasViewProvider` | Schemas within selected SR |
| `FlinkStatementsViewProvider` | Flink SQL statements |
| `FlinkDatabaseViewProvider` | Flink databases and tables |

## Panel Providers

Panel providers in `src/panelProviders/` manage webview panels (full editor-area views) as opposed
to tree views in the sidebar. They typically use the webview architecture (see webview rules).

## Adding a New View Provider

1. Extend `BaseViewProvider` or `ParentedBaseViewProvider`
2. Register in `package.json` under `contributes.views`
3. Register the provider in the activation code
4. Ensure the class extends `DisposableCollection` for proper cleanup
35 changes: 35 additions & 0 deletions .claude/rules/architecture/webview-architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
paths:
- src/webview/**/*
---

# Webview Architecture

Webviews render rich UI inside VS Code using HTML/CSS/JS in sandboxed iframes.

## Template Engine

- HTML templates in `src/webview/*.html` with template variables and functions like `this.${var}()`
bound to the `ViewModel` in corresponding `.ts` files
- Signal-based data binding for Template + ViewModel via custom template engine in
`src/webview/bindings`

## Communication

- Webviews communicate with the VS Code host via `sendWebviewMessage()` and message handlers in
`src/webview/comms`
- The comms layer wraps the vscode webview message API to provide type safety
- Messages flow: webview → postMessage → extension host handler → response → webview

## Styling

- General CSS styles in `src/webview/uikit/uikit.css` with view-specific overrides in individual
HTML templates
- VS Code color theme variables preferred and used when appropriate
- **`@vscode/webview-ui-toolkit` is deprecated** — don't use it in new code; use UIKit styles on
HTML elements instead

## Functional Tests

Webview functional tests (`src/webview/*.spec.ts`) use Playwright to test UI validation and user
interactions. See the functional tests rule for details.
24 changes: 24 additions & 0 deletions .claude/rules/testing/e2e-tests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
paths:
- tests/e2e/**/*
---

# End-to-End Tests (Playwright + Electron)

## Framework & Location

- Full workflow tests in `tests/e2e/` using Playwright + Electron
- Run with `npx gulp e2e` or `npx gulp e2e -t "test name"`
- Located in separate directory from source code

## Requirements

- Docker must be running for local Kafka/SR instances
- Extension Development Host launched via Playwright's `electron.launch()` API

## Key Patterns

- **Page Object Model**: page objects in `tests/e2e/pages/` abstract UI interactions
- **No conditionals in tests**: do not include conditionals within E2E tests to manage test
dimensions — this violates ESLint rules. Instead, use test tags and filtering at runtime.
- Test files should exercise complete user workflows, not isolated units
18 changes: 18 additions & 0 deletions .claude/rules/testing/functional-tests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
paths:
- src/webview/**/*.spec.ts
---

# Functional Tests (Playwright Webview Tests)

## Framework & Location

- Webview tests in `src/webview/*.spec.ts` using Playwright
- Run with `npx gulp functional`
- Test UI validation and user interactions in webview forms

## Purpose

Functional tests verify webview behavior — form validation, user interactions, data binding — in a
real browser environment via Playwright. They complement unit tests by testing the HTML/CSS/JS layer
that unit tests can't reach.
38 changes: 38 additions & 0 deletions .claude/rules/testing/unit-tests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
paths:
- src/**/*.test.ts
- tests/unit/**/*
- tests/stubs/**/*
- tests/fixtures/**/*
---

# Unit Testing (Mocha + Sinon)

## Framework & Location

- Co-located `.test.ts` files using Mocha + Sinon + `assert`
- Run with `npx gulp test` or `npx gulp test -t "test name"` for specific tests
- Coverage: `npx gulp test --coverage`

## Key Patterns

- Use `.only` for focused testing during development (remove before PR!)
- Focus on isolated behavior, mocking external dependencies
- Do not test side effects like logging
- Set up common stubs in the top-level `describe` block so they apply to all tests

## Design for Stubbing

When writing new functions, avoid calling other functions in the same module that you'll need to
stub — Sinon can only stub **module exports**, not internal calls within the same file.

**Solutions:**

- Extract dependencies to separate modules
- Pass dependencies as parameters
- Use dependency injection patterns

## Test Data

- Unit test fixtures in `tests/fixtures/`
- Shared stubs in `tests/stubs/`
Loading