@groma/scanner-javascript 0.1.1 → 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 +52 -37
- package/dist/index.js +529 -190
- package/package.json +23 -3
- package/validation.md +2 -8
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# JavaScript scanner
|
|
2
2
|
|
|
3
|
-
The JavaScript scanner reads
|
|
4
|
-
|
|
3
|
+
The JavaScript scanner reads the `.js`, `.mjs`, `.cjs` and `.jsx` files
|
|
4
|
+
groma.md hands it, covering ECMAScript modules, CommonJS modules and browser scripts.
|
|
5
5
|
It does not require Node.js, installed packages, a bundler, a project build or a
|
|
6
6
|
`tsconfig.json`. Discovery matches JavaScript source directly, even without a
|
|
7
7
|
package manifest.
|
|
@@ -17,7 +17,7 @@ groma scanner add /absolute/path/to/groma/plugins/scanners/javascript/dist/packa
|
|
|
17
17
|
groma scan
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
The package bundles the TypeScript 6.0
|
|
20
|
+
The package bundles the TypeScript 6.0 compiler, whose parser reads
|
|
21
21
|
JavaScript, including JSX in `.js` and `.jsx` files, and includes its license
|
|
22
22
|
notices. Every file is parsed on its own, so no project configuration, module
|
|
23
23
|
resolution or other file changes what a file reports. The compiler's declaration
|
|
@@ -31,28 +31,21 @@ TypeScript-style type annotations, as in many Flow-typed files, still parse, and
|
|
|
31
31
|
octal literals and escapes that only strict mode rejects, such as `0755`, are not
|
|
32
32
|
parse errors.
|
|
33
33
|
|
|
34
|
-
##
|
|
34
|
+
## Included and excluded files
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
source
|
|
36
|
+
The package declares the default
|
|
37
|
+
[include and exclude lists](../index.md#selecting-source-files). It includes
|
|
38
|
+
the four source extensions and the `package.json`, HTML, `project.json` and
|
|
39
|
+
`nx.json` files the entry reader reads. It excludes names that state minified
|
|
40
|
+
output, such as `jquery-ui.min.js`, and `node_modules`, `dist`, `build` and
|
|
41
|
+
`coverage` folders. The scan and the readiness check read only the files the
|
|
42
|
+
lists select.
|
|
38
43
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
produced under an ordinary name such as `vendor.js`.
|
|
44
|
+
A bundle under an ordinary name, such as `vendor.js`, is read like any other
|
|
45
|
+
source; a project that keeps it out adds a pattern to `scanners.json`.
|
|
42
46
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
exclusions configured in `scanners.json`.
|
|
46
|
-
|
|
47
|
-
Test sources are treated like any other JavaScript source, as in the PHP and
|
|
48
|
-
Swift scanners: a project excludes them explicitly in `scanners.json`. The
|
|
49
|
-
TypeScript scanner instead omits `test` directories and `.test` and `.spec` names
|
|
50
|
-
by default.
|
|
51
|
-
|
|
52
|
-
Discovery counts any `.js`, `.mjs`, `.cjs` or `.jsx` name, minified files
|
|
53
|
-
included, because it reads file names without opening them. A repository whose
|
|
54
|
-
only JavaScript is minified can therefore be recommended this scanner, and
|
|
55
|
-
readiness then reports that no authored JavaScript source was found.
|
|
47
|
+
Test sources are treated like any other JavaScript source: the defaults name
|
|
48
|
+
none, so a project that keeps them out adds a pattern to `scanners.json`.
|
|
56
49
|
|
|
57
50
|
TypeScript sources belong to the [TypeScript scanner](../typescript/index.md)
|
|
58
51
|
and single-file components to the [Vue scanner](../vue/index.md). This scanner
|
|
@@ -66,6 +59,8 @@ and methods and constructors with a body produce operation evidence with UTF-16
|
|
|
66
59
|
source offsets.
|
|
67
60
|
Code outside every function is the module's own work, so a browser script's
|
|
68
61
|
top-level calls keep an operation to belong to, without inventing a function.
|
|
62
|
+
Calls inside accessors belong to an anonymous accessor operation; accessors are
|
|
63
|
+
not compared for duplicate logic.
|
|
69
64
|
|
|
70
65
|
Calls remain unresolved. One parsed file proves no call target: an imported name,
|
|
71
66
|
a `require` result and a method on a value are all decided elsewhere, so core
|
|
@@ -77,6 +72,13 @@ JavaScript file belongs to one C4 runtime boundary. Core owns architecture
|
|
|
77
72
|
identity and curation, and repeated scans preserve one physical owner and the
|
|
78
73
|
authored architecture. JavaScript edits and new files refresh through the shared
|
|
79
74
|
scanner watcher.
|
|
75
|
+
Each literal local `node`, `bun`, `tsx` or `ts-node` command in an unquoted
|
|
76
|
+
`&&`-chained package script can supply an execution entry. Environment
|
|
77
|
+
assignments or `cross-env` may come before the runtime, and runtime options and
|
|
78
|
+
a `run` or `watch` subcommand before the script; the first remaining word must
|
|
79
|
+
name the script, so a preloaded module or `bun build` supplies none. An HTML
|
|
80
|
+
page's script supplies one too, named after the page, or after its folder for
|
|
81
|
+
an `index.html`.
|
|
80
82
|
|
|
81
83
|
## Source outline
|
|
82
84
|
|
|
@@ -86,7 +88,8 @@ parses the file alone and lists what it declares at the top level:
|
|
|
86
88
|
|
|
87
89
|
- functions, and arrow functions or function expressions assigned directly to a
|
|
88
90
|
`const`, `let` or `var` name;
|
|
89
|
-
- classes,
|
|
91
|
+
- classes, including a named class expression assigned to `module.exports`,
|
|
92
|
+
with every method and the constructor as members.
|
|
90
93
|
|
|
91
94
|
Fields, accessors, and declarations inside a function, method or block are not
|
|
92
95
|
listed. A declaration is marked as an entry when the component's Code names it,
|
|
@@ -96,12 +99,12 @@ Visibility follows how the file publishes a name:
|
|
|
96
99
|
|
|
97
100
|
| Value | JavaScript |
|
|
98
101
|
| --- | --- |
|
|
99
|
-
| `public` | An `export`, a name in the file's own `export { name }` list or `export default name`, a name a CommonJS `module.exports` or `exports.name` assignment publishes, and every top-level declaration of a file that states no module boundary, because those names are globals |
|
|
102
|
+
| `public` | An `export`, a name in the file's own `export { name }` list or `export default name`, a name a CommonJS `module.exports` or `exports.name` assignment publishes, including through a chained assignment, and every top-level declaration of a file that states no module boundary, because those names are globals |
|
|
100
103
|
| `private` | Every other top-level declaration, and a `#name` member |
|
|
101
104
|
|
|
102
105
|
A `.mjs` or `.cjs` file is a module whatever it contains, so its unpublished
|
|
103
106
|
declarations stay private. A `.js` file is a module when it states an `import`,
|
|
104
|
-
an `export
|
|
107
|
+
an `export`, a CommonJS export or a `require` call; otherwise it is a browser script whose
|
|
105
108
|
declarations any other script on the page may use. Members are `public` unless
|
|
106
109
|
their name is private.
|
|
107
110
|
|
|
@@ -125,8 +128,8 @@ that file states it and a value from another file is one the scanner cannot see.
|
|
|
125
128
|
|
|
126
129
|
| Construct | Reported |
|
|
127
130
|
| --- | --- |
|
|
128
|
-
| `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, or an input that is
|
|
129
|
-
| `axios.get`, `.post`, `.put`, `.patch`, `.delete`, `.head`, `.options` | Request with that method |
|
|
131
|
+
| `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, or an input that is neither URL text nor typed as a primitive such as a string, for example a `Request`, leave it out |
|
|
132
|
+
| `axios.get`, `.post`, `.put`, `.patch`, `.delete`, `.head`, `.options`, `.postForm`, `.putForm`, `.patchForm` | Request with that method; form helpers use their matching HTTP method |
|
|
130
133
|
| `axios(config)`, `axios.request(config)` | Request from the config's `url`; its `method`, else the client's, else `GET` |
|
|
131
134
|
| `axios.create(config)` instances | Request whose path follows the config's `baseURL`, and whose method defaults to the config's |
|
|
132
135
|
| `$.get`, `$.post`, `$.getJSON`, `$.getScript` | Request with that helper's method |
|
|
@@ -209,21 +212,29 @@ The [producer decisions](../evidence.md#producer-checklist) for this ecosystem:
|
|
|
209
212
|
7. **Constrained segments.** Route patterns are literal text, `:name`, `:name?`,
|
|
210
213
|
Express 5's trailing optional group `{/:name}`, and a trailing `*`, `*name`,
|
|
211
214
|
`(.*)` or `:name(.*)` catch-all, which needs at least one segment because a
|
|
212
|
-
request path cannot tell `/files` from `/files/`; Hono's trailing `*`
|
|
213
|
-
|
|
215
|
+
request path cannot tell `/files` from `/files/`; Hono's trailing `*` and
|
|
216
|
+
Express 5's trailing `{/*name}` or `/{*name}` also match the path without it.
|
|
217
|
+
A pattern parameter, such as `:id(\d+)`, and
|
|
214
218
|
text mixed with a placeholder, such as `talk-:id`, are constrained
|
|
215
219
|
parameters. A pattern that may span segments or that the scanner cannot
|
|
216
220
|
state, such as a regular expression, another optional group or a catch-all
|
|
217
221
|
that is not last, becomes a constrained optional catch-all in place of itself
|
|
218
|
-
and the rest of the route, so no route is omitted
|
|
222
|
+
and the rest of the route, so no route is omitted; the whole segments before
|
|
223
|
+
it stand.
|
|
219
224
|
8. **Registration order.** Express, Hono and Koa routers take the first
|
|
220
225
|
registered match, so their endpoints carry `order`: the application, named by
|
|
221
226
|
the file that creates it and the variable that holds it, such as
|
|
222
|
-
`server/app.js#app`, and a position.
|
|
227
|
+
`server/app.js#app`, and a position. Same-named local applications in one
|
|
228
|
+
file also carry their declaration position to keep their order separate.
|
|
229
|
+
The routing model has six rules:
|
|
223
230
|
1. A registrar's entries are its registrations and the references that hand
|
|
224
231
|
it off to other code, such as `registerRoutes(app)`. Serving it with
|
|
225
232
|
`listen`, Node's `createServer(app)` or an imported `serve(app)` registers
|
|
226
|
-
nothing
|
|
233
|
+
nothing, and neither does a route method called with fewer than two
|
|
234
|
+
arguments, such as the setting read `app.get('env')`. A `use` that only
|
|
235
|
+
adds middleware, which takes no place (rule 5), is no entry either, so
|
|
236
|
+
`if (app.get('env') === 'development') app.use(logger)` leaves the order
|
|
237
|
+
of the other entries known. The scanner never sees the files that import this one, which run
|
|
227
238
|
after all of it and may add any route, so an export, `export default app`,
|
|
228
239
|
`export const app` or an assignment to `module.exports` or `exports`,
|
|
229
240
|
hands the registrar off at the end of its order; a circular require is the
|
|
@@ -244,9 +255,9 @@ The [producer decisions](../evidence.md#producer-checklist) for this ecosystem:
|
|
|
244
255
|
prefix followed by a constrained optional catch-all, with method `*`
|
|
245
256
|
unless the call states one, named by the registering operation: a route
|
|
246
257
|
with a computed path, a mount under a computed prefix, a path mounted to
|
|
247
|
-
something other than a recognized router
|
|
248
|
-
`app.use('/static', express.static('public'))`, a router the
|
|
249
|
-
follow, mounted with or without a path, such as
|
|
258
|
+
something other than a recognized router or a function the scan sees,
|
|
259
|
+
such as `app.use('/static', express.static('public'))`, a router the
|
|
260
|
+
scan cannot follow, mounted with or without a path, such as
|
|
250
261
|
`app.use(require('./routes'))`, a Koa router's `routes()` from another
|
|
251
262
|
file, or a function imported from one, which the scanner cannot see, a
|
|
252
263
|
route builder such as `app.route('/reports')`, Hono's `on`, `mount` and
|
|
@@ -255,7 +266,11 @@ The [producer decisions](../evidence.md#producer-checklist) for this ecosystem:
|
|
|
255
266
|
registrar's root.
|
|
256
267
|
5. Middleware takes no place: a package's handler, such as `express.json()`,
|
|
257
268
|
and any handler before or beside a recognized router in one call, as in
|
|
258
|
-
`app.use(requireAuth, api)`, which then states no path.
|
|
269
|
+
`app.use(requireAuth, api)`, which then states no path. Hono's `use`
|
|
270
|
+
never mounts a router, so it takes no place with or without a path,
|
|
271
|
+
whatever its handlers. Under a path, an Express or Koa `use` takes none
|
|
272
|
+
when the scan sees that every handler is a function, as in
|
|
273
|
+
`app.use('/api', requireAuth)`.
|
|
259
274
|
6. Fastify and Bun.serve prefer the most specific route and carry no order; a
|
|
260
275
|
Fastify plugin, whose routes the scan does not read, blocks its prefix
|
|
261
276
|
without one.
|
|
@@ -263,7 +278,7 @@ The [producer decisions](../evidence.md#producer-checklist) for this ecosystem:
|
|
|
263
278
|
## Validation
|
|
264
279
|
|
|
265
280
|
Independent fixtures cover ECMAScript modules, CommonJS, JSX, browser scripts,
|
|
266
|
-
minified
|
|
281
|
+
minified names excluded by the default exclusions, exact source positions,
|
|
267
282
|
unresolved calls, the source outline with its visibility rules, one body that
|
|
268
283
|
tokenizes identically in JavaScript and in TypeScript, identical and
|
|
269
284
|
near-duplicate bodies found by `groma lint`, a file that does not parse next to
|