bc-atlas 0.5.0
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/.bca.example.json +38 -0
- package/LICENSE +21 -0
- package/README.md +328 -0
- package/THIRD_PARTY_NOTICES.md +23 -0
- package/docs/al-ui-test-documentation.md +126 -0
- package/docs/cli-reference.md +242 -0
- package/examples/README.md +32 -0
- package/examples/output/project.d2 +86 -0
- package/examples/output/project.svg +225 -0
- package/examples/output/ui.d2 +47 -0
- package/examples/output/ui.svg +166 -0
- package/examples/output/workflow.d2 +56 -0
- package/examples/output/workflow.svg +194 -0
- package/examples/warehouse-app/Automation.al +24 -0
- package/examples/warehouse-app/Inventory.al +46 -0
- package/examples/warehouse-app/WarehouseUI.al +29 -0
- package/examples/warehouse-app/app.json +8 -0
- package/package.json +59 -0
- package/scripts/generate-examples.js +56 -0
- package/scripts/update-grammar.js +22 -0
- package/src/analyzer.js +571 -0
- package/src/cli.js +357 -0
- package/src/config.js +25 -0
- package/src/d2.js +264 -0
- package/src/docs/al-ui-source.js +484 -0
- package/src/docs/cli.js +45 -0
- package/src/docs/markdown.js +77 -0
- package/src/insights.js +102 -0
- package/src/resolver.js +114 -0
- package/src/svg.js +42 -0
- package/src/views.js +674 -0
- package/src/workflow.js +569 -0
- package/vendor/README.md +12 -0
- package/vendor/tree-sitter-al.wasm +0 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"view": "project",
|
|
3
|
+
"direction": "right",
|
|
4
|
+
"title": "Business Central architecture",
|
|
5
|
+
"groupBy": "role",
|
|
6
|
+
"namespaces": ["Contoso.**"],
|
|
7
|
+
"exclude": ["**/test/**"],
|
|
8
|
+
"moduleDepth": "auto",
|
|
9
|
+
"folderDepth": 1,
|
|
10
|
+
"includeUnresolvedCalls": false,
|
|
11
|
+
"maxEdges": 500,
|
|
12
|
+
"workflow": {
|
|
13
|
+
"entries": ["ProcessDocument"],
|
|
14
|
+
"depth": 8,
|
|
15
|
+
"maxNodes": 100,
|
|
16
|
+
"maxEdges": 250,
|
|
17
|
+
"edgeTypes": ["calls", "events", "writes"],
|
|
18
|
+
"phases": {
|
|
19
|
+
"Validation": ["Validate*"],
|
|
20
|
+
"Processing": ["Process*", "Post*"]
|
|
21
|
+
},
|
|
22
|
+
"stop": ["Finalize*"],
|
|
23
|
+
"collapse": ["*Telemetry*"]
|
|
24
|
+
},
|
|
25
|
+
"details": false,
|
|
26
|
+
"noExternal": false,
|
|
27
|
+
"layout": "elk",
|
|
28
|
+
"theme": 0,
|
|
29
|
+
"sourceUrl": "https://github.com/example/repo/blob/main/{file}#L{line}",
|
|
30
|
+
"forbiddenDependencies": [
|
|
31
|
+
{
|
|
32
|
+
"from": "Contoso.Core:**",
|
|
33
|
+
"to": "Contoso.UI:**",
|
|
34
|
+
"severity": "warning",
|
|
35
|
+
"message": "Core must not depend on UI"
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
}
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 BC Atlas contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
# BC Atlas
|
|
2
|
+
|
|
3
|
+
[](https://github.com/SchulzOli/ALD2Tree/actions/workflows/ci.yml)
|
|
4
|
+
[](./LICENSE)
|
|
5
|
+
[](https://nodejs.org/)
|
|
6
|
+
|
|
7
|
+
Turn a Microsoft Dynamics 365 Business Central AL project into readable
|
|
8
|
+
architecture diagrams, focused dependency views, workflow traces, and
|
|
9
|
+
executable user documentation.
|
|
10
|
+
|
|
11
|
+
BC Atlas (`bca`) is an open-source CLI that parses AL source with
|
|
12
|
+
[`tree-sitter-al`](https://github.com/SShadowS/tree-sitter-al), builds a small
|
|
13
|
+
architecture graph, and writes [`D2`](https://github.com/terrastruct/d2), JSON,
|
|
14
|
+
or SVG. The parser and SVG renderer are WebAssembly-based, so the standard
|
|
15
|
+
workflow needs only Node.js.
|
|
16
|
+
|
|
17
|
+
See the [complete CLI command and option reference](./docs/cli-reference.md)
|
|
18
|
+
for every command, view, selector, option, default, and configuration setting.
|
|
19
|
+
|
|
20
|
+
## What it shows
|
|
21
|
+
|
|
22
|
+
The CLI discovers AL objects and relationships across a project, including:
|
|
23
|
+
|
|
24
|
+
- extension and customization targets;
|
|
25
|
+
- implemented interfaces;
|
|
26
|
+
- dependencies expressed through `Record`, object-reference, and database types;
|
|
27
|
+
- unresolved targets as external nodes;
|
|
28
|
+
- procedure calls, including calls through typed codeunit variables and common
|
|
29
|
+
event-subscriber attributes;
|
|
30
|
+
- app metadata from `app.json`, resolution diagnostics, cycles, hubs, and
|
|
31
|
+
orphan objects.
|
|
32
|
+
|
|
33
|
+
Ten focused views keep larger diagrams useful: `project`, `module`, `object`,
|
|
34
|
+
`data`, `call`, `boundary`, `contracts`, `events`, `ui`, and `workflow`.
|
|
35
|
+
|
|
36
|
+
## Screenshots
|
|
37
|
+
|
|
38
|
+
These images are generated from the checked-in
|
|
39
|
+
[warehouse example](./examples/README.md), using BC Atlas itself.
|
|
40
|
+
|
|
41
|
+
### Complete architecture
|
|
42
|
+
|
|
43
|
+

|
|
44
|
+
|
|
45
|
+
### Workflow and UI views
|
|
46
|
+
|
|
47
|
+
| Workflow trace | UI composition |
|
|
48
|
+
| --- | --- |
|
|
49
|
+
|  |  |
|
|
50
|
+
|
|
51
|
+
The matching editable [D2 and SVG outputs](./examples/output) are committed for
|
|
52
|
+
inspection and can be regenerated with `npm run examples`.
|
|
53
|
+
|
|
54
|
+
## Quick start
|
|
55
|
+
|
|
56
|
+
Requirements: Node.js 20 or later.
|
|
57
|
+
|
|
58
|
+
```sh
|
|
59
|
+
npm install --global bc-atlas
|
|
60
|
+
|
|
61
|
+
bca ./path/to/al-project -o architecture.d2
|
|
62
|
+
bca ./path/to/al-project -o architecture.svg
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
For local development, clone the repository and link the checkout:
|
|
66
|
+
|
|
67
|
+
```sh
|
|
68
|
+
git clone https://github.com/SchulzOli/ALD2Tree.git
|
|
69
|
+
cd ALD2Tree
|
|
70
|
+
npm ci
|
|
71
|
+
npm link
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
No native compiler toolchain or separate D2 installation is needed for `.d2`,
|
|
75
|
+
`.json`, or `.svg` output. PNG and PDF output requires the optional D2 executable.
|
|
76
|
+
You can also run the CLI without linking it:
|
|
77
|
+
|
|
78
|
+
```sh
|
|
79
|
+
node src/cli.js graph ./path/to/al-project --view project -o architecture.svg
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
When `--format` conflicts with the output extension, the format wins:
|
|
83
|
+
`-o calls.d2 -f svg` retains `calls.d2` and writes the rendered image to
|
|
84
|
+
`calls.svg`.
|
|
85
|
+
|
|
86
|
+
## Views and inspection
|
|
87
|
+
|
|
88
|
+
```sh
|
|
89
|
+
# Whole project
|
|
90
|
+
bca graph ./app --view project -o project.d2
|
|
91
|
+
|
|
92
|
+
# Aggregated namespace modules
|
|
93
|
+
bca graph ./app --view module -o modules.d2
|
|
94
|
+
|
|
95
|
+
# Folder-based modules instead of namespaces
|
|
96
|
+
bca graph ./app --view module --group-by folder -o folders.d2
|
|
97
|
+
|
|
98
|
+
# One object plus its neighbors
|
|
99
|
+
bca graph ./app --view object --object codeunit:50100 -o posting.d2
|
|
100
|
+
|
|
101
|
+
# Tables and data-oriented references
|
|
102
|
+
bca graph ./app --view data -o data.d2
|
|
103
|
+
|
|
104
|
+
# Procedures, triggers, and syntactically resolvable calls
|
|
105
|
+
bca graph ./app --view call -o calls.d2
|
|
106
|
+
|
|
107
|
+
# Include unresolved/external calls for investigation
|
|
108
|
+
bca graph ./app --view call --include-unresolved-calls -o all-calls.d2
|
|
109
|
+
|
|
110
|
+
# Dependencies crossing a namespace, folder, app, or object boundary
|
|
111
|
+
bca graph ./app --view boundary \
|
|
112
|
+
--scope namespace:Contoso.Sales -o boundary.svg
|
|
113
|
+
|
|
114
|
+
# Interfaces, direct implementations, and enum-mediated implementations
|
|
115
|
+
bca graph ./app --view contracts -o contracts.svg
|
|
116
|
+
|
|
117
|
+
# Event publishers and subscribers
|
|
118
|
+
bca graph ./app --view events --focus OnPosted -o events.svg
|
|
119
|
+
|
|
120
|
+
# Page composition, source tables, actions, and navigation
|
|
121
|
+
bca graph ./app --view ui --focus "Sales Order" -o ui.svg
|
|
122
|
+
|
|
123
|
+
# Trace a generic execution flow from one or more entry points
|
|
124
|
+
bca graph ./app --view workflow \
|
|
125
|
+
--entry "ProcessDocument" --entry "action:Release" -o workflow.svg
|
|
126
|
+
|
|
127
|
+
# Machine-readable graph, diagnostics, app metadata, and insights
|
|
128
|
+
bca inspect ./app -o model.json
|
|
129
|
+
|
|
130
|
+
# Rebuild after AL/config/app.json changes
|
|
131
|
+
bca watch ./app --view project -o architecture.d2
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Filters are repeatable and work in CI:
|
|
135
|
+
|
|
136
|
+
```sh
|
|
137
|
+
bca ./app \
|
|
138
|
+
--namespace "Contoso.Sales.**" \
|
|
139
|
+
--type table,codeunit \
|
|
140
|
+
--exclude "**/test/**" \
|
|
141
|
+
--max-edges 300 \
|
|
142
|
+
-o sales.d2
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Current views favor readability:
|
|
146
|
+
|
|
147
|
+
- project diagrams use role lanes (`Data`, `UI`, `Services`, `Contracts`,
|
|
148
|
+
`Security`) unless `--group-by namespace|folder|type` is supplied;
|
|
149
|
+
- module diagrams automatically keep the common namespace prefix and expose
|
|
150
|
+
the first meaningful segment; numeric `--module-depth` remains available;
|
|
151
|
+
- call diagrams show resolved calls by default;
|
|
152
|
+
- data diagrams show table relations and detected reads/writes instead of
|
|
153
|
+
every `Record` declaration;
|
|
154
|
+
- object diagrams include field, action, and procedure names for the focused
|
|
155
|
+
object;
|
|
156
|
+
- boundary diagrams show inbound and outbound dependencies for repeatable
|
|
157
|
+
`namespace:`, `folder:`, `app:`, and `object:` scopes;
|
|
158
|
+
- contract diagrams distinguish direct `implements` relationships from enum
|
|
159
|
+
implementation selection;
|
|
160
|
+
- event diagrams connect declared event publishers to subscriber procedures and
|
|
161
|
+
retain unresolved subscriptions;
|
|
162
|
+
- UI diagrams separate pages, actions, source tables, parts, and navigation
|
|
163
|
+
targets;
|
|
164
|
+
- workflow diagrams start at procedures, triggers, actions, or event publishers
|
|
165
|
+
and combine resolved calls, event dispatch, record mutations, cycles, and
|
|
166
|
+
unresolved branches. Direct call order is labelled `definite`; event
|
|
167
|
+
dispatch and collapsed paths are labelled `inferred`;
|
|
168
|
+
- relation colors are consistent across every view: calls are blue, reads are
|
|
169
|
+
dark blue, writes are orange-red, data relations are green, extensions are
|
|
170
|
+
pink, implementations are amber, events are magenta, navigation is green,
|
|
171
|
+
page composition is cyan, and permissions are purple; labels and dash
|
|
172
|
+
patterns remain present so color is never the only signal;
|
|
173
|
+
- repeated edges are aggregated and labelled with their count;
|
|
174
|
+
- permission-set and codeunit `Permissions` declarations are represented as
|
|
175
|
+
`permits [RIMD]` edges.
|
|
176
|
+
|
|
177
|
+
Run `bca --help` for the complete CLI reference.
|
|
178
|
+
|
|
179
|
+
## Publishing releases
|
|
180
|
+
|
|
181
|
+
Publishing is manual through the `Publish npm package` GitHub Actions workflow.
|
|
182
|
+
Before running it, update and commit the version in `package.json` and
|
|
183
|
+
`package-lock.json`, then enter that exact version in the workflow form. The
|
|
184
|
+
workflow rejects version mismatches and versions that already exist on npm,
|
|
185
|
+
runs all checks and tests, inspects the package contents, and publishes with the
|
|
186
|
+
selected npm distribution tag.
|
|
187
|
+
|
|
188
|
+
The initial publication requires a repository Actions secret named
|
|
189
|
+
`NPM_TOKEN`. Use a granular npm access token with read/write package access and
|
|
190
|
+
2FA bypass enabled. Never commit the token to this repository.
|
|
191
|
+
|
|
192
|
+
## Examples
|
|
193
|
+
|
|
194
|
+
The repository includes a self-contained AL project with interfaces, enum
|
|
195
|
+
implementations, pages, extensions, actions, events, data mutations, and
|
|
196
|
+
permissions. Generate its project, workflow, and UI diagrams with:
|
|
197
|
+
|
|
198
|
+
```sh
|
|
199
|
+
npm run examples
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
See [examples/README.md](./examples/README.md) for the expected outputs and
|
|
203
|
+
additional view commands.
|
|
204
|
+
|
|
205
|
+
## Configuration
|
|
206
|
+
|
|
207
|
+
Place `.bca.json` at the input root or pass `--config`. Command-line
|
|
208
|
+
options override configuration. See
|
|
209
|
+
[`.bca.example.json`](./.bca.example.json) for view, layout, filters,
|
|
210
|
+
theme, density, and forbidden-dependency policy examples.
|
|
211
|
+
|
|
212
|
+
Forbidden dependency patterns match
|
|
213
|
+
`Namespace:ObjectType:ObjectName`. Policy violations appear in JSON diagnostics
|
|
214
|
+
and cause `--strict` to fail when configured as warnings or errors.
|
|
215
|
+
|
|
216
|
+
Workflow configuration can select entries, label phases, stop traversal, and
|
|
217
|
+
collapse utility procedures without relying on a particular domain or naming
|
|
218
|
+
scheme:
|
|
219
|
+
|
|
220
|
+
```json
|
|
221
|
+
{
|
|
222
|
+
"view": "workflow",
|
|
223
|
+
"workflow": {
|
|
224
|
+
"entries": ["ProcessDocument", "action:Release"],
|
|
225
|
+
"depth": 8,
|
|
226
|
+
"maxNodes": 100,
|
|
227
|
+
"maxEdges": 250,
|
|
228
|
+
"edgeTypes": ["calls", "events", "writes"],
|
|
229
|
+
"phases": {
|
|
230
|
+
"Validation": ["Validate*", "*.Check*"],
|
|
231
|
+
"Posting": ["Post*", "Finalize*"]
|
|
232
|
+
},
|
|
233
|
+
"stop": ["FinalizeDocument", "event:OnCompleted"],
|
|
234
|
+
"collapse": ["*Telemetry*", "*FeatureFlag*"]
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
Pass it explicitly with
|
|
240
|
+
`bca graph src --view workflow --config bca.workflow.json`.
|
|
241
|
+
Selectors accept exact names, owner-qualified names, `*`/`?` globs, and the
|
|
242
|
+
optional `procedure:`, `trigger:`, `action:`, or `event:` prefix. With no
|
|
243
|
+
entries, the view infers roots from actions, triggers, event publishers, and
|
|
244
|
+
procedures without inbound calls. Reused nodes are emitted once and annotated
|
|
245
|
+
when multiple branches converge. The depth, node, edge, and allowed-edge-type
|
|
246
|
+
limits apply before rendering and are also reported under `workflow` in JSON.
|
|
247
|
+
|
|
248
|
+
Open the generated `.d2` file in the D2 playground or render it locally:
|
|
249
|
+
|
|
250
|
+
```sh
|
|
251
|
+
d2 architecture.d2 architecture.svg
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
## Design
|
|
255
|
+
|
|
256
|
+
The pipeline deliberately separates parsing, semantic extraction, and
|
|
257
|
+
presentation:
|
|
258
|
+
|
|
259
|
+
```text
|
|
260
|
+
*.al files -> tree-sitter AL AST -> neutral graph model -> D2 source -> optional image
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
This keeps the core useful without D2 installed and allows additional diagram
|
|
264
|
+
views without replacing the parser. See [plan.md](./plan.md) for the roadmap
|
|
265
|
+
and design decisions.
|
|
266
|
+
|
|
267
|
+
## Executable user documentation
|
|
268
|
+
|
|
269
|
+
The `docs generate` command turns an AL `[Test]` procedure into goal-oriented
|
|
270
|
+
Markdown directly. It combines `[SCENARIO]`, `[GIVEN]`, `[WHEN]`, and `[THEN]`
|
|
271
|
+
comments with `TestPage` operations to produce concrete page, field, action,
|
|
272
|
+
save, and outcome guidance:
|
|
273
|
+
|
|
274
|
+
```sh
|
|
275
|
+
bca docs generate ../app-test/src/PartnerUITest.Codeunit.al \
|
|
276
|
+
--procedure PartnersList_NewPartner_PersistsGeneralFields
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
No browser test or second implementation of the scenario is generated. See the
|
|
280
|
+
[AL UI-test documentation guide](./docs/al-ui-test-documentation.md) for source
|
|
281
|
+
conventions and CI usage.
|
|
282
|
+
|
|
283
|
+
## Current limits
|
|
284
|
+
|
|
285
|
+
This is an architecture extractor, not the AL compiler or language server.
|
|
286
|
+
Project-local references are resolved by object type, ID, name, namespace, app
|
|
287
|
+
preference, and declared app dependencies. Direct calls, calls through typed
|
|
288
|
+
object variables, and common `EventSubscriber` attributes are resolved where
|
|
289
|
+
possible. Dynamic calls, interface dispatch, and unusual subscriber forms
|
|
290
|
+
remain syntactic/unresolved when the source does not provide enough
|
|
291
|
+
information. Conditional compilation branches are represented as parsed by the
|
|
292
|
+
grammar rather than evaluated against a symbol set.
|
|
293
|
+
|
|
294
|
+
## Development
|
|
295
|
+
|
|
296
|
+
```sh
|
|
297
|
+
npm install
|
|
298
|
+
npm test
|
|
299
|
+
npm run check
|
|
300
|
+
node src/cli.js test/fixtures -o example.d2
|
|
301
|
+
npm pack --dry-run
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
Container usage:
|
|
305
|
+
|
|
306
|
+
```sh
|
|
307
|
+
docker build -t bc-atlas .
|
|
308
|
+
docker run --rm -v "$PWD:/workspace" bc-atlas /workspace -o /workspace/architecture.d2
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
The repository pins the upstream AL grammar artifact in
|
|
312
|
+
`vendor/tree-sitter-al.wasm`. Maintainers can update it with
|
|
313
|
+
`npm run update:grammar -- <tree-sitter-al tag>`.
|
|
314
|
+
|
|
315
|
+
## Contributing and support
|
|
316
|
+
|
|
317
|
+
Contributions are welcome. Start with [CONTRIBUTING.md](./CONTRIBUTING.md), and
|
|
318
|
+
read the [Code of Conduct](./CODE_OF_CONDUCT.md). Use the issue forms for bugs
|
|
319
|
+
and feature requests, [SUPPORT.md](./SUPPORT.md) for usage help, and
|
|
320
|
+
[SECURITY.md](./SECURITY.md) for private vulnerability reporting.
|
|
321
|
+
|
|
322
|
+
Release notes are maintained in [CHANGELOG.md](./CHANGELOG.md).
|
|
323
|
+
|
|
324
|
+
## License
|
|
325
|
+
|
|
326
|
+
[MIT](./LICENSE). Dependencies retain their own licenses: `tree-sitter-al` is
|
|
327
|
+
MIT, `web-tree-sitter` is MIT, and D2 is MPL-2.0. See
|
|
328
|
+
[THIRD_PARTY_NOTICES.md](./THIRD_PARTY_NOTICES.md).
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Third-party notices
|
|
2
|
+
|
|
3
|
+
## tree-sitter-al
|
|
4
|
+
|
|
5
|
+
Copyright Torben Leth and contributors. Licensed under the MIT License.
|
|
6
|
+
Source: <https://github.com/SShadowS/tree-sitter-al>
|
|
7
|
+
|
|
8
|
+
The compiled `vendor/tree-sitter-al.wasm` artifact is redistributed by this
|
|
9
|
+
project.
|
|
10
|
+
|
|
11
|
+
## web-tree-sitter
|
|
12
|
+
|
|
13
|
+
Copyright Tree-sitter contributors. Licensed under the MIT License.
|
|
14
|
+
Source: <https://github.com/tree-sitter/tree-sitter>
|
|
15
|
+
|
|
16
|
+
## D2
|
|
17
|
+
|
|
18
|
+
Copyright Terrastruct, Inc. and contributors. Licensed under the Mozilla Public
|
|
19
|
+
License 2.0. Source: <https://github.com/terrastruct/d2>
|
|
20
|
+
|
|
21
|
+
The official D2 WebAssembly package is redistributed as an npm dependency for
|
|
22
|
+
SVG rendering. The CLI can optionally invoke a separately installed D2
|
|
23
|
+
executable for PNG and PDF output.
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Generate documentation from AL UI tests
|
|
2
|
+
|
|
3
|
+
`bca docs generate` converts one AL `[Test]` procedure directly into
|
|
4
|
+
Markdown. The AL UI test remains the only executable implementation.
|
|
5
|
+
|
|
6
|
+
```text
|
|
7
|
+
AL TestPage test -> BC Atlas -> Markdown
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
No browser automation, generated JavaScript test, AI agent, or YAML scenario is
|
|
11
|
+
involved.
|
|
12
|
+
|
|
13
|
+
## Source convention
|
|
14
|
+
|
|
15
|
+
The selected procedure must have `[Test]` and a `[SCENARIO]` comment. The
|
|
16
|
+
standard test comments provide the documentation:
|
|
17
|
+
|
|
18
|
+
```al
|
|
19
|
+
[Test]
|
|
20
|
+
procedure EDIPartnersList_NewPartner_PersistsGeneralFields()
|
|
21
|
+
var
|
|
22
|
+
EDIPartner: Record EDIPartner;
|
|
23
|
+
EDIPartnersList: TestPage EDIPartners;
|
|
24
|
+
begin
|
|
25
|
+
// [FEATURE] [edi-partner]
|
|
26
|
+
// [SCENARIO] Creating a new partner from the EDI Partners list persists the general fields.
|
|
27
|
+
// [PERMISSIONS] EDI Partner, Edit
|
|
28
|
+
|
|
29
|
+
// [GIVEN] No partner exists yet.
|
|
30
|
+
PartnerFactory.CleanupPartnerData();
|
|
31
|
+
|
|
32
|
+
// [WHEN] A user creates a new partner from the list page.
|
|
33
|
+
EDIPartnersList.OpenNew();
|
|
34
|
+
EDIPartnersList.PartnerCode.SetValue('P-UI-LIST');
|
|
35
|
+
EDIPartnersList.Name.SetValue('UI List Partner');
|
|
36
|
+
EDIPartnersList.Close();
|
|
37
|
+
|
|
38
|
+
// [THEN] The partner persisted with the values entered in the list.
|
|
39
|
+
EDIPartner.Get('P-UI-LIST');
|
|
40
|
+
Assert.AreEqual(
|
|
41
|
+
'UI List Partner',
|
|
42
|
+
EDIPartner.Name,
|
|
43
|
+
'Partner name should have been saved from the list.');
|
|
44
|
+
end;
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
| AL source | Markdown |
|
|
48
|
+
| --- | --- |
|
|
49
|
+
| Procedure name | Stable output filename |
|
|
50
|
+
| `[SCENARIO]` | Title and summary |
|
|
51
|
+
| `[PERMISSIONS]` | Required permission sets under “Before you start” |
|
|
52
|
+
| `[GIVEN]` | User-friendly preparation guidance |
|
|
53
|
+
| `TestPage` calls | Detailed page, field, action, and save steps |
|
|
54
|
+
| `[WHEN]` | Numbered user phase and context for derived TestPage steps |
|
|
55
|
+
| `[THEN]` | Expected results |
|
|
56
|
+
|
|
57
|
+
When `[THEN]` has no text, the `[SCENARIO]` sentence is used as the expected
|
|
58
|
+
result. Explicit `[THEN]` text is preferred.
|
|
59
|
+
|
|
60
|
+
Each `[WHEN]` comment becomes a numbered phase. Supported `TestPage` operations
|
|
61
|
+
following that comment are rendered as detailed steps beneath the phase.
|
|
62
|
+
BC Atlas also follows reachable local procedure calls when a helper contains
|
|
63
|
+
`TestPage` work. Setup-only helpers are not expanded.
|
|
64
|
+
|
|
65
|
+
Within expanded UI helpers, `repeat` blocks are summarized as “for each record”
|
|
66
|
+
instructions and UI operations guarded by `if` are described as conditional.
|
|
67
|
+
Expansion is cycle-safe and limited to eight helper levels.
|
|
68
|
+
|
|
69
|
+
`[PERMISSIONS]` is optional and may be repeated for multiple permission sets.
|
|
70
|
+
`[PERMISSION]` is accepted as an alias. When neither tag is present, no
|
|
71
|
+
permission entry is generated and documentation generation continues normally.
|
|
72
|
+
|
|
73
|
+
## Generate Markdown
|
|
74
|
+
|
|
75
|
+
```powershell
|
|
76
|
+
$uiTest = "C:\Repos\App-Test\src\Partner\UITest\EDIPartnerCardUITest.Codeunit.al"
|
|
77
|
+
|
|
78
|
+
bca docs generate $uiTest `
|
|
79
|
+
--procedure EDIPartnersList_NewPartner_PersistsGeneralFields
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
An AL file containing exactly one `[Test]` procedure does not require
|
|
83
|
+
`--procedure`. A procedure can also be selected with:
|
|
84
|
+
|
|
85
|
+
```text
|
|
86
|
+
path/to/UITest.Codeunit.al#ProcedureName
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The default output directory is `docs/generated`. Override it with:
|
|
90
|
+
|
|
91
|
+
```powershell
|
|
92
|
+
bca docs generate $uiTest `
|
|
93
|
+
--procedure EDIPartnersList_NewPartner_PersistsGeneralFields `
|
|
94
|
+
--output-dir artifacts/docs
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Generated Markdown contains only the AL file name, procedure name, and SHA-256
|
|
98
|
+
fingerprint; it does not expose a local repository path. It is deterministic:
|
|
99
|
+
generating from unchanged AL produces the same file. Literal test values are
|
|
100
|
+
presented as examples so readers know to choose values appropriate for their
|
|
101
|
+
environment.
|
|
102
|
+
|
|
103
|
+
## Verification and CI
|
|
104
|
+
|
|
105
|
+
Run the AL UI test with the normal Business Central test framework. Then
|
|
106
|
+
generate its documentation and check that the repository remains clean:
|
|
107
|
+
|
|
108
|
+
```yaml
|
|
109
|
+
- name: Generate AL UI-test documentation
|
|
110
|
+
run: >
|
|
111
|
+
node src/cli.js docs generate
|
|
112
|
+
../App-Test/src/Partner/UITest/EDIPartnerCardUITest.Codeunit.al
|
|
113
|
+
--procedure EDIPartnersList_NewPartner_PersistsGeneralFields
|
|
114
|
+
|
|
115
|
+
- name: Verify generated documentation is current
|
|
116
|
+
run: git diff --exit-code -- docs/generated
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The test repository should be checked out at the revision corresponding to the
|
|
120
|
+
application being documented.
|
|
121
|
+
|
|
122
|
+
## Screenshots
|
|
123
|
+
|
|
124
|
+
Screenshot generation is intentionally not part of the current workflow. A
|
|
125
|
+
future, opt-in capture feature is recorded in [todo.md](../todo.md). It must
|
|
126
|
+
consume the AL-derived contract without becoming a second authoritative test.
|