@onlineapps/service-wrapper 2.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.
package/API.md ADDED
@@ -0,0 +1,336 @@
1
+ ## Modules
2
+
3
+ <dl>
4
+ <dt><a href="#module_@onlineapps/service-wrapper">@onlineapps/service-wrapper</a></dt>
5
+ <dd><p>Infrastructure orchestration for microservices.
6
+ Thin layer that delegates all work to specialized connectors.</p>
7
+ </dd>
8
+ <dt><a href="#module_@onlineapps/service-wrapper">@onlineapps/service-wrapper</a></dt>
9
+ <dd><p>Thin orchestration layer for microservices that handles all infrastructure concerns.
10
+ Delegates all actual work to specialized connectors.</p>
11
+ </dd>
12
+ </dl>
13
+
14
+ <a name="module_@onlineapps/service-wrapper"></a>
15
+
16
+ ## @onlineapps/service-wrapper
17
+ Infrastructure orchestration for microservices.
18
+ Thin layer that delegates all work to specialized connectors.
19
+
20
+ **See**: [GitHub Repository](https://github.com/onlineapps/oa-drive/tree/main/shared/service-wrapper)
21
+ **Since**: 2.0.0
22
+ **Author**: OA Drive Team
23
+ **License**: MIT
24
+
25
+ * [@onlineapps/service-wrapper](#module_@onlineapps/service-wrapper)
26
+ * [~ServiceWrapper](#module_@onlineapps/service-wrapper..ServiceWrapper)
27
+ * [new ServiceWrapper()](#new_module_@onlineapps/service-wrapper..ServiceWrapper_new)
28
+ * [new ServiceWrapper(options)](#new_module_@onlineapps/service-wrapper..ServiceWrapper_new)
29
+ * [~ServiceWrapper](#module_@onlineapps/service-wrapper..ServiceWrapper)
30
+ * [new ServiceWrapper()](#new_module_@onlineapps/service-wrapper..ServiceWrapper_new)
31
+ * [new ServiceWrapper(options)](#new_module_@onlineapps/service-wrapper..ServiceWrapper_new)
32
+ * [~start()](#module_@onlineapps/service-wrapper..start) ⇒ <code>Promise.&lt;void&gt;</code>
33
+ * [~stop()](#module_@onlineapps/service-wrapper..stop) ⇒ <code>Promise.&lt;void&gt;</code>
34
+ * [~getStatus()](#module_@onlineapps/service-wrapper..getStatus) ⇒ <code>Object</code>
35
+
36
+ <a name="module_@onlineapps/service-wrapper..ServiceWrapper"></a>
37
+
38
+ ### @onlineapps/service-wrapper~ServiceWrapper
39
+ **Kind**: inner class of [<code>@onlineapps/service-wrapper</code>](#module_@onlineapps/service-wrapper)
40
+
41
+ * [~ServiceWrapper](#module_@onlineapps/service-wrapper..ServiceWrapper)
42
+ * [new ServiceWrapper()](#new_module_@onlineapps/service-wrapper..ServiceWrapper_new)
43
+ * [new ServiceWrapper(options)](#new_module_@onlineapps/service-wrapper..ServiceWrapper_new)
44
+
45
+ <a name="new_module_@onlineapps/service-wrapper..ServiceWrapper_new"></a>
46
+
47
+ #### new ServiceWrapper()
48
+ Thin wrapper that orchestrates all infrastructure concerns for a microservice.
49
+ ALL actual functionality is delegated to specialized connectors.
50
+
51
+ **Example**
52
+ ```js
53
+ const wrapper = new ServiceWrapper({
54
+ service: expressApp,
55
+ serviceName: 'hello-service',
56
+ openApiSpec: require('./openapi.json'),
57
+ config: {
58
+ rabbitmq: process.env.RABBITMQ_URL,
59
+ redis: process.env.REDIS_HOST,
60
+ registry: process.env.REGISTRY_URL
61
+ }
62
+ });
63
+
64
+ await wrapper.start();
65
+ ```
66
+ <a name="new_module_@onlineapps/service-wrapper..ServiceWrapper_new"></a>
67
+
68
+ #### new ServiceWrapper(options)
69
+ Create a new ServiceWrapper instance
70
+
71
+ **Throws**:
72
+
73
+ - <code>Error</code> If required options are missing
74
+
75
+
76
+ | Param | Type | Default | Description |
77
+ | --- | --- | --- | --- |
78
+ | options | <code>Object</code> | | Configuration options |
79
+ | options.service | <code>Object</code> | | Express application instance |
80
+ | options.serviceName | <code>string</code> | | Name of the service |
81
+ | options.openApiSpec | <code>Object</code> | | OpenAPI specification |
82
+ | [options.config] | <code>Object</code> | <code>{}</code> | Infrastructure configuration |
83
+ | [options.config.rabbitmq] | <code>string</code> | | RabbitMQ connection URL |
84
+ | [options.config.redis] | <code>string</code> | | Redis connection string |
85
+ | [options.config.registry] | <code>string</code> | | Registry service URL |
86
+ | [options.config.port] | <code>number</code> | <code>3000</code> | Service port |
87
+ | [options.config.prefetch] | <code>number</code> | <code>10</code> | MQ prefetch count |
88
+
89
+ <a name="module_@onlineapps/service-wrapper..ServiceWrapper"></a>
90
+
91
+ ### @onlineapps/service-wrapper~ServiceWrapper
92
+ **Kind**: inner class of [<code>@onlineapps/service-wrapper</code>](#module_@onlineapps/service-wrapper)
93
+
94
+ * [~ServiceWrapper](#module_@onlineapps/service-wrapper..ServiceWrapper)
95
+ * [new ServiceWrapper()](#new_module_@onlineapps/service-wrapper..ServiceWrapper_new)
96
+ * [new ServiceWrapper(options)](#new_module_@onlineapps/service-wrapper..ServiceWrapper_new)
97
+
98
+ <a name="new_module_@onlineapps/service-wrapper..ServiceWrapper_new"></a>
99
+
100
+ #### new ServiceWrapper()
101
+ Thin wrapper that orchestrates all infrastructure concerns for a microservice.
102
+ ALL actual functionality is delegated to specialized connectors.
103
+
104
+ **Example**
105
+ ```js
106
+ const wrapper = new ServiceWrapper({
107
+ service: expressApp,
108
+ serviceName: 'hello-service',
109
+ openApiSpec: require('./openapi.json'),
110
+ config: {
111
+ rabbitmq: process.env.RABBITMQ_URL,
112
+ redis: process.env.REDIS_HOST,
113
+ registry: process.env.REGISTRY_URL
114
+ }
115
+ });
116
+
117
+ await wrapper.start();
118
+ ```
119
+ <a name="new_module_@onlineapps/service-wrapper..ServiceWrapper_new"></a>
120
+
121
+ #### new ServiceWrapper(options)
122
+ Create a new ServiceWrapper instance
123
+
124
+ **Throws**:
125
+
126
+ - <code>Error</code> If required options are missing
127
+
128
+
129
+ | Param | Type | Default | Description |
130
+ | --- | --- | --- | --- |
131
+ | options | <code>Object</code> | | Configuration options |
132
+ | options.service | <code>Object</code> | | Express application instance |
133
+ | options.serviceName | <code>string</code> | | Name of the service |
134
+ | options.openApiSpec | <code>Object</code> | | OpenAPI specification |
135
+ | [options.config] | <code>Object</code> | <code>{}</code> | Infrastructure configuration |
136
+ | [options.config.rabbitmq] | <code>string</code> | | RabbitMQ connection URL |
137
+ | [options.config.redis] | <code>string</code> | | Redis connection string |
138
+ | [options.config.registry] | <code>string</code> | | Registry service URL |
139
+ | [options.config.port] | <code>number</code> | <code>3000</code> | Service port |
140
+ | [options.config.prefetch] | <code>number</code> | <code>10</code> | MQ prefetch count |
141
+
142
+ <a name="module_@onlineapps/service-wrapper..start"></a>
143
+
144
+ ### @onlineapps/service-wrapper~start() ⇒ <code>Promise.&lt;void&gt;</code>
145
+ Start the service wrapper
146
+
147
+ **Kind**: inner method of [<code>@onlineapps/service-wrapper</code>](#module_@onlineapps/service-wrapper)
148
+ **Example**
149
+ ```js
150
+ await wrapper.start();
151
+ console.log('Service wrapper started');
152
+ ```
153
+ <a name="module_@onlineapps/service-wrapper..stop"></a>
154
+
155
+ ### @onlineapps/service-wrapper~stop() ⇒ <code>Promise.&lt;void&gt;</code>
156
+ Stop the service wrapper
157
+
158
+ **Kind**: inner method of [<code>@onlineapps/service-wrapper</code>](#module_@onlineapps/service-wrapper)
159
+ **Example**
160
+ ```js
161
+ await wrapper.stop();
162
+ console.log('Service wrapper stopped');
163
+ ```
164
+ <a name="module_@onlineapps/service-wrapper..getStatus"></a>
165
+
166
+ ### @onlineapps/service-wrapper~getStatus() ⇒ <code>Object</code>
167
+ Get wrapper status
168
+
169
+ **Kind**: inner method of [<code>@onlineapps/service-wrapper</code>](#module_@onlineapps/service-wrapper)
170
+ **Returns**: <code>Object</code> - Status information
171
+ **Example**
172
+ ```js
173
+ const status = wrapper.getStatus();
174
+ console.log('Wrapper status:', status);
175
+ ```
176
+ <a name="module_@onlineapps/service-wrapper"></a>
177
+
178
+ ## @onlineapps/service-wrapper
179
+ Thin orchestration layer for microservices that handles all infrastructure concerns.
180
+ Delegates all actual work to specialized connectors.
181
+
182
+ **Since**: 2.0.0
183
+ **Author**: OA Drive Team
184
+ **License**: MIT
185
+
186
+ * [@onlineapps/service-wrapper](#module_@onlineapps/service-wrapper)
187
+ * [~ServiceWrapper](#module_@onlineapps/service-wrapper..ServiceWrapper)
188
+ * [new ServiceWrapper()](#new_module_@onlineapps/service-wrapper..ServiceWrapper_new)
189
+ * [new ServiceWrapper(options)](#new_module_@onlineapps/service-wrapper..ServiceWrapper_new)
190
+ * [~ServiceWrapper](#module_@onlineapps/service-wrapper..ServiceWrapper)
191
+ * [new ServiceWrapper()](#new_module_@onlineapps/service-wrapper..ServiceWrapper_new)
192
+ * [new ServiceWrapper(options)](#new_module_@onlineapps/service-wrapper..ServiceWrapper_new)
193
+ * [~start()](#module_@onlineapps/service-wrapper..start) ⇒ <code>Promise.&lt;void&gt;</code>
194
+ * [~stop()](#module_@onlineapps/service-wrapper..stop) ⇒ <code>Promise.&lt;void&gt;</code>
195
+ * [~getStatus()](#module_@onlineapps/service-wrapper..getStatus) ⇒ <code>Object</code>
196
+
197
+ <a name="module_@onlineapps/service-wrapper..ServiceWrapper"></a>
198
+
199
+ ### @onlineapps/service-wrapper~ServiceWrapper
200
+ **Kind**: inner class of [<code>@onlineapps/service-wrapper</code>](#module_@onlineapps/service-wrapper)
201
+
202
+ * [~ServiceWrapper](#module_@onlineapps/service-wrapper..ServiceWrapper)
203
+ * [new ServiceWrapper()](#new_module_@onlineapps/service-wrapper..ServiceWrapper_new)
204
+ * [new ServiceWrapper(options)](#new_module_@onlineapps/service-wrapper..ServiceWrapper_new)
205
+
206
+ <a name="new_module_@onlineapps/service-wrapper..ServiceWrapper_new"></a>
207
+
208
+ #### new ServiceWrapper()
209
+ Thin wrapper that orchestrates all infrastructure concerns for a microservice.
210
+ ALL actual functionality is delegated to specialized connectors.
211
+
212
+ **Example**
213
+ ```js
214
+ const wrapper = new ServiceWrapper({
215
+ service: expressApp,
216
+ serviceName: 'hello-service',
217
+ openApiSpec: require('./openapi.json'),
218
+ config: {
219
+ rabbitmq: process.env.RABBITMQ_URL,
220
+ redis: process.env.REDIS_HOST,
221
+ registry: process.env.REGISTRY_URL
222
+ }
223
+ });
224
+
225
+ await wrapper.start();
226
+ ```
227
+ <a name="new_module_@onlineapps/service-wrapper..ServiceWrapper_new"></a>
228
+
229
+ #### new ServiceWrapper(options)
230
+ Create a new ServiceWrapper instance
231
+
232
+ **Throws**:
233
+
234
+ - <code>Error</code> If required options are missing
235
+
236
+
237
+ | Param | Type | Default | Description |
238
+ | --- | --- | --- | --- |
239
+ | options | <code>Object</code> | | Configuration options |
240
+ | options.service | <code>Object</code> | | Express application instance |
241
+ | options.serviceName | <code>string</code> | | Name of the service |
242
+ | options.openApiSpec | <code>Object</code> | | OpenAPI specification |
243
+ | [options.config] | <code>Object</code> | <code>{}</code> | Infrastructure configuration |
244
+ | [options.config.rabbitmq] | <code>string</code> | | RabbitMQ connection URL |
245
+ | [options.config.redis] | <code>string</code> | | Redis connection string |
246
+ | [options.config.registry] | <code>string</code> | | Registry service URL |
247
+ | [options.config.port] | <code>number</code> | <code>3000</code> | Service port |
248
+ | [options.config.prefetch] | <code>number</code> | <code>10</code> | MQ prefetch count |
249
+
250
+ <a name="module_@onlineapps/service-wrapper..ServiceWrapper"></a>
251
+
252
+ ### @onlineapps/service-wrapper~ServiceWrapper
253
+ **Kind**: inner class of [<code>@onlineapps/service-wrapper</code>](#module_@onlineapps/service-wrapper)
254
+
255
+ * [~ServiceWrapper](#module_@onlineapps/service-wrapper..ServiceWrapper)
256
+ * [new ServiceWrapper()](#new_module_@onlineapps/service-wrapper..ServiceWrapper_new)
257
+ * [new ServiceWrapper(options)](#new_module_@onlineapps/service-wrapper..ServiceWrapper_new)
258
+
259
+ <a name="new_module_@onlineapps/service-wrapper..ServiceWrapper_new"></a>
260
+
261
+ #### new ServiceWrapper()
262
+ Thin wrapper that orchestrates all infrastructure concerns for a microservice.
263
+ ALL actual functionality is delegated to specialized connectors.
264
+
265
+ **Example**
266
+ ```js
267
+ const wrapper = new ServiceWrapper({
268
+ service: expressApp,
269
+ serviceName: 'hello-service',
270
+ openApiSpec: require('./openapi.json'),
271
+ config: {
272
+ rabbitmq: process.env.RABBITMQ_URL,
273
+ redis: process.env.REDIS_HOST,
274
+ registry: process.env.REGISTRY_URL
275
+ }
276
+ });
277
+
278
+ await wrapper.start();
279
+ ```
280
+ <a name="new_module_@onlineapps/service-wrapper..ServiceWrapper_new"></a>
281
+
282
+ #### new ServiceWrapper(options)
283
+ Create a new ServiceWrapper instance
284
+
285
+ **Throws**:
286
+
287
+ - <code>Error</code> If required options are missing
288
+
289
+
290
+ | Param | Type | Default | Description |
291
+ | --- | --- | --- | --- |
292
+ | options | <code>Object</code> | | Configuration options |
293
+ | options.service | <code>Object</code> | | Express application instance |
294
+ | options.serviceName | <code>string</code> | | Name of the service |
295
+ | options.openApiSpec | <code>Object</code> | | OpenAPI specification |
296
+ | [options.config] | <code>Object</code> | <code>{}</code> | Infrastructure configuration |
297
+ | [options.config.rabbitmq] | <code>string</code> | | RabbitMQ connection URL |
298
+ | [options.config.redis] | <code>string</code> | | Redis connection string |
299
+ | [options.config.registry] | <code>string</code> | | Registry service URL |
300
+ | [options.config.port] | <code>number</code> | <code>3000</code> | Service port |
301
+ | [options.config.prefetch] | <code>number</code> | <code>10</code> | MQ prefetch count |
302
+
303
+ <a name="module_@onlineapps/service-wrapper..start"></a>
304
+
305
+ ### @onlineapps/service-wrapper~start() ⇒ <code>Promise.&lt;void&gt;</code>
306
+ Start the service wrapper
307
+
308
+ **Kind**: inner method of [<code>@onlineapps/service-wrapper</code>](#module_@onlineapps/service-wrapper)
309
+ **Example**
310
+ ```js
311
+ await wrapper.start();
312
+ console.log('Service wrapper started');
313
+ ```
314
+ <a name="module_@onlineapps/service-wrapper..stop"></a>
315
+
316
+ ### @onlineapps/service-wrapper~stop() ⇒ <code>Promise.&lt;void&gt;</code>
317
+ Stop the service wrapper
318
+
319
+ **Kind**: inner method of [<code>@onlineapps/service-wrapper</code>](#module_@onlineapps/service-wrapper)
320
+ **Example**
321
+ ```js
322
+ await wrapper.stop();
323
+ console.log('Service wrapper stopped');
324
+ ```
325
+ <a name="module_@onlineapps/service-wrapper..getStatus"></a>
326
+
327
+ ### @onlineapps/service-wrapper~getStatus() ⇒ <code>Object</code>
328
+ Get wrapper status
329
+
330
+ **Kind**: inner method of [<code>@onlineapps/service-wrapper</code>](#module_@onlineapps/service-wrapper)
331
+ **Returns**: <code>Object</code> - Status information
332
+ **Example**
333
+ ```js
334
+ const status = wrapper.getStatus();
335
+ console.log('Wrapper status:', status);
336
+ ```
package/README.md ADDED
@@ -0,0 +1,185 @@
1
+ # @onlineapps/service-wrapper
2
+
3
+ Infrastructure wrapper that handles all workflow processing, message queue operations, and service registration for microservices.
4
+
5
+ ## Purpose
6
+
7
+ This package provides the infrastructure layer that sits between:
8
+ - **Message Queues** (RabbitMQ) and **Services** (business logic)
9
+ - **Workflow Engine** and **Service APIs**
10
+ - **Service Registry** and **Service Implementation**
11
+
12
+ ## Key Features
13
+
14
+ - **Automatic workflow processing** - Handles cookbook execution
15
+ - **Message queue integration** - Subscribes to queues, routes messages
16
+ - **Service registration** - Auto-registers with service registry
17
+ - **API-to-Cookbook mapping** - Converts workflow steps to API calls
18
+ - **Error handling** - Retry logic, DLQ routing
19
+ - **Health checks** - Automatic health endpoint
20
+
21
+ ## Architecture
22
+
23
+ ```
24
+ [RabbitMQ Message] → [Service Wrapper] → [Service API Call] → [Business Logic]
25
+ ↑ ↑ ↑
26
+ This package OpenAPI spec Your service
27
+ Handles all Defines API Pure business
28
+ infrastructure interface logic only
29
+ ```
30
+
31
+ ## Usage
32
+
33
+ ### 1. Wrap Your Service
34
+
35
+ ```javascript
36
+ const ServiceWrapper = require('@onlineapps/service-wrapper');
37
+ const express = require('express');
38
+
39
+ // Your pure business logic service
40
+ const app = express();
41
+ app.get('/hello', (req, res) => {
42
+ res.json({ message: `Hello ${req.query.name}` });
43
+ });
44
+
45
+ // Wrap with infrastructure
46
+ const wrapper = new ServiceWrapper({
47
+ service: app,
48
+ serviceName: 'hello-service',
49
+ openApiSpec: require('./openapi.json'),
50
+ config: {
51
+ rabbitmq: process.env.RABBITMQ_URL,
52
+ registry: process.env.REGISTRY_URL,
53
+ port: process.env.PORT || 3000
54
+ }
55
+ });
56
+
57
+ // Start wrapped service
58
+ wrapper.start();
59
+ ```
60
+
61
+ ### 2. Service Receives
62
+
63
+ The wrapper automatically:
64
+ - Subscribes to `{serviceName}.workflow` queue
65
+ - Processes workflow messages
66
+ - Calls your API endpoints based on cookbook steps
67
+ - Routes results to next service
68
+
69
+ ### 3. Your Service Focuses on Business Logic
70
+
71
+ Your service only needs to:
72
+ - Expose API endpoints
73
+ - Implement business logic
74
+ - Return results
75
+
76
+ NO infrastructure code needed in your service!
77
+
78
+ ## Configuration
79
+
80
+ ```javascript
81
+ {
82
+ service: expressApp, // Your Express app
83
+ serviceName: 'my-service', // Service identifier
84
+ openApiSpec: {}, // OpenAPI specification
85
+ config: {
86
+ rabbitmq: 'amqp://...', // RabbitMQ connection
87
+ registry: 'http://...', // Registry URL
88
+ redis: 'redis://...', // Redis connection
89
+ port: 3000, // Service port
90
+ healthPath: '/health', // Health check path
91
+ retryPolicy: { // Retry configuration
92
+ maxRetries: 3,
93
+ backoffMs: 1000
94
+ }
95
+ }
96
+ }
97
+ ```
98
+
99
+ ## What This Handles
100
+
101
+ ### Workflow Processing
102
+ - Receives workflow messages from queue
103
+ - Validates cookbook structure
104
+ - Executes steps for this service
105
+ - Routes to next service or completion
106
+
107
+ ### API Mapping
108
+ - Maps cookbook steps to API calls
109
+ - Handles input/output transformation
110
+ - Manages context passing between steps
111
+
112
+ ### Infrastructure Concerns
113
+ - Service registration and health checks
114
+ - Message queue subscription and publishing
115
+ - Error handling and retry logic
116
+ - Dead letter queue routing
117
+
118
+ ## Service Requirements
119
+
120
+ Your service needs:
121
+ 1. **OpenAPI specification** - Describes your API
122
+ 2. **Express app** - With business logic endpoints
123
+ 3. **Environment variables** - For configuration
124
+
125
+ Your service should NOT have:
126
+ - Workflow processing code
127
+ - Message queue operations
128
+ - Service registration logic
129
+ - Connector imports
130
+
131
+ ## Example Service Structure
132
+
133
+ ```
134
+ my-service/
135
+ ├── src/
136
+ │ ├── index.js # Express app (business logic only)
137
+ │ ├── routes/ # API endpoints
138
+ │ └── services/ # Business logic
139
+ ├── connector-config/
140
+ │ └── openapi.json # API specification
141
+ └── package.json # Dependencies (no @onlineapps/connector-*)
142
+ ```
143
+
144
+ ## Testing
145
+
146
+ The wrapper provides test utilities:
147
+
148
+ ```javascript
149
+ const { TestWrapper } = require('@onlineapps/service-wrapper');
150
+
151
+ describe('My Service', () => {
152
+ let wrapper;
153
+
154
+ beforeAll(() => {
155
+ wrapper = new TestWrapper({
156
+ service: myApp,
157
+ mockQueues: true,
158
+ mockRegistry: true
159
+ });
160
+ });
161
+
162
+ test('processes workflow step', async () => {
163
+ const result = await wrapper.processStep({
164
+ type: 'task',
165
+ service: 'my-service',
166
+ operation: 'doSomething'
167
+ });
168
+ expect(result).toBeDefined();
169
+ });
170
+ });
171
+ ```
172
+
173
+ ## Migration from Embedded Infrastructure
174
+
175
+ If your service currently has workflow code:
176
+
177
+ 1. Install service-wrapper: `npm install @onlineapps/service-wrapper`
178
+ 2. Remove all `@onlineapps/connector-*` from service code
179
+ 3. Delete workflow processing files
180
+ 4. Wrap your Express app with ServiceWrapper
181
+ 5. Test that everything still works
182
+
183
+ ## License
184
+
185
+ PROPRIETARY - All rights reserved
package/build-docs.js ADDED
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * Manual documentation builder for service-wrapper
6
+ * Generates API.md from JSDoc comments
7
+ */
8
+
9
+ const jsdoc2md = require('jsdoc-to-markdown');
10
+ const fs = require('fs');
11
+ const path = require('path');
12
+
13
+ async function buildDocs() {
14
+ console.log('Building API documentation...');
15
+
16
+ try {
17
+ // Configure jsdoc2md options
18
+ const options = {
19
+ files: 'src/**/*.js',
20
+ 'no-cache': true,
21
+ 'heading-depth': 2,
22
+ template: fs.readFileSync(path.join(__dirname, 'docs-template.hbs'), 'utf8').toString()
23
+ };
24
+
25
+ // Generate markdown documentation
26
+ const output = await jsdoc2md.render(options);
27
+
28
+ // Write to API.md
29
+ fs.writeFileSync('API.md', output);
30
+
31
+ console.log('✓ API documentation generated successfully!');
32
+ console.log(' Output: API.md');
33
+
34
+ } catch (error) {
35
+ console.error('✗ Failed to generate documentation:', error.message);
36
+
37
+ // Fallback: use simple generation without template
38
+ try {
39
+ const simpleOutput = await jsdoc2md.render({ files: 'src/**/*.js' });
40
+ fs.writeFileSync('API.md', simpleOutput);
41
+ console.log('✓ API documentation generated (simple mode)');
42
+ } catch (fallbackError) {
43
+ console.error('✗ Fallback also failed:', fallbackError.message);
44
+ process.exit(1);
45
+ }
46
+ }
47
+ }
48
+
49
+ // Run if called directly
50
+ if (require.main === module) {
51
+ buildDocs();
52
+ }
53
+
54
+ module.exports = { buildDocs };