@boltic/cli 1.0.6-beta.0 → 1.0.6-beta.11
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/LICENSE +21 -0
- package/README.md +1 -4
- package/cli.js +21 -11
- package/commands/integration.js +146 -4
- package/commands/login.js +1 -1
- package/helper/env.js +1 -1
- package/helper/folder.js +19 -4
- package/helper/validation.js +17 -0
- package/package.json +13 -5
- package/templates/schemas.js +23 -5
- package/utils/integration.js +1 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Boltic.io
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
> A powerful CLI tool for creating, managing, and publishing Boltic integrations.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@boltic/cli)
|
|
6
|
+
[](https://github.com/<your-username>/<your-repo>)
|
|
6
7
|
[](./LICENSE)
|
|
7
|
-
[](https://nodejs.org/)
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
@@ -43,17 +43,14 @@ You’ll be prompted to enter:
|
|
|
43
43
|
- **Name**: Letters and underscores only (e.g., My_Integration)
|
|
44
44
|
- **Icon**: Select an SVG file from your computer
|
|
45
45
|
- **Integration Type**:
|
|
46
|
-
|
|
47
46
|
- Workflow Activity: Reusable components that perform specific tasks
|
|
48
47
|
- Workflow Trigger: Components that start your workflow based on external events
|
|
49
48
|
- You can choose to create both types for the same integration
|
|
50
49
|
|
|
51
50
|
- **Descriptions**
|
|
52
|
-
|
|
53
51
|
- Human-readable and AI-generated
|
|
54
52
|
|
|
55
53
|
- **Integration Group**
|
|
56
|
-
|
|
57
54
|
- e.g., Analytics, CRM, ERP, Marketing, Payment, Social Media, Other
|
|
58
55
|
|
|
59
56
|
### ✏️ Edit an Integration
|
package/cli.js
CHANGED
|
@@ -14,7 +14,8 @@ const createCLI = (consoleUrl, apiUrl, serviceName, env) => {
|
|
|
14
14
|
const commands = {
|
|
15
15
|
login: {
|
|
16
16
|
description: "Authenticate the user and save access token",
|
|
17
|
-
action: () =>
|
|
17
|
+
action: async () =>
|
|
18
|
+
await AuthCommands.handleLogin(consoleUrl, apiUrl, env),
|
|
18
19
|
},
|
|
19
20
|
integration: {
|
|
20
21
|
description: "Manage integrations (create, list)",
|
|
@@ -74,9 +75,10 @@ const createCLI = (consoleUrl, apiUrl, serviceName, env) => {
|
|
|
74
75
|
return;
|
|
75
76
|
}
|
|
76
77
|
|
|
77
|
-
// Check if user is authenticated for all commands except login, help, and version
|
|
78
|
+
// Check if user is authenticated for all commands except login, logout, help, and version
|
|
78
79
|
if (
|
|
79
80
|
command !== "login" &&
|
|
81
|
+
command !== "logout" &&
|
|
80
82
|
command !== "help" &&
|
|
81
83
|
command !== "version"
|
|
82
84
|
) {
|
|
@@ -112,7 +114,7 @@ async function showHelp(commands) {
|
|
|
112
114
|
packageJson = JSON.parse(
|
|
113
115
|
fs.readFileSync(path.join(process.cwd(), "package.json"))
|
|
114
116
|
);
|
|
115
|
-
} catch
|
|
117
|
+
} catch {
|
|
116
118
|
// Fallback version if package.json not found
|
|
117
119
|
packageJson = { version: "1.0.0" };
|
|
118
120
|
}
|
|
@@ -139,17 +141,25 @@ async function handleEnvironment(args) {
|
|
|
139
141
|
}
|
|
140
142
|
|
|
141
143
|
async function showVersion() {
|
|
142
|
-
let
|
|
144
|
+
let version = "1.0.0"; // default fallback
|
|
143
145
|
try {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
146
|
+
let packageJsonPath;
|
|
147
|
+
if (typeof import.meta !== "undefined" && import.meta.url) {
|
|
148
|
+
// ES modules in Node.js
|
|
149
|
+
const currentDir = path.dirname(new URL(import.meta.url).pathname);
|
|
150
|
+
packageJsonPath = path.join(currentDir, "package.json");
|
|
151
|
+
} else {
|
|
152
|
+
// Jest or other environments
|
|
153
|
+
packageJsonPath = path.join(process.cwd(), "package.json");
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const packageJson = JSON.parse(
|
|
157
|
+
fs.readFileSync(packageJsonPath, "utf-8")
|
|
147
158
|
);
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
159
|
+
version = packageJson.version;
|
|
160
|
+
} catch {
|
|
161
|
+
// fallback already defined
|
|
151
162
|
}
|
|
152
|
-
const version = packageJson.version;
|
|
153
163
|
console.log(`Boltic CLI Version: ${version}`);
|
|
154
164
|
}
|
|
155
165
|
|
package/commands/integration.js
CHANGED
|
@@ -50,6 +50,10 @@ const commands = {
|
|
|
50
50
|
description: "Show detailed information about an integration",
|
|
51
51
|
action: handleStatus,
|
|
52
52
|
},
|
|
53
|
+
test: {
|
|
54
|
+
description: "Run tests for the integration",
|
|
55
|
+
action: handleTest,
|
|
56
|
+
},
|
|
53
57
|
help: {
|
|
54
58
|
description: "Show help for integration commands",
|
|
55
59
|
action: showHelp,
|
|
@@ -147,6 +151,19 @@ async function handleSync(args) {
|
|
|
147
151
|
if (fs.existsSync(specPath)) {
|
|
148
152
|
const specContent = JSON.parse(fs.readFileSync(specPath, "utf8"));
|
|
149
153
|
// Update integration with spec.json content
|
|
154
|
+
|
|
155
|
+
if (
|
|
156
|
+
specContent.trigger_type &&
|
|
157
|
+
specContent.trigger_type !== "CloudTrigger"
|
|
158
|
+
) {
|
|
159
|
+
console.error(
|
|
160
|
+
chalk.red(
|
|
161
|
+
`Error: Invalid trigger_type "${specContent.trigger_type}". It should be "CloudTrigger" or null.`
|
|
162
|
+
)
|
|
163
|
+
);
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
|
|
150
167
|
const updatedIntegration = await updateIntegration(
|
|
151
168
|
apiUrl,
|
|
152
169
|
token,
|
|
@@ -245,6 +262,19 @@ async function handlePublish(args) {
|
|
|
245
262
|
if (fs.existsSync(specPath)) {
|
|
246
263
|
const specContent = JSON.parse(fs.readFileSync(specPath, "utf8"));
|
|
247
264
|
// Update integration with spec.json content
|
|
265
|
+
|
|
266
|
+
if (
|
|
267
|
+
specContent.trigger_type &&
|
|
268
|
+
specContent.trigger_type !== "CloudTrigger"
|
|
269
|
+
) {
|
|
270
|
+
console.error(
|
|
271
|
+
chalk.red(
|
|
272
|
+
`Error: Invalid trigger_type "${specContent.trigger_type}". It should be "CloudTrigger" or null.`
|
|
273
|
+
)
|
|
274
|
+
);
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
|
|
248
278
|
const updatedIntegration = await updateIntegration(
|
|
249
279
|
apiUrl,
|
|
250
280
|
token,
|
|
@@ -574,7 +604,10 @@ async function handleCreate() {
|
|
|
574
604
|
);
|
|
575
605
|
|
|
576
606
|
// Create folder structure with the integration name
|
|
577
|
-
await createIntegrationFolderStructure(
|
|
607
|
+
await createIntegrationFolderStructure(
|
|
608
|
+
integration,
|
|
609
|
+
create_catalogue
|
|
610
|
+
);
|
|
578
611
|
|
|
579
612
|
// Also share Documentation URL to the user: https://docs.boltic.io/docs/integration-builder/develop/boilerplate
|
|
580
613
|
const documentationUrl =
|
|
@@ -638,7 +671,12 @@ async function handleEdit() {
|
|
|
638
671
|
const choices =
|
|
639
672
|
integrations
|
|
640
673
|
.filter((integration) =>
|
|
641
|
-
[
|
|
674
|
+
[
|
|
675
|
+
"customActivity",
|
|
676
|
+
"CloudTrigger",
|
|
677
|
+
"applicationFdkActivity",
|
|
678
|
+
"platformFdkActivity",
|
|
679
|
+
].includes(
|
|
642
680
|
integration.activity_type || integration.trigger_type
|
|
643
681
|
)
|
|
644
682
|
)
|
|
@@ -793,7 +831,12 @@ async function handlePull(args) {
|
|
|
793
831
|
const choices =
|
|
794
832
|
integrations
|
|
795
833
|
.filter((integration) =>
|
|
796
|
-
[
|
|
834
|
+
[
|
|
835
|
+
"customActivity",
|
|
836
|
+
"CloudTrigger",
|
|
837
|
+
"applicationFdkActivity",
|
|
838
|
+
"platformFdkActivity",
|
|
839
|
+
].includes(
|
|
797
840
|
integration.activity_type ||
|
|
798
841
|
integration.trigger_type
|
|
799
842
|
)
|
|
@@ -899,7 +942,12 @@ async function handleStatus() {
|
|
|
899
942
|
const choices =
|
|
900
943
|
integrations
|
|
901
944
|
.filter((integration) =>
|
|
902
|
-
[
|
|
945
|
+
[
|
|
946
|
+
"customActivity",
|
|
947
|
+
"CloudTrigger",
|
|
948
|
+
"applicationFdkActivity",
|
|
949
|
+
"platformFdkActivity",
|
|
950
|
+
].includes(
|
|
903
951
|
integration.activity_type || integration.trigger_type
|
|
904
952
|
)
|
|
905
953
|
)
|
|
@@ -985,6 +1033,100 @@ async function handleStatus() {
|
|
|
985
1033
|
}
|
|
986
1034
|
}
|
|
987
1035
|
|
|
1036
|
+
async function handleTest(args) {
|
|
1037
|
+
// Parse command line arguments
|
|
1038
|
+
let currentDir = process.cwd();
|
|
1039
|
+
const pathIndex = args.indexOf("--path");
|
|
1040
|
+
|
|
1041
|
+
if (pathIndex !== -1 && args[pathIndex + 1]) {
|
|
1042
|
+
currentDir = args[pathIndex + 1];
|
|
1043
|
+
// Validate the provided path
|
|
1044
|
+
if (!fs.existsSync(currentDir)) {
|
|
1045
|
+
console.error(
|
|
1046
|
+
chalk.red(
|
|
1047
|
+
`Error: The specified path does not exist: ${currentDir}`
|
|
1048
|
+
)
|
|
1049
|
+
);
|
|
1050
|
+
return;
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
const { spawn } = await import("child_process");
|
|
1055
|
+
|
|
1056
|
+
console.log(chalk.cyan.bold("\n🧪 Running integration tests...\n"));
|
|
1057
|
+
|
|
1058
|
+
// Look for test directory
|
|
1059
|
+
const testDirs = ["test", "tests", "__tests__"];
|
|
1060
|
+
let testDir = null;
|
|
1061
|
+
|
|
1062
|
+
for (const dir of testDirs) {
|
|
1063
|
+
if (fs.existsSync(dir)) {
|
|
1064
|
+
testDir = dir;
|
|
1065
|
+
break;
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
if (!testDir) {
|
|
1070
|
+
console.log(
|
|
1071
|
+
chalk.yellow(
|
|
1072
|
+
"⚠️ No test directory found. Looked for: test, tests, __tests__"
|
|
1073
|
+
)
|
|
1074
|
+
);
|
|
1075
|
+
return;
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
console.log(chalk.dim(`📁 Found test directory: ${testDir}`));
|
|
1079
|
+
|
|
1080
|
+
// Check if Jest is available
|
|
1081
|
+
const packageJsonPath = path.join(process.cwd(), "package.json");
|
|
1082
|
+
let hasJest = false;
|
|
1083
|
+
|
|
1084
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
1085
|
+
try {
|
|
1086
|
+
const packageJson = JSON.parse(
|
|
1087
|
+
fs.readFileSync(packageJsonPath, "utf-8")
|
|
1088
|
+
);
|
|
1089
|
+
hasJest = !!(
|
|
1090
|
+
packageJson.devDependencies?.jest ||
|
|
1091
|
+
packageJson.dependencies?.jest
|
|
1092
|
+
);
|
|
1093
|
+
} catch (error) {
|
|
1094
|
+
console.log(chalk.yellow("⚠️ Could not read package.json"));
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
if (!hasJest) {
|
|
1099
|
+
console.log(
|
|
1100
|
+
chalk.red(
|
|
1101
|
+
"❌ Jest is not installed. Please install Jest to run tests."
|
|
1102
|
+
)
|
|
1103
|
+
);
|
|
1104
|
+
return;
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
// Run Jest with the test directory
|
|
1108
|
+
return new Promise((resolve, reject) => {
|
|
1109
|
+
const jestProcess = spawn("npx", ["jest", testDir, "--verbose"], {
|
|
1110
|
+
stdio: "inherit",
|
|
1111
|
+
shell: true,
|
|
1112
|
+
});
|
|
1113
|
+
|
|
1114
|
+
jestProcess.on("close", (code) => {
|
|
1115
|
+
if (code === 0) {
|
|
1116
|
+
console.log(chalk.green.bold("\n✅ All tests passed!"));
|
|
1117
|
+
} else {
|
|
1118
|
+
console.log(chalk.red.bold("\n❌ Some tests failed."));
|
|
1119
|
+
}
|
|
1120
|
+
resolve(code);
|
|
1121
|
+
});
|
|
1122
|
+
|
|
1123
|
+
jestProcess.on("error", (error) => {
|
|
1124
|
+
console.error(chalk.red("❌ Error running tests:"), error.message);
|
|
1125
|
+
reject(error);
|
|
1126
|
+
});
|
|
1127
|
+
});
|
|
1128
|
+
}
|
|
1129
|
+
|
|
988
1130
|
export default {
|
|
989
1131
|
execute,
|
|
990
1132
|
};
|
package/commands/login.js
CHANGED
package/helper/env.js
CHANGED
package/helper/folder.js
CHANGED
|
@@ -9,7 +9,10 @@ import {
|
|
|
9
9
|
webhook,
|
|
10
10
|
} from "../templates/schemas.js";
|
|
11
11
|
|
|
12
|
-
export const createIntegrationFolderStructure = async (
|
|
12
|
+
export const createIntegrationFolderStructure = async (
|
|
13
|
+
integration,
|
|
14
|
+
create_catalogue
|
|
15
|
+
) => {
|
|
13
16
|
const { id, name, description, icon, activity_type, trigger_type, meta } =
|
|
14
17
|
integration;
|
|
15
18
|
|
|
@@ -47,13 +50,25 @@ export const createIntegrationFolderStructure = async (integration) => {
|
|
|
47
50
|
// Create template files
|
|
48
51
|
const files = {
|
|
49
52
|
"schemas/resources/resource1.json": JSON.stringify(resource1, null, 4),
|
|
50
|
-
|
|
51
|
-
|
|
53
|
+
...(create_catalogue && {
|
|
54
|
+
"schemas/authentication.json": JSON.stringify(
|
|
55
|
+
authentication,
|
|
56
|
+
null,
|
|
57
|
+
4
|
|
58
|
+
),
|
|
59
|
+
}),
|
|
60
|
+
"schemas/base.json": JSON.stringify(
|
|
61
|
+
base(name, create_catalogue),
|
|
62
|
+
null,
|
|
63
|
+
4
|
|
64
|
+
),
|
|
52
65
|
...(!isEmpty(trigger_type) && {
|
|
53
66
|
"schemas/webhook.json": JSON.stringify(webhook(name), null, 4),
|
|
54
67
|
}),
|
|
55
68
|
"spec.json": JSON.stringify(spec, null, 4),
|
|
56
|
-
|
|
69
|
+
...(create_catalogue && {
|
|
70
|
+
"Authentication.mdx": `# ${name} Authentication`,
|
|
71
|
+
}),
|
|
57
72
|
"Documentation.mdx": `# ${name} Documentation`,
|
|
58
73
|
};
|
|
59
74
|
|
package/helper/validation.js
CHANGED
|
@@ -154,6 +154,23 @@ const validateResources = (resourcesDir, resourceFields, errors) => {
|
|
|
154
154
|
});
|
|
155
155
|
};
|
|
156
156
|
|
|
157
|
+
// const validateParametersScema = (schema, errors) => {
|
|
158
|
+
// if (!schema || !Array.isArray(schema.parameters)) {
|
|
159
|
+
// errors.add(
|
|
160
|
+
// `Schema is missing or parameters are not defined as an array.`
|
|
161
|
+
// );
|
|
162
|
+
// return;
|
|
163
|
+
// }
|
|
164
|
+
// schema.parameters.forEach((param) => {
|
|
165
|
+
// const { meta } = param;
|
|
166
|
+
// if (!param.name) {
|
|
167
|
+
// errors.add(
|
|
168
|
+
// `Parameter in schema is missing a name. Ensure all parameters have a "name" field.`
|
|
169
|
+
// );
|
|
170
|
+
// }
|
|
171
|
+
// });
|
|
172
|
+
// };
|
|
173
|
+
|
|
157
174
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
158
175
|
// MAIN FUNCTION
|
|
159
176
|
// ─────────────────────────────────────────────────────────────────────────────
|
package/package.json
CHANGED
|
@@ -1,18 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@boltic/cli",
|
|
3
|
-
"version": "1.0.6-beta.
|
|
3
|
+
"version": "1.0.6-beta.11",
|
|
4
4
|
"description": "A powerful CLI tool for managing Boltic Workflow integrations",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"boltic": "index.js"
|
|
8
8
|
},
|
|
9
9
|
"author": "Ahmed Sakri <ahmedsakri@gofynd.com>",
|
|
10
|
-
"
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/bolticio/cli.git"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://github.com/bolticio/cli#readme",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/bolticio/cli/issues"
|
|
17
|
+
},
|
|
11
18
|
"scripts": {
|
|
12
19
|
"start": "node index.js",
|
|
13
20
|
"dev": "nodemon index.js",
|
|
14
21
|
"test": "jest",
|
|
15
|
-
"prepare": "husky"
|
|
22
|
+
"prepare": "husky",
|
|
23
|
+
"lint": "eslint . --ext .js,.jsx,.ts,.tsx"
|
|
16
24
|
},
|
|
17
25
|
"keywords": [
|
|
18
26
|
"cli",
|
|
@@ -35,7 +43,8 @@
|
|
|
35
43
|
"chalk": "^5.3.0",
|
|
36
44
|
"keytar": "^7.9.0",
|
|
37
45
|
"open": "^10.1.0",
|
|
38
|
-
"uuid": "^11.1.0"
|
|
46
|
+
"uuid": "^11.1.0",
|
|
47
|
+
"lodash.isempty": "^4.4.0"
|
|
39
48
|
},
|
|
40
49
|
"devDependencies": {
|
|
41
50
|
"@babel/core": "^7.26.9",
|
|
@@ -51,7 +60,6 @@
|
|
|
51
60
|
"husky": "^9.1.7",
|
|
52
61
|
"jest": "^29.7.0",
|
|
53
62
|
"lint-staged": "^15.4.3",
|
|
54
|
-
"lodash.isempty": "^4.4.0",
|
|
55
63
|
"nodemon": "^3.1.9",
|
|
56
64
|
"prettier": "^3.5.3"
|
|
57
65
|
}
|
package/templates/schemas.js
CHANGED
|
@@ -45,10 +45,24 @@ const authentication = {
|
|
|
45
45
|
},
|
|
46
46
|
};
|
|
47
47
|
|
|
48
|
-
const base = (name) => {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
const base = (name, create_catalogue) => {
|
|
49
|
+
const secretParameter = create_catalogue
|
|
50
|
+
? {
|
|
51
|
+
name: "secret",
|
|
52
|
+
meta: {
|
|
53
|
+
displayName: "Service Account",
|
|
54
|
+
displayType: "hidden",
|
|
55
|
+
placeholder: "Select Service Account",
|
|
56
|
+
description:
|
|
57
|
+
"Your service account credentials are encrypted & can be removed at any time.",
|
|
58
|
+
options: [],
|
|
59
|
+
value: `__BOLTIC_INTEGRATION_${name.toUpperCase()}`,
|
|
60
|
+
validation: {
|
|
61
|
+
required: true,
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
}
|
|
65
|
+
: {
|
|
52
66
|
name: "secret",
|
|
53
67
|
meta: {
|
|
54
68
|
displayName: "Service Account",
|
|
@@ -72,7 +86,11 @@ const base = (name) => {
|
|
|
72
86
|
required: true,
|
|
73
87
|
},
|
|
74
88
|
},
|
|
75
|
-
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
parameters: [
|
|
93
|
+
secretParameter,
|
|
76
94
|
{
|
|
77
95
|
name: "resource",
|
|
78
96
|
meta: {
|