|
| 1 | +# OpenOps Block Style Guide ESLint Plugin |
| 2 | + |
| 3 | +Custom ESLint plugin to enforce style guide rules for `displayName` and `description` fields in OpenOps blocks. |
| 4 | + |
| 5 | +## Rules |
| 6 | + |
| 7 | +### `block-style-guide` |
| 8 | + |
| 9 | +Enforces the following style guide rules for block definitions: |
| 10 | + |
| 11 | +#### 1. displayName - Title Case |
| 12 | +- Must be in Title Case (first letter of each word capitalized) |
| 13 | +- Exception: small words like "a", "and", "the", "of" can be lowercase (unless first word) |
| 14 | +- Acronyms (API, SQL, UUID, HTTP, etc.) should remain uppercase |
| 15 | + |
| 16 | +**Examples:** |
| 17 | +```typescript |
| 18 | +// ✓ Good |
| 19 | +displayName: 'Get Recommendations' |
| 20 | +displayName: 'Execute SQL Statement' |
| 21 | +displayName: 'Send HTTP Request' |
| 22 | +displayName: 'Order By' |
| 23 | + |
| 24 | +// ✗ Bad |
| 25 | +displayName: 'get recommendations' |
| 26 | +displayName: 'Execute sql statement' |
| 27 | +displayName: 'send Http request' |
| 28 | +``` |
| 29 | + |
| 30 | +#### 2. description - Sentence Case |
| 31 | +- Must start with a capital letter |
| 32 | +- Should NOT end with a period (unless multiple sentences) |
| 33 | +- Use imperative form for actions (Get, Create, Send) not third-person (Gets, Creates, Sends) |
| 34 | + |
| 35 | +**Examples:** |
| 36 | +```typescript |
| 37 | +// ✓ Good |
| 38 | +description: 'Get cost recommendations from the provider' |
| 39 | +description: 'Send an email using SMTP. Supports attachments and HTML content.' |
| 40 | + |
| 41 | +// ✗ Bad |
| 42 | +description: 'get cost recommendations' |
| 43 | +description: 'Get cost recommendations from the provider.' // No period for single sentence |
| 44 | +description: 'Gets cost recommendations' // Use imperative, not third-person |
| 45 | +``` |
| 46 | + |
| 47 | +#### 3. displayName and description Must Be Distinct |
| 48 | +- displayName and description should not be the same or too similar (>80% similarity) |
| 49 | + |
| 50 | +**Examples:** |
| 51 | +```typescript |
| 52 | +// ✓ Good |
| 53 | +displayName: 'Get Recommendations' |
| 54 | +description: 'Fetch cost optimization suggestions from the provider' |
| 55 | + |
| 56 | +// ✗ Bad |
| 57 | +displayName: 'Get Recommendations' |
| 58 | +description: 'Get recommendations' // Too similar |
| 59 | +``` |
| 60 | + |
| 61 | +#### 4. description Must Not Be Empty |
| 62 | +- Every description field must have meaningful content |
| 63 | + |
| 64 | +**Examples:** |
| 65 | +```typescript |
| 66 | +// ✓ Good |
| 67 | +description: 'Create a new item in the database' |
| 68 | + |
| 69 | +// ✗ Bad |
| 70 | +description: '' |
| 71 | +description: ' ' |
| 72 | +``` |
| 73 | + |
| 74 | +#### 5. Action displayNames Should Use Verbs |
| 75 | +- For actions, displayName should start with an action verb |
| 76 | +- Common verbs: Get, Create, Update, Delete, Send, Execute, Run, Add, Remove, etc. |
| 77 | + |
| 78 | +**Examples:** |
| 79 | +```typescript |
| 80 | +// ✓ Good (in createAction context) |
| 81 | +displayName: 'Get User Profile' |
| 82 | +displayName: 'Create Database Entry' |
| 83 | +displayName: 'Send Notification' |
| 84 | + |
| 85 | +// ✗ Bad (in createAction context) |
| 86 | +displayName: 'User Profile' // Missing verb |
| 87 | +displayName: 'Database Entry Creation' // Not verb-first |
| 88 | +``` |
| 89 | + |
| 90 | +## Installation |
| 91 | + |
| 92 | +The plugin is already integrated into the OpenOps monorepo. To enable it: |
| 93 | + |
| 94 | +1. The plugin is located in `tools/eslint-rules/` |
| 95 | +2. It's configured in `.eslintrc.json` for the blocks package |
| 96 | + |
| 97 | +## Usage |
| 98 | + |
| 99 | +The rule runs automatically when you run ESLint: |
| 100 | + |
| 101 | +```bash |
| 102 | +# Lint all files |
| 103 | +npm run lint |
| 104 | + |
| 105 | +# Lint blocks specifically |
| 106 | +npx nx lint blocks |
| 107 | + |
| 108 | +# Auto-fix issues where possible |
| 109 | +npx nx lint blocks --fix |
| 110 | +``` |
| 111 | + |
| 112 | +## Configuration |
| 113 | + |
| 114 | +The rule is enabled by default for the blocks package. You can configure it in `.eslintrc.json`: |
| 115 | + |
| 116 | +```json |
| 117 | +{ |
| 118 | + "rules": { |
| 119 | + "@openops/block-style/block-style-guide": "error" |
| 120 | + } |
| 121 | +} |
| 122 | +``` |
| 123 | + |
| 124 | +## Development |
| 125 | + |
| 126 | +To test the rule: |
| 127 | + |
| 128 | +```bash |
| 129 | +# From the tools/eslint-rules directory |
| 130 | +npm test |
| 131 | + |
| 132 | +# Or test against actual block files |
| 133 | +npx eslint packages/blocks/*/src/**/*.ts |
| 134 | +``` |
| 135 | + |
| 136 | +## Error Messages |
| 137 | + |
| 138 | +The rule provides specific error messages for each violation: |
| 139 | + |
| 140 | +- `displayNameNotTitleCase`: displayName should be in Title Case |
| 141 | +- `descriptionNotSentenceCase`: description should start with a capital letter |
| 142 | +- `descriptionTrailingPeriod`: description should not end with a period (unless multiple sentences) |
| 143 | +- `descriptionEmpty`: description must not be empty |
| 144 | +- `displayNameDescriptionSimilar`: displayName and description are too similar |
| 145 | +- `actionDisplayNameNotVerb`: Action displayName should start with a verb |
| 146 | + |
| 147 | +## Examples |
| 148 | + |
| 149 | +### Before (Violations) |
| 150 | +```typescript |
| 151 | +createAction({ |
| 152 | + displayName: 'get recommendations', // Not Title Case |
| 153 | + description: 'Gets recommendations.', // Third-person verb + trailing period |
| 154 | + // ... |
| 155 | +}); |
| 156 | +``` |
| 157 | + |
| 158 | +### After (Compliant) |
| 159 | +```typescript |
| 160 | +createAction({ |
| 161 | + displayName: 'Get Recommendations', // Title Case |
| 162 | + description: 'Get cost optimization recommendations from the provider', // Imperative, no period |
| 163 | + // ... |
| 164 | +}); |
| 165 | +``` |
0 commit comments