Skip to content

Commit c19ca51

Browse files
improved cursor rule, added linter for enforcing architectural boundaries (#68)
1 parent 765b617 commit c19ca51

File tree

2 files changed

+87
-305
lines changed

2 files changed

+87
-305
lines changed

.cursor/rules/vscode-stepzen-project.mdc

Lines changed: 25 additions & 305 deletions
Original file line numberDiff line numberDiff line change
@@ -3,107 +3,49 @@ description:
33
globs:
44
alwaysApply: 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
7431
import { services } from "../services";
7532

76-
// In functions
7733
services.logger.info("Message");
7834
services.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
9541
try {
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
10850
export 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

Comments
 (0)