@sinemacula/coding-standards 1.12.2 → 1.13.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 +93 -59
- package/js/biome.json +1 -1
- package/js/eslint/type-checked.js +3 -0
- package/js/tsconfig.base.json +27 -0
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -98,10 +98,16 @@ After installing the npm package, extend the shared Biome config from your proje
|
|
|
98
98
|
{
|
|
99
99
|
"$schema": "https://biomejs.dev/schemas/2.0.0/schema.json",
|
|
100
100
|
"root": true,
|
|
101
|
-
"extends": [
|
|
101
|
+
"extends": [
|
|
102
|
+
"@sinemacula/coding-standards/js/biome.json"
|
|
103
|
+
],
|
|
102
104
|
"files": {
|
|
103
105
|
"ignoreUnknown": true,
|
|
104
|
-
"includes": [
|
|
106
|
+
"includes": [
|
|
107
|
+
"**",
|
|
108
|
+
"!**/node_modules/**",
|
|
109
|
+
"!**/vendor/**"
|
|
110
|
+
]
|
|
105
111
|
}
|
|
106
112
|
}
|
|
107
113
|
```
|
|
@@ -189,12 +195,40 @@ package_filters = [
|
|
|
189
195
|
]
|
|
190
196
|
```
|
|
191
197
|
|
|
198
|
+
### TypeScript (tsconfig)
|
|
199
|
+
|
|
200
|
+
The package ships a shared `tsconfig` base so every TypeScript repository checks its code to the same bar. Install the
|
|
201
|
+
package (as above) and extend the base from your `tsconfig.json`:
|
|
202
|
+
|
|
203
|
+
```json
|
|
204
|
+
{
|
|
205
|
+
"extends": "@sinemacula/coding-standards/js/tsconfig.base.json",
|
|
206
|
+
"compilerOptions": {
|
|
207
|
+
"lib": ["ES2023", "DOM", "DOM.Iterable"],
|
|
208
|
+
"types": ["node"]
|
|
209
|
+
},
|
|
210
|
+
"include": ["src"]
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
The base carries only the environment-independent options: the full strictness set and the module/resolution
|
|
215
|
+
discipline. Everything environment-specific stays in the consuming repo and layers on top - `lib` (DOM for the browser,
|
|
216
|
+
none for a Node service), `types`, Vue's `jsx`/`jsxImportSource`, `paths`, `noEmit`, and the `include`/`exclude` globs.
|
|
217
|
+
The `target` and `module` defaults suit bundler-built apps and libraries; a non-bundler project overrides them.
|
|
218
|
+
|
|
219
|
+
The base sets `noPropertyAccessFromIndexSignature`, so a property that comes from an index signature is accessed with
|
|
220
|
+
brackets (`config['key']`), not a dot. Biome cannot see types and so cannot tell that access apart from a normal one,
|
|
221
|
+
which is why its `useLiteralKeys` rule is off and the type-aware `@typescript-eslint/dot-notation` rule enforces dot
|
|
222
|
+
access for real properties instead. Load the type-checked ESLint layer to get it.
|
|
223
|
+
|
|
192
224
|
### Knip (JavaScript / TypeScript)
|
|
193
225
|
|
|
194
226
|
```json
|
|
195
227
|
{
|
|
196
228
|
"$schema": "https://unpkg.com/knip@6/schema.json",
|
|
197
|
-
"extends": [
|
|
229
|
+
"extends": [
|
|
230
|
+
"@sinemacula/coding-standards/js/knip.json"
|
|
231
|
+
]
|
|
198
232
|
}
|
|
199
233
|
```
|
|
200
234
|
|
|
@@ -212,20 +246,20 @@ tag = "<version>"
|
|
|
212
246
|
|
|
213
247
|
## What's Included
|
|
214
248
|
|
|
215
|
-
| Path
|
|
216
|
-
|
|
217
|
-
| `src/PhpCsFixerConfig.php`
|
|
218
|
-
| `php/.php-cs-fixer.rules.php`
|
|
219
|
-
| `SineMacula/ruleset.xml`
|
|
220
|
-
| `php/phpstan-base.neon`
|
|
221
|
-
| `js/biome.json`
|
|
222
|
-
| `js/knip.json`
|
|
223
|
-
| `js/eslint/`
|
|
224
|
-
| `markdown/.markdownlint.json`
|
|
225
|
-
| `yaml/.yamllint.yaml`
|
|
226
|
-
| `shell/.shellcheckrc`
|
|
227
|
-
| `security/.gitleaks.toml`
|
|
228
|
-
| `editorconfig/.editorconfig-checker.json` | editorconfig-checker | Disables only the max-line-length check
|
|
249
|
+
| Path | Tool | Description |
|
|
250
|
+
|-------------------------------------------|----------------------|--------------------------------------------------------|
|
|
251
|
+
| `src/PhpCsFixerConfig.php` | PHP CS Fixer | Factory class for building PHP CS Fixer configurations |
|
|
252
|
+
| `php/.php-cs-fixer.rules.php` | PHP CS Fixer | Shared rules array (PSR-12 base + org conventions) |
|
|
253
|
+
| `SineMacula/ruleset.xml` | PHPCS | Auto-discovered coding standard (PSR-12 + exclusions) |
|
|
254
|
+
| `php/phpstan-base.neon` | PHPStan | Base config (org-wide ignored errors + settings) |
|
|
255
|
+
| `js/biome.json` | Biome | JavaScript / TypeScript formatter + linter rules |
|
|
256
|
+
| `js/knip.json` | Knip | Unused-export detection rules |
|
|
257
|
+
| `js/eslint/` | ESLint | Structural, type-aware + Vue rules; runs with Biome |
|
|
258
|
+
| `markdown/.markdownlint.json` | markdownlint | Markdown linting rules |
|
|
259
|
+
| `yaml/.yamllint.yaml` | yamllint | YAML linting rules |
|
|
260
|
+
| `shell/.shellcheckrc` | ShellCheck | Shell script linting rules |
|
|
261
|
+
| `security/.gitleaks.toml` | Gitleaks | Secret-detection ruleset |
|
|
262
|
+
| `editorconfig/.editorconfig-checker.json` | editorconfig-checker | Disables only the max-line-length check |
|
|
229
263
|
|
|
230
264
|
## Rules
|
|
231
265
|
|
|
@@ -235,38 +269,38 @@ native directive - `// phpcs:ignore <code>` for a sniff, `@phpstan-ignore <ident
|
|
|
235
269
|
|
|
236
270
|
### PHPCS sniffs
|
|
237
271
|
|
|
238
|
-
| Sniff
|
|
239
|
-
|
|
240
|
-
| `SineMacula.Attributes.DisallowToolingAttribute`
|
|
241
|
-
| `SineMacula.Classes.RequireFinalClass`
|
|
242
|
-
| `SineMacula.Classes.RequireReadonlyPublicProperty`
|
|
243
|
-
| `SineMacula.Commenting.CommentLineLength`
|
|
244
|
-
| `SineMacula.Commenting.ConsistentEnumCaseComments`
|
|
245
|
-
| `SineMacula.Commenting.MultilineMethodComment`
|
|
246
|
-
| `SineMacula.Commenting.RequireConstantComment`
|
|
247
|
-
| `SineMacula.Commenting.RequireCopyrightTag`
|
|
248
|
-
| `SineMacula.Commenting.RequireNonPromotedParameterComment` | Plain params mixed with promoted ones need a comment.
|
|
249
|
-
| `SineMacula.Commenting.RequirePromotedPropertyComment`
|
|
250
|
-
| `SineMacula.Commenting.SingleLineMemberComment`
|
|
251
|
-
| `SineMacula.Exceptions.DisallowBaseException`
|
|
252
|
-
| `SineMacula.Exceptions.RequireEmptyCatchComment`
|
|
253
|
-
| `SineMacula.Functions.RequireSensitiveParameter`
|
|
254
|
-
| `SineMacula.Metrics.MaxMethodCount`
|
|
255
|
-
| `SineMacula.Metrics.MethodLength`
|
|
256
|
-
| `SineMacula.Namespaces.RequireConcernsNamespace`
|
|
257
|
-
| `SineMacula.Namespaces.RequireContractsNamespace`
|
|
258
|
-
| `SineMacula.Namespaces.RequireEnumsNamespace`
|
|
259
|
-
| `SineMacula.NamingConventions.BooleanMethodName`
|
|
260
|
-
| `SineMacula.NamingConventions.DisallowInterfacePrefix`
|
|
261
|
-
| `SineMacula.NamingConventions.ValidEnumCaseName`
|
|
262
|
-
| `SineMacula.NamingConventions.ValidGlobalFunctionName`
|
|
263
|
-
| `SineMacula.TypeHints.RequireConstantType`
|
|
264
|
-
| `SineMacula.WhiteSpace.PromotedConstructorSpacing`
|
|
272
|
+
| Sniff | Enforces |
|
|
273
|
+
|------------------------------------------------------------|-----------------------------------------------------------------------------|
|
|
274
|
+
| `SineMacula.Attributes.DisallowToolingAttribute` | No IDE/tooling attributes (e.g. `JetBrains\PhpStorm`). |
|
|
275
|
+
| `SineMacula.Classes.RequireFinalClass` | Concrete classes must be `final` or `abstract` (`@inheritable` opts out). |
|
|
276
|
+
| `SineMacula.Classes.RequireReadonlyPublicProperty` | Public properties (declared or promoted) must be `readonly`. |
|
|
277
|
+
| `SineMacula.Commenting.CommentLineLength` | Standalone comment lines must not exceed 80 chars (FQCN/URL exempt). |
|
|
278
|
+
| `SineMacula.Commenting.ConsistentEnumCaseComments` | Enum case docs are all-or-nothing within an enum. |
|
|
279
|
+
| `SineMacula.Commenting.MultilineMethodComment` | A method's doc comment must span multiple lines. |
|
|
280
|
+
| `SineMacula.Commenting.RequireConstantComment` | Every class/interface/enum/trait constant needs a doc comment. |
|
|
281
|
+
| `SineMacula.Commenting.RequireCopyrightTag` | Class/interface/enum/trait docblocks must carry an `@copyright` tag. |
|
|
282
|
+
| `SineMacula.Commenting.RequireNonPromotedParameterComment` | Plain params mixed with promoted ones need a comment. |
|
|
283
|
+
| `SineMacula.Commenting.RequirePromotedPropertyComment` | Every constructor-promoted property needs a doc comment. |
|
|
284
|
+
| `SineMacula.Commenting.SingleLineMemberComment` | A property, constant or enum-case doc comment sits on one line. |
|
|
285
|
+
| `SineMacula.Exceptions.DisallowBaseException` | No throwing the base `\Exception`; throw a domain exception. |
|
|
286
|
+
| `SineMacula.Exceptions.RequireEmptyCatchComment` | An empty catch block must comment its intentional swallow. |
|
|
287
|
+
| `SineMacula.Functions.RequireSensitiveParameter` | Secret-named params need `#[\SensitiveParameter]`. |
|
|
288
|
+
| `SineMacula.Metrics.MaxMethodCount` | A class/interface/trait/enum may declare at most 20 methods (tests exempt). |
|
|
289
|
+
| `SineMacula.Metrics.MethodLength` | A method body may have at most 50 significant lines (tests exempt). |
|
|
290
|
+
| `SineMacula.Namespaces.RequireConcernsNamespace` | Traits must live under a `Concerns` namespace segment. |
|
|
291
|
+
| `SineMacula.Namespaces.RequireContractsNamespace` | Interfaces must live under a `Contracts` namespace segment. |
|
|
292
|
+
| `SineMacula.Namespaces.RequireEnumsNamespace` | Enums must live under an `Enums` namespace segment. |
|
|
293
|
+
| `SineMacula.NamingConventions.BooleanMethodName` | `bool` methods are predicates; command verbs/@imperative exempt. |
|
|
294
|
+
| `SineMacula.NamingConventions.DisallowInterfacePrefix` | Interface names must not use the Hungarian `I` prefix. |
|
|
295
|
+
| `SineMacula.NamingConventions.ValidEnumCaseName` | Enum cases must be `SCREAMING_SNAKE_CASE`. |
|
|
296
|
+
| `SineMacula.NamingConventions.ValidGlobalFunctionName` | Global functions must be declared in `snake_case`. |
|
|
297
|
+
| `SineMacula.TypeHints.RequireConstantType` | Class/interface/enum/trait constants must declare a native type. |
|
|
298
|
+
| `SineMacula.WhiteSpace.PromotedConstructorSpacing` | Blank line above each promoted-constructor parameter. |
|
|
265
299
|
|
|
266
300
|
### PHPStan rules
|
|
267
301
|
|
|
268
|
-
| Identifier
|
|
269
|
-
|
|
302
|
+
| Identifier | Enforces |
|
|
303
|
+
|------------------------------------|-------------------------------------------------------------------|
|
|
270
304
|
| `sineMacula.mutableStaticProperty` | Static properties written at runtime; `@managed-static` opts out. |
|
|
271
305
|
|
|
272
306
|
### ESLint rules
|
|
@@ -274,19 +308,19 @@ native directive - `// phpcs:ignore <code>` for a sniff, `@phpstan-ignore <ident
|
|
|
274
308
|
All rules run in the base layer except `boolean-method-name`, which resolves return types and so requires the opt-in
|
|
275
309
|
type-checked layer.
|
|
276
310
|
|
|
277
|
-
| Rule
|
|
278
|
-
|
|
279
|
-
| `@sinemacula/no-interface-prefix`
|
|
280
|
-
| `@sinemacula/require-readonly-public-property` | Public class properties (declared or promoted) must be `readonly`.
|
|
281
|
-
| `@sinemacula/valid-enum-member-name`
|
|
282
|
-
| `@sinemacula/boolean-method-name`
|
|
283
|
-
| `@sinemacula/no-mutable-static`
|
|
284
|
-
| `@sinemacula/max-methods-per-class`
|
|
285
|
-
| `@sinemacula/no-base-error`
|
|
286
|
-
| `@sinemacula/require-copyright`
|
|
287
|
-
| `@sinemacula/align-doc-tags`
|
|
288
|
-
| `@sinemacula/single-line-property-doc`
|
|
289
|
-
| `@sinemacula/multiline-function-doc`
|
|
311
|
+
| Rule | Enforces |
|
|
312
|
+
|------------------------------------------------|-------------------------------------------------------------------------------------|
|
|
313
|
+
| `@sinemacula/no-interface-prefix` | Interface and type-alias names must not use the Hungarian `I` prefix. |
|
|
314
|
+
| `@sinemacula/require-readonly-public-property` | Public class properties (declared or promoted) must be `readonly`. |
|
|
315
|
+
| `@sinemacula/valid-enum-member-name` | Enum members must be declared in `SCREAMING_SNAKE_CASE`. |
|
|
316
|
+
| `@sinemacula/boolean-method-name` | Boolean-returning methods need an is/has/can prefix; `@imperative` exempt. |
|
|
317
|
+
| `@sinemacula/no-mutable-static` | No mutable exported bindings or mutable `static` class fields; test code exempt. |
|
|
318
|
+
| `@sinemacula/max-methods-per-class` | A single class may declare at most 20 methods; test code exempt. |
|
|
319
|
+
| `@sinemacula/no-base-error` | Throw a domain-specific `Error` subclass, never the base `Error`; test code exempt. |
|
|
320
|
+
| `@sinemacula/require-copyright` | Every file must carry a documentation comment with `@copyright` and `@author`. |
|
|
321
|
+
| `@sinemacula/align-doc-tags` | `@author` and `@copyright` values line up at a single column; autofixable. |
|
|
322
|
+
| `@sinemacula/single-line-property-doc` | A data member's documentation comment sits on one line; autofixable. |
|
|
323
|
+
| `@sinemacula/multiline-function-doc` | A method's documentation comment spans multiple lines; autofixable. |
|
|
290
324
|
|
|
291
325
|
`boolean-method-name` takes `additionalPrefixes`, `additionalPredicates` and `additionalCommandVerbs` (string arrays)
|
|
292
326
|
to widen the accepted vocabulary from a consumer config. `max-methods-per-class` takes `max`, `no-base-error` takes
|
package/js/biome.json
CHANGED
|
@@ -31,6 +31,9 @@ export default [
|
|
|
31
31
|
|
|
32
32
|
'@typescript-eslint/await-thenable': 'error',
|
|
33
33
|
'@typescript-eslint/consistent-type-imports': 'error',
|
|
34
|
+
// Type-aware replacement for Biome's useLiteralKeys: dot access for
|
|
35
|
+
// real properties, bracket access allowed on index signatures.
|
|
36
|
+
'@typescript-eslint/dot-notation': ['error', { allowIndexSignaturePropertyAccess: true }],
|
|
34
37
|
'@typescript-eslint/explicit-module-boundary-types': 'error',
|
|
35
38
|
'@typescript-eslint/no-floating-promises': 'error',
|
|
36
39
|
'@typescript-eslint/no-misused-promises': 'error',
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/tsconfig",
|
|
3
|
+
"display": "@sinemacula/coding-standards base",
|
|
4
|
+
"compilerOptions": {
|
|
5
|
+
"target": "ES2023",
|
|
6
|
+
"module": "Preserve",
|
|
7
|
+
"moduleResolution": "Bundler",
|
|
8
|
+
"moduleDetection": "force",
|
|
9
|
+
"verbatimModuleSyntax": true,
|
|
10
|
+
"isolatedModules": true,
|
|
11
|
+
"resolveJsonModule": true,
|
|
12
|
+
"esModuleInterop": true,
|
|
13
|
+
"strict": true,
|
|
14
|
+
"noUncheckedIndexedAccess": true,
|
|
15
|
+
"noPropertyAccessFromIndexSignature": true,
|
|
16
|
+
"exactOptionalPropertyTypes": true,
|
|
17
|
+
"noImplicitOverride": true,
|
|
18
|
+
"noFallthroughCasesInSwitch": true,
|
|
19
|
+
"noImplicitReturns": true,
|
|
20
|
+
"allowUnreachableCode": false,
|
|
21
|
+
"noUnusedLocals": true,
|
|
22
|
+
"noUnusedParameters": true,
|
|
23
|
+
"noUncheckedSideEffectImports": true,
|
|
24
|
+
"forceConsistentCasingInFileNames": true,
|
|
25
|
+
"skipLibCheck": true
|
|
26
|
+
}
|
|
27
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sinemacula/coding-standards",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.13.0",
|
|
4
4
|
"description": "Centralized coding standards, static analysis configurations, and code quality tooling for all Sine Macula repositories.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Ben Carey <bdmc@sinemacula.co.uk>",
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"biome",
|
|
17
17
|
"knip",
|
|
18
18
|
"eslint",
|
|
19
|
+
"typescript",
|
|
19
20
|
"coding-standards",
|
|
20
21
|
"linting",
|
|
21
22
|
"config"
|
|
@@ -36,6 +37,7 @@
|
|
|
36
37
|
"./js/eslint": "./js/eslint/index.js",
|
|
37
38
|
"./js/eslint/type-checked": "./js/eslint/type-checked.js",
|
|
38
39
|
"./js/eslint/vue": "./js/eslint/vue.js",
|
|
40
|
+
"./js/tsconfig.base.json": "./js/tsconfig.base.json",
|
|
39
41
|
"./*": "./*"
|
|
40
42
|
},
|
|
41
43
|
"scripts": {
|