@composurecdk/eslint-plugin 0.10.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/LICENSE +21 -0
- package/README.md +138 -0
- package/dist/commonjs/configs/presets.d.ts +42 -0
- package/dist/commonjs/configs/presets.d.ts.map +1 -0
- package/dist/commonjs/configs/presets.js +58 -0
- package/dist/commonjs/configs/presets.js.map +1 -0
- package/dist/commonjs/index.d.ts +84 -0
- package/dist/commonjs/index.d.ts.map +1 -0
- package/dist/commonjs/index.js +63 -0
- package/dist/commonjs/index.js.map +1 -0
- package/dist/commonjs/package.json +3 -0
- package/dist/commonjs/rules/builder-must-be-tagged.d.ts +15 -0
- package/dist/commonjs/rules/builder-must-be-tagged.d.ts.map +1 -0
- package/dist/commonjs/rules/builder-must-be-tagged.js +70 -0
- package/dist/commonjs/rules/builder-must-be-tagged.js.map +1 -0
- package/dist/commonjs/rules/builder-must-implement-copy-state.d.ts +13 -0
- package/dist/commonjs/rules/builder-must-implement-copy-state.d.ts.map +1 -0
- package/dist/commonjs/rules/builder-must-implement-copy-state.js +123 -0
- package/dist/commonjs/rules/builder-must-implement-copy-state.js.map +1 -0
- package/dist/commonjs/rules/constraint-metadata-required.d.ts +16 -0
- package/dist/commonjs/rules/constraint-metadata-required.d.ts.map +1 -0
- package/dist/commonjs/rules/constraint-metadata-required.js +79 -0
- package/dist/commonjs/rules/constraint-metadata-required.js.map +1 -0
- package/dist/commonjs/rules/index.d.ts +14 -0
- package/dist/commonjs/rules/index.d.ts.map +1 -0
- package/dist/commonjs/rules/index.js +52 -0
- package/dist/commonjs/rules/index.js.map +1 -0
- package/dist/commonjs/rules/lib/imports.d.ts +24 -0
- package/dist/commonjs/rules/lib/imports.d.ts.map +1 -0
- package/dist/commonjs/rules/lib/imports.js +76 -0
- package/dist/commonjs/rules/lib/imports.js.map +1 -0
- package/dist/commonjs/rules/lifecycle-build-context-required.d.ts +14 -0
- package/dist/commonjs/rules/lifecycle-build-context-required.d.ts.map +1 -0
- package/dist/commonjs/rules/lifecycle-build-context-required.js +46 -0
- package/dist/commonjs/rules/lifecycle-build-context-required.js.map +1 -0
- package/dist/commonjs/rules/lifecycle-build-must-forward-context.d.ts +18 -0
- package/dist/commonjs/rules/lifecycle-build-must-forward-context.d.ts.map +1 -0
- package/dist/commonjs/rules/lifecycle-build-must-forward-context.js +54 -0
- package/dist/commonjs/rules/lifecycle-build-must-forward-context.js.map +1 -0
- package/dist/commonjs/rules/no-cdk-api-above-floor.d.ts +15 -0
- package/dist/commonjs/rules/no-cdk-api-above-floor.d.ts.map +1 -0
- package/dist/commonjs/rules/no-cdk-api-above-floor.js +80 -0
- package/dist/commonjs/rules/no-cdk-api-above-floor.js.map +1 -0
- package/dist/commonjs/rules/no-cjs-incompatible-syntax.d.ts +14 -0
- package/dist/commonjs/rules/no-cjs-incompatible-syntax.d.ts.map +1 -0
- package/dist/commonjs/rules/no-cjs-incompatible-syntax.js +55 -0
- package/dist/commonjs/rules/no-cjs-incompatible-syntax.js.map +1 -0
- package/dist/commonjs/rules/no-realm-bound-instanceof.d.ts +25 -0
- package/dist/commonjs/rules/no-realm-bound-instanceof.d.ts.map +1 -0
- package/dist/commonjs/rules/no-realm-bound-instanceof.js +98 -0
- package/dist/commonjs/rules/no-realm-bound-instanceof.js.map +1 -0
- package/dist/commonjs/rules/no-typescript-private-modifier.d.ts +17 -0
- package/dist/commonjs/rules/no-typescript-private-modifier.d.ts.map +1 -0
- package/dist/commonjs/rules/no-typescript-private-modifier.js +91 -0
- package/dist/commonjs/rules/no-typescript-private-modifier.js.map +1 -0
- package/dist/commonjs/rules/redeclared-prop-must-track-cdk-type.d.ts +17 -0
- package/dist/commonjs/rules/redeclared-prop-must-track-cdk-type.d.ts.map +1 -0
- package/dist/commonjs/rules/redeclared-prop-must-track-cdk-type.js +152 -0
- package/dist/commonjs/rules/redeclared-prop-must-track-cdk-type.js.map +1 -0
- package/dist/esm/configs/presets.d.ts +42 -0
- package/dist/esm/configs/presets.d.ts.map +1 -0
- package/dist/esm/configs/presets.js +55 -0
- package/dist/esm/configs/presets.js.map +1 -0
- package/dist/esm/index.d.ts +84 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +60 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/rules/builder-must-be-tagged.d.ts +15 -0
- package/dist/esm/rules/builder-must-be-tagged.d.ts.map +1 -0
- package/dist/esm/rules/builder-must-be-tagged.js +67 -0
- package/dist/esm/rules/builder-must-be-tagged.js.map +1 -0
- package/dist/esm/rules/builder-must-implement-copy-state.d.ts +13 -0
- package/dist/esm/rules/builder-must-implement-copy-state.d.ts.map +1 -0
- package/dist/esm/rules/builder-must-implement-copy-state.js +120 -0
- package/dist/esm/rules/builder-must-implement-copy-state.js.map +1 -0
- package/dist/esm/rules/constraint-metadata-required.d.ts +16 -0
- package/dist/esm/rules/constraint-metadata-required.d.ts.map +1 -0
- package/dist/esm/rules/constraint-metadata-required.js +76 -0
- package/dist/esm/rules/constraint-metadata-required.js.map +1 -0
- package/dist/esm/rules/index.d.ts +14 -0
- package/dist/esm/rules/index.d.ts.map +1 -0
- package/dist/esm/rules/index.js +49 -0
- package/dist/esm/rules/index.js.map +1 -0
- package/dist/esm/rules/lib/imports.d.ts +24 -0
- package/dist/esm/rules/lib/imports.d.ts.map +1 -0
- package/dist/esm/rules/lib/imports.js +70 -0
- package/dist/esm/rules/lib/imports.js.map +1 -0
- package/dist/esm/rules/lifecycle-build-context-required.d.ts +14 -0
- package/dist/esm/rules/lifecycle-build-context-required.d.ts.map +1 -0
- package/dist/esm/rules/lifecycle-build-context-required.js +43 -0
- package/dist/esm/rules/lifecycle-build-context-required.js.map +1 -0
- package/dist/esm/rules/lifecycle-build-must-forward-context.d.ts +18 -0
- package/dist/esm/rules/lifecycle-build-must-forward-context.d.ts.map +1 -0
- package/dist/esm/rules/lifecycle-build-must-forward-context.js +51 -0
- package/dist/esm/rules/lifecycle-build-must-forward-context.js.map +1 -0
- package/dist/esm/rules/no-cdk-api-above-floor.d.ts +15 -0
- package/dist/esm/rules/no-cdk-api-above-floor.d.ts.map +1 -0
- package/dist/esm/rules/no-cdk-api-above-floor.js +77 -0
- package/dist/esm/rules/no-cdk-api-above-floor.js.map +1 -0
- package/dist/esm/rules/no-cjs-incompatible-syntax.d.ts +14 -0
- package/dist/esm/rules/no-cjs-incompatible-syntax.d.ts.map +1 -0
- package/dist/esm/rules/no-cjs-incompatible-syntax.js +52 -0
- package/dist/esm/rules/no-cjs-incompatible-syntax.js.map +1 -0
- package/dist/esm/rules/no-realm-bound-instanceof.d.ts +25 -0
- package/dist/esm/rules/no-realm-bound-instanceof.d.ts.map +1 -0
- package/dist/esm/rules/no-realm-bound-instanceof.js +95 -0
- package/dist/esm/rules/no-realm-bound-instanceof.js.map +1 -0
- package/dist/esm/rules/no-typescript-private-modifier.d.ts +17 -0
- package/dist/esm/rules/no-typescript-private-modifier.d.ts.map +1 -0
- package/dist/esm/rules/no-typescript-private-modifier.js +88 -0
- package/dist/esm/rules/no-typescript-private-modifier.js.map +1 -0
- package/dist/esm/rules/redeclared-prop-must-track-cdk-type.d.ts +17 -0
- package/dist/esm/rules/redeclared-prop-must-track-cdk-type.d.ts.map +1 -0
- package/dist/esm/rules/redeclared-prop-must-track-cdk-type.js +149 -0
- package/dist/esm/rules/redeclared-prop-must-track-cdk-type.js.map +1 -0
- package/docs/rules/builder-must-be-tagged.md +46 -0
- package/docs/rules/builder-must-implement-copy-state.md +50 -0
- package/docs/rules/constraint-metadata-required.md +44 -0
- package/docs/rules/lifecycle-build-context-required.md +39 -0
- package/docs/rules/lifecycle-build-must-forward-context.md +50 -0
- package/docs/rules/no-cdk-api-above-floor.md +56 -0
- package/docs/rules/no-cjs-incompatible-syntax.md +48 -0
- package/docs/rules/no-realm-bound-instanceof.md +87 -0
- package/docs/rules/no-typescript-private-modifier.md +72 -0
- package/docs/rules/redeclared-prop-must-track-cdk-type.md +60 -0
- package/package.json +81 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jason Duffett
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# @composurecdk/eslint-plugin
|
|
2
|
+
|
|
3
|
+
Internal ESLint plugin encoding ComposureCDK architectural invariants — tagged builders, lifecycle context, builder copy state.
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
npm install --save-dev @composurecdk/eslint-plugin
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Ships a dual ESM/CommonJS build, so it loads from either kind of flat config. Rule names, messages, preset names and option names are public API — see [Versioning](#versioning).
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
### Presets
|
|
14
|
+
|
|
15
|
+
Rules are grouped by **what must be true of you** for the rule to be correct, so you enable the tiers that describe your package ([ADR-0019](../../docs/adr/0019-lint-rules-as-public-contract.md)):
|
|
16
|
+
|
|
17
|
+
| Preset | Enable it if |
|
|
18
|
+
| ---------------- | ----------------------------------------------------------------------------- |
|
|
19
|
+
| `recommended` | You write a `Lifecycle` or a builder — whatever shape your project is. |
|
|
20
|
+
| `libraryAuthor` | You also publish a package other people compile against. |
|
|
21
|
+
| `dualPublishing` | You also ship both an ESM and a CommonJS build from one source. |
|
|
22
|
+
| `internal` | You are composureCDK. Published for reproducibility, not as a recommendation. |
|
|
23
|
+
|
|
24
|
+
They are additive, so extend every tier that describes you. A CDK **application** takes `recommended` alone: the `libraryAuthor` rules guard hazards that exist only once you emit a `.d.ts` someone else compiles against, and one of them (`lifecycle-build-must-forward-context`) reports on the root-level builds an application does as a matter of course.
|
|
25
|
+
|
|
26
|
+
Each is a self-contained flat config entry that registers the plugin, so extending it is all that is needed:
|
|
27
|
+
|
|
28
|
+
```js
|
|
29
|
+
import composurecdk from "@composurecdk/eslint-plugin";
|
|
30
|
+
|
|
31
|
+
export default [
|
|
32
|
+
{
|
|
33
|
+
files: ["src/**/*.ts"],
|
|
34
|
+
extends: [composurecdk.configs.recommended, composurecdk.configs.libraryAuthor],
|
|
35
|
+
},
|
|
36
|
+
];
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
From a CommonJS flat config the `require()` result is itself the plugin — `rules` and `configs` are own properties of it, so no `.default` unwrapping is needed:
|
|
40
|
+
|
|
41
|
+
```js
|
|
42
|
+
const composurecdk = require("@composurecdk/eslint-plugin");
|
|
43
|
+
|
|
44
|
+
module.exports = [
|
|
45
|
+
{
|
|
46
|
+
files: ["src/**/*.ts"],
|
|
47
|
+
extends: [composurecdk.configs.recommended],
|
|
48
|
+
},
|
|
49
|
+
];
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Scoping is yours
|
|
53
|
+
|
|
54
|
+
No preset declares `files`. The rules are written for **library source** — applying them unscoped will flag test, fixture and config code — but only you know where your source lives, so pick the glob as above. (This repo uses `packages/*/src/**/*.ts`.)
|
|
55
|
+
|
|
56
|
+
File-level overrides (e.g. disabling a rule on a specific file) likewise belong in your config, not in the preset.
|
|
57
|
+
|
|
58
|
+
### Picking rules individually
|
|
59
|
+
|
|
60
|
+
`configs.recommended.rules` is still a plain severity map, so you can register the plugin yourself and take a subset:
|
|
61
|
+
|
|
62
|
+
```js
|
|
63
|
+
import composurecdk from "@composurecdk/eslint-plugin";
|
|
64
|
+
|
|
65
|
+
export default [
|
|
66
|
+
{
|
|
67
|
+
files: ["src/**/*.ts"],
|
|
68
|
+
plugins: { composurecdk },
|
|
69
|
+
rules: { "composurecdk/lifecycle-build-context-required": "error" },
|
|
70
|
+
},
|
|
71
|
+
];
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Mixing the two forms is safe: the preset registers the same plugin object this `plugins` entry does, so ESLint sees one plugin rather than a conflicting redefinition.
|
|
75
|
+
|
|
76
|
+
## Rules
|
|
77
|
+
|
|
78
|
+
Each rule has a documentation page with its rationale, examples, deliberate exclusions and known gaps. `meta.docs.url` points at it, so an editor can open it straight from a reported violation.
|
|
79
|
+
|
|
80
|
+
| Rule | Preset | What it flags |
|
|
81
|
+
| --------------------------------------------------------------------------------------------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
|
82
|
+
| [`composurecdk/builder-must-be-tagged`](docs/rules/builder-must-be-tagged.md) | `internal` | `Builder` / `IBuilder` from `@composurecdk/core` in a library builder — use the tagged equivalents. |
|
|
83
|
+
| [`composurecdk/builder-must-implement-copy-state`](docs/rules/builder-must-implement-copy-state.md) | `recommended` | A builder class holding private state with no `[COPY_STATE]` hook, so `.copy()` silently drops it. |
|
|
84
|
+
| [`composurecdk/constraint-metadata-required`](docs/rules/constraint-metadata-required.md) | `internal` | A `stringConstraint({ … })` call with an empty `name`, `allowed` or `source`, degrading every error it produces. |
|
|
85
|
+
| [`composurecdk/lifecycle-build-context-required`](docs/rules/lifecycle-build-context-required.md) | `recommended` | `Lifecycle.build()` missing the `context` param when the class uses `Resolvable<…>`. |
|
|
86
|
+
| [`composurecdk/lifecycle-build-must-forward-context`](docs/rules/lifecycle-build-must-forward-context.md) | `libraryAuthor` | A two-argument `builder.build(scope, id)` — the sub-builder gets no context, so refs cannot resolve. |
|
|
87
|
+
| [`composurecdk/no-cdk-api-above-floor`](docs/rules/no-cdk-api-above-floor.md) | `internal` | `aws-cdk-lib` APIs newer than the supported peer floor — they throw on older versions in the range. |
|
|
88
|
+
| [`composurecdk/no-cjs-incompatible-syntax`](docs/rules/no-cjs-incompatible-syntax.md) | `dualPublishing` | `import.meta` / top-level `await` in library `src/` — neither emits to CommonJS. |
|
|
89
|
+
| [`composurecdk/no-realm-bound-instanceof`](docs/rules/no-realm-bound-instanceof.md) | `recommended` | `instanceof` against an imported class — realm-bound, so it silently returns false across the dual-package boundary. **Takes an option.** |
|
|
90
|
+
| [`composurecdk/no-typescript-private-modifier`](docs/rules/no-typescript-private-modifier.md) | `libraryAuthor` | The TypeScript `private` modifier — it stays in `keyof T` and leaks through mapped types into the emitted `.d.ts`. |
|
|
91
|
+
| [`composurecdk/redeclared-prop-must-track-cdk-type`](docs/rules/redeclared-prop-must-track-cdk-type.md) | `libraryAuthor` | A prop re-declared out of an `Omit<CdkProps, …>` that pins a CDK interface instead of reading CDK's own prop type. |
|
|
92
|
+
|
|
93
|
+
## Versioning
|
|
94
|
+
|
|
95
|
+
Rule names, messages and default severities are public API ([ADR-0019](../../docs/adr/0019-lint-rules-as-public-contract.md)):
|
|
96
|
+
|
|
97
|
+
- **A new rule ships registered but in no preset**, so you can enable it the day it lands. It **joins a preset in a major**: a caret range — what `npm install` writes — picks up minors automatically, so a new rule in a preset turns green CI red on unchanged code.
|
|
98
|
+
- **Tightening an existing rule is breaking**, including a widened selector or a narrowed exemption. New code failing an unchanged rule is not.
|
|
99
|
+
- **Loosening a rule, removing one, or renaming one is breaking.** A removed or renamed rule id in your own `rules:` block is a hard config error, not a silent gap.
|
|
100
|
+
- **Moving a rule between presets, or renaming a preset, is breaking.** Adding a new preset is not.
|
|
101
|
+
- **Option names and their defaults are API too.** Adding an option is minor when its default preserves behaviour, and breaking otherwise. Renaming one is breaking — the schemas reject unknown keys, so an old name becomes a hard config error rather than a silent no-op.
|
|
102
|
+
|
|
103
|
+
## Adding a new rule
|
|
104
|
+
|
|
105
|
+
1. Create `src/rules/<kebab-name>.ts`:
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
import type { Rule } from "eslint";
|
|
109
|
+
|
|
110
|
+
export const rule: Rule.RuleModule = {
|
|
111
|
+
meta: {
|
|
112
|
+
type: "problem",
|
|
113
|
+
docs: { description: "..." },
|
|
114
|
+
schema: [],
|
|
115
|
+
messages: { someId: "..." },
|
|
116
|
+
},
|
|
117
|
+
create(ctx) {
|
|
118
|
+
return {/* visitor */};
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
2. Register it in `src/rules/index.ts`.
|
|
124
|
+
3. Decide its tier in `src/configs/presets.ts` — the preset whose truth condition it matches, or none if it is landing ahead of the next major. A test asserts no rule lands in two tiers, and that a rule in none is listed as deliberate — see [ADR-0019](../../docs/adr/0019-lint-rules-as-public-contract.md).
|
|
125
|
+
4. Write `docs/rules/<kebab-name>.md`, leading with `# composurecdk/<kebab-name>`. This is where rationale, examples, deliberate exclusions and known gaps live — the rule's own source comment stays a summary plus a link. `meta.docs.url` is derived from the name you registered, so there is nothing to wire up.
|
|
126
|
+
5. Add a row to the table above, linking the page.
|
|
127
|
+
6. Write `test/rules/<kebab-name>.test.ts` using `RuleTester` (see existing tests). Cover at least one valid and one invalid case per `messageId`.
|
|
128
|
+
7. If the rule takes options, give each schema property a `description` (it is what `--print-config` and config inspectors show), keep `additionalProperties: false` so a typo fails loudly, and cover both settings in the tests. Option names are API — see Versioning above.
|
|
129
|
+
|
|
130
|
+
Steps 3–5 are each asserted by `test/docs.test.ts` and `test/configs/presets.test.ts` — skip one and the suite fails rather than the omission going unnoticed.
|
|
131
|
+
|
|
132
|
+
## Running tests
|
|
133
|
+
|
|
134
|
+
```sh
|
|
135
|
+
npx nx test eslint-plugin
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Tests use Vitest as the runner with ESLint's `RuleTester` driving fixtures. The shared `RuleTester` instance (configured with the typescript-eslint parser) lives in `test/rule-tester.ts`.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Linter } from "eslint";
|
|
2
|
+
/**
|
|
3
|
+
* The rule sets behind each preset, grouped by **what must be true of the
|
|
4
|
+
* consumer** for the rule to be correct — not by subject matter. Every rule
|
|
5
|
+
* belongs to exactly one, which a test enforces.
|
|
6
|
+
*
|
|
7
|
+
* The reasoning behind the tiers, and what moving a rule between them costs,
|
|
8
|
+
* is in ADR-0019.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* True for anyone writing a `Lifecycle` or a builder, in any shape of project —
|
|
12
|
+
* an application as much as a library.
|
|
13
|
+
*/
|
|
14
|
+
export declare const recommendedRules: Linter.RulesRecord;
|
|
15
|
+
/**
|
|
16
|
+
* Additionally true for a package other people compile against.
|
|
17
|
+
*
|
|
18
|
+
* Each hazard here exists only once you emit a `.d.ts` someone else consumes:
|
|
19
|
+
* TS4094 and TS2883 need an exported mapped type, and a narrowed prop type only
|
|
20
|
+
* hurts when it is your published API. An application emits none of that.
|
|
21
|
+
*
|
|
22
|
+
* `lifecycle-build-must-forward-context` sits here for a different reason — a
|
|
23
|
+
* root-level build has no context to forward and is correct, and in an
|
|
24
|
+
* application nearly every build is a root build. That is a property of where
|
|
25
|
+
* the call sits in the composition graph, so no amount of narrowing the rule
|
|
26
|
+
* fixes it.
|
|
27
|
+
*/
|
|
28
|
+
export declare const libraryAuthorRules: Linter.RulesRecord;
|
|
29
|
+
/**
|
|
30
|
+
* Additionally true for a package shipping both an ESM and a CommonJS build.
|
|
31
|
+
* Out of `recommended` because banning `import.meta` is a false positive for an
|
|
32
|
+
* ESM-only library, where it is legal and idiomatic.
|
|
33
|
+
*/
|
|
34
|
+
export declare const dualPublishingRules: Linter.RulesRecord;
|
|
35
|
+
/**
|
|
36
|
+
* composureCDK's own house rules. Each encodes a convention or a hardcoded
|
|
37
|
+
* value — this repo's CDK floor, its tagging wrapper, its constraint catalogue
|
|
38
|
+
* — that is wrong elsewhere. Published so the preset is reproducible, not as a
|
|
39
|
+
* recommendation.
|
|
40
|
+
*/
|
|
41
|
+
export declare const internalRules: Linter.RulesRecord;
|
|
42
|
+
//# sourceMappingURL=presets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../../../src/configs/presets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAErC;;;;;;;GAOG;AAEH;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,WAIrC,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,WAIvC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,WAExC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,WAIlC,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.internalRules = exports.dualPublishingRules = exports.libraryAuthorRules = exports.recommendedRules = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* The rule sets behind each preset, grouped by **what must be true of the
|
|
6
|
+
* consumer** for the rule to be correct — not by subject matter. Every rule
|
|
7
|
+
* belongs to exactly one, which a test enforces.
|
|
8
|
+
*
|
|
9
|
+
* The reasoning behind the tiers, and what moving a rule between them costs,
|
|
10
|
+
* is in ADR-0019.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* True for anyone writing a `Lifecycle` or a builder, in any shape of project —
|
|
14
|
+
* an application as much as a library.
|
|
15
|
+
*/
|
|
16
|
+
exports.recommendedRules = {
|
|
17
|
+
"composurecdk/builder-must-implement-copy-state": "error",
|
|
18
|
+
"composurecdk/lifecycle-build-context-required": "error",
|
|
19
|
+
"composurecdk/no-realm-bound-instanceof": "error",
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Additionally true for a package other people compile against.
|
|
23
|
+
*
|
|
24
|
+
* Each hazard here exists only once you emit a `.d.ts` someone else consumes:
|
|
25
|
+
* TS4094 and TS2883 need an exported mapped type, and a narrowed prop type only
|
|
26
|
+
* hurts when it is your published API. An application emits none of that.
|
|
27
|
+
*
|
|
28
|
+
* `lifecycle-build-must-forward-context` sits here for a different reason — a
|
|
29
|
+
* root-level build has no context to forward and is correct, and in an
|
|
30
|
+
* application nearly every build is a root build. That is a property of where
|
|
31
|
+
* the call sits in the composition graph, so no amount of narrowing the rule
|
|
32
|
+
* fixes it.
|
|
33
|
+
*/
|
|
34
|
+
exports.libraryAuthorRules = {
|
|
35
|
+
"composurecdk/lifecycle-build-must-forward-context": "error",
|
|
36
|
+
"composurecdk/no-typescript-private-modifier": "error",
|
|
37
|
+
"composurecdk/redeclared-prop-must-track-cdk-type": "error",
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Additionally true for a package shipping both an ESM and a CommonJS build.
|
|
41
|
+
* Out of `recommended` because banning `import.meta` is a false positive for an
|
|
42
|
+
* ESM-only library, where it is legal and idiomatic.
|
|
43
|
+
*/
|
|
44
|
+
exports.dualPublishingRules = {
|
|
45
|
+
"composurecdk/no-cjs-incompatible-syntax": "error",
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* composureCDK's own house rules. Each encodes a convention or a hardcoded
|
|
49
|
+
* value — this repo's CDK floor, its tagging wrapper, its constraint catalogue
|
|
50
|
+
* — that is wrong elsewhere. Published so the preset is reproducible, not as a
|
|
51
|
+
* recommendation.
|
|
52
|
+
*/
|
|
53
|
+
exports.internalRules = {
|
|
54
|
+
"composurecdk/builder-must-be-tagged": "error",
|
|
55
|
+
"composurecdk/constraint-metadata-required": "error",
|
|
56
|
+
"composurecdk/no-cdk-api-above-floor": "error",
|
|
57
|
+
};
|
|
58
|
+
//# sourceMappingURL=presets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.js","sourceRoot":"","sources":["../../../src/configs/presets.ts"],"names":[],"mappings":";;;AAEA;;;;;;;GAOG;AAEH;;;GAGG;AACU,QAAA,gBAAgB,GAAuB;IAClD,gDAAgD,EAAE,OAAO;IACzD,+CAA+C,EAAE,OAAO;IACxD,wCAAwC,EAAE,OAAO;CAClD,CAAC;AAEF;;;;;;;;;;;;GAYG;AACU,QAAA,kBAAkB,GAAuB;IACpD,mDAAmD,EAAE,OAAO;IAC5D,6CAA6C,EAAE,OAAO;IACtD,kDAAkD,EAAE,OAAO;CAC5D,CAAC;AAEF;;;;GAIG;AACU,QAAA,mBAAmB,GAAuB;IACrD,yCAAyC,EAAE,OAAO;CACnD,CAAC;AAEF;;;;;GAKG;AACU,QAAA,aAAa,GAAuB;IAC/C,qCAAqC,EAAE,OAAO;IAC9C,2CAA2C,EAAE,OAAO;IACpD,qCAAqC,EAAE,OAAO;CAC/C,CAAC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { rules } from "./rules/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Self-contained flat config entries — each registers the plugin, so a consumer
|
|
4
|
+
* needs no `plugins` entry of their own, and they compose:
|
|
5
|
+
*
|
|
6
|
+
* ```js
|
|
7
|
+
* import composurecdk from "@composurecdk/eslint-plugin";
|
|
8
|
+
* export default [
|
|
9
|
+
* {
|
|
10
|
+
* files: ["src/**\/*.ts"],
|
|
11
|
+
* extends: [composurecdk.configs.recommended, composurecdk.configs.dualPublishing],
|
|
12
|
+
* },
|
|
13
|
+
* ];
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* None declares `files`: the rules target library source, but only the consumer
|
|
17
|
+
* knows where theirs lives. See `./configs/presets.ts` for which rules each
|
|
18
|
+
* holds and why.
|
|
19
|
+
*/
|
|
20
|
+
export declare const configs: {
|
|
21
|
+
recommended: {
|
|
22
|
+
name: string;
|
|
23
|
+
plugins: {
|
|
24
|
+
composurecdk: import("@eslint/core").Plugin;
|
|
25
|
+
};
|
|
26
|
+
rules: import("@eslint/core").RulesConfig;
|
|
27
|
+
};
|
|
28
|
+
libraryAuthor: {
|
|
29
|
+
name: string;
|
|
30
|
+
plugins: {
|
|
31
|
+
composurecdk: import("@eslint/core").Plugin;
|
|
32
|
+
};
|
|
33
|
+
rules: import("@eslint/core").RulesConfig;
|
|
34
|
+
};
|
|
35
|
+
dualPublishing: {
|
|
36
|
+
name: string;
|
|
37
|
+
plugins: {
|
|
38
|
+
composurecdk: import("@eslint/core").Plugin;
|
|
39
|
+
};
|
|
40
|
+
rules: import("@eslint/core").RulesConfig;
|
|
41
|
+
};
|
|
42
|
+
internal: {
|
|
43
|
+
name: string;
|
|
44
|
+
plugins: {
|
|
45
|
+
composurecdk: import("@eslint/core").Plugin;
|
|
46
|
+
};
|
|
47
|
+
rules: import("@eslint/core").RulesConfig;
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
export { rules };
|
|
51
|
+
declare const _default: import("@eslint/core").Plugin & {
|
|
52
|
+
configs: {
|
|
53
|
+
recommended: {
|
|
54
|
+
name: string;
|
|
55
|
+
plugins: {
|
|
56
|
+
composurecdk: import("@eslint/core").Plugin;
|
|
57
|
+
};
|
|
58
|
+
rules: import("@eslint/core").RulesConfig;
|
|
59
|
+
};
|
|
60
|
+
libraryAuthor: {
|
|
61
|
+
name: string;
|
|
62
|
+
plugins: {
|
|
63
|
+
composurecdk: import("@eslint/core").Plugin;
|
|
64
|
+
};
|
|
65
|
+
rules: import("@eslint/core").RulesConfig;
|
|
66
|
+
};
|
|
67
|
+
dualPublishing: {
|
|
68
|
+
name: string;
|
|
69
|
+
plugins: {
|
|
70
|
+
composurecdk: import("@eslint/core").Plugin;
|
|
71
|
+
};
|
|
72
|
+
rules: import("@eslint/core").RulesConfig;
|
|
73
|
+
};
|
|
74
|
+
internal: {
|
|
75
|
+
name: string;
|
|
76
|
+
plugins: {
|
|
77
|
+
composurecdk: import("@eslint/core").Plugin;
|
|
78
|
+
};
|
|
79
|
+
rules: import("@eslint/core").RulesConfig;
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
export default _default;
|
|
84
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAkBzC;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqBqB,CAAC;AAE1C,OAAO,EAAE,KAAK,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEjB,wBAAkD"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.rules = exports.configs = void 0;
|
|
4
|
+
const presets_js_1 = require("./configs/presets.js");
|
|
5
|
+
const index_js_1 = require("./rules/index.js");
|
|
6
|
+
Object.defineProperty(exports, "rules", { enumerable: true, get: function () { return index_js_1.rules; } });
|
|
7
|
+
/**
|
|
8
|
+
* The plugin object, built before `configs` so every preset can register *this*
|
|
9
|
+
* object under `plugins`.
|
|
10
|
+
*
|
|
11
|
+
* The identity matters. ESLint rejects a flat config whose entries register two
|
|
12
|
+
* different objects under one plugin name, so a consumer extending two presets
|
|
13
|
+
* at once — or extending one and writing `plugins: { composurecdk }` themselves
|
|
14
|
+
* — must be handing ESLint the same reference each time. `Object.assign` below
|
|
15
|
+
* attaches `configs` to this object rather than producing a second one.
|
|
16
|
+
*/
|
|
17
|
+
const plugin = {
|
|
18
|
+
// Names the plugin in `--print-config` output and the flat config inspector.
|
|
19
|
+
meta: { name: "@composurecdk/eslint-plugin" },
|
|
20
|
+
rules: index_js_1.rules,
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Self-contained flat config entries — each registers the plugin, so a consumer
|
|
24
|
+
* needs no `plugins` entry of their own, and they compose:
|
|
25
|
+
*
|
|
26
|
+
* ```js
|
|
27
|
+
* import composurecdk from "@composurecdk/eslint-plugin";
|
|
28
|
+
* export default [
|
|
29
|
+
* {
|
|
30
|
+
* files: ["src/**\/*.ts"],
|
|
31
|
+
* extends: [composurecdk.configs.recommended, composurecdk.configs.dualPublishing],
|
|
32
|
+
* },
|
|
33
|
+
* ];
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* None declares `files`: the rules target library source, but only the consumer
|
|
37
|
+
* knows where theirs lives. See `./configs/presets.ts` for which rules each
|
|
38
|
+
* holds and why.
|
|
39
|
+
*/
|
|
40
|
+
exports.configs = {
|
|
41
|
+
recommended: {
|
|
42
|
+
name: "composurecdk/recommended",
|
|
43
|
+
plugins: { composurecdk: plugin },
|
|
44
|
+
rules: presets_js_1.recommendedRules,
|
|
45
|
+
},
|
|
46
|
+
libraryAuthor: {
|
|
47
|
+
name: "composurecdk/library-author",
|
|
48
|
+
plugins: { composurecdk: plugin },
|
|
49
|
+
rules: presets_js_1.libraryAuthorRules,
|
|
50
|
+
},
|
|
51
|
+
dualPublishing: {
|
|
52
|
+
name: "composurecdk/dual-publishing",
|
|
53
|
+
plugins: { composurecdk: plugin },
|
|
54
|
+
rules: presets_js_1.dualPublishingRules,
|
|
55
|
+
},
|
|
56
|
+
internal: {
|
|
57
|
+
name: "composurecdk/internal",
|
|
58
|
+
plugins: { composurecdk: plugin },
|
|
59
|
+
rules: presets_js_1.internalRules,
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
exports.default = Object.assign(plugin, { configs: exports.configs });
|
|
63
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;AACA,qDAK8B;AAC9B,+CAAyC;AA2DhC,sFA3DA,gBAAK,OA2DA;AAzDd;;;;;;;;;GASG;AACH,MAAM,MAAM,GAAkB;IAC5B,6EAA6E;IAC7E,IAAI,EAAE,EAAE,IAAI,EAAE,6BAA6B,EAAE;IAC7C,KAAK,EAAL,gBAAK;CACN,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACU,QAAA,OAAO,GAAG;IACrB,WAAW,EAAE;QACX,IAAI,EAAE,0BAA0B;QAChC,OAAO,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE;QACjC,KAAK,EAAE,6BAAgB;KACxB;IACD,aAAa,EAAE;QACb,IAAI,EAAE,6BAA6B;QACnC,OAAO,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE;QACjC,KAAK,EAAE,+BAAkB;KAC1B;IACD,cAAc,EAAE;QACd,IAAI,EAAE,8BAA8B;QACpC,OAAO,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE;QACjC,KAAK,EAAE,gCAAmB;KAC3B;IACD,QAAQ,EAAE;QACR,IAAI,EAAE,uBAAuB;QAC7B,OAAO,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE;QACjC,KAAK,EAAE,0BAAa;KACrB;CACsC,CAAC;AAI1C,kBAAe,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,OAAO,EAAP,eAAO,EAAE,CAAC,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Rule } from "eslint";
|
|
2
|
+
/**
|
|
3
|
+
* Flags `Builder()` or `IBuilder<…>` from `@composurecdk/core` in a builder that
|
|
4
|
+
* wraps a taggable resource.
|
|
5
|
+
*
|
|
6
|
+
* Tagging is cross-cutting: every deployable resource needs it, and a consumer
|
|
7
|
+
* expects the same tagging surface on every builder rather than on whichever
|
|
8
|
+
* ones remembered to add it. `taggedBuilder` / `ITaggedBuilder` from
|
|
9
|
+
* `@composurecdk/cloudformation` supply that surface; the core builder does not,
|
|
10
|
+
* because core stays independent of CloudFormation.
|
|
11
|
+
*
|
|
12
|
+
* See {@link https://github.com/laazyj/composureCDK/blob/main/packages/eslint-plugin/docs/rules/builder-must-be-tagged.md | the rule documentation}.
|
|
13
|
+
*/
|
|
14
|
+
export declare const rule: Rule.RuleModule;
|
|
15
|
+
//# sourceMappingURL=builder-must-be-tagged.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builder-must-be-tagged.d.ts","sourceRoot":"","sources":["../../../src/rules/builder-must-be-tagged.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAanC;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,IAAI,EAAE,IAAI,CAAC,UAkDvB,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.rule = void 0;
|
|
4
|
+
const taggedSuffix = "If the wrapped CFN resource has no Tags property (Route53 records, IAM ManagedPolicy, " +
|
|
5
|
+
"SNS Subscription, AWS Budgets), disable this rule on the offending line with a directive " +
|
|
6
|
+
"naming the resource: `// eslint-disable-next-line composurecdk/builder-must-be-tagged -- AWS::… has no Tags property`.";
|
|
7
|
+
/**
|
|
8
|
+
* Flags `Builder()` or `IBuilder<…>` from `@composurecdk/core` in a builder that
|
|
9
|
+
* wraps a taggable resource.
|
|
10
|
+
*
|
|
11
|
+
* Tagging is cross-cutting: every deployable resource needs it, and a consumer
|
|
12
|
+
* expects the same tagging surface on every builder rather than on whichever
|
|
13
|
+
* ones remembered to add it. `taggedBuilder` / `ITaggedBuilder` from
|
|
14
|
+
* `@composurecdk/cloudformation` supply that surface; the core builder does not,
|
|
15
|
+
* because core stays independent of CloudFormation.
|
|
16
|
+
*
|
|
17
|
+
* See {@link https://github.com/laazyj/composureCDK/blob/main/packages/eslint-plugin/docs/rules/builder-must-be-tagged.md | the rule documentation}.
|
|
18
|
+
*/
|
|
19
|
+
exports.rule = {
|
|
20
|
+
meta: {
|
|
21
|
+
type: "problem",
|
|
22
|
+
docs: {
|
|
23
|
+
description: "Library builders must use `taggedBuilder` / `ITaggedBuilder` from `@composurecdk/cloudformation` " +
|
|
24
|
+
"unless the wrapped CFN resource has no Tags property.",
|
|
25
|
+
},
|
|
26
|
+
schema: [],
|
|
27
|
+
messages: {
|
|
28
|
+
restrictedCall: "Use `taggedBuilder` from `@composurecdk/cloudformation` instead of `Builder` from `@composurecdk/core`. " +
|
|
29
|
+
taggedSuffix,
|
|
30
|
+
restrictedType: "Use `ITaggedBuilder` from `@composurecdk/cloudformation` instead of `IBuilder` from `@composurecdk/core`. " +
|
|
31
|
+
taggedSuffix,
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
create(ctx) {
|
|
35
|
+
const localBuilderNames = new Set();
|
|
36
|
+
const localIBuilderNames = new Set();
|
|
37
|
+
const listener = {
|
|
38
|
+
ImportDeclaration(node) {
|
|
39
|
+
if (node.source.value !== "@composurecdk/core")
|
|
40
|
+
return;
|
|
41
|
+
for (const spec of node.specifiers) {
|
|
42
|
+
if (spec.type !== "ImportSpecifier")
|
|
43
|
+
continue;
|
|
44
|
+
if (spec.imported.type !== "Identifier")
|
|
45
|
+
continue;
|
|
46
|
+
if (spec.imported.name === "Builder")
|
|
47
|
+
localBuilderNames.add(spec.local.name);
|
|
48
|
+
if (spec.imported.name === "IBuilder")
|
|
49
|
+
localIBuilderNames.add(spec.local.name);
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
CallExpression(node) {
|
|
53
|
+
if (node.callee.type === "Identifier" && localBuilderNames.has(node.callee.name)) {
|
|
54
|
+
ctx.report({ node: node.callee, messageId: "restrictedCall" });
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
listener.TSTypeReference = (node) => {
|
|
59
|
+
const ref = node;
|
|
60
|
+
const name = ref.typeName.name;
|
|
61
|
+
if (ref.typeName.type === "Identifier" &&
|
|
62
|
+
name !== undefined &&
|
|
63
|
+
localIBuilderNames.has(name)) {
|
|
64
|
+
ctx.report({ node: ref.typeName, messageId: "restrictedType" });
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
return listener;
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=builder-must-be-tagged.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builder-must-be-tagged.js","sourceRoot":"","sources":["../../../src/rules/builder-must-be-tagged.ts"],"names":[],"mappings":";;;AAGA,MAAM,YAAY,GAChB,wFAAwF;IACxF,2FAA2F;IAC3F,wHAAwH,CAAC;AAO3H;;;;;;;;;;;GAWG;AACU,QAAA,IAAI,GAAoB;IACnC,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EACT,mGAAmG;gBACnG,uDAAuD;SAC1D;QACD,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE;YACR,cAAc,EACZ,0GAA0G;gBAC1G,YAAY;YACd,cAAc,EACZ,4GAA4G;gBAC5G,YAAY;SACf;KACF;IACD,MAAM,CAAC,GAAG;QACR,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAU,CAAC;QAC5C,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAAU,CAAC;QAC7C,MAAM,QAAQ,GAAsB;YAClC,iBAAiB,CAAC,IAAI;gBACpB,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,KAAK,oBAAoB;oBAAE,OAAO;gBACvD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;oBACnC,IAAI,IAAI,CAAC,IAAI,KAAK,iBAAiB;wBAAE,SAAS;oBAC9C,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,YAAY;wBAAE,SAAS;oBAClD,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,SAAS;wBAAE,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBAC7E,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,UAAU;wBAAE,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBACjF,CAAC;YACH,CAAC;YACD,cAAc,CAAC,IAAI;gBACjB,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,YAAY,IAAI,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;oBACjF,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,gBAAgB,EAAE,CAAC,CAAC;gBACjE,CAAC;YACH,CAAC;SACF,CAAC;QACF,QAAQ,CAAC,eAAe,GAAG,CAAC,IAAU,EAAE,EAAE;YACxC,MAAM,GAAG,GAAG,IAAsC,CAAC;YACnD,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC;YAC/B,IACE,GAAG,CAAC,QAAQ,CAAC,IAAI,KAAK,YAAY;gBAClC,IAAI,KAAK,SAAS;gBAClB,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,EAC5B,CAAC;gBACD,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,gBAAgB,EAAE,CAAC,CAAC;YAClE,CAAC;QACH,CAAC,CAAC;QACF,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Rule } from "eslint";
|
|
2
|
+
/**
|
|
3
|
+
* Flags a builder class holding private state with no `[COPY_STATE]` hook.
|
|
4
|
+
*
|
|
5
|
+
* `.copy()` shallow-clones the builder's props. State held in private fields sits
|
|
6
|
+
* outside that copy, so without the hook it is silently dropped: the clone looks
|
|
7
|
+
* correct and behaves differently. Implement `[COPY_STATE]` to carry such state
|
|
8
|
+
* onto the clone.
|
|
9
|
+
*
|
|
10
|
+
* See {@link https://github.com/laazyj/composureCDK/blob/main/packages/eslint-plugin/docs/rules/builder-must-implement-copy-state.md | the rule documentation}.
|
|
11
|
+
*/
|
|
12
|
+
export declare const rule: Rule.RuleModule;
|
|
13
|
+
//# sourceMappingURL=builder-must-implement-copy-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builder-must-implement-copy-state.d.ts","sourceRoot":"","sources":["../../../src/rules/builder-must-implement-copy-state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,QAAQ,CAAC;AAkB/C;;;;;;;;;GASG;AACH,eAAO,MAAM,IAAI,EAAE,IAAI,CAAC,UAkGvB,CAAC"}
|