@groma/scanner-vue 0.1.2 → 0.1.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 +155 -8
- package/dist/index.js +1675 -39
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# Vue scanner
|
|
2
2
|
|
|
3
3
|
The Vue scanner adds single-file component (SFC) event bindings to Groma's
|
|
4
|
-
TypeScript scanner evidence.
|
|
5
|
-
|
|
6
|
-
it does not
|
|
4
|
+
TypeScript scanner evidence. Its bundled compiler tools read local source
|
|
5
|
+
without project dependencies. The scanner reads each selected project's
|
|
6
|
+
`tsconfig.json`; it does not execute application code.
|
|
7
7
|
|
|
8
8
|
```sh
|
|
9
9
|
bun install --frozen-lockfile --ignore-scripts
|
|
@@ -32,6 +32,26 @@ supplied-callback evidence contract; it has no separate name or type resolver.
|
|
|
32
32
|
|
|
33
33
|
## Supported interaction
|
|
34
34
|
|
|
35
|
+
### External source blocks
|
|
36
|
+
|
|
37
|
+
A `.vue` file can explicitly name local external script, template, and style
|
|
38
|
+
files with `src="./file"` or `src="../file"`, as described in the
|
|
39
|
+
[Vue SFC specification](https://vuejs.org/api/sfc-spec#src-imports).
|
|
40
|
+
The scanner reports those direct companions as one source unit. Core assigns
|
|
41
|
+
one component when ownership is unambiguous and preserves curated membership
|
|
42
|
+
on repeats. Code details expose the `.vue` file and every companion.
|
|
43
|
+
Imports from the script, global styles, transitive stylesheet imports, and
|
|
44
|
+
similarly named neighboring files do not extend that association.
|
|
45
|
+
|
|
46
|
+
Inline blocks create no extra files. External scripts cannot be combined with
|
|
47
|
+
`script setup`; Vue's [script setup restrictions](https://vuejs.org/api/sfc-script-setup#restrictions)
|
|
48
|
+
still apply. External block association does not add Options API or external
|
|
49
|
+
template event inference; the inline interaction rule below remains unchanged.
|
|
50
|
+
Edits to JavaScript, TypeScript, HTML, CSS, SCSS, Sass, Less, and Stylus companions
|
|
51
|
+
trigger the existing shared scanner refresh.
|
|
52
|
+
|
|
53
|
+
### Inline event bindings
|
|
54
|
+
|
|
35
55
|
The qualified example is Vue REPL's CodeMirror `change` event bound to the
|
|
36
56
|
parent's `onChange` function. A static imported SFC must use a typed
|
|
37
57
|
`defineEmits` declaration assigned to a constant. A call to that same symbol
|
|
@@ -51,7 +71,8 @@ Options API events, runtime `defineEmits` arrays, dynamic components, dynamic
|
|
|
51
71
|
event names, handler expressions or modifiers, state stores, routing, server
|
|
52
72
|
frameworks or arbitrary event mutation. Compiler syntax/template errors fail
|
|
53
73
|
the scan and preserve the previous complete map. Readiness errors explain
|
|
54
|
-
|
|
74
|
+
invalid configuration or source syntax. Typed event names are read from the
|
|
75
|
+
local `defineEmits` type literal; missing Vue types do not erase that evidence.
|
|
55
76
|
|
|
56
77
|
Vue contributes `vue` Code provenance for configured source files. Shared core
|
|
57
78
|
keeps one physical-file owner, interprets complementary and conflicting
|
|
@@ -63,15 +84,141 @@ is source evidence; it does not automatically define a C4 responsibility or
|
|
|
63
84
|
add a containment level. Groma's existing ownership and relationship model
|
|
64
85
|
owns that interpretation. No new architecture metadata is added.
|
|
65
86
|
|
|
66
|
-
See [validation](validation.md) for the pinned project and executed release
|
|
87
|
+
See [fresh-checkout validation](../fresh-checkout-validation.md) for the pinned project and executed release
|
|
67
88
|
checks. This prototype package name does not imply public publication.
|
|
68
89
|
|
|
90
|
+
## Source outline
|
|
91
|
+
|
|
92
|
+
The scanner outlines every script it owns in a component's Code with the
|
|
93
|
+
TypeScript rules of the [source outline contract](../creating-a-plugin.md#source-outline):
|
|
94
|
+
top-level functions and types (classes, interfaces, enums), including namespace
|
|
95
|
+
contents, and each type's constructors and methods. Every declaration has its
|
|
96
|
+
line and visibility, and `entry` marks the names the Code links give. Templates
|
|
97
|
+
and stylesheets have no outline.
|
|
98
|
+
|
|
99
|
+
A single-file component is read with the Vue single-file component parser: the
|
|
100
|
+
`<script>` and `<script setup>` blocks are outlined in source order, each in the
|
|
101
|
+
dialect its `lang` attribute names, and every declaration reports the line it
|
|
102
|
+
occupies in the `.vue` file. A `<script setup>` block exports nothing, because
|
|
103
|
+
its top-level bindings are the component's own API for its template, so its
|
|
104
|
+
top-level declarations are private; members keep their TypeScript visibility.
|
|
105
|
+
The package's own TypeScript parses each block alone, without `tsconfig.json`,
|
|
106
|
+
dependencies or compilation.
|
|
107
|
+
|
|
108
|
+
Core outlines each file once. For a script that the TypeScript scanner also
|
|
109
|
+
owns, the scanner with the lowest id among the file's Code links outlines it,
|
|
110
|
+
here TypeScript, with the symbols of all those links.
|
|
111
|
+
|
|
112
|
+
## HTTP endpoints and requests
|
|
113
|
+
|
|
114
|
+
The scanner reports [HTTP facts](../evidence.md#http-endpoints-and-requests) for
|
|
115
|
+
the clients it recognizes in the files it reads, single-file component scripts
|
|
116
|
+
included, and for the endpoints a Nuxt project declares by file location. A fact
|
|
117
|
+
from a `.vue` file names an operation in that file, at the line the call occupies
|
|
118
|
+
there.
|
|
119
|
+
|
|
120
|
+
| Construct | Reported |
|
|
121
|
+
| --- | --- |
|
|
122
|
+
| `fetch(url, options)`, `$fetch(url, options)`, `useFetch(url, options)` | Request; a literal `method` gives the method, no options means `GET`, and options the scanner cannot read leave it out |
|
|
123
|
+
| `$fetch` and `useFetch` with a `baseURL` option | Request whose path follows that base |
|
|
124
|
+
| `axios.get`, `.post`, `.put`, `.patch`, `.delete`, `.head`, `.options` | Request with that method |
|
|
125
|
+
| `axios(config)`, `axios.request(config)` | Request from the config's `url`; its `method`, else the client's, else `GET` |
|
|
126
|
+
| `axios.create(config)` instances | Request whose path follows the config's `baseURL`, and whose method defaults to the config's |
|
|
127
|
+
| `server/api/**` | Endpoint at `/api/...`, with the method its file name states |
|
|
128
|
+
| `server/routes/**` | Endpoint at the path after `server/routes`, with the method its file name states |
|
|
129
|
+
|
|
130
|
+
`fetch` counts when it is the runtime's or the default export of `node-fetch`,
|
|
131
|
+
as on the React page. `$fetch` and `useFetch` must resolve to a declaration
|
|
132
|
+
outside the project source, such as an installed package's types, so a project's
|
|
133
|
+
own `useFetch` composable, whose body decides the URL, is never read as Nuxt's;
|
|
134
|
+
a project scanned without its dependencies installed therefore reports no
|
|
135
|
+
`$fetch` or `useFetch` request. They read their `baseURL` option as axios reads
|
|
136
|
+
a request's own, except that, as ofetch does, they keep a URL whose text already
|
|
137
|
+
starts with a literal base followed by `/`, `?` or its end; where that boundary
|
|
138
|
+
falls on a computed part, the path starts unknown. Everything else, from the
|
|
139
|
+
axios clients and their `defaults` to the options, the `fetch` inputs and the
|
|
140
|
+
bases, follows the rules of the [React
|
|
141
|
+
scanner](../react/index.md#http-endpoints-and-requests).
|
|
142
|
+
|
|
143
|
+
The endpoints need the project to declare `nuxt`: another server that happens to
|
|
144
|
+
live in `server/` serves paths of its own, which these locations would misstate.
|
|
145
|
+
|
|
146
|
+
The [producer decisions](../evidence.md#producer-checklist) for this ecosystem:
|
|
147
|
+
|
|
148
|
+
1. **Prefixes.** A server route under `server/api` serves below `/api`, which its
|
|
149
|
+
endpoint path states; one under `server/routes` serves from the root. On the
|
|
150
|
+
client side, only a `baseURL`, as the options and axios clients above state it,
|
|
151
|
+
precedes a path.
|
|
152
|
+
2. **Endpoints.** Only the server route files above, and only in a project that
|
|
153
|
+
declares `nuxt`. `server/middleware/**`, `server/plugins/**`, a component, and
|
|
154
|
+
a page answer no request of their own. Nuxt serves every route file, so each
|
|
155
|
+
reports its endpoint, whatever its default export is.
|
|
156
|
+
3. **Dynamic or unknown.** `` `/talks/${id}` `` fills one whole segment, so it is
|
|
157
|
+
dynamic. `` `/talks/${id}-latest` ``, a path built from a parameter, and an
|
|
158
|
+
unresolvable value are unknown. The query and fragment are dropped, computed or
|
|
159
|
+
not. A method the scanner cannot read leaves the fact without one, rather than
|
|
160
|
+
claiming `GET`.
|
|
161
|
+
4. **Local helpers.** Not supported: the URL is read at the client call, so a
|
|
162
|
+
helper that forwards a path parameter reports unknown text, and its callers
|
|
163
|
+
report nothing. Author those rows.
|
|
164
|
+
5. **Bases.** The [React
|
|
165
|
+
scanner's](../react/index.md#http-endpoints-and-requests) decision 5 holds
|
|
166
|
+
unchanged.
|
|
167
|
+
6. **File-location routes.** A route file's path after `server/` is its served
|
|
168
|
+
path, read as Nitro names its routes: a route group directory such as
|
|
169
|
+
`(admin)` serves no segment, an environment suffix such as `.prod` and then a
|
|
170
|
+
`.get`, `.post`, `.put`, `.patch`, `.delete`, `.head`, `.options`, `.connect`
|
|
171
|
+
or `.trace` method suffix leave the path, a final `index` serves its
|
|
172
|
+
directory, and placeholders read as decision 7 describes. A file without a
|
|
173
|
+
method suffix answers every method. `.js`, `.mjs`, `.cjs`, `.ts`, `.mts`,
|
|
174
|
+
`.cts`, `.jsx` and `.tsx` route files count. The endpoint names the function
|
|
175
|
+
the default export designates: a default-exported function, or a function the
|
|
176
|
+
file declares, as a function or a variable holding one, that the default
|
|
177
|
+
export names or passes to a wrapper such as `defineEventHandler`. When it
|
|
178
|
+
designates no such function, the endpoint names the file's module operation.
|
|
179
|
+
A request in a file's own top-level code, which is what `<script setup>` runs
|
|
180
|
+
on setup, names that file's module operation, so the row starts at the
|
|
181
|
+
component.
|
|
182
|
+
7. **Constrained segments.** Nitro constrains no segment, and segments follow
|
|
183
|
+
the names it registers. A segment that starts with a placeholder, such as
|
|
184
|
+
`[id]` or `[id]-latest`, is a parameter that accepts any text, named `*` when
|
|
185
|
+
no name can spell it. Text before a placeholder makes the whole segment
|
|
186
|
+
literal, so `hello-[name]` serves only `/hello-:name`. `[...]` and
|
|
187
|
+
`[...slug]`, whose name is word characters, are catch-alls, while
|
|
188
|
+
`[...file-path]` is a parameter. A segment the scanner cannot state, such as
|
|
189
|
+
a catch-all before the last segment, becomes a constrained optional catch-all
|
|
190
|
+
in place of itself and the rest of the path.
|
|
191
|
+
8. **Registration order.** None: Nuxt prefers the most specific route, whatever
|
|
192
|
+
order its files are in.
|
|
193
|
+
|
|
194
|
+
## Compared operations
|
|
195
|
+
|
|
196
|
+
`groma lint` and scan findings compare the functions in the `<script>` and
|
|
197
|
+
`<script setup>` blocks of a single-file component under the
|
|
198
|
+
[shared rule](../../architecture-findings.md#compared-operations). The Vue,
|
|
199
|
+
JavaScript and TypeScript scanners share one rule and one tokenizer, so the
|
|
200
|
+
operations the [TypeScript scanner](../typescript/index.md#compared-operations)
|
|
201
|
+
compares, those it does not compare yet, and the tokens it keeps apply here too,
|
|
202
|
+
and one body compares equal in a component script and in a module.
|
|
203
|
+
|
|
204
|
+
In a component, the source range is in the `.vue` file's own lines. The
|
|
205
|
+
functions a `<script setup>` block exposes to its template are compared.
|
|
206
|
+
`setup()` on the argument of `defineComponent({ ... })` is an anonymous callback,
|
|
207
|
+
while the methods under its `methods` property are compared. Top-level statements
|
|
208
|
+
of a block are initializer code, and template expressions are not operations.
|
|
209
|
+
Scripts the component keeps in a separate file are TypeScript modules, which the
|
|
210
|
+
TypeScript scanner compares.
|
|
211
|
+
|
|
69
212
|
## Nested projects
|
|
70
213
|
|
|
71
214
|
Run Groma from the repository root. The scanner finds package declarations in
|
|
72
215
|
tracked and unignored files, including nested apps and libraries. Dependencies,
|
|
73
|
-
dev dependencies, peer dependencies and optional dependencies identify
|
|
74
|
-
|
|
216
|
+
dev dependencies, peer dependencies and optional dependencies identify candidates.
|
|
217
|
+
A candidate also needs a tracked or unignored `tsconfig.json` and Vue source
|
|
218
|
+
files belonging to that package, outside nested packages. Declaration files and
|
|
219
|
+
inactive fixtures with a `.fixture` suffix do not qualify. Packages with only
|
|
220
|
+
framework tooling dependencies are skipped. No matching project produces no evidence. Each compiler uses that project's configuration and local source;
|
|
75
221
|
imported source in sibling repository libraries keeps its original source path.
|
|
76
|
-
Readiness checks all selected projects.
|
|
222
|
+
Readiness checks all selected projects. An invalid selected project fails this scanner's observation; other scanners
|
|
223
|
+
can still update the architecture.
|
|
77
224
|
Source and nested package/configuration changes use the shared scanner watch flow.
|