@qvaroo/configs 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,391 @@
1
+ # @qvaro/configs
2
+
3
+ > **Centralized Qvaro coding standards for TypeScript frontend projects.**
4
+ >
5
+ > This library acts as the **single source of truth** for all coding, architecture, and tooling standards. All rule violations **fail CI/CD pipelines**, removing human discretion from standards enforcement.
6
+
7
+ [![npm version](https://img.shields.io/npm/v/@qvaro/configs.svg)](https://www.npmjs.com/package/@qvaro/configs)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
+
10
+ ---
11
+
12
+ ## 📦 Installation
13
+
14
+ ```bash
15
+ npm install --save-dev @qvaro/configs
16
+ ```
17
+
18
+ ### Peer Dependencies
19
+
20
+ Ensure these are installed in your project:
21
+
22
+ ```bash
23
+ npm install --save-dev eslint prettier typescript
24
+ ```
25
+
26
+ ---
27
+
28
+ ## 🚀 Quick Setup
29
+
30
+ ### 1. ESLint Configuration
31
+
32
+ Create `.eslintrc.js` in your project root:
33
+
34
+ **For React/Next.js projects:**
35
+ ```javascript
36
+ module.exports = {
37
+ extends: ['./node_modules/@qvaro/configs/eslint/react.js'],
38
+ parserOptions: {
39
+ project: './tsconfig.json',
40
+ tsconfigRootDir: __dirname,
41
+ },
42
+ };
43
+ ```
44
+
45
+ **For Node.js/Backend projects:**
46
+ ```javascript
47
+ module.exports = {
48
+ extends: ['./node_modules/@qvaro/configs/eslint/node.js'],
49
+ parserOptions: {
50
+ project: './tsconfig.json',
51
+ tsconfigRootDir: __dirname,
52
+ },
53
+ };
54
+ ```
55
+
56
+ **For base TypeScript projects:**
57
+ ```javascript
58
+ module.exports = {
59
+ extends: ['./node_modules/@qvaro/configs/eslint/index.js'],
60
+ parserOptions: {
61
+ project: './tsconfig.json',
62
+ tsconfigRootDir: __dirname,
63
+ },
64
+ };
65
+ ```
66
+
67
+ ### 2. Prettier Configuration
68
+
69
+ Create `prettier.config.js`:
70
+
71
+ ```javascript
72
+ module.exports = require('@qvaro/configs/prettier');
73
+ ```
74
+
75
+ ### 3. TypeScript Configuration
76
+
77
+ Create `tsconfig.json`:
78
+
79
+ **For React projects:**
80
+ ```json
81
+ {
82
+ "extends": "@qvaro/configs/typescript/react",
83
+ "compilerOptions": {
84
+ "baseUrl": "."
85
+ },
86
+ "include": ["src/**/*"],
87
+ "exclude": ["node_modules", "dist"]
88
+ }
89
+ ```
90
+
91
+ **For Node.js projects:**
92
+ ```json
93
+ {
94
+ "extends": "@qvaro/configs/typescript/node",
95
+ "compilerOptions": {
96
+ "baseUrl": "."
97
+ },
98
+ "include": ["src/**/*"],
99
+ "exclude": ["node_modules", "dist"]
100
+ }
101
+ ```
102
+
103
+ ---
104
+
105
+ ## 📐 Enforced Standards
106
+
107
+ ### Naming Conventions
108
+
109
+ | Element | Format | Example |
110
+ |---------|--------|---------|
111
+ | Classes, Controllers, Models | `PascalCase` | `UserController` |
112
+ | UI Components | `PascalCase` | `NavigationBar` |
113
+ | Interfaces | `IPascalCase` | `IUserService` |
114
+ | Local variables | `camelCase` | `userData` |
115
+ | Method parameters | `camelCase` | `userId` |
116
+ | Constants | `UPPER_SNAKE_CASE` | `MAX_RETRY_COUNT` |
117
+ | Private methods | `_camelCase` | `_validateInput` |
118
+ | Async methods | `*Async` suffix | `fetchUserAsync` |
119
+
120
+ ### Code Quality Limits
121
+
122
+ | Rule | Limit | Severity |
123
+ |------|-------|----------|
124
+ | Method length | 40 lines max | ❌ Error |
125
+ | File/Class length | 300 lines max | ❌ Error |
126
+ | Nested if statements | 2 levels max | ❌ Error |
127
+ | Cyclomatic complexity | 10 max | ❌ Error |
128
+ | Function parameters | 4 max | ❌ Error |
129
+
130
+ ### Prohibited Patterns
131
+
132
+ - ❌ Magic strings/numbers (use constants)
133
+ - ❌ Empty catch blocks (must log & rethrow)
134
+ - ❌ Deeply nested code (use guard clauses)
135
+ - ❌ Floating promises (must await or handle)
136
+ - ❌ Any type usage (must be explicit)
137
+
138
+ ---
139
+
140
+ ## 🏗️ Folder Structure Enforcement
141
+
142
+ Required project structure:
143
+
144
+ ```
145
+ src/
146
+ ├── api/ # API clients & endpoints
147
+ ├── components/ # Reusable UI components
148
+ ├── services/ # Business logic layer
149
+ ├── events/ # Event handlers & emitters
150
+ ├── animations/ # Animation definitions
151
+ ├── styles/ # Global styles & themes
152
+ ├── hooks/ # Custom React hooks
153
+ ├── views/ # Page-level components (presentation only)
154
+ ├── types/ # TypeScript interfaces & types
155
+ ├── constants/ # Application constants
156
+ └── utils/ # Utility functions
157
+ ```
158
+
159
+ ### Boundary Rules
160
+
161
+ | Layer | Can Import From |
162
+ |-------|-----------------|
163
+ | `views` | components, styles, hooks, animations, constants |
164
+ | `components` | components, styles, hooks, utils, types, animations |
165
+ | `hooks` | services, api, types, utils |
166
+ | `services` | api, types, utils, constants |
167
+ | `api` | types, utils, constants |
168
+
169
+ > ⚠️ **Views cannot import from `api` or `services` directly!** Use hooks instead.
170
+
171
+ ---
172
+
173
+ ## 🔧 CI/CD Integration
174
+
175
+ ### GitHub Actions
176
+
177
+ ```yaml
178
+ name: Lint & Type Check
179
+
180
+ on: [push, pull_request]
181
+
182
+ jobs:
183
+ lint:
184
+ runs-on: ubuntu-latest
185
+ steps:
186
+ - uses: actions/checkout@v4
187
+ - uses: actions/setup-node@v4
188
+ with:
189
+ node-version: '20'
190
+ cache: 'npm'
191
+
192
+ - run: npm ci
193
+ - run: npm run lint
194
+ # Fails on any lint error
195
+ - run: npx tsc --noEmit
196
+ # Fails on type errors
197
+ ```
198
+
199
+ ### Package.json Scripts
200
+
201
+ ```json
202
+ {
203
+ "scripts": {
204
+ "lint": "eslint . --ext .ts,.tsx --max-warnings 0",
205
+ "lint:fix": "eslint . --ext .ts,.tsx --fix",
206
+ "format": "prettier --write \"src/**/*.{ts,tsx,json,css}\"",
207
+ "format:check": "prettier --check \"src/**/*.{ts,tsx,json,css}\"",
208
+ "typecheck": "tsc --noEmit"
209
+ }
210
+ }
211
+ ```
212
+
213
+ ---
214
+
215
+ ## 📝 Examples
216
+
217
+ ### ✅ Correct Naming
218
+
219
+ ```typescript
220
+ // Constants - UPPER_SNAKE_CASE
221
+ const MAX_RETRY_ATTEMPTS = 3;
222
+ const API_BASE_URL = 'https://api.example.com';
223
+
224
+ // Interface - IPascalCase
225
+ interface IUserProfile {
226
+ id: string;
227
+ displayName: string;
228
+ }
229
+
230
+ // Class - PascalCase
231
+ class UserService {
232
+ // Private property - _camelCase
233
+ private readonly _httpClient: IHttpClient;
234
+
235
+ // Async method - ends with Async
236
+ public async fetchUserAsync(userId: string): Promise<IUserProfile> {
237
+ return await this._httpClient.getAsync(`/users/${userId}`);
238
+ }
239
+
240
+ // Private async method
241
+ private async _validateTokenAsync(): Promise<boolean> {
242
+ // ...
243
+ }
244
+ }
245
+ ```
246
+
247
+ ### ❌ Incorrect (Will Fail)
248
+
249
+ ```typescript
250
+ // ❌ Magic number
251
+ if (retryCount > 3) { }
252
+
253
+ // ❌ Interface without I prefix
254
+ interface UserProfile { }
255
+
256
+ // ❌ Async method without Async suffix
257
+ async function fetchUser() { }
258
+
259
+ // ❌ Empty catch block
260
+ try {
261
+ await riskyOperation();
262
+ } catch (e) {
263
+ // Empty - will error!
264
+ }
265
+
266
+ // ❌ Too much nesting
267
+ if (a) {
268
+ if (b) {
269
+ if (c) { // Error: max depth 2
270
+ }
271
+ }
272
+ }
273
+ ```
274
+
275
+ ### ✅ Guard Clause Pattern
276
+
277
+ ```typescript
278
+ // ✅ Preferred: Early returns
279
+ function processUser(user: IUser | null): void {
280
+ if (!user) {
281
+ throw new Error('User is required');
282
+ }
283
+
284
+ if (!user.isActive) {
285
+ return;
286
+ }
287
+
288
+ // Main logic here (flat, readable)
289
+ performAction(user);
290
+ }
291
+
292
+ // ❌ Avoid: Deep nesting
293
+ function processUser(user: IUser | null): void {
294
+ if (user) {
295
+ if (user.isActive) {
296
+ performAction(user);
297
+ }
298
+ } else {
299
+ throw new Error('User is required');
300
+ }
301
+ }
302
+ ```
303
+
304
+ ---
305
+
306
+ ## 🔄 Extending Rules
307
+
308
+ Override specific rules in your project's `.eslintrc.js`:
309
+
310
+ ```javascript
311
+ module.exports = {
312
+ extends: ['./node_modules/@qvaro/configs/eslint/react.js'],
313
+ rules: {
314
+ // Relax for specific project needs
315
+ 'max-lines-per-function': ['error', { max: 60 }],
316
+
317
+ // Add project-specific rules
318
+ 'no-restricted-imports': ['error', {
319
+ patterns: ['lodash/*'],
320
+ }],
321
+ },
322
+ };
323
+ ```
324
+
325
+ ---
326
+
327
+ ## 📋 Spellcheck Configuration
328
+
329
+ Variable names are checked for spelling. Add project-specific terms:
330
+
331
+ ```javascript
332
+ module.exports = {
333
+ extends: ['./node_modules/@qvaro/configs/eslint'],
334
+ rules: {
335
+ 'spellcheck/spell-checker': ['warn', {
336
+ skipWords: [
337
+ // Add your domain terms
338
+ 'qvaro',
339
+ 'oauth',
340
+ 'saml',
341
+ ],
342
+ }],
343
+ },
344
+ };
345
+ ```
346
+
347
+ ---
348
+
349
+ ## 🛡️ Enforcement Philosophy
350
+
351
+ > *"All rules are strictly enforced. Violations fail CI/CD pipelines. This library acts as the single source of truth, removing human discretion from coding standards enforcement."*
352
+
353
+ ### Why Strict Enforcement?
354
+
355
+ 1. **Consistency** - Every project follows identical standards
356
+ 2. **Onboarding** - New developers learn patterns immediately
357
+ 3. **Code Review** - Focus on logic, not style debates
358
+ 4. **Maintainability** - Consistent code is easier to maintain
359
+ 5. **Quality** - Prevents common bugs before they ship
360
+
361
+ ---
362
+
363
+ ## 📁 Package Contents
364
+
365
+ ```
366
+ @qvaro/configs/
367
+ ├── eslint/
368
+ │ ├── index.js # Base ESLint config
369
+ │ ├── react.js # React/Next.js config
370
+ │ ├── node.js # Node.js/Backend config
371
+ │ └── rules/
372
+ │ ├── naming-conventions.js
373
+ │ ├── code-quality.js
374
+ │ ├── architecture.js
375
+ │ └── spellcheck.js
376
+ ├── prettier/
377
+ │ └── index.js # Prettier config
378
+ ├── typescript/
379
+ │ ├── tsconfig.json # Base TS config
380
+ │ ├── tsconfig.react.json # React TS config
381
+ │ └── tsconfig.node.json # Node.js TS config
382
+ ├── index.js
383
+ ├── index.d.ts
384
+ └── package.json
385
+ ```
386
+
387
+ ---
388
+
389
+ ## 📄 License
390
+
391
+ MIT © Qvaro DevOps Team
@@ -0,0 +1,222 @@
1
+ /**
2
+ * @qvaroo/configs - ESLint Configuration
3
+ *
4
+ * Strict Qvaroo-wide ESLint rules for TypeScript projects.
5
+ * All violations will fail CI/CD pipelines.
6
+ *
7
+ * @author Qvaroo DevOps Team
8
+ * @version 1.0.0
9
+ */
10
+
11
+ const namingConventionRules = require('./rules/naming-conventions');
12
+ const codeQualityRules = require('./rules/code-quality');
13
+ const architectureRules = require('./rules/architecture');
14
+ const spellcheckRules = require('./rules/spellcheck');
15
+
16
+ /** @type {import('eslint').Linter.Config} */
17
+ module.exports = {
18
+ root: true,
19
+
20
+ parser: '@typescript-eslint/parser',
21
+
22
+ parserOptions: {
23
+ ecmaVersion: 2022,
24
+ sourceType: 'module',
25
+ project: './tsconfig.json',
26
+ tsconfigRootDir: process.cwd(),
27
+ },
28
+
29
+ plugins: [
30
+ '@typescript-eslint',
31
+ 'spellcheck',
32
+ 'boundaries',
33
+ 'import',
34
+ 'promise',
35
+ 'unicorn',
36
+ 'sonarjs',
37
+ ],
38
+
39
+ extends: [
40
+ 'eslint:recommended',
41
+ 'plugin:@typescript-eslint/recommended',
42
+ 'plugin:@typescript-eslint/recommended-requiring-type-checking',
43
+ 'plugin:@typescript-eslint/strict',
44
+ 'plugin:import/recommended',
45
+ 'plugin:import/typescript',
46
+ 'plugin:promise/recommended',
47
+ 'plugin:sonarjs/recommended',
48
+ 'prettier', // Must be last to override formatting rules
49
+ ],
50
+
51
+ settings: {
52
+ 'import/resolver': {
53
+ typescript: {
54
+ alwaysTryTypes: true,
55
+ project: './tsconfig.json',
56
+ },
57
+ },
58
+ 'boundaries/elements': [
59
+ { type: 'api', pattern: 'src/api/*' },
60
+ { type: 'components', pattern: 'src/components/*' },
61
+ { type: 'services', pattern: 'src/services/*' },
62
+ { type: 'events', pattern: 'src/events/*' },
63
+ { type: 'animations', pattern: 'src/animations/*' },
64
+ { type: 'styles', pattern: 'src/styles/*' },
65
+ { type: 'utils', pattern: 'src/utils/*' },
66
+ { type: 'types', pattern: 'src/types/*' },
67
+ { type: 'constants', pattern: 'src/constants/*' },
68
+ { type: 'hooks', pattern: 'src/hooks/*' },
69
+ { type: 'views', pattern: 'src/views/*' },
70
+ ],
71
+ },
72
+
73
+ rules: {
74
+ // ═══════════════════════════════════════════════════════════════════════
75
+ // NAMING CONVENTIONS - Strict enforcement
76
+ // ═══════════════════════════════════════════════════════════════════════
77
+ ...namingConventionRules,
78
+
79
+ // ═══════════════════════════════════════════════════════════════════════
80
+ // CODE QUALITY - Method/class length, nesting, magic values
81
+ // ═══════════════════════════════════════════════════════════════════════
82
+ ...codeQualityRules,
83
+
84
+ // ═══════════════════════════════════════════════════════════════════════
85
+ // ARCHITECTURE - Folder boundaries and separation of concerns
86
+ // ═══════════════════════════════════════════════════════════════════════
87
+ ...architectureRules,
88
+
89
+ // ═══════════════════════════════════════════════════════════════════════
90
+ // SPELLCHECK - Variable name clarity
91
+ // ═══════════════════════════════════════════════════════════════════════
92
+ ...spellcheckRules,
93
+
94
+ // ═══════════════════════════════════════════════════════════════════════
95
+ // ERROR HANDLING - No empty catches, must log & rethrow
96
+ // ═══════════════════════════════════════════════════════════════════════
97
+ 'no-empty': ['error', { allowEmptyCatch: false }],
98
+ '@typescript-eslint/no-empty-function': 'error',
99
+ 'no-useless-catch': 'error',
100
+
101
+ // ═══════════════════════════════════════════════════════════════════════
102
+ // PROMISE/ASYNC HANDLING
103
+ // ═══════════════════════════════════════════════════════════════════════
104
+ '@typescript-eslint/no-floating-promises': 'error',
105
+ '@typescript-eslint/no-misused-promises': 'error',
106
+ '@typescript-eslint/promise-function-async': 'error',
107
+ 'promise/always-return': 'error',
108
+ 'promise/no-return-wrap': 'error',
109
+ 'promise/param-names': 'error',
110
+ 'promise/catch-or-return': 'error',
111
+ 'promise/no-nesting': 'warn',
112
+
113
+ // ═══════════════════════════════════════════════════════════════════════
114
+ // IMPORT ORGANIZATION
115
+ // ═══════════════════════════════════════════════════════════════════════
116
+ 'import/order': [
117
+ 'error',
118
+ {
119
+ groups: [
120
+ 'builtin',
121
+ 'external',
122
+ 'internal',
123
+ 'parent',
124
+ 'sibling',
125
+ 'index',
126
+ 'type',
127
+ ],
128
+ 'newlines-between': 'always',
129
+ alphabetize: { order: 'asc', caseInsensitive: true },
130
+ },
131
+ ],
132
+ 'import/no-duplicates': 'error',
133
+ 'import/no-unresolved': 'error',
134
+ 'import/no-cycle': 'error',
135
+
136
+ // ═══════════════════════════════════════════════════════════════════════
137
+ // GENERAL BEST PRACTICES
138
+ // ═══════════════════════════════════════════════════════════════════════
139
+ 'no-console': ['error', { allow: ['warn', 'error', 'info'] }],
140
+ 'no-debugger': 'error',
141
+ 'no-alert': 'error',
142
+ 'prefer-const': 'error',
143
+ 'no-var': 'error',
144
+ 'eqeqeq': ['error', 'always'],
145
+ 'curly': ['error', 'all'],
146
+ 'no-eval': 'error',
147
+ 'no-implied-eval': 'error',
148
+ 'no-new-func': 'error',
149
+ 'no-return-await': 'off', // Handled by @typescript-eslint/return-await
150
+ '@typescript-eslint/return-await': ['error', 'in-try-catch'],
151
+ '@typescript-eslint/explicit-function-return-type': [
152
+ 'error',
153
+ {
154
+ allowExpressions: true,
155
+ allowTypedFunctionExpressions: true,
156
+ allowHigherOrderFunctions: true,
157
+ },
158
+ ],
159
+ '@typescript-eslint/explicit-member-accessibility': [
160
+ 'error',
161
+ { accessibility: 'explicit' },
162
+ ],
163
+ '@typescript-eslint/no-explicit-any': 'error',
164
+ '@typescript-eslint/no-unused-vars': [
165
+ 'error',
166
+ { argsIgnorePattern: '^_', varsIgnorePattern: '^_' },
167
+ ],
168
+
169
+ // ═══════════════════════════════════════════════════════════════════════
170
+ // UNICORN - Modern JavaScript practices
171
+ // ═══════════════════════════════════════════════════════════════════════
172
+ 'unicorn/prefer-module': 'error',
173
+ 'unicorn/prefer-node-protocol': 'error',
174
+ 'unicorn/prefer-top-level-await': 'error',
175
+ 'unicorn/no-null': 'off', // Allow null for React patterns
176
+ 'unicorn/prevent-abbreviations': [
177
+ 'error',
178
+ {
179
+ replacements: {
180
+ props: false,
181
+ params: false,
182
+ args: false,
183
+ ref: false,
184
+ err: false,
185
+ ctx: false,
186
+ req: false,
187
+ res: false,
188
+ },
189
+ },
190
+ ],
191
+ },
192
+
193
+ overrides: [
194
+ // Test files - relaxed rules
195
+ {
196
+ files: ['**/*.test.ts', '**/*.test.tsx', '**/*.spec.ts', '**/*.spec.tsx'],
197
+ rules: {
198
+ '@typescript-eslint/no-explicit-any': 'off',
199
+ 'sonarjs/no-duplicate-string': 'off',
200
+ 'max-lines-per-function': 'off',
201
+ },
202
+ },
203
+ // Configuration files
204
+ {
205
+ files: ['*.config.js', '*.config.ts', '.eslintrc.js'],
206
+ rules: {
207
+ '@typescript-eslint/no-var-requires': 'off',
208
+ 'unicorn/prefer-module': 'off',
209
+ },
210
+ },
211
+ ],
212
+
213
+ ignorePatterns: [
214
+ 'node_modules/',
215
+ 'dist/',
216
+ 'build/',
217
+ 'coverage/',
218
+ '.next/',
219
+ '*.min.js',
220
+ '*.generated.ts',
221
+ ],
222
+ };