@snteam/amplify-angular-core 1.0.37 → 1.0.38

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.
@@ -647,6 +647,8 @@ class ConfigurationAnalyzerService {
647
647
  selectors.push('id');
648
648
  // Convert target model to camelCase for field access
649
649
  const fieldName = this.toCamelCase(targetModel);
650
+ // Add the relationship field itself (this is important for validation)
651
+ selectors.push(fieldName);
650
652
  // Add the relationship field with its ID
651
653
  selectors.push(`${fieldName}.id`);
652
654
  // Add common display fields for the relationship
@@ -726,7 +728,7 @@ class ConfigurationAnalyzerService {
726
728
  return selectors;
727
729
  }
728
730
  /**
729
- * Enhanced field selector determination that supports nested paths
731
+ * Enhanced field selector determination that supports nested paths and handles different relationship types
730
732
  */
731
733
  determineFieldSelectorsEnhanced(targetModel, fieldName) {
732
734
  if (!targetModel) {
@@ -738,8 +740,28 @@ class ConfigurationAnalyzerService {
738
740
  if (effectiveFieldName.includes('.')) {
739
741
  return this.generateNestedFieldSelectors(effectiveFieldName, targetModel);
740
742
  }
741
- // Use the standard field selector generation for simple relationships
742
- return this.determineFieldSelectors(targetModel);
743
+ // Generate selectors for the relationship
744
+ const selectors = [];
745
+ // Always include the base record ID
746
+ selectors.push('id');
747
+ // For the relationship field, we need to be more flexible about how we include it
748
+ // Some relationships might need the field itself, others might need nested access
749
+ // Strategy 1: Include the relationship field directly
750
+ selectors.push(effectiveFieldName);
751
+ // Strategy 2: Include nested access to common fields
752
+ selectors.push(`${effectiveFieldName}.id`);
753
+ // Add common display fields for the relationship
754
+ for (const displayField of this.COMMON_DISPLAY_FIELDS) {
755
+ selectors.push(`${effectiveFieldName}.${displayField}`);
756
+ }
757
+ // Strategy 3: For some relationship types, we might need to include additional metadata
758
+ // Add some common relationship metadata fields
759
+ const metadataFields = ['createdAt', 'updatedAt'];
760
+ for (const metadataField of metadataFields) {
761
+ selectors.push(`${effectiveFieldName}.${metadataField}`);
762
+ }
763
+ console.log(`ConfigurationAnalyzer: Generated ${selectors.length} field selectors for ${targetModel} with field ${effectiveFieldName}:`, selectors);
764
+ return selectors;
743
765
  }
744
766
  /**
745
767
  * Convert a string to PascalCase (first letter uppercase, rest camelCase)
@@ -1559,16 +1581,33 @@ class SelectionSetGeneratorService {
1559
1581
  */
1560
1582
  generateConfigurationBasedSelectionSet(config, analysisResult) {
1561
1583
  const selectionSet = ['id'];
1584
+ console.log('SelectionSetGenerator: Generating configuration-based selection set:', {
1585
+ config: {
1586
+ relationshipModelName: config.relationshipModelName,
1587
+ fieldName: config.fieldName,
1588
+ baseModelName: config.baseModelName,
1589
+ associatedWith: config.associatedWith
1590
+ },
1591
+ analysisResult: {
1592
+ targetModelName: analysisResult.targetModelName,
1593
+ fieldSelectorsCount: analysisResult.fieldSelectors?.length || 0,
1594
+ fieldSelectors: analysisResult.fieldSelectors
1595
+ }
1596
+ });
1562
1597
  // Use the field selectors from configuration analysis
1563
1598
  for (const selector of analysisResult.fieldSelectors) {
1564
1599
  if (!selectionSet.includes(selector)) {
1565
1600
  selectionSet.push(selector);
1566
1601
  }
1567
1602
  }
1603
+ console.log('SelectionSetGenerator: Configuration-based selection set before optimization:', selectionSet);
1568
1604
  // Apply display optimization if enabled
1569
1605
  const optimizedSet = this.applyDisplayOptimization(selectionSet, config);
1606
+ console.log('SelectionSetGenerator: Selection set after display optimization:', optimizedSet);
1570
1607
  // Apply complexity limits
1571
- return this.applyComplexityLimits(optimizedSet);
1608
+ const finalSet = this.applyComplexityLimits(optimizedSet);
1609
+ console.log('SelectionSetGenerator: Final configuration-based selection set:', finalSet);
1610
+ return finalSet;
1572
1611
  }
1573
1612
  /**
1574
1613
  * Apply display optimization to prioritize display-relevant fields
@@ -2709,7 +2748,7 @@ class AmplifyModelService {
2709
2748
  }
2710
2749
  /**
2711
2750
  * Validate that relationship field data is populated in query results
2712
- * Enhanced with comprehensive error logging
2751
+ * Enhanced with comprehensive error logging and flexible validation
2713
2752
  */
2714
2753
  validateRelationshipFieldPopulation(result, config) {
2715
2754
  try {
@@ -2724,28 +2763,56 @@ class AmplifyModelService {
2724
2763
  // Check if any records have the relationship field populated
2725
2764
  const records = Array.isArray(result.data) ? result.data : [result.data];
2726
2765
  let populatedCount = 0;
2766
+ let partiallyPopulatedCount = 0;
2727
2767
  for (const record of records) {
2728
- if (record && record[config.fieldName] !== undefined && record[config.fieldName] !== null) {
2768
+ if (!record)
2769
+ continue;
2770
+ const relationshipData = record[config.fieldName];
2771
+ // Check for fully populated relationship (object with data)
2772
+ if (relationshipData !== undefined && relationshipData !== null) {
2773
+ // If it's an object with properties, consider it populated
2774
+ if (typeof relationshipData === 'object' && Object.keys(relationshipData).length > 0) {
2775
+ populatedCount++;
2776
+ }
2777
+ // If it's a non-null primitive value, also consider it populated
2778
+ else if (typeof relationshipData !== 'object') {
2779
+ populatedCount++;
2780
+ }
2781
+ // If it's an empty object or array, consider it partially populated
2782
+ else {
2783
+ partiallyPopulatedCount++;
2784
+ }
2785
+ }
2786
+ // Also check if the record has any nested relationship data
2787
+ // This handles cases where the selection set includes nested fields like "table.id", "table.name"
2788
+ const hasNestedRelationshipData = this.hasNestedRelationshipData(record, config.fieldName);
2789
+ if (hasNestedRelationshipData) {
2729
2790
  populatedCount++;
2730
2791
  }
2731
2792
  }
2732
- if (populatedCount === 0) {
2733
- // Log warning if no relationship fields are populated
2793
+ // Consider the validation successful if we have any populated or partially populated records
2794
+ const totalValidRecords = populatedCount + partiallyPopulatedCount;
2795
+ if (totalValidRecords === 0) {
2796
+ // Log detailed information about what we found
2734
2797
  this.errorHandler.logSelectionSetError(SelectionSetErrorType.FIELD_NOT_FOUND, `No records have relationship field '${config.fieldName}' populated`, config, undefined, {
2735
2798
  method: 'validateRelationshipFieldPopulation',
2736
2799
  recordCount: records.length,
2737
2800
  populatedCount,
2801
+ partiallyPopulatedCount,
2738
2802
  sampleRecord: records[0] ? Object.keys(records[0]) : [],
2739
- fieldName: config.fieldName
2803
+ sampleRecordData: records[0] ? records[0] : null,
2804
+ fieldName: config.fieldName,
2805
+ relationshipFieldValue: records[0] ? records[0][config.fieldName] : undefined
2740
2806
  });
2741
2807
  console.warn(`AmplifyModelService: No records have relationship field '${config.fieldName}' populated`, {
2742
2808
  config,
2743
2809
  recordCount: records.length,
2744
- sampleRecord: records[0]
2810
+ sampleRecord: records[0],
2811
+ sampleRelationshipValue: records[0] ? records[0][config.fieldName] : undefined
2745
2812
  });
2746
2813
  return false;
2747
2814
  }
2748
- console.log(`AmplifyModelService: Relationship field validation successful: ${populatedCount}/${records.length} records have populated '${config.fieldName}' field`);
2815
+ console.log(`AmplifyModelService: Relationship field validation successful: ${populatedCount}/${records.length} records fully populated, ${partiallyPopulatedCount} partially populated for '${config.fieldName}' field`);
2749
2816
  return true;
2750
2817
  }
2751
2818
  catch (error) {
@@ -2760,6 +2827,26 @@ class AmplifyModelService {
2760
2827
  return false;
2761
2828
  }
2762
2829
  }
2830
+ /**
2831
+ * Check if a record has nested relationship data based on field patterns
2832
+ * This helps validate cases where selection sets use nested field access like "table.id", "table.name"
2833
+ */
2834
+ hasNestedRelationshipData(record, fieldName) {
2835
+ if (!record || typeof record !== 'object') {
2836
+ return false;
2837
+ }
2838
+ // Look for any fields that start with the relationship field name followed by a dot
2839
+ const nestedFieldPattern = `${fieldName}.`;
2840
+ for (const key of Object.keys(record)) {
2841
+ if (key.startsWith(nestedFieldPattern)) {
2842
+ const value = record[key];
2843
+ if (value !== undefined && value !== null) {
2844
+ return true;
2845
+ }
2846
+ }
2847
+ }
2848
+ return false;
2849
+ }
2763
2850
  /**
2764
2851
  * Log query attempt details
2765
2852
  */