|
| 1 | +# GitHub Copilot Instructions for dependency-cruiser |
| 2 | + |
| 3 | +These instructions help GitHub Copilot generate code that aligns with the dependency-cruiser project's conventions. Keep responses brief and focused on the task at hand. |
| 4 | + |
| 5 | +## Communication Style |
| 6 | + |
| 7 | +- Provide concise responses without unnecessary elaboration |
| 8 | +- Focus on code solutions rather than lengthy explanations |
| 9 | +- Use bullet points for multi-part information when appropriate |
| 10 | +- Avoid repetition of information already visible in the code |
| 11 | + |
| 12 | +## Module System |
| 13 | + |
| 14 | +- Use ECMAScript Modules (ESM) with `.mjs` file extensions for new code |
| 15 | +- Use CommonJS with `.cjs` for backward compatibility when needed |
| 16 | +- Include explicit file extensions in imports (`.mjs` or `.cjs`) |
| 17 | +- Use the `#` import alias for internal modules (e.g., `import xyz from "#config-utl/extract-depcruise-config.mjs"`) |
| 18 | + |
| 19 | +## File Organization |
| 20 | + |
| 21 | +- Source code is located in `/src` directory, organized in feature-specific subdirectories |
| 22 | +- Tests are in `/test` directory, mirroring the structure of `/src` |
| 23 | +- Test files have the same name as the file they test with a `.spec.mjs` extension |
| 24 | +- Place test files in the same directory structure as the source files |
| 25 | + |
| 26 | +## Code Style & Formatting |
| 27 | + |
| 28 | +### Naming & Coding Conventions |
| 29 | + |
| 30 | +- Variables/functions: camelCase |
| 31 | +- Classes: PascalCase |
| 32 | +- Parameters: prefix with `p` (e.g., `pOptions`) |
| 33 | +- Local variables: prefix with `l` (e.g., `lVersion`) |
| 34 | +- Constants: UPPER_SNAKE_CASE |
| 35 | +- Boolean functions: use `is`/`has` prefixes |
| 36 | +- Strings: double quotes |
| 37 | +- Line length: ~80 characters |
| 38 | +- Prefer `const` over `let` |
| 39 | +- Use semicolons |
| 40 | +- Use ES6+ features (arrow functions, destructuring) |
| 41 | + |
| 42 | +## Documentation |
| 43 | + |
| 44 | +### JSDoc |
| 45 | + |
| 46 | +- Use JSDoc for public functions, classes, and methods |
| 47 | +- Include `@param`, `@returns`, and `@throws` tags |
| 48 | +- Use TypeScript-style type annotations |
| 49 | +- Use `@typedef` for complex types |
| 50 | + |
| 51 | +Example: |
| 52 | +```javascript |
| 53 | +/** |
| 54 | + * Function description |
| 55 | + * |
| 56 | + * @param {string} pModuleName - Description of parameter |
| 57 | + * @param {object} [pOptions] - Options object (square brackets denote optional) |
| 58 | + * @param {string} [pOptions.semanticVersion] - A semantic version range |
| 59 | + * @returns {Promise<NodeModule|false>} - Description of return value |
| 60 | + * @throws {Error} - When something goes wrong |
| 61 | + */ |
| 62 | +``` |
| 63 | + |
| 64 | +## Testing |
| 65 | + |
| 66 | +### Mocha Testing Framework |
| 67 | + |
| 68 | +- Tests use Mocha (note the `describe`, `it`, `beforeEach`, `afterEach` syntax) |
| 69 | +- Use Node.js built-in `assert` library for assertions (`import { deepEqual, ok } from "node:assert/strict"`) |
| 70 | +- Group related tests in `describe` blocks |
| 71 | +- Use meaningful test descriptions that explain what's being tested |
| 72 | +- When appropriate, use `beforeEach`/`afterEach` hooks for setup and teardown |
| 73 | +- Test both success and error cases |
| 74 | + |
| 75 | +Example test structure: |
| 76 | +```javascript |
| 77 | +import { deepEqual, ok } from "node:assert/strict"; |
| 78 | +import functionToTest from "#path/to/function.mjs"; |
| 79 | + |
| 80 | +describe("[I] module/functionToTest", () => { |
| 81 | + it("should handle normal case", () => { |
| 82 | + const result = functionToTest(input); |
| 83 | + deepEqual(result, expectedOutput); |
| 84 | + }); |
| 85 | + |
| 86 | + it("throws when given invalid input", () => { |
| 87 | + let error = null; |
| 88 | + try { |
| 89 | + functionToTest(invalidInput); |
| 90 | + } catch (pError) { |
| 91 | + error = pError; |
| 92 | + } |
| 93 | + ok(error instanceof Error); |
| 94 | + }); |
| 95 | +}); |
| 96 | +``` |
| 97 | + |
| 98 | +## Error Handling |
| 99 | + |
| 100 | +- Prefer try/catch blocks for error handling, especially with async operations |
| 101 | +- Return `false` or null for expected failure conditions instead of throwing (see `tryImport` pattern) |
| 102 | +- Use descriptive error messages that help pinpoint the issue |
| 103 | +- Use appropriate error types when throwing |
| 104 | + |
| 105 | +## Types |
| 106 | + |
| 107 | +- The project uses JSDoc comments with TypeScript-style types |
| 108 | +- Type definitions are stored in the `/types` directory with `.d.mts` extensions |
| 109 | +- Import types from type definition files where needed |
| 110 | +- Use TypeScript annotations in JSDoc comments where appropriate |
| 111 | + |
| 112 | +## Dependencies and Imports |
| 113 | + |
| 114 | +- Import statements should be ordered: |
| 115 | + 1. Node.js built-in modules (prefixed with `node:`) |
| 116 | + 2. External dependencies |
| 117 | + 3. Internal modules (using the `#` alias) |
| 118 | +- Use named imports where appropriate |
| 119 | +- Use async import() for dynamic imports |
| 120 | + |
| 121 | +## Best Practices |
| 122 | + |
| 123 | +- Write pure functions where possible |
| 124 | +- Avoid side effects |
| 125 | +- Use early returns to reduce nesting |
| 126 | +- Apply the single responsibility principle |
| 127 | +- Be mindful of performance, especially for operations that may run on large dependency trees |
| 128 | +- Write defensive code that handles edge cases gracefully |
| 129 | +- For optional features/dependencies, use the `tryImport` pattern to check availability |
0 commit comments