@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 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
  [![NPM Version](https://img.shields.io/npm/v/@boltic/cli)](https://www.npmjs.com/package/@boltic/cli)
6
+ [![GitHub Repo](https://img.shields.io/badge/GitHub-Repo-blue?logo=github)](https://github.com/<your-username>/<your-repo>)
6
7
  [![License](https://img.shields.io/npm/l/@boltic/cli)](./LICENSE)
7
- [![Node Version](https://img.shields.io/node/v/@boltic/cli)](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: () => AuthCommands.handleLogin(consoleUrl, apiUrl, env),
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 (error) {
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 packageJson;
144
+ let version = "1.0.0"; // default fallback
143
145
  try {
144
- // Try to read package.json from current directory
145
- packageJson = JSON.parse(
146
- fs.readFileSync(path.join(process.cwd(), "package.json"))
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
- } catch (error) {
149
- // Fallback version if package.json not found
150
- packageJson = { version: "1.0.0" };
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
 
@@ -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(integration);
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
- ["customActivity", "CloudTrigger"].includes(
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
- ["customActivity", "CloudTrigger"].includes(
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
- ["customActivity", "CloudTrigger"].includes(
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
@@ -40,7 +40,7 @@ function showHelp() {
40
40
  }
41
41
 
42
42
  // Handle login command
43
- async function handleLogin(args) {
43
+ async function handleLogin() {
44
44
  const { apiUrl, loginUrl, clientId, frontendUrl, name } =
45
45
  await getCurrentEnv();
46
46
 
package/helper/env.js CHANGED
@@ -11,7 +11,7 @@ export const getCurrentEnv = async () => {
11
11
 
12
12
  try {
13
13
  secrets = await getAllSecrets();
14
- } catch (_) {
14
+ } catch {
15
15
  // If getAllSecrets fails, use default bolt environment
16
16
  secrets = null;
17
17
  }
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 (integration) => {
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
- "schemas/authentication.json": JSON.stringify(authentication, null, 4),
51
- "schemas/base.json": JSON.stringify(base(name), null, 4),
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
- "Authentication.mdx": `# ${name} Authentication`,
69
+ ...(create_catalogue && {
70
+ "Authentication.mdx": `# ${name} Authentication`,
71
+ }),
57
72
  "Documentation.mdx": `# ${name} Documentation`,
58
73
  };
59
74
 
@@ -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.0",
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
- "homepage": "https://www.boltic.io",
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
  }
@@ -45,10 +45,24 @@ const authentication = {
45
45
  },
46
46
  };
47
47
 
48
- const base = (name) => {
49
- return {
50
- parameters: [
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: {
@@ -39,7 +39,7 @@ async function pickSvgFile() {
39
39
  console.error("Unsupported platform for file picker");
40
40
  return null;
41
41
  }
42
- } catch (_) {
42
+ } catch {
43
43
  return null;
44
44
  }
45
45
  }