@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 +9 -5
- package/commands/integration.js +45 -3
- package/helper/folder.js +28 -2
- package/helper/markdown.js +32 -0
- package/helper/validation.js +78 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -225,7 +225,9 @@ my-integration/
|
|
|
225
225
|
│ ├── base.json
|
|
226
226
|
│ └── webhook.json
|
|
227
227
|
├── Authentication.mdx
|
|
228
|
-
├──
|
|
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
|
-
|
|
241
|
-
-
|
|
242
|
-
-
|
|
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
|
|
426
|
+
ls -la # Should show: schemas/, Authentication.mdx (optional), documentation/, spec.json
|
|
423
427
|
|
|
424
428
|
# Check file permissions
|
|
425
429
|
ls -la schemas/
|
package/commands/integration.js
CHANGED
|
@@ -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
|
-
|
|
126
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
};
|
package/helper/validation.js
CHANGED
|
@@ -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 = (
|
|
329
|
-
|
|
330
|
-
|
|
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