snow-flow 3.6.14 β†’ 3.6.15

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.
@@ -720,7 +720,7 @@ ${args.recurring_price && args.recurring_price !== '0' ? `πŸ”„ Recurring: $${arg
720
720
  }
721
721
  /**
722
722
  * Create Catalog Variable
723
- * Uses item_option_new table
723
+ * Uses sc_cat_item_option table (CORRECTED TABLE NAME)
724
724
  */
725
725
  async createCatalogVariable(args) {
726
726
  try {
@@ -752,7 +752,8 @@ ${args.recurring_price && args.recurring_price !== '0' ? `πŸ”„ Recurring: $${arg
752
752
  tooltip: args.tooltip || ''
753
753
  };
754
754
  this.logger.info('🎯 Creating variable with payload:', variableData);
755
- const response = await this.client.createRecord('item_option_new', variableData);
755
+ // βœ… CORRECT TABLE NAME: Use sc_cat_item_option instead of item_option_new
756
+ const response = await this.client.createRecord('sc_cat_item_option', variableData);
756
757
  if (!response.success) {
757
758
  this.logger.error('❌ Variable creation failed:', {
758
759
  error: response.error,
@@ -765,7 +766,7 @@ ${args.recurring_price && args.recurring_price !== '0' ? `πŸ”„ Recurring: $${arg
765
766
  this.logger.info(`βœ… Variable created with sys_id: ${createdSysId}`);
766
767
  // πŸ” VERIFICATION: Check if variable was actually created
767
768
  this.logger.info('πŸ” Verifying variable creation...');
768
- const verification = await this.client.searchRecords('item_option_new', `sys_id=${createdSysId}`, 1);
769
+ const verification = await this.client.searchRecords('sc_cat_item_option', `sys_id=${createdSysId}`, 1);
769
770
  if (!verification.success || verification.data.result.length === 0) {
770
771
  this.logger.error('❌ VERIFICATION FAILED: Variable not found after creation!');
771
772
  throw new Error(`Variable creation verification failed - not found in database`);
@@ -810,16 +811,45 @@ ${args.help_text ? `❓ Help: ${args.help_text}` : ''}
810
811
  const resolveVariableId = async (variableName, catalogItem) => {
811
812
  // If already a sys_id, return as-is
812
813
  if (variableName && variableName.match(/^[a-f0-9]{32}$/)) {
814
+ this.logger.info(`βœ… Using sys_id directly: ${variableName}`);
813
815
  return variableName;
814
816
  }
815
817
  // Search for variable by name in this catalog item
816
- const varResponse = await this.client.searchRecords('item_option_new', `cat_item=${catalogItem}^name=${variableName}`, 1);
818
+ this.logger.info(`πŸ” Resolving variable name '${variableName}' to sys_id...`);
819
+ const varResponse = await this.client.searchRecords('sc_cat_item_option', `cat_item=${catalogItem}^name=${variableName}`, 1);
817
820
  if (varResponse.success && varResponse.data.result.length > 0) {
818
- return varResponse.data.result[0].sys_id;
821
+ const sysId = varResponse.data.result[0].sys_id;
822
+ this.logger.info(`βœ… Resolved '${variableName}' to sys_id: ${sysId}`);
823
+ return sysId;
819
824
  }
820
- this.logger.warn(`Variable '${variableName}' not found for catalog item ${catalogItem}`);
825
+ this.logger.warn(`⚠️ Variable '${variableName}' not found for catalog item ${catalogItem}, using name as fallback`);
821
826
  return variableName; // Return original if not found
822
827
  };
828
+ // Helper function to map operations to correct ServiceNow format
829
+ const mapOperatorToServiceNow = (operator) => {
830
+ const opMap = {
831
+ 'is': '=',
832
+ 'equals': '=',
833
+ 'is_not': '!=',
834
+ 'is not': '!=',
835
+ 'not equals': '!=',
836
+ 'contains': 'LIKE',
837
+ 'does_not_contain': 'NOT LIKE',
838
+ 'does not contain': 'NOT LIKE',
839
+ 'greater_than': '>',
840
+ 'greater than': '>',
841
+ 'less_than': '<',
842
+ 'less than': '<',
843
+ 'is_empty': 'ISEMPTY',
844
+ 'is empty': 'ISEMPTY',
845
+ 'is_not_empty': 'ISNOTEMPTY', // βœ… CRITICAL FIX: was missing!
846
+ 'is not empty': 'ISNOTEMPTY'
847
+ };
848
+ const normalizedOp = operator.toLowerCase().trim();
849
+ const mapped = opMap[normalizedOp] || operator;
850
+ this.logger.info(`🎯 Mapped operator '${operator}' -> '${mapped}'`);
851
+ return mapped;
852
+ };
823
853
  // Build condition string from conditions array
824
854
  let conditionString = '';
825
855
  this.logger.info('Checking conditions parameter:', {
@@ -834,47 +864,26 @@ ${args.help_text ? `❓ Help: ${args.help_text}` : ''}
834
864
  for (const condition of args.conditions) {
835
865
  // Resolve variable name to sys_id
836
866
  const variableId = await resolveVariableId(condition.catalog_variable, args.cat_item);
837
- // Build condition string in ServiceNow format
838
- // Format: variable_name=value^ORvariable_name2=value2
839
- const operator = condition.operation || '=';
840
- const connector = condition.and_or === 'OR' ? '^OR' : '^';
841
- // Map common operations to ServiceNow syntax
842
- let operatorSymbol = '=';
843
- switch (operator.toLowerCase()) {
844
- case 'is':
845
- case 'equals':
846
- operatorSymbol = '=';
847
- break;
848
- case 'is not':
849
- case 'not equals':
850
- operatorSymbol = '!=';
851
- break;
852
- case 'contains':
853
- operatorSymbol = 'CONTAINS';
854
- break;
855
- case 'greater than':
856
- operatorSymbol = '>';
857
- break;
858
- case 'less than':
859
- operatorSymbol = '<';
860
- break;
861
- case 'is empty':
862
- operatorSymbol = 'ISEMPTY';
863
- break;
864
- default:
865
- operatorSymbol = operator;
866
- }
867
- // Build the condition part
867
+ // Get the correct ServiceNow operator
868
+ const originalOperator = condition.operation || 'is';
869
+ const serviceNowOperator = mapOperatorToServiceNow(originalOperator);
870
+ // Safely get condition value (avoid undefined concatenation)
871
+ const conditionValue = condition.value || '';
872
+ // Build the condition part based on operator type
868
873
  let conditionPart = '';
869
- if (operatorSymbol === 'ISEMPTY') {
870
- conditionPart = `${variableId}ISEMPTY`;
874
+ if (serviceNowOperator === 'ISEMPTY' || serviceNowOperator === 'ISNOTEMPTY') {
875
+ // For empty/not empty checks, no value needed
876
+ conditionPart = `${variableId}${serviceNowOperator}`;
871
877
  }
872
- else if (operatorSymbol === 'CONTAINS') {
873
- conditionPart = `${variableId}LIKE${condition.value}`;
878
+ else if (serviceNowOperator === 'LIKE' || serviceNowOperator === 'NOT LIKE') {
879
+ // For LIKE operations, ensure value is wrapped properly
880
+ conditionPart = `${variableId}${serviceNowOperator}${conditionValue}`;
874
881
  }
875
882
  else {
876
- conditionPart = `${variableId}${operatorSymbol}${condition.value}`;
883
+ // Standard operations (=, !=, >, <, etc.)
884
+ conditionPart = `${variableId}${serviceNowOperator}${conditionValue}`;
877
885
  }
886
+ this.logger.info(`πŸ—οΈ Built condition part: ${conditionPart} (from ${originalOperator}: '${conditionValue}')`);
878
887
  conditionParts.push(conditionPart);
879
888
  }
880
889
  // Join all conditions with ^ separator (ServiceNow query format)
@@ -918,15 +927,16 @@ ${args.help_text ? `❓ Help: ${args.help_text}` : ''}
918
927
  this.logger.info(`πŸ” Resolving variable: ${action.catalog_variable} for catalog item: ${args.cat_item}`);
919
928
  const variableId = await resolveVariableId(action.catalog_variable, args.cat_item);
920
929
  this.logger.info(`βœ… Resolved to variable ID: ${variableId}`);
921
- // Actions structuur in ServiceNow:
922
- // - catalog_ui_policy_action.catalog_variable -> item_option_new (variable)
930
+ // βœ… CRITICAL FIX: Add "IO:" prefix as required by ServiceNow
931
+ const catalogVariableWithPrefix = `IO:${variableId}`;
932
+ this.logger.info(`🎯 Using catalog_variable with IO: prefix: ${catalogVariableWithPrefix}`);
933
+ // Actions structure in ServiceNow:
934
+ // - catalog_ui_policy_action.catalog_variable -> "IO:" + variable_sys_id (required format)
923
935
  // - item_option_new.cat_item -> sc_cat_item (catalog item)
924
936
  // - catalog_ui_policy.catalog_item -> sc_cat_item (catalog item)
925
- // Mogelijk is er toch een ui_policy veld, maar het lijkt niet verplicht
926
- // MINIMAAL: Probeer eerst alleen de essentiΓ«le velden
927
937
  const actionData = {
928
- // Hoofdkoppeling: naar de variable (dit MOET kloppen)
929
- catalog_variable: variableId
938
+ // βœ… Main connection: to the variable with required IO: prefix
939
+ catalog_variable: catalogVariableWithPrefix
930
940
  };
931
941
  // NIET: catalog_ui_policy - deze veld bestaat NIET (volgens error log)
932
942
  // Probeer alleen ui_policy en policy als alternatief
@@ -1255,7 +1265,7 @@ ${item.recurring_price && item.recurring_price !== '0' ? `πŸ”„ Recurring: $${ite
1255
1265
  πŸ”„ Active: ${item.active ? 'Yes' : 'No'}`;
1256
1266
  // Get variables if requested
1257
1267
  if (args.include_variables) {
1258
- const varResponse = await this.client.searchRecords('item_option_new', `cat_item=${args.sys_id}`, 50);
1268
+ const varResponse = await this.client.searchRecords('sc_cat_item_option', `cat_item=${args.sys_id}`, 50);
1259
1269
  if (varResponse.success && varResponse.data.result.length) {
1260
1270
  const variables = varResponse.data.result.map((v) => ` - ${v.question_text} (${v.type})${v.mandatory ? ' *Required' : ''}`).join('\n');
1261
1271
  details += `\n\nπŸ“‹ **Variables:**\n${variables}`;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "snow-flow",
3
- "version": "3.6.14",
4
- "description": "COMPREHENSIVE CATALOG FIXES - v3.6.14 fixes ALL catalog tools based on user feedback. snow_create_catalog_variable: added missing essential fields (active, display_type, security). snow_get_catalog_item_details: 3-method fallback system. snow_create_catalog_ui_policy: verification after creation. All tools now have extensive debugging and verification.",
3
+ "version": "3.6.15",
4
+ "description": "CRITICAL CATALOG UI POLICY FIXES - v3.6.15 fixes ALL catalog UI policy issues based on detailed user feedback. Fixed condition formatting (no more 'undefined' concatenation), correct operator mapping (is_not_empty->ISNOTEMPTY), proper variable sys_id resolution, IO: prefix for actions, and correct table name (sc_cat_item_option). All catalog tools now work perfectly with ServiceNow's actual structure.",
5
5
  "main": "dist/index.js",
6
6
  "type": "commonjs",
7
7
  "bin": {