@boltic/cli 1.0.7 → 1.0.8

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
@@ -519,15 +519,6 @@ npm install -g @boltic/cli@latest
519
519
  boltic --version
520
520
  ```
521
521
 
522
- **Development mode troubleshooting**:
523
-
524
- ```bash
525
- # For contributors using development installation
526
- npm install # Update dependencies
527
- npm link # Re-link CLI
528
- npm test # Run test suite
529
- ```
530
-
531
522
  #### 9. Emergency Recovery
532
523
 
533
524
  **If all else fails**:
@@ -54,10 +54,6 @@ const commands = {
54
54
  description: "Show detailed information about an integration",
55
55
  action: handleStatus,
56
56
  },
57
- test: {
58
- description: "Run tests for the integration with coverage",
59
- action: handleTest,
60
- },
61
57
  help: {
62
58
  description: "Show help for integration commands",
63
59
  action: showHelp,
@@ -1064,6 +1060,13 @@ async function handleStatus() {
1064
1060
  console.log(integration.documentation);
1065
1061
  }
1066
1062
  } catch (error) {
1063
+ if (
1064
+ error.message &&
1065
+ error.message.includes("User force closed the prompt")
1066
+ ) {
1067
+ console.log(chalk.yellow("\n⚠️ Operation cancelled by user"));
1068
+ return;
1069
+ }
1067
1070
  console.error(
1068
1071
  chalk.red("\n❌ Error fetching integration status:"),
1069
1072
  error.message || "Unknown error"
@@ -1071,258 +1074,6 @@ async function handleStatus() {
1071
1074
  }
1072
1075
  }
1073
1076
 
1074
- async function handleTest(args) {
1075
- // Parse command line arguments
1076
- let currentDir = process.cwd();
1077
- let jestConfigFile = null;
1078
- const pathIndex = args.indexOf("--path");
1079
- const configIndex = args.indexOf("--config");
1080
-
1081
- if (pathIndex !== -1 && args[pathIndex + 1]) {
1082
- currentDir = args[pathIndex + 1];
1083
- // Validate the provided path
1084
- if (!fs.existsSync(currentDir)) {
1085
- console.error(
1086
- chalk.red(
1087
- `Error: The specified path does not exist: ${currentDir}`
1088
- )
1089
- );
1090
- return;
1091
- }
1092
- }
1093
-
1094
- if (configIndex !== -1 && args[configIndex + 1]) {
1095
- jestConfigFile = args[configIndex + 1];
1096
- // Validate the config file path
1097
- const configPath = path.isAbsolute(jestConfigFile)
1098
- ? jestConfigFile
1099
- : path.join(currentDir, jestConfigFile);
1100
-
1101
- if (!fs.existsSync(configPath)) {
1102
- console.error(
1103
- chalk.red(
1104
- `Error: Jest config file does not exist: ${configPath}`
1105
- )
1106
- );
1107
- return;
1108
- }
1109
- }
1110
-
1111
- const { spawn } = await import("child_process");
1112
-
1113
- console.log(chalk.cyan.bold("\n🧪 Running integration tests...\n"));
1114
-
1115
- // Look for test directory and test files
1116
- const testDirs = ["test", "tests", "__tests__"];
1117
- let testDir = null;
1118
- let testFiles = [];
1119
-
1120
- // Check for test directories
1121
- for (const dir of testDirs) {
1122
- const testPath = path.join(currentDir, dir);
1123
- if (fs.existsSync(testPath)) {
1124
- testDir = dir;
1125
- // Find all test files in the directory
1126
- const files = fs.readdirSync(testPath);
1127
- testFiles = files.filter(
1128
- (file) =>
1129
- file.endsWith(".test.js") ||
1130
- file.endsWith(".spec.js") ||
1131
- file.endsWith(".test.ts") ||
1132
- file.endsWith(".spec.ts")
1133
- );
1134
- break;
1135
- }
1136
- }
1137
-
1138
- // If no test directory found, look for test files in current directory
1139
- if (!testDir) {
1140
- const currentDirFiles = fs.readdirSync(currentDir);
1141
- testFiles = currentDirFiles.filter(
1142
- (file) =>
1143
- file.endsWith(".test.js") ||
1144
- file.endsWith(".spec.js") ||
1145
- file.endsWith(".test.ts") ||
1146
- file.endsWith(".spec.ts")
1147
- );
1148
-
1149
- if (testFiles.length === 0) {
1150
- console.log(
1151
- chalk.yellow(
1152
- "⚠️ No test files found. Looked for: test, tests, __tests__ directories and *.test.js, *.spec.js, *.test.ts, *.spec.ts files"
1153
- )
1154
- );
1155
- return;
1156
- }
1157
- }
1158
-
1159
- if (testFiles.length === 0 && testDir) {
1160
- console.log(
1161
- chalk.yellow(
1162
- `⚠️ No test files found in ${testDir} directory. Looking for: *.test.js, *.spec.js, *.test.ts, *.spec.ts files`
1163
- )
1164
- );
1165
- return;
1166
- }
1167
-
1168
- console.log(chalk.dim(`📁 Found test directory: ${testDir || currentDir}`));
1169
- console.log(
1170
- chalk.dim(
1171
- `📋 Found ${testFiles.length} test file(s): ${testFiles.join(", ")}`
1172
- )
1173
- );
1174
-
1175
- // Check for Jest configuration
1176
- let jestConfigPath;
1177
- if (jestConfigFile) {
1178
- jestConfigPath = path.isAbsolute(jestConfigFile)
1179
- ? jestConfigFile
1180
- : path.join(currentDir, jestConfigFile);
1181
- } else {
1182
- // Look for default config files
1183
- const defaultConfigs = [
1184
- "jest.config.cjs",
1185
- "jest.config.js",
1186
- "jest.config.json",
1187
- ];
1188
- for (const configFile of defaultConfigs) {
1189
- const configPath = path.join(currentDir, configFile);
1190
- if (fs.existsSync(configPath)) {
1191
- jestConfigPath = configPath;
1192
- break;
1193
- }
1194
- }
1195
- }
1196
-
1197
- const jestConfigExists = !!jestConfigPath;
1198
- const configFileName = jestConfigPath
1199
- ? path.basename(jestConfigPath)
1200
- : null;
1201
-
1202
- console.log(
1203
- chalk.dim(
1204
- `⚙️ Jest configuration: ${jestConfigExists ? `Found ${configFileName}` : "Using default configuration"}`
1205
- )
1206
- );
1207
-
1208
- // Prepare Jest arguments
1209
- const jestArgs = ["jest"];
1210
-
1211
- // Add basic Jest flags
1212
- jestArgs.push("--coverage");
1213
- jestArgs.push("--verbose");
1214
- jestArgs.push("--colors");
1215
- jestArgs.push("--passWithNoTests");
1216
-
1217
- // Add config file if exists, otherwise use simple patterns
1218
- if (jestConfigExists) {
1219
- jestArgs.push("--config", jestConfigPath);
1220
- } else {
1221
- // Use simple test matching patterns
1222
- if (testDir) {
1223
- jestArgs.push(
1224
- "--testMatch",
1225
- `**/${testDir}/**/*.{test,spec}.{js,ts}`
1226
- );
1227
- } else {
1228
- jestArgs.push("--testMatch", "**/*.{test,spec}.{js,ts}");
1229
- }
1230
- jestArgs.push("--collectCoverageFrom", "lib/**/*.{js,ts}");
1231
- jestArgs.push("--collectCoverageFrom", "src/**/*.{js,ts}");
1232
- jestArgs.push("--collectCoverageFrom", "*.{js,ts}");
1233
- jestArgs.push("--coveragePathIgnorePatterns", "/node_modules/");
1234
- jestArgs.push("--coveragePathIgnorePatterns", "/tests/");
1235
- }
1236
-
1237
- // Add any additional Jest arguments passed by user
1238
- const additionalArgs = args.filter((arg, index) => {
1239
- // Skip our custom flags and their values
1240
- if (arg === "--path" || arg === "--config") return false;
1241
- if (args[index - 1] === "--path" || args[index - 1] === "--config")
1242
- return false;
1243
- return true;
1244
- });
1245
-
1246
- if (additionalArgs.length > 0) {
1247
- jestArgs.push(...additionalArgs);
1248
- console.log(
1249
- chalk.dim(
1250
- `🔧 Additional Jest arguments: ${additionalArgs.join(" ")}`
1251
- )
1252
- );
1253
- }
1254
-
1255
- console.log(chalk.dim(`🚀 Running command: npx ${jestArgs.join(" ")}`));
1256
- console.log(chalk.cyan("─".repeat(50)));
1257
-
1258
- // Run Jest with coverage
1259
- return new Promise((resolve, reject) => {
1260
- const jestProcess = spawn("npx", jestArgs, {
1261
- stdio: "inherit",
1262
- shell: true,
1263
- cwd: currentDir,
1264
- });
1265
-
1266
- jestProcess.on("close", (code) => {
1267
- console.log(chalk.cyan("─".repeat(50)));
1268
-
1269
- if (code === 0) {
1270
- console.log(chalk.green.bold("\n✅ All tests passed!"));
1271
-
1272
- // Check for coverage directory
1273
- const coverageDir = path.join(currentDir, "coverage");
1274
- if (fs.existsSync(coverageDir)) {
1275
- console.log(chalk.cyan("\n📊 Coverage Report Generated:"));
1276
- console.log(chalk.dim(` Directory: ${coverageDir}`));
1277
-
1278
- // Check for HTML report
1279
- const htmlReportPath = path.join(
1280
- coverageDir,
1281
- "lcov-report",
1282
- "index.html"
1283
- );
1284
- if (fs.existsSync(htmlReportPath)) {
1285
- console.log(
1286
- chalk.dim(` HTML Report: ${htmlReportPath}`)
1287
- );
1288
- }
1289
-
1290
- // Check for text report
1291
- const textReportPath = path.join(coverageDir, "lcov.info");
1292
- if (fs.existsSync(textReportPath)) {
1293
- console.log(
1294
- chalk.dim(` LCOV Report: ${textReportPath}`)
1295
- );
1296
- }
1297
- }
1298
-
1299
- // Show test summary
1300
- console.log(chalk.cyan("\n📋 Test Summary:"));
1301
- console.log(chalk.dim(` Test files: ${testFiles.length}`));
1302
- console.log(
1303
- chalk.dim(` Test directory: ${testDir || currentDir}`)
1304
- );
1305
- console.log(chalk.green(" Status: PASSED"));
1306
- } else {
1307
- console.log(chalk.red.bold("\n❌ Some tests failed."));
1308
- console.log(chalk.red(` Exit code: ${code}`));
1309
- }
1310
-
1311
- console.log(
1312
- chalk.cyan(
1313
- "\n💡 Tip: Check the coverage directory for detailed coverage reports"
1314
- )
1315
- );
1316
- resolve(code);
1317
- });
1318
-
1319
- jestProcess.on("error", (error) => {
1320
- console.error(chalk.red("❌ Error running tests:"), error.message);
1321
- reject(error);
1322
- });
1323
- });
1324
- }
1325
-
1326
1077
  export default {
1327
1078
  execute,
1328
1079
  };
@@ -150,6 +150,17 @@ const validateSchemaKeys = (
150
150
  Object.keys(schemaObj).forEach((key) => {
151
151
  const fullKey = prefix ? `${prefix}.${key}` : key;
152
152
 
153
+ // Special handling for config.body - skip validation for select, autocomplete, and multiselect
154
+ if (
155
+ fullKey === "config.body" &&
156
+ (displayType === "select" ||
157
+ displayType === "autocomplete" ||
158
+ displayType === "multiselect")
159
+ ) {
160
+ // For these display types, config.body can contain any keys, so we skip validation
161
+ return;
162
+ }
163
+
153
164
  if (!allowedKeys.has(fullKey)) {
154
165
  errors.add(
155
166
  `"${schemaName}" has an invalid key "${fullKey}" for displayType "${displayType}"${fileLabel}.`
@@ -159,7 +170,14 @@ const validateSchemaKeys = (
159
170
  if (
160
171
  typeof schemaObj[key] === "object" &&
161
172
  schemaObj[key] !== null &&
162
- !Array.isArray(schemaObj[key])
173
+ !Array.isArray(schemaObj[key]) &&
174
+ // Skip recursion for config.body of select/autocomplete/multiselect
175
+ !(
176
+ fullKey === "config.body" &&
177
+ (displayType === "select" ||
178
+ displayType === "autocomplete" ||
179
+ displayType === "multiselect")
180
+ )
163
181
  ) {
164
182
  validateSchemaKeys(
165
183
  schemaObj[key],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@boltic/cli",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "description": "A powerful CLI tool for managing Boltic Workflow integrations",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -914,6 +914,29 @@ const button = {
914
914
  },
915
915
  };
916
916
 
917
+ const datetime = {
918
+ name: "datetime-picker",
919
+ meta: {
920
+ displayName: "Enter Date with Start Time",
921
+ description: "Please enter date and start time",
922
+ displayType: "datetime",
923
+ value: "2024-02-14",
924
+ validation: {
925
+ required: false,
926
+ },
927
+ readOnly: false,
928
+ htmlProps: {
929
+ format: "YYYY-MM-DD HH:mm:ss",
930
+ disabled: false,
931
+ timeSteps: {
932
+ hours: 1,
933
+ minutes: 5,
934
+ seconds: 5,
935
+ },
936
+ },
937
+ },
938
+ };
939
+
917
940
  export {
918
941
  accordion,
919
942
  array,
@@ -922,6 +945,7 @@ export {
922
945
  checkbox,
923
946
  code,
924
947
  date,
948
+ datetime,
925
949
  divider,
926
950
  email,
927
951
  file,