@groma/scanner-react 0.1.5 → 0.2.1
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 -43
- package/dist/index.js +1003 -606
- package/package.json +23 -3
- package/validation.md +2 -2
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# React scanner
|
|
2
2
|
|
|
3
|
-
The React scanner connects a
|
|
4
|
-
the component's
|
|
3
|
+
The React scanner connects a callback that a JSX element supplies as a prop to
|
|
4
|
+
the component's calls of that prop. Enable it alongside the TypeScript scanner.
|
|
5
5
|
Core selects relationships from the combined evidence and keeps one owner per
|
|
6
6
|
physical source file.
|
|
7
7
|
|
|
@@ -20,15 +20,27 @@ groma scanner check
|
|
|
20
20
|
groma scan
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
The private prototype package bundles TypeScript 6.0
|
|
24
|
-
declarations.
|
|
23
|
+
The private prototype package bundles TypeScript 6.0 and its standard-library
|
|
24
|
+
declarations. The TypeScript scanner keeps its native TypeScript 7 SDK. No consumer build
|
|
25
25
|
or installation script is required. Public naming and publication are separate
|
|
26
26
|
release decisions.
|
|
27
27
|
|
|
28
|
-
The scanner reads each selected
|
|
29
|
-
using its bundled TypeScript compiler.
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
The scanner reads each selected package's nearest `tsconfig.json` and owned TSX
|
|
29
|
+
files using its bundled TypeScript compiler. It reads only the files groma.md
|
|
30
|
+
hands it, never declaration files as sources, and a syntax error only fails the
|
|
31
|
+
scan in a file it reads. The package declares the default
|
|
32
|
+
[include and exclude lists](../index.md#selecting-source-files): it includes
|
|
33
|
+
`.ts` and `.tsx` sources, `tsconfig*.json` configs, and the `package.json`, HTML,
|
|
34
|
+
`project.json` and `nx.json` files the entry reader reads, and excludes `.test`
|
|
35
|
+
and `.spec` files, the root `test` folder, and `node_modules`, `dist`, `build`
|
|
36
|
+
and `coverage` folders. Project dependencies and
|
|
37
|
+
React types do not need to be installed. A solution `tsconfig.json` that names no source of its
|
|
38
|
+
own compiles through the first config it references that compiles one of its
|
|
39
|
+
components. An extended config a fresh
|
|
40
|
+
checkout lacks, such as an uninstalled package or a generated file, leaves the
|
|
41
|
+
config's own settings and reports a `react-missing-config-base` warning.
|
|
42
|
+
Invalid configuration and source syntax fail with a diagnostic; missing external
|
|
43
|
+
types do not prevent local callback extraction.
|
|
32
44
|
The scanner does not run application code or require successful type checking.
|
|
33
45
|
|
|
34
46
|
## Evidence and tooling
|
|
@@ -36,17 +48,29 @@ The scanner does not run application code or require successful type checking.
|
|
|
36
48
|
[React documents callback props](https://react.dev/learn/responding-to-events).
|
|
37
49
|
[TypeScript owns JSX parsing and checking](https://www.typescriptlang.org/docs/handbook/jsx.html),
|
|
38
50
|
project membership, imported component identities, and source symbols.
|
|
39
|
-
The adapter uses the
|
|
40
|
-
[TypeScript 6.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-6-0.html)
|
|
41
|
-
|
|
51
|
+
The adapter uses the classic compiler API of its bundled
|
|
52
|
+
[TypeScript 6.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-6-0.html),
|
|
53
|
+
the last release that retains it. The plugin does not recreate language
|
|
42
54
|
name or type resolution.
|
|
43
55
|
|
|
44
|
-
A component
|
|
45
|
-
in the
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
56
|
+
A component, and a handler the JSX attribute names, must resolve to a source
|
|
57
|
+
function in the files the scanner reads, or to a `const` holding one. React's
|
|
58
|
+
`useCallback`, `memo` and `forwardRef` hand back the function they are given, so
|
|
59
|
+
a `const` holding such a call holds that function; they count only when imported
|
|
60
|
+
from `react`, by name or through its module object. A handler may also be a
|
|
61
|
+
function written in place, and a TypeScript module may hold it; that module then
|
|
62
|
+
joins the scanner's files. The component reads the callback prop from its first
|
|
63
|
+
parameter, by destructuring it, with or without a default, or as a property of
|
|
64
|
+
that parameter, such as `props.onSave()`. Calls are matched to the exact
|
|
65
|
+
compiler symbol of the destructured prop or the props parameter. Each concrete
|
|
66
|
+
JSX attribute has a separate binding; nested calls belong to their nearest
|
|
67
|
+
function, method or accessor.
|
|
68
|
+
|
|
69
|
+
In a project whose tsconfig sets `moduleSuffixes`, as React Native projects do,
|
|
70
|
+
the compiler resolves each import for one platform. A file named for a platform,
|
|
71
|
+
by one of those suffixes or `.web`, such as `Menu.web.tsx`, binds only to
|
|
72
|
+
components of its own platform, or to a shared file beside which its platform
|
|
73
|
+
has no file of its own.
|
|
50
74
|
|
|
51
75
|
Operation, call, and attribute positions are original zero-based UTF-16 offsets;
|
|
52
76
|
lines are one-based. The named prop supplies the existing `member` field.
|
|
@@ -81,22 +105,23 @@ here React, with the symbols of all those links.
|
|
|
81
105
|
The scanner reports [HTTP facts](../evidence.md#http-endpoints-and-requests) for
|
|
82
106
|
the clients it recognizes in the TSX files it reads, and for the endpoints a
|
|
83
107
|
Next.js project declares by file location. In a project that declares `next`, it
|
|
84
|
-
also reads `app/**/route.ts` and `.tsx` and `pages/api/**`,
|
|
108
|
+
also reads `app/**/route.ts` and `.tsx` and `pages/api/**`, including route files
|
|
109
|
+
the tsconfig leaves out, such as a `.well-known` directory, which another scanner
|
|
85
110
|
may read as well. Next.js reads each of `app` and `pages` from the project root,
|
|
86
111
|
or from `src` only when the root has none, so a `src/app` beside a root `app`
|
|
87
112
|
serves nothing.
|
|
88
113
|
|
|
89
114
|
| Construct | Reported |
|
|
90
115
|
| --- | --- |
|
|
91
|
-
| `fetch(url, init)`, including a `node-fetch` default import | Request; a literal `method` gives the method, no options means `GET`, and options the scanner cannot read leave it out |
|
|
92
|
-
| `axios.get`, `.post`, `.put`, `.patch`, `.delete`, `.head`, `.options` | Request with that method |
|
|
116
|
+
| `fetch(url, init)`, including a `node-fetch` default import or a named `undici` import | Request; a literal `method` gives the method, no options means `GET`, and options the scanner cannot read leave it out |
|
|
117
|
+
| `axios.get`, `.post`, `.put`, `.patch`, `.delete`, `.head`, `.options`, `.postForm`, `.putForm`, `.patchForm` | Request with that method; form helpers use their matching HTTP method |
|
|
93
118
|
| `axios(config)`, `axios.request(config)` | Request from the config's `url`; its `method`, else the client's, else `GET` |
|
|
94
119
|
| `axios.create(config)` instances | Request whose path follows the config's `baseURL`, and whose method defaults to the config's |
|
|
95
|
-
| `app/**/route.ts` | Endpoint per exported `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `HEAD` or `OPTIONS` handler, at the route's directory path |
|
|
120
|
+
| `app/**/route.ts` | Endpoint per exported `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `HEAD` or `OPTIONS` handler, including names in an export list, at the route's directory path |
|
|
96
121
|
| `pages/api/**` | Endpoint for the default export, which answers every method, so `*` |
|
|
97
122
|
|
|
98
123
|
`fetch` counts when it is the runtime's, which the project neither declares nor
|
|
99
|
-
imports,
|
|
124
|
+
imports, the default export of `node-fetch`, or a named `undici` import, so a `fetch` the project exports
|
|
100
125
|
from its own module is that function. An `axios` client counts only when its
|
|
101
126
|
name is the `axios` default import, or a variable the project never assigns
|
|
102
127
|
again holding `require('axios')` or `axios.create(...)` called on it, so
|
|
@@ -130,9 +155,9 @@ The [producer decisions](../evidence.md#producer-checklist) for this ecosystem:
|
|
|
130
155
|
declares `next`. A page, a layout, `middleware.ts`, and a component answer no
|
|
131
156
|
request of their own, and `pages/api.tsx` is a page, not a route. A route file
|
|
132
157
|
whose path holds a parallel route `@modal` or an intercepted route `(.)talks`
|
|
133
|
-
reports nothing, because the served path is not the file path there
|
|
134
|
-
|
|
135
|
-
nothing.
|
|
158
|
+
reports nothing, because the served path is not the file path there, and a
|
|
159
|
+
private folder such as `_lib` is not routed. An export whose value is a
|
|
160
|
+
literal, such as a configuration object, serves nothing.
|
|
136
161
|
3. **Dynamic or unknown.** `` `/talks/${id}` `` fills one whole segment, so it is
|
|
137
162
|
dynamic. `` `/talks/${id}-latest` ``, a path built from a parameter, and an
|
|
138
163
|
unresolvable value are unknown. The query and fragment are dropped, computed
|
|
@@ -166,8 +191,11 @@ The [producer decisions](../evidence.md#producer-checklist) for this ecosystem:
|
|
|
166
191
|
segment, so `app/api/(admin)/audit/route.ts` serves `/api/audit`. A Pages
|
|
167
192
|
Router `index` file serves its directory, while a directory named `index` is an
|
|
168
193
|
ordinary segment. An App Router endpoint names the exported handler for its
|
|
169
|
-
method
|
|
170
|
-
designates.
|
|
194
|
+
method, and a Pages Router endpoint the function its default export
|
|
195
|
+
designates. A handler the file does not define as a function, such as a
|
|
196
|
+
wrapper's result or an imported handler, is served by the file's module code,
|
|
197
|
+
which the endpoint then names. Every request names the function that runs the
|
|
198
|
+
call, or the module code outside every function.
|
|
171
199
|
7. **Constrained segments.** None: `[id]`, `[...rest]` and `[[...rest]]` accept
|
|
172
200
|
any text.
|
|
173
201
|
8. **Registration order.** None: Next.js prefers the most specific route,
|
|
@@ -175,27 +203,34 @@ The [producer decisions](../evidence.md#producer-checklist) for this ecosystem:
|
|
|
175
203
|
|
|
176
204
|
## Limits
|
|
177
205
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
206
|
+
The scanner does not analyze state stores, routing, server components, class
|
|
207
|
+
components, hooks other than `useCallback`, wrappers other than `memo` and
|
|
208
|
+
`forwardRef`, callback forwarding, returned functions, mutable values, DOM
|
|
209
|
+
dispatch, or callback expressions other than a function written in place. A prop the component calls
|
|
210
|
+
that receives anything other than a supported direct binding, and a JSX spread on
|
|
211
|
+
a component that calls a prop from its first parameter, produce `unsupported-react-binding`
|
|
212
|
+
diagnostics and no certain claim. A prop the component never calls is no
|
|
213
|
+
interaction of that component, and declared types, installed or not, decide
|
|
214
|
+
neither result. Components that cannot resolve to a supported source function do not
|
|
184
215
|
establish a callback interaction.
|
|
185
216
|
|
|
186
|
-
|
|
217
|
+
A change to a file the include list names triggers a rescan. Healthy scanners update the architecture while failed scanners keep their saved evidence. See [fresh-checkout validation](../fresh-checkout-validation.md) for
|
|
187
218
|
the executed artifact checks and remaining release gates.
|
|
188
219
|
|
|
189
220
|
## Nested projects
|
|
190
221
|
|
|
191
|
-
Run
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
A candidate also needs a
|
|
195
|
-
files belonging to that package, outside
|
|
196
|
-
inactive fixtures with a `.fixture` suffix
|
|
197
|
-
framework tooling dependencies are skipped. No
|
|
198
|
-
|
|
222
|
+
Run groma.md from the repository root. The scanner finds package declarations
|
|
223
|
+
among its files, including nested apps and libraries. Dependencies, dev
|
|
224
|
+
dependencies, peer dependencies and optional dependencies identify candidates.
|
|
225
|
+
A candidate also needs a `tsconfig.json` among its files in its directory or a
|
|
226
|
+
repository ancestor, and TSX source files belonging to that package, outside
|
|
227
|
+
nested packages. Declaration files and inactive fixtures with a `.fixture` suffix
|
|
228
|
+
do not qualify. Packages with only framework tooling dependencies are skipped. No
|
|
229
|
+
matching project produces no evidence, and neither does a package whose config
|
|
230
|
+
compiles none of its components, such as one holding only excluded tests. Each compiler uses the nearest config of
|
|
231
|
+
its package; imported source in sibling repository libraries keeps its original
|
|
232
|
+
source path. A file belongs to the nearest React package that contains it, so a
|
|
233
|
+
package whose config also compiles a nested package leaves that package's files
|
|
234
|
+
to it, while components and handlers still resolve across both.
|
|
199
235
|
Readiness checks all selected projects. An invalid selected project fails this scanner's observation; other scanners
|
|
200
236
|
can still update the architecture.
|
|
201
|
-
Source and nested package/configuration changes use the shared scanner watch flow.
|