@boltic/cli 1.0.26 → 1.0.27-1

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/README.md CHANGED
@@ -225,7 +225,9 @@ my-integration/
225
225
  │ ├── base.json
226
226
  │ └── webhook.json
227
227
  ├── Authentication.mdx
228
- ├── Documentation.mdx
228
+ ├── documentation/
229
+ │ ├── integration.mdx
230
+ │ └── trigger.mdx
229
231
  └── spec.json
230
232
  ```
231
233
 
@@ -237,9 +239,11 @@ my-integration/
237
239
  - **`base.json`** - Base integration configuration and parameters
238
240
  - **`webhook.json`** - Webhook configuration (for trigger integrations)
239
241
 
240
- - **`Authentication.mdx`** - Authentication documentation in Markdown format
241
- - **`Documentation.mdx`** - General integration documentation
242
- - **`spec.json`** - Integration specification and metadata
242
+ **Documentation files:**
243
+ - `Authentication.mdx` - Authentication documentation in Markdown format (optional, created when catalogue is enabled)
244
+ - `documentation/integration.mdx` - Activity documentation (required when activity_type is present; falls back to legacy `Documentation.mdx`)
245
+ - `documentation/trigger.mdx` - Trigger documentation (required when trigger_type is "CloudTrigger")
246
+ - `spec.json` - Integration specification and metadata
243
247
 
244
248
  ### Managing Existing Integrations
245
249
 
@@ -419,7 +423,7 @@ boltic --verbose login
419
423
 
420
424
  ```bash
421
425
  # Verify project structure
422
- ls -la # Should show: schemas/, Authentication.mdx, Documentation.mdx, spec.json
426
+ ls -la # Should show: schemas/, Authentication.mdx (optional), documentation/, spec.json
423
427
 
424
428
  # Check file permissions
425
429
  ls -la schemas/
@@ -114,6 +114,16 @@ async function readSchemaFiles(currentDir) {
114
114
  // Read documentation files
115
115
  const authDocPath = path.join(currentDir, "Authentication.mdx");
116
116
  const generalDocPath = path.join(currentDir, "Documentation.mdx");
117
+ const docsIntegrationPath = path.join(
118
+ currentDir,
119
+ "documentation",
120
+ "integration.mdx"
121
+ );
122
+ const docsTriggerPath = path.join(
123
+ currentDir,
124
+ "documentation",
125
+ "trigger.mdx"
126
+ );
117
127
 
118
128
  if (fs.existsSync(authDocPath)) {
119
129
  schemas.authentication_documentation = fs.readFileSync(
@@ -122,8 +132,22 @@ async function readSchemaFiles(currentDir) {
122
132
  );
123
133
  }
124
134
 
125
- if (fs.existsSync(generalDocPath)) {
126
- schemas.documentation = fs.readFileSync(generalDocPath, "utf8");
135
+ // Build documentation object with backward compatibility
136
+ const documentation = {};
137
+ if (fs.existsSync(docsIntegrationPath)) {
138
+ documentation.integration = fs.readFileSync(
139
+ docsIntegrationPath,
140
+ "utf8"
141
+ );
142
+ } else if (fs.existsSync(generalDocPath)) {
143
+ // Fallback to legacy Documentation.mdx
144
+ documentation.integration = fs.readFileSync(generalDocPath, "utf8");
145
+ }
146
+ if (fs.existsSync(docsTriggerPath)) {
147
+ documentation.trigger = fs.readFileSync(docsTriggerPath, "utf8");
148
+ }
149
+ if (Object.keys(documentation).length > 0) {
150
+ schemas.documentation = documentation;
127
151
  }
128
152
 
129
153
  return schemas;
@@ -1091,7 +1115,25 @@ async function handleStatus() {
1091
1115
 
1092
1116
  if (integration.documentation) {
1093
1117
  console.log(chalk.cyan("\nDocumentation:"));
1094
- console.log(integration.documentation);
1118
+ if (
1119
+ typeof integration.documentation === "object" &&
1120
+ integration.documentation !== null
1121
+ ) {
1122
+ if (integration.documentation.integration) {
1123
+ console.log(
1124
+ chalk.dim("integration.mdx:\n") +
1125
+ integration.documentation.integration
1126
+ );
1127
+ }
1128
+ if (integration.documentation.trigger) {
1129
+ console.log(
1130
+ chalk.dim("\ntrigger.mdx:\n") +
1131
+ integration.documentation.trigger
1132
+ );
1133
+ }
1134
+ } else {
1135
+ console.log(integration.documentation);
1136
+ }
1095
1137
  }
1096
1138
  } catch (error) {
1097
1139
  if (
package/helper/folder.js CHANGED
@@ -47,6 +47,9 @@ export const createIntegrationFolderStructure = async (
47
47
  const resourcesDir = path.join(schemasDir, "resources");
48
48
  fs.mkdirSync(resourcesDir, { recursive: true });
49
49
 
50
+ const docsDir = path.join(integrationDir, "documentation");
51
+ fs.mkdirSync(docsDir, { recursive: true });
52
+
50
53
  // Create template files
51
54
  const files = {
52
55
  "schemas/resources/resource1.json": JSON.stringify(resource1, null, 4),
@@ -69,7 +72,13 @@ export const createIntegrationFolderStructure = async (
69
72
  ...(create_catalogue && {
70
73
  "Authentication.mdx": `# ${name} Authentication`,
71
74
  }),
72
- "Documentation.mdx": `# ${name} Documentation`,
75
+ // Documentation files (new structure)
76
+ ...(!isEmpty(activity_type) && {
77
+ "documentation/integration.mdx": `# ${name} Integration`,
78
+ }),
79
+ ...(trigger_type === "CloudTrigger" && {
80
+ "documentation/trigger.mdx": `# ${name} Trigger`,
81
+ }),
73
82
  };
74
83
 
75
84
  // Create all files
@@ -147,7 +156,14 @@ export const createExistingIntegrationsFolder = async (payload) => {
147
156
  const resourcesDir = path.join(schemasDir, "resources");
148
157
  fs.mkdirSync(resourcesDir, { recursive: true });
149
158
 
159
+ const docsDir = path.join(integrationDir, "documentation");
160
+ fs.mkdirSync(docsDir, { recursive: true });
161
+
150
162
  const authentication_documentation = authentication?.documentation || "";
163
+ const isDocumentationObject =
164
+ documentation &&
165
+ typeof documentation === "object" &&
166
+ !Array.isArray(documentation);
151
167
 
152
168
  // Define files and content
153
169
  const files = {
@@ -168,7 +184,17 @@ export const createExistingIntegrationsFolder = async (payload) => {
168
184
  ...(authentication && {
169
185
  "Authentication.mdx": authentication_documentation || "",
170
186
  }),
171
- "Documentation.mdx": documentation || "",
187
+ ...(!isEmpty(activity_type) && {
188
+ "documentation/integration.mdx": isDocumentationObject
189
+ ? documentation?.integration || `# ${name} Integration`
190
+ : (typeof documentation === "string" && documentation) ||
191
+ `# ${name} Integration`,
192
+ }),
193
+ ...(trigger_type === "CloudTrigger" && {
194
+ "documentation/trigger.mdx": isDocumentationObject
195
+ ? documentation?.trigger || `# ${name} Trigger`
196
+ : `# ${name} Trigger`,
197
+ }),
172
198
  };
173
199
 
174
200
  // Write resource files
@@ -0,0 +1,32 @@
1
+ import fs from "fs";
2
+
3
+ const hasBalancedCodeFences = (content) => {
4
+ const fenceCount = (content.match(/```/g) || []).length;
5
+ return fenceCount % 2 === 0;
6
+ };
7
+
8
+ export const validateMarkdownString = (content, fileLabel, errors) => {
9
+ const label = fileLabel || "markdown";
10
+ if (!content || !content.trim()) {
11
+ errors.add(`"${label}" is empty.`);
12
+ return false;
13
+ }
14
+ // Keep checks minimal to avoid false positives in CLI usage
15
+ if (!hasBalancedCodeFences(content)) {
16
+ errors.add('"' + label + '" has unbalanced code fences (```).');
17
+ }
18
+ return true;
19
+ };
20
+
21
+ export const validateMarkdownFile = (filePath, errors, label) => {
22
+ try {
23
+ if (!fs.existsSync(filePath)) return false;
24
+ const content = fs.readFileSync(filePath, "utf8");
25
+ return validateMarkdownString(content, label || filePath, errors);
26
+ } catch (e) {
27
+ errors.add(
28
+ `Failed to read markdown file "${label || filePath}": ${e.message}`
29
+ );
30
+ return false;
31
+ }
32
+ };
@@ -2,6 +2,7 @@ import fs from "fs";
2
2
  import isEmpty from "lodash.isempty";
3
3
  import path from "path";
4
4
  import * as componentSchemas from "../templates/component-schemas.js";
5
+ import { validateMarkdownFile } from "./markdown.js";
5
6
 
6
7
  const validateOptionObject = (options, fieldName, fileLabel, errors) => {
7
8
  options.forEach((opt, index) => {
@@ -325,9 +326,82 @@ const validateComponentSchemas = (schemas, errors, filename = "") => {
325
326
  // INDIVIDUAL VALIDATORS
326
327
  // ─────────────────────────────────────────────────────────────────────────────
327
328
 
328
- const validateDocumentation = (docPath, errors) => {
329
- if (!fs.existsSync(docPath)) {
330
- errors.add(`"Documentation.mdx" not found in the root directory.`);
329
+ const validateDocumentation = (currentDir, spec, errors) => {
330
+ const docsIntegrationPath = path.join(
331
+ currentDir,
332
+ "documentation",
333
+ "integration.mdx"
334
+ );
335
+ const docsTriggerPath = path.join(
336
+ currentDir,
337
+ "documentation",
338
+ "trigger.mdx"
339
+ );
340
+ const legacyDocPath = path.join(currentDir, "Documentation.mdx");
341
+
342
+ const requiresIntegrationDoc = spec && !isEmpty(spec.activity_type);
343
+ const requiresTriggerDoc = spec && spec.trigger_type === "CloudTrigger";
344
+
345
+ // Backward-compatibility: if nothing specific is required by spec,
346
+ // ensure at least legacy Documentation.mdx or new docs exist
347
+ const hasLegacy = fs.existsSync(legacyDocPath);
348
+ const hasNewIntegration = fs.existsSync(docsIntegrationPath);
349
+ const hasNewTrigger = fs.existsSync(docsTriggerPath);
350
+
351
+ if (!requiresIntegrationDoc && !requiresTriggerDoc) {
352
+ if (!hasLegacy && !hasNewIntegration && !hasNewTrigger) {
353
+ errors.add('"Documentation.mdx" not found in the root directory.');
354
+ return; // No further checks needed
355
+ }
356
+ // If files exist, validate whatever is present
357
+ if (hasLegacy) {
358
+ validateMarkdownFile(legacyDocPath, errors, "Documentation.mdx");
359
+ }
360
+ if (hasNewIntegration) {
361
+ validateMarkdownFile(
362
+ docsIntegrationPath,
363
+ errors,
364
+ "documentation/integration.mdx"
365
+ );
366
+ }
367
+ if (hasNewTrigger) {
368
+ validateMarkdownFile(
369
+ docsTriggerPath,
370
+ errors,
371
+ "documentation/trigger.mdx"
372
+ );
373
+ }
374
+ return;
375
+ }
376
+
377
+ if (requiresIntegrationDoc) {
378
+ const hasNew = validateMarkdownFile(
379
+ docsIntegrationPath,
380
+ errors,
381
+ "documentation/integration.mdx"
382
+ );
383
+ const hasLegacyValidated = validateMarkdownFile(
384
+ legacyDocPath,
385
+ errors,
386
+ "Documentation.mdx"
387
+ );
388
+ if (!hasNew && !hasLegacyValidated) {
389
+ // Maintain backward-compatible error message expected by tests
390
+ errors.add('"Documentation.mdx" not found in the root directory.');
391
+ }
392
+ }
393
+
394
+ if (requiresTriggerDoc) {
395
+ const hasTrigger = validateMarkdownFile(
396
+ docsTriggerPath,
397
+ errors,
398
+ "documentation/trigger.mdx"
399
+ );
400
+ if (!hasTrigger) {
401
+ errors.add(
402
+ '"documentation/trigger.mdx" not found when trigger_type is "CloudTrigger".'
403
+ );
404
+ }
331
405
  }
332
406
  };
333
407
 
@@ -525,13 +599,11 @@ export const validateIntegrationSchemas = (currentDir) => {
525
599
  spec: path.join(currentDir, "spec.json"),
526
600
  webhook: path.join(currentDir, "schemas", "webhook.json"),
527
601
  authentication: path.join(currentDir, "schemas", "authentication.json"),
528
- documentation: path.join(currentDir, "Documentation.mdx"),
529
602
  };
530
603
 
531
604
  // Step-by-step validation
532
- validateDocumentation(paths.documentation, errors);
533
-
534
605
  const spec = validateSpec(paths.spec, errors);
606
+ validateDocumentation(currentDir, spec, errors);
535
607
  validateWebhook(paths.webhook, spec, errors);
536
608
  validateAuthentication(paths.authentication, errors);
537
609
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@boltic/cli",
3
- "version": "1.0.26",
3
+ "version": "1.0.27-1",
4
4
  "description": "A powerful CLI tool for managing Boltic Workflow integrations - create, sync, test, and publish integrations with ease",
5
5
  "main": "index.js",
6
6
  "bin": {