@dcupl/common 1.11.11 → 2.0.0-beta.1

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.
Files changed (97) hide show
  1. package/dist/esm/attribute-dependency-graph.d.ts +119 -0
  2. package/dist/esm/cache.controller.d.ts +56 -1
  3. package/dist/esm/changeDetection.d.ts +1 -1
  4. package/dist/esm/date-utils.d.ts +50 -0
  5. package/dist/esm/deep-query.service.d.ts +133 -0
  6. package/dist/esm/dependency-graph.d.ts +102 -3
  7. package/dist/esm/index.d.ts +4 -0
  8. package/dist/esm/index.js +3096 -19
  9. package/dist/esm/index.js.map +1 -1
  10. package/dist/esm/indices.controller.d.ts +92 -0
  11. package/dist/esm/logger/index.d.ts +2 -0
  12. package/dist/esm/logger/logger.d.ts +101 -0
  13. package/dist/esm/pivot.d.ts +2 -1
  14. package/dist/esm/query-builder.d.ts +435 -2
  15. package/dist/esm/queryData.d.ts +9 -4
  16. package/dist/esm/types/dcupl.types.d.ts +80 -0
  17. package/dist/esm/types/internal.types.d.ts +1 -1
  18. package/dist/esm/types/list.types.d.ts +10 -0
  19. package/dist/esm/types/model.types.d.ts +49 -12
  20. package/dist/esm/types/query.types.d.ts +500 -2
  21. package/dist/node/index.cjs +5 -0
  22. package/dist/node/index.cjs.map +1 -0
  23. package/package.json +7 -8
  24. package/dist/browser/common.umd.js +0 -2
  25. package/dist/browser/common.umd.js.map +0 -1
  26. package/dist/esm/analytics.controller.js +0 -105
  27. package/dist/esm/analytics.controller.js.map +0 -1
  28. package/dist/esm/cache.controller.js +0 -40
  29. package/dist/esm/cache.controller.js.map +0 -1
  30. package/dist/esm/changeDetection.js +0 -179
  31. package/dist/esm/changeDetection.js.map +0 -1
  32. package/dist/esm/computeSuggestions.js +0 -38
  33. package/dist/esm/computeSuggestions.js.map +0 -1
  34. package/dist/esm/dependency-graph.js +0 -136
  35. package/dist/esm/dependency-graph.js.map +0 -1
  36. package/dist/esm/getAggregation.js +0 -170
  37. package/dist/esm/getAggregation.js.map +0 -1
  38. package/dist/esm/getFacets.js +0 -67
  39. package/dist/esm/getFacets.js.map +0 -1
  40. package/dist/esm/helper.js +0 -102
  41. package/dist/esm/helper.js.map +0 -1
  42. package/dist/esm/indices.controller.js +0 -97
  43. package/dist/esm/indices.controller.js.map +0 -1
  44. package/dist/esm/object-hash.js +0 -33
  45. package/dist/esm/object-hash.js.map +0 -1
  46. package/dist/esm/performance.js +0 -33
  47. package/dist/esm/performance.js.map +0 -1
  48. package/dist/esm/pivot.js +0 -132
  49. package/dist/esm/pivot.js.map +0 -1
  50. package/dist/esm/property-parser.js +0 -57
  51. package/dist/esm/property-parser.js.map +0 -1
  52. package/dist/esm/query-builder.js +0 -233
  53. package/dist/esm/query-builder.js.map +0 -1
  54. package/dist/esm/query.helper.js +0 -172
  55. package/dist/esm/query.helper.js.map +0 -1
  56. package/dist/esm/queryData.js +0 -360
  57. package/dist/esm/queryData.js.map +0 -1
  58. package/dist/esm/script.controller.js +0 -54
  59. package/dist/esm/script.controller.js.map +0 -1
  60. package/dist/esm/template-parser.js +0 -22
  61. package/dist/esm/template-parser.js.map +0 -1
  62. package/dist/esm/types/aggregation.types.js +0 -2
  63. package/dist/esm/types/aggregation.types.js.map +0 -1
  64. package/dist/esm/types/app-loader.types.js +0 -2
  65. package/dist/esm/types/app-loader.types.js.map +0 -1
  66. package/dist/esm/types/data.types.js +0 -2
  67. package/dist/esm/types/data.types.js.map +0 -1
  68. package/dist/esm/types/dcupl.types.js +0 -2
  69. package/dist/esm/types/dcupl.types.js.map +0 -1
  70. package/dist/esm/types/facets.types.js +0 -2
  71. package/dist/esm/types/facets.types.js.map +0 -1
  72. package/dist/esm/types/filter.types.js +0 -2
  73. package/dist/esm/types/filter.types.js.map +0 -1
  74. package/dist/esm/types/group-by.types.js +0 -2
  75. package/dist/esm/types/group-by.types.js.map +0 -1
  76. package/dist/esm/types/index.js +0 -17
  77. package/dist/esm/types/index.js.map +0 -1
  78. package/dist/esm/types/internal.types.js +0 -2
  79. package/dist/esm/types/internal.types.js.map +0 -1
  80. package/dist/esm/types/list.types.js +0 -2
  81. package/dist/esm/types/list.types.js.map +0 -1
  82. package/dist/esm/types/model.types.js +0 -16
  83. package/dist/esm/types/model.types.js.map +0 -1
  84. package/dist/esm/types/projection.types.js +0 -2
  85. package/dist/esm/types/projection.types.js.map +0 -1
  86. package/dist/esm/types/quality.types.js +0 -2
  87. package/dist/esm/types/quality.types.js.map +0 -1
  88. package/dist/esm/types/query.types.js +0 -12
  89. package/dist/esm/types/query.types.js.map +0 -1
  90. package/dist/esm/types/section.types.js +0 -2
  91. package/dist/esm/types/section.types.js.map +0 -1
  92. package/dist/esm/types/suggestion.types.js +0 -2
  93. package/dist/esm/types/suggestion.types.js.map +0 -1
  94. package/dist/esm/types/testing.types.js +0 -2
  95. package/dist/esm/types/testing.types.js.map +0 -1
  96. package/dist/node/index.cjs.js +0 -1
  97. package/dist/tsconfig.tsbuildinfo +0 -1
@@ -0,0 +1,119 @@
1
+ export type AttributeNode = {
2
+ modelKey: string;
3
+ attributeKey: string;
4
+ type: 'property' | 'reference';
5
+ processingStep: 1 | 2 | 3 | 4;
6
+ };
7
+ export type AttributeNodeId = string;
8
+ export type ProcessingPlan = Map<string, Map<number, Set<string>>>;
9
+ /**
10
+ * AttributeDependencyGraph tracks attribute-level dependencies between models.
11
+ *
12
+ * This graph is item-agnostic: when ModelA.price depends on ModelB.cost,
13
+ * any change to ModelB.cost triggers reprocessing of ALL ModelA items
14
+ * that have the price derivation.
15
+ *
16
+ * The graph ensures:
17
+ * - Correct processing order based on dependencies
18
+ * - Impact analysis when attributes change
19
+ * - Efficient batch processing by grouping attributes by model and step
20
+ */
21
+ export declare class AttributeDependencyGraph {
22
+ private graph;
23
+ private nodeIndex;
24
+ constructor();
25
+ /**
26
+ * Creates a unique ID for an attribute node
27
+ */
28
+ private getNodeId;
29
+ /**
30
+ * Parses a node ID back into components
31
+ */
32
+ private parseNodeId;
33
+ /**
34
+ * Adds an attribute node to the graph
35
+ */
36
+ addAttribute(node: AttributeNode): void;
37
+ /**
38
+ * Adds a dependency between two attributes
39
+ * @param from - The dependent attribute (e.g., ModelA.derivedPrice)
40
+ * @param to - The source attribute it depends on (e.g., ModelB.baseCost)
41
+ */
42
+ addAttributeDependency(from: AttributeNode, to: AttributeNode): void;
43
+ /**
44
+ * Gets all attributes impacted by changes to the given attributes
45
+ * @param changed - Array of changed attribute nodes
46
+ * @returns Array of all impacted attribute nodes (including the changed ones)
47
+ */
48
+ getImpactedAttributes(changed: AttributeNode[]): AttributeNode[];
49
+ /**
50
+ * Generates a processing plan for the given attributes
51
+ * Groups attributes by model and processing step for efficient batch processing
52
+ *
53
+ * @param attributes - Array of attributes to process
54
+ * @returns Map<modelKey, Map<processingStep, Set<attributeKeys>>>
55
+ */
56
+ getProcessingOrder(attributes: AttributeNode[]): ProcessingPlan;
57
+ /**
58
+ * Gets all attributes for a specific model
59
+ */
60
+ getAttributesForModel(modelKey: string): AttributeNode[];
61
+ /**
62
+ * Gets dependencies for a specific attribute
63
+ */
64
+ getDependencies(node: AttributeNode): AttributeNode[];
65
+ /**
66
+ * Gets dependents for a specific attribute (attributes that depend on this one)
67
+ */
68
+ getDependents(node: AttributeNode): AttributeNode[];
69
+ /**
70
+ * Checks if an attribute has any dependencies
71
+ */
72
+ hasDependencies(node: AttributeNode): boolean;
73
+ /**
74
+ * Checks if a node exists in the graph
75
+ */
76
+ hasNode(nodeId: AttributeNodeId): boolean;
77
+ /**
78
+ * Gets all attribute nodes in the graph
79
+ */
80
+ getAllAttributes(): AttributeNode[];
81
+ /**
82
+ * Gets the maximum dependency depth in the graph
83
+ * Useful for determining if full update might be more efficient
84
+ */
85
+ getMaxDepth(): number;
86
+ /**
87
+ * Validates that all expected attributes are present in the graph.
88
+ * This helps catch silent failures during graph building where attributes
89
+ * with expressions or derivations might not be properly added.
90
+ *
91
+ * @param expectedAttributes - Map of modelKey to array of attribute keys that should exist
92
+ * @returns Object with validation result and any missing attributes
93
+ */
94
+ validateCompleteness(expectedAttributes: Map<string, string[]>): {
95
+ isComplete: boolean;
96
+ missing: Array<{
97
+ modelKey: string;
98
+ attributeKey: string;
99
+ }>;
100
+ };
101
+ /**
102
+ * Clears the entire graph
103
+ */
104
+ clear(): void;
105
+ /**
106
+ * Gets statistics about the graph
107
+ */
108
+ getStats(): {
109
+ totalAttributes: number;
110
+ totalDependencies: number;
111
+ maxDepth: number;
112
+ attributesByModel: Map<string, number>;
113
+ attributesByStep: Map<number, number>;
114
+ };
115
+ /**
116
+ * Exports the graph to JSON for debugging
117
+ */
118
+ toJSON(): any;
119
+ }
@@ -1,11 +1,66 @@
1
1
  export declare class CacheController {
2
2
  enabled: boolean;
3
3
  private cache;
4
+ private cacheDependencies;
5
+ private hitCount;
6
+ private missCount;
7
+ private log;
4
8
  constructor(enabled: boolean);
5
9
  get(key: string, context: any): any;
6
- set(key: string, context: any, value: any): void;
10
+ set(key: string, context: any, value: any, dependencies?: CacheDependencyInfo): void;
7
11
  has(key: string, context: any): boolean;
8
12
  clear(): void;
13
+ /**
14
+ * Invalidates cache entries that depend on the specified models and attributes
15
+ * @param changedModels - Map of modelKey → Set of changed attributeKeys
16
+ */
17
+ invalidateByDependencies(changedModels: Map<string, Set<string>>): void;
18
+ /**
19
+ * Invalidates all cache entries for specific models
20
+ * @param modelKeys - Array of model keys to invalidate
21
+ */
22
+ invalidateByModels(modelKeys: string[]): void;
23
+ /**
24
+ * Invalidates cache entries by key prefix (e.g., 'query', 'facets')
25
+ * @param keyPrefix - The key prefix to match
26
+ */
27
+ invalidateByKeyPrefix(keyPrefix: string): void;
28
+ /**
29
+ * Invalidates all cache entries for a specific model
30
+ * @param modelKey - The model key to invalidate
31
+ */
32
+ invalidateForModel(modelKey: string): void;
33
+ /**
34
+ * Invalidates cache entries that depend on a specific attribute of a model
35
+ * @param modelKey - The model key
36
+ * @param attributeKey - The attribute key to invalidate
37
+ */
38
+ invalidateForAttribute(modelKey: string, attributeKey: string): void;
39
+ /**
40
+ * Invalidates cache entries matching a custom predicate
41
+ * @param predicate - Function that returns true for cache keys to invalidate
42
+ */
43
+ invalidateMatching(predicate: (key: string) => boolean): void;
9
44
  generateContext(constext: any): any;
10
45
  getCacheName(key: string, context: any): string;
46
+ /**
47
+ * Gets cache statistics including hit rate
48
+ */
49
+ getStats(): {
50
+ size: number;
51
+ hitRate: number;
52
+ totalEntries: number;
53
+ entriesWithDependencies: number;
54
+ hits: number;
55
+ misses: number;
56
+ };
57
+ }
58
+ /**
59
+ * Information about which models and attributes a cache entry depends on
60
+ */
61
+ export interface CacheDependencyInfo {
62
+ /** Set of model keys this cache entry depends on */
63
+ models: Set<string>;
64
+ /** Map of modelKey → Set of attribute keys (if specific attributes matter) */
65
+ modelAttributes: Map<string, Set<string>>;
11
66
  }
@@ -2,7 +2,7 @@ import { CallbackFunction, DcuplInitOptions } from './types';
2
2
  import { AnalyticsController } from './analytics.controller';
3
3
  export type DcuplUpdateScope = 'all' | 'global' | 'list' | 'list$';
4
4
  export type DcuplUpdateTrigger = 'user' | 'loader';
5
- export type DcuplUpdateType = 'data_change' | 'dcupl_destroyed' | 'dcupl_handle_datacontainer' | 'dcupl_initialized' | 'dcupl_updated_manually' | 'filter_many' | 'filter_one' | 'fn_aggregate' | 'fn_facets' | 'fn_groupBy' | 'fn_metadata' | 'fn_pivot' | 'fn_suggest' | 'list_created' | 'list_destroyed' | 'list_updated' | 'loader_added' | 'loader_config_fetched' | 'loader_data_fetched' | 'loader_models_fetched' | 'loader_scripts_fetched' | 'loader_processed' | 'loader_removed' | 'model_add' | 'query_apply_options' | 'query_apply' | 'query_execute' | 'query_get' | 'query_has' | 'query_many' | 'query_one' | 'query_remove' | 'query_reset' | 'result_updated' | 'view_add';
5
+ export type DcuplUpdateType = 'data_change' | 'dcupl_destroyed' | 'dcupl_handle_datacontainer' | 'dcupl_initialized' | 'dcupl_updated_manually' | 'dcupl_partial_update' | 'filter_many' | 'filter_one' | 'fn_aggregate' | 'fn_facets' | 'fn_groupBy' | 'fn_metadata' | 'fn_pivot' | 'fn_suggest' | 'list_created' | 'list_destroyed' | 'list_updated' | 'loader_added' | 'loader_config_fetched' | 'loader_data_fetched' | 'loader_models_fetched' | 'loader_scripts_fetched' | 'loader_processed' | 'loader_removed' | 'model_add' | 'query_apply_options' | 'query_apply' | 'query_execute' | 'query_get' | 'query_has' | 'query_many' | 'query_one' | 'query_remove' | 'query_reset' | 'result_updated' | 'view_add';
6
6
  export type DcuplUpdateAction = 'update';
7
7
  export type DcuplUpdateMessage = {
8
8
  key?: number;
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Custom date utilities to replace date-fns
3
+ * Supports custom format patterns for date parsing
4
+ */
5
+ /**
6
+ * Check if a value is a Date instance
7
+ * @param value - Value to check
8
+ * @returns true if value is a Date instance (valid or invalid), false otherwise
9
+ */
10
+ export declare function isDateInstance(value: any): value is Date;
11
+ /**
12
+ * Check if a Date object represents a valid date
13
+ * @param date - Date object to validate
14
+ * @returns true if date is valid, false otherwise
15
+ */
16
+ export declare function isValidDate(date: Date): boolean;
17
+ /**
18
+ * Parse a date string according to a format pattern
19
+ *
20
+ * Supported format tokens:
21
+ * - yyyy: 4-digit year
22
+ * - yy: 2-digit year (00-99 → 2000-2099)
23
+ * - MM: 2-digit month (01-12)
24
+ * - M: 1-2 digit month (1-12)
25
+ * - dd: 2-digit day (01-31)
26
+ * - d: 1-2 digit day (1-31)
27
+ * - HH: 2-digit hour (00-23)
28
+ * - H: 1-2 digit hour (0-23)
29
+ * - mm: 2-digit minute (00-59)
30
+ * - m: 1-2 digit minute (0-59)
31
+ * - ss: 2-digit second (00-59)
32
+ * - s: 1-2 digit second (0-59)
33
+ * - SSS: 3-digit millisecond (000-999)
34
+ *
35
+ * Special formats:
36
+ * - 't': Unix timestamp in seconds
37
+ * - 'T': Unix timestamp in milliseconds
38
+ *
39
+ * @param value - The date string to parse
40
+ * @param format - Format pattern (e.g., 'yyyy-MM-dd', 'dd.MM.yyyy', 't', 'T')
41
+ * @param referenceDate - Optional reference date (reserved for future use, currently unused)
42
+ * @returns Parsed Date object or Invalid Date (NaN)
43
+ *
44
+ * @example
45
+ * parseDate('2023-12-25', 'yyyy-MM-dd') // Dec 25, 2023
46
+ * parseDate('25.12.2023', 'dd.MM.yyyy') // Dec 25, 2023
47
+ * parseDate('1640000000', 't') // Unix seconds
48
+ * parseDate('2023-02-31', 'yyyy-MM-dd') // Invalid Date (Feb only has 28/29 days)
49
+ */
50
+ export declare function parseDate(value: string, format: string, _referenceDate?: Date): Date;
@@ -0,0 +1,133 @@
1
+ import { QueryAttributeEntry } from './query-builder';
2
+ /**
3
+ * Result of path validation
4
+ */
5
+ export interface ValidationResult {
6
+ valid: boolean;
7
+ errors?: string[];
8
+ }
9
+ /**
10
+ * DeepQueryService - Centralized service for parsing, validating, and caching deep query attributes
11
+ *
12
+ * This service provides:
13
+ * - LRU caching for parsed attribute paths (1000 entries, targeting >80% hit rate)
14
+ * - Circular reference detection
15
+ * - Multi-level nesting support (3+ levels)
16
+ * - Path validation with descriptive errors
17
+ */
18
+ export declare class DeepQueryService {
19
+ private parseCache;
20
+ private circularRefDetector;
21
+ private cacheHits;
22
+ private cacheMisses;
23
+ constructor(cacheSize?: number);
24
+ /**
25
+ * Parse an attribute string into its components
26
+ *
27
+ * Supports:
28
+ * - Dot notation: `customer.name`
29
+ * - Bracket notation: `items[0].price`, `items[*].price`
30
+ * - Multi-level: `order.customer.address.city`
31
+ *
32
+ * @param attribute - The attribute path to parse
33
+ * @returns QueryAttributeEntry with isDeepQuery, reference, referenceAttribute
34
+ *
35
+ * @example
36
+ * ```typescript
37
+ * const service = new DeepQueryService();
38
+ * const entry = service.parse('customer.name');
39
+ * // Returns: { attribute: 'customer.name', isDeepQuery: true, reference: 'customer', referenceAttribute: 'name' }
40
+ * ```
41
+ */
42
+ parse(attribute: string): QueryAttributeEntry;
43
+ /**
44
+ * Detect circular references in a path
45
+ *
46
+ * Checks for:
47
+ * - Direct circular: A→B→A
48
+ * - Indirect circular: A→B→C→A
49
+ * - Self-referential: A→A
50
+ *
51
+ * @param path - Array of model/reference keys in the dependency chain
52
+ * @returns true if circular reference detected
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * const service = new DeepQueryService();
57
+ * const hasCircular = service.detectCircular(['Order', 'Customer', 'Order']);
58
+ * // Returns: true
59
+ * ```
60
+ */
61
+ detectCircular(path: string[]): boolean;
62
+ /**
63
+ * Validate attribute path syntax
64
+ *
65
+ * Checks for:
66
+ * - Empty strings
67
+ * - Malformed bracket notation
68
+ * - Invalid characters
69
+ * - Excessive nesting depth
70
+ *
71
+ * @param attribute - The attribute path to validate
72
+ * @param maxDepth - Maximum allowed nesting depth (default: 10)
73
+ * @returns ValidationResult with errors if invalid
74
+ *
75
+ * @example
76
+ * ```typescript
77
+ * const service = new DeepQueryService();
78
+ * const result = service.validatePath('customer.name');
79
+ * // Returns: { valid: true }
80
+ *
81
+ * const badResult = service.validatePath('customer.[invalid]');
82
+ * // Returns: { valid: false, errors: ['Invalid bracket notation: customer.[invalid]'] }
83
+ * ```
84
+ */
85
+ validatePath(attribute: string, maxDepth?: number): ValidationResult;
86
+ /**
87
+ * Clear the parse cache
88
+ * Should be called when models are updated or removed
89
+ */
90
+ clearCache(): void;
91
+ /**
92
+ * Clear the circular reference detector
93
+ */
94
+ clearCircularDetector(): void;
95
+ /**
96
+ * Get cache statistics for monitoring and debugging
97
+ *
98
+ * @returns Object containing cache size, hit rate, and other metrics
99
+ */
100
+ getCacheStats(): {
101
+ size: number;
102
+ maxSize: number;
103
+ hits: number;
104
+ misses: number;
105
+ hitRate: number;
106
+ };
107
+ /**
108
+ * Extract path segments from an attribute string
109
+ * Useful for analyzing deep query structure
110
+ *
111
+ * @param attribute - The attribute path
112
+ * @returns Array of path segments
113
+ *
114
+ * @example
115
+ * ```typescript
116
+ * const service = new DeepQueryService();
117
+ * const segments = service.getPathSegments('order.customer.name');
118
+ * // Returns: ['order', 'customer', 'name']
119
+ * ```
120
+ */
121
+ getPathSegments(attribute: string): string[];
122
+ /**
123
+ * Get the depth of a deep query path
124
+ *
125
+ * @param attribute - The attribute path
126
+ * @returns Depth of the path (1 for shallow, 2+ for deep)
127
+ */
128
+ getPathDepth(attribute: string): number;
129
+ }
130
+ /**
131
+ * Singleton instance for global use
132
+ */
133
+ export declare const deepQueryService: DeepQueryService;
@@ -1,9 +1,31 @@
1
- export declare class DependencyGraph {
1
+ export declare class DependencyGraph<K extends string = string, M = any> {
2
2
  private nodes;
3
3
  private edges;
4
+ private nodeKinds;
5
+ private nodeMeta;
6
+ private edgePolicy?;
4
7
  constructor();
5
- addNode(name: string): void;
8
+ addNode(name: string, options?: {
9
+ kind?: K;
10
+ meta?: M;
11
+ }): void;
6
12
  addDependency(from: string, to: string): void;
13
+ /** Configure an optional policy to validate edges before they are added */
14
+ setEdgePolicy(policy?: (from: {
15
+ name: string;
16
+ kind?: K;
17
+ }, to: {
18
+ name: string;
19
+ kind?: K;
20
+ }) => boolean): void;
21
+ /** Assign or change a node's kind */
22
+ setNodeKind(name: string, kind?: K): void;
23
+ /** Get a node's kind */
24
+ getNodeKind(name: string): K | undefined;
25
+ /** Set arbitrary metadata for a node */
26
+ setNodeMeta(name: string, meta: M): void;
27
+ /** Get metadata for a node */
28
+ getNodeMeta<T = M>(name: string): T | undefined;
7
29
  removeNode(name: string): void;
8
30
  removeDependency(from: string, to: string): void;
9
31
  hasNode(name: string): boolean;
@@ -11,8 +33,85 @@ export declare class DependencyGraph {
11
33
  getDependencies(name: string): string[];
12
34
  getDependents(name: string): string[];
13
35
  isCyclic(): boolean;
14
- order(): string[];
36
+ /**
37
+ * Validates that the graph has no cycles.
38
+ * Returns an object with hasCycle boolean and the cycle path if found.
39
+ * @returns {hasCycle: boolean, path?: string[]} - hasCycle is true if a cycle exists, path contains the cycle nodes
40
+ */
41
+ validateNoCycles(): {
42
+ hasCycle: boolean;
43
+ path?: string[];
44
+ };
45
+ order(options?: {
46
+ allowCycles?: boolean;
47
+ }): string[];
15
48
  clear(): void;
16
49
  getNodes(): string[];
17
50
  getAllEdges(): [string, string][];
51
+ /**
52
+ * Returns all nodes that have no dependants (i.e., no other node depends on them).
53
+ * In graph terms, nodes with zero incoming edges.
54
+ */
55
+ getNodesWithNoDependants(): string[];
56
+ /** Return nodes filtered by kind */
57
+ getNodesByKind(kind: K): string[];
58
+ /** Roots by kind (zero incoming) */
59
+ getRootsByKind(kind?: K): string[];
60
+ /** Leaves by kind (zero outgoing) */
61
+ getLeavesByKind(kind?: K): string[];
62
+ /** Filter dependencies of a node by kind */
63
+ getDependenciesOfKind(name: string, kind: K): string[];
64
+ /** Filter dependents of a node by kind */
65
+ getDependentsOfKind(name: string, kind: K): string[];
66
+ /**
67
+ * Create execution batches (topological levels). Throws if the graph has a cycle.
68
+ * If filterKinds is provided, batches contain only nodes of these kinds, but readiness
69
+ * is evaluated against the complete graph.
70
+ */
71
+ plan(options?: {
72
+ filterKinds?: K[];
73
+ }): {
74
+ batches: string[][];
75
+ };
76
+ /**
77
+ * Impact analysis: return nodes impacted by a set of changed nodes.
78
+ * direction:
79
+ * - 'downstream': nodes that depend (directly/indirectly) on changed
80
+ * - 'upstream': nodes that changed depends on
81
+ * - 'both': union of upstream and downstream
82
+ */
83
+ getImpactedNodes(changed: string[] | Set<string>, direction?: 'downstream' | 'upstream' | 'both', filterKinds?: K[]): string[];
84
+ toJSON(): {
85
+ nodes: Array<{
86
+ name: string;
87
+ kind?: K;
88
+ meta?: M;
89
+ }>;
90
+ edges: Array<{
91
+ from: string;
92
+ to: string;
93
+ }>;
94
+ };
95
+ static fromJSON<KK extends string, MM = any>(data: {
96
+ nodes: Array<{
97
+ name: string;
98
+ kind?: KK;
99
+ meta?: MM;
100
+ }>;
101
+ edges: Array<{
102
+ from: string;
103
+ to: string;
104
+ }>;
105
+ }): DependencyGraph<KK, MM>;
106
+ diff(other: DependencyGraph<K, any>): {
107
+ addedNodes: string[];
108
+ removedNodes: string[];
109
+ addedEdges: [string, string][];
110
+ removedEdges: [string, string][];
111
+ kindChanges: Array<{
112
+ name: string;
113
+ from?: K;
114
+ to?: K;
115
+ }>;
116
+ };
18
117
  }
@@ -1,12 +1,16 @@
1
1
  export * from './analytics.controller';
2
+ export * from './attribute-dependency-graph';
2
3
  export * from './cache.controller';
3
4
  export * from './changeDetection';
4
5
  export * from './computeSuggestions';
6
+ export * from './date-utils';
7
+ export * from './deep-query.service';
5
8
  export * from './dependency-graph';
6
9
  export * from './getAggregation';
7
10
  export * from './getFacets';
8
11
  export * from './helper';
9
12
  export * from './indices.controller';
13
+ export * from './logger';
10
14
  export * from './performance';
11
15
  export * from './pivot';
12
16
  export * from './property-parser';