ultravisor-beacon-capability 1.0.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.
Files changed (38) hide show
  1. package/README.md +106 -0
  2. package/docs/.nojekyll +0 -0
  3. package/docs/README.md +103 -0
  4. package/docs/_brand.json +18 -0
  5. package/docs/_cover.md +13 -0
  6. package/docs/_sidebar.md +31 -0
  7. package/docs/_topbar.md +5 -0
  8. package/docs/_version.json +7 -0
  9. package/docs/api/README.md +44 -0
  10. package/docs/api/action-convention.md +148 -0
  11. package/docs/api/add-action.md +68 -0
  12. package/docs/api/beacon-capability.md +89 -0
  13. package/docs/api/build-action-map.md +88 -0
  14. package/docs/api/connect.md +81 -0
  15. package/docs/api/disconnect.md +50 -0
  16. package/docs/api/is-connected.md +33 -0
  17. package/docs/api/lifecycle-hooks.md +115 -0
  18. package/docs/architecture.md +237 -0
  19. package/docs/css/docuserve.css +327 -0
  20. package/docs/examples/README.md +58 -0
  21. package/docs/examples/certificate-expiry-monitor.md +212 -0
  22. package/docs/examples/docker-container-management.md +265 -0
  23. package/docs/examples/log-archive-and-upload.md +214 -0
  24. package/docs/examples/log-file-cleanup.md +199 -0
  25. package/docs/examples/mysql-maintenance.md +253 -0
  26. package/docs/examples/postgresql-aggregation.md +247 -0
  27. package/docs/examples/rest-api-health-check.md +213 -0
  28. package/docs/examples/rest-endpoint-sync.md +240 -0
  29. package/docs/examples/server-metrics-collection.md +199 -0
  30. package/docs/examples/shell-commands.md +176 -0
  31. package/docs/index.html +39 -0
  32. package/docs/quickstart.md +199 -0
  33. package/docs/retold-catalog.json +85 -0
  34. package/docs/retold-keyword-index.json +10642 -0
  35. package/package.json +33 -0
  36. package/source/Ultravisor-Beacon-Capability-ActionMap.cjs +132 -0
  37. package/source/Ultravisor-Beacon-Capability.cjs +276 -0
  38. package/test/Ultravisor-Beacon-Capability_tests.js +744 -0
@@ -0,0 +1,88 @@
1
+ # buildActionMap
2
+
3
+ Discovers action methods on a capability instance by walking its prototype chain. This is an internal function used by `UltravisorBeaconCapability.connect()`, but it is exported for testing and advanced use cases.
4
+
5
+ ## Import
6
+
7
+ ```javascript
8
+ const { buildActionMap } = require('ultravisor-beacon-capability/source/Ultravisor-Beacon-Capability-ActionMap.cjs');
9
+ ```
10
+
11
+ ## Signature
12
+
13
+ ```javascript
14
+ buildActionMap(pInstance) => object
15
+ ```
16
+
17
+ ### Parameters
18
+
19
+ | Parameter | Type | Description |
20
+ |-----------|------|-------------|
21
+ | `pInstance` | `object` | A capability instance to inspect |
22
+
23
+ ### Returns
24
+
25
+ An object mapping action names to action definitions:
26
+
27
+ ```javascript
28
+ {
29
+ 'ActionName':
30
+ {
31
+ Description: 'Human-readable description',
32
+ SettingsSchema: [{ Name: 'Param', DataType: 'String', Required: true }],
33
+ Handler: function (pWorkItem, pContext, fCallback, fReportProgress) { ... }
34
+ }
35
+ }
36
+ ```
37
+
38
+ The `Handler` function uses the raw `ultravisor-beacon` signature (not the convention signature). It wraps the bound action method with Settings pre-extraction.
39
+
40
+ ## Example
41
+
42
+ ```javascript
43
+ const libFable = require('fable');
44
+ const libBeaconCapability = require('ultravisor-beacon-capability');
45
+ const { buildActionMap } = require('ultravisor-beacon-capability/source/Ultravisor-Beacon-Capability-ActionMap.cjs');
46
+
47
+ class MyCapability extends libBeaconCapability
48
+ {
49
+ constructor(pFable, pOptions, pServiceHash)
50
+ {
51
+ super(pFable, pOptions, pServiceHash);
52
+ this.capabilityName = 'Test';
53
+ }
54
+
55
+ get actionPing_Description() { return 'Respond with pong'; }
56
+ actionPing(pSettings, pWorkItem, fCallback)
57
+ {
58
+ return fCallback(null, { Outputs: { Response: 'pong' } });
59
+ }
60
+ }
61
+
62
+ let tmpFable = new libFable({});
63
+ let tmpCap = new MyCapability(tmpFable, {}, 'test');
64
+ let tmpMap = buildActionMap(tmpCap);
65
+
66
+ console.log(Object.keys(tmpMap));
67
+ // ['Ping']
68
+
69
+ console.log(tmpMap.Ping.Description);
70
+ // 'Respond with pong'
71
+ ```
72
+
73
+ ## Algorithm
74
+
75
+ 1. Get the first prototype of the instance
76
+ 2. While the prototype is not `Object.prototype`:
77
+ a. For each own property name on the prototype:
78
+ - Skip if already visited (subclass overrides win)
79
+ - Skip if not starting with `action` or too short
80
+ - Skip if ending with `_Schema` or `_Description`
81
+ - Skip if not a function (via `Object.getOwnPropertyDescriptor`)
82
+ - Strip `action` prefix to get the action name
83
+ - Resolve `_Schema` companion (getter, value, or method)
84
+ - Resolve `_Description` companion
85
+ - Create bound handler with Settings extraction wrapper
86
+ - Add to the action map
87
+ b. Move to the next prototype in the chain
88
+ 3. Return the action map
@@ -0,0 +1,81 @@
1
+ # connect()
2
+
3
+ Connect to an Ultravisor server, discover and register actions, and begin accepting work items.
4
+
5
+ ## Signature
6
+
7
+ ```javascript
8
+ connect(pBeaconConfig, fCallback)
9
+ ```
10
+
11
+ ### Parameters
12
+
13
+ | Parameter | Type | Description |
14
+ |-----------|------|-------------|
15
+ | `pBeaconConfig` | `object` | Connection configuration (see below) |
16
+ | `fCallback` | `function` | `function(pError, pBeaconInfo)` -- called when connection completes or fails |
17
+
18
+ ### Configuration
19
+
20
+ | Property | Type | Default | Required | Description |
21
+ |----------|------|---------|----------|-------------|
22
+ | `ServerURL` | `string` | -- | Yes | Ultravisor server URL (e.g. `http://localhost:54321`) |
23
+ | `Name` | `string` | `capabilityName` | No | Beacon worker name for registration |
24
+ | `Password` | `string` | `''` | No | Authentication password |
25
+ | `MaxConcurrent` | `number` | `1` | No | Maximum number of work items to execute in parallel |
26
+ | `StagingPath` | `string` | `process.cwd()` | No | Directory for file transfer staging |
27
+ | `Tags` | `object` | `{}` | No | Metadata tags sent to the coordinator |
28
+ | `BindAddresses` | `array` | `[]` | No | Network addresses to advertise for direct access |
29
+
30
+ ### Callback
31
+
32
+ On success, `fCallback` receives `(null, pBeaconInfo)` where `pBeaconInfo` contains:
33
+
34
+ | Property | Type | Description |
35
+ |----------|------|-------------|
36
+ | `BeaconID` | `string` | Unique identifier assigned by the server |
37
+
38
+ On failure, `fCallback` receives `(pError)`.
39
+
40
+ ## Behavior
41
+
42
+ 1. Validates that `ServerURL` is present in the config
43
+ 2. Validates that `capabilityName` is set on the instance
44
+ 3. Discovers action methods via `buildActionMap()`
45
+ 4. Merges any explicitly registered actions (from `addAction()`)
46
+ 5. Builds a capability descriptor
47
+ 6. Registers the `UltravisorBeacon` service type with Fable (if not already registered)
48
+ 7. Instantiates a beacon service with the provided config
49
+ 8. Registers the capability descriptor with the beacon service
50
+ 9. Enables the beacon (authenticates, registers with server, begins polling)
51
+
52
+ ## Example
53
+
54
+ ```javascript
55
+ tmpCapability.connect(
56
+ {
57
+ ServerURL: 'http://ultravisor.local:54321',
58
+ Name: 'my-worker',
59
+ Password: 'secret',
60
+ MaxConcurrent: 4,
61
+ Tags: { environment: 'production', host: require('os').hostname() }
62
+ },
63
+ (pError, pBeaconInfo) =>
64
+ {
65
+ if (pError)
66
+ {
67
+ console.error('Failed to connect:', pError.message);
68
+ return;
69
+ }
70
+ console.log('Beacon online:', pBeaconInfo.BeaconID);
71
+ });
72
+ ```
73
+
74
+ ## Error Cases
75
+
76
+ | Error | Cause |
77
+ |-------|-------|
78
+ | `ServerURL is required` | `pBeaconConfig.ServerURL` is missing or falsy |
79
+ | `capabilityName must be set` | `this.capabilityName` is empty |
80
+ | Authentication failure | Server rejected credentials |
81
+ | Network error | Server unreachable (beacon will auto-reconnect) |
@@ -0,0 +1,50 @@
1
+ # disconnect()
2
+
3
+ Disconnect from the Ultravisor server. Deregisters the beacon and cleans up the connection.
4
+
5
+ ## Signature
6
+
7
+ ```javascript
8
+ disconnect(fCallback)
9
+ ```
10
+
11
+ ### Parameters
12
+
13
+ | Parameter | Type | Description |
14
+ |-----------|------|-------------|
15
+ | `fCallback` | `function` | `function(pError)` -- called when disconnection completes |
16
+
17
+ ## Behavior
18
+
19
+ 1. If not currently connected, calls `fCallback(null)` immediately
20
+ 2. Calls `disable()` on the underlying beacon service, which:
21
+ - Sends a deregistration message to the server
22
+ - Closes the WebSocket connection (if open)
23
+ - Stops HTTP polling (if active)
24
+ - Calls `onShutdown()` on the capability
25
+ 3. Clears the internal beacon service reference
26
+ 4. Calls `fCallback`
27
+
28
+ ## Example
29
+
30
+ ```javascript
31
+ // Graceful shutdown on SIGTERM
32
+ process.on('SIGTERM', () =>
33
+ {
34
+ tmpCapability.disconnect((pError) =>
35
+ {
36
+ if (pError)
37
+ {
38
+ console.error('Disconnect error:', pError.message);
39
+ }
40
+ console.log('Beacon disconnected.');
41
+ process.exit(0);
42
+ });
43
+ });
44
+ ```
45
+
46
+ ## Notes
47
+
48
+ - Safe to call when not connected -- it is a no-op
49
+ - Safe to call without a callback -- errors are silently ignored
50
+ - After disconnecting, you can call `connect()` again to reconnect
@@ -0,0 +1,33 @@
1
+ # isConnected()
2
+
3
+ Check whether the beacon is currently connected to an Ultravisor server.
4
+
5
+ ## Signature
6
+
7
+ ```javascript
8
+ isConnected() => boolean
9
+ ```
10
+
11
+ ### Returns
12
+
13
+ `true` if the beacon service exists and is enabled; `false` otherwise.
14
+
15
+ ## Example
16
+
17
+ ```javascript
18
+ if (tmpCapability.isConnected())
19
+ {
20
+ console.log('Beacon is online and accepting work items');
21
+ }
22
+ else
23
+ {
24
+ console.log('Beacon is offline');
25
+ tmpCapability.connect({ ServerURL: 'http://ultravisor:54321' }, (pError) => { });
26
+ }
27
+ ```
28
+
29
+ ## Notes
30
+
31
+ - Returns `false` before `connect()` is called
32
+ - Returns `false` after `disconnect()` completes
33
+ - During auto-reconnection (after a connection drop), the beacon service remains enabled internally, so this may return `true` even while reconnecting
@@ -0,0 +1,115 @@
1
+ # onInitialize / onShutdown
2
+
3
+ Lifecycle hooks for resource management. Override these methods in your subclass to set up and tear down resources that your actions depend on.
4
+
5
+ ## onInitialize
6
+
7
+ Called after the beacon connects to the Ultravisor server, before it begins accepting work items.
8
+
9
+ ### Signature
10
+
11
+ ```javascript
12
+ onInitialize(fCallback)
13
+ ```
14
+
15
+ | Parameter | Type | Description |
16
+ |-----------|------|-------------|
17
+ | `fCallback` | `function` | `function(pError)` -- call with `null` on success, or an error to abort |
18
+
19
+ ### Default
20
+
21
+ No-op -- calls `fCallback(null)` immediately.
22
+
23
+ ### Example
24
+
25
+ ```javascript
26
+ onInitialize(fCallback)
27
+ {
28
+ // Create a database connection pool
29
+ this._Pool = require('mysql2').createPool({
30
+ host: this.fable.settings.DatabaseHost || 'localhost',
31
+ user: this.fable.settings.DatabaseUser || 'root',
32
+ database: this.fable.settings.DatabaseName || 'mydb'
33
+ });
34
+
35
+ // Verify the connection
36
+ this._Pool.query('SELECT 1', (pError) =>
37
+ {
38
+ if (pError)
39
+ {
40
+ this.log.error('Database connection failed:', pError.message);
41
+ return fCallback(pError);
42
+ }
43
+ this.log.info('Database connection pool ready');
44
+ return fCallback(null);
45
+ });
46
+ }
47
+ ```
48
+
49
+ ## onShutdown
50
+
51
+ Called when the beacon disconnects from the Ultravisor server.
52
+
53
+ ### Signature
54
+
55
+ ```javascript
56
+ onShutdown(fCallback)
57
+ ```
58
+
59
+ | Parameter | Type | Description |
60
+ |-----------|------|-------------|
61
+ | `fCallback` | `function` | `function(pError)` -- call with `null` on success |
62
+
63
+ ### Default
64
+
65
+ No-op -- calls `fCallback(null)` immediately.
66
+
67
+ ### Example
68
+
69
+ ```javascript
70
+ onShutdown(fCallback)
71
+ {
72
+ if (this._Pool)
73
+ {
74
+ this._Pool.end((pError) =>
75
+ {
76
+ if (pError)
77
+ {
78
+ this.log.warn('Error closing database pool:', pError.message);
79
+ }
80
+ this.log.info('Database connection pool closed');
81
+ return fCallback(null);
82
+ });
83
+ }
84
+ else
85
+ {
86
+ return fCallback(null);
87
+ }
88
+ }
89
+ ```
90
+
91
+ ## Lifecycle Sequence
92
+
93
+ ```
94
+ connect() called
95
+ -> Beacon authenticates with Ultravisor server
96
+ -> Beacon registers capabilities
97
+ -> onInitialize() called
98
+ -> Beacon begins accepting work items
99
+ -> ... actions execute ...
100
+ disconnect() called
101
+ -> Beacon stops accepting work items
102
+ -> onShutdown() called
103
+ -> Beacon deregisters from server
104
+ -> Connection closed
105
+ ```
106
+
107
+ ## Common Use Cases
108
+
109
+ | Resource | onInitialize | onShutdown |
110
+ |----------|-------------|------------|
111
+ | Database connection pool | Create pool, test connection | Close pool |
112
+ | HTTP client / API token | Fetch auth token, create client | Revoke token |
113
+ | Temporary directory | Create staging directory | Remove directory |
114
+ | File handle / stream | Open file | Close file |
115
+ | External service handle | Connect to service | Disconnect |
@@ -0,0 +1,237 @@
1
+ # Architecture
2
+
3
+ Ultravisor Beacon Capability is a thin convention layer on top of `ultravisor-beacon`. It discovers action methods on your subclass, builds the capability descriptor that `ultravisor-beacon` expects, and delegates all transport and execution to the underlying beacon service.
4
+
5
+ ## Class Hierarchy
6
+
7
+ ```mermaid
8
+ graph TD
9
+ FSPB[fable-serviceproviderbase<br/><small>Fable service base class</small>]
10
+ UBC[UltravisorBeaconCapability<br/><small>Convention-based base class</small>]
11
+ YOUR[YourCapability<br/><small>Your subclass with action methods</small>]
12
+
13
+ AM[ActionMap<br/><small>Prototype chain walker</small>]
14
+ UBS[UltravisorBeaconService<br/><small>ultravisor-beacon</small>]
15
+
16
+ CM[CapabilityManager<br/><small>Descriptor store</small>]
17
+ BC[BeaconClient<br/><small>Transport + polling</small>]
18
+ PR[ProviderRegistry<br/><small>Provider index</small>]
19
+ CA[CapabilityAdapter<br/><small>Descriptor to provider bridge</small>]
20
+
21
+ FSPB -->|extends| UBC
22
+ UBC -->|extends| YOUR
23
+ UBC -->|uses| AM
24
+ UBC -->|composes| UBS
25
+
26
+ UBS --> CM
27
+ UBS --> BC
28
+ CM -->|buildProviderDescriptors| CA
29
+ CA -->|registerProvider| PR
30
+ BC --> PR
31
+
32
+ style UBC fill:#e1f5fe
33
+ style YOUR fill:#c8e6c9
34
+ style AM fill:#fff3e0
35
+ ```
36
+
37
+ ## Module Composition
38
+
39
+ The capability base class composes three internal concerns:
40
+
41
+ | Component | Source | Responsibility |
42
+ |-----------|--------|----------------|
43
+ | **ActionMap** | `Ultravisor-Beacon-Capability-ActionMap.cjs` | Discovers `action*` methods on the prototype chain; resolves companion `_Schema` and `_Description` properties; builds bound handlers |
44
+ | **UltravisorBeaconCapability** | `Ultravisor-Beacon-Capability.cjs` | Base class; merges discovered and explicit actions; builds the capability descriptor; manages beacon lifecycle |
45
+ | **UltravisorBeaconService** | `ultravisor-beacon` (external) | Handles authentication, transport negotiation, polling, heartbeat, work item execution |
46
+
47
+ ## Connect Flow
48
+
49
+ When you call `connect()`, the following sequence executes:
50
+
51
+ ```mermaid
52
+ sequenceDiagram
53
+ participant Dev as Your Code
54
+ participant Cap as BeaconCapability
55
+ participant AM as ActionMap
56
+ participant BS as BeaconService
57
+ participant UV as Ultravisor Server
58
+
59
+ Dev->>Cap: connect({ ServerURL, Name, ... })
60
+ Cap->>AM: buildActionMap(this)
61
+ AM-->>Cap: { ActionName: { Handler, Schema, Description } }
62
+ Cap->>Cap: Merge explicit actions (addAction)
63
+ Cap->>Cap: Build capability descriptor
64
+ Cap->>BS: new UltravisorBeaconService(config)
65
+ Cap->>BS: registerCapability(descriptor)
66
+ Cap->>BS: enable()
67
+ BS->>UV: POST /1.0/Authenticate
68
+ UV-->>BS: session cookie
69
+ BS->>UV: POST /Beacon/Register
70
+ UV-->>BS: { BeaconID }
71
+ UV->>UV: Create task types for each action
72
+ BS-->>Cap: callback(null, beaconInfo)
73
+ Cap-->>Dev: callback(null, beaconInfo)
74
+
75
+ Note over UV: Task types now available:<br/>beacon-{capability}-{action}
76
+ ```
77
+
78
+ ## Action Discovery
79
+
80
+ The `buildActionMap()` function walks the prototype chain of your capability instance to find action methods:
81
+
82
+ ```mermaid
83
+ flowchart TD
84
+ START([Start]) --> PROTO[Get prototype of instance]
85
+ PROTO --> CHECK{prototype !== Object.prototype?}
86
+ CHECK -->|No| DONE([Return action map])
87
+ CHECK -->|Yes| PROPS[Get own property names]
88
+ PROPS --> EACH{Next property name}
89
+ EACH -->|None left| NEXT[Get parent prototype]
90
+ NEXT --> CHECK
91
+
92
+ EACH -->|Has name| VISITED{Already visited?}
93
+ VISITED -->|Yes| EACH
94
+ VISITED -->|No| PREFIX{Starts with 'action'?}
95
+ PREFIX -->|No| EACH
96
+ PREFIX -->|Yes| SUFFIX{Ends with '_Schema' or '_Description'?}
97
+ SUFFIX -->|Yes| EACH
98
+ SUFFIX -->|No| FUNC{Is a function?}
99
+ FUNC -->|No| EACH
100
+ FUNC -->|Yes| EXTRACT[Strip 'action' prefix to get action name]
101
+ EXTRACT --> SCHEMA[Resolve companion _Schema]
102
+ SCHEMA --> DESC[Resolve companion _Description]
103
+ DESC --> HANDLER[Create bound handler with Settings extraction]
104
+ HANDLER --> ADD[Add to action map]
105
+ ADD --> EACH
106
+
107
+ style EXTRACT fill:#c8e6c9
108
+ style HANDLER fill:#c8e6c9
109
+ ```
110
+
111
+ Key behaviors:
112
+ - **Subclass wins** -- If a method name is seen on a derived class, the base class version is skipped
113
+ - **Getters supported** -- `_Schema` and `_Description` companions can be ES class getters, plain properties, or methods
114
+ - **Bound handlers** -- Each handler is bound to the instance, preserving `this` context for access to services, connections, and state
115
+
116
+ ## Handler Wrapping
117
+
118
+ The convention-based handler signature differs from the raw `ultravisor-beacon` handler signature. The ActionMap creates a wrapper that bridges the two:
119
+
120
+ ```
121
+ Convention (your code):
122
+ actionDoWork(pSettings, pWorkItem, fCallback, fReportProgress)
123
+
124
+ Raw beacon (what ultravisor-beacon expects):
125
+ Handler(pWorkItem, pContext, fCallback, fReportProgress)
126
+
127
+ Wrapper (created by ActionMap):
128
+ function(pWorkItem, pContext, fCallback, fReportProgress)
129
+ {
130
+ let tmpSettings = (pWorkItem && pWorkItem.Settings) ? pWorkItem.Settings : {};
131
+ return boundMethod(tmpSettings, pWorkItem, fCallback, fReportProgress);
132
+ }
133
+ ```
134
+
135
+ The `pContext` parameter (containing `{ StagingPath }`) is not forwarded because it is unused in practice. If needed, it is available via `this.options.StagingPath` on the capability instance.
136
+
137
+ ## Capability Descriptor
138
+
139
+ The base class produces a descriptor matching the shape documented in `ultravisor-beacon`'s `CapabilityManager`:
140
+
141
+ ```javascript
142
+ {
143
+ Capability: 'YourCapabilityName',
144
+ Name: 'YourCapabilityNameProvider',
145
+ actions:
146
+ {
147
+ 'ActionOne':
148
+ {
149
+ Description: 'What it does',
150
+ SettingsSchema: [{ Name: 'Param', DataType: 'String', Required: true }],
151
+ Handler: function (pWorkItem, pContext, fCallback, fReportProgress) { ... }
152
+ },
153
+ 'ActionTwo': { ... }
154
+ },
155
+ initialize: function (fCallback) { /* delegates to onInitialize */ },
156
+ shutdown: function (fCallback) { /* delegates to onShutdown */ }
157
+ }
158
+ ```
159
+
160
+ The `initialize` and `shutdown` functions delegate to `onInitialize()` and `onShutdown()` on your subclass.
161
+
162
+ ## Server-Side Task Registration
163
+
164
+ When the Ultravisor server receives the beacon registration, its coordinator automatically creates task types for each action:
165
+
166
+ ```mermaid
167
+ graph LR
168
+ REG[Beacon registers<br/>Capability: DBMaint<br/>Actions: PurgeOld, Vacuum] --> COORD[Coordinator]
169
+ COORD --> T1[Task Type:<br/>beacon-dbmaint-purgeold]
170
+ COORD --> T2[Task Type:<br/>beacon-dbmaint-vacuum]
171
+
172
+ T1 --> UI[Ultravisor Dashboard]
173
+ T2 --> UI
174
+ T1 --> SCHED[Scheduler]
175
+ T2 --> SCHED
176
+ T1 --> GRAPH[Operation Graphs]
177
+ T2 --> GRAPH
178
+
179
+ style T1 fill:#e1f5fe
180
+ style T2 fill:#e1f5fe
181
+ ```
182
+
183
+ Each task type includes:
184
+ - **SettingsInputs** derived from the action's `SettingsSchema`
185
+ - **EventInputs/Outputs** for graph wiring (Trigger, Complete, Error)
186
+ - **StateOutputs** for capturing results (Result, StdOut)
187
+
188
+ ## Lifecycle
189
+
190
+ ```mermaid
191
+ stateDiagram-v2
192
+ [*] --> Created: new YourCapability(fable, options)
193
+ Created --> Connecting: connect(config)
194
+ Connecting --> Initializing: onInitialize()
195
+ Initializing --> Connected: Beacon enabled
196
+ Connected --> Executing: Work item received
197
+ Executing --> Connected: Work item complete
198
+ Connected --> ShuttingDown: disconnect()
199
+ ShuttingDown --> Disconnected: onShutdown()
200
+ Disconnected --> [*]
201
+
202
+ Connected --> Reconnecting: Connection lost
203
+ Reconnecting --> Connected: Auto-reconnect
204
+
205
+ note right of Initializing
206
+ Override onInitialize() to set up
207
+ database connections, service handles,
208
+ or other resources your actions need
209
+ end note
210
+
211
+ note right of ShuttingDown
212
+ Override onShutdown() to close
213
+ connections and release resources
214
+ end note
215
+ ```
216
+
217
+ ## File Layout
218
+
219
+ ```
220
+ ultravisor-beacon-capability/
221
+ package.json
222
+ README.md
223
+ source/
224
+ Ultravisor-Beacon-Capability.cjs # Base class (main export)
225
+ Ultravisor-Beacon-Capability-ActionMap.cjs # Action discovery helper
226
+ test/
227
+ Ultravisor-Beacon-Capability_tests.js # Mocha TDD tests
228
+ docs/
229
+ README.md # Overview
230
+ _cover.md # Landing page
231
+ _sidebar.md # Navigation
232
+ _topbar.md # Top bar
233
+ quickstart.md # Step-by-step guide
234
+ architecture.md # This file
235
+ api/ # API reference
236
+ examples/ # Real-world examples
237
+ ```