@activatus/code-standards 3.0.1 → 3.0.4
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 +10 -10
- package/docs/Guides/component-library-workflow.md +16 -16
- package/docs/Guides/migrating.md +15 -15
- package/docs/Guides/setup.md +12 -7
- package/docs/Standards/agent-skills.md +2 -2
- package/docs/Standards/agent-specs.md +3 -3
- package/docs/Standards/documentation.md +7 -7
- package/docs/Standards/eslint.md +169 -105
- package/docs/Standards/human-readable-names.md +15 -3
- package/docs/Standards/lint-errors.md +13 -12
- package/docs/Standards/readable-code.md +80 -43
- package/docs/Standards/stylelint.md +4 -4
- package/docs/Standards/styling.md +8 -8
- package/docs/Standards/tech-stack.md +1 -1
- package/docs/Structure/api-routes.md +3 -3
- package/docs/Structure/component-organization.md +19 -18
- package/docs/Structure/folder-structure.md +110 -12
- package/docs/Structure/naming-conventions.md +10 -8
- package/docs/design-system-components.md +3 -3
- package/docs/intro.md +20 -20
- package/docs/ontology.md +32 -31
- package/docs/templates.mdx +12 -12
- package/docs/version-history.md +76 -42
- package/package.json +1 -1
- package/static/templates/AGENTS.md +5 -4
- package/static/templates/docs/overview/writing-docs.md +1 -1
- package/static/templates/eslint/nextjs/eslint.config.mjs +48 -28
- package/static/templates/eslint/react/eslint.config.mjs +48 -28
- package/static/templates/eslint/typescript/eslint.config.mjs +48 -28
package/docs/version-history.md
CHANGED
|
@@ -17,13 +17,15 @@ sidebar_label: "Version History"
|
|
|
17
17
|
|
|
18
18
|
**Read only the versions newer than the project's.** A project on version 1 that is updating to version 3 reads version 2 and version 3 on this page, and nothing else. Do not re-read every standard or check the whole codebase: each version lists every change that matters, and how to find the code it affects.
|
|
19
19
|
|
|
20
|
-
1. **Find the project's version** in its `AGENTS.md`. If there is none, the project has never followed the standards: follow [Setup](/Guides/setup) instead.
|
|
20
|
+
1. **Find the project's version** in its `AGENTS.md`. If there is none, the project has never followed the standards: follow [Setup](/docs/Guides/setup) instead.
|
|
21
21
|
2. **Update the package:** `pnpm update @activatus/code-standards --latest`. Then read this page from `node_modules/@activatus/code-standards/docs/version-history.md`.
|
|
22
22
|
3. **Read each version newer than the project's**, oldest first. Skip any change to a standard the project opted out of: they are listed in `docs/development/coding-standards.md`.
|
|
23
23
|
4. **For each change, do the "What to do" steps**, then run the "How to check" searches. A search that still finds something means the change is not finished.
|
|
24
24
|
5. **Run `pnpm lint`, `pnpm test` and the build** after each change.
|
|
25
25
|
6. **Update the version number** in `AGENTS.md` once every change is done.
|
|
26
26
|
|
|
27
|
+
**A patch keeps the same version number.** When only the last number changes, such as 3.0.0 → 3.0.1, the project's version in `AGENTS.md` stays the same, but there may still be work to do. Update the package, then read that version's **Fixes** list and do anything it asks for the project's version. Check it every time the package is updated, even when the version number has not changed.
|
|
28
|
+
|
|
27
29
|
**When a change does not fit the project**, for example it renames a folder the project does not have, skip it. If you are not sure, ask; do not guess.
|
|
28
30
|
|
|
29
31
|
## Adding a version
|
|
@@ -36,15 +38,28 @@ Anyone changing the standards adds a version, alongside the change:
|
|
|
36
38
|
- **If a project has nothing to do, say so.**
|
|
37
39
|
- **Newest version at the top.**
|
|
38
40
|
- **Work in progress goes under `## Version N — not released yet`**, with a line saying projects should not apply it yet. Changes can be added to it over time. To release it: drop "not released yet", add the **Released** date and **Updates from** line, set `package.json` to `N.0.0`, then publish.
|
|
39
|
-
- **Fixing a released version** bumps only the last number: `3.0.0` → `3.0.1`. Update the version's changes in place, and list what was fixed under its **Fixes**. Projects keep the same version number in `AGENTS.md`.
|
|
41
|
+
- **Fixing a released version** bumps only the last number: `3.0.0` → `3.0.1`. Update the version's changes in place, and list what was fixed under its **Fixes**. Projects keep the same version number in `AGENTS.md`. Write each fix so a project already on that version knows what to do.
|
|
40
42
|
|
|
41
43
|
---
|
|
42
44
|
|
|
43
45
|
## Version 3
|
|
44
46
|
|
|
45
|
-
**Released:** 2026-10-17 · **Updates from:** version 2 · **Latest fix:** 3.0.
|
|
47
|
+
**Released:** 2026-10-17 · **Updates from:** version 2 · **Latest fix:** 3.0.4
|
|
48
|
+
|
|
49
|
+
Install it with `pnpm add -D @activatus/code-standards@3.0.4`. Do change 1 first: it says which parts of the project's `AGENTS.md` are now the project's own to write.
|
|
50
|
+
|
|
51
|
+
**Fixes in 3.0.4.** If the project already applied 3.0.3, do these:
|
|
52
|
+
|
|
53
|
+
- New standard 12.1: links, text and stand-in data live in `lib/constants/`, as `r`, `s` and noData. `r` and `s` are the only single-letter names allowed. Do change 11.
|
|
54
|
+
- The standards site has a home page, and the docs moved to `/docs/...`. Old links redirect, so nothing breaks. Update any link to the standards site in the project's `AGENTS.md` or docs to the `/docs/` address, such as `https://activatus-code-standards.vercel.app/docs/ontology`.
|
|
46
55
|
|
|
47
|
-
|
|
56
|
+
**Fixes in 3.0.3.** Change 8 now says how to type a function inside an object that is built somewhere else: give the function its own `Props` type, such as `LaunchSessionProps`, and use it. If the project wrote those parameter types out inline, such as `({ worktreePath }: { worktreePath: string })`, replace each with the function's `Props` type. Also new: type first, never `satisfies`. It is an ESLint error now, so copy the new ESLint config and replace each `satisfies` with a type on the declaration, except in Storybook story files.
|
|
57
|
+
|
|
58
|
+
**Fixes in 3.0.2.** Nothing to do in a project:
|
|
59
|
+
|
|
60
|
+
- The update steps say how to pick up a patch: the version number in `AGENTS.md` stays the same, so always read the version's Fixes list after updating the package.
|
|
61
|
+
- A removed decimal standard keeps its number, such as `11.2. Removed in version N`.
|
|
62
|
+
- [When lint must pass](/docs/Standards/lint-errors#when-lint-must-pass) names the usual ways projects check it: a CI job or a git hook.
|
|
48
63
|
|
|
49
64
|
**Fixes in 3.0.1.** If the project already applied 3.0.0, check these:
|
|
50
65
|
|
|
@@ -61,9 +76,9 @@ Install it with `pnpm add -D @activatus/code-standards@3.0.1`. Do change 1 first
|
|
|
61
76
|
|
|
62
77
|
- The Branch Naming and Commit Messages standards are gone, along with standards 19, 20 and 22 from the setup list. Keep whatever the project already does, and make sure it is written up in the project's own docs, usually `docs/development/`.
|
|
63
78
|
- **Standards 19, 20 and 22 keep their numbers, marked as removed.** No other number changes. If `docs/development/coding-standards.md` records a choice for 19, 20 or 22, move that rule into Project workflow and take it off the list.
|
|
64
|
-
- In `AGENTS.md`, replace the "Development workflow" section with a **Project workflow** section, copied from the [template](/templates#agents). Fill it in with the project's own rules: who commits, branches, commit messages, Pull Requests, merging and releases. Put the most important rule for agents, usually whether they may commit, at the very top: one line, or a short section if it needs more.
|
|
79
|
+
- In `AGENTS.md`, replace the "Development workflow" section with a **Project workflow** section, copied from the [template](/docs/templates#agents). Fill it in with the project's own rules: who commits, branches, commit messages, Pull Requests, merging and releases. Put the most important rule for agents, usually whether they may commit, at the very top: one line, or a short section if it needs more.
|
|
65
80
|
- Remove the "Never commit code" and "Do not create, switch or delete branches" lines from "Out of scope for AI agents", unless they are the project's own rule. If they are, they belong in Project workflow.
|
|
66
|
-
- Commitlint and the Husky hooks (`.husky/commit-msg` and `.husky/pre-commit`) are no longer templates. Keep them if the project wants them: they are now the project's choice. The standard is only that `pnpm lint` passes before work is finished. See [When lint must pass](/Standards/lint-errors#when-lint-must-pass).
|
|
81
|
+
- Commitlint and the Husky hooks (`.husky/commit-msg` and `.husky/pre-commit`) are no longer templates. Keep them if the project wants them: they are now the project's choice. The standard is only that `pnpm lint` passes before work is finished. See [When lint must pass](/docs/Standards/lint-errors#when-lint-must-pass).
|
|
67
82
|
|
|
68
83
|
**How to check:** `AGENTS.md` has a Project workflow section, and every rule in it is written up in the project's docs.
|
|
69
84
|
|
|
@@ -74,15 +89,15 @@ Install it with `pnpm add -D @activatus/code-standards@3.0.1`. Do change 1 first
|
|
|
74
89
|
**What to do:**
|
|
75
90
|
|
|
76
91
|
- Rename the `library/` folder to `lib/` with `git mv`, and fix the imports: `@/library/` → `@/lib/`.
|
|
77
|
-
- Rename every name ending in `Reference` to end in `Ref`, whatever it refers to: `inputReference` → `inputRef`, `surfaceReference` → `surfaceRef`. Rename `repository` back to `repo` where it is short for a Git repository, such as `repositoryName` → `repoName`. Use the editor's Rename Symbol (F2), or the [rename script](/Guides/migrating#renaming-from-the-command-line).
|
|
78
|
-
- Copy the new [ESLint config](/Standards/eslint). The naming rule now has `replacements: { docs: false, lib: false, props: false, ref: false, repo: false, utils: false }` and `allowList: { params: true, searchParams: true }`.
|
|
79
|
-
- Update the "Dictionary words stay short" line in `AGENTS.md` from the [template](/templates#agents), and remove `lib/` → `library/` and `repo` → `repository` from its Never / Always table.
|
|
92
|
+
- Rename every name ending in `Reference` to end in `Ref`, whatever it refers to: `inputReference` → `inputRef`, `surfaceReference` → `surfaceRef`. Rename `repository` back to `repo` where it is short for a Git repository, such as `repositoryName` → `repoName`. Use the editor's Rename Symbol (F2), or the [rename script](/docs/Guides/migrating#renaming-from-the-command-line).
|
|
93
|
+
- Copy the new [ESLint config](/docs/Standards/eslint). The naming rule now has `replacements: { docs: false, lib: false, props: false, ref: false, repo: false, utils: false }` and `allowList: { params: true, searchParams: true }`.
|
|
94
|
+
- Update the "Dictionary words stay short" line in `AGENTS.md` from the [template](/docs/templates#agents), and remove `lib/` → `library/` and `repo` → `repository` from its Never / Always table.
|
|
80
95
|
|
|
81
96
|
**How to check:** There is no `library/` folder, `grep -rn "@/library" --exclude-dir=node_modules .` finds nothing, and `pnpm lint` passes.
|
|
82
97
|
|
|
83
98
|
### 3. utils, services and lib are defined
|
|
84
99
|
|
|
85
|
-
**Why:** It wasn't clear which functions go in `utils/`, `services/` or `lib/`. See [utils, services and lib](/Structure/folder-structure#utils-services-and-lib).
|
|
100
|
+
**Why:** It wasn't clear which functions go in `utils/`, `services/` or `lib/`. See [utils, services and lib](/docs/Structure/folder-structure#utils-services-and-lib).
|
|
86
101
|
|
|
87
102
|
**What to do:** Check each function in those three folders against the definitions, and move any that are in the wrong one. The common one: a function in `utils/` that calls a database or an API belongs in `services/` or `lib/`. Shared constants and types live in `lib/constants/` and `lib/types/`; a component's own types stay in its `types.ts`. Move any root-level `constants/` or `types/` folder into `lib/`.
|
|
88
103
|
|
|
@@ -92,7 +107,7 @@ Install it with `pnpm add -D @activatus/code-standards@3.0.1`. Do change 1 first
|
|
|
92
107
|
|
|
93
108
|
**Why:** Project-management words mean different things in different projects. Launchpad's "project" is a product made of several MVPs, and its Pull Requests go through `feature → dev → uat → main`.
|
|
94
109
|
|
|
95
|
-
**What to do:** The code [Ontology](/ontology) no longer defines `project`, `repository`, `branch`, `commit`, `pull_request`, `pull_request_review` or `production`, and `human`, `developer` and `agent` no longer say who may commit. If the project uses those words, define them in its own `docs/product/ontology.md`, the way the project actually works.
|
|
110
|
+
**What to do:** The code [Ontology](/docs/ontology) no longer defines `project`, `repository`, `branch`, `commit`, `pull_request`, `pull_request_review` or `production`, and `human`, `developer` and `agent` no longer say who may commit. If the project uses those words, define them in its own `docs/product/ontology.md`, the way the project actually works.
|
|
96
111
|
|
|
97
112
|
**How to check:** The project's ontology defines every project-management word it uses.
|
|
98
113
|
|
|
@@ -103,7 +118,7 @@ Install it with `pnpm add -D @activatus/code-standards@3.0.1`. Do change 1 first
|
|
|
103
118
|
**What to do:**
|
|
104
119
|
|
|
105
120
|
- Rename each config file that is `.js`, `.ts` or `.mts` to `.mjs`, even in a TypeScript project, wherever the tool can read `.mjs`: `prettier.config.mjs`, `next.config.mjs`, `eslint.config.mjs`, `docsSite/docusaurus.config.mjs`, `docsSite/sidebars.mjs` and so on. Use `git mv`. Never convert a config to `.ts` or `.mts`.
|
|
106
|
-
- Remove any TypeScript-only syntax as you go. A type annotation becomes a JSDoc comment: `const config: NextConfig = {` becomes `/** @type {import("next").NextConfig} */ const config = {`. Copy the [`docsSite/` templates](/templates#docs-site), which are already `.mjs`.
|
|
121
|
+
- Remove any TypeScript-only syntax as you go. A type annotation becomes a JSDoc comment: `const config: NextConfig = {` becomes `/** @type {import("next").NextConfig} */ const config = {`. Copy the [`docsSite/` templates](/docs/templates#docs-site), which are already `.mjs`.
|
|
107
122
|
- Update anything that names the old file, such as `sidebarPath: './sidebars.mjs'` in the docs site config.
|
|
108
123
|
|
|
109
124
|
**How to check:** `ls *.config.* docsSite/*.config.* docsSite/sidebars.*` shows only `.mjs` files, and `pnpm lint`, `pnpm format:check`, the build and `pnpm docs:build` still run.
|
|
@@ -114,9 +129,9 @@ Install it with `pnpm add -D @activatus/code-standards@3.0.1`. Do change 1 first
|
|
|
114
129
|
|
|
115
130
|
**What to do:**
|
|
116
131
|
|
|
117
|
-
- Copy the new [`prettier.config.mjs`](/templates#prettier) and [`.editorconfig`](/templates#editorconfig). Prettier now has `printWidth: 70` and `useTabs: true`, and keeps spaces for Markdown and YAML. EditorConfig indents with tabs, except Markdown, YAML and Python.
|
|
132
|
+
- Copy the new [`prettier.config.mjs`](/docs/templates#prettier) and [`.editorconfig`](/docs/templates#editorconfig). Prettier now has `printWidth: 70` and `useTabs: true`, and keeps spaces for Markdown and YAML. EditorConfig indents with tabs, except Markdown, YAML and Python.
|
|
118
133
|
- Run `pnpm format` once, on its own, with no other changes mixed in. It touches nearly every file, so keep it apart from real changes.
|
|
119
|
-
- If the project shows code on a web page, such as its docs site, add `pre, code { tab-size: 2; }` to its CSS, so tabs are not shown 8 characters wide. The [`docsSite/` template](/templates#docs-site) already has it.
|
|
134
|
+
- If the project shows code on a web page, such as its docs site, add `pre, code { tab-size: 2; }` to its CSS, so tabs are not shown 8 characters wide. The [`docsSite/` template](/docs/templates#docs-site) already has it.
|
|
120
135
|
|
|
121
136
|
**How to check:** `pnpm format:check` passes.
|
|
122
137
|
|
|
@@ -127,10 +142,10 @@ Install it with `pnpm add -D @activatus/code-standards@3.0.1`. Do change 1 first
|
|
|
127
142
|
**What to do:** Search for renamed imports: `grep -rn "import {[^}]* as " --include=*.ts --include=*.tsx --exclude-dir=node_modules .`. For each one:
|
|
128
143
|
|
|
129
144
|
- **If nothing in the file clashes with the original name**, undo the rename and use the original name.
|
|
130
|
-
- **If our own thing clashes**, rename ours to a more specific full-word name, with the editor's Rename Symbol or the [rename script](/Guides/migrating#renaming-from-the-command-line). Then undo the import rename. For example, our `createClient` becomes `createProjectDatabaseClient`, and Supabase's `createClient` keeps its name.
|
|
145
|
+
- **If our own thing clashes**, rename ours to a more specific full-word name, with the editor's Rename Symbol or the [rename script](/docs/Guides/migrating#renaming-from-the-command-line). Then undo the import rename. For example, our `createClient` becomes `createProjectDatabaseClient`, and Supabase's `createClient` keeps its name.
|
|
131
146
|
- **If both names are third-party, or ours is fixed by a framework** (such as a Next.js route's `GET`), keep the import renamed, as the owner plus the original name, never shortened: `Link as LucideLinkIcon`.
|
|
132
147
|
|
|
133
|
-
See [When a name clashes](/Standards/human-readable-names#when-a-name-clashes).
|
|
148
|
+
See [When a name clashes](/docs/Standards/human-readable-names#when-a-name-clashes).
|
|
134
149
|
|
|
135
150
|
**How to check:** Every renamed import that is left clashes with another third-party name or a framework-fixed name, and starts with its owner's name.
|
|
136
151
|
|
|
@@ -138,15 +153,17 @@ See [When a name clashes](/Standards/human-readable-names#when-a-name-clashes).
|
|
|
138
153
|
|
|
139
154
|
**Why:** A type named after its role in one function, such as `StartAgentRunDependenciesType`, is a second name for what is really part of that function's props.
|
|
140
155
|
|
|
141
|
-
**What to do:** Find types used for only one field of one `Props` type. Move each one inside that `Props` and delete the separate type. Where the object is built somewhere else,
|
|
156
|
+
**What to do:** Find types used for only one field of one `Props` type. Move each one inside that `Props` and delete the separate type. Where the object is built somewhere else, don't just delete its type: the functions inside lose their parameter types and the type check fails. Give each function its own `Props` type for its single object parameter, named after the function, and use it there: `launchSession: async ({ worktreePath }: LaunchSessionProps) =>`. Don't write the type out inline, such as `({ worktreePath }: { worktreePath: string })`.
|
|
157
|
+
|
|
158
|
+
**Type first, never `satisfies`.** A value gets its type where it is declared, and `satisfies` is now an ESLint error. Replace each `{ … } satisfies SomeType` with a type on the declaration: `const config: ConfigType = { … }`. **Leave story files alone**: they follow Storybook's docs, `satisfies Meta<typeof Component>` with `StoryObj<typeof meta>`, and ESLint allows it there. Copy the new [ESLint config](/docs/Standards/eslint) to switch the check on.
|
|
142
159
|
|
|
143
|
-
**How to check:** No type is used only as the type of one field of one `Props
|
|
160
|
+
**How to check:** No type is used only as the type of one field of one `Props`, `grep -rn " satisfies " --include=*.ts --include=*.tsx --exclude=*.stories.* --exclude-dir=node_modules .` finds nothing, and the type check and `pnpm lint` pass.
|
|
144
161
|
|
|
145
162
|
### 9. "go" means carry on
|
|
146
163
|
|
|
147
164
|
**Why:** People often send just "go" to nudge an agent along, for example when their connection drops and the agent looks stuck. An agent must never read it as permission to commit.
|
|
148
165
|
|
|
149
|
-
**What to do:** Copy the line that starts **"go" means carry on** from the top of the [`AGENTS.md` template](/templates#agents) into the top of the project's `AGENTS.md`.
|
|
166
|
+
**What to do:** Copy the line that starts **"go" means carry on** from the top of the [`AGENTS.md` template](/docs/templates#agents) into the top of the project's `AGENTS.md`.
|
|
150
167
|
|
|
151
168
|
**How to check:** The project's `AGENTS.md` has the line near the top.
|
|
152
169
|
|
|
@@ -154,17 +171,34 @@ See [When a name clashes](/Standards/human-readable-names#when-a-name-clashes).
|
|
|
154
171
|
|
|
155
172
|
**Why:** A big change, such as switching on the standard ESLint config, may be finished later. The version number has to stay honest about that.
|
|
156
173
|
|
|
157
|
-
**What to do:** Add an "Unfinished changes" section to `docs/development/coding-standards.md`, from the [template](/templates#document-templates). List any change from any version that is not done yet, with what is left and where it is being done, or write "None". See [Finishing a change later](/Guides/setup#finishing-a-change-later).
|
|
174
|
+
**What to do:** Add an "Unfinished changes" section to `docs/development/coding-standards.md`, from the [template](/docs/templates#document-templates). List any change from any version that is not done yet, with what is left and where it is being done, or write "None". See [Finishing a change later](/docs/Guides/setup#finishing-a-change-later).
|
|
158
175
|
|
|
159
176
|
**How to check:** `docs/development/coding-standards.md` has an "Unfinished changes" section.
|
|
160
177
|
|
|
178
|
+
### 11. Links, text and stand-in data live in `lib/constants/`
|
|
179
|
+
|
|
180
|
+
**Why:** One place for every link and every piece of text means nothing is hard-coded in a component, and the keys of `s` become the translation keys when a site gets more languages. noData lets every page render while working locally with no internet.
|
|
181
|
+
|
|
182
|
+
**What to do:**
|
|
183
|
+
|
|
184
|
+
- Create `lib/constants/` with `routes.ts`, `strings.ts`, `noData.ts` and `index.ts`, as in [Constants](/docs/Structure/folder-structure#constants). If the project already has them somewhere else, such as `app/constants/`, move the folder with `git mv` and fix the imports: `@/app/constants` → `@/lib/constants`.
|
|
185
|
+
- `routes.ts` exports `r`, with every link: the app's own pages, outside sites, and `mailto:`, `tel:` and `sms:` links. `strings.ts` exports `s`, with every piece of static text. Use named exports, `export const r = { … }`, never `export default`.
|
|
186
|
+
- Move links and text written straight into components into `r` and `s`.
|
|
187
|
+
- Rename each noData export to `NO_DATA_` plus the thing it stands in for: `noDataInsights` → `NO_DATA_INSIGHTS`. Move dummy values, such as `dummyHeading`, out of `s` to the top of `noData.ts` as `DUMMY_HEADING` and the rest. Move anything in `noData.ts` that is real copy, such as a page's metadata, into `s`.
|
|
188
|
+
- Use noData only in local development: `query?.insights ?? (IS_LOCAL_DEVELOPMENT ? NO_DATA_INSIGHTS : [])`.
|
|
189
|
+
- Inside `lib/constants/`, files import each other directly, `import { s } from "./strings";`, never through `@/lib/constants`.
|
|
190
|
+
- Copy the new **Links, text and stand-in data** line and the `r` and `s` exception from the [`AGENTS.md` template](/docs/templates#agents).
|
|
191
|
+
- Add `12.1` to the project's standards: it is a new standard, so ask the person whether the project follows it. Record a no in `docs/development/coding-standards.md`.
|
|
192
|
+
|
|
193
|
+
**How to check:** `grep -rn "export default" lib/constants` and `grep -rn "noData[A-Z]\|dummy" lib/constants/strings.ts` find nothing, and the type check, `pnpm lint` and the build pass.
|
|
194
|
+
|
|
161
195
|
### No action needed
|
|
162
196
|
|
|
163
|
-
- The [Ontology](/ontology) defines `dependency`: something the code relies on but does not define itself. Ticket relationships are not dependencies; each project names those itself.
|
|
164
|
-
- The package now ships a rename script for agents working from the command line, using TypeScript's own rename: `node node_modules/@activatus/code-standards/scripts/renameSymbol.mjs <file> <currentName> <newName>`. Pass `--list renames.txt` to do many renames in one run, one per line. It can't reach keys in untyped object literals, such as the expected value in a test's `toEqual({ … })`: search the tests for old names and fix those by hand. See [Renaming from the command line](/Guides/migrating#renaming-from-the-command-line).
|
|
165
|
-
- The [Setup](/Guides/setup) guide says the standards are a base for code only, and explains how to get past pnpm's `minimumReleaseAge` when a new version is too fresh to install.
|
|
166
|
-
- [Folder Structure](/Structure/folder-structure) explains each `lib/` folder in one line.
|
|
167
|
-
- The [ESLint page](/Standards/eslint#installation) says the config needs ESLint 10.4 or later, and the React configs explain why they set `settings.react.version`.
|
|
197
|
+
- The [Ontology](/docs/ontology) defines `dependency`: something the code relies on but does not define itself. Ticket relationships are not dependencies; each project names those itself.
|
|
198
|
+
- The package now ships a rename script for agents working from the command line, using TypeScript's own rename: `node node_modules/@activatus/code-standards/scripts/renameSymbol.mjs <file> <currentName> <newName>`. Pass `--list renames.txt` to do many renames in one run, one per line. It can't reach keys in untyped object literals, such as the expected value in a test's `toEqual({ … })`: search the tests for old names and fix those by hand. See [Renaming from the command line](/docs/Guides/migrating#renaming-from-the-command-line).
|
|
199
|
+
- The [Setup](/docs/Guides/setup) guide says the standards are a base for code only, and explains how to get past pnpm's `minimumReleaseAge` when a new version is too fresh to install.
|
|
200
|
+
- [Folder Structure](/docs/Structure/folder-structure) explains each `lib/` folder in one line.
|
|
201
|
+
- The [ESLint page](/docs/Standards/eslint#installation) says the config needs ESLint 10.4 or later, and the React configs explain why they set `settings.react.version`.
|
|
168
202
|
|
|
169
203
|
---
|
|
170
204
|
|
|
@@ -180,7 +214,7 @@ See [When a name clashes](/Standards/human-readable-names#when-a-name-clashes).
|
|
|
180
214
|
|
|
181
215
|
- `pnpm add -D @activatus/code-standards`
|
|
182
216
|
- Read the rest of this update from `node_modules/@activatus/code-standards/docs/version-history.md`. The templates to copy are in `node_modules/@activatus/code-standards/static/templates/`.
|
|
183
|
-
- In `AGENTS.md`, under "Code standards", say the standards are installed as `@activatus/code-standards`, and that agents read them from `node_modules/@activatus/code-standards/docs/`. Copy the wording from the [`AGENTS.md` template](/templates#agents).
|
|
217
|
+
- In `AGENTS.md`, under "Code standards", say the standards are installed as `@activatus/code-standards`, and that agents read them from `node_modules/@activatus/code-standards/docs/`. Copy the wording from the [`AGENTS.md` template](/docs/templates#agents).
|
|
184
218
|
|
|
185
219
|
**How to check:** `@activatus/code-standards` is in the project's `devDependencies`.
|
|
186
220
|
|
|
@@ -190,7 +224,7 @@ See [When a name clashes](/Standards/human-readable-names#when-a-name-clashes).
|
|
|
190
224
|
|
|
191
225
|
**What to do:**
|
|
192
226
|
|
|
193
|
-
- Print the numbered list in [Setup, step 3](/Guides/setup#3-agree-the-standards) to the person, exactly as written, and record their answer in `docs/development/coding-standards.md`.
|
|
227
|
+
- Print the numbered list in [Setup, step 3](/docs/Guides/setup#3-agree-the-standards) to the person, exactly as written, and record their answer in `docs/development/coding-standards.md`.
|
|
194
228
|
- For the rest of this update, **skip any change to a standard the person opted out of.**
|
|
195
229
|
|
|
196
230
|
**How to check:** `docs/development/coding-standards.md` lists the opted-out standards by number, or says "No differences".
|
|
@@ -205,10 +239,10 @@ See [When a name clashes](/Standards/human-readable-names#when-a-name-clashes).
|
|
|
205
239
|
- **If both `docsSite/` and `documentationSite/` exist**, merge them into `docsSite/`: move each tracked file from `documentationSite/` with `git mv`, keeping whichever copy is newer, then delete `documentationSite/`. Ask the person before deleting a file that exists in only one of them.
|
|
206
240
|
- Rename `docs/overview/writing-documentation.md` → `docs/overview/writing-docs.md`, and fix every link to it.
|
|
207
241
|
- Rename the environment variable `DOCUMENTATION_URL` → `DOCS_URL` in `next.config.mjs`, `.env.local`, `.env.example` and the hosting provider's settings.
|
|
208
|
-
- Rename the route `/documentation` → `/docs`. Copy the new rewrite from the [`next.config.mjs` template](/templates#docs-route).
|
|
209
|
-
- **Re-copy `docsSite/docusaurus.config.ts`** from the [`docsSite/` template](/templates#docs-site), keeping the project's name and theme. Version 2 changed it: `baseUrl: '/docs/'`, `path: '../docs'`, full-word variable names (`rest` → `remainingArguments`, `doc` → `page`), and `static/img` → `static/images`. Rename the project's `docsSite/static/img/` to `static/images/` to match.
|
|
242
|
+
- Rename the route `/documentation` → `/docs`. Copy the new rewrite from the [`next.config.mjs` template](/docs/templates#docs-route).
|
|
243
|
+
- **Re-copy `docsSite/docusaurus.config.ts`** from the [`docsSite/` template](/docs/templates#docs-site), keeping the project's name and theme. Version 2 changed it: `baseUrl: '/docs/'`, `path: '../docs'`, full-word variable names (`rest` → `remainingArguments`, `doc` → `page`), and `static/img` → `static/images`. Rename the project's `docsSite/static/img/` to `static/images/` to match.
|
|
210
244
|
- Rename the scripts in `package.json`: `documentation:install` → `docs:install`, `documentation:dev` → `docs:dev`, `documentation:build` → `docs:build`.
|
|
211
|
-
- If the docs site's generated folders were ever committed, stop tracking them: `git rm -r --cached docsSite/.docusaurus docsSite/build`. They are in the [`docsSite/` template's](/templates#docs-site) `.gitignore`.
|
|
245
|
+
- If the docs site's generated folders were ever committed, stop tracking them: `git rm -r --cached docsSite/.docusaurus docsSite/build`. They are in the [`docsSite/` template's](/docs/templates#docs-site) `.gitignore`.
|
|
212
246
|
- Update every mention in `AGENTS.md`, `README.md` and the docs themselves.
|
|
213
247
|
- **Update every ignore list** that names the old folders: ESLint, Prettier, `tsconfig.json`, Vitest or Jest, and `.gitignore`. A leftover docs site with its own `node_modules` makes test runners and linters run its files too.
|
|
214
248
|
|
|
@@ -222,10 +256,10 @@ See [When a name clashes](/Standards/human-readable-names#when-a-name-clashes).
|
|
|
222
256
|
|
|
223
257
|
- Rename every type ending in `Properties` to end in `Props`: `ButtonProperties` → `ButtonProps`. Never use find-and-replace. Use the editor's Rename Symbol (F2) or, for an agent working from the command line, the rename script in version 3 and later of the package: `node node_modules/@activatus/code-standards/scripts/renameSymbol.mjs <file> <currentName> <newName>`. Both use TypeScript's own rename, so they change every use and nothing else.
|
|
224
258
|
- Rename variables and parameters called `properties` to `props`, including spreads: `...buttonProperties` → `...buttonProps`.
|
|
225
|
-
- **If the project already uses the standard ESLint config**, copy the new [ESLint config](/Standards/eslint). It needs ESLint 10.4 or later. Two things changed in it:
|
|
259
|
+
- **If the project already uses the standard ESLint config**, copy the new [ESLint config](/docs/Standards/eslint). It needs ESLint 10.4 or later. Two things changed in it:
|
|
226
260
|
- The type-name rule is now `(Props|Type)$`.
|
|
227
261
|
- `unicorn/name-replacements` now has `replacements: { docs: false, props: false, utils: false }`.
|
|
228
|
-
- **If the project never had the standard ESLint config**, do only the renames in this change. Switching the config on can find hundreds of problems, so do it separately with [Migrating an Existing Project](/Guides/migrating), one stage per Pull Request, and record it as unfinished: see [Finishing a change later](/Guides/setup#finishing-a-change-later).
|
|
262
|
+
- **If the project never had the standard ESLint config**, do only the renames in this change. Switching the config on can find hundreds of problems, so do it separately with [Migrating an Existing Project](/docs/Guides/migrating), one stage per Pull Request, and record it as unfinished: see [Finishing a change later](/docs/Guides/setup#finishing-a-change-later).
|
|
229
263
|
|
|
230
264
|
**How to check:** `grep -rn "Properties\b" --include=*.ts --include=*.tsx --exclude-dir=node_modules .` finds nothing of ours, and `pnpm lint` passes.
|
|
231
265
|
|
|
@@ -243,7 +277,7 @@ See [When a name clashes](/Standards/human-readable-names#when-a-name-clashes).
|
|
|
243
277
|
|
|
244
278
|
### 6. Components live where they are used: no feature folders
|
|
245
279
|
|
|
246
|
-
**Why:** Grouping by feature and grouping by page meant two places for the same component. Now there is one rule. See [Where components live](/Structure/folder-structure#-where-components-live).
|
|
280
|
+
**Why:** Grouping by feature and grouping by page meant two places for the same component. Now there is one rule. See [Where components live](/docs/Structure/folder-structure#-where-components-live).
|
|
247
281
|
|
|
248
282
|
| Used by | Lives in |
|
|
249
283
|
| -------------------------------------------------------- | --------------------------- |
|
|
@@ -274,13 +308,13 @@ See [When a name clashes](/Standards/human-readable-names#when-a-name-clashes).
|
|
|
274
308
|
|
|
275
309
|
### 8. The Dictionary: short names that are words
|
|
276
310
|
|
|
277
|
-
**Why:** Some short names are words, not abbreviations. The [Dictionary](/Standards/human-readable-names#dictionary) is the one list of them, so nobody has to guess.
|
|
311
|
+
**Why:** Some short names are words, not abbreviations. The [Dictionary](/docs/Standards/human-readable-names#dictionary) is the one list of them, so nobody has to guess.
|
|
278
312
|
|
|
279
313
|
**What to do:**
|
|
280
314
|
|
|
281
315
|
- The Dictionary has: `id`, `docs`, `props`, `utils`, `app`, `url`, `api`, `uat`, `pdf`, `html`, `css`, `json`, `readme`.
|
|
282
316
|
- Any other short name in the project's own code is written out in full. If one seems like a word, ask for it to be added to the Dictionary; do not just use it.
|
|
283
|
-
- Copy the new "Dictionary words stay short" bullet into `AGENTS.md` from the [template](/templates#agents).
|
|
317
|
+
- Copy the new "Dictionary words stay short" bullet into `AGENTS.md` from the [template](/docs/templates#agents).
|
|
284
318
|
|
|
285
319
|
**How to check:** `pnpm lint` passes with the new ESLint config.
|
|
286
320
|
|
|
@@ -302,17 +336,17 @@ See [When a name clashes](/Standards/human-readable-names#when-a-name-clashes).
|
|
|
302
336
|
**What to do:**
|
|
303
337
|
|
|
304
338
|
- Keep the project's product words in `docs/product/ontology.md`.
|
|
305
|
-
- Check every word in it against the [Ontology](/ontology). If the project gives a code word a different meaning, remove that entry and use the code standards' meaning. Tell a person what changed.
|
|
339
|
+
- Check every word in it against the [Ontology](/docs/ontology). If the project gives a code word a different meaning, remove that entry and use the code standards' meaning. Tell a person what changed.
|
|
306
340
|
- Make the project's ontology say that it adds to the code standards' ontology.
|
|
307
|
-
- Update the "Ontology" section of `AGENTS.md` from the [template](/templates#agents). It now points to both ontologies.
|
|
341
|
+
- Update the "Ontology" section of `AGENTS.md` from the [template](/docs/templates#agents). It now points to both ontologies.
|
|
308
342
|
|
|
309
|
-
**How to check:** No term in `docs/product/ontology.md` is also defined in the code standards' [Ontology](/ontology).
|
|
343
|
+
**How to check:** No term in `docs/product/ontology.md` is also defined in the code standards' [Ontology](/docs/ontology).
|
|
310
344
|
|
|
311
345
|
### 11. Whether agents may commit is the project's choice
|
|
312
346
|
|
|
313
347
|
**Why:** Strict no commit is right for most projects, but a tool built to ship code with AI, such as Launchpad, needs agents to commit.
|
|
314
348
|
|
|
315
|
-
**What to do:** This is standard 22 in the list from change 2. If the person kept it, keep the template's "NEVER COMMIT CODE" lines for strict no commit. Otherwise, replace them with the project's own rule, saying exactly which agents may commit, push and open Pull Requests, and when. See [A project can choose otherwise](/Standards/agent-specs#project-workflow).
|
|
349
|
+
**What to do:** This is standard 22 in the list from change 2. If the person kept it, keep the template's "NEVER COMMIT CODE" lines for strict no commit. Otherwise, replace them with the project's own rule, saying exactly which agents may commit, push and open Pull Requests, and when. See [A project can choose otherwise](/docs/Standards/agent-specs#project-workflow).
|
|
316
350
|
|
|
317
351
|
**How to check:** The top of `AGENTS.md` states the project's commit rule.
|
|
318
352
|
|
|
@@ -330,8 +364,8 @@ See [When a name clashes](/Standards/human-readable-names#when-a-name-clashes).
|
|
|
330
364
|
|
|
331
365
|
### No action needed
|
|
332
366
|
|
|
333
|
-
- The [Setup](/Guides/setup) guide is written for the agent: install the package, check the version, agree the standards, apply them. It never asks which framework the project uses, and never creates the app: the person does that.
|
|
334
|
-
- The [migration guide](/Guides/migrating#stage-4--names) has a Names stage.
|
|
367
|
+
- The [Setup](/docs/Guides/setup) guide is written for the agent: install the package, check the version, agree the standards, apply them. It never asks which framework the project uses, and never creates the app: the person does that.
|
|
368
|
+
- The [migration guide](/docs/Guides/migrating#stage-4--names) has a Names stage.
|
|
335
369
|
|
|
336
370
|
---
|
|
337
371
|
|
|
@@ -341,4 +375,4 @@ See [When a name clashes](/Standards/human-readable-names#when-a-name-clashes).
|
|
|
341
375
|
|
|
342
376
|
The first numbered version: everything in the standards on this date. It included `documentation/` for the docs folder, `Properties` at the end of prop types, `utilities/` for reusable functions, `components/features/`, and the Component Reference. Version 2 replaced all five.
|
|
343
377
|
|
|
344
|
-
**What to do in a project:** follow the [migration guide](/Guides/migrating) for everything.
|
|
378
|
+
**What to do in a project:** follow the [migration guide](/docs/Guides/migrating) for everything.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@activatus/code-standards",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.4",
|
|
4
4
|
"description": "The Activatus code standards: the rules as Markdown, and the config files to copy. Install it so an AI agent can read the standards from node_modules.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
|
|
58
58
|
Activatus uses a fixed vocabulary, the ontology, in two parts:
|
|
59
59
|
|
|
60
|
-
- **Code words** — component, utils, Decision Doc and the rest — are defined in the code standards: https://activatus-code-standards.vercel.app/ontology
|
|
60
|
+
- **Code words** — component, utils, Decision Doc and the rest — are defined in the code standards: https://activatus-code-standards.vercel.app/docs/ontology
|
|
61
61
|
- **Product words** — what this project builds and how its work is planned — are defined in `docs/product/ontology.md`.
|
|
62
62
|
|
|
63
63
|
- **Read both before starting work.** If the project's ontology gives a code word a different meaning, the code standards win — point the difference out.
|
|
@@ -89,7 +89,7 @@ Follow these rules in every change:
|
|
|
89
89
|
|
|
90
90
|
- **Every function and component has a test file**, created in the same change. One test file tests one function or one component.
|
|
91
91
|
- **No file longer than 300 lines** (test files are exempt).
|
|
92
|
-
- **Every name is made of whole, human-readable words.** Variables, parameters, props, types, constants, form fields, files, folders, routes, database columns, scripts and environment variables — everything. No shortened words, no single letters, no numbered names, not even for a loop counter or an event handler. Full rule: Human-Readable Names in the code standards (https://activatus-code-standards.vercel.app/Standards/human-readable-names).
|
|
92
|
+
- **Every name is made of whole, human-readable words.** Variables, parameters, props, types, constants, form fields, files, folders, routes, database columns, scripts and environment variables — everything. No shortened words, no single letters (except `r` and `s`, below), no numbered names, not even for a loop counter or an event handler. Full rule: Human-Readable Names in the code standards (https://activatus-code-standards.vercel.app/docs/Standards/human-readable-names).
|
|
93
93
|
|
|
94
94
|
| Never | Always |
|
|
95
95
|
| --- | --- |
|
|
@@ -100,7 +100,7 @@ Follow these rules in every change:
|
|
|
100
100
|
| `helpers/`, `utilities/`, `helpers.ts` | `utils/`, a file named after what it does |
|
|
101
101
|
|
|
102
102
|
- **`id` is a word.** Write `id`, `userId`, `user_id` — never `identifier` and never `userID`. `identifier` is only for an outside system's separate field of that name (Linear's readable `ACT-73`).
|
|
103
|
-
- **Dictionary words stay short:** `id`, `docs`, `lib`, `props`, `ref`, `repo`, `utils`, `app`, `url`, `api`, `uat`, `pdf`, `html`, `css`, `json`, `readme`. Case them as words: `imageUrl`, not `imageURL`. Any other short name is written in full. A new dictionary word is added to the Dictionary in the Human-Readable Names standard first (https://activatus-code-standards.vercel.app/Standards/human-readable-names#dictionary), never just used.
|
|
103
|
+
- **Dictionary words stay short:** `id`, `docs`, `lib`, `props`, `ref`, `repo`, `utils`, `app`, `url`, `api`, `uat`, `pdf`, `html`, `css`, `json`, `readme`. Case them as words: `imageUrl`, not `imageURL`. Any other short name is written in full. A new dictionary word is added to the Dictionary in the Human-Readable Names standard first (https://activatus-code-standards.vercel.app/docs/Standards/human-readable-names#dictionary), never just used.
|
|
104
104
|
- **Names owned by someone else stay exactly as they are** — Linear's `id` and `pageInfo`, Node's `cwd` option and `process.env`, React's `ref` and `children`, shadcn/ui's `cn` helper, Next.js's `params`, `searchParams` and `LayoutProps`, HTML attributes, Tailwind classes. The rule is for names we write, not names from someone else's code. Renaming them breaks the code. Give the value a full-word name as soon as it comes into our code: `const workingDirectory = process.cwd();`, then pass `{ cwd: workingDirectory }`.
|
|
105
105
|
- **When a name clashes with a third-party import, rename our own thing first**, to a more specific full-word name: our `createProjectDatabaseClient`, next to Supabase's `createClient`. Rename the import only when both names are third-party, or ours is fixed by a framework (a Next.js route's `GET`). Then use the owner plus the original name, `Link as LucideLinkIcon`. Never rename an import for taste, and never shorten it.
|
|
106
106
|
- **Form fields especially.** A field has one name everywhere it goes: the input's `name` and `id`, the form schema, the API request, the type and the database column (`emailAddress` / `email_address`). Every field has a visible `<label>` in plain English — never a placeholder instead. Option values are words (`"monthly"`), not numbers. Validation messages name the field and say what to do.
|
|
@@ -114,10 +114,11 @@ Follow these rules in every change:
|
|
|
114
114
|
- **One parameter per function.** Use a single object when more than one value is needed.
|
|
115
115
|
- **Return early.** Never nest more than three levels deep.
|
|
116
116
|
- **No magic numbers or strings.** Use named constants.
|
|
117
|
+
- **Links, text and stand-in data live in `lib/constants/`**, never written straight into a component. `r` holds every link (pages, outside sites, `mailto:`, `tel:`, `sms:`). `s` holds every piece of static text, and its keys become the translation keys when the site gets more languages. `noData.ts` holds stand-in data named `NO_DATA_` plus the thing it replaces (`NO_DATA_INSIGHTS`), used only in local development when the real source can't be reached, never in production. Dummy values sit at the top of `noData.ts`, never in `s`. Import them all in one line, `import { NO_DATA_INSIGHTS, r, s } from "@/lib/constants";`. `r` and `s` are the only single-letter names allowed anywhere. Full rule: https://activatus-code-standards.vercel.app/docs/Structure/folder-structure#constants
|
|
117
118
|
- **No nested ternaries. No boolean flag parameters.**
|
|
118
119
|
- **No `any`, no non-null `!`, no `as` cast without a comment saying why.**
|
|
119
120
|
- **Named exports only**, except where a tool requires a default export.
|
|
120
|
-
- **Type names end in `Props` or `Type`**, and say what the thing is, not the job it does. A type that only describes one field of a function's props is written inside the `Props`: `StartAgentRunProps` holds its `dependencies`, with no separate `StartAgentRunDependenciesType`.
|
|
121
|
+
- **Type names end in `Props` or `Type`**, and say what the thing is, not the job it does. A type that only describes one field of a function's props is written inside the `Props`: `StartAgentRunProps` holds its `dependencies`, with no separate `StartAgentRunDependenciesType`. Every function still has its own `Props` for its single object parameter, such as `LaunchSessionProps` for `launchSession`, used wherever that function is written: `async ({ worktreePath }: LaunchSessionProps) =>`. Type a value where it is declared, never afterwards with `satisfies`. The one exception is Storybook story files, which follow Storybook's docs: `satisfies Meta<typeof Component>`.
|
|
121
122
|
- **One component per file.** Server and client components live in separate files.
|
|
122
123
|
- **Component file order**: imports, component, variables, state, `useMemo` values, `useCallback` functions, effects, render. No inline functions in render.
|
|
123
124
|
- **Reusable functions live in a `utils/` folder** — global, section or component level — one folder per function, with an `index.ts`.
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
## Decision
|
|
8
8
|
|
|
9
|
-
This project's docs follow the Activatus documentation standard: https://activatus-code-standards.vercel.app/Standards/documentation
|
|
9
|
+
This project's docs follow the Activatus documentation standard: https://activatus-code-standards.vercel.app/docs/Standards/documentation
|
|
10
10
|
|
|
11
11
|
Every file in `docs/` is a Decision Doc. Read the standard before adding or editing one.
|
|
12
12
|
|
|
@@ -7,6 +7,45 @@ import { flatConfigs as importX } from "eslint-plugin-import-x";
|
|
|
7
7
|
import unicorn from "eslint-plugin-unicorn";
|
|
8
8
|
import globals from "globals";
|
|
9
9
|
|
|
10
|
+
// Code patterns that are errors in every file.
|
|
11
|
+
const RESTRICTED_SYNTAX = [
|
|
12
|
+
{
|
|
13
|
+
selector: "ClassDeclaration",
|
|
14
|
+
message: "Use functions, not classes.",
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
selector: "ClassExpression",
|
|
18
|
+
message: "Use functions, not classes.",
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
selector: "VariableDeclarator > FunctionExpression",
|
|
22
|
+
message: "Use an arrow function.",
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
selector: "VariableDeclaration[kind='let']",
|
|
26
|
+
message:
|
|
27
|
+
"Use const. If this value really must be reassigned, disable this rule on this line with a comment saying why.",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
selector: "FunctionDeclaration[params.length>1]",
|
|
31
|
+
message:
|
|
32
|
+
"Use a single object parameter when a function needs more than one value.",
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
selector:
|
|
36
|
+
"VariableDeclarator > :matches(ArrowFunctionExpression, FunctionExpression)[params.length>1]",
|
|
37
|
+
message:
|
|
38
|
+
"Use a single object parameter when a function needs more than one value.",
|
|
39
|
+
},
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
// Type a value where it is declared. Story files are the exception: see below.
|
|
43
|
+
const NO_SATISFIES = {
|
|
44
|
+
selector: "TSSatisfiesExpression",
|
|
45
|
+
message:
|
|
46
|
+
"Type a value where it is declared, not with satisfies afterwards.",
|
|
47
|
+
};
|
|
48
|
+
|
|
10
49
|
export default [
|
|
11
50
|
{
|
|
12
51
|
ignores: [
|
|
@@ -58,34 +97,8 @@ export default [
|
|
|
58
97
|
],
|
|
59
98
|
"no-restricted-syntax": [
|
|
60
99
|
"error",
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
message: "Use functions, not classes.",
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
selector: "ClassExpression",
|
|
67
|
-
message: "Use functions, not classes.",
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
selector: "VariableDeclarator > FunctionExpression",
|
|
71
|
-
message: "Use an arrow function.",
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
selector: "VariableDeclaration[kind='let']",
|
|
75
|
-
message:
|
|
76
|
-
"Use const. If this value really must be reassigned, disable this rule on this line with a comment saying why.",
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
selector: "FunctionDeclaration[params.length>1]",
|
|
80
|
-
message:
|
|
81
|
-
"Use a single object parameter when a function needs more than one value.",
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
selector:
|
|
85
|
-
"VariableDeclarator > :matches(ArrowFunctionExpression, FunctionExpression)[params.length>1]",
|
|
86
|
-
message:
|
|
87
|
-
"Use a single object parameter when a function needs more than one value.",
|
|
88
|
-
},
|
|
100
|
+
NO_SATISFIES,
|
|
101
|
+
...RESTRICTED_SYNTAX,
|
|
89
102
|
],
|
|
90
103
|
"import-x/no-cycle": "error",
|
|
91
104
|
"import-x/no-default-export": "error",
|
|
@@ -177,5 +190,12 @@ export default [
|
|
|
177
190
|
files: ["**/*.config.{js,mjs,ts}"],
|
|
178
191
|
rules: { "unicorn/no-top-level-side-effects": "off" },
|
|
179
192
|
},
|
|
193
|
+
{
|
|
194
|
+
// Storybook's own docs type stories with `satisfies Meta<typeof Component>`, so story files may use it.
|
|
195
|
+
files: ["**/*.stories.{ts,tsx}"],
|
|
196
|
+
rules: {
|
|
197
|
+
"no-restricted-syntax": ["error", ...RESTRICTED_SYNTAX],
|
|
198
|
+
},
|
|
199
|
+
},
|
|
180
200
|
prettier,
|
|
181
201
|
];
|
|
@@ -9,6 +9,45 @@ import unicorn from "eslint-plugin-unicorn";
|
|
|
9
9
|
import globals from "globals";
|
|
10
10
|
import { configs as typescript } from "typescript-eslint";
|
|
11
11
|
|
|
12
|
+
// Code patterns that are errors in every file.
|
|
13
|
+
const RESTRICTED_SYNTAX = [
|
|
14
|
+
{
|
|
15
|
+
selector: "ClassDeclaration",
|
|
16
|
+
message: "Use functions, not classes.",
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
selector: "ClassExpression",
|
|
20
|
+
message: "Use functions, not classes.",
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
selector: "VariableDeclarator > FunctionExpression",
|
|
24
|
+
message: "Use an arrow function.",
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
selector: "VariableDeclaration[kind='let']",
|
|
28
|
+
message:
|
|
29
|
+
"Use const. If this value really must be reassigned, disable this rule on this line with a comment saying why.",
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
selector: "FunctionDeclaration[params.length>1]",
|
|
33
|
+
message:
|
|
34
|
+
"Use a single object parameter when a function needs more than one value.",
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
selector:
|
|
38
|
+
"VariableDeclarator > :matches(ArrowFunctionExpression, FunctionExpression)[params.length>1]",
|
|
39
|
+
message:
|
|
40
|
+
"Use a single object parameter when a function needs more than one value.",
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
// Type a value where it is declared. Story files are the exception: see below.
|
|
45
|
+
const NO_SATISFIES = {
|
|
46
|
+
selector: "TSSatisfiesExpression",
|
|
47
|
+
message:
|
|
48
|
+
"Type a value where it is declared, not with satisfies afterwards.",
|
|
49
|
+
};
|
|
50
|
+
|
|
12
51
|
export default [
|
|
13
52
|
{ ignores: ["dist/", "build/", "coverage/", "**/vendor/**"] },
|
|
14
53
|
js.configs.recommended,
|
|
@@ -54,34 +93,8 @@ export default [
|
|
|
54
93
|
],
|
|
55
94
|
"no-restricted-syntax": [
|
|
56
95
|
"error",
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
message: "Use functions, not classes.",
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
selector: "ClassExpression",
|
|
63
|
-
message: "Use functions, not classes.",
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
selector: "VariableDeclarator > FunctionExpression",
|
|
67
|
-
message: "Use an arrow function.",
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
selector: "VariableDeclaration[kind='let']",
|
|
71
|
-
message:
|
|
72
|
-
"Use const. If this value really must be reassigned, disable this rule on this line with a comment saying why.",
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
selector: "FunctionDeclaration[params.length>1]",
|
|
76
|
-
message:
|
|
77
|
-
"Use a single object parameter when a function needs more than one value.",
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
selector:
|
|
81
|
-
"VariableDeclarator > :matches(ArrowFunctionExpression, FunctionExpression)[params.length>1]",
|
|
82
|
-
message:
|
|
83
|
-
"Use a single object parameter when a function needs more than one value.",
|
|
84
|
-
},
|
|
96
|
+
NO_SATISFIES,
|
|
97
|
+
...RESTRICTED_SYNTAX,
|
|
85
98
|
],
|
|
86
99
|
"import-x/no-cycle": "error",
|
|
87
100
|
"import-x/no-default-export": "error",
|
|
@@ -169,5 +182,12 @@ export default [
|
|
|
169
182
|
files: ["**/*.config.{js,mjs,ts}"],
|
|
170
183
|
rules: { "unicorn/no-top-level-side-effects": "off" },
|
|
171
184
|
},
|
|
185
|
+
{
|
|
186
|
+
// Storybook's own docs type stories with `satisfies Meta<typeof Component>`, so story files may use it.
|
|
187
|
+
files: ["**/*.stories.{ts,tsx}"],
|
|
188
|
+
rules: {
|
|
189
|
+
"no-restricted-syntax": ["error", ...RESTRICTED_SYNTAX],
|
|
190
|
+
},
|
|
191
|
+
},
|
|
172
192
|
prettier,
|
|
173
193
|
];
|