@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 CHANGED
@@ -1,7 +1,7 @@
1
1
  # JavaScript scanner
2
2
 
3
- The JavaScript scanner reads tracked and unignored `.js`, `.mjs`, `.cjs` and
4
- `.jsx` files, covering ECMAScript modules, CommonJS modules and browser scripts.
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.3 compiler, whose parser reads
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
- ## Excluded files
34
+ ## Included and excluded files
35
35
 
36
- Minified output is not authored source, so it is left out of the scan and the
37
- source outline:
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
- - a name that states minified output, such as `jquery-ui.min.js`;
40
- - text whose lines average 500 characters or more, the shape of a bundle a build
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
- The shared Git boundary omits ignored files and dependency or build directories
44
- such as `node_modules`, `vendor`, `dist` and `build`. Core applies the source
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, with every method and the constructor as members.
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` or a CommonJS export; otherwise it is a browser script whose
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 not a URL, such as a `Request`, leave it out |
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 `*` also
213
- matches the path without it. A pattern parameter, such as `:id(\d+)`, and
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. The routing model has six rules:
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. The scanner never sees the files that import this one, which run
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, such as
248
- `app.use('/static', express.static('public'))`, a router the scan cannot
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 files excluded by name and by line length, exact source positions,
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