pasika 0.10.2 → 0.10.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 +78 -201
- package/dist/chunk-7JI2V3HF.js +14 -0
- package/dist/eslint/pasika/index.d.ts +1 -0
- package/dist/eslint/pasika/index.js +335 -443
- package/dist/helpers/cn.d.ts +10 -0
- package/dist/helpers/cn.js +9 -0
- package/dist/helpers/http-error.d.ts +12 -0
- package/dist/helpers/http-error.js +6 -0
- package/dist/helpers/with-response.d.ts +27 -0
- package/dist/helpers/with-response.js +36 -0
- package/dist/helpers/zod-fetch.d.ts +29 -0
- package/dist/helpers/zod-fetch.js +45 -0
- package/package.json +39 -2
package/README.md
CHANGED
|
@@ -1,238 +1,115 @@
|
|
|
1
|
-
# pasika
|
|
2
|
-
|
|
3
|
-
Documentation, the lint rules derived from it, and the checks that apply and diagnose both.
|
|
4
|
-
|
|
5
|
-
`pasika` owns the framework's documentation and turns it into checks. Every requirement in `docs/` is recorded in an enforcement registry that says which ESLint rule or `pasika` check governs it — or, when none does, how a reviewer or agent applies it by hand. CI fails when a requirement has no recorded answer.
|
|
6
|
-
|
|
7
|
-
## Layout
|
|
8
|
-
|
|
9
|
-
```text
|
|
10
|
-
docs/
|
|
11
|
-
repository-policy.md # repo-wide code and documentation requirements (Policy)
|
|
12
|
-
next-codebase-guide/ # placement, extraction, module conventions
|
|
13
|
-
documentation-guide/ # how documents themselves are written
|
|
14
|
-
pasika-adoption-guide/ # adopting and updating the framework
|
|
15
|
-
next-tailwind-guide/ # Tailwind theme, composition, variants, states
|
|
16
|
-
scripts/
|
|
17
|
-
registry.json # requirement → enforcement, keyed by content hash
|
|
18
|
-
coverage.ts # reconciles the docs against the registry
|
|
19
|
-
dogfood.ts # lints sibling repos with the built presets
|
|
20
|
-
utils/ # doc parsing, classification, registry IO
|
|
21
|
-
types/ # registry schema
|
|
22
|
-
constants/
|
|
23
|
-
rfc2119.ts # single source of truth for RFC 2119 vocabulary
|
|
24
|
-
eslint/
|
|
25
|
-
rules/ # the lint rules, with fixture tests beside them
|
|
26
|
-
rules/documentation/ # the documentation-guide rules, linting docs/ itself
|
|
27
|
-
rules/tailwind/ # the Tailwind stylesheet rules
|
|
28
|
-
rules/package-json/ # the package.json rules
|
|
29
|
-
rules/husky/ # the husky-hook rules
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
## Documentation
|
|
33
|
-
|
|
34
|
-
Documents come in four kinds — Guide, Rule, Policy, and Reference — each with a template and a creation rule under `docs/documentation-guide/`. A Rule owns requirements about one subject and demonstrates them with paired Incorrect/Correct examples; a Reference describes and defines but never constrains; a Policy document collects repo-wide requirements that span unrelated subjects; a Guide sequences the others into workflows. Each guide owns its own glossary, so a term is defined beside the workflow that uses it.
|
|
35
|
-
|
|
36
|
-
## Enforcement
|
|
37
|
-
|
|
38
|
-
Requirements are identified by a hash of their canonical text, not by a hand-written id, so rewording one is visible:
|
|
39
|
-
|
|
40
|
-
```jsonc
|
|
41
|
-
{
|
|
42
|
-
"doc": "next-codebase-guide/rules/no-mixed-concerns-rule.md",
|
|
43
|
-
"text": "A .tsx file that defines a component MUST contain exactly one component.",
|
|
44
|
-
"hash": "b19fe3bd34",
|
|
45
|
-
"ref": "pasika/no-mixed-concerns",
|
|
46
|
-
"note": "counts exported components; a second component that is not exported is not detected",
|
|
47
|
-
}
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
The `text` field is the bullet as written in the document (markdown links and code spans intact), so it is greppable in the doc it came from; the `hash` is computed from the same text with links collapsed to their text and code spans unwrapped, so editing a URL or adding backticks does not read as a change.
|
|
1
|
+
# pasika 🐝
|
|
51
2
|
|
|
52
|
-
|
|
3
|
+
> пасіка — _apiary_ in Ukrainian
|
|
53
4
|
|
|
54
|
-
|
|
5
|
+
The documentation an agent works from, the ESLint rules that documentation turns into, and the runtime helpers those rules assume.
|
|
55
6
|
|
|
56
|
-
|
|
7
|
+
`pasika` is where a repository's conventions are written down once. Every requirement lives in `docs/`, and every one is recorded against the check that enforces it, so what the rules require and what the code does cannot drift apart. A **Rule** states requirements about one subject, a **Reference** defines the shapes and terms they are written in, a **Policy** collects the repo-wide ones, and a **Guide** sequences them into a workflow with its own glossary.
|
|
57
8
|
|
|
58
|
-
|
|
9
|
+
---
|
|
59
10
|
|
|
60
|
-
|
|
11
|
+
## 📦 Install
|
|
61
12
|
|
|
62
|
-
|
|
63
|
-
npm run coverage # check that every requirement has recorded enforcement
|
|
64
|
-
npm run coverage -- --accept # record reworded and removed requirements
|
|
65
|
-
npx libyear --limit-major-individual=1 # fail when a dependency trails the latest by >1 major (drift check)
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
Both acceptance and the report accept `--json` for agent use:
|
|
13
|
+
`zirka` brings pasika with it, as the package holding the preset's rules:
|
|
69
14
|
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
npx tsx scripts/coverage.ts --json # full report as JSON
|
|
73
|
-
npx tsx scripts/coverage.ts --accept # record accepted changes
|
|
15
|
+
```sh
|
|
16
|
+
npm i -D zirka eslint prettier typescript
|
|
74
17
|
```
|
|
75
18
|
|
|
76
|
-
|
|
19
|
+
Standalone, the presets need the language plugins as peers:
|
|
77
20
|
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
npx tsx scripts/coverage.ts --classify 041b665bd7 --note "no check can compare against the previous state"
|
|
21
|
+
```sh
|
|
22
|
+
npm i -D pasika eslint @eslint/css @eslint/json @eslint/markdown
|
|
81
23
|
```
|
|
82
24
|
|
|
83
|
-
The
|
|
25
|
+
The runtime helpers resolve `clsx` / `tailwind-merge`, `zod`, and `next` as optional peers, so install only the ones whose imports you use.
|
|
84
26
|
|
|
85
|
-
##
|
|
27
|
+
## ⚡ Quick start
|
|
86
28
|
|
|
87
|
-
|
|
29
|
+
Track the guides through `vulyk`, then switch them on in the ESLint config:
|
|
88
30
|
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
npm run dogfood -- ../some/repo --pasika-only # tally only pasika/* rules
|
|
94
|
-
npm run dogfood -- ../some/repo --rule=css-entry-point --findings
|
|
95
|
-
npm run dogfood -- ../some/repo --json # machine-readable report
|
|
31
|
+
```sh
|
|
32
|
+
npx vulyk add https://github.com/Bredansky/pasika/tree/<commit>/docs/next-codebase-guide \
|
|
33
|
+
--group managed --targets src
|
|
34
|
+
npx vulyk agents
|
|
96
35
|
```
|
|
97
36
|
|
|
98
|
-
The script writes a temporary standalone `eslint.config.mjs` that imports the preset from this repo's `dist`, so it exercises exactly the config a consuming repository would write. The exit code reports whether the run succeeded; the target's problem count is informational (printed as `Exit code would be`). A missing `dist` build or an unknown flag exits non-zero.
|
|
99
|
-
|
|
100
|
-
## ESLint ruleset
|
|
101
|
-
|
|
102
|
-
### With Zirka (recommended)
|
|
103
|
-
|
|
104
37
|
```ts
|
|
105
|
-
// eslint.config.ts
|
|
38
|
+
// eslint.config.ts
|
|
106
39
|
import { RuleSeverity, styleguide } from "zirka";
|
|
107
40
|
|
|
108
41
|
const { eslintConfig } = styleguide({
|
|
109
|
-
next: RuleSeverity.Error,
|
|
110
42
|
node: RuleSeverity.Error,
|
|
111
43
|
typescript: RuleSeverity.Error,
|
|
44
|
+
next: RuleSeverity.Error,
|
|
112
45
|
pasikaNextjsApp: RuleSeverity.Error,
|
|
113
46
|
});
|
|
114
47
|
|
|
115
48
|
export default eslintConfig;
|
|
116
49
|
```
|
|
117
50
|
|
|
118
|
-
|
|
51
|
+
Without `zirka`, import `pasikaNextjsApp` from `pasika/eslint` and export it directly. `pasikaApp` is the plain-TypeScript preset — the manifest, the zirka contract, and the docs, with no `src/**` source block.
|
|
119
52
|
|
|
120
|
-
|
|
53
|
+
## 🛡️ The ruleset
|
|
121
54
|
|
|
122
|
-
|
|
123
|
-
// eslint.config.ts — plain TypeScript repository
|
|
124
|
-
import { pasikaApp } from "pasika/eslint";
|
|
55
|
+
95 rules over five scopes:
|
|
125
56
|
|
|
126
|
-
|
|
127
|
-
|
|
57
|
+
| Scope | Rules | Language plugin |
|
|
58
|
+
| ----------------- | ----- | ------------------------------------ |
|
|
59
|
+
| `src/**` TS / TSX | 51 | `@typescript-eslint/parser`, bundled |
|
|
60
|
+
| `docs/**/*.md` | 25 | `@eslint/markdown` |
|
|
61
|
+
| Stylesheets | 12 | `@eslint/css` |
|
|
62
|
+
| `package.json` | 6 | `@eslint/json` |
|
|
63
|
+
| `.husky/*` | 1 | — |
|
|
64
|
+
|
|
65
|
+
The requirement behind every rule id is in the guides; `npx tsx scripts/coverage.ts --json` prints the mapping. CI fails when a requirement has no recorded answer, when its text changed, when its ref names no rule, or when a rule-governed requirement has no test titled with it.
|
|
66
|
+
|
|
67
|
+
Some rules are cross-file: where a component, hook, value, type, or style belongs depends on which files use it, so those index the whole `src/` tree instead of one file. A move therefore changes which file gets reported, which is why a lint command must not pass ESLint's `--cache` — the repository policy requires this — and why the index is read from disk rather than from ESLint's file list, so a partial run like `lint-staged` still judges against the true graph.
|
|
68
|
+
|
|
69
|
+
## 🧱 Runtime helpers
|
|
70
|
+
|
|
71
|
+
Four helpers ship with the package, so a repository imports them instead of writing its own copy to the shape the rules expect:
|
|
72
|
+
|
|
73
|
+
| Import | Exports | Resolves against (optional peer) |
|
|
74
|
+
| ---------------------- | -------------------------------------------------- | -------------------------------- |
|
|
75
|
+
| `pasika/cn` | `cn` | `clsx`, `tailwind-merge` |
|
|
76
|
+
| `pasika/http-error` | `HttpError` | — |
|
|
77
|
+
| `pasika/zod-fetch` | `zodFetch` | `zod` |
|
|
78
|
+
| `pasika/with-response` | `withResponse`, `HandlerResult`, `ResponseHeaders` | `next`, `zod` |
|
|
79
|
+
|
|
80
|
+
The entries share one `HttpError`, so a failure `zodFetch` throws satisfies the `instanceof` check `withResponse` makes. The TS/TSX rules call the TypeScript compiler API at lint time, so `typescript` is a pinned runtime dependency rather than a peer.
|
|
128
81
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
The
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
|
138
|
-
|
|
|
139
|
-
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
|
144
|
-
|
|
|
145
|
-
|
|
|
146
|
-
|
|
|
147
|
-
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
| `pasika/data-testid-case` | `data-testid` casing where a rendered result carries one |
|
|
154
|
-
| `pasika/support-folder-shape` | A `constants/`, `types/`, or `schemas/` folder defines exports directly in `index.ts` or in named-re-exported files |
|
|
155
|
-
| `pasika/import-through-index` | An extracted constant, type, or schema is imported through its folder's `index.ts` |
|
|
156
|
-
| `pasika/util-file-name` | A single-function utility file is named in the function's kebab-case form |
|
|
157
|
-
| `pasika/no-util-barrel` | A utility is imported directly, without a barrel |
|
|
158
|
-
| `pasika/jsx-hygiene` | Calculations and complex conditions stay out of JSX children and attributes |
|
|
159
|
-
| `pasika/interactive-component` | Interactive elements are component boundaries when mixed with other content |
|
|
160
|
-
| `pasika/ui-state` | Native or ARIA state expression and Tailwind state variants |
|
|
161
|
-
| `pasika/cross-feature-import` | A component importing from two or more feature folders lives in a shared location |
|
|
162
|
-
| `pasika/pure-function-extract` | Pure functions extracted to `utils/`, even with one consumer |
|
|
163
|
-
| `pasika/hook-complexity` | Hook complexity limits (imperative categories per hook) |
|
|
164
|
-
| `pasika/locale-dotted-path` | A namespaced locale is read through its full dotted path |
|
|
165
|
-
| `pasika/locales-location` | Locales live in the named locales object |
|
|
166
|
-
| `pasika/hook-extraction` † | A hook with two or more consumers is extracted to its own file |
|
|
167
|
-
| `pasika/value-extraction` † | A value with cross-folder consumers is extracted |
|
|
168
|
-
| `pasika/config-extraction` † | A type, schema, or utility used outside its config module is moved |
|
|
169
|
-
| `pasika/component-nesting` † | A component is not nested solely because it has support files |
|
|
170
|
-
| `pasika/stay-flat` † | A component stays flat until it has exclusive children |
|
|
171
|
-
| `pasika/type-extraction` † | A type or schema with cross-folder consumers is extracted |
|
|
172
|
-
| `pasika/locale-placement` † | Shared locales at the top level, single-feature locales namespaced |
|
|
173
|
-
| `pasika/locale-key-shape` | camelCase locale keys; keys over 30 characters end in a WAI-ARIA element role |
|
|
174
|
-
| `pasika/shared-style-dedup` † | A className combo used by two or more components becomes a named utility |
|
|
175
|
-
| `pasika/repeated-structure` | A block of elements repeated two or more times is extracted as a named component |
|
|
176
|
-
| `pasika/sole-state-owner` | A contiguous JSX part that is the sole consumer of a useState hook is extracted into a named component |
|
|
177
|
-
| `pasika/zirka-baseline` | eslint, prettier, and TypeScript configuration come from zirka instead of being restated locally |
|
|
178
|
-
| `pasika/zod-schema-validation` | Runtime validation through Zod schemas, not hand-written type guards |
|
|
179
|
-
| `pasika/source-under-src` | Application source lives under `src/`, not in root-level folders |
|
|
180
|
-
|
|
181
|
-
### Tailwind rules
|
|
182
|
-
|
|
183
|
-
Applied to `src/**/globals.css` (and other stylesheets) through `@eslint/css` with tolerant Tailwind v4 parsing.
|
|
184
|
-
|
|
185
|
-
| Rule | Enforces |
|
|
186
|
-
| --------------------------------- | ----------------------------------------------------------------------------------------------------- |
|
|
187
|
-
| `pasika/theme-reset` | A `--*: initial` theme reset is present |
|
|
188
|
-
| `pasika/root-variables` | `:root` defines the CSS custom properties |
|
|
189
|
-
| `pasika/apply-usage` | `@layer base` uses `@apply` for declarations |
|
|
190
|
-
| `pasika/base-layer-pair` | The base layer applies `base-canvas` and `base-ink` |
|
|
191
|
-
| `pasika/stylesheet-ordering` | Imports → `@custom-variant` → `:root` → `@theme` → `@utility` → `@layer base` |
|
|
192
|
-
| `pasika/css-variable-naming` | Background vars named `--<role>-canvas`, text vars `--<role>-ink` |
|
|
193
|
-
| `pasika/custom-utility-apply` | `@utility` blocks use `@apply` |
|
|
194
|
-
| `pasika/skin-utility` | Repeated style combinations become a named skin utility |
|
|
195
|
-
| `pasika/theme-variable-namespace` | Utility class groups share a namespace prefix |
|
|
196
|
-
| `pasika/css-entry-point` † | One global entry, imported by one module, project CSS only in a stylesheet the entry imports directly |
|
|
197
|
-
| `pasika/unused-utility` | A custom `@utility` no source file references is reported as dead |
|
|
198
|
-
|
|
199
|
-
### Package.json rules
|
|
200
|
-
|
|
201
|
-
Applied to `package.json` through `@eslint/json`. The framework-agnostic `exact-version` rule applies to any repository, including pasika itself; `nextjs-stack` applies to a Next.js/React application, and the Vulyk rules apply to a repository adopting the framework.
|
|
202
|
-
|
|
203
|
-
| Rule | Enforces |
|
|
204
|
-
| ------------------------- | ------------------------------------------------------------------------------------------------- |
|
|
205
|
-
| `pasika/exact-version` | Dependency and devDependency versions are pinned exactly, never ranges |
|
|
206
|
-
| `pasika/nextjs-stack` | All Tech Stack Reference packages are listed in `package.json` (Next.js/React apps) |
|
|
207
|
-
| `pasika/vulyk-dependency` | `vulyk` is listed in `devDependencies`, not `dependencies` |
|
|
208
|
-
| `pasika/tracked-docs` | `vulyk.config.ts` tracks the framework's required tracked docs from pasika and `AGENTS.md` exists |
|
|
209
|
-
|
|
210
|
-
### Documentation rules
|
|
211
|
-
|
|
212
|
-
The `pasika/*` markdown rules enforce the documentation guide over `docs/**/*.md` (22 rules): file-name suffixes and titles, overview shape (presence, sentence count, links), guide step structure, Incorrect/Correct pairing, policy document shape, reference block headings, RFC 2119 placement, template hygiene, link anchoring, and glossary-term linking. They run through `@eslint/markdown`; `npm run coverage` verifies each has a test and a registry entry. Pasika's own `docs/` are linted by them in CI (`npm run lint`).
|
|
213
|
-
|
|
214
|
-
Run `npx tsx scripts/coverage.ts --json` for the exact requirement each rule covers.
|
|
215
|
-
|
|
216
|
-
### † Cross-file rules
|
|
217
|
-
|
|
218
|
-
Where a component, hook, value, type, or style belongs depends on which files use it — and whether a stylesheet sits inside the global import graph depends on the whole `src/` tree — so the rules marked † index the whole `src/` tree instead of looking at one file. Two consequences:
|
|
219
|
-
|
|
220
|
-
- **Do not pass `--cache`.** Move a file and the finding belongs to a _different_ file, whose cache entry is unchanged — so ESLint would replay a stale verdict. `repository-policy.md` requires lint commands to run without it.
|
|
221
|
-
- The index is read from disk rather than from ESLint's file list, so a partial run such as `lint-staged` still judges against the true graph.
|
|
222
|
-
|
|
223
|
-
All are inert in a repository with no `src/` tree.
|
|
224
|
-
|
|
225
|
-
## Runtime dependency on typescript
|
|
226
|
-
|
|
227
|
-
Many of the TS/TSX rules call the TypeScript compiler API directly at lint time, so the published package imports `typescript` at runtime. `tsup` keeps it external (unbundled); `pasika` lists it as a pinned `dependency` so an installing consumer gets a version known to work with the rules. There is no `typescript` `peerDependency`.
|
|
228
|
-
|
|
229
|
-
## Development
|
|
230
|
-
|
|
231
|
-
```bash
|
|
232
|
-
npm run lint
|
|
82
|
+
## 📚 Documentation
|
|
83
|
+
|
|
84
|
+
The guides ship in this repository and are adopted into a project through `vulyk`. Each one owns its glossary:
|
|
85
|
+
|
|
86
|
+
| Document | Covers |
|
|
87
|
+
| -------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- |
|
|
88
|
+
| [Repository Policy](https://github.com/Bredansky/pasika/blob/main/docs/repository-policy.md) | requirements spanning every change in a repository |
|
|
89
|
+
| [Next Codebase Guide](https://github.com/Bredansky/pasika/blob/main/docs/next-codebase-guide/next-codebase-guide.md) | where code lives: modules, components, support files, imports |
|
|
90
|
+
| [Next Tailwind Guide](https://github.com/Bredansky/pasika/blob/main/docs/next-tailwind-guide/next-tailwind-guide.md) | theme tokens, class composition, variants, states |
|
|
91
|
+
| [Documentation Guide](https://github.com/Bredansky/pasika/blob/main/docs/documentation-guide/documentation-guide.md) | how documents themselves are written |
|
|
92
|
+
| [Pasika Adoption Guide](https://github.com/Bredansky/pasika/blob/main/docs/pasika-adoption-guide/pasika-adoption-guide.md) | adopting and updating the framework |
|
|
93
|
+
|
|
94
|
+
## 🐝 Sibling packages
|
|
95
|
+
|
|
96
|
+
| Package | What it does |
|
|
97
|
+
| ------------------------------------------- | ------------------------------------------------------------------------------- |
|
|
98
|
+
| [vulyk](https://github.com/Bredansky/vulyk) | Installs skills and tracked docs from pinned sources, and generates agent files |
|
|
99
|
+
| **pasika** | The documentation, the rules derived from it, and the helpers — this package |
|
|
100
|
+
| [zirka](https://github.com/Bredansky/zirka) | Wires ESLint, Prettier, and TypeScript into one `styleguide()` config |
|
|
101
|
+
|
|
102
|
+
## 🧪 Development
|
|
103
|
+
|
|
104
|
+
```sh
|
|
105
|
+
npm run lint # eslint, including the framework's own docs rules
|
|
233
106
|
npm run typecheck
|
|
234
107
|
npm run test:unit
|
|
235
|
-
npm run coverage
|
|
108
|
+
npm run coverage # every requirement still has recorded enforcement
|
|
236
109
|
npm run build
|
|
237
|
-
npm run dogfood -- ../some/repo #
|
|
110
|
+
npm run dogfood -- ../some/repo # lint a sibling repo with the built presets
|
|
238
111
|
```
|
|
112
|
+
|
|
113
|
+
## 📄 License
|
|
114
|
+
|
|
115
|
+
MIT
|
|
@@ -240,6 +240,7 @@ declare const pasikaPlugin: {
|
|
|
240
240
|
"route-handler-shape": eslint.Rule.RuleModule;
|
|
241
241
|
"http-error-usage": eslint.Rule.RuleModule;
|
|
242
242
|
"with-response-helper": eslint.Rule.RuleModule;
|
|
243
|
+
"zod-fetch-helper": eslint.Rule.RuleModule;
|
|
243
244
|
"hook-complexity": eslint.Rule.RuleModule;
|
|
244
245
|
"locale-dotted-path": eslint.Rule.RuleModule;
|
|
245
246
|
"locales-location": eslint.Rule.RuleModule;
|