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.
@@ -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
+ [![CI](https://github.com/SchulzOli/ALD2Tree/actions/workflows/ci.yml/badge.svg)](https://github.com/SchulzOli/ALD2Tree/actions/workflows/ci.yml)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](./LICENSE)
5
+ [![Node.js 20+](https://img.shields.io/badge/Node.js-20%2B-339933?logo=node.js&logoColor=white)](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
+ ![BC Atlas project view showing UI, service, data, contract, and security relationships](./docs/generated/images/project-view.png)
44
+
45
+ ### Workflow and UI views
46
+
47
+ | Workflow trace | UI composition |
48
+ | --- | --- |
49
+ | ![Workflow trace showing calls, an event dispatch, and a table write](./docs/generated/images/workflow-view.png) | ![UI view showing a page extension, page action, and source table](./docs/generated/images/ui-view.png) |
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.