donobu 2.30.0 → 2.31.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/dist/apis/GptConfigsApi.d.ts +0 -10
- package/dist/apis/GptConfigsApi.d.ts.map +1 -1
- package/dist/apis/GptConfigsApi.js +6 -11
- package/dist/apis/GptConfigsApi.js.map +1 -1
- package/dist/assets/generated/version +1 -1
- package/dist/cli/install-donobu-plugin.d.ts +6 -0
- package/dist/cli/install-donobu-plugin.d.ts.map +1 -0
- package/dist/cli/install-donobu-plugin.js +125 -0
- package/dist/cli/install-donobu-plugin.js.map +1 -0
- package/dist/cli/playwright-json-to-markdown.d.ts +43 -0
- package/dist/cli/playwright-json-to-markdown.d.ts.map +1 -0
- package/dist/cli/playwright-json-to-markdown.js +239 -0
- package/dist/cli/playwright-json-to-markdown.js.map +1 -0
- package/dist/cli/playwright-json-to-slack-json.d.ts +3 -0
- package/dist/cli/playwright-json-to-slack-json.d.ts.map +1 -0
- package/dist/cli/playwright-json-to-slack-json.js +207 -0
- package/dist/cli/playwright-json-to-slack-json.js.map +1 -0
- package/dist/{esm/clients/GoogleGptClient.d.ts → clients/GoogleGenerativeAiGptClient.d.ts} +4 -4
- package/dist/clients/GoogleGenerativeAiGptClient.d.ts.map +1 -0
- package/dist/clients/{GoogleGptClient.js → GoogleGenerativeAiGptClient.js} +9 -9
- package/dist/clients/GoogleGenerativeAiGptClient.js.map +1 -0
- package/dist/clients/GoogleVertexGptClient.d.ts +24 -0
- package/dist/clients/GoogleVertexGptClient.d.ts.map +1 -0
- package/dist/clients/GoogleVertexGptClient.js +98 -0
- package/dist/clients/GoogleVertexGptClient.js.map +1 -0
- package/dist/clients/GptClientFactory.d.ts.map +1 -1
- package/dist/clients/GptClientFactory.js +6 -2
- package/dist/clients/GptClientFactory.js.map +1 -1
- package/dist/clients/OpenAiGptClient.d.ts +2 -2
- package/dist/clients/OpenAiGptClient.d.ts.map +1 -1
- package/dist/clients/OpenAiGptClient.js.map +1 -1
- package/dist/clients/VercelAiGptClient.d.ts.map +1 -1
- package/dist/clients/VercelAiGptClient.js +6 -5
- package/dist/clients/VercelAiGptClient.js.map +1 -1
- package/dist/envVars.d.ts +20 -0
- package/dist/envVars.d.ts.map +1 -1
- package/dist/envVars.js +20 -0
- package/dist/envVars.js.map +1 -1
- package/dist/esm/apis/GptConfigsApi.d.ts +0 -10
- package/dist/esm/apis/GptConfigsApi.d.ts.map +1 -1
- package/dist/esm/apis/GptConfigsApi.js +6 -11
- package/dist/esm/apis/GptConfigsApi.js.map +1 -1
- package/dist/esm/assets/generated/version +1 -1
- package/dist/esm/cli/install-donobu-plugin.d.ts +6 -0
- package/dist/esm/cli/install-donobu-plugin.d.ts.map +1 -0
- package/dist/esm/cli/install-donobu-plugin.js +125 -0
- package/dist/esm/cli/install-donobu-plugin.js.map +1 -0
- package/dist/esm/cli/playwright-json-to-markdown.d.ts +43 -0
- package/dist/esm/cli/playwright-json-to-markdown.d.ts.map +1 -0
- package/dist/esm/cli/playwright-json-to-markdown.js +239 -0
- package/dist/esm/cli/playwright-json-to-markdown.js.map +1 -0
- package/dist/esm/cli/playwright-json-to-slack-json.d.ts +3 -0
- package/dist/esm/cli/playwright-json-to-slack-json.d.ts.map +1 -0
- package/dist/esm/cli/playwright-json-to-slack-json.js +207 -0
- package/dist/esm/cli/playwright-json-to-slack-json.js.map +1 -0
- package/dist/{clients/GoogleGptClient.d.ts → esm/clients/GoogleGenerativeAiGptClient.d.ts} +4 -4
- package/dist/esm/clients/GoogleGenerativeAiGptClient.d.ts.map +1 -0
- package/dist/esm/clients/{GoogleGptClient.js → GoogleGenerativeAiGptClient.js} +9 -9
- package/dist/esm/clients/GoogleGenerativeAiGptClient.js.map +1 -0
- package/dist/esm/clients/GoogleVertexGptClient.d.ts +24 -0
- package/dist/esm/clients/GoogleVertexGptClient.d.ts.map +1 -0
- package/dist/esm/clients/GoogleVertexGptClient.js +98 -0
- package/dist/esm/clients/GoogleVertexGptClient.js.map +1 -0
- package/dist/esm/clients/GptClientFactory.d.ts.map +1 -1
- package/dist/esm/clients/GptClientFactory.js +6 -2
- package/dist/esm/clients/GptClientFactory.js.map +1 -1
- package/dist/esm/clients/OpenAiGptClient.d.ts +2 -2
- package/dist/esm/clients/OpenAiGptClient.d.ts.map +1 -1
- package/dist/esm/clients/OpenAiGptClient.js.map +1 -1
- package/dist/esm/clients/VercelAiGptClient.d.ts.map +1 -1
- package/dist/esm/clients/VercelAiGptClient.js +6 -5
- package/dist/esm/clients/VercelAiGptClient.js.map +1 -1
- package/dist/esm/envVars.d.ts +20 -0
- package/dist/esm/envVars.d.ts.map +1 -1
- package/dist/esm/envVars.js +20 -0
- package/dist/esm/envVars.js.map +1 -1
- package/dist/esm/exceptions/GptPlatformAuthenticationFailedException.d.ts +2 -1
- package/dist/esm/exceptions/GptPlatformAuthenticationFailedException.d.ts.map +1 -1
- package/dist/esm/exceptions/GptPlatformAuthenticationFailedException.js +3 -2
- package/dist/esm/exceptions/GptPlatformAuthenticationFailedException.js.map +1 -1
- package/dist/esm/init.d.ts +9 -0
- package/dist/esm/init.d.ts.map +1 -0
- package/dist/esm/init.js +70 -0
- package/dist/esm/init.js.map +1 -0
- package/dist/esm/lib/fixtures/gptClients.d.ts.map +1 -1
- package/dist/esm/lib/fixtures/gptClients.js +16 -2
- package/dist/esm/lib/fixtures/gptClients.js.map +1 -1
- package/dist/esm/main.d.ts +1 -0
- package/dist/esm/main.d.ts.map +1 -1
- package/dist/esm/main.js +3 -50
- package/dist/esm/main.js.map +1 -1
- package/dist/esm/managers/DonobuFlowsManager.d.ts.map +1 -1
- package/dist/esm/managers/DonobuFlowsManager.js +13 -1
- package/dist/esm/managers/DonobuFlowsManager.js.map +1 -1
- package/dist/esm/models/BrowserConfig.d.ts +269 -4
- package/dist/esm/models/BrowserConfig.d.ts.map +1 -1
- package/dist/esm/models/BrowserConfig.js +17 -4
- package/dist/esm/models/BrowserConfig.js.map +1 -1
- package/dist/esm/models/BrowserStateFlowReference.d.ts +165 -14
- package/dist/esm/models/BrowserStateFlowReference.d.ts.map +1 -1
- package/dist/esm/models/BrowserStateFlowReference.js +19 -0
- package/dist/esm/models/BrowserStateFlowReference.js.map +1 -1
- package/dist/esm/models/BrowserStorageState.d.ts +88 -10
- package/dist/esm/models/BrowserStorageState.d.ts.map +1 -1
- package/dist/esm/models/BrowserStorageState.js +38 -0
- package/dist/esm/models/BrowserStorageState.js.map +1 -1
- package/dist/esm/models/CreateDonobuFlow.d.ts +347 -5
- package/dist/esm/models/CreateDonobuFlow.d.ts.map +1 -1
- package/dist/esm/models/FlowMetadata.d.ts +347 -5
- package/dist/esm/models/FlowMetadata.d.ts.map +1 -1
- package/dist/esm/models/GptConfig.d.ts +44 -6
- package/dist/esm/models/GptConfig.d.ts.map +1 -1
- package/dist/esm/models/GptConfig.js +17 -7
- package/dist/esm/models/GptConfig.js.map +1 -1
- package/dist/esm/tools/ReplayableInteraction.d.ts +1 -1
- package/dist/esm/tools/ReplayableInteraction.d.ts.map +1 -1
- package/dist/esm/tools/RunInlineJavaScriptCodeTool.js +8 -8
- package/dist/esm/tools/RunInlineJavaScriptCodeTool.js.map +1 -1
- package/dist/esm/tools/RunSandboxedJavaScriptCodeTool.d.ts.map +1 -1
- package/dist/esm/tools/RunSandboxedJavaScriptCodeTool.js +8 -9
- package/dist/esm/tools/RunSandboxedJavaScriptCodeTool.js.map +1 -1
- package/dist/esm/tools/TriggerDonobuFlowTool.d.ts +850 -14
- package/dist/esm/tools/TriggerDonobuFlowTool.d.ts.map +1 -1
- package/dist/esm/utils/BrowserUtils.d.ts +118 -5
- package/dist/esm/utils/BrowserUtils.d.ts.map +1 -1
- package/dist/esm/utils/BrowserUtils.js +171 -31
- package/dist/esm/utils/BrowserUtils.js.map +1 -1
- package/dist/esm/utils/JsonUtils.d.ts +94 -9
- package/dist/esm/utils/JsonUtils.d.ts.map +1 -1
- package/dist/esm/utils/JsonUtils.js +96 -77
- package/dist/esm/utils/JsonUtils.js.map +1 -1
- package/dist/exceptions/GptPlatformAuthenticationFailedException.d.ts +2 -1
- package/dist/exceptions/GptPlatformAuthenticationFailedException.d.ts.map +1 -1
- package/dist/exceptions/GptPlatformAuthenticationFailedException.js +3 -2
- package/dist/exceptions/GptPlatformAuthenticationFailedException.js.map +1 -1
- package/dist/init.d.ts +9 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +70 -0
- package/dist/init.js.map +1 -0
- package/dist/lib/fixtures/gptClients.d.ts.map +1 -1
- package/dist/lib/fixtures/gptClients.js +16 -2
- package/dist/lib/fixtures/gptClients.js.map +1 -1
- package/dist/main.d.ts +1 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +3 -50
- package/dist/main.js.map +1 -1
- package/dist/managers/DonobuFlowsManager.d.ts.map +1 -1
- package/dist/managers/DonobuFlowsManager.js +13 -1
- package/dist/managers/DonobuFlowsManager.js.map +1 -1
- package/dist/models/BrowserConfig.d.ts +269 -4
- package/dist/models/BrowserConfig.d.ts.map +1 -1
- package/dist/models/BrowserConfig.js +17 -4
- package/dist/models/BrowserConfig.js.map +1 -1
- package/dist/models/BrowserStateFlowReference.d.ts +165 -14
- package/dist/models/BrowserStateFlowReference.d.ts.map +1 -1
- package/dist/models/BrowserStateFlowReference.js +19 -0
- package/dist/models/BrowserStateFlowReference.js.map +1 -1
- package/dist/models/BrowserStorageState.d.ts +88 -10
- package/dist/models/BrowserStorageState.d.ts.map +1 -1
- package/dist/models/BrowserStorageState.js +38 -0
- package/dist/models/BrowserStorageState.js.map +1 -1
- package/dist/models/CreateDonobuFlow.d.ts +347 -5
- package/dist/models/CreateDonobuFlow.d.ts.map +1 -1
- package/dist/models/FlowMetadata.d.ts +347 -5
- package/dist/models/FlowMetadata.d.ts.map +1 -1
- package/dist/models/GptConfig.d.ts +44 -6
- package/dist/models/GptConfig.d.ts.map +1 -1
- package/dist/models/GptConfig.js +17 -7
- package/dist/models/GptConfig.js.map +1 -1
- package/dist/tools/ReplayableInteraction.d.ts +1 -1
- package/dist/tools/ReplayableInteraction.d.ts.map +1 -1
- package/dist/tools/RunInlineJavaScriptCodeTool.js +8 -8
- package/dist/tools/RunInlineJavaScriptCodeTool.js.map +1 -1
- package/dist/tools/RunSandboxedJavaScriptCodeTool.d.ts.map +1 -1
- package/dist/tools/RunSandboxedJavaScriptCodeTool.js +8 -9
- package/dist/tools/RunSandboxedJavaScriptCodeTool.js.map +1 -1
- package/dist/tools/TriggerDonobuFlowTool.d.ts +850 -14
- package/dist/tools/TriggerDonobuFlowTool.d.ts.map +1 -1
- package/dist/utils/BrowserUtils.d.ts +118 -5
- package/dist/utils/BrowserUtils.d.ts.map +1 -1
- package/dist/utils/BrowserUtils.js +171 -31
- package/dist/utils/BrowserUtils.js.map +1 -1
- package/dist/utils/JsonUtils.d.ts +94 -9
- package/dist/utils/JsonUtils.d.ts.map +1 -1
- package/dist/utils/JsonUtils.js +96 -77
- package/dist/utils/JsonUtils.js.map +1 -1
- package/package.json +12 -11
- package/dist/assets/install-donobu-plugin.js +0 -96
- package/dist/assets/playwright-json-to-markdown.js +0 -257
- package/dist/assets/playwright-json-to-slack-json.js +0 -171
- package/dist/clients/GoogleGptClient.d.ts.map +0 -1
- package/dist/clients/GoogleGptClient.js.map +0 -1
- package/dist/esm/assets/install-donobu-plugin.js +0 -96
- package/dist/esm/assets/playwright-json-to-markdown.js +0 -257
- package/dist/esm/assets/playwright-json-to-slack-json.js +0 -171
- package/dist/esm/clients/GoogleGptClient.d.ts.map +0 -1
- package/dist/esm/clients/GoogleGptClient.js.map +0 -1
- package/dist/esm/exceptions/UnparseableJsonBodyException.d.ts +0 -5
- package/dist/esm/exceptions/UnparseableJsonBodyException.d.ts.map +0 -1
- package/dist/esm/exceptions/UnparseableJsonBodyException.js +0 -11
- package/dist/esm/exceptions/UnparseableJsonBodyException.js.map +0 -1
- package/dist/exceptions/UnparseableJsonBodyException.d.ts +0 -5
- package/dist/exceptions/UnparseableJsonBodyException.d.ts.map +0 -1
- package/dist/exceptions/UnparseableJsonBodyException.js +0 -11
- package/dist/exceptions/UnparseableJsonBodyException.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JsonUtils.d.ts","sourceRoot":"","sources":["../../src/utils/JsonUtils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"JsonUtils.d.ts","sourceRoot":"","sources":["../../src/utils/JsonUtils.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,SAAS;IACpB;;;OAGG;IACH,OAAO;IAEP;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;WACW,YAAY,CAAC,MAAM,EAAE,GAAG,GAAG,GAAG;IA2F5C;;;;;;;;;;;;;;;;;;;OAmBG;WACW,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG;IAUrD;;;;;;;;;;;;;;;;;OAiBG;WACW,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI;CAQrE"}
|
package/dist/utils/JsonUtils.js
CHANGED
|
@@ -1,15 +1,68 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.JsonUtils = void 0;
|
|
7
4
|
const MiscUtils_1 = require("./MiscUtils");
|
|
8
|
-
const path_1 = __importDefault(require("path"));
|
|
9
5
|
const Logger_1 = require("./Logger");
|
|
10
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Utility class for JSON operations including serialization, parsing, and safe object conversion.
|
|
8
|
+
*
|
|
9
|
+
* Provides comprehensive JSON handling capabilities including:
|
|
10
|
+
* - Safe object-to-JSON conversion with circular reference detection
|
|
11
|
+
* - Resource file reading and parsing with error handling
|
|
12
|
+
* - JSON string parsing with graceful error recovery
|
|
13
|
+
*
|
|
14
|
+
* All methods handle errors gracefully and provide appropriate logging.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* // Safe object serialization
|
|
19
|
+
* const obj = { name: 'test', date: new Date() };
|
|
20
|
+
* const safeJson = JsonUtils.objectToJson(obj);
|
|
21
|
+
*
|
|
22
|
+
* // Read JSON from resource file
|
|
23
|
+
* const config = JsonUtils.readResourceAsJson('config.json');
|
|
24
|
+
*
|
|
25
|
+
* // Parse JSON string safely
|
|
26
|
+
* const parsed = JsonUtils.jsonStringToJsonObject('{"key": "value"}');
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @since 1.0.0
|
|
30
|
+
*/
|
|
11
31
|
class JsonUtils {
|
|
32
|
+
/**
|
|
33
|
+
* Private constructor to prevent instantiation of this utility class.
|
|
34
|
+
* All methods are static and should be called directly on the class.
|
|
35
|
+
*/
|
|
12
36
|
constructor() { }
|
|
37
|
+
/**
|
|
38
|
+
* Converts an object to a JSON-serializable format with comprehensive type handling and circular reference protection.
|
|
39
|
+
*
|
|
40
|
+
* Handles special cases including:
|
|
41
|
+
* - Date objects (converted to ISO strings)
|
|
42
|
+
* - RegExp objects (converted to string representation)
|
|
43
|
+
* - Error objects (converted to structured object with name, message, stack)
|
|
44
|
+
* - Node.js-specific objects (Timeout, EventEmitter, etc. - converted to descriptive strings)
|
|
45
|
+
* - Circular references (replaced with '[Circular Reference]' string)
|
|
46
|
+
* - Functions and symbols (excluded from output)
|
|
47
|
+
*
|
|
48
|
+
* @param object - The object to convert to JSON-safe format
|
|
49
|
+
* @returns A JSON-serializable version of the input object, or the original value for primitives
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```typescript
|
|
53
|
+
* const complexObj = {
|
|
54
|
+
* date: new Date(),
|
|
55
|
+
* error: new Error('test'),
|
|
56
|
+
* regex: /test/g,
|
|
57
|
+
* func: () => {}, // Will be excluded
|
|
58
|
+
* circular: null as any
|
|
59
|
+
* };
|
|
60
|
+
* complexObj.circular = complexObj; // Create circular reference
|
|
61
|
+
*
|
|
62
|
+
* const safe = JsonUtils.objectToJson(complexObj);
|
|
63
|
+
* // Result: { date: "2023-...", error: {...}, regex: "/test/g", circular: "[Circular Reference]" }
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
13
66
|
static objectToJson(object) {
|
|
14
67
|
// Handle undefined or null
|
|
15
68
|
if (object === undefined || object === null) {
|
|
@@ -85,6 +138,26 @@ class JsonUtils {
|
|
|
85
138
|
};
|
|
86
139
|
return JSON.parse(JSON.stringify(object, replacer));
|
|
87
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* Reads and parses a JSON file from the application's resource directory.
|
|
143
|
+
*
|
|
144
|
+
* Uses MiscUtils to read the file as a string and then parses it as JSON.
|
|
145
|
+
* Provides error handling and logging for file read and parse failures.
|
|
146
|
+
*
|
|
147
|
+
* @param source - The relative path to the JSON resource file
|
|
148
|
+
* @returns The parsed JSON object, or null if reading or parsing fails
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* ```typescript
|
|
152
|
+
* // Read configuration from resources
|
|
153
|
+
* const config = JsonUtils.readResourceAsJson('config/app-settings.json');
|
|
154
|
+
* if (config) {
|
|
155
|
+
* console.log('Config loaded:', config);
|
|
156
|
+
* } else {
|
|
157
|
+
* console.log('Failed to load config');
|
|
158
|
+
* }
|
|
159
|
+
* ```
|
|
160
|
+
*/
|
|
88
161
|
static readResourceAsJson(source) {
|
|
89
162
|
try {
|
|
90
163
|
const jsonString = MiscUtils_1.MiscUtils.getResourceFileAsString(source);
|
|
@@ -95,6 +168,24 @@ class JsonUtils {
|
|
|
95
168
|
return null;
|
|
96
169
|
}
|
|
97
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* Safely parses a JSON string into a JavaScript object.
|
|
173
|
+
*
|
|
174
|
+
* Provides error handling and logging for malformed JSON strings.
|
|
175
|
+
* Returns null instead of throwing an exception when parsing fails.
|
|
176
|
+
*
|
|
177
|
+
* @param jsonString - The JSON string to parse
|
|
178
|
+
* @returns The parsed JavaScript object, or null if parsing fails
|
|
179
|
+
*
|
|
180
|
+
* @example
|
|
181
|
+
* ```typescript
|
|
182
|
+
* const validJson = '{"name": "test", "value": 123}';
|
|
183
|
+
* const invalidJson = '{name: "test"}'; // Missing quotes
|
|
184
|
+
*
|
|
185
|
+
* const obj1 = JsonUtils.jsonStringToJsonObject(validJson); // Returns object
|
|
186
|
+
* const obj2 = JsonUtils.jsonStringToJsonObject(invalidJson); // Returns null
|
|
187
|
+
* ```
|
|
188
|
+
*/
|
|
98
189
|
static jsonStringToJsonObject(jsonString) {
|
|
99
190
|
try {
|
|
100
191
|
return JSON.parse(jsonString);
|
|
@@ -104,78 +195,6 @@ class JsonUtils {
|
|
|
104
195
|
return null;
|
|
105
196
|
}
|
|
106
197
|
}
|
|
107
|
-
/**
|
|
108
|
-
* Post-process the given schema to conform with OpenAI constraints
|
|
109
|
-
* @see https://platform.openai.com/docs/guides/structured-outputs/additionalproperties-false-must-always-be-set-in-objects
|
|
110
|
-
*/
|
|
111
|
-
static postProcessJsonSchema(schema) {
|
|
112
|
-
if (schema.type === 'object') {
|
|
113
|
-
schema.additionalProperties = false;
|
|
114
|
-
if (schema.properties) {
|
|
115
|
-
const properties = schema.properties;
|
|
116
|
-
schema.required = schema.required || [];
|
|
117
|
-
Object.entries(properties).forEach(([fieldName, fieldSchema]) => {
|
|
118
|
-
if (!schema.required?.includes(fieldName)) {
|
|
119
|
-
schema.required?.push(fieldName);
|
|
120
|
-
if (typeof fieldSchema.type === 'string') {
|
|
121
|
-
fieldSchema.type = [fieldSchema.type, 'null'];
|
|
122
|
-
}
|
|
123
|
-
else if (Array.isArray(fieldSchema.type) &&
|
|
124
|
-
!fieldSchema.type.includes('null')) {
|
|
125
|
-
fieldSchema.type.push('null');
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
// Recursively process nested schemas
|
|
132
|
-
if (schema.properties) {
|
|
133
|
-
Object.values(schema.properties).forEach((prop) => {
|
|
134
|
-
if (typeof prop === 'object') {
|
|
135
|
-
this.postProcessJsonSchema(prop);
|
|
136
|
-
}
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
if (schema.items) {
|
|
140
|
-
const items = Array.isArray(schema.items) ? schema.items : [schema.items];
|
|
141
|
-
items.forEach((item) => {
|
|
142
|
-
if (typeof item === 'object') {
|
|
143
|
-
this.postProcessJsonSchema(item);
|
|
144
|
-
}
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* Ensures the given file path exists. If the file does not initially exist,
|
|
150
|
-
* all directories to it will be created and the file will be created with a
|
|
151
|
-
* value of an empty JSON object (AKA {}).
|
|
152
|
-
*/
|
|
153
|
-
static async maybeInitEmptyJsonFile(filePath) {
|
|
154
|
-
// Ensure the directory exists
|
|
155
|
-
const directory = path_1.default.dirname(filePath);
|
|
156
|
-
await promises_1.default
|
|
157
|
-
.mkdir(directory, { recursive: true })
|
|
158
|
-
.catch((dirError) => {
|
|
159
|
-
// Directory already exists, continue...
|
|
160
|
-
if (dirError.code !== 'EEXIST') {
|
|
161
|
-
throw dirError;
|
|
162
|
-
}
|
|
163
|
-
});
|
|
164
|
-
// Try to access the file to check if it exists
|
|
165
|
-
try {
|
|
166
|
-
await promises_1.default.access(filePath);
|
|
167
|
-
}
|
|
168
|
-
catch (error) {
|
|
169
|
-
const fsError = error;
|
|
170
|
-
// File doesn't exist, create it.
|
|
171
|
-
if (fsError.code === 'ENOENT') {
|
|
172
|
-
await promises_1.default.writeFile(filePath, '{}', 'utf8');
|
|
173
|
-
}
|
|
174
|
-
else {
|
|
175
|
-
throw error;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
198
|
}
|
|
180
199
|
exports.JsonUtils = JsonUtils;
|
|
181
200
|
//# sourceMappingURL=JsonUtils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JsonUtils.js","sourceRoot":"","sources":["../../src/utils/JsonUtils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"JsonUtils.js","sourceRoot":"","sources":["../../src/utils/JsonUtils.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "donobu",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.31.0",
|
|
4
4
|
"description": "Create browser automations with an LLM agent and replay them as Playwright scripts.",
|
|
5
5
|
"main": "dist/main.js",
|
|
6
6
|
"module": "dist/esm/main.js",
|
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
"types": "./dist/main.d.ts"
|
|
12
12
|
},
|
|
13
13
|
"bin": {
|
|
14
|
-
"playwright-json-to-markdown": "./dist/
|
|
15
|
-
"playwright-json-to-slack-json": "./dist/
|
|
16
|
-
"install-donobu-plugin": "./dist/
|
|
14
|
+
"playwright-json-to-markdown": "./dist/cli/playwright-json-to-markdown.js",
|
|
15
|
+
"playwright-json-to-slack-json": "./dist/cli/playwright-json-to-slack-json.js",
|
|
16
|
+
"install-donobu-plugin": "./dist/cli/install-donobu-plugin.js"
|
|
17
17
|
},
|
|
18
18
|
"scripts": {
|
|
19
19
|
"clean": "rm -rf dist && rm -rf donobu-tool-plugins-for-docker",
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"license": "UNLICENSED",
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@eslint/js": "^9.17.0",
|
|
44
|
+
"@playwright/test": "1.53.2",
|
|
44
45
|
"@types/better-sqlite3": "^7.6.12",
|
|
45
46
|
"@types/express": "^5.0.0",
|
|
46
47
|
"@types/glob": "^8.1.0",
|
|
@@ -60,20 +61,20 @@
|
|
|
60
61
|
"jest": "^29.7.0",
|
|
61
62
|
"js-yaml": "^4.1.0",
|
|
62
63
|
"open": "^10.1.0",
|
|
64
|
+
"playwright": "1.53.2",
|
|
63
65
|
"slugify": "^1.6.6",
|
|
64
66
|
"ts-jest": "^29.3.0",
|
|
65
67
|
"ts-node": "^10.9.2",
|
|
66
|
-
"typescript-eslint": "^8.28.0"
|
|
67
|
-
"playwright": "1.53.2",
|
|
68
|
-
"@playwright/test": "1.53.2"
|
|
68
|
+
"typescript-eslint": "^8.28.0"
|
|
69
69
|
},
|
|
70
70
|
"dependencies": {
|
|
71
71
|
"@ai-sdk/amazon-bedrock": "^2.2.8",
|
|
72
|
-
"@ai-sdk/google": "^1.2.
|
|
72
|
+
"@ai-sdk/google": "^1.2.22",
|
|
73
|
+
"@ai-sdk/google-vertex": "^2.2.27",
|
|
73
74
|
"@aws-sdk/client-s3": "^3.750.0",
|
|
74
75
|
"@google-cloud/storage": "^7.15.2",
|
|
75
76
|
"@types/json-schema": "^7.0.15",
|
|
76
|
-
"ai": "^4.
|
|
77
|
+
"ai": "^4.3.19",
|
|
77
78
|
"better-sqlite3": "^11.8.1",
|
|
78
79
|
"commander": "^13.0.0",
|
|
79
80
|
"express": "^4.21.2",
|
|
@@ -89,8 +90,8 @@
|
|
|
89
90
|
"zod-to-json-schema": "^3.24.5"
|
|
90
91
|
},
|
|
91
92
|
"peerDependencies": {
|
|
92
|
-
"playwright": ">=1.40.0",
|
|
93
|
-
"
|
|
93
|
+
"@playwright/test": ">=1.40.0",
|
|
94
|
+
"playwright": ">=1.40.0"
|
|
94
95
|
},
|
|
95
96
|
"peerDependenciesMeta": {
|
|
96
97
|
"playwright": {
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
const { exec } = require('child_process');
|
|
4
|
-
const { promisify } = require('util');
|
|
5
|
-
const { access, mkdir, rm, cp, readFile } = require('fs/promises');
|
|
6
|
-
const { basename, join } = require('path');
|
|
7
|
-
const { constants } = require('fs');
|
|
8
|
-
|
|
9
|
-
const execAsync = promisify(exec);
|
|
10
|
-
|
|
11
|
-
async function getPluginName() {
|
|
12
|
-
try {
|
|
13
|
-
// First, try to read the plugin name from package.json
|
|
14
|
-
const packageJsonContent = await readFile('package.json', 'utf8');
|
|
15
|
-
const packageJson = JSON.parse(packageJsonContent);
|
|
16
|
-
|
|
17
|
-
if (packageJson.name) {
|
|
18
|
-
console.log(`Using plugin name from package.json: ${packageJson.name}`);
|
|
19
|
-
return packageJson.name;
|
|
20
|
-
}
|
|
21
|
-
} catch (error) {
|
|
22
|
-
console.warn(
|
|
23
|
-
'Could not read package.json name, falling back to git/user detection',
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Fallback to a heuristic
|
|
28
|
-
try {
|
|
29
|
-
const { stdout } = await execAsync('git rev-parse --show-toplevel');
|
|
30
|
-
const repoPath = stdout.trim();
|
|
31
|
-
const gitBasedName = `${basename(repoPath).replace(/\.git$/, '')}-custom-tools`;
|
|
32
|
-
console.log(`Using git-based plugin name: ${gitBasedName}`);
|
|
33
|
-
return gitBasedName;
|
|
34
|
-
} catch {
|
|
35
|
-
const user = process.env.USER || 'unknown-user';
|
|
36
|
-
const userBasedName = `${user}-custom-tools`;
|
|
37
|
-
console.log(`Using user-based plugin name: ${userBasedName}`);
|
|
38
|
-
return userBasedName;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
async function buildPlugin() {
|
|
43
|
-
console.log('Building plugin...');
|
|
44
|
-
await execAsync('npm run build');
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
async function installPlugin() {
|
|
48
|
-
const pluginName = await getPluginName();
|
|
49
|
-
const pluginsDir = join(
|
|
50
|
-
process.env.HOME,
|
|
51
|
-
'Library/Application Support/Donobu Studio/plugins',
|
|
52
|
-
);
|
|
53
|
-
const thisPluginDir = join(pluginsDir, pluginName);
|
|
54
|
-
|
|
55
|
-
console.log(`Installing plugin: ${pluginName}`);
|
|
56
|
-
|
|
57
|
-
// Create plugins directory
|
|
58
|
-
await mkdir(pluginsDir, { recursive: true });
|
|
59
|
-
|
|
60
|
-
// Remove old plugin if exists
|
|
61
|
-
try {
|
|
62
|
-
await rm(thisPluginDir, { recursive: true, force: true });
|
|
63
|
-
} catch (err) {
|
|
64
|
-
// Ignore if directory doesn't exist
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Copy built plugin
|
|
68
|
-
await cp('dist', thisPluginDir, { recursive: true });
|
|
69
|
-
|
|
70
|
-
console.log(`Plugin installed successfully to: ${thisPluginDir}`);
|
|
71
|
-
console.log('Restart Donobu to see the new tools.');
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
async function main() {
|
|
75
|
-
try {
|
|
76
|
-
// Check if we're in a plugin directory
|
|
77
|
-
try {
|
|
78
|
-
await access('package.json', constants.F_OK);
|
|
79
|
-
await access('src', constants.F_OK);
|
|
80
|
-
} catch {
|
|
81
|
-
console.error(
|
|
82
|
-
'Error: This command must be run from a Donobu plugin directory',
|
|
83
|
-
);
|
|
84
|
-
console.error('Make sure you have package.json and src/ directory');
|
|
85
|
-
process.exit(1);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
await buildPlugin();
|
|
89
|
-
await installPlugin();
|
|
90
|
-
} catch (error) {
|
|
91
|
-
console.error('Installation failed:', error.message);
|
|
92
|
-
process.exit(1);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
main();
|
|
@@ -1,257 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Convert Playwright JSON test results to a Markdown report.
|
|
5
|
-
*
|
|
6
|
-
* Usage: node playwright-json-to-markdown.js input.json > report.md
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
const fs = require('fs');
|
|
10
|
-
|
|
11
|
-
function stripAnsiCodes(str) {
|
|
12
|
-
return str.replace(
|
|
13
|
-
/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,
|
|
14
|
-
'',
|
|
15
|
-
);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// Function to format duration in a readable way
|
|
19
|
-
function formatDuration(ms) {
|
|
20
|
-
if (ms < 1000) {
|
|
21
|
-
return `${ms}ms`;
|
|
22
|
-
}
|
|
23
|
-
const seconds = Math.floor(ms / 1000);
|
|
24
|
-
if (seconds < 60) {
|
|
25
|
-
return `${seconds}s`;
|
|
26
|
-
}
|
|
27
|
-
const minutes = Math.floor(seconds / 60);
|
|
28
|
-
const remainingSeconds = seconds % 60;
|
|
29
|
-
return `${minutes}m ${remainingSeconds}s`;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// Read the JSON data from file or stdin
|
|
33
|
-
function readInput() {
|
|
34
|
-
const args = process.argv.slice(2);
|
|
35
|
-
if (args.length > 0) {
|
|
36
|
-
return JSON.parse(fs.readFileSync(args[0], 'utf8'));
|
|
37
|
-
} else {
|
|
38
|
-
return JSON.parse(fs.readFileSync(0, 'utf8')); // Read from stdin
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Process JSON and create markdown
|
|
43
|
-
function generateMarkdown(jsonData) {
|
|
44
|
-
const { suites } = jsonData;
|
|
45
|
-
|
|
46
|
-
// Count self-healed tests
|
|
47
|
-
let selfHealedCount = 0;
|
|
48
|
-
suites.forEach((suite) => {
|
|
49
|
-
suite.specs.forEach((spec) => {
|
|
50
|
-
spec.tests.forEach((test) => {
|
|
51
|
-
if (
|
|
52
|
-
test.annotations &&
|
|
53
|
-
test.annotations.some((a) => a.type === 'self-healed')
|
|
54
|
-
) {
|
|
55
|
-
selfHealedCount++;
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
// Create report header
|
|
62
|
-
let markdown = `# Playwright Test Report\n\n`;
|
|
63
|
-
// Tests by file
|
|
64
|
-
markdown += `## Summary\n\n`;
|
|
65
|
-
|
|
66
|
-
// Create file summary table with status counts
|
|
67
|
-
markdown += `| File | Passed | Self-Healed | Failed | Timed Out | Skipped | Interrupted | Duration |\n`;
|
|
68
|
-
markdown += `| - | - | - | - | - | - | - | - |\n`;
|
|
69
|
-
|
|
70
|
-
// Track totals for summary row
|
|
71
|
-
let totalPassed = 0;
|
|
72
|
-
let totalFailed = 0;
|
|
73
|
-
let totalTimedOut = 0;
|
|
74
|
-
let totalSkipped = 0;
|
|
75
|
-
let totalInterrupted = 0;
|
|
76
|
-
let totalSelfHealed = 0;
|
|
77
|
-
let totalDuration = 0;
|
|
78
|
-
|
|
79
|
-
suites.forEach((suite) => {
|
|
80
|
-
// Count tests by status for this file
|
|
81
|
-
let passed = 0;
|
|
82
|
-
let failed = 0;
|
|
83
|
-
let timedOut = 0;
|
|
84
|
-
let skipped = 0;
|
|
85
|
-
let interrupted = 0;
|
|
86
|
-
let selfHealed = 0;
|
|
87
|
-
|
|
88
|
-
const fileDuration = suite.specs.reduce(
|
|
89
|
-
(total, spec) =>
|
|
90
|
-
total +
|
|
91
|
-
spec.tests.reduce((testTotal, test) => {
|
|
92
|
-
const result = test.results && test.results.at(-1);
|
|
93
|
-
const isSelfHealed =
|
|
94
|
-
test.annotations &&
|
|
95
|
-
test.annotations.some((a) => a.type === 'self-healed');
|
|
96
|
-
|
|
97
|
-
if (
|
|
98
|
-
test.status === 'skipped' ||
|
|
99
|
-
(!result && test.status === undefined)
|
|
100
|
-
) {
|
|
101
|
-
skipped++;
|
|
102
|
-
} else if (result) {
|
|
103
|
-
if (isSelfHealed) {
|
|
104
|
-
selfHealed++;
|
|
105
|
-
} else {
|
|
106
|
-
switch (result.status) {
|
|
107
|
-
case 'passed':
|
|
108
|
-
passed++;
|
|
109
|
-
break;
|
|
110
|
-
case 'failed':
|
|
111
|
-
failed++;
|
|
112
|
-
break;
|
|
113
|
-
case 'timedOut':
|
|
114
|
-
timedOut++;
|
|
115
|
-
break;
|
|
116
|
-
case 'skipped':
|
|
117
|
-
skipped++;
|
|
118
|
-
break;
|
|
119
|
-
case 'interrupted':
|
|
120
|
-
interrupted++;
|
|
121
|
-
break;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return testTotal + (result?.duration || 0);
|
|
127
|
-
}, 0),
|
|
128
|
-
0,
|
|
129
|
-
);
|
|
130
|
-
|
|
131
|
-
// Add to totals
|
|
132
|
-
totalPassed += passed;
|
|
133
|
-
totalFailed += failed;
|
|
134
|
-
totalTimedOut += timedOut;
|
|
135
|
-
totalSkipped += skipped;
|
|
136
|
-
totalInterrupted += interrupted;
|
|
137
|
-
totalSelfHealed += selfHealed;
|
|
138
|
-
totalDuration += fileDuration;
|
|
139
|
-
|
|
140
|
-
markdown += `| ${suite.file} | ${passed ? passed + ' ✅' : ''} | ${selfHealed ? selfHealed + ' ❤️🩹' : ''} | ${failed ? failed + ' ❌' : ''} | ${timedOut ? timedOut + ' ⏰' : ''} | ${skipped ? skipped + ' ⏭️' : ''} | ${interrupted ? interrupted + ' ⚡' : ''} | ${formatDuration(fileDuration)} |\n`;
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
// Add totals row
|
|
144
|
-
markdown += `| **TOTAL** | **${totalPassed + ' ✅'}** | **${totalSelfHealed + ' ❤️🩹'}** | **${totalFailed + ' ❌'}** | **${totalTimedOut + ' ⏰'}** | **${totalSkipped + ' ⏭️'}** | **${totalInterrupted + ' ⚡'}** | **${formatDuration(totalDuration)}** |\n`;
|
|
145
|
-
|
|
146
|
-
markdown += `\n`;
|
|
147
|
-
|
|
148
|
-
// Generate test details sections
|
|
149
|
-
suites.forEach((suite) => {
|
|
150
|
-
const fileName = suite.file;
|
|
151
|
-
markdown += `## ${fileName}\n\n`;
|
|
152
|
-
|
|
153
|
-
suite.specs.forEach((spec) => {
|
|
154
|
-
markdown += `### ${spec.title}\n\n`;
|
|
155
|
-
|
|
156
|
-
spec.tests.forEach((test) => {
|
|
157
|
-
const result = test.results && test.results.at(-1);
|
|
158
|
-
|
|
159
|
-
if (test.status === 'skipped' || !result || test.status === undefined) {
|
|
160
|
-
markdown += `**Status**: ⏭️ Skipped \n`;
|
|
161
|
-
markdown += `**Duration**: N/A \n`;
|
|
162
|
-
// Get objective from annotations if available
|
|
163
|
-
let objective = 'No objective provided';
|
|
164
|
-
|
|
165
|
-
if (test.annotations) {
|
|
166
|
-
const objectiveAnnotation = test.annotations.find(
|
|
167
|
-
(a) => a.type === 'objective',
|
|
168
|
-
);
|
|
169
|
-
if (objectiveAnnotation) {
|
|
170
|
-
objective =
|
|
171
|
-
objectiveAnnotation.description || 'No objective provided';
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// Escape any existing triple backticks in the objective
|
|
176
|
-
objective = objective.replace(/```/g, '\\`\\`\\`');
|
|
177
|
-
markdown += `**Objective**:\n\`\`\`\n${objective}\n\`\`\`\n`;
|
|
178
|
-
markdown += `---\n\n`;
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
const isSelfHealed =
|
|
183
|
-
test.annotations &&
|
|
184
|
-
test.annotations.some((a) => a.type === 'self-healed');
|
|
185
|
-
|
|
186
|
-
// Determine status based on result status and self-healing annotation
|
|
187
|
-
let status;
|
|
188
|
-
if (result.status === 'passed') {
|
|
189
|
-
status = '✅ Passed';
|
|
190
|
-
} else if (isSelfHealed) {
|
|
191
|
-
status = '❌ Failed (❤️🩹 Self-Healed)';
|
|
192
|
-
} else if (result.status === 'failed') {
|
|
193
|
-
status = '❌ Failed';
|
|
194
|
-
} else if (result.status === 'timedOut') {
|
|
195
|
-
status = '⏰ Timed Out';
|
|
196
|
-
} else if (result.status === 'skipped') {
|
|
197
|
-
status = '⏭️ Skipped';
|
|
198
|
-
} else if (result.status === 'interrupted') {
|
|
199
|
-
status = '⚡ Interrupted';
|
|
200
|
-
} else {
|
|
201
|
-
status = `⚠️ ${result.status || 'Unknown'}`;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
const duration = formatDuration(result.duration || 0);
|
|
205
|
-
|
|
206
|
-
// Get objective from annotations if available
|
|
207
|
-
let objective = 'No objective provided';
|
|
208
|
-
if (test.annotations) {
|
|
209
|
-
const objectiveAnnotation = test.annotations.find(
|
|
210
|
-
(a) => a.type === 'objective',
|
|
211
|
-
);
|
|
212
|
-
if (objectiveAnnotation) {
|
|
213
|
-
objective =
|
|
214
|
-
objectiveAnnotation.description || 'No objective provided';
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// Escape any existing triple backticks in the objective by replacing ``` with \`\`\`
|
|
219
|
-
objective = objective.replace(/```/g, '\\`\\`\\`');
|
|
220
|
-
|
|
221
|
-
markdown += `**Status**: ${status} \n`;
|
|
222
|
-
markdown += `**Duration**: ${duration} \n`;
|
|
223
|
-
markdown += `**Objective**:\n\`\`\`\n${objective}\n\`\`\`\n`;
|
|
224
|
-
|
|
225
|
-
// Add error details if test failed
|
|
226
|
-
if (result.status === 'failed' && result.error) {
|
|
227
|
-
markdown += `\n<details>\n<summary>⚠️ Error Details</summary>\n\n`;
|
|
228
|
-
markdown += `\`\`\`\n${result.error.message || 'No error message available'}\n\`\`\`\n\n`;
|
|
229
|
-
|
|
230
|
-
// Include code snippet if available
|
|
231
|
-
if (result.error.snippet) {
|
|
232
|
-
markdown += `**Code Snippet**:\n\`\`\`\n${stripAnsiCodes(result.error.snippet)}\n\`\`\`\n\n`;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
markdown += `</details>\n\n`;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
markdown += `---\n\n`;
|
|
239
|
-
});
|
|
240
|
-
});
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
// Add timestamp footer
|
|
244
|
-
markdown += `_Report generated on ${new Date().toLocaleString()} by Donobu_\n`;
|
|
245
|
-
|
|
246
|
-
return markdown;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// Main execution
|
|
250
|
-
try {
|
|
251
|
-
const jsonData = readInput();
|
|
252
|
-
const markdown = generateMarkdown(jsonData);
|
|
253
|
-
console.log(markdown);
|
|
254
|
-
} catch (error) {
|
|
255
|
-
console.error('Error processing JSON:', error.message);
|
|
256
|
-
process.exit(1);
|
|
257
|
-
}
|