@boltic/cli 1.0.27 → 1.0.28

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
@@ -226,7 +226,9 @@ my-integration/
226
226
  │ ├── base.json
227
227
  │ └── webhook.json
228
228
  ├── Authentication.mdx
229
- ├── Documentation.mdx
229
+ ├── documentation/
230
+ │ ├── integration.mdx
231
+ │ └── trigger.mdx
230
232
  └── spec.json
231
233
  ```
232
234
 
@@ -238,9 +240,11 @@ my-integration/
238
240
  - **`base.json`** - Base integration configuration and parameters
239
241
  - **`webhook.json`** - Webhook configuration (for trigger integrations)
240
242
 
241
- - **`Authentication.mdx`** - Authentication documentation in Markdown format
242
- - **`Documentation.mdx`** - General integration documentation
243
- - **`spec.json`** - Integration specification and metadata
243
+ **Documentation files:**
244
+ - `Authentication.mdx` - Authentication documentation in Markdown format (optional, created when catalogue is enabled)
245
+ - `documentation/integration.mdx` - Activity documentation (required when activity_type is present; falls back to legacy `Documentation.mdx`)
246
+ - `documentation/trigger.mdx` - Trigger documentation (required when trigger_type is "CloudTrigger")
247
+ - `spec.json` - Integration specification and metadata
244
248
 
245
249
  ### Managing Existing Integrations
246
250
 
@@ -447,7 +451,7 @@ boltic --verbose login
447
451
 
448
452
  ```bash
449
453
  # Verify project structure
450
- ls -la # Should show: schemas/, Authentication.mdx, Documentation.mdx, spec.json
454
+ ls -la # Should show: schemas/, Authentication.mdx (optional), documentation/, spec.json
451
455
 
452
456
  # Check file permissions
453
457
  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.27",
3
+ "version": "1.0.28",
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": {
@@ -27,12 +27,6 @@
27
27
  "email": "ahmedsakri@gofynd.com",
28
28
  "url": "https://github.com/ahmedsakri"
29
29
  },
30
- "contributors": [
31
- {
32
- "name": "Boltic Team",
33
- "url": "https://www.boltic.io"
34
- }
35
- ],
36
30
  "repository": {
37
31
  "type": "git",
38
32
  "url": "https://github.com/bolticio/cli.git",