snow-flow 3.5.15 → 3.5.17

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.
@@ -86,19 +86,13 @@ export declare class ArtifactLocalSync {
86
86
  */
87
87
  private validateES5;
88
88
  /**
89
- * Strip headers/footers we added - FIXED to use actual fieldMapping wrappers
89
+ * AGGRESSIVE STRIP FUNCTION: Remove ALL possible Snow-Flow wrapper variations
90
+ * FIXED: Handles multiple/nested wrappers and all patterns
90
91
  */
91
92
  private stripAddedWrappers;
92
93
  /**
93
- * Create regex pattern from wrapper text, handling placeholders
94
- */
95
- private escapeRegexAndCreatePattern;
96
- /**
97
- * Fallback: Strip generic comments when no fieldMapping available
98
- */
99
- private stripGenericComments;
100
- /**
101
- * INTELLIGENT WRAPPER DETECTION: Check if content actually needs wrappers
94
+ * CONSERVATIVE WRAPPER DETECTION: Only add wrappers if content is truly minimal
95
+ * FIXED: Now properly detects ALL types of existing wrappers/comments
102
96
  */
103
97
  private needsWrappers;
104
98
  /**
@@ -115,6 +109,7 @@ export declare class ArtifactLocalSync {
115
109
  getSyncStatus(sys_id: string): string;
116
110
  /**
117
111
  * Pull any supported artifact type by detecting table from sys_id
112
+ * ENHANCED: Better error logging and more robust detection
118
113
  */
119
114
  pullArtifactBySysId(sys_id: string): Promise<LocalArtifact>;
120
115
  /**
@@ -127,7 +127,8 @@ class ArtifactLocalSync {
127
127
  throw new Error(`Unsupported artifact type: ${tableName}. Supported types: ${Object.keys(artifact_registry_1.ARTIFACT_REGISTRY).join(', ')}`);
128
128
  }
129
129
  console.log(`\nšŸ”„ Pulling ${config.displayName} (${sys_id}) to local files...`);
130
- console.log(`šŸ“‹ Snow-Flow v3.5.15 - Intelligent Wrapper System Active`);
130
+ console.log(`šŸ“‹ Snow-Flow v3.5.16 - ULTRA-CONSERVATIVE Wrapper System (No More Duplicates!)`);
131
+ console.log(`āš ļø CRITICAL FIX: Aggressive strip & minimal wrapper addition only`);
131
132
  // Get timeout configuration
132
133
  const timeoutConfig = (0, mcp_timeout_config_js_1.getMCPTimeoutConfig)();
133
134
  // Use smart fetcher for known types, otherwise direct query
@@ -187,16 +188,21 @@ class ArtifactLocalSync {
187
188
  .replace('{name}', sanitizedName)
188
189
  .replace('{api_name}', artifactData.api_name || sanitizedName)
189
190
  .replace('{short_description}', artifactData.short_description || sanitizedName);
190
- // INTELLIGENT WRAPPER SYSTEM: Only add wrappers if actually needed
191
+ // ULTRA-CONSERVATIVE WRAPPER SYSTEM: When in doubt, don't add wrappers
191
192
  let header = '';
192
193
  let footer = '';
193
- if (mapping.wrapperHeader && mapping.wrapperFooter && this.needsWrappers(processedContent, mapping)) {
194
- header = this.replacePlaceholders(mapping.wrapperHeader, artifactData);
195
- footer = this.replacePlaceholders(mapping.wrapperFooter, artifactData);
196
- console.log(` šŸ”§ Adding wrappers for ${filename} (content needs them)`);
197
- }
198
- else if (mapping.wrapperHeader && mapping.wrapperFooter) {
199
- console.log(` āœ… Skipping wrappers for ${filename} (content is already wrapped)`);
194
+ // FAILSAFE: Only add wrappers if we're absolutely certain it's safe
195
+ if (mapping.wrapperHeader && mapping.wrapperFooter) {
196
+ const shouldAddWrappers = this.needsWrappers(processedContent, mapping);
197
+ if (shouldAddWrappers && processedContent.trim().length < 50) {
198
+ // EXTRA SAFETY: Only for very short content
199
+ header = this.replacePlaceholders(mapping.wrapperHeader, artifactData);
200
+ footer = this.replacePlaceholders(mapping.wrapperFooter, artifactData);
201
+ console.log(` šŸ”§ Adding wrappers for ${filename} (content is minimal: ${processedContent.trim().length} chars)`);
202
+ }
203
+ else {
204
+ console.log(` āœ… Skipping wrappers for ${filename} (conservative approach)`);
205
+ }
200
206
  }
201
207
  const file = this.createLocalFile(artifactPath, `${filename}.${mapping.fileExtension}`, processedContent, mapping.serviceNowField, mapping.fileExtension, header, footer);
202
208
  file.fieldMapping = mapping;
@@ -580,104 +586,97 @@ snow-flow sync status ${widget.sys_id}
580
586
  return issues;
581
587
  }
582
588
  /**
583
- * Strip headers/footers we added - FIXED to use actual fieldMapping wrappers
589
+ * AGGRESSIVE STRIP FUNCTION: Remove ALL possible Snow-Flow wrapper variations
590
+ * FIXED: Handles multiple/nested wrappers and all patterns
584
591
  */
585
592
  stripAddedWrappers(content, type, fieldMapping) {
586
- if (!fieldMapping || !fieldMapping.wrapperHeader || !fieldMapping.wrapperFooter) {
587
- // No wrappers defined, just remove generic comments
588
- return this.stripGenericComments(content, type);
589
- }
590
- let cleaned = content;
591
- // Get the actual wrappers that were added (without placeholders)
592
- const header = fieldMapping.wrapperHeader;
593
- const footer = fieldMapping.wrapperFooter;
594
- // CRITICAL FIX: Use the EXACT wrappers from fieldMapping
595
- if (header && footer) {
596
- // Create regex patterns from the actual wrappers
597
- const headerPattern = this.escapeRegexAndCreatePattern(header);
598
- const footerPattern = this.escapeRegexAndCreatePattern(footer);
599
- // Remove footer first (from end)
600
- if (footerPattern) {
601
- cleaned = cleaned.replace(new RegExp(footerPattern + '$'), '');
602
- }
603
- // Remove header (from start)
604
- if (headerPattern) {
605
- cleaned = cleaned.replace(new RegExp('^' + headerPattern), '');
606
- }
607
- }
608
- return cleaned.trim();
609
- }
610
- /**
611
- * Create regex pattern from wrapper text, handling placeholders
612
- */
613
- escapeRegexAndCreatePattern(wrapper) {
614
- // Replace placeholders with generic patterns
615
- let pattern = wrapper
616
- .replace(/\{name\}/g, '[^}]*') // Replace {name} with pattern to match any name
617
- .replace(/\{[^}]+\}/g, '[^}]*'); // Replace any other {placeholder}
618
- // Escape special regex characters
619
- pattern = pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
620
- // Convert \n back to actual newlines in pattern
621
- pattern = pattern.replace(/\\n/g, '\\s*\\n\\s*');
622
- return pattern;
623
- }
624
- /**
625
- * Fallback: Strip generic comments when no fieldMapping available
626
- */
627
- stripGenericComments(content, type) {
628
593
  let cleaned = content;
594
+ // STEP 1: Remove ALL HTML comment variations (multiple times if needed)
595
+ if (type === 'html') {
596
+ let previousLength;
597
+ do {
598
+ previousLength = cleaned.length;
599
+ // Remove ServiceNow Widget Template comments (all variations)
600
+ cleaned = cleaned.replace(/^\s*<!--\s*ServiceNow\s+Widget\s+Template[\s\S]*?-->\s*\n?/gmi, '');
601
+ // Remove Angular bindings comments
602
+ cleaned = cleaned.replace(/^\s*<!--\s*Angular\s+bindings[\s\S]*?-->\s*\n?/gmi, '');
603
+ // Remove any other HTML comments at start
604
+ cleaned = cleaned.replace(/^\s*<!--[\s\S]*?-->\s*\n?/gm, '');
605
+ } while (cleaned.length !== previousLength); // Keep going until no more changes
606
+ }
607
+ // STEP 2: Remove ALL JS comment variations (multiple times if needed)
629
608
  if (type === 'js') {
630
- // Remove generic comment blocks at start
631
- cleaned = cleaned.replace(/^\/\*\*[\s\S]*?\*\/\s*\n?/, '');
632
- // Remove simple function wrappers (conservative approach)
633
- cleaned = cleaned.replace(/^\(function\(\) \{\s*\n?/, '');
634
- cleaned = cleaned.replace(/\s*\n?\}\)\(\);\s*$/, '');
635
- cleaned = cleaned.replace(/^function\(\s*/, 'function(');
636
- }
637
- else if (type === 'html') {
638
- // Remove HTML comments
639
- cleaned = cleaned.replace(/^<!--[\s\S]*?-->\s*\n?/, '');
640
- }
641
- else if (type === 'css') {
642
- // Remove CSS comments
643
- cleaned = cleaned.replace(/^\/\*[\s\S]*?\*\/\s*\n?/, '');
644
- }
609
+ let previousLength;
610
+ do {
611
+ previousLength = cleaned.length;
612
+ // Remove Server/Client script comment blocks
613
+ cleaned = cleaned.replace(/^\s*\/\*\*[\s\S]*?\*\/\s*\n?/gm, '');
614
+ // Remove function wrappers
615
+ cleaned = cleaned.replace(/^\s*\(function\s*\(\s*\)\s*\{\s*\n?/gm, '');
616
+ cleaned = cleaned.replace(/\s*\n?\s*\}\s*\)\s*\(\s*\)\s*;?\s*$/gm, '');
617
+ // Remove function( wrappers for client scripts
618
+ cleaned = cleaned.replace(/^\s*function\s*\(\s*$/gm, '');
619
+ cleaned = cleaned.replace(/^\s*\)\s*$/gm, '');
620
+ } while (cleaned.length !== previousLength);
621
+ }
622
+ // STEP 3: Remove ALL CSS comment variations
623
+ if (type === 'css') {
624
+ let previousLength;
625
+ do {
626
+ previousLength = cleaned.length;
627
+ // Remove widget style comments
628
+ cleaned = cleaned.replace(/^\s*\/\*[\s\S]*?\*\/\s*\n?/gm, '');
629
+ } while (cleaned.length !== previousLength);
630
+ }
631
+ // STEP 4: Clean up excessive whitespace
632
+ cleaned = cleaned.replace(/^\s*\n+/gm, ''); // Remove empty lines at start
633
+ cleaned = cleaned.replace(/\n\s*$/gm, ''); // Remove trailing whitespace
645
634
  return cleaned.trim();
646
635
  }
647
636
  /**
648
- * INTELLIGENT WRAPPER DETECTION: Check if content actually needs wrappers
637
+ * CONSERVATIVE WRAPPER DETECTION: Only add wrappers if content is truly minimal
638
+ * FIXED: Now properly detects ALL types of existing wrappers/comments
649
639
  */
650
640
  needsWrappers(content, mapping) {
651
641
  if (!content || !content.trim()) {
652
642
  return false; // Empty content doesn't need wrappers
653
643
  }
654
- // Check for server script wrappers
655
- if (mapping.wrapperHeader?.includes('(function()') && mapping.wrapperFooter?.includes('})()')) {
656
- // Check if content already has function wrapper
657
- const trimmed = content.trim();
658
- if (trimmed.match(/^\(function\s*\([^)]*\)\s*\{[\s\S]*\}\s*\)\s*\([^)]*\)\s*;?$/)) {
659
- return false; // Already has function wrapper
660
- }
661
- if (trimmed.match(/^\(function\(\)\s*\{[\s\S]*\}\)\(\)\s*;?$/)) {
662
- return false; // Already has our specific wrapper
663
- }
644
+ const trimmed = content.trim();
645
+ // CONSERVATIVE APPROACH: If content has ANY of these indicators, skip wrappers
646
+ // 1. Already has HTML comments (ANY HTML comments)
647
+ if (trimmed.includes('<!--')) {
648
+ console.log(` šŸ” Detected existing HTML comments - skipping wrappers`);
649
+ return false;
664
650
  }
665
- // Check for client script wrappers
666
- if (mapping.wrapperHeader?.includes('function(') && mapping.wrapperFooter?.includes(')')) {
667
- const trimmed = content.trim();
668
- if (trimmed.match(/^function\s*\([^)]*\)\s*\{[\s\S]*\}$/)) {
669
- return false; // Already is a function
670
- }
651
+ // 2. Already has JS comments (ANY block comments)
652
+ if (trimmed.includes('/**') || trimmed.includes('/*')) {
653
+ console.log(` šŸ” Detected existing JS comments - skipping wrappers`);
654
+ return false;
655
+ }
656
+ // 3. Already has function wrappers (ANY function patterns)
657
+ if (trimmed.includes('(function') || trimmed.match(/^function\s*\(/)) {
658
+ console.log(` šŸ” Detected existing function patterns - skipping wrappers`);
659
+ return false;
671
660
  }
672
- // Check if content already has comments that look like ours
673
- if (mapping.wrapperHeader?.includes('/**')) {
674
- if (content.includes('* Server Script for Widget:') ||
675
- content.includes('* Client Controller for Widget:') ||
676
- content.includes('* ES5 ONLY -')) {
677
- return false; // Already has our comments
661
+ // 4. Content is substantial (more than just basic code)
662
+ if (trimmed.length > 200) {
663
+ console.log(` šŸ” Content is substantial (${trimmed.length} chars) - skipping wrappers`);
664
+ return false;
665
+ }
666
+ // 5. Contains ServiceNow-specific patterns
667
+ const serviceNowPatterns = [
668
+ 'data.', 'input.', 'options.', '$scope.', 'c.server', 'gs.', '$sp.',
669
+ 'ng-', 'angular', 'spModal', 'spUtil', '{{', 'glide'
670
+ ];
671
+ for (const pattern of serviceNowPatterns) {
672
+ if (trimmed.toLowerCase().includes(pattern.toLowerCase())) {
673
+ console.log(` šŸ” Detected ServiceNow pattern '${pattern}' - skipping wrappers`);
674
+ return false;
678
675
  }
679
676
  }
680
- return true; // Content needs wrappers
677
+ // ONLY add wrappers for truly minimal/empty content
678
+ console.log(` ✨ Content is minimal and clean - adding wrappers`);
679
+ return true;
681
680
  }
682
681
  /**
683
682
  * Sanitize filename for filesystem
@@ -704,26 +703,55 @@ snow-flow sync status ${widget.sys_id}
704
703
  }
705
704
  /**
706
705
  * Pull any supported artifact type by detecting table from sys_id
706
+ * ENHANCED: Better error logging and more robust detection
707
707
  */
708
708
  async pullArtifactBySysId(sys_id) {
709
- // Try to detect table by querying common tables
710
- const tables = Object.keys(artifact_registry_1.ARTIFACT_REGISTRY);
709
+ console.log(`\nšŸ” Auto-detecting artifact type for sys_id: ${sys_id}`);
710
+ console.log(`šŸ“‹ Checking ${Object.keys(artifact_registry_1.ARTIFACT_REGISTRY).length} supported tables...`);
711
+ // SMART ORDER: Check most common tables first for better performance
712
+ const allTables = Object.keys(artifact_registry_1.ARTIFACT_REGISTRY);
713
+ const commonTables = ['sp_widget', 'sys_script_include', 'sys_script', 'sys_ui_page'];
714
+ const otherTables = allTables.filter(t => !commonTables.includes(t));
715
+ const tables = [...commonTables, ...otherTables]; // Common tables first
711
716
  const timeoutConfig = (0, mcp_timeout_config_js_1.getMCPTimeoutConfig)();
717
+ const errors = [];
712
718
  for (const table of tables) {
713
719
  try {
714
- // Quick query with short timeout
715
- const response = await (0, mcp_timeout_config_js_1.withMCPTimeout)(this.client.searchRecords(table, `sys_id=${sys_id}`, 1), 3000, // 3 second timeout for detection
720
+ console.log(` šŸ”Ž Checking table: ${table}...`);
721
+ // Increased timeout for better reliability
722
+ const response = await (0, mcp_timeout_config_js_1.withMCPTimeout)(this.client.searchRecords(table, `sys_id=${sys_id}`, 1), 8000, // 8 second timeout per table (was 3s)
716
723
  `Detect table for ${sys_id}`);
717
724
  if (response.result?.[0]) {
718
- console.log(`šŸŽ† Found artifact in table: ${table}`);
725
+ console.log(` āœ… Found in table: ${table}`);
726
+ console.log(`šŸŽ† Auto-detection successful! Proceeding with pull...`);
719
727
  return this.pullArtifact(table, sys_id);
720
728
  }
729
+ else {
730
+ console.log(` āŒ Not found in: ${table}`);
731
+ }
721
732
  }
722
733
  catch (error) {
723
- // Table might not exist, continue searching
734
+ const errorMsg = error instanceof Error ? error.message : String(error);
735
+ console.log(` āš ļø Error checking ${table}: ${errorMsg}`);
736
+ errors.push({ table, error: errorMsg });
737
+ // Don't fail on permission errors, timeouts, etc. - keep trying other tables
724
738
  }
725
739
  }
726
- throw new Error(`Could not find artifact with sys_id ${sys_id} in any supported table`);
740
+ // Generate detailed error message
741
+ console.log(`\nāŒ Artifact detection failed!`);
742
+ console.log(`šŸ” Searched ${tables.length} tables for sys_id: ${sys_id}`);
743
+ if (errors.length > 0) {
744
+ console.log(`\nāš ļø Errors encountered:`);
745
+ errors.forEach(({ table, error }) => {
746
+ console.log(` ${table}: ${error}`);
747
+ });
748
+ }
749
+ console.log(`\nšŸ’” Troubleshooting tips:`);
750
+ console.log(` 1. Verify the sys_id exists in ServiceNow`);
751
+ console.log(` 2. Check your permissions for the target table`);
752
+ console.log(` 3. Try specifying the table explicitly: snow_pull_artifact({sys_id, table: 'sp_widget'})`);
753
+ console.log(` 4. Supported tables: ${tables.join(', ')}`);
754
+ throw new Error(`Could not find artifact with sys_id ${sys_id} in any supported table. See details above.`);
727
755
  }
728
756
  /**
729
757
  * Get supported artifact types
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "snow-flow",
3
- "version": "3.5.15",
4
- "description": "ServiceNow development framework with FIXED local artifact sync system. CRITICAL BUG RESOLVED: Fixed cumulative wrapper problems in snow_pull_artifact where dynamic registry wrappers didn't match hardcoded strip patterns, causing dubbele function wrappers. Now features intelligent wrapper detection and proper content handling. Enhanced 'snow-flow init' creates optimized settings.json with 18 MCP servers, extensive development permissions, intelligent hooks, and ServiceNow-specific commands. Features intelligent timeout configuration and comprehensive ServiceNow development workflow.",
3
+ "version": "3.5.17",
4
+ "description": "ServiceNow development framework with ROBUST artifact detection fix. v3.5.17 FIXES the intermittent 'Could not find artifact' errors in snow_pull_artifact. Enhanced pullArtifactBySysId with detailed error logging, longer timeouts (8s per table), smart table ordering, and comprehensive troubleshooting guidance. ULTRA-CONSERVATIVE wrapper system prevents duplicate HTML comments. Enhanced 'snow-flow init' creates optimized settings.json with 18 MCP servers, extensive development permissions, intelligent hooks, and ServiceNow-specific commands. Features intelligent timeout configuration and comprehensive ServiceNow development workflow.",
5
5
  "main": "dist/index.js",
6
6
  "type": "commonjs",
7
7
  "bin": {