@@ -3,107 +3,49 @@ description:
33globs:
44alwaysApply: false
55---
6- # VSCode StepZen Extension Development Rules
6+ # VSCode StepZen Extension Architecture Rules
77
8- This project is a Visual Studio Code extension for working with StepZen GraphQL projects. Follow these conventions and patterns when contributing to or modifying this codebase .
8+ **CRITICAL**: Before making any architectural decisions, read `docs/architecture.md` for the complete layered design and service registry pattern .
99
10- **Note**: This project is undergoing active refactoring. Some patterns may change as issues #32-#49 are implemented.
10+ ## Layered Architecture
1111
12- ## Project Structure & Architecture
12+ Follow this strict import hierarchy:
1313
14- ### Directory Organization
15- - `src/commands/` - VSCode command implementations (being standardized via #35)
16- - `src/services/` - Business logic services (CLI, Logger, etc.)
17- - `src/utils/` - Utility functions and helpers (being reorganized via #49, #45)
18- - `src/panels/` - WebView panel implementations (base helper coming via #46)
19- - `src/types/` - TypeScript type definitions
20- - `src/errors/` - Error handling classes and utilities
21- - `src/test/` - Test files organized by type (unit, integration, fixtures, helpers)
22-
23- ### File Naming Conventions
24- - Use camelCase for file names: `stepzenProjectScanner.ts`
25- - Test files: `*.test.ts` suffix
26- - Type definition files: descriptive names in `src/types/`
27- - Constants: being centralized via #30 - check current patterns
28-
29- ## Code Style & Standards
30-
31- ### TypeScript Configuration
32- - Target: ES2022, Module: Node16
33- - Strict mode enabled with additional checks:
34- - `noImplicitReturns: true`
35- - `noFallthroughCasesInSwitch: true`
36- - `noUnusedParameters: true`
37- - `noUnusedLocals: true`
38-
39- ### ESLint Rules (Enhanced via #32)
40- - **No console statements**: Use `services.logger` instead of `console.log`
41- - **Naming convention**: camelCase for imports, PascalCase for types
42- - **Semicolons required**
43- - **Strict equality**: Use `===` and `!==`
44- - **Curly braces**: Always use braces for control statements
45- - Additional rules coming via #32 (ESLint + ts-prune + depcheck)
46-
47- ### Import Patterns
48- ```typescript
49- // VSCode API
50- import * as vscode from "vscode";
51-
52- // Node.js built-ins
53- import * as fs from "fs";
54- import * as path from "path";
55-
56- // GraphQL
57- import { parse, OperationDefinitionNode } from "graphql";
58-
59- // Internal services
60- import { services } from "../services";
61-
62- // Internal utilities
63- import { handleError, ValidationError } from "../errors";
64- // Note: Constants organization changing via #30
14+ ```
15+ Extension Layer (Commands, Panels, Utils)
16+ ↓ (can import from)
17+ Service Registry (CLI, Logger, ProjectResolver, SchemaIndex, Request)
18+ ↓ (can import from)
19+ Schema Processing Layer (Indexer, Linker, Parser)
20+ ↓ (can import from)
21+ Types (Pure data structures)
6522```
6623
67- ## Service Architecture
24+ **ESLint enforces these boundaries automatically.**
6825
69- ### Dependency Injection
70- Use the service registry pattern for testability:
26+ ## Core Patterns
7127
28+ ### Service Usage
7229```typescript
73- // Use services instead of direct imports
30+ // Always use the service registry
7431import { services } from "../services";
7532
76- // In functions
7733services.logger.info("Message");
7834services.cli.deploy();
7935```
8036
8137### Error Handling
82- - Use custom error classes from `src/errors/`
83- - Always use `handleError()` for consistent error processing
84- - Validate inputs early with descriptive error messages
85-
8638```typescript
87- import { handleError, ValidationError, NetworkError } from "../errors";
88-
89- // Input validation
90- if (!query || typeof query !== 'string') {
91- throw new ValidationError("Invalid query: expected a non-empty string", "INVALID_QUERY");
92- }
39+ import { handleError, ValidationError } from "../errors";
9340
94- // Error handling
9541try {
9642 // risky operation
9743} catch (err) {
98- handleError(err);
44+ handleError(err); // Logs and shows user notification
9945}
10046```
10147
102- ## Command Implementation (Being Standardized via #35)
103-
10448### Command Structure
105- Commands are being standardized via #35. Current pattern:
106-
10749```typescript
10850export async function commandName() {
10951 // 1. Check workspace trust if needed
@@ -121,243 +63,21 @@ export async function commandName() {
12163
12264 // 3. Main logic with error handling
12365 try {
66+ services.logger.info("Command started");
12467 // Implementation
12568 } catch (err) {
12669 handleError(err);
12770 }
12871}
12972```
13073
131- **Note**: Command patterns may change as #35 (CMD-INFRA), #38 (CMD-REQ-SPLIT), and #40-#43 are implemented.
132-
133- ### Progress Reporting
134- For long-running operations, use `vscode.window.withProgress`:
135-
136- ```typescript
137- await vscode.window.withProgress({
138- location: vscode.ProgressLocation.Notification,
139- title: "Processing...",
140- cancellable: true
141- }, async (progress, token) => {
142- // Implementation with progress.report()
143- });
144- ```
145-
146- ## Testing Standards (Expanding via #33)
147-
148- ### Test Organization
149- - Unit tests: `src/test/unit/` - mirror source structure
150- - Integration tests: `src/test/integration/`
151- - Fixtures: `src/test/fixtures/` - reusable test data
152- - Helpers: `src/test/helpers/` - shared test utilities
153-
154- ### Test Patterns
155- ```typescript
156- import * as assert from "assert";
157- import { services, setMockServices } from "../../services";
158- import { createMock } from "../helpers/test-utils";
159-
160- suite("Test Suite Name", () => {
161- setup(() => {
162- // Setup before each test
163- });
164-
165- teardown(() => {
166- // Cleanup after each test
167- });
168-
169- test("should do something specific", () => {
170- // Arrange
171- const mockServices = {
172- logger: createMock({ info: () => {}, error: () => {} })
173- };
174- const original = setMockServices(mockServices);
175-
176- try {
177- // Act & Assert
178- assert.strictEqual(actual, expected, "Descriptive message");
179- } finally {
180- // Cleanup
181- setMockServices(original);
182- }
183- });
184- });
185- ```
186-
187- ### Coverage Requirements
188- - Aim for 100% coverage on utility functions
189- - Test both happy path and error conditions
190- - Use descriptive test names and assertion messages
191- - **Note**: Test expansion planned via #33
192-
193- ## Constants & Configuration (Being Centralized via #30)
194-
195- ### Use Centralized Constants
196- **Note**: Constants are being reorganized via #30. Check current location before using:
197-
198- ```typescript
199- // Pattern may change - verify current structure
200- import { UI, FILE_PATTERNS, TIMEOUTS, GRAPHQL } from "../utils/constants";
201-
202- // Good
203- const outputChannel = vscode.window.createOutputChannel(UI.OUTPUT_CHANNEL_NAME);
204- const configPath = path.join(projectRoot, FILE_PATTERNS.CONFIG_FILE);
205-
206- // Avoid hardcoded strings
207- ```
208-
209- ### Configuration Access
210- ```typescript
211- const cfg = vscode.workspace.getConfiguration("stepzen");
212- const logLevel = cfg.get<string>("logLevel", "info");
213- const logToFile = cfg.get<boolean>("logToFile", false);
214- ```
215-
216- ## WebView Panels (Base Helper Coming via #46)
217-
218- ### Panel Lifecycle
219- - Implement proper disposal and cleanup
220- - Handle message passing between webview and extension
221- - Use CSP (Content Security Policy) for security
222- - **Note**: BaseWebviewPanel helper coming via #46
223-
224- ### Resource Management
225- ```typescript
226- // Proper cleanup
227- panel.onDidDispose(() => {
228- // Cleanup resources
229- });
230-
231- // Message handling
232- panel.webview.onDidReceiveMessage(message => {
233- switch (message.command) {
234- case 'action':
235- // Handle action
236- break;
237- }
238- });
239- ```
240-
241- ## GraphQL Specific Patterns (Major Changes Coming)
242-
243- ### Schema Scanning (Being Split via #49)
244- **Note**: `stepzenProjectScanner.ts` is being split into parts via #49. Current patterns:
245- - Use scanner functions for schema analysis
246- - Clear scanner state between operations: `clearScannerState()`
247- - Handle nested SDL files and executables properly
248-
249- **Warning**: Scanner API may change significantly with #49 refactoring.
250-
251- ### AST Parsing (Changing via #36)
252- **Note**: GraphQL AST parsing is being enhanced via #36. Current pattern:
253-
254- ```typescript
255- // Extract operation names
256- const ops = extractOperationNames(query);
257-
258- // Handle multiple operations
259- if (ops.length > 1) {
260- const operationName = await vscode.window.showQuickPick(ops, {
261- placeHolder: "Select operation to execute"
262- });
263- }
264- ```
265-
266- ### CodeLens (Being Refined via #44)
267- CodeLens functionality is being refined via #44 to inject services & AST parsing.
268-
269- ## Build & Development
270-
271- ### Scripts
272- - `npm run compile` - Build extension
273- - `npm run watch` - Watch mode for development
274- - `npm run test` - Run all tests
275- - `npm run lint` - ESLint checking (enhanced via #32)
276- - `npm run package` - Create VSIX package
277-
278- ### esbuild Configuration
279- - Bundle: true, Format: CJS, Platform: Node
280- - External: ["vscode"]
281- - Minify in production, sourcemaps in development
282- - **Note**: Webview bundling changes coming via #31
283-
284- ## Documentation
285-
286- ### Code Comments
287- - Use JSDoc for public functions
288- - Include parameter types and return types
289- - Document complex business logic
290-
291- ```typescript
292- /**
293- * Extracts operation names from a GraphQL query string
294- * @param query The GraphQL query string to parse
295- * @returns Array of operation names found in the query
296- */
297- function extractOperationNames(query: string): string[] {
298- // Implementation
299- }
300- ```
301-
302- ### README Updates
303- - Keep feature list current
304- - Update installation instructions
305- - Document new commands and configuration options
306-
307- ## Security & Trust
74+ ## Code Standards
30875
309- ### Workspace Trust
310- Always check workspace trust for operations that:
311- - Execute external commands
312- - Read/write files
313- - Make network requests
314-
315- ```typescript
316- if (!vscode.workspace.isTrusted) {
317- vscode.window.showWarningMessage("Feature not available in untrusted workspaces");
318- return;
319- }
320- ```
321-
322- ### File Operations
323- - Use proper error handling for file I/O
324- - Clean up temporary files with timeouts
325- - Validate file paths and contents
326-
327- ## Performance
328-
329- ### Async Operations
330- - Use proper async/await patterns
331- - Handle cancellation tokens where appropriate
332- - Avoid blocking the main thread
333-
334- ### Memory Management
335- - Dispose of resources properly
336- - Clear caches when appropriate
337- - Use weak references for event listeners where needed
338-
339- ## String Externalization (Coming via #39)
340-
341- **Note**: User-visible strings are being externalized via #39 for internationalization support.
76+ - **No console statements**: Use `services.logger` instead
77+ - **TypeScript strict mode**: All type checking enabled
78+ - **Dependency injection**: Use service registry for testability
79+ - **Constants**: Import from `utils/constants` (shared configuration)
34280
34381---
34482
345- ## Refactoring Notes
346-
347- **Active Refactoring Areas** (avoid prescriptive patterns):
348- - **Scanner (#49)**: Major split of `stepzenProjectScanner.ts` - API will change
349- - **Commands (#35, #38, #40-#43)**: Standardization and service extraction
350- - **Constants (#30)**: Centralization of constants and enums
351- - **AST Parsing (#36)**: Enhanced GraphQL AST usage
352- - **Testing (#33)**: Expansion to panels & utils
353- - **Linting (#32)**: Enhanced ESLint, ts-prune, depcheck
354- - **WebView (#31, #46)**: Bundling and base helper patterns
355-
356- When working on this extension, prioritize:
357- 1. **User Experience** - Clear error messages, progress indication
358- 2. **Reliability** - Proper error handling, input validation
359- 3. **Testability** - Use dependency injection, write comprehensive tests
360- 4. **Maintainability** - Follow established patterns, document complex logic
361- 5. **Security** - Respect workspace trust, validate inputs
362-
363- **Before implementing new features**: Check if the area is under active refactoring in issues #30-#49.
83+ *Portions of the Content may be generated with the assistance of CursorAI*
0 commit comments